diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 31fd1eb9f9820237c35485c81c91a007c7fd96eb..db0a9eb2d44002724066087dcc02b338ae7c75a1 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='utf-8'?> -<manifest android:hardwareAccelerated="true" android:versionCode="100060" android:versionName="1.0.6" package="fr.duniter.cesium" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> +<manifest android:hardwareAccelerated="true" android:versionCode="104015" android:versionName="1.4.15" package="fr.duniter.cesium" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:hardwareAccelerated="true" android:icon="@mipmap/icon" android:label="@string/app_name" android:supportsRtl="true"> @@ -22,5 +22,5 @@ <uses-feature android:name="android.hardware.camera" android:required="true" /> - <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="25" tools:overrideLibrary="org.kaliumjni.lib" /> + <uses-sdk android:minSdkVersion="20" android:targetSdkVersion="28" tools:overrideLibrary="org.kaliumjni.lib" /> </manifest> diff --git a/android.json b/android.json index 55cdb36031b6d6d5f2ef28a24b0b3cd5e4219a87..2cc8b7ef6824593960e7edbf8b20f0ad12f7dda1 100644 --- a/android.json +++ b/android.json @@ -1,357 +1,412 @@ { - "prepare_queue": { - "installed": [], - "uninstalled": [] - }, - "config_munge": { - "files": { - "res/xml/config.xml": { - "parents": { - "/*": [ - { - "xml": "<feature name=\"Clipboard\"><param name=\"android-package\" value=\"com.verso.cordova.clipboard.Clipboard\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"Camera\"><param name=\"android-package\" value=\"org.apache.cordova.camera.CameraLauncher\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"Device\"><param name=\"android-package\" value=\"org.apache.cordova.device.Device\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"Notification\"><param name=\"android-package\" value=\"org.apache.cordova.dialogs.Notification\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"InAppBrowser\"><param name=\"android-package\" value=\"org.apache.cordova.inappbrowser.InAppBrowser\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"MiniSodium\"><param name=\"android-package\" value=\"me.lockate.plugins.MiniSodium\" /><param name=\"onload\" value=\"true\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"SecureStorage\"><param name=\"android-package\" value=\"com.crypho.plugins.SecureStorage\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"SplashScreen\"><param name=\"android-package\" value=\"org.apache.cordova.splashscreen.SplashScreen\" /><param name=\"onload\" value=\"true\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"StatusBar\"><param name=\"android-package\" value=\"org.apache.cordova.statusbar.StatusBar\" /><param name=\"onload\" value=\"true\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"Vibration\"><param name=\"android-package\" value=\"org.apache.cordova.vibration.Vibration\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"WebSocket\"><param name=\"android-package\" value=\"com.knowledgecode.cordova.websocket.WebSocket\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"Whitelist\"><param name=\"android-package\" value=\"org.apache.cordova.whitelist.WhitelistPlugin\" /><param name=\"onload\" value=\"true\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"Toast\"><param name=\"android-package\" value=\"nl.xservices.plugins.Toast\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"Keyboard\"><param name=\"android-package\" value=\"io.ionic.keyboard.IonicKeyboard\" /><param name=\"onload\" value=\"true\" /></feature>", - "count": 1 - }, - { - "xml": "<feature name=\"BarcodeScanner\"><param name=\"android-package\" value=\"com.phonegap.plugins.barcodescanner.BarcodeScanner\" /></feature>", - "count": 1 - } - ] - } + "prepare_queue": { + "installed": [], + "uninstalled": [] + }, + "config_munge": { + "files": { + "res/xml/config.xml": { + "parents": { + "/*": [ + { + "xml": "<feature name=\"Clipboard\"><param name=\"android-package\" value=\"com.verso.cordova.clipboard.Clipboard\" /></feature>", + "count": 1 }, - "AndroidManifest.xml": { - "parents": { - "/*": [ - { - "xml": "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />", - "count": 1 - }, - { - "xml": "<uses-permission android:name=\"android.permission.INTERNET\" />", - "count": 1 - } - ], - "application": [ - { - "xml": "<provider android:authorities=\"${applicationId}.provider\" android:exported=\"false\" android:grantUriPermissions=\"true\" android:name=\"android.support.v4.content.FileProvider\"><meta-data android:name=\"android.support.FILE_PROVIDER_PATHS\" android:resource=\"@xml/provider_paths\" /></provider>", - "count": 1 - } - ], - "/manifest": [ - { - "xml": "<uses-sdk android:minSdkVersion=\"16\" android:targetSdkVersion=\"19\" />", - "count": 1 - }, - { - "xml": "<uses-permission android:name=\"android.permission.VIBRATE\" />", - "count": 1 - }, - { - "xml": "<uses-permission android:name=\"android.permission.CAMERA\" />", - "count": 1 - }, - { - "xml": "<uses-permission android:name=\"android.permission.FLASHLIGHT\" />", - "count": 1 - }, - { - "xml": "<uses-feature android:name=\"android.hardware.camera\" android:required=\"true\" />", - "count": 1 - } - ], - "/manifest/application": [ - { - "xml": "<activity android:clearTaskOnLaunch=\"true\" android:configChanges=\"orientation|keyboardHidden|screenSize\" android:exported=\"false\" android:name=\"com.google.zxing.client.android.CaptureActivity\" android:theme=\"@android:style/Theme.NoTitleBar.Fullscreen\" android:windowSoftInputMode=\"stateAlwaysHidden\" />", - "count": 1 - }, - { - "xml": "<activity android:label=\"Share\" android:name=\"com.google.zxing.client.android.encode.EncodeActivity\" />", - "count": 1 - } - ] - } + { + "xml": "<feature name=\"Camera\"><param name=\"android-package\" value=\"org.apache.cordova.camera.CameraLauncher\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"Device\"><param name=\"android-package\" value=\"org.apache.cordova.device.Device\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"Notification\"><param name=\"android-package\" value=\"org.apache.cordova.dialogs.Notification\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"InAppBrowser\"><param name=\"android-package\" value=\"org.apache.cordova.inappbrowser.InAppBrowser\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"MiniSodium\"><param name=\"android-package\" value=\"me.lockate.plugins.MiniSodium\" /><param name=\"onload\" value=\"true\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"SecureStorage\"><param name=\"android-package\" value=\"com.crypho.plugins.SecureStorage\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"SplashScreen\"><param name=\"android-package\" value=\"org.apache.cordova.splashscreen.SplashScreen\" /><param name=\"onload\" value=\"true\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"StatusBar\"><param name=\"android-package\" value=\"org.apache.cordova.statusbar.StatusBar\" /><param name=\"onload\" value=\"true\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"Vibration\"><param name=\"android-package\" value=\"org.apache.cordova.vibration.Vibration\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"WebSocket\"><param name=\"android-package\" value=\"com.knowledgecode.cordova.websocket.WebSocket\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"Whitelist\"><param name=\"android-package\" value=\"org.apache.cordova.whitelist.WhitelistPlugin\" /><param name=\"onload\" value=\"true\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"Toast\"><param name=\"android-package\" value=\"nl.xservices.plugins.Toast\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"Keyboard\"><param name=\"android-package\" value=\"io.ionic.keyboard.IonicKeyboard\" /><param name=\"onload\" value=\"true\" /></feature>", + "count": 1 + }, + { + "xml": "<feature name=\"BarcodeScanner\"><param name=\"android-package\" value=\"com.phonegap.plugins.barcodescanner.BarcodeScanner\" /></feature>", + "count": 1 } + ] } - }, - "installed_plugins": { - "cordova-clipboard": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-camera": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-console": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-device": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-dialogs": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-inappbrowser": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-minisodium": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-secure-storage": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-splashscreen": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-statusbar": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-vibration": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-websocket": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-whitelist": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "cordova-plugin-x-toast": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "ionic-plugin-keyboard": { - "PACKAGE_NAME": "fr.duniter.cesium" - }, - "phonegap-plugin-barcodescanner": { - "PACKAGE_NAME": "fr.duniter.cesium" + }, + "AndroidManifest.xml": { + "parents": { + "/*": [ + { + "xml": "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />", + "count": 1 + }, + { + "xml": "<uses-permission android:name=\"android.permission.INTERNET\" />", + "count": 1 + } + ], + "application": [ + { + "xml": "<provider android:authorities=\"${applicationId}.provider\" android:exported=\"false\" android:grantUriPermissions=\"true\" android:name=\"android.support.v4.content.FileProvider\"><meta-data android:name=\"android.support.FILE_PROVIDER_PATHS\" android:resource=\"@xml/provider_paths\" /></provider>", + "count": 1 + } + ], + "/manifest": [ + { + "xml": "<uses-sdk android:minSdkVersion=\"16\" android:targetSdkVersion=\"19\" />", + "count": 1 + }, + { + "xml": "<uses-permission android:name=\"android.permission.VIBRATE\" />", + "count": 1 + }, + { + "xml": "<uses-permission android:name=\"android.permission.CAMERA\" />", + "count": 1 + }, + { + "xml": "<uses-permission android:name=\"android.permission.FLASHLIGHT\" />", + "count": 1 + }, + { + "xml": "<uses-feature android:name=\"android.hardware.camera\" android:required=\"true\" />", + "count": 1 + } + ], + "/manifest/application": [ + { + "xml": "<activity android:clearTaskOnLaunch=\"true\" android:configChanges=\"orientation|keyboardHidden|screenSize\" android:exported=\"false\" android:name=\"com.google.zxing.client.android.CaptureActivity\" android:theme=\"@android:style/Theme.NoTitleBar.Fullscreen\" android:windowSoftInputMode=\"stateAlwaysHidden\" />", + "count": 1 + }, + { + "xml": "<activity android:label=\"Share\" android:name=\"com.google.zxing.client.android.encode.EncodeActivity\" />", + "count": 1 + } + ] } - }, - "dependent_plugins": {}, - "modules": [ - { - "id": "cordova-clipboard.Clipboard", - "file": "plugins/cordova-clipboard/www/clipboard.js", - "pluginId": "cordova-clipboard", - "clobbers": [ - "cordova.plugins.clipboard" - ] - }, - { - "id": "cordova-plugin-camera.Camera", - "file": "plugins/cordova-plugin-camera/www/CameraConstants.js", - "pluginId": "cordova-plugin-camera", - "clobbers": [ - "Camera" - ] - }, - { - "id": "cordova-plugin-camera.CameraPopoverOptions", - "file": "plugins/cordova-plugin-camera/www/CameraPopoverOptions.js", - "pluginId": "cordova-plugin-camera", - "clobbers": [ - "CameraPopoverOptions" - ] - }, - { - "id": "cordova-plugin-camera.camera", - "file": "plugins/cordova-plugin-camera/www/Camera.js", - "pluginId": "cordova-plugin-camera", - "clobbers": [ - "navigator.camera" - ] - }, - { - "id": "cordova-plugin-camera.CameraPopoverHandle", - "file": "plugins/cordova-plugin-camera/www/CameraPopoverHandle.js", - "pluginId": "cordova-plugin-camera", - "clobbers": [ - "CameraPopoverHandle" - ] - }, - { - "id": "cordova-plugin-device.device", - "file": "plugins/cordova-plugin-device/www/device.js", - "pluginId": "cordova-plugin-device", - "clobbers": [ - "device" - ] - }, - { - "id": "cordova-plugin-dialogs.notification", - "file": "plugins/cordova-plugin-dialogs/www/notification.js", - "pluginId": "cordova-plugin-dialogs", - "merges": [ - "navigator.notification" - ] - }, - { - "id": "cordova-plugin-dialogs.notification_android", - "file": "plugins/cordova-plugin-dialogs/www/android/notification.js", - "pluginId": "cordova-plugin-dialogs", - "merges": [ - "navigator.notification" - ] - }, - { - "id": "cordova-plugin-inappbrowser.inappbrowser", - "file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js", - "pluginId": "cordova-plugin-inappbrowser", - "clobbers": [ - "cordova.InAppBrowser.open", - "window.open" - ] - }, - { - "id": "cordova-plugin-minisodium.MiniSodium", - "file": "plugins/cordova-plugin-minisodium/www/MiniSodium.js", - "pluginId": "cordova-plugin-minisodium", - "clobbers": [ - "window.plugins.MiniSodium" - ] - }, - { - "id": "cordova-plugin-secure-storage.SecureStorage", - "file": "plugins/cordova-plugin-secure-storage/www/securestorage.js", - "pluginId": "cordova-plugin-secure-storage", - "clobbers": [ - "SecureStorage" - ] - }, - { - "id": "cordova-plugin-secure-storage.sjcl_ss", - "file": "plugins/cordova-plugin-secure-storage/www/sjcl_ss.js", - "pluginId": "cordova-plugin-secure-storage", - "runs": true - }, - { - "id": "cordova-plugin-splashscreen.SplashScreen", - "file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js", - "pluginId": "cordova-plugin-splashscreen", - "clobbers": [ - "navigator.splashscreen" - ] - }, - { - "id": "cordova-plugin-statusbar.statusbar", - "file": "plugins/cordova-plugin-statusbar/www/statusbar.js", - "pluginId": "cordova-plugin-statusbar", - "clobbers": [ - "window.StatusBar" - ] - }, - { - "id": "cordova-plugin-vibration.notification", - "file": "plugins/cordova-plugin-vibration/www/vibration.js", - "pluginId": "cordova-plugin-vibration", - "merges": [ - "navigator.notification", - "navigator" - ] - }, - { - "id": "cordova-plugin-websocket.websocket", - "file": "plugins/cordova-plugin-websocket/www/websocket.js", - "pluginId": "cordova-plugin-websocket", - "clobbers": [ - "WebSocket" - ] - }, - { - "id": "cordova-plugin-x-toast.Toast", - "file": "plugins/cordova-plugin-x-toast/www/Toast.js", - "pluginId": "cordova-plugin-x-toast", - "clobbers": [ - "window.plugins.toast" - ] - }, - { - "id": "cordova-plugin-x-toast.tests", - "file": "plugins/cordova-plugin-x-toast/test/tests.js", - "pluginId": "cordova-plugin-x-toast" - }, - { - "id": "ionic-plugin-keyboard.keyboard", - "file": "plugins/ionic-plugin-keyboard/www/android/keyboard.js", - "pluginId": "ionic-plugin-keyboard", - "clobbers": [ - "cordova.plugins.Keyboard" - ], - "runs": true - }, - { - "id": "phonegap-plugin-barcodescanner.BarcodeScanner", - "file": "plugins/phonegap-plugin-barcodescanner/www/barcodescanner.js", - "pluginId": "phonegap-plugin-barcodescanner", - "clobbers": [ - "cordova.plugins.barcodeScanner" - ] + }, + "config.xml": { + "parents": { + "/*": [ + { + "xml": "<feature name=\"CDVIonicKeyboard\"><param name=\"android-package\" onload=\"true\" value=\"io.ionic.keyboard.CDVIonicKeyboard\" /></feature>", + "count": 1 + }, + { + "xml": "<allow-navigation href=\"http://localhost/*\" />", + "count": 1 + }, + { + "xml": "<allow-navigation href=\"https://localhost/*\" />", + "count": 1 + }, + { + "xml": "<allow-navigation href=\"ionic://*\" />", + "count": 1 + }, + { + "xml": "<preference name=\"webView\" value=\"com.ionicframework.cordova.webview.IonicWebViewEngine\" />", + "count": 1 + }, + { + "xml": "<feature name=\"IonicWebView\"><param name=\"android-package\" value=\"com.ionicframework.cordova.webview.IonicWebView\" /></feature>", + "count": 1 + } + ] } - ], - "plugin_metadata": { - "cordova-clipboard": "1.1.1", - "cordova-plugin-camera": "2.4.1", - "cordova-plugin-console": "1.1.0", - "cordova-plugin-device": "1.1.7", - "cordova-plugin-dialogs": "1.3.4", - "cordova-plugin-inappbrowser": "1.7.2", - "cordova-plugin-minisodium": "1.0.0", - "cordova-plugin-secure-storage": "2.6.8", - "cordova-plugin-splashscreen": "3.2.2", - "cordova-plugin-statusbar": "2.3.0", - "cordova-plugin-vibration": "2.1.6", - "cordova-plugin-websocket": "0.12.2", - "cordova-plugin-whitelist": "1.3.3", - "cordova-plugin-x-toast": "2.6.0", - "ionic-plugin-keyboard": "2.2.1", - "phonegap-plugin-barcodescanner": "7.0.0" + } + } + }, + "installed_plugins": { + "cordova-clipboard": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-camera": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-console": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-device": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-dialogs": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-inappbrowser": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-minisodium": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-secure-storage": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-splashscreen": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-statusbar": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-vibration": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-websocket": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-whitelist": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-x-toast": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "ionic-plugin-keyboard": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "phonegap-plugin-barcodescanner": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-ionic-keyboard": { + "PACKAGE_NAME": "fr.duniter.cesium" + }, + "cordova-plugin-ionic-webview": { + "ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+", + "PACKAGE_NAME": "fr.duniter.cesium" + } + }, + "dependent_plugins": {}, + "modules": [ + { + "id": "cordova-clipboard.Clipboard", + "file": "plugins/cordova-clipboard/www/clipboard.js", + "pluginId": "cordova-clipboard", + "clobbers": [ + "cordova.plugins.clipboard" + ] + }, + { + "id": "cordova-plugin-camera.Camera", + "file": "plugins/cordova-plugin-camera/www/CameraConstants.js", + "pluginId": "cordova-plugin-camera", + "clobbers": [ + "Camera" + ] + }, + { + "id": "cordova-plugin-camera.CameraPopoverOptions", + "file": "plugins/cordova-plugin-camera/www/CameraPopoverOptions.js", + "pluginId": "cordova-plugin-camera", + "clobbers": [ + "CameraPopoverOptions" + ] + }, + { + "id": "cordova-plugin-camera.camera", + "file": "plugins/cordova-plugin-camera/www/Camera.js", + "pluginId": "cordova-plugin-camera", + "clobbers": [ + "navigator.camera" + ] + }, + { + "id": "cordova-plugin-camera.CameraPopoverHandle", + "file": "plugins/cordova-plugin-camera/www/CameraPopoverHandle.js", + "pluginId": "cordova-plugin-camera", + "clobbers": [ + "CameraPopoverHandle" + ] + }, + { + "id": "cordova-plugin-device.device", + "file": "plugins/cordova-plugin-device/www/device.js", + "pluginId": "cordova-plugin-device", + "clobbers": [ + "device" + ] + }, + { + "id": "cordova-plugin-dialogs.notification", + "file": "plugins/cordova-plugin-dialogs/www/notification.js", + "pluginId": "cordova-plugin-dialogs", + "merges": [ + "navigator.notification" + ] + }, + { + "id": "cordova-plugin-dialogs.notification_android", + "file": "plugins/cordova-plugin-dialogs/www/android/notification.js", + "pluginId": "cordova-plugin-dialogs", + "merges": [ + "navigator.notification" + ] + }, + { + "id": "cordova-plugin-inappbrowser.inappbrowser", + "file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js", + "pluginId": "cordova-plugin-inappbrowser", + "clobbers": [ + "cordova.InAppBrowser.open", + "window.open" + ] + }, + { + "id": "cordova-plugin-minisodium.MiniSodium", + "file": "plugins/cordova-plugin-minisodium/www/MiniSodium.js", + "pluginId": "cordova-plugin-minisodium", + "clobbers": [ + "window.plugins.MiniSodium" + ] + }, + { + "id": "cordova-plugin-secure-storage.SecureStorage", + "file": "plugins/cordova-plugin-secure-storage/www/securestorage.js", + "pluginId": "cordova-plugin-secure-storage", + "clobbers": [ + "SecureStorage" + ] + }, + { + "id": "cordova-plugin-secure-storage.sjcl_ss", + "file": "plugins/cordova-plugin-secure-storage/www/sjcl_ss.js", + "pluginId": "cordova-plugin-secure-storage", + "runs": true + }, + { + "id": "cordova-plugin-splashscreen.SplashScreen", + "file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js", + "pluginId": "cordova-plugin-splashscreen", + "clobbers": [ + "navigator.splashscreen" + ] + }, + { + "id": "cordova-plugin-statusbar.statusbar", + "file": "plugins/cordova-plugin-statusbar/www/statusbar.js", + "pluginId": "cordova-plugin-statusbar", + "clobbers": [ + "window.StatusBar" + ] + }, + { + "id": "cordova-plugin-vibration.notification", + "file": "plugins/cordova-plugin-vibration/www/vibration.js", + "pluginId": "cordova-plugin-vibration", + "merges": [ + "navigator.notification", + "navigator" + ] + }, + { + "id": "cordova-plugin-websocket.websocket", + "file": "plugins/cordova-plugin-websocket/www/websocket.js", + "pluginId": "cordova-plugin-websocket", + "clobbers": [ + "WebSocket" + ] + }, + { + "id": "cordova-plugin-x-toast.Toast", + "file": "plugins/cordova-plugin-x-toast/www/Toast.js", + "pluginId": "cordova-plugin-x-toast", + "clobbers": [ + "window.plugins.toast" + ] + }, + { + "id": "cordova-plugin-x-toast.tests", + "file": "plugins/cordova-plugin-x-toast/test/tests.js", + "pluginId": "cordova-plugin-x-toast" + }, + { + "id": "ionic-plugin-keyboard.keyboard", + "file": "plugins/ionic-plugin-keyboard/www/android/keyboard.js", + "pluginId": "ionic-plugin-keyboard", + "clobbers": [ + "cordova.plugins.Keyboard" + ], + "runs": true + }, + { + "id": "phonegap-plugin-barcodescanner.BarcodeScanner", + "file": "plugins/phonegap-plugin-barcodescanner/www/barcodescanner.js", + "pluginId": "phonegap-plugin-barcodescanner", + "clobbers": [ + "cordova.plugins.barcodeScanner" + ] + }, + { + "id": "cordova-plugin-ionic-keyboard.keyboard", + "file": "plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js", + "pluginId": "cordova-plugin-ionic-keyboard", + "clobbers": [ + "window.Keyboard" + ] + }, + { + "id": "cordova-plugin-ionic-webview.IonicWebView", + "file": "plugins/cordova-plugin-ionic-webview/src/www/util.js", + "pluginId": "cordova-plugin-ionic-webview", + "clobbers": [ + "Ionic.WebView" + ] } -} \ No newline at end of file + ], + "plugin_metadata": { + "cordova-clipboard": "1.1.1", + "cordova-plugin-camera": "2.4.1", + "cordova-plugin-console": "1.1.0", + "cordova-plugin-device": "1.1.7", + "cordova-plugin-dialogs": "1.3.4", + "cordova-plugin-inappbrowser": "1.7.2", + "cordova-plugin-minisodium": "1.0.0", + "cordova-plugin-secure-storage": "2.6.8", + "cordova-plugin-splashscreen": "3.2.2", + "cordova-plugin-statusbar": "2.3.0", + "cordova-plugin-vibration": "2.1.6", + "cordova-plugin-websocket": "0.12.2", + "cordova-plugin-whitelist": "1.3.3", + "cordova-plugin-x-toast": "2.6.0", + "ionic-plugin-keyboard": "2.2.1", + "phonegap-plugin-barcodescanner": "7.0.0", + "cordova-plugin-ionic-keyboard": "2.2.0", + "cordova-plugin-ionic-webview": "4.1.3" + } +} diff --git a/assets/www/api/index.html b/assets/www/api/index.html index a70c78817d8a4e25aae14466f07189f2a0b621da..dddac1f7e8889296ba9392e7ef60e18c0a0ce0f3 100644 --- a/assets/www/api/index.html +++ b/assets/www/api/index.html @@ -3,13 +3,19 @@ <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, width=device-width, minimal-ui"> - <meta name="apple-mobile-web-app-capable" content="yes"> <title>Cesium API</title> <link rel="icon" href="../img/favicon.ico"> + <meta name="theme-color" content="black"> + + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black"> + <link rel="apple-touch-icon" href="../img/logo_57px.png"> + <!-- build:css dist_css/cesium-api.css --> <link rel="stylesheet" type="text/css" href="../css/ionic.app.min.css"> <link rel="stylesheet" type="text/css" href="../css/style.css"> + <link rel="stylesheet" type="text/css" href="../lib/angular-image-crop/image-crop-styles.css"> <!--removeIf(device)--> <link rel="stylesheet" type="text/css" href="../css/style-no-device.css"> <!--endRemoveIf(device)--> @@ -25,42 +31,48 @@ <!-- build:js dist_js/vendor-api.js --> <!-- vendor js --> -<script src="../js/vendor/moment.min.js"></script> -<script src="../js/vendor/moment.fr.js"></script> -<script src="../js/vendor/moment.nl.js"></script> -<script src="../js/vendor/moment.es.js"></script> -<script src="../js/vendor/numeral.js"></script> -<script src="../js/vendor/numeral.fr.js"></script> -<script src="../js/vendor/numeral.en.js"></script> -<script src="../js/vendor/numeral.nl.js"></script> -<script src="../js/vendor/numeral.es.js"></script> -<script src="../js/vendor/socket-io.js"></script> -<script src="../js/vendor/underscore.js"></script> +<script src="../lib/moment/min/moment-with-locales.min.js"></script> +<script src="../lib/numeral/numeral.js"></script> +<script src="../lib/numeral/languages/fr.js"></script> +<script src="../lib/numeral/languages/en-gb.js"></script> +<script src="../lib/numeral/languages/nl-nl.js"></script> +<script src="../lib/numeral/languages/es.js"></script> +<script src="../lib/numeral/languages/it.js"></script> +<script src="../js/vendor/numeral.eo.js"></script> +<script src="../lib/socket.io-client/dist/socket.io.min.js"></script> +<script src="../lib/underscore/underscore-min.js"></script> + <!-- ionic/angularjs js --> -<script src="../lib/ionic/js/ionic.bundle.js"></script> -<script src="../lib/ionic/js/ionic.material.js"></script> -<script src="../lib/ionic/js/angular/angular-resource.js"></script> -<script src="../lib/ionic/js/angular/angular-translate.js"></script> -<script src="../lib/ionic/js/angular/angular-messages.js"></script> -<script src="../lib/ionic/js/angular/angular-api.js"></script> -<script src="../lib/ionic/js/angular/angular-cache.js"></script> -<script src="../lib/ionic/js/angular/angular-screenmatch.min.js"></script> -<script src="../lib/ionic/js/angular/angular-bind-notifier.min.js"></script> -<script src="../lib/ionic/js/angular/angular-file-saver.bundle.js"></script> -<script src="../lib/ionic/js/angular/angular-idle.js"></script> +<script src="../lib/ionic/js/ionic.js"></script> +<script src="../lib/angular/angular.js"></script> +<script src="../lib/angular-animate/angular-animate.js"></script> +<script src="../lib/angular-sanitize/angular-sanitize.js"></script> +<script src="../lib/angular-ui-router/release/angular-ui-router.js"></script> +<script src="../lib/ionic/js/ionic-angular.js"></script> +<script src="../lib/ionic-material/dist/ionic.material.js"></script> +<script src="../lib/angular-resource/angular-resource.js"></script> +<script src="../lib/angular-translate/angular-translate.js"></script> +<script src="../lib/angular-messages/angular-messages.js"></script> +<script src="../lib/angular-api/angular-api.js"></script> +<script src="../lib/angular-cache/dist/angular-cache.js"></script> +<script src="../lib/angular-screenmatch/dist/angular-screenmatch.min.js"></script> +<script src="../lib/angular-bind-notifier/dist/angular-bind-notifier.min.js"></script> +<script src="../lib/angular-file-saver/dist/angular-file-saver.bundle.js"></script> +<script src="../lib/ng-idle/angular-idle.js"></script> +<script src="../lib/angular-fullscreen/src/angular-fullscreen.js"></script> <script src="../js/vendor/base58.js" async></script> <!--removeIf(android)--> <!--removeIf(ios)--> - <script src="../js/vendor/nacl_factory.js" async></script> - <script src="../js/vendor/scrypt-em.js" async></script> + <script src="../lib/js-nacl/lib/nacl_factory.js" async></script> + <script src="../lib/js-scrypt/browser/scrypt.js" async></script> <script src="../js/vendor/base64.js" async></script> <!--endRemoveIf(ios)--> <!--endRemoveIf(android)--> <!--removeIf(no-device)--> <script src="../js/vendor/sha256.min.js" async></script> - <script src="../js/vendor/ng-cordova.min.js"></script> + <script src="../lib/ngCordova/dist/ng-cordova.min.js"></script> <!--endRemoveIf(no-device)--> <!-- endbuild --> @@ -73,6 +85,7 @@ <!-- services --> <script src="../dist/dist_js/app/services/settings-services.js"></script> <script src="../dist/dist_js/app/services/network-services.js"></script> +<script src="../dist/dist_js/app/services/desktop-services.js"></script> <script src="../dist/dist_js/app/services/crypto-services.js"></script> <script src="../dist/dist_js/app/services/utils-services.js"></script> <script src="../dist/dist_js/app/services/cache-services.js"></script> @@ -85,14 +98,15 @@ <script src="../dist/dist_js/app/services/wot-services.js"></script> <script src="../dist/dist_js/app/services/tx-services.js"></script> <script src="../dist/dist_js/app/services/wallet-services.js"></script> -<script src="../dist/dist_js/app/services/plugin-services.js"></script> <script src="../dist/dist_js/app/services/help-services.js"></script> +<script src="../dist/dist_js/app/services/plugin-services.js"></script> <script src="../dist/dist_js/app/services.js"></script> <script src="../dist/dist_js/app/api/api-demo-services.js"></script> <!-- entities --> <script src="../dist/dist_js/app/entities/peer.js"></script> <script src="../dist/dist_js/app/entities/block.js"></script> +<script src="../dist/dist_js/app/entities/ws2pmessage.js"></script> <!-- controllers --> <script src="../dist/dist_js/app/controllers/login-controllers.js"></script> diff --git a/assets/www/cordova_plugins.js b/assets/www/cordova_plugins.js index 119dd559adedd09804eb2a912245542ec963e574..2f67d65f5bcdf6c704b89d61fb1c6f99f6f08e98 100644 --- a/assets/www/cordova_plugins.js +++ b/assets/www/cordova_plugins.js @@ -157,6 +157,22 @@ module.exports = [ "clobbers": [ "cordova.plugins.barcodeScanner" ] + }, + { + "id": "cordova-plugin-ionic-keyboard.keyboard", + "file": "plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js", + "pluginId": "cordova-plugin-ionic-keyboard", + "clobbers": [ + "window.Keyboard" + ] + }, + { + "id": "cordova-plugin-ionic-webview.IonicWebView", + "file": "plugins/cordova-plugin-ionic-webview/src/www/util.js", + "pluginId": "cordova-plugin-ionic-webview", + "clobbers": [ + "Ionic.WebView" + ] } ]; module.exports.metadata = @@ -177,7 +193,9 @@ module.exports.metadata = "cordova-plugin-whitelist": "1.3.3", "cordova-plugin-x-toast": "2.6.0", "ionic-plugin-keyboard": "2.2.1", - "phonegap-plugin-barcodescanner": "7.0.0" + "phonegap-plugin-barcodescanner": "7.0.0", + "cordova-plugin-ionic-keyboard": "2.2.0", + "cordova-plugin-ionic-webview": "4.1.3" }; // BOTTOM OF METADATA }); \ No newline at end of file diff --git a/assets/www/css/angular-image-crop.css b/assets/www/css/angular-image-crop.css deleted file mode 100644 index 2da5e010667905e2e2e5b8f62a25e73a2c8bd9b6..0000000000000000000000000000000000000000 --- a/assets/www/css/angular-image-crop.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Some of these styles you can override, things like colors, - * however some styles are required for the structure, and are critical to this module behaving properly! - */ - -/* Core component styles */ -.ng-image-crop { - text-align: center; - margin: 0 auto; - position: relative; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; -} -/* Each of the 3 steps in the process are contained within sections */ -.ng-image-crop > section { - background: #ccc; -} -/* The cropping button */ -.ng-image-crop button { - margin-top: 10px; -} -/* The dashed cropping guideline */ -.ng-image-crop .cropping-guide { - display: block; - background: rgba(255, 255, 255, .3); - border: 2px dashed white; - position: absolute; - pointer-events: none; -} -/* The circular themed cropping guideline */ -.ng-image-crop--circle .cropping-guide { - border-radius: 50%; - -webkit-border-radius: 50%; - -moz-border-radius: 50%; - -ms-border-radius: 50%; - -o-border-radius: 50%; -} -/* The canvas where the user positions the image via dragging and zooming */ -.ng-image-crop .cropping-canvas { - background: rgba(255, 255, 255, .3); - margin: 0 auto; - cursor: move; -} -/* The overlayed draggable zoom handle in the corner of the module */ -.ng-image-crop .zoom-handle { - display: block; - position: absolute; - bottom: 1px; - left: 1px; - background: rgba(255,255,255,0.7); - width: 80px; - height: 80px; - cursor: move; - border-radius: 200px 50px; -} -/* The text within the zoom handle */ -.ng-image-crop .zoom-handle > span { - color: rgba(0, 0, 0, 0.5); - -webkit-transform: rotate(-45deg); - -moz-transform: rotate(-45deg); - -ms-transform: rotate(-45deg); - -o-transform: rotate(-45deg); - transform: rotate(-45deg); - display: block; - position: relative; - top: 32px; -} \ No newline at end of file diff --git a/assets/www/css/ionic.app.css b/assets/www/css/ionic.app.css index 88f178e12442dfa854cb5f652529f37034a84fa2..117697ee3f78cccc8e3423a73e41a26f421b315f 100644 --- a/assets/www/css/ionic.app.css +++ b/assets/www/css/ionic.app.css @@ -19,7 +19,7 @@ $dark: #444 !default; Ionicons, v2.0.1 Created by Ben Sperry for the Ionic Framework, http://ionicons.com/ https://twitter.com/benjsperry https://twitter.com/ionicframework - MIT License: https://github.com/driftyco/ionicons + MIT License: https://github.com/ionic-team/ionicons Android-style icons originally built by Google’s Material Design Icons: https://github.com/google/material-design-icons @@ -766,7 +766,7 @@ $dark: #444 !default; .ion-wineglass:before, .ion-woman:before, .ion-wrench:before, -.ion-xbox:before, .badge-editable:hover:before { +.ion-xbox:before, .badge-editable:hover:before, .text-editable:hover:after { display: inline-block; font-family: "Ionicons"; speak: none; @@ -3085,7 +3085,7 @@ a:hover { */ a { -webkit-user-drag: none; - -webkit-tap-highlight-color: transparent; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -webkit-tap-highlight-color: transparent; } a[href]:hover { cursor: pointer; } @@ -3322,7 +3322,7 @@ body, -webkit-text-size-adjust: none; -moz-text-size-adjust: none; text-size-adjust: none; - -webkit-tap-highlight-color: transparent; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -webkit-tap-highlight-color: transparent; -webkit-user-select: none; -moz-user-select: none; @@ -3487,8 +3487,8 @@ ion-infinite-scroll { ion-infinite-scroll:not(.active) .icon:before, ion-infinite-scroll:not(.active) .icon-help:before, ion-infinite-scroll:not(.active) .icon-alert:before, - ion-infinite-scroll:not(.active) #menu .footer .icon-help:before, #menu .footer - ion-infinite-scroll:not(.active) .icon-help:before { + ion-infinite-scroll:not(.active) #menu .footer .icon-help:before, + #menu .footer ion-infinite-scroll:not(.active) .icon-help:before { display: none; } .overflow-scroll { @@ -3735,7 +3735,7 @@ a.subdued { z-index: 11; width: 100%; height: 100%; - background-color: transparent; } + background-color: rgba(0, 0, 0, 0); } .action-sheet-backdrop.active { background-color: rgba(0, 0, 0, 0.4); } @@ -4036,13 +4036,13 @@ a.subdued { .bar .button .icon:before, .bar .button .icon-help:before, .bar .button .icon-alert:before, - .bar .button #menu .footer .icon-help:before, #menu .footer - .bar .button .icon-help:before, .bar .button.icon:before, .bar .button.icon-help:before, .bar .button.icon-alert:before, .bar #menu .footer .button.icon-help:before, #menu .footer .bar .button.icon-help:before, .bar .button.icon-left:before, .bar .button.icon-right:before, .bar button.button-icon:before, + .bar .button #menu .footer .icon-help:before, + #menu .footer .bar .button .icon-help:before, .bar .button.icon:before, .bar .button.icon-help:before, .bar .button.icon-alert:before, .bar #menu .footer .button.icon-help:before, #menu .footer .bar .button.icon-help:before, .bar .button.icon-left:before, .bar .button.icon-right:before, .bar button.button-icon:before, .bar button .icon:before, .bar button .icon-help:before, .bar button .icon-alert:before, - .bar button #menu .footer .icon-help:before, #menu .footer - .bar button .icon-help:before, .bar button.icon:before, .bar button.icon-help:before, .bar button.icon-alert:before, .bar #menu .footer button.icon-help:before, #menu .footer .bar button.icon-help:before, .bar button.icon-left:before, .bar button.icon-right:before { + .bar button #menu .footer .icon-help:before, + #menu .footer .bar button .icon-help:before, .bar button.icon:before, .bar button.icon-help:before, .bar button.icon-alert:before, .bar #menu .footer button.icon-help:before, #menu .footer .bar button.icon-help:before, .bar button.icon-left:before, .bar button.icon-right:before { padding-right: 2px; padding-left: 2px; font-size: 20px; @@ -4090,68 +4090,68 @@ a.subdued { display: inherit; } .bar .title + .button:last-child, .bar > .button + .button:last-child, - .bar > .button.pull-right, .popover-helptip - .bar > .button.icon.icon-right, .popover-helptip - .bar > .button.icon-right.icon-help, .popover-helptip - .bar > .button.icon-right.icon-alert, .popover-helptip #menu .footer - .bar > .button.icon-right.icon-help, #menu .footer .popover-helptip - .bar > .button.icon-right.icon-help, .popover-helptip - .bar > .button.icon.icon-center, .popover-helptip - .bar > .button.icon-center.icon-help, .popover-helptip - .bar > .button.icon-center.icon-alert, .popover-helptip #menu .footer - .bar > .button.icon-center.icon-help, #menu .footer .popover-helptip - .bar > .button.icon-center.icon-help, .popover-helptip - .bar > .button.icon.icon-bottom-right, .popover-helptip - .bar > .button.icon-bottom-right.icon-help, .popover-helptip - .bar > .button.icon-bottom-right.icon-alert, .popover-helptip #menu .footer - .bar > .button.icon-bottom-right.icon-help, #menu .footer .popover-helptip - .bar > .button.icon-bottom-right.icon-help, .popover-helptip - .bar > .button.icon.icon-bottom-center, .popover-helptip - .bar > .button.icon-bottom-center.icon-help, .popover-helptip - .bar > .button.icon-bottom-center.icon-alert, .popover-helptip #menu .footer - .bar > .button.icon-bottom-center.icon-help, #menu .footer .popover-helptip - .bar > .button.icon-bottom-center.icon-help, + .bar > .button.pull-right, + .popover-helptip .bar > .button.icon.icon-right, + .popover-helptip .bar > .button.icon-right.icon-help, + .popover-helptip .bar > .button.icon-right.icon-alert, + .popover-helptip #menu .footer .bar > .button.icon-right.icon-help, + #menu .footer .popover-helptip .bar > .button.icon-right.icon-help, + .popover-helptip .bar > .button.icon.icon-center, + .popover-helptip .bar > .button.icon-center.icon-help, + .popover-helptip .bar > .button.icon-center.icon-alert, + .popover-helptip #menu .footer .bar > .button.icon-center.icon-help, + #menu .footer .popover-helptip .bar > .button.icon-center.icon-help, + .popover-helptip .bar > .button.icon.icon-bottom-right, + .popover-helptip .bar > .button.icon-bottom-right.icon-help, + .popover-helptip .bar > .button.icon-bottom-right.icon-alert, + .popover-helptip #menu .footer .bar > .button.icon-bottom-right.icon-help, + #menu .footer .popover-helptip .bar > .button.icon-bottom-right.icon-help, + .popover-helptip .bar > .button.icon.icon-bottom-center, + .popover-helptip .bar > .button.icon-bottom-center.icon-help, + .popover-helptip .bar > .button.icon-bottom-center.icon-alert, + .popover-helptip #menu .footer .bar > .button.icon-bottom-center.icon-help, + #menu .footer .popover-helptip .bar > .button.icon-bottom-center.icon-help, .bar .buttons.pull-right, - .bar .popover-helptip .buttons.icon.icon-right, .popover-helptip - .bar .buttons.icon.icon-right, - .bar .popover-helptip .buttons.icon-right.icon-help, .popover-helptip - .bar .buttons.icon-right.icon-help, - .bar .popover-helptip .buttons.icon-right.icon-alert, .popover-helptip - .bar .buttons.icon-right.icon-alert, - .bar .popover-helptip #menu .footer .buttons.icon-right.icon-help, .popover-helptip #menu .footer - .bar .buttons.icon-right.icon-help, - .bar #menu .footer .popover-helptip .buttons.icon-right.icon-help, #menu .footer .popover-helptip - .bar .buttons.icon-right.icon-help, - .bar .popover-helptip .buttons.icon.icon-center, .popover-helptip - .bar .buttons.icon.icon-center, - .bar .popover-helptip .buttons.icon-center.icon-help, .popover-helptip - .bar .buttons.icon-center.icon-help, - .bar .popover-helptip .buttons.icon-center.icon-alert, .popover-helptip - .bar .buttons.icon-center.icon-alert, - .bar .popover-helptip #menu .footer .buttons.icon-center.icon-help, .popover-helptip #menu .footer - .bar .buttons.icon-center.icon-help, - .bar #menu .footer .popover-helptip .buttons.icon-center.icon-help, #menu .footer .popover-helptip - .bar .buttons.icon-center.icon-help, - .bar .popover-helptip .buttons.icon.icon-bottom-right, .popover-helptip - .bar .buttons.icon.icon-bottom-right, - .bar .popover-helptip .buttons.icon-bottom-right.icon-help, .popover-helptip - .bar .buttons.icon-bottom-right.icon-help, - .bar .popover-helptip .buttons.icon-bottom-right.icon-alert, .popover-helptip - .bar .buttons.icon-bottom-right.icon-alert, - .bar .popover-helptip #menu .footer .buttons.icon-bottom-right.icon-help, .popover-helptip #menu .footer - .bar .buttons.icon-bottom-right.icon-help, - .bar #menu .footer .popover-helptip .buttons.icon-bottom-right.icon-help, #menu .footer .popover-helptip - .bar .buttons.icon-bottom-right.icon-help, - .bar .popover-helptip .buttons.icon.icon-bottom-center, .popover-helptip - .bar .buttons.icon.icon-bottom-center, - .bar .popover-helptip .buttons.icon-bottom-center.icon-help, .popover-helptip - .bar .buttons.icon-bottom-center.icon-help, - .bar .popover-helptip .buttons.icon-bottom-center.icon-alert, .popover-helptip - .bar .buttons.icon-bottom-center.icon-alert, - .bar .popover-helptip #menu .footer .buttons.icon-bottom-center.icon-help, .popover-helptip #menu .footer - .bar .buttons.icon-bottom-center.icon-help, - .bar #menu .footer .popover-helptip .buttons.icon-bottom-center.icon-help, #menu .footer .popover-helptip - .bar .buttons.icon-bottom-center.icon-help, + .bar .popover-helptip .buttons.icon.icon-right, + .popover-helptip .bar .buttons.icon.icon-right, + .bar .popover-helptip .buttons.icon-right.icon-help, + .popover-helptip .bar .buttons.icon-right.icon-help, + .bar .popover-helptip .buttons.icon-right.icon-alert, + .popover-helptip .bar .buttons.icon-right.icon-alert, + .bar .popover-helptip #menu .footer .buttons.icon-right.icon-help, + .popover-helptip #menu .footer .bar .buttons.icon-right.icon-help, + .bar #menu .footer .popover-helptip .buttons.icon-right.icon-help, + #menu .footer .popover-helptip .bar .buttons.icon-right.icon-help, + .bar .popover-helptip .buttons.icon.icon-center, + .popover-helptip .bar .buttons.icon.icon-center, + .bar .popover-helptip .buttons.icon-center.icon-help, + .popover-helptip .bar .buttons.icon-center.icon-help, + .bar .popover-helptip .buttons.icon-center.icon-alert, + .popover-helptip .bar .buttons.icon-center.icon-alert, + .bar .popover-helptip #menu .footer .buttons.icon-center.icon-help, + .popover-helptip #menu .footer .bar .buttons.icon-center.icon-help, + .bar #menu .footer .popover-helptip .buttons.icon-center.icon-help, + #menu .footer .popover-helptip .bar .buttons.icon-center.icon-help, + .bar .popover-helptip .buttons.icon.icon-bottom-right, + .popover-helptip .bar .buttons.icon.icon-bottom-right, + .bar .popover-helptip .buttons.icon-bottom-right.icon-help, + .popover-helptip .bar .buttons.icon-bottom-right.icon-help, + .bar .popover-helptip .buttons.icon-bottom-right.icon-alert, + .popover-helptip .bar .buttons.icon-bottom-right.icon-alert, + .bar .popover-helptip #menu .footer .buttons.icon-bottom-right.icon-help, + .popover-helptip #menu .footer .bar .buttons.icon-bottom-right.icon-help, + .bar #menu .footer .popover-helptip .buttons.icon-bottom-right.icon-help, + #menu .footer .popover-helptip .bar .buttons.icon-bottom-right.icon-help, + .bar .popover-helptip .buttons.icon.icon-bottom-center, + .popover-helptip .bar .buttons.icon.icon-bottom-center, + .bar .popover-helptip .buttons.icon-bottom-center.icon-help, + .popover-helptip .bar .buttons.icon-bottom-center.icon-help, + .bar .popover-helptip .buttons.icon-bottom-center.icon-alert, + .popover-helptip .bar .buttons.icon-bottom-center.icon-alert, + .bar .popover-helptip #menu .footer .buttons.icon-bottom-center.icon-help, + .popover-helptip #menu .footer .bar .buttons.icon-bottom-center.icon-help, + .bar #menu .footer .popover-helptip .buttons.icon-bottom-center.icon-help, + #menu .footer .popover-helptip .bar .buttons.icon-bottom-center.icon-help, .bar .title + .buttons { position: absolute; top: 5px; @@ -5225,20 +5225,20 @@ ion-tabs.tabs-striped.tabs-color-active-dark .tab-item.tab-item-active, ion-tabs .tabs-icon-left > .tabs .tab-item .icon, .tabs-icon-left > .tabs .tab-item .icon-help, .tabs-icon-left > .tabs .tab-item .icon-alert, - .tabs-icon-left > .tabs .tab-item #menu .footer .icon-help, #menu .footer - .tabs-icon-left > .tabs .tab-item .icon-help, + .tabs-icon-left > .tabs .tab-item #menu .footer .icon-help, + #menu .footer .tabs-icon-left > .tabs .tab-item .icon-help, .tabs-icon-left > .tabs .tab-item .tab-title, .tabs-icon-right.tabs .tab-item .icon, .tabs-icon-right.tabs .tab-item .icon-help, .tabs-icon-right.tabs .tab-item .icon-alert, - .tabs-icon-right.tabs .tab-item #menu .footer .icon-help, #menu .footer - .tabs-icon-right.tabs .tab-item .icon-help, + .tabs-icon-right.tabs .tab-item #menu .footer .icon-help, + #menu .footer .tabs-icon-right.tabs .tab-item .icon-help, .tabs-icon-right.tabs .tab-item .tab-title, .tabs-icon-right > .tabs .tab-item .icon, .tabs-icon-right > .tabs .tab-item .icon-help, .tabs-icon-right > .tabs .tab-item .icon-alert, - .tabs-icon-right > .tabs .tab-item #menu .footer .icon-help, #menu .footer - .tabs-icon-right > .tabs .tab-item .icon-help, + .tabs-icon-right > .tabs .tab-item #menu .footer .icon-help, + #menu .footer .tabs-icon-right > .tabs .tab-item .icon-help, .tabs-icon-right > .tabs .tab-item .tab-title { display: inline-block; vertical-align: top; @@ -5247,46 +5247,51 @@ ion-tabs.tabs-striped.tabs-color-active-dark .tab-item.tab-item-active, ion-tabs .tabs-icon-left > .tabs .tab-item .icon:before, .tabs-icon-left > .tabs .tab-item .icon-help:before, .tabs-icon-left > .tabs .tab-item .icon-alert:before, - .tabs-icon-left > .tabs .tab-item #menu .footer .icon-help:before, #menu .footer - .tabs-icon-left > .tabs .tab-item .icon-help:before, + .tabs-icon-left > .tabs .tab-item #menu .footer .icon-help:before, + #menu .footer .tabs-icon-left > .tabs .tab-item .icon-help:before, .tabs-icon-left > .tabs .tab-item .tab-title:before, .tabs-icon-right.tabs .tab-item .icon:before, .tabs-icon-right.tabs .tab-item .icon-help:before, .tabs-icon-right.tabs .tab-item .icon-alert:before, - .tabs-icon-right.tabs .tab-item #menu .footer .icon-help:before, #menu .footer - .tabs-icon-right.tabs .tab-item .icon-help:before, + .tabs-icon-right.tabs .tab-item #menu .footer .icon-help:before, + #menu .footer .tabs-icon-right.tabs .tab-item .icon-help:before, .tabs-icon-right.tabs .tab-item .tab-title:before, .tabs-icon-right > .tabs .tab-item .icon:before, .tabs-icon-right > .tabs .tab-item .icon-help:before, .tabs-icon-right > .tabs .tab-item .icon-alert:before, - .tabs-icon-right > .tabs .tab-item #menu .footer .icon-help:before, #menu .footer - .tabs-icon-right > .tabs .tab-item .icon-help:before, + .tabs-icon-right > .tabs .tab-item #menu .footer .icon-help:before, + #menu .footer .tabs-icon-right > .tabs .tab-item .icon-help:before, .tabs-icon-right > .tabs .tab-item .tab-title:before { font-size: 24px; line-height: 49px; } -.tabs-icon-left > .tabs .tab-item .icon, .tabs-icon-left > .tabs .tab-item .icon-help, .tabs-icon-left > .tabs .tab-item .icon-alert, .tabs-icon-left > .tabs .tab-item #menu .footer .icon-help, #menu .footer .tabs-icon-left > .tabs .tab-item .icon-help, -.tabs-icon-left.tabs .tab-item .icon, -.tabs-icon-left.tabs .tab-item .icon-help, -.tabs-icon-left.tabs .tab-item .icon-alert, -.tabs-icon-left.tabs .tab-item #menu .footer .icon-help, #menu .footer -.tabs-icon-left.tabs .tab-item .icon-help { + +.tabs-icon-left > .tabs .tab-item .icon, +.tabs-icon-left > .tabs .tab-item .icon-help, +.tabs-icon-left > .tabs .tab-item .icon-alert, +.tabs-icon-left > .tabs .tab-item #menu .footer .icon-help, +#menu .footer .tabs-icon-left > .tabs .tab-item .icon-help, .tabs-icon-left.tabs .tab-item .icon, .tabs-icon-left.tabs .tab-item .icon-help, .tabs-icon-left.tabs .tab-item .icon-alert, .tabs-icon-left.tabs .tab-item #menu .footer .icon-help, #menu .footer .tabs-icon-left.tabs .tab-item .icon-help { padding-right: 3px; } -.tabs-icon-right > .tabs .tab-item .icon, .tabs-icon-right > .tabs .tab-item .icon-help, .tabs-icon-right > .tabs .tab-item .icon-alert, .tabs-icon-right > .tabs .tab-item #menu .footer .icon-help, #menu .footer .tabs-icon-right > .tabs .tab-item .icon-help, + +.tabs-icon-right > .tabs .tab-item .icon, +.tabs-icon-right > .tabs .tab-item .icon-help, +.tabs-icon-right > .tabs .tab-item .icon-alert, +.tabs-icon-right > .tabs .tab-item #menu .footer .icon-help, +#menu .footer .tabs-icon-right > .tabs .tab-item .icon-help, .tabs-icon-right.tabs .tab-item .icon, .tabs-icon-right.tabs .tab-item .icon-help, .tabs-icon-right.tabs .tab-item .icon-alert, -.tabs-icon-right.tabs .tab-item #menu .footer .icon-help, #menu .footer -.tabs-icon-right.tabs .tab-item .icon-help { +.tabs-icon-right.tabs .tab-item #menu .footer .icon-help, +#menu .footer .tabs-icon-right.tabs .tab-item .icon-help { padding-left: 3px; } .tabs-icon-only > .tabs .icon, .tabs-icon-only > .tabs .icon-help, .tabs-icon-only > .tabs .icon-alert, .tabs-icon-only > .tabs #menu .footer .icon-help, #menu .footer .tabs-icon-only > .tabs .icon-help, .tabs-icon-only.tabs .icon, .tabs-icon-only.tabs .icon-help, .tabs-icon-only.tabs .icon-alert, -.tabs-icon-only.tabs #menu .footer .icon-help, #menu .footer -.tabs-icon-only.tabs .icon-help { +.tabs-icon-only.tabs #menu .footer .icon-help, +#menu .footer .tabs-icon-only.tabs .icon-help { line-height: inherit; } .tab-item.has-badge { @@ -5509,7 +5514,7 @@ ion-tabs.tabs-striped.tabs-color-active-dark .tab-item.tab-item-active, ion-tabs z-index: 10; width: 100%; height: 100%; - background-color: transparent; } + background-color: rgba(0, 0, 0, 0); } .popover-backdrop.active { background-color: rgba(0, 0, 0, 0.1); } @@ -5633,7 +5638,7 @@ ion-tabs.tabs-striped.tabs-color-active-dark .tab-item.tab-item-active, ion-tabs left: 0; bottom: 0; right: 0; - background: transparent; + background: rgba(0, 0, 0, 0); display: -webkit-box; display: -webkit-flex; display: -moz-box; @@ -6253,8 +6258,8 @@ a.item-content { .item-icon-right .icon, .item-icon-right .icon-help, .item-icon-right .icon-alert, -.item-icon-right #menu .footer .icon-help, #menu .footer -.item-icon-right .icon-help { +.item-icon-right #menu .footer .icon-help, +#menu .footer .item-icon-right .icon-help { display: -webkit-box; display: -webkit-flex; display: -moz-box; @@ -6274,8 +6279,8 @@ a.item-content { .item-icon-right .icon:before, .item-icon-right .icon-help:before, .item-icon-right .icon-alert:before, - .item-icon-right #menu .footer .icon-help:before, #menu .footer - .item-icon-right .icon-help:before { + .item-icon-right #menu .footer .icon-help:before, + #menu .footer .item-icon-right .icon-help:before { display: block; width: 32px; text-align: center; } @@ -6297,7 +6302,12 @@ a.item-content { .item-icon-right { padding-right: 54px; } - .item-icon-right .icon, .item-icon-right .icon-help, .item-icon-right .icon-alert, .item-icon-right #menu .footer .icon-help, #menu .footer .item-icon-right .icon-help { + + .item-icon-right .icon, + .item-icon-right .icon-help, + .item-icon-right .icon-alert, + .item-icon-right #menu .footer .icon-help, + #menu .footer .item-icon-right .icon-help { right: 11px; } .item-complex.item-icon-right { @@ -6312,8 +6322,8 @@ a.item-content { .item-icon-left .item-delete .icon, .item-icon-left .item-delete .icon-help, .item-icon-left .item-delete .icon-alert, -.item-icon-left .item-delete #menu .footer .icon-help, #menu .footer -.item-icon-left .item-delete .icon-help { +.item-icon-left .item-delete #menu .footer .icon-help, +#menu .footer .item-icon-left .item-delete .icon-help { left: auto; } .item-icon-left .icon-accessory, @@ -6359,8 +6369,8 @@ a.item-content { .item-button-left .item-content > .button .icon:before, .item-button-left .item-content > .button .icon-help:before, .item-button-left .item-content > .button .icon-alert:before, - .item-button-left .item-content > .button #menu .footer .icon-help:before, #menu .footer - .item-button-left .item-content > .button .icon-help:before { + .item-button-left .item-content > .button #menu .footer .icon-help:before, + #menu .footer .item-button-left .item-content > .button .icon-help:before { position: relative; left: auto; width: auto; @@ -6403,18 +6413,18 @@ button.item.item-button-right { .item-button-right .item-content > .button .icon:before, .item-button-right .item-content > .button .icon-help:before, .item-button-right .item-content > .button .icon-alert:before, - .item-button-right .item-content > .button #menu .footer .icon-help:before, #menu .footer - .item-button-right .item-content > .button .icon-help:before, + .item-button-right .item-content > .button #menu .footer .icon-help:before, + #menu .footer .item-button-right .item-content > .button .icon-help:before, .item-button-right > .buttons .icon:before, .item-button-right > .buttons .icon-help:before, .item-button-right > .buttons .icon-alert:before, - .item-button-right > .buttons #menu .footer .icon-help:before, #menu .footer - .item-button-right > .buttons .icon-help:before, + .item-button-right > .buttons #menu .footer .icon-help:before, + #menu .footer .item-button-right > .buttons .icon-help:before, .item-button-right .item-content > .buttons .icon:before, .item-button-right .item-content > .buttons .icon-help:before, .item-button-right .item-content > .buttons .icon-alert:before, - .item-button-right .item-content > .buttons #menu .footer .icon-help:before, #menu .footer - .item-button-right .item-content > .buttons .icon-help:before { + .item-button-right .item-content > .buttons #menu .footer .icon-help:before, + #menu .footer .item-button-right .item-content > .buttons .icon-help:before { position: relative; left: auto; width: auto; @@ -6740,6 +6750,9 @@ button.item.item-button-right { align-items: center; } .item-options .button:before { margin: 0 auto; } + .item-options ion-option-button:last-child { + padding-right: calc(constant(safe-area-inset-right) + 12px); + padding-right: calc(env(safe-area-inset-right) + 12px); } /** * Lists @@ -6802,23 +6815,27 @@ button.item.item-button-right { .card .item:first-child, .list-inset .item:first-child, -.padding > .list .item:first-child, .item.large-button-bar > .list .item:first-child { +.padding > .list .item:first-child, +.item.large-button-bar > .list .item:first-child { border-top-left-radius: 2px; border-top-right-radius: 2px; } .card .item:first-child .item-content, .list-inset .item:first-child .item-content, - .padding > .list .item:first-child .item-content, .item.large-button-bar > .list .item:first-child .item-content { + .padding > .list .item:first-child .item-content, + .item.large-button-bar > .list .item:first-child .item-content { border-top-left-radius: 2px; border-top-right-radius: 2px; } .card .item:last-child, .list-inset .item:last-child, -.padding > .list .item:last-child, .item.large-button-bar > .list .item:last-child { +.padding > .list .item:last-child, +.item.large-button-bar > .list .item:last-child { border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; } .card .item:last-child .item-content, .list-inset .item:last-child .item-content, - .padding > .list .item:last-child .item-content, .item.large-button-bar > .list .item:last-child .item-content { + .padding > .list .item:last-child .item-content, + .item.large-button-bar > .list .item:last-child .item-content { border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; } @@ -6828,13 +6845,15 @@ button.item.item-button-right { .card .item, .list-inset .item, -.padding > .list .item, .item.large-button-bar > .list .item, +.padding > .list .item, +.item.large-button-bar > .list .item, .padding-horizontal > .list .item { margin-right: 0; margin-left: 0; } .card .item.item-input input, .list-inset .item.item-input input, - .padding > .list .item.item-input input, .item.large-button-bar > .list .item.item-input input, + .padding > .list .item.item-input input, + .item.large-button-bar > .list .item.item-input input, .padding-horizontal > .list .item.item-input input { padding-right: 44px; } @@ -7239,51 +7258,51 @@ button.swiper-pagination-bullet { z-index: 10; } .swiper-container-3d .swiper-slide-shadow-left { - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(transparent)); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0))); /* Safari 4+, Chrome */ - background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, 0.5), transparent); + background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Chrome 10+, Safari 5.1+, iOS 5+ */ - background-image: -moz-linear-gradient(right, rgba(0, 0, 0, 0.5), transparent); + background-image: -moz-linear-gradient(right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Firefox 3.6-15 */ - background-image: -o-linear-gradient(right, rgba(0, 0, 0, 0.5), transparent); + background-image: -o-linear-gradient(right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Opera 11.10-12.00 */ - background-image: linear-gradient(to left, rgba(0, 0, 0, 0.5), transparent); + background-image: linear-gradient(to left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Firefox 16+, IE10, Opera 12.50+ */ } .swiper-container-3d .swiper-slide-shadow-right { - background-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 0.5)), to(transparent)); + background-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0))); /* Safari 4+, Chrome */ - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5), transparent); + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Chrome 10+, Safari 5.1+, iOS 5+ */ - background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5), transparent); + background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Firefox 3.6-15 */ - background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5), transparent); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Opera 11.10-12.00 */ - background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5), transparent); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Firefox 16+, IE10, Opera 12.50+ */ } .swiper-container-3d .swiper-slide-shadow-top { - background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(transparent)); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0))); /* Safari 4+, Chrome */ - background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5), transparent); + background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Chrome 10+, Safari 5.1+, iOS 5+ */ - background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5), transparent); + background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Firefox 3.6-15 */ - background-image: -o-linear-gradient(bottom, rgba(0, 0, 0, 0.5), transparent); + background-image: -o-linear-gradient(bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Opera 11.10-12.00 */ - background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5), transparent); + background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Firefox 16+, IE10, Opera 12.50+ */ } .swiper-container-3d .swiper-slide-shadow-bottom { - background-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 0.5)), to(transparent)); + background-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0))); /* Safari 4+, Chrome */ - background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), transparent); + background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Chrome 10+, Safari 5.1+, iOS 5+ */ - background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.5), transparent); + background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Firefox 3.6-15 */ - background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0.5), transparent); + background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Opera 11.10-12.00 */ - background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), transparent); + background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); /* Firefox 16+, IE10, Opera 12.50+ */ } /* Coverflow */ @@ -8645,8 +8664,8 @@ input:checked + .checkbox-icon:after { width: 0; height: 0; border-top: 5px solid; - border-right: 5px solid transparent; - border-left: 5px solid transparent; + border-right: 5px solid rgba(0, 0, 0, 0); + border-left: 5px solid rgba(0, 0, 0, 0); color: #999; content: ""; pointer-events: none; } @@ -9174,8 +9193,8 @@ a.button { .button-bar > .button .icon:before, .button-bar > .button .icon-help:before, .button-bar > .button .icon-alert:before, - .button-bar > .button #menu .footer .icon-help:before, #menu .footer - .button-bar > .button .icon-help:before { + .button-bar > .button #menu .footer .icon-help:before, + #menu .footer .button-bar > .button .icon-help:before { line-height: 44px; } .button-bar > .button:first-child { border-radius: 4px 0px 0px 4px; } @@ -9189,8 +9208,8 @@ a.button { .button-bar > .button-small .icon:before, .button-bar > .button-small .icon-help:before, .button-bar > .button-small .icon-alert:before, -.button-bar > .button-small #menu .footer .icon-help:before, #menu .footer -.button-bar > .button-small .icon-help:before { +.button-bar > .button-small #menu .footer .icon-help:before, +#menu .footer .button-bar > .button-small .icon-help:before { line-height: 28px; } /** @@ -9539,7 +9558,7 @@ a.button { -ms-user-select: none; user-select: none; -webkit-touch-callout: none; - -webkit-tap-highlight-color: transparent; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -ms-touch-action: none; @@ -9653,7 +9672,7 @@ a.button { .stable-border { border-color: #b2b2b2; } -.positive, .icon-help, a.positive, a.icon-help { +.positive, .text-editable:hover, .icon-help, a.positive, a.text-editable:hover, a.icon-help { color: #387ef5; } .positive-bg { @@ -9710,8 +9729,7 @@ a.button { .dark, .button-text-dark, a.dark, a.button-text-dark { color: #444; } -.dark-bg, .view-identity .hero, -.view-identity .refresher-top-bg:before { +.dark-bg { background-color: #444; } .dark-border { @@ -9745,28 +9763,57 @@ a.button { * Platform specific tweaks */ .platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader) { - height: 64px; } + height: 64px; + height: calc(constant(safe-area-inset-top) + 44px); + height: calc(env(safe-area-inset-top) + 44px); } .platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper { margin-top: 19px !important; } .platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader) > * { - margin-top: 20px; } - -.platform-ios.platform-cordova:not(.fullscreen) .tabs-top > .tabs, -.platform-ios.platform-cordova:not(.fullscreen) .tabs.tabs-top { + margin-top: 20px; + margin-top: constant(safe-area-inset-top); + margin-top: env(safe-area-inset-top); } + +.platform-ios.platform-cordova:not(.fullscreen) .bar-header { + padding-left: calc( constant(safe-area-inset-left) + 5px); + padding-left: calc(env(safe-area-inset-left) + 5px); + padding-right: calc(constant(safe-area-inset-right) + 5px); + padding-right: calc(env(safe-area-inset-right) + 5px); } + .platform-ios.platform-cordova:not(.fullscreen) .bar-header .buttons:last-child { + right: calc(constant(safe-area-inset-right) + 5px); + right: calc(env(safe-area-inset-right) + 5px); } + +.platform-ios.platform-cordova:not(.fullscreen) .has-tabs, .platform-ios.platform-cordova:not(.fullscreen) .bar-footer.has-tabs { + bottom: calc(constant(safe-area-inset-bottom) + 49px); + bottom: calc(env(safe-area-inset-bottom) + 49px); } + +.platform-ios.platform-cordova:not(.fullscreen) .tabs-top > .tabs, .platform-ios.platform-cordova:not(.fullscreen) .tabs.tabs-top { top: 64px; } -.platform-ios.platform-cordova:not(.fullscreen) .has-header, -.platform-ios.platform-cordova:not(.fullscreen) .bar-subheader { - top: 64px; } +.platform-ios.platform-cordova:not(.fullscreen) .tabs { + padding-bottom: constant(safe-area-inset-bottom); + padding-bottom: env(safe-area-inset-bottom); + height: calc(constant(safe-area-inset-bottom) + 49px); + height: calc(env(safe-area-inset-bottom) + 49px); } + +.platform-ios.platform-cordova:not(.fullscreen) .has-header, .platform-ios.platform-cordova:not(.fullscreen) .bar-subheader { + top: 64px; + top: calc(constant(safe-area-inset-top) + 44px); + top: calc(env(safe-area-inset-top) + 44px); } .platform-ios.platform-cordova:not(.fullscreen) .has-subheader { - top: 108px; } + top: 108px; + top: calc(constant(safe-area-inset-top) + 88px); + top: calc(env(safe-area-inset-top) + 88px); } .platform-ios.platform-cordova:not(.fullscreen) .has-header.has-tabs-top { - top: 113px; } + top: 113px; + top: calc(93px + constant(safe-area-inset-top)); + top: calc(93px + env(safe-area-inset-top)); } .platform-ios.platform-cordova:not(.fullscreen) .has-header.has-subheader.has-tabs-top { - top: 157px; } + top: 157px; + top: calc(137px + constant(safe-area-inset-right)); + top: calc(137px + env(safe-area-inset-right)); } .platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader) { height: 44px; } @@ -9775,8 +9822,7 @@ a.button { .platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader) > * { margin-top: 0; } -.platform-ios.platform-cordova .popover .has-header, -.platform-ios.platform-cordova .popover .bar-subheader { +.platform-ios.platform-cordova .popover .has-header, .platform-ios.platform-cordova .popover .bar-subheader { top: 44px; } .platform-ios.platform-cordova .popover .has-subheader { @@ -9786,6 +9832,39 @@ a.button { margin-bottom: 20px; } @media (orientation: landscape) { + .item { + padding: 16px calc(constant(safe-area-inset-right) + 16px); } + .item .badge { + right: calc(constant(safe-area-inset-right) + 32px); } + .item-icon-left { + padding-left: calc(constant(safe-area-inset-left) + 54px); } + .item-icon-left .icon, .item-icon-left .icon-help, .item-icon-left .icon-alert, .item-icon-left #menu .footer .icon-help, #menu .footer .item-icon-left .icon-help { + left: calc(constant(safe-area-inset-left) + 11px); } + .item-icon-right { + padding-right: calc(constant(safe-area-inset-right) + 54px); } + + .item-icon-right .icon, + .item-icon-right .icon-help, + .item-icon-right .icon-alert, + .item-icon-right #menu .footer .icon-help, + #menu .footer .item-icon-right .icon-help { + right: calc(constant(safe-area-inset-right) + 11px); } + .item-complex, + a.item.item-complex, + button.item.item-complex { + padding: 0; } + .item-complex .item-content, a.item.item-complex .item-content, button.item.item-complex .item-content { + padding: 16px calc(constant(safe-area-inset-right) + 49px) 16px calc(constant(safe-area-inset-left) + 16px); } + .item-left-edit.visible.active { + -webkit-transform: translate3d(calc(constant(safe-area-inset-left) + 8px), 0, 0); + transform: translate3d(calc(constant(safe-area-inset-left) + 8px), 0, 0); } + .list-left-editing .item-left-editable .item-content, + .item-left-editing.item-left-editable .item-content { + -webkit-transform: translate3d(calc(constant(safe-area-inset-left) + 50px), 0, 0); + transform: translate3d(calc(constant(safe-area-inset-left) + 50px), 0, 0); } + .item-right-edit { + right: constant(safe-area-inset-right); + right: env(safe-area-inset-right); } .platform-ios.platform-browser.platform-ipad { position: fixed; } } @@ -9964,7 +10043,7 @@ a.button { /* BEGIN Thin */ @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/Thin/RobotoDraft-Thin.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/Thin/RobotoDraft-Thin.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/Thin/RobotoDraft-Thin.ttf?v=1.1.0") format("truetype"); font-weight: 100; font-style: normal; } @@ -9972,7 +10051,7 @@ a.button { /* BEGIN Light */ @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/Light/RobotoDraft-Light.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/Light/RobotoDraft-Light.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/Light/RobotoDraft-Light.ttf?v=1.1.0") format("truetype"); font-weight: 300; font-style: normal; } @@ -9980,13 +10059,13 @@ a.button { /* BEGIN Regular */ @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.ttf?v=1.1.0") format("truetype"); font-weight: 400; font-style: normal; } @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.ttf?v=1.1.0") format("truetype"); font-weight: normal; font-style: normal; } @@ -9994,13 +10073,13 @@ a.button { /* BEGIN Italic */ @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.ttf?v=1.1.0") format("truetype"); font-weight: 400; font-style: italic; } @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.ttf?v=1.1.0") format("truetype"); font-weight: normal; font-style: italic; } @@ -10008,7 +10087,7 @@ a.button { /* BEGIN Medium */ @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/Medium/RobotoDraft-Medium.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/Medium/RobotoDraft-Medium.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/Medium/RobotoDraft-Medium.ttf?v=1.1.0") format("truetype"); font-weight: 500; font-style: normal; } @@ -10016,13 +10095,13 @@ a.button { /* BEGIN Bold */ @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.ttf?v=1.1.0") format("truetype"); font-weight: 700; font-style: normal; } @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.ttf?v=1.1.0") format("truetype"); font-weight: bold; font-style: normal; } @@ -10030,13 +10109,13 @@ a.button { /* BEGIN Bold Italic */ @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0") format("truetype"); font-weight: 700; font-style: italic; } @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0") format("truetype"); font-weight: bold; font-style: italic; } @@ -10044,7 +10123,7 @@ a.button { /* BEGIN Black */ @font-face { font-family: RobotoDraft; - src: url("../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.ttf?v=1.1.0") format("truetype"); + src: url("../lib/robotodraft/fonts/Black/RobotoDraft-Black.woff2?v=1.1.0") format("woff2"), url("../lib/robotodraft/fonts/Black/RobotoDraft-Black.woff?v=1.1.0") format("woff"), url("../lib/robotodraft/fonts/Black/RobotoDraft-Black.ttf?v=1.1.0") format("truetype"); font-weight: 900; font-style: normal; } @@ -10210,7 +10289,8 @@ a.button { -webkit-transition: all 2s cubic-bezier(0.55, 0, 0.1, 1); transition: all 2s cubic-bezier(0.55, 0, 0.1, 1); } -.expanded .bar.bar-header .title, .bar.bar-header.expanded .title { +.expanded .bar.bar-header .title, +.bar.bar-header.expanded .title { bottom: 0; left: 42px !important; top: initial; } @@ -10250,7 +10330,12 @@ a.button { box-shadow: none; /* line-height: initial; */ } -.button-bar > .button .icon:before, .button-bar > .button .icon-help:before, .button-bar > .button .icon-alert:before, .button-bar > .button #menu .footer .icon-help:before, #menu .footer .button-bar > .button .icon-help:before, + +.button-bar > .button .icon:before, +.button-bar > .button .icon-help:before, +.button-bar > .button .icon-alert:before, +.button-bar > .button #menu .footer .icon-help:before, +#menu .footer .button-bar > .button .icon-help:before, .button-bar > .button:before { line-height: initial; } @@ -10773,7 +10858,11 @@ a.button { .animate-fade-slide-in-right .expanded .card.animate-fade-in.item, .animate-fade-slide-in-right .card.animate-fade-in.expanded.item, .animate-ripple .expanded .card.animate-fade-in.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.animate-fade-in.card-comment { +.animate-ripple .card.animate-fade-in.expanded.item, +.card-avatar-small.expanded .card.animate-fade-in.item, +.card-avatar-small .expanded .card.animate-fade-in.item, +.card-avatar-small.expanded .card.animate-fade-in.card-comment, +.card-avatar-small .expanded .card.animate-fade-in.card-comment { opacity: 1; filter: alpha(opacity=100); -webkit-transform: translate3d(0, 0, 0); } @@ -10905,7 +10994,12 @@ a.button { .item-icon-left .icon, .item-icon-left .icon-help, .item-icon-left .icon-alert, .item-icon-left #menu .footer .icon-help, #menu .footer .item-icon-left .icon-help { left: 16px; } -.item-icon-right .icon, .item-icon-right .icon-help, .item-icon-right .icon-alert, .item-icon-right #menu .footer .icon-help, #menu .footer .item-icon-right .icon-help { + +.item-icon-right .icon, +.item-icon-right .icon-help, +.item-icon-right .icon-alert, +.item-icon-right #menu .footer .icon-help, +#menu .footer .item-icon-right .icon-help { right: 16px; } /* @@ -10913,7 +11007,10 @@ a.button { padding-right: 60px; } */ -.item-thumbnail-left > img:first-child, .item-thumbnail-left .item-image, .item-thumbnail-left .item-content > img:first-child, .item-thumbnail-left .item-content .item-image { +.item-thumbnail-left > img:first-child, +.item-thumbnail-left .item-image, +.item-thumbnail-left .item-content > img:first-child, +.item-thumbnail-left .item-content .item-image { border-radius: 50%; } .tab-item.activated { @@ -10976,7 +11073,10 @@ a.button { text-shadow: 0 0 4px rgba(0, 0, 0, 0.95); z-index: 1; } -.item-avatar, .item-avatar .item-content, .item-avatar-left, .item-avatar-left .item-content { +.item-avatar, +.item-avatar .item-content, +.item-avatar-left, +.item-avatar-left .item-content { min-height: 80px; } /* List: Thumbnails @@ -10989,7 +11089,14 @@ a.button { /* List: Avatar ==================================*/ -.item-avatar > img:first-child, .item-avatar .item-image, .item-avatar .item-content > img:first-child, .item-avatar .item-content .item-image, .item-avatar-left > img:first-child, .item-avatar-left .item-image, .item-avatar-left .item-content > img:first-child, .item-avatar-left .item-content .item-image { +.item-avatar > img:first-child, +.item-avatar .item-image, +.item-avatar .item-content > img:first-child, +.item-avatar .item-content .item-image, +.item-avatar-left > img:first-child, +.item-avatar-left .item-image, +.item-avatar-left .item-content > img:first-child, +.item-avatar-left .item-content .item-image { border-radius: 50%; left: 16px; max-height: 40px; @@ -11068,7 +11175,12 @@ a.button { .item-avatar, .item-avatar .item-content, .item-avatar-left, .item-avatar-left .item-content, .card > .item-avatar { padding-left: 72px; } -.item.active, .item.activated, .item-complex.active .item-content, .item-complex.activated .item-content, .item .item-content.active, .item .item-content.activated { +.item.active, +.item.activated, +.item-complex.active .item-content, +.item-complex.activated .item-content, +.item .item-content.active, +.item .item-content.activated { background-color: transparent; } .list-inset { @@ -11184,7 +11296,7 @@ a.button { ==================================*/ .hero.has-mask:after, .item.has-mask:after, .card.has-mask:after { content: ''; - background: -webkit-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.6) 100%); + background: -webkit-linear-gradient(top, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.6) 100%); height: 100%; left: 0; position: absolute; @@ -11194,7 +11306,7 @@ a.button { .hero.has-mask-reverse:after, .item.has-mask-reverse:after, .card.has-mask-reverse:after { content: ''; - background: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.6) 0%, transparent 100%); + background: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%); height: 100%; left: 0; position: absolute; @@ -11448,102 +11560,92 @@ a.button { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } -.animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, .animate-blinds -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-blinds .expanded.item, .animate-blinds -.animate-fade-slide-in-right .expanded .item, -.animate-fade-slide-in-right .expanded .animate-blinds .item, .animate-blinds -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-blinds .expanded.item, .animate-blinds -.animate-ripple .expanded .item, -.animate-ripple .expanded .animate-blinds .item, .animate-blinds -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds .card.card-comment, -.animate-blinds.done > *, .animate-fade-slide-in .expanded .animate-blinds.item > *, +.animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-blinds .expanded.item, +.animate-blinds .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-blinds .expanded.item, +.animate-blinds .animate-ripple .expanded .item, .animate-ripple .expanded .animate-blinds .item, +.animate-blinds .animate-ripple .expanded.item, .animate-ripple .animate-blinds .expanded.item, +.animate-blinds .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-blinds .item, +.animate-blinds .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-blinds .item, +.animate-blinds .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-blinds .card.card-comment, +.animate-blinds .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-blinds .card.card-comment, +.animate-blinds.done > *, +.animate-fade-slide-in .expanded .animate-blinds.item > *, .animate-fade-slide-in .animate-blinds.expanded.item > *, .animate-fade-slide-in-right .expanded .animate-blinds.item > *, .animate-fade-slide-in-right .animate-blinds.expanded.item > *, .animate-ripple .expanded .animate-blinds.item > *, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment > *, -.animate-blinds .in, -.animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded -.animate-blinds .item, -.animate-blinds -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in -.animate-blinds .expanded.item, -.animate-blinds -.animate-fade-slide-in-right .expanded .item, -.animate-fade-slide-in-right .expanded -.animate-blinds .item, -.animate-blinds -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right -.animate-blinds .expanded.item, -.animate-blinds -.animate-ripple .expanded .item, -.animate-ripple .expanded -.animate-blinds .item, -.animate-blinds -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-blinds .card.card-comment, -.animate-blinds.done > *, .animate-fade-slide-in .expanded .animate-blinds.item > *, +.animate-ripple .animate-blinds.expanded.item > *, +.card-avatar-small.expanded .animate-blinds.item > *, +.card-avatar-small .expanded .animate-blinds.item > *, +.card-avatar-small.expanded .animate-blinds.card.card-comment > *, +.card-avatar-small .expanded .animate-blinds.card.card-comment > *, .animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-blinds .expanded.item, +.animate-blinds .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-blinds .expanded.item, +.animate-blinds .animate-ripple .expanded .item, .animate-ripple .expanded .animate-blinds .item, +.animate-blinds .animate-ripple .expanded.item, .animate-ripple .animate-blinds .expanded.item, +.animate-blinds .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-blinds .item, +.animate-blinds .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-blinds .item, +.animate-blinds .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-blinds .card.card-comment, +.animate-blinds .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-blinds .card.card-comment, +.animate-blinds.done > *, +.animate-fade-slide-in .expanded .animate-blinds.item > *, .animate-fade-slide-in .animate-blinds.expanded.item > *, .animate-fade-slide-in-right .expanded .animate-blinds.item > *, .animate-fade-slide-in-right .animate-blinds.expanded.item > *, .animate-ripple .expanded .animate-blinds.item > *, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment > * { +.animate-ripple .animate-blinds.expanded.item > *, +.card-avatar-small.expanded .animate-blinds.item > *, +.card-avatar-small .expanded .animate-blinds.item > *, +.card-avatar-small.expanded .animate-blinds.card.card-comment > *, +.card-avatar-small .expanded .animate-blinds.card.card-comment > * { -ms-transform: translate3d(0, 0, 0); -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } -.animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, .animate-blinds -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-blinds .expanded.item, .animate-blinds -.animate-fade-slide-in-right .expanded .item, -.animate-fade-slide-in-right .expanded .animate-blinds .item, .animate-blinds -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-blinds .expanded.item, .animate-blinds -.animate-ripple .expanded .item, -.animate-ripple .expanded .animate-blinds .item, .animate-blinds -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds .card.card-comment, -.animate-blinds.done .item, .animate-fade-slide-in .expanded .animate-blinds.item .item, +.animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-blinds .expanded.item, +.animate-blinds .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-blinds .expanded.item, +.animate-blinds .animate-ripple .expanded .item, .animate-ripple .expanded .animate-blinds .item, +.animate-blinds .animate-ripple .expanded.item, .animate-ripple .animate-blinds .expanded.item, +.animate-blinds .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-blinds .item, +.animate-blinds .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-blinds .item, +.animate-blinds .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-blinds .card.card-comment, +.animate-blinds .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-blinds .card.card-comment, +.animate-blinds.done .item, +.animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .animate-blinds.expanded.item .item, .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .animate-blinds.expanded.item .item, .animate-ripple .expanded .animate-blinds.item .item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .item, -.animate-blinds .in, -.animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded -.animate-blinds .item, -.animate-blinds -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in -.animate-blinds .expanded.item, -.animate-blinds -.animate-fade-slide-in-right .expanded .item, -.animate-fade-slide-in-right .expanded -.animate-blinds .item, -.animate-blinds -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right -.animate-blinds .expanded.item, -.animate-blinds -.animate-ripple .expanded .item, -.animate-ripple .expanded -.animate-blinds .item, -.animate-blinds -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-blinds .card.card-comment, -.animate-blinds.done .item, .animate-fade-slide-in .expanded .animate-blinds.item .item, +.animate-ripple .animate-blinds.expanded.item .item, +.card-avatar-small.expanded .animate-blinds.item .item, +.card-avatar-small .expanded .animate-blinds.item .item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .item, +.card-avatar-small .expanded .animate-blinds.card.card-comment .item, .animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-blinds .expanded.item, +.animate-blinds .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-blinds .expanded.item, +.animate-blinds .animate-ripple .expanded .item, .animate-ripple .expanded .animate-blinds .item, +.animate-blinds .animate-ripple .expanded.item, .animate-ripple .animate-blinds .expanded.item, +.animate-blinds .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-blinds .item, +.animate-blinds .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-blinds .item, +.animate-blinds .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-blinds .card.card-comment, +.animate-blinds .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-blinds .card.card-comment, +.animate-blinds.done .item, +.animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .animate-blinds.expanded.item .item, .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .animate-blinds.expanded.item .item, .animate-ripple .expanded .animate-blinds.item .item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .item { +.animate-ripple .animate-blinds.expanded.item .item, +.card-avatar-small.expanded .animate-blinds.item .item, +.card-avatar-small .expanded .animate-blinds.item .item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .item, +.card-avatar-small .expanded .animate-blinds.card.card-comment .item { visibility: visible; } .animate-blinds .item, @@ -11555,54 +11657,47 @@ a.button { opacity: 0; filter: alpha(opacity=0); } -.animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, .animate-blinds -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-blinds .expanded.item, .animate-blinds -.animate-fade-slide-in-right .expanded .item, -.animate-fade-slide-in-right .expanded .animate-blinds .item, .animate-blinds -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-blinds .expanded.item, .animate-blinds -.animate-ripple .expanded .item, -.animate-ripple .expanded .animate-blinds .item, .animate-blinds -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds .card.card-comment, +.animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-blinds .expanded.item, +.animate-blinds .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-blinds .expanded.item, +.animate-blinds .animate-ripple .expanded .item, .animate-ripple .expanded .animate-blinds .item, +.animate-blinds .animate-ripple .expanded.item, .animate-ripple .animate-blinds .expanded.item, +.animate-blinds .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-blinds .item, +.animate-blinds .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-blinds .item, +.animate-blinds .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-blinds .card.card-comment, +.animate-blinds .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-blinds .card.card-comment, .animate-blinds.done, .animate-fade-slide-in .expanded .animate-blinds.item, .animate-fade-slide-in .animate-blinds.expanded.item, .animate-fade-slide-in-right .expanded .animate-blinds.item, .animate-fade-slide-in-right .animate-blinds.expanded.item, .animate-ripple .expanded .animate-blinds.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment, -.animate-blinds .in, -.animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded -.animate-blinds .item, -.animate-blinds -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in -.animate-blinds .expanded.item, -.animate-blinds -.animate-fade-slide-in-right .expanded .item, -.animate-fade-slide-in-right .expanded -.animate-blinds .item, -.animate-blinds -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right -.animate-blinds .expanded.item, -.animate-blinds -.animate-ripple .expanded .item, -.animate-ripple .expanded -.animate-blinds .item, -.animate-blinds -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-blinds .card.card-comment, +.animate-ripple .animate-blinds.expanded.item, +.card-avatar-small.expanded .animate-blinds.item, +.card-avatar-small .expanded .animate-blinds.item, +.card-avatar-small.expanded .animate-blinds.card.card-comment, +.card-avatar-small .expanded .animate-blinds.card.card-comment, .animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-blinds .expanded.item, +.animate-blinds .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-blinds .expanded.item, +.animate-blinds .animate-ripple .expanded .item, .animate-ripple .expanded .animate-blinds .item, +.animate-blinds .animate-ripple .expanded.item, .animate-ripple .animate-blinds .expanded.item, +.animate-blinds .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-blinds .item, +.animate-blinds .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-blinds .item, +.animate-blinds .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-blinds .card.card-comment, +.animate-blinds .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-blinds .card.card-comment, .animate-blinds.done, .animate-fade-slide-in .expanded .animate-blinds.item, .animate-fade-slide-in .animate-blinds.expanded.item, .animate-fade-slide-in-right .expanded .animate-blinds.item, .animate-fade-slide-in-right .animate-blinds.expanded.item, .animate-ripple .expanded .animate-blinds.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment { +.animate-ripple .animate-blinds.expanded.item, +.card-avatar-small.expanded .animate-blinds.item, +.card-avatar-small .expanded .animate-blinds.item, +.card-avatar-small.expanded .animate-blinds.card.card-comment, +.card-avatar-small .expanded .animate-blinds.card.card-comment { -ms-transform: scale3d(1, 1, 1); -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); @@ -11611,116 +11706,248 @@ a.button { opacity: 1; filter: alpha(opacity=100); } -.animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, .animate-blinds -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-blinds .expanded.item, .animate-blinds -.animate-fade-slide-in-right .expanded .item, -.animate-fade-slide-in-right .expanded .animate-blinds .item, .animate-blinds -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-blinds .expanded.item, .animate-blinds -.animate-ripple .expanded .item, -.animate-ripple .expanded .animate-blinds .item, .animate-blinds -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds .card.card-comment, +.animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-blinds .expanded.item, +.animate-blinds .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-blinds .expanded.item, +.animate-blinds .animate-ripple .expanded .item, .animate-ripple .expanded .animate-blinds .item, +.animate-blinds .animate-ripple .expanded.item, .animate-ripple .animate-blinds .expanded.item, +.animate-blinds .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-blinds .item, +.animate-blinds .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-blinds .item, +.animate-blinds .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-blinds .card.card-comment, +.animate-blinds .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-blinds .card.card-comment, .animate-blinds.done, .animate-fade-slide-in .expanded .animate-blinds.item, .animate-fade-slide-in .animate-blinds.expanded.item, .animate-fade-slide-in-right .expanded .animate-blinds.item, .animate-fade-slide-in-right .animate-blinds.expanded.item, .animate-ripple .expanded .animate-blinds.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment, -.animate-blinds .in, -.animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded -.animate-blinds .item, -.animate-blinds -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in -.animate-blinds .expanded.item, -.animate-blinds -.animate-fade-slide-in-right .expanded .item, -.animate-fade-slide-in-right .expanded -.animate-blinds .item, -.animate-blinds -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right -.animate-blinds .expanded.item, -.animate-blinds -.animate-ripple .expanded .item, -.animate-ripple .expanded -.animate-blinds .item, -.animate-blinds -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-blinds .card.card-comment, +.animate-ripple .animate-blinds.expanded.item, +.card-avatar-small.expanded .animate-blinds.item, +.card-avatar-small .expanded .animate-blinds.item, +.card-avatar-small.expanded .animate-blinds.card.card-comment, +.card-avatar-small .expanded .animate-blinds.card.card-comment, .animate-blinds .in, .animate-blinds .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-blinds .expanded.item, +.animate-blinds .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-blinds .item, +.animate-blinds .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-blinds .expanded.item, +.animate-blinds .animate-ripple .expanded .item, .animate-ripple .expanded .animate-blinds .item, +.animate-blinds .animate-ripple .expanded.item, .animate-ripple .animate-blinds .expanded.item, +.animate-blinds .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-blinds .item, +.animate-blinds .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-blinds .item, +.animate-blinds .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-blinds .card.card-comment, +.animate-blinds .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-blinds .card.card-comment, .animate-blinds.done, .animate-fade-slide-in .expanded .animate-blinds.item, .animate-fade-slide-in .animate-blinds.expanded.item, .animate-fade-slide-in-right .expanded .animate-blinds.item, .animate-fade-slide-in-right .animate-blinds.expanded.item, .animate-ripple .expanded .animate-blinds.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment { +.animate-ripple .animate-blinds.expanded.item, +.card-avatar-small.expanded .animate-blinds.item, +.card-avatar-small .expanded .animate-blinds.item, +.card-avatar-small.expanded .animate-blinds.card.card-comment, +.card-avatar-small .expanded .animate-blinds.card.card-comment { visibility: visible; } -.animate-blinds.done .in, .animate-fade-slide-in .expanded .animate-blinds.item .in, -.animate-fade-slide-in .animate-blinds.expanded.item .in, -.animate-fade-slide-in-right .expanded .animate-blinds.item .in, -.animate-fade-slide-in-right .animate-blinds.expanded.item .in, -.animate-ripple .expanded .animate-blinds.item .in, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .in, .animate-blinds.done .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds.done .item, .animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .animate-blinds.expanded.item .item, .animate-blinds.done -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-blinds.done .expanded.item, .animate-blinds.done -.animate-fade-slide-in-right .expanded .item, -.animate-fade-slide-in-right .expanded .animate-blinds.done .item, .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .animate-blinds.expanded.item .item, .animate-blinds.done -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-blinds.done .expanded.item, .animate-blinds.done -.animate-ripple .expanded .item, -.animate-ripple .expanded .animate-blinds.done .item, .animate-ripple .expanded .animate-blinds.item .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .item, .animate-blinds.done -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.done .card.card-comment, -.animate-fade-slide-in -.animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple -.animate-fade-slide-in .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-fade-slide-in-right -.animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple -.animate-fade-slide-in-right .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-blinds.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .card.card-comment, -.animate-blinds.done .in, .animate-fade-slide-in .expanded .animate-blinds.item .in, -.animate-fade-slide-in .animate-blinds.expanded.item .in, -.animate-fade-slide-in-right .expanded .animate-blinds.item .in, -.animate-fade-slide-in-right .animate-blinds.expanded.item .in, -.animate-ripple .expanded .animate-blinds.item .in, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .in, -.animate-blinds.done .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded -.animate-blinds.done .item, .animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .animate-blinds.expanded.item .item, -.animate-blinds.done -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in -.animate-blinds.done .expanded.item, -.animate-blinds.done -.animate-fade-slide-in-right .expanded .item, -.animate-fade-slide-in-right .expanded -.animate-blinds.done .item, .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .animate-blinds.expanded.item .item, -.animate-blinds.done -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right -.animate-blinds.done .expanded.item, -.animate-blinds.done -.animate-ripple .expanded .item, -.animate-ripple .expanded -.animate-blinds.done .item, .animate-ripple .expanded .animate-blinds.item .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .item, -.animate-blinds.done -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-blinds.done .card.card-comment, -.animate-fade-slide-in -.animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple -.animate-fade-slide-in .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-fade-slide-in-right -.animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple -.animate-fade-slide-in-right .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-blinds.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .card.card-comment { +.animate-blinds.done .in, .animate-fade-slide-in .expanded .animate-blinds.item .in, .animate-fade-slide-in .animate-blinds.expanded.item .in, .animate-fade-slide-in-right .expanded .animate-blinds.item .in, .animate-fade-slide-in-right .animate-blinds.expanded.item .in, .animate-ripple .expanded .animate-blinds.item .in, .animate-ripple .animate-blinds.expanded.item .in, .card-avatar-small.expanded .animate-blinds.item .in, .card-avatar-small .expanded .animate-blinds.item .in, .card-avatar-small.expanded .animate-blinds.card.card-comment .in, .card-avatar-small .expanded .animate-blinds.card.card-comment .in, .animate-blinds.done .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds.done .item, .animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .animate-blinds.expanded.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-blinds.expanded.item .item, .animate-fade-slide-in .animate-fade-slide-in-right .animate-blinds.expanded.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .animate-ripple .expanded .animate-blinds.item .item, .animate-ripple .animate-fade-slide-in .animate-blinds.expanded.item .item, .animate-fade-slide-in .animate-ripple .animate-blinds.expanded.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.card.card-comment .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-blinds.card.card-comment .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.card.card-comment .item, +.animate-blinds.done .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-blinds.done .expanded.item, +.animate-fade-slide-in .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in .animate-blinds.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-blinds.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in-right .animate-blinds.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .animate-blinds.expanded.item .expanded.item, +.animate-ripple .expanded .animate-blinds.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .expanded .animate-blinds.item .expanded.item, +.animate-ripple .animate-blinds.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .animate-blinds.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.item .expanded.item, +.card-avatar-small .expanded .animate-blinds.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-blinds.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.card.card-comment .expanded.item, +.animate-blinds.done .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-blinds.done .item, +.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-blinds.item .item, +.animate-fade-slide-in .animate-fade-slide-in-right .animate-blinds.expanded.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-blinds.expanded.item .item, +.animate-fade-slide-in-right .expanded .animate-blinds.item .item, +.animate-fade-slide-in-right .animate-blinds.expanded.item .item, +.animate-ripple .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-blinds.item .item, +.animate-ripple .animate-fade-slide-in-right .animate-blinds.expanded.item .item, .animate-fade-slide-in-right .animate-ripple .animate-blinds.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.item .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.card.card-comment .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-blinds.card.card-comment .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.card.card-comment .item, +.animate-blinds.done .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-blinds.done .expanded.item, +.animate-fade-slide-in .expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in .animate-blinds.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-blinds.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in-right .animate-blinds.expanded.item .expanded.item, +.animate-ripple .expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-blinds.item .expanded.item, +.animate-ripple .animate-blinds.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .animate-blinds.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.item .expanded.item, +.card-avatar-small .expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-blinds.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.card.card-comment .expanded.item, +.animate-blinds.done .animate-ripple .expanded .item, .animate-ripple .expanded .animate-blinds.done .item, +.animate-fade-slide-in .animate-ripple .expanded .animate-blinds.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-blinds.item .item, +.animate-fade-slide-in .animate-ripple .animate-blinds.expanded.item .item, .animate-ripple .animate-fade-slide-in .animate-blinds.expanded.item .item, +.animate-fade-slide-in-right .animate-ripple .expanded .animate-blinds.item .item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-blinds.item .item, +.animate-fade-slide-in-right .animate-ripple .animate-blinds.expanded.item .item, .animate-ripple .animate-fade-slide-in-right .animate-blinds.expanded.item .item, +.animate-ripple .expanded .animate-blinds.item .item, +.animate-ripple .animate-blinds.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-blinds.item .item, +.card-avatar-small .animate-ripple .expanded .animate-blinds.item .item, .animate-ripple .card-avatar-small .expanded .animate-blinds.item .item, +.animate-ripple .card-avatar-small.expanded .animate-blinds.card.card-comment .item, +.card-avatar-small .animate-ripple .expanded .animate-blinds.card.card-comment .item, .animate-ripple .card-avatar-small .expanded .animate-blinds.card.card-comment .item, +.animate-blinds.done .animate-ripple .expanded.item, .animate-ripple .animate-blinds.done .expanded.item, +.animate-fade-slide-in .expanded .animate-blinds.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in .animate-blinds.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .animate-blinds.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-blinds.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in-right .animate-blinds.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .animate-blinds.expanded.item .expanded.item, +.animate-ripple .expanded .animate-blinds.item .expanded.item, +.animate-ripple .animate-blinds.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-blinds.item .expanded.item, +.card-avatar-small .expanded .animate-blinds.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-blinds.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-blinds.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-blinds.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-blinds.card.card-comment .expanded.item, +.animate-blinds.done .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-blinds.done .item, +.animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.item .item, +.animate-fade-slide-in .animate-blinds.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in .animate-blinds.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.item .item, +.animate-fade-slide-in-right .animate-blinds.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-blinds.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-blinds.item .item, +.animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-ripple .animate-blinds.expanded.item .item, +.card-avatar-small.expanded .animate-blinds.item .item, +.card-avatar-small.expanded .expanded .animate-blinds.item .item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .item, +.card-avatar-small.expanded .expanded .animate-blinds.card.card-comment .item, +.animate-blinds.done .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-blinds.done .item, +.animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-blinds.item .item, +.animate-fade-slide-in .card-avatar-small .animate-blinds.expanded.item .item, .card-avatar-small .animate-fade-slide-in .animate-blinds.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.item .item, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-blinds.item .item, +.animate-fade-slide-in-right .card-avatar-small .animate-blinds.expanded.item .item, .card-avatar-small .animate-fade-slide-in-right .animate-blinds.expanded.item .item, +.animate-ripple .card-avatar-small .expanded .animate-blinds.item .item, .card-avatar-small .animate-ripple .expanded .animate-blinds.item .item, +.animate-ripple .card-avatar-small .animate-blinds.expanded.item .item, .card-avatar-small .animate-ripple .animate-blinds.expanded.item .item, +.card-avatar-small.expanded .animate-blinds.item .expanded .item, .card-avatar-small.expanded .expanded .animate-blinds.item .item, +.card-avatar-small .expanded .animate-blinds.item .item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .expanded .item, .card-avatar-small.expanded .expanded .animate-blinds.card.card-comment .item, +.card-avatar-small .expanded .animate-blinds.card.card-comment .item, +.animate-blinds.done .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-blinds.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.item .card.card-comment, +.animate-fade-slide-in .animate-blinds.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .animate-blinds.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.item .card.card-comment, +.animate-fade-slide-in-right .animate-blinds.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-blinds.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small.expanded .animate-blinds.item .card.card-comment, +.animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .animate-blinds.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-blinds.item .card.card-comment, +.card-avatar-small.expanded .expanded .animate-blinds.item .card.card-comment, +.card-avatar-small.expanded .animate-blinds.card.card-comment .card.card-comment, +.card-avatar-small.expanded .expanded .animate-blinds.card.card-comment .card.card-comment, +.animate-blinds.done .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-blinds.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .expanded .animate-blinds.item .card.card-comment, +.animate-fade-slide-in .card-avatar-small .animate-blinds.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .animate-blinds.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-blinds.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .animate-blinds.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .animate-blinds.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small .expanded .animate-blinds.item .card.card-comment, .card-avatar-small .animate-ripple .expanded .animate-blinds.item .card.card-comment, +.animate-ripple .card-avatar-small .animate-blinds.expanded.item .card.card-comment, .card-avatar-small .animate-ripple .animate-blinds.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-blinds.item .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-blinds.item .card.card-comment, +.card-avatar-small .expanded .animate-blinds.item .card.card-comment, +.card-avatar-small.expanded .animate-blinds.card.card-comment .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-blinds.card.card-comment .card.card-comment, +.card-avatar-small .expanded .animate-blinds.card.card-comment .card.card-comment, .animate-blinds.done .in, .animate-fade-slide-in .expanded .animate-blinds.item .in, .animate-fade-slide-in .animate-blinds.expanded.item .in, .animate-fade-slide-in-right .expanded .animate-blinds.item .in, .animate-fade-slide-in-right .animate-blinds.expanded.item .in, .animate-ripple .expanded .animate-blinds.item .in, .animate-ripple .animate-blinds.expanded.item .in, .card-avatar-small.expanded .animate-blinds.item .in, .card-avatar-small .expanded .animate-blinds.item .in, .card-avatar-small.expanded .animate-blinds.card.card-comment .in, .card-avatar-small .expanded .animate-blinds.card.card-comment .in, .animate-blinds.done .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-blinds.done .item, .animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .animate-blinds.expanded.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-blinds.expanded.item .item, .animate-fade-slide-in .animate-fade-slide-in-right .animate-blinds.expanded.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .animate-ripple .expanded .animate-blinds.item .item, .animate-ripple .animate-fade-slide-in .animate-blinds.expanded.item .item, .animate-fade-slide-in .animate-ripple .animate-blinds.expanded.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-blinds.item .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.card.card-comment .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-blinds.card.card-comment .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.card.card-comment .item, +.animate-blinds.done .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-blinds.done .expanded.item, +.animate-fade-slide-in .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in .animate-blinds.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-blinds.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in-right .animate-blinds.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .animate-blinds.expanded.item .expanded.item, +.animate-ripple .expanded .animate-blinds.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .expanded .animate-blinds.item .expanded.item, +.animate-ripple .animate-blinds.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .animate-blinds.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.item .expanded.item, +.card-avatar-small .expanded .animate-blinds.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-blinds.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.card.card-comment .expanded.item, +.animate-blinds.done .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-blinds.done .item, +.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-blinds.item .item, +.animate-fade-slide-in .animate-fade-slide-in-right .animate-blinds.expanded.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-blinds.expanded.item .item, +.animate-fade-slide-in-right .expanded .animate-blinds.item .item, +.animate-fade-slide-in-right .animate-blinds.expanded.item .item, +.animate-ripple .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-blinds.item .item, +.animate-ripple .animate-fade-slide-in-right .animate-blinds.expanded.item .item, .animate-fade-slide-in-right .animate-ripple .animate-blinds.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.item .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-blinds.item .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.card.card-comment .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-blinds.card.card-comment .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.card.card-comment .item, +.animate-blinds.done .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-blinds.done .expanded.item, +.animate-fade-slide-in .expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in .animate-blinds.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-blinds.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in-right .animate-blinds.expanded.item .expanded.item, +.animate-ripple .expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-blinds.item .expanded.item, +.animate-ripple .animate-blinds.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .animate-blinds.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.item .expanded.item, +.card-avatar-small .expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-blinds.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.card.card-comment .expanded.item, +.animate-blinds.done .animate-ripple .expanded .item, .animate-ripple .expanded .animate-blinds.done .item, +.animate-fade-slide-in .animate-ripple .expanded .animate-blinds.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-blinds.item .item, +.animate-fade-slide-in .animate-ripple .animate-blinds.expanded.item .item, .animate-ripple .animate-fade-slide-in .animate-blinds.expanded.item .item, +.animate-fade-slide-in-right .animate-ripple .expanded .animate-blinds.item .item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-blinds.item .item, +.animate-fade-slide-in-right .animate-ripple .animate-blinds.expanded.item .item, .animate-ripple .animate-fade-slide-in-right .animate-blinds.expanded.item .item, +.animate-ripple .expanded .animate-blinds.item .item, +.animate-ripple .animate-blinds.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-blinds.item .item, +.card-avatar-small .animate-ripple .expanded .animate-blinds.item .item, .animate-ripple .card-avatar-small .expanded .animate-blinds.item .item, +.animate-ripple .card-avatar-small.expanded .animate-blinds.card.card-comment .item, +.card-avatar-small .animate-ripple .expanded .animate-blinds.card.card-comment .item, .animate-ripple .card-avatar-small .expanded .animate-blinds.card.card-comment .item, +.animate-blinds.done .animate-ripple .expanded.item, .animate-ripple .animate-blinds.done .expanded.item, +.animate-fade-slide-in .expanded .animate-blinds.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in .animate-blinds.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .animate-blinds.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-blinds.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-blinds.item .expanded.item, +.animate-fade-slide-in-right .animate-blinds.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .animate-blinds.expanded.item .expanded.item, +.animate-ripple .expanded .animate-blinds.item .expanded.item, +.animate-ripple .animate-blinds.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-blinds.item .expanded.item, +.card-avatar-small .expanded .animate-blinds.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-blinds.item .expanded.item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-blinds.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-blinds.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-blinds.card.card-comment .expanded.item, +.animate-blinds.done .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-blinds.done .item, +.animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.item .item, +.animate-fade-slide-in .animate-blinds.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in .animate-blinds.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.item .item, +.animate-fade-slide-in-right .animate-blinds.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-blinds.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-blinds.item .item, +.animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-ripple .animate-blinds.expanded.item .item, +.card-avatar-small.expanded .animate-blinds.item .item, +.card-avatar-small.expanded .expanded .animate-blinds.item .item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .item, +.card-avatar-small.expanded .expanded .animate-blinds.card.card-comment .item, +.animate-blinds.done .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-blinds.done .item, +.animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-blinds.item .item, +.animate-fade-slide-in .card-avatar-small .animate-blinds.expanded.item .item, .card-avatar-small .animate-fade-slide-in .animate-blinds.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.item .item, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-blinds.item .item, +.animate-fade-slide-in-right .card-avatar-small .animate-blinds.expanded.item .item, .card-avatar-small .animate-fade-slide-in-right .animate-blinds.expanded.item .item, +.animate-ripple .card-avatar-small .expanded .animate-blinds.item .item, .card-avatar-small .animate-ripple .expanded .animate-blinds.item .item, +.animate-ripple .card-avatar-small .animate-blinds.expanded.item .item, .card-avatar-small .animate-ripple .animate-blinds.expanded.item .item, +.card-avatar-small.expanded .animate-blinds.item .expanded .item, .card-avatar-small.expanded .expanded .animate-blinds.item .item, +.card-avatar-small .expanded .animate-blinds.item .item, +.card-avatar-small.expanded .animate-blinds.card.card-comment .expanded .item, .card-avatar-small.expanded .expanded .animate-blinds.card.card-comment .item, +.card-avatar-small .expanded .animate-blinds.card.card-comment .item, +.animate-blinds.done .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-blinds.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.item .card.card-comment, +.animate-fade-slide-in .animate-blinds.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .animate-blinds.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.item .card.card-comment, +.animate-fade-slide-in-right .animate-blinds.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-blinds.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small.expanded .animate-blinds.item .card.card-comment, +.animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .animate-blinds.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-blinds.item .card.card-comment, +.card-avatar-small.expanded .expanded .animate-blinds.item .card.card-comment, +.card-avatar-small.expanded .animate-blinds.card.card-comment .card.card-comment, +.card-avatar-small.expanded .expanded .animate-blinds.card.card-comment .card.card-comment, +.animate-blinds.done .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-blinds.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .expanded .animate-blinds.item .card.card-comment, +.animate-fade-slide-in .card-avatar-small .animate-blinds.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .animate-blinds.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-blinds.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .animate-blinds.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .animate-blinds.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small .expanded .animate-blinds.item .card.card-comment, .card-avatar-small .animate-ripple .expanded .animate-blinds.item .card.card-comment, +.animate-ripple .card-avatar-small .animate-blinds.expanded.item .card.card-comment, .card-avatar-small .animate-ripple .animate-blinds.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-blinds.item .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-blinds.item .card.card-comment, +.card-avatar-small .expanded .animate-blinds.item .card.card-comment, +.card-avatar-small.expanded .animate-blinds.card.card-comment .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-blinds.card.card-comment .card.card-comment, +.card-avatar-small .expanded .animate-blinds.card.card-comment .card.card-comment { opacity: 1; filter: alpha(opacity=100); } @@ -11731,18 +11958,7 @@ a.button { -webkit-transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out; } -.animate-blinds.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-blinds.item .has-mask-reverse:after, -.animate-fade-slide-in .animate-blinds.expanded.item .has-mask-reverse:after, -.animate-fade-slide-in-right .expanded .animate-blinds.item .has-mask-reverse:after, -.animate-fade-slide-in-right .animate-blinds.expanded.item .has-mask-reverse:after, -.animate-ripple .expanded .animate-blinds.item .has-mask-reverse:after, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .has-mask-reverse:after, -.animate-blinds.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-blinds.item .has-mask-reverse:after, -.animate-fade-slide-in .animate-blinds.expanded.item .has-mask-reverse:after, -.animate-fade-slide-in-right .expanded .animate-blinds.item .has-mask-reverse:after, -.animate-fade-slide-in-right .animate-blinds.expanded.item .has-mask-reverse:after, -.animate-ripple .expanded .animate-blinds.item .has-mask-reverse:after, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .has-mask-reverse:after { +.animate-blinds.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-blinds.item .has-mask-reverse:after, .animate-fade-slide-in .animate-blinds.expanded.item .has-mask-reverse:after, .animate-fade-slide-in-right .expanded .animate-blinds.item .has-mask-reverse:after, .animate-fade-slide-in-right .animate-blinds.expanded.item .has-mask-reverse:after, .animate-ripple .expanded .animate-blinds.item .has-mask-reverse:after, .animate-ripple .animate-blinds.expanded.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-blinds.item .has-mask-reverse:after, .card-avatar-small .expanded .animate-blinds.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-blinds.card.card-comment .has-mask-reverse:after, .card-avatar-small .expanded .animate-blinds.card.card-comment .has-mask-reverse:after, .animate-blinds.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-blinds.item .has-mask-reverse:after, .animate-fade-slide-in .animate-blinds.expanded.item .has-mask-reverse:after, .animate-fade-slide-in-right .expanded .animate-blinds.item .has-mask-reverse:after, .animate-fade-slide-in-right .animate-blinds.expanded.item .has-mask-reverse:after, .animate-ripple .expanded .animate-blinds.item .has-mask-reverse:after, .animate-ripple .animate-blinds.expanded.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-blinds.item .has-mask-reverse:after, .card-avatar-small .expanded .animate-blinds.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-blinds.card.card-comment .has-mask-reverse:after, .card-avatar-small .expanded .animate-blinds.card.card-comment .has-mask-reverse:after { opacity: 1; filter: alpha(opacity=100); } @@ -11760,44 +11976,26 @@ a.button { /* Motion: Ripple ==================================*/ -.animate-ripple .done, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .done, .animate-fade-slide-in .expanded -.animate-ripple .item, -.animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in -.animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded -.animate-ripple .item, -.animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right -.animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment { +.animate-ripple .done, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment, .animate-ripple .done, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment { visibility: hidden; } -.animate-ripple .done, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .done, .animate-fade-slide-in .expanded -.animate-ripple .item, -.animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in -.animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded -.animate-ripple .item, -.animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right -.animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment { +.animate-ripple .done, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment, .animate-ripple .done, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment { -ms-transform: scale3d(0.8, 0, 1); -webkit-transform: scale3d(0.8, 0, 1); transform: scale3d(0.8, 0, 1); @@ -11811,66 +12009,64 @@ a.button { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } -.animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, +.animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, .animate-fade-slide-in .animate-ripple.expanded.item, .animate-fade-slide-in-right .expanded .animate-ripple.item, .animate-fade-slide-in-right .animate-ripple.expanded.item, .animate-ripple .expanded .animate-ripple.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment, -.animate-ripple .in, .animate-fade-slide-in .expanded -.animate-ripple .item, -.animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in -.animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded -.animate-ripple .item, -.animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right -.animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, +.animate-ripple .animate-ripple.expanded.item, +.card-avatar-small.expanded .animate-ripple.item, +.card-avatar-small .expanded .animate-ripple.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment, +.card-avatar-small .expanded .animate-ripple.card.card-comment, .animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, .animate-fade-slide-in .animate-ripple.expanded.item, .animate-fade-slide-in-right .expanded .animate-ripple.item, .animate-fade-slide-in-right .animate-ripple.expanded.item, .animate-ripple .expanded .animate-ripple.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment { +.animate-ripple .animate-ripple.expanded.item, +.card-avatar-small.expanded .animate-ripple.item, +.card-avatar-small .expanded .animate-ripple.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment, +.card-avatar-small .expanded .animate-ripple.card.card-comment { -ms-transform: scale3d(1, 1, 1); -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } -.animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, +.animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, .animate-fade-slide-in .animate-ripple.expanded.item, .animate-fade-slide-in-right .expanded .animate-ripple.item, .animate-fade-slide-in-right .animate-ripple.expanded.item, .animate-ripple .expanded .animate-ripple.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment, -.animate-ripple .in, .animate-fade-slide-in .expanded -.animate-ripple .item, -.animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in -.animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded -.animate-ripple .item, -.animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right -.animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, +.animate-ripple .animate-ripple.expanded.item, +.card-avatar-small.expanded .animate-ripple.item, +.card-avatar-small .expanded .animate-ripple.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment, +.card-avatar-small .expanded .animate-ripple.card.card-comment, .animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, .animate-fade-slide-in .animate-ripple.expanded.item, .animate-fade-slide-in-right .expanded .animate-ripple.item, .animate-fade-slide-in-right .animate-ripple.expanded.item, .animate-ripple .expanded .animate-ripple.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment { +.animate-ripple .animate-ripple.expanded.item, +.card-avatar-small.expanded .animate-ripple.item, +.card-avatar-small .expanded .animate-ripple.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment, +.card-avatar-small .expanded .animate-ripple.card.card-comment { visibility: visible; } .animate-ripple .item { @@ -11880,41 +12076,30 @@ a.button { opacity: 0; filter: alpha(opacity=0); } -.animate-ripple .item.in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in .item.expanded, -.animate-fade-slide-in .animate-ripple .item.expanded, -.animate-fade-slide-in-right .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in-right .item.expanded, -.animate-fade-slide-in-right .animate-ripple .item.expanded, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .item.card.card-comment { +.animate-ripple .item.in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .item.expanded, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .item.card.card-comment, +.animate-ripple .card-avatar-small .expanded .item.card.card-comment { opacity: 1; filter: alpha(opacity=100); } -.animate-ripple .done, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment { +.animate-ripple .done, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment { visibility: hidden; } -.animate-ripple .done, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .done, .animate-fade-slide-in .expanded -.animate-ripple .item, -.animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in -.animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded -.animate-ripple .item, -.animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right -.animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment { +.animate-ripple .done, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment, .animate-ripple .done, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment { -ms-transform: scale3d(0.8, 0, 1); -webkit-transform: scale3d(0.8, 0, 1); transform: scale3d(0.8, 0, 1); @@ -11964,81 +12149,267 @@ a.button { opacity: 0.6; } */ -.animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, +.animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, .animate-fade-slide-in .animate-ripple.expanded.item, .animate-fade-slide-in-right .expanded .animate-ripple.item, .animate-fade-slide-in-right .animate-ripple.expanded.item, .animate-ripple .expanded .animate-ripple.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment, .animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, +.animate-ripple .animate-ripple.expanded.item, +.card-avatar-small.expanded .animate-ripple.item, +.card-avatar-small .expanded .animate-ripple.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment, +.card-avatar-small .expanded .animate-ripple.card.card-comment, .animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, .animate-fade-slide-in .animate-ripple.expanded.item, .animate-fade-slide-in-right .expanded .animate-ripple.item, .animate-fade-slide-in-right .animate-ripple.expanded.item, .animate-ripple .expanded .animate-ripple.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment { +.animate-ripple .animate-ripple.expanded.item, +.card-avatar-small.expanded .animate-ripple.item, +.card-avatar-small .expanded .animate-ripple.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment, +.card-avatar-small .expanded .animate-ripple.card.card-comment { -ms-transform: scale3d(1, 1, 1); -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); -webkit-transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out; } -.animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, +.animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, .animate-fade-slide-in .animate-ripple.expanded.item, .animate-fade-slide-in-right .expanded .animate-ripple.item, .animate-fade-slide-in-right .animate-ripple.expanded.item, .animate-ripple .expanded .animate-ripple.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment, .animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple .item, .animate-ripple -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple .expanded.item, .animate-ripple .expanded .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, +.animate-ripple .animate-ripple.expanded.item, +.card-avatar-small.expanded .animate-ripple.item, +.card-avatar-small .expanded .animate-ripple.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment, +.card-avatar-small .expanded .animate-ripple.card.card-comment, .animate-ripple .in, .animate-fade-slide-in .expanded .animate-ripple .item, .animate-fade-slide-in-right .expanded .animate-ripple .item, +.animate-ripple .expanded .item, +.animate-ripple .expanded.item, .card-avatar-small.expanded .animate-ripple .item, .card-avatar-small .expanded .animate-ripple .item, +.animate-ripple .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .card.card-comment, +.animate-ripple .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple .card.card-comment, .animate-ripple.done, .animate-fade-slide-in .expanded .animate-ripple.item, .animate-fade-slide-in .animate-ripple.expanded.item, .animate-fade-slide-in-right .expanded .animate-ripple.item, .animate-fade-slide-in-right .animate-ripple.expanded.item, .animate-ripple .expanded .animate-ripple.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment { +.animate-ripple .animate-ripple.expanded.item, +.card-avatar-small.expanded .animate-ripple.item, +.card-avatar-small .expanded .animate-ripple.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment, +.card-avatar-small .expanded .animate-ripple.card.card-comment { visibility: visible; } -.animate-ripple.done .in, .animate-fade-slide-in .expanded .animate-ripple.item .in, -.animate-fade-slide-in .animate-ripple.expanded.item .in, -.animate-fade-slide-in-right .expanded .animate-ripple.item .in, -.animate-fade-slide-in-right .animate-ripple.expanded.item .in, -.animate-ripple .expanded .animate-ripple.item .in, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .in, .animate-fade-slide-in .expanded .animate-ripple.done .item, .animate-fade-slide-in .expanded .animate-ripple.item .item, .animate-fade-slide-in .animate-ripple.expanded.item .item, .animate-ripple.done -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple.done .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple.done .item, .animate-fade-slide-in-right .expanded .animate-ripple.item .item, .animate-fade-slide-in-right .animate-ripple.expanded.item .item, .animate-ripple.done -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple.done .expanded.item, .animate-ripple.done .expanded .item, .animate-ripple .expanded .animate-ripple.item .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .item, .animate-ripple.done .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-fade-slide-in .animate-ripple.expanded.item .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-fade-slide-in-right .animate-ripple.expanded.item .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-ripple.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .card.card-comment, .animate-ripple.done .in, .animate-fade-slide-in .expanded .animate-ripple.item .in, -.animate-fade-slide-in .animate-ripple.expanded.item .in, -.animate-fade-slide-in-right .expanded .animate-ripple.item .in, -.animate-fade-slide-in-right .animate-ripple.expanded.item .in, -.animate-ripple .expanded .animate-ripple.item .in, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .in, .animate-fade-slide-in .expanded .animate-ripple.done .item, .animate-fade-slide-in .expanded .animate-ripple.item .item, .animate-fade-slide-in .animate-ripple.expanded.item .item, .animate-ripple.done -.animate-fade-slide-in .expanded.item, -.animate-fade-slide-in .animate-ripple.done .expanded.item, -.animate-fade-slide-in-right .expanded .animate-ripple.done .item, .animate-fade-slide-in-right .expanded .animate-ripple.item .item, .animate-fade-slide-in-right .animate-ripple.expanded.item .item, .animate-ripple.done -.animate-fade-slide-in-right .expanded.item, -.animate-fade-slide-in-right .animate-ripple.done .expanded.item, .animate-ripple.done .expanded .item, .animate-ripple .expanded .animate-ripple.item .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .item, .animate-ripple.done .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-fade-slide-in .animate-ripple.expanded.item .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-fade-slide-in-right .animate-ripple.expanded.item .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-ripple.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .card.card-comment { +.animate-ripple.done .in, .animate-fade-slide-in .expanded .animate-ripple.item .in, .animate-fade-slide-in .animate-ripple.expanded.item .in, .animate-fade-slide-in-right .expanded .animate-ripple.item .in, .animate-fade-slide-in-right .animate-ripple.expanded.item .in, .animate-ripple .expanded .animate-ripple.item .in, .animate-ripple .animate-ripple.expanded.item .in, .card-avatar-small.expanded .animate-ripple.item .in, .card-avatar-small .expanded .animate-ripple.item .in, .card-avatar-small.expanded .animate-ripple.card.card-comment .in, .card-avatar-small .expanded .animate-ripple.card.card-comment .in, .animate-ripple.done .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-ripple.done .item, .animate-fade-slide-in .expanded .animate-ripple.item .item, .animate-fade-slide-in .animate-ripple.expanded.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-ripple.item .item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-ripple.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-ripple.expanded.item .item, .animate-fade-slide-in .animate-fade-slide-in-right .animate-ripple.expanded.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-ripple.item .item, .animate-fade-slide-in .animate-ripple .expanded .animate-ripple.item .item, .animate-fade-slide-in .animate-ripple.expanded.item .animate-ripple.expanded.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-ripple.item .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.card.card-comment .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-ripple.card.card-comment .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.card.card-comment .item, +.animate-ripple.done .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple.done .expanded.item, +.animate-fade-slide-in .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in .animate-ripple.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-ripple.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .animate-ripple.expanded.item .expanded.item, +.animate-ripple .expanded .animate-ripple.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .expanded .animate-ripple.item .expanded.item, +.animate-ripple .animate-ripple.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .animate-ripple.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.item .expanded.item, +.card-avatar-small .expanded .animate-ripple.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-ripple.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.card.card-comment .expanded.item, +.animate-ripple.done .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-ripple.done .item, +.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-ripple.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-ripple.item .item, +.animate-fade-slide-in .animate-fade-slide-in-right .animate-ripple.expanded.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-ripple.expanded.item .item, +.animate-fade-slide-in-right .expanded .animate-ripple.item .item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .item, +.animate-ripple .animate-fade-slide-in-right .expanded .animate-ripple.item .item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-ripple.item .item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .animate-ripple.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.item .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-ripple.item .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.card.card-comment .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-ripple.card.card-comment .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.card.card-comment .item, +.animate-ripple.done .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple.done .expanded.item, +.animate-fade-slide-in .expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in .animate-ripple.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-ripple.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .expanded.item, +.animate-ripple .expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-ripple.item .expanded.item, +.animate-ripple .animate-ripple.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .animate-ripple.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.item .expanded.item, +.card-avatar-small .expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-ripple.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.card.card-comment .expanded.item, +.animate-ripple.done .expanded .item, +.animate-fade-slide-in .expanded .animate-ripple.item .expanded .item, +.animate-fade-slide-in .animate-ripple.expanded.item .expanded .item, +.animate-fade-slide-in-right .expanded .animate-ripple.item .expanded .item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .expanded .item, +.animate-ripple .expanded .animate-ripple.item .item, +.animate-ripple .animate-ripple.expanded.item .item, +.card-avatar-small.expanded .animate-ripple.item .expanded .item, +.card-avatar-small .expanded .animate-ripple.item .expanded .item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .expanded .item, +.card-avatar-small .expanded .animate-ripple.card.card-comment .expanded .item, +.animate-ripple.done .expanded.item, +.animate-fade-slide-in .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in .animate-ripple.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .expanded.item, +.animate-ripple.item .expanded .animate-ripple.item .expanded.item, +.animate-ripple.expanded.item .animate-ripple.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.item .expanded.item, +.card-avatar-small .expanded .animate-ripple.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-ripple.card.card-comment .expanded.item, +.animate-ripple.done .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-ripple.done .item, +.animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.item .item, +.animate-fade-slide-in .animate-ripple.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in .animate-ripple.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.item .item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-ripple.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-ripple.item .item, +.animate-ripple .animate-ripple.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-ripple .animate-ripple.expanded.item .item, +.card-avatar-small.expanded .animate-ripple.item .item, +.card-avatar-small.expanded .expanded .animate-ripple.item .item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .item, +.card-avatar-small.expanded .expanded .animate-ripple.card.card-comment .item, +.animate-ripple.done .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-ripple.done .item, +.animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-ripple.item .item, +.animate-fade-slide-in .card-avatar-small .animate-ripple.expanded.item .item, .card-avatar-small .animate-fade-slide-in .animate-ripple.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.item .item, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-ripple.item .item, +.animate-fade-slide-in-right .card-avatar-small .animate-ripple.expanded.item .item, .card-avatar-small .animate-fade-slide-in-right .animate-ripple.expanded.item .item, +.animate-ripple .card-avatar-small .expanded .animate-ripple.item .item, .card-avatar-small .animate-ripple .expanded .animate-ripple.item .item, +.card-avatar-small .animate-ripple.expanded.item .animate-ripple.expanded.item .item, +.card-avatar-small.expanded .animate-ripple.item .expanded .item, .card-avatar-small.expanded .expanded .animate-ripple.item .item, +.card-avatar-small .expanded .animate-ripple.item .item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .expanded .item, .card-avatar-small.expanded .expanded .animate-ripple.card.card-comment .item, +.card-avatar-small .expanded .animate-ripple.card.card-comment .item, +.animate-ripple.done .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.item .card.card-comment, +.animate-fade-slide-in .animate-ripple.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .animate-ripple.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.item .card.card-comment, +.animate-fade-slide-in-right .animate-ripple.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-ripple.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small.expanded .animate-ripple.item .card.card-comment, +.animate-ripple .animate-ripple.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .animate-ripple.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-ripple.item .card.card-comment, +.card-avatar-small.expanded .expanded .animate-ripple.item .card.card-comment, +.card-avatar-small.expanded .animate-ripple.card.card-comment .card.card-comment, +.card-avatar-small.expanded .expanded .animate-ripple.card.card-comment .card.card-comment, +.animate-ripple.done .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .expanded .animate-ripple.item .card.card-comment, +.animate-fade-slide-in .card-avatar-small .animate-ripple.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .animate-ripple.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-ripple.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .animate-ripple.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .animate-ripple.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small .expanded .animate-ripple.item .card.card-comment, .card-avatar-small .animate-ripple .expanded .animate-ripple.item .card.card-comment, +.card-avatar-small .animate-ripple.expanded.item .animate-ripple.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-ripple.item .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-ripple.item .card.card-comment, +.card-avatar-small .expanded .animate-ripple.item .card.card-comment, +.card-avatar-small.expanded .animate-ripple.card.card-comment .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-ripple.card.card-comment .card.card-comment, +.card-avatar-small .expanded .animate-ripple.card.card-comment .card.card-comment, .animate-ripple.done .in, .animate-fade-slide-in .expanded .animate-ripple.item .in, .animate-fade-slide-in .animate-ripple.expanded.item .in, .animate-fade-slide-in-right .expanded .animate-ripple.item .in, .animate-fade-slide-in-right .animate-ripple.expanded.item .in, .animate-ripple .expanded .animate-ripple.item .in, .animate-ripple .animate-ripple.expanded.item .in, .card-avatar-small.expanded .animate-ripple.item .in, .card-avatar-small .expanded .animate-ripple.item .in, .card-avatar-small.expanded .animate-ripple.card.card-comment .in, .card-avatar-small .expanded .animate-ripple.card.card-comment .in, .animate-ripple.done .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-ripple.done .item, .animate-fade-slide-in .expanded .animate-ripple.item .item, .animate-fade-slide-in .animate-ripple.expanded.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-ripple.item .item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-ripple.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-ripple.expanded.item .item, .animate-fade-slide-in .animate-fade-slide-in-right .animate-ripple.expanded.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-ripple.item .item, .animate-fade-slide-in .animate-ripple .expanded .animate-ripple.item .item, .animate-fade-slide-in .animate-ripple.expanded.item .animate-ripple.expanded.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-ripple.item .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.card.card-comment .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-ripple.card.card-comment .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.card.card-comment .item, +.animate-ripple.done .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple.done .expanded.item, +.animate-fade-slide-in .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in .animate-ripple.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-ripple.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .animate-ripple.expanded.item .expanded.item, +.animate-ripple .expanded .animate-ripple.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .expanded .animate-ripple.item .expanded.item, +.animate-ripple .animate-ripple.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .animate-ripple.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.item .expanded.item, +.card-avatar-small .expanded .animate-ripple.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-ripple.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.card.card-comment .expanded.item, +.animate-ripple.done .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-ripple.done .item, +.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-ripple.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-ripple.item .item, +.animate-fade-slide-in .animate-fade-slide-in-right .animate-ripple.expanded.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-ripple.expanded.item .item, +.animate-fade-slide-in-right .expanded .animate-ripple.item .item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .item, +.animate-ripple .animate-fade-slide-in-right .expanded .animate-ripple.item .item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-ripple.item .item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .animate-ripple.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.item .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-ripple.item .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.card.card-comment .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-ripple.card.card-comment .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.card.card-comment .item, +.animate-ripple.done .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple.done .expanded.item, +.animate-fade-slide-in .expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in .animate-ripple.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-ripple.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .expanded.item, +.animate-ripple .expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-ripple.item .expanded.item, +.animate-ripple .animate-ripple.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .animate-ripple.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.item .expanded.item, +.card-avatar-small .expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-ripple.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.card.card-comment .expanded.item, +.animate-ripple.done .expanded .item, +.animate-fade-slide-in .expanded .animate-ripple.item .expanded .item, +.animate-fade-slide-in .animate-ripple.expanded.item .expanded .item, +.animate-fade-slide-in-right .expanded .animate-ripple.item .expanded .item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .expanded .item, +.animate-ripple .expanded .animate-ripple.item .item, +.animate-ripple .animate-ripple.expanded.item .item, +.card-avatar-small.expanded .animate-ripple.item .expanded .item, +.card-avatar-small .expanded .animate-ripple.item .expanded .item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .expanded .item, +.card-avatar-small .expanded .animate-ripple.card.card-comment .expanded .item, +.animate-ripple.done .expanded.item, +.animate-fade-slide-in .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in .animate-ripple.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-ripple.item .expanded.item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .expanded.item, +.animate-ripple.item .expanded .animate-ripple.item .expanded.item, +.animate-ripple.expanded.item .animate-ripple.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.item .expanded.item, +.card-avatar-small .expanded .animate-ripple.item .expanded.item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-ripple.card.card-comment .expanded.item, +.animate-ripple.done .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-ripple.done .item, +.animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.item .item, +.animate-fade-slide-in .animate-ripple.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in .animate-ripple.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.item .item, +.animate-fade-slide-in-right .animate-ripple.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-ripple.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-ripple.item .item, +.animate-ripple .animate-ripple.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-ripple .animate-ripple.expanded.item .item, +.card-avatar-small.expanded .animate-ripple.item .item, +.card-avatar-small.expanded .expanded .animate-ripple.item .item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .item, +.card-avatar-small.expanded .expanded .animate-ripple.card.card-comment .item, +.animate-ripple.done .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-ripple.done .item, +.animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-ripple.item .item, +.animate-fade-slide-in .card-avatar-small .animate-ripple.expanded.item .item, .card-avatar-small .animate-fade-slide-in .animate-ripple.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.item .item, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-ripple.item .item, +.animate-fade-slide-in-right .card-avatar-small .animate-ripple.expanded.item .item, .card-avatar-small .animate-fade-slide-in-right .animate-ripple.expanded.item .item, +.animate-ripple .card-avatar-small .expanded .animate-ripple.item .item, .card-avatar-small .animate-ripple .expanded .animate-ripple.item .item, +.card-avatar-small .animate-ripple.expanded.item .animate-ripple.expanded.item .item, +.card-avatar-small.expanded .animate-ripple.item .expanded .item, .card-avatar-small.expanded .expanded .animate-ripple.item .item, +.card-avatar-small .expanded .animate-ripple.item .item, +.card-avatar-small.expanded .animate-ripple.card.card-comment .expanded .item, .card-avatar-small.expanded .expanded .animate-ripple.card.card-comment .item, +.card-avatar-small .expanded .animate-ripple.card.card-comment .item, +.animate-ripple.done .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.item .card.card-comment, +.animate-fade-slide-in .animate-ripple.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .animate-ripple.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.item .card.card-comment, +.animate-fade-slide-in-right .animate-ripple.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-ripple.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small.expanded .animate-ripple.item .card.card-comment, +.animate-ripple .animate-ripple.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .animate-ripple.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-ripple.item .card.card-comment, +.card-avatar-small.expanded .expanded .animate-ripple.item .card.card-comment, +.card-avatar-small.expanded .animate-ripple.card.card-comment .card.card-comment, +.card-avatar-small.expanded .expanded .animate-ripple.card.card-comment .card.card-comment, +.animate-ripple.done .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-ripple.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .expanded .animate-ripple.item .card.card-comment, +.animate-fade-slide-in .card-avatar-small .animate-ripple.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .animate-ripple.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-ripple.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .animate-ripple.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .animate-ripple.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small .expanded .animate-ripple.item .card.card-comment, .card-avatar-small .animate-ripple .expanded .animate-ripple.item .card.card-comment, +.card-avatar-small .animate-ripple.expanded.item .animate-ripple.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-ripple.item .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-ripple.item .card.card-comment, +.card-avatar-small .expanded .animate-ripple.item .card.card-comment, +.card-avatar-small.expanded .animate-ripple.card.card-comment .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-ripple.card.card-comment .card.card-comment, +.card-avatar-small .expanded .animate-ripple.card.card-comment .card.card-comment { opacity: 1; filter: alpha(opacity=100); } @@ -12048,17 +12419,7 @@ a.button { -webkit-transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out; } -.animate-ripple.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-ripple.item .has-mask-reverse:after, -.animate-fade-slide-in .animate-ripple.expanded.item .has-mask-reverse:after, -.animate-fade-slide-in-right .expanded .animate-ripple.item .has-mask-reverse:after, -.animate-fade-slide-in-right .animate-ripple.expanded.item .has-mask-reverse:after, -.animate-ripple .expanded .animate-ripple.item .has-mask-reverse:after, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .has-mask-reverse:after, .animate-ripple.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-ripple.item .has-mask-reverse:after, -.animate-fade-slide-in .animate-ripple.expanded.item .has-mask-reverse:after, -.animate-fade-slide-in-right .expanded .animate-ripple.item .has-mask-reverse:after, -.animate-fade-slide-in-right .animate-ripple.expanded.item .has-mask-reverse:after, -.animate-ripple .expanded .animate-ripple.item .has-mask-reverse:after, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .has-mask-reverse:after { +.animate-ripple.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-ripple.item .has-mask-reverse:after, .animate-fade-slide-in .animate-ripple.expanded.item .has-mask-reverse:after, .animate-fade-slide-in-right .expanded .animate-ripple.item .has-mask-reverse:after, .animate-fade-slide-in-right .animate-ripple.expanded.item .has-mask-reverse:after, .animate-ripple .expanded .animate-ripple.item .has-mask-reverse:after, .animate-ripple .animate-ripple.expanded.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-ripple.item .has-mask-reverse:after, .card-avatar-small .expanded .animate-ripple.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-ripple.card.card-comment .has-mask-reverse:after, .card-avatar-small .expanded .animate-ripple.card.card-comment .has-mask-reverse:after, .animate-ripple.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-ripple.item .has-mask-reverse:after, .animate-fade-slide-in .animate-ripple.expanded.item .has-mask-reverse:after, .animate-fade-slide-in-right .expanded .animate-ripple.item .has-mask-reverse:after, .animate-fade-slide-in-right .animate-ripple.expanded.item .has-mask-reverse:after, .animate-ripple .expanded .animate-ripple.item .has-mask-reverse:after, .animate-ripple .animate-ripple.expanded.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-ripple.item .has-mask-reverse:after, .card-avatar-small .expanded .animate-ripple.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-ripple.card.card-comment .has-mask-reverse:after, .card-avatar-small .expanded .animate-ripple.card.card-comment .has-mask-reverse:after { opacity: 1; filter: alpha(opacity=100); } @@ -12088,62 +12449,68 @@ a.button { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } -.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded.item, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, -.animate-ripple .expanded .animate-fade-slide-in .item, .animate-fade-slide-in -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, -.animate-fade-slide-in.done .item, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, +.animate-fade-slide-in .expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, .animate-ripple .expanded .animate-fade-slide-in .item, .card-avatar-small.expanded .animate-fade-slide-in .item, .card-avatar-small .expanded .animate-fade-slide-in .item, +.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in.done .item, +.animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, .animate-ripple .expanded .animate-fade-slide-in.item .item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, -.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded.item, -.animate-fade-slide-in-right .expanded -.animate-fade-slide-in .item, -.animate-ripple .expanded -.animate-fade-slide-in .item, -.animate-fade-slide-in -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-fade-slide-in .card.card-comment, -.animate-fade-slide-in.done .item, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, +.animate-ripple .animate-fade-slide-in.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.item .item, +.card-avatar-small .expanded .animate-fade-slide-in.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, .animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, +.animate-fade-slide-in .expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, .animate-ripple .expanded .animate-fade-slide-in .item, .card-avatar-small.expanded .animate-fade-slide-in .item, .card-avatar-small .expanded .animate-fade-slide-in .item, +.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in.done .item, +.animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, .animate-ripple .expanded .animate-fade-slide-in.item .item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item { +.animate-ripple .animate-fade-slide-in.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.item .item, +.card-avatar-small .expanded .animate-fade-slide-in.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item { -ms-transform: translate3d(0, 0, 0); -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } -.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded.item, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, -.animate-ripple .expanded .animate-fade-slide-in .item, .animate-fade-slide-in -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, -.animate-fade-slide-in.done .item, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, +.animate-fade-slide-in .expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, .animate-ripple .expanded .animate-fade-slide-in .item, .card-avatar-small.expanded .animate-fade-slide-in .item, .card-avatar-small .expanded .animate-fade-slide-in .item, +.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in.done .item, +.animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, .animate-ripple .expanded .animate-fade-slide-in.item .item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, -.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded.item, -.animate-fade-slide-in-right .expanded -.animate-fade-slide-in .item, -.animate-ripple .expanded -.animate-fade-slide-in .item, -.animate-fade-slide-in -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-fade-slide-in .card.card-comment, -.animate-fade-slide-in.done .item, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, +.animate-ripple .animate-fade-slide-in.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.item .item, +.card-avatar-small .expanded .animate-fade-slide-in.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, .animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, +.animate-fade-slide-in .expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, .animate-ripple .expanded .animate-fade-slide-in .item, .card-avatar-small.expanded .animate-fade-slide-in .item, .card-avatar-small .expanded .animate-fade-slide-in .item, +.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in.done .item, +.animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, .animate-ripple .expanded .animate-fade-slide-in.item .item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item { +.animate-ripple .animate-fade-slide-in.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.item .item, +.card-avatar-small .expanded .animate-fade-slide-in.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item { visibility: visible; } .list .item.item-bg-image, @@ -12164,34 +12531,35 @@ a.button { opacity: 0; filter: alpha(opacity=0); } -.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded.item, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, -.animate-ripple .expanded .animate-fade-slide-in .item, .animate-fade-slide-in -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, +.animate-fade-slide-in .expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, .animate-ripple .expanded .animate-fade-slide-in .item, .card-avatar-small.expanded .animate-fade-slide-in .item, .card-avatar-small .expanded .animate-fade-slide-in .item, +.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, .animate-fade-slide-in.done, .animate-fade-slide-in .expanded .animate-fade-slide-in.item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item, .animate-ripple .expanded .animate-fade-slide-in.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment, -.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded.item, -.animate-fade-slide-in-right .expanded -.animate-fade-slide-in .item, -.animate-ripple .expanded -.animate-fade-slide-in .item, -.animate-fade-slide-in -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-fade-slide-in .card.card-comment, +.animate-ripple .animate-fade-slide-in.expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.item, +.card-avatar-small .expanded .animate-fade-slide-in.item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment, .animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, +.animate-fade-slide-in .expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, .animate-ripple .expanded .animate-fade-slide-in .item, .card-avatar-small.expanded .animate-fade-slide-in .item, .card-avatar-small .expanded .animate-fade-slide-in .item, +.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, .animate-fade-slide-in.done, .animate-fade-slide-in .expanded .animate-fade-slide-in.item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item, .animate-ripple .expanded .animate-fade-slide-in.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment { +.animate-ripple .animate-fade-slide-in.expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.item, +.card-avatar-small .expanded .animate-fade-slide-in.item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment { -ms-transform: scale3d(1, 1, 1); -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); @@ -12200,72 +12568,236 @@ a.button { opacity: 1; filter: alpha(opacity=100); } -.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded.item, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, -.animate-ripple .expanded .animate-fade-slide-in .item, .animate-fade-slide-in -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, +.animate-fade-slide-in .expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, .animate-ripple .expanded .animate-fade-slide-in .item, .card-avatar-small.expanded .animate-fade-slide-in .item, .card-avatar-small .expanded .animate-fade-slide-in .item, +.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, .animate-fade-slide-in.done, .animate-fade-slide-in .expanded .animate-fade-slide-in.item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item, .animate-ripple .expanded .animate-fade-slide-in.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment, -.animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded.item, -.animate-fade-slide-in-right .expanded -.animate-fade-slide-in .item, -.animate-ripple .expanded -.animate-fade-slide-in .item, -.animate-fade-slide-in -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-fade-slide-in .card.card-comment, +.animate-ripple .animate-fade-slide-in.expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.item, +.card-avatar-small .expanded .animate-fade-slide-in.item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment, .animate-fade-slide-in .in, .animate-fade-slide-in .expanded .item, +.animate-fade-slide-in .expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in .item, .animate-ripple .expanded .animate-fade-slide-in .item, .card-avatar-small.expanded .animate-fade-slide-in .item, .card-avatar-small .expanded .animate-fade-slide-in .item, +.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment, .animate-fade-slide-in.done, .animate-fade-slide-in .expanded .animate-fade-slide-in.item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item, .animate-ripple .expanded .animate-fade-slide-in.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment { +.animate-ripple .animate-fade-slide-in.expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.item, +.card-avatar-small .expanded .animate-fade-slide-in.item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment { visibility: visible; } -.animate-fade-slide-in.done .in, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .in, -.animate-fade-slide-in .animate-fade-slide-in.expanded.item .in, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .in, -.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .in, -.animate-ripple .expanded .animate-fade-slide-in.item .in, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .in, .animate-fade-slide-in.done .expanded .item, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .item, .animate-fade-slide-in.done .expanded.item, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in.done .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, -.animate-ripple .expanded .animate-fade-slide-in.done .item, .animate-ripple .expanded .animate-fade-slide-in.item .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, .animate-fade-slide-in.done -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.done .card.card-comment, -.animate-ripple .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.expanded.item .card.card-comment, -.animate-fade-slide-in-right -.animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple -.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-fade-slide-in.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .card.card-comment, -.animate-fade-slide-in.done .in, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .in, -.animate-fade-slide-in .animate-fade-slide-in.expanded.item .in, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .in, -.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .in, -.animate-ripple .expanded .animate-fade-slide-in.item .in, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .in, .animate-fade-slide-in.done .expanded .item, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .item, .animate-fade-slide-in.done .expanded.item, -.animate-fade-slide-in-right .expanded -.animate-fade-slide-in.done .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, -.animate-ripple .expanded -.animate-fade-slide-in.done .item, .animate-ripple .expanded .animate-fade-slide-in.item .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, -.animate-fade-slide-in.done -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-fade-slide-in.done .card.card-comment, -.animate-ripple .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.expanded.item .card.card-comment, -.animate-fade-slide-in-right -.animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple -.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-fade-slide-in.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .card.card-comment { +.animate-fade-slide-in.done .in, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .in, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .in, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .in, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .in, .animate-ripple .expanded .animate-fade-slide-in.item .in, .animate-ripple .animate-fade-slide-in.expanded.item .in, .card-avatar-small.expanded .animate-fade-slide-in.item .in, .card-avatar-small .expanded .animate-fade-slide-in.item .in, .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .in, .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .in, .animate-fade-slide-in.done .expanded .item, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .expanded .item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .expanded .item, .animate-ripple .expanded .animate-fade-slide-in.item .expanded .item, .animate-ripple .animate-fade-slide-in.expanded.item .expanded .item, .card-avatar-small.expanded .animate-fade-slide-in.item .expanded .item, .card-avatar-small .expanded .animate-fade-slide-in.item .expanded .item, .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded .item, .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded .item, +.animate-fade-slide-in.done .expanded.item, +.animate-fade-slide-in.item .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in.item .expanded.item, +.animate-ripple .animate-fade-slide-in.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.animate-fade-slide-in.done .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.done .item, +.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, +.animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-fade-slide-in.item .item, +.animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, .animate-fade-slide-in-right .animate-ripple .animate-fade-slide-in.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.item .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in.card.card-comment .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, +.animate-fade-slide-in.done .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in.done .expanded.item, +.animate-fade-slide-in .expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in .animate-fade-slide-in.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-fade-slide-in.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-fade-slide-in.item .expanded.item, +.animate-ripple .animate-fade-slide-in.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .animate-fade-slide-in.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.animate-fade-slide-in.done .animate-ripple .expanded .item, .animate-ripple .expanded .animate-fade-slide-in.done .item, +.animate-fade-slide-in .animate-ripple .expanded .animate-fade-slide-in.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, +.animate-ripple .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .item, +.animate-fade-slide-in-right .animate-ripple .expanded .animate-fade-slide-in.item .item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .animate-ripple .animate-fade-slide-in.expanded.item .item, .animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, +.animate-ripple .expanded .animate-fade-slide-in.item .item, +.animate-ripple .animate-fade-slide-in.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.item .item, +.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in.item .item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in.card.card-comment .item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, +.animate-fade-slide-in.done .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in.done .expanded.item, +.animate-fade-slide-in .expanded .animate-fade-slide-in.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in .animate-fade-slide-in.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .animate-fade-slide-in.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in.item .expanded.item, +.animate-ripple .animate-fade-slide-in.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.animate-fade-slide-in.done .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in.done .item, +.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.item .item, +.animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-ripple .animate-fade-slide-in.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.item .item, +.card-avatar-small.expanded .expanded .animate-fade-slide-in.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small.expanded .expanded .animate-fade-slide-in.card.card-comment .item, +.animate-fade-slide-in.done .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-fade-slide-in.done .item, +.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, +.card-avatar-small .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.item .item, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .card-avatar-small .animate-fade-slide-in.expanded.item .item, .card-avatar-small .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, +.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.item .item, .card-avatar-small .animate-ripple .expanded .animate-fade-slide-in.item .item, +.animate-ripple .card-avatar-small .animate-fade-slide-in.expanded.item .item, .card-avatar-small .animate-ripple .animate-fade-slide-in.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.item .expanded .item, .card-avatar-small.expanded .expanded .animate-fade-slide-in.item .item, +.card-avatar-small .expanded .animate-fade-slide-in.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded .item, .card-avatar-small.expanded .expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, +.animate-fade-slide-in.done .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment, +.animate-fade-slide-in .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment, +.animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .animate-fade-slide-in.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment, +.card-avatar-small.expanded .expanded .animate-fade-slide-in.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .card.card-comment, +.card-avatar-small.expanded .expanded .animate-fade-slide-in.card.card-comment .card.card-comment, +.animate-fade-slide-in.done .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in.item .card.card-comment, +.card-avatar-small .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .animate-fade-slide-in.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment, .card-avatar-small .animate-ripple .expanded .animate-fade-slide-in.item .card.card-comment, +.animate-ripple .card-avatar-small .animate-fade-slide-in.expanded.item .card.card-comment, .card-avatar-small .animate-ripple .animate-fade-slide-in.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in.item .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-fade-slide-in.item .card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-fade-slide-in.card.card-comment .card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .card.card-comment, .animate-fade-slide-in.done .in, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .in, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .in, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .in, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .in, .animate-ripple .expanded .animate-fade-slide-in.item .in, .animate-ripple .animate-fade-slide-in.expanded.item .in, .card-avatar-small.expanded .animate-fade-slide-in.item .in, .card-avatar-small .expanded .animate-fade-slide-in.item .in, .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .in, .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .in, .animate-fade-slide-in.done .expanded .item, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .expanded .item, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .expanded .item, .animate-ripple .expanded .animate-fade-slide-in.item .expanded .item, .animate-ripple .animate-fade-slide-in.expanded.item .expanded .item, .card-avatar-small.expanded .animate-fade-slide-in.item .expanded .item, .card-avatar-small .expanded .animate-fade-slide-in.item .expanded .item, .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded .item, .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded .item, +.animate-fade-slide-in.done .expanded.item, +.animate-fade-slide-in.item .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in.item .expanded.item, +.animate-ripple .animate-fade-slide-in.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.animate-fade-slide-in.done .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.done .item, +.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, +.animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-fade-slide-in.item .item, +.animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, .animate-fade-slide-in-right .animate-ripple .animate-fade-slide-in.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.item .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in.card.card-comment .item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, +.animate-fade-slide-in.done .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in.done .expanded.item, +.animate-fade-slide-in .expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in .animate-fade-slide-in.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-fade-slide-in .animate-fade-slide-in.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .expanded .animate-fade-slide-in.item .expanded.item, +.animate-ripple .animate-fade-slide-in.expanded.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .animate-ripple .animate-fade-slide-in.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .animate-fade-slide-in-right .expanded.item, .animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.animate-fade-slide-in.done .animate-ripple .expanded .item, .animate-ripple .expanded .animate-fade-slide-in.done .item, +.animate-fade-slide-in .animate-ripple .expanded .animate-fade-slide-in.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, +.animate-ripple .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .item, +.animate-fade-slide-in-right .animate-ripple .expanded .animate-fade-slide-in.item .item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .animate-ripple .animate-fade-slide-in.expanded.item .item, .animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, +.animate-ripple .expanded .animate-fade-slide-in.item .item, +.animate-ripple .animate-fade-slide-in.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.item .item, +.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in.item .item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in.card.card-comment .item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, +.animate-fade-slide-in.done .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in.done .expanded.item, +.animate-fade-slide-in .expanded .animate-fade-slide-in.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in .animate-fade-slide-in.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .animate-fade-slide-in.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .expanded.item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in.item .expanded.item, +.animate-ripple .animate-fade-slide-in.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded.item, +.animate-fade-slide-in.done .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in.done .item, +.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.item .item, +.animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-ripple .animate-fade-slide-in.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.item .item, +.card-avatar-small.expanded .expanded .animate-fade-slide-in.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small.expanded .expanded .animate-fade-slide-in.card.card-comment .item, +.animate-fade-slide-in.done .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-fade-slide-in.done .item, +.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item, +.card-avatar-small .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.item .item, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item, +.animate-fade-slide-in-right .card-avatar-small .animate-fade-slide-in.expanded.item .item, .card-avatar-small .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item, +.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.item .item, .card-avatar-small .animate-ripple .expanded .animate-fade-slide-in.item .item, +.animate-ripple .card-avatar-small .animate-fade-slide-in.expanded.item .item, .card-avatar-small .animate-ripple .animate-fade-slide-in.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.item .expanded .item, .card-avatar-small.expanded .expanded .animate-fade-slide-in.item .item, +.card-avatar-small .expanded .animate-fade-slide-in.item .item, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded .item, .card-avatar-small.expanded .expanded .animate-fade-slide-in.card.card-comment .item, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item, +.animate-fade-slide-in.done .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment, +.animate-fade-slide-in .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment, +.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment, +.animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .animate-fade-slide-in.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment, +.card-avatar-small.expanded .expanded .animate-fade-slide-in.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .card.card-comment, +.card-avatar-small.expanded .expanded .animate-fade-slide-in.card.card-comment .card.card-comment, +.animate-fade-slide-in.done .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in.item .card.card-comment, +.card-avatar-small .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .animate-fade-slide-in.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment, .card-avatar-small .animate-ripple .expanded .animate-fade-slide-in.item .card.card-comment, +.animate-ripple .card-avatar-small .animate-fade-slide-in.expanded.item .card.card-comment, .card-avatar-small .animate-ripple .animate-fade-slide-in.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in.item .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-fade-slide-in.item .card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-fade-slide-in.card.card-comment .card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .card.card-comment { opacity: 1; filter: alpha(opacity=100); } @@ -12276,18 +12808,7 @@ a.button { -webkit-transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out; } -.animate-fade-slide-in.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .has-mask-reverse:after, -.animate-fade-slide-in .animate-fade-slide-in.expanded.item .has-mask-reverse:after, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .has-mask-reverse:after, -.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .has-mask-reverse:after, -.animate-ripple .expanded .animate-fade-slide-in.item .has-mask-reverse:after, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .has-mask-reverse:after, -.animate-fade-slide-in.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .has-mask-reverse:after, -.animate-fade-slide-in .animate-fade-slide-in.expanded.item .has-mask-reverse:after, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .has-mask-reverse:after, -.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .has-mask-reverse:after, -.animate-ripple .expanded .animate-fade-slide-in.item .has-mask-reverse:after, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .has-mask-reverse:after { +.animate-fade-slide-in.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .has-mask-reverse:after, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .has-mask-reverse:after, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .has-mask-reverse:after, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .has-mask-reverse:after, .animate-ripple .expanded .animate-fade-slide-in.item .has-mask-reverse:after, .animate-ripple .animate-fade-slide-in.expanded.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-fade-slide-in.item .has-mask-reverse:after, .card-avatar-small .expanded .animate-fade-slide-in.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .has-mask-reverse:after, .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .has-mask-reverse:after, .animate-fade-slide-in.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-fade-slide-in.item .has-mask-reverse:after, .animate-fade-slide-in .animate-fade-slide-in.expanded.item .has-mask-reverse:after, .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .has-mask-reverse:after, .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .has-mask-reverse:after, .animate-ripple .expanded .animate-fade-slide-in.item .has-mask-reverse:after, .animate-ripple .animate-fade-slide-in.expanded.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-fade-slide-in.item .has-mask-reverse:after, .card-avatar-small .expanded .animate-fade-slide-in.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .has-mask-reverse:after, .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .has-mask-reverse:after { opacity: 1; filter: alpha(opacity=100); } @@ -12318,58 +12839,72 @@ a.button { -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); } -.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded.item, -.animate-ripple .expanded .animate-fade-slide-in-right .item, .animate-fade-slide-in-right -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, -.animate-fade-slide-in-right.done > *, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item > *, +.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .expanded .item, +.animate-fade-slide-in-right .expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right .item, .card-avatar-small.expanded .animate-fade-slide-in-right .item, .card-avatar-small .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right.done > *, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item > *, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item > *, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item > *, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item > *, .animate-ripple .expanded .animate-fade-slide-in-right.item > *, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment > *, -.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded -.animate-fade-slide-in-right .item, .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded.item, -.animate-ripple .expanded -.animate-fade-slide-in-right .item, -.animate-fade-slide-in-right -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-fade-slide-in-right .card.card-comment, -.animate-fade-slide-in-right.done > *, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item > *, +.animate-ripple .animate-fade-slide-in-right.expanded.item > *, +.card-avatar-small.expanded .animate-fade-slide-in-right.item > *, +.card-avatar-small .expanded .animate-fade-slide-in-right.item > *, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment > *, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment > *, .animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .expanded .item, +.animate-fade-slide-in-right .expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right .item, .card-avatar-small.expanded .animate-fade-slide-in-right .item, .card-avatar-small .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right.done > *, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item > *, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item > *, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item > *, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item > *, .animate-ripple .expanded .animate-fade-slide-in-right.item > *, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment > * { +.animate-ripple .animate-fade-slide-in-right.expanded.item > *, +.card-avatar-small.expanded .animate-fade-slide-in-right.item > *, +.card-avatar-small .expanded .animate-fade-slide-in-right.item > *, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment > *, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment > * { -ms-transform: translate3d(0, 0, 0); -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } -.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded.item, -.animate-ripple .expanded .animate-fade-slide-in-right .item, .animate-fade-slide-in-right -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, -.animate-fade-slide-in-right.done .item, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, +.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .expanded .item, +.animate-fade-slide-in-right .expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right .item, .card-avatar-small.expanded .animate-fade-slide-in-right .item, .card-avatar-small .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right.done .item, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item, .animate-ripple .expanded .animate-fade-slide-in-right.item .item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item, -.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded -.animate-fade-slide-in-right .item, .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded.item, -.animate-ripple .expanded -.animate-fade-slide-in-right .item, -.animate-fade-slide-in-right -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-fade-slide-in-right .card.card-comment, -.animate-fade-slide-in-right.done .item, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item, .animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .expanded .item, +.animate-fade-slide-in-right .expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right .item, .card-avatar-small.expanded .animate-fade-slide-in-right .item, .card-avatar-small .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right.done .item, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item, .animate-ripple .expanded .animate-fade-slide-in-right.item .item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item { +.animate-ripple .animate-fade-slide-in-right.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item { visibility: visible; } .animate-fade-slide-in-right .item, @@ -12386,32 +12921,37 @@ a.button { opacity: 0; filter: alpha(opacity=0); } -.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded.item, -.animate-ripple .expanded .animate-fade-slide-in-right .item, .animate-fade-slide-in-right -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .expanded .item, +.animate-fade-slide-in-right .expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right .item, .card-avatar-small.expanded .animate-fade-slide-in-right .item, .card-avatar-small .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, .animate-fade-slide-in-right.done, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment, -.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded -.animate-fade-slide-in-right .item, .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded.item, -.animate-ripple .expanded -.animate-fade-slide-in-right .item, -.animate-fade-slide-in-right -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-fade-slide-in-right .card.card-comment, +.animate-ripple .animate-fade-slide-in-right.expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment, .animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .expanded .item, +.animate-fade-slide-in-right .expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right .item, .card-avatar-small.expanded .animate-fade-slide-in-right .item, .card-avatar-small .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, .animate-fade-slide-in-right.done, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment { +.animate-ripple .animate-fade-slide-in-right.expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment { -ms-transform: scale3d(1, 1, 1); -webkit-transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1); @@ -12420,68 +12960,238 @@ a.button { opacity: 1; filter: alpha(opacity=100); } -.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded.item, -.animate-ripple .expanded .animate-fade-slide-in-right .item, .animate-fade-slide-in-right -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .expanded .item, +.animate-fade-slide-in-right .expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right .item, .card-avatar-small.expanded .animate-fade-slide-in-right .item, .card-avatar-small .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, .animate-fade-slide-in-right.done, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment, -.animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded -.animate-fade-slide-in-right .item, .animate-fade-slide-in-right .expanded .item, .animate-fade-slide-in-right .expanded.item, -.animate-ripple .expanded -.animate-fade-slide-in-right .item, -.animate-fade-slide-in-right -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-fade-slide-in-right .card.card-comment, +.animate-ripple .animate-fade-slide-in-right.expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment, .animate-fade-slide-in-right .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .expanded .item, +.animate-fade-slide-in-right .expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right .item, .card-avatar-small.expanded .animate-fade-slide-in-right .item, .card-avatar-small .expanded .animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment, .animate-fade-slide-in-right.done, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item, .animate-ripple .expanded .animate-fade-slide-in-right.item, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment { +.animate-ripple .animate-fade-slide-in-right.expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment { visibility: visible; } -.animate-fade-slide-in-right.done .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .in, -.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .in, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .in, -.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .in, -.animate-ripple .expanded .animate-fade-slide-in-right.item .in, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.done .item, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in-right.done .expanded .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in-right.done .expanded.item, -.animate-ripple .expanded .animate-fade-slide-in-right.done .item, .animate-ripple .expanded .animate-fade-slide-in-right.item .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item, .animate-fade-slide-in-right.done -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.done .card.card-comment, -.animate-fade-slide-in -.animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple -.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.expanded.item .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-fade-slide-in-right.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment, -.animate-fade-slide-in-right.done .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .in, -.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .in, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .in, -.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .in, -.animate-ripple .expanded .animate-fade-slide-in-right.item .in, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .in, .animate-fade-slide-in .expanded -.animate-fade-slide-in-right.done .item, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in-right.done .expanded .item, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in-right.done .expanded.item, -.animate-ripple .expanded -.animate-fade-slide-in-right.done .item, .animate-ripple .expanded .animate-fade-slide-in-right.item .item, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item, -.animate-fade-slide-in-right.done -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded -.animate-fade-slide-in-right.done .card.card-comment, -.animate-fade-slide-in -.animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple -.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, -.animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.expanded.item .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-fade-slide-in-right.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment, .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment { +.animate-fade-slide-in-right.done .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .in, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .in, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .in, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .in, .animate-ripple .expanded .animate-fade-slide-in-right.item .in, .animate-ripple .animate-fade-slide-in-right.expanded.item .in, .card-avatar-small.expanded .animate-fade-slide-in-right.item .in, .card-avatar-small .expanded .animate-fade-slide-in-right.item .in, .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .in, .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .in, .animate-fade-slide-in-right.done .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.done .item, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-ripple .expanded .animate-fade-slide-in-right.item .item, .animate-ripple .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in .animate-ripple .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in-right.card.card-comment .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item, +.animate-fade-slide-in-right.done .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right.done .expanded.item, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .animate-fade-slide-in-right.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.animate-fade-slide-in-right.done .expanded .item, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .expanded .item, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .expanded .item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, +.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item, +.animate-ripple .expanded .animate-fade-slide-in-right.item .expanded .item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .expanded .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded .item, +.animate-fade-slide-in-right.done .expanded.item, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-fade-slide-in-right.item .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.animate-fade-slide-in-right.done .animate-ripple .expanded .item, .animate-ripple .expanded .animate-fade-slide-in-right.done .item, +.animate-fade-slide-in .animate-ripple .expanded .animate-fade-slide-in-right.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, +.animate-fade-slide-in .animate-ripple .animate-fade-slide-in-right.expanded.item .item, .animate-ripple .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, +.animate-fade-slide-in-right .animate-ripple .expanded .animate-fade-slide-in-right.item .item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .item, +.animate-ripple .expanded .animate-fade-slide-in-right.item .item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in-right.item .item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item, +.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in-right.card.card-comment .item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item, +.animate-fade-slide-in-right.done .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right.done .expanded.item, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.animate-fade-slide-in-right.done .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in-right.done .item, +.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-ripple .animate-fade-slide-in-right.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item, +.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.card.card-comment .item, +.animate-fade-slide-in-right.done .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-fade-slide-in-right.done .item, +.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, +.animate-fade-slide-in .card-avatar-small .animate-fade-slide-in-right.expanded.item .item, .card-avatar-small .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in-right.item .item, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .item, +.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.item .item, .card-avatar-small .animate-ripple .expanded .animate-fade-slide-in-right.item .item, +.animate-ripple .card-avatar-small .animate-fade-slide-in-right.expanded.item .item, .card-avatar-small .animate-ripple .animate-fade-slide-in-right.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded .item, .card-avatar-small.expanded .expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded .item, .card-avatar-small.expanded .expanded .animate-fade-slide-in-right.card.card-comment .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item, +.animate-fade-slide-in-right.done .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment, +.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment, +.animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .animate-fade-slide-in-right.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment, +.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment, +.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment, +.animate-fade-slide-in-right.done .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in-right.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .card.card-comment, +.animate-fade-slide-in .card-avatar-small .animate-fade-slide-in-right.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .card.card-comment, +.card-avatar-small .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment, .card-avatar-small .animate-ripple .expanded .animate-fade-slide-in-right.item .card.card-comment, +.animate-ripple .card-avatar-small .animate-fade-slide-in-right.expanded.item .card.card-comment, .card-avatar-small .animate-ripple .animate-fade-slide-in-right.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-fade-slide-in-right.item .card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment, .animate-fade-slide-in-right.done .in, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .in, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .in, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .in, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .in, .animate-ripple .expanded .animate-fade-slide-in-right.item .in, .animate-ripple .animate-fade-slide-in-right.expanded.item .in, .card-avatar-small.expanded .animate-fade-slide-in-right.item .in, .card-avatar-small .expanded .animate-fade-slide-in-right.item .in, .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .in, .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .in, .animate-fade-slide-in-right.done .animate-fade-slide-in .expanded .item, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.done .item, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .animate-ripple .expanded .animate-fade-slide-in-right.item .item, .animate-ripple .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in .animate-ripple .animate-fade-slide-in-right.expanded.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.item .item, .animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in-right.card.card-comment .item, .animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item, +.animate-fade-slide-in-right.done .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right.done .expanded.item, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .animate-ripple .animate-fade-slide-in-right.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .animate-fade-slide-in .expanded.item, .animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.animate-fade-slide-in-right.done .expanded .item, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .expanded .item, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .expanded .item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, +.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item, +.animate-ripple .expanded .animate-fade-slide-in-right.item .expanded .item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .expanded .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded .item, +.animate-fade-slide-in-right.done .expanded.item, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-fade-slide-in-right.item .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.animate-fade-slide-in-right.done .animate-ripple .expanded .item, .animate-ripple .expanded .animate-fade-slide-in-right.done .item, +.animate-fade-slide-in .animate-ripple .expanded .animate-fade-slide-in-right.item .item, .animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, +.animate-fade-slide-in .animate-ripple .animate-fade-slide-in-right.expanded.item .item, .animate-ripple .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, +.animate-fade-slide-in-right .animate-ripple .expanded .animate-fade-slide-in-right.item .item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .item, +.animate-ripple .expanded .animate-fade-slide-in-right.item .item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in-right.item .item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item, +.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in-right.card.card-comment .item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item, +.animate-fade-slide-in-right.done .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right.done .expanded.item, +.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .animate-ripple .expanded.item, .animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .expanded.item, +.animate-ripple .expanded .animate-fade-slide-in-right.item .expanded.item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded.item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .animate-ripple .expanded.item, .animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded.item, +.animate-fade-slide-in-right.done .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in-right.done .item, +.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item, .card-avatar-small.expanded .animate-ripple .animate-fade-slide-in-right.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item, +.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.card.card-comment .item, +.animate-fade-slide-in-right.done .card-avatar-small .expanded .item, .card-avatar-small .expanded .animate-fade-slide-in-right.done .item, +.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.item .item, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item, +.animate-fade-slide-in .card-avatar-small .animate-fade-slide-in-right.expanded.item .item, .card-avatar-small .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in-right.item .item, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .item, +.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.item .item, .card-avatar-small .animate-ripple .expanded .animate-fade-slide-in-right.item .item, +.animate-ripple .card-avatar-small .animate-fade-slide-in-right.expanded.item .item, .card-avatar-small .animate-ripple .animate-fade-slide-in-right.expanded.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded .item, .card-avatar-small.expanded .expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .item, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded .item, .card-avatar-small.expanded .expanded .animate-fade-slide-in-right.card.card-comment .item, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item, +.animate-fade-slide-in-right.done .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment, +.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment, +.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment, +.animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .card.card-comment, .card-avatar-small.expanded .animate-ripple .animate-fade-slide-in-right.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment, +.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment, +.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment, +.animate-fade-slide-in-right.done .card-avatar-small .expanded .card.card-comment, .card-avatar-small .expanded .animate-fade-slide-in-right.done .card.card-comment, +.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .card.card-comment, +.animate-fade-slide-in .card-avatar-small .animate-fade-slide-in-right.expanded.item .card.card-comment, .card-avatar-small .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card.card-comment, +.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment, .card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .card.card-comment, +.card-avatar-small .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .card.card-comment, +.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment, .card-avatar-small .animate-ripple .expanded .animate-fade-slide-in-right.item .card.card-comment, +.animate-ripple .card-avatar-small .animate-fade-slide-in-right.expanded.item .card.card-comment, .card-avatar-small .animate-ripple .animate-fade-slide-in-right.expanded.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-fade-slide-in-right.item .card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment, +.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded .card.card-comment, .card-avatar-small.expanded .expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment, +.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment { opacity: 1; filter: alpha(opacity=100); } @@ -12492,18 +13202,7 @@ a.button { -webkit-transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out; } -.animate-fade-slide-in-right.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, -.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, -.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after, -.animate-ripple .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .has-mask-reverse:after, -.animate-fade-slide-in-right.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, -.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after, -.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, -.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after, -.animate-ripple .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, -.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .has-mask-reverse:after { +.animate-fade-slide-in-right.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after, .animate-ripple .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, .animate-ripple .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, .card-avatar-small .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .has-mask-reverse:after, .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .has-mask-reverse:after, .animate-fade-slide-in-right.done .has-mask-reverse:after, .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after, .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after, .animate-ripple .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, .animate-ripple .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, .card-avatar-small .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after, .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .has-mask-reverse:after, .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .has-mask-reverse:after { opacity: 1; filter: alpha(opacity=100); } @@ -12600,9 +13299,7 @@ a.button { transition: none !important; } .button-fab, -.button-flat, -.button-clear, -.button-text, +.button-flat, .button-clear, .button-text, .button-raised, .ink-button, .ink-circle { @@ -12614,9 +13311,7 @@ a.button { .button-fab.activated, .button-flat.activated, -.button-raised.activated, -.button-clear.activated, -.activated.button-text, +.button-raised.activated, .button-clear.activated, .activated.button-text, .ink-button.activated, .ink.activated, .ink-circle.activated, @@ -12643,9 +13338,7 @@ a.button { .button-flat:link, .button-raised, .button-raised:visited, -.button-raised:link, -.button-clear, -.button-text, +.button-raised:link, .button-clear, .button-text, .button-clear:visited, .button-text:visited, .button-clear:link, @@ -12809,8 +13502,7 @@ a { background-color: #3F51B5; color: #fff; } -.positive-900-bg, .view-wallet .refresher-top-bg:before, .view-wallet-tx .refresher-top-bg:before, .view-identity .member .hero, -.view-identity .member.refresher-top-bg:before, +.positive-900-bg, .button-positive-900, .bar .button-positive-900, .header-positive-900, @@ -12818,10 +13510,6 @@ a { .bar-positive-900, .positive-900-border, .positive-900-bg:hover, -.view-wallet .refresher-top-bg:hover:before, -.view-wallet-tx .refresher-top-bg:hover:before, -.view-identity .member .hero:hover, -.view-identity .member.refresher-top-bg:hover:before, .button-positive-900:hover, .bar .button-positive-900:hover, .header-positive-900:hover, @@ -12829,10 +13517,6 @@ a { .bar-positive-900:hover, .positive-900-border:hover, .positive-900-bg:active, -.view-wallet .refresher-top-bg:active:before, -.view-wallet-tx .refresher-top-bg:active:before, -.view-identity .member .hero:active, -.view-identity .member.refresher-top-bg:active:before, .bar .button-positive-900:active, .button-positive-900:active, .header-positive-900:active, @@ -12840,10 +13524,6 @@ a { .bar-positive-900:active, .positive-900-border:active, .positive-900-bg.activated, -.view-wallet .activated.refresher-top-bg:before, -.view-wallet-tx .activated.refresher-top-bg:before, -.view-identity .member .activated.hero, -.view-identity .activated.member.refresher-top-bg:before, .button-positive-900.activated, .bar .button-positive-900.activated, .header-positive-900.activated, @@ -13384,19 +14064,30 @@ a { /* Text Colors ==================================*/ -.positive, .icon-help, -.positive *, .icon-help *, +.positive, .text-editable:hover, .icon-help, +.positive *, +.text-editable:hover *, +.icon-help *, *.positive, +*.text-editable:hover, *.icon-help, .positive:hover, +.text-editable:hover, .icon-help:hover, -.positive:hover *, .icon-help:hover *, +.positive:hover *, +.text-editable:hover *, +.icon-help:hover *, *.positive:hover, +*.text-editable:hover, *.icon-help:hover, .positive:active, +.text-editable:active:hover, .icon-help:active, -.positive:active *, .icon-help:active *, +.positive:active *, +.text-editable:active:hover *, +.icon-help:active *, *.positive:active, +*.text-editable:active:hover, *.icon-help:active { color: #3F51B5; } @@ -13555,17 +14246,20 @@ a { color: #FFE0B2; } .assertive, .icon-alert, -.assertive *, .icon-alert *, +.assertive *, +.icon-alert *, *.assertive, *.icon-alert, .assertive:hover, .icon-alert:hover, -.assertive:hover *, .icon-alert:hover *, +.assertive:hover *, +.icon-alert:hover *, *.assertive:hover, *.icon-alert:hover, .assertive:active, .icon-alert:active, -.assertive:active *, .icon-alert:active *, +.assertive:active *, +.icon-alert:active *, *.assertive:active, *.icon-alert:active { color: #F44336; } @@ -13615,17 +14309,20 @@ a { color: #fff; } .dark, .button-text-dark, -.dark *, .button-text-dark *, +.dark *, +.button-text-dark *, *.dark, *.button-text-dark, .dark:hover, .button-text-dark:hover, -.dark:hover *, .button-text-dark:hover *, +.dark:hover *, +.button-text-dark:hover *, *.dark:hover, *.button-text-dark:hover, .dark:active, .button-text-dark:active, -.dark:active *, .button-text-dark:active *, +.dark:active *, +.button-text-dark:active *, *.dark:active, *.button-text-dark:active { color: #444; } @@ -13661,11 +14358,7 @@ a { /* Item ==================================*/ -.item-avatar, -.item-avatar .item-content, -.item-avatar-left, -.item-avatar-left .item-content, -.card > .item-avatar { +.item-avatar, .item-avatar .item-content, .item-avatar-left, .item-avatar-left .item-content, .card > .item-avatar { padding-left: 95px; } .item, @@ -13673,10 +14366,8 @@ a { .item-radio .item-content { background-color: transparent; } -.dark-bg h2, .view-identity .hero h2, -.view-identity .refresher-top-bg:before h2, -.item.dark-bg h2, .view-identity .item.hero h2, -.view-identity .item.refresher-top-bg:before h2 { +.dark-bg h2, +.item.dark-bg h2 { color: #fff; } .tabs-striped .tabs { @@ -13695,8 +14386,7 @@ a { .menu { background-color: transparent; } -.button-icon.button.active, -.button-icon.button.activated { +.button-icon.button.active, .button-icon.button.activated { opacity: initial; } /* Popover @@ -13760,26 +14450,208 @@ a { .ion-library:before { content: ""; } +.digit-keyboard { + position: absolute; + left: 0; + right: 0; + bottom: 0; + background: transparent; + font-size: 24px; + z-index: 5000; + /* + * Keyboard color styles + */ } + .digit-keyboard * { + box-sizing: border-box; } + .digit-keyboard .digit-keyboard-row { + display: flex; + flex-direction: row; + border-bottom: 1px solid #333; } + .digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper { + flex: 1; + text-align: center; + position: relative; + height: 60px; } + .digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key { + display: block; + margin: 0 auto; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + border-right: 1px solid #333; + border-left: 1px solid #333; + line-height: 60px; + -webkit-transition: background-color 100ms linear; + -moz-transition: background-color 100ms linear; + -o-transition: background-color 100ms linear; + -ms-transition: background-color 100ms linear; + transition: background-color 100ms linear; + /*&.activated { + //background: $dk-btn-click-bg-color; + + .digit-keyboard-key-number { + //color: $dk-btn-click-text-color; + } + }*/ } + .digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number { + font-size: 1em; + vertical-align: middle; + display: inline-block; + line-height: normal; + text-align: center; + margin-top: -0.40em; } + .digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters { + font-size: 9.6px; + line-height: 9.6px; + height: 9.6px; + margin-top: -0.25em; } + .digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters.hidden { + visibility: hidden; } + .digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-action { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + line-height: 60px; + font-size: 24px; } + .digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper.hidden { + visibility: hidden; } + .digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper:first-child .digit-keyboard-key { + border-right: none; } + .digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper:last-child .digit-keyboard-key { + border-left: none; } + .digit-keyboard .digit-keyboard-row:first-child { + border-top: 1px solid #333; } + .digit-keyboard .digit-keyboard-row:last-child { + border: none; } + .digit-keyboard .digit-keyboard-row:last-child .digit-keyboard-key-wrapper .digit-keyboard-key { + border-bottom: 1px solid #333; } + .digit-keyboard.align-center { + margin: 0 auto; } + .digit-keyboard.align-left { + margin-right: auto; } + .digit-keyboard.align-right { + margin-left: auto; } + .digit-keyboard.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number { + margin-top: -0.30em; } + .digit-keyboard.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters { + display: none; } + .digit-keyboard.round-buttons .digit-keyboard-row { + border: none; } + .digit-keyboard.round-buttons .digit-keyboard-row .digit-keyboard-key-wrapper { + margin: 10px 0 0 0; } + .digit-keyboard.round-buttons .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key { + width: 60px; + -webkit-border-radius: 100%; + -moz-border-radius: 100%; + border-radius: 100%; + border: 1px solid #333; } + .digit-keyboard.round-buttons .digit-keyboard-row:last-child .digit-keyboard-key-wrapper { + margin-bottom: 10px; } + .digit-keyboard.round-buttons.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number { + height: 57.6px; + line-height: 57.6px; } + .digit-keyboard.keyboard-light * { + border-color: #e6e6e6 !important; } + .digit-keyboard.keyboard-light .digit-keyboard-key { + background: #fff; + color: #444; } + .digit-keyboard.keyboard-light .digit-keyboard-key.activated { + background: #e6e6e6; } + .digit-keyboard.keyboard-stable * { + border-color: #dfdfdf !important; } + .digit-keyboard.keyboard-stable .digit-keyboard-key { + background: #f8f8f8; + color: #444; } + .digit-keyboard.keyboard-stable .digit-keyboard-key.activated { + background: #dfdfdf; } + .digit-keyboard.keyboard-positive * { + border-color: #0c60ee !important; } + .digit-keyboard.keyboard-positive .digit-keyboard-key { + background: #387ef5; + color: #fff; } + .digit-keyboard.keyboard-positive .digit-keyboard-key.activated { + background: #0c60ee; } + .digit-keyboard.keyboard-calm * { + border-color: #0a9dc7 !important; } + .digit-keyboard.keyboard-calm .digit-keyboard-key { + background: #11c1f3; + color: #fff; } + .digit-keyboard.keyboard-calm .digit-keyboard-key.activated { + background: #0a9dc7; } + .digit-keyboard.keyboard-balanced * { + border-color: #28a54c !important; } + .digit-keyboard.keyboard-balanced .digit-keyboard-key { + background: #33cd5f; + color: #fff; } + .digit-keyboard.keyboard-balanced .digit-keyboard-key.activated { + background: #28a54c; } + .digit-keyboard.keyboard-energized * { + border-color: #e6b500 !important; } + .digit-keyboard.keyboard-energized .digit-keyboard-key { + background: #ffc900; + color: #fff; } + .digit-keyboard.keyboard-energized .digit-keyboard-key.activated { + background: #e6b500; } + .digit-keyboard.keyboard-assertive * { + border-color: #e42112 !important; } + .digit-keyboard.keyboard-assertive .digit-keyboard-key { + background: #ef473a; + color: #fff; } + .digit-keyboard.keyboard-assertive .digit-keyboard-key.activated { + background: #e42112; } + .digit-keyboard.keyboard-royal * { + border-color: #6b46e5 !important; } + .digit-keyboard.keyboard-royal .digit-keyboard-key { + background: #886aea; + color: #fff; } + .digit-keyboard.keyboard-royal .digit-keyboard-key.activated { + background: #6b46e5; } + .digit-keyboard.keyboard-dark * { + border-color: #2b2b2b !important; } + .digit-keyboard.keyboard-dark .digit-keyboard-key { + background: #444; + color: #fff; } + .digit-keyboard.keyboard-dark .digit-keyboard-key.activated { + background: #2b2b2b; } + .digit-keyboard.keyboard-opaque-black * { + border-color: rgba(0, 0, 0, 0.75) !important; } + .digit-keyboard.keyboard-opaque-black .digit-keyboard-key { + background: rgba(0, 0, 0, 0.15); + color: rgba(0, 0, 0, 0.75); } + .digit-keyboard.keyboard-opaque-black .digit-keyboard-key.activated { + background: rgba(0, 0, 0, 0.25); } + .digit-keyboard.keyboard-opaque-white * { + border-color: rgba(255, 255, 255, 0.75) !important; } + .digit-keyboard.keyboard-opaque-white .digit-keyboard-key { + background: rgba(255, 255, 255, 0.15); + color: rgba(255, 255, 255, 0.75); } + .digit-keyboard.keyboard-opaque-white .digit-keyboard-key.activated { + background: rgba(255, 255, 255, 0.25); } + .digit-keyboard.animation-slide-up { + -webkit-transition: transform linear 150ms; + transition: transform linear 150ms; + transform: translate3d(0, 0, 0); } + .digit-keyboard.animation-slide-up.ng-hide { + transform: translate3d(0, 100%, 0); } + .digit-keyboard.animation-pop { + -webkit-transition: transform linear 150ms; + transition: transform linear 150ms; + transform: scale3d(1, 1, 1); } + .digit-keyboard.animation-pop.ng-hide { + transform: scale3d(0, 0, 1); } + @media screen and (max-width: 400px) { @-ms-viewport { - width: 320px; } - .item .badge { - right: 16px; } } + width: 320px; } } @media screen and (max-width: 767px) { .hidden-xs { display: none !important; visibility: hidden !important; } - .badge { - text-overflow: ellipsis !important; - white-space: nowrap; - overflow: hidden !important; - max-width: 300px !important; - display: block !important; } - .badge:empty { - display: none !important; } - .item .badge { - right: 16px; } .padding-top-xs { padding-top: 10px; } } @@ -13790,16 +14662,14 @@ a { .row.hidden-xs { display: flex !important; } .button.hidden-xs { - display: inline-block; } - .item-toggle .toggle { - right: 32px; } } + display: inline-block; } } @media screen and (max-width: 767px) { .visible-xs { display: inherit !important; visibility: visible !important; } .button.visible-xs { - display: block !important; } } + display: inline-block !important; } } @media screen and (min-width: 768px) { .visible-xs { @@ -13808,30 +14678,16 @@ a { @media screen and (max-width: 767px) { .padding-xs { - padding: 16px !important; } } - -@media screen and (min-width: 768px) { - .padding-xs { - padding: inherit; } } - -@media screen and (max-width: 767px) { - .no-padding-xs { - padding: 0px !important; } } - -@media screen and (min-width: 768px) { + padding: 16px !important; } .no-padding-xs { - padding: inherit; } } - -@media screen and (max-width: 767px) { + padding: 0px !important; } .no-margin-xs { margin: 0px !important; } } -@media screen and (min-width: 768px) { - .no-margin-xs { - margin: inherit; } } - -@media screen and (max-width: 991px) and (min-width: 768px) { - .hidden-sm, .row-header.hidden-sm { +@media screen and (min-width: 768px) and (max-width: 991px) { + .hidden-sm, + .row.hidden-sm, + .row-header.hidden-sm { display: none !important; visibility: hidden !important; } .badge { @@ -13839,9 +14695,19 @@ a { white-space: nowrap; overflow: hidden !important; max-width: 400px !important; - display: block !important; } + display: inline-block !important; } .badge:empty { - display: none !important; } } + display: none !important; } + .padding-sm { + padding: 16px !important; } + .no-padding-sm { + padding: 0px !important; } + .no-margin-sm { + margin: 0px !important; } } + +@media screen and (min-width: 768px) { + .item-toggle .toggle { + right: 32px; } } @media screen and (min-width: 992px) { .hidden-sm { @@ -13852,7 +14718,17 @@ a { .button.hidden-sm { display: flex; } .pull-right .button.hidden-sm, .popover-helptip .icon.icon-right .button.hidden-sm, .popover-helptip .icon-right.icon-help .button.hidden-sm, .popover-helptip .icon-right.icon-alert .button.hidden-sm, .popover-helptip #menu .footer .icon-right.icon-help .button.hidden-sm, #menu .footer .popover-helptip .icon-right.icon-help .button.hidden-sm, .popover-helptip .icon.icon-center .button.hidden-sm, .popover-helptip .icon-center.icon-help .button.hidden-sm, .popover-helptip .icon-center.icon-alert .button.hidden-sm, .popover-helptip #menu .footer .icon-center.icon-help .button.hidden-sm, #menu .footer .popover-helptip .icon-center.icon-help .button.hidden-sm, .popover-helptip .icon.icon-bottom-right .button.hidden-sm, .popover-helptip .icon-bottom-right.icon-help .button.hidden-sm, .popover-helptip .icon-bottom-right.icon-alert .button.hidden-sm, .popover-helptip #menu .footer .icon-bottom-right.icon-help .button.hidden-sm, #menu .footer .popover-helptip .icon-bottom-right.icon-help .button.hidden-sm, .popover-helptip .icon.icon-bottom-center .button.hidden-sm, .popover-helptip .icon-bottom-center.icon-help .button.hidden-sm, .popover-helptip .icon-bottom-center.icon-alert .button.hidden-sm, .popover-helptip #menu .footer .icon-bottom-center.icon-help .button.hidden-sm, #menu .footer .popover-helptip .icon-bottom-center.icon-help .button.hidden-sm, - .pull-left .button.hidden-sm, .popover-helptip .icon.icon-left .button.hidden-sm, .popover-helptip .icon-left.icon-help .button.hidden-sm, .popover-helptip .icon-left.icon-alert .button.hidden-sm, .popover-helptip #menu .footer .icon-left.icon-help .button.hidden-sm, #menu .footer .popover-helptip .icon-left.icon-help .button.hidden-sm, .popover-helptip .icon.icon-bottom-left .button.hidden-sm, .popover-helptip .icon-bottom-left.icon-help .button.hidden-sm, .popover-helptip .icon-bottom-left.icon-alert .button.hidden-sm, .popover-helptip #menu .footer .icon-bottom-left.icon-help .button.hidden-sm, #menu .footer .popover-helptip .icon-bottom-left.icon-help .button.hidden-sm { + .pull-left .button.hidden-sm, + .popover-helptip .icon.icon-left .button.hidden-sm, + .popover-helptip .icon-left.icon-help .button.hidden-sm, + .popover-helptip .icon-left.icon-alert .button.hidden-sm, + .popover-helptip #menu .footer .icon-left.icon-help .button.hidden-sm, + #menu .footer .popover-helptip .icon-left.icon-help .button.hidden-sm, + .popover-helptip .icon.icon-bottom-left .button.hidden-sm, + .popover-helptip .icon-bottom-left.icon-help .button.hidden-sm, + .popover-helptip .icon-bottom-left.icon-alert .button.hidden-sm, + .popover-helptip #menu .footer .icon-bottom-left.icon-help .button.hidden-sm, + #menu .footer .popover-helptip .icon-bottom-left.icon-help .button.hidden-sm { display: inline-block; } } @media screen and (max-width: 767px) { @@ -13865,7 +14741,7 @@ a { display: inherit !important; visibility: visible !important; } .button.visible-sm { - display: block !important; } } + display: inline-block !important; } } @media screen and (min-width: 992px) { .visible-sm { @@ -13959,10 +14835,16 @@ a { @media screen and (min-width: 992px) { html, body, .scroll, .disable-user-behavior { - -webkit-user-selectuser-select: auto !important; + -webkit-user-select: auto !important; -moz-user-select: auto !important; -ms-user-select: auto !important; - user-select: auto !important; } } + user-select: auto !important; + -webkit-touch-callout: default !important; + -webkit-tap-highlight-color: #387ef5; + -webkit-user-drag: none !important; + touch-action: auto !important; + -ms-touch-action: auto !important; + -ms-content-zooming: none !important; } } /* ============ Left menu @@ -14002,6 +14884,13 @@ a { /********** Fix or extend generic CSS **********/ +html, body { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; } + .item.item-icon-right.item-select select, .item.item-icon-right .item-select select { right: 48px; @@ -14025,6 +14914,9 @@ a { .popover-share { width: auto; } } +.ios ion-content { + pointer-events: auto; } + .popover-share { height: 110px; } .popover-share .bar { @@ -14041,7 +14933,6 @@ a { text-align: left; } .popover-share .bar-header span { font-size: 10px; - margin: 5px; height: 20px; position: absolute; right: 0; @@ -14072,7 +14963,7 @@ a { outline: 0; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.3), 0 0 8px #08c; } .popover-share .list .item { - border-bottom: 0px !important; } + border-bottom: 0 !important; } /********** Notifications popover @@ -14094,131 +14985,131 @@ a { line-height: 30px; } .popover-light .bar-header .pull-right, .popover-light .bar-header .popover-helptip .icon.icon-right, .popover-helptip .popover-light .bar-header .icon.icon-right, .popover-light .bar-header .popover-helptip .icon-right.icon-help, .popover-helptip .popover-light .bar-header .icon-right.icon-help, .popover-light .bar-header .popover-helptip .icon-right.icon-alert, .popover-helptip .popover-light .bar-header .icon-right.icon-alert, .popover-light .bar-header .popover-helptip #menu .footer .icon-right.icon-help, .popover-helptip #menu .footer .popover-light .bar-header .icon-right.icon-help, .popover-light .bar-header #menu .footer .popover-helptip .icon-right.icon-help, #menu .footer .popover-helptip .popover-light .bar-header .icon-right.icon-help, .popover-light .bar-header .popover-helptip .icon.icon-center, .popover-helptip .popover-light .bar-header .icon.icon-center, .popover-light .bar-header .popover-helptip .icon-center.icon-help, .popover-helptip .popover-light .bar-header .icon-center.icon-help, .popover-light .bar-header .popover-helptip .icon-center.icon-alert, .popover-helptip .popover-light .bar-header .icon-center.icon-alert, .popover-light .bar-header .popover-helptip #menu .footer .icon-center.icon-help, .popover-helptip #menu .footer .popover-light .bar-header .icon-center.icon-help, .popover-light .bar-header #menu .footer .popover-helptip .icon-center.icon-help, #menu .footer .popover-helptip .popover-light .bar-header .icon-center.icon-help, .popover-light .bar-header .popover-helptip .icon.icon-bottom-right, .popover-helptip .popover-light .bar-header .icon.icon-bottom-right, .popover-light .bar-header .popover-helptip .icon-bottom-right.icon-help, .popover-helptip .popover-light .bar-header .icon-bottom-right.icon-help, .popover-light .bar-header .popover-helptip .icon-bottom-right.icon-alert, .popover-helptip .popover-light .bar-header .icon-bottom-right.icon-alert, .popover-light .bar-header .popover-helptip #menu .footer .icon-bottom-right.icon-help, .popover-helptip #menu .footer .popover-light .bar-header .icon-bottom-right.icon-help, .popover-light .bar-header #menu .footer .popover-helptip .icon-bottom-right.icon-help, #menu .footer .popover-helptip .popover-light .bar-header .icon-bottom-right.icon-help, .popover-light .bar-header .popover-helptip .icon.icon-bottom-center, .popover-helptip .popover-light .bar-header .icon.icon-bottom-center, .popover-light .bar-header .popover-helptip .icon-bottom-center.icon-help, .popover-helptip .popover-light .bar-header .icon-bottom-center.icon-help, .popover-light .bar-header .popover-helptip .icon-bottom-center.icon-alert, .popover-helptip .popover-light .bar-header .icon-bottom-center.icon-alert, .popover-light .bar-header .popover-helptip #menu .footer .icon-bottom-center.icon-help, .popover-helptip #menu .footer .popover-light .bar-header .icon-bottom-center.icon-help, .popover-light .bar-header #menu .footer .popover-helptip .icon-bottom-center.icon-help, #menu .footer .popover-helptip .popover-light .bar-header .icon-bottom-center.icon-help, .popover-light .bar-footer .pull-right, .popover-light .bar-footer .popover-helptip .icon.icon-right, .popover-helptip .popover-light .bar-footer .icon.icon-right, .popover-light .bar-footer .popover-helptip .icon-right.icon-help, .popover-helptip .popover-light .bar-footer .icon-right.icon-help, .popover-light .bar-footer .popover-helptip .icon-right.icon-alert, .popover-helptip .popover-light .bar-footer .icon-right.icon-alert, .popover-light .bar-footer .popover-helptip #menu .footer .icon-right.icon-help, .popover-helptip #menu .footer .popover-light .bar-footer .icon-right.icon-help, .popover-light .bar-footer #menu .footer .popover-helptip .icon-right.icon-help, #menu .footer .popover-helptip .popover-light .bar-footer .icon-right.icon-help, .popover-light .bar-footer .popover-helptip .icon.icon-center, .popover-helptip .popover-light .bar-footer .icon.icon-center, .popover-light .bar-footer .popover-helptip .icon-center.icon-help, .popover-helptip .popover-light .bar-footer .icon-center.icon-help, .popover-light .bar-footer .popover-helptip .icon-center.icon-alert, .popover-helptip .popover-light .bar-footer .icon-center.icon-alert, .popover-light .bar-footer .popover-helptip #menu .footer .icon-center.icon-help, .popover-helptip #menu .footer .popover-light .bar-footer .icon-center.icon-help, .popover-light .bar-footer #menu .footer .popover-helptip .icon-center.icon-help, #menu .footer .popover-helptip .popover-light .bar-footer .icon-center.icon-help, .popover-light .bar-footer .popover-helptip .icon.icon-bottom-right, .popover-helptip .popover-light .bar-footer .icon.icon-bottom-right, .popover-light .bar-footer .popover-helptip .icon-bottom-right.icon-help, .popover-helptip .popover-light .bar-footer .icon-bottom-right.icon-help, .popover-light .bar-footer .popover-helptip .icon-bottom-right.icon-alert, .popover-helptip .popover-light .bar-footer .icon-bottom-right.icon-alert, .popover-light .bar-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help, .popover-helptip #menu .footer .popover-light .bar-footer .icon-bottom-right.icon-help, .popover-light .bar-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help, #menu .footer .popover-helptip .popover-light .bar-footer .icon-bottom-right.icon-help, .popover-light .bar-footer .popover-helptip .icon.icon-bottom-center, .popover-helptip .popover-light .bar-footer .icon.icon-bottom-center, .popover-light .bar-footer .popover-helptip .icon-bottom-center.icon-help, .popover-helptip .popover-light .bar-footer .icon-bottom-center.icon-help, .popover-light .bar-footer .popover-helptip .icon-bottom-center.icon-alert, .popover-helptip .popover-light .bar-footer .icon-bottom-center.icon-alert, .popover-light .bar-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help, .popover-helptip #menu .footer .popover-light .bar-footer .icon-bottom-center.icon-help, .popover-light .bar-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help, #menu .footer .popover-helptip .popover-light .bar-footer .icon-bottom-center.icon-help, .popover-notification .bar-header .pull-right, - .popover-notification .bar-header .popover-helptip .icon.icon-right, .popover-helptip - .popover-notification .bar-header .icon.icon-right, - .popover-notification .bar-header .popover-helptip .icon-right.icon-help, .popover-helptip - .popover-notification .bar-header .icon-right.icon-help, - .popover-notification .bar-header .popover-helptip .icon-right.icon-alert, .popover-helptip - .popover-notification .bar-header .icon-right.icon-alert, - .popover-notification .bar-header .popover-helptip #menu .footer .icon-right.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-header .icon-right.icon-help, - .popover-notification .bar-header #menu .footer .popover-helptip .icon-right.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-header .icon-right.icon-help, - .popover-notification .bar-header .popover-helptip .icon.icon-center, .popover-helptip - .popover-notification .bar-header .icon.icon-center, - .popover-notification .bar-header .popover-helptip .icon-center.icon-help, .popover-helptip - .popover-notification .bar-header .icon-center.icon-help, - .popover-notification .bar-header .popover-helptip .icon-center.icon-alert, .popover-helptip - .popover-notification .bar-header .icon-center.icon-alert, - .popover-notification .bar-header .popover-helptip #menu .footer .icon-center.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-header .icon-center.icon-help, - .popover-notification .bar-header #menu .footer .popover-helptip .icon-center.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-header .icon-center.icon-help, - .popover-notification .bar-header .popover-helptip .icon.icon-bottom-right, .popover-helptip - .popover-notification .bar-header .icon.icon-bottom-right, - .popover-notification .bar-header .popover-helptip .icon-bottom-right.icon-help, .popover-helptip - .popover-notification .bar-header .icon-bottom-right.icon-help, - .popover-notification .bar-header .popover-helptip .icon-bottom-right.icon-alert, .popover-helptip - .popover-notification .bar-header .icon-bottom-right.icon-alert, - .popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-right.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-header .icon-bottom-right.icon-help, - .popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-right.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-header .icon-bottom-right.icon-help, - .popover-notification .bar-header .popover-helptip .icon.icon-bottom-center, .popover-helptip - .popover-notification .bar-header .icon.icon-bottom-center, - .popover-notification .bar-header .popover-helptip .icon-bottom-center.icon-help, .popover-helptip - .popover-notification .bar-header .icon-bottom-center.icon-help, - .popover-notification .bar-header .popover-helptip .icon-bottom-center.icon-alert, .popover-helptip - .popover-notification .bar-header .icon-bottom-center.icon-alert, - .popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-center.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-header .icon-bottom-center.icon-help, - .popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-center.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-header .icon-bottom-center.icon-help, + .popover-notification .bar-header .popover-helptip .icon.icon-right, + .popover-helptip .popover-notification .bar-header .icon.icon-right, + .popover-notification .bar-header .popover-helptip .icon-right.icon-help, + .popover-helptip .popover-notification .bar-header .icon-right.icon-help, + .popover-notification .bar-header .popover-helptip .icon-right.icon-alert, + .popover-helptip .popover-notification .bar-header .icon-right.icon-alert, + .popover-notification .bar-header .popover-helptip #menu .footer .icon-right.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-header .icon-right.icon-help, + .popover-notification .bar-header #menu .footer .popover-helptip .icon-right.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-header .icon-right.icon-help, + .popover-notification .bar-header .popover-helptip .icon.icon-center, + .popover-helptip .popover-notification .bar-header .icon.icon-center, + .popover-notification .bar-header .popover-helptip .icon-center.icon-help, + .popover-helptip .popover-notification .bar-header .icon-center.icon-help, + .popover-notification .bar-header .popover-helptip .icon-center.icon-alert, + .popover-helptip .popover-notification .bar-header .icon-center.icon-alert, + .popover-notification .bar-header .popover-helptip #menu .footer .icon-center.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-header .icon-center.icon-help, + .popover-notification .bar-header #menu .footer .popover-helptip .icon-center.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-header .icon-center.icon-help, + .popover-notification .bar-header .popover-helptip .icon.icon-bottom-right, + .popover-helptip .popover-notification .bar-header .icon.icon-bottom-right, + .popover-notification .bar-header .popover-helptip .icon-bottom-right.icon-help, + .popover-helptip .popover-notification .bar-header .icon-bottom-right.icon-help, + .popover-notification .bar-header .popover-helptip .icon-bottom-right.icon-alert, + .popover-helptip .popover-notification .bar-header .icon-bottom-right.icon-alert, + .popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-right.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-header .icon-bottom-right.icon-help, + .popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-right.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-header .icon-bottom-right.icon-help, + .popover-notification .bar-header .popover-helptip .icon.icon-bottom-center, + .popover-helptip .popover-notification .bar-header .icon.icon-bottom-center, + .popover-notification .bar-header .popover-helptip .icon-bottom-center.icon-help, + .popover-helptip .popover-notification .bar-header .icon-bottom-center.icon-help, + .popover-notification .bar-header .popover-helptip .icon-bottom-center.icon-alert, + .popover-helptip .popover-notification .bar-header .icon-bottom-center.icon-alert, + .popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-center.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-header .icon-bottom-center.icon-help, + .popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-center.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-header .icon-bottom-center.icon-help, .popover-notification .bar-footer .pull-right, - .popover-notification .bar-footer .popover-helptip .icon.icon-right, .popover-helptip - .popover-notification .bar-footer .icon.icon-right, - .popover-notification .bar-footer .popover-helptip .icon-right.icon-help, .popover-helptip - .popover-notification .bar-footer .icon-right.icon-help, - .popover-notification .bar-footer .popover-helptip .icon-right.icon-alert, .popover-helptip - .popover-notification .bar-footer .icon-right.icon-alert, - .popover-notification .bar-footer .popover-helptip #menu .footer .icon-right.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-footer .icon-right.icon-help, - .popover-notification .bar-footer #menu .footer .popover-helptip .icon-right.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-footer .icon-right.icon-help, - .popover-notification .bar-footer .popover-helptip .icon.icon-center, .popover-helptip - .popover-notification .bar-footer .icon.icon-center, - .popover-notification .bar-footer .popover-helptip .icon-center.icon-help, .popover-helptip - .popover-notification .bar-footer .icon-center.icon-help, - .popover-notification .bar-footer .popover-helptip .icon-center.icon-alert, .popover-helptip - .popover-notification .bar-footer .icon-center.icon-alert, - .popover-notification .bar-footer .popover-helptip #menu .footer .icon-center.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-footer .icon-center.icon-help, - .popover-notification .bar-footer #menu .footer .popover-helptip .icon-center.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-footer .icon-center.icon-help, - .popover-notification .bar-footer .popover-helptip .icon.icon-bottom-right, .popover-helptip - .popover-notification .bar-footer .icon.icon-bottom-right, - .popover-notification .bar-footer .popover-helptip .icon-bottom-right.icon-help, .popover-helptip - .popover-notification .bar-footer .icon-bottom-right.icon-help, - .popover-notification .bar-footer .popover-helptip .icon-bottom-right.icon-alert, .popover-helptip - .popover-notification .bar-footer .icon-bottom-right.icon-alert, - .popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-footer .icon-bottom-right.icon-help, - .popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-footer .icon-bottom-right.icon-help, - .popover-notification .bar-footer .popover-helptip .icon.icon-bottom-center, .popover-helptip - .popover-notification .bar-footer .icon.icon-bottom-center, - .popover-notification .bar-footer .popover-helptip .icon-bottom-center.icon-help, .popover-helptip - .popover-notification .bar-footer .icon-bottom-center.icon-help, - .popover-notification .bar-footer .popover-helptip .icon-bottom-center.icon-alert, .popover-helptip - .popover-notification .bar-footer .icon-bottom-center.icon-alert, - .popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-footer .icon-bottom-center.icon-help, - .popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-footer .icon-bottom-center.icon-help { + .popover-notification .bar-footer .popover-helptip .icon.icon-right, + .popover-helptip .popover-notification .bar-footer .icon.icon-right, + .popover-notification .bar-footer .popover-helptip .icon-right.icon-help, + .popover-helptip .popover-notification .bar-footer .icon-right.icon-help, + .popover-notification .bar-footer .popover-helptip .icon-right.icon-alert, + .popover-helptip .popover-notification .bar-footer .icon-right.icon-alert, + .popover-notification .bar-footer .popover-helptip #menu .footer .icon-right.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-footer .icon-right.icon-help, + .popover-notification .bar-footer #menu .footer .popover-helptip .icon-right.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-footer .icon-right.icon-help, + .popover-notification .bar-footer .popover-helptip .icon.icon-center, + .popover-helptip .popover-notification .bar-footer .icon.icon-center, + .popover-notification .bar-footer .popover-helptip .icon-center.icon-help, + .popover-helptip .popover-notification .bar-footer .icon-center.icon-help, + .popover-notification .bar-footer .popover-helptip .icon-center.icon-alert, + .popover-helptip .popover-notification .bar-footer .icon-center.icon-alert, + .popover-notification .bar-footer .popover-helptip #menu .footer .icon-center.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-footer .icon-center.icon-help, + .popover-notification .bar-footer #menu .footer .popover-helptip .icon-center.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-footer .icon-center.icon-help, + .popover-notification .bar-footer .popover-helptip .icon.icon-bottom-right, + .popover-helptip .popover-notification .bar-footer .icon.icon-bottom-right, + .popover-notification .bar-footer .popover-helptip .icon-bottom-right.icon-help, + .popover-helptip .popover-notification .bar-footer .icon-bottom-right.icon-help, + .popover-notification .bar-footer .popover-helptip .icon-bottom-right.icon-alert, + .popover-helptip .popover-notification .bar-footer .icon-bottom-right.icon-alert, + .popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-footer .icon-bottom-right.icon-help, + .popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-footer .icon-bottom-right.icon-help, + .popover-notification .bar-footer .popover-helptip .icon.icon-bottom-center, + .popover-helptip .popover-notification .bar-footer .icon.icon-bottom-center, + .popover-notification .bar-footer .popover-helptip .icon-bottom-center.icon-help, + .popover-helptip .popover-notification .bar-footer .icon-bottom-center.icon-help, + .popover-notification .bar-footer .popover-helptip .icon-bottom-center.icon-alert, + .popover-helptip .popover-notification .bar-footer .icon-bottom-center.icon-alert, + .popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-footer .icon-bottom-center.icon-help, + .popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-footer .icon-bottom-center.icon-help { margin-right: 10px; } .popover-light .bar-header .pull-left, .popover-light .bar-header .popover-helptip .icon.icon-left, .popover-helptip .popover-light .bar-header .icon.icon-left, .popover-light .bar-header .popover-helptip .icon-left.icon-help, .popover-helptip .popover-light .bar-header .icon-left.icon-help, .popover-light .bar-header .popover-helptip .icon-left.icon-alert, .popover-helptip .popover-light .bar-header .icon-left.icon-alert, .popover-light .bar-header .popover-helptip #menu .footer .icon-left.icon-help, .popover-helptip #menu .footer .popover-light .bar-header .icon-left.icon-help, .popover-light .bar-header #menu .footer .popover-helptip .icon-left.icon-help, #menu .footer .popover-helptip .popover-light .bar-header .icon-left.icon-help, .popover-light .bar-header .popover-helptip .icon.icon-bottom-left, .popover-helptip .popover-light .bar-header .icon.icon-bottom-left, .popover-light .bar-header .popover-helptip .icon-bottom-left.icon-help, .popover-helptip .popover-light .bar-header .icon-bottom-left.icon-help, .popover-light .bar-header .popover-helptip .icon-bottom-left.icon-alert, .popover-helptip .popover-light .bar-header .icon-bottom-left.icon-alert, .popover-light .bar-header .popover-helptip #menu .footer .icon-bottom-left.icon-help, .popover-helptip #menu .footer .popover-light .bar-header .icon-bottom-left.icon-help, .popover-light .bar-header #menu .footer .popover-helptip .icon-bottom-left.icon-help, #menu .footer .popover-helptip .popover-light .bar-header .icon-bottom-left.icon-help, .popover-light .bar-footer .pull-left, .popover-light .bar-footer .popover-helptip .icon.icon-left, .popover-helptip .popover-light .bar-footer .icon.icon-left, .popover-light .bar-footer .popover-helptip .icon-left.icon-help, .popover-helptip .popover-light .bar-footer .icon-left.icon-help, .popover-light .bar-footer .popover-helptip .icon-left.icon-alert, .popover-helptip .popover-light .bar-footer .icon-left.icon-alert, .popover-light .bar-footer .popover-helptip #menu .footer .icon-left.icon-help, .popover-helptip #menu .footer .popover-light .bar-footer .icon-left.icon-help, .popover-light .bar-footer #menu .footer .popover-helptip .icon-left.icon-help, #menu .footer .popover-helptip .popover-light .bar-footer .icon-left.icon-help, .popover-light .bar-footer .popover-helptip .icon.icon-bottom-left, .popover-helptip .popover-light .bar-footer .icon.icon-bottom-left, .popover-light .bar-footer .popover-helptip .icon-bottom-left.icon-help, .popover-helptip .popover-light .bar-footer .icon-bottom-left.icon-help, .popover-light .bar-footer .popover-helptip .icon-bottom-left.icon-alert, .popover-helptip .popover-light .bar-footer .icon-bottom-left.icon-alert, .popover-light .bar-footer .popover-helptip #menu .footer .icon-bottom-left.icon-help, .popover-helptip #menu .footer .popover-light .bar-footer .icon-bottom-left.icon-help, .popover-light .bar-footer #menu .footer .popover-helptip .icon-bottom-left.icon-help, #menu .footer .popover-helptip .popover-light .bar-footer .icon-bottom-left.icon-help, .popover-notification .bar-header .pull-left, - .popover-notification .bar-header .popover-helptip .icon.icon-left, .popover-helptip - .popover-notification .bar-header .icon.icon-left, - .popover-notification .bar-header .popover-helptip .icon-left.icon-help, .popover-helptip - .popover-notification .bar-header .icon-left.icon-help, - .popover-notification .bar-header .popover-helptip .icon-left.icon-alert, .popover-helptip - .popover-notification .bar-header .icon-left.icon-alert, - .popover-notification .bar-header .popover-helptip #menu .footer .icon-left.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-header .icon-left.icon-help, - .popover-notification .bar-header #menu .footer .popover-helptip .icon-left.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-header .icon-left.icon-help, - .popover-notification .bar-header .popover-helptip .icon.icon-bottom-left, .popover-helptip - .popover-notification .bar-header .icon.icon-bottom-left, - .popover-notification .bar-header .popover-helptip .icon-bottom-left.icon-help, .popover-helptip - .popover-notification .bar-header .icon-bottom-left.icon-help, - .popover-notification .bar-header .popover-helptip .icon-bottom-left.icon-alert, .popover-helptip - .popover-notification .bar-header .icon-bottom-left.icon-alert, - .popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-left.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-header .icon-bottom-left.icon-help, - .popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-left.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-header .icon-bottom-left.icon-help, + .popover-notification .bar-header .popover-helptip .icon.icon-left, + .popover-helptip .popover-notification .bar-header .icon.icon-left, + .popover-notification .bar-header .popover-helptip .icon-left.icon-help, + .popover-helptip .popover-notification .bar-header .icon-left.icon-help, + .popover-notification .bar-header .popover-helptip .icon-left.icon-alert, + .popover-helptip .popover-notification .bar-header .icon-left.icon-alert, + .popover-notification .bar-header .popover-helptip #menu .footer .icon-left.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-header .icon-left.icon-help, + .popover-notification .bar-header #menu .footer .popover-helptip .icon-left.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-header .icon-left.icon-help, + .popover-notification .bar-header .popover-helptip .icon.icon-bottom-left, + .popover-helptip .popover-notification .bar-header .icon.icon-bottom-left, + .popover-notification .bar-header .popover-helptip .icon-bottom-left.icon-help, + .popover-helptip .popover-notification .bar-header .icon-bottom-left.icon-help, + .popover-notification .bar-header .popover-helptip .icon-bottom-left.icon-alert, + .popover-helptip .popover-notification .bar-header .icon-bottom-left.icon-alert, + .popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-left.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-header .icon-bottom-left.icon-help, + .popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-left.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-header .icon-bottom-left.icon-help, .popover-notification .bar-footer .pull-left, - .popover-notification .bar-footer .popover-helptip .icon.icon-left, .popover-helptip - .popover-notification .bar-footer .icon.icon-left, - .popover-notification .bar-footer .popover-helptip .icon-left.icon-help, .popover-helptip - .popover-notification .bar-footer .icon-left.icon-help, - .popover-notification .bar-footer .popover-helptip .icon-left.icon-alert, .popover-helptip - .popover-notification .bar-footer .icon-left.icon-alert, - .popover-notification .bar-footer .popover-helptip #menu .footer .icon-left.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-footer .icon-left.icon-help, - .popover-notification .bar-footer #menu .footer .popover-helptip .icon-left.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-footer .icon-left.icon-help, - .popover-notification .bar-footer .popover-helptip .icon.icon-bottom-left, .popover-helptip - .popover-notification .bar-footer .icon.icon-bottom-left, - .popover-notification .bar-footer .popover-helptip .icon-bottom-left.icon-help, .popover-helptip - .popover-notification .bar-footer .icon-bottom-left.icon-help, - .popover-notification .bar-footer .popover-helptip .icon-bottom-left.icon-alert, .popover-helptip - .popover-notification .bar-footer .icon-bottom-left.icon-alert, - .popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-left.icon-help, .popover-helptip #menu .footer - .popover-notification .bar-footer .icon-bottom-left.icon-help, - .popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-left.icon-help, #menu .footer .popover-helptip - .popover-notification .bar-footer .icon-bottom-left.icon-help { + .popover-notification .bar-footer .popover-helptip .icon.icon-left, + .popover-helptip .popover-notification .bar-footer .icon.icon-left, + .popover-notification .bar-footer .popover-helptip .icon-left.icon-help, + .popover-helptip .popover-notification .bar-footer .icon-left.icon-help, + .popover-notification .bar-footer .popover-helptip .icon-left.icon-alert, + .popover-helptip .popover-notification .bar-footer .icon-left.icon-alert, + .popover-notification .bar-footer .popover-helptip #menu .footer .icon-left.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-footer .icon-left.icon-help, + .popover-notification .bar-footer #menu .footer .popover-helptip .icon-left.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-footer .icon-left.icon-help, + .popover-notification .bar-footer .popover-helptip .icon.icon-bottom-left, + .popover-helptip .popover-notification .bar-footer .icon.icon-bottom-left, + .popover-notification .bar-footer .popover-helptip .icon-bottom-left.icon-help, + .popover-helptip .popover-notification .bar-footer .icon-bottom-left.icon-help, + .popover-notification .bar-footer .popover-helptip .icon-bottom-left.icon-alert, + .popover-helptip .popover-notification .bar-footer .icon-bottom-left.icon-alert, + .popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-left.icon-help, + .popover-helptip #menu .footer .popover-notification .bar-footer .icon-bottom-left.icon-help, + .popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-left.icon-help, + #menu .footer .popover-helptip .popover-notification .bar-footer .icon-bottom-left.icon-help { margin-left: 10px; } .popover-light .bar-header a, .popover-light .bar-footer a, .popover-notification .bar-header a, @@ -14247,8 +15138,8 @@ a { .popover-notification .item-avatar h4 i.icon, .popover-notification .item-avatar h4 i.icon-help, .popover-notification .item-avatar h4 i.icon-alert, - .popover-notification .item-avatar h4 #menu .footer i.icon-help, #menu .footer - .popover-notification .item-avatar h4 i.icon-help { + .popover-notification .item-avatar h4 #menu .footer i.icon-help, + #menu .footer .popover-notification .item-avatar h4 i.icon-help { font-size: 18px !important; line-height: 12px !important; vertical-align: middle !important; } @@ -14274,12 +15165,17 @@ a { .popover-peer-info { width: 420px; } +.popover-wallets .item-avatar { + padding-left: 95px !important; } + .popover-wallets .item-avatar .icon:last-child, .popover-wallets .item-avatar .icon-help:last-child, .popover-wallets .item-avatar .icon-alert:last-child, .popover-wallets .item-avatar #menu .footer .icon-help:last-child, #menu .footer .popover-wallets .item-avatar .icon-help:last-child { + display: none; } + /********** Network **********/ .popover-peer-info .item .badge, .popover-endpoints .item .badge { - right: 16px; } + right: 16px !important; } .popover-peer-info .item .badge.badge-secondary, .popover-endpoints .item .badge.badge-secondary { @@ -14313,7 +15209,69 @@ a { padding-left: 8px; padding-right: 8px; } -.bar .buttons.pull-right, .bar .popover-helptip .buttons.icon.icon-right, .popover-helptip .bar .buttons.icon.icon-right, .bar .popover-helptip .buttons.icon-right.icon-help, .popover-helptip .bar .buttons.icon-right.icon-help, .bar .popover-helptip .buttons.icon-right.icon-alert, .popover-helptip .bar .buttons.icon-right.icon-alert, .bar .popover-helptip #menu .footer .buttons.icon-right.icon-help, .popover-helptip #menu .footer .bar .buttons.icon-right.icon-help, .bar #menu .footer .popover-helptip .buttons.icon-right.icon-help, #menu .footer .popover-helptip .bar .buttons.icon-right.icon-help, .bar .popover-helptip .buttons.icon.icon-center, .popover-helptip .bar .buttons.icon.icon-center, .bar .popover-helptip .buttons.icon-center.icon-help, .popover-helptip .bar .buttons.icon-center.icon-help, .bar .popover-helptip .buttons.icon-center.icon-alert, .popover-helptip .bar .buttons.icon-center.icon-alert, .bar .popover-helptip #menu .footer .buttons.icon-center.icon-help, .popover-helptip #menu .footer .bar .buttons.icon-center.icon-help, .bar #menu .footer .popover-helptip .buttons.icon-center.icon-help, #menu .footer .popover-helptip .bar .buttons.icon-center.icon-help, .bar .popover-helptip .buttons.icon.icon-bottom-right, .popover-helptip .bar .buttons.icon.icon-bottom-right, .bar .popover-helptip .buttons.icon-bottom-right.icon-help, .popover-helptip .bar .buttons.icon-bottom-right.icon-help, .bar .popover-helptip .buttons.icon-bottom-right.icon-alert, .popover-helptip .bar .buttons.icon-bottom-right.icon-alert, .bar .popover-helptip #menu .footer .buttons.icon-bottom-right.icon-help, .popover-helptip #menu .footer .bar .buttons.icon-bottom-right.icon-help, .bar #menu .footer .popover-helptip .buttons.icon-bottom-right.icon-help, #menu .footer .popover-helptip .bar .buttons.icon-bottom-right.icon-help, .bar .popover-helptip .buttons.icon.icon-bottom-center, .popover-helptip .bar .buttons.icon.icon-bottom-center, .bar .popover-helptip .buttons.icon-bottom-center.icon-help, .popover-helptip .bar .buttons.icon-bottom-center.icon-help, .bar .popover-helptip .buttons.icon-bottom-center.icon-alert, .popover-helptip .bar .buttons.icon-bottom-center.icon-alert, .bar .popover-helptip #menu .footer .buttons.icon-bottom-center.icon-help, .popover-helptip #menu .footer .bar .buttons.icon-bottom-center.icon-help, .bar #menu .footer .popover-helptip .buttons.icon-bottom-center.icon-help, #menu .footer .popover-helptip .bar .buttons.icon-bottom-center.icon-help, .bar .title + .button:last-child, .bar .title + .buttons, .bar > .button + .button:last-child, .bar > .button.pull-right, .popover-helptip .bar > .button.icon.icon-right, .popover-helptip .bar > .button.icon-right.icon-help, .popover-helptip .bar > .button.icon-right.icon-alert, .popover-helptip #menu .footer .bar > .button.icon-right.icon-help, #menu .footer .popover-helptip .bar > .button.icon-right.icon-help, .popover-helptip .bar > .button.icon.icon-center, .popover-helptip .bar > .button.icon-center.icon-help, .popover-helptip .bar > .button.icon-center.icon-alert, .popover-helptip #menu .footer .bar > .button.icon-center.icon-help, #menu .footer .popover-helptip .bar > .button.icon-center.icon-help, .popover-helptip .bar > .button.icon.icon-bottom-right, .popover-helptip .bar > .button.icon-bottom-right.icon-help, .popover-helptip .bar > .button.icon-bottom-right.icon-alert, .popover-helptip #menu .footer .bar > .button.icon-bottom-right.icon-help, #menu .footer .popover-helptip .bar > .button.icon-bottom-right.icon-help, .popover-helptip .bar > .button.icon.icon-bottom-center, .popover-helptip .bar > .button.icon-bottom-center.icon-help, .popover-helptip .bar > .button.icon-bottom-center.icon-alert, .popover-helptip #menu .footer .bar > .button.icon-bottom-center.icon-help, #menu .footer .popover-helptip .bar > .button.icon-bottom-center.icon-help { + +.bar .buttons.pull-right, +.bar .popover-helptip .buttons.icon.icon-right, +.popover-helptip .bar .buttons.icon.icon-right, +.bar .popover-helptip .buttons.icon-right.icon-help, +.popover-helptip .bar .buttons.icon-right.icon-help, +.bar .popover-helptip .buttons.icon-right.icon-alert, +.popover-helptip .bar .buttons.icon-right.icon-alert, +.bar .popover-helptip #menu .footer .buttons.icon-right.icon-help, +.popover-helptip #menu .footer .bar .buttons.icon-right.icon-help, +.bar #menu .footer .popover-helptip .buttons.icon-right.icon-help, +#menu .footer .popover-helptip .bar .buttons.icon-right.icon-help, +.bar .popover-helptip .buttons.icon.icon-center, +.popover-helptip .bar .buttons.icon.icon-center, +.bar .popover-helptip .buttons.icon-center.icon-help, +.popover-helptip .bar .buttons.icon-center.icon-help, +.bar .popover-helptip .buttons.icon-center.icon-alert, +.popover-helptip .bar .buttons.icon-center.icon-alert, +.bar .popover-helptip #menu .footer .buttons.icon-center.icon-help, +.popover-helptip #menu .footer .bar .buttons.icon-center.icon-help, +.bar #menu .footer .popover-helptip .buttons.icon-center.icon-help, +#menu .footer .popover-helptip .bar .buttons.icon-center.icon-help, +.bar .popover-helptip .buttons.icon.icon-bottom-right, +.popover-helptip .bar .buttons.icon.icon-bottom-right, +.bar .popover-helptip .buttons.icon-bottom-right.icon-help, +.popover-helptip .bar .buttons.icon-bottom-right.icon-help, +.bar .popover-helptip .buttons.icon-bottom-right.icon-alert, +.popover-helptip .bar .buttons.icon-bottom-right.icon-alert, +.bar .popover-helptip #menu .footer .buttons.icon-bottom-right.icon-help, +.popover-helptip #menu .footer .bar .buttons.icon-bottom-right.icon-help, +.bar #menu .footer .popover-helptip .buttons.icon-bottom-right.icon-help, +#menu .footer .popover-helptip .bar .buttons.icon-bottom-right.icon-help, +.bar .popover-helptip .buttons.icon.icon-bottom-center, +.popover-helptip .bar .buttons.icon.icon-bottom-center, +.bar .popover-helptip .buttons.icon-bottom-center.icon-help, +.popover-helptip .bar .buttons.icon-bottom-center.icon-help, +.bar .popover-helptip .buttons.icon-bottom-center.icon-alert, +.popover-helptip .bar .buttons.icon-bottom-center.icon-alert, +.bar .popover-helptip #menu .footer .buttons.icon-bottom-center.icon-help, +.popover-helptip #menu .footer .bar .buttons.icon-bottom-center.icon-help, +.bar #menu .footer .popover-helptip .buttons.icon-bottom-center.icon-help, +#menu .footer .popover-helptip .bar .buttons.icon-bottom-center.icon-help, .bar .title + .button:last-child, .bar .title + .buttons, .bar > .button + .button:last-child, +.bar > .button.pull-right, +.popover-helptip .bar > .button.icon.icon-right, +.popover-helptip .bar > .button.icon-right.icon-help, +.popover-helptip .bar > .button.icon-right.icon-alert, +.popover-helptip #menu .footer .bar > .button.icon-right.icon-help, +#menu .footer .popover-helptip .bar > .button.icon-right.icon-help, +.popover-helptip .bar > .button.icon.icon-center, +.popover-helptip .bar > .button.icon-center.icon-help, +.popover-helptip .bar > .button.icon-center.icon-alert, +.popover-helptip #menu .footer .bar > .button.icon-center.icon-help, +#menu .footer .popover-helptip .bar > .button.icon-center.icon-help, +.popover-helptip .bar > .button.icon.icon-bottom-right, +.popover-helptip .bar > .button.icon-bottom-right.icon-help, +.popover-helptip .bar > .button.icon-bottom-right.icon-alert, +.popover-helptip #menu .footer .bar > .button.icon-bottom-right.icon-help, +#menu .footer .popover-helptip .bar > .button.icon-bottom-right.icon-help, +.popover-helptip .bar > .button.icon.icon-bottom-center, +.popover-helptip .bar > .button.icon-bottom-center.icon-help, +.popover-helptip .bar > .button.icon-bottom-center.icon-alert, +.popover-helptip #menu .footer .bar > .button.icon-bottom-center.icon-help, +#menu .footer .popover-helptip .bar > .button.icon-bottom-center.icon-help { top: 0px !important; } .bar.bar-header { @@ -14351,6 +15309,10 @@ a { padding-right: 32px !important; line-height: 42px; } +.button-fab-bottom-left.has-footer, +.button-fab-bottom-right.has-footer { + bottom: 64px !important; } + /* ============ Home page =============== */ @@ -14399,41 +15361,20 @@ a { background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA1MDAgNTAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOmJ4PSJodHRwczovL2JveHktc3ZnLmNvbSI+CiAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoMC42MDgyNjEsIDAsIDAsIDAuNjA4MjYxLCAtMjAuMDg0OTc2LCAzLjI1NTczNikiPgogICAgPGc+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC43ODsiIGlkPSJwYXRoLTEwIiBkPSJNIDQxOS4xMzMgODUuNzM4IEMgNDE3LjI5NSA4NS43MzkgNDE1LjQ1NSA4NS43NTQgNDEzLjYxMSA4NS43NzggQyAzNTQuODUyIDg2LjU2MSAyOTkuMDIzIDk5LjE3NCAyNDguMzU4IDEyMS4zMiBDIDU4NC4xMjEgMTMuMjA2IDc5Ni4xNzUgMjExLjI2IDgzMS43IDUwOC43NzMgTCA4NDYuMzgzIDUwNy4xMjQgQyA4MTUuNTg2IDIzNS44MDEgNjUyLjQ3NyA4NS41ODggNDE5LjEzMyA4NS43MzggWiIgdHJhbnNmb3JtPSJtYXRyaXgoMC45NjM3MywgMC4yNjY4NzgsIC0wLjI2Njg3OCwgMC45NjM3MywgODkuNTA1MjMxLCAtMTM2LjYxNTA2MSkiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDE7IiBpZD0icGF0aC0zIiBkPSJNIDE0Ni4wMzcgMTk0LjA2NSBDIDE0NC4yMDEgMTk0LjA2NiAxNDIuMzYxIDE5NC4wODEgMTQwLjUxNyAxOTQuMTA0IEMgODEuNzYgMTk0Ljg4OCAyNS45MzEgMjA3LjUwMyAtMjQuNzM2IDIyOS42NDggQyAzMTEuMDI5IDEyMS41MzEgNTIzLjA4MyAzMTkuNTgzIDU1OC42MDQgNjE3LjA5MyBMIDU3My4yODQgNjE1LjQ0MyBDIDU0Mi40OSAzNDQuMTIyIDM3OS4zODUgMTkzLjkxMyAxNDYuMDM3IDE5NC4wNjUgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuMTgwOTg4LCAtMC45ODM0ODUsIDAuOTgzNDg1LCAtMC4xODA5ODgsIC0zOS4yOTg1ODEsIDcwNS44OTc1NDQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMSIgZD0iTSA0ODcuNzQ0IDE5My4wODQgQyA0ODUuOTA2IDE5My4wODUgNDg0LjA2NyAxOTMuMSA0ODIuMjIzIDE5My4xMjMgQyA0MjMuNDY0IDE5My45MDcgMzY3LjYzNSAyMDYuNTIgMzE2Ljk3NSAyMjguNjY4IEMgNjUyLjcyNiAxMjAuNTUyIDg2NC43NzUgMzE4LjYwNSA5MDAuMjk5IDYxNi4xMDkgTCA5MTQuOTc5IDYxNC40NiBDIDg4NC4xODQgMzQzLjE0NCA3MjEuMDgxIDE5Mi45MzUgNDg3Ljc0NCAxOTMuMDg0IFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNjE5OTk3LCAwLjc4NDYwNSwgLTAuNzg0NjA1LCAwLjYxOTk5NywgNTIzLjA2NzIzMSwgLTM0My4zMzE1MzkpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjg0OyIgaWQ9InBhdGgtMTIiIGQ9Ik0gMjk1Ljk2OSA0MzIuNzU3IEMgMjk0LjEzMSA0MzIuNzU4IDI5Mi4yOTMgNDMyLjc3MyAyOTAuNDQ5IDQzMi43OTcgQyAyMzEuNjg4IDQzMy41OCAxNzUuODYgNDQ2LjE5NCAxMjUuMTk4IDQ2OC4zNDEgQyA0NjAuOTU3IDM2MC4yMjYgNjczLjAwNSA1NTguMjggNzA4LjUyNiA4NTUuNzg2IEwgNzIzLjIwNyA4NTQuMTM5IEMgNjkyLjQxMiA1ODIuODE5IDUyOS4zMSA0MzIuNjA5IDI5NS45NjkgNDMyLjc1NyBaIiB0cmFuc2Zvcm09Im1hdHJpeCgtMC45Nzg4NDksIDAuMjA0NTg0LCAtMC4yMDQ1ODQsIC0wLjk3ODg0OSwgOTYzLjgyMDc5NiwgMTExNi4zNjcyOTMpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMyIgZD0iTSAxNTguMDM2IDE0OC44MyBDIDE1Ni4yIDE0OC44MzMgMTU0LjM2IDE0OC44NDYgMTUyLjUxNiAxNDguODcyIEMgOTMuNzU5IDE0OS42NTMgMzcuOTMgMTYyLjI2NyAtMTIuNzM0IDE4NC40MTEgQyAzMjMuMDIyIDc2LjMwMSA1MzUuMDc2IDI3NC4zNTIgNTcwLjYwNCA1NzEuODU3IEwgNTg1LjI4NiA1NzAuMjA4IEMgNTU0LjQ4MyAyOTguODkxIDM5MS4zOCAxNDguNjgzIDE1OC4wMzYgMTQ4LjgzIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuMzM4NjE0LCAtMC45NDA5MjYsIDAuOTQwOTI2LCAwLjMzODYxNCwgLTExNS41OTUxNTgsIDQ4My43MDU5ODQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAxOyIgaWQ9InBhdGgtMTQiIGQ9Ik0gNTAxLjAxOSAyODguMjkyIEMgNDk5LjE4MSAyODguMjkzIDQ5Ny4zNCAyODguMzA4IDQ5NS40OTYgMjg4LjMzMSBDIDQzNi43MzYgMjg5LjExNSAzODAuOTA4IDMwMS43MjYgMzMwLjI0MyAzMjMuODc0IEMgNjY2LjAwNCAyMTUuNzU3IDg3OC4wNjIgNDEzLjgxMiA5MTMuNTg2IDcxMS4zMjIgTCA5MjguMjY4IDcwOS42NzMgQyA4OTcuNDY4IDQzOC4zNTIgNzM0LjM2MSAyODguMTQxIDUwMS4wMTkgMjg4LjI5MiBaIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjE2NDY1NiwgMC45ODYzNTEsIC0wLjk4NjM1MSwgMC4xNjQ2NTYsIDk4Mi44NTcyNjYsIC0yMzMuNDUyMDYzKSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC40OyIgaWQ9InBhdGgtMTUiIGQ9Ik0gMTkyLjk1NCAzNzYuNTIxIEMgMTkxLjExNSAzNzYuNTIyIDE4OS4yNzcgMzc2LjUzNyAxODcuNDMzIDM3Ni41NjEgQyAxMjguNjc0IDM3Ny4zNDQgNzIuODQ1IDM4OS45NTggMjIuMTgxIDQxMi4xMDMgQyAzNTcuOTQgMzAzLjk4OSA1NjkuOTg3IDUwMi4wNDUgNjA1LjUwNSA3OTkuNTUzIEwgNjIwLjE4OCA3OTcuOTA1IEMgNTg5LjM5MiA1MjYuNTg0IDQyNi4yOTUgMzc2LjM2OSAxOTIuOTU0IDM3Ni41MjEgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuOTMxNDA0LCAtMC4zNjM5ODgsIDAuMzYzOTg4LCAtMC45MzE0MDQsIDQxOS40OTkwMDYsIDExODIuNTk5ODA5KSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMTsiIGlkPSJwYXRoLTE2IiBkPSJNIDIyMS42MTQgNjMuOTczIEMgMjE5Ljc3NyA2My45NzYgMjE3LjkzOCA2My45OSAyMTYuMDk0IDY0LjAxNSBDIDE1Ny4zMzQgNjQuNzk1IDEwMS41MDYgNzcuNDA5IDUwLjg0MSA5OS41NTQgQyAzODYuNTk4IC04LjU1OSA1OTguNjUxIDE4OS40OTcgNjM0LjE3MyA0ODcuMDAxIEwgNjQ4Ljg1NCA0ODUuMzU0IEMgNjE4LjA1OCAyMTQuMDM3IDQ1NC45NTQgNjMuODI0IDIyMS42MTQgNjMuOTczIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNzUwNDUyLCAtMC42NjA5MjUsIDAuNjYwOTI1LCAwLjc1MDQ1MiwgLTcwLjgwMzMyMiwgMjkwLjkyMDI3MykiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDAuNDsiIGlkPSJwYXRoLTE3IiBkPSJNIDQ0MS44ODggMzQyLjA5OCBDIDQ0MC4wNDcgMzQyLjA5OCA0MzguMjA3IDM0Mi4xMTQgNDM2LjM2MiAzNDIuMTM4IEMgMzc3LjYwMSAzNDIuOTIyIDMyMS43NjUgMzU1LjUzNSAyNzEuMTAzIDM3Ny42ODEgQyA2MDYuODg2IDI2OS41NjcgODE4Ljk0NCA0NjcuNjE1IDg1NC40NjIgNzY1LjEzMyBMIDg2OS4xNDIgNzYzLjQ4MyBDIDgzOC4zNTQgNDkyLjE1NCA2NzUuMjQyIDM0MS45NDggNDQxLjg4OCAzNDIuMDk4IFoiIHRyYW5zZm9ybT0ibWF0cml4KC0wLjM1NjU4MiwgMC45MzQyNjQsIC0wLjkzNDI2NCwgLTAuMzU2NTgyLCAxMjU2Ljc1OTQ5MywgMTY5LjE4MjU1MikiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgwLjc2MjQ5MywgMCwgMCwgMC43NjI0OTMsIDE5LjI5NDY0NywgLTcxNi4zMjI4MTUpIj4KICAgICAgICA8cGF0aCBkPSJNIDU2Ni40NjYgMTA4OS4xMzcgTCA1NjYuNDY2IDExNDguMjIyIEMgNTY1Ljg2NyAxMTQ4LjIxOSA1NjUuMjY3IDExNDguMjE3IDU2NC42NjcgMTE0OC4yMTcgQyA1NjEuNDgxIDExNDguMjE3IDU1OC4zMSAxMTQ4LjI1OSA1NTUuMTU0IDExNDguMzQxIEwgNTU1LjE1NCAxMDg5LjEzNyBaIE0gOTA4LjI5IDE0NzcuMTQ2IEwgOTU2Ljk4NyAxNDc3LjE0NiBMIDk1Ni45ODcgMTQ4OC40NTggTCA5MDguNTY5IDE0ODguNDU4IEMgOTA4LjUzOSAxNDg0LjY5MyA5MDguNDQ3IDE0ODAuOTIyIDkwOC4yOSAxNDc3LjE0NiBaIE0gNTY2LjQ2NiAxODM1LjAxMyBMIDU2Ni40NjYgMTg3Ni40NjcgTCA1NTUuMTU0IDE4NzYuNDY3IEwgNTU1LjE1NCAxODM0Ljg4NiBDIDU1OC4zMTggMTgzNC45NzMgNTYxLjQ5IDE4MzUuMDE3IDU2NC42NjcgMTgzNS4wMTcgQyA1NjUuMjY3IDE4MzUuMDE3IDU2NS44NjcgMTgzNS4wMTYgNTY2LjQ2NiAxODM1LjAxMyBaIE0gMjIwLjc3NSAxNDg4LjQ1OCBMIDE2OS42NTcgMTQ4OC40NTggTCAxNjkuNjU3IDE0NzcuMTQ2IEwgMjIxLjA4OSAxNDc3LjE0NiBDIDIyMC45MjEgMTQ4MC45MDkgMjIwLjgxNiAxNDg0LjY4IDIyMC43NzUgMTQ4OC40NTggWiIgc3R5bGU9ImZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgc3Ryb2tlOiBub25lOyIgYng6b3JpZ2luPSIwIDAiLz4KICAgICAgICA8cGF0aCBkPSJNIDc2MC4xMjEgMTE0My4zMTEgTCA3MTcuMzM2IDEyMTcuNDE3IEMgNzE1LjcyIDEyMTYuNTE4IDcxNC4wOTYgMTIxNS42MzIgNzEyLjQ2NSAxMjE0Ljc2MSBMIDc1NS4zMTggMTE0MC41MzcgWiBNIDgzMC4xMjIgMTMyNC4yMDMgTCA5MDAuNDI0IDEyODMuNjE0IEwgOTAzLjE5OCAxMjg4LjQxNyBMIDgzMy4wNCAxMzI4LjkyMyBDIDgzMi4wOCAxMzI3LjMzOSA4MzEuMTA3IDEzMjUuNzY2IDgzMC4xMjIgMTMyNC4yMDMgWiBNIDg0MC41OTkgMTY0MS4xMzcgTCA5MDMuMTk3IDE2NzcuMjc4IEwgOTAwLjQyNCAxNjgyLjA4MiBMIDgzNy45MTEgMTY0NS45OSBDIDgzOC44MjEgMTY0NC4zOCA4MzkuNzE3IDE2NDIuNzYyIDg0MC41OTkgMTY0MS4xMzcgWiBNIDcyNS4xNjggMTc2MS44NDMgTCA3NjAuMTIyIDE4MjIuMzg1IEwgNzU1LjMxOCAxODI1LjE1OCBMIDcyMC4zNzkgMTc2NC42NDEgQyA3MjEuOTg1IDE3NjMuNzIyIDcyMy41ODIgMTc2Mi43ODkgNzI1LjE2OCAxNzYxLjg0MyBaIE0gNDAzLjUzOCAxNzYwLjkzMiBMIDM2Ni40NTYgMTgyNS4xNTkgTCAzNjEuNjUzIDE4MjIuMzg2IEwgMzk4LjgwMiAxNzU4LjA0MiBDIDQwMC4zNzIgMTc1OS4wMTkgNDAxLjk1MSAxNzU5Ljk4MiA0MDMuNTM4IDE3NjAuOTMyIFogTSAyODkuNTggMTY0Mi42ODkgTCAyMjEuMzUgMTY4Mi4wODIgTCAyMTguNTc3IDE2NzcuMjc5IEwgMjg2Ljk0NCAxNjM3LjgwNyBDIDI4Ny44MDcgMTYzOS40MzcgMjg4LjY4NSAxNjQxLjA2NSAyODkuNTggMTY0Mi42ODkgWiBNIDI5NC4zNTQgMTMzMi4xNjggTCAyMTguNTc2IDEyODguNDE3IEwgMjIxLjM1IDEyODMuNjE0IEwgMjk3LjIxMyAxMzI3LjQxNCBDIDI5Ni4yNDYgMTMyOC45OSAyOTUuMjkzIDEzMzAuNTc1IDI5NC4zNTQgMTMzMi4xNjggWiBNIDQwNi4wNzkgMTIyMC4yNTkgTCAzNjEuNjUzIDExNDMuMzExIEwgMzY2LjQ1NyAxMTQwLjUzNyBMIDQxMC44ODkgMTIxNy40OTUgQyA0MDkuMjc2IDEyMTguNDAzIDQwNy42NzMgMTIxOS4zMjQgNDA2LjA3OSAxMjIwLjI1OSBaIiBzdHlsZT0iZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IG5vbmU7IiBieDpvcmlnaW49IjAgMCIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8cmVjdCB4PSI0MjkuMzY3IiB5PSI0MjUuOTc5IiB3aWR0aD0iMjAuMDAzIiBoZWlnaHQ9IjIxLjczNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTkxIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAwLjk5OTk5OSwgLTMwMS4zNzcwNzUsIC0yMTkuNDk4NDM0KSIvPgogICAgPHJlY3QgeD0iNDQ2Ljg1MyIgeT0iMjUuNDYyIiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05MyIvPgogICAgPHJlY3QgeD0iLTEzNS45NTYiIHk9IjYwNS4xNDEiIHdpZHRoPSIzOS44NTEiIGhlaWdodD0iMzkuODUxIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTQiIHRyYW5zZm9ybT0ibWF0cml4KDAuOTk5OTk5LCAwLCAwLCAxLCA4NDYuMTc2NzU2LCAtMzk0Ljk1NjAyNCkiLz4KICAgIDxyZWN0IHg9IjIyNS43NzkiIHk9IjY4OS44MzYiIHdpZHRoPSIyNS45OSIgaGVpZ2h0PSIyNS45OSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk1Ii8+CiAgICA8cmVjdCB4PSI1OTQuMDEzIiB5PSI3MzcuMTQyIiB3aWR0aD0iMjAuNzkyIiBoZWlnaHQ9IjIyLjUyNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk2Ii8+CiAgICA8cmVjdCB4PSIzODcuMjM1IiB5PSI0NzkuMzk3IiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05OCIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMDAwMDEsIDAsIDAsIDAuOTk5OTk5LCAzNjUuMjc0OTY2LCA3OS4yOTUyNDEpIi8+CiAgICA8cmVjdCB4PSI0MjEuOTYyIiB5PSI3NzUuOTM3IiB3aWR0aD0iMzIuOTIiIGhlaWdodD0iMzQuNjUzIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTkiLz4KICAgIDxyZWN0IHg9Ii02Ni45MzkiIHk9Ii01NjguOTc4IiB3aWR0aD0iMjAuODY3IiBoZWlnaHQ9IjIwLjc5MiIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTEwMSIgdHJhbnNmb3JtPSJtYXRyaXgoLTEsIDAsIDAsIDAuOTk5OTk3LCAzMS4zNTY5MjgsIDk4NC43MzYzMDYpIi8+CiAgPC9nPgo8L3N2Zz4=); background-repeat: no-repeat; background-position: -725px -145px; - background-size: 1024px 1024px; } - .menu.menu-left { - background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA1MDAgNTAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOmJ4PSJodHRwczovL2JveHktc3ZnLmNvbSI+CiAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoMC42MDgyNjEsIDAsIDAsIDAuNjA4MjYxLCAtMjAuMDg0OTc2LCAzLjI1NTczNikiPgogICAgPGc+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC43ODsiIGlkPSJwYXRoLTEwIiBkPSJNIDQxOS4xMzMgODUuNzM4IEMgNDE3LjI5NSA4NS43MzkgNDE1LjQ1NSA4NS43NTQgNDEzLjYxMSA4NS43NzggQyAzNTQuODUyIDg2LjU2MSAyOTkuMDIzIDk5LjE3NCAyNDguMzU4IDEyMS4zMiBDIDU4NC4xMjEgMTMuMjA2IDc5Ni4xNzUgMjExLjI2IDgzMS43IDUwOC43NzMgTCA4NDYuMzgzIDUwNy4xMjQgQyA4MTUuNTg2IDIzNS44MDEgNjUyLjQ3NyA4NS41ODggNDE5LjEzMyA4NS43MzggWiIgdHJhbnNmb3JtPSJtYXRyaXgoMC45NjM3MywgMC4yNjY4NzgsIC0wLjI2Njg3OCwgMC45NjM3MywgODkuNTA1MjMxLCAtMTM2LjYxNTA2MSkiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDE7IiBpZD0icGF0aC0zIiBkPSJNIDE0Ni4wMzcgMTk0LjA2NSBDIDE0NC4yMDEgMTk0LjA2NiAxNDIuMzYxIDE5NC4wODEgMTQwLjUxNyAxOTQuMTA0IEMgODEuNzYgMTk0Ljg4OCAyNS45MzEgMjA3LjUwMyAtMjQuNzM2IDIyOS42NDggQyAzMTEuMDI5IDEyMS41MzEgNTIzLjA4MyAzMTkuNTgzIDU1OC42MDQgNjE3LjA5MyBMIDU3My4yODQgNjE1LjQ0MyBDIDU0Mi40OSAzNDQuMTIyIDM3OS4zODUgMTkzLjkxMyAxNDYuMDM3IDE5NC4wNjUgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuMTgwOTg4LCAtMC45ODM0ODUsIDAuOTgzNDg1LCAtMC4xODA5ODgsIC0zOS4yOTg1ODEsIDcwNS44OTc1NDQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMSIgZD0iTSA0ODcuNzQ0IDE5My4wODQgQyA0ODUuOTA2IDE5My4wODUgNDg0LjA2NyAxOTMuMSA0ODIuMjIzIDE5My4xMjMgQyA0MjMuNDY0IDE5My45MDcgMzY3LjYzNSAyMDYuNTIgMzE2Ljk3NSAyMjguNjY4IEMgNjUyLjcyNiAxMjAuNTUyIDg2NC43NzUgMzE4LjYwNSA5MDAuMjk5IDYxNi4xMDkgTCA5MTQuOTc5IDYxNC40NiBDIDg4NC4xODQgMzQzLjE0NCA3MjEuMDgxIDE5Mi45MzUgNDg3Ljc0NCAxOTMuMDg0IFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNjE5OTk3LCAwLjc4NDYwNSwgLTAuNzg0NjA1LCAwLjYxOTk5NywgNTIzLjA2NzIzMSwgLTM0My4zMzE1MzkpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjg0OyIgaWQ9InBhdGgtMTIiIGQ9Ik0gMjk1Ljk2OSA0MzIuNzU3IEMgMjk0LjEzMSA0MzIuNzU4IDI5Mi4yOTMgNDMyLjc3MyAyOTAuNDQ5IDQzMi43OTcgQyAyMzEuNjg4IDQzMy41OCAxNzUuODYgNDQ2LjE5NCAxMjUuMTk4IDQ2OC4zNDEgQyA0NjAuOTU3IDM2MC4yMjYgNjczLjAwNSA1NTguMjggNzA4LjUyNiA4NTUuNzg2IEwgNzIzLjIwNyA4NTQuMTM5IEMgNjkyLjQxMiA1ODIuODE5IDUyOS4zMSA0MzIuNjA5IDI5NS45NjkgNDMyLjc1NyBaIiB0cmFuc2Zvcm09Im1hdHJpeCgtMC45Nzg4NDksIDAuMjA0NTg0LCAtMC4yMDQ1ODQsIC0wLjk3ODg0OSwgOTYzLjgyMDc5NiwgMTExNi4zNjcyOTMpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMyIgZD0iTSAxNTguMDM2IDE0OC44MyBDIDE1Ni4yIDE0OC44MzMgMTU0LjM2IDE0OC44NDYgMTUyLjUxNiAxNDguODcyIEMgOTMuNzU5IDE0OS42NTMgMzcuOTMgMTYyLjI2NyAtMTIuNzM0IDE4NC40MTEgQyAzMjMuMDIyIDc2LjMwMSA1MzUuMDc2IDI3NC4zNTIgNTcwLjYwNCA1NzEuODU3IEwgNTg1LjI4NiA1NzAuMjA4IEMgNTU0LjQ4MyAyOTguODkxIDM5MS4zOCAxNDguNjgzIDE1OC4wMzYgMTQ4LjgzIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuMzM4NjE0LCAtMC45NDA5MjYsIDAuOTQwOTI2LCAwLjMzODYxNCwgLTExNS41OTUxNTgsIDQ4My43MDU5ODQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAxOyIgaWQ9InBhdGgtMTQiIGQ9Ik0gNTAxLjAxOSAyODguMjkyIEMgNDk5LjE4MSAyODguMjkzIDQ5Ny4zNCAyODguMzA4IDQ5NS40OTYgMjg4LjMzMSBDIDQzNi43MzYgMjg5LjExNSAzODAuOTA4IDMwMS43MjYgMzMwLjI0MyAzMjMuODc0IEMgNjY2LjAwNCAyMTUuNzU3IDg3OC4wNjIgNDEzLjgxMiA5MTMuNTg2IDcxMS4zMjIgTCA5MjguMjY4IDcwOS42NzMgQyA4OTcuNDY4IDQzOC4zNTIgNzM0LjM2MSAyODguMTQxIDUwMS4wMTkgMjg4LjI5MiBaIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjE2NDY1NiwgMC45ODYzNTEsIC0wLjk4NjM1MSwgMC4xNjQ2NTYsIDk4Mi44NTcyNjYsIC0yMzMuNDUyMDYzKSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC40OyIgaWQ9InBhdGgtMTUiIGQ9Ik0gMTkyLjk1NCAzNzYuNTIxIEMgMTkxLjExNSAzNzYuNTIyIDE4OS4yNzcgMzc2LjUzNyAxODcuNDMzIDM3Ni41NjEgQyAxMjguNjc0IDM3Ny4zNDQgNzIuODQ1IDM4OS45NTggMjIuMTgxIDQxMi4xMDMgQyAzNTcuOTQgMzAzLjk4OSA1NjkuOTg3IDUwMi4wNDUgNjA1LjUwNSA3OTkuNTUzIEwgNjIwLjE4OCA3OTcuOTA1IEMgNTg5LjM5MiA1MjYuNTg0IDQyNi4yOTUgMzc2LjM2OSAxOTIuOTU0IDM3Ni41MjEgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuOTMxNDA0LCAtMC4zNjM5ODgsIDAuMzYzOTg4LCAtMC45MzE0MDQsIDQxOS40OTkwMDYsIDExODIuNTk5ODA5KSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMTsiIGlkPSJwYXRoLTE2IiBkPSJNIDIyMS42MTQgNjMuOTczIEMgMjE5Ljc3NyA2My45NzYgMjE3LjkzOCA2My45OSAyMTYuMDk0IDY0LjAxNSBDIDE1Ny4zMzQgNjQuNzk1IDEwMS41MDYgNzcuNDA5IDUwLjg0MSA5OS41NTQgQyAzODYuNTk4IC04LjU1OSA1OTguNjUxIDE4OS40OTcgNjM0LjE3MyA0ODcuMDAxIEwgNjQ4Ljg1NCA0ODUuMzU0IEMgNjE4LjA1OCAyMTQuMDM3IDQ1NC45NTQgNjMuODI0IDIyMS42MTQgNjMuOTczIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNzUwNDUyLCAtMC42NjA5MjUsIDAuNjYwOTI1LCAwLjc1MDQ1MiwgLTcwLjgwMzMyMiwgMjkwLjkyMDI3MykiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDAuNDsiIGlkPSJwYXRoLTE3IiBkPSJNIDQ0MS44ODggMzQyLjA5OCBDIDQ0MC4wNDcgMzQyLjA5OCA0MzguMjA3IDM0Mi4xMTQgNDM2LjM2MiAzNDIuMTM4IEMgMzc3LjYwMSAzNDIuOTIyIDMyMS43NjUgMzU1LjUzNSAyNzEuMTAzIDM3Ny42ODEgQyA2MDYuODg2IDI2OS41NjcgODE4Ljk0NCA0NjcuNjE1IDg1NC40NjIgNzY1LjEzMyBMIDg2OS4xNDIgNzYzLjQ4MyBDIDgzOC4zNTQgNDkyLjE1NCA2NzUuMjQyIDM0MS45NDggNDQxLjg4OCAzNDIuMDk4IFoiIHRyYW5zZm9ybT0ibWF0cml4KC0wLjM1NjU4MiwgMC45MzQyNjQsIC0wLjkzNDI2NCwgLTAuMzU2NTgyLCAxMjU2Ljc1OTQ5MywgMTY5LjE4MjU1MikiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgwLjc2MjQ5MywgMCwgMCwgMC43NjI0OTMsIDE5LjI5NDY0NywgLTcxNi4zMjI4MTUpIj4KICAgICAgICA8cGF0aCBkPSJNIDU2Ni40NjYgMTA4OS4xMzcgTCA1NjYuNDY2IDExNDguMjIyIEMgNTY1Ljg2NyAxMTQ4LjIxOSA1NjUuMjY3IDExNDguMjE3IDU2NC42NjcgMTE0OC4yMTcgQyA1NjEuNDgxIDExNDguMjE3IDU1OC4zMSAxMTQ4LjI1OSA1NTUuMTU0IDExNDguMzQxIEwgNTU1LjE1NCAxMDg5LjEzNyBaIE0gOTA4LjI5IDE0NzcuMTQ2IEwgOTU2Ljk4NyAxNDc3LjE0NiBMIDk1Ni45ODcgMTQ4OC40NTggTCA5MDguNTY5IDE0ODguNDU4IEMgOTA4LjUzOSAxNDg0LjY5MyA5MDguNDQ3IDE0ODAuOTIyIDkwOC4yOSAxNDc3LjE0NiBaIE0gNTY2LjQ2NiAxODM1LjAxMyBMIDU2Ni40NjYgMTg3Ni40NjcgTCA1NTUuMTU0IDE4NzYuNDY3IEwgNTU1LjE1NCAxODM0Ljg4NiBDIDU1OC4zMTggMTgzNC45NzMgNTYxLjQ5IDE4MzUuMDE3IDU2NC42NjcgMTgzNS4wMTcgQyA1NjUuMjY3IDE4MzUuMDE3IDU2NS44NjcgMTgzNS4wMTYgNTY2LjQ2NiAxODM1LjAxMyBaIE0gMjIwLjc3NSAxNDg4LjQ1OCBMIDE2OS42NTcgMTQ4OC40NTggTCAxNjkuNjU3IDE0NzcuMTQ2IEwgMjIxLjA4OSAxNDc3LjE0NiBDIDIyMC45MjEgMTQ4MC45MDkgMjIwLjgxNiAxNDg0LjY4IDIyMC43NzUgMTQ4OC40NTggWiIgc3R5bGU9ImZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgc3Ryb2tlOiBub25lOyIgYng6b3JpZ2luPSIwIDAiLz4KICAgICAgICA8cGF0aCBkPSJNIDc2MC4xMjEgMTE0My4zMTEgTCA3MTcuMzM2IDEyMTcuNDE3IEMgNzE1LjcyIDEyMTYuNTE4IDcxNC4wOTYgMTIxNS42MzIgNzEyLjQ2NSAxMjE0Ljc2MSBMIDc1NS4zMTggMTE0MC41MzcgWiBNIDgzMC4xMjIgMTMyNC4yMDMgTCA5MDAuNDI0IDEyODMuNjE0IEwgOTAzLjE5OCAxMjg4LjQxNyBMIDgzMy4wNCAxMzI4LjkyMyBDIDgzMi4wOCAxMzI3LjMzOSA4MzEuMTA3IDEzMjUuNzY2IDgzMC4xMjIgMTMyNC4yMDMgWiBNIDg0MC41OTkgMTY0MS4xMzcgTCA5MDMuMTk3IDE2NzcuMjc4IEwgOTAwLjQyNCAxNjgyLjA4MiBMIDgzNy45MTEgMTY0NS45OSBDIDgzOC44MjEgMTY0NC4zOCA4MzkuNzE3IDE2NDIuNzYyIDg0MC41OTkgMTY0MS4xMzcgWiBNIDcyNS4xNjggMTc2MS44NDMgTCA3NjAuMTIyIDE4MjIuMzg1IEwgNzU1LjMxOCAxODI1LjE1OCBMIDcyMC4zNzkgMTc2NC42NDEgQyA3MjEuOTg1IDE3NjMuNzIyIDcyMy41ODIgMTc2Mi43ODkgNzI1LjE2OCAxNzYxLjg0MyBaIE0gNDAzLjUzOCAxNzYwLjkzMiBMIDM2Ni40NTYgMTgyNS4xNTkgTCAzNjEuNjUzIDE4MjIuMzg2IEwgMzk4LjgwMiAxNzU4LjA0MiBDIDQwMC4zNzIgMTc1OS4wMTkgNDAxLjk1MSAxNzU5Ljk4MiA0MDMuNTM4IDE3NjAuOTMyIFogTSAyODkuNTggMTY0Mi42ODkgTCAyMjEuMzUgMTY4Mi4wODIgTCAyMTguNTc3IDE2NzcuMjc5IEwgMjg2Ljk0NCAxNjM3LjgwNyBDIDI4Ny44MDcgMTYzOS40MzcgMjg4LjY4NSAxNjQxLjA2NSAyODkuNTggMTY0Mi42ODkgWiBNIDI5NC4zNTQgMTMzMi4xNjggTCAyMTguNTc2IDEyODguNDE3IEwgMjIxLjM1IDEyODMuNjE0IEwgMjk3LjIxMyAxMzI3LjQxNCBDIDI5Ni4yNDYgMTMyOC45OSAyOTUuMjkzIDEzMzAuNTc1IDI5NC4zNTQgMTMzMi4xNjggWiBNIDQwNi4wNzkgMTIyMC4yNTkgTCAzNjEuNjUzIDExNDMuMzExIEwgMzY2LjQ1NyAxMTQwLjUzNyBMIDQxMC44ODkgMTIxNy40OTUgQyA0MDkuMjc2IDEyMTguNDAzIDQwNy42NzMgMTIxOS4zMjQgNDA2LjA3OSAxMjIwLjI1OSBaIiBzdHlsZT0iZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IG5vbmU7IiBieDpvcmlnaW49IjAgMCIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8cmVjdCB4PSI0MjkuMzY3IiB5PSI0MjUuOTc5IiB3aWR0aD0iMjAuMDAzIiBoZWlnaHQ9IjIxLjczNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTkxIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAwLjk5OTk5OSwgLTMwMS4zNzcwNzUsIC0yMTkuNDk4NDM0KSIvPgogICAgPHJlY3QgeD0iNDQ2Ljg1MyIgeT0iMjUuNDYyIiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05MyIvPgogICAgPHJlY3QgeD0iLTEzNS45NTYiIHk9IjYwNS4xNDEiIHdpZHRoPSIzOS44NTEiIGhlaWdodD0iMzkuODUxIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTQiIHRyYW5zZm9ybT0ibWF0cml4KDAuOTk5OTk5LCAwLCAwLCAxLCA4NDYuMTc2NzU2LCAtMzk0Ljk1NjAyNCkiLz4KICAgIDxyZWN0IHg9IjIyNS43NzkiIHk9IjY4OS44MzYiIHdpZHRoPSIyNS45OSIgaGVpZ2h0PSIyNS45OSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk1Ii8+CiAgICA8cmVjdCB4PSI1OTQuMDEzIiB5PSI3MzcuMTQyIiB3aWR0aD0iMjAuNzkyIiBoZWlnaHQ9IjIyLjUyNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk2Ii8+CiAgICA8cmVjdCB4PSIzODcuMjM1IiB5PSI0NzkuMzk3IiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05OCIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMDAwMDEsIDAsIDAsIDAuOTk5OTk5LCAzNjUuMjc0OTY2LCA3OS4yOTUyNDEpIi8+CiAgICA8cmVjdCB4PSI0MjEuOTYyIiB5PSI3NzUuOTM3IiB3aWR0aD0iMzIuOTIiIGhlaWdodD0iMzQuNjUzIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTkiLz4KICAgIDxyZWN0IHg9Ii02Ni45MzkiIHk9Ii01NjguOTc4IiB3aWR0aD0iMjAuODY3IiBoZWlnaHQ9IjIwLjc5MiIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTEwMSIgdHJhbnNmb3JtPSJtYXRyaXgoLTEsIDAsIDAsIDAuOTk5OTk3LCAzMS4zNTY5MjgsIDk4NC43MzYzMDYpIi8+CiAgPC9nPgo8L3N2Zz4=); - background-repeat: no-repeat; - background-position: -500px -100px; - background-size: 1024px 1024px; - background-color: whitesmoke; - height: 100%; } - .menu.menu-left .item.active { - background-color: #b2e0ff !important; } - .menu.menu-left .item.active .item-content { - background-color: transparent; - opacity: 1; - color: black; } - .menu.menu-left .item { - opacity: 0.75; - color: black; } - .menu.menu-left .item .item-content { - background-color: transparent; - opacity: 1; } - .menu.menu-left .item-menu-disable { - color: #444 !important; } } + background-size: 1024px 1024px; } } .gray, .popover-share .bar-header span, .popover-share .bar-footer .button-close, .popover-helptip .button-close { color: grey !important; } .gray b, .popover-share .bar-header span b, .popover-share .bar-footer .button-close b, .popover-helptip .button-close b { color: grey !important; } -.gray a, .popover-share .bar-header span a, .popover-share .bar-footer .button-close a, .popover-helptip .button-close a, .positive a, .icon-help a { +.gray a, .popover-share .bar-header span a, .popover-share .bar-footer .button-close a, .popover-helptip .button-close a, .positive a, .text-editable:hover a, .icon-help a { color: inherit; } -.gray a:hover, .popover-share .bar-header span a:hover, .popover-share .bar-footer .button-close a:hover, .popover-helptip .button-close a:hover, .positive a:hover, .icon-help a:hover { +.gray a:hover, .popover-share .bar-header span a:hover, .popover-share .bar-footer .button-close a:hover, .popover-helptip .button-close a:hover, .positive a:hover, .text-editable:hover a:hover, .icon-help a:hover { color: inherit; } -.gray a:visited, .popover-share .bar-header span a:visited, .popover-share .bar-footer .button-close a:visited, .popover-helptip .button-close a:visited, .positive a:visited, .icon-help a:visited { +.gray a:visited, .popover-share .bar-header span a:visited, .popover-share .bar-footer .button-close a:visited, .popover-helptip .button-close a:visited, .positive a:visited, .text-editable:hover a:visited, .icon-help a:visited { color: inherit; } .item a { @@ -14451,31 +15392,6 @@ a { .avatar-wallet { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAQAAABpN6lAAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfgBA0JMBOJU4OdAAAB2klEQVR42u3au0ocUQCH8e+IxFRKUohrkG0Eu4BiLrCFDxDBNtjoI1gYTJnGQrRInc4HyBuopNHgBVZIwCJFsHBXLURtQiIyKYyFN3B3zJyd3e/X7e7MmXP+e26zOyBJkiRJkiRJkiRJkiRJkppVSF9E0sk0r+jKuOYnrLMQTqMHkHSzQTHS17fLy3CYroi21JWYj9Z8KDIfvwdUKAC7bGfc+CH6gGrojTyJJBemMr/u+4sLpy2njRZnAAZgAK2t/YHKGUzeZlzz5w2yFU6/EKVsQHAIGIABGIABGIABRN4ILbOVcc1fM9IQCfp7gHOAARiAAbgMXpuhH/GJ0brK/sG78OVfKR0cXPnsQ/iYkwAYY6LOM4eZpXR5q3/t77bH+RkCO5HObZQeEL4nQ7ypcwh8boIAIJQpuwoYQMsugwBJ/73L/h1+3vr+OYtXXn/Lzz7gCV8ZqOH4LUrhz4155IzJvA6B0VqaDwzHu7f/PwEsc1zT8RXWmmoOCJWkl9L95wBWbw6AvO8DfrHkMmgABmAABtDw0j8gUaWHeA9K7odC7GVwhXGgGOmB2ZX4PaDAJs8i9d89XoRq5AAgecoMg3Rm3PhTysyFIyRJkiRJkiRJkiRJkiRJku7wFyuiadmIs5Q9AAAAAElFTkSuQmCC); } -.item.item-icon-left > i.avatar:first-child { - position: absolute; - display: flex; - height: 100%; - align-items: center; - font-size: 16px; - left: 16px; - top: 8px; - max-height: 32px; - max-width: 32px; } - -.item.item-checkbox.item-avatar > i.avatar:first-child, -.item.item-checkbox.item-avatar > i.item-image:first-child, -.item.item-checkbox.item-avatar .item-content > i.avatar:first-child, -.item.item-checkbox.item-avatar .item-content > i.item-image:first-child, -.item.item-checkbox.item-avatar * > i.avatar:first-child, -.item.item-checkbox.item-avatar * > i.item-image:first-child, -.item.item-checkbox.item-avatar * .item-content > i.avatar:first-child, -.item.item-checkbox.item-avatar * .item-content > i.item-image:first-child { - left: 65px; } - -.item.item-checkbox.item-avatar .item-content, -.item.item-checkbox .item-content .item-avatar { - padding-left: 65px; } - /* ---- Popup alert ---- */ @@ -14502,22 +15418,43 @@ a { /****** * 'ion-refresher' *******/ -.refresher-top-bg:before { +body { + --refresher-bg-height: 100px; + --refresher-background-color: inherit; } + +.refresher-positive-900-bg { + --refresher-background-color: #1A237E; } + +.refresher-dark-100-bg { + --refresher-background-color: #555; } + +.platform-android .refresher-positive-900-bg:before, +.platform-android .refresher-dark-100-bg:before { + background-color: var(--refresher-background-color); position: absolute; display: block; top: 0; width: 100%; - height: 100px; + height: var(--refresher-bg-height, 100px); z-index: -10; content: " "; } -.refresher-top-bg .scroll-refresher { +.platform-android .scroll-refresher { z-index: 50; } -.refresher-light .scroll-refresher .ionic-refresher-content, .view-wallet .refresher-top-bg .scroll-refresher .ionic-refresher-content, .view-wallet-tx .refresher-top-bg .scroll-refresher .ionic-refresher-content, .view-identity .refresher-top-bg .scroll-refresher .ionic-refresher-content { +.platform-ios .refresher-positive-900-bg, +.platform-ios .refresher-dark-100-bg { + background-color: var(--refresher-background-color) !important; } + .platform-ios .refresher-positive-900-bg .scroll, + .platform-ios .refresher-dark-100-bg .scroll { + background-color: #fff; + bottom: auto; + min-height: 100%; } + +.refresher-light .scroll-refresher .ionic-refresher-content, .refresher-positive-900-bg .scroll-refresher .ionic-refresher-content, .refresher-dark-100-bg .scroll-refresher .ionic-refresher-content { color: #fff; } -.refresher-light .scroll-refresher .spinner, .view-wallet .refresher-top-bg .scroll-refresher .spinner, .view-wallet-tx .refresher-top-bg .scroll-refresher .spinner, .view-identity .refresher-top-bg .scroll-refresher .spinner { +.refresher-light .scroll-refresher .spinner, .refresher-positive-900-bg .scroll-refresher .spinner, .refresher-dark-100-bg .scroll-refresher .spinner { stroke: #fff; fill: #fff; } @@ -14525,31 +15462,12 @@ a { * Wallet view *******/ .view-wallet { - /* set 'ion-refresher' background color */ } - .view-wallet .refresher-top-bg:before { + --refresher-bg-height: 200px; } + .view-wallet .hero { height: 200px; } - .view-wallet .qrcode { - position: absolute; - top: 30px; - padding: 3px; - background: #fff; - width: 90px; - max-width: 30%; - right: -170px; - -webkit-backface-visibility: hidden !important; - backface-visibility: hidden !important; - -webkit-transition: all 0.5s ease-out !important; - transition: all 0.5s ease-out !important; } - .view-wallet .qrcode img { - width: 100%; } - .view-wallet .qrcode.on { - right: 30px; } - .view-wallet .qrcode.active { - top: 0px !important; - right: 0px !important; - padding: 10px; - width: 200px; - max-width: 50%; } + .view-wallet .hero h4:after { + content: ' '; + display: inline-block; } .view-wallet .item-text-wrap { white-space: normal !important; } .view-wallet .item .comment { @@ -14569,16 +15487,67 @@ a { .view-wallet .item.item-wallet-event:last-child { min-height: 48px; } .view-wallet .item.item-icon-left.item-wallet-event .icon, .view-wallet .item.item-icon-left.item-wallet-event .icon-help, .view-wallet .item.item-icon-left.item-wallet-event .icon-alert, .view-wallet .item.item-icon-left.item-wallet-event #menu .footer .icon-help, #menu .footer .view-wallet .item.item-icon-left.item-wallet-event .icon-help { - font-size: 15px; } + font-size: 17px; + height: 18px; + top: 6px; } + +/* -- + QR code +-- */ +.view-wallet .qrcode, +.view-identity .qrcode { + position: absolute; + display: block; + top: 0; + right: 0; + width: 0; + height: 0; + background: #fff; + z-index: 1; + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; + overflow: hidden; } + .view-wallet .qrcode img, + .view-identity .qrcode img { + display: float; + float: right; + width: 0; + height: 0; + z-index: 1; + transition: all 0.5s ease-out !important; } + +.view-wallet .qrcode.on, +.view-identity .qrcode.on { + width: 50px; + height: 50px; + padding: 3px; + margin: 7px; } + .view-wallet .qrcode.on img, + .view-identity .qrcode.on img { + width: 44px; + height: 44px; } + +.view-wallet .qrcode.on.active, +.view-identity .qrcode.on.active { + margin: 0 !important; + padding: 10px; + width: 200px; + height: 200px; } + .view-wallet .qrcode.on.active img, + .view-identity .qrcode.on.active img { + width: 180px; + height: 180px; } @media screen and (max-width: 991px) { - .view-wallet .qrcode { - top: 8px; - width: 60px; - max-width: 30%; } - .view-wallet .qrcode.on { - right: 8px; } - .view-wallet .hero.hero-qrcode-active h1, .view-wallet .hero.hero-qrcode-active h2, .view-wallet .hero.hero-qrcode-active h3, .view-wallet .hero.hero-qrcode-active h4, .view-wallet .hero.hero-qrcode-active h5, .view-wallet .hero.hero-qrcode-active i { + .view-wallet .hero.hero-qrcode-active h1, .view-wallet .hero.hero-qrcode-active h2, .view-wallet .hero.hero-qrcode-active h3, .view-wallet .hero.hero-qrcode-active h4, .view-wallet .hero.hero-qrcode-active h5, .view-wallet .hero.hero-qrcode-active i.avatar, + .view-identity .hero.hero-qrcode-active h1, + .view-identity .hero.hero-qrcode-active h2, + .view-identity .hero.hero-qrcode-active h3, + .view-identity .hero.hero-qrcode-active h4, + .view-identity .hero.hero-qrcode-active h5, + .view-identity .hero.hero-qrcode-active i.avatar { margin-right: 200px; } } .popover-wallet-actions { @@ -14587,22 +15556,32 @@ a { /****** * Wallet TX view *******/ -.view-wallet-tx { - /* set 'ion-refresher' background color */ } - .view-wallet-tx .hero { - height: 100px; } - .view-wallet-tx .refresher-top-bg:before { - height: 100px; } - .view-wallet-tx .item-text-wrap { - white-space: normal !important; } - .view-wallet-tx .item .comment { - font-style: italic !important; } - .view-wallet-tx .item h3 .gray, .view-wallet-tx .item h3 .popover-share .bar-header span, .popover-share .bar-header .view-wallet-tx .item h3 span, .view-wallet-tx .item h3 .popover-share .bar-footer .button-close, .popover-share .bar-footer .view-wallet-tx .item h3 .button-close, .view-wallet-tx .item h3 .popover-helptip .button-close, .popover-helptip .view-wallet-tx .item h3 .button-close { - font-size: 11px !important; } - .view-wallet-tx .list .item span { - display: inline; } - .view-wallet-tx .item-divider .badge { - top: 16px !important; } +@media screen and (max-width: 991px) { + .view-wallet-tx { + --refresher-bg-height: 100px; } + .view-wallet-tx .hero { + height: 100px; } } + +@media screen and (min-width: 992px) { + .view-wallet-tx { + --refresher-bg-height: 140px; } + .view-wallet-tx .hero { + height: 140px; } } + +.view-wallet-tx .item-text-wrap { + white-space: normal !important; } + +.view-wallet-tx .item .comment { + font-style: italic !important; } + +.view-wallet-tx .item h3 .gray, .view-wallet-tx .item h3 .popover-share .bar-header span, .popover-share .bar-header .view-wallet-tx .item h3 span, .view-wallet-tx .item h3 .popover-share .bar-footer .button-close, .popover-share .bar-footer .view-wallet-tx .item h3 .button-close, .view-wallet-tx .item h3 .popover-helptip .button-close, .popover-helptip .view-wallet-tx .item h3 .button-close { + font-size: 11px !important; } + +.view-wallet-tx .list .item span { + display: inline; } + +.view-wallet-tx .item-divider .badge { + top: 16px !important; } .stable-100-bg { background-color: #f2f2f2 !important; } @@ -14610,16 +15589,43 @@ a { /****** * TX view (wallet or identity) *******/ -.item-tx .badge-energized { - background-color: rgba(255, 201, 0, 0.3); - color: #888 !important; } +.item-tx { + border-top: solid 1px lightgray !important; + padding-bottom: 6px; + padding-top: 8px; + margin: 0 !important; } + .item-tx .badge-energized { + background-color: rgba(255, 201, 0, 0.3); + color: #888 !important; } + .item-tx .badge { + right: 1% !important; + top: 13px; } + .item-tx .badge-white { + background-color: white; } + .item-tx .vertical-center { + position: absolute; + top: 30%; + width: 40%; } + .item-tx .width-cup { + width: 175px; } + +.expert-mode .item-tx .item-note { + top: 8%; } + +.expert-mode .item-tx .badge-secondary { + top: calc(8% + 23px) !important; } /****** * Identity view *******/ -.view-identity .hero, -.view-identity .refresher-top-bg:before { - height: 200px; } +.view-identity { + --refresher-bg-height: 200px; + --refresher-background-color: #555; } + .view-identity .member { + --refresher-background-color: #1A237E; } + .view-identity .hero { + height: 200px; + background-color: var(--refresher-background-color); } /****** * Cards @@ -14673,7 +15679,8 @@ a { .card.card-avatar .item.item-avatar { padding-top: 10px; padding-bottom: 2px; - min-height: 45px !important; } + min-height: 45px !important; + margin-bottom: 1px; } .card .card-avatar .card-footer, .card.card-avatar .card-footer { @@ -14681,46 +15688,46 @@ a { overflow: hidden; } .card .card-avatar .card-footer .pull-right a, .card .card-avatar .card-footer .popover-helptip .icon.icon-right a, .popover-helptip .card .card-avatar .card-footer .icon.icon-right a, .card .card-avatar .card-footer .popover-helptip .icon-right.icon-help a, .popover-helptip .card .card-avatar .card-footer .icon-right.icon-help a, .card .card-avatar .card-footer .popover-helptip .icon-right.icon-alert a, .popover-helptip .card .card-avatar .card-footer .icon-right.icon-alert a, .card .card-avatar .card-footer .popover-helptip #menu .footer .icon-right.icon-help a, .popover-helptip #menu .footer .card .card-avatar .card-footer .icon-right.icon-help a, .card .card-avatar .card-footer #menu .footer .popover-helptip .icon-right.icon-help a, #menu .footer .popover-helptip .card .card-avatar .card-footer .icon-right.icon-help a, .card .card-avatar .card-footer .popover-helptip .icon.icon-center a, .popover-helptip .card .card-avatar .card-footer .icon.icon-center a, .card .card-avatar .card-footer .popover-helptip .icon-center.icon-help a, .popover-helptip .card .card-avatar .card-footer .icon-center.icon-help a, .card .card-avatar .card-footer .popover-helptip .icon-center.icon-alert a, .popover-helptip .card .card-avatar .card-footer .icon-center.icon-alert a, .card .card-avatar .card-footer .popover-helptip #menu .footer .icon-center.icon-help a, .popover-helptip #menu .footer .card .card-avatar .card-footer .icon-center.icon-help a, .card .card-avatar .card-footer #menu .footer .popover-helptip .icon-center.icon-help a, #menu .footer .popover-helptip .card .card-avatar .card-footer .icon-center.icon-help a, .card .card-avatar .card-footer .popover-helptip .icon.icon-bottom-right a, .popover-helptip .card .card-avatar .card-footer .icon.icon-bottom-right a, .card .card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-help a, .popover-helptip .card .card-avatar .card-footer .icon-bottom-right.icon-help a, .card .card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-alert a, .popover-helptip .card .card-avatar .card-footer .icon-bottom-right.icon-alert a, .card .card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help a, .popover-helptip #menu .footer .card .card-avatar .card-footer .icon-bottom-right.icon-help a, .card .card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help a, #menu .footer .popover-helptip .card .card-avatar .card-footer .icon-bottom-right.icon-help a, .card .card-avatar .card-footer .popover-helptip .icon.icon-bottom-center a, .popover-helptip .card .card-avatar .card-footer .icon.icon-bottom-center a, .card .card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-help a, .popover-helptip .card .card-avatar .card-footer .icon-bottom-center.icon-help a, .card .card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-alert a, .popover-helptip .card .card-avatar .card-footer .icon-bottom-center.icon-alert a, .card .card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help a, .popover-helptip #menu .footer .card .card-avatar .card-footer .icon-bottom-center.icon-help a, .card .card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help a, #menu .footer .popover-helptip .card .card-avatar .card-footer .icon-bottom-center.icon-help a, .card.card-avatar .card-footer .pull-right a, - .card.card-avatar .card-footer .popover-helptip .icon.icon-right a, .popover-helptip - .card.card-avatar .card-footer .icon.icon-right a, - .card.card-avatar .card-footer .popover-helptip .icon-right.icon-help a, .popover-helptip - .card.card-avatar .card-footer .icon-right.icon-help a, - .card.card-avatar .card-footer .popover-helptip .icon-right.icon-alert a, .popover-helptip - .card.card-avatar .card-footer .icon-right.icon-alert a, - .card.card-avatar .card-footer .popover-helptip #menu .footer .icon-right.icon-help a, .popover-helptip #menu .footer - .card.card-avatar .card-footer .icon-right.icon-help a, - .card.card-avatar .card-footer #menu .footer .popover-helptip .icon-right.icon-help a, #menu .footer .popover-helptip - .card.card-avatar .card-footer .icon-right.icon-help a, - .card.card-avatar .card-footer .popover-helptip .icon.icon-center a, .popover-helptip - .card.card-avatar .card-footer .icon.icon-center a, - .card.card-avatar .card-footer .popover-helptip .icon-center.icon-help a, .popover-helptip - .card.card-avatar .card-footer .icon-center.icon-help a, - .card.card-avatar .card-footer .popover-helptip .icon-center.icon-alert a, .popover-helptip - .card.card-avatar .card-footer .icon-center.icon-alert a, - .card.card-avatar .card-footer .popover-helptip #menu .footer .icon-center.icon-help a, .popover-helptip #menu .footer - .card.card-avatar .card-footer .icon-center.icon-help a, - .card.card-avatar .card-footer #menu .footer .popover-helptip .icon-center.icon-help a, #menu .footer .popover-helptip - .card.card-avatar .card-footer .icon-center.icon-help a, - .card.card-avatar .card-footer .popover-helptip .icon.icon-bottom-right a, .popover-helptip - .card.card-avatar .card-footer .icon.icon-bottom-right a, - .card.card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-help a, .popover-helptip - .card.card-avatar .card-footer .icon-bottom-right.icon-help a, - .card.card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-alert a, .popover-helptip - .card.card-avatar .card-footer .icon-bottom-right.icon-alert a, - .card.card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help a, .popover-helptip #menu .footer - .card.card-avatar .card-footer .icon-bottom-right.icon-help a, - .card.card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help a, #menu .footer .popover-helptip - .card.card-avatar .card-footer .icon-bottom-right.icon-help a, - .card.card-avatar .card-footer .popover-helptip .icon.icon-bottom-center a, .popover-helptip - .card.card-avatar .card-footer .icon.icon-bottom-center a, - .card.card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-help a, .popover-helptip - .card.card-avatar .card-footer .icon-bottom-center.icon-help a, - .card.card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-alert a, .popover-helptip - .card.card-avatar .card-footer .icon-bottom-center.icon-alert a, - .card.card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help a, .popover-helptip #menu .footer - .card.card-avatar .card-footer .icon-bottom-center.icon-help a, - .card.card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help a, #menu .footer .popover-helptip - .card.card-avatar .card-footer .icon-bottom-center.icon-help a { + .card.card-avatar .card-footer .popover-helptip .icon.icon-right a, + .popover-helptip .card.card-avatar .card-footer .icon.icon-right a, + .card.card-avatar .card-footer .popover-helptip .icon-right.icon-help a, + .popover-helptip .card.card-avatar .card-footer .icon-right.icon-help a, + .card.card-avatar .card-footer .popover-helptip .icon-right.icon-alert a, + .popover-helptip .card.card-avatar .card-footer .icon-right.icon-alert a, + .card.card-avatar .card-footer .popover-helptip #menu .footer .icon-right.icon-help a, + .popover-helptip #menu .footer .card.card-avatar .card-footer .icon-right.icon-help a, + .card.card-avatar .card-footer #menu .footer .popover-helptip .icon-right.icon-help a, + #menu .footer .popover-helptip .card.card-avatar .card-footer .icon-right.icon-help a, + .card.card-avatar .card-footer .popover-helptip .icon.icon-center a, + .popover-helptip .card.card-avatar .card-footer .icon.icon-center a, + .card.card-avatar .card-footer .popover-helptip .icon-center.icon-help a, + .popover-helptip .card.card-avatar .card-footer .icon-center.icon-help a, + .card.card-avatar .card-footer .popover-helptip .icon-center.icon-alert a, + .popover-helptip .card.card-avatar .card-footer .icon-center.icon-alert a, + .card.card-avatar .card-footer .popover-helptip #menu .footer .icon-center.icon-help a, + .popover-helptip #menu .footer .card.card-avatar .card-footer .icon-center.icon-help a, + .card.card-avatar .card-footer #menu .footer .popover-helptip .icon-center.icon-help a, + #menu .footer .popover-helptip .card.card-avatar .card-footer .icon-center.icon-help a, + .card.card-avatar .card-footer .popover-helptip .icon.icon-bottom-right a, + .popover-helptip .card.card-avatar .card-footer .icon.icon-bottom-right a, + .card.card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-help a, + .popover-helptip .card.card-avatar .card-footer .icon-bottom-right.icon-help a, + .card.card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-alert a, + .popover-helptip .card.card-avatar .card-footer .icon-bottom-right.icon-alert a, + .card.card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help a, + .popover-helptip #menu .footer .card.card-avatar .card-footer .icon-bottom-right.icon-help a, + .card.card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help a, + #menu .footer .popover-helptip .card.card-avatar .card-footer .icon-bottom-right.icon-help a, + .card.card-avatar .card-footer .popover-helptip .icon.icon-bottom-center a, + .popover-helptip .card.card-avatar .card-footer .icon.icon-bottom-center a, + .card.card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-help a, + .popover-helptip .card.card-avatar .card-footer .icon-bottom-center.icon-help a, + .card.card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-alert a, + .popover-helptip .card.card-avatar .card-footer .icon-bottom-center.icon-alert a, + .card.card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help a, + .popover-helptip #menu .footer .card.card-avatar .card-footer .icon-bottom-center.icon-help a, + .card.card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help a, + #menu .footer .popover-helptip .card.card-avatar .card-footer .icon-bottom-center.icon-help a { margin-right: 8px; } a.underline:focus, @@ -14790,7 +15797,9 @@ a.underline:hover, min-height: 80px !important; } .lookupForm .list .item.item-avatar.item-checkbox .item-content { - padding-left: 47px; } + padding-left: 47px; + min-height: auto !important; + height: auto !important; } /************************ Additional motions @@ -14833,13 +15842,8 @@ a.underline:hover, border: solid 1px #D9D9D9; overflow: hidden !important; font-size: 45px !important; - /*padding-left: 0px; - padding-top: 0px; - text-align: center; - vertical-align: middle;*/ line-height: 56px; width: 100% !important; - /*display: block !important;*/ max-height: 56px !important; max-width: 56px !important; top: 12px !important; } @@ -14848,18 +15852,18 @@ a.underline:hover, .item-avatar .icon.item-image:first-child:before, .item-avatar .item-image.icon-help:first-child:before, .item-avatar .item-image.icon-alert:first-child:before, -.item-avatar #menu .footer .item-image.icon-help:first-child:before, #menu .footer -.item-avatar .item-image.icon-help:first-child:before, +.item-avatar #menu .footer .item-image.icon-help:first-child:before, +#menu .footer .item-avatar .item-image.icon-help:first-child:before, .item-avatar .item-content > .icon:first-child:before, .item-avatar .item-content > .icon-help:first-child:before, .item-avatar .item-content > .icon-alert:first-child:before, -.item-avatar #menu .footer .item-content > .icon-help:first-child:before, #menu .footer -.item-avatar .item-content > .icon-help:first-child:before, +.item-avatar #menu .footer .item-content > .icon-help:first-child:before, +#menu .footer .item-avatar .item-content > .icon-help:first-child:before, .item-avatar.item-icon-right .icon:first-child:before, .item-avatar.item-icon-right .icon-help:first-child:before, .item-avatar.item-icon-right .icon-alert:first-child:before, -.item-avatar.item-icon-right #menu .footer .icon-help:first-child:before, #menu .footer -.item-avatar.item-icon-right .icon-help:first-child:before, +.item-avatar.item-icon-right #menu .footer .icon-help:first-child:before, +#menu .footer .item-avatar.item-icon-right .icon-help:first-child:before, .item-avatar.item-icon-right .icon-help:first-child:before, .item-avatar.item-icon-right .icon-alert:first-child:before, .item-avatar.item-icon-right #menu .footer .icon-help:first-child:before, @@ -14869,27 +15873,80 @@ a.underline:hover, .item-avatar.item-icon-right .icon:last-child, .item-avatar.item-icon-right .icon-help:last-child, .item-avatar.item-icon-right .icon-alert:last-child, .item-avatar.item-icon-right #menu .footer .icon-help:last-child, #menu .footer .item-avatar.item-icon-right .icon-help:last-child, .item-avatar.item-icon-right .icon-help:last-child, .item-avatar.item-icon-right .icon-alert:last-child, +.item-avatar.item-icon-right.ink .icon.ion-ios-arrow-right, +.item-avatar.item-icon-right.ink .ion-ios-arrow-right.icon-help, +.item-avatar.item-icon-right.ink .ion-ios-arrow-right.icon-alert, +.item-avatar.item-icon-right.ink #menu .footer .ion-ios-arrow-right.icon-help, +#menu .footer .item-avatar.item-icon-right.ink .ion-ios-arrow-right.icon-help, .item-avatar.item-icon-right #menu .footer .icon-help:last-child, #menu .footer .item-avatar.item-icon-right .icon-help:last-child { left: auto; } /********** - Item > Other + Item > Left icon position +**********/ +.item.item-icon-left > i.avatar:first-child { + position: absolute; + display: flex; + height: 100%; + align-items: center; + font-size: 16px; + left: 16px; + top: 8px; + max-height: 32px; + max-width: 32px; } + +.item.item-checkbox.item-avatar > i.avatar:first-child, +.item.item-checkbox.item-avatar > i.item-image:first-child, +.item.item-checkbox.item-avatar .item-content > i.avatar:first-child, +.item.item-checkbox.item-avatar .item-content > i.item-image:first-child, +.item.item-checkbox.item-avatar * > i.avatar:first-child, +.item.item-checkbox.item-avatar * > i.item-image:first-child, +.item.item-checkbox.item-avatar * .item-content > i.avatar:first-child, +.item.item-checkbox.item-avatar * .item-content > i.item-image:first-child { + left: 65px; } + +.item.item-checkbox.item-avatar .item-content, +.item.item-checkbox .item-content .item-avatar { + padding-left: 65px; } + +/********** + Item > Right icon position +**********/ +.item-icon-left.item-icon-right.ink .icon.ion-ios-arrow-right, .item-icon-left.item-icon-right.ink .ion-ios-arrow-right.icon-help, .item-icon-left.item-icon-right.ink .ion-ios-arrow-right.icon-alert, .item-icon-left.item-icon-right.ink #menu .footer .ion-ios-arrow-right.icon-help, #menu .footer .item-icon-left.item-icon-right.ink .ion-ios-arrow-right.icon-help { + left: auto; } + +@media screen and (max-width: 767px) { + .item.item-icon-right > .icon:last-child, .item.item-icon-right > .icon-help:last-child, .item.item-icon-right > .icon-alert:last-child, #menu .footer .item.item-icon-right > .icon-help:last-child, + .item.item-icon-right > .icon.ion-ios-arrow-right, + .item.item-icon-right > .ion-ios-arrow-right.icon-help, + .item.item-icon-right > .ion-ios-arrow-right.icon-alert, + #menu .footer .item.item-icon-right > .ion-ios-arrow-right.icon-help { + right: 1px; } } + +/********** + Item > Other properties **********/ .item em { font-weight: bold !important; } +@media screen and (max-width: 991px) { + .item .badge { + right: 16px; } } + @media screen and (min-width: 992px) { .list .item.item-border-large { + margin-bottom: 1px; border-bottom: solid 1px #ccc !important; } .list.item-border-large .item { border-bottom: solid 1px #ccc !important; - margin: 0px; } + margin: 0px 0px 1px; } .list.item-border-large .item-divider { border-top: 0; } } .list .item.item-border { - border-bottom: solid 1px #ccc !important; } + border-bottom: solid 1px #ccc !important; + margin-bottom: 1px; } .list .item.item-small-height { padding-top: 2px; @@ -14949,33 +16006,99 @@ a.underline:hover, .item-input.item-button-right.item-floating-label .button-icon { height: inherit; } +/********** + Badge +**********/ /* -* Badge + Badge inside an item */ .item.item-icon-right .badge, .item.item-button-right .badge { right: 43px; } +@media screen and (max-width: 767px) { + .badge { + text-overflow: ellipsis !important; + white-space: nowrap; + overflow: hidden !important; + max-width: 300px !important; + display: block !important; } + .badge:empty { + display: none !important; } + .item.item-button-right .badge, + .item.item-icon-right .badge { + right: 26px !important; } } + +/* + Editable badge +*/ .badge-editable:hover { cursor: pointer; } .badge-editable:hover:before { content: " "; } +/* + Badge inside toolbar's button +*/ +.platform-ipad .bar-title { + border-color: #111; + background-color: #444; + background-image: linear-gradient(0deg, #111, #111 50%, transparent 50%); } + .platform-ipad .bar-title .title { + background-color: white; + margin-left: 0; + margin-right: 0; + height: 44px; } + .bar .badge-button { margin: 0 !important; - padding: 0px 4px !important; + padding: 0 4px !important; font-size: 10px; position: absolute !important; top: 5px; right: 3px; } +/********** + Editable text +**********/ +.text-editable:hover { + cursor: pointer; } + +.text-editable:hover:after { + content: ""; } + +.item h2 .text-editable:hover:after { + font-size: 14px; } + /********** Modals **********/ .modal.modal-full-height { bottom: 0px; } +@media screen and (max-width: 767px) { + .modal { + top: 0 !important; + left: 0 !important; + bottom: 0px; + min-height: 100% !important; + width: 100% !important; } } + +@media screen and (max-width: 991px) { + .modal { + bottom: 0px; } + .modal .swiper-pagination { + visibility: hidden !important; } + .modal.modal-full-height { + top: 0; } + .modal.modal-full-height ion-content.keyboard-up .scroll { + min-height: calc(100% + 67px); } } + +@media (min-width: 992px) { + .modal.modal-full-height { + min-height: 80%; } } + .modal.about .bar.bar-header .button + .title { left: 0px !important; /* avoid title offset on large screens, if button are 'visible-xs')'*/ } @@ -15059,61 +16182,81 @@ a.underline:hover, /********** Screen - Left Menu **********/ -#menu .item-button-right > .button, -.item-button-right .item-content > .button, -.item-button-right > .buttons, -.item-button-right .item-content > .buttons { - top: 8px !important; } +.menu.menu-left { + background-color: whitesmoke; } + .menu.menu-left .item { + opacity: 0.75; + color: black; } + .menu.menu-left .item-button-right > .button, + .menu.menu-left .item-button-right .item-content > .button, + .menu.menu-left .item-button-right > .buttons, + .menu.menu-left .item-button-right .item-content > .buttons { + top: 8px !important; } + .menu.menu-left .item.active { + background-color: #b2e0ff !important; } + .menu.menu-left .item.active .item-content { + background-color: transparent; } + .menu.menu-left .item-menu-disable { + color: #444 !important; } -@media screen and (max-width: 400px) { - #menu .item.item-divider { +@media screen and (max-width: 991px) { + .menu.menu-left .item.item-divider { min-height: 2px; height: 2px; padding-top: 0px; padding-bottom: 0px; } - #menu .item, - #menu .item.item-complex .item-content { + .menu.menu-left .item, + .menu.menu-left .item.item-complex .item-content { height: 40px; min-height: 40px; padding-top: 12px; } - #menu .item.item-complex { + .menu.menu-left .item.item-complex { padding-top: 0px; } - #menu .item.item-button-right .button { + .menu.menu-left .item.item-button-right .button { height: 30px; min-height: 30px; top: 4px; } - #menu .item.active a { - background-color: #b2e0ff !important; } - #menu ion-content.has-footer { + .menu.menu-left ion-content.has-footer { bottom: 0px !important; - /*ignore footer*/ } } + /*ignore footer*/ } + .menu.menu-left .bar-header { + background-color: #1A237E; + color: #fff; + height: 150px; + padding-right: 0px !important; } + .platform-ios.platform-cordova .menu.menu-left .bar-header { + height: calc(constant(safe-area-inset-top) + 150px); + height: calc(env(safe-area-inset-top) + 150px); } + .menu.menu-left .bar-header .hero { + height: 150px; + box-shadow: none; } + .menu.menu-left .bar-header .hero .content { + bottom: 0px; } + .menu.menu-left .has-header { + top: 150px; } + .platform-ios.platform-cordova .menu.menu-left .has-header { + top: calc(constant(safe-area-inset-top) + 150px); + top: calc(env(safe-area-inset-top) + 150px); } } -@media screen and (min-width: 401px) { - #menu .item.active a { - background-color: #b2e0ff !important; } - #menu .item.item-divider { +/********** + Menu +**********/ +@media screen and (min-width: 768px) { + .menu.menu-left .item.item-divider { min-height: 5px; height: 5px; } - #menu .footer a { + .menu.menu-left .footer a { font-size: 14px !important; color: grey !important; } } -@media screen and (max-width: 991px) { - #menu .bar-header { - background-color: #1A237E; - color: #fff; - height: 175px; - padding-right: 0px !important; } - #menu .bar-header .hero { - height: 175px; - box-shadow: none; } - #menu .bar-header .hero .content { - bottom: 5px; } - #menu .has-header { - top: 175px; } } - -.hero.stable-bg { - background-color: #f8f8f8 !important; } +@media screen and (min-width: 992px) { + .menu.menu-left { + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA1MDAgNTAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOmJ4PSJodHRwczovL2JveHktc3ZnLmNvbSI+CiAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoMC42MDgyNjEsIDAsIDAsIDAuNjA4MjYxLCAtMjAuMDg0OTc2LCAzLjI1NTczNikiPgogICAgPGc+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC43ODsiIGlkPSJwYXRoLTEwIiBkPSJNIDQxOS4xMzMgODUuNzM4IEMgNDE3LjI5NSA4NS43MzkgNDE1LjQ1NSA4NS43NTQgNDEzLjYxMSA4NS43NzggQyAzNTQuODUyIDg2LjU2MSAyOTkuMDIzIDk5LjE3NCAyNDguMzU4IDEyMS4zMiBDIDU4NC4xMjEgMTMuMjA2IDc5Ni4xNzUgMjExLjI2IDgzMS43IDUwOC43NzMgTCA4NDYuMzgzIDUwNy4xMjQgQyA4MTUuNTg2IDIzNS44MDEgNjUyLjQ3NyA4NS41ODggNDE5LjEzMyA4NS43MzggWiIgdHJhbnNmb3JtPSJtYXRyaXgoMC45NjM3MywgMC4yNjY4NzgsIC0wLjI2Njg3OCwgMC45NjM3MywgODkuNTA1MjMxLCAtMTM2LjYxNTA2MSkiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDE7IiBpZD0icGF0aC0zIiBkPSJNIDE0Ni4wMzcgMTk0LjA2NSBDIDE0NC4yMDEgMTk0LjA2NiAxNDIuMzYxIDE5NC4wODEgMTQwLjUxNyAxOTQuMTA0IEMgODEuNzYgMTk0Ljg4OCAyNS45MzEgMjA3LjUwMyAtMjQuNzM2IDIyOS42NDggQyAzMTEuMDI5IDEyMS41MzEgNTIzLjA4MyAzMTkuNTgzIDU1OC42MDQgNjE3LjA5MyBMIDU3My4yODQgNjE1LjQ0MyBDIDU0Mi40OSAzNDQuMTIyIDM3OS4zODUgMTkzLjkxMyAxNDYuMDM3IDE5NC4wNjUgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuMTgwOTg4LCAtMC45ODM0ODUsIDAuOTgzNDg1LCAtMC4xODA5ODgsIC0zOS4yOTg1ODEsIDcwNS44OTc1NDQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMSIgZD0iTSA0ODcuNzQ0IDE5My4wODQgQyA0ODUuOTA2IDE5My4wODUgNDg0LjA2NyAxOTMuMSA0ODIuMjIzIDE5My4xMjMgQyA0MjMuNDY0IDE5My45MDcgMzY3LjYzNSAyMDYuNTIgMzE2Ljk3NSAyMjguNjY4IEMgNjUyLjcyNiAxMjAuNTUyIDg2NC43NzUgMzE4LjYwNSA5MDAuMjk5IDYxNi4xMDkgTCA5MTQuOTc5IDYxNC40NiBDIDg4NC4xODQgMzQzLjE0NCA3MjEuMDgxIDE5Mi45MzUgNDg3Ljc0NCAxOTMuMDg0IFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNjE5OTk3LCAwLjc4NDYwNSwgLTAuNzg0NjA1LCAwLjYxOTk5NywgNTIzLjA2NzIzMSwgLTM0My4zMzE1MzkpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjg0OyIgaWQ9InBhdGgtMTIiIGQ9Ik0gMjk1Ljk2OSA0MzIuNzU3IEMgMjk0LjEzMSA0MzIuNzU4IDI5Mi4yOTMgNDMyLjc3MyAyOTAuNDQ5IDQzMi43OTcgQyAyMzEuNjg4IDQzMy41OCAxNzUuODYgNDQ2LjE5NCAxMjUuMTk4IDQ2OC4zNDEgQyA0NjAuOTU3IDM2MC4yMjYgNjczLjAwNSA1NTguMjggNzA4LjUyNiA4NTUuNzg2IEwgNzIzLjIwNyA4NTQuMTM5IEMgNjkyLjQxMiA1ODIuODE5IDUyOS4zMSA0MzIuNjA5IDI5NS45NjkgNDMyLjc1NyBaIiB0cmFuc2Zvcm09Im1hdHJpeCgtMC45Nzg4NDksIDAuMjA0NTg0LCAtMC4yMDQ1ODQsIC0wLjk3ODg0OSwgOTYzLjgyMDc5NiwgMTExNi4zNjcyOTMpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMyIgZD0iTSAxNTguMDM2IDE0OC44MyBDIDE1Ni4yIDE0OC44MzMgMTU0LjM2IDE0OC44NDYgMTUyLjUxNiAxNDguODcyIEMgOTMuNzU5IDE0OS42NTMgMzcuOTMgMTYyLjI2NyAtMTIuNzM0IDE4NC40MTEgQyAzMjMuMDIyIDc2LjMwMSA1MzUuMDc2IDI3NC4zNTIgNTcwLjYwNCA1NzEuODU3IEwgNTg1LjI4NiA1NzAuMjA4IEMgNTU0LjQ4MyAyOTguODkxIDM5MS4zOCAxNDguNjgzIDE1OC4wMzYgMTQ4LjgzIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuMzM4NjE0LCAtMC45NDA5MjYsIDAuOTQwOTI2LCAwLjMzODYxNCwgLTExNS41OTUxNTgsIDQ4My43MDU5ODQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAxOyIgaWQ9InBhdGgtMTQiIGQ9Ik0gNTAxLjAxOSAyODguMjkyIEMgNDk5LjE4MSAyODguMjkzIDQ5Ny4zNCAyODguMzA4IDQ5NS40OTYgMjg4LjMzMSBDIDQzNi43MzYgMjg5LjExNSAzODAuOTA4IDMwMS43MjYgMzMwLjI0MyAzMjMuODc0IEMgNjY2LjAwNCAyMTUuNzU3IDg3OC4wNjIgNDEzLjgxMiA5MTMuNTg2IDcxMS4zMjIgTCA5MjguMjY4IDcwOS42NzMgQyA4OTcuNDY4IDQzOC4zNTIgNzM0LjM2MSAyODguMTQxIDUwMS4wMTkgMjg4LjI5MiBaIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjE2NDY1NiwgMC45ODYzNTEsIC0wLjk4NjM1MSwgMC4xNjQ2NTYsIDk4Mi44NTcyNjYsIC0yMzMuNDUyMDYzKSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC40OyIgaWQ9InBhdGgtMTUiIGQ9Ik0gMTkyLjk1NCAzNzYuNTIxIEMgMTkxLjExNSAzNzYuNTIyIDE4OS4yNzcgMzc2LjUzNyAxODcuNDMzIDM3Ni41NjEgQyAxMjguNjc0IDM3Ny4zNDQgNzIuODQ1IDM4OS45NTggMjIuMTgxIDQxMi4xMDMgQyAzNTcuOTQgMzAzLjk4OSA1NjkuOTg3IDUwMi4wNDUgNjA1LjUwNSA3OTkuNTUzIEwgNjIwLjE4OCA3OTcuOTA1IEMgNTg5LjM5MiA1MjYuNTg0IDQyNi4yOTUgMzc2LjM2OSAxOTIuOTU0IDM3Ni41MjEgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuOTMxNDA0LCAtMC4zNjM5ODgsIDAuMzYzOTg4LCAtMC45MzE0MDQsIDQxOS40OTkwMDYsIDExODIuNTk5ODA5KSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMTsiIGlkPSJwYXRoLTE2IiBkPSJNIDIyMS42MTQgNjMuOTczIEMgMjE5Ljc3NyA2My45NzYgMjE3LjkzOCA2My45OSAyMTYuMDk0IDY0LjAxNSBDIDE1Ny4zMzQgNjQuNzk1IDEwMS41MDYgNzcuNDA5IDUwLjg0MSA5OS41NTQgQyAzODYuNTk4IC04LjU1OSA1OTguNjUxIDE4OS40OTcgNjM0LjE3MyA0ODcuMDAxIEwgNjQ4Ljg1NCA0ODUuMzU0IEMgNjE4LjA1OCAyMTQuMDM3IDQ1NC45NTQgNjMuODI0IDIyMS42MTQgNjMuOTczIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNzUwNDUyLCAtMC42NjA5MjUsIDAuNjYwOTI1LCAwLjc1MDQ1MiwgLTcwLjgwMzMyMiwgMjkwLjkyMDI3MykiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDAuNDsiIGlkPSJwYXRoLTE3IiBkPSJNIDQ0MS44ODggMzQyLjA5OCBDIDQ0MC4wNDcgMzQyLjA5OCA0MzguMjA3IDM0Mi4xMTQgNDM2LjM2MiAzNDIuMTM4IEMgMzc3LjYwMSAzNDIuOTIyIDMyMS43NjUgMzU1LjUzNSAyNzEuMTAzIDM3Ny42ODEgQyA2MDYuODg2IDI2OS41NjcgODE4Ljk0NCA0NjcuNjE1IDg1NC40NjIgNzY1LjEzMyBMIDg2OS4xNDIgNzYzLjQ4MyBDIDgzOC4zNTQgNDkyLjE1NCA2NzUuMjQyIDM0MS45NDggNDQxLjg4OCAzNDIuMDk4IFoiIHRyYW5zZm9ybT0ibWF0cml4KC0wLjM1NjU4MiwgMC45MzQyNjQsIC0wLjkzNDI2NCwgLTAuMzU2NTgyLCAxMjU2Ljc1OTQ5MywgMTY5LjE4MjU1MikiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgwLjc2MjQ5MywgMCwgMCwgMC43NjI0OTMsIDE5LjI5NDY0NywgLTcxNi4zMjI4MTUpIj4KICAgICAgICA8cGF0aCBkPSJNIDU2Ni40NjYgMTA4OS4xMzcgTCA1NjYuNDY2IDExNDguMjIyIEMgNTY1Ljg2NyAxMTQ4LjIxOSA1NjUuMjY3IDExNDguMjE3IDU2NC42NjcgMTE0OC4yMTcgQyA1NjEuNDgxIDExNDguMjE3IDU1OC4zMSAxMTQ4LjI1OSA1NTUuMTU0IDExNDguMzQxIEwgNTU1LjE1NCAxMDg5LjEzNyBaIE0gOTA4LjI5IDE0NzcuMTQ2IEwgOTU2Ljk4NyAxNDc3LjE0NiBMIDk1Ni45ODcgMTQ4OC40NTggTCA5MDguNTY5IDE0ODguNDU4IEMgOTA4LjUzOSAxNDg0LjY5MyA5MDguNDQ3IDE0ODAuOTIyIDkwOC4yOSAxNDc3LjE0NiBaIE0gNTY2LjQ2NiAxODM1LjAxMyBMIDU2Ni40NjYgMTg3Ni40NjcgTCA1NTUuMTU0IDE4NzYuNDY3IEwgNTU1LjE1NCAxODM0Ljg4NiBDIDU1OC4zMTggMTgzNC45NzMgNTYxLjQ5IDE4MzUuMDE3IDU2NC42NjcgMTgzNS4wMTcgQyA1NjUuMjY3IDE4MzUuMDE3IDU2NS44NjcgMTgzNS4wMTYgNTY2LjQ2NiAxODM1LjAxMyBaIE0gMjIwLjc3NSAxNDg4LjQ1OCBMIDE2OS42NTcgMTQ4OC40NTggTCAxNjkuNjU3IDE0NzcuMTQ2IEwgMjIxLjA4OSAxNDc3LjE0NiBDIDIyMC45MjEgMTQ4MC45MDkgMjIwLjgxNiAxNDg0LjY4IDIyMC43NzUgMTQ4OC40NTggWiIgc3R5bGU9ImZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgc3Ryb2tlOiBub25lOyIgYng6b3JpZ2luPSIwIDAiLz4KICAgICAgICA8cGF0aCBkPSJNIDc2MC4xMjEgMTE0My4zMTEgTCA3MTcuMzM2IDEyMTcuNDE3IEMgNzE1LjcyIDEyMTYuNTE4IDcxNC4wOTYgMTIxNS42MzIgNzEyLjQ2NSAxMjE0Ljc2MSBMIDc1NS4zMTggMTE0MC41MzcgWiBNIDgzMC4xMjIgMTMyNC4yMDMgTCA5MDAuNDI0IDEyODMuNjE0IEwgOTAzLjE5OCAxMjg4LjQxNyBMIDgzMy4wNCAxMzI4LjkyMyBDIDgzMi4wOCAxMzI3LjMzOSA4MzEuMTA3IDEzMjUuNzY2IDgzMC4xMjIgMTMyNC4yMDMgWiBNIDg0MC41OTkgMTY0MS4xMzcgTCA5MDMuMTk3IDE2NzcuMjc4IEwgOTAwLjQyNCAxNjgyLjA4MiBMIDgzNy45MTEgMTY0NS45OSBDIDgzOC44MjEgMTY0NC4zOCA4MzkuNzE3IDE2NDIuNzYyIDg0MC41OTkgMTY0MS4xMzcgWiBNIDcyNS4xNjggMTc2MS44NDMgTCA3NjAuMTIyIDE4MjIuMzg1IEwgNzU1LjMxOCAxODI1LjE1OCBMIDcyMC4zNzkgMTc2NC42NDEgQyA3MjEuOTg1IDE3NjMuNzIyIDcyMy41ODIgMTc2Mi43ODkgNzI1LjE2OCAxNzYxLjg0MyBaIE0gNDAzLjUzOCAxNzYwLjkzMiBMIDM2Ni40NTYgMTgyNS4xNTkgTCAzNjEuNjUzIDE4MjIuMzg2IEwgMzk4LjgwMiAxNzU4LjA0MiBDIDQwMC4zNzIgMTc1OS4wMTkgNDAxLjk1MSAxNzU5Ljk4MiA0MDMuNTM4IDE3NjAuOTMyIFogTSAyODkuNTggMTY0Mi42ODkgTCAyMjEuMzUgMTY4Mi4wODIgTCAyMTguNTc3IDE2NzcuMjc5IEwgMjg2Ljk0NCAxNjM3LjgwNyBDIDI4Ny44MDcgMTYzOS40MzcgMjg4LjY4NSAxNjQxLjA2NSAyODkuNTggMTY0Mi42ODkgWiBNIDI5NC4zNTQgMTMzMi4xNjggTCAyMTguNTc2IDEyODguNDE3IEwgMjIxLjM1IDEyODMuNjE0IEwgMjk3LjIxMyAxMzI3LjQxNCBDIDI5Ni4yNDYgMTMyOC45OSAyOTUuMjkzIDEzMzAuNTc1IDI5NC4zNTQgMTMzMi4xNjggWiBNIDQwNi4wNzkgMTIyMC4yNTkgTCAzNjEuNjUzIDExNDMuMzExIEwgMzY2LjQ1NyAxMTQwLjUzNyBMIDQxMC44ODkgMTIxNy40OTUgQyA0MDkuMjc2IDEyMTguNDAzIDQwNy42NzMgMTIxOS4zMjQgNDA2LjA3OSAxMjIwLjI1OSBaIiBzdHlsZT0iZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IG5vbmU7IiBieDpvcmlnaW49IjAgMCIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8cmVjdCB4PSI0MjkuMzY3IiB5PSI0MjUuOTc5IiB3aWR0aD0iMjAuMDAzIiBoZWlnaHQ9IjIxLjczNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTkxIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAwLjk5OTk5OSwgLTMwMS4zNzcwNzUsIC0yMTkuNDk4NDM0KSIvPgogICAgPHJlY3QgeD0iNDQ2Ljg1MyIgeT0iMjUuNDYyIiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05MyIvPgogICAgPHJlY3QgeD0iLTEzNS45NTYiIHk9IjYwNS4xNDEiIHdpZHRoPSIzOS44NTEiIGhlaWdodD0iMzkuODUxIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTQiIHRyYW5zZm9ybT0ibWF0cml4KDAuOTk5OTk5LCAwLCAwLCAxLCA4NDYuMTc2NzU2LCAtMzk0Ljk1NjAyNCkiLz4KICAgIDxyZWN0IHg9IjIyNS43NzkiIHk9IjY4OS44MzYiIHdpZHRoPSIyNS45OSIgaGVpZ2h0PSIyNS45OSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk1Ii8+CiAgICA8cmVjdCB4PSI1OTQuMDEzIiB5PSI3MzcuMTQyIiB3aWR0aD0iMjAuNzkyIiBoZWlnaHQ9IjIyLjUyNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk2Ii8+CiAgICA8cmVjdCB4PSIzODcuMjM1IiB5PSI0NzkuMzk3IiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05OCIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMDAwMDEsIDAsIDAsIDAuOTk5OTk5LCAzNjUuMjc0OTY2LCA3OS4yOTUyNDEpIi8+CiAgICA8cmVjdCB4PSI0MjEuOTYyIiB5PSI3NzUuOTM3IiB3aWR0aD0iMzIuOTIiIGhlaWdodD0iMzQuNjUzIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTkiLz4KICAgIDxyZWN0IHg9Ii02Ni45MzkiIHk9Ii01NjguOTc4IiB3aWR0aD0iMjAuODY3IiBoZWlnaHQ9IjIwLjc5MiIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTEwMSIgdHJhbnNmb3JtPSJtYXRyaXgoLTEsIDAsIDAsIDAuOTk5OTk3LCAzMS4zNTY5MjgsIDk4NC43MzYzMDYpIi8+CiAgPC9nPgo8L3N2Zz4=); + background-repeat: no-repeat; + background-position: -500px -100px; + background-size: 1024px 1024px; + background-color: whitesmoke; + height: 100%; } } /********** Screen - identity Certifications @@ -15279,24 +16422,33 @@ a.underline:hover, font-style: italic; top: 37px; font-weight: normal !important; - margin-right: 0px; - padding-right: 0px; } + margin-right: 0; + padding: 3px 8px; } + +.list .item-avatar .badge.badge-avatar { + position: absolute !important; + left: 60px !important; + right: inherit !important; + top: 15px !important; + margin: 0 !important; + padding: 0 4px !important; + font-size: 10px; } /********** Login method popover **********/ .popover.popover-login-methods { height: 280px; - width: 260px; } + width: 290px; } .popover.popover-login-methods.auth { height: 204px; } @media (max-width: 767px) { .popover.popover-login-methods { - height: 233px; } + height: 256px; } .popover.popover-login-methods.auth { - height: 152px; } } + height: 204px; } } /********** Item peer @@ -15350,6 +16502,9 @@ a.underline:hover, left: 25px; top: -7px; } +/********** + Drop zone component +**********/ div[dropzone] { border: 2px dashed #bbb; border-radius: 5px; @@ -15357,12 +16512,32 @@ div[dropzone] { text-align: center; font: 20pt bold; color: #bbb; - margin-bottom: 20px; } + margin-bottom: 20px; + cursor: pointer; } + div[dropzone] .list .item, + div[dropzone] .item { + text-align: left; } + +div[dropzone]:hover { + background-color: #f2f2f2; } .hero .button-fab-top-right, -.hero .button-fab-top-left { +.hero .button-fab-top-left, +.button-fab-hero.button-fab-top-right, +.button-fab-hero.button-fab-top-left { top: 170px !important; } +.button.button-fab.mini, +.bar .button.button-fab.mini { + min-width: 40px; + min-height: 40px; } + +.hero .button-fab-top-right.mini, +.hero .button-fab-top-left.mini, +.button-fab-hero.button-fab-top-right.mini, +.button-fab-hero.button-fab-top-left.mini { + top: 178px !important; } + .text-no-transform { text-transform: inherit; } @@ -15375,24 +16550,25 @@ div[dropzone] { .button-icon-event .icon, .button-icon-event .icon-help, .button-icon-event .icon-alert, - .button-icon-event #menu .footer .icon-help, #menu .footer - .button-icon-event .icon-help, + .button-icon-event #menu .footer .icon-help, + #menu .footer .button-icon-event .icon-help, .button-icon-event .icon-event { pointer-events: all !important; } /********** Wot identity **********/ -.hero.dark-bg, .view-identity .hero, -.view-identity .hero.refresher-top-bg:before { +.hero.dark-100-bg { background-color: #555; } -.hero.positive-900-bg, .view-wallet .hero.refresher-top-bg:before, .view-wallet-tx .hero.refresher-top-bg:before, .view-identity .member .hero, -.view-identity .hero.member.refresher-top-bg:before { +.hero.positive-900-bg { background-color: #1A237E !important; } +.hero.stable-bg { + background-color: #f8f8f8 !important; } + .popover-locked-outputs .item .badge { - right: 16px; } + right: 16px !important; } /************************ Animation hide/show @@ -15407,18 +16583,23 @@ div[dropzone] { /********** join wizard modal **********/ -@media screen and (max-width: 991px) { +.modal iframe.iframe-license { + width: 100%; + height: calc(100% - 171px) !important; } + +@media screen and (max-width: 767px) { .modal iframe.iframe-license { - width: 100%; - height: 78%; } } + height: calc(100% - 104px); } } + +@media screen and (min-width: 768px) and (max-width: 991px) and (min-height: 600px) { + .modal iframe.iframe-license { + height: calc(100% - 171px); } } @media screen and (min-width: 992px) { .modal iframe.iframe-license { - width: 100%; - height: 70%; } + height: calc(100% - 171px); } .modal.modal-license iframe.iframe-license { - width: 100%; - height: 85% !important; } } + height: calc(100% - 111px) !important; } } /********** Help modal diff --git a/assets/www/css/ionic.app.min.css b/assets/www/css/ionic.app.min.css index 779b61ee8aebe2c583ef583997628de58bf25e3c..f6c6bd33a3c84225983b488a7edc6ca8a97ca141 100644 --- a/assets/www/css/ionic.app.min.css +++ b/assets/www/css/ionic.app.min.css @@ -2,13 +2,13 @@ Ionicons, v2.0.1 Created by Ben Sperry for the Ionic Framework, http://ionicons.com/ https://twitter.com/benjsperry https://twitter.com/ionicframework - MIT License: https://github.com/driftyco/ionicons + MIT License: https://github.com/ionic-team/ionicons Android-style icons originally built by Google’s Material Design Icons: https://github.com/google/material-design-icons used under CC BY http://creativecommons.org/licenses/by/4.0/ Modified icons to fit ionicon’s grid from original. -*/@font-face{font-family:Ionicons;src:url(../lib/ionic/fonts/ionicons.eot?v=2.0.1);src:url(../lib/ionic/fonts/ionicons.eot?v=2.0.1#iefix) format("embedded-opentype"),url(../lib/ionic/fonts/ionicons.ttf?v=2.0.1) format("truetype"),url(../lib/ionic/fonts/ionicons.woff?v=2.0.1) format("woff"),url(../lib/ionic/fonts/ionicons.woff) format("woff"),url(../lib/ionic/fonts/ionicons.svg?v=2.0.1#Ionicons) format("svg");font-weight:400;font-style:normal}#menu .footer .icon-help:before,.badge-editable:hover:before,.icon-alert:before,.icon-help:before,.ion,.ion-alert-circled:before,.ion-alert:before,.ion-android-add-circle:before,.ion-android-add:before,.ion-android-alarm-clock:before,.ion-android-alert:before,.ion-android-apps:before,.ion-android-archive:before,.ion-android-arrow-back:before,.ion-android-arrow-down:before,.ion-android-arrow-dropdown-circle:before,.ion-android-arrow-dropdown:before,.ion-android-arrow-dropleft-circle:before,.ion-android-arrow-dropleft:before,.ion-android-arrow-dropright-circle:before,.ion-android-arrow-dropright:before,.ion-android-arrow-dropup-circle:before,.ion-android-arrow-dropup:before,.ion-android-arrow-forward:before,.ion-android-arrow-up:before,.ion-android-attach:before,.ion-android-bar:before,.ion-android-bicycle:before,.ion-android-boat:before,.ion-android-bookmark:before,.ion-android-bulb:before,.ion-android-bus:before,.ion-android-calendar:before,.ion-android-call:before,.ion-android-camera:before,.ion-android-cancel:before,.ion-android-car:before,.ion-android-cart:before,.ion-android-chat:before,.ion-android-checkbox-blank:before,.ion-android-checkbox-outline-blank:before,.ion-android-checkbox-outline:before,.ion-android-checkbox:before,.ion-android-checkmark-circle:before,.ion-android-clipboard:before,.ion-android-close:before,.ion-android-cloud-circle:before,.ion-android-cloud-done:before,.ion-android-cloud-outline:before,.ion-android-cloud:before,.ion-android-color-palette:before,.ion-android-compass:before,.ion-android-contact:before,.ion-android-contacts:before,.ion-android-contract:before,.ion-android-create:before,.ion-android-delete:before,.ion-android-desktop:before,.ion-android-document:before,.ion-android-done-all:before,.ion-android-done:before,.ion-android-download:before,.ion-android-drafts:before,.ion-android-exit:before,.ion-android-expand:before,.ion-android-favorite-outline:before,.ion-android-favorite:before,.ion-android-film:before,.ion-android-folder-open:before,.ion-android-folder:before,.ion-android-funnel:before,.ion-android-globe:before,.ion-android-hand:before,.ion-android-hangout:before,.ion-android-happy:before,.ion-android-home:before,.ion-android-image:before,.ion-android-laptop:before,.ion-android-list:before,.ion-android-locate:before,.ion-android-lock:before,.ion-android-mail:before,.ion-android-map:before,.ion-android-menu:before,.ion-android-microphone-off:before,.ion-android-microphone:before,.ion-android-more-horizontal:before,.ion-android-more-vertical:before,.ion-android-navigate:before,.ion-android-notifications-none:before,.ion-android-notifications-off:before,.ion-android-notifications:before,.ion-android-open:before,.ion-android-options:before,.ion-android-people:before,.ion-android-person-add:before,.ion-android-person:before,.ion-android-phone-landscape:before,.ion-android-phone-portrait:before,.ion-android-pin:before,.ion-android-plane:before,.ion-android-playstore:before,.ion-android-print:before,.ion-android-radio-button-off:before,.ion-android-radio-button-on:before,.ion-android-refresh:before,.ion-android-remove-circle:before,.ion-android-remove:before,.ion-android-restaurant:before,.ion-android-sad:before,.ion-android-search:before,.ion-android-send:before,.ion-android-settings:before,.ion-android-share-alt:before,.ion-android-share:before,.ion-android-star-half:before,.ion-android-star-outline:before,.ion-android-star:before,.ion-android-stopwatch:before,.ion-android-subway:before,.ion-android-sunny:before,.ion-android-sync:before,.ion-android-textsms:before,.ion-android-time:before,.ion-android-train:before,.ion-android-unlock:before,.ion-android-upload:before,.ion-android-volume-down:before,.ion-android-volume-mute:before,.ion-android-volume-off:before,.ion-android-volume-up:before,.ion-android-walk:before,.ion-android-warning:before,.ion-android-watch:before,.ion-android-wifi:before,.ion-aperture:before,.ion-archive:before,.ion-arrow-down-a:before,.ion-arrow-down-b:before,.ion-arrow-down-c:before,.ion-arrow-expand:before,.ion-arrow-graph-down-left:before,.ion-arrow-graph-down-right:before,.ion-arrow-graph-up-left:before,.ion-arrow-graph-up-right:before,.ion-arrow-left-a:before,.ion-arrow-left-b:before,.ion-arrow-left-c:before,.ion-arrow-move:before,.ion-arrow-resize:before,.ion-arrow-return-left:before,.ion-arrow-return-right:before,.ion-arrow-right-a:before,.ion-arrow-right-b:before,.ion-arrow-right-c:before,.ion-arrow-shrink:before,.ion-arrow-swap:before,.ion-arrow-up-a:before,.ion-arrow-up-b:before,.ion-arrow-up-c:before,.ion-asterisk:before,.ion-at:before,.ion-backspace-outline:before,.ion-backspace:before,.ion-bag:before,.ion-battery-charging:before,.ion-battery-empty:before,.ion-battery-full:before,.ion-battery-half:before,.ion-battery-low:before,.ion-beaker:before,.ion-beer:before,.ion-bluetooth:before,.ion-bonfire:before,.ion-bookmark:before,.ion-bowtie:before,.ion-briefcase:before,.ion-bug:before,.ion-calculator:before,.ion-calendar:before,.ion-camera:before,.ion-card:before,.ion-cash:before,.ion-chatbox-working:before,.ion-chatbox:before,.ion-chatboxes:before,.ion-chatbubble-working:before,.ion-chatbubble:before,.ion-chatbubbles:before,.ion-checkmark-circled:before,.ion-checkmark-round:before,.ion-checkmark:before,.ion-chevron-down:before,.ion-chevron-left:before,.ion-chevron-right:before,.ion-chevron-up:before,.ion-clipboard:before,.ion-clock:before,.ion-close-circled:before,.ion-close-round:before,.ion-close:before,.ion-closed-captioning:before,.ion-cloud:before,.ion-code-download:before,.ion-code-working:before,.ion-code:before,.ion-coffee:before,.ion-compass:before,.ion-compose:before,.ion-connection-bars:before,.ion-contrast:before,.ion-crop:before,.ion-cube:before,.ion-disc:before,.ion-document-text:before,.ion-document:before,.ion-drag:before,.ion-earth:before,.ion-easel:before,.ion-edit:before,.ion-egg:before,.ion-eject:before,.ion-email-unread:before,.ion-email:before,.ion-erlenmeyer-flask-bubbles:before,.ion-erlenmeyer-flask:before,.ion-eye-disabled:before,.ion-eye:before,.ion-female:before,.ion-filing:before,.ion-film-marker:before,.ion-fireball:before,.ion-flag:before,.ion-flame:before,.ion-flash-off:before,.ion-flash:before,.ion-folder:before,.ion-fork-repo:before,.ion-fork:before,.ion-forward:before,.ion-funnel:before,.ion-gear-a:before,.ion-gear-b:before,.ion-grid:before,.ion-hammer:before,.ion-happy-outline:before,.ion-happy:before,.ion-headphone:before,.ion-heart-broken:before,.ion-heart:before,.ion-help-buoy:before,.ion-help-circled:before,.ion-help:before,.ion-home:before,.ion-icecream:before,.ion-image:before,.ion-images:before,.ion-information-circled:before,.ion-information:before,.ion-ionic:before,.ion-ios-alarm-outline:before,.ion-ios-alarm:before,.ion-ios-albums-outline:before,.ion-ios-albums:before,.ion-ios-americanfootball-outline:before,.ion-ios-americanfootball:before,.ion-ios-analytics-outline:before,.ion-ios-analytics:before,.ion-ios-arrow-back:before,.ion-ios-arrow-down:before,.ion-ios-arrow-forward:before,.ion-ios-arrow-left:before,.ion-ios-arrow-right:before,.ion-ios-arrow-thin-down:before,.ion-ios-arrow-thin-left:before,.ion-ios-arrow-thin-right:before,.ion-ios-arrow-thin-up:before,.ion-ios-arrow-up:before,.ion-ios-at-outline:before,.ion-ios-at:before,.ion-ios-barcode-outline:before,.ion-ios-barcode:before,.ion-ios-baseball-outline:before,.ion-ios-baseball:before,.ion-ios-basketball-outline:before,.ion-ios-basketball:before,.ion-ios-bell-outline:before,.ion-ios-bell:before,.ion-ios-body-outline:before,.ion-ios-body:before,.ion-ios-bolt-outline:before,.ion-ios-bolt:before,.ion-ios-book-outline:before,.ion-ios-book:before,.ion-ios-bookmarks-outline:before,.ion-ios-bookmarks:before,.ion-ios-box-outline:before,.ion-ios-box:before,.ion-ios-briefcase-outline:before,.ion-ios-briefcase:before,.ion-ios-browsers-outline:before,.ion-ios-browsers:before,.ion-ios-calculator-outline:before,.ion-ios-calculator:before,.ion-ios-calendar-outline:before,.ion-ios-calendar:before,.ion-ios-camera-outline:before,.ion-ios-camera:before,.ion-ios-cart-outline:before,.ion-ios-cart:before,.ion-ios-chatboxes-outline:before,.ion-ios-chatboxes:before,.ion-ios-chatbubble-outline:before,.ion-ios-chatbubble:before,.ion-ios-checkmark-empty:before,.ion-ios-checkmark-outline:before,.ion-ios-checkmark:before,.ion-ios-circle-filled:before,.ion-ios-circle-outline:before,.ion-ios-clock-outline:before,.ion-ios-clock:before,.ion-ios-close-empty:before,.ion-ios-close-outline:before,.ion-ios-close:before,.ion-ios-cloud-download-outline:before,.ion-ios-cloud-download:before,.ion-ios-cloud-outline:before,.ion-ios-cloud-upload-outline:before,.ion-ios-cloud-upload:before,.ion-ios-cloud:before,.ion-ios-cloudy-night-outline:before,.ion-ios-cloudy-night:before,.ion-ios-cloudy-outline:before,.ion-ios-cloudy:before,.ion-ios-cog-outline:before,.ion-ios-cog:before,.ion-ios-color-filter-outline:before,.ion-ios-color-filter:before,.ion-ios-color-wand-outline:before,.ion-ios-color-wand:before,.ion-ios-compose-outline:before,.ion-ios-compose:before,.ion-ios-contact-outline:before,.ion-ios-contact:before,.ion-ios-copy-outline:before,.ion-ios-copy:before,.ion-ios-crop-strong:before,.ion-ios-crop:before,.ion-ios-download-outline:before,.ion-ios-download:before,.ion-ios-drag:before,.ion-ios-email-outline:before,.ion-ios-email:before,.ion-ios-eye-outline:before,.ion-ios-eye:before,.ion-ios-fastforward-outline:before,.ion-ios-fastforward:before,.ion-ios-filing-outline:before,.ion-ios-filing:before,.ion-ios-film-outline:before,.ion-ios-film:before,.ion-ios-flag-outline:before,.ion-ios-flag:before,.ion-ios-flame-outline:before,.ion-ios-flame:before,.ion-ios-flask-outline:before,.ion-ios-flask:before,.ion-ios-flower-outline:before,.ion-ios-flower:before,.ion-ios-folder-outline:before,.ion-ios-folder:before,.ion-ios-football-outline:before,.ion-ios-football:before,.ion-ios-game-controller-a-outline:before,.ion-ios-game-controller-a:before,.ion-ios-game-controller-b-outline:before,.ion-ios-game-controller-b:before,.ion-ios-gear-outline:before,.ion-ios-gear:before,.ion-ios-glasses-outline:before,.ion-ios-glasses:before,.ion-ios-grid-view-outline:before,.ion-ios-grid-view:before,.ion-ios-heart-outline:before,.ion-ios-heart:before,.ion-ios-help-empty:before,.ion-ios-help-outline:before,.ion-ios-help:before,.ion-ios-home-outline:before,.ion-ios-home:before,.ion-ios-infinite-outline:before,.ion-ios-infinite:before,.ion-ios-information-empty:before,.ion-ios-information-outline:before,.ion-ios-information:before,.ion-ios-ionic-outline:before,.ion-ios-keypad-outline:before,.ion-ios-keypad:before,.ion-ios-lightbulb-outline:before,.ion-ios-lightbulb:before,.ion-ios-list-outline:before,.ion-ios-list:before,.ion-ios-location-outline:before,.ion-ios-location:before,.ion-ios-locked-outline:before,.ion-ios-locked:before,.ion-ios-loop-strong:before,.ion-ios-loop:before,.ion-ios-medical-outline:before,.ion-ios-medical:before,.ion-ios-medkit-outline:before,.ion-ios-medkit:before,.ion-ios-mic-off:before,.ion-ios-mic-outline:before,.ion-ios-mic:before,.ion-ios-minus-empty:before,.ion-ios-minus-outline:before,.ion-ios-minus:before,.ion-ios-monitor-outline:before,.ion-ios-monitor:before,.ion-ios-moon-outline:before,.ion-ios-moon:before,.ion-ios-more-outline:before,.ion-ios-more:before,.ion-ios-musical-note:before,.ion-ios-musical-notes:before,.ion-ios-navigate-outline:before,.ion-ios-navigate:before,.ion-ios-nutrition-outline:before,.ion-ios-nutrition:before,.ion-ios-paper-outline:before,.ion-ios-paper:before,.ion-ios-paperplane-outline:before,.ion-ios-paperplane:before,.ion-ios-partlysunny-outline:before,.ion-ios-partlysunny:before,.ion-ios-pause-outline:before,.ion-ios-pause:before,.ion-ios-paw-outline:before,.ion-ios-paw:before,.ion-ios-people-outline:before,.ion-ios-people:before,.ion-ios-person-outline:before,.ion-ios-person:before,.ion-ios-personadd-outline:before,.ion-ios-personadd:before,.ion-ios-photos-outline:before,.ion-ios-photos:before,.ion-ios-pie-outline:before,.ion-ios-pie:before,.ion-ios-pint-outline:before,.ion-ios-pint:before,.ion-ios-play-outline:before,.ion-ios-play:before,.ion-ios-plus-empty:before,.ion-ios-plus-outline:before,.ion-ios-plus:before,.ion-ios-pricetag-outline:before,.ion-ios-pricetag:before,.ion-ios-pricetags-outline:before,.ion-ios-pricetags:before,.ion-ios-printer-outline:before,.ion-ios-printer:before,.ion-ios-pulse-strong:before,.ion-ios-pulse:before,.ion-ios-rainy-outline:before,.ion-ios-rainy:before,.ion-ios-recording-outline:before,.ion-ios-recording:before,.ion-ios-redo-outline:before,.ion-ios-redo:before,.ion-ios-refresh-empty:before,.ion-ios-refresh-outline:before,.ion-ios-refresh:before,.ion-ios-reload:before,.ion-ios-reverse-camera-outline:before,.ion-ios-reverse-camera:before,.ion-ios-rewind-outline:before,.ion-ios-rewind:before,.ion-ios-rose-outline:before,.ion-ios-rose:before,.ion-ios-search-strong:before,.ion-ios-search:before,.ion-ios-settings-strong:before,.ion-ios-settings:before,.ion-ios-shuffle-strong:before,.ion-ios-shuffle:before,.ion-ios-skipbackward-outline:before,.ion-ios-skipbackward:before,.ion-ios-skipforward-outline:before,.ion-ios-skipforward:before,.ion-ios-snowy:before,.ion-ios-speedometer-outline:before,.ion-ios-speedometer:before,.ion-ios-star-half:before,.ion-ios-star-outline:before,.ion-ios-star:before,.ion-ios-stopwatch-outline:before,.ion-ios-stopwatch:before,.ion-ios-sunny-outline:before,.ion-ios-sunny:before,.ion-ios-telephone-outline:before,.ion-ios-telephone:before,.ion-ios-tennisball-outline:before,.ion-ios-tennisball:before,.ion-ios-thunderstorm-outline:before,.ion-ios-thunderstorm:before,.ion-ios-time-outline:before,.ion-ios-time:before,.ion-ios-timer-outline:before,.ion-ios-timer:before,.ion-ios-toggle-outline:before,.ion-ios-toggle:before,.ion-ios-trash-outline:before,.ion-ios-trash:before,.ion-ios-undo-outline:before,.ion-ios-undo:before,.ion-ios-unlocked-outline:before,.ion-ios-unlocked:before,.ion-ios-upload-outline:before,.ion-ios-upload:before,.ion-ios-videocam-outline:before,.ion-ios-videocam:before,.ion-ios-volume-high:before,.ion-ios-volume-low:before,.ion-ios-wineglass-outline:before,.ion-ios-wineglass:before,.ion-ios-world-outline:before,.ion-ios-world:before,.ion-ipad:before,.ion-iphone:before,.ion-ipod:before,.ion-jet:before,.ion-key:before,.ion-knife:before,.ion-laptop:before,.ion-leaf:before,.ion-levels:before,.ion-lightbulb:before,.ion-link:before,.ion-load-a:before,.ion-load-b:before,.ion-load-c:before,.ion-load-d:before,.ion-location:before,.ion-lock-combination:before,.ion-locked:before,.ion-log-in:before,.ion-log-out:before,.ion-loop:before,.ion-magnet:before,.ion-male:before,.ion-man:before,.ion-map:before,.ion-medkit:before,.ion-merge:before,.ion-mic-a:before,.ion-mic-b:before,.ion-mic-c:before,.ion-minus-circled:before,.ion-minus-round:before,.ion-minus:before,.ion-model-s:before,.ion-monitor:before,.ion-more:before,.ion-mouse:before,.ion-music-note:before,.ion-navicon-round:before,.ion-navicon:before,.ion-navigate:before,.ion-network:before,.ion-no-smoking:before,.ion-nuclear:before,.ion-outlet:before,.ion-paintbrush:before,.ion-paintbucket:before,.ion-paper-airplane:before,.ion-paperclip:before,.ion-pause:before,.ion-person-add:before,.ion-person-stalker:before,.ion-person:before,.ion-pie-graph:before,.ion-pin:before,.ion-pinpoint:before,.ion-pizza:before,.ion-plane:before,.ion-planet:before,.ion-play:before,.ion-playstation:before,.ion-plus-circled:before,.ion-plus-round:before,.ion-plus:before,.ion-podium:before,.ion-pound:before,.ion-power:before,.ion-pricetag:before,.ion-pricetags:before,.ion-printer:before,.ion-pull-request:before,.ion-qr-scanner:before,.ion-quote:before,.ion-radio-waves:before,.ion-record:before,.ion-refresh:before,.ion-reply-all:before,.ion-reply:before,.ion-ribbon-a:before,.ion-ribbon-b:before,.ion-sad-outline:before,.ion-sad:before,.ion-scissors:before,.ion-search:before,.ion-settings:before,.ion-share:before,.ion-shuffle:before,.ion-skip-backward:before,.ion-skip-forward:before,.ion-social-android-outline:before,.ion-social-android:before,.ion-social-angular-outline:before,.ion-social-angular:before,.ion-social-apple-outline:before,.ion-social-apple:before,.ion-social-bitcoin-outline:before,.ion-social-bitcoin:before,.ion-social-buffer-outline:before,.ion-social-buffer:before,.ion-social-chrome-outline:before,.ion-social-chrome:before,.ion-social-codepen-outline:before,.ion-social-codepen:before,.ion-social-css3-outline:before,.ion-social-css3:before,.ion-social-designernews-outline:before,.ion-social-designernews:before,.ion-social-dribbble-outline:before,.ion-social-dribbble:before,.ion-social-dropbox-outline:before,.ion-social-dropbox:before,.ion-social-euro-outline:before,.ion-social-euro:before,.ion-social-facebook-outline:before,.ion-social-facebook:before,.ion-social-foursquare-outline:before,.ion-social-foursquare:before,.ion-social-freebsd-devil:before,.ion-social-github-outline:before,.ion-social-github:before,.ion-social-google-outline:before,.ion-social-google:before,.ion-social-googleplus-outline:before,.ion-social-googleplus:before,.ion-social-hackernews-outline:before,.ion-social-hackernews:before,.ion-social-html5-outline:before,.ion-social-html5:before,.ion-social-instagram-outline:before,.ion-social-instagram:before,.ion-social-javascript-outline:before,.ion-social-javascript:before,.ion-social-linkedin-outline:before,.ion-social-linkedin:before,.ion-social-markdown:before,.ion-social-nodejs:before,.ion-social-octocat:before,.ion-social-pinterest-outline:before,.ion-social-pinterest:before,.ion-social-python:before,.ion-social-reddit-outline:before,.ion-social-reddit:before,.ion-social-rss-outline:before,.ion-social-rss:before,.ion-social-sass:before,.ion-social-skype-outline:before,.ion-social-skype:before,.ion-social-snapchat-outline:before,.ion-social-snapchat:before,.ion-social-tumblr-outline:before,.ion-social-tumblr:before,.ion-social-tux:before,.ion-social-twitch-outline:before,.ion-social-twitch:before,.ion-social-twitter-outline:before,.ion-social-twitter:before,.ion-social-usd-outline:before,.ion-social-usd:before,.ion-social-vimeo-outline:before,.ion-social-vimeo:before,.ion-social-whatsapp-outline:before,.ion-social-whatsapp:before,.ion-social-windows-outline:before,.ion-social-windows:before,.ion-social-wordpress-outline:before,.ion-social-wordpress:before,.ion-social-yahoo-outline:before,.ion-social-yahoo:before,.ion-social-yen-outline:before,.ion-social-yen:before,.ion-social-youtube-outline:before,.ion-social-youtube:before,.ion-soup-can-outline:before,.ion-soup-can:before,.ion-speakerphone:before,.ion-speedometer:before,.ion-spoon:before,.ion-star:before,.ion-stats-bars:before,.ion-steam:before,.ion-stop:before,.ion-thermometer:before,.ion-thumbsdown:before,.ion-thumbsup:before,.ion-toggle-filled:before,.ion-toggle:before,.ion-transgender:before,.ion-trash-a:before,.ion-trash-b:before,.ion-trophy:before,.ion-tshirt-outline:before,.ion-tshirt:before,.ion-umbrella:before,.ion-university:before,.ion-unlocked:before,.ion-upload:before,.ion-usb:before,.ion-videocamera:before,.ion-volume-high:before,.ion-volume-low:before,.ion-volume-medium:before,.ion-volume-mute:before,.ion-wand:before,.ion-waterdrop:before,.ion-wifi:before,.ion-wineglass:before,.ion-woman:before,.ion-wrench:before,.ion-xbox:before,.ionicons{display:inline-block;font-family:Ionicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ion-alert:before{content:"ï„"}.ion-alert-circled:before{content:"ï„€"}.ion-android-add:before{content:""}.ion-android-add-circle:before{content:"ï™"}.ion-android-alarm-clock:before{content:"ïš"}.icon-alert:before,.ion-android-alert:before{content:"ï›"}.ion-android-apps:before{content:"ïœ"}.ion-android-archive:before{content:""}.ion-android-arrow-back:before{content:""}.ion-android-arrow-down:before{content:"ï"}.ion-android-arrow-dropdown:before{content:"ïŸ"}.ion-android-arrow-dropdown-circle:before{content:"ïž"}.ion-android-arrow-dropleft:before{content:"ï¡"}.ion-android-arrow-dropleft-circle:before{content:"ï "}.ion-android-arrow-dropright:before{content:"ï£"}.ion-android-arrow-dropright-circle:before{content:"ï¢"}.ion-android-arrow-dropup:before{content:"ï¥"}.ion-android-arrow-dropup-circle:before{content:"ï¤"}.ion-android-arrow-forward:before{content:"ïŒ"}.ion-android-arrow-up:before{content:"ï¦"}.ion-android-attach:before{content:"ï§"}.ion-android-bar:before{content:"ï¨"}.ion-android-bicycle:before{content:"ï©"}.ion-android-boat:before{content:"ïª"}.ion-android-bookmark:before{content:"ï«"}.ion-android-bulb:before{content:"ï¬"}.ion-android-bus:before{content:"ï"}.ion-android-calendar:before{content:"ï‹‘"}.ion-android-call:before{content:"ï‹’"}.ion-android-camera:before{content:"ï‹“"}.ion-android-cancel:before{content:"ï®"}.ion-android-car:before{content:"ï¯"}.ion-android-cart:before{content:"ï°"}.ion-android-chat:before{content:"ï‹”"}.ion-android-checkbox:before{content:"ï´"}.ion-android-checkbox-blank:before{content:"ï±"}.ion-android-checkbox-outline:before{content:"ï³"}.ion-android-checkbox-outline-blank:before{content:"ï²"}.ion-android-checkmark-circle:before{content:"ïµ"}.ion-android-clipboard:before{content:"ï¶"}.ion-android-close:before{content:"ï‹—"}.ion-android-cloud:before{content:"ïº"}.ion-android-cloud-circle:before{content:"ï·"}.ion-android-cloud-done:before{content:"ï¸"}.ion-android-cloud-outline:before{content:"ï¹"}.ion-android-color-palette:before{content:"ï»"}.ion-android-compass:before{content:"ï¼"}.ion-android-contact:before{content:""}.ion-android-contacts:before{content:"ï‹™"}.ion-android-contract:before{content:"ï½"}.ion-android-create:before{content:"ï¾"}.ion-android-delete:before{content:"ï¿"}.ion-android-desktop:before{content:""}.ion-android-document:before{content:"ïŽ"}.ion-android-done:before{content:""}.ion-android-done-all:before{content:""}.ion-android-download:before{content:"ï‹"}.ion-android-drafts:before{content:""}.ion-android-exit:before{content:""}.ion-android-expand:before{content:""}.ion-android-favorite:before{content:""}.ion-android-favorite-outline:before{content:""}.ion-android-film:before{content:""}.ion-android-folder:before{content:"ï‹ "}.ion-android-folder-open:before{content:""}.ion-android-funnel:before{content:""}.ion-android-globe:before{content:""}.ion-android-hand:before{content:"ï‹£"}.ion-android-hangout:before{content:"ïŽ"}.ion-android-happy:before{content:""}.ion-android-home:before{content:"ïŽ"}.ion-android-image:before{content:""}.ion-android-laptop:before{content:"ïŽ"}.ion-android-list:before{content:""}.ion-android-locate:before{content:"ï‹©"}.ion-android-lock:before{content:""}.ion-android-mail:before{content:"ï‹«"}.ion-android-map:before{content:""}.ion-android-menu:before{content:""}.ion-android-microphone:before{content:""}.ion-android-microphone-off:before{content:""}.ion-android-more-horizontal:before{content:""}.ion-android-more-vertical:before{content:""}.ion-android-navigate:before{content:""}.ion-android-notifications:before{content:""}.ion-android-notifications-none:before{content:""}.ion-android-notifications-off:before{content:""}.ion-android-open:before{content:""}.ion-android-options:before{content:"ïŽ"}.ion-android-people:before{content:""}.ion-android-person:before{content:"ïŽ "}.ion-android-person-add:before{content:""}.ion-android-phone-landscape:before{content:""}.ion-android-phone-portrait:before{content:""}.ion-android-pin:before{content:""}.ion-android-plane:before{content:""}.ion-android-playstore:before{content:"ï‹°"}.ion-android-print:before{content:""}.ion-android-radio-button-off:before{content:""}.ion-android-radio-button-on:before{content:""}.ion-android-refresh:before{content:""}.ion-android-remove:before{content:"ï‹´"}.ion-android-remove-circle:before{content:""}.ion-android-restaurant:before{content:""}.ion-android-sad:before{content:""}.ion-android-search:before{content:""}.ion-android-send:before{content:"ï‹¶"}.ion-android-settings:before{content:"ï‹·"}.ion-android-share:before{content:""}.ion-android-share-alt:before{content:""}.ion-android-star:before{content:""}.ion-android-star-half:before{content:"ïŽ"}.ion-android-star-outline:before{content:""}.ion-android-stopwatch:before{content:""}.ion-android-subway:before{content:""}.ion-android-sunny:before{content:""}.ion-android-sync:before{content:""}.ion-android-textsms:before{content:""}.ion-android-time:before{content:""}.ion-android-train:before{content:""}.ion-android-unlock:before{content:""}.ion-android-upload:before{content:""}.ion-android-volume-down:before{content:""}.ion-android-volume-mute:before{content:""}.ion-android-volume-off:before{content:""}.ion-android-volume-up:before{content:""}.ion-android-walk:before{content:""}.ion-android-warning:before{content:""}.ion-android-watch:before{content:""}.ion-android-wifi:before{content:""}.ion-aperture:before{content:""}.ion-archive:before{content:"ï„‚"}.ion-arrow-down-a:before{content:""}.ion-arrow-down-b:before{content:"ï„„"}.ion-arrow-down-c:before{content:"ï„…"}.ion-arrow-expand:before{content:""}.ion-arrow-graph-down-left:before{content:""}.ion-arrow-graph-down-right:before{content:"ï‰ "}.ion-arrow-graph-up-left:before{content:""}.ion-arrow-graph-up-right:before{content:""}.ion-arrow-left-a:before{content:""}.ion-arrow-left-b:before{content:""}.ion-arrow-left-c:before{content:""}.ion-arrow-move:before{content:""}.ion-arrow-resize:before{content:""}.ion-arrow-return-left:before{content:""}.ion-arrow-return-right:before{content:""}.ion-arrow-right-a:before{content:""}.ion-arrow-right-b:before{content:""}.ion-arrow-right-c:before{content:"ï„‹"}.ion-arrow-shrink:before{content:""}.ion-arrow-swap:before{content:""}.ion-arrow-up-a:before{content:""}.ion-arrow-up-b:before{content:"ï„"}.ion-arrow-up-c:before{content:""}.ion-asterisk:before{content:""}.ion-at:before{content:"ï„"}.ion-backspace:before{content:""}.ion-backspace-outline:before{content:""}.ion-bag:before{content:"ï„"}.ion-battery-charging:before{content:"ï„‘"}.ion-battery-empty:before{content:"ï„’"}.ion-battery-full:before{content:"ï„“"}.ion-battery-half:before{content:"ï„”"}.ion-battery-low:before{content:"ï„•"}.ion-beaker:before{content:""}.ion-beer:before{content:""}.ion-bluetooth:before{content:"ï„–"}.ion-bonfire:before{content:""}.ion-bookmark:before{content:""}.ion-bowtie:before{content:"ï€"}.ion-briefcase:before{content:""}.ion-bug:before{content:""}.ion-calculator:before{content:"ï‰"}.ion-calendar:before{content:"ï„—"}.ion-camera:before{content:""}.ion-card:before{content:"ï„™"}.ion-cash:before{content:""}.ion-chatbox:before{content:"ï„›"}.ion-chatbox-working:before{content:""}.ion-chatboxes:before{content:""}.ion-chatbubble:before{content:""}.ion-chatbubble-working:before{content:"ï„"}.ion-chatbubbles:before{content:""}.ion-checkmark:before{content:"ï„¢"}.ion-checkmark-circled:before{content:"ï„ "}.ion-checkmark-round:before{content:"ï„¡"}.ion-chevron-down:before{content:"ï„£"}.ion-chevron-left:before{content:""}.ion-chevron-right:before{content:"ï„¥"}.ion-chevron-up:before{content:""}.ion-clipboard:before{content:"ï„§"}.ion-clock:before{content:""}.ion-close:before{content:""}.ion-close-circled:before{content:""}.ion-close-round:before{content:"ï„©"}.ion-closed-captioning:before{content:""}.ion-cloud:before{content:"ï„«"}.ion-code:before{content:""}.ion-code-download:before{content:""}.ion-code-working:before{content:""}.ion-coffee:before{content:""}.ion-compass:before{content:""}.ion-compose:before{content:""}.ion-connection-bars:before{content:""}.ion-contrast:before{content:""}.ion-crop:before{content:"ï"}.ion-cube:before{content:""}.ion-disc:before{content:"ï„"}.ion-document:before{content:""}.ion-document-text:before{content:"ï„®"}.ion-drag:before{content:"ï„°"}.ion-earth:before{content:""}.ion-easel:before{content:"ï‚"}.ion-edit:before{content:""}.ion-egg:before{content:""}.ion-eject:before{content:""}.ion-email:before{content:""}.ion-email-unread:before{content:"ïƒ"}.ion-erlenmeyer-flask:before{content:"ï…"}.ion-erlenmeyer-flask-bubbles:before{content:"ï„"}.ion-eye:before{content:""}.ion-eye-disabled:before{content:""}.ion-female:before{content:""}.ion-filing:before{content:"ï„´"}.ion-film-marker:before{content:""}.ion-fireball:before{content:""}.ion-flag:before{content:""}.ion-flame:before{content:""}.ion-flash:before{content:"ï„·"}.ion-flash-off:before{content:"ï„¶"}.ion-folder:before{content:""}.ion-fork:before{content:""}.ion-fork-repo:before{content:"ï‹€"}.ion-forward:before{content:""}.ion-funnel:before{content:""}.ion-gear-a:before{content:""}.ion-gear-b:before{content:""}.ion-grid:before{content:"ï„¿"}.ion-hammer:before{content:""}.ion-happy:before{content:""}.ion-happy-outline:before{content:"ï†"}.ion-headphone:before{content:"ï…€"}.ion-heart:before{content:"ï…"}.ion-heart-broken:before{content:"ïŒ"}.ion-help:before{content:"ï…ƒ"}.ion-help-buoy:before{content:""}.ion-help-circled:before{content:"ï…‚"}.ion-home:before{content:"ï…„"}.ion-icecream:before{content:""}.ion-image:before{content:"ï…‡"}.ion-images:before{content:"ï…ˆ"}.ion-information:before{content:"ï…Š"}.ion-information-circled:before{content:"ï…‰"}.ion-ionic:before{content:"ï…‹"}.ion-ios-alarm:before{content:"ïˆ"}.ion-ios-alarm-outline:before{content:"ï‡"}.ion-ios-albums:before{content:"ïŠ"}.ion-ios-albums-outline:before{content:"ï‰"}.ion-ios-americanfootball:before{content:"ïŒ"}.ion-ios-americanfootball-outline:before{content:"ï‹"}.ion-ios-analytics:before{content:"ïŽ"}.ion-ios-analytics-outline:before{content:"ï"}.ion-ios-arrow-back:before{content:"ï"}.ion-ios-arrow-down:before{content:"ï"}.ion-ios-arrow-forward:before{content:"ï‘"}.ion-ios-arrow-left:before{content:"ï’"}.ion-ios-arrow-right:before{content:"ï“"}.ion-ios-arrow-thin-down:before{content:"ï”"}.ion-ios-arrow-thin-left:before{content:"ï•"}.ion-ios-arrow-thin-right:before{content:"ï–"}.ion-ios-arrow-thin-up:before{content:"ï—"}.ion-ios-arrow-up:before{content:"ï˜"}.ion-ios-at:before{content:"ïš"}.ion-ios-at-outline:before{content:"ï™"}.ion-ios-barcode:before{content:"ïœ"}.ion-ios-barcode-outline:before{content:"ï›"}.ion-ios-baseball:before{content:"ïž"}.ion-ios-baseball-outline:before{content:"ï"}.ion-ios-basketball:before{content:"ï "}.ion-ios-basketball-outline:before{content:"ïŸ"}.ion-ios-bell:before{content:"ï¢"}.ion-ios-bell-outline:before{content:"ï¡"}.ion-ios-body:before{content:"ï¤"}.ion-ios-body-outline:before{content:"ï£"}.ion-ios-bolt:before{content:"ï¦"}.ion-ios-bolt-outline:before{content:"ï¥"}.ion-ios-book:before{content:"ï¨"}.ion-ios-book-outline:before{content:"ï§"}.ion-ios-bookmarks:before{content:"ïª"}.ion-ios-bookmarks-outline:before{content:"ï©"}.ion-ios-box:before{content:"ï¬"}.ion-ios-box-outline:before{content:"ï«"}.ion-ios-briefcase:before{content:"ï®"}.ion-ios-briefcase-outline:before{content:"ï"}.ion-ios-browsers:before{content:"ï°"}.ion-ios-browsers-outline:before{content:"ï¯"}.ion-ios-calculator:before{content:"ï²"}.ion-ios-calculator-outline:before{content:"ï±"}.ion-ios-calendar:before{content:"ï´"}.ion-ios-calendar-outline:before{content:"ï³"}.ion-ios-camera:before{content:"ï¶"}.ion-ios-camera-outline:before{content:"ïµ"}.ion-ios-cart:before{content:"ï¸"}.ion-ios-cart-outline:before{content:"ï·"}.ion-ios-chatboxes:before{content:"ïº"}.ion-ios-chatboxes-outline:before{content:"ï¹"}.ion-ios-chatbubble:before{content:"ï¼"}.ion-ios-chatbubble-outline:before{content:"ï»"}.ion-ios-checkmark:before{content:"ï¿"}.ion-ios-checkmark-empty:before{content:"ï½"}.ion-ios-checkmark-outline:before{content:"ï¾"}.ion-ios-circle-filled:before{content:"ï€"}.ion-ios-circle-outline:before{content:"ï"}.ion-ios-clock:before{content:"ïƒ"}.ion-ios-clock-outline:before{content:"ï‚"}.ion-ios-close:before{content:"ï†"}.ion-ios-close-empty:before{content:"ï„"}.ion-ios-close-outline:before{content:"ï…"}.ion-ios-cloud:before{content:"ïŒ"}.ion-ios-cloud-download:before{content:"ïˆ"}.ion-ios-cloud-download-outline:before{content:"ï‡"}.ion-ios-cloud-outline:before{content:"ï‰"}.ion-ios-cloud-upload:before{content:"ï‹"}.ion-ios-cloud-upload-outline:before{content:"ïŠ"}.ion-ios-cloudy:before{content:"ï"}.ion-ios-cloudy-night:before{content:"ïŽ"}.ion-ios-cloudy-night-outline:before{content:"ï"}.ion-ios-cloudy-outline:before{content:"ï"}.ion-ios-cog:before{content:"ï’"}.ion-ios-cog-outline:before{content:"ï‘"}.ion-ios-color-filter:before{content:"ï”"}.ion-ios-color-filter-outline:before{content:"ï“"}.ion-ios-color-wand:before{content:"ï–"}.ion-ios-color-wand-outline:before{content:"ï•"}.ion-ios-compose:before{content:"ï˜"}.ion-ios-compose-outline:before{content:"ï—"}.ion-ios-contact:before{content:"ïš"}.ion-ios-contact-outline:before{content:"ï™"}.ion-ios-copy:before{content:"ïœ"}.ion-ios-copy-outline:before{content:"ï›"}.ion-ios-crop:before{content:"ïž"}.ion-ios-crop-strong:before{content:"ï"}.ion-ios-download:before{content:"ï "}.ion-ios-download-outline:before{content:"ïŸ"}.ion-ios-drag:before{content:"ï¡"}.ion-ios-email:before{content:"ï£"}.ion-ios-email-outline:before{content:"ï¢"}.ion-ios-eye:before{content:"ï¥"}.ion-ios-eye-outline:before{content:"ï¤"}.ion-ios-fastforward:before{content:"ï§"}.ion-ios-fastforward-outline:before{content:"ï¦"}.ion-ios-filing:before{content:"ï©"}.ion-ios-filing-outline:before{content:"ï¨"}.ion-ios-film:before{content:"ï«"}.ion-ios-film-outline:before{content:"ïª"}.ion-ios-flag:before{content:"ï"}.ion-ios-flag-outline:before{content:"ï¬"}.ion-ios-flame:before{content:"ï¯"}.ion-ios-flame-outline:before{content:"ï®"}.ion-ios-flask:before{content:"ï±"}.ion-ios-flask-outline:before{content:"ï°"}.ion-ios-flower:before{content:"ï³"}.ion-ios-flower-outline:before{content:"ï²"}.ion-ios-folder:before{content:"ïµ"}.ion-ios-folder-outline:before{content:"ï´"}.ion-ios-football:before{content:"ï·"}.ion-ios-football-outline:before{content:"ï¶"}.ion-ios-game-controller-a:before{content:"ï¹"}.ion-ios-game-controller-a-outline:before{content:"ï¸"}.ion-ios-game-controller-b:before{content:"ï»"}.ion-ios-game-controller-b-outline:before{content:"ïº"}.ion-ios-gear:before{content:"ï½"}.ion-ios-gear-outline:before{content:"ï¼"}.ion-ios-glasses:before{content:"ï¿"}.ion-ios-glasses-outline:before{content:"ï¾"}.ion-ios-grid-view:before{content:"ï‘"}.ion-ios-grid-view-outline:before{content:"ï‘€"}.ion-ios-heart:before{content:""}.ion-ios-heart-outline:before{content:"ï‘‚"}.ion-ios-help:before{content:""}.ion-ios-help-empty:before{content:"ï‘„"}#menu .footer .icon-help:before,.icon-help:before,.ion-ios-help-outline:before{content:"ï‘…"}.ion-ios-home:before{content:""}.ion-ios-home-outline:before{content:""}.ion-ios-infinite:before{content:""}.ion-ios-infinite-outline:before{content:""}.ion-ios-information:before{content:"ï‘"}.ion-ios-information-empty:before{content:"ï‘‹"}.ion-ios-information-outline:before{content:""}.ion-ios-ionic-outline:before{content:""}.ion-ios-keypad:before{content:"ï‘"}.ion-ios-keypad-outline:before{content:"ï‘"}.ion-ios-lightbulb:before{content:"ï‘’"}.ion-ios-lightbulb-outline:before{content:"ï‘‘"}.ion-ios-list:before{content:"ï‘”"}.ion-ios-list-outline:before{content:"ï‘“"}.ion-ios-location:before{content:"ï‘–"}.ion-ios-location-outline:before{content:"ï‘•"}.ion-ios-locked:before{content:""}.ion-ios-locked-outline:before{content:"ï‘—"}.ion-ios-loop:before{content:""}.ion-ios-loop-strong:before{content:"ï‘™"}.ion-ios-medical:before{content:""}.ion-ios-medical-outline:before{content:"ï‘›"}.ion-ios-medkit:before{content:""}.ion-ios-medkit-outline:before{content:"ï‘"}.ion-ios-mic:before{content:"ï‘¡"}.ion-ios-mic-off:before{content:""}.ion-ios-mic-outline:before{content:"ï‘ "}.ion-ios-minus:before{content:""}.ion-ios-minus-empty:before{content:"ï‘¢"}.ion-ios-minus-outline:before{content:"ï‘£"}.ion-ios-monitor:before{content:""}.ion-ios-monitor-outline:before{content:"ï‘¥"}.ion-ios-moon:before{content:""}.ion-ios-moon-outline:before{content:"ï‘§"}.ion-ios-more:before{content:""}.ion-ios-more-outline:before{content:"ï‘©"}.ion-ios-musical-note:before{content:"ï‘«"}.ion-ios-musical-notes:before{content:""}.ion-ios-navigate:before{content:"ï‘®"}.ion-ios-navigate-outline:before{content:"ï‘"}.ion-ios-nutrition:before{content:"ï‘°"}.ion-ios-nutrition-outline:before{content:""}.ion-ios-paper:before{content:""}.ion-ios-paper-outline:before{content:""}.ion-ios-paperplane:before{content:"ï‘´"}.ion-ios-paperplane-outline:before{content:""}.ion-ios-partlysunny:before{content:"ï‘¶"}.ion-ios-partlysunny-outline:before{content:""}.ion-ios-pause:before{content:""}.ion-ios-pause-outline:before{content:"ï‘·"}.ion-ios-paw:before{content:""}.ion-ios-paw-outline:before{content:""}.ion-ios-people:before{content:""}.ion-ios-people-outline:before{content:"ï‘»"}.ion-ios-person:before{content:""}.ion-ios-person-outline:before{content:""}.ion-ios-personadd:before{content:"ï’€"}.ion-ios-personadd-outline:before{content:"ï‘¿"}.ion-ios-photos:before{content:"ï’‚"}.ion-ios-photos-outline:before{content:"ï’"}.ion-ios-pie:before{content:"ï’„"}.ion-ios-pie-outline:before{content:"ï’ƒ"}.ion-ios-pint:before{content:"ï’†"}.ion-ios-pint-outline:before{content:"ï’…"}.ion-ios-play:before{content:"ï’ˆ"}.ion-ios-play-outline:before{content:"ï’‡"}.ion-ios-plus:before{content:"ï’‹"}.ion-ios-plus-empty:before{content:"ï’‰"}.ion-ios-plus-outline:before{content:"ï’Š"}.ion-ios-pricetag:before{content:"ï’"}.ion-ios-pricetag-outline:before{content:"ï’Œ"}.ion-ios-pricetags:before{content:"ï’"}.ion-ios-pricetags-outline:before{content:"ï’Ž"}.ion-ios-printer:before{content:"ï’‘"}.ion-ios-printer-outline:before{content:"ï’"}.ion-ios-pulse:before{content:"ï’“"}.ion-ios-pulse-strong:before{content:"ï’’"}.ion-ios-rainy:before{content:"ï’•"}.ion-ios-rainy-outline:before{content:"ï’”"}.ion-ios-recording:before{content:"ï’—"}.ion-ios-recording-outline:before{content:"ï’–"}.ion-ios-redo:before{content:"ï’™"}.ion-ios-redo-outline:before{content:"ï’˜"}.ion-ios-refresh:before{content:"ï’œ"}.ion-ios-refresh-empty:before{content:"ï’š"}.ion-ios-refresh-outline:before{content:"ï’›"}.ion-ios-reload:before{content:"ï’"}.ion-ios-reverse-camera:before{content:"ï’Ÿ"}.ion-ios-reverse-camera-outline:before{content:"ï’ž"}.ion-ios-rewind:before{content:"ï’¡"}.ion-ios-rewind-outline:before{content:"ï’ "}.ion-ios-rose:before{content:"ï’£"}.ion-ios-rose-outline:before{content:"ï’¢"}.ion-ios-search:before{content:"ï’¥"}.ion-ios-search-strong:before{content:"ï’¤"}.ion-ios-settings:before{content:"ï’§"}.ion-ios-settings-strong:before{content:"ï’¦"}.ion-ios-shuffle:before{content:"ï’©"}.ion-ios-shuffle-strong:before{content:"ï’¨"}.ion-ios-skipbackward:before{content:"ï’«"}.ion-ios-skipbackward-outline:before{content:"ï’ª"}.ion-ios-skipforward:before{content:"ï’"}.ion-ios-skipforward-outline:before{content:"ï’¬"}.ion-ios-snowy:before{content:"ï’®"}.ion-ios-speedometer:before{content:"ï’°"}.ion-ios-speedometer-outline:before{content:"ï’¯"}.ion-ios-star:before{content:"ï’³"}.ion-ios-star-half:before{content:"ï’±"}.ion-ios-star-outline:before{content:"ï’²"}.ion-ios-stopwatch:before{content:"ï’µ"}.ion-ios-stopwatch-outline:before{content:"ï’´"}.ion-ios-sunny:before{content:"ï’·"}.ion-ios-sunny-outline:before{content:"ï’¶"}.ion-ios-telephone:before{content:"ï’¹"}.ion-ios-telephone-outline:before{content:"ï’¸"}.ion-ios-tennisball:before{content:"ï’»"}.ion-ios-tennisball-outline:before{content:"ï’º"}.ion-ios-thunderstorm:before{content:"ï’½"}.ion-ios-thunderstorm-outline:before{content:"ï’¼"}.ion-ios-time:before{content:"ï’¿"}.ion-ios-time-outline:before{content:"ï’¾"}.ion-ios-timer:before{content:"ï“"}.ion-ios-timer-outline:before{content:"ï“€"}.ion-ios-toggle:before{content:""}.ion-ios-toggle-outline:before{content:"ï“‚"}.ion-ios-trash:before{content:"ï“…"}.ion-ios-trash-outline:before{content:"ï“„"}.ion-ios-undo:before{content:""}.ion-ios-undo-outline:before{content:""}.ion-ios-unlocked:before{content:""}.ion-ios-unlocked-outline:before{content:""}.ion-ios-upload:before{content:"ï“‹"}.ion-ios-upload-outline:before{content:""}.ion-ios-videocam:before{content:"ï“"}.ion-ios-videocam-outline:before{content:""}.ion-ios-volume-high:before{content:""}.ion-ios-volume-low:before{content:"ï“"}.ion-ios-wineglass:before{content:"ï“‘"}.ion-ios-wineglass-outline:before{content:"ï“"}.ion-ios-world:before{content:"ï““"}.ion-ios-world-outline:before{content:"ï“’"}.ion-ipad:before{content:""}.ion-iphone:before{content:""}.ion-ipod:before{content:""}.ion-jet:before{content:""}.ion-key:before{content:""}.ion-knife:before{content:""}.ion-laptop:before{content:""}.ion-leaf:before{content:""}.ion-levels:before{content:""}.ion-lightbulb:before{content:""}.ion-link:before{content:""}.ion-load-a:before{content:""}.ion-load-b:before{content:""}.ion-load-c:before{content:""}.ion-load-d:before{content:"ïŠ"}.ion-location:before{content:""}.ion-lock-combination:before{content:"ï“”"}.ion-locked:before{content:""}.ion-log-in:before{content:""}.ion-log-out:before{content:""}.ion-loop:before{content:"ïˆ"}.ion-magnet:before{content:"ïŠ "}.ion-male:before{content:""}.ion-man:before{content:""}.ion-map:before{content:""}.ion-medkit:before{content:""}.ion-merge:before{content:""}.ion-mic-a:before{content:""}.ion-mic-b:before{content:""}.ion-mic-c:before{content:""}.ion-minus:before{content:""}.ion-minus-circled:before{content:""}.ion-minus-round:before{content:""}.ion-model-s:before{content:"ï‹"}.ion-monitor:before{content:""}.ion-more:before{content:""}.ion-mouse:before{content:"ï€"}.ion-music-note:before{content:""}.ion-navicon:before{content:""}.ion-navicon-round:before{content:"ïˆ"}.ion-navigate:before{content:""}.ion-network:before{content:"ï"}.ion-no-smoking:before{content:"ï‹‚"}.ion-nuclear:before{content:""}.ion-outlet:before{content:"ï‚"}.ion-paintbrush:before{content:"ï“•"}.ion-paintbucket:before{content:"ï“–"}.ion-paper-airplane:before{content:""}.ion-paperclip:before{content:"ïˆ"}.ion-pause:before{content:"ïˆ"}.ion-person:before{content:""}.ion-person-add:before{content:""}.ion-person-stalker:before{content:""}.ion-pie-graph:before{content:""}.ion-pin:before{content:""}.ion-pinpoint:before{content:""}.ion-pizza:before{content:""}.ion-plane:before{content:""}.ion-planet:before{content:"ïƒ"}.ion-play:before{content:""}.ion-playstation:before{content:""}.ion-plus:before{content:""}.ion-plus-circled:before{content:""}.ion-plus-round:before{content:""}.ion-podium:before{content:"ï„"}.ion-pound:before{content:""}.ion-power:before{content:""}.ion-pricetag:before{content:""}.ion-pricetags:before{content:""}.ion-printer:before{content:""}.ion-pull-request:before{content:"ï…"}.ion-qr-scanner:before{content:"ï†"}.ion-quote:before{content:"ï‡"}.ion-radio-waves:before{content:""}.ion-record:before{content:""}.ion-refresh:before{content:""}.ion-reply:before{content:""}.ion-reply-all:before{content:"ïˆ"}.ion-ribbon-a:before{content:"ïˆ"}.ion-ribbon-b:before{content:"ï‰"}.ion-sad:before{content:"ïŠ"}.ion-sad-outline:before{content:"ï“—"}.ion-scissors:before{content:"ï‹"}.ion-search:before{content:""}.ion-settings:before{content:"ïŠ"}.ion-share:before{content:"ïˆ "}.ion-shuffle:before{content:""}.ion-skip-backward:before{content:""}.ion-skip-forward:before{content:""}.ion-social-android:before{content:""}.ion-social-android-outline:before{content:""}.ion-social-angular:before{content:"ï“™"}.ion-social-angular-outline:before{content:""}.ion-social-apple:before{content:""}.ion-social-apple-outline:before{content:""}.ion-social-bitcoin:before{content:""}.ion-social-bitcoin-outline:before{content:""}.ion-social-buffer:before{content:""}.ion-social-buffer-outline:before{content:""}.ion-social-chrome:before{content:"ï“›"}.ion-social-chrome-outline:before{content:""}.ion-social-codepen:before{content:"ï“"}.ion-social-codepen-outline:before{content:""}.ion-social-css3:before{content:""}.ion-social-css3-outline:before{content:""}.ion-social-designernews:before{content:""}.ion-social-designernews-outline:before{content:""}.ion-social-dribbble:before{content:"ïˆ"}.ion-social-dribbble-outline:before{content:""}.ion-social-dropbox:before{content:""}.ion-social-dropbox-outline:before{content:""}.ion-social-euro:before{content:"ï“¡"}.ion-social-euro-outline:before{content:"ï“ "}.ion-social-facebook:before{content:""}.ion-social-facebook-outline:before{content:""}.ion-social-foursquare:before{content:"ï"}.ion-social-foursquare-outline:before{content:"ïŒ"}.ion-social-freebsd-devil:before{content:"ï‹„"}.ion-social-github:before{content:""}.ion-social-github-outline:before{content:""}.ion-social-google:before{content:"ï"}.ion-social-google-outline:before{content:"ïŽ"}.ion-social-googleplus:before{content:""}.ion-social-googleplus-outline:before{content:""}.ion-social-hackernews:before{content:""}.ion-social-hackernews-outline:before{content:""}.ion-social-html5:before{content:"ï“£"}.ion-social-html5-outline:before{content:"ï“¢"}.ion-social-instagram:before{content:"ï‘"}.ion-social-instagram-outline:before{content:"ï"}.ion-social-javascript:before{content:"ï“¥"}.ion-social-javascript-outline:before{content:""}.ion-social-linkedin:before{content:""}.ion-social-linkedin-outline:before{content:""}.ion-social-markdown:before{content:""}.ion-social-nodejs:before{content:"ï“§"}.ion-social-octocat:before{content:""}.ion-social-pinterest:before{content:""}.ion-social-pinterest-outline:before{content:""}.ion-social-python:before{content:"ï“©"}.ion-social-reddit:before{content:""}.ion-social-reddit-outline:before{content:""}.ion-social-rss:before{content:""}.ion-social-rss-outline:before{content:""}.ion-social-sass:before{content:""}.ion-social-skype:before{content:""}.ion-social-skype-outline:before{content:""}.ion-social-snapchat:before{content:""}.ion-social-snapchat-outline:before{content:"ï“«"}.ion-social-tumblr:before{content:"ï‰"}.ion-social-tumblr-outline:before{content:""}.ion-social-tux:before{content:"ï‹…"}.ion-social-twitch:before{content:"ï“®"}.ion-social-twitch-outline:before{content:"ï“"}.ion-social-twitter:before{content:""}.ion-social-twitter-outline:before{content:""}.ion-social-usd:before{content:"ï“"}.ion-social-usd-outline:before{content:"ï’"}.ion-social-vimeo:before{content:""}.ion-social-vimeo-outline:before{content:""}.ion-social-whatsapp:before{content:"ï“°"}.ion-social-whatsapp-outline:before{content:""}.ion-social-windows:before{content:""}.ion-social-windows-outline:before{content:""}.ion-social-wordpress:before{content:""}.ion-social-wordpress-outline:before{content:""}.ion-social-yahoo:before{content:""}.ion-social-yahoo-outline:before{content:""}.ion-social-yen:before{content:""}.ion-social-yen-outline:before{content:""}.ion-social-youtube:before{content:"ï‰"}.ion-social-youtube-outline:before{content:""}.ion-soup-can:before{content:"ï“´"}.ion-soup-can-outline:before{content:""}.ion-speakerphone:before{content:""}.ion-speedometer:before{content:""}.ion-spoon:before{content:""}.ion-star:before{content:""}.ion-stats-bars:before{content:""}.ion-steam:before{content:""}.ion-stop:before{content:"ï‰"}.ion-thermometer:before{content:""}.ion-thumbsdown:before{content:"ï‰"}.ion-thumbsup:before{content:""}.ion-toggle:before{content:"ï•"}.ion-toggle-filled:before{content:"ï”"}.ion-transgender:before{content:""}.ion-trash-a:before{content:""}.ion-trash-b:before{content:""}.ion-trophy:before{content:"ï–"}.ion-tshirt:before{content:"ï“·"}.ion-tshirt-outline:before{content:"ï“¶"}.ion-umbrella:before{content:""}.ion-university:before{content:"ï—"}.ion-unlocked:before{content:""}.ion-upload:before{content:""}.ion-usb:before{content:""}.ion-videocamera:before{content:""}.ion-volume-high:before{content:""}.ion-volume-low:before{content:""}.ion-volume-medium:before{content:""}.ion-volume-mute:before{content:""}.ion-wand:before{content:"ï˜"}.ion-waterdrop:before{content:""}.ion-wifi:before{content:""}.ion-wineglass:before{content:""}.ion-woman:before{content:"ï‰"}.ion-wrench:before{content:""}.ion-xbox:before{content:""}a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;vertical-align:baseline;font:inherit;font-size:100%}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:'';content:none}audio:not([controls]){display:none;height:0}[hidden],template{display:none}script{display:none!important}html{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0;line-height:1}:focus,a,a:active,a:focus,a:hover,button,button:focus{outline:0}a{-webkit-user-drag:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent}a[href]:hover{cursor:pointer}b,strong{font-weight:700}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}code,kbd,pre,samp{font-size:1em;font-family:monospace,serif}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{position:relative;vertical-align:baseline;font-size:75%;line-height:0}sup{top:-.5em}sub{bottom:-.25em}fieldset{margin:0 2px;padding:.35em .625em .75em;border:1px solid silver}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-size:100%;font-family:inherit;outline-offset:0;outline-style:none;outline-width:0;-webkit-font-smoothing:inherit;background-image:none}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}img{-webkit-user-drag:none}table{border-spacing:0;border-collapse:collapse}*,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{overflow:hidden;-ms-touch-action:pan-y;touch-action:pan-y}.ionic-body,body{-webkit-touch-callout:none;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;top:0;right:0;bottom:0;left:0;overflow:hidden;margin:0;padding:0;color:#000;word-wrap:break-word;font-size:14px;font-family:-apple-system;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;line-height:20px;text-rendering:optimizeLegibility;-webkit-backface-visibility:hidden;-webkit-user-drag:none;-ms-content-zooming:none}body.grade-b,body.grade-c{text-rendering:auto}.content{position:relative}.scroll-content{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;margin-top:-1px;padding-top:1px;margin-bottom:-1px;width:auto;height:auto}.menu .scroll-content.scroll-content-false{z-index:11}.scroll-view{position:relative;display:block;overflow:hidden;margin-top:-1px}.scroll-view.overflow-scroll{position:relative}.scroll-view.scroll-x{overflow-x:scroll;overflow-y:hidden}.scroll-view.scroll-y{overflow-x:hidden;overflow-y:scroll}.scroll-view.scroll-xy{overflow-x:scroll;overflow-y:scroll}.scroll{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;-webkit-transform-origin:left top;transform-origin:left top}@-ms-viewport{width:device-width}.scroll-bar{position:absolute;z-index:9999}.ng-animate .scroll-bar{visibility:hidden}.scroll-bar-h{right:2px;bottom:3px;left:2px;height:3px}.scroll-bar-h .scroll-bar-indicator{height:100%}.scroll-bar-v{top:2px;right:3px;bottom:2px;width:3px}.scroll-bar-v .scroll-bar-indicator{width:100%}.scroll-bar-indicator{position:absolute;border-radius:4px;background:rgba(0,0,0,.3);opacity:1;-webkit-transition:opacity .3s linear;transition:opacity .3s linear}.scroll-bar-indicator.scroll-bar-fade-out{opacity:0}.platform-android .scroll-bar-indicator{border-radius:0}.grade-b .scroll-bar-indicator,.grade-c .scroll-bar-indicator{background:#aaa}.grade-b .scroll-bar-indicator.scroll-bar-fade-out,.grade-c .scroll-bar-indicator.scroll-bar-fade-out{-webkit-transition:none;transition:none}ion-infinite-scroll{height:60px;width:100%;display:block;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}#menu .footer ion-infinite-scroll .icon-help,ion-infinite-scroll #menu .footer .icon-help,ion-infinite-scroll .icon,ion-infinite-scroll .icon-alert,ion-infinite-scroll .icon-help{color:#666;font-size:30px;color:#666}#menu .footer ion-infinite-scroll:not(.active) .icon-help:before,ion-infinite-scroll:not(.active) #menu .footer .icon-help:before,ion-infinite-scroll:not(.active) .icon-alert:before,ion-infinite-scroll:not(.active) .icon-help:before,ion-infinite-scroll:not(.active) .icon:before,ion-infinite-scroll:not(.active) .spinner{display:none}.overflow-scroll{overflow-x:hidden;overflow-y:scroll;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;top:0;right:0;bottom:0;left:0;position:absolute}.overflow-scroll.pane{overflow-x:hidden;overflow-y:scroll}.overflow-scroll .scroll{position:static;height:100%;-webkit-transform:translate3d(0,0,0)}.has-header{top:44px}.no-header{top:0}.has-subheader{top:88px}.has-tabs-top{top:93px}.has-header.has-subheader.has-tabs-top{top:137px}.has-footer{bottom:44px}.has-subfooter{bottom:88px}.bar-footer.has-tabs,.has-tabs{bottom:49px}.bar-footer.has-tabs.pane,.has-tabs.pane{bottom:49px;height:auto}.bar-subfooter.has-tabs{bottom:93px}.has-footer.has-tabs{bottom:93px}.pane{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition-duration:0;transition-duration:0;z-index:1}.view{z-index:1}.pane,.view{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;background-color:#fff;overflow:hidden}.view-container{position:absolute;display:block;width:100%;height:100%}p{margin:0 0 10px}small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.item.large-button-bar,.text-center{text-align:center}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{color:#000;font-weight:500;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;line-height:1.2}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:400;line-height:1}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1:first-child,.h2:first-child,.h3:first-child,h1:first-child,h2:first-child,h3:first-child{margin-top:0}.h1+.h1,.h1+.h2,.h1+.h3,.h1+h1,.h1+h2,.h1+h3,.h2+.h1,.h2+.h2,.h2+.h3,.h2+h1,.h2+h2,.h2+h3,.h3+.h1,.h3+.h2,.h3+.h3,.h3+h1,.h3+h2,.h3+h3,h1+.h1,h1+.h2,h1+.h3,h1+h1,h1+h2,h1+h3,h2+.h1,h2+.h2,h2+.h3,h2+h1,h2+h2,h2+h3,h3+.h1,h3+.h2,h3+.h3,h3+h1,h3+h2,h3+h3{margin-top:10px}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}.h1 small,h1 small{font-size:24px}.h2 small,h2 small{font-size:18px}.h3 small,.h4 small,h3 small,h4 small{font-size:14px}dl{margin-bottom:20px}dd,dt{line-height:1.42857}dt{font-weight:700}blockquote{margin:0 0 20px;padding:10px 20px;border-left:5px solid gray}blockquote p{font-weight:300;font-size:17.5px;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.42857}blockquote small:before{content:'\2014 \00A0'}blockquote:after,blockquote:before,q:after,q:before{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:1.42857}a{color:#387ef5}a.subdued{padding-right:10px;color:#888;text-decoration:none}a.subdued:hover{text-decoration:none}a.subdued:last-child{padding-right:0}.action-sheet-backdrop{-webkit-transition:background-color 150ms ease-in-out;transition:background-color 150ms ease-in-out;position:fixed;top:0;left:0;z-index:11;width:100%;height:100%;background-color:transparent}.action-sheet-backdrop.active{background-color:rgba(0,0,0,.4)}.action-sheet-wrapper{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);-webkit-transition:all cubic-bezier(.36,.66,.04,1) .5s;transition:all cubic-bezier(.36,.66,.04,1) .5s;position:absolute;bottom:0;left:0;right:0;width:100%;max-width:500px;margin:auto}.action-sheet-up{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.action-sheet{margin-left:8px;margin-right:8px;width:auto;z-index:11;overflow:hidden}.action-sheet .button{display:block;padding:1px;width:100%;border-radius:0;border-color:#d1d3d6;background-color:transparent;color:#007aff;font-size:21px}.action-sheet .button:hover{color:#007aff}.action-sheet .button.destructive{color:#ff3b30}.action-sheet .button.destructive:hover{color:#ff3b30}.action-sheet .button.activated,.action-sheet .button.active{box-shadow:none;border-color:#d1d3d6;color:#007aff;background:#e4e5e7}#menu .footer .action-sheet-has-icons .icon-help,.action-sheet-has-icons #menu .footer .icon-help,.action-sheet-has-icons .icon,.action-sheet-has-icons .icon-alert,.action-sheet-has-icons .icon-help{position:absolute;left:16px}.action-sheet-title{padding:16px;color:#8f8f8f;text-align:center;font-size:13px}.action-sheet-group{margin-bottom:8px;border-radius:4px;background-color:#fff;overflow:hidden}.action-sheet-group .button{border-width:1px 0 0 0}.action-sheet-group .button:first-child:last-child{border-width:0}.action-sheet-options{background:#f1f2f3}.action-sheet-cancel .button{font-weight:500}.action-sheet-open{pointer-events:none}.action-sheet-open.modal-open .modal{pointer-events:none}.action-sheet-open .action-sheet-backdrop{pointer-events:auto}.platform-android .action-sheet-backdrop.active{background-color:rgba(0,0,0,.2)}.platform-android .action-sheet{margin:0}.platform-android .action-sheet .action-sheet-title,.platform-android .action-sheet .button{text-align:left;border-color:transparent;font-size:16px;color:inherit}.platform-android .action-sheet .action-sheet-title{font-size:14px;padding:16px;color:#666}.platform-android .action-sheet .button.activated,.platform-android .action-sheet .button.active{background:#e8e8e8}.platform-android .action-sheet-group{margin:0;border-radius:0;background-color:#fafafa}.platform-android .action-sheet-cancel{display:none}.platform-android .action-sheet-has-icons .button{padding-left:56px}.backdrop{position:fixed;top:0;left:0;z-index:11;width:100%;height:100%;background-color:rgba(0,0,0,.4);visibility:hidden;opacity:0;-webkit-transition:.1s opacity linear;transition:.1s opacity linear}.backdrop.visible{visibility:visible}.backdrop.active{opacity:1}.bar{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:absolute;right:0;left:0;z-index:9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:5px;width:100%;height:44px;border-width:0;border-style:solid;border-top:1px solid transparent;border-bottom:1px solid #ddd;background-color:#fff;background-size:0}@media (min--moz-device-pixel-ratio:1.5),(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5),(min-resolution:144dpi),(min-resolution:1.5dppx){.bar{border:none;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);background-position:bottom;background-size:100% 1px;background-repeat:no-repeat}}.bar.bar-clear{border:none;background:0 0;color:#fff}.bar.bar-clear .button{color:#fff}.bar.bar-clear .title{color:#fff}.bar.item-input-inset .item-input-wrapper{margin-top:-1px}.bar.item-input-inset .item-input-wrapper input{padding-left:8px;width:94%;height:28px;background:0 0}.bar.bar-light{border-color:#ddd;background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);color:#444}.bar.bar-light .title{color:#444}.bar.bar-light.bar-footer{background-image:linear-gradient(180deg,#ddd,#ddd 50%,transparent 50%)}.bar.bar-stable{border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444}.bar.bar-stable .title{color:#444}.bar.bar-stable.bar-footer{background-image:linear-gradient(180deg,#b2b2b2,#b2b2b2 50%,transparent 50%)}.bar.bar-positive{border-color:#0c60ee;background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);color:#fff}.bar.bar-positive .title{color:#fff}.bar.bar-positive.bar-footer{background-image:linear-gradient(180deg,#0c60ee,#0c60ee 50%,transparent 50%)}.bar.bar-calm{border-color:#0a9dc7;background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);color:#fff}.bar.bar-calm .title{color:#fff}.bar.bar-calm.bar-footer{background-image:linear-gradient(180deg,#0a9dc7,#0a9dc7 50%,transparent 50%)}.bar.bar-assertive{border-color:#e42112;background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);color:#fff}.bar.bar-assertive .title{color:#fff}.bar.bar-assertive.bar-footer{background-image:linear-gradient(180deg,#e42112,#e42112 50%,transparent 50%)}.bar.bar-balanced{border-color:#28a54c;background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);color:#fff}.bar.bar-balanced .title{color:#fff}.bar.bar-balanced.bar-footer{background-image:linear-gradient(180deg,#28a54c,#28a54c 50%,transparent 50%)}.bar.bar-energized{border-color:#e6b500;background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);color:#fff}.bar.bar-energized .title{color:#fff}.bar.bar-energized.bar-footer{background-image:linear-gradient(180deg,#e6b500,#e6b500 50%,transparent 50%)}.bar.bar-royal{border-color:#6b46e5;background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);color:#fff}.bar.bar-royal .title{color:#fff}.bar.bar-royal.bar-footer{background-image:linear-gradient(180deg,#6b46e5,#6b46e5 50%,transparent 50%)}.bar.bar-dark{border-color:#111;background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);color:#fff}.bar.bar-dark .title{color:#fff}.bar.bar-dark.bar-footer{background-image:linear-gradient(180deg,#111,#111 50%,transparent 50%)}.bar .title{display:block;position:absolute;top:0;right:0;left:0;z-index:0;overflow:hidden;margin:0 10px;min-width:30px;height:43px;text-align:center;text-overflow:ellipsis;white-space:nowrap;font-size:17px;font-weight:500;line-height:44px}.bar .title.title-left{text-align:left}.bar .title.title-right{text-align:right}.bar .title a{color:inherit}.bar .button,.bar button{z-index:1;padding:0 8px;min-width:initial;min-height:31px;font-weight:400;font-size:13px;line-height:32px}#menu .footer .bar .button .icon-help:before,#menu .footer .bar .button.icon-help:before,#menu .footer .bar button .icon-help:before,#menu .footer .bar button.icon-help:before,.bar #menu .footer .button.icon-help:before,.bar #menu .footer button.icon-help:before,.bar .button #menu .footer .icon-help:before,.bar .button .icon-alert:before,.bar .button .icon-help:before,.bar .button .icon:before,.bar .button.button-icon:before,.bar .button.icon-alert:before,.bar .button.icon-help:before,.bar .button.icon-left:before,.bar .button.icon-right:before,.bar .button.icon:before,.bar button #menu .footer .icon-help:before,.bar button .icon-alert:before,.bar button .icon-help:before,.bar button .icon:before,.bar button.button-icon:before,.bar button.icon-alert:before,.bar button.icon-help:before,.bar button.icon-left:before,.bar button.icon-right:before,.bar button.icon:before{padding-right:2px;padding-left:2px;font-size:20px;line-height:32px}.bar .button.button-icon,.bar button.button-icon{font-size:17px}#menu .footer .bar .button.button-icon .icon-help:before,#menu .footer .bar button.button-icon .icon-help:before,.bar .button.button-icon #menu .footer .icon-help:before,.bar .button.button-icon .icon-alert:before,.bar .button.button-icon .icon-help:before,.bar .button.button-icon .icon:before,.bar .button.button-icon.icon-left:before,.bar .button.button-icon.icon-right:before,.bar .button.button-icon:before,.bar button.button-icon #menu .footer .icon-help:before,.bar button.button-icon .icon-alert:before,.bar button.button-icon .icon-help:before,.bar button.button-icon .icon:before,.bar button.button-icon.icon-left:before,.bar button.button-icon.icon-right:before,.bar button.button-icon:before{vertical-align:top;font-size:32px;line-height:32px}.bar .button.button-clear,.bar .button.button-text,.bar button.button-clear,.bar button.button-text{padding-right:2px;padding-left:2px;font-weight:300;font-size:17px}#menu .footer .bar .button.button-clear .icon-help:before,#menu .footer .bar .button.button-clear.icon-help:before,#menu .footer .bar .button.button-text .icon-help:before,#menu .footer .bar .button.button-text.icon-help:before,#menu .footer .bar button.button-clear .icon-help:before,#menu .footer .bar button.button-clear.icon-help:before,#menu .footer .bar button.button-text .icon-help:before,#menu .footer .bar button.button-text.icon-help:before,.bar #menu .footer .button.button-clear.icon-help:before,.bar #menu .footer .button.button-text.icon-help:before,.bar #menu .footer button.button-clear.icon-help:before,.bar #menu .footer button.button-text.icon-help:before,.bar .button.button-clear #menu .footer .icon-help:before,.bar .button.button-clear .icon-alert:before,.bar .button.button-clear .icon-help:before,.bar .button.button-clear .icon:before,.bar .button.button-clear.icon-alert:before,.bar .button.button-clear.icon-help:before,.bar .button.button-clear.icon-left:before,.bar .button.button-clear.icon-right:before,.bar .button.button-clear.icon:before,.bar .button.button-text #menu .footer .icon-help:before,.bar .button.button-text .icon-alert:before,.bar .button.button-text .icon-help:before,.bar .button.button-text .icon:before,.bar .button.button-text.icon-alert:before,.bar .button.button-text.icon-help:before,.bar .button.icon-left.button-text:before,.bar .button.icon-right.button-text:before,.bar .button.icon.button-text:before,.bar button.button-clear #menu .footer .icon-help:before,.bar button.button-clear .icon-alert:before,.bar button.button-clear .icon-help:before,.bar button.button-clear .icon:before,.bar button.button-clear.icon-alert:before,.bar button.button-clear.icon-help:before,.bar button.button-clear.icon-left:before,.bar button.button-clear.icon-right:before,.bar button.button-clear.icon:before,.bar button.button-text #menu .footer .icon-help:before,.bar button.button-text .icon-alert:before,.bar button.button-text .icon-help:before,.bar button.button-text .icon:before,.bar button.button-text.icon-alert:before,.bar button.button-text.icon-help:before,.bar button.icon-left.button-text:before,.bar button.icon-right.button-text:before,.bar button.icon.button-text:before{font-size:32px;line-height:32px}.bar .button.back-button,.bar button.back-button{display:block;margin-right:5px;padding:0;white-space:nowrap;font-weight:400}.bar .button.back-button.activated,.bar .button.back-button.active,.bar button.back-button.activated,.bar button.back-button.active{opacity:.2}.bar .button-bar>.button,.bar .buttons>.button{min-height:31px;line-height:32px}.bar .button+.button-bar,.bar .button-bar+.button{margin-left:5px}.bar .buttons,.bar .buttons.primary-buttons,.bar .buttons.secondary-buttons{display:inherit}.bar .buttons span{display:inline-block}.bar .buttons-left span{margin-right:5px;display:inherit}.bar .buttons-right span{margin-left:5px;display:inherit}#menu .footer .popover-helptip .bar .buttons.icon-bottom-center.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-bottom-right.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-center.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-right.icon-help,#menu .footer .popover-helptip .bar>.button.icon-bottom-center.icon-help,#menu .footer .popover-helptip .bar>.button.icon-bottom-right.icon-help,#menu .footer .popover-helptip .bar>.button.icon-center.icon-help,#menu .footer .popover-helptip .bar>.button.icon-right.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-bottom-center.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-bottom-right.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-center.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-right.icon-help,.bar .buttons.pull-right,.bar .popover-helptip #menu .footer .buttons.icon-bottom-center.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-bottom-right.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-center.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-right.icon-help,.bar .popover-helptip .buttons.icon-bottom-center.icon-alert,.bar .popover-helptip .buttons.icon-bottom-center.icon-help,.bar .popover-helptip .buttons.icon-bottom-right.icon-alert,.bar .popover-helptip .buttons.icon-bottom-right.icon-help,.bar .popover-helptip .buttons.icon-center.icon-alert,.bar .popover-helptip .buttons.icon-center.icon-help,.bar .popover-helptip .buttons.icon-right.icon-alert,.bar .popover-helptip .buttons.icon-right.icon-help,.bar .popover-helptip .buttons.icon.icon-bottom-center,.bar .popover-helptip .buttons.icon.icon-bottom-right,.bar .popover-helptip .buttons.icon.icon-center,.bar .popover-helptip .buttons.icon.icon-right,.bar .title+.button:last-child,.bar .title+.buttons,.bar>.button+.button:last-child,.bar>.button.pull-right,.popover-helptip #menu .footer .bar .buttons.icon-bottom-center.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-bottom-right.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-center.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-right.icon-help,.popover-helptip #menu .footer .bar>.button.icon-bottom-center.icon-help,.popover-helptip #menu .footer .bar>.button.icon-bottom-right.icon-help,.popover-helptip #menu .footer .bar>.button.icon-center.icon-help,.popover-helptip #menu .footer .bar>.button.icon-right.icon-help,.popover-helptip .bar .buttons.icon-bottom-center.icon-alert,.popover-helptip .bar .buttons.icon-bottom-center.icon-help,.popover-helptip .bar .buttons.icon-bottom-right.icon-alert,.popover-helptip .bar .buttons.icon-bottom-right.icon-help,.popover-helptip .bar .buttons.icon-center.icon-alert,.popover-helptip .bar .buttons.icon-center.icon-help,.popover-helptip .bar .buttons.icon-right.icon-alert,.popover-helptip .bar .buttons.icon-right.icon-help,.popover-helptip .bar .buttons.icon.icon-bottom-center,.popover-helptip .bar .buttons.icon.icon-bottom-right,.popover-helptip .bar .buttons.icon.icon-center,.popover-helptip .bar .buttons.icon.icon-right,.popover-helptip .bar>.button.icon-bottom-center.icon-alert,.popover-helptip .bar>.button.icon-bottom-center.icon-help,.popover-helptip .bar>.button.icon-bottom-right.icon-alert,.popover-helptip .bar>.button.icon-bottom-right.icon-help,.popover-helptip .bar>.button.icon-center.icon-alert,.popover-helptip .bar>.button.icon-center.icon-help,.popover-helptip .bar>.button.icon-right.icon-alert,.popover-helptip .bar>.button.icon-right.icon-help,.popover-helptip .bar>.button.icon.icon-bottom-center,.popover-helptip .bar>.button.icon.icon-bottom-right,.popover-helptip .bar>.button.icon.icon-center,.popover-helptip .bar>.button.icon.icon-right{position:absolute;top:5px;right:5px;bottom:5px}.platform-android .nav-bar-has-subheader .bar{background-image:none}#menu .footer .platform-android .bar .back-button .icon-help:before,.platform-android .bar .back-button #menu .footer .icon-help:before,.platform-android .bar .back-button .icon-alert:before,.platform-android .bar .back-button .icon-help:before,.platform-android .bar .back-button .icon:before{font-size:24px}.platform-android .bar .title{font-size:19px;line-height:44px}.bar-light .button{border-color:#ddd;background-color:#fff;color:#444}.bar-light .button:hover{color:#444;text-decoration:none}.bar-light .button.activated,.bar-light .button.active{border-color:#ccc;background-color:#fafafa}.bar-light .button.button-clear,.bar-light .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#444;font-size:17px}.bar-light .button.button-icon{border-color:transparent;background:0 0}.bar-stable .button{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.bar-stable .button:hover{color:#444;text-decoration:none}.bar-stable .button.activated,.bar-stable .button.active{border-color:#a2a2a2;background-color:#e5e5e5}.bar-stable .button.button-clear,.bar-stable .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#444;font-size:17px}.bar-stable .button.button-icon{border-color:transparent;background:0 0}.bar-positive .button{border-color:#0c60ee;background-color:#387ef5;color:#fff}.bar-positive .button:hover{color:#fff;text-decoration:none}.bar-positive .button.activated,.bar-positive .button.active{border-color:#0c60ee;background-color:#0c60ee}.bar-positive .button.button-clear,.bar-positive .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-positive .button.button-icon{border-color:transparent;background:0 0}.bar-calm .button{border-color:#0a9dc7;background-color:#11c1f3;color:#fff}.bar-calm .button:hover{color:#fff;text-decoration:none}.bar-calm .button.activated,.bar-calm .button.active{border-color:#0a9dc7;background-color:#0a9dc7}.bar-calm .button.button-clear,.bar-calm .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-calm .button.button-icon{border-color:transparent;background:0 0}.bar-assertive .button{border-color:#e42112;background-color:#ef473a;color:#fff}.bar-assertive .button:hover{color:#fff;text-decoration:none}.bar-assertive .button.activated,.bar-assertive .button.active{border-color:#e42112;background-color:#e42112}.bar-assertive .button.button-clear,.bar-assertive .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-assertive .button.button-icon{border-color:transparent;background:0 0}.bar-balanced .button{border-color:#28a54c;background-color:#33cd5f;color:#fff}.bar-balanced .button:hover{color:#fff;text-decoration:none}.bar-balanced .button.activated,.bar-balanced .button.active{border-color:#28a54c;background-color:#28a54c}.bar-balanced .button.button-clear,.bar-balanced .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-balanced .button.button-icon{border-color:transparent;background:0 0}.bar-energized .button{border-color:#e6b500;background-color:#ffc900;color:#fff}.bar-energized .button:hover{color:#fff;text-decoration:none}.bar-energized .button.activated,.bar-energized .button.active{border-color:#e6b500;background-color:#e6b500}.bar-energized .button.button-clear,.bar-energized .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-energized .button.button-icon{border-color:transparent;background:0 0}.bar-royal .button{border-color:#6b46e5;background-color:#886aea;color:#fff}.bar-royal .button:hover{color:#fff;text-decoration:none}.bar-royal .button.activated,.bar-royal .button.active{border-color:#6b46e5;background-color:#6b46e5}.bar-royal .button.button-clear,.bar-royal .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-royal .button.button-icon{border-color:transparent;background:0 0}.bar-dark .button{border-color:#111;background-color:#444;color:#fff}.bar-dark .button:hover{color:#fff;text-decoration:none}.bar-dark .button.activated,.bar-dark .button.active{border-color:#000;background-color:#262626}.bar-dark .button.button-clear,.bar-dark .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-dark .button.button-icon{border-color:transparent;background:0 0}.bar-header{top:0;border-top-width:0;border-bottom-width:1px}.bar-header.has-tabs-top{border-bottom-width:0;background-image:none}.tabs-top .bar-header{border-bottom-width:0;background-image:none}.bar-footer{bottom:0;border-top-width:1px;border-bottom-width:0;background-position:top;height:44px}.bar-footer.item-input-inset{position:absolute}.bar-footer .title{height:43px;line-height:44px}.bar-tabs{padding:0}.bar-subheader{top:44px;height:44px}.bar-subheader .title{height:43px;line-height:44px}.bar-subfooter{bottom:44px;height:44px}.bar-subfooter .title{height:43px;line-height:44px}.nav-bar-block{position:absolute;top:0;right:0;left:0;z-index:9}.bar .back-button.hide,.bar .buttons .hide{display:none}.nav-bar-tabs-top .bar{background-image:none}.tabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:horizontal;-moz-flex-direction:horizontal;-ms-flex-direction:horizontal;flex-direction:horizontal;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444;position:absolute;bottom:0;z-index:5;width:100%;height:49px;border-style:solid;border-top-width:1px;background-size:0;line-height:49px}.tabs .tab-item .badge{background-color:#444;color:#f8f8f8}@media (min--moz-device-pixel-ratio:1.5),(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5),(min-resolution:144dpi),(min-resolution:1.5dppx){.tabs{padding-top:2px;border-top:none!important;border-bottom:none;background-position:top;background-size:100% 1px;background-repeat:no-repeat}}.tabs-light>.tabs,.tabs.tabs-light{border-color:#ddd;background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);color:#444}.tabs-light>.tabs .tab-item .badge,.tabs.tabs-light .tab-item .badge{background-color:#444;color:#fff}.tabs-stable>.tabs,.tabs.tabs-stable{border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444}.tabs-stable>.tabs .tab-item .badge,.tabs.tabs-stable .tab-item .badge{background-color:#444;color:#f8f8f8}.tabs-positive>.tabs,.tabs.tabs-positive{border-color:#0c60ee;background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);color:#fff}.tabs-positive>.tabs .tab-item .badge,.tabs.tabs-positive .tab-item .badge{background-color:#fff;color:#387ef5}.tabs-calm>.tabs,.tabs.tabs-calm{border-color:#0a9dc7;background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);color:#fff}.tabs-calm>.tabs .tab-item .badge,.tabs.tabs-calm .tab-item .badge{background-color:#fff;color:#11c1f3}.tabs-assertive>.tabs,.tabs.tabs-assertive{border-color:#e42112;background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);color:#fff}.tabs-assertive>.tabs .tab-item .badge,.tabs.tabs-assertive .tab-item .badge{background-color:#fff;color:#ef473a}.tabs-balanced>.tabs,.tabs.tabs-balanced{border-color:#28a54c;background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);color:#fff}.tabs-balanced>.tabs .tab-item .badge,.tabs.tabs-balanced .tab-item .badge{background-color:#fff;color:#33cd5f}.tabs-energized>.tabs,.tabs.tabs-energized{border-color:#e6b500;background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);color:#fff}.tabs-energized>.tabs .tab-item .badge,.tabs.tabs-energized .tab-item .badge{background-color:#fff;color:#ffc900}.tabs-royal>.tabs,.tabs.tabs-royal{border-color:#6b46e5;background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);color:#fff}.tabs-royal>.tabs .tab-item .badge,.tabs.tabs-royal .tab-item .badge{background-color:#fff;color:#886aea}.tabs-dark>.tabs,.tabs.tabs-dark{border-color:#111;background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);color:#fff}.tabs-dark>.tabs .tab-item .badge,.tabs.tabs-dark .tab-item .badge{background-color:#fff;color:#444}.tabs-striped .tabs{background-color:#fff;background-image:none;border:none;border-bottom:1px solid #ddd;padding-top:2px}.tabs-striped .tab-item.activated,.tabs-striped .tab-item.active,.tabs-striped .tab-item.tab-item-active{margin-top:-2px;border-style:solid;border-width:2px 0 0 0;border-color:#444}.tabs-striped .tab-item.activated .badge,.tabs-striped .tab-item.active .badge,.tabs-striped .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-light .tabs{background-color:#fff}.tabs-striped.tabs-light .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-light .tab-item .badge{opacity:.4}.tabs-striped.tabs-light .tab-item.activated,.tabs-striped.tabs-light .tab-item.active,.tabs-striped.tabs-light .tab-item.tab-item-active{margin-top:-2px;color:#444;border-style:solid;border-width:2px 0 0 0;border-color:#444}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-stable .tabs{background-color:#f8f8f8}.tabs-striped.tabs-stable .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-stable .tab-item .badge{opacity:.4}.tabs-striped.tabs-stable .tab-item.activated,.tabs-striped.tabs-stable .tab-item.active,.tabs-striped.tabs-stable .tab-item.tab-item-active{margin-top:-2px;color:#444;border-style:solid;border-width:2px 0 0 0;border-color:#444}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-positive .tabs{background-color:#387ef5}.tabs-striped.tabs-positive .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-positive .tab-item .badge{opacity:.4}.tabs-striped.tabs-positive .tab-item.activated,.tabs-striped.tabs-positive .tab-item.active,.tabs-striped.tabs-positive .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-calm .tabs{background-color:#11c1f3}.tabs-striped.tabs-calm .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-calm .tab-item .badge{opacity:.4}.tabs-striped.tabs-calm .tab-item.activated,.tabs-striped.tabs-calm .tab-item.active,.tabs-striped.tabs-calm .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-assertive .tabs{background-color:#ef473a}.tabs-striped.tabs-assertive .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-assertive .tab-item .badge{opacity:.4}.tabs-striped.tabs-assertive .tab-item.activated,.tabs-striped.tabs-assertive .tab-item.active,.tabs-striped.tabs-assertive .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-balanced .tabs{background-color:#33cd5f}.tabs-striped.tabs-balanced .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-balanced .tab-item .badge{opacity:.4}.tabs-striped.tabs-balanced .tab-item.activated,.tabs-striped.tabs-balanced .tab-item.active,.tabs-striped.tabs-balanced .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-energized .tabs{background-color:#ffc900}.tabs-striped.tabs-energized .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-energized .tab-item .badge{opacity:.4}.tabs-striped.tabs-energized .tab-item.activated,.tabs-striped.tabs-energized .tab-item.active,.tabs-striped.tabs-energized .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-royal .tabs{background-color:#886aea}.tabs-striped.tabs-royal .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-royal .tab-item .badge{opacity:.4}.tabs-striped.tabs-royal .tab-item.activated,.tabs-striped.tabs-royal .tab-item.active,.tabs-striped.tabs-royal .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-dark .tabs{background-color:#444}.tabs-striped.tabs-dark .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-dark .tab-item .badge{opacity:.4}.tabs-striped.tabs-dark .tab-item.activated,.tabs-striped.tabs-dark .tab-item.active,.tabs-striped.tabs-dark .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-background-light .tabs{background-color:#fff;background-image:none}.tabs-striped.tabs-background-stable .tabs{background-color:#f8f8f8;background-image:none}.tabs-striped.tabs-background-positive .tabs{background-color:#387ef5;background-image:none}.tabs-striped.tabs-background-calm .tabs{background-color:#11c1f3;background-image:none}.tabs-striped.tabs-background-assertive .tabs{background-color:#ef473a;background-image:none}.tabs-striped.tabs-background-balanced .tabs{background-color:#33cd5f;background-image:none}.tabs-striped.tabs-background-energized .tabs{background-color:#ffc900;background-image:none}.tabs-striped.tabs-background-royal .tabs{background-color:#886aea;background-image:none}.tabs-striped.tabs-background-dark .tabs{background-color:#444;background-image:none}.tabs-striped.tabs-color-light .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-color-light .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-light .tab-item.activated,.tabs-striped.tabs-color-light .tab-item.active,.tabs-striped.tabs-color-light .tab-item.tab-item-active{margin-top:-2px;color:#fff;border:0 solid #fff;border-top-width:2px}.tabs-striped.tabs-color-light .tab-item.activated .badge,.tabs-striped.tabs-color-light .tab-item.active .badge,.tabs-striped.tabs-color-light .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-stable .tab-item{color:rgba(248,248,248,.4);opacity:1}.tabs-striped.tabs-color-stable .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-stable .tab-item.activated,.tabs-striped.tabs-color-stable .tab-item.active,.tabs-striped.tabs-color-stable .tab-item.tab-item-active{margin-top:-2px;color:#f8f8f8;border:0 solid #f8f8f8;border-top-width:2px}.tabs-striped.tabs-color-stable .tab-item.activated .badge,.tabs-striped.tabs-color-stable .tab-item.active .badge,.tabs-striped.tabs-color-stable .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-positive .tab-item{color:rgba(56,126,245,.4);opacity:1}.tabs-striped.tabs-color-positive .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-positive .tab-item.activated,.tabs-striped.tabs-color-positive .tab-item.active,.tabs-striped.tabs-color-positive .tab-item.tab-item-active{margin-top:-2px;color:#387ef5;border:0 solid #387ef5;border-top-width:2px}.tabs-striped.tabs-color-positive .tab-item.activated .badge,.tabs-striped.tabs-color-positive .tab-item.active .badge,.tabs-striped.tabs-color-positive .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-calm .tab-item{color:rgba(17,193,243,.4);opacity:1}.tabs-striped.tabs-color-calm .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-calm .tab-item.activated,.tabs-striped.tabs-color-calm .tab-item.active,.tabs-striped.tabs-color-calm .tab-item.tab-item-active{margin-top:-2px;color:#11c1f3;border:0 solid #11c1f3;border-top-width:2px}.tabs-striped.tabs-color-calm .tab-item.activated .badge,.tabs-striped.tabs-color-calm .tab-item.active .badge,.tabs-striped.tabs-color-calm .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-assertive .tab-item{color:rgba(239,71,58,.4);opacity:1}.tabs-striped.tabs-color-assertive .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-assertive .tab-item.activated,.tabs-striped.tabs-color-assertive .tab-item.active,.tabs-striped.tabs-color-assertive .tab-item.tab-item-active{margin-top:-2px;color:#ef473a;border:0 solid #ef473a;border-top-width:2px}.tabs-striped.tabs-color-assertive .tab-item.activated .badge,.tabs-striped.tabs-color-assertive .tab-item.active .badge,.tabs-striped.tabs-color-assertive .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-balanced .tab-item{color:rgba(51,205,95,.4);opacity:1}.tabs-striped.tabs-color-balanced .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-balanced .tab-item.activated,.tabs-striped.tabs-color-balanced .tab-item.active,.tabs-striped.tabs-color-balanced .tab-item.tab-item-active{margin-top:-2px;color:#33cd5f;border:0 solid #33cd5f;border-top-width:2px}.tabs-striped.tabs-color-balanced .tab-item.activated .badge,.tabs-striped.tabs-color-balanced .tab-item.active .badge,.tabs-striped.tabs-color-balanced .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-energized .tab-item{color:rgba(255,201,0,.4);opacity:1}.tabs-striped.tabs-color-energized .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-energized .tab-item.activated,.tabs-striped.tabs-color-energized .tab-item.active,.tabs-striped.tabs-color-energized .tab-item.tab-item-active{margin-top:-2px;color:#ffc900;border:0 solid #ffc900;border-top-width:2px}.tabs-striped.tabs-color-energized .tab-item.activated .badge,.tabs-striped.tabs-color-energized .tab-item.active .badge,.tabs-striped.tabs-color-energized .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-royal .tab-item{color:rgba(136,106,234,.4);opacity:1}.tabs-striped.tabs-color-royal .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-royal .tab-item.activated,.tabs-striped.tabs-color-royal .tab-item.active,.tabs-striped.tabs-color-royal .tab-item.tab-item-active{margin-top:-2px;color:#886aea;border:0 solid #886aea;border-top-width:2px}.tabs-striped.tabs-color-royal .tab-item.activated .badge,.tabs-striped.tabs-color-royal .tab-item.active .badge,.tabs-striped.tabs-color-royal .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-dark .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-color-dark .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-dark .tab-item.activated,.tabs-striped.tabs-color-dark .tab-item.active,.tabs-striped.tabs-color-dark .tab-item.tab-item-active{margin-top:-2px;color:#444;border:0 solid #444;border-top-width:2px}.tabs-striped.tabs-color-dark .tab-item.activated .badge,.tabs-striped.tabs-color-dark .tab-item.active .badge,.tabs-striped.tabs-color-dark .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-background-light .tabs,.tabs-background-light>.tabs{background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);border-color:#ddd}.tabs-background-stable .tabs,.tabs-background-stable>.tabs{background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);border-color:#b2b2b2}.tabs-background-positive .tabs,.tabs-background-positive>.tabs{background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);border-color:#0c60ee}.tabs-background-calm .tabs,.tabs-background-calm>.tabs{background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);border-color:#0a9dc7}.tabs-background-assertive .tabs,.tabs-background-assertive>.tabs{background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);border-color:#e42112}.tabs-background-balanced .tabs,.tabs-background-balanced>.tabs{background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);border-color:#28a54c}.tabs-background-energized .tabs,.tabs-background-energized>.tabs{background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);border-color:#e6b500}.tabs-background-royal .tabs,.tabs-background-royal>.tabs{background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);border-color:#6b46e5}.tabs-background-dark .tabs,.tabs-background-dark>.tabs{background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);border-color:#111}.tabs-color-light .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-color-light .tab-item .badge{opacity:.4}.tabs-color-light .tab-item.activated,.tabs-color-light .tab-item.active,.tabs-color-light .tab-item.tab-item-active{color:#fff;border:0 solid #fff}.tabs-color-light .tab-item.activated .badge,.tabs-color-light .tab-item.active .badge,.tabs-color-light .tab-item.tab-item-active .badge{opacity:1}.tabs-color-stable .tab-item{color:rgba(248,248,248,.4);opacity:1}.tabs-color-stable .tab-item .badge{opacity:.4}.tabs-color-stable .tab-item.activated,.tabs-color-stable .tab-item.active,.tabs-color-stable .tab-item.tab-item-active{color:#f8f8f8;border:0 solid #f8f8f8}.tabs-color-stable .tab-item.activated .badge,.tabs-color-stable .tab-item.active .badge,.tabs-color-stable .tab-item.tab-item-active .badge{opacity:1}.tabs-color-positive .tab-item{color:rgba(56,126,245,.4);opacity:1}.tabs-color-positive .tab-item .badge{opacity:.4}.tabs-color-positive .tab-item.activated,.tabs-color-positive .tab-item.active,.tabs-color-positive .tab-item.tab-item-active{color:#387ef5;border:0 solid #387ef5}.tabs-color-positive .tab-item.activated .badge,.tabs-color-positive .tab-item.active .badge,.tabs-color-positive .tab-item.tab-item-active .badge{opacity:1}.tabs-color-calm .tab-item{color:rgba(17,193,243,.4);opacity:1}.tabs-color-calm .tab-item .badge{opacity:.4}.tabs-color-calm .tab-item.activated,.tabs-color-calm .tab-item.active,.tabs-color-calm .tab-item.tab-item-active{color:#11c1f3;border:0 solid #11c1f3}.tabs-color-calm .tab-item.activated .badge,.tabs-color-calm .tab-item.active .badge,.tabs-color-calm .tab-item.tab-item-active .badge{opacity:1}.tabs-color-assertive .tab-item{color:rgba(239,71,58,.4);opacity:1}.tabs-color-assertive .tab-item .badge{opacity:.4}.tabs-color-assertive .tab-item.activated,.tabs-color-assertive .tab-item.active,.tabs-color-assertive .tab-item.tab-item-active{color:#ef473a;border:0 solid #ef473a}.tabs-color-assertive .tab-item.activated .badge,.tabs-color-assertive .tab-item.active .badge,.tabs-color-assertive .tab-item.tab-item-active .badge{opacity:1}.tabs-color-balanced .tab-item{color:rgba(51,205,95,.4);opacity:1}.tabs-color-balanced .tab-item .badge{opacity:.4}.tabs-color-balanced .tab-item.activated,.tabs-color-balanced .tab-item.active,.tabs-color-balanced .tab-item.tab-item-active{color:#33cd5f;border:0 solid #33cd5f}.tabs-color-balanced .tab-item.activated .badge,.tabs-color-balanced .tab-item.active .badge,.tabs-color-balanced .tab-item.tab-item-active .badge{opacity:1}.tabs-color-energized .tab-item{color:rgba(255,201,0,.4);opacity:1}.tabs-color-energized .tab-item .badge{opacity:.4}.tabs-color-energized .tab-item.activated,.tabs-color-energized .tab-item.active,.tabs-color-energized .tab-item.tab-item-active{color:#ffc900;border:0 solid #ffc900}.tabs-color-energized .tab-item.activated .badge,.tabs-color-energized .tab-item.active .badge,.tabs-color-energized .tab-item.tab-item-active .badge{opacity:1}.tabs-color-royal .tab-item{color:rgba(136,106,234,.4);opacity:1}.tabs-color-royal .tab-item .badge{opacity:.4}.tabs-color-royal .tab-item.activated,.tabs-color-royal .tab-item.active,.tabs-color-royal .tab-item.tab-item-active{color:#886aea;border:0 solid #886aea}.tabs-color-royal .tab-item.activated .badge,.tabs-color-royal .tab-item.active .badge,.tabs-color-royal .tab-item.tab-item-active .badge{opacity:1}.tabs-color-dark .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-color-dark .tab-item .badge{opacity:.4}.tabs-color-dark .tab-item.activated,.tabs-color-dark .tab-item.active,.tabs-color-dark .tab-item.tab-item-active{color:#444;border:0 solid #444}.tabs-color-dark .tab-item.activated .badge,.tabs-color-dark .tab-item.active .badge,.tabs-color-dark .tab-item.tab-item-active .badge{opacity:1}ion-tabs.tabs-color-active-light .tab-item{color:#444}ion-tabs.tabs-color-active-light .tab-item.activated,ion-tabs.tabs-color-active-light .tab-item.active,ion-tabs.tabs-color-active-light .tab-item.tab-item-active{color:#fff}ion-tabs.tabs-striped.tabs-color-active-light .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-light .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-light .tab-item.tab-item-active{border-color:#fff;color:#fff}ion-tabs.tabs-color-active-stable .tab-item{color:#444}ion-tabs.tabs-color-active-stable .tab-item.activated,ion-tabs.tabs-color-active-stable .tab-item.active,ion-tabs.tabs-color-active-stable .tab-item.tab-item-active{color:#f8f8f8}ion-tabs.tabs-striped.tabs-color-active-stable .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-stable .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-stable .tab-item.tab-item-active{border-color:#f8f8f8;color:#f8f8f8}ion-tabs.tabs-color-active-positive .tab-item{color:#444}ion-tabs.tabs-color-active-positive .tab-item.activated,ion-tabs.tabs-color-active-positive .tab-item.active,ion-tabs.tabs-color-active-positive .tab-item.tab-item-active{color:#387ef5}ion-tabs.tabs-striped.tabs-color-active-positive .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-positive .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-positive .tab-item.tab-item-active{border-color:#387ef5;color:#387ef5}ion-tabs.tabs-color-active-calm .tab-item{color:#444}ion-tabs.tabs-color-active-calm .tab-item.activated,ion-tabs.tabs-color-active-calm .tab-item.active,ion-tabs.tabs-color-active-calm .tab-item.tab-item-active{color:#11c1f3}ion-tabs.tabs-striped.tabs-color-active-calm .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-calm .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-calm .tab-item.tab-item-active{border-color:#11c1f3;color:#11c1f3}ion-tabs.tabs-color-active-assertive .tab-item{color:#444}ion-tabs.tabs-color-active-assertive .tab-item.activated,ion-tabs.tabs-color-active-assertive .tab-item.active,ion-tabs.tabs-color-active-assertive .tab-item.tab-item-active{color:#ef473a}ion-tabs.tabs-striped.tabs-color-active-assertive .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-assertive .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-assertive .tab-item.tab-item-active{border-color:#ef473a;color:#ef473a}ion-tabs.tabs-color-active-balanced .tab-item{color:#444}ion-tabs.tabs-color-active-balanced .tab-item.activated,ion-tabs.tabs-color-active-balanced .tab-item.active,ion-tabs.tabs-color-active-balanced .tab-item.tab-item-active{color:#33cd5f}ion-tabs.tabs-striped.tabs-color-active-balanced .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-balanced .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-balanced .tab-item.tab-item-active{border-color:#33cd5f;color:#33cd5f}ion-tabs.tabs-color-active-energized .tab-item{color:#444}ion-tabs.tabs-color-active-energized .tab-item.activated,ion-tabs.tabs-color-active-energized .tab-item.active,ion-tabs.tabs-color-active-energized .tab-item.tab-item-active{color:#ffc900}ion-tabs.tabs-striped.tabs-color-active-energized .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-energized .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-energized .tab-item.tab-item-active{border-color:#ffc900;color:#ffc900}ion-tabs.tabs-color-active-royal .tab-item{color:#444}ion-tabs.tabs-color-active-royal .tab-item.activated,ion-tabs.tabs-color-active-royal .tab-item.active,ion-tabs.tabs-color-active-royal .tab-item.tab-item-active{color:#886aea}ion-tabs.tabs-striped.tabs-color-active-royal .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-royal .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-royal .tab-item.tab-item-active{border-color:#886aea;color:#886aea}ion-tabs.tabs-color-active-dark .tab-item{color:#fff}ion-tabs.tabs-color-active-dark .tab-item.activated,ion-tabs.tabs-color-active-dark .tab-item.active,ion-tabs.tabs-color-active-dark .tab-item.tab-item-active{color:#444}ion-tabs.tabs-striped.tabs-color-active-dark .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-dark .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-dark .tab-item.tab-item-active{border-color:#444;color:#444}.tabs-top.tabs-striped{padding-bottom:0}.tabs-top.tabs-striped .tab-item{background:0 0;-webkit-transition:color .1s ease;-moz-transition:color .1s ease;-ms-transition:color .1s ease;-o-transition:color .1s ease;transition:color .1s ease}.tabs-top.tabs-striped .tab-item.activated,.tabs-top.tabs-striped .tab-item.active,.tabs-top.tabs-striped .tab-item.tab-item-active{margin-top:1px;border-width:0 0 2px 0!important;border-style:solid}.tabs-top.tabs-striped .tab-item.activated>.badge,.tabs-top.tabs-striped .tab-item.activated>i,.tabs-top.tabs-striped .tab-item.active>.badge,.tabs-top.tabs-striped .tab-item.active>i,.tabs-top.tabs-striped .tab-item.tab-item-active>.badge,.tabs-top.tabs-striped .tab-item.tab-item-active>i{margin-top:-1px}.tabs-top.tabs-striped .tab-item .badge{-webkit-transition:color .2s ease;-moz-transition:color .2s ease;-ms-transition:color .2s ease;-o-transition:color .2s ease;transition:color .2s ease}.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated i,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active i,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active i{display:block;margin-top:-1px}.tabs-top.tabs-striped.tabs-icon-left .tab-item{margin-top:1px}.tabs-top.tabs-striped.tabs-icon-left .tab-item.activated .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.activated i,.tabs-top.tabs-striped.tabs-icon-left .tab-item.active .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.active i,.tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active i{margin-top:-.1em}.tabs-top>.tabs,.tabs.tabs-top{top:44px;padding-top:0;background-position:bottom;border-top-width:0;border-bottom-width:1px}.tabs-top>.tabs .tab-item.activated .badge,.tabs-top>.tabs .tab-item.active .badge,.tabs-top>.tabs .tab-item.tab-item-active .badge,.tabs.tabs-top .tab-item.activated .badge,.tabs.tabs-top .tab-item.active .badge,.tabs.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-top~.bar-header{border-bottom-width:0}.tab-item{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;overflow:hidden;max-width:150px;height:100%;color:inherit;text-align:center;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;font-weight:400;font-size:14px;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;opacity:.7}.tab-item:hover{cursor:pointer}.tab-item.tab-hidden{display:none}.tabs-item-hide>.tabs,.tabs.tabs-item-hide{display:none}.tabs-icon-bottom.tabs .tab-item,.tabs-icon-bottom>.tabs .tab-item,.tabs-icon-top.tabs .tab-item,.tabs-icon-top>.tabs .tab-item{font-size:10px;line-height:14px}#menu .footer .tab-item .icon-help,.tab-item #menu .footer .icon-help,.tab-item .icon,.tab-item .icon-alert,.tab-item .icon-help{display:block;margin:0 auto;height:32px;font-size:32px}.tabs-icon-left.tabs .tab-item,.tabs-icon-left>.tabs .tab-item,.tabs-icon-right.tabs .tab-item,.tabs-icon-right>.tabs .tab-item{font-size:10px}#menu .footer .tabs-icon-left.tabs .tab-item .icon-help,#menu .footer .tabs-icon-left>.tabs .tab-item .icon-help,#menu .footer .tabs-icon-right.tabs .tab-item .icon-help,#menu .footer .tabs-icon-right>.tabs .tab-item .icon-help,.tabs-icon-left.tabs .tab-item #menu .footer .icon-help,.tabs-icon-left.tabs .tab-item .icon,.tabs-icon-left.tabs .tab-item .icon-alert,.tabs-icon-left.tabs .tab-item .icon-help,.tabs-icon-left.tabs .tab-item .tab-title,.tabs-icon-left>.tabs .tab-item #menu .footer .icon-help,.tabs-icon-left>.tabs .tab-item .icon,.tabs-icon-left>.tabs .tab-item .icon-alert,.tabs-icon-left>.tabs .tab-item .icon-help,.tabs-icon-left>.tabs .tab-item .tab-title,.tabs-icon-right.tabs .tab-item #menu .footer .icon-help,.tabs-icon-right.tabs .tab-item .icon,.tabs-icon-right.tabs .tab-item .icon-alert,.tabs-icon-right.tabs .tab-item .icon-help,.tabs-icon-right.tabs .tab-item .tab-title,.tabs-icon-right>.tabs .tab-item #menu .footer .icon-help,.tabs-icon-right>.tabs .tab-item .icon,.tabs-icon-right>.tabs .tab-item .icon-alert,.tabs-icon-right>.tabs .tab-item .icon-help,.tabs-icon-right>.tabs .tab-item .tab-title{display:inline-block;vertical-align:top;margin-top:-.1em}#menu .footer .tabs-icon-left.tabs .tab-item .icon-help:before,#menu .footer .tabs-icon-left>.tabs .tab-item .icon-help:before,#menu .footer .tabs-icon-right.tabs .tab-item .icon-help:before,#menu .footer .tabs-icon-right>.tabs .tab-item .icon-help:before,.tabs-icon-left.tabs .tab-item #menu .footer .icon-help:before,.tabs-icon-left.tabs .tab-item .icon-alert:before,.tabs-icon-left.tabs .tab-item .icon-help:before,.tabs-icon-left.tabs .tab-item .icon:before,.tabs-icon-left.tabs .tab-item .tab-title:before,.tabs-icon-left>.tabs .tab-item #menu .footer .icon-help:before,.tabs-icon-left>.tabs .tab-item .icon-alert:before,.tabs-icon-left>.tabs .tab-item .icon-help:before,.tabs-icon-left>.tabs .tab-item .icon:before,.tabs-icon-left>.tabs .tab-item .tab-title:before,.tabs-icon-right.tabs .tab-item #menu .footer .icon-help:before,.tabs-icon-right.tabs .tab-item .icon-alert:before,.tabs-icon-right.tabs .tab-item .icon-help:before,.tabs-icon-right.tabs .tab-item .icon:before,.tabs-icon-right.tabs .tab-item .tab-title:before,.tabs-icon-right>.tabs .tab-item #menu .footer .icon-help:before,.tabs-icon-right>.tabs .tab-item .icon-alert:before,.tabs-icon-right>.tabs .tab-item .icon-help:before,.tabs-icon-right>.tabs .tab-item .icon:before,.tabs-icon-right>.tabs .tab-item .tab-title:before{font-size:24px;line-height:49px}#menu .footer .tabs-icon-left.tabs .tab-item .icon-help,#menu .footer .tabs-icon-left>.tabs .tab-item .icon-help,.tabs-icon-left.tabs .tab-item #menu .footer .icon-help,.tabs-icon-left.tabs .tab-item .icon,.tabs-icon-left.tabs .tab-item .icon-alert,.tabs-icon-left.tabs .tab-item .icon-help,.tabs-icon-left>.tabs .tab-item #menu .footer .icon-help,.tabs-icon-left>.tabs .tab-item .icon,.tabs-icon-left>.tabs .tab-item .icon-alert,.tabs-icon-left>.tabs .tab-item .icon-help{padding-right:3px}#menu .footer .tabs-icon-right.tabs .tab-item .icon-help,#menu .footer .tabs-icon-right>.tabs .tab-item .icon-help,.tabs-icon-right.tabs .tab-item #menu .footer .icon-help,.tabs-icon-right.tabs .tab-item .icon,.tabs-icon-right.tabs .tab-item .icon-alert,.tabs-icon-right.tabs .tab-item .icon-help,.tabs-icon-right>.tabs .tab-item #menu .footer .icon-help,.tabs-icon-right>.tabs .tab-item .icon,.tabs-icon-right>.tabs .tab-item .icon-alert,.tabs-icon-right>.tabs .tab-item .icon-help{padding-left:3px}#menu .footer .tabs-icon-only.tabs .icon-help,#menu .footer .tabs-icon-only>.tabs .icon-help,.tabs-icon-only.tabs #menu .footer .icon-help,.tabs-icon-only.tabs .icon,.tabs-icon-only.tabs .icon-alert,.tabs-icon-only.tabs .icon-help,.tabs-icon-only>.tabs #menu .footer .icon-help,.tabs-icon-only>.tabs .icon,.tabs-icon-only>.tabs .icon-alert,.tabs-icon-only>.tabs .icon-help{line-height:inherit}.tab-item.has-badge{position:relative}.tab-item .badge{position:absolute;top:4%;right:33%;right:calc(50% - 26px);padding:1px 6px;height:auto;font-size:12px;line-height:16px}.tab-item.activated,.tab-item.active,.tab-item.tab-item-active{opacity:1}.tab-item.activated.tab-item-light,.tab-item.active.tab-item-light,.tab-item.tab-item-active.tab-item-light{color:#fff}.tab-item.activated.tab-item-stable,.tab-item.active.tab-item-stable,.tab-item.tab-item-active.tab-item-stable{color:#f8f8f8}.tab-item.activated.tab-item-positive,.tab-item.active.tab-item-positive,.tab-item.tab-item-active.tab-item-positive{color:#387ef5}.tab-item.activated.tab-item-calm,.tab-item.active.tab-item-calm,.tab-item.tab-item-active.tab-item-calm{color:#11c1f3}.tab-item.activated.tab-item-assertive,.tab-item.active.tab-item-assertive,.tab-item.tab-item-active.tab-item-assertive{color:#ef473a}.tab-item.activated.tab-item-balanced,.tab-item.active.tab-item-balanced,.tab-item.tab-item-active.tab-item-balanced{color:#33cd5f}.tab-item.activated.tab-item-energized,.tab-item.active.tab-item-energized,.tab-item.tab-item-active.tab-item-energized{color:#ffc900}.tab-item.activated.tab-item-royal,.tab-item.active.tab-item-royal,.tab-item.tab-item-active.tab-item-royal{color:#886aea}.tab-item.activated.tab-item-dark,.tab-item.active.tab-item-dark,.tab-item.tab-item-active.tab-item-dark{color:#444}.item.tabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;padding:0}#menu .footer .item.tabs .icon-help:before,.item.tabs #menu .footer .icon-help:before,.item.tabs .icon-alert:before,.item.tabs .icon-help:before,.item.tabs .icon:before{position:relative}.tab-item.disabled,.tab-item[disabled]{opacity:.4;cursor:default;pointer-events:none}.nav-bar-tabs-top.hide~.view-container .tabs-top .tabs{top:0}.pane[hide-nav-bar=true] .has-tabs-top{top:49px}.menu{position:absolute;top:0;bottom:0;z-index:0;overflow:hidden;min-height:100%;max-height:100%;width:275px;background-color:#fff}.menu .scroll-content{z-index:10}.menu .bar-header{z-index:11}.menu-content{-webkit-transform:none;transform:none;box-shadow:-1px 0 2px rgba(0,0,0,.2),1px 0 2px rgba(0,0,0,.2)}.menu-open .menu-content .pane,.menu-open .menu-content .scroll-content{pointer-events:none}.menu-open .menu-content .scroll-content .scroll{pointer-events:none}.menu-open .menu-content .scroll-content:not(.overflow-scroll){overflow:hidden}.grade-b .menu-content,.grade-c .menu-content{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;right:-1px;left:-1px;border-right:1px solid #ccc;border-left:1px solid #ccc;box-shadow:none}.menu-left{left:0}.menu-right{right:0}.aside-open.aside-resizing .menu-right{display:none}.menu-animated{-webkit-transition:-webkit-transform .2s ease;transition:transform .2s ease}.modal-backdrop,.modal-backdrop-bg{position:fixed;top:0;left:0;z-index:10;width:100%;height:100%}.modal-backdrop-bg{pointer-events:none}.modal{display:block;position:absolute;top:0;z-index:10;overflow:hidden;min-height:100%;width:100%;background-color:#fff}@media (min-width:680px){.modal{top:20%;right:20%;bottom:20%;left:20%;min-height:240px;width:60%}.modal.ng-leave-active{bottom:0}.platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader){height:44px}.platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader)>*{margin-top:0}.platform-ios.platform-cordova .modal-wrapper .modal .tabs-top>.tabs,.platform-ios.platform-cordova .modal-wrapper .modal .tabs.tabs-top{top:44px}.platform-ios.platform-cordova .modal-wrapper .modal .bar-subheader,.platform-ios.platform-cordova .modal-wrapper .modal .has-header{top:44px}.platform-ios.platform-cordova .modal-wrapper .modal .has-subheader{top:88px}.platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-tabs-top{top:93px}.platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-subheader.has-tabs-top{top:137px}.modal-backdrop-bg{-webkit-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out;background-color:#000;opacity:0}.active .modal-backdrop-bg{opacity:.5}}.modal-open{pointer-events:none}.modal-open .modal,.modal-open .modal-backdrop{pointer-events:auto}.modal-open.loading-active .modal,.modal-open.loading-active .modal-backdrop{pointer-events:none}.popover-backdrop{position:fixed;top:0;left:0;z-index:10;width:100%;height:100%;background-color:transparent}.popover-backdrop.active{background-color:rgba(0,0,0,.1)}.popover{position:absolute;top:25%;left:50%;z-index:10;display:block;margin-top:12px;margin-left:-110px;height:280px;width:220px;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.4);opacity:0}.popover .item:first-child{border-top:0}.popover .item:last-child{border-bottom:0}.popover.popover-bottom{margin-top:-12px}.popover,.popover .bar-header{border-radius:2px}.popover .scroll-content{z-index:1;margin:2px 0}.popover .bar-header{border-bottom-right-radius:0;border-bottom-left-radius:0}.popover .has-header{border-top-right-radius:0;border-top-left-radius:0}.popover-arrow{display:none}.platform-ios .popover{box-shadow:0 0 40px rgba(0,0,0,.08);border-radius:10px}.platform-ios .popover .bar-header{-webkit-border-top-right-radius:10px;border-top-right-radius:10px;-webkit-border-top-left-radius:10px;border-top-left-radius:10px}.platform-ios .popover .scroll-content{margin:8px 0;border-radius:10px}.platform-ios .popover .scroll-content.has-header{margin-top:0}.platform-ios .popover-arrow{position:absolute;display:block;top:-17px;width:30px;height:19px;overflow:hidden}.platform-ios .popover-arrow:after{position:absolute;top:12px;left:5px;width:20px;height:20px;background-color:#fff;border-radius:3px;content:'';-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.platform-ios .popover-bottom .popover-arrow{top:auto;bottom:-10px}.platform-ios .popover-bottom .popover-arrow:after{top:-6px}.platform-android .popover{margin-top:-32px;background-color:#fafafa;box-shadow:0 2px 6px rgba(0,0,0,.35)}.platform-android .popover .item{border-color:#fafafa;background-color:#fafafa;color:#4d4d4d}.platform-android .popover.popover-bottom{margin-top:32px}.platform-android .popover-backdrop,.platform-android .popover-backdrop.active{background-color:transparent}.popover-open{pointer-events:none}.popover-open .popover,.popover-open .popover-backdrop{pointer-events:auto}.popover-open.loading-active .popover,.popover-open.loading-active .popover-backdrop{pointer-events:none}@media (min-width:680px){.popover{width:360px;margin-left:-180px}}.popup-container{position:absolute;top:0;left:0;bottom:0;right:0;background:0 0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;z-index:12;visibility:hidden}.popup-container.popup-showing{visibility:visible}.popup-container.popup-hidden .popup{-webkit-animation-name:scaleOut;animation-name:scaleOut;-webkit-animation-duration:.1s;animation-duration:.1s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.popup-container.active .popup{-webkit-animation-name:superScaleIn;animation-name:superScaleIn;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.popup-container .popup{width:250px;max-width:100%;max-height:90%;border-radius:0;background-color:rgba(255,255,255,.9);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.popup-container input,.popup-container textarea{width:100%}.popup-head{padding:15px 10px;border-bottom:1px solid #eee;text-align:center}.popup-title{margin:0;padding:0;font-size:15px}.popup-sub-title{margin:5px 0 0 0;padding:0;font-weight:400;font-size:11px}.popup-body{padding:10px;overflow:auto}.popup-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;flex-direction:row;padding:10px;min-height:65px}.popup-buttons .button{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;min-height:45px;border-radius:2px;line-height:20px;margin-right:5px}.popup-buttons .button:last-child{margin-right:0}.popup-open{pointer-events:none}.popup-open.modal-open .modal{pointer-events:none}.popup-open .popup,.popup-open .popup-backdrop{pointer-events:auto}.loading-container{position:absolute;left:0;top:0;right:0;bottom:0;z-index:13;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;-webkit-transition:.2s opacity linear;transition:.2s opacity linear;visibility:hidden;opacity:0}#menu .footer .loading-container:not(.visible) .icon-help,.loading-container:not(.visible) #menu .footer .icon-help,.loading-container:not(.visible) .icon,.loading-container:not(.visible) .icon-alert,.loading-container:not(.visible) .icon-help,.loading-container:not(.visible) .spinner{display:none}.loading-container.visible{visibility:visible}.loading-container.active{opacity:1}.loading-container .loading{padding:20px;border-radius:5px;background-color:rgba(0,0,0,.7);color:#fff;text-align:center;text-overflow:ellipsis;font-size:15px}.loading-container .loading h1,.loading-container .loading h2,.loading-container .loading h3,.loading-container .loading h4,.loading-container .loading h5,.loading-container .loading h6{color:#fff}.item{border-color:#ddd;background-color:#fff;color:#444;position:relative;z-index:2;display:block;margin:-1px;padding:16px;border-width:1px;border-style:solid;font-size:16px}.item h2{margin:0 0 2px 0;font-size:16px;font-weight:400}.item h3{margin:0 0 4px 0;font-size:14px}.item h4{margin:0 0 4px 0;font-size:12px}.item h5,.item h6{margin:0 0 3px 0;font-size:10px}.item p{color:#666;font-size:14px;margin-bottom:2px}.item h1:last-child,.item h2:last-child,.item h3:last-child,.item h4:last-child,.item h5:last-child,.item h6:last-child,.item p:last-child{margin-bottom:0}.item .badge{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;position:absolute;top:16px;right:32px}.item.item-button-right .badge{right:67px}.item.item-divider .badge{top:8px}.item .badge+.badge{margin-right:5px}.item.item-light{border-color:#ddd;background-color:#fff;color:#444}.item.item-stable{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.item.item-positive{border-color:#0c60ee;background-color:#387ef5;color:#fff}.item.item-calm{border-color:#0a9dc7;background-color:#11c1f3;color:#fff}.item.item-assertive{border-color:#e42112;background-color:#ef473a;color:#fff}.item.item-balanced{border-color:#28a54c;background-color:#33cd5f;color:#fff}.item.item-energized{border-color:#e6b500;background-color:#ffc900;color:#fff}.item.item-royal{border-color:#6b46e5;background-color:#886aea;color:#fff}.item.item-dark{border-color:#111;background-color:#444;color:#fff}.item[ng-click]:hover{cursor:pointer}.item-borderless,.list-borderless .item{border-width:0}.item .item-content.activated,.item .item-content.active,.item-complex.activated .item-content,.item-complex.active .item-content,.item.activated,.item.active{border-color:#ccc;background-color:#d9d9d9}.item .item-content.activated.item-complex>.item-content,.item .item-content.active.item-complex>.item-content,.item-complex.activated .item-content.item-complex>.item-content,.item-complex.active .item-content.item-complex>.item-content,.item.activated.item-complex>.item-content,.item.active.item-complex>.item-content{border-color:#ccc;background-color:#d9d9d9}.item .item-content.activated.item-light,.item .item-content.active.item-light,.item-complex.activated .item-content.item-light,.item-complex.active .item-content.item-light,.item.activated.item-light,.item.active.item-light{border-color:#ccc;background-color:#fafafa}.item .item-content.activated.item-light.item-complex>.item-content,.item .item-content.active.item-light.item-complex>.item-content,.item-complex.activated .item-content.item-light.item-complex>.item-content,.item-complex.active .item-content.item-light.item-complex>.item-content,.item.activated.item-light.item-complex>.item-content,.item.active.item-light.item-complex>.item-content{border-color:#ccc;background-color:#fafafa}.item .item-content.activated.item-stable,.item .item-content.active.item-stable,.item-complex.activated .item-content.item-stable,.item-complex.active .item-content.item-stable,.item.activated.item-stable,.item.active.item-stable{border-color:#a2a2a2;background-color:#e5e5e5}.item .item-content.activated.item-stable.item-complex>.item-content,.item .item-content.active.item-stable.item-complex>.item-content,.item-complex.activated .item-content.item-stable.item-complex>.item-content,.item-complex.active .item-content.item-stable.item-complex>.item-content,.item.activated.item-stable.item-complex>.item-content,.item.active.item-stable.item-complex>.item-content{border-color:#a2a2a2;background-color:#e5e5e5}.item .item-content.activated.item-positive,.item .item-content.active.item-positive,.item-complex.activated .item-content.item-positive,.item-complex.active .item-content.item-positive,.item.activated.item-positive,.item.active.item-positive{border-color:#0c60ee;background-color:#0c60ee}.item .item-content.activated.item-positive.item-complex>.item-content,.item .item-content.active.item-positive.item-complex>.item-content,.item-complex.activated .item-content.item-positive.item-complex>.item-content,.item-complex.active .item-content.item-positive.item-complex>.item-content,.item.activated.item-positive.item-complex>.item-content,.item.active.item-positive.item-complex>.item-content{border-color:#0c60ee;background-color:#0c60ee}.item .item-content.activated.item-calm,.item .item-content.active.item-calm,.item-complex.activated .item-content.item-calm,.item-complex.active .item-content.item-calm,.item.activated.item-calm,.item.active.item-calm{border-color:#0a9dc7;background-color:#0a9dc7}.item .item-content.activated.item-calm.item-complex>.item-content,.item .item-content.active.item-calm.item-complex>.item-content,.item-complex.activated .item-content.item-calm.item-complex>.item-content,.item-complex.active .item-content.item-calm.item-complex>.item-content,.item.activated.item-calm.item-complex>.item-content,.item.active.item-calm.item-complex>.item-content{border-color:#0a9dc7;background-color:#0a9dc7}.item .item-content.activated.item-assertive,.item .item-content.active.item-assertive,.item-complex.activated .item-content.item-assertive,.item-complex.active .item-content.item-assertive,.item.activated.item-assertive,.item.active.item-assertive{border-color:#e42112;background-color:#e42112}.item .item-content.activated.item-assertive.item-complex>.item-content,.item .item-content.active.item-assertive.item-complex>.item-content,.item-complex.activated .item-content.item-assertive.item-complex>.item-content,.item-complex.active .item-content.item-assertive.item-complex>.item-content,.item.activated.item-assertive.item-complex>.item-content,.item.active.item-assertive.item-complex>.item-content{border-color:#e42112;background-color:#e42112}.item .item-content.activated.item-balanced,.item .item-content.active.item-balanced,.item-complex.activated .item-content.item-balanced,.item-complex.active .item-content.item-balanced,.item.activated.item-balanced,.item.active.item-balanced{border-color:#28a54c;background-color:#28a54c}.item .item-content.activated.item-balanced.item-complex>.item-content,.item .item-content.active.item-balanced.item-complex>.item-content,.item-complex.activated .item-content.item-balanced.item-complex>.item-content,.item-complex.active .item-content.item-balanced.item-complex>.item-content,.item.activated.item-balanced.item-complex>.item-content,.item.active.item-balanced.item-complex>.item-content{border-color:#28a54c;background-color:#28a54c}.item .item-content.activated.item-energized,.item .item-content.active.item-energized,.item-complex.activated .item-content.item-energized,.item-complex.active .item-content.item-energized,.item.activated.item-energized,.item.active.item-energized{border-color:#e6b500;background-color:#e6b500}.item .item-content.activated.item-energized.item-complex>.item-content,.item .item-content.active.item-energized.item-complex>.item-content,.item-complex.activated .item-content.item-energized.item-complex>.item-content,.item-complex.active .item-content.item-energized.item-complex>.item-content,.item.activated.item-energized.item-complex>.item-content,.item.active.item-energized.item-complex>.item-content{border-color:#e6b500;background-color:#e6b500}.item .item-content.activated.item-royal,.item .item-content.active.item-royal,.item-complex.activated .item-content.item-royal,.item-complex.active .item-content.item-royal,.item.activated.item-royal,.item.active.item-royal{border-color:#6b46e5;background-color:#6b46e5}.item .item-content.activated.item-royal.item-complex>.item-content,.item .item-content.active.item-royal.item-complex>.item-content,.item-complex.activated .item-content.item-royal.item-complex>.item-content,.item-complex.active .item-content.item-royal.item-complex>.item-content,.item.activated.item-royal.item-complex>.item-content,.item.active.item-royal.item-complex>.item-content{border-color:#6b46e5;background-color:#6b46e5}.item .item-content.activated.item-dark,.item .item-content.active.item-dark,.item-complex.activated .item-content.item-dark,.item-complex.active .item-content.item-dark,.item.activated.item-dark,.item.active.item-dark{border-color:#000;background-color:#262626}.item .item-content.activated.item-dark.item-complex>.item-content,.item .item-content.active.item-dark.item-complex>.item-content,.item-complex.activated .item-content.item-dark.item-complex>.item-content,.item-complex.active .item-content.item-dark.item-complex>.item-content,.item.activated.item-dark.item-complex>.item-content,.item.active.item-dark.item-complex>.item-content{border-color:#000;background-color:#262626}.item,.item h1,.item h2,.item h3,.item h4,.item h5,.item h6,.item p,.item-content,.item-content h1,.item-content h2,.item-content h3,.item-content h4,.item-content h5,.item-content h6,.item-content p{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}a.item{color:inherit;text-decoration:none}a.item:focus,a.item:hover{text-decoration:none}.item-complex,a.item.item-complex,button.item.item-complex{padding:0}.item-complex .item-content,.item-radio .item-content{position:relative;z-index:2;padding:16px 49px 16px 16px;border:none;background-color:#fff}a.item-content{display:block;color:inherit;text-decoration:none}.item-body h1,.item-body h2,.item-body h3,.item-body h4,.item-body h5,.item-body h6,.item-body p,.item-complex.item-text-wrap .item-content,.item-text-wrap,.item-text-wrap .item,.item-text-wrap .item-content,.item-text-wrap h1,.item-text-wrap h2,.item-text-wrap h3,.item-text-wrap h4,.item-text-wrap h5,.item-text-wrap h6,.item-text-wrap p{overflow:visible;white-space:normal}.item-complex.item-text-wrap,.item-complex.item-text-wrap h1,.item-complex.item-text-wrap h2,.item-complex.item-text-wrap h3,.item-complex.item-text-wrap h4,.item-complex.item-text-wrap h5,.item-complex.item-text-wrap h6,.item-complex.item-text-wrap p{overflow:visible;white-space:normal}.item-complex.item-light>.item-content{border-color:#ddd;background-color:#fff;color:#444}.item-complex.item-light>.item-content.active,.item-complex.item-light>.item-content:active{border-color:#ccc;background-color:#fafafa}.item-complex.item-light>.item-content.active.item-complex>.item-content,.item-complex.item-light>.item-content:active.item-complex>.item-content{border-color:#ccc;background-color:#fafafa}.item-complex.item-stable>.item-content{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.item-complex.item-stable>.item-content.active,.item-complex.item-stable>.item-content:active{border-color:#a2a2a2;background-color:#e5e5e5}.item-complex.item-stable>.item-content.active.item-complex>.item-content,.item-complex.item-stable>.item-content:active.item-complex>.item-content{border-color:#a2a2a2;background-color:#e5e5e5}.item-complex.item-positive>.item-content{border-color:#0c60ee;background-color:#387ef5;color:#fff}.item-complex.item-positive>.item-content.active,.item-complex.item-positive>.item-content:active{border-color:#0c60ee;background-color:#0c60ee}.item-complex.item-positive>.item-content.active.item-complex>.item-content,.item-complex.item-positive>.item-content:active.item-complex>.item-content{border-color:#0c60ee;background-color:#0c60ee}.item-complex.item-calm>.item-content{border-color:#0a9dc7;background-color:#11c1f3;color:#fff}.item-complex.item-calm>.item-content.active,.item-complex.item-calm>.item-content:active{border-color:#0a9dc7;background-color:#0a9dc7}.item-complex.item-calm>.item-content.active.item-complex>.item-content,.item-complex.item-calm>.item-content:active.item-complex>.item-content{border-color:#0a9dc7;background-color:#0a9dc7}.item-complex.item-assertive>.item-content{border-color:#e42112;background-color:#ef473a;color:#fff}.item-complex.item-assertive>.item-content.active,.item-complex.item-assertive>.item-content:active{border-color:#e42112;background-color:#e42112}.item-complex.item-assertive>.item-content.active.item-complex>.item-content,.item-complex.item-assertive>.item-content:active.item-complex>.item-content{border-color:#e42112;background-color:#e42112}.item-complex.item-balanced>.item-content{border-color:#28a54c;background-color:#33cd5f;color:#fff}.item-complex.item-balanced>.item-content.active,.item-complex.item-balanced>.item-content:active{border-color:#28a54c;background-color:#28a54c}.item-complex.item-balanced>.item-content.active.item-complex>.item-content,.item-complex.item-balanced>.item-content:active.item-complex>.item-content{border-color:#28a54c;background-color:#28a54c}.item-complex.item-energized>.item-content{border-color:#e6b500;background-color:#ffc900;color:#fff}.item-complex.item-energized>.item-content.active,.item-complex.item-energized>.item-content:active{border-color:#e6b500;background-color:#e6b500}.item-complex.item-energized>.item-content.active.item-complex>.item-content,.item-complex.item-energized>.item-content:active.item-complex>.item-content{border-color:#e6b500;background-color:#e6b500}.item-complex.item-royal>.item-content{border-color:#6b46e5;background-color:#886aea;color:#fff}.item-complex.item-royal>.item-content.active,.item-complex.item-royal>.item-content:active{border-color:#6b46e5;background-color:#6b46e5}.item-complex.item-royal>.item-content.active.item-complex>.item-content,.item-complex.item-royal>.item-content:active.item-complex>.item-content{border-color:#6b46e5;background-color:#6b46e5}.item-complex.item-dark>.item-content{border-color:#111;background-color:#444;color:#fff}.item-complex.item-dark>.item-content.active,.item-complex.item-dark>.item-content:active{border-color:#000;background-color:#262626}.item-complex.item-dark>.item-content.active.item-complex>.item-content,.item-complex.item-dark>.item-content:active.item-complex>.item-content{border-color:#000;background-color:#262626}#menu .footer .item-icon-left .icon-help,#menu .footer .item-icon-right .icon-help,.item-icon-left #menu .footer .icon-help,.item-icon-left .icon,.item-icon-left .icon-alert,.item-icon-left .icon-help,.item-icon-right #menu .footer .icon-help,.item-icon-right .icon,.item-icon-right .icon-alert,.item-icon-right .icon-help{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%;font-size:32px}#menu .footer .item-icon-left .icon-help:before,#menu .footer .item-icon-right .icon-help:before,.item-icon-left #menu .footer .icon-help:before,.item-icon-left .icon-alert:before,.item-icon-left .icon-help:before,.item-icon-left .icon:before,.item-icon-right #menu .footer .icon-help:before,.item-icon-right .icon-alert:before,.item-icon-right .icon-help:before,.item-icon-right .icon:before{display:block;width:32px;text-align:center}.item .fill-icon{min-width:30px;min-height:30px;font-size:28px}.item-icon-left{padding-left:54px}#menu .footer .item-icon-left .icon-help,.item-icon-left #menu .footer .icon-help,.item-icon-left .icon,.item-icon-left .icon-alert,.item-icon-left .icon-help{left:11px}.item-complex.item-icon-left{padding-left:0}.item-complex.item-icon-left .item-content{padding-left:54px}.item-icon-right{padding-right:54px}#menu .footer .item-icon-right .icon-help,.item-icon-right #menu .footer .icon-help,.item-icon-right .icon,.item-icon-right .icon-alert,.item-icon-right .icon-help{right:11px}.item-complex.item-icon-right{padding-right:0}.item-complex.item-icon-right .item-content{padding-right:54px}#menu .footer .item-icon-left.item-icon-right .icon-help:first-child,.item-icon-left.item-icon-right #menu .footer .icon-help:first-child,.item-icon-left.item-icon-right .icon-alert:first-child,.item-icon-left.item-icon-right .icon-help:first-child,.item-icon-left.item-icon-right .icon:first-child{right:auto}#menu .footer .item-icon-left .item-delete .icon-help,#menu .footer .item-icon-left.item-icon-right .icon-help:last-child,.item-icon-left .item-delete #menu .footer .icon-help,.item-icon-left .item-delete .icon,.item-icon-left .item-delete .icon-alert,.item-icon-left .item-delete .icon-help,.item-icon-left.item-icon-right #menu .footer .icon-help:last-child,.item-icon-left.item-icon-right .icon-alert:last-child,.item-icon-left.item-icon-right .icon-help:last-child,.item-icon-left.item-icon-right .icon:last-child{left:auto}.item-icon-left .icon-accessory,.item-icon-right .icon-accessory{color:#ccc;font-size:16px}.item-icon-left .icon-accessory{left:3px}.item-icon-right .icon-accessory{right:3px}.item-button-left{padding-left:72px}.item-button-left .item-content>.button,.item-button-left>.button{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:8px;left:11px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}#menu .footer .item-button-left .item-content>.button .icon-help:before,#menu .footer .item-button-left>.button .icon-help:before,.item-button-left .item-content>.button #menu .footer .icon-help:before,.item-button-left .item-content>.button .icon-alert:before,.item-button-left .item-content>.button .icon-help:before,.item-button-left .item-content>.button .icon:before,.item-button-left>.button #menu .footer .icon-help:before,.item-button-left>.button .icon-alert:before,.item-button-left>.button .icon-help:before,.item-button-left>.button .icon:before{position:relative;left:auto;width:auto;line-height:31px}.item-button-left .item-content>.button>.button,.item-button-left>.button>.button{margin:0 2px;min-height:34px;font-size:18px;line-height:32px}.item-button-right,a.item.item-button-right,button.item.item-button-right{padding-right:80px}.item-button-right .item-content>.button,.item-button-right .item-content>.buttons,.item-button-right>.button,.item-button-right>.buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:8px;right:16px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}#menu .footer .item-button-right .item-content>.button .icon-help:before,#menu .footer .item-button-right .item-content>.buttons .icon-help:before,#menu .footer .item-button-right>.button .icon-help:before,#menu .footer .item-button-right>.buttons .icon-help:before,.item-button-right .item-content>.button #menu .footer .icon-help:before,.item-button-right .item-content>.button .icon-alert:before,.item-button-right .item-content>.button .icon-help:before,.item-button-right .item-content>.button .icon:before,.item-button-right .item-content>.buttons #menu .footer .icon-help:before,.item-button-right .item-content>.buttons .icon-alert:before,.item-button-right .item-content>.buttons .icon-help:before,.item-button-right .item-content>.buttons .icon:before,.item-button-right>.button #menu .footer .icon-help:before,.item-button-right>.button .icon-alert:before,.item-button-right>.button .icon-help:before,.item-button-right>.button .icon:before,.item-button-right>.buttons #menu .footer .icon-help:before,.item-button-right>.buttons .icon-alert:before,.item-button-right>.buttons .icon-help:before,.item-button-right>.buttons .icon:before{position:relative;left:auto;width:auto;line-height:31px}.item-button-right .item-content>.button>.button,.item-button-right .item-content>.buttons>.button,.item-button-right>.button>.button,.item-button-right>.buttons>.button{margin:0 2px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}.item-button-left.item-button-right .button:first-child{right:auto}.item-button-left.item-button-right .button:last-child{left:auto}.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{padding-left:72px;min-height:72px}.item-avatar .item-content .item-image,.item-avatar .item-content>img:first-child,.item-avatar .item-image,.item-avatar-left .item-content .item-image,.item-avatar-left .item-content>img:first-child,.item-avatar-left .item-image,.item-avatar-left>img:first-child,.item-avatar>img:first-child{position:absolute;top:16px;left:16px;max-width:40px;max-height:40px;width:100%;height:100%;border-radius:50%}.item-avatar-right,.item-avatar-right .item-content{padding-right:72px;min-height:72px}.item-avatar-right .item-content .item-image,.item-avatar-right .item-content>img:first-child,.item-avatar-right .item-image,.item-avatar-right>img:first-child{position:absolute;top:16px;right:16px;max-width:40px;max-height:40px;width:100%;height:100%;border-radius:50%}.item-thumbnail-left,.item-thumbnail-left .item-content{padding-top:8px;padding-left:106px;min-height:100px}.item-thumbnail-left .item-content .item-image,.item-thumbnail-left .item-content>img:first-child,.item-thumbnail-left .item-image,.item-thumbnail-left>img:first-child{position:absolute;top:10px;left:10px;max-width:80px;max-height:80px;width:100%;height:100%}.item-avatar-left.item-complex,.item-avatar.item-complex,.item-thumbnail-left.item-complex{padding-top:0;padding-left:0}.item-thumbnail-right,.item-thumbnail-right .item-content{padding-top:8px;padding-right:106px;min-height:100px}.item-thumbnail-right .item-content .item-image,.item-thumbnail-right .item-content>img:first-child,.item-thumbnail-right .item-image,.item-thumbnail-right>img:first-child{position:absolute;top:10px;right:10px;max-width:80px;max-height:80px;width:100%;height:100%}.item-avatar-right.item-complex,.item-thumbnail-right.item-complex{padding-top:0;padding-right:0}.item-image{padding:0;text-align:center}.item-image .list-img,.item-image img:first-child{width:100%;vertical-align:middle}.item-body{overflow:auto;padding:16px;text-overflow:inherit;white-space:normal}.item-body h1,.item-body h2,.item-body h3,.item-body h4,.item-body h5,.item-body h6,.item-body p{margin-top:16px;margin-bottom:16px}.item-divider{padding-top:8px;padding-bottom:8px;min-height:30px;background-color:#f5f5f5;color:#222;font-weight:500}.item-divider-ios,.platform-ios .item-divider-platform{padding-top:26px;text-transform:uppercase;font-weight:300;font-size:13px;background-color:#efeff4;color:#555}.item-divider-android,.platform-android .item-divider-platform{font-weight:300;font-size:13px}.item-note{float:right;color:#aaa;font-size:14px}.item-left-editable .item-content,.item-right-editable .item-content{-webkit-transition-duration:250ms;transition-duration:250ms;-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;transition-property:transform}.item-left-editing.item-left-editable .item-content,.list-left-editing .item-left-editable .item-content{-webkit-transform:translate3d(50px,0,0);transform:translate3d(50px,0,0)}.item-remove-animate.ng-leave{-webkit-transition-duration:.3s;transition-duration:.3s}.item-remove-animate.ng-leave .item-content,.item-remove-animate.ng-leave:last-of-type{-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;-webkit-transition-property:all;transition-property:all}.item-remove-animate.ng-leave.ng-leave-active .item-content{opacity:0;-webkit-transform:translate3d(-100%,0,0)!important;transform:translate3d(-100%,0,0)!important}.item-remove-animate.ng-leave.ng-leave-active:last-of-type{opacity:0}.item-remove-animate.ng-leave.ng-leave-active~ion-item:not(.ng-leave){-webkit-transform:translate3d(0,-webkit-calc(-100% + 1px),0);transform:translate3d(0,calc(-100% + 1px),0);-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-timing-function:cubic-bezier(.25,.81,.24,1);transition-timing-function:cubic-bezier(.25,.81,.24,1);-webkit-transition-property:all;transition-property:all}.item-left-edit{-webkit-transition:all ease-in-out 125ms;transition:all ease-in-out 125ms;position:absolute;top:0;left:0;z-index:0;width:50px;height:100%;line-height:100%;display:none;opacity:0;-webkit-transform:translate3d(-21px,0,0);transform:translate3d(-21px,0,0)}.item-left-edit .button{height:100%}#menu .footer .item-left-edit .button.icon-help,.item-left-edit #menu .footer .button.icon-help,.item-left-edit .button.icon,.item-left-edit .button.icon-alert,.item-left-edit .button.icon-help{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%}.item-left-edit.visible{display:block}.item-left-edit.visible.active{opacity:1;-webkit-transform:translate3d(8px,0,0);transform:translate3d(8px,0,0)}.list-left-editing .item-left-edit{-webkit-transition-delay:125ms;transition-delay:125ms}#menu .footer .item-delete .button.icon-help,.item-delete #menu .footer .button.icon-help,.item-delete .button.icon,.item-delete .button.icon-alert,.item-delete .button.icon-help{color:#ef473a;font-size:24px}#menu .footer .item-delete .button.icon-help:hover,.item-delete #menu .footer .button.icon-help:hover,.item-delete .button.icon-alert:hover,.item-delete .button.icon-help:hover,.item-delete .button.icon:hover{opacity:.7}.item-right-edit{-webkit-transition:all ease-in-out 250ms;transition:all ease-in-out 250ms;position:absolute;top:0;right:0;z-index:3;width:75px;height:100%;background:inherit;padding-left:20px;display:block;opacity:0;-webkit-transform:translate3d(75px,0,0);transform:translate3d(75px,0,0)}.item-right-edit .button{min-width:50px;height:100%}#menu .footer .item-right-edit .button.icon-help,.item-right-edit #menu .footer .button.icon-help,.item-right-edit .button.icon,.item-right-edit .button.icon-alert,.item-right-edit .button.icon-help{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%;font-size:32px}.item-right-edit.visible{display:block}.item-right-edit.visible.active{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}#menu .footer .item-reorder .button.icon-help,.item-reorder #menu .footer .button.icon-help,.item-reorder .button.icon,.item-reorder .button.icon-alert,.item-reorder .button.icon-help{color:#444;font-size:32px}.item-reordering{position:absolute;left:0;top:0;z-index:9;width:100%;box-shadow:0 0 10px 0 #aaa}.item-reordering .item-reorder{z-index:9}.item-placeholder{opacity:.7}.item-options{position:absolute;top:0;right:0;z-index:1;height:100%}.item-options .button{height:100%;border:none;border-radius:0;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}.item-options .button:before{margin:0 auto}.list{position:relative;padding-top:1px;padding-bottom:1px;padding-left:0;margin-bottom:20px}.list:last-child{margin-bottom:0}.list:last-child.card{margin-bottom:40px}.list-header{margin-top:20px;padding:5px 15px;background-color:transparent;color:#222;font-weight:700}.card.list .list-item{padding-right:1px;padding-left:1px}.card,.list-inset{overflow:hidden;margin:20px 10px;border-radius:2px;background-color:#fff}.card{padding-top:1px;padding-bottom:1px;box-shadow:0 1px 3px rgba(0,0,0,.3)}.card .item{border-left:0;border-right:0}.card .item:first-child{border-top:0}.card .item:last-child{border-bottom:0}.item.large-button-bar .card,.item.large-button-bar .list-inset,.padding .card,.padding .list-inset{margin-left:0;margin-right:0}.card .item:first-child,.item.large-button-bar>.list .item:first-child,.list-inset .item:first-child,.padding>.list .item:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.card .item:first-child .item-content,.item.large-button-bar>.list .item:first-child .item-content,.list-inset .item:first-child .item-content,.padding>.list .item:first-child .item-content{border-top-left-radius:2px;border-top-right-radius:2px}.card .item:last-child,.item.large-button-bar>.list .item:last-child,.list-inset .item:last-child,.padding>.list .item:last-child{border-bottom-right-radius:2px;border-bottom-left-radius:2px}.card .item:last-child .item-content,.item.large-button-bar>.list .item:last-child .item-content,.list-inset .item:last-child .item-content,.padding>.list .item:last-child .item-content{border-bottom-right-radius:2px;border-bottom-left-radius:2px}.card .item:last-child,.list-inset .item:last-child{margin-bottom:-1px}.card .item,.item.large-button-bar>.list .item,.list-inset .item,.padding-horizontal>.list .item,.padding>.list .item{margin-right:0;margin-left:0}.card .item.item-input input,.item.large-button-bar>.list .item.item-input input,.list-inset .item.item-input input,.padding-horizontal>.list .item.item-input input,.padding>.list .item.item-input input{padding-right:44px}.padding-left>.list .item{margin-left:0}.padding-right>.list .item,.popover-share .bar-footer .button-close>.list .item{margin-right:0}.badge{background-color:transparent;color:#aaa;z-index:1;display:inline-block;padding:3px 8px;min-width:10px;border-radius:10px;vertical-align:baseline;text-align:center;white-space:nowrap;font-weight:700;font-size:14px;line-height:16px}.badge:empty{display:none}.badge.badge-light,.tabs .tab-item .badge.badge-light{background-color:#fff;color:#444}.badge.badge-stable,.tabs .tab-item .badge.badge-stable{background-color:#f8f8f8;color:#444}.badge.badge-positive,.tabs .tab-item .badge.badge-positive{background-color:#387ef5;color:#fff}.badge.badge-calm,.tabs .tab-item .badge.badge-calm{background-color:#11c1f3;color:#fff}.badge.badge-assertive,.badge.badge-editable:hover,.tabs .tab-item .badge.badge-assertive,.tabs .tab-item .badge.badge-editable:hover{background-color:#ef473a;color:#fff}.badge.badge-balanced,.tabs .tab-item .badge.badge-balanced{background-color:#33cd5f;color:#fff}.badge.badge-energized,.tabs .tab-item .badge.badge-energized{background-color:#ffc900;color:#fff}.badge.badge-royal,.tabs .tab-item .badge.badge-royal{background-color:#886aea;color:#fff}.badge.badge-dark,.tabs .tab-item .badge.badge-dark{background-color:#444;color:#fff}.button .badge{position:relative;top:-1px}.slider{position:relative;visibility:hidden;overflow:hidden}.slider-slides{position:relative;height:100%}.slider-slide{position:relative;display:block;float:left;width:100%;height:100%;vertical-align:top}.slider-slide-image>img{width:100%}.slider-pager{position:absolute;bottom:20px;z-index:1;width:100%;height:15px;text-align:center}.slider-pager .slider-pager-page{display:inline-block;margin:0 3px;width:15px;color:#000;text-decoration:none;opacity:.3}.slider-pager .slider-pager-page.active{-webkit-transition:opacity .4s ease-in;transition:opacity .4s ease-in;opacity:1}.slider-pager-page.ng-animate,.slider-pager-page.ng-enter,.slider-pager-page.ng-leave,.slider-slide.ng-animate,.slider-slide.ng-enter,.slider-slide.ng-leave{-webkit-transition:none!important;transition:none!important}.slider-pager-page.ng-animate,.slider-slide.ng-animate{-webkit-animation:none 0s;animation:none 0s}.swiper-container{margin:0 auto;position:relative;overflow:hidden;z-index:1}.swiper-container-no-flexbox .swiper-slide{float:left}.swiper-container-vertical>.swiper-wrapper{-webkit-box-orient:vertical;-moz-box-orient:vertical;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.swiper-wrapper{position:relative;width:100%;height:100%;z-index:1;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.swiper-container-android .swiper-slide,.swiper-wrapper{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate(0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.swiper-container-multirow>.swiper-wrapper{-webkit-box-lines:multiple;-moz-box-lines:multiple;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap}.swiper-container-free-mode>.swiper-wrapper{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out;margin:0 auto}.swiper-slide{display:block;-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;width:100%;height:100%;position:relative}.swiper-container-autoheight,.swiper-container-autoheight .swiper-slide{height:auto}.swiper-container-autoheight .swiper-wrapper{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start;-webkit-transition-property:-webkit-transform,height;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform,height}.swiper-container .swiper-notification{position:absolute;left:0;top:0;pointer-events:none;opacity:0;z-index:-1000}.swiper-wp8-horizontal{-ms-touch-action:pan-y;touch-action:pan-y}.swiper-wp8-vertical{-ms-touch-action:pan-x;touch-action:pan-x}.swiper-button-next,.swiper-button-prev{position:absolute;top:50%;width:27px;height:44px;margin-top:-22px;z-index:10;cursor:pointer;-moz-background-size:27px 44px;-webkit-background-size:27px 44px;background-size:27px 44px;background-position:center;background-repeat:no-repeat}.swiper-button-next.swiper-button-disabled,.swiper-button-prev.swiper-button-disabled{opacity:.35;cursor:auto;pointer-events:none}.swiper-button-prev,.swiper-container-rtl .swiper-button-next{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");left:10px;right:auto}.swiper-button-prev.swiper-button-black,.swiper-container-rtl .swiper-button-next.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-prev.swiper-button-white,.swiper-container-rtl .swiper-button-next.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next,.swiper-container-rtl .swiper-button-prev{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");right:10px;left:auto}.swiper-button-next.swiper-button-black,.swiper-container-rtl .swiper-button-prev.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next.swiper-button-white,.swiper-container-rtl .swiper-button-prev.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-pagination{position:absolute;text-align:center;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;transition:.3s;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0);z-index:10}.swiper-pagination.swiper-pagination-hidden{opacity:0}.swiper-pagination-bullet{width:8px;height:8px;display:inline-block;border-radius:100%;background:#000;opacity:.2}button.swiper-pagination-bullet{border:none;margin:0;padding:0;box-shadow:none;-moz-appearance:none;-ms-appearance:none;-webkit-appearance:none;appearance:none}.swiper-pagination-clickable .swiper-pagination-bullet{cursor:pointer}.swiper-pagination-white .swiper-pagination-bullet{background:#fff}.swiper-pagination-bullet-active{opacity:1}.swiper-pagination-white .swiper-pagination-bullet-active{background:#fff}.swiper-pagination-black .swiper-pagination-bullet-active{background:#000}.swiper-container-vertical>.swiper-pagination{right:10px;top:50%;-webkit-transform:translate3d(0,-50%,0);-moz-transform:translate3d(0,-50%,0);-o-transform:translate(0,-50%);-ms-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.swiper-container-vertical>.swiper-pagination .swiper-pagination-bullet{margin:5px 0;display:block}.swiper-container-horizontal>.swiper-pagination{bottom:10px;left:0;width:100%}.swiper-container-horizontal>.swiper-pagination .swiper-pagination-bullet{margin:0 5px}.swiper-container-3d{-webkit-perspective:1200px;-moz-perspective:1200px;-o-perspective:1200px;perspective:1200px}.swiper-container-3d .swiper-cube-shadow,.swiper-container-3d .swiper-slide,.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top,.swiper-container-3d .swiper-wrapper{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;transform-style:preserve-3d}.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10}.swiper-container-3d .swiper-slide-shadow-left{background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(right,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(right,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(right,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to left,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-right{background-image:-webkit-gradient(linear,right top,left top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(left,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(left,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to right,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-top{background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(bottom,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(bottom,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(bottom,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to top,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-bottom{background-image:-webkit-gradient(linear,left bottom,left top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(top,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(top,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(top,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to bottom,rgba(0,0,0,.5),transparent)}.swiper-container-coverflow .swiper-wrapper{-ms-perspective:1200px}.swiper-container-fade.swiper-container-free-mode .swiper-slide{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out}.swiper-container-fade .swiper-slide{pointer-events:none}.swiper-container-fade .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-fade .swiper-slide-active,.swiper-container-fade .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-container-cube{overflow:visible}.swiper-container-cube .swiper-slide{pointer-events:none;visibility:hidden;-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;width:100%;height:100%;z-index:1}.swiper-container-cube.swiper-container-rtl .swiper-slide{-webkit-transform-origin:100% 0;-moz-transform-origin:100% 0;-ms-transform-origin:100% 0;transform-origin:100% 0}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-next,.swiper-container-cube .swiper-slide-next+.swiper-slide,.swiper-container-cube .swiper-slide-prev{pointer-events:auto;visibility:visible}.swiper-container-cube .swiper-slide-shadow-bottom,.swiper-container-cube .swiper-slide-shadow-left,.swiper-container-cube .swiper-slide-shadow-right,.swiper-container-cube .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.swiper-container-cube .swiper-cube-shadow{position:absolute;left:0;bottom:0;width:100%;height:100%;background:#000;opacity:.6;-webkit-filter:blur(50px);filter:blur(50px);z-index:0}.swiper-scrollbar{border-radius:10px;position:relative;-ms-touch-action:none;background:rgba(0,0,0,.1)}.swiper-container-horizontal>.swiper-scrollbar{position:absolute;left:1%;bottom:3px;z-index:50;height:5px;width:98%}.swiper-container-vertical>.swiper-scrollbar{position:absolute;right:3px;top:1%;z-index:50;width:5px;height:98%}.swiper-scrollbar-drag{height:100%;width:100%;position:relative;background:rgba(0,0,0,.5);border-radius:10px;left:0;top:0}.swiper-scrollbar-cursor-drag{cursor:move}.swiper-lazy-preloader{width:42px;height:42px;position:absolute;left:50%;top:50%;margin-left:-21px;margin-top:-21px;z-index:10;-webkit-transform-origin:50%;-moz-transform-origin:50%;transform-origin:50%;-webkit-animation:swiper-preloader-spin 1s steps(12,end) infinite;-moz-animation:swiper-preloader-spin 1s steps(12,end) infinite;animation:swiper-preloader-spin 1s steps(12,end) infinite}.swiper-lazy-preloader:after{display:block;content:"";width:100%;height:100%;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");background-position:50%;-webkit-background-size:100%;background-size:100%;background-repeat:no-repeat}.swiper-lazy-preloader-white:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}@-webkit-keyframes swiper-preloader-spin{100%{-webkit-transform:rotate(360deg)}}@keyframes swiper-preloader-spin{100%{transform:rotate(360deg)}}ion-slides{width:100%;height:100%;display:block}.slide-zoom{display:block;width:100%;text-align:center}.swiper-container{width:100%;height:100%;padding:0;overflow:hidden}.swiper-wrapper{position:absolute;left:0;top:0;width:100%;height:100%;padding:0}.swiper-slide{width:100%;height:100%;box-sizing:border-box}.swiper-slide img{width:auto;height:auto;max-width:100%;max-height:100%}.scroll-refresher{position:absolute;top:-60px;right:0;left:0;overflow:hidden;margin:auto;height:60px}.scroll-refresher .ionic-refresher-content{position:absolute;bottom:15px;left:0;width:100%;color:#666;text-align:center;font-size:30px}.scroll-refresher .ionic-refresher-content .text-pulling,.scroll-refresher .ionic-refresher-content .text-refreshing{font-size:16px;line-height:16px}.scroll-refresher .ionic-refresher-content.ionic-refresher-with-text{bottom:10px}.scroll-refresher .icon-pulling,.scroll-refresher .icon-refreshing{width:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.scroll-refresher .icon-pulling{-webkit-animation-name:refresh-spin-back;animation-name:refresh-spin-back;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:none;animation-fill-mode:none;-webkit-transform:translate3d(0,0,0) rotate(0);transform:translate3d(0,0,0) rotate(0)}.scroll-refresher .icon-refreshing,.scroll-refresher .text-refreshing{display:none}.scroll-refresher .icon-refreshing{-webkit-animation-duration:1.5s;animation-duration:1.5s}.scroll-refresher.active .icon-pulling:not(.pulling-rotation-disabled){-webkit-animation-name:refresh-spin;animation-name:refresh-spin;-webkit-transform:translate3d(0,0,0) rotate(-180deg);transform:translate3d(0,0,0) rotate(-180deg)}.scroll-refresher.active.refreshing{-webkit-transition:-webkit-transform .2s;transition:-webkit-transform .2s;-webkit-transition:transform .2s;transition:transform .2s;-webkit-transform:scale(1,1);transform:scale(1,1)}.scroll-refresher.active.refreshing .icon-pulling,.scroll-refresher.active.refreshing .text-pulling{display:none}.scroll-refresher.active.refreshing .icon-refreshing,.scroll-refresher.active.refreshing .text-refreshing{display:block}.scroll-refresher.active.refreshing.refreshing-tail{-webkit-transform:scale(0,0);transform:scale(0,0)}.overflow-scroll>.scroll{-webkit-overflow-scrolling:touch;width:100%}.overflow-scroll>.scroll.overscroll{position:fixed;right:0;left:0}.overflow-scroll.item.large-button-bar>.scroll.overscroll,.overflow-scroll.padding>.scroll.overscroll{padding:10px}@-webkit-keyframes refresh-spin{0%{-webkit-transform:translate3d(0,0,0) rotate(0)}100%{-webkit-transform:translate3d(0,0,0) rotate(180deg)}}@keyframes refresh-spin{0%{transform:translate3d(0,0,0) rotate(0)}100%{transform:translate3d(0,0,0) rotate(180deg)}}@-webkit-keyframes refresh-spin-back{0%{-webkit-transform:translate3d(0,0,0) rotate(180deg)}100%{-webkit-transform:translate3d(0,0,0) rotate(0)}}@keyframes refresh-spin-back{0%{transform:translate3d(0,0,0) rotate(180deg)}100%{transform:translate3d(0,0,0) rotate(0)}}.spinner{stroke:#444;fill:#444}.spinner svg{width:28px;height:28px}.spinner.spinner-light{stroke:#fff;fill:#fff}.spinner.spinner-stable{stroke:#f8f8f8;fill:#f8f8f8}.spinner.spinner-positive{stroke:#387ef5;fill:#387ef5}.spinner.spinner-calm{stroke:#11c1f3;fill:#11c1f3}.spinner.spinner-balanced{stroke:#33cd5f;fill:#33cd5f}.spinner.spinner-assertive{stroke:#ef473a;fill:#ef473a}.spinner.spinner-energized{stroke:#ffc900;fill:#ffc900}.spinner.spinner-royal{stroke:#886aea;fill:#886aea}.spinner.spinner-dark{stroke:#444;fill:#444}.spinner-android{stroke:#4b8bf4}.spinner-ios,.spinner-ios-small{stroke:#69717d}.spinner-spiral .stop1{stop-color:#fff;stop-opacity:0}.spinner-spiral.spinner-light .stop1{stop-color:#444}.spinner-spiral.spinner-light .stop2{stop-color:#fff}.spinner-spiral.spinner-stable .stop2{stop-color:#f8f8f8}.spinner-spiral.spinner-positive .stop2{stop-color:#387ef5}.spinner-spiral.spinner-calm .stop2{stop-color:#11c1f3}.spinner-spiral.spinner-balanced .stop2{stop-color:#33cd5f}.spinner-spiral.spinner-assertive .stop2{stop-color:#ef473a}.spinner-spiral.spinner-energized .stop2{stop-color:#ffc900}.spinner-spiral.spinner-royal .stop2{stop-color:#886aea}.spinner-spiral.spinner-dark .stop2{stop-color:#444}form{margin:0 0 1.42857}legend{display:block;margin-bottom:1.42857;padding:0;width:100%;border:1px solid #ddd;color:#444;font-size:21px;line-height:2.85714}legend small{color:#f8f8f8;font-size:1.07143}button,input,label,select,textarea{font-weight:400;font-size:14px;line-height:1.42857}button,input,select,textarea{font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif}.item-input{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:relative;overflow:hidden;padding:6px 0 5px 16px}.item-input input{-webkit-border-radius:0;border-radius:0;-webkit-box-flex:1;-webkit-flex:1 220px;-moz-box-flex:1;-moz-flex:1 220px;-ms-flex:1 220px;flex:1 220px;-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0;padding-right:24px;background-color:transparent}#menu .footer .item-input .button .icon-help,.item-input .button #menu .footer .icon-help,.item-input .button .icon,.item-input .button .icon-alert,.item-input .button .icon-help{-webkit-box-flex:0;-webkit-flex:0 0 24px;-moz-box-flex:0;-moz-flex:0 0 24px;-ms-flex:0 0 24px;flex:0 0 24px;position:static;display:inline-block;height:auto;text-align:center;font-size:16px}.item-input .button-bar{-webkit-border-radius:0;border-radius:0;-webkit-box-flex:1;-webkit-flex:1 0 220px;-moz-box-flex:1;-moz-flex:1 0 220px;-ms-flex:1 0 220px;flex:1 0 220px;-webkit-appearance:none;-moz-appearance:none;appearance:none}#menu .footer .item-input .icon-help,.item-input #menu .footer .icon-help,.item-input .icon,.item-input .icon-alert,.item-input .icon-help{min-width:14px}.platform-windowsphone .item-input input{flex-shrink:1}.item-input-inset{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:relative;overflow:hidden;padding:10.66667px}.item-input-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0;-moz-box-flex:1;-moz-flex:1 0;-ms-flex:1 0;flex:1 0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;-webkit-border-radius:4px;border-radius:4px;padding-right:8px;padding-left:8px;background:#eee}.item-input-inset .item-input-wrapper input{padding-left:4px;height:29px;background:0 0;line-height:18px}.item-input-wrapper~.button{margin-left:10.66667px}.input-label{display:table;padding:7px 10px 7px 0;max-width:200px;width:35%;color:#444;font-size:16px}.placeholder-icon{color:#aaa}.placeholder-icon:first-child{padding-right:6px}.placeholder-icon:last-child{padding-left:6px}.item-stacked-label{display:block;background-color:transparent;box-shadow:none}#menu .footer .item-stacked-label .icon-help,.item-stacked-label #menu .footer .icon-help,.item-stacked-label .icon,.item-stacked-label .icon-alert,.item-stacked-label .icon-help,.item-stacked-label .input-label{display:inline-block;padding:4px 0 0 0;vertical-align:middle}.item-stacked-label input,.item-stacked-label textarea{-webkit-border-radius:2px;border-radius:2px;padding:4px 8px 3px 0;border:none;background-color:#fff}.item-stacked-label input{overflow:hidden;height:46px}.item-select.item-stacked-label select{position:relative;padding:0;max-width:90%;direction:ltr;white-space:pre-wrap;margin:-3px}.item-floating-label{display:block;background-color:transparent;box-shadow:none}.item-floating-label .input-label{position:relative;padding:5px 0 0 0;opacity:0;top:10px;-webkit-transition:opacity .15s ease-in,top .2s linear;transition:opacity .15s ease-in,top .2s linear}.item-floating-label .input-label.has-input{opacity:1;top:0;-webkit-transition:opacity .15s ease-in,top .2s linear;transition:opacity .15s ease-in,top .2s linear}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],textarea{display:block;padding-top:2px;padding-left:0;height:34px;color:#111;vertical-align:middle;font-size:14px;line-height:16px}.platform-android input[type=date],.platform-android input[type=datetime-local],.platform-android input[type=month],.platform-android input[type=time],.platform-android input[type=week],.platform-ios input[type=date],.platform-ios input[type=datetime-local],.platform-ios input[type=month],.platform-ios input[type=time],.platform-ios input[type=week]{padding-top:8px}.item-input input,.item-input textarea{width:100%}textarea{padding-left:0}textarea::-moz-placeholder{color:#aaa}textarea:-ms-input-placeholder{color:#aaa}textarea::-webkit-input-placeholder{color:#aaa;text-indent:-3px}textarea{height:auto}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],textarea{border:0}input[type=checkbox],input[type=radio]{margin:0;line-height:normal}.item-input input[type=button],.item-input input[type=checkbox],.item-input input[type=file],.item-input input[type=image],.item-input input[type=radio],.item-input input[type=reset],.item-input input[type=submit]{width:auto}input[type=file]{line-height:34px}.cloned-text-input+input,.cloned-text-input+textarea,.previous-input-focus{position:absolute!important;left:-9999px;width:200px}input::-moz-placeholder,textarea::-moz-placeholder{color:#aaa}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#aaa}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#aaa;text-indent:0}input[disabled],input[readonly]:not(.cloned-text-input),select[disabled],select[readonly],textarea[disabled],textarea[readonly]:not(.cloned-text-input){background-color:#f8f8f8;cursor:not-allowed}input[type=checkbox][disabled],input[type=checkbox][readonly],input[type=radio][disabled],input[type=radio][readonly]{background-color:transparent}.checkbox{position:relative;display:inline-block;padding:7px 7px;cursor:pointer}.checkbox .checkbox-icon:before,.checkbox input:before{border-color:#ddd}.checkbox input:checked+.checkbox-icon:before,.checkbox input:checked:before{background:#387ef5;border-color:#387ef5}.checkbox-light .checkbox-icon:before,.checkbox-light input:before{border-color:#ddd}.checkbox-light input:checked+.checkbox-icon:before,.checkbox-light input:checked:before{background:#ddd;border-color:#ddd}.checkbox-stable .checkbox-icon:before,.checkbox-stable input:before{border-color:#b2b2b2}.checkbox-stable input:checked+.checkbox-icon:before,.checkbox-stable input:checked:before{background:#b2b2b2;border-color:#b2b2b2}.checkbox-positive .checkbox-icon:before,.checkbox-positive input:before{border-color:#387ef5}.checkbox-positive input:checked+.checkbox-icon:before,.checkbox-positive input:checked:before{background:#387ef5;border-color:#387ef5}.checkbox-calm .checkbox-icon:before,.checkbox-calm input:before{border-color:#11c1f3}.checkbox-calm input:checked+.checkbox-icon:before,.checkbox-calm input:checked:before{background:#11c1f3;border-color:#11c1f3}.checkbox-assertive .checkbox-icon:before,.checkbox-assertive input:before{border-color:#ef473a}.checkbox-assertive input:checked+.checkbox-icon:before,.checkbox-assertive input:checked:before{background:#ef473a;border-color:#ef473a}.checkbox-balanced .checkbox-icon:before,.checkbox-balanced input:before{border-color:#33cd5f}.checkbox-balanced input:checked+.checkbox-icon:before,.checkbox-balanced input:checked:before{background:#33cd5f;border-color:#33cd5f}.checkbox-energized .checkbox-icon:before,.checkbox-energized input:before{border-color:#ffc900}.checkbox-energized input:checked+.checkbox-icon:before,.checkbox-energized input:checked:before{background:#ffc900;border-color:#ffc900}.checkbox-royal .checkbox-icon:before,.checkbox-royal input:before{border-color:#886aea}.checkbox-royal input:checked+.checkbox-icon:before,.checkbox-royal input:checked:before{background:#886aea;border-color:#886aea}.checkbox-dark .checkbox-icon:before,.checkbox-dark input:before{border-color:#444}.checkbox-dark input:checked+.checkbox-icon:before,.checkbox-dark input:checked:before{background:#444;border-color:#444}.checkbox input:disabled+.checkbox-icon:before,.checkbox input:disabled:before{border-color:#ddd}.checkbox input:disabled:checked+.checkbox-icon:before,.checkbox input:disabled:checked:before{background:#ddd}.checkbox.checkbox-input-hidden input{display:none!important}.checkbox input,.checkbox-icon{position:relative;width:28px;height:28px;display:block;border:0;background:0 0;cursor:pointer;-webkit-appearance:none}.checkbox input:before,.checkbox-icon:before{display:table;width:100%;height:100%;border-width:1px;border-style:solid;border-radius:28px;background:#fff;content:' ';-webkit-transition:background-color 20ms ease-in-out;transition:background-color 20ms ease-in-out}.checkbox input:checked:before,input:checked+.checkbox-icon:before{border-width:2px}.checkbox input:after,.checkbox-icon:after{-webkit-transition:opacity 50ms ease-in-out;transition:opacity 50ms ease-in-out;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);position:absolute;top:33%;left:25%;display:table;width:14px;height:6px;border:1px solid #fff;border-top:0;border-right:0;content:' ';opacity:0}.checkbox-square .checkbox-icon:before,.checkbox-square input:before,.platform-android .checkbox-platform .checkbox-icon:before,.platform-android .checkbox-platform input:before{border-radius:2px;width:72%;height:72%;margin-top:14%;margin-left:14%;border-width:2px}.checkbox-square .checkbox-icon:after,.checkbox-square input:after,.platform-android .checkbox-platform .checkbox-icon:after,.platform-android .checkbox-platform input:after{border-width:2px;top:19%;left:25%;width:13px;height:7px}.platform-android .item-checkbox-right .checkbox-square .checkbox-icon::after{top:31%}.grade-c .checkbox input:after,.grade-c .checkbox-icon:after{-webkit-transform:rotate(0);transform:rotate(0);top:3px;left:4px;border:none;color:#fff;content:'\2713';font-weight:700;font-size:20px}.checkbox input:checked:after,input:checked+.checkbox-icon:after{opacity:1}.item-checkbox{padding-left:60px}.item-checkbox.active{box-shadow:none}.item-checkbox .checkbox{position:absolute;top:50%;right:8px;left:8px;z-index:3;margin-top:-21px}.item-checkbox.item-checkbox-right{padding-right:60px;padding-left:16px}.item-checkbox-right .checkbox input,.item-checkbox-right .checkbox-icon{float:right}.item-toggle{pointer-events:none}.toggle{position:relative;display:inline-block;pointer-events:auto;margin:-5px;padding:5px}.toggle input:checked+.track{border-color:#4cd964;background-color:#4cd964}.toggle.dragging .handle{background-color:#f2f2f2!important}.toggle.toggle-light input:checked+.track{border-color:#ddd;background-color:#ddd}.toggle.toggle-stable input:checked+.track{border-color:#b2b2b2;background-color:#b2b2b2}.toggle.toggle-positive input:checked+.track{border-color:#387ef5;background-color:#387ef5}.toggle.toggle-calm input:checked+.track{border-color:#11c1f3;background-color:#11c1f3}.toggle.toggle-assertive input:checked+.track{border-color:#ef473a;background-color:#ef473a}.toggle.toggle-balanced input:checked+.track{border-color:#33cd5f;background-color:#33cd5f}.toggle.toggle-energized input:checked+.track{border-color:#ffc900;background-color:#ffc900}.toggle.toggle-royal input:checked+.track{border-color:#886aea;background-color:#886aea}.toggle.toggle-dark input:checked+.track{border-color:#444;background-color:#444}.toggle input{display:none}.toggle .track{-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:background-color,border;transition-property:background-color,border;display:inline-block;box-sizing:border-box;width:51px;height:31px;border:solid 2px #e6e6e6;border-radius:20px;background-color:#fff;content:' ';cursor:pointer;pointer-events:none}.platform-android4_2 .toggle .track{-webkit-background-clip:padding-box}.toggle .handle{-webkit-transition:.3s cubic-bezier(0,1.1,1,1.1);transition:.3s cubic-bezier(0,1.1,1,1.1);-webkit-transition-property:background-color,transform;transition-property:background-color,transform;position:absolute;display:block;width:27px;height:27px;border-radius:27px;background-color:#fff;top:7px;left:7px;box-shadow:0 2px 7px rgba(0,0,0,.35),0 1px 1px rgba(0,0,0,.15)}.toggle .handle:before{position:absolute;top:-4px;left:-21.5px;padding:18.5px 34px;content:" "}.toggle input:checked+.track .handle{-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0);background-color:#fff}.item-toggle.active{box-shadow:none}.item-toggle,.item-toggle.item-complex .item-content{padding-right:99px}.item-toggle.item-complex{padding-right:0}.item-toggle .toggle{position:absolute;top:10px;right:16px;z-index:3}.toggle input:disabled+.track{opacity:.6}.toggle-small .track{border:0;width:34px;height:15px;background:#9e9e9e}.toggle-small input:checked+.track{background:rgba(0,150,137,.5)}.toggle-small .handle{top:2px;left:4px;width:21px;height:21px;box-shadow:0 2px 5px rgba(0,0,0,.25)}.toggle-small input:checked+.track .handle{-webkit-transform:translate3d(16px,0,0);transform:translate3d(16px,0,0);background:#009689}.toggle-small.item-toggle .toggle{top:19px}.toggle-small .toggle-light input:checked+.track{background-color:rgba(221,221,221,.5)}.toggle-small .toggle-light input:checked+.track .handle{background-color:#ddd}.toggle-small .toggle-stable input:checked+.track{background-color:rgba(178,178,178,.5)}.toggle-small .toggle-stable input:checked+.track .handle{background-color:#b2b2b2}.toggle-small .toggle-positive input:checked+.track{background-color:rgba(56,126,245,.5)}.toggle-small .toggle-positive input:checked+.track .handle{background-color:#387ef5}.toggle-small .toggle-calm input:checked+.track{background-color:rgba(17,193,243,.5)}.toggle-small .toggle-calm input:checked+.track .handle{background-color:#11c1f3}.toggle-small .toggle-assertive input:checked+.track{background-color:rgba(239,71,58,.5)}.toggle-small .toggle-assertive input:checked+.track .handle{background-color:#ef473a}.toggle-small .toggle-balanced input:checked+.track{background-color:rgba(51,205,95,.5)}.toggle-small .toggle-balanced input:checked+.track .handle{background-color:#33cd5f}.toggle-small .toggle-energized input:checked+.track{background-color:rgba(255,201,0,.5)}.toggle-small .toggle-energized input:checked+.track .handle{background-color:#ffc900}.toggle-small .toggle-royal input:checked+.track{background-color:rgba(136,106,234,.5)}.toggle-small .toggle-royal input:checked+.track .handle{background-color:#886aea}.toggle-small .toggle-dark input:checked+.track{background-color:rgba(68,68,68,.5)}.toggle-small .toggle-dark input:checked+.track .handle{background-color:#444}.item-radio{padding:0}.item-radio:hover{cursor:pointer}.item-radio .item-content{padding-right:64px}.item-radio .radio-icon{position:absolute;top:0;right:0;z-index:3;visibility:hidden;padding:14px;height:100%;font-size:24px}.item-radio input{position:absolute;left:-9999px}.item-radio input:checked+.radio-content .item-content{background:#f7f7f7}.item-radio input:checked+.radio-content .radio-icon{visibility:visible}.range input{display:inline-block;overflow:hidden;margin-top:5px;margin-bottom:5px;padding-right:2px;padding-left:1px;width:auto;height:43px;outline:0;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(0,#ccc),color-stop(100%,#ccc));background:linear-gradient(to right,#ccc 0,#ccc 100%);background-position:center;background-size:99% 2px;background-repeat:no-repeat;-webkit-appearance:none}.range input::-moz-focus-outer{border:0}.range input::-webkit-slider-thumb{position:relative;width:28px;height:28px;border-radius:50%;background-color:#fff;box-shadow:0 0 2px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2);cursor:pointer;-webkit-appearance:none;border:0}.range input::-webkit-slider-thumb:before{position:absolute;top:13px;left:-2001px;width:2000px;height:2px;background:#444;content:' '}.range input::-webkit-slider-thumb:after{position:absolute;top:-15px;left:-15px;padding:30px;content:' '}.range input::-ms-fill-lower{height:2px;background:#444}.range{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;padding:2px 11px}.range.range-light input::-webkit-slider-thumb:before{background:#ddd}.range.range-light input::-ms-fill-lower{background:#ddd}.range.range-stable input::-webkit-slider-thumb:before{background:#b2b2b2}.range.range-stable input::-ms-fill-lower{background:#b2b2b2}.range.range-positive input::-webkit-slider-thumb:before{background:#387ef5}.range.range-positive input::-ms-fill-lower{background:#387ef5}.range.range-calm input::-webkit-slider-thumb:before{background:#11c1f3}.range.range-calm input::-ms-fill-lower{background:#11c1f3}.range.range-balanced input::-webkit-slider-thumb:before{background:#33cd5f}.range.range-balanced input::-ms-fill-lower{background:#33cd5f}.range.range-assertive input::-webkit-slider-thumb:before{background:#ef473a}.range.range-assertive input::-ms-fill-lower{background:#ef473a}.range.range-energized input::-webkit-slider-thumb:before{background:#ffc900}.range.range-energized input::-ms-fill-lower{background:#ffc900}.range.range-royal input::-webkit-slider-thumb:before{background:#886aea}.range.range-royal input::-ms-fill-lower{background:#886aea}.range.range-dark input::-webkit-slider-thumb:before{background:#444}.range.range-dark input::-ms-fill-lower{background:#444}#menu .footer .range .icon-help,.range #menu .footer .icon-help,.range .icon,.range .icon-alert,.range .icon-help{-webkit-box-flex:0;-webkit-flex:0;-moz-box-flex:0;-moz-flex:0;-ms-flex:0;flex:0;display:block;min-width:24px;text-align:center;font-size:24px}.range input{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;margin-right:10px;margin-left:10px}.range-label{-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-moz-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;display:block;white-space:nowrap}.range-label:first-child{padding-left:5px}.range input+.range-label{padding-right:5px;padding-left:0}.platform-windowsphone .range input{height:auto}.item-select{position:relative}.item-select select{-webkit-appearance:none;-moz-appearance:none;appearance:none;position:absolute;top:0;bottom:0;right:0;padding:0 48px 0 16px;max-width:65%;border:none;background:#fff;color:#333;text-indent:.01px;text-overflow:'';white-space:nowrap;font-size:14px;cursor:pointer;direction:rtl}.item-select select::-ms-expand{display:none}.item-select option{direction:ltr}.item-select:after{position:absolute;top:50%;right:16px;margin-top:-3px;width:0;height:0;border-top:5px solid;border-right:5px solid transparent;border-left:5px solid transparent;color:#999;content:"";pointer-events:none}.item-select.item-light select{background:#fff;color:#444}.item-select.item-stable select{background:#f8f8f8;color:#444}.item-select.item-stable .input-label,.item-select.item-stable:after{color:#666}.item-select.item-positive select{background:#387ef5;color:#fff}.item-select.item-positive .input-label,.item-select.item-positive:after{color:#fff}.item-select.item-calm select{background:#11c1f3;color:#fff}.item-select.item-calm .input-label,.item-select.item-calm:after{color:#fff}.item-select.item-assertive select{background:#ef473a;color:#fff}.item-select.item-assertive .input-label,.item-select.item-assertive:after{color:#fff}.item-select.item-balanced select{background:#33cd5f;color:#fff}.item-select.item-balanced .input-label,.item-select.item-balanced:after{color:#fff}.item-select.item-energized select{background:#ffc900;color:#fff}.item-select.item-energized .input-label,.item-select.item-energized:after{color:#fff}.item-select.item-royal select{background:#886aea;color:#fff}.item-select.item-royal .input-label,.item-select.item-royal:after{color:#fff}.item-select.item-dark select{background:#444;color:#fff}.item-select.item-dark .input-label,.item-select.item-dark:after{color:#fff}select[multiple],select[size]{height:auto}progress{display:block;margin:15px auto;width:100%}.button{border-color:transparent;background-color:#f8f8f8;color:#444;position:relative;display:inline-block;margin:0;padding:0 12px;min-width:52px;min-height:47px;border-width:1px;border-style:solid;border-radius:4px;vertical-align:top;text-align:center;text-overflow:ellipsis;font-size:16px;line-height:42px;cursor:pointer}.button:hover{color:#444;text-decoration:none}.button.activated,.button.active{border-color:#a2a2a2;background-color:#e5e5e5}.button:after{position:absolute;top:-6px;right:-6px;bottom:-6px;left:-6px;content:' '}#menu .footer .button .icon-help,.button #menu .footer .icon-help,.button .icon,.button .icon-alert,.button .icon-help{vertical-align:top;pointer-events:none}#menu .footer .button .icon-help:before,#menu .footer .button.icon-help:before,.button #menu .footer .icon-help:before,.button .icon-alert:before,.button .icon-help:before,.button .icon:before,.button.icon-alert:before,.button.icon-help:before,.button.icon-left:before,.button.icon-right:before,.button.icon:before{display:inline-block;padding:0 0 1px 0;vertical-align:inherit;font-size:24px;line-height:41px;pointer-events:none}.button.icon-left:before{float:left;padding-right:.2em;padding-left:0}.button.icon-right:before{float:right;padding-right:0;padding-left:.2em}.button.button-block,.button.button-full{margin-top:10px;margin-bottom:10px}.button.button-light{border-color:transparent;background-color:#fff;color:#444}.button.button-light:hover{color:#444;text-decoration:none}.button.button-light.activated,.button.button-light.active{border-color:#a2a2a2;background-color:#fafafa}.button.button-light.button-clear,.button.button-light.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#ddd}.button.button-light.button-icon{border-color:transparent;background:0 0}.button.button-light.button-outline{border-color:#ddd;background:0 0;color:#ddd}.button.button-light.button-outline.activated,.button.button-light.button-outline.active{background-color:#ddd;box-shadow:none;color:#fff}.button.button-stable{border-color:transparent;background-color:#f8f8f8;color:#444}.button.button-stable:hover{color:#444;text-decoration:none}.button.button-stable.activated,.button.button-stable.active{border-color:#a2a2a2;background-color:#e5e5e5}.button.button-stable.button-clear,.button.button-stable.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#b2b2b2}.button.button-stable.button-icon{border-color:transparent;background:0 0}.button.button-stable.button-outline{border-color:#b2b2b2;background:0 0;color:#b2b2b2}.button.button-stable.button-outline.activated,.button.button-stable.button-outline.active{background-color:#b2b2b2;box-shadow:none;color:#fff}.button.button-positive,.button.button-text{border-color:transparent;background-color:#387ef5;color:#fff}.button.button-positive:hover,.button.button-text:hover{color:#fff;text-decoration:none}.button.activated.button-text,.button.active.button-text,.button.button-positive.activated,.button.button-positive.active{border-color:#a2a2a2;background-color:#0c60ee}.button.button-positive.button-clear,.button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#387ef5}.button.button-icon.button-text,.button.button-positive.button-icon{border-color:transparent;background:0 0}.button.button-outline.button-text,.button.button-positive.button-outline{border-color:#387ef5;background:0 0;color:#387ef5}.button.button-outline.activated.button-text,.button.button-outline.active.button-text,.button.button-positive.button-outline.activated,.button.button-positive.button-outline.active{background-color:#387ef5;box-shadow:none;color:#fff}.button.button-calm{border-color:transparent;background-color:#11c1f3;color:#fff}.button.button-calm:hover{color:#fff;text-decoration:none}.button.button-calm.activated,.button.button-calm.active{border-color:#a2a2a2;background-color:#0a9dc7}.button.button-calm.button-clear,.button.button-calm.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#11c1f3}.button.button-calm.button-icon{border-color:transparent;background:0 0}.button.button-calm.button-outline{border-color:#11c1f3;background:0 0;color:#11c1f3}.button.button-calm.button-outline.activated,.button.button-calm.button-outline.active{background-color:#11c1f3;box-shadow:none;color:#fff}.button.button-assertive{border-color:transparent;background-color:#ef473a;color:#fff}.button.button-assertive:hover{color:#fff;text-decoration:none}.button.button-assertive.activated,.button.button-assertive.active{border-color:#a2a2a2;background-color:#e42112}.button.button-assertive.button-clear,.button.button-assertive.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#ef473a}.button.button-assertive.button-icon{border-color:transparent;background:0 0}.button.button-assertive.button-outline{border-color:#ef473a;background:0 0;color:#ef473a}.button.button-assertive.button-outline.activated,.button.button-assertive.button-outline.active{background-color:#ef473a;box-shadow:none;color:#fff}.button.button-balanced{border-color:transparent;background-color:#33cd5f;color:#fff}.button.button-balanced:hover{color:#fff;text-decoration:none}.button.button-balanced.activated,.button.button-balanced.active{border-color:#a2a2a2;background-color:#28a54c}.button.button-balanced.button-clear,.button.button-balanced.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#33cd5f}.button.button-balanced.button-icon{border-color:transparent;background:0 0}.button.button-balanced.button-outline{border-color:#33cd5f;background:0 0;color:#33cd5f}.button.button-balanced.button-outline.activated,.button.button-balanced.button-outline.active{background-color:#33cd5f;box-shadow:none;color:#fff}.button.button-energized{border-color:transparent;background-color:#ffc900;color:#fff}.button.button-energized:hover{color:#fff;text-decoration:none}.button.button-energized.activated,.button.button-energized.active{border-color:#a2a2a2;background-color:#e6b500}.button.button-energized.button-clear,.button.button-energized.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#ffc900}.button.button-energized.button-icon{border-color:transparent;background:0 0}.button.button-energized.button-outline{border-color:#ffc900;background:0 0;color:#ffc900}.button.button-energized.button-outline.activated,.button.button-energized.button-outline.active{background-color:#ffc900;box-shadow:none;color:#fff}.button.button-royal{border-color:transparent;background-color:#886aea;color:#fff}.button.button-royal:hover{color:#fff;text-decoration:none}.button.button-royal.activated,.button.button-royal.active{border-color:#a2a2a2;background-color:#6b46e5}.button.button-royal.button-clear,.button.button-royal.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#886aea}.button.button-royal.button-icon{border-color:transparent;background:0 0}.button.button-royal.button-outline{border-color:#886aea;background:0 0;color:#886aea}.button.button-royal.button-outline.activated,.button.button-royal.button-outline.active{background-color:#886aea;box-shadow:none;color:#fff}.button.button-dark{border-color:transparent;background-color:#444;color:#fff}.button.button-dark:hover{color:#fff;text-decoration:none}.button.button-dark.activated,.button.button-dark.active{border-color:#a2a2a2;background-color:#262626}.button.button-dark.button-clear,.button.button-dark.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#444}.button.button-dark.button-icon{border-color:transparent;background:0 0}.button.button-dark.button-outline{border-color:#444;background:0 0;color:#444}.button.button-dark.button-outline.activated,.button.button-dark.button-outline.active{background-color:#444;box-shadow:none;color:#fff}.button-small,.button-text.button-small{padding:2px 4px 1px;min-width:28px;min-height:30px;font-size:12px;line-height:26px}#menu .footer .button-small .icon-help:before,#menu .footer .button-small.icon-help:before,.button-small #menu .footer .icon-help:before,.button-small .icon-alert:before,.button-small .icon-help:before,.button-small .icon:before,.button-small.icon-alert:before,.button-small.icon-help:before,.button-small.icon-left:before,.button-small.icon-right:before,.button-small.icon:before{font-size:16px;line-height:19px;margin-top:3px}.button-large{padding:0 16px;min-width:68px;min-height:59px;font-size:20px;line-height:53px}#menu .footer .button-large .icon-help:before,#menu .footer .button-large.icon-help:before,.button-large #menu .footer .icon-help:before,.button-large .icon-alert:before,.button-large .icon-help:before,.button-large .icon:before,.button-large.icon-alert:before,.button-large.icon-help:before,.button-large.icon-left:before,.button-large.icon-right:before,.button-large.icon:before{padding-bottom:2px;font-size:32px;line-height:51px}.button-icon{-webkit-transition:opacity .1s;transition:opacity .1s;padding:0 6px;min-width:initial;border-color:transparent;background:0 0}.button-icon.button.activated,.button-icon.button.active{border-color:transparent;background:0 0;box-shadow:none;opacity:.3}#menu .footer .button-icon .icon-help:before,#menu .footer .button-icon.icon-help:before,.button-icon #menu .footer .icon-help:before,.button-icon .icon-alert:before,.button-icon .icon-help:before,.button-icon .icon:before,.button-icon.icon-alert:before,.button-icon.icon-help:before,.button-icon.icon:before{font-size:32px}.button-clear,.button-text{-webkit-transition:opacity .1s;transition:opacity .1s;padding:0 6px;max-height:42px;border-color:transparent;background:0 0;box-shadow:none}.button-clear.button-clear,.button-text{border-color:transparent;background:0 0;box-shadow:none;color:transparent}.button-clear.button-icon,.button-icon.button-text{border-color:transparent;background:0 0}.activated.button-text,.active.button-text,.button-clear.activated,.button-clear.active{opacity:.3}.button-outline{-webkit-transition:opacity .1s;transition:opacity .1s;background:0 0;box-shadow:none}.button-outline.button-outline{border-color:transparent;background:0 0;color:transparent}.button-outline.button-outline.activated,.button-outline.button-outline.active{background-color:transparent;box-shadow:none;color:#fff}.item.large-button-bar>.button.button-block:first-child,.padding>.button.button-block:first-child{margin-top:0}.button-block{display:block;clear:both}.button-block:after{clear:both}.button-full,.button-full>.button{display:block;margin-right:0;margin-left:0;border-right-width:0;border-left-width:0;border-radius:0}.button-full>button.button,button.button-block,button.button-full,input.button.button-block{width:100%}a.button{text-decoration:none}#menu .footer a.button .icon-help:before,#menu .footer a.button.icon-help:before,a.button #menu .footer .icon-help:before,a.button .icon-alert:before,a.button .icon-help:before,a.button .icon:before,a.button.icon-alert:before,a.button.icon-help:before,a.button.icon-left:before,a.button.icon-right:before,a.button.icon:before{margin-top:2px}.button.disabled,.button[disabled]{opacity:.4;cursor:default!important;pointer-events:none}.button-bar{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;width:100%}.button-bar.button-bar-inline{display:block;width:auto}.button-bar.button-bar-inline:after,.button-bar.button-bar-inline:before{display:table;content:"";line-height:0}.button-bar.button-bar-inline:after{clear:both}.button-bar.button-bar-inline>.button{width:auto;display:inline-block;float:left}.button-bar.bar-light>.button{border-color:#ddd}.button-bar.bar-stable>.button{border-color:#b2b2b2}.button-bar.bar-positive>.button{border-color:#0c60ee}.button-bar.bar-calm>.button{border-color:#0a9dc7}.button-bar.bar-assertive>.button{border-color:#e42112}.button-bar.bar-balanced>.button{border-color:#28a54c}.button-bar.bar-energized>.button{border-color:#e6b500}.button-bar.bar-royal>.button{border-color:#6b46e5}.button-bar.bar-dark>.button{border-color:#111}.button-bar>.button{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;overflow:hidden;padding:0 16px;width:0;border-width:1px 0 1px 1px;border-radius:0;text-align:center;text-overflow:ellipsis;white-space:nowrap}#menu .footer .button-bar>.button .icon-help:before,.button-bar>.button #menu .footer .icon-help:before,.button-bar>.button .icon-alert:before,.button-bar>.button .icon-help:before,.button-bar>.button .icon:before,.button-bar>.button:before{line-height:44px}.button-bar>.button:first-child{border-radius:4px 0 0 4px}.button-bar>.button:last-child{border-right-width:1px;border-radius:0 4px 4px 0}.button-bar>.button:only-child{border-radius:4px}#menu .footer .button-bar>.button-small .icon-help:before,.button-bar>.button-small #menu .footer .icon-help:before,.button-bar>.button-small .icon-alert:before,.button-bar>.button-small .icon-help:before,.button-bar>.button-small .icon:before,.button-bar>.button-small:before{line-height:28px}.row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;padding:5px;width:100%}.row-wrap{-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.row-no-padding{padding:0}.row-no-padding>.col{padding:0}.row+.row{margin-top:-5px;padding-top:0}.col{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;padding:5px;width:100%}.row-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;-moz-align-items:flex-start;align-items:flex-start}.row-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;-moz-align-items:flex-end;align-items:flex-end}.row-center{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}.row-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;-moz-align-items:stretch;align-items:stretch}.row-baseline{-webkit-box-align:baseline;-ms-flex-align:baseline;-webkit-align-items:baseline;-moz-align-items:baseline;align-items:baseline}.col-top{-webkit-align-self:flex-start;-moz-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start}.col-bottom{-webkit-align-self:flex-end;-moz-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end}.col-center{-webkit-align-self:center;-moz-align-self:center;-ms-flex-item-align:center;align-self:center}.col-offset-10{margin-left:10%}.col-offset-20{margin-left:20%}.col-offset-25{margin-left:25%}.col-offset-33,.col-offset-34{margin-left:33.3333%}.col-offset-50{margin-left:50%}.col-offset-66,.col-offset-67{margin-left:66.6666%}.col-offset-75{margin-left:75%}.col-offset-80{margin-left:80%}.col-offset-90{margin-left:90%}.col-10{-webkit-box-flex:0;-webkit-flex:0 0 10%;-moz-box-flex:0;-moz-flex:0 0 10%;-ms-flex:0 0 10%;flex:0 0 10%;max-width:10%}.col-20{-webkit-box-flex:0;-webkit-flex:0 0 20%;-moz-box-flex:0;-moz-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.col-25{-webkit-box-flex:0;-webkit-flex:0 0 25%;-moz-box-flex:0;-moz-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-33,.col-34{-webkit-box-flex:0;-webkit-flex:0 0 33.3333%;-moz-box-flex:0;-moz-flex:0 0 33.3333%;-ms-flex:0 0 33.3333%;flex:0 0 33.3333%;max-width:33.3333%}.col-40{-webkit-box-flex:0;-webkit-flex:0 0 40%;-moz-box-flex:0;-moz-flex:0 0 40%;-ms-flex:0 0 40%;flex:0 0 40%;max-width:40%}.col-50{-webkit-box-flex:0;-webkit-flex:0 0 50%;-moz-box-flex:0;-moz-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-60{-webkit-box-flex:0;-webkit-flex:0 0 60%;-moz-box-flex:0;-moz-flex:0 0 60%;-ms-flex:0 0 60%;flex:0 0 60%;max-width:60%}.col-66,.col-67{-webkit-box-flex:0;-webkit-flex:0 0 66.6666%;-moz-box-flex:0;-moz-flex:0 0 66.6666%;-ms-flex:0 0 66.6666%;flex:0 0 66.6666%;max-width:66.6666%}.col-75{-webkit-box-flex:0;-webkit-flex:0 0 75%;-moz-box-flex:0;-moz-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-80{-webkit-box-flex:0;-webkit-flex:0 0 80%;-moz-box-flex:0;-moz-flex:0 0 80%;-ms-flex:0 0 80%;flex:0 0 80%;max-width:80%}.col-90{-webkit-box-flex:0;-webkit-flex:0 0 90%;-moz-box-flex:0;-moz-flex:0 0 90%;-ms-flex:0 0 90%;flex:0 0 90%;max-width:90%}@media (max-width:567px){.responsive-sm{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-sm .col,.responsive-sm .col-10,.responsive-sm .col-20,.responsive-sm .col-25,.responsive-sm .col-33,.responsive-sm .col-34,.responsive-sm .col-50,.responsive-sm .col-66,.responsive-sm .col-67,.responsive-sm .col-75,.responsive-sm .col-80,.responsive-sm .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}@media (max-width:767px){.responsive-md{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-md .col,.responsive-md .col-10,.responsive-md .col-20,.responsive-md .col-25,.responsive-md .col-33,.responsive-md .col-34,.responsive-md .col-50,.responsive-md .col-66,.responsive-md .col-67,.responsive-md .col-75,.responsive-md .col-80,.responsive-md .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}@media (max-width:1023px){.responsive-lg{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-lg .col,.responsive-lg .col-10,.responsive-lg .col-20,.responsive-lg .col-25,.responsive-lg .col-33,.responsive-lg .col-34,.responsive-lg .col-50,.responsive-lg .col-66,.responsive-lg .col-67,.responsive-lg .col-75,.responsive-lg .col-80,.responsive-lg .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}.hide{display:none}.opacity-hide{opacity:0}.grade-b .opacity-hide,.grade-c .opacity-hide{opacity:1;display:none}.show{display:block}.opacity-show{opacity:1}.invisible{visibility:hidden}.keyboard-open .hide-on-keyboard-open{display:none}.keyboard-open .bar-footer.hide-on-keyboard-open+.pane .has-footer,.keyboard-open .tabs.hide-on-keyboard-open+.pane .has-tabs{bottom:0}.inline{display:inline-block}.disable-pointer-events{pointer-events:none}.enable-pointer-events{pointer-events:auto}.disable-user-behavior{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-ms-touch-action:none;-ms-content-zooming:none}.click-block{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;z-index:99999;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);overflow:hidden}.click-block-hide{-webkit-transform:translate3d(-9999px,0,0);transform:translate3d(-9999px,0,0)}.no-resize{resize:none}.block{display:block;clear:both}.block:after{display:block;visibility:hidden;clear:both;height:0;content:"."}.full-image{width:100%}.clearfix:after,.clearfix:before{display:table;content:"";line-height:0}.clearfix:after{clear:both}.item.large-button-bar,.padding{padding:10px}.padding-top,.padding-vertical{padding-top:10px}.padding-horizontal,.padding-right,.popover-share .bar-footer .button-close{padding-right:10px}.padding-bottom,.padding-vertical,.popover-share .bar-footer .button-close{padding-bottom:10px}.padding-horizontal,.padding-left{padding-left:10px}.iframe-wrapper{position:fixed;-webkit-overflow-scrolling:touch;overflow:scroll}.iframe-wrapper iframe{height:100%;width:100%}.rounded{border-radius:4px}.light,a.light{color:#fff}.light-bg{background-color:#fff}.light-border{border-color:#ddd}.stable,a.stable{color:#f8f8f8}.stable-bg{background-color:#f8f8f8}.stable-border{border-color:#b2b2b2}.icon-help,.positive,a.icon-help,a.positive{color:#387ef5}.positive-bg{background-color:#387ef5}.positive-border{border-color:#0c60ee}#menu .footer .icon-help,#menu .footer a.icon-help,.calm,a.calm{color:#11c1f3}.calm-bg{background-color:#11c1f3}.calm-border{border-color:#0a9dc7}.assertive,.icon-alert,a.assertive,a.icon-alert{color:#ef473a}.assertive-bg{background-color:#ef473a}.assertive-border{border-color:#e42112}.balanced,a.balanced{color:#33cd5f}.balanced-bg{background-color:#33cd5f}.balanced-border{border-color:#28a54c}.energized,a.energized{color:#ffc900}.energized-bg{background-color:#ffc900}.energized-border{border-color:#e6b500}.royal,a.royal{color:#886aea}.royal-bg{background-color:#886aea}.royal-border{border-color:#6b46e5}.button-text-dark,.dark,a.button-text-dark,a.dark{color:#444}.dark-bg,.view-identity .hero,.view-identity .refresher-top-bg:before{background-color:#444}.dark-border{border-color:#111}[collection-repeat]{left:0!important;top:0!important;position:absolute!important;z-index:1}.collection-repeat-container{position:relative;z-index:1}.collection-repeat-after-container{z-index:0;display:block}.collection-repeat-after-container.horizontal{display:inline-block}.ng-cloak,.ng-hide:not(.ng-hide-animate),.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader){height:64px}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper{margin-top:19px!important}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader)>*{margin-top:20px}.platform-ios.platform-cordova:not(.fullscreen) .tabs-top>.tabs,.platform-ios.platform-cordova:not(.fullscreen) .tabs.tabs-top{top:64px}.platform-ios.platform-cordova:not(.fullscreen) .bar-subheader,.platform-ios.platform-cordova:not(.fullscreen) .has-header{top:64px}.platform-ios.platform-cordova:not(.fullscreen) .has-subheader{top:108px}.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-tabs-top{top:113px}.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-subheader.has-tabs-top{top:157px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader){height:44px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper{margin-top:-1px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader)>*{margin-top:0}.platform-ios.platform-cordova .popover .bar-subheader,.platform-ios.platform-cordova .popover .has-header{top:44px}.platform-ios.platform-cordova .popover .has-subheader{top:88px}.platform-ios.platform-cordova.status-bar-hide{margin-bottom:20px}@media (orientation:landscape){.platform-ios.platform-browser.platform-ipad{position:fixed}}.platform-c:not(.enable-transitions) *{-webkit-transition:none!important;transition:none!important}.slide-in-up{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.slide-in-up.ng-enter,.slide-in-up>.ng-enter{-webkit-transition:all cubic-bezier(.1,.7,.1,1) .4s;transition:all cubic-bezier(.1,.7,.1,1) .4s}.slide-in-up.ng-enter-active,.slide-in-up>.ng-enter-active{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.slide-in-up.ng-leave,.slide-in-up>.ng-leave{-webkit-transition:all ease-in-out 250ms;transition:all ease-in-out 250ms}@-webkit-keyframes scaleOut{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@keyframes scaleOut{from{transform:scale(1);opacity:1}to{transform:scale(.8);opacity:0}}@-webkit-keyframes superScaleIn{from{-webkit-transform:scale(1.2);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@keyframes superScaleIn{from{transform:scale(1.2);opacity:0}to{transform:scale(1);opacity:1}}[nav-view-transition=ios] [nav-view=entering],[nav-view-transition=ios] [nav-view=leaving]{-webkit-transition-duration:.5s;transition-duration:.5s;-webkit-transition-timing-function:cubic-bezier(.36,.66,.04,1);transition-timing-function:cubic-bezier(.36,.66,.04,1);-webkit-transition-property:opacity,-webkit-transform,box-shadow;transition-property:opacity,transform,box-shadow}[nav-view-transition=ios][nav-view-direction=back],[nav-view-transition=ios][nav-view-direction=forward]{background-color:#000}[nav-view-transition=ios] [nav-view=active],[nav-view-transition=ios][nav-view-direction=back] [nav-view=leaving],[nav-view-transition=ios][nav-view-direction=forward] [nav-view=entering]{z-index:3}[nav-view-transition=ios][nav-view-direction=back] [nav-view=entering],[nav-view-transition=ios][nav-view-direction=forward] [nav-view=leaving]{z-index:2}[nav-bar-transition=ios] .back-text,[nav-bar-transition=ios] .buttons,[nav-bar-transition=ios] .title{-webkit-transition-duration:.5s;transition-duration:.5s;-webkit-transition-timing-function:cubic-bezier(.36,.66,.04,1);transition-timing-function:cubic-bezier(.36,.66,.04,1);-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,transform}[nav-bar-transition=ios] [nav-bar=active],[nav-bar-transition=ios] [nav-bar=entering]{z-index:10}[nav-bar-transition=ios] [nav-bar=active] .bar,[nav-bar-transition=ios] [nav-bar=entering] .bar{background:0 0}[nav-bar-transition=ios] [nav-bar=cached]{display:block}[nav-bar-transition=ios] [nav-bar=cached] .header-item{display:none}[nav-view-transition=android] [nav-view=entering],[nav-view-transition=android] [nav-view=leaving]{-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-timing-function:cubic-bezier(.4,.6,.2,1);transition-timing-function:cubic-bezier(.4,.6,.2,1);-webkit-transition-property:-webkit-transform;transition-property:transform}[nav-view-transition=android] [nav-view=active],[nav-view-transition=android][nav-view-direction=back] [nav-view=leaving],[nav-view-transition=android][nav-view-direction=forward] [nav-view=entering]{z-index:3}[nav-view-transition=android][nav-view-direction=back] [nav-view=entering],[nav-view-transition=android][nav-view-direction=forward] [nav-view=leaving]{z-index:2}[nav-bar-transition=android] .buttons,[nav-bar-transition=android] .title{-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-timing-function:cubic-bezier(.4,.6,.2,1);transition-timing-function:cubic-bezier(.4,.6,.2,1);-webkit-transition-property:opacity;transition-property:opacity}[nav-bar-transition=android] [nav-bar=active],[nav-bar-transition=android] [nav-bar=entering]{z-index:10}[nav-bar-transition=android] [nav-bar=active] .bar,[nav-bar-transition=android] [nav-bar=entering] .bar{background:0 0}[nav-bar-transition=android] [nav-bar=cached]{display:block}[nav-bar-transition=android] [nav-bar=cached] .header-item{display:none}[nav-swipe=fast] .back-text,[nav-swipe=fast] .buttons,[nav-swipe=fast] .title,[nav-swipe=fast] [nav-view]{-webkit-transition-duration:50ms;transition-duration:50ms;-webkit-transition-timing-function:linear;transition-timing-function:linear}[nav-swipe=slow] .back-text,[nav-swipe=slow] .buttons,[nav-swipe=slow] .title,[nav-swipe=slow] [nav-view]{-webkit-transition-duration:160ms;transition-duration:160ms;-webkit-transition-timing-function:linear;transition-timing-function:linear}[nav-bar=cached],[nav-view=cached]{display:none}[nav-view=stage]{opacity:0;-webkit-transition-duration:0;transition-duration:0}[nav-bar=stage] .back-text,[nav-bar=stage] .buttons,[nav-bar=stage] .title{position:absolute;opacity:0;-webkit-transition-duration:0s;transition-duration:0s}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.ttf?v=1.1.0) format("truetype");font-weight:100;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.ttf?v=1.1.0) format("truetype");font-weight:300;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.ttf?v=1.1.0) format("truetype");font-weight:500;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.ttf?v=1.1.0) format("truetype");font-weight:900;font-style:normal}.item-md-label{display:block;background:0 0;box-shadow:none;margin-left:12px;margin-right:12px;padding:30px 0 0}.item-md-label .input-label{position:absolute;padding:5px 0 0;z-index:2;-webkit-transform:translate3d(0,-30px,0) scale(1);transform:translate3d(0,-30px,0) scale(1);-webkit-transition:all .2s ease;transition:all .2s ease;color:#fff;opacity:.5;-webkit-transform-origin:0;-ms-transform-origin:0;transform-origin:0}.item-md-label input{background-color:rgba(0,0,0,.6);bottom:0;color:#fff;letter-spacing:.25rem;padding:20px 10px;position:relative;z-index:1}.item-md-label .highlight{position:absolute;bottom:0;height:2px;left:0;width:100%;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);-webkit-transition:all .15s ease;transition:all .15s ease;z-index:1}.item-md-label .highlight-light{background:#fff}.item-md-label .highlight-stable{background:#f8f8f8}.item-md-label .highlight-positive{background:#387ef5}.item-md-label .highlight-calm{background:#11c1f3}.item-md-label .highlight-balanced{background:#33cd5f}.item-md-label .highlight-energized{background:#ffc900}.item-md-label .highlight-assertive{background:#ef473a}.item-md-label .highlight-royal{background:#886aea}.item-md-label .highlight-dark{background:#444}.item-md-label .input-label{letter-spacing:.25rem;padding:0 10px}.item-md-label input.used~.input-label,.item-md-label input:focus~.input-label{font-weight:700;opacity:.7;padding:0;text-transform:uppercase;-webkit-transform:translate3d(0,-60px,0) scale(.9);transform:translate3d(0,-60px,0) scale(.9)}.item-md-label input:focus~.highlight{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bar.bar-header.expanded,.expanded .bar.bar-header{height:75px}.bar.bar-header.expanded .title,.expanded.bar.bar-header .title{bottom:0;top:initial;padding-left:16px}.bar.bar-header.expanded .title.fab-left,.expanded .bar.bar-header .title.fab-left{bottom:0;left:90px;position:absolute;right:initial;top:initial}.bar.bar-header.expanded .title.fab-right,.expanded .bar.bar-header .title.fab-right{bottom:0;left:4px;position:absolute;top:initial;right:initial}.bar.bar-header.expanded+.button-fab,.expanded .bar.bar-header+.button-fab{top:50px}.bar.bar-header.expanded.push-down,.expanded .bar.bar-header.push-down{height:44px;overflow:hidden}.bar.bar-header.expanded,.expanded .bar.bar-header{-webkit-transition:height 1s cubic-bezier(.55,0,.1,1);transition:height 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bar.bar-header.expanded+.button-fab,.expanded .bar.bar-header+.button-fab{-webkit-transition:all 1.1s cubic-bezier(.55,0,.1,1);transition:all 1.1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0) scale(1);transform:translate3d(0,0,0) scale(1)}.bar.bar-header.expanded.push-down+.button-fab,.expanded .bar.bar-header.push-down+.button-fab{top:0;-webkit-transform:translate3d(-100px,-100px,0) scale(2.5);transform:translate3d(-100px,-100px,0) scale(2.5)}.bar.bar-header.expanded.push-down .title,.expanded .bar.bar-header.push-down .title{opacity:0;left:initial;right:initial}.bar.bar-header.expanded .title,.expanded .bar.bar-header .title{opacity:1;-webkit-transition:all 2s cubic-bezier(.55,0,.1,1);transition:all 2s cubic-bezier(.55,0,.1,1)}.bar.bar-header.expanded .title,.expanded .bar.bar-header .title{bottom:0;left:42px!important;top:initial}.bar.bar-header.expanded.has-header-fab-left .title,.expanded.has-header-fab-left .bar.bar-header .title{left:76px!important}.bar{z-index:2;font-size:1.3em;width:100%;box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar .button{min-width:38px;z-index:3}.bar .no-text span.back-text{display:none}.bar .title sup{opacity:.7}.bar.bar-header .button+.title{text-align:left;left:35px;line-height:46px}.button-bar{box-shadow:0 1px 3px rgba(0,0,0,.15)}.button-bar>.button{box-shadow:none}#menu .footer .button-bar>.button .icon-help:before,.button-bar>.button #menu .footer .icon-help:before,.button-bar>.button .icon-alert:before,.button-bar>.button .icon-help:before,.button-bar>.button .icon:before,.button-bar>.button:before{line-height:initial}.bar-footer .button-fab{position:absolute;top:-26px;bottom:initial}.bar-footer .buttons-left .button-fab{left:8px}.bar-footer .buttons-right .button-fab{right:8px}.bar .button.button-clear,.bar .button.button-text{box-shadow:none}.left-buttons .button-fab{left:8px;top:16px}.right-buttons .button-fab{right:8px;top:16px}.fab-left.title-left,.fab-left.title.title-left{left:68px}.bar .button.button-fab,.button.button-fab{box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);z-index:9999;width:56px;height:56px;max-height:initial;max-width:initial;border-radius:50%;border-radius:50%;overflow:hidden;padding:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:.3s fade-in-out;transition:.3s fade-in-out;-webkit-transition-property:-webkit-transform,box-shadow;transition-property:transform,box-shadow}.bar .button.button-fab.button-fab-bottom-right,.button.button-fab.button-fab-bottom-right{top:auto;right:16px;bottom:16px;left:auto;position:absolute}.bar .button.button-fab.button-fab-bottom-left,.button.button-fab.button-fab-bottom-left{top:auto;right:auto;bottom:16px;left:16px;position:absolute}.bar .button.button-fab.button-fab-top-right,.button.button-fab.button-fab-top-right{top:32px;right:16px;bottom:auto;left:auto;position:absolute}.bar .button.button-fab.button-fab-top-left,.button.button-fab.button-fab-top-left{top:32px;right:auto;bottom:auto;left:16px;position:absolute}.bar .button.button-fab.button-fab-top-left.expanded,.bar .button.button-fab.button-fab-top-right.expanded,.button.button-fab.button-fab-top-left.expanded,.button.button-fab.button-fab-top-right.expanded{top:48px}.bar .button.button-fab i,.button.button-fab i{font-size:2.5rem;margin-top:0}.bar .button.button-fab.mini,.button.button-fab.mini{width:40px;height:40px}.bar .button.button-fab.mini i,.button.button-fab.mini i{font-size:2rem}.motion{-webkit-transition:all .5s ease-out;transition:all .5s ease-out}.fade{opacity:0;-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spin-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0)!important;transform:translateZ(0) rotate(360deg) scale(0)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.menu-open .avatar{opacity:1;-webkit-transform:translateZ(0) rotate(0) scale(1)!important;transform:translateZ(0) rotate(0) scale(1)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.button.button-fab.button-fab-top-left.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(-120px,60px,0);transform:translate3d(-120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-top-right.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(120px,60px,0);transform:translate3d(120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-bottom-left.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(-120px,60px,0);transform:translate3d(-120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-bottom-right.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(120px,60px,0);transform:translate3d(120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.spin{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(0) scale(0)!important;transform:translateZ(0) rotate(0) scale(0)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.spin.on{-webkit-transform:translateZ(0) rotate(-360deg) scale(1)!important;transform:translateZ(0) rotate(-360deg) scale(1)!important}.flap{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flap.on{-webkit-transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) scale(3)!important;transform:translateZ(0) scale(3)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop.on{-webkit-transform:translateZ(0) scale(1)!important;transform:translateZ(0) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateY(0) scale(0)!important;transform:translateZ(0) rotateY(0) scale(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip.on{-webkit-transform:translateZ(0) rotateY(-720deg) scale(1)!important;transform:translateZ(0) rotateY(-720deg) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.bar .button.button-floating,.button.button-floating{display:inline-block;color:#fff;position:relative;z-index:1;width:37px;height:37px;line-height:37px;padding:0;border-radius:50%;background-clip:padding-box;-webkit-transition:.3s;transition:.3s;cursor:pointer}.bar .button.button-floating i,.button.button-floating i{width:inherit;display:inline-block;text-align:center;color:#fff;font-size:1.6rem;line-height:37px}.bar .button.button-floating.button-large,.button.button-floating.button-large{width:55.5px;height:55.5px}.bar .button.button-floating.button-large i,.button.button-floating.button-large i{line-height:55.5px}.bar .button,.bar .button.button-flat,.bar .button.button-large,.button,.button.button-flat,.button.button-large{box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);display:inline-block;height:36px;padding:0 2rem;border-radius:2px;background-clip:padding-box;text-transform:uppercase;border:none;outline:0;-webkit-tap-highlight-color:transparent}.bar .button.button-floating.disabled,.bar .button.button-floating:disabled,.bar .button.button-large.disabled,.bar .button.button-large:disabled,.bar .button.button:disabled,.bar .button.disabled,.bar .button.disabled.button-large,.button.button-floating.disabled,.button.button-floating:disabled,.button.button-large.disabled,.button.button-large:disabled,.button.button:disabled,.button.disabled,.button.disabled.button-large{background-color:#dfdfdf;box-shadow:none;color:#9f9f9f}.bar .button.button-floating.disabled:hover,.bar .button.button-floating:disabled:hover,.bar .button.button-large.disabled:hover,.bar .button.button-large:disabled:hover,.bar .button.button:disabled:hover,.bar .button.disabled.button-large:hover,.bar .button.disabled:hover,.button.button-floating.disabled:hover,.button.button-floating:disabled:hover,.button.button-large.disabled:hover,.button.button-large:disabled:hover,.button.button:disabled:hover,.button.disabled.button-large:hover,.button.disabled:hover{background-color:#dfdfdf;color:#9f9f9f}.bar .button i,.bar .button.button-flat i,.bar .button.button-floating i,.bar .button.button-large i,.button i,.button.button-flat i,.button.button-floating i,.button.button-large i{font-size:1.3rem}.button-bar .button{border-radius:0}.bar .button,.bar .button-large,.button,.button-large{text-decoration:none;text-align:center;letter-spacing:.5px;-webkit-transition:.2s ease-out;transition:.2s ease-out;cursor:pointer}.button{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;outline:0;margin:0;white-space:nowrap;text-align:center;text-transform:uppercase;font-weight:500;font-style:inherit;font-variant:inherit;font-size:inherit;text-decoration:none;cursor:pointer;overflow:hidden;-webkit-transition:box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1),-webkit-transform .4s cubic-bezier(.25,.8,.25,1);transition:box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1),transform .4s cubic-bezier(.25,.8,.25,1)}.button:focus{outline:0}.button.ng-hide{-webkit-transition:none;transition:none}.button.cornered{border-radius:0}.button.raised{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.button-outline,.button-outline:active,.button-outline:hover{border-style:solid;border-width:1px}.button.button-outline,.button.button-outline.button-assertive,.button.button-outline.button-balanced,.button.button-outline.button-calm,.button.button-outline.button-dark,.button.button-outline.button-energized,.button.button-outline.button-light,.button.button-outline.button-positive,.button.button-outline.button-royal,.button.button-outline.button-stable,.button.button-outline.button-text{border-color:rgba(0,0,0,.1)}.bar .button-flat,.button-flat{box-shadow:none;background-color:transparent;color:#343434;cursor:pointer}.bar .button.button-flat.disabled,.button.button-flat.disabled{color:#b3b3b3}.bar .button.button-large i,.button.button-large i{font-size:1.6rem}.button-pin-header.button-floating{position:absolute;z-index:1000}.button-pin-header.button-pin-left{left:24px;top:-24px}.button-pin-header.button-pin-right{right:24px;top:-24px}.button:not([disabled]).floating:focus,.button:not([disabled]).floating:hover,.button:not([disabled]).raised:focus,.button:not([disabled]).raised:hover{-webkit-transform:translate3d(0,-1px,0);transform:translate3d(0,-1px,0)}.button.button-flat{box-shadow:none;color:inherit}.button.button-flat:hover{color:inherit}.button.button-flat,.button.button-flat:active,.button.button-flat:hover{color:#fff}.button.button-clear,.button.button-clear:active,.button.button-clear:hover,.button.button-text,.button.button-text:active,.button.button-text:hover{background:0 0}.button-block.ink,.button-full.ink{display:block}.card-item.item{border:none;padding-bottom:4px;padding-top:4px}.card-item.item:first-child{padding-top:16px}.card{box-shadow:0 2px 5px 0 rgba(0,0,0,.26);display:block;margin:8px;padding:0;position:relative}.card .image{display:block;margin-top:10px;margin-bottom:5px}.card img{box-shadow:0 2px 5px 0 rgba(0,0,0,.26);display:block;max-width:100%;max-height:initial;position:static}.card.card-gallery img{border:none;box-shadow:none;display:block}.card .card-footer{font-size:90%;opacity:.8;padding-top:10px}.card>.item{border:none}.card.card-gallery>.item{background:inherit}#menu .footer .card .icon+.icon-help,#menu .footer .card .icon-alert+.icon-help,#menu .footer .card .icon-help+.icon,#menu .footer .card .icon-help+.icon-alert,#menu .footer .card .icon-help+.icon-help,.card #menu .footer .icon+.icon-help,.card #menu .footer .icon-alert+.icon-help,.card #menu .footer .icon-help+.icon,.card #menu .footer .icon-help+.icon-alert,.card #menu .footer .icon-help+.icon-help,.card .icon+.icon,.card .icon+.icon-alert,.card .icon+.icon-help,.card .icon-alert+.icon,.card .icon-alert+.icon-alert,.card .icon-alert+.icon-help,.card .icon-help+.icon,.card .icon-help+.icon-alert,.card .icon-help+.icon-help{padding-left:1rem}.card.animate-fade-in{opacity:0;-webkit-transform:translate3d(-30px,1px,0);-webkit-transition:all 1s ease-in-out}.animate-fade-slide-in .card.animate-fade-in.expanded.item,.animate-fade-slide-in .expanded .card.animate-fade-in.item,.animate-fade-slide-in-right .card.animate-fade-in.expanded.item,.animate-fade-slide-in-right .expanded .card.animate-fade-in.item,.animate-ripple .expanded .card.animate-fade-in.item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.animate-fade-in.card-comment,.card.animate-fade-in.done{opacity:1;-webkit-transform:translate3d(0,0,0)}.card .item.item-avatar{min-height:88px;padding-left:88px}.hero{background-size:cover;box-shadow:0 2px 5px 0 rgba(0,0,0,.26);color:#fff;height:200px;position:relative;text-align:center;-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);width:100%}.hero>*{-webkit-transition:opacity 2.5s cubic-bezier(.55,0,.1,1);transition:opacity 2.5s cubic-bezier(.55,0,.1,1);opacity:1}.hero+.mid-bar{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);height:initial;opacity:1}.hero .hero-icon{box-shadow:0 0 2px 0 rgba(0,0,0,.26);border-radius:50%;display:inline-block;font-size:65px;height:150px;padding:10px 30px;line-height:136px;width:150px}.hero.no-header{height:244px}.hero>.content{bottom:0;position:absolute;text-align:center;width:100%;z-index:1}.hero>.content>.avatar{background-position:center;background-size:cover;border:solid 1px rgba(255,255,255,.8);border-radius:50%;display:inline-block;height:88px;left:auto;margin-bottom:10px;position:relative;width:88px}.hero h1 .hero h2,.hero h3,.hero h4,.hero h5,.hero h6{color:#fff;margin:0}.hero h4{color:rgba(255,255,255,.7);margin:3px 0 16px}.hero h1>a,.hero h2>a,.hero h3>a,.hero h4>a,.hero h5>a,.hero h6>a{text-decoration:none}.hero+.button-bar{border-radius:0;margin-top:0}.hero+.button-bar>.button:first-child,.hero+.button-bar>.button:last-child{border-radius:0}.hero .hero-icon{color:#fff;font-size:96px}.hero .hero-icon+h1{color:#fff;letter-spacing:.15rem}.hero .button,.hero .button.button-flat,.hero .button.button-large{margin:0}.hero h1.title{color:#fff;font-size:23px;margin:0;text-align:left;padding-left:80px;line-height:59px}.hero+.mid-bar{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);height:initial;opacity:1}.hero>*{-webkit-transition:opacity 2.5s cubic-bezier(.55,0,.1,1);transition:opacity 2.5s cubic-bezier(.55,0,.1,1);opacity:1}.item{font-size:14px;width:100%}#menu .footer .item-icon-left .icon-help,.item-icon-left #menu .footer .icon-help,.item-icon-left .icon,.item-icon-left .icon-alert,.item-icon-left .icon-help{left:16px}#menu .footer .item-icon-right .icon-help,.item-icon-right #menu .footer .icon-help,.item-icon-right .icon,.item-icon-right .icon-alert,.item-icon-right .icon-help{right:16px}.item-thumbnail-left .item-content .item-image,.item-thumbnail-left .item-content>img:first-child,.item-thumbnail-left .item-image,.item-thumbnail-left>img:first-child{border-radius:50%}.tab-item.activated{height:calc(100% + 3px)}.content+.list{padding-top:0}.list .item{border:none;min-height:48px;text-align:left}.list .item.tabs{padding:initial}.list .item.item-bg-image{max-height:150px;min-height:150px}.list .item.item-bg-image>img{height:100%;left:0;max-width:initial;opacity:.65;position:absolute;top:0;width:100%;z-index:0}.list a.item{opacity:1}.list .item.item-bg-image h1,.list .item.item-bg-image h2,.list .item.item-bg-image h3,.list .item.item-bg-image h4,.list .item.item-bg-image h5,.list .item.item-bg-image h6{color:#fff;font-weight:700;position:relative;text-shadow:0 0 3px rgba(0,0,0,.95);z-index:1}.list .item.item-bg-image h2{font-size:24px}.list .item.item-bg-image h2{font-size:24px}.list .item.item-bg-image p{color:#fff;font-size:17px;position:relative;text-shadow:0 0 4px rgba(0,0,0,.95);z-index:1}.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{min-height:80px}.card>.item.item-thumbnail-left,.item-thumbnail-left,.item-thumbnail-left .item-content{padding-left:106px}.card>.item.item-thumbnail-right,.item-thumbnail-right,.item-thumbnail-right .item-content{padding-right:106px}.item-avatar .item-content .item-image,.item-avatar .item-content>img:first-child,.item-avatar .item-image,.item-avatar-left .item-content .item-image,.item-avatar-left .item-content>img:first-child,.item-avatar-left .item-image,.item-avatar-left>img:first-child,.item-avatar>img:first-child{border-radius:50%;left:16px;max-height:40px;max-width:40px}.avatar,.item-avatar .avatar{background-position:center;background-size:cover;border-radius:50%;display:inline-block;height:56px;left:16px;position:absolute;width:56px}.list.half{display:inline-block;float:left;margin:0;padding:0;width:50%}.list.half:first-child{padding:16px 8px 16px 16px}.list.half:last-child{padding:16px 16px 16px 8px}.list.half:first-child .card.card-gallery{margin-left:0;margin-right:0}.list.half:last-child .card.card-gallery{margin-left:0;margin-right:0}.list.condensed-space>.card,.list.condensed-space>.item{margin:0 0 2px}.list .card.card-gallery{display:block;float:left;margin:0 0 0 13px;padding:0;width:auto}.list.half .item{width:100%}.list.half .item.card{margin-bottom:16px}.list .card.card-gallery.item h2{padding:12px}.list .item.item-gallery img{width:100%}.item.item-divider{border-top:solid 1px rgba(0,0,0,.12);font-size:14px;font-weight:700;height:48px;line-height:48px;color:rgba(0,0,0,.54)}.item.item-divider:first-child{border:none}.card>.item-avatar,.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{padding-left:72px}.item .item-content.activated,.item .item-content.active,.item-complex.activated .item-content,.item-complex.active .item-content,.item.activated,.item.active{background-color:transparent}.list-inset{margin:20px 30px;border-left:solid 1px #ccc;border-radius:0;background-color:#fff}.item-floating-label,.list .item.item-floating-label{border-bottom:solid 1px #ccc}.loader{position:relative;margin:0 auto;width:100px;height:100px;zoom:1.7}.circular{-webkit-animation:rotate 2s linear infinite;animation:rotate 2s linear infinite;height:100px;position:relative;width:100px}.path{stroke-dasharray:1,200;stroke-dashoffset:0;-webkit-animation:dash 1.5s ease-in-out infinite,color 6s ease-in-out infinite;animation:dash 1.5s ease-in-out infinite,color 6s ease-in-out infinite;stroke-linecap:round}@-webkit-keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35}100%{stroke-dasharray:89,200;stroke-dashoffset:-124}}@keyframes dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35}100%{stroke-dasharray:89,200;stroke-dashoffset:-124}}@-webkit-keyframes color{0%,100%{stroke:#d62d20}40%{stroke:#0057e7}66%{stroke:#008744}80%,90%{stroke:#ffa700}}@keyframes color{0%,100%{stroke:#d62d20}40%{stroke:#0057e7}66%{stroke:#008744}80%,90%{stroke:#ffa700}}.login{background-position:25% 25%;background-size:180% 180%;height:100%;-webkit-transition:all 1.5s ease-in-out;transition:all 1.5s ease-in-out}.login .item{margin:0 12px;padding-left:0;padding-right:0;width:initial}.login .button-bar{bottom:0;margin:28px 12px 0;width:initial}.login .light-bg{background-color:#fff}#menu .footer .hero-icon.icon-help:before,.hero-icon.icon-alert:before,.hero-icon.icon-help:before,.icon.hero-icon:before{line-height:130px}.card.has-mask:after,.hero.has-mask:after,.item.has-mask:after{content:'';background:-webkit-linear-gradient(top,transparent 0,rgba(0,0,0,.6) 100%);height:100%;left:0;position:absolute;top:0;z-index:0;width:100%}.card.has-mask-reverse:after,.hero.has-mask-reverse:after,.item.has-mask-reverse:after{content:'';background:-webkit-linear-gradient(top,rgba(0,0,0,.6) 0,transparent 100%);height:100%;left:0;position:absolute;top:0;z-index:0;width:100%}.menu-bottom{bottom:16px;left:16px;right:16px;position:absolute}.menu-top{top:16px;left:16px;right:16px;position:absolute}.menu .avatar{top:16px;left:16px;height:65px;width:65px}.menu .bar.bar-header.expanded{box-shadow:none;min-height:150px;color:#fff}.menu-open .bar.bar-header.expanded{background-position:0;background-size:100%}.has-expanded-header{top:150px!important}.motion{-webkit-transition:all .5s ease-out;transition:all .5s ease-out}.fade{opacity:0;-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spin-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0)!important;transform:translateZ(0) rotate(360deg) scale(0)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.menu-open .avatar{opacity:1;-webkit-transform:translateZ(0) rotate(0) scale(1)!important;transform:translateZ(0) rotate(0) scale(1)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.spin{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(0) scale(0)!important;transform:translateZ(0) rotate(0) scale(0)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.spin.on{-webkit-transform:translateZ(0) rotate(-360deg) scale(1)!important;transform:translateZ(0) rotate(-360deg) scale(1)!important}.flap{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flap.on{-webkit-transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) scale(3)!important;transform:translateZ(0) scale(3)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop.on{-webkit-transform:translateZ(0) scale(1)!important;transform:translateZ(0) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateY(0) scale(0)!important;transform:translateZ(0) rotateY(0) scale(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip.on{-webkit-transform:translateZ(0) rotateY(-720deg) scale(1)!important;transform:translateZ(0) rotateY(-720deg) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.bold{font-weight:700}.static{position:static}#menu .footer .popover-helptip .icon-bottom-left.icon-help,#menu .footer .popover-helptip .icon-left.icon-help,.popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-helptip #menu .footer .icon-left.icon-help,.popover-helptip .icon-bottom-left.icon-alert,.popover-helptip .icon-bottom-left.icon-help,.popover-helptip .icon-left.icon-alert,.popover-helptip .icon-left.icon-help,.popover-helptip .icon.icon-bottom-left,.popover-helptip .icon.icon-left,.pull-left{float:left}#menu .footer .popover-helptip .icon-bottom-center.icon-help,#menu .footer .popover-helptip .icon-bottom-right.icon-help,#menu .footer .popover-helptip .icon-center.icon-help,#menu .footer .popover-helptip .icon-right.icon-help,.popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-helptip #menu .footer .icon-center.icon-help,.popover-helptip #menu .footer .icon-right.icon-help,.popover-helptip .icon-bottom-center.icon-alert,.popover-helptip .icon-bottom-center.icon-help,.popover-helptip .icon-bottom-right.icon-alert,.popover-helptip .icon-bottom-right.icon-help,.popover-helptip .icon-center.icon-alert,.popover-helptip .icon-center.icon-help,.popover-helptip .icon-right.icon-alert,.popover-helptip .icon-right.icon-help,.popover-helptip .icon.icon-bottom-center,.popover-helptip .icon.icon-bottom-right,.popover-helptip .icon.icon-center,.popover-helptip .icon.icon-right,.pull-right{float:right}.double-padding,.ionic-content.double-padding{padding:16px}.double-padding-x{padding-left:16px;padding-right:16px}.double-padding-y{padding-top:16px;padding-bottom:16px}.outline{border-style:solid;border-width:1px}.border-top{border-top:solid 1px #ccc;padding-top:30px}.no-border{border:none}.circle{border-radius:50%}.bar.no-padding,.button-bar.no-padding,.button.no-padding,.card.no-padding,.item.no-padding,.list.no-padding,.no-padding{padding:0}#menu .footer .flat.button.icon-help,.flat,.flat.button,.flat.button.icon,.flat.button.icon-alert,.flat.button.icon-help,.flat.hero,.flat.tabs{box-shadow:none;-webkit-box-shadow:none}.im-wrapper,.item.large-button-bar,.padding{padding:16px!important}.padding-bottom,.popover-share .bar-footer .button-close{padding-bottom:16px!important}.padding-top{padding-top:16px!important}.padding-left{padding-left:16px!important}.padding-right,.popover-share .bar-footer .button-close{padding-right:16px!important}.no-padding-bottom{padding-bottom:0!important}.no-padding-top{padding-top:0!important}.no-padding-left{padding-left:0!important}.no-padding-right{padding-right:0!important}.z1{box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar.bar-positive.darker{background-color:#164fab}.bar.bar-positive.dark-positive-bg{background-color:#2c5cad}.muted{color:#c3c3c3}.clear-bg{background:0 0}.animate-blinds .item{visibility:hidden}.animate-blinds .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-blinds .item-bg-image>img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-blinds .animate-fade-slide-in .expanded .item,.animate-blinds .animate-fade-slide-in .expanded.item,.animate-blinds .animate-fade-slide-in-right .expanded .item,.animate-blinds .animate-fade-slide-in-right .expanded.item,.animate-blinds .animate-ripple .expanded .item,.animate-blinds .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-blinds .in,.animate-blinds.done>*,.animate-fade-slide-in .animate-blinds .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item>*,.animate-fade-slide-in .expanded .animate-blinds .item,.animate-fade-slide-in .expanded .animate-blinds.item>*,.animate-fade-slide-in-right .animate-blinds .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item>*,.animate-fade-slide-in-right .expanded .animate-blinds .item,.animate-fade-slide-in-right .expanded .animate-blinds.item>*,.animate-ripple .expanded .animate-blinds .item,.animate-ripple .expanded .animate-blinds.item>*,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment>*{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.animate-blinds .animate-fade-slide-in .expanded .item,.animate-blinds .animate-fade-slide-in .expanded.item,.animate-blinds .animate-fade-slide-in-right .expanded .item,.animate-blinds .animate-fade-slide-in-right .expanded.item,.animate-blinds .animate-ripple .expanded .item,.animate-blinds .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-blinds .in,.animate-blinds.done .item,.animate-fade-slide-in .animate-blinds .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item .item,.animate-fade-slide-in .expanded .animate-blinds .item,.animate-fade-slide-in .expanded .animate-blinds.item .item,.animate-fade-slide-in-right .animate-blinds .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item .item,.animate-fade-slide-in-right .expanded .animate-blinds .item,.animate-fade-slide-in-right .expanded .animate-blinds.item .item,.animate-ripple .expanded .animate-blinds .item,.animate-ripple .expanded .animate-blinds.item .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .item{visibility:visible}.animate-blinds .item{visibility:hidden}.animate-blinds .item{opacity:0}.animate-blinds .animate-fade-slide-in .expanded .item,.animate-blinds .animate-fade-slide-in .expanded.item,.animate-blinds .animate-fade-slide-in-right .expanded .item,.animate-blinds .animate-fade-slide-in-right .expanded.item,.animate-blinds .animate-ripple .expanded .item,.animate-blinds .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-blinds .in,.animate-blinds.done,.animate-fade-slide-in .animate-blinds .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item,.animate-fade-slide-in .expanded .animate-blinds .item,.animate-fade-slide-in .expanded .animate-blinds.item,.animate-fade-slide-in-right .animate-blinds .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item,.animate-fade-slide-in-right .expanded .animate-blinds .item,.animate-fade-slide-in-right .expanded .animate-blinds.item,.animate-ripple .expanded .animate-blinds .item,.animate-ripple .expanded .animate-blinds.item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;opacity:1}.animate-blinds .animate-fade-slide-in .expanded .item,.animate-blinds .animate-fade-slide-in .expanded.item,.animate-blinds .animate-fade-slide-in-right .expanded .item,.animate-blinds .animate-fade-slide-in-right .expanded.item,.animate-blinds .animate-ripple .expanded .item,.animate-blinds .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-blinds .in,.animate-blinds.done,.animate-fade-slide-in .animate-blinds .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item,.animate-fade-slide-in .expanded .animate-blinds .item,.animate-fade-slide-in .expanded .animate-blinds.item,.animate-fade-slide-in-right .animate-blinds .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item,.animate-fade-slide-in-right .expanded .animate-blinds .item,.animate-fade-slide-in-right .expanded .animate-blinds.item,.animate-ripple .expanded .animate-blinds .item,.animate-ripple .expanded .animate-blinds.item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment{visibility:visible}.animate-blinds.done .animate-fade-slide-in .expanded .item,.animate-blinds.done .animate-fade-slide-in .expanded.item,.animate-blinds.done .animate-fade-slide-in-right .expanded .item,.animate-blinds.done .animate-fade-slide-in-right .expanded.item,.animate-blinds.done .animate-ripple .expanded .item,.animate-blinds.done .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-blinds.done .in,.animate-fade-slide-in .animate-blinds.done .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item .in,.animate-fade-slide-in .animate-blinds.expanded.item .item,.animate-fade-slide-in .animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in .expanded .animate-blinds.done .item,.animate-fade-slide-in .expanded .animate-blinds.item .in,.animate-fade-slide-in .expanded .animate-blinds.item .item,.animate-fade-slide-in-right .animate-blinds.done .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item .in,.animate-fade-slide-in-right .animate-blinds.expanded.item .item,.animate-fade-slide-in-right .animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right .expanded .animate-blinds.done .item,.animate-fade-slide-in-right .expanded .animate-blinds.item .in,.animate-fade-slide-in-right .expanded .animate-blinds.item .item,.animate-ripple .animate-fade-slide-in .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .animate-fade-slide-in-right .animate-blinds.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .expanded .animate-blinds.done .item,.animate-ripple .expanded .animate-blinds.item .in,.animate-ripple .expanded .animate-blinds.item .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-blinds.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .in,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.done .card.card-comment{opacity:1}.animate-blinds .has-mask-reverse:after{opacity:0;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-blinds.done .has-mask-reverse:after,.animate-fade-slide-in .animate-blinds.expanded.item .has-mask-reverse:after,.animate-fade-slide-in .expanded .animate-blinds.item .has-mask-reverse:after,.animate-fade-slide-in-right .animate-blinds.expanded.item .has-mask-reverse:after,.animate-fade-slide-in-right .expanded .animate-blinds.item .has-mask-reverse:after,.animate-ripple .expanded .animate-blinds.item .has-mask-reverse:after,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-blinds.card.card-comment .has-mask-reverse:after{opacity:1}.animate-blinds .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-pan-in-left{background-position:0 0}.animate-fade-slide-in .animate-ripple .expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in-right .animate-ripple .expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-ripple .animate-fade-slide-in .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded.item,.animate-ripple .done,.animate-ripple .expanded .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment{visibility:hidden}.animate-fade-slide-in .animate-ripple .expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in-right .animate-ripple .expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-ripple .animate-fade-slide-in .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded.item,.animate-ripple .done,.animate-ripple .expanded .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-ripple .item-bg-image img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in .animate-ripple .expanded.item,.animate-fade-slide-in .animate-ripple.expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in .expanded .animate-ripple.item,.animate-fade-slide-in-right .animate-ripple .expanded.item,.animate-fade-slide-in-right .animate-ripple.expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple.item,.animate-ripple .animate-fade-slide-in .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded.item,.animate-ripple .expanded .animate-ripple.item,.animate-ripple .expanded .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .in,.animate-ripple.done{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in .animate-ripple .expanded.item,.animate-fade-slide-in .animate-ripple.expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in .expanded .animate-ripple.item,.animate-fade-slide-in-right .animate-ripple .expanded.item,.animate-fade-slide-in-right .animate-ripple.expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple.item,.animate-ripple .animate-fade-slide-in .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded.item,.animate-ripple .expanded .animate-ripple.item,.animate-ripple .expanded .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .in,.animate-ripple.done{visibility:visible}.animate-ripple .item{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1);opacity:0}.animate-fade-slide-in .animate-ripple .item.expanded,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in-right .animate-ripple .item.expanded,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-ripple .animate-fade-slide-in .item.expanded,.animate-ripple .animate-fade-slide-in-right .item.expanded,.animate-ripple .expanded .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .item.card.card-comment,.animate-ripple .item.in{opacity:1}.animate-fade-slide-in .animate-ripple .expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in-right .animate-ripple .expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-ripple .animate-fade-slide-in .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded.item,.animate-ripple .done,.animate-ripple .expanded .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment{visibility:hidden}.animate-fade-slide-in .animate-ripple .expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in-right .animate-ripple .expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-ripple .animate-fade-slide-in .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded.item,.animate-ripple .done,.animate-ripple .expanded .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-fade-slide-in .animate-ripple .expanded.item,.animate-fade-slide-in .animate-ripple.expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in .expanded .animate-ripple.item,.animate-fade-slide-in-right .animate-ripple .expanded.item,.animate-fade-slide-in-right .animate-ripple.expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple.item,.animate-ripple .animate-fade-slide-in .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded.item,.animate-ripple .expanded .animate-ripple.item,.animate-ripple .expanded .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .in,.animate-ripple.done{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in .animate-ripple .expanded.item,.animate-fade-slide-in .animate-ripple.expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in .expanded .animate-ripple.item,.animate-fade-slide-in-right .animate-ripple .expanded.item,.animate-fade-slide-in-right .animate-ripple.expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple.item,.animate-ripple .animate-fade-slide-in .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded.item,.animate-ripple .expanded .animate-ripple.item,.animate-ripple .expanded .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .in,.animate-ripple.done{visibility:visible}.animate-fade-slide-in .animate-ripple.done .expanded.item,.animate-fade-slide-in .animate-ripple.expanded.item .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in .animate-ripple.expanded.item .in,.animate-fade-slide-in .animate-ripple.expanded.item .item,.animate-fade-slide-in .expanded .animate-ripple.done .item,.animate-fade-slide-in .expanded .animate-ripple.item .in,.animate-fade-slide-in .expanded .animate-ripple.item .item,.animate-fade-slide-in-right .animate-ripple.done .expanded.item,.animate-fade-slide-in-right .animate-ripple.expanded.item .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right .animate-ripple.expanded.item .in,.animate-fade-slide-in-right .animate-ripple.expanded.item .item,.animate-fade-slide-in-right .expanded .animate-ripple.done .item,.animate-fade-slide-in-right .expanded .animate-ripple.item .in,.animate-fade-slide-in-right .expanded .animate-ripple.item .item,.animate-ripple .expanded .animate-ripple.item .in,.animate-ripple .expanded .animate-ripple.item .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-ripple.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .in,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .item,.animate-ripple.done .animate-fade-slide-in .expanded.item,.animate-ripple.done .animate-fade-slide-in-right .expanded.item,.animate-ripple.done .expanded .item,.animate-ripple.done .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple.done .in{opacity:1}.animate-ripple .has-mask-reverse:after{opacity:0;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in .animate-ripple.expanded.item .has-mask-reverse:after,.animate-fade-slide-in .expanded .animate-ripple.item .has-mask-reverse:after,.animate-fade-slide-in-right .animate-ripple.expanded.item .has-mask-reverse:after,.animate-fade-slide-in-right .expanded .animate-ripple.item .has-mask-reverse:after,.animate-ripple .expanded .animate-ripple.item .has-mask-reverse:after,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-ripple.card.card-comment .has-mask-reverse:after,.animate-ripple.done .has-mask-reverse:after{opacity:1}.animate-ripple .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-fade-slide-in .item{visibility:hidden}.animate-fade-slide-in .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-fade-slide-in .item-bg-image img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in .expanded .item,.animate-fade-slide-in .expanded.item,.animate-fade-slide-in .in,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in.done .item,.animate-ripple .expanded .animate-fade-slide-in .item,.animate-ripple .expanded .animate-fade-slide-in.item .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.animate-fade-slide-in .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in .expanded .item,.animate-fade-slide-in .expanded.item,.animate-fade-slide-in .in,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in.done .item,.animate-ripple .expanded .animate-fade-slide-in .item,.animate-ripple .expanded .animate-fade-slide-in.item .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item{visibility:visible}.list .item.item-bg-image{max-height:150px}.animate-fade-slide-in .item{visibility:hidden}.animate-fade-slide-in .item{-ms-transform:translate3d(-250px,250px,0);-webkit-transform:translate3d(-250px,250px,0);transform:translate3d(-250px,250px,0);-webkit-transition:-webkit-transform .5s cubic-bezier(.55,0,.1,1);transition:transform .5s cubic-bezier(.55,0,.1,1);opacity:0}.animate-fade-slide-in .animate-fade-slide-in.expanded.item,.animate-fade-slide-in .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in .expanded .animate-fade-slide-in.item,.animate-fade-slide-in .expanded .item,.animate-fade-slide-in .expanded.item,.animate-fade-slide-in .in,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item,.animate-fade-slide-in.done,.animate-ripple .expanded .animate-fade-slide-in .item,.animate-ripple .expanded .animate-fade-slide-in.item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .5s ease-in-out;transition:all .5s ease-in-out;opacity:1}.animate-fade-slide-in .animate-fade-slide-in.expanded.item,.animate-fade-slide-in .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in .expanded .animate-fade-slide-in.item,.animate-fade-slide-in .expanded .item,.animate-fade-slide-in .expanded.item,.animate-fade-slide-in .in,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item,.animate-fade-slide-in.done,.animate-ripple .expanded .animate-fade-slide-in .item,.animate-ripple .expanded .animate-fade-slide-in.item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment{visibility:visible}.animate-fade-slide-in .animate-fade-slide-in.expanded.item .in,.animate-fade-slide-in .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .in,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .in,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in-right .animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.done .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .in,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in.done .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in.done .expanded .item,.animate-fade-slide-in.done .expanded.item,.animate-fade-slide-in.done .in,.animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.expanded.item .card.card-comment,.animate-ripple .expanded .animate-fade-slide-in.done .item,.animate-ripple .expanded .animate-fade-slide-in.item .in,.animate-ripple .expanded .animate-fade-slide-in.item .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-fade-slide-in.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .in,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.done .card.card-comment{opacity:1}.animate-fade-slide-in .has-mask-reverse:after{opacity:0;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in .animate-fade-slide-in.expanded.item .has-mask-reverse:after,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .has-mask-reverse:after,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .has-mask-reverse:after,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .has-mask-reverse:after,.animate-fade-slide-in.done .has-mask-reverse:after,.animate-ripple .expanded .animate-fade-slide-in.item .has-mask-reverse:after,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .has-mask-reverse:after{opacity:1}.animate-fade-slide-in .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-fade-slide-in-right .item{visibility:hidden}.animate-fade-slide-in-right .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-fade-slide-in-right .item-bg-image>img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item>*,.animate-fade-slide-in .expanded .animate-fade-slide-in-right .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item>*,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item>*,.animate-fade-slide-in-right .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item>*,.animate-fade-slide-in-right .expanded .item,.animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done>*,.animate-ripple .expanded .animate-fade-slide-in-right .item,.animate-ripple .expanded .animate-fade-slide-in-right.item>*,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment>*{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item,.animate-fade-slide-in-right .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right .expanded .item,.animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done .item,.animate-ripple .expanded .animate-fade-slide-in-right .item,.animate-ripple .expanded .animate-fade-slide-in-right.item .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item{visibility:visible}.animate-fade-slide-in-right .item{visibility:hidden}.animate-fade-slide-in-right .item{-ms-transform:translate3d(250px,250px,0);-webkit-transform:translate3d(250px,250px,0);transform:translate3d(250px,250px,0);-webkit-transition:-webkit-transform .5s cubic-bezier(.55,0,.1,1);transition:transform .5s cubic-bezier(.55,0,.1,1);opacity:0}.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item,.animate-fade-slide-in-right .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item,.animate-fade-slide-in-right .expanded .item,.animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done,.animate-ripple .expanded .animate-fade-slide-in-right .item,.animate-ripple .expanded .animate-fade-slide-in-right.item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;opacity:1}.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item,.animate-fade-slide-in-right .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item,.animate-fade-slide-in-right .expanded .item,.animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done,.animate-ripple .expanded .animate-fade-slide-in-right .item,.animate-ripple .expanded .animate-fade-slide-in-right.item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment{visibility:visible}.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .in,.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item,.animate-fade-slide-in .animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.done .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .in,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .in,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .in,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right.done .animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right.done .expanded .item,.animate-fade-slide-in-right.done .expanded.item,.animate-fade-slide-in-right.done .in,.animate-ripple .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.expanded.item .card.card-comment,.animate-ripple .expanded .animate-fade-slide-in-right.done .item,.animate-ripple .expanded .animate-fade-slide-in-right.item .in,.animate-ripple .expanded .animate-fade-slide-in-right.item .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .animate-fade-slide-in-right.item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .in,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.done .card.card-comment{opacity:1}.animate-fade-slide-in-right .has-mask-reverse:after{opacity:0;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after,.animate-fade-slide-in-right.done .has-mask-reverse:after,.animate-ripple .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after,.animate-ripple .expanded.item .card-avatar-small.expanded .item .card-avatar-small .expanded .item .card-avatar-small.expanded .card.card-comment .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .has-mask-reverse:after{opacity:1}.animate-fade-slide-in-right .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.hero.slide-up,.slide-up{height:100%;overflow:hidden;text-align:center}.slide-up{-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.hero.slide-up *,.slide-up *{opacity:0}.hero.slide-up+.mid-bar,.slide-up+.mid-bar{height:100%;opacity:.7;-webkit-transform:translate3d(100%,-240px,0);transform:translate3d(100%,-240px,0)}/*! +*/@font-face{font-family:Ionicons;src:url(../lib/ionic/fonts/ionicons.eot?v=2.0.1);src:url(../lib/ionic/fonts/ionicons.eot?v=2.0.1#iefix) format("embedded-opentype"),url(../lib/ionic/fonts/ionicons.ttf?v=2.0.1) format("truetype"),url(../lib/ionic/fonts/ionicons.woff?v=2.0.1) format("woff"),url(../lib/ionic/fonts/ionicons.woff) format("woff"),url(../lib/ionic/fonts/ionicons.svg?v=2.0.1#Ionicons) format("svg");font-weight:400;font-style:normal}#menu .footer .icon-help:before,.badge-editable:hover:before,.icon-alert:before,.icon-help:before,.ion,.ion-alert-circled:before,.ion-alert:before,.ion-android-add-circle:before,.ion-android-add:before,.ion-android-alarm-clock:before,.ion-android-alert:before,.ion-android-apps:before,.ion-android-archive:before,.ion-android-arrow-back:before,.ion-android-arrow-down:before,.ion-android-arrow-dropdown-circle:before,.ion-android-arrow-dropdown:before,.ion-android-arrow-dropleft-circle:before,.ion-android-arrow-dropleft:before,.ion-android-arrow-dropright-circle:before,.ion-android-arrow-dropright:before,.ion-android-arrow-dropup-circle:before,.ion-android-arrow-dropup:before,.ion-android-arrow-forward:before,.ion-android-arrow-up:before,.ion-android-attach:before,.ion-android-bar:before,.ion-android-bicycle:before,.ion-android-boat:before,.ion-android-bookmark:before,.ion-android-bulb:before,.ion-android-bus:before,.ion-android-calendar:before,.ion-android-call:before,.ion-android-camera:before,.ion-android-cancel:before,.ion-android-car:before,.ion-android-cart:before,.ion-android-chat:before,.ion-android-checkbox-blank:before,.ion-android-checkbox-outline-blank:before,.ion-android-checkbox-outline:before,.ion-android-checkbox:before,.ion-android-checkmark-circle:before,.ion-android-clipboard:before,.ion-android-close:before,.ion-android-cloud-circle:before,.ion-android-cloud-done:before,.ion-android-cloud-outline:before,.ion-android-cloud:before,.ion-android-color-palette:before,.ion-android-compass:before,.ion-android-contact:before,.ion-android-contacts:before,.ion-android-contract:before,.ion-android-create:before,.ion-android-delete:before,.ion-android-desktop:before,.ion-android-document:before,.ion-android-done-all:before,.ion-android-done:before,.ion-android-download:before,.ion-android-drafts:before,.ion-android-exit:before,.ion-android-expand:before,.ion-android-favorite-outline:before,.ion-android-favorite:before,.ion-android-film:before,.ion-android-folder-open:before,.ion-android-folder:before,.ion-android-funnel:before,.ion-android-globe:before,.ion-android-hand:before,.ion-android-hangout:before,.ion-android-happy:before,.ion-android-home:before,.ion-android-image:before,.ion-android-laptop:before,.ion-android-list:before,.ion-android-locate:before,.ion-android-lock:before,.ion-android-mail:before,.ion-android-map:before,.ion-android-menu:before,.ion-android-microphone-off:before,.ion-android-microphone:before,.ion-android-more-horizontal:before,.ion-android-more-vertical:before,.ion-android-navigate:before,.ion-android-notifications-none:before,.ion-android-notifications-off:before,.ion-android-notifications:before,.ion-android-open:before,.ion-android-options:before,.ion-android-people:before,.ion-android-person-add:before,.ion-android-person:before,.ion-android-phone-landscape:before,.ion-android-phone-portrait:before,.ion-android-pin:before,.ion-android-plane:before,.ion-android-playstore:before,.ion-android-print:before,.ion-android-radio-button-off:before,.ion-android-radio-button-on:before,.ion-android-refresh:before,.ion-android-remove-circle:before,.ion-android-remove:before,.ion-android-restaurant:before,.ion-android-sad:before,.ion-android-search:before,.ion-android-send:before,.ion-android-settings:before,.ion-android-share-alt:before,.ion-android-share:before,.ion-android-star-half:before,.ion-android-star-outline:before,.ion-android-star:before,.ion-android-stopwatch:before,.ion-android-subway:before,.ion-android-sunny:before,.ion-android-sync:before,.ion-android-textsms:before,.ion-android-time:before,.ion-android-train:before,.ion-android-unlock:before,.ion-android-upload:before,.ion-android-volume-down:before,.ion-android-volume-mute:before,.ion-android-volume-off:before,.ion-android-volume-up:before,.ion-android-walk:before,.ion-android-warning:before,.ion-android-watch:before,.ion-android-wifi:before,.ion-aperture:before,.ion-archive:before,.ion-arrow-down-a:before,.ion-arrow-down-b:before,.ion-arrow-down-c:before,.ion-arrow-expand:before,.ion-arrow-graph-down-left:before,.ion-arrow-graph-down-right:before,.ion-arrow-graph-up-left:before,.ion-arrow-graph-up-right:before,.ion-arrow-left-a:before,.ion-arrow-left-b:before,.ion-arrow-left-c:before,.ion-arrow-move:before,.ion-arrow-resize:before,.ion-arrow-return-left:before,.ion-arrow-return-right:before,.ion-arrow-right-a:before,.ion-arrow-right-b:before,.ion-arrow-right-c:before,.ion-arrow-shrink:before,.ion-arrow-swap:before,.ion-arrow-up-a:before,.ion-arrow-up-b:before,.ion-arrow-up-c:before,.ion-asterisk:before,.ion-at:before,.ion-backspace-outline:before,.ion-backspace:before,.ion-bag:before,.ion-battery-charging:before,.ion-battery-empty:before,.ion-battery-full:before,.ion-battery-half:before,.ion-battery-low:before,.ion-beaker:before,.ion-beer:before,.ion-bluetooth:before,.ion-bonfire:before,.ion-bookmark:before,.ion-bowtie:before,.ion-briefcase:before,.ion-bug:before,.ion-calculator:before,.ion-calendar:before,.ion-camera:before,.ion-card:before,.ion-cash:before,.ion-chatbox-working:before,.ion-chatbox:before,.ion-chatboxes:before,.ion-chatbubble-working:before,.ion-chatbubble:before,.ion-chatbubbles:before,.ion-checkmark-circled:before,.ion-checkmark-round:before,.ion-checkmark:before,.ion-chevron-down:before,.ion-chevron-left:before,.ion-chevron-right:before,.ion-chevron-up:before,.ion-clipboard:before,.ion-clock:before,.ion-close-circled:before,.ion-close-round:before,.ion-close:before,.ion-closed-captioning:before,.ion-cloud:before,.ion-code-download:before,.ion-code-working:before,.ion-code:before,.ion-coffee:before,.ion-compass:before,.ion-compose:before,.ion-connection-bars:before,.ion-contrast:before,.ion-crop:before,.ion-cube:before,.ion-disc:before,.ion-document-text:before,.ion-document:before,.ion-drag:before,.ion-earth:before,.ion-easel:before,.ion-edit:before,.ion-egg:before,.ion-eject:before,.ion-email-unread:before,.ion-email:before,.ion-erlenmeyer-flask-bubbles:before,.ion-erlenmeyer-flask:before,.ion-eye-disabled:before,.ion-eye:before,.ion-female:before,.ion-filing:before,.ion-film-marker:before,.ion-fireball:before,.ion-flag:before,.ion-flame:before,.ion-flash-off:before,.ion-flash:before,.ion-folder:before,.ion-fork-repo:before,.ion-fork:before,.ion-forward:before,.ion-funnel:before,.ion-gear-a:before,.ion-gear-b:before,.ion-grid:before,.ion-hammer:before,.ion-happy-outline:before,.ion-happy:before,.ion-headphone:before,.ion-heart-broken:before,.ion-heart:before,.ion-help-buoy:before,.ion-help-circled:before,.ion-help:before,.ion-home:before,.ion-icecream:before,.ion-image:before,.ion-images:before,.ion-information-circled:before,.ion-information:before,.ion-ionic:before,.ion-ios-alarm-outline:before,.ion-ios-alarm:before,.ion-ios-albums-outline:before,.ion-ios-albums:before,.ion-ios-americanfootball-outline:before,.ion-ios-americanfootball:before,.ion-ios-analytics-outline:before,.ion-ios-analytics:before,.ion-ios-arrow-back:before,.ion-ios-arrow-down:before,.ion-ios-arrow-forward:before,.ion-ios-arrow-left:before,.ion-ios-arrow-right:before,.ion-ios-arrow-thin-down:before,.ion-ios-arrow-thin-left:before,.ion-ios-arrow-thin-right:before,.ion-ios-arrow-thin-up:before,.ion-ios-arrow-up:before,.ion-ios-at-outline:before,.ion-ios-at:before,.ion-ios-barcode-outline:before,.ion-ios-barcode:before,.ion-ios-baseball-outline:before,.ion-ios-baseball:before,.ion-ios-basketball-outline:before,.ion-ios-basketball:before,.ion-ios-bell-outline:before,.ion-ios-bell:before,.ion-ios-body-outline:before,.ion-ios-body:before,.ion-ios-bolt-outline:before,.ion-ios-bolt:before,.ion-ios-book-outline:before,.ion-ios-book:before,.ion-ios-bookmarks-outline:before,.ion-ios-bookmarks:before,.ion-ios-box-outline:before,.ion-ios-box:before,.ion-ios-briefcase-outline:before,.ion-ios-briefcase:before,.ion-ios-browsers-outline:before,.ion-ios-browsers:before,.ion-ios-calculator-outline:before,.ion-ios-calculator:before,.ion-ios-calendar-outline:before,.ion-ios-calendar:before,.ion-ios-camera-outline:before,.ion-ios-camera:before,.ion-ios-cart-outline:before,.ion-ios-cart:before,.ion-ios-chatboxes-outline:before,.ion-ios-chatboxes:before,.ion-ios-chatbubble-outline:before,.ion-ios-chatbubble:before,.ion-ios-checkmark-empty:before,.ion-ios-checkmark-outline:before,.ion-ios-checkmark:before,.ion-ios-circle-filled:before,.ion-ios-circle-outline:before,.ion-ios-clock-outline:before,.ion-ios-clock:before,.ion-ios-close-empty:before,.ion-ios-close-outline:before,.ion-ios-close:before,.ion-ios-cloud-download-outline:before,.ion-ios-cloud-download:before,.ion-ios-cloud-outline:before,.ion-ios-cloud-upload-outline:before,.ion-ios-cloud-upload:before,.ion-ios-cloud:before,.ion-ios-cloudy-night-outline:before,.ion-ios-cloudy-night:before,.ion-ios-cloudy-outline:before,.ion-ios-cloudy:before,.ion-ios-cog-outline:before,.ion-ios-cog:before,.ion-ios-color-filter-outline:before,.ion-ios-color-filter:before,.ion-ios-color-wand-outline:before,.ion-ios-color-wand:before,.ion-ios-compose-outline:before,.ion-ios-compose:before,.ion-ios-contact-outline:before,.ion-ios-contact:before,.ion-ios-copy-outline:before,.ion-ios-copy:before,.ion-ios-crop-strong:before,.ion-ios-crop:before,.ion-ios-download-outline:before,.ion-ios-download:before,.ion-ios-drag:before,.ion-ios-email-outline:before,.ion-ios-email:before,.ion-ios-eye-outline:before,.ion-ios-eye:before,.ion-ios-fastforward-outline:before,.ion-ios-fastforward:before,.ion-ios-filing-outline:before,.ion-ios-filing:before,.ion-ios-film-outline:before,.ion-ios-film:before,.ion-ios-flag-outline:before,.ion-ios-flag:before,.ion-ios-flame-outline:before,.ion-ios-flame:before,.ion-ios-flask-outline:before,.ion-ios-flask:before,.ion-ios-flower-outline:before,.ion-ios-flower:before,.ion-ios-folder-outline:before,.ion-ios-folder:before,.ion-ios-football-outline:before,.ion-ios-football:before,.ion-ios-game-controller-a-outline:before,.ion-ios-game-controller-a:before,.ion-ios-game-controller-b-outline:before,.ion-ios-game-controller-b:before,.ion-ios-gear-outline:before,.ion-ios-gear:before,.ion-ios-glasses-outline:before,.ion-ios-glasses:before,.ion-ios-grid-view-outline:before,.ion-ios-grid-view:before,.ion-ios-heart-outline:before,.ion-ios-heart:before,.ion-ios-help-empty:before,.ion-ios-help-outline:before,.ion-ios-help:before,.ion-ios-home-outline:before,.ion-ios-home:before,.ion-ios-infinite-outline:before,.ion-ios-infinite:before,.ion-ios-information-empty:before,.ion-ios-information-outline:before,.ion-ios-information:before,.ion-ios-ionic-outline:before,.ion-ios-keypad-outline:before,.ion-ios-keypad:before,.ion-ios-lightbulb-outline:before,.ion-ios-lightbulb:before,.ion-ios-list-outline:before,.ion-ios-list:before,.ion-ios-location-outline:before,.ion-ios-location:before,.ion-ios-locked-outline:before,.ion-ios-locked:before,.ion-ios-loop-strong:before,.ion-ios-loop:before,.ion-ios-medical-outline:before,.ion-ios-medical:before,.ion-ios-medkit-outline:before,.ion-ios-medkit:before,.ion-ios-mic-off:before,.ion-ios-mic-outline:before,.ion-ios-mic:before,.ion-ios-minus-empty:before,.ion-ios-minus-outline:before,.ion-ios-minus:before,.ion-ios-monitor-outline:before,.ion-ios-monitor:before,.ion-ios-moon-outline:before,.ion-ios-moon:before,.ion-ios-more-outline:before,.ion-ios-more:before,.ion-ios-musical-note:before,.ion-ios-musical-notes:before,.ion-ios-navigate-outline:before,.ion-ios-navigate:before,.ion-ios-nutrition-outline:before,.ion-ios-nutrition:before,.ion-ios-paper-outline:before,.ion-ios-paper:before,.ion-ios-paperplane-outline:before,.ion-ios-paperplane:before,.ion-ios-partlysunny-outline:before,.ion-ios-partlysunny:before,.ion-ios-pause-outline:before,.ion-ios-pause:before,.ion-ios-paw-outline:before,.ion-ios-paw:before,.ion-ios-people-outline:before,.ion-ios-people:before,.ion-ios-person-outline:before,.ion-ios-person:before,.ion-ios-personadd-outline:before,.ion-ios-personadd:before,.ion-ios-photos-outline:before,.ion-ios-photos:before,.ion-ios-pie-outline:before,.ion-ios-pie:before,.ion-ios-pint-outline:before,.ion-ios-pint:before,.ion-ios-play-outline:before,.ion-ios-play:before,.ion-ios-plus-empty:before,.ion-ios-plus-outline:before,.ion-ios-plus:before,.ion-ios-pricetag-outline:before,.ion-ios-pricetag:before,.ion-ios-pricetags-outline:before,.ion-ios-pricetags:before,.ion-ios-printer-outline:before,.ion-ios-printer:before,.ion-ios-pulse-strong:before,.ion-ios-pulse:before,.ion-ios-rainy-outline:before,.ion-ios-rainy:before,.ion-ios-recording-outline:before,.ion-ios-recording:before,.ion-ios-redo-outline:before,.ion-ios-redo:before,.ion-ios-refresh-empty:before,.ion-ios-refresh-outline:before,.ion-ios-refresh:before,.ion-ios-reload:before,.ion-ios-reverse-camera-outline:before,.ion-ios-reverse-camera:before,.ion-ios-rewind-outline:before,.ion-ios-rewind:before,.ion-ios-rose-outline:before,.ion-ios-rose:before,.ion-ios-search-strong:before,.ion-ios-search:before,.ion-ios-settings-strong:before,.ion-ios-settings:before,.ion-ios-shuffle-strong:before,.ion-ios-shuffle:before,.ion-ios-skipbackward-outline:before,.ion-ios-skipbackward:before,.ion-ios-skipforward-outline:before,.ion-ios-skipforward:before,.ion-ios-snowy:before,.ion-ios-speedometer-outline:before,.ion-ios-speedometer:before,.ion-ios-star-half:before,.ion-ios-star-outline:before,.ion-ios-star:before,.ion-ios-stopwatch-outline:before,.ion-ios-stopwatch:before,.ion-ios-sunny-outline:before,.ion-ios-sunny:before,.ion-ios-telephone-outline:before,.ion-ios-telephone:before,.ion-ios-tennisball-outline:before,.ion-ios-tennisball:before,.ion-ios-thunderstorm-outline:before,.ion-ios-thunderstorm:before,.ion-ios-time-outline:before,.ion-ios-time:before,.ion-ios-timer-outline:before,.ion-ios-timer:before,.ion-ios-toggle-outline:before,.ion-ios-toggle:before,.ion-ios-trash-outline:before,.ion-ios-trash:before,.ion-ios-undo-outline:before,.ion-ios-undo:before,.ion-ios-unlocked-outline:before,.ion-ios-unlocked:before,.ion-ios-upload-outline:before,.ion-ios-upload:before,.ion-ios-videocam-outline:before,.ion-ios-videocam:before,.ion-ios-volume-high:before,.ion-ios-volume-low:before,.ion-ios-wineglass-outline:before,.ion-ios-wineglass:before,.ion-ios-world-outline:before,.ion-ios-world:before,.ion-ipad:before,.ion-iphone:before,.ion-ipod:before,.ion-jet:before,.ion-key:before,.ion-knife:before,.ion-laptop:before,.ion-leaf:before,.ion-levels:before,.ion-lightbulb:before,.ion-link:before,.ion-load-a:before,.ion-load-b:before,.ion-load-c:before,.ion-load-d:before,.ion-location:before,.ion-lock-combination:before,.ion-locked:before,.ion-log-in:before,.ion-log-out:before,.ion-loop:before,.ion-magnet:before,.ion-male:before,.ion-man:before,.ion-map:before,.ion-medkit:before,.ion-merge:before,.ion-mic-a:before,.ion-mic-b:before,.ion-mic-c:before,.ion-minus-circled:before,.ion-minus-round:before,.ion-minus:before,.ion-model-s:before,.ion-monitor:before,.ion-more:before,.ion-mouse:before,.ion-music-note:before,.ion-navicon-round:before,.ion-navicon:before,.ion-navigate:before,.ion-network:before,.ion-no-smoking:before,.ion-nuclear:before,.ion-outlet:before,.ion-paintbrush:before,.ion-paintbucket:before,.ion-paper-airplane:before,.ion-paperclip:before,.ion-pause:before,.ion-person-add:before,.ion-person-stalker:before,.ion-person:before,.ion-pie-graph:before,.ion-pin:before,.ion-pinpoint:before,.ion-pizza:before,.ion-plane:before,.ion-planet:before,.ion-play:before,.ion-playstation:before,.ion-plus-circled:before,.ion-plus-round:before,.ion-plus:before,.ion-podium:before,.ion-pound:before,.ion-power:before,.ion-pricetag:before,.ion-pricetags:before,.ion-printer:before,.ion-pull-request:before,.ion-qr-scanner:before,.ion-quote:before,.ion-radio-waves:before,.ion-record:before,.ion-refresh:before,.ion-reply-all:before,.ion-reply:before,.ion-ribbon-a:before,.ion-ribbon-b:before,.ion-sad-outline:before,.ion-sad:before,.ion-scissors:before,.ion-search:before,.ion-settings:before,.ion-share:before,.ion-shuffle:before,.ion-skip-backward:before,.ion-skip-forward:before,.ion-social-android-outline:before,.ion-social-android:before,.ion-social-angular-outline:before,.ion-social-angular:before,.ion-social-apple-outline:before,.ion-social-apple:before,.ion-social-bitcoin-outline:before,.ion-social-bitcoin:before,.ion-social-buffer-outline:before,.ion-social-buffer:before,.ion-social-chrome-outline:before,.ion-social-chrome:before,.ion-social-codepen-outline:before,.ion-social-codepen:before,.ion-social-css3-outline:before,.ion-social-css3:before,.ion-social-designernews-outline:before,.ion-social-designernews:before,.ion-social-dribbble-outline:before,.ion-social-dribbble:before,.ion-social-dropbox-outline:before,.ion-social-dropbox:before,.ion-social-euro-outline:before,.ion-social-euro:before,.ion-social-facebook-outline:before,.ion-social-facebook:before,.ion-social-foursquare-outline:before,.ion-social-foursquare:before,.ion-social-freebsd-devil:before,.ion-social-github-outline:before,.ion-social-github:before,.ion-social-google-outline:before,.ion-social-google:before,.ion-social-googleplus-outline:before,.ion-social-googleplus:before,.ion-social-hackernews-outline:before,.ion-social-hackernews:before,.ion-social-html5-outline:before,.ion-social-html5:before,.ion-social-instagram-outline:before,.ion-social-instagram:before,.ion-social-javascript-outline:before,.ion-social-javascript:before,.ion-social-linkedin-outline:before,.ion-social-linkedin:before,.ion-social-markdown:before,.ion-social-nodejs:before,.ion-social-octocat:before,.ion-social-pinterest-outline:before,.ion-social-pinterest:before,.ion-social-python:before,.ion-social-reddit-outline:before,.ion-social-reddit:before,.ion-social-rss-outline:before,.ion-social-rss:before,.ion-social-sass:before,.ion-social-skype-outline:before,.ion-social-skype:before,.ion-social-snapchat-outline:before,.ion-social-snapchat:before,.ion-social-tumblr-outline:before,.ion-social-tumblr:before,.ion-social-tux:before,.ion-social-twitch-outline:before,.ion-social-twitch:before,.ion-social-twitter-outline:before,.ion-social-twitter:before,.ion-social-usd-outline:before,.ion-social-usd:before,.ion-social-vimeo-outline:before,.ion-social-vimeo:before,.ion-social-whatsapp-outline:before,.ion-social-whatsapp:before,.ion-social-windows-outline:before,.ion-social-windows:before,.ion-social-wordpress-outline:before,.ion-social-wordpress:before,.ion-social-yahoo-outline:before,.ion-social-yahoo:before,.ion-social-yen-outline:before,.ion-social-yen:before,.ion-social-youtube-outline:before,.ion-social-youtube:before,.ion-soup-can-outline:before,.ion-soup-can:before,.ion-speakerphone:before,.ion-speedometer:before,.ion-spoon:before,.ion-star:before,.ion-stats-bars:before,.ion-steam:before,.ion-stop:before,.ion-thermometer:before,.ion-thumbsdown:before,.ion-thumbsup:before,.ion-toggle-filled:before,.ion-toggle:before,.ion-transgender:before,.ion-trash-a:before,.ion-trash-b:before,.ion-trophy:before,.ion-tshirt-outline:before,.ion-tshirt:before,.ion-umbrella:before,.ion-university:before,.ion-unlocked:before,.ion-upload:before,.ion-usb:before,.ion-videocamera:before,.ion-volume-high:before,.ion-volume-low:before,.ion-volume-medium:before,.ion-volume-mute:before,.ion-wand:before,.ion-waterdrop:before,.ion-wifi:before,.ion-wineglass:before,.ion-woman:before,.ion-wrench:before,.ion-xbox:before,.ionicons,.text-editable:hover:after{display:inline-block;font-family:Ionicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ion-alert:before{content:"ï„"}.ion-alert-circled:before{content:"ï„€"}.ion-android-add:before{content:""}.ion-android-add-circle:before{content:"ï™"}.ion-android-alarm-clock:before{content:"ïš"}.icon-alert:before,.ion-android-alert:before{content:"ï›"}.ion-android-apps:before{content:"ïœ"}.ion-android-archive:before{content:""}.ion-android-arrow-back:before{content:""}.ion-android-arrow-down:before{content:"ï"}.ion-android-arrow-dropdown:before{content:"ïŸ"}.ion-android-arrow-dropdown-circle:before{content:"ïž"}.ion-android-arrow-dropleft:before{content:"ï¡"}.ion-android-arrow-dropleft-circle:before{content:"ï "}.ion-android-arrow-dropright:before{content:"ï£"}.ion-android-arrow-dropright-circle:before{content:"ï¢"}.ion-android-arrow-dropup:before{content:"ï¥"}.ion-android-arrow-dropup-circle:before{content:"ï¤"}.ion-android-arrow-forward:before{content:"ïŒ"}.ion-android-arrow-up:before{content:"ï¦"}.ion-android-attach:before{content:"ï§"}.ion-android-bar:before{content:"ï¨"}.ion-android-bicycle:before{content:"ï©"}.ion-android-boat:before{content:"ïª"}.ion-android-bookmark:before{content:"ï«"}.ion-android-bulb:before{content:"ï¬"}.ion-android-bus:before{content:"ï"}.ion-android-calendar:before{content:"ï‹‘"}.ion-android-call:before{content:"ï‹’"}.ion-android-camera:before{content:"ï‹“"}.ion-android-cancel:before{content:"ï®"}.ion-android-car:before{content:"ï¯"}.ion-android-cart:before{content:"ï°"}.ion-android-chat:before{content:"ï‹”"}.ion-android-checkbox:before{content:"ï´"}.ion-android-checkbox-blank:before{content:"ï±"}.ion-android-checkbox-outline:before{content:"ï³"}.ion-android-checkbox-outline-blank:before{content:"ï²"}.ion-android-checkmark-circle:before{content:"ïµ"}.ion-android-clipboard:before{content:"ï¶"}.ion-android-close:before{content:"ï‹—"}.ion-android-cloud:before{content:"ïº"}.ion-android-cloud-circle:before{content:"ï·"}.ion-android-cloud-done:before{content:"ï¸"}.ion-android-cloud-outline:before{content:"ï¹"}.ion-android-color-palette:before{content:"ï»"}.ion-android-compass:before{content:"ï¼"}.ion-android-contact:before{content:""}.ion-android-contacts:before{content:"ï‹™"}.ion-android-contract:before{content:"ï½"}.ion-android-create:before{content:"ï¾"}.ion-android-delete:before{content:"ï¿"}.ion-android-desktop:before{content:""}.ion-android-document:before{content:"ïŽ"}.ion-android-done:before{content:""}.ion-android-done-all:before{content:""}.ion-android-download:before{content:"ï‹"}.ion-android-drafts:before{content:""}.ion-android-exit:before{content:""}.ion-android-expand:before{content:""}.ion-android-favorite:before{content:""}.ion-android-favorite-outline:before{content:""}.ion-android-film:before{content:""}.ion-android-folder:before{content:"ï‹ "}.ion-android-folder-open:before{content:""}.ion-android-funnel:before{content:""}.ion-android-globe:before{content:""}.ion-android-hand:before{content:"ï‹£"}.ion-android-hangout:before{content:"ïŽ"}.ion-android-happy:before{content:""}.ion-android-home:before{content:"ïŽ"}.ion-android-image:before{content:""}.ion-android-laptop:before{content:"ïŽ"}.ion-android-list:before{content:""}.ion-android-locate:before{content:"ï‹©"}.ion-android-lock:before{content:""}.ion-android-mail:before{content:"ï‹«"}.ion-android-map:before{content:""}.ion-android-menu:before{content:""}.ion-android-microphone:before{content:""}.ion-android-microphone-off:before{content:""}.ion-android-more-horizontal:before{content:""}.ion-android-more-vertical:before{content:""}.ion-android-navigate:before{content:""}.ion-android-notifications:before{content:""}.ion-android-notifications-none:before{content:""}.ion-android-notifications-off:before{content:""}.ion-android-open:before{content:""}.ion-android-options:before{content:"ïŽ"}.ion-android-people:before{content:""}.ion-android-person:before{content:"ïŽ "}.ion-android-person-add:before{content:""}.ion-android-phone-landscape:before{content:""}.ion-android-phone-portrait:before{content:""}.ion-android-pin:before{content:""}.ion-android-plane:before{content:""}.ion-android-playstore:before{content:"ï‹°"}.ion-android-print:before{content:""}.ion-android-radio-button-off:before{content:""}.ion-android-radio-button-on:before{content:""}.ion-android-refresh:before{content:""}.ion-android-remove:before{content:"ï‹´"}.ion-android-remove-circle:before{content:""}.ion-android-restaurant:before{content:""}.ion-android-sad:before{content:""}.ion-android-search:before{content:""}.ion-android-send:before{content:"ï‹¶"}.ion-android-settings:before{content:"ï‹·"}.ion-android-share:before{content:""}.ion-android-share-alt:before{content:""}.ion-android-star:before{content:""}.ion-android-star-half:before{content:"ïŽ"}.ion-android-star-outline:before{content:""}.ion-android-stopwatch:before{content:""}.ion-android-subway:before{content:""}.ion-android-sunny:before{content:""}.ion-android-sync:before{content:""}.ion-android-textsms:before{content:""}.ion-android-time:before{content:""}.ion-android-train:before{content:""}.ion-android-unlock:before{content:""}.ion-android-upload:before{content:""}.ion-android-volume-down:before{content:""}.ion-android-volume-mute:before{content:""}.ion-android-volume-off:before{content:""}.ion-android-volume-up:before{content:""}.ion-android-walk:before{content:""}.ion-android-warning:before{content:""}.ion-android-watch:before{content:""}.ion-android-wifi:before{content:""}.ion-aperture:before{content:""}.ion-archive:before{content:"ï„‚"}.ion-arrow-down-a:before{content:""}.ion-arrow-down-b:before{content:"ï„„"}.ion-arrow-down-c:before{content:"ï„…"}.ion-arrow-expand:before{content:""}.ion-arrow-graph-down-left:before{content:""}.ion-arrow-graph-down-right:before{content:"ï‰ "}.ion-arrow-graph-up-left:before{content:""}.ion-arrow-graph-up-right:before{content:""}.ion-arrow-left-a:before{content:""}.ion-arrow-left-b:before{content:""}.ion-arrow-left-c:before{content:""}.ion-arrow-move:before{content:""}.ion-arrow-resize:before{content:""}.ion-arrow-return-left:before{content:""}.ion-arrow-return-right:before{content:""}.ion-arrow-right-a:before{content:""}.ion-arrow-right-b:before{content:""}.ion-arrow-right-c:before{content:"ï„‹"}.ion-arrow-shrink:before{content:""}.ion-arrow-swap:before{content:""}.ion-arrow-up-a:before{content:""}.ion-arrow-up-b:before{content:"ï„"}.ion-arrow-up-c:before{content:""}.ion-asterisk:before{content:""}.ion-at:before{content:"ï„"}.ion-backspace:before{content:""}.ion-backspace-outline:before{content:""}.ion-bag:before{content:"ï„"}.ion-battery-charging:before{content:"ï„‘"}.ion-battery-empty:before{content:"ï„’"}.ion-battery-full:before{content:"ï„“"}.ion-battery-half:before{content:"ï„”"}.ion-battery-low:before{content:"ï„•"}.ion-beaker:before{content:""}.ion-beer:before{content:""}.ion-bluetooth:before{content:"ï„–"}.ion-bonfire:before{content:""}.ion-bookmark:before{content:""}.ion-bowtie:before{content:"ï€"}.ion-briefcase:before{content:""}.ion-bug:before{content:""}.ion-calculator:before{content:"ï‰"}.ion-calendar:before{content:"ï„—"}.ion-camera:before{content:""}.ion-card:before{content:"ï„™"}.ion-cash:before{content:""}.ion-chatbox:before{content:"ï„›"}.ion-chatbox-working:before{content:""}.ion-chatboxes:before{content:""}.ion-chatbubble:before{content:""}.ion-chatbubble-working:before{content:"ï„"}.ion-chatbubbles:before{content:""}.ion-checkmark:before{content:"ï„¢"}.ion-checkmark-circled:before{content:"ï„ "}.ion-checkmark-round:before{content:"ï„¡"}.ion-chevron-down:before{content:"ï„£"}.ion-chevron-left:before{content:""}.ion-chevron-right:before{content:"ï„¥"}.ion-chevron-up:before{content:""}.ion-clipboard:before{content:"ï„§"}.ion-clock:before{content:""}.ion-close:before{content:""}.ion-close-circled:before{content:""}.ion-close-round:before{content:"ï„©"}.ion-closed-captioning:before{content:""}.ion-cloud:before{content:"ï„«"}.ion-code:before{content:""}.ion-code-download:before{content:""}.ion-code-working:before{content:""}.ion-coffee:before{content:""}.ion-compass:before{content:""}.ion-compose:before{content:""}.ion-connection-bars:before{content:""}.ion-contrast:before{content:""}.ion-crop:before{content:"ï"}.ion-cube:before{content:""}.ion-disc:before{content:"ï„"}.ion-document:before{content:""}.ion-document-text:before{content:"ï„®"}.ion-drag:before{content:"ï„°"}.ion-earth:before{content:""}.ion-easel:before{content:"ï‚"}.ion-edit:before{content:""}.ion-egg:before{content:""}.ion-eject:before{content:""}.ion-email:before{content:""}.ion-email-unread:before{content:"ïƒ"}.ion-erlenmeyer-flask:before{content:"ï…"}.ion-erlenmeyer-flask-bubbles:before{content:"ï„"}.ion-eye:before{content:""}.ion-eye-disabled:before{content:""}.ion-female:before{content:""}.ion-filing:before{content:"ï„´"}.ion-film-marker:before{content:""}.ion-fireball:before{content:""}.ion-flag:before{content:""}.ion-flame:before{content:""}.ion-flash:before{content:"ï„·"}.ion-flash-off:before{content:"ï„¶"}.ion-folder:before{content:""}.ion-fork:before{content:""}.ion-fork-repo:before{content:"ï‹€"}.ion-forward:before{content:""}.ion-funnel:before{content:""}.ion-gear-a:before{content:""}.ion-gear-b:before{content:""}.ion-grid:before{content:"ï„¿"}.ion-hammer:before{content:""}.ion-happy:before{content:""}.ion-happy-outline:before{content:"ï†"}.ion-headphone:before{content:"ï…€"}.ion-heart:before{content:"ï…"}.ion-heart-broken:before{content:"ïŒ"}.ion-help:before{content:"ï…ƒ"}.ion-help-buoy:before{content:""}.ion-help-circled:before{content:"ï…‚"}.ion-home:before{content:"ï…„"}.ion-icecream:before{content:""}.ion-image:before{content:"ï…‡"}.ion-images:before{content:"ï…ˆ"}.ion-information:before{content:"ï…Š"}.ion-information-circled:before{content:"ï…‰"}.ion-ionic:before{content:"ï…‹"}.ion-ios-alarm:before{content:"ïˆ"}.ion-ios-alarm-outline:before{content:"ï‡"}.ion-ios-albums:before{content:"ïŠ"}.ion-ios-albums-outline:before{content:"ï‰"}.ion-ios-americanfootball:before{content:"ïŒ"}.ion-ios-americanfootball-outline:before{content:"ï‹"}.ion-ios-analytics:before{content:"ïŽ"}.ion-ios-analytics-outline:before{content:"ï"}.ion-ios-arrow-back:before{content:"ï"}.ion-ios-arrow-down:before{content:"ï"}.ion-ios-arrow-forward:before{content:"ï‘"}.ion-ios-arrow-left:before{content:"ï’"}.ion-ios-arrow-right:before{content:"ï“"}.ion-ios-arrow-thin-down:before{content:"ï”"}.ion-ios-arrow-thin-left:before{content:"ï•"}.ion-ios-arrow-thin-right:before{content:"ï–"}.ion-ios-arrow-thin-up:before{content:"ï—"}.ion-ios-arrow-up:before{content:"ï˜"}.ion-ios-at:before{content:"ïš"}.ion-ios-at-outline:before{content:"ï™"}.ion-ios-barcode:before{content:"ïœ"}.ion-ios-barcode-outline:before{content:"ï›"}.ion-ios-baseball:before{content:"ïž"}.ion-ios-baseball-outline:before{content:"ï"}.ion-ios-basketball:before{content:"ï "}.ion-ios-basketball-outline:before{content:"ïŸ"}.ion-ios-bell:before{content:"ï¢"}.ion-ios-bell-outline:before{content:"ï¡"}.ion-ios-body:before{content:"ï¤"}.ion-ios-body-outline:before{content:"ï£"}.ion-ios-bolt:before{content:"ï¦"}.ion-ios-bolt-outline:before{content:"ï¥"}.ion-ios-book:before{content:"ï¨"}.ion-ios-book-outline:before{content:"ï§"}.ion-ios-bookmarks:before{content:"ïª"}.ion-ios-bookmarks-outline:before{content:"ï©"}.ion-ios-box:before{content:"ï¬"}.ion-ios-box-outline:before{content:"ï«"}.ion-ios-briefcase:before{content:"ï®"}.ion-ios-briefcase-outline:before{content:"ï"}.ion-ios-browsers:before{content:"ï°"}.ion-ios-browsers-outline:before{content:"ï¯"}.ion-ios-calculator:before{content:"ï²"}.ion-ios-calculator-outline:before{content:"ï±"}.ion-ios-calendar:before{content:"ï´"}.ion-ios-calendar-outline:before{content:"ï³"}.ion-ios-camera:before{content:"ï¶"}.ion-ios-camera-outline:before{content:"ïµ"}.ion-ios-cart:before{content:"ï¸"}.ion-ios-cart-outline:before{content:"ï·"}.ion-ios-chatboxes:before{content:"ïº"}.ion-ios-chatboxes-outline:before{content:"ï¹"}.ion-ios-chatbubble:before{content:"ï¼"}.ion-ios-chatbubble-outline:before{content:"ï»"}.ion-ios-checkmark:before{content:"ï¿"}.ion-ios-checkmark-empty:before{content:"ï½"}.ion-ios-checkmark-outline:before{content:"ï¾"}.ion-ios-circle-filled:before{content:"ï€"}.ion-ios-circle-outline:before{content:"ï"}.ion-ios-clock:before{content:"ïƒ"}.ion-ios-clock-outline:before{content:"ï‚"}.ion-ios-close:before{content:"ï†"}.ion-ios-close-empty:before{content:"ï„"}.ion-ios-close-outline:before{content:"ï…"}.ion-ios-cloud:before{content:"ïŒ"}.ion-ios-cloud-download:before{content:"ïˆ"}.ion-ios-cloud-download-outline:before{content:"ï‡"}.ion-ios-cloud-outline:before{content:"ï‰"}.ion-ios-cloud-upload:before{content:"ï‹"}.ion-ios-cloud-upload-outline:before{content:"ïŠ"}.ion-ios-cloudy:before{content:"ï"}.ion-ios-cloudy-night:before{content:"ïŽ"}.ion-ios-cloudy-night-outline:before{content:"ï"}.ion-ios-cloudy-outline:before{content:"ï"}.ion-ios-cog:before{content:"ï’"}.ion-ios-cog-outline:before{content:"ï‘"}.ion-ios-color-filter:before{content:"ï”"}.ion-ios-color-filter-outline:before{content:"ï“"}.ion-ios-color-wand:before{content:"ï–"}.ion-ios-color-wand-outline:before{content:"ï•"}.ion-ios-compose:before{content:"ï˜"}.ion-ios-compose-outline:before{content:"ï—"}.ion-ios-contact:before{content:"ïš"}.ion-ios-contact-outline:before{content:"ï™"}.ion-ios-copy:before{content:"ïœ"}.ion-ios-copy-outline:before{content:"ï›"}.ion-ios-crop:before{content:"ïž"}.ion-ios-crop-strong:before{content:"ï"}.ion-ios-download:before{content:"ï "}.ion-ios-download-outline:before{content:"ïŸ"}.ion-ios-drag:before{content:"ï¡"}.ion-ios-email:before{content:"ï£"}.ion-ios-email-outline:before{content:"ï¢"}.ion-ios-eye:before{content:"ï¥"}.ion-ios-eye-outline:before{content:"ï¤"}.ion-ios-fastforward:before{content:"ï§"}.ion-ios-fastforward-outline:before{content:"ï¦"}.ion-ios-filing:before{content:"ï©"}.ion-ios-filing-outline:before{content:"ï¨"}.ion-ios-film:before{content:"ï«"}.ion-ios-film-outline:before{content:"ïª"}.ion-ios-flag:before{content:"ï"}.ion-ios-flag-outline:before{content:"ï¬"}.ion-ios-flame:before{content:"ï¯"}.ion-ios-flame-outline:before{content:"ï®"}.ion-ios-flask:before{content:"ï±"}.ion-ios-flask-outline:before{content:"ï°"}.ion-ios-flower:before{content:"ï³"}.ion-ios-flower-outline:before{content:"ï²"}.ion-ios-folder:before{content:"ïµ"}.ion-ios-folder-outline:before{content:"ï´"}.ion-ios-football:before{content:"ï·"}.ion-ios-football-outline:before{content:"ï¶"}.ion-ios-game-controller-a:before{content:"ï¹"}.ion-ios-game-controller-a-outline:before{content:"ï¸"}.ion-ios-game-controller-b:before{content:"ï»"}.ion-ios-game-controller-b-outline:before{content:"ïº"}.ion-ios-gear:before{content:"ï½"}.ion-ios-gear-outline:before{content:"ï¼"}.ion-ios-glasses:before{content:"ï¿"}.ion-ios-glasses-outline:before{content:"ï¾"}.ion-ios-grid-view:before{content:"ï‘"}.ion-ios-grid-view-outline:before{content:"ï‘€"}.ion-ios-heart:before{content:""}.ion-ios-heart-outline:before{content:"ï‘‚"}.ion-ios-help:before{content:""}.ion-ios-help-empty:before{content:"ï‘„"}#menu .footer .icon-help:before,.icon-help:before,.ion-ios-help-outline:before{content:"ï‘…"}.ion-ios-home:before{content:""}.ion-ios-home-outline:before{content:""}.ion-ios-infinite:before{content:""}.ion-ios-infinite-outline:before{content:""}.ion-ios-information:before{content:"ï‘"}.ion-ios-information-empty:before{content:"ï‘‹"}.ion-ios-information-outline:before{content:""}.ion-ios-ionic-outline:before{content:""}.ion-ios-keypad:before{content:"ï‘"}.ion-ios-keypad-outline:before{content:"ï‘"}.ion-ios-lightbulb:before{content:"ï‘’"}.ion-ios-lightbulb-outline:before{content:"ï‘‘"}.ion-ios-list:before{content:"ï‘”"}.ion-ios-list-outline:before{content:"ï‘“"}.ion-ios-location:before{content:"ï‘–"}.ion-ios-location-outline:before{content:"ï‘•"}.ion-ios-locked:before{content:""}.ion-ios-locked-outline:before{content:"ï‘—"}.ion-ios-loop:before{content:""}.ion-ios-loop-strong:before{content:"ï‘™"}.ion-ios-medical:before{content:""}.ion-ios-medical-outline:before{content:"ï‘›"}.ion-ios-medkit:before{content:""}.ion-ios-medkit-outline:before{content:"ï‘"}.ion-ios-mic:before{content:"ï‘¡"}.ion-ios-mic-off:before{content:""}.ion-ios-mic-outline:before{content:"ï‘ "}.ion-ios-minus:before{content:""}.ion-ios-minus-empty:before{content:"ï‘¢"}.ion-ios-minus-outline:before{content:"ï‘£"}.ion-ios-monitor:before{content:""}.ion-ios-monitor-outline:before{content:"ï‘¥"}.ion-ios-moon:before{content:""}.ion-ios-moon-outline:before{content:"ï‘§"}.ion-ios-more:before{content:""}.ion-ios-more-outline:before{content:"ï‘©"}.ion-ios-musical-note:before{content:"ï‘«"}.ion-ios-musical-notes:before{content:""}.ion-ios-navigate:before{content:"ï‘®"}.ion-ios-navigate-outline:before{content:"ï‘"}.ion-ios-nutrition:before{content:"ï‘°"}.ion-ios-nutrition-outline:before{content:""}.ion-ios-paper:before{content:""}.ion-ios-paper-outline:before{content:""}.ion-ios-paperplane:before{content:"ï‘´"}.ion-ios-paperplane-outline:before{content:""}.ion-ios-partlysunny:before{content:"ï‘¶"}.ion-ios-partlysunny-outline:before{content:""}.ion-ios-pause:before{content:""}.ion-ios-pause-outline:before{content:"ï‘·"}.ion-ios-paw:before{content:""}.ion-ios-paw-outline:before{content:""}.ion-ios-people:before{content:""}.ion-ios-people-outline:before{content:"ï‘»"}.ion-ios-person:before{content:""}.ion-ios-person-outline:before{content:""}.ion-ios-personadd:before{content:"ï’€"}.ion-ios-personadd-outline:before{content:"ï‘¿"}.ion-ios-photos:before{content:"ï’‚"}.ion-ios-photos-outline:before{content:"ï’"}.ion-ios-pie:before{content:"ï’„"}.ion-ios-pie-outline:before{content:"ï’ƒ"}.ion-ios-pint:before{content:"ï’†"}.ion-ios-pint-outline:before{content:"ï’…"}.ion-ios-play:before{content:"ï’ˆ"}.ion-ios-play-outline:before{content:"ï’‡"}.ion-ios-plus:before{content:"ï’‹"}.ion-ios-plus-empty:before{content:"ï’‰"}.ion-ios-plus-outline:before{content:"ï’Š"}.ion-ios-pricetag:before{content:"ï’"}.ion-ios-pricetag-outline:before{content:"ï’Œ"}.ion-ios-pricetags:before{content:"ï’"}.ion-ios-pricetags-outline:before{content:"ï’Ž"}.ion-ios-printer:before{content:"ï’‘"}.ion-ios-printer-outline:before{content:"ï’"}.ion-ios-pulse:before{content:"ï’“"}.ion-ios-pulse-strong:before{content:"ï’’"}.ion-ios-rainy:before{content:"ï’•"}.ion-ios-rainy-outline:before{content:"ï’”"}.ion-ios-recording:before{content:"ï’—"}.ion-ios-recording-outline:before{content:"ï’–"}.ion-ios-redo:before{content:"ï’™"}.ion-ios-redo-outline:before{content:"ï’˜"}.ion-ios-refresh:before{content:"ï’œ"}.ion-ios-refresh-empty:before{content:"ï’š"}.ion-ios-refresh-outline:before{content:"ï’›"}.ion-ios-reload:before{content:"ï’"}.ion-ios-reverse-camera:before{content:"ï’Ÿ"}.ion-ios-reverse-camera-outline:before{content:"ï’ž"}.ion-ios-rewind:before{content:"ï’¡"}.ion-ios-rewind-outline:before{content:"ï’ "}.ion-ios-rose:before{content:"ï’£"}.ion-ios-rose-outline:before{content:"ï’¢"}.ion-ios-search:before{content:"ï’¥"}.ion-ios-search-strong:before{content:"ï’¤"}.ion-ios-settings:before{content:"ï’§"}.ion-ios-settings-strong:before{content:"ï’¦"}.ion-ios-shuffle:before{content:"ï’©"}.ion-ios-shuffle-strong:before{content:"ï’¨"}.ion-ios-skipbackward:before{content:"ï’«"}.ion-ios-skipbackward-outline:before{content:"ï’ª"}.ion-ios-skipforward:before{content:"ï’"}.ion-ios-skipforward-outline:before{content:"ï’¬"}.ion-ios-snowy:before{content:"ï’®"}.ion-ios-speedometer:before{content:"ï’°"}.ion-ios-speedometer-outline:before{content:"ï’¯"}.ion-ios-star:before{content:"ï’³"}.ion-ios-star-half:before{content:"ï’±"}.ion-ios-star-outline:before{content:"ï’²"}.ion-ios-stopwatch:before{content:"ï’µ"}.ion-ios-stopwatch-outline:before{content:"ï’´"}.ion-ios-sunny:before{content:"ï’·"}.ion-ios-sunny-outline:before{content:"ï’¶"}.ion-ios-telephone:before{content:"ï’¹"}.ion-ios-telephone-outline:before{content:"ï’¸"}.ion-ios-tennisball:before{content:"ï’»"}.ion-ios-tennisball-outline:before{content:"ï’º"}.ion-ios-thunderstorm:before{content:"ï’½"}.ion-ios-thunderstorm-outline:before{content:"ï’¼"}.ion-ios-time:before{content:"ï’¿"}.ion-ios-time-outline:before{content:"ï’¾"}.ion-ios-timer:before{content:"ï“"}.ion-ios-timer-outline:before{content:"ï“€"}.ion-ios-toggle:before{content:""}.ion-ios-toggle-outline:before{content:"ï“‚"}.ion-ios-trash:before{content:"ï“…"}.ion-ios-trash-outline:before{content:"ï“„"}.ion-ios-undo:before{content:""}.ion-ios-undo-outline:before{content:""}.ion-ios-unlocked:before{content:""}.ion-ios-unlocked-outline:before{content:""}.ion-ios-upload:before{content:"ï“‹"}.ion-ios-upload-outline:before{content:""}.ion-ios-videocam:before{content:"ï“"}.ion-ios-videocam-outline:before{content:""}.ion-ios-volume-high:before{content:""}.ion-ios-volume-low:before{content:"ï“"}.ion-ios-wineglass:before{content:"ï“‘"}.ion-ios-wineglass-outline:before{content:"ï“"}.ion-ios-world:before{content:"ï““"}.ion-ios-world-outline:before{content:"ï“’"}.ion-ipad:before{content:""}.ion-iphone:before{content:""}.ion-ipod:before{content:""}.ion-jet:before{content:""}.ion-key:before{content:""}.ion-knife:before{content:""}.ion-laptop:before{content:""}.ion-leaf:before{content:""}.ion-levels:before{content:""}.ion-lightbulb:before{content:""}.ion-link:before{content:""}.ion-load-a:before{content:""}.ion-load-b:before{content:""}.ion-load-c:before{content:""}.ion-load-d:before{content:"ïŠ"}.ion-location:before{content:""}.ion-lock-combination:before{content:"ï“”"}.ion-locked:before{content:""}.ion-log-in:before{content:""}.ion-log-out:before{content:""}.ion-loop:before{content:"ïˆ"}.ion-magnet:before{content:"ïŠ "}.ion-male:before{content:""}.ion-man:before{content:""}.ion-map:before{content:""}.ion-medkit:before{content:""}.ion-merge:before{content:""}.ion-mic-a:before{content:""}.ion-mic-b:before{content:""}.ion-mic-c:before{content:""}.ion-minus:before{content:""}.ion-minus-circled:before{content:""}.ion-minus-round:before{content:""}.ion-model-s:before{content:"ï‹"}.ion-monitor:before{content:""}.ion-more:before{content:""}.ion-mouse:before{content:"ï€"}.ion-music-note:before{content:""}.ion-navicon:before{content:""}.ion-navicon-round:before{content:"ïˆ"}.ion-navigate:before{content:""}.ion-network:before{content:"ï"}.ion-no-smoking:before{content:"ï‹‚"}.ion-nuclear:before{content:""}.ion-outlet:before{content:"ï‚"}.ion-paintbrush:before{content:"ï“•"}.ion-paintbucket:before{content:"ï“–"}.ion-paper-airplane:before{content:""}.ion-paperclip:before{content:"ïˆ"}.ion-pause:before{content:"ïˆ"}.ion-person:before{content:""}.ion-person-add:before{content:""}.ion-person-stalker:before{content:""}.ion-pie-graph:before{content:""}.ion-pin:before{content:""}.ion-pinpoint:before{content:""}.ion-pizza:before{content:""}.ion-plane:before{content:""}.ion-planet:before{content:"ïƒ"}.ion-play:before{content:""}.ion-playstation:before{content:""}.ion-plus:before{content:""}.ion-plus-circled:before{content:""}.ion-plus-round:before{content:""}.ion-podium:before{content:"ï„"}.ion-pound:before{content:""}.ion-power:before{content:""}.ion-pricetag:before{content:""}.ion-pricetags:before{content:""}.ion-printer:before{content:""}.ion-pull-request:before{content:"ï…"}.ion-qr-scanner:before{content:"ï†"}.ion-quote:before{content:"ï‡"}.ion-radio-waves:before{content:""}.ion-record:before{content:""}.ion-refresh:before{content:""}.ion-reply:before{content:""}.ion-reply-all:before{content:"ïˆ"}.ion-ribbon-a:before{content:"ïˆ"}.ion-ribbon-b:before{content:"ï‰"}.ion-sad:before{content:"ïŠ"}.ion-sad-outline:before{content:"ï“—"}.ion-scissors:before{content:"ï‹"}.ion-search:before{content:""}.ion-settings:before{content:"ïŠ"}.ion-share:before{content:"ïˆ "}.ion-shuffle:before{content:""}.ion-skip-backward:before{content:""}.ion-skip-forward:before{content:""}.ion-social-android:before{content:""}.ion-social-android-outline:before{content:""}.ion-social-angular:before{content:"ï“™"}.ion-social-angular-outline:before{content:""}.ion-social-apple:before{content:""}.ion-social-apple-outline:before{content:""}.ion-social-bitcoin:before{content:""}.ion-social-bitcoin-outline:before{content:""}.ion-social-buffer:before{content:""}.ion-social-buffer-outline:before{content:""}.ion-social-chrome:before{content:"ï“›"}.ion-social-chrome-outline:before{content:""}.ion-social-codepen:before{content:"ï“"}.ion-social-codepen-outline:before{content:""}.ion-social-css3:before{content:""}.ion-social-css3-outline:before{content:""}.ion-social-designernews:before{content:""}.ion-social-designernews-outline:before{content:""}.ion-social-dribbble:before{content:"ïˆ"}.ion-social-dribbble-outline:before{content:""}.ion-social-dropbox:before{content:""}.ion-social-dropbox-outline:before{content:""}.ion-social-euro:before{content:"ï“¡"}.ion-social-euro-outline:before{content:"ï“ "}.ion-social-facebook:before{content:""}.ion-social-facebook-outline:before{content:""}.ion-social-foursquare:before{content:"ï"}.ion-social-foursquare-outline:before{content:"ïŒ"}.ion-social-freebsd-devil:before{content:"ï‹„"}.ion-social-github:before{content:""}.ion-social-github-outline:before{content:""}.ion-social-google:before{content:"ï"}.ion-social-google-outline:before{content:"ïŽ"}.ion-social-googleplus:before{content:""}.ion-social-googleplus-outline:before{content:""}.ion-social-hackernews:before{content:""}.ion-social-hackernews-outline:before{content:""}.ion-social-html5:before{content:"ï“£"}.ion-social-html5-outline:before{content:"ï“¢"}.ion-social-instagram:before{content:"ï‘"}.ion-social-instagram-outline:before{content:"ï"}.ion-social-javascript:before{content:"ï“¥"}.ion-social-javascript-outline:before{content:""}.ion-social-linkedin:before{content:""}.ion-social-linkedin-outline:before{content:""}.ion-social-markdown:before{content:""}.ion-social-nodejs:before{content:"ï“§"}.ion-social-octocat:before{content:""}.ion-social-pinterest:before{content:""}.ion-social-pinterest-outline:before{content:""}.ion-social-python:before{content:"ï“©"}.ion-social-reddit:before{content:""}.ion-social-reddit-outline:before{content:""}.ion-social-rss:before{content:""}.ion-social-rss-outline:before{content:""}.ion-social-sass:before{content:""}.ion-social-skype:before{content:""}.ion-social-skype-outline:before{content:""}.ion-social-snapchat:before{content:""}.ion-social-snapchat-outline:before{content:"ï“«"}.ion-social-tumblr:before{content:"ï‰"}.ion-social-tumblr-outline:before{content:""}.ion-social-tux:before{content:"ï‹…"}.ion-social-twitch:before{content:"ï“®"}.ion-social-twitch-outline:before{content:"ï“"}.ion-social-twitter:before{content:""}.ion-social-twitter-outline:before{content:""}.ion-social-usd:before{content:"ï“"}.ion-social-usd-outline:before{content:"ï’"}.ion-social-vimeo:before{content:""}.ion-social-vimeo-outline:before{content:""}.ion-social-whatsapp:before{content:"ï“°"}.ion-social-whatsapp-outline:before{content:""}.ion-social-windows:before{content:""}.ion-social-windows-outline:before{content:""}.ion-social-wordpress:before{content:""}.ion-social-wordpress-outline:before{content:""}.ion-social-yahoo:before{content:""}.ion-social-yahoo-outline:before{content:""}.ion-social-yen:before{content:""}.ion-social-yen-outline:before{content:""}.ion-social-youtube:before{content:"ï‰"}.ion-social-youtube-outline:before{content:""}.ion-soup-can:before{content:"ï“´"}.ion-soup-can-outline:before{content:""}.ion-speakerphone:before{content:""}.ion-speedometer:before{content:""}.ion-spoon:before{content:""}.ion-star:before{content:""}.ion-stats-bars:before{content:""}.ion-steam:before{content:""}.ion-stop:before{content:"ï‰"}.ion-thermometer:before{content:""}.ion-thumbsdown:before{content:"ï‰"}.ion-thumbsup:before{content:""}.ion-toggle:before{content:"ï•"}.ion-toggle-filled:before{content:"ï”"}.ion-transgender:before{content:""}.ion-trash-a:before{content:""}.ion-trash-b:before{content:""}.ion-trophy:before{content:"ï–"}.ion-tshirt:before{content:"ï“·"}.ion-tshirt-outline:before{content:"ï“¶"}.ion-umbrella:before{content:""}.ion-university:before{content:"ï—"}.ion-unlocked:before{content:""}.ion-upload:before{content:""}.ion-usb:before{content:""}.ion-videocamera:before{content:""}.ion-volume-high:before{content:""}.ion-volume-low:before{content:""}.ion-volume-medium:before{content:""}.ion-volume-mute:before{content:""}.ion-wand:before{content:"ï˜"}.ion-waterdrop:before{content:""}.ion-wifi:before{content:""}.ion-wineglass:before{content:""}.ion-woman:before{content:"ï‰"}.ion-wrench:before{content:""}.ion-xbox:before{content:""}a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;vertical-align:baseline;font:inherit;font-size:100%}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:'';content:none}audio:not([controls]){display:none;height:0}[hidden],template{display:none}script{display:none!important}html{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0;line-height:1}:focus,a,a:active,a:focus,a:hover,button,button:focus{outline:0}a{-webkit-user-drag:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent}a[href]:hover{cursor:pointer}b,strong{font-weight:700}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}code,kbd,pre,samp{font-size:1em;font-family:monospace,serif}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{position:relative;vertical-align:baseline;font-size:75%;line-height:0}sup{top:-.5em}sub{bottom:-.25em}fieldset{margin:0 2px;padding:.35em .625em .75em;border:1px solid silver}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-size:100%;font-family:inherit;outline-offset:0;outline-style:none;outline-width:0;-webkit-font-smoothing:inherit;background-image:none}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}img{-webkit-user-drag:none}table{border-spacing:0;border-collapse:collapse}*,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{overflow:hidden;-ms-touch-action:pan-y;touch-action:pan-y}.ionic-body,body{-webkit-touch-callout:none;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;top:0;right:0;bottom:0;left:0;overflow:hidden;margin:0;padding:0;color:#000;word-wrap:break-word;font-size:14px;font-family:-apple-system;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;line-height:20px;text-rendering:optimizeLegibility;-webkit-backface-visibility:hidden;-webkit-user-drag:none;-ms-content-zooming:none}body.grade-b,body.grade-c{text-rendering:auto}.content{position:relative}.scroll-content{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;margin-top:-1px;padding-top:1px;margin-bottom:-1px;width:auto;height:auto}.menu .scroll-content.scroll-content-false{z-index:11}.scroll-view{position:relative;display:block;overflow:hidden;margin-top:-1px}.scroll-view.overflow-scroll{position:relative}.scroll-view.scroll-x{overflow-x:scroll;overflow-y:hidden}.scroll-view.scroll-y{overflow-x:hidden;overflow-y:scroll}.scroll-view.scroll-xy{overflow-x:scroll;overflow-y:scroll}.scroll{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;-webkit-transform-origin:left top;transform-origin:left top}@-ms-viewport{width:device-width}.scroll-bar{position:absolute;z-index:9999}.ng-animate .scroll-bar{visibility:hidden}.scroll-bar-h{right:2px;bottom:3px;left:2px;height:3px}.scroll-bar-h .scroll-bar-indicator{height:100%}.scroll-bar-v{top:2px;right:3px;bottom:2px;width:3px}.scroll-bar-v .scroll-bar-indicator{width:100%}.scroll-bar-indicator{position:absolute;border-radius:4px;background:rgba(0,0,0,.3);opacity:1;-webkit-transition:opacity .3s linear;transition:opacity .3s linear}.scroll-bar-indicator.scroll-bar-fade-out{opacity:0}.platform-android .scroll-bar-indicator{border-radius:0}.grade-b .scroll-bar-indicator,.grade-c .scroll-bar-indicator{background:#aaa}.grade-b .scroll-bar-indicator.scroll-bar-fade-out,.grade-c .scroll-bar-indicator.scroll-bar-fade-out{-webkit-transition:none;transition:none}ion-infinite-scroll{height:60px;width:100%;display:block;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}#menu .footer ion-infinite-scroll .icon-help,ion-infinite-scroll #menu .footer .icon-help,ion-infinite-scroll .icon,ion-infinite-scroll .icon-alert,ion-infinite-scroll .icon-help{color:#666;font-size:30px;color:#666}#menu .footer ion-infinite-scroll:not(.active) .icon-help:before,ion-infinite-scroll:not(.active) #menu .footer .icon-help:before,ion-infinite-scroll:not(.active) .icon-alert:before,ion-infinite-scroll:not(.active) .icon-help:before,ion-infinite-scroll:not(.active) .icon:before,ion-infinite-scroll:not(.active) .spinner{display:none}.overflow-scroll{overflow-x:hidden;overflow-y:scroll;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;top:0;right:0;bottom:0;left:0;position:absolute}.overflow-scroll.pane{overflow-x:hidden;overflow-y:scroll}.overflow-scroll .scroll{position:static;height:100%;-webkit-transform:translate3d(0,0,0)}.has-header{top:44px}.no-header{top:0}.has-subheader{top:88px}.has-tabs-top{top:93px}.has-header.has-subheader.has-tabs-top{top:137px}.has-footer{bottom:44px}.has-subfooter{bottom:88px}.bar-footer.has-tabs,.has-tabs{bottom:49px}.bar-footer.has-tabs.pane,.has-tabs.pane{bottom:49px;height:auto}.bar-subfooter.has-tabs{bottom:93px}.has-footer.has-tabs{bottom:93px}.pane{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition-duration:0;transition-duration:0;z-index:1}.view{z-index:1}.pane,.view{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;background-color:#fff;overflow:hidden}.view-container{position:absolute;display:block;width:100%;height:100%}p{margin:0 0 10px}small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.item.large-button-bar,.text-center{text-align:center}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{color:#000;font-weight:500;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;line-height:1.2}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:400;line-height:1}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1:first-child,.h2:first-child,.h3:first-child,h1:first-child,h2:first-child,h3:first-child{margin-top:0}.h1+.h1,.h1+.h2,.h1+.h3,.h1+h1,.h1+h2,.h1+h3,.h2+.h1,.h2+.h2,.h2+.h3,.h2+h1,.h2+h2,.h2+h3,.h3+.h1,.h3+.h2,.h3+.h3,.h3+h1,.h3+h2,.h3+h3,h1+.h1,h1+.h2,h1+.h3,h1+h1,h1+h2,h1+h3,h2+.h1,h2+.h2,h2+.h3,h2+h1,h2+h2,h2+h3,h3+.h1,h3+.h2,h3+.h3,h3+h1,h3+h2,h3+h3{margin-top:10px}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}.h1 small,h1 small{font-size:24px}.h2 small,h2 small{font-size:18px}.h3 small,.h4 small,h3 small,h4 small{font-size:14px}dl{margin-bottom:20px}dd,dt{line-height:1.42857}dt{font-weight:700}blockquote{margin:0 0 20px;padding:10px 20px;border-left:5px solid gray}blockquote p{font-weight:300;font-size:17.5px;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.42857}blockquote small:before{content:'\2014 \00A0'}blockquote:after,blockquote:before,q:after,q:before{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:1.42857}a{color:#387ef5}a.subdued{padding-right:10px;color:#888;text-decoration:none}a.subdued:hover{text-decoration:none}a.subdued:last-child{padding-right:0}.action-sheet-backdrop{-webkit-transition:background-color 150ms ease-in-out;transition:background-color 150ms ease-in-out;position:fixed;top:0;left:0;z-index:11;width:100%;height:100%;background-color:rgba(0,0,0,0)}.action-sheet-backdrop.active{background-color:rgba(0,0,0,.4)}.action-sheet-wrapper{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);-webkit-transition:all cubic-bezier(.36,.66,.04,1) .5s;transition:all cubic-bezier(.36,.66,.04,1) .5s;position:absolute;bottom:0;left:0;right:0;width:100%;max-width:500px;margin:auto}.action-sheet-up{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.action-sheet{margin-left:8px;margin-right:8px;width:auto;z-index:11;overflow:hidden}.action-sheet .button{display:block;padding:1px;width:100%;border-radius:0;border-color:#d1d3d6;background-color:transparent;color:#007aff;font-size:21px}.action-sheet .button:hover{color:#007aff}.action-sheet .button.destructive{color:#ff3b30}.action-sheet .button.destructive:hover{color:#ff3b30}.action-sheet .button.activated,.action-sheet .button.active{box-shadow:none;border-color:#d1d3d6;color:#007aff;background:#e4e5e7}#menu .footer .action-sheet-has-icons .icon-help,.action-sheet-has-icons #menu .footer .icon-help,.action-sheet-has-icons .icon,.action-sheet-has-icons .icon-alert,.action-sheet-has-icons .icon-help{position:absolute;left:16px}.action-sheet-title{padding:16px;color:#8f8f8f;text-align:center;font-size:13px}.action-sheet-group{margin-bottom:8px;border-radius:4px;background-color:#fff;overflow:hidden}.action-sheet-group .button{border-width:1px 0 0 0}.action-sheet-group .button:first-child:last-child{border-width:0}.action-sheet-options{background:#f1f2f3}.action-sheet-cancel .button{font-weight:500}.action-sheet-open{pointer-events:none}.action-sheet-open.modal-open .modal{pointer-events:none}.action-sheet-open .action-sheet-backdrop{pointer-events:auto}.platform-android .action-sheet-backdrop.active{background-color:rgba(0,0,0,.2)}.platform-android .action-sheet{margin:0}.platform-android .action-sheet .action-sheet-title,.platform-android .action-sheet .button{text-align:left;border-color:transparent;font-size:16px;color:inherit}.platform-android .action-sheet .action-sheet-title{font-size:14px;padding:16px;color:#666}.platform-android .action-sheet .button.activated,.platform-android .action-sheet .button.active{background:#e8e8e8}.platform-android .action-sheet-group{margin:0;border-radius:0;background-color:#fafafa}.platform-android .action-sheet-cancel{display:none}.platform-android .action-sheet-has-icons .button{padding-left:56px}.backdrop{position:fixed;top:0;left:0;z-index:11;width:100%;height:100%;background-color:rgba(0,0,0,.4);visibility:hidden;opacity:0;-webkit-transition:.1s opacity linear;transition:.1s opacity linear}.backdrop.visible{visibility:visible}.backdrop.active{opacity:1}.bar{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:absolute;right:0;left:0;z-index:9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:5px;width:100%;height:44px;border-width:0;border-style:solid;border-top:1px solid transparent;border-bottom:1px solid #ddd;background-color:#fff;background-size:0}@media (min--moz-device-pixel-ratio:1.5),(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5),(min-resolution:144dpi),(min-resolution:1.5dppx){.bar{border:none;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);background-position:bottom;background-size:100% 1px;background-repeat:no-repeat}}.bar.bar-clear{border:none;background:0 0;color:#fff}.bar.bar-clear .button{color:#fff}.bar.bar-clear .title{color:#fff}.bar.item-input-inset .item-input-wrapper{margin-top:-1px}.bar.item-input-inset .item-input-wrapper input{padding-left:8px;width:94%;height:28px;background:0 0}.bar.bar-light{border-color:#ddd;background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);color:#444}.bar.bar-light .title{color:#444}.bar.bar-light.bar-footer{background-image:linear-gradient(180deg,#ddd,#ddd 50%,transparent 50%)}.bar.bar-stable{border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444}.bar.bar-stable .title{color:#444}.bar.bar-stable.bar-footer{background-image:linear-gradient(180deg,#b2b2b2,#b2b2b2 50%,transparent 50%)}.bar.bar-positive{border-color:#0c60ee;background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);color:#fff}.bar.bar-positive .title{color:#fff}.bar.bar-positive.bar-footer{background-image:linear-gradient(180deg,#0c60ee,#0c60ee 50%,transparent 50%)}.bar.bar-calm{border-color:#0a9dc7;background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);color:#fff}.bar.bar-calm .title{color:#fff}.bar.bar-calm.bar-footer{background-image:linear-gradient(180deg,#0a9dc7,#0a9dc7 50%,transparent 50%)}.bar.bar-assertive{border-color:#e42112;background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);color:#fff}.bar.bar-assertive .title{color:#fff}.bar.bar-assertive.bar-footer{background-image:linear-gradient(180deg,#e42112,#e42112 50%,transparent 50%)}.bar.bar-balanced{border-color:#28a54c;background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);color:#fff}.bar.bar-balanced .title{color:#fff}.bar.bar-balanced.bar-footer{background-image:linear-gradient(180deg,#28a54c,#28a54c 50%,transparent 50%)}.bar.bar-energized{border-color:#e6b500;background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);color:#fff}.bar.bar-energized .title{color:#fff}.bar.bar-energized.bar-footer{background-image:linear-gradient(180deg,#e6b500,#e6b500 50%,transparent 50%)}.bar.bar-royal{border-color:#6b46e5;background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);color:#fff}.bar.bar-royal .title{color:#fff}.bar.bar-royal.bar-footer{background-image:linear-gradient(180deg,#6b46e5,#6b46e5 50%,transparent 50%)}.bar.bar-dark{border-color:#111;background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);color:#fff}.bar.bar-dark .title{color:#fff}.bar.bar-dark.bar-footer{background-image:linear-gradient(180deg,#111,#111 50%,transparent 50%)}.bar .title{display:block;position:absolute;top:0;right:0;left:0;z-index:0;overflow:hidden;margin:0 10px;min-width:30px;height:43px;text-align:center;text-overflow:ellipsis;white-space:nowrap;font-size:17px;font-weight:500;line-height:44px}.bar .title.title-left{text-align:left}.bar .title.title-right{text-align:right}.bar .title a{color:inherit}.bar .button,.bar button{z-index:1;padding:0 8px;min-width:initial;min-height:31px;font-weight:400;font-size:13px;line-height:32px}#menu .footer .bar .button .icon-help:before,#menu .footer .bar .button.icon-help:before,#menu .footer .bar button .icon-help:before,#menu .footer .bar button.icon-help:before,.bar #menu .footer .button.icon-help:before,.bar #menu .footer button.icon-help:before,.bar .button #menu .footer .icon-help:before,.bar .button .icon-alert:before,.bar .button .icon-help:before,.bar .button .icon:before,.bar .button.button-icon:before,.bar .button.icon-alert:before,.bar .button.icon-help:before,.bar .button.icon-left:before,.bar .button.icon-right:before,.bar .button.icon:before,.bar button #menu .footer .icon-help:before,.bar button .icon-alert:before,.bar button .icon-help:before,.bar button .icon:before,.bar button.button-icon:before,.bar button.icon-alert:before,.bar button.icon-help:before,.bar button.icon-left:before,.bar button.icon-right:before,.bar button.icon:before{padding-right:2px;padding-left:2px;font-size:20px;line-height:32px}.bar .button.button-icon,.bar button.button-icon{font-size:17px}#menu .footer .bar .button.button-icon .icon-help:before,#menu .footer .bar button.button-icon .icon-help:before,.bar .button.button-icon #menu .footer .icon-help:before,.bar .button.button-icon .icon-alert:before,.bar .button.button-icon .icon-help:before,.bar .button.button-icon .icon:before,.bar .button.button-icon.icon-left:before,.bar .button.button-icon.icon-right:before,.bar .button.button-icon:before,.bar button.button-icon #menu .footer .icon-help:before,.bar button.button-icon .icon-alert:before,.bar button.button-icon .icon-help:before,.bar button.button-icon .icon:before,.bar button.button-icon.icon-left:before,.bar button.button-icon.icon-right:before,.bar button.button-icon:before{vertical-align:top;font-size:32px;line-height:32px}.bar .button.button-clear,.bar .button.button-text,.bar button.button-clear,.bar button.button-text{padding-right:2px;padding-left:2px;font-weight:300;font-size:17px}#menu .footer .bar .button.button-clear .icon-help:before,#menu .footer .bar .button.button-clear.icon-help:before,#menu .footer .bar .button.button-text .icon-help:before,#menu .footer .bar .button.button-text.icon-help:before,#menu .footer .bar button.button-clear .icon-help:before,#menu .footer .bar button.button-clear.icon-help:before,#menu .footer .bar button.button-text .icon-help:before,#menu .footer .bar button.button-text.icon-help:before,.bar #menu .footer .button.button-clear.icon-help:before,.bar #menu .footer .button.button-text.icon-help:before,.bar #menu .footer button.button-clear.icon-help:before,.bar #menu .footer button.button-text.icon-help:before,.bar .button.button-clear #menu .footer .icon-help:before,.bar .button.button-clear .icon-alert:before,.bar .button.button-clear .icon-help:before,.bar .button.button-clear .icon:before,.bar .button.button-clear.icon-alert:before,.bar .button.button-clear.icon-help:before,.bar .button.button-clear.icon-left:before,.bar .button.button-clear.icon-right:before,.bar .button.button-clear.icon:before,.bar .button.button-text #menu .footer .icon-help:before,.bar .button.button-text .icon-alert:before,.bar .button.button-text .icon-help:before,.bar .button.button-text .icon:before,.bar .button.button-text.icon-alert:before,.bar .button.button-text.icon-help:before,.bar .button.icon-left.button-text:before,.bar .button.icon-right.button-text:before,.bar .button.icon.button-text:before,.bar button.button-clear #menu .footer .icon-help:before,.bar button.button-clear .icon-alert:before,.bar button.button-clear .icon-help:before,.bar button.button-clear .icon:before,.bar button.button-clear.icon-alert:before,.bar button.button-clear.icon-help:before,.bar button.button-clear.icon-left:before,.bar button.button-clear.icon-right:before,.bar button.button-clear.icon:before,.bar button.button-text #menu .footer .icon-help:before,.bar button.button-text .icon-alert:before,.bar button.button-text .icon-help:before,.bar button.button-text .icon:before,.bar button.button-text.icon-alert:before,.bar button.button-text.icon-help:before,.bar button.icon-left.button-text:before,.bar button.icon-right.button-text:before,.bar button.icon.button-text:before{font-size:32px;line-height:32px}.bar .button.back-button,.bar button.back-button{display:block;margin-right:5px;padding:0;white-space:nowrap;font-weight:400}.bar .button.back-button.activated,.bar .button.back-button.active,.bar button.back-button.activated,.bar button.back-button.active{opacity:.2}.bar .button-bar>.button,.bar .buttons>.button{min-height:31px;line-height:32px}.bar .button+.button-bar,.bar .button-bar+.button{margin-left:5px}.bar .buttons,.bar .buttons.primary-buttons,.bar .buttons.secondary-buttons{display:inherit}.bar .buttons span{display:inline-block}.bar .buttons-left span{margin-right:5px;display:inherit}.bar .buttons-right span{margin-left:5px;display:inherit}#menu .footer .popover-helptip .bar .buttons.icon-bottom-center.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-bottom-right.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-center.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-right.icon-help,#menu .footer .popover-helptip .bar>.button.icon-bottom-center.icon-help,#menu .footer .popover-helptip .bar>.button.icon-bottom-right.icon-help,#menu .footer .popover-helptip .bar>.button.icon-center.icon-help,#menu .footer .popover-helptip .bar>.button.icon-right.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-bottom-center.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-bottom-right.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-center.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-right.icon-help,.bar .buttons.pull-right,.bar .popover-helptip #menu .footer .buttons.icon-bottom-center.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-bottom-right.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-center.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-right.icon-help,.bar .popover-helptip .buttons.icon-bottom-center.icon-alert,.bar .popover-helptip .buttons.icon-bottom-center.icon-help,.bar .popover-helptip .buttons.icon-bottom-right.icon-alert,.bar .popover-helptip .buttons.icon-bottom-right.icon-help,.bar .popover-helptip .buttons.icon-center.icon-alert,.bar .popover-helptip .buttons.icon-center.icon-help,.bar .popover-helptip .buttons.icon-right.icon-alert,.bar .popover-helptip .buttons.icon-right.icon-help,.bar .popover-helptip .buttons.icon.icon-bottom-center,.bar .popover-helptip .buttons.icon.icon-bottom-right,.bar .popover-helptip .buttons.icon.icon-center,.bar .popover-helptip .buttons.icon.icon-right,.bar .title+.button:last-child,.bar .title+.buttons,.bar>.button+.button:last-child,.bar>.button.pull-right,.popover-helptip #menu .footer .bar .buttons.icon-bottom-center.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-bottom-right.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-center.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-right.icon-help,.popover-helptip #menu .footer .bar>.button.icon-bottom-center.icon-help,.popover-helptip #menu .footer .bar>.button.icon-bottom-right.icon-help,.popover-helptip #menu .footer .bar>.button.icon-center.icon-help,.popover-helptip #menu .footer .bar>.button.icon-right.icon-help,.popover-helptip .bar .buttons.icon-bottom-center.icon-alert,.popover-helptip .bar .buttons.icon-bottom-center.icon-help,.popover-helptip .bar .buttons.icon-bottom-right.icon-alert,.popover-helptip .bar .buttons.icon-bottom-right.icon-help,.popover-helptip .bar .buttons.icon-center.icon-alert,.popover-helptip .bar .buttons.icon-center.icon-help,.popover-helptip .bar .buttons.icon-right.icon-alert,.popover-helptip .bar .buttons.icon-right.icon-help,.popover-helptip .bar .buttons.icon.icon-bottom-center,.popover-helptip .bar .buttons.icon.icon-bottom-right,.popover-helptip .bar .buttons.icon.icon-center,.popover-helptip .bar .buttons.icon.icon-right,.popover-helptip .bar>.button.icon-bottom-center.icon-alert,.popover-helptip .bar>.button.icon-bottom-center.icon-help,.popover-helptip .bar>.button.icon-bottom-right.icon-alert,.popover-helptip .bar>.button.icon-bottom-right.icon-help,.popover-helptip .bar>.button.icon-center.icon-alert,.popover-helptip .bar>.button.icon-center.icon-help,.popover-helptip .bar>.button.icon-right.icon-alert,.popover-helptip .bar>.button.icon-right.icon-help,.popover-helptip .bar>.button.icon.icon-bottom-center,.popover-helptip .bar>.button.icon.icon-bottom-right,.popover-helptip .bar>.button.icon.icon-center,.popover-helptip .bar>.button.icon.icon-right{position:absolute;top:5px;right:5px;bottom:5px}.platform-android .nav-bar-has-subheader .bar{background-image:none}#menu .footer .platform-android .bar .back-button .icon-help:before,.platform-android .bar .back-button #menu .footer .icon-help:before,.platform-android .bar .back-button .icon-alert:before,.platform-android .bar .back-button .icon-help:before,.platform-android .bar .back-button .icon:before{font-size:24px}.platform-android .bar .title{font-size:19px;line-height:44px}.bar-light .button{border-color:#ddd;background-color:#fff;color:#444}.bar-light .button:hover{color:#444;text-decoration:none}.bar-light .button.activated,.bar-light .button.active{border-color:#ccc;background-color:#fafafa}.bar-light .button.button-clear,.bar-light .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#444;font-size:17px}.bar-light .button.button-icon{border-color:transparent;background:0 0}.bar-stable .button{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.bar-stable .button:hover{color:#444;text-decoration:none}.bar-stable .button.activated,.bar-stable .button.active{border-color:#a2a2a2;background-color:#e5e5e5}.bar-stable .button.button-clear,.bar-stable .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#444;font-size:17px}.bar-stable .button.button-icon{border-color:transparent;background:0 0}.bar-positive .button{border-color:#0c60ee;background-color:#387ef5;color:#fff}.bar-positive .button:hover{color:#fff;text-decoration:none}.bar-positive .button.activated,.bar-positive .button.active{border-color:#0c60ee;background-color:#0c60ee}.bar-positive .button.button-clear,.bar-positive .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-positive .button.button-icon{border-color:transparent;background:0 0}.bar-calm .button{border-color:#0a9dc7;background-color:#11c1f3;color:#fff}.bar-calm .button:hover{color:#fff;text-decoration:none}.bar-calm .button.activated,.bar-calm .button.active{border-color:#0a9dc7;background-color:#0a9dc7}.bar-calm .button.button-clear,.bar-calm .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-calm .button.button-icon{border-color:transparent;background:0 0}.bar-assertive .button{border-color:#e42112;background-color:#ef473a;color:#fff}.bar-assertive .button:hover{color:#fff;text-decoration:none}.bar-assertive .button.activated,.bar-assertive .button.active{border-color:#e42112;background-color:#e42112}.bar-assertive .button.button-clear,.bar-assertive .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-assertive .button.button-icon{border-color:transparent;background:0 0}.bar-balanced .button{border-color:#28a54c;background-color:#33cd5f;color:#fff}.bar-balanced .button:hover{color:#fff;text-decoration:none}.bar-balanced .button.activated,.bar-balanced .button.active{border-color:#28a54c;background-color:#28a54c}.bar-balanced .button.button-clear,.bar-balanced .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-balanced .button.button-icon{border-color:transparent;background:0 0}.bar-energized .button{border-color:#e6b500;background-color:#ffc900;color:#fff}.bar-energized .button:hover{color:#fff;text-decoration:none}.bar-energized .button.activated,.bar-energized .button.active{border-color:#e6b500;background-color:#e6b500}.bar-energized .button.button-clear,.bar-energized .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-energized .button.button-icon{border-color:transparent;background:0 0}.bar-royal .button{border-color:#6b46e5;background-color:#886aea;color:#fff}.bar-royal .button:hover{color:#fff;text-decoration:none}.bar-royal .button.activated,.bar-royal .button.active{border-color:#6b46e5;background-color:#6b46e5}.bar-royal .button.button-clear,.bar-royal .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-royal .button.button-icon{border-color:transparent;background:0 0}.bar-dark .button{border-color:#111;background-color:#444;color:#fff}.bar-dark .button:hover{color:#fff;text-decoration:none}.bar-dark .button.activated,.bar-dark .button.active{border-color:#000;background-color:#262626}.bar-dark .button.button-clear,.bar-dark .button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-dark .button.button-icon{border-color:transparent;background:0 0}.bar-header{top:0;border-top-width:0;border-bottom-width:1px}.bar-header.has-tabs-top{border-bottom-width:0;background-image:none}.tabs-top .bar-header{border-bottom-width:0;background-image:none}.bar-footer{bottom:0;border-top-width:1px;border-bottom-width:0;background-position:top;height:44px}.bar-footer.item-input-inset{position:absolute}.bar-footer .title{height:43px;line-height:44px}.bar-tabs{padding:0}.bar-subheader{top:44px;height:44px}.bar-subheader .title{height:43px;line-height:44px}.bar-subfooter{bottom:44px;height:44px}.bar-subfooter .title{height:43px;line-height:44px}.nav-bar-block{position:absolute;top:0;right:0;left:0;z-index:9}.bar .back-button.hide,.bar .buttons .hide{display:none}.nav-bar-tabs-top .bar{background-image:none}.tabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:horizontal;-moz-flex-direction:horizontal;-ms-flex-direction:horizontal;flex-direction:horizontal;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444;position:absolute;bottom:0;z-index:5;width:100%;height:49px;border-style:solid;border-top-width:1px;background-size:0;line-height:49px}.tabs .tab-item .badge{background-color:#444;color:#f8f8f8}@media (min--moz-device-pixel-ratio:1.5),(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5),(min-resolution:144dpi),(min-resolution:1.5dppx){.tabs{padding-top:2px;border-top:none!important;border-bottom:none;background-position:top;background-size:100% 1px;background-repeat:no-repeat}}.tabs-light>.tabs,.tabs.tabs-light{border-color:#ddd;background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);color:#444}.tabs-light>.tabs .tab-item .badge,.tabs.tabs-light .tab-item .badge{background-color:#444;color:#fff}.tabs-stable>.tabs,.tabs.tabs-stable{border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444}.tabs-stable>.tabs .tab-item .badge,.tabs.tabs-stable .tab-item .badge{background-color:#444;color:#f8f8f8}.tabs-positive>.tabs,.tabs.tabs-positive{border-color:#0c60ee;background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);color:#fff}.tabs-positive>.tabs .tab-item .badge,.tabs.tabs-positive .tab-item .badge{background-color:#fff;color:#387ef5}.tabs-calm>.tabs,.tabs.tabs-calm{border-color:#0a9dc7;background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);color:#fff}.tabs-calm>.tabs .tab-item .badge,.tabs.tabs-calm .tab-item .badge{background-color:#fff;color:#11c1f3}.tabs-assertive>.tabs,.tabs.tabs-assertive{border-color:#e42112;background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);color:#fff}.tabs-assertive>.tabs .tab-item .badge,.tabs.tabs-assertive .tab-item .badge{background-color:#fff;color:#ef473a}.tabs-balanced>.tabs,.tabs.tabs-balanced{border-color:#28a54c;background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);color:#fff}.tabs-balanced>.tabs .tab-item .badge,.tabs.tabs-balanced .tab-item .badge{background-color:#fff;color:#33cd5f}.tabs-energized>.tabs,.tabs.tabs-energized{border-color:#e6b500;background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);color:#fff}.tabs-energized>.tabs .tab-item .badge,.tabs.tabs-energized .tab-item .badge{background-color:#fff;color:#ffc900}.tabs-royal>.tabs,.tabs.tabs-royal{border-color:#6b46e5;background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);color:#fff}.tabs-royal>.tabs .tab-item .badge,.tabs.tabs-royal .tab-item .badge{background-color:#fff;color:#886aea}.tabs-dark>.tabs,.tabs.tabs-dark{border-color:#111;background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);color:#fff}.tabs-dark>.tabs .tab-item .badge,.tabs.tabs-dark .tab-item .badge{background-color:#fff;color:#444}.tabs-striped .tabs{background-color:#fff;background-image:none;border:none;border-bottom:1px solid #ddd;padding-top:2px}.tabs-striped .tab-item.activated,.tabs-striped .tab-item.active,.tabs-striped .tab-item.tab-item-active{margin-top:-2px;border-style:solid;border-width:2px 0 0 0;border-color:#444}.tabs-striped .tab-item.activated .badge,.tabs-striped .tab-item.active .badge,.tabs-striped .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-light .tabs{background-color:#fff}.tabs-striped.tabs-light .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-light .tab-item .badge{opacity:.4}.tabs-striped.tabs-light .tab-item.activated,.tabs-striped.tabs-light .tab-item.active,.tabs-striped.tabs-light .tab-item.tab-item-active{margin-top:-2px;color:#444;border-style:solid;border-width:2px 0 0 0;border-color:#444}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-stable .tabs{background-color:#f8f8f8}.tabs-striped.tabs-stable .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-stable .tab-item .badge{opacity:.4}.tabs-striped.tabs-stable .tab-item.activated,.tabs-striped.tabs-stable .tab-item.active,.tabs-striped.tabs-stable .tab-item.tab-item-active{margin-top:-2px;color:#444;border-style:solid;border-width:2px 0 0 0;border-color:#444}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-positive .tabs{background-color:#387ef5}.tabs-striped.tabs-positive .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-positive .tab-item .badge{opacity:.4}.tabs-striped.tabs-positive .tab-item.activated,.tabs-striped.tabs-positive .tab-item.active,.tabs-striped.tabs-positive .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-calm .tabs{background-color:#11c1f3}.tabs-striped.tabs-calm .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-calm .tab-item .badge{opacity:.4}.tabs-striped.tabs-calm .tab-item.activated,.tabs-striped.tabs-calm .tab-item.active,.tabs-striped.tabs-calm .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-assertive .tabs{background-color:#ef473a}.tabs-striped.tabs-assertive .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-assertive .tab-item .badge{opacity:.4}.tabs-striped.tabs-assertive .tab-item.activated,.tabs-striped.tabs-assertive .tab-item.active,.tabs-striped.tabs-assertive .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-balanced .tabs{background-color:#33cd5f}.tabs-striped.tabs-balanced .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-balanced .tab-item .badge{opacity:.4}.tabs-striped.tabs-balanced .tab-item.activated,.tabs-striped.tabs-balanced .tab-item.active,.tabs-striped.tabs-balanced .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-energized .tabs{background-color:#ffc900}.tabs-striped.tabs-energized .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-energized .tab-item .badge{opacity:.4}.tabs-striped.tabs-energized .tab-item.activated,.tabs-striped.tabs-energized .tab-item.active,.tabs-striped.tabs-energized .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-royal .tabs{background-color:#886aea}.tabs-striped.tabs-royal .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-royal .tab-item .badge{opacity:.4}.tabs-striped.tabs-royal .tab-item.activated,.tabs-striped.tabs-royal .tab-item.active,.tabs-striped.tabs-royal .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-dark .tabs{background-color:#444}.tabs-striped.tabs-dark .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-dark .tab-item .badge{opacity:.4}.tabs-striped.tabs-dark .tab-item.activated,.tabs-striped.tabs-dark .tab-item.active,.tabs-striped.tabs-dark .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-background-light .tabs{background-color:#fff;background-image:none}.tabs-striped.tabs-background-stable .tabs{background-color:#f8f8f8;background-image:none}.tabs-striped.tabs-background-positive .tabs{background-color:#387ef5;background-image:none}.tabs-striped.tabs-background-calm .tabs{background-color:#11c1f3;background-image:none}.tabs-striped.tabs-background-assertive .tabs{background-color:#ef473a;background-image:none}.tabs-striped.tabs-background-balanced .tabs{background-color:#33cd5f;background-image:none}.tabs-striped.tabs-background-energized .tabs{background-color:#ffc900;background-image:none}.tabs-striped.tabs-background-royal .tabs{background-color:#886aea;background-image:none}.tabs-striped.tabs-background-dark .tabs{background-color:#444;background-image:none}.tabs-striped.tabs-color-light .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-color-light .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-light .tab-item.activated,.tabs-striped.tabs-color-light .tab-item.active,.tabs-striped.tabs-color-light .tab-item.tab-item-active{margin-top:-2px;color:#fff;border:0 solid #fff;border-top-width:2px}.tabs-striped.tabs-color-light .tab-item.activated .badge,.tabs-striped.tabs-color-light .tab-item.active .badge,.tabs-striped.tabs-color-light .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-stable .tab-item{color:rgba(248,248,248,.4);opacity:1}.tabs-striped.tabs-color-stable .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-stable .tab-item.activated,.tabs-striped.tabs-color-stable .tab-item.active,.tabs-striped.tabs-color-stable .tab-item.tab-item-active{margin-top:-2px;color:#f8f8f8;border:0 solid #f8f8f8;border-top-width:2px}.tabs-striped.tabs-color-stable .tab-item.activated .badge,.tabs-striped.tabs-color-stable .tab-item.active .badge,.tabs-striped.tabs-color-stable .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-positive .tab-item{color:rgba(56,126,245,.4);opacity:1}.tabs-striped.tabs-color-positive .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-positive .tab-item.activated,.tabs-striped.tabs-color-positive .tab-item.active,.tabs-striped.tabs-color-positive .tab-item.tab-item-active{margin-top:-2px;color:#387ef5;border:0 solid #387ef5;border-top-width:2px}.tabs-striped.tabs-color-positive .tab-item.activated .badge,.tabs-striped.tabs-color-positive .tab-item.active .badge,.tabs-striped.tabs-color-positive .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-calm .tab-item{color:rgba(17,193,243,.4);opacity:1}.tabs-striped.tabs-color-calm .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-calm .tab-item.activated,.tabs-striped.tabs-color-calm .tab-item.active,.tabs-striped.tabs-color-calm .tab-item.tab-item-active{margin-top:-2px;color:#11c1f3;border:0 solid #11c1f3;border-top-width:2px}.tabs-striped.tabs-color-calm .tab-item.activated .badge,.tabs-striped.tabs-color-calm .tab-item.active .badge,.tabs-striped.tabs-color-calm .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-assertive .tab-item{color:rgba(239,71,58,.4);opacity:1}.tabs-striped.tabs-color-assertive .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-assertive .tab-item.activated,.tabs-striped.tabs-color-assertive .tab-item.active,.tabs-striped.tabs-color-assertive .tab-item.tab-item-active{margin-top:-2px;color:#ef473a;border:0 solid #ef473a;border-top-width:2px}.tabs-striped.tabs-color-assertive .tab-item.activated .badge,.tabs-striped.tabs-color-assertive .tab-item.active .badge,.tabs-striped.tabs-color-assertive .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-balanced .tab-item{color:rgba(51,205,95,.4);opacity:1}.tabs-striped.tabs-color-balanced .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-balanced .tab-item.activated,.tabs-striped.tabs-color-balanced .tab-item.active,.tabs-striped.tabs-color-balanced .tab-item.tab-item-active{margin-top:-2px;color:#33cd5f;border:0 solid #33cd5f;border-top-width:2px}.tabs-striped.tabs-color-balanced .tab-item.activated .badge,.tabs-striped.tabs-color-balanced .tab-item.active .badge,.tabs-striped.tabs-color-balanced .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-energized .tab-item{color:rgba(255,201,0,.4);opacity:1}.tabs-striped.tabs-color-energized .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-energized .tab-item.activated,.tabs-striped.tabs-color-energized .tab-item.active,.tabs-striped.tabs-color-energized .tab-item.tab-item-active{margin-top:-2px;color:#ffc900;border:0 solid #ffc900;border-top-width:2px}.tabs-striped.tabs-color-energized .tab-item.activated .badge,.tabs-striped.tabs-color-energized .tab-item.active .badge,.tabs-striped.tabs-color-energized .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-royal .tab-item{color:rgba(136,106,234,.4);opacity:1}.tabs-striped.tabs-color-royal .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-royal .tab-item.activated,.tabs-striped.tabs-color-royal .tab-item.active,.tabs-striped.tabs-color-royal .tab-item.tab-item-active{margin-top:-2px;color:#886aea;border:0 solid #886aea;border-top-width:2px}.tabs-striped.tabs-color-royal .tab-item.activated .badge,.tabs-striped.tabs-color-royal .tab-item.active .badge,.tabs-striped.tabs-color-royal .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-dark .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-color-dark .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-dark .tab-item.activated,.tabs-striped.tabs-color-dark .tab-item.active,.tabs-striped.tabs-color-dark .tab-item.tab-item-active{margin-top:-2px;color:#444;border:0 solid #444;border-top-width:2px}.tabs-striped.tabs-color-dark .tab-item.activated .badge,.tabs-striped.tabs-color-dark .tab-item.active .badge,.tabs-striped.tabs-color-dark .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-background-light .tabs,.tabs-background-light>.tabs{background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);border-color:#ddd}.tabs-background-stable .tabs,.tabs-background-stable>.tabs{background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);border-color:#b2b2b2}.tabs-background-positive .tabs,.tabs-background-positive>.tabs{background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);border-color:#0c60ee}.tabs-background-calm .tabs,.tabs-background-calm>.tabs{background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);border-color:#0a9dc7}.tabs-background-assertive .tabs,.tabs-background-assertive>.tabs{background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);border-color:#e42112}.tabs-background-balanced .tabs,.tabs-background-balanced>.tabs{background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);border-color:#28a54c}.tabs-background-energized .tabs,.tabs-background-energized>.tabs{background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);border-color:#e6b500}.tabs-background-royal .tabs,.tabs-background-royal>.tabs{background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);border-color:#6b46e5}.tabs-background-dark .tabs,.tabs-background-dark>.tabs{background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);border-color:#111}.tabs-color-light .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-color-light .tab-item .badge{opacity:.4}.tabs-color-light .tab-item.activated,.tabs-color-light .tab-item.active,.tabs-color-light .tab-item.tab-item-active{color:#fff;border:0 solid #fff}.tabs-color-light .tab-item.activated .badge,.tabs-color-light .tab-item.active .badge,.tabs-color-light .tab-item.tab-item-active .badge{opacity:1}.tabs-color-stable .tab-item{color:rgba(248,248,248,.4);opacity:1}.tabs-color-stable .tab-item .badge{opacity:.4}.tabs-color-stable .tab-item.activated,.tabs-color-stable .tab-item.active,.tabs-color-stable .tab-item.tab-item-active{color:#f8f8f8;border:0 solid #f8f8f8}.tabs-color-stable .tab-item.activated .badge,.tabs-color-stable .tab-item.active .badge,.tabs-color-stable .tab-item.tab-item-active .badge{opacity:1}.tabs-color-positive .tab-item{color:rgba(56,126,245,.4);opacity:1}.tabs-color-positive .tab-item .badge{opacity:.4}.tabs-color-positive .tab-item.activated,.tabs-color-positive .tab-item.active,.tabs-color-positive .tab-item.tab-item-active{color:#387ef5;border:0 solid #387ef5}.tabs-color-positive .tab-item.activated .badge,.tabs-color-positive .tab-item.active .badge,.tabs-color-positive .tab-item.tab-item-active .badge{opacity:1}.tabs-color-calm .tab-item{color:rgba(17,193,243,.4);opacity:1}.tabs-color-calm .tab-item .badge{opacity:.4}.tabs-color-calm .tab-item.activated,.tabs-color-calm .tab-item.active,.tabs-color-calm .tab-item.tab-item-active{color:#11c1f3;border:0 solid #11c1f3}.tabs-color-calm .tab-item.activated .badge,.tabs-color-calm .tab-item.active .badge,.tabs-color-calm .tab-item.tab-item-active .badge{opacity:1}.tabs-color-assertive .tab-item{color:rgba(239,71,58,.4);opacity:1}.tabs-color-assertive .tab-item .badge{opacity:.4}.tabs-color-assertive .tab-item.activated,.tabs-color-assertive .tab-item.active,.tabs-color-assertive .tab-item.tab-item-active{color:#ef473a;border:0 solid #ef473a}.tabs-color-assertive .tab-item.activated .badge,.tabs-color-assertive .tab-item.active .badge,.tabs-color-assertive .tab-item.tab-item-active .badge{opacity:1}.tabs-color-balanced .tab-item{color:rgba(51,205,95,.4);opacity:1}.tabs-color-balanced .tab-item .badge{opacity:.4}.tabs-color-balanced .tab-item.activated,.tabs-color-balanced .tab-item.active,.tabs-color-balanced .tab-item.tab-item-active{color:#33cd5f;border:0 solid #33cd5f}.tabs-color-balanced .tab-item.activated .badge,.tabs-color-balanced .tab-item.active .badge,.tabs-color-balanced .tab-item.tab-item-active .badge{opacity:1}.tabs-color-energized .tab-item{color:rgba(255,201,0,.4);opacity:1}.tabs-color-energized .tab-item .badge{opacity:.4}.tabs-color-energized .tab-item.activated,.tabs-color-energized .tab-item.active,.tabs-color-energized .tab-item.tab-item-active{color:#ffc900;border:0 solid #ffc900}.tabs-color-energized .tab-item.activated .badge,.tabs-color-energized .tab-item.active .badge,.tabs-color-energized .tab-item.tab-item-active .badge{opacity:1}.tabs-color-royal .tab-item{color:rgba(136,106,234,.4);opacity:1}.tabs-color-royal .tab-item .badge{opacity:.4}.tabs-color-royal .tab-item.activated,.tabs-color-royal .tab-item.active,.tabs-color-royal .tab-item.tab-item-active{color:#886aea;border:0 solid #886aea}.tabs-color-royal .tab-item.activated .badge,.tabs-color-royal .tab-item.active .badge,.tabs-color-royal .tab-item.tab-item-active .badge{opacity:1}.tabs-color-dark .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-color-dark .tab-item .badge{opacity:.4}.tabs-color-dark .tab-item.activated,.tabs-color-dark .tab-item.active,.tabs-color-dark .tab-item.tab-item-active{color:#444;border:0 solid #444}.tabs-color-dark .tab-item.activated .badge,.tabs-color-dark .tab-item.active .badge,.tabs-color-dark .tab-item.tab-item-active .badge{opacity:1}ion-tabs.tabs-color-active-light .tab-item{color:#444}ion-tabs.tabs-color-active-light .tab-item.activated,ion-tabs.tabs-color-active-light .tab-item.active,ion-tabs.tabs-color-active-light .tab-item.tab-item-active{color:#fff}ion-tabs.tabs-striped.tabs-color-active-light .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-light .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-light .tab-item.tab-item-active{border-color:#fff;color:#fff}ion-tabs.tabs-color-active-stable .tab-item{color:#444}ion-tabs.tabs-color-active-stable .tab-item.activated,ion-tabs.tabs-color-active-stable .tab-item.active,ion-tabs.tabs-color-active-stable .tab-item.tab-item-active{color:#f8f8f8}ion-tabs.tabs-striped.tabs-color-active-stable .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-stable .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-stable .tab-item.tab-item-active{border-color:#f8f8f8;color:#f8f8f8}ion-tabs.tabs-color-active-positive .tab-item{color:#444}ion-tabs.tabs-color-active-positive .tab-item.activated,ion-tabs.tabs-color-active-positive .tab-item.active,ion-tabs.tabs-color-active-positive .tab-item.tab-item-active{color:#387ef5}ion-tabs.tabs-striped.tabs-color-active-positive .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-positive .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-positive .tab-item.tab-item-active{border-color:#387ef5;color:#387ef5}ion-tabs.tabs-color-active-calm .tab-item{color:#444}ion-tabs.tabs-color-active-calm .tab-item.activated,ion-tabs.tabs-color-active-calm .tab-item.active,ion-tabs.tabs-color-active-calm .tab-item.tab-item-active{color:#11c1f3}ion-tabs.tabs-striped.tabs-color-active-calm .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-calm .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-calm .tab-item.tab-item-active{border-color:#11c1f3;color:#11c1f3}ion-tabs.tabs-color-active-assertive .tab-item{color:#444}ion-tabs.tabs-color-active-assertive .tab-item.activated,ion-tabs.tabs-color-active-assertive .tab-item.active,ion-tabs.tabs-color-active-assertive .tab-item.tab-item-active{color:#ef473a}ion-tabs.tabs-striped.tabs-color-active-assertive .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-assertive .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-assertive .tab-item.tab-item-active{border-color:#ef473a;color:#ef473a}ion-tabs.tabs-color-active-balanced .tab-item{color:#444}ion-tabs.tabs-color-active-balanced .tab-item.activated,ion-tabs.tabs-color-active-balanced .tab-item.active,ion-tabs.tabs-color-active-balanced .tab-item.tab-item-active{color:#33cd5f}ion-tabs.tabs-striped.tabs-color-active-balanced .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-balanced .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-balanced .tab-item.tab-item-active{border-color:#33cd5f;color:#33cd5f}ion-tabs.tabs-color-active-energized .tab-item{color:#444}ion-tabs.tabs-color-active-energized .tab-item.activated,ion-tabs.tabs-color-active-energized .tab-item.active,ion-tabs.tabs-color-active-energized .tab-item.tab-item-active{color:#ffc900}ion-tabs.tabs-striped.tabs-color-active-energized .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-energized .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-energized .tab-item.tab-item-active{border-color:#ffc900;color:#ffc900}ion-tabs.tabs-color-active-royal .tab-item{color:#444}ion-tabs.tabs-color-active-royal .tab-item.activated,ion-tabs.tabs-color-active-royal .tab-item.active,ion-tabs.tabs-color-active-royal .tab-item.tab-item-active{color:#886aea}ion-tabs.tabs-striped.tabs-color-active-royal .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-royal .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-royal .tab-item.tab-item-active{border-color:#886aea;color:#886aea}ion-tabs.tabs-color-active-dark .tab-item{color:#fff}ion-tabs.tabs-color-active-dark .tab-item.activated,ion-tabs.tabs-color-active-dark .tab-item.active,ion-tabs.tabs-color-active-dark .tab-item.tab-item-active{color:#444}ion-tabs.tabs-striped.tabs-color-active-dark .tab-item.activated,ion-tabs.tabs-striped.tabs-color-active-dark .tab-item.active,ion-tabs.tabs-striped.tabs-color-active-dark .tab-item.tab-item-active{border-color:#444;color:#444}.tabs-top.tabs-striped{padding-bottom:0}.tabs-top.tabs-striped .tab-item{background:0 0;-webkit-transition:color .1s ease;-moz-transition:color .1s ease;-ms-transition:color .1s ease;-o-transition:color .1s ease;transition:color .1s ease}.tabs-top.tabs-striped .tab-item.activated,.tabs-top.tabs-striped .tab-item.active,.tabs-top.tabs-striped .tab-item.tab-item-active{margin-top:1px;border-width:0 0 2px 0!important;border-style:solid}.tabs-top.tabs-striped .tab-item.activated>.badge,.tabs-top.tabs-striped .tab-item.activated>i,.tabs-top.tabs-striped .tab-item.active>.badge,.tabs-top.tabs-striped .tab-item.active>i,.tabs-top.tabs-striped .tab-item.tab-item-active>.badge,.tabs-top.tabs-striped .tab-item.tab-item-active>i{margin-top:-1px}.tabs-top.tabs-striped .tab-item .badge{-webkit-transition:color .2s ease;-moz-transition:color .2s ease;-ms-transition:color .2s ease;-o-transition:color .2s ease;transition:color .2s ease}.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated i,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active i,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active i{display:block;margin-top:-1px}.tabs-top.tabs-striped.tabs-icon-left .tab-item{margin-top:1px}.tabs-top.tabs-striped.tabs-icon-left .tab-item.activated .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.activated i,.tabs-top.tabs-striped.tabs-icon-left .tab-item.active .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.active i,.tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active i{margin-top:-.1em}.tabs-top>.tabs,.tabs.tabs-top{top:44px;padding-top:0;background-position:bottom;border-top-width:0;border-bottom-width:1px}.tabs-top>.tabs .tab-item.activated .badge,.tabs-top>.tabs .tab-item.active .badge,.tabs-top>.tabs .tab-item.tab-item-active .badge,.tabs.tabs-top .tab-item.activated .badge,.tabs.tabs-top .tab-item.active .badge,.tabs.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-top~.bar-header{border-bottom-width:0}.tab-item{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;overflow:hidden;max-width:150px;height:100%;color:inherit;text-align:center;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;font-weight:400;font-size:14px;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;opacity:.7}.tab-item:hover{cursor:pointer}.tab-item.tab-hidden{display:none}.tabs-item-hide>.tabs,.tabs.tabs-item-hide{display:none}.tabs-icon-bottom.tabs .tab-item,.tabs-icon-bottom>.tabs .tab-item,.tabs-icon-top.tabs .tab-item,.tabs-icon-top>.tabs .tab-item{font-size:10px;line-height:14px}#menu .footer .tab-item .icon-help,.tab-item #menu .footer .icon-help,.tab-item .icon,.tab-item .icon-alert,.tab-item .icon-help{display:block;margin:0 auto;height:32px;font-size:32px}.tabs-icon-left.tabs .tab-item,.tabs-icon-left>.tabs .tab-item,.tabs-icon-right.tabs .tab-item,.tabs-icon-right>.tabs .tab-item{font-size:10px}#menu .footer .tabs-icon-left.tabs .tab-item .icon-help,#menu .footer .tabs-icon-left>.tabs .tab-item .icon-help,#menu .footer .tabs-icon-right.tabs .tab-item .icon-help,#menu .footer .tabs-icon-right>.tabs .tab-item .icon-help,.tabs-icon-left.tabs .tab-item #menu .footer .icon-help,.tabs-icon-left.tabs .tab-item .icon,.tabs-icon-left.tabs .tab-item .icon-alert,.tabs-icon-left.tabs .tab-item .icon-help,.tabs-icon-left.tabs .tab-item .tab-title,.tabs-icon-left>.tabs .tab-item #menu .footer .icon-help,.tabs-icon-left>.tabs .tab-item .icon,.tabs-icon-left>.tabs .tab-item .icon-alert,.tabs-icon-left>.tabs .tab-item .icon-help,.tabs-icon-left>.tabs .tab-item .tab-title,.tabs-icon-right.tabs .tab-item #menu .footer .icon-help,.tabs-icon-right.tabs .tab-item .icon,.tabs-icon-right.tabs .tab-item .icon-alert,.tabs-icon-right.tabs .tab-item .icon-help,.tabs-icon-right.tabs .tab-item .tab-title,.tabs-icon-right>.tabs .tab-item #menu .footer .icon-help,.tabs-icon-right>.tabs .tab-item .icon,.tabs-icon-right>.tabs .tab-item .icon-alert,.tabs-icon-right>.tabs .tab-item .icon-help,.tabs-icon-right>.tabs .tab-item .tab-title{display:inline-block;vertical-align:top;margin-top:-.1em}#menu .footer .tabs-icon-left.tabs .tab-item .icon-help:before,#menu .footer .tabs-icon-left>.tabs .tab-item .icon-help:before,#menu .footer .tabs-icon-right.tabs .tab-item .icon-help:before,#menu .footer .tabs-icon-right>.tabs .tab-item .icon-help:before,.tabs-icon-left.tabs .tab-item #menu .footer .icon-help:before,.tabs-icon-left.tabs .tab-item .icon-alert:before,.tabs-icon-left.tabs .tab-item .icon-help:before,.tabs-icon-left.tabs .tab-item .icon:before,.tabs-icon-left.tabs .tab-item .tab-title:before,.tabs-icon-left>.tabs .tab-item #menu .footer .icon-help:before,.tabs-icon-left>.tabs .tab-item .icon-alert:before,.tabs-icon-left>.tabs .tab-item .icon-help:before,.tabs-icon-left>.tabs .tab-item .icon:before,.tabs-icon-left>.tabs .tab-item .tab-title:before,.tabs-icon-right.tabs .tab-item #menu .footer .icon-help:before,.tabs-icon-right.tabs .tab-item .icon-alert:before,.tabs-icon-right.tabs .tab-item .icon-help:before,.tabs-icon-right.tabs .tab-item .icon:before,.tabs-icon-right.tabs .tab-item .tab-title:before,.tabs-icon-right>.tabs .tab-item #menu .footer .icon-help:before,.tabs-icon-right>.tabs .tab-item .icon-alert:before,.tabs-icon-right>.tabs .tab-item .icon-help:before,.tabs-icon-right>.tabs .tab-item .icon:before,.tabs-icon-right>.tabs .tab-item .tab-title:before{font-size:24px;line-height:49px}#menu .footer .tabs-icon-left.tabs .tab-item .icon-help,#menu .footer .tabs-icon-left>.tabs .tab-item .icon-help,.tabs-icon-left.tabs .tab-item #menu .footer .icon-help,.tabs-icon-left.tabs .tab-item .icon,.tabs-icon-left.tabs .tab-item .icon-alert,.tabs-icon-left.tabs .tab-item .icon-help,.tabs-icon-left>.tabs .tab-item #menu .footer .icon-help,.tabs-icon-left>.tabs .tab-item .icon,.tabs-icon-left>.tabs .tab-item .icon-alert,.tabs-icon-left>.tabs .tab-item .icon-help{padding-right:3px}#menu .footer .tabs-icon-right.tabs .tab-item .icon-help,#menu .footer .tabs-icon-right>.tabs .tab-item .icon-help,.tabs-icon-right.tabs .tab-item #menu .footer .icon-help,.tabs-icon-right.tabs .tab-item .icon,.tabs-icon-right.tabs .tab-item .icon-alert,.tabs-icon-right.tabs .tab-item .icon-help,.tabs-icon-right>.tabs .tab-item #menu .footer .icon-help,.tabs-icon-right>.tabs .tab-item .icon,.tabs-icon-right>.tabs .tab-item .icon-alert,.tabs-icon-right>.tabs .tab-item .icon-help{padding-left:3px}#menu .footer .tabs-icon-only.tabs .icon-help,#menu .footer .tabs-icon-only>.tabs .icon-help,.tabs-icon-only.tabs #menu .footer .icon-help,.tabs-icon-only.tabs .icon,.tabs-icon-only.tabs .icon-alert,.tabs-icon-only.tabs .icon-help,.tabs-icon-only>.tabs #menu .footer .icon-help,.tabs-icon-only>.tabs .icon,.tabs-icon-only>.tabs .icon-alert,.tabs-icon-only>.tabs .icon-help{line-height:inherit}.tab-item.has-badge{position:relative}.tab-item .badge{position:absolute;top:4%;right:33%;right:calc(50% - 26px);padding:1px 6px;height:auto;font-size:12px;line-height:16px}.tab-item.activated,.tab-item.active,.tab-item.tab-item-active{opacity:1}.tab-item.activated.tab-item-light,.tab-item.active.tab-item-light,.tab-item.tab-item-active.tab-item-light{color:#fff}.tab-item.activated.tab-item-stable,.tab-item.active.tab-item-stable,.tab-item.tab-item-active.tab-item-stable{color:#f8f8f8}.tab-item.activated.tab-item-positive,.tab-item.active.tab-item-positive,.tab-item.tab-item-active.tab-item-positive{color:#387ef5}.tab-item.activated.tab-item-calm,.tab-item.active.tab-item-calm,.tab-item.tab-item-active.tab-item-calm{color:#11c1f3}.tab-item.activated.tab-item-assertive,.tab-item.active.tab-item-assertive,.tab-item.tab-item-active.tab-item-assertive{color:#ef473a}.tab-item.activated.tab-item-balanced,.tab-item.active.tab-item-balanced,.tab-item.tab-item-active.tab-item-balanced{color:#33cd5f}.tab-item.activated.tab-item-energized,.tab-item.active.tab-item-energized,.tab-item.tab-item-active.tab-item-energized{color:#ffc900}.tab-item.activated.tab-item-royal,.tab-item.active.tab-item-royal,.tab-item.tab-item-active.tab-item-royal{color:#886aea}.tab-item.activated.tab-item-dark,.tab-item.active.tab-item-dark,.tab-item.tab-item-active.tab-item-dark{color:#444}.item.tabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;padding:0}#menu .footer .item.tabs .icon-help:before,.item.tabs #menu .footer .icon-help:before,.item.tabs .icon-alert:before,.item.tabs .icon-help:before,.item.tabs .icon:before{position:relative}.tab-item.disabled,.tab-item[disabled]{opacity:.4;cursor:default;pointer-events:none}.nav-bar-tabs-top.hide~.view-container .tabs-top .tabs{top:0}.pane[hide-nav-bar=true] .has-tabs-top{top:49px}.menu{position:absolute;top:0;bottom:0;z-index:0;overflow:hidden;min-height:100%;max-height:100%;width:275px;background-color:#fff}.menu .scroll-content{z-index:10}.menu .bar-header{z-index:11}.menu-content{-webkit-transform:none;transform:none;box-shadow:-1px 0 2px rgba(0,0,0,.2),1px 0 2px rgba(0,0,0,.2)}.menu-open .menu-content .pane,.menu-open .menu-content .scroll-content{pointer-events:none}.menu-open .menu-content .scroll-content .scroll{pointer-events:none}.menu-open .menu-content .scroll-content:not(.overflow-scroll){overflow:hidden}.grade-b .menu-content,.grade-c .menu-content{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;right:-1px;left:-1px;border-right:1px solid #ccc;border-left:1px solid #ccc;box-shadow:none}.menu-left{left:0}.menu-right{right:0}.aside-open.aside-resizing .menu-right{display:none}.menu-animated{-webkit-transition:-webkit-transform .2s ease;transition:transform .2s ease}.modal-backdrop,.modal-backdrop-bg{position:fixed;top:0;left:0;z-index:10;width:100%;height:100%}.modal-backdrop-bg{pointer-events:none}.modal{display:block;position:absolute;top:0;z-index:10;overflow:hidden;min-height:100%;width:100%;background-color:#fff}@media (min-width:680px){.modal{top:20%;right:20%;bottom:20%;left:20%;min-height:240px;width:60%}.modal.ng-leave-active{bottom:0}.platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader){height:44px}.platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader)>*{margin-top:0}.platform-ios.platform-cordova .modal-wrapper .modal .tabs-top>.tabs,.platform-ios.platform-cordova .modal-wrapper .modal .tabs.tabs-top{top:44px}.platform-ios.platform-cordova .modal-wrapper .modal .bar-subheader,.platform-ios.platform-cordova .modal-wrapper .modal .has-header{top:44px}.platform-ios.platform-cordova .modal-wrapper .modal .has-subheader{top:88px}.platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-tabs-top{top:93px}.platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-subheader.has-tabs-top{top:137px}.modal-backdrop-bg{-webkit-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out;background-color:#000;opacity:0}.active .modal-backdrop-bg{opacity:.5}}.modal-open{pointer-events:none}.modal-open .modal,.modal-open .modal-backdrop{pointer-events:auto}.modal-open.loading-active .modal,.modal-open.loading-active .modal-backdrop{pointer-events:none}.popover-backdrop{position:fixed;top:0;left:0;z-index:10;width:100%;height:100%;background-color:rgba(0,0,0,0)}.popover-backdrop.active{background-color:rgba(0,0,0,.1)}.popover{position:absolute;top:25%;left:50%;z-index:10;display:block;margin-top:12px;margin-left:-110px;height:280px;width:220px;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.4);opacity:0}.popover .item:first-child{border-top:0}.popover .item:last-child{border-bottom:0}.popover.popover-bottom{margin-top:-12px}.popover,.popover .bar-header{border-radius:2px}.popover .scroll-content{z-index:1;margin:2px 0}.popover .bar-header{border-bottom-right-radius:0;border-bottom-left-radius:0}.popover .has-header{border-top-right-radius:0;border-top-left-radius:0}.popover-arrow{display:none}.platform-ios .popover{box-shadow:0 0 40px rgba(0,0,0,.08);border-radius:10px}.platform-ios .popover .bar-header{-webkit-border-top-right-radius:10px;border-top-right-radius:10px;-webkit-border-top-left-radius:10px;border-top-left-radius:10px}.platform-ios .popover .scroll-content{margin:8px 0;border-radius:10px}.platform-ios .popover .scroll-content.has-header{margin-top:0}.platform-ios .popover-arrow{position:absolute;display:block;top:-17px;width:30px;height:19px;overflow:hidden}.platform-ios .popover-arrow:after{position:absolute;top:12px;left:5px;width:20px;height:20px;background-color:#fff;border-radius:3px;content:'';-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.platform-ios .popover-bottom .popover-arrow{top:auto;bottom:-10px}.platform-ios .popover-bottom .popover-arrow:after{top:-6px}.platform-android .popover{margin-top:-32px;background-color:#fafafa;box-shadow:0 2px 6px rgba(0,0,0,.35)}.platform-android .popover .item{border-color:#fafafa;background-color:#fafafa;color:#4d4d4d}.platform-android .popover.popover-bottom{margin-top:32px}.platform-android .popover-backdrop,.platform-android .popover-backdrop.active{background-color:transparent}.popover-open{pointer-events:none}.popover-open .popover,.popover-open .popover-backdrop{pointer-events:auto}.popover-open.loading-active .popover,.popover-open.loading-active .popover-backdrop{pointer-events:none}@media (min-width:680px){.popover{width:360px;margin-left:-180px}}.popup-container{position:absolute;top:0;left:0;bottom:0;right:0;background:rgba(0,0,0,0);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;z-index:12;visibility:hidden}.popup-container.popup-showing{visibility:visible}.popup-container.popup-hidden .popup{-webkit-animation-name:scaleOut;animation-name:scaleOut;-webkit-animation-duration:.1s;animation-duration:.1s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.popup-container.active .popup{-webkit-animation-name:superScaleIn;animation-name:superScaleIn;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.popup-container .popup{width:250px;max-width:100%;max-height:90%;border-radius:0;background-color:rgba(255,255,255,.9);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.popup-container input,.popup-container textarea{width:100%}.popup-head{padding:15px 10px;border-bottom:1px solid #eee;text-align:center}.popup-title{margin:0;padding:0;font-size:15px}.popup-sub-title{margin:5px 0 0 0;padding:0;font-weight:400;font-size:11px}.popup-body{padding:10px;overflow:auto}.popup-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;flex-direction:row;padding:10px;min-height:65px}.popup-buttons .button{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;min-height:45px;border-radius:2px;line-height:20px;margin-right:5px}.popup-buttons .button:last-child{margin-right:0}.popup-open{pointer-events:none}.popup-open.modal-open .modal{pointer-events:none}.popup-open .popup,.popup-open .popup-backdrop{pointer-events:auto}.loading-container{position:absolute;left:0;top:0;right:0;bottom:0;z-index:13;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;-webkit-transition:.2s opacity linear;transition:.2s opacity linear;visibility:hidden;opacity:0}#menu .footer .loading-container:not(.visible) .icon-help,.loading-container:not(.visible) #menu .footer .icon-help,.loading-container:not(.visible) .icon,.loading-container:not(.visible) .icon-alert,.loading-container:not(.visible) .icon-help,.loading-container:not(.visible) .spinner{display:none}.loading-container.visible{visibility:visible}.loading-container.active{opacity:1}.loading-container .loading{padding:20px;border-radius:5px;background-color:rgba(0,0,0,.7);color:#fff;text-align:center;text-overflow:ellipsis;font-size:15px}.loading-container .loading h1,.loading-container .loading h2,.loading-container .loading h3,.loading-container .loading h4,.loading-container .loading h5,.loading-container .loading h6{color:#fff}.item{border-color:#ddd;background-color:#fff;color:#444;position:relative;z-index:2;display:block;margin:-1px;padding:16px;border-width:1px;border-style:solid;font-size:16px}.item h2{margin:0 0 2px 0;font-size:16px;font-weight:400}.item h3{margin:0 0 4px 0;font-size:14px}.item h4{margin:0 0 4px 0;font-size:12px}.item h5,.item h6{margin:0 0 3px 0;font-size:10px}.item p{color:#666;font-size:14px;margin-bottom:2px}.item h1:last-child,.item h2:last-child,.item h3:last-child,.item h4:last-child,.item h5:last-child,.item h6:last-child,.item p:last-child{margin-bottom:0}.item .badge{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;position:absolute;top:16px;right:32px}.item.item-button-right .badge{right:67px}.item.item-divider .badge{top:8px}.item .badge+.badge{margin-right:5px}.item.item-light{border-color:#ddd;background-color:#fff;color:#444}.item.item-stable{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.item.item-positive{border-color:#0c60ee;background-color:#387ef5;color:#fff}.item.item-calm{border-color:#0a9dc7;background-color:#11c1f3;color:#fff}.item.item-assertive{border-color:#e42112;background-color:#ef473a;color:#fff}.item.item-balanced{border-color:#28a54c;background-color:#33cd5f;color:#fff}.item.item-energized{border-color:#e6b500;background-color:#ffc900;color:#fff}.item.item-royal{border-color:#6b46e5;background-color:#886aea;color:#fff}.item.item-dark{border-color:#111;background-color:#444;color:#fff}.item[ng-click]:hover{cursor:pointer}.item-borderless,.list-borderless .item{border-width:0}.item .item-content.activated,.item .item-content.active,.item-complex.activated .item-content,.item-complex.active .item-content,.item.activated,.item.active{border-color:#ccc;background-color:#d9d9d9}.item .item-content.activated.item-complex>.item-content,.item .item-content.active.item-complex>.item-content,.item-complex.activated .item-content.item-complex>.item-content,.item-complex.active .item-content.item-complex>.item-content,.item.activated.item-complex>.item-content,.item.active.item-complex>.item-content{border-color:#ccc;background-color:#d9d9d9}.item .item-content.activated.item-light,.item .item-content.active.item-light,.item-complex.activated .item-content.item-light,.item-complex.active .item-content.item-light,.item.activated.item-light,.item.active.item-light{border-color:#ccc;background-color:#fafafa}.item .item-content.activated.item-light.item-complex>.item-content,.item .item-content.active.item-light.item-complex>.item-content,.item-complex.activated .item-content.item-light.item-complex>.item-content,.item-complex.active .item-content.item-light.item-complex>.item-content,.item.activated.item-light.item-complex>.item-content,.item.active.item-light.item-complex>.item-content{border-color:#ccc;background-color:#fafafa}.item .item-content.activated.item-stable,.item .item-content.active.item-stable,.item-complex.activated .item-content.item-stable,.item-complex.active .item-content.item-stable,.item.activated.item-stable,.item.active.item-stable{border-color:#a2a2a2;background-color:#e5e5e5}.item .item-content.activated.item-stable.item-complex>.item-content,.item .item-content.active.item-stable.item-complex>.item-content,.item-complex.activated .item-content.item-stable.item-complex>.item-content,.item-complex.active .item-content.item-stable.item-complex>.item-content,.item.activated.item-stable.item-complex>.item-content,.item.active.item-stable.item-complex>.item-content{border-color:#a2a2a2;background-color:#e5e5e5}.item .item-content.activated.item-positive,.item .item-content.active.item-positive,.item-complex.activated .item-content.item-positive,.item-complex.active .item-content.item-positive,.item.activated.item-positive,.item.active.item-positive{border-color:#0c60ee;background-color:#0c60ee}.item .item-content.activated.item-positive.item-complex>.item-content,.item .item-content.active.item-positive.item-complex>.item-content,.item-complex.activated .item-content.item-positive.item-complex>.item-content,.item-complex.active .item-content.item-positive.item-complex>.item-content,.item.activated.item-positive.item-complex>.item-content,.item.active.item-positive.item-complex>.item-content{border-color:#0c60ee;background-color:#0c60ee}.item .item-content.activated.item-calm,.item .item-content.active.item-calm,.item-complex.activated .item-content.item-calm,.item-complex.active .item-content.item-calm,.item.activated.item-calm,.item.active.item-calm{border-color:#0a9dc7;background-color:#0a9dc7}.item .item-content.activated.item-calm.item-complex>.item-content,.item .item-content.active.item-calm.item-complex>.item-content,.item-complex.activated .item-content.item-calm.item-complex>.item-content,.item-complex.active .item-content.item-calm.item-complex>.item-content,.item.activated.item-calm.item-complex>.item-content,.item.active.item-calm.item-complex>.item-content{border-color:#0a9dc7;background-color:#0a9dc7}.item .item-content.activated.item-assertive,.item .item-content.active.item-assertive,.item-complex.activated .item-content.item-assertive,.item-complex.active .item-content.item-assertive,.item.activated.item-assertive,.item.active.item-assertive{border-color:#e42112;background-color:#e42112}.item .item-content.activated.item-assertive.item-complex>.item-content,.item .item-content.active.item-assertive.item-complex>.item-content,.item-complex.activated .item-content.item-assertive.item-complex>.item-content,.item-complex.active .item-content.item-assertive.item-complex>.item-content,.item.activated.item-assertive.item-complex>.item-content,.item.active.item-assertive.item-complex>.item-content{border-color:#e42112;background-color:#e42112}.item .item-content.activated.item-balanced,.item .item-content.active.item-balanced,.item-complex.activated .item-content.item-balanced,.item-complex.active .item-content.item-balanced,.item.activated.item-balanced,.item.active.item-balanced{border-color:#28a54c;background-color:#28a54c}.item .item-content.activated.item-balanced.item-complex>.item-content,.item .item-content.active.item-balanced.item-complex>.item-content,.item-complex.activated .item-content.item-balanced.item-complex>.item-content,.item-complex.active .item-content.item-balanced.item-complex>.item-content,.item.activated.item-balanced.item-complex>.item-content,.item.active.item-balanced.item-complex>.item-content{border-color:#28a54c;background-color:#28a54c}.item .item-content.activated.item-energized,.item .item-content.active.item-energized,.item-complex.activated .item-content.item-energized,.item-complex.active .item-content.item-energized,.item.activated.item-energized,.item.active.item-energized{border-color:#e6b500;background-color:#e6b500}.item .item-content.activated.item-energized.item-complex>.item-content,.item .item-content.active.item-energized.item-complex>.item-content,.item-complex.activated .item-content.item-energized.item-complex>.item-content,.item-complex.active .item-content.item-energized.item-complex>.item-content,.item.activated.item-energized.item-complex>.item-content,.item.active.item-energized.item-complex>.item-content{border-color:#e6b500;background-color:#e6b500}.item .item-content.activated.item-royal,.item .item-content.active.item-royal,.item-complex.activated .item-content.item-royal,.item-complex.active .item-content.item-royal,.item.activated.item-royal,.item.active.item-royal{border-color:#6b46e5;background-color:#6b46e5}.item .item-content.activated.item-royal.item-complex>.item-content,.item .item-content.active.item-royal.item-complex>.item-content,.item-complex.activated .item-content.item-royal.item-complex>.item-content,.item-complex.active .item-content.item-royal.item-complex>.item-content,.item.activated.item-royal.item-complex>.item-content,.item.active.item-royal.item-complex>.item-content{border-color:#6b46e5;background-color:#6b46e5}.item .item-content.activated.item-dark,.item .item-content.active.item-dark,.item-complex.activated .item-content.item-dark,.item-complex.active .item-content.item-dark,.item.activated.item-dark,.item.active.item-dark{border-color:#000;background-color:#262626}.item .item-content.activated.item-dark.item-complex>.item-content,.item .item-content.active.item-dark.item-complex>.item-content,.item-complex.activated .item-content.item-dark.item-complex>.item-content,.item-complex.active .item-content.item-dark.item-complex>.item-content,.item.activated.item-dark.item-complex>.item-content,.item.active.item-dark.item-complex>.item-content{border-color:#000;background-color:#262626}.item,.item h1,.item h2,.item h3,.item h4,.item h5,.item h6,.item p,.item-content,.item-content h1,.item-content h2,.item-content h3,.item-content h4,.item-content h5,.item-content h6,.item-content p{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}a.item{color:inherit;text-decoration:none}a.item:focus,a.item:hover{text-decoration:none}.item-complex,a.item.item-complex,button.item.item-complex{padding:0}.item-complex .item-content,.item-radio .item-content{position:relative;z-index:2;padding:16px 49px 16px 16px;border:none;background-color:#fff}a.item-content{display:block;color:inherit;text-decoration:none}.item-body h1,.item-body h2,.item-body h3,.item-body h4,.item-body h5,.item-body h6,.item-body p,.item-complex.item-text-wrap .item-content,.item-text-wrap,.item-text-wrap .item,.item-text-wrap .item-content,.item-text-wrap h1,.item-text-wrap h2,.item-text-wrap h3,.item-text-wrap h4,.item-text-wrap h5,.item-text-wrap h6,.item-text-wrap p{overflow:visible;white-space:normal}.item-complex.item-text-wrap,.item-complex.item-text-wrap h1,.item-complex.item-text-wrap h2,.item-complex.item-text-wrap h3,.item-complex.item-text-wrap h4,.item-complex.item-text-wrap h5,.item-complex.item-text-wrap h6,.item-complex.item-text-wrap p{overflow:visible;white-space:normal}.item-complex.item-light>.item-content{border-color:#ddd;background-color:#fff;color:#444}.item-complex.item-light>.item-content.active,.item-complex.item-light>.item-content:active{border-color:#ccc;background-color:#fafafa}.item-complex.item-light>.item-content.active.item-complex>.item-content,.item-complex.item-light>.item-content:active.item-complex>.item-content{border-color:#ccc;background-color:#fafafa}.item-complex.item-stable>.item-content{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.item-complex.item-stable>.item-content.active,.item-complex.item-stable>.item-content:active{border-color:#a2a2a2;background-color:#e5e5e5}.item-complex.item-stable>.item-content.active.item-complex>.item-content,.item-complex.item-stable>.item-content:active.item-complex>.item-content{border-color:#a2a2a2;background-color:#e5e5e5}.item-complex.item-positive>.item-content{border-color:#0c60ee;background-color:#387ef5;color:#fff}.item-complex.item-positive>.item-content.active,.item-complex.item-positive>.item-content:active{border-color:#0c60ee;background-color:#0c60ee}.item-complex.item-positive>.item-content.active.item-complex>.item-content,.item-complex.item-positive>.item-content:active.item-complex>.item-content{border-color:#0c60ee;background-color:#0c60ee}.item-complex.item-calm>.item-content{border-color:#0a9dc7;background-color:#11c1f3;color:#fff}.item-complex.item-calm>.item-content.active,.item-complex.item-calm>.item-content:active{border-color:#0a9dc7;background-color:#0a9dc7}.item-complex.item-calm>.item-content.active.item-complex>.item-content,.item-complex.item-calm>.item-content:active.item-complex>.item-content{border-color:#0a9dc7;background-color:#0a9dc7}.item-complex.item-assertive>.item-content{border-color:#e42112;background-color:#ef473a;color:#fff}.item-complex.item-assertive>.item-content.active,.item-complex.item-assertive>.item-content:active{border-color:#e42112;background-color:#e42112}.item-complex.item-assertive>.item-content.active.item-complex>.item-content,.item-complex.item-assertive>.item-content:active.item-complex>.item-content{border-color:#e42112;background-color:#e42112}.item-complex.item-balanced>.item-content{border-color:#28a54c;background-color:#33cd5f;color:#fff}.item-complex.item-balanced>.item-content.active,.item-complex.item-balanced>.item-content:active{border-color:#28a54c;background-color:#28a54c}.item-complex.item-balanced>.item-content.active.item-complex>.item-content,.item-complex.item-balanced>.item-content:active.item-complex>.item-content{border-color:#28a54c;background-color:#28a54c}.item-complex.item-energized>.item-content{border-color:#e6b500;background-color:#ffc900;color:#fff}.item-complex.item-energized>.item-content.active,.item-complex.item-energized>.item-content:active{border-color:#e6b500;background-color:#e6b500}.item-complex.item-energized>.item-content.active.item-complex>.item-content,.item-complex.item-energized>.item-content:active.item-complex>.item-content{border-color:#e6b500;background-color:#e6b500}.item-complex.item-royal>.item-content{border-color:#6b46e5;background-color:#886aea;color:#fff}.item-complex.item-royal>.item-content.active,.item-complex.item-royal>.item-content:active{border-color:#6b46e5;background-color:#6b46e5}.item-complex.item-royal>.item-content.active.item-complex>.item-content,.item-complex.item-royal>.item-content:active.item-complex>.item-content{border-color:#6b46e5;background-color:#6b46e5}.item-complex.item-dark>.item-content{border-color:#111;background-color:#444;color:#fff}.item-complex.item-dark>.item-content.active,.item-complex.item-dark>.item-content:active{border-color:#000;background-color:#262626}.item-complex.item-dark>.item-content.active.item-complex>.item-content,.item-complex.item-dark>.item-content:active.item-complex>.item-content{border-color:#000;background-color:#262626}#menu .footer .item-icon-left .icon-help,#menu .footer .item-icon-right .icon-help,.item-icon-left #menu .footer .icon-help,.item-icon-left .icon,.item-icon-left .icon-alert,.item-icon-left .icon-help,.item-icon-right #menu .footer .icon-help,.item-icon-right .icon,.item-icon-right .icon-alert,.item-icon-right .icon-help{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%;font-size:32px}#menu .footer .item-icon-left .icon-help:before,#menu .footer .item-icon-right .icon-help:before,.item-icon-left #menu .footer .icon-help:before,.item-icon-left .icon-alert:before,.item-icon-left .icon-help:before,.item-icon-left .icon:before,.item-icon-right #menu .footer .icon-help:before,.item-icon-right .icon-alert:before,.item-icon-right .icon-help:before,.item-icon-right .icon:before{display:block;width:32px;text-align:center}.item .fill-icon{min-width:30px;min-height:30px;font-size:28px}.item-icon-left{padding-left:54px}#menu .footer .item-icon-left .icon-help,.item-icon-left #menu .footer .icon-help,.item-icon-left .icon,.item-icon-left .icon-alert,.item-icon-left .icon-help{left:11px}.item-complex.item-icon-left{padding-left:0}.item-complex.item-icon-left .item-content{padding-left:54px}.item-icon-right{padding-right:54px}#menu .footer .item-icon-right .icon-help,.item-icon-right #menu .footer .icon-help,.item-icon-right .icon,.item-icon-right .icon-alert,.item-icon-right .icon-help{right:11px}.item-complex.item-icon-right{padding-right:0}.item-complex.item-icon-right .item-content{padding-right:54px}#menu .footer .item-icon-left.item-icon-right .icon-help:first-child,.item-icon-left.item-icon-right #menu .footer .icon-help:first-child,.item-icon-left.item-icon-right .icon-alert:first-child,.item-icon-left.item-icon-right .icon-help:first-child,.item-icon-left.item-icon-right .icon:first-child{right:auto}#menu .footer .item-icon-left .item-delete .icon-help,#menu .footer .item-icon-left.item-icon-right .icon-help:last-child,.item-icon-left .item-delete #menu .footer .icon-help,.item-icon-left .item-delete .icon,.item-icon-left .item-delete .icon-alert,.item-icon-left .item-delete .icon-help,.item-icon-left.item-icon-right #menu .footer .icon-help:last-child,.item-icon-left.item-icon-right .icon-alert:last-child,.item-icon-left.item-icon-right .icon-help:last-child,.item-icon-left.item-icon-right .icon:last-child{left:auto}.item-icon-left .icon-accessory,.item-icon-right .icon-accessory{color:#ccc;font-size:16px}.item-icon-left .icon-accessory{left:3px}.item-icon-right .icon-accessory{right:3px}.item-button-left{padding-left:72px}.item-button-left .item-content>.button,.item-button-left>.button{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:8px;left:11px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}#menu .footer .item-button-left .item-content>.button .icon-help:before,#menu .footer .item-button-left>.button .icon-help:before,.item-button-left .item-content>.button #menu .footer .icon-help:before,.item-button-left .item-content>.button .icon-alert:before,.item-button-left .item-content>.button .icon-help:before,.item-button-left .item-content>.button .icon:before,.item-button-left>.button #menu .footer .icon-help:before,.item-button-left>.button .icon-alert:before,.item-button-left>.button .icon-help:before,.item-button-left>.button .icon:before{position:relative;left:auto;width:auto;line-height:31px}.item-button-left .item-content>.button>.button,.item-button-left>.button>.button{margin:0 2px;min-height:34px;font-size:18px;line-height:32px}.item-button-right,a.item.item-button-right,button.item.item-button-right{padding-right:80px}.item-button-right .item-content>.button,.item-button-right .item-content>.buttons,.item-button-right>.button,.item-button-right>.buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:8px;right:16px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}#menu .footer .item-button-right .item-content>.button .icon-help:before,#menu .footer .item-button-right .item-content>.buttons .icon-help:before,#menu .footer .item-button-right>.button .icon-help:before,#menu .footer .item-button-right>.buttons .icon-help:before,.item-button-right .item-content>.button #menu .footer .icon-help:before,.item-button-right .item-content>.button .icon-alert:before,.item-button-right .item-content>.button .icon-help:before,.item-button-right .item-content>.button .icon:before,.item-button-right .item-content>.buttons #menu .footer .icon-help:before,.item-button-right .item-content>.buttons .icon-alert:before,.item-button-right .item-content>.buttons .icon-help:before,.item-button-right .item-content>.buttons .icon:before,.item-button-right>.button #menu .footer .icon-help:before,.item-button-right>.button .icon-alert:before,.item-button-right>.button .icon-help:before,.item-button-right>.button .icon:before,.item-button-right>.buttons #menu .footer .icon-help:before,.item-button-right>.buttons .icon-alert:before,.item-button-right>.buttons .icon-help:before,.item-button-right>.buttons .icon:before{position:relative;left:auto;width:auto;line-height:31px}.item-button-right .item-content>.button>.button,.item-button-right .item-content>.buttons>.button,.item-button-right>.button>.button,.item-button-right>.buttons>.button{margin:0 2px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}.item-button-left.item-button-right .button:first-child{right:auto}.item-button-left.item-button-right .button:last-child{left:auto}.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{padding-left:72px;min-height:72px}.item-avatar .item-content .item-image,.item-avatar .item-content>img:first-child,.item-avatar .item-image,.item-avatar-left .item-content .item-image,.item-avatar-left .item-content>img:first-child,.item-avatar-left .item-image,.item-avatar-left>img:first-child,.item-avatar>img:first-child{position:absolute;top:16px;left:16px;max-width:40px;max-height:40px;width:100%;height:100%;border-radius:50%}.item-avatar-right,.item-avatar-right .item-content{padding-right:72px;min-height:72px}.item-avatar-right .item-content .item-image,.item-avatar-right .item-content>img:first-child,.item-avatar-right .item-image,.item-avatar-right>img:first-child{position:absolute;top:16px;right:16px;max-width:40px;max-height:40px;width:100%;height:100%;border-radius:50%}.item-thumbnail-left,.item-thumbnail-left .item-content{padding-top:8px;padding-left:106px;min-height:100px}.item-thumbnail-left .item-content .item-image,.item-thumbnail-left .item-content>img:first-child,.item-thumbnail-left .item-image,.item-thumbnail-left>img:first-child{position:absolute;top:10px;left:10px;max-width:80px;max-height:80px;width:100%;height:100%}.item-avatar-left.item-complex,.item-avatar.item-complex,.item-thumbnail-left.item-complex{padding-top:0;padding-left:0}.item-thumbnail-right,.item-thumbnail-right .item-content{padding-top:8px;padding-right:106px;min-height:100px}.item-thumbnail-right .item-content .item-image,.item-thumbnail-right .item-content>img:first-child,.item-thumbnail-right .item-image,.item-thumbnail-right>img:first-child{position:absolute;top:10px;right:10px;max-width:80px;max-height:80px;width:100%;height:100%}.item-avatar-right.item-complex,.item-thumbnail-right.item-complex{padding-top:0;padding-right:0}.item-image{padding:0;text-align:center}.item-image .list-img,.item-image img:first-child{width:100%;vertical-align:middle}.item-body{overflow:auto;padding:16px;text-overflow:inherit;white-space:normal}.item-body h1,.item-body h2,.item-body h3,.item-body h4,.item-body h5,.item-body h6,.item-body p{margin-top:16px;margin-bottom:16px}.item-divider{padding-top:8px;padding-bottom:8px;min-height:30px;background-color:#f5f5f5;color:#222;font-weight:500}.item-divider-ios,.platform-ios .item-divider-platform{padding-top:26px;text-transform:uppercase;font-weight:300;font-size:13px;background-color:#efeff4;color:#555}.item-divider-android,.platform-android .item-divider-platform{font-weight:300;font-size:13px}.item-note{float:right;color:#aaa;font-size:14px}.item-left-editable .item-content,.item-right-editable .item-content{-webkit-transition-duration:250ms;transition-duration:250ms;-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;transition-property:transform}.item-left-editing.item-left-editable .item-content,.list-left-editing .item-left-editable .item-content{-webkit-transform:translate3d(50px,0,0);transform:translate3d(50px,0,0)}.item-remove-animate.ng-leave{-webkit-transition-duration:.3s;transition-duration:.3s}.item-remove-animate.ng-leave .item-content,.item-remove-animate.ng-leave:last-of-type{-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;-webkit-transition-property:all;transition-property:all}.item-remove-animate.ng-leave.ng-leave-active .item-content{opacity:0;-webkit-transform:translate3d(-100%,0,0)!important;transform:translate3d(-100%,0,0)!important}.item-remove-animate.ng-leave.ng-leave-active:last-of-type{opacity:0}.item-remove-animate.ng-leave.ng-leave-active~ion-item:not(.ng-leave){-webkit-transform:translate3d(0,-webkit-calc(-100% + 1px),0);transform:translate3d(0,calc(-100% + 1px),0);-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-timing-function:cubic-bezier(.25,.81,.24,1);transition-timing-function:cubic-bezier(.25,.81,.24,1);-webkit-transition-property:all;transition-property:all}.item-left-edit{-webkit-transition:all ease-in-out 125ms;transition:all ease-in-out 125ms;position:absolute;top:0;left:0;z-index:0;width:50px;height:100%;line-height:100%;display:none;opacity:0;-webkit-transform:translate3d(-21px,0,0);transform:translate3d(-21px,0,0)}.item-left-edit .button{height:100%}#menu .footer .item-left-edit .button.icon-help,.item-left-edit #menu .footer .button.icon-help,.item-left-edit .button.icon,.item-left-edit .button.icon-alert,.item-left-edit .button.icon-help{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%}.item-left-edit.visible{display:block}.item-left-edit.visible.active{opacity:1;-webkit-transform:translate3d(8px,0,0);transform:translate3d(8px,0,0)}.list-left-editing .item-left-edit{-webkit-transition-delay:125ms;transition-delay:125ms}#menu .footer .item-delete .button.icon-help,.item-delete #menu .footer .button.icon-help,.item-delete .button.icon,.item-delete .button.icon-alert,.item-delete .button.icon-help{color:#ef473a;font-size:24px}#menu .footer .item-delete .button.icon-help:hover,.item-delete #menu .footer .button.icon-help:hover,.item-delete .button.icon-alert:hover,.item-delete .button.icon-help:hover,.item-delete .button.icon:hover{opacity:.7}.item-right-edit{-webkit-transition:all ease-in-out 250ms;transition:all ease-in-out 250ms;position:absolute;top:0;right:0;z-index:3;width:75px;height:100%;background:inherit;padding-left:20px;display:block;opacity:0;-webkit-transform:translate3d(75px,0,0);transform:translate3d(75px,0,0)}.item-right-edit .button{min-width:50px;height:100%}#menu .footer .item-right-edit .button.icon-help,.item-right-edit #menu .footer .button.icon-help,.item-right-edit .button.icon,.item-right-edit .button.icon-alert,.item-right-edit .button.icon-help{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%;font-size:32px}.item-right-edit.visible{display:block}.item-right-edit.visible.active{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}#menu .footer .item-reorder .button.icon-help,.item-reorder #menu .footer .button.icon-help,.item-reorder .button.icon,.item-reorder .button.icon-alert,.item-reorder .button.icon-help{color:#444;font-size:32px}.item-reordering{position:absolute;left:0;top:0;z-index:9;width:100%;box-shadow:0 0 10px 0 #aaa}.item-reordering .item-reorder{z-index:9}.item-placeholder{opacity:.7}.item-options{position:absolute;top:0;right:0;z-index:1;height:100%}.item-options .button{height:100%;border:none;border-radius:0;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}.item-options .button:before{margin:0 auto}.item-options ion-option-button:last-child{padding-right:calc(constant(safe-area-inset-right) + 12px);padding-right:calc(env(safe-area-inset-right) + 12px)}.list{position:relative;padding-top:1px;padding-bottom:1px;padding-left:0;margin-bottom:20px}.list:last-child{margin-bottom:0}.list:last-child.card{margin-bottom:40px}.list-header{margin-top:20px;padding:5px 15px;background-color:transparent;color:#222;font-weight:700}.card.list .list-item{padding-right:1px;padding-left:1px}.card,.list-inset{overflow:hidden;margin:20px 10px;border-radius:2px;background-color:#fff}.card{padding-top:1px;padding-bottom:1px;box-shadow:0 1px 3px rgba(0,0,0,.3)}.card .item{border-left:0;border-right:0}.card .item:first-child{border-top:0}.card .item:last-child{border-bottom:0}.item.large-button-bar .card,.item.large-button-bar .list-inset,.padding .card,.padding .list-inset{margin-left:0;margin-right:0}.card .item:first-child,.item.large-button-bar>.list .item:first-child,.list-inset .item:first-child,.padding>.list .item:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.card .item:first-child .item-content,.item.large-button-bar>.list .item:first-child .item-content,.list-inset .item:first-child .item-content,.padding>.list .item:first-child .item-content{border-top-left-radius:2px;border-top-right-radius:2px}.card .item:last-child,.item.large-button-bar>.list .item:last-child,.list-inset .item:last-child,.padding>.list .item:last-child{border-bottom-right-radius:2px;border-bottom-left-radius:2px}.card .item:last-child .item-content,.item.large-button-bar>.list .item:last-child .item-content,.list-inset .item:last-child .item-content,.padding>.list .item:last-child .item-content{border-bottom-right-radius:2px;border-bottom-left-radius:2px}.card .item:last-child,.list-inset .item:last-child{margin-bottom:-1px}.card .item,.item.large-button-bar>.list .item,.list-inset .item,.padding-horizontal>.list .item,.padding>.list .item{margin-right:0;margin-left:0}.card .item.item-input input,.item.large-button-bar>.list .item.item-input input,.list-inset .item.item-input input,.padding-horizontal>.list .item.item-input input,.padding>.list .item.item-input input{padding-right:44px}.padding-left>.list .item{margin-left:0}.padding-right>.list .item,.popover-share .bar-footer .button-close>.list .item{margin-right:0}.badge{background-color:transparent;color:#aaa;z-index:1;display:inline-block;padding:3px 8px;min-width:10px;border-radius:10px;vertical-align:baseline;text-align:center;white-space:nowrap;font-weight:700;font-size:14px;line-height:16px}.badge:empty{display:none}.badge.badge-light,.tabs .tab-item .badge.badge-light{background-color:#fff;color:#444}.badge.badge-stable,.tabs .tab-item .badge.badge-stable{background-color:#f8f8f8;color:#444}.badge.badge-positive,.tabs .tab-item .badge.badge-positive{background-color:#387ef5;color:#fff}.badge.badge-calm,.tabs .tab-item .badge.badge-calm{background-color:#11c1f3;color:#fff}.badge.badge-assertive,.badge.badge-editable:hover,.tabs .tab-item .badge.badge-assertive,.tabs .tab-item .badge.badge-editable:hover{background-color:#ef473a;color:#fff}.badge.badge-balanced,.tabs .tab-item .badge.badge-balanced{background-color:#33cd5f;color:#fff}.badge.badge-energized,.tabs .tab-item .badge.badge-energized{background-color:#ffc900;color:#fff}.badge.badge-royal,.tabs .tab-item .badge.badge-royal{background-color:#886aea;color:#fff}.badge.badge-dark,.tabs .tab-item .badge.badge-dark{background-color:#444;color:#fff}.button .badge{position:relative;top:-1px}.slider{position:relative;visibility:hidden;overflow:hidden}.slider-slides{position:relative;height:100%}.slider-slide{position:relative;display:block;float:left;width:100%;height:100%;vertical-align:top}.slider-slide-image>img{width:100%}.slider-pager{position:absolute;bottom:20px;z-index:1;width:100%;height:15px;text-align:center}.slider-pager .slider-pager-page{display:inline-block;margin:0 3px;width:15px;color:#000;text-decoration:none;opacity:.3}.slider-pager .slider-pager-page.active{-webkit-transition:opacity .4s ease-in;transition:opacity .4s ease-in;opacity:1}.slider-pager-page.ng-animate,.slider-pager-page.ng-enter,.slider-pager-page.ng-leave,.slider-slide.ng-animate,.slider-slide.ng-enter,.slider-slide.ng-leave{-webkit-transition:none!important;transition:none!important}.slider-pager-page.ng-animate,.slider-slide.ng-animate{-webkit-animation:none 0s;animation:none 0s}.swiper-container{margin:0 auto;position:relative;overflow:hidden;z-index:1}.swiper-container-no-flexbox .swiper-slide{float:left}.swiper-container-vertical>.swiper-wrapper{-webkit-box-orient:vertical;-moz-box-orient:vertical;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.swiper-wrapper{position:relative;width:100%;height:100%;z-index:1;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.swiper-container-android .swiper-slide,.swiper-wrapper{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate(0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.swiper-container-multirow>.swiper-wrapper{-webkit-box-lines:multiple;-moz-box-lines:multiple;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap}.swiper-container-free-mode>.swiper-wrapper{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out;margin:0 auto}.swiper-slide{display:block;-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;width:100%;height:100%;position:relative}.swiper-container-autoheight,.swiper-container-autoheight .swiper-slide{height:auto}.swiper-container-autoheight .swiper-wrapper{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start;-webkit-transition-property:-webkit-transform,height;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform,height}.swiper-container .swiper-notification{position:absolute;left:0;top:0;pointer-events:none;opacity:0;z-index:-1000}.swiper-wp8-horizontal{-ms-touch-action:pan-y;touch-action:pan-y}.swiper-wp8-vertical{-ms-touch-action:pan-x;touch-action:pan-x}.swiper-button-next,.swiper-button-prev{position:absolute;top:50%;width:27px;height:44px;margin-top:-22px;z-index:10;cursor:pointer;-moz-background-size:27px 44px;-webkit-background-size:27px 44px;background-size:27px 44px;background-position:center;background-repeat:no-repeat}.swiper-button-next.swiper-button-disabled,.swiper-button-prev.swiper-button-disabled{opacity:.35;cursor:auto;pointer-events:none}.swiper-button-prev,.swiper-container-rtl .swiper-button-next{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");left:10px;right:auto}.swiper-button-prev.swiper-button-black,.swiper-container-rtl .swiper-button-next.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-prev.swiper-button-white,.swiper-container-rtl .swiper-button-next.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next,.swiper-container-rtl .swiper-button-prev{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");right:10px;left:auto}.swiper-button-next.swiper-button-black,.swiper-container-rtl .swiper-button-prev.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next.swiper-button-white,.swiper-container-rtl .swiper-button-prev.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-pagination{position:absolute;text-align:center;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;transition:.3s;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0);z-index:10}.swiper-pagination.swiper-pagination-hidden{opacity:0}.swiper-pagination-bullet{width:8px;height:8px;display:inline-block;border-radius:100%;background:#000;opacity:.2}button.swiper-pagination-bullet{border:none;margin:0;padding:0;box-shadow:none;-moz-appearance:none;-ms-appearance:none;-webkit-appearance:none;appearance:none}.swiper-pagination-clickable .swiper-pagination-bullet{cursor:pointer}.swiper-pagination-white .swiper-pagination-bullet{background:#fff}.swiper-pagination-bullet-active{opacity:1}.swiper-pagination-white .swiper-pagination-bullet-active{background:#fff}.swiper-pagination-black .swiper-pagination-bullet-active{background:#000}.swiper-container-vertical>.swiper-pagination{right:10px;top:50%;-webkit-transform:translate3d(0,-50%,0);-moz-transform:translate3d(0,-50%,0);-o-transform:translate(0,-50%);-ms-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.swiper-container-vertical>.swiper-pagination .swiper-pagination-bullet{margin:5px 0;display:block}.swiper-container-horizontal>.swiper-pagination{bottom:10px;left:0;width:100%}.swiper-container-horizontal>.swiper-pagination .swiper-pagination-bullet{margin:0 5px}.swiper-container-3d{-webkit-perspective:1200px;-moz-perspective:1200px;-o-perspective:1200px;perspective:1200px}.swiper-container-3d .swiper-cube-shadow,.swiper-container-3d .swiper-slide,.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top,.swiper-container-3d .swiper-wrapper{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;transform-style:preserve-3d}.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10}.swiper-container-3d .swiper-slide-shadow-left{background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(right,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(right,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(right,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to left,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-3d .swiper-slide-shadow-right{background-image:-webkit-gradient(linear,right top,left top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(left,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(left,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to right,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-3d .swiper-slide-shadow-top{background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(bottom,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(bottom,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(bottom,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to top,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-3d .swiper-slide-shadow-bottom{background-image:-webkit-gradient(linear,left bottom,left top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(top,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(top,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(top,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to bottom,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-coverflow .swiper-wrapper{-ms-perspective:1200px}.swiper-container-fade.swiper-container-free-mode .swiper-slide{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out}.swiper-container-fade .swiper-slide{pointer-events:none}.swiper-container-fade .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-fade .swiper-slide-active,.swiper-container-fade .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-container-cube{overflow:visible}.swiper-container-cube .swiper-slide{pointer-events:none;visibility:hidden;-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;width:100%;height:100%;z-index:1}.swiper-container-cube.swiper-container-rtl .swiper-slide{-webkit-transform-origin:100% 0;-moz-transform-origin:100% 0;-ms-transform-origin:100% 0;transform-origin:100% 0}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-next,.swiper-container-cube .swiper-slide-next+.swiper-slide,.swiper-container-cube .swiper-slide-prev{pointer-events:auto;visibility:visible}.swiper-container-cube .swiper-slide-shadow-bottom,.swiper-container-cube .swiper-slide-shadow-left,.swiper-container-cube .swiper-slide-shadow-right,.swiper-container-cube .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.swiper-container-cube .swiper-cube-shadow{position:absolute;left:0;bottom:0;width:100%;height:100%;background:#000;opacity:.6;-webkit-filter:blur(50px);filter:blur(50px);z-index:0}.swiper-scrollbar{border-radius:10px;position:relative;-ms-touch-action:none;background:rgba(0,0,0,.1)}.swiper-container-horizontal>.swiper-scrollbar{position:absolute;left:1%;bottom:3px;z-index:50;height:5px;width:98%}.swiper-container-vertical>.swiper-scrollbar{position:absolute;right:3px;top:1%;z-index:50;width:5px;height:98%}.swiper-scrollbar-drag{height:100%;width:100%;position:relative;background:rgba(0,0,0,.5);border-radius:10px;left:0;top:0}.swiper-scrollbar-cursor-drag{cursor:move}.swiper-lazy-preloader{width:42px;height:42px;position:absolute;left:50%;top:50%;margin-left:-21px;margin-top:-21px;z-index:10;-webkit-transform-origin:50%;-moz-transform-origin:50%;transform-origin:50%;-webkit-animation:swiper-preloader-spin 1s steps(12,end) infinite;-moz-animation:swiper-preloader-spin 1s steps(12,end) infinite;animation:swiper-preloader-spin 1s steps(12,end) infinite}.swiper-lazy-preloader:after{display:block;content:"";width:100%;height:100%;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");background-position:50%;-webkit-background-size:100%;background-size:100%;background-repeat:no-repeat}.swiper-lazy-preloader-white:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}@-webkit-keyframes swiper-preloader-spin{100%{-webkit-transform:rotate(360deg)}}@keyframes swiper-preloader-spin{100%{transform:rotate(360deg)}}ion-slides{width:100%;height:100%;display:block}.slide-zoom{display:block;width:100%;text-align:center}.swiper-container{width:100%;height:100%;padding:0;overflow:hidden}.swiper-wrapper{position:absolute;left:0;top:0;width:100%;height:100%;padding:0}.swiper-slide{width:100%;height:100%;box-sizing:border-box}.swiper-slide img{width:auto;height:auto;max-width:100%;max-height:100%}.scroll-refresher{position:absolute;top:-60px;right:0;left:0;overflow:hidden;margin:auto;height:60px}.scroll-refresher .ionic-refresher-content{position:absolute;bottom:15px;left:0;width:100%;color:#666;text-align:center;font-size:30px}.scroll-refresher .ionic-refresher-content .text-pulling,.scroll-refresher .ionic-refresher-content .text-refreshing{font-size:16px;line-height:16px}.scroll-refresher .ionic-refresher-content.ionic-refresher-with-text{bottom:10px}.scroll-refresher .icon-pulling,.scroll-refresher .icon-refreshing{width:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.scroll-refresher .icon-pulling{-webkit-animation-name:refresh-spin-back;animation-name:refresh-spin-back;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:none;animation-fill-mode:none;-webkit-transform:translate3d(0,0,0) rotate(0);transform:translate3d(0,0,0) rotate(0)}.scroll-refresher .icon-refreshing,.scroll-refresher .text-refreshing{display:none}.scroll-refresher .icon-refreshing{-webkit-animation-duration:1.5s;animation-duration:1.5s}.scroll-refresher.active .icon-pulling:not(.pulling-rotation-disabled){-webkit-animation-name:refresh-spin;animation-name:refresh-spin;-webkit-transform:translate3d(0,0,0) rotate(-180deg);transform:translate3d(0,0,0) rotate(-180deg)}.scroll-refresher.active.refreshing{-webkit-transition:-webkit-transform .2s;transition:-webkit-transform .2s;-webkit-transition:transform .2s;transition:transform .2s;-webkit-transform:scale(1,1);transform:scale(1,1)}.scroll-refresher.active.refreshing .icon-pulling,.scroll-refresher.active.refreshing .text-pulling{display:none}.scroll-refresher.active.refreshing .icon-refreshing,.scroll-refresher.active.refreshing .text-refreshing{display:block}.scroll-refresher.active.refreshing.refreshing-tail{-webkit-transform:scale(0,0);transform:scale(0,0)}.overflow-scroll>.scroll{-webkit-overflow-scrolling:touch;width:100%}.overflow-scroll>.scroll.overscroll{position:fixed;right:0;left:0}.overflow-scroll.item.large-button-bar>.scroll.overscroll,.overflow-scroll.padding>.scroll.overscroll{padding:10px}@-webkit-keyframes refresh-spin{0%{-webkit-transform:translate3d(0,0,0) rotate(0)}100%{-webkit-transform:translate3d(0,0,0) rotate(180deg)}}@keyframes refresh-spin{0%{transform:translate3d(0,0,0) rotate(0)}100%{transform:translate3d(0,0,0) rotate(180deg)}}@-webkit-keyframes refresh-spin-back{0%{-webkit-transform:translate3d(0,0,0) rotate(180deg)}100%{-webkit-transform:translate3d(0,0,0) rotate(0)}}@keyframes refresh-spin-back{0%{transform:translate3d(0,0,0) rotate(180deg)}100%{transform:translate3d(0,0,0) rotate(0)}}.spinner{stroke:#444;fill:#444}.spinner svg{width:28px;height:28px}.spinner.spinner-light{stroke:#fff;fill:#fff}.spinner.spinner-stable{stroke:#f8f8f8;fill:#f8f8f8}.spinner.spinner-positive{stroke:#387ef5;fill:#387ef5}.spinner.spinner-calm{stroke:#11c1f3;fill:#11c1f3}.spinner.spinner-balanced{stroke:#33cd5f;fill:#33cd5f}.spinner.spinner-assertive{stroke:#ef473a;fill:#ef473a}.spinner.spinner-energized{stroke:#ffc900;fill:#ffc900}.spinner.spinner-royal{stroke:#886aea;fill:#886aea}.spinner.spinner-dark{stroke:#444;fill:#444}.spinner-android{stroke:#4b8bf4}.spinner-ios,.spinner-ios-small{stroke:#69717d}.spinner-spiral .stop1{stop-color:#fff;stop-opacity:0}.spinner-spiral.spinner-light .stop1{stop-color:#444}.spinner-spiral.spinner-light .stop2{stop-color:#fff}.spinner-spiral.spinner-stable .stop2{stop-color:#f8f8f8}.spinner-spiral.spinner-positive .stop2{stop-color:#387ef5}.spinner-spiral.spinner-calm .stop2{stop-color:#11c1f3}.spinner-spiral.spinner-balanced .stop2{stop-color:#33cd5f}.spinner-spiral.spinner-assertive .stop2{stop-color:#ef473a}.spinner-spiral.spinner-energized .stop2{stop-color:#ffc900}.spinner-spiral.spinner-royal .stop2{stop-color:#886aea}.spinner-spiral.spinner-dark .stop2{stop-color:#444}form{margin:0 0 1.42857}legend{display:block;margin-bottom:1.42857;padding:0;width:100%;border:1px solid #ddd;color:#444;font-size:21px;line-height:2.85714}legend small{color:#f8f8f8;font-size:1.07143}button,input,label,select,textarea{font-weight:400;font-size:14px;line-height:1.42857}button,input,select,textarea{font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif}.item-input{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:relative;overflow:hidden;padding:6px 0 5px 16px}.item-input input{-webkit-border-radius:0;border-radius:0;-webkit-box-flex:1;-webkit-flex:1 220px;-moz-box-flex:1;-moz-flex:1 220px;-ms-flex:1 220px;flex:1 220px;-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0;padding-right:24px;background-color:transparent}#menu .footer .item-input .button .icon-help,.item-input .button #menu .footer .icon-help,.item-input .button .icon,.item-input .button .icon-alert,.item-input .button .icon-help{-webkit-box-flex:0;-webkit-flex:0 0 24px;-moz-box-flex:0;-moz-flex:0 0 24px;-ms-flex:0 0 24px;flex:0 0 24px;position:static;display:inline-block;height:auto;text-align:center;font-size:16px}.item-input .button-bar{-webkit-border-radius:0;border-radius:0;-webkit-box-flex:1;-webkit-flex:1 0 220px;-moz-box-flex:1;-moz-flex:1 0 220px;-ms-flex:1 0 220px;flex:1 0 220px;-webkit-appearance:none;-moz-appearance:none;appearance:none}#menu .footer .item-input .icon-help,.item-input #menu .footer .icon-help,.item-input .icon,.item-input .icon-alert,.item-input .icon-help{min-width:14px}.platform-windowsphone .item-input input{flex-shrink:1}.item-input-inset{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:relative;overflow:hidden;padding:10.66667px}.item-input-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0;-moz-box-flex:1;-moz-flex:1 0;-ms-flex:1 0;flex:1 0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;-webkit-border-radius:4px;border-radius:4px;padding-right:8px;padding-left:8px;background:#eee}.item-input-inset .item-input-wrapper input{padding-left:4px;height:29px;background:0 0;line-height:18px}.item-input-wrapper~.button{margin-left:10.66667px}.input-label{display:table;padding:7px 10px 7px 0;max-width:200px;width:35%;color:#444;font-size:16px}.placeholder-icon{color:#aaa}.placeholder-icon:first-child{padding-right:6px}.placeholder-icon:last-child{padding-left:6px}.item-stacked-label{display:block;background-color:transparent;box-shadow:none}#menu .footer .item-stacked-label .icon-help,.item-stacked-label #menu .footer .icon-help,.item-stacked-label .icon,.item-stacked-label .icon-alert,.item-stacked-label .icon-help,.item-stacked-label .input-label{display:inline-block;padding:4px 0 0 0;vertical-align:middle}.item-stacked-label input,.item-stacked-label textarea{-webkit-border-radius:2px;border-radius:2px;padding:4px 8px 3px 0;border:none;background-color:#fff}.item-stacked-label input{overflow:hidden;height:46px}.item-select.item-stacked-label select{position:relative;padding:0;max-width:90%;direction:ltr;white-space:pre-wrap;margin:-3px}.item-floating-label{display:block;background-color:transparent;box-shadow:none}.item-floating-label .input-label{position:relative;padding:5px 0 0 0;opacity:0;top:10px;-webkit-transition:opacity .15s ease-in,top .2s linear;transition:opacity .15s ease-in,top .2s linear}.item-floating-label .input-label.has-input{opacity:1;top:0;-webkit-transition:opacity .15s ease-in,top .2s linear;transition:opacity .15s ease-in,top .2s linear}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],textarea{display:block;padding-top:2px;padding-left:0;height:34px;color:#111;vertical-align:middle;font-size:14px;line-height:16px}.platform-android input[type=date],.platform-android input[type=datetime-local],.platform-android input[type=month],.platform-android input[type=time],.platform-android input[type=week],.platform-ios input[type=date],.platform-ios input[type=datetime-local],.platform-ios input[type=month],.platform-ios input[type=time],.platform-ios input[type=week]{padding-top:8px}.item-input input,.item-input textarea{width:100%}textarea{padding-left:0}textarea::-moz-placeholder{color:#aaa}textarea:-ms-input-placeholder{color:#aaa}textarea::-webkit-input-placeholder{color:#aaa;text-indent:-3px}textarea{height:auto}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],textarea{border:0}input[type=checkbox],input[type=radio]{margin:0;line-height:normal}.item-input input[type=button],.item-input input[type=checkbox],.item-input input[type=file],.item-input input[type=image],.item-input input[type=radio],.item-input input[type=reset],.item-input input[type=submit]{width:auto}input[type=file]{line-height:34px}.cloned-text-input+input,.cloned-text-input+textarea,.previous-input-focus{position:absolute!important;left:-9999px;width:200px}input::-moz-placeholder,textarea::-moz-placeholder{color:#aaa}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#aaa}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#aaa;text-indent:0}input[disabled],input[readonly]:not(.cloned-text-input),select[disabled],select[readonly],textarea[disabled],textarea[readonly]:not(.cloned-text-input){background-color:#f8f8f8;cursor:not-allowed}input[type=checkbox][disabled],input[type=checkbox][readonly],input[type=radio][disabled],input[type=radio][readonly]{background-color:transparent}.checkbox{position:relative;display:inline-block;padding:7px 7px;cursor:pointer}.checkbox .checkbox-icon:before,.checkbox input:before{border-color:#ddd}.checkbox input:checked+.checkbox-icon:before,.checkbox input:checked:before{background:#387ef5;border-color:#387ef5}.checkbox-light .checkbox-icon:before,.checkbox-light input:before{border-color:#ddd}.checkbox-light input:checked+.checkbox-icon:before,.checkbox-light input:checked:before{background:#ddd;border-color:#ddd}.checkbox-stable .checkbox-icon:before,.checkbox-stable input:before{border-color:#b2b2b2}.checkbox-stable input:checked+.checkbox-icon:before,.checkbox-stable input:checked:before{background:#b2b2b2;border-color:#b2b2b2}.checkbox-positive .checkbox-icon:before,.checkbox-positive input:before{border-color:#387ef5}.checkbox-positive input:checked+.checkbox-icon:before,.checkbox-positive input:checked:before{background:#387ef5;border-color:#387ef5}.checkbox-calm .checkbox-icon:before,.checkbox-calm input:before{border-color:#11c1f3}.checkbox-calm input:checked+.checkbox-icon:before,.checkbox-calm input:checked:before{background:#11c1f3;border-color:#11c1f3}.checkbox-assertive .checkbox-icon:before,.checkbox-assertive input:before{border-color:#ef473a}.checkbox-assertive input:checked+.checkbox-icon:before,.checkbox-assertive input:checked:before{background:#ef473a;border-color:#ef473a}.checkbox-balanced .checkbox-icon:before,.checkbox-balanced input:before{border-color:#33cd5f}.checkbox-balanced input:checked+.checkbox-icon:before,.checkbox-balanced input:checked:before{background:#33cd5f;border-color:#33cd5f}.checkbox-energized .checkbox-icon:before,.checkbox-energized input:before{border-color:#ffc900}.checkbox-energized input:checked+.checkbox-icon:before,.checkbox-energized input:checked:before{background:#ffc900;border-color:#ffc900}.checkbox-royal .checkbox-icon:before,.checkbox-royal input:before{border-color:#886aea}.checkbox-royal input:checked+.checkbox-icon:before,.checkbox-royal input:checked:before{background:#886aea;border-color:#886aea}.checkbox-dark .checkbox-icon:before,.checkbox-dark input:before{border-color:#444}.checkbox-dark input:checked+.checkbox-icon:before,.checkbox-dark input:checked:before{background:#444;border-color:#444}.checkbox input:disabled+.checkbox-icon:before,.checkbox input:disabled:before{border-color:#ddd}.checkbox input:disabled:checked+.checkbox-icon:before,.checkbox input:disabled:checked:before{background:#ddd}.checkbox.checkbox-input-hidden input{display:none!important}.checkbox input,.checkbox-icon{position:relative;width:28px;height:28px;display:block;border:0;background:0 0;cursor:pointer;-webkit-appearance:none}.checkbox input:before,.checkbox-icon:before{display:table;width:100%;height:100%;border-width:1px;border-style:solid;border-radius:28px;background:#fff;content:' ';-webkit-transition:background-color 20ms ease-in-out;transition:background-color 20ms ease-in-out}.checkbox input:checked:before,input:checked+.checkbox-icon:before{border-width:2px}.checkbox input:after,.checkbox-icon:after{-webkit-transition:opacity 50ms ease-in-out;transition:opacity 50ms ease-in-out;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);position:absolute;top:33%;left:25%;display:table;width:14px;height:6px;border:1px solid #fff;border-top:0;border-right:0;content:' ';opacity:0}.checkbox-square .checkbox-icon:before,.checkbox-square input:before,.platform-android .checkbox-platform .checkbox-icon:before,.platform-android .checkbox-platform input:before{border-radius:2px;width:72%;height:72%;margin-top:14%;margin-left:14%;border-width:2px}.checkbox-square .checkbox-icon:after,.checkbox-square input:after,.platform-android .checkbox-platform .checkbox-icon:after,.platform-android .checkbox-platform input:after{border-width:2px;top:19%;left:25%;width:13px;height:7px}.platform-android .item-checkbox-right .checkbox-square .checkbox-icon::after{top:31%}.grade-c .checkbox input:after,.grade-c .checkbox-icon:after{-webkit-transform:rotate(0);transform:rotate(0);top:3px;left:4px;border:none;color:#fff;content:'\2713';font-weight:700;font-size:20px}.checkbox input:checked:after,input:checked+.checkbox-icon:after{opacity:1}.item-checkbox{padding-left:60px}.item-checkbox.active{box-shadow:none}.item-checkbox .checkbox{position:absolute;top:50%;right:8px;left:8px;z-index:3;margin-top:-21px}.item-checkbox.item-checkbox-right{padding-right:60px;padding-left:16px}.item-checkbox-right .checkbox input,.item-checkbox-right .checkbox-icon{float:right}.item-toggle{pointer-events:none}.toggle{position:relative;display:inline-block;pointer-events:auto;margin:-5px;padding:5px}.toggle input:checked+.track{border-color:#4cd964;background-color:#4cd964}.toggle.dragging .handle{background-color:#f2f2f2!important}.toggle.toggle-light input:checked+.track{border-color:#ddd;background-color:#ddd}.toggle.toggle-stable input:checked+.track{border-color:#b2b2b2;background-color:#b2b2b2}.toggle.toggle-positive input:checked+.track{border-color:#387ef5;background-color:#387ef5}.toggle.toggle-calm input:checked+.track{border-color:#11c1f3;background-color:#11c1f3}.toggle.toggle-assertive input:checked+.track{border-color:#ef473a;background-color:#ef473a}.toggle.toggle-balanced input:checked+.track{border-color:#33cd5f;background-color:#33cd5f}.toggle.toggle-energized input:checked+.track{border-color:#ffc900;background-color:#ffc900}.toggle.toggle-royal input:checked+.track{border-color:#886aea;background-color:#886aea}.toggle.toggle-dark input:checked+.track{border-color:#444;background-color:#444}.toggle input{display:none}.toggle .track{-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:background-color,border;transition-property:background-color,border;display:inline-block;box-sizing:border-box;width:51px;height:31px;border:solid 2px #e6e6e6;border-radius:20px;background-color:#fff;content:' ';cursor:pointer;pointer-events:none}.platform-android4_2 .toggle .track{-webkit-background-clip:padding-box}.toggle .handle{-webkit-transition:.3s cubic-bezier(0,1.1,1,1.1);transition:.3s cubic-bezier(0,1.1,1,1.1);-webkit-transition-property:background-color,transform;transition-property:background-color,transform;position:absolute;display:block;width:27px;height:27px;border-radius:27px;background-color:#fff;top:7px;left:7px;box-shadow:0 2px 7px rgba(0,0,0,.35),0 1px 1px rgba(0,0,0,.15)}.toggle .handle:before{position:absolute;top:-4px;left:-21.5px;padding:18.5px 34px;content:" "}.toggle input:checked+.track .handle{-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0);background-color:#fff}.item-toggle.active{box-shadow:none}.item-toggle,.item-toggle.item-complex .item-content{padding-right:99px}.item-toggle.item-complex{padding-right:0}.item-toggle .toggle{position:absolute;top:10px;right:16px;z-index:3}.toggle input:disabled+.track{opacity:.6}.toggle-small .track{border:0;width:34px;height:15px;background:#9e9e9e}.toggle-small input:checked+.track{background:rgba(0,150,137,.5)}.toggle-small .handle{top:2px;left:4px;width:21px;height:21px;box-shadow:0 2px 5px rgba(0,0,0,.25)}.toggle-small input:checked+.track .handle{-webkit-transform:translate3d(16px,0,0);transform:translate3d(16px,0,0);background:#009689}.toggle-small.item-toggle .toggle{top:19px}.toggle-small .toggle-light input:checked+.track{background-color:rgba(221,221,221,.5)}.toggle-small .toggle-light input:checked+.track .handle{background-color:#ddd}.toggle-small .toggle-stable input:checked+.track{background-color:rgba(178,178,178,.5)}.toggle-small .toggle-stable input:checked+.track .handle{background-color:#b2b2b2}.toggle-small .toggle-positive input:checked+.track{background-color:rgba(56,126,245,.5)}.toggle-small .toggle-positive input:checked+.track .handle{background-color:#387ef5}.toggle-small .toggle-calm input:checked+.track{background-color:rgba(17,193,243,.5)}.toggle-small .toggle-calm input:checked+.track .handle{background-color:#11c1f3}.toggle-small .toggle-assertive input:checked+.track{background-color:rgba(239,71,58,.5)}.toggle-small .toggle-assertive input:checked+.track .handle{background-color:#ef473a}.toggle-small .toggle-balanced input:checked+.track{background-color:rgba(51,205,95,.5)}.toggle-small .toggle-balanced input:checked+.track .handle{background-color:#33cd5f}.toggle-small .toggle-energized input:checked+.track{background-color:rgba(255,201,0,.5)}.toggle-small .toggle-energized input:checked+.track .handle{background-color:#ffc900}.toggle-small .toggle-royal input:checked+.track{background-color:rgba(136,106,234,.5)}.toggle-small .toggle-royal input:checked+.track .handle{background-color:#886aea}.toggle-small .toggle-dark input:checked+.track{background-color:rgba(68,68,68,.5)}.toggle-small .toggle-dark input:checked+.track .handle{background-color:#444}.item-radio{padding:0}.item-radio:hover{cursor:pointer}.item-radio .item-content{padding-right:64px}.item-radio .radio-icon{position:absolute;top:0;right:0;z-index:3;visibility:hidden;padding:14px;height:100%;font-size:24px}.item-radio input{position:absolute;left:-9999px}.item-radio input:checked+.radio-content .item-content{background:#f7f7f7}.item-radio input:checked+.radio-content .radio-icon{visibility:visible}.range input{display:inline-block;overflow:hidden;margin-top:5px;margin-bottom:5px;padding-right:2px;padding-left:1px;width:auto;height:43px;outline:0;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(0,#ccc),color-stop(100%,#ccc));background:linear-gradient(to right,#ccc 0,#ccc 100%);background-position:center;background-size:99% 2px;background-repeat:no-repeat;-webkit-appearance:none}.range input::-moz-focus-outer{border:0}.range input::-webkit-slider-thumb{position:relative;width:28px;height:28px;border-radius:50%;background-color:#fff;box-shadow:0 0 2px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2);cursor:pointer;-webkit-appearance:none;border:0}.range input::-webkit-slider-thumb:before{position:absolute;top:13px;left:-2001px;width:2000px;height:2px;background:#444;content:' '}.range input::-webkit-slider-thumb:after{position:absolute;top:-15px;left:-15px;padding:30px;content:' '}.range input::-ms-fill-lower{height:2px;background:#444}.range{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;padding:2px 11px}.range.range-light input::-webkit-slider-thumb:before{background:#ddd}.range.range-light input::-ms-fill-lower{background:#ddd}.range.range-stable input::-webkit-slider-thumb:before{background:#b2b2b2}.range.range-stable input::-ms-fill-lower{background:#b2b2b2}.range.range-positive input::-webkit-slider-thumb:before{background:#387ef5}.range.range-positive input::-ms-fill-lower{background:#387ef5}.range.range-calm input::-webkit-slider-thumb:before{background:#11c1f3}.range.range-calm input::-ms-fill-lower{background:#11c1f3}.range.range-balanced input::-webkit-slider-thumb:before{background:#33cd5f}.range.range-balanced input::-ms-fill-lower{background:#33cd5f}.range.range-assertive input::-webkit-slider-thumb:before{background:#ef473a}.range.range-assertive input::-ms-fill-lower{background:#ef473a}.range.range-energized input::-webkit-slider-thumb:before{background:#ffc900}.range.range-energized input::-ms-fill-lower{background:#ffc900}.range.range-royal input::-webkit-slider-thumb:before{background:#886aea}.range.range-royal input::-ms-fill-lower{background:#886aea}.range.range-dark input::-webkit-slider-thumb:before{background:#444}.range.range-dark input::-ms-fill-lower{background:#444}#menu .footer .range .icon-help,.range #menu .footer .icon-help,.range .icon,.range .icon-alert,.range .icon-help{-webkit-box-flex:0;-webkit-flex:0;-moz-box-flex:0;-moz-flex:0;-ms-flex:0;flex:0;display:block;min-width:24px;text-align:center;font-size:24px}.range input{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;margin-right:10px;margin-left:10px}.range-label{-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-moz-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;display:block;white-space:nowrap}.range-label:first-child{padding-left:5px}.range input+.range-label{padding-right:5px;padding-left:0}.platform-windowsphone .range input{height:auto}.item-select{position:relative}.item-select select{-webkit-appearance:none;-moz-appearance:none;appearance:none;position:absolute;top:0;bottom:0;right:0;padding:0 48px 0 16px;max-width:65%;border:none;background:#fff;color:#333;text-indent:.01px;text-overflow:'';white-space:nowrap;font-size:14px;cursor:pointer;direction:rtl}.item-select select::-ms-expand{display:none}.item-select option{direction:ltr}.item-select:after{position:absolute;top:50%;right:16px;margin-top:-3px;width:0;height:0;border-top:5px solid;border-right:5px solid transparent;border-left:5px solid transparent;color:#999;content:"";pointer-events:none}.item-select.item-light select{background:#fff;color:#444}.item-select.item-stable select{background:#f8f8f8;color:#444}.item-select.item-stable .input-label,.item-select.item-stable:after{color:#666}.item-select.item-positive select{background:#387ef5;color:#fff}.item-select.item-positive .input-label,.item-select.item-positive:after{color:#fff}.item-select.item-calm select{background:#11c1f3;color:#fff}.item-select.item-calm .input-label,.item-select.item-calm:after{color:#fff}.item-select.item-assertive select{background:#ef473a;color:#fff}.item-select.item-assertive .input-label,.item-select.item-assertive:after{color:#fff}.item-select.item-balanced select{background:#33cd5f;color:#fff}.item-select.item-balanced .input-label,.item-select.item-balanced:after{color:#fff}.item-select.item-energized select{background:#ffc900;color:#fff}.item-select.item-energized .input-label,.item-select.item-energized:after{color:#fff}.item-select.item-royal select{background:#886aea;color:#fff}.item-select.item-royal .input-label,.item-select.item-royal:after{color:#fff}.item-select.item-dark select{background:#444;color:#fff}.item-select.item-dark .input-label,.item-select.item-dark:after{color:#fff}select[multiple],select[size]{height:auto}progress{display:block;margin:15px auto;width:100%}.button{border-color:transparent;background-color:#f8f8f8;color:#444;position:relative;display:inline-block;margin:0;padding:0 12px;min-width:52px;min-height:47px;border-width:1px;border-style:solid;border-radius:4px;vertical-align:top;text-align:center;text-overflow:ellipsis;font-size:16px;line-height:42px;cursor:pointer}.button:hover{color:#444;text-decoration:none}.button.activated,.button.active{border-color:#a2a2a2;background-color:#e5e5e5}.button:after{position:absolute;top:-6px;right:-6px;bottom:-6px;left:-6px;content:' '}#menu .footer .button .icon-help,.button #menu .footer .icon-help,.button .icon,.button .icon-alert,.button .icon-help{vertical-align:top;pointer-events:none}#menu .footer .button .icon-help:before,#menu .footer .button.icon-help:before,.button #menu .footer .icon-help:before,.button .icon-alert:before,.button .icon-help:before,.button .icon:before,.button.icon-alert:before,.button.icon-help:before,.button.icon-left:before,.button.icon-right:before,.button.icon:before{display:inline-block;padding:0 0 1px 0;vertical-align:inherit;font-size:24px;line-height:41px;pointer-events:none}.button.icon-left:before{float:left;padding-right:.2em;padding-left:0}.button.icon-right:before{float:right;padding-right:0;padding-left:.2em}.button.button-block,.button.button-full{margin-top:10px;margin-bottom:10px}.button.button-light{border-color:transparent;background-color:#fff;color:#444}.button.button-light:hover{color:#444;text-decoration:none}.button.button-light.activated,.button.button-light.active{border-color:#a2a2a2;background-color:#fafafa}.button.button-light.button-clear,.button.button-light.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#ddd}.button.button-light.button-icon{border-color:transparent;background:0 0}.button.button-light.button-outline{border-color:#ddd;background:0 0;color:#ddd}.button.button-light.button-outline.activated,.button.button-light.button-outline.active{background-color:#ddd;box-shadow:none;color:#fff}.button.button-stable{border-color:transparent;background-color:#f8f8f8;color:#444}.button.button-stable:hover{color:#444;text-decoration:none}.button.button-stable.activated,.button.button-stable.active{border-color:#a2a2a2;background-color:#e5e5e5}.button.button-stable.button-clear,.button.button-stable.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#b2b2b2}.button.button-stable.button-icon{border-color:transparent;background:0 0}.button.button-stable.button-outline{border-color:#b2b2b2;background:0 0;color:#b2b2b2}.button.button-stable.button-outline.activated,.button.button-stable.button-outline.active{background-color:#b2b2b2;box-shadow:none;color:#fff}.button.button-positive,.button.button-text{border-color:transparent;background-color:#387ef5;color:#fff}.button.button-positive:hover,.button.button-text:hover{color:#fff;text-decoration:none}.button.activated.button-text,.button.active.button-text,.button.button-positive.activated,.button.button-positive.active{border-color:#a2a2a2;background-color:#0c60ee}.button.button-positive.button-clear,.button.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#387ef5}.button.button-icon.button-text,.button.button-positive.button-icon{border-color:transparent;background:0 0}.button.button-outline.button-text,.button.button-positive.button-outline{border-color:#387ef5;background:0 0;color:#387ef5}.button.button-outline.activated.button-text,.button.button-outline.active.button-text,.button.button-positive.button-outline.activated,.button.button-positive.button-outline.active{background-color:#387ef5;box-shadow:none;color:#fff}.button.button-calm{border-color:transparent;background-color:#11c1f3;color:#fff}.button.button-calm:hover{color:#fff;text-decoration:none}.button.button-calm.activated,.button.button-calm.active{border-color:#a2a2a2;background-color:#0a9dc7}.button.button-calm.button-clear,.button.button-calm.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#11c1f3}.button.button-calm.button-icon{border-color:transparent;background:0 0}.button.button-calm.button-outline{border-color:#11c1f3;background:0 0;color:#11c1f3}.button.button-calm.button-outline.activated,.button.button-calm.button-outline.active{background-color:#11c1f3;box-shadow:none;color:#fff}.button.button-assertive{border-color:transparent;background-color:#ef473a;color:#fff}.button.button-assertive:hover{color:#fff;text-decoration:none}.button.button-assertive.activated,.button.button-assertive.active{border-color:#a2a2a2;background-color:#e42112}.button.button-assertive.button-clear,.button.button-assertive.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#ef473a}.button.button-assertive.button-icon{border-color:transparent;background:0 0}.button.button-assertive.button-outline{border-color:#ef473a;background:0 0;color:#ef473a}.button.button-assertive.button-outline.activated,.button.button-assertive.button-outline.active{background-color:#ef473a;box-shadow:none;color:#fff}.button.button-balanced{border-color:transparent;background-color:#33cd5f;color:#fff}.button.button-balanced:hover{color:#fff;text-decoration:none}.button.button-balanced.activated,.button.button-balanced.active{border-color:#a2a2a2;background-color:#28a54c}.button.button-balanced.button-clear,.button.button-balanced.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#33cd5f}.button.button-balanced.button-icon{border-color:transparent;background:0 0}.button.button-balanced.button-outline{border-color:#33cd5f;background:0 0;color:#33cd5f}.button.button-balanced.button-outline.activated,.button.button-balanced.button-outline.active{background-color:#33cd5f;box-shadow:none;color:#fff}.button.button-energized{border-color:transparent;background-color:#ffc900;color:#fff}.button.button-energized:hover{color:#fff;text-decoration:none}.button.button-energized.activated,.button.button-energized.active{border-color:#a2a2a2;background-color:#e6b500}.button.button-energized.button-clear,.button.button-energized.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#ffc900}.button.button-energized.button-icon{border-color:transparent;background:0 0}.button.button-energized.button-outline{border-color:#ffc900;background:0 0;color:#ffc900}.button.button-energized.button-outline.activated,.button.button-energized.button-outline.active{background-color:#ffc900;box-shadow:none;color:#fff}.button.button-royal{border-color:transparent;background-color:#886aea;color:#fff}.button.button-royal:hover{color:#fff;text-decoration:none}.button.button-royal.activated,.button.button-royal.active{border-color:#a2a2a2;background-color:#6b46e5}.button.button-royal.button-clear,.button.button-royal.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#886aea}.button.button-royal.button-icon{border-color:transparent;background:0 0}.button.button-royal.button-outline{border-color:#886aea;background:0 0;color:#886aea}.button.button-royal.button-outline.activated,.button.button-royal.button-outline.active{background-color:#886aea;box-shadow:none;color:#fff}.button.button-dark{border-color:transparent;background-color:#444;color:#fff}.button.button-dark:hover{color:#fff;text-decoration:none}.button.button-dark.activated,.button.button-dark.active{border-color:#a2a2a2;background-color:#262626}.button.button-dark.button-clear,.button.button-dark.button-text{border-color:transparent;background:0 0;box-shadow:none;color:#444}.button.button-dark.button-icon{border-color:transparent;background:0 0}.button.button-dark.button-outline{border-color:#444;background:0 0;color:#444}.button.button-dark.button-outline.activated,.button.button-dark.button-outline.active{background-color:#444;box-shadow:none;color:#fff}.button-small,.button-text.button-small{padding:2px 4px 1px;min-width:28px;min-height:30px;font-size:12px;line-height:26px}#menu .footer .button-small .icon-help:before,#menu .footer .button-small.icon-help:before,.button-small #menu .footer .icon-help:before,.button-small .icon-alert:before,.button-small .icon-help:before,.button-small .icon:before,.button-small.icon-alert:before,.button-small.icon-help:before,.button-small.icon-left:before,.button-small.icon-right:before,.button-small.icon:before{font-size:16px;line-height:19px;margin-top:3px}.button-large{padding:0 16px;min-width:68px;min-height:59px;font-size:20px;line-height:53px}#menu .footer .button-large .icon-help:before,#menu .footer .button-large.icon-help:before,.button-large #menu .footer .icon-help:before,.button-large .icon-alert:before,.button-large .icon-help:before,.button-large .icon:before,.button-large.icon-alert:before,.button-large.icon-help:before,.button-large.icon-left:before,.button-large.icon-right:before,.button-large.icon:before{padding-bottom:2px;font-size:32px;line-height:51px}.button-icon{-webkit-transition:opacity .1s;transition:opacity .1s;padding:0 6px;min-width:initial;border-color:transparent;background:0 0}.button-icon.button.activated,.button-icon.button.active{border-color:transparent;background:0 0;box-shadow:none;opacity:.3}#menu .footer .button-icon .icon-help:before,#menu .footer .button-icon.icon-help:before,.button-icon #menu .footer .icon-help:before,.button-icon .icon-alert:before,.button-icon .icon-help:before,.button-icon .icon:before,.button-icon.icon-alert:before,.button-icon.icon-help:before,.button-icon.icon:before{font-size:32px}.button-clear,.button-text{-webkit-transition:opacity .1s;transition:opacity .1s;padding:0 6px;max-height:42px;border-color:transparent;background:0 0;box-shadow:none}.button-clear.button-clear,.button-text{border-color:transparent;background:0 0;box-shadow:none;color:transparent}.button-clear.button-icon,.button-icon.button-text{border-color:transparent;background:0 0}.activated.button-text,.active.button-text,.button-clear.activated,.button-clear.active{opacity:.3}.button-outline{-webkit-transition:opacity .1s;transition:opacity .1s;background:0 0;box-shadow:none}.button-outline.button-outline{border-color:transparent;background:0 0;color:transparent}.button-outline.button-outline.activated,.button-outline.button-outline.active{background-color:transparent;box-shadow:none;color:#fff}.item.large-button-bar>.button.button-block:first-child,.padding>.button.button-block:first-child{margin-top:0}.button-block{display:block;clear:both}.button-block:after{clear:both}.button-full,.button-full>.button{display:block;margin-right:0;margin-left:0;border-right-width:0;border-left-width:0;border-radius:0}.button-full>button.button,button.button-block,button.button-full,input.button.button-block{width:100%}a.button{text-decoration:none}#menu .footer a.button .icon-help:before,#menu .footer a.button.icon-help:before,a.button #menu .footer .icon-help:before,a.button .icon-alert:before,a.button .icon-help:before,a.button .icon:before,a.button.icon-alert:before,a.button.icon-help:before,a.button.icon-left:before,a.button.icon-right:before,a.button.icon:before{margin-top:2px}.button.disabled,.button[disabled]{opacity:.4;cursor:default!important;pointer-events:none}.button-bar{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;width:100%}.button-bar.button-bar-inline{display:block;width:auto}.button-bar.button-bar-inline:after,.button-bar.button-bar-inline:before{display:table;content:"";line-height:0}.button-bar.button-bar-inline:after{clear:both}.button-bar.button-bar-inline>.button{width:auto;display:inline-block;float:left}.button-bar.bar-light>.button{border-color:#ddd}.button-bar.bar-stable>.button{border-color:#b2b2b2}.button-bar.bar-positive>.button{border-color:#0c60ee}.button-bar.bar-calm>.button{border-color:#0a9dc7}.button-bar.bar-assertive>.button{border-color:#e42112}.button-bar.bar-balanced>.button{border-color:#28a54c}.button-bar.bar-energized>.button{border-color:#e6b500}.button-bar.bar-royal>.button{border-color:#6b46e5}.button-bar.bar-dark>.button{border-color:#111}.button-bar>.button{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;overflow:hidden;padding:0 16px;width:0;border-width:1px 0 1px 1px;border-radius:0;text-align:center;text-overflow:ellipsis;white-space:nowrap}#menu .footer .button-bar>.button .icon-help:before,.button-bar>.button #menu .footer .icon-help:before,.button-bar>.button .icon-alert:before,.button-bar>.button .icon-help:before,.button-bar>.button .icon:before,.button-bar>.button:before{line-height:44px}.button-bar>.button:first-child{border-radius:4px 0 0 4px}.button-bar>.button:last-child{border-right-width:1px;border-radius:0 4px 4px 0}.button-bar>.button:only-child{border-radius:4px}#menu .footer .button-bar>.button-small .icon-help:before,.button-bar>.button-small #menu .footer .icon-help:before,.button-bar>.button-small .icon-alert:before,.button-bar>.button-small .icon-help:before,.button-bar>.button-small .icon:before,.button-bar>.button-small:before{line-height:28px}.row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;padding:5px;width:100%}.row-wrap{-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.row-no-padding{padding:0}.row-no-padding>.col{padding:0}.row+.row{margin-top:-5px;padding-top:0}.col{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;padding:5px;width:100%}.row-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;-moz-align-items:flex-start;align-items:flex-start}.row-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;-moz-align-items:flex-end;align-items:flex-end}.row-center{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}.row-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;-moz-align-items:stretch;align-items:stretch}.row-baseline{-webkit-box-align:baseline;-ms-flex-align:baseline;-webkit-align-items:baseline;-moz-align-items:baseline;align-items:baseline}.col-top{-webkit-align-self:flex-start;-moz-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start}.col-bottom{-webkit-align-self:flex-end;-moz-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end}.col-center{-webkit-align-self:center;-moz-align-self:center;-ms-flex-item-align:center;align-self:center}.col-offset-10{margin-left:10%}.col-offset-20{margin-left:20%}.col-offset-25{margin-left:25%}.col-offset-33,.col-offset-34{margin-left:33.3333%}.col-offset-50{margin-left:50%}.col-offset-66,.col-offset-67{margin-left:66.6666%}.col-offset-75{margin-left:75%}.col-offset-80{margin-left:80%}.col-offset-90{margin-left:90%}.col-10{-webkit-box-flex:0;-webkit-flex:0 0 10%;-moz-box-flex:0;-moz-flex:0 0 10%;-ms-flex:0 0 10%;flex:0 0 10%;max-width:10%}.col-20{-webkit-box-flex:0;-webkit-flex:0 0 20%;-moz-box-flex:0;-moz-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.col-25{-webkit-box-flex:0;-webkit-flex:0 0 25%;-moz-box-flex:0;-moz-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-33,.col-34{-webkit-box-flex:0;-webkit-flex:0 0 33.3333%;-moz-box-flex:0;-moz-flex:0 0 33.3333%;-ms-flex:0 0 33.3333%;flex:0 0 33.3333%;max-width:33.3333%}.col-40{-webkit-box-flex:0;-webkit-flex:0 0 40%;-moz-box-flex:0;-moz-flex:0 0 40%;-ms-flex:0 0 40%;flex:0 0 40%;max-width:40%}.col-50{-webkit-box-flex:0;-webkit-flex:0 0 50%;-moz-box-flex:0;-moz-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-60{-webkit-box-flex:0;-webkit-flex:0 0 60%;-moz-box-flex:0;-moz-flex:0 0 60%;-ms-flex:0 0 60%;flex:0 0 60%;max-width:60%}.col-66,.col-67{-webkit-box-flex:0;-webkit-flex:0 0 66.6666%;-moz-box-flex:0;-moz-flex:0 0 66.6666%;-ms-flex:0 0 66.6666%;flex:0 0 66.6666%;max-width:66.6666%}.col-75{-webkit-box-flex:0;-webkit-flex:0 0 75%;-moz-box-flex:0;-moz-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-80{-webkit-box-flex:0;-webkit-flex:0 0 80%;-moz-box-flex:0;-moz-flex:0 0 80%;-ms-flex:0 0 80%;flex:0 0 80%;max-width:80%}.col-90{-webkit-box-flex:0;-webkit-flex:0 0 90%;-moz-box-flex:0;-moz-flex:0 0 90%;-ms-flex:0 0 90%;flex:0 0 90%;max-width:90%}@media (max-width:567px){.responsive-sm{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-sm .col,.responsive-sm .col-10,.responsive-sm .col-20,.responsive-sm .col-25,.responsive-sm .col-33,.responsive-sm .col-34,.responsive-sm .col-50,.responsive-sm .col-66,.responsive-sm .col-67,.responsive-sm .col-75,.responsive-sm .col-80,.responsive-sm .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}@media (max-width:767px){.responsive-md{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-md .col,.responsive-md .col-10,.responsive-md .col-20,.responsive-md .col-25,.responsive-md .col-33,.responsive-md .col-34,.responsive-md .col-50,.responsive-md .col-66,.responsive-md .col-67,.responsive-md .col-75,.responsive-md .col-80,.responsive-md .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}@media (max-width:1023px){.responsive-lg{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-lg .col,.responsive-lg .col-10,.responsive-lg .col-20,.responsive-lg .col-25,.responsive-lg .col-33,.responsive-lg .col-34,.responsive-lg .col-50,.responsive-lg .col-66,.responsive-lg .col-67,.responsive-lg .col-75,.responsive-lg .col-80,.responsive-lg .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}.hide{display:none}.opacity-hide{opacity:0}.grade-b .opacity-hide,.grade-c .opacity-hide{opacity:1;display:none}.show{display:block}.opacity-show{opacity:1}.invisible{visibility:hidden}.keyboard-open .hide-on-keyboard-open{display:none}.keyboard-open .bar-footer.hide-on-keyboard-open+.pane .has-footer,.keyboard-open .tabs.hide-on-keyboard-open+.pane .has-tabs{bottom:0}.inline{display:inline-block}.disable-pointer-events{pointer-events:none}.enable-pointer-events{pointer-events:auto}.disable-user-behavior{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-ms-touch-action:none;-ms-content-zooming:none}.click-block{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;z-index:99999;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);overflow:hidden}.click-block-hide{-webkit-transform:translate3d(-9999px,0,0);transform:translate3d(-9999px,0,0)}.no-resize{resize:none}.block{display:block;clear:both}.block:after{display:block;visibility:hidden;clear:both;height:0;content:"."}.full-image{width:100%}.clearfix:after,.clearfix:before{display:table;content:"";line-height:0}.clearfix:after{clear:both}.item.large-button-bar,.padding{padding:10px}.padding-top,.padding-vertical{padding-top:10px}.padding-horizontal,.padding-right,.popover-share .bar-footer .button-close{padding-right:10px}.padding-bottom,.padding-vertical,.popover-share .bar-footer .button-close{padding-bottom:10px}.padding-horizontal,.padding-left{padding-left:10px}.iframe-wrapper{position:fixed;-webkit-overflow-scrolling:touch;overflow:scroll}.iframe-wrapper iframe{height:100%;width:100%}.rounded{border-radius:4px}.light,a.light{color:#fff}.light-bg{background-color:#fff}.light-border{border-color:#ddd}.stable,a.stable{color:#f8f8f8}.stable-bg{background-color:#f8f8f8}.stable-border{border-color:#b2b2b2}.icon-help,.positive,.text-editable:hover,a.icon-help,a.positive,a.text-editable:hover{color:#387ef5}.positive-bg{background-color:#387ef5}.positive-border{border-color:#0c60ee}#menu .footer .icon-help,#menu .footer a.icon-help,.calm,a.calm{color:#11c1f3}.calm-bg{background-color:#11c1f3}.calm-border{border-color:#0a9dc7}.assertive,.icon-alert,a.assertive,a.icon-alert{color:#ef473a}.assertive-bg{background-color:#ef473a}.assertive-border{border-color:#e42112}.balanced,a.balanced{color:#33cd5f}.balanced-bg{background-color:#33cd5f}.balanced-border{border-color:#28a54c}.energized,a.energized{color:#ffc900}.energized-bg{background-color:#ffc900}.energized-border{border-color:#e6b500}.royal,a.royal{color:#886aea}.royal-bg{background-color:#886aea}.royal-border{border-color:#6b46e5}.button-text-dark,.dark,a.button-text-dark,a.dark{color:#444}.dark-bg{background-color:#444}.dark-border{border-color:#111}[collection-repeat]{left:0!important;top:0!important;position:absolute!important;z-index:1}.collection-repeat-container{position:relative;z-index:1}.collection-repeat-after-container{z-index:0;display:block}.collection-repeat-after-container.horizontal{display:inline-block}.ng-cloak,.ng-hide:not(.ng-hide-animate),.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader){height:64px;height:calc(constant(safe-area-inset-top) + 44px);height:calc(env(safe-area-inset-top) + 44px)}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper{margin-top:19px!important}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader)>*{margin-top:20px;margin-top:constant(safe-area-inset-top);margin-top:env(safe-area-inset-top)}.platform-ios.platform-cordova:not(.fullscreen) .bar-header{padding-left:calc(constant(safe-area-inset-left) + 5px);padding-left:calc(env(safe-area-inset-left) + 5px);padding-right:calc(constant(safe-area-inset-right) + 5px);padding-right:calc(env(safe-area-inset-right) + 5px)}.platform-ios.platform-cordova:not(.fullscreen) .bar-header .buttons:last-child{right:calc(constant(safe-area-inset-right) + 5px);right:calc(env(safe-area-inset-right) + 5px)}.platform-ios.platform-cordova:not(.fullscreen) .bar-footer.has-tabs,.platform-ios.platform-cordova:not(.fullscreen) .has-tabs{bottom:calc(constant(safe-area-inset-bottom) + 49px);bottom:calc(env(safe-area-inset-bottom) + 49px)}.platform-ios.platform-cordova:not(.fullscreen) .tabs-top>.tabs,.platform-ios.platform-cordova:not(.fullscreen) .tabs.tabs-top{top:64px}.platform-ios.platform-cordova:not(.fullscreen) .tabs{padding-bottom:constant(safe-area-inset-bottom);padding-bottom:env(safe-area-inset-bottom);height:calc(constant(safe-area-inset-bottom) + 49px);height:calc(env(safe-area-inset-bottom) + 49px)}.platform-ios.platform-cordova:not(.fullscreen) .bar-subheader,.platform-ios.platform-cordova:not(.fullscreen) .has-header{top:64px;top:calc(constant(safe-area-inset-top) + 44px);top:calc(env(safe-area-inset-top) + 44px)}.platform-ios.platform-cordova:not(.fullscreen) .has-subheader{top:108px;top:calc(constant(safe-area-inset-top) + 88px);top:calc(env(safe-area-inset-top) + 88px)}.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-tabs-top{top:113px;top:calc(93px + constant(safe-area-inset-top));top:calc(93px + env(safe-area-inset-top))}.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-subheader.has-tabs-top{top:157px;top:calc(137px + constant(safe-area-inset-right));top:calc(137px + env(safe-area-inset-right))}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader){height:44px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper{margin-top:-1px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader)>*{margin-top:0}.platform-ios.platform-cordova .popover .bar-subheader,.platform-ios.platform-cordova .popover .has-header{top:44px}.platform-ios.platform-cordova .popover .has-subheader{top:88px}.platform-ios.platform-cordova.status-bar-hide{margin-bottom:20px}@media (orientation:landscape){.item{padding:16px calc(constant(safe-area-inset-right) + 16px)}.item .badge{right:calc(constant(safe-area-inset-right) + 32px)}.item-icon-left{padding-left:calc(constant(safe-area-inset-left) + 54px)}#menu .footer .item-icon-left .icon-help,.item-icon-left #menu .footer .icon-help,.item-icon-left .icon,.item-icon-left .icon-alert,.item-icon-left .icon-help{left:calc(constant(safe-area-inset-left) + 11px)}.item-icon-right{padding-right:calc(constant(safe-area-inset-right) + 54px)}#menu .footer .item-icon-right .icon-help,.item-icon-right #menu .footer .icon-help,.item-icon-right .icon,.item-icon-right .icon-alert,.item-icon-right .icon-help{right:calc(constant(safe-area-inset-right) + 11px)}.item-complex,a.item.item-complex,button.item.item-complex{padding:0}.item-complex .item-content,a.item.item-complex .item-content,button.item.item-complex .item-content{padding:16px calc(constant(safe-area-inset-right) + 49px) 16px calc(constant(safe-area-inset-left) + 16px)}.item-left-edit.visible.active{-webkit-transform:translate3d(calc(constant(safe-area-inset-left) + 8px),0,0);transform:translate3d(calc(constant(safe-area-inset-left) + 8px),0,0)}.item-left-editing.item-left-editable .item-content,.list-left-editing .item-left-editable .item-content{-webkit-transform:translate3d(calc(constant(safe-area-inset-left) + 50px),0,0);transform:translate3d(calc(constant(safe-area-inset-left) + 50px),0,0)}.item-right-edit{right:constant(safe-area-inset-right);right:env(safe-area-inset-right)}.platform-ios.platform-browser.platform-ipad{position:fixed}}.platform-c:not(.enable-transitions) *{-webkit-transition:none!important;transition:none!important}.slide-in-up{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.slide-in-up.ng-enter,.slide-in-up>.ng-enter{-webkit-transition:all cubic-bezier(.1,.7,.1,1) .4s;transition:all cubic-bezier(.1,.7,.1,1) .4s}.slide-in-up.ng-enter-active,.slide-in-up>.ng-enter-active{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.slide-in-up.ng-leave,.slide-in-up>.ng-leave{-webkit-transition:all ease-in-out 250ms;transition:all ease-in-out 250ms}@-webkit-keyframes scaleOut{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@keyframes scaleOut{from{transform:scale(1);opacity:1}to{transform:scale(.8);opacity:0}}@-webkit-keyframes superScaleIn{from{-webkit-transform:scale(1.2);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@keyframes superScaleIn{from{transform:scale(1.2);opacity:0}to{transform:scale(1);opacity:1}}[nav-view-transition=ios] [nav-view=entering],[nav-view-transition=ios] [nav-view=leaving]{-webkit-transition-duration:.5s;transition-duration:.5s;-webkit-transition-timing-function:cubic-bezier(.36,.66,.04,1);transition-timing-function:cubic-bezier(.36,.66,.04,1);-webkit-transition-property:opacity,-webkit-transform,box-shadow;transition-property:opacity,transform,box-shadow}[nav-view-transition=ios][nav-view-direction=back],[nav-view-transition=ios][nav-view-direction=forward]{background-color:#000}[nav-view-transition=ios] [nav-view=active],[nav-view-transition=ios][nav-view-direction=back] [nav-view=leaving],[nav-view-transition=ios][nav-view-direction=forward] [nav-view=entering]{z-index:3}[nav-view-transition=ios][nav-view-direction=back] [nav-view=entering],[nav-view-transition=ios][nav-view-direction=forward] [nav-view=leaving]{z-index:2}[nav-bar-transition=ios] .back-text,[nav-bar-transition=ios] .buttons,[nav-bar-transition=ios] .title{-webkit-transition-duration:.5s;transition-duration:.5s;-webkit-transition-timing-function:cubic-bezier(.36,.66,.04,1);transition-timing-function:cubic-bezier(.36,.66,.04,1);-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,transform}[nav-bar-transition=ios] [nav-bar=active],[nav-bar-transition=ios] [nav-bar=entering]{z-index:10}[nav-bar-transition=ios] [nav-bar=active] .bar,[nav-bar-transition=ios] [nav-bar=entering] .bar{background:0 0}[nav-bar-transition=ios] [nav-bar=cached]{display:block}[nav-bar-transition=ios] [nav-bar=cached] .header-item{display:none}[nav-view-transition=android] [nav-view=entering],[nav-view-transition=android] [nav-view=leaving]{-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-timing-function:cubic-bezier(.4,.6,.2,1);transition-timing-function:cubic-bezier(.4,.6,.2,1);-webkit-transition-property:-webkit-transform;transition-property:transform}[nav-view-transition=android] [nav-view=active],[nav-view-transition=android][nav-view-direction=back] [nav-view=leaving],[nav-view-transition=android][nav-view-direction=forward] [nav-view=entering]{z-index:3}[nav-view-transition=android][nav-view-direction=back] [nav-view=entering],[nav-view-transition=android][nav-view-direction=forward] [nav-view=leaving]{z-index:2}[nav-bar-transition=android] .buttons,[nav-bar-transition=android] .title{-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-timing-function:cubic-bezier(.4,.6,.2,1);transition-timing-function:cubic-bezier(.4,.6,.2,1);-webkit-transition-property:opacity;transition-property:opacity}[nav-bar-transition=android] [nav-bar=active],[nav-bar-transition=android] [nav-bar=entering]{z-index:10}[nav-bar-transition=android] [nav-bar=active] .bar,[nav-bar-transition=android] [nav-bar=entering] .bar{background:0 0}[nav-bar-transition=android] [nav-bar=cached]{display:block}[nav-bar-transition=android] [nav-bar=cached] .header-item{display:none}[nav-swipe=fast] .back-text,[nav-swipe=fast] .buttons,[nav-swipe=fast] .title,[nav-swipe=fast] [nav-view]{-webkit-transition-duration:50ms;transition-duration:50ms;-webkit-transition-timing-function:linear;transition-timing-function:linear}[nav-swipe=slow] .back-text,[nav-swipe=slow] .buttons,[nav-swipe=slow] .title,[nav-swipe=slow] [nav-view]{-webkit-transition-duration:160ms;transition-duration:160ms;-webkit-transition-timing-function:linear;transition-timing-function:linear}[nav-bar=cached],[nav-view=cached]{display:none}[nav-view=stage]{opacity:0;-webkit-transition-duration:0;transition-duration:0}[nav-bar=stage] .back-text,[nav-bar=stage] .buttons,[nav-bar=stage] .title{position:absolute;opacity:0;-webkit-transition-duration:0s;transition-duration:0s}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/Thin/RobotoDraft-Thin.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/Thin/RobotoDraft-Thin.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/Thin/RobotoDraft-Thin.ttf?v=1.1.0) format("truetype");font-weight:100;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/Light/RobotoDraft-Light.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/Light/RobotoDraft-Light.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/Light/RobotoDraft-Light.ttf?v=1.1.0) format("truetype");font-weight:300;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/Regular/RobotoDraft-Regular.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/Italic/RobotoDraft-Italic.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/Medium/RobotoDraft-Medium.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/Medium/RobotoDraft-Medium.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/Medium/RobotoDraft-Medium.ttf?v=1.1.0) format("truetype");font-weight:500;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/Bold/RobotoDraft-Bold.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/robotodraft/fonts/Black/RobotoDraft-Black.woff2?v=1.1.0) format("woff2"),url(../lib/robotodraft/fonts/Black/RobotoDraft-Black.woff?v=1.1.0) format("woff"),url(../lib/robotodraft/fonts/Black/RobotoDraft-Black.ttf?v=1.1.0) format("truetype");font-weight:900;font-style:normal}.item-md-label{display:block;background:0 0;box-shadow:none;margin-left:12px;margin-right:12px;padding:30px 0 0}.item-md-label .input-label{position:absolute;padding:5px 0 0;z-index:2;-webkit-transform:translate3d(0,-30px,0) scale(1);transform:translate3d(0,-30px,0) scale(1);-webkit-transition:all .2s ease;transition:all .2s ease;color:#fff;opacity:.5;-webkit-transform-origin:0;-ms-transform-origin:0;transform-origin:0}.item-md-label input{background-color:rgba(0,0,0,.6);bottom:0;color:#fff;letter-spacing:.25rem;padding:20px 10px;position:relative;z-index:1}.item-md-label .highlight{position:absolute;bottom:0;height:2px;left:0;width:100%;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);-webkit-transition:all .15s ease;transition:all .15s ease;z-index:1}.item-md-label .highlight-light{background:#fff}.item-md-label .highlight-stable{background:#f8f8f8}.item-md-label .highlight-positive{background:#387ef5}.item-md-label .highlight-calm{background:#11c1f3}.item-md-label .highlight-balanced{background:#33cd5f}.item-md-label .highlight-energized{background:#ffc900}.item-md-label .highlight-assertive{background:#ef473a}.item-md-label .highlight-royal{background:#886aea}.item-md-label .highlight-dark{background:#444}.item-md-label .input-label{letter-spacing:.25rem;padding:0 10px}.item-md-label input.used~.input-label,.item-md-label input:focus~.input-label{font-weight:700;opacity:.7;padding:0;text-transform:uppercase;-webkit-transform:translate3d(0,-60px,0) scale(.9);transform:translate3d(0,-60px,0) scale(.9)}.item-md-label input:focus~.highlight{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bar.bar-header.expanded,.expanded .bar.bar-header{height:75px}.bar.bar-header.expanded .title,.expanded.bar.bar-header .title{bottom:0;top:initial;padding-left:16px}.bar.bar-header.expanded .title.fab-left,.expanded .bar.bar-header .title.fab-left{bottom:0;left:90px;position:absolute;right:initial;top:initial}.bar.bar-header.expanded .title.fab-right,.expanded .bar.bar-header .title.fab-right{bottom:0;left:4px;position:absolute;top:initial;right:initial}.bar.bar-header.expanded+.button-fab,.expanded .bar.bar-header+.button-fab{top:50px}.bar.bar-header.expanded.push-down,.expanded .bar.bar-header.push-down{height:44px;overflow:hidden}.bar.bar-header.expanded,.expanded .bar.bar-header{-webkit-transition:height 1s cubic-bezier(.55,0,.1,1);transition:height 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bar.bar-header.expanded+.button-fab,.expanded .bar.bar-header+.button-fab{-webkit-transition:all 1.1s cubic-bezier(.55,0,.1,1);transition:all 1.1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0) scale(1);transform:translate3d(0,0,0) scale(1)}.bar.bar-header.expanded.push-down+.button-fab,.expanded .bar.bar-header.push-down+.button-fab{top:0;-webkit-transform:translate3d(-100px,-100px,0) scale(2.5);transform:translate3d(-100px,-100px,0) scale(2.5)}.bar.bar-header.expanded.push-down .title,.expanded .bar.bar-header.push-down .title{opacity:0;left:initial;right:initial}.bar.bar-header.expanded .title,.expanded .bar.bar-header .title{opacity:1;-webkit-transition:all 2s cubic-bezier(.55,0,.1,1);transition:all 2s cubic-bezier(.55,0,.1,1)}.bar.bar-header.expanded .title,.expanded .bar.bar-header .title{bottom:0;left:42px!important;top:initial}.bar.bar-header.expanded.has-header-fab-left .title,.expanded.has-header-fab-left .bar.bar-header .title{left:76px!important}.bar{z-index:2;font-size:1.3em;width:100%;box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar .button{min-width:38px;z-index:3}.bar .no-text span.back-text{display:none}.bar .title sup{opacity:.7}.bar.bar-header .button+.title{text-align:left;left:35px;line-height:46px}.button-bar{box-shadow:0 1px 3px rgba(0,0,0,.15)}.button-bar>.button{box-shadow:none}#menu .footer .button-bar>.button .icon-help:before,.button-bar>.button #menu .footer .icon-help:before,.button-bar>.button .icon-alert:before,.button-bar>.button .icon-help:before,.button-bar>.button .icon:before,.button-bar>.button:before{line-height:initial}.bar-footer .button-fab{position:absolute;top:-26px;bottom:initial}.bar-footer .buttons-left .button-fab{left:8px}.bar-footer .buttons-right .button-fab{right:8px}.bar .button.button-clear,.bar .button.button-text{box-shadow:none}.left-buttons .button-fab{left:8px;top:16px}.right-buttons .button-fab{right:8px;top:16px}.fab-left.title-left,.fab-left.title.title-left{left:68px}.bar .button.button-fab,.button.button-fab{box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);z-index:9999;width:56px;height:56px;max-height:initial;max-width:initial;border-radius:50%;border-radius:50%;overflow:hidden;padding:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:.3s fade-in-out;transition:.3s fade-in-out;-webkit-transition-property:-webkit-transform,box-shadow;transition-property:transform,box-shadow}.bar .button.button-fab.button-fab-bottom-right,.button.button-fab.button-fab-bottom-right{top:auto;right:16px;bottom:16px;left:auto;position:absolute}.bar .button.button-fab.button-fab-bottom-left,.button.button-fab.button-fab-bottom-left{top:auto;right:auto;bottom:16px;left:16px;position:absolute}.bar .button.button-fab.button-fab-top-right,.button.button-fab.button-fab-top-right{top:32px;right:16px;bottom:auto;left:auto;position:absolute}.bar .button.button-fab.button-fab-top-left,.button.button-fab.button-fab-top-left{top:32px;right:auto;bottom:auto;left:16px;position:absolute}.bar .button.button-fab.button-fab-top-left.expanded,.bar .button.button-fab.button-fab-top-right.expanded,.button.button-fab.button-fab-top-left.expanded,.button.button-fab.button-fab-top-right.expanded{top:48px}.bar .button.button-fab i,.button.button-fab i{font-size:2.5rem;margin-top:0}.bar .button.button-fab.mini,.button.button-fab.mini{width:40px;height:40px}.bar .button.button-fab.mini i,.button.button-fab.mini i{font-size:2rem}.motion{-webkit-transition:all .5s ease-out;transition:all .5s ease-out}.fade{opacity:0;-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spin-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0)!important;transform:translateZ(0) rotate(360deg) scale(0)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.menu-open .avatar{opacity:1;-webkit-transform:translateZ(0) rotate(0) scale(1)!important;transform:translateZ(0) rotate(0) scale(1)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.button.button-fab.button-fab-top-left.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(-120px,60px,0);transform:translate3d(-120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-top-right.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(120px,60px,0);transform:translate3d(120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-bottom-left.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(-120px,60px,0);transform:translate3d(-120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-bottom-right.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(120px,60px,0);transform:translate3d(120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.spin{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(0) scale(0)!important;transform:translateZ(0) rotate(0) scale(0)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.spin.on{-webkit-transform:translateZ(0) rotate(-360deg) scale(1)!important;transform:translateZ(0) rotate(-360deg) scale(1)!important}.flap{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flap.on{-webkit-transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) scale(3)!important;transform:translateZ(0) scale(3)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop.on{-webkit-transform:translateZ(0) scale(1)!important;transform:translateZ(0) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateY(0) scale(0)!important;transform:translateZ(0) rotateY(0) scale(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip.on{-webkit-transform:translateZ(0) rotateY(-720deg) scale(1)!important;transform:translateZ(0) rotateY(-720deg) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.bar .button.button-floating,.button.button-floating{display:inline-block;color:#fff;position:relative;z-index:1;width:37px;height:37px;line-height:37px;padding:0;border-radius:50%;background-clip:padding-box;-webkit-transition:.3s;transition:.3s;cursor:pointer}.bar .button.button-floating i,.button.button-floating i{width:inherit;display:inline-block;text-align:center;color:#fff;font-size:1.6rem;line-height:37px}.bar .button.button-floating.button-large,.button.button-floating.button-large{width:55.5px;height:55.5px}.bar .button.button-floating.button-large i,.button.button-floating.button-large i{line-height:55.5px}.bar .button,.bar .button.button-flat,.bar .button.button-large,.button,.button.button-flat,.button.button-large{box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);display:inline-block;height:36px;padding:0 2rem;border-radius:2px;background-clip:padding-box;text-transform:uppercase;border:none;outline:0;-webkit-tap-highlight-color:transparent}.bar .button.button-floating.disabled,.bar .button.button-floating:disabled,.bar .button.button-large.disabled,.bar .button.button-large:disabled,.bar .button.button:disabled,.bar .button.disabled,.bar .button.disabled.button-large,.button.button-floating.disabled,.button.button-floating:disabled,.button.button-large.disabled,.button.button-large:disabled,.button.button:disabled,.button.disabled,.button.disabled.button-large{background-color:#dfdfdf;box-shadow:none;color:#9f9f9f}.bar .button.button-floating.disabled:hover,.bar .button.button-floating:disabled:hover,.bar .button.button-large.disabled:hover,.bar .button.button-large:disabled:hover,.bar .button.button:disabled:hover,.bar .button.disabled.button-large:hover,.bar .button.disabled:hover,.button.button-floating.disabled:hover,.button.button-floating:disabled:hover,.button.button-large.disabled:hover,.button.button-large:disabled:hover,.button.button:disabled:hover,.button.disabled.button-large:hover,.button.disabled:hover{background-color:#dfdfdf;color:#9f9f9f}.bar .button i,.bar .button.button-flat i,.bar .button.button-floating i,.bar .button.button-large i,.button i,.button.button-flat i,.button.button-floating i,.button.button-large i{font-size:1.3rem}.button-bar .button{border-radius:0}.bar .button,.bar .button-large,.button,.button-large{text-decoration:none;text-align:center;letter-spacing:.5px;-webkit-transition:.2s ease-out;transition:.2s ease-out;cursor:pointer}.button{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;outline:0;margin:0;white-space:nowrap;text-align:center;text-transform:uppercase;font-weight:500;font-style:inherit;font-variant:inherit;font-size:inherit;text-decoration:none;cursor:pointer;overflow:hidden;-webkit-transition:box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1),-webkit-transform .4s cubic-bezier(.25,.8,.25,1);transition:box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1),transform .4s cubic-bezier(.25,.8,.25,1)}.button:focus{outline:0}.button.ng-hide{-webkit-transition:none;transition:none}.button.cornered{border-radius:0}.button.raised{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.button-outline,.button-outline:active,.button-outline:hover{border-style:solid;border-width:1px}.button.button-outline,.button.button-outline.button-assertive,.button.button-outline.button-balanced,.button.button-outline.button-calm,.button.button-outline.button-dark,.button.button-outline.button-energized,.button.button-outline.button-light,.button.button-outline.button-positive,.button.button-outline.button-royal,.button.button-outline.button-stable,.button.button-outline.button-text{border-color:rgba(0,0,0,.1)}.bar .button-flat,.button-flat{box-shadow:none;background-color:transparent;color:#343434;cursor:pointer}.bar .button.button-flat.disabled,.button.button-flat.disabled{color:#b3b3b3}.bar .button.button-large i,.button.button-large i{font-size:1.6rem}.button-pin-header.button-floating{position:absolute;z-index:1000}.button-pin-header.button-pin-left{left:24px;top:-24px}.button-pin-header.button-pin-right{right:24px;top:-24px}.button:not([disabled]).floating:focus,.button:not([disabled]).floating:hover,.button:not([disabled]).raised:focus,.button:not([disabled]).raised:hover{-webkit-transform:translate3d(0,-1px,0);transform:translate3d(0,-1px,0)}.button.button-flat{box-shadow:none;color:inherit}.button.button-flat:hover{color:inherit}.button.button-flat,.button.button-flat:active,.button.button-flat:hover{color:#fff}.button.button-clear,.button.button-clear:active,.button.button-clear:hover,.button.button-text,.button.button-text:active,.button.button-text:hover{background:0 0}.button-block.ink,.button-full.ink{display:block}.card-item.item{border:none;padding-bottom:4px;padding-top:4px}.card-item.item:first-child{padding-top:16px}.card{box-shadow:0 2px 5px 0 rgba(0,0,0,.26);display:block;margin:8px;padding:0;position:relative}.card .image{display:block;margin-top:10px;margin-bottom:5px}.card img{box-shadow:0 2px 5px 0 rgba(0,0,0,.26);display:block;max-width:100%;max-height:initial;position:static}.card.card-gallery img{border:none;box-shadow:none;display:block}.card .card-footer{font-size:90%;opacity:.8;padding-top:10px}.card>.item{border:none}.card.card-gallery>.item{background:inherit}#menu .footer .card .icon+.icon-help,#menu .footer .card .icon-alert+.icon-help,#menu .footer .card .icon-help+.icon,#menu .footer .card .icon-help+.icon-alert,#menu .footer .card .icon-help+.icon-help,.card #menu .footer .icon+.icon-help,.card #menu .footer .icon-alert+.icon-help,.card #menu .footer .icon-help+.icon,.card #menu .footer .icon-help+.icon-alert,.card #menu .footer .icon-help+.icon-help,.card .icon+.icon,.card .icon+.icon-alert,.card .icon+.icon-help,.card .icon-alert+.icon,.card .icon-alert+.icon-alert,.card .icon-alert+.icon-help,.card .icon-help+.icon,.card .icon-help+.icon-alert,.card .icon-help+.icon-help{padding-left:1rem}.card.animate-fade-in{opacity:0;-webkit-transform:translate3d(-30px,1px,0);-webkit-transition:all 1s ease-in-out}.animate-fade-slide-in .card.animate-fade-in.expanded.item,.animate-fade-slide-in .expanded .card.animate-fade-in.item,.animate-fade-slide-in-right .card.animate-fade-in.expanded.item,.animate-fade-slide-in-right .expanded .card.animate-fade-in.item,.animate-ripple .card.animate-fade-in.expanded.item,.animate-ripple .expanded .card.animate-fade-in.item,.card-avatar-small .expanded .card.animate-fade-in.card-comment,.card-avatar-small .expanded .card.animate-fade-in.item,.card-avatar-small.expanded .card.animate-fade-in.card-comment,.card-avatar-small.expanded .card.animate-fade-in.item,.card.animate-fade-in.done{opacity:1;-webkit-transform:translate3d(0,0,0)}.card .item.item-avatar{min-height:88px;padding-left:88px}.hero{background-size:cover;box-shadow:0 2px 5px 0 rgba(0,0,0,.26);color:#fff;height:200px;position:relative;text-align:center;-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);width:100%}.hero>*{-webkit-transition:opacity 2.5s cubic-bezier(.55,0,.1,1);transition:opacity 2.5s cubic-bezier(.55,0,.1,1);opacity:1}.hero+.mid-bar{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);height:initial;opacity:1}.hero .hero-icon{box-shadow:0 0 2px 0 rgba(0,0,0,.26);border-radius:50%;display:inline-block;font-size:65px;height:150px;padding:10px 30px;line-height:136px;width:150px}.hero.no-header{height:244px}.hero>.content{bottom:0;position:absolute;text-align:center;width:100%;z-index:1}.hero>.content>.avatar{background-position:center;background-size:cover;border:solid 1px rgba(255,255,255,.8);border-radius:50%;display:inline-block;height:88px;left:auto;margin-bottom:10px;position:relative;width:88px}.hero h1 .hero h2,.hero h3,.hero h4,.hero h5,.hero h6{color:#fff;margin:0}.hero h4{color:rgba(255,255,255,.7);margin:3px 0 16px}.hero h1>a,.hero h2>a,.hero h3>a,.hero h4>a,.hero h5>a,.hero h6>a{text-decoration:none}.hero+.button-bar{border-radius:0;margin-top:0}.hero+.button-bar>.button:first-child,.hero+.button-bar>.button:last-child{border-radius:0}.hero .hero-icon{color:#fff;font-size:96px}.hero .hero-icon+h1{color:#fff;letter-spacing:.15rem}.hero .button,.hero .button.button-flat,.hero .button.button-large{margin:0}.hero h1.title{color:#fff;font-size:23px;margin:0;text-align:left;padding-left:80px;line-height:59px}.hero+.mid-bar{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);height:initial;opacity:1}.hero>*{-webkit-transition:opacity 2.5s cubic-bezier(.55,0,.1,1);transition:opacity 2.5s cubic-bezier(.55,0,.1,1);opacity:1}.item{font-size:14px;width:100%}#menu .footer .item-icon-left .icon-help,.item-icon-left #menu .footer .icon-help,.item-icon-left .icon,.item-icon-left .icon-alert,.item-icon-left .icon-help{left:16px}#menu .footer .item-icon-right .icon-help,.item-icon-right #menu .footer .icon-help,.item-icon-right .icon,.item-icon-right .icon-alert,.item-icon-right .icon-help{right:16px}.item-thumbnail-left .item-content .item-image,.item-thumbnail-left .item-content>img:first-child,.item-thumbnail-left .item-image,.item-thumbnail-left>img:first-child{border-radius:50%}.tab-item.activated{height:calc(100% + 3px)}.content+.list{padding-top:0}.list .item{border:none;min-height:48px;text-align:left}.list .item.tabs{padding:initial}.list .item.item-bg-image{max-height:150px;min-height:150px}.list .item.item-bg-image>img{height:100%;left:0;max-width:initial;opacity:.65;position:absolute;top:0;width:100%;z-index:0}.list a.item{opacity:1}.list .item.item-bg-image h1,.list .item.item-bg-image h2,.list .item.item-bg-image h3,.list .item.item-bg-image h4,.list .item.item-bg-image h5,.list .item.item-bg-image h6{color:#fff;font-weight:700;position:relative;text-shadow:0 0 3px rgba(0,0,0,.95);z-index:1}.list .item.item-bg-image h2{font-size:24px}.list .item.item-bg-image h2{font-size:24px}.list .item.item-bg-image p{color:#fff;font-size:17px;position:relative;text-shadow:0 0 4px rgba(0,0,0,.95);z-index:1}.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{min-height:80px}.card>.item.item-thumbnail-left,.item-thumbnail-left,.item-thumbnail-left .item-content{padding-left:106px}.card>.item.item-thumbnail-right,.item-thumbnail-right,.item-thumbnail-right .item-content{padding-right:106px}.item-avatar .item-content .item-image,.item-avatar .item-content>img:first-child,.item-avatar .item-image,.item-avatar-left .item-content .item-image,.item-avatar-left .item-content>img:first-child,.item-avatar-left .item-image,.item-avatar-left>img:first-child,.item-avatar>img:first-child{border-radius:50%;left:16px;max-height:40px;max-width:40px}.avatar,.item-avatar .avatar{background-position:center;background-size:cover;border-radius:50%;display:inline-block;height:56px;left:16px;position:absolute;width:56px}.list.half{display:inline-block;float:left;margin:0;padding:0;width:50%}.list.half:first-child{padding:16px 8px 16px 16px}.list.half:last-child{padding:16px 16px 16px 8px}.list.half:first-child .card.card-gallery{margin-left:0;margin-right:0}.list.half:last-child .card.card-gallery{margin-left:0;margin-right:0}.list.condensed-space>.card,.list.condensed-space>.item{margin:0 0 2px}.list .card.card-gallery{display:block;float:left;margin:0 0 0 13px;padding:0;width:auto}.list.half .item{width:100%}.list.half .item.card{margin-bottom:16px}.list .card.card-gallery.item h2{padding:12px}.list .item.item-gallery img{width:100%}.item.item-divider{border-top:solid 1px rgba(0,0,0,.12);font-size:14px;font-weight:700;height:48px;line-height:48px;color:rgba(0,0,0,.54)}.item.item-divider:first-child{border:none}.card>.item-avatar,.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{padding-left:72px}.item .item-content.activated,.item .item-content.active,.item-complex.activated .item-content,.item-complex.active .item-content,.item.activated,.item.active{background-color:transparent}.list-inset{margin:20px 30px;border-left:solid 1px #ccc;border-radius:0;background-color:#fff}.item-floating-label,.list .item.item-floating-label{border-bottom:solid 1px #ccc}.loader{position:relative;margin:0 auto;width:100px;height:100px;zoom:1.7}.circular{-webkit-animation:rotate 2s linear infinite;animation:rotate 2s linear infinite;height:100px;position:relative;width:100px}.path{stroke-dasharray:1,200;stroke-dashoffset:0;-webkit-animation:dash 1.5s ease-in-out infinite,color 6s ease-in-out infinite;animation:dash 1.5s ease-in-out infinite,color 6s ease-in-out infinite;stroke-linecap:round}@-webkit-keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35}100%{stroke-dasharray:89,200;stroke-dashoffset:-124}}@keyframes dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35}100%{stroke-dasharray:89,200;stroke-dashoffset:-124}}@-webkit-keyframes color{0%,100%{stroke:#d62d20}40%{stroke:#0057e7}66%{stroke:#008744}80%,90%{stroke:#ffa700}}@keyframes color{0%,100%{stroke:#d62d20}40%{stroke:#0057e7}66%{stroke:#008744}80%,90%{stroke:#ffa700}}.login{background-position:25% 25%;background-size:180% 180%;height:100%;-webkit-transition:all 1.5s ease-in-out;transition:all 1.5s ease-in-out}.login .item{margin:0 12px;padding-left:0;padding-right:0;width:initial}.login .button-bar{bottom:0;margin:28px 12px 0;width:initial}.login .light-bg{background-color:#fff}#menu .footer .hero-icon.icon-help:before,.hero-icon.icon-alert:before,.hero-icon.icon-help:before,.icon.hero-icon:before{line-height:130px}.card.has-mask:after,.hero.has-mask:after,.item.has-mask:after{content:'';background:-webkit-linear-gradient(top,rgba(0,0,0,0) 0,rgba(0,0,0,.6) 100%);height:100%;left:0;position:absolute;top:0;z-index:0;width:100%}.card.has-mask-reverse:after,.hero.has-mask-reverse:after,.item.has-mask-reverse:after{content:'';background:-webkit-linear-gradient(top,rgba(0,0,0,.6) 0,rgba(0,0,0,0) 100%);height:100%;left:0;position:absolute;top:0;z-index:0;width:100%}.menu-bottom{bottom:16px;left:16px;right:16px;position:absolute}.menu-top{top:16px;left:16px;right:16px;position:absolute}.menu .avatar{top:16px;left:16px;height:65px;width:65px}.menu .bar.bar-header.expanded{box-shadow:none;min-height:150px;color:#fff}.menu-open .bar.bar-header.expanded{background-position:0;background-size:100%}.has-expanded-header{top:150px!important}.motion{-webkit-transition:all .5s ease-out;transition:all .5s ease-out}.fade{opacity:0;-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spin-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0)!important;transform:translateZ(0) rotate(360deg) scale(0)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.menu-open .avatar{opacity:1;-webkit-transform:translateZ(0) rotate(0) scale(1)!important;transform:translateZ(0) rotate(0) scale(1)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.spin{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(0) scale(0)!important;transform:translateZ(0) rotate(0) scale(0)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.spin.on{-webkit-transform:translateZ(0) rotate(-360deg) scale(1)!important;transform:translateZ(0) rotate(-360deg) scale(1)!important}.flap{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flap.on{-webkit-transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) scale(3)!important;transform:translateZ(0) scale(3)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop.on{-webkit-transform:translateZ(0) scale(1)!important;transform:translateZ(0) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateY(0) scale(0)!important;transform:translateZ(0) rotateY(0) scale(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip.on{-webkit-transform:translateZ(0) rotateY(-720deg) scale(1)!important;transform:translateZ(0) rotateY(-720deg) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.bold{font-weight:700}.static{position:static}#menu .footer .popover-helptip .icon-bottom-left.icon-help,#menu .footer .popover-helptip .icon-left.icon-help,.popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-helptip #menu .footer .icon-left.icon-help,.popover-helptip .icon-bottom-left.icon-alert,.popover-helptip .icon-bottom-left.icon-help,.popover-helptip .icon-left.icon-alert,.popover-helptip .icon-left.icon-help,.popover-helptip .icon.icon-bottom-left,.popover-helptip .icon.icon-left,.pull-left{float:left}#menu .footer .popover-helptip .icon-bottom-center.icon-help,#menu .footer .popover-helptip .icon-bottom-right.icon-help,#menu .footer .popover-helptip .icon-center.icon-help,#menu .footer .popover-helptip .icon-right.icon-help,.popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-helptip #menu .footer .icon-center.icon-help,.popover-helptip #menu .footer .icon-right.icon-help,.popover-helptip .icon-bottom-center.icon-alert,.popover-helptip .icon-bottom-center.icon-help,.popover-helptip .icon-bottom-right.icon-alert,.popover-helptip .icon-bottom-right.icon-help,.popover-helptip .icon-center.icon-alert,.popover-helptip .icon-center.icon-help,.popover-helptip .icon-right.icon-alert,.popover-helptip .icon-right.icon-help,.popover-helptip .icon.icon-bottom-center,.popover-helptip .icon.icon-bottom-right,.popover-helptip .icon.icon-center,.popover-helptip .icon.icon-right,.pull-right{float:right}.double-padding,.ionic-content.double-padding{padding:16px}.double-padding-x{padding-left:16px;padding-right:16px}.double-padding-y{padding-top:16px;padding-bottom:16px}.outline{border-style:solid;border-width:1px}.border-top{border-top:solid 1px #ccc;padding-top:30px}.no-border{border:none}.circle{border-radius:50%}.bar.no-padding,.button-bar.no-padding,.button.no-padding,.card.no-padding,.item.no-padding,.list.no-padding,.no-padding{padding:0}#menu .footer .flat.button.icon-help,.flat,.flat.button,.flat.button.icon,.flat.button.icon-alert,.flat.button.icon-help,.flat.hero,.flat.tabs{box-shadow:none;-webkit-box-shadow:none}.im-wrapper,.item.large-button-bar,.padding{padding:16px!important}.padding-bottom,.popover-share .bar-footer .button-close{padding-bottom:16px!important}.padding-top{padding-top:16px!important}.padding-left{padding-left:16px!important}.padding-right,.popover-share .bar-footer .button-close{padding-right:16px!important}.no-padding-bottom{padding-bottom:0!important}.no-padding-top{padding-top:0!important}.no-padding-left{padding-left:0!important}.no-padding-right{padding-right:0!important}.z1{box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar.bar-positive.darker{background-color:#164fab}.bar.bar-positive.dark-positive-bg{background-color:#2c5cad}.muted{color:#c3c3c3}.clear-bg{background:0 0}.animate-blinds .item{visibility:hidden}.animate-blinds .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-blinds .item-bg-image>img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-blinds .animate-fade-slide-in .expanded .item,.animate-blinds .animate-fade-slide-in .expanded.item,.animate-blinds .animate-fade-slide-in-right .expanded .item,.animate-blinds .animate-fade-slide-in-right .expanded.item,.animate-blinds .animate-ripple .expanded .item,.animate-blinds .animate-ripple .expanded.item,.animate-blinds .card-avatar-small .expanded .card.card-comment,.animate-blinds .card-avatar-small .expanded .item,.animate-blinds .card-avatar-small.expanded .card.card-comment,.animate-blinds .card-avatar-small.expanded .item,.animate-blinds .in,.animate-blinds.done>*,.animate-fade-slide-in .animate-blinds .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item>*,.animate-fade-slide-in .expanded .animate-blinds .item,.animate-fade-slide-in .expanded .animate-blinds.item>*,.animate-fade-slide-in-right .animate-blinds .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item>*,.animate-fade-slide-in-right .expanded .animate-blinds .item,.animate-fade-slide-in-right .expanded .animate-blinds.item>*,.animate-ripple .animate-blinds .expanded.item,.animate-ripple .animate-blinds.expanded.item>*,.animate-ripple .expanded .animate-blinds .item,.animate-ripple .expanded .animate-blinds.item>*,.card-avatar-small .expanded .animate-blinds .card.card-comment,.card-avatar-small .expanded .animate-blinds .item,.card-avatar-small .expanded .animate-blinds.card.card-comment>*,.card-avatar-small .expanded .animate-blinds.item>*,.card-avatar-small.expanded .animate-blinds .card.card-comment,.card-avatar-small.expanded .animate-blinds .item,.card-avatar-small.expanded .animate-blinds.card.card-comment>*,.card-avatar-small.expanded .animate-blinds.item>*{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.animate-blinds .animate-fade-slide-in .expanded .item,.animate-blinds .animate-fade-slide-in .expanded.item,.animate-blinds .animate-fade-slide-in-right .expanded .item,.animate-blinds .animate-fade-slide-in-right .expanded.item,.animate-blinds .animate-ripple .expanded .item,.animate-blinds .animate-ripple .expanded.item,.animate-blinds .card-avatar-small .expanded .card.card-comment,.animate-blinds .card-avatar-small .expanded .item,.animate-blinds .card-avatar-small.expanded .card.card-comment,.animate-blinds .card-avatar-small.expanded .item,.animate-blinds .in,.animate-blinds.done .item,.animate-fade-slide-in .animate-blinds .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item .item,.animate-fade-slide-in .expanded .animate-blinds .item,.animate-fade-slide-in .expanded .animate-blinds.item .item,.animate-fade-slide-in-right .animate-blinds .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item .item,.animate-fade-slide-in-right .expanded .animate-blinds .item,.animate-fade-slide-in-right .expanded .animate-blinds.item .item,.animate-ripple .animate-blinds .expanded.item,.animate-ripple .animate-blinds.expanded.item .item,.animate-ripple .expanded .animate-blinds .item,.animate-ripple .expanded .animate-blinds.item .item,.card-avatar-small .expanded .animate-blinds .card.card-comment,.card-avatar-small .expanded .animate-blinds .item,.card-avatar-small .expanded .animate-blinds.card.card-comment .item,.card-avatar-small .expanded .animate-blinds.item .item,.card-avatar-small.expanded .animate-blinds .card.card-comment,.card-avatar-small.expanded .animate-blinds .item,.card-avatar-small.expanded .animate-blinds.card.card-comment .item,.card-avatar-small.expanded .animate-blinds.item .item{visibility:visible}.animate-blinds .item{visibility:hidden}.animate-blinds .item{opacity:0}.animate-blinds .animate-fade-slide-in .expanded .item,.animate-blinds .animate-fade-slide-in .expanded.item,.animate-blinds .animate-fade-slide-in-right .expanded .item,.animate-blinds .animate-fade-slide-in-right .expanded.item,.animate-blinds .animate-ripple .expanded .item,.animate-blinds .animate-ripple .expanded.item,.animate-blinds .card-avatar-small .expanded .card.card-comment,.animate-blinds .card-avatar-small .expanded .item,.animate-blinds .card-avatar-small.expanded .card.card-comment,.animate-blinds .card-avatar-small.expanded .item,.animate-blinds .in,.animate-blinds.done,.animate-fade-slide-in .animate-blinds .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item,.animate-fade-slide-in .expanded .animate-blinds .item,.animate-fade-slide-in .expanded .animate-blinds.item,.animate-fade-slide-in-right .animate-blinds .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item,.animate-fade-slide-in-right .expanded .animate-blinds .item,.animate-fade-slide-in-right .expanded .animate-blinds.item,.animate-ripple .animate-blinds .expanded.item,.animate-ripple .animate-blinds.expanded.item,.animate-ripple .expanded .animate-blinds .item,.animate-ripple .expanded .animate-blinds.item,.card-avatar-small .expanded .animate-blinds .card.card-comment,.card-avatar-small .expanded .animate-blinds .item,.card-avatar-small .expanded .animate-blinds.card.card-comment,.card-avatar-small .expanded .animate-blinds.item,.card-avatar-small.expanded .animate-blinds .card.card-comment,.card-avatar-small.expanded .animate-blinds .item,.card-avatar-small.expanded .animate-blinds.card.card-comment,.card-avatar-small.expanded .animate-blinds.item{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;opacity:1}.animate-blinds .animate-fade-slide-in .expanded .item,.animate-blinds .animate-fade-slide-in .expanded.item,.animate-blinds .animate-fade-slide-in-right .expanded .item,.animate-blinds .animate-fade-slide-in-right .expanded.item,.animate-blinds .animate-ripple .expanded .item,.animate-blinds .animate-ripple .expanded.item,.animate-blinds .card-avatar-small .expanded .card.card-comment,.animate-blinds .card-avatar-small .expanded .item,.animate-blinds .card-avatar-small.expanded .card.card-comment,.animate-blinds .card-avatar-small.expanded .item,.animate-blinds .in,.animate-blinds.done,.animate-fade-slide-in .animate-blinds .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item,.animate-fade-slide-in .expanded .animate-blinds .item,.animate-fade-slide-in .expanded .animate-blinds.item,.animate-fade-slide-in-right .animate-blinds .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item,.animate-fade-slide-in-right .expanded .animate-blinds .item,.animate-fade-slide-in-right .expanded .animate-blinds.item,.animate-ripple .animate-blinds .expanded.item,.animate-ripple .animate-blinds.expanded.item,.animate-ripple .expanded .animate-blinds .item,.animate-ripple .expanded .animate-blinds.item,.card-avatar-small .expanded .animate-blinds .card.card-comment,.card-avatar-small .expanded .animate-blinds .item,.card-avatar-small .expanded .animate-blinds.card.card-comment,.card-avatar-small .expanded .animate-blinds.item,.card-avatar-small.expanded .animate-blinds .card.card-comment,.card-avatar-small.expanded .animate-blinds .item,.card-avatar-small.expanded .animate-blinds.card.card-comment,.card-avatar-small.expanded .animate-blinds.item{visibility:visible}.animate-blinds.done .animate-fade-slide-in .expanded .item,.animate-blinds.done .animate-fade-slide-in .expanded.item,.animate-blinds.done .animate-fade-slide-in-right .expanded .item,.animate-blinds.done .animate-fade-slide-in-right .expanded.item,.animate-blinds.done .animate-ripple .expanded .item,.animate-blinds.done .animate-ripple .expanded.item,.animate-blinds.done .card-avatar-small .expanded .card.card-comment,.animate-blinds.done .card-avatar-small .expanded .item,.animate-blinds.done .card-avatar-small.expanded .card.card-comment,.animate-blinds.done .card-avatar-small.expanded .item,.animate-blinds.done .in,.animate-fade-slide-in .animate-blinds.done .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item .animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item .animate-ripple .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in .animate-blinds.expanded.item .card-avatar-small.expanded .item,.animate-fade-slide-in .animate-blinds.expanded.item .expanded.item,.animate-fade-slide-in .animate-blinds.expanded.item .in,.animate-fade-slide-in .animate-blinds.expanded.item .item,.animate-fade-slide-in .animate-fade-slide-in-right .animate-blinds.expanded.item .expanded.item,.animate-fade-slide-in .animate-fade-slide-in-right .animate-blinds.expanded.item .item,.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-blinds.item .expanded.item,.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-blinds.item .item,.animate-fade-slide-in .animate-ripple .animate-blinds.expanded.item .expanded.item,.animate-fade-slide-in .animate-ripple .animate-blinds.expanded.item .item,.animate-fade-slide-in .animate-ripple .expanded .animate-blinds.item .expanded.item,.animate-fade-slide-in .animate-ripple .expanded .animate-blinds.item .item,.animate-fade-slide-in .card-avatar-small .animate-blinds.expanded.item .card.card-comment,.animate-fade-slide-in .card-avatar-small .animate-blinds.expanded.item .item,.animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.card.card-comment .expanded.item,.animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.card.card-comment .item,.animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.item .card.card-comment,.animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.item .expanded.item,.animate-fade-slide-in .card-avatar-small .expanded .animate-blinds.item .item,.animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.card.card-comment .expanded.item,.animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.card.card-comment .item,.animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.item .card.card-comment,.animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.item .expanded.item,.animate-fade-slide-in .card-avatar-small.expanded .animate-blinds.item .item,.animate-fade-slide-in .expanded .animate-blinds.done .item,.animate-fade-slide-in .expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in .expanded .animate-blinds.item .animate-ripple .expanded.item,.animate-fade-slide-in .expanded .animate-blinds.item .expanded.item,.animate-fade-slide-in .expanded .animate-blinds.item .in,.animate-fade-slide-in .expanded .animate-blinds.item .item,.animate-fade-slide-in-right .animate-blinds.done .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item .animate-fade-slide-in .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item .animate-ripple .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in-right .animate-blinds.expanded.item .card-avatar-small.expanded .item,.animate-fade-slide-in-right .animate-blinds.expanded.item .expanded.item,.animate-fade-slide-in-right .animate-blinds.expanded.item .in,.animate-fade-slide-in-right .animate-blinds.expanded.item .item,.animate-fade-slide-in-right .animate-fade-slide-in .animate-blinds.expanded.item .expanded.item,.animate-fade-slide-in-right .animate-fade-slide-in .animate-blinds.expanded.item .item,.animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-blinds.item .expanded.item,.animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-blinds.item .item,.animate-fade-slide-in-right .animate-ripple .animate-blinds.expanded.item .expanded.item,.animate-fade-slide-in-right .animate-ripple .animate-blinds.expanded.item .item,.animate-fade-slide-in-right .animate-ripple .expanded .animate-blinds.item .expanded.item,.animate-fade-slide-in-right .animate-ripple .expanded .animate-blinds.item .item,.animate-fade-slide-in-right .card-avatar-small .animate-blinds.expanded.item .card.card-comment,.animate-fade-slide-in-right .card-avatar-small .animate-blinds.expanded.item .item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.card.card-comment .expanded.item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.card.card-comment .item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.item .card.card-comment,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.item .expanded.item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-blinds.item .item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.card.card-comment .expanded.item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.card.card-comment .item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.item .card.card-comment,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.item .expanded.item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-blinds.item .item,.animate-fade-slide-in-right .expanded .animate-blinds.done .item,.animate-fade-slide-in-right .expanded .animate-blinds.item .animate-fade-slide-in .expanded.item,.animate-fade-slide-in-right .expanded .animate-blinds.item .animate-ripple .expanded.item,.animate-fade-slide-in-right .expanded .animate-blinds.item .expanded.item,.animate-fade-slide-in-right .expanded .animate-blinds.item .in,.animate-fade-slide-in-right .expanded .animate-blinds.item .item,.animate-ripple .animate-blinds.done .expanded.item,.animate-ripple .animate-blinds.expanded.item .animate-fade-slide-in .expanded.item,.animate-ripple .animate-blinds.expanded.item .animate-fade-slide-in-right .expanded.item,.animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-ripple .animate-blinds.expanded.item .card-avatar-small.expanded .item,.animate-ripple .animate-blinds.expanded.item .expanded.item,.animate-ripple .animate-blinds.expanded.item .in,.animate-ripple .animate-blinds.expanded.item .item,.animate-ripple .animate-fade-slide-in .animate-blinds.expanded.item .expanded.item,.animate-ripple .animate-fade-slide-in .animate-blinds.expanded.item .item,.animate-ripple .animate-fade-slide-in .expanded .animate-blinds.item .expanded.item,.animate-ripple .animate-fade-slide-in .expanded .animate-blinds.item .item,.animate-ripple .animate-fade-slide-in-right .animate-blinds.expanded.item .expanded.item,.animate-ripple .animate-fade-slide-in-right .animate-blinds.expanded.item .item,.animate-ripple .animate-fade-slide-in-right .expanded .animate-blinds.item .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded .animate-blinds.item .item,.animate-ripple .card-avatar-small .animate-blinds.expanded.item .card.card-comment,.animate-ripple .card-avatar-small .animate-blinds.expanded.item .item,.animate-ripple .card-avatar-small .expanded .animate-blinds.card.card-comment .expanded.item,.animate-ripple .card-avatar-small .expanded .animate-blinds.card.card-comment .item,.animate-ripple .card-avatar-small .expanded .animate-blinds.item .card.card-comment,.animate-ripple .card-avatar-small .expanded .animate-blinds.item .expanded.item,.animate-ripple .card-avatar-small .expanded .animate-blinds.item .item,.animate-ripple .card-avatar-small.expanded .animate-blinds.card.card-comment .expanded.item,.animate-ripple .card-avatar-small.expanded .animate-blinds.card.card-comment .item,.animate-ripple .card-avatar-small.expanded .animate-blinds.item .card.card-comment,.animate-ripple .card-avatar-small.expanded .animate-blinds.item .expanded.item,.animate-ripple .card-avatar-small.expanded .animate-blinds.item .item,.animate-ripple .expanded .animate-blinds.done .item,.animate-ripple .expanded .animate-blinds.item .animate-fade-slide-in .expanded.item,.animate-ripple .expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item,.animate-ripple .expanded .animate-blinds.item .expanded.item,.animate-ripple .expanded .animate-blinds.item .in,.animate-ripple .expanded .animate-blinds.item .item,.card-avatar-small .animate-fade-slide-in .animate-blinds.expanded.item .card.card-comment,.card-avatar-small .animate-fade-slide-in .animate-blinds.expanded.item .item,.card-avatar-small .animate-fade-slide-in .expanded .animate-blinds.card.card-comment .item,.card-avatar-small .animate-fade-slide-in .expanded .animate-blinds.item .card.card-comment,.card-avatar-small .animate-fade-slide-in .expanded .animate-blinds.item .item,.card-avatar-small .animate-fade-slide-in-right .animate-blinds.expanded.item .card.card-comment,.card-avatar-small .animate-fade-slide-in-right .animate-blinds.expanded.item .item,.card-avatar-small .animate-fade-slide-in-right .expanded .animate-blinds.card.card-comment .item,.card-avatar-small .animate-fade-slide-in-right .expanded .animate-blinds.item .card.card-comment,.card-avatar-small .animate-fade-slide-in-right .expanded .animate-blinds.item .item,.card-avatar-small .animate-ripple .animate-blinds.expanded.item .card.card-comment,.card-avatar-small .animate-ripple .animate-blinds.expanded.item .item,.card-avatar-small .animate-ripple .expanded .animate-blinds.card.card-comment .item,.card-avatar-small .animate-ripple .expanded .animate-blinds.item .card.card-comment,.card-avatar-small .animate-ripple .expanded .animate-blinds.item .item,.card-avatar-small .expanded .animate-blinds.card.card-comment .animate-fade-slide-in .expanded.item,.card-avatar-small .expanded .animate-blinds.card.card-comment .animate-fade-slide-in-right .expanded.item,.card-avatar-small .expanded .animate-blinds.card.card-comment .animate-ripple .expanded.item,.card-avatar-small .expanded .animate-blinds.card.card-comment .card.card-comment,.card-avatar-small .expanded .animate-blinds.card.card-comment .in,.card-avatar-small .expanded .animate-blinds.card.card-comment .item,.card-avatar-small .expanded .animate-blinds.done .card.card-comment,.card-avatar-small .expanded .animate-blinds.done .item,.card-avatar-small .expanded .animate-blinds.item .animate-fade-slide-in .expanded.item,.card-avatar-small .expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item,.card-avatar-small .expanded .animate-blinds.item .animate-ripple .expanded.item,.card-avatar-small .expanded .animate-blinds.item .card.card-comment,.card-avatar-small .expanded .animate-blinds.item .in,.card-avatar-small .expanded .animate-blinds.item .item,.card-avatar-small.expanded .animate-blinds.card.card-comment .animate-fade-slide-in .expanded.item,.card-avatar-small.expanded .animate-blinds.card.card-comment .animate-fade-slide-in-right .expanded.item,.card-avatar-small.expanded .animate-blinds.card.card-comment .animate-ripple .expanded.item,.card-avatar-small.expanded .animate-blinds.card.card-comment .card.card-comment,.card-avatar-small.expanded .animate-blinds.card.card-comment .expanded .card.card-comment,.card-avatar-small.expanded .animate-blinds.card.card-comment .expanded .item,.card-avatar-small.expanded .animate-blinds.card.card-comment .in,.card-avatar-small.expanded .animate-blinds.card.card-comment .item,.card-avatar-small.expanded .animate-blinds.done .card.card-comment,.card-avatar-small.expanded .animate-blinds.done .item,.card-avatar-small.expanded .animate-blinds.item .animate-fade-slide-in .expanded.item,.card-avatar-small.expanded .animate-blinds.item .animate-fade-slide-in-right .expanded.item,.card-avatar-small.expanded .animate-blinds.item .animate-ripple .expanded.item,.card-avatar-small.expanded .animate-blinds.item .card.card-comment,.card-avatar-small.expanded .animate-blinds.item .expanded .card.card-comment,.card-avatar-small.expanded .animate-blinds.item .expanded .item,.card-avatar-small.expanded .animate-blinds.item .in,.card-avatar-small.expanded .animate-blinds.item .item,.card-avatar-small.expanded .animate-fade-slide-in .animate-blinds.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in .animate-blinds.expanded.item .item,.card-avatar-small.expanded .animate-fade-slide-in-right .animate-blinds.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right .animate-blinds.expanded.item .item,.card-avatar-small.expanded .animate-ripple .animate-blinds.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-ripple .animate-blinds.expanded.item .item,.card-avatar-small.expanded .expanded .animate-blinds.card.card-comment .card.card-comment,.card-avatar-small.expanded .expanded .animate-blinds.card.card-comment .item,.card-avatar-small.expanded .expanded .animate-blinds.item .card.card-comment,.card-avatar-small.expanded .expanded .animate-blinds.item .item{opacity:1}.animate-blinds .has-mask-reverse:after{opacity:0;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-blinds.done .has-mask-reverse:after,.animate-fade-slide-in .animate-blinds.expanded.item .has-mask-reverse:after,.animate-fade-slide-in .expanded .animate-blinds.item .has-mask-reverse:after,.animate-fade-slide-in-right .animate-blinds.expanded.item .has-mask-reverse:after,.animate-fade-slide-in-right .expanded .animate-blinds.item .has-mask-reverse:after,.animate-ripple .animate-blinds.expanded.item .has-mask-reverse:after,.animate-ripple .expanded .animate-blinds.item .has-mask-reverse:after,.card-avatar-small .expanded .animate-blinds.card.card-comment .has-mask-reverse:after,.card-avatar-small .expanded .animate-blinds.item .has-mask-reverse:after,.card-avatar-small.expanded .animate-blinds.card.card-comment .has-mask-reverse:after,.card-avatar-small.expanded .animate-blinds.item .has-mask-reverse:after{opacity:1}.animate-blinds .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-pan-in-left{background-position:0 0}.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-ripple .card-avatar-small .expanded .card.card-comment,.animate-ripple .card-avatar-small.expanded .card.card-comment,.animate-ripple .done,.animate-ripple .expanded .item,.animate-ripple .expanded.item,.card-avatar-small .expanded .animate-ripple .card.card-comment,.card-avatar-small .expanded .animate-ripple .item,.card-avatar-small.expanded .animate-ripple .card.card-comment,.card-avatar-small.expanded .animate-ripple .item{visibility:hidden}.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-ripple .card-avatar-small .expanded .card.card-comment,.animate-ripple .card-avatar-small.expanded .card.card-comment,.animate-ripple .done,.animate-ripple .expanded .item,.animate-ripple .expanded.item,.card-avatar-small .expanded .animate-ripple .card.card-comment,.card-avatar-small .expanded .animate-ripple .item,.card-avatar-small.expanded .animate-ripple .card.card-comment,.card-avatar-small.expanded .animate-ripple .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-ripple .item-bg-image img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in .animate-ripple.expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in .expanded .animate-ripple.item,.animate-fade-slide-in-right .animate-ripple.expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple.item,.animate-ripple .animate-ripple.expanded.item,.animate-ripple .card-avatar-small .expanded .card.card-comment,.animate-ripple .card-avatar-small.expanded .card.card-comment,.animate-ripple .expanded .animate-ripple.item,.animate-ripple .expanded .item,.animate-ripple .expanded.item,.animate-ripple .in,.animate-ripple.done,.card-avatar-small .expanded .animate-ripple .card.card-comment,.card-avatar-small .expanded .animate-ripple .item,.card-avatar-small .expanded .animate-ripple.card.card-comment,.card-avatar-small .expanded .animate-ripple.item,.card-avatar-small.expanded .animate-ripple .card.card-comment,.card-avatar-small.expanded .animate-ripple .item,.card-avatar-small.expanded .animate-ripple.card.card-comment,.card-avatar-small.expanded .animate-ripple.item{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in .animate-ripple.expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in .expanded .animate-ripple.item,.animate-fade-slide-in-right .animate-ripple.expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple.item,.animate-ripple .animate-ripple.expanded.item,.animate-ripple .card-avatar-small .expanded .card.card-comment,.animate-ripple .card-avatar-small.expanded .card.card-comment,.animate-ripple .expanded .animate-ripple.item,.animate-ripple .expanded .item,.animate-ripple .expanded.item,.animate-ripple .in,.animate-ripple.done,.card-avatar-small .expanded .animate-ripple .card.card-comment,.card-avatar-small .expanded .animate-ripple .item,.card-avatar-small .expanded .animate-ripple.card.card-comment,.card-avatar-small .expanded .animate-ripple.item,.card-avatar-small.expanded .animate-ripple .card.card-comment,.card-avatar-small.expanded .animate-ripple .item,.card-avatar-small.expanded .animate-ripple.card.card-comment,.card-avatar-small.expanded .animate-ripple.item{visibility:visible}.animate-ripple .item{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1);opacity:0}.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-ripple .card-avatar-small .expanded .item.card.card-comment,.animate-ripple .card-avatar-small.expanded .item.card.card-comment,.animate-ripple .expanded .item,.animate-ripple .item.expanded,.animate-ripple .item.in,.card-avatar-small .expanded .animate-ripple .item,.card-avatar-small.expanded .animate-ripple .item{opacity:1}.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-ripple .card-avatar-small .expanded .card.card-comment,.animate-ripple .card-avatar-small.expanded .card.card-comment,.animate-ripple .done,.animate-ripple .expanded .item,.animate-ripple .expanded.item,.card-avatar-small .expanded .animate-ripple .card.card-comment,.card-avatar-small .expanded .animate-ripple .item,.card-avatar-small.expanded .animate-ripple .card.card-comment,.card-avatar-small.expanded .animate-ripple .item{visibility:hidden}.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-ripple .card-avatar-small .expanded .card.card-comment,.animate-ripple .card-avatar-small.expanded .card.card-comment,.animate-ripple .done,.animate-ripple .expanded .item,.animate-ripple .expanded.item,.card-avatar-small .expanded .animate-ripple .card.card-comment,.card-avatar-small .expanded .animate-ripple .item,.card-avatar-small.expanded .animate-ripple .card.card-comment,.card-avatar-small.expanded .animate-ripple .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-fade-slide-in .animate-ripple.expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in .expanded .animate-ripple.item,.animate-fade-slide-in-right .animate-ripple.expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple.item,.animate-ripple .animate-ripple.expanded.item,.animate-ripple .card-avatar-small .expanded .card.card-comment,.animate-ripple .card-avatar-small.expanded .card.card-comment,.animate-ripple .expanded .animate-ripple.item,.animate-ripple .expanded .item,.animate-ripple .expanded.item,.animate-ripple .in,.animate-ripple.done,.card-avatar-small .expanded .animate-ripple .card.card-comment,.card-avatar-small .expanded .animate-ripple .item,.card-avatar-small .expanded .animate-ripple.card.card-comment,.card-avatar-small .expanded .animate-ripple.item,.card-avatar-small.expanded .animate-ripple .card.card-comment,.card-avatar-small.expanded .animate-ripple .item,.card-avatar-small.expanded .animate-ripple.card.card-comment,.card-avatar-small.expanded .animate-ripple.item{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in .animate-ripple.expanded.item,.animate-fade-slide-in .expanded .animate-ripple .item,.animate-fade-slide-in .expanded .animate-ripple.item,.animate-fade-slide-in-right .animate-ripple.expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple .item,.animate-fade-slide-in-right .expanded .animate-ripple.item,.animate-ripple .animate-ripple.expanded.item,.animate-ripple .card-avatar-small .expanded .card.card-comment,.animate-ripple .card-avatar-small.expanded .card.card-comment,.animate-ripple .expanded .animate-ripple.item,.animate-ripple .expanded .item,.animate-ripple .expanded.item,.animate-ripple .in,.animate-ripple.done,.card-avatar-small .expanded .animate-ripple .card.card-comment,.card-avatar-small .expanded .animate-ripple .item,.card-avatar-small .expanded .animate-ripple.card.card-comment,.card-avatar-small .expanded .animate-ripple.item,.card-avatar-small.expanded .animate-ripple .card.card-comment,.card-avatar-small.expanded .animate-ripple .item,.card-avatar-small.expanded .animate-ripple.card.card-comment,.card-avatar-small.expanded .animate-ripple.item{visibility:visible}.animate-fade-slide-in .animate-fade-slide-in-right .animate-ripple.expanded.item .expanded.item,.animate-fade-slide-in .animate-fade-slide-in-right .animate-ripple.expanded.item .item,.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-ripple.item .expanded.item,.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-ripple.item .item,.animate-fade-slide-in .animate-ripple .animate-ripple.expanded.item .expanded.item,.animate-fade-slide-in .animate-ripple .expanded .animate-ripple.item .expanded.item,.animate-fade-slide-in .animate-ripple .expanded .animate-ripple.item .item,.animate-fade-slide-in .animate-ripple.done .expanded.item,.animate-fade-slide-in .animate-ripple.expanded.item .animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in .animate-ripple.expanded.item .animate-ripple.expanded.item .item,.animate-fade-slide-in .animate-ripple.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in .animate-ripple.expanded.item .card-avatar-small.expanded .item,.animate-fade-slide-in .animate-ripple.expanded.item .expanded .item,.animate-fade-slide-in .animate-ripple.expanded.item .expanded.item,.animate-fade-slide-in .animate-ripple.expanded.item .in,.animate-fade-slide-in .animate-ripple.expanded.item .item,.animate-fade-slide-in .card-avatar-small .animate-ripple.expanded.item .card.card-comment,.animate-fade-slide-in .card-avatar-small .animate-ripple.expanded.item .item,.animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.card.card-comment .expanded.item,.animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.card.card-comment .item,.animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.item .card.card-comment,.animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.item .expanded.item,.animate-fade-slide-in .card-avatar-small .expanded .animate-ripple.item .item,.animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.card.card-comment .expanded.item,.animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.card.card-comment .item,.animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.item .card.card-comment,.animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.item .expanded.item,.animate-fade-slide-in .card-avatar-small.expanded .animate-ripple.item .item,.animate-fade-slide-in .expanded .animate-ripple.done .item,.animate-fade-slide-in .expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in .expanded .animate-ripple.item .expanded .item,.animate-fade-slide-in .expanded .animate-ripple.item .expanded.item,.animate-fade-slide-in .expanded .animate-ripple.item .in,.animate-fade-slide-in .expanded .animate-ripple.item .item,.animate-fade-slide-in-right .animate-fade-slide-in .animate-ripple.expanded.item .expanded.item,.animate-fade-slide-in-right .animate-fade-slide-in .animate-ripple.expanded.item .item,.animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-ripple.item .expanded.item,.animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-ripple.item .item,.animate-fade-slide-in-right .animate-ripple .animate-ripple.expanded.item .expanded.item,.animate-fade-slide-in-right .animate-ripple .expanded .animate-ripple.item .expanded.item,.animate-fade-slide-in-right .animate-ripple .expanded .animate-ripple.item .item,.animate-fade-slide-in-right .animate-ripple.done .expanded.item,.animate-fade-slide-in-right .animate-ripple.expanded.item .animate-fade-slide-in .expanded.item,.animate-fade-slide-in-right .animate-ripple.expanded.item .animate-ripple.expanded.item .item,.animate-fade-slide-in-right .animate-ripple.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in-right .animate-ripple.expanded.item .card-avatar-small.expanded .item,.animate-fade-slide-in-right .animate-ripple.expanded.item .expanded .item,.animate-fade-slide-in-right .animate-ripple.expanded.item .expanded.item,.animate-fade-slide-in-right .animate-ripple.expanded.item .in,.animate-fade-slide-in-right .animate-ripple.expanded.item .item,.animate-fade-slide-in-right .card-avatar-small .animate-ripple.expanded.item .card.card-comment,.animate-fade-slide-in-right .card-avatar-small .animate-ripple.expanded.item .item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.card.card-comment .expanded.item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.card.card-comment .item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.item .card.card-comment,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.item .expanded.item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-ripple.item .item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.card.card-comment .expanded.item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.card.card-comment .item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.item .card.card-comment,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.item .expanded.item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-ripple.item .item,.animate-fade-slide-in-right .expanded .animate-ripple.done .item,.animate-fade-slide-in-right .expanded .animate-ripple.item .animate-fade-slide-in .expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple.item .expanded .item,.animate-fade-slide-in-right .expanded .animate-ripple.item .expanded.item,.animate-fade-slide-in-right .expanded .animate-ripple.item .in,.animate-fade-slide-in-right .expanded .animate-ripple.item .item,.animate-ripple .animate-fade-slide-in .expanded .animate-ripple.item .item,.animate-ripple .animate-fade-slide-in-right .expanded .animate-ripple.item .item,.animate-ripple .animate-ripple.expanded.item .animate-fade-slide-in .expanded.item,.animate-ripple .animate-ripple.expanded.item .animate-fade-slide-in-right .expanded.item,.animate-ripple .animate-ripple.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-ripple .animate-ripple.expanded.item .card-avatar-small.expanded .item,.animate-ripple .animate-ripple.expanded.item .in,.animate-ripple .animate-ripple.expanded.item .item,.animate-ripple .card-avatar-small .expanded .animate-ripple.item .card.card-comment,.animate-ripple .card-avatar-small .expanded .animate-ripple.item .item,.animate-ripple .card-avatar-small.expanded .animate-ripple.item .card.card-comment,.animate-ripple .card-avatar-small.expanded .animate-ripple.item .item,.animate-ripple .expanded .animate-ripple.item .animate-fade-slide-in .expanded.item,.animate-ripple .expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item,.animate-ripple .expanded .animate-ripple.item .in,.animate-ripple .expanded .animate-ripple.item .item,.animate-ripple.done .animate-fade-slide-in .expanded .item,.animate-ripple.done .animate-fade-slide-in .expanded.item,.animate-ripple.done .animate-fade-slide-in-right .expanded .item,.animate-ripple.done .animate-fade-slide-in-right .expanded.item,.animate-ripple.done .card-avatar-small .expanded .card.card-comment,.animate-ripple.done .card-avatar-small .expanded .item,.animate-ripple.done .card-avatar-small.expanded .card.card-comment,.animate-ripple.done .card-avatar-small.expanded .item,.animate-ripple.done .expanded .item,.animate-ripple.done .expanded.item,.animate-ripple.done .in,.animate-ripple.expanded.item .animate-ripple.expanded.item .expanded.item,.animate-ripple.item .expanded .animate-ripple.item .expanded.item,.card-avatar-small .animate-fade-slide-in .animate-ripple.expanded.item .card.card-comment,.card-avatar-small .animate-fade-slide-in .animate-ripple.expanded.item .item,.card-avatar-small .animate-fade-slide-in .expanded .animate-ripple.card.card-comment .item,.card-avatar-small .animate-fade-slide-in .expanded .animate-ripple.item .card.card-comment,.card-avatar-small .animate-fade-slide-in .expanded .animate-ripple.item .item,.card-avatar-small .animate-fade-slide-in-right .animate-ripple.expanded.item .card.card-comment,.card-avatar-small .animate-fade-slide-in-right .animate-ripple.expanded.item .item,.card-avatar-small .animate-fade-slide-in-right .expanded .animate-ripple.card.card-comment .item,.card-avatar-small .animate-fade-slide-in-right .expanded .animate-ripple.item .card.card-comment,.card-avatar-small .animate-fade-slide-in-right .expanded .animate-ripple.item .item,.card-avatar-small .animate-ripple .expanded .animate-ripple.item .card.card-comment,.card-avatar-small .animate-ripple .expanded .animate-ripple.item .item,.card-avatar-small .animate-ripple.expanded.item .animate-ripple.expanded.item .card.card-comment,.card-avatar-small .animate-ripple.expanded.item .animate-ripple.expanded.item .item,.card-avatar-small .expanded .animate-ripple.card.card-comment .animate-fade-slide-in .expanded.item,.card-avatar-small .expanded .animate-ripple.card.card-comment .animate-fade-slide-in-right .expanded.item,.card-avatar-small .expanded .animate-ripple.card.card-comment .card.card-comment,.card-avatar-small .expanded .animate-ripple.card.card-comment .expanded .item,.card-avatar-small .expanded .animate-ripple.card.card-comment .expanded.item,.card-avatar-small .expanded .animate-ripple.card.card-comment .in,.card-avatar-small .expanded .animate-ripple.card.card-comment .item,.card-avatar-small .expanded .animate-ripple.done .card.card-comment,.card-avatar-small .expanded .animate-ripple.done .item,.card-avatar-small .expanded .animate-ripple.item .animate-fade-slide-in .expanded.item,.card-avatar-small .expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item,.card-avatar-small .expanded .animate-ripple.item .card.card-comment,.card-avatar-small .expanded .animate-ripple.item .expanded .item,.card-avatar-small .expanded .animate-ripple.item .expanded.item,.card-avatar-small .expanded .animate-ripple.item .in,.card-avatar-small .expanded .animate-ripple.item .item,.card-avatar-small.expanded .animate-fade-slide-in .animate-ripple.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in .animate-ripple.expanded.item .item,.card-avatar-small.expanded .animate-fade-slide-in-right .animate-ripple.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right .animate-ripple.expanded.item .item,.card-avatar-small.expanded .animate-ripple .animate-ripple.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-ripple .animate-ripple.expanded.item .item,.card-avatar-small.expanded .animate-ripple.card.card-comment .animate-fade-slide-in .expanded.item,.card-avatar-small.expanded .animate-ripple.card.card-comment .animate-fade-slide-in-right .expanded.item,.card-avatar-small.expanded .animate-ripple.card.card-comment .card.card-comment,.card-avatar-small.expanded .animate-ripple.card.card-comment .expanded .card.card-comment,.card-avatar-small.expanded .animate-ripple.card.card-comment .expanded .item,.card-avatar-small.expanded .animate-ripple.card.card-comment .expanded.item,.card-avatar-small.expanded .animate-ripple.card.card-comment .in,.card-avatar-small.expanded .animate-ripple.card.card-comment .item,.card-avatar-small.expanded .animate-ripple.done .card.card-comment,.card-avatar-small.expanded .animate-ripple.done .item,.card-avatar-small.expanded .animate-ripple.item .animate-fade-slide-in .expanded.item,.card-avatar-small.expanded .animate-ripple.item .animate-fade-slide-in-right .expanded.item,.card-avatar-small.expanded .animate-ripple.item .card.card-comment,.card-avatar-small.expanded .animate-ripple.item .expanded .card.card-comment,.card-avatar-small.expanded .animate-ripple.item .expanded .item,.card-avatar-small.expanded .animate-ripple.item .expanded.item,.card-avatar-small.expanded .animate-ripple.item .in,.card-avatar-small.expanded .animate-ripple.item .item,.card-avatar-small.expanded .expanded .animate-ripple.card.card-comment .card.card-comment,.card-avatar-small.expanded .expanded .animate-ripple.card.card-comment .item,.card-avatar-small.expanded .expanded .animate-ripple.item .card.card-comment,.card-avatar-small.expanded .expanded .animate-ripple.item .item{opacity:1}.animate-ripple .has-mask-reverse:after{opacity:0;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in .animate-ripple.expanded.item .has-mask-reverse:after,.animate-fade-slide-in .expanded .animate-ripple.item .has-mask-reverse:after,.animate-fade-slide-in-right .animate-ripple.expanded.item .has-mask-reverse:after,.animate-fade-slide-in-right .expanded .animate-ripple.item .has-mask-reverse:after,.animate-ripple .animate-ripple.expanded.item .has-mask-reverse:after,.animate-ripple .expanded .animate-ripple.item .has-mask-reverse:after,.animate-ripple.done .has-mask-reverse:after,.card-avatar-small .expanded .animate-ripple.card.card-comment .has-mask-reverse:after,.card-avatar-small .expanded .animate-ripple.item .has-mask-reverse:after,.card-avatar-small.expanded .animate-ripple.card.card-comment .has-mask-reverse:after,.card-avatar-small.expanded .animate-ripple.item .has-mask-reverse:after{opacity:1}.animate-ripple .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-fade-slide-in .item{visibility:hidden}.animate-fade-slide-in .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-fade-slide-in .item-bg-image img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in .expanded .item,.animate-fade-slide-in .expanded.item,.animate-fade-slide-in .in,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in.done .item,.animate-ripple .animate-fade-slide-in.expanded.item .item,.animate-ripple .expanded .animate-fade-slide-in .item,.animate-ripple .expanded .animate-fade-slide-in.item .item,.card-avatar-small .expanded .animate-fade-slide-in .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in .item,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item,.card-avatar-small .expanded .animate-fade-slide-in.item .item,.card-avatar-small.expanded .animate-fade-slide-in .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in .item,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item,.card-avatar-small.expanded .animate-fade-slide-in.item .item{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.animate-fade-slide-in .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in .expanded .item,.animate-fade-slide-in .expanded.item,.animate-fade-slide-in .in,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in.done .item,.animate-ripple .animate-fade-slide-in.expanded.item .item,.animate-ripple .expanded .animate-fade-slide-in .item,.animate-ripple .expanded .animate-fade-slide-in.item .item,.card-avatar-small .expanded .animate-fade-slide-in .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in .item,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item,.card-avatar-small .expanded .animate-fade-slide-in.item .item,.card-avatar-small.expanded .animate-fade-slide-in .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in .item,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item,.card-avatar-small.expanded .animate-fade-slide-in.item .item{visibility:visible}.list .item.item-bg-image{max-height:150px}.animate-fade-slide-in .item{visibility:hidden}.animate-fade-slide-in .item{-ms-transform:translate3d(-250px,250px,0);-webkit-transform:translate3d(-250px,250px,0);transform:translate3d(-250px,250px,0);-webkit-transition:-webkit-transform .5s cubic-bezier(.55,0,.1,1);transition:transform .5s cubic-bezier(.55,0,.1,1);opacity:0}.animate-fade-slide-in .animate-fade-slide-in.expanded.item,.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in .expanded .animate-fade-slide-in.item,.animate-fade-slide-in .expanded .item,.animate-fade-slide-in .expanded.item,.animate-fade-slide-in .in,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item,.animate-fade-slide-in.done,.animate-ripple .animate-fade-slide-in.expanded.item,.animate-ripple .expanded .animate-fade-slide-in .item,.animate-ripple .expanded .animate-fade-slide-in.item,.card-avatar-small .expanded .animate-fade-slide-in .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in .item,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in.item,.card-avatar-small.expanded .animate-fade-slide-in .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in .item,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in.item{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .5s ease-in-out;transition:all .5s ease-in-out;opacity:1}.animate-fade-slide-in .animate-fade-slide-in.expanded.item,.animate-fade-slide-in .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in .expanded .animate-fade-slide-in.item,.animate-fade-slide-in .expanded .item,.animate-fade-slide-in .expanded.item,.animate-fade-slide-in .in,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item,.animate-fade-slide-in.done,.animate-ripple .animate-fade-slide-in.expanded.item,.animate-ripple .expanded .animate-fade-slide-in .item,.animate-ripple .expanded .animate-fade-slide-in.item,.card-avatar-small .expanded .animate-fade-slide-in .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in .item,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in.item,.card-avatar-small.expanded .animate-fade-slide-in .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in .item,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in.item{visibility:visible}.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in .animate-fade-slide-in.expanded.item .animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in .animate-fade-slide-in.expanded.item .animate-ripple .expanded.item,.animate-fade-slide-in .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item,.animate-fade-slide-in .animate-fade-slide-in.expanded.item .in,.animate-fade-slide-in .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in .animate-ripple .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment,.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment,.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .animate-ripple .expanded.item,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .in,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in-right .animate-fade-slide-in .animate-fade-slide-in.expanded.item .expanded.item,.animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-fade-slide-in.item .expanded.item,.animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in-right .animate-fade-slide-in.done .expanded.item,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .animate-ripple .expanded.item,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .expanded .item,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .expanded.item,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .in,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in-right .animate-ripple .animate-fade-slide-in.expanded.item .expanded.item,.animate-fade-slide-in-right .animate-ripple .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in-right .animate-ripple .expanded .animate-fade-slide-in.item .expanded.item,.animate-fade-slide-in-right .animate-ripple .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in-right .card-avatar-small .animate-fade-slide-in.expanded.item .card.card-comment,.animate-fade-slide-in-right .card-avatar-small .animate-fade-slide-in.expanded.item .item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded.item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.item .expanded.item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded.item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.item .expanded.item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.done .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .animate-ripple .expanded.item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .expanded .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .expanded.item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .in,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item,.animate-fade-slide-in.done .animate-fade-slide-in-right .expanded .item,.animate-fade-slide-in.done .animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in.done .animate-ripple .expanded .item,.animate-fade-slide-in.done .animate-ripple .expanded.item,.animate-fade-slide-in.done .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in.done .card-avatar-small .expanded .item,.animate-fade-slide-in.done .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in.done .card-avatar-small.expanded .item,.animate-fade-slide-in.done .expanded .item,.animate-fade-slide-in.done .expanded.item,.animate-fade-slide-in.done .in,.animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .expanded.item,.animate-fade-slide-in.item .expanded .animate-fade-slide-in.item .expanded.item,.animate-ripple .animate-fade-slide-in .animate-fade-slide-in.expanded.item .expanded.item,.animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in.item .expanded.item,.animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item,.animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .expanded.item,.animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item,.animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item,.animate-ripple .animate-fade-slide-in.done .expanded.item,.animate-ripple .animate-fade-slide-in.expanded.item .animate-fade-slide-in-right .expanded.item,.animate-ripple .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .item,.animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-ripple .animate-fade-slide-in.expanded.item .card-avatar-small.expanded .item,.animate-ripple .animate-fade-slide-in.expanded.item .expanded .item,.animate-ripple .animate-fade-slide-in.expanded.item .expanded.item,.animate-ripple .animate-fade-slide-in.expanded.item .in,.animate-ripple .animate-fade-slide-in.expanded.item .item,.animate-ripple .card-avatar-small .animate-fade-slide-in.expanded.item .card.card-comment,.animate-ripple .card-avatar-small .animate-fade-slide-in.expanded.item .item,.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded.item,.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item,.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment,.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.item .expanded.item,.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in.item .item,.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded.item,.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item,.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment,.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.item .expanded.item,.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in.item .item,.animate-ripple .expanded .animate-fade-slide-in.done .item,.animate-ripple .expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item,.animate-ripple .expanded .animate-fade-slide-in.item .expanded .item,.animate-ripple .expanded .animate-fade-slide-in.item .expanded.item,.animate-ripple .expanded .animate-fade-slide-in.item .in,.animate-ripple .expanded .animate-fade-slide-in.item .item,.card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in.item .card.card-comment,.card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in.item .item,.card-avatar-small .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card.card-comment,.card-avatar-small .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item,.card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in.card.card-comment .item,.card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .card.card-comment,.card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .item,.card-avatar-small .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .card.card-comment,.card-avatar-small .animate-fade-slide-in.expanded.item .animate-fade-slide-in.expanded.item .item,.card-avatar-small .animate-ripple .animate-fade-slide-in.expanded.item .card.card-comment,.card-avatar-small .animate-ripple .animate-fade-slide-in.expanded.item .item,.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in.card.card-comment .item,.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in.item .card.card-comment,.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in.item .item,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .animate-fade-slide-in-right .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .animate-ripple .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded .item,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .in,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .item,.card-avatar-small .expanded .animate-fade-slide-in.done .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in.done .item,.card-avatar-small .expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in.item .animate-ripple .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in.item .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in.item .expanded .item,.card-avatar-small .expanded .animate-fade-slide-in.item .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in.item .in,.card-avatar-small .expanded .animate-fade-slide-in.item .item,.card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in.expanded.item .item,.card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .item,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .animate-fade-slide-in-right .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .animate-ripple .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded .item,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .in,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .item,.card-avatar-small.expanded .animate-fade-slide-in.done .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in.done .item,.card-avatar-small.expanded .animate-fade-slide-in.item .animate-fade-slide-in-right .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in.item .animate-ripple .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in.item .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in.item .expanded .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in.item .expanded .item,.card-avatar-small.expanded .animate-fade-slide-in.item .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in.item .in,.card-avatar-small.expanded .animate-fade-slide-in.item .item,.card-avatar-small.expanded .animate-ripple .animate-fade-slide-in.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-ripple .animate-fade-slide-in.expanded.item .item,.card-avatar-small.expanded .expanded .animate-fade-slide-in.card.card-comment .card.card-comment,.card-avatar-small.expanded .expanded .animate-fade-slide-in.card.card-comment .item,.card-avatar-small.expanded .expanded .animate-fade-slide-in.item .card.card-comment,.card-avatar-small.expanded .expanded .animate-fade-slide-in.item .item{opacity:1}.animate-fade-slide-in .has-mask-reverse:after{opacity:0;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in .animate-fade-slide-in.expanded.item .has-mask-reverse:after,.animate-fade-slide-in .expanded .animate-fade-slide-in.item .has-mask-reverse:after,.animate-fade-slide-in-right .animate-fade-slide-in.expanded.item .has-mask-reverse:after,.animate-fade-slide-in-right .expanded .animate-fade-slide-in.item .has-mask-reverse:after,.animate-fade-slide-in.done .has-mask-reverse:after,.animate-ripple .animate-fade-slide-in.expanded.item .has-mask-reverse:after,.animate-ripple .expanded .animate-fade-slide-in.item .has-mask-reverse:after,.card-avatar-small .expanded .animate-fade-slide-in.card.card-comment .has-mask-reverse:after,.card-avatar-small .expanded .animate-fade-slide-in.item .has-mask-reverse:after,.card-avatar-small.expanded .animate-fade-slide-in.card.card-comment .has-mask-reverse:after,.card-avatar-small.expanded .animate-fade-slide-in.item .has-mask-reverse:after{opacity:1}.animate-fade-slide-in .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-fade-slide-in-right .item{visibility:hidden}.animate-fade-slide-in-right .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-fade-slide-in-right .item-bg-image>img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item>*,.animate-fade-slide-in .expanded .animate-fade-slide-in-right .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item>*,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item>*,.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item>*,.animate-fade-slide-in-right .expanded .item,.animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done>*,.animate-ripple .animate-fade-slide-in-right.expanded.item>*,.animate-ripple .expanded .animate-fade-slide-in-right .item,.animate-ripple .expanded .animate-fade-slide-in-right.item>*,.card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in-right .item,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment>*,.card-avatar-small .expanded .animate-fade-slide-in-right.item>*,.card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right .item,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment>*,.card-avatar-small.expanded .animate-fade-slide-in-right.item>*{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item,.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right .expanded .item,.animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done .item,.animate-ripple .animate-fade-slide-in-right.expanded.item .item,.animate-ripple .expanded .animate-fade-slide-in-right .item,.animate-ripple .expanded .animate-fade-slide-in-right.item .item,.card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in-right .item,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item,.card-avatar-small .expanded .animate-fade-slide-in-right.item .item,.card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right .item,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item,.card-avatar-small.expanded .animate-fade-slide-in-right.item .item{visibility:visible}.animate-fade-slide-in-right .item{visibility:hidden}.animate-fade-slide-in-right .item{-ms-transform:translate3d(250px,250px,0);-webkit-transform:translate3d(250px,250px,0);transform:translate3d(250px,250px,0);-webkit-transition:-webkit-transform .5s cubic-bezier(.55,0,.1,1);transition:transform .5s cubic-bezier(.55,0,.1,1);opacity:0}.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item,.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item,.animate-fade-slide-in-right .expanded .item,.animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done,.animate-ripple .animate-fade-slide-in-right.expanded.item,.animate-ripple .expanded .animate-fade-slide-in-right .item,.animate-ripple .expanded .animate-fade-slide-in-right.item,.card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in-right .item,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in-right.item,.card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right .item,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right.item{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;opacity:1}.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item,.animate-fade-slide-in-right .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item,.animate-fade-slide-in-right .expanded .item,.animate-fade-slide-in-right .expanded.item,.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done,.animate-ripple .animate-fade-slide-in-right.expanded.item,.animate-ripple .expanded .animate-fade-slide-in-right .item,.animate-ripple .expanded .animate-fade-slide-in-right.item,.card-avatar-small .expanded .animate-fade-slide-in-right .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in-right .item,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in-right.item,.card-avatar-small.expanded .animate-fade-slide-in-right .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right .item,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right.item{visibility:visible}.animate-fade-slide-in .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .expanded.item,.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .expanded.item,.animate-fade-slide-in .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in .animate-fade-slide-in-right.done .expanded.item,.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .item,.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .animate-ripple .expanded.item,.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item,.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .expanded .item,.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .expanded.item,.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .in,.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item,.animate-fade-slide-in .animate-ripple .animate-fade-slide-in-right.expanded.item .expanded.item,.animate-fade-slide-in .animate-ripple .animate-fade-slide-in-right.expanded.item .item,.animate-fade-slide-in .animate-ripple .expanded .animate-fade-slide-in-right.item .expanded.item,.animate-fade-slide-in .animate-ripple .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in .card-avatar-small .animate-fade-slide-in-right.expanded.item .card.card-comment,.animate-fade-slide-in .card-avatar-small .animate-fade-slide-in-right.expanded.item .item,.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded.item,.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item,.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment,.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded.item,.animate-fade-slide-in .card-avatar-small .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded.item,.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item,.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment,.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded.item,.animate-fade-slide-in .card-avatar-small.expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.done .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .expanded .item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .expanded.item,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .in,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in .expanded.item,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .animate-ripple .expanded.item,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .in,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item,.animate-fade-slide-in-right .animate-ripple .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment,.animate-fade-slide-in-right .card-avatar-small .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment,.animate-fade-slide-in-right .card-avatar-small.expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .in,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item,.animate-fade-slide-in-right.done .animate-fade-slide-in .expanded .item,.animate-fade-slide-in-right.done .animate-fade-slide-in .expanded.item,.animate-fade-slide-in-right.done .animate-ripple .expanded .item,.animate-fade-slide-in-right.done .animate-ripple .expanded.item,.animate-fade-slide-in-right.done .card-avatar-small .expanded .card.card-comment,.animate-fade-slide-in-right.done .card-avatar-small .expanded .item,.animate-fade-slide-in-right.done .card-avatar-small.expanded .card.card-comment,.animate-fade-slide-in-right.done .card-avatar-small.expanded .item,.animate-fade-slide-in-right.done .expanded .item,.animate-fade-slide-in-right.done .expanded.item,.animate-fade-slide-in-right.done .in,.animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .expanded.item,.animate-fade-slide-in-right.item .expanded .animate-fade-slide-in-right.item .expanded.item,.animate-ripple .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .expanded.item,.animate-ripple .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item,.animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .expanded.item,.animate-ripple .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item,.animate-ripple .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .expanded.item,.animate-ripple .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item,.animate-ripple .animate-fade-slide-in-right.done .expanded.item,.animate-ripple .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in .expanded.item,.animate-ripple .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .item,.animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .card.card-comment,.animate-ripple .animate-fade-slide-in-right.expanded.item .card-avatar-small.expanded .item,.animate-ripple .animate-fade-slide-in-right.expanded.item .expanded .item,.animate-ripple .animate-fade-slide-in-right.expanded.item .expanded.item,.animate-ripple .animate-fade-slide-in-right.expanded.item .in,.animate-ripple .animate-fade-slide-in-right.expanded.item .item,.animate-ripple .card-avatar-small .animate-fade-slide-in-right.expanded.item .card.card-comment,.animate-ripple .card-avatar-small .animate-fade-slide-in-right.expanded.item .item,.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded.item,.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item,.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment,.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded.item,.animate-ripple .card-avatar-small .expanded .animate-fade-slide-in-right.item .item,.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded.item,.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item,.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment,.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded.item,.animate-ripple .card-avatar-small.expanded .animate-fade-slide-in-right.item .item,.animate-ripple .expanded .animate-fade-slide-in-right.done .item,.animate-ripple .expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item,.animate-ripple .expanded .animate-fade-slide-in-right.item .expanded .item,.animate-ripple .expanded .animate-fade-slide-in-right.item .expanded.item,.animate-ripple .expanded .animate-fade-slide-in-right.item .in,.animate-ripple .expanded .animate-fade-slide-in-right.item .item,.card-avatar-small .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card.card-comment,.card-avatar-small .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item,.card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in-right.card.card-comment .item,.card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .card.card-comment,.card-avatar-small .animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .item,.card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .card.card-comment,.card-avatar-small .animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .item,.card-avatar-small .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .card.card-comment,.card-avatar-small .animate-fade-slide-in-right.expanded.item .animate-fade-slide-in-right.expanded.item .item,.card-avatar-small .animate-ripple .animate-fade-slide-in-right.expanded.item .card.card-comment,.card-avatar-small .animate-ripple .animate-fade-slide-in-right.expanded.item .item,.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in-right.card.card-comment .item,.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in-right.item .card.card-comment,.card-avatar-small .animate-ripple .expanded .animate-fade-slide-in-right.item .item,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .animate-fade-slide-in .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .animate-ripple .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded .item,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .in,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .item,.card-avatar-small .expanded .animate-fade-slide-in-right.done .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in-right.done .item,.card-avatar-small .expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in-right.item .card.card-comment,.card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded .item,.card-avatar-small .expanded .animate-fade-slide-in-right.item .expanded.item,.card-avatar-small .expanded .animate-fade-slide-in-right.item .in,.card-avatar-small .expanded .animate-fade-slide-in-right.item .item,.card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .item,.card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .item,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .animate-fade-slide-in .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .animate-ripple .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded .item,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .in,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .item,.card-avatar-small.expanded .animate-fade-slide-in-right.done .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right.done .item,.card-avatar-small.expanded .animate-fade-slide-in-right.item .animate-fade-slide-in .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in-right.item .animate-ripple .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in-right.item .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded .card.card-comment,.card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded .item,.card-avatar-small.expanded .animate-fade-slide-in-right.item .expanded.item,.card-avatar-small.expanded .animate-fade-slide-in-right.item .in,.card-avatar-small.expanded .animate-fade-slide-in-right.item .item,.card-avatar-small.expanded .animate-ripple .animate-fade-slide-in-right.expanded.item .card.card-comment,.card-avatar-small.expanded .animate-ripple .animate-fade-slide-in-right.expanded.item .item,.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.card.card-comment .card.card-comment,.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.card.card-comment .item,.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.item .card.card-comment,.card-avatar-small.expanded .expanded .animate-fade-slide-in-right.item .item{opacity:1}.animate-fade-slide-in-right .has-mask-reverse:after{opacity:0;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after,.animate-fade-slide-in .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after,.animate-fade-slide-in-right .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after,.animate-fade-slide-in-right .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after,.animate-fade-slide-in-right.done .has-mask-reverse:after,.animate-ripple .animate-fade-slide-in-right.expanded.item .has-mask-reverse:after,.animate-ripple .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after,.card-avatar-small .expanded .animate-fade-slide-in-right.card.card-comment .has-mask-reverse:after,.card-avatar-small .expanded .animate-fade-slide-in-right.item .has-mask-reverse:after,.card-avatar-small.expanded .animate-fade-slide-in-right.card.card-comment .has-mask-reverse:after,.card-avatar-small.expanded .animate-fade-slide-in-right.item .has-mask-reverse:after{opacity:1}.animate-fade-slide-in-right .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.hero.slide-up,.slide-up{height:100%;overflow:hidden;text-align:center}.slide-up{-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.hero.slide-up *,.slide-up *{opacity:0}.hero.slide-up+.mid-bar,.slide-up+.mid-bar{height:100%;opacity:.7;-webkit-transform:translate3d(100%,-240px,0);transform:translate3d(100%,-240px,0)}/*! * Waves v0.5.4 * http://fian.my.id/Waves * @@ -18,4 +18,4 @@ * Released under the MIT license * https://github.com/fians/Waves/blob/master/LICENSE * - */.button-clear,.button-fab,.button-flat,.button-raised,.button-text,.ink,.popup .button{position:relative;cursor:pointer;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.ink-ripple{position:absolute;border-radius:50%;width:100px;height:100px;margin-top:-50px;margin-left:-50px;opacity:0;background-color:rgba(255,255,255,.4);-webkit-transition:all .5s ease-out;-moz-transition:all .5s ease-out;-o-transition:all .5s ease-out;transition:all .5s ease-out;-webkit-transition-property:-webkit-transform,opacity;-moz-transition-property:-moz-transform,opacity;-o-transition-property:-o-transform,opacity;transition-property:transform,opacity;-webkit-transform:scale(0);-moz-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);pointer-events:none}.ink-notransition{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.button-clear,.button-fab,.button-flat,.button-raised,.button-text,.ink-button,.ink-circle{-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.activated.button-text,.button-clear.activated,.button-clear:active,.button-fab.activated,.button-fab:active,.button-flat.activated,.button-flat:active,.button-raised.activated,.button-raised:active,.button-text:active,.ink-button.activated,.ink-button:active,.ink-circle.activated,.ink-circle:active,.ink.activated,.ink:active,.popup .button.activated,.popup .button:active{-webkit-mask-image:-webkit-radial-gradient(circle,#fff 100%,#000 100%)}.button-clear,.button-clear:link,.button-clear:visited,.button-fab,.button-fab:link,.button-fab:visited,.button-flat,.button-flat:link,.button-flat:visited,.button-raised,.button-raised:link,.button-raised:visited,.button-text,.button-text:link,.button-text:visited,.ink-button,.ink-button-input,.ink-button:link,.ink-button:visited{white-space:nowrap;vertical-align:middle;cursor:pointer;border:none;outline:0;font-size:14px;text-align:center;text-decoration:none;z-index:1}.ink-button{padding:10px 15px;border-radius:2px}.ink-button-input{margin:0;padding:10px 15px}.ink-input-wrapper{border-radius:2px;vertical-align:bottom}.ink-input-wrapper.ink-button{padding:0}.ink-input-wrapper .ink-button-input{position:relative;top:0;left:0;z-index:1}.ink-circle{text-align:center;width:2.5em;height:2.5em;line-height:2.5em;border-radius:50%}.ink-float{-webkit-mask-image:none;-webkit-box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12);box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12)}.ink-float:active{-webkit-box-shadow:0 8px 20px 1px rgba(0,0,0,.3);box-shadow:0 8px 20px 1px rgba(0,0,0,.3)}.ink-block{display:block}.ink-ripple{z-index:0}.button-clear .ink-ripple,.button-text .ink-ripple,.ink-dark .ink-ripple,.list .ink-ripple,[class$="-100"]>.ink-ripple,[class$="-clear"]>.ink-ripple,[class$="-light"]>.ink-ripple,[class$="-stable"]>.ink-ripple{background-color:rgba(0,0,0,.2)}.tab-item{position:relative}*{font-family:RobotoDraft,Roboto,"Helvetica Neue","Segoe UI",sans-serif}.rounded{border-radius:4px}a{cursor:pointer}.has-header.expanded{top:76px}.bar{border-bottom:none;padding:0}.bar .button{min-height:44px;min-width:44px;max-width:48px;margin-bottom:0;max-height:44px;width:48px}.bar .title+.buttons.buttons-right{right:0;top:0}.title-left,.title.title-left{left:48px}.title-right,.title.title-right{left:48px}.activated.button-text,.bar .activated.button-text,.bar .button-positive,.bar .button-positive.activated,.bar .button-positive:active,.bar .button-positive:hover,.bar .button-text,.bar .button-text:active,.bar .button-text:hover,.bar-positive,.bar-positive.activated,.bar-positive:active,.bar-positive:hover,.button-bar-positive,.button-bar-positive.activated,.button-bar-positive:active,.button-bar-positive:hover,.button-positive,.button-positive.activated,.button-positive:active,.button-positive:hover,.button-text,.button-text:active,.button-text:hover,.header-positive,.header-positive.activated,.header-positive:active,.header-positive:hover,.positive-bg,.positive-bg.activated,.positive-bg:active,.positive-bg:hover,.positive-border,.positive-border.activated,.positive-border:active,.positive-border:hover{background-color:#3f51b5;color:#fff}.bar .button-positive-900,.bar .button-positive-900.activated,.bar .button-positive-900:active,.bar .button-positive-900:hover,.bar-positive-900,.bar-positive-900.activated,.bar-positive-900:active,.bar-positive-900:hover,.button-bar-positive-900,.button-bar-positive-900.activated,.button-bar-positive-900:active,.button-bar-positive-900:hover,.button-positive-900,.button-positive-900.activated,.button-positive-900:active,.button-positive-900:hover,.header-positive-900,.header-positive-900.activated,.header-positive-900:active,.header-positive-900:hover,.positive-900-bg,.positive-900-bg.activated,.positive-900-bg:active,.positive-900-bg:hover,.positive-900-border,.positive-900-border.activated,.positive-900-border:active,.positive-900-border:hover,.view-identity .activated.member.refresher-top-bg:before,.view-identity .member .activated.hero,.view-identity .member .hero,.view-identity .member .hero:active,.view-identity .member .hero:hover,.view-identity .member.refresher-top-bg:active:before,.view-identity .member.refresher-top-bg:before,.view-identity .member.refresher-top-bg:hover:before,.view-wallet .activated.refresher-top-bg:before,.view-wallet .refresher-top-bg:active:before,.view-wallet .refresher-top-bg:before,.view-wallet .refresher-top-bg:hover:before,.view-wallet-tx .activated.refresher-top-bg:before,.view-wallet-tx .refresher-top-bg:active:before,.view-wallet-tx .refresher-top-bg:before,.view-wallet-tx .refresher-top-bg:hover:before{background-color:#1a237e;color:#fff}.bar .button-positive-100,.bar .button-positive-100.activated,.bar .button-positive-100:active,.bar .button-positive-100:hover,.bar-positive-100,.bar-positive-100.activated,.bar-positive-100:active,.bar-positive-100:hover,.button-bar-positive-100,.button-bar-positive-100.activated,.button-bar-positive-100:active,.button-bar-positive-100:hover,.button-positive-100,.button-positive-100.activated,.button-positive-100:active,.button-positive-100:hover,.header-positive-100,.header-positive-100.activated,.header-positive-100:active,.header-positive-100:hover,.positive-100-bg,.positive-100-bg.activated,.positive-100-bg:active,.positive-100-bg:hover,.positive-100-border,.positive-100-border.activated,.positive-100-border:active,.positive-100-border:hover{background-color:#c5cae9;color:#fff}.bar .button-calm,.bar .button-calm.activated,.bar .button-calm:active,.bar .button-calm:hover,.bar-calm,.bar-calm.activated,.bar-calm:active,.bar-calm:hover,.button-bar-calm,.button-bar-calm.activated,.button-bar-calm:active,.button-bar-calm:hover,.button-calm,.button-calm.activated,.button-calm:active,.button-calm:hover,.calm-bg,.calm-bg.activated,.calm-bg:active,.calm-bg:hover,.calm-border,.calm-border.activated,.calm-border:active,.calm-border:hover,.header-calm,.header-calm.activated,.header-calm:active,.header-calm:hover{background-color:#2196f3;color:#fff}.bar .button-calm-900,.bar .button-calm-900.activated,.bar .button-calm-900:active,.bar .button-calm-900:hover,.bar-calm-900,.bar-calm-900.activated,.bar-calm-900:active,.bar-calm-900:hover,.button-bar-calm-900,.button-bar-calm-900.activated,.button-bar-calm-900:active,.button-bar-calm-900:hover,.button-calm-900,.button-calm-900.activated,.button-calm-900:active,.button-calm-900:hover,.calm-900-bg,.calm-900-bg.activated,.calm-900-bg:active,.calm-900-bg:hover,.calm-900-border,.calm-900-border.activated,.calm-900-border:active,.calm-900-border:hover,.header-calm-900,.header-calm-900.activated,.header-calm-900:active,.header-calm-900:hover{background-color:#0d47a1;color:#fff}.bar .button-calm-100,.bar .button-calm-100.activated,.bar .button-calm-100:active,.bar .button-calm-100:hover,.bar-calm-100,.bar-calm-100.activated,.bar-calm-100:active,.bar-calm-100:hover,.button-bar-calm-100,.button-bar-calm-100.activated,.button-bar-calm-100:active,.button-bar-calm-100:hover,.button-calm-100,.button-calm-100.activated,.button-calm-100:active,.button-calm-100:hover,.calm-100-bg,.calm-100-bg.activated,.calm-100-bg:active,.calm-100-bg:hover,.calm-100-border,.calm-100-border.activated,.calm-100-border:active,.calm-100-border:hover,.header-calm-100,.header-calm-100.activated,.header-calm-100:active,.header-calm-100:hover{background-color:#bbdefb;color:#fff}.bar .button-royal,.bar .button-royal.activated,.bar .button-royal:active,.bar .button-royal:hover,.bar-royal,.bar-royal.activated,.bar-royal:active,.bar-royal:hover,.button-bar-royal,.button-bar-royal.activated,.button-bar-royal:active,.button-bar-royal:hover,.button-royal,.button-royal.activated,.button-royal:active,.button-royal:hover,.header-royal,.header-royal.activated,.header-royal:active,.header-royal:hover,.royal-bg,.royal-bg.activated,.royal-bg:active,.royal-bg:hover,.royal-border,.royal-border.activated,.royal-border:active,.royal-border:hover{background-color:#673ab7;color:#fff}.bar .button-royal-900,.bar .button-royal-900.activated,.bar .button-royal-900:active,.bar .button-royal-900:hover,.bar-royal-900,.bar-royal-900.activated,.bar-royal-900:active,.bar-royal-900:hover,.button-bar-royal-900,.button-bar-royal-900.activated,.button-bar-royal-900:active,.button-bar-royal-900:hover,.button-royal-900,.button-royal-900.activated,.button-royal-900:active,.button-royal-900:hover,.header-royal-900,.header-royal-900.activated,.header-royal-900:active,.header-royal-900:hover,.royal-900-bg,.royal-900-bg.activated,.royal-900-bg:active,.royal-900-bg:hover,.royal-900-border,.royal-900-border.activated,.royal-900-border:active,.royal-900-border:hover{background-color:#311b92;color:#fff}.bar .button-royal-100,.bar .button-royal-100.activated,.bar .button-royal-100:active,.bar .button-royal-100:hover,.bar-royal-100,.bar-royal-100.activated,.bar-royal-100:active,.bar-royal-100:hover,.button-bar-royal-100,.button-bar-royal-100.activated,.button-bar-royal-100:active,.button-bar-royal-100:hover,.button-royal-100,.button-royal-100.activated,.button-royal-100:active,.button-royal-100:hover,.header-royal-100,.header-royal-100.activated,.header-royal-100:active,.header-royal-100:hover,.royal-100-bg,.royal-100-bg.activated,.royal-100-bg:active,.royal-100-bg:hover,.royal-100-border,.royal-100-border.activated,.royal-100-border:active,.royal-100-border:hover{background-color:#d1c4e9;color:#fff}.balanced-bg,.balanced-bg.activated,.balanced-bg:active,.balanced-bg:hover,.balanced-border,.balanced-border.activated,.balanced-border:active,.balanced-border:hover,.bar .button-balanced,.bar .button-balanced.activated,.bar .button-balanced:active,.bar .button-balanced:hover,.bar-balanced,.bar-balanced.activated,.bar-balanced:active,.bar-balanced:hover,.button-balanced,.button-balanced.activated,.button-balanced:active,.button-balanced:hover,.button-bar-balanced,.button-bar-balanced.activated,.button-bar-balanced:active,.button-bar-balanced:hover,.header-balanced,.header-balanced.activated,.header-balanced:active,.header-balanced:hover{background-color:#4caf50;color:#fff}.balanced-900-bg,.balanced-900-bg.activated,.balanced-900-bg:active,.balanced-900-bg:hover,.balanced-900-border,.balanced-900-border.activated,.balanced-900-border:active,.balanced-900-border:hover,.bar .button-balanced-900,.bar .button-balanced-900.activated,.bar .button-balanced-900:active,.bar .button-balanced-900:hover,.bar-balanced-900,.bar-balanced-900.activated,.bar-balanced-900:active,.bar-balanced-900:hover,.button-balanced-900,.button-balanced-900.activated,.button-balanced-900:active,.button-balanced-900:hover,.button-bar-balanced-900,.button-bar-balanced-900.activated,.button-bar-balanced-900:active,.button-bar-balanced-900:hover,.header-balanced-900,.header-balanced-900.activated,.header-balanced-900:active,.header-balanced-900:hover{background-color:#1b5e20;color:#fff}.balanced-100-bg,.balanced-100-bg.activated,.balanced-100-bg:active,.balanced-100-bg:hover,.balanced-100-border,.balanced-100-border.activated,.balanced-100-border:active,.balanced-100-border:hover,.bar .balanced-100-bg:hover,.bar .button-balanced-100,.bar .button-balanced-100.activated,.bar .button-balanced-100:active,.bar-balanced-100,.bar-balanced-100.activated,.bar-balanced-100:active,.bar-balanced-100:hover,.button-balanced-100,.button-balanced-100.activated,.button-balanced-100:active,.button-balanced-100:hover,.button-bar-balanced-100,.button-bar-balanced-100.activated,.button-bar-balanced-100:active,.button-bar-balanced-100:hover,.header-balanced-100,.header-balanced-100.activated,.header-balanced-100:active,.header-balanced-100:hover{background-color:#c8e6c9;color:#fff}.bar .button-energized,.bar .button-energized.activated,.bar .button-energized:active,.bar .button-energized:hover,.bar-energized,.bar-energized.activated,.bar-energized:active,.bar-energized:hover,.button-bar-energized,.button-bar-energized.activated,.button-bar-energized:active,.button-bar-energized:hover,.button-energized,.button-energized.activated,.button-energized:active,.button-energized:hover,.energized-bg,.energized-bg.activated,.energized-bg:active,.energized-bg:hover,.energized-border,.energized-border.activated,.energized-border:active,.energized-border:hover,.header-energized,.header-energized.activated,.header-energized:active,.header-energized:hover{background-color:#ff9800;color:#fff}.bar .button-energized-900,.bar .button-energized-900.activated,.bar .button-energized-900:active,.bar .button-energized-900:hover,.bar-energized-900,.bar-energized-900.activated,.bar-energized-900:active,.bar-energized-900:hover,.button-bar-energized-900,.button-bar-energized-900.activated,.button-bar-energized-900:active,.button-bar-energized-900:hover,.button-energized-900,.button-energized-900.activated,.button-energized-900:active,.button-energized-900:hover,.energized-900-bg,.energized-900-bg.activated,.energized-900-bg:active,.energized-900-bg:hover,.energized-900-border,.energized-900-border.activated,.energized-900-border:active,.energized-900-border:hover,.header-energized-900,.header-energized-900.activated,.header-energized-900:active,.header-energized-900:hover{background-color:#e65100;color:#fff}.bar .button-energized-100,.bar .button-energized-100.activated,.bar .button-energized-100:active,.bar .button-energized-100:hover,.bar-energized-100,.bar-energized-100.activated,.bar-energized-100:active,.bar-energized-100:hover,.button-bar-energized-100,.button-bar-energized-100.activated,.button-bar-energized-100:active,.button-bar-energized-100:hover,.button-energized-100,.button-energized-100.activated,.button-energized-100:active,.button-energized-100:hover,.energized-100-bg,.energized-100-bg.activated,.energized-100-bg:active,.energized-100-bg:hover,.energized-100-border,.energized-100-border.activated,.energized-100-border:active,.energized-100-border:hover,.header-energized-100,.header-energized-100.activated,.header-energized-100:active,.header-energized-100:hover,.modal.modal-help .activated.row.selected,.modal.modal-help .row.selected,.modal.modal-help .row.selected:active,.modal.modal-help .row.selected:hover{background-color:#ffe0b2}.assertive-bg,.assertive-bg.activated,.assertive-bg:active,.assertive-bg:hover,.assertive-border,.assertive-border.activated,.assertive-border:active,.assertive-border:hover,.bar .button-assertive,.bar .button-assertive.activated,.bar .button-assertive:active,.bar .button-assertive:hover,.bar-assertive,.bar-assertive.activated,.bar-assertive:active,.bar-assertive:hover,.button-assertive,.button-assertive.activated,.button-assertive:active,.button-assertive:hover,.button-bar-assertive,.button-bar-assertive.activated,.button-bar-assertive:active,.button-bar-assertive:hover,.header-assertive,.header-assertive.activated,.header-assertive:active,.header-assertive:hover{background-color:#f44336;color:#fff}.assertive-900-bg,.assertive-900-bg.activated,.assertive-900-bg:active,.assertive-900-bg:hover,.assertive-900-border,.assertive-900-border.activated,.assertive-900-border:active,.assertive-900-border:hover,.bar .button-assertive-900,.bar .button-assertive-900.activated,.bar .button-assertive-900:active,.bar .button-assertive-900:hover,.bar-assertive-900,.bar-assertive-900.activated,.bar-assertive-900:active,.bar-assertive-900:hover,.button-assertive-900,.button-assertive-900.activated,.button-assertive-900:active,.button-assertive-900:hover,.button-bar-assertive-900,.button-bar-assertive-900.activated,.button-bar-assertive-900:active,.button-bar-assertive-900:hover,.header-assertive-900,.header-assertive-900.activated,.header-assertive-900:active,.header-assertive-900:hover{background-color:#b71c1c;color:#fff}.assertive-100-bg,.assertive-100-bg.activated,.assertive-100-bg:active,.assertive-100-bg:hover,.assertive-100-border,.assertive-100-border.activated,.assertive-100-border:active,.assertive-100-border:hover,.bar .button-assertive-100,.bar .button-assertive-100.activated,.bar .button-assertive-100:active,.bar .button-assertive-100:hover,.bar-assertive-100,.bar-assertive-100.activated,.bar-assertive-100:active,.bar-assertive-100:hover,.button-assertive-100,.button-assertive-100.activated,.button-assertive-100:active,.button-assertive-100:hover,.button-bar-assertive-100,.button-bar-assertive-100.activated,.button-bar-assertive-100:active,.button-bar-assertive-100:hover,.header-assertive-100,.header-assertive-100.activated,.header-assertive-100:active,.header-assertive-100:hover{background-color:#ffcdd2;color:#fff}.bar .button-stable,.bar .button-stable.activated,.bar .button-stable:active,.bar .button-stable:hover,.bar-stable,.bar-stable.activated,.bar-stable:active,.bar-stable:hover,.button-bar-stable,.button-bar-stable.activated,.button-bar-stable:active,.button-bar-stable:hover,.button-stable,.button-stable.activated,.button-stable:active,.button-stable:hover,.header-stable,.header-stable.activated,.header-stable:active,.header-stable:hover,.stable-bg,.stable-bg.activated,.stable-bg:active,.stable-bg:hover,.stable-border,.stable-border.activated,.stable-border:active,.stable-border:hover{background-color:#e0e0e0;color:#fff}.icon-help,.icon-help *,.icon-help:active,.icon-help:active *,.icon-help:hover,.icon-help:hover *,.positive,.positive *,.positive:active,.positive:active *,.positive:hover,.positive:hover *{color:#3f51b5}.positive-900,.positive-900 *,.positive-900:active,.positive-900:active *,.positive-900:hover,.positive-900:hover *{color:#3f51b5}.positive-100,.positive-100 *,.positive-100:active,.positive-100:active *,.positive-100:hover,.positive-100:hover *{color:#c5cae9}.calm-100,.calm-100 *,.calm-100:active,.calm-100:active *,.calm-100:hover,.calm-100:hover *{color:#2196f3}.calm-900,.calm-900 *,.calm-900:active,.calm-900:active *,.calm-900:hover,.calm-900:hover *{color:#0d47a1}.calm-100,.calm-100 *,.calm-100:active,.calm-100:active *,.calm-100:hover,.calm-100:hover *{color:#bbdefb}.royal,.royal *,.royal:active,.royal:active *,.royal:hover,.royal:hover *{color:#673ab7}.royal-900,.royal-900 *,.royal-900:active,.royal-900:active *,.royal-900:hover,.royal-900:hover *{color:#311b92}.royal-100,.royal-100 *,.royal-100:active,.royal-100:active *,.royal-100:hover,.royal-100:hover *{color:#d1c4e9}.balanced,.balanced *,.balanced:active,.balanced:active *,.balanced:hover,.balanced:hover *{color:#4caf50}.balanced-900,.balanced-900 *,.balanced-900:active,.balanced-900:active *,.balanced-900:hover,.balanced-900:hover *{color:#1b5e20}.balanced-100,.balanced-100 *,.balanced-100:active,.balanced-100:active *,.balanced-100:hover,.balanced-100:hover *{color:#c8e6c9}.energized,.energized *,.energized:active,.energized:active *,.energized:hover,.energized:hover *{color:#ff9800}.energized-900,.energized-900 *,.energized-900:active,.energized-900:active *,.energized-900:hover,.energized-900:hover *{color:#e65100}.energized-100,.energized-100 *,.energized-100:active,.energized-100:active *,.energized-100:hover,.energized-100:hover *{color:#ffe0b2}.assertive,.assertive *,.assertive:active,.assertive:active *,.assertive:hover,.assertive:hover *,.icon-alert,.icon-alert *,.icon-alert:active,.icon-alert:active *,.icon-alert:hover,.icon-alert:hover *{color:#f44336}.assertive-900,.assertive-900 *,.assertive-900:active,.assertive-900:active *,.assertive-900:hover,.assertive-900:hover *{color:#b71c1c}.assertive-100,.assertive-100 *,.assertive-100:active,.assertive-100:active *,.assertive-100:hover,.assertive-100:hover *{color:#ffcdd2}.stable,.stable *,.stable:active,.stable:active *,.stable:hover,.stable:hover *{color:#e0e0e0}.light,.light *,.light:active,.light:active *,.light:hover,.light:hover *{color:#fff}.button-text-dark,.button-text-dark *,.button-text-dark:active,.button-text-dark:active *,.button-text-dark:hover,.button-text-dark:hover *,.dark,.dark *,.dark:active,.dark:active *,.dark:hover,.dark:hover *{color:#444}.light-border{border-color:#ddd}.navbar-default .navbar-nav>li>a{margin:0;padding-right:26px;padding-left:26px;border-top:3px solid transparent;color:#bfd5c9;opacity:1}.mid-bar{padding:16px}.mid-bar h1,.mid-bar h2,.mid-bar h3,.mid-bar h4,.mid-bar h5,.mid-bar h6{color:#fff;margin-bottom:5px}.mid-bar p{color:rgba(255,255,255,.5);margin-bottom:0}.card>.item-avatar,.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{padding-left:95px}.item,.item-complex .item-content,.item-radio .item-content{background-color:transparent}.dark-bg h2,.item.dark-bg h2,.view-identity .hero h2,.view-identity .item.hero h2,.view-identity .item.refresher-top-bg:before h2,.view-identity .refresher-top-bg:before h2{color:#fff}.tabs-striped .tabs{box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar .button.button-clear,.bar .button.button-text{color:#fff}#menu .footer .bar .button.button-icon .icon-help:before,.bar .button.button-icon #menu .footer .icon-help:before,.bar .button.button-icon .icon-alert:before,.bar .button.button-icon .icon-help:before,.bar .button.button-icon .icon:before,.bar .button.button-icon.icon-left:before,.bar .button.button-icon.icon-right:before,.bar .button.button-icon:before{vertical-align:top;font-size:24px}.menu{background-color:transparent}.button-icon.button.activated,.button-icon.button.active{opacity:initial}.popover{opacity:0;position:absolute;right:8px;transform:translate(50%,-50%) scale(0,0);transition:transform .3s ease-in-out,opacity .3s ease-in-out;top:8px}.popover.ng-enter{opacity:1;transform:translate(0,-14px) scale(1,1);transition:transform .3s ease-in-out,opacity .3s ease-in-out}.popover.ng-leave{opacity:0;transform:translate(50%,-50%) scale(0,0);transition:transform .3s ease-in-out,opacity .3s ease-in-out}.button{overflow:hidden!important}@font-face{font-family:Cesiumicons;src:url(../fonts/cesiumicons.eot?v=1.2);src:url(../fonts/cesiumicons.eot?v=1.2#iefix) format("embedded-opentype"),url(../fonts/cesiumicons.ttf?v=1.2) format("truetype"),url(../fonts/cesiumicons.woff?v=1.2) format("woff"),url(../fonts/cesiumicons.woff) format("woff"),url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiID4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8bWV0YWRhdGE+R2VuZXJhdGVkIGJ5IEljb01vb248L21ldGFkYXRhPgo8ZGVmcz4KPGZvbnQgaWQ9ImNlc2l1bWljb25zIiBob3Jpei1hZHYteD0iMTAyNCI+Cjxmb250LWZhY2UgdW5pdHMtcGVyLWVtPSIxMDI0IiBhc2NlbnQ9Ijk2MCIgZGVzY2VudD0iLTY0IiAvPgo8bWlzc2luZy1nbHlwaCBob3Jpei1hZHYteD0iMTAyNCIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeDIwOyIgaG9yaXotYWR2LXg9IjUxMiIgZD0iIiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwMDsiIGQ9Ik03MDQuNjMxIDU3MS4xMjhjLTg4LjYxMy0xNDEuNDA5LTIyMC40MDMtMjYzLjQwOC0zODUuNTIxLTMwNS40NzMtNjcuMjUyLTE4LjQ5My0xMzcuMTEyLTI1LjgyMi0yMDYuNzA1LTI3LjAyMiA4NS41NDktMTYzLjA5NSAyNzUuODEtMjYyLjI3MiA0NTguNTQ1LTIzNy45NSAxODEuMTY2IDE5LjA3NiAzNDEuNjYyIDE1Ny4yMTUgMzg4LjMzOCAzMzMuMTYyLTU0LjYwMSAxMDMuOTI0LTE0MS40OSAxOTcuODc0LTI1NC42NTYgMjM3LjI4M3oiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTAxOyIgZD0iTTcwNS45MzcgNTcyLjA4OGMtMTYuNzU2LTExMS44MTUtODUuMDg2LTIwNy4yLTEwNy4yNjctMzE3LjIyMS05LjE4OC01MS41NDEgMjYuNzg2LTExMC42NDItMTQuNTc5LTE1NS41MTQtNDYuMjEtNTIuNDAyLTExOC45MDctNjUuMzc5LTE4MS45MzgtODcuNDY2IDE3Ny43My00Ny45MSAzNzkuNjYgMjQuMjE1IDQ4NS45ODIgMTc0Ljc4IDUwLjU1IDY5LjExNiA4MC45OTIgMTUyLjY4OSA4Ni42OTYgMjM4LjEyNS00Ni4wODUgOS40ODMtNjkuNDM2IDU1LjAyMC0xMTAuNTU2IDc0LjIwMS00OS45MTcgMjkuOTkyLTEwMy41NzEgNTMuNTE0LTE1OC4zMzkgNzMuMDk1eiIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeGU5MDI7IiBkPSJNNzA0LjQyMiA1NjMuNGMtMjMuNzg2LTUxLjQwOC0yNi40MzYtMTA5Ljc1Ny01NC4wODQtMTU5LjcyNi03LjIxMS0zMi45MDktNDEuMDkxLTg0LjI4OC0yOS40OTgtMTA2LjQ4OSAxMDEuNTktMTYuNTQyIDIwMy4xODEtMzMuMDg1IDMwNC43NzEtNDkuNjI3IDE4LjI3OCAzNS42NDkgMzEuODQ1IDczLjcxMSA0MC4yMDEgMTEyLjg5NC03My44NjggNzkuMjY5LTE1MC40NzEgMTYzLjQyNi0yNTUuMzU4IDIwMC42MzVsLTYuMDMyIDIuMzE0eiIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeGU5MDM7IiBkPSJNNjY4LjYxNiA0NDUuNzk0Yy0yMC45ODMtMzEuNjc5LTI3LjI0NS03MC40MDgtNDQuMTA0LTEwNC40MjYtMTYuMjIxLTM1LjY4OS01MS40MTUtMTE5LjQ3MiAxOS42ODQtMTA5Ljg5IDUwLjQ1OSAyNC42NTQgOTUuMDUwLTEzLjM3OSAxNDUuODE5LTE2LjkyOSA0MC4zMTctNS41NjEgODIuMTM3LTQuNjY1IDEyMS4yOTUgNy4yMDEgMTQuOTgzIDMxLjcxNiA1MC42ODYgODIuNTk0IDM4LjcyNiAxMDguMzA1LTQ4LjU2MyA5Ljg2Ny05OS40NzMgMTMuODc5LTE0NS4yMTUgMzMuNjkgMTkuMjczIDQ1LjU5NS01NC45NzQgNTUuNDY1LTg5Ljk3NiA2OC44NC0xNS4zNDEgNC42MzctMzAuNzY1IDguOTk4LTQ2LjIyOSAxMy4yMDh6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwNDsiIGQ9Ik02MDcuNzE0IDE2MC44NzNjLTMwLjE4My04NS4wMDItMTIzLjE4Ni0xMTkuOTQ4LTIwMS44MzItMTQ1Ljk0MyA1LjAyMC0xMS4xODYgNzEuMTg2LTE2LjMyNSAxMDAuNzg3LTE3LjMyNiAxMTcuMTE1LTMuMDY3IDIzNC41NDIgNDEuMDg2IDMyMC40OCAxMjAuNzUyLTc0LjgzMSAyLjgzNC0xNDkuNTQ5IDE0Ljc4NC0yMTkuNDM1IDQyLjUxN3oiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTA1OyIgZD0iTTU5OC40ODUgMjY4LjUzNGMtNC4xNzQtNDIuNzY0LTI1LjE4OC0xMTUuOTM2IDM0LjAyOC0xMjguNDk0IDU4LjUzNy0xNC41ODEgMTE5LjQzNC0xOC41MTEgMTc3LjA2Ny0zNy4wMjAgNDUuMjAxIDM3LjQ0NyA4My4xNjcgODMuNTk5IDExMS4xMiAxMzUuMjE3LTEwNy45OC0xLjY4MS0yMTkuNDMxLTEwLjIwNC0zMjIuMjE1IDMwLjI5N3oiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTA2OyIgZD0iTTYwNy4yMSA2MDAuNzhjMTguOTU5IDIuMjkgMzUuMjM0IDEuODk2IDI4LjI4OC0yMS43MiA1LjkzNS0xNC42NDQtMzYuNjE0LTE0LjYwNy0yOC4yODggMS44NDEgMCA2LjYyNiAwIDEzLjI1MiAwIDE5Ljg3OXoiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTA3OyIgZD0iTTQ0NC41NDEgNzAyLjk2MmMyMS4wODggMy45NTggMzIuNjU0LTEuNjA0IDI2Ljk1NC0yNC40MzUtNS42NzMtMTEuMDcxLTM3LjY5Ny03LjY1LTI2Ljk1NCAxNC4wMzYgMCAzLjQ2NiAwIDYuOTMzIDAgMTAuMzk5eiIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeGU5MDg7IiBkPSJNNTA0LjUzMiA2ODEuNzhjMTMuNDc4LTMuMjk4IDQzLjIzNiA5LjY4MiAzNi43NTUtMTMuNTc1IDYuMjU0LTIzLjAzMC03LjA1Ny0yNi40OTYtMjcuMTUtMjMuMTgtMTguNTY3LTUuNDk2LTUuODcxIDI2LjUyNy05LjYwNSAzNi43NTV6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwOTsiIGQ9Ik01MDIuNTM5IDQxNy40MjZjMTguNzg2IDAgMzcuNTcyIDAgNTYuMzU4IDAgMC0xOC43ODYgMC0zNy41NzIgMC01Ni4zNTgtMTguNzg2IDAtMzcuNTcyIDAtNTYuMzU4IDAgMCAxOC43ODYgMCAzNy41NzIgMCA1Ni4zNTh6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwYTsiIGQ9Ik01MDguODU2IDYzMC4xNTdjMTMuNDc4LTMuMjk4IDQzLjIzNiA5LjY4MiAzNi43NTUtMTMuNTc1IDYuMjU0LTIzLjAzMC03LjA1Ny0yNi40OTYtMjcuMTUtMjMuMTgtMTguNTY3LTUuNDk2LTUuODcxIDI2LjUyNy05LjYwNSAzNi43NTV6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwYjsiIGQ9Ik01NjkuMTAzIDQ3NC4xNGMxOC45NyAxLjkyOSAzNi40OTIgMi40MDkgMjkuNDA0LTIxLjcyIDYuODk0LTE1LjkzMi0zNy4yMzUtMTUuODMzLTI5LjQwNCAwLjcyNSAwIDYuOTk4IDAgMTMuOTk2IDAgMjAuOTk0eiIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeGU5MGM7IiBkPSJNNjI3LjA4NyA1MzEuNDAzYzE5LjM1IDcuODY5IDI5LjQwOC05LjU4MiAxOS4zMzgtMjIuMDUzLTIxLjU4My00LjE0Ny0yMC44MDEgMy4zODctMTkuMzM4IDIyLjA1M3oiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTBkOyIgZD0iTTU0Ny42MjcgNTI1LjIzMWMxMy40NzgtMy4yOTggNDMuMjM2IDkuNjgyIDM2Ljc1NS0xMy41NzUgNi4yNTQtMjMuMDMwLTcuMDU3LTI2LjQ5Ni0yNy4xNS0yMy4xOC0xOC41NjctNS40OTYtNS44NzEgMjYuNTI3LTkuNjA1IDM2Ljc1NXoiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTBlOyIgZD0iTTQwMy44MDIgMzM1LjAyNGMxNC40MjYtMS45OTggMzYuNzMgMy44ODIgNDYuNTU2LTIuNzE1LTIuMDIwLTE0LjMxNSAzLjkxMy0zNi41ODQtMi43MTUtNDYuMjkyLTEyLjg3OSAzLjU0NS00MC4wMTctNy4xNjktNDMuODQxIDUuNDMgMCAxNC41MjYgMCAyOS4wNTEgMCA0My41Nzd6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwZjsiIGQ9Ik00NDcuOTA3IDQwNi4wODRjMTYuODM2LTAuMTE3IDM5LjY3NyA1Ljc3IDMxLjg1NC0xOS4wMDUgNy44Mi0yNC4zNTUtMTYuMDgwLTE2Ljk5LTMxLjg1NC0xNy43NSAwIDEyLjI1MiAwIDI0LjUwMyAwIDM2Ljc1NXoiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTEwOyIgZD0iTTUxNS4yOTEgNDY4LjU2N2MtMTguOTcxIDEuODk0LTM2LjYxMiAyLjQ1OS0yOS41MS0yMS43Mi0yLjUzOC0xMi45OSAzOS42MjctMTMuMzc0IDI5LjUxIDUuODkxIDAgNS4yNzYgMCAxMC41NTMgMCAxNS44Mjl6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkxMTsiIGQ9Ik01NzguNDg2IDU3Mi44NjZjMjEuMjMyIDQuOTIgMjkuNDY5LTMuMTU2IDI0LjUwMy0yNC40MzUtMTMuMTA0LTguNTMyLTMyLjk1NS0yLjEwNi0yNC41MDMgMTkuMjAxdjUuMjM0eiIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeGU5MTI7IiBkPSJNNjAxLjQ3MSA2NDEuNjg5Yy0xOC45NzEgMS44OTQtMzYuNjEyIDIuNDU5LTI5LjUxLTIxLjcyLTIuNTM4LTEyLjk5IDM5LjYyNy0xMy4zNzQgMjkuNTEgNS44OTEgMCA1LjI3NiAwIDEwLjU1MyAwIDE1LjgyOXoiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTE1OyIgZ2x5cGgtbmFtZT0iZGlhc3BvcmEiIGhvcml6LWFkdi14PSIxMDY0IiBkPSJNNjcwLjEgMjIuMTA5Yy0yOC42OTIgNDAuMDQ2LTczLjQ1OSAxMDIuNTcxLTk5LjQ4MiAxMzguOTQ1LTI2LjU3OSAzNy4xNTEtNDguMjAyIDY2LjE0Ni00OS4zNCA2Ni4xNjEtMS4xNjkgMC4wMTUtNDIuOTg2LTU2LjE5Ni05OC45MTItMTMyLjk2MS01My4yODgtNzMuMTQzLTk3LjMzLTEzMi45ODctOTcuODcyLTEzMi45ODctMS41MTYgMC0xOTIuMTE0IDEzNC4yNS0xOTIuNjA1IDEzNS42NjMtMC4yMzcgMC42ODQgNDIuODUgNjMuOTM1IDk1Ljc1MSAxNDAuNTU5czk2LjE4MiAxNDAuNTIzIDk2LjE4MiAxNDEuOTk5YzAgMi4zOC0xNy4xNDIgOC4zOTgtMTUxLjYwNSA1My4yMjYtODMuMzgzIDI3Ljc5OC0xNTIuNDIyIDUwLjg2MS0xNTMuNDIgNTEuMjUxLTEuMzg4IDAuNTQyIDYuNTUgMjcuMTAzIDMzLjc4MyAxMTMuMDMyIDE5LjU3OCA2MS43NzggMzYuMDQwIDExMi44MjggMzYuNTgxIDExMy40NDRzNzMuMDExLTIyLjU3NCAxNjEuMDQzLTUxLjUzNGM4OC4wMzMtMjguOTYgMTYwLjc5Ni01Mi42NTQgMTYxLjY5Ni01Mi42NTNzMS45MTkgMS4zNDggMi4yNjMgMi45OTRjMC4zNDQgMS42NDYgMS4xMDQgNzYuNjAxIDEuNjg4IDE2Ni41NjZzMS41NDYgMTY0LjMyMiAyLjEzNyAxNjUuMjM2YzAuODQ3IDEuMzA5IDI1LjU3NiAxLjY1OCAxMTYuMzY0IDEuNjQyIDYzLjQwOC0wLjAxMSAxMTUuOTQ4LTAuNDYgMTE2Ljc1Ni0wLjk5NyAxLjAxOC0wLjY3NyAyLjc1Ny01MC4xMzggNS42Ny0xNjEuMjI2IDQuNzgzLTE4Mi40MDggNC44ODYtMTg0Ljg1MiA3Ljc5NS0xODQuODUyIDEuMTI4IDAgNzAuODk2IDIzLjM1MyAxNTUuMDQxIDUxLjg5NnMxNTMuNCA1MS40MzMgMTUzLjkwMSA1MC44NjhjMS43LTEuOTE4IDcwLjcxNS0yMjYuNjAyIDY5Ljg2NS0yMjcuNDUxLTAuNDY0LTAuNDY0LTcwLjY5LTI0LjUxNC0xNTYuMDU2LTUzLjQ0NC0xMTcuNDMyLTM5Ljc5Ny0xNTUuMzE1LTUzLjE0My0xNTUuNjMzLTU0LjgyNy0wLjIzNS0xLjI0NCA0MC4xNDktNjEuNTk0IDkxLjQ5OS0xMzYuNzM3IDUwLjU1NS03My45ODEgOTEuNzMzLTEzNS4wNjIgOTEuNTA3LTEzNS43MzctMC41MjEtMS41NDktMTg5LjY4MS0xNDAuODg0LTE5MS4yNjMtMTQwLjg4NC0wLjY0MiAwLTI0LjY0MyAzMi43NjUtNTMuMzM1IDcyLjgxeiIgLz4KPC9mb250PjwvZGVmcz48L3N2Zz4=) format("svg");font-weight:400;font-style:normal}.cesiumicons,.cion,.ion-library:before,.ion-office:before,.ion-social-diaspora:before,.ion-social-duniter:before{display:inline-block;font-family:Cesiumicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ion-social-duniter:before{content:""}.ion-social-diaspora:before{content:""}.ion-office:before{content:""}.ion-library:before{content:""}@media screen and (max-width:400px){@-ms-viewport{width:320px}.item .badge{right:16px}}@media screen and (max-width:767px){.hidden-xs{display:none!important;visibility:hidden!important}.badge{text-overflow:ellipsis!important;white-space:nowrap;overflow:hidden!important;max-width:300px!important;display:block!important}.badge:empty{display:none!important}.item .badge{right:16px}.padding-top-xs{padding-top:10px}}@media screen and (min-width:768px){.hidden-xs{display:inherit;visibility:visible}.row.hidden-xs{display:flex!important}.button.hidden-xs{display:inline-block}.item-toggle .toggle{right:32px}}@media screen and (max-width:767px){.visible-xs{display:inherit!important;visibility:visible!important}.button.visible-xs{display:block!important}}@media screen and (min-width:768px){.visible-xs{display:none!important;visibility:hidden!important}}@media screen and (max-width:767px){.padding-xs{padding:16px!important}}@media screen and (min-width:768px){.padding-xs{padding:inherit}}@media screen and (max-width:767px){.no-padding-xs{padding:0!important}}@media screen and (min-width:768px){.no-padding-xs{padding:inherit}}@media screen and (max-width:767px){.no-margin-xs{margin:0!important}}@media screen and (min-width:768px){.no-margin-xs{margin:inherit}}@media screen and (max-width:991px) and (min-width:768px){.hidden-sm,.row-header.hidden-sm{display:none!important;visibility:hidden!important}.badge{text-overflow:ellipsis!important;white-space:nowrap;overflow:hidden!important;max-width:400px!important;display:block!important}.badge:empty{display:none!important}}@media screen and (min-width:992px){.hidden-sm{display:inherit;visibility:visible}.row.hidden-sm{display:flex!important}.button.hidden-sm{display:flex}#menu .footer .popover-helptip .icon-bottom-center.icon-help .button.hidden-sm,#menu .footer .popover-helptip .icon-bottom-left.icon-help .button.hidden-sm,#menu .footer .popover-helptip .icon-bottom-right.icon-help .button.hidden-sm,#menu .footer .popover-helptip .icon-center.icon-help .button.hidden-sm,#menu .footer .popover-helptip .icon-left.icon-help .button.hidden-sm,#menu .footer .popover-helptip .icon-right.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-bottom-center.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-bottom-left.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-bottom-right.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-center.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-left.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-right.icon-help .button.hidden-sm,.popover-helptip .icon-bottom-center.icon-alert .button.hidden-sm,.popover-helptip .icon-bottom-center.icon-help .button.hidden-sm,.popover-helptip .icon-bottom-left.icon-alert .button.hidden-sm,.popover-helptip .icon-bottom-left.icon-help .button.hidden-sm,.popover-helptip .icon-bottom-right.icon-alert .button.hidden-sm,.popover-helptip .icon-bottom-right.icon-help .button.hidden-sm,.popover-helptip .icon-center.icon-alert .button.hidden-sm,.popover-helptip .icon-center.icon-help .button.hidden-sm,.popover-helptip .icon-left.icon-alert .button.hidden-sm,.popover-helptip .icon-left.icon-help .button.hidden-sm,.popover-helptip .icon-right.icon-alert .button.hidden-sm,.popover-helptip .icon-right.icon-help .button.hidden-sm,.popover-helptip .icon.icon-bottom-center .button.hidden-sm,.popover-helptip .icon.icon-bottom-left .button.hidden-sm,.popover-helptip .icon.icon-bottom-right .button.hidden-sm,.popover-helptip .icon.icon-center .button.hidden-sm,.popover-helptip .icon.icon-left .button.hidden-sm,.popover-helptip .icon.icon-right .button.hidden-sm,.pull-left .button.hidden-sm,.pull-right .button.hidden-sm{display:inline-block}}@media screen and (max-width:767px){.hidden-sm{display:inherit;visibility:visible}}@media screen and (max-width:991px){.visible-sm{display:inherit!important;visibility:visible!important}.button.visible-sm{display:block!important}}@media screen and (min-width:992px){.visible-sm{display:none;visibility:hidden}}@media screen and (max-width:767px){.visible-sm{display:none;visibility:hidden}}@media screen and (max-width:991px){body{cursor:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAEbSURBVDiNndMxK4ZRGMbx3zmRMrwvM2XCQFFik/IJpCw+hJLPgfIhLBY+gEEGJQPFwGZg9TIoBrfhOfSQHl7XeM7/fw3nvk+KCPWklEawgGlMlOMrnOMoIm6/8B8FKaWMFazhGQ94LFwbg+jHDvYi4u2zIKWUsIk5XNfE72ljHKfYiIjI5WIZMzhrkJW7s8IuQ8IwdnGDpwa5nhbGsJqxiNcuZIV9xWJWvXY3cr1kOmMSnX8UdDCZEb+RDYmMS9WMu80gLrNqw1r/KGjhPOMQvaol+Wva6MFhjoh7bGEUuVGrkgu7HRH3H8IBTjCLgQZ5oDAnxfnymRKWsI4X1Zw7NbGFPmxjP4qYfvjOQ5jHlGpHqCZ1geOIuKvz76QSW1T3cwmnAAAAAElFTkSuQmCC),auto}}@media screen and (min-width:992px){body{cursor:inherit}}@media screen and (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important;visibility:hidden!important}.badge{text-overflow:ellipsis!important;white-space:nowrap;overflow:hidden!important;max-width:400px!important;display:block!important}.badge:empty{display:none!important}}@media screen and (min-width:1200px){.hidden-md{display:inherit;visibility:visible}}@media screen and (max-width:991px){.hidden-md{display:inherit;visibility:visible}}@media screen and (min-width:992px) and (max-width:1199px){.visible-md{display:inherit!important;visibility:visible!important}}@media screen and (min-width:1200px){.visible-md{display:none;visibility:hidden}}@media screen and (max-width:991px){.visible-md{display:none;visibility:hidden}}@media screen and (min-width:1200px){.hidden-lg{display:none!important;visibility:hidden!important}.visible-lg{display:inherit!important;visibility:visible!important}.badge{text-overflow:ellipsis!important;white-space:nowrap;overflow:hidden!important;max-width:450px!important;display:block!important}.badge:empty{display:none!important}}@media screen and (max-width:1199px){.hidden-lg{display:inherit;visibility:visible}}@media screen and (max-width:1199px){.visible-lg{display:none;visibility:hidden}}@media screen and (max-width:768px){.no-padding-xs{padding:inherit}}@media screen and (max-width:767px){.no-margin-xs{margin:0!important}}@media screen and (min-width:992px){.disable-user-behavior,.scroll,body,html{-webkit-user-selectuser-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}}@media screen and (max-width:844px){.hidden-nomenu{display:none!important;visibility:hidden!important}.visible-nomenu{display:inherit!important;visibility:visible!important}}@media screen and (min-width:845px){.hidden-nomenu{display:inherit;visibility:visible}.visible-nomenu{display:none!important;visibility:hidden!important}}@media screen and (min-width:845px){.hidden-menu{display:none!important;visibility:hidden!important}.visible-menu{display:inherit!important;visibility:visible!important}}@media screen and (max-width:844px){.hidden-menu{display:inherit;visibility:visible}.visible-menu{display:none;visibility:hidden}}.item.item-icon-right .item-select select,.item.item-icon-right.item-select select{right:48px;padding:0 20px 0 16px}.item.item-icon-right .item-select:after,.item.item-icon-right.item-select:after{right:56px}#unitPopover .item.selected,.popover-unit .item.selected{background-color:#f8f8f8}@media (max-width:767px){.popover-share{width:auto}}.popover-share{height:110px}.popover-share .bar{box-shadow:none!important}.popover-share .bar-header{height:20px}.popover-share .bar-header .title{font-size:12px;font-weight:700;height:20px;line-height:19px;max-width:260px;margin:0 5px;text-align:left}.popover-share .bar-header span{font-size:10px;margin:5px;height:20px;position:absolute;right:0;top:0;margin:0 5px;display:block}.popover-share .has-header{top:20px}.popover-share .has-footer{bottom:40px}.popover-share .bar-footer{color:#387ef5;height:40px}.popover-share .bar-footer .button-icon{padding:0 5px}.popover-share .bar-footer .button-close{position:absolute;right:0;bottom:0}.popover-share .item{padding:5px}.popover-share .item input{border:1px solid grey;border-radius:3px;box-shadow:inset 0 1px 1px rgba(0,0,0,.3)}.popover-share .item input:focus{border-color:#387ef5;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.3),0 0 8px #08c}.popover-share .list .item{border-bottom:0!important}.popover-light .bar-footer,.popover-light .bar-header,.popover-notification .bar-footer,.popover-notification .bar-header{height:30px}.popover-light .bar-footer .title,.popover-light .bar-header .title,.popover-notification .bar-footer .title,.popover-notification .bar-header .title{color:#000;text-align:left;left:0!important;font-size:14px;line-height:30px}#menu .footer .popover-helptip .popover-light .bar-footer .icon-bottom-center.icon-help,#menu .footer .popover-helptip .popover-light .bar-footer .icon-bottom-right.icon-help,#menu .footer .popover-helptip .popover-light .bar-footer .icon-center.icon-help,#menu .footer .popover-helptip .popover-light .bar-footer .icon-right.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-bottom-center.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-bottom-right.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-center.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-right.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-bottom-center.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-bottom-right.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-center.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-right.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-bottom-center.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-bottom-right.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-center.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-right.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-bottom-center.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-bottom-right.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-center.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-right.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-bottom-center.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-bottom-right.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-center.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-right.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-bottom-center.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-bottom-right.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-center.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-right.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-bottom-center.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-bottom-right.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-center.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-right.icon-help,.popover-helptip .popover-light .bar-footer .icon-bottom-center.icon-alert,.popover-helptip .popover-light .bar-footer .icon-bottom-center.icon-help,.popover-helptip .popover-light .bar-footer .icon-bottom-right.icon-alert,.popover-helptip .popover-light .bar-footer .icon-bottom-right.icon-help,.popover-helptip .popover-light .bar-footer .icon-center.icon-alert,.popover-helptip .popover-light .bar-footer .icon-center.icon-help,.popover-helptip .popover-light .bar-footer .icon-right.icon-alert,.popover-helptip .popover-light .bar-footer .icon-right.icon-help,.popover-helptip .popover-light .bar-footer .icon.icon-bottom-center,.popover-helptip .popover-light .bar-footer .icon.icon-bottom-right,.popover-helptip .popover-light .bar-footer .icon.icon-center,.popover-helptip .popover-light .bar-footer .icon.icon-right,.popover-helptip .popover-light .bar-header .icon-bottom-center.icon-alert,.popover-helptip .popover-light .bar-header .icon-bottom-center.icon-help,.popover-helptip .popover-light .bar-header .icon-bottom-right.icon-alert,.popover-helptip .popover-light .bar-header .icon-bottom-right.icon-help,.popover-helptip .popover-light .bar-header .icon-center.icon-alert,.popover-helptip .popover-light .bar-header .icon-center.icon-help,.popover-helptip .popover-light .bar-header .icon-right.icon-alert,.popover-helptip .popover-light .bar-header .icon-right.icon-help,.popover-helptip .popover-light .bar-header .icon.icon-bottom-center,.popover-helptip .popover-light .bar-header .icon.icon-bottom-right,.popover-helptip .popover-light .bar-header .icon.icon-center,.popover-helptip .popover-light .bar-header .icon.icon-right,.popover-helptip .popover-notification .bar-footer .icon-bottom-center.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-bottom-center.icon-help,.popover-helptip .popover-notification .bar-footer .icon-bottom-right.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-bottom-right.icon-help,.popover-helptip .popover-notification .bar-footer .icon-center.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-center.icon-help,.popover-helptip .popover-notification .bar-footer .icon-right.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-right.icon-help,.popover-helptip .popover-notification .bar-footer .icon.icon-bottom-center,.popover-helptip .popover-notification .bar-footer .icon.icon-bottom-right,.popover-helptip .popover-notification .bar-footer .icon.icon-center,.popover-helptip .popover-notification .bar-footer .icon.icon-right,.popover-helptip .popover-notification .bar-header .icon-bottom-center.icon-alert,.popover-helptip .popover-notification .bar-header .icon-bottom-center.icon-help,.popover-helptip .popover-notification .bar-header .icon-bottom-right.icon-alert,.popover-helptip .popover-notification .bar-header .icon-bottom-right.icon-help,.popover-helptip .popover-notification .bar-header .icon-center.icon-alert,.popover-helptip .popover-notification .bar-header .icon-center.icon-help,.popover-helptip .popover-notification .bar-header .icon-right.icon-alert,.popover-helptip .popover-notification .bar-header .icon-right.icon-help,.popover-helptip .popover-notification .bar-header .icon.icon-bottom-center,.popover-helptip .popover-notification .bar-header .icon.icon-bottom-right,.popover-helptip .popover-notification .bar-header .icon.icon-center,.popover-helptip .popover-notification .bar-header .icon.icon-right,.popover-light .bar-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help,.popover-light .bar-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help,.popover-light .bar-footer #menu .footer .popover-helptip .icon-center.icon-help,.popover-light .bar-footer #menu .footer .popover-helptip .icon-right.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-center.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-right.icon-help,.popover-light .bar-footer .popover-helptip .icon-bottom-center.icon-alert,.popover-light .bar-footer .popover-helptip .icon-bottom-center.icon-help,.popover-light .bar-footer .popover-helptip .icon-bottom-right.icon-alert,.popover-light .bar-footer .popover-helptip .icon-bottom-right.icon-help,.popover-light .bar-footer .popover-helptip .icon-center.icon-alert,.popover-light .bar-footer .popover-helptip .icon-center.icon-help,.popover-light .bar-footer .popover-helptip .icon-right.icon-alert,.popover-light .bar-footer .popover-helptip .icon-right.icon-help,.popover-light .bar-footer .popover-helptip .icon.icon-bottom-center,.popover-light .bar-footer .popover-helptip .icon.icon-bottom-right,.popover-light .bar-footer .popover-helptip .icon.icon-center,.popover-light .bar-footer .popover-helptip .icon.icon-right,.popover-light .bar-footer .pull-right,.popover-light .bar-header #menu .footer .popover-helptip .icon-bottom-center.icon-help,.popover-light .bar-header #menu .footer .popover-helptip .icon-bottom-right.icon-help,.popover-light .bar-header #menu .footer .popover-helptip .icon-center.icon-help,.popover-light .bar-header #menu .footer .popover-helptip .icon-right.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-center.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-right.icon-help,.popover-light .bar-header .popover-helptip .icon-bottom-center.icon-alert,.popover-light .bar-header .popover-helptip .icon-bottom-center.icon-help,.popover-light .bar-header .popover-helptip .icon-bottom-right.icon-alert,.popover-light .bar-header .popover-helptip .icon-bottom-right.icon-help,.popover-light .bar-header .popover-helptip .icon-center.icon-alert,.popover-light .bar-header .popover-helptip .icon-center.icon-help,.popover-light .bar-header .popover-helptip .icon-right.icon-alert,.popover-light .bar-header .popover-helptip .icon-right.icon-help,.popover-light .bar-header .popover-helptip .icon.icon-bottom-center,.popover-light .bar-header .popover-helptip .icon.icon-bottom-right,.popover-light .bar-header .popover-helptip .icon.icon-center,.popover-light .bar-header .popover-helptip .icon.icon-right,.popover-light .bar-header .pull-right,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-center.icon-help,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-right.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-center.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-right.icon-help,.popover-notification .bar-footer .popover-helptip .icon-bottom-center.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-bottom-center.icon-help,.popover-notification .bar-footer .popover-helptip .icon-bottom-right.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-bottom-right.icon-help,.popover-notification .bar-footer .popover-helptip .icon-center.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-center.icon-help,.popover-notification .bar-footer .popover-helptip .icon-right.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-right.icon-help,.popover-notification .bar-footer .popover-helptip .icon.icon-bottom-center,.popover-notification .bar-footer .popover-helptip .icon.icon-bottom-right,.popover-notification .bar-footer .popover-helptip .icon.icon-center,.popover-notification .bar-footer .popover-helptip .icon.icon-right,.popover-notification .bar-footer .pull-right,.popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-center.icon-help,.popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-right.icon-help,.popover-notification .bar-header #menu .footer .popover-helptip .icon-center.icon-help,.popover-notification .bar-header #menu .footer .popover-helptip .icon-right.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-center.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-right.icon-help,.popover-notification .bar-header .popover-helptip .icon-bottom-center.icon-alert,.popover-notification .bar-header .popover-helptip .icon-bottom-center.icon-help,.popover-notification .bar-header .popover-helptip .icon-bottom-right.icon-alert,.popover-notification .bar-header .popover-helptip .icon-bottom-right.icon-help,.popover-notification .bar-header .popover-helptip .icon-center.icon-alert,.popover-notification .bar-header .popover-helptip .icon-center.icon-help,.popover-notification .bar-header .popover-helptip .icon-right.icon-alert,.popover-notification .bar-header .popover-helptip .icon-right.icon-help,.popover-notification .bar-header .popover-helptip .icon.icon-bottom-center,.popover-notification .bar-header .popover-helptip .icon.icon-bottom-right,.popover-notification .bar-header .popover-helptip .icon.icon-center,.popover-notification .bar-header .popover-helptip .icon.icon-right,.popover-notification .bar-header .pull-right{margin-right:10px}#menu .footer .popover-helptip .popover-light .bar-footer .icon-bottom-left.icon-help,#menu .footer .popover-helptip .popover-light .bar-footer .icon-left.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-bottom-left.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-left.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-bottom-left.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-left.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-bottom-left.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-left.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-bottom-left.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-left.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-bottom-left.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-left.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-bottom-left.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-left.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-bottom-left.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-left.icon-help,.popover-helptip .popover-light .bar-footer .icon-bottom-left.icon-alert,.popover-helptip .popover-light .bar-footer .icon-bottom-left.icon-help,.popover-helptip .popover-light .bar-footer .icon-left.icon-alert,.popover-helptip .popover-light .bar-footer .icon-left.icon-help,.popover-helptip .popover-light .bar-footer .icon.icon-bottom-left,.popover-helptip .popover-light .bar-footer .icon.icon-left,.popover-helptip .popover-light .bar-header .icon-bottom-left.icon-alert,.popover-helptip .popover-light .bar-header .icon-bottom-left.icon-help,.popover-helptip .popover-light .bar-header .icon-left.icon-alert,.popover-helptip .popover-light .bar-header .icon-left.icon-help,.popover-helptip .popover-light .bar-header .icon.icon-bottom-left,.popover-helptip .popover-light .bar-header .icon.icon-left,.popover-helptip .popover-notification .bar-footer .icon-bottom-left.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-bottom-left.icon-help,.popover-helptip .popover-notification .bar-footer .icon-left.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-left.icon-help,.popover-helptip .popover-notification .bar-footer .icon.icon-bottom-left,.popover-helptip .popover-notification .bar-footer .icon.icon-left,.popover-helptip .popover-notification .bar-header .icon-bottom-left.icon-alert,.popover-helptip .popover-notification .bar-header .icon-bottom-left.icon-help,.popover-helptip .popover-notification .bar-header .icon-left.icon-alert,.popover-helptip .popover-notification .bar-header .icon-left.icon-help,.popover-helptip .popover-notification .bar-header .icon.icon-bottom-left,.popover-helptip .popover-notification .bar-header .icon.icon-left,.popover-light .bar-footer #menu .footer .popover-helptip .icon-bottom-left.icon-help,.popover-light .bar-footer #menu .footer .popover-helptip .icon-left.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-left.icon-help,.popover-light .bar-footer .popover-helptip .icon-bottom-left.icon-alert,.popover-light .bar-footer .popover-helptip .icon-bottom-left.icon-help,.popover-light .bar-footer .popover-helptip .icon-left.icon-alert,.popover-light .bar-footer .popover-helptip .icon-left.icon-help,.popover-light .bar-footer .popover-helptip .icon.icon-bottom-left,.popover-light .bar-footer .popover-helptip .icon.icon-left,.popover-light .bar-footer .pull-left,.popover-light .bar-header #menu .footer .popover-helptip .icon-bottom-left.icon-help,.popover-light .bar-header #menu .footer .popover-helptip .icon-left.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-left.icon-help,.popover-light .bar-header .popover-helptip .icon-bottom-left.icon-alert,.popover-light .bar-header .popover-helptip .icon-bottom-left.icon-help,.popover-light .bar-header .popover-helptip .icon-left.icon-alert,.popover-light .bar-header .popover-helptip .icon-left.icon-help,.popover-light .bar-header .popover-helptip .icon.icon-bottom-left,.popover-light .bar-header .popover-helptip .icon.icon-left,.popover-light .bar-header .pull-left,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-left.icon-help,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-left.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-left.icon-help,.popover-notification .bar-footer .popover-helptip .icon-bottom-left.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-bottom-left.icon-help,.popover-notification .bar-footer .popover-helptip .icon-left.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-left.icon-help,.popover-notification .bar-footer .popover-helptip .icon.icon-bottom-left,.popover-notification .bar-footer .popover-helptip .icon.icon-left,.popover-notification .bar-footer .pull-left,.popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-left.icon-help,.popover-notification .bar-header #menu .footer .popover-helptip .icon-left.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-left.icon-help,.popover-notification .bar-header .popover-helptip .icon-bottom-left.icon-alert,.popover-notification .bar-header .popover-helptip .icon-bottom-left.icon-help,.popover-notification .bar-header .popover-helptip .icon-left.icon-alert,.popover-notification .bar-header .popover-helptip .icon-left.icon-help,.popover-notification .bar-header .popover-helptip .icon.icon-bottom-left,.popover-notification .bar-header .popover-helptip .icon.icon-left,.popover-notification .bar-header .pull-left{margin-left:10px}.popover-light .bar-footer a,.popover-light .bar-header a,.popover-notification .bar-footer a,.popover-notification .bar-header a{font-size:14px;text-decoration:none;line-height:30px}.popover-light .has-footer,.popover-notification .has-footer{bottom:28px}.popover-light .has-header,.popover-notification .has-header{top:30px}.popover-light .item.unread,.popover-notification .item.unread{background-color:#ecf0f7!important;border-color:#dddfe2!important}.popover-light .item-avatar,.popover-notification .item-avatar{padding-top:12px;padding-bottom:8px;padding-left:76px;padding-right:10px;min-height:80px!important}#menu .footer .popover-light .item-avatar h4 i.icon-help,#menu .footer .popover-notification .item-avatar h4 i.icon-help,.popover-light .item-avatar h4 #menu .footer i.icon-help,.popover-light .item-avatar h4 i.icon,.popover-light .item-avatar h4 i.icon-alert,.popover-light .item-avatar h4 i.icon-help,.popover-notification .item-avatar h4 #menu .footer i.icon-help,.popover-notification .item-avatar h4 i.icon,.popover-notification .item-avatar h4 i.icon-alert,.popover-notification .item-avatar h4 i.icon-help{font-size:18px!important;line-height:12px!important;vertical-align:middle!important}.popover-light .item-avatar .item-content .item-image,.popover-light .item-avatar .item-content>img:first-child,.popover-light .item-avatar .item-image,.popover-light .item-avatar>img:first-child,.popover-notification .item-avatar .item-content .item-image,.popover-notification .item-avatar .item-content>img:first-child,.popover-notification .item-avatar .item-image,.popover-notification .item-avatar>img:first-child{top:12px;left:10px}.popover-light .button.button-small,.popover-notification .button.button-small{height:30px;font-size:12px;padding:0 5px!important;line-height:30px}.popover-invitation,.popover-network,.popover-peer-info{width:420px}.popover-endpoints .item .badge,.popover-peer-info .item .badge{right:16px}.popover-endpoints .item .badge.badge-secondary,.popover-peer-info .item .badge.badge-secondary{top:35px!important}.popover-unit{height:108px;max-width:115px}.view-notification .item.unread{background-color:#ecf0f7!important;border-color:#dddfe2!important}#menu .footer .view-notification ion-item h4 i.icon-help,.view-notification ion-item h4 #menu .footer i.icon-help,.view-notification ion-item h4 i.icon,.view-notification ion-item h4 i.icon-alert,.view-notification ion-item h4 i.icon-help{font-size:18px!important;line-height:12px!important;vertical-align:middle!important}.bar.bar-header .button.button-clear.button-icon i.ion-android-more-vertical,.bar.bar-header .button.button-clear.button-icon.ion-android-more-vertical,.bar.bar-header .button.button-icon.button-text i.ion-android-more-vertical,.bar.bar-header .button.button-icon.ion-android-more-vertical.button-text{padding-left:8px;padding-right:8px}#menu .footer .popover-helptip .bar .buttons.icon-bottom-center.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-bottom-right.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-center.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-right.icon-help,#menu .footer .popover-helptip .bar>.button.icon-bottom-center.icon-help,#menu .footer .popover-helptip .bar>.button.icon-bottom-right.icon-help,#menu .footer .popover-helptip .bar>.button.icon-center.icon-help,#menu .footer .popover-helptip .bar>.button.icon-right.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-bottom-center.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-bottom-right.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-center.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-right.icon-help,.bar .buttons.pull-right,.bar .popover-helptip #menu .footer .buttons.icon-bottom-center.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-bottom-right.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-center.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-right.icon-help,.bar .popover-helptip .buttons.icon-bottom-center.icon-alert,.bar .popover-helptip .buttons.icon-bottom-center.icon-help,.bar .popover-helptip .buttons.icon-bottom-right.icon-alert,.bar .popover-helptip .buttons.icon-bottom-right.icon-help,.bar .popover-helptip .buttons.icon-center.icon-alert,.bar .popover-helptip .buttons.icon-center.icon-help,.bar .popover-helptip .buttons.icon-right.icon-alert,.bar .popover-helptip .buttons.icon-right.icon-help,.bar .popover-helptip .buttons.icon.icon-bottom-center,.bar .popover-helptip .buttons.icon.icon-bottom-right,.bar .popover-helptip .buttons.icon.icon-center,.bar .popover-helptip .buttons.icon.icon-right,.bar .title+.button:last-child,.bar .title+.buttons,.bar>.button+.button:last-child,.bar>.button.pull-right,.popover-helptip #menu .footer .bar .buttons.icon-bottom-center.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-bottom-right.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-center.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-right.icon-help,.popover-helptip #menu .footer .bar>.button.icon-bottom-center.icon-help,.popover-helptip #menu .footer .bar>.button.icon-bottom-right.icon-help,.popover-helptip #menu .footer .bar>.button.icon-center.icon-help,.popover-helptip #menu .footer .bar>.button.icon-right.icon-help,.popover-helptip .bar .buttons.icon-bottom-center.icon-alert,.popover-helptip .bar .buttons.icon-bottom-center.icon-help,.popover-helptip .bar .buttons.icon-bottom-right.icon-alert,.popover-helptip .bar .buttons.icon-bottom-right.icon-help,.popover-helptip .bar .buttons.icon-center.icon-alert,.popover-helptip .bar .buttons.icon-center.icon-help,.popover-helptip .bar .buttons.icon-right.icon-alert,.popover-helptip .bar .buttons.icon-right.icon-help,.popover-helptip .bar .buttons.icon.icon-bottom-center,.popover-helptip .bar .buttons.icon.icon-bottom-right,.popover-helptip .bar .buttons.icon.icon-center,.popover-helptip .bar .buttons.icon.icon-right,.popover-helptip .bar>.button.icon-bottom-center.icon-alert,.popover-helptip .bar>.button.icon-bottom-center.icon-help,.popover-helptip .bar>.button.icon-bottom-right.icon-alert,.popover-helptip .bar>.button.icon-bottom-right.icon-help,.popover-helptip .bar>.button.icon-center.icon-alert,.popover-helptip .bar>.button.icon-center.icon-help,.popover-helptip .bar>.button.icon-right.icon-alert,.popover-helptip .bar>.button.icon-right.icon-help,.popover-helptip .bar>.button.icon.icon-bottom-center,.popover-helptip .bar>.button.icon.icon-bottom-right,.popover-helptip .bar>.button.icon.icon-center,.popover-helptip .bar>.button.icon.icon-right{top:0!important}.bar.bar-header{padding-right:5px!important}.bar.bar-header .buttons-right span{margin-left:0!important}.bar .title+.buttons.buttons-right{right:5px}.button-icon{border-color:transparent;box-shadow:none!important}.button-small-padding{padding:0 7px!important}.button-text{color:grey!important;font-size:12px}.button-text.button-small{padding:5px 2px;font-size:12px!important}.button-text-positive{color:#387ef5!important}.button-text-stable{color:#b2b2b2!important}.popup-buttons .button.icon-left,.popup-buttons .button.icon-right{padding-left:32px!important;padding-right:32px!important;line-height:42px}#home .logo{margin-top:15px;width:100%;background-position:center center;background-repeat:no-repeat}#home .center{float:none;text-align:center;display:inline-block}#home .center .button{display:inline-block}@media screen and (max-width:767px){#home .logo{height:96px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4AgRBwUf93UlLAAAIABJREFUeNrtnXd8VkX2/99z71PTewEChBK6VCnSAigIUlVgLeuqq7vq2nddf+vqV9a2rm0XXQvsVxF11Q0qJKFLCSBNqZESOoSEkoTwpD/t3vP7IyEkkEASsO3Xeb2e1+u5be7c85k5M/M558zAz+nn9HP6Of1gSf3UP2DSOxuuMUW1AbAoWfH5Pf33/ZTKb/lJS3+aaIba+mfN9A4FMOA24GcAGi4/0TI+IcIMJlxBlAbh4scGoOv4fVAOIAqXHQr8BeRl3I4nOZ1+CqaIMNkoDGqhVRT+ZOvQDwpAxhwCkkoomnmzKjhTc5NTJMhnR1UIAXYnIVJGuKYR6dHoa4libHI6VwHhUqlAS02rc5vptRdofs8JEfPAhd43OUV0QJ8zRXl/7gMamIalSgdTcZ+CXwOBgBtYpjTSMdipFC1N6ILCIbDT6mXVshvUwfryG71Q7BUVRJcUcHLzb5XvZwDqScNTZYipMQ1hWFVJj4vJGw47M5Zcqwrr6g+GXEVb5WGQMmmlwUm/TsbqsWp3XfkPSZNEzYIvY4zK+RmAmjV+nvQTjSeBsQAi7FXwFiHMyBim3A3NZ0SqxBqK0UAHUXztrWDx+imqouY9ySkSh5W45IlkTlPK/D8NQPJ86YrJC8C4qlP7gLUIZUojRgQNReiZ+0UoBE4oxXFMjiPkorMtY5wqODfvwenSyyKMFY1iND6rWet7p0tAEHQP0Nm5aIwq/j8HwLBUGSgaT4nJNUqhVZ32C2QrOI3iNEKRUpgihAGaQLiCSIF4ReWoqUY6DGxGsUlg1arNbGRaZe0eMk8SlMYvFRheO7PWjVJ5ZzrnfCcD8JOTMUkd/u8GYJpoyb25SgnXi3CzaEQowaqgHOEjMflrxkSOoJQ0JK8hPWiu6bQVoZuC7gJXAl0V1WDmK5iPMF88LM2YokpHpkmiT3GHKeQrgw8zJikXwLD50tvwUr76+rr7jZ80AIMXSrTu5zcCdwL7lRCCoj8gCDN0gyeXX69O1SfogT0J1PwEKRtBmARpGoHqw8ljJC8rSRtwz3Lp/7ts0bAKGLqJQxSdTKE3igEKoqu+1o3wmTL558qJamNyqvRB8VsMFmRMUvMABs+TzladoBXj1Nf/FQCMSJUrDMWDQAcFH5omu5XGe0A74CRwV8Z4Nf+czjHIEkCM3yRGCTEGROnq/DmLvNT+finY31Uf+tgMue6lrXW9X0ApaCnQT+BKBSFVFw4rxVzNZK5PZ6hSRPisvLhulMpLTpeOpkHE6omshwa0xB8jAEPSJFHBc5rCKiYvZUxQm4aly20ivAM4ET7TDe45U+uT0yVKhEQ0Wmsm4TXzig3A2j2SkE7hhMc6aR5sJTjQQuDL9yb32r1lTdifXvrYlTxmqnhNTISSKsF7vCbuMh+lJT7yT7kpOFlByapjxO0tpp/XoE1V9iUIS5TGQUwGicZbGePUv0d8IUk+jajVE9W6n9RMOHmuhCmNJ0whVmk8u3Kcyhq9UOxD0+TfItwMuJTirpXj1cfJKRI0PF36+qGdEoIUYFOYI1sT3j+GpJZBdIl00M6pE1nXu0KCgkCBw24Ns2pgrdT6te6NsNd+5sYqsW8v5NAr2zidU0p3FDeKcFrpfClwdfJ8aWFs4lVrXyzJC6RHxnVq208CgOR0uQW4yYTnV41T68+okwofnynFKIGDojFWPLiS58vVylfeRiSApBAcN7ahfY8oukY76KspAr5r1dg9gsQPh5N4rIwTf9vi25vpsvYTkylKyFEKm/Tk76qUJw0nbUd8IUnLr1d76+ufzoyyfjAABi+UaIufV0XYmbGF8WcKNOILiTQszAf6AxuUxt1K6IBuxqq/tn8wNj6hfPrsjNMxAQwH9Ka9/dJUdIzNG3fquS5xt954X9GGpEe27i+mv8DNaOzwO/jECneLnbZD5knF6onq6Hnf3pfINZD/gwEwLFWuF4PJuuLxZeNUdnUfME8SDI0VQDtN8ZnpY7aycFWbUJz3dNb6rM0c0ybt07cdFcd3Q9tOTXp3xyv64naXEx3bosnlT5n1GseO7qf/lf1Df92D/utOsPfZrWhuP10FksRkqa4Ypym6DEwV19oJqqTm87qgX5Mqzb6coI59r51w8kqxqGJeEEVRxhb+WrMZVtX8NUAn4H1RrOsQSuBDXRjSMZyxmsJaXlbC1GEJtEzsyJv/2fCDTAJdp/KYOqIVfQdfy7NvzK0+bwrmu1ms+WQ/3QXCAJcGN2BgWbGdZeeqnGHzZdTKsWpJU8qgNeWhUYslQkqYrWB+xnj1fM0CjUuXAMNCKtBJQUqonW9e7MtVbw/ixc4RTNIUVoCAwGDuffw1dmVuZH3G/B8EgDdeeBjTMHjgiem1haLQ7u7E0E+uxh/pYDsQZsAS00Kv5J70Oi8jk5yh6TLgeyn0iAWSlJwqc4akSeK513rPEOvQNFmQnCaSnCbpb+yQp8p8clTqSYZhyG3XdZLrB8eJ1+OW7zPt3bVFkjspeW/6Uxe8zxSRd3fLhuRU8VZ916JrPpP252mENHn8uyfM0iU5OU3mjV4oIXX2B2nyWnKayIj5svbbUzK/IYLYsXWdDOuEfDzzxe8VgLsm9ZDx/SLFXVHWoPt3FkrO8HQpqgIhe8h86XROXzh+SKr0/M5U0PA0GW4tK3wyOGfrDOf+jSF1gDNR4GGHTtbn19C8awTXNSTfLj0GcNWIibz/5jRcp/K+l1a8YuGn7N+9jYeffgu7o2Ej3s7hNH9jINkojgMJymRDcrokn7ke5WGBUtz4nQAwPE2GC9waULi/u453oWmRSeeg3wHhA02j4OPhxITaaNWYQjz05zdAYF1G+vcCQGH+CXr0TWbY6CmNeq5zOF1/2Z5vUBxQEBiUt2vFhLc35U56a8MOf8HG7cH5u64dvkBaXVYAhqfKEBPuc1i4F5QFwFQWZ03extSYK2B58ypOhTuIaKxAouNa8PGyg4y54dfnXzQ8cPrbyp8YlwWAG3/1MH+fvbJJz96exNhYBzsQVmt+N0r8zQS6CHTRvWVe0+CeywbA8HTpZWj8nmBuXTRGedxh8a9XhLR4VTT1KUDyLHEoJy8podNN7fimYzgdmyqUyOj4eq6Y4HFV/hB+6KQptBf70U7p2JRp1rLQaWJWICQg0uDhfb0TsZFfSIwXngnQuXnRMOVOXikObwm5JhxdcmuL7MkpYsuzMhlhSridzb/pxODv6JPBEVV72uIpwMidV3nGGoaWcOP3CkLrYLoMi2Pe5hxlqaNOfDN0Pv1Xwfomt4DeM8TqtTLdAvdVm+lcxAFoGnkgKt/OcKUxBgj45yDi1XfFrOp2COtU+VM6P5b0aHcGmxZ7mWmxuQS1F2SHIAc1C/MUTL2kFhAUzyuYvLpswllqAb0SANE4OTidnsogQjQmj23JmhDDlXwqr5zImGb8X0kFR3ZFjh7QdV7KfuJF59+rxqo3aswJ2jaUpNPqGE5ORdiRMUFtqkV5qUqrkkNh0YRYE661ahx5qBtXzXr9f7jp6jbMfusZvB73d//19kj0xNvRE29Ha3F2QFZ2bCOFuz+l+NDS7+zVecezeeLecdwxriu9i1eOtGq4lcnwIfMkocZt24f3pkejW0ByukQh9F81QT1SB+kYJhoet58edjvbPR6m3tOZrRaNNrfd9z+43eXMfnMaX3wwnfv+32uMmvirJn9kWUkRh/btoCDvGOVlxZiGgTMwGKczkBatk2iW0AbNtR78ZZW1KGoQWEPwlR3HXbgHW1D8ZRe8x11OyqxX+fDt51Cazp0PPkvPXlcFjN5DYdphWqC4HpgOoBQrBQYBWxpFxg1Ll2eC4MX0caq85vnJKWIrcHC7qRFlMXjXD390WBi9aAwdahi/2bdrCy/9+dfsz9pG+869ePz592jbsXuDPvDIgd0sTf2AtStSOXLgwjZxXbfQqWM7evdMYkRyf1r0+Q3KHklpzlo8rgNYnJGEtr3usgl/7Yo0XnnqLlynCxg68gYefupNwiJjADjt5vgNyzkoJvkEc1NG1YBFipmxaoL6VYMBGJYuYzA4tXKi2nge/5MqsSbcic5Jr8EcqyL3d13ZcWMi5xFQIsLy+R/z+vMPUlpymlETbuOex14hNDyqzgIcP3qQGa8+zuovv0DMxts1lKb45V2/545HXq5dDvdJMN2gB6HskU1TNyeO8sS94ziQtZ2kLr3543Pv1lmhHljL3B2nSBR4dNUEtbJKnikrx6kpZ+02otXl/KUBDEgRp0CzuoRfOfEiCkW8YbDVChN0RfGk1vStUyBKcfW4W0hZmc0v7vwjy+d/SvbBrDo/cP6cf/Hrid1ZteSzOoWv6ToRUXHExLckMDi0bnOMKfQZdH5tl9NbME98iRTvbHLND4+IISgkjKf/nsKMzzbV25pvbU+M0vAqmFKD0j5ek7BMn4+j3j7AbmMgQbxfX0FEo79mkm3qFGkmU0Y0J0tXNL9Q4R3OQH7z+xf5xa8fIyTs/Br47vQn+eid5887f+WgUQy55nr6DBxJbLNWKHVWSxa7TrE/axub1y3jq+XzyD6YRc/+w+l2ZXLjpev3gsV2wVusNjv/mJ1x0ayujKafVZHhUfRNnithGZOUS1NsFugNHAJwKuxUudvXAmBgqgSbGkdWD1P+egwvQZQQLFBs86FMnavv7EiDXfjqEn7KrFfPE377Tj25/8/TuaL34Avm1av/CHr1H8Hdj/6VzE2rCQyq0TJMH+RtAM2KihyAJl5Eq6PiuQ5T+t51+ALjsLfqT8DIZ0HTmtxSNIXlqjhKMo4Rr2AE8LloZCo/I6s1g6fuFqAFGjhXj1P1R5WU0kMJ2QCGheFhdnbGOoltamEzN69hxqu1qfN+Q8bwxsdfXVD4daUr+gypVy0oWxjYY1DWkHN1FmTNozy+M+VdhlBqFOCaMZjTsyfjP7y+ySCMSSAe8Boalc2xjP2mOktKWrW6HQ20pZkU1Jfp6IUSguA3tcoJtzIZOiaB0qYW0jQMpj97P6ZxllTr1X8Ez705r8G08IV7ZAtE9oDwrvXfszedshN7MOI7AOALbUZZt5F4midQuup/yH//Bjy7Gm+h6xVND4uiTKt0jSRjiirVwHlmFOm31M06WC40W/MIPXCzBQeJojAFBoxv3XSXkWULPubgnszq4+DQCP704mwsFuulCV78YFZpUEvAWcpC/JinNqJsYRT5Y9i/IZ3cfevJ37sJX2gkNpuV8NBg4uMiad48BqPtIKzFJyjbOpOib2YR3GkMzr6/bhhjonC0CSNv72muGJkuHZeOU9Ujj+IQguweyhpFxvVOlwBDkFVTVOnQdHEgBNl1fLHOSkqiKWnuv/9Z6/iOB/5CVGzzS674Zv4apLQyOkmLHowK7lB1wc/GFSn8Z+5KMjN3XnCY63TY6ZjUin5XdqFv906ElORSfGIDJR8sJqTbDTh6/uKi5RgQjWNfIYZXkQxkiapsAT6DYDOEokbR0QHQ0YAdZ4BS0KZdCCeaKqSjh/aQlXnW3zUgKOSSZssXSz6vhxeeuIsnnn6d7du+vegco8LtYWvmXt55dy6rN+7EHdMeHT8S1wxXbgb5H/4C39FvLphHvxiamQpDhG4ASqiYnCK6CeHR+eePgC7QAkQpIWzNOHW6Rt+VMDCu6X5E33xV22tj+OipBAQGXxZhK6WfsRVV16m//+Vevkz7d635Sdeu3YjWSwmIqyQNS0rLyD2Wz6Hs4xj+yn4pMMDJ4KsqO3ZPRGusJXkoDbyJnTi1/h84vw4ldNLroJ0viqRQOipFFpB0ZryVD07NT0h9gYF1CvTqdBIMk9wa02VBI/rKaKKaKqRvt66tddytz+UzH6joIajoIdXH+7O2seiLWdXHfXp259HHniA+Pp4Ti17FaF/bdl5e4WbL9j1s2rybhBax2G1n5we+4Bh0dxE2Vw7eZkmU+91437+eiDEvoMfV7ux1DUeIlfJiLy2SZ4nDVPjsFgK8Wv2apk4ADGhffILVtT5SiE4Mbpytt2Y6dzbcpUfT3GjchfswvSXojjDsYW1qXTu14wMMTxErl571pQ0KCOCZ51/C6XRinDqEFhzAuYbNAKeDQf27M6h/3UNawxEKKGynj+INT8Cb1Jv8L6cR2m0yzh61qf8YB95iL7qKpK0Ifr+DYAz8DaajJ6eIDeDcEE5dR7do2JsKwPGjB2upg/jmiU1jSo+tw3UgnfIT5+tjv/s0fncheSeqGy8tWrbE6aw0YRdvW4wvrkOT3ms4QjCcIdhclXkbid0oykqjbOOsWvclhqBVcWztAAwvzUwfpxoMwPEAWig/h8+honWR+lFsyPjfXVFWqwPW9Mtv3bIFNcMWnEBQjdlxbk4uHo8bTBOf99Ji8AxHKKbNgaWs0hfXaJFESU4GxYufqr6nZTCBCjRTiFGKQA0CNGv9zrvnqSAdmkf62Hh+t4xLqqC9upsNw187xnn8L+7hkaffrlttuMsROWs8DQoOa7IQIrvcWpmXOt8CGt5xMhheOsdvYF7VuZLSEv7xj79zb3I7jFadLhlkf0Ak1uITHM7ay5Ovfnz2wiPPAfC7WZlAN5QiBiEIDUfyWAozGtYCRCmw+wo2fjTx7Q2ZE9/a8OyZTlhMigwTz5kmcR6SFyC2bPbaNIjffwkB6kpHISh/KfiKzv7ED34PZM5myNjJxETHVD+yePEiHnrtAzZ8m41hXno4sC8kDoe/pO75xJrnWldJKEYUEZi4LxSDXKsFDF5IlDI5LUp1USKdDYujoKr2mwgej8Fxi0brZd82ToAWixWHM7BaDZUWuxr3xd5CEANR1kqOpyIHs6A2b6OFXQkHMiC+A3almPaXZ/jDY7+nvKzynYfzinj9nRQiwkMYPqQPw4b0IjQkqMkgxHXpxWcvhOCOru0muj8rv6hK2lFKiNNsHL0gkVerpvqI93s4hqan+QIiT/sCooKqxqGiwOfycbKpBQ4OPRv25XGX4/N6GjHT/aqS2y/cVM/QqAj2zodmHatVU6dOnXn7rRl06FDbVanwdDGfpa7gwcf/zjvvzuXQkWNNbIkKb2iz6k757GmbW4GhhAiBQKOU7AYDYGhE6BHkp/62z5/KI9p94g5pHjQsVTpg4EZhFFTQZOfN8MjaBOqhfTsuT89bfBLysiC27XmXWrZsyduvT+fhCb1JbFXbY8PwG3y1YTtPPTeT516axZbtexo/uLAFVgrRe3aSW64HlCqoUOBU4M2YokobDICYqIwqu4Cq9PHHhAla5UIZlmNlHG+qnDp07VPreHdmI8JwraFgi0DZzqGW8/ZC2TGIqN8IX/rNHPpeey3PPvkbnnniboYO6onNVpv8y9p3hNf++QmvvfkJ5RWN8+rwhjXHVlzZiixuF4UB7Q4KlJtCNIr9F7UlnPkzTURTGtXKvd1RVlIZ0TjeVBxDYd1f1PQW0Ll7/1rHWzYsb7jBI2YoWvy1qIhKK6jowagTx1AhzVGxvVABrRC9TnsH5cUnMavY1jaJzbn7VxN4/W+PMPX6q4kMr23m3LJtD8+//D5er6+RILTA5spFHT/M2sipG4ASTSNMGuAVUQ3AmuWEo6juHWf+VvkQlgARGrQX0DNP1T+huFjq2vOqWsfrVqRxKr8JDSp/F2rvfFTClajQjihni8qf7jx/tHJkM4SfT94GBQUwbvQgXnvhQaZMGlGLejhy9ATpi75qnCqyOFCmD79Yjd1uZ4VoVJhCgGayq8EAGD6CTX9tytTUSamiJiYqsB0oodxtNK0jbtE6iXYde9Qaip5LT5+tUqeh7NDZn1EOhhd2poBrN8S0bZAJ0bVvHf6o+ulu3aIzfsxgnnzs9lpqafW6xocFe8MS8LqNUkzQIECDALGwucEAmAZOo0YLAFg9Vu0W2KiEAYpKm+bxCpoctDzxlt/VOv7Pe6+wP+v87KQ8G7NgffVP9s2HnR9DRCwExzRwxlSBmA1bmSyxdTNGX3OWmzpVWERFI/sCS1kBJSGdjlT1pWGi8EWXXTx8tRoAXbCtnXC+uVHXmQVgSKVr4o5CmrySyKgJt9G8ZbuzMvJ5ee4PN1NYUI+ZoeAQ6tA6sJqVtV413HBeunkuRssuDb4/Pra284ApjXOFtx7OZH3XaXPFJEIUIUDhnCnKaLgK0jDrWphixRjWCOzXNKJNIfTLoxxpKgAWq41H//IOqob6OHJgNw/cMojc7KoBgwjkbEEdWQ+aF4luAVZH40m74lOYF3E7qZlycs+OLxx2G4EBzsZNCywBsuKkJU9pODGIEhqmqs+2AAOzngmHaML7CH6lMXRHIeUl3nPIukakXv1HcPv902qdO5Z9gDvHd2Xmn2+gZMPbqIAAiL8CFdQCZYtEaeeTsH6/j127dpK1+/wGmZ46j3U7D2IYDYuoyT56guWrzk7yrujarnEkYP5hPK1HHs8rIxQ4qTRClFx4BnweFaEM6lV6UR7m5zs5AfRAsXaXi4x+MdzeVBBuu/cpKspK+fTdl852Yh4Pn3zxBSmpqXTp0pUePXoSGxtLWGgYcApXkYvCwlOcPn2aPXuy2Lt3Lz6fjylTptKxU22Sbd+W1aSv3kzgsl307JZE506JtE6IIzoqHKfTjuE3KCop42ReIZu2ZbFy9ebqoaeuaYwbPahxLfvEPr4eO+sLthFnCLGa4pSCkkYB4HPWbbMEmDNFeZPTZSbC0yYMm3eEJf0u0hd6PW4++d+/0a5jDwaOmFDFQRRD7jfgLeG3o7uRGHQfr787m7LSs1S1YRhkZm4nM3N70xnLispvLyur4KsN2/lqw9m8lKYQs279rjTF7bdcV2vWXOH2sGffEXp0S6p7JOUrxxaeyEd7KVMKlwb3A6eFhjmvVQPgL+bC5EwQ71DM4yjafX2czNMessLtdceErUp/n3+88CiuIhe3Tp7MwHgPGG6w6BDaAgIigUhGTmxFnyEj+fiTj1i4YAEVFRWN07uaRljY+dR2YlwoAU5HnbPa+oTfLD6KX04dTbcutSmNNWu38cGni2jfNoG7fjWe5vHRta7bd6/BddOKPcfW4jAhFHCgyDFpmANDNaneO10CNp/jln5uGpouC5VJm0BKnX8IWHIwOUFPxnBXEmCmwZGj2bz81v+yc98BWrZqyeN//BOdOzdsJOLxuNm4cSPbt2/j4MGDuFwuiopcFBUX4XA4seg6ERGRxMTE0KplK9onJdGnTx/Cw88PyjyxdDplzTvw7c797Nx9iNzj+ZzMK8Tj8VHuduOw2XA47cRGR9AyIZY+PTrSMak1mna+jUFE2LhpF+//ewFl5RUM7HcFt0wdRXBQAHrZaUJLiuWZVu/965uT7PIL92iKr0VIUhr/WjlWvddgAOpzn66ZktPkDxoM1MTbv4slu/CVHsfbWjTsJSXFzJw5gwUL5xMYGMT9v7ufkSOvreVY+32mE0unY7Tpdlnz9Hi9pC5Yw4Ila9F1nRsnDOP6mCKyp6z75JGvtW+VSXNR3GFzu54ydfutFl/FGwOyImZPu0iYUrUKatDCpUKGqYg1lK3NPl98wsbCwgMDozydZ73/HosXL+Lmm27hl7+8DbvdwQ+bLj/wdpuNKZNGMGxQL979MJ2P5ywl8b67i6Zv1dYhmMB9CmYGFuz5W5Vc39sWap8LuC5bSavW10w1DVJ03Xi+uZzU3ut1MLqirMjqdlcQExPLjyHlL38Hb6uk7+4FhsHx1UvMlGs2PvxNAYUKJogwHgvtwg5vPMyZxac89vB5j/R0NZiOvliaM0UZAid9XpYj+to8M8ox80BEXkhIyI9G+AB253e74plz51LZPPKzF7YUsEmZtBRhLIp3KlfklVwgD+GkR/eYl72tDkuXEQgdxMpC8bIkkPKYvyV9a3YN80b8WAAwDm/kVOEBfCFxlz1v28HNbHWOWPHXwId+rwzaCkxDEeXU6dCUpY8bHZWwcjMrgf4Zo9VhCzxboZzlL+xt7Sv3qYofCwB6dBu00tOXPV/L6aPs8bXe96LzoRcsQjHCDUBXJTzU1HWnGx8WMk2ZArlXp0vL5RPUR6A+P0mUenF7UK78GBZzAFBWxDAuL6gVJRzM9uQ+Ff36g1FjyfDDJNG4EVi1crxKaWq+TYrL0U0+9MMdAA4Lj5mavnOddAualdm0ha8vyU2lrvxyt2NGXL5YYc1TYe7bnXviz60+/E20hy/z0+iJyWMiVFgUt11S3k15aPlEtUtB7OQU0ReNUR6Lg9tNpbs+qehrT93rb/SGCM899yzT/vL0ZRNYac5u/IH1h6aapsniZRvYmrn34v2Jz+vZvuPE8RcTZt4jm1maX4YVxf+KIkaDO2uuFPm9AVBZMmbnORkDsOwalW36uNOv2TxvFg801h4oOtrQbLJ272b16gzatml7eaRvmngqii6soZRi1dqt/Gt2Kn5//R6X5adPFW7a4cqb0fzlu8szgxdkPI0hUaQA3RW8u3K8+vySW1dTH1w5UW3UhGo/71XXq/Wm4n6/2Jh2alTZjv3HsrmIUUNEePmVlwgLC+cXv7jpssi/6Kt3MVt3vSgAv71jIsUlZaTVY//NOXLi6LrsgILprd6cMG9yzKKMaco/NJ3pShgHbKeABy6LervE+eZXyalS7W+yepxaaJg84cMa8MjpycXb9ufn4KufXlq6dDEHDx7g0Uf/gNVqveSPKft2MRWawrRd3JjSumU8/Xp3IW3hGlyus8xxhc9wbco8tn9rcfPD77d9cdTqCWpr1fD7TwoeUIqDaNyacYdy/+AArBivVkBtRnT1RPWxUjzjRwv8Q9ENheuP23dSdKxO8u2tN9+kQ8eODBp06cEaJRvnUOI6ihHXpsHP3HbTaFCK2Z8uwjQxdhdUbFuXWVp8yN593udRT47LGF05qEhOlWkivKAUuUrn4Yyx6jJ5lV0iAABYyTh3obqM8epdBY/4BdsTJ5P5oHTgEk4eEIyzjPes92dRUlrK43/806WNePIPULDoNUrtghEUwp5tAAAGFUlEQVTfuH4kNCSICdcOlm+27OLTpbuzj+Yq+9Ko+6Y+ctd9f1w2RRVNThHb0HR5F8XTqnJ2+4IdLutaOJcMQMYYlaM4P3Bj5XiVqsPvBDyzjrVo9Uf37Z8ZbvGRtx8xDfZk7ebaa68lMbFpgRpSWsDhea+ya+3nFLfqjBnUuOgpQ/DtK2Knpe2V3wQEBvuz9mXvndPmr/3/fWv7DaBkxBcSme9giRLuFDhqKl71CvMWjVGeywnAZaENe88Qa3ASel3bTA1Lky6m8A8NWkY5OfLWAHfXqJzF8Xhd+MJaYLU1LujGvfNLinN3IhaNl+fvYPO2LB6+Zyp9ejXM97/Yy6k9xWp/ToEhTrc3xir+bZ9y3UOLHhxWPXyu2tEpDUgEtuuK9/zC+lXjVb1hkpPXiXPOANwN2vum5uz6cgBQFc5UazY16c31d5tK3a+OblSGxfppSXyv6Hw319y00pH7SPeJ+8e08wy2HvwSXLkQFg22+iMmPftWU3J0J4a3FIlvjdHmiipScjuqAXWo2MupI6VyZF+pPd/qKmtpFSMyFHP9+63/duOKcSoXXqlZYW4Qk1lAMDBfUyzwC0dWjaNO1+wRqRLr0wgpdZHdWOFfNgDqVBGailPCFSgQ3XFUabwlgssPo17eSvS8w/aFL/Yd2zPCQTzHt4DrEHiLICwebEF49iynJGcvhq8EiWuF0bJhsV0iSsp8RmF+hco/WqEV5FQEFIeUF7XSff6wEMo1V0DCix9FPTC3chn6s04BoxZLhMfD6wK3AB4NnhfIFsEV42b5ucIdtVji3T76i5/M1RNUk3dw/X428xTApLmC40pYampcta+ITpOXU9E1gmVjE3odbxbbKzTMSnRwwdfxLH0lzlecazWtNt0SGIy3yivaFIVflN8veH2GuCt8ZoAgjv2FnoPuE/qJ0369zFviDQ7weqNElNUUPTpez7PkWdu/lt7s7qUZ33KMB5QJD57L8I7xeJlJ5RI8ezTFg6aQgOC3eFhSM8Z3SJokaopRHi85MW7SGuJ89Z33AXWlsW+va25VeksA5fcf87W6Kr9IiNUgVkFzEwYqoYdSJImiWAmrlWKbSG3/pK5Fa1t1KF07yO4rDfbruq5M06LhtyKK/VnbA0+dyHW069anMDK2ebkhyuO3Bm/7Kvz6uSedrY7iI+fMHmF1qo8vJNLQmY7iFgBRvKdrPGOYDFeg42Vxxg0qh2miDe3JUKUxVAnfSjCpGfUs7/OjAaAhaViqdFBWhpsmvUUYqIQSEZYpja+ViWmCXemV1iUBQ4zKEF8d/GiUmVBuMSnzaVSIjiuutGHugANSxOmw84Ao/h8QjuKAMnlI9/CVz8F4FA5lshIbfs3HOEORAKzvcIz5My/zDqw/+FaGk1NEL7TTxdRJEJP2UrmXZJgSFioL86PK2HSpzfwslS7a0J7coBR/qxrhVCC8FHpqawp+6eBxxPT1RLQoEUFTQrypOGwoPv9qbP3b4/7kAagBhC3PQXdlEmqCTdO5AhihBBuQgcY63c6GZdeooqYIflgvxgk8D3Sp6pVSLRq/17yU2gp3vWLxlvxSlGYUt7hyughzko6zeeb3sN/wj2472+SVYtErSPL7aC46OVYDq0+nj2bSTaCzUvgQdgBZunDEp5FjmJw4d3MdgIGpEmxT3GTCQwo6V53erjRWmIIPE4umKA3M29XO4i25GVT5vPv6BX6f3/sj3lFb1NXpJPhMOugKwzQ4yHZyPP0JsfvoDMQBsUqIEUUMEKZMSkRRpiBUoBuKrggOQFDsBP5jGqywKg4sn6CqvZcnvLOhsyZcIeCbd2//z38G4Jw0eqHYywxaIiRoGprh51iQjZyadthRiyXC42USMFVghKrc9rZQwQcoZmTUWMHqx5R+EgCcq6KC927/H01840CzidKDyyMSC3yOkK7KxFr1RZsVzAxSfJR+EXfLnwFoQprw1oZ/KqiOdyqN6ojfGbobWAUs1032+gTBxG+zUuaHcpuNitAi3HMmYzaFMviukoX/ghRQevz2tClhs3+KZdf+GwDQvUXHfqpl/2m2AI23BBZW61G/2vJTBeD/A62herFIRO47AAAAAElFTkSuQmCC);background-size:96px 96px}#home .footer{display:none}}@media screen and (min-width:768px) and (max-width:991px){#home .logo{height:144px;background-image:url(../img/logo_144px.png);background-size:144px 144px}#home .button{max-width:350px;margin-top:20px}}@media screen and (min-width:992px){#home .logo{height:200px;background-image:url(../img/logo_200px.png);background-size:200px 200px}#home .button{max-width:350px;margin-top:20px}}@media screen and (min-width:992px){.circle-bg-dark{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA1MDAgNTAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOmJ4PSJodHRwczovL2JveHktc3ZnLmNvbSI+CiAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoMC42MDgyNjEsIDAsIDAsIDAuNjA4MjYxLCAtMjAuMDg0OTc2LCAzLjI1NTczNikiPgogICAgPGc+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC43ODsiIGlkPSJwYXRoLTEwIiBkPSJNIDQxOS4xMzMgODUuNzM4IEMgNDE3LjI5NSA4NS43MzkgNDE1LjQ1NSA4NS43NTQgNDEzLjYxMSA4NS43NzggQyAzNTQuODUyIDg2LjU2MSAyOTkuMDIzIDk5LjE3NCAyNDguMzU4IDEyMS4zMiBDIDU4NC4xMjEgMTMuMjA2IDc5Ni4xNzUgMjExLjI2IDgzMS43IDUwOC43NzMgTCA4NDYuMzgzIDUwNy4xMjQgQyA4MTUuNTg2IDIzNS44MDEgNjUyLjQ3NyA4NS41ODggNDE5LjEzMyA4NS43MzggWiIgdHJhbnNmb3JtPSJtYXRyaXgoMC45NjM3MywgMC4yNjY4NzgsIC0wLjI2Njg3OCwgMC45NjM3MywgODkuNTA1MjMxLCAtMTM2LjYxNTA2MSkiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDE7IiBpZD0icGF0aC0zIiBkPSJNIDE0Ni4wMzcgMTk0LjA2NSBDIDE0NC4yMDEgMTk0LjA2NiAxNDIuMzYxIDE5NC4wODEgMTQwLjUxNyAxOTQuMTA0IEMgODEuNzYgMTk0Ljg4OCAyNS45MzEgMjA3LjUwMyAtMjQuNzM2IDIyOS42NDggQyAzMTEuMDI5IDEyMS41MzEgNTIzLjA4MyAzMTkuNTgzIDU1OC42MDQgNjE3LjA5MyBMIDU3My4yODQgNjE1LjQ0MyBDIDU0Mi40OSAzNDQuMTIyIDM3OS4zODUgMTkzLjkxMyAxNDYuMDM3IDE5NC4wNjUgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuMTgwOTg4LCAtMC45ODM0ODUsIDAuOTgzNDg1LCAtMC4xODA5ODgsIC0zOS4yOTg1ODEsIDcwNS44OTc1NDQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMSIgZD0iTSA0ODcuNzQ0IDE5My4wODQgQyA0ODUuOTA2IDE5My4wODUgNDg0LjA2NyAxOTMuMSA0ODIuMjIzIDE5My4xMjMgQyA0MjMuNDY0IDE5My45MDcgMzY3LjYzNSAyMDYuNTIgMzE2Ljk3NSAyMjguNjY4IEMgNjUyLjcyNiAxMjAuNTUyIDg2NC43NzUgMzE4LjYwNSA5MDAuMjk5IDYxNi4xMDkgTCA5MTQuOTc5IDYxNC40NiBDIDg4NC4xODQgMzQzLjE0NCA3MjEuMDgxIDE5Mi45MzUgNDg3Ljc0NCAxOTMuMDg0IFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNjE5OTk3LCAwLjc4NDYwNSwgLTAuNzg0NjA1LCAwLjYxOTk5NywgNTIzLjA2NzIzMSwgLTM0My4zMzE1MzkpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjg0OyIgaWQ9InBhdGgtMTIiIGQ9Ik0gMjk1Ljk2OSA0MzIuNzU3IEMgMjk0LjEzMSA0MzIuNzU4IDI5Mi4yOTMgNDMyLjc3MyAyOTAuNDQ5IDQzMi43OTcgQyAyMzEuNjg4IDQzMy41OCAxNzUuODYgNDQ2LjE5NCAxMjUuMTk4IDQ2OC4zNDEgQyA0NjAuOTU3IDM2MC4yMjYgNjczLjAwNSA1NTguMjggNzA4LjUyNiA4NTUuNzg2IEwgNzIzLjIwNyA4NTQuMTM5IEMgNjkyLjQxMiA1ODIuODE5IDUyOS4zMSA0MzIuNjA5IDI5NS45NjkgNDMyLjc1NyBaIiB0cmFuc2Zvcm09Im1hdHJpeCgtMC45Nzg4NDksIDAuMjA0NTg0LCAtMC4yMDQ1ODQsIC0wLjk3ODg0OSwgOTYzLjgyMDc5NiwgMTExNi4zNjcyOTMpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMyIgZD0iTSAxNTguMDM2IDE0OC44MyBDIDE1Ni4yIDE0OC44MzMgMTU0LjM2IDE0OC44NDYgMTUyLjUxNiAxNDguODcyIEMgOTMuNzU5IDE0OS42NTMgMzcuOTMgMTYyLjI2NyAtMTIuNzM0IDE4NC40MTEgQyAzMjMuMDIyIDc2LjMwMSA1MzUuMDc2IDI3NC4zNTIgNTcwLjYwNCA1NzEuODU3IEwgNTg1LjI4NiA1NzAuMjA4IEMgNTU0LjQ4MyAyOTguODkxIDM5MS4zOCAxNDguNjgzIDE1OC4wMzYgMTQ4LjgzIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuMzM4NjE0LCAtMC45NDA5MjYsIDAuOTQwOTI2LCAwLjMzODYxNCwgLTExNS41OTUxNTgsIDQ4My43MDU5ODQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAxOyIgaWQ9InBhdGgtMTQiIGQ9Ik0gNTAxLjAxOSAyODguMjkyIEMgNDk5LjE4MSAyODguMjkzIDQ5Ny4zNCAyODguMzA4IDQ5NS40OTYgMjg4LjMzMSBDIDQzNi43MzYgMjg5LjExNSAzODAuOTA4IDMwMS43MjYgMzMwLjI0MyAzMjMuODc0IEMgNjY2LjAwNCAyMTUuNzU3IDg3OC4wNjIgNDEzLjgxMiA5MTMuNTg2IDcxMS4zMjIgTCA5MjguMjY4IDcwOS42NzMgQyA4OTcuNDY4IDQzOC4zNTIgNzM0LjM2MSAyODguMTQxIDUwMS4wMTkgMjg4LjI5MiBaIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjE2NDY1NiwgMC45ODYzNTEsIC0wLjk4NjM1MSwgMC4xNjQ2NTYsIDk4Mi44NTcyNjYsIC0yMzMuNDUyMDYzKSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC40OyIgaWQ9InBhdGgtMTUiIGQ9Ik0gMTkyLjk1NCAzNzYuNTIxIEMgMTkxLjExNSAzNzYuNTIyIDE4OS4yNzcgMzc2LjUzNyAxODcuNDMzIDM3Ni41NjEgQyAxMjguNjc0IDM3Ny4zNDQgNzIuODQ1IDM4OS45NTggMjIuMTgxIDQxMi4xMDMgQyAzNTcuOTQgMzAzLjk4OSA1NjkuOTg3IDUwMi4wNDUgNjA1LjUwNSA3OTkuNTUzIEwgNjIwLjE4OCA3OTcuOTA1IEMgNTg5LjM5MiA1MjYuNTg0IDQyNi4yOTUgMzc2LjM2OSAxOTIuOTU0IDM3Ni41MjEgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuOTMxNDA0LCAtMC4zNjM5ODgsIDAuMzYzOTg4LCAtMC45MzE0MDQsIDQxOS40OTkwMDYsIDExODIuNTk5ODA5KSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMTsiIGlkPSJwYXRoLTE2IiBkPSJNIDIyMS42MTQgNjMuOTczIEMgMjE5Ljc3NyA2My45NzYgMjE3LjkzOCA2My45OSAyMTYuMDk0IDY0LjAxNSBDIDE1Ny4zMzQgNjQuNzk1IDEwMS41MDYgNzcuNDA5IDUwLjg0MSA5OS41NTQgQyAzODYuNTk4IC04LjU1OSA1OTguNjUxIDE4OS40OTcgNjM0LjE3MyA0ODcuMDAxIEwgNjQ4Ljg1NCA0ODUuMzU0IEMgNjE4LjA1OCAyMTQuMDM3IDQ1NC45NTQgNjMuODI0IDIyMS42MTQgNjMuOTczIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNzUwNDUyLCAtMC42NjA5MjUsIDAuNjYwOTI1LCAwLjc1MDQ1MiwgLTcwLjgwMzMyMiwgMjkwLjkyMDI3MykiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDAuNDsiIGlkPSJwYXRoLTE3IiBkPSJNIDQ0MS44ODggMzQyLjA5OCBDIDQ0MC4wNDcgMzQyLjA5OCA0MzguMjA3IDM0Mi4xMTQgNDM2LjM2MiAzNDIuMTM4IEMgMzc3LjYwMSAzNDIuOTIyIDMyMS43NjUgMzU1LjUzNSAyNzEuMTAzIDM3Ny42ODEgQyA2MDYuODg2IDI2OS41NjcgODE4Ljk0NCA0NjcuNjE1IDg1NC40NjIgNzY1LjEzMyBMIDg2OS4xNDIgNzYzLjQ4MyBDIDgzOC4zNTQgNDkyLjE1NCA2NzUuMjQyIDM0MS45NDggNDQxLjg4OCAzNDIuMDk4IFoiIHRyYW5zZm9ybT0ibWF0cml4KC0wLjM1NjU4MiwgMC45MzQyNjQsIC0wLjkzNDI2NCwgLTAuMzU2NTgyLCAxMjU2Ljc1OTQ5MywgMTY5LjE4MjU1MikiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgwLjc2MjQ5MywgMCwgMCwgMC43NjI0OTMsIDE5LjI5NDY0NywgLTcxNi4zMjI4MTUpIj4KICAgICAgICA8cGF0aCBkPSJNIDU2Ni40NjYgMTA4OS4xMzcgTCA1NjYuNDY2IDExNDguMjIyIEMgNTY1Ljg2NyAxMTQ4LjIxOSA1NjUuMjY3IDExNDguMjE3IDU2NC42NjcgMTE0OC4yMTcgQyA1NjEuNDgxIDExNDguMjE3IDU1OC4zMSAxMTQ4LjI1OSA1NTUuMTU0IDExNDguMzQxIEwgNTU1LjE1NCAxMDg5LjEzNyBaIE0gOTA4LjI5IDE0NzcuMTQ2IEwgOTU2Ljk4NyAxNDc3LjE0NiBMIDk1Ni45ODcgMTQ4OC40NTggTCA5MDguNTY5IDE0ODguNDU4IEMgOTA4LjUzOSAxNDg0LjY5MyA5MDguNDQ3IDE0ODAuOTIyIDkwOC4yOSAxNDc3LjE0NiBaIE0gNTY2LjQ2NiAxODM1LjAxMyBMIDU2Ni40NjYgMTg3Ni40NjcgTCA1NTUuMTU0IDE4NzYuNDY3IEwgNTU1LjE1NCAxODM0Ljg4NiBDIDU1OC4zMTggMTgzNC45NzMgNTYxLjQ5IDE4MzUuMDE3IDU2NC42NjcgMTgzNS4wMTcgQyA1NjUuMjY3IDE4MzUuMDE3IDU2NS44NjcgMTgzNS4wMTYgNTY2LjQ2NiAxODM1LjAxMyBaIE0gMjIwLjc3NSAxNDg4LjQ1OCBMIDE2OS42NTcgMTQ4OC40NTggTCAxNjkuNjU3IDE0NzcuMTQ2IEwgMjIxLjA4OSAxNDc3LjE0NiBDIDIyMC45MjEgMTQ4MC45MDkgMjIwLjgxNiAxNDg0LjY4IDIyMC43NzUgMTQ4OC40NTggWiIgc3R5bGU9ImZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgc3Ryb2tlOiBub25lOyIgYng6b3JpZ2luPSIwIDAiLz4KICAgICAgICA8cGF0aCBkPSJNIDc2MC4xMjEgMTE0My4zMTEgTCA3MTcuMzM2IDEyMTcuNDE3IEMgNzE1LjcyIDEyMTYuNTE4IDcxNC4wOTYgMTIxNS42MzIgNzEyLjQ2NSAxMjE0Ljc2MSBMIDc1NS4zMTggMTE0MC41MzcgWiBNIDgzMC4xMjIgMTMyNC4yMDMgTCA5MDAuNDI0IDEyODMuNjE0IEwgOTAzLjE5OCAxMjg4LjQxNyBMIDgzMy4wNCAxMzI4LjkyMyBDIDgzMi4wOCAxMzI3LjMzOSA4MzEuMTA3IDEzMjUuNzY2IDgzMC4xMjIgMTMyNC4yMDMgWiBNIDg0MC41OTkgMTY0MS4xMzcgTCA5MDMuMTk3IDE2NzcuMjc4IEwgOTAwLjQyNCAxNjgyLjA4MiBMIDgzNy45MTEgMTY0NS45OSBDIDgzOC44MjEgMTY0NC4zOCA4MzkuNzE3IDE2NDIuNzYyIDg0MC41OTkgMTY0MS4xMzcgWiBNIDcyNS4xNjggMTc2MS44NDMgTCA3NjAuMTIyIDE4MjIuMzg1IEwgNzU1LjMxOCAxODI1LjE1OCBMIDcyMC4zNzkgMTc2NC42NDEgQyA3MjEuOTg1IDE3NjMuNzIyIDcyMy41ODIgMTc2Mi43ODkgNzI1LjE2OCAxNzYxLjg0MyBaIE0gNDAzLjUzOCAxNzYwLjkzMiBMIDM2Ni40NTYgMTgyNS4xNTkgTCAzNjEuNjUzIDE4MjIuMzg2IEwgMzk4LjgwMiAxNzU4LjA0MiBDIDQwMC4zNzIgMTc1OS4wMTkgNDAxLjk1MSAxNzU5Ljk4MiA0MDMuNTM4IDE3NjAuOTMyIFogTSAyODkuNTggMTY0Mi42ODkgTCAyMjEuMzUgMTY4Mi4wODIgTCAyMTguNTc3IDE2NzcuMjc5IEwgMjg2Ljk0NCAxNjM3LjgwNyBDIDI4Ny44MDcgMTYzOS40MzcgMjg4LjY4NSAxNjQxLjA2NSAyODkuNTggMTY0Mi42ODkgWiBNIDI5NC4zNTQgMTMzMi4xNjggTCAyMTguNTc2IDEyODguNDE3IEwgMjIxLjM1IDEyODMuNjE0IEwgMjk3LjIxMyAxMzI3LjQxNCBDIDI5Ni4yNDYgMTMyOC45OSAyOTUuMjkzIDEzMzAuNTc1IDI5NC4zNTQgMTMzMi4xNjggWiBNIDQwNi4wNzkgMTIyMC4yNTkgTCAzNjEuNjUzIDExNDMuMzExIEwgMzY2LjQ1NyAxMTQwLjUzNyBMIDQxMC44ODkgMTIxNy40OTUgQyA0MDkuMjc2IDEyMTguNDAzIDQwNy42NzMgMTIxOS4zMjQgNDA2LjA3OSAxMjIwLjI1OSBaIiBzdHlsZT0iZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IG5vbmU7IiBieDpvcmlnaW49IjAgMCIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8cmVjdCB4PSI0MjkuMzY3IiB5PSI0MjUuOTc5IiB3aWR0aD0iMjAuMDAzIiBoZWlnaHQ9IjIxLjczNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTkxIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAwLjk5OTk5OSwgLTMwMS4zNzcwNzUsIC0yMTkuNDk4NDM0KSIvPgogICAgPHJlY3QgeD0iNDQ2Ljg1MyIgeT0iMjUuNDYyIiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05MyIvPgogICAgPHJlY3QgeD0iLTEzNS45NTYiIHk9IjYwNS4xNDEiIHdpZHRoPSIzOS44NTEiIGhlaWdodD0iMzkuODUxIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTQiIHRyYW5zZm9ybT0ibWF0cml4KDAuOTk5OTk5LCAwLCAwLCAxLCA4NDYuMTc2NzU2LCAtMzk0Ljk1NjAyNCkiLz4KICAgIDxyZWN0IHg9IjIyNS43NzkiIHk9IjY4OS44MzYiIHdpZHRoPSIyNS45OSIgaGVpZ2h0PSIyNS45OSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk1Ii8+CiAgICA8cmVjdCB4PSI1OTQuMDEzIiB5PSI3MzcuMTQyIiB3aWR0aD0iMjAuNzkyIiBoZWlnaHQ9IjIyLjUyNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk2Ii8+CiAgICA8cmVjdCB4PSIzODcuMjM1IiB5PSI0NzkuMzk3IiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05OCIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMDAwMDEsIDAsIDAsIDAuOTk5OTk5LCAzNjUuMjc0OTY2LCA3OS4yOTUyNDEpIi8+CiAgICA8cmVjdCB4PSI0MjEuOTYyIiB5PSI3NzUuOTM3IiB3aWR0aD0iMzIuOTIiIGhlaWdodD0iMzQuNjUzIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTkiLz4KICAgIDxyZWN0IHg9Ii02Ni45MzkiIHk9Ii01NjguOTc4IiB3aWR0aD0iMjAuODY3IiBoZWlnaHQ9IjIwLjc5MiIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTEwMSIgdHJhbnNmb3JtPSJtYXRyaXgoLTEsIDAsIDAsIDAuOTk5OTk3LCAzMS4zNTY5MjgsIDk4NC43MzYzMDYpIi8+CiAgPC9nPgo8L3N2Zz4=);background-repeat:no-repeat;background-position:-725px -145px;background-size:1024px 1024px}.menu.menu-left{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA1MDAgNTAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOmJ4PSJodHRwczovL2JveHktc3ZnLmNvbSI+CiAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoMC42MDgyNjEsIDAsIDAsIDAuNjA4MjYxLCAtMjAuMDg0OTc2LCAzLjI1NTczNikiPgogICAgPGc+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC43ODsiIGlkPSJwYXRoLTEwIiBkPSJNIDQxOS4xMzMgODUuNzM4IEMgNDE3LjI5NSA4NS43MzkgNDE1LjQ1NSA4NS43NTQgNDEzLjYxMSA4NS43NzggQyAzNTQuODUyIDg2LjU2MSAyOTkuMDIzIDk5LjE3NCAyNDguMzU4IDEyMS4zMiBDIDU4NC4xMjEgMTMuMjA2IDc5Ni4xNzUgMjExLjI2IDgzMS43IDUwOC43NzMgTCA4NDYuMzgzIDUwNy4xMjQgQyA4MTUuNTg2IDIzNS44MDEgNjUyLjQ3NyA4NS41ODggNDE5LjEzMyA4NS43MzggWiIgdHJhbnNmb3JtPSJtYXRyaXgoMC45NjM3MywgMC4yNjY4NzgsIC0wLjI2Njg3OCwgMC45NjM3MywgODkuNTA1MjMxLCAtMTM2LjYxNTA2MSkiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDE7IiBpZD0icGF0aC0zIiBkPSJNIDE0Ni4wMzcgMTk0LjA2NSBDIDE0NC4yMDEgMTk0LjA2NiAxNDIuMzYxIDE5NC4wODEgMTQwLjUxNyAxOTQuMTA0IEMgODEuNzYgMTk0Ljg4OCAyNS45MzEgMjA3LjUwMyAtMjQuNzM2IDIyOS42NDggQyAzMTEuMDI5IDEyMS41MzEgNTIzLjA4MyAzMTkuNTgzIDU1OC42MDQgNjE3LjA5MyBMIDU3My4yODQgNjE1LjQ0MyBDIDU0Mi40OSAzNDQuMTIyIDM3OS4zODUgMTkzLjkxMyAxNDYuMDM3IDE5NC4wNjUgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuMTgwOTg4LCAtMC45ODM0ODUsIDAuOTgzNDg1LCAtMC4xODA5ODgsIC0zOS4yOTg1ODEsIDcwNS44OTc1NDQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMSIgZD0iTSA0ODcuNzQ0IDE5My4wODQgQyA0ODUuOTA2IDE5My4wODUgNDg0LjA2NyAxOTMuMSA0ODIuMjIzIDE5My4xMjMgQyA0MjMuNDY0IDE5My45MDcgMzY3LjYzNSAyMDYuNTIgMzE2Ljk3NSAyMjguNjY4IEMgNjUyLjcyNiAxMjAuNTUyIDg2NC43NzUgMzE4LjYwNSA5MDAuMjk5IDYxNi4xMDkgTCA5MTQuOTc5IDYxNC40NiBDIDg4NC4xODQgMzQzLjE0NCA3MjEuMDgxIDE5Mi45MzUgNDg3Ljc0NCAxOTMuMDg0IFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNjE5OTk3LCAwLjc4NDYwNSwgLTAuNzg0NjA1LCAwLjYxOTk5NywgNTIzLjA2NzIzMSwgLTM0My4zMzE1MzkpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjg0OyIgaWQ9InBhdGgtMTIiIGQ9Ik0gMjk1Ljk2OSA0MzIuNzU3IEMgMjk0LjEzMSA0MzIuNzU4IDI5Mi4yOTMgNDMyLjc3MyAyOTAuNDQ5IDQzMi43OTcgQyAyMzEuNjg4IDQzMy41OCAxNzUuODYgNDQ2LjE5NCAxMjUuMTk4IDQ2OC4zNDEgQyA0NjAuOTU3IDM2MC4yMjYgNjczLjAwNSA1NTguMjggNzA4LjUyNiA4NTUuNzg2IEwgNzIzLjIwNyA4NTQuMTM5IEMgNjkyLjQxMiA1ODIuODE5IDUyOS4zMSA0MzIuNjA5IDI5NS45NjkgNDMyLjc1NyBaIiB0cmFuc2Zvcm09Im1hdHJpeCgtMC45Nzg4NDksIDAuMjA0NTg0LCAtMC4yMDQ1ODQsIC0wLjk3ODg0OSwgOTYzLjgyMDc5NiwgMTExNi4zNjcyOTMpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMyIgZD0iTSAxNTguMDM2IDE0OC44MyBDIDE1Ni4yIDE0OC44MzMgMTU0LjM2IDE0OC44NDYgMTUyLjUxNiAxNDguODcyIEMgOTMuNzU5IDE0OS42NTMgMzcuOTMgMTYyLjI2NyAtMTIuNzM0IDE4NC40MTEgQyAzMjMuMDIyIDc2LjMwMSA1MzUuMDc2IDI3NC4zNTIgNTcwLjYwNCA1NzEuODU3IEwgNTg1LjI4NiA1NzAuMjA4IEMgNTU0LjQ4MyAyOTguODkxIDM5MS4zOCAxNDguNjgzIDE1OC4wMzYgMTQ4LjgzIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuMzM4NjE0LCAtMC45NDA5MjYsIDAuOTQwOTI2LCAwLjMzODYxNCwgLTExNS41OTUxNTgsIDQ4My43MDU5ODQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAxOyIgaWQ9InBhdGgtMTQiIGQ9Ik0gNTAxLjAxOSAyODguMjkyIEMgNDk5LjE4MSAyODguMjkzIDQ5Ny4zNCAyODguMzA4IDQ5NS40OTYgMjg4LjMzMSBDIDQzNi43MzYgMjg5LjExNSAzODAuOTA4IDMwMS43MjYgMzMwLjI0MyAzMjMuODc0IEMgNjY2LjAwNCAyMTUuNzU3IDg3OC4wNjIgNDEzLjgxMiA5MTMuNTg2IDcxMS4zMjIgTCA5MjguMjY4IDcwOS42NzMgQyA4OTcuNDY4IDQzOC4zNTIgNzM0LjM2MSAyODguMTQxIDUwMS4wMTkgMjg4LjI5MiBaIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjE2NDY1NiwgMC45ODYzNTEsIC0wLjk4NjM1MSwgMC4xNjQ2NTYsIDk4Mi44NTcyNjYsIC0yMzMuNDUyMDYzKSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC40OyIgaWQ9InBhdGgtMTUiIGQ9Ik0gMTkyLjk1NCAzNzYuNTIxIEMgMTkxLjExNSAzNzYuNTIyIDE4OS4yNzcgMzc2LjUzNyAxODcuNDMzIDM3Ni41NjEgQyAxMjguNjc0IDM3Ny4zNDQgNzIuODQ1IDM4OS45NTggMjIuMTgxIDQxMi4xMDMgQyAzNTcuOTQgMzAzLjk4OSA1NjkuOTg3IDUwMi4wNDUgNjA1LjUwNSA3OTkuNTUzIEwgNjIwLjE4OCA3OTcuOTA1IEMgNTg5LjM5MiA1MjYuNTg0IDQyNi4yOTUgMzc2LjM2OSAxOTIuOTU0IDM3Ni41MjEgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuOTMxNDA0LCAtMC4zNjM5ODgsIDAuMzYzOTg4LCAtMC45MzE0MDQsIDQxOS40OTkwMDYsIDExODIuNTk5ODA5KSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMTsiIGlkPSJwYXRoLTE2IiBkPSJNIDIyMS42MTQgNjMuOTczIEMgMjE5Ljc3NyA2My45NzYgMjE3LjkzOCA2My45OSAyMTYuMDk0IDY0LjAxNSBDIDE1Ny4zMzQgNjQuNzk1IDEwMS41MDYgNzcuNDA5IDUwLjg0MSA5OS41NTQgQyAzODYuNTk4IC04LjU1OSA1OTguNjUxIDE4OS40OTcgNjM0LjE3MyA0ODcuMDAxIEwgNjQ4Ljg1NCA0ODUuMzU0IEMgNjE4LjA1OCAyMTQuMDM3IDQ1NC45NTQgNjMuODI0IDIyMS42MTQgNjMuOTczIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNzUwNDUyLCAtMC42NjA5MjUsIDAuNjYwOTI1LCAwLjc1MDQ1MiwgLTcwLjgwMzMyMiwgMjkwLjkyMDI3MykiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDAuNDsiIGlkPSJwYXRoLTE3IiBkPSJNIDQ0MS44ODggMzQyLjA5OCBDIDQ0MC4wNDcgMzQyLjA5OCA0MzguMjA3IDM0Mi4xMTQgNDM2LjM2MiAzNDIuMTM4IEMgMzc3LjYwMSAzNDIuOTIyIDMyMS43NjUgMzU1LjUzNSAyNzEuMTAzIDM3Ny42ODEgQyA2MDYuODg2IDI2OS41NjcgODE4Ljk0NCA0NjcuNjE1IDg1NC40NjIgNzY1LjEzMyBMIDg2OS4xNDIgNzYzLjQ4MyBDIDgzOC4zNTQgNDkyLjE1NCA2NzUuMjQyIDM0MS45NDggNDQxLjg4OCAzNDIuMDk4IFoiIHRyYW5zZm9ybT0ibWF0cml4KC0wLjM1NjU4MiwgMC45MzQyNjQsIC0wLjkzNDI2NCwgLTAuMzU2NTgyLCAxMjU2Ljc1OTQ5MywgMTY5LjE4MjU1MikiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgwLjc2MjQ5MywgMCwgMCwgMC43NjI0OTMsIDE5LjI5NDY0NywgLTcxNi4zMjI4MTUpIj4KICAgICAgICA8cGF0aCBkPSJNIDU2Ni40NjYgMTA4OS4xMzcgTCA1NjYuNDY2IDExNDguMjIyIEMgNTY1Ljg2NyAxMTQ4LjIxOSA1NjUuMjY3IDExNDguMjE3IDU2NC42NjcgMTE0OC4yMTcgQyA1NjEuNDgxIDExNDguMjE3IDU1OC4zMSAxMTQ4LjI1OSA1NTUuMTU0IDExNDguMzQxIEwgNTU1LjE1NCAxMDg5LjEzNyBaIE0gOTA4LjI5IDE0NzcuMTQ2IEwgOTU2Ljk4NyAxNDc3LjE0NiBMIDk1Ni45ODcgMTQ4OC40NTggTCA5MDguNTY5IDE0ODguNDU4IEMgOTA4LjUzOSAxNDg0LjY5MyA5MDguNDQ3IDE0ODAuOTIyIDkwOC4yOSAxNDc3LjE0NiBaIE0gNTY2LjQ2NiAxODM1LjAxMyBMIDU2Ni40NjYgMTg3Ni40NjcgTCA1NTUuMTU0IDE4NzYuNDY3IEwgNTU1LjE1NCAxODM0Ljg4NiBDIDU1OC4zMTggMTgzNC45NzMgNTYxLjQ5IDE4MzUuMDE3IDU2NC42NjcgMTgzNS4wMTcgQyA1NjUuMjY3IDE4MzUuMDE3IDU2NS44NjcgMTgzNS4wMTYgNTY2LjQ2NiAxODM1LjAxMyBaIE0gMjIwLjc3NSAxNDg4LjQ1OCBMIDE2OS42NTcgMTQ4OC40NTggTCAxNjkuNjU3IDE0NzcuMTQ2IEwgMjIxLjA4OSAxNDc3LjE0NiBDIDIyMC45MjEgMTQ4MC45MDkgMjIwLjgxNiAxNDg0LjY4IDIyMC43NzUgMTQ4OC40NTggWiIgc3R5bGU9ImZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgc3Ryb2tlOiBub25lOyIgYng6b3JpZ2luPSIwIDAiLz4KICAgICAgICA8cGF0aCBkPSJNIDc2MC4xMjEgMTE0My4zMTEgTCA3MTcuMzM2IDEyMTcuNDE3IEMgNzE1LjcyIDEyMTYuNTE4IDcxNC4wOTYgMTIxNS42MzIgNzEyLjQ2NSAxMjE0Ljc2MSBMIDc1NS4zMTggMTE0MC41MzcgWiBNIDgzMC4xMjIgMTMyNC4yMDMgTCA5MDAuNDI0IDEyODMuNjE0IEwgOTAzLjE5OCAxMjg4LjQxNyBMIDgzMy4wNCAxMzI4LjkyMyBDIDgzMi4wOCAxMzI3LjMzOSA4MzEuMTA3IDEzMjUuNzY2IDgzMC4xMjIgMTMyNC4yMDMgWiBNIDg0MC41OTkgMTY0MS4xMzcgTCA5MDMuMTk3IDE2NzcuMjc4IEwgOTAwLjQyNCAxNjgyLjA4MiBMIDgzNy45MTEgMTY0NS45OSBDIDgzOC44MjEgMTY0NC4zOCA4MzkuNzE3IDE2NDIuNzYyIDg0MC41OTkgMTY0MS4xMzcgWiBNIDcyNS4xNjggMTc2MS44NDMgTCA3NjAuMTIyIDE4MjIuMzg1IEwgNzU1LjMxOCAxODI1LjE1OCBMIDcyMC4zNzkgMTc2NC42NDEgQyA3MjEuOTg1IDE3NjMuNzIyIDcyMy41ODIgMTc2Mi43ODkgNzI1LjE2OCAxNzYxLjg0MyBaIE0gNDAzLjUzOCAxNzYwLjkzMiBMIDM2Ni40NTYgMTgyNS4xNTkgTCAzNjEuNjUzIDE4MjIuMzg2IEwgMzk4LjgwMiAxNzU4LjA0MiBDIDQwMC4zNzIgMTc1OS4wMTkgNDAxLjk1MSAxNzU5Ljk4MiA0MDMuNTM4IDE3NjAuOTMyIFogTSAyODkuNTggMTY0Mi42ODkgTCAyMjEuMzUgMTY4Mi4wODIgTCAyMTguNTc3IDE2NzcuMjc5IEwgMjg2Ljk0NCAxNjM3LjgwNyBDIDI4Ny44MDcgMTYzOS40MzcgMjg4LjY4NSAxNjQxLjA2NSAyODkuNTggMTY0Mi42ODkgWiBNIDI5NC4zNTQgMTMzMi4xNjggTCAyMTguNTc2IDEyODguNDE3IEwgMjIxLjM1IDEyODMuNjE0IEwgMjk3LjIxMyAxMzI3LjQxNCBDIDI5Ni4yNDYgMTMyOC45OSAyOTUuMjkzIDEzMzAuNTc1IDI5NC4zNTQgMTMzMi4xNjggWiBNIDQwNi4wNzkgMTIyMC4yNTkgTCAzNjEuNjUzIDExNDMuMzExIEwgMzY2LjQ1NyAxMTQwLjUzNyBMIDQxMC44ODkgMTIxNy40OTUgQyA0MDkuMjc2IDEyMTguNDAzIDQwNy42NzMgMTIxOS4zMjQgNDA2LjA3OSAxMjIwLjI1OSBaIiBzdHlsZT0iZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IG5vbmU7IiBieDpvcmlnaW49IjAgMCIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8cmVjdCB4PSI0MjkuMzY3IiB5PSI0MjUuOTc5IiB3aWR0aD0iMjAuMDAzIiBoZWlnaHQ9IjIxLjczNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTkxIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAwLjk5OTk5OSwgLTMwMS4zNzcwNzUsIC0yMTkuNDk4NDM0KSIvPgogICAgPHJlY3QgeD0iNDQ2Ljg1MyIgeT0iMjUuNDYyIiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05MyIvPgogICAgPHJlY3QgeD0iLTEzNS45NTYiIHk9IjYwNS4xNDEiIHdpZHRoPSIzOS44NTEiIGhlaWdodD0iMzkuODUxIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTQiIHRyYW5zZm9ybT0ibWF0cml4KDAuOTk5OTk5LCAwLCAwLCAxLCA4NDYuMTc2NzU2LCAtMzk0Ljk1NjAyNCkiLz4KICAgIDxyZWN0IHg9IjIyNS43NzkiIHk9IjY4OS44MzYiIHdpZHRoPSIyNS45OSIgaGVpZ2h0PSIyNS45OSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk1Ii8+CiAgICA8cmVjdCB4PSI1OTQuMDEzIiB5PSI3MzcuMTQyIiB3aWR0aD0iMjAuNzkyIiBoZWlnaHQ9IjIyLjUyNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk2Ii8+CiAgICA8cmVjdCB4PSIzODcuMjM1IiB5PSI0NzkuMzk3IiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05OCIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMDAwMDEsIDAsIDAsIDAuOTk5OTk5LCAzNjUuMjc0OTY2LCA3OS4yOTUyNDEpIi8+CiAgICA8cmVjdCB4PSI0MjEuOTYyIiB5PSI3NzUuOTM3IiB3aWR0aD0iMzIuOTIiIGhlaWdodD0iMzQuNjUzIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTkiLz4KICAgIDxyZWN0IHg9Ii02Ni45MzkiIHk9Ii01NjguOTc4IiB3aWR0aD0iMjAuODY3IiBoZWlnaHQ9IjIwLjc5MiIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTEwMSIgdHJhbnNmb3JtPSJtYXRyaXgoLTEsIDAsIDAsIDAuOTk5OTk3LCAzMS4zNTY5MjgsIDk4NC43MzYzMDYpIi8+CiAgPC9nPgo8L3N2Zz4=);background-repeat:no-repeat;background-position:-500px -100px;background-size:1024px 1024px;background-color:#f5f5f5;height:100%}.menu.menu-left .item.active{background-color:#b2e0ff!important}.menu.menu-left .item.active .item-content{background-color:transparent;opacity:1;color:#000}.menu.menu-left .item{opacity:.75;color:#000}.menu.menu-left .item .item-content{background-color:transparent;opacity:1}.menu.menu-left .item-menu-disable{color:#444!important}}.gray,.popover-helptip .button-close,.popover-share .bar-footer .button-close,.popover-share .bar-header span{color:grey!important}.gray b,.popover-helptip .button-close b,.popover-share .bar-footer .button-close b,.popover-share .bar-header span b{color:grey!important}.gray a,.icon-help a,.popover-helptip .button-close a,.popover-share .bar-footer .button-close a,.popover-share .bar-header span a,.positive a{color:inherit}.gray a:hover,.icon-help a:hover,.popover-helptip .button-close a:hover,.popover-share .bar-footer .button-close a:hover,.popover-share .bar-header span a:hover,.positive a:hover{color:inherit}.gray a:visited,.icon-help a:visited,.popover-helptip .button-close a:visited,.popover-share .bar-footer .button-close a:visited,.popover-share .bar-header span a:visited,.positive a:visited{color:inherit}.item a{text-decoration:none}.no-padding{padding:0!important}.avatar-member{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAQAAABpN6lAAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfgBA0LKSJACf7RAAAFqElEQVR42u2dbUjdZRjGf+c4dTndFnO+TRcD3ZIxdVlJL2PSIHDZBqtRaINojWRrgR8a4fDbIOrzoIKIMay2iGpQsg0y4xRZIk5i1NTaik3TZeRcvmzl0wc7qTPz6Lnv5/kfz/86XzxyuM59Xf/r//o893MCBqtIoYgSSsgjndWkk8RV+v959dFPP9/wm82CAtYM2MCTPMZGgnN87iZNvMdH1mww+q8Es9e0m/nhhjltnjG361enL3+HOT9P8ZMYNC+YhFg2IN2cWbD4MNrN3bFqQIm5FLV8Y4wZMbtj0YBdZlhEvjHGjJsXY82A+8yomPwJ1OhUqnMazKOVTGHOUe7lW/lS5zorLwSJnBKXD0s5SUpsGHCAzQqsUMgr8qTyu8AqulmpYgCMcQd9spTyCahTkw/JHJCmlE5AIj2kqxkAA6xlWJJQOgEVqvJhFY/LEkobUKUqH2Cbtw0oVTdgqyyd7DEgiWES1C1YxyU5MtkEFFiQD/dLkskacKcF+ZAb7waIXmbHogEZ3jVANJyxaEDAigHJ8W6AKDRuh2MKfgJcF+AafgJ8A+IcfgJcF+AafgJcF+AafgJE2URvU2aFqM2SzwSXM8ASCwaMkc9lKTLJBNRbkQ/JvCRHJpeANPpZasUAuEa21PiQXAJ2WJMPy9ktRSVnwBPW5IPgCJScAXdZNSDHewbcsGpAmvcMGLVqgNhkGTkDfrVqQLv3DHjfqgGnpYjkrgMyuGLpQgigkO9liOQS0M+H1uS/JSVf9l5gBV9RaEH+TxRxTYpM8l5gkEcZUJc/zB45+dK3wz9QhW4LiuERQpKE0k+EzvKuqgENNMsSyj8SO6lqwFFpQvmpskv4kTwl+e3ydxzyCfhTfiv9i9flKTX6BVZymWUK8ofI4bo0qcZj8d85psAKDfLytRonC7ig8Ii8hA75UnUGRrr4RJyzRUO+3sjQq8J8hjqdQrUMCAkfsV/jM51C9Zqnl3GOfCGuixRpHABBc3D0D/bwlwiTYa+WfN3R4RZeFuFRiz9orx+QSEvUF6+K8Qft+QE3eSpqDsX4g40VJKL9AuU5B/4MEdcFuIZvgOsCXEPbgFQPMDg1INsDDL4BLg2IfqRIeaxJ24CdHmD4X+heCaZxNerJk2OsZkivRN0EVAvMHU2mWrNEzQSk0C1yCOslX3bViKnQTECt0BE8m1q9IvUSUEaz2NTJUcr5OrYMyKWVLEG+X7hHboL0VOjsArk0isqHLBp1WrM1DCijlU3irJtopcz7BqRwmGbhrR9GFs0cFl9PTHBpujRTY3qEF9GbiR5TY9K8tJxeKtlkU8hOHrLUMgNjNHGK7+ilN9pHpvMxYAXVPKu0Upwc2nmTtxmM+PMRRiXB7DcD6vGWwoDZH+lqtJEl4EGOUux6084THTzPF3N/bO6zQA4NhGJOPhQToiGCxoo5InLQDLnOc1QYMgcXvgsk8QZPu96QAjjGc7P3s8xuQAYf8IDr2oXwJbvon58BG2lkreu6BfEz2zkfuQEb+FxhYVy36GMrFyIzYB0h1riuVwFX2MLFW/858zSYR9OilA9raJo5i/nWBGQSosB1pYroYsv0lYmnJyDIiUUtHwo4MV3zdAPqKXddoTrKqZ/6duouUM6ncTFcPs62yb6TSQPS6ZBrSfY4eigOd7qGt3iA43EjH3I4Hp58FTZgHxWuq7KKCvZN/DGxC6TSveiu/OZCH/lcDyfgUNzJh0wOwUQCcujS+PEKz2OYAnqCwJG4lA8pHIGAKaI9Ls7+/4VxNgfMGR52XYdDnA0Yyz846DXEa/h9A3wDfAN8A3wDfAOAIL2uS3CK3iBtrmtwira4NyBg1nOO21zX4QgjlATp1OrMjwHU0RkwEOBjtruuxQEaqcQEAUMltYy4rscqRqilEjN1XGA9VZRSqt2k5By9tNHGO3ROvP0bpkYvBeY8k00AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDQtMTNUMTE6NDE6MzQrMDI6MDCAxbwoAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE2LTA0LTEzVDExOjQxOjM0KzAyOjAw8ZgElAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII=)}.avatar.disable{opacity:.7}.avatar-wallet{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAQAAABpN6lAAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfgBA0JMBOJU4OdAAAB2klEQVR42u3au0ocUQCH8e+IxFRKUohrkG0Eu4BiLrCFDxDBNtjoI1gYTJnGQrRInc4HyBuopNHgBVZIwCJFsHBXLURtQiIyKYyFN3B3zJyd3e/X7e7MmXP+e26zOyBJkiRJkiRJkiRJkiRJkppVSF9E0sk0r+jKuOYnrLMQTqMHkHSzQTHS17fLy3CYroi21JWYj9Z8KDIfvwdUKAC7bGfc+CH6gGrojTyJJBemMr/u+4sLpy2njRZnAAZgAK2t/YHKGUzeZlzz5w2yFU6/EKVsQHAIGIABGIABGIABRN4ILbOVcc1fM9IQCfp7gHOAARiAAbgMXpuhH/GJ0brK/sG78OVfKR0cXPnsQ/iYkwAYY6LOM4eZpXR5q3/t77bH+RkCO5HObZQeEL4nQ7ypcwh8boIAIJQpuwoYQMsugwBJ/73L/h1+3vr+OYtXXn/Lzz7gCV8ZqOH4LUrhz4155IzJvA6B0VqaDwzHu7f/PwEsc1zT8RXWmmoOCJWkl9L95wBWbw6AvO8DfrHkMmgABmAABtDw0j8gUaWHeA9K7odC7GVwhXGgGOmB2ZX4PaDAJs8i9d89XoRq5AAgecoMg3Rm3PhTysyFIyRJkiRJkiRJkiRJkiRJku7wFyuiadmIs5Q9AAAAAElFTkSuQmCC)}.item.item-icon-left>i.avatar:first-child{position:absolute;display:flex;height:100%;align-items:center;font-size:16px;left:16px;top:8px;max-height:32px;max-width:32px}.item.item-checkbox.item-avatar * .item-content>i.avatar:first-child,.item.item-checkbox.item-avatar * .item-content>i.item-image:first-child,.item.item-checkbox.item-avatar *>i.avatar:first-child,.item.item-checkbox.item-avatar *>i.item-image:first-child,.item.item-checkbox.item-avatar .item-content>i.avatar:first-child,.item.item-checkbox.item-avatar .item-content>i.item-image:first-child,.item.item-checkbox.item-avatar>i.avatar:first-child,.item.item-checkbox.item-avatar>i.item-image:first-child{left:65px}.item.item-checkbox .item-content .item-avatar,.item.item-checkbox.item-avatar .item-content{padding-left:65px}.popup-container.confirm .popup,.popup-container.warning .popup{min-width:250px!important;width:350px!important}.popup-container.confirm .popup-head h1,.popup-container.confirm .popup-head h2,.popup-container.confirm .popup-head h3,.popup-container.confirm .popup-head h5,.popup-container.confirm .popup-head h6,.popup-container.confirm .popup-head p,.popup-container.warning .popup-head h1,.popup-container.warning .popup-head h2,.popup-container.warning .popup-head h3,.popup-container.warning .popup-head h5,.popup-container.warning .popup-head h6,.popup-container.warning .popup-head p{color:#fff}.popup-container.warning .popup-head{background-color:#ef473a}.popup-container.confirm .popup-head{background-color:#387ef5}.refresher-top-bg:before{position:absolute;display:block;top:0;width:100%;height:100px;z-index:-10;content:" "}.refresher-top-bg .scroll-refresher{z-index:50}.refresher-light .scroll-refresher .ionic-refresher-content,.view-identity .refresher-top-bg .scroll-refresher .ionic-refresher-content,.view-wallet .refresher-top-bg .scroll-refresher .ionic-refresher-content,.view-wallet-tx .refresher-top-bg .scroll-refresher .ionic-refresher-content{color:#fff}.refresher-light .scroll-refresher .spinner,.view-identity .refresher-top-bg .scroll-refresher .spinner,.view-wallet .refresher-top-bg .scroll-refresher .spinner,.view-wallet-tx .refresher-top-bg .scroll-refresher .spinner{stroke:#fff;fill:#fff}.view-wallet .refresher-top-bg:before{height:200px}.view-wallet .qrcode{position:absolute;top:30px;padding:3px;background:#fff;width:90px;max-width:30%;right:-170px;-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.view-wallet .qrcode img{width:100%}.view-wallet .qrcode.on{right:30px}.view-wallet .qrcode.active{top:0!important;right:0!important;padding:10px;width:200px;max-width:50%}.view-wallet .item-text-wrap{white-space:normal!important}.view-wallet .item .comment{font-style:italic!important}.popover-helptip .view-wallet .item h3 .button-close,.popover-share .bar-footer .view-wallet .item h3 .button-close,.popover-share .bar-header .view-wallet .item h3 span,.view-wallet .item h3 .gray,.view-wallet .item h3 .popover-helptip .button-close,.view-wallet .item h3 .popover-share .bar-footer .button-close,.view-wallet .item h3 .popover-share .bar-header span{font-size:11px!important}.view-wallet .list .item span{display:inline}.view-wallet .item-divider .badge{top:16px!important}.view-wallet .item.item-wallet-event{padding-top:5px;padding-bottom:5px;min-height:30px;max-height:auto;height:auto}.view-wallet .item.item-wallet-event:last-child{min-height:48px}#menu .footer .view-wallet .item.item-icon-left.item-wallet-event .icon-help,.view-wallet .item.item-icon-left.item-wallet-event #menu .footer .icon-help,.view-wallet .item.item-icon-left.item-wallet-event .icon,.view-wallet .item.item-icon-left.item-wallet-event .icon-alert,.view-wallet .item.item-icon-left.item-wallet-event .icon-help{font-size:15px}@media screen and (max-width:991px){.view-wallet .qrcode{top:8px;width:60px;max-width:30%}.view-wallet .qrcode.on{right:8px}.view-wallet .hero.hero-qrcode-active h1,.view-wallet .hero.hero-qrcode-active h2,.view-wallet .hero.hero-qrcode-active h3,.view-wallet .hero.hero-qrcode-active h4,.view-wallet .hero.hero-qrcode-active h5,.view-wallet .hero.hero-qrcode-active i{margin-right:200px}}.popover-wallet-actions{height:400px}.view-wallet-tx .hero{height:100px}.view-wallet-tx .refresher-top-bg:before{height:100px}.view-wallet-tx .item-text-wrap{white-space:normal!important}.view-wallet-tx .item .comment{font-style:italic!important}.popover-helptip .view-wallet-tx .item h3 .button-close,.popover-share .bar-footer .view-wallet-tx .item h3 .button-close,.popover-share .bar-header .view-wallet-tx .item h3 span,.view-wallet-tx .item h3 .gray,.view-wallet-tx .item h3 .popover-helptip .button-close,.view-wallet-tx .item h3 .popover-share .bar-footer .button-close,.view-wallet-tx .item h3 .popover-share .bar-header span{font-size:11px!important}.view-wallet-tx .list .item span{display:inline}.view-wallet-tx .item-divider .badge{top:16px!important}.stable-100-bg{background-color:#f2f2f2!important}.item-tx .badge-energized{background-color:rgba(255,201,0,.3);color:#888!important}.view-identity .hero,.view-identity .refresher-top-bg:before{height:200px}.card .card-header{font-size:90%;opacity:.8}.card .stable-900-bg,.card.stable-900-bg,.item .stable-900-bg,.item-complex .item-content .stable-900-bg,.item-radio .item-content .stable-900-bg,.item.stable-900-bg{background-color:#e0e0e0!important}.card .item{background:inherit}.card .stable-bg,.card.stable-bg,.item .stable-bg,.item-complex .item-content .stable-bg,.item-radio .item-content .stable-bg,.item.stable-bg{background-color:#f8f8f8!important}.card .card-header{padding-top:5px!important;padding-bottom:0!important;min-height:25px}.card .item .card-footer{margin-bottom:5px}.card .card-avatar .avatar,.card.card-avatar .avatar{box-shadow:0 3px 4px 0 rgba(0,0,0,.26);top:7px;background-color:#d9d9d9}.card .card-avatar img.avatar,.card.card-avatar img.avatar{border:0;min-height:54px;min-width:54px}.card .card-avatar .item.item-avatar,.card.card-avatar .item.item-avatar{padding-top:10px;padding-bottom:2px;min-height:45px!important}.card .card-avatar .card-footer,.card.card-avatar .card-footer{padding-left:88px;overflow:hidden}#menu .footer .popover-helptip .card .card-avatar .card-footer .icon-bottom-center.icon-help a,#menu .footer .popover-helptip .card .card-avatar .card-footer .icon-bottom-right.icon-help a,#menu .footer .popover-helptip .card .card-avatar .card-footer .icon-center.icon-help a,#menu .footer .popover-helptip .card .card-avatar .card-footer .icon-right.icon-help a,#menu .footer .popover-helptip .card.card-avatar .card-footer .icon-bottom-center.icon-help a,#menu .footer .popover-helptip .card.card-avatar .card-footer .icon-bottom-right.icon-help a,#menu .footer .popover-helptip .card.card-avatar .card-footer .icon-center.icon-help a,#menu .footer .popover-helptip .card.card-avatar .card-footer .icon-right.icon-help a,.card .card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help a,.card .card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help a,.card .card-avatar .card-footer #menu .footer .popover-helptip .icon-center.icon-help a,.card .card-avatar .card-footer #menu .footer .popover-helptip .icon-right.icon-help a,.card .card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help a,.card .card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help a,.card .card-avatar .card-footer .popover-helptip #menu .footer .icon-center.icon-help a,.card .card-avatar .card-footer .popover-helptip #menu .footer .icon-right.icon-help a,.card .card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-alert a,.card .card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-help a,.card .card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-alert a,.card .card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-help a,.card .card-avatar .card-footer .popover-helptip .icon-center.icon-alert a,.card .card-avatar .card-footer .popover-helptip .icon-center.icon-help a,.card .card-avatar .card-footer .popover-helptip .icon-right.icon-alert a,.card .card-avatar .card-footer .popover-helptip .icon-right.icon-help a,.card .card-avatar .card-footer .popover-helptip .icon.icon-bottom-center a,.card .card-avatar .card-footer .popover-helptip .icon.icon-bottom-right a,.card .card-avatar .card-footer .popover-helptip .icon.icon-center a,.card .card-avatar .card-footer .popover-helptip .icon.icon-right a,.card .card-avatar .card-footer .pull-right a,.card.card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help a,.card.card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help a,.card.card-avatar .card-footer #menu .footer .popover-helptip .icon-center.icon-help a,.card.card-avatar .card-footer #menu .footer .popover-helptip .icon-right.icon-help a,.card.card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help a,.card.card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help a,.card.card-avatar .card-footer .popover-helptip #menu .footer .icon-center.icon-help a,.card.card-avatar .card-footer .popover-helptip #menu .footer .icon-right.icon-help a,.card.card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-alert a,.card.card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-help a,.card.card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-alert a,.card.card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-help a,.card.card-avatar .card-footer .popover-helptip .icon-center.icon-alert a,.card.card-avatar .card-footer .popover-helptip .icon-center.icon-help a,.card.card-avatar .card-footer .popover-helptip .icon-right.icon-alert a,.card.card-avatar .card-footer .popover-helptip .icon-right.icon-help a,.card.card-avatar .card-footer .popover-helptip .icon.icon-bottom-center a,.card.card-avatar .card-footer .popover-helptip .icon.icon-bottom-right a,.card.card-avatar .card-footer .popover-helptip .icon.icon-center a,.card.card-avatar .card-footer .popover-helptip .icon.icon-right a,.card.card-avatar .card-footer .pull-right a,.popover-helptip #menu .footer .card .card-avatar .card-footer .icon-bottom-center.icon-help a,.popover-helptip #menu .footer .card .card-avatar .card-footer .icon-bottom-right.icon-help a,.popover-helptip #menu .footer .card .card-avatar .card-footer .icon-center.icon-help a,.popover-helptip #menu .footer .card .card-avatar .card-footer .icon-right.icon-help a,.popover-helptip #menu .footer .card.card-avatar .card-footer .icon-bottom-center.icon-help a,.popover-helptip #menu .footer .card.card-avatar .card-footer .icon-bottom-right.icon-help a,.popover-helptip #menu .footer .card.card-avatar .card-footer .icon-center.icon-help a,.popover-helptip #menu .footer .card.card-avatar .card-footer .icon-right.icon-help a,.popover-helptip .card .card-avatar .card-footer .icon-bottom-center.icon-alert a,.popover-helptip .card .card-avatar .card-footer .icon-bottom-center.icon-help a,.popover-helptip .card .card-avatar .card-footer .icon-bottom-right.icon-alert a,.popover-helptip .card .card-avatar .card-footer .icon-bottom-right.icon-help a,.popover-helptip .card .card-avatar .card-footer .icon-center.icon-alert a,.popover-helptip .card .card-avatar .card-footer .icon-center.icon-help a,.popover-helptip .card .card-avatar .card-footer .icon-right.icon-alert a,.popover-helptip .card .card-avatar .card-footer .icon-right.icon-help a,.popover-helptip .card .card-avatar .card-footer .icon.icon-bottom-center a,.popover-helptip .card .card-avatar .card-footer .icon.icon-bottom-right a,.popover-helptip .card .card-avatar .card-footer .icon.icon-center a,.popover-helptip .card .card-avatar .card-footer .icon.icon-right a,.popover-helptip .card.card-avatar .card-footer .icon-bottom-center.icon-alert a,.popover-helptip .card.card-avatar .card-footer .icon-bottom-center.icon-help a,.popover-helptip .card.card-avatar .card-footer .icon-bottom-right.icon-alert a,.popover-helptip .card.card-avatar .card-footer .icon-bottom-right.icon-help a,.popover-helptip .card.card-avatar .card-footer .icon-center.icon-alert a,.popover-helptip .card.card-avatar .card-footer .icon-center.icon-help a,.popover-helptip .card.card-avatar .card-footer .icon-right.icon-alert a,.popover-helptip .card.card-avatar .card-footer .icon-right.icon-help a,.popover-helptip .card.card-avatar .card-footer .icon.icon-bottom-center a,.popover-helptip .card.card-avatar .card-footer .icon.icon-bottom-right a,.popover-helptip .card.card-avatar .card-footer .icon.icon-center a,.popover-helptip .card.card-avatar .card-footer .icon.icon-right a{margin-right:8px}.a.underline:active,.underline a:active,.underline a:focus,.underline a:hover,a.underline:focus,a.underline:hover{outline:1px!important;text-decoration:underline!important}.card-avatar-small .card,.card-avatar-small .card .card-avatar,.card-avatar-small .card.card-avatar,.card-avatar-small.card{min-height:45px}.card-avatar-small .card .avatar,.card-avatar-small .card .card-avatar .avatar,.card-avatar-small .card .card-avatar .item-avatar .avatar,.card-avatar-small .card .item-avatar .avatar,.card-avatar-small .card.card-avatar .avatar,.card-avatar-small .card.card-avatar .item-avatar .avatar,.card-avatar-small.card .avatar,.card-avatar-small.card .item-avatar .avatar{box-shadow:0 2px 2px 0 rgba(0,0,0,.26);height:30px!important;width:30px!important;left:5px!important}.card-avatar-small .card .card-avatar .item.item-avatar,.card-avatar-small .card .item.item-avatar,.card-avatar-small .card.card-avatar .item.item-avatar,.card-avatar-small.card .item.item-avatar{min-height:25px!important;padding-left:42px!important}.card-avatar-small .card .card-avatar .card-footer,.card-avatar-small .card .card-footer,.card-avatar-small .card.card-avatar .card-footer,.card-avatar-small.card .card-footer{padding-top:0;padding-left:42px!important}.gallery .card-gallery,.gallery .card.card-gallery{margin-bottom:15px!important;float:left;display:block}.gallery .card-gallery img,.gallery .card.card-gallery img{max-height:150px}.gallery .card-gallery-new{max-height:199px}.list .item.text-left{text-align:left!important}.list .item.large-button-bar,.list .item.text-center{text-align:center!important}.list .item.text-right{text-align:right!important}.list .item-divider.item-divider-top-border{border-top:solid 1px rgba(0,0,0,.12)}.lookupForm .list .item.item-avatar{min-height:80px!important}.lookupForm .list .item.item-avatar.item-checkbox .item-content{padding-left:47px}.fade-in{opacity:0;-webkit-transform:translate3d(-30px,1px,0);-webkit-transition:all 1s ease-in-out}.fade-in.on{opacity:1;-webkit-transform:translate3d(0,0,0)}.item-avatar{min-height:80px!important}.item-avatar .item-content i.item-image:first-child,.item-avatar .item-content img.item-image:first-child,.item-avatar .item-content>i:first-child,.item-avatar .item-content>img:first-child,.item-avatar i.item-image:first-child,.item-avatar img.item-image:first-child,.item-avatar-left .item-content i.item-image:first-child,.item-avatar-left .item-content img.item-image:first-child,.item-avatar-left .item-content>i:first-child,.item-avatar-left .item-content>img:first-child,.item-avatar-left i.item-image:first-child,.item-avatar-left img.item-image:first-child,.item-avatar-left>i:first-child,.item-avatar-left>img:first-child,.item-avatar>i:first-child,.item-avatar>img:first-child{color:#d9d9d9;background-color:#f8f8f8;border:solid 1px #d9d9d9;overflow:hidden!important;font-size:45px!important;line-height:56px;width:100%!important;max-height:56px!important;max-width:56px!important;top:12px!important}#menu .footer .item-avatar .item-content>.icon-help:first-child:before,#menu .footer .item-avatar .item-image.icon-help:first-child:before,#menu .footer .item-avatar.item-icon-right .icon-help:first-child:before,#menu .footer .item-avatar>.icon-help:first-child:before,.item-avatar #menu .footer .item-content>.icon-help:first-child:before,.item-avatar #menu .footer .item-image.icon-help:first-child:before,.item-avatar .icon.item-image:first-child:before,.item-avatar .item-content>.icon-alert:first-child:before,.item-avatar .item-content>.icon-help:first-child:before,.item-avatar .item-content>.icon:first-child:before,.item-avatar .item-image.icon-alert:first-child:before,.item-avatar .item-image.icon-help:first-child:before,.item-avatar.item-icon-right #menu .footer .icon-help:first-child:before,.item-avatar.item-icon-right .icon-alert:first-child:before,.item-avatar.item-icon-right .icon-help:first-child:before,.item-avatar.item-icon-right .icon:first-child:before,.item-avatar>.icon-alert:first-child:before,.item-avatar>.icon-help:first-child:before,.item-avatar>.icon:first-child:before{width:56px!important}#menu .footer .item-avatar.item-icon-right .icon-help:last-child,.item-avatar.item-icon-right #menu .footer .icon-help:last-child,.item-avatar.item-icon-right .icon-alert:last-child,.item-avatar.item-icon-right .icon-help:last-child,.item-avatar.item-icon-right .icon:last-child{left:auto}.item em{font-weight:700!important}@media screen and (min-width:992px){.list .item.item-border-large{border-bottom:solid 1px #ccc!important}.list.item-border-large .item{border-bottom:solid 1px #ccc!important;margin:0}.list.item-border-large .item-divider{border-top:0}}.list .item.item-border{border-bottom:solid 1px #ccc!important}.list .item.item-small-height{padding-top:2px;padding-bottom:0;min-height:24px}.list .item.item-small-height .badge{padding-top:0!important;top:inherit}.list .item.item-small-height .badge.badge-assertive,.list .item.item-small-height .badge.badge-balanced,.list .item.item-small-height .badge.badge-calm,.list .item.item-small-height .badge.badge-editable:hover,.list .item.item-small-height .badge.badge-energized,.list .item.item-small-height .badge.badge-positive,.list .item.item-small-height .badge.badge-royal{top:1px!important;padding-top:3px!important;padding-bottom:2px!important}.form-errors:first-child{margin:5px 0}.form-errors:last-child{margin:5px 0 0}.form-error{padding:0 16px;font-size:12px;color:red;vertical-align:middle;text-align:end;top:0;position:relative}.item-input-error{border-bottom:2px solid red!important}.item-input.item-button-right input,.item-input.item-button-right textarea{margin-right:100px}.item-input.item-button-right .button,.item-input.item-button-right button{top:6px}.item-input.item-button-right.item-floating-label input,.item-input.item-button-right.item-floating-label textarea{padding-right:100px}.item-input.item-button-right.item-floating-label .button{top:inherit;bottom:6px}.item-input.item-button-right.item-floating-label .button-icon{height:inherit}.item.item-button-right .badge,.item.item-icon-right .badge{right:43px}.badge-editable:hover{cursor:pointer}.badge-editable:hover:before{content:" "}.bar .badge-button{margin:0!important;padding:0 4px!important;font-size:10px;position:absolute!important;top:5px;right:3px}.modal.modal-full-height{bottom:0}.modal.about .bar.bar-header .button+.title{left:0!important}.item-button-right .item-content>.button,.item-button-right .item-content>.buttons,.item-button-right>.button,.item-button-right>.buttons{top:16px}.item-button-right .item-content>.button.button-small,.item-button-right .item-content>.buttons .button-small,.item-button-right>.button.button-small,.item-button-right>.buttons .button-small{font-size:14px}.item.large-button-bar{margin-bottom:10px}.item-avatar-left-padding{padding-left:95px}.item-thumbnail-left-padding{padding-left:106px}.item-thumbnail-left,.item.item-thumbnail-left{min-height:100px!important}.item-thumbnail-left .item-content i.item-image,.item-thumbnail-left .item-content>i:first-child,.item-thumbnail-left i.item-image,.item-thumbnail-left>i:first-child{color:#d9d9d9;background-color:#f8f8f8;overflow:hidden!important;font-size:50px!important;line-height:80px;padding:0 15px;background-position:center;background-size:cover;display:inline-block}@media screen and (max-width:400px){.card>.item.item-thumbnail-left,.item-thumbnail-left,.item-thumbnail-left .item-content{padding-left:84px!important}.item-thumbnail-left .item-content img.item-image,.item-thumbnail-left .item-content>img:first-child,.item-thumbnail-left img.item-image,.item-thumbnail-left>img:first-child{max-width:70px;max-height:70px}.item h2{font-size:13px!important}}.item-icon-left-padding{padding-left:40px}.item-icon-right-padding{padding-right:40px}.text-keep-lines{white-space:pre-line!important}.text-italic{font-style:italic!important}#menu .item-button-right>.button,.item-button-right .item-content>.button,.item-button-right .item-content>.buttons,.item-button-right>.buttons{top:8px!important}@media screen and (max-width:400px){#menu .item.item-divider{min-height:2px;height:2px;padding-top:0;padding-bottom:0}#menu .item,#menu .item.item-complex .item-content{height:40px;min-height:40px;padding-top:12px}#menu .item.item-complex{padding-top:0}#menu .item.item-button-right .button{height:30px;min-height:30px;top:4px}#menu .item.active a{background-color:#b2e0ff!important}#menu ion-content.has-footer{bottom:0!important}}@media screen and (min-width:401px){#menu .item.active a{background-color:#b2e0ff!important}#menu .item.item-divider{min-height:5px;height:5px}#menu .footer a{font-size:14px!important;color:grey!important}}@media screen and (max-width:991px){#menu .bar-header{background-color:#1a237e;color:#fff;height:175px;padding-right:0!important}#menu .bar-header .hero{height:175px;box-shadow:none}#menu .bar-header .hero .content{bottom:5px}#menu .has-header{top:175px}}.hero.stable-bg{background-color:#f8f8f8!important}.certifications .item-divider .badge{top:16px!important}.certifications-lg .avatar-large{left:auto;position:relative;font-size:55px!important;height:88px;width:88px;color:#d9d9d9;background-color:#e0e0e0;border:solid 1px #d9d9d9}.icon-help{font-size:38px;vertical-align:middle}.icon-alert{font-size:38px;vertical-align:middle}#menu .footer .icon-help{font-size:25px!important;position:absolute;left:12px;top:8px;z-index:99}.popover-helptip{background-color:rgba(68,68,68,.85)!important;height:auto!important}.popover-helptip .button-close{padding:8px;height:25px;font-size:18.2px}.popover-helptip a,.popover-helptip a:active,.popover-helptip a:hover{text-decoration:underline}.nobackdrop .popover-backdrop.active{background-color:transparent!important}.helptip-anchor,.helptip-anchor-center,.helptip-anchor-left,.helptip-anchor-right{display:block;position:absolute;width:100%;bottom:0}.helptip-anchor-center{text-align:center}.helptip-anchor-left{text-align:left}.helptip-anchor-right{text-align:right}.helptip-anchor a:before,.helptip-anchor-center a:before,.helptip-anchor-left a:before,.helptip-anchor-right a:before{content:" "}@media (max-width:767px){.popover-helptip{width:auto}}#menu .footer .popover-helptip .icon-left.icon-help,.popover-helptip #menu .footer .icon-left.icon-help,.popover-helptip .icon-left.icon-alert,.popover-helptip .icon-left.icon-help,.popover-helptip .icon.icon-left{font-size:30px;position:relative;top:8px;left:8px}#menu .footer .popover-helptip .icon-right.icon-help,.popover-helptip #menu .footer .icon-right.icon-help,.popover-helptip .icon-right.icon-alert,.popover-helptip .icon-right.icon-help,.popover-helptip .icon.icon-right{font-size:30px;position:relative;top:8px;right:8px}#menu .footer .popover-helptip .icon-center.icon-help,.popover-helptip #menu .footer .icon-center.icon-help,.popover-helptip .icon-center.icon-alert,.popover-helptip .icon-center.icon-help,.popover-helptip .icon.icon-center{font-size:30px;width:100%;text-align:center;position:relative;top:8px;height:0}#menu .footer .popover-helptip .icon-bottom-right.icon-help,.popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-helptip .icon-bottom-right.icon-alert,.popover-helptip .icon-bottom-right.icon-help,.popover-helptip .icon.icon-bottom-right{font-size:30px;position:relative;bottom:8px;right:8px}#menu .footer .popover-helptip .icon-bottom-left.icon-help,.popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-helptip .icon-bottom-left.icon-alert,.popover-helptip .icon-bottom-left.icon-help,.popover-helptip .icon.icon-bottom-left{font-size:30px;position:relative;bottom:8px;left:8px}#menu .footer .popover-helptip .icon-bottom-center.icon-help,.popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-helptip .icon-bottom-center.icon-alert,.popover-helptip .icon-bottom-center.icon-help,.popover-helptip .icon.icon-bottom-center{font-size:30px;position:relative;width:100%;bottom:8px;text-align:center;height:0}.popover.popover-profile{height:200px}.popover.popover-profile .avatar{height:90px;width:90px;left:20px;top:20px}.popover.popover-profile .avatar{border:solid 1px #d9d9d9}.popover.popover-profile .bar.bar-footer{height:58px}.popover.popover-profile .bar.bar-footer .col .button{max-width:inherit;width:100%;padding:5px 0;margin:0}.popover.popover-profile .bar .button-positive,.popover.popover-profile .bar .button-text{background-color:#387ef5!important}.popover.popover-profile .bar .button-stable{color:#444!important}.bar-header .button-icon .avatar{height:35px;width:35px;position:relative;left:0;top:4px;border:solid 1px #d9d9d9}.bar-header .button-icon .avatar.active{background-color:#e0e0e0}.bar-header .button-icon .avatar{height:31px;width:31px;position:relative;left:0;top:6px}.list .badge .badge-secondary,.list .badge.badge-secondary{font-size:12px;font-style:italic;top:37px;font-weight:400!important;margin-right:0;padding-right:0}.popover.popover-login-methods{height:280px;width:260px}.popover.popover-login-methods.auth{height:204px}@media (max-width:767px){.popover.popover-login-methods{height:233px}.popover.popover-login-methods.auth{height:152px}}.ion-es-user-api:before{content:url(../img/logo.small.cs.dune.svg)}.ion-bma-tor-api:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAATEAYAAAChBNO0AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAB3lJREFUWMPNmGtUVNcVx/93mBlmgEGeAyhYUoSERhmM9ZHSCL4AqURFEmSBEZOgWGqh0pqYNkREiIlxxSXqYpUoJhqVRWJ41tooKNYIGR8R8QlKAsj7PQ9k7tx7++Gc6VpQnctK4lo9X35zz+x79v7vM2fffYfB/8lYty4iIjFx/Oz0TEJpD2HTLwj1RmqwvbDw9OmjR3+8XylxHPBPcuk1QucbKIUn3GeZ/45eJlCWEfJfEJp3Ew6qqIADhNw3lsDHCrf1I9SMEi6XERpOEV7YRLn950q8lODUfcLJWVRIpkgCLGMG5S5q/kfKRXR+D0H7TSrIhfD2+B33JUiII0xZR6i4QljwiLC23HLDT915y2BIIIKY0J84DFsII/5NePHS2O9dqdDT8YTBdOezUwlzHxKyOT+XcMuQUCY93QQwv6TudkAKbygBhKAEMZMiuA7uGtc601HIETYL259loYASikNbif2uWU9LuGXQI2CqI5Q/rQw4Uvq6/86rUq0DpB9KG2xWrmzybvMt8FFnyBvmX6m5sbN/qiFT3294Pq9HUi1RSq4YE3+s8McXVUkela0g5BxoAr5MJgycR8i8Q+OmP1nfY3S+zbrbrgrKNdQ+gPDBNcIWvxFvw7GRBkChV+bbajvbg34951pwcYDUrDLfM2fZpGtrapK/XR1ikLCSQxKPG/8VIpaIxwv2CSNcyRH+ZgehcwFhz1l6BJLoDi2IIgwtpsvSwAevWxcu+BBmLiZ8iZ7d0BrC+C19tl2He9f+cKcitXhhaar8kGyJ/Dl5+txbihi7EuV+mZ1sozxavt9mhcQoiZTIVx3Hi1iE36pN1gU+aX6BPWHpAsI9VHBcJ2F4NGFCNWN9wUBavM7fInQvx2MHq6WZbiGsjL3N1JfdqgDWx2ZoNu4FKtnil8oLnhkMUsz+SPPu1mURbas+XuqX+KW7ndc2dYVS3Tjjps89CVA+fGxJaTY/YDira9GvO/cv5gFjwzx8fwNZt9qbkLv5+DiC/k5Y/AFhQBNEhsT613wppVnkF0AbE65EOCDkCHnAkYozyuNNQM2bpz87lxKuXey/PDo8unRnkmt66xs+yYemF866PENQqtllplzWH5g27Vce/ksBzRtzZJp7EmfhIr9X+HphHBgwYIrayfoZ9GlgmzXWv00rYZr/RIVPNAGhlG+JrEMbFcFTtlwmk20Gco9t/ir76gtVizetKAnPP1ATv3BDbYJqxvsqT6cwx2z4DysHzw7nA85rXZ2d2wAunq3mQgDNxrlzZnYBCg+7VMVqAJ8Je4VCFzuyflY9YcpHY917ORGGFU1MthBLqJOLJEAIox/iRVbsoPaOB9dUag4XSouDN80Nmdm/9fXIPaviohr8NhtN+lhjEcDam15kWwCPbVNe8wwFdMuH5uk6AVOaKce0CFAE2mUpUwHVQadGRwdA8BZG4GZxo6C1Jo2eZb+phPafEqpU1sM0BBK+R/uMcEYkAaiiwr4RsRsFBw4cfz6mbl7wy/y0Rv/h5+UB3qGZ/B4hht8B8LuFFfx2wCXHLcXFFeg/2VPcNxlQJtg/tDsOyJbKOGkqYC5idWwuYDNV8pZEAwiXUPW/3n19CWfT2oRXCSRfWQ/zPu0r9tNOs9YkloA+ygEROw5deIhOYZFdmMOAfZ7DC47tzsGT4pS8/s7QXf0WwKnTJdc5BeiWd6R0xQIOMY7xqn8A8lrbM/IRgPFkIphngJFso/ej+QDrZYpihwDmbWYX87fx7phuwilrqfA/j92wJ+5TCSGrscyIJeA8ZZ2I3SBsoYAtWvlWbhdfL+SzR9ledpugtmmXJtlwwPCRgSVDQYDiO6WXwgmQVksTpU3AUFR/xYAWQC860Qv0ft25vscDMMzXbzV0AEwxapnSJ7k10scZQ99JmG+th2mm/Y7wygQTIFgeiH8SScBtuEINN2Ztt7LjD11xP5R9H9Ho2BzedFBoFIqFemCgo8+jfw0gmybn5NHA4M6+GwM2gPRz2UaZFjCFjEaa7IG2qmbPlruA6dToSdMOAMuY1Yge7073HmE9rQ6S+TQB90X0PEf5yUQTcJiQvyxiRxsn5vfT5bMWB6X28tdwafBqRt65u6jfd+fCSMOw20Dd8BGgc1ZbZEcGwJawJnY3wDfwb/M1gL5E12B4Beha1v5x1z4AznCHCwAj9DCO91dOH3PafYRS+pbJXBDZKNqvWIq2aAK412gCSq3bWYoQ79K/t/uDPjNwVXpReznt875qTWXOWb+c9d+nNYU2pw/trw/QFlwvA/rcux/1vQv0xHfoesqgbyy6mX33HfT2nux8tccOECqFE0IZADd4wp1LosLpa/ZfHQhN9H8MNNONyLUeJm9L7dSWGan1G4y0pexeRTg5nS5Eqyi6CPrpe/yQgpkpeZMJwRlV3aRc1WyTtEpdrj0z5cMSvXF4jc7jtp9tgCJfEb+p9Eaydsn183OTZa/Lm2VHld2tUQ8+bY2Gg+nEaORooPkE8xfGh6lt3EAaoSO0un9Ci1xPztg4hxtpnLQfcaA1QaBHhKH/U7Q/S8g6We78Dzmv92D5rFiKAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTEwLTE0VDExOjU4OjIwKzA1OjAwUOI3hwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0xMC0xNFQxMTo1ODoyMCswNTowMCG/jzsAAAAvdEVYdHN2Zzpjb21tZW50AD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/5MH3awAAAABJRU5ErkJggg==)}.row-header{border-bottom:solid 1px #ccc!important;margin:0;min-height:28px!important}.col-header{text-align:center;display:block!important}.col-15{-webkit-box-flex:0;-webkit-flex:0 0 15%;-moz-box-flex:0;-moz-flex:0 0 15%;-ms-flex:0 0 15%;flex:0 0 15%;max-width:15%}.col-border-left{border-left:solid 1px #ccc!important}.col-border-right{border-right:solid 1px #ccc!important}.ion-spinner-small{height:14px;width:14px;line-height:14px;margin:0;padding:0}.ion-spinner-small svg{height:14px;width:14px}.icon-secondary{position:absolute;height:100%;display:flex;align-items:center;font-size:16px;left:25px;top:-7px}div[dropzone]{border:2px dashed #bbb;border-radius:5px;padding:15px;text-align:center;font:20pt bold;color:#bbb;margin-bottom:20px}.hero .button-fab-top-left,.hero .button-fab-top-right{top:170px!important}.text-no-transform{text-transform:inherit}.button-icon-event,.item-icon-event{text-transform:inherit;pointer-events:none!important}#menu .footer .button-icon-event .icon-help,#menu .footer .item-icon-event .icon-help,.button-icon-event #menu .footer .icon-help,.button-icon-event .icon,.button-icon-event .icon-alert,.button-icon-event .icon-event,.button-icon-event .icon-help,.item-icon-event #menu .footer .icon-help,.item-icon-event .icon,.item-icon-event .icon-alert,.item-icon-event .icon-event,.item-icon-event .icon-help{pointer-events:all!important}.hero.dark-bg,.view-identity .hero,.view-identity .hero.refresher-top-bg:before{background-color:#555}.hero.positive-900-bg,.view-identity .hero.member.refresher-top-bg:before,.view-identity .member .hero,.view-wallet .hero.refresher-top-bg:before,.view-wallet-tx .hero.refresher-top-bg:before{background-color:#1a237e!important}.popover-locked-outputs .item .badge{right:16px}.animate-show-hide.ng-hide{opacity:0}.animate-show-hide.ng-hide-add,.animate-show-hide.ng-hide-remove{transition:all linear .3s}@media screen and (max-width:991px){.modal iframe.iframe-license{width:100%;height:78%}}@media screen and (min-width:992px){.modal iframe.iframe-license{width:100%;height:70%}.modal.modal-license iframe.iframe-license{width:100%;height:85%!important}}.modal.modal-help .row.selected .col:first-child{font-weight:700}@media screen and (max-width:767px){.modal.modal-help .row .col:first-child{font-weight:700}.modal.modal-help h2{padding-left:10px}}.modal.modal-login .item.item-icon-right.item-text-wrap .item-content{margin-right:58px;text-overflow:ellipsis;overflow:hidden}.popover-locales{height:284px;width:200px}.popover-locales .item{height:48px}.buttons-tabs{display:block;height:57px;border:0;padding:16px 16px 0 16px;overflow:hidden}.buttons-tabs .button.button-tab:first-child{border-top-left-radius:15px}.buttons-tabs .button.button-tab:last-child{border-top-right-radius:15px}.buttons-tabs .button.button-tab.active{background-color:#b2e0ff}.buttons-tabs.border-bottom{border-bottom:solid 1px #ccc!important}@media screen and (max-width:767px){.buttons-tabs{padding:10px 10px 0 10px}.buttons-tabs .button.button-tab{padding:2px 10px 0 10px!important}} \ No newline at end of file + */.button-clear,.button-fab,.button-flat,.button-raised,.button-text,.ink,.popup .button{position:relative;cursor:pointer;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.ink-ripple{position:absolute;border-radius:50%;width:100px;height:100px;margin-top:-50px;margin-left:-50px;opacity:0;background-color:rgba(255,255,255,.4);-webkit-transition:all .5s ease-out;-moz-transition:all .5s ease-out;-o-transition:all .5s ease-out;transition:all .5s ease-out;-webkit-transition-property:-webkit-transform,opacity;-moz-transition-property:-moz-transform,opacity;-o-transition-property:-o-transform,opacity;transition-property:transform,opacity;-webkit-transform:scale(0);-moz-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);pointer-events:none}.ink-notransition{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.button-clear,.button-fab,.button-flat,.button-raised,.button-text,.ink-button,.ink-circle{-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.activated.button-text,.button-clear.activated,.button-clear:active,.button-fab.activated,.button-fab:active,.button-flat.activated,.button-flat:active,.button-raised.activated,.button-raised:active,.button-text:active,.ink-button.activated,.ink-button:active,.ink-circle.activated,.ink-circle:active,.ink.activated,.ink:active,.popup .button.activated,.popup .button:active{-webkit-mask-image:-webkit-radial-gradient(circle,#fff 100%,#000 100%)}.button-clear,.button-clear:link,.button-clear:visited,.button-fab,.button-fab:link,.button-fab:visited,.button-flat,.button-flat:link,.button-flat:visited,.button-raised,.button-raised:link,.button-raised:visited,.button-text,.button-text:link,.button-text:visited,.ink-button,.ink-button-input,.ink-button:link,.ink-button:visited{white-space:nowrap;vertical-align:middle;cursor:pointer;border:none;outline:0;font-size:14px;text-align:center;text-decoration:none;z-index:1}.ink-button{padding:10px 15px;border-radius:2px}.ink-button-input{margin:0;padding:10px 15px}.ink-input-wrapper{border-radius:2px;vertical-align:bottom}.ink-input-wrapper.ink-button{padding:0}.ink-input-wrapper .ink-button-input{position:relative;top:0;left:0;z-index:1}.ink-circle{text-align:center;width:2.5em;height:2.5em;line-height:2.5em;border-radius:50%}.ink-float{-webkit-mask-image:none;-webkit-box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12);box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12)}.ink-float:active{-webkit-box-shadow:0 8px 20px 1px rgba(0,0,0,.3);box-shadow:0 8px 20px 1px rgba(0,0,0,.3)}.ink-block{display:block}.ink-ripple{z-index:0}.button-clear .ink-ripple,.button-text .ink-ripple,.ink-dark .ink-ripple,.list .ink-ripple,[class$="-100"]>.ink-ripple,[class$="-clear"]>.ink-ripple,[class$="-light"]>.ink-ripple,[class$="-stable"]>.ink-ripple{background-color:rgba(0,0,0,.2)}.tab-item{position:relative}*{font-family:RobotoDraft,Roboto,"Helvetica Neue","Segoe UI",sans-serif}.rounded{border-radius:4px}a{cursor:pointer}.has-header.expanded{top:76px}.bar{border-bottom:none;padding:0}.bar .button{min-height:44px;min-width:44px;max-width:48px;margin-bottom:0;max-height:44px;width:48px}.bar .title+.buttons.buttons-right{right:0;top:0}.title-left,.title.title-left{left:48px}.title-right,.title.title-right{left:48px}.activated.button-text,.bar .activated.button-text,.bar .button-positive,.bar .button-positive.activated,.bar .button-positive:active,.bar .button-positive:hover,.bar .button-text,.bar .button-text:active,.bar .button-text:hover,.bar-positive,.bar-positive.activated,.bar-positive:active,.bar-positive:hover,.button-bar-positive,.button-bar-positive.activated,.button-bar-positive:active,.button-bar-positive:hover,.button-positive,.button-positive.activated,.button-positive:active,.button-positive:hover,.button-text,.button-text:active,.button-text:hover,.header-positive,.header-positive.activated,.header-positive:active,.header-positive:hover,.positive-bg,.positive-bg.activated,.positive-bg:active,.positive-bg:hover,.positive-border,.positive-border.activated,.positive-border:active,.positive-border:hover{background-color:#3f51b5;color:#fff}.bar .button-positive-900,.bar .button-positive-900.activated,.bar .button-positive-900:active,.bar .button-positive-900:hover,.bar-positive-900,.bar-positive-900.activated,.bar-positive-900:active,.bar-positive-900:hover,.button-bar-positive-900,.button-bar-positive-900.activated,.button-bar-positive-900:active,.button-bar-positive-900:hover,.button-positive-900,.button-positive-900.activated,.button-positive-900:active,.button-positive-900:hover,.header-positive-900,.header-positive-900.activated,.header-positive-900:active,.header-positive-900:hover,.positive-900-bg,.positive-900-bg.activated,.positive-900-bg:active,.positive-900-bg:hover,.positive-900-border,.positive-900-border.activated,.positive-900-border:active,.positive-900-border:hover{background-color:#1a237e;color:#fff}.bar .button-positive-100,.bar .button-positive-100.activated,.bar .button-positive-100:active,.bar .button-positive-100:hover,.bar-positive-100,.bar-positive-100.activated,.bar-positive-100:active,.bar-positive-100:hover,.button-bar-positive-100,.button-bar-positive-100.activated,.button-bar-positive-100:active,.button-bar-positive-100:hover,.button-positive-100,.button-positive-100.activated,.button-positive-100:active,.button-positive-100:hover,.header-positive-100,.header-positive-100.activated,.header-positive-100:active,.header-positive-100:hover,.positive-100-bg,.positive-100-bg.activated,.positive-100-bg:active,.positive-100-bg:hover,.positive-100-border,.positive-100-border.activated,.positive-100-border:active,.positive-100-border:hover{background-color:#c5cae9;color:#fff}.bar .button-calm,.bar .button-calm.activated,.bar .button-calm:active,.bar .button-calm:hover,.bar-calm,.bar-calm.activated,.bar-calm:active,.bar-calm:hover,.button-bar-calm,.button-bar-calm.activated,.button-bar-calm:active,.button-bar-calm:hover,.button-calm,.button-calm.activated,.button-calm:active,.button-calm:hover,.calm-bg,.calm-bg.activated,.calm-bg:active,.calm-bg:hover,.calm-border,.calm-border.activated,.calm-border:active,.calm-border:hover,.header-calm,.header-calm.activated,.header-calm:active,.header-calm:hover{background-color:#2196f3;color:#fff}.bar .button-calm-900,.bar .button-calm-900.activated,.bar .button-calm-900:active,.bar .button-calm-900:hover,.bar-calm-900,.bar-calm-900.activated,.bar-calm-900:active,.bar-calm-900:hover,.button-bar-calm-900,.button-bar-calm-900.activated,.button-bar-calm-900:active,.button-bar-calm-900:hover,.button-calm-900,.button-calm-900.activated,.button-calm-900:active,.button-calm-900:hover,.calm-900-bg,.calm-900-bg.activated,.calm-900-bg:active,.calm-900-bg:hover,.calm-900-border,.calm-900-border.activated,.calm-900-border:active,.calm-900-border:hover,.header-calm-900,.header-calm-900.activated,.header-calm-900:active,.header-calm-900:hover{background-color:#0d47a1;color:#fff}.bar .button-calm-100,.bar .button-calm-100.activated,.bar .button-calm-100:active,.bar .button-calm-100:hover,.bar-calm-100,.bar-calm-100.activated,.bar-calm-100:active,.bar-calm-100:hover,.button-bar-calm-100,.button-bar-calm-100.activated,.button-bar-calm-100:active,.button-bar-calm-100:hover,.button-calm-100,.button-calm-100.activated,.button-calm-100:active,.button-calm-100:hover,.calm-100-bg,.calm-100-bg.activated,.calm-100-bg:active,.calm-100-bg:hover,.calm-100-border,.calm-100-border.activated,.calm-100-border:active,.calm-100-border:hover,.header-calm-100,.header-calm-100.activated,.header-calm-100:active,.header-calm-100:hover{background-color:#bbdefb;color:#fff}.bar .button-royal,.bar .button-royal.activated,.bar .button-royal:active,.bar .button-royal:hover,.bar-royal,.bar-royal.activated,.bar-royal:active,.bar-royal:hover,.button-bar-royal,.button-bar-royal.activated,.button-bar-royal:active,.button-bar-royal:hover,.button-royal,.button-royal.activated,.button-royal:active,.button-royal:hover,.header-royal,.header-royal.activated,.header-royal:active,.header-royal:hover,.royal-bg,.royal-bg.activated,.royal-bg:active,.royal-bg:hover,.royal-border,.royal-border.activated,.royal-border:active,.royal-border:hover{background-color:#673ab7;color:#fff}.bar .button-royal-900,.bar .button-royal-900.activated,.bar .button-royal-900:active,.bar .button-royal-900:hover,.bar-royal-900,.bar-royal-900.activated,.bar-royal-900:active,.bar-royal-900:hover,.button-bar-royal-900,.button-bar-royal-900.activated,.button-bar-royal-900:active,.button-bar-royal-900:hover,.button-royal-900,.button-royal-900.activated,.button-royal-900:active,.button-royal-900:hover,.header-royal-900,.header-royal-900.activated,.header-royal-900:active,.header-royal-900:hover,.royal-900-bg,.royal-900-bg.activated,.royal-900-bg:active,.royal-900-bg:hover,.royal-900-border,.royal-900-border.activated,.royal-900-border:active,.royal-900-border:hover{background-color:#311b92;color:#fff}.bar .button-royal-100,.bar .button-royal-100.activated,.bar .button-royal-100:active,.bar .button-royal-100:hover,.bar-royal-100,.bar-royal-100.activated,.bar-royal-100:active,.bar-royal-100:hover,.button-bar-royal-100,.button-bar-royal-100.activated,.button-bar-royal-100:active,.button-bar-royal-100:hover,.button-royal-100,.button-royal-100.activated,.button-royal-100:active,.button-royal-100:hover,.header-royal-100,.header-royal-100.activated,.header-royal-100:active,.header-royal-100:hover,.royal-100-bg,.royal-100-bg.activated,.royal-100-bg:active,.royal-100-bg:hover,.royal-100-border,.royal-100-border.activated,.royal-100-border:active,.royal-100-border:hover{background-color:#d1c4e9;color:#fff}.balanced-bg,.balanced-bg.activated,.balanced-bg:active,.balanced-bg:hover,.balanced-border,.balanced-border.activated,.balanced-border:active,.balanced-border:hover,.bar .button-balanced,.bar .button-balanced.activated,.bar .button-balanced:active,.bar .button-balanced:hover,.bar-balanced,.bar-balanced.activated,.bar-balanced:active,.bar-balanced:hover,.button-balanced,.button-balanced.activated,.button-balanced:active,.button-balanced:hover,.button-bar-balanced,.button-bar-balanced.activated,.button-bar-balanced:active,.button-bar-balanced:hover,.header-balanced,.header-balanced.activated,.header-balanced:active,.header-balanced:hover{background-color:#4caf50;color:#fff}.balanced-900-bg,.balanced-900-bg.activated,.balanced-900-bg:active,.balanced-900-bg:hover,.balanced-900-border,.balanced-900-border.activated,.balanced-900-border:active,.balanced-900-border:hover,.bar .button-balanced-900,.bar .button-balanced-900.activated,.bar .button-balanced-900:active,.bar .button-balanced-900:hover,.bar-balanced-900,.bar-balanced-900.activated,.bar-balanced-900:active,.bar-balanced-900:hover,.button-balanced-900,.button-balanced-900.activated,.button-balanced-900:active,.button-balanced-900:hover,.button-bar-balanced-900,.button-bar-balanced-900.activated,.button-bar-balanced-900:active,.button-bar-balanced-900:hover,.header-balanced-900,.header-balanced-900.activated,.header-balanced-900:active,.header-balanced-900:hover{background-color:#1b5e20;color:#fff}.balanced-100-bg,.balanced-100-bg.activated,.balanced-100-bg:active,.balanced-100-bg:hover,.balanced-100-border,.balanced-100-border.activated,.balanced-100-border:active,.balanced-100-border:hover,.bar .balanced-100-bg:hover,.bar .button-balanced-100,.bar .button-balanced-100.activated,.bar .button-balanced-100:active,.bar-balanced-100,.bar-balanced-100.activated,.bar-balanced-100:active,.bar-balanced-100:hover,.button-balanced-100,.button-balanced-100.activated,.button-balanced-100:active,.button-balanced-100:hover,.button-bar-balanced-100,.button-bar-balanced-100.activated,.button-bar-balanced-100:active,.button-bar-balanced-100:hover,.header-balanced-100,.header-balanced-100.activated,.header-balanced-100:active,.header-balanced-100:hover{background-color:#c8e6c9;color:#fff}.bar .button-energized,.bar .button-energized.activated,.bar .button-energized:active,.bar .button-energized:hover,.bar-energized,.bar-energized.activated,.bar-energized:active,.bar-energized:hover,.button-bar-energized,.button-bar-energized.activated,.button-bar-energized:active,.button-bar-energized:hover,.button-energized,.button-energized.activated,.button-energized:active,.button-energized:hover,.energized-bg,.energized-bg.activated,.energized-bg:active,.energized-bg:hover,.energized-border,.energized-border.activated,.energized-border:active,.energized-border:hover,.header-energized,.header-energized.activated,.header-energized:active,.header-energized:hover{background-color:#ff9800;color:#fff}.bar .button-energized-900,.bar .button-energized-900.activated,.bar .button-energized-900:active,.bar .button-energized-900:hover,.bar-energized-900,.bar-energized-900.activated,.bar-energized-900:active,.bar-energized-900:hover,.button-bar-energized-900,.button-bar-energized-900.activated,.button-bar-energized-900:active,.button-bar-energized-900:hover,.button-energized-900,.button-energized-900.activated,.button-energized-900:active,.button-energized-900:hover,.energized-900-bg,.energized-900-bg.activated,.energized-900-bg:active,.energized-900-bg:hover,.energized-900-border,.energized-900-border.activated,.energized-900-border:active,.energized-900-border:hover,.header-energized-900,.header-energized-900.activated,.header-energized-900:active,.header-energized-900:hover{background-color:#e65100;color:#fff}.bar .button-energized-100,.bar .button-energized-100.activated,.bar .button-energized-100:active,.bar .button-energized-100:hover,.bar-energized-100,.bar-energized-100.activated,.bar-energized-100:active,.bar-energized-100:hover,.button-bar-energized-100,.button-bar-energized-100.activated,.button-bar-energized-100:active,.button-bar-energized-100:hover,.button-energized-100,.button-energized-100.activated,.button-energized-100:active,.button-energized-100:hover,.energized-100-bg,.energized-100-bg.activated,.energized-100-bg:active,.energized-100-bg:hover,.energized-100-border,.energized-100-border.activated,.energized-100-border:active,.energized-100-border:hover,.header-energized-100,.header-energized-100.activated,.header-energized-100:active,.header-energized-100:hover,.modal.modal-help .activated.row.selected,.modal.modal-help .row.selected,.modal.modal-help .row.selected:active,.modal.modal-help .row.selected:hover{background-color:#ffe0b2}.assertive-bg,.assertive-bg.activated,.assertive-bg:active,.assertive-bg:hover,.assertive-border,.assertive-border.activated,.assertive-border:active,.assertive-border:hover,.bar .button-assertive,.bar .button-assertive.activated,.bar .button-assertive:active,.bar .button-assertive:hover,.bar-assertive,.bar-assertive.activated,.bar-assertive:active,.bar-assertive:hover,.button-assertive,.button-assertive.activated,.button-assertive:active,.button-assertive:hover,.button-bar-assertive,.button-bar-assertive.activated,.button-bar-assertive:active,.button-bar-assertive:hover,.header-assertive,.header-assertive.activated,.header-assertive:active,.header-assertive:hover{background-color:#f44336;color:#fff}.assertive-900-bg,.assertive-900-bg.activated,.assertive-900-bg:active,.assertive-900-bg:hover,.assertive-900-border,.assertive-900-border.activated,.assertive-900-border:active,.assertive-900-border:hover,.bar .button-assertive-900,.bar .button-assertive-900.activated,.bar .button-assertive-900:active,.bar .button-assertive-900:hover,.bar-assertive-900,.bar-assertive-900.activated,.bar-assertive-900:active,.bar-assertive-900:hover,.button-assertive-900,.button-assertive-900.activated,.button-assertive-900:active,.button-assertive-900:hover,.button-bar-assertive-900,.button-bar-assertive-900.activated,.button-bar-assertive-900:active,.button-bar-assertive-900:hover,.header-assertive-900,.header-assertive-900.activated,.header-assertive-900:active,.header-assertive-900:hover{background-color:#b71c1c;color:#fff}.assertive-100-bg,.assertive-100-bg.activated,.assertive-100-bg:active,.assertive-100-bg:hover,.assertive-100-border,.assertive-100-border.activated,.assertive-100-border:active,.assertive-100-border:hover,.bar .button-assertive-100,.bar .button-assertive-100.activated,.bar .button-assertive-100:active,.bar .button-assertive-100:hover,.bar-assertive-100,.bar-assertive-100.activated,.bar-assertive-100:active,.bar-assertive-100:hover,.button-assertive-100,.button-assertive-100.activated,.button-assertive-100:active,.button-assertive-100:hover,.button-bar-assertive-100,.button-bar-assertive-100.activated,.button-bar-assertive-100:active,.button-bar-assertive-100:hover,.header-assertive-100,.header-assertive-100.activated,.header-assertive-100:active,.header-assertive-100:hover{background-color:#ffcdd2;color:#fff}.bar .button-stable,.bar .button-stable.activated,.bar .button-stable:active,.bar .button-stable:hover,.bar-stable,.bar-stable.activated,.bar-stable:active,.bar-stable:hover,.button-bar-stable,.button-bar-stable.activated,.button-bar-stable:active,.button-bar-stable:hover,.button-stable,.button-stable.activated,.button-stable:active,.button-stable:hover,.header-stable,.header-stable.activated,.header-stable:active,.header-stable:hover,.stable-bg,.stable-bg.activated,.stable-bg:active,.stable-bg:hover,.stable-border,.stable-border.activated,.stable-border:active,.stable-border:hover{background-color:#e0e0e0;color:#fff}.icon-help,.icon-help *,.icon-help:active,.icon-help:active *,.icon-help:hover,.icon-help:hover *,.positive,.positive *,.positive:active,.positive:active *,.positive:hover,.positive:hover *,.text-editable:active:hover,.text-editable:active:hover *,.text-editable:hover,.text-editable:hover *{color:#3f51b5}.positive-900,.positive-900 *,.positive-900:active,.positive-900:active *,.positive-900:hover,.positive-900:hover *{color:#3f51b5}.positive-100,.positive-100 *,.positive-100:active,.positive-100:active *,.positive-100:hover,.positive-100:hover *{color:#c5cae9}.calm-100,.calm-100 *,.calm-100:active,.calm-100:active *,.calm-100:hover,.calm-100:hover *{color:#2196f3}.calm-900,.calm-900 *,.calm-900:active,.calm-900:active *,.calm-900:hover,.calm-900:hover *{color:#0d47a1}.calm-100,.calm-100 *,.calm-100:active,.calm-100:active *,.calm-100:hover,.calm-100:hover *{color:#bbdefb}.royal,.royal *,.royal:active,.royal:active *,.royal:hover,.royal:hover *{color:#673ab7}.royal-900,.royal-900 *,.royal-900:active,.royal-900:active *,.royal-900:hover,.royal-900:hover *{color:#311b92}.royal-100,.royal-100 *,.royal-100:active,.royal-100:active *,.royal-100:hover,.royal-100:hover *{color:#d1c4e9}.balanced,.balanced *,.balanced:active,.balanced:active *,.balanced:hover,.balanced:hover *{color:#4caf50}.balanced-900,.balanced-900 *,.balanced-900:active,.balanced-900:active *,.balanced-900:hover,.balanced-900:hover *{color:#1b5e20}.balanced-100,.balanced-100 *,.balanced-100:active,.balanced-100:active *,.balanced-100:hover,.balanced-100:hover *{color:#c8e6c9}.energized,.energized *,.energized:active,.energized:active *,.energized:hover,.energized:hover *{color:#ff9800}.energized-900,.energized-900 *,.energized-900:active,.energized-900:active *,.energized-900:hover,.energized-900:hover *{color:#e65100}.energized-100,.energized-100 *,.energized-100:active,.energized-100:active *,.energized-100:hover,.energized-100:hover *{color:#ffe0b2}.assertive,.assertive *,.assertive:active,.assertive:active *,.assertive:hover,.assertive:hover *,.icon-alert,.icon-alert *,.icon-alert:active,.icon-alert:active *,.icon-alert:hover,.icon-alert:hover *{color:#f44336}.assertive-900,.assertive-900 *,.assertive-900:active,.assertive-900:active *,.assertive-900:hover,.assertive-900:hover *{color:#b71c1c}.assertive-100,.assertive-100 *,.assertive-100:active,.assertive-100:active *,.assertive-100:hover,.assertive-100:hover *{color:#ffcdd2}.stable,.stable *,.stable:active,.stable:active *,.stable:hover,.stable:hover *{color:#e0e0e0}.light,.light *,.light:active,.light:active *,.light:hover,.light:hover *{color:#fff}.button-text-dark,.button-text-dark *,.button-text-dark:active,.button-text-dark:active *,.button-text-dark:hover,.button-text-dark:hover *,.dark,.dark *,.dark:active,.dark:active *,.dark:hover,.dark:hover *{color:#444}.light-border{border-color:#ddd}.navbar-default .navbar-nav>li>a{margin:0;padding-right:26px;padding-left:26px;border-top:3px solid transparent;color:#bfd5c9;opacity:1}.mid-bar{padding:16px}.mid-bar h1,.mid-bar h2,.mid-bar h3,.mid-bar h4,.mid-bar h5,.mid-bar h6{color:#fff;margin-bottom:5px}.mid-bar p{color:rgba(255,255,255,.5);margin-bottom:0}.card>.item-avatar,.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{padding-left:95px}.item,.item-complex .item-content,.item-radio .item-content{background-color:transparent}.dark-bg h2,.item.dark-bg h2{color:#fff}.tabs-striped .tabs{box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar .button.button-clear,.bar .button.button-text{color:#fff}#menu .footer .bar .button.button-icon .icon-help:before,.bar .button.button-icon #menu .footer .icon-help:before,.bar .button.button-icon .icon-alert:before,.bar .button.button-icon .icon-help:before,.bar .button.button-icon .icon:before,.bar .button.button-icon.icon-left:before,.bar .button.button-icon.icon-right:before,.bar .button.button-icon:before{vertical-align:top;font-size:24px}.menu{background-color:transparent}.button-icon.button.activated,.button-icon.button.active{opacity:initial}.popover{opacity:0;position:absolute;right:8px;transform:translate(50%,-50%) scale(0,0);transition:transform .3s ease-in-out,opacity .3s ease-in-out;top:8px}.popover.ng-enter{opacity:1;transform:translate(0,-14px) scale(1,1);transition:transform .3s ease-in-out,opacity .3s ease-in-out}.popover.ng-leave{opacity:0;transform:translate(50%,-50%) scale(0,0);transition:transform .3s ease-in-out,opacity .3s ease-in-out}.button{overflow:hidden!important}@font-face{font-family:Cesiumicons;src:url(../fonts/cesiumicons.eot?v=1.2);src:url(../fonts/cesiumicons.eot?v=1.2#iefix) format("embedded-opentype"),url(../fonts/cesiumicons.ttf?v=1.2) format("truetype"),url(../fonts/cesiumicons.woff?v=1.2) format("woff"),url(../fonts/cesiumicons.woff) format("woff"),url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiID4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8bWV0YWRhdGE+R2VuZXJhdGVkIGJ5IEljb01vb248L21ldGFkYXRhPgo8ZGVmcz4KPGZvbnQgaWQ9ImNlc2l1bWljb25zIiBob3Jpei1hZHYteD0iMTAyNCI+Cjxmb250LWZhY2UgdW5pdHMtcGVyLWVtPSIxMDI0IiBhc2NlbnQ9Ijk2MCIgZGVzY2VudD0iLTY0IiAvPgo8bWlzc2luZy1nbHlwaCBob3Jpei1hZHYteD0iMTAyNCIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeDIwOyIgaG9yaXotYWR2LXg9IjUxMiIgZD0iIiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwMDsiIGQ9Ik03MDQuNjMxIDU3MS4xMjhjLTg4LjYxMy0xNDEuNDA5LTIyMC40MDMtMjYzLjQwOC0zODUuNTIxLTMwNS40NzMtNjcuMjUyLTE4LjQ5My0xMzcuMTEyLTI1LjgyMi0yMDYuNzA1LTI3LjAyMiA4NS41NDktMTYzLjA5NSAyNzUuODEtMjYyLjI3MiA0NTguNTQ1LTIzNy45NSAxODEuMTY2IDE5LjA3NiAzNDEuNjYyIDE1Ny4yMTUgMzg4LjMzOCAzMzMuMTYyLTU0LjYwMSAxMDMuOTI0LTE0MS40OSAxOTcuODc0LTI1NC42NTYgMjM3LjI4M3oiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTAxOyIgZD0iTTcwNS45MzcgNTcyLjA4OGMtMTYuNzU2LTExMS44MTUtODUuMDg2LTIwNy4yLTEwNy4yNjctMzE3LjIyMS05LjE4OC01MS41NDEgMjYuNzg2LTExMC42NDItMTQuNTc5LTE1NS41MTQtNDYuMjEtNTIuNDAyLTExOC45MDctNjUuMzc5LTE4MS45MzgtODcuNDY2IDE3Ny43My00Ny45MSAzNzkuNjYgMjQuMjE1IDQ4NS45ODIgMTc0Ljc4IDUwLjU1IDY5LjExNiA4MC45OTIgMTUyLjY4OSA4Ni42OTYgMjM4LjEyNS00Ni4wODUgOS40ODMtNjkuNDM2IDU1LjAyMC0xMTAuNTU2IDc0LjIwMS00OS45MTcgMjkuOTkyLTEwMy41NzEgNTMuNTE0LTE1OC4zMzkgNzMuMDk1eiIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeGU5MDI7IiBkPSJNNzA0LjQyMiA1NjMuNGMtMjMuNzg2LTUxLjQwOC0yNi40MzYtMTA5Ljc1Ny01NC4wODQtMTU5LjcyNi03LjIxMS0zMi45MDktNDEuMDkxLTg0LjI4OC0yOS40OTgtMTA2LjQ4OSAxMDEuNTktMTYuNTQyIDIwMy4xODEtMzMuMDg1IDMwNC43NzEtNDkuNjI3IDE4LjI3OCAzNS42NDkgMzEuODQ1IDczLjcxMSA0MC4yMDEgMTEyLjg5NC03My44NjggNzkuMjY5LTE1MC40NzEgMTYzLjQyNi0yNTUuMzU4IDIwMC42MzVsLTYuMDMyIDIuMzE0eiIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeGU5MDM7IiBkPSJNNjY4LjYxNiA0NDUuNzk0Yy0yMC45ODMtMzEuNjc5LTI3LjI0NS03MC40MDgtNDQuMTA0LTEwNC40MjYtMTYuMjIxLTM1LjY4OS01MS40MTUtMTE5LjQ3MiAxOS42ODQtMTA5Ljg5IDUwLjQ1OSAyNC42NTQgOTUuMDUwLTEzLjM3OSAxNDUuODE5LTE2LjkyOSA0MC4zMTctNS41NjEgODIuMTM3LTQuNjY1IDEyMS4yOTUgNy4yMDEgMTQuOTgzIDMxLjcxNiA1MC42ODYgODIuNTk0IDM4LjcyNiAxMDguMzA1LTQ4LjU2MyA5Ljg2Ny05OS40NzMgMTMuODc5LTE0NS4yMTUgMzMuNjkgMTkuMjczIDQ1LjU5NS01NC45NzQgNTUuNDY1LTg5Ljk3NiA2OC44NC0xNS4zNDEgNC42MzctMzAuNzY1IDguOTk4LTQ2LjIyOSAxMy4yMDh6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwNDsiIGQ9Ik02MDcuNzE0IDE2MC44NzNjLTMwLjE4My04NS4wMDItMTIzLjE4Ni0xMTkuOTQ4LTIwMS44MzItMTQ1Ljk0MyA1LjAyMC0xMS4xODYgNzEuMTg2LTE2LjMyNSAxMDAuNzg3LTE3LjMyNiAxMTcuMTE1LTMuMDY3IDIzNC41NDIgNDEuMDg2IDMyMC40OCAxMjAuNzUyLTc0LjgzMSAyLjgzNC0xNDkuNTQ5IDE0Ljc4NC0yMTkuNDM1IDQyLjUxN3oiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTA1OyIgZD0iTTU5OC40ODUgMjY4LjUzNGMtNC4xNzQtNDIuNzY0LTI1LjE4OC0xMTUuOTM2IDM0LjAyOC0xMjguNDk0IDU4LjUzNy0xNC41ODEgMTE5LjQzNC0xOC41MTEgMTc3LjA2Ny0zNy4wMjAgNDUuMjAxIDM3LjQ0NyA4My4xNjcgODMuNTk5IDExMS4xMiAxMzUuMjE3LTEwNy45OC0xLjY4MS0yMTkuNDMxLTEwLjIwNC0zMjIuMjE1IDMwLjI5N3oiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTA2OyIgZD0iTTYwNy4yMSA2MDAuNzhjMTguOTU5IDIuMjkgMzUuMjM0IDEuODk2IDI4LjI4OC0yMS43MiA1LjkzNS0xNC42NDQtMzYuNjE0LTE0LjYwNy0yOC4yODggMS44NDEgMCA2LjYyNiAwIDEzLjI1MiAwIDE5Ljg3OXoiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTA3OyIgZD0iTTQ0NC41NDEgNzAyLjk2MmMyMS4wODggMy45NTggMzIuNjU0LTEuNjA0IDI2Ljk1NC0yNC40MzUtNS42NzMtMTEuMDcxLTM3LjY5Ny03LjY1LTI2Ljk1NCAxNC4wMzYgMCAzLjQ2NiAwIDYuOTMzIDAgMTAuMzk5eiIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeGU5MDg7IiBkPSJNNTA0LjUzMiA2ODEuNzhjMTMuNDc4LTMuMjk4IDQzLjIzNiA5LjY4MiAzNi43NTUtMTMuNTc1IDYuMjU0LTIzLjAzMC03LjA1Ny0yNi40OTYtMjcuMTUtMjMuMTgtMTguNTY3LTUuNDk2LTUuODcxIDI2LjUyNy05LjYwNSAzNi43NTV6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwOTsiIGQ9Ik01MDIuNTM5IDQxNy40MjZjMTguNzg2IDAgMzcuNTcyIDAgNTYuMzU4IDAgMC0xOC43ODYgMC0zNy41NzIgMC01Ni4zNTgtMTguNzg2IDAtMzcuNTcyIDAtNTYuMzU4IDAgMCAxOC43ODYgMCAzNy41NzIgMCA1Ni4zNTh6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwYTsiIGQ9Ik01MDguODU2IDYzMC4xNTdjMTMuNDc4LTMuMjk4IDQzLjIzNiA5LjY4MiAzNi43NTUtMTMuNTc1IDYuMjU0LTIzLjAzMC03LjA1Ny0yNi40OTYtMjcuMTUtMjMuMTgtMTguNTY3LTUuNDk2LTUuODcxIDI2LjUyNy05LjYwNSAzNi43NTV6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwYjsiIGQ9Ik01NjkuMTAzIDQ3NC4xNGMxOC45NyAxLjkyOSAzNi40OTIgMi40MDkgMjkuNDA0LTIxLjcyIDYuODk0LTE1LjkzMi0zNy4yMzUtMTUuODMzLTI5LjQwNCAwLjcyNSAwIDYuOTk4IDAgMTMuOTk2IDAgMjAuOTk0eiIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeGU5MGM7IiBkPSJNNjI3LjA4NyA1MzEuNDAzYzE5LjM1IDcuODY5IDI5LjQwOC05LjU4MiAxOS4zMzgtMjIuMDUzLTIxLjU4My00LjE0Ny0yMC44MDEgMy4zODctMTkuMzM4IDIyLjA1M3oiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTBkOyIgZD0iTTU0Ny42MjcgNTI1LjIzMWMxMy40NzgtMy4yOTggNDMuMjM2IDkuNjgyIDM2Ljc1NS0xMy41NzUgNi4yNTQtMjMuMDMwLTcuMDU3LTI2LjQ5Ni0yNy4xNS0yMy4xOC0xOC41NjctNS40OTYtNS44NzEgMjYuNTI3LTkuNjA1IDM2Ljc1NXoiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTBlOyIgZD0iTTQwMy44MDIgMzM1LjAyNGMxNC40MjYtMS45OTggMzYuNzMgMy44ODIgNDYuNTU2LTIuNzE1LTIuMDIwLTE0LjMxNSAzLjkxMy0zNi41ODQtMi43MTUtNDYuMjkyLTEyLjg3OSAzLjU0NS00MC4wMTctNy4xNjktNDMuODQxIDUuNDMgMCAxNC41MjYgMCAyOS4wNTEgMCA0My41Nzd6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkwZjsiIGQ9Ik00NDcuOTA3IDQwNi4wODRjMTYuODM2LTAuMTE3IDM5LjY3NyA1Ljc3IDMxLjg1NC0xOS4wMDUgNy44Mi0yNC4zNTUtMTYuMDgwLTE2Ljk5LTMxLjg1NC0xNy43NSAwIDEyLjI1MiAwIDI0LjUwMyAwIDM2Ljc1NXoiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTEwOyIgZD0iTTUxNS4yOTEgNDY4LjU2N2MtMTguOTcxIDEuODk0LTM2LjYxMiAyLjQ1OS0yOS41MS0yMS43Mi0yLjUzOC0xMi45OSAzOS42MjctMTMuMzc0IDI5LjUxIDUuODkxIDAgNS4yNzYgMCAxMC41NTMgMCAxNS44Mjl6IiAvPgo8Z2x5cGggdW5pY29kZT0iJiN4ZTkxMTsiIGQ9Ik01NzguNDg2IDU3Mi44NjZjMjEuMjMyIDQuOTIgMjkuNDY5LTMuMTU2IDI0LjUwMy0yNC40MzUtMTMuMTA0LTguNTMyLTMyLjk1NS0yLjEwNi0yNC41MDMgMTkuMjAxdjUuMjM0eiIgLz4KPGdseXBoIHVuaWNvZGU9IiYjeGU5MTI7IiBkPSJNNjAxLjQ3MSA2NDEuNjg5Yy0xOC45NzEgMS44OTQtMzYuNjEyIDIuNDU5LTI5LjUxLTIxLjcyLTIuNTM4LTEyLjk5IDM5LjYyNy0xMy4zNzQgMjkuNTEgNS44OTEgMCA1LjI3NiAwIDEwLjU1MyAwIDE1LjgyOXoiIC8+CjxnbHlwaCB1bmljb2RlPSImI3hlOTE1OyIgZ2x5cGgtbmFtZT0iZGlhc3BvcmEiIGhvcml6LWFkdi14PSIxMDY0IiBkPSJNNjcwLjEgMjIuMTA5Yy0yOC42OTIgNDAuMDQ2LTczLjQ1OSAxMDIuNTcxLTk5LjQ4MiAxMzguOTQ1LTI2LjU3OSAzNy4xNTEtNDguMjAyIDY2LjE0Ni00OS4zNCA2Ni4xNjEtMS4xNjkgMC4wMTUtNDIuOTg2LTU2LjE5Ni05OC45MTItMTMyLjk2MS01My4yODgtNzMuMTQzLTk3LjMzLTEzMi45ODctOTcuODcyLTEzMi45ODctMS41MTYgMC0xOTIuMTE0IDEzNC4yNS0xOTIuNjA1IDEzNS42NjMtMC4yMzcgMC42ODQgNDIuODUgNjMuOTM1IDk1Ljc1MSAxNDAuNTU5czk2LjE4MiAxNDAuNTIzIDk2LjE4MiAxNDEuOTk5YzAgMi4zOC0xNy4xNDIgOC4zOTgtMTUxLjYwNSA1My4yMjYtODMuMzgzIDI3Ljc5OC0xNTIuNDIyIDUwLjg2MS0xNTMuNDIgNTEuMjUxLTEuMzg4IDAuNTQyIDYuNTUgMjcuMTAzIDMzLjc4MyAxMTMuMDMyIDE5LjU3OCA2MS43NzggMzYuMDQwIDExMi44MjggMzYuNTgxIDExMy40NDRzNzMuMDExLTIyLjU3NCAxNjEuMDQzLTUxLjUzNGM4OC4wMzMtMjguOTYgMTYwLjc5Ni01Mi42NTQgMTYxLjY5Ni01Mi42NTNzMS45MTkgMS4zNDggMi4yNjMgMi45OTRjMC4zNDQgMS42NDYgMS4xMDQgNzYuNjAxIDEuNjg4IDE2Ni41NjZzMS41NDYgMTY0LjMyMiAyLjEzNyAxNjUuMjM2YzAuODQ3IDEuMzA5IDI1LjU3NiAxLjY1OCAxMTYuMzY0IDEuNjQyIDYzLjQwOC0wLjAxMSAxMTUuOTQ4LTAuNDYgMTE2Ljc1Ni0wLjk5NyAxLjAxOC0wLjY3NyAyLjc1Ny01MC4xMzggNS42Ny0xNjEuMjI2IDQuNzgzLTE4Mi40MDggNC44ODYtMTg0Ljg1MiA3Ljc5NS0xODQuODUyIDEuMTI4IDAgNzAuODk2IDIzLjM1MyAxNTUuMDQxIDUxLjg5NnMxNTMuNCA1MS40MzMgMTUzLjkwMSA1MC44NjhjMS43LTEuOTE4IDcwLjcxNS0yMjYuNjAyIDY5Ljg2NS0yMjcuNDUxLTAuNDY0LTAuNDY0LTcwLjY5LTI0LjUxNC0xNTYuMDU2LTUzLjQ0NC0xMTcuNDMyLTM5Ljc5Ny0xNTUuMzE1LTUzLjE0My0xNTUuNjMzLTU0LjgyNy0wLjIzNS0xLjI0NCA0MC4xNDktNjEuNTk0IDkxLjQ5OS0xMzYuNzM3IDUwLjU1NS03My45ODEgOTEuNzMzLTEzNS4wNjIgOTEuNTA3LTEzNS43MzctMC41MjEtMS41NDktMTg5LjY4MS0xNDAuODg0LTE5MS4yNjMtMTQwLjg4NC0wLjY0MiAwLTI0LjY0MyAzMi43NjUtNTMuMzM1IDcyLjgxeiIgLz4KPC9mb250PjwvZGVmcz48L3N2Zz4=) format("svg");font-weight:400;font-style:normal}.cesiumicons,.cion,.ion-library:before,.ion-office:before,.ion-social-diaspora:before,.ion-social-duniter:before{display:inline-block;font-family:Cesiumicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ion-social-duniter:before{content:""}.ion-social-diaspora:before{content:""}.ion-office:before{content:""}.ion-library:before{content:""}.digit-keyboard{position:absolute;left:0;right:0;bottom:0;background:0 0;font-size:24px;z-index:5000}.digit-keyboard *{box-sizing:border-box}.digit-keyboard .digit-keyboard-row{display:flex;flex-direction:row;border-bottom:1px solid #333}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper{flex:1;text-align:center;position:relative;height:60px}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key{display:block;margin:0 auto;position:absolute;left:0;top:0;right:0;bottom:0;border-right:1px solid #333;border-left:1px solid #333;line-height:60px;-webkit-transition:background-color .1s linear;-moz-transition:background-color .1s linear;-o-transition:background-color .1s linear;-ms-transition:background-color .1s linear;transition:background-color .1s linear}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number{font-size:1em;vertical-align:middle;display:inline-block;line-height:normal;text-align:center;margin-top:-.4em}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters{font-size:9.6px;line-height:9.6px;height:9.6px;margin-top:-.25em}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters.hidden{visibility:hidden}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-action{position:absolute;left:0;top:0;right:0;bottom:0;line-height:60px;font-size:24px}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper.hidden{visibility:hidden}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper:first-child .digit-keyboard-key{border-right:none}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper:last-child .digit-keyboard-key{border-left:none}.digit-keyboard .digit-keyboard-row:first-child{border-top:1px solid #333}.digit-keyboard .digit-keyboard-row:last-child{border:none}.digit-keyboard .digit-keyboard-row:last-child .digit-keyboard-key-wrapper .digit-keyboard-key{border-bottom:1px solid #333}.digit-keyboard.align-center{margin:0 auto}.digit-keyboard.align-left{margin-right:auto}.digit-keyboard.align-right{margin-left:auto}.digit-keyboard.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number{margin-top:-.3em}.digit-keyboard.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters{display:none}.digit-keyboard.round-buttons .digit-keyboard-row{border:none}.digit-keyboard.round-buttons .digit-keyboard-row .digit-keyboard-key-wrapper{margin:10px 0 0 0}.digit-keyboard.round-buttons .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key{width:60px;-webkit-border-radius:100%;-moz-border-radius:100%;border-radius:100%;border:1px solid #333}.digit-keyboard.round-buttons .digit-keyboard-row:last-child .digit-keyboard-key-wrapper{margin-bottom:10px}.digit-keyboard.round-buttons.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number{height:57.6px;line-height:57.6px}.digit-keyboard.keyboard-light *{border-color:#e6e6e6!important}.digit-keyboard.keyboard-light .digit-keyboard-key{background:#fff;color:#444}.digit-keyboard.keyboard-light .digit-keyboard-key.activated{background:#e6e6e6}.digit-keyboard.keyboard-stable *{border-color:#dfdfdf!important}.digit-keyboard.keyboard-stable .digit-keyboard-key{background:#f8f8f8;color:#444}.digit-keyboard.keyboard-stable .digit-keyboard-key.activated{background:#dfdfdf}.digit-keyboard.keyboard-positive *{border-color:#0c60ee!important}.digit-keyboard.keyboard-positive .digit-keyboard-key{background:#387ef5;color:#fff}.digit-keyboard.keyboard-positive .digit-keyboard-key.activated{background:#0c60ee}.digit-keyboard.keyboard-calm *{border-color:#0a9dc7!important}.digit-keyboard.keyboard-calm .digit-keyboard-key{background:#11c1f3;color:#fff}.digit-keyboard.keyboard-calm .digit-keyboard-key.activated{background:#0a9dc7}.digit-keyboard.keyboard-balanced *{border-color:#28a54c!important}.digit-keyboard.keyboard-balanced .digit-keyboard-key{background:#33cd5f;color:#fff}.digit-keyboard.keyboard-balanced .digit-keyboard-key.activated{background:#28a54c}.digit-keyboard.keyboard-energized *{border-color:#e6b500!important}.digit-keyboard.keyboard-energized .digit-keyboard-key{background:#ffc900;color:#fff}.digit-keyboard.keyboard-energized .digit-keyboard-key.activated{background:#e6b500}.digit-keyboard.keyboard-assertive *{border-color:#e42112!important}.digit-keyboard.keyboard-assertive .digit-keyboard-key{background:#ef473a;color:#fff}.digit-keyboard.keyboard-assertive .digit-keyboard-key.activated{background:#e42112}.digit-keyboard.keyboard-royal *{border-color:#6b46e5!important}.digit-keyboard.keyboard-royal .digit-keyboard-key{background:#886aea;color:#fff}.digit-keyboard.keyboard-royal .digit-keyboard-key.activated{background:#6b46e5}.digit-keyboard.keyboard-dark *{border-color:#2b2b2b!important}.digit-keyboard.keyboard-dark .digit-keyboard-key{background:#444;color:#fff}.digit-keyboard.keyboard-dark .digit-keyboard-key.activated{background:#2b2b2b}.digit-keyboard.keyboard-opaque-black *{border-color:rgba(0,0,0,.75)!important}.digit-keyboard.keyboard-opaque-black .digit-keyboard-key{background:rgba(0,0,0,.15);color:rgba(0,0,0,.75)}.digit-keyboard.keyboard-opaque-black .digit-keyboard-key.activated{background:rgba(0,0,0,.25)}.digit-keyboard.keyboard-opaque-white *{border-color:rgba(255,255,255,.75)!important}.digit-keyboard.keyboard-opaque-white .digit-keyboard-key{background:rgba(255,255,255,.15);color:rgba(255,255,255,.75)}.digit-keyboard.keyboard-opaque-white .digit-keyboard-key.activated{background:rgba(255,255,255,.25)}.digit-keyboard.animation-slide-up{-webkit-transition:transform linear 150ms;transition:transform linear 150ms;transform:translate3d(0,0,0)}.digit-keyboard.animation-slide-up.ng-hide{transform:translate3d(0,100%,0)}.digit-keyboard.animation-pop{-webkit-transition:transform linear 150ms;transition:transform linear 150ms;transform:scale3d(1,1,1)}.digit-keyboard.animation-pop.ng-hide{transform:scale3d(0,0,1)}@media screen and (max-width:400px){@-ms-viewport{width:320px}}@media screen and (max-width:767px){.hidden-xs{display:none!important;visibility:hidden!important}.padding-top-xs{padding-top:10px}}@media screen and (min-width:768px){.hidden-xs{display:inherit;visibility:visible}.row.hidden-xs{display:flex!important}.button.hidden-xs{display:inline-block}}@media screen and (max-width:767px){.visible-xs{display:inherit!important;visibility:visible!important}.button.visible-xs{display:inline-block!important}}@media screen and (min-width:768px){.visible-xs{display:none!important;visibility:hidden!important}}@media screen and (max-width:767px){.padding-xs{padding:16px!important}.no-padding-xs{padding:0!important}.no-margin-xs{margin:0!important}}@media screen and (min-width:768px) and (max-width:991px){.hidden-sm,.row-header.hidden-sm,.row.hidden-sm{display:none!important;visibility:hidden!important}.badge{text-overflow:ellipsis!important;white-space:nowrap;overflow:hidden!important;max-width:400px!important;display:inline-block!important}.badge:empty{display:none!important}.padding-sm{padding:16px!important}.no-padding-sm{padding:0!important}.no-margin-sm{margin:0!important}}@media screen and (min-width:768px){.item-toggle .toggle{right:32px}}@media screen and (min-width:992px){.hidden-sm{display:inherit;visibility:visible}.row.hidden-sm{display:flex!important}.button.hidden-sm{display:flex}#menu .footer .popover-helptip .icon-bottom-center.icon-help .button.hidden-sm,#menu .footer .popover-helptip .icon-bottom-left.icon-help .button.hidden-sm,#menu .footer .popover-helptip .icon-bottom-right.icon-help .button.hidden-sm,#menu .footer .popover-helptip .icon-center.icon-help .button.hidden-sm,#menu .footer .popover-helptip .icon-left.icon-help .button.hidden-sm,#menu .footer .popover-helptip .icon-right.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-bottom-center.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-bottom-left.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-bottom-right.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-center.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-left.icon-help .button.hidden-sm,.popover-helptip #menu .footer .icon-right.icon-help .button.hidden-sm,.popover-helptip .icon-bottom-center.icon-alert .button.hidden-sm,.popover-helptip .icon-bottom-center.icon-help .button.hidden-sm,.popover-helptip .icon-bottom-left.icon-alert .button.hidden-sm,.popover-helptip .icon-bottom-left.icon-help .button.hidden-sm,.popover-helptip .icon-bottom-right.icon-alert .button.hidden-sm,.popover-helptip .icon-bottom-right.icon-help .button.hidden-sm,.popover-helptip .icon-center.icon-alert .button.hidden-sm,.popover-helptip .icon-center.icon-help .button.hidden-sm,.popover-helptip .icon-left.icon-alert .button.hidden-sm,.popover-helptip .icon-left.icon-help .button.hidden-sm,.popover-helptip .icon-right.icon-alert .button.hidden-sm,.popover-helptip .icon-right.icon-help .button.hidden-sm,.popover-helptip .icon.icon-bottom-center .button.hidden-sm,.popover-helptip .icon.icon-bottom-left .button.hidden-sm,.popover-helptip .icon.icon-bottom-right .button.hidden-sm,.popover-helptip .icon.icon-center .button.hidden-sm,.popover-helptip .icon.icon-left .button.hidden-sm,.popover-helptip .icon.icon-right .button.hidden-sm,.pull-left .button.hidden-sm,.pull-right .button.hidden-sm{display:inline-block}}@media screen and (max-width:767px){.hidden-sm{display:inherit;visibility:visible}}@media screen and (max-width:991px){.visible-sm{display:inherit!important;visibility:visible!important}.button.visible-sm{display:inline-block!important}}@media screen and (min-width:992px){.visible-sm{display:none;visibility:hidden}}@media screen and (max-width:767px){.visible-sm{display:none;visibility:hidden}}@media screen and (max-width:991px){body{cursor:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAEbSURBVDiNndMxK4ZRGMbx3zmRMrwvM2XCQFFik/IJpCw+hJLPgfIhLBY+gEEGJQPFwGZg9TIoBrfhOfSQHl7XeM7/fw3nvk+KCPWklEawgGlMlOMrnOMoIm6/8B8FKaWMFazhGQ94LFwbg+jHDvYi4u2zIKWUsIk5XNfE72ljHKfYiIjI5WIZMzhrkJW7s8IuQ8IwdnGDpwa5nhbGsJqxiNcuZIV9xWJWvXY3cr1kOmMSnX8UdDCZEb+RDYmMS9WMu80gLrNqw1r/KGjhPOMQvaol+Wva6MFhjoh7bGEUuVGrkgu7HRH3H8IBTjCLgQZ5oDAnxfnymRKWsI4X1Zw7NbGFPmxjP4qYfvjOQ5jHlGpHqCZ1geOIuKvz76QSW1T3cwmnAAAAAElFTkSuQmCC),auto}}@media screen and (min-width:992px){body{cursor:inherit}}@media screen and (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important;visibility:hidden!important}.badge{text-overflow:ellipsis!important;white-space:nowrap;overflow:hidden!important;max-width:400px!important;display:block!important}.badge:empty{display:none!important}}@media screen and (min-width:1200px){.hidden-md{display:inherit;visibility:visible}}@media screen and (max-width:991px){.hidden-md{display:inherit;visibility:visible}}@media screen and (min-width:992px) and (max-width:1199px){.visible-md{display:inherit!important;visibility:visible!important}}@media screen and (min-width:1200px){.visible-md{display:none;visibility:hidden}}@media screen and (max-width:991px){.visible-md{display:none;visibility:hidden}}@media screen and (min-width:1200px){.hidden-lg{display:none!important;visibility:hidden!important}.visible-lg{display:inherit!important;visibility:visible!important}.badge{text-overflow:ellipsis!important;white-space:nowrap;overflow:hidden!important;max-width:450px!important;display:block!important}.badge:empty{display:none!important}}@media screen and (max-width:1199px){.hidden-lg{display:inherit;visibility:visible}}@media screen and (max-width:1199px){.visible-lg{display:none;visibility:hidden}}@media screen and (max-width:768px){.no-padding-xs{padding:inherit}}@media screen and (max-width:767px){.no-margin-xs{margin:0!important}}@media screen and (min-width:992px){.disable-user-behavior,.scroll,body,html{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important;-webkit-touch-callout:default!important;-webkit-tap-highlight-color:#387ef5;-webkit-user-drag:none!important;touch-action:auto!important;-ms-touch-action:auto!important;-ms-content-zooming:none!important}}@media screen and (max-width:844px){.hidden-nomenu{display:none!important;visibility:hidden!important}.visible-nomenu{display:inherit!important;visibility:visible!important}}@media screen and (min-width:845px){.hidden-nomenu{display:inherit;visibility:visible}.visible-nomenu{display:none!important;visibility:hidden!important}}@media screen and (min-width:845px){.hidden-menu{display:none!important;visibility:hidden!important}.visible-menu{display:inherit!important;visibility:visible!important}}@media screen and (max-width:844px){.hidden-menu{display:inherit;visibility:visible}.visible-menu{display:none;visibility:hidden}}body,html{position:absolute;top:0;left:0;height:100%;width:100%}.item.item-icon-right .item-select select,.item.item-icon-right.item-select select{right:48px;padding:0 20px 0 16px}.item.item-icon-right .item-select:after,.item.item-icon-right.item-select:after{right:56px}#unitPopover .item.selected,.popover-unit .item.selected{background-color:#f8f8f8}@media (max-width:767px){.popover-share{width:auto}}.ios ion-content{pointer-events:auto}.popover-share{height:110px}.popover-share .bar{box-shadow:none!important}.popover-share .bar-header{height:20px}.popover-share .bar-header .title{font-size:12px;font-weight:700;height:20px;line-height:19px;max-width:260px;margin:0 5px;text-align:left}.popover-share .bar-header span{font-size:10px;height:20px;position:absolute;right:0;top:0;margin:0 5px;display:block}.popover-share .has-header{top:20px}.popover-share .has-footer{bottom:40px}.popover-share .bar-footer{color:#387ef5;height:40px}.popover-share .bar-footer .button-icon{padding:0 5px}.popover-share .bar-footer .button-close{position:absolute;right:0;bottom:0}.popover-share .item{padding:5px}.popover-share .item input{border:1px solid grey;border-radius:3px;box-shadow:inset 0 1px 1px rgba(0,0,0,.3)}.popover-share .item input:focus{border-color:#387ef5;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.3),0 0 8px #08c}.popover-share .list .item{border-bottom:0!important}.popover-light .bar-footer,.popover-light .bar-header,.popover-notification .bar-footer,.popover-notification .bar-header{height:30px}.popover-light .bar-footer .title,.popover-light .bar-header .title,.popover-notification .bar-footer .title,.popover-notification .bar-header .title{color:#000;text-align:left;left:0!important;font-size:14px;line-height:30px}#menu .footer .popover-helptip .popover-light .bar-footer .icon-bottom-center.icon-help,#menu .footer .popover-helptip .popover-light .bar-footer .icon-bottom-right.icon-help,#menu .footer .popover-helptip .popover-light .bar-footer .icon-center.icon-help,#menu .footer .popover-helptip .popover-light .bar-footer .icon-right.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-bottom-center.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-bottom-right.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-center.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-right.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-bottom-center.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-bottom-right.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-center.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-right.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-bottom-center.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-bottom-right.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-center.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-right.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-bottom-center.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-bottom-right.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-center.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-right.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-bottom-center.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-bottom-right.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-center.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-right.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-bottom-center.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-bottom-right.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-center.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-right.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-bottom-center.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-bottom-right.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-center.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-right.icon-help,.popover-helptip .popover-light .bar-footer .icon-bottom-center.icon-alert,.popover-helptip .popover-light .bar-footer .icon-bottom-center.icon-help,.popover-helptip .popover-light .bar-footer .icon-bottom-right.icon-alert,.popover-helptip .popover-light .bar-footer .icon-bottom-right.icon-help,.popover-helptip .popover-light .bar-footer .icon-center.icon-alert,.popover-helptip .popover-light .bar-footer .icon-center.icon-help,.popover-helptip .popover-light .bar-footer .icon-right.icon-alert,.popover-helptip .popover-light .bar-footer .icon-right.icon-help,.popover-helptip .popover-light .bar-footer .icon.icon-bottom-center,.popover-helptip .popover-light .bar-footer .icon.icon-bottom-right,.popover-helptip .popover-light .bar-footer .icon.icon-center,.popover-helptip .popover-light .bar-footer .icon.icon-right,.popover-helptip .popover-light .bar-header .icon-bottom-center.icon-alert,.popover-helptip .popover-light .bar-header .icon-bottom-center.icon-help,.popover-helptip .popover-light .bar-header .icon-bottom-right.icon-alert,.popover-helptip .popover-light .bar-header .icon-bottom-right.icon-help,.popover-helptip .popover-light .bar-header .icon-center.icon-alert,.popover-helptip .popover-light .bar-header .icon-center.icon-help,.popover-helptip .popover-light .bar-header .icon-right.icon-alert,.popover-helptip .popover-light .bar-header .icon-right.icon-help,.popover-helptip .popover-light .bar-header .icon.icon-bottom-center,.popover-helptip .popover-light .bar-header .icon.icon-bottom-right,.popover-helptip .popover-light .bar-header .icon.icon-center,.popover-helptip .popover-light .bar-header .icon.icon-right,.popover-helptip .popover-notification .bar-footer .icon-bottom-center.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-bottom-center.icon-help,.popover-helptip .popover-notification .bar-footer .icon-bottom-right.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-bottom-right.icon-help,.popover-helptip .popover-notification .bar-footer .icon-center.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-center.icon-help,.popover-helptip .popover-notification .bar-footer .icon-right.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-right.icon-help,.popover-helptip .popover-notification .bar-footer .icon.icon-bottom-center,.popover-helptip .popover-notification .bar-footer .icon.icon-bottom-right,.popover-helptip .popover-notification .bar-footer .icon.icon-center,.popover-helptip .popover-notification .bar-footer .icon.icon-right,.popover-helptip .popover-notification .bar-header .icon-bottom-center.icon-alert,.popover-helptip .popover-notification .bar-header .icon-bottom-center.icon-help,.popover-helptip .popover-notification .bar-header .icon-bottom-right.icon-alert,.popover-helptip .popover-notification .bar-header .icon-bottom-right.icon-help,.popover-helptip .popover-notification .bar-header .icon-center.icon-alert,.popover-helptip .popover-notification .bar-header .icon-center.icon-help,.popover-helptip .popover-notification .bar-header .icon-right.icon-alert,.popover-helptip .popover-notification .bar-header .icon-right.icon-help,.popover-helptip .popover-notification .bar-header .icon.icon-bottom-center,.popover-helptip .popover-notification .bar-header .icon.icon-bottom-right,.popover-helptip .popover-notification .bar-header .icon.icon-center,.popover-helptip .popover-notification .bar-header .icon.icon-right,.popover-light .bar-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help,.popover-light .bar-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help,.popover-light .bar-footer #menu .footer .popover-helptip .icon-center.icon-help,.popover-light .bar-footer #menu .footer .popover-helptip .icon-right.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-center.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-right.icon-help,.popover-light .bar-footer .popover-helptip .icon-bottom-center.icon-alert,.popover-light .bar-footer .popover-helptip .icon-bottom-center.icon-help,.popover-light .bar-footer .popover-helptip .icon-bottom-right.icon-alert,.popover-light .bar-footer .popover-helptip .icon-bottom-right.icon-help,.popover-light .bar-footer .popover-helptip .icon-center.icon-alert,.popover-light .bar-footer .popover-helptip .icon-center.icon-help,.popover-light .bar-footer .popover-helptip .icon-right.icon-alert,.popover-light .bar-footer .popover-helptip .icon-right.icon-help,.popover-light .bar-footer .popover-helptip .icon.icon-bottom-center,.popover-light .bar-footer .popover-helptip .icon.icon-bottom-right,.popover-light .bar-footer .popover-helptip .icon.icon-center,.popover-light .bar-footer .popover-helptip .icon.icon-right,.popover-light .bar-footer .pull-right,.popover-light .bar-header #menu .footer .popover-helptip .icon-bottom-center.icon-help,.popover-light .bar-header #menu .footer .popover-helptip .icon-bottom-right.icon-help,.popover-light .bar-header #menu .footer .popover-helptip .icon-center.icon-help,.popover-light .bar-header #menu .footer .popover-helptip .icon-right.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-center.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-right.icon-help,.popover-light .bar-header .popover-helptip .icon-bottom-center.icon-alert,.popover-light .bar-header .popover-helptip .icon-bottom-center.icon-help,.popover-light .bar-header .popover-helptip .icon-bottom-right.icon-alert,.popover-light .bar-header .popover-helptip .icon-bottom-right.icon-help,.popover-light .bar-header .popover-helptip .icon-center.icon-alert,.popover-light .bar-header .popover-helptip .icon-center.icon-help,.popover-light .bar-header .popover-helptip .icon-right.icon-alert,.popover-light .bar-header .popover-helptip .icon-right.icon-help,.popover-light .bar-header .popover-helptip .icon.icon-bottom-center,.popover-light .bar-header .popover-helptip .icon.icon-bottom-right,.popover-light .bar-header .popover-helptip .icon.icon-center,.popover-light .bar-header .popover-helptip .icon.icon-right,.popover-light .bar-header .pull-right,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-center.icon-help,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-right.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-center.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-right.icon-help,.popover-notification .bar-footer .popover-helptip .icon-bottom-center.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-bottom-center.icon-help,.popover-notification .bar-footer .popover-helptip .icon-bottom-right.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-bottom-right.icon-help,.popover-notification .bar-footer .popover-helptip .icon-center.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-center.icon-help,.popover-notification .bar-footer .popover-helptip .icon-right.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-right.icon-help,.popover-notification .bar-footer .popover-helptip .icon.icon-bottom-center,.popover-notification .bar-footer .popover-helptip .icon.icon-bottom-right,.popover-notification .bar-footer .popover-helptip .icon.icon-center,.popover-notification .bar-footer .popover-helptip .icon.icon-right,.popover-notification .bar-footer .pull-right,.popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-center.icon-help,.popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-right.icon-help,.popover-notification .bar-header #menu .footer .popover-helptip .icon-center.icon-help,.popover-notification .bar-header #menu .footer .popover-helptip .icon-right.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-center.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-right.icon-help,.popover-notification .bar-header .popover-helptip .icon-bottom-center.icon-alert,.popover-notification .bar-header .popover-helptip .icon-bottom-center.icon-help,.popover-notification .bar-header .popover-helptip .icon-bottom-right.icon-alert,.popover-notification .bar-header .popover-helptip .icon-bottom-right.icon-help,.popover-notification .bar-header .popover-helptip .icon-center.icon-alert,.popover-notification .bar-header .popover-helptip .icon-center.icon-help,.popover-notification .bar-header .popover-helptip .icon-right.icon-alert,.popover-notification .bar-header .popover-helptip .icon-right.icon-help,.popover-notification .bar-header .popover-helptip .icon.icon-bottom-center,.popover-notification .bar-header .popover-helptip .icon.icon-bottom-right,.popover-notification .bar-header .popover-helptip .icon.icon-center,.popover-notification .bar-header .popover-helptip .icon.icon-right,.popover-notification .bar-header .pull-right{margin-right:10px}#menu .footer .popover-helptip .popover-light .bar-footer .icon-bottom-left.icon-help,#menu .footer .popover-helptip .popover-light .bar-footer .icon-left.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-bottom-left.icon-help,#menu .footer .popover-helptip .popover-light .bar-header .icon-left.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-bottom-left.icon-help,#menu .footer .popover-helptip .popover-notification .bar-footer .icon-left.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-bottom-left.icon-help,#menu .footer .popover-helptip .popover-notification .bar-header .icon-left.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-bottom-left.icon-help,.popover-helptip #menu .footer .popover-light .bar-footer .icon-left.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-bottom-left.icon-help,.popover-helptip #menu .footer .popover-light .bar-header .icon-left.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-bottom-left.icon-help,.popover-helptip #menu .footer .popover-notification .bar-footer .icon-left.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-bottom-left.icon-help,.popover-helptip #menu .footer .popover-notification .bar-header .icon-left.icon-help,.popover-helptip .popover-light .bar-footer .icon-bottom-left.icon-alert,.popover-helptip .popover-light .bar-footer .icon-bottom-left.icon-help,.popover-helptip .popover-light .bar-footer .icon-left.icon-alert,.popover-helptip .popover-light .bar-footer .icon-left.icon-help,.popover-helptip .popover-light .bar-footer .icon.icon-bottom-left,.popover-helptip .popover-light .bar-footer .icon.icon-left,.popover-helptip .popover-light .bar-header .icon-bottom-left.icon-alert,.popover-helptip .popover-light .bar-header .icon-bottom-left.icon-help,.popover-helptip .popover-light .bar-header .icon-left.icon-alert,.popover-helptip .popover-light .bar-header .icon-left.icon-help,.popover-helptip .popover-light .bar-header .icon.icon-bottom-left,.popover-helptip .popover-light .bar-header .icon.icon-left,.popover-helptip .popover-notification .bar-footer .icon-bottom-left.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-bottom-left.icon-help,.popover-helptip .popover-notification .bar-footer .icon-left.icon-alert,.popover-helptip .popover-notification .bar-footer .icon-left.icon-help,.popover-helptip .popover-notification .bar-footer .icon.icon-bottom-left,.popover-helptip .popover-notification .bar-footer .icon.icon-left,.popover-helptip .popover-notification .bar-header .icon-bottom-left.icon-alert,.popover-helptip .popover-notification .bar-header .icon-bottom-left.icon-help,.popover-helptip .popover-notification .bar-header .icon-left.icon-alert,.popover-helptip .popover-notification .bar-header .icon-left.icon-help,.popover-helptip .popover-notification .bar-header .icon.icon-bottom-left,.popover-helptip .popover-notification .bar-header .icon.icon-left,.popover-light .bar-footer #menu .footer .popover-helptip .icon-bottom-left.icon-help,.popover-light .bar-footer #menu .footer .popover-helptip .icon-left.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-light .bar-footer .popover-helptip #menu .footer .icon-left.icon-help,.popover-light .bar-footer .popover-helptip .icon-bottom-left.icon-alert,.popover-light .bar-footer .popover-helptip .icon-bottom-left.icon-help,.popover-light .bar-footer .popover-helptip .icon-left.icon-alert,.popover-light .bar-footer .popover-helptip .icon-left.icon-help,.popover-light .bar-footer .popover-helptip .icon.icon-bottom-left,.popover-light .bar-footer .popover-helptip .icon.icon-left,.popover-light .bar-footer .pull-left,.popover-light .bar-header #menu .footer .popover-helptip .icon-bottom-left.icon-help,.popover-light .bar-header #menu .footer .popover-helptip .icon-left.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-light .bar-header .popover-helptip #menu .footer .icon-left.icon-help,.popover-light .bar-header .popover-helptip .icon-bottom-left.icon-alert,.popover-light .bar-header .popover-helptip .icon-bottom-left.icon-help,.popover-light .bar-header .popover-helptip .icon-left.icon-alert,.popover-light .bar-header .popover-helptip .icon-left.icon-help,.popover-light .bar-header .popover-helptip .icon.icon-bottom-left,.popover-light .bar-header .popover-helptip .icon.icon-left,.popover-light .bar-header .pull-left,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-bottom-left.icon-help,.popover-notification .bar-footer #menu .footer .popover-helptip .icon-left.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-notification .bar-footer .popover-helptip #menu .footer .icon-left.icon-help,.popover-notification .bar-footer .popover-helptip .icon-bottom-left.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-bottom-left.icon-help,.popover-notification .bar-footer .popover-helptip .icon-left.icon-alert,.popover-notification .bar-footer .popover-helptip .icon-left.icon-help,.popover-notification .bar-footer .popover-helptip .icon.icon-bottom-left,.popover-notification .bar-footer .popover-helptip .icon.icon-left,.popover-notification .bar-footer .pull-left,.popover-notification .bar-header #menu .footer .popover-helptip .icon-bottom-left.icon-help,.popover-notification .bar-header #menu .footer .popover-helptip .icon-left.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-notification .bar-header .popover-helptip #menu .footer .icon-left.icon-help,.popover-notification .bar-header .popover-helptip .icon-bottom-left.icon-alert,.popover-notification .bar-header .popover-helptip .icon-bottom-left.icon-help,.popover-notification .bar-header .popover-helptip .icon-left.icon-alert,.popover-notification .bar-header .popover-helptip .icon-left.icon-help,.popover-notification .bar-header .popover-helptip .icon.icon-bottom-left,.popover-notification .bar-header .popover-helptip .icon.icon-left,.popover-notification .bar-header .pull-left{margin-left:10px}.popover-light .bar-footer a,.popover-light .bar-header a,.popover-notification .bar-footer a,.popover-notification .bar-header a{font-size:14px;text-decoration:none;line-height:30px}.popover-light .has-footer,.popover-notification .has-footer{bottom:28px}.popover-light .has-header,.popover-notification .has-header{top:30px}.popover-light .item.unread,.popover-notification .item.unread{background-color:#ecf0f7!important;border-color:#dddfe2!important}.popover-light .item-avatar,.popover-notification .item-avatar{padding-top:12px;padding-bottom:8px;padding-left:76px;padding-right:10px;min-height:80px!important}#menu .footer .popover-light .item-avatar h4 i.icon-help,#menu .footer .popover-notification .item-avatar h4 i.icon-help,.popover-light .item-avatar h4 #menu .footer i.icon-help,.popover-light .item-avatar h4 i.icon,.popover-light .item-avatar h4 i.icon-alert,.popover-light .item-avatar h4 i.icon-help,.popover-notification .item-avatar h4 #menu .footer i.icon-help,.popover-notification .item-avatar h4 i.icon,.popover-notification .item-avatar h4 i.icon-alert,.popover-notification .item-avatar h4 i.icon-help{font-size:18px!important;line-height:12px!important;vertical-align:middle!important}.popover-light .item-avatar .item-content .item-image,.popover-light .item-avatar .item-content>img:first-child,.popover-light .item-avatar .item-image,.popover-light .item-avatar>img:first-child,.popover-notification .item-avatar .item-content .item-image,.popover-notification .item-avatar .item-content>img:first-child,.popover-notification .item-avatar .item-image,.popover-notification .item-avatar>img:first-child{top:12px;left:10px}.popover-light .button.button-small,.popover-notification .button.button-small{height:30px;font-size:12px;padding:0 5px!important;line-height:30px}.popover-invitation,.popover-network,.popover-peer-info{width:420px}.popover-wallets .item-avatar{padding-left:95px!important}#menu .footer .popover-wallets .item-avatar .icon-help:last-child,.popover-wallets .item-avatar #menu .footer .icon-help:last-child,.popover-wallets .item-avatar .icon-alert:last-child,.popover-wallets .item-avatar .icon-help:last-child,.popover-wallets .item-avatar .icon:last-child{display:none}.popover-endpoints .item .badge,.popover-peer-info .item .badge{right:16px!important}.popover-endpoints .item .badge.badge-secondary,.popover-peer-info .item .badge.badge-secondary{top:35px!important}.popover-unit{height:108px;max-width:115px}.view-notification .item.unread{background-color:#ecf0f7!important;border-color:#dddfe2!important}#menu .footer .view-notification ion-item h4 i.icon-help,.view-notification ion-item h4 #menu .footer i.icon-help,.view-notification ion-item h4 i.icon,.view-notification ion-item h4 i.icon-alert,.view-notification ion-item h4 i.icon-help{font-size:18px!important;line-height:12px!important;vertical-align:middle!important}.bar.bar-header .button.button-clear.button-icon i.ion-android-more-vertical,.bar.bar-header .button.button-clear.button-icon.ion-android-more-vertical,.bar.bar-header .button.button-icon.button-text i.ion-android-more-vertical,.bar.bar-header .button.button-icon.ion-android-more-vertical.button-text{padding-left:8px;padding-right:8px}#menu .footer .popover-helptip .bar .buttons.icon-bottom-center.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-bottom-right.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-center.icon-help,#menu .footer .popover-helptip .bar .buttons.icon-right.icon-help,#menu .footer .popover-helptip .bar>.button.icon-bottom-center.icon-help,#menu .footer .popover-helptip .bar>.button.icon-bottom-right.icon-help,#menu .footer .popover-helptip .bar>.button.icon-center.icon-help,#menu .footer .popover-helptip .bar>.button.icon-right.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-bottom-center.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-bottom-right.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-center.icon-help,.bar #menu .footer .popover-helptip .buttons.icon-right.icon-help,.bar .buttons.pull-right,.bar .popover-helptip #menu .footer .buttons.icon-bottom-center.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-bottom-right.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-center.icon-help,.bar .popover-helptip #menu .footer .buttons.icon-right.icon-help,.bar .popover-helptip .buttons.icon-bottom-center.icon-alert,.bar .popover-helptip .buttons.icon-bottom-center.icon-help,.bar .popover-helptip .buttons.icon-bottom-right.icon-alert,.bar .popover-helptip .buttons.icon-bottom-right.icon-help,.bar .popover-helptip .buttons.icon-center.icon-alert,.bar .popover-helptip .buttons.icon-center.icon-help,.bar .popover-helptip .buttons.icon-right.icon-alert,.bar .popover-helptip .buttons.icon-right.icon-help,.bar .popover-helptip .buttons.icon.icon-bottom-center,.bar .popover-helptip .buttons.icon.icon-bottom-right,.bar .popover-helptip .buttons.icon.icon-center,.bar .popover-helptip .buttons.icon.icon-right,.bar .title+.button:last-child,.bar .title+.buttons,.bar>.button+.button:last-child,.bar>.button.pull-right,.popover-helptip #menu .footer .bar .buttons.icon-bottom-center.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-bottom-right.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-center.icon-help,.popover-helptip #menu .footer .bar .buttons.icon-right.icon-help,.popover-helptip #menu .footer .bar>.button.icon-bottom-center.icon-help,.popover-helptip #menu .footer .bar>.button.icon-bottom-right.icon-help,.popover-helptip #menu .footer .bar>.button.icon-center.icon-help,.popover-helptip #menu .footer .bar>.button.icon-right.icon-help,.popover-helptip .bar .buttons.icon-bottom-center.icon-alert,.popover-helptip .bar .buttons.icon-bottom-center.icon-help,.popover-helptip .bar .buttons.icon-bottom-right.icon-alert,.popover-helptip .bar .buttons.icon-bottom-right.icon-help,.popover-helptip .bar .buttons.icon-center.icon-alert,.popover-helptip .bar .buttons.icon-center.icon-help,.popover-helptip .bar .buttons.icon-right.icon-alert,.popover-helptip .bar .buttons.icon-right.icon-help,.popover-helptip .bar .buttons.icon.icon-bottom-center,.popover-helptip .bar .buttons.icon.icon-bottom-right,.popover-helptip .bar .buttons.icon.icon-center,.popover-helptip .bar .buttons.icon.icon-right,.popover-helptip .bar>.button.icon-bottom-center.icon-alert,.popover-helptip .bar>.button.icon-bottom-center.icon-help,.popover-helptip .bar>.button.icon-bottom-right.icon-alert,.popover-helptip .bar>.button.icon-bottom-right.icon-help,.popover-helptip .bar>.button.icon-center.icon-alert,.popover-helptip .bar>.button.icon-center.icon-help,.popover-helptip .bar>.button.icon-right.icon-alert,.popover-helptip .bar>.button.icon-right.icon-help,.popover-helptip .bar>.button.icon.icon-bottom-center,.popover-helptip .bar>.button.icon.icon-bottom-right,.popover-helptip .bar>.button.icon.icon-center,.popover-helptip .bar>.button.icon.icon-right{top:0!important}.bar.bar-header{padding-right:5px!important}.bar.bar-header .buttons-right span{margin-left:0!important}.bar .title+.buttons.buttons-right{right:5px}.button-icon{border-color:transparent;box-shadow:none!important}.button-small-padding{padding:0 7px!important}.button-text{color:grey!important;font-size:12px}.button-text.button-small{padding:5px 2px;font-size:12px!important}.button-text-positive{color:#387ef5!important}.button-text-stable{color:#b2b2b2!important}.popup-buttons .button.icon-left,.popup-buttons .button.icon-right{padding-left:32px!important;padding-right:32px!important;line-height:42px}.button-fab-bottom-left.has-footer,.button-fab-bottom-right.has-footer{bottom:64px!important}#home .logo{margin-top:15px;width:100%;background-position:center center;background-repeat:no-repeat}#home .center{float:none;text-align:center;display:inline-block}#home .center .button{display:inline-block}@media screen and (max-width:767px){#home .logo{height:96px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4AgRBwUf93UlLAAAIABJREFUeNrtnXd8VkX2/99z71PTewEChBK6VCnSAigIUlVgLeuqq7vq2nddf+vqV9a2rm0XXQvsVxF11Q0qJKFLCSBNqZESOoSEkoTwpD/t3vP7IyEkkEASsO3Xeb2e1+u5be7c85k5M/M558zAz+nn9HP6Of1gSf3UP2DSOxuuMUW1AbAoWfH5Pf33/ZTKb/lJS3+aaIba+mfN9A4FMOA24GcAGi4/0TI+IcIMJlxBlAbh4scGoOv4fVAOIAqXHQr8BeRl3I4nOZ1+CqaIMNkoDGqhVRT+ZOvQDwpAxhwCkkoomnmzKjhTc5NTJMhnR1UIAXYnIVJGuKYR6dHoa4libHI6VwHhUqlAS02rc5vptRdofs8JEfPAhd43OUV0QJ8zRXl/7gMamIalSgdTcZ+CXwOBgBtYpjTSMdipFC1N6ILCIbDT6mXVshvUwfryG71Q7BUVRJcUcHLzb5XvZwDqScNTZYipMQ1hWFVJj4vJGw47M5Zcqwrr6g+GXEVb5WGQMmmlwUm/TsbqsWp3XfkPSZNEzYIvY4zK+RmAmjV+nvQTjSeBsQAi7FXwFiHMyBim3A3NZ0SqxBqK0UAHUXztrWDx+imqouY9ySkSh5W45IlkTlPK/D8NQPJ86YrJC8C4qlP7gLUIZUojRgQNReiZ+0UoBE4oxXFMjiPkorMtY5wqODfvwenSyyKMFY1iND6rWet7p0tAEHQP0Nm5aIwq/j8HwLBUGSgaT4nJNUqhVZ32C2QrOI3iNEKRUpgihAGaQLiCSIF4ReWoqUY6DGxGsUlg1arNbGRaZe0eMk8SlMYvFRheO7PWjVJ5ZzrnfCcD8JOTMUkd/u8GYJpoyb25SgnXi3CzaEQowaqgHOEjMflrxkSOoJQ0JK8hPWiu6bQVoZuC7gJXAl0V1WDmK5iPMF88LM2YokpHpkmiT3GHKeQrgw8zJikXwLD50tvwUr76+rr7jZ80AIMXSrTu5zcCdwL7lRCCoj8gCDN0gyeXX69O1SfogT0J1PwEKRtBmARpGoHqw8ljJC8rSRtwz3Lp/7ts0bAKGLqJQxSdTKE3igEKoqu+1o3wmTL558qJamNyqvRB8VsMFmRMUvMABs+TzladoBXj1Nf/FQCMSJUrDMWDQAcFH5omu5XGe0A74CRwV8Z4Nf+czjHIEkCM3yRGCTEGROnq/DmLvNT+finY31Uf+tgMue6lrXW9X0ApaCnQT+BKBSFVFw4rxVzNZK5PZ6hSRPisvLhulMpLTpeOpkHE6omshwa0xB8jAEPSJFHBc5rCKiYvZUxQm4aly20ivAM4ET7TDe45U+uT0yVKhEQ0Wmsm4TXzig3A2j2SkE7hhMc6aR5sJTjQQuDL9yb32r1lTdifXvrYlTxmqnhNTISSKsF7vCbuMh+lJT7yT7kpOFlByapjxO0tpp/XoE1V9iUIS5TGQUwGicZbGePUv0d8IUk+jajVE9W6n9RMOHmuhCmNJ0whVmk8u3Kcyhq9UOxD0+TfItwMuJTirpXj1cfJKRI0PF36+qGdEoIUYFOYI1sT3j+GpJZBdIl00M6pE1nXu0KCgkCBw24Ns2pgrdT6te6NsNd+5sYqsW8v5NAr2zidU0p3FDeKcFrpfClwdfJ8aWFs4lVrXyzJC6RHxnVq208CgOR0uQW4yYTnV41T68+okwofnynFKIGDojFWPLiS58vVylfeRiSApBAcN7ahfY8oukY76KspAr5r1dg9gsQPh5N4rIwTf9vi25vpsvYTkylKyFEKm/Tk76qUJw0nbUd8IUnLr1d76+ufzoyyfjAABi+UaIufV0XYmbGF8WcKNOILiTQszAf6AxuUxt1K6IBuxqq/tn8wNj6hfPrsjNMxAQwH9Ka9/dJUdIzNG3fquS5xt954X9GGpEe27i+mv8DNaOzwO/jECneLnbZD5knF6onq6Hnf3pfINZD/gwEwLFWuF4PJuuLxZeNUdnUfME8SDI0VQDtN8ZnpY7aycFWbUJz3dNb6rM0c0ybt07cdFcd3Q9tOTXp3xyv64naXEx3bosnlT5n1GseO7qf/lf1Df92D/utOsPfZrWhuP10FksRkqa4Ypym6DEwV19oJqqTm87qgX5Mqzb6coI59r51w8kqxqGJeEEVRxhb+WrMZVtX8NUAn4H1RrOsQSuBDXRjSMZyxmsJaXlbC1GEJtEzsyJv/2fCDTAJdp/KYOqIVfQdfy7NvzK0+bwrmu1ms+WQ/3QXCAJcGN2BgWbGdZeeqnGHzZdTKsWpJU8qgNeWhUYslQkqYrWB+xnj1fM0CjUuXAMNCKtBJQUqonW9e7MtVbw/ixc4RTNIUVoCAwGDuffw1dmVuZH3G/B8EgDdeeBjTMHjgiem1haLQ7u7E0E+uxh/pYDsQZsAS00Kv5J70Oi8jk5yh6TLgeyn0iAWSlJwqc4akSeK513rPEOvQNFmQnCaSnCbpb+yQp8p8clTqSYZhyG3XdZLrB8eJ1+OW7zPt3bVFkjspeW/6Uxe8zxSRd3fLhuRU8VZ916JrPpP252mENHn8uyfM0iU5OU3mjV4oIXX2B2nyWnKayIj5svbbUzK/IYLYsXWdDOuEfDzzxe8VgLsm9ZDx/SLFXVHWoPt3FkrO8HQpqgIhe8h86XROXzh+SKr0/M5U0PA0GW4tK3wyOGfrDOf+jSF1gDNR4GGHTtbn19C8awTXNSTfLj0GcNWIibz/5jRcp/K+l1a8YuGn7N+9jYeffgu7o2Ej3s7hNH9jINkojgMJymRDcrokn7ke5WGBUtz4nQAwPE2GC9waULi/u453oWmRSeeg3wHhA02j4OPhxITaaNWYQjz05zdAYF1G+vcCQGH+CXr0TWbY6CmNeq5zOF1/2Z5vUBxQEBiUt2vFhLc35U56a8MOf8HG7cH5u64dvkBaXVYAhqfKEBPuc1i4F5QFwFQWZ03extSYK2B58ypOhTuIaKxAouNa8PGyg4y54dfnXzQ8cPrbyp8YlwWAG3/1MH+fvbJJz96exNhYBzsQVmt+N0r8zQS6CHTRvWVe0+CeywbA8HTpZWj8nmBuXTRGedxh8a9XhLR4VTT1KUDyLHEoJy8podNN7fimYzgdmyqUyOj4eq6Y4HFV/hB+6KQptBf70U7p2JRp1rLQaWJWICQg0uDhfb0TsZFfSIwXngnQuXnRMOVOXikObwm5JhxdcmuL7MkpYsuzMhlhSridzb/pxODv6JPBEVV72uIpwMidV3nGGoaWcOP3CkLrYLoMi2Pe5hxlqaNOfDN0Pv1Xwfomt4DeM8TqtTLdAvdVm+lcxAFoGnkgKt/OcKUxBgj45yDi1XfFrOp2COtU+VM6P5b0aHcGmxZ7mWmxuQS1F2SHIAc1C/MUTL2kFhAUzyuYvLpswllqAb0SANE4OTidnsogQjQmj23JmhDDlXwqr5zImGb8X0kFR3ZFjh7QdV7KfuJF59+rxqo3aswJ2jaUpNPqGE5ORdiRMUFtqkV5qUqrkkNh0YRYE661ahx5qBtXzXr9f7jp6jbMfusZvB73d//19kj0xNvRE29Ha3F2QFZ2bCOFuz+l+NDS7+zVecezeeLecdwxriu9i1eOtGq4lcnwIfMkocZt24f3pkejW0ByukQh9F81QT1SB+kYJhoet58edjvbPR6m3tOZrRaNNrfd9z+43eXMfnMaX3wwnfv+32uMmvirJn9kWUkRh/btoCDvGOVlxZiGgTMwGKczkBatk2iW0AbNtR78ZZW1KGoQWEPwlR3HXbgHW1D8ZRe8x11OyqxX+fDt51Cazp0PPkvPXlcFjN5DYdphWqC4HpgOoBQrBQYBWxpFxg1Ll2eC4MX0caq85vnJKWIrcHC7qRFlMXjXD390WBi9aAwdahi/2bdrCy/9+dfsz9pG+869ePz592jbsXuDPvDIgd0sTf2AtStSOXLgwjZxXbfQqWM7evdMYkRyf1r0+Q3KHklpzlo8rgNYnJGEtr3usgl/7Yo0XnnqLlynCxg68gYefupNwiJjADjt5vgNyzkoJvkEc1NG1YBFipmxaoL6VYMBGJYuYzA4tXKi2nge/5MqsSbcic5Jr8EcqyL3d13ZcWMi5xFQIsLy+R/z+vMPUlpymlETbuOex14hNDyqzgIcP3qQGa8+zuovv0DMxts1lKb45V2/545HXq5dDvdJMN2gB6HskU1TNyeO8sS94ziQtZ2kLr3543Pv1lmhHljL3B2nSBR4dNUEtbJKnikrx6kpZ+02otXl/KUBDEgRp0CzuoRfOfEiCkW8YbDVChN0RfGk1vStUyBKcfW4W0hZmc0v7vwjy+d/SvbBrDo/cP6cf/Hrid1ZteSzOoWv6ToRUXHExLckMDi0bnOMKfQZdH5tl9NbME98iRTvbHLND4+IISgkjKf/nsKMzzbV25pvbU+M0vAqmFKD0j5ek7BMn4+j3j7AbmMgQbxfX0FEo79mkm3qFGkmU0Y0J0tXNL9Q4R3OQH7z+xf5xa8fIyTs/Br47vQn+eid5887f+WgUQy55nr6DBxJbLNWKHVWSxa7TrE/axub1y3jq+XzyD6YRc/+w+l2ZXLjpev3gsV2wVusNjv/mJ1x0ayujKafVZHhUfRNnithGZOUS1NsFugNHAJwKuxUudvXAmBgqgSbGkdWD1P+egwvQZQQLFBs86FMnavv7EiDXfjqEn7KrFfPE377Tj25/8/TuaL34Avm1av/CHr1H8Hdj/6VzE2rCQyq0TJMH+RtAM2KihyAJl5Eq6PiuQ5T+t51+ALjsLfqT8DIZ0HTmtxSNIXlqjhKMo4Rr2AE8LloZCo/I6s1g6fuFqAFGjhXj1P1R5WU0kMJ2QCGheFhdnbGOoltamEzN69hxqu1qfN+Q8bwxsdfXVD4daUr+gypVy0oWxjYY1DWkHN1FmTNozy+M+VdhlBqFOCaMZjTsyfjP7y+ySCMSSAe8Boalc2xjP2mOktKWrW6HQ20pZkU1Jfp6IUSguA3tcoJtzIZOiaB0qYW0jQMpj97P6ZxllTr1X8Ez705r8G08IV7ZAtE9oDwrvXfszedshN7MOI7AOALbUZZt5F4midQuup/yH//Bjy7Gm+h6xVND4uiTKt0jSRjiirVwHlmFOm31M06WC40W/MIPXCzBQeJojAFBoxv3XSXkWULPubgnszq4+DQCP704mwsFuulCV78YFZpUEvAWcpC/JinNqJsYRT5Y9i/IZ3cfevJ37sJX2gkNpuV8NBg4uMiad48BqPtIKzFJyjbOpOib2YR3GkMzr6/bhhjonC0CSNv72muGJkuHZeOU9Ujj+IQguweyhpFxvVOlwBDkFVTVOnQdHEgBNl1fLHOSkqiKWnuv/9Z6/iOB/5CVGzzS674Zv4apLQyOkmLHowK7lB1wc/GFSn8Z+5KMjN3XnCY63TY6ZjUin5XdqFv906ElORSfGIDJR8sJqTbDTh6/uKi5RgQjWNfIYZXkQxkiapsAT6DYDOEokbR0QHQ0YAdZ4BS0KZdCCeaKqSjh/aQlXnW3zUgKOSSZssXSz6vhxeeuIsnnn6d7du+vegco8LtYWvmXt55dy6rN+7EHdMeHT8S1wxXbgb5H/4C39FvLphHvxiamQpDhG4ASqiYnCK6CeHR+eePgC7QAkQpIWzNOHW6Rt+VMDCu6X5E33xV22tj+OipBAQGXxZhK6WfsRVV16m//+Vevkz7d635Sdeu3YjWSwmIqyQNS0rLyD2Wz6Hs4xj+yn4pMMDJ4KsqO3ZPRGusJXkoDbyJnTi1/h84vw4ldNLroJ0viqRQOipFFpB0ZryVD07NT0h9gYF1CvTqdBIMk9wa02VBI/rKaKKaKqRvt66tddytz+UzH6joIajoIdXH+7O2seiLWdXHfXp259HHniA+Pp4Ti17FaF/bdl5e4WbL9j1s2rybhBax2G1n5we+4Bh0dxE2Vw7eZkmU+91437+eiDEvoMfV7ux1DUeIlfJiLy2SZ4nDVPjsFgK8Wv2apk4ADGhffILVtT5SiE4Mbpytt2Y6dzbcpUfT3GjchfswvSXojjDsYW1qXTu14wMMTxErl571pQ0KCOCZ51/C6XRinDqEFhzAuYbNAKeDQf27M6h/3UNawxEKKGynj+INT8Cb1Jv8L6cR2m0yzh61qf8YB95iL7qKpK0Ifr+DYAz8DaajJ6eIDeDcEE5dR7do2JsKwPGjB2upg/jmiU1jSo+tw3UgnfIT5+tjv/s0fncheSeqGy8tWrbE6aw0YRdvW4wvrkOT3ms4QjCcIdhclXkbid0oykqjbOOsWvclhqBVcWztAAwvzUwfpxoMwPEAWig/h8+honWR+lFsyPjfXVFWqwPW9Mtv3bIFNcMWnEBQjdlxbk4uHo8bTBOf99Ji8AxHKKbNgaWs0hfXaJFESU4GxYufqr6nZTCBCjRTiFGKQA0CNGv9zrvnqSAdmkf62Hh+t4xLqqC9upsNw187xnn8L+7hkaffrlttuMsROWs8DQoOa7IQIrvcWpmXOt8CGt5xMhheOsdvYF7VuZLSEv7xj79zb3I7jFadLhlkf0Ak1uITHM7ay5Ovfnz2wiPPAfC7WZlAN5QiBiEIDUfyWAozGtYCRCmw+wo2fjTx7Q2ZE9/a8OyZTlhMigwTz5kmcR6SFyC2bPbaNIjffwkB6kpHISh/KfiKzv7ED34PZM5myNjJxETHVD+yePEiHnrtAzZ8m41hXno4sC8kDoe/pO75xJrnWldJKEYUEZi4LxSDXKsFDF5IlDI5LUp1USKdDYujoKr2mwgej8Fxi0brZd82ToAWixWHM7BaDZUWuxr3xd5CEANR1kqOpyIHs6A2b6OFXQkHMiC+A3almPaXZ/jDY7+nvKzynYfzinj9nRQiwkMYPqQPw4b0IjQkqMkgxHXpxWcvhOCOru0muj8rv6hK2lFKiNNsHL0gkVerpvqI93s4hqan+QIiT/sCooKqxqGiwOfycbKpBQ4OPRv25XGX4/N6GjHT/aqS2y/cVM/QqAj2zodmHatVU6dOnXn7rRl06FDbVanwdDGfpa7gwcf/zjvvzuXQkWNNbIkKb2iz6k757GmbW4GhhAiBQKOU7AYDYGhE6BHkp/62z5/KI9p94g5pHjQsVTpg4EZhFFTQZOfN8MjaBOqhfTsuT89bfBLysiC27XmXWrZsyduvT+fhCb1JbFXbY8PwG3y1YTtPPTeT516axZbtexo/uLAFVgrRe3aSW64HlCqoUOBU4M2YokobDICYqIwqu4Cq9PHHhAla5UIZlmNlHG+qnDp07VPreHdmI8JwraFgi0DZzqGW8/ZC2TGIqN8IX/rNHPpeey3PPvkbnnniboYO6onNVpv8y9p3hNf++QmvvfkJ5RWN8+rwhjXHVlzZiixuF4UB7Q4KlJtCNIr9F7UlnPkzTURTGtXKvd1RVlIZ0TjeVBxDYd1f1PQW0Ll7/1rHWzYsb7jBI2YoWvy1qIhKK6jowagTx1AhzVGxvVABrRC9TnsH5cUnMavY1jaJzbn7VxN4/W+PMPX6q4kMr23m3LJtD8+//D5er6+RILTA5spFHT/M2sipG4ASTSNMGuAVUQ3AmuWEo6juHWf+VvkQlgARGrQX0DNP1T+huFjq2vOqWsfrVqRxKr8JDSp/F2rvfFTClajQjihni8qf7jx/tHJkM4SfT94GBQUwbvQgXnvhQaZMGlGLejhy9ATpi75qnCqyOFCmD79Yjd1uZ4VoVJhCgGayq8EAGD6CTX9tytTUSamiJiYqsB0oodxtNK0jbtE6iXYde9Qaip5LT5+tUqeh7NDZn1EOhhd2poBrN8S0bZAJ0bVvHf6o+ulu3aIzfsxgnnzs9lpqafW6xocFe8MS8LqNUkzQIECDALGwucEAmAZOo0YLAFg9Vu0W2KiEAYpKm+bxCpoctDzxlt/VOv7Pe6+wP+v87KQ8G7NgffVP9s2HnR9DRCwExzRwxlSBmA1bmSyxdTNGX3OWmzpVWERFI/sCS1kBJSGdjlT1pWGi8EWXXTx8tRoAXbCtnXC+uVHXmQVgSKVr4o5CmrySyKgJt9G8ZbuzMvJ5ee4PN1NYUI+ZoeAQ6tA6sJqVtV413HBeunkuRssuDb4/Pra284ApjXOFtx7OZH3XaXPFJEIUIUDhnCnKaLgK0jDrWphixRjWCOzXNKJNIfTLoxxpKgAWq41H//IOqob6OHJgNw/cMojc7KoBgwjkbEEdWQ+aF4luAVZH40m74lOYF3E7qZlycs+OLxx2G4EBzsZNCywBsuKkJU9pODGIEhqmqs+2AAOzngmHaML7CH6lMXRHIeUl3nPIukakXv1HcPv902qdO5Z9gDvHd2Xmn2+gZMPbqIAAiL8CFdQCZYtEaeeTsH6/j127dpK1+/wGmZ46j3U7D2IYDYuoyT56guWrzk7yrujarnEkYP5hPK1HHs8rIxQ4qTRClFx4BnweFaEM6lV6UR7m5zs5AfRAsXaXi4x+MdzeVBBuu/cpKspK+fTdl852Yh4Pn3zxBSmpqXTp0pUePXoSGxtLWGgYcApXkYvCwlOcPn2aPXuy2Lt3Lz6fjylTptKxU22Sbd+W1aSv3kzgsl307JZE506JtE6IIzoqHKfTjuE3KCop42ReIZu2ZbFy9ebqoaeuaYwbPahxLfvEPr4eO+sLthFnCLGa4pSCkkYB4HPWbbMEmDNFeZPTZSbC0yYMm3eEJf0u0hd6PW4++d+/0a5jDwaOmFDFQRRD7jfgLeG3o7uRGHQfr787m7LSs1S1YRhkZm4nM3N70xnLispvLyur4KsN2/lqw9m8lKYQs279rjTF7bdcV2vWXOH2sGffEXp0S6p7JOUrxxaeyEd7KVMKlwb3A6eFhjmvVQPgL+bC5EwQ71DM4yjafX2czNMessLtdceErUp/n3+88CiuIhe3Tp7MwHgPGG6w6BDaAgIigUhGTmxFnyEj+fiTj1i4YAEVFRWN07uaRljY+dR2YlwoAU5HnbPa+oTfLD6KX04dTbcutSmNNWu38cGni2jfNoG7fjWe5vHRta7bd6/BddOKPcfW4jAhFHCgyDFpmANDNaneO10CNp/jln5uGpouC5VJm0BKnX8IWHIwOUFPxnBXEmCmwZGj2bz81v+yc98BWrZqyeN//BOdOzdsJOLxuNm4cSPbt2/j4MGDuFwuiopcFBUX4XA4seg6ERGRxMTE0KplK9onJdGnTx/Cw88PyjyxdDplzTvw7c797Nx9iNzj+ZzMK8Tj8VHuduOw2XA47cRGR9AyIZY+PTrSMak1mna+jUFE2LhpF+//ewFl5RUM7HcFt0wdRXBQAHrZaUJLiuWZVu/965uT7PIL92iKr0VIUhr/WjlWvddgAOpzn66ZktPkDxoM1MTbv4slu/CVHsfbWjTsJSXFzJw5gwUL5xMYGMT9v7ufkSOvreVY+32mE0unY7Tpdlnz9Hi9pC5Yw4Ila9F1nRsnDOP6mCKyp6z75JGvtW+VSXNR3GFzu54ydfutFl/FGwOyImZPu0iYUrUKatDCpUKGqYg1lK3NPl98wsbCwgMDozydZ73/HosXL+Lmm27hl7+8DbvdwQ+bLj/wdpuNKZNGMGxQL979MJ2P5ywl8b67i6Zv1dYhmMB9CmYGFuz5W5Vc39sWap8LuC5bSavW10w1DVJ03Xi+uZzU3ut1MLqirMjqdlcQExPLjyHlL38Hb6uk7+4FhsHx1UvMlGs2PvxNAYUKJogwHgvtwg5vPMyZxac89vB5j/R0NZiOvliaM0UZAid9XpYj+to8M8ox80BEXkhIyI9G+AB253e74plz51LZPPKzF7YUsEmZtBRhLIp3KlfklVwgD+GkR/eYl72tDkuXEQgdxMpC8bIkkPKYvyV9a3YN80b8WAAwDm/kVOEBfCFxlz1v28HNbHWOWPHXwId+rwzaCkxDEeXU6dCUpY8bHZWwcjMrgf4Zo9VhCzxboZzlL+xt7Sv3qYofCwB6dBu00tOXPV/L6aPs8bXe96LzoRcsQjHCDUBXJTzU1HWnGx8WMk2ZArlXp0vL5RPUR6A+P0mUenF7UK78GBZzAFBWxDAuL6gVJRzM9uQ+Ff36g1FjyfDDJNG4EVi1crxKaWq+TYrL0U0+9MMdAA4Lj5mavnOddAualdm0ha8vyU2lrvxyt2NGXL5YYc1TYe7bnXviz60+/E20hy/z0+iJyWMiVFgUt11S3k15aPlEtUtB7OQU0ReNUR6Lg9tNpbs+qehrT93rb/SGCM899yzT/vL0ZRNYac5u/IH1h6aapsniZRvYmrn34v2Jz+vZvuPE8RcTZt4jm1maX4YVxf+KIkaDO2uuFPm9AVBZMmbnORkDsOwalW36uNOv2TxvFg801h4oOtrQbLJ272b16gzatml7eaRvmngqii6soZRi1dqt/Gt2Kn5//R6X5adPFW7a4cqb0fzlu8szgxdkPI0hUaQA3RW8u3K8+vySW1dTH1w5UW3UhGo/71XXq/Wm4n6/2Jh2alTZjv3HsrmIUUNEePmVlwgLC+cXv7jpssi/6Kt3MVt3vSgAv71jIsUlZaTVY//NOXLi6LrsgILprd6cMG9yzKKMaco/NJ3pShgHbKeABy6LervE+eZXyalS7W+yepxaaJg84cMa8MjpycXb9ufn4KufXlq6dDEHDx7g0Uf/gNVqveSPKft2MRWawrRd3JjSumU8/Xp3IW3hGlyus8xxhc9wbco8tn9rcfPD77d9cdTqCWpr1fD7TwoeUIqDaNyacYdy/+AArBivVkBtRnT1RPWxUjzjRwv8Q9ENheuP23dSdKxO8u2tN9+kQ8eODBp06cEaJRvnUOI6ihHXpsHP3HbTaFCK2Z8uwjQxdhdUbFuXWVp8yN593udRT47LGF05qEhOlWkivKAUuUrn4Yyx6jJ5lV0iAABYyTh3obqM8epdBY/4BdsTJ5P5oHTgEk4eEIyzjPes92dRUlrK43/806WNePIPULDoNUrtghEUwp5tAAAGFUlEQVTfuH4kNCSICdcOlm+27OLTpbuzj+Yq+9Ko+6Y+ctd9f1w2RRVNThHb0HR5F8XTqnJ2+4IdLutaOJcMQMYYlaM4P3Bj5XiVqsPvBDyzjrVo9Uf37Z8ZbvGRtx8xDfZk7ebaa68lMbFpgRpSWsDhea+ya+3nFLfqjBnUuOgpQ/DtK2Knpe2V3wQEBvuz9mXvndPmr/3/fWv7DaBkxBcSme9giRLuFDhqKl71CvMWjVGeywnAZaENe88Qa3ASel3bTA1Lky6m8A8NWkY5OfLWAHfXqJzF8Xhd+MJaYLU1LujGvfNLinN3IhaNl+fvYPO2LB6+Zyp9ejXM97/Yy6k9xWp/ToEhTrc3xir+bZ9y3UOLHhxWPXyu2tEpDUgEtuuK9/zC+lXjVb1hkpPXiXPOANwN2vum5uz6cgBQFc5UazY16c31d5tK3a+OblSGxfppSXyv6Hw319y00pH7SPeJ+8e08wy2HvwSXLkQFg22+iMmPftWU3J0J4a3FIlvjdHmiipScjuqAXWo2MupI6VyZF+pPd/qKmtpFSMyFHP9+63/duOKcSoXXqlZYW4Qk1lAMDBfUyzwC0dWjaNO1+wRqRLr0wgpdZHdWOFfNgDqVBGailPCFSgQ3XFUabwlgssPo17eSvS8w/aFL/Yd2zPCQTzHt4DrEHiLICwebEF49iynJGcvhq8EiWuF0bJhsV0iSsp8RmF+hco/WqEV5FQEFIeUF7XSff6wEMo1V0DCix9FPTC3chn6s04BoxZLhMfD6wK3AB4NnhfIFsEV42b5ucIdtVji3T76i5/M1RNUk3dw/X428xTApLmC40pYampcta+ITpOXU9E1gmVjE3odbxbbKzTMSnRwwdfxLH0lzlecazWtNt0SGIy3yivaFIVflN8veH2GuCt8ZoAgjv2FnoPuE/qJ0369zFviDQ7weqNElNUUPTpez7PkWdu/lt7s7qUZ33KMB5QJD57L8I7xeJlJ5RI8ezTFg6aQgOC3eFhSM8Z3SJokaopRHi85MW7SGuJ89Z33AXWlsW+va25VeksA5fcf87W6Kr9IiNUgVkFzEwYqoYdSJImiWAmrlWKbSG3/pK5Fa1t1KF07yO4rDfbruq5M06LhtyKK/VnbA0+dyHW069anMDK2ebkhyuO3Bm/7Kvz6uSedrY7iI+fMHmF1qo8vJNLQmY7iFgBRvKdrPGOYDFeg42Vxxg0qh2miDe3JUKUxVAnfSjCpGfUs7/OjAaAhaViqdFBWhpsmvUUYqIQSEZYpja+ViWmCXemV1iUBQ4zKEF8d/GiUmVBuMSnzaVSIjiuutGHugANSxOmw84Ao/h8QjuKAMnlI9/CVz8F4FA5lshIbfs3HOEORAKzvcIz5My/zDqw/+FaGk1NEL7TTxdRJEJP2UrmXZJgSFioL86PK2HSpzfwslS7a0J7coBR/qxrhVCC8FHpqawp+6eBxxPT1RLQoEUFTQrypOGwoPv9qbP3b4/7kAagBhC3PQXdlEmqCTdO5AhihBBuQgcY63c6GZdeooqYIflgvxgk8D3Sp6pVSLRq/17yU2gp3vWLxlvxSlGYUt7hyughzko6zeeb3sN/wj2472+SVYtErSPL7aC46OVYDq0+nj2bSTaCzUvgQdgBZunDEp5FjmJw4d3MdgIGpEmxT3GTCQwo6V53erjRWmIIPE4umKA3M29XO4i25GVT5vPv6BX6f3/sj3lFb1NXpJPhMOugKwzQ4yHZyPP0JsfvoDMQBsUqIEUUMEKZMSkRRpiBUoBuKrggOQFDsBP5jGqywKg4sn6CqvZcnvLOhsyZcIeCbd2//z38G4Jw0eqHYywxaIiRoGprh51iQjZyadthRiyXC42USMFVghKrc9rZQwQcoZmTUWMHqx5R+EgCcq6KC927/H01840CzidKDyyMSC3yOkK7KxFr1RZsVzAxSfJR+EXfLnwFoQprw1oZ/KqiOdyqN6ojfGbobWAUs1032+gTBxG+zUuaHcpuNitAi3HMmYzaFMviukoX/ghRQevz2tClhs3+KZdf+GwDQvUXHfqpl/2m2AI23BBZW61G/2vJTBeD/A62herFIRO47AAAAAElFTkSuQmCC);background-size:96px 96px}#home .footer{display:none}}@media screen and (min-width:768px) and (max-width:991px){#home .logo{height:144px;background-image:url(../img/logo_144px.png);background-size:144px 144px}#home .button{max-width:350px;margin-top:20px}}@media screen and (min-width:992px){#home .logo{height:200px;background-image:url(../img/logo_200px.png);background-size:200px 200px}#home .button{max-width:350px;margin-top:20px}}@media screen and (min-width:992px){.circle-bg-dark{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA1MDAgNTAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOmJ4PSJodHRwczovL2JveHktc3ZnLmNvbSI+CiAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoMC42MDgyNjEsIDAsIDAsIDAuNjA4MjYxLCAtMjAuMDg0OTc2LCAzLjI1NTczNikiPgogICAgPGc+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC43ODsiIGlkPSJwYXRoLTEwIiBkPSJNIDQxOS4xMzMgODUuNzM4IEMgNDE3LjI5NSA4NS43MzkgNDE1LjQ1NSA4NS43NTQgNDEzLjYxMSA4NS43NzggQyAzNTQuODUyIDg2LjU2MSAyOTkuMDIzIDk5LjE3NCAyNDguMzU4IDEyMS4zMiBDIDU4NC4xMjEgMTMuMjA2IDc5Ni4xNzUgMjExLjI2IDgzMS43IDUwOC43NzMgTCA4NDYuMzgzIDUwNy4xMjQgQyA4MTUuNTg2IDIzNS44MDEgNjUyLjQ3NyA4NS41ODggNDE5LjEzMyA4NS43MzggWiIgdHJhbnNmb3JtPSJtYXRyaXgoMC45NjM3MywgMC4yNjY4NzgsIC0wLjI2Njg3OCwgMC45NjM3MywgODkuNTA1MjMxLCAtMTM2LjYxNTA2MSkiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDE7IiBpZD0icGF0aC0zIiBkPSJNIDE0Ni4wMzcgMTk0LjA2NSBDIDE0NC4yMDEgMTk0LjA2NiAxNDIuMzYxIDE5NC4wODEgMTQwLjUxNyAxOTQuMTA0IEMgODEuNzYgMTk0Ljg4OCAyNS45MzEgMjA3LjUwMyAtMjQuNzM2IDIyOS42NDggQyAzMTEuMDI5IDEyMS41MzEgNTIzLjA4MyAzMTkuNTgzIDU1OC42MDQgNjE3LjA5MyBMIDU3My4yODQgNjE1LjQ0MyBDIDU0Mi40OSAzNDQuMTIyIDM3OS4zODUgMTkzLjkxMyAxNDYuMDM3IDE5NC4wNjUgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuMTgwOTg4LCAtMC45ODM0ODUsIDAuOTgzNDg1LCAtMC4xODA5ODgsIC0zOS4yOTg1ODEsIDcwNS44OTc1NDQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMSIgZD0iTSA0ODcuNzQ0IDE5My4wODQgQyA0ODUuOTA2IDE5My4wODUgNDg0LjA2NyAxOTMuMSA0ODIuMjIzIDE5My4xMjMgQyA0MjMuNDY0IDE5My45MDcgMzY3LjYzNSAyMDYuNTIgMzE2Ljk3NSAyMjguNjY4IEMgNjUyLjcyNiAxMjAuNTUyIDg2NC43NzUgMzE4LjYwNSA5MDAuMjk5IDYxNi4xMDkgTCA5MTQuOTc5IDYxNC40NiBDIDg4NC4xODQgMzQzLjE0NCA3MjEuMDgxIDE5Mi45MzUgNDg3Ljc0NCAxOTMuMDg0IFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNjE5OTk3LCAwLjc4NDYwNSwgLTAuNzg0NjA1LCAwLjYxOTk5NywgNTIzLjA2NzIzMSwgLTM0My4zMzE1MzkpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjg0OyIgaWQ9InBhdGgtMTIiIGQ9Ik0gMjk1Ljk2OSA0MzIuNzU3IEMgMjk0LjEzMSA0MzIuNzU4IDI5Mi4yOTMgNDMyLjc3MyAyOTAuNDQ5IDQzMi43OTcgQyAyMzEuNjg4IDQzMy41OCAxNzUuODYgNDQ2LjE5NCAxMjUuMTk4IDQ2OC4zNDEgQyA0NjAuOTU3IDM2MC4yMjYgNjczLjAwNSA1NTguMjggNzA4LjUyNiA4NTUuNzg2IEwgNzIzLjIwNyA4NTQuMTM5IEMgNjkyLjQxMiA1ODIuODE5IDUyOS4zMSA0MzIuNjA5IDI5NS45NjkgNDMyLjc1NyBaIiB0cmFuc2Zvcm09Im1hdHJpeCgtMC45Nzg4NDksIDAuMjA0NTg0LCAtMC4yMDQ1ODQsIC0wLjk3ODg0OSwgOTYzLjgyMDc5NiwgMTExNi4zNjcyOTMpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMyIgZD0iTSAxNTguMDM2IDE0OC44MyBDIDE1Ni4yIDE0OC44MzMgMTU0LjM2IDE0OC44NDYgMTUyLjUxNiAxNDguODcyIEMgOTMuNzU5IDE0OS42NTMgMzcuOTMgMTYyLjI2NyAtMTIuNzM0IDE4NC40MTEgQyAzMjMuMDIyIDc2LjMwMSA1MzUuMDc2IDI3NC4zNTIgNTcwLjYwNCA1NzEuODU3IEwgNTg1LjI4NiA1NzAuMjA4IEMgNTU0LjQ4MyAyOTguODkxIDM5MS4zOCAxNDguNjgzIDE1OC4wMzYgMTQ4LjgzIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuMzM4NjE0LCAtMC45NDA5MjYsIDAuOTQwOTI2LCAwLjMzODYxNCwgLTExNS41OTUxNTgsIDQ4My43MDU5ODQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAxOyIgaWQ9InBhdGgtMTQiIGQ9Ik0gNTAxLjAxOSAyODguMjkyIEMgNDk5LjE4MSAyODguMjkzIDQ5Ny4zNCAyODguMzA4IDQ5NS40OTYgMjg4LjMzMSBDIDQzNi43MzYgMjg5LjExNSAzODAuOTA4IDMwMS43MjYgMzMwLjI0MyAzMjMuODc0IEMgNjY2LjAwNCAyMTUuNzU3IDg3OC4wNjIgNDEzLjgxMiA5MTMuNTg2IDcxMS4zMjIgTCA5MjguMjY4IDcwOS42NzMgQyA4OTcuNDY4IDQzOC4zNTIgNzM0LjM2MSAyODguMTQxIDUwMS4wMTkgMjg4LjI5MiBaIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjE2NDY1NiwgMC45ODYzNTEsIC0wLjk4NjM1MSwgMC4xNjQ2NTYsIDk4Mi44NTcyNjYsIC0yMzMuNDUyMDYzKSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC40OyIgaWQ9InBhdGgtMTUiIGQ9Ik0gMTkyLjk1NCAzNzYuNTIxIEMgMTkxLjExNSAzNzYuNTIyIDE4OS4yNzcgMzc2LjUzNyAxODcuNDMzIDM3Ni41NjEgQyAxMjguNjc0IDM3Ny4zNDQgNzIuODQ1IDM4OS45NTggMjIuMTgxIDQxMi4xMDMgQyAzNTcuOTQgMzAzLjk4OSA1NjkuOTg3IDUwMi4wNDUgNjA1LjUwNSA3OTkuNTUzIEwgNjIwLjE4OCA3OTcuOTA1IEMgNTg5LjM5MiA1MjYuNTg0IDQyNi4yOTUgMzc2LjM2OSAxOTIuOTU0IDM3Ni41MjEgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuOTMxNDA0LCAtMC4zNjM5ODgsIDAuMzYzOTg4LCAtMC45MzE0MDQsIDQxOS40OTkwMDYsIDExODIuNTk5ODA5KSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMTsiIGlkPSJwYXRoLTE2IiBkPSJNIDIyMS42MTQgNjMuOTczIEMgMjE5Ljc3NyA2My45NzYgMjE3LjkzOCA2My45OSAyMTYuMDk0IDY0LjAxNSBDIDE1Ny4zMzQgNjQuNzk1IDEwMS41MDYgNzcuNDA5IDUwLjg0MSA5OS41NTQgQyAzODYuNTk4IC04LjU1OSA1OTguNjUxIDE4OS40OTcgNjM0LjE3MyA0ODcuMDAxIEwgNjQ4Ljg1NCA0ODUuMzU0IEMgNjE4LjA1OCAyMTQuMDM3IDQ1NC45NTQgNjMuODI0IDIyMS42MTQgNjMuOTczIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNzUwNDUyLCAtMC42NjA5MjUsIDAuNjYwOTI1LCAwLjc1MDQ1MiwgLTcwLjgwMzMyMiwgMjkwLjkyMDI3MykiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDAuNDsiIGlkPSJwYXRoLTE3IiBkPSJNIDQ0MS44ODggMzQyLjA5OCBDIDQ0MC4wNDcgMzQyLjA5OCA0MzguMjA3IDM0Mi4xMTQgNDM2LjM2MiAzNDIuMTM4IEMgMzc3LjYwMSAzNDIuOTIyIDMyMS43NjUgMzU1LjUzNSAyNzEuMTAzIDM3Ny42ODEgQyA2MDYuODg2IDI2OS41NjcgODE4Ljk0NCA0NjcuNjE1IDg1NC40NjIgNzY1LjEzMyBMIDg2OS4xNDIgNzYzLjQ4MyBDIDgzOC4zNTQgNDkyLjE1NCA2NzUuMjQyIDM0MS45NDggNDQxLjg4OCAzNDIuMDk4IFoiIHRyYW5zZm9ybT0ibWF0cml4KC0wLjM1NjU4MiwgMC45MzQyNjQsIC0wLjkzNDI2NCwgLTAuMzU2NTgyLCAxMjU2Ljc1OTQ5MywgMTY5LjE4MjU1MikiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgwLjc2MjQ5MywgMCwgMCwgMC43NjI0OTMsIDE5LjI5NDY0NywgLTcxNi4zMjI4MTUpIj4KICAgICAgICA8cGF0aCBkPSJNIDU2Ni40NjYgMTA4OS4xMzcgTCA1NjYuNDY2IDExNDguMjIyIEMgNTY1Ljg2NyAxMTQ4LjIxOSA1NjUuMjY3IDExNDguMjE3IDU2NC42NjcgMTE0OC4yMTcgQyA1NjEuNDgxIDExNDguMjE3IDU1OC4zMSAxMTQ4LjI1OSA1NTUuMTU0IDExNDguMzQxIEwgNTU1LjE1NCAxMDg5LjEzNyBaIE0gOTA4LjI5IDE0NzcuMTQ2IEwgOTU2Ljk4NyAxNDc3LjE0NiBMIDk1Ni45ODcgMTQ4OC40NTggTCA5MDguNTY5IDE0ODguNDU4IEMgOTA4LjUzOSAxNDg0LjY5MyA5MDguNDQ3IDE0ODAuOTIyIDkwOC4yOSAxNDc3LjE0NiBaIE0gNTY2LjQ2NiAxODM1LjAxMyBMIDU2Ni40NjYgMTg3Ni40NjcgTCA1NTUuMTU0IDE4NzYuNDY3IEwgNTU1LjE1NCAxODM0Ljg4NiBDIDU1OC4zMTggMTgzNC45NzMgNTYxLjQ5IDE4MzUuMDE3IDU2NC42NjcgMTgzNS4wMTcgQyA1NjUuMjY3IDE4MzUuMDE3IDU2NS44NjcgMTgzNS4wMTYgNTY2LjQ2NiAxODM1LjAxMyBaIE0gMjIwLjc3NSAxNDg4LjQ1OCBMIDE2OS42NTcgMTQ4OC40NTggTCAxNjkuNjU3IDE0NzcuMTQ2IEwgMjIxLjA4OSAxNDc3LjE0NiBDIDIyMC45MjEgMTQ4MC45MDkgMjIwLjgxNiAxNDg0LjY4IDIyMC43NzUgMTQ4OC40NTggWiIgc3R5bGU9ImZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgc3Ryb2tlOiBub25lOyIgYng6b3JpZ2luPSIwIDAiLz4KICAgICAgICA8cGF0aCBkPSJNIDc2MC4xMjEgMTE0My4zMTEgTCA3MTcuMzM2IDEyMTcuNDE3IEMgNzE1LjcyIDEyMTYuNTE4IDcxNC4wOTYgMTIxNS42MzIgNzEyLjQ2NSAxMjE0Ljc2MSBMIDc1NS4zMTggMTE0MC41MzcgWiBNIDgzMC4xMjIgMTMyNC4yMDMgTCA5MDAuNDI0IDEyODMuNjE0IEwgOTAzLjE5OCAxMjg4LjQxNyBMIDgzMy4wNCAxMzI4LjkyMyBDIDgzMi4wOCAxMzI3LjMzOSA4MzEuMTA3IDEzMjUuNzY2IDgzMC4xMjIgMTMyNC4yMDMgWiBNIDg0MC41OTkgMTY0MS4xMzcgTCA5MDMuMTk3IDE2NzcuMjc4IEwgOTAwLjQyNCAxNjgyLjA4MiBMIDgzNy45MTEgMTY0NS45OSBDIDgzOC44MjEgMTY0NC4zOCA4MzkuNzE3IDE2NDIuNzYyIDg0MC41OTkgMTY0MS4xMzcgWiBNIDcyNS4xNjggMTc2MS44NDMgTCA3NjAuMTIyIDE4MjIuMzg1IEwgNzU1LjMxOCAxODI1LjE1OCBMIDcyMC4zNzkgMTc2NC42NDEgQyA3MjEuOTg1IDE3NjMuNzIyIDcyMy41ODIgMTc2Mi43ODkgNzI1LjE2OCAxNzYxLjg0MyBaIE0gNDAzLjUzOCAxNzYwLjkzMiBMIDM2Ni40NTYgMTgyNS4xNTkgTCAzNjEuNjUzIDE4MjIuMzg2IEwgMzk4LjgwMiAxNzU4LjA0MiBDIDQwMC4zNzIgMTc1OS4wMTkgNDAxLjk1MSAxNzU5Ljk4MiA0MDMuNTM4IDE3NjAuOTMyIFogTSAyODkuNTggMTY0Mi42ODkgTCAyMjEuMzUgMTY4Mi4wODIgTCAyMTguNTc3IDE2NzcuMjc5IEwgMjg2Ljk0NCAxNjM3LjgwNyBDIDI4Ny44MDcgMTYzOS40MzcgMjg4LjY4NSAxNjQxLjA2NSAyODkuNTggMTY0Mi42ODkgWiBNIDI5NC4zNTQgMTMzMi4xNjggTCAyMTguNTc2IDEyODguNDE3IEwgMjIxLjM1IDEyODMuNjE0IEwgMjk3LjIxMyAxMzI3LjQxNCBDIDI5Ni4yNDYgMTMyOC45OSAyOTUuMjkzIDEzMzAuNTc1IDI5NC4zNTQgMTMzMi4xNjggWiBNIDQwNi4wNzkgMTIyMC4yNTkgTCAzNjEuNjUzIDExNDMuMzExIEwgMzY2LjQ1NyAxMTQwLjUzNyBMIDQxMC44ODkgMTIxNy40OTUgQyA0MDkuMjc2IDEyMTguNDAzIDQwNy42NzMgMTIxOS4zMjQgNDA2LjA3OSAxMjIwLjI1OSBaIiBzdHlsZT0iZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IG5vbmU7IiBieDpvcmlnaW49IjAgMCIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8cmVjdCB4PSI0MjkuMzY3IiB5PSI0MjUuOTc5IiB3aWR0aD0iMjAuMDAzIiBoZWlnaHQ9IjIxLjczNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTkxIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAwLjk5OTk5OSwgLTMwMS4zNzcwNzUsIC0yMTkuNDk4NDM0KSIvPgogICAgPHJlY3QgeD0iNDQ2Ljg1MyIgeT0iMjUuNDYyIiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05MyIvPgogICAgPHJlY3QgeD0iLTEzNS45NTYiIHk9IjYwNS4xNDEiIHdpZHRoPSIzOS44NTEiIGhlaWdodD0iMzkuODUxIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTQiIHRyYW5zZm9ybT0ibWF0cml4KDAuOTk5OTk5LCAwLCAwLCAxLCA4NDYuMTc2NzU2LCAtMzk0Ljk1NjAyNCkiLz4KICAgIDxyZWN0IHg9IjIyNS43NzkiIHk9IjY4OS44MzYiIHdpZHRoPSIyNS45OSIgaGVpZ2h0PSIyNS45OSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk1Ii8+CiAgICA8cmVjdCB4PSI1OTQuMDEzIiB5PSI3MzcuMTQyIiB3aWR0aD0iMjAuNzkyIiBoZWlnaHQ9IjIyLjUyNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk2Ii8+CiAgICA8cmVjdCB4PSIzODcuMjM1IiB5PSI0NzkuMzk3IiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05OCIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMDAwMDEsIDAsIDAsIDAuOTk5OTk5LCAzNjUuMjc0OTY2LCA3OS4yOTUyNDEpIi8+CiAgICA8cmVjdCB4PSI0MjEuOTYyIiB5PSI3NzUuOTM3IiB3aWR0aD0iMzIuOTIiIGhlaWdodD0iMzQuNjUzIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTkiLz4KICAgIDxyZWN0IHg9Ii02Ni45MzkiIHk9Ii01NjguOTc4IiB3aWR0aD0iMjAuODY3IiBoZWlnaHQ9IjIwLjc5MiIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTEwMSIgdHJhbnNmb3JtPSJtYXRyaXgoLTEsIDAsIDAsIDAuOTk5OTk3LCAzMS4zNTY5MjgsIDk4NC43MzYzMDYpIi8+CiAgPC9nPgo8L3N2Zz4=);background-repeat:no-repeat;background-position:-725px -145px;background-size:1024px 1024px}}.gray,.popover-helptip .button-close,.popover-share .bar-footer .button-close,.popover-share .bar-header span{color:grey!important}.gray b,.popover-helptip .button-close b,.popover-share .bar-footer .button-close b,.popover-share .bar-header span b{color:grey!important}.gray a,.icon-help a,.popover-helptip .button-close a,.popover-share .bar-footer .button-close a,.popover-share .bar-header span a,.positive a,.text-editable:hover a{color:inherit}.gray a:hover,.icon-help a:hover,.popover-helptip .button-close a:hover,.popover-share .bar-footer .button-close a:hover,.popover-share .bar-header span a:hover,.positive a:hover,.text-editable:hover a:hover{color:inherit}.gray a:visited,.icon-help a:visited,.popover-helptip .button-close a:visited,.popover-share .bar-footer .button-close a:visited,.popover-share .bar-header span a:visited,.positive a:visited,.text-editable:hover a:visited{color:inherit}.item a{text-decoration:none}.no-padding{padding:0!important}.avatar-member{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAQAAABpN6lAAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfgBA0LKSJACf7RAAAFqElEQVR42u2dbUjdZRjGf+c4dTndFnO+TRcD3ZIxdVlJL2PSIHDZBqtRaINojWRrgR8a4fDbIOrzoIKIMay2iGpQsg0y4xRZIk5i1NTaik3TZeRcvmzl0wc7qTPz6Lnv5/kfz/86XzxyuM59Xf/r//o893MCBqtIoYgSSsgjndWkk8RV+v959dFPP9/wm82CAtYM2MCTPMZGgnN87iZNvMdH1mww+q8Es9e0m/nhhjltnjG361enL3+HOT9P8ZMYNC+YhFg2IN2cWbD4MNrN3bFqQIm5FLV8Y4wZMbtj0YBdZlhEvjHGjJsXY82A+8yomPwJ1OhUqnMazKOVTGHOUe7lW/lS5zorLwSJnBKXD0s5SUpsGHCAzQqsUMgr8qTyu8AqulmpYgCMcQd9spTyCahTkw/JHJCmlE5AIj2kqxkAA6xlWJJQOgEVqvJhFY/LEkobUKUqH2Cbtw0oVTdgqyyd7DEgiWES1C1YxyU5MtkEFFiQD/dLkskacKcF+ZAb7waIXmbHogEZ3jVANJyxaEDAigHJ8W6AKDRuh2MKfgJcF+AafgJ8A+IcfgJcF+AafgJcF+AafgJE2URvU2aFqM2SzwSXM8ASCwaMkc9lKTLJBNRbkQ/JvCRHJpeANPpZasUAuEa21PiQXAJ2WJMPy9ktRSVnwBPW5IPgCJScAXdZNSDHewbcsGpAmvcMGLVqgNhkGTkDfrVqQLv3DHjfqgGnpYjkrgMyuGLpQgigkO9liOQS0M+H1uS/JSVf9l5gBV9RaEH+TxRxTYpM8l5gkEcZUJc/zB45+dK3wz9QhW4LiuERQpKE0k+EzvKuqgENNMsSyj8SO6lqwFFpQvmpskv4kTwl+e3ydxzyCfhTfiv9i9flKTX6BVZymWUK8ofI4bo0qcZj8d85psAKDfLytRonC7ig8Ii8hA75UnUGRrr4RJyzRUO+3sjQq8J8hjqdQrUMCAkfsV/jM51C9Zqnl3GOfCGuixRpHABBc3D0D/bwlwiTYa+WfN3R4RZeFuFRiz9orx+QSEvUF6+K8Qft+QE3eSpqDsX4g40VJKL9AuU5B/4MEdcFuIZvgOsCXEPbgFQPMDg1INsDDL4BLg2IfqRIeaxJ24CdHmD4X+heCaZxNerJk2OsZkivRN0EVAvMHU2mWrNEzQSk0C1yCOslX3bViKnQTECt0BE8m1q9IvUSUEaz2NTJUcr5OrYMyKWVLEG+X7hHboL0VOjsArk0isqHLBp1WrM1DCijlU3irJtopcz7BqRwmGbhrR9GFs0cFl9PTHBpujRTY3qEF9GbiR5TY9K8tJxeKtlkU8hOHrLUMgNjNHGK7+ilN9pHpvMxYAXVPKu0Upwc2nmTtxmM+PMRRiXB7DcD6vGWwoDZH+lqtJEl4EGOUux6084THTzPF3N/bO6zQA4NhGJOPhQToiGCxoo5InLQDLnOc1QYMgcXvgsk8QZPu96QAjjGc7P3s8xuQAYf8IDr2oXwJbvon58BG2lkreu6BfEz2zkfuQEb+FxhYVy36GMrFyIzYB0h1riuVwFX2MLFW/858zSYR9OilA9raJo5i/nWBGQSosB1pYroYsv0lYmnJyDIiUUtHwo4MV3zdAPqKXddoTrKqZ/6duouUM6ncTFcPs62yb6TSQPS6ZBrSfY4eigOd7qGt3iA43EjH3I4Hp58FTZgHxWuq7KKCvZN/DGxC6TSveiu/OZCH/lcDyfgUNzJh0wOwUQCcujS+PEKz2OYAnqCwJG4lA8pHIGAKaI9Ls7+/4VxNgfMGR52XYdDnA0Yyz846DXEa/h9A3wDfAN8A3wDfAOAIL2uS3CK3iBtrmtwira4NyBg1nOO21zX4QgjlATp1OrMjwHU0RkwEOBjtruuxQEaqcQEAUMltYy4rscqRqilEjN1XGA9VZRSqt2k5By9tNHGO3ROvP0bpkYvBeY8k00AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTYtMDQtMTNUMTE6NDE6MzQrMDI6MDCAxbwoAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE2LTA0LTEzVDExOjQxOjM0KzAyOjAw8ZgElAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII=)}.avatar.disable{opacity:.7}.avatar-wallet{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAQAAABpN6lAAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAADdcAAA3XAUIom3gAAAAHdElNRQfgBA0JMBOJU4OdAAAB2klEQVR42u3au0ocUQCH8e+IxFRKUohrkG0Eu4BiLrCFDxDBNtjoI1gYTJnGQrRInc4HyBuopNHgBVZIwCJFsHBXLURtQiIyKYyFN3B3zJyd3e/X7e7MmXP+e26zOyBJkiRJkiRJkiRJkiRJkppVSF9E0sk0r+jKuOYnrLMQTqMHkHSzQTHS17fLy3CYroi21JWYj9Z8KDIfvwdUKAC7bGfc+CH6gGrojTyJJBemMr/u+4sLpy2njRZnAAZgAK2t/YHKGUzeZlzz5w2yFU6/EKVsQHAIGIABGIABGIABRN4ILbOVcc1fM9IQCfp7gHOAARiAAbgMXpuhH/GJ0brK/sG78OVfKR0cXPnsQ/iYkwAYY6LOM4eZpXR5q3/t77bH+RkCO5HObZQeEL4nQ7ypcwh8boIAIJQpuwoYQMsugwBJ/73L/h1+3vr+OYtXXn/Lzz7gCV8ZqOH4LUrhz4155IzJvA6B0VqaDwzHu7f/PwEsc1zT8RXWmmoOCJWkl9L95wBWbw6AvO8DfrHkMmgABmAABtDw0j8gUaWHeA9K7odC7GVwhXGgGOmB2ZX4PaDAJs8i9d89XoRq5AAgecoMg3Rm3PhTysyFIyRJkiRJkiRJkiRJkiRJku7wFyuiadmIs5Q9AAAAAElFTkSuQmCC)}.popup-container.confirm .popup,.popup-container.warning .popup{min-width:250px!important;width:350px!important}.popup-container.confirm .popup-head h1,.popup-container.confirm .popup-head h2,.popup-container.confirm .popup-head h3,.popup-container.confirm .popup-head h5,.popup-container.confirm .popup-head h6,.popup-container.confirm .popup-head p,.popup-container.warning .popup-head h1,.popup-container.warning .popup-head h2,.popup-container.warning .popup-head h3,.popup-container.warning .popup-head h5,.popup-container.warning .popup-head h6,.popup-container.warning .popup-head p{color:#fff}.popup-container.warning .popup-head{background-color:#ef473a}.popup-container.confirm .popup-head{background-color:#387ef5}body{--refresher-bg-height:100px;--refresher-background-color:inherit}.refresher-positive-900-bg{--refresher-background-color:#1A237E}.refresher-dark-100-bg{--refresher-background-color:#555}.platform-android .refresher-dark-100-bg:before,.platform-android .refresher-positive-900-bg:before{background-color:var(--refresher-background-color);position:absolute;display:block;top:0;width:100%;height:var(--refresher-bg-height,100px);z-index:-10;content:" "}.platform-android .scroll-refresher{z-index:50}.platform-ios .refresher-dark-100-bg,.platform-ios .refresher-positive-900-bg{background-color:var(--refresher-background-color)!important}.platform-ios .refresher-dark-100-bg .scroll,.platform-ios .refresher-positive-900-bg .scroll{background-color:#fff;bottom:auto;min-height:100%}.refresher-dark-100-bg .scroll-refresher .ionic-refresher-content,.refresher-light .scroll-refresher .ionic-refresher-content,.refresher-positive-900-bg .scroll-refresher .ionic-refresher-content{color:#fff}.refresher-dark-100-bg .scroll-refresher .spinner,.refresher-light .scroll-refresher .spinner,.refresher-positive-900-bg .scroll-refresher .spinner{stroke:#fff;fill:#fff}.view-wallet{--refresher-bg-height:200px}.view-wallet .hero{height:200px}.view-wallet .hero h4:after{content:' ';display:inline-block}.view-wallet .item-text-wrap{white-space:normal!important}.view-wallet .item .comment{font-style:italic!important}.popover-helptip .view-wallet .item h3 .button-close,.popover-share .bar-footer .view-wallet .item h3 .button-close,.popover-share .bar-header .view-wallet .item h3 span,.view-wallet .item h3 .gray,.view-wallet .item h3 .popover-helptip .button-close,.view-wallet .item h3 .popover-share .bar-footer .button-close,.view-wallet .item h3 .popover-share .bar-header span{font-size:11px!important}.view-wallet .list .item span{display:inline}.view-wallet .item-divider .badge{top:16px!important}.view-wallet .item.item-wallet-event{padding-top:5px;padding-bottom:5px;min-height:30px;max-height:auto;height:auto}.view-wallet .item.item-wallet-event:last-child{min-height:48px}#menu .footer .view-wallet .item.item-icon-left.item-wallet-event .icon-help,.view-wallet .item.item-icon-left.item-wallet-event #menu .footer .icon-help,.view-wallet .item.item-icon-left.item-wallet-event .icon,.view-wallet .item.item-icon-left.item-wallet-event .icon-alert,.view-wallet .item.item-icon-left.item-wallet-event .icon-help{font-size:17px;height:18px;top:6px}.view-identity .qrcode,.view-wallet .qrcode{position:absolute;display:block;top:0;right:0;width:0;height:0;background:#fff;z-index:1;-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important;overflow:hidden}.view-identity .qrcode img,.view-wallet .qrcode img{display:float;float:right;width:0;height:0;z-index:1;transition:all .5s ease-out!important}.view-identity .qrcode.on,.view-wallet .qrcode.on{width:50px;height:50px;padding:3px;margin:7px}.view-identity .qrcode.on img,.view-wallet .qrcode.on img{width:44px;height:44px}.view-identity .qrcode.on.active,.view-wallet .qrcode.on.active{margin:0!important;padding:10px;width:200px;height:200px}.view-identity .qrcode.on.active img,.view-wallet .qrcode.on.active img{width:180px;height:180px}@media screen and (max-width:991px){.view-identity .hero.hero-qrcode-active h1,.view-identity .hero.hero-qrcode-active h2,.view-identity .hero.hero-qrcode-active h3,.view-identity .hero.hero-qrcode-active h4,.view-identity .hero.hero-qrcode-active h5,.view-identity .hero.hero-qrcode-active i.avatar,.view-wallet .hero.hero-qrcode-active h1,.view-wallet .hero.hero-qrcode-active h2,.view-wallet .hero.hero-qrcode-active h3,.view-wallet .hero.hero-qrcode-active h4,.view-wallet .hero.hero-qrcode-active h5,.view-wallet .hero.hero-qrcode-active i.avatar{margin-right:200px}}.popover-wallet-actions{height:400px}@media screen and (max-width:991px){.view-wallet-tx{--refresher-bg-height:100px}.view-wallet-tx .hero{height:100px}}@media screen and (min-width:992px){.view-wallet-tx{--refresher-bg-height:140px}.view-wallet-tx .hero{height:140px}}.view-wallet-tx .item-text-wrap{white-space:normal!important}.view-wallet-tx .item .comment{font-style:italic!important}.popover-helptip .view-wallet-tx .item h3 .button-close,.popover-share .bar-footer .view-wallet-tx .item h3 .button-close,.popover-share .bar-header .view-wallet-tx .item h3 span,.view-wallet-tx .item h3 .gray,.view-wallet-tx .item h3 .popover-helptip .button-close,.view-wallet-tx .item h3 .popover-share .bar-footer .button-close,.view-wallet-tx .item h3 .popover-share .bar-header span{font-size:11px!important}.view-wallet-tx .list .item span{display:inline}.view-wallet-tx .item-divider .badge{top:16px!important}.stable-100-bg{background-color:#f2f2f2!important}.item-tx{border-top:solid 1px #d3d3d3!important;padding-bottom:6px;padding-top:8px;margin:0!important}.item-tx .badge-energized{background-color:rgba(255,201,0,.3);color:#888!important}.item-tx .badge{right:1%!important;top:13px}.item-tx .badge-white{background-color:#fff}.item-tx .vertical-center{position:absolute;top:30%;width:40%}.item-tx .width-cup{width:175px}.expert-mode .item-tx .item-note{top:8%}.expert-mode .item-tx .badge-secondary{top:calc(8% + 23px)!important}.view-identity{--refresher-bg-height:200px;--refresher-background-color:#555}.view-identity .member{--refresher-background-color:#1A237E}.view-identity .hero{height:200px;background-color:var(--refresher-background-color)}.card .card-header{font-size:90%;opacity:.8}.card .stable-900-bg,.card.stable-900-bg,.item .stable-900-bg,.item-complex .item-content .stable-900-bg,.item-radio .item-content .stable-900-bg,.item.stable-900-bg{background-color:#e0e0e0!important}.card .item{background:inherit}.card .stable-bg,.card.stable-bg,.item .stable-bg,.item-complex .item-content .stable-bg,.item-radio .item-content .stable-bg,.item.stable-bg{background-color:#f8f8f8!important}.card .card-header{padding-top:5px!important;padding-bottom:0!important;min-height:25px}.card .item .card-footer{margin-bottom:5px}.card .card-avatar .avatar,.card.card-avatar .avatar{box-shadow:0 3px 4px 0 rgba(0,0,0,.26);top:7px;background-color:#d9d9d9}.card .card-avatar img.avatar,.card.card-avatar img.avatar{border:0;min-height:54px;min-width:54px}.card .card-avatar .item.item-avatar,.card.card-avatar .item.item-avatar{padding-top:10px;padding-bottom:2px;min-height:45px!important;margin-bottom:1px}.card .card-avatar .card-footer,.card.card-avatar .card-footer{padding-left:88px;overflow:hidden}#menu .footer .popover-helptip .card .card-avatar .card-footer .icon-bottom-center.icon-help a,#menu .footer .popover-helptip .card .card-avatar .card-footer .icon-bottom-right.icon-help a,#menu .footer .popover-helptip .card .card-avatar .card-footer .icon-center.icon-help a,#menu .footer .popover-helptip .card .card-avatar .card-footer .icon-right.icon-help a,#menu .footer .popover-helptip .card.card-avatar .card-footer .icon-bottom-center.icon-help a,#menu .footer .popover-helptip .card.card-avatar .card-footer .icon-bottom-right.icon-help a,#menu .footer .popover-helptip .card.card-avatar .card-footer .icon-center.icon-help a,#menu .footer .popover-helptip .card.card-avatar .card-footer .icon-right.icon-help a,.card .card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help a,.card .card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help a,.card .card-avatar .card-footer #menu .footer .popover-helptip .icon-center.icon-help a,.card .card-avatar .card-footer #menu .footer .popover-helptip .icon-right.icon-help a,.card .card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help a,.card .card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help a,.card .card-avatar .card-footer .popover-helptip #menu .footer .icon-center.icon-help a,.card .card-avatar .card-footer .popover-helptip #menu .footer .icon-right.icon-help a,.card .card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-alert a,.card .card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-help a,.card .card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-alert a,.card .card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-help a,.card .card-avatar .card-footer .popover-helptip .icon-center.icon-alert a,.card .card-avatar .card-footer .popover-helptip .icon-center.icon-help a,.card .card-avatar .card-footer .popover-helptip .icon-right.icon-alert a,.card .card-avatar .card-footer .popover-helptip .icon-right.icon-help a,.card .card-avatar .card-footer .popover-helptip .icon.icon-bottom-center a,.card .card-avatar .card-footer .popover-helptip .icon.icon-bottom-right a,.card .card-avatar .card-footer .popover-helptip .icon.icon-center a,.card .card-avatar .card-footer .popover-helptip .icon.icon-right a,.card .card-avatar .card-footer .pull-right a,.card.card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-center.icon-help a,.card.card-avatar .card-footer #menu .footer .popover-helptip .icon-bottom-right.icon-help a,.card.card-avatar .card-footer #menu .footer .popover-helptip .icon-center.icon-help a,.card.card-avatar .card-footer #menu .footer .popover-helptip .icon-right.icon-help a,.card.card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-center.icon-help a,.card.card-avatar .card-footer .popover-helptip #menu .footer .icon-bottom-right.icon-help a,.card.card-avatar .card-footer .popover-helptip #menu .footer .icon-center.icon-help a,.card.card-avatar .card-footer .popover-helptip #menu .footer .icon-right.icon-help a,.card.card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-alert a,.card.card-avatar .card-footer .popover-helptip .icon-bottom-center.icon-help a,.card.card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-alert a,.card.card-avatar .card-footer .popover-helptip .icon-bottom-right.icon-help a,.card.card-avatar .card-footer .popover-helptip .icon-center.icon-alert a,.card.card-avatar .card-footer .popover-helptip .icon-center.icon-help a,.card.card-avatar .card-footer .popover-helptip .icon-right.icon-alert a,.card.card-avatar .card-footer .popover-helptip .icon-right.icon-help a,.card.card-avatar .card-footer .popover-helptip .icon.icon-bottom-center a,.card.card-avatar .card-footer .popover-helptip .icon.icon-bottom-right a,.card.card-avatar .card-footer .popover-helptip .icon.icon-center a,.card.card-avatar .card-footer .popover-helptip .icon.icon-right a,.card.card-avatar .card-footer .pull-right a,.popover-helptip #menu .footer .card .card-avatar .card-footer .icon-bottom-center.icon-help a,.popover-helptip #menu .footer .card .card-avatar .card-footer .icon-bottom-right.icon-help a,.popover-helptip #menu .footer .card .card-avatar .card-footer .icon-center.icon-help a,.popover-helptip #menu .footer .card .card-avatar .card-footer .icon-right.icon-help a,.popover-helptip #menu .footer .card.card-avatar .card-footer .icon-bottom-center.icon-help a,.popover-helptip #menu .footer .card.card-avatar .card-footer .icon-bottom-right.icon-help a,.popover-helptip #menu .footer .card.card-avatar .card-footer .icon-center.icon-help a,.popover-helptip #menu .footer .card.card-avatar .card-footer .icon-right.icon-help a,.popover-helptip .card .card-avatar .card-footer .icon-bottom-center.icon-alert a,.popover-helptip .card .card-avatar .card-footer .icon-bottom-center.icon-help a,.popover-helptip .card .card-avatar .card-footer .icon-bottom-right.icon-alert a,.popover-helptip .card .card-avatar .card-footer .icon-bottom-right.icon-help a,.popover-helptip .card .card-avatar .card-footer .icon-center.icon-alert a,.popover-helptip .card .card-avatar .card-footer .icon-center.icon-help a,.popover-helptip .card .card-avatar .card-footer .icon-right.icon-alert a,.popover-helptip .card .card-avatar .card-footer .icon-right.icon-help a,.popover-helptip .card .card-avatar .card-footer .icon.icon-bottom-center a,.popover-helptip .card .card-avatar .card-footer .icon.icon-bottom-right a,.popover-helptip .card .card-avatar .card-footer .icon.icon-center a,.popover-helptip .card .card-avatar .card-footer .icon.icon-right a,.popover-helptip .card.card-avatar .card-footer .icon-bottom-center.icon-alert a,.popover-helptip .card.card-avatar .card-footer .icon-bottom-center.icon-help a,.popover-helptip .card.card-avatar .card-footer .icon-bottom-right.icon-alert a,.popover-helptip .card.card-avatar .card-footer .icon-bottom-right.icon-help a,.popover-helptip .card.card-avatar .card-footer .icon-center.icon-alert a,.popover-helptip .card.card-avatar .card-footer .icon-center.icon-help a,.popover-helptip .card.card-avatar .card-footer .icon-right.icon-alert a,.popover-helptip .card.card-avatar .card-footer .icon-right.icon-help a,.popover-helptip .card.card-avatar .card-footer .icon.icon-bottom-center a,.popover-helptip .card.card-avatar .card-footer .icon.icon-bottom-right a,.popover-helptip .card.card-avatar .card-footer .icon.icon-center a,.popover-helptip .card.card-avatar .card-footer .icon.icon-right a{margin-right:8px}.a.underline:active,.underline a:active,.underline a:focus,.underline a:hover,a.underline:focus,a.underline:hover{outline:1px!important;text-decoration:underline!important}.card-avatar-small .card,.card-avatar-small .card .card-avatar,.card-avatar-small .card.card-avatar,.card-avatar-small.card{min-height:45px}.card-avatar-small .card .avatar,.card-avatar-small .card .card-avatar .avatar,.card-avatar-small .card .card-avatar .item-avatar .avatar,.card-avatar-small .card .item-avatar .avatar,.card-avatar-small .card.card-avatar .avatar,.card-avatar-small .card.card-avatar .item-avatar .avatar,.card-avatar-small.card .avatar,.card-avatar-small.card .item-avatar .avatar{box-shadow:0 2px 2px 0 rgba(0,0,0,.26);height:30px!important;width:30px!important;left:5px!important}.card-avatar-small .card .card-avatar .item.item-avatar,.card-avatar-small .card .item.item-avatar,.card-avatar-small .card.card-avatar .item.item-avatar,.card-avatar-small.card .item.item-avatar{min-height:25px!important;padding-left:42px!important}.card-avatar-small .card .card-avatar .card-footer,.card-avatar-small .card .card-footer,.card-avatar-small .card.card-avatar .card-footer,.card-avatar-small.card .card-footer{padding-top:0;padding-left:42px!important}.gallery .card-gallery,.gallery .card.card-gallery{margin-bottom:15px!important;float:left;display:block}.gallery .card-gallery img,.gallery .card.card-gallery img{max-height:150px}.gallery .card-gallery-new{max-height:199px}.list .item.text-left{text-align:left!important}.list .item.large-button-bar,.list .item.text-center{text-align:center!important}.list .item.text-right{text-align:right!important}.list .item-divider.item-divider-top-border{border-top:solid 1px rgba(0,0,0,.12)}.lookupForm .list .item.item-avatar{min-height:80px!important}.lookupForm .list .item.item-avatar.item-checkbox .item-content{padding-left:47px;min-height:auto!important;height:auto!important}.fade-in{opacity:0;-webkit-transform:translate3d(-30px,1px,0);-webkit-transition:all 1s ease-in-out}.fade-in.on{opacity:1;-webkit-transform:translate3d(0,0,0)}.item-avatar{min-height:80px!important}.item-avatar .item-content i.item-image:first-child,.item-avatar .item-content img.item-image:first-child,.item-avatar .item-content>i:first-child,.item-avatar .item-content>img:first-child,.item-avatar i.item-image:first-child,.item-avatar img.item-image:first-child,.item-avatar-left .item-content i.item-image:first-child,.item-avatar-left .item-content img.item-image:first-child,.item-avatar-left .item-content>i:first-child,.item-avatar-left .item-content>img:first-child,.item-avatar-left i.item-image:first-child,.item-avatar-left img.item-image:first-child,.item-avatar-left>i:first-child,.item-avatar-left>img:first-child,.item-avatar>i:first-child,.item-avatar>img:first-child{color:#d9d9d9;background-color:#f8f8f8;border:solid 1px #d9d9d9;overflow:hidden!important;font-size:45px!important;line-height:56px;width:100%!important;max-height:56px!important;max-width:56px!important;top:12px!important}#menu .footer .item-avatar .item-content>.icon-help:first-child:before,#menu .footer .item-avatar .item-image.icon-help:first-child:before,#menu .footer .item-avatar.item-icon-right .icon-help:first-child:before,#menu .footer .item-avatar>.icon-help:first-child:before,.item-avatar #menu .footer .item-content>.icon-help:first-child:before,.item-avatar #menu .footer .item-image.icon-help:first-child:before,.item-avatar .icon.item-image:first-child:before,.item-avatar .item-content>.icon-alert:first-child:before,.item-avatar .item-content>.icon-help:first-child:before,.item-avatar .item-content>.icon:first-child:before,.item-avatar .item-image.icon-alert:first-child:before,.item-avatar .item-image.icon-help:first-child:before,.item-avatar.item-icon-right #menu .footer .icon-help:first-child:before,.item-avatar.item-icon-right .icon-alert:first-child:before,.item-avatar.item-icon-right .icon-help:first-child:before,.item-avatar.item-icon-right .icon:first-child:before,.item-avatar>.icon-alert:first-child:before,.item-avatar>.icon-help:first-child:before,.item-avatar>.icon:first-child:before{width:56px!important}#menu .footer .item-avatar.item-icon-right .icon-help:last-child,#menu .footer .item-avatar.item-icon-right.ink .ion-ios-arrow-right.icon-help,.item-avatar.item-icon-right #menu .footer .icon-help:last-child,.item-avatar.item-icon-right .icon-alert:last-child,.item-avatar.item-icon-right .icon-help:last-child,.item-avatar.item-icon-right .icon:last-child,.item-avatar.item-icon-right.ink #menu .footer .ion-ios-arrow-right.icon-help,.item-avatar.item-icon-right.ink .icon.ion-ios-arrow-right,.item-avatar.item-icon-right.ink .ion-ios-arrow-right.icon-alert,.item-avatar.item-icon-right.ink .ion-ios-arrow-right.icon-help{left:auto}.item.item-icon-left>i.avatar:first-child{position:absolute;display:flex;height:100%;align-items:center;font-size:16px;left:16px;top:8px;max-height:32px;max-width:32px}.item.item-checkbox.item-avatar * .item-content>i.avatar:first-child,.item.item-checkbox.item-avatar * .item-content>i.item-image:first-child,.item.item-checkbox.item-avatar *>i.avatar:first-child,.item.item-checkbox.item-avatar *>i.item-image:first-child,.item.item-checkbox.item-avatar .item-content>i.avatar:first-child,.item.item-checkbox.item-avatar .item-content>i.item-image:first-child,.item.item-checkbox.item-avatar>i.avatar:first-child,.item.item-checkbox.item-avatar>i.item-image:first-child{left:65px}.item.item-checkbox .item-content .item-avatar,.item.item-checkbox.item-avatar .item-content{padding-left:65px}#menu .footer .item-icon-left.item-icon-right.ink .ion-ios-arrow-right.icon-help,.item-icon-left.item-icon-right.ink #menu .footer .ion-ios-arrow-right.icon-help,.item-icon-left.item-icon-right.ink .icon.ion-ios-arrow-right,.item-icon-left.item-icon-right.ink .ion-ios-arrow-right.icon-alert,.item-icon-left.item-icon-right.ink .ion-ios-arrow-right.icon-help{left:auto}@media screen and (max-width:767px){#menu .footer .item.item-icon-right>.icon-help:last-child,#menu .footer .item.item-icon-right>.ion-ios-arrow-right.icon-help,.item.item-icon-right>.icon-alert:last-child,.item.item-icon-right>.icon-help:last-child,.item.item-icon-right>.icon.ion-ios-arrow-right,.item.item-icon-right>.icon:last-child,.item.item-icon-right>.ion-ios-arrow-right.icon-alert,.item.item-icon-right>.ion-ios-arrow-right.icon-help{right:1px}}.item em{font-weight:700!important}@media screen and (max-width:991px){.item .badge{right:16px}}@media screen and (min-width:992px){.list .item.item-border-large{margin-bottom:1px;border-bottom:solid 1px #ccc!important}.list.item-border-large .item{border-bottom:solid 1px #ccc!important;margin:0 0 1px}.list.item-border-large .item-divider{border-top:0}}.list .item.item-border{border-bottom:solid 1px #ccc!important;margin-bottom:1px}.list .item.item-small-height{padding-top:2px;padding-bottom:0;min-height:24px}.list .item.item-small-height .badge{padding-top:0!important;top:inherit}.list .item.item-small-height .badge.badge-assertive,.list .item.item-small-height .badge.badge-balanced,.list .item.item-small-height .badge.badge-calm,.list .item.item-small-height .badge.badge-editable:hover,.list .item.item-small-height .badge.badge-energized,.list .item.item-small-height .badge.badge-positive,.list .item.item-small-height .badge.badge-royal{top:1px!important;padding-top:3px!important;padding-bottom:2px!important}.form-errors:first-child{margin:5px 0}.form-errors:last-child{margin:5px 0 0}.form-error{padding:0 16px;font-size:12px;color:red;vertical-align:middle;text-align:end;top:0;position:relative}.item-input-error{border-bottom:2px solid red!important}.item-input.item-button-right input,.item-input.item-button-right textarea{margin-right:100px}.item-input.item-button-right .button,.item-input.item-button-right button{top:6px}.item-input.item-button-right.item-floating-label input,.item-input.item-button-right.item-floating-label textarea{padding-right:100px}.item-input.item-button-right.item-floating-label .button{top:inherit;bottom:6px}.item-input.item-button-right.item-floating-label .button-icon{height:inherit}.item.item-button-right .badge,.item.item-icon-right .badge{right:43px}@media screen and (max-width:767px){.badge{text-overflow:ellipsis!important;white-space:nowrap;overflow:hidden!important;max-width:300px!important;display:block!important}.badge:empty{display:none!important}.item.item-button-right .badge,.item.item-icon-right .badge{right:26px!important}}.badge-editable:hover{cursor:pointer}.badge-editable:hover:before{content:" "}.platform-ipad .bar-title{border-color:#111;background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%)}.platform-ipad .bar-title .title{background-color:#fff;margin-left:0;margin-right:0;height:44px}.bar .badge-button{margin:0!important;padding:0 4px!important;font-size:10px;position:absolute!important;top:5px;right:3px}.text-editable:hover{cursor:pointer}.text-editable:hover:after{content:""}.item h2 .text-editable:hover:after{font-size:14px}.modal.modal-full-height{bottom:0}@media screen and (max-width:767px){.modal{top:0!important;left:0!important;bottom:0;min-height:100%!important;width:100%!important}}@media screen and (max-width:991px){.modal{bottom:0}.modal .swiper-pagination{visibility:hidden!important}.modal.modal-full-height{top:0}.modal.modal-full-height ion-content.keyboard-up .scroll{min-height:calc(100% + 67px)}}@media (min-width:992px){.modal.modal-full-height{min-height:80%}}.modal.about .bar.bar-header .button+.title{left:0!important}.item-button-right .item-content>.button,.item-button-right .item-content>.buttons,.item-button-right>.button,.item-button-right>.buttons{top:16px}.item-button-right .item-content>.button.button-small,.item-button-right .item-content>.buttons .button-small,.item-button-right>.button.button-small,.item-button-right>.buttons .button-small{font-size:14px}.item.large-button-bar{margin-bottom:10px}.item-avatar-left-padding{padding-left:95px}.item-thumbnail-left-padding{padding-left:106px}.item-thumbnail-left,.item.item-thumbnail-left{min-height:100px!important}.item-thumbnail-left .item-content i.item-image,.item-thumbnail-left .item-content>i:first-child,.item-thumbnail-left i.item-image,.item-thumbnail-left>i:first-child{color:#d9d9d9;background-color:#f8f8f8;overflow:hidden!important;font-size:50px!important;line-height:80px;padding:0 15px;background-position:center;background-size:cover;display:inline-block}@media screen and (max-width:400px){.card>.item.item-thumbnail-left,.item-thumbnail-left,.item-thumbnail-left .item-content{padding-left:84px!important}.item-thumbnail-left .item-content img.item-image,.item-thumbnail-left .item-content>img:first-child,.item-thumbnail-left img.item-image,.item-thumbnail-left>img:first-child{max-width:70px;max-height:70px}.item h2{font-size:13px!important}}.item-icon-left-padding{padding-left:40px}.item-icon-right-padding{padding-right:40px}.text-keep-lines{white-space:pre-line!important}.text-italic{font-style:italic!important}.menu.menu-left{background-color:#f5f5f5}.menu.menu-left .item{opacity:.75;color:#000}.menu.menu-left .item-button-right .item-content>.button,.menu.menu-left .item-button-right .item-content>.buttons,.menu.menu-left .item-button-right>.button,.menu.menu-left .item-button-right>.buttons{top:8px!important}.menu.menu-left .item.active{background-color:#b2e0ff!important}.menu.menu-left .item.active .item-content{background-color:transparent}.menu.menu-left .item-menu-disable{color:#444!important}@media screen and (max-width:991px){.menu.menu-left .item.item-divider{min-height:2px;height:2px;padding-top:0;padding-bottom:0}.menu.menu-left .item,.menu.menu-left .item.item-complex .item-content{height:40px;min-height:40px;padding-top:12px}.menu.menu-left .item.item-complex{padding-top:0}.menu.menu-left .item.item-button-right .button{height:30px;min-height:30px;top:4px}.menu.menu-left ion-content.has-footer{bottom:0!important}.menu.menu-left .bar-header{background-color:#1a237e;color:#fff;height:150px;padding-right:0!important}.platform-ios.platform-cordova .menu.menu-left .bar-header{height:calc(constant(safe-area-inset-top) + 150px);height:calc(env(safe-area-inset-top) + 150px)}.menu.menu-left .bar-header .hero{height:150px;box-shadow:none}.menu.menu-left .bar-header .hero .content{bottom:0}.menu.menu-left .has-header{top:150px}.platform-ios.platform-cordova .menu.menu-left .has-header{top:calc(constant(safe-area-inset-top) + 150px);top:calc(env(safe-area-inset-top) + 150px)}}@media screen and (min-width:768px){.menu.menu-left .item.item-divider{min-height:5px;height:5px}.menu.menu-left .footer a{font-size:14px!important;color:grey!important}}@media screen and (min-width:992px){.menu.menu-left{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA1MDAgNTAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOmJ4PSJodHRwczovL2JveHktc3ZnLmNvbSI+CiAgPGcgdHJhbnNmb3JtPSJtYXRyaXgoMC42MDgyNjEsIDAsIDAsIDAuNjA4MjYxLCAtMjAuMDg0OTc2LCAzLjI1NTczNikiPgogICAgPGc+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC43ODsiIGlkPSJwYXRoLTEwIiBkPSJNIDQxOS4xMzMgODUuNzM4IEMgNDE3LjI5NSA4NS43MzkgNDE1LjQ1NSA4NS43NTQgNDEzLjYxMSA4NS43NzggQyAzNTQuODUyIDg2LjU2MSAyOTkuMDIzIDk5LjE3NCAyNDguMzU4IDEyMS4zMiBDIDU4NC4xMjEgMTMuMjA2IDc5Ni4xNzUgMjExLjI2IDgzMS43IDUwOC43NzMgTCA4NDYuMzgzIDUwNy4xMjQgQyA4MTUuNTg2IDIzNS44MDEgNjUyLjQ3NyA4NS41ODggNDE5LjEzMyA4NS43MzggWiIgdHJhbnNmb3JtPSJtYXRyaXgoMC45NjM3MywgMC4yNjY4NzgsIC0wLjI2Njg3OCwgMC45NjM3MywgODkuNTA1MjMxLCAtMTM2LjYxNTA2MSkiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDE7IiBpZD0icGF0aC0zIiBkPSJNIDE0Ni4wMzcgMTk0LjA2NSBDIDE0NC4yMDEgMTk0LjA2NiAxNDIuMzYxIDE5NC4wODEgMTQwLjUxNyAxOTQuMTA0IEMgODEuNzYgMTk0Ljg4OCAyNS45MzEgMjA3LjUwMyAtMjQuNzM2IDIyOS42NDggQyAzMTEuMDI5IDEyMS41MzEgNTIzLjA4MyAzMTkuNTgzIDU1OC42MDQgNjE3LjA5MyBMIDU3My4yODQgNjE1LjQ0MyBDIDU0Mi40OSAzNDQuMTIyIDM3OS4zODUgMTkzLjkxMyAxNDYuMDM3IDE5NC4wNjUgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuMTgwOTg4LCAtMC45ODM0ODUsIDAuOTgzNDg1LCAtMC4xODA5ODgsIC0zOS4yOTg1ODEsIDcwNS44OTc1NDQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMSIgZD0iTSA0ODcuNzQ0IDE5My4wODQgQyA0ODUuOTA2IDE5My4wODUgNDg0LjA2NyAxOTMuMSA0ODIuMjIzIDE5My4xMjMgQyA0MjMuNDY0IDE5My45MDcgMzY3LjYzNSAyMDYuNTIgMzE2Ljk3NSAyMjguNjY4IEMgNjUyLjcyNiAxMjAuNTUyIDg2NC43NzUgMzE4LjYwNSA5MDAuMjk5IDYxNi4xMDkgTCA5MTQuOTc5IDYxNC40NiBDIDg4NC4xODQgMzQzLjE0NCA3MjEuMDgxIDE5Mi45MzUgNDg3Ljc0NCAxOTMuMDg0IFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNjE5OTk3LCAwLjc4NDYwNSwgLTAuNzg0NjA1LCAwLjYxOTk5NywgNTIzLjA2NzIzMSwgLTM0My4zMzE1MzkpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjg0OyIgaWQ9InBhdGgtMTIiIGQ9Ik0gMjk1Ljk2OSA0MzIuNzU3IEMgMjk0LjEzMSA0MzIuNzU4IDI5Mi4yOTMgNDMyLjc3MyAyOTAuNDQ5IDQzMi43OTcgQyAyMzEuNjg4IDQzMy41OCAxNzUuODYgNDQ2LjE5NCAxMjUuMTk4IDQ2OC4zNDEgQyA0NjAuOTU3IDM2MC4yMjYgNjczLjAwNSA1NTguMjggNzA4LjUyNiA4NTUuNzg2IEwgNzIzLjIwNyA4NTQuMTM5IEMgNjkyLjQxMiA1ODIuODE5IDUyOS4zMSA0MzIuNjA5IDI5NS45NjkgNDMyLjc1NyBaIiB0cmFuc2Zvcm09Im1hdHJpeCgtMC45Nzg4NDksIDAuMjA0NTg0LCAtMC4yMDQ1ODQsIC0wLjk3ODg0OSwgOTYzLjgyMDc5NiwgMTExNi4zNjcyOTMpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAwLjQ7IiBpZD0icGF0aC0xMyIgZD0iTSAxNTguMDM2IDE0OC44MyBDIDE1Ni4yIDE0OC44MzMgMTU0LjM2IDE0OC44NDYgMTUyLjUxNiAxNDguODcyIEMgOTMuNzU5IDE0OS42NTMgMzcuOTMgMTYyLjI2NyAtMTIuNzM0IDE4NC40MTEgQyAzMjMuMDIyIDc2LjMwMSA1MzUuMDc2IDI3NC4zNTIgNTcwLjYwNCA1NzEuODU3IEwgNTg1LjI4NiA1NzAuMjA4IEMgNTU0LjQ4MyAyOTguODkxIDM5MS4zOCAxNDguNjgzIDE1OC4wMzYgMTQ4LjgzIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuMzM4NjE0LCAtMC45NDA5MjYsIDAuOTQwOTI2LCAwLjMzODYxNCwgLTExNS41OTUxNTgsIDQ4My43MDU5ODQpIiBieDpvcmlnaW49IjAuNSAwLjUiLz4KICAgICAgPHBhdGggc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IGZpbGwtcnVsZTogZXZlbm9kZDsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDFweDsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1saW5lam9pbjogbWl0ZXI7IHN0cm9rZS1vcGFjaXR5OiAxOyBvcGFjaXR5OiAxOyIgaWQ9InBhdGgtMTQiIGQ9Ik0gNTAxLjAxOSAyODguMjkyIEMgNDk5LjE4MSAyODguMjkzIDQ5Ny4zNCAyODguMzA4IDQ5NS40OTYgMjg4LjMzMSBDIDQzNi43MzYgMjg5LjExNSAzODAuOTA4IDMwMS43MjYgMzMwLjI0MyAzMjMuODc0IEMgNjY2LjAwNCAyMTUuNzU3IDg3OC4wNjIgNDEzLjgxMiA5MTMuNTg2IDcxMS4zMjIgTCA5MjguMjY4IDcwOS42NzMgQyA4OTcuNDY4IDQzOC4zNTIgNzM0LjM2MSAyODguMTQxIDUwMS4wMTkgMjg4LjI5MiBaIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjE2NDY1NiwgMC45ODYzNTEsIC0wLjk4NjM1MSwgMC4xNjQ2NTYsIDk4Mi44NTcyNjYsIC0yMzMuNDUyMDYzKSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMC40OyIgaWQ9InBhdGgtMTUiIGQ9Ik0gMTkyLjk1NCAzNzYuNTIxIEMgMTkxLjExNSAzNzYuNTIyIDE4OS4yNzcgMzc2LjUzNyAxODcuNDMzIDM3Ni41NjEgQyAxMjguNjc0IDM3Ny4zNDQgNzIuODQ1IDM4OS45NTggMjIuMTgxIDQxMi4xMDMgQyAzNTcuOTQgMzAzLjk4OSA1NjkuOTg3IDUwMi4wNDUgNjA1LjUwNSA3OTkuNTUzIEwgNjIwLjE4OCA3OTcuOTA1IEMgNTg5LjM5MiA1MjYuNTg0IDQyNi4yOTUgMzc2LjM2OSAxOTIuOTU0IDM3Ni41MjEgWiIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuOTMxNDA0LCAtMC4zNjM5ODgsIDAuMzYzOTg4LCAtMC45MzE0MDQsIDQxOS40OTkwMDYsIDExODIuNTk5ODA5KSIgYng6b3JpZ2luPSIwLjUgMC41Ii8+CiAgICAgIDxwYXRoIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBmaWxsLXJ1bGU6IGV2ZW5vZGQ7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAxcHg7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2Utb3BhY2l0eTogMTsgb3BhY2l0eTogMTsiIGlkPSJwYXRoLTE2IiBkPSJNIDIyMS42MTQgNjMuOTczIEMgMjE5Ljc3NyA2My45NzYgMjE3LjkzOCA2My45OSAyMTYuMDk0IDY0LjAxNSBDIDE1Ny4zMzQgNjQuNzk1IDEwMS41MDYgNzcuNDA5IDUwLjg0MSA5OS41NTQgQyAzODYuNTk4IC04LjU1OSA1OTguNjUxIDE4OS40OTcgNjM0LjE3MyA0ODcuMDAxIEwgNjQ4Ljg1NCA0ODUuMzU0IEMgNjE4LjA1OCAyMTQuMDM3IDQ1NC45NTQgNjMuODI0IDIyMS42MTQgNjMuOTczIFoiIHRyYW5zZm9ybT0ibWF0cml4KDAuNzUwNDUyLCAtMC42NjA5MjUsIDAuNjYwOTI1LCAwLjc1MDQ1MiwgLTcwLjgwMzMyMiwgMjkwLjkyMDI3MykiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8cGF0aCBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgZmlsbC1ydWxlOiBldmVub2RkOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMXB4OyBzdHJva2UtbGluZWNhcDogYnV0dDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW9wYWNpdHk6IDE7IG9wYWNpdHk6IDAuNDsiIGlkPSJwYXRoLTE3IiBkPSJNIDQ0MS44ODggMzQyLjA5OCBDIDQ0MC4wNDcgMzQyLjA5OCA0MzguMjA3IDM0Mi4xMTQgNDM2LjM2MiAzNDIuMTM4IEMgMzc3LjYwMSAzNDIuOTIyIDMyMS43NjUgMzU1LjUzNSAyNzEuMTAzIDM3Ny42ODEgQyA2MDYuODg2IDI2OS41NjcgODE4Ljk0NCA0NjcuNjE1IDg1NC40NjIgNzY1LjEzMyBMIDg2OS4xNDIgNzYzLjQ4MyBDIDgzOC4zNTQgNDkyLjE1NCA2NzUuMjQyIDM0MS45NDggNDQxLjg4OCAzNDIuMDk4IFoiIHRyYW5zZm9ybT0ibWF0cml4KC0wLjM1NjU4MiwgMC45MzQyNjQsIC0wLjkzNDI2NCwgLTAuMzU2NTgyLCAxMjU2Ljc1OTQ5MywgMTY5LjE4MjU1MikiIGJ4Om9yaWdpbj0iMC41IDAuNSIvPgogICAgICA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgwLjc2MjQ5MywgMCwgMCwgMC43NjI0OTMsIDE5LjI5NDY0NywgLTcxNi4zMjI4MTUpIj4KICAgICAgICA8cGF0aCBkPSJNIDU2Ni40NjYgMTA4OS4xMzcgTCA1NjYuNDY2IDExNDguMjIyIEMgNTY1Ljg2NyAxMTQ4LjIxOSA1NjUuMjY3IDExNDguMjE3IDU2NC42NjcgMTE0OC4yMTcgQyA1NjEuNDgxIDExNDguMjE3IDU1OC4zMSAxMTQ4LjI1OSA1NTUuMTU0IDExNDguMzQxIEwgNTU1LjE1NCAxMDg5LjEzNyBaIE0gOTA4LjI5IDE0NzcuMTQ2IEwgOTU2Ljk4NyAxNDc3LjE0NiBMIDk1Ni45ODcgMTQ4OC40NTggTCA5MDguNTY5IDE0ODguNDU4IEMgOTA4LjUzOSAxNDg0LjY5MyA5MDguNDQ3IDE0ODAuOTIyIDkwOC4yOSAxNDc3LjE0NiBaIE0gNTY2LjQ2NiAxODM1LjAxMyBMIDU2Ni40NjYgMTg3Ni40NjcgTCA1NTUuMTU0IDE4NzYuNDY3IEwgNTU1LjE1NCAxODM0Ljg4NiBDIDU1OC4zMTggMTgzNC45NzMgNTYxLjQ5IDE4MzUuMDE3IDU2NC42NjcgMTgzNS4wMTcgQyA1NjUuMjY3IDE4MzUuMDE3IDU2NS44NjcgMTgzNS4wMTYgNTY2LjQ2NiAxODM1LjAxMyBaIE0gMjIwLjc3NSAxNDg4LjQ1OCBMIDE2OS42NTcgMTQ4OC40NTggTCAxNjkuNjU3IDE0NzcuMTQ2IEwgMjIxLjA4OSAxNDc3LjE0NiBDIDIyMC45MjEgMTQ4MC45MDkgMjIwLjgxNiAxNDg0LjY4IDIyMC43NzUgMTQ4OC40NTggWiIgc3R5bGU9ImZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgc3Ryb2tlOiBub25lOyIgYng6b3JpZ2luPSIwIDAiLz4KICAgICAgICA8cGF0aCBkPSJNIDc2MC4xMjEgMTE0My4zMTEgTCA3MTcuMzM2IDEyMTcuNDE3IEMgNzE1LjcyIDEyMTYuNTE4IDcxNC4wOTYgMTIxNS42MzIgNzEyLjQ2NSAxMjE0Ljc2MSBMIDc1NS4zMTggMTE0MC41MzcgWiBNIDgzMC4xMjIgMTMyNC4yMDMgTCA5MDAuNDI0IDEyODMuNjE0IEwgOTAzLjE5OCAxMjg4LjQxNyBMIDgzMy4wNCAxMzI4LjkyMyBDIDgzMi4wOCAxMzI3LjMzOSA4MzEuMTA3IDEzMjUuNzY2IDgzMC4xMjIgMTMyNC4yMDMgWiBNIDg0MC41OTkgMTY0MS4xMzcgTCA5MDMuMTk3IDE2NzcuMjc4IEwgOTAwLjQyNCAxNjgyLjA4MiBMIDgzNy45MTEgMTY0NS45OSBDIDgzOC44MjEgMTY0NC4zOCA4MzkuNzE3IDE2NDIuNzYyIDg0MC41OTkgMTY0MS4xMzcgWiBNIDcyNS4xNjggMTc2MS44NDMgTCA3NjAuMTIyIDE4MjIuMzg1IEwgNzU1LjMxOCAxODI1LjE1OCBMIDcyMC4zNzkgMTc2NC42NDEgQyA3MjEuOTg1IDE3NjMuNzIyIDcyMy41ODIgMTc2Mi43ODkgNzI1LjE2OCAxNzYxLjg0MyBaIE0gNDAzLjUzOCAxNzYwLjkzMiBMIDM2Ni40NTYgMTgyNS4xNTkgTCAzNjEuNjUzIDE4MjIuMzg2IEwgMzk4LjgwMiAxNzU4LjA0MiBDIDQwMC4zNzIgMTc1OS4wMTkgNDAxLjk1MSAxNzU5Ljk4MiA0MDMuNTM4IDE3NjAuOTMyIFogTSAyODkuNTggMTY0Mi42ODkgTCAyMjEuMzUgMTY4Mi4wODIgTCAyMTguNTc3IDE2NzcuMjc5IEwgMjg2Ljk0NCAxNjM3LjgwNyBDIDI4Ny44MDcgMTYzOS40MzcgMjg4LjY4NSAxNjQxLjA2NSAyODkuNTggMTY0Mi42ODkgWiBNIDI5NC4zNTQgMTMzMi4xNjggTCAyMTguNTc2IDEyODguNDE3IEwgMjIxLjM1IDEyODMuNjE0IEwgMjk3LjIxMyAxMzI3LjQxNCBDIDI5Ni4yNDYgMTMyOC45OSAyOTUuMjkzIDEzMzAuNTc1IDI5NC4zNTQgMTMzMi4xNjggWiBNIDQwNi4wNzkgMTIyMC4yNTkgTCAzNjEuNjUzIDExNDMuMzExIEwgMzY2LjQ1NyAxMTQwLjUzNyBMIDQxMC44ODkgMTIxNy40OTUgQyA0MDkuMjc2IDEyMTguNDAzIDQwNy42NzMgMTIxOS4zMjQgNDA2LjA3OSAxMjIwLjI1OSBaIiBzdHlsZT0iZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IG5vbmU7IiBieDpvcmlnaW49IjAgMCIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8cmVjdCB4PSI0MjkuMzY3IiB5PSI0MjUuOTc5IiB3aWR0aD0iMjAuMDAzIiBoZWlnaHQ9IjIxLjczNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTkxIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAwLjk5OTk5OSwgLTMwMS4zNzcwNzUsIC0yMTkuNDk4NDM0KSIvPgogICAgPHJlY3QgeD0iNDQ2Ljg1MyIgeT0iMjUuNDYyIiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05MyIvPgogICAgPHJlY3QgeD0iLTEzNS45NTYiIHk9IjYwNS4xNDEiIHdpZHRoPSIzOS44NTEiIGhlaWdodD0iMzkuODUxIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTQiIHRyYW5zZm9ybT0ibWF0cml4KDAuOTk5OTk5LCAwLCAwLCAxLCA4NDYuMTc2NzU2LCAtMzk0Ljk1NjAyNCkiLz4KICAgIDxyZWN0IHg9IjIyNS43NzkiIHk9IjY4OS44MzYiIHdpZHRoPSIyNS45OSIgaGVpZ2h0PSIyNS45OSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk1Ii8+CiAgICA8cmVjdCB4PSI1OTQuMDEzIiB5PSI3MzcuMTQyIiB3aWR0aD0iMjAuNzkyIiBoZWlnaHQ9IjIyLjUyNSIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTk2Ii8+CiAgICA8cmVjdCB4PSIzODcuMjM1IiB5PSI0NzkuMzk3IiB3aWR0aD0iMjUuOTkiIGhlaWdodD0iMjUuOTkiIHN0eWxlPSJkaXNwbGF5OiBpbmxpbmU7IG9wYWNpdHk6IDE7IGZpbGw6IHJnYigyNTUsIDI1NSwgMjU1KTsgZmlsbC1vcGFjaXR5OiAxOyBzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMzQuOTsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2Utb3BhY2l0eTogMC45OTYwNzg7IiBpZD0icGF0aC05OCIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMDAwMDEsIDAsIDAsIDAuOTk5OTk5LCAzNjUuMjc0OTY2LCA3OS4yOTUyNDEpIi8+CiAgICA8cmVjdCB4PSI0MjEuOTYyIiB5PSI3NzUuOTM3IiB3aWR0aD0iMzIuOTIiIGhlaWdodD0iMzQuNjUzIiBzdHlsZT0iZGlzcGxheTogaW5saW5lOyBvcGFjaXR5OiAxOyBmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7IGZpbGwtb3BhY2l0eTogMTsgc3Ryb2tlOiBub25lOyBzdHJva2Utd2lkdGg6IDM0Ljk7IHN0cm9rZS1taXRlcmxpbWl0OiA0OyBzdHJva2UtZGFzaGFycmF5OiBub25lOyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLW9wYWNpdHk6IDAuOTk2MDc4OyIgaWQ9InBhdGgtOTkiLz4KICAgIDxyZWN0IHg9Ii02Ni45MzkiIHk9Ii01NjguOTc4IiB3aWR0aD0iMjAuODY3IiBoZWlnaHQ9IjIwLjc5MiIgc3R5bGU9ImRpc3BsYXk6IGlubGluZTsgb3BhY2l0eTogMTsgZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBmaWxsLW9wYWNpdHk6IDE7IHN0cm9rZTogbm9uZTsgc3Ryb2tlLXdpZHRoOiAzNC45OyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDA7IHN0cm9rZS1vcGFjaXR5OiAwLjk5NjA3ODsiIGlkPSJwYXRoLTEwMSIgdHJhbnNmb3JtPSJtYXRyaXgoLTEsIDAsIDAsIDAuOTk5OTk3LCAzMS4zNTY5MjgsIDk4NC43MzYzMDYpIi8+CiAgPC9nPgo8L3N2Zz4=);background-repeat:no-repeat;background-position:-500px -100px;background-size:1024px 1024px;background-color:#f5f5f5;height:100%}}.certifications .item-divider .badge{top:16px!important}.certifications-lg .avatar-large{left:auto;position:relative;font-size:55px!important;height:88px;width:88px;color:#d9d9d9;background-color:#e0e0e0;border:solid 1px #d9d9d9}.icon-help{font-size:38px;vertical-align:middle}.icon-alert{font-size:38px;vertical-align:middle}#menu .footer .icon-help{font-size:25px!important;position:absolute;left:12px;top:8px;z-index:99}.popover-helptip{background-color:rgba(68,68,68,.85)!important;height:auto!important}.popover-helptip .button-close{padding:8px;height:25px;font-size:18.2px}.popover-helptip a,.popover-helptip a:active,.popover-helptip a:hover{text-decoration:underline}.nobackdrop .popover-backdrop.active{background-color:transparent!important}.helptip-anchor,.helptip-anchor-center,.helptip-anchor-left,.helptip-anchor-right{display:block;position:absolute;width:100%;bottom:0}.helptip-anchor-center{text-align:center}.helptip-anchor-left{text-align:left}.helptip-anchor-right{text-align:right}.helptip-anchor a:before,.helptip-anchor-center a:before,.helptip-anchor-left a:before,.helptip-anchor-right a:before{content:" "}@media (max-width:767px){.popover-helptip{width:auto}}#menu .footer .popover-helptip .icon-left.icon-help,.popover-helptip #menu .footer .icon-left.icon-help,.popover-helptip .icon-left.icon-alert,.popover-helptip .icon-left.icon-help,.popover-helptip .icon.icon-left{font-size:30px;position:relative;top:8px;left:8px}#menu .footer .popover-helptip .icon-right.icon-help,.popover-helptip #menu .footer .icon-right.icon-help,.popover-helptip .icon-right.icon-alert,.popover-helptip .icon-right.icon-help,.popover-helptip .icon.icon-right{font-size:30px;position:relative;top:8px;right:8px}#menu .footer .popover-helptip .icon-center.icon-help,.popover-helptip #menu .footer .icon-center.icon-help,.popover-helptip .icon-center.icon-alert,.popover-helptip .icon-center.icon-help,.popover-helptip .icon.icon-center{font-size:30px;width:100%;text-align:center;position:relative;top:8px;height:0}#menu .footer .popover-helptip .icon-bottom-right.icon-help,.popover-helptip #menu .footer .icon-bottom-right.icon-help,.popover-helptip .icon-bottom-right.icon-alert,.popover-helptip .icon-bottom-right.icon-help,.popover-helptip .icon.icon-bottom-right{font-size:30px;position:relative;bottom:8px;right:8px}#menu .footer .popover-helptip .icon-bottom-left.icon-help,.popover-helptip #menu .footer .icon-bottom-left.icon-help,.popover-helptip .icon-bottom-left.icon-alert,.popover-helptip .icon-bottom-left.icon-help,.popover-helptip .icon.icon-bottom-left{font-size:30px;position:relative;bottom:8px;left:8px}#menu .footer .popover-helptip .icon-bottom-center.icon-help,.popover-helptip #menu .footer .icon-bottom-center.icon-help,.popover-helptip .icon-bottom-center.icon-alert,.popover-helptip .icon-bottom-center.icon-help,.popover-helptip .icon.icon-bottom-center{font-size:30px;position:relative;width:100%;bottom:8px;text-align:center;height:0}.popover.popover-profile{height:200px}.popover.popover-profile .avatar{height:90px;width:90px;left:20px;top:20px}.popover.popover-profile .avatar{border:solid 1px #d9d9d9}.popover.popover-profile .bar.bar-footer{height:58px}.popover.popover-profile .bar.bar-footer .col .button{max-width:inherit;width:100%;padding:5px 0;margin:0}.popover.popover-profile .bar .button-positive,.popover.popover-profile .bar .button-text{background-color:#387ef5!important}.popover.popover-profile .bar .button-stable{color:#444!important}.bar-header .button-icon .avatar{height:35px;width:35px;position:relative;left:0;top:4px;border:solid 1px #d9d9d9}.bar-header .button-icon .avatar.active{background-color:#e0e0e0}.bar-header .button-icon .avatar{height:31px;width:31px;position:relative;left:0;top:6px}.list .badge .badge-secondary,.list .badge.badge-secondary{font-size:12px;font-style:italic;top:37px;font-weight:400!important;margin-right:0;padding:3px 8px}.list .item-avatar .badge.badge-avatar{position:absolute!important;left:60px!important;right:inherit!important;top:15px!important;margin:0!important;padding:0 4px!important;font-size:10px}.popover.popover-login-methods{height:280px;width:290px}.popover.popover-login-methods.auth{height:204px}@media (max-width:767px){.popover.popover-login-methods{height:256px}.popover.popover-login-methods.auth{height:204px}}.ion-es-user-api:before{content:url(../img/logo.small.cs.dune.svg)}.ion-bma-tor-api:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAATEAYAAAChBNO0AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAB3lJREFUWMPNmGtUVNcVx/93mBlmgEGeAyhYUoSERhmM9ZHSCL4AqURFEmSBEZOgWGqh0pqYNkREiIlxxSXqYpUoJhqVRWJ41tooKNYIGR8R8QlKAsj7PQ9k7tx7++Gc6VpQnctK4lo9X35zz+x79v7vM2fffYfB/8lYty4iIjFx/Oz0TEJpD2HTLwj1RmqwvbDw9OmjR3+8XylxHPBPcuk1QucbKIUn3GeZ/45eJlCWEfJfEJp3Ew6qqIADhNw3lsDHCrf1I9SMEi6XERpOEV7YRLn950q8lODUfcLJWVRIpkgCLGMG5S5q/kfKRXR+D0H7TSrIhfD2+B33JUiII0xZR6i4QljwiLC23HLDT915y2BIIIKY0J84DFsII/5NePHS2O9dqdDT8YTBdOezUwlzHxKyOT+XcMuQUCY93QQwv6TudkAKbygBhKAEMZMiuA7uGtc601HIETYL259loYASikNbif2uWU9LuGXQI2CqI5Q/rQw4Uvq6/86rUq0DpB9KG2xWrmzybvMt8FFnyBvmX6m5sbN/qiFT3294Pq9HUi1RSq4YE3+s8McXVUkela0g5BxoAr5MJgycR8i8Q+OmP1nfY3S+zbrbrgrKNdQ+gPDBNcIWvxFvw7GRBkChV+bbajvbg34951pwcYDUrDLfM2fZpGtrapK/XR1ikLCSQxKPG/8VIpaIxwv2CSNcyRH+ZgehcwFhz1l6BJLoDi2IIgwtpsvSwAevWxcu+BBmLiZ8iZ7d0BrC+C19tl2He9f+cKcitXhhaar8kGyJ/Dl5+txbihi7EuV+mZ1sozxavt9mhcQoiZTIVx3Hi1iE36pN1gU+aX6BPWHpAsI9VHBcJ2F4NGFCNWN9wUBavM7fInQvx2MHq6WZbiGsjL3N1JfdqgDWx2ZoNu4FKtnil8oLnhkMUsz+SPPu1mURbas+XuqX+KW7ndc2dYVS3Tjjps89CVA+fGxJaTY/YDira9GvO/cv5gFjwzx8fwNZt9qbkLv5+DiC/k5Y/AFhQBNEhsT613wppVnkF0AbE65EOCDkCHnAkYozyuNNQM2bpz87lxKuXey/PDo8unRnkmt66xs+yYemF866PENQqtllplzWH5g27Vce/ksBzRtzZJp7EmfhIr9X+HphHBgwYIrayfoZ9GlgmzXWv00rYZr/RIVPNAGhlG+JrEMbFcFTtlwmk20Gco9t/ir76gtVizetKAnPP1ATv3BDbYJqxvsqT6cwx2z4DysHzw7nA85rXZ2d2wAunq3mQgDNxrlzZnYBCg+7VMVqAJ8Je4VCFzuyflY9YcpHY917ORGGFU1MthBLqJOLJEAIox/iRVbsoPaOB9dUag4XSouDN80Nmdm/9fXIPaviohr8NhtN+lhjEcDam15kWwCPbVNe8wwFdMuH5uk6AVOaKce0CFAE2mUpUwHVQadGRwdA8BZG4GZxo6C1Jo2eZb+phPafEqpU1sM0BBK+R/uMcEYkAaiiwr4RsRsFBw4cfz6mbl7wy/y0Rv/h5+UB3qGZ/B4hht8B8LuFFfx2wCXHLcXFFeg/2VPcNxlQJtg/tDsOyJbKOGkqYC5idWwuYDNV8pZEAwiXUPW/3n19CWfT2oRXCSRfWQ/zPu0r9tNOs9YkloA+ygEROw5deIhOYZFdmMOAfZ7DC47tzsGT4pS8/s7QXf0WwKnTJdc5BeiWd6R0xQIOMY7xqn8A8lrbM/IRgPFkIphngJFso/ej+QDrZYpihwDmbWYX87fx7phuwilrqfA/j92wJ+5TCSGrscyIJeA8ZZ2I3SBsoYAtWvlWbhdfL+SzR9ledpugtmmXJtlwwPCRgSVDQYDiO6WXwgmQVksTpU3AUFR/xYAWQC860Qv0ft25vscDMMzXbzV0AEwxapnSJ7k10scZQ99JmG+th2mm/Y7wygQTIFgeiH8SScBtuEINN2Ztt7LjD11xP5R9H9Ho2BzedFBoFIqFemCgo8+jfw0gmybn5NHA4M6+GwM2gPRz2UaZFjCFjEaa7IG2qmbPlruA6dToSdMOAMuY1Yge7073HmE9rQ6S+TQB90X0PEf5yUQTcJiQvyxiRxsn5vfT5bMWB6X28tdwafBqRt65u6jfd+fCSMOw20Dd8BGgc1ZbZEcGwJawJnY3wDfwb/M1gL5E12B4Beha1v5x1z4AznCHCwAj9DCO91dOH3PafYRS+pbJXBDZKNqvWIq2aAK412gCSq3bWYoQ79K/t/uDPjNwVXpReznt875qTWXOWb+c9d+nNYU2pw/trw/QFlwvA/rcux/1vQv0xHfoesqgbyy6mX33HfT2nux8tccOECqFE0IZADd4wp1LosLpa/ZfHQhN9H8MNNONyLUeJm9L7dSWGan1G4y0pexeRTg5nS5Eqyi6CPrpe/yQgpkpeZMJwRlV3aRc1WyTtEpdrj0z5cMSvXF4jc7jtp9tgCJfEb+p9Eaydsn183OTZa/Lm2VHld2tUQ8+bY2Gg+nEaORooPkE8xfGh6lt3EAaoSO0un9Ci1xPztg4hxtpnLQfcaA1QaBHhKH/U7Q/S8g6We78Dzmv92D5rFiKAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTEwLTE0VDExOjU4OjIwKzA1OjAwUOI3hwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0xMC0xNFQxMTo1ODoyMCswNTowMCG/jzsAAAAvdEVYdHN2Zzpjb21tZW50AD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/5MH3awAAAABJRU5ErkJggg==)}.row-header{border-bottom:solid 1px #ccc!important;margin:0;min-height:28px!important}.col-header{text-align:center;display:block!important}.col-15{-webkit-box-flex:0;-webkit-flex:0 0 15%;-moz-box-flex:0;-moz-flex:0 0 15%;-ms-flex:0 0 15%;flex:0 0 15%;max-width:15%}.col-border-left{border-left:solid 1px #ccc!important}.col-border-right{border-right:solid 1px #ccc!important}.ion-spinner-small{height:14px;width:14px;line-height:14px;margin:0;padding:0}.ion-spinner-small svg{height:14px;width:14px}.icon-secondary{position:absolute;height:100%;display:flex;align-items:center;font-size:16px;left:25px;top:-7px}div[dropzone]{border:2px dashed #bbb;border-radius:5px;padding:15px;text-align:center;font:20pt bold;color:#bbb;margin-bottom:20px;cursor:pointer}div[dropzone] .item,div[dropzone] .list .item{text-align:left}div[dropzone]:hover{background-color:#f2f2f2}.button-fab-hero.button-fab-top-left,.button-fab-hero.button-fab-top-right,.hero .button-fab-top-left,.hero .button-fab-top-right{top:170px!important}.bar .button.button-fab.mini,.button.button-fab.mini{min-width:40px;min-height:40px}.button-fab-hero.button-fab-top-left.mini,.button-fab-hero.button-fab-top-right.mini,.hero .button-fab-top-left.mini,.hero .button-fab-top-right.mini{top:178px!important}.text-no-transform{text-transform:inherit}.button-icon-event,.item-icon-event{text-transform:inherit;pointer-events:none!important}#menu .footer .button-icon-event .icon-help,#menu .footer .item-icon-event .icon-help,.button-icon-event #menu .footer .icon-help,.button-icon-event .icon,.button-icon-event .icon-alert,.button-icon-event .icon-event,.button-icon-event .icon-help,.item-icon-event #menu .footer .icon-help,.item-icon-event .icon,.item-icon-event .icon-alert,.item-icon-event .icon-event,.item-icon-event .icon-help{pointer-events:all!important}.hero.dark-100-bg{background-color:#555}.hero.positive-900-bg{background-color:#1a237e!important}.hero.stable-bg{background-color:#f8f8f8!important}.popover-locked-outputs .item .badge{right:16px!important}.animate-show-hide.ng-hide{opacity:0}.animate-show-hide.ng-hide-add,.animate-show-hide.ng-hide-remove{transition:all linear .3s}.modal iframe.iframe-license{width:100%;height:calc(100% - 171px)!important}@media screen and (max-width:767px){.modal iframe.iframe-license{height:calc(100% - 104px)}}@media screen and (min-width:768px) and (max-width:991px) and (min-height:600px){.modal iframe.iframe-license{height:calc(100% - 171px)}}@media screen and (min-width:992px){.modal iframe.iframe-license{height:calc(100% - 171px)}.modal.modal-license iframe.iframe-license{height:calc(100% - 111px)!important}}.modal.modal-help .row.selected .col:first-child{font-weight:700}@media screen and (max-width:767px){.modal.modal-help .row .col:first-child{font-weight:700}.modal.modal-help h2{padding-left:10px}}.modal.modal-login .item.item-icon-right.item-text-wrap .item-content{margin-right:58px;text-overflow:ellipsis;overflow:hidden}.popover-locales{height:284px;width:200px}.popover-locales .item{height:48px}.buttons-tabs{display:block;height:57px;border:0;padding:16px 16px 0 16px;overflow:hidden}.buttons-tabs .button.button-tab:first-child{border-top-left-radius:15px}.buttons-tabs .button.button-tab:last-child{border-top-right-radius:15px}.buttons-tabs .button.button-tab.active{background-color:#b2e0ff}.buttons-tabs.border-bottom{border-bottom:solid 1px #ccc!important}@media screen and (max-width:767px){.buttons-tabs{padding:10px 10px 0 10px}.buttons-tabs .button.button-tab{padding:2px 10px 0 10px!important}} \ No newline at end of file diff --git a/assets/www/css/style.css b/assets/www/css/style.css index 673d6c1767a5429136ffb6f844c81abe449db287..f8bcc3291f97fd076feaeb9af87b52816740a00d 100644 --- a/assets/www/css/style.css +++ b/assets/www/css/style.css @@ -60,6 +60,9 @@ #transfer .list .item { border-bottom: solid 1px #ccc; } +#transfer .list .item.item-no-border { + border-bottom: 0; +} #transfer .item.item-icon-right input { padding-right: 50px !important; @@ -145,7 +148,22 @@ .settings .item-divider { background-color: #f5f5f5; } - +.settings .item .input-label{ + width: 80%; +} +.settings .item-toggle .input-label{ + display: inline; + width: auto; + max-width: 50%; +} +.settings .item-select .input-label{ + display: inline; + width: auto; + max-width: 50%; +} +.settings .item .badge { + top: 22px; +} .no-margin { margin: 0 !important; } @@ -178,6 +196,18 @@ padding-right: 6px; } +.list .item-peer.compacted { + padding-top: 0px; + padding-bottom: 0px; + min-height: 3px !important; + max-height: 3px !important; + border-bottom: double 1px #ddd !important; +} +.list .item-peer.compacted > * { + display: none; +} + + /********** Block items **********/ @@ -196,17 +226,17 @@ .item-block.item-block-empty { min-height: 24px !important; max-height: 24px !important; - padding-top: 0px; - padding-bottom: 0px; + padding-top: 0; + padding-bottom: 0; } .item-block.item-block-empty .badge { - padding-top: 0px !important; + padding-top: 0 !important; top: inherit; } .item-block.item-block-empty .badge.badge-balanced { - top: 0px !important; + top: 0 !important; padding-top: 3px !important; padding-bottom: 2px !important; } @@ -214,57 +244,20 @@ .item-block-empty.compacted { min-height: 3px !important; max-height: 3px !important; - border-bottom: 0px !important; + border-bottom: 0 !important; } .item-block.item-block-empty.compacted { border-bottom: double 1px #eee !important; } - -/********** - TX items -**********/ - -.item-tx{ - border-top: solid 1px lightgray !important; - margin-bottom: 4px ; - padding-bottom: 6px; - padding-top: 8px; - margin: 0 !important; -} - -.item-tx .badge{ - right : 1%; - top: 13px; -} - -.item-tx .vertical-center{ - position: absolute; - top: 30%; - width: 40%; -} - -.item-tx .width-cup{ - width: 175px; -} - -.expert-mode .item-tx .item-note { - top : 8%; -} - -.expert-mode .item-tx .badge-secondary { - top : 52% !important; -} - - /********** - Drop zone component + List of wallet **********/ -.dropzone { - cursor: pointer; +.list .item.item-wallet .badge{ + top: 29px; } -.dropzone.hover { - background: lawngreen; +.list .item.item-wallet { + height: 38px; } diff --git a/assets/www/dist/dist_js/app/api/app.js b/assets/www/dist/dist_js/app/api/app.js index fd764fc9172e006180744ebb829a6fca8896b30c..417f8efb1b95f282acc560f5f60a693a1b1d2574 100644 --- a/assets/www/dist/dist_js/app/api/app.js +++ b/assets/www/dist/dist_js/app/api/app.js @@ -5,6 +5,7 @@ // the 2nd parameter is an array of 'requires' // 'starter.controllers' is found in controllers.js angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht.translate', 'ngApi', 'angular-cache', 'angular.screenmatch', + 'FBAngular', // = angular-fullscreen // removeIf(no-device) 'ngCordova', // endRemoveIf(no-device) @@ -25,7 +26,7 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr }) .state('app.home', { - url: "/home?result&service&cancel", + url: "/home?result&service&cancel&node", views: { 'menuContent': { templateUrl: "templates/api/home.html", @@ -43,7 +44,7 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr .state('api.transfer', { cache: false, - url: "/payment/:pubkey?name&amount&udAmount&comment&redirect_url&cancel_url&demo", + url: "/payment/:pubkey?name&amount&udAmount&comment&preferred_node&redirect_url&cancel_url&demo&error", views: { 'menuContent': { templateUrl: "templates/api/transfer.html", @@ -56,9 +57,11 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr $urlRouterProvider.otherwise('/app/home'); }]) - .controller('ApiCtrl', ['$scope', '$state', '$translate', '$ionicPopover', 'Modals', 'csSettings', function ($scope, $state, $translate, $ionicPopover, Modals, csSettings){ + .controller('ApiCtrl', ['$scope', '$state', '$translate', '$ionicPopover', 'UIUtils', 'Modals', 'csSettings', function ($scope, $state, $translate, $ionicPopover, UIUtils, Modals, csSettings){ 'ngInject'; + // Fill locales + $scope.locales = angular.copy(csSettings.locales); $scope.showAboutModal = function(e) { e.preventDefault(); // avoid to open link href @@ -78,29 +81,20 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr /* -- show/hide locales popup -- */ $scope.showLocalesPopover = function(event) { - if (!$scope.localesPopover) { - // Fill locales - $scope.locales = angular.copy(csSettings.locales); - - $ionicPopover.fromTemplateUrl('templates/api/locales_popover.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/api/locales_popover.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.localesPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.localesPopover.remove(); - }); - $scope.localesPopover.show(event); - }); - } - else { - $scope.localesPopover.show(event); - } + } + }); }; $scope.hideLocalesPopover = function() { if ($scope.localesPopover) { $scope.localesPopover.hide(); + $scope.localesPopover = null; } }; }]) @@ -114,7 +108,8 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr amount: 100, comment: 'REFERENCE', name: 'www.domain.com', - redirect_url: 'http://www.domain.com/payment?ref={comment}&tx={tx}', + preferred_node: undefined, + redirect_url: 'http://www.domain.com/payment?ref={comment}&tx={tx}&node={node}', cancel_url: 'http://www.domain.com/payment?ref={comment}&cancel' }; $scope.transferButton = { @@ -152,7 +147,7 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr $scope.transferButton.style.icon = $scope.transferButton.icons[1/*Duniter icon*/]; $scope.transferDemoUrl = $rootScope.rootPath + $state.href('api.transfer', angular.merge({}, $scope.transferData, { demo: true, - redirect_url: $rootScope.rootPath + '#/app/home?service=payment&result={tx}', + redirect_url: $rootScope.rootPath + '#/app/home?service=payment&result={tx}&node={node}', cancel_url: $rootScope.rootPath + '#/app/home?service=payment&cancel' })); @@ -169,6 +164,9 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr if (state.stateParams && state.stateParams.cancel) { $scope.result.cancelled = true; } + if (state.stateParams && state.stateParams.node) { + $scope.result.node = state.stateParams.node; + } csCurrency.get() .then(function(currency) { @@ -230,8 +228,9 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr $scope.$watch('transferButton.style', $scope.computeTransferButtonHtml, true); }]) - .controller('ApiTransferCtrl', ['$scope', '$rootScope', '$timeout', '$controller', '$state', '$q', '$translate', '$filter', 'BMA', 'CryptoUtils', 'UIUtils', 'csCurrency', 'csTx', 'csWallet', 'csDemoWallet', function ($scope, $rootScope, $timeout, $controller, $state, $q, $translate, $filter, - BMA, CryptoUtils, UIUtils, csCurrency, csTx, csWallet, csDemoWallet){ + .controller('ApiTransferCtrl', ['$scope', '$rootScope', '$timeout', '$controller', '$state', '$q', '$translate', '$filter', '$window', '$ionicHistory', 'BMA', 'CryptoUtils', 'UIUtils', 'csSettings', 'csCurrency', 'csPlatform', 'csTx', 'csWallet', 'csDemoWallet', function ($scope, $rootScope, $timeout, $controller, $state, $q, $translate, $filter, + $window, $ionicHistory, BMA, CryptoUtils, UIUtils, csSettings, csCurrency, + csPlatform, csTx, csWallet, csDemoWallet){ 'ngInject'; // Initialize the super class and extend it. @@ -240,16 +239,41 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr $scope.loading = true; $scope.transferData = { amount: undefined, + amounts: undefined, comment: undefined, pubkey: undefined, name: undefined, redirect_url: undefined, - cancel_url: undefined + cancel_url: undefined, + node: undefined }; $scope.enter = function(e, state) { + $rootScope.errorState = state.stateName; + + if (!$scope.loading) return; // already enter + if (state.stateParams && state.stateParams.amount) { - $scope.transferData.amount = parseFloat(state.stateParams.amount.replace(new RegExp('[.,]'), '.')).toFixed(2) * 100; + var amountStr = state.stateParams.amount.trim(); + var amounts = ((amountStr.indexOf('|') !== -1) && amountStr.split('|')) + || ((amountStr.indexOf(' ') !== -1) && amountStr.split(' ')) + || ((amountStr.indexOf(';') !== -1) && amountStr.split(';')); + if (amounts){ + $scope.transferData.amounts = amounts.reduce(function(res, amountStr) { + var amount = normalizeAmount(amountStr); + return amount > 0 ? res.concat(amount) : res; + }, []); + if ($scope.transferData.amounts.length === 1) { + $scope.transferData.amount = $scope.transferData.amounts[0]; + delete $scope.transferData.amounts; + } + else { + $scope.transferData.amounts.sort(); + } + } + else { + $scope.transferData.amount = normalizeAmount(amountStr); + } } if (state.stateParams && state.stateParams.pubkey) { $scope.transferData.pubkey = state.stateParams.pubkey; @@ -269,27 +293,127 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr if (state.stateParams && state.stateParams.demo) { $scope.demo = true; } + + if (state.stateParams && state.stateParams.preferred_node) { + var + isHttpsMode = $window.location.protocol === 'https:', + useSsl = isHttpsMode, + preferredNode = state.stateParams.preferred_node; + var matches = /^(?:(http[s]?:)\/\/)(.*)$/.exec(preferredNode); + if (matches) { + useSsl = matches[1] === 'https:'; + preferredNode = matches[2]; + } + var parts = preferredNode.split(':'); + if (parts.length >= 1) { + var port = parts[1] || (useSsl ? 443 : 80); + $scope.node = { + host: parts[0], + port: port, + useSsl: useSsl || (port == 443) + }; + + // Add a fallback node that use SSL + if (!$scope.node.useSsl) { + var node = angular.copy($scope.node); + node.useSsl = true; + node.port = 443; + csSettings.data.fallbackNodes = csSettings.data.fallbackNodes || []; + csSettings.data.fallbackNodes.splice(0,0,node); + } + } + else { + console.warn("[api] Invalid preferred node address: {0}. Using default node." + state.stateParams.preferred_node); + } + } + + // Start + return $scope.start(); }; $scope.$on('$ionicView.enter', $scope.enter); + + $scope.start = function() { + if ($scope.starting) return; + + $scope.starting = true; + $scope.loading = true; + + // Set BMA node + if (!$scope.error && $scope.node && !BMA.node.same($scope.node.host, $scope.node.port)) { + console.debug("[api] Using preferred node: {0}:{1}".format($scope.node.host, $scope.node.port)); + BMA.stop(); + BMA.copy($scope.node); + $scope.node.server = BMA.server; + } + + // Start platform (or restart) platform + // This will start the BMA node + return csPlatform.restart() + .then(csCurrency.get) + .then(function(currency) { + $scope.currency = currency; + $scope.node = currency.node; + $scope.loading = false; + $scope.error = false; + $scope.starting = false; + // Reset history cache + $ionicHistory.clearCache(); + }) + // Error during load (BMA not alive ?) + .catch(function(err) { + console.error(err && err.message || err); + $scope.error = true; + $scope.loading = false; + $scope.starting = false; + + // Make sure to retry if user choose a fallback node + var unsubscribe = BMA.api.node.on.start($scope, function() { + $scope.start(); + unsubscribe(); + }); + }) + ; + }; + + function normalizeAmount(amountStr) { + return parseFloat((amountStr||'0').trim().replace(new RegExp('[.,]'), '.')).toFixed(2) * 100; + } + function onLogin(authData) { // User cancelled if (!authData) return $scope.onCancel(); + // Make sure amount require fields + if (!$scope.transferData.amount || !$scope.transferData.pubkey) { + $scope.form.$submitted=true; + UIUtils.loading.hide(); + return $q.reject(); + } + // Avoid multiple click if ($scope.sending) return; $scope.sending = true; + delete $scope.transferData.error; var wallet = $scope.demo ? csDemoWallet.instance(authData) : csWallet.instance('api', BMA); UIUtils.loading.show(); - wallet.start({restore: false}/*skip restore from local storage*/) + wallet.start({restore: false/*skip restore from local storage*/}) .then(function() { - return wallet.login({auth: true, authData: authData}); + return wallet.login({ + auth: true, + authData: authData, + minData: true, + sources: true, + tx: {enable: false} + }); }) .then(function(walletData) { + if (!walletData) return; + $scope.login = true; UIUtils.loading.hide(); @@ -367,8 +491,9 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr url = url.replace(/\{pubkey\}/g, $scope.transferData.pubkey); url = url.replace(/\{hash\}/g, txRes.hash||''); url = url.replace(/\{comment\}/g, $scope.transferData.comment||''); - url = url.replace(/\{amount\}/g, $scope.transferData.amount.toString()); + url = url.replace(/\{amount\}/g, $scope.transferData.amount && ($scope.transferData.amount/100).toString() || ''); url = url.replace(/\{tx\}/g, encodeURI(txRes.tx)); + url = url.replace(/\{node\}/g, encodeURI(BMA.host+':'+BMA.port)); return $scope.redirectToUrl(url, 2500); }); @@ -390,7 +515,7 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr // Make replacements - fix #548 url = url.replace(/\{pubkey\}/g, $scope.transferData.pubkey); url = url.replace(/\{comment\}/g, $scope.transferData.comment||''); - url = url.replace(/\{amount\}/g, $scope.transferData.amount.toString()); + url = url.replace(/\{amount\}/g, $scope.transferData.amount && ($scope.transferData.amount/100).toString() || ''); return $scope.redirectToUrl(url, 1500); }); @@ -416,16 +541,18 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr /* -- methods need by Login controller -- */ - $scope.setForm = function(form) { - $scope.form = form; - }; $scope.closeModal = onLogin; }]) - .run(['csPlatform', function(csPlatform) { + .run(['csSettings', function(csSettings) { 'ngInject'; - csPlatform.start(); + csSettings.data.rememberMe = false; + csSettings.data.useLocalStorage = false; + // Force auth idle to 30s + csSettings.data.keepAuthIdle = 30; + + //csPlatform.start(); }]) ; diff --git a/assets/www/dist/dist_js/app/app-controllers.js b/assets/www/dist/dist_js/app/app-controllers.js new file mode 100644 index 0000000000000000000000000000000000000000..0ffe00f5ef337245bb252166659b4f6b697654a0 --- /dev/null +++ b/assets/www/dist/dist_js/app/app-controllers.js @@ -0,0 +1,606 @@ + +AppController.$inject = ['$scope', '$rootScope', '$state', '$ionicSideMenuDelegate', '$q', '$timeout', '$ionicHistory', '$controller', '$window', 'csPlatform', 'CryptoUtils', 'csCrypto', 'UIUtils', 'BMA', 'csWallet', 'Device', 'Modals', 'csConfig', 'csHttp']; +HomeController.$inject = ['$scope', '$state', '$timeout', '$ionicHistory', '$translate', 'UIUtils', 'csPlatform', 'csCurrency', 'csSettings']; +PluginExtensionPointController.$inject = ['$scope', 'PluginService'];angular.module('cesium.app.controllers', ['cesium.platform', 'cesium.services']) + + .config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) { + 'ngInject'; + + $stateProvider + + .state('app', { + url: "/app", + abstract: true, + templateUrl: "templates/menu.html", + controller: 'AppCtrl', + data: { + large: false + } + }) + + .state('app.home', { + url: "/home?error", + views: { + 'menuContent': { + templateUrl: "templates/home/home.html", + controller: 'HomeCtrl' + } + } + }) + + .state('app.lock', { + cache: false, + url: "/lock", + views: { + 'menuContent': { + templateUrl: "templates/common/view_passcode.html", + controller: 'PassCodeCtrl' + } + } + }) + ; + + // if none of the above states are matched, use this as the fallback + $urlRouterProvider.otherwise('/app/home'); + + }]) + + .controller('AppCtrl', AppController) + + .controller('HomeCtrl', HomeController) + + .controller('PluginExtensionPointCtrl', PluginExtensionPointController) + + + +; + +/** + * Useful controller that could be reuse in plugin, using $scope.extensionPoint for condition rendered in templates + */ +function PluginExtensionPointController($scope, PluginService) { + 'ngInject'; + $scope.extensionPoint = PluginService.extensions.points.current.get(); +} + +/** + * Abstract controller (inherited by other controllers) + */ +function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $timeout, + $ionicHistory, $controller, $window, csPlatform, CryptoUtils, csCrypto, + UIUtils, BMA, csWallet, Device, Modals, csConfig, csHttp +) { + 'ngInject'; + + $scope.walletData = csWallet.data; + $scope.search = {}; + $scope.login = csWallet.isLogin(); + $scope.auth = csWallet.isAuth(); + $scope.motion = UIUtils.motion.default; + $scope.fullscreen = UIUtils.screen.fullscreen.isEnabled(); + + alert("HOME 7"); + + $scope.showHome = function() { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + return $state.go('app.home') + .then(UIUtils.loading.hide); + }; + + // removeIf(no-device) + //////////////////////////////////////// + // Device only methods + // (code removed when NO device) + //////////////////////////////////////// + + $scope.scanQrCodeAndGo = function() { + + if (!Device.barcode.enable) return; + + // Run scan cordova plugin, on device + return Device.barcode.scan() + .then(function(data) { + if (!data) return; + + // Try to parse as an URI + return BMA.uri.parse(data) + .then(function(res){ + if (!res || !res.pubkey) throw {message: 'ERROR.SCAN_UNKNOWN_FORMAT'}; + // If pubkey: open the identity + return $state.go('app.wot_identity', { + pubkey: res.pubkey, + node: res.host ? res.host: null} + ); + }) + + // Not an URI: try WIF or EWIF format + .catch(function(err) { + console.debug("[app] Scan data is not an URI (get error: " + (err && err.message || err) + "). Trying to decode as a WIF or EWIF format..."); + + // Try to read as WIF format + return csCrypto.keyfile.parseData(data) + .then(function(keypair) { + if (!keypair || !keypair.signPk || !keypair.signSk) throw err; // rethrow the first error (e.g. Bad URI) + + var pubkey = CryptoUtils.base58.encode(keypair.signPk); + console.debug("[app] Detected WIF/EWIF format. Will login to wallet {" + pubkey.substring(0, 8) + "}"); + + // Create a new wallet (if default wallet is already used) + var wallet = !csWallet.isLogin() ? csWallet : csWallet.children.create({store: false}); + + // Login using keypair + return wallet.login({ + silent: true, + forceAuth: true, + minData: false, + authData: { + pubkey: pubkey, + keypair: keypair + } + }) + .then(function () { + + // Open transfer all wallet + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + return $state.go('app.new_transfer', { + all: true, // transfer all sources + wallet: !wallet.isDefault() ? wallet.id : undefined + }); + }); + }) + // Unknown format (nor URI, nor WIF/EWIF) + .catch(UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')); + }); + }) + .catch(UIUtils.onError('ERROR.SCAN_FAILED')); + }; + + //////////////////////////////////////// + // End of device only methods + //////////////////////////////////////// + // endRemoveIf(no-device) + + //////////////////////////////////////// + // Show Help tour + //////////////////////////////////////// + + $scope.createHelptipScope = function(isTour, helpController) { + if (!isTour && ($rootScope.tour || !$rootScope.settings.helptip.enable || UIUtils.screen.isSmall())) { + return; // avoid other helptip to be launched (e.g. csWallet) + } + // Create a new scope for the tour controller + var helptipScope = $scope.$new(); + $controller(helpController||'HelpTipCtrl', { '$scope': helptipScope}); + return helptipScope; + }; + + $scope.startHelpTour = function(helpController, skipClearCache) { + $rootScope.tour = true; // to avoid other helptip to be launched (e.g. csWallet) + + // Clear cache history + if (!skipClearCache) { + $ionicHistory.clearHistory(); + return $ionicHistory.clearCache() + .then(function() { + $scope.startHelpTour(helpController, true/*continue*/); + }); + } + + var helptipScope = $scope.createHelptipScope(true/*is tour*/, helpController); + return helptipScope.startHelpTour() + .then(function() { + helptipScope.$destroy(); + delete $rootScope.tour; + }) + .catch(function(err){ + delete $rootScope.tour; + }); + }; + + //////////////////////////////////////// + // Login & wallet + //////////////////////////////////////// + + $scope.isLogin = function() { + return $scope.login; + }; + + // Load wallet data (after login) + $scope.loadWalletData = function(options) { + + console.warn("[app-controller] DEPRECATED - Please use csWallet.load() instead of $scope.loadWalletData()", new Error()); + + options = options || {}; + var wallet = options.wallet || csWallet; + return wallet.loadData(options) + + .then(function(walletData) { + // cancel login + if (!walletData) throw 'CANCELLED'; + return walletData; + }); + }; + + // Login and load wallet + $scope.loadWallet = function(options) { + + console.warn("[app-controller] DEPRECATED - Please use csWallet.loginOrLoad() instead of $scope.loadWallet()", new Error()); + + // Make sure the platform is ready + if (!csPlatform.isStarted()) { + return csPlatform.ready().then(function(){ + return $scope.loadWallet(options); + }); + } + + options = options || {}; + + var wallet = options.wallet || csWallet; + + // If need auth + if (options.auth && !wallet.isAuth()) { + return wallet.auth(options) + .then(function (walletData) { + if (walletData) return walletData; + // failed to auth + throw 'CANCELLED'; + }); + } + + // If need login + else if (!wallet.isLogin()) { + return wallet.login(options) + .then(function (walletData) { + if (walletData) return walletData; + // failed to login + throw 'CANCELLED'; + }); + } + + // Already login or auth + else if (!wallet.isDataLoaded(options)) { + return $scope.loadWalletData(options); + } + else { + return $q.when(wallet.data); + } + }; + + // Login and go to a state (or wallet if not) + $scope.loginAndGo = function(state, options) { + $scope.closeProfilePopover(); + options = options || {}; + var wallet = options.wallet || csWallet; + delete options.wallet; + + state = state || 'app.view_wallet'; + + if (!wallet.isLogin()) { + + // Make sure to protect login modal, if HTTPS enable - fix #340 + if (csConfig.httpsMode && $window.location && $window.location.protocol !== 'https:') { + var href = $window.location.href; + var hashIndex = href.indexOf('#'); + var rootPath = (hashIndex != -1) ? href.substr(0, hashIndex) : href; + rootPath = 'https' + rootPath.substr(4); + href = rootPath + $state.href(state); + if (csConfig.httpsModeDebug) { + // Debug mode: just log, then continue + console.debug('[httpsMode] --- Should redirect to: ' + href); + } + else { + $window.location.href = href; + return; + } + } + + return wallet.login(options) + .then(function(){ + return $state.go(state, options); + }) + .then(UIUtils.loading.hide); + } + else { + return $state.go(state, options); + } + }; + + // Logout + $scope.logout = function(options) { + options = options || {}; + var wallet = options.wallet || csWallet; + if (!options.force && $scope.profilePopover) { + // Make the popover if really closed, to avoid UI refresh on popover buttons + return $scope.profilePopover.hide() + .then(function(){ + options.force = true; + return $scope.logout(options); + }); + } + if (options.askConfirm) { + return UIUtils.alert.confirm('CONFIRM.LOGOUT') + .then(function(confirm) { + if (confirm) { + options.askConfirm=false; + return $scope.logout(options); + } + }); + } + + UIUtils.loading.show(); + return wallet.logout() + .then(function() { + // Close left menu if open + if ($ionicSideMenuDelegate.isOpenLeft()) { + $ionicSideMenuDelegate.toggleLeft(); + } + + // If default wallet: clear navigation history, then go back to home + if (wallet.isDefault()) { + $ionicHistory.clearHistory(); + + return $ionicHistory.clearCache() + .then(function() { + return $scope.showHome(); + }); + } + else { + + } + }) + .catch(UIUtils.onError()); + }; + // Do authentification + $scope.doAuth = function(options) { + var wallet = options && options.wallet || csWallet; + return wallet.auth() + .then(UIUtils.loading.hide); + }; + + // If connected and same pubkey + $scope.isUserPubkey = function(pubkey) { + return csWallet.isUserPubkey(pubkey); + }; + + // add listener on wallet event + csWallet.api.data.on.login($scope, function(data, deferred) { + $scope.login = true; + return deferred ? deferred.resolve() : $q.when(); + }); + csWallet.api.data.on.logout($scope, function() { + $scope.login = false; + }); + csWallet.api.data.on.auth($scope, function(data, deferred) { + $scope.auth = true; + return deferred ? deferred.resolve() : $q.when(); + }); + csWallet.api.data.on.unauth($scope, function() { + $scope.auth = false; + }); + + //////////////////////////////////////// + // Useful modals + //////////////////////////////////////// + + // Open transfer modal + $scope.showTransferModal = function(parameters) { + return Modals.showTransfer(parameters); + }; + + $scope.showAboutModal = function() { + return Modals.showAbout(); + }; + + $scope.showJoinModal = function() { + $scope.closeProfilePopover(); + return Modals.showJoin(); + }; + + $scope.showSettings = function() { + $scope.closeProfilePopover(); + return $state.go('app.settings'); + }; + + $scope.showHelpModal = function(parameters) { + return Modals.showHelp(parameters); + }; + + //////////////////////////////////////// + // Useful popovers + //////////////////////////////////////// + + $scope.showProfilePopover = function(event) { + return UIUtils.popover.show(event, { + templateUrl :'templates/common/popover_profile.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.profilePopover = popover; + $timeout(function() { + UIUtils.ink({selector: '#profile-popover .ink, #profile-popover .ink-dark'}); + }, 100); + } + }); + }; + + $scope.closeProfilePopover = function() { + if ($scope.profilePopover && $scope.profilePopover.isShown()) { + $timeout(function(){$scope.profilePopover.hide();}); + } + }; + // Change peer info + $scope.showPeerInfoPopover = function(event) { + return UIUtils.popover.show(event, { + templateUrl: 'templates/network/popover_peer_info.html', + autoremove: true, + scope: $scope.$new(true) + }); + }; + + //////////////////////////////////////// + // Link management (fix issue #) + //////////////////////////////////////// + + $scope.openLink = function($event, uri, options) { + $event.stopPropagation(); + $event.preventDefault(); + + options = options || {}; + + // If unable to open, just copy value + options.onError = function() { + return UIUtils.popover.copy($event, uri); + }; + + csHttp.uri.open(uri, options); + + return false; + }; + + //////////////////////////////////////// + // Layout Methods + //////////////////////////////////////// + $scope.showFab = function(id, timeout) { + UIUtils.motion.toggleOn({selector: '#'+id + '.button-fab'}, timeout); + }; + + $scope.hideFab = function(id, timeout) { + UIUtils.motion.toggleOff({selector: '#'+id + '.button-fab'}, timeout); + }; + + // Could be override by subclass + $scope.doMotion = function(options) { + return $scope.motion.show(options); + }; + + + //////////////////////////////////////// + // Fullscreen mode + //////////////////////////////////////// + + $scope.askFullscreen = function() { + var skip = $scope.fullscreen || !UIUtils.screen.isSmall() || !Device.isWeb(); + if (skip) return; + + return UIUtils.alert.confirm('CONFIRM.FULLSCREEN', null, { + cancelText: 'COMMON.BTN_NO', + okText: 'COMMON.BTN_YES' + }) + .then(function(confirm) { + if (!confirm) return; + $scope.toggleFullscreen(); + }); + }; + + $scope.toggleFullscreen = function() { + $scope.fullscreen = !UIUtils.screen.fullscreen.isEnabled(); + UIUtils.screen.fullscreen.toggleAll(); + }; + + // removeIf(device) + // Ask switching fullscreen + $scope.askFullscreen(); + // endRemoveIf(device) +} + + +function HomeController($scope, $state, $timeout, $ionicHistory, $translate, UIUtils, csPlatform, csCurrency, csSettings) { + 'ngInject'; + + $scope.loading = true; + $scope.locales = angular.copy(csSettings.locales); + + $scope.enter = function(e, state) { + if (ionic.Platform.isIOS()) { + if(window.StatusBar) { + // needed to fix Xcode 9 / iOS 11 issue with blank space at bottom of webview + // https://github.com/meteor/meteor/issues/9041 + StatusBar.overlaysWebView(false); + StatusBar.overlaysWebView(true); + } + } + + if (state && state.stateParams && state.stateParams.error) { // Error query parameter + $scope.error = state.stateParams.error; + $scope.node = csCurrency.data.node; + $scope.loading = false; + $ionicHistory.nextViewOptions({ + disableAnimate: true, + disableBack: true, + historyRoot: true + }); + $state.go('app.home', {error: undefined}, { + reload: false, + inherit: true, + notify: false}); + } + else { + // Start platform + csPlatform.ready() + .then(function() { + $scope.loading = false; + }) + .catch(function(err) { + $scope.node = csCurrency.data.node; + $scope.loading = false; + $scope.error = err; + }); + } + }; + $scope.$on('$ionicView.enter', $scope.enter); + + $scope.reload = function() { + $scope.loading = true; + delete $scope.error; + + $timeout($scope.enter, 200); + }; + + /** + * Catch click for quick fix + * @param event + */ + $scope.doQuickFix = function(event) { + if (event == 'settings') { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + $state.go('app.settings'); + } + }; + + $scope.changeLanguage = function(langKey) { + $translate.use(langKey); + $scope.hideLocalesPopover(); + csSettings.data.locale = _.findWhere($scope.locales, {id: langKey}); + }; + + /* -- show/hide locales popup -- */ + + $scope.showLocalesPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'templates/api/locales_popover.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.localesPopover = popover; + } + }); + }; + + $scope.hideLocalesPopover = function() { + if ($scope.localesPopover) { + $scope.localesPopover.hide(); + $scope.localesPopover = null; + } + }; + + // For DEV ONLY + /*$timeout(function() { + $scope.loginAndGo(); + }, 500);*/ +} diff --git a/assets/www/dist/dist_js/app/app.js b/assets/www/dist/dist_js/app/app.js index 27d7899dffa4b2c80dd78962bee9c6f1925cdf7d..25c19ff4ea9c0ccaf1bf5181d430e58e7392506a 100644 --- a/assets/www/dist/dist_js/app/app.js +++ b/assets/www/dist/dist_js/app/app.js @@ -4,8 +4,9 @@ // 'starter' is the name of this angular module example (also set in a <body> attribute in index.html) // the 2nd parameter is an array of 'requires' // 'starter.controllers' is found in controllers.js -angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht.translate', +angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'ngSanitize', 'pascalprecht.translate', 'ngApi', 'angular-cache', 'angular.screenmatch', 'angular.bind.notifier', 'ImageCropper', 'ion-digit-keyboard', + 'FBAngular', // = angular-fullscreen // removeIf(no-device) 'ngCordova', // endRemoveIf(no-device) @@ -27,9 +28,6 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht Device, UIUtils, $ionicConfig, PluginService, csPlatform, csWallet) { 'ngInject'; - // Allow access to service data, from HTML templates - $rootScope.walletData = csWallet.data; - // Must be done before any other $stateChangeStart listeners csPlatform.disableChangeState(); @@ -47,8 +45,12 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht var options; + var wallet = nextParams.wallet && nextParams.wallet != "default" ? csWallet.children.get(nextParams.wallet) : csWallet; + if (nextParams.wallet && !wallet) { + console.warn("[app] Unable to find the children wallet: " + nextParams.wallet); + } // If state need auth - if (next.data.auth && !csWallet.isAuth()) { + if (next.data.auth && !wallet.isAuth()) { event.preventDefault(); options = next.data.minData ? {minData: true} : undefined; preventStateChange = true; @@ -60,7 +62,7 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht .catch(function(err) { preventStateChange = false; // If cancel, redirect to home, if no current state - if (err == 'CANCELLED' && !$state.current.name) { + if (err === 'CANCELLED' && !$state.current.name) { return $state.go('app.home'); } }); @@ -79,7 +81,7 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht .catch(function(err) { preventStateChange = false; // If cancel, redirect to home, if no current state - if (err == 'CANCELLED' && !$state.current.name) { + if (err === 'CANCELLED' && !$state.current.name) { return $state.go('app.home'); } }); @@ -88,11 +90,11 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht // If state need login or auth, make sure to load wallet data else if (next.data.login || next.data.auth) { options = next.data.minData ? {minData: true} : undefined; - if (!csWallet.isDataLoaded(options)) { + if (!wallet.isDataLoaded(options)) { event.preventDefault(); // Show loading message, when full load if (!options || !options.minData) UIUtils.loading.show(); - return csWallet.loadData(options) + return wallet.loadData(options) .then(function() { preventStateChange = false; return $state.go(next.name, nextParams); @@ -116,10 +118,24 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht if (sameUrl) event.preventDefault(); } }); + // Configures $urlRouter's listener *after* the previous listener $urlRouter.listen(); // Start plugins eager services PluginService.start(); + + ionicReady().then(function() { + if (ionic.Platform.isIOS()) { + if(window.StatusBar) { + // fix font color not white on iOS 11+ + StatusBar.styleLightContent(); + } + } + }); }]) ; + +window.ionic.Platform.ready(function() { + angular.bootstrap(document, ['cesium']); +}); diff --git a/assets/www/dist/dist_js/app/config.js b/assets/www/dist/dist_js/app/config.js index 79a743c695ec21539ae6ca89ff9aa02f96101444..57d256481f63d4c50d46fafce1e5412a3e99c9cf 100644 --- a/assets/www/dist/dist_js/app/config.js +++ b/assets/www/dist/dist_js/app/config.js @@ -13,10 +13,10 @@ angular.module("cesium.config", []) "fallbackLanguage": "en", "rememberMe": true, "showUDHistory": true, - "timeout": 30000, + "timeout": 40000, "timeWarningExpireMembership": 5184000, "timeWarningExpire": 7776000, - "keepAuthIlde": 600, + "keepAuthIdle": 600, "useLocalStorage": true, "useRelative": false, "expertMode": false, @@ -31,21 +31,34 @@ angular.module("cesium.config", []) } }, "license": { + "en": "license/license_g1-en", "fr-FR": "license/license_g1-fr-FR", - "en": "license/license_g1-en" + "es-ES": "license/license_g1-es-ES" }, "node": { "host": "g1.duniter.org", - "port": "443" + "port": 443 }, "fallbackNodes": [ { - "host": "g1.duniter.fr", - "port": "443" + "host": "g1.nordstrom.duniter.org", + "port": 443 + }, + { + "host": "g1.cgeek.fr", + "port": 443 + }, + { + "host": "g1.monnaielibreoccitanie.org", + "port": 443 + }, + { + "host": "g1.le-sou.org", + "port": 443 }, { - "host": "g1.duniter.org", - "port": "443" + "host": "g1.duniter.fr", + "port": 443 } ], "developers": [ @@ -58,16 +71,17 @@ angular.module("cesium.config", []) "es": { "enable": true, "askEnable": true, + "useRemoteStorage": true, "host": "g1.data.duniter.fr", - "port": "443", + "port": 443, "fallbackNodes": [ { "host": "g1.data.le-sou.org", - "port": "443" + "port": 443 }, { "host": "g1.data.duniter.fr", - "port": "443" + "port": 443 } ], "notifications": { @@ -79,9 +93,9 @@ angular.module("cesium.config", []) "defaultCountry": "France" } }, - "version": "1.0.6", - "build": "2018-05-09T15:28:09.984Z", - "newIssueUrl": "https://git.duniter.org/clients/cesium/cesium/issues/new" + "version": "1.4.15", + "build": "2019-12-27T19:43:48.157Z", + "newIssueUrl": "https://git.duniter.org/clients/cesium-grp/cesium/issues/new" }) ; \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/controllers.js b/assets/www/dist/dist_js/app/controllers.js index a612166287398398363b2d659baf4dfc0c8f2367..5ed49c51576e0032ddf87bf2b62cfbc130b8b201 100644 --- a/assets/www/dist/dist_js/app/controllers.js +++ b/assets/www/dist/dist_js/app/controllers.js @@ -5,6 +5,7 @@ angular.module('cesium.controllers', [ 'cesium.login.controllers', 'cesium.help.controllers', 'cesium.wallet.controllers', + 'cesium.wallets.controllers', 'cesium.currency.controllers', 'cesium.wot.controllers', 'cesium.transfer.controllers', diff --git a/assets/www/dist/dist_js/app/controllers/app-controllers.js b/assets/www/dist/dist_js/app/controllers/app-controllers.js index 3ee2352f38d0efcb87c7deeb88d819af92f83fa6..1ad176c43014eb715c143d0e93e22343eb704459 100644 --- a/assets/www/dist/dist_js/app/controllers/app-controllers.js +++ b/assets/www/dist/dist_js/app/controllers/app-controllers.js @@ -1,6 +1,6 @@ -AppController.$inject = ['$scope', '$rootScope', '$state', '$ionicSideMenuDelegate', '$q', '$timeout', '$ionicHistory', '$controller', '$window', 'csPlatform', 'CryptoUtils', 'UIUtils', 'BMA', 'csWallet', 'Device', 'Modals', 'csConfig', 'csHttp']; -HomeController.$inject = ['$scope', '$state', '$timeout', '$ionicHistory', 'csPlatform', 'csCurrency']; + AppController.$inject = ['$scope', '$rootScope', '$state', '$ionicSideMenuDelegate', '$q', '$timeout', '$ionicHistory', '$controller', '$window', 'csPlatform', 'CryptoUtils', 'csCrypto', 'UIUtils', 'BMA', 'csWallet', 'Device', 'Modals', 'csConfig', 'csHttp']; +HomeController.$inject = ['$scope', '$state', '$timeout', '$ionicHistory', '$translate', 'UIUtils', 'csPlatform', 'csCurrency', 'csSettings']; PluginExtensionPointController.$inject = ['$scope', 'PluginService'];angular.module('cesium.app.controllers', ['cesium.platform', 'cesium.services']) .config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) { @@ -67,15 +67,17 @@ function PluginExtensionPointController($scope, PluginService) { * Abstract controller (inherited by other controllers) */ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $timeout, - $ionicHistory, $controller, $window, csPlatform, CryptoUtils, + $ionicHistory, $controller, $window, csPlatform, CryptoUtils, csCrypto, UIUtils, BMA, csWallet, Device, Modals, csConfig, csHttp ) { 'ngInject'; + $scope.walletData = csWallet.data; $scope.search = {}; $scope.login = csWallet.isLogin(); $scope.auth = csWallet.isAuth(); $scope.motion = UIUtils.motion.default; + $scope.fullscreen = UIUtils.screen.fullscreen.isEnabled(); $scope.showHome = function() { $ionicHistory.nextViewOptions({ @@ -85,78 +87,81 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ .then(UIUtils.loading.hide); }; + // removeIf(no-device) //////////////////////////////////////// - // Device Methods + // Device only methods + // (code removed when NO device) //////////////////////////////////////// $scope.scanQrCodeAndGo = function() { - if (!Device.barcode.enable) { - return; - } - Device.barcode.scan() + + if (!Device.barcode.enable) return; + + // Run scan cordova plugin, on device + return Device.barcode.scan() .then(function(data) { if (!data) return; - BMA.uri.parse(data) - .then(function(result){ - // If pubkey - if (result && result.pubkey) { - $state.go('app.wot_identity', { - pubkey: result.pubkey, - node: result.host ? result.host: null} - ); - } - else { - UIUtils.alert.error(result, 'ERROR.SCAN_UNKNOWN_FORMAT'); - } + + // Try to parse as an URI + return BMA.uri.parse(data) + .then(function(res){ + if (!res || !res.pubkey) throw {message: 'ERROR.SCAN_UNKNOWN_FORMAT'}; + // If pubkey: open the identity + return $state.go('app.wot_identity', { + pubkey: res.pubkey, + node: res.host ? res.host: null} + ); }) + + // Not an URI: try WIF or EWIF format .catch(function(err) { + console.debug("[app] Scan data is not an URI (get error: " + (err && err.message || err) + "). Trying to decode as a WIF or EWIF format..."); // Try to read as WIF format - var keypairPromise; - try { - keypairPromise = Promise.resolve(CryptoUtils.keypair_from_wif_v1(data)); - } catch(err2) { /*silent*/ } - - // Try to read as EWIF format - if (!keypairPromise) { - try { - CryptoUtils.keypair_from_ewif_v1(data); - } catch(err2) { - if (err && (err == 'NEED_PASSWORD' || (err == 'BAD_PASSWORD'))) { - keypairPromise = Modals.showPassword({ - title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', - subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP' - }) - .then(function(password) { - if (!password) throw 'CANCELLED'; - return CryptoUtils.keypair_from_ewif_v1(data, password); + return csCrypto.keyfile.parseData(data) + .then(function(keypair) { + if (!keypair || !keypair.signPk || !keypair.signSk) throw err; // rethrow the first error (e.g. Bad URI) + + var pubkey = CryptoUtils.base58.encode(keypair.signPk); + console.debug("[app] Detected WIF/EWIF format. Will login to wallet {" + pubkey.substring(0, 8) + "}"); + + // Create a new wallet (if default wallet is already used) + var wallet = !csWallet.isLogin() ? csWallet : csWallet.children.create({store: false}); + + // Login using keypair + return wallet.login({ + silent: true, + forceAuth: true, + minData: false, + authData: { + pubkey: pubkey, + keypair: keypair + } + }) + .then(function () { + + // Open transfer all wallet + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + return $state.go('app.new_transfer', { + all: true, // transfer all sources + wallet: !wallet.isDefault() ? wallet.id : undefined }); - } - } - } - if (keypairPromise) { - keypairPromise.then(function(keypair) { - return csWallet.login({ - forceAuth: true, - authData: { - pubkey: CryptoUtils.base58.encode(keypair.signPk), - keypair: keypair - } - }) - .catch(UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')) - .then(function (res) { - if (res) return $state.go('app.view_wallet'); - }); - }); - } - else { - UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')(err); - } + }); + }) + // Unknown format (nor URI, nor WIF/EWIF) + .catch(UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')); }); }) .catch(UIUtils.onError('ERROR.SCAN_FAILED')); }; + //////////////////////////////////////// + // End of device only methods + //////////////////////////////////////// + // endRemoveIf(no-device) + //////////////////////////////////////// // Show Help tour //////////////////////////////////////// @@ -202,44 +207,27 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ return $scope.login; }; - $scope.showProfilePopover = function(event) { - return UIUtils.popover.show(event, { - templateUrl :'templates/common/popover_profile.html', - scope: $scope, - autoremove: true, - afterShow: function(popover) { - $scope.profilePopover = popover; - $timeout(function() { - UIUtils.ink({selector: '#profile-popover .ink, #profile-popover .ink-dark'}); - }, 100); - } - }); - }; - - $scope.closeProfilePopover = function() { - if ($scope.profilePopover && $scope.profilePopover.isShown()) { - $timeout(function(){$scope.profilePopover.hide();}); - } - }; - // Load wallet data (after login) $scope.loadWalletData = function(options) { - return csWallet.loadData(options) + + console.warn("[app-controller] DEPRECATED - Please use csWallet.load() instead of $scope.loadWalletData()", new Error()); + + options = options || {}; + var wallet = options.wallet || csWallet; + return wallet.loadData(options) .then(function(walletData) { - if (walletData) { - $rootScope.walletData = walletData; - return walletData; - } - else { // cancel login - throw 'CANCELLED'; - } + // cancel login + if (!walletData) throw 'CANCELLED'; + return walletData; }); }; // Login and load wallet $scope.loadWallet = function(options) { + console.warn("[app-controller] DEPRECATED - Please use csWallet.loginOrLoad() instead of $scope.loadWallet()", new Error()); + // Make sure the platform is ready if (!csPlatform.isStarted()) { return csPlatform.ready().then(function(){ @@ -249,9 +237,11 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ options = options || {}; + var wallet = options.wallet || csWallet; + // If need auth - if (options.auth && !csWallet.isAuth()) { - return csWallet.auth(options) + if (options.auth && !wallet.isAuth()) { + return wallet.auth(options) .then(function (walletData) { if (walletData) return walletData; // failed to auth @@ -260,8 +250,8 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ } // If need login - else if (!csWallet.isLogin()) { - return csWallet.login(options) + else if (!wallet.isLogin()) { + return wallet.login(options) .then(function (walletData) { if (walletData) return walletData; // failed to login @@ -270,21 +260,24 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ } // Already login or auth - else if (!csWallet.isDataLoaded(options)) { + else if (!wallet.isDataLoaded(options)) { return $scope.loadWalletData(options); } else { - return $q.when(csWallet.data); + return $q.when(wallet.data); } }; // Login and go to a state (or wallet if not) $scope.loginAndGo = function(state, options) { $scope.closeProfilePopover(); + options = options || {}; + var wallet = options.wallet || csWallet; + delete options.wallet; state = state || 'app.view_wallet'; - if (!csWallet.isLogin()) { + if (!wallet.isLogin()) { // Make sure to protect login modal, if HTTPS enable - fix #340 if (csConfig.httpsMode && $window.location && $window.location.protocol !== 'https:') { @@ -294,17 +287,16 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ rootPath = 'https' + rootPath.substr(4); href = rootPath + $state.href(state); if (csConfig.httpsModeDebug) { + // Debug mode: just log, then continue console.debug('[httpsMode] --- Should redirect to: ' + href); - // continue } else { $window.location.href = href; return; } - } - return csWallet.login(options) + return wallet.login(options) .then(function(){ return $state.go(state, options); }) @@ -318,6 +310,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ // Logout $scope.logout = function(options) { options = options || {}; + var wallet = options.wallet || csWallet; if (!options.force && $scope.profilePopover) { // Make the popover if really closed, to avoid UI refresh on popover buttons return $scope.profilePopover.hide() @@ -337,28 +330,33 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ } UIUtils.loading.show(); - return csWallet.logout() + return wallet.logout() .then(function() { // Close left menu if open if ($ionicSideMenuDelegate.isOpenLeft()) { $ionicSideMenuDelegate.toggleLeft(); } - $ionicHistory.clearHistory(); - return $ionicHistory.clearCache() - .then(function() { - return $scope.showHome(); - }); + // If default wallet: clear navigation history, then go back to home + if (wallet.isDefault()) { + $ionicHistory.clearHistory(); + + return $ionicHistory.clearCache() + .then(function() { + return $scope.showHome(); + }); + } + else { + + } }) .catch(UIUtils.onError()); }; - - // Login and go to a state (or wallet if not) - $scope.doAuth = function() { - return $scope.loadWallet({auth: true}) - .then(function() { - UIUtils.loading.hide(); - }); + // Do authentification + $scope.doAuth = function(options) { + var wallet = options && options.wallet || csWallet; + return wallet.auth() + .then(UIUtils.loading.hide); }; // If connected and same pubkey @@ -367,20 +365,16 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }; // add listener on wallet event - csWallet.api.data.on.login($scope, function(walletData, deferred) { + csWallet.api.data.on.login($scope, function(data, deferred) { $scope.login = true; - $rootScope.walletData = walletData || {}; return deferred ? deferred.resolve() : $q.when(); }); csWallet.api.data.on.logout($scope, function() { $scope.login = false; - $rootScope.walletData = {}; }); csWallet.api.data.on.auth($scope, function(data, deferred) { - deferred = deferred || $q.defer(); $scope.auth = true; - deferred.resolve(); - return deferred.promise; + return deferred ? deferred.resolve() : $q.when(); }); csWallet.api.data.on.unauth($scope, function() { $scope.auth = false; @@ -414,10 +408,30 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }; //////////////////////////////////////// - // Change node (expert mode) + // Useful popovers //////////////////////////////////////// - $scope.showNodeListPopover = function(event) { + $scope.showProfilePopover = function(event) { + return UIUtils.popover.show(event, { + templateUrl :'templates/common/popover_profile.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.profilePopover = popover; + $timeout(function() { + UIUtils.ink({selector: '#profile-popover .ink, #profile-popover .ink-dark'}); + }, 100); + } + }); + }; + + $scope.closeProfilePopover = function() { + if ($scope.profilePopover && $scope.profilePopover.isShown()) { + $timeout(function(){$scope.profilePopover.hide();}); + } + }; + // Change peer info + $scope.showPeerInfoPopover = function(event) { return UIUtils.popover.show(event, { templateUrl: 'templates/network/popover_peer_info.html', autoremove: true, @@ -426,10 +440,13 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }; //////////////////////////////////////// - // Link managment (fix issue #) + // Link management (fix issue #) //////////////////////////////////////// $scope.openLink = function($event, uri, options) { + $event.stopPropagation(); + $event.preventDefault(); + options = options || {}; // If unable to open, just copy value @@ -437,8 +454,9 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ return UIUtils.popover.copy($event, uri); }; - $event.stopPropagation(); - return csHttp.uri.open(uri, options); + csHttp.uri.open(uri, options); + + return false; }; //////////////////////////////////////// @@ -457,16 +475,50 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ return $scope.motion.show(options); }; -} + //////////////////////////////////////// + // Fullscreen mode + //////////////////////////////////////// + + $scope.askFullscreen = function() { + var skip = $scope.fullscreen || !UIUtils.screen.isSmall() || !Device.isWeb(); + if (skip) return; + + return UIUtils.alert.confirm('CONFIRM.FULLSCREEN', null, { + cancelText: 'COMMON.BTN_NO', + okText: 'COMMON.BTN_YES' + }) + .then(function(confirm) { + if (!confirm) return; + $scope.toggleFullscreen(); + }); + }; + + $scope.toggleFullscreen = function() { + $scope.fullscreen = !UIUtils.screen.fullscreen.isEnabled(); + UIUtils.screen.fullscreen.toggleAll(); + }; -function HomeController($scope, $state, $timeout, $ionicHistory, csPlatform, csCurrency) { + } + + +function HomeController($scope, $state, $timeout, $ionicHistory, $translate, UIUtils, csPlatform, csCurrency, csSettings) { 'ngInject'; $scope.loading = true; + $scope.locales = angular.copy(csSettings.locales); $scope.enter = function(e, state) { - if (state && state.stateParams && state.stateParams.error) { // Query parameter + if (ionic.Platform.isIOS()) { + if(window.StatusBar) { + // needed to fix Xcode 9 / iOS 11 issue with blank space at bottom of webview + // https://github.com/meteor/meteor/issues/9041 + StatusBar.overlaysWebView(false); + StatusBar.overlaysWebView(true); + } + } + + if (state && state.stateParams && state.stateParams.error) { // Error query parameter $scope.error = state.stateParams.error; $scope.node = csCurrency.data.node; $scope.loading = false; @@ -515,6 +567,32 @@ function HomeController($scope, $state, $timeout, $ionicHistory, csPlatform, csC } }; + $scope.changeLanguage = function(langKey) { + $translate.use(langKey); + $scope.hideLocalesPopover(); + csSettings.data.locale = _.findWhere($scope.locales, {id: langKey}); + }; + + /* -- show/hide locales popup -- */ + + $scope.showLocalesPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'templates/api/locales_popover.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.localesPopover = popover; + } + }); + }; + + $scope.hideLocalesPopover = function() { + if ($scope.localesPopover) { + $scope.localesPopover.hide(); + $scope.localesPopover = null; + } + }; + // For DEV ONLY /*$timeout(function() { $scope.loginAndGo(); diff --git a/assets/www/dist/dist_js/app/controllers/blockchain-controllers.js b/assets/www/dist/dist_js/app/controllers/blockchain-controllers.js index c983e9b1e70fbb40bf5cd100ee701f477aaea0e6..b4d50afaf8f7cd5e4899d68b3fd43f91d9a4915b 100644 --- a/assets/www/dist/dist_js/app/controllers/blockchain-controllers.js +++ b/assets/www/dist/dist_js/app/controllers/blockchain-controllers.js @@ -109,6 +109,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho $scope.ionItemClass = 'item-border-large'; $scope.defaultSizeLimit = UIUtils.screen.isSmall() ? 50 : 100; $scope.helptipPrefix = 'helptip-network'; + $scope.listeners = []; /** * Enter into the view @@ -178,14 +179,14 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho $scope.doSearch(); - $scope.startListenBlock(); + $scope.addListeners(); $scope.entered = true; $scope.showHelpTip(); } else { - $scope.startListenBlock(); + $scope.addListeners(); } }; //$scope.$on('$ionicView.enter', $scope.enter); @@ -198,11 +199,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho * @param state */ $scope.leave = function() { - if ($scope.wsBlock) { - console.debug('[block] Stopping websocket [/ws/block]'); - $scope.wsBlock.close(); - delete $scope.wsBlock; - } + $scope.removeListeners(); }; //$scope.$on('$ionicView.leave', $scope.leave); $scope.$on('$ionicParentView.leave', $scope.leave); @@ -228,7 +225,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho var size = current.number < $scope.defaultSizeLimit ? current.number : $scope.defaultSizeLimit; return $scope.node.blockchain.blocksSlice({count: size, from: current.number-size}) .then(function(blocks) { - blocks.splice(0,0,current); + if (!!blocks) blocks.splice(0,0,current); return blocks; }); }) @@ -327,12 +324,12 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho $scope.smallscreen = UIUtils.screen.isSmall(); + $scope.$broadcast('$$rebind::rebind'); // notify binder + // Set Motion if (res && res.length) { $scope.motion.show({selector: '.list-blocks .item-block'}); } - - $scope.$broadcast('$$rebind::rebind'); // notify binder }; $scope.showMore = function() { @@ -353,22 +350,35 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho }); }; - $scope.startListenBlock = function() { - if (!$scope.wsBlock) { - if ($scope.node == BMA) { - csCurrency.api.data.on.newBlock($scope, $scope.onBlock); - } - else { - console.debug('[block] Listening on websocket [/ws/block]'); - $scope.wsBlock = $scope.node.websocket.block(); - $scope.wsBlock.on(function(json) { + $scope.removeListeners = function() { + if ($scope.listeners.length) { + console.debug("[block] Closing listeners"); + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + } + }; + + $scope.addListeners = function() { + if ($scope.listeners.length) return; // already started + + console.debug("[block] Starting listeners"); + if ($scope.node === BMA) { + $scope.listeners = [ + csCurrency.api.data.on.newBlock($scope, $scope.onBlock) + ]; + } + else { + $scope.listeners = [ + $scope.node.websocket.block().onListener(function(json) { // Skip if WS closed (after leave view - should never happen) or invalid json - if (!$scope.wsBlock || !json) return; + if (!json) return; var block = new Block(json); block.cleanData(); // Remove unused content (arrays...) $scope.onBlock(block); - }); - } + }) + ]; } }; @@ -685,29 +695,20 @@ function BlockViewController($scope, $ionicPopover, $state, UIUtils, BMA, csCurr $scope.popoverData.unlockConditions = $scope.toUnlockUIArray(output.unlockTree); // Open popover - if (!$scope.unlockConditionPopover) { - $ionicPopover.fromTemplateUrl('templates/blockchain/unlock_condition_popover.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/blockchain/unlock_condition_popover.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.unlockConditionPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.unlockConditionPopover.remove(); - }); - $scope.unlockConditionPopover.show(event); - }); - } - else { - $scope.unlockConditionPopover.show(event); - } + } + }); }; $scope.hideUnlockConditionsPopover = function() { if ($scope.unlockConditionPopover) { $scope.unlockConditionPopover.hide(); - if ($scope.popoverData) { - delete $scope.popoverData.unlockConditions; - } + $scope.unlockConditionPopover = null; } }; diff --git a/assets/www/dist/dist_js/app/controllers/currency-controllers.js b/assets/www/dist/dist_js/app/controllers/currency-controllers.js index fb981d268210957c36749a31cf094a5603951c4b..ada2d160151c58a81f338ce2dced41748cf984f5 100644 --- a/assets/www/dist/dist_js/app/controllers/currency-controllers.js +++ b/assets/www/dist/dist_js/app/controllers/currency-controllers.js @@ -79,9 +79,10 @@ angular.module('cesium.currency.controllers', ['ngFileSaver', 'cesium.services'] ; function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA, UIUtils, csSettings, csCurrency, csNetwork, ModalUtils) { + 'ngInject'; $scope.formData = { - useRelative: csSettings.data.useRelative, + useRelative: false, // Override in enter() currency: '', M: 0, MoverN: 0, @@ -119,7 +120,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA $scope.enter = function(e, state) { if ($scope.loading) { // run only once (first enter) - + $scope.formData.useRelative = csSettings.data.useRelative; csCurrency.get() .then($scope.load) .then(function() { @@ -145,7 +146,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA $scope.load = function() { // Load data from node - var data = {}, M, lastUDTime, now = new Date().getTime(); + var data = {}, M, lastUDTime, now = Date.now(); return $q.all([ // Get the currency parameters @@ -188,7 +189,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA if (err && err.ucode == BMA.errorCodes.NO_CURRENT_BLOCK) { M = 0; data.N = 0; - data.medianTime = Math.trunc(new Date().getTime() / 1000); + data.medianTime = moment().utc().unix(); data.difficulty = 0; data.blockUid = null; return; @@ -234,9 +235,9 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA // Apply to formData angular.extend($scope.formData, data); - console.debug("[currency] Parameters loaded in " + (new Date().getTime() - now) + 'ms' ); + console.debug("[currency] Parameters loaded in " + (Date.now() - now) + 'ms' ); $scope.loading = false; - $scope.$broadcast('$$rebind::' + 'rebind'); // force bind of currency name + $scope.$broadcast('$$rebind::rebind'); // force bind of currency name // Set Ink UIUtils.ink(); @@ -279,7 +280,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA csSettings.store(); } }; - $scope.$watch('formData.allRules', $scope.onAllRulesChange, true); + $scope.$watch('formData.allRules', $scope.onAllRulesChange); $scope.onAllWotRulesChange = function() { csSettings.data.currency = csSettings.data.currency || {}; @@ -288,7 +289,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA csSettings.store(); } }; - $scope.$watch('formData.allWotRules', $scope.onAllWotRulesChange, true); + $scope.$watch('formData.allWotRules', $scope.onAllWotRulesChange); /* -- help tip -- */ @@ -329,26 +330,20 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA /* -- popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('templates/currency/popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/currency/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; } diff --git a/assets/www/dist/dist_js/app/controllers/help-controllers.js b/assets/www/dist/dist_js/app/controllers/help-controllers.js index 780a0ea7c805e44234dafeedff87f6b883fc4050..9618630b7a435251dc93edb4bba03c7b16c862af 100644 --- a/assets/www/dist/dist_js/app/controllers/help-controllers.js +++ b/assets/www/dist/dist_js/app/controllers/help-controllers.js @@ -1076,10 +1076,10 @@ function HelpTipController($scope, $state, $window, $ionicSideMenuDelegate, $tim bindings: { content: 'HELP.TIP.SETTINGS_CHANGE_UNIT', contentParams: contentParams, - icon: { + icon: UIUtils.screen.isSmall() ? { position: 'right', style: 'margin-right: 60px' - }, + } : {position: 'center'}, hasNext: hasNext }, timeout: 1000 @@ -1109,11 +1109,12 @@ function HelpTipController($scope, $state, $window, $ionicSideMenuDelegate, $tim if (csWallet.isLogin()) { return $state.go('app.view_wallet') .then(function(){ - return $scope.showHelpTip('helptip-wallet-certifications', { + return $scope.showHelpTip('helptip-wallet-pubkey', { bindings: { content: 'HELP.TIP.END_LOGIN', hasNext: false - } + }, + timeout: 1200 }); }); } diff --git a/assets/www/dist/dist_js/app/controllers/join-controllers.js b/assets/www/dist/dist_js/app/controllers/join-controllers.js index af2410db7a5aeb832187036fd54480ec36008289..19e21e362435b8d71a868fbd36a60661a09ff3d2 100644 --- a/assets/www/dist/dist_js/app/controllers/join-controllers.js +++ b/assets/www/dist/dist_js/app/controllers/join-controllers.js @@ -1,7 +1,7 @@ -JoinController.$inject = ['$timeout', 'Modals']; +JoinController.$inject = ['$scope', '$timeout', '$controller', 'Modals', 'csWallet']; JoinChooseAccountTypeModalController.$inject = ['$scope', '$state', 'Modals', 'UIUtils', 'csCurrency']; -JoinModalController.$inject = ['$scope', '$state', '$interval', '$timeout', 'Device', 'UIUtils', 'CryptoUtils', 'csSettings', 'Modals', 'csWallet', 'BMA', 'parameters'];angular.module('cesium.join.controllers', ['cesium.services']) +JoinModalController.$inject = ['$scope', '$state', '$interval', '$q', '$timeout', 'Device', 'UIUtils', 'CryptoUtils', 'csSettings', 'Modals', 'csWallet', 'BMA', 'parameters'];angular.module('cesium.join.controllers', ['cesium.services']) .config(['$stateProvider', function($stateProvider) { 'ngInject'; @@ -26,13 +26,21 @@ JoinModalController.$inject = ['$scope', '$state', '$interval', '$timeout', 'Dev .controller('JoinModalCtrl', JoinModalController) ; -function JoinController($timeout, Modals) { +function JoinController($scope, $timeout, $controller, Modals, csWallet) { 'ngInject'; - // Open join modal - $timeout(function() { - Modals.showJoin(); - }, 100); + // Initialize the super class and extend it. + angular.extend(this, $controller('HomeCtrl', {$scope: $scope})); + + $scope.showJoinModal = function() { + if ($scope.loading) return $timeout($scope.showJoinModal, 500); // recursive call + + if (!csWallet.isLogin() && !$scope.error) { + return $timeout(Modals.showJoin, 300); + } + }; + $scope.$on('$ionicView.enter', $scope.showJoinModal); + } function JoinChooseAccountTypeModalController($scope, $state, Modals, UIUtils, csCurrency) { @@ -108,18 +116,21 @@ function JoinChooseAccountTypeModalController($scope, $state, Modals, UIUtils, c } -function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtils, CryptoUtils, csSettings, Modals, csWallet, BMA, parameters) { +function JoinModalController($scope, $state, $interval, $q, $timeout, Device, UIUtils, CryptoUtils, csSettings, Modals, csWallet, BMA, parameters) { 'ngInject'; $scope.formData = { - pseudo: '' + pseudo: parameters.uid || '', + pubkey: parameters.pubkey || undefined }; $scope.slides = { slider: null, options: { loop: false, effect: 'slide', - speed: 500 + speed: 500, + pager: false, + showPager: false } }; $scope.slideBehavior = {}; @@ -130,16 +141,27 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil $scope.showPassword = false; $scope.formData.computing=false; $scope.smallscreen = UIUtils.screen.isSmall(); - $scope.userIdPattern = BMA.constants.regex.USER_ID; + $scope.userIdPattern = BMA.constants.regexp.USER_ID; + $scope.accountAvailable = !!parameters.pubkey; // Read input parameters $scope.currency = parameters.currency; $scope.accountType = parameters.accountType || 'member'; + var wallet; + $scope.load = function() { if ($scope.loading) { - if ($scope.accountType == 'member') { + // Get the wallet + wallet = (parameters.walletId && csWallet.children.get(parameters.walletId)) || + (parameters.pubkey && csWallet.children.getByPubkey(parameters.pubkey)) || + ((!parameters.pubkey || csWallet.isUserPubkey(parameters.pubkey)) && csWallet); + if (!wallet) throw new Error("Cannot found the corresponding wallet, from parameters.pubkey or parameters.walletId"); + + console.debug("[join] Starting join modal on wallet {0}".format(wallet.id)); + + if ($scope.accountType === 'member') { $scope.licenseFileUrl = csSettings.getLicenseUrl(); if ($scope.licenseFileUrl) { // Use HTML in iframe, when original file is markdown (fix #538) @@ -183,17 +205,27 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil }; $scope.showAccountPubkey = function() { + if (parameters.pubkey && parameters.pseudo === $scope.formData.pseudo) { + $scope.formData.pubkey = parameters.pubkey; + $scope.formData.computing = false; + return; + } + $scope.formData.computing=true; CryptoUtils.scryptKeypair($scope.formData.username, $scope.formData.password) .then(function(keypair) { $scope.formData.pubkey = CryptoUtils.util.encode_base58(keypair.signPk); - $scope.formData.computing=false; - $scope.checkAccountAvailable(); + return $scope.checkAccountAvailable(); + }) + .then(function() { + return $timeout(function(){ + $scope.formData.computing=false; + }, 400); }) .catch(function(err) { - $scope.formData.computing=false; $scope.formData.pubkey = undefined; + $scope.formData.computing=false; UIUtils.onError('ERROR.CRYPTO_UNKNOWN_ERROR')(err); }); }; @@ -207,6 +239,7 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil var index = $scope.slides.slider.activeIndex; if($scope.accountType === 'member') { index += ($scope.licenseFileUrl ? 0 : 1); // skip index 0, when no license file + index += (parameters.pubkey && index >= 2 ? 2 : 0); // skip salt+pass, if already a pubkey if (index === 0) return "licenseForm"; if (index === 1) return "pseudoForm"; if (index === 2) return "saltForm"; @@ -224,14 +257,14 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil var formName = $scope.getCurrentFormName(); var behavior; - if (formName == "licenseForm") { + if (formName === "licenseForm") { behavior = { hasPreviousButton: false, hasNextButton: false, hasAcceptButton: true }; } - else if (formName == "pseudoForm") { + else if (formName === "pseudoForm") { behavior = { helpAnchor: 'join-pseudo', hasPreviousButton: $scope.licenseFileUrl && true, @@ -239,15 +272,15 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil focus: 'pseudo' }; } - else if (formName == "saltForm") { + else if (formName === "saltForm") { behavior = { helpAnchor: 'join-salt', - hasPreviousButton: true, + hasPreviousButton: $scope.accountType === 'member', hasNextButton: true, focus: 'salt' }; } - else if (formName == "passwordForm") { + else if (formName === "passwordForm") { behavior = { helpAnchor: 'join-password', hasPreviousButton: true, @@ -255,7 +288,7 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil focus: 'password' }; } - else if (formName == "confirmForm") { + else if (formName === "confirmForm") { behavior = { hasPreviousButton: true, hasNextButton: false, @@ -294,6 +327,11 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil $scope.slideBehavior = $scope.computeSlideBehavior(); }; + $scope.doPrev = function() { + $scope.slidePrev(); + $scope.slideBehavior = $scope.computeSlideBehavior(); + }; + $scope.doNewAccount = function(confirm) { if (!confirm) { @@ -316,16 +354,25 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil var onErrorLogout = function(message) { return function(err) { - csWallet.logout() - .then(function(){ - UIUtils.onError(message)(err); - }); + if (parameter.uid) { + wallet.unauth() + .then(function(){ + UIUtils.onError(message)(err); + }); + } + else { + wallet.logout() + .then(function(){ + UIUtils.onError(message)(err); + }); + } + throw new Error('CANCELLED'); }; }; UIUtils.loading.show(); - return csWallet.login({ + return wallet.login({ auth: true, isNew: true, method: 'SCRYPT_DEFAULT', @@ -338,44 +385,74 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil csSettings.data.wallet = csSettings.data.wallet || {}; csSettings.data.wallet.alertIfUnusedWallet = false; // do not alert if empty - // Send self - return csWallet.self($scope.formData.pseudo, false/*do NOT load membership here*/) + var needSelf = angular.isUndefined(parameters.uid) || angular.isUndefined(parameters.blockUid) || + (parameters.uid.toUpperCase() !== $scope.formData.pseudo.toUpperCase()); + if (!needSelf) { + wallet.setSelf(parameters.uid, parameters.blockUid); + } + + // Self promise (if need) + var selfPromise = needSelf ? + wallet.self($scope.formData.pseudo, false/*do NOT load membership here*/) + .catch(onErrorLogout('ERROR.SEND_IDENTITY_FAILED')) : + $q.when(); + + return selfPromise .then(function() { // Send membership IN - csWallet.membership.inside() - .then(function() { - - $scope.closeModal(); - - // Redirect to wallet - $state.go('app.view_wallet') - .then(function() { - // Wait 12s (for wallet load) - // then ask to download revocation file - return $timeout( - $scope.downloadRevocationRegistration, - 2000); - }); - }) - .catch(function(err) { - if (err && err.ucode != BMA.errorCodes.MEMBERSHIP_ALREADY_SEND) return; - onErrorLogout('ERROR.SEND_MEMBERSHIP_IN_FAILED')(err); - }); + return wallet.membership.inside() + .catch(function(err) { + if (err && err.ucode != BMA.errorCodes.MEMBERSHIP_ALREADY_SEND) return; + onErrorLogout('ERROR.SEND_MEMBERSHIP_IN_FAILED')(err); + }); + }) + .then(function() { + + $scope.closeModal(); + + // Redirect to wallet + if (wallet.isDefault()) { + return $state.go('app.view_wallet'); + } else { + return $state.go('app.view_wallet_by_id', {id: wallet.id}); + } }) - .catch(onErrorLogout('ERROR.SEND_IDENTITY_FAILED')); + .then(function() { + // Wait 2s (for wallet load) + // then ask to download revocation file + return $timeout(function() { + // Hide the loading indicator, if wallet already loaded + if (wallet.isDataLoaded({requirements: true})) { + UIUtils.loading.hide(); + } + return $scope.downloadRevocationRegistration(); + }, + 2000); + }); } else{ $scope.closeModal(); // Redirect to wallet - $state.go('app.view_wallet'); + if (wallet.isDefault()) { + $state.go('app.view_wallet'); + } + else { + $state.go('app.view_wallet_by_id', {id: wallet.id}); + } } }) .catch(function(err) { UIUtils.loading.hide(); - console.error('>>>>>>>' , err); - UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); + if (err === 'CANCELLED') return; + if (err && err.ucode != BMA.errorCodes.MEMBERSHIP_ALREADY_SEND) { + console.error("[wallet] Node: already membership", err); + return; // OK + } + else { + UIUtils.alert.error('ERROR.UNKNOWN_ERROR'); + } }); }; @@ -388,7 +465,7 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil }) .then(function(confirm) { if (!confirm) return; - return csWallet.downloadRevocation(); + return wallet.downloadRevocation(); }); }; @@ -434,48 +511,59 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil var uid = $scope.formData.pseudo.toUpperCase(); $scope.formData.computing=true; - // search on uid - BMA.wot.lookup({ search: uid }) - .then(function(res) { - $scope.uiAlreadyUsed = (res.results || []).some(function(pub){ - return (pub.uids || []).some(function(idty) { - return (idty.uid.toUpperCase() === uid); // same Uid - }); - }); - $scope.formData.computing=false; - }) - .catch(function(err){ - console.error(err); - $scope.formData.computing=false; - $scope.uiAlreadyUsed = false; - }); + // Same has given uid + self block: skip control + if (parameters.uid && uid === parameters.uid.toUpperCase()) { + $scope.formData.computing=false; + $scope.uiAlreadyUsed = false; + return; + } + else { + // search on uid + BMA.wot.lookup({ search: uid }) + .then(function(res) { + $scope.uiAlreadyUsed = (res.results || []).some(function(pub){ + return (pub.uids || []).some(function(idty) { + return (idty.uid.toUpperCase() === uid); // same Uid + }); + }); + $scope.formData.computing=false; + }) + .catch(function(err){ + console.error(err); + $scope.formData.computing=false; + $scope.uiAlreadyUsed = false; + }); + } }; $scope.$watch('formData.pseudo', $scope.checkUid, true); $scope.checkAccountAvailable = function() { + if (parameters.pubkey) { + $scope.accountAvailable = true; + return; + } + delete $scope.accountAvailable; // Search for tx source, from pubkey - BMA.tx.sources({ pubkey: $scope.formData.pubkey }) + return BMA.tx.sources({ pubkey: $scope.formData.pubkey }) .then(function(res) { - if(!res.sources.length) { - $scope.formData.computing=false; - $scope.accountAvailable = true; - } - else{ - $scope.formData.computing=false; - $scope.accountAvailable = false; - } + $scope.accountAvailable = !res || !res.sources.length; }) .catch(function(err) { console.error(err); - $scope.formData.computing=false; $scope.accountAvailable = false; }); }; $scope.identifierRecovery = function() { - for (var i = 0; i < 2; i++) - $scope.slidePrev(); + // Go back + $scope.slides.slider.unlockSwipes(); + for (var i = 0; i < 2; i++) { + $scope.slides.slider.slidePrev(); + } + $scope.slides.slider.lockSwipes(); + // Recompute behavior + $scope.slideBehavior = $scope.computeSlideBehavior(); }; // TODO: remove auto add account when done diff --git a/assets/www/dist/dist_js/app/controllers/login-controllers.js b/assets/www/dist/dist_js/app/controllers/login-controllers.js index dac34de333772b684ec448d6269c2daf1c488b8c..6ddd4a486bc27ab30d95f54e939468c1ad403749 100644 --- a/assets/www/dist/dist_js/app/controllers/login-controllers.js +++ b/assets/www/dist/dist_js/app/controllers/login-controllers.js @@ -1,16 +1,53 @@ -LoginModalController.$inject = ['$scope', '$timeout', '$q', '$ionicPopover', '$ionicPopup', '$translate', 'CryptoUtils', 'UIUtils', 'BMA', 'Modals', 'csSettings', 'Device', 'parameters']; +LoginController.$inject = ['$scope', '$timeout', '$controller', 'csWallet']; +LoginModalController.$inject = ['$scope', '$timeout', '$q', '$ionicPopover', 'CryptoUtils', 'csCrypto', 'ionicReady', 'UIUtils', 'BMA', 'Modals', 'csSettings', 'Device', 'parameters']; AuthController.$inject = ['$scope', '$controller']; angular.module('cesium.login.controllers', ['cesium.services']) + .config(['$stateProvider', function($stateProvider) { + 'ngInject'; + + $stateProvider + .state('app.login', { + url: "/login", + views: { + 'menuContent': { + templateUrl: "templates/home/home.html", + controller: 'LoginCtrl' + } + } + }) + ; + }]) + + .controller('LoginCtrl', LoginController) + .controller('LoginModalCtrl', LoginModalController) .controller('AuthCtrl', AuthController) ; -function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, $translate, - CryptoUtils, UIUtils, BMA, Modals, csSettings, Device, parameters) { + +function LoginController($scope, $timeout, $controller, csWallet) { + 'ngInject'; + + // Initialize the super class and extend it. + angular.extend(this, $controller('HomeCtrl', {$scope: $scope})); + + $scope.showLoginModal = function() { + if ($scope.loading) return $timeout($scope.showLoginModal, 500); // recursive call + + if (!csWallet.isLogin() && !$scope.error) { + return $timeout(csWallet.login, 300); + } + }; + $scope.$on('$ionicView.enter', $scope.showLoginModal); + +} + +function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, csCrypto, ionicReady, + UIUtils, BMA, Modals, csSettings, Device, parameters) { 'ngInject'; parameters = parameters || {}; @@ -21,11 +58,15 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, $scope.showPubkey = false; $scope.showComputePubkeyButton = false; $scope.autoComputePubkey = false; - $scope.pubkeyPattern = '^' + BMA.constants.regexp.PUBKEY + '$'; + $scope.pubkeyPattern = '^(:?{0}|{1})$'.format(BMA.constants.regexp.PUBKEY, BMA.constants.regexp.PUBKEY_WITH_CHECKSUM); $scope.isAuth = parameters.auth; + $scope.okText = parameters.okText; + $scope.title = parameters.title || ($scope.isAuth ? 'AUTH.TITLE' : 'LOGIN.TITLE'); $scope.showMethods = angular.isDefined(parameters.showMethods) ? parameters.showMethods : true; + $scope.showNewAccountLink = angular.isDefined(parameters.showNewAccountLink) ? parameters.showNewAccountLink : true; $scope.expectedPubkey = parameters.expectedPubkey; + $scope.expectedUid = parameters.uid; $scope.scryptParamsValues = _.keys(CryptoUtils.constants.SCRYPT_PARAMS) .reduce(function(res, key) { @@ -34,9 +75,12 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, // modal init $scope.init = function() { - // Should auto-compute pubkey ? - $scope.autoComputePubkey = ionic.Platform.grade.toLowerCase()==='a' && - !UIUtils.screen.isSmall(); + + ionicReady().then(function(){ + // Should auto-compute pubkey ? + $scope.autoComputePubkey = ionic.Platform.grade.toLowerCase()==='a' && + !UIUtils.screen.isSmall(); + }); // Init remember me $scope.formData.rememberMe = csSettings.data.rememberMe; @@ -48,8 +92,9 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, // Init method var method = parameters.method || csSettings.data.login && csSettings.data.login.method || 'SCRYPT_DEFAULT'; var params = csSettings.data.login && csSettings.data.login.params; - if ($scope.isAuth && method == 'PUBKEY') { - method = 'SCRYPT_DEFAULT'; // PUBKEY not enable if auth need + // used default method, when PUBKEY + auth, or SCAN, or if ask for 'default' + if (($scope.isAuth && method === 'PUBKEY') || (method === 'SCAN') || (method === 'default')) { + method = 'SCRYPT_DEFAULT'; } $scope.changeMethod(method, params); }; @@ -72,15 +117,15 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, $scope.$on('modal.hide', $scope.leave); // Login form submit - $scope.doLogin = function() { - if(!$scope.form.$valid) { - return; - } + $scope.doLogin = function(skipForm) { + var method = $scope.formData.method; + + if(!$scope.form.$valid && method !== 'SCAN') return; + // removeIf(no-device) Device.keyboard.close(); // endRemoveIf(no-device) - var method = $scope.formData.method; var keepAuthIdle = $scope.formData.keepAuthIdle; var promise; @@ -119,9 +164,12 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, // If checkbox keep auth checked: set idle time to session keepAuthIdle = ($scope.formData.keepAuth && csSettings.constants.KEEP_AUTH_IDLE_SESSION) || keepAuthIdle; - UIUtils.loading.show(); - promise = $scope.readKeyFile($scope.formData.file, { - withSecret: ($scope.isAuth||$scope.formData.keepAuth) + promise = + UIUtils.loading.show() + .then(function() { + return $scope.readKeyFile($scope.formData.file, { + withSecret: ($scope.isAuth || $scope.formData.keepAuth) + }); }) .then(function(keypair) { if (!keypair) return UIUtils.loading.hide(10); @@ -140,18 +188,67 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, keypair: keypair }; }) - .catch(function(err) { - - UIUtils.onError('ERROR.AUTH_FILE_ERROR')(err); - }); + .catch(UIUtils.onError('ERROR.AUTH_FILE_ERROR')); } // Pubkey else if (method === 'PUBKEY') { - if (!$scope.formData.pubkey) return; - promise = $q.when({ - pubkey: $scope.formData.pubkey - }); + var pubkey = $scope.formData.pubkey && $scope.formData.pubkey.trim(); + var uid = $scope.formData.uid && $scope.formData.uid.trim() || undefined; + if (!pubkey) return; + var matches = BMA.regexp.PUBKEY.exec(pubkey); + // valid pubkey: use it + if (matches) { + promise = UIUtils.loading.show() + .then(function() { + return { + pubkey: pubkey, + uid : uid + }; + }); + } + + // Check checksum + else { + + matches = BMA.regexp.PUBKEY_WITH_CHECKSUM.exec(pubkey); + if (matches) { + + pubkey = matches[1]; + var checksum = matches[2]; + var expectedChecksum = csCrypto.util.pkChecksum(pubkey); + if (checksum != expectedChecksum) { + $scope.form.pubkey.$error = {checksum: true}; + } + else { + promise = UIUtils.loading.show() + .then(function() { + return { + pubkey: pubkey, + uid : uid + }; + }); + } + } + // Not a pubkey: launch search on + else { + return $scope.showWotLookupModal(pubkey); + } + } + } + + // Scan QR code + else if (method === 'SCAN') { + var valid = $scope.formData.pubkey && (!$scope.isAuth || !!$scope.formData.keypair); + if (!valid) return; + + promise = UIUtils.loading.show() + .then(function() { + return { + pubkey: $scope.formData.pubkey, + keypair: $scope.formData.keypair + }; + }); } if (!promise) { @@ -233,6 +330,7 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, .catch(function (err) { UIUtils.onError('ERROR.CRYPTO_UNKNOWN_ERROR')(err); $scope.computing = false; + $scope.autoComputePubkey = false; // Avoid a infinite loop (computePubkey -> onScryptFormChanged -> computePubkey) $scope.onScryptFormChanged(); }); }, 100); @@ -256,12 +354,79 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, return Modals.showHelp(parameters); }; + $scope.doScan = function() { + if ($scope.computing) return; + + $scope.computing = true; + $scope.formData.pubkey = null; + $scope.formData.keypair = null; + + // Run scan cordova plugin, on device + return Device.barcode.scan() + .then(function(data) { + if (!data) return; + + // Skip simple parsing, if auth if need + if ($scope.isAuth) return $q.when(data); + + // Try to parse as an URI + return BMA.uri.parse(data) + .then(function (res) { + if (!res || !res.pubkey) throw {message: 'ERROR.SCAN_UNKNOWN_FORMAT'}; + // If simple pubkey + return res; + }) + .catch(function(err) { + console.debug('[login] Error while parsing as URI: ' + (err && err.message || err)); + return data; + }); + }) + .then(function(data) { + if (!data) return; + // Parse success: continue + if (data && data.pubkey) return data; + + // Try to read as WIF format + return csCrypto.keyfile.parseData(data, {silent: true}) + .then(function(keypair) { + if (!keypair || !keypair.signPk || !keypair.signSk) throw {message: 'ERROR.SCAN_UNKNOWN_FORMAT'}; // rethrow an error + + var pubkey = CryptoUtils.base58.encode(keypair.signPk); + + // Login using keypair + return { + pubkey: pubkey, + keypair: keypair + }; + }) + // Unknown format (nor URI, nor WIF/EWIF) + .catch(UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')); + }) + .then(function(res) { + if (!res || !res.pubkey) return; // no data + + $scope.pubkeyError = $scope.expectedPubkey && $scope.expectedPubkey != res.pubkey; + $scope.formData.pubkey = res.pubkey; + $scope.formData.keypair = res.keypair; + }) + .then(function() { + $scope.computing = false; + UIUtils.loading.hide(10); + }) + .catch(function(err) { + $scope.computing = false; + UIUtils.onError('ERROR.SCAN_FAILED')(err); + }); + }; + $scope.changeMethod = function(method, params){ $scope.hideMethodsPopover(); - if (method == $scope.formData.method) return; // same method + + if (!method || method == $scope.formData.method) return; // same method console.debug("[login] method is: " + method); $scope.formData.method = method; + $scope.formData.uid = null; if ($scope.form) { // hide form's fields errors on the form @@ -270,6 +435,9 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, // Scrypt (advanced or not) if (method == 'SCRYPT_DEFAULT' || method == 'SCRYPT_ADVANCED') { + $scope.pubkey = null; + + // Search scrypt object var scrypt; if (params) { @@ -288,11 +456,15 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, $scope.autoComputePubkey = $scope.autoComputePubkey && (method == 'SCRYPT_DEFAULT'); } + else if (method == 'SCAN') { + return $scope.doScan(); + } else { $scope.formData.username = null; $scope.formData.password = null; $scope.formData.pubkey = null; - $scope.formData.computing = false; + $scope.pubkey = null; + $scope.computing = false; } }; @@ -304,23 +476,34 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, $scope.readKeyFile = function(file, options) { options = options || {}; - options.password = options.password || $scope.formData.file.password; - return CryptoUtils.readKeyFile($scope.formData.file, options) + + options.password = options.password || $scope.formData.file.password || function() { + $scope.formData.file.password = undefined; + return Modals.showPassword({ + title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', + subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP', + error: options.error, + scope: $scope + }) + .then(function (password) { + // Remember password (for validation) + $scope.formData.file.password = password; + // Timeout is need to force popup to be hide + return $timeout(function() { + return password; + }, 150); + }); + }; + + return csCrypto.keyfile.read($scope.formData.file, options) .catch(function(err) { - if (err && (err == 'NEED_PASSWORD' || err == 'BAD_PASSWORD')) { - $scope.formData.file.password = undefined; // reset password - options.password = undefined; // reset password - return Modals.showPassword({ - title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', - subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP' - }) - .then(function (password) { - if (!password) throw 'CANCELLED'; - - // Set password, then retry - $scope.formData.file.password = password; - return $scope.readKeyFile($scope.formData.file, options); - }); + $scope.formData.file.password = undefined; + if (err === 'CANCELLED') { + UIUtils.loading.hide(10); + } + if (err && err.ucode == csCrypto.errorCodes.BAD_PASSWORD) { + // Recursive call + return $scope.readKeyFile($scope.formData.file, {withSecret: options.withSecret, error: 'ACCOUNT.SECURITY.KEYFILE.ERROR.BAD_PASSWORD'}); } throw err; }); @@ -352,7 +535,7 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, }) .catch(function(err) { - if (err && err == 'CANCELLED') { + if (err && err === 'CANCELLED') { $scope.removeKeyFile(); return; } @@ -405,48 +588,38 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, /* -- modals -- */ - $scope.showWotLookupModal = function() { - return Modals.showWotLookup() + $scope.showWotLookupModal = function(searchText) { + return Modals.showWotLookup({q: searchText}) .then(function(res){ if (res && res.pubkey) { $scope.formData.pubkey = res.pubkey; + $scope.formData.uid = res.uid || undefined; + return $timeout($scope.doLogin, 300); } }); }; /* -- popover -- */ - $scope.showMethodsPopover = function(event) { if (event.defaultPrevented) return; - if (!$scope.methodsPopover) { - - $ionicPopover.fromTemplateUrl('templates/login/popover_methods.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl :'templates/login/popover_methods.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.methodsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.methodsPopover.remove(); - }); - $scope.methodsPopover.show(event) - .then(function() { - UIUtils.ink({selector: '.popover-login-methods .item'}); - }); - }); - } - else { - $scope.methodsPopover.show(event); - } + UIUtils.ink({selector: '.popover-login-methods .item'}); + } + }); }; $scope.hideMethodsPopover = function() { if ($scope.methodsPopover) { $scope.methodsPopover.hide(); + $scope.methodsPopover = null; } }; - - // Default action $scope.init(); diff --git a/assets/www/dist/dist_js/app/controllers/network-controllers.js b/assets/www/dist/dist_js/app/controllers/network-controllers.js index 907156590a982625ef5dc79667c0db84cdfcbb14..75f1a622e1f809272ae3222e3ce2ae409db349b4 100644 --- a/assets/www/dist/dist_js/app/controllers/network-controllers.js +++ b/assets/www/dist/dist_js/app/controllers/network-controllers.js @@ -13,7 +13,7 @@ angular.module('cesium.network.controllers', ['cesium.services']) .state('app.network', { url: "/network?type&expert", - cache: false, + cache: false, // fix #766 views: { 'menuContent': { templateUrl: "templates/network/view_network.html", @@ -65,12 +65,27 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win loading: true, type: undefined, results: [], - endpointFilter: null, + endpoint: null, + bma: undefined, + ssl: undefined, + ws2p: undefined, sort : undefined, asc: true }; + $scope.compactMode = true; + $scope.listeners = []; $scope.helptipPrefix = 'helptip-network'; - $scope.eanbleLocationHref = true; // can be overrided by sub-controler (e.g. popup) + $scope.enableLocationHref = true; // can be overrided by sub-controler (e.g. popup) + + $scope.removeListeners = function() { + if ($scope.listeners.length) { + console.debug("[network] Closing listeners"); + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + } + }; /** * Enter in view @@ -107,6 +122,7 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win */ $scope.leave = function() { if (!$scope.networkStarted) return; + $scope.removeListeners(); csNetwork.close(); $scope.networkStarted = false; $scope.search.loading = true; @@ -115,12 +131,16 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.$on('$ionicParentView.beforeLeave', $scope.leave); $scope.$on('$destroy', $scope.leave); + $scope.computeOptions = function() { var options = { filter: { member: (!$scope.search.type || $scope.search.type === 'member'), mirror: (!$scope.search.type || $scope.search.type === 'mirror'), - endpointFilter : (angular.isDefined($scope.search.endpointFilter) ? $scope.search.endpointFilter : null), + endpoint : (angular.isDefined($scope.search.endpoint) ? $scope.search.endpoint : null), + bma : $scope.search.bma, + ssl : $scope.search.ssl, + ws2p : $scope.search.ws2p, online: !($scope.search.type && $scope.search.type === 'offline') }, sort: { @@ -137,23 +157,25 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.load = function() { if ($scope.search.loading){ + // Start network scan csNetwork.start($scope.node, $scope.computeOptions()); // Catch event on new peers $scope.refreshing = false; - csNetwork.api.data.on.changed($scope, function(data){ - if (!$scope.refreshing) { - $scope.refreshing = true; - csWot.extendAll(data.peers) - .then(function() { - // Avoid to refresh if view has been leaving - if ($scope.networkStarted) { - $scope.updateView(data); - } - $scope.refreshing = false; - }); - } - }); + $scope.listeners.push( + csNetwork.api.data.on.changed($scope, function(data){ + if (!$scope.refreshing) { + $scope.refreshing = true; + csWot.extendAll(data.peers) + .then(function() { + // Avoid to refresh if view has been leaving + if ($scope.networkStarted) { + $scope.updateView(data); + } + $scope.refreshing = false; + }); + } + })); } // Show help tip @@ -162,17 +184,17 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.updateView = function(data) { console.debug("[peers] Updating UI"); - $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding + $scope.$broadcast('$$rebind::rebind'); // force data binding $scope.search.results = data.peers; $scope.search.memberPeersCount = data.memberPeersCount; // Always tru if network not started (e.g. after leave+renter the view) $scope.search.loading = !$scope.networkStarted || csNetwork.isBusy(); + if (!$scope.loading) { + $scope.$broadcast('$$rebind::rebind'); // force data binding + } if ($scope.motion && $scope.search.results && $scope.search.results.length > 0) { $scope.motion.show({selector: '.item-peer'}); } - if (!$scope.loading) { - $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding - } }; $scope.refresh = function() { @@ -201,18 +223,18 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.load(); // Update location href - if ($scope.eanbleLocationHref) { + if ($scope.enableLocationHref) { $location.search({type: $scope.search.type}).replace(); } }; $scope.toggleSearchEndpoint = function(endpoint){ $scope.hideActionsPopover(); - if ($scope.search.endpointFilter === endpoint || endpoint === null) { - $scope.search.endpointFilter = null; + if ($scope.search.endpoint === endpoint || endpoint === null) { + $scope.search.endpoint = null; } else { - $scope.search.endpointFilter = endpoint; + $scope.search.endpoint = endpoint; } $scope.sort(); }; @@ -229,9 +251,19 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.sort(); }; + $scope.toggleCompactMode = function() { + $scope.compactMode = !$scope.compactMode; + $scope.$broadcast('$$rebind::rebind'); // force data binding + }; + $scope.selectPeer = function(peer) { - // Skipp offline or WS2P node - if (!peer.online || peer.isWs2p()) return; + if (peer.compacted && $scope.compactMode) { + $scope.toggleCompactMode(); + return; + } + + // Skipp offline or not a BMA peer + if (!peer.online || !peer.hasBma()) return; var stateParams = {server: peer.getServer()}; if (peer.isSsl()) { @@ -244,7 +276,7 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win }; $scope.$on('csView.action.refresh', function(event, context) { - if (context == 'peers') { + if (context === 'peers') { $scope.refresh(); } }); @@ -256,48 +288,45 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win /* -- popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('templates/network/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/network/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; - $scope.showEndpointsPopover = function($event, peer, endpointFilter) { - var endpoints = peer.getEndpoints(endpointFilter); + $scope.showEndpointsPopover = function($event, peer, endpointName) { + $event.preventDefault(); + $event.stopPropagation(); + + var endpoints = peer.getEndpoints(endpointName); endpoints = (endpoints||[]).reduce(function(res, ep) { - var bma = BMA.node.parseEndPoint(ep); + var bma = BMA.node.parseEndPoint(ep) || BMA.node.parseEndPoint(ep, endpointName); return res.concat({ label: 'NETWORK.VIEW.NODE_ADDRESS', - value: peer.getServer() + (bma.path||'') + value: peer.getServer(bma) + (bma && bma.path||'') }); }, []); if (!endpoints.length) return; + // Call extension points UIUtils.popover.show($event, { templateUrl: 'templates/network/popover_endpoints.html', bindings: { - titleKey: 'NETWORK.VIEW.ENDPOINTS.' + endpointFilter, + titleKey: 'NETWORK.VIEW.ENDPOINTS.' + endpointName, items: endpoints } }); - $event.stopPropagation(); }; $scope.showWs2pPopover = function($event, peer) { @@ -365,10 +394,13 @@ function NetworkLookupModalController($scope, $controller, parameters) { parameters = parameters || {}; $scope.enableFilter = angular.isDefined(parameters.enableFilter) ? parameters.enableFilter : true; $scope.search.type = angular.isDefined(parameters.type) ? parameters.type : $scope.search.type; - $scope.search.endpointFilter = angular.isDefined(parameters.endpointFilter) ? parameters.endpointFilter : $scope.search.endpointFilter; + $scope.search.endpoint = angular.isDefined(parameters.endpoint) ? parameters.endpoint : $scope.search.endpoint; + $scope.search.bma = angular.isDefined(parameters.bma) ? parameters.bma : $scope.search.bma; + $scope.search.ssl = angular.isDefined(parameters.ssl) ? parameters.ssl : $scope.search.ssl; + $scope.search.ws2p = angular.isDefined(parameters.ws2p) ? parameters.ws2p : $scope.search.ws2p; $scope.expertMode = angular.isDefined(parameters.expertMode) ? parameters.expertMode : $scope.expertMode; $scope.ionItemClass = parameters.ionItemClass || 'item-border-large'; - $scope.eanbleLocationHref = false; + $scope.enableLocationHref = false; $scope.helptipPrefix = ''; $scope.selectPeer = function(peer) { @@ -397,7 +429,7 @@ function NetworkLookupPopoverController($scope, $controller) { var parameters = parameters || {}; $scope.enableFilter = angular.isDefined(parameters.enableFilter) ? parameters.enableFilter : true; $scope.search.type = angular.isDefined(parameters.type) ? parameters.type : $scope.search.type; - $scope.search.endpointFilter = angular.isDefined(parameters.endpointFilter) ? parameters.endpointFilter : $scope.search.endpointFilter; + $scope.search.endpoint = angular.isDefined(parameters.endpoint) ? parameters.endpoint : $scope.search.endpoint; $scope.expertMode = angular.isDefined(parameters.expertMode) ? parameters.expertMode : $scope.expertMode; $scope.ionItemClass = parameters.ionItemClass || 'item-border-large'; $scope.helptipPrefix = ''; @@ -448,7 +480,6 @@ function PeerInfoPopoverController($scope, $q, csSettings, csCurrency, csHttp, B // Get node current version BMA.node.summary() .then(function(res){ - console.log(res); $scope.formData.version = res && res.duniter && res.duniter.version; $scope.formData.software = res && res.duniter && res.duniter.software; }) @@ -480,7 +511,7 @@ function PeerInfoPopoverController($scope, $q, csSettings, csCurrency, csHttp, B $scope.formData.hasNewRelease = false; } $scope.loading = false; - $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding + $scope.$broadcast('$$rebind::rebind'); // force data binding }); }; @@ -527,6 +558,9 @@ function PeerViewController($scope, $q, $window, $state, UIUtils, csWot, BMA) { }) .then(function(){ $scope.loading = false; + }) + .catch(function() { + $scope.loading = false; }); }); @@ -589,15 +623,19 @@ function PeerViewController($scope, $q, $window, $state, UIUtils, csWot, BMA) { .then(function(json) { $scope.node.pubkey = json.pubkey; $scope.node.currency = json.currency; + }) + .catch(function(err){ + console.error(err && err.message || err); }), // Get known peers $scope.node.network.peers() .then(function(json) { - var peers = json.peers.map(function (p) { + var peers = (json && json.peers || []).map(function (p) { var peer = new Peer(p); - peer.online = p.status == 'UP'; - peer.blockNumber = peer.block.replace(/-.+$/, ''); + peer.online = p.status === 'UP'; + peer.buid = peer.block; + peer.blockNumber = peer.buid && peer.buid.split('-')[0]; peer.dns = peer.getDns(); peer.id = peer.keyID(); peer.server = peer.getServer(); @@ -625,7 +663,11 @@ function PeerViewController($scope, $q, $window, $state, UIUtils, csWot, BMA) { $scope.current = json; }) ]) - .catch(UIUtils.onError(useTor ? "PEER.VIEW.ERROR.LOADING_TOR_NODE_ERROR" : "PEER.VIEW.ERROR.LOADING_NODE_ERROR")); + .catch(function(err) { + console.error(err && err.message || err); + UIUtils.onError(useTor ? "PEER.VIEW.ERROR.LOADING_TOR_NODE_ERROR" : "PEER.VIEW.ERROR.LOADING_NODE_ERROR")(err); + throw err; + }); }; $scope.selectPeer = function(peer) { diff --git a/assets/www/dist/dist_js/app/controllers/settings-controllers.js b/assets/www/dist/dist_js/app/controllers/settings-controllers.js index 51a699c1be37bfb9692aaf2f9926a9ea1ac4d9bb..72931bd6ed8f9f808c5203e972521918853b95f6 100644 --- a/assets/www/dist/dist_js/app/controllers/settings-controllers.js +++ b/assets/www/dist/dist_js/app/controllers/settings-controllers.js @@ -1,5 +1,5 @@ -SettingsController.$inject = ['$scope', '$q', '$ionicHistory', '$ionicPopup', '$timeout', '$translate', 'csHttp', 'UIUtils', 'BMA', 'csSettings', 'csPlatform', '$ionicPopover', 'Modals']; +SettingsController.$inject = ['$scope', '$q', '$window', '$ionicHistory', '$ionicPopup', '$timeout', '$translate', '$ionicPopover', 'UIUtils', 'Modals', 'BMA', 'csHttp', 'csConfig', 'csCurrency', 'csSettings', 'csPlatform']; angular.module('cesium.settings.controllers', ['cesium.services', 'cesium.currency.controllers']) .config(['$stateProvider', function($stateProvider) { 'ngInject'; @@ -21,8 +21,8 @@ angular.module('cesium.settings.controllers', ['cesium.services', 'cesium.curren .controller('SettingsCtrl', SettingsController) ; -function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $translate, csHttp, - UIUtils, BMA, csSettings, csPlatform, $ionicPopover, Modals) { +function SettingsController($scope, $q, $window, $ionicHistory, $ionicPopup, $timeout, $translate, $ionicPopover, + UIUtils, Modals, BMA, csHttp, csConfig, csCurrency, csSettings, csPlatform) { 'ngInject'; $scope.formData = angular.copy(csSettings.data); @@ -62,8 +62,47 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t }; $scope.keepAuthIdles = _.keys($scope.keepAuthIdleLabels); + $scope.blockValidityWindowLabels = { + 0: { + labelKey: 'SETTINGS.BLOCK_VALIDITY_OPTION.NONE' + }, + 6: { + labelKey: 'SETTINGS.BLOCK_VALIDITY_OPTION.N', + labelParams: {count: 6, time: undefined /*defined in enter*/} + }, + 12: { + labelKey: 'SETTINGS.BLOCK_VALIDITY_OPTION.N', + labelParams: {count: 12, time: undefined /*defined in enter*/} + }, + 24: { + labelKey: 'SETTINGS.BLOCK_VALIDITY_OPTION.N', + labelParams: {count: 24, time: undefined /*defined in enter*/} + } + }; + $scope.blockValidityWindows = _.keys($scope.blockValidityWindowLabels); + $scope.$on('$ionicView.enter', function() { - csSettings.ready().then($scope.load); + $q.all([ + csSettings.ready(), + csCurrency.parameters() + .then(function(parameters) { + return parameters && parameters.avgGenTime; + }) + // Make sure to continue even if node is down - Fix #788 + .catch(function(err) { + console.error("[settings] Could not not currency parameters. Using default 'avgGenTime' (300)", err); + return {avgGenTime: 300}; + }) + .then(function(parameters) { + _.each($scope.blockValidityWindows, function(blockCount) { + if (blockCount > 0) { + $scope.blockValidityWindowLabels[blockCount].labelParams.time= parameters.avgGenTime * blockCount; + } + }); + }) + ]) + .then($scope.load) + ; }); $scope.setPopupForm = function(popupForm) { @@ -83,9 +122,9 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t $scope.formData.locale = (csSettings.data.locale && csSettings.data.locale.id && _.findWhere($scope.locales, {id: csSettings.data.locale.id})) || _.findWhere($scope.locales, {id: csSettings.defaultSettings.locale.id}); - $scope.loading = false; - $timeout(function() { + return $timeout(function() { + $scope.loading = false; // Set Ink UIUtils.ink({selector: '.item'}); $scope.showHelpTip(); @@ -112,9 +151,10 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t // Change node $scope.changeNode= function(node) { + var port = !!$scope.formData.node.port && $scope.formData.node.port != 80 && $scope.formData.node.port != 443 ? $scope.formData.node.port : undefined; node = node || { host: $scope.formData.node.host, - port: $scope.formData.node.port && $scope.formData.node.port != 80 && $scope.formData.node.port != 443 ? $scope.formData.node.port : undefined, + port: port, useSsl: angular.isDefined($scope.formData.node.useSsl) ? $scope.formData.node.useSsl : ($scope.formData.node.port == 443) @@ -123,7 +163,7 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t .then(function(newNode) { if (newNode.host === $scope.formData.node.host && newNode.port === $scope.formData.node.port && - newNode.useSsl === $scope.formData.node.useSsl) { + newNode.useSsl === $scope.formData.node.useSsl && !$scope.formData.node.temporary) { return; // same node = nothing to do } UIUtils.loading.show(); @@ -139,12 +179,12 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t }); } UIUtils.loading.hide(); - $scope.formData.node = newNode; - delete $scope.formData.temporary; + angular.merge($scope.formData.node, newNode); + delete $scope.formData.node.temporary; BMA.copy(nodeBMA); $scope.bma = BMA; - // Start platform is not already started + // Restart platform (or start if not already started) csPlatform.restart(); // Reset history cache @@ -154,8 +194,16 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t }; $scope.showNodeList = function() { + // Check if need a filter on SSL node + var forceUseSsl = (csConfig.httpsMode === 'true' || csConfig.httpsMode === true || csConfig.httpsMode === 'force') || + ($window.location && $window.location.protocol === 'https:') ? true : false; + $ionicPopup._popupStack[0].responseDeferred.promise.close(); - return Modals.showNetworkLookup({enableFilter: true, type: 'member'}) + return Modals.showNetworkLookup({ + enableFilter: true, // enable filter button + bma: true, // only BMA node + ssl: forceUseSsl ? true : undefined + }) .then(function (peer) { if (peer) { var bma = peer.getBMA(); @@ -163,7 +211,7 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t host: (bma.dns ? bma.dns : (peer.hasValid4(bma) ? bma.ipv4 : bma.ipv6)), port: bma.port || 80, - useSsl: bma.useSsl + useSsl: bma.useSsl || bma.port == 443 }; } }) @@ -237,17 +285,22 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t $scope.saving = true; // Async - to avoid UI lock - $timeout(function() { + return $timeout(function() { // Make sure to format helptip $scope.cleanupHelpTip(); - angular.merge(csSettings.data, $scope.formData); - // Manually removed some attributes - if (!$scope.formData.temporary) { - delete csSettings.data.node.temporary; - } - csSettings.store(); - $scope.saving = false; - }, 100); + + // Applying + csSettings.apply($scope.formData); + + // Store + return csSettings.store(); + + }, 100) + .then(function() { + //return $timeout(function() { + $scope.saving = false; + //}, 100); + }); }; $scope.onDataChanged = function(oldValue, newValue, scope) { @@ -261,14 +314,24 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t }, 500); } - var updated = !angular.equals(oldValue, newValue); - if (updated) { - //console.debug('Detected settings update: will save it'); + // Changes from the current scope: save changes + if ((scope === $scope) && !angular.equals(oldValue, newValue)) { $scope.save(); } }; $scope.$watch('formData', $scope.onDataChanged, true); + // Detected changes from outside (e.g. enabling encryption on wallet can be rollback if user cancel auth) + csSettings.api.data.on.changed($scope, function(data) { + if ($scope.loading || $scope.saving || $scope.pendingSaving) return; + + var updated = !angular.equals(data.useLocalStorageEncryption, $scope.formData.useLocalStorageEncryption); + if (updated) { + console.debug('[settings] Settings changed (outside the settings page). Reloading...'); + $scope.load(); + } + }); + $scope.getServer = function() { if (!$scope.formData.node || !$scope.formData.node.host) return ''; return csHttp.getServer($scope.formData.node.host, $scope.formData.node.port); @@ -288,26 +351,20 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t /* -- modals & popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('templates/settings/popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/settings/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; diff --git a/assets/www/dist/dist_js/app/controllers/transfer-controllers.js b/assets/www/dist/dist_js/app/controllers/transfer-controllers.js index 5a8c9a35fa77d46f8694e7971c3da3a3f278000c..bceda146579887b450117eed7c7137c997ef6ae8 100644 --- a/assets/www/dist/dist_js/app/controllers/transfer-controllers.js +++ b/assets/www/dist/dist_js/app/controllers/transfer-controllers.js @@ -1,6 +1,6 @@ -TransferController.$inject = ['$scope', '$controller', 'Device', 'UIUtils', 'csWot', 'csWallet']; -TransferModalController.$inject = ['$scope', '$q', '$translate', '$timeout', '$filter', '$focus', 'Device', 'BMA', 'csWallet', 'UIUtils', 'Modals', 'csCurrency', 'csSettings', 'parameters'];angular.module('cesium.transfer.controllers', ['cesium.services', 'cesium.currency.controllers']) +TransferController.$inject = ['$scope', '$controller', 'UIUtils']; +TransferModalController.$inject = ['$scope', '$q', '$translate', '$timeout', '$filter', '$focus', 'Device', 'BMA', 'UIUtils', 'Modals', 'csWallet', 'csWot', 'csCurrency', 'csSettings', 'parameters'];angular.module('cesium.transfer.controllers', ['cesium.services', 'cesium.currency.controllers']) .config(['$stateProvider', function($stateProvider) { 'ngInject'; @@ -8,7 +8,7 @@ TransferModalController.$inject = ['$scope', '$q', '$translate', '$timeout', '$f .state('app.new_transfer', { cache: false, - url: "/transfer?amount&udAmount&comment", + url: "/transfer?amount&udAmount&comment&restPub&all&wallet", views: { 'menuContent': { templateUrl: "templates/wallet/new_transfer.html", @@ -19,7 +19,7 @@ TransferModalController.$inject = ['$scope', '$q', '$translate', '$timeout', '$f .state('app.new_transfer_pubkey_uid', { cache: false, - url: "/transfer/:pubkey/:uid?amount&udAmount&comment", + url: "/transfer/:pubkey/:uid?amount&udAmount&comment&restPub&all&wallet", views: { 'menuContent': { templateUrl: "templates/wallet/new_transfer.html", @@ -30,7 +30,7 @@ TransferModalController.$inject = ['$scope', '$q', '$translate', '$timeout', '$f .state('app.new_transfer_pubkey', { cache: false, - url: "/transfer/:pubkey?amount&udAmount&comment", + url: "/transfer/:pubkey?amount&udAmount&comment&restPub&all&wallet", views: { 'menuContent': { templateUrl: "templates/wallet/new_transfer.html", @@ -46,7 +46,7 @@ TransferModalController.$inject = ['$scope', '$q', '$translate', '$timeout', '$f .controller('TransferModalCtrl', TransferModalController) ; -function TransferController($scope, $controller, Device, UIUtils, csWot, csWallet) { +function TransferController($scope, $controller, UIUtils) { 'ngInject'; // Initialize the super class and extend it. @@ -54,49 +54,14 @@ function TransferController($scope, $controller, Device, UIUtils, csWot, csWalle $scope.enter = function(e, state) { - // Compute parameters - var parameters = {}; + // Apply state parameters if (state && state.stateParams) { - if (state.stateParams.pubkey) { - parameters.pubkey = state.stateParams.pubkey; - } - if (state.stateParams.amount) { - parameters.useRelative = false; - parameters.amount = state.stateParams.amount; - } - else if (state.stateParams.udAmount) { - parameters.useRelative = true; - parameters.udAmount = state.stateParams.udAmount; - } - if (state.stateParams.comment) { - parameters.comment = state.stateParams.comment; - } + $scope.setParameters(state.stateParams); } - // Make sure wallet is loaded - csWallet.login({sources: true}) - - // If pubkey, get the uid (+ name, avatar) - .then(function(data) { - $scope.walletData = data; - if (parameters.pubkey) { - return csWot.extend({pubkey: parameters.pubkey}) - .then(function(dest) { - if (dest && dest.uid) { - parameters.uid = dest.name || dest.uid; - } - }); - } - }) - - // Apply parameters, then recompute relative amount - .then(function() { - $scope.setParameters(parameters); - $scope.onUseRelativeChanged(); - UIUtils.loading.hide(); - $scope.loading = false; - UIUtils.ink({selector: '.modal-transfer .ink'}); - }); + // Load wallet + return $scope.load() + .then(UIUtils.loading.hide); }; $scope.$on('$ionicView.enter', $scope.enter); @@ -110,18 +75,25 @@ function TransferController($scope, $controller, Device, UIUtils, csWot, csWalle }; } -function TransferModalController($scope, $q, $translate, $timeout, $filter, $focus, Device, BMA, csWallet, UIUtils, Modals, - csCurrency, csSettings, parameters) { +function TransferModalController($scope, $q, $translate, $timeout, $filter, $focus, Device, BMA, UIUtils, Modals, + csWallet, csWot, csCurrency, csSettings, parameters) { 'ngInject'; - var minQuantitativeAmount = 0.01; + var + wallet, + minQuantitativeAmount = 0.01; + $scope.convertedBalance = 0; $scope.formData = { destPub: null, amount: null, comment: null, useRelative: csSettings.data.useRelative, - useComment: false + useComment: false, + all: false, + restPub: null, + restAmount: null, + walletId: null }; $scope.udAmount = null; $scope.minAmount = minQuantitativeAmount; @@ -129,6 +101,7 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc $scope.currency = csCurrency.data.name; $scope.loading = true; $scope.commentInputId = 'transferComment-' + $scope.$id; + $scope.enableSelectWallet = true; // Define keyboard settings, to bind with model (If small screen AND mobile devices) $scope.smallscreen = angular.isDefined($scope.smallscreen) ? $scope.smallscreen : UIUtils.screen.isSmall(); @@ -139,7 +112,7 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc { decimal: true, decimalSeparator: '.', - resizeContent: true + resizeContent:false }); $scope.digitKeyboardVisible = false; } @@ -169,69 +142,149 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc $scope.formData.useComment=true; $scope.formData.comment = parameters.comment; } + if (parameters.restPub || parameters.all) { + $scope.restUid = ''; + $scope.restPub = parameters.restPub; + $scope.formData.restPub = parameters.restPub; + $scope.formData.all = true; + } + else { + $scope.formData.all = false; + } + if (!parameters.wallet || parameters.wallet === "default") { + $scope.formData.walletId = csWallet.id; + } + else { + $scope.formData.walletId = parameters.wallet; + } }; // Read default parameters $scope.setParameters(parameters); - $scope.enter = function() { + $scope.load = function() { + $scope.enableSelectWallet = csWallet.children.count() > 0; + + wallet = $scope.enableSelectWallet && ($scope.formData.walletId ? csWallet.children.get($scope.formData.walletId) : csWallet) || csWallet; + if (!wallet.isDefault()) { + console.debug("[transfer] Using wallet {" + wallet.id + "}"); + } // Make to sure to load full wallet data (balance) - return csWallet.login({sources: true, silent: true}) + return wallet.login({sources: true, silent: true}) .then(function(data) { - $scope.walletData = data; - $scope.onUseRelativeChanged(); + if (!wallet || $scope.$$destroyed) return; // user have cancelled before end of load + $scope.walletData = data; + $scope.formData.walletId = wallet.id; + $scope.onUseRelativeChanged(); + $scope.onAmountChanged(); + + $scope.$watch('walletData.balance', $scope.onAmountChanged, true); + $scope.$watch('formData.amount', $scope.onAmountChanged, true); + + $scope.$watch('formData.useRelative', $scope.onUseRelativeChanged, true); + $scope.$watch('walletData.balance', $scope.onUseRelativeChanged, true); + + UIUtils.ink({selector: '.modal-transfer .ink'}); + + if (!$scope.destPub || $scope.destUid) { $scope.loading = false; - UIUtils.ink({selector: '.modal-transfer .ink'}); - }) - .catch(function(err){ - if (err == 'CANCELLED') return $scope.cancel(); // close the modal - UIUtils.onError('ERROR.LOGIN_FAILED')(err); - }); + } + else { + // Fill the uid from the pubkey + return csWot.extend({pubkey: $scope.destPub}) + .then(function(res) { + $scope.destUid = res && (res.name || res.uid); + if ($scope.destUid) { + $scope.destPub = ''; + } + $scope.loading = false; + }); + } + }) + .catch(function(err){ + if (err === 'CANCELLED') return $scope.cancel(); // close the modal + UIUtils.onError('ERROR.LOGIN_FAILED')(err); + }); }; - $scope.$on('modal.shown', $scope.enter); + $scope.$on('modal.shown', $scope.load); $scope.cancel = function() { $scope.closeModal(); + wallet = null; }; // When changing use relative UD $scope.onUseRelativeChanged = function() { $scope.currency = csCurrency.data.name; if ($scope.formData.useRelative) { - $scope.convertedBalance = csWallet.data.balance / csCurrency.data.currentUD; + $scope.convertedBalance = $scope.walletData.balance / csCurrency.data.currentUD; $scope.minAmount = minQuantitativeAmount / (csCurrency.data.currentUD / 100); } else { - $scope.convertedBalance = csWallet.data.balance / 100; + $scope.convertedBalance = $scope.walletData.balance / 100; $scope.minAmount = minQuantitativeAmount; } - if ($scope.form) { - $scope.form.$valid = undefined; + if ($scope.form && !$scope.loading) { + $scope.form.$setPristine(true); } }; - $scope.$watch('formData.useRelative', $scope.onUseRelativeChanged, true); - $scope.$watch('walletData.balance', $scope.onUseRelativeChanged, true); - $scope.doTransfer = function() { - $scope.form.$submitted=true; + $scope.onAmountChanged = function() { + if ($scope.sending) return; // skip if sending TX - if(!$scope.form.$valid || !$scope.formData.destPub || !$scope.formData.amount) { - return; - } var amount = $scope.formData.amount; - if (typeof amount === "string") { + if (amount && typeof amount === "string") { amount = parseFloat(amount.replace(new RegExp('[.,]'), '.')); } + var valid = true; + // Avoid amount less than the minimal - fix #373 - if (amount < $scope.minAmount) { + if (amount && amount < $scope.minAmount) { + valid = false; + $scope.form.amount.$error = $scope.form.amount.$error || {}; + $scope.form.amount.$error.min = true; + } + else if ($scope.form.amount && $scope.form.amount.$error && $scope.form.amount.$error.min){ + delete $scope.form.amount.$error.min; + } + + // Avoid amount greater than the balance + if (amount && amount > $scope.convertedBalance){ $scope.form.$valid = false; $scope.form.amount.$invalid = true; $scope.form.amount.$error = $scope.form.amount.$error || {}; - $scope.form.amount.$error.min = true; + $scope.form.amount.$error = {max: true}; + } + else if ($scope.form.amount && $scope.form.amount.$error && $scope.form.amount.$error.max){ + delete $scope.form.amount.$error.max; + } + + $scope.form.$valid = valid; + if ($scope.form.amount) $scope.form.amount.$invalid = !valid; + + if (!valid || !$scope.formData.all || !amount) { + $scope.formData.restAmount = undefined; + } + else { + if ($scope.formData.useRelative) { + $scope.formData.restAmount = $scope.walletData.balance - amount * csCurrency.data.currentUD; + if ($scope.formData.restAmount < minQuantitativeAmount) { + $scope.formData.restAmount = 0; + } + } else { + $scope.formData.restAmount = $scope.walletData.balance - amount * 100; + } + } + }; + + $scope.doTransfer = function() { + $scope.form.$submitted=true; + + if(!$scope.form.$valid || !$scope.formData.destPub || !$scope.formData.amount) { return; } - else if ($scope.form.amount.$error && $scope.form.amount.$error.min){ - $scope.form.amount.$invalid = false; - delete $scope.form.amount.$error.min; + var amount = $scope.formData.amount; + if (typeof amount === "string") { + amount = parseFloat(amount.replace(new RegExp('[.,]'), '.')); } // Avoid multiple call @@ -241,7 +294,7 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc var currentUD; return $q.all([ // Make sure user is auth - csWallet.auth({silent: true}), + wallet.auth({silent: true}), // Get current UD csCurrency.currentUD() @@ -274,36 +327,46 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc if (comment && !comment.length) { comment = null; } - - return csWallet.transfer($scope.formData.destPub, amount, comment, $scope.formData.useRelative); + var hasRest = $scope.formData.all && $scope.formData.restAmount > 0; + if (hasRest) { + return wallet.transferAll($scope.formData.destPub, amount, comment, $scope.formData.useRelative, $scope.formData.restPub); + } + else { + return wallet.transfer($scope.formData.destPub, amount, comment, $scope.formData.useRelative); + } }) .then(function() { - $scope.sending = false; UIUtils.loading.hide(); return $scope.closeModal(true); }) .then(function(res) { $timeout(function() { + $scope.sending = false; UIUtils.toast.show('INFO.TRANSFER_SENT'); }, 500); return res; - }) - .catch(function(err) { - $scope.sending = false; - UIUtils.onError('ERROR.SEND_TX_FAILED')(err); }); + }) + .catch(function(err) { + $scope.sending = false; + // Wallet auth cancelled by user + if (err === 'CANCELLED') return; + UIUtils.onError('ERROR.SEND_TX_FAILED')(err); }); }; $scope.askTransferConfirm = function() { return $translate(['COMMON.UD', 'COMMON.EMPTY_PARENTHESIS']) .then(function(translations) { - return $translate('CONFIRM.TRANSFER', { - from: csWallet.data.isMember ? csWallet.data.uid : $filter('formatPubkey')(csWallet.data.pubkey), - to: $scope.destUid ? $scope.destUid : $scope.destPub, + var hasRest = $scope.formData.all && $scope.formData.restAmount > 0; + return $translate(hasRest ? 'CONFIRM.TRANSFER_ALL' : 'CONFIRM.TRANSFER', { + from: $scope.walletData.isMember ? $scope.walletData.uid : $filter('formatPubkey')($scope.walletData.pubkey), + to: $scope.destUid || $scope.destPub, amount: $scope.formData.amount, unit: $scope.formData.useRelative ? translations['COMMON.UD'] : $filter('abbreviate')($scope.currency), - comment: (!$scope.formData.comment || $scope.formData.comment.trim().length === 0) ? translations['COMMON.EMPTY_PARENTHESIS'] : $scope.formData.comment + comment: (!$scope.formData.comment || $scope.formData.comment.trim().length === 0) ? translations['COMMON.EMPTY_PARENTHESIS'] : $scope.formData.comment, + restAmount: hasRest && $filter('formatAmount')($scope.formData.restAmount, {useRelative: $scope.formData.useRelative}), + restTo: hasRest && ($scope.restUid || $scope.restPub) }); }) .then(UIUtils.alert.confirm); @@ -312,34 +375,50 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc $scope.addComment = function() { $scope.formData.useComment = true; // Focus on comment field - if ($scope.commentInputId) { - $timeout(function() { - $focus($scope.commentInputId); - }, 200); - } - }; + }; /* -- modals -- */ - $scope.showWotLookupModal = function() { + $scope.showWotLookupModal = function(formDataField) { + + formDataField = formDataField || 'destPub'; + // Hide numerical keyboard $scope.hideDigitKeyboard(0); - return Modals.showWotLookup() + return Modals.showWotLookup({enableWallets: true}) .then(function(result){ if (result) { - if (result.uid) { + if (formDataField == 'destPub') { $scope.destUid = result.uid; - $scope.destPub = ''; + $scope.destPub = result.uid ? '' : result.pubkey; + $scope.formData.destPub = result.pubkey; } - else { - $scope.destUid = ''; - $scope.destPub = result.pubkey; + else if (formDataField == 'restPub') { + $scope.restUid = result.uid; + $scope.restPub = result.uid ? '' : result.pubkey; + $scope.formData.restPub = result.pubkey; } - $scope.formData.destPub = result.pubkey; } }); }; + $scope.showSelectWalletModal = function() { + if (!$scope.enableSelectWallet) return; + + return Modals.showSelectWallet({ + useRelative: $scope.formData.useRelative, + showDefault: true, + showBalance: true + }) + .then(function(newWallet) { + if (!newWallet || (wallet && wallet.id === newWallet.id)) return; + wallet = newWallet; + $scope.walletData = wallet.data; + console.debug("[transfer] Using wallet {" + wallet.id + "}"); + $scope.onAmountChanged(); + }); + }; + /* -- popover -- */ $scope.showUnitPopover = function($event) { @@ -374,7 +453,6 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc return $q.when(); }; - $scope.hideDigitKeyboard = function(timeout) { if (!$scope.digitKeyboardVisible) return $q.when(); $scope.digitKeyboardVisible = false; diff --git a/assets/www/dist/dist_js/app/controllers/wallet-controllers.js b/assets/www/dist/dist_js/app/controllers/wallet-controllers.js index f8fe51215a031c6f3f115ef11f02ba7dd1467716..7e45275bd994ec5c8c0d0ad1091ffe2e0053fdc3 100644 --- a/assets/www/dist/dist_js/app/controllers/wallet-controllers.js +++ b/assets/www/dist/dist_js/app/controllers/wallet-controllers.js @@ -1,8 +1,8 @@ -WalletController.$inject = ['$scope', '$rootScope', '$q', '$ionicPopup', '$timeout', '$state', '$translate', '$ionicPopover', 'UIUtils', 'Modals', 'BMA', 'csConfig', 'csSettings', 'csWallet', 'csHelp']; -WalletTxController.$inject = ['$scope', '$ionicPopover', '$state', '$timeout', '$location', 'UIUtils', 'Modals', 'BMA', 'csSettings', 'csWallet', 'csTx']; -WalletTxErrorController.$inject = ['$scope', 'UIUtils', 'csWallet']; -WalletSecurityModalController.$inject = ['$scope', 'UIUtils', 'csWallet', '$translate'];angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency.controllers']) +WalletController.$inject = ['$scope', '$rootScope', '$q', '$ionicPopup', '$timeout', '$state', '$translate', '$ionicPopover', '$location', 'UIUtils', 'ModalUtils', 'Modals', 'csPopovers', 'BMA', 'csConfig', 'csSettings', 'csWallet', 'csHelp']; +WalletTxController.$inject = ['$scope', '$ionicPopover', '$state', '$timeout', '$location', 'UIUtils', 'Modals', 'csPopovers', 'BMA', 'csHttp', 'csSettings', 'csCurrency', 'csWallet', 'csTx']; +WalletTxErrorController.$inject = ['$scope', 'UIUtils', 'csSettings', 'csWallet']; +WalletSecurityModalController.$inject = ['$scope', 'UIUtils', 'csWallet', '$translate', 'parameters'];angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency.controllers']) .config(['$stateProvider', function($stateProvider) { 'ngInject'; @@ -10,7 +10,7 @@ WalletSecurityModalController.$inject = ['$scope', 'UIUtils', 'csWallet', '$tran .state('app.view_wallet', { - url: "/wallet?refresh", + url: "/account?refresh", views: { 'menuContent': { templateUrl: "templates/wallet/view_wallet.html", @@ -18,12 +18,13 @@ WalletSecurityModalController.$inject = ['$scope', 'UIUtils', 'csWallet', '$tran } }, data: { - login: true + login: true, + silentLocationChange: true } }) .state('app.view_wallet_tx', { - url: "/history?refresh", + url: "/history/account?refresh", views: { 'menuContent': { templateUrl: "templates/wallet/view_wallet_tx.html", @@ -37,7 +38,7 @@ WalletSecurityModalController.$inject = ['$scope', 'UIUtils', 'csWallet', '$tran }) .state('app.view_wallet_tx_errors', { - url: "/wallet/tx/errors", + url: "/history/account/errors", views: { 'menuContent': { templateUrl: "templates/wallet/view_wallet_tx_error.html", @@ -51,7 +52,6 @@ WalletSecurityModalController.$inject = ['$scope', 'UIUtils', 'csWallet', '$tran ; }]) - .controller('WalletCtrl', WalletController) .controller('WalletTxCtrl', WalletTxController) @@ -61,17 +61,33 @@ WalletSecurityModalController.$inject = ['$scope', 'UIUtils', 'csWallet', '$tran .controller('WalletSecurityModalCtrl', WalletSecurityModalController) ; -function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $translate, $ionicPopover, - UIUtils, Modals, BMA, csConfig, csSettings, csWallet, csHelp) { +function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $translate, $ionicPopover, $location, + UIUtils, ModalUtils, Modals, csPopovers, BMA, csConfig, csSettings, csWallet, csHelp) { 'ngInject'; $scope.loading = true; $scope.settings = csSettings.data; $scope.qrcodeId = 'qrcode-wallet-' + $scope.$id; + $scope.toggleQRCode = false; - $scope.$on('$ionicView.enter', function(e, state) { + + var wallet; + + $scope.enter = function(e, state) { $scope.loading = $scope.loading || (state.stateParams && state.stateParams.refresh); + $scope.enableSelectWallet = csWallet.children.count() > 0; if ($scope.loading) { // load once + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + $scope.isDefaultWallet = wallet.isDefault(); + $scope.walletId = wallet.id; + + $scope.cleanLocationHref(state); + return $scope.load(); } else { @@ -79,20 +95,24 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, UIUtils.loading.hide(); $timeout($scope.updateView, 300); } - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function() { - return $scope.loadWallet() + if (!wallet) return; + + return wallet.login() .then(function(walletData) { $scope.formData = walletData; $scope.loading=false; // very important, to avoid TX to be display before wallet.currentUd is loaded $scope.updateView(); $scope.showQRCode(); - $scope.showHelpTip(); + if (wallet.isDefault()) $scope.showHelpTip(); + $scope.addListeners(); UIUtils.loading.hide(); // loading could have be open (e.g. new account) }) .catch(function(err){ - if (err == 'CANCELLED') { + if (err === 'CANCELLED') { $scope.showHome(); } }); @@ -100,13 +120,9 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.updateView = function() { $scope.motion.show({selector: '#wallet .item'}); - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind + $scope.$broadcast('$$rebind::rebind'); // force rebind }; - // Listen new events (can appears from security wizard also) - $scope.$watchCollection('formData.events', function(newEvents, oldEvents) { - if (!oldEvents || $scope.loading || angular.equals(newEvents, oldEvents)) return; - $scope.updateView(); - }); + $scope.setRegisterForm = function(registerForm) { $scope.registerForm = registerForm; @@ -115,22 +131,43 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, // Clean controller data when logout $scope.onWalletLogout = function() { // clean QRcode - $scope.hideQRCode('qrcode'); + $scope.hideQRCode(); + $scope.removeListeners(); delete $scope.formData; + wallet = null; $scope.loading = true; }; - csWallet.api.data.on.logout($scope, $scope.onWalletLogout); + + $scope.addListeners = function() { + $scope.listeners = [ + // Reset the view on logout + wallet.api.data.on.logout($scope, $scope.onWalletLogout), + + // Listen new events (can appears from security wizard also) + $scope.$watchCollection('formData.events', function(newEvents, oldEvents) { + if (!oldEvents || $scope.loading || angular.equals(newEvents, oldEvents)) return; + $scope.updateView(); + }) + ]; + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; // Ask uid $scope.showUidPopup = function() { return $q(function(resolve, reject) { - $translate(['ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP', 'COMMON.BTN_OK', 'COMMON.BTN_CANCEL']) + $translate(['ACCOUNT.NEW.TITLE', 'ACCOUNT.POPUP_REGISTER.TITLE', 'ACCOUNT.POPUP_REGISTER.HELP', 'COMMON.BTN_OK', 'COMMON.BTN_CANCEL']) .then(function (translations) { $scope.formData.newUid = (!!$scope.formData.uid ? ''+$scope.formData.uid : ''); // Choose UID popup $ionicPopup.show({ - templateUrl: 'templates/login/popup_register.html', + templateUrl: 'templates/wallet/popup_register.html', title: translations['ACCOUNT.POPUP_REGISTER.TITLE'], subTitle: translations['ACCOUNT.POPUP_REGISTER.HELP'], scope: $scope, @@ -171,7 +208,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, .then(function(uid) { UIUtils.loading.show(); - return csWallet.self(uid) + return wallet.self(uid) .then(function() { $scope.updateView(); UIUtils.loading.hide(); @@ -186,17 +223,21 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, }; $scope.doMembershipIn = function(retryCount) { - return csWallet.membership.inside() + return wallet.membership.inside() .then(function() { $scope.updateView(); UIUtils.loading.hide(); }) .catch(function(err) { - if (err == 'CANCELLED') throw err; - if (err && err.ucode != BMA.errorCodes.MEMBERSHIP_ALREADY_SEND) return; + if (err === 'CANCELLED') throw err; + if (err && err.ucode != BMA.errorCodes.MEMBERSHIP_ALREADY_SEND) { + console.error("[wallet] Node: already membership", err); + UIUtils.loading.hide(); + return; // OK + } if (!retryCount || retryCount <= 2) { return $timeout(function() { - $scope.doMembershipIn(retryCount ? retryCount+1 : 1); + return $scope.doMembershipIn((retryCount||0) + 1); }, 1000); } throw err; @@ -208,48 +249,27 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.membershipIn = function(keepSelf) { $scope.hideActionsPopover(); - if (csWallet.isMember()) { + if (wallet.isMember()) { return UIUtils.alert.info("INFO.NOT_NEED_MEMBERSHIP"); } - // Select uid (or reuse it) - return ((keepSelf && !!$scope.formData.blockUid) ? - $q.when($scope.formData.uid) : - $scope.showUidPopup()) - - // Ask user confirmation - .then(function(uid) { - return UIUtils.alert.confirm("CONFIRM.MEMBERSHIP") - .then(function(confirm) { - if (!confirm) throw 'CANCELLED'; - return uid; - }); - }) - - // Send self (identity) - if need - .then(function (uid) { - UIUtils.loading.show(); - - // If uid changed, or self blockUid not retrieve : do self() first - if (!$scope.formData.blockUid || uid != $scope.formData.uid) { - $scope.formData.blockUid = null; - $scope.formData.uid = uid; - - return csWallet.self(uid, false/*do NOT load membership here*/); - } - }) + var uid = angular.isDefined($scope.formData.blockUid) && $scope.formData.uid || undefined; - // Send membership - .then($scope.doMembershipIn) - .catch(function(err) { - if (err == 'CANCELLED') return; - if (!csWallet.data.uid) { - UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')(err); - } - else { - UIUtils.onError('ERROR.SEND_MEMBERSHIP_IN_FAILED')(err); - } - }); + // Approve the license + return Modals.showJoinMember({ + uid : uid, + blockUid: uid && $scope.formData.blockUid, + pubkey: $scope.formData.pubkey + }) + .catch(function(err) { + if (err === 'CANCELLED') return; + if (!wallet.data.uid) { + UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')(err); + } + else { + UIUtils.onError('ERROR.SEND_MEMBERSHIP_IN_FAILED')(err); + } + }); }; // Send membership OUT @@ -280,7 +300,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, } UIUtils.loading.show(); - return csWallet.membership.out() + return wallet.membership.out() .then(function() { UIUtils.loading.hide(); UIUtils.toast.show('INFO.MEMBERSHIP_OUT_SENT'); @@ -292,9 +312,9 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.doUpdate = function(silent) { console.debug('[wallet] Refreshing data...'); return (silent ? - csWallet.refreshData() : + wallet.refreshData() : UIUtils.loading.show() - .then(csWallet.refreshData) + .then(wallet.refreshData) .then(UIUtils.loading.hide) ) .then($scope.updateView) @@ -306,20 +326,26 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, */ $scope.renewMembership = function(confirm) { - if (!$scope.formData.isMember && !$scope.formData.requirements.wasMember) { + // Make sure user is (or was) a member + if (!wallet.isMember() && !$scope.formData.requirements.wasMember) { return UIUtils.alert.error("ERROR.ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION"); } + + // If renew is not need, ask confirmation if (!confirm && !$scope.formData.requirements.needRenew) { return $translate("CONFIRM.NOT_NEED_RENEW_MEMBERSHIP", {membershipExpiresIn: $scope.formData.requirements.membershipExpiresIn}) .then(function(message) { return UIUtils.alert.confirm(message); }) .then(function(confirm) { - if (confirm) $scope.renewMembership(true); // loop with confirm + if (confirm) { + // loop with confirm + return $scope.renewMembership(true); + } }); } - return csWallet.auth({minData: true}) // Ask user to auth, before confirmation - fix #508 + return wallet.auth({minData: true}) // Ask user to auth, before confirmation - fix #508 .then(function() { UIUtils.loading.hide(); return UIUtils.alert.confirm("CONFIRM.RENEW_MEMBERSHIP"); @@ -331,7 +357,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, } }) .catch(function(err){ - if (err == 'CANCELLED') return; + if (err === 'CANCELLED') return; UIUtils.loading.hide(); UIUtils.alert.error(err); }); @@ -345,7 +371,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, if (!$scope.formData.uid) return; return $q.all([ - csWallet.auth(), + wallet.auth(), $translate('CONFIRM.FIX_IDENTITY', {uid: $scope.formData.uid}) ]) .then(function(res) { @@ -358,11 +384,11 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.formData.blockUid = null; // Reset membership data $scope.formData.sigDate = null; - return csWallet.self($scope.formData.uid); + return wallet.self($scope.formData.uid); }) .then($scope.doMembershipIn) .catch(function(err){ - if (err == 'CANCELLED') return; + if (err === 'CANCELLED') return; UIUtils.loading.hide(); UIUtils.alert.error(err); }); @@ -374,11 +400,13 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.fixMembership = function() { if (!$scope.formData.uid) return; - if (csWallet.isMember()) { + if (wallet.isMember()) { return UIUtils.alert.info("INFO.NOT_NEED_MEMBERSHIP"); } - return csWallet.auth() + $scope.hideActionsPopover(); + + return wallet.auth({silent: true}) .then(function() { UIUtils.alert.confirm("CONFIRM.FIX_MEMBERSHIP"); }) @@ -389,11 +417,11 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.formData.blockUid = null; // Reset membership data $scope.formData.sigDate = null; - return csWallet.self($scope.formData.uid, false/*do NOT load membership here*/); + return wallet.self($scope.formData.uid, false/*do NOT load membership here*/); }) .then($scope.doMembershipIn) .catch(function(err){ - if (err == 'CANCELLED') return; + if (err === 'CANCELLED') return; UIUtils.loading.hide(); UIUtils.alert.error(err); }); @@ -404,37 +432,27 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, * @param fix */ $scope.doQuickFix = function(event) { - if (event == 'renew') { + if (event === 'renew') { $scope.renewMembership(); } - else if (event == 'membership') { + else if (event === 'membership') { $scope.membershipIn(true/*keep self*/); } - else if (event == 'fixMembership') { - $scope.fixMembership(); + else if (event === 'fixMembership') { + $scope.fixMembership(false); } - else if (event == 'fixIdentity') { + else if (event === 'fixIdentity') { $scope.fixIdentity(); } }; - /* -- popup / UI -- */ + /* -- UI actions -- */ - // Transfer - $scope.showTransferModal = function() { - var hasCredit = (!!$scope.formData.balance && $scope.formData.balance > 0); - if (!hasCredit) { - UIUtils.alert.info('INFO.NOT_ENOUGH_CREDIT'); - return; + var inheritedLogout = $scope.logout; + $scope.logout = function(options) { + if ($scope.isDefaultWallet) { + return inheritedLogout(options); } - Modals.showTransfer() - .then(function(done){ - if (done) { - UIUtils.toast.show('INFO.TRANSFER_SENT'); - $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance - $scope.motion.show({selector: '.item-pending'}); - } - }); }; $scope.startWalletTour = function() { @@ -452,8 +470,8 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.qrcodeId, { text: $scope.formData.pubkey, - width: 200, - height: 200, + width: 180, + height: 180, correctLevel: QRCode.CorrectLevel.L }); UIUtils.motion.toggleOn({selector: '#'+$scope.qrcodeId}, timeout || 1100); @@ -465,7 +483,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, } }; - $scope.hideQRCode = function(id) { + $scope.hideQRCode = function() { if ($scope.qrcode) { $scope.qrcode.clear(); UIUtils.motion.toggleOff({selector: '#'+$scope.qrcodeId}); @@ -474,71 +492,66 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.showCertifications = function() { // Warn: do not use a simple link here (a ng-click is mandatory for help tour) - $state.go(UIUtils.screen.isSmall() ? 'app.wallet_cert' : 'app.wallet_cert_lg', { - pubkey: $scope.formData.pubkey, - uid: $scope.formData.name || $scope.formData.uid, - type: 'received' - }); + if ($scope.isDefaultWallet) { + $state.go(UIUtils.screen.isSmall() ? 'app.wallet_cert' : 'app.wallet_cert_lg', { + type: 'received' + }); + } + else { + $state.go(UIUtils.screen.isSmall() ? 'app.wallet_cert_by_id' : 'app.wallet_cert_by_id_lg', { + id: $scope.walletId, + type: 'received' + }); + } }; $scope.showGivenCertifications = function() { // Warn: do not use a simple link here (a ng-click is mandatory for help tour) + if ($scope.isDefaultWallet) { $state.go(UIUtils.screen.isSmall() ? 'app.wallet_cert' : 'app.wallet_cert_lg', { - pubkey: $scope.formData.pubkey, - uid: $scope.formData.name || $scope.formData.uid, type: 'given' - }); - }; - - $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('templates/wallet/popover_actions.html', { - scope: $scope - }).then(function(popover) { - $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); }); } else { - $scope.actionsPopover.show(event); + $state.go(UIUtils.screen.isSmall() ? 'app.wallet_cert_by_id' : 'app.wallet_cert_by_id_lg', { + id: $scope.walletId, + type: 'given' + }); } }; - $scope.hideActionsPopover = function() { - if ($scope.actionsPopover) { - $scope.actionsPopover.hide(); - } + $scope.showTxHistory = function() { + $state.go($scope.isDefaultWallet ? 'app.view_wallet_tx' : 'app.view_wallet_tx_by_id', { + id: $scope.walletId + }); }; - $scope.showSharePopover = function(event) { - $scope.hideActionsPopover(); + $scope.showLicenseModal = function() { + return ModalUtils.show('templates/currency/modal_license.html','CurrencyLicenseModalCtrl'); + }; - var title = $scope.formData.name || $scope.formData.uid || $scope.formData.pubkey; - // Use shareBasePath (fix #530) or rootPath (fix #390) - var url = (csConfig.shareBaseUrl || $rootScope.rootPath) + $state.href('app.wot_identity', {pubkey: $scope.formData.pubkey, uid: $scope.formData.name || $scope.formData.uid}); + /* -- modals -- */ - // Override default position, is small screen - fix #545 - if (UIUtils.screen.isSmall()) { - event = angular.element(document.querySelector('#wallet-share-anchor')) || event; + // Transfer + $scope.showTransferModal = function() { + var hasCredit = (!!$scope.formData.balance && $scope.formData.balance > 0); + if (!hasCredit && !csWallet.children.count()) { + UIUtils.alert.info('INFO.NOT_ENOUGH_CREDIT'); + return; } - - UIUtils.popover.share(event, { - bindings: { - url: url, - titleKey: 'WOT.VIEW.POPOVER_SHARE_TITLE', - titleValues: {title: title}, - postMessage: title - } - }); + return Modals.showTransfer({wallet: wallet.id}) + .then(function(done){ + if (done) { + UIUtils.toast.show('INFO.TRANSFER_SENT'); + $scope.$broadcast('$$rebind::balance'); // force rebind balance + $scope.motion.show({selector: '.item-pending'}); + } + }); }; $scope.showSecurityModal = function(){ $scope.hideActionsPopover(); - return Modals.showAccountSecurity() + return Modals.showAccountSecurity({wallet: wallet}) .then(function(res) { if (!res) return; @@ -563,7 +576,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.loading = true; // Set self (= uid + blockUid) - return csWallet.setSelf(idty.uid, idty.blockUid) + return wallet.setSelf(idty.uid, idty.blockUid) .then(function() { $scope.loading=false; $scope.updateView(); @@ -572,51 +585,185 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, }); }; + $scope.showSelectWalletModal = function() { + if (!csWallet.children.count()) return; + + return Modals.showSelectWallet({ + parameters: { + showDefault: true, + showBalance: false, + excludedWalletId: $scope.walletId + } + }) + .then(function(newWallet) { + if (!newWallet || wallet && newWallet.id === wallet.id) return; + $scope.removeListeners(); + $scope.loading = true; + wallet = newWallet; + console.debug("[transfer] Using wallet {" + wallet.id + "}"); + $scope.formData = {}; + return $scope.load(); + }); + }; + + /* -- popovers -- */ + + $scope.showActionsPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'templates/wallet/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } + }); + }; + + $scope.hideActionsPopover = function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + $scope.actionsPopover = null; + } + }; + + $scope.showSharePopover = function(event) { + $scope.hideActionsPopover(); + + var title = $scope.formData.name || $scope.formData.uid || $scope.formData.pubkey; + // Use shareBasePath (fix #530) or rootPath (fix #390) + var url = (csConfig.shareBaseUrl || $rootScope.rootPath) + $state.href('app.wot_identity', {pubkey: $scope.formData.pubkey, uid: $scope.formData.uid}); + + // Override default position, is small screen - fix #545 + if (UIUtils.screen.isSmall()) { + event = angular.element(document.querySelector('#wallet-share-anchor')) || event; + } + + UIUtils.popover.share(event, { + bindings: { + url: url, + titleKey: 'WOT.VIEW.POPOVER_SHARE_TITLE', + titleValues: {title: title}, + postMessage: title + } + }); + }; + + $scope.showSelectWalletPopover = function(event) { + + return csPopovers.showSelectWallet(event, { + parameters: { + excludedWalletId: $scope.walletId + }}) + .then(function(newWallet) { + if (!newWallet || newWallet.id === $scope.walletId) return; // nothing changed + if (newWallet.isDefault()) { + return $state.go('app.view_wallet'); + } + return $state.go('app.view_wallet_by_id', {id: newWallet.id}); + }); + }; + + // remove '?refresh' from the location URI + $scope.cleanLocationHref = function(state) { + if (state && state.stateParams && state.stateParams.refresh) { + $timeout(function() { + var stateParams = angular.copy(state.stateParams); + delete stateParams.refresh; + delete stateParams.id; + $location.search(stateParams).replace(); + }, 300); + } + }; } function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, - UIUtils, Modals, BMA, csSettings, csWallet, csTx) { + UIUtils, Modals, csPopovers, BMA, csHttp, csSettings, csCurrency, csWallet, csTx) { 'ngInject'; $scope.loading = true; $scope.settings = csSettings.data; + $scope.listeners = []; - $scope.$on('$ionicView.enter', function(e, state) { + var wallet; + + $scope.enter = function(e, state) { $scope.loading = $scope.loading || (state.stateParams && state.stateParams.refresh); + $scope.enableSelectWallet = csWallet.children.count() > 0; if ($scope.loading) { - $scope.loadWallet() - .then(function (res) { - $scope.formData = res; - $scope.loading = false; // very important, to avoid TX to be display before wallet.currentUd is loaded - $scope.updateView(); - $scope.showFab('fab-transfer'); - $scope.showHelpTip(); - UIUtils.loading.hide(); // loading could have be open (e.g. new account) - - // remove the stateParams - if (state.stateParams && state.stateParams.refresh) { - $location.search({}).replace(); - } - }) - .catch(function (err) { - if (err == 'CANCELLED') { - $scope.showHome(); - } - }); + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + $scope.walletId = wallet.id; + + $scope.cleanLocationHref(state); + + return $scope.load(); } else { + $scope.addListeners(); // Make sure to display new pending (e.g. sending using another screen button) $timeout($scope.updateView, 300); } - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); + + $scope.leave = function() { + $scope.removeListeners(); + }; + $scope.$on('$ionicView.leave', $scope.leave); + + $scope.load = function() { + if (!wallet) return; + + var hasMinData = wallet.isDataLoaded({minData: true}); + var options = { + requirements: !hasMinData, // load requirements (=minData) once + minData: !hasMinData, + sources: true, + tx: { + enable: true + } + }; + + return wallet.login(options) + .then(function(walletData) { + $scope.formData = walletData; + $scope.loading = false; // very important, to avoid TX to be display before wallet.currentUd is loaded + $scope.updateView(); + $scope.showFab('fab-transfer'); + if (wallet.isDefault()) $scope.showHelpTip(); + $scope.addListeners(); + UIUtils.loading.hide(); // loading could have be open (e.g. during login phase) + }) + .catch(function(err){ + if (err === 'CANCELLED') { + $scope.showHome(); + } + }); + }; + // remove '?refresh' from the location URI + $scope.cleanLocationHref = function(state) { + if (state && state.stateParams && state.stateParams.refresh) { + $timeout(function() { + var stateParams = angular.copy(state.stateParams); + delete stateParams.refresh; + delete stateParams.id; + $location.search(stateParams).replace(); + }, 300); + } + }; // Update view $scope.updateView = function() { if (!$scope.formData || $scope.loading) return; - $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind + $scope.$broadcast('$$rebind::balance'); // force rebind balance + $scope.$broadcast('$$rebind::rebind'); // force rebind $scope.motion.show({selector: '.view-wallet-tx .item', ink: false}); }; @@ -630,10 +777,23 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, // Updating wallet data $scope.doUpdate = function(silent) { console.debug('[wallet] TX history reloading...'); + var fromTime = $scope.formData && $scope.formData.tx && $scope.formData.tx.fromTime || undefined; + var options = { + sources: true, + tx: { + enable: true, + fromTime: fromTime + }, + api: false + }; return (silent ? - csWallet.refreshData() : + // If silent: just refresh + wallet.refreshData(options) : + // If not silent: show/hide loading indicator UIUtils.loading.show() - .then(csWallet.refreshData) + .then(function() { + return wallet.refreshData(options); + }) .then(UIUtils.loading.hide) ) .then($scope.updateView) @@ -642,38 +802,78 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, /* -- add listeners -- */ - csWallet.api.data.on.balanceChanged($scope, $scope.updateView); - $scope.$watch('settings.useRelative', $scope.updateView); - $scope.$watch('settings.showUDHistory', function() { - // Reload if show UD changed - if (!$scope.formData || $scope.loading) return; - $scope.doUpdate(); - }, true); + $scope.addListeners = function() { + $scope.listeners = [ + // Reload if wallet balanced changed + wallet.api.data.on.balanceChanged($scope, $scope.updateView), + // Reload if useRelative changed + $scope.$watch('settings.useRelative', $scope.updateView, true), + // Reload if showUDHistory changed + $scope.$watch('settings.showUDHistory', function(newVal, oldVal) { + if (!$scope.formData || $scope.loading || (newVal === oldVal)) return; + $scope.doUpdate(); + }, true) + ]; + + // Listening new block (if auto refresh enable) + if ($scope.settings.walletHistoryAutoRefresh) { + $scope.listeners.push( + csCurrency.api.data.on.newBlock($scope, function(block) { + if ($scope.loading) return; + console.debug("[wallet] Received new block. Will reload history."); + $timeout(function() { + $scope.doUpdate(true); + }, 500/*waiting for block propagation*/); + }) + ); + } + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; /* -- popup / UI -- */ // Transfer $scope.showTransferModal = function() { var hasCredit = (!!$scope.formData.balance && $scope.formData.balance > 0); - if (!hasCredit) { + if (!hasCredit && !csWallet.children.count()) { UIUtils.alert.info('INFO.NOT_ENOUGH_CREDIT'); return; } - return Modals.showTransfer(); + return Modals.showTransfer({wallet: wallet.id}) + .then(function(done){ + if (done) { + UIUtils.toast.show('INFO.TRANSFER_SENT'); + $scope.$broadcast('$$rebind::balance'); // force rebind balance + $scope.motion.show({selector: '.item-pending'}); + } + }); }; $scope.showHelpTip = function(index, isTour) { // TODO }; + $scope.showTxErrors = function(event) { + if (wallet.isDefault()) { + return $scope.goState('app.view_wallet_tx_errors'); + } + return $scope.goState('app.view_wallet_tx_errors_by_id', {id: wallet.id}); + }; + $scope.showMoreTx = function(fromTime) { fromTime = fromTime || ($scope.formData.tx.fromTime - csSettings.data.walletHistoryTimeSecond) || - (Math.trunc(new Date().getTime() / 1000) - 2 * csSettings.data.walletHistoryTimeSecond); + (csHttp.date.now() - 2 * csSettings.data.walletHistoryTimeSecond); UIUtils.loading.show(); - return csWallet.refreshData({tx: {enable: true,fromTime: fromTime}}) + return wallet.refreshData({tx: {enable: true, fromTime: fromTime}}) .then(function() { $scope.updateView(); UIUtils.loading.hide(); @@ -691,6 +891,27 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, }); }; + $scope.showSelectWalletModal = function() { + if (!csWallet.children.count()) return; + + return Modals.showSelectWallet({ + parameters: { + showDefault: true, + showBalance: false, + excludedWalletId: $scope.walletId + } + }) + .then(function(newWallet) { + if (!newWallet || wallet && newWallet.id === wallet.id) return; + $scope.removeListeners(); + $scope.loading = true; + wallet = newWallet; + console.debug("[transfer] Using wallet {" + wallet.id + "}"); + $scope.formData = {}; + return $scope.load(); + }); + }; + /* -- popover -- */ var paddingIndent = 10; @@ -742,21 +963,14 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, }, []); // Open popover - if (!$scope.lockedOutputsPopover) { - $ionicPopover.fromTemplateUrl('templates/wallet/tx_locked_outputs_popover.html', { - scope: $scope - }).then(function(popover) { - $scope.lockedOutputsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.lockedOutputsPopover.remove(); - }); - $scope.lockedOutputsPopover.show(event); - }); - } - else { - $scope.lockedOutputsPopover.show(event); - } + UIUtils.popover.show(event, { + templateUrl: 'templates/wallet/tx_locked_outputs_popover.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } + }); }; $scope.hideLockedOutputsPopover = function() { @@ -765,41 +979,79 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, if ($scope.popoverData) { delete $scope.popoverData.unlockConditions; } + $scope.lockedOutputsPopover = null; } }; + $scope.showSelectWalletPopover = function(event) { + return csPopovers.showSelectWallet(event, { + scope: $scope + }) + .then(function(newWallet) { + if (!newWallet || newWallet.id === wallet.id) return; + if (newWallet.isDefault()) { + return $scope.goState('app.view_wallet_tx'); + } + return $scope.goState('app.view_wallet_tx_by_id', {id: newWallet.id}); + }); + }; + $scope.goState = function(stateName, stateParams) { $scope.hideLockedOutputsPopover(); - $state.go(stateName, stateParams); + return $state.go(stateName, stateParams); }; } -function WalletTxErrorController($scope, UIUtils, csWallet) { +function WalletTxErrorController($scope, UIUtils, csSettings, csWallet) { 'ngInject'; + var wallet; + $scope.settings = csSettings.data; + $scope.loading = true; $scope.formData = {}; - $scope.$on('$ionicView.enter', function(e) { - $scope.loadWallet() + $scope.$on('$ionicView.enter', function(e, state) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + return $scope.load(); + }); + + $scope.load = function() { + if (!wallet) return; + + return wallet.login() .then(function(walletData) { $scope.formData = walletData; + $scope.loading = false; $scope.doMotion(); - $scope.showFab('fab-redo-transfer'); + //$scope.showFab('fab-redo-transfer'); UIUtils.loading.hide(); }); - }); + }; // Updating wallet data $scope.doUpdate = function(silent) { + $scope.loading = true; return (silent ? - csWallet.refreshData() : + wallet.refreshData() : UIUtils.loading.show() .then(csWallet.refreshData) .then(UIUtils.loading.hide) ) - .then($scope.doMotion) - .catch(UIUtils.onError('ERROR.REFRESH_WALLET_DATA')); + .then(function() { + $scope.doMotion(); + $scope.loading = false; + }) + .catch(function(err) { + UIUtils.onError('ERROR.REFRESH_WALLET_DATA')(err); + $scope.loading = false; + }); }; $scope.filterReceivedTx = function(tx){ @@ -810,9 +1062,19 @@ function WalletTxErrorController($scope, UIUtils, csWallet) { return tx.amount && tx.amount < 0; }; + $scope.hasReceivedTx = function(){ + return $scope.formData.tx && _($scope.formData.tx.errors || []).find($scope.filterReceivedTx) && true; + }; + + $scope.hasSentTx = function(){ + return $scope.formData.tx && _($scope.formData.tx.errors || []).find($scope.filterSentTx) && true; + }; + } -function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ +function WalletSecurityModalController($scope, UIUtils, csWallet, $translate, parameters){ + + var wallet = parameters && parameters.wallet || csWallet; $scope.slides = { slider: null, @@ -828,11 +1090,13 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ $scope.recover = {}; $scope.isValidFile = false; - $scope.isLogin = csWallet.isLogin(); - $scope.hasSelf = csWallet.hasSelf(); - $scope.needSelf = $scope.isLogin && csWallet.data.requirements.needSelf; - $scope.needMembership = $scope.isLogin && csWallet.data.requirements.needMembership; - $scope.option = $scope.isLogin ? 'saveID' : 'recoverID'; + + $scope.login = wallet.isLogin(); + $scope.hasSelf = wallet.hasSelf(); + $scope.needSelf = $scope.login && wallet.data.requirements.needSelf; + $scope.canRevoke = $scope.login && $scope.hasSelf && !wallet.data.requirements.revoked; + $scope.needMembership = $scope.login && wallet.data.requirements.needMembership; + $scope.option = $scope.login ? 'saveID' : 'recoverID'; $scope.formData = { addQuestion: '', @@ -1015,7 +1279,7 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ $scope.recover.answer += element.answer; }); - return csWallet.recoverId($scope.recover) + return wallet.recoverId($scope.recover) .then(function (recover){ if (angular.isDefined(recover)) { $scope.recover = recover; @@ -1041,7 +1305,7 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ $scope.downloadSaveIDFile = function(){ // Force user re-auth var loginData; - return csWallet.auth({ + return wallet.auth({ forceAuth: true, expectedPubkey: $scope.pubkey, silent: true, @@ -1050,7 +1314,7 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ } }) .catch(function(err) { - if (err && err == 'CANCELLED') return; + if (err && err === 'CANCELLED') return; UIUtils.alert.error('ERROR.SALT_OR_PASSWORD_NOT_CONFIRMED', 'ERROR.LOGIN_FAILED'); return; }) @@ -1072,9 +1336,9 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ record.answer += question.answer; }); - return csWallet.getCryptedId(record) + return wallet.getCryptedId(record) .then(function(record){ - csWallet.downloadSaveId(record); + wallet.downloadSaveId(record); $scope.closeModal(); }); }) @@ -1102,11 +1366,11 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ */ $scope.downloadRevokeFile = function () { // Force re-authentication - return csWallet.auth({forceAuth: true}) + return wallet.auth({forceAuth: true}) // Download file .then(function() { - return csWallet.downloadRevocation(); + return wallet.downloadRevocation(); }) .then(function() { @@ -1114,7 +1378,7 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ }) .catch(function(err){ - if (err && err == 'CANCELLED') return; + if (err && err === 'CANCELLED') return; UIUtils.onError('ERROR.DOWNLOAD_REVOCATION_FAILED')(err); }) ; @@ -1130,14 +1394,14 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ } // Make sure user re-auth - return csWallet.auth({forceAuth: true}) + return wallet.auth({forceAuth: true}) .then(function(confirm) { UIUtils.loading.hide(); if (!confirm) return; return $scope.revokeIdentity(); }) .catch(function (err) { - if (err == 'CANCELLED') return; + if (err === 'CANCELLED') return; UIUtils.onError('ERROR.REVOCATION_FAILED')(err); }); }; @@ -1170,10 +1434,10 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ return UIUtils.loading.show() .then(function () { if (!$scope.revocation){ - return csWallet.revoke(); + return wallet.revoke(); } else { - return csWallet.revokeWithFile($scope.revocation); + return wallet.revokeWithFile($scope.revocation); } }) .then(function () { @@ -1204,11 +1468,11 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ */ $scope.downloadKeyFile = function (format) { // Force re-authentication - return csWallet.auth({forceAuth: true}) + return wallet.auth({forceAuth: true}) // Download file .then(function() { - return csWallet.downloadKeyFile(format); + return wallet.downloadKeyFile(format); }) .then(function() { @@ -1217,12 +1481,12 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ }) .catch(function(err){ - if (err && err == 'CANCELLED') return; + if (err && err === 'CANCELLED') { + UIUtils.loading.hide(); + return; + } UIUtils.onError('ERROR.DOWNLOAD_KEYFILE_FAILED')(err); }) ; }; - } - - diff --git a/assets/www/dist/dist_js/app/controllers/wallets-controllers.js b/assets/www/dist/dist_js/app/controllers/wallets-controllers.js new file mode 100644 index 0000000000000000000000000000000000000000..4fb2c06838ed9d97b73902f2d5ba11ae7ba5e3e2 --- /dev/null +++ b/assets/www/dist/dist_js/app/controllers/wallets-controllers.js @@ -0,0 +1,838 @@ + +WalletListAbstractController.$inject = ['$scope', '$q', '$timeout', 'UIUtils', 'filterTranslations', 'csSettings', 'csCurrency', 'csWallet']; +WalletListViewController.$inject = ['$scope', '$controller', '$state', '$timeout', '$q', '$translate', '$ionicPopover', '$ionicPopup', 'ModalUtils', 'UIUtils', 'Modals', 'csCurrency', 'csSettings', 'csWallet']; +WalletSelectModalController.$inject = ['$scope', '$controller', 'parameters']; +WalletListImportModalController.$inject = ['$scope', '$timeout', 'BMA', 'csWallet']; +WalletSelectPopoverController.$inject = ['$scope', '$controller', 'UIUtils', 'parameters'];angular.module('cesium.wallets.controllers', ['cesium.services', 'cesium.currency.controllers']) + + .config(['$stateProvider', function($stateProvider) { + 'ngInject'; + $stateProvider + + .state('app.view_wallets', { + url: "/wallets", + views: { + 'menuContent': { + templateUrl: "templates/wallet/list/view_wallets.html", + controller: 'WalletListViewCtrl' + } + }, + data: { + login: true + } + }) + + .state('app.view_wallet_by_id', { + url: "/wallets/:id?refresh", + views: { + 'menuContent': { + templateUrl: "templates/wallet/view_wallet.html", + controller: 'WalletCtrl' + } + }, + data: { + login: true, + silentLocationChange: true + } + }) + + .state('app.view_wallet_tx_by_id', { + url: "/history/wallets/:id?refresh", + views: { + 'menuContent': { + templateUrl: "templates/wallet/view_wallet_tx.html", + controller: 'WalletTxCtrl' + } + }, + data: { + login: true, + silentLocationChange: true + } + }) + + .state('app.view_wallet_tx_errors_by_id', { + url: "/history/wallets/:id/errors", + views: { + 'menuContent': { + templateUrl: "templates/wallet/view_wallet_tx_error.html", + controller: 'WalletTxErrorCtrl' + } + }, + data: { + login: true + } + }) + ; + }]) + .controller('WalletListAbstractCtrl', WalletListAbstractController) + + .controller('WalletListViewCtrl', WalletListViewController) + + .controller('WalletSelectModalCtrl', WalletSelectModalController) + + .controller('WalletListImportModalCtrl', WalletListImportModalController) + + .controller('WalletSelectPopoverCtrl', WalletSelectPopoverController) +; + + +function WalletListAbstractController($scope, $q, $timeout, UIUtils, filterTranslations, csSettings, csCurrency, csWallet) { + 'ngInject'; + + $scope.loading = true; + $scope.wallets = null; + $scope.formData = { + useRelative: csSettings.data.useRelative, + showDefault: true, + showBalance: false, + balance: undefined, + updatingWalletId: undefined, + stopped: false, + minData: true + }; + $scope.motion = null; // no animation + + $scope.setParameters = function(parameters) { + parameters = parameters || {}; + + $scope.formData.useRelative = angular.isDefined(parameters.useRelative) ? parameters.useRelative : $scope.formData.useRelative; + $scope.formData.showBalance = angular.isDefined(parameters.showBalance) ? parameters.showBalance : $scope.formData.showBalance; + $scope.formData.minData = angular.isDefined(parameters.minData) ? parameters.minData : $scope.formData.minData; + $scope.formData.excludedWalletId = parameters.excludedWalletId; + $scope.formData.showDefault = (angular.isDefined(parameters.showDefault) ? parameters.showDefault : $scope.formData.showDefault) && + ($scope.formData.excludedWalletId !== 'default'); + + }; + + $scope.load = function(options) { + + options = options || {}; + $scope.loading = (options.silent !== false); + $scope.formData.balance = undefined; + $scope.formData.updatingWalletId = undefined; + $scope.formData.stopped = false; + + // Load currency, and filter translations (need by 'formatAmount' filter) + var jobs = []; + + jobs.push(csCurrency.name() + .then(function(currency) { + $scope.currency = currency; + return filterTranslations.ready(); + })); + + // Get children wallets + $scope.defaultWallet = $scope.formData.showDefault ? csWallet : undefined; + if (!$scope.wallets) { + jobs.push( + csWallet.children.all() + .then(function(children) { + $scope.wallets=children; + UIUtils.loading.hide(); + }) + ); + } + + // Prepare load options + var walletLoadOptions = { + silent: true, + minData: $scope.formData.minData, + sources: $scope.formData.showBalance, + tx: { + enable: false + }, + api: true + }; + var hasLoadError = false; + var loadCounter = 0; + var now = Date.now(); + var balance = 0; + return (jobs.length ? $q.all(jobs) : $q.when()) + // Load wallet data (apply a timeout between each wallet) + .then(function() { + var wallets = $scope.formData.showDefault ? [csWallet].concat($scope.wallets) : $scope.wallets; + if (!wallets.length) return; + console.debug("[wallets] Loading {0} wallets...".format(wallets.length)); + return wallets.reduce(function(res, wallet) { + var skip= !options.refresh && wallet.isDataLoaded(walletLoadOptions); + if (skip) { + console.debug("[wallets] Wallet #{0} already loaded. Skipping".format(wallet.id)); + return res.then(function(){ + balance += wallet.data.balance; + $scope.updateWalletView(wallet.id); + }); + } + loadCounter++; + return res.then(function() { + if ($scope.formData.stopped) return; // skip if stopped + // Loading next wallet, after waiting some time + $scope.formData.updatingWalletId = wallet.id; + var loadPromise; + if (options.refresh && wallet.data.loaded) { + var refreshOptions = angular.merge({ + // Refresh requirements if member account + requirements: (!wallet.data.requirements.loaded || wallet.data.requirements.isMember || wallet.data.requirements.wasMember || wallet.data.requirements.pendingMembership) + }, walletLoadOptions); + loadPromise = wallet.refreshData(refreshOptions); + } + else { + loadPromise = wallet.loadData(walletLoadOptions); + } + + loadPromise.then(function(walletData) { + balance += walletData.balance; + $scope.updateWalletView(wallet.id); + }) + .catch(function(err) { + console.error("[wallets] Error while loading data of wallet #{0}".format(wallet.id), err); + hasLoadError = true; + }); + return loadPromise; + }); + }, $q.when()); + }) + .then(function() { + if (hasLoadError) { + return UIUtils.alert.error('ERROR.LOAD_WALLET_LIST_FAILED') + .then(function() { + $scope.resetData(); + $scope.cancel(); + }); + } + // Stop + if ($scope.formData.stopped) return; + if (loadCounter) { + console.debug("[wallets] Loaded data of {0} wallet(s) in {1}ms".format(loadCounter, (Date.now() - now))); + } + $scope.formData.balance = balance; + $scope.formData.updatingWalletId = undefined; + $scope.loading = false; + UIUtils.loading.hide(); + $scope.updateView(); + }) + .catch(function(err) { + $scope.resetData(); + if (err && err === 'CANCELLED') { + $scope.cancel(); + throw err; + } + return UIUtils.onError('ERROR.LOAD_WALLET_LIST_FAILED')(err); + }); + }; + + $scope.filterFn = function(parameters) { + return function(wallet) { + return !parameters || wallet.id !== parameters.excludedWalletId; + }; + }; + + + // Clean controller data + $scope.resetData = function() { + console.debug("[wallets] Cleaning wallet list"); + $scope.wallets = null; + $scope.loading = true; + $scope.entered = false; + $scope.formData.balance = undefined; + $scope.formData.updatingWalletId = undefined; + }; + + $scope.updateView = function(walletId) { + if (!$scope.wallets || !$scope.wallets.length) return; + + var selectorSuffix = walletId && (' #wallet-' + walletId) || ''; + + if ($scope.motion) { + $scope.motion.show({selector: '.list .item.item-wallet' + selectorSuffix, ink: true}); + } + else { + UIUtils.ink({selector: '.list .item.item-wallet' + selectorSuffix}); + } + }; + + $scope.updateWalletView = function(walletId) { + if ($scope.motion) { + $scope.motion.show({selector: '.list #wallet-' + walletId, ink: true}); + } + else { + UIUtils.ink({selector: '.list #wallet-' + walletId}); + } + }; + + $scope.doUpdate = function(silent) { + if ($scope.loading || !$scope.wallets || !$scope.wallets.length || $scope.formData.updatingWalletId) return $q.when(); + + $scope.selectPrevented = true; + $timeout(function() { + $scope.selectPrevented = false; + }, 1000); + + return $scope.load({silent: silent, refresh: true}) + .then(function() { + $scope.loading = false; + $scope.selectPrevented = false; + if (silent) { + $scope.$broadcast('$$rebind::rebind'); // force rebind + } + $scope.updateView(); + }); + }; + + $scope.addNewWallet = function(wallet) { + + if (!wallet) return $q.reject("Missing 'wallet' argument"); + + // Make sure auth on the main wallet + if (csSettings.data.useLocalStorageEncryption && !csWallet.isAuth()) { + return csWallet.auth({minData: true}) + .then(function() { + return $scope.addNewWallet(wallet); // loop + }) + .catch(function(err) { + if (err === 'CANCELLED') { + return UIUtils.loading.hide(); + } + UIUtils.onError('ERROR.ADD_SECONDARY_WALLET_FAILED')(err); + }); + } + + // Call API extension on child wallet + return csWallet.api.data.raisePromise.load(wallet.data) + // continue, when plugins extension failed (just log in console) + .catch(console.error) + .then(function() { + $scope.addListenersOnWallet(wallet); + csWallet.children.add(wallet); + }); + }; + + /* -- modals -- */ + + $scope.showNewWalletModal = function() { + + var wallet = csWallet.children.instance(); + return wallet.login({ + showNewAccountLink: false, + title: 'ACCOUNT.WALLET_LIST.BTN_NEW', + okText: 'COMMON.BTN_ADD', + // Load data options : + minData: true, + sources: true, + api: false, + success: UIUtils.loading.show, + method: 'PUBKEY' // Default method - fix #767 + }) + .then(function(walletData) { + if (!walletData) { // User cancelled + UIUtils.loading.hide(100); + return; + } + + // Avoid to add main wallet again + if (csWallet.isUserPubkey(walletData.pubkey)) { + UIUtils.loading.hide(); + UIUtils.alert.error('ERROR.COULD_NOT_ADD_MAIN_WALLET'); + return; + } + + // Avoid to add exists wallet again + if (csWallet.children.hasPubkey(walletData.pubkey)) { + UIUtils.loading.hide(); + UIUtils.alert.error('ERROR.COULD_NOT_ADD_EXISTING_WALLET'); + return; + } + + console.debug("[wallet] Adding secondary wallet {"+walletData.pubkey.substring(0,8)+"}"); + + // Add the child wallet + return $scope.addNewWallet(wallet) + .then(function() { + UIUtils.loading.hide(); + $scope.updateView(); + }); + }) + .catch(function(err) { + if (err === 'CANCELLED') { + // Silent + UIUtils.loading.hide(); + } + }); + }; + + /* -- Method to override by subclasses-- */ + + $scope.addListenersOnWallet = function(wallet) { + // Can be override by subclass + }; + + $scope.cancel = function() { + console.warn("cancel() must be implement by subclass"); + }; + + $scope.select = function(event, wallet) { + console.warn("select() must be implement by subclass"); + }; +} + +function WalletSelectModalController($scope, $controller, parameters) { + 'ngInject'; + + // Initialize the super class and extend it. + angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope})); + + $scope.$on('modal.shown', function() { + $scope.setParameters(parameters); + $scope.load(); + }); + + $scope.cancel = function() { + $scope.closeModal(); + }; + + $scope.select = function(event, wallet) { + if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; + $scope.closeModal(wallet); + }; + + // Default actions + if (parameters) { + $scope.setParameters(parameters); + } +} + +function WalletListViewController($scope, $controller, $state, $timeout, $q, $translate, $ionicPopover, $ionicPopup, + ModalUtils, UIUtils, Modals, csCurrency, csSettings, csWallet){ + 'ngInject'; + + $scope.settings = csSettings.data; + $scope.listeners = []; + + // Initialize the super class and extend it. + angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope, parameters: {}})); + + // Override defaults + $scope.formData.name = undefined; + $scope.motion = UIUtils.motion.default; + $scope.entered = false; + + $scope.enter = function(e, state) { + // First enter + if (!$scope.entered) { + $scope.entered = true; + $scope.setParameters({ + showDefault: true, + showBalance: true, + minData: false + }); + + return $scope.load() + .then(function() { + UIUtils.loading.hide(); + if (!$scope.wallets) return; // user cancel, or error + $scope.addListeners(); + $scope.showFab('fab-add-wallet'); + }); + } + // If already enter + else { + // Re-add listeners + $scope.addListeners(); + if ($scope.formData.stopped) { + $scope.loading = false; + $scope.formData.stopped = false; + $scope.formData.updatingWalletId = undefined; + $scope.updateView(); + } + } + }; + $scope.$on('$ionicView.enter', $scope.enter); + + $scope.leave = function() { + $scope.formData.stopped = true; + $scope.formData.updatingWalletId = undefined; + $scope.loading = false; + $scope.removeListeners(); + }; + $scope.$on('$ionicView.leave', $scope.leave); + + $scope.cancel = function() { + $scope.showHome(); + }; + + $scope.select = function(event, wallet) { + if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; + if (wallet.isDefault()) { + $state.go('app.view_wallet'); + } + else { + $state.go('app.view_wallet_by_id', {id: wallet.id}); + } + event.preventDefault(); + }; + + $scope.editWallet = function(event, wallet) { + + event.preventDefault(); + + return $scope.showEditPopup(wallet) + .then(function(newName) { + if (!newName) return; + + // Auth (if encryption is need) + return (csSettings.data.useLocalStorageEncryption ? csWallet.auth({minData: true}) : $q.when()) + + // Save changes + .then(function() { + wallet.data.localName = newName; + csWallet.storeData(); + UIUtils.loading.hide(); + $scope.updateView(); + }) + .catch(function(err) { + if (err === 'CANCELLED') { + return UIUtils.loading.hide(); + } + UIUtils.onError('ERROR.SAVE_WALLET_LIST_FAILED')(err); + }); + }); + }; + + $scope.downloadAsFile = function() { + if (!$scope.wallets) return; // user cancel + return csWallet.children.downloadFile(); + }; + + + + $scope.selectAndRemoveWallet = function() { + $scope.hideActionsPopover(); + return Modals.showSelectWallet({ + wallets: $scope.wallets, + showDefault: false + }) + .then(function(wallet) { + if (!wallet || !wallet.id) return; + + // Auth (if encryption is need)) + return (csSettings.data.useLocalStorageEncryption ? csWallet.auth({minData: true}) : $q.when()) + + // Remove the wallet + .then(function() { + csWallet.children.remove(wallet.id); + UIUtils.loading.hide(); + $scope.updateView(); + }) + .catch(function(err) { + if (err === 'CANCELLED') { + return UIUtils.loading.hide(); + } + UIUtils.onError('ERROR.ADD_SECONDARY_WALLET_FAILED')(err); + }); + }); + }; + + $scope.showImportFileModal = function() { + $scope.hideActionsPopover(); + + var loginAndAddWallet = function(authData) { + console.debug("[wallet] Adding secondary wallet {"+authData.pubkey.substring(0,8)+"}"); + var wallet = csWallet.children.instance(); + return wallet.login({ + authData: authData, + // Load data options : + minData: true, + sources: true, + api: false, + success: UIUtils.loading.show + }) + .then(function(walletData) { + walletData.localName = authData.localName; + return $scope.addNewWallet(wallet); + }); + }; + + return ModalUtils.show( + 'templates/wallet/list/modal_import_file.html', + 'WalletListImportModalCtrl' + ) + .then(function(items){ + if (!items || !items.length) return; // User cancel + + UIUtils.loading.show(); + + // Auth (if encryption is need) + return (csSettings.data.useLocalStorageEncryption ? csWallet.auth({minData: true}) : $q.when()) + .then(function() { + // Add wallet one after one + return items.reduce(function(promise, authData){ + return promise.then(function() { + return loginAndAddWallet(authData); + }); + }, $q.when()); + }) + .then(function() { + UIUtils.loading.hide(); + $scope.updateView(); + }) + .catch(function(err) { + if (err === 'CANCELLED') { + return UIUtils.loading.hide(); + } + UIUtils.onError('ERROR.ADD_SECONDARY_WALLET_FAILED')(err); + }); + }); + }; + + /* -- popups -- */ + + $scope.setEditForm = function(editForm) { + $scope.editForm = editForm; + }; + + $scope.showEditPopup = function(wallet) { + return $q(function(resolve, reject) { + $translate(['ACCOUNT.WALLET_LIST.EDIT_POPOVER.TITLE', 'ACCOUNT.WALLET_LIST.EDIT_POPOVER.HELP', 'COMMON.BTN_OK', 'COMMON.BTN_CANCEL']) + .then(function (translations) { + $scope.formData.name = wallet.data.localName || wallet.data.name || wallet.data.uid || wallet.data.pubkey.substring(0, 8); + + // Choose UID popup + $ionicPopup.show({ + templateUrl: 'templates/wallet/list/popup_edit_name.html', + title: translations['ACCOUNT.WALLET_LIST.EDIT_POPOVER.TITLE'], + subTitle: translations['ACCOUNT.WALLET_LIST.EDIT_POPOVER.HELP'], + scope: $scope, + buttons: [ + { text: translations['COMMON.BTN_CANCEL'] }, + { + text: translations['COMMON.BTN_OK'], + type: 'button-positive', + onTap: function(e) { + $scope.editForm.$submitted=true; + if(!$scope.editForm.$valid || !$scope.formData.name) { + //don't allow the user to close unless he enters a name + e.preventDefault(); + } else { + return $scope.formData.name; + } + } + } + ] + }) + .then(function(name) { + if (!name) { // user cancel + delete $scope.formData.name; + UIUtils.loading.hide(); + return; + } + resolve(name); + }); + }); + }); + }; + + /* -- popovers -- */ + + $scope.showActionsPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'templates/wallet/list/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } + }); + }; + + $scope.hideActionsPopover = function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + $scope.actionsPopover = null; + } + }; + + /* -- listeners -- */ + + // Clean controller data when logout + $scope.onWalletLogout = function() { + $scope.resetData(); + $scope.removeListeners(); + }; + + $scope.addListeners = function() { + + // First remove lod listeners, if any + $scope.removeListeners(); + + $scope.listeners = [ + csWallet.api.data.on.logout($scope, $scope.onWalletLogout) + ]; + + // Auto-update on new block + if (csSettings.data.walletHistoryAutoRefresh) { + $scope.listeners.push( + csCurrency.api.data.on.newBlock($scope, function (block) { + if ($scope.loading) return; + console.debug("[wallet-list] Received new block. Will reload list."); + $timeout(function () { + $scope.doUpdate(true); + }, 300/*waiting for node cache propagation*/); + })); + } + + // Listen auth events on each wallet + _.forEach($scope.wallets||[], $scope.addListenersOnWallet); + }; + + $scope.addListenersOnWallet = function(wallet) { + if (!wallet) return; + $scope.listeners.push(wallet.api.data.on.unauth($scope, $scope.updateView)); + $scope.listeners.push(wallet.api.data.on.auth($scope, function (data, deferred) { + $timeout($scope.updateView); + return deferred ? deferred.resolve() : $q.when(); + })); + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; + + var inheritedUpdateView = $scope.updateView; + $scope.updateView = function() { + inheritedUpdateView(); + $scope.$broadcast('$$rebind::rebind'); // force rebind + }; + + var inheritedUpdateWalletView = $scope.updateWalletView; + $scope.updateWalletView = function(walletId) { + inheritedUpdateWalletView(walletId); + $scope.$broadcast('$$rebind::rebind'); // force rebind + }; + + // Detect changes in settings useRelative + $scope.$watch('settings.useRelative', function(newVal, oldVal) { + if (!$scope.formData || $scope.loading || (newVal === oldVal)) return; + $scope.formData.useRelative = csSettings.data.useRelative; + $scope.updateView(); + }, true); +} + + +function WalletSelectPopoverController($scope, $controller, UIUtils, parameters) { + 'ngInject'; + + // Initialize the super class and extend it. + angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope})); + + // Disable list motion + $scope.motion = null; + + $scope.$on('popover.shown', function() { + if ($scope.loading) { + $scope.setParameters(parameters); + $scope.load(); + } + }); + + $scope.updateView = function() { + if (!$scope.wallets || !$scope.wallets.length) return; + + UIUtils.ink({selector: '.popover-wallets .list .item'}); + $scope.$broadcast('$$rebind::rebind'); // force rebind + }; + + $scope.select = function(event, wallet) { + if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; // no selection + $scope.closePopover(wallet); + }; + +} + +function WalletListImportModalController($scope, $timeout, BMA, csWallet) { + 'ngInject'; + + $scope.hasContent = false; + $scope.content = null; + $scope.fileData = ''; + $scope.isValidFile = false; + $scope.validatingFile = false; + + $scope.importFromFile = function(file) { + $scope.validatingFile = true; + + $scope.hasContent = angular.isDefined(file) && file !== ''; + $scope.fileData = file.fileData ? file.fileData : ''; + var isValidFile = $scope.fileData !== '' && + ($scope.fileData.type == 'text/csv' || $scope.fileData.type == 'text/plain' || 'application/vnd.ms-excel' /*fix issue #810*/); + + // Bad file type: invalid file + if (!isValidFile) { + console.error("[wallet] Import failed. Invalid file type: " + $scope.fileData.type); + $scope.isValidFile = false; + $scope.validatingFile = false; + return; + } + + // Parse file + console.debug("[wallet] Parsing file to import..."); + var rows = file.fileContent.split('\n'); + $scope.content = rows.reduce(function(res, row) { + // Skip empty row + if (!row || !row.trim().length) return res; + + // Split + var cols = row.split('\t', 3) || undefined; + + // Invalid column count: mark file as invalid + if (cols && cols.length != 3) { + console.debug("[wallet] Import: skip invalid row: " + row); + isValidFile = false; + return res; + } + + var item = { + pubkey: cols[0], + uid: cols[1], + localName: cols[2] + }; + + // Check pubkey validity + if (!BMA.regexp.PUBKEY.test(item.pubkey)) { + console.debug("[wallet] Invalid pubkey, found in this row: ", row); + isValidFile = false; + return res; + } + + // Ignore if same as current wallet + if (csWallet.isUserPubkey(item.pubkey)) { + console.debug("[wallet] Pubkey equals to main wallet. Skip this row: ", row); + return res; + } + + // Ignore if already in children wallet + if (csWallet.children.hasPubkey(item.pubkey)) { + console.debug("[wallet] Pubkey already in wallet list. Skip this row", row); + return res; + } + + // OK: add it to result + return res.concat(item); + }, []); + + $scope.isValidFile = isValidFile; + + $timeout(function() { + $scope.validatingFile = false; + }, 250); // need to have a loading effect + }; + + $scope.removeFile = function() { + $scope.hasContent = false; + $scope.content = null; + $scope.fileData = ''; + $scope.isValidFile = false; + $scope.validatingFile = false; + }; +} diff --git a/assets/www/dist/dist_js/app/controllers/wot-controllers.js b/assets/www/dist/dist_js/app/controllers/wot-controllers.js index c046e8881f142e83d47f4972884dde2c589093f4..dff1498fe8865862d13d540c004a8833aa335093 100644 --- a/assets/www/dist/dist_js/app/controllers/wot-controllers.js +++ b/assets/www/dist/dist_js/app/controllers/wot-controllers.js @@ -1,8 +1,8 @@ WotLookupController.$inject = ['$scope', '$state', '$q', '$timeout', '$focus', '$location', '$ionicPopover', '$ionicHistory', 'UIUtils', 'csConfig', 'csCurrency', 'csSettings', 'Device', 'BMA', 'csWallet', 'csWot']; - WotLookupModalController.$inject = ['$scope', '$controller', '$focus', 'parameters']; -WotIdentityAbstractController.$inject = ['$scope', '$rootScope', '$state', '$translate', '$ionicHistory', 'UIUtils', 'Modals', 'csConfig', 'csCurrency', 'csWot', 'csWallet']; -WotIdentityViewController.$inject = ['$scope', '$rootScope', '$controller', '$timeout', 'UIUtils', 'csWallet']; + WotLookupModalController.$inject = ['$scope', '$controller', '$focus', 'csWallet', 'parameters']; +WotIdentityAbstractController.$inject = ['$scope', '$rootScope', '$state', '$translate', '$ionicHistory', '$q', 'UIUtils', 'Modals', 'csConfig', 'csSettings', 'csCurrency', 'csWot', 'csWallet']; +WotIdentityViewController.$inject = ['$scope', '$rootScope', '$controller', '$timeout', '$state', 'UIUtils', 'Modals', 'csWallet']; WotIdentityTxViewController.$inject = ['$scope', '$timeout', '$q', 'BMA', 'csSettings', 'csWot', 'csTx', 'UIUtils']; WotCertificationsViewController.$inject = ['$scope', '$rootScope', '$controller', 'csSettings', 'csWallet', 'UIUtils']; WotSelectPubkeyIdentityModalController.$inject = ['$scope', '$q', 'csWot', 'parameters'];angular.module('cesium.wot.controllers', ['cesium.services']) @@ -50,7 +50,7 @@ WotSelectPubkeyIdentityModalController.$inject = ['$scope', '$q', 'csWot', 'para }) .state('app.wot_identity', { - url: "/wot/:pubkey/:uid?action", + url: "/wot/:pubkey/:uid?action&block", views: { 'menuContent': { templateUrl: "templates/wot/view_identity.html", @@ -71,19 +71,6 @@ WotSelectPubkeyIdentityModalController.$inject = ['$scope', '$q', 'csWot', 'para .state('app.wot_identity_tx_uid', { url: "/wot/tx/:pubkey/:uid?action", - views: { - 'menuContent': { - templateUrl: "templates/wot/view_identity_tx.html", - controller: 'WotIdentityTxViewCtrl' - }, - data: { - large: 'app.wot_identity_tx_uid_lg' - } - } - }) - - .state('app.wot_identity_tx_uid_lg', { - url: "/wot/tx/lg/:pubkey/:uid?action", views: { 'menuContent': { templateUrl: "templates/wot/view_identity_tx.html", @@ -93,7 +80,7 @@ WotSelectPubkeyIdentityModalController.$inject = ['$scope', '$q', 'csWot', 'para }) .state('app.wot_cert', { - url: "/wot/:pubkey/:uid/:type", + url: "/wot/:pubkey/:uid/:type?block", views: { 'menuContent': { templateUrl: "templates/wot/view_certifications.html", @@ -106,7 +93,7 @@ WotSelectPubkeyIdentityModalController.$inject = ['$scope', '$q', 'csWot', 'para }) .state('app.wot_cert_lg', { - url: "/wot/cert/lg/:pubkey/:uid", + url: "/wot/cert/lg/:pubkey/:uid?block", views: { 'menuContent': { templateUrl: "templates/wot/view_certifications.html", @@ -117,7 +104,7 @@ WotSelectPubkeyIdentityModalController.$inject = ['$scope', '$q', 'csWot', 'para // wallet cert .state('app.wallet_cert', { - url: "/wallet/cert/:type", + url: "/account/cert/:type", views: { 'menuContent': { templateUrl: "templates/wot/view_certifications.html", @@ -130,7 +117,31 @@ WotSelectPubkeyIdentityModalController.$inject = ['$scope', '$q', 'csWot', 'para }) .state('app.wallet_cert_lg', { - url: "/wallet/cert/lg", + url: "/account/cert/lg", + views: { + 'menuContent': { + templateUrl: "templates/wot/view_certifications.html", + controller: 'WotCertificationsViewCtrl' + } + } + }) + + // wallet cert + .state('app.wallet_cert_by_id', { + url: "/wallets/:id/cert/:type", + views: { + 'menuContent': { + templateUrl: "templates/wot/view_certifications.html", + controller: 'WotCertificationsViewCtrl' + } + }, + data: { + large: 'app.wallet_cert_lg_by_id' + } + }) + + .state('app.wallet_cert_lg_by_id', { + url: "/wallets/:id/cert/lg", views: { 'menuContent': { templateUrl: "templates/wot/view_certifications.html", @@ -172,21 +183,23 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i $scope.entered = false; $scope.wotSearchTextId = 'wotSearchText'; $scope.enableFilter = true; + $scope.enableWallets = false; $scope.allowMultiple = false; $scope.selection = []; $scope.showResultLabel = true; $scope.parameters = {}; // override in the modal controller - $scope.$on('$ionicView.enter', function(e, state) { + $scope.enter = function(e, state) { if (!$scope.entered) { - if (state.stateParams && state.stateParams.q) { // Query parameter - $scope.search.text = state.stateParams.q; + var params = angular.merge({}, $scope.parameters, state && state.stateParams); + if (params && params.q) { // Query parameter + $scope.search.text = params.q; $timeout(function() { $scope.doSearch(); }, 100); } - else if (state.stateParams && state.stateParams.hash) { // hash tag parameter - $scope.search.text = '#' + state.stateParams.hash; + else if (params && params.hash) { // hash tag parameter + $scope.search.text = '#' + params.hash; $timeout(function() { $scope.doSearch(); }, 100); @@ -194,16 +207,19 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i else { $timeout(function() { // Init phase - if (csCurrency.data.initPhase && !state.stateParams.type) { + if (csCurrency.data.initPhase && !params.type) { $scope.doGetPending(0, undefined, true/*skipLocationUpdate*/); } // get new comers - else if (state.stateParams.type == 'newcomers' || (!csConfig.initPhase && !state.stateParams.type)) { + else if (params.type == 'newcomers' || (!csConfig.initPhase && !params.type)) { $scope.doGetNewcomers(0, undefined, true/*skipLocationUpdate*/); } - else if (state.stateParams.type == 'pending') { + else if (params.type == 'pending') { $scope.doGetPending(0, undefined, true/*skipLocationUpdate*/); } + else if (params.type == 'wallets') { + $scope.doGetWallets(0, undefined, true/*skipLocationUpdate*/); + } }, 100); } @@ -220,7 +236,8 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i $scope.motion.show({selector: '.lookupForm .list .item', ink: true}); } } - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.resetWotSearch = function() { $scope.search = { @@ -296,7 +313,7 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i return csWot.newcomers(offset, size) .then(function(res){ - if ($scope.search.type != 'newcomers') return false; // could have change + if ($scope.search.type !== 'newcomers') return false; // could have change $scope.doDisplayResult(res && res.hits, offset, size, res && res.total); return true; }) @@ -344,6 +361,42 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i }); }; + $scope.doGetWallets = function(offset, size, skipLocationUpdate) { + offset = offset || 0; + size = size || defaultSearchLimit; + if (size < defaultSearchLimit) size = defaultSearchLimit; + + $scope.hideActionsPopover(); + $scope.search.loading = (offset === 0); + $scope.search.type = 'wallets'; + + // Update location href + if (!offset && !skipLocationUpdate) { + $scope.updateLocationHref(); + } + + return csWallet.children.all() + .then(function(children) { + if (!children || $scope.search.type != 'wallets') return false; // could have change + var res = [csWallet].concat(children).reduce(function(res, wallet, index) { + var item = { + id: index, + pubkey: wallet.data.pubkey, + uid: wallet.data.uid, + name: wallet.data.localName || wallet.data.name, + avatar: wallet.data.avatar + }; + return res.concat(item); + }, []); + + $scope.doDisplayResult(res, offset, size, res.length); + $scope.search.hasMore = false; + return true; + }); + + + }; + $scope.showMore = function() { var offset = $scope.search.results ? $scope.search.results.length : 0; @@ -516,32 +569,25 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i /* -- show/hide popup -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('templates/wot/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/wot/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; - } -function WotLookupModalController($scope, $controller, $focus, parameters){ +function WotLookupModalController($scope, $controller, $focus, csWallet, parameters){ 'ngInject'; // Initialize the super class and extend it. @@ -550,6 +596,7 @@ function WotLookupModalController($scope, $controller, $focus, parameters){ parameters = parameters || {}; $scope.search.loading = false; $scope.enableFilter = angular.isDefined(parameters.enableFilter) ? parameters.enableFilter : false; + $scope.enableWallets = angular.isDefined(parameters.enableWallets) ? (csWallet.isLogin() && csWallet.children.count() && parameters.enableWallets) : false; $scope.allowMultiple = angular.isDefined(parameters.allowMultiple) ? parameters.allowMultiple : false; $scope.parameters = parameters; $scope.showResultLabel = false; @@ -560,6 +607,17 @@ function WotLookupModalController($scope, $controller, $focus, parameters){ $scope.selection = parameters.selection; } + var superEnter = $scope.enter; + $scope.enter = function(e) { + if ($scope.parameters && $scope.parameters.q) { + $scope.search.text=$scope.parameters.q; + if ($scope.parameters.q.trim().length > 2) { + superEnter(e); // call enter, that launch the search + } + } + }; + $scope.$on('modal.shown', $scope.enter); + $scope.cancel = function(){ $scope.closeModal(); }; @@ -567,7 +625,8 @@ function WotLookupModalController($scope, $controller, $focus, parameters){ $scope.select = function(identity){ $scope.closeModal({ pubkey: identity.pubkey, - uid: identity.uid + uid: identity.uid, + name: identity.name && identity.name.replace(/<\/?em>/ig, '') }); }; @@ -597,8 +656,8 @@ function WotLookupModalController($scope, $controller, $focus, parameters){ * @param csWallet * @constructor */ -function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ionicHistory, - UIUtils, Modals, csConfig, csCurrency, csWot, csWallet) { +function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ionicHistory, $q, + UIUtils, Modals, csConfig, csSettings, csCurrency, csWot, csWallet) { 'ngInject'; $scope.formData = { @@ -612,17 +671,19 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ viewData.enableBack = UIUtils.screen.isSmall() ? true : viewData.enableBack; }); - $scope.load = function(pubkey, withCache, uid) { - return csWot.load(pubkey, withCache, uid) + $scope.load = function(pubkey, uid, options) { + return csWot.load(pubkey, uid, options) .then(function(identity){ if (!identity) return UIUtils.onError('ERROR.IDENTITY_NOT_FOUND')().then($scope.showHome); $scope.formData = identity; + var isLogin = csWallet.isLogin(); $scope.revoked = identity.requirements && (identity.requirements.revoked || identity.requirements.pendingRevocation); - $scope.canCertify = identity.hasSelf && (!csWallet.isLogin() || (!csWallet.isUserPubkey(pubkey))) && !$scope.revoked; - $scope.canSelectAndCertify = identity.hasSelf && csWallet.isUserPubkey(pubkey); - $scope.alreadyCertified = !$scope.canCertify || !csWallet.isLogin() ? false : - (!!_.findWhere(identity.received_cert, { pubkey: csWallet.data.pubkey, valid: true }) || - !!_.findWhere(identity.received_cert_pending, { pubkey: csWallet.data.pubkey, valid: true })); + $scope.canCertify = identity.hasSelf && !$scope.revoked && (!isLogin || !csWallet.isUserPubkey(pubkey) || csWallet.children.count() > 0); + $scope.canSelectAndCertify = identity.hasSelf && (csWallet.isUserPubkey(pubkey) || csWallet.children.hasPubkey(pubkey)); + var cert = isLogin && _.find((identity.received_cert||[]).concat(identity.received_cert_pending||[]), function (cert) { + return cert.pubkey === csWallet.data.pubkey && cert.valid && cert.expiresIn > csSettings.data.timeWarningExpire; + }); + $scope.alreadyCertified = (!$scope.canCertify || !isLogin || csWallet.children.count() > 0) ? false : !!cert; $scope.disableCertifyButton = $scope.alreadyCertified || $scope.revoked; $scope.loading = false; }) @@ -638,201 +699,217 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ $scope.loading = true; UIUtils.loading.show(); } - return $scope.load($scope.formData.pubkey, false/*no cache*/, $scope.formData.uid) + var options = { + cache: false, // No cache + blockUid: $scope.formData.blockUid || undefined + }; + return $scope.load($scope.formData.pubkey, $scope.formData.uid, options) .then(UIUtils.loading.hide); }; // Certify the current identity $scope.certify = function() { - // Need user auth - fix #513 - return csWallet.auth({minData: true}) - .then(function(walletData) { - UIUtils.loading.hide(); + // Select wallet, if many + return (csWallet.children.count() ? Modals.showSelectWallet({displayBalance: false}) : $q.when(csWallet)) + .then(function(wallet) { + if (!wallet) return; // user cancelled - if (!csCurrency.data.initPhase && !walletData.isMember) { - UIUtils.alert.error(walletData.requirements.needSelf ? - 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY' : 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF'); - return; - } + // Need user auth - fix #513 + return wallet.auth({minData: true}) + .then(function(walletData) { + UIUtils.loading.hide(); - if (!csCurrency.data.initPhase && !$scope.formData.hasSelf) { - UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); - return; - } + if (!csCurrency.data.initPhase && !walletData.isMember) { + UIUtils.alert.error(walletData.requirements.needSelf ? + 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY' : 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF'); + return; + } - // Check identity not expired - if ($scope.formData.requirements.expired) { - UIUtils.alert.error('ERROR.IDENTITY_EXPIRED'); - return; - } + if (!csCurrency.data.initPhase && !$scope.formData.hasSelf) { + UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); + return; + } - // Check not already certified - var previousCert = _.findWhere($scope.formData.received_cert, { pubkey: walletData.pubkey, valid: true}); - if (previousCert) { - $translate('ERROR.IDENTITY_ALREADY_CERTIFY', previousCert) - .then(function(message) { - UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); - }); - return; - } + // Check identity not expired + if ($scope.formData.requirements.expired) { + UIUtils.alert.error('ERROR.IDENTITY_EXPIRED'); + return; + } - // Check not pending certification - previousCert = _.findWhere($scope.formData.received_cert_pending, { pubkey: walletData.pubkey, valid: true}); - if (previousCert) { - $translate('ERROR.IDENTITY_ALREADY_CERTIFY_PENDING', previousCert) - .then(function(message) { - UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + // Check not already certified + var previousCert = _.find($scope.formData.received_cert, function(cert) { + return cert.pubkey === wallet.data.pubkey && cert.valid && cert.expiresIn > csSettings.data.timeWarningExpire; }); - return; - } + if (previousCert) { + $translate('ERROR.IDENTITY_ALREADY_CERTIFY', previousCert) + .then(function(message) { + UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + }); + return; + } - UIUtils.alert.confirm('CONFIRM.CERTIFY_RULES', 'CONFIRM.POPUP_SECURITY_WARNING_TITLE', { - cssClass: 'warning', - okText: 'WOT.BTN_YES_CERTIFY', - okType: 'button-assertive' - }) - .then(function(confirm){ - if (!confirm) { + // Check no pending certification + previousCert = _.findWhere($scope.formData.received_cert_pending, { pubkey: wallet.data.pubkey, valid: true}); + if (previousCert) { + $translate('ERROR.IDENTITY_ALREADY_CERTIFY_PENDING', previousCert) + .then(function(message) { + UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + }); return; } - UIUtils.loading.show(); - csWallet.certify($scope.formData.uid, - $scope.formData.pubkey, - $scope.formData.timestamp, - $scope.formData.sig, - $scope.formData.isMember, - $scope.formData.wasMember) - .then(function(cert) { - UIUtils.loading.hide(); - if (cert) { - $scope.prepareNewCert(cert); - $scope.alreadyCertified = true; - UIUtils.alert.info('INFO.CERTIFICATION_DONE'); - $scope.formData.received_cert_pending.unshift(cert); - $scope.formData.requirements.pendingCertificationCount++; - $scope.doMotion(); + + UIUtils.alert.confirm('CONFIRM.CERTIFY_RULES', 'CONFIRM.POPUP_SECURITY_WARNING_TITLE', { + cssClass: 'warning', + okText: 'WOT.BTN_YES_CERTIFY', + okType: 'button-assertive' + }) + .then(function(confirm){ + if (!confirm) { + return; } - }) - .catch(UIUtils.onError('ERROR.SEND_CERTIFICATION_FAILED')); + UIUtils.loading.show(); + wallet.certify($scope.formData.uid, + $scope.formData.pubkey, + $scope.formData.blockUid || ($scope.formData.requirements && $scope.formData.requirements.meta && $scope.formData.requirements.meta.timestamp), + $scope.formData.requirements && $scope.formData.requirements.meta && $scope.formData.requirements.meta.sig, + $scope.formData.isMember, + $scope.formData.wasMember) + .then(function(cert) { + UIUtils.loading.hide(); + if (cert) { + $scope.prepareNewCert(wallet, cert); + $scope.alreadyCertified = true; + UIUtils.toast.show('INFO.CERTIFICATION_DONE'); + $scope.formData.received_cert_pending.unshift(cert); + $scope.formData.requirements.pendingCertificationCount++; + $scope.doMotion(); + } + }) + .catch(UIUtils.onError('ERROR.SEND_CERTIFICATION_FAILED')); + }); + }) + .catch(function(err) { + if (err === 'CANCELLED') return; + UIUtils.onError('ERROR.LOGIN_FAILED')(err); }); - }) - .catch(function(err) { - if (err == 'CANCELLED') return; - UIUtils.onError('ERROR.LOGIN_FAILED')(err); }); }; // Select an identity and certify $scope.selectAndCertify = function() { - // Need user auth - fix #513 - return csWallet.auth({minData: true}) - - .then(function(walletData) { - if (!csCurrency.data.initPhase && !walletData.isMember) { - UIUtils.alert.error(walletData.requirements.needSelf || walletData.requirements.needMembership ? - 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY' : 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF'); - return; - } - UIUtils.loading.hide(); - // Open Wot lookup modal - return Modals.showWotLookup(); - }) - .then(function(idty) { - if (!idty || !idty.pubkey) { - return; // cancelled - } - if (!idty.uid) { // not a member - UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); - return; - } + // Select wallet, if many + return (csWallet.children.count() ? Modals.showSelectWallet({displayBalance: false}) : $q.when(csWallet)) + .then(function(wallet) { + // Need user auth - fix #513 + return wallet.auth({minData: true}) + .then(function (walletData) { + if (!csCurrency.data.initPhase && !walletData.isMember) { + UIUtils.alert.error(walletData.requirements.needSelf || walletData.requirements.needMembership ? + 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY' : 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF'); + return; + } + UIUtils.loading.hide(); + // Open Wot lookup modal + return Modals.showWotLookup(); + }) + .then(function (idty) { + if (!idty || !idty.pubkey) { + return; // cancelled + } + if (!idty.uid) { // not a member + UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); + return; + } - UIUtils.loading.show(); + UIUtils.loading.show(); - // load selected identity - return csWot.load(idty.pubkey, false /*no cache*/); - }) + var options = {cache: false, blockUid: idty.blockUid}; - .then(function(identity) { - if (!identity) return; // cancelled - UIUtils.loading.hide(); - if (!identity || !identity.hasSelf) { - UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); - return; - } + // load selected identity + return csWot.load(idty.pubkey, idty.uid, options); + }) - // Check identity not expired - if (identity.requirements.expired) { - UIUtils.alert.error('ERROR.IDENTITY_EXPIRED'); - return; - } + .then(function (identity) { + if (!identity) return; // cancelled + UIUtils.loading.hide(); + if (!identity || !identity.hasSelf) { + UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); + return; + } - // Check not already certified - var previousCert = _.findWhere(identity.received_cert, { pubkey: csWallet.data.pubkey, valid: true}); - if (previousCert) { - $translate('ERROR.IDENTITY_ALREADY_CERTIFY', previousCert) - .then(function(message) { - UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); - }); - return; - } + // Check identity not expired + if (identity.requirements.expired) { + UIUtils.alert.error('ERROR.IDENTITY_EXPIRED'); + return; + } - // Check not pending certification - previousCert = _.findWhere(identity.received_cert_pending, { pubkey: csWallet.data.pubkey, valid: true}); - if (previousCert) { - $translate('ERROR.IDENTITY_ALREADY_CERTIFY_PENDING', previousCert) - .then(function(message) { - UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); - }); - return; - } + // Check not already certified + var previousCert = _.findWhere(identity.received_cert, {pubkey: wallet.data.pubkey, valid: true}); + if (previousCert) { + $translate('ERROR.IDENTITY_ALREADY_CERTIFY', previousCert) + .then(function (message) { + UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + }); + return; + } - // Ask confirmation - $translate('CONFIRM.CERTIFY_RULES_TITLE_UID', {uid: identity.uid}) - .then(function(confirmTitle) { - return UIUtils.alert.confirm('CONFIRM.CERTIFY_RULES', confirmTitle); - }) - .then(function(confirm){ - if (!confirm) { + // Check not pending certification + previousCert = _.findWhere(identity.received_cert_pending, {pubkey: wallet.data.pubkey, valid: true}); + if (previousCert) { + $translate('ERROR.IDENTITY_ALREADY_CERTIFY_PENDING', previousCert) + .then(function (message) { + UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + }); return; } - UIUtils.loading.show(); - // Send certification - csWallet.certify(identity.uid, - identity.pubkey, - identity.timestamp, - identity.sig, - identity.isMember, - identity.wasMember) - .then(function(cert) { - UIUtils.loading.hide(); - if (!cert) return; - return csWot.extendAll([cert], 'pubkey') - .then(function(){ - UIUtils.toast.show('INFO.CERTIFICATION_DONE'); - $scope.formData.given_cert_pending.unshift(cert); - $scope.doMotion(); - }); + // Ask confirmation + $translate('CONFIRM.CERTIFY_RULES_TITLE_UID', {uid: identity.uid}) + .then(function (confirmTitle) { + return UIUtils.alert.confirm('CONFIRM.CERTIFY_RULES', confirmTitle); }) - .catch(UIUtils.onError('ERROR.SEND_CERTIFICATION_FAILED')); + .then(function (confirm) { + if (!confirm) { + return; + } + UIUtils.loading.show(); + + // Send certification + wallet.certify(identity.uid, + identity.pubkey, + identity.blockUid || (identity.requirements && identity.requirements.meta && identity.requirements.meta.timestamp), + identity.requirements && identity.requirements.meta && identity.requirements.meta.sig, + identity.isMember, + identity.wasMember) + .then(function (cert) { + UIUtils.loading.hide(); + if (!cert) return; + return csWot.extendAll([cert], 'pubkey') + .then(function () { + UIUtils.toast.show('INFO.CERTIFICATION_DONE'); + $scope.formData.given_cert_pending.unshift(cert); + $scope.doMotion(); + }); + }) + .catch(UIUtils.onError('ERROR.SEND_CERTIFICATION_FAILED')); + }); + }) + .catch(function (err) { + if (err === 'CANCELLED') return; + UIUtils.onError('ERROR.LOAD_IDENTITY_FAILED')(err); }); - }) - .catch(function(err) { - if (err == 'CANCELLED') return; - UIUtils.onError('ERROR.LOAD_IDENTITY_FAILED')(err); }); - }; // Add wallet's data to a new cert - $scope.prepareNewCert = function(cert) { - cert.uid = csWallet.data.uid; - cert.pubkey = csWallet.data.pubkey; - cert.isMember = csWallet.data.isMember; - cert.avatar = csWallet.data.avatar; - cert.name = csWallet.data.name; + $scope.prepareNewCert = function(wallet, cert) { + cert.uid = wallet.data.uid; + cert.pubkey = wallet.data.pubkey; + cert.isMember = wallet.data.isMember; + cert.avatar = wallet.data.avatar; + cert.name = wallet.data.name; }; $scope.removeActionParamInLocationHref = function(state) { @@ -869,35 +946,41 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ /* -- open screens -- */ $scope.showCertifications = function() { + var block = $scope.formData.requirements && $scope.formData.requirements.alternatives && $scope.formData.blockUid || undefined; // Warn: do not use a simple link here (a ng-click is mandatory for help tour) if (UIUtils.screen.isSmall() ) { $state.go('app.wot_cert', { pubkey: $scope.formData.pubkey, uid: $scope.formData.uid, - type: 'received' + type: 'received', + block: block }); } else { $state.go('app.wot_cert_lg', { pubkey: $scope.formData.pubkey, - uid: $scope.formData.uid + uid: $scope.formData.uid, + block: block }); } }; $scope.showGivenCertifications = function() { + var block = $scope.formData.requirements && $scope.formData.requirements.alternatives && $scope.formData.blockUid || undefined; // Warn: do not use a simple link here (a ng-click is mandatory for help tour) if (UIUtils.screen.isSmall() ) { $state.go('app.wot_cert', { pubkey: $scope.formData.pubkey, uid: $scope.formData.uid, - type: 'given' + type: 'given', + block: block }); } else { $state.go('app.wot_cert_lg', { pubkey: $scope.formData.pubkey, - uid: $scope.formData.uid + uid: $scope.formData.uid, + block: block }); } }; @@ -924,15 +1007,15 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ /** * Identity view controller - should extend WotIdentityAbstractCtrl */ -function WotIdentityViewController($scope, $rootScope, $controller, $timeout, UIUtils, csWallet) { +function WotIdentityViewController($scope, $rootScope, $controller, $timeout, $state, UIUtils, Modals, csWallet) { 'ngInject'; // Initialize the super class and extend it. angular.extend(this, $controller('WotIdentityAbstractCtrl', {$scope: $scope})); $scope.motion = UIUtils.motion.fadeSlideInRight; + $scope.qrcodeId = 'qrcode-wot-' + $scope.$id; $scope.$on('$ionicView.enter', function(e, state) { - var onLoadSuccess = function() { $scope.doMotion(); if (state.stateParams && state.stateParams.action) { @@ -942,13 +1025,20 @@ function WotIdentityViewController($scope, $rootScope, $controller, $timeout, UI $scope.removeActionParamInLocationHref(state); } + + $scope.showQRCode(); + }; + var options = { + cache: true, + blockUid: state.stateParams && state.stateParams.block || undefined }; if (state.stateParams && state.stateParams.pubkey && state.stateParams.pubkey.trim().length > 0) { if ($scope.loading) { // load once - return $scope.load(state.stateParams.pubkey.trim(), true /*withCache*/, state.stateParams.uid) + + return $scope.load(state.stateParams.pubkey.trim(), state.stateParams.uid, options) .then(onLoadSuccess); } } @@ -957,16 +1047,7 @@ function WotIdentityViewController($scope, $rootScope, $controller, $timeout, UI state.stateParams.uid && state.stateParams.uid.trim().length > 0) { if ($scope.loading) { // load once - return $scope.load(null, true /*withCache*/, state.stateParams.uid) - .then(onLoadSuccess); - } - } - - // Load from wallet pubkey - else if (csWallet.isLogin()){ - - if ($scope.loading) { - return $scope.load(csWallet.data.pubkey, true /*withCache*/, csWallet.data.uid) + return $scope.load(null, state.stateParams.uid, options) .then(onLoadSuccess); } } @@ -988,6 +1069,57 @@ function WotIdentityViewController($scope, $rootScope, $controller, $timeout, UI if (($scope.canCertify && !$scope.alreadyCertified) || $rootScope.tour) { $scope.showFab('fab-certify-' + $scope.formData.uid); } + + $scope.$broadcast('$csExtension.motion'); + }; + + $scope.doQuickFix = function(event) { + if (event === 'showSelectIdentities') { + return $scope.showSelectIdentities(); + } + }; + + $scope.showSelectIdentities = function() { + if (!$scope.formData.requirements || !$scope.formData.requirements.alternatives) return; + + return Modals.showSelectPubkeyIdentity({ + identities: [$scope.formData.requirements].concat($scope.formData.requirements.alternatives) + }) + .then(function(res) { + if (!res || !res.pubkey) return; // Skip if cancelled + // open the identity + return $state.go('app.wot_identity', { + pubkey: res.pubkey, + uid: res.uid, + block: res.meta && res.meta.timestamp || res.blockUid + }); + }); + }; + + $scope.showQRCode = function(timeout) { + if (!$scope.qrcode) { + $scope.qrcode = new QRCode( + $scope.qrcodeId, + { + text: $scope.formData.pubkey, + width: 180, + height: 180, + correctLevel: QRCode.CorrectLevel.L + }); + UIUtils.motion.toggleOn({selector: '#'+$scope.qrcodeId}, timeout || 1100); + } + else { + $scope.qrcode.clear(); + $scope.qrcode.makeCode($scope.formData.pubkey); + UIUtils.motion.toggleOn({selector: '#'+$scope.qrcodeId}, timeout || 1100); + } + }; + + $scope.hideQRCode = function() { + if ($scope.qrcode) { + $scope.qrcode.clear(); + UIUtils.motion.toggleOff({selector: '#'+$scope.qrcodeId}); + } }; } @@ -1042,8 +1174,8 @@ function WotIdentityTxViewController($scope, $timeout, $q, BMA, csSettings, csWo // Update view $scope.updateView = function() { - $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind + $scope.$broadcast('$$rebind::balance'); // force rebind balance + $scope.$broadcast('$$rebind::rebind'); // force rebind $scope.motion.show(); }; @@ -1057,7 +1189,7 @@ function WotIdentityTxViewController($scope, $timeout, $q, BMA, csSettings, csWo fromTime = fromTime || ($scope.formData.tx.fromTime - csSettings.data.walletHistoryTimeSecond) || - (Math.trunc(new Date().getTime() / 1000) - 2 * csSettings.data.walletHistoryTimeSecond); + (moment().utc().unix() - 2 * csSettings.data.walletHistoryTimeSecond); UIUtils.loading.show(); return csTx.load($scope.pubkey, fromTime) @@ -1087,6 +1219,9 @@ function WotIdentityTxViewController($scope, $timeout, $q, BMA, csSettings, csWo */ function WotCertificationsViewController($scope, $rootScope, $controller, csSettings, csWallet, UIUtils) { 'ngInject'; + + var wallet; + // Initialize the super class and extend it. angular.extend(this, $controller('WotIdentityAbstractCtrl', {$scope: $scope})); @@ -1107,39 +1242,43 @@ function WotCertificationsViewController($scope, $rootScope, $controller, csSett $scope.motions.avatar.enable = false; } - if (state.stateParams && - state.stateParams.pubkey && - state.stateParams.pubkey.trim().length > 0) { + // First load + if ($scope.loading) { + var options = { + cache: true, + blockUid: state.stateParams && state.stateParams.block || undefined + }; - if ($scope.loading) { // load once - return $scope.load(state.stateParams.pubkey.trim(), true /*withCache*/, state.stateParams.uid) - .then(function() { + if (state.stateParams && + state.stateParams.pubkey && + state.stateParams.pubkey.trim().length > 0) { + + return $scope.load(state.stateParams.pubkey.trim(), state.stateParams.uid, options) + .then(function () { $scope.doMotion(); $scope.showHelpTip(); }); } - else { - $scope.doMotion(); - } - } - // Load from wallet pubkey - else if (csWallet.isLogin()){ - if ($scope.loading) { - return $scope.load(csWallet.data.pubkey, true /*withCache*/, csWallet.data.uid) - .then(function() { + else { + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + if (!wallet.isLogin()) { + return $scope.showHome(); + } + return $scope.load(wallet.data.pubkey, wallet.data.uid, options) + .then(function () { $scope.doMotion(); $scope.showHelpTip(); }); } - else { - $scope.doMotion(); - } } - // Redirect to home else { - $scope.showHome(); + $scope.doMotion(); } }); @@ -1149,7 +1288,11 @@ function WotCertificationsViewController($scope, $rootScope, $controller, csSett // Updating data $scope.doUpdate = function() { - return $scope.load($scope.formData.pubkey, false /*no cache*/, $scope.formData.uid) + var options = { + cache: false, // No cache + blockUid: $scope.formData.blockUid || undefined + }; + return $scope.load($scope.formData.pubkey, $scope.formData.uid, options) .then(function() { $scope.doMotion(); $scope.showHelpTip(); @@ -1157,6 +1300,7 @@ function WotCertificationsViewController($scope, $rootScope, $controller, csSett }; $scope.doMotion = function(skipItems) { + // Motions received certifications part $scope.doMotionReceivedCertifications(0, skipItems); @@ -1244,7 +1388,7 @@ function WotCertificationsViewController($scope, $rootScope, $controller, csSett /** - * Select identities from a pubkey (yusfull when many self on the same pubkey) + * Select identities from a pubkey (useful when many self on the same pubkey) * @param $scope * @param $q * @param csWot diff --git a/assets/www/dist/dist_js/app/directives.js b/assets/www/dist/dist_js/app/directives.js index 58479d33ce7dacf78f28fb59e267b5b5ecf4dbd8..34cbab3a5a43c27c15d7b0e9adb833d2cbb617f3 100644 --- a/assets/www/dist/dist_js/app/directives.js +++ b/assets/www/dist/dist_js/app/directives.js @@ -102,7 +102,11 @@ angular.module('cesium.directives', []) link: function(scope, element, attributes, ngModel) { if (ngModel) { ngModel.$validators.geoPoint = function(value) { - return ngModel.$isEmpty(value) || (angular.isDefined(value.lat) && angular.isDefined(value.lon)); + return ngModel.$isEmpty(value) || + // twice are defined + (angular.isDefined(value.lat) && angular.isDefined(value.lon)) || + // or twice are NOT defined (=empty object - can be useful to override data in ES node) + (angular.isUndefined(value.lat) && angular.isUndefined(value.lon)); }; } } @@ -110,7 +114,7 @@ angular.module('cesium.directives', []) }) // Add a copy-on-click directive - .directive('copyOnClick', ['$window', '$document', 'Device', 'UIUtils', function ($window, $document, Device, UIUtils) { + .directive('copyOnClick', ['$window', 'Device', 'UIUtils', function ($window, Device, UIUtils) { 'ngInject'; return { restrict: 'A', @@ -409,15 +413,17 @@ angular.module('cesium.directives', []) // Un-authenticate when window closed // see: https://stackoverflow.com/questions/28197316/javascript-or-angularjs-defer-browser-close-or-tab-close-between-refresh - .directive('windowExitUnauth', ['$window', 'csWallet', function($window, csWallet) { + .directive('windowExitUnauth', ['$window', 'csSettings', 'csWallet', function($window, csSettings, csWallet) { return { restrict: 'AE', link: function(element, attrs){ var myEvent = $window.attachEvent || $window.addEventListener, - chkevent = $window.attachEvent ? 'onunload' : 'unload'; /// make IE7, IE8 compatable + chkevent = $window.attachEvent ? 'onunload' : 'unload'; /// make IE7, IE8 compatible myEvent(chkevent, function (e) { // For >=IE7, Chrome, Firefox - return csWallet.unauth(); + if (csSettings.data && csSettings.data.keepAuthIdle != csSettings.constants.KEEP_AUTH_IDLE_SESSION) { + return csWallet.unauth(); + } }); } }; diff --git a/assets/www/dist/dist_js/app/entities/peer.js b/assets/www/dist/dist_js/app/entities/peer.js index 0800c571386f74ec4ddc493ec1d510c5be0a4489..6672ba834b6a773841df4ab1c56084b8e21b7f84 100644 --- a/assets/www/dist/dist_js/app/entities/peer.js +++ b/assets/www/dist/dist_js/app/entities/peer.js @@ -9,7 +9,6 @@ function Peer(json) { }); that.endpoints = that.endpoints || []; - that.statusTS = that.statusTS || 0; } @@ -34,7 +33,7 @@ Peer.prototype.keyID = function () { Peer.prototype.copyValues = function(to) { var obj = this; - ["version", "currency", "pub", "endpoints", "hash", "status", "statusTS", "block", "signature"].forEach(function (key) { + ["version", "currency", "pub", "endpoints", "hash", "status", "block", "signature"].forEach(function (key) { to[key] = obj[key]; }); }; @@ -60,7 +59,8 @@ Peer.prototype.json = function() { Peer.prototype.getBMA = function() { if (this.bma) return this.bma; var bma = null; - var bmaRegex = this.regex.BMA_REGEXP; + var bmaRegex = this.regexp.BMA_REGEXP; + var bmasRegex = this.regexp.BMAS_REGEXP; this.endpoints.forEach(function(ep){ var matches = !bma && bmaRegex.exec(ep); if (matches) { @@ -68,7 +68,20 @@ Peer.prototype.getBMA = function() { "dns": matches[2] || '', "ipv4": matches[4] || '', "ipv6": matches[6] || '', - "port": matches[8] || 80 + "port": matches[8] || 80, + "useSsl": matches[8] == 443, + "useBma": true + }; + } + matches = !bma && bmasRegex.exec(ep); + if (matches) { + bma = { + "dns": matches[2] || '', + "ipv4": matches[4] || '', + "ipv6": matches[6] || '', + "port": matches[8] || 80, + "useSsl": true, + "useBma": true }; } }); @@ -88,7 +101,6 @@ Peer.prototype.hasEndpoint = function(endpoint){ var endpoints = this.getEndpoints(regExp); if (!endpoints.length) return false; else return true; - }; Peer.prototype.getDns = function() { @@ -111,24 +123,24 @@ Peer.prototype.getPort = function() { return bma.port ? bma.port : null; }; -Peer.prototype.getHost = function() { - var bma = this.bma || this.getBMA(); +Peer.prototype.getHost = function(getHost) { + bma = getHost || this.bma || this.getBMA(); return ((bma.port == 443 || bma.useSsl) && bma.dns) ? bma.dns : (this.hasValid4(bma) ? bma.ipv4 : (bma.dns ? bma.dns : (bma.ipv6 ? '[' + bma.ipv6 + ']' :''))); }; -Peer.prototype.getURL = function() { - var bma = this.bma || this.getBMA(); - var host = this.getHost(); +Peer.prototype.getURL = function(bma) { + bma = bma || this.bma || this.getBMA(); + var host = this.getHost(bma); var protocol = (bma.port == 443 || bma.useSsl) ? 'https' : 'http'; return protocol + '://' + host + (bma.port ? (':' + bma.port) : ''); }; -Peer.prototype.getServer = function() { - var bma = this.bma || this.getBMA(); - var host = this.getHost(); +Peer.prototype.getServer = function(bma) { + bma = bma || this.bma || this.getBMA(); + var host = this.getHost(bma); return host + (host && bma.port ? (':' + bma.port) : ''); }; @@ -153,8 +165,16 @@ Peer.prototype.isTor = function() { return bma.useTor; }; - Peer.prototype.isWs2p = function() { var bma = this.bma || this.getBMA(); return bma.useWs2p; }; + +Peer.prototype.isBma = function() { + var bma = this.bma || this.getBMA(); + return !bma.useWs2p && !bma.useTor; +}; + +Peer.prototype.hasBma = function() { + return this.hasEndpoint('(BASIC_MERKLE_API|BMAS|BMATOR)'); +}; diff --git a/assets/www/dist/dist_js/app/filters.js b/assets/www/dist/dist_js/app/filters.js index 2422ca130d1b9f884a8bde40960050e8a00d9085..19e740476d3a985a3c2e34d16cf46e3e344d7762 100644 --- a/assets/www/dist/dist_js/app/filters.js +++ b/assets/www/dist/dist_js/app/filters.js @@ -2,7 +2,7 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalprecht.translate', 'cesium.translations' ]) - .factory('filterTranslations', ['$rootScope', 'csPlatform', 'csSettings', '$translate', function($rootScope, csPlatform, csSettings, $translate) { + .factory('filterTranslations', ['$rootScope', '$q', 'csPlatform', 'csSettings', 'csCurrency', '$translate', '$timeout', function($rootScope, $q, csPlatform, csSettings, csCurrency, $translate, $timeout) { 'ngInject'; var @@ -10,6 +10,8 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre startPromise, that = this; + that.MEDIAN_TIME_OFFSET = 3600 /*G1 default value*/; + // Update some translations, when locale changed function onLocaleChange() { console.debug('[filter] Loading translations for locale [{0}]'.format($translate.use())); @@ -38,8 +40,14 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre }); } + // Update some translations, when locale changed + function onCurrencyChange() { + console.debug('[filter] Computing constants from currency parameters'); + that.MEDIAN_TIME_OFFSET = csCurrency.data.medianTimeOffset || that.MEDIAN_TIME_OFFSET; + } + that.ready = function() { - if (started) return $q.when(data); + if (started) return $q.when(); return startPromise || that.start(); }; @@ -47,15 +55,20 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre startPromise = csPlatform.ready() .then(onLocaleChange) .then(function() { + onCurrencyChange(); started = true; csSettings.api.locale.on.changed($rootScope, onLocaleChange, this); + csCurrency.api.data.on.ready($rootScope, onCurrencyChange, this); }); return startPromise; }; // Default action - that.start(); + // Must be started with a delay, to allow settings override, before starting platform (need by Cesium API) + $timeout(function() { + that.start(); + }); return that; }]) @@ -150,7 +163,6 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre }; }]) - .filter('currencySymbol', ['filterTranslations', '$filter', 'csSettings', function(filterTranslations, $filter, csSettings) { return function(input, useRelative) { if (!input) return ''; @@ -169,7 +181,6 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre }; }]) - .filter('formatDecimal', ['csConfig', 'csCurrency', function(csConfig, csCurrency) { var minValue = 1 / Math.pow(10, csConfig.decimalCount || 4); var format = '0,0.0' + Array(csConfig.decimalCount || 4).join('0'); @@ -233,6 +244,12 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre }; }) + .filter('formatFromNowAndDate', ['filterTranslations', function(filterTranslations) { + return function(input, options) { + var m = input && moment.unix(parseInt(input)); + return m && (m.fromNow() + (options && options.separator || ' | ') + m.local().format(filterTranslations.DATE_PATTERN || 'YYYY-MM-DD HH:mm')) || ''; + }; + }]) .filter('formatDurationTo', function() { return function(input) { @@ -281,10 +298,53 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre .filter('formatFromNowShort', function() { return function(input) { - return input ? moment.unix(parseInt(input)).fromNow(true) : ''; + return input ? moment.unix(parseInt(input)+offset).fromNow(true) : ''; }; }) + /* -- median time (apply currency offset)-- */ + + .filter('medianDate', ['filterTranslations', function(filterTranslations) { + return function(input) { + return input ? moment.unix(parseInt(input) + filterTranslations.MEDIAN_TIME_OFFSET).local().format(filterTranslations.DATE_PATTERN || 'YYYY-MM-DD HH:mm') : ''; + }; + }]) + + .filter('medianDateShort', ['filterTranslations', function(filterTranslations) { + return function(input) { + return input ? moment.unix(parseInt(input) + filterTranslations.MEDIAN_TIME_OFFSET).local().format(filterTranslations.DATE_SHORT_PATTERN || 'YYYY-MM-DD') : ''; + }; + }]) + + + .filter('medianTime', ['filterTranslations', function(filterTranslations) { + return function(input) { + return input ? moment.unix(parseInt(input)+filterTranslations.MEDIAN_TIME_OFFSET).local().format('HH:mm') : ''; + }; + }]) + + .filter('medianFromNow', ['filterTranslations', function(filterTranslations) { + return function(input) { + return input ? moment.unix(parseInt(input) + filterTranslations.MEDIAN_TIME_OFFSET).fromNow() : ''; + }; + }]) + + .filter('medianFromNowShort', ['filterTranslations', function(filterTranslations) { + return function(input) { + return input ? moment.unix(parseInt(input)+filterTranslations.MEDIAN_TIME_OFFSET).fromNow(true) : ''; + }; + }]) + + .filter('medianFromNowAndDate', ['filterTranslations', function(filterTranslations) { + return function(input, options) { + var m = input && moment.unix(parseInt(input)+filterTranslations.MEDIAN_TIME_OFFSET); + return m && (m.fromNow() + (options && options.separator || ' | ') + m.local().format(filterTranslations.DATE_PATTERN || 'YYYY-MM-DD HH:mm')) || ''; + }; + }]) + + + /* -- text filter -- */ + .filter('capitalize', function() { return function(input) { if (!input) return ''; @@ -378,6 +438,7 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre return function(input, size) { size = size || 25; var startIndex = input.startsWith('http://') ? 7 : (input.startsWith('https://') ? 8 : 0); + startIndex = input.startsWith('www.', startIndex) ? startIndex + 4 : startIndex; // Remove sequence 'www.' return !input || (input.length-startIndex) <= size ? input.substr(startIndex) : (input.substr(startIndex, size) + '...'); }; }) diff --git a/assets/www/dist/dist_js/app/platform.js b/assets/www/dist/dist_js/app/platform.js index b5c57aec42875da6c69c2b09064e14fccc761c8c..faad33264857dc3bb23f2a70629cee215a370846 100644 --- a/assets/www/dist/dist_js/app/platform.js +++ b/assets/www/dist/dist_js/app/platform.js @@ -77,14 +77,14 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] IdleProvider.timeout(csConfig.logoutTimeout||15); // display warning during 15s }]) - .factory('$exceptionHandler', function() { + .factory('$exceptionHandler', ['$log', function($log) { 'ngInject'; return function(exception, cause) { - if (cause) console.error(exception, cause); - else console.error(exception); + if (cause) $log.error(exception, cause); + else $log.error(exception); }; - }) + }]) .factory('csPlatform', ['ionicReady', '$rootScope', '$q', '$state', '$translate', '$timeout', 'UIUtils', 'BMA', 'Device', 'csHttp', 'csConfig', 'csSettings', 'csCurrency', 'csWallet', function (ionicReady, $rootScope, $q, $state, $translate, $timeout, UIUtils, @@ -137,23 +137,52 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] throw 'ERROR.CHECK_NETWORK_CONNECTION'; } var newServer = fallbackNode.host + ((!fallbackNode.port && fallbackNode.port != 80 && fallbackNode.port != 443) ? (':' + fallbackNode.port) : ''); - return $translate('CONFIRM.USE_FALLBACK_NODE', {old: BMA.server, new: newServer}) - .then(function(msg) { - return UIUtils.alert.confirm(msg); + + // Skip is same as actual node + if (BMA.node.same(fallbackNode.host, fallbackNode.port)) { + console.debug('[platform] Skipping fallback node [{0}]: same as actual node'.format(newServer)); + return checkBmaNodeAlive(); // loop (= go to next node) + } + + // Try to get summary + return csHttp.get(fallbackNode.host, fallbackNode.port, '/node/summary', fallbackNode.port==443 || BMA.node.forceUseSsl)() + .catch(function(err) { + console.error('[platform] Could not reach fallback node [{0}]: skipping'.format(newServer)); + // silent, but return no result (will loop to the next fallback node) }) - .then(function (confirm) { - if (!confirm) return; + .then(function(res) { + if (!res) return checkBmaNodeAlive(); // Loop + + // Force to show port/ssl, if this is the only difference + var messageParam = {old: BMA.server, new: newServer}; + if (messageParam.old === messageParam.new) { + if (BMA.port != fallbackNode.port) { + messageParam.new += ':' + fallbackNode.port; + } + else if (BMA.useSsl == false && (fallbackNode.useSsl || fallbackNode.port==443)) { + messageParam.new += ' (SSL)'; + } + } + + return $translate('CONFIRM.USE_FALLBACK_NODE', messageParam) + .then(function(msg) { + return UIUtils.alert.confirm(msg); + }) + .then(function (confirm) { + if (!confirm) return; - // FIXME: should not change settings, but only tha BMA content - // in UI, display data form BMA object - csSettings.data.node = fallbackNode; + // Only change BMA node in settings + csSettings.data.node = fallbackNode; - csSettings.data.node.temporary = true; - csHttp.cache.clear(); + // Add a marker, for UI + csSettings.data.node.temporary = true; - // loop - return BMA.copy(fallbackNode) - .then(checkBmaNodeAlive); + csHttp.cache.clear(); + + // loop + return BMA.copy(fallbackNode) + .then(checkBmaNodeAlive); + }); }); } @@ -161,7 +190,6 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] return started; } - function getLatestRelease() { var latestRelease = csSettings.data.latestReleaseUrl && csHttp.uri.parse(csSettings.data.latestReleaseUrl); if (latestRelease) { @@ -247,8 +275,8 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] .catch(function(err) { startPromise = null; started = false; - if($state.current.name !== 'app.home') { - $state.go('app.home', {error: 'peer'}); + if($state.current.name !== $rootScope.errorState) { + $state.go($rootScope.errorState, {error: 'peer'}); } throw err; }); @@ -284,7 +312,7 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] }; }]) - .run(['$rootScope', '$translate', '$state', '$window', '$urlRouter', 'ionicReady', 'Device', 'UIUtils', '$ionicConfig', 'PluginService', 'csPlatform', 'csWallet', 'csSettings', 'csConfig', 'csCurrency', function($rootScope, $translate, $state, $window, $urlRouter, ionicReady, + .run(['$rootScope', '$state', '$window', '$urlRouter', 'ionicReady', '$ionicPlatform', '$ionicHistory', 'Device', 'UIUtils', '$ionicConfig', 'PluginService', 'csPlatform', 'csWallet', 'csSettings', 'csConfig', 'csCurrency', function($rootScope, $state, $window, $urlRouter, ionicReady, $ionicPlatform, $ionicHistory, Device, UIUtils, $ionicConfig, PluginService, csPlatform, csWallet, csSettings, csConfig, csCurrency) { 'ngInject'; @@ -293,6 +321,8 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] $rootScope.settings = csSettings.data; $rootScope.currency = csCurrency.data; $rootScope.device = Device; + $rootScope.errorState = 'app.home'; + $rootScope.smallscreen = UIUtils.screen.isSmall(); // Compute the root path var hashIndex = $window.location.href.indexOf('#'); @@ -316,15 +346,14 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] } // Ionic Platform Grade is not A, disabling views transitions - if (ionic.Platform.grade.toLowerCase() != 'a') { + if (ionic.Platform.grade.toLowerCase() !== 'a') { console.info('[app] Disabling UI effects, because plateform\'s grade is [' + ionic.Platform.grade + ']'); UIUtils.setEffects(false); } // Status bar style if (window.StatusBar) { - // org.apache.cordova.statusbar required - StatusBar.styleDefault(); + console.debug("[app] Status bar plugin enable"); } // Get latest release @@ -339,17 +368,33 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] } }); + // Prevent BACK button to exit without confirmation + $ionicPlatform.registerBackButtonAction(function(event) { + if ($ionicHistory.backView()) { + return $ionicHistory.goBack(); + } + event.preventDefault(); + return UIUtils.alert.confirm('CONFIRM.EXIT_APP') + .then(function (confirm) { + if (!confirm) return; // user cancelled + ionic.Platform.exitApp(); + }); + }, 100); + // Make sure platform is started return csPlatform.ready(); }); + + + }]) ; // Workaround to add "".startsWith() if not present if (typeof String.prototype.startsWith !== 'function') { console.debug("Adding String.prototype.startsWith() -> was missing on this platform"); - String.prototype.startsWith = function(prefix) { - return this.indexOf(prefix) === 0; + String.prototype.startsWith = function(prefix, position) { + return this.indexOf(prefix, position) === 0; }; } diff --git a/assets/www/dist/dist_js/app/services/bma-services.js b/assets/www/dist/dist_js/app/services/bma-services.js index e02a99005b2cd77ffa9a0a2a5db30cd22bfa21c5..be423437501670c4936f0ac1aa6f84499c45f98c 100644 --- a/assets/www/dist/dist_js/app/services/bma-services.js +++ b/assets/www/dist/dist_js/app/services/bma-services.js @@ -2,7 +2,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.settings.services']) -.factory('BMA', ['$q', '$window', '$rootScope', '$timeout', 'CryptoUtils', 'Api', 'Device', 'csConfig', 'csSettings', 'csHttp', function($q, $window, $rootScope, $timeout, CryptoUtils, Api, Device, csConfig, csSettings, csHttp) { +.factory('BMA', ['$q', '$window', '$rootScope', '$timeout', 'csCrypto', 'Api', 'Device', 'UIUtils', 'csConfig', 'csSettings', 'csHttp', function($q, $window, $rootScope, $timeout, csCrypto, Api, Device, UIUtils, csConfig, csSettings, csHttp) { 'ngInject'; function BMA(host, port, useSsl, useCache) { @@ -20,20 +20,28 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. OUTPUT_OBJ = 'OBJ\\(([0-9]+)\\)', OUTPUT_OBJ_OPERATOR = OUTPUT_OBJ + '[ ]*' + OUTPUT_OPERATOR + '[ ]*' + OUTPUT_OBJ, REGEX_ENDPOINT_PARAMS = "( ([a-z_][a-z0-9-_.ÄŸÄž]*))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))( (.+))?", + api = { + BMA: 'BASIC_MERKLED_API', + BMAS: 'BMAS', + WS2P: 'WS2P', + BMATOR: 'BMATOR', + WS2PTOR: 'WS2PTOR' + }, regexp = { - USER_ID: "[A-Za-z0-9_-]+", - CURRENCY: "[A-Za-z0-9_-]+", + USER_ID: "[0-9a-zA-Z-_]+", + CURRENCY: "[0-9a-zA-Z-_]+", PUBKEY: pubkey, - PUBKEY_WITH_CHECKSUM: "(" + pubkey +")" + ":([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{3})", + PUBKEY_WITH_CHECKSUM: "(" + pubkey +"):([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{3})", COMMENT: "[ a-zA-Z0-9-_:/;*\\[\\]()?!^\\+=@&~#{}|\\\\<>%.]*", + INVALID_COMMENT_CHARS: "[^ a-zA-Z0-9-_:/;*\\[\\]()?!^\\+=@&~#{}|\\\\<>%.]*", // duniter://[uid]:[pubkey]@[host]:[port] URI_WITH_AT: "duniter://(?:([A-Za-z0-9_-]+):)?("+pubkey+"@([a-zA-Z0-9-.]+.[ a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+)", URI_WITH_PATH: "duniter://([a-zA-Z0-9-.]+.[a-zA-Z0-9-_:.]+)/("+pubkey+")(?:/([A-Za-z0-9_-]+))?", - BMA_ENDPOINT: "BASIC_MERKLED_API" + REGEX_ENDPOINT_PARAMS, - BMAS_ENDPOINT: "BMAS" + REGEX_ENDPOINT_PARAMS, - WS2P_ENDPOINT: "WS2P ([a-f0-9]{8})"+ REGEX_ENDPOINT_PARAMS, - BMATOR_ENDPOINT: "BMATOR ([a-z0-9-_.]*|[0-9.]+|[0-9a-f:]+.onion)(?: ([0-9]+))?", - WS2PTOR_ENDPOINT: "WS2PTOR ([a-f0-9]{8}) ([a-z0-9-_.]*|[0-9.]+|[0-9a-f:]+.onion)(?: ([0-9]+))?(?: (.+))?" + BMA_ENDPOINT: api.BMA + REGEX_ENDPOINT_PARAMS, + BMAS_ENDPOINT: api.BMAS + REGEX_ENDPOINT_PARAMS, + WS2P_ENDPOINT: api.WS2P + " ([a-f0-9]{8})"+ REGEX_ENDPOINT_PARAMS, + BMATOR_ENDPOINT: api.BMATOR + " ([a-z0-9-_.]*|[0-9.]+|[0-9a-f:]+.onion)(?: ([0-9]+))?", + WS2PTOR_ENDPOINT: api.WS2PTOR + " ([a-f0-9]{8}) ([a-z0-9-_.]*|[0-9.]+|[0-9a-f:]+.onion)(?: ([0-9]+))?(?: (.+))?" }, errorCodes = { REVOCATION_ALREADY_REGISTERED: 1002, @@ -57,13 +65,12 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. ROOT_BLOCK_HASH: 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', LIMIT_REQUEST_COUNT: 5, // simultaneous async request to a Duniter node LIMIT_REQUEST_DELAY: 1000, // time (in second) to wait between to call of a rest request - regex: regexp, // deprecated - regexp: regexp + regexp: regexp, + api: api }, listeners, that = this; - that.date = {now: csHttp.date.now}; that.api = new Api(this, 'BMA-' + that.server); that.started = false; that.init = init; @@ -75,7 +82,6 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. console.debug('[BMA] Enable SSL (forced by config or detected in URL)'); } - if (host) { init(host, port, useSsl, useCache); } @@ -123,8 +129,10 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. } function closeWs() { + if (!that.cache) return; + console.warn('[BMA] Closing all websockets...'); - _.keys(that.cache.wsByPath).forEach(function(key) { + _.keys(that.cache.wsByPath||{}).forEach(function(key) { var sock = that.cache.wsByPath[key]; sock.close(); }); @@ -142,14 +150,14 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. cacheTime = that.useCache && cacheTime; var cacheKey = path + (cacheTime ? ('#'+cacheTime) : ''); - var getRequest = function(params) { + var getRequestFn = function(params) { if (!that.started) { if (!that._startPromise) { - console.error('[BMA] Trying to get [{0}] before start()...'.format(path)); + console.warn('[BMA] Trying to get [{0}] before start(). Waiting...'.format(path)); } return that.ready().then(function() { - return getRequest(params); + return getRequestFn(params); }); } @@ -163,10 +171,30 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. } that.cache.getByPath[cacheKey] = request; } - return request(params); + var execCount = 1; + return request(params) + .catch(function(err){ + // If node return too many requests error + if (err && err.ucode == exports.errorCodes.HTTP_LIMITATION) { + // If max number of retry not reach + if (execCount <= exports.constants.LIMIT_REQUEST_COUNT) { + if (execCount === 1) { + console.warn("[BMA] Too many HTTP requests: Will wait then retry..."); + // Update the loading message (if exists) + UIUtils.loading.update({template: "COMMON.LOADING_WAIT"}); + } + // Wait 1s then retry + return $timeout(function() { + execCount++; + return request(params); + }, exports.constants.LIMIT_REQUEST_DELAY); + } + } + throw err; + }); }; - return getRequest; + return getRequestFn; }; post = function(path) { @@ -194,26 +222,16 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. ws = function(path) { return function() { var sock = that.cache.wsByPath[path]; - if (!sock) { + if (!sock || sock.isClosed()) { sock = csHttp.ws(that.host, that.port, path, that.useSsl); - // Override close methods (add a usage counter) - sock._counter = 1; - var inheritedClose = sock.close; - sock.close = function() { - sock._counter--; - if (sock._counter <= 0) { - console.debug('[BMA] Closing websocket ['+path+']'); - inheritedClose(); - delete that.cache.wsByPath[path]; - } + // When close, remove from cache + sock.onclose = function() { + delete that.cache.wsByPath[path]; }; that.cache.wsByPath[path] = sock; } - else { - sock._counter++; - } return sock; }; }; @@ -221,10 +239,19 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. that.isAlive = function() { return csHttp.get(that.host, that.port, '/node/summary', that.useSsl)() .then(function(json) { - var isDuniter = json && json.duniter && json.duniter.software == 'duniter' && json.duniter.version; - var isCompatible = isDuniter && csHttp.version.isCompatible(csSettings.data.minVersion, json.duniter.version); - if (isDuniter && !isCompatible) { - console.error('[BMA] Uncompatible version [{0}] - expected at least [{1}]'.format(json.duniter.version, csSettings.data.minVersion)); + var software = json && json.duniter && json.duniter.software; + var isCompatible = true; + + // Check duniter min version + if (software === 'duniter' && json.duniter.version && true) { + isCompatible = csHttp.version.isCompatible(csSettings.data.minVersion, json.duniter.version); + } + // TODO: check other software (DURS, Juniter, etc.) + else { + console.debug('[BMA] Unknown node software [{0} v{1}]: could not check compatibility.'.format(software || '?', json.duniter.version || '?')); + } + if (!isCompatible) { + console.error('[BMA] Incompatible node [{0} v{1}]: expected at least v{2}'.format(software, json.duniter.version, csSettings.data.minVersion)); } return isCompatible; }) @@ -289,7 +316,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. console.debug('[BMA] Starting [{0}]...'.format(that.server)); } - var now = new Date().getTime(); + var now = Date.now(); that._startPromise = $q.all([ csSettings.ready, @@ -308,7 +335,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. if (!listeners || listeners.length === 0) { addListeners(); } - console.debug('[BMA] Started in '+(new Date().getTime()-now)+'ms'); + console.debug('[BMA] Started in '+(Date.now()-now)+'ms'); that.api.node.raise.start(); that.started = true; @@ -372,8 +399,9 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. node: { summary: get('/node/summary', csHttp.cache.LONG), same: function(host2, port2) { - return host2 == that.host && ((!that.port && !port2) || (that.port == port2||80)); + return host2 === that.host && ((!that.port && !port2) || (that.port == port2||80)) && (that.useSsl == (port2 && port2 === 443)); }, + forceUseSsl: that.forceUseSsl }, network: { peering: { @@ -387,34 +415,38 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. } }, wot: { - lookup: get('/wot/lookup/:search'), + lookup: get('/wot/lookup/:search', csHttp.cache.MEDIUM), certifiedBy: get('/wot/certified-by/:pubkey'), certifiersOf: get('/wot/certifiers-of/:pubkey'), member: { all: get('/wot/members', csHttp.cache.LONG), pending: get('/wot/pending', csHttp.cache.SHORT) }, - requirements: get('/wot/requirements/:pubkey'), + requirements: function(params, withCache) { + // No cache by default + if (withCache !== true) return exports.raw.requirementsNoCache(params); + return exports.raw.requirementsWithCache(params); + }, add: post('/wot/add'), certify: post('/wot/certify'), revoke: post('/wot/revoke') }, blockchain: { - parameters: get('/blockchain/parameters', csHttp.cache.LONG), + parameters: get('/blockchain/parameters', csHttp.cache.VERY_LONG), block: get('/blockchain/block/:block', csHttp.cache.SHORT), blocksSlice: get('/blockchain/blocks/:count/:from'), - current: get('/blockchain/current'), + current: get('/blockchain/current', csHttp.cache.SHORT), membership: post('/blockchain/membership'), stats: { - ud: get('/blockchain/with/ud', csHttp.cache.SHORT), + ud: get('/blockchain/with/ud', csHttp.cache.MEDIUM), tx: get('/blockchain/with/tx'), - newcomers: get('/blockchain/with/newcomers'), + newcomers: get('/blockchain/with/newcomers', csHttp.cache.MEDIUM), hardship: get('/blockchain/hardship/:pubkey'), difficulties: get('/blockchain/difficulties') } }, tx: { - sources: get('/tx/sources/:pubkey'), + sources: get('/tx/sources/:pubkey', csHttp.cache.SHORT), process: post('/tx/process'), history: { all: get('/tx/history/:pubkey'), @@ -429,7 +461,10 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. }, uri: {}, version: {}, - raw: {} + raw: { + requirementsWithCache: get('/wot/requirements/:pubkey', csHttp.cache.LONG), + requirementsNoCache: get('/wot/requirements/:pubkey') + } }; exports.regex = exports.regexp; // deprecated @@ -528,7 +563,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. }; }; - exports.node.parseEndPoint = function(endpoint) { + exports.node.parseEndPoint = function(endpoint, epPrefix) { // Try BMA var matches = exports.regexp.BMA_ENDPOINT.exec(endpoint); if (matches) { @@ -593,12 +628,35 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. "useWs2p": true }; } + + // Use generic match + if (epPrefix) { + matches = exact(epPrefix + REGEX_ENDPOINT_PARAMS).exec(endpoint); + if (matches) { + return { + "dns": matches[2] || '', + "ipv4": matches[4] || '', + "ipv6": matches[6] || '', + "port": matches[8] || 80, + "useSsl": matches[8] && matches[8] == 443, + "path": matches[10], + "useBma": false + }; + } + } + }; exports.copy = function(otherNode) { - if (that.started) that.stop(); - that.init(otherNode.host, otherNode.port, otherNode.useSsl, that.useCache/*keep original value*/); - return that.start(); + var wasStarted = that.started; + + var server = csHttp.getUrl(otherNode.host, otherNode.port, ''/*path*/, otherNode.useSsl); + var hasChanged = (server !== that.url); + if (hasChanged) { + that.init(otherNode.host, otherNode.port, otherNode.useSsl, that.useCache/*keep original value*/); + // Restart (only if was already started) + return wasStarted ? that.restart() : $q.when(); + } }; exports.wot.member.uids = function() { @@ -642,10 +700,10 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. * @param blockNumbers a rray of block number */ exports.network.peering.peersByLeaves = function(leaves){ - return exports.raw.getHttpRecursive(exports.network.peering.peers, 'leaf', leaves, 0, 10, callbackFlush); + return exports.raw.getHttpRecursive(exports.network.peering.peers, 'leaf', leaves, 0, 10); }; - exports.raw.getHttpRecursive = function(httpGetRequest, paramName, paramValues, offset, size, callbackFlush) { + exports.raw.getHttpRecursive = function(httpGetRequest, paramName, paramValues, offset, size) { offset = angular.isDefined(offset) ? offset : 0; size = size || exports.constants.LIMIT_REQUEST_COUNT; return $q(function(resolve, reject) { @@ -726,6 +784,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. exports.uri.parse = function(uri) { return $q(function(resolve, reject) { var pubkey; + // If pubkey: not need to parse if (exact(regexp.PUBKEY).test(uri)) { resolve({ @@ -734,14 +793,21 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. } // If pubkey+checksum else if (exact(regexp.PUBKEY_WITH_CHECKSUM).test(uri)) { + console.debug("[BMA.parse] Detecting a pubkey with checksum: " + uri); var matches = exports.regexp.PUBKEY_WITH_CHECKSUM.exec(uri); pubkey = matches[1]; var checksum = matches[2]; - var expectedChecksum = CryptoUtils.checksum_from_sign_pk(CryptoUtils.base58.decode(pubkey)); - if (checksum != expectedChecksum) throw {message: 'ERROR.PUBKEY_INVALID_CHECKSUM'}; - resolve({ - pubkey: pubkey - }); + console.debug("[BMA.parse] Detecting a pubkey {"+pubkey+"} with checksum {" + checksum + "}"); + var expectedChecksum = csCrypto.util.pkChecksum(pubkey); + console.debug("[BMA.parse] Expecting checksum for pubkey is {" + expectedChecksum + "}"); + if (checksum != expectedChecksum) { + reject( {message: 'ERROR.PUBKEY_INVALID_CHECKSUM'}); + } + else { + resolve({ + pubkey: pubkey + }); + } } else if(uri.startsWith('duniter://')) { var parser = csHttp.uri.parse(uri), @@ -787,6 +853,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. }); }) .catch(function(err) { + console.error(err); reject({message: 'Could not get node parameter. Currency could not be retrieve'}); }); } @@ -815,25 +882,30 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. host: host, currency: currency }); + }) + .catch(function(err) { + console.error(err); + reject({message: 'Could not get node parameter. Currency could not be retrieve'}); }); } } else { - console.warn('Unknown URI format: ' + uri); - throw {message: 'ERROR.UNKNOWN_URI_FORMAT'}; + console.debug("[BMA.parse] Could not parse URI: " + uri); + reject({message: 'ERROR.UNKNOWN_URI_FORMAT'}); } }) // Check values against regex .then(function(result) { + if (!result) return; if (result.pubkey && !(exact(regexp.PUBKEY).test(result.pubkey))) { - reject({message: "Invalid pubkey format [" + result.pubkey + "]"}); return; + throw {message: "Invalid pubkey format [" + result.pubkey + "]"}; } if (result.uid && !(exact(regexp.USER_ID).test(result.uid))) { - reject({message: "Invalid uid format [" + result.uid + "]"}); return; + throw {message: "Invalid uid format [" + result.uid + "]"}; } if (result.currency && !(exact(regexp.CURRENCY).test(result.currency))) { - reject({message: "Invalid currency format ["+result.currency+"]"}); return; + throw {message: "Invalid currency format ["+result.currency+"]"}; } return result; }); @@ -888,9 +960,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. var service = new BMA(undefined, undefined, undefined, true); service.instance = function(host, port, useSsl, useCache) { - var bma = new BMA(); - bma.init(host, port, useSsl, useCache); - return bma; + return new BMA(host, port, useSsl, useCache); }; service.lightInstance = function(host, port, useSsl, timeout) { diff --git a/assets/www/dist/dist_js/app/services/cache-services.js b/assets/www/dist/dist_js/app/services/cache-services.js index bf08be6e30d4aaee95c687e5c8225d0ca70ec023..291c51475463263e7c0b219b17150e61138567d4 100644 --- a/assets/www/dist/dist_js/app/services/cache-services.js +++ b/assets/www/dist/dist_js/app/services/cache-services.js @@ -1,12 +1,14 @@ angular.module('cesium.cache.services', ['angular-cache']) -.factory('csCache', ['$http', 'csSettings', 'CacheFactory', function($http, csSettings, CacheFactory) { +.factory('csCache', ['$http', '$window', 'csSettings', 'CacheFactory', function($http, $window, csSettings, CacheFactory) { 'ngInject'; var constants = { - LONG: 1 * 60 * 60 * 1000 /*5 min*/, - SHORT: csSettings.defaultSettings.cacheTimeMs + VERY_LONG: 54000000, /*15 days*/ + LONG: 1 * 60 * 60 * 1000 /*1 hour*/, + MEDIUM: 5 * 60 * 1000 /*5 min*/, + SHORT: csSettings.defaultSettings.cacheTimeMs // around 1min }, cacheNames = [] ; @@ -15,19 +17,22 @@ angular.module('cesium.cache.services', ['angular-cache']) prefix = prefix || 'csCache-'; maxAge = maxAge || constants.SHORT; var cacheName = prefix + maxAge; + + // FIXME : enable this when cache is cleaning on rollback + var storageMode = csSettings.data.useLocalStorage && $window.localStorage ? 'localStorage' : 'memory'; + if (!onExpire) { if (!cacheNames[cacheName]) { cacheNames[cacheName] = true; + console.debug("[cache] Creating cache {0}...".format(cacheName)); } return CacheFactory.get(cacheName) || CacheFactory.createCache(cacheName, { maxAge: maxAge, - deleteOnExpire: 'aggressive', + deleteOnExpire: 'passive', //cacheFlushInterval: 60 * 60 * 1000, // clear itself every hour recycleFreq: Math.max(maxAge - 1000, 5 * 60 * 1000 /*5min*/), - storageMode: 'memory' - // FIXME : enable this when cache is cleaning on rollback - //csSettings.data.useLocalStorage ? 'localStorage' : 'memory' + storageMode: storageMode }); } else { @@ -39,15 +44,14 @@ angular.module('cesium.cache.services', ['angular-cache']) if (!cacheNames[cacheName]) { cacheNames[cacheName] = true; } + console.debug("[cache] Creating cache {0} with 'onExpire' option...".format(cacheName)); return CacheFactory.createCache(cacheName, { maxAge: maxAge, deleteOnExpire: 'aggressive', //cacheFlushInterval: 60 * 60 * 1000, // This cache will clear itself every hour recycleFreq: maxAge, onExpire: onExpire, - storageMode: 'memory' - // FIXME : enable this when cache is cleaning on rollback - //csSettings.data.useLocalStorage ? 'localStorage' : 'memory' + storageMode: storageMode }); } } @@ -65,7 +69,7 @@ angular.module('cesium.cache.services', ['angular-cache']) function clearFromPrefix(cachePrefix) { _.forEach(_.keys(cacheNames), function(cacheName) { if (cacheName.startsWith(cachePrefix)) { - var cache = CacheFactory.get(cacheNames); + var cache = CacheFactory.get(cacheName); if (cache) { cache.removeAll(); } @@ -77,10 +81,7 @@ angular.module('cesium.cache.services', ['angular-cache']) get: getOrCreateCache, clear: clearFromPrefix, clearAll: clearAllCaches, - constants: { - LONG : constants.LONG, - SHORT: constants.SHORT - } + constants: constants }; }]) ; diff --git a/assets/www/dist/dist_js/app/services/crypto-services.js b/assets/www/dist/dist_js/app/services/crypto-services.js index 892c535330255daedb8848a3b9b59c062ca72a83..8520aee3fc6fb34fc4319af72109161638524a01 100644 --- a/assets/www/dist/dist_js/app/services/crypto-services.js +++ b/assets/www/dist/dist_js/app/services/crypto-services.js @@ -5,26 +5,6 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) .factory('CryptoUtils', ['$q', '$timeout', 'ionicReady', function($q, $timeout, ionicReady) { 'ngInject'; - function xor(a, b) { - var length = Math.max(a.length, b.length); - var buffer = new Uint8Array(length); - for (var i = 0; i < length; ++i) { - buffer[i] = a[i] ^ b[i]; - } - return buffer; - } - - function concat_Uint8Array( buffer1, buffer2 ) { - var tmp = new Uint8Array( buffer1.byteLength + buffer2.byteLength ); - tmp.set( new Uint8Array( buffer1 ), 0 ); - tmp.set( new Uint8Array( buffer2 ), buffer1.byteLength ); - return tmp; - } - - function test(regexpContent) { - return new RegExp(regexpContent); - } - /** * CryptoAbstract, abstract class with useful methods * @type {number} @@ -80,48 +60,26 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) p: 1, memory: -1 // default }, + // removeIf(no-device) SECURE: { N: 16384, r: 32, p: 2, - memory: -1 // default + memory: 33554432 }, HARDEST: { N: 65536, r: 32, p: 4, - memory: -1 // default + memory: 134217728 }, EXTREME: { N: 262144, r: 64, p: 8, - memory: -1 // default - } - }, - EWIF: { - SALT_LENGTH: 4, - DERIVED_HALF_LENGTH: 16, - }, - REGEXP: { - PUBKEY: '[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44}', - SECKEY: '[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{86,88}', - FILE: { - TYPE_LINE: '^Type: ([a-zA-Z0-9]+)\n', - VERSION: 'Version: ([0-9]+)\n', - PUB: '[Pp]ub: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44})\n', - SEC: '[Ss]ec: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{86,88})(\n|$)', - DATA: '[Dd]ata: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)(\n|$)' + memory: 536870912 } - } - }; - - CryptoAbstractService.prototype.regexp = { - FILE: { - TYPE_LINE: test(CryptoAbstractService.prototype.constants.REGEXP.FILE.TYPE_LINE), - PUB: test(CryptoAbstractService.prototype.constants.REGEXP.FILE.PUB), - SEC: test(CryptoAbstractService.prototype.constants.REGEXP.FILE.SEC), - DATA: test(CryptoAbstractService.prototype.constants.REGEXP.FILE.DATA) + // endRemoveIf(no-device) } }; @@ -133,11 +91,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) CryptoAbstractService.prototype.async_load_scrypt = function(on_ready, options) { var that = this; - if (scrypt_module_factory !== null){ - on_ready(scrypt_module_factory(options.requested_total_memory)); - that.scrypt.requested_total_memory = options.requested_total_memory; - //console.log('inside async_load_scrypt', that); // TODO manage memory changes - } + if (scrypt_module_factory !== null){scrypt_module_factory(on_ready, options);} else {$timeout(function(){that.async_load_scrypt(on_ready, options);}, 100);} }; @@ -159,290 +113,18 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) else {$timeout(function(){that.async_load_sha256(on_ready);}, 100);} }; - CryptoAbstractService.prototype.readKeyFile = function(file, options) { - var that = this; - - if (file && file.content) { - return that.parseKeyFileContent(file.content, options); - } - - return $q(function(resolve, reject) { - if (!file) { - return reject('Argument [file] is missing'); - } - - console.debug('[crypto] [keypair] reading file: ', file); - var reader = new FileReader(); - reader.onload = function (event) { - that.parseKeyFileContent(event.target.result, options) - .then(resolve) - .catch(reject); - }; - reader.readAsText(file, 'utf8'); - }); - }; - - CryptoAbstractService.prototype.parseKeyFileContent = function(content, options) { - options = options || {}; - options.withSecret = angular.isDefined(options.withSecret) ? options.withSecret : false; - options.defaultType = options.defaultType || 'PubSec'; - - var that = this; - return $q(function(resolve, reject) { - if (!content) { - return reject('Argument [content] is missing'); - } - var typeMatch = that.regexp.FILE.TYPE_LINE.exec(content); - - // no Type (first line) - if (!typeMatch && options.defaultType) { - // Add default type, then retry - return resolve(that.parseKeyFileContent('Type: {0}\n{1}'.format(options.defaultType, content), options)); - } - - var type = typeMatch[1]; - - // Type: PubSec - if (type == 'PubSec') { - var pubMatch = that.regexp.FILE.PUB.exec(content); - if (!pubMatch) { - return reject('Missing [pub] field in file, or invalid public key value'); - } - if (!options.withSecret) { - return resolve({ - signPk: that.base58.decode(pubMatch[1]) - }); - } - var secMatch = that.regexp.FILE.SEC.exec(content); - if (!secMatch) { - return reject('Missing [sec] field in file, or invalid secret key value'); - } - return resolve({ - signPk: that.base58.decode(pubMatch[1]), - signSk: that.base58.decode(secMatch[1]) - }); - } - - var signKeypair; - var matches; - - // Type: WIF - if (type == 'WIF') { - matches = that.regexp.FILE.DATA.exec(content); - if (!matches) { - return reject('Missing [Data] field in file, or invalid public key value'); - } - signKeypair = that.keypair_from_wif_v1(matches[1]); - } - - // Type: EWIF - else if (type == 'EWIF') { - matches = that.regexp.FILE.DATA.exec(content); - if (!matches) { - return reject('Missing [Data] field in file, or invalid public key value'); - } - if (!options.password) { - reject('NEED_PASSWORD'); - return; - } - try { - signKeypair = that.keypair_from_ewif_v1(matches[1], options.password); - } - catch(err) { - reject(err); - } - } - - // Unknown type - else { - if (options.defaultType) { - return reject('Bad file format: missing Type field'); - } - else { - return reject('Bad file format, unknown type [' + type + ']'); - } - } - - if (signKeypair && !options.withSecret) { - resolve({ - signPk: signKeypair.signPk - }); - } - else { - resolve(signKeypair); - } - }); - }; - - CryptoAbstractService.prototype.keypair_from_wif_v1 = function(wif_base58) { - var that = this; - var i; - var wif_int8 = that.base58.decode(wif_base58); - - if (wif_int8[0] != 1) { - throw 'Invalid WIF format: The first byte of data must be [0x01].'; - } - + CryptoAbstractService.prototype.seed_from_signSk = function(signSk) { var seed = new Uint8Array(that.constants.SEED_LENGTH); - for (i = 0; i < seed.length; i++) seed[i] = wif_int8[i+1]; - var signKeypair = that.nacl.crypto_sign_seed_keypair(seed); - - // Compute expected checksum - var checksumContent = new Uint8Array(that.constants.SEED_LENGTH + 1); - for (i = 0; i < checksumContent.length; i++) checksumContent[i] = wif_int8[i]; - var checksumHash = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(checksumContent)); - var expectedChecksum = new Uint8Array(2); - for (i = 0; i < expectedChecksum.length; i++) expectedChecksum[i] = checksumHash[i]; - expectedChecksum = that.base58.encode(expectedChecksum); - - var checksum = new Uint8Array(2); - for (i = 0; i < checksum.length; i++) checksum[i] = wif_int8[i+33]; - checksum = that.base58.encode(checksum); - - if (expectedChecksum !== checksum) { - throw 'Invalid WIF format: bad checksum'; - } - - return { - signPk: signKeypair.signPk, - signSk: signKeypair.signSk - }; - }; - - CryptoAbstractService.prototype.checksum_from_sign_pk = function(signPk) { - return this.base58.encode(this.nacl.crypto_hash_sha256(this.nacl.crypto_hash_sha256(signPk))).substring(0,3); - }; - - CryptoAbstractService.prototype.keypair_from_ewif_v1 = function(ewif_base58, password) { - var that = this; - var ewif_int8 = that.base58.decode(ewif_base58); - if (ewif_int8.length != 39) { - throw 'Invalid EWIF format: Data must be a 39 bytes array, encoded in base 58.'; - } - var fi = ewif_int8.slice(0,1); - if (fi != 0x02) { - throw 'Invalid EWIF format: The first byte of data must be [0x02].'; - } - - var ewif_int8_no_checksum = ewif_int8.slice(0,-2); - var checksum = ewif_int8.slice(-2); - var salt = ewif_int8.slice(1,5); - var encryptedhalf1 = ewif_int8.slice(5,21); - var encryptedhalf2 = ewif_int8.slice(21,37); - - var scrypt_seed = that.scrypt.crypto_scrypt( - that.util.encode_utf8(password), - salt, - 16384, - 8,8,64); - var derivedhalf1 = scrypt_seed.subarray(0,32); - var derivedhalf2 = scrypt_seed.subarray(32,64); - - //AES - var aesEcb = new aesjs.ModeOfOperation.ecb(derivedhalf2); - var decryptedhalf1 = aesEcb.decrypt(encryptedhalf1); - var decryptedhalf2 = aesEcb.decrypt(encryptedhalf2); - - decryptedhalf1 = new Uint8Array(decryptedhalf1); - decryptedhalf2 = new Uint8Array(decryptedhalf2); - - //xor - var seed1 = xor(decryptedhalf1, derivedhalf1.subarray(0,16)); - var seed2 = xor(decryptedhalf2, derivedhalf1.subarray(16,32)); - var seed = concat_Uint8Array(seed1,seed2); - var signKeypair = that.nacl.crypto_sign_seed_keypair(seed); - - // check salt - var salt_from_seed = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(signKeypair.signPk)).subarray(0,4); - if(that.base58.encode(salt) !== that.base58.encode(salt_from_seed)) { - throw 'BAD_PASSWORD'; //"Invalid password to encrypt EWIF data"; - } - - // Compute expected checksum - var expectedChecksum = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(ewif_int8_no_checksum)).subarray(0,2); - expectedChecksum = that.base58.encode(expectedChecksum); - checksum = that.base58.encode(checksum); - - if (expectedChecksum !== checksum) { - throw "Invalid EWIF format: bad checksum"; - } - - return { - signPk: signKeypair.signPk, - signSk: signKeypair.signSk - }; + for (var i = 0; i < seed.length; i++) seed[i] = signSk[i]; + return seed; }; - CryptoAbstractService.prototype.seed_from_signSk = function(signSk) { - var that = this; var seed = new Uint8Array(that.constants.SEED_LENGTH); for (var i = 0; i < seed.length; i++) seed[i] = signSk[i]; return seed; }; - CryptoAbstractService.prototype.wif_v1_from_keypair = function(keypair) { - - var that = this; - - var seed = that.seed_from_signSk(keypair.signSk); - if (!seed || seed.byteLength !== that.constants.SEED_LENGTH) - throw "Bad see format. Expected {0} bytes".format(that.constants.SEED_LENGTH); - - var fi = new Uint8Array(1); - fi[0] = 0x01; - var seed_fi = concat_Uint8Array(fi, seed); - - // checksum - var checksum = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(seed_fi)).subarray(0,2); - - var wif_int8 = concat_Uint8Array(seed_fi, checksum); - return that.base58.encode(wif_int8); - }; - - CryptoAbstractService.prototype.ewif_v1_from_keypair = function(keypair, password) { - - var that = this; - - var seed = that.seed_from_signSk(keypair.signSk); - if (!seed || seed.byteLength !== that.constants.SEED_LENGTH) - throw "Bad see format. Expected {0} bytes".format(that.constants.SEED_LENGTH); - - // salt - var salt = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(keypair.signPk)).subarray(0,4); - - // scrypt_seed - var scrypt_seed = that.scrypt.crypto_scrypt( - that.util.encode_utf8(password), - that.util.encode_utf8(salt), - 16384,8,8,64); - var derivedhalf1 = scrypt_seed.subarray(0,32); - var derivedhalf2 = scrypt_seed.subarray(32,64); - - //XOR & AES - var seed1_xor_derivedhalf1_1 = xor(seed.subarray(0,16), derivedhalf1.subarray(0,16)); - var seed2_xor_derivedhalf1_2 = xor(seed.subarray(16,32), derivedhalf1.subarray(16,32)); - - var aesEcb = new aesjs.ModeOfOperation.ecb(derivedhalf2); - var encryptedhalf1 = aesEcb.encrypt(seed1_xor_derivedhalf1_1); - var encryptedhalf2 = aesEcb.encrypt(seed2_xor_derivedhalf1_2); - - encryptedhalf1 = new Uint8Array(encryptedhalf1); - encryptedhalf2 = new Uint8Array(encryptedhalf2); - - // concatenate ewif - var ewif_int8 = new Uint8Array(1); - ewif_int8[0] = 0x02; - ewif_int8 = concat_Uint8Array(ewif_int8,salt); - ewif_int8 = concat_Uint8Array(ewif_int8,encryptedhalf1); - ewif_int8 = concat_Uint8Array(ewif_int8,encryptedhalf2); - - var checksum = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(ewif_int8)).subarray(0,2); - ewif_int8 = concat_Uint8Array(ewif_int8,checksum); - - return that.base58.encode(ewif_int8); - }; - // Web crypto API - see https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API var crypto = window.crypto || window.msCrypto || window.Crypto; if (crypto && crypto.getRandomValues) { @@ -454,16 +136,6 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) return $q.when(nonce); }; } - else { - // TODO: add a default function ? - //CryptoAbstractService.prototype.random_nonce = function() { - // var nonce = new Uint8Array(crypto_secretbox_NONCEBYTES); - // var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - // for(var i = 0; i < length; i++) { - // text += possible.charAt(Math.floor(Math.random() * possible.length)); - // } - //} - } function FullJSServiceFactory() { this.id = 'FullJS'; @@ -489,9 +161,9 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) }; this.util.decode_base58 = function (a) { // TODO : move to abstract factory var i; - a = that.base58.decode(a); - var b = new Uint8Array(a.length); - for (i = 0; i < a.length; i++) b[i] = a[i]; + var d = that.base58.decode(a); + var b = new Uint8Array(d.length); + for (i = 0; i < d.length; i++) b[i] = d[i]; return b; }; this.util.decode_base64 = function (a) { @@ -518,24 +190,74 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) return $q.when(that.nacl.crypto_box_random_nonce()); } }; + this.util.crypto_hash_sha256 = function(msg_int8) { + return that.nacl.crypto_hash_sha256(msg_int8); + }; + this.util.crypto_scrypt = function(password, salt, N, r, p, seedLength) { + + return $q(function(resolve, reject) { + try { + var seed = that.scrypt.crypto_scrypt( + password, + salt, + N, + r, + p, + seedLength); + resolve(seed); + } + catch(err) { + reject(err); + } + }); + }; /** * Compute the box key pair, from a sign key pair */ this.box_keypair_from_sign = function (signKeyPair) { - if (signKeyPair.bokSk && signKeyPair.boxPk) return $q.when(signKeyPair); - return $q.when(that.nacl.crypto_box_keypair_from_sign_sk(signKeyPair.signSk)); + if (signKeyPair.boxSk && signKeyPair.boxPk) return $q.when(signKeyPair); + return $q(function (resolve, reject) { + try { + // TODO: waiting for a new version of js-nacl, with missing functions expose + //resolve(that.nacl.crypto_box_keypair_from_sign_sk(signPk); + + resolve(crypto_box_keypair_from_sign_sk(signPk)); + } + catch(err) { + reject(err); + } + }); }; /** * Compute the box public key, from a sign public key */ this.box_pk_from_sign = function (signPk) { - return $q.when(that.nacl.crypto_box_pk_from_sign_pk(signPk)); + return $q(function(resolve, reject) { + try { + // TODO: waiting for a new version of js-nacl, with missing functions expose + //resolve(that.nacl.crypto_box_pk_from_sign_pk(signPk)); + + resolve(crypto_box_pk_from_sign_pk(signPk)); + } + catch(err) { + reject(err); + } + }); }; this.box_sk_from_sign = function (signSk) { - return $q.when(that.nacl.crypto_box_sk_from_sign_sk(signSk)); + return $q(function(resolve, reject) { + try { + // TODO: waiting for a new version of js-nacl, with missing functions expose + //resolve(that.nacl.crypto_box_sk_from_sign_sk(signSk)); + resolve(crypto_box_sk_from_sign_sk(signSk)); + } + catch(err) { + reject(err); + } + }); }; /** @@ -547,17 +269,14 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) resolve(message); return; } - var messageBin = that.util.decode_utf8(message); + var messageBin = that.nacl.encode_utf8(message); if (typeof recipientPk === "string") { recipientPk = that.util.decode_base58(recipientPk); } - //console.debug('Original message: ' + message); try { var ciphertextBin = that.nacl.crypto_box(messageBin, nonce, recipientPk, senderSk); var ciphertext = that.util.encode_base64(ciphertextBin); - - //console.debug('Encrypted message: ' + ciphertext); resolve(ciphertext); } catch (err) { @@ -575,6 +294,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) resolve(cypherText); return; } + var ciphertextBin = that.util.decode_base64(cypherText); if (typeof senderPk === "string") { senderPk = that.util.decode_base58(senderPk); @@ -582,10 +302,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) try { var message = that.nacl.crypto_box_open(ciphertextBin, nonce, senderPk, recipientSk); - that.util.array_to_string(message, function (result) { - //console.debug('Decrypted text: ' + result); - resolve(result); - }); + resolve(that.nacl.decode_utf8(message)); } catch (err) { reject(err); @@ -598,14 +315,30 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) * Create key pairs (sign and box), from salt+password (Scrypt auth) */ this.scryptKeypair = function(salt, password, scryptParams) { + return that.util.crypto_scrypt( + that.util.encode_utf8(password), + that.util.encode_utf8(salt), + scryptParams && scryptParams.N || that.constants.SCRYPT_PARAMS.DEFAULT.N, + scryptParams && scryptParams.r || that.constants.SCRYPT_PARAMS.DEFAULT.r, + scryptParams && scryptParams.p || that.constants.SCRYPT_PARAMS.DEFAULT.p, + that.constants.SEED_LENGTH) + .then(function(seed){ + var signKeypair = that.nacl.crypto_sign_seed_keypair(seed); + var boxKeypair = that.nacl.crypto_box_seed_keypair(seed); + return { + signPk: signKeypair.signPk, + signSk: signKeypair.signSk, + boxPk: boxKeypair.boxPk, + boxSk: boxKeypair.boxSk + }; + }); + }; + + /** + * Create key pairs from a seed + */ + this.seedKeypair = function(seed) { return $q(function(resolve, reject) { - var seed = that.scrypt.crypto_scrypt( - that.util.encode_utf8(password), - that.util.encode_utf8(salt), - scryptParams && scryptParams.N || that.constants.SCRYPT_PARAMS.DEFAULT.N, - scryptParams && scryptParams.r || that.constants.SCRYPT_PARAMS.DEFAULT.r, - scryptParams && scryptParams.p || that.constants.SCRYPT_PARAMS.DEFAULT.p, - that.constants.SEED_LENGTH); var signKeypair = that.nacl.crypto_sign_seed_keypair(seed); var boxKeypair = that.nacl.crypto_box_seed_keypair(seed); resolve({ @@ -678,7 +411,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) var naclOptions = {}; var scryptOptions = {}; if (ionic.Platform.grade.toLowerCase()!='a') { - console.info('Reduce NaCl memory because plateform grade is not [a] but [' + ionic.Platform.grade + ']'); + console.info('Reduce NaCl memory to 16mb, because plateform grade is not [a] but [{0}]'.format(ionic.Platform.grade)); naclOptions.requested_total_memory = 16 * 1048576; // 16 Mo } var loadedLib = 0; @@ -695,13 +428,14 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) }, naclOptions); this.async_load_scrypt(function(lib) { that.scrypt = lib; + that.scrypt.requested_total_memory = scryptOptions.requested_total_memory; checkAllLibLoaded(); }, scryptOptions); this.async_load_base58(function(lib) { that.base58 = lib; checkAllLibLoaded(); }); - this.async_load_base64(function(lib) { + that.async_load_base64(function(lib) { that.base64 = lib; checkAllLibLoaded(); }); @@ -719,6 +453,109 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) pack: that.box, open: that.box_open }; + + /*-- + start WORKAROUND - Publish missing functions (see PR js-nacl: https://github.com/tonyg/js-nacl/pull/54) + -- */ + + function crypto_box_keypair_from_sign_sk(sk) { + var ska = check_injectBytes("crypto_box_keypair_from_sign_sk", "sk", sk, + that.nacl.nacl_raw._crypto_sign_secretkeybytes()); + var skb = new Target(that.nacl.nacl_raw._crypto_box_secretkeybytes()); + check("_crypto_sign_ed25519_sk_to_curve25519", + that.nacl.nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska)); + FREE(ska); + return that.nacl.crypto_box_keypair_from_raw_sk(skb.extractBytes()); + } + + function crypto_box_pk_from_sign_pk(pk) { + var pka = check_injectBytes("crypto_box_pk_from_sign_pk", "pk", pk, + that.nacl.nacl_raw._crypto_sign_publickeybytes()); + var pkb = new Target(that.nacl.nacl_raw._crypto_box_publickeybytes()); + check("_crypto_sign_ed25519_pk_to_curve25519", + that.nacl.nacl_raw._crypto_sign_ed25519_pk_to_curve25519(pkb.address, pka)); + FREE(pka); + return pkb.extractBytes(); + } + + function crypto_box_sk_from_sign_sk(sk) { + var ska = check_injectBytes("crypto_box_sk_from_sign_sk", "sk", sk, + that.nacl.nacl_raw._crypto_sign_secretkeybytes()); + var skb = new Target(that.nacl.nacl_raw._crypto_box_secretkeybytes()); + check("_crypto_sign_ed25519_sk_to_curve25519", + that.nacl.nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska)); + FREE(ska); + return skb.extractBytes(); + } + + function check_length(function_name, what, thing, expected_length) { + if (thing.length !== expected_length) { + throw {message: "nacl." + function_name + " expected " + + expected_length + "-byte " + what + " but got length " + thing.length}; + } + } + + function check(function_name, result) { + if (result !== 0) { + throw {message: "nacl_raw." + function_name + " signalled an error"}; + } + } + + function check_injectBytes(function_name, what, thing, expected_length, leftPadding) { + check_length(function_name, what, thing, expected_length); + return injectBytes(thing, leftPadding); + } + + function injectBytes(bs, leftPadding) { + var p = leftPadding || 0; + var address = MALLOC(bs.length + p); + that.nacl.nacl_raw.HEAPU8.set(bs, address + p); + for (var i = address; i < address + p; i++) { + that.nacl.nacl_raw.HEAPU8[i] = 0; + } + return address; + } + + function MALLOC(nbytes) { + var result = that.nacl.nacl_raw._malloc(nbytes); + if (result === 0) { + throw {message: "malloc() failed", nbytes: nbytes}; + } + return result; + } + + function FREE(pointer) { + that.nacl.nacl_raw._free(pointer); + } + + function free_all(addresses) { + for (var i = 0; i < addresses.length; i++) { + FREE(addresses[i]); + } + } + + function extractBytes(address, length) { + var result = new Uint8Array(length); + result.set(that.nacl.nacl_raw.HEAPU8.subarray(address, address + length)); + return result; + } + + function Target(length) { + this.length = length; + this.address = MALLOC(length); + } + + Target.prototype.extractBytes = function (offset) { + var result = extractBytes(this.address + (offset || 0), this.length - (offset || 0)); + FREE(this.address); + this.address = null; + return result; + }; + + /*-- + end of WORKAROUND + -- */ + } FullJSServiceFactory.prototype = new CryptoAbstractService(); @@ -753,9 +590,9 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) }; this.util.decode_base58 = function(a) { var i; - a = that.base58.decode(a); - var b = new Uint8Array(a.length); - for (i = 0; i < a.length; i++) b[i] = a[i]; + var d = that.base58.decode(a); + var b = new Uint8Array(d.length); + for (i = 0; i < d.length; i++) b[i] = d[i]; return b; }; this.util.decode_base64 = function (a) { @@ -772,6 +609,26 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) that.crypto.getRandomValues(nonce); return $q.when(nonce); }; + this.util.crypto_hash_sha256 = function (message) { + return that.nacl.from_hex(that.sha256(message)); + }; + + this.util.crypto_scrypt = function(password, salt, N, r, p, seedLength) { + var deferred = $q.defer(); + that.nacl.crypto_pwhash_scryptsalsa208sha256_ll( + password, + salt, + N, + r, + p, + seedLength, + function (err, seed) { + if (err) { deferred.reject(err); return;} + deferred.resolve(seed); + } + ); + return deferred.promise; + }; /** * Create key pairs (sign and box), from salt+password (Scrypt), using cordova @@ -812,6 +669,23 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) return deferred.promise; }; + /** + * Create key pairs from a seed + */ + this.seedKeypair = function(seed) { + var deferred = $q.defer(); + + that.nacl.crypto_sign_seed_keypair(seed, function (err, signKeypair) { + if (err) { deferred.reject(err); return;} + deferred.resolve({ + signPk: signKeypair.pk, + signSk: signKeypair.sk + }); + }); + return deferred.promise; + }; + + /** * Get sign PK from salt+password (Scrypt), using cordova */ @@ -885,7 +759,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) * Compute the box key pair, from a sign key pair */ this.box_keypair_from_sign = function(signKeyPair) { - if (signKeyPair.bokSk && signKeyPair.boxPk) return $q.when(signKeyPair); + if (signKeyPair.boxSk && signKeyPair.boxPk) return $q.when(signKeyPair); var deferred = $q.defer(); var result = {}; that.nacl.crypto_sign_ed25519_pk_to_curve25519(signKeyPair.signPk, function(err, boxPk) { @@ -987,6 +861,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) } else { that.nacl = window.plugins.MiniSodium; + var loadedLib = 0; var checkAllLibLoaded = function() { loadedLib++; @@ -1034,17 +909,17 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) ionicReady().then(function() { console.debug('[crypto] Starting...'); - var now = new Date().getTime(); + var now = Date.now(); var serviceImpl; // Use Cordova plugin implementation, when exists if (isDevice && window.plugins && window.plugins.MiniSodium && crypto && crypto.getRandomValues) { - console.debug('[crypto] Loading Cordova MiniSodium implementation...'); + console.debug('[crypto] Loading \'MiniSodium\' implementation...'); serviceImpl = new CordovaServiceFactory(); } else { - console.debug('[crypto] Loading FullJS implementation...'); + console.debug('[crypto] Loading \'FullJS\' implementation...'); serviceImpl = new FullJSServiceFactory(); } @@ -1056,12 +931,651 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) }) .then(function() { service.copy(serviceImpl); - console.debug('[crypto] Loaded \'{0}\' implementation in {1}ms'.format(service.id, new Date().getTime() - now)); + console.debug('[crypto] Loaded \'{0}\' implementation in {1}ms'.format(service.id, Date.now() - now)); }); }); - return service; }]) + + + /* ----------------------------- + Crypto advanced service for Cesium + */ + + .factory('csCrypto', ['$q', '$rootScope', '$timeout', 'CryptoUtils', 'UIUtils', 'Modals', function($q, $rootScope, $timeout, CryptoUtils, UIUtils, Modals) { + 'ngInject'; + + function test(regexpContent) { + return new RegExp(regexpContent); + } + + function xor(a, b) { + var length = Math.max(a.length, b.length); + var buffer = new Uint8Array(length); + for (var i = 0; i < length; ++i) { + buffer[i] = a[i] ^ b[i]; + } + return buffer; + } + + function concat_Uint8Array( buffer1, buffer2 ) { + var tmp = new Uint8Array( buffer1.byteLength + buffer2.byteLength ); + tmp.set( new Uint8Array( buffer1 ), 0 ); + tmp.set( new Uint8Array( buffer2 ), buffer1.byteLength ); + return tmp; + } + + var constants = { + WIF: { + DATA_LENGTH: 35 + }, + EWIF: { + SALT_LENGTH: 4, + DERIVED_HALF_LENGTH: 16, + DATA_LENGTH: 39, + SCRYPT_PARAMS: { + N: 16384, + r: 8, + p: 8 + } + }, + REGEXP: { + PUBKEY: '[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44}', + SECKEY: '[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{86,88}', + FILE: { + TYPE_LINE: '^Type: ([a-zA-Z0-9]+)\n', + VERSION: 'Version: ([0-9]+)\n', + PUB: '[Pp]ub: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44})\n', + SEC: '[Ss]ec: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{86,88})(\n|$)', + DATA: '[Dd]ata: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)(\n|$)' + } + } + }, + regexp = { + FILE: { + TYPE_LINE: test(constants.REGEXP.FILE.TYPE_LINE), + VERSION: test(constants.REGEXP.FILE.VERSION), + PUB: test(constants.REGEXP.FILE.PUB), + SEC: test(constants.REGEXP.FILE.SEC), + DATA: test(constants.REGEXP.FILE.DATA) + } + }, + errorCodes = { + BAD_PASSWORD: 3001, + BAD_CHECKSUM: 3002 + }; + + /* -- keyfile -- */ + + function readKeyFile(file, options) { + + if (file && file.content) { + return parseKeyFileContent(file.content, options); + } + + return $q(function(resolve, reject) { + if (!file) { + return reject('Argument [file] is missing'); + } + + //console.debug('[crypto] [keypair] reading file: ', file); + var reader = new FileReader(); + reader.onload = function (event) { + parseKeyFileContent(event.target.result, options) + .then(resolve) + .catch(reject); + }; + reader.readAsText(file, 'utf8'); + }); + } + + function parseKeyFileContent(content, options) { + + if (!content) return $q.reject('Argument [content] is missing'); + + options = options || {}; + options.withSecret = angular.isDefined(options.withSecret) ? options.withSecret : false; + options.defaultType = options.defaultType || 'PubSec'; + + var matches; + + var typeMatch = regexp.FILE.TYPE_LINE.exec(content); + + // If no Type field: add default type + var type = typeMatch && typeMatch[1]; + if (!type && options.defaultType) { + return parseKeyFileContent('Type: {0}\n{1}'.format(options.defaultType, content), options); + } + + // Type: PubSec + if (type == 'PubSec') { + + // Read Pub field + matches = regexp.FILE.PUB.exec(content); + if (!matches) return $q.reject('Missing [pub] field in file, or invalid public key value'); + var signKeypair = { + signPk: CryptoUtils.base58.decode(matches[1]) + }; + if (!options.withSecret) return $q.resolve(signKeypair); + + // Read Sec field + matches= regexp.FILE.SEC.exec(content); + if (!matches) return $q.reject('Missing [sec] field in file, or invalid secret key value'); + signKeypair.signSk = CryptoUtils.base58.decode(matches[1]); + return $q.resolve(signKeypair); + } + + // Type: WIF or EWIF + else if (type == 'WIF' || type == 'EWIF') { + matches = regexp.FILE.DATA.exec(content); + if (!matches) { + return $q.reject('Missing [Data] field in file. This is required for WIF or EWIF format'); + } + + return parseWIF_or_EWIF(matches[1], { + type: type, + password: options.password + }) + .then(function(signKeypair) { + return signKeypair && !options.withSecret ? {signPk: signKeypair.signPk} : signKeypair; + }); + } + + // Type: unknown + if (options.defaultType) { + return $q.reject('Bad file format: missing Type field'); + } + else { + return $q.reject('Bad file format, unknown type [' + type + ']'); + } + } + + + /** + * + * @param data_base58 + * @param options + * @returns {*} + */ + function parseWIF_or_EWIF(data_base58, options) { + options = options || {}; + + var data_int8 = data_base58 && CryptoUtils.base58.decode(data_base58); + if (!data_int8 || data_int8.length != constants.EWIF.DATA_LENGTH && data_int8.length != constants.WIF.DATA_LENGTH) { + return $q.reject('Invalid WIF or EWIF format (invalid bytes count).'); + } + + // Detect the type from the first byte + options.type = options.type || (data_int8[0] == 1 && 'WIF') || (data_int8[0] == 2 && 'EWIF'); + + // Type: WIF + if (options.type == 'WIF') { + return parseWIF_v1(data_base58); + } + + // Type: EWIF + if (options.type == 'EWIF') { + + // If not set, resolve password using the given callback + if (typeof options.password == "function") { + //console.debug("[crypto] [EWIF] Executing 'options.password()' to resolve the password..."); + options.password = options.password(); + if (!options.password) { + return $q.reject({message: "Invalid callback result for 'options.password()': must return a promise or a string."}); + } + } + + // If password is a promise, get the result then read data + if (typeof options.password === "object" && options.password.then) { + return options.password.then(function(password) { + if (!password) throw 'CANCELLED'; + return parseEWIF_v1(data_base58, password); + }); + } + + // If password is a valid string, read data + if (typeof options.password == "string") { + return parseEWIF_v1(data_base58, options.password); + } + + return $q.reject({message: 'Invalid EWIF options.password. Waiting a callback function, a promise or a string.'}); + } + + // Unknown type + return $q.reject({message: 'Invalid WIF or EWIF format: unknown first byte identifier.'}); + } + + + function parseWIF_v1(wif_base58) { + var wif_int8 = CryptoUtils.util.decode_base58(wif_base58); + + // Check identifier byte = 0x01 + if (wif_int8[0] != 1) { + return $q.reject({message: 'Invalid WIF v1 format: expected [0x01] as first byte'}); + } + + // Check length + if (wif_int8.length != constants.WIF.DATA_LENGTH) { + return $q.reject({message: 'Invalid WIF v1 format: Data must be a '+constants.WIF.DATA_LENGTH+' bytes array, encoded in base 58.'}); + } + + var wif_int8_no_checksum = wif_int8.slice(0, -2), + seed = wif_int8.slice(1, -2), + checksum = wif_int8.slice(-2); + + // Compute expected checksum + var expectedChecksum = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(wif_int8_no_checksum)).slice(0,2); + if (CryptoUtils.util.encode_base58(checksum) != CryptoUtils.util.encode_base58(expectedChecksum)) { + $q.reject({message: 'Invalid WIF format: bad checksum'}); + } + + // Generate keypair from seed + return CryptoUtils.seedKeypair(seed); + } + + function parseEWIF_v1(ewif_base58, password) { + var ewif_int8 = CryptoUtils.util.decode_base58(ewif_base58); + + // Check identifier byte = 0x02 + if (ewif_int8[0] != 2) { + return $q.reject({message: 'Invalid EWIF v1 format: Expected [0x02] as first byte'}); + } + + // Check length + if (ewif_int8.length != constants.EWIF.DATA_LENGTH) { + return $q.reject({message: 'Invalid EWIF v1 format: Expected {0} bytes, encoded in base 58.'.format(constants.EWIF.DATA_LENGTH)}); + } + + var ewif_int8_no_checksum = ewif_int8.slice(0,-2); + var checksum = ewif_int8.slice(-2); + var salt = ewif_int8.slice(1,5); + var encryptedhalf1 = ewif_int8.slice(5,21); + var encryptedhalf2 = ewif_int8.slice(21,37); + + // Retrieve the scrypt_seed + return CryptoUtils.util.crypto_scrypt( + CryptoUtils.util.encode_utf8(password), + salt, + constants.EWIF.SCRYPT_PARAMS.N, + constants.EWIF.SCRYPT_PARAMS.r, + constants.EWIF.SCRYPT_PARAMS.p, + 64) + + // Compute the final seed + .then(function(scrypt_seed) { + + var derivedhalf1 = scrypt_seed.slice(0, 32); + var derivedhalf2 = scrypt_seed.slice(32, 64); + + //AES + var aesEcb = new aesjs.ModeOfOperation.ecb(derivedhalf2); + var decryptedhalf1 = aesEcb.decrypt(encryptedhalf1); + var decryptedhalf2 = aesEcb.decrypt(encryptedhalf2); + + decryptedhalf1 = new Uint8Array(decryptedhalf1); + decryptedhalf2 = new Uint8Array(decryptedhalf2); + + //xor + var seed1 = xor(decryptedhalf1, derivedhalf1.slice(0, 16)); + var seed2 = xor(decryptedhalf2, derivedhalf1.slice(16, 32)); + var seed = concat_Uint8Array(seed1, seed2); + + return seed; + }) + + // Get the keypair, from the seed + .then(CryptoUtils.seedKeypair) + + // Do some controls + .then(function(keypair) { + + // Check salt + var expectedSalt = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(keypair.signPk)).slice(0,4); + if(CryptoUtils.util.encode_base58(salt) !== CryptoUtils.util.encode_base58(expectedSalt)) { + throw {ucode: errorCodes.BAD_PASSWORD, message: 'ACCOUNT.SECURITY.KEYFILE.ERROR.BAD_PASSWORD'}; + } + + // Check checksum + var expectedChecksum = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(ewif_int8_no_checksum)).slice(0,2); + if (CryptoUtils.util.encode_base58(checksum) != CryptoUtils.util.encode_base58(expectedChecksum)) { + throw {ucode: errorCodes.BAD_CHECKSUM, message: 'ACCOUNT.SECURITY.KEYFILE.ERROR.BAD_CHECKSUM'}; + } + + return keypair; + }); + } + + + function wif_v1_from_keypair(keypair) { + + var seed = CryptoUtils.seed_from_signSk(keypair.signSk); + if (!seed || seed.byteLength !== CryptoUtils.constants.SEED_LENGTH) + throw "Bad see format. Expected {0} bytes".format(CryptoUtils.constants.SEED_LENGTH); + + var fi = new Uint8Array(1); + fi[0] = 0x01; + var seed_fi = concat_Uint8Array(fi, seed); + + // checksum + var checksum = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(seed_fi)).slice(0,2); + + var wif_int8 = concat_Uint8Array(seed_fi, checksum); + return $q.when(CryptoUtils.util.encode_base58(wif_int8)); + } + + function ewif_v1_from_keypair(keypair, password) { + + var seed = CryptoUtils.seed_from_signSk(keypair.signSk); + if (!seed || seed.byteLength !== CryptoUtils.constants.SEED_LENGTH) + return $q.reject({message: "Bad see format. Expected {0} bytes".format(CryptoUtils.constants.SEED_LENGTH)}); + + // salt + var salt = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(keypair.signPk)).slice(0,4); + + // scrypt_seed + return CryptoUtils.util.crypto_scrypt( + CryptoUtils.util.encode_utf8(password), + salt, + constants.EWIF.SCRYPT_PARAMS.N, + constants.EWIF.SCRYPT_PARAMS.r, + constants.EWIF.SCRYPT_PARAMS.p, + 64) + .then(function(scrypt_seed) { + var derivedhalf1 = scrypt_seed.slice(0,32); + var derivedhalf2 = scrypt_seed.slice(32,64); + + //XOR & AES + var seed1_xor_derivedhalf1_1 = xor(seed.slice(0,16), derivedhalf1.slice(0,16)); + var seed2_xor_derivedhalf1_2 = xor(seed.slice(16,32), derivedhalf1.slice(16,32)); + + var aesEcb = new aesjs.ModeOfOperation.ecb(derivedhalf2); + var encryptedhalf1 = aesEcb.encrypt(seed1_xor_derivedhalf1_1); + var encryptedhalf2 = aesEcb.encrypt(seed2_xor_derivedhalf1_2); + + encryptedhalf1 = new Uint8Array(encryptedhalf1); + encryptedhalf2 = new Uint8Array(encryptedhalf2); + + // concatenate ewif + var ewif_int8 = new Uint8Array(1); + ewif_int8[0] = 0x02; + ewif_int8 = concat_Uint8Array(ewif_int8,salt); + ewif_int8 = concat_Uint8Array(ewif_int8,encryptedhalf1); + ewif_int8 = concat_Uint8Array(ewif_int8,encryptedhalf2); + + var checksum = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(ewif_int8)).slice(0,2); + ewif_int8 = concat_Uint8Array(ewif_int8,checksum); + + return CryptoUtils.util.encode_base58(ewif_int8); + }); + } + + function generateKeyFileContent(keypair, options) { + options = options || {}; + options.type = options.type || "PubSec"; + + switch(options.type) { + + // PubSec + case "PubSec" : + return $q.resolve( + "Type: PubSec\n" + + "Version: 1\n" + + "pub: " + CryptoUtils.base58.encode(keypair.signPk) + "\n" + + "sec: " + CryptoUtils.base58.encode(keypair.signSk) + "\n"); + + // WIF - v1 + case "WIF" : + return wif_v1_from_keypair(keypair) + .then(function(data) { + return "Type: WIF\n" + + "Version: 1\n" + + "Data: " + data + "\n"; + }); + + // EWIF - v1 + case "EWIF" : + + if (!options.password) return $q.reject({message: 'Missing EWIF options.password.'}); + + // If not set, resolve password using the given callback + if (options.password && typeof options.password == "function") { + console.debug("[crypto] [EWIF] Executing 'options.password()' to resolve the password..."); + options.password = options.password(); + if (!options.password) { + return $q.reject({message: "Invalid callback result for 'options.password()': must return a promise or a string."}); + } + } + + // If password is a promise, get the result then read data + if (options.password && typeof options.password == "object" && options.password.then) { + return options.password.then(function(password) { + if (!password) throw 'CANCELLED'; + // Recursive call, with the string password in options + return generateKeyFileContent(keypair, angular.merge({}, options, {password: password})); + }); + } + + // If password is a valid string, read data + if (options.password && typeof options.password == "string") { + return ewif_v1_from_keypair(keypair, options.password) + .then(function(data) { + return "Type: EWIF\n" + + "Version: 1\n" + + "Data: " + data + "\n"; + }); + } + + return $q.reject({message: 'Invalid EWIF options.password. Waiting a callback function, a promise or a string.'}); + + default: + return $q.reject({message: "Unknown keyfile format: " + options.type}); + } + } + + + + /* -- usefull methods -- */ + + function pkChecksum(pubkey) { + var signPk_int8 = CryptoUtils.util.decode_base58(pubkey); + return CryptoUtils.util.encode_base58(CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(signPk_int8))).substring(0,3); + } + + /* -- box (pack/unpack a record) -- */ + + function getBoxKeypair(keypair) { + if (!keypair) { + throw new Error('Missing keypair'); + } + if (keypair.boxPk && keypair.boxSk) { + return $q.when(keypair); + } + + return $q.all([ + CryptoUtils.box.keypair.skFromSignSk(keypair.signSk), + CryptoUtils.box.keypair.pkFromSignPk(keypair.signPk) + ]) + .then(function(res) { + return { + boxSk: res[0], + boxPk: res[1] + }; + }); + } + + function packRecordFields(record, keypair, recipientFieldName, cypherFieldNames, nonce) { + + recipientFieldName = recipientFieldName || 'recipient'; + if (!record[recipientFieldName]) { + return $q.reject({message:'ES_WALLET.ERROR.RECIPIENT_IS_MANDATORY'}); + } + + cypherFieldNames = cypherFieldNames || 'content'; + if (typeof cypherFieldNames == 'string') { + cypherFieldNames = [cypherFieldNames]; + } + + // Work on a copy, to keep the original record (as it could be use again - fix #382) + record = angular.copy(record); + + // Get recipient + var recipientPk = CryptoUtils.util.decode_base58(record[recipientFieldName]); + + return $q.all([ + getBoxKeypair(keypair), + CryptoUtils.box.keypair.pkFromSignPk(recipientPk), + nonce ? $q.when(nonce) : CryptoUtils.util.random_nonce() + ]) + .then(function(res) { + //var senderSk = res[0]; + var boxKeypair = res[0]; + var senderSk = boxKeypair.boxSk; + var boxRecipientPk = res[1]; + var nonce = res[2]; + + return $q.all( + cypherFieldNames.reduce(function(res, fieldName) { + if (!record[fieldName]) return res; // skip undefined fields + return res.concat( + CryptoUtils.box.pack(record[fieldName], nonce, boxRecipientPk, senderSk) + ); + }, [])) + + .then(function(cypherTexts){ + // Replace field values with cypher texts + var i = 0; + _.forEach(cypherFieldNames, function(cypherFieldName) { + if (!record[cypherFieldName]) { + // Force undefined fields to be present in object + // This is better for ES storage, that always works on lazy update mode + record[cypherFieldName] = null; + } + else { + record[cypherFieldName] = cypherTexts[i++]; + } + }); + + // Set nonce + record.nonce = CryptoUtils.util.encode_base58(nonce); + + return record; + }); + }); + } + + function openRecordFields(records, keypair, issuerFieldName, cypherFieldNames) { + + issuerFieldName = issuerFieldName || 'issuer'; + cypherFieldNames = cypherFieldNames || 'content'; + if (typeof cypherFieldNames == 'string') { + cypherFieldNames = [cypherFieldNames]; + } + + var now = Date.now(); + var issuerBoxPks = {}; // a map used as cache + + var jobs = [getBoxKeypair(keypair)]; + return $q.all(records.reduce(function(jobs, message) { + var issuer = message[issuerFieldName]; + if (!issuer) {throw 'Record has no ' + issuerFieldName;} + if (issuerBoxPks[issuer]) return res; + return jobs.concat( + CryptoUtils.box.keypair.pkFromSignPk(CryptoUtils.util.decode_base58(issuer)) + .then(function(issuerBoxPk) { + issuerBoxPks[issuer] = issuerBoxPk; // fill box pk cache + })); + }, jobs)) + .then(function(res){ + var boxKeypair = res[0]; + return $q.all(records.reduce(function(jobs, record) { + var issuerBoxPk = issuerBoxPks[record[issuerFieldName]]; + var nonce = CryptoUtils.util.decode_base58(record.nonce); + record.valid = true; + + return jobs.concat( + cypherFieldNames.reduce(function(res, cypherFieldName) { + if (!record[cypherFieldName]) return res; + return res.concat(CryptoUtils.box.open(record[cypherFieldName], nonce, issuerBoxPk, boxKeypair.boxSk) + .then(function(text) { + record[cypherFieldName] = text; + }) + .catch(function(err){ + console.error(err); + console.warn('[ES] [crypto] a record may have invalid cypher ' + cypherFieldName); + record.valid = false; + })); + }, [])); + }, [])); + }) + .then(function() { + console.debug('[ES] [crypto] All record decrypted in ' + (Date.now() - now) + 'ms'); + return records; + }); + + } + + function parseKeyFileData(data, options){ + options = options || {}; + options.withSecret = angular.isDefined(options.withSecret) ? options.withSecret : true; + options.silent = angular.isDefined(options.withSecret) ? options.silent : false; + options.password = function() { + return UIUtils.loading.hide(100) + .then(function() { + return Modals.showPassword({ + title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', + subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP', + error: options.error, + scope: options.scope + }); + }) + .then(function(password) { + // Timeout is need to force popup to be hide + return $timeout(function() { + if (password) UIUtils.loading.show(); + return password; + }, 150); + }); + }; + + if (!options.silent) { + UIUtils.loading.show(); + } + + return parseWIF_or_EWIF(data, options) + .then(function(res){ + return res; + }) + .catch(function(err) { + if (err && err === 'CANCELLED') return; + if (err && err.ucode == errorCodes.BAD_PASSWORD) { + // recursive call + return parseKeyFileData(data, {withSecret: options.withSecret, error: 'ACCOUNT.SECURITY.KEYFILE.ERROR.BAD_PASSWORD'}); + } + console.error("[crypto] Unable to parse as WIF or EWIF format: " + (err && err.message || err)); + throw err; // rethrow + }); + } + + // exports + return { + errorCodes: errorCodes, + constants: constants, + // copy CryptoUtils + util: angular.extend({ + pkChecksum: pkChecksum + }, CryptoUtils.util), + keyfile: { + read: readKeyFile, + parseData: parseKeyFileData, + generateContent: generateKeyFileContent + }, + box: { + getKeypair: getBoxKeypair, + pack: packRecordFields, + open: openRecordFields + } + }; + }]) ; diff --git a/assets/www/dist/dist_js/app/services/currency-services.js b/assets/www/dist/dist_js/app/services/currency-services.js index fc91ed7ed0a484b7b736789c923a62fe7fb3d399..6a4389a47db9546854c4588d233f9bc93da33293 100644 --- a/assets/www/dist/dist_js/app/services/currency-services.js +++ b/assets/www/dist/dist_js/app/services/currency-services.js @@ -1,16 +1,22 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) -.factory('csCurrency', ['$rootScope', '$q', '$timeout', 'BMA', 'Api', function($rootScope, $q, $timeout, BMA, Api) { +.factory('csCurrency', ['$rootScope', '$q', '$timeout', 'BMA', 'Api', 'csSettings', function($rootScope, $q, $timeout, BMA, Api, csSettings) { 'ngInject'; - function factory(id, BMA) { + var defaultBMA = BMA; + + function CsCurrency(id, BMA) { + + BMA = BMA || defaultBMA; + var constants = { // Avoid to many call on well known currencies WELL_KNOWN_CURRENCIES: { g1: { - firstBlockTime: 1488987127 + firstBlockTime: 1488987127, + medianTimeOffset: 3600 } } }, @@ -33,6 +39,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) data.cache = {}; data.node = BMA; data.currentUD = null; + data.medianTimeOffset = 0; started = false; startPromise = undefined; api.data.raise.reset(data); @@ -67,6 +74,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) .then(function(res){ data.name = res.currency; data.parameters = res; + data.medianTimeOffset = res.avgGenTime * res.medianTimeBlocks / 2; return res; }); } @@ -97,25 +105,13 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) function loadCurrentUD() { return BMA.blockchain.stats.ud() - .then(function(res){ + .then(function(res) { // Special case for currency init if (!res.result.blocks.length) { data.currentUD = data.parameters ? data.parameters.ud0 : -1; return data.currentUD ; } - else { - var lastBlockWithUD = res.result.blocks[res.result.blocks.length - 1]; - return BMA.blockchain.block({ block: lastBlockWithUD }) - .then(function(block){ - data.currentUD = powBase(block.dividend, block.unitbase); - return data.currentUD; - }) - .catch(function(err) { - console.error("[currency] Unable to load last block with UD, with number {0}".format(lastBlockWithUD)); - data.currentUD = null; - throw err; - }); - } + return _safeLoadCurrentUD(res, res.result.blocks.length - 1); }) .catch(function(err) { data.currentUD = null; @@ -123,6 +119,38 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) }); } + /** + * Load the last UD, with a workaround if last block with UD is not found in the node + * @param res + * @param blockIndex + * @returns {*} + * @private + */ + function _safeLoadCurrentUD(res, blockIndex) { + // Special case for currency init + if (!res.result.blocks.length || blockIndex < 0) { + data.currentUD = data.parameters ? data.parameters.ud0 : -1; + return data.currentUD ; + } + else { + var lastBlockWithUD = res.result.blocks[blockIndex]; + return BMA.blockchain.block({ block: lastBlockWithUD }) + .then(function(block){ + data.currentUD = powBase(block.dividend, block.unitbase); + return data.currentUD; + }) + .catch(function(err) { + console.error("[currency] Unable to load last block with UD, with number {0}".format(lastBlockWithUD)); + if (blockIndex > 0) { + console.error("[currency] Retrying to load UD from a previous block..."); + return _safeLoadCurrentUD(res, blockIndex-1); + } + data.currentUD = null; + throw err; + }); + } + } + function getData() { if (started) { // load only once @@ -152,10 +180,10 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) block.cleanData(); // Remove unused content (arrays...) and keep items count //console.debug('[currency] Received new block', block); - console.debug('[currency] Received new block [' + block.number + '-' + block.hash + ']'); + console.debug('[currency] Received new block {' + block.number + '-' + block.hash + '}'); data.currentBlock = block; - data.currentBlock.receivedAt = new Date().getTime() / 1000; + data.currentBlock.receivedAt = moment().utc().unix(); data.medianTime = block.medianTime; data.membersCount = block.membersCount; @@ -170,14 +198,11 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) } function addListeners() { - // open web socket on block - var wsBlock = BMA.websocket.block(); - wsBlock.on(onBlock); - listeners = [ // Listen if node changed BMA.api.node.on.restart($rootScope, restart, this), - wsBlock.close + // open web socket on block + BMA.websocket.block().onListener(onBlock) ]; } @@ -206,7 +231,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) function start() { console.debug('[currency] Starting...'); - var now = new Date().getTime(); + var now = Date.now(); startPromise = BMA.ready() @@ -217,7 +242,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) .then(function() { addListeners(); - console.debug('[currency] Started in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[currency] Started in ' + (Date.now() - now) + 'ms'); started = true; startPromise = null; @@ -239,22 +264,26 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) return currentBlockField() .then(function(currentBlock) { + + var now = moment().utc().unix(); + if (cache) { - var now = new Date().getTime() / 1000; - if (currentBlock && (currentBlock.receivedAt - now) < 60/*1min*/) { - console.debug('[currency] find current block in cache: use it'); + if (currentBlock && (now - currentBlock.receivedAt) < 60/*1min*/) { + //console.debug('[currency] Use current block #'+ currentBlock.number +' from cache (age='+ (now - currentBlock.receivedAt) + 's)'); return currentBlock; } - // TODO : Should never occured if block event listener works ! - console.warn('[currency] No current block in cache: get it from network'); + if (!currentBlock) { + // Should never occur, if websocket /ws/block works ! + console.warn('[currency] No current block in cache: get it from network. Websocket [/ws/block] may not be started ?'); + } } return BMA.blockchain.current() .catch(function(err){ // Special case for currency init (root block not exists): use fixed values if (err && err.ucode == BMA.errorCodes.NO_CURRENT_BLOCK) { - return {number: 0, hash: BMA.constants.ROOT_BLOCK_HASH, medianTime: Math.trunc(new Date().getTime() / 1000)}; + return {number: 0, hash: BMA.constants.ROOT_BLOCK_HASH, medianTime: moment().utc().unix()}; } throw err; }) @@ -266,6 +295,23 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) }); } + function getLastValidBlock() { + if (csSettings.data.blockValidityWindow <= 0) { + return getCurrent(true); + } + + return getCurrent(true) + .then(function(current) { + var number = current.number - csSettings.data.blockValidityWindow; + return (number > 0) ? BMA.blockchain.block({block: number}) : current; + }); + } + + // Get time in second (UTC - medianTimeOffset) + function getDateNow() { + return moment().utc().unix() - (data.medianTimeOffset || constants.WELL_KNOWN_CURRENCIES.g1.medianTimeOffset); + } + // TODO register new block event, to get new UD value // Register extension points @@ -286,10 +332,16 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) stop: stop, data: data, get: getData, + name: getDataField('name'), parameters: getDataField('parameters'), currentUD: getDataField('currentUD'), + medianTimeOffset: getDataField('medianTimeOffset'), blockchain: { - current: getCurrent + current: getCurrent, + lastValid: getLastValidBlock + }, + date: { + now: getDateNow }, // api extension api: api, @@ -301,7 +353,9 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) }; } - var service = factory('default', BMA); - service.instance = factory; + var service = new CsCurrency('default'); + service.instance = function(id, bma) { + return new CsCurrency(id, bma); + }; return service; }]); diff --git a/assets/www/dist/dist_js/app/services/desktop-services.js b/assets/www/dist/dist_js/app/services/desktop-services.js new file mode 100644 index 0000000000000000000000000000000000000000..f6abda2509adfd7344cd6c540ce65cd988a0ee75 --- /dev/null +++ b/assets/www/dist/dist_js/app/services/desktop-services.js @@ -0,0 +1,11 @@ +var App, nw; + +angular.module('cesium.desktop.services', ['cesium.device.services', 'cesium.settings.services']) + + .factory('csDesktop', ['$rootScope', 'Device', function($rootScope, Device) { + 'ngInject'; + + if (!Device.isDesktop()) return; + + console.info("Starting desktop mode..."); + }]); diff --git a/assets/www/dist/dist_js/app/services/device-services.js b/assets/www/dist/dist_js/app/services/device-services.js index 4de2b903e1cb85f7c3e928ae9db389d81fbe3a3a..d5cf0990a0355aa4563005098fe58befc8647223 100644 --- a/assets/www/dist/dist_js/app/services/device-services.js +++ b/assets/www/dist/dist_js/app/services/device-services.js @@ -82,16 +82,17 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti var deferred = $q.defer(); cordova.plugins.barcodeScanner.scan( function(result) { - console.debug('[device] bar code result', result); if (!result.cancelled) { + console.debug('[device] barcode scanner scan: ' + result.text); deferred.resolve(result.text); // make sure to convert into String } else { + console.debug('[device] barcode scanner scan: CANCELLED'); deferred.resolve(); } }, function(err) { - console.error('[device] Error while using barcode scanner -> ' + err); + console.error('[device] Error while using barcode scanner: ' + err); deferred.reject(err); }, n); @@ -161,12 +162,13 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti }, modelScope); }; + settings.animation = settings.animation || 'pop'; settings.action = settings.action || function(number) { setModelValue((getModelValue() ||'') + number); }; if (settings.decimal) { settings.decimalSeparator = settings.decimalSeparator || '.'; - settings.leftButton = settings.leftButton = { + settings.leftButton = { html: '<span>.</span>', action: function () { var text = getModelValue() || ''; @@ -199,11 +201,15 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti return !!navigator.userAgent.match(/iPhone | iPad | iPod/i) || ionic.Platform.isIOS(); }; + exports.isOSX = function() { + return !!navigator.userAgent.match(/Macintosh/i) || ionic.Platform.is("osx"); + }; + exports.isDesktop = function() { if (!angular.isDefined(cache.isDesktop)) { try { // Should have NodeJs and NW - cache.isDesktop = !exports.enable && !!process && !!App; + cache.isDesktop = !exports.enable && !!process && !!nw && !!nw.App; } catch (err) { cache.isDesktop = false; } @@ -230,7 +236,7 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti if (exports.enable){ exports.camera.enable = !!navigator.camera; exports.keyboard.enable = cordova && cordova.plugins && !!cordova.plugins.Keyboard; - exports.barcode.enable = cordova && cordova.plugins && !!cordova.plugins.barcodeScanner; + exports.barcode.enable = cordova && cordova.plugins && !!cordova.plugins.barcodeScanner && !exports.isOSX(); exports.clipboard.enable = cordova && cordova.plugins && !!cordova.plugins.clipboard; if (exports.keyboard.enable) { diff --git a/assets/www/dist/dist_js/app/services/http-services.js b/assets/www/dist/dist_js/app/services/http-services.js index fde8f3c47cd33845b98442946c7173c94e169b02..f642e967a8f233418ecbb7458d1b7e7d73bd9bc5 100644 --- a/assets/www/dist/dist_js/app/services/http-services.js +++ b/assets/www/dist/dist_js/app/services/http-services.js @@ -7,7 +7,7 @@ angular.module('cesium.http.services', ['cesium.cache.services']) var sockets = [], - cachePrefix = 'csHttp' + cachePrefix = 'csHttp-' ; if (!timeout) { @@ -48,14 +48,14 @@ angular.module('cesium.http.services', ['cesium.cache.services']) function prepare(url, params, config, callback) { var pkeys = [], queryParams = {}, newUri = url; - if (typeof params == 'object') { + if (typeof params === 'object') { pkeys = _.keys(params); } _.forEach(pkeys, function(pkey){ var prevURI = newUri; newUri = newUri.replace(':' + pkey, params[pkey]); - if (prevURI == newUri) { + if (prevURI === newUri) { queryParams[pkey] = params[pkey]; } }); @@ -89,7 +89,7 @@ angular.module('cesium.http.services', ['cesium.cache.services']) }; } - function getResourceWithCache(host, port, path, useSsl, maxAge, autoRefresh, forcedTimeout) { + function getResourceWithCache(host, port, path, useSsl, maxAge, autoRefresh, forcedTimeout, cachePrefix) { var url = getUrl(host, port, path, useSsl); maxAge = maxAge || csCache.constants.LONG; //console.debug('[http] will cache ['+url+'] ' + maxAge + 'ms' + (autoRefresh ? ' with auto-refresh' : '')); @@ -101,11 +101,12 @@ angular.module('cesium.http.services', ['cesium.cache.services']) responseType: 'json' }; if (autoRefresh) { // redo the request if need - config.cache = csCache.get(cachePrefix, maxAge, function (key, value) { + config.cache = csCache.get(cachePrefix, maxAge, function (key, value, done) { console.debug('[http] Refreshing cache for ['+key+'] '); $http.get(key, config) .success(function (data) { config.cache.put(key, data); + if (done) done(key, data); }); }); } @@ -164,11 +165,13 @@ angular.module('cesium.http.services', ['cesium.cache.services']) if (self.delegate.readyState == 3) { return $q.reject('Unable to connect to websocket ['+self.delegate.url+']'); } - console.debug('[http] Waiting websocket ['+self.path+'] opening...'); if (self.waitDuration >= timeout) { - console.debug("[http] Will retry openning websocket later..."); - self.waitRetryDelay = 2000; // 2 seconds + self.waitRetryDelay = self.waitRetryDelay && Math.min(self.waitRetryDelay + 2000, 30000) || 2000; // add 2 seconds, until 30s) + console.debug("[http] Will retry websocket [{0}] in {1}s...".format(self.path, Math.round(self.waitRetryDelay/1000))); + } + else if (Math.round(self.waitDuration / 1000) % 10 === 0){ + console.debug('[http] Waiting websocket ['+self.path+']...'); } return $timeout(function(){ @@ -198,9 +201,9 @@ angular.module('cesium.http.services', ['cesium.cache.services']) self.delegate.onopen = function(e) { console.debug('[http] Listening on websocket ['+self.path+']...'); sockets.push(self); - self.delegate.openTime = new Date().getTime(); + self.delegate.openTime = Date.now(); }; - self.delegate.onclose = function() { + self.delegate.onclose = function(closeEvent) { // Remove from sockets arrays var index = _.findIndex(sockets, function(socket){return socket.path === self.path;}); @@ -215,20 +218,52 @@ angular.module('cesium.http.services', ['cesium.cache.services']) // If unexpected close event, reopen the socket (fix #535) else { - console.debug('[http] Unexpected close of websocket ['+path+'] (open '+ (new Date().getTime() - self.delegate.openTime) +'ms ago): re-opening...'); + if (self.delegate.openTime) { + console.debug('[http] Unexpected close of websocket [{0}] (open {1} ms ago): re-opening...', path, (Date.now() - self.delegate.openTime)); - self.delegate = null; + // Force new connection + self.delegate = null; + + // Loop, but without the already registered callback + _open(self, null, params); + } + else if (closeEvent) { + console.debug('[http] TODO -- Unexpected close of websocket [{0}]: error code: '.format(path), closeEvent); - // Loop, but without the already registered callback - _open(self, null, params); + // Force new connection + self.delegate = null; + + // Loop, but without the already registered callback + _open(self, null, params); + } } }; }); } + if (callback) self.callbacks.push(callback); return _waitOpen(self); } + function _close(self) { + if (self.delegate) { + self.delegate.closing = true; + console.debug('[http] Closing websocket ['+self.path+']...'); + self.delegate.close(); + self.callbacks = []; + if (self.onclose) self.onclose(); + } + } + + function _remove(self, callback) { + self.callbacks = _.reject(self.callbacks, function(item) { + return item === callback; + }); + if (!self.callbacks.length) { + _close(self); + } + } + return { open: function(params) { return _open(this, null, params); @@ -236,21 +271,27 @@ angular.module('cesium.http.services', ['cesium.cache.services']) on: function(callback, params) { return _open(this, callback, params); }, + onListener: function(callback, params) { + var self = this; + _open(self, callback, params); + return function() { + _remove(self, callback); + }; + }, send: function(data) { var self = this; return _waitOpen(self) .then(function(){ - self.delegate.send(data); + if (self.delegate) self.delegate.send(data); }); }, close: function() { var self = this; - if (self.delegate) { - self.delegate.closing = true; - console.debug('[http] Closing websocket ['+self.path+']...'); - self.delegate.close(); - self.callbacks = []; - } + _close(self); + }, + isClosed: function() { + var self = this; + return !self.delegate || self.delegate.closing; } }; } @@ -314,7 +355,18 @@ angular.module('cesium.http.services', ['cesium.cache.services']) uri = parts.protocol + uri; } - // Check if device is enable, on spcial tel: or mailto: protocole + // On desktop, open into external tool + if (parts.protocol == 'mailto:' && Device.isDesktop()) { + try { + nw.Shell.openExternal(uri); + return; + } + catch(err) { + console.error("[http] Failed not open 'mailto:' URI into external tool."); + } + } + + // Check if device is enable, on special tel: or mailto: protocole var validProtocol = (parts.protocol == 'mailto:' || parts.protocol == 'tel:') && Device.enable; if (!validProtocol) { if (options.onError && typeof options.onError == 'function') { @@ -326,24 +378,49 @@ angular.module('cesium.http.services', ['cesium.cache.services']) // Note: If device enable, then target=_system will use InAppBrowser cordova plugin var openTarget = (options.target || (Device.enable ? '_system' : '_blank')); - var openOptions; + + // If desktop, try to open into external browser + if (openTarget === '_blank' || openTarget === '_system' && Device.isDesktop()) { + try { + nw.Shell.openExternal(uri); + return; + } + catch(err) { + console.error("[http] Failed not open URI into external browser."); + } + } + // If desktop, should always open in new window (no tabs) - if (openTarget == '_blank' && Device.isDesktop() && $window.screen && $window.screen.width && $window.screen.height) { - openOptions= "width={0},height={1},location=1,menubar=1,toolbar=1,resizable=1,scrollbars=1".format($window.screen.width/2, $window.screen.height/2); + var openOptions; + if (openTarget === '_blank' && Device.isDesktop()) { + + if (nw && nw.Shell) { + nw.Shell.openExternal(uri); + return false; + } + // Override default options + openOptions= "location=1,titlebar=1,status=1,menubar=1,toolbar=1,resizable=1,scrollbars=1"; + // Add width/height + if ($window.screen && $window.screen.width && $window.screen.height) { + openOptions += ",width={0},height={1}".format(Math.trunc($window.screen.width/2), Math.trunc($window.screen.height/2)); + } } + var win = $window.open(uri, openTarget, openOptions); - if (openOptions) { + + // Center the opened window + if (openOptions && $window.screen && $window.screen.width && $window.screen.height) { win.moveTo($window.screen.width/2/2, $window.screen.height/2/2); win.focus(); } } - // Get time (UTC) + // Get time in second (UTC) function getDateNow() { - return Math.floor(moment().utc().valueOf() / 1000); + return moment().utc().unix(); } function isPositiveInteger(x) { @@ -408,8 +485,7 @@ angular.module('cesium.http.services', ['cesium.cache.services']) } function isVersionCompatible(minVersion, actualVersion) { - // TODO: add implementation - console.debug('[http] TODO: implement check version [{0}] compatible with [{1}]'.format(actualVersion, minVersion)); + console.debug('[http] Checking actual version [{0}] is compatible with min expected version [{1}]'.format(actualVersion, minVersion)); return compareVersionNumbers(minVersion, actualVersion) <= 0; } diff --git a/assets/www/dist/dist_js/app/services/modal-services.js b/assets/www/dist/dist_js/app/services/modal-services.js index 3a91e35044da29ef0db238bd4a98ddd2d153f852..74cd60f36a02289ba2f270c782627dcc796dc833 100644 --- a/assets/www/dist/dist_js/app/services/modal-services.js +++ b/assets/www/dist/dist_js/app/services/modal-services.js @@ -1,4 +1,4 @@ -angular.module('cesium.modal.services', []) +angular.module('cesium.modal.services', ['cesium.utils.services']) // Useful for modal with no controller .controller('EmptyModalCtrl', function () { @@ -21,7 +21,7 @@ angular.module('cesium.modal.services', []) }; }]) -.factory('ModalUtils', ['$ionicModal', '$rootScope', '$q', '$injector', '$controller', '$timeout', function($ionicModal, $rootScope, $q, $injector, $controller, $timeout) { +.factory('ModalUtils', ['$ionicModal', '$rootScope', '$q', '$injector', '$controller', '$timeout', 'Device', function($ionicModal, $rootScope, $q, $injector, $controller, $timeout, Device) { 'ngInject'; @@ -58,8 +58,15 @@ angular.module('cesium.modal.services', []) $scope.closeModal = function (result) { $scope.resolved = true; + + // removeIf(no-device) + if (Device.enable) Device.keyboard.close(); + // endRemoveIf(no-device) + return $scope.modal.remove() .then(function() { + // Workaround modal-open not removed + document.body.classList.remove('modal-open'); $scope.deferred.resolve(result); return result; }); @@ -89,7 +96,10 @@ angular.module('cesium.modal.services', []) $timeout(function() { $scope.deferred.resolve(); - return $scope.modal.remove(); + return $scope.modal.remove().then(function() { + // Workaround modal-open not removed + document.body.classList.remove('modal-open'); + }); }, ($scope.modal.hideDelay || 320) + 20); } }); @@ -101,6 +111,9 @@ angular.module('cesium.modal.services', []) options = options ? options : {} ; options.animation = options.animation || 'slide-in-up'; + var focusFirstInput = false; + options.focusFirstInput = focusFirstInput; + // If modal has a controller if (controller) { // If a controller defined, always use a new scope @@ -146,7 +159,7 @@ angular.module('cesium.modal.services', []) }; }]) -.factory('Modals', ['$rootScope', '$translate', '$ionicPopup', 'ModalUtils', 'UIUtils', function($rootScope, $translate, $ionicPopup, ModalUtils, UIUtils) { +.factory('Modals', ['$rootScope', '$translate', '$ionicPopup', '$timeout', 'ModalUtils', 'UIUtils', function($rootScope, $translate, $ionicPopup, $timeout, ModalUtils, UIUtils) { 'ngInject'; function showTransfer(parameters) { @@ -159,15 +172,9 @@ angular.module('cesium.modal.services', []) function showLogin(parameters) { return ModalUtils.show('templates/login/modal_login.html','LoginModalCtrl', - parameters, {focusFirstInput: true}); - } - - function showAdvancedLogin(parameters) { - return ModalUtils.show('templates/login/modal_advanced_login.html','LoginModalCtrl', - parameters, {focusFirstInput: true}); + parameters, {focusFirstInput: true, backdropClickToClose: false}); } - function showWotLookup(parameters) { return ModalUtils.show('templates/wot/modal_lookup.html','WotLookupModalCtrl', parameters || {}, {focusFirstInput: true}); @@ -224,6 +231,11 @@ angular.module('cesium.modal.services', []) parameters); } + function showSelectWallet(parameters) { + return ModalUtils.show('templates/wallet/list/modal_wallets.html','WalletSelectModalCtrl', + parameters); + } + function showPassword(options) { options = options || {}; options.title = options.title || 'COMMON.SET_PASSWORD_TITLE'; @@ -235,14 +247,14 @@ angular.module('cesium.modal.services', []) }; scope.submit = function(e) { scope.form.$submitted=true; - if(!scope.form.$valid || !scope.formData.password) { - //don't allow the user to close unless he enters a uid - if (e && e.preventDefault) e.preventDefault(); - } else { + if (e && e.preventDefault) e.preventDefault(); + if(scope.form.$valid && scope.formData.password) { options.popup.close(scope.formData.password); } }; + scope.error = options.error || undefined; + // Choose password popup return $translate([options.title, options.subTitle, 'COMMON.BTN_OK', 'COMMON.BTN_CANCEL']) .then(function (translations) { @@ -264,11 +276,9 @@ angular.module('cesium.modal.services', []) } - return { showTransfer: showTransfer, showLogin: showLogin, - showAdvancedLogin: showAdvancedLogin, showWotLookup: showWotLookup, showNetworkLookup: showNetworkLookup, showAbout: showAbout, @@ -279,7 +289,51 @@ angular.module('cesium.modal.services', []) showAccountSecurity: showAccountSecurity, showLicense: showLicense, showSelectPubkeyIdentity: showSelectPubkeyIdentity, + showSelectWallet: showSelectWallet, showPassword: showPassword }; -}]); +}]) + +.factory('csPopovers', ['$rootScope', '$translate', '$ionicPopup', '$timeout', 'UIUtils', '$controller', function($rootScope, $translate, $ionicPopup, $timeout, UIUtils, $controller) { + 'ngInject'; + + function showSelectWallet(event, options) { + options = options || {}; + + var parameters = options.parameters || {}; + delete options.parameters; + + var scope = options.scope && options.scope.$new() || $rootScope.$new(true); + options.scope = scope; + options.templateUrl = 'templates/wallet/list/popover_wallets.html'; + options.autoremove = true; + + // Initialize the popover controller, with parameters + angular.extend(this, $controller('WalletSelectPopoverCtrl', {$scope: options.scope, parameters: parameters})); + + var afterShowSaved = options.afterShow; + options.afterShow = function(popover) { + + // Add a missing method, to close the popover + scope.closePopover = function(res) { + popover.scope.closePopover(res); + }; + + // Execute default afterShow fn, if any + if (afterShowSaved) afterShowSaved(popover); + }; + // Show the popover + return UIUtils.popover.show(event, options) + .then(function(res) { + // Then destroy the scope + scope.$destroy(); + return res; + }); + } + + return { + showSelectWallet: showSelectWallet + }; + + }]); diff --git a/assets/www/dist/dist_js/app/services/network-services.js b/assets/www/dist/dist_js/app/services/network-services.js index 5f2c79e2bdc36b4cfe6913b4358491ecc738cee9..c6692a70536482537b888ac35ef8775348ad48d9 100644 --- a/assets/www/dist/dist_js/app/services/network-services.js +++ b/assets/www/dist/dist_js/app/services/network-services.js @@ -1,39 +1,44 @@ -angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesium.http.services']) +angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services', 'cesium.http.services']) -.factory('csNetwork', ['$rootScope', '$q', '$interval', '$timeout', '$window', 'csConfig', 'BMA', 'csHttp', 'Api', function($rootScope, $q, $interval, $timeout, $window, csConfig, BMA, csHttp, Api) { +.factory('csNetwork', ['$rootScope', '$q', '$interval', '$timeout', '$window', 'csConfig', 'BMA', 'csHttp', 'csCurrency', 'Api', function($rootScope, $q, $interval, $timeout, $window, csConfig, BMA, csHttp, csCurrency, Api) { 'ngInject'; - factory = function(id) { + function CsNetwork(id) { var interval, constants = { - UNKNOWN_BUID: -1 + UNKNOWN_BUID: -1, + MAX_BLOCK_OFFSET: 1000 }, isHttpsMode = $window.location.protocol === 'https:', api = new Api(this, "csNetwork-" + id), data = { bma: null, - websockets: [], + listeners: [], loading: true, peers: [], filter: { member: true, mirror: true, - endpointFilter: null, + endpoint: null, online: false, + bma: false, ssl: undefined, tor: undefined }, sort:{ type: null, - asc: true + asc: true, + compact: true }, + groupBy: 'pubkey', expertMode: false, knownBlocks: [], mainBlock: null, + minOnlineBlockNumber: 0, uidsByPubkeys: null, searchingPeersOnNetwork: false, difficulties: null, @@ -48,22 +53,27 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi resetData = function() { data.bma = null; - data.websockets = []; + data.listeners = []; data.peers.splice(0); data.filter = { member: true, mirror: true, - endpointFilter: null, - online: true + endpoint: null, + online: true, + bma: false, + ssl: undefined, + tor: undefined }; data.sort = { type: null, asc: true }; + data.groupBy = 'pubkey'; data.expertMode = false; data.memberPeersCount = 0; data.knownBlocks = []; data.mainBlock = null; + data.minOnlineBlockNumber = 0; data.uidsByPubkeys = {}; data.loading = true; data.searchingPeersOnNetwork = false; @@ -172,8 +182,8 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi data.uidsByPubkeys = uids; }) .catch(function(err) { + console.error(err); data.uidsByPubkeys = {}; - //throw err; }), // Load WS2P heads @@ -186,99 +196,96 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi } return $q.all(initJobs) - .then(function(){ - // online nodes + .then(function() { + return data.bma.network.peers(); + }) + .then(function(res){ + if (!res || !res.peers || !res.peers.length) return; + + // If filter online peers if (data.filter.online) { - /*return data.bma.network.peering.peers({leaves: true}) - .then(function(res){ - return $q.all(res.leaves.map(function(leaf) { - return data.bma.network.peering.peers({ leaf: leaf }) - .then(function(subres){ - return addOrRefreshPeerFromJson(subres.leaf.value, newPeers); - }); - })); - });*/ - return data.bma.network.peers() - .then(function(res){ - var jobs = []; - _.forEach(res.peers, function(json) { - if (json.status == 'UP') { - jobs.push(addOrRefreshPeerFromJson(json, newPeers)); - - // Mark WS2P - _.forEach(json.endpoints||[], function(ep) { - if (ep.startsWith('WS2P')) { - var key = json.pubkey + '-' + ep.split(' ')[1]; - if (data.ws2pHeads[key]) { - data.ws2pHeads[key].hasEndpoint = true; - } - } - }); - } - }); - - // Add private WS2P endpoints - var privateWs2pHeads = _.values(data.ws2pHeads); - if (privateWs2pHeads && privateWs2pHeads.length) { - var privateEPCount = 0; - //console.debug("[http] Found WS2P endpoints without endpoint:", data.ws2pHeads); - _.forEach(privateWs2pHeads, function(head) { - if (!head.hasEndPoint) { - var peer = new Peer({ - buid: head.buid, - currentNumber: head.buid && head.buid.split('-')[0], - pubkey: head.pubkey, - version: head.version, - powPrefix: head.powPrefix, - online: true, - uid: data.uidsByPubkeys[head.pubkey], - bma: { - useWs2p: true, - private: true, - ws2pid: head.ws2pid - }, - endpoints: [ - // fake endpoint - 'WS2P ' + head.ws2pid - ] - }); - peer.id = peer.keyID(); - if (peer.uid && data.expertMode && data.difficulties) { - peer.difficulty = data.difficulties[peer.uid]; - } - if (applyPeerFilter(peer)) { - newPeers.push(peer); - privateEPCount++; - } - } - }); + var jobs = []; + _.forEach(res.peers, function(json) { + // Exclude, if not UP or on a too old block + if (json.status !== 'UP') return; + json.blockNumber = json.block && parseInt(json.block.split('-')[0]); + if (json.blockNumber && json.blockNumber < data.minOnlineBlockNumber) { + console.debug("[network] Exclude a too old peer document, on pubkey {0}".format(json.pubkey.substring(0,6))); + return; + } + + jobs.push(addOrRefreshPeerFromJson(json, newPeers)); - if (privateEPCount) { - console.debug("[http] Found {0} WS2P endpoints without endpoint (private ?)".format(privateEPCount)); + // Mark WS2P + _.forEach(json.endpoints||[], function(ep) { + if (ep.startsWith('WS2P')) { + var key = json.pubkey + '-' + ep.split(' ')[1]; + if (data.ws2pHeads[key]) { + data.ws2pHeads[key].hasEndpoint = true; } } - - if (jobs.length) return $q.all(jobs); - }) - .catch(function(err) { - // Log and continue - console.error(err); }); - } + }); - // offline nodes - return data.bma.network.peers() - .then(function(res){ - var jobs = []; - _.forEach(res.peers, function(json) { - if (json.status !== 'UP') { - jobs.push(addOrRefreshPeerFromJson(json, newPeers)); + // Add private WS2P endpoints + var privateWs2pHeads = _.values(data.ws2pHeads); + if (privateWs2pHeads && privateWs2pHeads.length) { + var privateEPCount = 0; + //console.debug("[http] Found WS2P endpoints without endpoint:", data.ws2pHeads); + _.forEach(privateWs2pHeads, function(head) { + + if (!head.hasEndPoint) { + var currentNumber = head.buid && parseInt(head.buid.split('-')[0]); + // Exclude if on a too old block + if (currentNumber && currentNumber < data.minOnlineBlockNumber) { + console.debug("[network] Exclude a too old WS2P message, on pubkey {0}".format(head.pubkey.substring(0,6))); + return; + } + + var peer = new Peer({ + buid: head.buid, + currentNumber: currentNumber, + pubkey: head.pubkey, + version: head.version, + powPrefix: head.powPrefix, + online: true, + uid: data.uidsByPubkeys[head.pubkey], + bma: { + useWs2p: true, + private: true, + ws2pid: head.ws2pid + }, + endpoints: [ + // fake endpoint + 'WS2P ' + head.ws2pid + ] + }); + peer.id = peer.keyID(); + if (peer.uid && data.expertMode && data.difficulties) { + peer.difficulty = data.difficulties[peer.uid]; + } + if (applyPeerFilter(peer)) { + newPeers.push(peer); + privateEPCount++; + } } }); - if (jobs.length) return $q.all(jobs); - }); - }) + if (privateEPCount) { + console.debug("[http] Found {0} WS2P endpoints without endpoint (private ?)".format(privateEPCount)); + } + } + + if (jobs.length) return $q.all(jobs); + } + + // If filter offline peers + else { + return $q.all(_(res && res.peers || []).reduce(function(res, json) { + return res.concat(addOrRefreshPeerFromJson(json, newPeers)); + }, [])); + } + }) .then(function(){ data.searchingPeersOnNetwork = false; }) @@ -301,13 +308,23 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi return false; } - // Filter on endpoints - if (data.filter.endpointFilter && !peer.hasEndpoint(data.filter.endpointFilter)) { + // Filter on endpoint + if (data.filter.endpoint && !peer.hasEndpoint(data.filter.endpoint)) { return false; } // Filter on status - if (!data.filter.online && peer.status == 'UP') { + if ((data.filter.online && peer.status !== 'UP' && peer.oldBlock) || (!data.filter.online && peer.status === 'UP' && !peer.oldBlock)) { + return false; + } + + // Filter on bma + if (angular.isDefined(data.filter.bma) && peer.isBma() != data.filter.bma) { + return false; + } + + // Filter on ws2p + if (angular.isDefined(data.filter.ws2p) && peer.isWs2p() != data.filter.ws2p) { return false; } @@ -327,6 +344,10 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi addOrRefreshPeerFromJson = function(json, list) { list = list || data.newPeers; + // Analyze the peer document, and exclude using the online filter + json.blockNumber = json.block && parseInt(json.block.split('-')[0]); + json.oldBlock = (json.status === 'UP' && json.blockNumber && json.blockNumber < data.minOnlineBlockNumber); + var peers = createPeerEntities(json); var hasUpdates = false; @@ -347,26 +368,26 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi } else if (refreshedPeer.buid !== existingMainBuid){ console.debug('[network] {0} endpoint [{1}] new current block'.format( - refreshedPeer.bma.useBma ? 'BMA' : 'WS2P', + refreshedPeer.bma && (refreshedPeer.bma.useBma ? 'BMA' : 'WS2P') || 'null', refreshedPeer.server)); hasUpdates = true; } else if (existingOnline !== refreshedPeer.online){ console.debug('[network] {0} endpoint [{1}] is now {2}'.format( - refreshedPeer.bma.useBma ? 'BMA' : 'WS2P', + refreshedPeer.bma && (refreshedPeer.bma.useBma ? 'BMA' : 'WS2P') || 'null', refreshedPeer.server, refreshedPeer.online ? 'UP' : 'DOWN')); hasUpdates = true; } else { console.debug("[network] {0} endpoint [{1}] unchanged".format( - refreshedPeer.bma.useBma ? 'BMA' : 'WS2P', + refreshedPeer.bma && (refreshedPeer.bma.useBma ? 'BMA' : 'WS2P') || 'null', refreshedPeer.server)); } } else if (refreshedPeer && (refreshedPeer.online === data.filter.online || data.filter.online === 'all')) { console.debug("[network] {0} endpoint [{1}] is {2}".format( - refreshedPeer.bma.useBma ? 'BMA' : 'WS2P', + refreshedPeer.bma && (refreshedPeer.bma.useBma ? 'BMA' : 'WS2P') || 'null', refreshedPeer.server, refreshedPeer.online ? 'UP' : 'DOWN' )); @@ -402,15 +423,17 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi return res.concat(createPeerEntities(json, ep)); }, []); } - - // if only one bma endpoint: use it and continue - ep = endpoints[0]; + else { + // if only one endpoint: use it and continue + ep = endpoints[0]; + } } peer.bma = ep; peer.server = peer.getServer(); peer.dns = peer.getDns(); - peer.blockNumber = peer.block.replace(/-.+$/, ''); - peer.uid = data.uidsByPubkeys[peer.pubkey]; + peer.buid = peer.buid || peer.block; + peer.blockNumber = peer.buid && parseInt(peer.buid.split('-')[0]); + peer.uid = peer.pubkey && data.uidsByPubkeys[peer.pubkey]; peer.id = peer.keyID(); return [peer]; }, @@ -420,7 +443,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi // Apply filter if (!applyPeerFilter(peer)) return $q.when(); - if (!data.filter.online || (data.filter.online === 'all' && peer.status === 'DOWN') || !peer.getHost() /*fix #537*/) { + if (!data.filter.online || (!data.filter.online && peer.status === 'DOWN') || !peer.getHost() /*fix #537*/) { peer.online = false; return $q.when(peer); } @@ -431,7 +454,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi delete data.ws2pHeads[ws2pHeadKey]; if (head) { peer.buid = head.buid; - peer.currentNumber=peer.buid && peer.buid.split('-')[0]; + peer.currentNumber=head.buid && parseInt(head.buid.split('-')[0]); peer.version = head.version; peer.powPrefix = head.powPrefix; } @@ -459,7 +482,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi // Do not try to access TOR or WS2P endpoints if (peer.bma.useTor || peer.bma.useWs2p) { - peer.online = (peer.status == 'UP'); + peer.online = (peer.status === 'UP'); peer.buid = constants.UNKNOWN_BUID; delete peer.version; @@ -493,7 +516,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi } if (!peer.secondTry) { var bma = peer.bma || peer.getBMA(); - if (bma.dns && peer.server.indexOf(bma.dns) == -1) { + if (bma.dns && peer.server.indexOf(bma.dns) === -1) { // try again, using DNS instead of IPv4 / IPV6 peer.secondTry = true; peer.api = BMA.lightInstance(bma.dns, bma.port, bma.useSsl); @@ -501,9 +524,10 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi } } - peer.online=false; - peer.currentNumber = null; peer.buid = null; + peer.blockNumber = null; + peer.currentNumber = null; + peer.online=false; peer.uid = data.uidsByPubkeys[peer.pubkey]; return peer; }) @@ -526,9 +550,11 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi // Get Version jobs.push(peer.api.node.summary() .then(function(res){ - peer.version = res && res.duniter && res.duniter.version; + peer.software = res && res.duniter && res.duniter.software || undefined; + peer.version = res && res.duniter && res.duniter.version || '?'; }) .catch(function() { + peer.software = undefined; peer.version = '?'; // continue })); @@ -585,8 +611,8 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi if (!buid || !buid.medianTime) { buid = { buid: peer.buid, - count: 0, - medianTime: peer.medianTime + medianTime: peer.medianTime, + count: 0 }; buids[peer.buid] = buid; } @@ -594,42 +620,44 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi else if (!buid.medianTime && peer.medianTime) { buid.medianTime = peer.medianTime; } - if (buid.buid != constants.UNKNOWN_BUID) { + if (buid.buid !== constants.UNKNOWN_BUID) { buid.count++; } } data.memberPeersCount += peer.uid ? 1 : 0; }); - // Compute pct of use, per buid - _.forEach(_.values(buids), function(buid) { - buid.pct = buid.count * 100 / data.peers.length; - }); - var mainBlock = _.max(buids, function(obj) { - return obj.count; - }); - _.forEach(data.peers, function(peer){ - peer.hasMainConsensusBlock = peer.buid == mainBlock.buid; - peer.hasConsensusBlock = peer.buid && !peer.hasMainConsensusBlock && buids[peer.buid].count > 1; - if (peer.hasConsensusBlock) { - peer.consensusBlockDelta = buids[peer.buid].medianTime - mainBlock.medianTime; - } - }); + var mainBlock = data.mainBlock; + if (data.filter.online) { + // Compute pct of use, per buid + _.forEach(_.values(buids), function(buid) { + buid.pct = buid.count * 100 / data.peers.length; + }); + mainBlock = _.max(buids, function(obj) { + return obj.count; + }); + _.forEach(data.peers, function(peer){ + peer.hasMainConsensusBlock = peer.buid === mainBlock.buid; + peer.hasConsensusBlock = peer.buid && !peer.hasMainConsensusBlock && buids[peer.buid].count > 1; + if (peer.hasConsensusBlock) { + peer.consensusBlockDelta = buids[peer.buid].medianTime - mainBlock.medianTime; + } + }); + } data.peers = _.uniq(data.peers, false, function(peer) { return peer.id; }); data.peers = _.sortBy(data.peers, function(peer) { var score = 0; if (data.sort.type) { - var sortScore = 0; - sortScore += (data.sort.type == 'uid' ? computeScoreAlphaValue(peer.uid||peer.pubkey, 3, data.sort.asc) : 0); - sortScore += (data.sort.type == 'api') && + score += (data.sort.type === 'uid' ? computeScoreAlphaValue(peer.uid||peer.pubkey, 3, data.sort.asc) : 0); + score += (data.sort.type === 'api') && ((peer.isWs2p() && (data.sort.asc ? 1 : -1) || 0) + (peer.hasEndpoint('ES_USER_API') && (data.sort.asc ? 0.01 : -0.01) || 0) + (peer.isSsl() && (data.sort.asc ? 0.75 : -0.75) || 0)) || 0; - sortScore += (data.sort.type == 'difficulty' ? (peer.difficulty ? (data.sort.asc ? (10000-peer.difficulty) : peer.difficulty): 0) : 0); - sortScore += (data.sort.type == 'current_block' ? (peer.currentNumber ? (data.sort.asc ? (1000000000 - peer.currentNumber) : peer.currentNumber) : 0) : 0); - score += (10000000000 * sortScore); + score += (data.sort.type === 'difficulty' ? (peer.difficulty ? (data.sort.asc ? (10000-peer.difficulty) : peer.difficulty): 0) : 0); + score += (data.sort.type === 'current_block' ? (peer.currentNumber ? (data.sort.asc ? (1000000000 - peer.currentNumber) : peer.currentNumber) : 0) : 0); } + score = (10000000000 * score); score += (1000000000 * (peer.online ? 1 : 0)); score += (100000000 * (peer.hasMainConsensusBlock ? 1 : 0)); score += (1000000 * (peer.hasConsensusBlock ? buids[peer.buid].pct : 0)); @@ -641,9 +669,18 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi score += (100 * (peer.uid ? computeScoreAlphaValue(peer.uid, 2, true) : 0)); score += (1 * (!peer.uid ? computeScoreAlphaValue(peer.pubkey, 2, true) : 0)); } + score += (peer.isBma() ? (peer.isSsl() ? 0.01 : 0.001) :0); // If many endpoints: BMAS first, then BMA return -score; }); + if (data.groupBy) { + var previousPeer; + data.peers.forEach(function(peer) { + peer.compacted = (previousPeer && peer[data.groupBy] && peer[data.groupBy] === previousPeer[data.groupBy]); + previousPeer = peer; + }); + } + // Raise event on new main block if (updateMainBuid && mainBlock.buid && (!data.mainBlock || data.mainBlock.buid !== mainBlock.buid)) { data.mainBlock = mainBlock; @@ -654,46 +691,53 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi api.data.raise.changed(data); // raise event }, - startListeningOnSocket = function() { - // Listen for new block - var wsBlock = data.bma.websocket.block(); - data.websockets.push(wsBlock); - wsBlock.on(function(block) { - if (!block || data.loading) return; - var buid = [block.number, block.hash].join('-'); - if (data.knownBlocks.indexOf(buid) === -1) { - console.debug('[network] Receiving block: ' + buid.substring(0, 20)); - data.knownBlocks.push(buid); - // If first block: do NOT refresh peers (will be done in start() method) - var skipRefreshPeers = data.knownBlocks.length === 1; - if (!skipRefreshPeers) { - data.loading = true; - // We wait 2s when a new block is received, just to wait for network propagation - $timeout(function() { - console.debug('[network] new block received by WS: will refresh peers'); - loadPeers(); - }, 2000, false /*invokeApply*/); - } - } + removeListeners = function() { + _.forEach(data.listeners, function(remove){ + remove(); }); - // Listen for new peer - var wsPeer = data.bma.websocket.peer(); - data.websockets.push(wsPeer); - wsPeer.on(function(json) { - if (!json || data.loading) return; - var newPeers = []; - addOrRefreshPeerFromJson(json, newPeers) - .then(function(hasUpdates) { - if (!hasUpdates) return; - if (newPeers.length>0) { - flushNewPeersAndSort(newPeers, true); - } - else { - console.debug('[network] [ws] Peers updated received'); - sortPeers(true); + data.listeners = []; + }, + + addListeners = function() { + data.listeners = [ + + // Listen for new block + data.bma.websocket.block().onListener(function(block) { + if (!block || data.loading) return; + var buid = [block.number, block.hash].join('-'); + if (data.knownBlocks.indexOf(buid) === -1) { + console.debug('[network] Receiving block: ' + buid.substring(0, 20)); + data.knownBlocks.push(buid); + // If first block: do NOT refresh peers (will be done in start() method) + var skipRefreshPeers = data.knownBlocks.length === 1; + if (!skipRefreshPeers) { + data.loading = true; + // We wait 2s when a new block is received, just to wait for network propagation + $timeout(function() { + console.debug('[network] new block received by WS: will refresh peers'); + loadPeers(); + }, 2000, false /*invokeApply*/); } - }); - }); + } + }), + + // Listen for new peer + data.bma.websocket.peer().onListener(function(json) { + if (!json || data.loading) return; + var newPeers = []; + addOrRefreshPeerFromJson(json, newPeers) + .then(function(hasUpdates) { + if (!hasUpdates) return; + if (newPeers.length>0) { + flushNewPeersAndSort(newPeers, true); + } + else { + console.debug('[network] [ws] Peers updated received'); + sortPeers(true); + } + }); + }) + ]; }, sort = function(options) { @@ -708,19 +752,31 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi return BMA.ready() .then(function() { close(); + data.bma = bma ? bma : BMA; data.filter = options.filter ? angular.merge(data.filter, options.filter) : data.filter; data.sort = options.sort ? angular.merge(data.sort, options.sort) : data.sort; data.expertMode = angular.isDefined(options.expertMode) ? options.expertMode : data.expertMode; data.timeout = angular.isDefined(options.timeout) ? options.timeout : csConfig.timeout; + + // Init a min block number + data.minOnlineBlockNumber = data.mainBlock && data.mainBlock.buid && (parseInt(data.mainBlock.buid.split('-')[0]) - constants.MAX_BLOCK_OFFSET) || undefined; + if (data.minOnlineBlockNumber === undefined) { + return csCurrency.blockchain.current(true/*use cache*/) + .then(function(current) { + data.minOnlineBlockNumber = current.number - constants.MAX_BLOCK_OFFSET; + }); + } + }) + .then(function() { console.info('[network] Starting network from [{0}]'.format(bma.server)); - var now = new Date(); + var now = Date.now(); - startListeningOnSocket(); + addListeners(); return loadPeers() .then(function(peers){ - console.debug('[network] Started in '+(new Date().getTime() - now.getTime())+'ms'); + console.debug('[network] Started in '+(Date.now() - now)+'ms'); return peers; }); }); @@ -728,11 +784,8 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi close = function() { if (data.bma) { - console.info('[network] Stopping'); - - _.forEach(data.websockets, function(ws){ - ws.close(); - }); + console.info('[network-service] Stopping...'); + removeListeners(); resetData(); } }, @@ -790,10 +843,13 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi // api extension api: api }; - }; + } - var service = factory('default'); + var service = new CsNetwork('default'); + + service.instance = function(id) { + return new CsNetwork(id); + }; - service.instance = factory; return service; }]); diff --git a/assets/www/dist/dist_js/app/services/settings-services.js b/assets/www/dist/dist_js/app/services/settings-services.js index 5922f86f0341b743b07be2a03859d929364501a1..61c0a22d613c8a735026c6ec36f2dae700d69865 100644 --- a/assets/www/dist/dist_js/app/services/settings-services.js +++ b/assets/www/dist/dist_js/app/services/settings-services.js @@ -6,11 +6,13 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) // Define app locales var locales = [ - {id:'en', label:'English'}, - {id:'en-GB', label:'English (UK)'}, - {id:'fr-FR', label:'Français'}, - {id:'nl-NL', label:'Nederlands'}, - {id:'es-ES', label:'Spanish'} + {id:'en', label:'English', country: 'us'}, + {id:'en-GB', label:'English (UK)', country: 'gb'}, + {id:'eo-EO', label:'Esperanto'}, + {id:'fr-FR', label:'Français' , country: 'fr'}, + {id:'nl-NL', label:'Nederlands', country: 'nl'}, + {id:'es-ES', label:'Spanish', country: 'es'}, + {id:'it-IT', label:'Italiano', country: 'it'} ]; var fallbackLocale = csConfig.fallbackLanguage ? fixLocale(csConfig.fallbackLanguage) : 'en'; @@ -21,7 +23,7 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) // exists in app locales: use it if (_.findWhere(locales, {id: locale})) return locale; - // not exists: reiterate with the root(e.g. 'fr-XX' -> 'fr') + // not exists: reiterate with the root (e.g. 'fr-XX' -> 'fr') var localeParts = locale.split('-'); if (localeParts.length > 1) { return fixLocale(localeParts[0]); @@ -47,30 +49,36 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) var constants = { - STORAGE_KEY: 'CESIUM_SETTINGS', + STORAGE_KEY: 'settings', // for version >= v1.1.0 KEEP_AUTH_IDLE_SESSION: 9999 }, - defaultSettings = angular.merge({ + // Settings that user cannot change himself (only config can override this values) + fixedSettings = { timeout : 4000, cacheTimeMs: 60000, /*1 min*/ - useRelative: false, timeWarningExpireMembership: 2592000 * 2 /*=2 mois*/, timeWarningExpire: 2592000 * 3 /*=3 mois*/, + minVersion: '1.1.0', + newIssueUrl: "https://git.duniter.org/clients/cesium-grp/cesium/issues/new", + userForumUrl: "https://forum.monnaie-libre.fr", + latestReleaseUrl: "https://api.github.com/repos/duniter/cesium/releases/latest", + duniterLatestReleaseUrl: "https://api.github.com/repos/duniter/duniter/releases/latest", + httpsMode: false + }, + defaultSettings = angular.merge({ + useRelative: false, useLocalStorage: true, // override to false if no device + useLocalStorageEncryption: false, walletHistoryTimeSecond: 30 * 24 * 60 * 60 /*30 days*/, walletHistorySliceSecond: 5 * 24 * 60 * 60 /*download using 5 days slice*/, + walletHistoryAutoRefresh: true, // override to false if device rememberMe: true, - keepAuthIdle: 10 * 60, // 10min - override to false if no device + keepAuthIdle: 10 * 60, showUDHistory: true, - httpsMode: false, expertMode: false, decimalCount: 4, uiEffects: true, - minVersion: '1.1.0', - newIssueUrl: "https://git.duniter.org/clients/cesium/cesium/issues/new", - userForumUrl: "https://forum.monnaie-libre.fr", - latestReleaseUrl: "https://api.github.com/repos/duniter/cesium/releases/latest", - duniterLatestReleaseUrl: "https://api.github.com/repos/duniter/duniter/releases/latest", + blockValidityWindow: 6, helptip: { enable: true, installDocUrl: "https://duniter.org/en/wiki/duniter/install/", @@ -90,13 +98,19 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) }, wallet: { showPubkey: true, - alertIfUnusedWallet: true, - notificationReadTime: 0 + alertIfUnusedWallet: true }, locale: { id: fixLocaleWithLog(csConfig.defaultLanguage || $translate.use()) // use config locale if set, or browser default + }, + license: { + "en": "license/license_g1-en", + "fr-FR": "license/license_g1-fr-FR", + "es-ES": "license/license_g1-es-ES" } - }, csConfig), + }, + fixedSettings, + csConfig), data = {}, previousData, @@ -104,6 +118,11 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) startPromise, api = new Api(this, "csSettings"); + // removeIf(no-device) + // set defaults for device + defaultSettings.walletHistoryAutoRefresh = false; + // endRemoveIf(no-device) + var reset = function() { _.keys(data).forEach(function(key){ @@ -130,10 +149,10 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) }, emitChangedEvent = function() { - var hasChanged = previousData && !angular.equals(previousData, data); - previousData = angular.copy(data); + var hasChanged = angular.isUndefined(previousData) || !angular.equals(previousData, data); if (hasChanged) { - api.data.raise.changed(data); + previousData = angular.copy(data); + return api.data.raise.changed(data); } }, @@ -177,38 +196,43 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) .then(emitChangedEvent); }, + /** + * Apply new settings (can be partial) + * @param newData + */ applyData = function(newData) { + if (!newData) return; // skip empty + var localeChanged = false; if (newData.locale && newData.locale.id) { // Fix previously stored locale (could use bad format) - newData.locale.id = fixLocale(newData.locale.id); + var localeId = fixLocale(newData.locale.id); + newData.locale = _.findWhere(locales, {id: localeId}); localeChanged = !data.locale || newData.locale.id !== data.locale.id || newData.locale.id !== $translate.use(); } - // Apply stored settings + // Force some fixed settings, before merging + _.keys(fixedSettings).forEach(function(key) { + newData[key] = defaultSettings[key]; // This will apply fixed value (override by config.js file) + }); + + // Apply new settings angular.merge(data, newData); - // Always force the usage of default settings - // This is a workaround for DEV (TODO: implement edition in settings ?) - data.timeWarningExpire = defaultSettings.timeWarningExpire; - data.timeWarningExpireMembership = defaultSettings.timeWarningExpireMembership; - data.cacheTimeMs = defaultSettings.cacheTimeMs; - data.timeout = defaultSettings.timeout; - data.minVersion = defaultSettings.minVersion; - data.latestReleaseUrl = defaultSettings.latestReleaseUrl; - data.duniterLatestReleaseUrl = defaultSettings.duniterLatestReleaseUrl; - data.newIssueUrl = defaultSettings.newIssueUrl; - data.userForumUrl = defaultSettings.userForumUrl; + // Delete temporary properties, if false + if (newData && newData.node && !newData.node.temporary || !data.node.temporary) delete data.node.temporary; // Apply the new locale (only if need) + // will produce an event cached by onLocaleChange(); if (localeChanged) { - $translate.use(fixLocale(data.locale.id)); // will produce an event cached by onLocaleChange(); + $translate.use(data.locale.id); } }, restore = function() { - var now = new Date().getTime(); + var now = Date.now(); + return localStorage.getObject(constants.STORAGE_KEY) .then(function(storedData) { // No settings stored @@ -219,15 +243,10 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) return; } - // Workaround, to turn on 'rememberMe', but only once (at version 0.13.2) - if (!storedData.rememberMe && (!storedData.login || !storedData.login.method)) { - storedData.rememberMe = true; - } - // Apply stored data applyData(storedData); - console.debug('[settings] Loaded from local storage in '+(new Date().getTime()-now)+'ms'); + console.debug('[settings] Loaded from local storage in '+(Date.now()-now)+'ms'); emitChangedEvent(); }); }, @@ -235,30 +254,40 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) getLicenseUrl = function() { var locale = data.locale && data.locale.id || csConfig.defaultLanguage || 'en'; return (csConfig.license) ? - (csConfig.license[locale] ? csConfig.license[locale] : csConfig.license[csConfig.defaultLanguage || 'en'] || csConfig.license) : undefined; + (csConfig.license[locale] ? csConfig.license[locale] : defaultSettings.license[csConfig.defaultLanguage || 'en'] || csConfig.license) : undefined; }, - // Detect locale sucessuf changes, then apply to vendor libs + // Detect locale successful changes, then apply to vendor libs onLocaleChange = function() { var locale = $translate.use(); console.debug('[settings] Locale ['+locale+']'); // config moment lib try { - moment.locale(locale.substr(0,2)); + moment.locale(locale.toLowerCase()); } catch(err) { - moment.locale('en'); - console.warn('[settings] Unknown local for moment lib. Using default [en]'); + try { + moment.locale(locale.substr(0,2)); + } + catch(err) { + moment.locale('en-gb'); + console.warn('[settings] Unknown local for moment lib. Using default [en]'); + } } // config numeral lib try { - numeral.language(locale.substr(0,2)); + numeral.language(locale.toLowerCase()); } catch(err) { - numeral.language('en'); - console.warn('[settings] Unknown local for numeral lib. Using default [en]'); + try { + numeral.language(locale.substring(0, 2)); + } + catch(err) { + numeral.language('en-gb'); + console.warn('[settings] Unknown local for numeral lib. Using default [en]'); + } } // Emit event @@ -309,6 +338,7 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) ready: ready, start: start, data: data, + apply: applyData, getByPath: getByPath, reset: reset, store: store, diff --git a/assets/www/dist/dist_js/app/services/storage-services.js b/assets/www/dist/dist_js/app/services/storage-services.js index e9f507abc73ee00316da9f08c597c734b4ae795f..d1f74c8418591f5d954e75e078d91e2f24190888 100644 --- a/assets/www/dist/dist_js/app/services/storage-services.js +++ b/assets/www/dist/dist_js/app/services/storage-services.js @@ -24,13 +24,13 @@ angular.module('cesium.storage.services', [ 'cesium.config']) }; exports.getObject = function(key) { - return $q.when(JSON.parse(exports.storage[key] || '{}')); + return $q.when(JSON.parse(exports.storage[key] || 'null')); }; return exports; }]) - .factory('localStorage', ['$window', '$q', 'sessionStorage', function($window, $q, sessionStorage) { + .factory('localStorage', ['$window', '$q', '$log', 'sessionStorage', function($window, $q, $log, sessionStorage) { 'ngInject'; var @@ -50,7 +50,17 @@ angular.module('cesium.storage.services', [ 'cesium.config']) /* -- Use standard browser implementation -- */ exports.standard.put = function(key, value) { - exports.standard.storage[key] = value; + if (angular.isDefined(value) && value != null) { + exports.standard.storage[key] = value; + } + else { + exports.standard.storage.removeItem(key); + } + return $q.when(); + }; + + exports.standard.remove = function(key, value) { + exports.standard.storage.removeItem(key); return $q.when(); }; @@ -64,58 +74,84 @@ angular.module('cesium.storage.services', [ 'cesium.config']) }; exports.standard.getObject = function(key) { - return $q.when(JSON.parse(exports.standard.storage[key] || '{}')); + return $q.when(JSON.parse(exports.standard.storage[key] || 'null')); }; /* -- Use secure storage (using a cordova plugin) -- */ // Set a value to the secure storage (or remove if value is not defined) exports.secure.put = function(key, value) { - var deferred = $q.defer(); - if (angular.isDefined(value)) { - exports.secure.storage.set( - function (key) { deferred.resolve(); }, - function (err) { deferred.reject(err); }, - key, value); - } - // Remove - else { - exports.secure.storage.remove( - function (key) { deferred.resolve(); }, - function (err) { deferred.reject(err); }, - key); - } - return deferred.promise; + return $q(function(resolve, reject) { + if (value !== undefined && value !== null) { + exports.secure.storage.set( + function (key) { + resolve(); + }, + function (err) { + $log.error(err); + reject(err); + }, + key, value); + } + // Remove + else { + exports.secure.storage.remove( + function () { + resolve(); + }, + function (err) { + $log.error(err); + resolve(); // Error = not found + }, + key); + } + }); }; // Get a value from the secure storage exports.secure.get = function(key, defaultValue) { - var deferred = $q.defer(); - exports.secure.storage.get( - function (value) { - if (!value && defaultValue) { - deferred.resolve(defaultValue); - } - else { - deferred.resolve(value); - } - }, - function (err) { deferred.reject(err); }, - key); - return deferred.promise; + return $q(function(resolve, reject) { + exports.secure.storage.get( + function (value) { + if (!value && defaultValue) { + resolve(defaultValue); + } + else { + resolve(value); + } + }, + function (err) { + $log.error(err); + resolve(); // Error = not found + }, + key); + }); }; // Set a object to the secure storage exports.secure.setObject = function(key, value) { - return exports.secure.put(key, value ? JSON.stringify(value) : undefined); + $log.debug("[storage] Setting object into secure storage, using key=" + key); + return $q(function(resolve, reject){ + exports.secure.storage.set( + resolve, + reject, + key, + value ? JSON.stringify(value) : undefined); + }); }; // Get a object from the secure storage exports.secure.getObject = function(key) { - return exports.secure.storage.get(key) - .then(function(value) { - return (value && JSON.parse(value)) || {}; - }); + $log.debug("[storage] Getting object from secure storage, using key=" + key); + return $q(function(resolve, reject){ + exports.secure.storage.get( + function(value) {resolve(JSON.parse(value||'null'));}, + function(err) { + $log.error(err); + resolve(); // Error = not found + }, + key); + }); }; function initStandardStorage() { @@ -129,7 +165,7 @@ angular.module('cesium.storage.services', [ 'cesium.config']) }); } - // Fallback to session storage (locaStorage could have been disabled on some browser) + // Fallback to session storage (localStorage could have been disabled on some browser) else { console.debug('[storage] Starting {session} storage...'); // Set standard storage as default @@ -182,11 +218,10 @@ angular.module('cesium.storage.services', [ 'cesium.config']) function start() { if (startPromise) return startPromise; - var now = new Date().getTime(); + var now = Date.now(); // Use Cordova secure storage plugin if (isDevice) { - console.debug("[storage] Starting secure storage..."); startPromise = initSecureStorage(); } @@ -197,7 +232,7 @@ angular.module('cesium.storage.services', [ 'cesium.config']) return startPromise .then(function() { - console.debug('[storage] Started in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[storage] Started in ' + (Date.now() - now) + 'ms'); started = true; startPromise = null; }); diff --git a/assets/www/dist/dist_js/app/services/tx-services.js b/assets/www/dist/dist_js/app/services/tx-services.js index 41e2886ff7d78e22192f089718408638734a3ae9..14a83eba7eaaf37aa38f2724d2066af984c98063 100644 --- a/assets/www/dist/dist_js/app/services/tx-services.js +++ b/assets/www/dist/dist_js/app/services/tx-services.js @@ -6,21 +6,22 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', csConfig, csSettings, csWot, csCurrency) { 'ngInject'; - function factory(id, BMA) { + var defaultBMA = BMA; + function CsTx(id, BMA) { + + BMA = BMA || defaultBMA; var api = new Api(this, "csTx-" + id), _reduceTxAndPush = function(pubkey, txArray, result, processedTxMap, allowPendings) { - if (!txArray || txArray.length === 0) { - return; - } + if (!txArray || !txArray.length) return; // Skip if empty _.forEach(txArray, function(tx) { if (tx.block_number || allowPendings) { var walletIsIssuer = false; var otherIssuer = tx.issuers.reduce(function(issuer, res) { - walletIsIssuer = (res === pubkey) ? true : walletIsIssuer; + walletIsIssuer = walletIsIssuer || (res === pubkey); return issuer + ((res !== pubkey) ? ', ' + res : ''); }, ''); if (otherIssuer.length > 0) { @@ -126,112 +127,119 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', loadTx = function(pubkey, fromTime) { return $q(function(resolve, reject) { - var txHistory = []; - var udHistory = []; - var txPendings = []; - var nowInSec = Math.trunc(new Date().getTime() / 1000); // TODO test to replace using moment().utc().unix() + var nowInSec = moment().utc().unix(); fromTime = fromTime || (nowInSec - csSettings.data.walletHistoryTimeSecond); - var processedTxMap = {}; var tx = { - pendings: [] + pendings: [], + validating: [], + history: [], + errors: [] }; - var _reduceTx = function(res){ - _reduceTxAndPush(pubkey, res.history.sent, txHistory, processedTxMap); - _reduceTxAndPush(pubkey, res.history.received, txHistory, processedTxMap); - _reduceTxAndPush(pubkey, res.history.sending, txPendings, processedTxMap, true /*allow pendings*/); - _reduceTxAndPush(pubkey, res.history.pending, txPendings, processedTxMap, true /*allow pendings*/); + var processedTxMap = {}; + var _reduceTx = function (res) { + _reduceTxAndPush(pubkey, res.history.sent, tx.history, processedTxMap); + _reduceTxAndPush(pubkey, res.history.received, tx.history, processedTxMap); + _reduceTxAndPush(pubkey, res.history.sending, tx.pendings, processedTxMap, true /*allow pendings*/); + _reduceTxAndPush(pubkey, res.history.pending, tx.pendings, processedTxMap, true /*allow pendings*/); }; var jobs = [ - // get pendings history + // get current block + csCurrency.blockchain.current(true), + + // get pending tx BMA.tx.history.pending({pubkey: pubkey}) .then(_reduceTx) ]; // get TX history since - if (fromTime !== -1) { - var sliceTime = csSettings.data.walletHistorySliceSecond; - fromTime = fromTime - (fromTime % sliceTime); - for(var i = fromTime; i - sliceTime < nowInSec; i += sliceTime) { - var startTime = Math.max(i, fromTime); - jobs.push(BMA.tx.history.times({pubkey: pubkey, from: i, to: i+sliceTime-1}) + if (fromTime !== 'pending') { + + // get TX from a given time + if (fromTime > 0) { + // Use slice, to be able to cache requests result + var sliceTime = csSettings.data.walletHistorySliceSecond; + fromTime = fromTime - (fromTime % sliceTime); + for(var i = fromTime; i - sliceTime < nowInSec; i += sliceTime) { + jobs.push(BMA.tx.history.times({pubkey: pubkey, from: i, to: i+sliceTime-1}) + .then(_reduceTx) + ); + } + + jobs.push(BMA.tx.history.timesNoCache({pubkey: pubkey, from: nowInSec - (nowInSec % sliceTime), to: nowInSec+999999999}) + .then(_reduceTx)); + } + + // get all TX + else { + jobs.push(BMA.tx.history.all({pubkey: pubkey}) .then(_reduceTx) ); } - jobs.push(BMA.tx.history.timesNoCache({pubkey: pubkey, from: nowInSec - (nowInSec % sliceTime), to: nowInSec+999999999}) - .then(_reduceTx)); - } - - // get all TX - else { - jobs.push(BMA.tx.history.all({pubkey: pubkey}) - .then(_reduceTx) - ); - } - - // get UD history - if (csSettings.data.showUDHistory) { - /*jobs.push( - BMA.ud.history({pubkey: pubkey}) - .then(function(res){ - udHistory = !res.history || !res.history.history ? [] : - res.history.history.reduce(function(res, ud){ - if (ud.time < fromTime) return res; // skip to old UD - var amount = powBase(ud.amount, ud.base); - return res.concat({ - time: ud.time, - amount: amount, - isUD: true, - block_number: ud.block_number + // get UD history + if (csSettings.data.showUDHistory && fromTime > 0) { + /*jobs.push( + BMA.ud.history({pubkey: pubkey}) + .then(function(res){ + udHistory = !res.history || !res.history.history ? [] : + _.forEach(res.history.history, function(ud){ + if (ud.time < fromTime) return res; // skip to old UD + var amount = powBase(ud.amount, ud.base); + udHistory.push({ + time: ud.time, + amount: amount, + isUD: true, + block_number: ud.block_number + }); }); - }, []); - }));*/ - // API extension - jobs.push( - api.data.raisePromise.loadUDs({ - pubkey: pubkey, - fromTime: fromTime - }) - .then(function(res) { - if (!res || !res.length) return; - udHistory = res.reduce(function(res, hits) { - return res.concat(hits); - }, udHistory); + }));*/ + // API extension + jobs.push( + api.data.raisePromise.loadUDs({ + pubkey: pubkey, + fromTime: fromTime }) + .then(function(res) { + if (!res || !res.length) return; + _.forEach(res, function(hits) { + tx.history.push(hits); + }); + }) - .catch(function(err) { - console.debug('Error while loading UDs history, on extension point.'); - console.error(err); - }) - ); + .catch(function(err) { + console.debug('Error while loading UDs history, on extension point.'); + console.error(err); + }) + ); + } } // Execute jobs $q.all(jobs) - .then(function(){ + .then(function(res){ + var current = res[0]; + // sort by time desc - tx.history = txHistory.concat(udHistory).sort(function(tx1, tx2) { + tx.history.sort(function(tx1, tx2) { return (tx2.time - tx1.time); }); - tx.pendings = txPendings; - - tx.fromTime = fromTime; - tx.toTime = tx.history.length ? tx.history[0].time /*=max(tx.time)*/: fromTime; + tx.validating = tx.history.filter(function(tx) { + return (tx.block_number > current.number - csSettings.data.blockValidityWindow); + }); + // remove validating from history + if (tx.validating.length) { + tx.history.splice(0, tx.validating.length); + } + tx.fromTime = fromTime !== 'pending' && fromTime || undefined; + tx.toTime = tx.history.length ? tx.history[0].time /*=max(tx.time)*/: tx.fromTime; resolve(tx); }) - .catch(function(err) { - tx.history = []; - tx.pendings = []; - tx.errors = []; - delete tx.fromTime; - delete tx.toTime; - reject(err); - }); + .catch(reject); }); }, @@ -256,7 +264,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', loadSourcesAndBalance = function(pubkey) { return BMA.tx.sources({pubkey: pubkey}) .then(function(res){ - var result = { + var data = { sources: [], sourcesIndexByKey: [], balance: 0 @@ -264,19 +272,23 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', if (res.sources && res.sources.length) { _.forEach(res.sources, function(src) { src.consumed = false; - result.balance += powBase(src.amount, src.base); + data.balance += powBase(src.amount, src.base); }); - addSources(result, res.sources); + addSources(data, res.sources); } - return result; + return data; + }) + .catch(function(err) { + console.warn("[tx] Error while getting sources...", err); + throw err; }); }, loadData = function(pubkey, fromTime) { - var now = new Date().getTime(); + var now = Date.now(); - var data = {}; return $q.all([ + // Load Sources loadSourcesAndBalance(pubkey), @@ -285,12 +297,14 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', ]) .then(function(res) { - angular.merge(data, res[0]); + // Copy sources and balance + var data = res[0]; data.tx = res[1]; var txPendings = []; var txErrors = []; - var balance = data.balance; + var balanceFromSource = data.balance; + var balanceWithPending = data.balance; function _processPendingTx(tx) { var consumedSources = []; @@ -318,7 +332,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', delete tx.inputs; } if (valid) { - balance += tx.amount; // update balance + balanceWithPending += tx.amount; // update balance txPendings.push(tx); _.forEach(consumedSources, function(src) { src.consumed=true; @@ -331,7 +345,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', var txs = data.tx.pendings; var retry = true; - while(txs && txs.length > 0) { + while(txs && txs.length) { // process TX pendings _.forEach(txs, _processPendingTx); @@ -346,18 +360,30 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', } } - data.tx.pendings = txPendings; - data.tx.errors = txErrors; - data.balance = balance; + data.tx = data.tx || {}; + data.tx.pendings = txPendings.sort(function(tx1, tx2) { + return (tx2.time - tx1.time); + }); + data.tx.errors = txErrors.sort(function(tx1, tx2) { + return (tx2.time - tx1.time); + }); + // Negative balance not allow (use only source's balance) - fix #769 + data.balance = (balanceWithPending < 0) ? balanceFromSource : balanceWithPending; // Will add uid (+ plugin will add name, avatar, etc. if enable) - return csWot.extendAll((data.tx.history || []).concat(data.tx.pendings||[]), 'pubkey'); - }) - .then(function() { - console.debug('[tx] TX and sources loaded in '+ (new Date().getTime()-now) +'ms'); - return data; + var allTx = (data.tx.history || []).concat(data.tx.validating||[], data.tx.pendings||[], data.tx.errors||[]); + return csWot.extendAll(allTx, 'pubkey') + .then(function() { + console.debug('[tx] TX and sources loaded in '+ (Date.now()-now) +'ms'); + return data; + }); }); - }; + }, + + loadSources = function(pubkey) { + console.debug("[tx] Loading sources for " + pubkey.substring(0,8)); + return loadData(pubkey, 'pending'); + }; // Download TX history file downloadHistoryFile = function(pubkey, options) { @@ -378,17 +404,15 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', loadData(pubkey, options.fromTime) ]) .then(function(result){ - var translations = result[0]; - var currentBlock = result[1]; var currentTime = (currentBlock && currentBlock.medianTime) || moment().utc().unix(); var currency = currentBlock && currentBlock.currency; - result = result[2]; + var data = result[2]; // no TX - if (!result || !result.tx || !result.tx.history) { + if (!data || !data.tx || !data.tx.history) { return UIUtils.toast.show('INFO.EMPTY_TX_HISTORY'); } @@ -396,9 +420,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', .then(function(filename){ var formatDecimal = $filter('formatDecimal'); - var formatPubkey = $filter('formatPubkey'); - var formatDate = $filter('formatDate'); - var formatDateForFile = $filter('formatDateForFile'); + var medianDate = $filter('medianDate'); var formatSymbol = $filter('currencySymbolNoHtml'); var headers = [ @@ -408,9 +430,9 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', translations['ACCOUNT.HEADERS.AMOUNT'] + ' (' + formatSymbol(currency) + ')', translations['ACCOUNT.HEADERS.COMMENT'] ]; - var content = result.tx.history.reduce(function(res, tx){ + var content = data.tx.history.concat(data.tx.validating).reduce(function(res, tx){ return res.concat([ - formatDate(tx.time), + medianDate(tx.time), tx.uid, tx.pubkey, formatDecimal(tx.amount/100), @@ -430,14 +452,17 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', return { id: id, load: loadData, + loadSources: loadSources, downloadHistoryFile: downloadHistoryFile, // api extension api: api }; } - var service = factory('default', BMA); + var service = new CsTx('default'); - service.instance = factory; + service.instance = function(id, bma) { + return new CsTx(id, bma); + }; return service; }]); diff --git a/assets/www/dist/dist_js/app/services/utils-services.js b/assets/www/dist/dist_js/app/services/utils-services.js index b67a8871b1a41e33f738f609b35678a570aa9904..7d0e289d81d8aca85e6c84b3dc3623e4c7f6ab23 100644 --- a/assets/www/dist/dist_js/app/services/utils-services.js +++ b/assets/www/dist/dist_js/app/services/utils-services.js @@ -15,28 +15,29 @@ angular.module('cesium.utils.services', []) }; }]) -.factory('UIUtils', ['$ionicLoading', '$ionicPopup', '$ionicConfig', '$translate', '$q', 'ionicMaterialInk', 'ionicMaterialMotion', '$window', '$timeout', '$cordovaToast', '$ionicPopover', '$state', '$rootScope', 'screenmatch', 'csSettings', function($ionicLoading, $ionicPopup, $ionicConfig, $translate, $q, ionicMaterialInk, ionicMaterialMotion, $window, $timeout, +.factory('UIUtils', ['$ionicLoading', '$ionicPopup', '$ionicConfig', '$ionicHistory', '$translate', '$q', 'ionicMaterialInk', 'ionicMaterialMotion', '$window', '$timeout', 'Fullscreen', '$cordovaToast', '$ionicPopover', '$state', '$rootScope', 'screenmatch', function($ionicLoading, $ionicPopup, $ionicConfig, $ionicHistory, $translate, $q, + ionicMaterialInk, ionicMaterialMotion, $window, $timeout, Fullscreen, // removeIf(no-device) $cordovaToast, // endRemoveIf(no-device) - $ionicPopover, $state, $rootScope, screenmatch, csSettings) { + $ionicPopover, $state, $rootScope, screenmatch) { 'ngInject'; var loadingTextCache=null, CONST = { - MAX_HEIGHT: 400, - MAX_WIDTH: 400, - THUMB_MAX_HEIGHT: 100, - THUMB_MAX_WIDTH: 100 + MAX_HEIGHT: 480, + MAX_WIDTH: 640, + THUMB_MAX_HEIGHT: 200, + THUMB_MAX_WIDTH: 200 }, data = { smallscreen: screenmatch.bind('xs, sm', $rootScope) }, exports, raw = {} - ; + ; function alertError(err, subtitle) { if (!err) { @@ -45,45 +46,45 @@ angular.module('cesium.utils.services', []) return $q(function(resolve) { $translate([err, subtitle, 'ERROR.POPUP_TITLE', 'ERROR.UNKNOWN_ERROR', 'COMMON.BTN_OK']) - .then(function (translations) { - var message = err.message || translations[err]; - return $ionicPopup.show({ - template: '<p>' + (message || translations['ERROR.UNKNOWN_ERROR']) + '</p>', - title: translations['ERROR.POPUP_TITLE'], - subTitle: translations[subtitle], - buttons: [ - { - text: '<b>'+translations['COMMON.BTN_OK']+'</b>', - type: 'button-assertive', - onTap: function(e) { - resolve(e); + .then(function (translations) { + var message = err.message || translations[err]; + return $ionicPopup.show({ + template: '<p>' + (message || translations['ERROR.UNKNOWN_ERROR']) + '</p>', + title: translations['ERROR.POPUP_TITLE'], + subTitle: translations[subtitle], + buttons: [ + { + text: '<b>'+translations['COMMON.BTN_OK']+'</b>', + type: 'button-assertive', + onTap: function(e) { + resolve(e); + } } - } - ] + ] + }); }); - }); }); } function alertInfo(message, subtitle) { return $q(function(resolve) { $translate([message, subtitle, 'INFO.POPUP_TITLE', 'COMMON.BTN_OK']) - .then(function (translations) { - $ionicPopup.show({ - template: '<p>' + translations[message] + '</p>', - title: translations['INFO.POPUP_TITLE'], - subTitle: translations[subtitle], - buttons: [ - { - text: translations['COMMON.BTN_OK'], - type: 'button-positive', - onTap: function(e) { - resolve(e); + .then(function (translations) { + $ionicPopup.show({ + template: '<p>' + translations[message] + '</p>', + title: translations['INFO.POPUP_TITLE'], + subTitle: translations[subtitle], + buttons: [ + { + text: translations['COMMON.BTN_OK'], + type: 'button-positive', + onTap: function(e) { + resolve(e); + } } - } - ] + ] + }); }); - }); }); } @@ -138,6 +139,23 @@ angular.module('cesium.utils.services', []) return $ionicLoading.show(options); } + function updateLoading(options) { + return $ionicLoading._getLoader().then(function(loader) { + if (!loader || !loader.isShown) return; + // Translate template (if exists) + if (options && options.template) { + return $translate(options && options.template) + .then(function(template) { + options.template = template; + return loader; + }); + } + }) + .then(function(loader) { + if (loader && loader.isShown) return showLoading(options); + }); + } + function showToast(message, duration, position) { duration = duration || 'short'; position = position || 'bottom'; @@ -213,41 +231,82 @@ angular.module('cesium.utils.services', []) function getSelectionText(){ var selectedText = ""; if (window.getSelection){ // all modern browsers and IE9+ - selectedText = $window.getSelection().toString(); + selectedText = $window.getSelection().toString(); } return selectedText; } function imageOnLoadResize(resolve, reject, thumbnail) { return function(event) { - var width = event.target.width; - var height = event.target.height; - var maxWidth = (thumbnail ? CONST.THUMB_MAX_WIDTH : CONST.MAX_WIDTH); - var maxHeight = (thumbnail ? CONST.THUMB_MAX_HEIGHT : CONST.MAX_HEIGHT); - - if (width > height) { - if (width > maxWidth) { - height *= maxWidth / width; - width = maxWidth; - } - } else { - if (height > maxHeight) { - width *= maxHeight / height; - height = maxHeight; - } + var width = event.target.width, + height = event.target.height, + maxWidth = (thumbnail ? CONST.THUMB_MAX_WIDTH : CONST.MAX_WIDTH), + maxHeight = (thumbnail ? CONST.THUMB_MAX_HEIGHT : CONST.MAX_HEIGHT) + ; + + var canvas = document.createElement("canvas"); + var ctx; + + // Thumbnail: resize and crop (to the expected size) + if (thumbnail) { + + // landscape + if (width > height) { + width *= maxHeight / height; + height = maxHeight; + } + + // portrait + else { + height *= maxWidth / width; + width = maxWidth; + } + canvas.width = maxWidth; + canvas.height = maxHeight; + ctx = canvas.getContext("2d"); + var xoffset = Math.trunc((maxWidth - width) / 2 + 0.5); + var yoffset = Math.trunc((maxHeight - height) / 2 + 0.5); + ctx.drawImage(event.target, + xoffset, // x1 + yoffset, // y1 + maxWidth + -2 * xoffset, // x2 + maxHeight + -2 * yoffset // y2 + ); + } + + // Resize, but keep the full image + else { + + // landscape + if (width > height) { + if (width > maxWidth) { + height *= maxWidth / width; + width = maxWidth; } - var canvas = document.createElement("canvas"); - canvas.width = width; - canvas.height = height; - var ctx = canvas.getContext("2d"); - ctx.drawImage(event.target, 0, 0, canvas.width, canvas.height); + } - var dataurl = canvas.toDataURL(); + // portrait + else { + if (height > maxHeight) { + width *= maxHeight / height; + height = maxHeight; + } + } - canvas.remove(); + canvas.width = width; + canvas.height = height; + ctx = canvas.getContext("2d"); - resolve(dataurl); - }; + // Resize the whole image + ctx.drawImage(event.target, 0, 0, canvas.width, canvas.height); + } + + var dataurl = canvas.toDataURL(); + + canvas.remove(); + + resolve(dataurl); + }; } function resizeImageFromFile(file, thumbnail) { @@ -343,7 +402,6 @@ angular.module('cesium.utils.services', []) options.scope = options.scope || $rootScope; options.scope.popovers = options.scope.popovers || {}; options.autoselect = options.autoselect || false; - options.bindings = options.bindings || {}; options.autoremove = angular.isDefined(options.autoremove) ? options.autoremove : true; options.backdropClickToClose = angular.isDefined(options.backdropClickToClose) ? options.backdropClickToClose : true; options.focusFirstInput = angular.isDefined(options.focusFirstInput) ? options.focusFirstInput : false; @@ -354,37 +412,39 @@ angular.module('cesium.utils.services', []) popover.deferred=deferred; popover.options=options; // Fill the popover scope - angular.merge(popover.scope, options.bindings); + if (options.bindings) { + angular.merge(popover.scope, options.bindings); + } $timeout(function() { // This is need for Firefox popover.show(event) - .then(function() { - var element; - // Auto select text - if (options.autoselect) { - element = document.querySelectorAll(options.autoselect)[0]; - if (element) { - if ($window.getSelection && !$window.getSelection().toString()) { - element.setSelectionRange(0, element.value.length); - element.focus(); - } - else { - element.focus(); + .then(function() { + var element; + // Auto select text + if (options.autoselect) { + element = document.querySelectorAll(options.autoselect)[0]; + if (element) { + if ($window.getSelection && !$window.getSelection().toString()) { + element.setSelectionRange(0, element.value.length); + element.focus(); + } + else { + element.focus(); + } } } - } - else { - // Auto focus on a element - if (options.autofocus) { - element = document.querySelectorAll(options.autofocus)[0]; - if (element) element.focus(); + else { + // Auto focus on a element + if (options.autofocus) { + element = document.querySelectorAll(options.autofocus)[0]; + if (element) element.focus(); + } } - } - popover.scope.$parent.$emit('popover.shown'); + popover.scope.$parent.$emit('popover.shown'); - // Callback 'afterShow' - if (options.afterShow) options.afterShow(popover); - }); + // Callback 'afterShow' + if (options.afterShow) options.afterShow(popover); + }); }); }; @@ -394,9 +454,9 @@ angular.module('cesium.utils.services', []) delete options.scope.popovers[options.templateUrl]; // Remove the popover popover.remove() - // Workaround for issue #244 - // See also https://github.com/driftyco/ionic-v1/issues/71 - // and https://github.com/driftyco/ionic/issues/9069 + // Workaround for issue #244 + // See also https://github.com/driftyco/ionic-v1/issues/71 + // and https://github.com/driftyco/ionic/issues/9069 .then(function() { var bodyEl = angular.element($window.document.querySelectorAll('body')[0]); bodyEl.removeClass('popover-open'); @@ -415,8 +475,8 @@ angular.module('cesium.utils.services', []) popover.isResolved = false; popover.scope.closePopover = function(result) { - var autoremove = popover.options.autoremove; - delete popover.options.autoremove; // remove to avoid to trigger 'popover.hidden' + var autoremove = popover.options && popover.options.autoremove; + if (popover.options) delete popover.options.autoremove; // remove to avoid to trigger 'popover.hidden' popover.hide() .then(function() { if (autoremove) { @@ -598,7 +658,7 @@ angular.module('cesium.utils.services', []) function motionDelegate(delegate, ionListClass) { var motionTimeout = isSmallScreen() ? 100 : 10; var defaultSelector = '.list.{0} .item, .list .{0} .item'.format(ionListClass, ionListClass); - return { + return { ionListClass: ionListClass, show: function(options) { options = options || {}; @@ -621,9 +681,10 @@ angular.module('cesium.utils.services', []) if (exports.motion.enable === enable) return; // same console.debug('[UI] [effects] ' + (enable ? 'Enable' : 'Disable')); + exports.motion.enable = enable; if (enable) { $ionicConfig.views.transition('platform'); - exports.motion = raw.motion; + angular.merge(exports.motion, raw.motion); } else { $ionicConfig.views.transition('none'); @@ -631,7 +692,7 @@ angular.module('cesium.utils.services', []) class: undefined, show: function(){} }; - exports.motion = { + angular.merge(exports.motion, { enable : false, default: nothing, fadeSlideIn: nothing, @@ -643,8 +704,10 @@ angular.module('cesium.utils.services', []) fadeIn: nothing, toggleOn: toggleOn, toggleOff: toggleOff - }; + }); + $rootScope.motion = nothing; } + $ionicHistory.clearCache(); } raw.motion = { @@ -658,8 +721,8 @@ angular.module('cesium.utils.services', []) ripple: motionDelegate(ionicMaterialMotion.ripple, 'animate-ripple'), slideUp: motionDelegate(ionicMaterialMotion.slideUp, 'slide-up'), fadeIn: motionDelegate(function(options) { - toggleOn(options); - }, 'fade-in'), + toggleOn(options); + }, 'fade-in'), toggleOn: toggleOn, toggleOff: toggleOff }; @@ -713,12 +776,6 @@ angular.module('cesium.utils.services', []) }, timeout || 900); } - - - csSettings.api.data.on.changed($rootScope, function(data) { - setEffects(data.uiEffects); - }); - exports = { alert: { error: alertError, @@ -728,14 +785,16 @@ angular.module('cesium.utils.services', []) }, loading: { show: showLoading, - hide: hideLoading + hide: hideLoading, + update: updateLoading }, toast: { show: showToast }, onError: onError, screen: { - isSmall: isSmallScreen + isSmall: isSmallScreen, + fullscreen: Fullscreen }, ink: ionicMaterialInk.displayEffect, motion: raw.motion, diff --git a/assets/www/dist/dist_js/app/services/wallet-services.js b/assets/www/dist/dist_js/app/services/wallet-services.js index d61ce84af5f637780c1e797e6ff1663a5b3f19c8..0960f8d75ec42715805db313027da64fe7725e49 100644 --- a/assets/www/dist/dist_js/app/services/wallet-services.js +++ b/assets/www/dist/dist_js/app/services/wallet-services.js @@ -3,29 +3,34 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se 'cesium.settings.services']) -.factory('csWallet', ['$q', '$rootScope', '$timeout', '$translate', '$filter', '$ionicHistory', 'UIUtils', 'Api', 'Idle', 'localStorage', 'sessionStorage', 'Modals', 'CryptoUtils', 'BMA', 'csConfig', 'csSettings', 'FileSaver', 'Blob', 'csWot', 'csTx', 'csCurrency', function($q, $rootScope, $timeout, $translate, $filter, $ionicHistory, UIUtils, +.factory('csWallet', ['$q', '$rootScope', '$timeout', '$translate', '$filter', '$ionicHistory', 'UIUtils', 'Api', 'Idle', 'localStorage', 'sessionStorage', 'Modals', 'CryptoUtils', 'csCrypto', 'BMA', 'csConfig', 'csSettings', 'FileSaver', 'Blob', 'csWot', 'csTx', 'csCurrency', function($q, $rootScope, $timeout, $translate, $filter, $ionicHistory, UIUtils, Api, Idle, localStorage, sessionStorage, Modals, - CryptoUtils, BMA, csConfig, csSettings, FileSaver, Blob, csWot, csTx, csCurrency) { + CryptoUtils, csCrypto, BMA, csConfig, csSettings, FileSaver, Blob, csWot, csTx, csCurrency) { 'ngInject'; + var defaultBMA = BMA; + var service; + function factory(id, BMA) { + BMA = BMA || defaultBMA; var + exports, constants = { - // @Deprecated - OLD_STORAGE_KEY: 'CESIUM_DATA', STORAGE_PUBKEY: 'pubkey', STORAGE_UID: 'uid', + STORAGE_DATA_PREFIX: 'data-', STORAGE_SECKEY: 'seckey', /* Need for compat with old currencies (test_net and sou) */ - TX_VERSION: csConfig.compatProtocol_0_80 ? 3 : BMA.constants.PROTOCOL_VERSION, - IDTY_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION, - MS_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION, - CERT_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION, - REVOKE_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION, + TX_VERSION: BMA.constants.PROTOCOL_VERSION, + IDTY_VERSION: BMA.constants.PROTOCOL_VERSION, + MS_VERSION: BMA.constants.PROTOCOL_VERSION, + CERT_VERSION: BMA.constants.PROTOCOL_VERSION, + REVOKE_VERSION: BMA.constants.PROTOCOL_VERSION, TX_MAX_INPUTS_COUNT: 40 // Allow to get a TX with less than 100 rows (=max row count in Duniter protocol) }, data = {}, + settings, listeners, started, startPromise, @@ -38,15 +43,23 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se data.pubkey= null; data.uid = null; + data.localName = null; data.isNew = null; data.sourcesIndexByKey = null; data.medianTime = null; data.requirements = {}; data.blockUid = null; data.sigDate = null; + data.sigStock = null; data.isMember = false; data.events = []; + // children's wallets + data.children = []; + + // Encrypted (need auth() to be encrypted) + data.encryptedData = null; + resetKeypair(); resetTxAndSources(); @@ -57,7 +70,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se api.data.raise.init(data); } else { - if (!csSettings.data.useLocalStorage) { + if (isDefault() && settings && !settings.useLocalStorage) { csSettings.reset(); } api.data.raise.reset(data); @@ -71,20 +84,39 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }; }, - resetTxAndSources = function(){ + resetSources = function(){ // reset sources data data.sources = undefined; data.sourcesIndexByKey = undefined; data.balance = 0; + }, + + resetTx = function(){ // reset TX data data.tx = data.tx || {}; data.tx.history = []; data.tx.pendings = []; + data.tx.validating = []; data.tx.errors = []; delete data.tx.fromTime; delete data.tx.toTime; }, + resetTxAndSources = function(){ + // reset sources data + resetSources(); + // reset TX data + resetTx(); + }, + + isDefault = function(){ + return id === 'default'; + }, + + hasEncryptedData = function(){ + return data.encryptedData && data.encryptedData.nonce && data.encryptedData.content; + }, + addSource = function(src, sources, sourcesIndexByKey) { var srcKey = src.type+':'+src.identifier+':'+src.noffset; if (angular.isUndefined(sourcesIndexByKey[srcKey])) { @@ -133,10 +165,11 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se } // invalid data authData = res; - data.pubkey = res.pubkey; + data.pubkey = authData.pubkey; + data.uid = authData.uid || data.uid; data.isNew = options && angular.isDefined(options.isNew) ? options.isNew : data.isNew; if (keepAuth) { - data.keypair = res.keypair || { + data.keypair = authData.keypair || { signSk: null, signPk: null }; @@ -163,8 +196,20 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }) .then(function() { - // store wallet if need - if (csSettings.data.useLocalStorage) { + // Read data from pubkey (when first login) + if (needLogin) { + return restoreData(); + } + // Or the was login but now auth: just try to decrypt data + else if (needAuth) { + return openEncryptedData(); + } + }) + + .then(function() { + if (needLogin) { + + // store wallet store(); } @@ -175,7 +220,8 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return api.data.raisePromise.auth(keepAuth ? data : authData); } - }).then(function() { + }) + .then(function() { // Load data if need // If user just login, force data full load (even if min data asked) // because the user can wait (after the login modal) @@ -206,8 +252,9 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return $q(function(resolve, reject) { + var pubkey = data.pubkey; resetData(); // will reset keypair - store(); // store (if local storage enable) + resetStore(pubkey); // reset store // Send logout event api.data.raise.logout(); @@ -264,7 +311,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }, isAuth = function() { - return !!(data.pubkey && data.keypair && data.keypair.signSk); + return data.pubkey && data.keypair && data.keypair.signSk && true; }, getKeypair = function(options) { @@ -287,12 +334,17 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }, hasSelf = function() { - return !!data.pubkey && data.requirements && !data.requirements.needSelf; + return !!data.pubkey && !data.requirements.needSelf; }, isDataLoaded = function(options) { - if (options && options.minData) return data.loaded; - return data.loaded && data.sources; + if (options) { + if (options.minData && !options.sources) return data.loaded && true; + if (options.requirements && !data.requirements.loaded) return false; + if (options.tx && options.tx.enable && (!data.tx.fromTime || data.tx.fromTime == 'pending')) return false; + if (options.sigStock && !data.sigStock) return false; + } + return data.loaded && data.sources && true; }, isNeverUsed = function() { @@ -301,6 +353,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se // Check registration data.isMember || data.requirements.pendingMembership || + data.requirements.revoked || !data.requirements.needSelf || data.requirements.wasMember || @@ -309,6 +362,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se data.tx.pendings.length || // Check extended data (name+avatar) + data.localName || data.name || data.avatar ); @@ -321,16 +375,21 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return isLogin() && data.pubkey === pubkey; }, - store = function() { - if (csSettings.data.useLocalStorage) { + // store pubkey and uid + store = function(pubkey) { + pubkey = pubkey && typeof pubkey == 'string' ? pubkey : data.pubkey; + if (settings.useLocalStorage) { - if (isLogin() && csSettings.data.rememberMe) { + if (isLogin() && settings.rememberMe) { + + var now = Date.now(); + console.debug("[wallet] Storing..."); var jobs = []; // Use session storage for secret key - fix #372 - if (csSettings.data.keepAuthIdle == constants.KEEP_AUTH_IDLE_SESSION && isAuth()) { - jobs.push(sessionStorage.put(constants.STORAGE_SECKEY, CryptoUtils.base58.encode(data.keypair.signSk))); + if (settings.keepAuthIdle == csSettings.constants.KEEP_AUTH_IDLE_SESSION && isAuth()) { + jobs.push(sessionStorage.put(constants.STORAGE_SECKEY, CryptoUtils.util.encode_base58(data.keypair.signSk))); } else { jobs.push(sessionStorage.put(constants.STORAGE_SECKEY, null)); @@ -347,20 +406,19 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se jobs.push(localStorage.put(constants.STORAGE_UID, null)); } - // Clean old storage - jobs.push(localStorage.put(constants.OLD_STORAGE_KEY, null)); - - return $q.all(jobs).then(function() { - console.debug('[wallet] Saved locally'); - }); + return $q.all(jobs) + .then(function() { + console.debug("[wallet] Stored in "+ (Date.now() - now) +"ms"); + }); } else { + // Resetting local storage return $q.all([ sessionStorage.put(constants.STORAGE_SECKEY, null), localStorage.put(constants.STORAGE_PUBKEY, null), localStorage.put(constants.STORAGE_UID, null), - // Clean old storage - localStorage.put(constants.OLD_STORAGE_KEY, null) + // Clean data (only in the session storage - keep local) + pubkey ? sessionStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when() ]); } } @@ -369,13 +427,117 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se sessionStorage.put(constants.STORAGE_SECKEY, null), localStorage.put(constants.STORAGE_PUBKEY, null), localStorage.put(constants.STORAGE_UID, null), - // Clean old storage - localStorage.put(constants.OLD_STORAGE_KEY, null) + // Clean data + pubkey ? sessionStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when(), + pubkey ? localStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when() ]); + } + }, + + // reset data store for this pubkey + resetStore = function(pubkey) { + + console.debug("[wallet] Resetting stored pubkey (and uid) in local storage..."); + + sessionStorage.put(constants.STORAGE_SECKEY, null); + localStorage.put(constants.STORAGE_PUBKEY, null); + localStorage.put(constants.STORAGE_UID, null); + if (settings.useLocalStorage) { + // Clean data (only in the session storage - keep local) + return pubkey ? sessionStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when(); + } + else { + console.debug("[wallet] Resetting stored data in local storage..."); + return $q.all([ + pubkey ? sessionStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when(), + pubkey ? localStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when() + ]); } }, + // store children wallet, notifications read Time, ... + storeData = function() { + if (!isLogin()) throw {message:'ERROR.NEED_LOGIN_FIRST'}; + + var useEncryption = settings.useLocalStorageEncryption; + var storageKey = constants.STORAGE_DATA_PREFIX + data.pubkey; + + var content; // Init only if used + var secureContent; // Init only if used + + // Add time + if (data.notifications && data.notifications.time) { + content = content || {}; + content.notifications = { + time: data.notifications.time + }; + } + if (data.invitations && data.invitations.time) { + content = content || {}; + content.invitations = { + time: data.invitations.time + }; + } + + // Add children wallets + if (data.children && data.children.length) { + // remember children count - need when data still encrypted, by method getChildrenCount() + content = content || {}; + content.childrenCount = data.children.length; + + secureContent = secureContent || {}; // Init th secured content + // Add children wallet + secureContent.children = _.map(data.children, function(wallet) { + return { + pubkey: wallet.data.pubkey, + uid: wallet.data.uid, + localName: wallet.data.localName + }; + }); + } + var contentStr = (content || secureContent) && JSON.stringify(angular.merge({}, content||{}, secureContent||{})); + + // Not encryption (or nothing to secure content): store without encryption + if (!useEncryption || !secureContent) { + return $q.all([ + sessionStorage.put(storageKey, null), // clear session storage (not used if no encryption) + localStorage.put(storageKey, contentStr || null) + ]); + } + + // Encryption is enable, but user not auth: use the session storage + // (and keep the local storage value) + if (!isAuth()) { + return sessionStorage.put(storageKey, contentStr||null); + } + + return $q.all([ + // Get a unique nonce + CryptoUtils.util.random_nonce(), + // Get box keypair + CryptoUtils.box.keypair.fromSignKeypair(data.keypair), + // Put also (without encryption) in the session storage + sessionStorage.put(storageKey, contentStr || null) + ]) + .then(function(res) { + var nonce = res[0]; + var keypair = res[1]; + + return CryptoUtils.box.pack(JSON.stringify(secureContent), nonce, keypair.boxPk, keypair.boxSk) + .then(function(cypherContent) { + content = angular.merge(content||{}, { + encryptedData: { + nonce: CryptoUtils.util.encode_base58(nonce), + content: cypherContent + } + }); + //console.debug("[wallet] Storing with encryption: ", content); + return localStorage.put(storageKey, JSON.stringify(content)); + }); + }); + }, + restore = function() { return $q.all([ sessionStorage.get(constants.STORAGE_SECKEY), @@ -388,6 +550,8 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se var uid = res[2]; if (!pubkey || pubkey == 'null') return; + console.debug('[wallet] Restore {' + pubkey.substring(0, 8) + '} from local storage'); + var keypair; if (seckey && seckey.length && seckey != 'null') { try { @@ -396,7 +560,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se signSk: CryptoUtils.util.decode_base58(seckey) }; } - catch(err) { + catch (err) { console.warn('[wallet] Secret key restoration failed: ', err); keypair = undefined; } @@ -406,60 +570,130 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se data.uid = uid && uid != 'null' ? uid : undefined; data.keypair = keypair || {signPk: undefined, signSk: undefined}; - console.debug('[wallet] Restore \'{0}\' from local storage.'.format(pubkey.substring(0,8))); + // Get pubkey's data + return restoreData(); + }) - // Call extend api - return api.data.raisePromise.login(data); + .then(function() { + // Successful restored: raise API events + if (isAuth()) { + return $q.all([ + api.data.raisePromise.login(data), + checkAuthIdle(true), + api.data.raisePromise.auth(data) + ]) + .catch(function(err) { + console.warn('Error during extension call [wallet.api.data.on.auth]', err); + // continue + }); + } + else if (isLogin()) { + return api.data.raisePromise.login(data) + .catch(function(err) { + console.warn('Error during extension call [wallet.api.data.on.login]', err); + // continue + }); + } }) + .then(function(){ return data; }); }, + restoreData = function() { + if (!isLogin()) throw {message:'ERROR.NEED_LOGIN_FIRST'}; + if (isNew()) return $q.when(data); // Skip restore + // Get pubkey's data + return $q.all([ + sessionStorage.getObject(constants.STORAGE_DATA_PREFIX + data.pubkey), + localStorage.getObject(constants.STORAGE_DATA_PREFIX + data.pubkey) + ]) + // Apply data, first from the session storage, then from local storage + .then(function (res) { + var sessionStorageData = res[0]; + var localStorageData = res[1]; + if (sessionStorageData && sessionStorageData.children && sessionStorageData.children.length === localStorageData.childrenCount) { + return applyRestoredData(sessionStorageData) + .catch(function(err) { + console.error("[wallet] Failed to restore from the session storage ! Retrying from the local storage...", err); + // Retry using another storage + return applyRestoredData(localStorageData); + }); + } + return applyRestoredData(localStorageData); + }); + }, + + applyRestoredData = function(content) { + if (!content) return $q.when(); // skip + + // Apply children + if (content.children) { + var oldChildrenCount = data.childrenCount; + var oldChildren = removeAllChildrenWallets({ + stop: false, /*do not stop wallet*/ + store: false/*skip store*/ + }); + + try { + var pubkeys = {}; + _.forEach(content.children, function(child) { + if (!pubkeys[child.pubkey]) { // make sure wallet is unique by pubkey + pubkeys[child.pubkey] = true; + var wallet = getNewChildrenInstance(); + wallet.data.pubkey = child.pubkey; + wallet.data.localName = child.localName; + wallet.data.uid = child.uid; + addChildWallet(wallet, {store: false/*skip store*/}); + } + }); + delete content.children; + // childrenCount not need anymore + delete data.childrenCount; + } + catch(err) { + console.error("[wallet] Failed to restore children wallet.", err); + // Restore removed values + data.childrenCount = oldChildrenCount; + data.children = oldChildren; + return $q.reject({message:'ERROR.RESTORE_WALLET_LIST_FAILED'}); + } + + // Restoration succeed: stop old children + _.forEach(oldChildren||[], function(child) { + child.stop(); + }); + } + + // make sure to remove pubkey before copy + delete content.pubkey; + delete content.uid; + + // Copy to data + angular.merge(data, content); + + // If auth: open encrypted data + if (hasEncryptedData() && isAuth()) { + return openEncryptedData({store: false}) + .then(function(){ + return data; // Important: return the data + }); + } + + return $q.when(data); // Important: return the data + }, + getData = function() { return data; }, - loadRequirements = function() { + loadRequirements = function(withCache) { // Clean existing events cleanEventsByContext('requirements'); // Get requirements - return csWot.loadRequirements(data) - .then(function(){ - - if (!data.requirements.uid) return; - - // Get sigDate - var blockParts = data.requirements.blockUid.split('-', 2); - var blockNumber = parseInt(blockParts[0]); - var blockHash = blockParts[1]; - // Retrieve registration date - return BMA.blockchain.block({block: blockNumber}) - .then(function(block) { - data.sigDate = block.medianTime; - - // Check if self has been done on a valid block - if (!data.isMember && blockNumber !== 0 && blockHash !== block.hash) { - addEvent({type: 'error', message: 'ERROR.WALLET_INVALID_BLOCK_HASH', context: 'requirements'}); - console.debug("Invalid membership for uid={0}: block hash changed".format(data.uid)); - } - // Check if self expired - else if (!data.isMember && data.requirements.expired) { - addEvent({type: 'error', message: 'ERROR.WALLET_IDENTITY_EXPIRED', context: 'requirements'}); - console.debug("Identity expired for uid={0}.".format(data.uid)); - } - }) - .catch(function(err){ - // Special case for currency init (root block not exists): use now - if (err && err.ucode == BMA.errorCodes.BLOCK_NOT_FOUND && blockNumber === 0) { - data.sigDate = Math.trunc(new Date().getTime() / 1000); - } - else { - throw err; - } - }); - }); + return csWot.loadRequirements(data, withCache); }, loadTxAndSources = function(fromTime) { @@ -474,65 +708,126 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }); }, - // Generate events from requirements - addEvents = function() { + loadSources = function() { + return csTx.loadSources(data.pubkey) + .then(function(res){ + resetSources(); + angular.merge(data, res); + }) + .catch(function(err) { + resetSources(); + throw err; + }); + }, - // Add user events + /** + * Add user events (generate events from requirements) + */ + addEvents = function() { if (data.requirements.revoked) { - addEvent({type:'warn', message: 'ERROR.WALLET_REVOKED', context: 'requirements'}); + delete data.requirements.meta.invalid; + addEvent({type:'info', message: 'ERROR.WALLET_REVOKED', context: 'requirements'}); } else if (data.requirements.pendingRevocation) { + delete data.requirements.meta.invalid; addEvent({type:'pending', message: 'INFO.REVOCATION_SENT_WAITING_PROCESS', context: 'requirements'}); } + + // If not revoked else { - if (data.requirements.pendingMembership) { + if (!data.isMember && data.requirements.meta && data.requirements.meta.invalid) { + addEvent({type: 'error', message: 'ERROR.WALLET_INVALID_BLOCK_HASH', context: 'requirements'}); + console.debug("Invalid membership for uid={0}: block hash changed".format(data.uid)); + } + // Check if self expired + else if (!data.isMember && data.requirements.expired) { + addEvent({type: 'error', message: 'ERROR.WALLET_IDENTITY_EXPIRED', context: 'requirements'}); + console.debug("Identity expired for uid={0}.".format(data.uid)); + } + // Pending membership + else if (data.requirements.pendingMembership) { addEvent({type:'pending', message: 'ACCOUNT.WAITING_MEMBERSHIP', context: 'requirements'}); + + // Add a warning when out distanced + // (only if has enough certification - fix #808) + if (!data.requirements.needCertificationCount && data.requirements.outdistanced) { + addEvent({type:'warn', message: 'ACCOUNT.OUT_DISTANCED', context: 'requirements'}); + } } // If user has send a SELF, ask for membership - fix #625 else if (!data.requirements.needSelf && data.requirements.needMembership){ addEvent({type:'warn', message: 'ACCOUNT.NO_WAITING_MEMBERSHIP', context: 'requirements'}); } - if (data.requirements.needCertificationCount > 0) { - addEvent({type:'warn', message: 'ACCOUNT.WAITING_CERTIFICATIONS', messageParams: data.requirements, context: 'requirements'}); - } - if (data.requirements.willNeedCertificationCount > 0) { - addEvent({type:'warn', message: 'ACCOUNT.WILL_MISSING_CERTIFICATIONS', messageParams: data.requirements, context: 'requirements'}); - } + if (data.requirements.needRenew) { - addEvent({type:'warn', message: 'ACCOUNT.WILL_NEED_RENEW_MEMBERSHIP', messageParams: data.requirements, context: 'requirements'}); + // Still a member: WILL need renew + if (data.isMember && data.requirements.membershipExpiresIn > 0) { + addEvent({type:'warn', message: 'ACCOUNT.WILL_NEED_RENEW_MEMBERSHIP', messageParams: data.requirements, context: 'requirements'}); + } + // Fix #649: Not a member anymore, even if membership NOT expired, because membersjip cancelled for lack of certifications + else if (!data.isMember && data.requirements.membershipExpiresIn > 0 && data.requirements.needCertificationCount > 0) { + addEvent({type:'warn', message: 'ACCOUNT.NEED_RENEW_MEMBERSHIP_AFTER_CANCELLED', messageParams: data.requirements, context: 'requirements'}); + } + // Not a member anymore + else { + addEvent({type:'warn', message: 'ACCOUNT.NEED_RENEW_MEMBERSHIP', messageParams: data.requirements, context: 'requirements'}); + } } - else if (data.requirements.wasMember && data.requirements.needMembership) { - addEvent({type:'warn', message: 'ACCOUNT.NEED_RENEW_MEMBERSHIP', messageParams: data.requirements, context: 'requirements'}); + else + { + if (data.requirements.needCertificationCount > 0) { + addEvent({type:'info', message: 'ACCOUNT.WAITING_CERTIFICATIONS', messageParams: data.requirements, context: 'requirements'}); + // Add a help message, if user has never been a member + if (!data.requirements.wasMember) { + addEvent({ + type: 'help', + message: 'ACCOUNT.WAITING_CERTIFICATIONS_HELP', + messageParams: data.requirements, + context: 'requirements' + }); + } + } + if (data.requirements.willNeedCertificationCount > 0) { + addEvent({type:'warn', message: 'ACCOUNT.WILL_MISSING_CERTIFICATIONS', messageParams: data.requirements, context: 'requirements'}); + } + if (data.requirements.wasMember && data.requirements.needMembership) { + addEvent({type:'warn', message: 'ACCOUNT.NEED_RENEW_MEMBERSHIP', messageParams: data.requirements, context: 'requirements'}); + } + // Add a warning when out distanced - fix #777 + if (!data.requirements.needCertificationCount && !data.requirements.willNeedCertificationCount && data.requirements.outdistanced) { + addEvent({type:'warn', message: 'ACCOUNT.OUT_DISTANCED', context: 'requirements'}); + } } } }, loadSigStock = function() { - return $q(function(resolve, reject) { - // Get certified by, then count written certification - BMA.wot.certifiedBy({pubkey: data.pubkey}) - .then(function(res){ - data.sigStock = !res.certifications ? 0 : res.certifications.reduce(function(res, cert) { - return cert.written === null ? res : res+1; - }, 0); - resolve(); - }) - .catch(function(err) { - if (!!err && err.ucode == BMA.errorCodes.NO_MATCHING_MEMBER) { - data.sigStock = 0; - resolve(); // not found - } - else { - reject(err); - } - }); - }); + // Get certified by, then count written certification + return BMA.wot.certifiedBy({pubkey: data.pubkey}) + .then(function(res){ + data.sigStock = !res.certifications ? 0 : res.certifications.reduce(function(res, cert) { + return cert.written === null ? res : res+1; + }, 0); + }) + .catch(function(err) { + if (!!err && err.ucode == BMA.errorCodes.NO_MATCHING_MEMBER) { + data.sigStock = 0; + } + /*FIXME: workaround for Duniter issue #1309 */ + else if (!!err && err.ucode == 1002) { + console.warn("[wallet-service] Detecting Duniter issue #1309 ! Applying workaround... "); + data.sigStock = 0; + } + else { + throw err; + } + }); }, loadData = function(options) { var alertIfUnusedWallet = !csCurrency.data.initPhase && (!csSettings.data.wallet || csSettings.data.wallet.alertIfUnusedWallet) && - !data.loaded && (!options || !options.minData); + !data.loaded && (!options || !options.minData || !options.silent); // Make sure to load once at a time if (loadPromise) { @@ -601,13 +896,19 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return $q.all([ // Get requirements - loadRequirements(), + loadRequirements(true) + .then(function(data) { + if (data.requirements && (data.requirements.isMember || data.requirements.wasMember)) { + // Load sigStock + return loadSigStock(); + } + else { + data.sigStock = 0; + } + }), // Get TX and sources - loadTxAndSources(), - - // Load sigStock - loadSigStock() + loadTxAndSources() ]) .then(function() { @@ -633,7 +934,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se loadMinData = function(options) { options = options || {}; options.requirements = angular.isDefined(options.requirements) ? options.requirements : - (!data.requirements || angular.isUndefined(data.requirements.needSelf)); + (!data.requirements.loaded || angular.isUndefined(data.requirements.needSelf)); if (!options.requirements) { return $q.when(data); } @@ -657,7 +958,12 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }; // Force some load (requirements) if not already loaded - options.requirements = angular.isDefined(options.requirements) ? options.requirements : angular.isDefined(data.requirements.needSelf); + options.requirements = angular.isDefined(options.requirements) ? options.requirements : !data.requirements.loaded; + + // Force sources when TX enable + if (angular.isUndefined(options.sources) && options.tx && options.tx.enable) { + options.sources = true; + } var jobs = []; @@ -667,29 +973,43 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se cleanEventsByContext('requirements'); jobs.push( - loadRequirements() + loadRequirements(true) // Add wallet events .then(addEvents) ); } - if (options.sources || (options.tx && options.tx.enable)) { + if (options.sources && (!options.tx || options.tx.enable)) { // Get TX and sources jobs.push(loadTxAndSources(options.tx ? options.tx.fromTime: undefined)); } + else if (options.sources && (options.tx && !options.tx.enable)) { + // Get sources (no TX) + jobs.push(loadSources()); + } + // Load sigStock if (options.sigStock) jobs.push(loadSigStock()); return (jobs.length ? $q.all(jobs) : $q.when()) - .then(function(){ - // API extension (after all other jobs) - return api.data.raisePromise.load(data); - }) - .then(function(){ - return data; - }); + .then(function(){ + // Skip api + if (angular.isDefined(options.api) && !options.api) return data; + + // API extension (after all other jobs) + return api.data.raisePromise.load(data) + .then(function(){ + + // Compute if full loaded + if (!data.loaded) { + data.loaded = data.requirements.loaded && data.sources; + } + + return data; + }); + }); }, setSelf = function(uid, blockUid){ @@ -712,8 +1032,10 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se // Refresh requirements return refreshData({requirements: true, sigStock: true}) - // Store (to remember the new uid) - .then(store); + .then(function() { + // Store (to remember the new uid) + return store({skipData: true}); + }); }, isBase = function(amount, base) { @@ -748,8 +1070,11 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se var sources = []; var minBase = filterBase; var maxBase = filterBase; - _.find(data.sources, function(source) { - if (!source.consumed && source.base == filterBase){ + _.find(data.sources || [], function(source) { + if (!source.consumed && source.base === filterBase && + // Filter on simple SIG output condition - fix #845 + BMA.regexp.TX_OUTPUT_SIG.exec(source.conditions) + ) { sourcesAmount += powBase(source.amount, source.base); sources.push(source); } @@ -782,16 +1107,16 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se /** * Send a new transaction */ - transfer = function(destPub, amount, comments, useRelative) { + transfer = function(destPub, amount, comments, useRelative, restPub, block) { return $q.all([ getKeypair(), csCurrency.get(), - csCurrency.blockchain.current() + block && $q.when(block) || csCurrency.blockchain.current() ]) .then(function(res) { var keypair = res[0]; var currency = res[1]; - var block = res[2]; + block = res[2]; if (!BMA.regexp.PUBKEY.test(destPub)){ throw {message:'ERROR.INVALID_PUBKEY'}; } @@ -801,6 +1126,9 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se if (!isLogin()){ throw {message:'ERROR.NEED_LOGIN_FIRST'}; } + if (destPub === data.pubkey){ + throw {message:'ERROR.SAME_TX_RECIPIENT'}; + } if (!amount) { throw {message:'ERROR.AMOUNT_REQUIRED'}; } @@ -878,21 +1206,23 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se } // Send tx - return createAndSendTx(currency, block, keypair, destPub, amount, inputs, comments, logs) + return createAndSendTx(currency, block, keypair, destPub, amount, inputs, comments, restPub||data.pubkey, logs) .then(function(res) { - data.balance -= amount; + data.balance -= res.amount; + if (data.balance < 0) data.balance = 0; // fix #712 _.forEach(inputs.sources, function(source) { source.consumed=true; }); // Add new sources if (res && res.sources.length) { + console.debug("[wallet-service] New sources to be add after the TX: ", res.sources); addSources(res.sources); } // Add TX to pendings var pendingTx = { - time: (Math.floor(moment().utc().valueOf() / 1000)), + time: csCurrency.date.now(), amount: -amount, pubkey: destPub, comment: comments, @@ -922,7 +1252,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se console.debug('[wallet] TX rejected by node with error [{0}]. Reloading sources then retry...'.format(err.message||'Source already consumed')); return $timeout(loadTxAndSources, 500) .then(function() { - return transfer(destPub, amount, comments, useRelative); + return transfer(destPub, amount, comments, useRelative, restPub, block); }); } @@ -958,6 +1288,33 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }); }, + /** + * Send a WIF wallet + */ + transferAll = function(destPub, amount, comments, useRelative, restPub) { + if (!isLogin()) return $q.reject({message:'ERROR.NEED_LOGIN_FIRST'}); + + if (!restPub || destPub == restPub) { + return $q.reject({message: "Could not have same pubkey for 'destPub' and 'restPub'"}); + } + + return csCurrency.blockchain.lastValid() + .then(function(block) { + console.debug("[wallet] Using last valid block as TX reference (to avoid network fork): ", block); + + return transfer(destPub, amount, comments, useRelative, restPub, block) + .then(function() { + // If more money: transfer all to restPub + if (data.balance > 0 && restPub) { + console.debug("[wallet] Wallet has some more money: transfering fund to [{0}]".format(restPub.substring(0,8))); + return transfer(restPub, data.balance, undefined/*comments*/, false/*useRelative*/, restPub, block); + } + }); + + }); + + }, + /** * Create TX doc and send it * @param block the current block @@ -967,7 +1324,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se * @param comments * @return the hash of the sent TX */ - createAndSendTx = function(currency, block, keypair, destPub, amount, inputs, comments, logs) { + createAndSendTx = function(currency, block, keypair, destPub, amount, inputs, comments, restPub, logs) { // Make sure a TX in compact mode has no more than 100 lines (fix #118) // (If more than 100 lines, send to TX to himself first, then its result as sources for the final TX) @@ -988,7 +1345,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }); // Send inputs first slice - return createAndSendTx(currency, block, keypair, data.pubkey/*to himself*/, firstSlice.amount, firstSlice, undefined/*comment not need*/, logs) + return createAndSendTx(currency, block, keypair, data.pubkey/*to himself*/, firstSlice.amount, firstSlice, undefined/*comment not need*/, data.pubkey/*rest to himself*/, logs) .then(function(res) { _.forEach(firstSlice.sources, function(source) { source.consumed=true; @@ -1004,11 +1361,11 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se _.forEach(secondSlice.sources, function(source) { if (source.base < secondSlice.minBase) secondSlice.minBase = source.base; if (source.base > secondSlice.maxBase) secondSlice.maxBase = source.base; - secondSlice.amount += source.amount; + secondSlice.amount += powBase(source.amount, source.base); }); // Send inputs second slice (recursive call) - return createAndSendTx(currency, block, keypair, destPub, amount, secondSlice, comments, logs); + return createAndSendTx(currency, block, keypair, destPub, amount, secondSlice, comments, restPub, logs); }); } @@ -1055,19 +1412,22 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se rest = inputs.amount - amount; outputBase = inputs.maxBase; } - // Outputs to himself + // Outputs to restPub while(rest > 0) { outputAmount = truncBase(rest, outputBase); rest -= outputAmount; if (outputAmount > 0) { outputAmount = outputBase === 0 ? outputAmount : outputAmount / Math.pow(10, outputBase); - tx += outputAmount +':'+outputBase+':SIG('+data.pubkey+')\n'; - newSources.push({ - type: 'T', - noffset: outputOffset, - amount: outputAmount, - base: outputBase - }); + tx += outputAmount +':'+outputBase+':SIG('+restPub+')\n'; + // If rest to himself: add new sources + if (data.pubkey === restPub) { + newSources.push({ + type: 'T', + noffset: outputOffset, + amount: outputAmount, + base: outputBase + }); + } outputOffset++; } outputBase--; @@ -1110,6 +1470,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se output.pending = true; }); return { + amount: (data.pubkey === destPub) ? 0 : ((data.pubkey === restPub) ? amount : inputs.amount), tx: signedTx, hash: txHash, sources: newSources @@ -1124,7 +1485,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se if (!uid || !blockUid) { throw {message: 'ERROR.WALLET_HAS_NO_SELF'}; } - if (data.requirements && data.requirements.expired) { + if (data.requirements.expired) { throw {message: 'ERROR.WALLET_IDENTITY_EXPIRED'}; } @@ -1153,7 +1514,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return $q.all([ getKeypair(), csCurrency.get(), - csCurrency.blockchain.current() + csCurrency.blockchain.lastValid() ]) // Create identity document .then(function(res) { @@ -1171,7 +1532,10 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se .then(function () { if (!!needToLoadRequirements) { // Refresh membership data (if need) - return loadRequirements(); + return loadRequirements(false/*no cache*/) + + // Add wallet events + .then(addEvents); } else { data.uid = uid; @@ -1195,7 +1559,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return $q.all([ getKeypair(), - csCurrency.blockchain.current() + csCurrency.blockchain.lastValid() ]) .then(function(res) { var keypair = res[0]; @@ -1219,7 +1583,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }) .then(function() { return $timeout(function() { - return loadRequirements(); + return loadRequirements(false /*no cache*/); }, 1000); // waiting for node to process membership doc }) @@ -1311,20 +1675,17 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se getCryptedId = function(record){ return getkeypairSaveId(record) - .then(function() { - return CryptoUtils.util.random_nonce(); - }) + .then(CryptoUtils.util.random_nonce) .then(function(nonce) { - record.nonce = nonce; - return CryptoUtils.box.pack(record.salt, record.nonce, record.keypair.boxPk, record.keypair.boxSk); - }) - .then(function (cypherSalt) { - record.salt = cypherSalt; - return CryptoUtils.box.pack(record.pwd, record.nonce, record.keypair.boxPk, record.keypair.boxSk); + record.nonce = CryptoUtils.util.encode_base58(nonce); + return $q.all([ + CryptoUtils.box.pack(record.salt, nonce, record.keypair.boxPk, record.keypair.boxSk), + CryptoUtils.box.pack(record.pwd, nonce, record.keypair.boxPk, record.keypair.boxSk) + ]); }) - .then(function (cypherPwd) { - record.pwd = cypherPwd; - record.nonce = CryptoUtils.util.encode_base58(record.nonce); + .then(function (res) { + record.salt = res[0]; + record.pwd = res[1]; return record; }); }, @@ -1373,46 +1734,35 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return getSaveIDDocument(record) .then(function(saveId) { var saveIdFile = new Blob([saveId], {type: 'text/plain; charset=utf-8'}); - FileSaver.saveAs(saveIdFile, 'saveID-{0}.txt'.format(data.pubkey.substring(0,6))); + FileSaver.saveAs(saveIdFile, '{0}-recover_ID.txt'.format(data.pubkey.substring(0,8))); }); }, - getKeyFileDocument =function(format) { - - var document; - switch(format) { - case "PubSec" : - document = "Type: PubSec\n" + - "Version: 1\n" + - "pub: " + data.pubkey + "\n" + - "sec: " + CryptoUtils.base58.encode(data.keypair.signSk) + "\n"; - break; - case "WIF" : - document = "Type: WIF\n" + - "Version: 1\n" + - "Data: " + CryptoUtils.wif_v1_from_keypair(data.keypair)+ "\n"; - break; - case "EWIF" : - document = "Type: EWIF\n" + - "Version: 1\n" + - "Data: " + CryptoUtils.ewif_v1_from_keypair(data.keypair, "bonjour") + "\n"; - break; - default: - return Promise.reject("Unknown keyfile format: " + format); - } - if (document) { - return Promise.resolve(document); - } - }, downloadKeyFile = function(format){ - if (!isAuth()) return Promise.reject('user not authenticated'); + if (!isAuth()) return $q.reject('user not authenticated'); return $q.all([ csCurrency.get(), - getKeyFileDocument(format) + csCrypto.keyfile.generateContent(data.keypair, + { + type: format, + password: function() { + UIUtils.loading.hide(); + return Modals.showPassword({ + title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', + subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP' + }) + .then(function(password) { + return UIUtils.loading.show(10) + .then(function(){ + return password; + }); + }); + } + }) ]) .then(function(res) { var currency = res[0]; @@ -1488,7 +1838,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se .then(function() { return $timeout(function() { - return loadRequirements(); + return loadRequirements(false/*no cache*/); }, 1000); // waiting for node to process membership doc }) @@ -1515,7 +1865,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se .then(function(res) { if (isLogin()) { return $timeout(function () { - return loadRequirements(); + return loadRequirements(false/*no cache*/); }, 1000) // waiting for node to process membership doc // Add wallet events @@ -1539,24 +1889,24 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }, downloadRevocation = function(){ - return $q.all([ - csCurrency.get(), - getRevocationDocument() - ]) - .then(function(res) { - var currency = res[0]; - var revocation = res[1]; - var revocationFile = new Blob([revocation], {type: 'text/plain; charset=utf-8'}); - return $translate('ACCOUNT.SECURITY.REVOCATION_FILENAME', { - uid: data.uid, - currency: currency.name, - pubkey: data.pubkey - }) - .then(function (fileName) { - FileSaver.saveAs(revocationFile, fileName); - }); + return $q.all([ + csCurrency.get(), + getRevocationDocument() + ]) + .then(function(res) { + var currency = res[0]; + var revocation = res[1]; + var revocationFile = new Blob([revocation], {type: 'text/plain; charset=utf-8'}); + return $translate('ACCOUNT.SECURITY.REVOCATION_FILENAME', { + uid: data.uid, + currency: currency.name, + pubkey: data.pubkey + }) + .then(function (fileName) { + FileSaver.saveAs(revocationFile, fileName); }); - }, + }); + }, cleanEventsByContext = function(context){ data.events = data.events.reduce(function(res, event) { @@ -1565,6 +1915,169 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se },[]); }, + /* -- children wallets -- */ + + setParentWallet = function(parentWallet) { + listeners = listeners || []; + var listener; + _.forEach(['load', 'reset'], function(method) { + listener = api.data.on[method]($rootScope, function(data, deferred) { + deferred = deferred || $q.defer(); + parentWallet.api.data.raisePromise[method](data) + .then(deferred.resolve) + .catch(deferred.reject); + return deferred.promise; + }, this); + listeners.push(listener); + }); + + // Unauth when parent wallet unauth + listener = parentWallet.api.data.on.unauth($rootScope, function() { + if (isAuth()) unauth(); + }, this); + listeners.push(listener); + }, + + createNewChildWallet = function(options) { + var walletId = getChildrenWalletCount()+1; + var wallet = service.instance(walletId); + addChildWallet(wallet, options); + return wallet; + }, + + addChildWallet = function(wallet, options) { + // Link to parent + wallet.children.setParent(exports); // = link to self wallet + + data.children = data.children || []; + data.children.push(wallet); + + // Store (store children locally) + if (!options || angular.isUndefined(options.store) || options.store) { + return storeData(); + } + return $q.when(); + }, + + removeAllChildrenWallets = function(options) { + + // stop/unauth all existing wallets + if (!options || options.stop) { + _.forEach(data.children || [], function(wallet){ + wallet.stop(); + }); + } + var removedChildren = data.children.splice(0, data.children.length); + + // Store (store children locally) + if (!options || angular.isUndefined(options.store) || options.store) { + return storeData(); + } + return removedChildren; + + }, + + removeChildWalletById = function(id, options) { + data.children = data.children || []; + var childIndex = _.findIndex(data.children, function(child) {return child.id == id;}); + if (childIndex === -1) { + console.warn('[wallet] Unable to remove child wallet {'+id+'} (not found)'); + return; + } + // Remove the wallet, and return it + var wallet = data.children.splice(childIndex, 1)[0]; + + // Force to stop without calling api + wallet.stop(); + + // Store (store children locally) + if (!options || angular.isUndefined(options.store) || options.store) { + return storeData(); + } + }, + + getChildWalletById = function(id) { + return (id !== 'default') && _.find(data.children|| [], function(child) {return child.id == id;}) || undefined; + }, + + getChildWalletByPubkey = function(pubkey) { + return _.find(data.children|| [], function(child) {return child.isUserPubkey(pubkey);}); + }, + + hasChildrenWithPubkey = function(pubkey) { + return !!getChildWalletByPubkey(pubkey); + }, + + getChildrenWalletCount = function() { + return angular.isDefined(data.childrenCount) ? data.childrenCount : (data.children && data.children.length || 0); + }, + + getNewChildrenInstance = function() { + // Return max(id) + 1 + var walletId = (data.children && data.children.reduce(function(res, wallet) { + return Math.max(res, wallet.id); + }, 0) || data.childrenCount || 0 )+ 1; + return service.instance(walletId, BMA); + }, + + getAllChildrenWallet = function() { + return openEncryptedData() + .then(function() { + return data.children; + }); + }, + + downloadChildrenWalletFile = function() { + return $q.all([ + getAllChildrenWallet(), + csCurrency.get() + ]) + .then(function(res) { + var children = res[0]; + var currency = res[1]; + var content = (children||[]).reduce(function(res, wallet) { + return res + [wallet.data.pubkey, wallet.data.uid, wallet.data.localName||wallet.data.name].join('\t') + '\n'; + }, ''); + var file = new Blob([content], {type: 'text/plain; charset=utf-8'}); + return $translate('ACCOUNT.WALLET_LIST.EXPORT_FILENAME', { + pubkey: data.pubkey, + currency: currency.name, + }) + .then(function (fileName) { + FileSaver.saveAs(file, fileName); + }); + }); + }, + + /* -- END children wallets -- */ + + openEncryptedData = function(options) { + if (!hasEncryptedData()) return $q.when(); + if (!isAuth()) return auth().then(openEncryptedData); // Force auth if need + + // Open encrypted data + return CryptoUtils.box.keypair.fromSignKeypair(data.keypair) + .then(function(keypair) { + var nonce = CryptoUtils.util.decode_base58(data.encryptedData.nonce); + return CryptoUtils.box.open(data.encryptedData.content, nonce, keypair.boxPk, keypair.boxSk); + }) + // Then apply + .then(function(content) { + data.encryptedData = null; // reset encrypted data + var promise = applyRestoredData(JSON.parse(content)); + + // Store (store data into session storage) + if (!options || angular.isUndefined(options.store) || options.store) { + promise.then(function() { + return storeData(); + }); + } + + return promise; + }) + ; + }, + /** * De-serialize from JSON string */ @@ -1620,39 +2133,107 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }); }, - checkAuthIdle = function(isAuth) { - isAuth = angular.isDefined(isAuth) ? isAuth : isAuth(); - var enable = isAuth && csSettings.data.keepAuthIdle > 0 && csSettings.data.keepAuthIdle != csSettings.constants.KEEP_AUTH_IDLE_SESSION; - var changed = (enableAuthIdle != enable); + checkAuthIdle = function(isAuthResult) { + isAuthResult = angular.isDefined(isAuthResult) ? isAuthResult : isAuth(); + var newEnableAuthIdle = isAuthResult && settings.keepAuthIdle > 0 && settings.keepAuthIdle != csSettings.constants.KEEP_AUTH_IDLE_SESSION; + var changed = (enableAuthIdle != newEnableAuthIdle); // need start/top watching if (changed) { // start idle - if (enable) { - console.debug("[wallet] Start idle (delay: {0}s)".format(csSettings.data.keepAuthIdle)); - Idle.setIdle(csSettings.data.keepAuthIdle); + if (newEnableAuthIdle) { + console.debug("[wallet] Start idle (delay: {0}s)".format(settings.keepAuthIdle)); + Idle.setIdle(settings.keepAuthIdle); Idle.watch(); } - // stop idle, if need + // stop idle, if was enable else if (enableAuthIdle){ console.debug("[wallet] Stop idle"); Idle.unwatch(); } - enableAuthIdle = enable; + enableAuthIdle = newEnableAuthIdle; } // if idle time changed: apply it - else if (enable && Idle.getIdle() !== csSettings.data.keepAuthIdle) { - console.debug("[idle] Updating auth idle (delay: {0}s)".format(csSettings.data.keepAuthIdle)); - Idle.setIdle(csSettings.data.keepAuthIdle); + else if (newEnableAuthIdle && Idle.getIdle() !== settings.keepAuthIdle) { + console.debug("[idle] Updating auth idle (delay: {0}s)".format(settings.keepAuthIdle)); + Idle.setIdle(settings.keepAuthIdle); + } + + // Make sure to store seckey, in the session storage for secret key -fix #372 + var storeSecKey = isAuthResult && settings.keepAuthIdle == csSettings.constants.KEEP_AUTH_IDLE_SESSION && true; + if (storeSecKey) { + sessionStorage.put(constants.STORAGE_SECKEY, CryptoUtils.util.encode_base58(data.keypair.signSk)); + } + // Make sure to clean previous seckey, if exists in session storage + else if (changed) { + sessionStorage.put(constants.STORAGE_SECKEY, null); } }; + function getWalletSettings(settings) { + return { + useLocalStorage: settings.useLocalStorage, + useLocalStorageEncryption: settings.useLocalStorageEncryption, + rememberMe: settings.rememberMe, + keepAuthIdle: settings.keepAuthIdle + }; + } + + function onSettingsChanged(allSettings) { + var newSettings = getWalletSettings(allSettings); + var hasChanged = !angular.equals(settings, newSettings); + if (!hasChanged) return; // skip + + var useEncryptionChanged = !angular.equals(settings.useLocalStorageEncryption, newSettings.useLocalStorageEncryption); + var useStorageChanged = !angular.equals(settings.useLocalStorage, newSettings.useLocalStorage) || useEncryptionChanged; + var keepAuthIdleChanged = !angular.equals(settings.keepAuthIdle, newSettings.keepAuthIdle); + + settings = newSettings; + + if (keepAuthIdleChanged) { + checkAuthIdle(); + } + + // Local storage option changed + if (useStorageChanged) { + + // If disabled, then reset the store + if (!settings.useLocalStorage) { + resetStore(data.pubkey); + } + // If storage enable + else { + // Store login data + return store() + .then(function() { + + // Encryption enable: auth before saving data + if (data.childrenCount > 0 && useEncryptionChanged && settings.useLocalStorageEncryption) { + return auth({minData: true, silent: true}) + .catch(function(err){ + // user not auth: revert encryption to false + if (err === 'CANCELLED') { + csSettings.apply({useLocalStorageEncryption: false}); + return csSettings.store(); + } + else { + throw err; + } + }); + } + }) + + // Store other data (children wallet, ...) + .then(storeData); + } + } + } + function addListeners() { listeners = [ // Listen if settings changed - csSettings.api.data.on.changed($rootScope, store, this), - csSettings.api.data.on.changed($rootScope, checkAuthIdle, this), + csSettings.api.data.on.changed($rootScope, onSettingsChanged, this), // Listen if node changed BMA.api.node.on.restart($rootScope, restart, this) ]; @@ -1660,6 +2241,11 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se $rootScope.$on('IdleStart', unauth); } + function addListener(listener) { + listeners = listeners || []; + listeners.push(listener); + } + function removeListeners() { _.forEach(listeners, function(remove){ remove(); @@ -1689,10 +2275,13 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se options.restore = angular.isDefined(options.restore) ? options.restore : (id === 'default'); console.debug('[wallet] Starting...'); - var now = new Date().getTime(); + var now = Date.now(); startPromise = $q.all([ - csSettings.ready(), + csSettings.ready() + .then(function() { + settings = getWalletSettings(csSettings.data); + }), csCurrency.ready(), BMA.ready() ]); @@ -1704,7 +2293,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se startPromise.then(function() { addListeners(); - console.debug('[wallet] Started in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[wallet] Started in ' + (Date.now() - now) + 'ms'); started = true; startPromise = null; @@ -1725,6 +2314,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se api.registerEvent('data', 'load'); api.registerEvent('data', 'logout'); api.registerEvent('data', 'reset'); + api.registerEvent('data', 'store'); api.registerEvent('error', 'send'); @@ -1738,7 +2328,17 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se // init data resetData(true); - return { + // Override default store/restore function, when not the 'default' wallet + if (id !== "default") { + //start = $q.when; + //started = true; + store = $q.when; + restore = $q.when; + restoreData = $q.when; + //checkAuthIdle = function(){}; + } + + exports = { id: id, data: data, ready: ready, @@ -1758,14 +2358,24 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return data.isMember; }, isDataLoaded : isDataLoaded, + isDefault: isDefault, isNeverUsed: isNeverUsed, isNew: isNew, isUserPubkey: isUserPubkey, getData: getData, loadData: loadData, refreshData: refreshData, + // internal + internal: { + addListener: addListener, + removeListeners: removeListeners + }, + // local storage + store: store, + storeData: storeData, // store children wallet, readTime, etc. // operations transfer: transfer, + transferAll: transferAll, self: self, revoke: revoke, revokeWithFile: revokeWithFile, @@ -1783,11 +2393,25 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se add: addEvent, cleanByContext: cleanEventsByContext }, + children: { + create: createNewChildWallet, + add: addChildWallet, + remove: removeChildWalletById, + get: getChildWalletById, + getByPubkey: getChildWalletByPubkey, + all: getAllChildrenWallet, + setParent: setParentWallet, + count: getChildrenWalletCount, + hasPubkey: hasChildrenWithPubkey, + instance: getNewChildrenInstance, + downloadFile: downloadChildrenWalletFile + }, api: api }; + return exports; } - var service = factory('default', BMA); + service = factory('default', BMA); service.instance = factory; return service; diff --git a/assets/www/dist/dist_js/app/services/wot-services.js b/assets/www/dist/dist_js/app/services/wot-services.js index c3367b6e580d159cba3e70cfa31e451dfae2ae25..45890ec4d0d5bcef02891fcc1c916882cc4211f2 100644 --- a/assets/www/dist/dist_js/app/services/wot-services.js +++ b/assets/www/dist/dist_js/app/services/wot-services.js @@ -2,14 +2,16 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.crypto.services', 'cesium.utils.services', 'cesium.settings.services']) -.factory('csWot', ['$q', '$timeout', 'BMA', 'Api', 'CacheFactory', 'csConfig', 'csCurrency', 'csSettings', 'csCache', function($q, $timeout, BMA, Api, CacheFactory, csConfig, csCurrency, csSettings, csCache) { +.factory('csWot', ['$rootScope', '$q', '$timeout', 'BMA', 'Api', 'CacheFactory', 'csConfig', 'csCurrency', 'csSettings', 'csCache', function($rootScope, $q, $timeout, BMA, Api, CacheFactory, csConfig, csCurrency, csSettings, csCache) { 'ngInject'; function factory(id) { var api = new Api(this, "csWot-" + id), - identityCache = csCache.get('csWot-idty-', csCache.constants.SHORT), + cachePrefix = 'csWot-', + identityCache = csCache.get(cachePrefix + 'idty-', csCache.constants.MEDIUM), + requirementsCache = csCache.get(cachePrefix + 'requirements-', csCache.constants.MEDIUM), // Add id, and remove duplicated id _addUniqueIds = function(idties) { @@ -58,11 +60,15 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c _resetRequirements = function(data) { data.requirements = { + loaded: false, + meta: {}, + hasSelf: false, needSelf: true, needMembership: true, canMembershipOut: false, needRenew: false, pendingMembership: false, + isMember: false, wasMember: false, certificationCount: 0, needCertifications: false, @@ -73,30 +79,32 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c data.blockUid = null; data.isMember = false; data.sigDate = null; + data.hasSelf = false; }, _fillRequirements = function(requirements, currencyParameters) { // Add useful custom fields - requirements.hasSelf = true; - requirements.needSelf = false; + requirements.hasSelf = !!requirements.meta.timestamp; + requirements.needSelf = !requirements.hasSelf || requirements.meta.invalid; requirements.wasMember = angular.isDefined(requirements.wasMember) ? requirements.wasMember : false; // Compat with Duniter 0.9 - requirements.needMembership = (requirements.membershipExpiresIn <= 0 && requirements.membershipPendingExpiresIn <= 0 && !requirements.wasMember); - requirements.needRenew = (!requirements.needMembership && + requirements.needMembership = (!requirements.revoked && requirements.membershipExpiresIn <= 0 && requirements.membershipPendingExpiresIn <= 0 && !requirements.wasMember); + requirements.needRenew = (!requirements.needMembership && !requirements.revoked && requirements.membershipExpiresIn <= csSettings.data.timeWarningExpireMembership && requirements.membershipPendingExpiresIn <= 0) || - (requirements.wasMember && requirements.membershipExpiresIn === 0 && + (requirements.wasMember && !requirements.revoked && requirements.membershipExpiresIn === 0 && requirements.membershipPendingExpiresIn === 0); - requirements.canMembershipOut = (requirements.membershipExpiresIn > 0); - requirements.pendingMembership = (requirements.membershipExpiresIn <= 0 && requirements.membershipPendingExpiresIn > 0); - requirements.isMember = (requirements.membershipExpiresIn > 0); + requirements.canMembershipOut = (!requirements.revoked && requirements.membershipExpiresIn > 0); + requirements.pendingMembership = (!requirements.revoked && requirements.membershipExpiresIn <= 0 && requirements.membershipPendingExpiresIn > 0); + requirements.isMember = (!requirements.revoked && requirements.membershipExpiresIn > 0); requirements.blockUid = requirements.meta.timestamp; // Force certification count to 0, is not a member yet - fix #269 - requirements.certificationCount = (requirements.isMember && requirements.certifications) ? requirements.certifications.length : 0; + requirements.certificationCount = ((requirements.isMember || (requirements.wasMember && !requirements.expired)) && requirements.certifications) ? requirements.certifications.length : 0; requirements.willExpireCertificationCount = requirements.certifications ? requirements.certifications.reduce(function(count, cert){ return count + (cert.expiresIn <= csSettings.data.timeWarningExpire ? 1 : 0); }, 0) : 0; requirements.willExpire = requirements.willExpireCertificationCount > 0; requirements.pendingRevocation = !requirements.revoked && !!requirements.revocation_sig; + //requirements.outdistanced = requirements.outdistanced; // outdistanced is always present in requirement - see #777 // Fix pending certifications count - Fix #624 if (!requirements.isMember && !requirements.wasMember) { @@ -117,28 +125,90 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c (requirements.certificationCount - requirements.willExpireCertificationCount) < currencyParameters.sigQty) ? (currencyParameters.sigQty - requirements.certificationCount + requirements.willExpireCertificationCount) : 0; + // Mark as loaded - need by csWallet.isDataLoaded() + requirements.loaded = true; + return requirements; }, - loadRequirements = function(data) { - if (!data || (!data.pubkey && !data.uid)) return $q.when(data); + _fillIdentitiesMeta = function(identities) { + if (!identities) return $q.when(identities); + + var blocks = []; + _.forEach(identities, function(identity) { + var blockUid = identity.meta.timestamp.split('-', 2); + identity.meta.number = parseInt(blockUid[0]); + identity.meta.hash = blockUid[1]; + identity.meta.sig = identity.meta.sig || identity.sig; + delete identity.sig; + blocks.push(identity.meta.number); + }); + + // Get identities blocks, to fill self and revocation time + return BMA.blockchain.blocks(_.uniq(blocks)) + .then(function(blocks) { + _.forEach(identities, function(identity) { + var block = _.findWhere(blocks, {number: identity.meta.number}); + identity.meta.time = block && block.medianTime; + + // Check if self has been done on a valid block + if (block && identity.meta.number !== 0 && identity.meta.hash !== block.hash) { + identity.meta.invalid = true; + } + }); + + return identities; + }) + .catch(function(err){ + // Special case for currency init (root block not exists): use now + if (err && err.ucode == BMA.errorCodes.BLOCK_NOT_FOUND) { + _.forEach(identities, function(identity) { + if (identity.number === 0) { + identity.meta.time = moment().utc().unix(); + } + }); + return identities; + } + else { + throw err; + } + }); + }, + + loadRequirements = function(inputData, withCache) { + if (!inputData || (!inputData.pubkey && !inputData.uid)) return $q.when(inputData); + + var cacheKey = inputData.pubkey||inputData.uid; + var data = (withCache !== false) ? requirementsCache.get(cacheKey) : null; + if (data) { + console.debug("[wot] Requirements " + cacheKey + " found in cache"); + // Update data with cache + angular.merge(inputData, data); + return $q.when(data); + } + data = {pubkey: inputData.pubkey, uid: inputData.uid}; + + var now = Date.now(); return $q.all([ // Get currency csCurrency.get(), + // Get requirements - BMA.wot.requirements({pubkey: data.pubkey||data.uid}) + BMA.wot.requirements({pubkey: data.pubkey||data.uid}, false/*no cache*/) + .then(function(res) { + return _fillIdentitiesMeta(res && res.identities); + }) ]) .then(function(res){ var currency = res[0]; + var identities = res[1]; - res = res[1]; - - if (!res.identities || !res.identities.length) return; + if (!identities || !identities.length) return; // Sort to select the best identity - if (res.identities.length > 1) { + if (identities.length > 1) { // Select the best identity, by sorting using this order // - same wallet uid // - is member @@ -149,101 +219,153 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c // max(count(certification) // else // max(membershipPendingExpiresIn) = must recent membership - res.identities = _.sortBy(res.identities, function(idty) { + identities = _.sortBy(identities, function(idty) { var score = 0; - score += (10000000000 * ((data.uid && idty.uid === data.uid) ? 1 : 0)); - score += (10000000000 * ((data.blockUid && idty.meta && idty.meta.timestamp === data.blockUid) ? 1 : 0)); - score += (1000000000 * (idty.membershipExpiresIn > 0 ? 1 : 0)); - score += (100000000 * (idty.membershipPendingExpiresIn > 0 ? 1 : 0)); - score += (10000000 * (!idty.expired ? 1 : 0)); - score += (1000000 * (!idty.outdistanced ? 1 : 0)); - score += (100000 * (idty.wasMember ? 1 : 0)); + score += (1000000000000* ((data.uid && idty.uid === data.uid) ? 1 : 0)); + score += (100000000000 * (!idty.meta.invalid ? 1 : 0)); + score += (10000000000 * ((data.blockUid && idty.meta.timestamp && idty.meta.timestamp === data.blockUid) ? 1 : 0)); + score += (1000000000 * (idty.membershipExpiresIn > 0 ? 1 : 0)); + score += (100000000 * (idty.membershipPendingExpiresIn > 0 ? 1 : 0)); + score += (10000000 * (!idty.expired ? 1 : 0)); + score += (1000000 * (!idty.outdistanced ? 1 : 0)); + score += (100000 * (idty.wasMember ? 1 : 0)); var certCount = !idty.expired && idty.certifications ? idty.certifications.length : 0; - score += (1 * (certCount ? certCount : 0)); - score += (1 * (!certCount && idty.membershipPendingExpiresIn > 0 ? idty.membershipPendingExpiresIn/1000 : 0)); + score += (1 * (certCount ? certCount : 0)); + score += (1 * (!certCount && idty.membershipPendingExpiresIn > 0 ? idty.membershipPendingExpiresIn/1000 : 0)); return -score; }); - console.debug('[wot] Found {0} identities. Will selected the best one'.format(res.identities.length)); + console.debug('[wot] Found {0} identities (in requirements). Will selected the best one'.format(identities.length)); } // Select the first identity - var requirements = _fillRequirements(res.identities[0], currency.parameters); + data.requirements = _fillRequirements(identities[0], currency.parameters); - data.requirements = requirements; - data.pubkey = requirements.pubkey; - data.uid = requirements.uid; - data.isMember = requirements.isMember; - data.blockUid = requirements.blockUid; + // Copy some useful properties into data + data.pubkey = data.requirements.pubkey; + data.uid = data.requirements.uid; + data.isMember = data.requirements.isMember; + data.blockUid = data.requirements.meta && data.requirements.meta.timestamp; + data.hasSelf = data.requirements.hasSelf; + data.sigDate = data.requirements.meta && data.requirements.meta.time; // Prepare alternatives identities if any - if (!requirements.isMember && !requirements.wasMember && res.identities.length > 1) { - requirements.alternatives = res.identities.splice(1); - _.forEach(requirements.alternatives, function(requirements) { + if (!data.requirements.isMember && !data.requirements.wasMember && identities.length > 1) { + data.requirements.alternatives = identities.splice(1); + _.forEach(data.requirements.alternatives, function(requirements) { _fillRequirements(requirements, currency.parameters); }); } - // TODO : get sigDate from blockUid ?? + /// Save to cache + requirementsCache.put(cacheKey, data); - return data; + angular.merge(inputData, data); // Update the input data + + console.debug("[wot] Requirements for '{0}' loaded in {1}ms".format((data.pubkey && data.pubkey.substring(0,8))||data.uid, Date.now() - now)); + + return inputData; }) .catch(function(err) { - _resetRequirements(data); + _resetRequirements(inputData); // If not a member: continue if (!!err && (err.ucode == BMA.errorCodes.NO_MATCHING_MEMBER || err.ucode == BMA.errorCodes.NO_IDTY_MATCHING_PUB_OR_UID)) { - return data; + inputData.requirements.loaded = true; + return inputData; } throw err; - }) - ; + }); }, + + loadIdentityByLookup = function(pubkey, uid) { + var data = { + pubkey: pubkey, + uid: uid, + hasSelf: false + }; return BMA.wot.lookup({ search: pubkey||uid }) .then(function(res){ var identities = res.results.reduce(function(idties, res) { return idties.concat(res.uids.reduce(function(uids, idty) { var blockUid = idty.meta.timestamp.split('-', 2); + var blockNumber = parseInt(blockUid[0]); return uids.concat({ uid: idty.uid, pubkey: res.pubkey, - timestamp: idty.meta.timestamp, - number: parseInt(blockUid[0]), - hash: blockUid[1], + meta: { + timestamp: idty.meta.timestamp, + number: blockNumber, + hash: blockUid[1], + sig: idty.self + }, revoked: idty.revoked, - revocationNumber: idty.revoked_on, - sig: idty.self + revoked_on: idty.revoked_on }); }, [])); }, []); + // Fill identities meta (self) + return _fillIdentitiesMeta(identities) + .then(function(identities) { + return { + identities: identities, + results: res.results + }; + }); + }) + .then(function(res){ + var identities = res.identities; + // Sort identities if need - if (identities.length) { + if (identities.length > 1) { // Select the best identity, by sorting using this order + // - valid block // - same given uid // - not revoked // - max(block_number) - identities = _.sortBy(identities, function(idty) { + res.identities = _.sortBy(identities, function(idty) { var score = 0; - score += (10000000000 * ((uid && idty.uid === uid) ? 1 : 0)); - score += (1000000000 * (!idty.revoked ? 1 : 0)); - score += (1 * (idty.number ? idty.number : 0)); + score += (100000000000 * ((data.uid && idty.uid === data.uid) ? 1 : 0)); + score += (10000000000 * (!idty.meta.invalid ? 1 : 0)); + score += (1000000000 * ((data.blockUid && idty.meta.timestamp && idty.meta.timestamp === data.blockUid) ? 1 : 0)); + score += (100000000 * (!idty.revoked ? 1 : 0)); + score += (1 * (idty.meta.number ? idty.meta.number : 0) / 1000); return -score; }); + console.debug('[wot] Found {0} identities (in lookup). Will selected the best one'.format(identities.length)); } - var identity = identities[0]; - identity.hasSelf = !!(identity.uid && identity.timestamp && identity.sig); - identity.lookup = {}; + // Prepare alternatives identities + _.forEach(identities, function(idty) { + idty.hasSelf = !!(idty.uid && idty.meta.timestamp && idty.meta.sig); + }); + + // Select the first identity + data.requirements = identities[0]; + + // Copy some useful properties into data + data.pubkey = data.requirements.pubkey; + data.uid = data.requirements.uid; + data.blockUid = data.requirements.meta && data.requirements.meta.timestamp; + data.hasSelf = data.requirements.hasSelf; + data.sigDate = data.requirements.meta && data.requirements.meta.time; + + if (identities.length > 1) { + data.requirements.alternatives = identities.splice(1); + } - // Store received certifications - var certPubkeys = []; - identity.lookup.certifications = !res.results ? {} : res.results.reduce(function(certsMap, res) { + // Store additional data (e.g. certs) + data.lookup = {}; + + // Store received certifications (can be usefull later) + var certPubkeys = {}; + data.lookup.certifications = (res.results || []).reduce(function(certsMap, res) { return res.uids.reduce(function(certsMap, idty) { var idtyFullKey = idty.uid + '-' + (idty.meta ? idty.meta.timestamp : ''); - certsMap[idtyFullKey] = idty.others.reduce(function(certs, cert) { + certsMap[idtyFullKey] = (idty.others||[]).reduce(function(certs, cert) { var certFullKey = idtyFullKey + '-' + cert.pubkey; var result = { pubkey: cert.pubkey, @@ -275,9 +397,9 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c }, {}); // Store given certifications - certPubkeys = []; - identity.lookup.givenCertifications = !res.results ? [] : res.results.reduce(function(certs, res) { - return res.signed.reduce(function(certs, cert) { + certPubkeys = {}; + data.lookup.givenCertifications = (res.results || []).reduce(function(certs, res) { + return (res.signed || []).reduce(function(certs, cert) { var result = { pubkey: cert.pubkey, uid: cert.uid, @@ -291,60 +413,30 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c }; if (!certPubkeys[cert.pubkey]) { certPubkeys[cert.pubkey] = result; - // TODO : to not add, but replace the old one } else { // if duplicated cert: keep the most recent if (result.block > certPubkeys[cert.pubkey].block) { certPubkeys[cert.pubkey] = result; + // TODO: Replace the existing one ? May be not, to be able to see renewal + // (see issue #806) + // If yes (need to replace), check this code works: + //certs.splice(_.findIndex(certs, {pubkey: cert.pubkey}), 1, result); + //return certs; } else { - return certs; // skip this result + return certs; // skip this cert } } return certs.concat(result); }, certs); }, []); - // Retrieve time (self and revocation) - var blocks = [identity.number]; - if (identity.revocationNumber) { - blocks.push(identity.revocationNumber); - } - return BMA.blockchain.blocks(blocks) - .then(function(blocks){ - identity.sigDate = blocks[0].medianTime; - - // Check if self has been done on a valid block - if (identity.number !== 0 && identity.hash !== blocks[0].hash) { - identity.hasBadSelfBlock = true; - } - - // Set revocation time - if (identity.revocationNumber) { - identity.revocationTime = blocks[1].medianTime; - } - - return identity; - }) - .catch(function(err){ - // Special case for currency init (root block not exists): use now - if (err && err.ucode == BMA.errorCodes.BLOCK_NOT_FOUND && identity.number === 0) { - identity.sigDate = Math.trunc(new Date().getTime() / 1000); - return identity; - } - else { - throw err; - } - }); + return data; }) .catch(function(err) { if (!!err && err.ucode == BMA.errorCodes.NO_MATCHING_IDENTITY) { // Identity not found (if no self) - var identity = { - uid: null, - pubkey: pubkey, - hasSelf: false - }; - return identity; + _resetRequirements(data); + return data; } else { throw err; @@ -371,7 +463,7 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c return getFunction({ pubkey: pubkey }) .then(function(res) { - return res.certifications.reduce(function (res, cert) { + return (res && res.certifications || []).reduce(function (res, cert) { // Rappel : // cert.sigDate = blockstamp de l'identité // cert.cert_time.block : block au moment de la certification @@ -408,6 +500,12 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c isMember = false; return []; // continue (append pendings cert if exists in lookup) } + /*FIXME: workaround for Duniter issue #1309 */ + else if (!!err && err.ucode == 1002) { + console.warn("[wallet-service] Detecting Duniter issue #1309 ! Applying workaround... "); + isMember = false; + return []; // not found + } else { throw err; } @@ -523,19 +621,25 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c addEvents = function(data) { if (data.requirements.revoked) { - delete data.hasBadSelfBlock; - addEvent(data, {type: 'error', message: 'ERROR.IDENTITY_REVOKED', messageParams: {revocationTime: data.revocationTime}}); - console.debug("[wot] Identity [{0}] has been revoked".format(data.uid)); + delete data.requirements.meta.invalid; + if (data.requirements.revoked_on) { + addEvent(data, {type: 'error', message: 'ERROR.IDENTITY_REVOKED_WITH_TIME', messageParams: {revocationTime: data.requirements.revoked_on}}); + console.debug("[wot] Identity [{0}] has been revoked on {1}".format(data.uid, data.requirements.revoked_on)); + } + else { + addEvent(data, {type: 'error', message: 'ERROR.IDENTITY_REVOKED'}); + console.debug("[wot] Identity [{0}] has been revoked".format(data.uid)); + } } else if (data.requirements.pendingRevocation) { + delete data.requirements.meta.invalid; addEvent(data, {type:'error', message: 'ERROR.IDENTITY_PENDING_REVOCATION'}); console.debug("[wot] Identity [{0}] has pending revocation".format(data.uid)); } - else if (data.hasBadSelfBlock) { - delete data.hasBadSelfBlock; + else if (data.requirements.meta && data.requirements.meta.invalid) { if (!data.isMember) { addEvent(data, {type: 'error', message: 'ERROR.IDENTITY_INVALID_BLOCK_HASH'}); - console.debug("[wot] Invalid membership for {0}: block hash changed".format(data.uid)); + console.debug("[wot] Invalid membership for uid {0}: block hash changed".format(data.uid)); } } else if (data.requirements.expired) { @@ -550,25 +654,31 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c addEvent(data, {type: 'error', message: 'INFO.IDENTITY_NEED_MEMBERSHIP'}); console.debug("[wot] Identity {0} has a self but no membership".format(data.uid)); } + if (!data.isMember && data.requirements.alternatives) { + addEvent(data, {type: 'info', message: 'INFO.HAS_ALTERNATIVE_IDENTITIES'}); + } }, - loadData = function(pubkey, withCache, uid, force) { + loadData = function(pubkey, uid, options) { + options = options || {}; var data; - if (!pubkey && uid && !force) { + if (!pubkey && uid && !options.force) { return BMA.wot.member.getByUid(uid) .then(function(member) { - if (member) return loadData(member.pubkey, withCache, member.uid); // recursive call + if (member) return loadData(member.pubkey, member.uid, options); // recursive call, with a pubkey //throw {message: 'NOT_A_MEMBER'}; - return loadData(pubkey, withCache, uid, true/*force*/); + var options = angular.copy(options || {}); + options.force = true; + return loadData(pubkey, uid, options); // Loop with force=true }); } // Check cached data if (pubkey) { - data = withCache ? identityCache.get(pubkey) : null; - if (data && (!uid || data.uid == uid)) { + data = (options.cache !== false) ? identityCache.get(pubkey) : null; + if (data && (!uid || data.uid === uid) && (!options.blockUid || data.blockUid === options.blockUid)) { console.debug("[wot] Identity " + pubkey.substring(0, 8) + " found in cache"); return $q.when(data); } @@ -584,28 +694,29 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c uid: uid }; } + if (options.blockUid) { + data.blockUid = options.blockUid; + } - var now = new Date().getTime(); - + var now = Date.now(); var parameters; var medianTime; return $q.all([ // Get parameters - BMA.blockchain.parameters() + csCurrency.parameters() .then(function(res) { parameters = res; - }), // Get current time - BMA.blockchain.current() + csCurrency.blockchain.current() .then(function(current) { medianTime = current.medianTime; }) .catch(function(err){ // Special case for currency init (root block not exists): use now if (err && err.ucode == BMA.errorCodes.NO_CURRENT_BLOCK) { - medianTime = Math.trunc(new Date().getTime()/1000); + medianTime = moment.utc().unix(); } else { throw err; @@ -613,22 +724,28 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c }), // Get requirements - loadRequirements(data), + loadRequirements(data, options.cache !== false), // Get identity using lookup loadIdentityByLookup(pubkey, uid) - .then(function (identity) { - angular.merge(data, identity); - }) + ]) - .then(function() { - if (!data.requirements.uid) return; + .then(function(res) { + var dataByLookup = res[3]; + + // If no requirements found: copy from lookup data + if (!data.requirements.uid) { + console.debug("[wot] No requirements found: using data from lookup"); + angular.merge(data, dataByLookup); + delete data.lookup; // not need + return; + } var idtyFullKey = data.requirements.uid + '-' + data.requirements.meta.timestamp; return $q.all([ // Get received certifications - loadCertifications(BMA.wot.certifiersOf, data.pubkey, data.lookup ? data.lookup.certifications[idtyFullKey] : null, parameters, medianTime, true /*certifiersOf*/) + loadCertifications(BMA.wot.certifiersOf, data.pubkey, dataByLookup.lookup ? dataByLookup.lookup.certifications[idtyFullKey] : null, parameters, medianTime, true /*certifiersOf*/) .then(function (res) { data.received_cert = res.valid; data.received_cert_pending = res.pending; @@ -636,7 +753,7 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c }), // Get given certifications - loadCertifications(BMA.wot.certifiedBy, data.pubkey, data.lookup ? data.lookup.givenCertifications : null, parameters, medianTime, false/*certifiersOf*/) + loadCertifications(BMA.wot.certifiedBy, data.pubkey, dataByLookup.lookup ? dataByLookup.lookup.givenCertifications : null, parameters, medianTime, false/*certifiersOf*/) .then(function (res) { data.given_cert = res.valid; data.given_cert_pending = res.pending; @@ -663,9 +780,8 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c }) .then(function() { if (!data.pubkey) return undefined; // not found - delete data.lookup; // not need anymore identityCache.put(data.pubkey, data); // add to cache - console.debug('[wot] Identity '+ data.pubkey.substring(0, 8) +' loaded in '+ (new Date().getTime()-now) +'ms'); + console.debug('[wot] Identity '+ data.pubkey.substring(0, 8) +' loaded in '+ (Date.now()-now) +'ms'); return data; }); }, @@ -767,15 +883,13 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c return $q.all([ csCurrency.blockchain.current(true) .then(function(block) { - total = block.membersCount; + total = block.membersCount || 0; }), BMA.blockchain.stats.newcomers() ]) .then(function(res) { res = res[1]; - if (!res.result.blocks || !res.result.blocks.length) { - return null; - } + if (!res || !res.result || !res.result.blocks || !res.result.blocks.length) return null; // no result var blocks = _.sortBy(res.result.blocks, function (n) { return -n; }); @@ -790,13 +904,12 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c // Extension point return extendAll(idties, 'pubkey', true/*skipAddUid*/); }) - .then(function(idties) { - return { - hits: idties, - total: total - }; - }) - ; + .then(function(idties) { + return { + hits: idties, + total: total + }; + }); }, @@ -855,7 +968,7 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c getPending = function(offset, size) { offset = offset || 0; size = size || 20; - var now = new Date().getTime(); + var now = Date.now(); return $q.all([ BMA.wot.member.uids(), BMA.wot.member.pending() @@ -931,7 +1044,7 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c extendAll(idties, 'pubkey', true/*skipAddUid*/) ]) .then(function() { - console.debug("[ES] [wot] Loaded {0}/{1} pending identities in {2} ms".format(idties && idties.length || 0, total, new Date().getTime() - now)); + console.debug("[ES] [wot] Loaded {0}/{1} pending identities in {2} ms".format(idties && idties.length || 0, total, Date.now() - now)); return { hits: idties, total: total @@ -1064,6 +1177,11 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c event.messageParams = event.messageParams || {}; data.events = data.events || []; data.events.push(event); + }, + + cleanCache = function() { + console.debug("[wot] Cleaning cache..."); + csCache.clear(cachePrefix); } ; @@ -1071,6 +1189,9 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c api.registerEvent('data', 'load'); api.registerEvent('data', 'search'); + // Listen if node changed + BMA.api.node.on.stop($rootScope, cleanCache, this); + return { id: id, load: loadData, diff --git a/assets/www/dist/dist_js/app/templates.js b/assets/www/dist/dist_js/app/templates.js index 32a2453bb4df0f1507fd797c288f79e34a28046d..322fcd29abed218a0795518f8577bfc75bbd370f 100644 --- a/assets/www/dist/dist_js/app/templates.js +++ b/assets/www/dist/dist_js/app/templates.js @@ -1,103 +1,112 @@ -angular.module("cesium.templates", []).run(["$templateCache", function($templateCache) {$templateCache.put("templates/menu.html","<ion-side-menus enable-menu-with-back-views=\"true\" bind-notifier=\"{locale:$root.settings.locale.id}\"><ion-side-menu-content><ion-nav-bar class=\"bar-dark\" title-align=\"left\"><ion-nav-back-button class=\"no-text\"></ion-nav-back-button><ion-nav-buttons side=\"left\"><button class=\"button button-icon button-clear icon ion-navicon visible-nomenu\" menu-toggle=\"left\"></button></ion-nav-buttons><ion-nav-buttons side=\"right\"><cs-extension-point name=\"nav-buttons-right\"></cs-extension-point></ion-nav-buttons></ion-nav-bar><ion-nav-view name=\"menuContent\"></ion-nav-view></ion-side-menu-content><ion-side-menu id=\"menu\" side=\"left\" expose-aside-when=\"large\" enable-menu-with-back-views=\"false\" width=\"225\"><ion-header-bar><div class=\"visible-sm visible-xs hero\"><div class=\"content\"><i class=\"avatar avatar-member hero-icon\" ng-if=\"!$root.walletData.avatar\" ng-class=\"{\'royal-bg\': login, \'stable-bg\': !login}\" ng-click=\"!login ? showHome() : loginAndGo()\" menu-close=\"\"></i> <a class=\"avatar hero-icon\" ng-if=\"$root.walletData.avatar\" style=\"background-image: url(\'{{$root.walletData.avatar.src}}\')\" ui-sref=\"app.view_wallet\" menu-close=\"\"></a><h4 ng-if=\"login\"><a class=\"light\" ui-sref=\"app.view_wallet\" menu-close=\"\">{{$root.walletData.name||$root.walletData.uid}} <span ng-if=\"!$root.walletData.name && !$root.walletData.uid\"><i class=\"icon ion-key\"></i> {{$root.walletData.pubkey|formatPubkey}}</span></a></h4><h4 ng-if=\"!login\"><a class=\"light\" ui-sref=\"app.home\" menu-close=\"\">{{\'COMMON.BTN_LOGIN\'|translate}} <i class=\"ion-arrow-right-b\"></i></a></h4><cs-extension-point name=\"menu-profile-user\"></cs-extension-point></div><a ng-if=\"login\" class=\"button-icon\" ng-click=\"logout({askConfirm: true})\" style=\"position: absolute; top: 5px; left: 5px\"><i class=\"icon stable ion-android-exit\"></i></a></div></ion-header-bar><ion-content scroll=\"false\"><ion-list class=\"list\"><ion-item menu-close=\"\" class=\"item-icon-left hidden-xs\" ui-sref=\"app.home\" active-link=\"active\"><i class=\"icon ion-home\"></i> {{:locale:\'MENU.HOME\'|translate}}</ion-item><a menu-close=\"\" class=\"item item-icon-left\" active-link=\"active\" active-link-path-prefix=\"#/app/currency\" ui-sref=\"app.currency\"><i class=\"icon ion-ios-world-outline\"></i> {{:locale:\'MENU.CURRENCY\'|translate}} </a><a id=\"helptip-menu-btn-currency\"></a> <a id=\"helptip-menu-btn-network\"></a><cs-extension-point name=\"menu-discover\"></cs-extension-point><div class=\"item item-divider\"></div><a menu-close=\"\" class=\"item item-icon-left\" active-link=\"active\" active-link-path-prefix=\"#/app/wot\" ui-sref=\"app.wot_lookup.tab_search\"><i class=\"icon ion-person-stalker\"></i> {{:locale:\'MENU.WOT\'|translate}} </a><a id=\"helptip-menu-btn-wot\"></a><cs-extension-point name=\"menu-main\"></cs-extension-point><div class=\"item item-divider\"></div><a menu-close=\"\" class=\"item item-icon-left\" active-link=\"active\" active-link-path-prefix=\"#/app/wallet\" ui-sref=\"app.view_wallet\" ng-class=\"{\'item-menu-disable\': !login}\"><i class=\"icon ion-person\"></i> {{:locale:\'MENU.ACCOUNT\'|translate}} </a><a id=\"helptip-menu-btn-account\"></a> <a menu-close=\"\" class=\"item item-icon-left\" active-link=\"active\" active-link-path-prefix=\"#/app/history\" ui-sref=\"app.view_wallet_tx\" ng-class=\"{\'item-menu-disable\': !login}\"><i class=\"icon ion-card\"></i> {{:locale:\'MENU.TRANSACTIONS\'|translate}} </a><a id=\"helptip-menu-btn-tx\"></a><div class=\"item item-divider visible-xs visible-sm\"></div><cs-extension-point name=\"menu-user\"></cs-extension-point><a menu-close=\"\" class=\"item item-icon-left visible-xs visible-sm\" active-link=\"active\" active-link-path-prefix=\"#/app/settings\" ui-sref=\"app.settings\"><i class=\"icon ion-android-settings\"></i> {{:locale:\'MENU.SETTINGS\'|translate}} </a><a id=\"helptip-menu-btn-settings\"></a><div class=\"item item-divider\" ng-if=\"login\"></div><ion-item menu-close=\"\" class=\"item item-button-right\" ng-if=\"$root.device.barcode.enable\">{{:locale:\'MENU.SCAN\'|translate}} <button class=\"button button-stable ink\" ng-click=\"scanQrCodeAndGo()\"><i class=\"icon ion-qr-scanner\"></i></button></ion-item><cs-extension-point name=\"menu-actions\"></cs-extension-point></ion-list></ion-content></ion-side-menu></ion-side-menus>"); -$templateCache.put("templates/modal_about.html","<ion-modal-view class=\"about\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear visible-xs\" ng-click=\"closeModal()\" translate>COMMON.BTN_CLOSE</button><h1 class=\"title\" translate>ABOUT.TITLE</h1></ion-header-bar><ion-content class=\"text-center\" scroll=\"true\"><ion-list class=\"item-wrap-text\"><ion-item class=\"item-icon-left item-text-wrap\">{{\'COMMON.APP_NAME\'|translate}} <b>{{\'COMMON.APP_VERSION\'|translate:$root.config}}</b> <i ng-if=\"$root.newRelease\" class=\"assertive ion-alert-circled\"></i><h3 ng-if=\"$root.config.build\" class=\"gray\">{{\'COMMON.APP_BUILD\'|translate:$root.config}}</h3><span translate>ABOUT.LICENSE</span></ion-item><ion-item class=\"item-icon-left\" ng-if=\"$root.newRelease\"><i class=\"item-image icon ion-alert-circled assertive\"></i> <span ng-if=\"!$root.device.isWeb()\" ng-bind-html=\"\'ABOUT.PLEASE_UPDATE\' | translate:$root.newRelease \"></span> <span ng-if=\"$root.device.isWeb()\" ng-bind-html=\"\'ABOUT.LATEST_RELEASE\' | translate:$root.newRelease \"></span><h3 ng-if=\"!$root.device.enable\"><a ng-click=\"openLink($event, $root.newRelease.url)\" translate>{{::$root.newRelease.url}}</a></h3></ion-item><ion-item class=\"item-icon-left item-text-wrap\"><i class=\"item-image icon ion-bug\"></i> <span translate>ABOUT.PLEASE_REPORT_ISSUE</span><h3><a ng-click=\"openLink($event, $root.settings.newIssueUrl)\" translate>ABOUT.REPORT_ISSUE</a></h3></ion-item><ion-item class=\"item-icon-left\"><i class=\"item-image icon ion-network\"></i> {{\'ABOUT.CODE\' | translate}}<h3><a ng-click=\"openLink($event, \'https://git.duniter.org/clients/cesium/cesium\')\">https://git.duniter.org/clients/cesium/cesium</a></h3></ion-item><ion-item class=\"item-icon-left\"><i class=\"item-image icon ion-chatbubbles\"></i> {{\'ABOUT.FORUM\' | translate}}<h3><a ng-click=\"openLink($event, $root.settings.userForumUrl)\">{{::$root.settings.userForumUrl}}</a></h3></ion-item><ion-item class=\"item-icon-left\"><i class=\"item-image icon ion-person-stalker\"></i> {{\'ABOUT.DEVELOPERS\' | translate}}<h3><a href=\"https://github.com/blavenie\" target=\"_system\">Benoit Lavenier</a>, <a href=\"https://github.com/c-geek\" target=\"_system\">cgeek</a>, <a href=\"https://github.com/devingfx\" target=\"_system\">DiG</a>, <a href=\"https://git.duniter.org/ji_emme\" target=\"_system\">Ji_emme</a></h3></ion-item><div class=\"padding hidden-xs text-center\"><button class=\"button button-stable icon-left ink\" type=\"submit\" ng-click=\"closeModal()\" ui-sref=\"app.help\"><i class=\"icon ion-ios-help-outline\"></i> {{\'HOME.BTN_HELP\' | translate}}</button> <button class=\"button button-positive ink\" type=\"submit\" ng-click=\"closeModal()\">{{\'COMMON.BTN_CLOSE\' | translate}}</button></div></ion-list></ion-content></ion-modal-view>"); -$templateCache.put("templates/api/doc.html","<h2 class=\"padding\" translate=\"\">API.DOC.TRANSFER.TITLE</h2><div class=\"list padding no-padding-xs no-padding-top\"><div class=\"item item-divider no-border\"><p translate=\"\">API.DOC.DESCRIPTION_DIVIDER</p></div><div class=\"item item-text-wrap\"><p translate=\"\">API.DOC.TRANSFER.DESCRIPTION</p></div><div class=\"item item-divider no-border\"><p translate=\"\">API.DOC.URL_DIVIDER</p></div><div class=\"item item-text-wrap\"><p class=\"gray text-right\">{{$root.rootPath}}#/v1/payment/:pubkey?amount=<span class=\"text-italic\" translate=\"\">API.DOC.TRANSFER.PARAM_AMOUNT</span></p></div><div class=\"item item-divider no-border\"><p translate=\"\">API.DOC.PARAMETERS_DIVIDER</p></div><div class=\"item item-text-wrap\"><p translate=\"\">API.DOC.AVAILABLE_PARAMETERS</p><div class=\"row\"><div class=\"col col-20 text-italic\">pubkey</div><div class=\"col gray\" translate=\"\">API.DOC.TRANSFER.PARAM_PUBKEY_HELP</div></div><div class=\"row stable-bg\"><div class=\"col col-20 text-italic dark\">amount</div><div class=\"col gray\" translate=\"\">API.DOC.TRANSFER.PARAM_AMOUNT_HELP</div></div><div class=\"row\"><div class=\"col col-20 text-italic\">comment</div><div class=\"col gray\" translate=\"\">API.DOC.TRANSFER.PARAM_COMMENT_HELP</div></div><div class=\"row stable-bg\"><div class=\"col col-20 text-italic dark\">name</div><div class=\"col gray\" translate=\"\">API.DOC.TRANSFER.PARAM_NAME_HELP</div></div><div class=\"row\"><div class=\"col col-20 text-italic\">redirect_url</div><div class=\"col gray\" translate=\"\">API.DOC.TRANSFER.PARAM_REDIRECT_URL_HELP</div></div><div class=\"row stable-bg\"><div class=\"col col-20 text-italic dark\">cancel_url</div><div class=\"col gray\" translate=\"\">API.DOC.TRANSFER.PARAM_CANCEL_URL_HELP</div></div></div><div class=\"item item-divider no-border\"><p translate=\"\">API.DOC.DEMO_DIVIDER</p></div><div class=\"item item-button-right item-text-wrap padding-bottom\"><p class=\"item-icon-right-padding\" translate=\"\">API.DOC.DEMO_HELP</p><span class=\"badge\" ng-if=\"loading\"><ion-spinner class=\"icon\" icon=\"android\"></ion-spinner></span><a ng-if=\"!loading\" href=\"{{transferDemoUrl}}\" class=\"button button-raised button-positive icon ion-play\"></a></div><div class=\"item item-text-wrap\" ng-if=\"result.type === \'payment\' && !result.cancelled\"><h2 class=\"text-right balanced\" translate=\"\">API.DOC.DEMO_SUCCEED</h2><h4 class=\"gray\" translate=\"\">API.DOC.DEMO_RESULT</h4><p class=\"balanced-100-bg padding dark text-keep-lines\">{{result.content}}</p></div><div class=\"item item-text-wrap\" ng-if=\"result.type === \'payment\' && result.cancelled\"><h2 class=\"text-right assertive\" translate=\"\">API.DOC.DEMO_CANCELLED</h2></div><div class=\"item item-divider no-border\"><p translate=\"\">API.DOC.INTEGRATE_DIVIDER</p></div><div class=\"item item-text-wrap\"><p translate=\"\">API.DOC.TRANSFER.EXAMPLES_HELP</p><div class=\"row responsive-sm\"><div class=\"col col-20 text-italic\"><span translate=\"\">API.DOC.TRANSFER.EXAMPLE_BUTTON</span></div><div class=\"col gray no-border\"><p><i class=\"icon ion-code\"></i> <span translate=\"\">API.DOC.INTEGRATE_CODE</span></p><div class=\"item item-input\"><textarea class=\"gray\" select-on-click=\"\" rows=\"5\" ng-model=\"transferButton.html\" ng-model-options=\"{ debounce: 650 }\"></textarea></div><p class=\"padding-top\"><i class=\"icon ion-eye\"></i> <span translate=\"\">API.DOC.INTEGRATE_RESULT</span></p><div class=\"padding-left\" bind-notifier=\"{ notifierKey:watchedExpression }\"><ng-bind-html ng-bind-html=\"transferButton.html|trustAsHtml\"></ng-bind-html></div></div></div><div class=\"row responsive-sm\"><div class=\"col gray no-border\"><p class=\"padding-top\"><a class=\"positive\" ng-click=\"transferButton.showParameters=!transferButton.showParameters\"><i class=\"icon ion-wrench\"></i> <span translate=\"\">API.DOC.INTEGRATE_PARAMETERS</span> <i class=\"icon\" ng-class=\"{\'ion-arrow-down-b\': !transferButton.showParameters, \'ion-arrow-up-b\': transferButton.showParameters}\"></i></a></p><div ng-if=\"transferButton.showParameters\" class=\"padding-left\"><form id=\"transferForm\" class=\"stable-bg padding\"><p class=\"padding-top\"><i class=\"icon ion-key\"></i> {{\'API.DOC.TRANSFER.PARAM_PUBKEY\' | translate}} :</p><label class=\"item item-input\"><input type=\"text\" ng-model=\"transferData.pubkey\" ng-model-options=\"{ debounce: 650 }\" placeholder=\"{{\'API.DOC.TRANSFER.PARAM_PUBKEY_HELP\'|translate}}\"></label><p class=\"padding-top\"><i class=\"icon ion-pricetag\"></i> {{\'API.DOC.TRANSFER.PARAM_AMOUNT\' | translate}} :</p><label class=\"item item-input\"><input type=\"text\" ng-model=\"transferData.amount\" ng-model-options=\"{ debounce: 650 }\" placeholder=\"{{\'API.DOC.TRANSFER.PARAM_AMOUNT_HELP\'|translate}}\"></label><p class=\"padding-top\"><i class=\"icon ion-flag\"></i> {{\'API.DOC.TRANSFER.PARAM_COMMENT\' | translate}} :</p><label class=\"item item-input\"><input type=\"text\" ng-model=\"transferData.comment\" placeholder=\"{{\'API.DOC.TRANSFER.PARAM_COMMENT\'|translate}}\"></label><p class=\"padding-top\"><i class=\"icon ion-ios-world-outline\"></i> {{\'API.DOC.TRANSFER.PARAM_NAME\' | translate}} :</p><label class=\"item item-input\"><input type=\"text\" ng-model=\"transferData.name\" ng-model-options=\"{ debounce: 650 }\" placeholder=\"{{\'API.DOC.TRANSFER.PARAM_NAME\'|translate}}\"></label><p class=\"padding-top\"><i class=\"icon ion-arrow-return-left\"></i> {{\'API.DOC.TRANSFER.PARAM_REDIRECT_URL\' | translate}} :</p><label class=\"item item-input\"><input type=\"text\" ng-model=\"transferData.redirect_url\" ng-model-options=\"{ debounce: 650 }\" placeholder=\"{{\'API.DOC.TRANSFER.PARAM_REDIRECT_URL\'|translate}}\"></label><p class=\"padding-top\"><i class=\"icon ion-backspace\"></i> {{\'API.DOC.TRANSFER.PARAM_CANCEL_URL\' | translate}} :</p><label class=\"item item-input\"><input type=\"text\" ng-model=\"transferData.cancel_url\" ng-model-options=\"{ debounce: 650 }\" placeholder=\"{{\'API.DOC.TRANSFER.PARAM_CANCEL_URL\'|translate}}\"></label><p class=\"padding-top\"><a class=\"positive\" ng-click=\"transferButton.style.enable=!transferButton.style.enable\"><i class=\"icon\" ng-class=\"{\'ion-android-checkbox-outline\': transferButton.style.enable, \'ion-android-checkbox-outline-blank\': !transferButton.style.enable}\"></i> <span translate=\"\">API.DOC.TRANSFER.EXAMPLE_BUTTON_DEFAULT_STYLE</span></a></p><div ng-if=\"transferButton.style.enable\"><p class=\"padding-top\"><i class=\"icon ion-image\"></i> {{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_ICON\' | translate}} :</p><label class=\"item item-input item-select\"><select class=\"stable-bg dark\" ng-model=\"transferButton.style.icon\" style=\"width: 100%; max-width: 100%\" ng-options=\"l as (l.label | translate) for l in transferButton.icons track by l.filename\"></select></label><p class=\"padding-top\"><i class=\"icon ion-quote\"></i> {{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_HELP\' | translate}} :</p><label class=\"item item-input\"><input type=\"text\" ng-model=\"transferButton.style.text\" ng-model-options=\"{ debounce: 650 }\" placeholder=\"{{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_HELP\'|translate}}\"></label><p class=\"padding-top\"><i class=\"icon ion-paintbucket\"></i> {{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_BG_COLOR\' | translate}} :</p><label class=\"item item-input\"><input type=\"text\" ng-model=\"transferButton.style.bgColor\" ng-model-options=\"{ debounce: 650 }\" placeholder=\"{{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_BG_COLOR_HELP\'|translate}}\"></label><p class=\"padding-top\"><i class=\"icon ion-paintbrush\"></i> {{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_FONT_COLOR\' | translate}} :</p><label class=\"item item-input\"><input type=\"text\" ng-model=\"transferButton.style.fontColor\" ng-model-options=\"{ debounce: 650 }\" placeholder=\"{{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_FONT_COLOR_HELP\'|translate}}\"></label><p class=\"padding-top\"><i class=\"icon ion-ios-crop-strong\"></i> {{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_WIDTH\' | translate}} :</p><label class=\"item item-input\"><input type=\"text\" ng-model=\"transferButton.style.width\" ng-model-options=\"{ debounce: 650 }\" placeholder=\"{{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_WIDTH_HELP\'|translate}}\"></label></div></form></div></div></div></div></div>"); -$templateCache.put("templates/api/home.html","<ion-view class=\"circle-bg-dark\"><ion-nav-title><span class=\"title visible-xs visible-sm\" translate=\"\">API.HOME.TITLE</span></ion-nav-title><ion-nav-buttons side=\"right\"></ion-nav-buttons><ion-content class=\"has-header no-padding-xs positive-900-bg\"><br class=\"hidden-xs\"><div class=\"light text-center\"><h4 class=\"hidden-xs\" translate=\"\">API.HOME.MESSAGE</h4><h4 class=\"visible-xs padding\" translate=\"\">API.HOME.MESSAGE_SHORT</h4></div><br class=\"hidden-xs\"><div class=\"row no-padding-xs\"><div class=\"col\"><div class=\"light-bg no-padding\"><ng-include src=\"\'templates/api/doc.html\'\"></ng-include></div></div></div><p class=\"visible-xs visible-sm light padding-top text-center\">{{\'COMMON.APP_NAME\'|translate}} API - <a href=\"#\" ng-click=\"showAboutModal($event)\">v{{$root.config.version}}</a></p></ion-content></ion-view>"); -$templateCache.put("templates/api/locales_popover.html","<ion-popover-view class=\"fit popover-locales\" style=\"height: {{locales.length*48}}px\"><ion-content scroll=\"false\"><div class=\"list item-text-wrap block\"><a ng-repeat=\"l in locales track by l.id\" class=\"item item-icon-left ink\" ng-click=\"changeLanguage(l.id)\">{{l.label | translate}}</a></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/api/menu.html","<ion-nav-bar class=\"bar-dark\" title-align=\"left\"><ion-nav-back-button class=\"no-text\"></ion-nav-back-button><ion-nav-buttons side=\"left\"></ion-nav-buttons><ion-nav-buttons side=\"right\"></ion-nav-buttons></ion-nav-bar><ion-nav-view name=\"menuContent\"></ion-nav-view>"); -$templateCache.put("templates/api/transfer.html","<ion-view class=\"circle-bg-dark\"><ion-nav-buttons side=\"left\"><button class=\"button button-clear visible-xs\" ng-click=\"closeModal()\" translate=\"\">COMMON.BTN_CANCEL</button></ion-nav-buttons><ion-nav-title><span class=\"title visible-xs\" translate=\"\">API.TRANSFER.TITLE_SHORT</span></ion-nav-title><ion-nav-buttons side=\"right\"><button class=\"button button-positive button-icon button-clear icon ion-android-done visible-xs\" ng-click=\"doLogin()\"></button></ion-nav-buttons><ion-content class=\"has-header no-padding-xs positive-900-bg\"><br class=\"hidden-xs\"><div class=\"row no-padding-xs\"><div class=\"col no-padding-xs\"><div class=\"light-bg\"><h2 class=\"padding-top text-center hidden-xs\" translate=\"\">API.TRANSFER.TITLE</h2><div class=\"no-padding energized-100-bg\" ng-if=\"demo\"><div class=\"item item-icon-left item-text-wrap no-border\"><i class=\"icon ion-information-circled positive\"></i><p translate=\"\">API.TRANSFER.DEMO.HELP</p></div></div><ng-include src=\"\'templates/login/form_login.html\'\"></ng-include></div><br class=\"hidden-xs\"><br class=\"hidden-xs\"><div class=\"list padding no-padding-xs light-bg expert-mode\"><div class=\"item\"><p translate=\"\">API.TRANSFER.SUMMARY</p></div><div class=\"item item-icon-left-padding item-tx no-border\"><h2 translate=\"\">API.TRANSFER.AMOUNT</h2><div class=\"badge item-note badge-calm\" ng-bind-html=\"transferData.amount|formatAmount:{useRelative: false, currency: $root.currency.name}\"></div><div class=\"badge badge-secondary\" ng-bind-html=\"transferData.amount|formatAmount:{useRelative: true, currency: $root.currency.name}\"></div></div><div class=\"item item-icon-left-padding\" ng-if=\"transferData.name\"><h2 translate=\"\">API.TRANSFER.NAME</h2><div class=\"badge item-note\">{{transferData.name}}</div></div><div class=\"item item-icon-left-padding item-text-wrap\"><h2 translate=\"\">API.TRANSFER.PUBKEY</h2><div class=\"badge\"><span class=\"hidden-xs\"><br class=\"visible-sm visible-md\"><i class=\"icon ion-key\"></i>{{transferData.pubkey}}</span> <span class=\"visible-xs\" copy-on-click=\"{{transferData.pubkey}}\"><br class=\"visible-xs\"><i class=\"icon ion-key\"></i> {{transferData.pubkey|formatPubkey}}</span></div></div><div class=\"item item-icon-left-padding\"><h2 translate=\"\">API.TRANSFER.COMMENT</h2><div class=\"badge item-note\"><span class=\"hidden-xs\"><br class=\"visible-sm visible-md\">{{transferData.comment}}</span> <span class=\"visible-xs\" copy-on-click=\"{{transferData.comment}}\"><br>{{transferData.comment}}</span></div></div><div class=\"padding-bottom visible-xs\"> </div></div></div></div><p class=\"visible-xs visible-sm light padding-top text-center\">{{\'COMMON.APP_NAME\'|translate}} - <a href=\"#\" ng-click=\"showAboutModal($event)\">v{{$root.config.version}}</a></p></ion-content></ion-view>"); -$templateCache.put("templates/blockchain/item_block.html","<a name=\"block-{{:rebind:block.number}}\"></a><ion-item id=\"block-{{:rebind:block.number}}\" class=\"item item-icon-left item-block {{::ionItemClass}}\" ng-class=\"{\'ink\': !block.empty||!block.compacted, \'item-block-empty\': block.empty, \'compacted\': block.compacted && compactMode}\" ng-click=\"selectBlock(block)\"><i class=\"icon ion-cube stable\" ng-if=\":rebind:(!block.empty && !block.avatar)\"></i> <i class=\"avatar\" ng-if=\":rebind:!block.empty && block.avatar\" style=\"background-image: url(\'{{:rebind:block.avatar.src}}\')\"></i><div class=\"row no-padding\" ng-if=\":rebind:!block.compacted || !compactMode\"><div class=\"col\"><h4 ng-class=\"{\'gray\': block.compacted, \'dark\': !block.compacted}\"><i class=\"ion-clock\"></i> {{:rebind:block.medianTime|formatDate}}</h4><h4 ng-if=\"!block.empty\"><ng-if ng-if=\":rebind:block.joinersCount||(block.excludedCount-block.revokedCount)\"><i class=\"dark ion-person\"></i> <span class=\"dark\" ng-if=\":rebind:block.joinersCount\">+{{:rebind:block.joinersCount}}</span> <span class=\"dark\" ng-if=\":rebind:block.excludedCount\">-{{:rebind:block.excludedCount-block.revokedCount}}</span></ng-if><span class=\"dark\" ng-if=\":rebind:block.revokedCount\" class=\"assertive\"><i class=\"ion-minus-circled\"></i> {{:rebind:block.revokedCount}} </span> <span class=\"dark\" ng-if=\":rebind:block.activesCount\" class=\"gray\"><i class=\"gray ion-refresh\"></i> {{:rebind:block.activesCount}} </span> <span class=\"dark\" ng-if=\":rebind:block.certificationsCount\"><i class=\"ion-ribbon-a\"></i> {{:rebind:block.certificationsCount}} </span> <span class=\"dark\" ng-if=\":rebind:block.dividend\" class=\"gray\"><i class=\"gray ion-arrow-up-c\"></i> {{\'COMMON.UD\'|translate}} </span> <span class=\"dark\" ng-if=\":rebind:block.transactionsCount\"><i class=\"ion-card\">{{:rebind:block.transactionsCount}}</i></span></h4></div><div class=\"col col-33 positive hidden-md\"><h4><i class=\"ion-person\"></i> {{:rebind:block.name||block.uid}}</h4></div><div class=\"col col-20\"><span class=\"badge\" ng-class=\"{\'badge-balanced\': !$index , \'badge-calm\': $index && !block.compacted && !block.empty}\">{{:rebind:block.number|formatInteger}}</span></div></div></ion-item>"); -$templateCache.put("templates/blockchain/item_block_empty_lg.html","<a name=\"block-{{::block.number}}\"></a><div id=\"block-{{::block.number}}\" class=\"item item-block item-icon-left item-block-empty\" ng-class=\"{\'compacted\': block.compacted && compactMode}\" ng-click=\"selectBlock(block)\"><div class=\"row no-padding\" ng-if=\":rebind:!block.compacted || !compactMode\"><div class=\"col\"><h3 class=\"gray\"><i class=\"ion-clock\"></i> {{:rebind:block.medianTime|formatDate}}</h3></div><div class=\"col\"><h3><span class=\"gray\" ng-if=\":rebind:expertMode\"><i class=\"ion-key\"></i> {{:rebind:block.issuer|formatPubkey}} </span><span class=\"positive\"><i class=\"ion-person\"></i> {{:rebind:block.name||block.uid}}</span></h3></div><div class=\"col col-20\"></div><div class=\"col col-20\"><span class=\"badge\" ng-class=\"{\'badge-balanced\': !$index && search.type==\'last\'}\">{{block.number|formatInteger}}</span></div></div></div>"); -$templateCache.put("templates/blockchain/item_block_lg.html","<ion-item id=\"block-{{::block.number}}\" class=\"item item-block item-icon-left ink {{::ionItemClass}}\" ng-class=\"{{::ionItemClass}}\" ng-click=\"selectBlock(block)\"><i class=\"icon ion-cube stable\" ng-if=\":rebind:!block.avatar\"></i> <i class=\"avatar\" ng-if=\":rebind:!block.empty && block.avatar\" style=\"background-image: url(\'{{:rebind:block.avatar.src}}\')\"></i><div class=\"row no-padding\"><div class=\"col\"><h3 class=\"dark\"><i class=\"ion-clock\"></i> {{:rebind:block.medianTime|formatDate}}</h3><h4 class=\"gray\">{{:rebind:\'BLOCKCHAIN.HASH\'|translate}} {{:rebind:block.hash|formatHash}}</h4></div><div class=\"col\"><h3><span class=\"gray\" ng-if=\":rebind:expertMode\"><i class=\"ion-key\"></i> {{:rebind:block.issuer|formatPubkey}} </span><span class=\"positive\"><i class=\"ion-person\"></i> {{:rebind:block.name||block.uid}}</span></h3></div><div class=\"col col-20\"><small><ng-if ng-if=\":rebind:block.joinersCount||(block.excludedCount-block.revokedCount)\"><i class=\"ion-person\"></i> <span ng-if=\":rebind:block.joinersCount\">+{{:rebind:block.joinersCount}}</span> <span ng-if=\":rebind:block.excludedCount\">-{{:rebind:block.excludedCount-block.revokedCount}}</span> </ng-if><span ng-if=\":rebind:block.revokedCount\" class=\"assertive\"><i class=\"ion-minus-circled\"></i> -{{:rebind:block.revokedCount}} </span> <span ng-if=\":rebind:block.activesCount\"><i class=\"ion-refresh\"></i> {{:rebind:block.activesCount}} </span> <span ng-if=\":rebind:block.certificationsCount\"><i class=\"ion-ribbon-a\"></i> {{:rebind:block.certificationsCount}} </span> <span ng-if=\":rebind:block.dividend\"><i class=\"gray ion-arrow-up-c\"></i> {{:rebind:\'COMMON.UD\'|translate}} </span> <span ng-if=\":rebind:block.transactionsCount\"><i class=\"ion-card\">{{:rebind:block.transactionsCount}}</i> </span></small></div><div class=\"col col-20\"><span class=\"badge\" ng-class=\"{\'badge-balanced\': !$index && search.type==\'last\', \'badge-calm\': ($index || search.type!=\'last\')&& !block.compacted && !block.empty}\">{{:rebind:block.number}}</span></div></div></ion-item>"); -$templateCache.put("templates/blockchain/items_blocks.html","<div class=\"center padding\" ng-if=\"search.loading\"><ion-spinner icon=\"android\"></ion-spinner></div><ion-list class=\"animate-ripple padding padding-xs\"><div class=\"padding gray\" ng-if=\"!search.loading && !search.results.length\" translate>BLOCKCHAIN.LOOKUP.NO_BLOCK</div><ng-repeat ng-repeat=\"block in :rebind:search.results track by block.number\" ng-include=\"\'templates/blockchain/item_block.html\'\"></ng-repeat></ion-list><ion-infinite-scroll ng-if=\"search.hasMore\" icon=\"android\" on-infinite=\"showMore()\" distance=\"1%\"></ion-infinite-scroll>"); -$templateCache.put("templates/blockchain/link_identity.html","<a ui-sref=\"app.wot_identity({pubkey: identity.pubkey, uid: identity.uid})\"><span class=\"positive\" ng-if=\"identity.uid\"><i class=\"icon ion-person\"></i> {{::identity.uid}} </span> <span class=\"gray\" ng-class=\"{\'hidden-xs hidden-sm\': identity.uid}\"><i class=\"icon ion-key\"></i> {{::identity.pubkey|formatPubkey}}</span></a>"); -$templateCache.put("templates/blockchain/list_blocks.html","<div class=\"center padding\" ng-if=\"search.loading\"><ion-spinner icon=\"android\"></ion-spinner></div><ion-list class=\"padding padding-xs list-blocks\" ng-class=\"::motion.ionListClass\"><div class=\"padding gray\" ng-if=\"!search.loading && !search.results.length\" translate>BLOCKCHAIN.LOOKUP.NO_BLOCK</div><ng-repeat ng-repeat=\"block in :rebind:search.results track by block.number\" ng-include=\"\'templates/blockchain/item_block.html\'\"></ng-repeat></ion-list><ion-infinite-scroll ng-if=\"search.hasMore\" spinner=\"android\" on-infinite=\"showMore()\" distance=\"1%\"></ion-infinite-scroll>"); -$templateCache.put("templates/blockchain/list_blocks_lg.html","<div class=\"padding padding-xs\" style=\"display: block; height: 100px\"><h4 translate>BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4><div class=\"pull-right\"><a class=\"button button-text button-small ink\" ng-class=\"{\'button-text-positive\': compactMode, \'button-text-stable\': !compactMode}\" ng-click=\"toggleCompactMode()\"><i class=\"icon ion-navicon\"></i> <b class=\"ion-arrow-down-b\" style=\"position: absolute; top: -2px; left: 4px; font-size: 8px\"></b> <b class=\"ion-arrow-up-b\" style=\"position: absolute; top: 10px; left: 4px; font-size: 8px\"></b> <span>{{\'BLOCKCHAIN.LOOKUP.BTN_COMPACT\'|translate}}</span></a></div></div><div class=\"center padding\" ng-if=\"search.loading\"><ion-spinner icon=\"android\"></ion-spinner></div><ion-list class=\"padding padding-xs list-blocks\" ng-class=\"::motion.ionListClass\"><div class=\"padding gray\" ng-if=\"!search.loading && !search.results.length\" translate>BLOCKCHAIN.LOOKUP.NO_BLOCK</div><ng-repeat ng-repeat=\"block in search.results\" ng-include=\"!block.empty ? \'templates/blockchain/item_block_lg.html\' : \'templates/blockchain/item_block_empty_lg.html\'\"></ng-repeat></ion-list><ion-infinite-scroll ng-if=\"search.hasMore\" spinner=\"android\" on-infinite=\"showMore()\" distance=\"1%\"></ion-infinite-scroll>"); -$templateCache.put("templates/blockchain/lookup.html","<ion-view><ion-nav-title><span translate>BLOCKCHAIN.LOOKUP.TITLE</span></ion-nav-title><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><ng-include src=\"\'templates/blockchain/list_blocks.html\'\"></ng-include></ion-content></ion-view>"); -$templateCache.put("templates/blockchain/lookup_lg.html","<ion-view><ion-nav-title><span translate>BLOCKCHAIN.LOOKUP.TITLE</span></ion-nav-title><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><ng-include src=\"\'templates/blockchain/list_blocks_lg.html\'\"></ng-include></ion-content></ion-view>"); -$templateCache.put("templates/blockchain/unlock_condition_popover.html","<ion-popover-view class=\"fit\"><ion-header-bar><h1 class=\"title\" translate>BLOCKCHAIN.VIEW.TX_OUTPUT_UNLOCK_CONDITIONS</h1></ion-header-bar><ion-content scroll=\"true\"><div class=\"row\" ng-repeat=\"condition in popoverData.unlockConditions track by $index\" ng-style=\"::condition.style\"><span class=\"gray\" ng-if=\"::condition.operator\">{{::\'BLOCKCHAIN.VIEW.TX_OUTPUT_OPERATOR.\'+condition.operator|translate}} </span><div ng-if=\"::condition.type==\'SIG\'\"><i class=\"icon ion-key dark\"></i> <span class=\"dark\" ng-bind-html=\"::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.SIG\' | translate\"></span> <a ng-click=\"goState(\'app.wot_identity\', {pubkey:condition.value})\" style=\"text-decoration: none\" class=\"positive\">{{condition.value|formatPubkey}}</a></div><div ng-if=\"::condition.type==\'XHX\'\"><i class=\"icon ion-lock-combination dark\"></i> <span class=\"dark\" ng-bind-html=\"::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.XHX\' | translate\"></span> <a copy-on-click=\"{{::condition.value}}\" class=\"positive\">{{::condition.value|formatPubkey}}...</a></div><div ng-if=\"condition.type==\'CSV\'\"><i class=\"icon ion-clock dark\"></i> <span class=\"dark\" ng-bind-html=\"::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CSV\' | translate\"></span> {{::condition.value|formatDuration}}</div><div ng-if=\"condition.type==\'CLTV\'\"><i class=\"icon ion-clock dark\"></i> <span class=\"dark\" ng-bind-html=\"::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CLTV\' | translate\"></span> {{::condition.value|formatDate}}</div></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/blockchain/view_block.html","<ion-view><ion-nav-title><span class=\"title visible-xs visible-sm\" ng-if=\"number==\'current\'\">{{\'BLOCKCHAIN.VIEW.TITLE_CURRENT\'|translate}}</span> <span class=\"title visible-xs visible-sm\" ng-if=\"number!=\'current\'\">{{\'BLOCKCHAIN.VIEW.TITLE\'|translate:formData}}</span></ion-nav-title><ion-content class=\"no-padding-xs\" scroll=\"true\"><div class=\"row no-padding\"><div class=\"col no-padding\"><div class=\"center padding\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></div><ion-list class=\"item-text-wrap no-padding-xs\" ng-if=\"!loading\"><div class=\"item item-text-wrap\"><h3><span class=\"dark\"><i class=\"icon ion-clock\"></i> {{formData.medianTime | formatDate}} </span><span class=\"gray\">| {{formData.medianTime | formatFromNow}}</span></h3><h3><span class=\"dark\"><i class=\"icon ion-lock-combination\"></i> {{\'BLOCKCHAIN.VIEW.COMPUTED_BY\'|translate}} </span><a class=\"positive\" ui-sref=\"app.wot_identity({pubkey:issuer.pubkey, uid: issuer.uid})\"><i class=\"icon ion-person positive\"></i> {{issuer.name||issuer.uid}} <span class=\"gray\" ng-if=\"issuer.name\">({{issuer.uid}})</span></a></h3><h3><a ng-click=\"openRawBlock($event)\"><i class=\"icon ion-share\"></i> {{\'BLOCKCHAIN.VIEW.SHOW_RAW\'|translate}}</a></h3></div><span class=\"item item-divider\">{{\'BLOCKCHAIN.VIEW.TECHNICAL_DIVIDER\' | translate}}</span><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"!compactMode || $root.settings.expertMode\"><i class=\"icon ion-gear-b\"></i> {{\'BLOCKCHAIN.VIEW.VERSION\'|translate}} <span class=\"badge badge-stable\">{{::formData.version}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"!compactMode || $root.settings.expertMode\" copy-on-click=\"{{::formData.powMin}}\"><i class=\"icon ion-lock-combination\"></i> {{\'BLOCKCHAIN.VIEW.POW_MIN\'|translate}}<h4 class=\"gray\">{{\'BLOCKCHAIN.VIEW.POW_MIN_HELP\'|translate}}</h4><span class=\"badge badge-stable\">{{::formData.powMin}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" copy-on-click=\"{{::formData.hash}}\"><i class=\"icon ion-pound\"></i> {{\'BLOCKCHAIN.VIEW.HASH\'|translate}}<h5 class=\"visible-xs visible-sm dark\">{{::formData.hash}}</h5></ion-item><span class=\"item item-divider\">{{\'BLOCKCHAIN.VIEW.DATA_DIVIDER\' | translate}}</span><ion-item ng-if=\"compactMode && formData.empty\" class=\"item-icon-left item-text-wrap\">{{\'BLOCKCHAIN.VIEW.EMPTY\'|translate}}</ion-item><ion-item ng-if=\"!compactMode || formData.dividend\" class=\"item-icon-left item-text-wrap\" copy-on-click=\"{{::formData.dividend/100}}\"><i class=\"icon ion-arrow-up-c\"></i><div class=\"col col-60\">{{\'COMMON.UNIVERSAL_DIVIDEND\'|translate}}<h4 class=\"gray\">{{\'BLOCKCHAIN.VIEW.UNIVERSAL_DIVIDEND_HELP\'|translate: {membersCount: formData.membersCount} }}</h4></div><span class=\"badge badge-balanced\" ng-if=\"formData.dividend\">+1 <span ng-bind-html=\"formData.currency|currencySymbol: {useRelative: true} \"></span> / {{\'COMMON.MEMBER\'|translate|lowercase}} </span><span class=\"badge badge-stable\" ng-if=\"!formData.dividend\">0</span> <span class=\"badge badge-secondary\" ng-if=\"formData.dividend\">+ {{formData.dividend| formatAmount: {currency: formData.currency, useRelative: false} }} / {{\'COMMON.MEMBER\'|translate|lowercase}}</span></ion-item><ng-if ng-if=\"!compactMode || formData.identitiesCount\"><ion-item class=\"item-icon-left\"><i class=\"icon ion-person\"></i> <b class=\"ion-clock\" style=\"position: absolute; top: 16px; left: 39px; font-size: 12px\"></b> {{\'BLOCKCHAIN.VIEW.IDENTITIES_COUNT\'|translate}} <span class=\"badge badge-balanced\" ng-if=\"formData.identitiesCount\">+{{::formData.identitiesCount}}</span> <span class=\"badge badge-stable\" ng-if=\"!formData.identitiesCount\">0</span></ion-item><div class=\"padding-bottom item-icon-left-padding item-icon-right-padding\" ng-if=\"formData.identitiesCount\"><ion-item ng-repeat=\"identity in ::formData.identities\" class=\"item-border-large item-small-height\" ng-include=\"\'templates/blockchain/link_identity.html\'\"></ion-item></div></ng-if><ng-if ng-if=\"!compactMode || formData.joinersCount\"><ion-item class=\"item-icon-left\"><i class=\"icon ion-person-add\"></i> {{\'BLOCKCHAIN.VIEW.JOINERS_COUNT\'|translate}} <span class=\"badge badge-balanced\" ng-if=\"formData.joinersCount\">+{{::formData.joinersCount}}</span> <span class=\"badge badge-stable\" ng-if=\"!formData.joinersCount\">0</span></ion-item><div class=\"padding-bottom item-icon-left-padding item-icon-right-padding\" ng-if=\"formData.joinersCount\"><ion-item ng-repeat=\"identity in ::formData.joiners\" class=\"item-border-large item-small-height\" ng-include=\"\'templates/blockchain/link_identity.html\'\"></ion-item></div></ng-if><ng-if ng-if=\"!compactMode || formData.activesCount\"><ion-item class=\"item-icon-left\"><i class=\"icon ion-person\"></i> <b class=\"ion-refresh\" style=\"position: absolute; top: 25px; left: 39px; font-size: 12px\"></b> {{\'BLOCKCHAIN.VIEW.ACTIVES_COUNT\'|translate}}<h4 class=\"gray\">{{\'BLOCKCHAIN.VIEW.ACTIVES_COUNT_HELP\'|translate}}</h4><span class=\"badge badge-balanced\" ng-if=\"formData.activesCount\">{{::formData.activesCount}}</span> <span class=\"badge badge-stable\" ng-if=\"!formData.activesCount\">0</span></ion-item><div class=\"padding-bottom item-icon-left-padding item-icon-right-padding\" ng-if=\"formData.activesCount\"><ion-item ng-repeat=\"identity in ::formData.actives\" class=\"item-border-large item-small-height\" ng-include=\"\'templates/blockchain/link_identity.html\'\"></ion-item></div></ng-if><ng-if ng-if=\"!compactMode || (formData.excludedCount-formData.revokedCount)\"><ion-item class=\"item-icon-left\"><i class=\"icon ion-person\"></i> <b class=\"ion-close dark\" style=\"position: absolute; top: 25px; left: 39px; font-size: 12px\"></b> {{\'BLOCKCHAIN.VIEW.EXCLUDED_COUNT\'|translate}}<h4 class=\"gray\">{{\'BLOCKCHAIN.VIEW.EXCLUDED_COUNT_HELP\'|translate}}</h4><span class=\"badge badge-assertive\" ng-if=\"formData.excludedCount-formData.revokedCount\">-{{::formData.excludedCount-formData.revokedCount}}</span> <span class=\"badge badge-stable\" ng-if=\"!(formData.excludedCount-formData.revokedCount)\">0</span></ion-item><div class=\"padding-bottom item-icon-left-padding item-icon-right-padding\" ng-if=\"formData.excludedCount\"><ion-item ng-repeat=\"identity in ::formData.excluded\" class=\"item-border-large item-small-height\" ng-include=\"\'templates/blockchain/link_identity.html\'\"></ion-item></div></ng-if><ng-if ng-if=\"!compactMode || formData.leaversCount\"><ion-item class=\"item-icon-left\" ng-if=\"!compactMode || formData.leaversCount\"><i class=\"icon ion-person\"></i> <b class=\"ion-minus\" style=\"position: absolute; top: 25px; left: 39px; font-size: 12px\"></b> {{\'BLOCKCHAIN.VIEW.LEAVERS_COUNT\'|translate}}<h4 class=\"gray\">{{\'BLOCKCHAIN.VIEW.LEAVERS_COUNT_HELP\'|translate}}</h4><span class=\"badge badge-assertive\" ng-if=\"formData.leaversCount\">-{{::formData.leaversCount}}</span> <span class=\"badge badge-stable\" ng-if=\"!formData.leaversCount\">0</span></ion-item><div class=\"padding-bottom item-icon-left-padding item-icon-right-padding\" ng-if=\"formData.leaversCount\"><ion-item ng-repeat=\"identity in ::formData.leavers\" class=\"item-border-large item-small-height\" ng-include=\"\'templates/blockchain/link_identity.html\'\"></ion-item></div></ng-if><ng-if ng-if=\"!compactMode || formData.revokedCount\"><ion-item class=\"item-icon-left\"><i class=\"icon ion-person\"></i> <b class=\"ion-minus-circled assertive\" style=\"position: absolute; top: 25px; left: 39px; font-size: 12px\"></b> {{\'BLOCKCHAIN.VIEW.REVOKED_COUNT\'|translate}}<h4 class=\"gray\">{{\'BLOCKCHAIN.VIEW.REVOKED_COUNT_HELP\'|translate}}</h4><span class=\"badge badge-balanced\" ng-if=\"formData.revokedCount\">-{{::formData.revokedCount}}</span> <span class=\"badge badge-stable\" ng-if=\"!formData.revokedCount\">0</span></ion-item><div class=\"padding-bottom item-icon-left-padding item-icon-right-padding\" ng-if=\"formData.revokedCount\"><ion-item ng-repeat=\"identity in ::formData.revoked\" class=\"item-border-large item-small-height\" ng-include=\"\'templates/blockchain/link_identity.html\'\"></ion-item></div></ng-if><ng-if ng-if=\"!compactMode || formData.certificationsCount\"><ion-item class=\"item-icon-left\"><i class=\"icon ion-ribbon-a\"></i> {{\'BLOCKCHAIN.VIEW.CERT_COUNT\'|translate}} <span class=\"badge badge-stable\" ng-class=\"{\'badge-positive\':formData.certificationsCount}\">{{::formData.certificationsCount}}</span></ion-item><div class=\"padding-bottom item-icon-left-padding item-icon-right-padding no-padding-xs\" ng-if=\"formData.certificationsCount\"><div ng-repeat=\"(key, certs) in formData.certifications\" class=\"item item-border-large item-small-height\"><div class=\"row no-padding\"><div class=\"col col-center no-padding\"><ng-repeat ng-repeat=\"cert in certs\"><ng-include src=\"\'templates/blockchain/link_identity.html\'\" onload=\"identity=cert.from\"></ng-include><br></ng-repeat></div><div class=\"col col-10 col-center gray text-center no-padding\"><h2><i class=\"icon ion-arrow-right-a\"></i></h2></div><div class=\"col col-40 col-center no-padding\" ng-include=\"\'templates/blockchain/link_identity.html\'\" onload=\"identity=certs[0].to\"></div></div></div></div></ng-if><ng-if ng-if=\"!compactMode || formData.transactionsCount\"><ion-item class=\"item-icon-left\"><i class=\"icon ion-card\"></i> {{\'BLOCKCHAIN.VIEW.TX_COUNT\'|translate}} <span class=\"badge badge-stable\" ng-class=\"{\'badge-positive\':formData.transactionsCount}\">{{::formData.transactionsCount}}</span></ion-item><div class=\"padding-bottom item-icon-left-padding item-icon-right-padding no-padding-xs\" ng-if=\"formData.transactionsCount\"><div ng-repeat=\"tx in ::formData.transactions\" class=\"item item-small-height item-border-large\"><div class=\"row no-padding\" style=\"padding-top: 3px\"><div class=\"col col-40 col-center no-padding list no-margin\"><div ng-repeat=\"identity in ::tx.issuers\" class=\"item no-padding item-small-height\"><ng-include src=\"\'templates/blockchain/link_identity.html\'\"></ng-include></div></div><div class=\"col col-10 col-center gray text-center no-padding\"><h2><i class=\"icon ion-arrow-right-a\"></i></h2></div><div class=\"col no-padding padding-right no-padding-xs col-text-wrap list no-margin\"><span class=\"gray\" ng-if=\"tx.toHimself\" translate=\"\">BLOCKCHAIN.VIEW.TX_TO_HIMSELF</span><div ng-repeat=\"output in ::tx.outputs\" class=\"item no-padding item-small-height\"><ng-include ng-if=\"::output.pubkey\" src=\"\'templates/blockchain/link_identity.html\'\" onload=\"identity=output\"></ng-include><span ng-if=\"::!output.pubkey && output.unlockFunctions\"><i class=\"icon ion-locked\"></i> (<a ng-click=\"showUnlockConditionPopover(output, $event)\"> <i ng-repeat=\"unlockFunction in ::output.unlockFunctions\" ng-class=\"::{\'ion-key\': (unlockFunction==\'SIG\'), \'ion-clock\': (unlockFunction==\'CSV\' || unlockFunction==\'CLTV\'), \'ion-lock-combination\': (unlockFunction==\'XHX\') }\" class=\"icon\"></i> </a>) </span><span class=\"badge badge-balanced\" ng-bind-html=\"::output.amount | formatAmount:{currency: formData.currency, useRelative: false} \"></span></div></div></div></div></div></ng-if></ion-list></div><div class=\"col col-15 hidden-xs\"></div></div></ion-content></ion-view>"); -$templateCache.put("templates/common/badge_certification_count.html","<span ng-attr-id=\"{{$ctrl.csId}}\" class=\"badge badge-balanced\" ng-class=\"{\'badge-energized\': $ctrl.requirements.willNeedCertificationCount || ($ctrl.requirements.needCertificationCount + $ctrl.requirements.pendingCertificationCount >= $ctrl.parameters.sigQty),\n \'badge-assertive\': ($ctrl.requirements.needCertificationCount + $ctrl.requirements.pendingCertificationCount < $ctrl.parameters.sigQty)}\"><span ng-if=\"$ctrl.requirements.certificationCount || !$ctrl.requirements.pendingCertificationCount\"><i ng-if=\"!$ctrl.requirements.needCertificationCount\" class=\"ion-android-done\"></i> {{$ctrl.requirements.certificationCount}} <i ng-if=\"$ctrl.requirements.willNeedCertificationCount\" class=\"ion-android-warning\"></i> </span><span ng-if=\"$ctrl.requirements.pendingCertificationCount\"><ng-if ng-if=\"$ctrl.requirements.certificationCount\">+</ng-if><i class=\"ion-clock\"></i> {{$ctrl.requirements.pendingCertificationCount}}</span></span>"); -$templateCache.put("templates/common/badge_given_certification_count.html","<div ng-attr-id=\"{{$ctrl.csId}}\" class=\"badge badge-calm\" ng-class=\"{\'badge-assertive\': $ctrl.identity.given_cert.length >= $ctrl.parameters.sigStock}\"><span><i ng-if=\"$ctrl.identity.given_cert.length\" class=\"ion-android-done\"></i> {{$ctrl.identity.given_cert.length}} </span><span ng-if=\"$ctrl.identity.given_cert_pending.length\">(<ng-if ng-if=\"$ctrl.identity.given_cert.length\">+</ng-if><i class=\"ion-clock\"></i> {{$ctrl.identity.given_cert_pending.length}}) </span><small>/ {{$ctrl.parameters.sigStock}}</small></div>"); -$templateCache.put("templates/common/form_error_messages.html","<div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT\"></span></div><div class=\"form-error\" ng-message=\"maxlength\"><span translate=\"ERROR.FIELD_TOO_LONG\"></span></div><div class=\"form-error\" ng-message=\"pattern\"><span translate=\"ERROR.FIELD_ACCENT\"></span></div><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div>"); -$templateCache.put("templates/common/popover_copy.html","<ion-popover-view class=\"popover-copy\" style=\"height: {{(!rows || rows <= 1) ? 50 : rows*22}}px\"><ion-content scroll=\"false\"><div class=\"list\"><div class=\"item item-input\"><input type=\"text\" ng-if=\"!rows || rows <= 1\" ng-model=\"value\"><textarea ng-if=\"rows && rows > 1\" ng-model=\"value\" rows=\"{{rows}}\" cols=\"10\">\n </textarea></div></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/common/popover_helptip.html","<ion-popover-view class=\"popover-helptip\"><ion-content scroll=\"false\" class=\"list\"><p><i ng-if=\"icon.position && !icon.position.startsWith(\'bottom-\')\" class=\"{{icon.class}} icon-{{icon.position}} hidden-xs\" style=\"{{icon.style}}\"></i><a ng-click=\"closePopover()\" class=\"pull-right button-close\" ng-class=\"{\'pull-left\': icon.position === \'right\', \'pull-right\': icon.position !== \'right\'}\"><i class=\"ion-close\"></i> </a><span> </span></p><p class=\"padding light\"><ng-bind-html ng-bind-html=\"content | translate:contentParams\"></ng-bind-html><ng-bind-html ng-bind-html=\"trustContent\"></ng-bind-html></p><div class=\"text-center\" ng-if=\"!tour\"><button class=\"button button-small button-stable\" ng-if=\"!hasNext\" ng-click=\"closePopover(true)\" translate>COMMON.BTN_UNDERSTOOD</button> <button class=\"button button-small button-stable\" id=\"helptip-btn-ok\" ng-if=\"hasNext\" ng-click=\"closePopover(false)\" translate>COMMON.BTN_UNDERSTOOD</button> <button id=\"helptip-btn-ok\" class=\"button button-small button-positive icon-right ink\" ng-if=\"hasNext\" ng-click=\"closePopover(true)\"><i class=\"icon ion-chevron-right\"></i></button></div><div class=\"text-center\" ng-if=\"tour\"><button class=\"button button-small button-positive\" id=\"helptip-btn-ok\" ng-if=\"!hasNext\" ng-click=\"closePopover(false)\" translate>COMMON.BTN_CLOSE</button> <button id=\"helptip-btn-ok\" class=\"button button-small button-positive icon-right ink\" ng-if=\"hasNext\" ng-click=\"closePopover(true)\">{{\'COMMON.BTN_CONTINUE\'|translate}} <i class=\"icon ion-chevron-right\"></i></button></div><p><i ng-if=\"icon.position && icon.position.startsWith(\'bottom-\')\" class=\"{{icon.class}} icon-{{icon.position}} hidden-xs\"></i></p></ion-content></ion-popover-view>"); -$templateCache.put("templates/common/popover_profile.html",""); -$templateCache.put("templates/common/popover_share.html","<ion-popover-view class=\"popover-share\"><ion-content scroll=\"false\"><div class=\"bar bar-header\"><h1 class=\"title\">{{titleKey|translate:titleValues}}</h1><span class=\"gray pull-right\">{{time|formatDate}}</span></div><div class=\"list no-margin no-padding has-header has-footer block\"><div class=\"item item-input\"><input type=\"text\" ng-model=\"value\"></div></div><div class=\"bar bar-footer\"><div class=\"button-bar\"><a class=\"button button-icon positive icon ion-social-facebook\" href=\"https://www.facebook.com/sharer/sharer.php?u={{postUrl|formatEncodeURI}}&title={{postMessage|formatEncodeURI}}\" onclick=\"window.open(this.href, \'facebook-share\',\'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,width=580,height=296\');return false;\" title=\"{{\'COMMON.POPOVER_SHARE.SHARE_ON_FACEBOOK\'|translate}}\"></a> <a class=\"button button-icon positive icon ion-social-twitter\" href=\"https://twitter.com/intent/tweet?url={{postUrl|formatEncodeURI}}&text={{postMessage|formatEncodeURI}}\" onclick=\"window.open(this.href, \'twitter-share\',\'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,width=580,height=296\');return false;\" title=\"{{\'COMMON.POPOVER_SHARE.SHARE_ON_TWITTER\'|translate}}\"></a> <a class=\"button button-icon positive icon ion-social-googleplus\" href=\"https://plus.google.com/share?url={{postUrl|formatEncodeURI}}\" onclick=\"window.open(this.href, \'google-plus-share\', \'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=296,width=580\');return false;\" title=\"{{\'COMMON.POPOVER_SHARE.SHARE_ON_GOOGLEPLUS\'|translate}}\"></a> <a class=\"button button-icon positive icon ion-social-diaspora\" href=\"https://sharetodiaspora.github.io/?title={{postMessage|formatEncodeURI}}&url={{postUrl|formatEncodeURI}}\" onclick=\"window.open(this.href, \'diaspora-share\',\'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,width=580,height=296\');return false;\" title=\"{{\'COMMON.POPOVER_SHARE.SHARE_ON_DIASPORA\'|translate}}\"></a> <a class=\"button-close\" title=\"{{\'COMMON.BTN_CLOSE\'|translate}}\" ng-click=\"closePopover()\"><i class=\"icon ion-close\"></i></a></div></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/common/popup_password.html","<form name=\"pwdForm\" ng-submit=\"submit($event)\"><div class=\"list\" ng-init=\"setForm(pwdForm)\"><label class=\"item item-input\" ng-class=\"{\'item-input-error\': pwdForm.$submitted && pwdForm.password.$invalid}\"><input name=\"password\" type=\"password\" placeholder=\"{{\'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.PASSWORD_HELP\' | translate}}\" ng-model=\"formData.password\" ng-minlength=\"1\" required></label><div class=\"form-errors\" ng-if=\"pwdForm.$submitted && pwdForm.pseudo.$error\" ng-messages=\"pwdForm.password.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div><div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT\"></span></div></div></div></form>"); -$templateCache.put("templates/common/view_passcode.html","<ion-view left-buttons=\"leftButtons\"><ion-nav-title><span class=\"visible-xs visible-sm\" translate>COMMON.PASSCODE.TITLE</span></ion-nav-title><ion-content scroll=\"false\"></ion-content></ion-view>"); -$templateCache.put("templates/currency/items_network.html","<ion-item id=\"helptip-network-blockchain\" class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-clock\"></i> <span class=\"col col-60\" translate=\"\">CURRENCY.VIEW.MEDIAN_TIME</span> <span class=\"badge badge-stable\">{{formData.medianTime | formatDate}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-lock-combination\"></i> <span class=\"col col-75\" translate=\"\">CURRENCY.VIEW.POW_MIN</span> <span class=\"badge badge-stable\">{{formData.difficulty | formatInteger}}</span></ion-item><cs-extension-point name=\"network-actual\"></cs-extension-point><div class=\"item item-divider\"><span translate=\"\">CURRENCY.VIEW.NETWORK_RULES_DIVIDER</span></div><ion-item class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-clock\" style=\"position: absolute; font-size: 20px; left: 16px; margin-top: 11px\"></i> <b class=\"icon-secondary ion-lock-combination\" style=\"left: 14px; margin-top: -4px\"></b> <b class=\"icon-secondary ion-arrow-right-c\" style=\"font-size: 12px; left: 28px; margin-top: -4px\"></b> <b class=\"icon-secondary ion-lock-combination\" style=\"left: 38px; margin-top: -4px\"></b> <span class=\"col col-75\" translate=\"\">CURRENCY.VIEW.AVG_GEN_TIME</span> <span class=\"badge badge-stable\">{{formData.avgGenTime | formatDuration}}</span></ion-item><div id=\"helptip-network-peers\" class=\"item item-divider\"><div class=\"pull-left\"><span ng-if=\"search.type==\'member\'\" translate=\"\">PEER.MEMBERS</span> <span ng-if=\"search.type==\'mirror\'\" translate=\"\">PEER.MIRRORS</span> <span ng-if=\"search.type==\'offline\'\" translate=\"\">PEER.OFFLINE</span> <span ng-if=\"!search.type\" translate=\"\">PEER.PEERS</span> <span ng-if=\"!search.loading\">({{search.results.length}})</span></div><div class=\"buttons pull-right\"><ion-spinner class=\"icon\" icon=\"android\" ng-if=\"search.loading\"></ion-spinner></div></div><ng-include src=\"\'templates/network/items_peers.html\'\"></ng-include>"); -$templateCache.put("templates/currency/items_parameters.html","<div bind-notifier=\"{ rebind:formData.useRelative }\"><ion-item class=\"item-icon-left item-text-wrap visible-xs visible-sm\"><i class=\"icon ion-android-bookmark\"></i> <span translate>CURRENCY.VIEW.CURRENCY_NAME</span><div class=\"item-note dark\" ng-if=\"!loading\">{{formData.currency}} (<span ng-bind-html=\":rebind:formData.currency | currencySymbol:formData.useRelative\"></span>)</div></ion-item><ion-item class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-record\"></i><div class=\"col col-60\"><span translate>CURRENCY.VIEW.MASS</span> <span class=\"gray\">(M<sub>t</sub>)</span></div><span class=\"badge badge-calm\" ng-if=\"!loading\" ng-bind-html=\":rebind:formData.M | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}\"></span></ion-item><ion-item id=\"helptip-currency-mass-member\" class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-pie-graph\"></i><div class=\"col col-60\"><span translate>CURRENCY.VIEW.SHARE</span> <span class=\"gray\">(M<sub>t</sub>/N<sub>t</sub>)</span></div><span id=\"helptip-currency-mass-member-unit\" ng-if=\"!loading\" class=\"badge badge-energized\" ng-bind-html=\":rebind:formData.MoverN | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}\"></span></ion-item><cs-extension-point name=\"parameters-actual\"></cs-extension-point><ion-item class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-arrow-graph-up-right\"></i><div class=\"col col-60\"><span translate>CURRENCY.VIEW.C_ACTUAL</span> <span class=\"gray\">(c<sub>{{\'CURRENCY.VIEW.CURRENT\'|translate}}</sub>)</span></div><span class=\"badge badge-stable\">{{formData.cactual | formatNumeral: \'0,0.00\'}} % / {{formData.dt | formatPeriod}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-load-c\"></i><div class=\"col col-60\"><span translate>CURRENCY.VIEW.UD</span> <span class=\"gray\">({{\'COMMON.UD\'|translate}}<sub>t</sub>)</span></div><div class=\"badge badge-royal\" ng-if=\"!loading\"><span ng-if=\"formData.useRelative\">1<ng-bind-html ng-bind-html=\":rebind:formData.currency| currencySymbol:true\"></ng-bind-html></span><span ng-if=\"!formData.useRelative\" ng-bind-html=\":rebind:formData.currentUD | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}\"></span> / {{formData.dt | formatPeriod}}</div></ion-item><div class=\"item item-toggle dark\"><div class=\"item-label text-right gray\" translate>COMMON.BTN_RELATIVE_UNIT</div><label class=\"toggle toggle-royal\" id=\"helptip-currency-change-unit\"><input type=\"checkbox\" ng-model=\"formData.useRelative\"><div class=\"track\"><div class=\"handle\"></div></div></label></div><a name=\"helptip-currency-rules-anchor\"></a><div class=\"item item-divider\" id=\"helptip-currency-rules\"><span translate>CURRENCY.VIEW.MONEY_RULES_DIVIDER</span></div><ion-item class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-arrow-graph-up-right\"></i><div class=\"col col-60\"><span translate>CURRENCY.VIEW.C_RULE</span> <span class=\"gray\">(c)</span></div><span class=\"item-note dark\" ng-if=\"!loading && !formData.udReevalTime0\">{{formData.c*100 | formatNumeral: \'0,0.00\'}} % / {{formData.dt | formatPeriod}}</span><span class=\"badge badge-stable\" ng-if=\"!loading && formData.udReevalTime0\">{{formData.c*100 | formatNumeral: \'0,0.00\'}} % / {{formData.dtReeval | formatDuration}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"formData.udReevalTime0 && formData.allRules\"><i class=\"icon ion-load-c\"></i> <b class=\"ion-clock icon-secondary\" style=\"font-size: 18px; left: 36px; top: -12px\"></b><div class=\"col col-60\"><span translate>CURRENCY.VIEW.DT_REEVAL</span> <span class=\"gray\">(dt<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub>)</span></div><span class=\"item-note dark\" ng-if=\"!loading\" translate=\"CURRENCY.VIEW.DT_REEVAL_VALUE\" translate-values=\"formData\"></span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"formData.udReevalTime0 && formData.allRules\"><i class=\"icon ion-load-c\"></i> <b class=\"ion-calendar icon-secondary\" style=\"font-size: 18px; left: 36px; top: -12px\"></b><div class=\"col col-60\"><span translate>CURRENCY.VIEW.UD_REEVAL_TIME0</span> <span class=\"gray\">(t0<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub>)</span></div><span class=\"item-note dark\" ng-if=\"!loading\">{{formData.udReevalTime0|formatDate}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"formData.allRules\"><i class=\"icon ion-load-c\"></i> <b class=\"ion-calculator icon-secondary\" style=\"font-size: 18px; left: 36px; top: -12px\"></b><div class=\"col col-60\"><span translate>CURRENCY.VIEW.UD_RULE</span> <span class=\"gray\" ng-if=\"formData.udReevalTime0\">- {{\'COMMON.UD\'|translate}}<sub>{{formData.dt|formatPeriod}}</sub>(t<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub>)</span></div><span class=\"item-note dark\" ng-if=\"!loading && !formData.udReevalTime0\">{{\'COMMON.UD\'|translate}}<sub>t-1</sub> + c<sup>2</sup> * M<sub>t-1</sub>/N<sub>t-1</sub></span><span class=\"item-note dark\" ng-if=\"!loading && formData.udReevalTime0\">{{\'COMMON.UD\'|translate}}<sub>{{formData.dt|formatPeriod}}</sub>(t<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub> - dt<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub>)+ c<sup>2</sup> * (M/N)(t<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub> - dt<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub>) / dt<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub></span></ion-item><div class=\"item item-toggle dark\"><div class=\"item-label text-right gray\" translate>CURRENCY.VIEW.DISPLAY_ALL_RULES</div><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.allRules\"><div class=\"track\"><div class=\"handle\"></div></div></label></div></div>"); -$templateCache.put("templates/currency/items_wot.html","<div bind-notifier=\"{ rebind:formData.useRelative }\"><a name=\"helptip-currency-newcomers-anchor\"></a><ion-item class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-person-stalker\"></i><div class=\"col col-60\"><span translate>CURRENCY.VIEW.MEMBERS</span> <span class=\"gray\">(N<sub>{{\'CURRENCY.VIEW.CURRENT\'|translate}}</sub>)</span></div><span class=\"badge badge-calm\" ng-if=\"!loading\">{{formData.N | formatInteger}}</span></ion-item><ion-item id=\"helptip-currency-newcomers\" class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-arrow-graph-up-right\"></i><div class=\"col col-75\"><span translate=\"CURRENCY.VIEW.MEMBERS_VARIATION\" translate-values=\"{duration: formData.durationFromLastUD}\"></span> <span class=\"gray\">(ΔN)</span></div><div class=\"badge\" ng-if=\"!loading\" ng-class=\"{\'badge-balanced\': (formData.N>formData.Nprev), \'badge-stable\': (formData.N==formData.Nprev) ,\'badge-assertive\': (formData.Nprev>formData.N)}\">{{formData.N > formData.Nprev ? \'+\' : \'\'}}{{formData.N - formData.Nprev}}</div></ion-item><cs-extension-point name=\"wot-actual\"></cs-extension-point><div class=\"item item-divider\"><span translate>CURRENCY.VIEW.WOT_RULES_DIVIDER</span></div><ion-item class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-ribbon-b\"></i> <span class=\"col col-75\" translate>CURRENCY.VIEW.SIG_QTY_RULE</span> <span class=\"badge badge-balanced\" ng-if=\"!loading\">{{formData.sigQty}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-person\"></i> <b class=\"ion-clock icon-secondary\" style=\"font-size: 18px; left: 33px; top: -12px\"></b> <span class=\"col col-60\" translate>CURRENCY.VIEW.MS_WINDOW</span> <span class=\"badge badge-assertive\" ng-if=\"!loading\">{{formData.msWindow | formatDuration}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\"><i class=\"icon ion-person\"></i> <b class=\"ion-calendar icon-secondary\" style=\"font-size: 18px; left: 33px; top: -12px\"></b> <span class=\"col col-60\" translate>CURRENCY.VIEW.MS_VALIDITY</span> <span class=\"badge badge-balanced\" ng-if=\"!loading\">{{formData.msValidity | formatDuration}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"formData.allWotRules\"><i class=\"icon ion-ribbon-b\"></i> <b class=\"ion-clock icon-secondary\" style=\"font-size: 18px; left: 33px; top: -12px\"></b> <span class=\"col col-60\" translate>CURRENCY.VIEW.SIG_WINDOW</span> <span class=\"badge badge-stable\" ng-if=\"!loading\">{{formData.sigWindow | formatDuration}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"formData.allWotRules\"><i class=\"icon ion-ribbon-b\"></i> <b class=\"ion-calendar icon-secondary\" style=\"font-size: 18px; left: 33px; top: -12px\"></b> <span class=\"col col-60\" translate>CURRENCY.VIEW.SIG_VALIDITY</span> <span class=\"badge badge-balanced\" ng-if=\"!loading\">{{formData.sigValidity | formatDuration}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"formData.allWotRules\"><i class=\"icon ion-ribbon-a\"></i> <span class=\"col col-75\" translate>CURRENCY.VIEW.SIG_STOCK</span> <span class=\"badge badge-stable\" ng-if=\"!loading\">{{formData.sigStock}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"formData.allWotRules\"><i class=\"icon ion-clock\" style=\"position: absolute; font-size: 20px; left: 16px\"></i> <b class=\"ion-ribbon-a icon-secondary\" style=\"left: 16px; top: -15px\"></b> <b class=\"ion-arrow-right-c icon-secondary\" style=\"left: 28px; top: -15px\"></b> <b class=\"ion-ribbon-a icon-secondary\" style=\"left: 40px; top: -15px\"></b> <span class=\"col col-75\" translate>CURRENCY.VIEW.SIG_PERIOD</span> <span class=\"badge badge-stable\" ng-if=\"!loading\">{{formData.sigPeriod | formatDuration}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"formData.allWotRules\"><i class=\"icon ion-steam\"></i> <b class=\"ion-person icon-secondary\" style=\"left: 38px; top: -17px\"></b><div class=\"col col-75\"><span ng-bind-html=\"\'CURRENCY.VIEW.STEP_MAX\'|translate\"></span> <span class=\"gray\">(stepMax)</span></div><span class=\"badge badge-assertive\" ng-if=\"!loading\">{{formData.stepMax}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"formData.allWotRules\"><i class=\"icon ion-ribbon-b\"></i> <b class=\"ion-star icon-secondary\" style=\"color: yellow; font-size: 16px; left: 25px; top: -7px\"></b> <span class=\"col col-75\" translate>CURRENCY.VIEW.SENTRIES</span> <span class=\"badge badge-stable\" ng-if=\"!loading\">{{formData.sentries}}</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"formData.allWotRules\"><i class=\"icon ion-ribbon-b\"></i> <b class=\"ion-star icon-secondary\" style=\"color: yellow; font-size: 16px; left: 25px; top: -7px\"></b> <span class=\"col col-75\" translate>CURRENCY.VIEW.SENTRIES_FORMULA</span> <span class=\"item-note dark\" ng-if=\"!loading\">{{\'CURRENCY.VIEW.MATH_CEILING\'| translate}}( N<sub>t</sub><sup>^ (1 / stepMax)</sup>)</span></ion-item><ion-item class=\"item-icon-left item-text-wrap\" ng-if=\"formData.allWotRules\"><i class=\"icon ion-pull-request\"></i> <span class=\"col col-75\" translate>CURRENCY.VIEW.XPERCENT</span> <span class=\"badge badge-stable\" ng-if=\"!loading\">{{formData.xpercent*100| formatNumeral: \'0,0\'}} %</span></ion-item><div class=\"item item-toggle dark\"><div class=\"item-label text-right gray\" translate>CURRENCY.VIEW.DISPLAY_ALL_RULES</div><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.allWotRules\"><div class=\"track\"><div class=\"handle\"></div></div></label></div></div>"); -$templateCache.put("templates/currency/lookup.html","<ion-view view-title=\"{{\'CURRENCY.SELECT.TITLE\' | translate}}\"><ion-content class=\"padding no-padding-xs\"><h4 class=\"content double-padding-x\" translate>CURRENCY.SELECT.CURRENCIES</h4><ng-include src=\"\'templates/currency/lookup_form.html\'\"></ion-content></ion-view>"); -$templateCache.put("templates/currency/lookup_form.html","<ion-list><div class=\"item center\" ng-if=\"search.loading\"><ion-spinner icon=\"android\"></ion-spinner></div><div ng-repeat=\"currency in search.results\" ng-class=\"{ selected: selectedCurrency == currency }\"><a class=\"item card card-item stable-bg padding ink\" ng-click=\"selectCurrency(currency)\" ng-class=\"{ selected: selectedCurrency && selectedCurrency.name == currency.name }\"><h2>{{currency.name}}</h2><h4 class=\"gray\">{{currency.peer.server}}</h4><span class=\"badge badge-royal\">{{\'CURRENCY.SELECT.MEMBERS_COUNT\'|translate:currency}}</span></a></div></ion-list>"); -$templateCache.put("templates/currency/modal_license.html","<ion-modal-view class=\"modal-full-height modal-license\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear visible-xs\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title\" translate>CURRENCY.LICENSE.TITLE</h1><button class=\"button button-icon button-clear icon ion-android-send visible-xs\" ng-click=\"doTransfer()\"></button></ion-header-bar><ion-content scroll=\"false\" style=\"bottom: 0px\"><p ng-if=\"!licenseUrl && !loading\">translate>CURRENCY.LICENSE.NO_LICENSE_FILE</p><iframe ng-if=\"licenseUrl && !loading\" class=\"padding-left padding-right no-padding-xs iframe-license\" id=\"iframe-license\" ng-src=\"{{licenseUrlHtml||licenseUrl}}\"></iframe><div class=\"padding hidden-xs text-center\"><button class=\"button button-stable ink\" ng-click=\"downloadFile()\">{{\'CURRENCY.LICENSE.BTN_DOWNLOAD\' | translate}}</button> <button class=\"button button-positive ink\" type=\"submit\" ng-click=\"closeModal()\">{{\'COMMON.BTN_CLOSE\' | translate}}</button></div></ion-content></ion-modal-view>"); -$templateCache.put("templates/currency/popover_actions.html","<ion-popover-view class=\"fit has-header popover-wallet-actions\"><ion-header-bar><h1 class=\"title\" translate=\"\">COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/currency/view_currency.html","<ion-view left-buttons=\"leftButtons\" cache-view=\"false\"><ion-tabs class=\"tabs-positive tabs-icon-top\"><ion-tab title=\"{{\'CURRENCY.VIEW.TAB_CURRENCY\'|translate}}\" icon=\"ion-stats-bars\" ui-sref=\"app.currency.tab_parameters\"><ion-nav-view name=\"tab-parameters\"></ion-nav-view></ion-tab><ion-tab title=\"{{\'CURRENCY.VIEW.TAB_WOT\'|translate}}\" icon=\"ion-person-stalker\" ui-sref=\"app.currency.tab_wot\"><ion-nav-view name=\"tab-wot\"></ion-nav-view></ion-tab><ion-tab id=\"helptip-currency-tab-peers\" title=\"{{\'CURRENCY.VIEW.TAB_NETWORK\'|translate}}\" icon=\"ion-cloud\" ui-sref=\"app.currency.tab_network\"><ion-nav-view name=\"tab-network\"></ion-nav-view></ion-tab><ion-tab title=\"{{\'CURRENCY.VIEW.TAB_BLOCKS\'|translate}}\" icon=\"ion-lock-combination\" ui-sref=\"app.currency.tab_blocks\"><ion-nav-view name=\"tab-blocks\"></ion-nav-view></ion-tab></ion-tabs></ion-view>"); -$templateCache.put("templates/currency/view_currency_lg.html","<ion-view left-buttons=\"leftButtons\" cache-view=\"false\"><ion-nav-title bind-notifier=\"{ rebind:formData.useRelative }\"><span ng-if=\"!loading\">{{\'CURRENCY.VIEW.TITLE\' | translate}} {{formData.currency|abbreviate}}</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-loop visible-xs visible-sm\" ng-click=\"refreshPeers()\"></button><cs-extension-point name=\"nav-buttons\"></cs-extension-point></ion-nav-buttons><ion-content><div class=\"item item-text-wrap no-border no-padding pull-left\"><div class=\"item-icon-left card padding stable-900-bg\"><ion-spinner class=\"icon\" icon=\"android\" ng-if=\"loading\"></ion-spinner><i class=\"icon ion-help-circled calm\" ng-if=\"!loading\"></i><div class=\"item-icon-left-padding\" style=\"min-height: 26px\"><span ng-if=\"!loading\" trust-as-html=\"\'CURRENCY.VIEW.CURRENCY_SHORT_DESCRIPTION\'|translate:formData\"></span></div></div></div><div class=\"row responsive-sm\"><div class=\"col list\"><div class=\"item item-divider\"><span translate=\"\">CURRENCY.VIEW.MONEY_DIVIDER</span></div><ng-include src=\"\'templates/currency/items_parameters.html\'\"></ng-include></div><div class=\"col list\"><div class=\"item item-divider\"><span translate=\"\">CURRENCY.VIEW.WOT_DIVIDER</span></div><ng-include src=\"\'templates/currency/items_wot.html\'\"></ng-include></div></div></ion-content></ion-view>"); -$templateCache.put("templates/help/help.html","<a name=\"join\"></a><h2 translate>HELP.JOIN.SECTION</h2><a name=\"join-salt\"></a><div class=\"row responsive-sm\" ng-class=\"itemsClass[\'join-salt\']\"><div class=\"col col-20\" translate>LOGIN.SALT</div><div class=\"col\" translate>HELP.JOIN.SALT</div></div><a name=\"join-password\"></a><div class=\"row responsive-sm\" ng-class=\"itemsClass[\'join-password\']\"><div class=\"col col-20\" translate>LOGIN.PASSWORD</div><div class=\"col\" translate>HELP.JOIN.PASSWORD</div></div><a name=\"join-pseudo\"></a><div class=\"row responsive-sm\" ng-class=\"itemsClass[\'join-pseudo\']\"><div class=\"col col-20\" translate>ACCOUNT.NEW.PSEUDO</div><div class=\"col\" translate>HELP.JOIN.PSEUDO</div></div><a name=\"login\"></a><h2 translate>HELP.LOGIN.SECTION</h2><a name=\"login-pubkey\"></a><div class=\"row responsive-sm\" ng-class=\"itemsClass[\'login-pubkey\']\"><div class=\"col col-20\" translate>HELP.LOGIN.PUBKEY</div><div class=\"col\" translate>HELP.LOGIN.PUBKEY_DEF</div></div><a name=\"login-method\"></a><div class=\"row responsive-sm\" ng-class=\"itemsClass[\'login-method\']\"><div class=\"col col-20\" translate>HELP.LOGIN.METHOD</div><div class=\"col\" translate>HELP.LOGIN.METHOD_DEF</div></div><a name=\"glossary\"></a><h2 translate>HELP.GLOSSARY.SECTION</h2><a name=\"pubkey\"></a><div class=\"row responsive-sm\" ng-class=\"itemsClass.pubkey\"><div class=\"col col-20\" translate>COMMON.PUBKEY</div><div class=\"col\" translate>HELP.GLOSSARY.PUBKEY_DEF</div></div><a name=\"blockchain\"></a><div class=\"row responsive-sm\" ng-class=\"itemsClass.blockchain\"><div class=\"col col-20\" translate>HELP.GLOSSARY.BLOCKCHAIN</div><div class=\"col\" translate>HELP.GLOSSARY.BLOCKCHAIN_DEF</div></div><a name=\"universal_dividend\"></a> <a name=\"ud\"></a><div class=\"row responsive-sm\" ng-class=\"itemsClass.ud\"><div class=\"col col-20\" translate>COMMON.UNIVERSAL_DIVIDEND</div><div class=\"col\" translate>HELP.GLOSSARY.UNIVERSAL_DIVIDEND_DEF</div></div><a name=\"member\"></a><div class=\"row responsive-sm\" ng-class=\"itemsClass.member\"><div class=\"col col-20\" translate>HELP.GLOSSARY.MEMBER</div><div class=\"col\" translate>HELP.GLOSSARY.MEMBER_DEF</div></div><a name=\"currency_rules\"></a><div class=\"row responsive-sm\" ng-class=\"itemsClass.currency_rules\"><div class=\"col col-20\" translate>HELP.GLOSSARY.CURRENCY_RULES</div><div class=\"col\" translate>HELP.GLOSSARY.CURRENCY_RULES_DEF</div></div>"); -$templateCache.put("templates/help/modal_help.html","<ion-modal-view class=\"modal-full-height modal-help\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear\" ng-click=\"closeModal()\" translate>COMMON.BTN_CLOSE</button><h1 class=\"title\" translate>HELP.TITLE</h1></ion-header-bar><ion-content scroll=\"true\" class=\"padding no-padding-xs\"><div ng-class=\"listClass\"><ng-include src=\"\'templates/help/help.html\'\"></ng-include></div><div class=\"padding hidden-xs text-center\"><button class=\"button button-positive ink\" type=\"submit\" ng-click=\"closeModal()\">{{\'COMMON.BTN_CLOSE\' | translate}}</button></div></ion-content></ion-modal-view>"); -$templateCache.put("templates/help/view_help.html","<ion-view left-buttons=\"leftButtons\"><ion-nav-title><span class=\"visible-xs visible-sm\" translate=\"\">HELP.TITLE</span></ion-nav-title><ion-content scroll=\"true\" class=\"padding\"><ng-include src=\"\'templates/help/help.html\'\"></ng-include></ion-content></ion-view>"); -$templateCache.put("templates/home/home.html","<ion-view id=\"home\" class=\"\"><ion-nav-title></ion-nav-title><ion-content class=\"has-header text-center padding-xs positive-900-bg circle-bg-dark\"><div id=\"helptip-home-logo\" class=\"logo\"></div><h4><span class=\"hidden-xs\" translate=\"\">HOME.WELCOME</span> <span ng-show=\"!loading\" translate-values=\":currency:{currency: $root.currency.name}\" translate=\"\">HOME.MESSAGE</span></h4><div class=\"center padding\"><ion-spinner icon=\"android\" ng-if=\"loading\"></ion-spinner><div class=\"animate-fade-in animate-show-hide ng-hide\" ng-show=\"!loading && error\"><div class=\"card card-item padding\"><p class=\"item-content item-text-wrap\"><span class=\"dark\" trust-as-html=\"\'HOME.CONNECTION_ERROR\'|translate:node\"></span></p><button type=\"button\" class=\"button button-positive icon icon-left ion-refresh ink\" ng-click=\"reload()\">{{\'COMMON.BTN_REFRESH\'|translate}}</button></div></div></div><div class=\"center animate-fade-in animate-show-hide ng-hide\" ng-show=\"!loading && !error\"><button type=\"button\" class=\"button button-block button-stable button-raised icon-left icon ion-easel ink-dark hidden-xs\" ng-click=\"startHelpTour()\">{{\'COMMON.BTN_HELP_TOUR\'|translate}}</button> <button type=\"button\" class=\"item button button-block button-positive button-raised icon icon-left ion-locked ink-dark\" ui-sref=\"app.view_wallet\" ng-show=\"!login\" translate=\"\">COMMON.BTN_LOGIN</button> <button type=\"button\" class=\"item button button-block button-positive button-raised icon icon-left ion-person ink-dark\" ui-sref=\"app.view_wallet\" ng-show=\"login\" translate=\"\">MENU.ACCOUNT</button> <button type=\"button\" class=\"item button button-block button-positive button-raised icon icon-left ion-card ink-dark visible-xs\" ui-sref=\"app.view_wallet_tx\" ng-show=\"login\" translate=\"\">MENU.TRANSACTIONS</button><br class=\"visible-xs visible-sm\"><div class=\"text-center no-padding\" ng-show=\"!login\"><br class=\"visible-xs visible-sm\">{{\'LOGIN.NO_ACCOUNT_QUESTION\'|translate}} <b></b></div><div class=\"text-center no-padding\" ng-show=\"login\"><br class=\"visible-xs visible-sm\"><span ng-bind-html=\"\'HOME.NOT_YOUR_ACCOUNT_QUESTION\'|translate:$root.walletData\"></span><br><b></b></div><button type=\"button\" class=\"button button-block button-calm button-raised icon icon-left ion-wand ink-dark visible-xs visible-sm\" ng-click=\"showJoinModal()\" ng-if=\"!login\" translate=\"\">LOGIN.CREATE_ACCOUNT</button> <button type=\"button\" class=\"button button-block button-assertive button-raised icon icon-left ion-wand ink-dark visible-xs visible-sm\" ng-click=\"logout()\" ng-if=\"login\" translate=\"\">COMMON.BTN_LOGOUT</button><div class=\"text-center no-padding visible-xs stable\"><br>{{\'COMMON.APP_VERSION\'|translate:{version: config.version} }} | <a href=\"#\" ng-click=\"showAboutModal()\" translate=\"\">HOME.BTN_ABOUT</a></div></div></ion-content></ion-view>"); -$templateCache.put("templates/join/modal_choose_account_type.html","<ion-modal-view class=\"modal-full-height\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear visible-xs\" ng-if=\"!slides.slider.activeIndex\" ng-click=\"closeModal()\" translate=\"\">COMMON.BTN_CANCEL</button> <button class=\"button button-icon button-clear icon ion-ios-arrow-back buttons header-item\" ng-click=\"slidePrev()\" ng-if=\"slides.slider.activeIndex\"></button><h1 class=\"title\" translate=\"\">ACCOUNT.NEW.TITLE</h1><button class=\"button button-clear icon-right visible-xs\" ng-if=\"slides.slider.activeIndex === 0\" ng-click=\"slideNext()\"><span translate=\"\">COMMON.BTN_NEXT</span> <i class=\"icon ion-ios-arrow-right\"></i></button></ion-header-bar><ion-slides options=\"slides.options\" slider=\"slides.slider\"><ion-slide-page><ion-content class=\"has-header padding\"><div class=\"center padding\" ng-if=\"loading\"><ion-spinner class=\"icon\" icon=\"android\"></ion-spinner></div><div ng-if=\"!loading\"><p ng-bind-html=\"\'ACCOUNT.NEW.INTRO_WARNING_TIME\'|translate:currency\"></p><div class=\"row responsive-sm\"><div class=\"col\"><div class=\"item card item-icon-left padding item-text-wrap stable-bg\"><i class=\"icon ion-android-warning assertive\"></i><p class=\"item-content item-icon-left-padding\"><span class=\"dark\" translate=\"\">ACCOUNT.NEW.INTRO_WARNING_SECURITY</span><br><small translate=\"\">ACCOUNT.NEW.INTRO_WARNING_SECURITY_HELP</small></p></div></div><div class=\"col\"><div class=\"item card item-icon-left padding item-text-wrap stable-bg\"><i class=\"icon ion-information-circled positive\"></i><p class=\"item-content item-icon-left-padding\"><span class=\"dark\" trust-as-html=\"\'ACCOUNT.NEW.REGISTRATION_NODE\'|translate:currency.node\"></span><br><small trust-as-html=\"\'ACCOUNT.NEW.REGISTRATION_NODE_HELP\'|translate:currency.node\"></small></p></div></div></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate=\"\">COMMON.BTN_CANCEL</button> <button class=\"button button-positive icon-right ion-chevron-right ink\" ng-click=\"slideNext()\" ng-disabled=\"loading\" type=\"button\" translate=\"\">COMMON.BTN_START</button></div></ion-content></ion-slide-page><ion-slide-page><ion-content class=\"has-header padding\"><p translate=\"\">ACCOUNT.NEW.SELECT_ACCOUNT_TYPE</p><div class=\"list\"><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"selectAccountTypeAndClose(\'member\')\"><div class=\"item-content item-text-wrap\"><i class=\"item-image icon dark ion-person\"></i><h2 translate=\"\">ACCOUNT.NEW.MEMBER_ACCOUNT</h2><h4 class=\"gray\" ng-bind-html=\"\'ACCOUNT.NEW.MEMBER_ACCOUNT_HELP\'|translate:currency\"></h4><i class=\"icon dark ion-ios-arrow-right\"></i></div></div><cs-extension-point name=\"select-account-type\"></cs-extension-point><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"selectAccountTypeAndClose(\'wallet\')\"><div class=\"item-content item-text-wrap\"><i class=\"item-image icon dark ion-card\"></i><h2 translate=\"\">ACCOUNT.NEW.WALLET_ACCOUNT</h2><h4 class=\"gray\" translate=\"\">ACCOUNT.NEW.WALLET_ACCOUNT_HELP</h4><i class=\"icon dark ion-ios-arrow-right\"></i></div></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate=\"\">COMMON.BTN_CANCEL</button></div></ion-content></ion-slide-page></ion-slides></ion-modal-view>"); -$templateCache.put("templates/join/modal_join_member.html","<ion-modal-view class=\"modal-full-height\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear visible-xs\" ng-if=\"!slides.slider.activeIndex\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-icon button-clear icon ion-ios-arrow-back buttons header-item\" ng-click=\"slidePrev()\" ng-if=\"slides.slider.activeIndex && slideBehavior.hasPreviousButton\"></button> <button class=\"button button-icon button-clear icon ion-ios-help-outline visible-xs\" ng-if=\"slideBehavior.helpAnchor\" ng-click=\"showHelpModal(slideBehavior.helpAnchor)\"></button><h1 class=\"title\" translate>ACCOUNT.NEW.MEMBER_ACCOUNT_TITLE</h1><button class=\"button button-clear icon-right visible-xs\" ng-if=\"slideBehavior.hasNextButton\" ng-click=\"doNext()\"><span translate>COMMON.BTN_NEXT</span> <i class=\"icon ion-ios-arrow-right\"></i></button> <button class=\"button button-clear icon-right visible-xs\" ng-class=\"{\'button-text-stable\': !isLicenseRead}\" ng-if=\"slideBehavior.hasAcceptButton\" ng-click=\"isLicenseRead ? doNext() : undefined\"><span translate>ACCOUNT.NEW.BTN_ACCEPT</span> <i class=\"icon ion-ios-arrow-right\"></i></button> <button class=\"button button-clear icon-right visible-xs\" ng-if=\"slideBehavior.hasSendButton\" ng-click=\"doNewAccount()\"><i class=\"icon ion-android-send\"></i></button></ion-header-bar><ion-slides options=\"slides.options\" slider=\"slides.slider\" ng-init=\"console.log(\'START SLIDE\');\"><ion-slide-page ng-if=\"licenseFileUrl\"><ion-content class=\"has-header\" scroll=\"false\"><div class=\"padding\" translate>ACCOUNT.NEW.INFO_LICENSE</div><div class=\"center padding\" ng-if=\"loading\"><ion-spinner class=\"icon\" icon=\"android\"></ion-spinner></div><iframe ng-if=\"!loading\" class=\"padding-left padding-right no-padding-xs iframe-license\" id=\"iframe-license\" ng-src=\"{{licenseFileUrl}}\"></iframe><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-calm icon-right ion-chevron-right ink\" ng-click=\"doNext(\'licenceForm\')\" ng-disabled=\"!isLicenseRead\" type=\"button\" translate>ACCOUNT.NEW.BTN_ACCEPT_LICENSE</button></div></ion-content></ion-slide-page><ion-slide-page><ion-content class=\"has-header\" scroll=\"false\"><form name=\"pseudoForm\" novalidate=\"\" ng-submit=\"doNext(\'pseudoForm\')\"><div class=\"item item-text-wrap text-center padding\"><a class=\"pull-right icon-help hidden-xs\" ng-click=\"showHelpModal(\'join-pseudo\')\"></a> <span translate>ACCOUNT.NEW.PSEUDO_WARNING</span></div><div class=\"list\" ng-init=\"setForm(pseudoForm, \'pseudoForm\')\"><div class=\"item item-input\" ng-class=\"{\'item-input-error\': (pseudoForm.$submitted && pseudoForm.pseudo.$invalid) || (uiAlreadyUsed && formData.pseudo)}\"><span class=\"input-label\" translate>ACCOUNT.NEW.PSEUDO</span> <input id=\"pseudo\" name=\"pseudo\" type=\"text\" placeholder=\"{{\'ACCOUNT.NEW.PSEUDO_HELP\' | translate}}\" ng-model=\"formData.pseudo\" autocomplete=\"off\" ng-minlength=\"3\" ng-maxlength=\"100\" ng-pattern=\"userIdPattern\" ng-model-options=\"{ debounce: 250 }\" required></div><div class=\"form-errors\" ng-show=\"pseudoForm.$submitted && pseudoForm.pseudo.$error\" ng-messages=\"pseudoForm.pseudo.$error\"><div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT_WITH_LENGTH\" translate-values=\"{minLength: 3}\"></span></div><div class=\"form-error\" ng-message=\"maxlength\"><span translate=\"ERROR.FIELD_TOO_LONG_WITH_LENGTH\" translate-values=\"{maxLength: 100}\"></span></div><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div><div class=\"form-error\" ng-message=\"pattern\"><span translate=\"ERROR.INVALID_USER_ID\"></span></div></div><div class=\"text-right\" style=\"min-height: 18px\"><div class=\"form-error gray\" ng-if=\"formData.computing && formData.pseudo\"><ion-spinner class=\"icon ion-spinner-small\" icon=\"android\" ng-if=\"formData.computing && formData.pseudo\"></ion-spinner><span translate>ACCOUNT.NEW.CHECKING_PSEUDO</span></div><ng-if ng-if=\"!formData.computing && formData.pseudo\"><div class=\"form-error balanced\" ng-if=\"!uiAlreadyUsed \"><i class=\"icon ion-checkmark balanced\"></i> <span translate>ACCOUNT.NEW.PSEUDO_AVAILABLE</span></div><div class=\"form-error\" ng-if=\"uiAlreadyUsed\"><i class=\"icon ion-close-circled assertive\"></i> <span translate>ACCOUNT.NEW.PSEUDO_NOT_AVAILABLE</span></div></ng-if></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-calm icon-right ion-chevron-right ink\" type=\"submit\" ng-disabled=\"UIDFound\" translate>COMMON.BTN_NEXT</button></div></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class=\"has-header\" scroll=\"false\"><form name=\"saltForm\" novalidate=\"\" ng-submit=\"doNext(\'saltForm\')\"><div class=\"list\" ng-init=\"setForm(saltForm, \'saltForm\')\"><div class=\"item item-text-wrap text-center padding hidden-xs\"><a class=\"pull-right icon-help\" ng-click=\"showHelpModal(\'join-salt\')\"></a> <span translate>ACCOUNT.NEW.SALT_WARNING</span></div><div class=\"item item-input\" ng-class=\"{ \'item-input-error\': saltForm.$submitted && saltForm.username.$invalid}\"><span class=\"input-label\" translate>LOGIN.SALT</span> <input ng-if=\"!showUsername\" name=\"username\" type=\"password\" placeholder=\"{{\'LOGIN.SALT_HELP\' | translate}}\" ng-change=\"formDataChanged()\" ng-model=\"formData.username\" autocomplete=\"off\" ng-minlength=\"8\" different-to=\"formData.pseudo\" required> <input ng-if=\"showUsername\" name=\"username\" type=\"text\" placeholder=\"{{\'LOGIN.SALT_HELP\' | translate}}\" ng-change=\"formDataChanged()\" ng-model=\"formData.username\" autocomplete=\"off\" ng-minlength=\"8\" different-to=\"formData.pseudo\" required></div><div class=\"form-errors\" ng-show=\"saltForm.$submitted && saltForm.username.$error\" ng-messages=\"saltForm.username.$error\"><div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT_WITH_LENGTH\" translate-values=\"{minLength: 8}\"></span></div><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div><div class=\"form-error\" ng-message=\"differentTo\"><span translate=\"ERROR.EQUALS_TO_PSEUDO\"></span></div></div><div class=\"item item-input\" ng-class=\"{ \'item-input-error\': saltForm.$submitted && saltForm.confirmSalt.$invalid}\"><span class=\"input-label pull-right\" translate>ACCOUNT.NEW.SALT_CONFIRM</span> <input ng-if=\"!showUsername\" name=\"confirmUsername\" type=\"password\" placeholder=\"{{\'ACCOUNT.NEW.SALT_CONFIRM_HELP\' | translate}}\" ng-model=\"formData.confirmUsername\" autocomplete=\"off\" compare-to=\"formData.username\"> <input ng-if=\"showUsername\" name=\"confirmUsername\" type=\"text\" placeholder=\"{{\'ACCOUNT.NEW.SALT_CONFIRM_HELP\' | translate}}\" ng-model=\"formData.confirmUsername\" autocomplete=\"off\" compare-to=\"formData.username\"></div><div class=\"form-errors\" ng-show=\"saltForm.$submitted && saltForm.confirmUsername.$error\" ng-messages=\"saltForm.confirmUsername.$error\"><div class=\"form-error\" ng-message=\"compareTo\"><span translate=\"ERROR.SALT_NOT_CONFIRMED\"></span></div></div><div class=\"item item-toggle dark\"><span translate>COMMON.SHOW_VALUES</span><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"showUsername\"><div class=\"track\"><div class=\"handle\"></div></div></label></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-calm icon-right ion-chevron-right ink\" type=\"submit\" translate>COMMON.BTN_NEXT <i class=\"icon ion-arrow-right-a\"></i></button></div></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class=\"has-header\" scroll=\"false\"><form name=\"passwordForm\" novalidate=\"\" ng-submit=\"doNext(\'passwordForm\')\"><div class=\"item item-text-wrap text-center padding hidden-xs\"><a class=\"pull-right icon-help\" ng-click=\"showHelpModal(\'join-password\')\"></a> <span translate>ACCOUNT.NEW.PASSWORD_WARNING</span></div><div class=\"list\" ng-init=\"setForm(passwordForm, \'passwordForm\')\"><div class=\"item item-input\" ng-class=\"{ \'item-input-error\': passwordForm.$submitted && passwordForm.password.$invalid}\"><span class=\"input-label\" translate>LOGIN.PASSWORD</span> <input ng-if=\"!showPassword\" name=\"password\" type=\"password\" placeholder=\"{{\'LOGIN.PASSWORD_HELP\' | translate}}\" ng-model=\"formData.password\" autocomplete=\"off\" ng-change=\"formDataChanged()\" ng-minlength=\"8\" different-to=\"formData.username\" required> <input ng-if=\"showPassword\" name=\"text\" type=\"text\" placeholder=\"{{\'LOGIN.PASSWORD_HELP\' | translate}}\" ng-model=\"formData.password\" autocomplete=\"off\" ng-change=\"formDataChanged()\" ng-minlength=\"8\" different-to=\"formData.username\" required></div><div class=\"form-errors\" ng-show=\"passwordForm.$submitted && passwordForm.password.$error\" ng-messages=\"passwordForm.password.$error\"><div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT_WITH_LENGTH\" translate-values=\"{minLength: 8}\"></span></div><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div><div class=\"form-error\" ng-message=\"differentTo\"><span translate=\"ERROR.EQUALS_TO_SALT\"></span></div></div><div class=\"item item-input\" ng-class=\"{ \'item-input-error\': passwordForm.$submitted && passwordForm.confirmPassword.$invalid}\"><span class=\"input-label\" translate>ACCOUNT.NEW.PASSWORD_CONFIRM</span> <input ng-if=\"!showPassword\" name=\"confirmPassword\" type=\"password\" placeholder=\"{{\'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP\' | translate}}\" ng-model=\"formData.confirmPassword\" autocomplete=\"off\" compare-to=\"formData.password\"> <input ng-if=\"showPassword\" name=\"confirmPassword\" type=\"text\" placeholder=\"{{\'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP\' | translate}}\" ng-model=\"formData.confirmPassword\" autocomplete=\"off\" compare-to=\"formData.password\"></div><div class=\"form-errors\" ng-show=\"passwordForm.$submitted && passwordForm.confirmPassword.$error\" ng-messages=\"passwordForm.confirmPassword.$error\"><div class=\"form-error\" ng-message=\"compareTo\"><span translate=\"ERROR.PASSWORD_NOT_CONFIRMED\"></span></div></div><div class=\"item item-toggle dark\"><span translate>COMMON.SHOW_VALUES</span><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"showPassword\"><div class=\"track\"><div class=\"handle\"></div></div></label></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-calm icon-right ion-chevron-right ink\" type=\"submit\" ng-click=\"getRevocationDocument()\" translate>COMMON.BTN_NEXT</button></div><div class=\"padding hidden-xs\"></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class=\"has-header\" scroll=\"false\"><div class=\"center padding\" ng-if=\"formData.computing\"><ion-spinner icon=\"android\"></ion-spinner></div><div ng-if=\"accountAvailable && !formData.computing\"><div class=\"padding text-center\" translate>ACCOUNT.NEW.LAST_SLIDE_CONGRATULATION</div><div class=\"list\"><ion-item class=\"item text-center item-text-wrap\"><h3 class=\"gray\" translate>LOGIN.ASSOCIATED_PUBKEY</h3><h3 class=\"dark bold\">{{formData.pubkey}}</h3></ion-item></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-positive ink\" ng-click=\"doNewAccount()\" translate>COMMON.BTN_SEND <i class=\"icon ion-android-send\"></i></button></div></div><div ng-if=\"!accountAvailable && !formData.computing\"><ion-item class=\"item-icon-left item-text-wrap text-center\"><i class=\"icon ion-minus-circled assertive\"></i> <span id=\"modal-license\" trust-as-html=\"\'ERROR.EXISTING_ACCOUNT\'|translate\"></span></ion-item><div class=\"list\"><ion-item class=\"item item-text-wrap item-border\"><div class=\"padding text-center\"><span class=\"gray text-no-wrap\">{{formData.pubkey}}</span></div></ion-item><div class=\"padding text-center\"><span translate>ERROR.EXISTING_ACCOUNT_REQUEST</span></div></div><div class=\"padding hidden-xs text-left\"><button class=\"button button-assertive icon-left ion-chevron-left ink\" ng-click=\"identifierRecovery()\" translate>COMMON.BTN_MODIFY</button></div></div></ion-content></ion-slide-page></ion-slides></ion-modal-view>"); -$templateCache.put("templates/join/modal_join_wallet.html","<ion-modal-view class=\"modal-full-height\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear visible-xs\" ng-if=\"!slides.slider.activeIndex\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-icon button-clear icon ion-ios-arrow-back buttons header-item\" ng-click=\"slidePrev()\" ng-if=\"slideBehavior.hasPreviousButton\"></button> <button class=\"button button-icon button-clear icon ion-ios-help-outline visible-xs\" ng-if=\"slideBehavior.helpAnchor\" ng-click=\"showHelpModal(slideBehavior.helpAnchor)\"></button><h1 class=\"title\" translate>ACCOUNT.NEW.WALLET_ACCOUNT_TITLE</h1><button class=\"button button-clear icon-right visible-xs\" ng-if=\"slideBehavior.hasNextButton\" ng-click=\"doNext()\"><span translate>COMMON.BTN_NEXT</span> <i class=\"icon ion-ios-arrow-right\"></i></button> <button class=\"button button-clear icon-right visible-xs\" ng-if=\"slideBehavior.hasSendButton\" ng-click=\"doNewAccount()\"><i class=\"icon ion-android-send\"></i></button></ion-header-bar><ion-slides options=\"slides.options\" slider=\"slides.slider\"><ion-slide-page><ion-content class=\"has-header\" scroll=\"false\"><form name=\"saltForm\" novalidate=\"\" ng-submit=\"doNext(\'saltForm\')\"><div class=\"list\" ng-init=\"setForm(saltForm, \'saltForm\')\"><div class=\"item item-text-wrap text-center padding hidden-xs\"><a class=\"pull-right icon-help\" ng-click=\"showHelpModal(\'join-salt\')\"></a> <span translate>ACCOUNT.NEW.SALT_WARNING</span></div><div class=\"item item-input\" ng-class=\"{ \'item-input-error\': saltForm.$submitted && saltForm.username.$invalid}\"><span class=\"input-label\" translate>LOGIN.SALT</span> <input ng-if=\"!showUsername\" name=\"username\" type=\"password\" placeholder=\"{{\'LOGIN.SALT_HELP\' | translate}}\" ng-change=\"formDataChanged()\" ng-model=\"formData.username\" ng-minlength=\"8\" required> <input ng-if=\"showUsername\" name=\"username\" type=\"text\" placeholder=\"{{\'LOGIN.SALT_HELP\' | translate}}\" ng-change=\"formDataChanged()\" ng-model=\"formData.username\" ng-minlength=\"8\" required></div><div class=\"form-errors\" ng-show=\"saltForm.$submitted && saltForm.username.$error\" ng-messages=\"saltForm.username.$error\"><div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT_WITH_LENGTH\" translate-values=\"{minLength: 8}\"></span></div><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div><div class=\"item item-input\" ng-class=\"{ \'item-input-error\': saltForm.$submitted && saltForm.confirmSalt.$invalid}\"><span class=\"input-label pull-right\" translate>ACCOUNT.NEW.SALT_CONFIRM</span> <input ng-if=\"!showUsername\" name=\"confirmUsername\" type=\"password\" placeholder=\"{{\'ACCOUNT.NEW.SALT_CONFIRM_HELP\' | translate}}\" ng-model=\"formData.confirmUsername\" compare-to=\"formData.username\"> <input ng-if=\"showUsername\" name=\"confirmUsername\" type=\"text\" placeholder=\"{{\'ACCOUNT.NEW.SALT_CONFIRM_HELP\' | translate}}\" ng-model=\"formData.confirmUsername\" compare-to=\"formData.username\"></div><div class=\"form-errors\" ng-show=\"saltForm.$submitted && saltForm.confirmUsername.$error\" ng-messages=\"saltForm.confirmUsername.$error\"><div class=\"form-error\" ng-message=\"compareTo\"><span translate=\"ERROR.SALT_NOT_CONFIRMED\"></span></div></div><div class=\"item item-toggle dark\"><span translate>COMMON.SHOW_VALUES</span><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"showUsername\"><div class=\"track\"><div class=\"handle\"></div></div></label></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-calm icon-right ion-chevron-right ink\" type=\"submit\" translate>COMMON.BTN_NEXT <i class=\"icon ion-arrow-right-a\"></i></button></div></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class=\"has-header\" scroll=\"false\"><form name=\"passwordForm\" novalidate=\"\" ng-submit=\"doNext(\'passwordForm\')\"><div class=\"item item-text-wrap text-center padding hidden-xs\"><a class=\"pull-right icon-help\" ng-click=\"showHelpModal(\'join-password\')\"></a> <span translate>ACCOUNT.NEW.PASSWORD_WARNING</span></div><div class=\"list\" ng-init=\"setForm(passwordForm, \'passwordForm\')\"><div class=\"item item-input\" ng-class=\"{ \'item-input-error\': passwordForm.$submitted && passwordForm.password.$invalid}\"><span class=\"input-label\" translate>LOGIN.PASSWORD</span> <input ng-if=\"!showPassword\" name=\"password\" type=\"password\" placeholder=\"{{\'LOGIN.PASSWORD_HELP\' | translate}}\" ng-model=\"formData.password\" ng-change=\"formDataChanged()\" ng-minlength=\"8\" required> <input ng-if=\"showPassword\" name=\"text\" type=\"text\" placeholder=\"{{\'LOGIN.PASSWORD_HELP\' | translate}}\" ng-model=\"formData.password\" ng-change=\"formDataChanged()\" ng-minlength=\"8\" required></div><div class=\"form-errors\" ng-show=\"passwordForm.$submitted && passwordForm.password.$error\" ng-messages=\"passwordForm.password.$error\"><div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT_WITH_LENGTH\" translate-values=\"{minLength: 8}\"></span></div><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div><div class=\"item item-input\" ng-class=\"{ \'item-input-error\': passwordForm.$submitted && passwordForm.confirmPassword.$invalid}\"><span class=\"input-label\" translate>ACCOUNT.NEW.PASSWORD_CONFIRM</span> <input ng-if=\"!showPassword\" name=\"confirmPassword\" type=\"password\" placeholder=\"{{\'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP\' | translate}}\" ng-model=\"formData.confirmPassword\" compare-to=\"formData.password\"> <input ng-if=\"showPassword\" name=\"confirmPassword\" type=\"text\" placeholder=\"{{\'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP\' | translate}}\" ng-model=\"formData.confirmPassword\" compare-to=\"formData.password\"></div><div class=\"form-errors\" ng-show=\"passwordForm.$submitted && passwordForm.confirmPassword.$error\" ng-messages=\"passwordForm.confirmPassword.$error\"><div class=\"form-error\" ng-message=\"compareTo\"><span translate=\"ERROR.PASSWORD_NOT_CONFIRMED\"></span></div></div><div class=\"item item-toggle dark\"><span translate>COMMON.SHOW_VALUES</span><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"showPassword\"><div class=\"track\"><div class=\"handle\"></div></div></label></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-calm icon-right ion-chevron-right ink\" type=\"submit\" translate>COMMON.BTN_NEXT</button></div><div class=\"padding hidden-xs\"></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class=\"has-header\" scroll=\"false\"><div class=\"padding center\" ng-if=\"formData.computing\"><ion-spinner icon=\"android\"></ion-spinner></div><div ng-if=\"accountAvailable && !formData.computing\"><div class=\"padding text-center\" translate>ACCOUNT.NEW.LAST_SLIDE_CONGRATULATION</div><div class=\"list\"><ion-item class=\"item item-text-wrap item-border\"><div class=\"dark pull-right padding-right\" ng-if=\"formData.computing\"><ion-spinner icon=\"android\"></ion-spinner></div><span class=\"input-label\" translate>COMMON.PUBKEY</span> <span class=\"gray text-no-wrap\" ng-if=\"formData.computing\" translate>ACCOUNT.NEW.COMPUTING_PUBKEY </span><span class=\"gray text-no-wrap\" ng-if=\"formData.pubkey\">{{formData.pubkey}}</span></ion-item></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-positive ink\" ng-click=\"doNewAccount()\" translate>COMMON.BTN_CREATE</button></div></div><div ng-if=\"!accountAvailable && !formData.computing\"><ion-item class=\"item-icon-left item-text-wrap text-center\"><i class=\"icon ion-android-close active\"></i> <span id=\"modal-license\" translate>ERROR.EXISTING_ACCOUNT</span></ion-item><div class=\"list\"><ion-item class=\"item item-text-wrap item-border\"><div class=\"dark pull-right padding-right\" ng-if=\"formData.computing\"><ion-spinner icon=\"android\"></ion-spinner></div><span class=\"gray text-no-wrap\" ng-if=\"formData.computing\" translate>ACCOUNT.NEW.COMPUTING_PUBKEY</span><div class=\"padding text-center\"><span class=\"gray text-no-wrap\" ng-if=\"formData.pubkey\">{{formData.pubkey}}</span></div></ion-item><div class=\"padding text-center\"><span translate>ERROR.EXISTING_ACCOUNT_REQUEST</span></div></div><div class=\"padding hidden-xs text-left\"><button class=\"button button-assertive icon-left ion-chevron-left ink\" ng-click=\"identifierRecovery()\" translate>COMMON.BTN_MODIFY</button></div></div></ion-content></ion-slide-page></ion-slides></ion-modal-view>"); -$templateCache.put("templates/login/form_file_import.html","<div class=\"item\"><p class=\"item-text-wrap\" translate>LOGIN.FILE_FORM_HELP</p></div><div class=\"item item-icon-left item-text-wrap\"><i class=\"icon ion-ios-information-outline positive\"></i> <span class=\"positive\" translate>LOGIN.FILE.HELP</span></div><div class=\"dropzone\" dropzone=\"onKeyFileDrop(file)\"><div ng-if=\"!formData.file\" onclick=\"angular.element(document.querySelector(\'#loginImportFile\'))[0].click();\"><h2 class=\"gray\" translate>COMMON.CHOOSE_FILE</h2><input type=\"file\" id=\"loginImportFile\" accept=\".dunikey,.yml\" style=\"visibility:hidden; position:absolute\" onchange=\"angular.element(this).scope().fileChanged(event)\"></div><div class=\"item item-icon-left item-icon-right stable-bg\" ng-if=\"formData.file\"><i class=\"icon ion-document-text dark\"></i><div class=\"item-content row\"><div class=\"col\"><h2>{{formData.file.name}}</h2><h4 class=\"dark\" ng-if=\"formData.file.lastModified\"><span class=\"gray\" translate>LOGIN.FILE.DATE</span> {{formData.file.lastModified/1000|formatDate}}</h4><h5 class=\"dark\"><span class=\"gray\" translate>LOGIN.FILE.SIZE</span> {{formData.file.size|formatInteger}} Ko</h5></div><div class=\"col\"><h3><span class=\"gray\" translate>COMMON.PUBKEY</span></h3><h3 ng-if=\"validatingFile\" translate>LOGIN.FILE.VALIDATING</h3><h3 ng-if=\"!validatingFile\"><span class=\"dark animate-show-hide ng-hide\" ng-show=\"formData.file.pubkey\">{{formData.file.pubkey}}</span> <span class=\"assertive animate-show-hide ng-hide\" ng-show=\"!formData.file.valid\"><br><i class=\"ion-close-circled assertive\"></i> {{formData.file.pubkey ? \'ERROR.AUTH_INVALID_PUBKEY\' : \'ERROR.AUTH_INVALID_FILE\' |translate}}</span></h3></div></div><a class=\"ion-close-round gray pull-right\" style=\"font-size: 10px; position: absolute; top: 6px; right: 6px\" ng-click=\"removeKeyFile()\"></a></div></div><ion-checkbox ng-model=\"formData.keepAuth\" class=\"item ink item-text-wrap\"><div class=\"item-content dark\" translate>LOGIN.MEMORIZE_AUTH_FILE</div></ion-checkbox>"); -$templateCache.put("templates/login/form_login.html","<form name=\"loginForm\" novalidate=\"\" ng-submit=\"doLogin()\" autocomplete=\"off\"><div class=\"list padding no-padding-xs\" ng-init=\"setForm(loginForm)\" ng-switch on=\"formData.method\"><div class=\"item hidden-xs no-padding\" ng-if=\"showMethods\"><div class=\"pull-right\"><a class=\"button button-text button-small-padding icon-right ink\" ng-click=\"showMethodsPopover($event)\"><i class=\"icon ion-wrench\"></i> {{\'LOGIN.BTN_METHODS\'| translate}} </a> <a class=\"button button-icon positive button-small-padding icon ion-ios-help-outline\" style=\"right: 8px\" ng-click=\"showHelpModal(\'login-method\')\"></a></div></div><div ng-switch-when=\"SCRYPT_DEFAULT\"><ng-include src=\"\'templates/login/form_scrypt.html\'\"></ng-include></div><div ng-switch-when=\"SCRYPT_ADVANCED\"><ng-include src=\"\'templates/login/form_scrypt_advanced.html\'\"></ng-include></div><div ng-switch-when=\"PUBKEY\"><ng-include src=\"\'templates/login/form_pubkey.html\'\"></ng-include></div><div ng-switch-when=\"FILE\"><ng-include src=\"\'templates/login/form_file_import.html\'\"></ng-include></div><div ng-switch-default><ng-include src=\"\'templates/login/form_scrypt.html\'\"></ng-include></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-positive ink\" ng-class=\"{\'button-assertive\': isAuth, \'button-positive\': !isAuth}\" type=\"submit\">{{isAuth ? \'AUTH.BTN_AUTH\' : \'COMMON.BTN_LOGIN\' | translate}}</button></div><div class=\"text-center no-padding visible-xs\"><br><a ng-click=\"showMethodsPopover($event)\"><i class=\"ion-loop\"></i> <span translate>LOGIN.BTN_METHODS_DOTS</span></a><br><br></div><ng-if ng-if=\"!isAuth\"><div class=\"text-center no-padding\">{{\'LOGIN.NO_ACCOUNT_QUESTION\'|translate}}<br class=\"visible-xs\"><a ng-click=\"showJoinModal()\" translate>LOGIN.CREATE_ACCOUNT</a></div><br class=\"visible-xs\"><div class=\"text-center no-padding\"><a ng-click=\"showAccountSecurityModal()\" translate>LOGIN.FORGOTTEN_ID</a></div></ng-if></form>"); -$templateCache.put("templates/login/form_pubkey.html","<div class=\"item\"><p class=\"item-text-wrap\" translate>LOGIN.PUBKEY_FORM_HELP</p></div><div class=\"item item-input item-button-right\" ng-class=\"{ \'item-input-error\': form.$submitted && form.pubkey.$invalid}\"><span class=\"input-label hidden-xs\" translate>COMMON.PUBKEY</span> <input name=\"pubkey\" type=\"text\" placeholder=\"{{\'LOGIN.PUBKEY_HELP\' | translate}}\" ng-model=\"formData.pubkey\" ng-model-options=\"{ debounce: 650 }\" ng-pattern=\"pubkeyPattern\" required> <a class=\"button button-stable icon ion-android-search ink\" ng-click=\"showWotLookupModal()\"></a></div><div class=\"form-errors\" ng-show=\"form.$submitted && form.pubkey.$error\" ng-messages=\"form.pubkey.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div><div class=\"form-error\" ng-message=\"pattern\"><span translate=\"ERROR.INVALID_PUBKEY\"></span></div></div>"); -$templateCache.put("templates/login/form_scrypt.html","<div class=\"item item-text-wrap\"><p ng-bind-html=\"isAuth ? \'AUTH.SCRYPT_FORM_HELP\': \'LOGIN.SCRYPT_FORM_HELP\'|translate\"></p></div><input type=\"password\" name=\"fake-password\" autocomplete=\"off\" style=\"visibility:hidden; position:absolute\"><label class=\"item item-input\" ng-class=\"{ \'item-input-error\': form.$submitted && form.username.$invalid}\"><span class=\"input-label hidden-xs\" translate>LOGIN.SALT</span> <input name=\"username\" type=\"password\" placeholder=\"{{\'LOGIN.SALT_HELP\' | translate}}\" autocomplete=\"off\" ng-model=\"formData.username\" ng-model-options=\"{ debounce: 650 }\" class=\"highlight-light\" required></label><div class=\"form-errors\" ng-show=\"form.$submitted && form.username.$error\" ng-messages=\"form.username.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div><label class=\"item item-input\" ng-class=\"{ \'item-input-error\': form.$submitted && form.password.$invalid}\"><span class=\"input-label hidden-xs\" translate>LOGIN.PASSWORD</span> <input name=\"password\" type=\"password\" placeholder=\"{{\'LOGIN.PASSWORD_HELP\' | translate}}\" autocomplete=\"off\" ng-model=\"formData.password\" ng-model-options=\"{ debounce: 650 }\" select-on-click required></label><div class=\"form-errors\" ng-show=\"form.$submitted && form.password.$error\" ng-messages=\"form.password.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div><div class=\"item item-icon-right item-text-wrap\" ng-class=\"{ \'item-input-error\': pubkeyError, \'item-input\': showPubkey}\"><span class=\"input-label hidden-xs animate-show-hide ng-hide\" ng-show=\"showPubkey\" translate>COMMON.PUBKEY</span><div class=\"item-content text-wrap\"><a class=\"positive ink animate-show-hide ng-hide\" ng-show=\"showComputePubkeyButton && !pubkey\" ng-click=\"computePubkey()\"><i class=\"ion-eye\"></i> {{\'COMMON.BTN_SHOW_PUBKEY\' | translate}} </a><span class=\"gray animate-show-hide\" ng-show=\"!computing && pubkey\">{{pubkey}}</span><ion-spinner class=\"ion-spinner-small\" icon=\"android\" ng-if=\"computing\"></ion-spinner></div><a class=\"button button-icon positive button-small-padding icon ion-ios-help-outline animate-show-hide\" ng-click=\"showHelpModal(\'login-pubkey\')\" ng-if=\"!expectedPubkey\" ng-show=\"showPubkey\"></a> <span class=\"button button-icon balanced button-small-padding icon ion-checkmark animate-show-hide\" ng-if=\"expectedPubkey\" ng-show=\"showPubkey && !showComputePubkeyButton && !computing && !pubkeyError\"></span></div><div class=\"form-errors\" ng-if=\"expectedPubkey\"><div class=\"form-error\" ng-show=\"pubkeyError\"><span trust-as-html=\"::\'ERROR.AUTH_INVALID_PUBKEY\'|translate:{pubkey: expectedPubkey}\"></span></div></div>"); -$templateCache.put("templates/login/form_scrypt_advanced.html","<div class=\"row responsive-md responsive-sm padding-left\"><div class=\"col col-33 no-padding\"><label class=\"item item-input item-select\"><select ng-model=\"formData.scrypt\" style=\"max-width: 100%\" ng-change=\"changeScrypt(formData.scrypt)\" ng-options=\"l as (l.label | translate) for l in scryptParamsValues track by l.id\"></select></label></div><div class=\"col no-padding\"><label class=\"item item-input\"><span class=\"input-label\" translate>LOGIN.SCRYPT.N</span> <input class=\"no-padding-right\" type=\"number\" placeholder=\"N\" ng-model=\"formData.scrypt.params.N\" ng-model-options=\"{ debounce: 650 }\" ng-change=\"onScryptFormChanged()\" required></label></div><div class=\"col no-padding\"><label class=\"item item-input\"><span class=\"input-label\" translate>LOGIN.SCRYPT.r</span> <input class=\"no-padding-right\" type=\"number\" placeholder=\"r\" ng-model=\"formData.scrypt.params.r\" ng-model-options=\"{ debounce: 650 }\" ng-change=\"onScryptFormChanged()\" required></label></div><div class=\"col no-padding\"><label class=\"item item-input\"><span class=\"input-label\" translate>LOGIN.SCRYPT.p</span> <input class=\"no-padding-right\" type=\"number\" placeholder=\"p\" ng-model=\"formData.scrypt.params.p\" ng-model-options=\"{ debounce: 650 }\" ng-change=\"onScryptFormChanged()\" required></label></div></div><p class=\"energized-100-bg padding\"><i class=\"icon ion-android-warning\"></i> <span translate>INFO.FEATURES_NOT_IMPLEMENTED</span></p><ng-include src=\"\'templates/login/form_scrypt.html\'\"></ng-include>"); -$templateCache.put("templates/login/item_remember_me.html","<ion-checkbox ng-model=\"formData.rememberMe\" ng-if=\"!isAuth\" class=\"item ink item-text-wrap\"><div class=\"item-content dark\" translate>SETTINGS.REMEMBER_ME</div></ion-checkbox>"); -$templateCache.put("templates/login/modal_login.html","<ion-modal-view class=\"modal-full-height modal-login\"><ion-header-bar class=\"\" ng-class=\"{\'bar-positive\': !isAuth, \'bar-assertive\': isAuth}\"><button class=\"button button-clear visible-xs\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title\" ng-bind-html=\"isAuth ? \'AUTH.TITLE\' : \'LOGIN.TITLE\' | translate\"></h1><div class=\"buttons buttons-right\"><div class=\"secondary-buttons\"><button class=\"button button-positive button-icon button-clear icon ion-android-done visible-xs\" ng-click=\"doLogin()\"></button></div></div></ion-header-bar><ion-content><ng-include src=\"\'templates/login/form_login.html\'\"></ng-include></ion-content></ion-modal-view>"); -$templateCache.put("templates/login/popover_methods.html","<ion-popover-view class=\"fit has-header popover-login-methods\" ng-class=\"{\'auth\': isAuth}\"><ion-header-bar><h1 class=\"title\" translate>LOGIN.METHOD_POPOVER_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink\" ng-click=\"changeMethod(\'SCRYPT_DEFAULT\')\"><i class=\"icon ion-shuffle\" style=\"font-size: 22px\"></i> {{\'LOGIN.METHOD.SCRYPT_DEFAULT\' | translate}} </a><a class=\"item item-icon-left ink\" ng-click=\"changeMethod(\'SCRYPT_ADVANCED\')\"><i class=\"icon ion-shuffle\" style=\"font-size: 22px\"></i> <i class=\"icon-secondary ion-plus\" style=\"font-size: 13px; left: 40px; margin-top: -4px\"></i> {{\'LOGIN.METHOD.SCRYPT_ADVANCED\' | translate}} </a><a class=\"item item-icon-left ink hidden-xs\" ng-click=\"changeMethod(\'FILE\')\"><i class=\"icon ion-document-text\"></i> {{\'LOGIN.METHOD.FILE\' | translate}}</a><ng-if ng-if=\"!isAuth\"><div class=\"item-divider\"></div><a class=\"item item-icon-left ink\" ng-click=\"changeMethod(\'PUBKEY\')\"><i class=\"icon ion-key\"></i> {{\'LOGIN.METHOD.PUBKEY\' | translate}}</a></ng-if></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/network/item_content_peer.html","<i class=\"icon ion-android-desktop\" ng-class=\":rebind:{\'balanced\': peer.online && peer.hasMainConsensusBlock, \'energized\': peer.online && peer.hasConsensusBlock, \'gray\': peer.online && !peer.hasConsensusBlock && !peer.hasMainConsensusBlock, \'stable\': !peer.online}\" ng-if=\":rebind:!peer.avatar\"></i> <b class=\"icon-secondary ion-person\" ng-if=\":rebind:!peer.avatar\" ng-class=\":rebind:{\'balanced\': peer.online && peer.hasMainConsensusBlock, \'energized\': peer.online && peer.hasConsensusBlock, \'gray\': peer.online && !peer.hasConsensusBlock && !peer.hasMainConsensusBlock, \'stable\': !peer.online}\" style=\"left: 26px; top: -3px\"></b> <i class=\"avatar\" ng-if=\":rebind:peer.avatar\" style=\"background-image: url(\'{{:rebind:peer.avatar.src}}\')\"></i> <b class=\"icon-secondary assertive ion-close-circled\" ng-if=\":rebind:!peer.online\" style=\"left: 37px; top: -10px\"></b><div class=\"row no-padding\"><div class=\"col no-padding\"><h3 class=\"dark\" ng-if=\":rebind:!peer.bma.private\">{{:rebind:peer.dns || peer.server}}</h3><h4 class=\"gray\" ng-if=\":rebind:peer.bma.private\"><i class=\"ion-flash\"></i> {{\'NETWORK.VIEW.PRIVATE_ACCESS\'|translate}}</h4><h4><span class=\"gray\" ng-if=\":rebind:!peer.uid\"><i class=\"ion-key\"></i> {{:rebind:peer.pubkey|formatPubkey}} </span><span class=\"positive\" ng-if=\":rebind:peer.uid\"><i class=\"ion-person\"></i> {{:rebind:peer.name || peer.uid}} </span><span class=\"gray\">{{:rebind:peer.dns && (\' | \' + peer.server) + (peer.bma.path||\'\') }}</span></h4></div><div class=\"col col-20 no-padding text-center\" ng-if=\"::expertMode && search.type != \'offline\'\"></div><div class=\"col col-20 no-padding text-center\"><span id=\"{{$index === 0 ? helptipPrefix + \'-peer-0-block\' : \'\'}}\" class=\"badge\" ng-class=\":rebind:{\'badge-balanced\': peer.hasMainConsensusBlock, \'badge-energized\': peer.hasConsensusBlock, \'ng-hide\': !peer.currentNumber }\">{{::!expertMode ? (\'COMMON.BLOCK\'|translate) : \'\' }} {{:rebind:peer.currentNumber|formatInteger}}</span> <span class=\"badge badge-secondary\" ng-if=\":rebind:peer.consensusBlockDelta && expertMode\"><i class=\"ion-clock\"></i> {{:rebind:peer.consensusBlockDelta|formatDurationTime}}</span></div></div>"); -$templateCache.put("templates/network/items_peers.html","<div ng-class=\"::motion.ionListClass\" class=\"no-padding\"><div class=\"item item-text-wrap no-border done in gray no-padding-top no-padding-bottom inline text-italic\" ng-if=\"::isHttps && expertMode\"><small><i class=\"icon ion-alert-circled\"></i> {{\'NETWORK.INFO.ONLY_SSL_PEERS\'|translate}}</small></div><div ng-repeat=\"peer in :rebind:search.results track by peer.id\" class=\"item item-peer item-icon-left ink\" ng-class=\"::ionItemClass\" id=\"{{helptipPrefix}}-peer-{{$index}}\" ng-click=\"selectPeer(peer)\" ng-include=\"\'templates/network/item_content_peer.html\'\"></div></div>"); -$templateCache.put("templates/network/lookup_popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>PEER.POPOVER_FILTER_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left item-icon-right ink\" ng-click=\"toggleSearchType(\'member\')\"><i class=\"icon ion-person\"></i> {{\'PEER.MEMBERS\' | translate}} <i class=\"icon ion-ios-checkmark-empty\" ng-show=\"search.type==\'member\'\"></i> </a><a class=\"item item-icon-left item-icon-right ink\" ng-click=\"toggleSearchType(\'mirror\')\"><i class=\"icon ion-radio-waves\"></i> {{\'PEER.MIRRORS\' | translate}} <i class=\"icon ion-ios-checkmark-empty\" ng-show=\"search.type==\'mirror\'\"></i> </a><a class=\"item item-icon-left item-icon-right ink\" ng-click=\"toggleSearchType(\'offline\')\"><i class=\"icon ion-eye-disabled\"></i> {{\'PEER.OFFLINE\' | translate}} <i class=\"icon ion-ios-checkmark-empty\" ng-show=\"search.type==\'offline\'\"></i></a></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/network/modal_network.html","<ion-modal-view id=\"nodes\" class=\"modal-full-height\" cache-view=\"false\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear\" ng-click=\"closeModal()\" translate=\"\">COMMON.BTN_CANCEL</button><h1 class=\"title\" translate=\"\">PEER.PEER_LIST</h1><div class=\"buttons buttons-right header-item\"><span class=\"secondary\"><button class=\"button button-clear icon ion-loop button-clear\" ng-click=\"refresh()\"></button> <button class=\"button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"></button></span></div></ion-header-bar><ion-content><div class=\"list\"><div class=\"padding padding-xs\" style=\"display: block; height: 60px\"><div class=\"pull-left\"><h4 ng-if=\"enableFilter && search.type==\'member\'\">{{\'PEER.MEMBERS\' | translate}} <span ng-if=\"!search.loading\">({{search.results.length}})</span></h4><h4 ng-if=\"enableFilter && search.type==\'mirror\'\">{{\'PEER.MIRRORS\' | translate}} <span ng-if=\"!search.loading\">({{search.results.length}})</span></h4><h4 ng-if=\"!enableFilter || !search.type\">{{\'PEER.ALL_PEERS\' | translate}} <span ng-if=\"!search.loading\">({{search.results.length}})</span></h4></div><div class=\"pull-right\"><ion-spinner class=\"icon\" icon=\"android\" ng-if=\"search.loading\"></ion-spinner> <div class=\"pull-right\"> </div></div></div><ng-include src=\"\'templates/network/items_peers.html\'\"></ng-include></div></ion-content></ion-modal-view>"); -$templateCache.put("templates/network/popover_endpoints.html","<ion-popover-view class=\"popover-endpoints popover-light\" style=\"height: {{(titleKey?30:0)+((!items || items.length <= 1) ? 55 : 3+items.length*52)}}px\"><ion-header-bar class=\"bar bar-header stable-bg\" ng-if=\"titleKey\"><div class=\"title\">{{titleKey | translate:titleValues }}</div></ion-header-bar><ion-content scroll=\"false\"><div class=\"list\" ng-class=\"{\'has-header\': titleKey}\"><div class=\"item item-text-wrap\" ng-repeat=\"item in items\"><div class=\"item-label\" ng-if=\"item.label\">{{item.label | translate}}</div><div id=\"endpoint_{{$index}}\" class=\"badge item-note dark\">{{item.value}}</div></div></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/network/popover_network.html",""); -$templateCache.put("templates/network/popover_peer_info.html",""); -$templateCache.put("templates/network/view_network.html","<ion-view><ion-nav-title><span translate=\"\">MENU.NETWORK</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-loop visible-xs visible-sm\" ng-click=\"refresh()\"></button></ion-nav-buttons><ion-content scroll=\"true\" ng-init=\"enableFilter=true; ionItemClass=\'item-border-large\';\"><div class=\"row responsive-sm responsive-md responsive-lg\"><div class=\"col list col-border-right\"><div class=\"padding padding-xs\" style=\"display: block; height: 60px\"><div class=\"pull-left\"><h4><span ng-if=\"enableFilter && search.type==\'member\'\" translate=\"\">PEER.MEMBERS</span> <span ng-if=\"enableFilter && search.type==\'mirror\'\" translate=\"\">PEER.MIRRORS</span> <span ng-if=\"enableFilter && search.type==\'offline\'\" translate=\"\">PEER.OFFLINE</span> <span ng-if=\"!enableFilter || !search.type\" translate=\"\">PEER.ALL_PEERS</span> <span ng-if=\"search.results.length\">({{search.results.length}})</span><ion-spinner ng-if=\"search.loading\" class=\"icon ion-spinner-small\" icon=\"android\"></ion-spinner></h4></div><div class=\"pull-right\"><div class=\"pull-right\" ng-if=\"enableFilter\"> <cs-extension-point name=\"filter-buttons\"></cs-extension-point></div></div></div><div id=\"helptip-network-blockchain\" style=\"display: block\"></div><div id=\"helptip-network-peers\" style=\"display: block\"></div><ng-include src=\"\'templates/network/items_peers.html\'\"></ng-include></div><div class=\"col col-33\" ng-controller=\"BlockLookupCtrl\"><div class=\"padding padding-xs\" style=\"display: block; height: 100px\"><h4 translate=\"\">BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4></div><ng-include src=\"\'templates/blockchain/list_blocks.html\'\"></ng-include></div></div></ion-content></ion-view>"); -$templateCache.put("templates/network/view_peer.html","<ion-view><ion-nav-title><span translate=\"\">PEER.VIEW.TITLE</span></ion-nav-title><ion-content class=\"has-header\" scroll=\"true\"><div class=\"row no-padding\"><div class=\"col list\"><ion-item><h1><span translate=\"\">PEER.VIEW.TITLE</span> <span class=\"gray\">{{node.host}}</span></h1><h2 class=\"gray\"><i class=\"gray icon ion-android-globe\"></i> {{node.bma.dns || node.server}} <span class=\"gray\" ng-if=\"!loading && node.useSsl\"><i class=\"gray ion-locked\"></i> <small>SSL</small> </span><span class=\"gray\" ng-if=\"!loading && node.useTor\"><i class=\"gray ion-bma-tor-api\"></i> </span><span class=\"assertive\" ng-if=\"!loading && !node.uid\">({{\'PEER.MIRROR\'|translate}})</span></h2><h3><span class=\"dark\"><i class=\"icon ion-android-desktop\"></i> {{\'PEER.VIEW.OWNER\'|translate}} </span><a class=\"positive\" ng-if=\"node.uid\" ui-sref=\"app.wot_identity({pubkey: node.pubkey, uid: node.uid})\"><i class=\"ion-person\"></i> {{node.name || node.uid}} <span class=\"gray\" ng-if=\"node.name\">({{node.uid}}) </span></a><span ng-if=\"!loading && !node.uid\"><a class=\"gray\" ui-sref=\"app.wot_identity({pubkey: node.pubkey})\"><i class=\"ion-key\"></i> {{node.pubkey|formatPubkey}} <span class=\"gray\" ng-if=\"node.name\">({{node.name}})</span></a></span></h3><h3><a ng-click=\"openRawPeering($event)\"><i class=\"icon ion-share\"></i> {{\'PEER.VIEW.SHOW_RAW_PEERING\'|translate}} </a><span class=\"gray\" ng-if=\"!isReachable\">| </span><a ng-if=\"!isReachable\" ng-click=\"openRawCurrentBlock($event)\"><i class=\"icon ion-share\"></i> <span translate=\"\">PEER.VIEW.SHOW_RAW_CURRENT_BLOCK</span></a></h3></ion-item><div class=\"item item-divider\" translate=\"\">PEER.VIEW.GENERAL_DIVIDER</div><ion-item class=\"item-icon-left item-text-wrap ink\" copy-on-click=\"{{node.pubkey}}\"><i class=\"icon ion-key\"></i> <span translate=\"\">COMMON.PUBKEY</span><h4 class=\"dark text-left\">{{node.pubkey}}</h4></ion-item><a class=\"item item-icon-left item-icon-right item-text-wrap ink\" ng-if=\"isReachable\" ui-sref=\"app.view_server_block_hash({server: node.server, ssl: node.useSsl, tor: node.useTor, number: current.number, hash: current.hash})\"><i class=\"icon ion-cube\"></i> <span translate=\"\">BLOCKCHAIN.VIEW.TITLE_CURRENT</span><div class=\"badge badge-calm\" ng-if=\"!loading\">{{current.number|formatInteger}}</div><i class=\"gray icon ion-ios-arrow-right\"></i> </a><a class=\"item item-icon-left item-icon-right item-text-wrap ink\" ng-if=\"isReachable\" ui-sref=\"app.server_blockchain({server: node.server, ssl: node.useSsl, tor: node.useTor})\"><i class=\"icon ion-cube\" style=\"font-size: 25px\"></i> <i class=\"icon-secondary ion-clock\" style=\"font-size: 18px; left: 33px; top: -12px\"></i> <span translate=\"\">PEER.VIEW.LAST_BLOCKS</span> <i class=\"gray icon ion-ios-arrow-right\"></i></a><cs-extension-point name=\"general\"></cs-extension-point><div class=\"item item-divider\" ng-hide=\"loading || !isReachable\" translate=\"\">PEER.VIEW.KNOWN_PEERS</div><ion-item class=\"item item-text-wrap no-border done in gray no-padding-top no-padding-bottom inline text-italic\" ng-show=\"!loading && !isReachable\"><small><i class=\"icon ion-alert-circled\"></i> {{\'NETWORK.INFO.ONLY_SSL_PEERS\'|translate}}</small></ion-item><div class=\"item center\" ng-if=\"loading\"><ion-spinner class=\"icon\" icon=\"android\"></ion-spinner></div><div class=\"list no-padding {{::motion.ionListClass}}\" ng-if=\"isReachable\"><div ng-repeat=\"peer in :rebind:peers track by peer.id\" class=\"item item-peer item-icon-left ink\" ng-class=\"::ionItemClass\" ng-click=\"selectPeer(peer)\" ng-include=\"\'templates/network/item_content_peer.html\'\"></div></div></div></div></ion-content></ion-view>"); -$templateCache.put("templates/settings/popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink visible-xs visible-sm\" ng-click=\"reset()\"><i class=\"icon ion-refresh\"></i> {{\'SETTINGS.BTN_RESET\' | translate}} </a><a class=\"item item-icon-left ink\" ng-click=\"startSettingsTour()\"><i class=\"icon ion-easel\"></i> {{\'COMMON.BTN_HELP_TOUR_SCREEN\' | translate}}</a></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/settings/popup_node.html","<form name=\"popupForm\" ng-submit=\"\"><div class=\"list no-padding\" ng-init=\"setPopupForm(popupForm)\"><div class=\"item item-input item-floating-label\" ng-class=\"{\'item-input-error\': popupForm.$submitted && popupForm.newNode.$invalid}\"><span class=\"input-label\" ng-bind-html=\"\'SETTINGS.POPUP_PEER.HOST\'|translate\"></span> <input name=\"newNode\" type=\"text\" placeholder=\"{{\'SETTINGS.POPUP_PEER.HOST_HELP\' | translate}}\" ng-model=\"popupData.newNode\" ng-minlength=\"3\" required></div><div class=\"form-errors\" ng-if=\"popupForm.$submitted && popupForm.newNode.$error\" ng-messages=\"popupForm.newNode.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div><div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT\"></span></div></div><div class=\"item item-toggle\"><span class=\"input-label\">{{\'SETTINGS.POPUP_PEER.USE_SSL\' | translate}}</span><h4><small class=\"gray\" ng-bind-html=\"\'SETTINGS.POPUP_PEER.USE_SSL_HELP\' | translate\"></small></h4><label class=\"toggle toggle-royal no-padding-right\"><input type=\"checkbox\" ng-model=\"popupData.useSsl\"><div class=\"track\"><div class=\"handle\"></div></div></label></div><a class=\"button button-positive button-clear positive button-outline button-full button-small-padding icon-left ink no-padding\" ng-click=\"showNodeList()\"><i class=\"icon ion-search\"></i> {{\'SETTINGS.POPUP_PEER.BTN_SHOW_LIST\' | translate}}</a></div><button type=\"submit\" class=\"hide\"></button></form>"); -$templateCache.put("templates/settings/settings.html","<ion-view left-buttons=\"leftButtons\" cache-view=\"false\" class=\"settings\"><ion-nav-title translate=\"\">SETTINGS.TITLE</ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"></button></ion-nav-buttons><ion-content><div class=\"list item-border-large\"><div class=\"item item-toggle dark\"><div class=\"input-label\">{{\'COMMON.BTN_RELATIVE_UNIT\' | translate}}</div><label class=\"toggle toggle-royal\" id=\"helptip-settings-btn-unit-relative\"><input type=\"checkbox\" ng-model=\"formData.useRelative\"><div class=\"track\"><div class=\"handle\"></div></div></label></div><label class=\"item item-input item-select\"><div class=\"input-label\">{{\'COMMON.LANGUAGE\' | translate}}</div><select ng-model=\"formData.locale\" ng-change=\"changeLanguage(formData.locale.id)\" ng-options=\"l as l.label for l in locales track by l.id\"></select></label><div class=\"item item-text-wrap item-toggle dark\"><div class=\"input-label\">{{\'SETTINGS.USE_LOCAL_STORAGE\' | translate}}</div><h4 class=\"gray\" ng-bind-html=\"\'SETTINGS.USE_LOCAL_STORAGE_HELP\' | translate\"></h4><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.useLocalStorage\"><div class=\"track\"><div class=\"handle\"></div></div></label></div><div class=\"item item-toggle dark item-text-wrap\"><div class=\"input-label\" ng-bind-html=\"\'SETTINGS.ENABLE_HELPTIP\' | translate\"></div><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.helptip.enable\"><div class=\"track\"><div class=\"handle\"></div></div></label></div><cs-extension-point name=\"common\"></cs-extension-point><span class=\"item item-divider\">{{\'SETTINGS.AUTHENTICATION_SETTINGS\' | translate}}</span><div class=\"item item-toggle\"><div class=\"input-label\" ng-class=\"{\'gray\': !formData.useLocalStorage}\">{{\'SETTINGS.REMEMBER_ME\' | translate}}</div><h4 class=\"gray text-wrap\" ng-bind-html=\"\'SETTINGS.REMEMBER_ME_HELP\' | translate\"></h4><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.rememberMe\" ng-disabled=\"!formData.useLocalStorage\"><div class=\"track\"><div class=\"handle\"></div></div></label></div><div class=\"item item-input item-select\"><div class=\"input-label\"><span class=\"input-label\" translate=\"\">SETTINGS.KEEP_AUTH</span><h4 class=\"gray text-wrap\" ng-bind-html=\"\'SETTINGS.KEEP_AUTH_HELP\' | translate\"></h4></div><label><select ng-model=\"formData.keepAuthIdle\" ng-options=\"i as (keepAuthIdleLabels[i].labelKey | translate:keepAuthIdleLabels[i].labelParams ) for i in keepAuthIdles track by i\"></select></label></div><span class=\"item item-divider\" translate=\"\">SETTINGS.HISTORY_SETTINGS</span><div class=\"item item-toggle dark\"><div class=\"col col-75 input-label\" translate=\"\">SETTINGS.DISPLAY_UD_HISTORY</div><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.showUDHistory\"><div class=\"track\"><div class=\"handle\"></div></div></label></div><cs-extension-point name=\"history\"></cs-extension-point><span class=\"item item-divider\" translate=\"\">SETTINGS.NETWORK_SETTINGS</span><div class=\"item ink item-text-wrap\" ng-click=\"changeNode()\"><div class=\"input-label\">{{\'SETTINGS.PEER\' | translate}}</div><ng-if ng-if=\"formData.node.temporary\"><h4 class=\"gray text-wrap assertive\"><i class=\"icon ion-alert-circled\"></i> <span ng-bind-html=\"\'SETTINGS.PEER_CHANGED_TEMPORARY\' | translate \"></span></h4><div class=\"item-note assertive text-italic\">{{bma.server}}</div></ng-if><div class=\"item-note dark\" ng-if=\"!formData.node.temporary\">{{bma.server}}</div></div><cs-extension-point name=\"network\"></cs-extension-point><span class=\"item item-divider\" ng-if=\"$root.config.plugins\" translate=\"\">SETTINGS.PLUGINS_SETTINGS</span><cs-extension-point name=\"plugins\"></cs-extension-point></div></ion-content></ion-view>"); -$templateCache.put("templates/wallet/item_tx.html","<i class=\"icon item-image\" ng-if=\"::!tx.avatar\" ng-class=\"::{\'ion-person dark\': tx.uid, \'ion-card dark\': !tx.uid}\"></i> <i class=\"avatar\" ng-if=\"::tx.avatar\" style=\"background-image: url({{::tx.avatar.src}})\"></i><div class=\"row no-padding\"><div class=\"col no-padding\"><b class=\"ion-clock\" ng-if=\"::pending\"></b> <a class=\"\" ui-sref=\"app.wot_identity({pubkey:tx.pubkey, uid:tx.uid})\" ng-if=\"tx.uid\">{{::tx.name||tx.uid}} </a><a class=\"gray\" ui-sref=\"app.wot_identity({pubkey:tx.pubkey, uid:tx.uid})\" ng-if=\"!tx.uid\"><i class=\"ion-key gray\"></i> {{::tx.pubkey | formatPubkey}}</a><p class=\"dark visible-xs width-cup text-italic\" data-toggle=\"tooltip\" ng-if=\"::tx.comment\" title=\"{{::tx.comment}}\"><i class=\"ion-ios-chatbubble-outline\"></i> {{::tx.comment}}<br></p><h4><a ng-if=\"::!pending\" class=\"gray underline\" ui-sref=\"app.view_block({number: tx.block_number})\">{{::tx.time | formatFromNow}} | {{::tx.time | formatDate}} </a><span ng-if=\"::pending\" class=\"gray\">{{::tx.time | formatFromNow}} | {{::tx.time | formatDate}}</span></h4></div><div class=\"col col-50 no-padding\" ng-if=\"::tx.comment\"><p class=\"vertical-center gray text-italic hidden-xs\" data-toggle=\"tooltip\" title=\"{{::tx.comment}}\">{{::tx.comment}}</p></div><div class=\"col col-10 no-padding\"><span ng-if=\"::!tx.lockedOutputs\" class=\"badge item-note\" ng-class=\"{\'badge-calm\': tx.amount > 0}\"><span ng-bind-html=\":rebind:tx.amount| formatAmount:{currency:$root.currency.name}\"></span> </span><a ng-if=\":rebind:tx.lockedOutputs\" class=\"badge item-note\" ng-class=\"{\'badge-calm\': tx.amount > 0}\" ng-click=\"showLockedOutputsPopover(tx, $event)\"><i class=\"icon ion-locked\"></i><span ng-bind-html=\":rebind:tx.amount| formatAmount:{currency:$root.currency.name}\"></span></a><div class=\"badge badge-secondary\" ng-if=\"$root.settings.expertMode\">(<span ng-bind-html=\":rebind:tx.amount| formatAmount:{useRelative: !$root.settings.useRelative, currency:$root.currency.name}\"></span>)</div></div></div>"); -$templateCache.put("templates/wallet/item_ud.html","<i class=\"icon item-image ion-arrow-up-c energized\"></i><div class=\"row no-padding\"><div class=\"col no-padding\"><span class=\"energized\" translate>COMMON.UNIVERSAL_DIVIDEND</span><h4><a class=\"gray underline\" ui-sref=\"app.view_block({number: tx.block_number})\">{{::tx.time | formatFromNow}} | {{::tx.time | formatDate}}</a></h4></div><div class=\"col col-10 no-padding\"><span class=\"badge item-note badge-energized\"><span ng-bind-html=\":rebind:tx.amount| formatAmount:{currency:$root.currency.name}\"></span></span><div class=\"badge badge-secondary\" ng-if=\"$root.settings.expertMode\">(<span ng-bind-html=\":rebind:tx.amount| formatAmount:{useRelative: !$root.settings.useRelative, currency:$root.currency.name}\"></span>)</div></div></div>"); -$templateCache.put("templates/wallet/modal_security.html","<ion-modal-view class=\"modal-full-height\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear visible-xs\" ng-if=\"!slides.slider.activeIndex\" ng-click=\"closeModal()\" translate=\"\">COMMON.BTN_CANCEL</button> <button class=\"button button-icon button-clear icon ion-ios-arrow-back buttons header-item\" ng-click=\"slidePrev()\" ng-if=\"slides.slider.activeIndex\"></button><h1 class=\"title hidden-xs\" translate=\"\">ACCOUNT.SECURITY.TITLE</h1><button class=\"button button-clear icon-right visible-xs\" ng-if=\"!isLastSlide && slides.slider.activeIndex > 0\" ng-click=\"doNext()\"><span translate=\"\">COMMON.BTN_NEXT</span> <i class=\"icon ion-ios-arrow-right\"></i></button> <button class=\"button button-positive button-icon button-clear icon ion-android-done visible-xs\" ng-click=\"doNext()\" ng-if=\"isLastSlide && option === \'saveID\'\"></button></ion-header-bar><ion-slides options=\"slides.options\" slider=\"slides.slider\"><ion-slide-page><ion-content class=\"has-header padding\"><div class=\"list\"><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"selectOption(\'recoverID\')\" ng-if=\"!isLogin\"><div class=\"item-content item-text-wrap\"><i class=\"item-image dark icon ion-person\"></i> <b class=\"ion-ios-undo icon-secondary dark\" style=\"top: -8px; left: 39px; font-size: 12px\"></b><h2 translate=\"\">ACCOUNT.SECURITY.RECOVER_ID</h2><h4 class=\"gray\" translate=\"\">ACCOUNT.SECURITY.RECOVER_ID_HELP</h4><i class=\"icon dark ion-ios-arrow-right\"></i></div></div><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"selectOption(\'revocation\')\" ng-if=\"!isLogin\"><div class=\"item-content item-text-wrap\"><i class=\"item-image dark icon ion-person\"></i> <b class=\"ion-close icon-secondary dark\" style=\"top: -8px; left: 39px; font-size: 12px\"></b><h2 translate=\"\">ACCOUNT.SECURITY.REVOCATION_WITH_FILE</h2><h4 class=\"gray\" translate=\"\">ACCOUNT.SECURITY.REVOCATION_WITH_FILE_DESCRIPTION</h4><i class=\"icon dark ion-ios-arrow-right\"></i></div></div><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"selectOption(\'saveID\')\" ng-if=\"isLogin\"><div class=\"item-content item-text-wrap\"><i class=\"item-image dark icon ion-person\"></i> <b class=\"ion-ios-redo icon-secondary dark\" style=\"top: -8px; left: 39px; font-size: 12px\"></b> <b class=\"ion-locked icon-secondary dark\" style=\"top: 0px; left: 40px; font-size: 8px\"></b><h2 translate=\"\">ACCOUNT.SECURITY.SAVE_ID</h2><h4 class=\"gray\" translate=\"\">ACCOUNT.SECURITY.SAVE_ID_HELP</h4><i class=\"icon dark ion-ios-arrow-right\"></i></div></div><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"selectOption(\'generateKeyfile\')\" ng-if=\"isLogin\"><div class=\"item-content item-text-wrap\"><i class=\"item-image dark icon ion-document-text\"></i> <b class=\"ion-key icon-secondary dark\" style=\"top: -8px; left: 42px; font-size: 12px\"></b><h2 translate=\"\">ACCOUNT.SECURITY.GENERATE_KEYFILE</h2><h4 class=\"gray\" translate=\"\">ACCOUNT.SECURITY.GENERATE_KEYFILE_HELP</h4><i class=\"icon dark ion-ios-arrow-right\"></i></div></div><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"self()\" ng-if=\"needSelf\"><div class=\"item-content item-text-wrap\"><i class=\"item-image icon ion-person dark\"></i> <b class=\"ion-flag icon-secondary dark\" style=\"top: -8px; left: 39px; font-size: 12px\"></b><h2 translate=\"\">ACCOUNT.SECURITY.SEND_IDENTITY</h2><h4 class=\"gray\" ng-bind-html=\"::\'ACCOUNT.SECURITY.SEND_IDENTITY_HELP\' | translate\"></h4></div></div><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"membershipIn()\" ng-if=\"needMembership\"><div class=\"item-content item-text-wrap\"><i class=\"item-image icon ion-person dark\"></i> <b class=\"ion-plus icon-secondary dark\" style=\"top: -8px; left: 39px; font-size: 12px\"></b><h2 translate=\"\">ACCOUNT.SECURITY.MEMBERSHIP_IN</h2><h4 class=\"gray\" ng-bind-html=\"::\'ACCOUNT.SECURITY.MEMBERSHIP_IN_HELP\' | translate\"></h4></div></div><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"revokeWalletIdentity()\" ng-if=\"isLogin && hasSelf\"><div class=\"item-content item-text-wrap\"><i class=\"item-image icon ion-person assertive-900\"></i> <b class=\"ion-close icon-secondary assertive-900\" style=\"top: -8px; left: 39px; font-size: 12px\"></b><h2 translate=\"\">ACCOUNT.SECURITY.REVOCATION_WALLET</h2><h4 class=\"gray\" translate=\"\">ACCOUNT.SECURITY.REVOCATION_WALLET_HELP</h4></div></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate=\"\">COMMON.BTN_CANCEL</button></div></ion-content></ion-slide-page><ion-slide-page ng-if=\"option == \'revocation\'\"><ng-include src=\"\'templates/wallet/slides/slides_revocation_file.html\'\"></ng-include></ion-slide-page><ion-slide-page ng-if=\"isLogin && option == \'saveID\'\"><ng-include src=\"\'templates/wallet/slides/slides_saveID_1.html\'\"></ng-include></ion-slide-page><ion-slide-page ng-if=\"isLogin && option == \'saveID\'\"><ng-include src=\"\'templates/wallet/slides/slides_saveID_2.html\'\"></ng-include></ion-slide-page><ion-slide-page ng-if=\"option == \'recoverID\'\"><ng-include src=\"\'templates/wallet/slides/slides_recoverID_1.html\'\"></ng-include></ion-slide-page><ion-slide-page ng-if=\"option == \'recoverID\'\"><ng-include src=\"\'templates/wallet/slides/slides_recoverID_2.html\'\"></ng-include></ion-slide-page><ion-slide-page ng-if=\"option == \'recoverID\'\"><ng-include src=\"\'templates/wallet/slides/slides_recoverID_3.html\'\"></ng-include></ion-slide-page><ion-slide-page ng-if=\"isLogin && option == \'generateKeyfile\'\"><ng-include src=\"\'templates/wallet/slides/slides_generate_keyfile.html\'\"></ng-include></ion-slide-page></ion-slides></ion-modal-view>"); -$templateCache.put("templates/wallet/modal_transfer.html","<ion-modal-view id=\"transfer\" class=\"modal-full-height modal-transfer\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear visible-xs\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title\" translate>TRANSFER.MODAL.TITLE</h1><button class=\"button button-icon button-clear icon ion-android-send visible-xs\" ng-click=\"doTransfer()\"></button></ion-header-bar><ion-content scroll=\"true\"><ng-include src=\"\'templates/wallet/transfer_form.html\'\"></ng-include></ion-content><ion-digit-keyboard settings=\"digitKeyboardSettings\" ng-if=\"digitKeyboardVisible\"></ion-digit-keyboard></ion-modal-view>"); -$templateCache.put("templates/wallet/new_transfer.html","<ion-view left-buttons=\"leftButtons\" id=\"transfer\"><ion-nav-title><span class=\"visible-xs visible-sm\" translate=\"\">TRANSFER.TITLE</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-android-send visible-xs\" ng-click=\"doTransfer()\"></button></ion-nav-buttons><ion-content scroll=\"true\"><div class=\"row no-padding-xs\"><div class=\"col no-padding-xs\"><ng-include src=\"\'templates/wallet/transfer_form.html\'\"></ng-include></div></div></ion-content><ion-digit-keyboard settings=\"digitKeyboardSettings\" ng-if=\"digitKeyboardVisible\"></ion-digit-keyboard></ion-view>"); -$templateCache.put("templates/wallet/popover_actions.html","<ion-popover-view class=\"fit has-header popover-wallet-actions\"><ion-header-bar><h1 class=\"title\" translate=\"\">COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink visible-xs visible-sm\" ng-click=\"showSharePopover($event)\"><i class=\"icon ion-android-share-alt\"></i> {{\'COMMON.BTN_SHARE\' | translate}} </a><a class=\"item item-icon-left ink\" ng-if=\"walletData.requirements.alternatives\" ng-click=\"showSelectIdentitiesModal()\"><i class=\"icon ion-person\"></i> <b class=\"icon-secondary ion-loop\" style=\"margin-top: 4px; left: 15px\"></b> {{\'ACCOUNT.BTN_SELECT_ALTERNATIVES_IDENTITIES\' | translate}} </a><a class=\"item item-icon-left ink visible-xs visible-sm\" ng-if=\"!walletData.requirements.needSelf && walletData.requirements.needRenew\" ng-click=\"renewMembership()\"><i class=\"icon ion-loop\"></i> {{\'ACCOUNT.BTN_MEMBERSHIP_RENEW_DOTS\' | translate}} </a><a class=\"item item-icon-left assertive ink\" ng-if=\"walletData.requirements.canMembershipOut\" ng-click=\"membershipOut()\"><i class=\"icon ion-log-out\"></i> {{\'ACCOUNT.BTN_MEMBERSHIP_OUT_DOTS\' | translate}} </a><a class=\"item item-icon-left ink\" ng-click=\"showSecurityModal()\"><i class=\"icon ion-locked\"></i> <span ng-bind-html=\"\'ACCOUNT.BTN_SECURITY_DOTS\' | translate\"></span></a></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/wallet/popover_unit.html","<ion-popover-view class=\"popover-unit\"><ion-content scroll=\"false\"><div class=\"list\"><a class=\"item item-icon-left\" ng-class=\"{ \'selected\': !formData.useRelative}\" ng-click=\"closePopover(false)\"><i class=\"icon\" ng-class=\"{ \'ion-ios-checkmark-empty\': !formData.useRelative}\"></i> <i ng-bind-html=\"$root.currency.name | currencySymbol:false\"></i> </a><a class=\"item item-icon-left\" ng-class=\"{ \'selected\': formData.useRelative}\" ng-click=\"closePopover(true)\"><i class=\"icon\" ng-class=\"{ \'ion-ios-checkmark-empty\': formData.useRelative}\"></i> <i ng-bind-html=\"$root.currency.name | currencySymbol:true\"></i></a></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/wallet/popup_register.html","<form name=\"registerForm\" ng-submit=\"\"><div class=\"list\" ng-init=\"setRegisterForm(registerForm)\"><label class=\"item item-input\" ng-class=\"{\'item-input-error\': registerForm.$submitted && registerForm.pseudo.$invalid}\"><input name=\"pseudo\" type=\"text\" placeholder=\"{{\'ACCOUNT.NEW.PSEUDO_HELP\' | translate}}\" ng-model=\"walletData.newUid\" ng-minlength=\"3\" required></label><div class=\"form-errors\" ng-if=\"registerForm.$submitted && registerForm.pseudo.$error\" ng-messages=\"registerForm.pseudo.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div><div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT\"></span></div></div></div></form>"); -$templateCache.put("templates/wallet/transfer_form.html","<form name=\"transferForm\" novalidate=\"\" ng-submit=\"doTransfer()\"><div class=\"list no-padding-xs\" ng-init=\"setForm(transferForm)\"><a class=\"item item-icon-right gray ink\" ng-class=\"{\'item-input-error\': form.$submitted && !formData.destPub}\" ng-click=\"showWotLookupModal()\"><span class=\"gray\" translate=\"\">TRANSFER.TO</span> <span class=\"badge badge-royal animate-fade-in animate-show-hide ng-hide\" ng-show=\"destUid\"><i class=\"ion-person\"></i> {{destUid}} </span> <span class=\"badge badge-royal\" ng-show=\"!destUid && formData.destPub\"><i class=\"ion-key\"></i> {{formData.destPub | formatPubkey}} </span><i class=\"gray icon ion-ios-arrow-right\"></i></a><div class=\"form-errors\" ng-if=\"form.$submitted && !formData.destPub\"><div class=\"form-error\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div><span class=\"item item-text-wrap\"><span class=\"gray\" translate=\"\">TRANSFER.FROM</span> <span class=\"badge animate-fade-in animate-show-hide ng-hide\" ng-show=\"!loading\" ng-class=\"{\'badge-assertive\': (convertedBalance <= 0 || (formData.amount && convertedBalance < formData.amount)), \'badge-balanced\': (convertedBalance > 0 && (!formData.amount || convertedBalance >= formData.amount)) }\"><ion-spinner icon=\"android\" ng-if=\"!walletData.pubkey\"></ion-spinner><span ng-if=\"walletData.pubkey && !walletData.isMember\"><i class=\"ion-key\"></i> {{walletData.pubkey| formatPubkey}} </span><span ng-if=\"walletData.isMember\"><i class=\"ion-person\"></i> {{walletData.name||walletData.uid}} </span><span ng-bind-html=\"walletData.balance|formatAmount:{useRelative: formData.useRelative, currency:currency}\"></span></span></span><ion-item class=\"item-input item-floating-label item-button-right\" ng-class=\"{\'item-input-error\': form.$submitted && form.amount.$invalid}\"><div class=\"input-label\"><span translate=\"\">TRANSFER.AMOUNT</span> (<span ng-bind-html=\"$root.currency.name | currencySymbol:formData.useRelative\"></span>)</div><input type=\"text\" class=\"visible-xs visible-sm\" name=\"amount\" placeholder=\"{{::\'TRANSFER.AMOUNT_HELP\' | translate}} ({{$root.currency.name | currencySymbolNoHtml:formData.useRelative}})\" ng-model=\"formData.amount\" required number-float=\"\"><div class=\"block visible-xs visible-sm\" style=\"position:absolute; opacity:0; z-index:100; top: 0; left: 0; height: 100%; width: 100%\" ng-click=\"showDigitKeyboard()\"></div><a class=\"button button-icon gray icon ion-android-more-vertical ink visible-xs visible-sm\" style=\"z-index:110; right: 0px\" ng-click=\"showUnitPopover($event)\"></a></ion-item><div class=\"form-errors\" ng-show=\"form.$submitted && form.amount.$error\" ng-messages=\"form.amount.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div><div class=\"form-error\" ng-message=\"numberFloat\"><span translate=\"ERROR.FIELD_NOT_NUMBER\"></span></div><div class=\"form-error\" ng-message=\"numberInt\"><span translate=\"ERROR.FIELD_NOT_INT\"></span></div><div class=\"form-error\" ng-message=\"min\"><span translate=\"ERROR.FIELD_MIN\" translate-values=\"{min: minAmount}\"></span></div></div><div class=\"pull-right visible-xs visible-sm\" ng-if=\"!formData.useComment\"><a class=\"button button-text button-small ink\" ng-click=\"addComment()\"><i class=\"icon ion-plus\"></i> <span translate=\"\">TRANSFER.BTN_ADD_COMMENT</span></a></div><label class=\"item item-input item-floating-label visible-xs visible-sm\" ng-if=\"formData.useComment\" ng-class=\"{\'item-input-error\': form.$submitted && form.comment.$invalid}\"><span class=\"input-label\">{{\'TRANSFER.COMMENT\' | translate}}</span><textarea placeholder=\"{{\'TRANSFER.COMMENT_HELP\' | translate}}\" id=\"{{commentInputId}}\" name=\"comment\" ng-model=\"formData.comment\" ng-maxlength=\"255\" ng-pattern=\"commentPattern\" ng-focus=\"hideDigitKeyboard()\">\n </textarea></label><div class=\"form-errors\" ng-show=\"form.$submitted && form.comment.$error\" ng-messages=\"form.comment.$error\"><div class=\"form-error\" ng-message=\"maxlength\"><span translate=\"ERROR.FIELD_TOO_LONG\"></span></div><div class=\"form-error\" ng-message=\"pattern\"><span translate=\"ERROR.FIELD_ACCENT\"></span></div></div><div class=\"item item-icon-left item-text-wrap visible-xs visible-sm\" ng-if=\"formData.useComment\"><i class=\"icon ion-ios-information-outline positive\"></i><h4 class=\"positive\" translate=\"\">TRANSFER.WARN_COMMENT_IS_PUBLIC</h4></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"cancel()\" type=\"button\" translate=\"\">COMMON.BTN_CANCEL</button> <button class=\"button button-positive ink\" type=\"submit\">{{\'TRANSFER.BTN_SEND\' | translate}}</button></div></form>"); -$templateCache.put("templates/wallet/tx_locked_outputs_popover.html","<ion-popover-view class=\"fit popover-locked-outputs\"><ion-header-bar><h1 class=\"title\" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.TITLE</h1></ion-header-bar><ion-content scroll=\"true\"><div ng-if=\"popoverData.lockedOuputs.length == 1\" class=\"item item-text-wrap no-border\"><h4 class=\"positive\" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.DESCRIPTION</h4></div><div ng-if=\"popoverData.lockedOuputs.length > 1\" class=\"item item-text-wrap no-border\"><h4 class=\"positive\" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.DESCRIPTION_MANY</h4></div><div ng-repeat=\"output in popoverData.lockedOuputs track by $index\" class=\"item\"><h2 class=\"gray\" ng-if=\"popoverData.lockedOuputs.length > 1\" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.LOCKED_AMOUNT</h2><div ng-if=\"popoverData.lockedOuputs.length > 1\" class=\"badge item-note\" ng-class=\"{\'badge-balanced\': output.amount > 0}\"><i class=\"icon ion-locked\"></i> <span ng-bind-html=\"::output.amount| formatAmount\"></span> <span ng-bind-html=\"::unit\"></span></div><div ng-repeat=\"condition in output.unlockConditions track by $index\" class=\"row\" ng-class=\"::{\'padding-top\': !$index && popoverData.lockedOuputs.length > 1}\" ng-style=\"::condition.style\"><span class=\"gray\" ng-if=\"::condition.operator\">{{::\'BLOCKCHAIN.VIEW.TX_OUTPUT_OPERATOR.\'+condition.operator|translate}} </span><div ng-if=\"::condition.type==\'SIG\'\"><i class=\"icon ion-key dark\"></i> <span class=\"dark\" ng-bind-html=\"::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.SIG\' | translate\"></span> <a ng-click=\"goState(\'app.wot_identity\', {pubkey:condition.value})\" style=\"text-decoration: none\" class=\"positive\">{{condition.value|formatPubkey}}</a></div><div ng-if=\"::condition.type==\'XHX\'\"><i class=\"icon ion-lock-combination dark\"></i> <span class=\"dark\" ng-bind-html=\"::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.XHX\' | translate\"></span> <a copy-on-click=\"{{::condition.value}}\" class=\"positive\">{{::condition.value|formatPubkey}}...</a></div><div ng-if=\"condition.type==\'CSV\'\"><i class=\"icon ion-clock dark\"></i> <span class=\"dark\" ng-bind-html=\"::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CSV\' | translate\"></span> {{::condition.value|formatDuration}}</div><div ng-if=\"condition.type==\'CLTV\'\"><i class=\"icon ion-clock dark\"></i> <span class=\"dark\" ng-bind-html=\"::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CLTV\' | translate\"></span> {{::condition.value|formatDate}}</div></div></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/wallet/view_wallet.html","<ion-view left-buttons=\"leftButtons\" class=\"view-wallet\" id=\"wallet\"><ion-nav-title></ion-nav-title><ion-nav-buttons side=\"secondary\"><cs-extension-point name=\"nav-buttons\"></cs-extension-point><button class=\"button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm\" id=\"helptip-wallet-options-xs\" ng-click=\"showActionsPopover($event)\"></button></ion-nav-buttons><ion-content scroll=\"true\" class=\"refresher-top-bg refresher-light\" bind-notifier=\"{ rebind:settings.useRelative, locale:$root.settings.locale.id}\"><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"doUpdate(true)\"></ion-refresher><div class=\"positive-900-bg hero\" id=\"wallet-header\" ng-class=\"{\'hero-qrcode-active\': toggleQRCode}\"><div class=\"content\" ng-if=\"!loading\"><i class=\"avatar\" ng-if=\":rebind:!formData.avatar\" ng-class=\":rebind:{\'avatar-wallet\': !formData.isMember, \'avatar-member\': formData.isMember}\"></i> <i class=\"avatar\" ng-if=\":rebind:formData.avatar\" style=\"background-image: url({{:rebind:formData.avatar.src}})\"></i><ng-if ng-if=\":rebind:formData.name\"><h3 class=\"light\">{{:rebind:formData.name}}</h3></ng-if><ng-if ng-if=\":rebind:!formData.name\"><h3 class=\"light\" ng-if=\":rebind:formData.uid\">{{:rebind:formData.uid}}</h3><h3 class=\"light\" ng-if=\":rebind:!formData.uid\"><i class=\"ion-key\"></i> {{:rebind:formData.pubkey | formatPubkey}}</h3></ng-if><h4 class=\"assertive\"><ng-if ng-if=\":rebind:(formData.name || formData.uid) && !formData.isMember\" translate=\"\">WOT.NOT_MEMBER_PARENTHESIS</ng-if></h4></div><h4 class=\"content light\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></h4></div><div ng-attr-id=\"{{ qrcodeId }}\" class=\"qrcode spin\" ng-class=\"{\'active\': toggleQRCode}\" ng-click=\"toggleQRCode = !toggleQRCode\"></div><a id=\"wallet-share-anchor\"></a><div class=\"visible-xs visible-sm padding text-center\" ng-if=\"!loading\"><button class=\"button button-assertive button-small-padding ink\" ng-click=\"logout({askConfirm: true})\"><i class=\"icon ion-log-out\"></i> {{\'COMMON.BTN_LOGOUT\' | translate}}</button><div ng-if=\"formData.requirements.needRenew\"><br><button class=\"button button-raised button-stable button-small-padding ink\" ng-click=\"renewMembership()\"><i class=\"icon ion-loop assertive\"></i> <span class=\"assertive\">{{:locale:\'ACCOUNT.BTN_MEMBERSHIP_RENEW\' | translate}}</span></button></div></div><div class=\"row no-padding\"><div class=\"col\"><div class=\"list\" ng-class=\"::motion.ionListClass\" ng-hide=\"loading\"><span class=\"item item-divider\" translate=\"\">WOT.GENERAL_DIVIDER</span><div id=\"helptip-wallet-pubkey\" class=\"item item-icon-left item-text-wrap ink\" on-hold=\"copy(formData.pubkey)\" copy-on-click=\"{{:rebind:formData.pubkey}}\"><i class=\"icon ion-key\"></i> <span>{{:locale:\'COMMON.PUBKEY\'|translate}}</span><h4 id=\"pubkey\" class=\"dark\">{{:rebind:formData.pubkey}}</h4></div><ion-item class=\"item-icon-left\" ng-if=\":rebind:formData.sigDate||formData.uid\"><i class=\"icon ion-calendar\"></i> <span translate=\"\">COMMON.UID</span><h5 class=\"dark\" ng-if=\":rebind:formData.sigDate\"><span translate=\"\">WOT.REGISTERED_SINCE</span> {{:rebind:formData.sigDate | formatDate}}</h5><span class=\"badge badge-stable\">{{:rebind:formData.uid}}</span></ion-item><a id=\"helptip-wallet-certifications\" class=\"item item-icon-left item-icon-right item-text-wrap ink\" ng-if=\"formData.isMember||formData.requirements.pendingMembership||!formData.requirements.needSelf\" ng-click=\"showCertifications()\"><i class=\"icon ion-ribbon-b\"></i> <b ng-if=\"formData.requirements.isSentry\" class=\"ion-star icon-secondary\" style=\"color: yellow; font-size: 16px; left: 25px; top: -7px\"></b> {{:locale:\'ACCOUNT.CERTIFICATION_COUNT\'|translate}}<cs-badge-certification requirements=\"formData.requirements\" parameters=\"::currency.parameters\"></cs-badge-certification><i class=\"gray icon ion-ios-arrow-right\"></i> </a><a id=\"helptip-wallet-given-certifications\" class=\"item item-icon-left item-text-wrap item-icon-right ink visible-xs visible-sm\" ng-if=\"formData.isMember\" ng-click=\"showGivenCertifications()\"><i class=\"icon ion-ribbon-a\"></i> <span translate=\"\">WOT.GIVEN_CERTIFICATIONS.SENT</span> <i class=\"gray icon ion-ios-arrow-right\"></i> </a><a class=\"item item-icon-left item-icon-right ink\" ng-if=\"!loading\" ui-sref=\"app.view_wallet_tx\"><i class=\"icon ion-card\"></i> <span translate=\"\">WOT.ACCOUNT_OPERATIONS</span> <i class=\"gray icon ion-ios-arrow-right\"></i> </a><span class=\"item item-divider\" ng-if=\"formData.events.length\">{{:locale:\'ACCOUNT.EVENTS\' | translate}}</span><div class=\"item item-text-wrap item-icon-left item-wallet-event\" ng-repeat=\"event in formData.events\"><i class=\"icon\" ng-class=\"{\'ion-information-circled royal\': event.type==\'info\',\'ion-alert-circled\': event.type==\'warn\'||event.type==\'error\',\'assertive\': event.type==\'error\',\'ion-clock\': event.type==\'pending\'}\"></i> <span trust-as-html=\"event.message | translate:event.messageParams\"></span></div><cs-extension-point name=\"general\"></cs-extension-point><cs-extension-point name=\"after-general\"></cs-extension-point></div></div></div></ion-content></ion-view>"); -$templateCache.put("templates/wallet/view_wallet_tx.html","<ion-view left-buttons=\"leftButtons\" class=\"view-wallet-tx\"><ion-nav-title></ion-nav-title><ion-nav-buttons side=\"secondary\"><cs-extension-point name=\"nav-buttons\"></cs-extension-point></ion-nav-buttons><ion-content scroll=\"true\" class=\"refresher-top-bg refresher-light\" bind-notifier=\"{ rebind:settings.useRelative, locale:settings.locale.id}\"><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"doUpdate(true)\"></ion-refresher><div class=\"positive-900-bg hero\"><div class=\"content\" ng-if=\"!loading\"><h1 class=\"light\"><span ng-bind-html=\":balance:rebind:formData.balance | formatAmount:{currency: $root.currency.name}\"></span></h1><h4 ng-if=\"!loading && $root.settings.expertMode\" style=\"font-style: italic\">(<span ng-bind-html=\":balance:rebind:formData.balance | formatAmount:{useRelative:!$root.settings.useRelative, currency: $root.currency.name}\"></span>)</h4><div class=\"helptip-anchor-center\"><a id=\"helptip-wallet-balance\"> </a></div></div><h2 class=\"content light\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></h2></div><div class=\"row no-padding\"><div class=\"col\"><div class=\"list\" ng-class=\"::motion.ionListClass\"><a class=\"item item-icon-left item-icon-right ink\" ng-if=\"formData.tx.errors && formData.tx.errors.length\" ui-sref=\"app.view_wallet_tx_errors\"><i class=\"icon ion-alert-circled\"></i> {{:locale:\'ACCOUNT.ERROR_TX\'|translate}}<div class=\"badge badge-assertive\">{{formData.tx.errors.length}}</div><i class=\"gray icon ion-ios-arrow-right\"></i> </a><span class=\"item item-pending item-divider\" ng-if=\"formData.tx.pendings && formData.tx.pendings.length\">{{:locale:\'ACCOUNT.PENDING_TX\'|translate}}</span><div class=\"item item-pending item-tx item-icon-left\" ng-repeat=\"tx in formData.tx.pendings\" ng-init=\"pending=true;\" ng-include=\"\'templates/wallet/item_tx.html\'\"></div><span class=\"item item-divider\" ng-if=\"!loading\">{{:locale:\'ACCOUNT.LAST_TX\'|translate}} <a id=\"helptip-wallet-tx\" style=\"position: relative; bottom: 0; right: 0px\"> </a> </span><span class=\"item padding\" ng-if=\"!loading && !formData.tx.history.length\"><span class=\"gray\">{{:locale:\'ACCOUNT.NO_TX\'|translate}}</span></span><div ng-repeat=\"tx in formData.tx.history\" class=\"item item-tx item-icon-left\" ng-include=\"::!tx.isUD ? \'templates/wallet/item_tx.html\' : \'templates/wallet/item_ud.html\'\"></div><div class=\"item item-text-wrap text-center\" ng-if=\"formData.tx.fromTime > 0\"><p><a ng-click=\"showMoreTx()\">{{:locale:\'ACCOUNT.SHOW_MORE_TX\'|translate}}</a> <span class=\"gray\" translate=\"ACCOUNT.TX_FROM_DATE\" translate-values=\"{fromTime: formData.tx.fromTime}\"></span> <span class=\"gray\">|</span> <a ng-click=\"showMoreTx(-1)\" translate=\"\">ACCOUNT.SHOW_ALL_TX</a></p></div></div></div></div></ion-content><button id=\"fab-transfer\" ng-if=\"formData\" class=\"button button-fab button-fab-bottom-right button-energized-900 hidden-md hidden-lg drop\" ng-click=\"showTransferModal()\"><i class=\"icon ion-android-send\"></i></button></ion-view>"); -$templateCache.put("templates/wallet/view_wallet_tx_error.html","<ion-view left-buttons=\"leftButtons\" id=\"wallet\"><ion-nav-title></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-loop visible-xs visible-sm\" ng-click=\"doUpdate()\"></button></ion-nav-buttons><ion-content scroll=\"true\"><div class=\"row no-padding\"><div class=\"col list\" ng-class=\"::motion.ionListClass\"><span class=\"item item-divider\"><span translate=\"\">ACCOUNT.PENDING_TX_RECEIVED</span><div class=\"badge item-note\"><span ng-if=\"!$root.settings.useRelative\">({{$root.currency.name | abbreviate}})</span> <span ng-if=\"$root.settings.useRelative\">({{\'COMMON.UD\' | translate}}<sub>{{$root.currency.name | abbreviate}}</sub>)</span></div></span><span class=\"item\" ng-if=\"!formData.tx.errors.length\"><h3 translate=\"\">ACCOUNT.NO_TX</h3></span><div class=\"item item-pending item-tx item-icon-left\" ng-repeat=\"tx in formData.tx.errors | filter: filterReceivedTx\" ng-init=\"pending=true;\" ng-include=\"\'templates/wallet/item_tx.html\'\"></div><span class=\"item item-divider\"><span translate=\"\">ACCOUNT.ERROR_TX_SENT</span><div class=\"badge item-note\"><span ng-if=\"!$root.settings.useRelative\">({{$root.currency.name | abbreviate}})</span> <span ng-if=\"$root.settings.useRelative\">({{\'COMMON.UD\' | translate}}<sub>{{$root.currency.name | abbreviate}}</sub>)</span></div></span><span class=\"item\" ng-if=\"!formData.tx.errors.length\"><h3 translate=\"\">ACCOUNT.NO_TX</h3></span><div class=\"item item-pending item-tx item-icon-left\" ng-repeat=\"tx in formData.tx.errors | filter: filterSentTx\" ng-init=\"error=true;\" ng-include=\"\'templates/wallet/item_tx.html\'\"></div></div></div></ion-content></ion-view>"); -$templateCache.put("templates/wot/item_certification.html","<i class=\"item-image\" ng-if=\"!cert.avatar\" ng-class=\"{\'ion-card\': !cert.isMember, \'ion-person\': cert.isMember}\"></i> <i class=\"item-image avatar\" ng-if=\"cert.avatar\" style=\"background-image: url({{::cert.avatar.src}})\"></i> <span ng-if=\"cert.isMember\"><h3><i class=\"icon ion-clock\" ng-if=\"cert.pending\"></i> <span class=\"positive\">{{::cert.name||cert.uid}}</span></h3><h4 class=\"gray\"><i class=\"ion-key\"></i> {{::cert.pubkey | formatPubkey}} <span class=\"gray\">| {{::cert.time|formatDate}}</span> <span class=\"gray\" ng-if=\"$root.settings.expertMode\">| {{::cert.pending ? \'WOT.SIGNED_ON_BLOCK\' : \'WOT.WRITTEN_ON_BLOCK\' | translate:cert}}</span></h4></span><span ng-if=\"!cert.isMember\"><h3><i class=\"icon ion-clock\" ng-if=\"cert.pending\"></i> <span ng-if=\"cert.uid\" class=\"dark\">{{::cert.name||cert.uid}} </span><span ng-if=\"!cert.uid\" class=\"gray\"><i class=\"ion-key\"></i> {{::cert.pubkey | formatPubkey}}</span></h3><h5 class=\"assertive\">{{::\'WOT.NOT_MEMBER_PARENTHESIS\'|translate}}</h5><h4 class=\"gray\"><span ng-if=\"cert.uid\"><i class=\"ion-key\"></i> {{::cert.pubkey | formatPubkey}} </span><span class=\"gray\">| {{::cert.time|formatDate}}</span> <span class=\"gray\" ng-if=\"$root.settings.expertMode\">| {{::cert.pending ? \'WOT.SIGNED_ON_BLOCK\' : \'WOT.WRITTEN_ON_BLOCK\' | translate:cert}}</span></h4></span><div class=\"badge badge-stable\" ng-class=\"{\'badge-energized\': cert.willExpire}\" ng-if=\"cert.expiresIn\">{{::cert.expiresIn | formatDurationTo}}</div><div class=\"badge badge-assertive\" ng-if=\"!cert.expiresIn\">{{::\'WOT.EXPIRED\' | translate}}</div>"); -$templateCache.put("templates/wot/item_content_identity.html","<i ng-if=\"::!item.avatar\" class=\"item-image icon ion-person\"></i> <i ng-if=\"::item.avatar\" class=\"item-image avatar\" style=\"background-image: url({{::item.avatar.src}})\"></i><h2><ng-if ng-if=\"::item.name||item.uid\" ng-bind-html=\"::item.name||item.uid\"></ng-if><ng-if ng-if=\"::!item.name && !item.uid\">{{::item.pubkey|formatPubkey}}</ng-if></h2><h4 class=\"gray\" ng-class=\"{\'pull-right\': !smallscreen}\" ng-if=\"::item.sigDate\"><i class=\"ion-clock\"></i> {{::\'WOT.LOOKUP.REGISTERED\' | translate:item}}</h4><h4 class=\"gray\" ng-class=\"{\'pull-right\': !smallscreen}\" ng-if=\"item.memberDate\"><i class=\"ion-clock\"></i> {{::\'WOT.LOOKUP.MEMBER_FROM\' | translate:item}}</h4><h4 class=\"gray\"><span class=\"positive\" ng-if=\"::item.name && item.uid\"><i class=\"ion-person\"></i> {{::item.uid}} </span><b class=\"ion-key\"></b> {{::item.pubkey | formatPubkey}} <span ng-if=\"::!item.uid\" class=\"assertive\" translate>WOT.NOT_MEMBER_PARENTHESIS</span> <span ng-if=\"::item.revoked\" class=\"assertive\" translate>WOT.IDENTITY_REVOKED_PARENTHESIS</span></h4><h4 ng-if=\"::item.events||item.tags\"><span ng-repeat=\"event in ::item.events\" class=\"assertive\"><i class=\"ion-alert-circled\" ng-if=\"::!item.valid\"></i> <span ng-bind-html=\"::event.message|translate:event.messageParams\"></span> </span><span ng-if=\"::item.tags\" class=\"dark\"><ng-repeat ng-repeat=\"tag in ::item.tags\">#<ng-bind-html ng-bind-html=\"::tag\"></ng-bind-html></ng-repeat></span></h4>"); -$templateCache.put("templates/wot/items_given_certifications.html","<div class=\"list given-certifications\" ng-class=\"::motions.givenCertifications.ionListClass\"><span class=\"item item-divider hidden-xs\"><span translate>WOT.GIVEN_CERTIFICATIONS.SUMMARY</span></span><div id=\"helptip-certs-stock\" class=\"item item-icon-left item-text-wrap ink\"><i class=\"icon ion-ribbon-a\"></i> <span translate>WOT.GIVEN_CERTIFICATIONS.SENT</span><cs-badge-given-certification identity=\"formData\" parameters=\"$root.currency.parameters\"></cs-badge-given-certification></div><div class=\"item item-icon-left item-text-wrap ink\" ng-if=\"formData.given_cert_error.length\"><i class=\"icon ion-alert-circled\"></i> <span translate>WOT.GIVEN_CERTIFICATIONS.ERROR</span> <span class=\"badge badge-assertive\">{{formData.given_cert_error.length}}</span></div><span class=\"item item-divider\" ng-if=\"formData.given_cert_pending.length\"><span translate>WOT.GIVEN_CERTIFICATIONS.PENDING_LIST</span><div class=\"badge item-note\" style=\"text-align: right !important\" translate>WOT.NOT_WRITTEN_EXPIRE_IN</div></span><a class=\"item item-avatar ink\" ng-repeat=\"cert in formData.given_cert_pending\" ui-sref=\"app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})\" ng-include=\"\'templates/wot/item_certification.html\'\"></a><span class=\"item item-divider\"><span translate>WOT.GIVEN_CERTIFICATIONS.LIST</span><div class=\"badge item-note\" translate>WOT.EXPIRE_IN</div></span><span class=\"item gray\" ng-if=\"!formData.given_cert.length\" translate>WOT.NO_GIVEN_CERTIFICATION </span><a class=\"item item-avatar ink\" ng-repeat=\"cert in formData.given_cert\" ui-sref=\"app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})\" ng-include=\"\'templates/wot/item_certification.html\'\"></a></div>"); -$templateCache.put("templates/wot/items_received_certifications.html","<div class=\"list certifications\" ng-class=\"::motions.receivedCertifications.ionListClass\"><span class=\"item item-divider hidden-xs\"><span translate>WOT.CERTIFICATIONS.SUMMARY</span></span><div id=\"helptip-received-certs\" class=\"item item-icon-left item-text-wrap ink\"><i class=\"icon ion-ribbon-b\"></i> <b ng-if=\"formData.requirements.isSentry\" class=\"ion-star icon-secondary\" style=\"color: yellow; font-size: 16px; left: 25px; top: -7px\"></b> <span translate>WOT.CERTIFICATIONS.RECEIVED</span><h4 class=\"gray\" ng-if=\"formData.requirements.isSentry\" translate>WOT.CERTIFICATIONS.SENTRY_MEMBER</h4><cs-badge-certification cs-id=\"helptip-wot-view-certifications-count\" requirements=\"formData.requirements\" parameters=\"$root.currency.parameters\"></cs-badge-certification></div><div class=\"item item-icon-left item-text-wrap ink\" ng-if=\"formData.received_cert_error.length\"><i class=\"icon ion-alert-circled\"></i> <span translate>WOT.CERTIFICATIONS.ERROR</span> <span class=\"badge badge-assertive\">{{formData.received_cert_error.length}}</span></div><span class=\"item item-divider\" ng-if=\"formData.received_cert_pending.length\"><span translate>WOT.CERTIFICATIONS.PENDING_LIST</span><div class=\"badge item-note\" style=\"text-align: right !important\" translate>WOT.NOT_WRITTEN_EXPIRE_IN</div></span><a class=\"item item-avatar ink\" ng-repeat=\"cert in formData.received_cert_pending\" ui-sref=\"app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})\" ng-include=\"\'templates/wot/item_certification.html\'\"></a><span class=\"item item-divider\"><span translate>WOT.CERTIFICATIONS.LIST</span><div class=\"badge item-note\" translate>WOT.EXPIRE_IN</div></span><span class=\"item gray\" ng-if=\"!formData.received_cert.length\" translate>WOT.NO_CERTIFICATION</span> <a class=\"item item-avatar ink\" ng-repeat=\"cert in formData.received_cert\" ui-sref=\"app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})\" ng-include=\"\'templates/wot/item_certification.html\'\"></a></div>"); -$templateCache.put("templates/wot/lookup.html","<ion-view left-buttons=\"leftButtons\"><ion-tabs class=\"tabs-positive tabs-icon-top\"><ion-tab title=\"{{\'WOT.LOOKUP.TITLE\'|translate}}\" icon=\"ion-person-stalker\" ui-sref=\"app.wot_lookup.tab_search\"><ion-nav-view name=\"tab\"></ion-nav-view></ion-tab><cs-extension-point name=\"tabs\"></cs-extension-point></ion-tabs></ion-view>"); -$templateCache.put("templates/wot/lookup_form.html","<div class=\"lookupForm\"><div class=\"item no-padding\"><div class=\"double-padding-x padding-top-xs item-text-wrap\" ng-if=\"::allowMultiple\" style=\"height: 36px\"><div class=\"gray padding-top\" ng-if=\"!selection.length && parameters.help\">{{::parameters.help|translate}}</div><div ng-repeat=\"identity in selection track by identity.id\" class=\"button button-small button-text button-stable button-icon-event ink\" ng-class=\"{\'button-text-positive\': identity.selected}\"><span ng-bind-html=\"identity.name||identity.uid||(identity.pubkey|formatPubkey)\"></span> <i class=\"icon ion-close\" ng-click=\"removeSelection(identity, $event)\"> </i></div></div><div class=\"item-input\"><i class=\"icon ion-search placeholder-icon\"></i> <input type=\"text\" class=\"visible-xs visible-sm\" placeholder=\"{{\'WOT.SEARCH_HELP\'|translate}}\" ng-model=\"search.text\" ng-model-options=\"{ debounce: 650 }\" ng-change=\"doSearch()\" on-return=\"doSearchText()\" select-on-click=\"\"><div class=\"helptip-anchor-center\"><a id=\"helptip-wot-search-text\"></a></div></div></div><div class=\"padding-top padding-xs\" style=\"display: block; height: 60px\" ng-class=\"::{\'hidden-xs\': !showResultLabel}\"><div class=\"pull-left\" ng-if=\"!search.loading && showResultLabel\"><ng-if ng-if=\"search.type==\'newcomers\'\"><h4 translate=\"\">WOT.LOOKUP.NEWCOMERS</h4><small class=\"gray no-padding\" ng-if=\"search.total\">{{\'WOT.LOOKUP.NEWCOMERS_COUNT\'|translate:{count: search.total} }}</small></ng-if><ng-if ng-if=\"search.type==\'pending\'\"><h4 translate=\"\">WOT.LOOKUP.PENDING</h4><small class=\"gray no-padding\" ng-if=\"search.total\">{{\'WOT.LOOKUP.PENDING_COUNT\'|translate:{count: search.total} }}</small></ng-if><h4 ng-if=\"search.type==\'text\'\"><span translate=\"\">COMMON.RESULTS_LIST</span> <small class=\"gray\" ng-if=\"search.total\">({{search.total}})</small></h4></div></div><div class=\"text-center\" ng-if=\"search.loading\"><p class=\"gray\" ng-if=\"::$root.currency.initPhase\" translate=\"\">WOT.SEARCH_INIT_PHASE_WARNING</p><ion-spinner icon=\"android\"></ion-spinner></div><ng-if ng-if=\"!search.loading\"><div class=\"assertive padding\" ng-if=\"!search.results.length\"><span ng-if=\"search.type==\'text\'\" translate=\"\">COMMON.SEARCH_NO_RESULT</span> <span ng-if=\"search.type==\'pending\'\" translate=\"\">WOT.LOOKUP.NO_PENDING</span> <span ng-if=\"search.type==\'newcomers\'\" translate=\"\">WOT.LOOKUP.NO_NEWCOMERS</span></div><ion-list ng-if=\"::!allowMultiple && $root.device.enable\" class=\"{{::motion.ionListClass}}\" can-swipe=\"true\"><ng-repeat ng-repeat=\"item in search.results track by item.id\"><div ng-if=\"::item.divider\" class=\"item item-divider\" id=\"helptip-wot-search-result-{{$index}}\">{{::(\'WOT.SEARCH.DIVIDER_\' + item.index)|upper|translate}}</div><ion-item ng-if=\"::!item.divider\" id=\"helptip-wot-search-result-{{$index}}\" class=\"item item-border-large item-avatar item-icon-right ink\" ng-click=\"::select(item)\"><ng-include src=\"item.templateUrl || \'templates/wot/item_content_identity.html\'\"></ng-include><i class=\"icon ion-ios-arrow-right\"></i><ion-option-button class=\"button-positive\" ng-click=\"showTransferModal({pubkey: item.pubkey, uid: item.name ||item.uid})\" translate=\"\">COMMON.BTN_SEND_MONEY_SHORT</ion-option-button></ion-item></ng-repeat></ion-list><div ng-if=\"::allowMultiple\" class=\"list {{::motion.ionListClass}}\"><ion-checkbox ng-repeat=\"item in search.results track by item.id\" ng-model=\"item.checked\" class=\"item item-border-large item-avatar ink\" ng-click=\"toggleCheck($index, $event)\"><ng-include src=\"\'templates/wot/item_content_identity.html\'\"></ng-include></ion-checkbox></div><ion-infinite-scroll ng-if=\"search.hasMore\" spinner=\"android\" on-infinite=\"showMore()\" distance=\"20%\"></ion-infinite-scroll></ng-if></div>"); -$templateCache.put("templates/wot/lookup_lg.html","<ion-view><ion-nav-title>{{\'MENU.WOT\' | translate}}</ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-qr-scanner hidden-no-device\" ng-if=\"$root.device.barcode.enable\" ng-click=\"scanQrCode()\"></button> <button class=\"button button-icon button-clear visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"><i class=\"icon ion-android-funnel\"></i></button></ion-nav-buttons><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><cs-extension-point name=\"top\"></cs-extension-point><ng-include src=\"\'templates/wot/lookup_form.html\'\"></ng-include></ion-content></ion-view>"); -$templateCache.put("templates/wot/lookup_popover_actions.html","<ion-popover-view class=\"fit has-header visible-sm visible-xs\"><ion-header-bar><h1 class=\"title\" translate>COMMON.POPOVER_FILTER_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink\" ng-click=\"doGetNewcomers()\"><i class=\"icon ion-person\"></i> {{\'WOT.LOOKUP.BTN_NEWCOMERS\' | translate}} </a><a class=\"item item-icon-left ink\" ng-click=\"doGetPending()\"><i class=\"icon ion-clock\"></i> {{\'WOT.LOOKUP.BTN_PENDING\' | translate}}</a></div></ion-content></ion-popover-view>"); -$templateCache.put("templates/wot/modal_lookup.html","<ion-modal-view id=\"wotLookup\" class=\"modal-full-height\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title hidden-xs\">{{::parameters.title?parameters.title:\'WOT.MODAL.TITLE\'|translate}}</h1><button class=\"button button-clear icon-right visible-xs ink\" ng-if=\"allowMultiple && selection.length\" ng-click=\"closeModal(selection)\">{{::parameters.okText||\'COMMON.BTN_NEXT\' | translate}} <i ng-if=\"::!parameters.okText||parameters.okIcon\" class=\"icon {{::parameters.okIcon||\'ion-ios-arrow-right\'}}\"></i></button></ion-header-bar><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><div class=\"visible-xs visible-sm text-right stable-bg stable\"><button class=\"button button-icon button-small-padding dark hidden-no-device ink\" ng-if=\"$root.device.barcode.enable\" ng-click=\"scanQrCode()\"><i class=\"icon ion-qr-scanner\"></i></button> <button class=\"button button-icon button-small-padding dark ink\" ng-click=\"showActionsPopover($event)\"><i class=\"icon ion-android-funnel\"></i></button></div><ng-include src=\"\'templates/wot/lookup_form.html\'\"></ng-include></ion-content></ion-modal-view>"); -$templateCache.put("templates/wot/modal_select_pubkey_identity.html","<ion-modal-view id=\"transfer\" class=\"modal-full-height modal-transfer\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title\" translate>ACCOUNT.SELECT_IDENTITY_MODAL.TITLE</h1></ion-header-bar><ion-content scroll=\"true\"><div class=\"padding\"><p trust-as-html=\"\'ACCOUNT.SELECT_IDENTITY_MODAL.HELP\'|translate:{pubkey: pubkey}\"></p></div><ion-list><ion-item class=\"item-avatar item-icon-right\" ng-repeat=\"item in identities\" ng-click=\"closeModal(item)\"><i class=\"item-image icon ion-person\"></i><h2>{{item.uid}}</h2><h4 class=\"gray\"><b class=\"ion-key\"></b> {{::item.pubkey | formatPubkey}} <span ng-if=\"::!item.revoked && !item.pendingRevocation && !item.isMember\" class=\"assertive\" translate>WOT.NOT_MEMBER_PARENTHESIS</span> <span ng-if=\"::item.revoked || item.pendingRevocation\" class=\"assertive bold\" translate>WOT.IDENTITY_REVOKED_PARENTHESIS</span></h4><ng-if ng-if=\"::!item.revoked && !item.pendingRevocation && (item.certificationCount || item.pendingCertificationCount)\"><cs-badge-certification requirements=\"item\" parameters=\"$root.currency.parameters\"></cs-badge-certification><div class=\"gray badge badge-secondary\"><span translate>ACCOUNT.CERTIFICATION_COUNT</span></div></ng-if><i class=\"icon ion-ios-arrow-right\"></i></ion-item></ion-list></ion-content></ion-modal-view>"); -$templateCache.put("templates/wot/view_certifications.html","<ion-view left-buttons=\"leftButtons\"><ion-nav-title><span class=\"visible-xs visible-sm\">{{::formData.name||formData.uid}}</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><cs-extension-point name=\"nav-buttons\"></cs-extension-point></ion-nav-buttons><ion-content class=\"certifications certifications-lg\"><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"doUpdate()\"></ion-refresher><div class=\"center padding\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></div><div class=\"row responsive-sm responsive-md responsive-lg\"><div class=\"col no-padding\" ng-if=\"motions.receivedCertifications.enable\"><ng-include src=\"\'templates/wot/items_received_certifications.html\'\"></ng-include></div><div class=\"col no-padding\" ng-if=\"motions.givenCertifications.enable\"><ng-include src=\"\'templates/wot/items_given_certifications.html\'\"></ng-include></div></div></ion-content><div class=\"visible-xs visible-sm\"><button id=\"fab-certify\" class=\"button button-fab button-fab-bottom-right button-energized-900 spin\" ng-if=\"canCertify && !alreadyCertified\" ng-click=\"certify()\"><i class=\"icon ion-ribbon-b\"></i></button> <button id=\"fab-select-certify\" class=\"button button-fab button-fab-bottom-right button-energized-900 spin\" ng-if=\"canSelectAndCertify\" ng-click=\"selectAndCertify()\"><i class=\"icon ion-plus\"></i></button></div></ion-view>"); -$templateCache.put("templates/wot/view_identity.html","<ion-view left-buttons=\"leftButtons\" class=\"view-identity\"><ion-nav-title></ion-nav-title><ion-content scroll=\"true\" class=\"refresher-top-bg\" ng-class=\"{\'member\': !loading && formData.isMember}\"><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"doUpdate(true)\"></ion-refresher><div class=\"hero\"><div class=\"content\" ng-if=\"!loading\"><i class=\"avatar\" ng-if=\"::!formData.avatar\" ng-class=\"{\'avatar-wallet\': !formData.isMember, \'avatar-member\': formData.isMember}\"></i> <i class=\"avatar\" ng-if=\"::formData.avatar\" style=\"background-image: url({{::formData.avatar.src}})\"></i><ng-if ng-if=\"::formData.name\"><h3 class=\"light\">{{::formData.name}}</h3></ng-if><ng-if ng-if=\"::!formData.name\"><h3 class=\"light\" ng-if=\"::formData.uid\">{{::formData.uid}}</h3><h3 class=\"light\" ng-if=\"::!formData.uid\"><i class=\"ion-key\"></i> {{::formData.pubkey | formatPubkey}}</h3></ng-if><h4 class=\"assertive\"><ng-if ng-if=\"::(formData.name || formData.uid) && !formData.isMember && revoked\" translate=\"\">WOT.IDENTITY_REVOKED_PARENTHESIS</ng-if><ng-if ng-if=\"::(formData.name || formData.uid) && formData.isMember && revoked\" translate=\"\">WOT.MEMBER_PENDING_REVOCATION_PARENTHESIS</ng-if></h4></div><h4 class=\"content light\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></h4></div><a id=\"wot-share-anchor-{{::formData.pubkey}}\"></a><div class=\"row no-padding\"><div class=\"visible-xs visible-sm\"><button id=\"fab-certify-{{:rebind:formData.uid}}\" style=\"top: 170px\" class=\"button button-fab button-fab-top-left button-fab-hero button-calm spin\" ng-if=\":rebind:(canCertify && !alreadyCertified)\" ng-click=\"certify()\"><i class=\"icon ion-ribbon-b\"></i></button></div><div class=\"col list\" ng-class=\"::motion.ionListClass\" bind-notifier=\"{ rebind:loading}\"><span class=\"item item-divider\" translate=\"\">WOT.GENERAL_DIVIDER</span><ion-item class=\"item-icon-left item-text-wrap ink\" copy-on-click=\"{{:rebind:formData.pubkey}}\"><i class=\"icon ion-key\"></i> <span translate=\"\">COMMON.PUBKEY</span><h4 id=\"pubkey\" class=\"dark text-left\">{{:rebind:formData.pubkey}}</h4></ion-item><div class=\"item item-icon-left item-text-wrap\" ng-if=\":rebind:!formData.hasSelf\"><i class=\"icon ion-ios-help-outline positive\"></i> <span translate=\"\">WOT.NOT_MEMBER_ACCOUNT</span><h4 class=\"gray\" translate=\"\">WOT.NOT_MEMBER_ACCOUNT_HELP</h4></div><ion-item class=\"item-icon-left\" ng-if=\":rebind:formData.sigDate||formData.uid\"><i class=\"icon ion-calendar\"></i> <span translate=\"\">COMMON.UID</span><h5 class=\"dark\" ng-if=\":rebind:formData.sigDate\"><span translate=\"\">WOT.REGISTERED_SINCE</span> {{:rebind:formData.sigDate | formatDate}}</h5><span class=\"badge badge-stable\">{{:rebind:formData.uid}}</span></ion-item><a id=\"helptip-wot-view-certifications\" class=\"item item-icon-left item-text-wrap item-icon-right ink\" ng-if=\":rebind:formData.hasSelf\" ng-click=\"showCertifications()\"><i class=\"icon ion-ribbon-b\"></i> <b ng-if=\":rebind:formData.requirements.isSentry\" class=\"ion-star icon-secondary\" style=\"color: yellow; font-size: 16px; left: 25px; top: -7px\"></b> <span translate=\"\">ACCOUNT.CERTIFICATION_COUNT</span><cs-badge-certification cs-id=\"helptip-wot-view-certifications-count\" requirements=\"formData.requirements\" parameters=\"{sigQty: formData.sigQty}\"></cs-badge-certification><i class=\"gray icon ion-ios-arrow-right\"></i> </a><a class=\"item item-icon-left item-text-wrap item-icon-right ink visible-xs visible-sm\" ng-if=\":rebind:formData.hasSelf && formData.isMember\" ng-click=\"showGivenCertifications()\"><i class=\"icon ion-ribbon-a\"></i> <span translate=\"\">WOT.GIVEN_CERTIFICATIONS.SENT</span><cs-badge-given-certification identity=\"formData\" parameters=\"{sigStock: formData.sigStock}\"></cs-badge-given-certification><i class=\"gray icon ion-ios-arrow-right\"></i> </a><a class=\"item item-icon-left item-icon-right ink\" ng-if=\"!loading\" ui-sref=\"app.wot_identity_tx_uid({uid:formData.uid,pubkey:formData.pubkey})\"><i class=\"icon ion-card\"></i> <span translate=\"\">WOT.ACCOUNT_OPERATIONS</span> <i class=\"gray icon ion-ios-arrow-right\"></i></a><div class=\"item item-text-wrap item-icon-left item-wallet-event assertive\" ng-repeat=\"event in :rebind:formData.events | filter: {type: \'error\'}\"><i class=\"icon ion-alert-circled\"></i> <span trust-as-html=\"event.message | translate:event.messageParams\"></span></div><cs-extension-point name=\"general\"></cs-extension-point><cs-extension-point name=\"after-general\"></cs-extension-point></div></div></ion-content><div class=\"visible-xs visible-sm\" ng-hide=\"loading\"><button id=\"fab-transfer\" class=\"button button-fab button-fab-bottom-right button-assertive drop\" ng-click=\"showTransferModal({pubkey:formData.pubkey, uid: formData.uid})\"><i class=\"icon ion-android-send\"></i></button></div></ion-view>"); -$templateCache.put("templates/wot/view_identity_tx.html","<ion-view left-buttons=\"leftButtons\"><ion-nav-title><span class=\"visible-xs visible-sm\">{{::formData.name||formData.uid}}</span></ion-nav-title><ion-content scroll=\"true\"><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"doUpdate(true)\"></ion-refresher><div class=\"center padding\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></div><div class=\"list {{motion.ionListClass}}\" ng-if=\"!loading\"><div class=\"row\"><div class=\"col\"><div class=\"item item-tx item-divider\">{{\'ACCOUNT.BALANCE_ACCOUNT\'|translate}}<div class=\"badge item-note badge-balanced\" ng-bind-html=\":balance:formData.balance|formatAmount:{currency: $root.currency.name}\"></div><div class=\"badge badge-secondary\" ng-if=\"$root.settings.expertMode\">(<span ng-bind-html=\":balance:formData.balance| formatAmount: {useRelative: !$root.settings.useRelative, currency: $root.currency.name} \"></span>)</div></div><span class=\"item item-divider\" ng-if=\"!loading\">{{:locale:\'ACCOUNT.LAST_TX\'|translate}} <a id=\"helptip-wallet-tx\" style=\"position: relative; bottom: 0; right: 0px\"> </a></span><div ng-repeat=\"tx in formData.tx.history\" class=\"item item-tx item-icon-left\" ng-include=\"::!tx.isUD ? \'templates/wallet/item_tx.html\' : \'templates/wallet/item_ud.html\'\"></div><div class=\"item item-text-wrap text-center\" ng-if=\"formData.tx.fromTime > 0\"><p><a ng-click=\"showMoreTx()\">{{:locale:\'ACCOUNT.SHOW_MORE_TX\'|translate}}</a> <span class=\"gray\" translate=\"ACCOUNT.TX_FROM_DATE\" translate-values=\"{fromTime: tx.fromTime}\"></span> <span class=\"gray\">|</span> <a ng-click=\"showMoreTx(-1)\" translate=\"\">ACCOUNT.SHOW_ALL_TX</a></p></div></div></div></div></ion-content></ion-view>"); -$templateCache.put("templates/currency/tabs/tab_blocks.html","<ion-view><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-navicon visible-xs visible-sm\" ng-click=\"toggleCompactMode()\"><b class=\"icon-secondary\" ng-class=\"{\'ion-arrow-down-b\': !compactMode, \'ion-arrow-up-b\': compactMode}\" style=\"top: -12px; left: 11px; font-size: 10px\"></b> <b class=\"icon-secondary\" ng-class=\"{\'ion-arrow-up-b\': !compactMode,\'ion-arrow-down-b\': compactMode}\" style=\"top: 12px; left: 11px; font-size: 10px\"></b></button><cs-extension-point name=\"nav-buttons\"></cs-extension-point></ion-nav-buttons><ion-content><div class=\"item item-divider\"><span translate>BLOCKCHAIN.LOOKUP.LAST_BLOCKS</span></div><cs-extension-point name=\"buttons\"></cs-extension-point><ng-include src=\"\'templates/blockchain/list_blocks.html\'\"></ng-include></ion-content></ion-view>"); -$templateCache.put("templates/currency/tabs/tab_network.html","<ion-view><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear\" ng-click=\"showExtendActionsPopover($event)\"><i class=\"icon ion-android-funnel\"></i></button></ion-nav-buttons><ion-content><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"refreshPeers()\"></ion-refresher><div class=\"list\"><ng-include src=\"\'templates/currency/items_network.html\'\"></ng-include></div></ion-content></ion-view>"); -$templateCache.put("templates/currency/tabs/tab_parameters.html","<ion-view><ion-nav-buttons side=\"secondary\"><cs-extension-point name=\"nav-buttons\"></cs-extension-point></ion-nav-buttons><ion-content><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"refresh()\"></ion-refresher><div class=\"list\"><ng-include src=\"\'templates/currency/items_parameters.html\'\"></ng-include></div></ion-content></ion-view>"); -$templateCache.put("templates/currency/tabs/tab_wot.html","<ion-view><ion-content><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"refresh()\"></ion-refresher><div class=\"list\"><ng-include src=\"\'templates/currency/items_wot.html\'\"></ng-include></div></ion-content></ion-view>"); -$templateCache.put("templates/wallet/slides/slides_generate_keyfile.html","<ion-content class=\"has-header padding\"><h3 translate>ACCOUNT.SECURITY.GENERATE_KEYFILE</h3><div class=\"list\"><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"downloadKeyFile(\'PubSec\')\"><div class=\"item-content item-text-wrap\"><i class=\"item-image dark icon ion-document-text\"></i> <b class=\"ion-ios-redo icon-secondary dark\" style=\"top: -8px; left: 42px; font-size: 12px\"></b><h2 translate>ACCOUNT.SECURITY.KEYFILE.PUBSEC_FORMAT</h2><h4 class=\"gray\" translate>ACCOUNT.SECURITY.KEYFILE.PUBSEC_FORMAT_HELP</h4><i class=\"icon dark ion-ios-arrow-right\"></i></div></div><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"downloadKeyFile(\'WIF\')\"><div class=\"item-content item-text-wrap\"><i class=\"item-image dark icon ion-document-text\"></i> <b class=\"ion-ios-redo icon-secondary dark\" style=\"top: -8px; left: 42px; font-size: 12px\"></b><h2 translate>ACCOUNT.SECURITY.KEYFILE.WIF_FORMAT</h2><h4 class=\"gray\" translate>ACCOUNT.SECURITY.KEYFILE.WIF_FORMAT_HELP</h4><i class=\"icon dark ion-ios-arrow-right\"></i></div></div><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-click=\"downloadKeyFile(\'EWIF\')\"><div class=\"item-content item-text-wrap\"><i class=\"item-image dark icon ion-document-text\"></i> <b class=\"ion-ios-redo icon-secondary dark\" style=\"top: -8px; left: 42px; font-size: 12px\"></b> <b class=\"ion-locked icon-secondary dark\" style=\"top: 0px; left: 43px; font-size: 8px\"></b><h2 translate>ACCOUNT.SECURITY.KEYFILE.EWIF_FORMAT</h2><h4 class=\"gray\" translate>ACCOUNT.SECURITY.KEYFILE.EWIF_FORMAT_HELP</h4><i class=\"icon dark ion-ios-arrow-right\"></i></div></div></div></ion-content>"); -$templateCache.put("templates/wallet/slides/slides_recoverID_1.html","<ion-content class=\"has-header padding\"><h3 translate>ACCOUNT.SECURITY.RECOVER_ID</h3><div dropzone=\"recoverContent(file)\"><div ng-if=\"!hasContent\" onclick=\"angular.element(document.querySelector(\'#saveIdFile\'))[0].click();\"><h2 class=\"gray\" translate>COMMON.CHOOSE_FILE</h2><input type=\"file\" id=\"saveIdFile\" accept=\".txt\" style=\"visibility:hidden; position:absolute\" on-read-file=\"recoverContent(file)\"></div><div ng-if=\"hasContent\" class=\"item row item-icon-left no-padding\"><i class=\"icon ion-document-text gray\"></i><div class=\"col\"><span>{{fileData.name}}</span><br><small>{{fileData.size}} Ko</small></div><div class=\"col-10\"><b ng-class=\"{\'ion-android-done balanced\': isValidFile,\'ion-close-circled assertive\': !isValidFile}\" style=\"font-size: 28px; position: relative; top: 6px\"></b> <button class=\"button-icon ion-close-round gray pull-right\" style=\"font-size:10px\" ng-click=\"restore()\"></button></div></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-calm icon-right ion-chevron-right ink\" ng-click=\"doNext()\" translate>COMMON.BTN_NEXT <i class=\"icon ion-arrow-right-a\"></i></button></div></ion-content>"); -$templateCache.put("templates/wallet/slides/slides_recoverID_2.html","<ion-content class=\"has-header padding\"><h3 translate>ACCOUNT.SECURITY.RECOVER_ID</h3><form name=\"recoverForm\" novalidate ng-submit=\"recoverId()\"><div class=\"list\" ng-init=\"setForm(recoverForm, \'recoverForm\')\"><ng-repeat ng-repeat=\"question in recover.questions \"><label class=\"item item-input {{smallscreen ? \'item-stacked-label\' : \'item-floating-label\'}}\" ng-class=\"{\'item-input-error\': recoverForm.$submitted && recoverForm[\'question{{$index}}\'].$invalid}\"><span class=\"input-label\" style=\"{{smallscreen ? \'white-space: normal\' : \'\'}}\">{{question.value }}</span> <input type=\"text\" name=\"question{{$index}}\" placeholder=\"{{smallscreen ? \'\' : question.value }}\" ng-model=\"question.answer\" required></label><div class=\"form-errors\" ng-show=\"recoverForm.$submitted && recoverForm[\'question{{$index}}\'].$error\" ng-messages=\"recoverForm[\'question{{$index}}\'].$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div></ng-repeat><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-clear button-dark\" ng-click=\"restore()\" type=\"button\" translate>ACCOUNT.SECURITY.BTN_CLEAN</button> <button class=\"button button-calm icon-right ion-chevron-right ink\" type=\"submit\" translate>COMMON.BTN_NEXT <i class=\"icon ion-arrow-right-a\"></i></button></div></div></form></ion-content>"); -$templateCache.put("templates/wallet/slides/slides_recoverID_3.html","<ion-content class=\"has-header padding\"><h3 translate>ACCOUNT.SECURITY.RECOVER_ID</h3><div class=\"item item-input\"><span class=\"input-label\">{{\'LOGIN.SALT\' | translate}} :</span> <span>{{recover.salt}}</span></div><div class=\"item item-input\"><span class=\"input-label\">{{\'LOGIN.PASSWORD\' | translate}} :</span> <span>{{recover.pwd}}</span></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CLOSE</button></div></ion-content>"); -$templateCache.put("templates/wallet/slides/slides_revocation_file.html","<ion-content class=\"has-header padding\"><p translate>ACCOUNT.SECURITY.REVOCATION_WITH_FILE_HELP</p><div dropzone=\"recoverContent(file)\"><div ng-if=\"!hasContent\" onclick=\"angular.element(document.querySelector(\'#revocationFile\'))[0].click();\"><h2 class=\"gray\" translate>COMMON.CHOOSE_FILE</h2><input type=\"file\" id=\"revocationFile\" accept=\".txt\" style=\"visibility:hidden; position:absolute\" on-read-file=\"recoverContent(file)\"></div><div ng-if=\"hasContent\" class=\"item row item-icon-left no-padding\"><i class=\"icon ion-document-text gray\"></i><div class=\"col\"><span>{{fileData.name}}</span><br><small>{{fileData.size}} Ko</small></div><div class=\"col-10\"><b ng-class=\"{\'ion-android-done balanced\': isValidFile,\'ion-close-circled assertive\': !isValidFile}\" style=\"font-size: 28px; position: relative; top: 6px\"></b> <button class=\"button-icon ion-close-round gray pull-right\" style=\"font-size:10px\" ng-click=\"restore()\"></button></div></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-calm icon-right ion-chevron-right ink\" ng-click=\"revokeWithFile()\" translate>COMMON.BTN_NEXT <i class=\"icon ion-arrow-right-a\"></i></button></div></ion-content>"); -$templateCache.put("templates/wallet/slides/slides_saveID_1.html","<ion-content class=\"has-header padding\"><h3 translate>ACCOUNT.SECURITY.SAVE_ID</h3><label class=\"item item-input item-select\"><div class=\"input-label\" translate>ACCOUNT.SECURITY.LEVEL</div><select ng-model=\"formData.level\"><option value=\"2\" ng-bind-html=\"\'ACCOUNT.SECURITY.LOW_LEVEL\' | translate\"></option><option value=\"4\" translate>ACCOUNT.SECURITY.MEDIUM_LEVEL</option><option value=\"6\" translate>ACCOUNT.SECURITY.STRONG_LEVEL</option></select></label><div class=\"padding-top\" translate=\"ACCOUNT.SECURITY.HELP_LEVEL\" translate-values=\"{nb: {{formData.level}}}\"></div><form name=\"questionsForm\" novalidate ng-submit=\"doNext(\'questionsForm\')\"><div class=\"list\" ng-init=\"setForm(questionsForm, \'questionsForm\')\"><ion-checkbox ng-repeat=\"question in formData.questions\" ng-model=\"question.checked\" ng-required=\"isRequired()\"><span style=\"white-space: normal\">{{question.value | translate}}</span></ion-checkbox><div class=\"item item-icon-right no-padding-top\"><a class=\"dark\"><i class=\"icon ion-android-add\" ng-click=\"addQuestion()\"></i></a><div class=\"list list-inset\"><label class=\"item item-input\"><input type=\"text\" placeholder=\"{{\'ACCOUNT.SECURITY.ADD_QUESTION\' | translate}}\" ng-model=\"formData.addQuestion\"></label></div></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-clear button-dark\" ng-click=\"restore()\" type=\"button\" translate>ACCOUNT.SECURITY.BTN_RESET</button> <button class=\"button button-calm icon-right ion-chevron-right ink\" ng-disabled=\"questionsForm.$invalid\" type=\"submit\" translate>COMMON.BTN_NEXT <i class=\"icon ion-arrow-right-a\"></i></button></div></form></ion-content>"); -$templateCache.put("templates/wallet/slides/slides_saveID_2.html","<ion-content class=\"has-header padding\"><h3 translate>ACCOUNT.SECURITY.SAVE_ID</h3><form name=\"answersForm\" novalidate ng-submit=\"doNext(\'answersForm\')\"><div class=\"list\" ng-init=\"setForm(answersForm, \'answersForm\')\"><ng-repeat ng-repeat=\"question in formData.questions |filter:true:checked\"><label class=\"item item-input item-text-wrap {{smallscreen ? \'item-stacked-label\' : \'item-floating-label\'}}\" ng-class=\"{\'item-input-error\': answersForm.$submitted && answersForm[\'question{{$index}}\'].$invalid}\"><span class=\"input-label\" style=\"width: 100%; max-width: inherit\">{{question.value | translate}}</span> <input type=\"text\" name=\"question{{$index}}\" placeholder=\"{{smallscreen ? \'\' : question.value | translate}}\" ng-model=\"question.answer\" required></label><div class=\"form-errors\" ng-show=\"answersForm.$submitted && answersForm[\'question{{$index}}\'].$error\" ng-messages=\"answersForm[\'question{{$index}}\'].$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div></ng-repeat><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-clear button-dark\" ng-click=\"restore()\" type=\"button\" translate>ACCOUNT.SECURITY.BTN_CLEAN</button> <button class=\"button button-positive ink\" type=\"submit\" translate>COMMON.BTN_CONTINUE <i class=\"icon ion-android-archive\"></i></button></div></div></form></ion-content>"); -$templateCache.put("templates/wot/tabs/tab_given_certifications.html","<ion-view><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-loop\" ng-click=\"doUpdate()\"></button></ion-nav-buttons><ion-content ng-init=\"motions.receivedCertifications=false; motions.avatar=false\"><div class=\"center padding\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></div><ng-include src=\"\'templates/wot/items_given_certifications.html\'\"></ng-include></ion-content><div class=\"visible-xs visible-sm\"><button id=\"fab-select-certify\" class=\"button button-fab button-fab-bottom-right button-energized-900 spin\" ng-if=\"canSelectAndCertify || $root.tour\" ng-click=\"selectAndCertify()\"><i class=\"icon ion-plus\"></i></button></div></ion-view>"); -$templateCache.put("templates/wot/tabs/tab_lookup.html","<ion-view><ion-nav-buttons side=\"secondary\"><cs-extension-point name=\"nav-buttons\"></cs-extension-point><button class=\"button button-icon button-clear\" ng-click=\"showActionsPopover($event)\"><i class=\"icon ion-android-funnel\"></i></button></ion-nav-buttons><ion-content><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"doSearch()\"></ion-refresher><cs-extension-point name=\"buttons\"></cs-extension-point><ng-include src=\"\'templates/wot/lookup_form.html\'\"></ng-include></ion-content></ion-view>"); -$templateCache.put("templates/wot/tabs/tab_received_certifications.html","<ion-view><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-loop\" ng-click=\"doUpdate()\"></button></ion-nav-buttons><ion-content ng-init=\"motions.givenCertifications=false; motions.avatar=false;\" class=\"has-header\"><div class=\"center padding\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></div><ng-include src=\"\'templates/wot/items_received_certifications.html\'\"></ng-include></ion-content><div class=\"visible-xs visible-sm\"><button id=\"fab-certify\" class=\"button button-fab button-fab-bottom-right button-energized-900 spin\" ng-click=\"certify()\" ng-if=\"(formData.hasSelf && canCertify && !alreadyCertified) || $root.tour\"><i class=\"icon ion-ribbon-b\"></i></button></div></ion-view>");}]); \ No newline at end of file +angular.module('cesium.templates', []).run(['$templateCache', function($templateCache) {$templateCache.put('templates/menu.html','<ion-side-menus enable-menu-with-back-views="true" bind-notifier="{locale:$root.settings.locale.id}"><ion-side-menu-content><ion-nav-bar class="bar-dark" title-align="left"><ion-nav-back-button class="no-text"></ion-nav-back-button><ion-nav-buttons side="left"><button class="button button-icon button-clear icon ion-navicon visible-nomenu" menu-toggle="left"></button></ion-nav-buttons><ion-nav-buttons side="right"><cs-extension-point name="nav-buttons-right"></cs-extension-point></ion-nav-buttons></ion-nav-bar><ion-nav-view name="menuContent"></ion-nav-view></ion-side-menu-content><ion-side-menu id="menu" side="left" expose-aside-when="large" enable-menu-with-back-views="false" width="225"><ion-header-bar class="bar-title"><div class="visible-sm visible-xs hero"><div class="content"><i class="avatar avatar-member hero-icon" ng-if="!walletData.avatar" ng-class="{\'royal-bg\': login, \'stable-bg\': !login}" ng-click="!login ? showHome() : loginAndGo()" menu-close=""></i> <a class="avatar hero-icon" ng-if="walletData.avatar" style="background-image: url(\'{{walletData.avatar.src}}\')" ui-sref="app.view_wallet" menu-close=""></a><h4 ng-if="login"><a class="light" ui-sref="app.view_wallet" menu-close="">{{walletData.name||walletData.uid}} <span ng-if="!walletData.name && !walletData.uid"><i class="icon ion-key"></i> {{walletData.pubkey|formatPubkey}}</span></a></h4><h4 ng-if="!login"><a class="light" ui-sref="app.login" menu-close="">{{\'COMMON.BTN_LOGIN\'|translate}} <i class="ion-arrow-right-b"></i></a></h4><cs-extension-point name="menu-profile-user"></cs-extension-point></div><a ng-if="login" class="button-icon" ng-click="logout({askConfirm: true})" style="position: absolute; top: 5px; left: 5px; z-index: 999"><i class="icon light ion-android-exit"></i></a></div></ion-header-bar><ion-content scroll="false" class="scroll-content ionic-scroll" ng-class="{\'overflow-scroll\': smallscreen, \'scroll-content-false\': !smallscreen}"><ion-list class="list" ng-class="{\'scroll\': smallscreen}"><ion-item menu-close="" class="item-icon-left hidden-xs" ui-sref="app.home" active-link="active"><i class="icon ion-home"></i> {{:locale:\'MENU.HOME\'|translate}}</ion-item><ion-item menu-close="" ng-if="!login" class="item-icon-left visible-xs" ui-sref="app.home" active-link="active"><i class="icon ion-home"></i> {{:locale:\'MENU.HOME\'|translate}}</ion-item><div class="item item-divider"></div><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/account" ui-sref="app.view_wallet" ng-class="{\'item-menu-disable\': !login}"><i class="icon ion-person"></i> {{:locale:\'MENU.ACCOUNT\'|translate}} </a><a id="helptip-menu-btn-account"></a> <a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/history" ui-sref="app.view_wallet_tx" ng-class="{\'item-menu-disable\': !login}"><i class="icon ion-card"></i> {{:locale:\'MENU.TRANSACTIONS\'|translate}} </a><a id="helptip-menu-btn-tx"></a> <a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/wallets" ui-sref="app.view_wallets" ng-class="{\'item-menu-disable\': !login}"><i class="icon ion-card" style="top: -5px; left: 22px; font-size: 18px"></i> <i class="icon-secondary ion-card" style="top: 22px; left: 19px; font-size: 20px; background-color: white; width:17px; height: 14px"></i> {{:locale:\'MENU.WALLETS\'|translate}}</a><div class="item item-divider"></div><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/wot" ui-sref="app.wot_lookup.tab_search"><i class="icon ion-person-stalker"></i> {{:locale:\'MENU.WOT\'|translate}} </a><a id="helptip-menu-btn-wot"></a><cs-extension-point name="menu-main"></cs-extension-point><div class="item item-divider"></div><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/currency" ui-sref="app.currency"><i class="icon ion-ios-world-outline"></i> {{:locale:\'MENU.CURRENCY\'|translate}} </a><a id="helptip-menu-btn-currency"></a> <a id="helptip-menu-btn-network"></a><cs-extension-point name="menu-discover"></cs-extension-point><div class="item item-divider visible-xs visible-sm"></div><cs-extension-point name="menu-user"></cs-extension-point><a menu-close="" class="item item-icon-left visible-xs visible-sm" active-link="active" active-link-path-prefix="#/app/settings" ui-sref="app.settings"><i class="icon ion-android-settings"></i> {{:locale:\'MENU.SETTINGS\'|translate}} </a><a id="helptip-menu-btn-settings"></a><div class="item item-divider" ng-if="login"></div><ion-item menu-close="" class="item item-button-right" ng-if="login" ng-class="::{\'item-button-left\': $root.device.barcode.enable}"><button class="button button-positive ink-dark" ng-click="showTransferModal()"><i class="icon ion-paper-airplane"></i></button> <button class="button button-stable ink" ng-if="$root.device.barcode.enable" ng-click="scanQrCodeAndGo()"><i class="icon ion-qr-scanner"></i></button></ion-item><cs-extension-point name="menu-actions"></cs-extension-point></ion-list></ion-content></ion-side-menu></ion-side-menus>'); +$templateCache.put('templates/modal_about.html','<ion-modal-view class="about"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CLOSE</button><h1 class="title" translate>ABOUT.TITLE</h1></ion-header-bar><ion-content class="text-center" scroll="true"><div class="list item-wrap-text"><ion-item class="item-icon-left item-text-wrap"><span>{{\'COMMON.APP_NAME\'|translate}} <b>{{\'COMMON.APP_VERSION\'|translate:$root.config}}</b> - <a ng-click="openLink($event, \'http://cesium.app\')">www.cesium.app</a></span> <i ng-if="$root.newRelease" class="assertive ion-alert-circled"></i><h3 ng-if="$root.config.build" class="gray">{{\'COMMON.APP_BUILD\'|translate:$root.config}}</h3><span translate>ABOUT.LICENSE</span></ion-item><ion-item class="item-icon-left" ng-if="$root.newRelease"><i class="item-image icon ion-alert-circled assertive"></i> <span ng-if="!$root.device.isWeb()" ng-bind-html="\'ABOUT.PLEASE_UPDATE\' | translate:$root.newRelease "></span> <span ng-if="$root.device.isWeb()" ng-bind-html="\'ABOUT.LATEST_RELEASE\' | translate:$root.newRelease "></span><h3 ng-if="!$root.device.enable"><a ng-click="openLink($event, $root.newRelease.url)" translate>{{::$root.newRelease.url}}</a></h3></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="item-image icon ion-android-laptop"></i> <span translate>ABOUT.OFFICIAL_WEB_SITE</span><h3><a ng-click="openLink($event, \'https://www.cesium.app\')">https://www.cesium.app</a></h3></ion-item><ion-item class="item-icon-left"><i class="item-image icon ion-chatbubbles"></i> {{\'ABOUT.FORUM\' | translate}}<h3><a ng-click="openLink($event, $root.settings.userForumUrl)">{{::$root.settings.userForumUrl}}</a></h3></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="item-image icon ion-bug"></i> <span translate>ABOUT.PLEASE_REPORT_ISSUE</span><h3><a ng-click="openLink($event, $root.settings.newIssueUrl)" translate>ABOUT.REPORT_ISSUE</a></h3></ion-item><ion-item class="item-icon-left"><i class="item-image icon ion-network"></i> {{\'ABOUT.CODE\' | translate}}<h3><a ng-click="openLink($event, \'https://git.duniter.org/clients/cesium-grp/cesium\')">https://git.duniter.org/clients/cesium-grp/cesium</a></h3></ion-item><ion-item class="item-icon-left"><i class="item-image icon ion-person-stalker"></i> {{\'ABOUT.DEVELOPERS\' | translate}}<h3><a href="https://github.com/blavenie" target="_system">Benoit Lavenier</a>, <a href="https://github.com/bpresles" target="_system">bpresles</a>, <a href="https://github.com/c-geek" target="_system">cgeek</a>, <a href="https://github.com/devingfx" target="_system">DiG</a>, <a href="https://git.duniter.org/ji_emme" target="_system">Ji_emme</a></h3></ion-item><div class="padding hidden-xs text-center"><button class="button button-stable icon-left ink" type="submit" ng-click="closeModal()" ui-sref="app.help"><i class="icon ion-ios-help-outline"></i> {{\'HOME.BTN_HELP\' | translate}}</button> <button class="button button-positive ink" type="submit" ng-click="closeModal()">{{\'COMMON.BTN_CLOSE\' | translate}}</button></div></div></ion-content></ion-modal-view>'); +$templateCache.put('templates/api/doc.html','<h2 class="padding" translate="">API.DOC.TRANSFER.TITLE</h2><div class="list padding no-padding-xs no-padding-top"><div class="item item-divider no-border"><p translate="">API.DOC.DESCRIPTION_DIVIDER</p></div><div class="item item-text-wrap"><p translate="">API.DOC.TRANSFER.DESCRIPTION</p></div><div class="item item-divider no-border"><p translate="">API.DOC.URL_DIVIDER</p></div><div class="item item-text-wrap"><p class="gray text-right">{{$root.rootPath}}#/v1/payment/:pubkey?amount=<span class="text-italic" translate="">API.DOC.TRANSFER.PARAM_AMOUNT</span></p></div><div class="item item-divider no-border"><p translate="">API.DOC.PARAMETERS_DIVIDER</p></div><div class="item item-text-wrap"><p translate="">API.DOC.AVAILABLE_PARAMETERS</p><div class="row"><div class="col col-20 text-italic">pubkey</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_PUBKEY_HELP</div></div><div class="row stable-bg"><div class="col col-20 text-italic dark">amount</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_AMOUNT_HELP</div></div><div class="row"><div class="col col-20 text-italic">comment</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_COMMENT_HELP</div></div><div class="row stable-bg"><div class="col col-20 text-italic dark">name</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_NAME_HELP</div></div><div class="row"><div class="col col-20 text-italic">preferred_node</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_PREFERRED_NODE_HELP</div></div><div class="row stable-bg"><div class="col col-20 text-italic dark">redirect_url</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_REDIRECT_URL_HELP</div></div><div class="row"><div class="col col-20 text-italic">cancel_url</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_CANCEL_URL_HELP</div></div></div><div class="item item-divider no-border"><p translate="">API.DOC.DEMO_DIVIDER</p></div><div class="item item-button-right item-text-wrap padding-bottom"><p class="item-icon-right-padding" translate="">API.DOC.DEMO_HELP</p><span class="badge" ng-if="loading"><ion-spinner class="icon" icon="android"></ion-spinner></span><a ng-if="!loading" href="{{transferDemoUrl}}" class="button button-raised button-positive icon ion-play"></a></div><div class="item item-text-wrap" ng-if="result.type === \'payment\' && !result.cancelled"><h2 class="text-right balanced" translate="">API.DOC.DEMO_SUCCEED</h2><h4 class="gray" translate="">API.DOC.DEMO_RESULT</h4><p class="balanced-100-bg padding dark text-keep-lines">{{result.content}}</p><h4 class="gray"><span translate="">API.DOC.DEMO_RESULT_PEER</span> <b>{{result.node}}</b></h4></div><div class="item item-text-wrap" ng-if="result.type === \'payment\' && result.cancelled"><h2 class="text-right assertive" translate="">API.DOC.DEMO_CANCELLED</h2></div><div class="item item-divider no-border"><p translate="">API.DOC.INTEGRATE_DIVIDER</p></div><div class="item item-text-wrap"><p translate="">API.DOC.TRANSFER.EXAMPLES_HELP</p><div class="row responsive-sm"><div class="col col-20 text-italic"><span translate="">API.DOC.TRANSFER.EXAMPLE_BUTTON</span></div><div class="col gray no-border"><p><i class="icon ion-code"></i> <span translate="">API.DOC.INTEGRATE_CODE</span></p><div class="item item-input"><textarea class="gray" select-on-click="" rows="5" ng-model="transferButton.html" ng-model-options="{ debounce: 650 }"></textarea></div><p class="padding-top"><i class="icon ion-eye"></i> <span translate="">API.DOC.INTEGRATE_RESULT</span></p><div class="padding-left" bind-notifier="{ notifierKey:watchedExpression }"><ng-bind-html ng-bind-html="transferButton.html|trustAsHtml"></ng-bind-html></div></div></div><div class="row responsive-sm"><div class="col gray no-border"><p class="padding-top"><a class="positive" ng-click="transferButton.showParameters=!transferButton.showParameters"><i class="icon ion-wrench"></i> <span translate="">API.DOC.INTEGRATE_PARAMETERS</span> <i class="icon" ng-class="{\'ion-arrow-down-b\': !transferButton.showParameters, \'ion-arrow-up-b\': transferButton.showParameters}"></i></a></p><div ng-if="transferButton.showParameters" class="padding-left"><form id="transferForm" class="stable-bg padding"><p class="padding-top"><i class="icon ion-key"></i> {{\'API.DOC.TRANSFER.PARAM_PUBKEY\' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.pubkey" ng-model-options="{ debounce: 650 }" placeholder="{{\'API.DOC.TRANSFER.PARAM_PUBKEY_HELP\'|translate}}"></label><p class="padding-top"><i class="icon ion-pricetag"></i> {{\'API.DOC.TRANSFER.PARAM_AMOUNT\' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.amount" ng-model-options="{ debounce: 650 }" placeholder="{{\'API.DOC.TRANSFER.PARAM_AMOUNT_HELP\'|translate}}"></label><p class="padding-top"><i class="icon ion-flag"></i> {{\'API.DOC.TRANSFER.PARAM_COMMENT\' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.comment" placeholder="{{\'API.DOC.TRANSFER.PARAM_COMMENT\'|translate}}"></label><p class="padding-top"><i class="icon ion-ios-world-outline"></i> {{\'API.DOC.TRANSFER.PARAM_NAME\' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.name" ng-model-options="{ debounce: 650 }" placeholder="{{\'API.DOC.TRANSFER.PARAM_NAME\'|translate}}"></label><p class="padding-top"><i class="icon ion-key"></i> {{\'API.DOC.TRANSFER.PARAM_PREFERRED_NODE\' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.preferred_node" ng-model-options="{ debounce: 650 }" placeholder="{{\'API.DOC.TRANSFER.PARAM_PREFERRED_NODE_HELP\'|translate}}"></label><p class="padding-top"><i class="icon ion-arrow-return-left"></i> {{\'API.DOC.TRANSFER.PARAM_REDIRECT_URL\' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.redirect_url" ng-model-options="{ debounce: 650 }" placeholder="{{\'API.DOC.TRANSFER.PARAM_REDIRECT_URL\'|translate}}"></label><p class="padding-top"><i class="icon ion-backspace"></i> {{\'API.DOC.TRANSFER.PARAM_CANCEL_URL\' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.cancel_url" ng-model-options="{ debounce: 650 }" placeholder="{{\'API.DOC.TRANSFER.PARAM_CANCEL_URL\'|translate}}"></label><p class="padding-top"><a class="positive" ng-click="transferButton.style.enable=!transferButton.style.enable"><i class="icon" ng-class="{\'ion-android-checkbox-outline\': transferButton.style.enable, \'ion-android-checkbox-outline-blank\': !transferButton.style.enable}"></i> <span translate="">API.DOC.TRANSFER.EXAMPLE_BUTTON_DEFAULT_STYLE</span></a></p><div ng-if="transferButton.style.enable"><p class="padding-top"><i class="icon ion-image"></i> {{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_ICON\' | translate}} :</p><label class="item item-input item-select"><select class="stable-bg dark" ng-model="transferButton.style.icon" style="width: 100%; max-width: 100%" ng-options="l as (l.label | translate) for l in transferButton.icons track by l.filename"></select></label><p class="padding-top"><i class="icon ion-quote"></i> {{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_HELP\' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.text" ng-model-options="{ debounce: 650 }" placeholder="{{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_HELP\'|translate}}"></label><p class="padding-top"><i class="icon ion-paintbucket"></i> {{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_BG_COLOR\' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.bgColor" ng-model-options="{ debounce: 650 }" placeholder="{{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_BG_COLOR_HELP\'|translate}}"></label><p class="padding-top"><i class="icon ion-paintbrush"></i> {{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_FONT_COLOR\' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.fontColor" ng-model-options="{ debounce: 650 }" placeholder="{{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_FONT_COLOR_HELP\'|translate}}"></label><p class="padding-top"><i class="icon ion-ios-crop-strong"></i> {{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_WIDTH\' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.width" ng-model-options="{ debounce: 650 }" placeholder="{{\'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_WIDTH_HELP\'|translate}}"></label></div></form></div></div></div></div></div>'); +$templateCache.put('templates/api/home.html','<ion-view class="circle-bg-dark"><ion-nav-title><span class="title visible-xs visible-sm" translate="">API.HOME.TITLE</span></ion-nav-title><ion-nav-buttons side="right"></ion-nav-buttons><ion-content class="has-header no-padding-xs no-padding-sm positive-900-bg"><br class="hidden-xs"><div class="light text-center"><h4 class="hidden-xs" translate="">API.HOME.MESSAGE</h4><h4 class="visible-xs padding" translate="">API.HOME.MESSAGE_SHORT</h4></div><br class="hidden-xs"><div class="row no-padding-xs"><div class="col"><div class="light-bg no-padding"><ng-include src="\'templates/api/doc.html\'"></ng-include></div></div></div><p class="visible-xs visible-sm light padding-top text-center">{{\'COMMON.APP_NAME\'|translate}} API - <a href="#" ng-click="showAboutModal($event)">v{{$root.config.version}}</a></p></ion-content></ion-view>'); +$templateCache.put('templates/api/locales_popover.html','<ion-popover-view class="fit popover-locales" style="height: {{locales.length*48}}px"><ion-content scroll="false"><div class="list item-text-wrap block"><a ng-repeat="l in locales track by l.id" class="item item-icon-left ink" ng-click="changeLanguage(l.id)"><i class="item-image avatar" style="border-radius: 0; background-image: url(https://www.countryflags.io/{{l.country}}/shiny/64.png)"></i> {{l.label | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/api/menu.html','<ion-nav-bar class="bar-dark" title-align="left"><ion-nav-back-button class="no-text"></ion-nav-back-button><ion-nav-buttons side="left"></ion-nav-buttons><ion-nav-buttons side="right"></ion-nav-buttons></ion-nav-bar><ion-nav-view name="menuContent"></ion-nav-view>'); +$templateCache.put('templates/api/transfer.html','<ion-view class="circle-bg-dark"><ion-nav-buttons side="left"><button class="button button-clear visible-xs" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button></ion-nav-buttons><ion-nav-title><span class="title visible-xs" translate="">API.TRANSFER.TITLE_SHORT</span></ion-nav-title><ion-nav-buttons side="right"><button class="button button-positive button-icon button-clear icon ion-android-send visible-xs" ng-click="doLogin()"></button></ion-nav-buttons><ion-content class="has-header no-padding-xs positive-900-bg"><br class="hidden-xs"><div class="row no-padding-xs"><div class="col no-padding-xs"><div class="light-bg"><h2 class="padding-top text-center hidden-xs" translate="">API.TRANSFER.TITLE</h2><div class="no-padding energized-100-bg" ng-if="demo"><div class="item item-icon-left item-text-wrap no-border"><i class="icon ion-information-circled positive"></i><p translate="">API.TRANSFER.DEMO.HELP</p></div></div><ng-include src="\'templates/login/form_login.html\'"></ng-include></div><br class="hidden-xs"><br class="hidden-xs"><div class="list padding no-padding-xs light-bg"><div class="item"><p translate="">API.TRANSFER.SUMMARY</p></div><div class="item item-icon-left-padding item-tx no-border" ng-if="!transferData.amounts" style="min-height: 56px"><h2 translate="">API.TRANSFER.AMOUNT</h2><ion-spinner class="badge item-note" icon="android" ng-show="loading"></ion-spinner><div class="badge badge-calm ng-hide" ng-show="!loading" ng-bind-html="transferData.amount|formatAmount:{useRelative: false, currency: currency.name}"></div><div class="badge badge-secondary ng-hide" ng-show="!loading" ng-bind-html="transferData.amount|formatAmount:{useRelative: true, currency: currency.name, currentUD: currency.currentUD}"></div></div><label ng-if="transferData.amounts" style="min-height: 58px" class="item item-icon-left-padding item-input item-select item-tx no-border" ng-class="{ \'item-input-error\': form.$submitted && !transferData.amount}"><div class="input-label"><span translate="">API.TRANSFER.AMOUNT</span></div><select ng-model="transferData.amount" required="true" ng-options="(amount |formatAmount:{useRelative: false, currency: currency.name}) for amount in transferData.amounts"></select><span class="badge badge-secondary ng-hide" ng-show="transferData.amount" ng-bind-html="transferData.amount|formatAmount:{useRelative: true, currency: currency.name, currentUD: currency.currentUD}"></span></label><div class="form-errors" ng-if="form.$submitted && !transferData.amount"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-icon-left-padding"><h2 translate="">API.TRANSFER.NAME</h2><div class="badge item-note">{{transferData.name}}</div></div><div class="item item-icon-left-padding item-text-wrap"><h2 translate="">API.TRANSFER.PUBKEY</h2><div class="badge"><span class="hidden-xs"><br class="visible-sm visible-md"><i class="icon ion-key"></i>{{transferData.pubkey}}</span> <span class="visible-xs" copy-on-click="{{transferData.pubkey}}"><br class="visible-xs"><i class="icon ion-key"></i> {{transferData.pubkey|formatPubkey}}</span></div></div><div class="item item-icon-left-padding"><h2 translate="">API.TRANSFER.COMMENT</h2><div class="badge item-note"><span class="hidden-xs"><br class="visible-sm visible-md">{{::transferData.comment}}</span> <span class="visible-xs" copy-on-click="{{transferData.comment}}"><br>{{::transferData.comment}}</span></div></div><div class="item item-icon-left-padding" ng-hide="error"><h2 translate="">API.TRANSFER.NODE</h2><div class="badge item-note" ng-if="!loading"><br class="visible-sm visible-md"><i class="icon ion-locked" ng-if="node.useSsl"></i> {{node.server}}</div></div><div class="center padding animate-fade-in animate-show-hide ng-hide" ng-show="!loading && error"><div class="card card-item padding"><p class="item-content item-text-wrap"><i class="icon ion-android-alert assertive"></i> <span class="dark" trust-as-html="\'API.COMMON.CONNECTION_ERROR\'|translate:node"></span></p><button type="button" class="button button-positive icon icon-left ion-refresh ink" ng-click="start()">{{\'COMMON.BTN_REFRESH\'|translate}}</button></div></div><div class="padding-bottom visible-xs"> </div></div></div></div><p class="visible-xs visible-sm light padding-top text-center">{{\'COMMON.APP_NAME\'|translate}} - <a href="#" ng-click="showAboutModal($event)">v{{$root.config.version}}</a></p></ion-content></ion-view>'); +$templateCache.put('templates/blockchain/item_block.html','<a name="block-{{:rebind:block.number}}"></a><ion-item id="block-{{:rebind:block.number}}" class="item item-icon-left item-block {{::ionItemClass}}" ng-class="{\'ink\': !block.empty||!block.compacted, \'item-block-empty\': block.empty, \'compacted\': block.compacted && compactMode}" ng-click="selectBlock(block)"><i class="icon ion-cube stable" ng-if=":rebind:(!block.empty && !block.avatar)"></i> <i class="avatar" ng-if=":rebind:!block.empty && block.avatar" style="background-image: url(\'{{:rebind:block.avatar.src}}\')"></i><div class="row no-padding" ng-if=":rebind:!block.compacted || !compactMode"><div class="col" style="min-width: 110px; max-width: 130px"><h4 ng-class="{\'gray\': block.compacted, \'dark\': !block.compacted}"><i class="ion-clock"></i> {{:rebind:block.medianTime|medianDate}}</h4><h4 ng-if="!block.empty"><ng-if ng-if=":rebind:block.joinersCount||(block.excludedCount-block.revokedCount)"><i class="dark ion-person"></i> <span class="dark" ng-if=":rebind:block.joinersCount">+{{:rebind:block.joinersCount}}</span> <span class="dark" ng-if=":rebind:block.excludedCount">-{{:rebind:block.excludedCount-block.revokedCount}}</span></ng-if><span class="dark" ng-if=":rebind:block.revokedCount" class="assertive"><i class="ion-minus-circled"></i> {{:rebind:block.revokedCount}} </span> <span class="dark" ng-if=":rebind:block.activesCount" class="gray"><i class="gray ion-refresh"></i> {{:rebind:block.activesCount}} </span> <span class="dark" ng-if=":rebind:block.certificationsCount"><i class="ion-ribbon-a"></i> {{:rebind:block.certificationsCount}} </span> <span class="dark" ng-if=":rebind:block.dividend" class="gray"><i class="gray ion-arrow-up-c"></i> {{\'COMMON.UD\'|translate}} </span> <span class="dark" ng-if=":rebind:block.transactionsCount"><i class="ion-card">{{:rebind:block.transactionsCount}}</i></span></h4></div><div class="col positive hidden-md"><h4><i class="ion-person"></i> {{:rebind:block.name||block.uid}}</h4></div><div class="col col-20"><span class="badge" ng-class="{\'badge-balanced\': !$index , \'badge-calm\': $index && !block.compacted && !block.empty}">{{:rebind:block.number|formatInteger}}</span></div></div></ion-item>'); +$templateCache.put('templates/blockchain/item_block_empty_lg.html','<a name="block-{{::block.number}}"></a><div id="block-{{::block.number}}" class="item item-block item-icon-left item-block-empty" ng-class="{\'compacted\': block.compacted && compactMode}" ng-click="selectBlock(block)"><div class="row no-padding" ng-if=":rebind:!block.compacted || !compactMode"><div class="col"><h3 class="gray"><i class="ion-clock"></i> {{:rebind:block.medianTime|medianDate}}</h3></div><div class="col"><h3><span class="gray" ng-if=":rebind:expertMode"><i class="ion-key"></i> {{:rebind:block.issuer|formatPubkey}} </span><span class="positive"><i class="ion-person"></i> {{:rebind:block.name||block.uid}}</span></h3></div><div class="col col-20"></div><div class="col col-20"><span class="badge" ng-class="{\'badge-balanced\': !$index && search.type==\'last\'}">{{block.number|formatInteger}}</span></div></div></div>'); +$templateCache.put('templates/blockchain/item_block_lg.html','<ion-item id="block-{{::block.number}}" class="item item-block item-icon-left ink {{::ionItemClass}}" ng-class="{{::ionItemClass}}" ng-click="selectBlock(block)"><i class="icon ion-cube stable" ng-if=":rebind:!block.avatar"></i> <i class="avatar" ng-if=":rebind:!block.empty && block.avatar" style="background-image: url(\'{{:rebind:block.avatar.src}}\')"></i><div class="row no-padding"><div class="col"><h3 class="dark"><i class="ion-clock"></i> {{:rebind:block.medianTime|medianDate}}</h3><h4 class="gray">{{:rebind:\'BLOCKCHAIN.HASH\'|translate}} {{:rebind:block.hash|formatHash}}</h4></div><div class="col"><h3><span class="gray" ng-if=":rebind:expertMode"><i class="ion-key"></i> {{:rebind:block.issuer|formatPubkey}} </span><span class="positive"><i class="ion-person"></i> {{:rebind:block.name||block.uid}}</span></h3></div><div class="col col-20"><small><ng-if ng-if=":rebind:block.joinersCount||(block.excludedCount-block.revokedCount)"><i class="ion-person"></i> <span ng-if=":rebind:block.joinersCount">+{{:rebind:block.joinersCount}}</span> <span ng-if=":rebind:block.excludedCount">-{{:rebind:block.excludedCount-block.revokedCount}}</span> </ng-if><span ng-if=":rebind:block.revokedCount" class="assertive"><i class="ion-minus-circled"></i> -{{:rebind:block.revokedCount}} </span> <span ng-if=":rebind:block.activesCount"><i class="ion-refresh"></i> {{:rebind:block.activesCount}} </span> <span ng-if=":rebind:block.certificationsCount"><i class="ion-ribbon-a"></i> {{:rebind:block.certificationsCount}} </span> <span ng-if=":rebind:block.dividend"><i class="gray ion-arrow-up-c"></i> {{:rebind:\'COMMON.UD\'|translate}} </span> <span ng-if=":rebind:block.transactionsCount"><i class="ion-card">{{:rebind:block.transactionsCount}}</i> </span></small></div><div class="col col-20"><span class="badge" ng-class="{\'badge-balanced\': !$index && search.type==\'last\', \'badge-calm\': ($index || search.type!=\'last\')&& !block.compacted && !block.empty}">{{:rebind:block.number}}</span></div></div></ion-item>'); +$templateCache.put('templates/blockchain/items_blocks.html','<div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><ion-list class="animate-ripple padding padding-xs"><div class="padding gray" ng-if="!search.loading && !search.results.length" translate>BLOCKCHAIN.LOOKUP.NO_BLOCK</div><ng-repeat ng-repeat="block in :rebind:search.results track by block.number" ng-include="\'templates/blockchain/item_block.html\'"></ng-repeat></ion-list><ion-infinite-scroll ng-if="search.hasMore" icon="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll>'); +$templateCache.put('templates/blockchain/link_identity.html','<a ui-sref="app.wot_identity({pubkey: identity.pubkey, uid: identity.uid})"><span class="positive" ng-if="identity.uid"><i class="icon ion-person"></i> {{::identity.uid}} </span> <span class="gray" ng-class="{\'hidden-xs hidden-sm\': identity.uid}"><i class="icon ion-key"></i> {{::identity.pubkey|formatPubkey}}</span></a>'); +$templateCache.put('templates/blockchain/list_blocks.html','<div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><ion-list class="padding padding-xs list-blocks {{::motion.ionListClass}}"><div class="padding gray" ng-if="!search.loading && !search.results.length" translate>BLOCKCHAIN.LOOKUP.NO_BLOCK</div><ng-repeat ng-repeat="block in :rebind:search.results track by block.number" ng-include="\'templates/blockchain/item_block.html\'"></ng-repeat></ion-list><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll>'); +$templateCache.put('templates/blockchain/list_blocks_lg.html','<div class="padding padding-xs" style="display: block; height: 100px"><h4 translate>BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4><div class="pull-right"><a class="button button-text button-small ink" ng-class="{\'button-text-positive\': compactMode, \'button-text-stable\': !compactMode}" ng-click="toggleCompactMode()"><i class="icon ion-navicon"></i> <b class="ion-arrow-down-b" style="position: absolute; top: -2px; left: 4px; font-size: 8px"></b> <b class="ion-arrow-up-b" style="position: absolute; top: 10px; left: 4px; font-size: 8px"></b> <span>{{\'BLOCKCHAIN.LOOKUP.BTN_COMPACT\'|translate}}</span></a></div></div><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><ion-list class="padding padding-xs list-blocks {{::motion.ionListClass}}"><div class="padding gray" ng-if="!search.loading && !search.results.length" translate>BLOCKCHAIN.LOOKUP.NO_BLOCK</div><ng-repeat ng-repeat="block in search.results" ng-include="!block.empty ? \'templates/blockchain/item_block_lg.html\' : \'templates/blockchain/item_block_empty_lg.html\'"></ng-repeat></ion-list><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll>'); +$templateCache.put('templates/blockchain/lookup.html','<ion-view><ion-nav-title><span translate>BLOCKCHAIN.LOOKUP.TITLE</span></ion-nav-title><ion-content class="padding no-padding-xs" scroll="true"><ng-include src="\'templates/blockchain/list_blocks.html\'"></ng-include></ion-content></ion-view>'); +$templateCache.put('templates/blockchain/lookup_lg.html','<ion-view><ion-nav-title><span translate>BLOCKCHAIN.LOOKUP.TITLE</span></ion-nav-title><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ng-include src="\'templates/blockchain/list_blocks_lg.html\'"></ng-include></ion-content></ion-view>'); +$templateCache.put('templates/blockchain/unlock_condition_popover.html','<ion-popover-view class="fit"><ion-header-bar><h1 class="title" translate>BLOCKCHAIN.VIEW.TX_OUTPUT_UNLOCK_CONDITIONS</h1></ion-header-bar><ion-content scroll="true"><div class="row" ng-repeat="condition in popoverData.unlockConditions track by $index" ng-style="::condition.style"><span class="gray" ng-if="::condition.operator">{{::\'BLOCKCHAIN.VIEW.TX_OUTPUT_OPERATOR.\'+condition.operator|translate}} </span><div ng-if="::condition.type==\'SIG\'"><i class="icon ion-key dark"></i> <span class="dark" ng-bind-html="::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.SIG\' | translate"></span> <a ng-click="goState(\'app.wot_identity\', {pubkey:condition.value})" style="text-decoration: none" class="positive">{{condition.value|formatPubkey}}</a></div><div ng-if="::condition.type==\'XHX\'"><i class="icon ion-lock-combination dark"></i> <span class="dark" ng-bind-html="::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.XHX\' | translate"></span> <a copy-on-click="{{::condition.value}}" class="positive">{{::condition.value|formatPubkey}}...</a></div><div ng-if="condition.type==\'CSV\'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CSV\' | translate"></span> {{::condition.value|formatDuration}}</div><div ng-if="condition.type==\'CLTV\'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CLTV\' | translate"></span> {{::condition.value|medianDate}}</div></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/blockchain/view_block.html','<ion-view><ion-nav-title><span class="title visible-xs visible-sm" ng-if="number==\'current\'">{{\'BLOCKCHAIN.VIEW.TITLE_CURRENT\'|translate}}</span> <span class="title visible-xs visible-sm" ng-if="number!=\'current\'">{{\'BLOCKCHAIN.VIEW.TITLE\'|translate:formData}}</span></ion-nav-title><ion-content class="no-padding-xs no-padding-sm" scroll="true"><div class="row no-padding"><div class="col no-padding"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="list item-text-wrap no-padding-xs" ng-if="!loading"><div class="item item-text-wrap"><h3><span class="dark"><i class="icon ion-clock"></i> {{formData.medianTime | medianFromNowAndDate}}</span></h3><h3><span class="dark"><i class="icon ion-lock-combination"></i> {{\'BLOCKCHAIN.VIEW.COMPUTED_BY\'|translate}} </span><a class="positive" ui-sref="app.wot_identity({pubkey:issuer.pubkey, uid: issuer.uid})"><i class="icon ion-person positive"></i> {{issuer.name||issuer.uid}} <span class="gray" ng-if="issuer.name">({{issuer.uid}})</span></a></h3><h3><a ng-click="openRawBlock($event)"><i class="icon ion-share"></i> {{\'BLOCKCHAIN.VIEW.SHOW_RAW\'|translate}}</a></h3></div><span class="item item-divider">{{\'BLOCKCHAIN.VIEW.TECHNICAL_DIVIDER\' | translate}}</span><ion-item class="item-icon-left item-text-wrap" ng-if="!compactMode || $root.settings.expertMode"><i class="icon ion-gear-b"></i> {{\'BLOCKCHAIN.VIEW.VERSION\'|translate}} <span class="badge badge-stable">{{::formData.version}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="!compactMode || $root.settings.expertMode" copy-on-click="{{::formData.powMin}}"><i class="icon ion-lock-combination"></i> {{\'BLOCKCHAIN.VIEW.POW_MIN\'|translate}}<h4 class="gray">{{\'BLOCKCHAIN.VIEW.POW_MIN_HELP\'|translate}}</h4><span class="badge badge-stable">{{::formData.powMin}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" copy-on-click="{{::formData.hash}}"><i class="icon ion-pound"></i> {{\'BLOCKCHAIN.VIEW.HASH\'|translate}}<h5 class="visible-xs visible-sm dark">{{::formData.hash}}</h5></ion-item><span class="item item-divider">{{\'BLOCKCHAIN.VIEW.DATA_DIVIDER\' | translate}}</span><ion-item ng-if="compactMode && formData.empty" class="item-icon-left item-text-wrap">{{\'BLOCKCHAIN.VIEW.EMPTY\'|translate}}</ion-item><ion-item ng-if="!compactMode || formData.dividend" class="item-icon-left item-text-wrap" copy-on-click="{{::formData.dividend/100}}"><i class="icon ion-arrow-up-c"></i><div class="col col-60">{{\'COMMON.UNIVERSAL_DIVIDEND\'|translate}}<h4 class="gray">{{\'BLOCKCHAIN.VIEW.UNIVERSAL_DIVIDEND_HELP\'|translate: {membersCount: formData.membersCount} }}</h4></div><span class="badge badge-balanced" ng-if="formData.dividend">+1 <span ng-bind-html="formData.currency|currencySymbol: {useRelative: true} "></span> / {{\'COMMON.MEMBER\'|translate|lowercase}} </span><span class="badge badge-stable" ng-if="!formData.dividend">0</span> <span class="badge badge-secondary" ng-if="formData.dividend">+ {{formData.dividend| formatAmount: {currency: formData.currency, useRelative: false} }} / {{\'COMMON.MEMBER\'|translate|lowercase}}</span></ion-item><ng-if ng-if="!compactMode || formData.identitiesCount"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-clock" style="position: absolute; top: 16px; left: 39px; font-size: 12px"></b> {{\'BLOCKCHAIN.VIEW.IDENTITIES_COUNT\'|translate}} <span class="badge badge-balanced" ng-if="formData.identitiesCount">+{{::formData.identitiesCount}}</span> <span class="badge badge-stable" ng-if="!formData.identitiesCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.identitiesCount"><ion-item ng-repeat="identity in ::formData.identities" class="item-border-large item-small-height" ng-include="\'templates/blockchain/link_identity.html\'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.joinersCount"><ion-item class="item-icon-left"><i class="icon ion-person-add"></i> {{\'BLOCKCHAIN.VIEW.JOINERS_COUNT\'|translate}} <span class="badge badge-balanced" ng-if="formData.joinersCount">+{{::formData.joinersCount}}</span> <span class="badge badge-stable" ng-if="!formData.joinersCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.joinersCount"><ion-item ng-repeat="identity in ::formData.joiners" class="item-border-large item-small-height" ng-include="\'templates/blockchain/link_identity.html\'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.activesCount"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-refresh" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{\'BLOCKCHAIN.VIEW.ACTIVES_COUNT\'|translate}}<h4 class="gray">{{\'BLOCKCHAIN.VIEW.ACTIVES_COUNT_HELP\'|translate}}</h4><span class="badge badge-balanced" ng-if="formData.activesCount">{{::formData.activesCount}}</span> <span class="badge badge-stable" ng-if="!formData.activesCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.activesCount"><ion-item ng-repeat="identity in ::formData.actives" class="item-border-large item-small-height" ng-include="\'templates/blockchain/link_identity.html\'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || (formData.excludedCount-formData.revokedCount)"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-close dark" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{\'BLOCKCHAIN.VIEW.EXCLUDED_COUNT\'|translate}}<h4 class="gray">{{\'BLOCKCHAIN.VIEW.EXCLUDED_COUNT_HELP\'|translate}}</h4><span class="badge badge-assertive" ng-if="formData.excludedCount-formData.revokedCount">-{{::formData.excludedCount-formData.revokedCount}}</span> <span class="badge badge-stable" ng-if="!(formData.excludedCount-formData.revokedCount)">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.excludedCount"><ion-item ng-repeat="identity in ::formData.excluded" class="item-border-large item-small-height" ng-include="\'templates/blockchain/link_identity.html\'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.leaversCount"><ion-item class="item-icon-left" ng-if="!compactMode || formData.leaversCount"><i class="icon ion-person"></i> <b class="ion-minus" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{\'BLOCKCHAIN.VIEW.LEAVERS_COUNT\'|translate}}<h4 class="gray">{{\'BLOCKCHAIN.VIEW.LEAVERS_COUNT_HELP\'|translate}}</h4><span class="badge badge-assertive" ng-if="formData.leaversCount">-{{::formData.leaversCount}}</span> <span class="badge badge-stable" ng-if="!formData.leaversCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.leaversCount"><ion-item ng-repeat="identity in ::formData.leavers" class="item-border-large item-small-height" ng-include="\'templates/blockchain/link_identity.html\'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.revokedCount"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-minus-circled assertive" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{\'BLOCKCHAIN.VIEW.REVOKED_COUNT\'|translate}}<h4 class="gray">{{\'BLOCKCHAIN.VIEW.REVOKED_COUNT_HELP\'|translate}}</h4><span class="badge badge-balanced" ng-if="formData.revokedCount">-{{::formData.revokedCount}}</span> <span class="badge badge-stable" ng-if="!formData.revokedCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.revokedCount"><ion-item ng-repeat="identity in ::formData.revoked" class="item-border-large item-small-height" ng-include="\'templates/blockchain/link_identity.html\'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.certificationsCount"><ion-item class="item-icon-left"><i class="icon ion-ribbon-a"></i> {{\'BLOCKCHAIN.VIEW.CERT_COUNT\'|translate}} <span class="badge badge-stable" ng-class="{\'badge-positive\':formData.certificationsCount}">{{::formData.certificationsCount}}</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding no-padding-xs" ng-if="formData.certificationsCount"><div ng-repeat="(key, certs) in formData.certifications" class="item item-border-large item-small-height"><div class="row no-padding"><div class="col col-center no-padding"><ng-repeat ng-repeat="cert in certs"><ng-include src="\'templates/blockchain/link_identity.html\'" onload="identity=cert.from"></ng-include><br></ng-repeat></div><div class="col col-10 col-center gray text-center no-padding"><h2><i class="icon ion-arrow-right-a"></i></h2></div><div class="col col-40 col-center no-padding" ng-include="\'templates/blockchain/link_identity.html\'" onload="identity=certs[0].to"></div></div></div></div></ng-if><ng-if ng-if="!compactMode || formData.transactionsCount"><ion-item class="item-icon-left"><i class="icon ion-card"></i> {{\'BLOCKCHAIN.VIEW.TX_COUNT\'|translate}} <span class="badge badge-stable" ng-class="{\'badge-positive\':formData.transactionsCount}">{{::formData.transactionsCount}}</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding no-padding-xs" ng-if="formData.transactionsCount"><div ng-repeat="tx in ::formData.transactions" class="item item-small-height item-border-large"><div class="row no-padding" style="padding-top: 3px"><div class="col col-40 col-center no-padding list no-margin"><div ng-repeat="identity in ::tx.issuers" class="item no-padding item-small-height"><ng-include src="\'templates/blockchain/link_identity.html\'"></ng-include></div></div><div class="col col-10 col-center gray text-center no-padding"><h2><i class="icon ion-arrow-right-a"></i></h2></div><div class="col no-padding padding-right no-padding-xs col-text-wrap list no-margin"><span class="gray" ng-if="tx.toHimself" translate="">BLOCKCHAIN.VIEW.TX_TO_HIMSELF</span><div ng-repeat="output in ::tx.outputs" class="item no-padding item-small-height"><ng-include ng-if="::output.pubkey" src="\'templates/blockchain/link_identity.html\'" onload="identity=output"></ng-include><span ng-if="::!output.pubkey && output.unlockFunctions"><i class="icon ion-locked"></i> (<a ng-click="showUnlockConditionPopover(output, $event)"> <i ng-repeat="unlockFunction in ::output.unlockFunctions" ng-class="::{\'ion-key\': (unlockFunction==\'SIG\'), \'ion-clock\': (unlockFunction==\'CSV\' || unlockFunction==\'CLTV\'), \'ion-lock-combination\': (unlockFunction==\'XHX\') }" class="icon"></i> </a>) </span><span class="badge badge-balanced" ng-bind-html="::output.amount | formatAmount:{currency: formData.currency, useRelative: false} "></span></div></div></div></div></div></ng-if></div></div></div></ion-content></ion-view>'); +$templateCache.put('templates/common/badge_certification_count.html','<span ng-attr-id="{{$ctrl.csId}}" class="badge badge-balanced" ng-class="{\'badge-energized\': $ctrl.requirements.willNeedCertificationCount || ($ctrl.requirements.needCertificationCount + $ctrl.requirements.pendingCertificationCount >= $ctrl.parameters.sigQty),\n \'badge-assertive\': ($ctrl.requirements.needCertificationCount + $ctrl.requirements.pendingCertificationCount < $ctrl.parameters.sigQty)}"><span ng-if="$ctrl.requirements.certificationCount || !$ctrl.requirements.pendingCertificationCount"><i ng-if="!$ctrl.requirements.needCertificationCount" class="ion-android-done"></i> {{$ctrl.requirements.certificationCount}} <i ng-if="$ctrl.requirements.willNeedCertificationCount" class="ion-android-warning"></i> </span><span ng-if="$ctrl.requirements.pendingCertificationCount"><ng-if ng-if="$ctrl.requirements.certificationCount">+</ng-if><i class="ion-clock"></i> {{$ctrl.requirements.pendingCertificationCount}}</span></span>'); +$templateCache.put('templates/common/badge_given_certification_count.html','<div ng-attr-id="{{$ctrl.csId}}" class="badge badge-calm" ng-class="{\'badge-assertive\': $ctrl.identity.given_cert.length >= $ctrl.parameters.sigStock}"><span><i ng-if="$ctrl.identity.given_cert.length" class="ion-android-done"></i> {{$ctrl.identity.given_cert.length}} </span><span ng-if="$ctrl.identity.given_cert_pending.length">(<ng-if ng-if="$ctrl.identity.given_cert.length">+</ng-if><i class="ion-clock"></i> {{$ctrl.identity.given_cert_pending.length}}) </span><small>/ {{$ctrl.parameters.sigStock}}</small></div>'); +$templateCache.put('templates/common/form_error_messages.html','<div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div><div class="form-error" ng-message="maxlength"><span translate="ERROR.FIELD_TOO_LONG"></span></div><div class="form-error" ng-message="pattern"><span translate="ERROR.FIELD_ACCENT"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div>'); +$templateCache.put('templates/common/popover_copy.html','<ion-popover-view class="popover-copy" style="height: {{(!rows || rows <= 1) ? 50 : rows*22}}px"><ion-content scroll="false"><div class="list"><div class="item item-input"><input type="text" ng-if="!rows || rows <= 1" ng-model="value"><textarea ng-if="rows && rows > 1" ng-model="value" rows="{{rows}}" cols="10">\n </textarea></div></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/common/popover_helptip.html','<ion-popover-view class="popover-helptip"><ion-content scroll="false" class="list"><p><i ng-if="icon.position && !icon.position.startsWith(\'bottom-\')" class="{{icon.class}} icon-{{icon.position}} hidden-xs" style="{{icon.style}}"></i><a ng-click="closePopover()" class="pull-right button-close" ng-class="{\'pull-left\': icon.position === \'right\', \'pull-right\': icon.position !== \'right\'}"><i class="ion-close"></i> </a><span> </span></p><p class="padding light"><ng-bind-html ng-bind-html="content | translate:contentParams"></ng-bind-html><ng-bind-html ng-bind-html="trustContent"></ng-bind-html></p><div class="text-center" ng-if="!tour"><button class="button button-small button-stable" ng-if="!hasNext" ng-click="closePopover(true)" translate>COMMON.BTN_UNDERSTOOD</button> <button class="button button-small button-stable" id="helptip-btn-ok" ng-if="hasNext" ng-click="closePopover(false)" translate>COMMON.BTN_UNDERSTOOD</button> <button id="helptip-btn-ok" class="button button-small button-positive icon-right ink" ng-if="hasNext" ng-click="closePopover(true)"><i class="icon ion-chevron-right"></i></button></div><div class="text-center" ng-if="tour"><button class="button button-small button-positive" id="helptip-btn-ok" ng-if="!hasNext" ng-click="closePopover(false)" translate>COMMON.BTN_CLOSE</button> <button id="helptip-btn-ok" class="button button-small button-positive icon-right ink" ng-if="hasNext" ng-click="closePopover(true)">{{\'COMMON.BTN_CONTINUE\'|translate}} <i class="icon ion-chevron-right"></i></button></div><p><i ng-if="icon.position && icon.position.startsWith(\'bottom-\')" class="{{icon.class}} icon-{{icon.position}} hidden-xs"></i></p></ion-content></ion-popover-view>'); +$templateCache.put('templates/common/popover_profile.html',''); +$templateCache.put('templates/common/popover_share.html','<ion-popover-view class="popover-share"><ion-content scroll="false"><div class="bar bar-header"><h1 class="title">{{titleKey|translate:titleValues}}</h1><span class="gray pull-right">{{time|formatDate}}</span></div><div class="list no-margin no-padding has-header has-footer block"><div class="item item-input"><input type="text" ng-model="value"></div></div><div class="bar bar-footer"><div class="button-bar"><a class="button button-icon positive icon ion-social-facebook" href="https://www.facebook.com/sharer/sharer.php?u={{postUrl|formatEncodeURI}}&title={{postMessage|formatEncodeURI}}" onclick="window.open(this.href, \'facebook-share\',\'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,width=580,height=296\');return false;" title="{{\'COMMON.POPOVER_SHARE.SHARE_ON_FACEBOOK\'|translate}}"></a> <a class="button button-icon positive icon ion-social-twitter" href="https://twitter.com/intent/tweet?url={{postUrl|formatEncodeURI}}&text={{postMessage|formatEncodeURI}}" onclick="window.open(this.href, \'twitter-share\',\'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,width=580,height=296\');return false;" title="{{\'COMMON.POPOVER_SHARE.SHARE_ON_TWITTER\'|translate}}"></a> <a class="button button-icon positive icon ion-social-googleplus" href="https://plus.google.com/share?url={{postUrl|formatEncodeURI}}" onclick="window.open(this.href, \'google-plus-share\', \'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=296,width=580\');return false;" title="{{\'COMMON.POPOVER_SHARE.SHARE_ON_GOOGLEPLUS\'|translate}}"></a> <a class="button button-icon positive icon ion-social-diaspora" href="https://sharetodiaspora.github.io/?title={{postMessage|formatEncodeURI}}&url={{postUrl|formatEncodeURI}}" onclick="window.open(this.href, \'diaspora-share\',\'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,width=580,height=296\');return false;" title="{{\'COMMON.POPOVER_SHARE.SHARE_ON_DIASPORA\'|translate}}"></a> <a class="button-close" title="{{\'COMMON.BTN_CLOSE\'|translate}}" ng-click="closePopover()"><i class="icon ion-close"></i></a></div></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/common/popup_password.html','<form name="pwdForm" ng-submit="submit($event)"><div class="list" ng-init="setForm(pwdForm)"><label class="item item-input" ng-class="{\'item-input-error\': pwdForm.$submitted && pwdForm.password.$invalid}"><input name="password" type="password" placeholder="{{\'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.PASSWORD_HELP\' | translate}}" ng-model="formData.password" ng-minlength="1" required></label><div class="form-errors" ng-if="pwdForm.$submitted && pwdForm.pseudo.$error" ng-messages="pwdForm.password.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div><div class="form-errors" ng-if="error"><div class="form-error">{{error|translate}}</div></div></div></form>'); +$templateCache.put('templates/common/view_passcode.html','<ion-view left-buttons="leftButtons"><ion-nav-title><span class="visible-xs visible-sm" translate>COMMON.PASSCODE.TITLE</span></ion-nav-title><ion-content scroll="false"></ion-content></ion-view>'); +$templateCache.put('templates/currency/items_network.html','<ion-item id="helptip-network-blockchain" class="item-icon-left item-text-wrap"><i class="icon ion-clock"></i> <span class="col col-60" translate="">CURRENCY.VIEW.MEDIAN_TIME</span> <span class="badge badge-stable">{{formData.medianTime | medianDate}}</span></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-lock-combination"></i> <span class="col col-75" translate="">CURRENCY.VIEW.POW_MIN</span> <span class="badge badge-stable">{{formData.difficulty | formatInteger}}</span></ion-item><cs-extension-point name="network-actual"></cs-extension-point><div class="item item-divider"><span translate="">CURRENCY.VIEW.NETWORK_RULES_DIVIDER</span></div><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-clock" style="position: absolute; font-size: 20px; left: 16px; margin-top: 11px"></i> <b class="icon-secondary ion-lock-combination" style="left: 14px; margin-top: -4px"></b> <b class="icon-secondary ion-arrow-right-c" style="font-size: 12px; left: 28px; margin-top: -4px"></b> <b class="icon-secondary ion-lock-combination" style="left: 38px; margin-top: -4px"></b> <span class="col col-75" translate="">CURRENCY.VIEW.AVG_GEN_TIME</span> <span class="badge badge-stable">{{formData.avgGenTime | formatDuration}}</span></ion-item><div id="helptip-network-peers" class="item item-divider"><div class="pull-left"><span ng-if="search.type==\'member\'" translate="">PEER.MEMBERS</span> <span ng-if="search.type==\'mirror\'" translate="">PEER.MIRRORS</span> <span ng-if="search.type==\'offline\'" translate="">PEER.OFFLINE</span> <span ng-if="!search.type" translate="">PEER.PEERS</span> <span ng-if="!search.loading">({{search.results.length}})</span></div><div class="buttons pull-right"><ion-spinner class="icon" icon="android" ng-if="search.loading"></ion-spinner></div></div><ng-include src="\'templates/network/items_peers.html\'"></ng-include>'); +$templateCache.put('templates/currency/items_parameters.html','<div bind-notifier="{ rebind:formData.useRelative }"><ion-item class="item-icon-left item-text-wrap visible-xs visible-sm"><i class="icon ion-android-bookmark"></i> <span translate>CURRENCY.VIEW.CURRENCY_NAME</span><div class="item-note dark" ng-if="!loading">{{formData.currency}} (<span ng-bind-html=":rebind:formData.currency | currencySymbol:formData.useRelative"></span>)</div></ion-item><ion-item id="helptip-currency-mass-member" class="item-icon-left item-text-wrap"><i class="icon ion-pie-graph"></i><div class="col col-60"><span translate>CURRENCY.VIEW.SHARE</span> <span class="gray">(M<sub>t</sub>/N<sub>t</sub>)</span></div><span id="helptip-currency-mass-member-unit" ng-if="!loading" class="badge badge-calm" ng-bind-html=":rebind:formData.MoverN | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}"></span></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-record"></i><div class="col col-60"><span translate>CURRENCY.VIEW.MASS</span> <span class="gray">(M<sub>t</sub>)</span></div><span class="badge badge-energized" ng-if="!loading" ng-bind-html=":rebind:formData.M | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}"></span></ion-item><cs-extension-point name="parameters-actual"></cs-extension-point><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-arrow-graph-up-right"></i><div class="col col-60"><span translate>CURRENCY.VIEW.C_ACTUAL</span> <span class="gray">(c<sub>{{\'CURRENCY.VIEW.CURRENT\'|translate}}</sub>)</span></div><span class="badge badge-stable">{{formData.cactual | formatNumeral: \'0,0.00\'}} % / {{formData.dt | formatPeriod}}</span></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-load-c"></i><div class="col col-60"><span translate>CURRENCY.VIEW.UD</span> <span class="gray">({{\'COMMON.UD\'|translate}}<sub>t</sub>)</span></div><div class="badge badge-royal" ng-if="!loading"><span ng-if="formData.useRelative">1<ng-bind-html ng-bind-html=":rebind:formData.currency| currencySymbol:true"></ng-bind-html></span><span ng-if="!formData.useRelative" ng-bind-html=":rebind:formData.currentUD | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}"></span> / {{formData.dt | formatPeriod}}</div></ion-item><div class="item item-toggle dark"><div class="item-label text-right gray" translate>COMMON.BTN_RELATIVE_UNIT</div><label class="toggle toggle-royal" id="helptip-currency-change-unit"><input type="checkbox" ng-model="formData.useRelative"><div class="track"><div class="handle"></div></div></label></div><a name="helptip-currency-rules-anchor"></a><div class="item item-divider" id="helptip-currency-rules"><span translate>CURRENCY.VIEW.MONEY_RULES_DIVIDER</span></div><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-arrow-graph-up-right"></i><div class="col col-60"><span translate>CURRENCY.VIEW.C_RULE</span> <span class="gray">(c)</span></div><span class="item-note dark" ng-if="!loading && !formData.udReevalTime0">{{formData.c*100 | formatNumeral: \'0,0.00\'}} % / {{formData.dt | formatPeriod}}</span><span class="badge badge-stable" ng-if="!loading && formData.udReevalTime0">{{formData.c*100 | formatNumeral: \'0,0.00\'}} % / {{formData.dtReeval | formatDuration}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.udReevalTime0 && formData.allRules"><i class="icon ion-load-c"></i> <b class="ion-clock icon-secondary" style="font-size: 18px; left: 36px; top: -12px"></b><div class="col col-60"><span translate>CURRENCY.VIEW.DT_REEVAL</span> <span class="gray">(dt<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub>)</span></div><span class="item-note dark" ng-if="!loading" translate="CURRENCY.VIEW.DT_REEVAL_VALUE" translate-values="formData"></span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.udReevalTime0 && formData.allRules"><i class="icon ion-load-c"></i> <b class="ion-calendar icon-secondary" style="font-size: 18px; left: 36px; top: -12px"></b><div class="col col-60"><span translate>CURRENCY.VIEW.UD_REEVAL_TIME0</span> <span class="gray">(t0<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub>)</span></div><span class="item-note dark" ng-if="!loading">{{formData.udReevalTime0|medianDate}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.allRules"><i class="icon ion-load-c"></i> <b class="ion-calculator icon-secondary" style="font-size: 18px; left: 36px; top: -12px"></b><div class="col col-60"><span translate>CURRENCY.VIEW.UD_RULE</span> <span class="gray" ng-if="formData.udReevalTime0">- {{\'COMMON.UD\'|translate}}<sub>{{formData.dt|formatPeriod}}</sub>(t<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub>)</span></div><span class="item-note dark" ng-if="!loading && !formData.udReevalTime0">{{\'COMMON.UD\'|translate}}<sub>t-1</sub> + c<sup>2</sup> * M<sub>t-1</sub>/N<sub>t-1</sub></span><span class="item-note dark" ng-if="!loading && formData.udReevalTime0">{{\'COMMON.UD\'|translate}}<sub>{{formData.dt|formatPeriod}}</sub>(t<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub> - dt<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub>)+ c<sup>2</sup> * (M/N)(t<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub> - dt<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub>) / dt<sub>{{\'CURRENCY.VIEW.REEVAL_SYMBOL\'|translate}}</sub></span></ion-item><div class="item item-toggle dark"><div class="item-label text-right gray" translate>CURRENCY.VIEW.DISPLAY_ALL_RULES</div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.allRules"><div class="track"><div class="handle"></div></div></label></div></div>'); +$templateCache.put('templates/currency/items_wot.html','<div bind-notifier="{ rebind:formData.useRelative }"><a name="helptip-currency-newcomers-anchor"></a><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-person-stalker"></i><div class="col col-60"><span translate>CURRENCY.VIEW.MEMBERS</span> <span class="gray">(N<sub>{{\'CURRENCY.VIEW.CURRENT\'|translate}}</sub>)</span></div><span class="badge badge-calm" ng-if="!loading">{{formData.N | formatInteger}}</span></ion-item><ion-item id="helptip-currency-newcomers" class="item-icon-left item-text-wrap"><i class="icon ion-arrow-graph-up-right"></i><div class="col col-75"><span translate="CURRENCY.VIEW.MEMBERS_VARIATION" translate-values="{duration: formData.durationFromLastUD}"></span> <span class="gray">(ΔN)</span></div><div class="badge" ng-if="!loading" ng-class="{\'badge-balanced\': (formData.N>formData.Nprev), \'badge-stable\': (formData.N==formData.Nprev) ,\'badge-assertive\': (formData.Nprev>formData.N)}">{{formData.N > formData.Nprev ? \'+\' : \'\'}}{{formData.N - formData.Nprev}}</div></ion-item><cs-extension-point name="wot-actual"></cs-extension-point><div class="item item-divider"><span translate>CURRENCY.VIEW.WOT_RULES_DIVIDER</span></div><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-ribbon-b"></i> <span class="col col-75" translate>CURRENCY.VIEW.SIG_QTY_RULE</span> <span class="badge badge-balanced" ng-if="!loading">{{formData.sigQty}}</span></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-person"></i> <b class="ion-clock icon-secondary" style="font-size: 18px; left: 33px; top: -12px"></b> <span class="col col-60" translate>CURRENCY.VIEW.MS_WINDOW</span> <span class="badge badge-assertive" ng-if="!loading">{{formData.msWindow | formatDuration}}</span></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-person"></i> <b class="ion-calendar icon-secondary" style="font-size: 18px; left: 33px; top: -12px"></b> <span class="col col-60" translate>CURRENCY.VIEW.MS_VALIDITY</span> <span class="badge badge-balanced" ng-if="!loading">{{formData.msValidity | formatDuration}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.allWotRules"><i class="icon ion-ribbon-b"></i> <b class="ion-clock icon-secondary" style="font-size: 18px; left: 33px; top: -12px"></b> <span class="col col-60" translate>CURRENCY.VIEW.SIG_WINDOW</span> <span class="badge badge-stable" ng-if="!loading">{{formData.sigWindow | formatDuration}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.allWotRules"><i class="icon ion-ribbon-b"></i> <b class="ion-calendar icon-secondary" style="font-size: 18px; left: 33px; top: -12px"></b> <span class="col col-60" translate>CURRENCY.VIEW.SIG_VALIDITY</span> <span class="badge badge-balanced" ng-if="!loading">{{formData.sigValidity | formatDuration}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.allWotRules"><i class="icon ion-ribbon-a"></i> <span class="col col-75" translate>CURRENCY.VIEW.SIG_STOCK</span> <span class="badge badge-stable" ng-if="!loading">{{formData.sigStock}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.allWotRules"><i class="icon ion-clock" style="position: absolute; font-size: 20px; left: 16px"></i> <b class="ion-ribbon-a icon-secondary" style="left: 16px; top: -15px"></b> <b class="ion-arrow-right-c icon-secondary" style="left: 28px; top: -15px"></b> <b class="ion-ribbon-a icon-secondary" style="left: 40px; top: -15px"></b> <span class="col col-75" translate>CURRENCY.VIEW.SIG_PERIOD</span> <span class="badge badge-stable" ng-if="!loading">{{formData.sigPeriod | formatDuration}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.allWotRules"><i class="icon ion-steam"></i> <b class="ion-person icon-secondary" style="left: 38px; top: -17px"></b><div class="col col-75"><span ng-bind-html="\'CURRENCY.VIEW.STEP_MAX\'|translate"></span> <span class="gray">(stepMax)</span></div><span class="badge badge-assertive" ng-if="!loading">{{formData.stepMax}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.allWotRules"><i class="icon ion-ribbon-b"></i> <b class="ion-star icon-secondary" style="color: yellow; font-size: 16px; left: 25px; top: -7px"></b> <span class="col col-75" translate>CURRENCY.VIEW.SENTRIES</span> <span class="badge badge-stable" ng-if="!loading">{{formData.sentries}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.allWotRules"><i class="icon ion-ribbon-b"></i> <b class="ion-star icon-secondary" style="color: yellow; font-size: 16px; left: 25px; top: -7px"></b> <span class="col col-75" translate>CURRENCY.VIEW.SENTRIES_FORMULA</span> <span class="item-note dark" ng-if="!loading">{{\'CURRENCY.VIEW.MATH_CEILING\'| translate}}( N<sub>t</sub><sup>^ (1 / stepMax)</sup>)</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.allWotRules"><i class="icon ion-pull-request"></i> <span class="col col-75" translate>CURRENCY.VIEW.XPERCENT</span> <span class="badge badge-stable" ng-if="!loading">{{formData.xpercent*100| formatNumeral: \'0,0\'}} %</span></ion-item><div class="item item-toggle dark"><div class="item-label text-right gray" translate>CURRENCY.VIEW.DISPLAY_ALL_RULES</div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.allWotRules"><div class="track"><div class="handle"></div></div></label></div></div>'); +$templateCache.put('templates/currency/lookup.html','<ion-view view-title="{{\'CURRENCY.SELECT.TITLE\' | translate}}"><ion-content class="padding no-padding-xs no-padding-sm"><h4 class="content double-padding-x" translate>CURRENCY.SELECT.CURRENCIES</h4><ng-include src="\'templates/currency/lookup_form.html\'"></ion-content></ion-view>'); +$templateCache.put('templates/currency/lookup_form.html','<ion-list><div class="item center" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div ng-repeat="currency in search.results" ng-class="{ selected: selectedCurrency == currency }"><a class="item card card-item stable-bg padding ink" ng-click="selectCurrency(currency)" ng-class="{ selected: selectedCurrency && selectedCurrency.name == currency.name }"><h2>{{currency.name}}</h2><h4 class="gray">{{currency.peer.server}}</h4><span class="badge badge-royal">{{\'CURRENCY.SELECT.MEMBERS_COUNT\'|translate:currency}}</span></a></div></ion-list>'); +$templateCache.put('templates/currency/modal_license.html','<ion-modal-view class="modal-full-height modal-license"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>CURRENCY.LICENSE.TITLE</h1><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doTransfer()"></button></ion-header-bar><ion-content scroll="false" style="bottom: 0px"><p ng-if="!licenseUrl && !loading">translate>CURRENCY.LICENSE.NO_LICENSE_FILE</p><iframe ng-if="licenseUrl && !loading" class="padding-left padding-right no-padding-xs iframe-license" id="iframe-license" ng-src="{{licenseUrlHtml||licenseUrl}}"></iframe><div class="padding hidden-xs text-center"><button class="button button-stable ink" ng-click="downloadFile()">{{\'CURRENCY.LICENSE.BTN_DOWNLOAD\' | translate}}</button> <button class="button button-positive ink" type="submit" ng-click="closeModal()">{{\'COMMON.BTN_CLOSE\' | translate}}</button></div></ion-content></ion-modal-view>'); +$templateCache.put('templates/currency/popover_actions.html','<ion-popover-view class="fit has-header popover-wallet-actions"><ion-header-bar><h1 class="title" translate="">COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/currency/view_currency.html','<ion-view left-buttons="leftButtons" cache-view="false"><ion-tabs class="tabs-positive tabs-icon-top"><ion-tab title="{{\'CURRENCY.VIEW.TAB_CURRENCY\'|translate}}" icon="ion-stats-bars" ui-sref="app.currency.tab_parameters"><ion-nav-view name="tab-parameters"></ion-nav-view></ion-tab><ion-tab title="{{\'CURRENCY.VIEW.TAB_WOT\'|translate}}" icon="ion-person-stalker" ui-sref="app.currency.tab_wot"><ion-nav-view name="tab-wot"></ion-nav-view></ion-tab><ion-tab id="helptip-currency-tab-peers" title="{{\'CURRENCY.VIEW.TAB_NETWORK\'|translate}}" icon="ion-cloud" ui-sref="app.currency.tab_network"><ion-nav-view name="tab-network"></ion-nav-view></ion-tab><ion-tab title="{{\'CURRENCY.VIEW.TAB_BLOCKS\'|translate}}" icon="ion-lock-combination" ui-sref="app.currency.tab_blocks"><ion-nav-view name="tab-blocks"></ion-nav-view></ion-tab></ion-tabs></ion-view>'); +$templateCache.put('templates/currency/view_currency_lg.html','<ion-view left-buttons="leftButtons" cache-view="false"><ion-nav-title bind-notifier="{ rebind:formData.useRelative }"><span ng-if="!loading">{{\'CURRENCY.VIEW.TITLE\' | translate}} {{formData.currency|abbreviate}}</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-loop visible-xs visible-sm" ng-click="refreshPeers()"></button><cs-extension-point name="nav-buttons"></cs-extension-point></ion-nav-buttons><ion-content><div class="item item-text-wrap no-border no-padding pull-left"><div class="item-icon-left card padding stable-900-bg"><ion-spinner class="icon" icon="android" ng-if="loading"></ion-spinner><i class="icon ion-help-circled calm" ng-if="!loading"></i><div class="item-icon-left-padding" style="min-height: 26px"><span ng-if="!loading" trust-as-html="\'CURRENCY.VIEW.CURRENCY_SHORT_DESCRIPTION\'|translate:formData"></span></div></div></div><div class="row responsive-sm"><div class="col list"><div class="item item-divider"><span translate="">CURRENCY.VIEW.MONEY_DIVIDER</span></div><ng-include src="\'templates/currency/items_parameters.html\'"></ng-include></div><div class="col list"><div class="item item-divider"><span translate="">CURRENCY.VIEW.WOT_DIVIDER</span></div><ng-include src="\'templates/currency/items_wot.html\'"></ng-include></div></div></ion-content></ion-view>'); +$templateCache.put('templates/help/help.html','<a name="join"></a><h2 translate>HELP.JOIN.SECTION</h2><a name="join-salt"></a><div class="row responsive-sm" ng-class="itemsClass[\'join-salt\']"><div class="col col-20" translate>LOGIN.SALT</div><div class="col" translate>HELP.JOIN.SALT</div></div><a name="join-password"></a><div class="row responsive-sm" ng-class="itemsClass[\'join-password\']"><div class="col col-20" translate>LOGIN.PASSWORD</div><div class="col" translate>HELP.JOIN.PASSWORD</div></div><a name="join-pseudo"></a><div class="row responsive-sm" ng-class="itemsClass[\'join-pseudo\']"><div class="col col-20" translate>ACCOUNT.NEW.PSEUDO</div><div class="col" translate>HELP.JOIN.PSEUDO</div></div><a name="login"></a><h2 translate>HELP.LOGIN.SECTION</h2><a name="login-pubkey"></a><div class="row responsive-sm" ng-class="itemsClass[\'login-pubkey\']"><div class="col col-20" translate>HELP.LOGIN.PUBKEY</div><div class="col" translate>HELP.LOGIN.PUBKEY_DEF</div></div><a name="login-method"></a><div class="row responsive-sm" ng-class="itemsClass[\'login-method\']"><div class="col col-20" translate>HELP.LOGIN.METHOD</div><div class="col" translate>HELP.LOGIN.METHOD_DEF</div></div><a name="glossary"></a><h2 translate>HELP.GLOSSARY.SECTION</h2><a name="pubkey"></a><div class="row responsive-sm" ng-class="itemsClass.pubkey"><div class="col col-20" translate>COMMON.PUBKEY</div><div class="col" translate>HELP.GLOSSARY.PUBKEY_DEF</div></div><a name="blockchain"></a><div class="row responsive-sm" ng-class="itemsClass.blockchain"><div class="col col-20" translate>HELP.GLOSSARY.BLOCKCHAIN</div><div class="col" translate>HELP.GLOSSARY.BLOCKCHAIN_DEF</div></div><a name="universal_dividend"></a> <a name="ud"></a><div class="row responsive-sm" ng-class="itemsClass.ud"><div class="col col-20" translate>COMMON.UNIVERSAL_DIVIDEND</div><div class="col" translate>HELP.GLOSSARY.UNIVERSAL_DIVIDEND_DEF</div></div><a name="member"></a><div class="row responsive-sm" ng-class="itemsClass.member"><div class="col col-20" translate>HELP.GLOSSARY.MEMBER</div><div class="col" translate>HELP.GLOSSARY.MEMBER_DEF</div></div><a name="wot"></a><div class="row responsive-sm" ng-class="itemsClass.wot"><div class="col col-20" translate>HELP.GLOSSARY.WOT</div><div class="col" translate>HELP.GLOSSARY.WOT_DEF</div></div><a name="currency_rules"></a><div class="row responsive-sm" ng-class="itemsClass.currency_rules"><div class="col col-20" translate>HELP.GLOSSARY.CURRENCY_RULES</div><div class="col" translate>HELP.GLOSSARY.CURRENCY_RULES_DEF</div></div><a name="distance_rule"></a><div class="row responsive-sm" ng-class="itemsClass.distance_rule"><div class="col col-20" translate>HELP.GLOSSARY.DISTANCE_RULE</div><div class="col" translate>HELP.GLOSSARY.DISTANCE_RULE_DEF</div></div>'); +$templateCache.put('templates/help/modal_help.html','<ion-modal-view class="modal-full-height modal-help"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CLOSE</button><h1 class="title" translate>HELP.TITLE</h1></ion-header-bar><ion-content scroll="true" class="padding no-padding-xs"><div ng-class="listClass"><ng-include src="\'templates/help/help.html\'"></ng-include></div><div class="padding hidden-xs text-center"><button class="button button-positive ink" type="submit" ng-click="closeModal()">{{\'COMMON.BTN_CLOSE\' | translate}}</button></div></ion-content></ion-modal-view>'); +$templateCache.put('templates/help/view_help.html','<ion-view left-buttons="leftButtons"><ion-nav-title><span class="visible-xs visible-sm" translate="">HELP.TITLE</span></ion-nav-title><ion-content scroll="true" class="padding"><ng-include src="\'templates/help/help.html\'"></ng-include></ion-content></ion-view>'); +$templateCache.put('templates/home/home.html','<ion-view id="home" class=""><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"></ion-nav-buttons><ion-content class="has-header text-center no-padding-xs positive-900-bg circle-bg-dark"><div id="helptip-home-logo" class="logo"></div><h4><span class="hidden-xs" translate="">HOME.WELCOME</span> <b ng-show="!loading" translate-values=":currency:{currency: $root.currency.name}" translate="">HOME.MESSAGE</b></h4><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding animate-fade-in animate-show-hide ng-hide" ng-show="!loading && error"><div class="card card-item padding"><p class="item-content item-text-wrap"><span class="dark" trust-as-html="\'HOME.CONNECTION_ERROR\'|translate:node"></span></p><button type="button" class="button button-positive icon icon-left ion-refresh ink" ng-click="reload()">{{\'COMMON.BTN_REFRESH\'|translate}}</button></div></div><div class="center animate-fade-in animate-show-hide ng-hide" ng-show="!loading && !error"><button type="button" class="button button-block button-stable button-raised icon-left icon ion-easel ink-dark hidden-xs" ng-show="login" ng-click="startHelpTour()">{{\'COMMON.BTN_HELP_TOUR\'|translate}}</button> <button type="button" class="button button-block button-positive button-raised ink-dark" ng-click="showJoinModal()" ng-if="!login" translate="">LOGIN.CREATE_FREE_ACCOUNT</button> <button type="button" class="item button button-block button-positive button-raised icon icon-left ion-person ink-dark" ui-sref="app.view_wallet" ng-show="login" translate="">MENU.ACCOUNT</button> <button type="button" class="item button button-block button-positive button-raised icon icon-left ion-card ink-dark visible-xs" ui-sref="app.view_wallet_tx" ng-if="login" translate="">MENU.TRANSACTIONS</button><br class="visible-xs visible-sm"><div class="text-center no-padding" ng-show="!login"><br class="visible-xs visible-sm">{{\'LOGIN.HAVE_ACCOUNT_QUESTION\'|translate}} <b></b></div><div class="text-center no-padding" ng-show="login"><br class="visible-xs visible-sm"><span ng-bind-html="\'HOME.NOT_YOUR_ACCOUNT_QUESTION\'|translate:{pubkey: walletData.pubkey}"></span><br><b></b></div><button type="button" class="button button-block button-stable button-raised ink visible-xs visible-sm" ui-sref="app.view_wallet" ng-if="!login" translate="">COMMON.BTN_LOGIN</button> <button type="button" class="button button-block button-assertive button-raised icon icon-left ion-wand ink-dark visible-xs visible-sm" ng-click="logout()" ng-if="login" translate="">COMMON.BTN_LOGOUT</button><div class="text-center no-padding visible-xs stable"><br>{{\'COMMON.APP_VERSION\'|translate:{version: config.version} }} | <a href="#" ng-click="showAboutModal()" translate="">HOME.BTN_ABOUT</a></div></div></ion-content></ion-view>'); +$templateCache.put('templates/join/modal_choose_account_type.html','<ion-modal-view class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-if="!slides.slider.activeIndex" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button> <button class="button button-icon button-clear icon ion-ios-arrow-back buttons header-item" ng-click="slidePrev()" ng-if="slides.slider.activeIndex"></button><h1 class="title" translate="">ACCOUNT.NEW.TITLE</h1><button class="button button-clear icon-right visible-xs" ng-if="slides.slider.activeIndex === 0" ng-click="slideNext()"><span translate="">COMMON.BTN_NEXT</span> <i class="icon ion-ios-arrow-right"></i></button></ion-header-bar><ion-slides options="slides.options" slider="slides.slider"><ion-slide-page><ion-content class="has-header padding"><div class="center padding" ng-if="loading"><ion-spinner class="icon" icon="android"></ion-spinner></div><div ng-if="!loading"><p ng-bind-html="\'ACCOUNT.NEW.INTRO_WARNING_TIME\'|translate:currency"></p><div class="row responsive-sm"><div class="col"><div class="item card item-icon-left padding item-text-wrap stable-bg"><i class="icon ion-android-warning assertive"></i><p class="item-content item-icon-left-padding"><span class="dark" translate="">ACCOUNT.NEW.INTRO_WARNING_SECURITY</span><br><small translate="">ACCOUNT.NEW.INTRO_WARNING_SECURITY_HELP</small></p></div></div><div class="col"><div class="item card item-icon-left padding item-text-wrap stable-bg"><i class="icon ion-information-circled positive"></i><p class="item-content item-icon-left-padding"><span class="dark" trust-as-html="\'ACCOUNT.NEW.REGISTRATION_NODE\'|translate:currency.node"></span><br><small trust-as-html="\'ACCOUNT.NEW.REGISTRATION_NODE_HELP\'|translate:currency.node"></small></p></div></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate="">COMMON.BTN_CANCEL</button> <button class="button button-positive icon-right ion-chevron-right ink" ng-click="slideNext()" ng-disabled="loading" type="button" translate="">COMMON.BTN_START</button></div></ion-content></ion-slide-page><ion-slide-page><ion-content class="has-header padding"><p translate="">ACCOUNT.NEW.SELECT_ACCOUNT_TYPE</p><div class="list"><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="selectAccountTypeAndClose(\'member\')"><div class="item-content item-text-wrap"><i class="item-image icon dark ion-person"></i><h2 translate="">ACCOUNT.NEW.MEMBER_ACCOUNT</h2><h4 class="gray" ng-bind-html="\'ACCOUNT.NEW.MEMBER_ACCOUNT_HELP\'|translate:currency"></h4><i class="icon dark ion-ios-arrow-right"></i></div></div><cs-extension-point name="select-account-type"></cs-extension-point><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="selectAccountTypeAndClose(\'wallet\')"><div class="item-content item-text-wrap"><i class="item-image icon dark ion-card"></i><h2 translate="">ACCOUNT.NEW.WALLET_ACCOUNT</h2><h4 class="gray" translate="">ACCOUNT.NEW.WALLET_ACCOUNT_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate="">COMMON.BTN_CANCEL</button></div></ion-content></ion-slide-page></ion-slides></ion-modal-view>'); +$templateCache.put('templates/join/modal_join_member.html','<ion-modal-view class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-if="!slides.slider.activeIndex" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button> <button class="button button-icon button-clear icon ion-ios-arrow-back buttons header-item" ng-click="doPrev()" ng-if="slides.slider.activeIndex && slideBehavior.hasPreviousButton"></button> <button class="button button-icon button-clear icon ion-ios-help-outline visible-xs" ng-if="slideBehavior.helpAnchor" ng-click="showHelpModal(slideBehavior.helpAnchor)"></button><h1 class="title" translate>ACCOUNT.NEW.MEMBER_ACCOUNT_TITLE</h1><button class="button button-clear icon-right visible-xs" ng-if="slideBehavior.hasNextButton" ng-click="doNext()"><span translate>COMMON.BTN_NEXT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-clear icon-right visible-xs" ng-class="{\'button-text-stable\': !isLicenseRead}" ng-if="slideBehavior.hasAcceptButton" ng-click="isLicenseRead ? doNext() : undefined"><span translate>ACCOUNT.NEW.BTN_ACCEPT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-clear icon-right visible-xs" ng-if="slideBehavior.hasSendButton" ng-click="doNewAccount()"><i class="icon ion-android-send"></i></button></ion-header-bar><ion-slides options="slides.options" slider="slides.slider"><ion-slide-page ng-if="licenseFileUrl"><ion-content class="has-header" scroll="false"><div class="padding" translate>ACCOUNT.NEW.INFO_LICENSE</div><div class="center padding" ng-if="loading"><ion-spinner class="icon" icon="android"></ion-spinner></div><iframe ng-if="!loading" class="padding-left padding-right no-padding-xs iframe-license" id="iframe-license" ng-src="{{licenseFileUrl}}"></iframe><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" ng-click="doNext(\'licenceForm\')" ng-disabled="!isLicenseRead" type="button" translate>ACCOUNT.NEW.BTN_ACCEPT_LICENSE</button></div></ion-content></ion-slide-page><ion-slide-page><ion-content class="has-header" scroll="true"><form name="pseudoForm" novalidate="" ng-submit="doNext(\'pseudoForm\')"><div class="item item-text-wrap text-center padding"><a class="pull-right icon-help hidden-xs" ng-click="showHelpModal(\'join-pseudo\')"></a> <span translate>ACCOUNT.NEW.PSEUDO_WARNING</span></div><div class="list" ng-init="setForm(pseudoForm, \'pseudoForm\')"><div class="item item-input" ng-class="{\'item-input-error\': (pseudoForm.$submitted && pseudoForm.pseudo.$invalid) || (uiAlreadyUsed && formData.pseudo)}"><span class="input-label" translate>ACCOUNT.NEW.PSEUDO</span> <input id="pseudo" name="pseudo" type="text" placeholder="{{\'ACCOUNT.NEW.PSEUDO_HELP\' | translate}}" ng-model="formData.pseudo" autocomplete="off" ng-minlength="3" ng-maxlength="100" ng-pattern="userIdPattern" ng-model-options="{ debounce: 250 }" required></div><div class="form-errors" ng-show="pseudoForm.$submitted && pseudoForm.pseudo.$error" ng-messages="pseudoForm.pseudo.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT_WITH_LENGTH" translate-values="{minLength: 3}"></span></div><div class="form-error" ng-message="maxlength"><span translate="ERROR.FIELD_TOO_LONG_WITH_LENGTH" translate-values="{maxLength: 100}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="pattern"><span translate="ERROR.INVALID_USER_ID"></span></div></div><div class="text-right" style="min-height: 18px"><div class="form-error gray" ng-if="formData.computing && formData.pseudo"><ion-spinner class="icon ion-spinner-small" icon="android" ng-if="formData.computing && formData.pseudo"></ion-spinner><span translate>ACCOUNT.NEW.CHECKING_PSEUDO</span></div><ng-if ng-if="!formData.computing && formData.pseudo"><div class="form-error balanced" ng-if="!uiAlreadyUsed "><i class="icon ion-checkmark balanced"></i> <span translate>ACCOUNT.NEW.PSEUDO_AVAILABLE</span></div><div class="form-error" ng-if="uiAlreadyUsed"><i class="icon ion-close-circled assertive"></i> <span translate>ACCOUNT.NEW.PSEUDO_NOT_AVAILABLE</span></div></ng-if></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" ng-disabled="uiAlreadyUsed" translate>COMMON.BTN_NEXT</button></div></div></form></ion-content></ion-slide-page><ion-slide-page ng-if="!formData.pubkey"><ion-content class="has-header" scroll="true"><form name="saltForm" novalidate="" ng-submit="doNext(\'saltForm\')"><div class="list" ng-init="setForm(saltForm, \'saltForm\')"><div class="item item-text-wrap text-center padding hidden-xs"><a class="pull-right icon-help" ng-click="showHelpModal(\'join-salt\')"></a> <span translate>ACCOUNT.NEW.SALT_WARNING</span></div><div class="item item-input" ng-class="{ \'item-input-error\': saltForm.$submitted && saltForm.username.$invalid}"><span class="input-label" translate>LOGIN.SALT</span> <input ng-if="!showUsername" name="username" type="password" placeholder="{{\'LOGIN.SALT_HELP\' | translate}}" ng-change="formDataChanged()" ng-model="formData.username" autocomplete="off" ng-minlength="8" different-to="formData.pseudo" required> <input ng-if="showUsername" name="username" type="text" placeholder="{{\'LOGIN.SALT_HELP\' | translate}}" ng-change="formDataChanged()" ng-model="formData.username" autocomplete="off" ng-minlength="8" different-to="formData.pseudo" required></div><div class="form-errors" ng-show="saltForm.$submitted && saltForm.username.$error" ng-messages="saltForm.username.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT_WITH_LENGTH" translate-values="{minLength: 8}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="differentTo"><span translate="ERROR.EQUALS_TO_PSEUDO"></span></div></div><div class="item item-input" ng-class="{ \'item-input-error\': saltForm.$submitted && saltForm.confirmSalt.$invalid}"><span class="input-label pull-right" translate>ACCOUNT.NEW.SALT_CONFIRM</span> <input ng-if="!showUsername" name="confirmUsername" type="password" placeholder="{{\'ACCOUNT.NEW.SALT_CONFIRM_HELP\' | translate}}" ng-model="formData.confirmUsername" autocomplete="off" compare-to="formData.username"> <input ng-if="showUsername" name="confirmUsername" type="text" placeholder="{{\'ACCOUNT.NEW.SALT_CONFIRM_HELP\' | translate}}" ng-model="formData.confirmUsername" autocomplete="off" compare-to="formData.username"></div><div class="form-errors" ng-show="saltForm.$submitted && saltForm.confirmUsername.$error" ng-messages="saltForm.confirmUsername.$error"><div class="form-error" ng-message="compareTo"><span translate="ERROR.SALT_NOT_CONFIRMED"></span></div></div><div class="item item-toggle dark"><span translate>COMMON.SHOW_VALUES</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="showUsername"><div class="track"><div class="handle"></div></div></label></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" translate>COMMON.BTN_NEXT <i class="icon ion-arrow-right-a"></i></button></div></div></form></ion-content></ion-slide-page><ion-slide-page ng-if="!formData.pubkey"><ion-content class="has-header" scroll="true"><form name="passwordForm" novalidate="" ng-submit="doNext(\'passwordForm\')"><div class="item item-text-wrap text-center padding hidden-xs"><a class="pull-right icon-help" ng-click="showHelpModal(\'join-password\')"></a> <span translate>ACCOUNT.NEW.PASSWORD_WARNING</span></div><div class="list" ng-init="setForm(passwordForm, \'passwordForm\')"><div class="item item-input" ng-class="{ \'item-input-error\': passwordForm.$submitted && passwordForm.password.$invalid}"><span class="input-label" translate>LOGIN.PASSWORD</span> <input ng-if="!showPassword" name="password" type="password" placeholder="{{\'LOGIN.PASSWORD_HELP\' | translate}}" ng-model="formData.password" autocomplete="off" ng-change="formDataChanged()" ng-minlength="8" different-to="formData.username" required> <input ng-if="showPassword" name="text" type="text" placeholder="{{\'LOGIN.PASSWORD_HELP\' | translate}}" ng-model="formData.password" autocomplete="off" ng-change="formDataChanged()" ng-minlength="8" different-to="formData.username" required></div><div class="form-errors" ng-show="passwordForm.$submitted && passwordForm.password.$error" ng-messages="passwordForm.password.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT_WITH_LENGTH" translate-values="{minLength: 8}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="differentTo"><span translate="ERROR.EQUALS_TO_SALT"></span></div></div><div class="item item-input" ng-class="{ \'item-input-error\': passwordForm.$submitted && passwordForm.confirmPassword.$invalid}"><span class="input-label" translate>ACCOUNT.NEW.PASSWORD_CONFIRM</span> <input ng-if="!showPassword" name="confirmPassword" type="password" placeholder="{{\'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP\' | translate}}" ng-model="formData.confirmPassword" autocomplete="off" compare-to="formData.password"> <input ng-if="showPassword" name="confirmPassword" type="text" placeholder="{{\'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP\' | translate}}" ng-model="formData.confirmPassword" autocomplete="off" compare-to="formData.password"></div><div class="form-errors" ng-show="passwordForm.$submitted && passwordForm.confirmPassword.$error" ng-messages="passwordForm.confirmPassword.$error"><div class="form-error" ng-message="compareTo"><span translate="ERROR.PASSWORD_NOT_CONFIRMED"></span></div></div><div class="item item-toggle dark"><span translate>COMMON.SHOW_VALUES</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="showPassword"><div class="track"><div class="handle"></div></div></label></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" ng-click="getRevocationDocument()" translate>COMMON.BTN_NEXT</button></div><div class="padding hidden-xs"></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class="has-header" scroll="true"><div class="center padding" ng-if="formData.computing"><ion-spinner icon="android"></ion-spinner></div><ng-if ng-if="!formData.computing"><div class="animate-fade-in animate-show-hide ng-hide" ng-show="accountAvailable"><div class="padding text-center" translate>ACCOUNT.NEW.LAST_SLIDE_CONGRATULATION</div><div class="list"><ion-item class="item text-center item-text-wrap"><h3 class="gray" translate>LOGIN.ASSOCIATED_PUBKEY</h3><h3 class="dark bold">{{formData.pubkey}}</h3></ion-item></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" ng-click="doNewAccount()" translate>COMMON.BTN_SEND <i class="icon ion-android-send"></i></button></div></div><div class="animate-fade-in animate-show-hide ng-hide" ng-show="!accountAvailable"><ion-item class="item-icon-left item-text-wrap text-center"><i class="icon ion-minus-circled assertive"></i> <span id="modal-license" trust-as-html="\'ERROR.EXISTING_ACCOUNT\'|translate"></span></ion-item><div class="list"><ion-item class="item item-text-wrap item-border"><div class="padding text-center"><span class="gray text-no-wrap">{{formData.pubkey}}</span></div></ion-item><div class="padding text-center"><span translate>ERROR.EXISTING_ACCOUNT_REQUEST</span></div></div><div class="padding hidden-xs text-left"><button class="button button-assertive icon-left ion-chevron-left ink" ng-click="identifierRecovery()" translate>COMMON.BTN_MODIFY</button></div></div></ng-if></ion-content></ion-slide-page></ion-slides></ion-modal-view>'); +$templateCache.put('templates/join/modal_join_wallet.html','<ion-modal-view class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-if="!slides.slider.activeIndex" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button> <button class="button button-icon button-clear icon ion-ios-arrow-back buttons header-item" ng-click="slidePrev()" ng-if="slideBehavior.hasPreviousButton"></button> <button class="button button-icon button-clear icon ion-ios-help-outline visible-xs" ng-if="slideBehavior.helpAnchor" ng-click="showHelpModal(slideBehavior.helpAnchor)"></button><h1 class="title" translate>ACCOUNT.NEW.WALLET_ACCOUNT_TITLE</h1><button class="button button-clear icon-right visible-xs" ng-if="slideBehavior.hasNextButton" ng-click="doNext()"><span translate>COMMON.BTN_NEXT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-clear icon-right visible-xs" ng-if="slideBehavior.hasSendButton" ng-click="doNewAccount()"><i class="icon ion-android-send"></i></button></ion-header-bar><ion-slides options="slides.options" slider="slides.slider"><ion-slide-page><ion-content class="has-header" scroll="false"><form name="saltForm" novalidate="" ng-submit="doNext(\'saltForm\')"><div class="list" ng-init="setForm(saltForm, \'saltForm\')"><div class="item item-text-wrap text-center padding hidden-xs"><a class="pull-right icon-help" ng-click="showHelpModal(\'join-salt\')"></a> <span translate>ACCOUNT.NEW.SALT_WARNING</span></div><div class="item item-input" ng-class="{ \'item-input-error\': saltForm.$submitted && saltForm.username.$invalid}"><span class="input-label" translate>LOGIN.SALT</span> <input ng-if="!showUsername" name="username" type="password" placeholder="{{\'LOGIN.SALT_HELP\' | translate}}" ng-change="formDataChanged()" ng-model="formData.username" ng-minlength="8" required> <input ng-if="showUsername" name="username" type="text" placeholder="{{\'LOGIN.SALT_HELP\' | translate}}" ng-change="formDataChanged()" ng-model="formData.username" ng-minlength="8" required></div><div class="form-errors" ng-show="saltForm.$submitted && saltForm.username.$error" ng-messages="saltForm.username.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT_WITH_LENGTH" translate-values="{minLength: 8}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-input" ng-class="{ \'item-input-error\': saltForm.$submitted && saltForm.confirmSalt.$invalid}"><span class="input-label pull-right" translate>ACCOUNT.NEW.SALT_CONFIRM</span> <input ng-if="!showUsername" name="confirmUsername" type="password" placeholder="{{\'ACCOUNT.NEW.SALT_CONFIRM_HELP\' | translate}}" ng-model="formData.confirmUsername" compare-to="formData.username"> <input ng-if="showUsername" name="confirmUsername" type="text" placeholder="{{\'ACCOUNT.NEW.SALT_CONFIRM_HELP\' | translate}}" ng-model="formData.confirmUsername" compare-to="formData.username"></div><div class="form-errors" ng-show="saltForm.$submitted && saltForm.confirmUsername.$error" ng-messages="saltForm.confirmUsername.$error"><div class="form-error" ng-message="compareTo"><span translate="ERROR.SALT_NOT_CONFIRMED"></span></div></div><div class="item item-toggle dark"><span translate>COMMON.SHOW_VALUES</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="showUsername"><div class="track"><div class="handle"></div></div></label></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" translate>COMMON.BTN_NEXT <i class="icon ion-arrow-right-a"></i></button></div></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class="has-header" scroll="false"><form name="passwordForm" novalidate="" ng-submit="doNext(\'passwordForm\')"><div class="item item-text-wrap text-center padding hidden-xs"><a class="pull-right icon-help" ng-click="showHelpModal(\'join-password\')"></a> <span translate>ACCOUNT.NEW.PASSWORD_WARNING</span></div><div class="list" ng-init="setForm(passwordForm, \'passwordForm\')"><div class="item item-input" ng-class="{ \'item-input-error\': passwordForm.$submitted && passwordForm.password.$invalid}"><span class="input-label" translate>LOGIN.PASSWORD</span> <input ng-if="!showPassword" name="password" type="password" placeholder="{{\'LOGIN.PASSWORD_HELP\' | translate}}" ng-model="formData.password" ng-change="formDataChanged()" ng-minlength="8" required> <input ng-if="showPassword" name="text" type="text" placeholder="{{\'LOGIN.PASSWORD_HELP\' | translate}}" ng-model="formData.password" ng-change="formDataChanged()" ng-minlength="8" required></div><div class="form-errors" ng-show="passwordForm.$submitted && passwordForm.password.$error" ng-messages="passwordForm.password.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT_WITH_LENGTH" translate-values="{minLength: 8}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-input" ng-class="{ \'item-input-error\': passwordForm.$submitted && passwordForm.confirmPassword.$invalid}"><span class="input-label" translate>ACCOUNT.NEW.PASSWORD_CONFIRM</span> <input ng-if="!showPassword" name="confirmPassword" type="password" placeholder="{{\'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP\' | translate}}" ng-model="formData.confirmPassword" compare-to="formData.password"> <input ng-if="showPassword" name="confirmPassword" type="text" placeholder="{{\'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP\' | translate}}" ng-model="formData.confirmPassword" compare-to="formData.password"></div><div class="form-errors" ng-show="passwordForm.$submitted && passwordForm.confirmPassword.$error" ng-messages="passwordForm.confirmPassword.$error"><div class="form-error" ng-message="compareTo"><span translate="ERROR.PASSWORD_NOT_CONFIRMED"></span></div></div><div class="item item-toggle dark"><span translate>COMMON.SHOW_VALUES</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="showPassword"><div class="track"><div class="handle"></div></div></label></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" translate>COMMON.BTN_NEXT</button></div><div class="padding hidden-xs"></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class="has-header" scroll="false"><div class="padding center" ng-if="formData.computing"><ion-spinner icon="android"></ion-spinner></div><div ng-if="accountAvailable && !formData.computing"><div class="padding text-center" translate>ACCOUNT.NEW.LAST_SLIDE_CONGRATULATION</div><div class="list"><ion-item class="item item-text-wrap item-border"><div class="dark pull-right padding-right" ng-if="formData.computing"><ion-spinner icon="android"></ion-spinner></div><span class="input-label" translate>COMMON.PUBKEY</span> <span class="gray text-no-wrap" ng-if="formData.computing" translate>ACCOUNT.NEW.COMPUTING_PUBKEY </span><span class="gray text-no-wrap" ng-if="formData.pubkey">{{formData.pubkey}}</span></ion-item></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" ng-click="doNewAccount()" translate>COMMON.BTN_CREATE</button></div></div><div ng-if="!accountAvailable && !formData.computing"><ion-item class="item-icon-left item-text-wrap text-center"><i class="icon ion-android-close active"></i> <span id="modal-license" translate>ERROR.EXISTING_ACCOUNT</span></ion-item><div class="list"><ion-item class="item item-text-wrap item-border"><div class="dark pull-right padding-right" ng-if="formData.computing"><ion-spinner icon="android"></ion-spinner></div><span class="gray text-no-wrap" ng-if="formData.computing" translate>ACCOUNT.NEW.COMPUTING_PUBKEY</span><div class="padding text-center"><span class="gray text-no-wrap" ng-if="formData.pubkey">{{formData.pubkey}}</span></div></ion-item><div class="padding text-center"><span translate>ERROR.EXISTING_ACCOUNT_REQUEST</span></div></div><div class="padding hidden-xs text-left"><button class="button button-assertive icon-left ion-chevron-left ink" ng-click="identifierRecovery()" translate>COMMON.BTN_MODIFY</button></div></div></ion-content></ion-slide-page></ion-slides></ion-modal-view>'); +$templateCache.put('templates/login/form_file_import.html','<div class="item"><p class="item-text-wrap" translate>LOGIN.FILE_FORM_HELP</p></div><div class="item item-icon-left item-text-wrap"><i class="icon ion-ios-information-outline positive"></i> <span class="positive" translate>LOGIN.FILE.HELP</span></div><div dropzone="onKeyFileDrop(file)"><div ng-if="!formData.file" onclick="angular.element(document.querySelector(\'#loginImportFile\'))[0].click();"><h2 class="gray" translate>COMMON.CHOOSE_FILE</h2><input type="file" id="loginImportFile" accept=".dunikey,.yml" style="visibility:hidden; position:absolute" onchange="angular.element(this).scope().fileChanged(event)"></div><div class="item item-icon-left item-icon-right stable-bg" ng-if="formData.file"><i class="icon ion-document-text dark"></i><div class="item-content row"><div class="col"><h2>{{formData.file.name}}</h2><h4 class="dark" ng-if="formData.file.lastModified"><span class="gray" translate>COMMON.FILE.DATE</span> {{formData.file.lastModified/1000|formatDate}}</h4><h5 class="dark"><span class="gray" translate>COMMON.FILE.SIZE</span> {{formData.file.size|formatInteger}} Ko</h5></div><div class="col"><h3><span class="gray" translate>COMMON.PUBKEY</span></h3><h3 ng-if="validatingFile" translate>COMMON.FILE.VALIDATING</h3><h3 ng-if="!validatingFile"><span class="dark animate-show-hide ng-hide" ng-show="formData.file.pubkey">{{formData.file.pubkey}}</span> <span class="assertive animate-show-hide ng-hide" ng-show="!formData.file.valid"><br><i class="ion-close-circled assertive"></i> {{formData.file.pubkey ? \'ERROR.AUTH_INVALID_PUBKEY\' : \'ERROR.AUTH_INVALID_FILE\' |translate}}</span></h3></div></div><a class="ion-close-round gray pull-right" style="font-size: 10px; position: absolute; top: 6px; right: 6px" ng-click="removeKeyFile()"></a></div></div><ion-checkbox ng-model="formData.keepAuth" class="item ink item-text-wrap"><div class="item-content dark" translate>LOGIN.MEMORIZE_AUTH_FILE</div></ion-checkbox>'); +$templateCache.put('templates/login/form_login.html','<form name="loginForm" novalidate="" ng-submit="doLogin()" autocomplete="off"><div class="list padding no-padding-xs" ng-init="setForm(loginForm)" ng-switch on="formData.method"><div class="item hidden-xs no-padding" ng-if="showMethods"><div class="pull-right"><a class="button button-text button-small-padding icon-right ink" ng-click="showMethodsPopover($event)"><i class="icon ion-wrench"></i> {{\'LOGIN.BTN_METHODS\'| translate}} </a> <a class="button button-icon positive button-small-padding icon ion-ios-help-outline" style="right: 8px" ng-click="showHelpModal(\'login-method\')"></a></div></div><div class="item item-text-wrap" ng-if="::isAuth"><p ng-if="::expectedPubkey" ng-bind-html="::expectedUid ? \'AUTH.EXPECTED_UID_HELP\' : \'AUTH.EXPECTED_PUBKEY_HELP\' |translate: {uid: expectedUid, pubkey: expectedPubkey}"></p><p ng-if="::!expectedPubkey" ng-bind-html="::\'AUTH.GENERAL_HELP\'|translate"></p></div><div ng-switch-when="SCRYPT_DEFAULT"><ng-include src="\'templates/login/form_scrypt.html\'"></ng-include></div><div ng-switch-when="SCRYPT_ADVANCED"><ng-include src="\'templates/login/form_scrypt_advanced.html\'"></ng-include></div><div ng-switch-when="PUBKEY"><ng-include src="\'templates/login/form_pubkey.html\'"></ng-include></div><div ng-switch-when="FILE"><ng-include src="\'templates/login/form_file_import.html\'"></ng-include></div><div ng-switch-when="SCAN"><ng-include src="\'templates/login/form_scan.html\'"></ng-include></div><div ng-switch-default><ng-include src="\'templates/login/form_scrypt.html\'"></ng-include></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" ng-class="{\'button-assertive\': isAuth, \'button-positive\': !isAuth}" type="submit">{{okText || (isAuth ? \'AUTH.BTN_AUTH\' : \'COMMON.BTN_LOGIN\') | translate}}</button></div><div class="text-center no-padding visible-xs"><button type="button" class="button button-small icon-right ink" ng-click="showMethodsPopover($event)"><i class="icon ion-loop"></i> <span translate>LOGIN.BTN_METHODS_DOTS</span></button><br><br></div><ng-if ng-if="!isAuth && showNewAccountLink"><div class="text-center no-padding">{{\'LOGIN.NO_ACCOUNT_QUESTION\'|translate}}<br class="visible-xs"><a ng-click="showJoinModal()" translate>LOGIN.CREATE_ACCOUNT</a></div><br class="visible-xs"><div class="text-center no-padding"><a ng-click="showAccountSecurityModal()" translate>LOGIN.FORGOTTEN_ID</a></div></ng-if></form>'); +$templateCache.put('templates/login/form_pubkey.html','<div class="item"><p class="item-text-wrap" translate>LOGIN.PUBKEY_FORM_HELP</p></div><div class="item item-input item-button-right" ng-class="{ \'item-input-error\': form.$submitted && form.pubkey.$invalid}"><span class="input-label hidden-xs" translate>COMMON.PUBKEY</span> <input name="pubkey" type="text" placeholder="{{\'LOGIN.PUBKEY_HELP\' | translate}}" autocomplete="off" ng-model="formData.pubkey" ng-model-options="{ debounce: 650 }" required> <a class="button button-stable icon ion-android-search ink" ng-click="showWotLookupModal(form.pubkey.$viewValue)"></a></div><div class="form-errors" ng-show="form.$submitted && form.pubkey.$error" ng-messages="form.pubkey.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="checksum"><span translate="ERROR.INVALID_PUBKEY_CHECKSUM"></span></div></div>'); +$templateCache.put('templates/login/form_scan.html','<div class="item"><p class="item-text-wrap" ng-bind-html="::isAuth ? \'AUTH.SCAN_FORM_HELP\' : \'LOGIN.SCAN_FORM_HELP\' |translate"></p></div><div class="item item-icon-right item-text-wrap item-input" ng-class="{ \'item-input-error\': pubkeyError}"><span class="input-label" translate>COMMON.PUBKEY</span><div class="item-content text-wrap"><span class="gray animate-show-hide" ng-show="!computing && formData.pubkey">{{formData.pubkey}}</span><ion-spinner class="ion-spinner-small" icon="android" ng-if="computing"></ion-spinner><input type="hidden" ng-model="formData.pubkey" required></div><a class="button button-icon positive button-small-padding icon ion-qr-scanner animate-show-hide" ng-show="!computing && (!expectedPubkey || pubkeyError)" ng-click="doScan()"></a> <span class="button button-icon balanced button-small-padding icon ion-checkmark animate-show-hide" ng-if="expectedPubkey" ng-show="!computing && !pubkeyError"></span></div><div class="form-errors" ng-if="expectedPubkey"><div class="form-error" ng-show="pubkeyError"><span trust-as-html="::\'ERROR.AUTH_INVALID_PUBKEY\'|translate:{pubkey: expectedPubkey}"></span></div></div>'); +$templateCache.put('templates/login/form_scrypt.html','<div class="item item-text-wrap" ng-if="!isAuth"><p ng-bind-html="\'LOGIN.SCRYPT_FORM_HELP\'|translate"></p></div><input type="password" name="fake-password" autocomplete="off" style="visibility:hidden; position:absolute"><label class="item item-input" ng-class="{ \'item-input-error\': form.$submitted && form.username.$invalid}"><span class="input-label hidden-xs" translate>LOGIN.SALT</span> <input name="username" type="password" placeholder="{{\'LOGIN.SALT_HELP\' | translate}}" autocomplete="off" ng-model="formData.username" ng-model-options="{ debounce: 650 }" class="highlight-light" required></label><div class="form-errors" ng-show="form.$submitted && form.username.$error" ng-messages="form.username.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><label class="item item-input" ng-class="{ \'item-input-error\': form.$submitted && form.password.$invalid}"><span class="input-label hidden-xs" translate>LOGIN.PASSWORD</span> <input name="password" type="password" placeholder="{{\'LOGIN.PASSWORD_HELP\' | translate}}" autocomplete="off" ng-model="formData.password" ng-model-options="{ debounce: 650 }" select-on-click required></label><div class="form-errors" ng-show="form.$submitted && form.password.$error" ng-messages="form.password.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-icon-right item-text-wrap" ng-class="{ \'item-input-error\': pubkeyError, \'item-input\': showPubkey}"><span class="input-label hidden-xs animate-show-hide ng-hide" ng-show="showPubkey" translate>COMMON.PUBKEY</span><div class="item-content text-wrap"><a class="positive ink animate-show-hide ng-hide" ng-show="showComputePubkeyButton && !pubkey" ng-click="computePubkey()"><i class="ion-eye"></i> {{\'COMMON.BTN_SHOW_PUBKEY\' | translate}} </a><span class="gray animate-show-hide" ng-show="!computing && pubkey">{{pubkey}}</span><ion-spinner class="ion-spinner-small" icon="android" ng-if="computing"></ion-spinner></div><a class="button button-icon positive button-small-padding icon ion-ios-help-outline animate-show-hide" ng-click="showHelpModal(\'login-pubkey\')" ng-if="!expectedPubkey" ng-show="showPubkey"></a> <span class="button button-icon balanced button-small-padding icon ion-checkmark animate-show-hide" ng-if="expectedPubkey" ng-show="showPubkey && !showComputePubkeyButton && !computing && !pubkeyError"></span></div><div class="form-errors" ng-if="expectedPubkey"><div class="form-error" ng-show="pubkeyError"><span trust-as-html="::\'ERROR.AUTH_INVALID_PUBKEY\'|translate:{pubkey: expectedPubkey}"></span></div></div>'); +$templateCache.put('templates/login/form_scrypt_advanced.html','<div class="row responsive-md responsive-sm padding-left"><div class="col col-33 no-padding"><label class="item item-input item-select"><select ng-model="formData.scrypt" style="max-width: 100%" ng-change="changeScrypt(formData.scrypt)" ng-options="l as (l.label | translate) for l in scryptParamsValues track by l.id"></select></label></div><div class="col no-padding"><label class="item item-input"><span class="input-label" translate>LOGIN.SCRYPT.N</span> <input class="no-padding-right" type="number" placeholder="N" autocomplete="off" ng-model="formData.scrypt.params.N" ng-model-options="{ debounce: 650 }" ng-change="onScryptFormChanged()" required></label></div><div class="col no-padding"><label class="item item-input"><span class="input-label" translate>LOGIN.SCRYPT.r</span> <input class="no-padding-right" type="number" placeholder="r" ng-model="formData.scrypt.params.r" autocomplete="off" ng-model-options="{ debounce: 650 }" ng-change="onScryptFormChanged()" required></label></div><div class="col no-padding"><label class="item item-input"><span class="input-label" translate>LOGIN.SCRYPT.p</span> <input class="no-padding-right" type="number" placeholder="p" autocomplete="off" ng-model="formData.scrypt.params.p" ng-model-options="{ debounce: 650 }" ng-change="onScryptFormChanged()" required></label></div></div><p class="energized-100-bg padding dark"><i class="icon ion-android-warning"></i> <span translate>INFO.FEATURES_NOT_IMPLEMENTED</span></p><ng-include src="\'templates/login/form_scrypt.html\'"></ng-include>'); +$templateCache.put('templates/login/item_remember_me.html','<ion-checkbox ng-model="formData.rememberMe" ng-if="!isAuth" class="item ink item-text-wrap"><div class="item-content dark" translate>SETTINGS.REMEMBER_ME</div></ion-checkbox>'); +$templateCache.put('templates/login/modal_login.html','<ion-modal-view class="modal-full-height modal-login"><ion-header-bar class="" ng-class="{\'bar-positive\': !isAuth, \'bar-assertive\': isAuth}"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" ng-bind-html="title | translate"></h1><div class="buttons buttons-right"><div class="secondary-buttons"><button class="button button-icon button-clear icon ion-android-done visible-xs" ng-class="{\'button-positive\': !isAuth}" style="color: #fff" ng-click="doLogin()"></button></div></div></ion-header-bar><ion-content scroll="true"><ng-include src="\'templates/login/form_login.html\'"></ng-include></ion-content></ion-modal-view>'); +$templateCache.put('templates/login/popover_methods.html','<ion-popover-view class="fit has-header popover-login-methods" ng-class="{\'auth\': isAuth}"><ion-header-bar><h1 class="title" translate="">LOGIN.METHOD_POPOVER_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-click="changeMethod(\'SCRYPT_DEFAULT\')"><i class="icon ion-shuffle" style="font-size: 22px"></i> {{\'LOGIN.METHOD.SCRYPT_DEFAULT\' | translate}} </a><a class="item item-icon-left ink" ng-click="changeMethod(\'SCRYPT_ADVANCED\')"><i class="icon ion-shuffle" style="font-size: 22px"></i> <i class="icon-secondary ion-plus" style="font-size: 13px; left: 40px; margin-top: -4px"></i> {{\'LOGIN.METHOD.SCRYPT_ADVANCED\' | translate}} </a><a class="item item-icon-left ink hidden-xs" ng-click="changeMethod(\'FILE\')"><i class="icon ion-document-text"></i> {{\'LOGIN.METHOD.FILE\' | translate}} </a><a class="item item-icon-left ink" ng-if="$root.device.barcode.enable" ng-click="changeMethod(\'SCAN\')"><i class="icon ion-qr-scanner"></i> {{\'LOGIN.METHOD.SCAN\' | translate}} </a><a class="item item-icon-left ink" ng-if="!isAuth" ng-click="changeMethod(\'PUBKEY\')"><i class="icon ion-key"></i> {{\'LOGIN.METHOD.PUBKEY\' | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/network/item_content_peer.html','<i class="icon ion-android-desktop" ng-class=":rebind:{\'balanced\': peer.online && peer.hasMainConsensusBlock, \'energized\': peer.online && peer.hasConsensusBlock, \'gray\': peer.online && !peer.hasConsensusBlock && !peer.hasMainConsensusBlock, \'stable\': !peer.online}" ng-if=":rebind:!peer.avatar"></i> <b class="icon-secondary ion-person" ng-if=":rebind:!peer.avatar" ng-class=":rebind:{\'balanced\': peer.online && peer.hasMainConsensusBlock, \'energized\': peer.online && peer.hasConsensusBlock, \'gray\': peer.online && !peer.hasConsensusBlock && !peer.hasMainConsensusBlock, \'stable\': !peer.online}" style="left: 26px; top: -3px"></b> <i class="avatar" ng-if=":rebind:peer.avatar" style="background-image: url(\'{{:rebind:peer.avatar.src}}\')"></i> <b class="icon-secondary assertive ion-close-circled" ng-if=":rebind:!peer.online" style="left: 37px; top: -10px"></b><div class="row no-padding"><div class="col no-padding"><h3 class="dark" ng-if=":rebind:!peer.bma.private">{{:rebind:peer.dns || peer.server}}</h3><h4 class="gray" ng-if=":rebind:peer.bma.private"><i class="ion-flash"></i> {{\'NETWORK.VIEW.PRIVATE_ACCESS\'|translate}}</h4><h4><span class="gray" ng-if=":rebind:!peer.uid"><i class="ion-key"></i> {{:rebind:peer.pubkey|formatPubkey}} </span><span class="positive" ng-if=":rebind:peer.uid"><i class="ion-person"></i> {{:rebind:peer.name || peer.uid}} </span><span class="gray" ng-if=":rebind:!compactMode">{{:rebind:peer.dns && (\' | \' + peer.server) + (peer.bma.path||\'\') }}</span></h4></div><div class="col col-20 no-padding text-center" ng-if="::expertMode && search.type != \'offline\'"></div><div class="col col-20 no-padding text-center"><span id="{{$index === 0 ? helptipPrefix + \'-peer-0-block\' : \'\'}}" class="badge" ng-class=":rebind:{\'badge-balanced\': peer.hasMainConsensusBlock, \'badge-energized\': peer.hasConsensusBlock, \'ng-hide\': !peer.currentNumber && !peer.blockNumber }">{{::!expertMode ? (\'COMMON.BLOCK\'|translate) : \'\' }} {{:rebind:(peer.currentNumber || peer.blockNumber) | formatInteger}}</span> <span class="badge badge-secondary" ng-if=":rebind:peer.consensusBlockDelta && expertMode"><i class="ion-clock"></i> {{:rebind:peer.consensusBlockDelta|formatDurationTime}}</span></div></div>'); +$templateCache.put('templates/network/items_peers.html','<div class="no-padding {{::motion.ionListClass}}"><div class="item item-text-wrap no-border done in gray no-padding-top no-padding-bottom inline text-italic" ng-if="::isHttps && expertMode"><small><i class="icon ion-alert-circled"></i> {{\'NETWORK.INFO.ONLY_SSL_PEERS\'|translate}}</small></div><div ng-repeat="peer in :rebind:search.results track by peer.id" class="item item-peer item-icon-left ink {{::ionItemClass}}" ng-class=":rebind:{\'compacted\': peer.compacted && compactMode}" id="{{::helptipPrefix}}-peer-{{::$index}}" ng-click="selectPeer(peer)" ng-include="::\'templates/network/item_content_peer.html\'"></div></div>'); +$templateCache.put('templates/network/lookup_popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>PEER.POPOVER_FILTER_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left item-icon-right ink" ng-click="toggleSearchType(\'member\')"><i class="icon ion-person"></i> {{\'PEER.MEMBERS\' | translate}} <i class="icon ion-ios-checkmark-empty" ng-show="search.type==\'member\'"></i> </a><a class="item item-icon-left item-icon-right ink" ng-click="toggleSearchType(\'mirror\')"><i class="icon ion-radio-waves"></i> {{\'PEER.MIRRORS\' | translate}} <i class="icon ion-ios-checkmark-empty" ng-show="search.type==\'mirror\'"></i> </a><a class="item item-icon-left item-icon-right ink" ng-click="toggleSearchType(\'offline\')"><i class="icon ion-eye-disabled"></i> {{\'PEER.OFFLINE\' | translate}} <i class="icon ion-ios-checkmark-empty" ng-show="search.type==\'offline\'"></i></a></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/network/modal_network.html','<ion-modal-view id="nodes" class="modal-full-height" cache-view="false"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button><h1 class="title" translate="">PEER.PEER_LIST</h1><div class="buttons buttons-right header-item"><span class="secondary"><button class="button button-clear icon ion-loop button-clear" ng-click="refresh()"></button> <button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></span></div></ion-header-bar><ion-content><div class="list"><div class="padding padding-xs" style="display: block; height: 60px"><div class="pull-left"><h4><span ng-if="enableFilter && search.type==\'member\'" translate="">PEER.MEMBER_PEERS</span> <span ng-if="enableFilter && search.type==\'mirror\'" translate="">PEER.MIRROR_PEERS</span> <span ng-if="!enableFilter || !search.type" translate="">PEER.ALL_PEERS</span> <span ng-if="!search.loading">({{search.results.length}})</span></h4></div><div class="pull-right"><ion-spinner class="icon" icon="android" ng-if="search.loading"></ion-spinner> <div class="pull-right"> </div></div></div><ng-include src="\'templates/network/items_peers.html\'"></ng-include></div></ion-content></ion-modal-view>'); +$templateCache.put('templates/network/popover_endpoints.html','<ion-popover-view class="popover-endpoints popover-light" style="height: {{(titleKey?30:0)+((!items || items.length <= 1) ? 55 : 3+items.length*52)}}px"><ion-header-bar class="bar bar-header stable-bg" ng-if="titleKey"><div class="title">{{titleKey | translate:titleValues }}</div></ion-header-bar><ion-content scroll="false"><div class="list" ng-class="{\'has-header\': titleKey}"><div class="item item-text-wrap" ng-repeat="item in items"><div class="item-label" ng-if="item.label">{{item.label | translate}}</div><div id="endpoint_{{$index}}" class="badge item-note dark">{{item.value}}</div></div></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/network/popover_network.html',''); +$templateCache.put('templates/network/popover_peer_info.html',''); +$templateCache.put('templates/network/view_network.html','<ion-view><ion-nav-title><span translate="">MENU.NETWORK</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-loop visible-xs visible-sm" ng-click="refresh()"></button></ion-nav-buttons><ion-content scroll="true" ng-init="enableFilter=true; ionItemClass=\'item-border-large\';"><div class="row responsive-sm responsive-md responsive-lg"><div class="col list col-border-right"><div class="padding padding-xs" style="display: block; height: 60px"><div class="pull-left"><h4><span ng-if="enableFilter && search.type==\'member\'" translate="">PEER.MEMBER_PEERS</span> <span ng-if="enableFilter && search.type==\'mirror\'" translate="">PEER.MIRROR_PEERS</span> <span ng-if="enableFilter && search.type==\'offline\'" translate="">PEER.OFFLINE_PEERS</span> <span ng-if="!enableFilter || !search.type" translate="">PEER.ALL_PEERS</span> <span ng-if="search.results.length">({{search.results.length}})</span><ion-spinner ng-if="search.loading" class="icon ion-spinner-small" icon="android"></ion-spinner></h4></div><div class="pull-right"><div class="pull-right" ng-if="enableFilter"> <cs-extension-point name="filter-buttons"></cs-extension-point></div></div></div><div id="helptip-network-blockchain" style="display: block"></div><div id="helptip-network-peers" style="display: block"></div><ng-include src="\'templates/network/items_peers.html\'"></ng-include></div><div class="col col-33" ng-controller="BlockLookupCtrl"><div class="padding padding-xs" style="display: block; height: 100px"><h4 translate="">BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4></div><ng-include src="\'templates/blockchain/list_blocks.html\'"></ng-include></div></div></ion-content></ion-view>'); +$templateCache.put('templates/network/view_peer.html','<ion-view><ion-nav-title><span translate="">PEER.VIEW.TITLE</span></ion-nav-title><ion-content class="has-header" scroll="true"><div class="row no-padding"><div class="col list"><ion-item><h1><span translate="">PEER.VIEW.TITLE</span> <span class="gray">{{node.host}}</span></h1><h2 class="gray"><i class="gray icon ion-android-globe"></i> {{node.bma.dns || node.server}} <span class="gray" ng-if="!loading && node.useSsl"><i class="gray ion-locked"></i> <small>SSL</small> </span><span class="gray" ng-if="!loading && node.useTor"><i class="gray ion-bma-tor-api"></i> </span><span class="assertive" ng-if="!loading && !node.uid">({{\'PEER.MIRROR\'|translate}})</span></h2><h3><span class="dark"><i class="icon ion-android-desktop"></i> {{\'PEER.VIEW.OWNER\'|translate}} </span><a class="positive" ng-if="node.uid" ui-sref="app.wot_identity({pubkey: node.pubkey, uid: node.uid})"><i class="ion-person"></i> {{node.name || node.uid}} <span class="gray" ng-if="node.name">({{node.uid}}) </span></a><span ng-if="!loading && !node.uid"><a class="gray" ui-sref="app.wot_identity({pubkey: node.pubkey})"><i class="ion-key"></i> {{node.pubkey|formatPubkey}} <span class="gray" ng-if="node.name">({{node.name}})</span></a></span></h3><h3><a ng-click="openRawPeering($event)"><i class="icon ion-share"></i> {{\'PEER.VIEW.SHOW_RAW_PEERING\'|translate}} </a><span class="gray" ng-if="!isReachable">| </span><a ng-if="!isReachable" ng-click="openRawCurrentBlock($event)"><i class="icon ion-share"></i> <span translate="">PEER.VIEW.SHOW_RAW_CURRENT_BLOCK</span></a></h3></ion-item><div class="item item-divider" translate="">PEER.VIEW.GENERAL_DIVIDER</div><ion-item class="item-icon-left item-text-wrap ink" copy-on-click="{{node.pubkey}}"><i class="icon ion-key"></i> <span translate="">COMMON.PUBKEY</span><h4 class="dark text-left">{{node.pubkey}}</h4></ion-item><a class="item item-icon-left item-icon-right item-text-wrap ink" ng-if="isReachable" ui-sref="app.view_server_block_hash({server: node.server, ssl: node.useSsl, tor: node.useTor, number: current.number, hash: current.hash})"><i class="icon ion-cube"></i> <span translate="">BLOCKCHAIN.VIEW.TITLE_CURRENT</span><div class="badge badge-calm" ng-if="!loading">{{current.number|formatInteger}}</div><i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-icon-right item-text-wrap ink" ng-if="isReachable" ui-sref="app.server_blockchain({server: node.server, ssl: node.useSsl, tor: node.useTor})"><i class="icon ion-cube" style="font-size: 25px"></i> <i class="icon-secondary ion-clock" style="font-size: 18px; left: 33px; top: -12px"></i> <span translate="">PEER.VIEW.LAST_BLOCKS</span> <i class="gray icon ion-ios-arrow-right"></i></a><cs-extension-point name="general"></cs-extension-point><div class="item item-divider" ng-hide="loading || !isReachable" translate="">PEER.VIEW.KNOWN_PEERS</div><ion-item class="item item-text-wrap no-border done in gray no-padding-top no-padding-bottom inline text-italic" ng-show="!loading && !isReachable"><small><i class="icon ion-alert-circled"></i> {{\'NETWORK.INFO.ONLY_SSL_PEERS\'|translate}}</small></ion-item><div class="item center" ng-if="loading"><ion-spinner class="icon" icon="android"></ion-spinner></div><div class="list no-padding {{::motion.ionListClass}}" ng-if="isReachable"><div ng-repeat="peer in :rebind:peers track by peer.id" class="item item-peer item-icon-left ink {{::ionItemClass}}" ng-click="selectPeer(peer)" ng-include="\'templates/network/item_content_peer.html\'"></div></div></div></div></ion-content></ion-view>'); +$templateCache.put('templates/settings/popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink visible-xs visible-sm" ng-click="reset()"><i class="icon ion-refresh"></i> {{\'SETTINGS.BTN_RESET\' | translate}} </a><a class="item item-icon-left ink" ng-click="startSettingsTour()"><i class="icon ion-easel"></i> {{\'COMMON.BTN_HELP_TOUR_SCREEN\' | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/settings/popup_node.html','<form name="popupForm" ng-submit=""><div class="list no-padding" ng-init="setPopupForm(popupForm)"><div class="item item-input item-floating-label" ng-class="{\'item-input-error\': popupForm.$submitted && popupForm.newNode.$invalid}"><span class="input-label" ng-bind-html="\'SETTINGS.POPUP_PEER.HOST\'|translate"></span> <input name="newNode" type="text" placeholder="{{\'SETTINGS.POPUP_PEER.HOST_HELP\' | translate}}" ng-model="popupData.newNode" ng-minlength="3" required></div><div class="form-errors" ng-if="popupForm.$submitted && popupForm.newNode.$error" ng-messages="popupForm.newNode.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div><div class="item item-toggle"><span class="input-label">{{\'SETTINGS.POPUP_PEER.USE_SSL\' | translate}}</span><h4><small class="gray" ng-bind-html="\'SETTINGS.POPUP_PEER.USE_SSL_HELP\' | translate"></small></h4><label class="toggle toggle-royal no-padding-right"><input type="checkbox" ng-model="popupData.useSsl"><div class="track"><div class="handle"></div></div></label></div><a class="button button-positive button-clear positive button-outline button-full button-small-padding icon-left ink no-padding" ng-click="showNodeList()"><i class="icon ion-search"></i> {{\'SETTINGS.POPUP_PEER.BTN_SHOW_LIST\' | translate}}</a></div><button type="submit" class="hide"></button></form>'); +$templateCache.put('templates/settings/settings.html','<ion-view left-buttons="leftButtons" cache-view="false" class="settings"><ion-nav-title translate="">SETTINGS.TITLE</ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content><div class="row no-padding responsive-sm responsive-md responsive-lg"><div class="col col-50 list item-border-large padding-left padding-right no-padding-xs no-padding-sm" style="margin-bottom: 2px"><span class="item item-divider" translate="">SETTINGS.DISPLAY_DIVIDER</span><label class="item item-input item-select"><div class="input-label" translate="">COMMON.LANGUAGE</div><select ng-model="formData.locale" ng-change="changeLanguage(formData.locale.id)" ng-options="l as l.label for l in locales track by l.id"></select></label><div class="item item-toggle dark"><div class="input-label">{{\'COMMON.BTN_RELATIVE_UNIT\' | translate}}</div><label class="toggle toggle-royal" id="helptip-settings-btn-unit-relative"><input type="checkbox" ng-model="formData.useRelative"><div class="track"><div class="handle"></div></div></label></div><div class="item item-toggle dark item-text-wrap"><div class="input-label" ng-bind-html="\'SETTINGS.ENABLE_HELPTIP\' | translate"></div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.helptip.enable"><div class="track"><div class="handle"></div></div></label></div><span class="item item-divider" translate="">SETTINGS.STORAGE_DIVIDER</span><div class="item item-text-wrap item-toggle dark"><div class="input-label">{{\'SETTINGS.USE_LOCAL_STORAGE\' | translate}}</div><h4 class="gray" ng-bind-html="\'SETTINGS.USE_LOCAL_STORAGE_HELP\' | translate"></h4><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.useLocalStorage"><div class="track"><div class="handle"></div></div></label></div><cs-extension-point name="common"></cs-extension-point><span class="item item-divider">{{\'SETTINGS.AUTHENTICATION_SETTINGS\' | translate}}</span><div class="item item-toggle item-text-wrap"><div class="input-label" ng-class="{\'gray\': !formData.useLocalStorage}">{{\'SETTINGS.REMEMBER_ME\' | translate}}</div><h4 class="gray text-wrap" ng-bind-html="\'SETTINGS.REMEMBER_ME_HELP\' | translate"></h4><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.rememberMe" ng-disabled="!formData.useLocalStorage"><div class="track"><div class="handle"></div></div></label></div><label class="item item-input item-select item-text-wrap"><div class="input-label hidden-xs"><span class="hidden-xs" translate="">SETTINGS.KEEP_AUTH</span><h4 class="gray text-wrap hidden-xs" ng-bind-html="\'SETTINGS.KEEP_AUTH_HELP\' | translate"></h4></div><span class="visible-xs" translate="">SETTINGS.KEEP_AUTH_SHORT</span><select ng-model="formData.keepAuthIdle" ng-options="i as (keepAuthIdleLabels[i].labelKey | translate:keepAuthIdleLabels[i].labelParams ) for i in keepAuthIdles track by i"></select></label></div><div class="col col-50 list item-border-large padding-left padding-right no-padding-xs no-padding-sm no-margin-xs no-margin-sm"><span class="item item-divider">{{\'SETTINGS.WALLETS_SETTINGS\' | translate}}</span><div class="item item-toggle item-text-wrap dark"><span class="input-label" ng-class="{\'gray\': !formData.useLocalStorage}" translate="">SETTINGS.USE_WALLETS_ENCRYPTION</span><h4 class="gray text-wrap" ng-bind-html="\'SETTINGS.USE_WALLETS_ENCRYPTION_HELP\' | translate"></h4><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.useLocalStorageEncryption" ng-disabled="!formData.useLocalStorage"><div class="track"><div class="handle"></div></div></label></div><span class="item item-divider" translate="">SETTINGS.HISTORY_SETTINGS</span><div class="item item-toggle item-text-wrap dark"><div class="input-label" translate="">SETTINGS.DISPLAY_UD_HISTORY</div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.showUDHistory"><div class="track"><div class="handle"></div></div></label></div><cs-extension-point name="history"></cs-extension-point><span class="item item-divider" translate="">SETTINGS.NETWORK_SETTINGS</span><ion-item class="ink item-icon-right visible-xs visible-sm" ng-click="changeNode()"><div class="input-label hidden-xs" translate="">SETTINGS.PEER</div><div class="input-label visible-xs" translate="">SETTINGS.PEER_SHORT</div><ng-if ng-if="formData.node.temporary"><h4 class="gray text-wrap assertive"><b class="ion-alert-circled"></b> <span ng-bind-html="\'SETTINGS.PEER_CHANGED_TEMPORARY\' | translate "></span></h4><div class="badge badge-assertive">{{bma.server}}</div></ng-if><div class="badge badge-balanced" ng-if="!formData.node.temporary">{{bma.server}}</div><i class="icon ion-ios-arrow-right"></i></ion-item><label class="item item-input item-select item-text-wrap"><div class="input-label hidden-xs"><span translate="">SETTINGS.BLOCK_VALIDITY_WINDOW</span><h4 class="gray text-wrap hidden-xs" ng-bind-html="\'SETTINGS.BLOCK_VALIDITY_WINDOW_HELP\' | translate"></h4></div><div class="input-label visible-xs" translate="">SETTINGS.BLOCK_VALIDITY_WINDOW_SHORT</div><select ng-model="formData.blockValidityWindow" ng-options="i as (blockValidityWindowLabels[i].labelKey | translate:blockValidityWindowLabels[i].labelParams ) for i in blockValidityWindows track by i"></select></label><cs-extension-point name="network"></cs-extension-point><span class="item item-divider" ng-if="$root.config.plugins" translate="">SETTINGS.PLUGINS_SETTINGS</span><cs-extension-point name="plugins"></cs-extension-point></div></div></ion-content></ion-view>'); +$templateCache.put('templates/wallet/item_tx.html','<i class="icon item-image" ng-if="::!tx.avatar" ng-class="::{\'ion-person dark\': tx.uid, \'ion-card dark\': !tx.uid}"></i> <i class="avatar" ng-if="::tx.avatar" style="background-image: url({{::tx.avatar.src}})"></i><div class="row no-padding"><div class="col no-padding"><a class="" ui-sref="app.wot_identity({pubkey:tx.pubkey, uid:tx.uid})" ng-if="::tx.uid">{{::tx.name||tx.uid}} </a><a class="gray" ui-sref="app.wot_identity({pubkey:tx.pubkey, uid:tx.uid})" ng-if="::!tx.uid && tx.pubkey"><i class="ion-key gray"></i> {{::tx.pubkey | formatPubkey}} <span ng-if="::tx.name">- {{::tx.name | truncText:40}}</span></a><p class="dark visible-xs width-cup text-italic" data-toggle="tooltip" ng-if="::tx.comment" title="{{::tx.comment}}"><i class="ion-ios-chatbubble-outline"></i> {{::tx.comment}}<br></p><h4><a ng-if="::!pending" class="gray underline" ui-sref="app.view_block({number: tx.block_number})">{{::tx.time | medianFromNowAndDate: false}} </a><span ng-if="::pending" class="gray">{{::tx.time | medianFromNowAndDate: false}}</span></h4></div><div class="col col-50 no-padding" ng-if="::tx.comment"><p class="vertical-center gray text-italic hidden-xs" data-toggle="tooltip" title="{{::tx.comment}}">{{::tx.comment}}</p></div><div class="col col-10 no-padding"><span ng-if="::!tx.lockedOutputs" class="badge item-note" ng-class="{\'badge-calm\': tx.amount > 0, \'badge-white\': tx.amount <= 0}"><span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span> </span><a ng-if=":rebind:tx.lockedOutputs" class="badge item-note" ng-class="{\'badge-calm\': tx.amount > 0}" ng-click="showLockedOutputsPopover(tx, $event)"><b class="ion-locked"></b> <span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span></a><div class="badge badge-secondary" ng-if="$root.settings.expertMode">(<span ng-bind-html=":rebind:tx.amount| formatAmount:{useRelative: !$root.settings.useRelative, currency:$root.currency.name}"></span>)</div></div></div>'); +$templateCache.put('templates/wallet/item_ud.html','<i class="icon item-image ion-arrow-up-c energized"></i><div class="row no-padding"><div class="col no-padding"><span class="energized" translate>COMMON.UNIVERSAL_DIVIDEND</span><h4><a class="gray underline" ui-sref="app.view_block({number: tx.block_number})">{{::tx.time | medianFromNowAndDate}}</a></h4></div><div class="col col-10 no-padding"><span class="badge item-note badge-energized"><span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span></span><div class="badge badge-secondary" ng-if="$root.settings.expertMode">(<span ng-bind-html=":rebind:tx.amount| formatAmount:{useRelative: !$root.settings.useRelative, currency:$root.currency.name}"></span>)</div></div></div>'); +$templateCache.put('templates/wallet/modal_security.html','<ion-modal-view class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-if="!slides.slider.activeIndex" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button> <button class="button button-icon button-clear icon ion-ios-arrow-back buttons header-item" ng-click="slidePrev()" ng-if="slides.slider.activeIndex"></button><h1 class="title hidden-xs" translate="">ACCOUNT.SECURITY.TITLE</h1><button class="button button-clear icon-right visible-xs" ng-if="!isLastSlide && slides.slider.activeIndex > 0" ng-click="doNext()"><span translate="">COMMON.BTN_NEXT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-positive button-icon button-clear icon ion-android-done visible-xs" ng-click="doNext()" ng-if="isLastSlide && option === \'saveID\'"></button></ion-header-bar><ion-slides options="slides.options" slider="slides.slider"><ion-slide-page><ion-content class="has-header padding"><div class="list"><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="selectOption(\'recoverID\')" ng-if="!login"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-person"></i> <b class="ion-ios-undo icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.RECOVER_ID</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.RECOVER_ID_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="selectOption(\'revocation\')" ng-if="!login"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-person"></i> <b class="ion-close icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.REVOCATION_WITH_FILE</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.REVOCATION_WITH_FILE_DESCRIPTION</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink hidden-xs" ng-click="selectOption(\'saveID\')" ng-if="login && !$root.device.enable"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-person"></i> <b class="ion-ios-redo icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b> <b class="ion-locked icon-secondary dark" style="top: 0px; left: 40px; font-size: 8px"></b><h2 translate="">ACCOUNT.SECURITY.SAVE_ID</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.SAVE_ID_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink hidden-xs" ng-click="selectOption(\'generateKeyfile\')" ng-if="login && !$root.device.enable"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-document-text"></i> <b class="ion-key icon-secondary dark" style="top: -8px; left: 42px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.GENERATE_KEYFILE</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.GENERATE_KEYFILE_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="self()" ng-if="needSelf"><div class="item-content item-text-wrap"><i class="item-image icon ion-person dark"></i> <b class="ion-flag icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.SEND_IDENTITY</h2><h4 class="gray" ng-bind-html="::\'ACCOUNT.SECURITY.SEND_IDENTITY_HELP\' | translate"></h4></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="membershipIn()" ng-if="needMembership"><div class="item-content item-text-wrap"><i class="item-image icon ion-person dark"></i> <b class="ion-plus icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.MEMBERSHIP_IN</h2><h4 class="gray" ng-bind-html="::\'ACCOUNT.SECURITY.MEMBERSHIP_IN_HELP\' | translate"></h4></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="revokeWalletIdentity()" ng-if="canRevoke"><div class="item-content item-text-wrap"><i class="item-image icon ion-person assertive-900"></i> <b class="ion-close icon-secondary assertive-900" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.REVOCATION_WALLET</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.REVOCATION_WALLET_HELP</h4></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate="">COMMON.BTN_CANCEL</button></div></ion-content></ion-slide-page><ion-slide-page ng-if="option == \'revocation\'"><ng-include src="\'templates/wallet/slides/slides_revocation_file.html\'"></ng-include></ion-slide-page><ion-slide-page ng-if="login && option == \'saveID\'"><ng-include src="\'templates/wallet/slides/slides_saveID_1.html\'"></ng-include></ion-slide-page><ion-slide-page ng-if="login && option == \'saveID\'"><ng-include src="\'templates/wallet/slides/slides_saveID_2.html\'"></ng-include></ion-slide-page><ion-slide-page ng-if="option == \'recoverID\'"><ng-include src="\'templates/wallet/slides/slides_recoverID_1.html\'"></ng-include></ion-slide-page><ion-slide-page ng-if="option == \'recoverID\'"><ng-include src="\'templates/wallet/slides/slides_recoverID_2.html\'"></ng-include></ion-slide-page><ion-slide-page ng-if="option == \'recoverID\'"><ng-include src="\'templates/wallet/slides/slides_recoverID_3.html\'"></ng-include></ion-slide-page><ion-slide-page ng-if="login && option == \'generateKeyfile\'"><ng-include src="\'templates/wallet/slides/slides_generate_keyfile.html\'"></ng-include></ion-slide-page></ion-slides></ion-modal-view>'); +$templateCache.put('templates/wallet/modal_transfer.html','<ion-modal-view id="transfer" class="modal-full-height modal-transfer"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>TRANSFER.MODAL.TITLE</h1><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doTransfer()"></button></ion-header-bar><ion-content><ng-include src="\'templates/wallet/transfer_form.html\'"></ng-include></ion-content><ion-digit-keyboard settings="digitKeyboardSettings" ng-if="digitKeyboardVisible"></ion-digit-keyboard></ion-modal-view>'); +$templateCache.put('templates/wallet/new_transfer.html','<ion-view left-buttons="leftButtons" id="transfer"><ion-nav-title><span class="visible-xs visible-sm" translate="">TRANSFER.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doTransfer()"></button></ion-nav-buttons><ion-content scroll="true"><div class="row no-padding-xs"><div class="col no-padding-xs"><ng-include src="\'templates/wallet/transfer_form.html\'"></ng-include></div></div></ion-content><ion-digit-keyboard settings="digitKeyboardSettings" ng-if="digitKeyboardVisible"></ion-digit-keyboard></ion-view>'); +$templateCache.put('templates/wallet/popover_actions.html','<ion-popover-view class="fit has-header popover-wallet-actions"><ion-header-bar><h1 class="title" translate="">COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink visible-xs visible-sm" ng-click="showSharePopover($event)"><i class="icon ion-android-share-alt"></i> {{\'COMMON.BTN_SHARE\' | translate}} </a><a class="item item-icon-left ink" ng-if="walletData.requirements.alternatives" ng-click="showSelectIdentitiesModal()"><i class="icon ion-person"></i> <b class="icon-secondary ion-loop" style="margin-top: 4px; left: 15px"></b> {{\'ACCOUNT.BTN_SELECT_ALTERNATIVES_IDENTITIES\' | translate}} </a><a class="item item-icon-left ink visible-xs visible-sm" ng-if="!walletData.requirements.needSelf && walletData.requirements.needRenew" ng-click="renewMembership()"><i class="icon ion-loop"></i> {{\'ACCOUNT.BTN_MEMBERSHIP_RENEW_DOTS\' | translate}} </a><a class="item item-icon-left assertive ink" ng-if="walletData.requirements.canMembershipOut" ng-click="membershipOut()"><i class="icon ion-log-out"></i> {{\'ACCOUNT.BTN_MEMBERSHIP_OUT_DOTS\' | translate}} </a><a class="item item-icon-left ink" ng-click="showSecurityModal()"><i class="icon ion-locked"></i> <span ng-bind-html="\'ACCOUNT.BTN_SECURITY_DOTS\' | translate"></span></a></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/wallet/popover_unit.html','<ion-popover-view class="popover-unit"><ion-content scroll="false"><div class="list"><a class="item item-icon-left" ng-class="{ \'selected\': !formData.useRelative}" ng-click="closePopover(false)"><i class="icon" ng-class="{ \'ion-ios-checkmark-empty\': !formData.useRelative}"></i> <i ng-bind-html="$root.currency.name | currencySymbol:false"></i> </a><a class="item item-icon-left" ng-class="{ \'selected\': formData.useRelative}" ng-click="closePopover(true)"><i class="icon" ng-class="{ \'ion-ios-checkmark-empty\': formData.useRelative}"></i> <i ng-bind-html="$root.currency.name | currencySymbol:true"></i></a></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/wallet/popup_register.html','<form name="registerForm" ng-submit=""><div class="list" ng-init="setRegisterForm(registerForm)"><label class="item item-input" ng-class="{\'item-input-error\': registerForm.$submitted && registerForm.pseudo.$invalid}"><input name="pseudo" type="text" placeholder="{{\'ACCOUNT.NEW.PSEUDO_HELP\' | translate}}" ng-model="formData.newUid" ng-minlength="3" required></label><div class="form-errors" ng-if="registerForm.$submitted && registerForm.pseudo.$error" ng-messages="registerForm.pseudo.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div></div></form>'); +$templateCache.put('templates/wallet/transfer_form.html','<form name="transferForm" novalidate="" ng-submit="doTransfer()"><div class="list no-padding-xs" ng-init="setForm(transferForm)"><ion-item class="item-icon-right gray ink" ng-class="{\'item-input-error\': form.$submitted && !formData.destPub}" tabindex="1" ng-click="showWotLookupModal()"><span class="gray" translate="">TRANSFER.TO</span> <span class="badge badge-royal animate-fade-in animate-show-hide ng-hide" ng-show="destUid"><i class="ion-person"></i> {{destUid}} </span> <span class="badge badge-royal" ng-show="!destUid && formData.destPub"><i class="ion-key"></i> {{formData.destPub | formatPubkey}} </span><i class="gray icon ion-ios-arrow-right"></i></ion-item><div class="form-errors" ng-if="form.$submitted && !formData.destPub"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><ion-item class="item-text-wrap ink" ng-class="{\'item-icon-right\': enableSelectWallet}" tabindex="2" ng-click="showSelectWalletModal()"><span class="gray" translate="">TRANSFER.FROM</span> <span class="badge animate-fade-in animate-show-hide ng-hide" ng-show="!loading" ng-class="{\'badge-assertive\': (convertedBalance <= 0 || form.amount.$error.max), \'badge-balanced\': (convertedBalance > 0 && (!form.amount.$error.max)) }"><ion-spinner icon="android" ng-show="!walletData.pubkey"></ion-spinner><span ng-if="walletData.pubkey && !walletData.isMember"><i class="ion-key"></i> {{walletData.pubkey| formatPubkey}} </span><span ng-if="walletData.isMember"><i class="ion-person"></i> {{walletData.name||walletData.uid}} </span><span ng-bind-html="walletData.balance|formatAmount:{useRelative: formData.useRelative, currency:currency}"></span> </span><i class="gray icon ion-ios-arrow-right" ng-if="enableSelectWallet"></i></ion-item><ion-item class="item-input item-floating-label item-button-right" ng-class="{\'item-input-error\': form.$submitted && form.amount.$invalid}"><div class="input-label"><span translate="">TRANSFER.AMOUNT</span> (<span ng-bind-html="$root.currency.name | currencySymbol:formData.useRelative"></span>)</div><input type="text" tabindex="-1" autocomplete="off" class="visible-xs visible-sm" name="amount" placeholder="{{::\'TRANSFER.AMOUNT_HELP\' | translate}}" ng-model="formData.amount" required number-float=""><div class="block visible-xs visible-sm" style="position:absolute; opacity:0; z-index:100; top: 0; left: 0; height: 100%; width: 100%" tabindex="4" ng-click="showDigitKeyboard()"></div><a class="button button-clear button-stable dark ink" tabindex="-1" style="z-index:110; padding: 0px 16px" ng-click="showUnitPopover($event)"><span ng-bind-html="$root.currency.name | currencySymbol:formData.useRelative"></span> <b class="ion-arrow-down-b" style="font-size: 12pt"></b></a></ion-item><div class="form-errors" ng-show="form.$submitted && form.amount.$error" ng-messages="form.amount.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="numberFloat"><span translate="ERROR.FIELD_NOT_NUMBER"></span></div><div class="form-error" ng-message="numberInt"><span translate="ERROR.FIELD_NOT_INT"></span></div><div class="form-error" ng-message="min"><span translate="ERROR.FIELD_MIN" translate-values="{min: minAmount}"></span></div><div class="form-error" ng-message="max"><span translate="ERROR.NOT_ENOUGH_CREDIT"></span></div></div><a class="item item-icon-right gray ink" ng-class="{\'item-input-error\': form.$submitted && !formData.destPub}" ng-click="showWotLookupModal(\'restPub\')" tabindex="5" ng-if="formData.all && formData.restAmount"><span class="gray"><i translate="">TRANSFER.REST</i><ng-if ng-if="formData.restAmount">(<i ng-bind-html="formData.restAmount|formatAmount:{useRelative: formData.useRelative, currency:currency}"></i>)</ng-if><i translate="">TRANSFER.REST_TO</i> </span><span class="badge badge-royal animate-fade-in animate-show-hide ng-hide" ng-show="restUid"><i class="ion-person"></i> {{restUid}} </span> <span class="badge badge-royal" ng-show="!restUid && formData.restPub"><i class="ion-key"></i> {{formData.restPub | formatPubkey}} </span><i class="gray icon ion-ios-arrow-right"></i></a><div class="form-errors" ng-if="form.$submitted && formData.all && !formData.restPub && formData.restAmount > 0"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="pull-right visible-xs visible-sm" ng-if="!formData.useComment"><a class="button button-text button-small ink" tabindex="-1" ng-click="addComment()"><i class="icon ion-plus"></i> <span translate="">TRANSFER.BTN_ADD_COMMENT</span></a></div><label class="item item-input item-floating-label visible-xs visible-sm" ng-if="formData.useComment" ng-class="{\'item-input-error\': form.$submitted && form.comment.$invalid}"><span class="input-label">{{\'TRANSFER.COMMENT\' | translate}}</span> <input type="text" placeholder="{{\'TRANSFER.COMMENT_HELP\' | translate}}" id="{{commentInputId}}" tabindex="7" name="comment" autocomplete="off" ng-model="formData.comment" ng-model-options="{ debounce: 650 }" ng-maxlength="255" ng-pattern="commentPattern" ng-focus="hideDigitKeyboard()"></label><div class="form-errors" ng-show="form.comment.$error" ng-messages="form.comment.$error"><div class="form-error" ng-message="maxlength"><span translate="ERROR.FIELD_TOO_LONG"></span></div><div class="form-error" ng-message="pattern"><span translate="ERROR.FIELD_ACCENT"></span></div></div><div class="item item-icon-left item-text-wrap item-no-border visible-xs visible-sm" ng-if="formData.useComment"><i class="icon ion-android-alert positive"></i><h4 class="positive" translate="">TRANSFER.WARN_COMMENT_IS_PUBLIC</h4></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" tabindex="-1" ng-click="cancel()" type="button" translate="">COMMON.BTN_CANCEL</button> <button class="button ink" tabindex="8" ng-class="{\'button-assertive\': formData.all, \'button-positive\': !formData.all}" type="submit" translate="">TRANSFER.BTN_SEND</button></div></form>'); +$templateCache.put('templates/wallet/tx_locked_outputs_popover.html','<ion-popover-view class="fit popover-locked-outputs"><ion-header-bar><h1 class="title" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.TITLE</h1></ion-header-bar><ion-content scroll="true"><div ng-if="popoverData.lockedOuputs.length == 1" class="item item-text-wrap no-border"><h4 class="positive" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.DESCRIPTION</h4></div><div ng-if="popoverData.lockedOuputs.length > 1" class="item item-text-wrap no-border"><h4 class="positive" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.DESCRIPTION_MANY</h4></div><div ng-repeat="output in popoverData.lockedOuputs track by $index" class="item"><h2 class="gray" ng-if="popoverData.lockedOuputs.length > 1" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.LOCKED_AMOUNT</h2><div ng-if="popoverData.lockedOuputs.length > 1" class="badge item-note" ng-class="{\'badge-balanced\': output.amount > 0}"><i class="icon ion-locked"></i> <span ng-bind-html="::output.amount| formatAmount"></span> <span ng-bind-html="::unit"></span></div><div ng-repeat="condition in output.unlockConditions track by $index" class="row" ng-class="::{\'padding-top\': !$index && popoverData.lockedOuputs.length > 1}" ng-style="::condition.style"><span class="gray" ng-if="::condition.operator">{{::\'BLOCKCHAIN.VIEW.TX_OUTPUT_OPERATOR.\'+condition.operator|translate}} </span><div ng-if="::condition.type==\'SIG\'"><i class="icon ion-key dark"></i> <span class="dark" ng-bind-html="::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.SIG\' | translate"></span> <a ng-click="goState(\'app.wot_identity\', {pubkey:condition.value})" style="text-decoration: none" class="positive">{{condition.value|formatPubkey}}</a></div><div ng-if="::condition.type==\'XHX\'"><i class="icon ion-lock-combination dark"></i> <span class="dark" ng-bind-html="::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.XHX\' | translate"></span> <a copy-on-click="{{::condition.value}}" class="positive">{{::condition.value|formatPubkey}}...</a></div><div ng-if="condition.type==\'CSV\'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CSV\' | translate"></span> {{::condition.value|formatDuration}}</div><div ng-if="condition.type==\'CLTV\'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::\'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CLTV\' | translate"></span> {{::condition.value|medianDate}}</div></div></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/wallet/view_wallet.html','<ion-view left-buttons="leftButtons" class="view-wallet" id="wallet"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" id="helptip-wallet-options-xs" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true" class="refresher-positive-900-bg" bind-notifier="{ rebind:settings.useRelative, locale:$root.settings.locale.id}"><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="positive-900-bg hero" style="max-width: 100%; display: block" ng-class="{\'hero-qrcode-active\': toggleQRCode}"><div class="content" ng-if="!loading" style="max-width: 100%"><i class="avatar" ng-if=":rebind:!formData.avatar" ng-class=":rebind:{\'avatar-wallet\': !formData.isMember, \'avatar-member\': formData.isMember}"></i> <i class="avatar" ng-if=":rebind:formData.avatar" style="background-image: url({{:rebind:formData.avatar.src}})"></i><h3 class="light" ng-if=":rebind:!enableSelectWallet"><span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span> <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span> <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span></h3><h3 class="light" ng-if=":rebind:enableSelectWallet"><a class="visible-xs visible-sm" style="color: lightgray" title="{{:locale:\'ACCOUNT.SELECT_WALLET_MODAL.TITLE\'|translate}}" ng-click="showSelectWalletModal($event)"><span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span> <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span> <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span> <small><i class="ion-arrow-down-b"></i></small></a></h3><h4 class="assertive"><span ng-if=":rebind:(formData.name || formData.uid) && !formData.isMember" translate="">WOT.NOT_MEMBER_PARENTHESIS</span></h4></div><h4 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><a ng-attr-id="{{ qrcodeId }}" class="qrcode spin pull-right" ng-class="{\'active\': toggleQRCode}" ng-click="toggleQRCode = !toggleQRCode"></a><a id="wallet-share-anchor"></a><div class="visible-xs visible-sm padding text-center" ng-if="!loading"><button class="button button-assertive button-small-padding ink" ng-if="isDefaultWallet" ng-click="logout({askConfirm: true})"><i class="icon ion-log-out"></i> {{\'COMMON.BTN_LOGOUT\' | translate}}</button><div ng-if="formData.requirements.needRenew"><br><button class="button button-raised icon-left button-stable button-small-padding ink" ng-click="renewMembership()"><i class="icon ion-loop assertive"></i> <span class="assertive">{{:locale:\'ACCOUNT.BTN_MEMBERSHIP_RENEW\' | translate}}</span></button></div></div><div class="row no-padding"><div class="col"><div class="list {{::motion.ionListClass}}" ng-hide="loading"><span class="item item-divider" translate="">WOT.GENERAL_DIVIDER</span><div id="helptip-wallet-pubkey" class="item item-icon-left item-text-wrap ink" on-hold="copy(formData.pubkey)" copy-on-click="{{:rebind:formData.pubkey}}"><i class="icon ion-key"></i> <span>{{:locale:\'COMMON.PUBKEY\'|translate}}</span><h4 id="pubkey" class="dark">{{:rebind:formData.pubkey}}</h4></div><ion-item class="item-icon-left" ng-if=":rebind:formData.sigDate||formData.uid"><i class="icon ion-calendar"></i> <span translate="">COMMON.UID</span><h5 class="dark" ng-if=":rebind:formData.sigDate"><span translate="">WOT.REGISTERED_SINCE</span> {{:rebind:formData.sigDate | medianDate}}</h5><span class="badge badge-stable">{{:rebind:formData.uid}}</span></ion-item><a id="helptip-wallet-certifications" class="item item-icon-left item-icon-right item-text-wrap ink" ng-if="formData.isMember||formData.requirements.pendingMembership||!formData.requirements.needSelf" ng-click="showCertifications()"><i class="icon ion-ribbon-b"></i> <b ng-if="formData.requirements.isSentry" class="ion-star icon-secondary" style="color: yellow; font-size: 16px; left: 25px; top: -7px"></b> {{:locale:\'ACCOUNT.CERTIFICATION_COUNT\'|translate}}<cs-badge-certification requirements="formData.requirements" parameters="::currency.parameters"></cs-badge-certification><i class="gray icon ion-ios-arrow-right"></i> </a><a id="helptip-wallet-given-certifications" class="item item-icon-left item-text-wrap item-icon-right ink visible-xs visible-sm" ng-if="formData.isMember" ng-click="showGivenCertifications()"><i class="icon ion-ribbon-a"></i> <span translate="">WOT.GIVEN_CERTIFICATIONS.SENT</span> <i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-icon-right ink" ng-click="showTxHistory()"><i class="icon ion-card"></i> <span translate="">WOT.ACCOUNT_OPERATIONS</span> <i class="gray icon ion-ios-arrow-right"></i> </a><span class="item item-divider" ng-if="formData.events.length">{{:locale:\'ACCOUNT.EVENTS\' | translate}}</span><div class="item item-text-wrap item-icon-left item-wallet-event" ng-repeat="event in formData.events"><i class="icon" ng-class="{\'ion-information-circled royal\': event.type==\'info\',\'ion-alert-circled assertive\': event.type==\'warn\'||event.type==\'error\',\'assertive\': event.type==\'error\',\'ion-clock\': event.type==\'pending\'}"></i> <span trust-as-html="event.message | translate:event.messageParams"></span></div><cs-extension-point name="general"></cs-extension-point><cs-extension-point name="after-general"></cs-extension-point></div></div></div></ion-content></ion-view>'); +$templateCache.put('templates/wallet/view_wallet_tx.html','<ion-view left-buttons="leftButtons" class="view-wallet-tx"><ion-nav-title><span class="visible-xs visible-sm" translate="">MENU.TRANSACTIONS</span></ion-nav-title><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point></ion-nav-buttons><ion-content scroll="true" class="refresher-positive-900-bg" bind-notifier="{ rebind:settings.useRelative, locale:settings.locale.id}"><ion-refresher pulling-text="{{:locale:\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="positive-900-bg hero"><div class="content" ng-if="!loading"><h1 class="light"><span ng-bind-html=":balance:rebind:formData.balance | formatAmount:{currency: $root.currency.name}"></span></h1><h4><ng-if ng-if="!loading && $root.settings.expertMode" style="font-style: italic">(<span ng-bind-html=":balance:rebind:formData.balance | formatAmount:{useRelative:!$root.settings.useRelative, currency: $root.currency.name}"></span>)</ng-if><ng-if ng-if=":rebind:!enableSelectWallet" style="color: lightgray"><span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span> <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span> <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span></ng-if><ng-if ng-if=":rebind:enableSelectWallet"><a class="visible-xs visible-sm" style="color: lightgray" title="{{:locale:\'ACCOUNT.SELECT_WALLET_MODAL.TITLE\'|translate}}" ng-click="showSelectWalletModal($event)"><span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span> <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span> <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span> <small><i class="ion-arrow-down-b"></i></small></a></ng-if></h4><div class="helptip-anchor-center"><a id="helptip-wallet-balance"> </a></div></div><h2 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h2></div><div class="row no-padding"><div class="col"><div class="list {{::motion.ionListClass}}"><a class="item item-icon-left item-icon-right ink" ng-if="formData.tx.errors && formData.tx.errors.length" ng-click="showTxErrors()"><i class="icon ion-alert-circled"></i> {{:locale:\'ACCOUNT.ERROR_TX\'|translate}}<div class="badge badge-assertive">{{formData.tx.errors.length}}</div><i class="gray icon ion-ios-arrow-right"></i></a><ng-if ng-if="formData.tx.pendings.length"><span class="item item-pending item-divider"><b class="ion-clock"></b> {{:locale:\'ACCOUNT.PENDING_TX\'|translate}}</span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.pendings" ng-init="pending=true;" ng-include="\'templates/wallet/item_tx.html\'"></div></ng-if><ng-if ng-if="formData.tx.validating.length"><span class="item item-pending item-divider"><b class="icon ion-checkmark" style="font-size: 12px"></b> <b class="icon-secondary ion-help" style="font-size: 12px; top: 2px; left: 11px"></b> {{:locale:\'ACCOUNT.VALIDATING_TX\'|translate}}</span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.validating" ng-init="validating=true;" ng-include="::\'templates/wallet/item_tx.html\'"></div></ng-if><span class="item item-divider" ng-if="!loading"><b class="icon ion-checkmark"></b> {{:locale:\'ACCOUNT.LAST_TX\'|translate}} <a id="helptip-wallet-tx" style="position: relative; bottom: 0; right: 0px"> </a> </span><span class="item padding" ng-if="!loading && !formData.tx.history.length"><span class="gray">{{:locale:\'ACCOUNT.NO_TX\'|translate}}</span></span><div ng-repeat="tx in formData.tx.history" class="item item-tx item-icon-left" ng-include="::!tx.isUD ? \'templates/wallet/item_tx.html\' : \'templates/wallet/item_ud.html\'"></div><div class="item item-text-wrap text-center" ng-if="formData.tx.fromTime > 0"><p><a ng-click="showMoreTx()">{{:locale:\'ACCOUNT.SHOW_MORE_TX\'|translate}}</a> <span class="gray" translate="ACCOUNT.TX_FROM_DATE" translate-values="{fromTime: formData.tx.fromTime}"></span> <span class="gray">|</span> <a ng-click="showMoreTx(-1)" translate="">ACCOUNT.SHOW_ALL_TX</a></p></div></div></div></div></ion-content><button id="fab-transfer" ng-show="!loading" class="button button-fab button-fab-bottom-right button-energized-900 hidden-md hidden-lg drop ng-hide" ng-click="showTransferModal()"><i class="icon ion-android-send"></i></button></ion-view>'); +$templateCache.put('templates/wallet/view_wallet_tx_error.html','<ion-view left-buttons="leftButtons" class="view-wallet-tx-error"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point></ion-nav-buttons><ion-content scroll="true" class="refresher-top-bg" bind-notifier="{ rebind:settings.useRelative, locale:settings.locale.id}"><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="row no-padding"><div class="col list {{::motion.ionListClass}}"><div class="item item-divider"><span><b class="ion-clock"></b> {{:locale:\'ACCOUNT.PENDING_TX_RECEIVED\'|translate}}</span><div class="badge item-note"><span ng-if="!$root.settings.useRelative">({{$root.currency.name | abbreviate}})</span> <span ng-if="$root.settings.useRelative">({{\'COMMON.UD\' | translate}}<sub>{{$root.currency.name | abbreviate}}</sub>)</span></div></div><span class="item padding" ng-if="!loading && !hasReceivedTx()"><span class="gray">{{:locale:\'ACCOUNT.NO_TX\'|translate}}</span></span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.errors | filter: filterReceivedTx" ng-init="pending=true;" ng-include="\'templates/wallet/item_tx.html\'"></div><div class="item item-divider"><span><b class="ion-close-circled"></b> {{:locale:\'ACCOUNT.ERROR_TX_SENT\'|translate}}</span><div class="badge item-note"><span ng-if="!$root.settings.useRelative">({{$root.currency.name | abbreviate}})</span> <span ng-if="$root.settings.useRelative">({{\'COMMON.UD\' | translate}}<sub>{{$root.currency.name | abbreviate}}</sub>)</span></div></div><span class="item padding" ng-if="!loading && !hasSentTx()"><span class="gray">{{:locale:\'ACCOUNT.NO_TX\'|translate}}</span></span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.errors | filter: filterSentTx" ng-init="error=true;" ng-include="\'templates/wallet/item_tx.html\'"></div></div></div></ion-content></ion-view>'); +$templateCache.put('templates/wot/item_certification.html','<i class="item-image" ng-if="!cert.avatar" ng-class="{\'ion-card\': !cert.isMember, \'ion-person\': cert.isMember}"></i> <i class="item-image avatar" ng-if="cert.avatar" style="background-image: url({{::cert.avatar.src}})"></i> <span ng-if="cert.isMember"><h3><i class="icon ion-clock" ng-if="cert.pending"></i> <span class="positive">{{::cert.name||cert.uid}}</span></h3><h4 class="gray"><i class="ion-key"></i> {{::cert.pubkey | formatPubkey}} <span class="gray">| {{::cert.time|medianDate}}</span> <span class="gray" ng-if="$root.settings.expertMode">| {{::cert.pending ? \'WOT.SIGNED_ON_BLOCK\' : \'WOT.WRITTEN_ON_BLOCK\' | translate:cert}}</span></h4></span><span ng-if="!cert.isMember"><h3><i class="icon ion-clock" ng-if="cert.pending"></i> <span ng-if="cert.uid" class="dark">{{::cert.name||cert.uid}} </span><span ng-if="!cert.uid" class="gray"><i class="ion-key"></i> {{::cert.pubkey | formatPubkey}}</span></h3><h5 class="assertive">{{::\'WOT.NOT_MEMBER_PARENTHESIS\'|translate}}</h5><h4 class="gray"><span ng-if="cert.uid"><i class="ion-key"></i> {{::cert.pubkey | formatPubkey}} </span><span class="gray">| {{::cert.time|medianDate}}</span> <span class="gray" ng-if="$root.settings.expertMode">| {{::cert.pending ? \'WOT.SIGNED_ON_BLOCK\' : \'WOT.WRITTEN_ON_BLOCK\' | translate:cert}}</span></h4></span><div class="badge badge-stable" ng-class="{\'badge-energized\': cert.willExpire}" ng-if="cert.expiresIn">{{::cert.expiresIn | formatDurationTo}}</div><div class="badge badge-assertive" ng-if="!cert.expiresIn">{{::\'WOT.EXPIRED\' | translate}}</div>'); +$templateCache.put('templates/wot/item_content_identity.html','<i ng-if="::!item.avatar" class="item-image icon ion-person"></i> <i ng-if="::item.avatar" class="item-image avatar" style="background-image: url({{::item.avatar.src}})"></i><h2><ng-if ng-if="::item.name||item.uid" ng-bind-html="::item.name||item.uid"></ng-if><ng-if ng-if="::!item.name && !item.uid">{{::item.pubkey|formatPubkey}}</ng-if></h2><h4 class="gray" ng-class="{\'pull-right\': !smallscreen}" ng-if="::item.sigDate"><i class="ion-clock"></i> {{::\'WOT.LOOKUP.REGISTERED\' | translate:item }}</h4><h4 class="gray" ng-class="{\'pull-right\': !smallscreen}" ng-if="item.memberDate"><i class="ion-clock"></i> {{::\'WOT.LOOKUP.MEMBER_FROM\' | translate:item}}</h4><h4 class="gray"><span class="positive" ng-if="::item.name && item.uid"><i class="ion-person"></i> {{::item.uid}} </span><b class="ion-key"></b> {{::item.pubkey | formatPubkey}} <span ng-if="::(!item.uid && !item.revoked)" class="assertive" translate>WOT.NOT_MEMBER_PARENTHESIS</span> <span ng-if="::item.revoked" class="assertive" translate>WOT.IDENTITY_REVOKED_PARENTHESIS</span></h4><h4 ng-if="::item.events||item.tags"><span ng-repeat="event in ::item.events" class="assertive"><i class="ion-alert-circled" ng-if="::!item.valid"></i> <span ng-bind-html="::event.message|translate:event.messageParams"></span> </span><span ng-if="::item.tags" class="dark"><ng-repeat ng-repeat="tag in ::item.tags">#<ng-bind-html ng-bind-html="::tag"></ng-bind-html></ng-repeat></span></h4>'); +$templateCache.put('templates/wot/items_given_certifications.html','<div class="list given-certifications" ng-class="::motions.givenCertifications.ionListClass"><span class="item item-divider hidden-xs"><span translate>WOT.GIVEN_CERTIFICATIONS.SUMMARY</span></span><div id="helptip-certs-stock" class="item item-icon-left item-text-wrap ink"><i class="icon ion-ribbon-a"></i> <span translate>WOT.GIVEN_CERTIFICATIONS.SENT</span><cs-badge-given-certification identity="formData" parameters="$root.currency.parameters"></cs-badge-given-certification></div><div class="item item-icon-left item-text-wrap ink" ng-if="formData.given_cert_error.length"><i class="icon ion-alert-circled"></i> <span translate>WOT.GIVEN_CERTIFICATIONS.ERROR</span> <span class="badge badge-assertive">{{formData.given_cert_error.length}}</span></div><span class="item item-divider" ng-if="formData.given_cert_pending.length"><span translate>WOT.GIVEN_CERTIFICATIONS.PENDING_LIST</span><div class="badge item-note" style="text-align: right !important" translate>WOT.NOT_WRITTEN_EXPIRE_IN</div></span><a class="item item-avatar ink" ng-repeat="cert in formData.given_cert_pending" ui-sref="app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})" ng-include="\'templates/wot/item_certification.html\'"></a><span class="item item-divider"><span translate>WOT.GIVEN_CERTIFICATIONS.LIST</span><div class="badge item-note" translate>WOT.EXPIRE_IN</div></span><span class="item gray" ng-if="!formData.given_cert.length" translate>WOT.NO_GIVEN_CERTIFICATION </span><a class="item item-avatar ink" ng-repeat="cert in formData.given_cert" ui-sref="app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})" ng-include="\'templates/wot/item_certification.html\'"></a></div>'); +$templateCache.put('templates/wot/items_received_certifications.html','<div class="list certifications" ng-class="::motions.receivedCertifications.ionListClass"><span class="item item-divider hidden-xs"><span translate>WOT.CERTIFICATIONS.SUMMARY</span></span><div id="helptip-received-certs" class="item item-icon-left item-text-wrap ink"><i class="icon ion-ribbon-b"></i> <b ng-if="formData.requirements.isSentry" class="ion-star icon-secondary" style="color: yellow; font-size: 16px; left: 25px; top: -7px"></b> <span translate>WOT.CERTIFICATIONS.RECEIVED</span><h4 class="gray" ng-if="formData.requirements.isSentry" translate>WOT.CERTIFICATIONS.SENTRY_MEMBER</h4><cs-badge-certification cs-id="helptip-wot-view-certifications-count" requirements="formData.requirements" parameters="$root.currency.parameters"></cs-badge-certification></div><div class="item item-icon-left item-text-wrap ink" ng-if="formData.received_cert_error.length"><i class="icon ion-alert-circled"></i> <span translate>WOT.CERTIFICATIONS.ERROR</span> <span class="badge badge-assertive">{{formData.received_cert_error.length}}</span></div><span class="item item-divider" ng-if="formData.received_cert_pending.length"><span translate>WOT.CERTIFICATIONS.PENDING_LIST</span><div class="badge item-note" style="text-align: right !important" translate>WOT.NOT_WRITTEN_EXPIRE_IN</div></span><a class="item item-avatar ink" ng-repeat="cert in formData.received_cert_pending" ui-sref="app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})" ng-include="\'templates/wot/item_certification.html\'"></a><span class="item item-divider"><span translate>WOT.CERTIFICATIONS.LIST</span><div class="badge item-note" translate>WOT.EXPIRE_IN</div></span><span class="item gray" ng-if="!formData.received_cert.length" translate>WOT.NO_CERTIFICATION</span> <a class="item item-avatar ink" ng-repeat="cert in formData.received_cert" ui-sref="app.wot_identity({pubkey:cert.pubkey, uid:cert.uid})" ng-include="\'templates/wot/item_certification.html\'"></a></div>'); +$templateCache.put('templates/wot/lookup.html','<ion-view left-buttons="leftButtons"><ion-tabs class="tabs-positive tabs-icon-top"><ion-tab title="{{\'WOT.LOOKUP.TITLE\'|translate}}" icon="ion-person-stalker" ui-sref="app.wot_lookup.tab_search"><ion-nav-view name="tab"></ion-nav-view></ion-tab><cs-extension-point name="tabs"></cs-extension-point></ion-tabs></ion-view>'); +$templateCache.put('templates/wot/lookup_form.html','<div class="lookupForm"><div class="item no-padding"><div class="double-padding-x padding-top-xs item-text-wrap" ng-if="::allowMultiple" style="height: 36px"><div class="gray padding-top" ng-if="!selection.length && parameters.help">{{::parameters.help|translate}}</div><div ng-repeat="identity in selection track by identity.id" class="button button-small button-text button-stable button-icon-event ink" ng-class="{\'button-text-positive\': identity.selected}"><span ng-bind-html="identity.name||identity.uid||(identity.pubkey|formatPubkey)"></span> <i class="icon ion-close" ng-click="removeSelection(identity, $event)"> </i></div></div><div class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{\'WOT.SEARCH_HELP\'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()" on-return="doSearchText()" select-on-click=""><div class="helptip-anchor-center"><a id="helptip-wot-search-text"></a></div></div></div><div class="padding-top padding-xs padding-sm" style="display: block; height: 60px" ng-class="::{\'hidden-xs hidden-sm\': !showResultLabel}"><div class="pull-left" ng-if="!search.loading && showResultLabel"><ng-if ng-if="search.type==\'newcomers\'"><h4 translate="">WOT.LOOKUP.NEWCOMERS</h4><small class="gray no-padding" ng-if="search.total">{{\'WOT.LOOKUP.NEWCOMERS_COUNT\'|translate:{count: search.total} }}</small></ng-if><ng-if ng-if="search.type==\'pending\'"><h4 translate="">WOT.LOOKUP.PENDING</h4><small class="gray no-padding" ng-if="search.total">{{\'WOT.LOOKUP.PENDING_COUNT\'|translate:{count: search.total} }}</small></ng-if><h4 ng-if="search.type==\'text\'"><span translate="">COMMON.RESULTS_LIST</span> <small class="gray" ng-if="search.total">({{search.total}})</small></h4></div></div><div class="text-center padding-top" ng-if="search.loading"><p class="gray" ng-if="::$root.currency.initPhase" translate="">WOT.SEARCH_INIT_PHASE_WARNING</p><ion-spinner icon="android"></ion-spinner></div><ng-if ng-if="!search.loading"><div class="assertive padding" ng-if="!search.results.length"><span ng-if="search.type==\'text\'" translate="">COMMON.SEARCH_NO_RESULT</span> <span ng-if="search.type==\'pending\'" translate="">WOT.LOOKUP.NO_PENDING</span> <span ng-if="search.type==\'newcomers\'" translate="">WOT.LOOKUP.NO_NEWCOMERS</span></div><ion-list ng-if="::!allowMultiple && $root.device.enable" class="{{::motion.ionListClass}}" can-swipe="true"><ng-repeat ng-repeat="item in search.results track by item.id"><div ng-if="::item.divider" class="item item-divider" id="helptip-wot-search-result-{{$index}}">{{::(\'WOT.SEARCH.DIVIDER_\' + item.index)|upper|translate}}</div><ion-item ng-if="::!item.divider" id="helptip-wot-search-result-{{$index}}" class="item item-border-large item-avatar item-icon-right ink" ng-click="::select(item)"><ng-include src="item.templateUrl || \'templates/wot/item_content_identity.html\'"></ng-include><i class="icon ion-ios-arrow-right"></i><ion-option-button class="button-positive" ng-click="showTransferModal({pubkey: item.pubkey, uid: item.name ||item.uid})" translate="">COMMON.BTN_SEND_MONEY_SHORT</ion-option-button></ion-item></ng-repeat></ion-list><div ng-if="::allowMultiple" class="list {{::motion.ionListClass}}"><ion-checkbox ng-repeat="item in search.results track by item.id" ng-model="item.checked" class="item item-border-large item-avatar ink" ng-click="toggleCheck($index, $event)"><ng-include src="\'templates/wot/item_content_identity.html\'"></ng-include></ion-checkbox></div><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="20%"></ion-infinite-scroll></ng-if></div>'); +$templateCache.put('templates/wot/lookup_lg.html','<ion-view><ion-nav-title>{{\'MENU.WOT\' | translate}}</ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-qr-scanner hidden-no-device" ng-if="$root.device.barcode.enable" ng-click="scanQrCode()"></button> <button class="button button-icon button-clear visible-xs visible-sm" ng-click="showActionsPopover($event)"><i class="icon ion-android-funnel"></i></button></ion-nav-buttons><ion-content class="padding no-padding-x no-padding-sm" scroll="true"><cs-extension-point name="top"></cs-extension-point><ng-include src="\'templates/wot/lookup_form.html\'"></ng-include></ion-content></ion-view>'); +$templateCache.put('templates/wot/lookup_popover_actions.html','<ion-popover-view class="fit has-header visible-sm visible-xs"><ion-header-bar><h1 class="title" translate>COMMON.POPOVER_FILTER_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-click="doGetNewcomers()"><i class="icon ion-person"></i> {{\'WOT.LOOKUP.BTN_NEWCOMERS\' | translate}} </a><a class="item item-icon-left ink" ng-click="doGetPending()"><i class="icon ion-clock"></i> {{\'WOT.LOOKUP.BTN_PENDING\' | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/wot/modal_lookup.html','<ion-modal-view id="wotLookup" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title hidden-xs">{{::parameters.title?parameters.title:\'WOT.MODAL.TITLE\'|translate}}</h1><button class="button button-clear icon-right visible-xs ink" ng-if="allowMultiple && selection.length" ng-click="closeModal(selection)">{{::parameters.okText||\'COMMON.BTN_NEXT\' | translate}} <i ng-if="::!parameters.okText||parameters.okIcon" class="icon {{::parameters.okIcon||\'ion-ios-arrow-right\'}}"></i></button></ion-header-bar><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><div class="visible-xs visible-sm text-right stable-bg stable"><button class="button button-icon button-small-padding dark hidden-no-device ink" ng-if="$root.device.barcode.enable" ng-click="scanQrCode()"><i class="icon ion-qr-scanner"></i></button> <button class="button button-icon button-small-padding dark ink" ng-click="showActionsPopover($event)"><i class="icon ion-android-funnel"></i></button></div><ng-include src="\'templates/wot/lookup_form.html\'"></ng-include></ion-content></ion-modal-view>'); +$templateCache.put('templates/wot/modal_select_pubkey_identity.html','<ion-modal-view id="transfer" class="modal-full-height modal-transfer"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>ACCOUNT.SELECT_IDENTITY_MODAL.TITLE</h1></ion-header-bar><ion-content scroll="true"><div class="padding"><p trust-as-html="\'ACCOUNT.SELECT_IDENTITY_MODAL.HELP\'|translate:{pubkey: pubkey}"></p></div><ion-list><ion-item class="item-avatar item-icon-right" ng-repeat="item in identities" ng-click="closeModal(item)"><i class="item-image icon ion-person"></i><h2>{{item.uid}}</h2><h4 class="gray"><b class="ion-key"></b> {{::item.pubkey | formatPubkey}} <span ng-if="::!item.revoked && !item.pendingRevocation && !item.isMember" class="assertive" translate>WOT.NOT_MEMBER_PARENTHESIS</span> <span ng-if="::item.revoked || item.pendingRevocation" class="assertive bold" translate>WOT.IDENTITY_REVOKED_PARENTHESIS</span> <span ng-if="::item.meta.invalid" class="assertive" translate>ERROR.WOT_PENDING_INVALID_BLOCK_HASH</span></h4><h4 class="dark" ng-if="::item.meta.time"><i class="ion-calendar"></i> <span translate>WOT.REGISTERED_SINCE</span> {{::item.meta.time|medianDate}}</h4><ng-if ng-if="::!item.revoked && !item.pendingRevocation && (item.certificationCount || item.pendingCertificationCount)"><cs-badge-certification requirements="item" parameters="$root.currency.parameters"></cs-badge-certification><div class="gray badge badge-secondary hidden-xs"><span translate>ACCOUNT.CERTIFICATION_COUNT</span></div></ng-if><i class="icon ion-ios-arrow-right"></i></ion-item></ion-list></ion-content></ion-modal-view>'); +$templateCache.put('templates/wot/view_certifications.html','<ion-view left-buttons="leftButtons"><ion-nav-title><span class="visible-xs visible-sm">{{::formData.name||formData.uid}}</span></ion-nav-title><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point></ion-nav-buttons><ion-content class="certifications certifications-lg"><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="doUpdate()"></ion-refresher><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="row responsive-sm responsive-md responsive-lg"><div class="col no-padding" ng-if="motions.receivedCertifications.enable"><ng-include src="\'templates/wot/items_received_certifications.html\'"></ng-include></div><div class="col no-padding" ng-if="motions.givenCertifications.enable"><ng-include src="\'templates/wot/items_given_certifications.html\'"></ng-include></div></div></ion-content><div class="visible-xs visible-sm"><button id="fab-certify" class="button button-fab button-fab-bottom-right button-energized-900 spin" ng-if="canCertify && !alreadyCertified" ng-click="certify()"><i class="icon ion-ribbon-b"></i></button> <button id="fab-select-certify" class="button button-fab button-fab-bottom-right button-energized-900 spin" ng-if="canSelectAndCertify" ng-click="selectAndCertify()"><i class="icon ion-plus"></i></button></div></ion-view>'); +$templateCache.put('templates/wot/view_identity.html','<ion-view left-buttons="leftButtons" class="view-identity"><ion-nav-title></ion-nav-title><ion-content scroll="true" class="refresher-light" ng-class="{\'member refresher-positive-900-bg\': !loading && formData.isMember, \'refresher-dark-100-bg\': loading || !formData.isMember}"><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="hero" ng-class="{\'hero-qrcode-active\': toggleQRCode}"><div class="content" ng-if="!loading"><i class="avatar" ng-if=":rebind:!formData.avatar" ng-class="{\'avatar-wallet\': !formData.isMember, \'avatar-member\': formData.isMember}"></i> <i class="avatar" ng-if=":rebind:formData.avatar" style="background-image: url({{::formData.avatar.src}})"></i><ng-if ng-if=":rebind:formData.name"><h3 class="light">{{::formData.name}}</h3></ng-if><ng-if ng-if=":rebind:!formData.name"><h3 class="light" ng-if=":rebind:formData.uid">{{:rebind:formData.uid}}</h3><h3 class="light" ng-if=":rebind:!formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</h3></ng-if><h4 class="assertive"><ng-if ng-if=":rebind:(formData.name || formData.uid) && !formData.isMember && revoked" translate="">WOT.IDENTITY_REVOKED_PARENTHESIS</ng-if><ng-if ng-if=":rebind:(formData.name || formData.uid) && formData.isMember && revoked" translate="">WOT.MEMBER_PENDING_REVOCATION_PARENTHESIS</ng-if></h4></div><h4 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><div ng-attr-id="{{ qrcodeId }}" class="qrcode spin" ng-class="{\'active\': toggleQRCode}" ng-click="toggleQRCode = !toggleQRCode"></div><a id="wot-share-anchor-{{::formData.pubkey}}"></a><div class="visible-xs visible-sm"><button id="fab-certify-{{:rebind:formData.uid}}" class="button button-fab button-fab-top-left button-fab-hero button-calm spin" ng-if=":rebind:(canCertify && !alreadyCertified)" ng-click="certify()"><i class="icon ion-ribbon-b"></i></button><cs-extension-point name="buttons-top-fab"></cs-extension-point></div><div class="row no-padding"><div class="col list {{::motion.ionListClass}}" bind-notifier="{ rebind:loading}"><span class="item item-divider" translate="">WOT.GENERAL_DIVIDER</span><ion-item class="item-icon-left item-text-wrap ink" copy-on-click="{{:rebind:formData.pubkey}}"><i class="icon ion-key"></i> <span translate="">COMMON.PUBKEY</span><h4 id="pubkey" class="dark text-left">{{:rebind:formData.pubkey}}</h4></ion-item><div class="item item-icon-left item-text-wrap" ng-if=":rebind:!formData.hasSelf"><i class="icon ion-ios-help-outline positive"></i> <span translate="">WOT.NOT_MEMBER_ACCOUNT</span><h4 class="gray" translate="">WOT.NOT_MEMBER_ACCOUNT_HELP</h4></div><ion-item class="item-icon-left" ng-if=":rebind:formData.sigDate||formData.uid"><i class="icon ion-calendar"></i> <span translate="">COMMON.UID</span><h5 class="dark" ng-if=":rebind:formData.sigDate "><span translate="">WOT.REGISTERED_SINCE</span> {{:rebind:formData.sigDate|medianDate}}</h5><span class="badge badge-energized">{{:rebind:formData.uid}}</span></ion-item><a id="helptip-wot-view-certifications" class="item item-icon-left item-text-wrap item-icon-right ink" ng-if=":rebind:formData.hasSelf" ng-click="showCertifications()"><i class="icon ion-ribbon-b"></i> <b ng-if=":rebind:formData.requirements.isSentry" class="ion-star icon-secondary" style="color: yellow; font-size: 16px; left: 25px; top: -7px"></b> <span translate="">ACCOUNT.CERTIFICATION_COUNT</span><cs-badge-certification cs-id="helptip-wot-view-certifications-count" requirements="formData.requirements" parameters="{sigQty: formData.sigQty}"></cs-badge-certification><i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-text-wrap item-icon-right ink visible-xs visible-sm" ng-if=":rebind:formData.hasSelf && formData.isMember" ng-click="showGivenCertifications()"><i class="icon ion-ribbon-a"></i> <span translate="">WOT.GIVEN_CERTIFICATIONS.SENT</span><cs-badge-given-certification identity="formData" parameters="$root.currency.parameters"></cs-badge-given-certification><i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-icon-right ink" ng-if="!loading" ui-sref="app.wot_identity_tx_uid({uid:formData.uid,pubkey:formData.pubkey})"><i class="icon ion-card"></i> <span translate="">WOT.ACCOUNT_OPERATIONS</span> <i class="gray icon ion-ios-arrow-right"></i></a><div class="item item-text-wrap item-icon-left item-wallet-event" ng-class="{\'assertive\': event.type==\'error\'}" ng-repeat="event in :rebind:formData.events"><i class="icon" ng-class="{\'ion-information-circled royal\': event.type==\'info\',\'ion-alert-circled\': event.type==\'warn\'||event.type==\'error\',\'assertive\': event.type==\'error\',\'ion-clock\': event.type==\'pending\'}"></i> <span trust-as-html="event.message | translate:event.messageParams"></span></div><cs-extension-point name="general"></cs-extension-point><cs-extension-point name="after-general"></cs-extension-point></div></div></ion-content><div class="visible-xs visible-sm" ng-hide="loading"><button id="fab-transfer" class="button button-fab button-fab-bottom-right button-assertive drop" ng-click="showTransferModal({pubkey:formData.pubkey, uid: formData.uid})"><i class="icon ion-android-send"></i></button></div></ion-view>'); +$templateCache.put('templates/wot/view_identity_tx.html','<ion-view left-buttons="leftButtons"><ion-nav-title><span class="visible-xs visible-sm" ng-if="!loading"><span ng-if="formData.name || formData.uid">{{formData.name || formData.uid}} </span><span ng-if="!formData.name && !formData.uid"><i class="ion-key"></i> {{formData.pubkey|formatPubkey}}</span></span></ion-nav-title><ion-content scroll="true"><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="list {{motion.ionListClass}}" ng-if="!loading"><div class="row"><div class="col"><div class="item item-tx item-divider">{{:locale:\'ACCOUNT.BALANCE_ACCOUNT\'|translate}}<div class="badge item-note" ng-class=":balance:{\'badge-assertive\': formData.balance <= 0, \'badge-balanced\': formData.balance > 0 }" ng-bind-html=":balance:formData.balance|formatAmount:{currency: $root.currency.name}"></div><div class="badge badge-secondary" ng-if="$root.settings.expertMode">(<span ng-bind-html=":balance:formData.balance| formatAmount: {useRelative: !$root.settings.useRelative, currency: $root.currency.name} "></span>)</div></div><div class="item item-icon-left" ng-if="formData.tx.errors.length"><i class="icon ion-alert-circled"></i> {{:locale:\'ACCOUNT.ERROR_TX\'|translate}}<div class="badge badge-assertive">{{formData.tx.errors.length}}</div></div><ng-if ng-if="formData.tx.pendings.length"><span class="item item-pending item-divider"><i class="ion-clock"></i> {{:locale:\'ACCOUNT.PENDING_TX\'|translate}}</span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.pendings" ng-init="pending=true;" ng-include="::\'templates/wallet/item_tx.html\'"></div></ng-if><ng-if ng-if="formData.tx.validating.length"><span class="item item-pending item-divider">{{:locale:\'ACCOUNT.VALIDATING_TX\'|translate}}</span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.validating" ng-init="validating=true;" ng-include="::\'templates/wallet/item_tx.html\'"></div></ng-if><span class="item item-divider" ng-if="!loading">{{:locale:\'ACCOUNT.LAST_TX\'|translate}} <a id="helptip-wallet-tx" style="position: relative; bottom: 0; right: 0px"> </a></span><div ng-repeat="tx in formData.tx.history" class="item item-tx item-icon-left" ng-include="::!tx.isUD ? \'templates/wallet/item_tx.html\' : \'templates/wallet/item_ud.html\'"></div><div class="item item-text-wrap text-center" ng-if="formData.tx.fromTime > 0"><p><a ng-click="showMoreTx()">{{:locale:\'ACCOUNT.SHOW_MORE_TX\'|translate}}</a> <span class="gray" translate="ACCOUNT.TX_FROM_DATE" translate-values="{fromTime: formData.tx.fromTime}"></span> <span class="gray">|</span> <a ng-click="showMoreTx(-1)" translate="">ACCOUNT.SHOW_ALL_TX</a></p></div></div></div></div></ion-content></ion-view>'); +$templateCache.put('templates/currency/tabs/tab_blocks.html','<ion-view><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-navicon visible-xs visible-sm" ng-click="toggleCompactMode()"><b class="icon-secondary" ng-class="{\'ion-arrow-down-b\': !compactMode, \'ion-arrow-up-b\': compactMode}" style="top: -12px; left: 11px; font-size: 10px"></b> <b class="icon-secondary" ng-class="{\'ion-arrow-up-b\': !compactMode,\'ion-arrow-down-b\': compactMode}" style="top: 12px; left: 11px; font-size: 10px"></b></button><cs-extension-point name="nav-buttons"></cs-extension-point></ion-nav-buttons><ion-content><div class="item item-divider"><span translate>BLOCKCHAIN.LOOKUP.LAST_BLOCKS</span></div><cs-extension-point name="buttons"></cs-extension-point><ng-include src="\'templates/blockchain/list_blocks.html\'"></ng-include></ion-content></ion-view>'); +$templateCache.put('templates/currency/tabs/tab_network.html','<ion-view><ion-nav-buttons side="secondary"><button class="button button-icon button-clear" ng-click="showExtendActionsPopover($event)"><i class="icon ion-android-funnel"></i></button></ion-nav-buttons><ion-content><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="refreshPeers()"></ion-refresher><div class="list"><ng-include src="\'templates/currency/items_network.html\'"></ng-include></div></ion-content></ion-view>'); +$templateCache.put('templates/currency/tabs/tab_parameters.html','<ion-view><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point></ion-nav-buttons><ion-content><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="refresh()"></ion-refresher><div class="list"><ng-include src="\'templates/currency/items_parameters.html\'"></ng-include></div></ion-content></ion-view>'); +$templateCache.put('templates/currency/tabs/tab_wot.html','<ion-view><ion-content><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="refresh()"></ion-refresher><div class="list"><ng-include src="\'templates/currency/items_wot.html\'"></ng-include></div></ion-content></ion-view>'); +$templateCache.put('templates/wallet/list/item_wallet.html','<div class="item item-avatar item-icon-right item-border-large item-wallet ink" id="wallet-{{::wallet.id}}" ng-click="select($event, wallet)" ng-init="walletData=wallet.data;"><i ng-if=":rebind:!walletData.avatar" class="item-image icon" ng-class=":rebind:{\'ion-card\': !walletData.isMember, \'ion-person\': walletData.isMember}"></i> <i ng-if=":rebind:walletData.avatar" class="item-image avatar" style="background-image: url({{::walletData.avatar.src}})"></i><div class="badge badge-button badge-avatar badge-assertive ion-locked" ng-hide=":rebind:wallet.isAuth()"></div><h2><span class="text-editable" ng-click="editWallet($event, wallet)" title="{{\'ACCOUNT.WALLET_LIST.BTN_RENAME\'|translate}}"><ng-if ng-if=":rebind:walletData.localName||walletData.name||walletData.uid" ng-bind-html="::walletData.localName||walletData.name||walletData.uid"></ng-if><ng-if ng-if=":rebind:!walletData.localName && !walletData.name && !walletData.uid">{{::walletData.pubkey|formatPubkey}}</ng-if></span></h2><h4 class="gray"><span class="positive" ng-if="::walletData.name && walletData.uid"><i class="ion-person"></i> {{::walletData.uid}} </span><b class="ion-key"></b> {{::walletData.pubkey | formatPubkey}} <span ng-if="::!walletData.uid" class="assertive" translate>WOT.NOT_MEMBER_PARENTHESIS</span></h4><cs-extension-point name="item-wallet"></cs-extension-point><span class="badge" ng-if=":rebind:formData.showBalance && walletData.sources" ng-class=":rebind:{\'badge-calm\': (walletData.balance > 0) }"><ion-spinner class="ion-spinner-small" ng-if="formData.updatingWalletId==wallet.id" icon="android"></ion-spinner><span ng-bind-html=":rebind:walletData.balance|formatAmount:{useRelative: formData.useRelative, currency: currency}"></span> </span><i class="icon ion-ios-arrow-right"></i></div>'); +$templateCache.put('templates/wallet/list/item_wallet_light.html','<div class="item item-avatar item-icon-right item-border item-wallet" ng-click="select($event, wallet)" ng-init="walletData=wallet.data;"><i ng-if="::!walletData.avatar" class="item-image icon" ng-class="::{\'ion-card\': !walletData.isMember, \'ion-person\': walletData.isMember}"></i> <i ng-if="::walletData.avatar" class="item-image avatar" style="background-image: url({{::walletData.avatar.src}})"></i><div class="badge badge-button badge-avatar badge-assertive ion-locked" ng-hide="::wallet.isAuth()"></div><h2><ng-if ng-if="::walletData.localName||walletData.name||walletData.uid">{{::walletData.localName||walletData.name||walletData.uid}}</ng-if><ng-if ng-if="::!walletData.localName && !walletData.name && !walletData.uid">{{::walletData.pubkey|formatPubkey}}</ng-if></h2><h4 class="gray"><span class="positive" ng-if="::walletData.name && walletData.uid"><i class="ion-person"></i> {{::walletData.uid}} </span><b class="ion-key"></b> {{::walletData.pubkey | formatPubkey}} <span ng-if="::!walletData.uid" class="assertive" translate>WOT.NOT_MEMBER_PARENTHESIS</span></h4><div class="badge" ng-if="formData.showBalance" ng-class="{\'badge-calm\': (walletData.balance > 0) }"><span ng-bind-html="walletData.balance|formatAmount:{useRelative: formData.useRelative, currency: currency}"></span></div><i class="icon ion-ios-arrow-right"></i></div>'); +$templateCache.put('templates/wallet/list/modal_import_file.html','<ion-modal-view id="transfer" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>ACCOUNT.WALLET_LIST.IMPORT_MODAL.TITLE</h1></ion-header-bar><ion-content scroll="true" class="padding"><p translate>ACCOUNT.WALLET_LIST.IMPORT_MODAL.HELP</p><div dropzone="importFromFile(file)"><div ng-if="!hasContent" onclick="angular.element(document.querySelector(\'#walletsImportFile\'))[0].click();"><h2 class="gray" translate>COMMON.CHOOSE_FILE</h2><input type="file" id="walletsImportFile" accept=".csv,.txt" style="visibility:hidden; position:absolute" on-read-file="importFromFile(file)"></div><div ng-if="hasContent" class="item item-icon-left item-icon-right stable-bg"><i class="icon ion-document-text gray"></i><div class="item-content row"><div class="col"><h2>{{fileData.name}}</h2><h4 ng-if="fileData.lastModified"><span class="gray" translate>COMMON.FILE.DATE</span> {{fileData.lastModified/1000|formatDate}}</h4><h5><span class="gray" translate>COMMON.FILE.SIZE</span> {{fileData.size|formatInteger}} Ko</h5></div><div class="col padding-left"><h3 ng-if="validatingFile" translate>COMMON.FILE.VALIDATING</h3><h3 ng-if="!validatingFile"><span class="dark animate-show-hide ng-hide" ng-show="isValidFile && content.length" ng-bind-html="\'ACCOUNT.WALLET_LIST.IMPORT_MODAL.WALLET_COUNT\'|translate:{count: content.length}"></span> <span class="assertive animate-show-hide ng-hide" ng-show="isValidFile && !content.length"><br><i class="ion-close-circled assertive"></i> {{\'ACCOUNT.WALLET_LIST.IMPORT_MODAL.NO_NEW_WALLET\' |translate}} </span><span class="assertive animate-show-hide ng-hide" ng-show="!isValidFile"><br><i class="ion-close-circled assertive"></i> {{\'ERROR.INVALID_FILE_FORMAT\' |translate}}</span></h3></div></div><a class="ion-close-round gray pull-right" style="font-size: 10px; position: absolute; top: 6px; right: 6px" ng-click="removeFile()"></a></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" ng-disabled="loading || !content.length" ng-click="closeModal(content)" translate>COMMON.BTN_IMPORT</button></div></ion-content></ion-modal-view>'); +$templateCache.put('templates/wallet/list/modal_wallets.html','<ion-modal-view id="transfer" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>ACCOUNT.SELECT_WALLET_MODAL.TITLE</h1></ion-header-bar><ion-content scroll="true"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding gray" ng-if="!loading && !wallets.length && !defaultWallet">{{:locale:\'ACCOUNT.WALLET_LIST.NO_WALLET\'|translate}}</div><ion-list ng-if="!loading" class="{{::motion.ionListClass}}"><ng-include ng-if="defaultWallet" ng-init="wallet = defaultWallet" src="\'templates/wallet/list/item_wallet.html\'"></ng-include><ng-repeat ng-repeat="wallet in wallets track by wallet.id" ng-include="\'templates/wallet/list/item_wallet_light.html\'"></ng-repeat></ion-list></ion-content></ion-modal-view>'); +$templateCache.put('templates/wallet/list/popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate="">COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><button class="item item-icon-left ink" ng-class="{\'gray\': loading || !wallets.length, \'assertive\': !loading && wallets.length}" ng-disabled="loading || !wallets.length" ng-click="selectAndRemoveWallet()"><i class="icon ion-trash-a"></i> {{\'ACCOUNT.WALLET_LIST.BTN_DELETE\' | translate}}</button></div></ion-content></ion-popover-view>'); +$templateCache.put('templates/wallet/list/popover_wallets.html','<ion-popover-view class="fit popover-wallets popover-light"><ion-header-bar class="stable-bg block"><div class="title" translate>ACCOUNT.SELECT_WALLET_MODAL.TITLE</div><div class="pull-right"><a class="positive" ng-click="showNewWalletModal()" translate>ACCOUNT.WALLET_LIST.BTN_NEW</a></div></ion-header-bar><ion-content scroll="true"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding gray" ng-if="!loading && !wallets.length && !defaultWallet">{{:locale:\'ACCOUNT.WALLET_LIST.NO_WALLET\'|translate}}</div><ion-list ng-if="!loading"><ng-include ng-if="defaultWallet" ng-init="wallet = defaultWallet" src="\'templates/wallet/list/item_wallet_light.html\'"></ng-include><ng-repeat ng-repeat="wallet in :rebind:wallets | filter:filterFn(formData) track by wallet.id" ng-include="\'templates/wallet/list/item_wallet_light.html\'"></ng-repeat></ion-list></ion-content><ion-footer-bar class="stable-bg block"><div class="pull-right"><a class="positive" ui-sref="app.view_wallets" ng-click="closePopover()" translate>COMMON.NOTIFICATIONS.SHOW_ALL</a></div></ion-footer-bar></ion-popover-view>'); +$templateCache.put('templates/wallet/list/popup_edit_name.html','<form name="editForm" ng-submit=""><div class="list" ng-init="setEditForm(editForm)"><label class="item item-input" ng-class="{\'item-input-error\': editForm.$submitted && editForm.name.$invalid}"><input name="name" type="text" placeholder="{{\'ACCOUNT.WALLET_LIST.EDIT_POPOVER.NAME_HELP\' | translate}}" ng-model="formData.name" ng-minlength="3" required></label><div class="form-errors" ng-if="editForm.$submitted && editForm.name.$error" ng-messages="editForm.name.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div></div></form>'); +$templateCache.put('templates/wallet/list/view_wallets.html','<ion-view left-buttons="leftButtons" class="view-wallet-list"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true" class="padding no-padding-xs no-padding-sm" bind-notifier="{ rebind:formData.useRelative, locale:settings.locale.id}"><ion-refresher pulling-text="{{:locale:\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="doUpdate(true, $event)"></ion-refresher><div class="center padding gray" ng-if="!loading && wallets && !wallets.length && !defaultWallet">{{:locale:\'ACCOUNT.WALLET_LIST.NO_WALLET\'|translate}}</div><ion-list class="{{::motion.ionListClass}}"><ng-include ng-if="defaultWallet" ng-init="wallet = defaultWallet" src="\'templates/wallet/list/item_wallet.html\'"></ng-include><ng-include ng-repeat="wallet in wallets track by wallet.id" src="\'templates/wallet/list/item_wallet.html\'"></ng-include></ion-list><div class="center padding visible-xs visible-sm" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div></ion-content><button id="fab-add-wallet" class="button button-fab button-fab-bottom-right button-assertive hidden-md hidden-lg drop ng-hide" ng-show="!loading" ng-click="showNewWalletModal()"><i class="icon ion-plus"></i></button></ion-view>'); +$templateCache.put('templates/wallet/slides/slides_generate_keyfile.html','<ion-content class="has-header padding"><h3 translate>ACCOUNT.SECURITY.GENERATE_KEYFILE</h3><div class="list"><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="downloadKeyFile(\'PubSec\')"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-document-text"></i> <b class="ion-ios-redo icon-secondary dark" style="top: -8px; left: 42px; font-size: 12px"></b><h2 translate>ACCOUNT.SECURITY.KEYFILE.PUBSEC_FORMAT</h2><h4 class="gray" translate>ACCOUNT.SECURITY.KEYFILE.PUBSEC_FORMAT_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="downloadKeyFile(\'WIF\')"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-document-text"></i> <b class="ion-ios-redo icon-secondary dark" style="top: -8px; left: 42px; font-size: 12px"></b><h2 translate>ACCOUNT.SECURITY.KEYFILE.WIF_FORMAT</h2><h4 class="gray" translate>ACCOUNT.SECURITY.KEYFILE.WIF_FORMAT_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="downloadKeyFile(\'EWIF\')"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-document-text"></i> <b class="ion-ios-redo icon-secondary dark" style="top: -8px; left: 42px; font-size: 12px"></b> <b class="ion-locked icon-secondary dark" style="top: 0px; left: 43px; font-size: 8px"></b><h2 translate>ACCOUNT.SECURITY.KEYFILE.EWIF_FORMAT</h2><h4 class="gray" translate>ACCOUNT.SECURITY.KEYFILE.EWIF_FORMAT_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div></div></ion-content>'); +$templateCache.put('templates/wallet/slides/slides_recoverID_1.html','<ion-content class="has-header padding"><h3 translate>ACCOUNT.SECURITY.RECOVER_ID</h3><div dropzone="recoverContent(file)"><div ng-if="!hasContent" onclick="angular.element(document.querySelector(\'#saveIdFile\'))[0].click();"><h2 class="gray" translate>COMMON.CHOOSE_FILE</h2><input type="file" id="saveIdFile" accept=".txt" style="visibility:hidden; position:absolute" on-read-file="recoverContent(file)"></div><div ng-if="hasContent" class="item row item-icon-left no-padding"><i class="icon ion-document-text gray"></i><div class="col"><span>{{fileData.name}}</span><br><small>{{fileData.size}} Ko</small></div><div class="col-10"><b ng-class="{\'ion-android-done balanced\': isValidFile,\'ion-close-circled assertive\': !isValidFile}" style="font-size: 28px; position: relative; top: 6px"></b> <button class="button-icon ion-close-round gray pull-right" style="font-size:10px" ng-click="restore()"></button></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" ng-click="doNext()" translate>COMMON.BTN_NEXT <i class="icon ion-arrow-right-a"></i></button></div></ion-content>'); +$templateCache.put('templates/wallet/slides/slides_recoverID_2.html','<ion-content class="has-header padding"><h3 translate>ACCOUNT.SECURITY.RECOVER_ID</h3><form name="recoverForm" novalidate ng-submit="recoverId()"><div class="list" ng-init="setForm(recoverForm, \'recoverForm\')"><ng-repeat ng-repeat="question in recover.questions "><label class="item item-input {{smallscreen ? \'item-stacked-label\' : \'item-floating-label\'}}" ng-class="{\'item-input-error\': recoverForm.$submitted && recoverForm[\'question{{$index}}\'].$invalid}"><span class="input-label" style="{{smallscreen ? \'white-space: normal\' : \'\'}}">{{question.value }}</span> <input type="text" name="question{{$index}}" placeholder="{{smallscreen ? \'\' : question.value }}" ng-model="question.answer" required></label><div class="form-errors" ng-show="recoverForm.$submitted && recoverForm[\'question{{$index}}\'].$error" ng-messages="recoverForm[\'question{{$index}}\'].$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div></ng-repeat><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-clear button-dark" ng-click="restore()" type="button" translate>ACCOUNT.SECURITY.BTN_CLEAN</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" translate>COMMON.BTN_NEXT <i class="icon ion-arrow-right-a"></i></button></div></div></form></ion-content>'); +$templateCache.put('templates/wallet/slides/slides_recoverID_3.html','<ion-content class="has-header padding"><h3 translate>ACCOUNT.SECURITY.RECOVER_ID</h3><div class="item item-input"><span class="input-label">{{\'LOGIN.SALT\' | translate}} :</span> <span>{{recover.salt}}</span></div><div class="item item-input"><span class="input-label">{{\'LOGIN.PASSWORD\' | translate}} :</span> <span>{{recover.pwd}}</span></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CLOSE</button></div></ion-content>'); +$templateCache.put('templates/wallet/slides/slides_revocation_file.html','<ion-content class="has-header padding"><p translate>ACCOUNT.SECURITY.REVOCATION_WITH_FILE_HELP</p><div dropzone="recoverContent(file)"><div ng-if="!hasContent" onclick="angular.element(document.querySelector(\'#revocationFile\'))[0].click();"><h2 class="gray" translate>COMMON.CHOOSE_FILE</h2><input type="file" id="revocationFile" accept=".txt" style="visibility:hidden; position:absolute" on-read-file="recoverContent(file)"></div><div ng-if="hasContent" class="item row item-icon-left no-padding"><i class="icon ion-document-text gray"></i><div class="col"><span>{{fileData.name}}</span><br><small>{{fileData.size}} Ko</small></div><div class="col-10"><b ng-class="{\'ion-android-done balanced\': isValidFile,\'ion-close-circled assertive\': !isValidFile}" style="font-size: 28px; position: relative; top: 6px"></b> <button class="button-icon ion-close-round gray pull-right" style="font-size:10px" ng-click="restore()"></button></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" ng-click="revokeWithFile()" translate>COMMON.BTN_NEXT <i class="icon ion-arrow-right-a"></i></button></div></ion-content>'); +$templateCache.put('templates/wallet/slides/slides_saveID_1.html','<ion-content class="has-header padding"><h3 translate>ACCOUNT.SECURITY.SAVE_ID</h3><label class="item item-input item-select"><div class="input-label" translate>ACCOUNT.SECURITY.LEVEL</div><select ng-model="formData.level"><option value="2" ng-bind-html="\'ACCOUNT.SECURITY.LOW_LEVEL\' | translate"></option><option value="4" translate>ACCOUNT.SECURITY.MEDIUM_LEVEL</option><option value="6" translate>ACCOUNT.SECURITY.STRONG_LEVEL</option></select></label><div class="padding-top" translate="ACCOUNT.SECURITY.HELP_LEVEL" translate-values="{nb: {{formData.level}}}"></div><form name="questionsForm" novalidate ng-submit="doNext(\'questionsForm\')"><div class="list" ng-init="setForm(questionsForm, \'questionsForm\')"><ion-checkbox ng-repeat="question in formData.questions" ng-model="question.checked" ng-required="isRequired()"><span style="white-space: normal">{{question.value | translate}}</span></ion-checkbox><div class="item item-icon-right no-padding-top"><a class="dark"><i class="icon ion-android-add" ng-click="addQuestion()"></i></a><div class="list list-inset"><label class="item item-input"><input type="text" placeholder="{{\'ACCOUNT.SECURITY.ADD_QUESTION\' | translate}}" ng-model="formData.addQuestion"></label></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-clear button-dark" ng-click="restore()" type="button" translate>ACCOUNT.SECURITY.BTN_RESET</button> <button class="button button-calm icon-right ion-chevron-right ink" ng-disabled="questionsForm.$invalid" type="submit" translate>COMMON.BTN_NEXT <i class="icon ion-arrow-right-a"></i></button></div></form></ion-content>'); +$templateCache.put('templates/wallet/slides/slides_saveID_2.html','<ion-content class="has-header padding"><h3 translate>ACCOUNT.SECURITY.SAVE_ID</h3><form name="answersForm" novalidate ng-submit="doNext(\'answersForm\')"><div class="list" ng-init="setForm(answersForm, \'answersForm\')"><ng-repeat ng-repeat="question in formData.questions |filter:true:checked"><label class="item item-input item-text-wrap {{smallscreen ? \'item-stacked-label\' : \'item-floating-label\'}}" ng-class="{\'item-input-error\': answersForm.$submitted && answersForm[\'question{{$index}}\'].$invalid}"><span class="input-label" style="width: 100%; max-width: inherit">{{question.value | translate}}</span> <input type="text" name="question{{$index}}" placeholder="{{smallscreen ? \'\' : question.value | translate}}" ng-model="question.answer" required></label><div class="form-errors" ng-show="answersForm.$submitted && answersForm[\'question{{$index}}\'].$error" ng-messages="answersForm[\'question{{$index}}\'].$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div></ng-repeat><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-clear button-dark" ng-click="restore()" type="button" translate>ACCOUNT.SECURITY.BTN_CLEAN</button> <button class="button button-positive ink" type="submit" translate>COMMON.BTN_CONTINUE <i class="icon ion-android-archive"></i></button></div></div></form></ion-content>'); +$templateCache.put('templates/wot/tabs/tab_given_certifications.html','<ion-view><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-loop" ng-click="doUpdate()"></button></ion-nav-buttons><ion-content ng-init="motions.receivedCertifications=false; motions.avatar=false"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><ng-include src="\'templates/wot/items_given_certifications.html\'"></ng-include></ion-content><div class="visible-xs visible-sm"><button id="fab-select-certify" class="button button-fab button-fab-bottom-right button-energized-900 spin" ng-if="canSelectAndCertify || $root.tour" ng-click="selectAndCertify()"><i class="icon ion-plus"></i></button></div></ion-view>'); +$templateCache.put('templates/wot/tabs/tab_lookup.html','<ion-view><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point><button class="button button-icon button-clear" ng-click="showActionsPopover($event)"><i class="icon ion-android-funnel"></i></button></ion-nav-buttons><ion-content><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="doSearch()"></ion-refresher><cs-extension-point name="buttons"></cs-extension-point><ng-include src="\'templates/wot/lookup_form.html\'"></ng-include></ion-content></ion-view>'); +$templateCache.put('templates/wot/tabs/tab_received_certifications.html','<ion-view><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-loop" ng-click="doUpdate()"></button></ion-nav-buttons><ion-content ng-init="motions.givenCertifications=false; motions.avatar=false;" class="has-header"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><ng-include src="\'templates/wot/items_received_certifications.html\'"></ng-include></ion-content><div class="visible-xs visible-sm"><button id="fab-certify" class="button button-fab button-fab-bottom-right button-energized-900 spin" ng-click="certify()" ng-if="(formData.hasSelf && canCertify && !alreadyCertified) || $root.tour"><i class="icon ion-ribbon-b"></i></button></div></ion-view>');}]); \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/translations.js b/assets/www/dist/dist_js/app/translations.js index 3ef78a553d87d87fa2315c82ee5a92ca45abb8bd..7bfe22f89509fbc9f6615bc22bed5a821754849e 100644 --- a/assets/www/dist/dist_js/app/translations.js +++ b/assets/www/dist/dist_js/app/translations.js @@ -18,9 +18,10 @@ $translateProvider.translations("en-GB", { "BTN_YES_CONTINUE": "Yes, Continue", "BTN_SHOW": "Show", "BTN_SHOW_PUBKEY": "Show key", - "BTN_RELATIVE_UNIT": "Use relative unit", + "BTN_RELATIVE_UNIT": "Display amounts in UD?", "BTN_BACK": "Back", "BTN_NEXT": "Next", + "BTN_IMPORT": "Import", "BTN_CANCEL": "Cancel", "BTN_CLOSE": "Close", "BTN_LATER": "Later", @@ -37,7 +38,7 @@ $translateProvider.translations("en-GB", { "BTN_START": "Start", "BTN_CONTINUE": "Continue", "BTN_CREATE": "Create", - "BTN_UNDERSTOOD": "I understood", + "BTN_UNDERSTOOD": "I understand", "BTN_OPTIONS": "Options", "BTN_HELP_TOUR": "Features tour", "BTN_HELP_TOUR_SCREEN": "Discover this screen", @@ -49,6 +50,7 @@ $translateProvider.translations("en-GB", { "NO_ACCOUNT_QUESTION": "Not a member yet? Register now!", "SEARCH_NO_RESULT": "No result found", "LOADING": "Loading...", + "LOADING_WAIT": "Loading...<br/><small>(Waiting for node availability)</small>", "SEARCHING": "Searching...", "FROM": "From", "TO": "To", @@ -78,6 +80,12 @@ $translateProvider.translations("en-GB", { "SHARE_ON_FACEBOOK": "Share on Facebook", "SHARE_ON_DIASPORA": "Share on Diaspora*", "SHARE_ON_GOOGLEPLUS": "Share on Google+" + }, + "FILE": { + "DATE" : "Date:", + "TYPE" : "Type:", + "SIZE": "Size:", + "VALIDATING": "Validating..." } }, "SYSTEM": { @@ -90,6 +98,7 @@ $translateProvider.translations("en-GB", { "WOT": "Registry", "CURRENCY": "Currency", "ACCOUNT": "My Account", + "WALLETS": "My wallets", "TRANSFER": "Transfer", "SCAN": "Scan", "SETTINGS": "Settings", @@ -98,14 +107,16 @@ $translateProvider.translations("en-GB", { }, "ABOUT": { "TITLE": "About", - "LICENSE": "<b>Free/libre software</b> (License GNU GPLv3).", + "LICENSE": "<b>Free/libre software</b> (License GNU AGPLv3).", "LATEST_RELEASE": "There is a <b>newer version</ b> of {{'COMMON.APP_NAME' | translate}} (<b>v{{version}}</b>)", "PLEASE_UPDATE": "Please update {{'COMMON.APP_NAME' | translate}} (latest version: <b>v{{version}}</b>)", "CODE": "Source code:", + "OFFICIAL_WEB_SITE": "Official web site:", "DEVELOPERS": "Developers:", "FORUM": "Forum:", "PLEASE_REPORT_ISSUE": "Please report any issue to us!", - "REPORT_ISSUE": "Report an issue" + "REPORT_ISSUE": "Report an issue", + "BTN_OPEN_DEV_WINDOW": "Open the debug window" }, "HOME": { "TITLE": "Cesium", @@ -121,18 +132,27 @@ $translateProvider.translations("en-GB", { }, "SETTINGS": { "TITLE": "Settings", + "DISPLAY_DIVIDER": "Display", + "STORAGE_DIVIDER": "Storage", "NETWORK_SETTINGS": "Network", "PEER": "Duniter peer address", + "PEER_SHORT": "Peer address", "PEER_CHANGED_TEMPORARY": "Address used temporarily", "USE_LOCAL_STORAGE": "Enable local storage", "USE_LOCAL_STORAGE_HELP": "Allows you to save your settings", + "WALLETS_SETTINGS": "My wallets", + "USE_WALLETS_ENCRYPTION": "Secure the list", + "USE_WALLETS_ENCRYPTION_HELP": "Enables you to encrypt the list of your wallets. Authentication required to access it.", "ENABLE_HELPTIP": "Enable contextual help tips", "ENABLE_UI_EFFECTS": "Enable visual effects", "HISTORY_SETTINGS": "Account operations", "DISPLAY_UD_HISTORY": "Display produced dividends?", + "TX_HISTORY_AUTO_REFRESH": "Enable automatic refresh?", + "TX_HISTORY_AUTO_REFRESH_HELP": "Updates the list of operations to each new block.", "AUTHENTICATION_SETTINGS": "Authentication", "KEEP_AUTH": "Expiration of authentication", - "KEEP_AUTH_HELP": "Define when authentication is cleared from memory", + "KEEP_AUTH_SHORT": "Expiration", + "KEEP_AUTH_HELP": "Define when authentication is cleared from memory.", "KEEP_AUTH_OPTION": { "NEVER": "After each operation", "SECONDS": "After {{value}}s of inactivity", @@ -141,12 +161,21 @@ $translateProvider.translations("en-GB", { "HOUR": "After {{value}}h of inactivity", "ALWAYS": "At the end of the session" }, + "KEYRING_FILE": "Keyring file", + "KEYRING_FILE_HELP": "Allow auto-connect at startup, or to authenticate (only if \"Expiration of authentication\" is \"at the end of the session\"", "REMEMBER_ME": "Remember me ?", "REMEMBER_ME_HELP": "Allows to remain identified from one session to another, keeping the public key locally.", "PLUGINS_SETTINGS": "Extensions", "BTN_RESET": "Restore default values", "EXPERT_MODE": "Enable expert mode", "EXPERT_MODE_HELP": "Allow to see more details", + "BLOCK_VALIDITY_WINDOW": "Block uncertainty time", + "BLOCK_VALIDITY_WINDOW_SHORT": "Time of uncertainty", + "BLOCK_VALIDITY_WINDOW_HELP": "Time to wait before considering an information is validated", + "BLOCK_VALIDITY_OPTION": { + "NONE": "No delay", + "N": "{{time | formatDuration}} ({{count}} blocks)" + }, "POPUP_PEER": { "TITLE" : "Duniter peer", "HOST" : "Address", @@ -281,15 +310,18 @@ $translateProvider.translations("en-GB", { "PEERS": "Peers", "SIGNED_ON_BLOCK": "Signed on block", "MIRROR": "mirror", - "MIRRORS": "Mirror peers", + "MIRRORS": "Mirrors", + "MIRROR_PEERS": "Mirror peers", "PEER_LIST" : "Peer's list", - "MEMBERS" : "Member peers", + "MEMBERS" : "Members", + "MEMBER_PEERS" : "Member peers", "ALL_PEERS" : "All peers", "DIFFICULTY" : "Difficulty", "API" : "API", "CURRENT_BLOCK" : "Block #", "POPOVER_FILTER_TITLE": "Filter", - "OFFLINE": "Offline peers", + "OFFLINE": "Offline", + "OFFLINE_PEERS": "Offline peers", "BTN_SHOW_PEER": "Show peer", "VIEW": { "TITLE": "Peer", @@ -339,7 +371,7 @@ $translateProvider.translations("en-GB", { "PENDING": "Pending registrations:", "PENDING_COUNT": "{{count}} pending registrations", "REGISTERED": "Registered {{sigDate | formatFromNow}}", - "MEMBER_FROM": "Member since {{memberDate|formatFromNowShort}}", + "MEMBER_FROM": "Member since {{memberDate|medianFromNowShort}}", "BTN_NEWCOMERS": "Latest members", "BTN_PENDING": "Pending registrations", "SHOW_MORE": "Show more", @@ -381,14 +413,17 @@ $translateProvider.translations("en-GB", { "SCRYPT_FORM_HELP": "Please enter your credentials. <br> Remember to check the public key for your account.", "PUBKEY_FORM_HELP": "Please enter a public account key:", "FILE_FORM_HELP": "Choose the keychain file to use:", + "SCAN_FORM_HELP": "Scan the QR code of a wallet.", "SALT": "Secret identifier", "SALT_HELP": "Secret identifier", "SHOW_SALT": "Display secret identifier?", "PASSWORD": "Password", "PASSWORD_HELP": "Password", - "PUBKEY_HELP": "Example: « AbsxSY4qoZRzyV2irfep1V9xw1EMNyKJw2TkuVD4N1mv »", + "PUBKEY_HELP": "Public key or pseudonym", "NO_ACCOUNT_QUESTION": "Don't have an account yet?", + "HAVE_ACCOUNT_QUESTION": "Already have an account ?", "CREATE_ACCOUNT": "Create an account", + "CREATE_FREE_ACCOUNT": "Create a free account", "FORGOTTEN_ID": "Forgot password?", "ASSOCIATED_PUBKEY": "Public key :", "BTN_METHODS": "Other methods", @@ -403,10 +438,11 @@ $translateProvider.translations("en-GB", { "IDLE_WARNING": "You will be logout... {{countdown}}" }, "METHOD": { - "SCRYPT_DEFAULT": "Standard salt (default)", + "SCRYPT_DEFAULT": "Secret identifier and password", "SCRYPT_ADVANCED": "Advanced salt", "FILE": "Keychain file", - "PUBKEY": "Public key only" + "PUBKEY": "Public key or pseudonym", + "SCAN": "Scan a QR code" }, "SCRYPT": { "SIMPLE": "Light salt", @@ -420,44 +456,47 @@ $translateProvider.translations("en-GB", { "p": "p (CPU):" }, "FILE": { - "DATE" : "Date:", - "TYPE" : "Type:", - "SIZE": "Size:", - "VALIDATING": "Validating...", "HELP": "Expected file format: <b>.dunikey</b> (type PubSec). Other formats are under development (EWIF, WIF)." } }, "AUTH": { "TITLE": "<i class=\"icon ion-locked\"></i> Authentication", - "METHOD_LABEL": "Authentication method", "BTN_AUTH": "Authenticate", - "SCRYPT_FORM_HELP": "Please authenticate yourself:" + "GENERAL_HELP": "Please authenticate yourself:", + "EXPECTED_UID_HELP": "Please authenticate to the account <i class=\"ion-person\"></i> {{uid}}:", + "EXPECTED_PUBKEY_HELP": "Please authenticate to the wallet <i class=\"ion-key\"></i> {{pubkey|formatPubkey}}:", + "SCAN_FORM_HELP": "Scan the QR code of the <b>private key</b> of the wallet." }, "ACCOUNT": { "TITLE": "My Account", "BALANCE": "Balance", - "LAST_TX": "Latest transactions", + "LAST_TX": "Latest validated transactions", "BALANCE_ACCOUNT": "Account balance", "NO_TX": "No transaction", "SHOW_MORE_TX": "Show more", "SHOW_ALL_TX": "Show all", - "TX_FROM_DATE": "(current limit to {{fromTime|formatFromNowShort}})", + "TX_FROM_DATE": "(current limit to {{fromTime|medianFromNowShort}})", "PENDING_TX": "Pending transactions", + "VALIDATING_TX": "Transactions being validated", "ERROR_TX": "Transaction not executed", "ERROR_TX_SENT": "Sent transactions", "PENDING_TX_RECEIVED": "Transactions awaiting receipt", "EVENTS": "Events", + "OUT_DISTANCED": "Your current certifications come from a group too isolated from the <a ng-click=\"showHelpModal('wot')\"> Web of Trust</a> (WoT): the <a ng-click=\"showHelpModal('distance_rule')\">maximum distance rule</a> is violated.<br/>You must obtain certifications from another area of the Web of Trust, or wait for it to tighten.", "WAITING_MEMBERSHIP": "Membership application sent. Waiting validation.", - "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member", + "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member and produce the <a ng-click=\"showHelpModal('ud')\">Universal Dividend</a>. Your account is however already operational, to receive and send payments.", + "WAITING_CERTIFICATIONS_HELP": "To get your certifications, only request members <b>who know you enough</b>, as required by <a ng-click=\"showLicenseModal()\">the currency license</a> that you have accepted.<br/>If you do not know enough members, let them know on <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">the user forum</a>.", "WILL_MISSING_CERTIFICATIONS": "You will <b>lack certifications</b> soon (at least {{willNeedCertificationCount}} more are needed)", "WILL_NEED_RENEW_MEMBERSHIP": "Your membership <b>will expire {{membershipExpiresIn|formatDurationTo}}</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a> before then.", "NEED_RENEW_MEMBERSHIP": "You are no longer a member because your membership <b>has expired</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a>.", + "NEED_RENEW_MEMBERSHIP_AFTER_CANCELLED": "You are no longer a member because your membership <b>has been cancelled</b> for lack of certifications. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a>.", "NO_WAITING_MEMBERSHIP": "No membership application pending. If you'd like to <b>become a member</ b>, please <a ng-click=\"doQuickFix('membership')\">send the membership application</a>.", "CERTIFICATION_COUNT": "Received certifications", "CERTIFICATION_COUNT_SHORT": "Certifications", "SIG_STOCK": "Stock of certifications to give", "BTN_RECEIVE_MONEY": "Receive", "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Switch to another identity...", + "BTN_FIX_MEMBERSHIP": "Resubmit membership request...", "BTN_MEMBERSHIP_RENEW": "Renew membership", "BTN_MEMBERSHIP_RENEW_DOTS": "Renew membership...", "BTN_MEMBERSHIP_OUT_DOTS": "Revoke membership...", @@ -513,12 +552,40 @@ $translateProvider.translations("en-GB", { "TITLE": "Identity selection", "HELP": "Several <b>different identities</b> have been sent, for the public key <span class=\"gray\"> <i class=\"ion-key\"></i> {{pubkey | formatPubkey}}</span>.<br/>Please select the identity to use:" }, + "SELECT_WALLET_MODAL": { + "TITLE": "Wallet selection" + }, + "WALLET_LIST": { + "TITLE": "My wallets", + "BTN_NEW": "Add a wallet", + "BTN_DOWNLOAD": "Download the list", + "BTN_IMPORT_FILE_DOTS": "Import from a file...", + "NO_WALLET": "No secondary wallet", + "BTN_DELETE": "Remove a secondary wallet...", + "BTN_RENAME": "Rename the wallet", + "EXPORT_FILENAME": "my_wallets-{{pubkey|formatPubkey}}-{{currency}}.csv", + "TOTAL_DOTS": "Total: ", + "EDIT_POPOVER": { + "TITLE": "Rename the wallet", + "HELP": "Fill in the new name", + "NAME_HELP": "Wallet name" + }, + "IMPORT_MODAL": { + "TITLE": "Import secondary wallets", + "HELP": "To <b>import secodnary wallets</b>, please drag the file in the box below, or click in the box to search for a file.", + "WALLET_COUNT": "<b>{{count}}</b> new wallet{{count > 1 ? 's' : ''}}", + "NO_NEW_WALLET": "No new wallet" + } + }, "SECURITY":{ "ADD_QUESTION" : "Add custom question", "BTN_CLEAN" : "Clean", "BTN_RESET" : "Reset", "DOWNLOAD_REVOKE": "Save a revocation file", "DOWNLOAD_REVOKE_HELP" : "Having a revocation file is important, for example in case of loss of identifiers. It allows you to <b>get this account out of the Web Of Trust</b>, thus becoming a simple wallet.", + "GENERATE_KEYFILE": "Generate my keychain file ...", + "GENERATE_KEYFILE_HELP": "Generate a file allowing you to authenticate without entering your identifiers.<br/><b>Warning:</b> this file will contain your secret key; It is therefore very important to put it in a safe place!", + "KEYFILE_FILENAME": "keychain-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Register as member...", "MEMBERSHIP_IN_HELP": "Allows you to <b>transform </b> a simple wallet account <b>into a member account</b>, by sending a membership request. Useful only if you do not already have another member account.", "SEND_IDENTITY": "Publish identity...", @@ -557,7 +624,24 @@ $translateProvider.translations("en-GB", { "SAVE_ID": "Save my credentials...", "SAVE_ID_HELP": "Creating a backup file, to <b>retrieve your password</b> (and the secret identifier) <b> in case of forgetting</b>. The file is <b>secured</ b> (encrypted) using personal questions.", "STRONG_LEVEL": "Strong <span class=\"hidden-xs \">(6 questions minimum)</span>", - "TITLE": "Account and security" + "TITLE": "Account and security", + "KEYFILE": { + "PUBSEC_FORMAT": "PubSec format.", + "PUBSEC_FORMAT_HELP": "This file format is compatible in particular with Cesium and Gannonce. Your keychain is stored <b>without encryption</b>: anyone with a copy of this file will be able to empty your account.", + "WIF_FORMAT": "Wallet Import Format (WIF)", + "WIF_FORMAT_HELP": "This format is used in particular by paper wallets. Your keychain is stored <b>without encryption</b>: anyone with a copy of this file will be able to empty your account.", + "EWIF_FORMAT": "Encrypted Wallet Import Format (WIF)", + "EWIF_FORMAT_HELP": "This format is used in particular by paper wallets. However, <b>the keychain is encrypted</b> from a passphrase of your choice.", + "PASSWORD_POPUP": { + "TITLE": "Keychain file encrypted", + "HELP": "Please enter the passphrase:", + "PASSWORD_HELP": "Passphrase" + }, + "ERROR": { + "BAD_PASSWORD": "Bad passphrase", + "BAD_CHECKSUM": "Bad checksum" + } + } }, "FILE_NAME": "{{currency}} - Account statement {{pubkey|formatPubkey}} to {{currentTime|formatDateForFile}}.csv", "HEADERS": { @@ -569,6 +653,7 @@ $translateProvider.translations("en-GB", { "TRANSFER": { "TITLE": "Transfer", "SUB_TITLE": "Transfer money", + "SUB_TITLE_ALL": "Empty the account", "FROM": "From", "TO": "To", "AMOUNT": "Amount", @@ -577,15 +662,20 @@ $translateProvider.translations("en-GB", { "COMMENT_HELP": "Comment (optional)", "BTN_SEND": "Send", "BTN_ADD_COMMENT": "Add a comment", + "REST": "Rest of account", + "REST_TO": "to", "WARN_COMMENT_IS_PUBLIC": "Please note that <b>comments are public</b> (not encrypted).", "MODAL": { "TITLE": "Transfer" } }, "ERROR": { + "UNKNOWN_URI_FORMAT": "Unknown URI format", + "PUBKEY_INVALID_CHECKSUM": "Invalid public key (bad checksum).", "POPUP_TITLE": "Error", "UNKNOWN_ERROR": "Unknown error", "CRYPTO_UNKNOWN_ERROR": "Your browser is not compatible with cryptographic features.", + "DOWNLOAD_KEYFILE_FAILED": "Failed to generate the keychain file.", "EQUALS_TO_PSEUDO": "Must be different from pseudonym", "EQUALS_TO_SALT": "Must be different from secret identifier", "FIELD_REQUIRED": "This field is required.", @@ -635,7 +725,9 @@ $translateProvider.translations("en-GB", { "INVALID_USER_ID": "Field 'pseudonym' must not contains spaces or special characters.", "INVALID_COMMENT": "Field 'reference' has a bad format.", "INVALID_PUBKEY": "Public key has a bad format.", - "IDENTITY_REVOKED": "This identity <b>has been revoked {{revocationTime|formatFromNow}}</b> ({{revocationTime|formatDate}}). It can no longer become a member.", + "INVALID_PUBKEY_CHECKSUM": "Invalid checksum.", + "IDENTITY_REVOKED": "This identity <b>has been revoked</b>. It can no longer become a member.", + "IDENTITY_REVOKED_WITH_TIME": "This identity <b>has been revoked {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). It can no longer become a member.", "IDENTITY_PENDING_REVOCATION": "The <b>revocation of this identity</b> has been requested and is awaiting processing. Certification is therefore disabled.", "IDENTITY_INVALID_BLOCK_HASH": "This membership application is no longer valid (because it references a block that network peers are cancelled): the person must renew its application for membership <b>before</b> being certified.", "IDENTITY_EXPIRED": "This identity has expired: this person must re-apply <b>before</b> being certified.", @@ -658,6 +750,7 @@ $translateProvider.translations("en-GB", { "LOAD_NEWCOMERS_FAILED": "Unable to load new members.", "LOAD_PENDING_FAILED": "Unable to load pending registrations.", "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "You must <b>be a member</b> in order to perform this action.", + "ONLY_MEMBER_OR_WAS_MEMBER_CAN_EXECUTE_THIS_ACTION": "You must <b>be a member (or old member)</b> in order to perform this action.", "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "You must have <b>published your identity</b> in order to perform this action.", "GET_BLOCK_FAILED": "Error while getting block", "INVALID_BLOCK_HASH": "Block not found (incorrect hash)", @@ -673,7 +766,17 @@ $translateProvider.translations("en-GB", { "EXISTING_ACCOUNT_REQUEST": "Please modify your credentials so that they correspond to an unused account.", "GET_LICENSE_FILE_FAILED": "Unable to get license file", "CHECK_NETWORK_CONNECTION": "No peer appears to be accessible.<br/><br/>Please <b>check your Internet connection</b>.", - "ISSUE_524_TX_FAILED": "Failed to transfer.<br/><br/>A message has been sent to developers to help solve the problem.<b>Thank you for your help</b>." + "ISSUE_524_TX_FAILED": "Failed to transfer.<br/><br/>A message has been sent to developers to help solve the problem.<b>Thank you for your help</b>.", + "ADD_SECONDARY_WALLET_FAILED": "Unable to add secondary wallet.", + "UPDATE_WALLET_LIST_FAILED": "Unable to refresh the list of wallets.", + "LOAD_WALLET_LIST_FAILED": "Unable to load the list of wallets.", + "SAVE_WALLET_LIST_FAILED": "Unable to save the list of wallets.", + "COULD_NOT_ADD_MAIN_WALLET": "This wallet <b>is the main account</b> with which you are connected. Unable to add it as a secondary wallet.", + "COULD_NOT_ADD_EXISTING_WALLET": "Wallet already existing in the list.", + "UNKNOWN_WALLET_ID": "Unknown secondary wallet.", + "RESTORE_WALLET_LIST_FAILED": "Unable to restore the list of wallets.", + "INVALID_FILE_FORMAT": "Invalid file format.", + "SAME_TX_RECIPIENT": "The recipient must be different from the issuer." }, "INFO": { "POPUP_TITLE": "Information", @@ -685,6 +788,7 @@ $translateProvider.translations("en-GB", { "NOT_NEED_MEMBERSHIP": "Already a member.", "IDENTITY_WILL_MISSING_CERTIFICATIONS": "This identity will soon lack certification (at least {{willNeedCertificationCount}}).", "IDENTITY_NEED_MEMBERSHIP": "This identity did not send a membership request. She will have to if she wishes to become a member.", + "HAS_ALTERNATIVE_IDENTITIES": "There are <b>multiple identities</b> attached to this public key. <b>Before any certification</b>, please <a ng-click=\"doQuickFix('showSelectIdentities')\">check other identities</a> to choose the correct one, or contact the wallet owner.", "REVOCATION_SENT": "Revocation sent successfully", "REVOCATION_SENT_WAITING_PROCESS": "Revocation <b>has been sent successfully</b>. It is awaiting processing.", "FEATURES_NOT_IMPLEMENTED": "This features is not implemented yet.<br/><br/>Why not to contribute to get it faster? ;)", @@ -696,7 +800,10 @@ $translateProvider.translations("en-GB", { "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Security warning</b>", "CERTIFY_RULES_TITLE_UID": "Certify {{uid}}", "CERTIFY_RULES": "<b class=\"assertive\">Don't certify an account</b> if you believe that: <ul><li>1.) the issuers identity might be faked.<li>2.) the issuer already has another certified account.<li>3.) the issuer purposely or carelessly violates rule 1 or 2 (he certifies faked or double accounts).</ul></small><br/>Are you sure you want to certify this identity?", + "FULLSCREEN": "View the application in full screen?", + "EXIT_APP": "Close the application ?", "TRANSFER": "<b>Transfer summary:</b><br/><br/><ul><li> - From: <b>{{from}}</b></li><li> - To: <b>{{to}}</b></li><li> - Amount: <b>{{amount}} {{unit}}</b></li><li> - Comment: <i>{{comment}}</i></li></ul><br/><b>Are-you sure you want to do this transfer?</b>", + "TRANSFER_ALL": "<b>Transfer summary:</b><br/><br/><ul><li> - From: <b>{{from}}</b></li><li> - To: <b>{{to}}</b></li><li> - Amount: <b>{{amount}} {{unit}}</b></li><li> - Comment: <i>{{comment}}</i></li><br/><li> - Rest : <b>{{restAmount}} {{unit}}</b> to <b>{{restTo}}</b></li></ul><br/><b>Are-you sure you want to do this transfer?</b>", "MEMBERSHIP_OUT": "This operation is <b>irreversible</b>.<br/></br/><b>Are you sure you want to terminate your membership?</b>", "MEMBERSHIP_OUT_2": "This operation is <b>irreversible</b>!<br/><br/>Are you sure you want to <b>terminate your membership</b>?", "LOGIN_UNUSED_WALLET_TITLE": "Typing error?", @@ -742,7 +849,11 @@ $translateProvider.translations("en-GB", { "CURRENCY_RULES_DEF": "The currency rules are defined only once, and for all. They set the parameters under which the currency will perform: universal dividend calculation, the amount of certifications needed to become a member, the maximum amount of certifications a member can send, etc.<br/><br/>The parameters cannot be modified because of the use of a <span class=\"text-italic\">Blockchain</span> which carries and executes these rules, and constantly verifies their correct application. <a href=\"#/app/currency\">See current parameters</a>.", "BLOCKCHAIN": "Blockchain", "BLOCKCHAIN_DEF": "The Blockchain is a decentralised system which, in case of Duniter, serves to carry and execute the <span class=\"text-italic\">currency rules</span>.<br/><a href=\"http://en.duniter.org/presentation/\" target=\"_blank\">Read more about Duniter</a> and the working of its blockchain.", - "UNIVERSAL_DIVIDEND_DEF": "The Universal Dividend (UD) is the quantity of money co-created by each member, according to the period and the calculation defined in the <span class=\"text-italic\">currency rules</span>.<br/>Every term, the members receive an equal amount of new money on their account.<br/><br/>The UD undergoes a steady growth, to remain fair under its members (current and future), calculated by an average life expectancy, as demonstrated in the Relative Theory of Money (RTM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Read more about RTM</a> and open money." + "UNIVERSAL_DIVIDEND_DEF": "The Universal Dividend (UD) is the quantity of money co-created by each member, according to the period and the calculation defined in the <span class=\"text-italic\">currency rules</span>.<br/>Every term, the members receive an equal amount of new money on their account.<br/><br/>The UD undergoes a steady growth, to remain fair under its members (current and future), calculated by an average life expectancy, as demonstrated in the Relative Theory of Money (RTM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Read more about RTM</a> and open money.", + "WOT": "Web of Trust (WoT)", + "WOT_DEF": "The Web of Trust is made up of all the members of the currency, and the links of certification which connect them.", + "DISTANCE_RULE": "Distance rule", + "DISTANCE_RULE_DEF": "The rule of distance defines <b>a maximum distance to meet</b> between an applicant and a minimum number of referring member. This distance is calculated using the certification links." }, "TIP": { "MENU_BTN_CURRENCY": "Menu <b>{{'MENU.CURRENCY'|translate}}</b> allows discovery of <b>currency parameters</b> and its state.", @@ -795,7 +906,8 @@ $translateProvider.translations("en-GB", { "LINK_DOC": "API documentation", "LINK_DOC_HELP": "API documentation for developers", "LINK_STANDARD_APP": "Standard version", - "LINK_STANDARD_APP_HELP": "Open standard version of {{'COMMON.APP_NAME'|translate}}" + "LINK_STANDARD_APP_HELP": "Open standard version of {{'COMMON.APP_NAME'|translate}}", + "CONNECTION_ERROR": "Peer <b>{{server}}</b> unreachable or invalid address.<br/><br/>Check your Internet connection, or contact the web site administrator." }, "HOME": { "TITLE": "{{'COMMON.APP_NAME'|translate}} API Documentation", @@ -808,9 +920,11 @@ $translateProvider.translations("en-GB", { "TITLE_SHORT": "Online payment", "SUMMARY": "Order summary:", "AMOUNT": "Amount:", + "AMOUNTS_HELP": "Please select the amount:", "NAME": "Name:", "PUBKEY": "Public key of the recipient:", "COMMENT": "Order reference:", + "NODE": "Peer address:", "DEMO": { "SALT": "demo", "PASSWORD": "demo", @@ -836,6 +950,7 @@ $translateProvider.translations("en-GB", { "DEMO_DIVIDER": "Try it !", "DEMO_HELP": "To test this service, click on this button. The result content will be display below.", "DEMO_RESULT": "Result returned by call:", + "DEMO_RESULT_PEER": "Peer address used:", "DEMO_SUCCEED": "<i class=\"icon ion-checkmark\"></i> Success!", "DEMO_CANCELLED": "<i class=\"icon ion-close\"></i> Canceled by user", "INTEGRATE_DIVIDER": "Website integration", @@ -857,6 +972,8 @@ $translateProvider.translations("en-GB", { "PARAM_REDIRECT_URL_HELP": "URL redirection after sending payment, after the payment has been sent. Can contain the following strings, which will be replaced by the values of the transaction: \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\" and \"{pubkey}\".", "PARAM_CANCEL_URL": "URL if cancelled", "PARAM_CANCEL_URL_HELP": "URL in case of cancellation. Can contain the following strings, which will be replaced: \"{comment}\", \"{amount}\" and \"{pubkey}\".", + "PARAM_PREFERRED_NODE": "Preferred Duniter peer", + "PARAM_PREFERRED_NODE_HELP": "Peer address (URL) to use preferably (\"g1.domain.com:443\" or \"https://g1.domain.com\")", "EXAMPLES_HELP": "Examples of integration:", "EXAMPLE_BUTTON": "HTML Button", "EXAMPLE_BUTTON_DEFAULT_TEXT": "Pay in {{currency|abbreviate}}", @@ -899,9 +1016,10 @@ $translateProvider.translations("en", { "BTN_YES_CONTINUE": "Yes, Continue", "BTN_SHOW": "Show", "BTN_SHOW_PUBKEY": "Show key", - "BTN_RELATIVE_UNIT": "Use relative unit", + "BTN_RELATIVE_UNIT": "Display amounts in UD?", "BTN_BACK": "Back", "BTN_NEXT": "Next", + "BTN_IMPORT": "Import", "BTN_CANCEL": "Cancel", "BTN_CLOSE": "Close", "BTN_LATER": "Later", @@ -918,7 +1036,7 @@ $translateProvider.translations("en", { "BTN_START": "Start", "BTN_CONTINUE": "Continue", "BTN_CREATE": "Create", - "BTN_UNDERSTOOD": "I understood", + "BTN_UNDERSTOOD": "I understand", "BTN_OPTIONS": "Options", "BTN_HELP_TOUR": "Features tour", "BTN_HELP_TOUR_SCREEN": "Discover this screen", @@ -930,6 +1048,7 @@ $translateProvider.translations("en", { "NO_ACCOUNT_QUESTION": "Not a member yet? Register now!", "SEARCH_NO_RESULT": "No result found", "LOADING": "Loading...", + "LOADING_WAIT": "Loading...<br/><small>(Waiting for node availability)</small>", "SEARCHING": "Searching...", "FROM": "From", "TO": "To", @@ -959,6 +1078,12 @@ $translateProvider.translations("en", { "SHARE_ON_FACEBOOK": "Share on Facebook", "SHARE_ON_DIASPORA": "Share on Diaspora*", "SHARE_ON_GOOGLEPLUS": "Share on Google+" + }, + "FILE": { + "DATE" : "Date:", + "TYPE" : "Type:", + "SIZE": "Size:", + "VALIDATING": "Validating..." } }, "SYSTEM": { @@ -971,6 +1096,7 @@ $translateProvider.translations("en", { "WOT": "Registry", "CURRENCY": "Currency", "ACCOUNT": "My Account", + "WALLETS": "My wallets", "TRANSFER": "Transfer", "SCAN": "Scan", "SETTINGS": "Settings", @@ -979,14 +1105,16 @@ $translateProvider.translations("en", { }, "ABOUT": { "TITLE": "About", - "LICENSE": "<b>Free/libre software</b> (License GNU GPLv3).", + "LICENSE": "<b>Free/libre software</b> (License GNU AGPLv3).", "LATEST_RELEASE": "There is a <b>newer version</ b> of {{'COMMON.APP_NAME' | translate}} (<b>v{{version}}</b>)", "PLEASE_UPDATE": "Please update {{'COMMON.APP_NAME' | translate}} (latest version: <b>v{{version}}</b>)", "CODE": "Source code:", + "OFFICIAL_WEB_SITE": "Official web site:", "DEVELOPERS": "Developers:", "FORUM": "Forum:", "PLEASE_REPORT_ISSUE": "Please report any issue to us!", - "REPORT_ISSUE": "Report an issue" + "REPORT_ISSUE": "Report an issue", + "BTN_OPEN_DEV_WINDOW": "Open the debug window" }, "HOME": { "TITLE": "Cesium", @@ -1002,18 +1130,27 @@ $translateProvider.translations("en", { }, "SETTINGS": { "TITLE": "Settings", + "DISPLAY_DIVIDER": "Display", + "STORAGE_DIVIDER": "Storage", "NETWORK_SETTINGS": "Network", "PEER": "Duniter peer address", + "PEER_SHORT": "Peer address", "PEER_CHANGED_TEMPORARY": "Address used temporarily", "USE_LOCAL_STORAGE": "Enable local storage", "USE_LOCAL_STORAGE_HELP": "Allows you to save your settings", + "WALLETS_SETTINGS": "My wallets", + "USE_WALLETS_ENCRYPTION": "Secure the list", + "USE_WALLETS_ENCRYPTION_HELP": "Enables you to encrypt the list of your wallets. Authentication required to access it.", "ENABLE_HELPTIP": "Enable contextual help tips", "ENABLE_UI_EFFECTS": "Enable visual effects", "HISTORY_SETTINGS": "Account operations", "DISPLAY_UD_HISTORY": "Display produced dividends?", + "TX_HISTORY_AUTO_REFRESH": "Enable automatic refresh?", + "TX_HISTORY_AUTO_REFRESH_HELP": "Updates the list of operations to each new block.", "AUTHENTICATION_SETTINGS": "Authentication", "KEEP_AUTH": "Expiration of authentication", - "KEEP_AUTH_HELP": "Define when authentication is cleared from memory", + "KEEP_AUTH_SHORT": "Expiration", + "KEEP_AUTH_HELP": "Define when authentication is cleared from memory.", "KEEP_AUTH_OPTION": { "NEVER": "After each operation", "SECONDS": "After {{value}}s of inactivity", @@ -1022,12 +1159,21 @@ $translateProvider.translations("en", { "HOUR": "After {{value}}h of inactivity", "ALWAYS": "At the end of the session" }, + "KEYRING_FILE": "Keyring file", + "KEYRING_FILE_HELP": "Allow auto-connect at startup, or to authenticate (only if \"Expiration of authentication\" is \"at the end of the session\"", "REMEMBER_ME": "Remember me ?", "REMEMBER_ME_HELP": "Allows to remain identified from one session to another, keeping the public key locally.", "PLUGINS_SETTINGS": "Extensions", "BTN_RESET": "Restore default values", "EXPERT_MODE": "Enable expert mode", "EXPERT_MODE_HELP": "Allow to see more details", + "BLOCK_VALIDITY_WINDOW": "Block uncertainty time", + "BLOCK_VALIDITY_WINDOW_SHORT": "Time of uncertainty", + "BLOCK_VALIDITY_WINDOW_HELP": "Time to wait before considering an information is validated", + "BLOCK_VALIDITY_OPTION": { + "NONE": "No delay", + "N": "{{time | formatDuration}} ({{count}} blocks)" + }, "POPUP_PEER": { "TITLE" : "Duniter peer", "HOST" : "Address", @@ -1162,15 +1308,18 @@ $translateProvider.translations("en", { "PEERS": "Peers", "SIGNED_ON_BLOCK": "Signed on block", "MIRROR": "mirror", - "MIRRORS": "Mirror peers", + "MIRRORS": "Mirrors", + "MIRROR_PEERS": "Mirror peers", "PEER_LIST" : "Peer's list", - "MEMBERS" : "Member peers", + "MEMBERS" : "Members", + "MEMBER_PEERS" : "Member peers", "ALL_PEERS" : "All peers", "DIFFICULTY" : "Difficulty", "API" : "API", "CURRENT_BLOCK" : "Block #", "POPOVER_FILTER_TITLE": "Filter", - "OFFLINE": "Offline peers", + "OFFLINE": "Offline", + "OFFLINE_PEERS": "Offline peers", "BTN_SHOW_PEER": "Show peer", "VIEW": { "TITLE": "Peer", @@ -1220,7 +1369,7 @@ $translateProvider.translations("en", { "PENDING": "Pending registrations:", "PENDING_COUNT": "{{count}} pending registrations", "REGISTERED": "Registered {{sigDate | formatFromNow}}", - "MEMBER_FROM": "Member since {{memberDate|formatFromNowShort}}", + "MEMBER_FROM": "Member since {{memberDate|medianFromNowShort}}", "BTN_NEWCOMERS": "Latest members", "BTN_PENDING": "Pending registrations", "SHOW_MORE": "Show more", @@ -1262,14 +1411,17 @@ $translateProvider.translations("en", { "SCRYPT_FORM_HELP": "Please enter your credentials. <br> Remember to check the public key for your account.", "PUBKEY_FORM_HELP": "Please enter a public account key:", "FILE_FORM_HELP": "Choose the keychain file to use:", + "SCAN_FORM_HELP": "Scan the QR code of a wallet.", "SALT": "Secret identifier", "SALT_HELP": "Secret identifier", "SHOW_SALT": "Display secret identifier?", "PASSWORD": "Password", "PASSWORD_HELP": "Password", - "PUBKEY_HELP": "Example: « AbsxSY4qoZRzyV2irfep1V9xw1EMNyKJw2TkuVD4N1mv »", + "PUBKEY_HELP": "Public key or pseudonym", "NO_ACCOUNT_QUESTION": "Don't have an account yet?", + "HAVE_ACCOUNT_QUESTION": "Already have an account ?", "CREATE_ACCOUNT": "Create an account", + "CREATE_FREE_ACCOUNT": "Create a free account", "FORGOTTEN_ID": "Forgot password?", "ASSOCIATED_PUBKEY": "Public key :", "BTN_METHODS": "Other methods", @@ -1284,10 +1436,11 @@ $translateProvider.translations("en", { "IDLE_WARNING": "You will be logout... {{countdown}}" }, "METHOD": { - "SCRYPT_DEFAULT": "Standard salt (default)", + "SCRYPT_DEFAULT": "Secret identifier and password", "SCRYPT_ADVANCED": "Advanced salt", "FILE": "Keychain file", - "PUBKEY": "Public key only" + "PUBKEY": "Public key or pseudonym", + "SCAN": "Scan a QR code" }, "SCRYPT": { "SIMPLE": "Light salt", @@ -1301,44 +1454,47 @@ $translateProvider.translations("en", { "p": "p (CPU):" }, "FILE": { - "DATE" : "Date:", - "TYPE" : "Type:", - "SIZE": "Size:", - "VALIDATING": "Validating...", "HELP": "Expected file format: <b>.dunikey</b> (type PubSec). Other formats are under development (EWIF, WIF)." } }, "AUTH": { "TITLE": "<i class=\"icon ion-locked\"></i> Authentication", - "METHOD_LABEL": "Authentication method", "BTN_AUTH": "Authenticate", - "SCRYPT_FORM_HELP": "Please authenticate yourself:" + "GENERAL_HELP": "Please authenticate yourself:", + "EXPECTED_UID_HELP": "Please authenticate to the account <i class=\"ion-person\"></i> {{uid}}:", + "EXPECTED_PUBKEY_HELP": "Please authenticate to the wallet <i class=\"ion-key\"></i> {{pubkey|formatPubkey}}:", + "SCAN_FORM_HELP": "Scan the QR code of the <b>private key</b> of the wallet." }, "ACCOUNT": { "TITLE": "My Account", "BALANCE": "Balance", - "LAST_TX": "Latest transactions", + "LAST_TX": "Latest validated transactions", "BALANCE_ACCOUNT": "Account balance", "NO_TX": "No transaction", "SHOW_MORE_TX": "Show more", "SHOW_ALL_TX": "Show all", - "TX_FROM_DATE": "(current limit to {{fromTime|formatFromNowShort}})", + "TX_FROM_DATE": "(current limit to {{fromTime|medianFromNowShort}})", "PENDING_TX": "Pending transactions", + "VALIDATING_TX": "Transactions being validated", "ERROR_TX": "Transaction not executed", "ERROR_TX_SENT": "Sent transactions", "PENDING_TX_RECEIVED": "Transactions awaiting receipt", "EVENTS": "Events", + "OUT_DISTANCED": "Your current certifications come from a group too isolated from the <a ng-click=\"showHelpModal('wot')\"> Web of Trust</a> (WoT): the <a ng-click=\"showHelpModal('distance_rule')\">maximum distance rule</a> is violated.<br/>You must obtain certifications from another area of the Web of Trust, or wait for it to tighten.", "WAITING_MEMBERSHIP": "Membership application sent. Waiting validation.", - "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member", + "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member and produce the <a ng-click=\"showHelpModal('ud')\">Universal Dividend</a>. Your account is however already operational, to receive and send payments.", + "WAITING_CERTIFICATIONS_HELP": "To get your certifications, only request members <b>who know you enough</b>, as required by <a ng-click=\"showLicenseModal()\">the currency license</a> that you have accepted.<br/>If you do not know enough members, let them know on <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">the user forum</a>.", "WILL_MISSING_CERTIFICATIONS": "You will <b>lack certifications</b> soon (at least {{willNeedCertificationCount}} more are needed)", "WILL_NEED_RENEW_MEMBERSHIP": "Your membership <b>will expire {{membershipExpiresIn|formatDurationTo}}</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a> before then.", "NEED_RENEW_MEMBERSHIP": "You are no longer a member because your membership <b>has expired</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a>.", + "NEED_RENEW_MEMBERSHIP_AFTER_CANCELLED": "You are no longer a member because your membership <b>has been canceled</b> for lack of certifications. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a>.", "NO_WAITING_MEMBERSHIP": "No membership application pending. If you'd like to <b>become a member</ b>, please <a ng-click=\"doQuickFix('membership')\">send the membership application</a>.", "CERTIFICATION_COUNT": "Received certifications", "CERTIFICATION_COUNT_SHORT": "Certifications", "SIG_STOCK": "Stock of certifications to give", "BTN_RECEIVE_MONEY": "Receive", "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Switch to another identity...", + "BTN_FIX_MEMBERSHIP": "Resubmit membership request...", "BTN_MEMBERSHIP_RENEW": "Renew membership", "BTN_MEMBERSHIP_RENEW_DOTS": "Renew membership...", "BTN_MEMBERSHIP_OUT_DOTS": "Revoke membership...", @@ -1394,12 +1550,40 @@ $translateProvider.translations("en", { "TITLE": "Identity selection", "HELP": "Several <b>different identities</b> have been sent, for the public key <span class=\"gray\"> <i class=\"ion-key\"></i> {{pubkey | formatPubkey}}</span>.<br/>Please select the identity to use:" }, + "SELECT_WALLET_MODAL": { + "TITLE": "Wallet selection" + }, + "WALLET_LIST": { + "TITLE": "My wallets", + "BTN_NEW": "Add a wallet", + "BTN_DOWNLOAD": "Download the list", + "BTN_IMPORT_FILE_DOTS": "Import from a file...", + "NO_WALLET": "No secondary wallet", + "BTN_DELETE": "Remove a secondary wallet...", + "BTN_RENAME": "Rename the wallet", + "EXPORT_FILENAME": "my_wallets-{{pubkey|formatPubkey}}-{{currency}}.csv", + "TOTAL_DOTS": "Total: ", + "EDIT_POPOVER": { + "TITLE": "Rename the wallet", + "HELP": "Fill in the new name", + "NAME_HELP": "Wallet name" + }, + "IMPORT_MODAL": { + "TITLE": "Import secondary wallets", + "HELP": "To <b>import secodnary wallets</b>, please drag the file in the box below, or click in the box to search for a file.", + "WALLET_COUNT": "<b>{{count}}</b> new wallet{{count > 1 ? 's' : ''}}", + "NO_NEW_WALLET": "No new wallet" + } + }, "SECURITY":{ "ADD_QUESTION" : "Add custom question", "BTN_CLEAN" : "Clean", "BTN_RESET" : "Reset", "DOWNLOAD_REVOKE": "Save a revocation file", "DOWNLOAD_REVOKE_HELP" : "Having a revocation file is important, for example in case of loss of identifiers. It allows you to <b>get this account out of the Web Of Trust</b>, thus becoming a simple wallet.", + "GENERATE_KEYFILE": "Generate my keychain file ...", + "GENERATE_KEYFILE_HELP": "Generate a file allowing you to authenticate without entering your identifiers.<br/><b>Warning:</b> this file will contain your secret key; It is therefore very important to put it in a safe place!", + "KEYFILE_FILENAME": "keychain-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Register as member...", "MEMBERSHIP_IN_HELP": "Allows you to <b>transform </b> a simple wallet account <b>into a member account</b>, by sending a membership request. Useful only if you do not already have another member account.", "SEND_IDENTITY": "Publish identity...", @@ -1438,7 +1622,24 @@ $translateProvider.translations("en", { "SAVE_ID": "Save my credentials...", "SAVE_ID_HELP": "Creating a backup file, to <b>retrieve your password</b> (and the secret identifier) <b> in case of forgetting</b>. The file is <b>secured</ b> (encrypted) using personal questions.", "STRONG_LEVEL": "Strong <span class=\"hidden-xs \">(6 questions minimum)</span>", - "TITLE": "Account and security" + "TITLE": "Account and security", + "KEYFILE": { + "PUBSEC_FORMAT": "PubSec format.", + "PUBSEC_FORMAT_HELP": "This file format is compatible in particular with Cesium and Gannonce. Your keychain is stored <b>without encryption</b>: anyone with a copy of this file will be able to empty your account.", + "WIF_FORMAT": "Wallet Import Format (WIF)", + "WIF_FORMAT_HELP": "This format is used in particular by paper wallets. Your keychain is stored <b>without encryption</b>: anyone with a copy of this file will be able to empty your account.", + "EWIF_FORMAT": "Encrypted Wallet Import Format (WIF)", + "EWIF_FORMAT_HELP": "This format is used in particular by paper wallets. However, <b>the keychain is encrypted</b> from a passphrase of your choice.", + "PASSWORD_POPUP": { + "TITLE": "Keychain file encrypted", + "HELP": "Please enter the passphrase:", + "PASSWORD_HELP": "Passphrase" + }, + "ERROR": { + "BAD_PASSWORD": "Bad passphrase", + "BAD_CHECKSUM": "Bad checksum" + } + } }, "FILE_NAME": "{{currency}} - Account statement {{pubkey|formatPubkey}} to {{currentTime|formatDateForFile}}.csv", "HEADERS": { @@ -1450,6 +1651,7 @@ $translateProvider.translations("en", { "TRANSFER": { "TITLE": "Transfer", "SUB_TITLE": "Transfer money", + "SUB_TITLE_ALL": "Empty the account", "FROM": "From", "TO": "To", "AMOUNT": "Amount", @@ -1458,15 +1660,20 @@ $translateProvider.translations("en", { "COMMENT_HELP": "Comment (optional)", "BTN_SEND": "Send", "BTN_ADD_COMMENT": "Add a comment", + "REST": "Rest of account", + "REST_TO": "to", "WARN_COMMENT_IS_PUBLIC": "Please note that <b>comments are public</b> (not encrypted).", "MODAL": { "TITLE": "Transfer" } }, "ERROR": { + "UNKNOWN_URI_FORMAT": "Unknown URI format", + "PUBKEY_INVALID_CHECKSUM": "Invalid public key (bad checksum).", "POPUP_TITLE": "Error", "UNKNOWN_ERROR": "Unknown error", "CRYPTO_UNKNOWN_ERROR": "Your browser is not compatible with cryptographic features.", + "DOWNLOAD_KEYFILE_FAILED": "Failed to generate the keychain file.", "EQUALS_TO_PSEUDO": "Must be different from pseudonym", "EQUALS_TO_SALT": "Must be different from secret identifier", "FIELD_REQUIRED": "This field is required.", @@ -1516,7 +1723,9 @@ $translateProvider.translations("en", { "INVALID_USER_ID": "Field 'pseudonym' must not contains spaces or special characters.", "INVALID_COMMENT": "Field 'reference' has a bad format.", "INVALID_PUBKEY": "Public key has a bad format.", - "IDENTITY_REVOKED": "This identity <b>has been revoked {{revocationTime|formatFromNow}}</b> ({{revocationTime|formatDate}}). It can no longer become a member.", + "INVALID_PUBKEY_CHECKSUM": "Invalid checksum.", + "IDENTITY_REVOKED": "This identity <b>has been revoked</b>. It can no longer become a member.", + "IDENTITY_REVOKED_WITH_TIME": "This identity <b>has been revoked {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). It can no longer become a member.", "IDENTITY_PENDING_REVOCATION": "The <b>revocation of this identity</b> has been requested and is awaiting processing. Certification is therefore disabled.", "IDENTITY_INVALID_BLOCK_HASH": "This membership application is no longer valid (because it references a block that network peers are cancelled): the person must renew its application for membership <b>before</b> being certified.", "IDENTITY_EXPIRED": "This identity has expired: this person must re-apply <b>before</b> being certified.", @@ -1539,6 +1748,7 @@ $translateProvider.translations("en", { "LOAD_NEWCOMERS_FAILED": "Unable to load new members.", "LOAD_PENDING_FAILED": "Unable to load pending registrations.", "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "You must <b>be a member</b> in order to perform this action.", + "ONLY_MEMBER_OR_WAS_MEMBER_CAN_EXECUTE_THIS_ACTION": "You must <b>be a member (or old member)</b> in order to perform this action.", "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "You must have <b>published your identity</b> in order to perform this action.", "GET_BLOCK_FAILED": "Error while getting block", "INVALID_BLOCK_HASH": "Block not found (incorrect hash)", @@ -1554,7 +1764,17 @@ $translateProvider.translations("en", { "EXISTING_ACCOUNT_REQUEST": "Please modify your credentials so that they correspond to an unused account.", "GET_LICENSE_FILE_FAILED": "Unable to get license file", "CHECK_NETWORK_CONNECTION": "No peer appears to be accessible.<br/><br/>Please <b>check your Internet connection</b>.", - "ISSUE_524_TX_FAILED": "Failed to transfer.<br/><br/>A message has been sent to developers to help solve the problem.<b>Thank you for your help</b>." + "ISSUE_524_TX_FAILED": "Failed to transfer.<br/><br/>A message has been sent to developers to help solve the problem.<b>Thank you for your help</b>.", + "ADD_SECONDARY_WALLET_FAILED": "Unable to add secondary wallet.", + "UPDATE_WALLET_LIST_FAILED": "Unable to refresh the list of wallets.", + "LOAD_WALLET_LIST_FAILED": "Unable to load the list of wallets.", + "SAVE_WALLET_LIST_FAILED": "Unable to save the list of wallets.", + "COULD_NOT_ADD_MAIN_WALLET": "This wallet <b>is the main account</b> with which you are connected. Unable to add it as a secondary wallet.", + "COULD_NOT_ADD_EXISTING_WALLET": "Wallet already existing in the list.", + "UNKNOWN_WALLET_ID": "Unknown secondary wallet.", + "RESTORE_WALLET_LIST_FAILED": "Unable to restore the list of wallets.", + "INVALID_FILE_FORMAT": "Invalid file format.", + "SAME_TX_RECIPIENT": "The recipient must be different from the issuer." }, "INFO": { "POPUP_TITLE": "Information", @@ -1566,6 +1786,7 @@ $translateProvider.translations("en", { "NOT_NEED_MEMBERSHIP": "Already a member.", "IDENTITY_WILL_MISSING_CERTIFICATIONS": "This identity will soon lack certification (at least {{willNeedCertificationCount}}).", "IDENTITY_NEED_MEMBERSHIP": "This identity did not send a membership request. She will have to if she wishes to become a member.", + "HAS_ALTERNATIVE_IDENTITIES": "There are <b>multiple identities</b> attached to this public key. <b>Before any certification</b>, please <a ng-click=\"doQuickFix('showSelectIdentities')\">check other identities</a> to choose the correct one, or contact the wallet owner.", "REVOCATION_SENT": "Revocation sent successfully", "REVOCATION_SENT_WAITING_PROCESS": "Revocation <b>has been sent successfully</b>. It is awaiting processing.", "FEATURES_NOT_IMPLEMENTED": "This features is not implemented yet.<br/><br/>Why not to contribute to get it faster? ;)", @@ -1577,7 +1798,10 @@ $translateProvider.translations("en", { "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Security warning</b>", "CERTIFY_RULES_TITLE_UID": "Certify {{uid}}", "CERTIFY_RULES": "<b class=\"assertive\">Don't certify an account</b> if you believe that: <ul><li>1.) the issuers identity might be faked.<li>2.) the issuer already has another certified account.<li>3.) the issuer purposely or carelessly violates rule 1 or 2 (he certifies faked or double accounts).</ul></small><br/>Are you sure you want to certify this identity?", + "FULLSCREEN": "View the application in full screen?", + "EXIT_APP": "Close the application ?", "TRANSFER": "<b>Transfer summary:</b><br/><br/><ul><li> - From: <b>{{from}}</b></li><li> - To: <b>{{to}}</b></li><li> - Amount: <b>{{amount}} {{unit}}</b></li><li> - Comment: <i>{{comment}}</i></li></ul><br/><b>Are-you sure you want to do this transfer?</b>", + "TRANSFER_ALL": "<b>Transfer summary:</b><br/><br/><ul><li> - From: <b>{{from}}</b></li><li> - To: <b>{{to}}</b></li><li> - Amount: <b>{{amount}} {{unit}}</b></li><li> - Comment: <i>{{comment}}</i></li><br/><li> - Rest : <b>{{restAmount}} {{unit}}</b> to <b>{{restTo}}</b></li></ul><br/><b>Are-you sure you want to do this transfer?</b>", "MEMBERSHIP_OUT": "This operation is <b>irreversible</b>.<br/></br/><b>Are you sure you want to terminate your membership?</b>", "MEMBERSHIP_OUT_2": "This operation is <b>irreversible</b>!<br/><br/>Are you sure you want to <b>terminate your membership</b>?", "LOGIN_UNUSED_WALLET_TITLE": "Typing error?", @@ -1623,7 +1847,11 @@ $translateProvider.translations("en", { "CURRENCY_RULES_DEF": "The currency rules are defined only once, and for all. They set the parameters under which the currency will perform: universal dividend calculation, the amount of certifications needed to become a member, the maximum amount of certifications a member can send, etc.<br/><br/>The parameters cannot be modified because of the use of a <span class=\"text-italic\">Blockchain</span> which carries and executes these rules, and constantly verifies their correct application. <a href=\"#/app/currency\">See current parameters</a>.", "BLOCKCHAIN": "Blockchain", "BLOCKCHAIN_DEF": "The Blockchain is a decentralised system which, in case of Duniter, serves to carry and execute the <span class=\"text-italic\">currency rules</span>.<br/><a href=\"http://en.duniter.org/presentation/\" target=\"_blank\">Read more about Duniter</a> and the working of its blockchain.", - "UNIVERSAL_DIVIDEND_DEF": "The Universal Dividend (UD) is the quantity of money co-created by each member, according to the period and the calculation defined in the <span class=\"text-italic\">currency rules</span>.<br/>Every term, the members receive an equal amount of new money on their account.<br/><br/>The UD undergoes a steady growth, to remain fair under its members (current and future), calculated by an average life expectancy, as demonstrated in the Relative Theory of Money (RTM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Read more about RTM</a> and open money." + "UNIVERSAL_DIVIDEND_DEF": "The Universal Dividend (UD) is the quantity of money co-created by each member, according to the period and the calculation defined in the <span class=\"text-italic\">currency rules</span>.<br/>Every term, the members receive an equal amount of new money on their account.<br/><br/>The UD undergoes a steady growth, to remain fair under its members (current and future), calculated by an average life expectancy, as demonstrated in the Relative Theory of Money (RTM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Read more about RTM</a> and open money.", + "WOT": "Web of Trust (WoT)", + "WOT_DEF": "The Web of Trust is made up of all the members of the currency, and the links of certification which connect them.", + "DISTANCE_RULE": "Distance rule", + "DISTANCE_RULE_DEF": "The rule of distance defines <b>a maximum distance to meet</b> between an applicant and a minimum number of referring member. This distance is calculated using the certification links." }, "TIP": { "MENU_BTN_CURRENCY": "Menu <b>{{'MENU.CURRENCY'|translate}}</b> allows discovery of <b>currency parameters</b> and its state.", @@ -1676,7 +1904,8 @@ $translateProvider.translations("en", { "LINK_DOC": "API documentation", "LINK_DOC_HELP": "API documentation for developers", "LINK_STANDARD_APP": "Standard version", - "LINK_STANDARD_APP_HELP": "Open standard version of {{'COMMON.APP_NAME'|translate}}" + "LINK_STANDARD_APP_HELP": "Open standard version of {{'COMMON.APP_NAME'|translate}}", + "CONNECTION_ERROR": "Peer <b>{{server}}</b> unreachable or invalid address.<br/><br/>Check your Internet connection, or contact the web site administrator." }, "HOME": { "TITLE": "{{'COMMON.APP_NAME'|translate}} API Documentation", @@ -1689,9 +1918,11 @@ $translateProvider.translations("en", { "TITLE_SHORT": "Online payment", "SUMMARY": "Order summary:", "AMOUNT": "Amount:", + "AMOUNTS_HELP": "Please select the amount:", "NAME": "Name:", "PUBKEY": "Public key of the recipient:", "COMMENT": "Order reference:", + "NODE": "Peer address:", "DEMO": { "SALT": "demo", "PASSWORD": "demo", @@ -1717,6 +1948,7 @@ $translateProvider.translations("en", { "DEMO_DIVIDER": "Try it !", "DEMO_HELP": "To test this service, click on this button. The result content will be display below.", "DEMO_RESULT": "Result returned by call:", + "DEMO_RESULT_PEER": "Peer address used:", "DEMO_SUCCEED": "<i class=\"icon ion-checkmark\"></i> Success!", "DEMO_CANCELLED": "<i class=\"icon ion-close\"></i> Canceled by user", "INTEGRATE_DIVIDER": "Website integration", @@ -1738,6 +1970,8 @@ $translateProvider.translations("en", { "PARAM_REDIRECT_URL_HELP": "URL redirection after sending payment, after the payment has been sent. Can contain the following strings, which will be replaced by the values of the transaction: \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\" and \"{pubkey}\".", "PARAM_CANCEL_URL": "URL if cancelled", "PARAM_CANCEL_URL_HELP": "URL in case of cancellation. Can contain the following strings, which will be replaced: \"{comment}\", \"{amount}\" and \"{pubkey}\".", + "PARAM_PREFERRED_NODE": "Preferred Duniter peer", + "PARAM_PREFERRED_NODE_HELP": "Peer address (URL) to use preferably (\"g1.domain.com:443\" or \"https://g1.domain.com\")", "EXAMPLES_HELP": "Examples of integration:", "EXAMPLE_BUTTON": "HTML Button", "EXAMPLE_BUTTON_DEFAULT_TEXT": "Pay in {{currency|abbreviate}}", @@ -1761,6 +1995,1003 @@ $translateProvider.translations("en", { } ); +$translateProvider.translations("eo-EO", { + "COMMON": { + "APP_NAME": "Cesium", + "APP_VERSION": "v{{version}}", + "APP_BUILD": "date : {{build}}", + "PUBKEY": "Publika Ålosilo", + "MEMBER": "Membro", + "BLOCK" : "Bloko", + "BTN_OK": "OK", + "BTN_YES": "Jes", + "BTN_NO": "Ne", + "BTN_SEND": "Sendi", + "BTN_SEND_MONEY": "Fari elspezon", + "BTN_SEND_MONEY_SHORT": "Elspezo", + "BTN_SAVE": "Konservi", + "BTN_YES_SAVE": "Jes, Konservi", + "BTN_YES_CONTINUE": "Jes, DaÅrigi", + "BTN_SHOW": "Vidi", + "BTN_SHOW_PUBKEY": "AfiÅi la publikan Ålosilon", + "BTN_RELATIVE_UNIT": "AfiÅi la sumojn en UD?", + "BTN_BACK": "Reiro", + "BTN_NEXT": "Sekva", + "BTN_IMPORT": "Enporti", + "BTN_CANCEL": "Nuligi", + "BTN_CLOSE": "Fermi", + "BTN_LATER": "Poste", + "BTN_LOGIN": "KonektiÄi", + "BTN_LOGOUT": "MalkonektiÄo", + "BTN_ADD_ACCOUNT": "Nova konto", + "BTN_SHARE": "Diskonigi", + "BTN_EDIT": "Modifi", + "BTN_DELETE": "Forigi", + "BTN_ADD": "Aldoni", + "BTN_SEARCH": "Serĉi", + "BTN_REFRESH": "Aktualigi", + "BTN_RETRY": "Rekomenci", + "BTN_START": "Komenci", + "BTN_CONTINUE": "DaÅrigi", + "BTN_CREATE": "Krei", + "BTN_UNDERSTOOD": "Mi komprenis", + "BTN_OPTIONS": "Kromeblecoj", + "BTN_HELP_TOUR": "Gvidata vizito", + "BTN_HELP_TOUR_SCREEN": "Malkovri tiun ĉi paÄon", + "BTN_DOWNLOAD": "ElÅuti", + "BTN_DOWNLOAD_ACCOUNT_STATEMENT": "ElÅuti la konto-tabelon", + "BTN_MODIFY": "Modifi", + "CHOOSE_FILE": "Almetu vian dosieron <br/>aÅ klaku por elekti Äin", + "DAYS": "tagoj", + "NO_ACCOUNT_QUESTION": "AnkoraÅ sen konto? Kreu Äin senpage!", + "SEARCH_NO_RESULT": "Neniu rezulto trovita", + "LOADING": "Bonvolu pacienci...", + "LOADING_WAIT": "Bonvolu pacienci...<br/><small>(Atendado pri disponebleco de la nodo)</small>", + "SEARCHING": "Serĉanta...", + "FROM": "De", + "TO": "Al", + "COPY": "Kopii", + "LANGUAGE": "Lingvo", + "UNIVERSAL_DIVIDEND": "Universala dividendo", + "UD": "UD", + "DATE_PATTERN": "DD/MM/YY HH:mm", + "DATE_FILE_PATTERN": "YYYY-MM-DD", + "DATE_SHORT_PATTERN": "DD/MM/YY", + "DATE_MONTH_YEAR_PATTERN": "MM/YYYY", + "EMPTY_PARENTHESIS": "(malplena)", + "UID": "PseÅdonimo", + "ENABLE": "Aktiva", + "DISABLE": "Malaktiva", + "RESULTS_LIST": "Rezultoj", + "RESULTS_COUNT": "{{count}} rezultoj", + "EXECUTION_TIME": "Plenumita en {{duration|formatDurationMs}}", + "SHOW_VALUES": "AfiÅi la signojn klare?", + "POPOVER_ACTIONS_TITLE": "Kromeblecoj", + "POPOVER_FILTER_TITLE": "Filtriloj", + "SHOW_MORE": "AfiÅi pli", + "SHOW_MORE_COUNT": "(nuna limo je {{limit}})", + "POPOVER_SHARE": { + "TITLE": "Diskonigi", + "SHARE_ON_TWITTER": "Diskonigi ĉe Twitter", + "SHARE_ON_FACEBOOK": "Diskonigi ĉe Facebook", + "SHARE_ON_DIASPORA": "Diskonigi ĉe Diaspora*", + "SHARE_ON_GOOGLEPLUS": "Diskonigi ĉe Google+" + }, + "FILE": { + "DATE": "Dato:", + "TYPE": "Tipo:", + "SIZE": "Pezo:", + "VALIDATING": "ValidiÄanta..." + } + }, + "SYSTEM": { + "PICTURE_CHOOSE_TYPE": "Elekti la fonton:", + "BTN_PICTURE_GALLERY": "Bildaro", + "BTN_PICTURE_CAMERA": "<b>Kamerao</b>" + }, + "MENU": { + "HOME": "HejmpaÄo", + "WOT": "Kontaro", + "CURRENCY": "Mono", + "ACCOUNT": "Mia konto", + "WALLETS": "Miaj monujoj", + "TRANSFER": "Elspezo", + "SCAN": "Skani", + "SETTINGS": "Parametroj", + "NETWORK": "Reto", + "TRANSACTIONS": "Miaj spezoj" + }, + "ABOUT": { + "TITLE": "Prie", + "LICENSE": "Programo <b>libera</b> (Licenco GNU AGPLv3).", + "LATEST_RELEASE": "Ekzistas <b>pli freÅdata versio</b> de {{'COMMON.APP_NAME'|translate}} (<b>v{{version}}</b>)", + "PLEASE_UPDATE": "Bonvolu Äisdatigi {{'COMMON.APP_NAME'|translate}} (lasta versio: <b>v{{version}}</b>)", + "CODE": "Fonto-kodo:", + "OFFICIAL_WEB_SITE": "Oficiala retejo:", + "DEVELOPERS": "Programita de:", + "FORUM": "Forumo:", + "PLEASE_REPORT_ISSUE": "Ne hezitu sciigi al ni la renkontitajn fuÅaĵojn", + "REPORT_ISSUE": "Sciigi problemon", + "BTN_OPEN_DEV_WINDOW": "Malfermi la fenestron pri malfuÅigado" + }, + "HOME": { + "TITLE": "Cesium", + "WELCOME": "Bonvenon ĉe la programo Cesium!", + "MESSAGE": "Ricevu kaj sendu liberan monon {{currency|abbreviate}}", + "BTN_CURRENCY": "Esploru la monon {{name|abbreviate}}", + "BTN_ABOUT": "prie", + "BTN_HELP": "Reta helpo", + "REPORT_ISSUE": "fuÅaĵo", + "NOT_YOUR_ACCOUNT_QUESTION" : "Vi ne posedas la konton <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> ?", + "BTN_CHANGE_ACCOUNT": "Malkonektu tiun ĉi konton", + "CONNECTION_ERROR": "Nodo <b>{{server}}</b> neatingebla aÅ adreso nevalida.<br/><br/>Kontrolu vian retkonekton, aÅ elektu alian nodon <a class=\"positive\" ng-click=\"doQuickFix('settings')\">ĉe la parametroj</a>." + }, + "SETTINGS": { + "TITLE": "Parametroj", + "DISPLAY_DIVIDER": "AfiÅado", + "STORAGE_DIVIDER": "Stokado", + "NETWORK_SETTINGS": "Reto", + "PEER": "Adreso de la nodo Duniter", + "PEER_SHORT": "Adreso de la nodo", + "PEER_CHANGED_TEMPORARY": "Adreso provizore uzata", + "USE_LOCAL_STORAGE": "Aktivigi lokan stokadon", + "USE_LOCAL_STORAGE_HELP": "Ebligas konservi viajn parametrojn", + "WALLETS_SETTINGS": "Miaj monujoj", + "USE_WALLETS_ENCRYPTION": "Sekurigi la liston?", + "USE_WALLETS_ENCRYPTION_HELP": "Ebligas sekurigi la liston de viaj monujoj (per ĉifrado), postulante aÅtentigado por aliri ilin.", + "ENABLE_HELPTIP": "Aktivigi la rilatigajn help-vezikojn", + "ENABLE_UI_EFFECTS": "Aktivigi la vid-efikojn", + "HISTORY_SETTINGS": "Miaj spezoj", + "DISPLAY_UD_HISTORY": "AfiÅi la produktitajn dividendojn?", + "TX_HISTORY_AUTO_REFRESH": "Aktualigi aÅtomate", + "TX_HISTORY_AUTO_REFRESH_HELP": "Aktualigas la saldon kaj la spezojn aÅtomate, por ĉiu nova bloko de la reto.", + "AUTHENTICATION_SETTINGS": "AÅtentigado", + "KEEP_AUTH": "AÅtomata malaÅtentigado", + "KEEP_AUTH_SHORT": "MalaÅtentigado", + "KEEP_AUTH_HELP": "Difinas la momenton, kiam la aÅtentigado estas forviÅita de la memoro.", + "KEEP_AUTH_OPTION": { + "NEVER": "Post ĉiu ago", + "SECONDS": "Post {{value}}s de neatktiveco", + "MINUTE": "Post {{value}}min de neatktiveco", + "MINUTES": "Post {{value}}min de neatktiveco", + "HOUR": "Post {{value}}h de neatktiveco", + "ALWAYS": "Fine de la sesio" + }, + "KEYRING_FILE": "Dosiero pri Ålosilaro", + "KEYRING_FILE_HELP": "Ebligas <b>konektiÄi</b> aÅtomate por ĉiu ekuzo<br/>kaj eĉ <b>aÅtentiÄi</b> (nur se \"FiniÄo de la aÅtentiÄo\" estas agordita kiel \"fine de la sesio\").", + "REMEMBER_ME": "Memori min?", + "REMEMBER_ME_HELP": "Ebligas resti identigita de sesio al alia, loke konservante la publikan Ålosilon.", + "PLUGINS_SETTINGS": "Krom-programoj", + "BTN_RESET": "Restarigi la originajn valorojn", + "EXPERT_MODE": "Aktivigi la spertan moduson", + "EXPERT_MODE_HELP": "Ebligas pli detalan afiÅadon.", + "BLOCK_VALIDITY_WINDOW": "Limtempo pri necerteco de la blokoj", + "BLOCK_VALIDITY_WINDOW_SHORT": "Limtempo pri necerteco", + "BLOCK_VALIDITY_WINDOW_HELP": "Limtempo antaÅ ol taksi, ke iu informo estas validigita", + "BLOCK_VALIDITY_OPTION": { + "NONE": "Neniu limtempo", + "N": "{{time | formatDuration}} ({{count}} blokoj)" + }, + "POPUP_PEER": { + "TITLE": "Nodo Duniter", + "HOST": "Adreso", + "HOST_HELP": "Adreso: servilo: konektujo", + "USE_SSL": "Sekurigita?", + "USE_SSL_HELP": "(SSL-ĉifrado)", + "BTN_SHOW_LIST": "Listo de la nodoj" + } + }, + "BLOCKCHAIN": { + "HASH": "Haketo: {{hash}}", + "VIEW": { + "HEADER_TITLE": "Bloko #{{number}}-{{hash|formatHash}}", + "TITLE_CURRENT": "Nuna bloko", + "TITLE": "Bloko #{{number|formatInteger}}", + "COMPUTED_BY": "Kalkulita de la nodo de", + "SHOW_RAW": "Vidi la kompletan dosieron", + "TECHNICAL_DIVIDER": "Teknikaj informoj", + "VERSION": "Versio de la daten-strukturo", + "HASH": "Kalkulita haketo", + "UNIVERSAL_DIVIDEND_HELP": "Mono kunproduktita de ĉiu el la {{membersCount}} membroj", + "EMPTY": "Neniu dateno en tiu ĉi bloko", + "POW_MIN": "Minimuma malfacileco", + "POW_MIN_HELP": "Malfacileco trudita por la haket-kalkulo", + "DATA_DIVIDER": "Datenoj", + "IDENTITIES_COUNT": "Novaj identecoj", + "JOINERS_COUNT": "Novaj membroj", + "ACTIVES_COUNT": "Revalidigoj", + "ACTIVES_COUNT_HELP": "Membroj revalidigintaj sian membrecon", + "LEAVERS_COUNT": "Membroj elirintaj", + "LEAVERS_COUNT_HELP": "Membroj ne plu dezirantaj atestaĵon", + "EXCLUDED_COUNT": "Membroj eksigitaj", + "EXCLUDED_COUNT_HELP": "Malnovaj membroj eksigitaj pro nerevalidiÄo aÅ manko de atestaĵoj", + "REVOKED_COUNT": "Nuligitaj identecoj", + "REVOKED_COUNT_HELP": "Tiuj kontoj ne plu povos esti membroj", + "TX_COUNT": "Spezoj", + "CERT_COUNT": "Atestaĵoj", + "TX_TO_HIMSELF": "Operacio pri monÅanÄo", + "TX_OUTPUT_UNLOCK_CONDITIONS": "Kondiĉoj por malblokado", + "TX_OUTPUT_OPERATOR": { + "AND": "kaj", + "OR": "aÅ" + }, + "TX_OUTPUT_FUNCTION": { + "SIG": "<b>Subskribo</b> de ", + "XHX": "<b>Pasvorto</b>, el kiu SHA256 =", + "CSV": "Blokita dum", + "CLTV": "Blokita Äis" + } + }, + "LOOKUP": { + "TITLE": "Blokoj", + "NO_BLOCK": "Neniu bloko", + "LAST_BLOCKS": "Lastaj blokoj:", + "BTN_COMPACT": "Densigi" + } + }, + "CURRENCY": { + "VIEW": { + "TITLE": "Mono", + "TAB_CURRENCY": "Mono", + "TAB_WOT": "Reto de fido", + "TAB_NETWORK": "Reto", + "TAB_BLOCKS": "Blokoj", + "CURRENCY_SHORT_DESCRIPTION": "{{currency|abbreviate}} estas <b>libera mono</b>, kiu ekis {{firstBlockTime|formatFromNow}}. Äœi nombras nun <b>{{N}} membrojn</b>, kiuj produktas kaj ricevas <a ng-click=\"showHelpModal('ud')\">Universalan Dividendon</a> (UD), ĉiun {{dt|formatPeriod}}n.", + "NETWORK_RULES_DIVIDER": "Reguloj de la reto", + "CURRENCY_NAME": "Nomo de la mono", + "MEMBERS": "Nombro de membroj", + "MEMBERS_VARIATION": "Variado depost la lasta UD", + "MONEY_DIVIDER": "Mono", + "MASS": "Mona maso", + "SHARE": "Maso por membro", + "UD": "Universala Dividendo", + "C_ACTUAL": "Nuna kreskado", + "MEDIAN_TIME": "Horo de la blokĉeno", + "POW_MIN": "Minimuma nivelo pri malfacileco de kalkulo", + "MONEY_RULES_DIVIDER": "Reguloj de la mono", + "C_RULE": "Teoria kreskado celata", + "UD_RULE": "Kalkulo de la universala dividendo", + "DT_REEVAL": "Periodo de revalorigo de la UD", + "REEVAL_SYMBOL": "reval", + "DT_REEVAL_VALUE": "Ĉiuj <b>{{dtReeval|formatDuration}}</b> ({{dtReeval/86400}} {{'COMMON.DAYS'|translate}})", + "UD_REEVAL_TIME0": "Dato de la unua revalorigo", + "SIG_QTY_RULE": "Nombro de necesaj atestaĵoj por fariÄi membro", + "SIG_STOCK": "Maksimuma nombro da senditaj atestaĵoj por membro", + "SIG_PERIOD": "Minimuma daÅro de atendado inter 2 sinsekvaj atestaĵoj senditaj de sama persono", + "SIG_WINDOW": "LimdaÅro por akcepti atestaĵon", + "SIG_VALIDITY": "VivdaÅro de atestaĵo, kiu estis akceptita", + "MS_WINDOW": "LimdaÅro por akcepti aliÄ-peton kiel membron", + "MS_VALIDITY": "VivdaÅro de aliÄo, kiu estis akceptita", + "STEP_MAX": "Maksimuma distanco, per la atestaĵoj, inter nova eniranto kaj la referencaj membroj", + "WOT_RULES_DIVIDER": "Reguloj de la reto de fido", + "SENTRIES": "Nombro de atestaĵoj (senditaj <b>kaj</b> ricevitaj) por fariÄi referenca membro", + "SENTRIES_FORMULA": "Nombro de atestaĵoj (senditaj <b>kaj</b> ricevitaj) por fariÄi referenca membro (formulo)", + "XPERCENT":"Minimuma procento da referencaj membroj atingenda por konformiÄi al la regulo pri distanco", + "AVG_GEN_TIME": "Meza daÅro inter du blokoj", + "CURRENT": "nuna", + "MATH_CEILING": "PLAFONO", + "DISPLAY_ALL_RULES": "AfiÅi ĉiujn regulojn?", + "BTN_SHOW_LICENSE": "Vidi la licencon", + "WOT_DIVIDER": "Reto de fido" + }, + "LICENSE": { + "TITLE": "Licenco de la mono", + "BTN_DOWNLOAD": "ElÅuti la dosieron", + "NO_LICENSE_FILE": "Dosiero pri licenco ne trovita." + } + }, + "NETWORK": { + "VIEW": { + "MEDIAN_TIME": "Horo de la blokĉeno", + "LOADING_PEERS": "Nodoj ÅarÄiÄantaj...", + "NODE_ADDRESS": "Adreso:", + "SOFTWARE": "Programo", + "WARN_PRE_RELEASE": "AntaÅ-versio (lasta stabila versio: <b>{{version}}</b>)", + "WARN_NEW_RELEASE": "Versio <b>{{version}}</b> disponebla", + "WS2PID": "Identigilo:", + "PRIVATE_ACCESS": "Privata aliro", + "POW_PREFIX": "Prefikso pri labor-pruvo:", + "ENDPOINTS": { + "BMAS": "Sekurigita interfaco (SSL)", + "BMATOR": "Reta interfaco TOR", + "WS2P": "Interfaco WS2P", + "ES_USER_API": "Nodo de datenoj Cesium+" + } + }, + "INFO": { + "ONLY_SSL_PEERS": "La nodoj ne-SSL estas mis-afiÅitaj, ĉar Cesium funkcias laÅ moduso HTTPS." + } + }, + "PEER": { + "PEERS": "Nodoj", + "SIGNED_ON_BLOCK": "Skribita en la bloko", + "MIRROR": "spegulo", + "MIRRORS": "Speguloj", + "MIRROR_PEERS": "Spegul-nodoj", + "PEER_LIST" : "Listo de la nodoj", + "MEMBERS" : "Membroj", + "MEMBER_PEERS" : "Membro-nodoj", + "ALL_PEERS" : "Ĉiuj nodoj", + "DIFFICULTY" : "Malfacileco", + "API" : "API", + "CURRENT_BLOCK" : "Bloko #", + "POPOVER_FILTER_TITLE": "Filtrilo", + "OFFLINE": "Nekonektita", + "OFFLINE_PEERS": "Nekonektitaj nodoj", + "BTN_SHOW_PEER": "Vidi la nodon", + "VIEW": { + "TITLE": "Nodo", + "OWNER": "Apartenas al", + "SHOW_RAW_PEERING": "Vidi la samrangan dokumenton", + "SHOW_RAW_CURRENT_BLOCK": "Vidi la lastan blokon (kompleta strukturo)", + "LAST_BLOCKS": "Lastaj blokoj konataj", + "KNOWN_PEERS": "Konataj nodoj:", + "GENERAL_DIVIDER": "Äœeneralaj informoj", + "ERROR": { + "LOADING_TOR_NODE_ERROR": "Neeblas ricevi la informojn de la nodo. La limdaÅro de atendado estas transpasita.", + "LOADING_NODE_ERROR": "Neeblas ricevi la informojn de la nodo" + } + } + }, + "WOT": { + "SEARCH_HELP": "Traserĉado (pseÅdo aÅ publika Ålosilo)", + "SEARCH_INIT_PHASE_WARNING": "Dum la periodo de antaÅ-aliÄo, la traserĉado de la atendantaj aliÄoj <b>povas esti longa</b>. Bonvolu pacienci...", + "REGISTERED_SINCE": "Enskribita la", + "REGISTERED_SINCE_BLOCK": "Enskribita en la bloko #", + "NO_CERTIFICATION": "Neniu atestaĵo validigita", + "NO_GIVEN_CERTIFICATION": "Neniu atestaĵo sendita", + "NOT_MEMBER_PARENTHESIS": "(ne membro)", + "IDENTITY_REVOKED_PARENTHESIS": "(identeco nuligita)", + "MEMBER_PENDING_REVOCATION_PARENTHESIS": "(nuliÄanta)", + "EXPIRE_IN": "FiniÄo", + "NOT_WRITTEN_EXPIRE_IN": "Limdato<br/>de traktado", + "EXPIRED": "FiniÄinta", + "PSEUDO": "PseÅdonimo", + "SIGNED_ON_BLOCK": "Sendita en la bloko #{{block}}", + "WRITTEN_ON_BLOCK": "Enskribita en la bloko #{{block}}", + "GENERAL_DIVIDER": "Äœeneralaj informoj", + "NOT_MEMBER_ACCOUNT": "Simpla konto (ne membro)", + "NOT_MEMBER_ACCOUNT_HELP": "Temas pri simpla monujo, sen aliÄ-peto atendanta.", + "TECHNICAL_DIVIDER": "Teknikaj informoj", + "BTN_CERTIFY": "Atesti", + "BTN_YES_CERTIFY": "Jes, atesti", + "BTN_SELECT_AND_CERTIFY": "Nova atestaĵo", + "ACCOUNT_OPERATIONS": "Spezoj en la konto", + "VIEW": { + "POPOVER_SHARE_TITLE": "Identeco {{title}}" + }, + "LOOKUP": { + "TITLE": "Reto de fido", + "NEWCOMERS": "Novaj membroj", + "NEWCOMERS_COUNT": "{{count}} membroj", + "PENDING": "Atendantaj enskribiÄoj", + "PENDING_COUNT": "{{count}} atendantaj enskribiÄoj", + "REGISTERED": "Enskribita {{sigDate | formatFromNow}}", + "MEMBER_FROM": "Membro depost {{memberDate|medianFromNowShort}}", + "BTN_NEWCOMERS": "Novaj membroj", + "BTN_PENDING": "Atendantaj enskribiÄoj", + "SHOW_MORE": "AfiÅi pli", + "SHOW_MORE_COUNT": "(nuna limo je {{limit}})", + "NO_PENDING": "Neniu enskribiÄo atendanta.", + "NO_NEWCOMERS": "Neniu membro." + }, + "CONTACTS": { + "TITLE": "Kontaktoj" + }, + "MODAL": { + "TITLE": "Traserĉado" + }, + "CERTIFICATIONS": { + "TITLE": "{{uid}} - Atestaĵoj", + "SUMMARY": "Ricevitaj atestaĵoj", + "LIST": "Detalo pri la ricevitaj atestaĵoj", + "PENDING_LIST": "Atestaĵoj atendantaj traktadon", + "RECEIVED": "Ricevitaj atestaĵoj", + "RECEIVED_BY": "Atestaĵoj ricevitaj de {{uid}}", + "ERROR": "Atestaĵoj erare ricevitaj", + "SENTRY_MEMBER": "Referenca membro" + }, + "OPERATIONS": { + "TITLE": "{{uid}} - Spezoj" + }, + "GIVEN_CERTIFICATIONS": { + "TITLE": "{{uid}} - Senditaj atestaĵoj", + "SUMMARY": "Senditaj atestaĵoj", + "LIST": "Detalo pri la senditaj atestaĵoj", + "PENDING_LIST": "Atestaĵoj atendantaj traktadon", + "SENT": "Senditaj atestaĵoj", + "SENT_BY": "Atestaĵoj senditaj de {{uid}}", + "ERROR": "Atestaĵoj erare senditaj" + } + }, + "LOGIN": { + "TITLE": "<i class=\"icon ion-log-in\"></i> KonektiÄo", + "SCRYPT_FORM_HELP": "Bonvolu tajpi viajn identigilojn.<br>Pensu kontroli, ke la publika Ålosilo estas tiu de via konto.", + "PUBKEY_FORM_HELP": "Bonvolu tajpi publikan Ålosilon de konto:", + "FILE_FORM_HELP": "Elektu la Ålosilaro-dosieron uzotan:", + "SCAN_FORM_HELP": "Skani la QR-kodon de monujo.", + "SALT": "Sekreta identigilo", + "SALT_HELP": "Sekreta identigilo", + "SHOW_SALT": "AfiÅi la sekretan identigilon?", + "PASSWORD": "Pasvorto", + "PASSWORD_HELP": "Pasvorto", + "PUBKEY_HELP": "Publika Ålosilo aÅ pseÅdonimo", + "NO_ACCOUNT_QUESTION": "Vi ankoraÅ ne havas konton?", + "HAVE_ACCOUNT_QUESTION": "Vi jam havas konton?", + "CREATE_ACCOUNT": "Krei konton...", + "CREATE_FREE_ACCOUNT": "Krei konton senpage", + "FORGOTTEN_ID": "Pasvorto forgesita?", + "ASSOCIATED_PUBKEY": "Publika Ålosilo de la Ålosilaro:", + "BTN_METHODS": "Aliaj metodoj", + "BTN_METHODS_DOTS": "ÅœanÄi metodon...", + "METHOD_POPOVER_TITLE": "Metodoj", + "MEMORIZE_AUTH_FILE": "Memorigi tiun Ålosilaron por la daÅro de la sesio de retumado", + "SCRYPT_PARAMETERS": "Parametroj (Skripto):", + "AUTO_LOGOUT": { + "TITLE": "Informo", + "MESSAGE": "<i class=\"ion-android-time\"></i> Vi estis <b>malkonektita</b> aÅtomate, pro tro longa senaktiveco.", + "BTN_RELOGIN": "RekonektiÄi", + "IDLE_WARNING": "Vi estos malkonektita... {{countdown}}" + }, + "METHOD": { + "SCRYPT_DEFAULT": "Sekreta identigilo kaj pasvorto", + "SCRYPT_ADVANCED": "Sperta salumado", + "FILE": "Dosiero pri Ålosilaro", + "PUBKEY": "Publika Ålosilo aÅ pseÅdonimo", + "SCAN": "Skani QR-kodon" + }, + "SCRYPT": { + "SIMPLE": "Malpeza salumado", + "DEFAULT": "Kutima salumado", + "SECURE": "Sekura salumado", + "HARDEST": "Plej sekura salumado", + "EXTREME": "Ekstrema salumado", + "USER": "Personigita salumado", + "N": "N (Loop):", + "r": "r (RAM):", + "p": "p (CPU):" + }, + "FILE": { + "HELP": "Atendita strukturo de dosiero: <b>.yml</b> aÅ <b>.dunikey</b> (tipo PubSec, WIF aÅ EWIF)." + } + }, + "AUTH": { + "TITLE": "<i class=\"icon ion-locked\"></i> AÅtentigado", + "BTN_AUTH": "AÅtentiÄi", + "GENERAL_HELP": "Bonvolu aÅtentiÄi:", + "EXPECTED_UID_HELP": "Bonvolu aÅtentiÄi ĉe la konto <i class=\"ion-person\"></i> {{uid}} :", + "EXPECTED_PUBKEY_HELP": "Bonvolu aÅtentiÄi ĉe la monujo <br class=\"visible-xs\"/><i class=\"ion-key\"></i> {{pubkey|formatPubkey}} :", + "SCAN_FORM_HELP": "Skani la QR-kodon de la <b>privata Ålosilo</b> de la monujo." + }, + "ACCOUNT": { + "TITLE": "Mia konto", + "BALANCE": "Saldo", + "LAST_TX": "Lastaj spezoj validigitaj", + "BALANCE_ACCOUNT": "Konto-saldo", + "NO_TX": "Neniu spezo", + "SHOW_MORE_TX": "AfiÅi pli", + "SHOW_ALL_TX": "AfiÅi ĉion", + "TX_FROM_DATE": "(nuna limo je {{fromTime|medianFromNowShort}})", + "PENDING_TX": "Spezoj atendantaj traktadon", + "VALIDATING_TX": "Spezoj traktitaj, ne validigitaj", + "ERROR_TX": "Spezoj ne realigitaj", + "ERROR_TX_SENT": "Spezoj malsukcesintaj", + "PENDING_TX_RECEIVED": "Spezoj atendantaj ricevon", + "EVENTS": "Okazaĵoj", + "OUT_DISTANCED": "Viaj nunaj atestaĵoj venas de tro izolita grupo de la <a ng-click=\"showHelpModal('wot')\">Reto de Fido</a> (RdF): al la <a ng-click=\"showHelpModal('distance_rule')\">regulo de maksimuma distanco</a> vi ne konformiÄas.<br/>Vi devas akiri atestaĵojn venantajn de aliaj lokoj de la RdF, aÅ atendi ke tiu ĉi densiÄos.", + "WAITING_MEMBERSHIP": "AliÄo-peto sendita. Atendanta akcepton.", + "WAITING_CERTIFICATIONS": "Vi devas <b>akiri {{needCertificationCount}} atestaĵo(j)n</b> por fariÄi membro kaj produkti la <a ng-click=\"showHelpModal('ud')\">Universalan Dividendon</a>. Via konto tamen estas jam funkcianta, por ricevi kaj efektivigi pagojn.", + "WAITING_CERTIFICATIONS_HELP": "Por akiri viajn atestaĵojn, petu nur membrojn <b>kiuj sufiĉe konas vin</b>, kiel postulas <a ng-click=\"showLicenseModal()\">la licenco de la mono</a>, kiun vi akceptis.<br/>Se vi ne konas sufiĉe da membroj, sciigu tion ĉe <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">la forumo por uzantoj</a>.", + "WILL_MISSING_CERTIFICATIONS": "BaldaÅ <b>mankos al vi atestaĵoj</b> (almenaÅ {{willNeedCertificationCount}} estas necesaj)", + "WILL_NEED_RENEW_MEMBERSHIP": "Via aliÄo kiel membro <b>estas finiÄonta {{membershipExpiresIn|formatDurationTo}}</b>. Pensu <a ng-click=\"doQuickFix('renew')\">revalidigi vian aliÄon</a> Äis tiam.", + "NEED_RENEW_MEMBERSHIP": "Vi ne plu estas membro de la mono, ĉar <b>via aliÄo finiÄis</b>. Pensu <a ng-click=\"doQuickFix('renew')\">revalidigi vian aliÄon</a>.", + "NEED_RENEW_MEMBERSHIP_AFTER_CANCELLED": "Vi ne plu estas membro de la mono, <b>pro manko da atestaĵoj</b>. Pensu <a ng-click=\"doQuickFix('renew')\">revalidigi vian aliÄon</a>.", + "NO_WAITING_MEMBERSHIP": "Neniu aliÄo-peto atendanta. Se vi deziras <b>fariÄi membro</b>, pensu <a ng-click=\"doQuickFix('membership')\">sendi la aliÄo-peton</a>.", + "CERTIFICATION_COUNT": "Ricevitaj atestaĵoj", + "CERTIFICATION_COUNT_SHORT": "Atestaĵoj", + "SIG_STOCK": "Senditaj atestaĵoj", + "BTN_RECEIVE_MONEY": "Enkasigi", + "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Aliri alian identecon...", + "BTN_FIX_MEMBERSHIP": "Resendi la aliÄo-peton...", + "BTN_MEMBERSHIP_RENEW": "Revalidigi la aliÄon", + "BTN_MEMBERSHIP_RENEW_DOTS": "Revalidigi la aliÄon...", + "BTN_MEMBERSHIP_OUT_DOTS": "Ĉesigi la aliÄon...", + "BTN_SECURITY_DOTS": "Konto kaj sekureco...", + "BTN_SHOW_DETAILS": "AfiÅi la teknikajn informojn", + "LOCKED_OUTPUTS_POPOVER": { + "TITLE": "Sumo blokita", + "DESCRIPTION": "Jen la kondiĉoj de malblokado de tiu sumo:", + "DESCRIPTION_MANY": "Tiu spezo entenas plurajn partojn, pri kiuj la kondiĉoj de malblokado estas:", + "LOCKED_AMOUNT": "Kondiĉoj por la sumo:" + }, + "NEW": { + "TITLE": "Kreado de konto", + "INTRO_WARNING_TIME": "La kreado de konto ĉe {{name|capitalize}} estas tre simpla. Bonvolu tamen dediĉi sufiĉe da tempo por Äuste efektivigi tiun proceduron (por ne forgesi la identigilojn, pasvortojn, ktp.).", + "INTRO_WARNING_SECURITY": "Kontrolu ke la aparatoj, kiujn vi nun uzas (komputilo, tabuleto, telefono), <b>estas sekurigitaj kaj fidindaj</b>.", + "INTRO_WARNING_SECURITY_HELP": "Senvirusigilo Äisdata, fajroÅirmilo aktivigita, sesio protektita per pasvorto aÅ PIN-kodo, ktp.", + "INTRO_HELP": "Alklaku <b>{{'COMMON.BTN_START'|translate}}</b> por ekigi la kreadon de konto. Vi estos gvidata paÅon post paÅo.", + "REGISTRATION_NODE": "Via aliÄo estos registrita tra la nodo Duniter <b>{{server}}</b>, kiu dissendos Äin poste al la cetero de la mon-reto.", + "REGISTRATION_NODE_HELP": "Se vi ne fidas tiun nodon, bonvolu ÅanÄi Äin <a ng-click=\"doQuickFix('settings')\">en la parametroj</a> de Cesium.", + "SELECT_ACCOUNT_TYPE": "Elektu la tipon de konto kreota:", + "MEMBER_ACCOUNT": "Membro-konto", + "MEMBER_ACCOUNT_TITLE": "Kreado de membro-konto", + "MEMBER_ACCOUNT_HELP": "Se vi ankoraÅ ne enskribiÄis kiel individuo (nur unu konto eblas por unu individuo). Tia konto ebligas kunprodukti la monon, ricevante <b> universalan dividendon</b> ĉiun {{parameters.dt|formatPeriod}}n.", + "WALLET_ACCOUNT": "Simpla monujo", + "WALLET_ACCOUNT_TITLE": "Kreado de monujo", + "WALLET_ACCOUNT_HELP": "Por ĉiuj aliaj kazoj, ekzemple se vi bezonas plian konton.<br/>Neniu universala dividendo estos kreita per tia konto.", + "SALT_WARNING": "Elektu vian sekretan identigilon.<br/>Oni petos Äin de vi ĉiufoje, kiam vi konektiÄos al tiu konto.<br/><br/><b>Bone memorigu Äin</b>: kaze de perdo, neniu alia povos aliri vian konton!", + "PASSWORD_WARNING": "Elektu pasvorton.<br/>Oni petos Äin de vi ĉiufoje, kiam vi konektiÄos al tiu konto.<br/><br/><b>Bone memorigu tiun pasvorton</b: kaze de perdo, neniu alia povos aliri vian konton!", + "PSEUDO_WARNING": "Elektu pseÅdonimon.<br/>Äœi utilas al la aliaj membroj, por identigi vin pli facile.<div class='hidden-xs'><br/>Äœi <b>ne povos esti modifita</b>, sen rekrei konton.</div><br/><br/>Äœi entenu <b>nek spacon, nek diakritan literon (kun supersigno, ktp.)</b>.<div class='hidden-xs'><br/>Ekzemple: <span class='gray'>NataljaBelulino, JohanoStelaro, ktp.</span>", + "PSEUDO": "PseÅdonimo", + "PSEUDO_HELP": "PseÅdonimo", + "SALT_CONFIRM": "Konfirmo", + "SALT_CONFIRM_HELP": "Konfirmo de la sekreta identigilo", + "PASSWORD_CONFIRM": "Konfirmo", + "PASSWORD_CONFIRM_HELP": "Konfirmo de la pasvorto", + "SLIDE_6_TITLE": "Konfirmo:", + "COMPUTING_PUBKEY": "Kalkulanta...", + "LAST_SLIDE_CONGRATULATION": "Vi tajpis ĉiujn necesajn informojn: Gratulon!<br/>Vi nun povas <b>sendi la peton por kreado</b> de la konto.</b><br/><br/>Por informo, la publika Ålosilo ĉi-sube identigos vian estontan konton.<br/>Äœi povos estis sciigita al aliuloj por ricevi iliajn pagojn.<br/><b>Ne estas devige</b> noti Äin nun, vi ankaÅ povos fari tion poste.", + "CONFIRMATION_MEMBER_ACCOUNT": "<b class=\"assertive\">Averto:</b> la sekreta identigilo, la pasvorto kaj la pseÅdonimo ne plu povos esti modifitaj.<br/><br/><b>CertiÄu, ke vi ĉiam rememorigos Äin!</b><br/><br/><b>Ĉu vi certas</b>, ke vi deziras sendi tiun ĉi aliÄo-peton?", + "CONFIRMATION_WALLET_ACCOUNT": "<b class=\"assertive\">Averto:</b> la sekreta identigilo kaj la pasvorto ne plu povos esti modifitaj.<br/><br/><b>CertiÄu, ke vi ĉiam rememorigos Äin!</b><br/><br/><b>Ĉu vi certas</b>, ke vi deziras daÅrigi per tiuj ĉi identigiloj?", + "CHECKING_PSEUDO": "Kontrolo...", + "PSEUDO_AVAILABLE": "PseÅdonimo disponebla", + "PSEUDO_NOT_AVAILABLE": "PseÅdonimo ne disponebla", + "INFO_LICENSE": "AntaÅ ol krei membro-konton, <b>bonvolu legi kaj akcepti la licencon</b> pri uzado de la mono:", + "BTN_ACCEPT": "Mi akceptas", + "BTN_ACCEPT_LICENSE": "Mi akceptas la licencon" + }, + "POPUP_REGISTER": { + "TITLE": "Elektu pseÅdonimon", + "HELP": "PseÅdonimo estas deviga por fariÄi membro." + }, + "SELECT_IDENTITY_MODAL": { + "TITLE": "Elekto de la identeco", + "HELP": "Pluraj <b>malsamaj identecoj</b> estis senditaj, por la publika Ålosilo <span class=\"gray\"><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</span>.<br/>Bonvolu elekti la dosierujon uzotan:" + }, + "SELECT_WALLET_MODAL": { + "TITLE": "Elekto de la monujo" + }, + "WALLET_LIST": { + "TITLE": "Miaj monujoj", + "BTN_NEW": "Aldoni monujon", + "BTN_DOWNLOAD": "ElÅuti la liston", + "BTN_IMPORT_FILE_DOTS": "Enporti el dosiero...", + "NO_WALLET": "Neniu kroma monujo", + "BTN_DELETE": "Forigi kroman monujon...", + "BTN_RENAME": "Renomi la monujon", + "EXPORT_FILENAME": "miaj_monujoj-{{pubkey|formatPubkey}}-{{currency}}.csv", + "TOTAL_DOTS": "Sumo: ", + "EDIT_POPOVER": { + "TITLE": "Renomi la monujon", + "HELP": "Sciigu la novan nomon", + "NAME_HELP": "Nomo de la monujo" + }, + "IMPORT_MODAL": { + "TITLE": "Enporti monujojn", + "HELP": "Por <b>enporti monujojn</b>, bonvolu glitigi en la ĉi-suban zonon la dosieron pri la listo de monujoj, aÅ alklaki la zonon por serĉadi dosieron.", + "WALLET_COUNT": "<b>{{count}}</b> nova{{count > 1 ? 'j' : ''}} monujo{{count > 1 ? 'j' : ''}}", + "NO_NEW_WALLET": "Neniu nova monujo" + } + }, + "SECURITY": { + "ADD_QUESTION": "Aldoni personigitan demandon", + "BTN_CLEAN": "Malplenigi", + "BTN_RESET": "Restartigi", + "DOWNLOAD_REVOKE": "Konservi mian dosieron pri nuligo", + "DOWNLOAD_REVOKE_HELP": "Disponi dosieron pri nuligo estas grave, ekzemple kaze de perdo de viaj identigiloj. Äœi ebligas al vi <b>elirigi tiun konton el la reto de fido</b>, tiel ke Äi refariÄu simpla monujo.", + "GENERATE_KEYFILE": "Krei mian dosieron pri Ålosilaro...", + "GENERATE_KEYFILE_HELP": "Kreas dosieron, kiu ebligas al vi aÅtentiÄi sen tajpi viajn identigilojn.<br/><b>Atenton:</b> tiu dosiero entenos vian konto-Ålosilaron (publikan kaj sekretan Ålosilojn); do tre gravas meti Äin en sekuran lokon!", + "KEYFILE_FILENAME": "Ålosilaro-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", + "MEMBERSHIP_IN": "Transformi en membro-konton...", + "MEMBERSHIP_IN_HELP": "Ebligas <b>transformi</b> simplan monujo-konton <b>en membro-konton</b>, sendante aliÄo-peton. Utilas nur se vi ne havas jam alian membro-konton.", + "SEND_IDENTITY": "Publikigi sian identecon...", + "SEND_IDENTITY_HELP": "Ebligas kunligi pseÅdonimon kun tiu ĉi konto, sed <b>sen fari aliÄo-peton</b> por iÄi membro. Tiu kunligo kutime ne utilas, ĉar la valideco de tiu kunligo de pseÅdonimo estas limigita en la tempo.", + "HELP_LEVEL": "Por krei konserv-dosieron pri viaj identigiloj, elektu <strong> almenaÅ {{nb}} demandojn:</strong>", + "LEVEL": "Nivelo de sekureco", + "LOW_LEVEL": "Malforta <span class=\"hidden-xs\">(2 demandoj minimume)</span>", + "MEDIUM_LEVEL": "Meza <span class=\"hidden-xs\">(4 demandoj minimume)</span>", + "QUESTION_1": "Kiel nomiÄis via plej bona amik.in.o, kiam vi estis adoleskant.in.o?", + "QUESTION_2": "Kiel nomiÄis via unua hejm-besto?", + "QUESTION_3": "Kiun pladon vi unue lernis kuiradi?", + "QUESTION_4": "Kiun filmon vi unue spektis en kinejo?", + "QUESTION_5": "Kien vi iris la unuan fojon, kiam vi vojaÄis per aviadilo?", + "QUESTION_6": "Kiel nomiÄis via preferata instruist.i.no en bazlernejo?", + "QUESTION_7": "Kio estus laÅ vi la ideala profesio?", + "QUESTION_8": "Kiun libron por infanoj vi preferas?", + "QUESTION_9": "Kio estis la marko de via unua veturilo?", + "QUESTION_10": "Kio estis via kromnomo, kiam vi estis infano?", + "QUESTION_11": "Kiun rolant.in.on aÅ aktor.in.on vi preferis en kino, kiam vi estis student.in.o?", + "QUESTION_12": "Kiun kanzonist.ino.n aÅ muzikgrupon vi preferis, kiam vi estis student.in.o?", + "QUESTION_13": "En kiu urbo renkontiÄis viaj gepatroj?", + "QUESTION_14": "Kiel nomiÄis via unua ĉefo?", + "QUESTION_15": "Kiel nomiÄas la strato, kie vi kreskis?", + "QUESTION_16": "Kiel nomiÄas la marbordo, kie vi unuafoje baniÄis?", + "QUESTION_17": "Kiun muzik-albumon vi unuafoje aĉetis?", + "QUESTION_18": "Kiel nomiÄas via preferata sporto-teamo?", + "QUESTION_19": "Kio estis la profesio de via avo?", + "RECOVER_ID": "Retrovi mian pasvorton...", + "RECOVER_ID_HELP": "Se vi disponas <b>konserv-dosieron pri viaj identigiloj</b>, vi povas retrovi ilin respondante Äuste viajn personajn demandojn.", + "REVOCATION_WITH_FILE": "Nuligi mian membro-konton...", + "REVOCATION_WITH_FILE_DESCRIPTION": "Se vi <b>definitive perdis viajn identigilojn</b> pri via membro-konto (aÅ ke la sekureco de la konto estas endanÄerigita), vi povas uzi <b>la dosieron pri nuligo</b> de la konto por <b>trudi ties definitivan eliradon el la reto de fido</b>.", + "REVOCATION_WITH_FILE_HELP": "Por <b>definitive nuligi</b> membro-konton, bonvolu glitigi en la ĉi-suban zonon vian dosieron pri nuligo, aÅ alklaki la zonon por serĉadi dosieron.", + "REVOCATION_WALLET": "Nuligi tiun ĉi konton tuj", + "REVOCATION_WALLET_HELP": "Peti la nuligon de via identeco estigas la <b>eliradon el la reto de fido</b> (definitivan por la pseÅdonimo kaj la publika Ålosilo kunligitaj). La konto ne plu povos produkti Universalan Dividendon.<br/>Vi tamen daÅre povos konektiÄi al Äi, kiel al simpla monujo.", + "REVOCATION_FILENAME": "nuligo-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "SAVE_ID": "Konservi miajn identigilojn...", + "SAVE_ID_HELP": "Kreado de konserv-dosiero, por <b>retrovi vian pasvorton</b> (kaj la sekretan identigilon) <b>kaze de forgeso</b>. La dosiero estas <b>sekurigita</b> (ĉifrita) dank'al personaj demandoj.", + "STRONG_LEVEL": "Forta <span class=\"hidden-xs \">(6 demandoj minimume)</span>", + "TITLE": "Konto kaj sekureco", + "KEYFILE": { + "PUBSEC_FORMAT": "Strukturo PubSec.", + "PUBSEC_FORMAT_HELP": "Tiu strukturo stokas vian Ålosilaron laÅ tre simpla maniero. Äœi kongruas aparte kun Cesium, ÄŸannonce kaj Duniter.<br/><b>Atenton:</b>La dosiero <b>ne estas ĉifrita</b> (la sekreta Ålosilo klare aperas en Äi); bonvolu do stoki Äin en sekura loko!", + "WIF_FORMAT": "Strukturo WIF (Wallet Import Format) - v1", + "WIF_FORMAT_HELP": "Tiu strukturo stokas vian Ålosilaron inkluzivante en Äin kontrol-sumon por kontroli la sendifektecon de la dosiero. Äœi kongruas aparte kun la paper-monujoj (Duniter paper wallet).<br/><b>Atenton:</b>La dosiero <b>ne estas ĉifrita</b> (la sekreta Ålosilo klare aperas en Äi); bonvolu do stoki Äin en sekura loko!", + "EWIF_FORMAT": "Strukturo EWIF (Encrypted Wallet Import Format) - v1", + "EWIF_FORMAT_HELP": "Tiu strukturo stokas vian Ålosilaron <b>laŠĉifrita maniero</b> dank'al sekreta frazo elektita de vi. Äœi ankaÅ inkluzivas kontrol-sumon por kontroli la sendifektecon de la dosiero.<br/><b>Atenton:</b> Zorgu, ke vi ĉiam rememoru vian sekretan frazon!", + "PASSWORD_POPUP": { + "TITLE": "Ĉifrita dosiero pri Ålosilaro", + "HELP": "Bonvolu indiki la la sekretan frazon:", + "PASSWORD_HELP": "Sekreta frazo" + }, + "ERROR": { + "BAD_PASSWORD": "Sekreta frazo malÄusta", + "BAD_CHECKSUM": "Kontrol-sumo malÄusta" + } + } + }, + "FILE_NAME": "{{currency}} - Konto-tabelo {{pubkey|formatPubkey}} je {{currentTime|formatDateForFile}}.csv", + "HEADERS": { + "TIME": "Dato", + "AMOUNT": "Sumo", + "COMMENT": "Komento" + } + }, + "TRANSFER": { + "TITLE": "Elspezo", + "SUB_TITLE": "Fari elspezon", + "SUB_TITLE_ALL": "Malplenigi la konton", + "FROM": "De", + "TO": "Al", + "AMOUNT": "Sumo", + "AMOUNT_HELP": "Sumo", + "COMMENT": "Komento", + "COMMENT_HELP": "Komento", + "BTN_SEND": "Sendi", + "BTN_ADD_COMMENT": "Aldoni komenton", + "REST": "Resto de la konto", + "REST_TO": "al", + "WARN_COMMENT_IS_PUBLIC": "Bonvolu noti, ke <b>la komentoj estas publikaj</b> (ne ĉifritaj).", + "MODAL": { + "TITLE": "Elspezo" + } + }, + "ERROR": { + "UNKNOWN_URI_FORMAT": "URI-strukturo nekonata", + "PUBKEY_INVALID_CHECKSUM": "Publika Ålosilo nevalida (bad checksum).", + "POPUP_TITLE": "Eraro", + "UNKNOWN_ERROR": "Eraro nekonata", + "CRYPTO_UNKNOWN_ERROR": "Via retumilo Åajnas ne kongrua kun la kriptografiaj funkcioj.", + "DOWNLOAD_KEYFILE_FAILED": "Malsukceso por la kreado de la dosiero pri Ålosilaro.", + "EQUALS_TO_PSEUDO": "Devas esti malsama ol la pseÅdonimo", + "EQUALS_TO_SALT": "Devas esti malsama ol la sekreta identigilo", + "FIELD_REQUIRED": "Deviga kampo", + "FIELD_TOO_SHORT": "Signaro tro mallonga", + "FIELD_TOO_SHORT_WITH_LENGTH": "Signaro tro mallonga ({{minLength}} signoj minimume)", + "FIELD_TOO_LONG": "Signaro tro longa", + "FIELD_TOO_LONG_WITH_LENGTH": "Signaro tro longa ({{maxLength}} signoj maksimume)", + "FIELD_MIN": "Minimuma longeco: {{min}}", + "FIELD_MAX": "Maksimuma longeco: {{max}}", + "FIELD_ACCENT": "Diakritaj literoj kaj komoj ne permesataj", + "FIELD_NOT_NUMBER": "Nombra valoro atendata", + "FIELD_NOT_INT": "Entjera nombro atendata", + "FIELD_NOT_EMAIL": "Retadreso nevalida", + "PASSWORD_NOT_CONFIRMED": "Ne kongruas kun la pasvorto", + "SALT_NOT_CONFIRMED": "Ne kongruas kun la sekreta identigilo", + "SEND_IDENTITY_FAILED": "AliÄo malsukcesa", + "SEND_CERTIFICATION_FAILED": "Atestado malsukcesa", + "NEED_MEMBER_ACCOUNT_TO_CERTIFY": "Vi ne povas efektivigi atestadon, ĉar via konto <b>ne estas membro</b>.", + "NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF": "Vi ne povas efektivigi atestadon, ĉar via konto ankoraÅ ne estas membro.<br/><br/>AnkoraÅ mankas al vi atestaĵoj, aÅ tiuj ĉi ankoraÅ ne estis validigitaj.", + "NOT_MEMBER_FOR_CERTIFICATION": "Via konto ankoraÅ ne estas membro.", + "IDENTITY_TO_CERTIFY_HAS_NO_SELF": "Konto ne atestebla. Neniu aliÄo-peto estis farita, aÅ la aliÄo ne estis revalidigita.", + "LOGIN_FAILED": "Eraro dum konektiÄo.", + "LOAD_IDENTITY_FAILED": "Eraro por ÅarÄi la identecon.", + "LOAD_REQUIREMENTS_FAILED": "Eraro por ÅarÄi la antaÅ-necesaĵoj de la identeco.", + "SEND_MEMBERSHIP_IN_FAILED": "Malsukceso pri la provado eniri la komunumon.", + "SEND_MEMBERSHIP_OUT_FAILED": "Malsukceso pri la ĉesigo de la aliÄo.", + "REFRESH_WALLET_DATA": "Malsukceso pri la Äisdatigo de la monujo.", + "GET_CURRENCY_PARAMETER": "Malsukceso por ricevi la regulojn de la mono.", + "GET_CURRENCY_FAILED": "Ne eblis ÅarÄi la monon. Bonvolu reprovi pli poste.", + "SEND_TX_FAILED": "Elspezado malsukcesa.", + "ALL_SOURCES_USED": "Bonvolu atendi la kalkulon de la venonta bloko (ĉiuj viaj monfontoj estis uzitaj).", + "NOT_ENOUGH_SOURCES": "Ne sufiĉe da mono por sendi tiun ĉi sumon per ununura spezo.<br/>Maksimuma sumo: {{amount}} {{unit}}<sub>{{subUnit}}</sub>.", + "ACCOUNT_CREATION_FAILED": "Malsukceso por krei la membro-konton.", + "RESTORE_WALLET_DATA_ERROR": "Malsukceso por reÅarÄi la parametrojn de la loka stokaĵo", + "LOAD_WALLET_DATA_ERROR": "Malsukceso por ÅarÄi la datenojn de la monujo.", + "COPY_CLIPBOARD_FAILED": "Ne eblis kopii la valoron.", + "TAKE_PICTURE_FAILED": "Malsukceso por ricevi la foton.", + "SCAN_FAILED": "Malsukceso por skani la QR-kodon.", + "SCAN_UNKNOWN_FORMAT": "Kodo nerekonata.", + "WOT_LOOKUP_FAILED": "Serĉado malsukcesa.", + "LOAD_PEER_DATA_FAILED": "Ne eblis legi la nodon Duniter. Bonvolu reprovi poste.", + "NEED_LOGIN_FIRST": "Bonvolu unue konektiÄi.", + "AMOUNT_REQUIRED": "La monsumo estas deviga.", + "AMOUNT_NEGATIVE": "Negativa sumo nepermesata.", + "NOT_ENOUGH_CREDIT": "Saldo nesufiĉa.", + "INVALID_NODE_SUMMARY": "Nodo neatingebla aÅ adreso nevalida.", + "INVALID_USER_ID": "La pseÅdonimo devas enteni nek spacon nek signon specialan aÅ kun supersigno.", + "INVALID_COMMENT": "La kampo 'referenco' ne devas enteni literojn kun supersigno.", + "INVALID_PUBKEY": "La publika Ålosilo ne havas la atenditan strukturon.", + "INVALID_PUBKEY_CHECKSUM": "Kontrol-sumo nevalida.", + "IDENTITY_REVOKED": "Tiu ĉi identeco <b>estis nuligita</b>. Äœi ne plu povas fariÄi membro.", + "IDENTITY_REVOKED_WITH_TIME": "Tiu ĉi identeco <b>estis nuligita {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). Äœi ne plu povas fariÄi membro.", + "IDENTITY_PENDING_REVOCATION": "La <b>nuligo de tiu ĉi identeco</b> estis petita kaj atendas traktadon. La atestado estas do malaktivigita.", + "IDENTITY_INVALID_BLOCK_HASH": "Tiu ĉi aliÄo-peto ne plu validas (ĉar Äi rilatas al bloko, kiun nuligis la nodoj de la reto): tiu persono devas refari sian aliÄo-peton <b>antaÅ ol</b> esti atestita.", + "IDENTITY_EXPIRED": "La publikigo de tiu ĉi identeco finiÄis: tiu persono devas fari novan aliÄo-peton <b>antaÅ ol</b> esti atestita.", + "IDENTITY_SANDBOX_FULL": "La nodo Duniter uzata de Cesium ne plu povas ricevi novajn identecojn, ĉar Äia atendo-vico estas plena.<br/><br/>Bonvolu reprovi poste aÅ ÅanÄi la nodon (per la menuo <b>Parametroj</b>).", + "IDENTITY_NOT_FOUND": "Identeco ne trovita.", + "IDENTITY_TX_FAILED": "Malsukceso por ÅarÄi la spezojn.", + "WOT_PENDING_INVALID_BLOCK_HASH": "AliÄo ne valida.", + "WALLET_INVALID_BLOCK_HASH": "Via aliÄo-peto ne plu validas (ĉar Äi rilatas al bloko, kiun nuligis la nodoj de la reto).<br/>Vi devas <a ng-click=\"doQuickFix('fixMembership')\">sendi novan peton</a> por solvi tiun ĉi problemon.", + "WALLET_IDENTITY_EXPIRED": "La publikigo de <b>via identeco finiÄis</b>.<br/>Vi devas <a ng-click=\"doQuickFix('fixIdentity')\">publikigi denove vian identecon</a> por solvi tiun ĉi problemon.", + "WALLET_REVOKED": "Via identeco estis <b>nuligita</b>: nek via pseÅdonimo nek via publika Ålosilo povos esti uzata en la estonteco por membro-konto.", + "WALLET_HAS_NO_SELF": "Via identeco devas unue esti publikigita, kaj ne esti finiÄinta.", + "AUTH_REQUIRED": "AÅtentigado necesa.", + "AUTH_INVALID_PUBKEY": "La atendata Ålosilo estas <i class=\"ion-key\"></i> {{pubkey|formatPubkey}}...", + "AUTH_INVALID_SCRYPT": "Identigilo aÅ pasvorto nevalida.", + "AUTH_INVALID_FILE": "Dosiero pri Ålosilaro nevalida.", + "AUTH_FILE_ERROR": "Malsukceso por malfermi la dosieron pri Ålosilaro.", + "IDENTITY_ALREADY_CERTIFY": "Vi <b>jam atestis</b> tiun identecon.<br/><br/>Tiu atestado daÅre validas (finiÄo {{expiresIn|formatDurationTo}}).", + "IDENTITY_ALREADY_CERTIFY_PENDING": "Vi <b>jam atestis</b> tiun identecon.<br/><br/>Tiu atestado atendas traktadon (limdato de traktado {{expiresIn|formatDurationTo}}).", + "UNABLE_TO_CERTIFY_TITLE": "Atestado neebla", + "LOAD_NEWCOMERS_FAILED": "Malsukceso por ÅarÄi la novajn membrojn.", + "LOAD_PENDING_FAILED": "Malsukceso por ÅarÄi la atendantajn aliÄojn.", + "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "Vi devas <b>esti membro</b> por rajti efektivigi tiun ĉi agon.", + "ONLY_MEMBER_OR_WAS_MEMBER_CAN_EXECUTE_THIS_ACTION": "Vi devas <b>esti membro (aÅ eksa membro)</b> por rajti efektivigi tiun ĉi agon.", + "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "Via identeco devas <b>jam esti publikigita</b>, por ke vi rajtu efektivigi tiun ĉi agon.", + "GET_BLOCK_FAILED": "Malsukceso por ricevi la blokon.", + "INVALID_BLOCK_HASH": "Bloko ne trovita (haketo malsama)", + "DOWNLOAD_REVOCATION_FAILED": "Malsukceso por elÅuti la dosieron pri nuligo.", + "REVOCATION_FAILED": "Malsukceso pri nuligo.", + "SALT_OR_PASSWORD_NOT_CONFIRMED": "Sekreta identigilo aÅ pasvorto malÄusta.", + "RECOVER_ID_FAILED": "Malsukceso por ricevi la identigilojn", + "LOAD_FILE_FAILED" : "Malsukceso por ÅarÄi la dosieron", + "NOT_VALID_REVOCATION_FILE": "Dosiero pri nuligo ne valida (malÄusta strukturo de dosiero)", + "NOT_VALID_SAVE_ID_FILE": "Dosiero pri konservado ne valida (malÄusta strukturo de dosiero)", + "NOT_VALID_KEY_FILE": "Dosiero pri Ålosilaro ne valida (strukturo ne rekonata)", + "EXISTING_ACCOUNT": "Viaj identigiloj rilatas al jam ekzistanta konto, kies <a ng-click=\"showHelpModal('pubkey')\">publika Ålosilo</a> estas:", + "EXISTING_ACCOUNT_REQUEST": "Bonvolu modifi viajn identigilojn, por ke ili rilatu al ne uzata konto.", + "GET_LICENSE_FILE_FAILED": "La ricevo de la dosiero pri licenco ne eblis.", + "CHECK_NETWORK_CONNECTION": "Neniu nodo Åajnas atingebla.<br/><br/>Bonvolu <b>kontroli vian retkonekton</b>.", + "ISSUE_524_TX_FAILED": "Malsukcesa elspezo.<br/><br/>MesaÄo estis sendita al la programistoj por faciligi la solvadon de la problemo. <b>Dankon pro via helpo</b>.", + "ADD_SECONDARY_WALLET_FAILED": "Malsukceso por aldoni kroman monujon.", + "UPDATE_WALLET_LIST_FAILED": "Malsukceso por Äisdatigi la kromajn monujojn.", + "LOAD_WALLET_LIST_FAILED": "Malsukceso por ÅarÄi la kromajn monujojn.", + "SAVE_WALLET_LIST_FAILED": "Malsukceso por konservi la kromajn monujojn.", + "COULD_NOT_ADD_MAIN_WALLET": "Tiu ĉi monujo <b>rilatas al la ĉefa konto</b>, kun kiu vi estas konektita.<br/>Ne eblas aldoni Äin kiel kroman monujon.", + "COULD_NOT_ADD_EXISTING_WALLET": "Monujo jam ekzistanta en la listo.", + "UNKNOWN_WALLET_ID": "Kroma monujo nekonata.", + "RESTORE_WALLET_LIST_FAILED": "Malsukceso por restarigi la kromajn monujojn.", + "INVALID_FILE_FORMAT": "Strukturo de dosiero nevalida." + }, + "INFO": { + "POPUP_TITLE": "Informo", + "CERTIFICATION_DONE": "Atestaĵo sendita", + "NOT_ENOUGH_CREDIT": "Saldo nesufiĉa", + "TRANSFER_SENT": "Elspezo sendita", + "COPY_TO_CLIPBOARD_DONE": "Kopiita en la memoreto", + "MEMBERSHIP_OUT_SENT": "EksiÄo sendita", + "NOT_NEED_MEMBERSHIP": "Vi jam estas membro.", + "IDENTITY_WILL_MISSING_CERTIFICATIONS": "Al tiu ĉi identeco baldaÅ mankos atestaĵoj (almenaÅ {{willNeedCertificationCount}}).", + "IDENTITY_NEED_MEMBERSHIP": "Tiu ĉi identeco ne sendis aliÄo-peton. Tion Äi devos fari, se Äi deziras fariÄi membro.", + "HAS_ALTERNATIVE_IDENTITIES": "Ekzistas <b>pluraj identecoj</b> ligitaj kun tiu ĉi publika Ålosilo. <b>AntaŠĉia atestado</b>, pensu <a ng-click=\"doQuickFix('showSelectIdentities')\">trarigardi la aliajn identecojn</a> por elekti la Äustan, aÅ kontaktu la posedanton de la konto.", + "REVOCATION_SENT": "Nuligo sendita", + "REVOCATION_SENT_WAITING_PROCESS": "La <b>nuligo de tiu ĉi identeco</b> estis petita kaj atendas traktadon.", + "FEATURES_NOT_IMPLEMENTED": "Tiu ĉi funkciaro ankoraÅ estas programiÄanta.<br/>Kial ne <b>kontribui al Cesium</b>, por ekhavi Äin pli rapide? ;)", + "EMPTY_TX_HISTORY": "Neniu spezo elportota" + }, + "CONFIRM": { + "POPUP_TITLE": "<b>Konfirmo</b>", + "POPUP_WARNING_TITLE": "<b>Averto</b>", + "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Averto pri sekureco</b>", + "CERTIFY_RULES_TITLE_UID": "Atesti {{uid}}", + "CERTIFY_RULES": "<b class=\"assertive\">NE atestu</b> konton, se vi pensas ke:<br/><br/><ul><li>1.) Äi ne rilatas al persono <b>fizika kaj vivanta</b>.<li>2.) Äia posedanto <b>havas alian konton</b> jam atestitan.<li>3.) Äia posedanto malobservas (vole aÅ ne) la regulon 1 aÅ 2 (ekzemple atestante falsajn kontojn aÅ duoblajn).</ul><br/><b>Ĉu vi certas,</b> ke vi tamen volas atesti tiun ĉi identecon?", + "FULLSCREEN": "AfiÅi la programon plen-ekrane?", + "EXIT_APP": "Fermi la programon?", + "TRANSFER": "<b>Resumo de la elspezo</b> :<br/><br/><ul><li> - De: {{from}}</li><li> - Al: <b>{{to}}</b></li><li> - Sumo: <b>{{amount}} {{unit}}</b></li><li> - Komento: <i>{{comment}}</i></li></ul><br/><b>Ĉu vi certas, ke vi volas efektivigi tiun ĉi elspezon?</b>", + "TRANSFER_ALL": "<b>Resumo de la elspezo</b>:<br/><br/><ul><li> - De : {{from}}</li><li> - Al : <b>{{to}}</b></li><li> - Sumo: <b>{{amount}} {{unit}}</b></li><li> - Komento: <i>{{comment}}</i></li><br/><li> - Resto: <b>{{restAmount}} {{unit}}</b> al <b>{{restTo}}</b></li></ul><br/><b>Ĉu vi certas, ke vi volas efektivigi tiun ĉi elspezon?</b>", + "MEMBERSHIP_OUT": "Tiu ĉi ago estas <b>neinversigebla</b>.<br/></br/>Ĉu vi certas, ke vi volas <b>nuligi vian membro-konton</b>?", + "MEMBERSHIP_OUT_2": "Tiu ĉi ago estas <b>neinversigebla</b> !<br/><br/>Ĉu vi vere certas, ke vi volas <b>nuligi vian aliÄon</b> kiel membron?", + "LOGIN_UNUSED_WALLET_TITLE": "Tajperaro?", + "LOGIN_UNUSED_WALLET": "La konektita konto Åajnas <b>neaktiva</b>.<br/><br/>Temas probable pri <b>tajperaro</b> en viaj konekto-identigiloj. Bonvolu rekomenci, kontrolante ke <b>la publika Ålosilo estas tiu de via konto</b>.", + "FIX_IDENTITY": "La pseÅdonimo <b>{{uid}}</b> estos denove publikigita, anstataÅigante la malnovan publikigon, kiu finiÄis.<br/></br/><b>Ĉu vi certas</b>, ke vi volas daÅrigi?", + "FIX_MEMBERSHIP": "Via aliÄo-peto kiel membro tuj estos resendita.<br/></br/><b>Ĉu vi certas</b>, ke vi volas daÅrigi?", + "MEMBERSHIP": "Via aliÄo-peto kiel membro tuj estos sendita.<br/></br/><b>Ĉu vi certas</b>, ke vi volas daÅrigi?", + "RENEW_MEMBERSHIP": "Via aliÄo kiel membro tuj estos revalidigita.<br/></br/><b>Ĉu vi certas</b>, ke vi volas daÅrigi?", + "REVOKE_IDENTITY": "Vi estas <b>nuligonta definitive tiun ĉi identecon</b>.<br/><br/>La publika Ålosilo kaj la ligita pseÅdonimo <b>neniam plu povos esti uzataj</b> (por membro-konto). <br/></br/><b>Ĉu vi certas</b>, ke vi volas definitive nuligi tiun ĉi konton?", + "REVOKE_IDENTITY_2": "Tiu ĉi ago estas <b>neinversigebla</b>!<br/><br/>Ĉu vi vere certas, ke vi volas <b>definitive nuligi</b> tiun ĉi konton?", + "NOT_NEED_RENEW_MEMBERSHIP": "Via aliÄo ne bezonas esti revalidigita (Äi finiÄos nur post {{membershipExpiresIn|formatDuration}}).<br/></br/><b>Ĉu vi certas</b>, ke vi volas revalidigi vian aliÄon?", + "SAVE_BEFORE_LEAVE": "Ĉu vi volas <b>konservi viajn modifojn</b> antaÅ ol eliri el la paÄo?", + "SAVE_BEFORE_LEAVE_TITLE": "Modifoj ne registritaj", + "LOGOUT": "Ĉu vi certas, ke vi volas malkonektiÄi?", + "USE_FALLBACK_NODE": "Nodo <b>{{old}}</b> neatingebla aÅ adreso nevalida.<br/><br/>Ĉu vi volas provizore uzi la nodon <b>{{new}}</b> ?", + "ISSUE_524_SEND_LOG": "La spezo estis forĵetita, pro konata anomalio (petslipo #524) sed <b>ne ripetita</b>.<br/><br/>Por helpi la programistojn korekti tiun eraron, <b>ĉu vi akceptas la sendadon de viaj protokolaj dosieroj</b> per mesaÄo?<br/><small>(neniu konfidenca dateno estas sendita)</small>." + }, + "DOWNLOAD": { + "POPUP_TITLE": "<b>Dosiero pri nuligo</b>", + "POPUP_REVOKE_MESSAGE": "Por sekurigi vian konton, bonvolu elÅuti la <b>dokumenton pri konto-nuligo</b>. Äœi ebligos al vi eventuale nuligi vian konton (kaze de konto-Åtelo, ÅanÄo de identigilo, konto erare kreita, ktp.).<br/><br/><b>Bonvolu stoki Äin en sekura loko.</b>" + }, + "HELP": { + "TITLE": "Ret-helpo", + "JOIN": { + "SECTION": "EnskribiÄo", + "SALT": "La sekreta identigilo estas tre grava. Äœi utilas por miksi la pasvorton, antaÅ ol Äi servos por kalkuli la <span class=\"text-italic\">publikan Ålosilon</span> de via konto (ties numeron) kaj la sekretan Ålosilon por aliri Äin.<br/><b>Zorgu pri Äia bona memorigado</b>, ĉar neniu rimedo estas nuntempe planita por retrovi Äin kaze de perdo.<br/>Krom tio, Äi ne povas esti modifita sen devige krei novan konton.<br/><br/>Bona sekreta identigilo devas esti sufiĉe longa (kun almenaÅ 8 signoj) kaj kiel eble plej originala.", + "PASSWORD": "La pasvorto estas tre grava. Kun la sekreta identigilo, Äi servas por kalkuli la numeron (la publikan Ålosilon) de via konto, kaj la sekretan Ålosilon por aliri Äin.<br/><b>Zorgu pri Äia bona memorigado</b>, ĉar neniu rimedo estas planita por retrovi Äin kaze de perdo (krom se oni generas konserv-dosieron).<br/>Krom tio, Äi ne povas esti modifita sen devige krei novan konton.<br/><br/>Bona pasvorto entenas (ideale) almenaÅ 8 signojn, inter kiuj estas almenaÅ unu majusklo kaj unu cifero.", + "PSEUDO": "La pseÅdonimo estas utila nur kaze de enskribiÄo kiel <span class=\"text-italic\">membro</span>. Äœi ĉiam estas ligita kun monujo (tra Äia <span class=\"text-italic\">publika Ålosilo</span>).<br/>Äœi estas publikigita en la reto, tiel ke la aliaj uzantoj povu identigi Äin, atesti Äin aÅ sendi monon al Äia konto.<br/>PseÅdonimo devas esti unika ene de la membroj (<u>nunaj</u> kaj eksaj)." + }, + "LOGIN": { + "SECTION": "Konekto", + "PUBKEY": "Publika Ålosilo de la Ålosilaro", + "PUBKEY_DEF": "La publika Ålosilo de la Ålosilaro estas kreita per la tajpitaj identigiloj (iuj ajn), sen ke ili necese rilatu al konto jam uzata.<br/><b>Atente kontrolu, ke la publika Ålosilo estas tiu de via konto</b>. Alikaze, vi estos konektita al konto probable neniam uzita, la risko de kolizio kun ekzistanta konto estante tre eta.<br/><a href=\"https://fr.wikipedia.org/wiki/Cryptographie_asym%C3%A9trique\" target=\"_system\">Scii pli pri kriptografio</a> per publika Ålosilo.", + "METHOD": "Konekto-metodoj", + "METHOD_DEF": "Pluraj eblecoj disponeblas por konekti vin al monujo:<br/> - La konekto <b>per salumado (simpla aÅ sperta)</b> miksas vian pasvorton dank'al la sekreta identigilo, por limigi la provojn de <a href=\"https://fr.wikipedia.org/wiki/Attaque_par_force_brute\" target=\"_system\">kodrompado per kruda forto</a> (ekzemple per konataj vortoj.<br/> - La konekto <b>per publika Ålosilo</b> evitigas tajpi viajn identigilojn, kiuj estos petataj de vi, nur kiam venos la momento dum operacio ĉe la konto.<br/> - La konekto <b>per dosiero pri Ålosilaro</b> legas la Ålosilojn (publikan kaj privatan) de la konto, per dosiero, sen la bezono tajpi identigilojn. Pluraj strukturoj de dosiero eblas." + }, + "GLOSSARY": { + "SECTION": "Glosaro", + "PUBKEY_DEF": "Publika Ålosilo identigas monujon, kiu povas identigi membron aÅ rilati al anonima monujo. Ĉe Cesium la publika Ålosilo estas kalkulita (implicite) dank'al la sekreta identigilo kaj la pasvorto.<br/><a href=\"https://fr.wikipedia.org/wiki/Cryptographie_asym%C3%A9trique\" target=\"_system\">Scii pli pri kriptografio</a> per publika Ålosilo.", + "MEMBER": "Membro", + "MEMBER_DEF": "Membro estas homa persono fizika kaj vivanta, kiu deziras libere partopreni en la mona komunumo. Li/Åi kunproduktas universalan dividendon, laÅ periodo kaj sumo tiel difinitaj kiel en la <span class=\"text-italic\">reguloj de la mono</span>", + "CURRENCY_RULES": "Reguloj de la mono", + "CURRENCY_RULES_DEF": "La reguloj de la mono estas difinitaj definitive. Ili fiksas la funkciadon de la mono: la kalkulon de la universala dividendo, la nombron de necesaj atestaĵoj por esti membro, la maksimuman nombron da atestaĵoj, kiujn povas doni unu membro, ktp. <a href=\"#/app/currency\">Vidi la nuntempajn regulojn</a>.<br/>La nemodifo de la reguloj tra la tempo eblas per uzado de <span class=\"text-italic\">Blokĉeno</span>, kiu entenas kaj plenumas tiujn regulojn, kaj konstante kontrolas ties Äustan aplikadon.", + "BLOCKCHAIN": "Ĉeno de blokoj (<span class=\"text-italic\">Blokchain/Blokĉeno</span>)", + "BLOCKCHAIN_DEF": "La Blokĉeno estas malcentrigita sistemo, kiu, kaze de Duniter, servas por enteni kaj plenumi la <span class=\"text-italic\">regulojn de la mono</span>.<br/><a href=\"https://duniter.org/fr/comprendre/\" target=\"_system\">Scii pli pri Duniter</a> kaj la funkciado de ties blokĉeno.", + "UNIVERSAL_DIVIDEND_DEF": "La Universala Dividendo (UD) estas la kvanto de mono kunkreita de ĉiu membro, laÅ la periodo kaj kalkulo difinitaj en la <span class=\"text-italic\">reguloj de la mono</span>.<br/>Por ĉiu perioda dato, la membroj ricevas en sian konton la saman kvanton da nova mono.<br/><br/>La UD spertas regulan kreskon, por resti justa inter la membroj (nunaj kaj venontaj), kalkulitan depende de la meza vivespero, kiel estas demonstrite en la Teorio Relativa pri la Mono (TRM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Scii pli pri la TRM</a> kaj la liberaj monoj.", + "WOT": "Reto de Fido (RdF)", + "WOT_DEF": "La Reto de Fido konsistas el la tuto de la membroj de la mono, kaj el la atesto-ligoj, kiuj kunligas ilin.", + "DISTANCE_RULE": "Regulo pri distanco", + "DISTANCE_RULE_DEF": "La regulo pri distanco de la Reto de Fido difinas <b>maksimuman distancon nepran</b> inter petanto kaj minimuma nombro da referencaj membroj (aÅ centraj membroj). Tiu distanco estas kalkulita uzante la ligojn inter atestaĵoj." + }, + "TIP": { + "MENU_BTN_CURRENCY": "La menuo <b>{{'MENU.CURRENCY'|translate}}</b> ebligas konsulti la <b>regulojn de la mono</b> kaj ties staton.", + "CURRENCY_WOT": "La <b>nombro de membroj</b> montras la gravecon de la komunumo kaj ebligas <b>sekvi ties evoluon</b>.", + "CURRENCY_MASS": "Sekvu ĉi tie la <b>ĉioman kvanton da mono</b> ekzistanta kaj ties <b>mezan distribuon</b> por membro.<br/><br/>Tio ĉi ebligas taksi la <b>gravecon de iu sumo</b>, kompare kun tio, kion <b>posedas la aliuloj</b> en sia konto (mezume).", + "CURRENCY_UNIT_RELATIVE": "La unuo uzata (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) signifas, ke la sumoj en {{currency|capitalize}} estis dividitaj per la <b> Universala Dividendo</b> (UD).<br/><br/><small>Tiu relativa unuo estas <b>trafa</b>, ĉar stabila malgraÅ la kvanto de mono, kiu kreskas seninterrompe.</small>", + "CURRENCY_CHANGE_UNIT": "La kromaĵo <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> ebligas <b>ÅanÄi la unuon</b>, por vidigi la sumojn <b>rekte en {{currency|capitalize}}</b> (prefere ol en “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”).", + "CURRENCY_CHANGE_UNIT_TO_RELATIVE": "La kromaĵo <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> ebligas <b>ÅanÄi la unuon</b>, por vidigi la sumojn en “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”, tio estas rilate al la Universala Dividendo (la sumo kunproduktita de ĉiu membro).", + "CURRENCY_RULES": "La <b>reguloj</b> de la mono fiksas ties funkciadon <b>Äustan kaj antaÅvideblan</b>.<br/><br/>Vera DNA de la mono, ili igas sian monan kodon <b>legebla kaj travidebla</b>.", + "MENU_BTN_NETWORK": "La menuo <b>{{'MENU.NETWORK'|translate}}</b> ebligas konsulti la staton de la reto.", + "NETWORK_BLOCKCHAIN": "Ĉiuj operacioj pri la mono estas registritaj en granda konto-libro <b>publika kaj nefalsigebla</b>, ankaÅ nomata <b>blokĉeno</b> (<em>BlockChain</em> en la angla).", + "NETWORK_PEERS": "La <b>nodoj</b> videblaj ĉi tie rilatas al la <b>komputiloj, kiuj Äisdatigas kaj kontrolas</b> la blokĉenon.<br/><br/>Ju pli estas nodoj, des pli la mono havas administradon <b>malcentrigitan</b> kaj fidindan.", + "NETWORK_PEERS_BLOCK_NUMBER": "Tiu ĉi <b>numero</b> (verda) indikas la <b>lastan blokon validigitan</b> por tiu ĉi nodo (lasta paÄo skribita en la granda konto-libro).<br/><br/>La verda koloro indikas, ke tiu ĉi bloko estas validigita ankaÅ de <b>la plej multaj el la aliaj nodoj</b>.", + "NETWORK_PEERS_PARTICIPATE": "<b>Ĉiu membro</b>, ekipita per komputilo kun interreto, <b>povas partopreni aldonante nodon</b>. Sufiĉas <b>instali la programon Duniter</b> (libera kaj senpaga). <a href=\"{{installDocUrl}}\" target=\"_system\">Vidi la gvidilon pri instalado >></a>.", + "MENU_BTN_ACCOUNT": "La menuo <b>{{'ACCOUNT.TITLE'|translate}}</b> ebligas aliri la administradon de via konto.", + "MENU_BTN_ACCOUNT_MEMBER": "Konsultu ĉi tie la staton de via konto kaj la informojn pri viaj atestaĵoj.", + "WALLET_CERTIFICATIONS": "Alklaku ĉi tien por konsulti la detalon pri viaj atestaĵoj (ricevitaj kaj senditaj).", + "WALLET_RECEIVED_CERTIFICATIONS": "Alklaku ĉi tien por konsulti la detalon pri viaj <b>ricevitaj atestaĵoj</b>.", + "WALLET_GIVEN_CERTIFICATIONS": "Alklaku ĉi tien por konsulti la detalon pri viaj <b>senditaj atestaĵoj</b>.", + "WALLET_BALANCE": "La <b>saldo</b> de via konto afiÅiÄas tie ĉi.", + "WALLET_BALANCE_RELATIVE": "{{'HELP.TIP.WALLET_BALANCE'|translate}}<br/><br/>La uzata unuo (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) signifas, ke la sumo en {{currency|capitalize}} estis dividita per la <b>Universala Dividendo</b> (UD) kunkreita de ĉiu membro.<br/><br/>Nuntempe 1 UD valoras {{currentUD|formatInteger}} {{currency|capitalize}}j.", + "WALLET_BALANCE_CHANGE_UNIT": "Vi povos <b>ÅanÄi la unuon</b> afiÅitan por la sumoj en la <b><i class=\"icon ion-android-settings\"></i> {{'MENU.SETTINGS'|translate}}</b>.<br/><br/>Ekzemple por vidigi la sumojn <b>rekte en {{currency|capitalize}}</b>, prefere ol en relativa unuo.", + "WALLET_PUBKEY": "Jen la publika Ålosilo de via konto. Vi povas sciigi Äin al aliulo, por ke li identigu pli simple vian konton.", + "WALLET_SEND": "Efektivigi pagon per kelkaj klakoj.", + "WALLET_SEND_NO_MONEY": "Efektivigi pagon per kelkaj klakoj.<br/>(Via saldo ankoraÅ ne permesas tion)", + "WALLET_OPTIONS": "Tiu ĉi butono ebligas aliri la <b>agojn pri aliÄo</b> kaj sekureco.<br/><br/>Ne forgesu okulumi al Äi!", + "WALLET_RECEIVED_CERTS": "AfiÅiÄos ĉi tie la listo de la personoj, kiuj atestis vin.", + "WALLET_CERTIFY": "La butono <b>{{'WOT.BTN_SELECT_AND_CERTIFY'|translate}}</b> ebligas elekti identecon kaj atesti Äin.<br/><br/>Nur uzantoj <b>jam membroj</b> povas atesti aliajn.", + "WALLET_CERT_STOCK": "Via stoko da atestaĵoj (senditaj) estas limigita je <b>{{sigStock}} atestaĵoj</b>.<br/><br/>Tiu stoko plu evoluas laÅ la tempo, samtempe kiam la atestaĵoj malvalidiÄas.", + "MENU_BTN_TX_MEMBER": "La menuo <b>{{'MENU.TRANSACTIONS'|translate}}</b> ebligas konsulti vian konton, la liston de viaj spezoj, kaj sendi pagon.", + "MENU_BTN_TX": "Konsultu ĉi tie <b>la liston de viaj spezoj</b> kaj efektivigu novajn operaciojn.", + "MENU_BTN_WOT": "La menuo <b>{{'MENU.WOT'|translate}}</b> ebligas traserĉi inter la <b>uzantoj</b> de la mono (membroj aÅ ne).", + "WOT_SEARCH_TEXT_XS": "Por traserĉi en la kontaro, tajpu la <b>unuajn literojn de pseÅdonimo</b> (aÅ de publika Ålosilo).<br/><br/>La serĉado ekos aÅtomate.", + "WOT_SEARCH_TEXT": "Por traserĉi en la kontaro, tajpu la <b>unuajn literojn de de pseÅdonimo</b> (aÅ de publika Ålosilo). <br/><br/>Premu poste sur la klavon <b>Enigi</b> por ekigi la serĉadon.", + "WOT_SEARCH_RESULT": "Vidigu la detalan slipon simple <b>alklakante</b> linion.", + "WOT_VIEW_CERTIFICATIONS": "La linio <b>{{'ACCOUNT.CERTIFICATION_COUNT'|translate}}</b> montras kiom da membroj validigis tiun ĉi identecon.<br/><br/>Tiuj atestaĵoj pruvas, ke la konto apartenas al <b>persono homa kaj vivanta</b>, havanta <b>neniun alian membro-konton</b>.", + "WOT_VIEW_CERTIFICATIONS_COUNT": "Necesas almenaÅ <b>{{sigQty}} atestaĵoj</b> por fariÄi membro kaj ricevi la <b>Universalan Dividendon</b>.", + "WOT_VIEW_CERTIFICATIONS_CLICK": "Alklaki ĉi tien ebligas malfermi <b>la liston de ĉiuj atestaĵoj</b> de la identeco (ricevitaj kaj senditaj).", + "WOT_VIEW_CERTIFY": "La butono <b>{{'WOT.BTN_CERTIFY'|translate}}</b> ebligas aldoni vian atestaĵon al tiu identeco.", + "CERTIFY_RULES": "<b>Atenton:</b> Atestu nur <b>personojn fizikajn vivantajn</b>, posedantajn neniun alian membro-konton.<br/><br/>La sekureco de la mono dependas de ĉies atentego!", + "MENU_BTN_SETTINGS": "La <b>{{'MENU.SETTINGS'|translate}}</b> ebligos al vi agordi la programon.", + "HEADER_BAR_BTN_PROFILE": "Alklaku ĉi tien por aliri vian <b>uzanto-profilon.</b>", + "SETTINGS_CHANGE_UNIT": "Vi povos <b>ÅanÄi la afiÅ-unuon</b> de la sumoj alklakante ĉi-supren.<br/><br/>- Malaktivigu la kromaĵon por afiÅi sumojn en {{currency|capitalize}}.<br/>- Aktivigu la kromaĵon por relativa afiÅado en {{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub> (ĉiuj sumoj estos <b>dividitaj</b> per la Universala Dividendo aktuala).", + "END_LOGIN": "Tiu ĉi gvidata vizito <b>finiÄis</b>!<br/><br/>Bonan daÅrigon al vi, en la nova mondo de la<b>libera ekonomio</b>!", + "END_NOT_LOGIN": "Tiu ĉi gvidata vizito <b>finiÄis</b>!<br/><br/>Se vi deziras partopreni en la mono {{currency|capitalize}}, sufiĉos al vi alklaki <b>{{'LOGIN.CREATE_ACCOUNT'|translate}}</b> ĉi-sube." + } + }, + "API" :{ + "COMMON": { + "LINK_DOC": "Dokumentaro API", + "LINK_DOC_HELP": "Dokumentaro por la programistoj", + "LINK_STANDARD_APP": "Klasika versio", + "LINK_STANDARD_APP_HELP": "Malfermi la klasikan version de {{'COMMON.APP_NAME'|translate}}", + "CONNECTION_ERROR": "Nodo <b>{{server}}</b> neatingebla aÅ adreso nevalida.<br/><br/>Kontrolu vian interretan konekton, aÅ kontaktu la administranton de la retejo</a>." + }, + "HOME": { + "TITLE": "Dokumentaro API {{'COMMON.APP_NAME'|translate}}", + "MESSAGE": "Bonvenon en la <b>dokumentaro de la API</b> {{'COMMON.APP_NAME'|translate}}.<br/>Konektu viajn retejojn al <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> tre simple!", + "MESSAGE_SHORT": "Konektu viajn retejojn al <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> tre simple!", + "DOC_HEADER": "Servoj disponeblaj:" + }, + "TRANSFER": { + "TITLE": "{{'COMMON.APP_NAME'|translate}} - Reta pago", + "TITLE_SHORT": "Reta pago", + "SUMMARY": "Resumo de la pago:", + "AMOUNT": "Sumo:", + "AMOUNTS_HELP": "Bonvolu elekti la sumon:", + "NAME": "Nomo:", + "PUBKEY": "Publika Ålosilo de la ricevonto:", + "COMMENT": "Referenco de la spezo:", + "NODE": "Adreso de la nodo:", + "DEMO": { + "SALT": "demo", + "PASSWORD": "demo", + "PUBKEY": "3G28bL6deXQBYpPBpLFuECo46d3kfYMJwst7uhdVBnD1", + "HELP": "<b>Demonstra moduso</b>: Neniu pago reale estos sendita dum tiu simulado.<br/>Bonvolu uzi la identigilojn: <b>{{'API.TRANSFER.DEMO.SALT'|translate}} / {{'API.TRANSFER.DEMO.PASSWORD'|translate}}</b>", + "BAD_CREDENTIALS": "Kontrolu vian tajpaĵon.<br/>En demonstra moduso, la identigiloj estas: {{'API.TRANSFER.DEMO.SALT'|translate}} / {{'API.TRANSFER.DEMO.PASSWORD'|translate}}" + }, + "INFO": { + "SUCCESS_REDIRECTING_WITH_NAME": "Pago sendita.<br/>RedirektiÄo al <b>{{name}}</b>...", + "SUCCESS_REDIRECTING": "Pago sendita.<br/>RedirektiÄo al la retejo de la vendanto...", + "CANCEL_REDIRECTING_WITH_NAME": "Pago nuligita.<br/>RedirektiÄo al <b>{{name}}</b>...", + "CANCEL_REDIRECTING": "Pago nuligita.<br/>RedirektiÄo al la retejo de la vendanto..." + }, + "ERROR": { + "TRANSFER_FAILED": "Pago malsukcesa" + } + }, + "DOC": { + "DESCRIPTION_DIVIDER": "Priskribo", + "URL_DIVIDER": "Adreso alvokita", + "PARAMETERS_DIVIDER": "Parametroj", + "AVAILABLE_PARAMETERS": "Jen la listo de la eblaj parametroj:", + "DEMO_DIVIDER": "Testi", + "DEMO_HELP": "Por testi tiun servon, alklaku la butonon ĉi-apude. La rezulto afiÅiÄos sube.", + "DEMO_RESULT": "Rezulto sendita de la alvoko:", + "DEMO_RESULT_PEER": "Adreso de la uzata nodo:", + "DEMO_SUCCEED": "<i class=\"icon ion-checkmark\"></i> Sukceso!", + "DEMO_CANCELLED": "<i class=\"icon ion-close\"></i> Nuligita de la uzanto", + "INTEGRATE_DIVIDER": "Integri", + "INTEGRATE_CODE": "Kodo:", + "INTEGRATE_RESULT": "AntaÅvidigo de la rezulto:", + "INTEGRATE_PARAMETERS": "Parametroj", + "TRANSFER": { + "TITLE": "Pagoj", + "DESCRIPTION": "De retejo (ekz.: ret-vendado) vi povas komisii la pagon en libera mono al Cesium API. Por tio, sufiĉas al vi ekigi la malfermon de paÄo ĉe la sekvanta adreso:", + "PARAM_PUBKEY": "Publika Ålosilo de la ricevonto", + "PARAM_PUBKEY_HELP": "Publika Ålosilo de la ricevonto (devige)", + "PARAM_AMOUNT": "Sumo", + "PARAM_AMOUNT_HELP": "Sumo de la spezo (devige). Pluraj valoroj permesataj, uzante apartigilon (punkto-komo, vertikala streko aÅ spaco).", + "PARAM_COMMENT": "Referenco (aÅ komento)", + "PARAM_COMMENT_HELP": "Referenco aÅ komento. Tio ekzemple ebligos al vi identigi la pagon en la blokĉeno.", + "PARAM_NAME": "Nomo (de la ricevonto aÅ de la retejo)", + "PARAM_NAME_HELP": "La nomo de la ricevonto, aÅ de la retejo alvokanta. Tio povas estis legebla nomo (\"Mia retejo\"), aÅ alie pseÅdo-retadreso (\"MiaRetejo.com\").", + "PARAM_REDIRECT_URL": "Retadreso por redirektiÄo", + "PARAM_REDIRECT_URL_HELP": "Retadreso (URL) por redirektiÄo, alvokita kiam la pago estis sendita. Äœi povas enteni la sekvantajn signojn, kiuj estos anstataÅigitaj per la valoroj de la spezo: \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\", \"{pubkey}\" kaj \"{node}\".", + "PARAM_CANCEL_URL": "Retadreso por nuligo", + "PARAM_CANCEL_URL_HELP": "Retadreso (URL) kaze de nuligo de la pago, fare de la uzanto. Äœi povas enteni la sekvantajn signojn, kiuj estos anstataÅigitaj lastmomente: \"{comment}\", \"{amount}\" kaj {pubkey}.", + "PARAM_PREFERRED_NODE": "Adreso de la preferata nodo", + "PARAM_PREFERRED_NODE_HELP": "Adreso (URL) de la nodo Duniter preferinde uzota (\"g1.domaine.com:443\" aÅ \"https://g1.domaine.com\").", + "EXAMPLES_HELP": "Jen ekzemploj pri integrado:", + "EXAMPLE_BUTTON": "Butono HTML", + "EXAMPLE_BUTTON_DEFAULT_TEXT": "Pagi en {{currency|currencySymbol}}", + "EXAMPLE_BUTTON_DEFAULT_STYLE": "Personigita stilo", + "EXAMPLE_BUTTON_TEXT_HELP": "Buton-teksto", + "EXAMPLE_BUTTON_BG_COLOR": "Fon-koloro", + "EXAMPLE_BUTTON_BG_COLOR_HELP": "Ekzemplo: #fbc14c, nigra, helgriza, rgb(180,180,180)", + "EXAMPLE_BUTTON_FONT_COLOR": "Teksto-koloro", + "EXAMPLE_BUTTON_FONT_COLOR_HELP": "Ekzemplo: nigra, oranÄa, rgb(180,180,180)", + "EXAMPLE_BUTTON_TEXT_ICON": "Ikono", + "EXAMPLE_BUTTON_TEXT_WIDTH": "LarÄeco", + "EXAMPLE_BUTTON_TEXT_WIDTH_HELP": "Ekzemplo: 200px, 50%", + "EXAMPLE_BUTTON_ICON_NONE": "Neniu", + "EXAMPLE_BUTTON_ICON_DUNITER": "Insigno Duniter", + "EXAMPLE_BUTTON_ICON_CESIUM": "Insigno Cesium", + "EXAMPLE_BUTTON_ICON_G1_COLOR": "Insigno Äž1", + "EXAMPLE_BUTTON_ICON_G1_BLACK": "Insigno Äž1 (nigra)" + } + } + } +} +); + $translateProvider.translations("es-ES", { "COMMON": { "APP_NAME": "Cesium", @@ -1780,9 +3011,10 @@ $translateProvider.translations("es-ES", { "BTN_YES_CONTINUE": "SÃ, continuar", "BTN_SHOW": "Ver", "BTN_SHOW_PUBKEY": "Ver la llave", - "BTN_RELATIVE_UNIT": "¿Visualizar en unidad relativa?", + "BTN_RELATIVE_UNIT": "¿Mostrar las importes en DU?", "BTN_BACK": "Anterior", "BTN_NEXT": "Siguiente", + "BTN_IMPORT": "Importar", "BTN_CANCEL": "Cancelar", "BTN_CLOSE": "Cerrar", "BTN_LATER": "Más tarde", @@ -1811,6 +3043,7 @@ $translateProvider.translations("es-ES", { "NO_ACCOUNT_QUESTION": "¿TodavÃa no es miembro? ¡Crear una cuenta!", "SEARCH_NO_RESULT": "Ningún resultado encontrado", "LOADING": "Espere por favor...", + "LOADING_WAIT": "Espere por favor...<br/><small>(Esperando disponibilidad de nodo)</small>", "SEARCHING": "Búsqueda en proceso...", "FROM": "De", "TO": "A", @@ -1840,6 +3073,12 @@ $translateProvider.translations("es-ES", { "SHARE_ON_FACEBOOK": "Compartir en Facebook", "SHARE_ON_DIASPORA": "Compartir en Diaspora*", "SHARE_ON_GOOGLEPLUS": "Compartir en Google+" + }, + "FILE": { + "DATE" : "Fecha:", + "TYPE" : "Tipo:", + "SIZE": "Tamaño:", + "VALIDATING": "Validación en progreso..." } }, "SYSTEM": { @@ -1852,6 +3091,7 @@ $translateProvider.translations("es-ES", { "WOT": "Directorio", "CURRENCY": "Moneda", "ACCOUNT": "Mi cuenta", + "WALLETS": "Mis monederos", "TRANSFER": "Transferencia", "SCAN": "Escáner", "SETTINGS": "Configuraciones", @@ -1860,7 +3100,7 @@ $translateProvider.translations("es-ES", { }, "ABOUT": { "TITLE": "A propósito ", - "LICENSE": "Aplicación <b>libre</b> (licencia GNU GPLv3).", + "LICENSE": "Aplicación <b>libre</b> (licencia GNU AGPLv3).", "LATEST_RELEASE": "Hay una <b>versión más nueva</b> de {{'COMMON.APP_NAME' | translate}} (<b>v{{version}}</b>)", "PLEASE_UPDATE": "Por favor actualice {{'COMMON.APP_NAME' | translate}} (última versión: <b>v{{version}}</b>)", "CODE": "Código fuente:", @@ -1883,18 +3123,25 @@ $translateProvider.translations("es-ES", { }, "SETTINGS": { "TITLE": "Configuración", + "DISPLAY_DIVIDER": "Visualización", + "STORAGE_DIVIDER": "Almacenamiento", "NETWORK_SETTINGS": "Red", "PEER": "Dirección del nodo Duniter", "PEER_CHANGED_TEMPORARY": "Dirección utilizada temporalmente", "USE_LOCAL_STORAGE": "Activar el almacenamiento local", "USE_LOCAL_STORAGE_HELP": "Permitir el ahorro de almacenamiento local", + "WALLETS_SETTINGS": "Mis monederos", + "USE_WALLETS_ENCRYPTION": "¿Asegurar la lista?", "ENABLE_HELPTIP": "Activar las ayudas contextuales", "ENABLE_UI_EFFECTS": "Activar los efectos visuales", "HISTORY_SETTINGS": "Operaciones de cuentas", "DISPLAY_UD_HISTORY": "¿Publicar los dividendos producidos?", + "TX_HISTORY_AUTO_REFRESH": "Activar actualización automática?", + "TX_HISTORY_AUTO_REFRESH_HELP": "Actualice el saldo y las operaciones automáticamente, en cada nuevo bloque.", "AUTHENTICATION_SETTINGS": "Autenticación", "KEEP_AUTH": "Caducidad de la autenticación", - "KEEP_AUTH_HELP": "Definir cuándo limpiar la memoria de autenticación", + "KEEP_AUTH_SHORT": "Caducidad", + "KEEP_AUTH_HELP": "Definir cuándo limpiar la memoria de autenticación.", "KEEP_AUTH_OPTION": { "NEVER": "Después de cada operación", "SECONDS": "Después de {{value}} segundos de inactividad", @@ -1903,6 +3150,7 @@ $translateProvider.translations("es-ES", { "HOUR": "Después de {{value}}h de inactividad", "ALWAYS": "Al finalizar la sesión" }, + "KEYRING_FILE": "Archivo de llavero", "REMEMBER_ME": "Recordarme", "REMEMBER_ME_HELP": "Permite mantenerse siempre conectado (no recomendado), conservando localmente la llave pública.", "PLUGINS_SETTINGS": "Extensiones", @@ -1973,7 +3221,7 @@ $translateProvider.translations("es-ES", { "TAB_WOT": "Red de confianza", "TAB_NETWORK": "Red", "TAB_BLOCKS": "Bloques", - "CURRENCY_SHORT_DESCRIPTION": "{{currency|capitalizar}} es una <b>moneda libre</b>, originada el {{firstBlockTime|formatFromNow}}. Ella cuenta actualmente <b>{{N}} miembros</b>, que producen y recibir un <a ng-click=\"showHelpModal('ud')\">Dividendo universal</a> (DU), cada {{dt|formatPeriod}}.", + "CURRENCY_SHORT_DESCRIPTION": "{{currency|abbreviate}} es una <b>moneda libre</b>, originada el {{firstBlockTime|formatFromNow}}. Ella cuenta actualmente <b>{{N}} miembros</b>, que producen y recibir un <a ng-click=\"showHelpModal('ud')\">Dividendo universal</a> (DU), cada {{dt|formatPeriod}}.", "NETWORK_RULES_DIVIDER": "Reglas de la red", "CURRENCY_NAME": "Nombre de la moneda", "MEMBERS": "Cantidad de miembros", @@ -2026,6 +3274,7 @@ $translateProvider.translations("es-ES", { "WARN_PRE_RELEASE": "prelanzamiento (última versión estable: <b>{{version}}</b>)", "WARN_NEW_RELEASE": "Versión <b>{{version}}</b> disponible", "WS2PID": "ID:", + "PRIVATE_ACCESS": "Acceso privado", "POW_PREFIX": "Prefijo de la prueba de trabajo:", "ENDPOINTS": { "BMAS": "Interfaz segura (SSL)", @@ -2042,20 +3291,23 @@ $translateProvider.translations("es-ES", { "PEERS": "Nodos", "SIGNED_ON_BLOCK": "Firmado sobre el bloque", "MIRROR": "espejo", - "MIRRORS": "Nodos espejo", + "MIRRORS": "Espejo", + "MIRROR_PEERS": "Nodos espejo", "PEER_LIST": "Lista de nodos", - "MEMBERS": "Nodos miembro", + "MEMBERS": "Miembro", + "MEMBER_PEERS": "Nodos miembro", "ALL_PEERS": "Todos los nodos", "DIFFICULTY": "Dificultad", "API": "API", "CURRENT_BLOCK": "Bloque #", "POPOVER_FILTER_TITLE": "Filtro", - "OFFLINE": "Nodos fuera de lÃnea", + "OFFLINE": "Fuera de lÃnea", + "OFFLINE_PEERS": "Nodos fuera de lÃnea", "BTN_SHOW_PEER": "Ver nodo", "VIEW": { "TITLE": "Nodo", "OWNER": "Propiedad de", - "SHOW_RAW_PEERING": "Ver la tarjeta de red", + "SHOW_RAW_PEERING": "Ver la mapa de red", "SHOW_RAW_CURRENT_BLOCK": "Ver el último bloque (formato bruto)", "LAST_BLOCKS": "Bloques recientes", "KNOWN_PEERS": "Nodos conocidos:", @@ -2100,7 +3352,7 @@ $translateProvider.translations("es-ES", { "PENDING": "Inscripciones en espera:", "PENDING_COUNT": "{{count}} inscripciones en espera", "REGISTERED": "Inscrito {{sigDate | formatFromNow}}", - "MEMBER_FROM": "Miembro desde {{memberDate|formatFromNowShort}}", + "MEMBER_FROM": "Miembro desde {{memberDate|medianFromNowShort}}", "BTN_NEWCOMERS": "Nuevos miembros", "BTN_PENDING": "Inscripciones en espera", "SHOW_MORE": "Mostrar más", @@ -2139,38 +3391,74 @@ $translateProvider.translations("es-ES", { }, "LOGIN": { "TITLE": "<i class=\"icon ion-locked\"></i> Conexión", + "SCRYPT_FORM_HELP": "Ingrese sus credenciales.<br>Recuerde verificar que la clave pública es su cuenta.", + "PUBKEY_FORM_HELP": "Por favor ingrese una clave de cuenta pública:", + "FILE_FORM_HELP": "Elija el archivo de llavero para usar:", + "SCAN_FORM_HELP": "Escanee el código QR de la monedero.", "SALT": "Identificador secreto", "SALT_HELP": "Identificador secreto", "SHOW_SALT": "¿Visualizar el identificador secreto?", "PASSWORD": "Frase secreta", "PASSWORD_HELP": "Frase secreta", - "PUBKEY_HELP": "Ejemplo: «AbsxSY4qoZRzyV2irfep1V9xw1EMNyKJw2TkuVD4N1mv»", + "PUBKEY_HELP": "llave pública", "NO_ACCOUNT_QUESTION": "¿Aún no tiene cuenta?", + "HAVE_ACCOUNT_QUESTION": "¿Ya tienes una cuenta?", "CREATE_ACCOUNT": "Crear una cuenta", + "CREATE_FREE_ACCOUNT": "Crear una cuenta gratis", "FORGOTTEN_ID": "¿Olvidó su frase secreta?", + "ASSOCIATED_PUBKEY": "Clave pública del llavero:", + "BTN_METHODS": "Otros métodos", + "BTN_METHODS_DOTS": "Método de cambio...", + "METHOD_POPOVER_TITLE": "Métodos", + "MEMORIZE_AUTH_FILE": "Recuerda este llavero al momento de la sesión de navegación", + "SCRYPT_PARAMETERS": "Configuraciones (Scrypt) :", "AUTO_LOGOUT": { "TITLE": "Información", "MESSAGE": "<i class=\"ion-android-time\"></i> Se ha <b>desconectado</b> de forma automática, después de un periodo de inactividad prolongada.", "BTN_RELOGIN": "Volver a conectarme", "IDLE_WARNING": "Se desconectará en... {{countdown}}" + }, + "METHOD": { + "SCRYPT_DEFAULT": "Identificación predeterminada", + "SCRYPT_ADVANCED": "Sallaje avanzado", + "FILE": "Archivo llavero", + "PUBKEY": "Solo clave pública", + "SCAN": "Escanear un código QR" + }, + "SCRYPT": { + "SIMPLE": "Ligero", + "DEFAULT": "Predeterminado", + "SECURE": "Seguro", + "HARDEST": "El más seguro", + "EXTREME": "Extremo", + "USER": "Personalizado", + "N": "N (Loop):", + "r": "r (RAM):", + "p": "p (CPU):" + }, + "FILE": { + "HELP": "Formato de archivo esperado: <b>.yml</b> o <b>.dunikey</b> (tipo PubSec, WIF o EWIF)." } }, "AUTH": { "TITLE": "<i class=\"icon ion-locked\"></i> AAutenticación", - "METHOD_LABEL": "Método de autenticación", "BTN_AUTH": "Autenticar", - "SCRYPT_FORM_HELP": "Por favor, autentÃquese:" + "GENERAL_HELP": "Por favor, autentÃquese:", + "EXPECTED_UID_HELP": "Por favor inicie sesión en la cuenta de <i class=\"ion-person\"></i> {{uid}}:", + "EXPECTED_PUBKEY_HELP": "Por favor, autentifÃquese en la monedero <i class=\"ion-key\"></i> {{pubkey|formatPubkey}} :", + "SCAN_FORM_HELP": "Escanee el código QR de la <b>clave privada</b> de la monedero." }, "ACCOUNT": { "TITLE": "Mi cuenta", "BALANCE": "Saldo", - "LAST_TX": "última transacción", + "LAST_TX": "última validadas transacción", "BALANCE_ACCOUNT": "Saldo de la cuenta", "NO_TX": "Ninguna transacción", "SHOW_MORE_TX": "Mostrar más", "SHOW_ALL_TX": "Mostrar todo", - "TX_FROM_DATE": "(lÃmite actual a {{fromTime|formatFromNowShort}})", + "TX_FROM_DATE": "(lÃmite actual a {{fromTime|medianFromNowShort}})", "PENDING_TX": "Transacciones en proceso de se procesadas", + "VALIDATING_TX": "Transacciones validadas", "ERROR_TX": "Transacciones no ejecutadas", "ERROR_TX_SENT": "Transacciones ejecutadas fallidas", "PENDING_TX_RECEIVED": "Tansacciones en espera de recepción", @@ -2186,11 +3474,10 @@ $translateProvider.translations("es-ES", { "SIG_STOCK": "Certificaciones emitidas", "BTN_RECEIVE_MONEY": "Recibir", "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Cambiar a otra identidad...", - "BTN_MEMBERSHIP_IN_DOTS": "Volverse miembro...", + "BTN_FIX_MEMBERSHIP": "Volver a enviar la adhesión...", "BTN_MEMBERSHIP_RENEW": "Renovar la adhesión", "BTN_MEMBERSHIP_RENEW_DOTS": "Renovar la adhesión...", "BTN_MEMBERSHIP_OUT_DOTS": "Cancelar la adhesión...", - "BTN_SEND_IDENTITY_DOTS": "Publicar su identidad...", "BTN_SECURITY_DOTS": "Cuenta y securidad...", "BTN_SHOW_DETAILS": "Publicar la información técnica", "LOCKED_OUTPUTS_POPOVER": { @@ -2213,7 +3500,7 @@ $translateProvider.translations("es-ES", { "MEMBER_ACCOUNT_HELP": "Si aún no está inscrito como un individuo (Solamente una cuenta posible por individuo).", "WALLET_ACCOUNT": "Simple monedero", "WALLET_ACCOUNT_TITLE": "Crear una cuenta simple", - "WALLET_ACCOUNT_HELP": "Cartera simple para todos los otros casos, por ejemplo si necesita una cuenta suplementaria.<br/>El Dividendo Universal no será producido para esta cuenta.", + "WALLET_ACCOUNT_HELP": "Monedero simple para todos los otros casos, por ejemplo si necesita una cuenta suplementaria.<br/>El Dividendo Universal no será producido para esta cuenta.", "SALT_WARNING": "Elija su identificador secreto.<br/>Se solicitará cada vez que se conectará con esta cuenta.<br/><br/><b>Retenga bien este identificador secreto</b>.<br/>¡En caso de pérdida, nadie podrá acceder a su cuenta!", "PASSWORD_WARNING": "Elija su frase secreta.<br/>Se solicitará cada vez que se conectará con esta cuenta.<br/><br/><b>Retenga bien esta frase secreta</b>.<br/>¡En caso de pérdida, nadie podrá acceder su cuenta!", "PSEUDO_WARNING": "Elija un seudónimo.<br/>Sirve para que los otros miembros puedan encontrarlo más fácilmente.<br/><br/>No debe contener <b>ni espacios ni caracteres acentuados</b>.<div class='hidden-xs'><br/>Ejemplo: <span class='gray'>SophieDupond, MarcelChemin, etc.</span>", @@ -2243,6 +3530,24 @@ $translateProvider.translations("es-ES", { "TITLE": "Selección de identidad", "HELP": "Se han enviado varias <b>identidades diferentes</b> para la clave pública <span class=\"gray\"><i class=\"ion-key\"></i>{{pubkey | formatPubkey}}</span>.<br/>Por favor, selecciona la carpeta para usar:" }, + "SELECT_WALLET_MODAL": { + "TITLE": "Selección de monedero" + }, + "WALLET_LIST": { + "TITLE": "Mis monederos", + "BTN_NEW": "Añadir un monedero", + "BTN_DOWNLOAD": "Descargue la lista", + "BTN_IMPORT_FILE_DOTS": "Importar desde un archivo...", + "NO_WALLET": "Sin monedero secundaria", + "BTN_DELETE": "Eliminar una monedero secundaria...", + "BTN_RENAME": "Renombrar el monedero", + "EXPORT_FILENAME": "monederos-{{pubkey|formatPubkey}}-{{currency}}.csv", + "EDIT_POPOVER": { + "TITLE": "Renombrar el monedero", + "HELP": "Completa el nuevo nombre", + "NAME_HELP": "Nombre de la monedero" + } + }, "SECURITY": { "ADD_QUESTION": "Añadir una pregunta personalizada", "BTN_CLEAN": "Limpiar", @@ -2299,15 +3604,20 @@ $translateProvider.translations("es-ES", { "COMMENT_HELP": "Comentario", "BTN_SEND": "Enviar", "BTN_ADD_COMMENT": "Añadir un comentario", + "REST": "Resto de cuenta", + "REST_TO": "a", "WARN_COMMENT_IS_PUBLIC": "Tenga en cuenta que los <b>comentarios son públicos</b> (sin encriptar).", "MODAL": { "TITLE": "Transferencia" } }, "ERROR": { + "UNKNOWN_URI_FORMAT": "Formato URI desconocido", + "PUBKEY_INVALID_CHECKSUM": "Clave pública no válida (suma de comprobación incorrecta).", "POPUP_TITLE": "Error", "UNKNOWN_ERROR": "Error desconocido", "CRYPTO_UNKNOWN_ERROR": "Su navegador parece incompatible con las funcionalidades de cryptografÃa.", + "DOWNLOAD_KEYFILE_FAILED": "Error al generar el archivo de llavero.", "EQUALS_TO_PSEUDO": "Debe ser diferente del seudónimo.", "EQUALS_TO_SALT": "Debe ser diferente del identificador secreto.", "FIELD_REQUIRED": "Campo obligatorio.", @@ -2356,8 +3666,10 @@ $translateProvider.translations("es-ES", { "INVALID_NODE_SUMMARY": "Nodo ilocalizable o dirección inválida.", "INVALID_USER_ID": "El seudónimo no debe contener ni espacios ni caracteres especiales o acentuado.", "INVALID_COMMENT": "El campo 'referencia’ no debe contener carácteres acentuados.", - "INVALID_PUBKEY": "La llave pública no tiene el formato esperado.", - "IDENTITY_REVOKED": "Esta identidad <b>fue revocada {{revocationTime|formatFromNow}}</b> ({{revocationTime|formatDate}}). No puede estar miembro.", + "INVALID_PUBKEY": "La clave pública no tiene el formato esperado.", + "INVALID_PUBKEY_CHECKSUM": "Suma de comprobación inválida.", + "IDENTITY_REVOKED": "Esta identidad <b>fue revocada</b>. No puede estar miembro.", + "IDENTITY_REVOKED_WITH_TIME": "Esta identidad <b>fue revocada {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). No puede estar miembro.", "IDENTITY_PENDING_REVOCATION": "La <b>revocación de esta identidad</b> fue solicitado y esta en espera de tratamiento. Por lo que, la certificación es desactivada.", "IDENTITY_INVALID_BLOCK_HASH": "Esta solicitud de adhesión no es valida (porque denomina un bloque los nodos de la red han anulado): esta persona debe renovelar su solicitud de adhesión <b>antes que</b> estar certificada.", "IDENTITY_EXPIRED": "La publicación de esta identidad ha caducada: esta persona debe realizar una nueva solicitud de adhesión <b>antes que</b> estar certificada.", @@ -2394,7 +3706,9 @@ $translateProvider.translations("es-ES", { "EXISTING_ACCOUNT": "Su frase secreta corresponde a una cuenta existente, la <a ng-click=\"showHelpModal('pubkey')\">clave pública</a> es:", "EXISTING_ACCOUNT_REQUEST": "Por favor, cambie su frase secreta para que coincida con una cuenta sin usar.", "GET_LICENSE_FILE_FAILED": "Error al obtener el archivo de licencia", - "CHECK_NETWORK_CONNECTION": "Ningún nodo parece alcanzable.<br/><br/><b>Compruebe la conexión a Internet</b>." + "CHECK_NETWORK_CONNECTION": "Ningún nodo parece alcanzable.<br/><br/><b>Compruebe la conexión a Internet</b>.", + "INVALID_FILE_FORMAT": "Formato de archivo inválido.", + "SAME_TX_RECIPIENT": "El destinatario debe ser diferente del emisor." }, "INFO": { "POPUP_TITLE": "Información", @@ -2405,6 +3719,8 @@ $translateProvider.translations("es-ES", { "MEMBERSHIP_OUT_SENT": "Anulación enviada", "NOT_NEED_MEMBERSHIP": "Ya es miembro.", "IDENTITY_WILL_MISSING_CERTIFICATIONS": "Esta identidad pronto va a necesitar certificaciones (al menos {{willNeedCertificationCount}}).", + "IDENTITY_NEED_MEMBERSHIP": "Esta identidad no envió una solicitud de membresÃa. Ella tendrá que hacerlo si desea hacerse miembro.", + "HAS_ALTERNATIVE_IDENTITIES": "Hay <b>identidades múltiples</b> adjuntas a esta clave pública. <b>Antes de cualquier certificación</b>, <a ng-click=\"doQuickFix('showSelectIdentities')\">verifique otras identidades</a> para elegir la correcta o comunÃquese con el propietario de la cuenta.", "REVOCATION_SENT": "Revocación enviada", "REVOCATION_SENT_WAITING_PROCESS": "La <b>revocación de esta identidad</b> fue solicitada y está en espera de ser procesada.", "FEATURES_NOT_IMPLEMENTED": "Esta funcionalidad todavÃa está en proceso de desarrollo.<br/><br/>¿Por qué no <b>contribuir a Cesium</b>, para obtenerla más rápido? ;)", @@ -2416,12 +3732,14 @@ $translateProvider.translations("es-ES", { "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Advertencia de seguridad</b>", "CERTIFY_RULES_TITLE_UID": "Certificar {{uid}}", "CERTIFY_RULES": "<b class=\"assertive\">NO CERTIFICAR</b> una cuenta si piense que :<br/><br/><ul><li>1.) no corresponde a una persona <b>fÃsica y viviente</b>.<li>2.) su propietario <b>posee una otra cuenta</b> ya certificada.<li>3.) su propietario viola (voluntariamente o no) la regla 1 o 2 (por ejemplo certificando cuentas falsas o duplicadas).</ul><br/><b>¿Está usted seguro</b> sin embargo querer certificar esta identidad?", "TRANSFER": "<b>Recapitulativo de la transferencia</b>:<br/><br/><ul><li> - De: {{from}}</li><li> - A: <b>{{to}}</b></li><li> - Importe: <b>{{amount}} {{unit}}</b></li><li> - Comentario: <i>{{comment}}</i></li></ul><br/><b>¿Está usted seguro de querer realizar esta transferencia?</b>", + "TRANSFER_ALL": "<b>Recapitulativo de la transferencia</b>:<br/><br/><ul><li> - De: {{from}}</li><li> - A: <b>{{to}}</b></li><li> - Importe: <b>{{amount}} {{unit}}</b></li><li> - Comentario: <i>{{comment}}</i></li><br/><li> - Resto: <b>{{restAmount}} {{unit}}</b> para <b>{{restTo}}</b></li></ul><br/><b>¿Está usted seguro de querer realizar esta transferencia?</b>", "MEMBERSHIP_OUT": "Esta operación es <b>irreversible</b>.<br/></br/>¿Está usted seguro querer <b>anular su cuenta miembro</b>?", "MEMBERSHIP_OUT_2": "¡Esta operación es <b>irreversible</b>!<br/><br/>¿Está usted seguro querer <b>anular su adhesión</b> como miembro?", "LOGIN_UNUSED_WALLET_TITLE": "¿Error de introducción de datos?", "LOGIN_UNUSED_WALLET": "Está usted conectado a une cuenta que parece <b>inactiva</b>.<br/><br/>Si esta cuenta no corresponde a la suya, se trata probablemente de un <b>error al introducir los datos</b> de sus identificadores de conexión.<br/></br/><b>¿Quiere usted sin embargo continuar con esta cuenta?</b>", "FIX_IDENTITY": "El seudónimo <b>{{uid}}</b> va a ser publicado de nuevo, en reemplazo del antiguo que caducó.<br/></br/><b>¿Está usted seguro</b> de querer continuar?", "FIX_MEMBERSHIP": "Su solicitud de adhesión como miembro va a ser enviada de nuevo.<br/></br/><b>¿Está usted seguro</b>de querer continuar?", + "MEMBERSHIP": "Se enviará su solicitud de membresÃa como miembro.<br/></br/><b>¿Está usted seguro</b>de querer continuar?", "RENEW_MEMBERSHIP": "Su adhesión como miembro va a estar renovada.<br/></br/><b>¿Está usted seguro</b>de querer continuar?", "REVOKE_IDENTITY": "Va a <b>revocar definitivamente esta identidad</b>.<br/><br/>La llave pública y el seudónimo asociados <b>jamás podrán ser utilizados</b> (para una cuenta miembro). <br/></br/><b>¿Está usted seguro</b> de querer revocar definitivamente esta cuenta?", "REVOKE_IDENTITY_2": "¡Esta operación es <b>irreversible</b>!<br/><br/>¿Está usted seguro de querer <b>revocar definitivamente</b> esta cuenta?", @@ -2522,9 +3840,10 @@ $translateProvider.translations("fr-FR", { "BTN_YES_CONTINUE": "Oui, Continuer", "BTN_SHOW": "Voir", "BTN_SHOW_PUBKEY": "Afficher la clé publique", - "BTN_RELATIVE_UNIT": "Afficher en unité relative ?", + "BTN_RELATIVE_UNIT": "Afficher les montants en DU ?", "BTN_BACK": "Retour", "BTN_NEXT": "Suivant", + "BTN_IMPORT": "Importer", "BTN_CANCEL": "Annuler", "BTN_CLOSE": "Fermer", "BTN_LATER": "Plus tard", @@ -2550,9 +3869,10 @@ $translateProvider.translations("fr-FR", { "BTN_MODIFY": "Modifier", "CHOOSE_FILE": "Déposez votre fichier <br/>ou cliquez pour le sélectionner", "DAYS": "jours", - "NO_ACCOUNT_QUESTION": "Pas de encore membre ? Créer un compte !", + "NO_ACCOUNT_QUESTION": "Pas encore de compte ? Créez-en un gratuitement !", "SEARCH_NO_RESULT": "Aucun résultat trouvé", "LOADING": "Veuillez patienter...", + "LOADING_WAIT": "Veuillez patienter...<br/><small>(Attente de disponibilité du noeud)</small>", "SEARCHING": "Recherche en cours...", "FROM": "De", "TO": "À", @@ -2570,7 +3890,7 @@ $translateProvider.translations("fr-FR", { "DISABLE": "Désactivé", "RESULTS_LIST": "Résultats", "RESULTS_COUNT": "{{count}} résultats", - "EXECUTION_TIME": "executé en {{duration|formatDurationMs}}", + "EXECUTION_TIME": "exécuté en {{duration|formatDurationMs}}", "SHOW_VALUES": "Afficher les valeurs en clair ?", "POPOVER_ACTIONS_TITLE": "Options", "POPOVER_FILTER_TITLE": "Filtres", @@ -2582,6 +3902,12 @@ $translateProvider.translations("fr-FR", { "SHARE_ON_FACEBOOK": "Partager sur Facebook", "SHARE_ON_DIASPORA": "Partager sur Diaspora*", "SHARE_ON_GOOGLEPLUS": "Partager sur Google+" + }, + "FILE": { + "DATE": "Date :", + "TYPE": "Type :", + "SIZE": "Taille :", + "VALIDATING": "Validation en cours..." } }, "SYSTEM": { @@ -2594,6 +3920,7 @@ $translateProvider.translations("fr-FR", { "WOT": "Annuaire", "CURRENCY": "Monnaie", "ACCOUNT": "Mon compte", + "WALLETS": "Mes portefeuilles", "TRANSFER": "Virement", "SCAN": "Scanner", "SETTINGS": "Paramètres", @@ -2602,41 +3929,52 @@ $translateProvider.translations("fr-FR", { }, "ABOUT": { "TITLE": "À propos", - "LICENSE": "Application <b>libre</b> (licence GNU GPLv3).", + "LICENSE": "Application <b>libre</b> (Licence GNU AGPLv3).", "LATEST_RELEASE": "Il existe une <b>version plus récente</b> de {{'COMMON.APP_NAME'|translate}} (<b>v{{version}}</b>)", "PLEASE_UPDATE": "Veuillez mettre à jour {{'COMMON.APP_NAME'|translate}} (dernière version : <b>v{{version}}</b>)", "CODE": "Code source :", + "OFFICIAL_WEB_SITE": "Site web officiel :", "DEVELOPERS": "Développé par :", "FORUM": "Forum :", "PLEASE_REPORT_ISSUE": "N'hésitez pas à nous remonter les anomalies rencontrées", - "REPORT_ISSUE": "Remonter un problème" + "REPORT_ISSUE": "Remonter un problème", + "BTN_OPEN_DEV_WINDOW": "Ouvrir la fenêtre de debuggage" }, "HOME": { "TITLE": "Cesium", "WELCOME": "Bienvenue dans l'application Cesium !", - "MESSAGE": "Suivez vos comptes {{currency|abbreviate}} en toute simplicité", + "MESSAGE": "Recevez et envoyez de la monnaie libre {{currency|abbreviate}}", "BTN_CURRENCY": "Explorer la monnaie {{name|abbreviate}}", "BTN_ABOUT": "à propos", "BTN_HELP": "Aide en ligne", "REPORT_ISSUE": "anomalie", "NOT_YOUR_ACCOUNT_QUESTION" : "Vous n'êtes pas propriétaire du compte <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> ?", "BTN_CHANGE_ACCOUNT": "Déconnecter ce compte", - "CONNECTION_ERROR": "NÅ“ud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifiez votre connection Internet, ou changer de nÅ“ud <a class=\"positive\" ng-click=\"doQuickFix('settings')\">dans les paramètres</a>." + "CONNECTION_ERROR": "NÅ“ud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifiez votre connexion Internet, ou changer de nÅ“ud <a class=\"positive\" ng-click=\"doQuickFix('settings')\">dans les paramètres</a>." }, "SETTINGS": { "TITLE": "Paramètres", + "DISPLAY_DIVIDER": "Affichage", + "STORAGE_DIVIDER": "Stockage", "NETWORK_SETTINGS": "Réseau", "PEER": "Adresse du nÅ“ud Duniter", + "PEER_SHORT": "Adresse du nÅ“ud", "PEER_CHANGED_TEMPORARY": "Adresse utilisée temporairement", "USE_LOCAL_STORAGE": "Activer le stockage local", "USE_LOCAL_STORAGE_HELP": "Permet de sauvegarder vos paramètres", + "WALLETS_SETTINGS": "Mes portefeuilles", + "USE_WALLETS_ENCRYPTION": "Sécuriser la liste ?", + "USE_WALLETS_ENCRYPTION_HELP": "Permet de sécuriser la liste de vos portefeuilles (par chiffrement), en exigeant une authentification pour y accéder.", "ENABLE_HELPTIP": "Activer les bulles d'aide contextuelles", "ENABLE_UI_EFFECTS": "Activer les effets visuels", - "HISTORY_SETTINGS": "Liste des opérations", + "HISTORY_SETTINGS": "Mes opérations", "DISPLAY_UD_HISTORY": "Afficher les dividendes produits ?", + "TX_HISTORY_AUTO_REFRESH": "Rafraîchir automatiquement", + "TX_HISTORY_AUTO_REFRESH_HELP": "Rafraîchit le solde et les opérations automatiquement, à chaque nouveau bloc du réseau.", "AUTHENTICATION_SETTINGS": "Authentification", - "KEEP_AUTH": "Expiration de l'authentification", - "KEEP_AUTH_HELP": "Défini le moment où l'authentification est nettoyée de la mémoire", + "KEEP_AUTH": "Désauthentification automatique", + "KEEP_AUTH_SHORT": "Désauthentification", + "KEEP_AUTH_HELP": "Définit le moment où l'authentification est nettoyée de la mémoire.", "KEEP_AUTH_OPTION": { "NEVER": "Après chaque opération", "SECONDS": "Après {{value}}s d'inactivité", @@ -2645,19 +3983,28 @@ $translateProvider.translations("fr-FR", { "HOUR": "Après {{value}}h d'inactivité", "ALWAYS": "A la fin de la session" }, + "KEYRING_FILE": "Fichier de trousseau", + "KEYRING_FILE_HELP": "Permet de vous <b>connecter</b> automatiquement à chaque lancement<br/>et même de vous <b>authentifier</b> (seulement si \"Expiration de l'authentification\" est configurée \"à la fin de la session\").", "REMEMBER_ME": "Se souvenir de moi ?", "REMEMBER_ME_HELP": "Permet de rester identifié d'une session à l'autre, en conservant localement la clé publique.", "PLUGINS_SETTINGS": "Extensions", "BTN_RESET": "Restaurer les valeurs par défaut", "EXPERT_MODE": "Activer le mode expert", - "EXPERT_MODE_HELP": "Permet un affichage plus détaillé", + "EXPERT_MODE_HELP": "Permet un affichage plus détaillé.", + "BLOCK_VALIDITY_WINDOW": "Délai d'incertitude des blocs", + "BLOCK_VALIDITY_WINDOW_SHORT": "Délai d'incertitude", + "BLOCK_VALIDITY_WINDOW_HELP": "Délai avant de considérer qu'une information est validée", + "BLOCK_VALIDITY_OPTION": { + "NONE": "Aucun délai", + "N": "{{time | formatDuration}} ({{count}} blocs)" + }, "POPUP_PEER": { - "TITLE" : "NÅ“ud Duniter", - "HOST" : "Adresse", + "TITLE": "NÅ“ud Duniter", + "HOST": "Adresse", "HOST_HELP": "Adresse : serveur:port", - "USE_SSL" : "Sécurisé ?", - "USE_SSL_HELP" : "(Chiffrement SSL)", - "BTN_SHOW_LIST" : "Liste des noeuds" + "USE_SSL": "Sécurisé ?", + "USE_SSL_HELP": "(Chiffrement SSL)", + "BTN_SHOW_LIST": "Liste des noeuds" } }, "BLOCKCHAIN": { @@ -2679,12 +4026,12 @@ $translateProvider.translations("fr-FR", { "IDENTITIES_COUNT": "Nouvelles identités", "JOINERS_COUNT": "Nouveaux membres", "ACTIVES_COUNT": "Renouvellements", - "ACTIVES_COUNT_HELP": "Membres ayant renouvellés leur adhésion", + "ACTIVES_COUNT_HELP": "Membres ayant renouvelé leur adhésion", "LEAVERS_COUNT": "Membres sortants", "LEAVERS_COUNT_HELP": "Membres ne souhaitant plus de certification", "EXCLUDED_COUNT": "Membres exclus", "EXCLUDED_COUNT_HELP": "Anciens membres exclus par non renouvellement ou manque de certifications", - "REVOKED_COUNT": "Identités revoquées", + "REVOKED_COUNT": "Identités révoquées", "REVOKED_COUNT_HELP": "Ces comptes ne pourront plus être membres", "TX_COUNT": "Transactions", "CERT_COUNT": "Certifications", @@ -2744,7 +4091,7 @@ $translateProvider.translations("fr-FR", { "STEP_MAX": "Distance maximale, par les certifications, entre un nouvel entrant et les membres référents", "WOT_RULES_DIVIDER": "Règles de la toile de confiance", "SENTRIES": "Nombre de certifications (émises <b>et</b> reçues) pour devenir membre référent", - "SENTRIES_FORMULA": "Nombre de certification (émises <b>et</b> reçues) pour devenir membre référent (formule)", + "SENTRIES_FORMULA": "Nombre de certifications (émises <b>et</b> reçues) pour devenir membre référent (formule)", "XPERCENT":"Pourcentage minimum de membres référents à atteindre pour respecter la règle de distance", "AVG_GEN_TIME": "Temps moyen entre deux blocs", "CURRENT": "actuel", @@ -2785,15 +4132,18 @@ $translateProvider.translations("fr-FR", { "PEERS": "NÅ“uds", "SIGNED_ON_BLOCK": "Signé sur le bloc", "MIRROR": "miroir", - "MIRRORS": "NÅ“uds miroirs", + "MIRRORS": "Miroirs", + "MIRROR_PEERS": "NÅ“uds miroirs", "PEER_LIST" : "Liste des nÅ“uds", - "MEMBERS" : "NÅ“uds membres", + "MEMBERS" : "Membres", + "MEMBER_PEERS" : "NÅ“uds membres", "ALL_PEERS" : "Tous les nÅ“uds", "DIFFICULTY" : "Difficulté", "API" : "API", "CURRENT_BLOCK" : "Bloc #", "POPOVER_FILTER_TITLE": "Filtre", - "OFFLINE": "NÅ“uds hors ligne", + "OFFLINE": "Hors ligne", + "OFFLINE_PEERS": "NÅ“uds hors ligne", "BTN_SHOW_PEER": "Voir le nÅ“ud", "VIEW": { "TITLE": "NÅ“ud", @@ -2811,13 +4161,13 @@ $translateProvider.translations("fr-FR", { }, "WOT": { "SEARCH_HELP": "Recherche (pseudo ou clé publique)", - "SEARCH_INIT_PHASE_WARNING": "Durant la phase de pré-inscription, la recherche des inscriptions en attente <b>peut-être longue</b>. Merci de patienter...", + "SEARCH_INIT_PHASE_WARNING": "Durant la phase de pré-inscription, la recherche des inscriptions en attente <b>peut être longue</b>. Merci de patienter...", "REGISTERED_SINCE": "Inscrit le", - "REGISTERED_SINCE_BLOCK": "Inscrit au block #", + "REGISTERED_SINCE_BLOCK": "Inscrit au bloc #", "NO_CERTIFICATION": "Aucune certification validée", "NO_GIVEN_CERTIFICATION": "Aucune certification émise", "NOT_MEMBER_PARENTHESIS": "(non membre)", - "IDENTITY_REVOKED_PARENTHESIS": "(identité revoquée)", + "IDENTITY_REVOKED_PARENTHESIS": "(identité révoquée)", "MEMBER_PENDING_REVOCATION_PARENTHESIS": "(en cours de révocation)", "EXPIRE_IN": "Expiration", "NOT_WRITTEN_EXPIRE_IN": "Date limite<br/>de traitement", @@ -2843,7 +4193,7 @@ $translateProvider.translations("fr-FR", { "PENDING": "Inscriptions en attente", "PENDING_COUNT": "{{count}} inscriptions en attente", "REGISTERED": "Inscrit {{sigDate | formatFromNow}}", - "MEMBER_FROM": "Membre depuis {{memberDate|formatFromNowShort}}", + "MEMBER_FROM": "Membre depuis {{memberDate|medianFromNowShort}}", "BTN_NEWCOMERS": "Nouveaux membres", "BTN_PENDING": "Inscriptions en attente", "SHOW_MORE": "Afficher plus", @@ -2885,14 +4235,17 @@ $translateProvider.translations("fr-FR", { "SCRYPT_FORM_HELP": "Veuillez saisir vos identifiants.<br>Pensez à vérifier que la clé publique est celle de votre compte.", "PUBKEY_FORM_HELP": "Veuillez saisir une clé publique de compte :", "FILE_FORM_HELP": "Choisissez le fichier de trousseau à utiliser :", + "SCAN_FORM_HELP": "Scanner le QR code d'un portefeuille.", "SALT": "Identifiant secret", "SALT_HELP": "Identifiant secret", "SHOW_SALT": "Afficher l'identifiant secret ?", "PASSWORD": "Mot de passe", "PASSWORD_HELP": "Mot de passe", - "PUBKEY_HELP": "Exemple : « AbsxSY4qoZRzyV2irfep1V9xw1EMNyKJw2TkuVD4N1mv »", + "PUBKEY_HELP": "Clé publique ou pseudonyme", "NO_ACCOUNT_QUESTION": "Vous n'avez pas encore de compte ?", + "HAVE_ACCOUNT_QUESTION": "Vous avez déjà un compte ?", "CREATE_ACCOUNT": "Créer un compte...", + "CREATE_FREE_ACCOUNT": "Créer un compte gratuitement", "FORGOTTEN_ID": "Mot de passe oublié ?", "ASSOCIATED_PUBKEY": "Clé publique du trousseau :", "BTN_METHODS": "Autres méthodes", @@ -2907,61 +4260,65 @@ $translateProvider.translations("fr-FR", { "IDLE_WARNING": "Vous allez être déconnecté... {{countdown}}" }, "METHOD": { - "SCRYPT_DEFAULT": "Sallage standard (par défaut)", - "SCRYPT_ADVANCED": "Sallage avancé", + "SCRYPT_DEFAULT": "Identifiant secret et mot de passe", + "SCRYPT_ADVANCED": "Salage avancé", "FILE": "Fichier de trousseau", - "PUBKEY": "Clé publique seule" + "PUBKEY": "Clé publique ou pseudonyme", + "SCAN": "Scanner un QR code" }, "SCRYPT": { - "SIMPLE": "Sallage léger", - "DEFAULT": "Sallage standard", - "SECURE": "Sallage sûr", - "HARDEST": "Sallage le plus sûr", - "EXTREME": "Sallage extrème", - "USER": "Sallage personnalisé", + "SIMPLE": "Salage léger", + "DEFAULT": "Salage standard", + "SECURE": "Salage sûr", + "HARDEST": "Salage le plus sûr", + "EXTREME": "Salage extrême", + "USER": "Salage personnalisé", "N": "N (Loop):", "r": "r (RAM):", "p": "p (CPU):" }, "FILE": { - "DATE" : "Date :", - "TYPE" : "Type :", - "SIZE": "Taille :", - "VALIDATING": "Validation en cours...", - "HELP": "Format de fichier attendu : <b>.dunikey</b> (type PubSec). D'autres formats sont en cours de développement (EWIF, WIF)." + "HELP": "Format de fichier attendu : <b>.yml</b> ou <b>.dunikey</b> (type PubSec, WIF ou EWIF)." } }, "AUTH": { "TITLE": "<i class=\"icon ion-locked\"></i> Authentification", - "METHOD_LABEL": "Méthode d'authentification", "BTN_AUTH": "S'authentifier", - "SCRYPT_FORM_HELP": "Veuillez vous authentifier :" + "GENERAL_HELP": "Veuillez vous authentifier :", + "EXPECTED_UID_HELP": "Veuillez vous authentifier sur le compte <i class=\"ion-person\"></i> {{uid}} :", + "EXPECTED_PUBKEY_HELP": "Veuillez vous authentifier sur le portefeuille <br class=\"visible-xs\"/><i class=\"ion-key\"></i> {{pubkey|formatPubkey}} :", + "SCAN_FORM_HELP": "Scanner le QR code de la <b>clef privée</b> du portefeuille." }, "ACCOUNT": { "TITLE": "Mon compte", "BALANCE": "Solde", - "LAST_TX": "Dernières transactions", + "LAST_TX": "Dernières transactions validées", "BALANCE_ACCOUNT": "Solde du compte", "NO_TX": "Aucune transaction", "SHOW_MORE_TX": "Afficher plus", "SHOW_ALL_TX": "Afficher tout", - "TX_FROM_DATE": "(limite actuelle à {{fromTime|formatFromNowShort}})", - "PENDING_TX": "Transactions en cours de traitement", + "TX_FROM_DATE": "(limite actuelle à {{fromTime|medianFromNowShort}})", + "PENDING_TX": "Transactions en attente de traitement", + "VALIDATING_TX": "Transactions traitées, non validées", "ERROR_TX": "Transactions non executées", "ERROR_TX_SENT": "Transactions envoyées en échec", "PENDING_TX_RECEIVED": "Transactions en attente de réception", "EVENTS": "Evénements", + "OUT_DISTANCED": "Vos certifications actuelles proviennent d'un groupe trop isolé de la <a ng-click=\"showHelpModal('wot')\">Toile de Confiance</a> (TdC) : la <a ng-click=\"showHelpModal('distance_rule')\">règle de distance maximale</a> n'est pas respectée.<br/>Vous devez obtenir des certifications provenant d'autres secteurs de la TdC, ou bien attendre que celle-ci se resserre.", "WAITING_MEMBERSHIP": "Demande d'adhésion envoyée. En attente d'acceptation.", - "WAITING_CERTIFICATIONS": "Vous devez obtenir {{needCertificationCount}} certification(s) pour devenir membre.", - "WILL_MISSING_CERTIFICATIONS": "Vous allez bientôt <b>manquer de certification</b> (au moins {{willNeedCertificationCount}} sont requises)", + "WAITING_CERTIFICATIONS": "Vous devez <b>obtenir {{needCertificationCount}} certification(s)</b> pour devenir membre et produire le <a ng-click=\"showHelpModal('ud')\">Dividende Universel</a>. Votre compte est cependant déjà opérationnel, pour recevoir et effectuer des paiements.", + "WAITING_CERTIFICATIONS_HELP": "Pour obtenir vos certifications, sollicitez uniquement des membres <b>qui vous connaissent suffisamment</b>, comme l'exige <a ng-click=\"showLicenseModal()\">la licence de la monnaie</a> que vous avez acceptée.<br/>Si vous ne connaissez pas suffisamment de membres, faites-le savoir sur <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">le forum utilisateur</a>.", + "WILL_MISSING_CERTIFICATIONS": "Vous allez bientôt <b>manquer de certifications</b> (au moins {{willNeedCertificationCount}} sont requises)", "WILL_NEED_RENEW_MEMBERSHIP": "Votre adhésion comme membre <b>va expirer {{membershipExpiresIn|formatDurationTo}}</b>. Pensez à <a ng-click=\"doQuickFix('renew')\">renouveler votre adhésion</a> d'ici là .", - "NEED_RENEW_MEMBERSHIP": "Vous n'êtes plus membre, car votre adhésion <b>a expiré</b>. Pensez à <a ng-click=\"doQuickFix('renew')\">renouveler votre adhésion</a>.", + "NEED_RENEW_MEMBERSHIP": "Vous n'êtes plus membre de la monnaie, car <b>votre adhésion a expiré</b>. Pensez à <a ng-click=\"doQuickFix('renew')\">renouveler votre adhésion</a>.", + "NEED_RENEW_MEMBERSHIP_AFTER_CANCELLED": "Vous n'êtes plus membre de la monnaie, <b>pour manque de certifications</b>. Pensez à <a ng-click=\"doQuickFix('renew')\">renouveler votre adhésion</a>.", "NO_WAITING_MEMBERSHIP": "Aucune demande d'adhésion en attente. Si vous souhaitez <b>devenir membre</b>, pensez à <a ng-click=\"doQuickFix('membership')\">envoyer la demande d'adhésion</a>.", "CERTIFICATION_COUNT": "Certifications reçues", "CERTIFICATION_COUNT_SHORT": "Certifications", "SIG_STOCK": "Certifications envoyées", "BTN_RECEIVE_MONEY": "Encaisser", "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Basculer vers une autre identité...", + "BTN_FIX_MEMBERSHIP": "Renvoyer la demande d'adhésion...", "BTN_MEMBERSHIP_RENEW": "Renouveler l'adhésion", "BTN_MEMBERSHIP_RENEW_DOTS": "Renouveler l'adhésion...", "BTN_MEMBERSHIP_OUT_DOTS": "Arrêter l'adhésion...", @@ -2976,7 +4333,7 @@ $translateProvider.translations("fr-FR", { "NEW": { "TITLE": "Création de compte", "INTRO_WARNING_TIME": "La création d'un compte sur {{name|capitalize}} est très simple. Veuillez néanmoins prendre suffisament de temps pour faire correctement cette formalité (pour ne pas oublier les identifiants, mots de passe, etc.).", - "INTRO_WARNING_SECURITY": "Vérifier que le matériel que vous utilisez actuellement (ordinateur, tablette, téléphone) <b>est sécurisé et digne de confiance</b>.", + "INTRO_WARNING_SECURITY": "Vérifiez que le matériel que vous utilisez actuellement (ordinateur, tablette, téléphone) <b>est sécurisé et digne de confiance</b>.", "INTRO_WARNING_SECURITY_HELP": "Anti-virus à jour, pare-feu activé, session protégée par mot de passe ou code pin, etc.", "INTRO_HELP": "Cliquez sur <b>{{'COMMON.BTN_START'|translate}}</b> pour débuter la création de compte. Vous serez guidé étape par étape.", "REGISTRATION_NODE": "Votre inscription sera enregistrée via le noeud Duniter <b>{{server}}</b>, qui le diffusera ensuite au reste du réseau de la monnaie.", @@ -2999,9 +4356,9 @@ $translateProvider.translations("fr-FR", { "PASSWORD_CONFIRM_HELP": "Confirmation du mot de passe", "SLIDE_6_TITLE": "Confirmation :", "COMPUTING_PUBKEY": "Calcul en cours...", - "LAST_SLIDE_CONGRATULATION": "Vous avez saisi toutes les informations nécessaires : Bravo !<br/>Vous pouvez maintenant <b>envoyer la demande de création</b> de compte.</b><br/><br/>Pour information, la clé publique ci-dessous identifiera votre futur compte.<br/>Elle pourra être communiquée à des tiers pour recevoir leur paiement.<br/><b>Il n'est pas obligatoire</b> de la noter ici, vous pourrez également le faire plus tard.", - "CONFIRMATION_MEMBER_ACCOUNT": "<b class=\"assertive\">Avertissement :</b> l'identifiant secret, le mot de passe et le pseudonyme ne pourront plus être modifiés.<br/><br/><b>Assurez-vous de toujours vous en rappeller !</b><br/><br/><b>Etes-vous sûr</b> de vouloir envoyer cette demande d'inscription ?", - "CONFIRMATION_WALLET_ACCOUNT": "<b class=\"assertive\">Avertissement :</b> l'identifiant secret et le mot de passe ne pourront plus être modifiés.<br/><br/><b>Assurez-vous de toujours vous en rappeller !</b><br/><br/><b>Etes-vous sûr</b> de vouloir continuer avec ces identifiants ?", + "LAST_SLIDE_CONGRATULATION": "Vous avez saisi toutes les informations nécessaires : Bravo !<br/>Vous pouvez maintenant <b>envoyer la demande de création</b> de compte.</b><br/><br/>Pour information, la clé publique ci-dessous identifiera votre futur compte.<br/>Elle pourra être communiquée à des tiers pour recevoir leurs paiements.<br/><b>Il n'est pas obligatoire</b> de la noter ici, vous pourrez également le faire plus tard.", + "CONFIRMATION_MEMBER_ACCOUNT": "<b class=\"assertive\">Avertissement :</b> l'identifiant secret, le mot de passe et le pseudonyme ne pourront plus être modifiés.<br/><br/><b>Assurez-vous de toujours vous en rappeler !</b><br/><br/><b>Êtes-vous sûr</b> de vouloir envoyer cette demande d'inscription ?", + "CONFIRMATION_WALLET_ACCOUNT": "<b class=\"assertive\">Avertissement :</b> l'identifiant secret et le mot de passe ne pourront plus être modifiés.<br/><br/><b>Assurez-vous de toujours vous en rappeler !</b><br/><br/><b>Êtes-vous sûr</b> de vouloir continuer avec ces identifiants ?", "CHECKING_PSEUDO": "Vérification...", "PSEUDO_AVAILABLE": "Pseudonyme disponible", "PSEUDO_NOT_AVAILABLE": "Pseudonyme non disponible", @@ -3017,17 +4374,42 @@ $translateProvider.translations("fr-FR", { "TITLE": "Sélection de l'identité", "HELP": "Plusieurs <b>identités différentes</b> ont été envoyées, pour la clé publique <span class=\"gray\"><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</span>.<br/>Veuillez sélectionner le dossier à utiliser :" }, + "SELECT_WALLET_MODAL": { + "TITLE": "Sélection du portefeuille" + }, + "WALLET_LIST": { + "TITLE": "Mes portefeuilles", + "BTN_NEW": "Ajouter un portefeuille", + "BTN_DOWNLOAD": "Télécharger la liste", + "BTN_IMPORT_FILE_DOTS": "Importer depuis un fichier...", + "NO_WALLET": "Aucun portefeuille secondaire", + "BTN_DELETE": "Retirer un portefeuille secondaire...", + "BTN_RENAME": "Renommer le portefeuille", + "EXPORT_FILENAME": "mes_portefeuilles-{{pubkey|formatPubkey}}-{{currency}}.csv", + "TOTAL_DOTS": "Total : ", + "EDIT_POPOVER": { + "TITLE": "Renommer le portefeuille", + "HELP": "Renseignez le nouveau nom", + "NAME_HELP": "Nom du portefeuille" + }, + "IMPORT_MODAL": { + "TITLE": "Importer des portefeuilles", + "HELP": "Pour <b>importer des porftefeuilles</b>, veuillez glisser dans la zone ci-dessous le fichier de la liste des portefeuilles, ou bien cliquer dans la zone pour rechercher un fichier.", + "WALLET_COUNT": "<b>{{count}}</b> nouveau{{count > 1 ? 'x' : ''}} portefeuille{{count > 1 ? 's' : ''}}", + "NO_NEW_WALLET": "Aucun nouveau portefeuille" + } + }, "SECURITY": { - "ADD_QUESTION": "Ajouter une question personnalisée ", + "ADD_QUESTION": "Ajouter une question personnalisée", "BTN_CLEAN": "Vider", "BTN_RESET": "Réinitialiser", "DOWNLOAD_REVOKE": "Sauvegarder mon fichier de révocation", "DOWNLOAD_REVOKE_HELP": "Disposer d'un fichier de révocation est important, par exemple en cas de perte de vos identifiants. Il vous permet de <b>sortir ce compte de la toile de confiance</b>, en redevenant ainsi un simple portefeuille.", "GENERATE_KEYFILE": "Générer mon fichier de trousseau...", - "GENERATE_KEYFILE_HELP": "Génère un fichier permettant de vous authentifier sans saisir vos identifiants.<br/><b>Attention :</b> ce fichier contiendra votre clef secrète : il est donc très important de le mettre en lieu sûr !", + "GENERATE_KEYFILE_HELP": "Génère un fichier permettant de vous authentifier sans saisir vos identifiants.<br/><b>Attention :</b> ce fichier contiendra votre trousseau de compte (clefs publique et secrète) ; il est donc très important de le mettre en lieu sûr !", "KEYFILE_FILENAME": "trousseau-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Transformer en compte membre...", - "MEMBERSHIP_IN_HELP": "Permet de <b>transformer</b> un compte simple portefeuille <b>en compte membre</b>, en envoyant une demande d'adhésion. Utile uniquement si vous n'avez pas déjà une autre compte membre.", + "MEMBERSHIP_IN_HELP": "Permet de <b>transformer</b> un compte simple portefeuille <b>en compte membre</b>, en envoyant une demande d'adhésion. Utile uniquement si vous n'avez pas déjà un autre compte membre.", "SEND_IDENTITY": "Publier son identité...", "SEND_IDENTITY_HELP": "Permet d'associer un pseudonyme à ce compte, mais <b>sans faire de demande d'adhésion</b> pour devenir membre. Cette association n'est généralement pas utile, car la validité de cette association de pseudonyme est limitée dans le temps.", "HELP_LEVEL": "Pour générer un fichier de sauvegarde de vos identifiants, choisissez <strong> au moins {{nb}} questions :</strong>", @@ -3059,7 +4441,7 @@ $translateProvider.translations("fr-FR", { "REVOCATION_WITH_FILE_DESCRIPTION": "Si vous avez <b>définitivement perdus vos identifiants</b> de compte membre (ou que la sécurité du compte est compromise), vous pouvez utiliser <b>le fichier de révocation</b> du compte pour <b>forcer sa sortie définitive de la toile de confiance</b>.", "REVOCATION_WITH_FILE_HELP": "Pour <b>révoquer définitivement</b> un compte membre, veuillez glisser dans la zone ci-dessous votre fichier de révocation, ou bien cliquer dans la zone pour rechercher un fichier.", "REVOCATION_WALLET": "Révoquer immédiatement ce compte", - "REVOCATION_WALLET_HELP": "Demander la révocation de votre identité entraine la <b>sortie de la toile de confiance</b> (définitive pour le pseudonyme et la clé publique associés). Le compte ne pourra plus produire de Dividende Universel.<br/>Vous pourrez toutefois encore vous y connecter, comme à un simple portefeuille.", + "REVOCATION_WALLET_HELP": "Demander la révocation de votre identité entraîne la <b>sortie de la toile de confiance</b> (définitive pour le pseudonyme et la clé publique associés). Le compte ne pourra plus produire de Dividende Universel.<br/>Vous pourrez toutefois encore vous y connecter, comme à un simple portefeuille.", "REVOCATION_FILENAME": "revocation-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", "SAVE_ID": "Sauvegarder mes identifiants...", "SAVE_ID_HELP": "Création d'un fichier de sauvegarde, pour <b>retrouver votre mot de passe</b> (et l'identifiant secret) <b>en cas de d'oubli</b>. Le fichier est <b>sécurisé</b> (chiffré) à l'aide de questions personnelles.", @@ -3067,15 +4449,19 @@ $translateProvider.translations("fr-FR", { "TITLE": "Compte et sécurité", "KEYFILE": { "PUBSEC_FORMAT": "Format PubSec.", - "PUBSEC_FORMAT_HELP": "Ce format de fichier est compatible notamment avec Cesium et gannonce.", - "WIF_FORMAT": "Format WIF", - "WIF_FORMAT_HELP": "Ce format permet notamment la génération de portefeuilles papier (Paper Wallet).", - "EWIF_FORMAT": "Format EWIF", - "EWIF_FORMAT_HELP": "Ce format protège le trousseau par un mot de passe. Il permet notamment la génération de portefeuilles papier (Paper Wallet).", + "PUBSEC_FORMAT_HELP": "Ce format stocke votre trousseau de manière très simple. Il est compatible notamment avec Cesium, ÄŸannonce et Duniter.<br/><b>Attention :</b>Le fichier <b>n'est pas chiffré</b> (la clef secrète y apparaît en clair) ; veuillez donc le stocker en lieu sûr !", + "WIF_FORMAT": "Format WIF (Wallet Import Format) - v1", + "WIF_FORMAT_HELP": "Ce format stocke votre trousseau en y intégrant une somme de contrôle pour vérifier l'intégrité du fichier. Il est compatible notamment avec les portefeuilles papier (Duniter paper wallet).<br/><b>Attention :</b>Le fichier <b>n'est pas chiffré</b> (la clef secrète y apparaît en clair) ; veuillez donc le stocker en lieu sûr !", + "EWIF_FORMAT": "Format EWIF (Encrypted Wallet Import Format) - v1", + "EWIF_FORMAT_HELP": "Ce format stocke votre trousseau <b>de manière chiffrée</b> à partir d'une phrase secrète de votre choix. Il intègre aussi une somme de contrôle pour vérifier l'intégrité du fichier.<br/><b>Attention :</b> Veillez à toujours vous souvenir de votre phrase secrète !", "PASSWORD_POPUP": { "TITLE": "Fichier de trousseau chiffré", - "HELP": "Veuillez indiquer le mot de passe:", - "PASSWORD_HELP": "Mot de passe" + "HELP": "Veuillez indiquer la phrase secrète :", + "PASSWORD_HELP": "Phrase secrète" + }, + "ERROR": { + "BAD_PASSWORD": "Phrase secrète incorrecte", + "BAD_CHECKSUM": "Somme de contrôle incorrecte" } } }, @@ -3089,6 +4475,7 @@ $translateProvider.translations("fr-FR", { "TRANSFER": { "TITLE": "Virement", "SUB_TITLE": "Faire un virement", + "SUB_TITLE_ALL": "Vider le compte", "FROM": "De", "TO": "À", "AMOUNT": "Montant", @@ -3097,22 +4484,24 @@ $translateProvider.translations("fr-FR", { "COMMENT_HELP": "Commentaire", "BTN_SEND": "Envoyer", "BTN_ADD_COMMENT": "Ajouter un commentaire", - "WARN_COMMENT_IS_PUBLIC": "Veuillez noter que <b>les commentaires sont publiques</b> (non chiffré).", + "REST": "Reste du compte", + "REST_TO": "à ", + "WARN_COMMENT_IS_PUBLIC": "Veuillez noter que <b>les commentaires sont publics</b> (non chiffrés).", "MODAL": { "TITLE": "Virement" } }, "ERROR": { - "UNKNOWN_URI_FORMAT": "Format inconnu (unknown URI)", + "UNKNOWN_URI_FORMAT": "Format d'URI inconnu", "PUBKEY_INVALID_CHECKSUM": "Clé publique invalide (bad checksum).", "POPUP_TITLE": "Erreur", "UNKNOWN_ERROR": "Erreur inconnue", "CRYPTO_UNKNOWN_ERROR": "Votre navigateur ne semble pas compatible avec les fonctionnalités de cryptographie.", - "DOWNLOAD_KEYFILE_FAILED": "Echec de le génération du fichier de trousseau.", + "DOWNLOAD_KEYFILE_FAILED": "Échec de la génération du fichier de trousseau.", "EQUALS_TO_PSEUDO": "Doit être différent du pseudonyme", "EQUALS_TO_SALT": "Doit être différent de l'identifiant secret", - "FIELD_REQUIRED": "Champ obligatoire.", - "FIELD_TOO_SHORT": "Valeur trop courte.", + "FIELD_REQUIRED": "Champ obligatoire", + "FIELD_TOO_SHORT": "Valeur trop courte", "FIELD_TOO_SHORT_WITH_LENGTH": "Valeur trop courte ({{minLength}} caractères min)", "FIELD_TOO_LONG": "Valeur trop longue", "FIELD_TOO_LONG_WITH_LENGTH": "Valeur trop longue ({{maxLength}} caractères max)", @@ -3122,81 +4511,94 @@ $translateProvider.translations("fr-FR", { "FIELD_NOT_NUMBER": "Valeur numérique attendue", "FIELD_NOT_INT": "Valeur entière attendue", "FIELD_NOT_EMAIL": "Adresse email non valide", - "PASSWORD_NOT_CONFIRMED": "Ne correspond pas au mot de passe.", - "SALT_NOT_CONFIRMED": "Ne correspond pas à l'identifiant secret.", - "SEND_IDENTITY_FAILED": "Echec de l'inscription.", - "SEND_CERTIFICATION_FAILED": "Echec de la certification.", + "PASSWORD_NOT_CONFIRMED": "Ne correspond pas au mot de passe", + "SALT_NOT_CONFIRMED": "Ne correspond pas à l'identifiant secret", + "SEND_IDENTITY_FAILED": "Échec de l'inscription", + "SEND_CERTIFICATION_FAILED": "Échec de la certification", "NEED_MEMBER_ACCOUNT_TO_CERTIFY": "Vous ne pouvez pas effectuer de certification, car votre compte n'est <b>pas membre</b>.", "NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF": "Vous ne pouvez pas effectuer de certification, car votre compte n'est pas encore membre.<br/><br/>Il vous manque encore des certifications, ou bien celles-ci n'ont pas encore été validées.", "NOT_MEMBER_FOR_CERTIFICATION": "Votre compte n'est pas encore membre.", - "IDENTITY_TO_CERTIFY_HAS_NO_SELF": "Compte non certifiable. Aucune demande d'adhésion n'a été faite, ou bien elle n'a pas été renouvellée.", + "IDENTITY_TO_CERTIFY_HAS_NO_SELF": "Compte non certifiable. Aucune demande d'adhésion n'a été faite, ou bien elle n'a pas été renouvelée.", "LOGIN_FAILED": "Erreur lors de la connexion.", "LOAD_IDENTITY_FAILED": "Erreur de chargement de l'identité.", "LOAD_REQUIREMENTS_FAILED": "Erreur de chargement des prérequis de l'identité.", - "SEND_MEMBERSHIP_IN_FAILED": "Echec de la tentative d'entrée dans la communauté.", - "SEND_MEMBERSHIP_OUT_FAILED": "Echec de l'arret de l'adhésion.", - "REFRESH_WALLET_DATA": "Echec du rafraichissement du portefeuille.", - "GET_CURRENCY_PARAMETER": "Echec de la récupération des règles de la monnaie.", - "GET_CURRENCY_FAILED": "Chargement de la monnaie impossible. Veuillez ressayer plus tard.", - "SEND_TX_FAILED": "Echec du virement.", - "ALL_SOURCES_USED": "Veuillez attendre le calcul du prochain bloc (Toutes vos sources de monnaie ont été utilisées).", + "SEND_MEMBERSHIP_IN_FAILED": "Échec de la tentative d'entrée dans la communauté.", + "SEND_MEMBERSHIP_OUT_FAILED": "Échec de l'arrêt de l'adhésion.", + "REFRESH_WALLET_DATA": "Échec du rafraîchissement du portefeuille.", + "GET_CURRENCY_PARAMETER": "Échec de la récupération des règles de la monnaie.", + "GET_CURRENCY_FAILED": "Chargement de la monnaie impossible. Veuillez réessayer plus tard.", + "SEND_TX_FAILED": "Échec du virement.", + "ALL_SOURCES_USED": "Veuillez attendre le calcul du prochain bloc (toutes vos sources de monnaie ont été utilisées).", "NOT_ENOUGH_SOURCES": "Pas assez de change pour envoyer ce montant en une seule transaction.<br/>Montant maximum : {{amount}} {{unit}}<sub>{{subUnit}}</sub>.", - "ACCOUNT_CREATION_FAILED": "Echec de la création du compte membre.", - "RESTORE_WALLET_DATA_ERROR": "Echec du rechargement des paramètres depuis le stockage local", - "LOAD_WALLET_DATA_ERROR": "Echec du chargement des données du portefeuille.", + "ACCOUNT_CREATION_FAILED": "Échec de la création du compte membre.", + "RESTORE_WALLET_DATA_ERROR": "Échec du rechargement des paramètres depuis le stockage local", + "LOAD_WALLET_DATA_ERROR": "Échec du chargement des données du portefeuille.", "COPY_CLIPBOARD_FAILED": "Copie de la valeur impossible.", - "TAKE_PICTURE_FAILED": "Echec de la récupération de la photo.", - "SCAN_FAILED": "Echec du scan de QR Code", + "TAKE_PICTURE_FAILED": "Échec de la récupération de la photo.", + "SCAN_FAILED": "Échec du scan de QR-code.", "SCAN_UNKNOWN_FORMAT": "Code non reconnu.", - "WOT_LOOKUP_FAILED": "Echec de la recherche", + "WOT_LOOKUP_FAILED": "Échec de la recherche.", "LOAD_PEER_DATA_FAILED": "Lecture du nÅ“ud Duniter impossible. Veuillez réessayer ultérieurement.", "NEED_LOGIN_FIRST": "Veuillez d'abord vous connecter.", "AMOUNT_REQUIRED": "Le montant est obligatoire.", "AMOUNT_NEGATIVE": "Montant négatif non autorisé.", - "NOT_ENOUGH_CREDIT": "Crédit insufisant.", + "NOT_ENOUGH_CREDIT": "Crédit insuffisant.", "INVALID_NODE_SUMMARY": "NÅ“ud injoignable ou adresse invalide.", "INVALID_USER_ID": "Le pseudonyme ne doit contenir ni espace ni caractère spécial ou accentué.", "INVALID_COMMENT": "Le champ 'référence' ne doit pas contenir de caractères accentués.", "INVALID_PUBKEY": "La clé publique n'a pas le format attendu.", - "IDENTITY_REVOKED": "Cette identité <b>a été révoquée {{revocationTime|formatFromNow}}</b> ({{revocationTime|formatDate}}). Elle ne peut plus devenir membre.", + "INVALID_PUBKEY_CHECKSUM": "Somme de contrôle invalide.", + "IDENTITY_REVOKED": "Cette identité <b>a été révoquée</b>. Elle ne peut plus devenir membre.", + "IDENTITY_REVOKED_WITH_TIME": "Cette identité <b>a été révoquée {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). Elle ne peut plus devenir membre.", "IDENTITY_PENDING_REVOCATION": "La <b>révocation de cette identité</b> a été demandée et est en attente de traitement. La certification est donc désactivée.", "IDENTITY_INVALID_BLOCK_HASH": "Cette demande d'adhésion n'est plus valide (car elle référence un bloc que les nÅ“uds du réseau ont annulé) : cette personne doit renouveler sa demande d'adhésion <b>avant</b> d'être certifiée.", - "IDENTITY_EXPIRED": "La publication de cette identité a expirée : cette personne doit effectuer une nouvelle demande d'adhésion <b>avant</b> d'être certifiée.", + "IDENTITY_EXPIRED": "La publication de cette identité a expiré : cette personne doit effectuer une nouvelle demande d'adhésion <b>avant</b> d'être certifiée.", "IDENTITY_SANDBOX_FULL": "Le nÅ“ud Duniter utilisé par Cesium ne peut plus recevoir de nouvelles identités, car sa file d'attente est pleine.<br/><br/>Veuillez réessayer ultérieurement ou changer de nÅ“ud (via le menu <b>Paramètres</b>).", - "IDENTITY_NOT_FOUND": "Identité non trouvée", - "IDENTITY_TX_FAILED": "Echec du chargement des opérations", + "IDENTITY_NOT_FOUND": "Identité non trouvée.", + "IDENTITY_TX_FAILED": "Échec du chargement des opérations.", "WOT_PENDING_INVALID_BLOCK_HASH": "Adhésion non valide.", "WALLET_INVALID_BLOCK_HASH": "Votre demande d'adhésion n'est plus valide (car elle référence un bloc que les nÅ“uds du réseau ont annulé).<br/>Vous devez <a ng-click=\"doQuickFix('fixMembership')\">envoyer une nouvelle demande</a> pour résoudre ce problème.", "WALLET_IDENTITY_EXPIRED": "La publication de <b>votre identité a expirée</b>.<br/>Vous devez <a ng-click=\"doQuickFix('fixIdentity')\">publier à nouveau votre identité</a> pour résoudre ce problème.", - "WALLET_REVOKED": "Votre identité a été <b>révoquée</b> : ni votre pseudonyme ni votre clef publique ne pourront être utilisés à l'avenir pour un compte membre.", + "WALLET_REVOKED": "Votre identité a été <b>révoquée</b> : ni votre pseudonyme ni votre clef publique ne pourra être utilisé à l'avenir pour un compte membre.", "WALLET_HAS_NO_SELF": "Votre identité doit d'abord avoir été publiée, et ne pas être expirée.", "AUTH_REQUIRED": "Authentification requise.", "AUTH_INVALID_PUBKEY": "La clef attendue est <i class=\"ion-key\"></i> {{pubkey|formatPubkey}}...", "AUTH_INVALID_SCRYPT": "Identifiant ou mot de passe invalide.", "AUTH_INVALID_FILE": "Fichier de trousseau invalide.", - "AUTH_FILE_ERROR": "Echec de l'ouverture du fichier de trousseau", + "AUTH_FILE_ERROR": "Échec de l'ouverture du fichier de trousseau.", "IDENTITY_ALREADY_CERTIFY": "Vous avez <b>déjà certifié</b> cette identité.<br/><br/>Cette certification est encore valide (expiration {{expiresIn|formatDurationTo}}).", "IDENTITY_ALREADY_CERTIFY_PENDING": "Vous avez <b>déjà certifié</b> cette identité.<br/><br/>Cette certification est en attente de traitement (date limite de traitement {{expiresIn|formatDurationTo}}).", "UNABLE_TO_CERTIFY_TITLE": "Certification impossible", - "LOAD_NEWCOMERS_FAILED": "Echec du chargement des nouveaux membres.", - "LOAD_PENDING_FAILED": "Echec du chargement des inscriptions en attente.", + "LOAD_NEWCOMERS_FAILED": "Échec du chargement des nouveaux membres.", + "LOAD_PENDING_FAILED": "Échec du chargement des inscriptions en attente.", "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "Vous devez <b>être membre</b> pour pouvoir effectuer cette action.", + "ONLY_MEMBER_OR_WAS_MEMBER_CAN_EXECUTE_THIS_ACTION": "Vous devez <b>être membre (ou ancien membre)</b> pour pouvoir effectuer cette action.", "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "Vous devez avoir <b>publié votre identité</b> pour pouvoir effectuer cette action.", - "GET_BLOCK_FAILED": "Echec de la récupération du bloc", - "INVALID_BLOCK_HASH": "Bloc non trouvé (hash différent)", - "DOWNLOAD_REVOCATION_FAILED": "Echec du téléchargement du fichier de révocation.", - "REVOCATION_FAILED": "Echec de la révocation.", - "SALT_OR_PASSWORD_NOT_CONFIRMED": "Identifiant secret ou mot de passe incorrects", - "RECOVER_ID_FAILED": "Echec de la récupération des identifiants", - "LOAD_FILE_FAILED" : "Echec du chargement du fichier", - "NOT_VALID_REVOCATION_FILE": "Fichier de revocation non valide (mauvais format de fichier)", + "GET_BLOCK_FAILED": "Échec de la récupération du bloc.", + "INVALID_BLOCK_HASH": "Bloc non trouvé (hash différent).", + "DOWNLOAD_REVOCATION_FAILED": "Échec du téléchargement du fichier de révocation.", + "REVOCATION_FAILED": "Échec de la révocation.", + "SALT_OR_PASSWORD_NOT_CONFIRMED": "Identifiant secret ou mot de passe incorrect.", + "RECOVER_ID_FAILED": "Échec de la récupération des identifiants", + "LOAD_FILE_FAILED" : "Échec du chargement du fichier", + "NOT_VALID_REVOCATION_FILE": "Fichier de révocation non valide (mauvais format de fichier)", "NOT_VALID_SAVE_ID_FILE": "Fichier de récupération non valide (mauvais format de fichier)", "NOT_VALID_KEY_FILE": "Fichier de trousseau non valide (format non reconnu)", "EXISTING_ACCOUNT": "Vos identifiants correspondent à un compte déjà existant, dont la <a ng-click=\"showHelpModal('pubkey')\">clef publique</a> est :", "EXISTING_ACCOUNT_REQUEST": "Veuillez modifier vos identifiants afin qu'ils correspondent à un compte non utilisé.", - "GET_LICENSE_FILE_FAILED": "Récupérer du fichier de licence impossible", - "CHECK_NETWORK_CONNECTION": "Aucun nÅ“ud ne semble accessible.<br/><br/>Veuillez <b>vérifier votre connection Internet</b>.", - "ISSUE_524_TX_FAILED": "Echec du virement.<br/><br/>Un message a été envoyé aux développeurs pour faciliter la résolution du problème. <b>Merci de votre aide</b>." + "GET_LICENSE_FILE_FAILED": "Récupération du fichier de licence impossible.", + "CHECK_NETWORK_CONNECTION": "Aucun nÅ“ud ne semble accessible.<br/><br/>Veuillez <b>vérifier votre connexion Internet</b>.", + "ISSUE_524_TX_FAILED": "Échec du virement.<br/><br/>Un message a été envoyé aux développeurs pour faciliter la résolution du problème. <b>Merci de votre aide</b>.", + "ADD_SECONDARY_WALLET_FAILED": "Échec de l'ajout du portefeuille secondaire.", + "UPDATE_WALLET_LIST_FAILED": "Échec du rafraîchissement des portefeuilles secondaires.", + "LOAD_WALLET_LIST_FAILED": "Échec du chargement des portefeuilles secondaires.", + "SAVE_WALLET_LIST_FAILED": "Échec de la sauvegarde des portefeuilles secondaires.", + "COULD_NOT_ADD_MAIN_WALLET": "Ce portefeuille <b>correspond au compte principal</b> avec lequel vous êtes connecté.<br/>Impossible de l'ajouter comme portefeuille secondaire.", + "COULD_NOT_ADD_EXISTING_WALLET": "Portefeuille déjà existant dans la liste.", + "UNKNOWN_WALLET_ID": "Portefeuille secondaire inconnu.", + "RESTORE_WALLET_LIST_FAILED": "Échec de la restauration des portefeuilles secondaires.", + "INVALID_FILE_FORMAT": "Format de fichier invalide.", + "SAME_TX_RECIPIENT": "Le destinataire doit être différent de l'émetteur." }, "INFO": { "POPUP_TITLE": "Information", @@ -3206,9 +4608,10 @@ $translateProvider.translations("fr-FR", { "COPY_TO_CLIPBOARD_DONE": "Copié dans le presse-papier", "MEMBERSHIP_OUT_SENT": "Résiliation envoyée", "NOT_NEED_MEMBERSHIP": "Vous êtes déjà membre.", - "IDENTITY_WILL_MISSING_CERTIFICATIONS": "Cette identité va bientôt manquer de certification (au moins {{willNeedCertificationCount}}).", - "IDENTITY_NEED_MEMBERSHIP": "Cette identité n'a pas envoyée de demande d'adhésion. Elle devra si elle souhaite devenir membre.", - "REVOCATION_SENT": "Revocation envoyée", + "IDENTITY_WILL_MISSING_CERTIFICATIONS": "Cette identité va bientôt manquer de certifications (au moins {{willNeedCertificationCount}}).", + "IDENTITY_NEED_MEMBERSHIP": "Cette identité n'a pas envoyée de demande d'adhésion. Elle le devra si elle souhaite devenir membre.", + "HAS_ALTERNATIVE_IDENTITIES": "Il existe <b>plusieurs identités</b> rattachées à cette clé publique. <b>Avant toute certification</b>, pensez à <a ng-click=\"doQuickFix('showSelectIdentities')\">consulter les autres identités</a> pour choisir la bonne, ou bien contacter le propriétaire du compte.", + "REVOCATION_SENT": "Révocation envoyée", "REVOCATION_SENT_WAITING_PROCESS": "La <b>révocation de cette identité</b> a été demandée et est en attente de traitement.", "FEATURES_NOT_IMPLEMENTED": "Cette fonctionnalité est encore en cours de développement.<br/>Pourquoi ne pas <b>contribuer à Cesium</b>, pour l'obtenir plus rapidement ? ;)", "EMPTY_TX_HISTORY": "Aucune opération à exporter" @@ -3218,24 +4621,27 @@ $translateProvider.translations("fr-FR", { "POPUP_WARNING_TITLE": "<b>Avertissement</b>", "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Avertissement de sécurité</b>", "CERTIFY_RULES_TITLE_UID": "Certifier {{uid}}", - "CERTIFY_RULES": "<b class=\"assertive\">Ne PAS certifier</b> un compte si vous pensez que :<br/><br/><ul><li>1.) il ne correspond pas à une personne <b>physique et vivante</b>.<li>2.) son propriétaire <b>possède un autre compte</b> déjà certifié.<li>3.) son propriétaire viole (volontairement ou non) la règle 1 ou 2 (par exemple en certifiant des comptes factices ou en double).</ul><br/><b>Etes-vous sûr</b> de vouloir néanmoins certifier cette identité ?", - "TRANSFER": "<b>Récapitulatif du virement</b> :<br/><br/><ul><li> - De : {{from}}</li><li> - A : <b>{{to}}</b></li><li> - Montant : <b>{{amount}} {{unit}}</b></li><li> - Commentaire : <i>{{comment}}</i></li></ul><br/><b>Etes-vous sûr de vouloir effectuer ce virement ?</b>", - "MEMBERSHIP_OUT": "Cette opération est <b>irréversible</b>.<br/></br/>Etes-vous sûr de vouloir <b>résilier votre compte membre</b> ?", - "MEMBERSHIP_OUT_2": "Cette opération est <b>irreversible</b> !<br/><br/>Etes-vous vraiment sûr de vouloir <b>résilier votre adhésion</b> comme membre ?", + "CERTIFY_RULES": "<b class=\"assertive\">Ne PAS certifier</b> un compte si vous pensez que :<br/><br/><ul><li>1.) il ne correspond pas à une personne <b>physique et vivante</b>.<li>2.) son propriétaire <b>possède un autre compte</b> déjà certifié.<li>3.) son propriétaire viole (volontairement ou non) la règle 1 ou 2 (par exemple en certifiant des comptes factices ou en double).</ul><br/><b>Êtes-vous sûr</b> de vouloir néanmoins certifier cette identité ?", + "FULLSCREEN": "Afficher l'application en plein écran ?", + "EXIT_APP": "Fermer l'application ?", + "TRANSFER": "<b>Récapitulatif du virement</b> :<br/><br/><ul><li> - De : {{from}}</li><li> - A : <b>{{to}}</b></li><li> - Montant : <b>{{amount}} {{unit}}</b></li><li> - Commentaire : <i>{{comment}}</i></li></ul><br/><b>Êtes-vous sûr de vouloir effectuer ce virement ?</b>", + "TRANSFER_ALL": "<b>Récapitulatif du virement</b> :<br/><br/><ul><li> - De : {{from}}</li><li> - A : <b>{{to}}</b></li><li> - Montant : <b>{{amount}} {{unit}}</b></li><li> - Commentaire : <i>{{comment}}</i></li><br/><li> - Reste : <b>{{restAmount}} {{unit}}</b> à <b>{{restTo}}</b></li></ul><br/><b>Êtes-vous sûr de vouloir effectuer ce virement ?</b>", + "MEMBERSHIP_OUT": "Cette opération est <b>irréversible</b>.<br/></br/>Êtes-vous sûr de vouloir <b>résilier votre compte membre</b> ?", + "MEMBERSHIP_OUT_2": "Cette opération est <b>irreversible</b> !<br/><br/>Êtes-vous vraiment sûr de vouloir <b>résilier votre adhésion</b> comme membre ?", "LOGIN_UNUSED_WALLET_TITLE": "Erreur de saisie ?", "LOGIN_UNUSED_WALLET": "Le compte connecté semble <b>inactif</b>.<br/><br/>Il s'agit probablement d'une <b>erreur de saisie</b> dans vos identifiants de connexion. Veuillez recommencer, en vérifiant que <b>la clé publique est celle de votre compte</b>.", - "FIX_IDENTITY": "Le pseudonyme <b>{{uid}}</b> va être publiée à nouveau, en remplacement de l'ancienne publication qui a expirée.<br/></br/><b>Etes-vous sûr</b> de vouloir continuer ?", - "FIX_MEMBERSHIP": "Votre demande d'adhésion comme membre va être renvoyée.<br/></br/><b>Etes-vous sûr</b> de vouloir continuer ?", - "MEMBERSHIP": "Votre demande d'adhésion comme membre va être envoyée.<br/></br/><b>Etes-vous sûr</b> de vouloir continuer ?", - "RENEW_MEMBERSHIP": "Votre adhésion comme membre va être renouvellée.<br/></br/><b>Etes-vous sûr</b> de vouloir continuer ?", - "REVOKE_IDENTITY": "Vous allez <b>revoquer définitivement cette identité</b>.<br/><br/>La clé publique et le pseudonyme associés <b>ne pourront plus jamais être utilisés</b> (pour un compte membre). <br/></br/><b>Etes-vous sûr</b> de vouloir révoquer définitivement ce compte ?", - "REVOKE_IDENTITY_2": "Cette opération est <b>irreversible</b> !<br/><br/>Etes-vous vraiment sûr de vouloir <b>révoquer définitivement</b> ce compte ?", - "NOT_NEED_RENEW_MEMBERSHIP": "Votre adhésion n'a pas besoin d'être renouvellée (elle n'expirera que dans {{membershipExpiresIn|formatDuration}}).<br/></br/><b>Etes-vous sûr</b> de vouloir renouveler votre adhésion ?", + "FIX_IDENTITY": "Le pseudonyme <b>{{uid}}</b> va être publiée à nouveau, en remplacement de l'ancienne publication qui a expirée.<br/></br/><b>Êtes-vous sûr</b> de vouloir continuer ?", + "FIX_MEMBERSHIP": "Votre demande d'adhésion comme membre va être renvoyée.<br/></br/><b>Êtes-vous sûr</b> de vouloir continuer ?", + "MEMBERSHIP": "Votre demande d'adhésion comme membre va être envoyée.<br/></br/><b>Êtes-vous sûr</b> de vouloir continuer ?", + "RENEW_MEMBERSHIP": "Votre adhésion comme membre va être renouvelée.<br/></br/><b>Êtes-vous sûr</b> de vouloir continuer ?", + "REVOKE_IDENTITY": "Vous allez <b>revoquer définitivement cette identité</b>.<br/><br/>La clé publique et le pseudonyme associés <b>ne pourront plus jamais être utilisés</b> (pour un compte membre). <br/></br/><b>Êtes-vous sûr</b> de vouloir révoquer définitivement ce compte ?", + "REVOKE_IDENTITY_2": "Cette opération est <b>irreversible</b> !<br/><br/>Êtes-vous vraiment sûr de vouloir <b>révoquer définitivement</b> ce compte ?", + "NOT_NEED_RENEW_MEMBERSHIP": "Votre adhésion n'a pas besoin d'être renouvelée (elle n'expirera que dans {{membershipExpiresIn|formatDuration}}).<br/></br/><b>Êtes-vous sûr</b> de vouloir renouveler votre adhésion ?", "SAVE_BEFORE_LEAVE": "Voulez-vous <b>sauvegarder vos modifications</b> avant de quitter la page ?", "SAVE_BEFORE_LEAVE_TITLE": "Modifications non enregistrées", - "LOGOUT": "Etes-vous sûr de vouloir vous déconnecter ?", + "LOGOUT": "Êtes-vous sûr de vouloir vous déconnecter ?", "USE_FALLBACK_NODE": "NÅ“ud <b>{{old}}</b> injoignable ou adresse invalide.<br/><br/>Voulez-vous temporairement utiliser le nÅ“ud <b>{{new}}</b> ?", - "ISSUE_524_SEND_LOG": "La transaction a été rejettée, à cause d'une anomalie connue (ticket #524) mais <b>non reproduite</b>.<br/><br/>Pour nous aider les développeurs à corriger cette erreur, <b>acceptez-vous la transmission de vos logs</b> par message ?<br/><small>(Aucune donnée confidentielle n'est envoyée)</small>." + "ISSUE_524_SEND_LOG": "La transaction a été rejetée, à cause d'une anomalie connue (ticket #524) mais <b>non reproduite</b>.<br/><br/>Pour aider les développeurs à corriger cette erreur, <b>acceptez-vous la transmission de vos logs</b> par message ?<br/><small>(aucune donnée confidentielle n'est envoyée)</small>." }, "DOWNLOAD": { "POPUP_TITLE": "<b>Fichier de révocation</b>", @@ -3245,27 +4651,31 @@ $translateProvider.translations("fr-FR", { "TITLE": "Aide en ligne", "JOIN": { "SECTION": "Inscription", - "SALT": "L'identifiant secret est très important. Il sert à mélanger le mot de passe, avant qu'il ne servent à calculer la <span class=\"text-italic\">clé publique</span> de votre compte (son numéro) et la clé secrète pour y accéder.<br/><b>Veuillez à bien la mémoriser</b>, car aucun moyen n'est actuellement prévu pour la retrouver en cas de perte.<br/>Par ailleurs, il ne peut pas être modifié sans devoir créer un nouveau compte.<br/><br/>Un bon identifiant secret doit être suffisamment long (au moins 8 caractères) et le plus original possible.", - "PASSWORD": "Le mot de passe est très important. Avec l'identifiant secret, il sert à à calculer le numéro (la clé publique) de votre compte, et la clé secrète pour y accéder.<br/><b>Veuillez à bien le mémoriser</b>, car aucun moyen n'est de le retrouver en cas de perte (sauf à générer un fichier de sauvegarde).<br/>Par ailleurs, il ne peut pas être modifié sans devoir créer un nouveau compte.<br/><br/>Un bon mot de passe contient (idéalement) au moins 8 caractères, dont au moins une majuscule et un chiffre.", - "PSEUDO": "Le pseudonyme utilisé uniquement dans le cas d'inscription comme <span class=\"text-italic\">membre</span>. Il est toujours associé à un portefeuille (via sa <span class=\"text-italic\">clé publique</span>).<br/>Il est publié sur le réseau, afin que les autres utilisateurs puisse l'identifier, le certifier ou envoyer de la monnaie sur le compte.<br/>Un pseudonyme doit être unique au sein des membres (<u>actuels</u> et anciens)." + "SALT": "L'identifiant secret est très important. Il sert à mélanger le mot de passe, avant qu'il ne serve à calculer la <span class=\"text-italic\">clé publique</span> de votre compte (son numéro) et la clé secrète pour y accéder.<br/><b>Veillez à bien la mémoriser</b>, car aucun moyen n'est actuellement prévu pour la retrouver en cas de perte.<br/>Par ailleurs, il ne peut pas être modifié sans devoir créer un nouveau compte.<br/><br/>Un bon identifiant secret doit être suffisamment long (au moins 8 caractères) et le plus original possible.", + "PASSWORD": "Le mot de passe est très important. Avec l'identifiant secret, il sert à calculer le numéro (la clé publique) de votre compte, et la clé secrète pour y accéder.<br/><b>Veillez à bien le mémoriser</b>, car aucun moyen n'est prévu de le retrouver en cas de perte (sauf à générer un fichier de sauvegarde).<br/>Par ailleurs, il ne peut pas être modifié sans devoir créer un nouveau compte.<br/><br/>Un bon mot de passe contient (idéalement) au moins 8 caractères, dont au moins une majuscule et un chiffre.", + "PSEUDO": "Le pseudonyme est utilisé uniquement dans le cas d'inscription comme <span class=\"text-italic\">membre</span>. Il est toujours associé à un portefeuille (via sa <span class=\"text-italic\">clé publique</span>).<br/>Il est publié sur le réseau, afin que les autres utilisateurs puisse l'identifier, le certifier ou envoyer de la monnaie sur le compte.<br/>Un pseudonyme doit être unique au sein des membres (<u>actuels</u> et anciens)." }, "LOGIN": { "SECTION": "Connexion", "PUBKEY": "Clé publique du trousseau", "PUBKEY_DEF": "La clef publique du trousseau est générée à partir des identifiants saisis (n'importe lesquels), sans pour autant qu'ils correspondent à un compte déjà utilisé.<br/><b>Vérifiez attentivement que la clé publique est celle de votre compte</b>. Dans le cas contraire, vous serez connecté à un compte probablement jamais utilisé, le risque de collision avec un compte existant étant infime.<br/><a href=\"https://fr.wikipedia.org/wiki/Cryptographie_asym%C3%A9trique\" target=\"_system\">En savoir plus sur la cryptographie</a> par clé publique.", "METHOD": "Méthodes de connexion", - "METHOD_DEF": "Plusieurs options sont disponibles pour vous connecter à un portfeuille :<br/> - La connexion <b>par sallage (simple ou avancé)</b> mélange votre mot de passe grâce à l'identifiant secret, pour limiter les tentatives de <a href=\"https://fr.wikipedia.org/wiki/Attaque_par_force_brute\" target=\"_system\">piratage par force brute</a> (par exemple à partir de mots connus).<br/> - La connexion <b>par clé publique</b> évite de saisir vos identifiants, qui vous seront demandé seulement le moment venu lors d'une opération sur le compte.<br/> - La connexion <b>par fichier de trousseau</b> va lire les clés (publique et privée) du compte, depuis un fichier, sans besoin de saisir d'identifiants. Plusieurs formats de fichier sont possibles." + "METHOD_DEF": "Plusieurs options sont disponibles pour vous connecter à un portefeuille :<br/> - La connexion <b>par salage (simple ou avancé)</b> mélange votre mot de passe grâce à l'identifiant secret, pour limiter les tentatives de <a href=\"https://fr.wikipedia.org/wiki/Attaque_par_force_brute\" target=\"_system\">piratage par force brute</a> (par exemple à partir de mots connus).<br/> - La connexion <b>par clé publique</b> évite de saisir vos identifiants, qui vous seront demandé seulement le moment venu lors d'une opération sur le compte.<br/> - La connexion <b>par fichier de trousseau</b> va lire les clés (publique et privée) du compte, depuis un fichier, sans besoin de saisir d'identifiants. Plusieurs formats de fichier sont possibles." }, "GLOSSARY": { "SECTION": "Glossaire", "PUBKEY_DEF": "Une clé publique identifie un portefeuille de monnaie, qui peut identifier un membre ou correspondre à un portefeuille anonyme. Dans Cesium la clé publique est calculée (par défaut) grâce à l'identifiant secret et au mot de passe.<br/><a href=\"https://fr.wikipedia.org/wiki/Cryptographie_asym%C3%A9trique\" target=\"_system\">En savoir plus sur la cryptographie</a> par clé publique.", "MEMBER": "Membre", - "MEMBER_DEF": "Un membre est une personne humaine physique et vivante, désireuse de participer librement à la communauté monétaire. Elle percoit un dividende universel, suivant une période et un montant tels que définis dans les <span class=\"text-italic\">règles de la monnaie</span>", + "MEMBER_DEF": "Un membre est une personne humaine physique et vivante, désireuse de participer librement à la communauté monétaire. Elle co-produit un dividende universel, suivant une période et un montant tels que définis dans les <span class=\"text-italic\">règles de la monnaie</span>", "CURRENCY_RULES": "Règles de la monnaie", - "CURRENCY_RULES_DEF": "Les règles de la monnaie sont définies une fois pour toute. Elle fixe le fonctionnement de la monnaie : le calcul du dividend universel, le nombre de certifications nécessaire pour être membre, le nombre de certification maximum qu'un membre peut donner, etc. <a href=\"#/app/currency\">Voir les règles actuelles</a>.<br/>La non modification des règles dans le temps est possible par l'utilisation d'une <span class=\"text-italic\">BlockChain</span> qui porte et execute ces règles, et en vérifie constamment la bonne application.", + "CURRENCY_RULES_DEF": "Les règles de la monnaie sont définies une fois pour toutes. Elle fixe le fonctionnement de la monnaie : le calcul du dividende universel, le nombre de certifications nécessaire pour être membre, le nombre de certification maximum qu'un membre peut donner, etc. <a href=\"#/app/currency\">Voir les règles actuelles</a>.<br/>La non modification des règles dans le temps est possible par l'utilisation d'une <span class=\"text-italic\">BlockChain</span> qui porte et exécute ces règles, et en vérifie constamment la bonne application.", "BLOCKCHAIN": "Chaîne de blocs (<span class=\"text-italic\">Blockchain</span>)", - "BLOCKCHAIN_DEF": "La BlockChain est un système décentralisé, qui, dans le cas de Duniter, sert à porter et executer les <span class=\"text-italic\">règles de la monnaie</span>.<br/><a href=\"https://duniter.org/fr/comprendre/\" target=\"_system\">En savoir plus sur Duniter</a> et le fonctionnement de sa blockchain.", - "UNIVERSAL_DIVIDEND_DEF": "Le Dividende Universel (DU) est la quantité de monnaie co-créée par chaque membre, suivant la période et le calcul définie dans les <span class=\"text-italic\">règles de la monnaie</span>.<br/>A chaque échéance, les membres recoivent sur leur compte la meme quantité de nouvelle monnaie.<br/><br/>Le DU subit une croissance régulière, pour rester juste entre les membres (actuels et à venir), calculée en fonction de l'espérance de vie moyenne, telle que démontré dans la Thérorie Relative de la Monnaie (TRM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">En savoir plus sur la TRM</a> et les monnaies libres." + "BLOCKCHAIN_DEF": "La BlockChain est un système décentralisé, qui, dans le cas de Duniter, sert à porter et exécuter les <span class=\"text-italic\">règles de la monnaie</span>.<br/><a href=\"https://duniter.org/fr/comprendre/\" target=\"_system\">En savoir plus sur Duniter</a> et le fonctionnement de sa blockchain.", + "UNIVERSAL_DIVIDEND_DEF": "Le Dividende Universel (DU) est la quantité de monnaie co-créée par chaque membre, suivant la période et le calcul définis dans les <span class=\"text-italic\">règles de la monnaie</span>.<br/>A chaque échéance, les membres recoivent sur leur compte la meme quantité de nouvelle monnaie.<br/><br/>Le DU subit une croissance régulière, pour rester juste entre les membres (actuels et à venir), calculée en fonction de l'espérance de vie moyenne, telle que démontré dans la Thérorie Relative de la Monnaie (TRM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">En savoir plus sur la TRM</a> et les monnaies libres.", + "WOT": "Toile de Confiance (TdC)", + "WOT_DEF": "La Toile de Confiance est constituée de l'ensemble des membres de la monnaie, et des liens de certification qui les relient.", + "DISTANCE_RULE": "Règle de distance", + "DISTANCE_RULE_DEF": "La règle de distance de la Toile de Confiance définie <b>une distance maximale à respecter</b> entre un postulant et un nombre minimum de membres référents (ou membres centraux). Cette distance est calculée en utilisant les liens de certification." }, "TIP": { "MENU_BTN_CURRENCY": "Le menu <b>{{'MENU.CURRENCY'|translate}}</b> permet la consultation des <b>règles de la monnaie</b> et de son état.", @@ -3273,11 +4683,11 @@ $translateProvider.translations("fr-FR", { "CURRENCY_MASS": "Suivez ici la <b>quantité totale de monnaie</b> existante et sa <b>répartition moyenne</b> par membre.<br/><br/>Ceci permet de juger de l'<b>importance d'un montant</b>, vis à vis de ce que <b>possède les autres</b> sur leur compte (en moyenne).", "CURRENCY_UNIT_RELATIVE": "L'unité utilisée (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) signifie que les montants en {{currency|capitalize}} ont été divisés par le <b>Dividende Universel</b> (DU).<br/><br/><small>Cette unité relative est <b>pertinente</b>, car stable malgré la quantitié de monnaie qui augmente en permanence.</small>", "CURRENCY_CHANGE_UNIT": "L'option <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> permet de <b>changer d'unité</b>, pour visualiser les montants <b>directement en {{currency|capitalize}}</b> (plutôt qu'en “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”).", - "CURRENCY_CHANGE_UNIT_TO_RELATIVE": "L'option <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> permet de <b>changer d'unité</b>, pour visualiser les montants en “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”, c'est à dire relativement au Dividende Universel (le montant co-produit par chaque membre).", + "CURRENCY_CHANGE_UNIT_TO_RELATIVE": "L'option <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> permet de <b>changer d'unité</b>, pour visualiser les montants en “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”, c'est-à -dire relativement au Dividende Universel (le montant co-produit par chaque membre).", "CURRENCY_RULES": "Les <b>règles</b> de la monnaie fixent son fonctionnement <b>exact et prévisible</b>.<br/><br/>Véritable ADN de la monnaie, elles rendent son code monétaire <b>lisible et transparent</b>.", "MENU_BTN_NETWORK": "Le menu <b>{{'MENU.NETWORK'|translate}}</b> permet la consultation de l'état du réseau.", - "NETWORK_BLOCKCHAIN": "Toutes les opérations de la monnaie sont enregistrées dans un grand livre de compte <b>public et infalsifiable</b>, appellé aussi <b>chaine de blocs</b> (<em>BlockChain</em> en anglais).", - "NETWORK_PEERS": "Les <b>nÅ“uds</b> visibles ici correspondent aux <b>ordinateurs qui actualisent et contrôlent</b> la chaine de blocs.<br/><br/>Plus il y a de nÅ“uds, plus la monnaie à une gestion <b>décentralisée</b> et digne de confiance.", + "NETWORK_BLOCKCHAIN": "Toutes les opérations de la monnaie sont enregistrées dans un grand livre de compte <b>public et infalsifiable</b>, appelé aussi <b>chaine de blocs</b> (<em>BlockChain</em> en anglais).", + "NETWORK_PEERS": "Les <b>nÅ“uds</b> visibles ici correspondent aux <b>ordinateurs qui actualisent et contrôlent</b> la chaine de blocs.<br/><br/>Plus il y a de nÅ“uds, plus la monnaie a une gestion <b>décentralisée</b> et digne de confiance.", "NETWORK_PEERS_BLOCK_NUMBER": "Ce <b>numéro</b> (en vert) indique le <b>dernier bloc validé</b> pour ce nÅ“ud (dernière page écrite dans le grand livre de comptes).<br/><br/>La couleur verte indique que ce bloc est également validé par <b>la plupart des autres nÅ“uds</b>.", "NETWORK_PEERS_PARTICIPATE": "<b>Chaque membre</b>, équipé d'un ordinateur avec Internet, <b>peut participer en ajoutant un nÅ“ud</b>. Il suffit d'<b>installer le logiciel Duniter</b> (libre et gratuit). <a href=\"{{installDocUrl}}\" target=\"_system\">Voir le manuel d'installation >></a>.", "MENU_BTN_ACCOUNT": "Le menu <b>{{'ACCOUNT.TITLE'|translate}}</b> permet d'accéder à la gestion de votre compte.", @@ -3289,25 +4699,25 @@ $translateProvider.translations("fr-FR", { "WALLET_BALANCE_RELATIVE": "{{'HELP.TIP.WALLET_BALANCE'|translate}}<br/><br/>L'unité utilisée (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) signifie que le montant en {{currency|capitalize}} a été divisé par le <b>Dividende Universel</b> (DU) co-créé par chaque membre.<br/><br/>Actuellement 1 DU vaut {{currentUD|formatInteger}} {{currency|capitalize}}s.", "WALLET_BALANCE_CHANGE_UNIT": "Vous pourrez <b>changer l'unité</b> d'affichage des montants dans les <b><i class=\"icon ion-android-settings\"></i> {{'MENU.SETTINGS'|translate}}</b>.<br/><br/>Par exemple pour visualiser les montants <b>directement en {{currency|capitalize}}</b>, plutôt qu'en unité relative.", "WALLET_PUBKEY": "Voici la clé publique de votre compte. Vous pouvez la communiquer à un tiers afin qu'il identifie plus simplement votre compte.", - "WALLET_SEND": "Effectuer un paiement en quelques clics", + "WALLET_SEND": "Effectuer un paiement en quelques clics.", "WALLET_SEND_NO_MONEY": "Effectuer un paiement en quelques clics.<br/>(Votre solde ne le permet pas encore)", "WALLET_OPTIONS": "Ce bouton permet l'accès aux <b>actions d'adhésion</b> et de sécurité.<br/><br/>N'oubliez pas d'y jeter un oeil !", "WALLET_RECEIVED_CERTS": "S'affichera ici la liste des personnes qui vous ont certifié.", - "WALLET_CERTIFY": "Le bouton <b>{{'WOT.BTN_SELECT_AND_CERTIFY'|translate}}</b> permet de sélectionner une identitié et de la certifier.<br/><br/>Seuls des utilisateurs <b>déjà membre</b> peuvent en certifier d'autres.", - "WALLET_CERT_STOCK": "Votre stock de certification (émises) est limité à <b>{{sigStock}} certifications</b>.<br/><br/>Ce stock se renouvelle avec le temps, au fur et à mesure que les certifications s'invalident.", + "WALLET_CERTIFY": "Le bouton <b>{{'WOT.BTN_SELECT_AND_CERTIFY'|translate}}</b> permet de sélectionner une identité et de la certifier.<br/><br/>Seuls des utilisateurs <b>déjà membres</b> peuvent en certifier d'autres.", + "WALLET_CERT_STOCK": "Votre stock de certifications (émises) est limité à <b>{{sigStock}} certifications</b>.<br/><br/>Ce stock se renouvelle avec le temps, au fur et à mesure que les certifications s'invalident.", "MENU_BTN_TX_MEMBER": "Le menu <b>{{'MENU.TRANSACTIONS'|translate}}</b> permet de consulter votre solde, l'historique vos transactions et d'envoyer un paiement.", - "MENU_BTN_TX": "Consultez ici <b>l'historique de vos transactions</b> et effectuer de nouvelles opérations.", - "MENU_BTN_WOT": "Le menu <b>{{'MENU.WOT'|translate}}</b> permet de rechercher parmi les <b>utilisateurs</b> de la monnaie (membre ou non).", + "MENU_BTN_TX": "Consultez ici <b>l'historique de vos transactions</b> et effectuez de nouvelles opérations.", + "MENU_BTN_WOT": "Le menu <b>{{'MENU.WOT'|translate}}</b> permet de rechercher parmi les <b>utilisateurs</b> de la monnaie (membres ou non).", "WOT_SEARCH_TEXT_XS": "Pour rechercher dans l'annuaire, tapez les <b>premières lettres d'un pseudonyme</b> (ou d'une clé publique).<br/><br/>La recherche se lancera automatiquement.", "WOT_SEARCH_TEXT": "Pour rechercher dans l'annuaire, tapez les <b>premières lettres d'un pseudonyme</b> (ou d'une clé publique). <br/><br/>Appuyer ensuite sur <b>Entrée</b> pour lancer la recherche.", "WOT_SEARCH_RESULT": "Visualisez la fiche détaillée simplement en <b>cliquant</b> sur une ligne.", - "WOT_VIEW_CERTIFICATIONS": "La ligne <b>{{'ACCOUNT.CERTIFICATION_COUNT'|translate}}</b> montre combien de membres ont validés cette identité.<br/><br/>Ces certifications attestent que le compte appartient à <b>une personne humaine vivante</b> n'ayant <b>aucun autre compte membre</b>.", + "WOT_VIEW_CERTIFICATIONS": "La ligne <b>{{'ACCOUNT.CERTIFICATION_COUNT'|translate}}</b> montre combien de membres ont validé cette identité.<br/><br/>Ces certifications attestent que le compte appartient à <b>une personne humaine vivante</b> n'ayant <b>aucun autre compte membre</b>.", "WOT_VIEW_CERTIFICATIONS_COUNT": "Il faut au moins <b>{{sigQty}} certifications</b> pour devenir membre et recevoir le <b>Dividende Universel</b>.", "WOT_VIEW_CERTIFICATIONS_CLICK": "Un clic ici permet d'ouvrir <b>la liste de toutes les certifications</b> de l'identité (reçues et émises).", "WOT_VIEW_CERTIFY": "Le bouton <b>{{'WOT.BTN_CERTIFY'|translate}}</b> permet d'ajouter votre certification à cette identité.", - "CERTIFY_RULES": "<b>Attention :</b> Ne certifier que des <b>personnes physiques vivantes</b>, ne possèdant aucun autre compte membre.<br/><br/>La sécurité de la monnaie dépend de la vigilance de chacun !", + "CERTIFY_RULES": "<b>Attention :</b> Ne certifiez que des <b>personnes physiques vivantes</b>, ne possédant aucun autre compte membre.<br/><br/>La sécurité de la monnaie dépend de la vigilance de chacun !", "MENU_BTN_SETTINGS": "Les <b>{{'MENU.SETTINGS'|translate}}</b> vous permettront de configurer l'application.", - "HEADER_BAR_BTN_PROFILE": "Cliquez ici pour accéder à votre <b>profil utilisateur</b>", + "HEADER_BAR_BTN_PROFILE": "Cliquez ici pour accéder à votre <b>profil utilisateur.</b>", "SETTINGS_CHANGE_UNIT": "Vous pourrez <b>changer d'unité d'affichage</b> des montants en cliquant ci-dessus.<br/><br/>- Désactivez l'option pour un affichage des montants en {{currency|capitalize}}.<br/>- Activez l'option pour un affichage relatif en {{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub> (tous les montants seront <b>divisés</b> par le Dividende Universel courant).", "END_LOGIN": "Cette visite guidée est <b>terminée</b> !<br/><br/>Bonne continuation à vous, dans le nouveau monde de l'<b>économie libre</b> !", "END_NOT_LOGIN": "Cette visite guidée est <b>terminée</b> !<br/><br/>Si vous souhaitez rejoindre la monnaie {{currency|capitalize}}, il vous suffira de cliquer sur <b>{{'LOGIN.CREATE_ACCOUNT'|translate}}</b> ci-dessous." @@ -3315,25 +4725,28 @@ $translateProvider.translations("fr-FR", { }, "API" :{ "COMMON": { - "LINK_DOC": "documentation API", + "LINK_DOC": "Documentation API", "LINK_DOC_HELP": "Documentation pour les développeurs", - "LINK_STANDARD_APP": "version classique", - "LINK_STANDARD_APP_HELP": "Ouvrir la version classique de {{'COMMON.APP_NAME'|translate}}" + "LINK_STANDARD_APP": "Version classique", + "LINK_STANDARD_APP_HELP": "Ouvrir la version classique de {{'COMMON.APP_NAME'|translate}}", + "CONNECTION_ERROR": "NÅ“ud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifiez votre connexion Internet, ou contactez l'administrateur du site</a>." }, "HOME": { "TITLE": "Documentation API {{'COMMON.APP_NAME'|translate}}", - "MESSAGE": "Bienvenue dans la <b>documentation de l'API</b> {{'COMMON.APP_NAME'|translate}}.<br/>Connecter vos sites web à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", - "MESSAGE_SHORT": "Connecter vos sites à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", + "MESSAGE": "Bienvenue dans la <b>documentation de l'API</b> {{'COMMON.APP_NAME'|translate}}.<br/>Connectez vos sites web à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", + "MESSAGE_SHORT": "Connectez vos sites à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", "DOC_HEADER": "Services disponibles :" }, "TRANSFER": { "TITLE": "{{'COMMON.APP_NAME'|translate}} - Paiement en ligne", "TITLE_SHORT": "Paiement en ligne", - "SUMMARY": "Récapitulatif de la commande :", + "SUMMARY": "Récapitulatif du paiement :", "AMOUNT": "Montant :", + "AMOUNTS_HELP": "Veuillez choisir le montant :", "NAME": "Nom :", - "PUBKEY": "Clé publique du destinaire :", - "COMMENT": "Référence de la commande :", + "PUBKEY": "Clé publique du destinataire :", + "COMMENT": "Référence de l'opération :", + "NODE": "Adresse du nÅ“ud :", "DEMO": { "SALT": "demo", "PASSWORD": "demo", @@ -3348,7 +4761,7 @@ $translateProvider.translations("fr-FR", { "CANCEL_REDIRECTING": "Paiement annulé.<br/>Redirection vers le site du vendeur..." }, "ERROR": { - "TRANSFER_FAILED": "Echec du paiement" + "TRANSFER_FAILED": "Échec du paiement" } }, "DOC": { @@ -3359,6 +4772,7 @@ $translateProvider.translations("fr-FR", { "DEMO_DIVIDER": "Tester", "DEMO_HELP": "Pour tester ce service, cliquez sur le bouton ci-contre. Le résultat s'affichera en dessous.", "DEMO_RESULT": "Résultat retourné par l'appel :", + "DEMO_RESULT_PEER": "Adresse du nÅ“ud utilisé :", "DEMO_SUCCEED": "<i class=\"icon ion-checkmark\"></i> Succès !", "DEMO_CANCELLED": "<i class=\"icon ion-close\"></i> Annulé par l'utilisateur", "INTEGRATE_DIVIDER": "Intégrer", @@ -3367,31 +4781,33 @@ $translateProvider.translations("fr-FR", { "INTEGRATE_PARAMETERS": "Paramètres", "TRANSFER": { "TITLE": "Paiements", - "DESCRIPTION": "Depuis un site (ex: vente en ligne) vous pouvez déléguer le paiement en monnaie libre à Cesium API. Pour cela, il vous suffit de déclencher l'ouveture d'un page sur l'adresse suivante :", + "DESCRIPTION": "Depuis un site (ex: vente en ligne) vous pouvez déléguer le paiement en monnaie libre à Cesium API. Pour cela, il vous suffit de déclencher l'ouverture d'une page sur l'adresse suivante :", "PARAM_PUBKEY": "Clé publique du destinataire", "PARAM_PUBKEY_HELP": "Clé publique du destinataire (obligatoire)", "PARAM_AMOUNT": "Montant", - "PARAM_AMOUNT_HELP": "Montant de la transaction (obligatoire)", + "PARAM_AMOUNT_HELP": "Montant de la transaction (obligatoire). Valeurs multiples autorisées, en utilisant un séparateur (point-virgule, barre verticale ou espace).", "PARAM_COMMENT": "Référence (ou commentaire)", "PARAM_COMMENT_HELP": "Référence ou commentaire. Vous permettra par exemple d'identifier le paiement dans la BlockChain.", "PARAM_NAME": "Nom (du destinataire ou du site web)", - "PARAM_NAME_HELP": "Le nom du destinataire, ou du site web appellant. Cela peut-etre un nom lisible (\"Mon site en ligne\"), ou encore une pseudo-adresse web (\"MonSite.com\").", + "PARAM_NAME_HELP": "Le nom du destinataire, ou du site web appelant. Cela peut être un nom lisible (\"Mon site en ligne\"), ou encore une pseudo-adresse web (\"MonSite.com\").", "PARAM_REDIRECT_URL": "Adresse web de redirection", - "PARAM_REDIRECT_URL_HELP": "Adresse web (URL) de redirection, appellé quand le paiement a été envoyé. Peut contenir les chaines suivantes, qui seront remplacée par les valeurs de la transaction : \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\" et {pubkey}.", + "PARAM_REDIRECT_URL_HELP": "Adresse web (URL) de redirection, appelé quand le paiement a été envoyé. Peut contenir les chaînes suivantes, qui seront remplacées par les valeurs de la transaction : \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\", \"{pubkey}\" et \"{node}\".", "PARAM_CANCEL_URL": "Adresse web d'annulation", - "PARAM_CANCEL_URL_HELP": "Adresse web (URL) en cas d'annulation du paiement, par l'utilisateur. Peut contenir les chaines suivantes, qui seront remplacée dynamiquement: \"{comment}\", \"{amount}\" et {pubkey}.", + "PARAM_CANCEL_URL_HELP": "Adresse web (URL) en cas d'annulation du paiement, par l'utilisateur. Peut contenir les chaînes suivantes, qui seront remplacées dynamiquement : \"{comment}\", \"{amount}\" et {pubkey}.", + "PARAM_PREFERRED_NODE": "Adresse du nÅ“ud préféré", + "PARAM_PREFERRED_NODE_HELP": "Adresse (URL) du nÅ“ud Duniter à utiliser de préférence (\"g1.domaine.com:443\" ou \"https://g1.domaine.com\").", "EXAMPLES_HELP": "Voici des exemples d'intégration :", "EXAMPLE_BUTTON": "Bouton HTML", "EXAMPLE_BUTTON_DEFAULT_TEXT": "Payer en {{currency|currencySymbol}}", "EXAMPLE_BUTTON_DEFAULT_STYLE": "Style personnalisé", "EXAMPLE_BUTTON_TEXT_HELP": "Texte du bouton", "EXAMPLE_BUTTON_BG_COLOR": "Couleur du fond", - "EXAMPLE_BUTTON_BG_COLOR_HELP": "Exemple: #fbc14c, black, lightgrey, rgb(180,180,180)", + "EXAMPLE_BUTTON_BG_COLOR_HELP": "Exemple : #fbc14c, black, lightgrey, rgb(180,180,180)", "EXAMPLE_BUTTON_FONT_COLOR": "Couleur du texte", - "EXAMPLE_BUTTON_FONT_COLOR_HELP": "Exemple: black, orange, rgb(180,180,180)", + "EXAMPLE_BUTTON_FONT_COLOR_HELP": "Exemple : black, orange, rgb(180,180,180)", "EXAMPLE_BUTTON_TEXT_ICON": "Icône", "EXAMPLE_BUTTON_TEXT_WIDTH": "Largeur", - "EXAMPLE_BUTTON_TEXT_WIDTH_HELP": "Exemple: 200px, 50%", + "EXAMPLE_BUTTON_TEXT_WIDTH_HELP": "Exemple : 200px, 50%", "EXAMPLE_BUTTON_ICON_NONE": "Aucune", "EXAMPLE_BUTTON_ICON_DUNITER": "Logo Duniter", "EXAMPLE_BUTTON_ICON_CESIUM": "Logo Cesium", @@ -3403,6 +4819,914 @@ $translateProvider.translations("fr-FR", { } ); +$translateProvider.translations("it-IT", { + "COMMON": { + "APP_NAME": "Cesium", + "APP_VERSION": "v{{version}}", + "APP_BUILD": "build {{build}}", + "PUBKEY": "Chiave privata", + "MEMBER": "Membro", + "BLOCK" : "Blocco", + "BTN_OK": "OK", + "BTN_YES": "Si", + "BTN_NO": "No", + "BTN_SEND": "Inviare", + "BTN_SEND_MONEY": "Trasferire soldi", + "BTN_SEND_MONEY_SHORT": "Trasferire", + "BTN_SAVE": "Salvare", + "BTN_YES_SAVE": "Si, salvare", + "BTN_YES_CONTINUE": "Si, continuare", + "BTN_SHOW": "Mostrare", + "BTN_SHOW_PUBKEY": "Mostrare chiave pubblica", + "BTN_RELATIVE_UNIT": "Mostra importi in DU?", + "BTN_BACK": "Indietro", + "BTN_NEXT": "Avanti", + "BTN_CANCEL": "Cancellare", + "BTN_CLOSE": "Chiudere", + "BTN_LATER": "Più tardi", + "BTN_LOGIN": "Accedi", + "BTN_LOGOUT": "Log out", + "BTN_ADD_ACCOUNT": "Nuovo conto", + "BTN_SHARE": "Condividere", + "BTN_EDIT": "Modificare", + "BTN_DELETE": "Eliminare", + "BTN_ADD": "Aggiungere", + "BTN_SEARCH": "Cercare", + "BTN_REFRESH": "Aggiornare", + "BTN_RETRY": "Riprovare", + "BTN_START": "Iniziare", + "BTN_CONTINUE": "Continuare", + "BTN_CREATE": "Creare", + "BTN_UNDERSTOOD": "Ho capito", + "BTN_OPTIONS": "Opzioni", + "BTN_HELP_TOUR": "Mostrami le funzionalità ", + "BTN_HELP_TOUR_SCREEN": "Scoprire questo schermo", + "BTN_DOWNLOAD": "Scaricare", + "BTN_DOWNLOAD_ACCOUNT_STATEMENT": "Scaricare estratto conto", + "BTN_MODIFY": "Modificare", + "CHOOSE_FILE": "Trascini un file <br/>o cliccare per selezionare", + "DAYS": "giorni", + "NO_ACCOUNT_QUESTION": "Non sei ancora membro? Registrati subito!", + "SEARCH_NO_RESULT": "Nessun risultato trovato", + "LOADING": "Caricando...", + "SEARCHING": "Cercando...", + "FROM": "Da", + "TO": "A", + "COPY": "Copiare", + "LANGUAGE": "Lingua", + "UNIVERSAL_DIVIDEND": "Dividendo universale", + "UD": "UD", + "DATE_PATTERN": "DD/MM/YYYY HH:mm", + "DATE_FILE_PATTERN": "YYYY-MM-DD", + "DATE_SHORT_PATTERN": "DD/MM/YY", + "DATE_MONTH_YEAR_PATTERN": "MM/YYYY", + "EMPTY_PARENTHESIS": "(empty)", + "UID": "Pseudonimo", + "ENABLE": "Attivato", + "DISABLE": "Disattivato", + "RESULTS_LIST": "Risultati:", + "RESULTS_COUNT": "{{count}} risultati", + "EXECUTION_TIME": "eeseguit in {{duration|formatDurationMs}}", + "SHOW_VALUES": "Mostrare valori in modo trasparente?", + "POPOVER_ACTIONS_TITLE": "Opzioni", + "POPOVER_FILTER_TITLE": "Filtri", + "SHOW_MORE": "Mostrare di più", + "SHOW_MORE_COUNT": "(limite attuale di {{limit}})", + "POPOVER_SHARE": { + "TITLE": "Condividere", + "SHARE_ON_TWITTER": "Condividere su Twitter", + "SHARE_ON_FACEBOOK": "Condividere su Facebook", + "SHARE_ON_DIASPORA": "Condividere su Diaspora*", + "SHARE_ON_GOOGLEPLUS":"Condividere su Google+" + }, + "FILE": { + "DATE" : "Data:", + "TYPE" : "Tipo:", + "SIZE": "Dimensioni del file:", + "VALIDATING": "Validazione in corso..." + } + }, + "SYSTEM": { + "PICTURE_CHOOSE_TYPE": "Scegliere un file:", + "BTN_PICTURE_GALLERY": "Galleria", + "BTN_PICTURE_CAMERA": "<b>Camera</b>" + }, + "MENU": { + "HOME": "Home", + "WOT": "Annuario", + "CURRENCY": "Moneta", + "ACCOUNT": "Mio conto", + "WALLETS": "I miei portafogli", + "TRANSFER": "Trasferire", + "SCAN": "Scansionare", + "SETTINGS": "Impostazioni", + "NETWORK": "Rete", + "TRANSACTIONS": "Miei pagamenti" + }, + "ABOUT": { + "TITLE": "A proposito", + "LICENSE": "<b>Free/libre software</b> (License GNU AGPLv3).", + "CODE": "Codice sorgente:", + "DEVELOPERS": "Sviluppatori:", + "FORUM": "Forum:", + "DEV_WARNING": "Attenzione!", + "DEV_WARNING_MESSAGE": "Questa app è ancora in sviluppo attivo.<br/>Facci sapere se trovi dei bugs!", + "DEV_WARNING_MESSAGE_SHORT": "Questa app è tutt'ora instabile (in sviluppo)", + "REPORT_ISSUE": "Segnalare un bug" + }, + "HOME": { + "TITLE": "Cesium", + "WELCOME": "Benvenuti nell'{{'COMMON.APP_NAME'|translate}} App!", + "MESSAGE": "Scambiate in moneta libera. {{currency|abbreviate}}!", + "BTN_CURRENCY": "Esplorare la moneta", + "BTN_ABOUT": "a proposito", + "BTN_HELP": "Aiuto", + "REPORT_ISSUE": "Segnalare un bug", + "NOT_YOUR_ACCOUNT_QUESTION" : "Non sei proprietario del conto <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b>?", + "BTN_CHANGE_ACCOUNT": "Disconettere questo conto", + "CONNECTION_ERROR": "Peer <b>{{server}}</b> irraggiungibile o indirizzo invalido. <br/><br/> Verifica tua connessione or cambia nodo. <a class=\"positive\" ng-click=\"doQuickFix('settings')\">nell impostazioni. </a>." + }, + "SETTINGS": { + "TITLE": "Impostazioni", + "NETWORK_SETTINGS": "Rete", + "PEER": "Indirizzo peer Duniter", + "PEER_CHANGED_TEMPORARY": "Indirizzo usato per un tempo determinato", + "USE_LOCAL_STORAGE": "Abilitare local storage", + "USE_LOCAL_STORAGE_HELP": "Permette di salvare tue impostazioni", + "ENABLE_HELPTIP": "Abilitare consigli dinamici", + "ENABLE_UI_EFFECTS": "Abilitare effetti visivi", + "HISTORY_SETTINGS": "Mio conto", + "DISPLAY_UD_HISTORY": "Mostrare dividendi prodotti?", + "AUTHENTICATION_SETTINGS": "Autenticazione", + "KEEP_AUTH": "Scadenza dell'autenticazione", + "KEEP_AUTH_SHORT": "Scadenza", + "KEEP_AUTH_HELP": "Definire quando l'autenticazione verrà eliminata dalla memoria.", + "KEEP_AUTH_OPTION": { + "NEVER": "Dopo ogni operazione", + "SECONDS": "Dopo {{value}}s d'inattività ", + "MINUTE": "Dopo{{value}}min d'inattività ", + "MINUTES": "Dopo {{value}}min d'inattività ", + "HOUR": "Dopo {{value}}h d'inattività ", + "ALWAYS": "Alla fine della sessione" + }, + "REMEMBER_ME": "Ricordarsi di me?", + "REMEMBER_ME_HELP": "Rimanere identificato/a da una sessione all'altra, conservando la chiave localmente.", + "PLUGINS_SETTINGS": "Estensioni", + "BTN_RESET": "Ripristini valori predefiniti", + "EXPERT_MODE": "Abilitare modlità eseperto", + "EXPERT_MODE_HELP": "Permette di vedere più dettagli", + "POPUP_PEER": { + "TITLE" : "Peer Duniter", + "HOST" : "Indirizzo", + "HOST_HELP": "Indirizzo: server:port", + "USE_SSL" : "Securizzato?", + "USE_SSL_HELP" : "(SSL Encryption)", + "BTN_SHOW_LIST" : "Lista dei peers" + } + }, + "BLOCKCHAIN": { + "HASH": "Hash: {{hash}}", + "VIEW": { + "HEADER_TITLE": "Blocco #{{number}}-{{hash|formatHash}}", + "TITLE_CURRENT": "Blocco attuale", + "TITLE": "Blocco #{{number|formatInteger}}", + "COMPUTED_BY": "Calcolato da", + "SHOW_RAW": "Mostrare dati grezzi", + "TECHNICAL_DIVIDER": "Informazioni tecniche", + "VERSION": "Versione di formatto", + "HASH": "Hash calcolato", + "UNIVERSAL_DIVIDEND_HELP": "Moneta co-prodotta da ciasciun dei {{membersCount}} membri", + "EMPTY": "Nessun dati in questo blocco", + "POW_MIN": "Difficoltà minimale", + "POW_MIN_HELP": "Difficoltà imposta nel calcolo del hash", + "DATA_DIVIDER": "Dati", + "IDENTITIES_COUNT": "Nuove identità ", + "JOINERS_COUNT": "Nuovi membri", + "ACTIVES_COUNT": "Rinnovi", + "ACTIVES_COUNT_HELP": "Membri che hanno rinnovato la loro presenza nella rete", + "LEAVERS_COUNT": "", + "LEAVERS_COUNT_HELP": "Membri che si sono fatti escludere dalla rete", + "EXCLUDED_COUNT": "Membri esclusi", + "EXCLUDED_COUNT_HELP": "Vecchi membri, esclusi per certificazione non rinnovata o soglia di certificazioni non raggiunta.", + "REVOKED_COUNT": "Identità revocate", + "REVOKED_COUNT_HELP": "Può essere che questi conti non siano più attivi", + "TX_COUNT": "Transazioni", + "CERT_COUNT": "Certificazioni", + "TX_TO_HIMSELF": "Cambio", + "TX_OUTPUT_UNLOCK_CONDITIONS": "Sbloccare condizioni", + "TX_OUTPUT_OPERATOR": { + "AND": "e", + "OR": "o" + }, + "TX_OUTPUT_FUNCTION": { + "SIG": "<b>Firma</b> della chive pubblica", + "XHX": "<b>Password</b>, incluso SHA256 =", + "CSV": "Bloccato per", + "CLTV": "Bloccato fino a" + } + }, + "LOOKUP": { + "TITLE": "Blocchi", + "NO_BLOCK": "Nessun blocco", + "LAST_BLOCKS": "Ultimi blocchi:", + "BTN_COMPACT": "Compact" + } + }, + "CURRENCY": { + "VIEW": { + "TITLE": "Moneta", + "TAB_CURRENCY": "Moneta", + "TAB_WOT": "Web of trust", + "TAB_NETWORK": "Rete", + "TAB_BLOCKS": "Blocchi", + "CURRENCY_SHORT_DESCRIPTION": "{{currency|capitalize}} è <b>una moneta libera</b>, {{firstBlockTime | formatFromNow}}. La rete comprende <b>{{N}} membri </b>, che produccono e ricevono un <a ng-click=\"showHelpModal('ud')\">Dividendo Universale</a> (DU), ogni {{dt | formatPeriod}}.", + "NETWORK_RULES_DIVIDER": "Regole della rete", + "CURRENCY_NAME": "Nome della moneta", + "MEMBERS": "Numero di membri", + "MEMBERS_VARIATION": "Variazione da {{duration|formatDuration}} (dall' ultimo UD)", + "MONEY_DIVIDER": "Moneta", + "MASS": "Massa monetaria", + "SHARE": "Quantità a testa", + "UD": "Dividendo universale", + "C_ACTUAL": "Crescita attuale", + "MEDIAN_TIME": "Current blockchain time", + "POW_MIN": "Difficoltà commune", + "MONEY_RULES_DIVIDER": "Regole della moneta", + "C_RULE": "Obbietivo teorico di crescità ", + "UD_RULE": "Dividendo universale (formula)", + "DT_REEVAL": "Periodo tra due re-evaluazioni del UD", + "REEVAL_SYMBOL": "reeval", + "DT_REEVAL_VALUE": "Ogni <b>{{dtReeval|formatDuration}}</b> ({{dtReeval/86400}} {{'COMMON.DAYS'|translate}})", + "UD_REEVAL_TIME0": "Data della prima re-evaluzione del UD", + "SIG_QTY_RULE": "Numero di certificazioni requisiti per diventare membro", + "SIG_STOCK": "Numero massimo di certificazioni inviate da un membro", + "SIG_PERIOD": "Tempo minimo tra 2 certificazioni inviate da un unico membro.", + "SIG_WINDOW": "Periodo massimo prima che una certificazione venga studiata", + "SIG_VALIDITY": "Durata di vita di una certificazione che è state presa in conto", + "MS_WINDOW": "Periodo massimo prima che una certificazione pendente sia validata", + "MS_VALIDITY": "Durata di vita di un'adesione che è state presa in conto", + "STEP_MAX": "Distanza massima tra un nuovo membro e ogni membro referente.", + "WOT_RULES_DIVIDER": "Regole della Web of Trust", + "SENTRIES": "Numero di certificazioni (date <b>e</b> ricevute) per diventare membro referente ", + "SENTRIES_FORMULA": "Numero di certificazioni necessarie per diventare membro (formula)", + "XPERCENT":"Percentaggio minimino di membri referenti per rispettare la regola di distanza tra i membri", + "AVG_GEN_TIME": "Tempo medio tra due blocchi", + "CURRENT": "attuale", + "MATH_CEILING": "CEILING", + "DISPLAY_ALL_RULES": "Mostrare tutte le regole?", + "BTN_SHOW_LICENSE": "Mostrare licenza", + "WOT_DIVIDER": "Web of trust" + }, + "LICENSE": { + "TITLE": "Licensa attuale", + "BTN_DOWNLOAD": "Scaricare il file", + "NO_LICENSE_FILE": "File di licenza non trovato ." + } + }, + "NETWORK": { + "VIEW": { + "MEDIAN_TIME": "Blockchain time", + "LOADING_PEERS": "Caricando peers...", + "NODE_ADDRESS": "Indirizzo del peer", + "SOFTWARE": "Software", + "WARN_PRE_RELEASE": "Pre-versione (ultima versione stabile: <b>{{version}}</b>)", + "WARN_NEW_RELEASE": "Versione <b>{{version}}</b> disponibile", + "WS2PID": "Identificativo :", + "PRIVATE_ACCESS": "Accesso privato", + "POW_PREFIX": "Prefisso Prova di Lavoro :", + "ENDPOINTS": { + "BMAS": "Endpoint sicuro (SSL)", + "BMATOR": "Interfaccia rete TOR", + "WS2P": "Interfaccia WS2P", + "ES_USER_API": "Cesium+ data node" + } + }, + "INFO": { + "ONLY_SSL_PEERS": "I nodi non-SSL hanno un display semplificato perche Cesium funziona in modalità HTTPS." + } + }, + "PEER": { + "PEERS": "Peers-Nodi", + "SIGNED_ON_BLOCK": "Firmato nel blocco", + "MIRROR": "Specchio", + "MIRRORS": "Specchio", + "MIRROR_PEERS": "Peers specchio", + "PEER_LIST" : "Lista dei peers", + "MEMBERS" : "Membri", + "MEMBER_PEERS" : "Peers membri", + "ALL_PEERS" : "Tutti i peers", + "DIFFICULTY" : "Difficoltà ", + "API" : "API", + "CURRENT_BLOCK" : "Blocco #", + "POPOVER_FILTER_TITLE": "Filtro", + "OFFLINE": "Sconessi", + "OFFLINE_PEERS": "Peers sconessi", + "BTN_SHOW_PEER": "Mostrare peer", + "VIEW": { + "TITLE": "Peer", + "OWNER": "Proprietà di ", + "SHOW_RAW_PEERING": "Vedere il documento di peering", + "SHOW_RAW_CURRENT_BLOCK": "Vedere l'utimo blocco (formatto grezzo)", + "LAST_BLOCKS": "Ultimi blocchi", + "KNOWN_PEERS": "Peers conosciuti :", + "GENERAL_DIVIDER": "Informazioni generali", + "ERROR": { + "LOADING_TOR_NODE_ERROR": "Impossibile ottenere i dati del peer, periodo di attesa scaduto.", + "LOADING_NODE_ERROR": "Impossibile ottenere i dati del peer" + } + } + }, + "WOT": { + "SEARCH_HELP": "Cercare (membro o chiave pubblica)", + "SEARCH_INIT_PHASE_WARNING": "La ricerca per le certificazioni pendenti <b>può essere lunga</b> durante la fase di pre-certificazione. La preghiamo di attendere...", + "REGISTERED_SINCE": "Certificato/a dal", + "REGISTERED_SINCE_BLOCK": "Certificato/a dal blocco #", + "NO_CERTIFICATION": "Nessuna certificazione valida", + "NO_GIVEN_CERTIFICATION": "Nessuna certificazione data", + "NOT_MEMBER_PARENTHESIS": "(non-membro)", + "IDENTITY_REVOKED_PARENTHESIS": "(identità revocata)", + "MEMBER_PENDING_REVOCATION_PARENTHESIS": "(Cancellazione dell'identità pendente)", + "EXPIRE_IN": "Scade", + "NOT_WRITTEN_EXPIRE_IN": "Scadenza <br/> ", + "EXPIRED": "Scaduto", + "PSEUDO": "Pseudonimo", + "SIGNED_ON_BLOCK": "Emessa nel blocco #{{block}}", + "WRITTEN_ON_BLOCK": "Scritta nel blocco #{{block}}", + "GENERAL_DIVIDER": "Informazioni generali", + "NOT_MEMBER_ACCOUNT": "Conto non-membro", + "NOT_MEMBER_ACCOUNT_HELP": "Questo è un semplice portafoglio osservatore, senza richiesta di certificazione emessa.", + "TECHNICAL_DIVIDER": "Dati tecnici", + "BTN_CERTIFY": "Certificare", + "BTN_YES_CERTIFY": "Si, certificare", + "BTN_SELECT_AND_CERTIFY": "Nuova certificazione", + "ACCOUNT_OPERATIONS": "Operazioni sul conto", + "VIEW": { + "POPOVER_SHARE_TITLE": "Identità {{title}}" + }, + "LOOKUP": { + "TITLE": "Annuario", + "NEWCOMERS": "Nuovi membri:", + "NEWCOMERS_COUNT": "{{count}} membri", + "PENDING": "Registrazioni pendenti", + "PENDING_COUNT": "{{count}} inscrizioni pendenti", + "REGISTERED": "Registrato {{sigDate | formatFromNow}}", + "MEMBER_FROM": "Membro dal {{memberDate|medianFromNowShort}}", + "BTN_NEWCOMERS": "Ultimi membri", + "BTN_PENDING": "Registrazioni pendenti", + "SHOW_MORE": "Vedere di più", + "SHOW_MORE_COUNT": "(limite attuale di {{limit}})", + "NO_PENDING": "Nessuna certificazione pendente.", + "NO_NEWCOMERS": "Nessun membro." + }, + "CONTACTS": { + "TITLE": "Contatti" + }, + "MODAL": { + "TITLE": "Ricerca" + }, + "CERTIFICATIONS": { + "TITLE": "{{uid}} - Certificazioni", + "SUMMARY": "Certificazioni ricevute", + "LIST": "Dettagli delle certificazioni ricevute", + "PENDING_LIST": "Certificazioni pendenti", + "RECEIVED": "Certificazioni ricevute", + "RECEIVED_BY": "Certifications ricevute da {{uid}}", + "ERROR": "Certificazioni ricevute per errore", + "SENTRY_MEMBER": "Membro referente" + }, + "OPERATIONS": { + "TITLE": "{{uid}} - Operazioni" + }, + "GIVEN_CERTIFICATIONS": { + "TITLE": "{{uid}} - Certificazioni inviate", + "SUMMARY": "Certificazioni inviate", + "LIST": "Dettagli delle certificazioni inviate", + "PENDING_LIST": "Certificazioni ", + "SENT": "Certificazioni inviate", + "SENT_BY": "Certificazioni inviate da {{uid}}", + "ERROR": "Certificazioni inviate per errore" + } + }, + "LOGIN": { + "TITLE": "<i class=\"icon ion-log-in\"></i> Accedi", + "SCRYPT_FORM_HELP": "Accedi con tuoi dati <br> Ricordati di verificare che stai utilizzando la chiave del tuo conto.", + "PUBKEY_FORM_HELP": "Scrivi qui la tua chiave privata:", + "FILE_FORM_HELP": "Scegliere un portachiavi da utilizzare:", + "SCAN_FORM_HELP": "Scansiona il codice QR di un portafoglio.", + "SALT": "Identificativo segreto", + "SALT_HELP": "Identificativo segreto", + "SHOW_SALT": "Mostrare identificativo segreto?", + "PASSWORD": "Passsord", + "PASSWORD_HELP": "Password", + "PUBKEY_HELP": "Chiave pubblica, pseudonimo", + "NO_ACCOUNT_QUESTION": "Ancora non hai un conto?", + "HAVE_ACCOUNT_QUESTION": "Hai già un account?", + "CREATE_ACCOUNT": "Creare un conto", + "CREATE_FREE_ACCOUNT": "Crea un conto gratuito", + "FORGOTTEN_ID": "Non ricordi la password?", + "ASSOCIATED_PUBKEY": "Chiave pubblica:", + "BTN_METHODS": "Altri metodi", + "BTN_METHODS_DOTS": "Cambiare metodo...", + "METHOD_POPOVER_TITLE": "Metodi", + "MEMORIZE_AUTH_FILE": "Memorizzare questo portachiavi per la durata di questa sessione", + "SCRYPT_PARAMETERS": "Parametri (Scrypt) :", + "AUTO_LOGOUT": { + "TITLE": "Informazioni", + "MESSAGE": "<i class=\"ion-android-time\"></i> Sei stato <b>sconesso/ b> automaticamente, per un periodo di inattività prolongata", + "BTN_RELOGIN": "Accedi", + "IDLE_WARNING": "Sarai disconesso in... {{countdown}}" + }, + "METHOD": { + "SCRYPT_DEFAULT": "Salatura standard (imp. predefinita)", + "SCRYPT_ADVANCED": "Salatura avanzata", + "FILE": "File del portachiavi", + "PUBKEY": "Chiave pubblica soltanto", + "SCAN": "Scansiona un codice QR" + }, + "SCRYPT": { + "SIMPLE": "Salatura leggera", + "DEFAULT": "Salatura standard", + "SECURE": "Salatura sicura", + "HARDEST": "Salatura più sicura", + "EXTREME": "Salatura estrema", + "USER": "Salatura personalizzata", + "N": "N (Loop):", + "r": "r (RAM):", + "p": "p (CPU):" + }, + "FILE": { + "HELP": "Format del file atteso: <b>.dunikey</b> (type PubSec). Altri formati in sviluppo (EWIF, WIF)." + } + }, + "AUTH": { + "TITLE": "<i class=\"icon ion-locked\"></i> Autenticazione", + "BTN_AUTH": "Autenticarsi", + "GENERAL_HELP": "Autenticati :", + "EXPECTED_UID_HELP": "Effettua il login nell'account <i class=\"ion-person\"></i> {{uid}}:", + "EXPECTED_PUBKEY_HELP": "Si prega di autenticarsi sul portafoglio <i class=\"ion-key\"></i> {{pubkey|formatPubkey}}:", + "SCAN_FORM_HELP": "Scansiona il codice QR della <b>chiave privata</b> del portafoglio." + }, + "ACCOUNT": { + "TITLE": "Mio conto", + "BALANCE": "Saldo", + "LAST_TX": "Ultime transazioni", + "BALANCE_ACCOUNT": "Saldo del conto", + "NO_TX": "Nessuna transazione", + "SHOW_MORE_TX": "Mostrare di più", + "SHOW_ALL_TX": "Mostrare tutte", + "TX_FROM_DATE": "(limite attuale del {{fromTime|medianFromNowShort}})", + "PENDING_TX": "Transazioni pendenti", + "VALIDATING_TX": "Transazioni in corso di convalida", + "ERROR_TX": "Transaction non eseguite", + "ERROR_TX_SENT": "Transazioni inviate", + "PENDING_TX_RECEIVED": "Transazioni in attesa di recezione", + "EVENTS": "Eventi", + "WAITING_MEMBERSHIP": "Richiesta di certificazione inviata. In attesa di validazione.", + "WAITING_CERTIFICATIONS": "Hai bisogno di {{needCertificationCount}} certificazione(i) per diventare membro.", + "WILL_MISSING_CERTIFICATIONS": "Mancherai a breve <b>di certificazioni</b> (occorrono almeno {{willNeedCertificationCount}} altre certificazioni)", + "WILL_NEED_RENEW_MEMBERSHIP": "Tua certificazione <b>scaderà {{membershipExpiresIn|formatDurationTo}}</b>. Ricordati di <a ng-click=\"doQuickFix('renew')\">rinnovarla</a> prima.", + "NEED_RENEW_MEMBERSHIP": "You are no longer a member because your membership <b>has expired</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a>.", + "NO_WAITING_MEMBERSHIP": "Nessuna domanda di adesione pendente. Se desideri <b>diventare membro</b>, ricordati di <a ng-click=\"doQuickFix('membership')\">inviare tua domanda di adesione</a>.", + "CERTIFICATION_COUNT": "Certificazioni ricevute", + "CERTIFICATION_COUNT_SHORT": "Certificazioni", + "SIG_STOCK": "Stock di certificazioni da inviare", + "BTN_RECEIVE_MONEY": "Ricevere", + "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Usare un'altra identità ..", + "BTN_FIX_MEMBERSHIP": "Invia nuovamente di adesione...", + "BTN_MEMBERSHIP_RENEW": "Rinnovare adesione", + "BTN_MEMBERSHIP_RENEW_DOTS": "Rinnovare adesione ...", + "BTN_MEMBERSHIP_OUT_DOTS": "Revocare adesione...", + "BTN_SECURITY_DOTS": "Login e securità ...", + "BTN_SHOW_DETAILS": "Visualizzare dati tecnici", + "LOCKED_OUTPUTS_POPOVER": { + "TITLE": "Importo bloccata", + "DESCRIPTION": "Ecco le condizioni per sbloccare questo importo:", + "DESCRIPTION_MANY": "Questa transazione è fatta da diverse parti, di cui queste sono le condizioni di sblocco:", + "LOCKED_AMOUNT": "Condizioni per l'importo:" + }, + "NEW": { + "TITLE": "Registrazione", + "INTRO_WARNING_TIME": "Crearsi un conto su {{name|capitalize}} è molto semplice. E consigliato prendere il giusto tempo per farlo correttamente (per evitare di dimenticare passwords, pseudonimi etc.).", + "INTRO_WARNING_SECURITY": "Occorre verificare che il hardware che stai utilizzando (computer, tablet, cellulare) <b>è sicuro e affidabile</b>.", + "INTRO_WARNING_SECURITY_HELP": "Anti-virus aggiornato, firewall abilitato, session protteta da un password o codice PIN...", + "INTRO_HELP": "Cliccare <b> {{'COMMON.BTN_START'|translate}}</b> per avviare la creazione del conto. Ti accompagniamo passo alla volta.", + "REGISTRATION_NODE": "Tua iscrizione verrà salvata dal nodo peer Duniter <b>{{server}}</b>, è verrà poi condivisa nella rete della moneta.", + "REGISTRATION_NODE_HELP": "Se non ti fidi di questo peer, per favore cambialo <a ng-click=\"doQuickFix('settings')\">nelle impostazioni/a> di Cesium.", + "SELECT_ACCOUNT_TYPE": "Scegliere un tipo di conto:", + "MEMBER_ACCOUNT": "Conto membro", + "MEMBER_ACCOUNT_TITLE": "Creare un conto membro", + "MEMBER_ACCOUNT_HELP": "Se non sei ancora registrato come individuo (un conto a persona soltanto).", + "WALLET_ACCOUNT": "Semplice portafoglio", + "WALLET_ACCOUNT_TITLE": "Creare un portafoglio", + "WALLET_ACCOUNT_HELP": "Se rappresenti un'azienda, associazione, altra ente o hai necessita di un altro portafoglio. Nessun Dividendo Universale sarà prodotto da questo conto.", + "SALT_WARNING": "Scegliere un identificativo segreto.<br/>E necessario per ogni connessione a questo conto.<br/><br/><b>Accertati di ricordarlo!</b>.<br/>Se lo dimentichi non ti potrà aiutare nessuno!", + "PASSWORD_WARNING": "Scegliere una password.<br/>E necessario per ogni connessione a questo conto.<br/><br/><b>Accertati di ricordarla!</b>.<br/>Se la dimentichi non ti potrà aiutare nessuno!", + "PSEUDO_WARNING": "Segliere uno pseudonimo.<br/>Puo essere utile per chi ti cerca nella rete.<br/><br/>.L'utilizzo delle<b>virgole, spazi e accenti</b> è vietato.<br/><div class='hidden-xs'><br/>Esempio: <span class='gray'>JohnDalton, JackieChan, etc.</span>", + "PSEUDO": "Pseudonimo", + "PSEUDO_HELP": "joe123", + "SALT_CONFIRM": "Confermare", + "SALT_CONFIRM_HELP": "Confermare l'identificativo segreto", + "PASSWORD_CONFIRM": "Confermare", + "PASSWORD_CONFIRM_HELP": "Confermare la password", + "SLIDE_6_TITLE": "Conferma:", + "COMPUTING_PUBKEY": "Calcolando...", + "LAST_SLIDE_CONGRATULATION": "Hai riempito tutti i campi richiesti.<br/><b>Puoi inviare la richiesta di creazione del conto</b>.<br/><br/>Per tua informazione, la chiave pubblica qui sotto identifica il tuo futuro conto.<br/>Puo essere communicata a chi ti deve pagare per esempio.<br/>Quando tuo conto verrà approvato potrai trovare la chiave qui <b>{{'ACCOUNT.TITLE'|translate}}</b>.", + "CONFIRMATION_MEMBER_ACCOUNT": "<b class=\"assertive\">Warning:</b> tuo identificare segreto, tua password e tuo pseudonimo non si possono cambiare.<br/><b>Ricordali per sempre!</b><br/><b>Sei sicuro/a</b>di voler inviare questa richiesta di creazione di conto?", + "CONFIRMATION_WALLET_ACCOUNT": "<b class=\"assertive\">Warning:</b> tuo identificare segreto, tua password e tuo pseudonimo non si possono cambiare..<br/><b>Ricordali per sempre!</b><br/><b>Sei sicuro/a</b> di voler continuare?", + "CHECKING_PSEUDO": "Verificazione in corso...", + "PSEUDO_AVAILABLE": "Pseudonimo disponibile", + "PSEUDO_NOT_AVAILABLE": "Pseudonimo indisponibile", + "INFO_LICENSE": "TPer aderire alla moneta, ti chiediamo di leggere e accetare le condizioni della licenza.", + "BTN_ACCEPT": "Accetto", + "BTN_ACCEPT_LICENSE": "Accetto la licenza" + }, + "POPUP_REGISTER": { + "TITLE": "Pseudonimo", + "HELP": "Un pseudonimo è necessario per che gli altri ti possino trovare." + }, + "SELECT_IDENTITY_MODAL": { + "TITLE": "Selezionare una identità ", + "HELP": "Più <b>identità diverse</b> sono state inviate per la chiave pubblica <span class=\"gray\"><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</span>.<br/>Seleziona un dossier da usare :" + }, + "SELECT_WALLET_MODAL": { + "TITLE": "Selezione del portafoglio" + }, + "WALLET_LIST": { + "TITLE": "Portafoglio secondario", + "BTN_NEW": "Aggiungi un portfolio", + "NO_WALLET": "Nessun portafoglio secondario", + "BTN_DELETE": "Rimuovi un portafoglio secondario ...", + "BTN_RENAME": "Rinominare il portafoglio", + "EDIT_POPOVER": { + "TITLE": "Rinominare il portafoglio", + "HELP": "Compila il nuovo nome", + "NAME_HELP": "Nome del portafoglio" + } + }, + "SECURITY":{ + "ADD_QUESTION" : "Aggiungere domanda personalizzata", + "BTN_CLEAN" : "Svuotare", + "BTN_RESET" : "Reset", + "DOWNLOAD_REVOKE": "Salvare un file di revoca", + "DOWNLOAD_REVOKE_HELP" : "Avere une file di revoca è necessario in caso di smarrimento dei tuoi credenziali. Ti permette <b> di rimuovere tuo conto dalla Web Of Trust</b>, per farlo tornare ad essere un semplice portafoglio.", + "HELP_LEVEL": "Scegliere <strong> almeno{{nb}} domande </strong> :", + "LEVEL": "Livello di sicurezza", + "LOW_LEVEL": "Basso <span class=\"hidden-xs\">(minimo di 2 domande)</span>", + "MEDIUM_LEVEL": "Medio <span class=\"hidden-xs\">(minimo di 4 domande)</span>", + "QUESTION_1": "Qual'era il nome del tuo miglior amico quando eri adolescente ?", + "QUESTION_2": "Qual'era il nome del tuo primo animale domestico?", + "QUESTION_3": "Qual'è il primo piatto che imparasti a cucinare?", + "QUESTION_4": "Qual'è il primo film che hai visto al cinema?", + "QUESTION_5": "Qual'era la destinazione del tuo primo volo?", + "QUESTION_6": "Qual'era il nome del tuo professore preferito in scuola ?", + "QUESTION_7": "Quale sarebbe il tuo lavoro preferito?", + "QUESTION_8": "Qual'è il tuo libro per bimbi preferito?", + "QUESTION_9": "Qual'era il marchio della tua prima macchina?", + "QUESTION_10": "Qual'era il tuo nomignolo da ragazzino/a ?", + "QUESTION_11": "Qual'era il tuo personaggio di film o attore preferito quand eri studente?", + "QUESTION_12": "Qual'era il tuo musicista/cantante/grupo preferito quand eri studente ?", + "QUESTION_13": "In che città si sono conosciuti tuoi genitori ?", + "QUESTION_14": "Qual'era il nome del tuo primo capo ?", + "QUESTION_15": "Qual'è il nome della strada dove sei cresciuto/a ?", + "QUESTION_16": "Qual'è il nome della tua spiaggia preferita ?", + "QUESTION_17": "Qual'è il primo album che ti sei comprato ?", + "QUESTION_18": "Qual'è il nome della squadra di sport preferita ?", + "QUESTION_19": "Cosa faceva tuo nonno ?", + "RECOVER_ID": "Ricuperare mia password...", + "RECOVER_ID_HELP": "Se hai un<b<file di backup dei tuoi credenziali</b>, li puoi trovare rispondendo correttamente alle tue domande personalizzate.", + "REVOCATION_WITH_FILE" : "Revocare il mio conto membro...", + "REVOCATION_WITH_FILE_DESCRIPTION": "Se pensi di aver perso <b>definitivamente tuoi credenziali</b> di conto membro (o che la sicurezza del tuo conto è compromessa), puoi usare <b>il file di revoca</b> del conto <b>per forzare la sua uscita permanente dalla Tela di Fiducia</b>.", + "REVOCATION_WITH_FILE_HELP": "Se hai <b>definitivamente perso tuoi credenziali (o se la sicurezza del tuo conto è compromessa), puoi usare <b>il file di revoca</b> del conto <b>per uscire dalla Web Of Trust</b>.", + "REVOCATION_WALLET": "Revocare questo conto subito", + "REVOCATION_WALLET_HELP": "Richiedere la cancellazione dell'identità <b>revocherà la tua adesione alla tua rete</ b> (con certezza per il pseudonimo e la chiave pubblica associata). Il conto non potrà più produrre il Dividendo Universale.<br/>Nonostante ciò, puoi ancora usare il conto come semplice portafoglio.", + "REVOCATION_FILENAME": "revocation-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "SAVE_ID": "Salvare miei credenziali...", + "SAVE_ID_HELP": "Creare un file di backup, per <b>ricuperare vostra password</b> (e l'identificativo segreto) <b> in caso di smarrimento</b>. Il file è <b>sicuro</ b> (cryptato) utilizzando le domande personalizzate.", + "STRONG_LEVEL": "Alto <span class=\"hidden-xs \">(minimo di 6 domande)</span>", + "TITLE": "Conto e sicurezza" + }, + "FILE_NAME": "{{currency}} - Account statement {{pubkey|formatPubkey}} to {{currentTime|formatDateForFile}}.csv", + "HEADERS": { + "TIME": "Date", + "AMOUNT": "Amount", + "COMMENT": "Comment" + } + }, + "TRANSFER": { + "TITLE": "Bonifico", + "SUB_TITLE": "Fare un bonifico", + "FROM": "Da", + "TO": "A", + "AMOUNT": "Importo", + "AMOUNT_HELP": "Importo", + "COMMENT": "Commenti", + "COMMENT_HELP": "Commenti", + "BTN_SEND": "Inviare", + "BTN_ADD_COMMENT": "Scrivere un comento ?", + "WARN_COMMENT_IS_PUBLIC": "Ti avvertiamo <b>che i commenti sono pubblici</b> (non cifrati).", + "MODAL": { + "TITLE": "Bonifico" + } + }, + "ERROR": { + "POPUP_TITLE": "Errore", + "UNKNOWN_ERROR": "Errore", + "CRYPTO_UNKNOWN_ERROR": "Suo navigatore non sembra compatibile con le funzionalità di cryptografia.", + "EQUALS_TO_PSEUDO": "Deve essere diverso dal pseudonimo", + "EQUALS_TO_SALT": "Deve essere diverso dal identificativo segreto", + "FIELD_REQUIRED": "Campo obbligatorio.", + "FIELD_TOO_SHORT": "Valore troppo corto.", + "FIELD_TOO_SHORT_WITH_LENGTH": "Valore troppo corto ({{minLength}} caratteri min)", + "FIELD_TOO_LONG": "Valore troppo lungo", + "FIELD_TOO_LONG_WITH_LENGTH": "Valore troppo lungo ({{maxLength}} caractteri max)", + "FIELD_MIN": "Valore minimo : {{min}}", + "FIELD_MAX": "Valore massimo : {{max}}", + "FIELD_ACCENT": "Virgole e caratteri accentati vietati", + "FIELD_NOT_NUMBER": "Valore numerico atteso", + "FIELD_NOT_INT": "Valore intero atteso", + "FIELD_NOT_EMAIL": "Indirizzo mail non valido", + "PASSWORD_NOT_CONFIRMED": "Non corrisponde alla password.", + "SALT_NOT_CONFIRMED": "Non corrisponde al identificativo segreto.", + "SEND_IDENTITY_FAILED": "Iscrizione fallita.", + "SEND_CERTIFICATION_FAILED": "Certificazione fallita.", + "NEED_MEMBER_ACCOUNT_TO_CERTIFY": "Non puoi inviare certificazioni perche tuo conto <b>non è ancora un conto membro</b>.", + "NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF": "Non puoi inviare certificazioni adesso perche <b>non sei ancora membro</b>.<br/><br/>Devi ancora entrare nella WOT.", + "NOT_MEMBER_FOR_CERTIFICATION": "Tuo conto non è ancora un conto membro.", + "IDENTITY_TO_CERTIFY_HAS_NO_SELF": "Impossibile certificare questo conto. Nessuna richiesta di certificazione trovata o bisogna rinnovarla.", + "LOGIN_FAILED": "Errore di login.", + "LOAD_IDENTITY_FAILED": "Impossibile caricare la tua identità .", + "LOAD_REQUIREMENTS_FAILED": "Impossibile caricare i prerequisiti dell'identità .", + "SEND_MEMBERSHIP_IN_FAILED": "Ingresso nella WOT fallito.", + "SEND_MEMBERSHIP_OUT_FAILED": "Errore nel invio della revocazione.", + "REFRESH_WALLET_DATA": "Impossibile aggiornare il portafoglio.", + "GET_CURRENCY_PARAMETER": "Impossibile ricuperare i parametri della moneta.", + "GET_CURRENCY_FAILED": "Impossibile caricare la moneta. Riprovare più tardi.", + "SEND_TX_FAILED": "Impossibile eseguire la transazione.", + "ALL_SOURCES_USED": "Per favore aspetta il calcolo del prossimo blocco (Tutte le tue fonti di moneta sono state utilizzate).", + "NOT_ENOUGH_SOURCES": "Non hai abbastanza cambio per inviare questo importo in una sola transazione.<br/>Importo massimo: {{amount}} {{unit}}<sub>{{subUnit}}</sub>.", + "ACCOUNT_CREATION_FAILED": "Errore nella creazione del tuo conto membro.", + "RESTORE_WALLET_DATA_ERROR": "Errore nel aggiornamento delle impostazioni definite in local storage.", + "LOAD_WALLET_DATA_ERROR": "Errore nel caricamento dei dati del portafoglio.", + "COPY_CLIPBOARD_FAILED": "Impossibile copiare al clipboard", + "TAKE_PICTURE_FAILED": "Impossibile ricuperare foto.", + "SCAN_FAILED": "Impossibile scansionare il codice QR.", + "SCAN_UNKNOWN_FORMAT": "Codice non riconosciuto.", + "WOT_LOOKUP_FAILED": "Ricerca fallita.", + "LOAD_PEER_DATA_FAILED": "Peer Duniter non accessibile. Riprovare più tardi.", + "NEED_LOGIN_FIRST": "Accedi al tuo conto prima.", + "AMOUNT_REQUIRED": "Importo necessario.", + "AMOUNT_NEGATIVE": "Importo negativo non consentito.", + "NOT_ENOUGH_CREDIT": "Saldo insufficiente", + "INVALID_NODE_SUMMARY": "Impossibile comunicare col peer o indirizzo non valido", + "INVALID_USER_ID": "Il campo del 'pseudonimo' non deve avere spazi vuoti o caratteri speciali.", + "INVALID_COMMENT": "Il formato del campo 'reference' è errato.", + "INVALID_PUBKEY": "If formato della chiave pubblica è errato.", + "IDENTITY_REVOKED": "Questa identità <b>è stata revocata</b>. Non puo più diventare membro.", + "IDENTITY_REVOKED_WITH_TIME": "Questa identità <b>è stata revocata {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). Non puo più diventare membro.", + "IDENTITY_PENDING_REVOCATION": "L'<b>annulamento di questa identità </b> è stata richiesta ed è in corso di evaluazione. Capacità ad inviare certificazioni disabilitata", + "IDENTITY_INVALID_BLOCK_HASH": "Questa richiesta di certificazione non è più valida (perche si riferisce ad un blocco che è stato eliminato dai peers): la persona deve rinnovare la sua domanda di certificazione <b>prima</b> di essere certificata.", + "IDENTITY_EXPIRED": "Questa identità è scaduta: la persona deve fare una nuova domanda di certificazione <b>prima di</b> essere certificata.", + "IDENTITY_SANDBOX_FULL": "Il nodo Duniter utilizzato da Cesium non puo ricevere altre domande di certificazione per ora, la lista d'attesa è piena.<br/><br/>Riprova più tardi o scegli un'altro peer Duniter (nelle <b>Impostazioni</b>).", + "IDENTITY_NOT_FOUND": "Identità non trovata", + "IDENTITY_TX_FAILED": "Impossibile caricare le operazioni", + "WOT_PENDING_INVALID_BLOCK_HASH": "Adesione non valida.", + "WALLET_INVALID_BLOCK_HASH": "Tua domanda di certificazione non è più valida (perche si riferisce ad un blocco che è stato eliminato dai peers).<br/>Devi <a ng-click=\"doQuickFix('renew')\">rinnvoare la tua richiesta di adesione alla WOT</a> per risolvere il problema.", + "WALLET_IDENTITY_EXPIRED": "La pubblicazione della tua identità <b>è scaduta</b>.<br/>Devi <a ng-click=\"doQuickFix('fixIdentity')\">ripubblicare la tua identità </a> per risolvere il problema.", + "WALLET_REVOKED": "La tua identità è stata <b>revocata</b>: ne tuo pseudonimo ne tua chiave pubblica sarano utilizzati in futuro.", + "WALLET_HAS_NO_SELF": "La tua identità deve prima essere stata pubblicata e non essere ancora scaduta.", + "AUTH_REQUIRED": "Autenticazione necessaria.", + "AUTH_INVALID_PUBKEY": "La chiave pubblica non corrisponde al conto conesso.", + "AUTH_INVALID_SCRYPT": "Password o nome di utente non valido.", + "AUTH_INVALID_FILE": "File di portachiavi non valido.", + "AUTH_FILE_ERROR": "Impossibile aprire il file di portachiavi", + "IDENTITY_ALREADY_CERTIFY": "Hai <b>già certificato</b> questa identità .<br/><br/>Tuo certificato è ancora valido (scade {{expiresIn|formatDuration}}).", + "IDENTITY_ALREADY_CERTIFY_PENDING": "Hai <b>già certificato</b> questa identità .<br/><br/>Tua certificazione è ancora pendente (Scadenza del periodo di treatment {{expiresIn|formatDuration}}).", + "UNABLE_TO_CERTIFY_TITLE": "Impossibile certificare", + "LOAD_NEWCOMERS_FAILED": "Impossibile caricare i nuovi membri.", + "LOAD_PENDING_FAILED": "Impossibile caricare le certificazioni pendenti.", + "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "Devi <b>essere membro</b> per poter fare questo.", + "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "Devi aver <b>publiccato tua identità </b> per poter fare questo.", + "GET_BLOCK_FAILED": "Impossibile caricare il blocco", + "INVALID_BLOCK_HASH": "Blocco non trovato (hash errato)", + "DOWNLOAD_REVOCATION_FAILED": "Errore avvenuto nel download del file di cancellazione d'identità .", + "REVOCATION_FAILED": "Errore avvenuto durante la richiesta di cancellazione dell'identità .", + "SALT_OR_PASSWORD_NOT_CONFIRMED": "identificativo segreto o password sbagliati", + "RECOVER_ID_FAILED": "Impossibile ricuperare la password", + "LOAD_FILE_FAILED" : "Impossibile caricare il file", + "NOT_VALID_REVOCATION_FILE": "File di cancellazione dell'identità errato (formato di file incorreto)", + "NOT_VALID_SAVE_ID_FILE": "File di backup dei credenziali errato (formato di file incorreto)", + "NOT_VALID_KEY_FILE": "File di portachiavi non valido (formato non riconosciuto)", + "EXISTING_ACCOUNT": "Tuoi credenziali corrispondono a quelli di un conto già esistente,di cui <a ng-click=\"showHelpModal('pubkey')\">la chiave pubblica</a> è:", + "EXISTING_ACCOUNT_REQUEST": "Per favore cambi tuoi credenziali in modo che corrispondino ad un conto non utilizzato.", + "GET_LICENSE_FILE_FAILED": "Impossibile caricare il file della licenza", + "CHECK_NETWORK_CONNECTION": "Nessun peer sembra disponibile.<br/><br/>Per favore <b>verifica la tua connessione Internet</b>.", + "ISSUE_524_TX_FAILED": "Bonifico .<br/><br/>Un message a été envoyé aux développeurs pour faciliter la résolution du problème. <b>Merci de votre aide</b>." + }, + "INFO": { + "POPUP_TITLE": "Informazioni", + "CERTIFICATION_DONE": "Identità firmata con successo", + "NOT_ENOUGH_CREDIT": "Saldo insufficiente", + "TRANSFER_SENT": "Transazione inviata con successo", + "COPY_TO_CLIPBOARD_DONE": "Copiato con successo", + "MEMBERSHIP_OUT_SENT": "Revoca dell'identità inviata", + "NOT_NEED_MEMBERSHIP": "Già un membro.", + "IDENTITY_WILL_MISSING_CERTIFICATIONS": "Questa identità mancherà a breve di certificazioni (almeno {{willNeedCertificationCount}}).", + "REVOCATION_SENT": "Revoca dell'identità inviata", + "REVOCATION_SENT_WAITING_PROCESS": "Cancellazione dell'identità <b>inviata con successo</b>. In attesa di validazione.", + "FEATURES_NOT_IMPLEMENTED": "Questa funzionalità non è ancora disponibile.<br/><br/>Vuoi contribuire per velocizzarne la disponibilità ? ;)", + "EMPTY_TX_HISTORY": "Nessuna operazione da esportare" + }, + "CONFIRM": { + "POPUP_TITLE": "<b>Conferma</b>", + "POPUP_WARNING_TITLE": "<b>Avviso</b>", + "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Avvertimento di sicurezza</b>", + "CERTIFY_RULES_TITLE_UID": "Certificare {{uid}}", + "CERTIFY_RULES": "<b class=\"assertive\">Non certificare un conto</b> se credi che: <ul><li>1.) l'identità della persona potrebbe essere finta.<li>2.) la oersona ha già un conto certicato.<li>3.) la persona trasgredisce la regola 1 o 2 o entrambe. (Certifica conti finti o gemelli).</ul></small><br/>Sei sicuro/a di voler certificare questa identità ?", + "TRANSFER": "<b>Resoconto del bonifico:</b><br/><br/><ul><li> - Inviato da: <b>{{from}}</b></li><li> - A: <b>{{to}}</b></li><li> - Importo: <b>{{amount}} {{unit}}</b></li><li> - Comento: <i>{{comment}}</i></li></ul><br/><b>Sei sicuro di voler procedere con questo bonifico?</b>", + "MEMBERSHIP_OUT": "Questa operazione è <b>irreversibile</b>.<br/></br/><b>Sei sicuro/a di voler cancellare la tua presenza nella WOT?</b>", + "MEMBERSHIP_OUT_2": "Questa operazione è <b>irreversibile</b>!<br/><br/>Sei sicuro/a <b>di voler revocare la tua identità </b>?", + "LOGIN_UNUSED_WALLET_TITLE": "Errore di battitura?", + "LOGIN_UNUSED_WALLET": "Il conto sembra <b>inattivo</b>.<br/><br/>Probabilmente è un<b>errore di battitura</b> mientre digitavi i tuoi credenziali. Per favore riprova, verificando che la <b>chiave pubblica sia tua<b/>.", + "FIX_IDENTITY": "Lo pseudonimo <b>{{uid}}</b> verrà pubblicato nuovamente. Si sostituirà alla precedente pubblicazione che è scaduta.<br/></br/><b>Sei sicuro/a</b> di voler procedere?", + "FIX_MEMBERSHIP": "Tua domanda di certificazione sarà inviata alla rete.<br/></br/><b>Sei sicuro/a?</b>", + "MEMBERSHIP": "Tua domanda per diventare membro sta per essere inviata alla rete.<br/></br/><b>Sei sicuro/a/b> di voler continuare ?", + "RENEW_MEMBERSHIP": "Tua adesione verrà rinnovata.<br/></br/><b>Sei sicuro/a?</b>", + "REVOKE_IDENTITY": "Stai per <b>revocare definitivamente questa identità </b>.<br/><br/>La chiave pubblica e lo pseudonimo associato <b>non saranno mai più utilizzati</b> (per un conto membro).<br/></br/><b>Sei sicuro/a</b> di voler revocare questa identità ?", + "REVOKE_IDENTITY_2": "Questa operazione è <b>irreversibile</b>!<br/><br/>Sei sicuro/a di volern<b>revocare questa identità </b>?", + "NOT_NEED_RENEW_MEMBERSHIP": "Tua presenza nella rete non deve ancora essere rinnovata (scaderà tra {{membershipExpiresIn|formatDuration}}).<br/></br/><b>Sei sicuro/a</b> di voler rinnovare la tua presenza?", + "SAVE_BEFORE_LEAVE": "Vuoi <b>salvare tue modifiche</b> prima di uscira dalla pagina?", + "SAVE_BEFORE_LEAVE_TITLE": "Modifiche non salvate", + "LOGOUT": "Sei sicuro/a di voler chiudere la sessione?", + "USE_FALLBACK_NODE": "Peer <b>{{old}}</b> indisponibile o indirizzo errato.<br/><br/>Vuoi utilizzare temporanemante il <b>{{new}}</b> nodo?", + "INVALID_FILE_FORMAT": "Formato file non valido.", + "SAME_TX_RECIPIENT": "Il destinatario deve essere diverso dall'emittente." + }, + "DOWNLOAD": { + "POPUP_TITLE": "<b>File di cancellazione dell'identità /b>", + "POPUP_REVOKE_MESSAGE": "Per migliorare la sicurezza del tuo conto, scarica <b>il documento di revoca del conto</b>. Ti consentirà di revocare tuo conto (nel caso di violazione del conto, della tua identità , conto creato con errori, etc.).<br/><br/><b>Tiene questo document al sicuro.</b>" + }, + "HELP": { + "TITLE": "Aiuto online", + "JOIN": { + "SECTION": "Entrare nella rete", + "SALT": "Il tuo identificativo segreto è molto importante. E utilizzato per cryptare tua password che permette poi di calcolare tua <span class=\"text-italic\">chiave pubblica</span> (suo numero) è la chiave privata che ne consenta l'accesso.<br/><b>Ricordati bene di questo identificativo</b>, perche non ti potrà aiutare nessuno se lo perdi.<br/>Tra l'altro, non puo essere cambiato senza dover creare un conto nuovo.<br/><br/>Raccomandiamo che sia abbastanza lungo (8 caratteri almeno) è il più originale possibile. (buona entropia)", + "PASSWORD": "La password è molto importante, è utilizzata per calcolare tuo numero di conto (tua chiave pubblica) e la chiave privata che ne consento l'accesso.<br/><b>Ricordatila bene</b>, perche non ti potrà aiutare nessuno se lo perdi.<br/>Tra l'altro, non puo essere cambiata senza dover creare un conto nuovo.<br/><br/>Una buona password (preferibilmente) è composta da almeno 8 caratteri, con almeno una maiuscola e un numero.", + "PSEUDO": "Un pseudonimo è utilizzato quando ti iscrivi come <span class=\"text-italic\">membro</span>. E sempre associato ad un portafoglio (con sua <span class=\"text-italic\">chiave pubblica</span>).<br/>E pubblicato sulla rete perche gli altri membri possino identificarla, certificarla o invarle soldi. <br/> Lo pseudonimo deve essere unico nella rete (tra quelli utilizzati adesso e in passato)." + }, + "LOGIN": { + "SECTION": "Accedi", + "PUBKEY": "Chiave pubblica del conto", + "PUBKEY_DEF": "La chiave pubblica del portachiavi è generata dai credenziali, ma non corrispode ad un conto già utilizzato.<br/><b>Accertati che tua chiave pubblica corrisponda al tuo conto</b>. Nel caso contrario, sarai conesso/a ad un conto probabilmente mai usato, datto che il rischio di collisione con un conto esistente è molto ridotto.<br/><a href=\"https://en.wikipedia.org/wiki/Elliptic_curve_cryptography\" target=\"_ system\">Saperne di più sulla cryptografia </a> con chiave pubblica.", + "METHOD": "Metodi di connessione", + "METHOD_DEF": "Hai diverse opzioni per accedere ad un portafoglio:<br/> - Accedendo con <b>salatura (leggera o sicura)</b> tua password sarà cryptata dal tuo identificativo segreto per scoraggiare tentativi di attachi di 'brute force' (per esempio con passwords conosciute).<br/> - Accedendo con la <b>chiave pubblica</b> ti evita di dover digitare tuoi credenziali che ti saranno chiesti solo quando vorrai fare una operazione col conto.<br/> - Accedendo <b>con un portachiavi</b> che leggerà tue chiave pubbliche e private da un file esterno, senza che tu li debba entrare." + }, + "GLOSSARY": { + "SECTION": "Glossario", + "PUBKEY_DEF": "Una chiave pubblica permette di identificare un portafoglio. Puo anche identificare un membro. In Cesium è calcolata con la password e lo pseudonimo.", + "MEMBER": "Membro", + "MEMBER_DEF": "Un membro è una persona reale e viva, che desidera participare liberamente alla communità monetaria. Questo membro riceverà un Dividendo Universale, a secondo delle regole definite <span class=\"text-italic\">nei parametri della moneta</span>.", + "CURRENCY_RULES": "Regole della moneta", + "CURRENCY_RULES_DEF": "I parametri delle moneta sono state definite per sempre e per tutti. I parametri con i quali la moneta si comporta: il calcolo del Dividendo Universale, il numero di certificazioni necessarie per diventare membro, il numero massimo di certificazioni che un membro puo inviare, etc.<br/><br/>I parametri non possono essere modificati perche c'è una<span class=\"text-italic\">Blockchain</span> che implementa e esegue queste regole e verifica costantemente la loro applicazione. <a href=\"#/app/currency\">Vedere i parametri </a>.", + "BLOCKCHAIN": "Blockchain", + "BLOCKCHAIN_DEF": "La Blockchain è un sistema decentralizzato che, nel caso di Duniter, permette di rispettare e implementare <span class=\"text-italic\">le regole della moneta</span>.<br/><a href=\"http://en.duniter.org/presentation/\" target=\"_blank\">Saperne di più su Duniter</a> e il funzionamento della blockchain.", + "UNIVERSAL_DIVIDEND_DEF": "Il Dividendo Universale (UD) è la quantità di moneta co-creata da ogni membro, seguendo le formule mathematiche definite nelle <span class=\"text-italic\">regole della moneta</span>.<br/>Al inizio di ogni periodo, il conto di ogni membro riceve una quantità uguale della nuova moneta creata. <br/><br/>Il DU conosce una crescita costante per rimanere equo nei confronti dei membri (attuali e passati). Viene calcolato tenendo in conto la speranza di vità media, cosi come dimostrato nella Teoria Relativa della Moneta (TRM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Saperne di più sulla TRM</a> e la moneta libera." + }, + "TIP": { + "MENU_BTN_CURRENCY": "Menu <b>{{'MENU.CURRENCY'|translate}}</b> permette la scoperta dei <b>parametri della moneta</b> e la sua condizione presente.", + "CURRENCY_WOT": "Il <b>numero di membri</b> mostra <b>le dimensioni della WoT e la sua evoluzione </b>.", + "CURRENCY_MASS": "In evidenza qui è <b>l'importo totale</b> attualmente in circolazione e la sua <b> ripartizione media </b> a testa.<br/><br/>Questa cifra permette di avere un'idea <b>del valore di qualsiasi importo</b>, in base a quello <b>hanno gli altri</b> sul loro conto (in media).", + "CURRENCY_UNIT_RELATIVE": "L'unità usata qui (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) significa che gli importi in {{currency|capitalize}} sono stati divisi dal <b>Dividendo Universale</b> (DU).<br/><br/><small>Questa unità relativa <b>ha senso</b> perche è stabile in contrasto con la massa monetaria che cresce costantemente.</small>", + "CURRENCY_CHANGE_UNIT": "Questa opzione <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> permette di <b>permutare unità </b> per vedere gli importi in <b>{{currency|capitalize}}</b>, non divisi dal Dividendo Universale (piuttosto che in “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”).", + "CURRENCY_CHANGE_UNIT_TO_RELATIVE": "Questa opzione <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> permette <b>di permutare unità </b> per vedere gli importi in “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”, che è relativo al Dividendo Universale (l'importo co-prodotto da ogni membro).", + "CURRENCY_RULES": "Le<b>regole</b> della moneta determinano il suo <b>esatto e previdibile</b> comportamento.<br/><br/> Considerate come il proprio DNA della moneta, queste regole rendono il codice monetario <b>trasparente e comprensibile</b>.", + "MENU_BTN_NETWORK": "Menu <b>{{'MENU.NETWORK'|translate}}</b> permette la scopertà dello <b>stato della rete<b>.", + "NETWORK_BLOCKCHAIN": "Tutte le transazioni monetarie sono registrate in <b>registro sicuro e a prova di manomissione</b>, spesso chiamato <b>blockchain</b>.", + "NETWORK_PEERS": "I<b>peers</b> mostrati qui corrispondono a <b>dei computers che aggiornano e monitorano</b> la blockchain.<br/><br/>Più peers ci sono, più <b>decentralizzata</b> e più affidabile diventa la moneta.", + "NETWORK_PEERS_BLOCK_NUMBER": "Questo <b>numero</b> (in verda) indica <b>l'ultimo blocco validato</b> dal peer (ultima pagina scritta nel regitro).<br/><br/>Il verda indica che il blocco è stato validato anche dalla <b>maggioranza degli altri peers</b>.", + "NETWORK_PEERS_PARTICIPATE": "<b>Ogni membro</b>, che dispone di un computer connesso a Internet <b>puo partecipare, aggiungendosi come peer installando il software Duniter</b> (free/libre). <a target=\"_new\" href=\"{{installDocUrl}}\" target=\"_system\">Leggi il manuale d'installazione >></a>.", + "MENU_BTN_ACCOUNT": "<b>{{'ACCOUNT.TITLE'|translate}}</b> permette l'accesso al saldo del conto e la cronologia delle transazioni.", + "MENU_BTN_ACCOUNT_MEMBER": "Qui puoi consultare lo stato del tuo conto, la cronologia delle transazioni e le tue certificazioni.", + "WALLET_CERTIFICATIONS": "Clicca qui per vedere i dettagli delle tue certificazioni (date o ricevute).", + "WALLET_RECEIVED_CERTIFICATIONS": "Clicca qui per vedere i dettagli delle <b>certificazioni che hai ricevuto</b>.", + "WALLET_GIVEN_CERTIFICATIONS": "Clicca qui per vedere i dettagli delle <b>certificazioni che hai date</b>.", + "WALLET_BALANCE": "Il <b>soldo</b> del tuo conto è visibile qui.", + "WALLET_BALANCE_RELATIVE": "{{'HELP.TIP.WALLET_BALANCE'|translate}}<br/><br/>L'unità utilizzata (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) significa che questo importo in {{currency|capitalize}} è stato diviso dal <b>Dividendo Universale</b> (DU) co-creato da ogni membro.<br/>Ad oggi, 1 DU equivale a {{currentUD}} {{currency|capitalize}}.", + "WALLET_BALANCE_CHANGE_UNIT": "Puoi <b>cambiare l'unità </b> in cui sono mostrati gli importi in <b><i class=\"icon ion-android-settings\"></i> {{'MENU.SETTINGS'|translate}}</b>.<br/><br/>Per esempio, per mostrare gli importi <b>direttamente in {{currency|capitalize}}</b> piuttosto che in unità relativa.", + "WALLET_PUBKEY": "Questa è la chiave pubblica del tuo conto. La puoi dare ad un terzo perche possa identificare tuo conto.", + "WALLET_SEND": "Paghi in pochi clics.", + "WALLET_SEND_NO_MONEY": "Paghi in pochi clics.<br/>(Tuo saldo ancora non lo permette)", + "WALLET_OPTIONS": "Questo bottone permette di fare <b>altre, meno frequenti azioni</b>.<br/><br/> Non dimenticarti di fare il tour guidato di Cesium quando hai un attimo!", + "WALLET_RECEIVED_CERTS": "Questo mostra l'elenco delle persone che ti hanno fatto entrare nella WoT.", + "WALLET_CERTIFY": "Questo bottone <b>{{'WOT.BTN_SELECT_AND_CERTIFY'|translate}}</b> permette di selezionare e certificare una identità .<br/><br/>Solo gli utenti <b>che sono già membri</b> possono certificare gli altri.", + "WALLET_CERT_STOCK": "Tuo stock di certificazioni da dare è limitato a <b>{{sigStock}} certificazioni</b>.<br/><br/>Questo stock si rifornisce col tempo, man mano che le certificazioni inviate scadono.", + "MENU_BTN_TX_MEMBER": "<b>{{'MENU.TRANSACTIONS'|translate}}</b> permette l'accesso alla cronologia delle transazioni, e permette di fare nuovi bonifici.", + "MENU_BTN_TX": "Visualizza la cronologia <b>delle tue transazioni</b> qui e fai nuovi bonifici.", + "MENU_BTN_WOT": "Il menu<b>{{'MENU.WOT'|translate}}</b> permette di cercare <b>utenti</b> della moneta (membri o non).", + "WOT_SEARCH_TEXT_XS": "Per fare una ricerca nel annuario, digita <b>le prime lettere dello pseudonimo o della chiave pubblica di un utente</b>.<br/><br/>La ricerca inizierà automaticamente.", + "WOT_SEARCH_TEXT": "Per cercare nel annuario, digita <b>le prime lettere dello pseudonimo o della chiave pubblica di un utente</b>.<br/><br/>Dopodichè calca <b>Enter</b> per avviare la ricerca.", + "WOT_SEARCH_RESULT": "Visualizza la scheda dettagliata di un utente con un semplice click sulla linea.", + "WOT_VIEW_CERTIFICATIONS": "La linea <b>{{'ACCOUNT.CERTIFICATION_COUNT'|translate}}</b> mostra quanti membri hanno certificato questa identità .<br/><br/>Queste certificazioni dimostrano che il conto appartiene ad <b>una persona viva</b> e che questa persona non ha <b>nessun altro conto membro</b>.", + "WOT_VIEW_CERTIFICATIONS_COUNT": "Ci vogliono almeno <b>{{sigQty}} certificazioni</b> per diventare membro e co-produrre il <b>Dividendo Universale</b>.", + "WOT_VIEW_CERTIFICATIONS_CLICK": "Clicca qui per aprire <b>una lista di tutte le certificazioni</b> ricevute e date da questa identità .", + "WOT_VIEW_CERTIFY": "Il bottone <b>{{'WOT.BTN_CERTIFY'|translate}}</b> permette di aggiungere tua certificazione a questa identità .", + "CERTIFY_RULES": "<b>Attenzione:</b> Certifichi <b> solo persone reali e vive</b> che non hanno nessun altro conto membro.<br/><br/>L'affidabilità della moneta dipende della vigilanza di ciascuno.", + "MENU_BTN_SETTINGS": "Les <b>{{'MENU.SETTINGS'|translate}}</b> ti permettono di configurare Cesium.<br/><br/>Per esempio, puoi <b>cambiare l'unità </b> in cui visualizzi la moneta.", + "HEADER_BAR_BTN_PROFILE": "Clicca qui per entrare nel <b>tuo profilo utente</b>", + "SETTINGS_CHANGE_UNIT": "Puoi cambiare <b>l'unità </b> della moneta cliccando qui.<br/><br/>- Disabilita questa opzione per vedere gli importi in {{currency|capitalize}}.<br/>- Abilita l'opzione per importi relativi in {{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub> (<b>divisi</b> dal attuale Dividendo Universale).", + "END_LOGIN": "Il tour guidato <b>è finito</b>.<br/><br/>Benvenuto nel <b>economia libera</b>!", + "END_NOT_LOGIN": "Il tour guidato <b>è finito</b>.<br/><br/>Se desideri entrare nella Web of Trust {{currency|capitalize}}, basta cliccare <b>{{'LOGIN.CREATE_ACCOUNT'|translate}}</b> qui sotto." + } + }, + "API" :{ + "COMMON": { + "LINK_DOC": "documentazione API", + "LINK_DOC_HELP": "Documentazione dello sviluppatore", + "LINK_STANDARD_APP": "versione classica", + "LINK_STANDARD_APP_HELP": "Apri la versione classica di {{'COMMON.APP_NAME'|translate}}" + }, + "HOME": { + "TITLE": "Documentazione API {{'COMMON.APP_NAME'|translate}}", + "MESSAGE": "Bienvenue dans la <b>documentation de l'API</b> {{'COMMON.APP_NAME'|translate}}.<br/>Connecter vos sites web à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", + "MESSAGE_SHORT": "Connecter vos sites à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", + "DOC_HEADER": "Services disponibles :" + }, + "TRANSFER": { + "TITLE": "{{'COMMON.APP_NAME'|translate}} - Paiement en ligne", + "TITLE_SHORT": "Pagamento online", + "SUMMARY": "Récapitulatif de la commande :", + "AMOUNT": "Montant :", + "NAME": "Nom :", + "PUBKEY": "Clé publique du destinaire :", + "COMMENT": "Référence de la commande :", + "DEMO": { + "SALT": "demo", + "PASSWORD": "demo", + "PUBKEY": "3G28bL6deXQBYpPBpLFuECo46d3kfYMJwst7uhdVBnD1", + "HELP": "<b>Mode démonstration</b> : Aucun paiement ne sera réellement envoyé pendant cette simulation.<br/>Veuillez utiliser les identifiants : <b>{{'API.TRANSFER.DEMO.SALT'|translate}} / {{'API.TRANSFER.DEMO.PASSWORD'|translate}}</b>", + "BAD_CREDENTIALS": "Vérifiez votre saisie.<br/>En mode démonstration, les identifiants sont : {{'API.TRANSFER.DEMO.SALT'|translate}} / {{'API.TRANSFER.DEMO.PASSWORD'|translate}}" + }, + "INFO": { + "SUCCESS_REDIRECTING_WITH_NAME": "Paiement envoyé.<br/>Redirection vers <b>{{name}}</b>...", + "SUCCESS_REDIRECTING": "Paiement envoyé.<br/>Redirection vers le site du vendeur...", + "CANCEL_REDIRECTING_WITH_NAME": "Paiement annulé.<br/>Redirection vers <b>{{name}}</b>...", + "CANCEL_REDIRECTING": "Paiement annulé.<br/>Redirection vers le site du vendeur..." + }, + "ERROR": { + "TRANSFER_FAILED": "Mancato pagamento" + } + }, + "DOC": { + "DESCRIPTION_DIVIDER": "Descrizione", + "URL_DIVIDER": "Indirizzo chiamata", + "PARAMETERS_DIVIDER": "Impostazioni", + "AVAILABLE_PARAMETERS": "Ecco l'elenco dei parametri disponibili :", + "DEMO_DIVIDER": "Provare", + "DEMO_HELP": "Per provare questo servizio, clicca sul bottone qui a fianco. Il risultato apparirà qui sotto .", + "DEMO_RESULT": "Risultato della chiamata :", + "DEMO_SUCCEED": "<i class=\"icon ion-checkmark\"></i> Successo !", + "DEMO_CANCELLED": "<i class=\"icon ion-close\"></i> Annulato dal utente", + "INTEGRATE_DIVIDER": "Integrare", + "INTEGRATE_CODE": "Codice :", + "INTEGRATE_RESULT": "Previsualizzare il risultato :", + "INTEGRATE_PARAMETERS": "Parametri", + "TRANSFER": { + "TITLE": "Pagamenti", + "DESCRIPTION": "Da un sito (per es. : un sito e-commerce) si può delegare il pagamento in moneta libera a Cesium API. Per invocare l'API, basta innescare l'apertura di una pagina con questo indirizzo:", + "PARAM_PUBKEY": "Chiave pubblica del destinatario", + "PARAM_PUBKEY_HELP": "Chiave pubblica del destinatario (obliggatoria)", + "PARAM_AMOUNT": "Importo", + "PARAM_AMOUNT_HELP": "Importo della transazione (obligatorio)", + "PARAM_COMMENT": "Riferimento (o commento)", + "PARAM_COMMENT_HELP": "Riferimento o commento. Ti può aiutare per esempio a trovare tuo pagamento nella blockchain.", + "PARAM_NAME": "Nome (de destinatario o del sito web)", + "PARAM_NAME_HELP": "Nom del sito web o del destinatario chiamando l'API. Può essere un nome leggibile (\"Mio sito\"), oppure l'indirizzo http del sito (\"MioSito.com\").", + "PARAM_REDIRECT_URL": "Indirizzo web di redirezione", + "PARAM_REDIRECT_URL_HELP": "Indirizzo web (URL) di redirezione, chiamato dopo aver inviato il pagamento. Può includere le seguenti stringe, che saranno sostituite con i valori della transazione : \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\" e {pubkey}.", + "PARAM_CANCEL_URL": "Indirizzo web della cancellazione", + "PARAM_CANCEL_URL_HELP": "Indirizzo web (URL) in caso dell'annullamento del pagamento dall'utente. Può includere le seguenti stringe, che saranno sostituite dinamicamente : \"{comment}\", \"{amount}\" e {pubkey}.", + "EXAMPLES_HELP": "Ecco esempi di integrazione :", + "EXAMPLE_BUTTON": "Bottone HTML", + "EXAMPLE_BUTTON_DEFAULT_TEXT": "Pagare in {{currency|currencySymbol}}", + "EXAMPLE_BUTTON_DEFAULT_STYLE": "Stile personnalizzato", + "EXAMPLE_BUTTON_TEXT_HELP": "Testo del bottone", + "EXAMPLE_BUTTON_BG_COLOR": "Colore del fondo", + "EXAMPLE_BUTTON_BG_COLOR_HELP": "Per esempio: #fbc14c, black, lightgrey, rgb(180,180,180)", + "EXAMPLE_BUTTON_FONT_COLOR": "Colore del testo", + "EXAMPLE_BUTTON_FONT_COLOR_HELP": "Esempio: black, orange, rgb(180,180,180)", + "EXAMPLE_BUTTON_TEXT_ICON": "Icona", + "EXAMPLE_BUTTON_TEXT_WIDTH": "Larghezza", + "EXAMPLE_BUTTON_TEXT_WIDTH_HELP": "Esempio: 200px, 50%", + "EXAMPLE_BUTTON_ICON_NONE": "Nessuna", + "EXAMPLE_BUTTON_ICON_DUNITER": "Logo Duniter", + "EXAMPLE_BUTTON_ICON_CESIUM": "Logo Cesium", + "EXAMPLE_BUTTON_ICON_G1_COLOR": "Logo Äž1", + "EXAMPLE_BUTTON_ICON_G1_BLACK": "Logo Äž1 (nero)" + } + } + } +} +); + $translateProvider.translations("nl-NL", { "COMMON": { "APP_NAME": "Cesium", @@ -3500,7 +5824,7 @@ $translateProvider.translations("nl-NL", { }, "ABOUT": { "TITLE": "Over", - "LICENSE": "<b>Vrije</b> software (GNU GPLv3 licentie).", + "LICENSE": "<b>Vrije</b> software (GNU AGPLv3 licentie).", "CODE": "Broncode:", "DEVELOPERS": "Ontwikkelaars:", "FORUM": "Forum:", @@ -3518,8 +5842,8 @@ $translateProvider.translations("nl-NL", { "BTN_ABOUT": "over", "BTN_HELP": "Help", "REPORT_ISSUE": "Meld een probleem", - "NOT_YOUR_ACCOUNT_QUESTION" : "Je hoeft niet de rekening <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> in uw bezit?", - "BTN_CHANGE_ACCOUNT": "Dit account ontkoppelen", + "NOT_YOUR_ACCOUNT_QUESTION" : "Is rekening <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> niet van jou?", + "BTN_CHANGE_ACCOUNT": "Dze rekening ontkoppelen", "CONNECTION_ERROR": "Node <b>{{server}}</b> onbereikbaar of ongeldig adres.<br/><br/>Controleer de internetverbinding, of schakel knooppunt <a class=\"positive\" ng-click=\"doQuickFix('settings')\">in parameters</a>." }, "SETTINGS": { @@ -3528,7 +5852,7 @@ $translateProvider.translations("nl-NL", { "PEER": "Duniter knooppunt adres", "PEER_CHANGED_TEMPORARY": "Adres tijdelijk worden gebruikt", "USE_LOCAL_STORAGE": "Lokale opslag inschakelen", - "USE_LOCAL_STORAGE_HELP": "Slaat uw instellingen", + "USE_LOCAL_STORAGE_HELP": "Laat je instellingen opslaan", "ENABLE_HELPTIP": "Contextgebonden hulp inschakelen", "ENABLE_UI_EFFECTS": "Schakel visuele effecten", "HISTORY_SETTINGS": "Mijn rekening", @@ -3671,7 +5995,7 @@ $translateProvider.translations("nl-NL", { "NO_GIVEN_CERTIFICATION": "Geen uitgegeven certificaties", "NOT_MEMBER_PARENTHESIS": "(niet-lid)", "IDENTITY_REVOKED_PARENTHESIS": "(ingetrokken identiteit)", - "MEMBER_PENDING_REVOCATION_PARENTHESIS": "(en cours de révocation)", + "MEMBER_PENDING_REVOCATION_PARENTHESIS": "(intrekking in behandeling)", "EXPIRE_IN": "Verloopt", "NOT_WRITTEN_EXPIRE_IN": "Uiterlijke<br/>behandeling", "EXPIRED": "Verlopen", @@ -3679,9 +6003,9 @@ $translateProvider.translations("nl-NL", { "SIGNED_ON_BLOCK": "Uitgegeven op block #{{block}}", "WRITTEN_ON_BLOCK": "Geschreven op block #{{block}}", "GENERAL_DIVIDER": "Algemene informatie", - "NOT_MEMBER_ACCOUNT": "Geen lidaccount", - "NOT_MEMBER_ACCOUNT_HELP": "Dit is een eenvoudige account zonder te wachten lidmaatschap aanvragen.", - "TECHNICAL_DIVIDER": "Technishe informatie", + "NOT_MEMBER_ACCOUNT": "Simpele rekening (geen lid)", + "NOT_MEMBER_ACCOUNT_HELP": "Dit is een eenvoudige rekening, zonder dat er een aanvraag voor lidmaatschap in de wacht wordt gezet.", + "TECHNICAL_DIVIDER": "Technische informatie", "BTN_CERTIFY": "Certificeren", "BTN_YES_CERTIFY": "Ja, Certificeren", "BTN_SELECT_AND_CERTIFY": "Nieuwe certificatie", @@ -3694,7 +6018,7 @@ $translateProvider.translations("nl-NL", { "NEWCOMERS": "Nieuwe leden:", "PENDING": "Aspirant leden:", "REGISTERED": "Geregistreerd {{sigDate | formatFromNow}}", - "MEMBER_FROM": "Lid sinds {{memberDate|formatFromNowShort}}", + "MEMBER_FROM": "Lid sinds {{memberDate|medianFromNowShort}}", "BTN_NEWCOMERS": "Nieuwste leden", "BTN_PENDING": "Registraties in afwachting", "SHOW_MORE": "Toon meer", @@ -3728,10 +6052,10 @@ $translateProvider.translations("nl-NL", { "LOGIN": { "TITLE": "<i class=\"icon ion-locked\"></i> Inloggen", "SALT": "Beveiligingszin", - "SALT_HELP": "Zin ter beveiliging van uw rekening", + "SALT_HELP": "Zin ter beveiliging van je rekening", "SHOW_SALT": "Toon de beveiligingszin", "PASSWORD": "Wachtwoord", - "PASSWORD_HELP": "Wachtwoord ter beveiliging van uw rekening", + "PASSWORD_HELP": "Wachtwoord ter beveiliging van je rekening", "NO_ACCOUNT_QUESTION": "Nog geen rekening?", "CREATE_ACCOUNT": "Open een rekening", "FORGOTTEN_ID": "Wachtwoord vergeten?" @@ -3744,7 +6068,7 @@ $translateProvider.translations("nl-NL", { "NO_TX": "Geen transacties", "SHOW_MORE_TX": "Show more", "SHOW_ALL_TX": "Show all", - "TX_FROM_DATE": "(huidige limiet op {{fromTime|formatFromNowShort}})", + "TX_FROM_DATE": "(huidige limiet op {{fromTime|medianFromNowShort}})", "PENDING_TX": "Transacties in afwachting", "ERROR_TX": "Niet uitgevoerde transacties", "ERROR_TX_SENT": "Verzonden transacties", @@ -3763,7 +6087,7 @@ $translateProvider.translations("nl-NL", { "BTN_MEMBERSHIP_RENEW_DOTS": "Lidmaatschap verlengen...", "BTN_MEMBERSHIP_OUT_DOTS": "Lidmaatschap opzeggen...", "BTN_SEND_IDENTITY_DOTS": "Identiteit publiceren...", - "BTN_SECURITY_DOTS": "Account en veiligheid...", + "BTN_SECURITY_DOTS": "Rekening en veiligheid...", "BTN_SHOW_DETAILS": "Tonen technische informatie", "BTN_REVOKE": "Deze identiteit<span class='hidden-xs hidden-sm'> definitief</span> opzeggen...", "NEW": { @@ -3774,8 +6098,8 @@ $translateProvider.translations("nl-NL", { "MEMBER_ACCOUNT_HELP": "Als je nog niet als individu geregistreerd bent (één rekening per individu mogelijk).", "WALLET_ACCOUNT": "Eenvoudige portefeille", "WALLET_ACCOUNT_HELP": "Als je een onderneming, stichting etc. vertegenwoordigd of eenvoudigweg een additionele portefeille nodig hebt. Geen individueel universeel dividend zal door deze rekening gecréeerd worden.", - "SALT_WARNING": "Kies een beveiligingszin.<br/>Deze heb je nodig voor ieder verbinding met je account.<br/><br/><b>Zorg dat je deze zin goed onthoud</b>.<br/>Eenmaal verloren, is er geen mogelijkheid om hem te achterhalen!", - "PASSWORD_WARNING": "Kies een wachtwoord.<br/>Deze heb je nodig voor ieder verbinding met je account.<br/><br/><b>Zorg dat je dit woord goed onthoud</b>.<br/>Eenmaal verloren, is er geen mogelijkheid om hem te achterhalen!", + "SALT_WARNING": "Kies een beveiligingszin.<br/>Deze heb je nodig voor ieder verbinding met je rekening.<br/><br/><b>Zorg dat je deze zin goed onthoud</b>.<br/>Eenmaal verloren, is er geen mogelijkheid om hem te achterhalen!", + "PASSWORD_WARNING": "Kies een wachtwoord.<br/>Deze heb je nodig voor ieder verbinding met je rekening.<br/><br/><b>Zorg dat je dit woord goed onthoud</b>.<br/>Eenmaal verloren, is er geen mogelijkheid om hem te achterhalen!", "PSEUDO_WARNING": "Kies een pseudoniem.<br/>Het dient om makkelijker gevonden te worden door anderen.<br/><br/>.Gebruik van spaties, komma's en accenten is niet toegestaan.<br/><div class='hidden-xs'><br/>Voorbeeld: <span class='gray'>JulesDeelder, JohanVermeer, etc.</span>", "PSEUDO": "Pseudoniem", "PSEUDO_HELP": "joe123", @@ -3883,8 +6207,8 @@ $translateProvider.translations("nl-NL", { "LOAD_PENDING_FAILED": "Unable to load pending registrations.", "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "You must <b>be a member</b> in order to perform this action.", "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "You must have <b>published your identity</b> in order to perform this action.", - "EXISTING_ACCOUNT": "Uw wachtwoord overeenkomen met een bestaande account, de <a ng-click=\"showHelpModal('pubkey')\">publieke sleutel</a> is:", - "EXISTING_ACCOUNT_REQUEST": "Gelieve uw wachtwoord wijzigen om een ongebruikte account." + "EXISTING_ACCOUNT": "Je gegevens komen overeen met een bestaande rekening, met de <a ng-click=\"showHelpModal('pubkey')\">publieke sleutel</a>:", + "EXISTING_ACCOUNT_REQUEST": "Gelieve je gegevens te wijzigen zodat ze met een niet gebruikte rekening overeenkomen." }, "INFO": { "POPUP_TITLE": "Informatie", @@ -3904,7 +6228,7 @@ $translateProvider.translations("nl-NL", { "TRANSFER": "<b>Samenvatting van de overboeking:</b><br/><br/><ul><li> - Van: <b>{{from}}</b></li><li> - Aan: <b>{{to}}</b></li><li> - Bedrag: <b>{{amount}} {{unit}}</b></li><li> - Opmerking: <i>{{comment}}</i></li></ul><br/><b>Weet je zeker dat je deze overboeking wil doen?</b>", "MEMBERSHIP_OUT": "<b>Waarschuwing</b>:<br/>Je staat op het punt je lidmaatschap te beëindigen. Dit kan <b>niet ongedaan</b> worden gemaakt.<br/></br/><b>Weet je zeker dat je door wil gaan?</b>", "LOGIN_UNUSED_WALLET_TITLE": "Typefout?", - "LOGIN_UNUSED_WALLET": "Je bent ingelogged op een rekening die <b>inactief</b> lijkt te zijn.<br/><br/>Als deze rekening niet met de uwe overeenkomt, komt dat waarschijnlijk door een <b>typefout</b> bij het inloggen.<br/><br/><b>Wilt u toch doorgaan met deze rekening?</b>", + "LOGIN_UNUSED_WALLET": "Je bent ingelogged op een rekening die <b>inactief</b> lijkt te zijn.<br/><br/>Als deze rekening niet met de jouwe overeenkomt, komt dat waarschijnlijk door een <b>typefout</b> bij het inloggen.<br/><br/><b>Wilt u toch doorgaan met deze rekening?</b>", "FIX_IDENTITY": "De pseudoniem <b>{{uid}}</b> zal opnieuw gepubliceerd worden, waarmee de oude verlopen publicatie wordt vervangen.<br/></br/><bWeet je zeker</b> dat je door wil gaan?", "FIX_MEMBERSHIP": "Je verzoek to lidmaatschap zal verstuurd worden.<br/></br/><b>Weet je het zeker?</b>", "RENEW_MEMBERSHIP": "Je lidmaatschap zal verlengd worden.<br/></br/><b>Weet je het zeker?</b>", @@ -3916,8 +6240,8 @@ $translateProvider.translations("nl-NL", { "LICENCE": "Ik heb gelezen en geaccepteerd de voorwaarden van de vergunning G1" }, "DOWNLOAD": { - "POPUP_TITLE": "<b>Intrekking File</b>", - "POPUP_REVOKE_MESSAGE": "Om uw account te beveiligen, het downloaden van de <b>Account intrekking document</b>. U zult indien nodig om uw account (annuleren in het geval van de rekening van diefstal, een verandering van de identifier, een ten onrechte gemaakte account, etc.).<br/><br/><b>Bewaar deze op een veilige plaats.</b>" + "POPUP_TITLE": "<b>Intrekkingsdocument</b>", + "POPUP_REVOKE_MESSAGE": "Om je rekening te beveiligen, download het <b>rekening intrekkingsdocument</b>. Dit heb je nodig om je rekening op te heffen (in het geval van diefstal, een verandering van ID, een ten onrechte gemaakte rekening, etc.).<br/><br/><b>Bewaar deze op een veilige plaats.</b>" }, "HELP": { "TITLE": "Online help", diff --git a/assets/www/dist/dist_js/app/vendor/Chart.js b/assets/www/dist/dist_js/app/vendor/Chart.js deleted file mode 100644 index bfd195ff09b5e2ae1def1892f71c019541d4864f..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/Chart.js +++ /dev/null @@ -1,12269 +0,0 @@ -/*! - * Chart.js - * http://chartjs.org/ - * Version: 2.5.0 - * - * Copyright 2017 Nick Downie - * Released under the MIT license - * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md - */ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Chart = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ - -},{}],2:[function(require,module,exports){ - /* MIT license */ - var colorNames = require(6); - - module.exports = { - getRgba: getRgba, - getHsla: getHsla, - getRgb: getRgb, - getHsl: getHsl, - getHwb: getHwb, - getAlpha: getAlpha, - - hexString: hexString, - rgbString: rgbString, - rgbaString: rgbaString, - percentString: percentString, - percentaString: percentaString, - hslString: hslString, - hslaString: hslaString, - hwbString: hwbString, - keyword: keyword - } - - function getRgba(string) { - if (!string) { - return; - } - var abbr = /^#([a-fA-F0-9]{3})$/, - hex = /^#([a-fA-F0-9]{6})$/, - rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/, - per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/, - keyword = /(\w+)/; - - var rgb = [0, 0, 0], - a = 1, - match = string.match(abbr); - if (match) { - match = match[1]; - for (var i = 0; i < rgb.length; i++) { - rgb[i] = parseInt(match[i] + match[i], 16); - } - } - else if (match = string.match(hex)) { - match = match[1]; - for (var i = 0; i < rgb.length; i++) { - rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16); - } - } - else if (match = string.match(rgba)) { - for (var i = 0; i < rgb.length; i++) { - rgb[i] = parseInt(match[i + 1]); - } - a = parseFloat(match[4]); - } - else if (match = string.match(per)) { - for (var i = 0; i < rgb.length; i++) { - rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); - } - a = parseFloat(match[4]); - } - else if (match = string.match(keyword)) { - if (match[1] == "transparent") { - return [0, 0, 0, 0]; - } - rgb = colorNames[match[1]]; - if (!rgb) { - return; - } - } - - for (var i = 0; i < rgb.length; i++) { - rgb[i] = scale(rgb[i], 0, 255); - } - if (!a && a != 0) { - a = 1; - } - else { - a = scale(a, 0, 1); - } - rgb[3] = a; - return rgb; - } - - function getHsla(string) { - if (!string) { - return; - } - var hsl = /^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; - var match = string.match(hsl); - if (match) { - var alpha = parseFloat(match[4]); - var h = scale(parseInt(match[1]), 0, 360), - s = scale(parseFloat(match[2]), 0, 100), - l = scale(parseFloat(match[3]), 0, 100), - a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); - return [h, s, l, a]; - } - } - - function getHwb(string) { - if (!string) { - return; - } - var hwb = /^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; - var match = string.match(hwb); - if (match) { - var alpha = parseFloat(match[4]); - var h = scale(parseInt(match[1]), 0, 360), - w = scale(parseFloat(match[2]), 0, 100), - b = scale(parseFloat(match[3]), 0, 100), - a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); - return [h, w, b, a]; - } - } - - function getRgb(string) { - var rgba = getRgba(string); - return rgba && rgba.slice(0, 3); - } - - function getHsl(string) { - var hsla = getHsla(string); - return hsla && hsla.slice(0, 3); - } - - function getAlpha(string) { - var vals = getRgba(string); - if (vals) { - return vals[3]; - } - else if (vals = getHsla(string)) { - return vals[3]; - } - else if (vals = getHwb(string)) { - return vals[3]; - } - } - -// generators - function hexString(rgb) { - return "#" + hexDouble(rgb[0]) + hexDouble(rgb[1]) - + hexDouble(rgb[2]); - } - - function rgbString(rgba, alpha) { - if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { - return rgbaString(rgba, alpha); - } - return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")"; - } - - function rgbaString(rgba, alpha) { - if (alpha === undefined) { - alpha = (rgba[3] !== undefined ? rgba[3] : 1); - } - return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] - + ", " + alpha + ")"; - } - - function percentString(rgba, alpha) { - if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { - return percentaString(rgba, alpha); - } - var r = Math.round(rgba[0]/255 * 100), - g = Math.round(rgba[1]/255 * 100), - b = Math.round(rgba[2]/255 * 100); - - return "rgb(" + r + "%, " + g + "%, " + b + "%)"; - } - - function percentaString(rgba, alpha) { - var r = Math.round(rgba[0]/255 * 100), - g = Math.round(rgba[1]/255 * 100), - b = Math.round(rgba[2]/255 * 100); - return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 1) + ")"; - } - - function hslString(hsla, alpha) { - if (alpha < 1 || (hsla[3] && hsla[3] < 1)) { - return hslaString(hsla, alpha); - } - return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)"; - } - - function hslaString(hsla, alpha) { - if (alpha === undefined) { - alpha = (hsla[3] !== undefined ? hsla[3] : 1); - } - return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " - + alpha + ")"; - } - -// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax -// (hwb have alpha optional & 1 is default value) - function hwbString(hwb, alpha) { - if (alpha === undefined) { - alpha = (hwb[3] !== undefined ? hwb[3] : 1); - } - return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%" - + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")"; - } - - function keyword(rgb) { - return reverseNames[rgb.slice(0, 3)]; - } - -// helpers - function scale(num, min, max) { - return Math.min(Math.max(min, num), max); - } - - function hexDouble(num) { - var str = num.toString(16).toUpperCase(); - return (str.length < 2) ? "0" + str : str; - } - - -//create a list of reverse color names - var reverseNames = {}; - for (var name in colorNames) { - reverseNames[colorNames[name]] = name; - } - -},{"6":6}],3:[function(require,module,exports){ - /* MIT license */ - var convert = require(5); - var string = require(2); - - var Color = function (obj) { - if (obj instanceof Color) { - return obj; - } - if (!(this instanceof Color)) { - return new Color(obj); - } - - this.values = { - rgb: [0, 0, 0], - hsl: [0, 0, 0], - hsv: [0, 0, 0], - hwb: [0, 0, 0], - cmyk: [0, 0, 0, 0], - alpha: 1 - }; - - // parse Color() argument - var vals; - if (typeof obj === 'string') { - vals = string.getRgba(obj); - if (vals) { - this.setValues('rgb', vals); - } else if (vals = string.getHsla(obj)) { - this.setValues('hsl', vals); - } else if (vals = string.getHwb(obj)) { - this.setValues('hwb', vals); - } else { - throw new Error('Unable to parse color from string "' + obj + '"'); - } - } else if (typeof obj === 'object') { - vals = obj; - if (vals.r !== undefined || vals.red !== undefined) { - this.setValues('rgb', vals); - } else if (vals.l !== undefined || vals.lightness !== undefined) { - this.setValues('hsl', vals); - } else if (vals.v !== undefined || vals.value !== undefined) { - this.setValues('hsv', vals); - } else if (vals.w !== undefined || vals.whiteness !== undefined) { - this.setValues('hwb', vals); - } else if (vals.c !== undefined || vals.cyan !== undefined) { - this.setValues('cmyk', vals); - } else { - throw new Error('Unable to parse color from object ' + JSON.stringify(obj)); - } - } - }; - - Color.prototype = { - rgb: function () { - return this.setSpace('rgb', arguments); - }, - hsl: function () { - return this.setSpace('hsl', arguments); - }, - hsv: function () { - return this.setSpace('hsv', arguments); - }, - hwb: function () { - return this.setSpace('hwb', arguments); - }, - cmyk: function () { - return this.setSpace('cmyk', arguments); - }, - - rgbArray: function () { - return this.values.rgb; - }, - hslArray: function () { - return this.values.hsl; - }, - hsvArray: function () { - return this.values.hsv; - }, - hwbArray: function () { - var values = this.values; - if (values.alpha !== 1) { - return values.hwb.concat([values.alpha]); - } - return values.hwb; - }, - cmykArray: function () { - return this.values.cmyk; - }, - rgbaArray: function () { - var values = this.values; - return values.rgb.concat([values.alpha]); - }, - hslaArray: function () { - var values = this.values; - return values.hsl.concat([values.alpha]); - }, - alpha: function (val) { - if (val === undefined) { - return this.values.alpha; - } - this.setValues('alpha', val); - return this; - }, - - red: function (val) { - return this.setChannel('rgb', 0, val); - }, - green: function (val) { - return this.setChannel('rgb', 1, val); - }, - blue: function (val) { - return this.setChannel('rgb', 2, val); - }, - hue: function (val) { - if (val) { - val %= 360; - val = val < 0 ? 360 + val : val; - } - return this.setChannel('hsl', 0, val); - }, - saturation: function (val) { - return this.setChannel('hsl', 1, val); - }, - lightness: function (val) { - return this.setChannel('hsl', 2, val); - }, - saturationv: function (val) { - return this.setChannel('hsv', 1, val); - }, - whiteness: function (val) { - return this.setChannel('hwb', 1, val); - }, - blackness: function (val) { - return this.setChannel('hwb', 2, val); - }, - value: function (val) { - return this.setChannel('hsv', 2, val); - }, - cyan: function (val) { - return this.setChannel('cmyk', 0, val); - }, - magenta: function (val) { - return this.setChannel('cmyk', 1, val); - }, - yellow: function (val) { - return this.setChannel('cmyk', 2, val); - }, - black: function (val) { - return this.setChannel('cmyk', 3, val); - }, - - hexString: function () { - return string.hexString(this.values.rgb); - }, - rgbString: function () { - return string.rgbString(this.values.rgb, this.values.alpha); - }, - rgbaString: function () { - return string.rgbaString(this.values.rgb, this.values.alpha); - }, - percentString: function () { - return string.percentString(this.values.rgb, this.values.alpha); - }, - hslString: function () { - return string.hslString(this.values.hsl, this.values.alpha); - }, - hslaString: function () { - return string.hslaString(this.values.hsl, this.values.alpha); - }, - hwbString: function () { - return string.hwbString(this.values.hwb, this.values.alpha); - }, - keyword: function () { - return string.keyword(this.values.rgb, this.values.alpha); - }, - - rgbNumber: function () { - var rgb = this.values.rgb; - return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]; - }, - - luminosity: function () { - // http://www.w3.org/TR/WCAG20/#relativeluminancedef - var rgb = this.values.rgb; - var lum = []; - for (var i = 0; i < rgb.length; i++) { - var chan = rgb[i] / 255; - lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4); - } - return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; - }, - - contrast: function (color2) { - // http://www.w3.org/TR/WCAG20/#contrast-ratiodef - var lum1 = this.luminosity(); - var lum2 = color2.luminosity(); - if (lum1 > lum2) { - return (lum1 + 0.05) / (lum2 + 0.05); - } - return (lum2 + 0.05) / (lum1 + 0.05); - }, - - level: function (color2) { - var contrastRatio = this.contrast(color2); - if (contrastRatio >= 7.1) { - return 'AAA'; - } - - return (contrastRatio >= 4.5) ? 'AA' : ''; - }, - - dark: function () { - // YIQ equation from http://24ways.org/2010/calculating-color-contrast - var rgb = this.values.rgb; - var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; - return yiq < 128; - }, - - light: function () { - return !this.dark(); - }, - - negate: function () { - var rgb = []; - for (var i = 0; i < 3; i++) { - rgb[i] = 255 - this.values.rgb[i]; - } - this.setValues('rgb', rgb); - return this; - }, - - lighten: function (ratio) { - var hsl = this.values.hsl; - hsl[2] += hsl[2] * ratio; - this.setValues('hsl', hsl); - return this; - }, - - darken: function (ratio) { - var hsl = this.values.hsl; - hsl[2] -= hsl[2] * ratio; - this.setValues('hsl', hsl); - return this; - }, - - saturate: function (ratio) { - var hsl = this.values.hsl; - hsl[1] += hsl[1] * ratio; - this.setValues('hsl', hsl); - return this; - }, - - desaturate: function (ratio) { - var hsl = this.values.hsl; - hsl[1] -= hsl[1] * ratio; - this.setValues('hsl', hsl); - return this; - }, - - whiten: function (ratio) { - var hwb = this.values.hwb; - hwb[1] += hwb[1] * ratio; - this.setValues('hwb', hwb); - return this; - }, - - blacken: function (ratio) { - var hwb = this.values.hwb; - hwb[2] += hwb[2] * ratio; - this.setValues('hwb', hwb); - return this; - }, - - greyscale: function () { - var rgb = this.values.rgb; - // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale - var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; - this.setValues('rgb', [val, val, val]); - return this; - }, - - clearer: function (ratio) { - var alpha = this.values.alpha; - this.setValues('alpha', alpha - (alpha * ratio)); - return this; - }, - - opaquer: function (ratio) { - var alpha = this.values.alpha; - this.setValues('alpha', alpha + (alpha * ratio)); - return this; - }, - - rotate: function (degrees) { - var hsl = this.values.hsl; - var hue = (hsl[0] + degrees) % 360; - hsl[0] = hue < 0 ? 360 + hue : hue; - this.setValues('hsl', hsl); - return this; - }, - - /** - * Ported from sass implementation in C - * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 - */ - mix: function (mixinColor, weight) { - var color1 = this; - var color2 = mixinColor; - var p = weight === undefined ? 0.5 : weight; - - var w = 2 * p - 1; - var a = color1.alpha() - color2.alpha(); - - var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - return this - .rgb( - w1 * color1.red() + w2 * color2.red(), - w1 * color1.green() + w2 * color2.green(), - w1 * color1.blue() + w2 * color2.blue() - ) - .alpha(color1.alpha() * p + color2.alpha() * (1 - p)); - }, - - toJSON: function () { - return this.rgb(); - }, - - clone: function () { - // NOTE(SB): using node-clone creates a dependency to Buffer when using browserify, - // making the final build way to big to embed in Chart.js. So let's do it manually, - // assuming that values to clone are 1 dimension arrays containing only numbers, - // except 'alpha' which is a number. - var result = new Color(); - var source = this.values; - var target = result.values; - var value, type; - - for (var prop in source) { - if (source.hasOwnProperty(prop)) { - value = source[prop]; - type = ({}).toString.call(value); - if (type === '[object Array]') { - target[prop] = value.slice(0); - } else if (type === '[object Number]') { - target[prop] = value; - } else { - console.error('unexpected color value:', value); - } - } - } - - return result; - } - }; - - Color.prototype.spaces = { - rgb: ['red', 'green', 'blue'], - hsl: ['hue', 'saturation', 'lightness'], - hsv: ['hue', 'saturation', 'value'], - hwb: ['hue', 'whiteness', 'blackness'], - cmyk: ['cyan', 'magenta', 'yellow', 'black'] - }; - - Color.prototype.maxes = { - rgb: [255, 255, 255], - hsl: [360, 100, 100], - hsv: [360, 100, 100], - hwb: [360, 100, 100], - cmyk: [100, 100, 100, 100] - }; - - Color.prototype.getValues = function (space) { - var values = this.values; - var vals = {}; - - for (var i = 0; i < space.length; i++) { - vals[space.charAt(i)] = values[space][i]; - } - - if (values.alpha !== 1) { - vals.a = values.alpha; - } - - // {r: 255, g: 255, b: 255, a: 0.4} - return vals; - }; - - Color.prototype.setValues = function (space, vals) { - var values = this.values; - var spaces = this.spaces; - var maxes = this.maxes; - var alpha = 1; - var i; - - if (space === 'alpha') { - alpha = vals; - } else if (vals.length) { - // [10, 10, 10] - values[space] = vals.slice(0, space.length); - alpha = vals[space.length]; - } else if (vals[space.charAt(0)] !== undefined) { - // {r: 10, g: 10, b: 10} - for (i = 0; i < space.length; i++) { - values[space][i] = vals[space.charAt(i)]; - } - - alpha = vals.a; - } else if (vals[spaces[space][0]] !== undefined) { - // {red: 10, green: 10, blue: 10} - var chans = spaces[space]; - - for (i = 0; i < space.length; i++) { - values[space][i] = vals[chans[i]]; - } - - alpha = vals.alpha; - } - - values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha))); - - if (space === 'alpha') { - return false; - } - - var capped; - - // cap values of the space prior converting all values - for (i = 0; i < space.length; i++) { - capped = Math.max(0, Math.min(maxes[space][i], values[space][i])); - values[space][i] = Math.round(capped); - } - - // convert to all the other color spaces - for (var sname in spaces) { - if (sname !== space) { - values[sname] = convert[space][sname](values[space]); - } - } - - return true; - }; - - Color.prototype.setSpace = function (space, args) { - var vals = args[0]; - - if (vals === undefined) { - // color.rgb() - return this.getValues(space); - } - - // color.rgb(10, 10, 10) - if (typeof vals === 'number') { - vals = Array.prototype.slice.call(args); - } - - this.setValues(space, vals); - return this; - }; - - Color.prototype.setChannel = function (space, index, val) { - var svalues = this.values[space]; - if (val === undefined) { - // color.red() - return svalues[index]; - } else if (val === svalues[index]) { - // color.red(color.red()) - return this; - } - - // color.red(100) - svalues[index] = val; - this.setValues(space, svalues); - - return this; - }; - - if (typeof window !== 'undefined') { - window.Color = Color; - } - - module.exports = Color; - -},{"2":2,"5":5}],4:[function(require,module,exports){ - /* MIT license */ - - module.exports = { - rgb2hsl: rgb2hsl, - rgb2hsv: rgb2hsv, - rgb2hwb: rgb2hwb, - rgb2cmyk: rgb2cmyk, - rgb2keyword: rgb2keyword, - rgb2xyz: rgb2xyz, - rgb2lab: rgb2lab, - rgb2lch: rgb2lch, - - hsl2rgb: hsl2rgb, - hsl2hsv: hsl2hsv, - hsl2hwb: hsl2hwb, - hsl2cmyk: hsl2cmyk, - hsl2keyword: hsl2keyword, - - hsv2rgb: hsv2rgb, - hsv2hsl: hsv2hsl, - hsv2hwb: hsv2hwb, - hsv2cmyk: hsv2cmyk, - hsv2keyword: hsv2keyword, - - hwb2rgb: hwb2rgb, - hwb2hsl: hwb2hsl, - hwb2hsv: hwb2hsv, - hwb2cmyk: hwb2cmyk, - hwb2keyword: hwb2keyword, - - cmyk2rgb: cmyk2rgb, - cmyk2hsl: cmyk2hsl, - cmyk2hsv: cmyk2hsv, - cmyk2hwb: cmyk2hwb, - cmyk2keyword: cmyk2keyword, - - keyword2rgb: keyword2rgb, - keyword2hsl: keyword2hsl, - keyword2hsv: keyword2hsv, - keyword2hwb: keyword2hwb, - keyword2cmyk: keyword2cmyk, - keyword2lab: keyword2lab, - keyword2xyz: keyword2xyz, - - xyz2rgb: xyz2rgb, - xyz2lab: xyz2lab, - xyz2lch: xyz2lch, - - lab2xyz: lab2xyz, - lab2rgb: lab2rgb, - lab2lch: lab2lch, - - lch2lab: lch2lab, - lch2xyz: lch2xyz, - lch2rgb: lch2rgb - } - - - function rgb2hsl(rgb) { - var r = rgb[0]/255, - g = rgb[1]/255, - b = rgb[2]/255, - min = Math.min(r, g, b), - max = Math.max(r, g, b), - delta = max - min, - h, s, l; - - if (max == min) - h = 0; - else if (r == max) - h = (g - b) / delta; - else if (g == max) - h = 2 + (b - r) / delta; - else if (b == max) - h = 4 + (r - g)/ delta; - - h = Math.min(h * 60, 360); - - if (h < 0) - h += 360; - - l = (min + max) / 2; - - if (max == min) - s = 0; - else if (l <= 0.5) - s = delta / (max + min); - else - s = delta / (2 - max - min); - - return [h, s * 100, l * 100]; - } - - function rgb2hsv(rgb) { - var r = rgb[0], - g = rgb[1], - b = rgb[2], - min = Math.min(r, g, b), - max = Math.max(r, g, b), - delta = max - min, - h, s, v; - - if (max == 0) - s = 0; - else - s = (delta/max * 1000)/10; - - if (max == min) - h = 0; - else if (r == max) - h = (g - b) / delta; - else if (g == max) - h = 2 + (b - r) / delta; - else if (b == max) - h = 4 + (r - g) / delta; - - h = Math.min(h * 60, 360); - - if (h < 0) - h += 360; - - v = ((max / 255) * 1000) / 10; - - return [h, s, v]; - } - - function rgb2hwb(rgb) { - var r = rgb[0], - g = rgb[1], - b = rgb[2], - h = rgb2hsl(rgb)[0], - w = 1/255 * Math.min(r, Math.min(g, b)), - b = 1 - 1/255 * Math.max(r, Math.max(g, b)); - - return [h, w * 100, b * 100]; - } - - function rgb2cmyk(rgb) { - var r = rgb[0] / 255, - g = rgb[1] / 255, - b = rgb[2] / 255, - c, m, y, k; - - k = Math.min(1 - r, 1 - g, 1 - b); - c = (1 - r - k) / (1 - k) || 0; - m = (1 - g - k) / (1 - k) || 0; - y = (1 - b - k) / (1 - k) || 0; - return [c * 100, m * 100, y * 100, k * 100]; - } - - function rgb2keyword(rgb) { - return reverseKeywords[JSON.stringify(rgb)]; - } - - function rgb2xyz(rgb) { - var r = rgb[0] / 255, - g = rgb[1] / 255, - b = rgb[2] / 255; - - // assume sRGB - r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); - g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); - b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); - - var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); - var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); - var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); - - return [x * 100, y *100, z * 100]; - } - - function rgb2lab(rgb) { - var xyz = rgb2xyz(rgb), - x = xyz[0], - y = xyz[1], - z = xyz[2], - l, a, b; - - x /= 95.047; - y /= 100; - z /= 108.883; - - x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116); - - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); - - return [l, a, b]; - } - - function rgb2lch(args) { - return lab2lch(rgb2lab(args)); - } - - function hsl2rgb(hsl) { - var h = hsl[0] / 360, - s = hsl[1] / 100, - l = hsl[2] / 100, - t1, t2, t3, rgb, val; - - if (s == 0) { - val = l * 255; - return [val, val, val]; - } - - if (l < 0.5) - t2 = l * (1 + s); - else - t2 = l + s - l * s; - t1 = 2 * l - t2; - - rgb = [0, 0, 0]; - for (var i = 0; i < 3; i++) { - t3 = h + 1 / 3 * - (i - 1); - t3 < 0 && t3++; - t3 > 1 && t3--; - - if (6 * t3 < 1) - val = t1 + (t2 - t1) * 6 * t3; - else if (2 * t3 < 1) - val = t2; - else if (3 * t3 < 2) - val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; - else - val = t1; - - rgb[i] = val * 255; - } - - return rgb; - } - - function hsl2hsv(hsl) { - var h = hsl[0], - s = hsl[1] / 100, - l = hsl[2] / 100, - sv, v; - - if(l === 0) { - // no need to do calc on black - // also avoids divide by 0 error - return [0, 0, 0]; - } - - l *= 2; - s *= (l <= 1) ? l : 2 - l; - v = (l + s) / 2; - sv = (2 * s) / (l + s); - return [h, sv * 100, v * 100]; - } - - function hsl2hwb(args) { - return rgb2hwb(hsl2rgb(args)); - } - - function hsl2cmyk(args) { - return rgb2cmyk(hsl2rgb(args)); - } - - function hsl2keyword(args) { - return rgb2keyword(hsl2rgb(args)); - } - - - function hsv2rgb(hsv) { - var h = hsv[0] / 60, - s = hsv[1] / 100, - v = hsv[2] / 100, - hi = Math.floor(h) % 6; - - var f = h - Math.floor(h), - p = 255 * v * (1 - s), - q = 255 * v * (1 - (s * f)), - t = 255 * v * (1 - (s * (1 - f))), - v = 255 * v; - - switch(hi) { - case 0: - return [v, t, p]; - case 1: - return [q, v, p]; - case 2: - return [p, v, t]; - case 3: - return [p, q, v]; - case 4: - return [t, p, v]; - case 5: - return [v, p, q]; - } - } - - function hsv2hsl(hsv) { - var h = hsv[0], - s = hsv[1] / 100, - v = hsv[2] / 100, - sl, l; - - l = (2 - s) * v; - sl = s * v; - sl /= (l <= 1) ? l : 2 - l; - sl = sl || 0; - l /= 2; - return [h, sl * 100, l * 100]; - } - - function hsv2hwb(args) { - return rgb2hwb(hsv2rgb(args)) - } - - function hsv2cmyk(args) { - return rgb2cmyk(hsv2rgb(args)); - } - - function hsv2keyword(args) { - return rgb2keyword(hsv2rgb(args)); - } - -// http://dev.w3.org/csswg/css-color/#hwb-to-rgb - function hwb2rgb(hwb) { - var h = hwb[0] / 360, - wh = hwb[1] / 100, - bl = hwb[2] / 100, - ratio = wh + bl, - i, v, f, n; - - // wh + bl cant be > 1 - if (ratio > 1) { - wh /= ratio; - bl /= ratio; - } - - i = Math.floor(6 * h); - v = 1 - bl; - f = 6 * h - i; - if ((i & 0x01) != 0) { - f = 1 - f; - } - n = wh + f * (v - wh); // linear interpolation - - switch (i) { - default: - case 6: - case 0: r = v; g = n; b = wh; break; - case 1: r = n; g = v; b = wh; break; - case 2: r = wh; g = v; b = n; break; - case 3: r = wh; g = n; b = v; break; - case 4: r = n; g = wh; b = v; break; - case 5: r = v; g = wh; b = n; break; - } - - return [r * 255, g * 255, b * 255]; - } - - function hwb2hsl(args) { - return rgb2hsl(hwb2rgb(args)); - } - - function hwb2hsv(args) { - return rgb2hsv(hwb2rgb(args)); - } - - function hwb2cmyk(args) { - return rgb2cmyk(hwb2rgb(args)); - } - - function hwb2keyword(args) { - return rgb2keyword(hwb2rgb(args)); - } - - function cmyk2rgb(cmyk) { - var c = cmyk[0] / 100, - m = cmyk[1] / 100, - y = cmyk[2] / 100, - k = cmyk[3] / 100, - r, g, b; - - r = 1 - Math.min(1, c * (1 - k) + k); - g = 1 - Math.min(1, m * (1 - k) + k); - b = 1 - Math.min(1, y * (1 - k) + k); - return [r * 255, g * 255, b * 255]; - } - - function cmyk2hsl(args) { - return rgb2hsl(cmyk2rgb(args)); - } - - function cmyk2hsv(args) { - return rgb2hsv(cmyk2rgb(args)); - } - - function cmyk2hwb(args) { - return rgb2hwb(cmyk2rgb(args)); - } - - function cmyk2keyword(args) { - return rgb2keyword(cmyk2rgb(args)); - } - - - function xyz2rgb(xyz) { - var x = xyz[0] / 100, - y = xyz[1] / 100, - z = xyz[2] / 100, - r, g, b; - - r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); - g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); - b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); - - // assume sRGB - r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) - : r = (r * 12.92); - - g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) - : g = (g * 12.92); - - b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) - : b = (b * 12.92); - - r = Math.min(Math.max(0, r), 1); - g = Math.min(Math.max(0, g), 1); - b = Math.min(Math.max(0, b), 1); - - return [r * 255, g * 255, b * 255]; - } - - function xyz2lab(xyz) { - var x = xyz[0], - y = xyz[1], - z = xyz[2], - l, a, b; - - x /= 95.047; - y /= 100; - z /= 108.883; - - x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116); - - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); - - return [l, a, b]; - } - - function xyz2lch(args) { - return lab2lch(xyz2lab(args)); - } - - function lab2xyz(lab) { - var l = lab[0], - a = lab[1], - b = lab[2], - x, y, z, y2; - - if (l <= 8) { - y = (l * 100) / 903.3; - y2 = (7.787 * (y / 100)) + (16 / 116); - } else { - y = 100 * Math.pow((l + 16) / 116, 3); - y2 = Math.pow(y / 100, 1/3); - } - - x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 7.787 : 95.047 * Math.pow((a / 500) + y2, 3); - - z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) / 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3); - - return [x, y, z]; - } - - function lab2lch(lab) { - var l = lab[0], - a = lab[1], - b = lab[2], - hr, h, c; - - hr = Math.atan2(b, a); - h = hr * 360 / 2 / Math.PI; - if (h < 0) { - h += 360; - } - c = Math.sqrt(a * a + b * b); - return [l, c, h]; - } - - function lab2rgb(args) { - return xyz2rgb(lab2xyz(args)); - } - - function lch2lab(lch) { - var l = lch[0], - c = lch[1], - h = lch[2], - a, b, hr; - - hr = h / 360 * 2 * Math.PI; - a = c * Math.cos(hr); - b = c * Math.sin(hr); - return [l, a, b]; - } - - function lch2xyz(args) { - return lab2xyz(lch2lab(args)); - } - - function lch2rgb(args) { - return lab2rgb(lch2lab(args)); - } - - function keyword2rgb(keyword) { - return cssKeywords[keyword]; - } - - function keyword2hsl(args) { - return rgb2hsl(keyword2rgb(args)); - } - - function keyword2hsv(args) { - return rgb2hsv(keyword2rgb(args)); - } - - function keyword2hwb(args) { - return rgb2hwb(keyword2rgb(args)); - } - - function keyword2cmyk(args) { - return rgb2cmyk(keyword2rgb(args)); - } - - function keyword2lab(args) { - return rgb2lab(keyword2rgb(args)); - } - - function keyword2xyz(args) { - return rgb2xyz(keyword2rgb(args)); - } - - var cssKeywords = { - aliceblue: [240,248,255], - antiquewhite: [250,235,215], - aqua: [0,255,255], - aquamarine: [127,255,212], - azure: [240,255,255], - beige: [245,245,220], - bisque: [255,228,196], - black: [0,0,0], - blanchedalmond: [255,235,205], - blue: [0,0,255], - blueviolet: [138,43,226], - brown: [165,42,42], - burlywood: [222,184,135], - cadetblue: [95,158,160], - chartreuse: [127,255,0], - chocolate: [210,105,30], - coral: [255,127,80], - cornflowerblue: [100,149,237], - cornsilk: [255,248,220], - crimson: [220,20,60], - cyan: [0,255,255], - darkblue: [0,0,139], - darkcyan: [0,139,139], - darkgoldenrod: [184,134,11], - darkgray: [169,169,169], - darkgreen: [0,100,0], - darkgrey: [169,169,169], - darkkhaki: [189,183,107], - darkmagenta: [139,0,139], - darkolivegreen: [85,107,47], - darkorange: [255,140,0], - darkorchid: [153,50,204], - darkred: [139,0,0], - darksalmon: [233,150,122], - darkseagreen: [143,188,143], - darkslateblue: [72,61,139], - darkslategray: [47,79,79], - darkslategrey: [47,79,79], - darkturquoise: [0,206,209], - darkviolet: [148,0,211], - deeppink: [255,20,147], - deepskyblue: [0,191,255], - dimgray: [105,105,105], - dimgrey: [105,105,105], - dodgerblue: [30,144,255], - firebrick: [178,34,34], - floralwhite: [255,250,240], - forestgreen: [34,139,34], - fuchsia: [255,0,255], - gainsboro: [220,220,220], - ghostwhite: [248,248,255], - gold: [255,215,0], - goldenrod: [218,165,32], - gray: [128,128,128], - green: [0,128,0], - greenyellow: [173,255,47], - grey: [128,128,128], - honeydew: [240,255,240], - hotpink: [255,105,180], - indianred: [205,92,92], - indigo: [75,0,130], - ivory: [255,255,240], - khaki: [240,230,140], - lavender: [230,230,250], - lavenderblush: [255,240,245], - lawngreen: [124,252,0], - lemonchiffon: [255,250,205], - lightblue: [173,216,230], - lightcoral: [240,128,128], - lightcyan: [224,255,255], - lightgoldenrodyellow: [250,250,210], - lightgray: [211,211,211], - lightgreen: [144,238,144], - lightgrey: [211,211,211], - lightpink: [255,182,193], - lightsalmon: [255,160,122], - lightseagreen: [32,178,170], - lightskyblue: [135,206,250], - lightslategray: [119,136,153], - lightslategrey: [119,136,153], - lightsteelblue: [176,196,222], - lightyellow: [255,255,224], - lime: [0,255,0], - limegreen: [50,205,50], - linen: [250,240,230], - magenta: [255,0,255], - maroon: [128,0,0], - mediumaquamarine: [102,205,170], - mediumblue: [0,0,205], - mediumorchid: [186,85,211], - mediumpurple: [147,112,219], - mediumseagreen: [60,179,113], - mediumslateblue: [123,104,238], - mediumspringgreen: [0,250,154], - mediumturquoise: [72,209,204], - mediumvioletred: [199,21,133], - midnightblue: [25,25,112], - mintcream: [245,255,250], - mistyrose: [255,228,225], - moccasin: [255,228,181], - navajowhite: [255,222,173], - navy: [0,0,128], - oldlace: [253,245,230], - olive: [128,128,0], - olivedrab: [107,142,35], - orange: [255,165,0], - orangered: [255,69,0], - orchid: [218,112,214], - palegoldenrod: [238,232,170], - palegreen: [152,251,152], - paleturquoise: [175,238,238], - palevioletred: [219,112,147], - papayawhip: [255,239,213], - peachpuff: [255,218,185], - peru: [205,133,63], - pink: [255,192,203], - plum: [221,160,221], - powderblue: [176,224,230], - purple: [128,0,128], - rebeccapurple: [102, 51, 153], - red: [255,0,0], - rosybrown: [188,143,143], - royalblue: [65,105,225], - saddlebrown: [139,69,19], - salmon: [250,128,114], - sandybrown: [244,164,96], - seagreen: [46,139,87], - seashell: [255,245,238], - sienna: [160,82,45], - silver: [192,192,192], - skyblue: [135,206,235], - slateblue: [106,90,205], - slategray: [112,128,144], - slategrey: [112,128,144], - snow: [255,250,250], - springgreen: [0,255,127], - steelblue: [70,130,180], - tan: [210,180,140], - teal: [0,128,128], - thistle: [216,191,216], - tomato: [255,99,71], - turquoise: [64,224,208], - violet: [238,130,238], - wheat: [245,222,179], - white: [255,255,255], - whitesmoke: [245,245,245], - yellow: [255,255,0], - yellowgreen: [154,205,50] - }; - - var reverseKeywords = {}; - for (var key in cssKeywords) { - reverseKeywords[JSON.stringify(cssKeywords[key])] = key; - } - -},{}],5:[function(require,module,exports){ - var conversions = require(4); - - var convert = function() { - return new Converter(); - } - - for (var func in conversions) { - // export Raw versions - convert[func + "Raw"] = (function(func) { - // accept array or plain args - return function(arg) { - if (typeof arg == "number") - arg = Array.prototype.slice.call(arguments); - return conversions[func](arg); - } - })(func); - - var pair = /(\w+)2(\w+)/.exec(func), - from = pair[1], - to = pair[2]; - - // export rgb2hsl and ["rgb"]["hsl"] - convert[from] = convert[from] || {}; - - convert[from][to] = convert[func] = (function(func) { - return function(arg) { - if (typeof arg == "number") - arg = Array.prototype.slice.call(arguments); - - var val = conversions[func](arg); - if (typeof val == "string" || val === undefined) - return val; // keyword - - for (var i = 0; i < val.length; i++) - val[i] = Math.round(val[i]); - return val; - } - })(func); - } - - - /* Converter does lazy conversion and caching */ - var Converter = function() { - this.convs = {}; - }; - - /* Either get the values for a space or - set the values for a space, depending on args */ - Converter.prototype.routeSpace = function(space, args) { - var values = args[0]; - if (values === undefined) { - // color.rgb() - return this.getValues(space); - } - // color.rgb(10, 10, 10) - if (typeof values == "number") { - values = Array.prototype.slice.call(args); - } - - return this.setValues(space, values); - }; - - /* Set the values for a space, invalidating cache */ - Converter.prototype.setValues = function(space, values) { - this.space = space; - this.convs = {}; - this.convs[space] = values; - return this; - }; - - /* Get the values for a space. If there's already - a conversion for the space, fetch it, otherwise - compute it */ - Converter.prototype.getValues = function(space) { - var vals = this.convs[space]; - if (!vals) { - var fspace = this.space, - from = this.convs[fspace]; - vals = convert[fspace][space](from); - - this.convs[space] = vals; - } - return vals; - }; - - ["rgb", "hsl", "hsv", "cmyk", "keyword"].forEach(function(space) { - Converter.prototype[space] = function(vals) { - return this.routeSpace(space, arguments); - } - }); - - module.exports = convert; -},{"4":4}],6:[function(require,module,exports){ - module.exports = { - "aliceblue": [240, 248, 255], - "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], - "aquamarine": [127, 255, 212], - "azure": [240, 255, 255], - "beige": [245, 245, 220], - "bisque": [255, 228, 196], - "black": [0, 0, 0], - "blanchedalmond": [255, 235, 205], - "blue": [0, 0, 255], - "blueviolet": [138, 43, 226], - "brown": [165, 42, 42], - "burlywood": [222, 184, 135], - "cadetblue": [95, 158, 160], - "chartreuse": [127, 255, 0], - "chocolate": [210, 105, 30], - "coral": [255, 127, 80], - "cornflowerblue": [100, 149, 237], - "cornsilk": [255, 248, 220], - "crimson": [220, 20, 60], - "cyan": [0, 255, 255], - "darkblue": [0, 0, 139], - "darkcyan": [0, 139, 139], - "darkgoldenrod": [184, 134, 11], - "darkgray": [169, 169, 169], - "darkgreen": [0, 100, 0], - "darkgrey": [169, 169, 169], - "darkkhaki": [189, 183, 107], - "darkmagenta": [139, 0, 139], - "darkolivegreen": [85, 107, 47], - "darkorange": [255, 140, 0], - "darkorchid": [153, 50, 204], - "darkred": [139, 0, 0], - "darksalmon": [233, 150, 122], - "darkseagreen": [143, 188, 143], - "darkslateblue": [72, 61, 139], - "darkslategray": [47, 79, 79], - "darkslategrey": [47, 79, 79], - "darkturquoise": [0, 206, 209], - "darkviolet": [148, 0, 211], - "deeppink": [255, 20, 147], - "deepskyblue": [0, 191, 255], - "dimgray": [105, 105, 105], - "dimgrey": [105, 105, 105], - "dodgerblue": [30, 144, 255], - "firebrick": [178, 34, 34], - "floralwhite": [255, 250, 240], - "forestgreen": [34, 139, 34], - "fuchsia": [255, 0, 255], - "gainsboro": [220, 220, 220], - "ghostwhite": [248, 248, 255], - "gold": [255, 215, 0], - "goldenrod": [218, 165, 32], - "gray": [128, 128, 128], - "green": [0, 128, 0], - "greenyellow": [173, 255, 47], - "grey": [128, 128, 128], - "honeydew": [240, 255, 240], - "hotpink": [255, 105, 180], - "indianred": [205, 92, 92], - "indigo": [75, 0, 130], - "ivory": [255, 255, 240], - "khaki": [240, 230, 140], - "lavender": [230, 230, 250], - "lavenderblush": [255, 240, 245], - "lawngreen": [124, 252, 0], - "lemonchiffon": [255, 250, 205], - "lightblue": [173, 216, 230], - "lightcoral": [240, 128, 128], - "lightcyan": [224, 255, 255], - "lightgoldenrodyellow": [250, 250, 210], - "lightgray": [211, 211, 211], - "lightgreen": [144, 238, 144], - "lightgrey": [211, 211, 211], - "lightpink": [255, 182, 193], - "lightsalmon": [255, 160, 122], - "lightseagreen": [32, 178, 170], - "lightskyblue": [135, 206, 250], - "lightslategray": [119, 136, 153], - "lightslategrey": [119, 136, 153], - "lightsteelblue": [176, 196, 222], - "lightyellow": [255, 255, 224], - "lime": [0, 255, 0], - "limegreen": [50, 205, 50], - "linen": [250, 240, 230], - "magenta": [255, 0, 255], - "maroon": [128, 0, 0], - "mediumaquamarine": [102, 205, 170], - "mediumblue": [0, 0, 205], - "mediumorchid": [186, 85, 211], - "mediumpurple": [147, 112, 219], - "mediumseagreen": [60, 179, 113], - "mediumslateblue": [123, 104, 238], - "mediumspringgreen": [0, 250, 154], - "mediumturquoise": [72, 209, 204], - "mediumvioletred": [199, 21, 133], - "midnightblue": [25, 25, 112], - "mintcream": [245, 255, 250], - "mistyrose": [255, 228, 225], - "moccasin": [255, 228, 181], - "navajowhite": [255, 222, 173], - "navy": [0, 0, 128], - "oldlace": [253, 245, 230], - "olive": [128, 128, 0], - "olivedrab": [107, 142, 35], - "orange": [255, 165, 0], - "orangered": [255, 69, 0], - "orchid": [218, 112, 214], - "palegoldenrod": [238, 232, 170], - "palegreen": [152, 251, 152], - "paleturquoise": [175, 238, 238], - "palevioletred": [219, 112, 147], - "papayawhip": [255, 239, 213], - "peachpuff": [255, 218, 185], - "peru": [205, 133, 63], - "pink": [255, 192, 203], - "plum": [221, 160, 221], - "powderblue": [176, 224, 230], - "purple": [128, 0, 128], - "rebeccapurple": [102, 51, 153], - "red": [255, 0, 0], - "rosybrown": [188, 143, 143], - "royalblue": [65, 105, 225], - "saddlebrown": [139, 69, 19], - "salmon": [250, 128, 114], - "sandybrown": [244, 164, 96], - "seagreen": [46, 139, 87], - "seashell": [255, 245, 238], - "sienna": [160, 82, 45], - "silver": [192, 192, 192], - "skyblue": [135, 206, 235], - "slateblue": [106, 90, 205], - "slategray": [112, 128, 144], - "slategrey": [112, 128, 144], - "snow": [255, 250, 250], - "springgreen": [0, 255, 127], - "steelblue": [70, 130, 180], - "tan": [210, 180, 140], - "teal": [0, 128, 128], - "thistle": [216, 191, 216], - "tomato": [255, 99, 71], - "turquoise": [64, 224, 208], - "violet": [238, 130, 238], - "wheat": [245, 222, 179], - "white": [255, 255, 255], - "whitesmoke": [245, 245, 245], - "yellow": [255, 255, 0], - "yellowgreen": [154, 205, 50] - }; -},{}],7:[function(require,module,exports){ - /** - * @namespace Chart - */ - var Chart = require(28)(); - - require(26)(Chart); - require(42)(Chart); - require(22)(Chart); - require(31)(Chart); - require(25)(Chart); - require(21)(Chart); - require(23)(Chart); - require(24)(Chart); - require(29)(Chart); - require(33)(Chart); - require(34)(Chart); - require(32)(Chart); - require(35)(Chart); - require(30)(Chart); - require(27)(Chart); - require(36)(Chart); - - require(37)(Chart); - require(38)(Chart); - require(39)(Chart); - require(40)(Chart); - - require(45)(Chart); - require(43)(Chart); - require(44)(Chart); - require(46)(Chart); - require(47)(Chart); - require(48)(Chart); - -// Controllers must be loaded after elements -// See Chart.core.datasetController.dataElementType - require(15)(Chart); - require(16)(Chart); - require(17)(Chart); - require(18)(Chart); - require(19)(Chart); - require(20)(Chart); - - require(8)(Chart); - require(9)(Chart); - require(10)(Chart); - require(11)(Chart); - require(12)(Chart); - require(13)(Chart); - require(14)(Chart); - - window.Chart = module.exports = Chart; - -},{"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16,"17":17,"18":18,"19":19,"20":20,"21":21,"22":22,"23":23,"24":24,"25":25,"26":26,"27":27,"28":28,"29":29,"30":30,"31":31,"32":32,"33":33,"34":34,"35":35,"36":36,"37":37,"38":38,"39":39,"40":40,"42":42,"43":43,"44":44,"45":45,"46":46,"47":47,"48":48,"8":8,"9":9}],8:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.Bar = function(context, config) { - config.type = 'bar'; - - return new Chart(context, config); - }; - - }; - -},{}],9:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.Bubble = function(context, config) { - config.type = 'bubble'; - return new Chart(context, config); - }; - - }; - -},{}],10:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.Doughnut = function(context, config) { - config.type = 'doughnut'; - - return new Chart(context, config); - }; - - }; - -},{}],11:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.Line = function(context, config) { - config.type = 'line'; - - return new Chart(context, config); - }; - - }; - -},{}],12:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.PolarArea = function(context, config) { - config.type = 'polarArea'; - - return new Chart(context, config); - }; - - }; - -},{}],13:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.Radar = function(context, config) { - config.type = 'radar'; - - return new Chart(context, config); - }; - - }; - -},{}],14:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var defaultConfig = { - hover: { - mode: 'single' - }, - - scales: { - xAxes: [{ - type: 'linear', // scatter should not use a category axis - position: 'bottom', - id: 'x-axis-1' // need an ID so datasets can reference the scale - }], - yAxes: [{ - type: 'linear', - position: 'left', - id: 'y-axis-1' - }] - }, - - tooltips: { - callbacks: { - title: function() { - // Title doesn't make sense for scatter since we format the data as a point - return ''; - }, - label: function(tooltipItem) { - return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')'; - } - } - } - }; - - // Register the default config for this type - Chart.defaults.scatter = defaultConfig; - - // Scatter charts use line controllers - Chart.controllers.scatter = Chart.controllers.line; - - Chart.Scatter = function(context, config) { - config.type = 'scatter'; - return new Chart(context, config); - }; - - }; - -},{}],15:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.bar = { - hover: { - mode: 'label' - }, - - scales: { - xAxes: [{ - type: 'category', - - // Specific to Bar Controller - categoryPercentage: 0.8, - barPercentage: 0.9, - - // grid line settings - gridLines: { - offsetGridLines: true - } - }], - yAxes: [{ - type: 'linear' - }] - } - }; - - Chart.controllers.bar = Chart.DatasetController.extend({ - - dataElementType: Chart.elements.Rectangle, - - initialize: function(chart, datasetIndex) { - Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex); - - var me = this; - var meta = me.getMeta(); - var dataset = me.getDataset(); - - meta.stack = dataset.stack; - // Use this to indicate that this is a bar dataset. - meta.bar = true; - }, - - // Correctly calculate the bar width accounting for stacks and the fact that not all bars are visible - getStackCount: function() { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - - var stacks = []; - helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) { - var dsMeta = me.chart.getDatasetMeta(datasetIndex); - if (dsMeta.bar && me.chart.isDatasetVisible(datasetIndex) && - (yScale.options.stacked === false || - (yScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) || - (yScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) { - stacks.push(dsMeta.stack); - } - }, me); - - return stacks.length; - }, - - update: function(reset) { - var me = this; - helpers.each(me.getMeta().data, function(rectangle, index) { - me.updateElement(rectangle, index, reset); - }, me); - }, - - updateElement: function(rectangle, index, reset) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var yScale = me.getScaleForId(meta.yAxisID); - var scaleBase = yScale.getBasePixel(); - var rectangleElementOptions = me.chart.options.elements.rectangle; - var custom = rectangle.custom || {}; - var dataset = me.getDataset(); - - rectangle._xScale = xScale; - rectangle._yScale = yScale; - rectangle._datasetIndex = me.index; - rectangle._index = index; - - var ruler = me.getRuler(index); // The index argument for compatible - rectangle._model = { - x: me.calculateBarX(index, me.index, ruler), - y: reset ? scaleBase : me.calculateBarY(index, me.index), - - // Tooltip - label: me.chart.data.labels[index], - datasetLabel: dataset.label, - - // Appearance - horizontal: false, - base: reset ? scaleBase : me.calculateBarBase(me.index, index), - width: me.calculateBarWidth(ruler), - backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor), - borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped, - borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor), - borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth) - }; - - rectangle.pivot(); - }, - - calculateBarBase: function(datasetIndex, index) { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - var base = yScale.getBaseValue(); - var original = base; - - if ((yScale.options.stacked === true) || - (yScale.options.stacked === undefined && meta.stack !== undefined)) { - var chart = me.chart; - var datasets = chart.data.datasets; - var value = Number(datasets[datasetIndex].data[index]); - - for (var i = 0; i < datasetIndex; i++) { - var currentDs = datasets[i]; - var currentDsMeta = chart.getDatasetMeta(i); - if (currentDsMeta.bar && currentDsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i) && - meta.stack === currentDsMeta.stack) { - var currentVal = Number(currentDs.data[index]); - base += value < 0 ? Math.min(currentVal, original) : Math.max(currentVal, original); - } - } - - return yScale.getPixelForValue(base); - } - - return yScale.getBasePixel(); - }, - - getRuler: function() { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var stackCount = me.getStackCount(); - - var tickWidth = xScale.width / xScale.ticks.length; - var categoryWidth = tickWidth * xScale.options.categoryPercentage; - var categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2; - var fullBarWidth = categoryWidth / stackCount; - - var barWidth = fullBarWidth * xScale.options.barPercentage; - var barSpacing = fullBarWidth - (fullBarWidth * xScale.options.barPercentage); - - return { - stackCount: stackCount, - tickWidth: tickWidth, - categoryWidth: categoryWidth, - categorySpacing: categorySpacing, - fullBarWidth: fullBarWidth, - barWidth: barWidth, - barSpacing: barSpacing - }; - }, - - calculateBarWidth: function(ruler) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - if (xScale.options.barThickness) { - return xScale.options.barThickness; - } - return ruler.barWidth; - }, - - // Get stack index from the given dataset index accounting for stacks and the fact that not all bars are visible - getStackIndex: function(datasetIndex) { - var me = this; - var meta = me.chart.getDatasetMeta(datasetIndex); - var yScale = me.getScaleForId(meta.yAxisID); - var dsMeta, j; - var stacks = [meta.stack]; - - for (j = 0; j < datasetIndex; ++j) { - dsMeta = this.chart.getDatasetMeta(j); - if (dsMeta.bar && this.chart.isDatasetVisible(j) && - (yScale.options.stacked === false || - (yScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) || - (yScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) { - stacks.push(dsMeta.stack); - } - } - - return stacks.length - 1; - }, - - calculateBarX: function(index, datasetIndex, ruler) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var stackIndex = me.getStackIndex(datasetIndex); - var leftTick = xScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo); - leftTick -= me.chart.isCombo ? (ruler.tickWidth / 2) : 0; - - return leftTick + - (ruler.barWidth / 2) + - ruler.categorySpacing + - (ruler.barWidth * stackIndex) + - (ruler.barSpacing / 2) + - (ruler.barSpacing * stackIndex); - }, - - calculateBarY: function(index, datasetIndex) { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - var value = Number(me.getDataset().data[index]); - - if (yScale.options.stacked || - (yScale.options.stacked === undefined && meta.stack !== undefined)) { - var base = yScale.getBaseValue(); - var sumPos = base, - sumNeg = base; - - for (var i = 0; i < datasetIndex; i++) { - var ds = me.chart.data.datasets[i]; - var dsMeta = me.chart.getDatasetMeta(i); - if (dsMeta.bar && dsMeta.yAxisID === yScale.id && me.chart.isDatasetVisible(i) && - meta.stack === dsMeta.stack) { - var stackedVal = Number(ds.data[index]); - if (stackedVal < 0) { - sumNeg += stackedVal || 0; - } else { - sumPos += stackedVal || 0; - } - } - } - - if (value < 0) { - return yScale.getPixelForValue(sumNeg + value); - } - return yScale.getPixelForValue(sumPos + value); - } - - return yScale.getPixelForValue(value); - }, - - draw: function(ease) { - var me = this; - var easingDecimal = ease || 1; - var metaData = me.getMeta().data; - var dataset = me.getDataset(); - var i, len; - - Chart.canvasHelpers.clipArea(me.chart.chart.ctx, me.chart.chartArea); - for (i = 0, len = metaData.length; i < len; ++i) { - var d = dataset.data[i]; - if (d !== null && d !== undefined && !isNaN(d)) { - metaData[i].transition(easingDecimal).draw(); - } - } - Chart.canvasHelpers.unclipArea(me.chart.chart.ctx); - }, - - setHoverStyle: function(rectangle) { - var dataset = this.chart.data.datasets[rectangle._datasetIndex]; - var index = rectangle._index; - - var custom = rectangle.custom || {}; - var model = rectangle._model; - model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor)); - model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor)); - model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth); - }, - - removeHoverStyle: function(rectangle) { - var dataset = this.chart.data.datasets[rectangle._datasetIndex]; - var index = rectangle._index; - var custom = rectangle.custom || {}; - var model = rectangle._model; - var rectangleElementOptions = this.chart.options.elements.rectangle; - - model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor); - model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor); - model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth); - } - - }); - - - // including horizontalBar in the bar file, instead of a file of its own - // it extends bar (like pie extends doughnut) - Chart.defaults.horizontalBar = { - hover: { - mode: 'label' - }, - - scales: { - xAxes: [{ - type: 'linear', - position: 'bottom' - }], - yAxes: [{ - position: 'left', - type: 'category', - - // Specific to Horizontal Bar Controller - categoryPercentage: 0.8, - barPercentage: 0.9, - - // grid line settings - gridLines: { - offsetGridLines: true - } - }] - }, - elements: { - rectangle: { - borderSkipped: 'left' - } - }, - tooltips: { - callbacks: { - title: function(tooltipItems, data) { - // Pick first xLabel for now - var title = ''; - - if (tooltipItems.length > 0) { - if (tooltipItems[0].yLabel) { - title = tooltipItems[0].yLabel; - } else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) { - title = data.labels[tooltipItems[0].index]; - } - } - - return title; - }, - label: function(tooltipItem, data) { - var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || ''; - return datasetLabel + ': ' + tooltipItem.xLabel; - } - } - } - }; - - Chart.controllers.horizontalBar = Chart.controllers.bar.extend({ - - // Correctly calculate the bar width accounting for stacks and the fact that not all bars are visible - getStackCount: function() { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - - var stacks = []; - helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) { - var dsMeta = me.chart.getDatasetMeta(datasetIndex); - if (dsMeta.bar && me.chart.isDatasetVisible(datasetIndex) && - (xScale.options.stacked === false || - (xScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) || - (xScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) { - stacks.push(dsMeta.stack); - } - }, me); - - return stacks.length; - }, - - updateElement: function(rectangle, index, reset) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var yScale = me.getScaleForId(meta.yAxisID); - var scaleBase = xScale.getBasePixel(); - var custom = rectangle.custom || {}; - var dataset = me.getDataset(); - var rectangleElementOptions = me.chart.options.elements.rectangle; - - rectangle._xScale = xScale; - rectangle._yScale = yScale; - rectangle._datasetIndex = me.index; - rectangle._index = index; - - var ruler = me.getRuler(index); // The index argument for compatible - rectangle._model = { - x: reset ? scaleBase : me.calculateBarX(index, me.index), - y: me.calculateBarY(index, me.index, ruler), - - // Tooltip - label: me.chart.data.labels[index], - datasetLabel: dataset.label, - - // Appearance - horizontal: true, - base: reset ? scaleBase : me.calculateBarBase(me.index, index), - height: me.calculateBarHeight(ruler), - backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor), - borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped, - borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor), - borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth) - }; - - rectangle.pivot(); - }, - - calculateBarBase: function(datasetIndex, index) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var base = xScale.getBaseValue(); - var originalBase = base; - - if (xScale.options.stacked || - (xScale.options.stacked === undefined && meta.stack !== undefined)) { - var chart = me.chart; - var datasets = chart.data.datasets; - var value = Number(datasets[datasetIndex].data[index]); - - for (var i = 0; i < datasetIndex; i++) { - var currentDs = datasets[i]; - var currentDsMeta = chart.getDatasetMeta(i); - if (currentDsMeta.bar && currentDsMeta.xAxisID === xScale.id && chart.isDatasetVisible(i) && - meta.stack === currentDsMeta.stack) { - var currentVal = Number(currentDs.data[index]); - base += value < 0 ? Math.min(currentVal, originalBase) : Math.max(currentVal, originalBase); - } - } - - return xScale.getPixelForValue(base); - } - - return xScale.getBasePixel(); - }, - - getRuler: function() { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - var stackCount = me.getStackCount(); - - var tickHeight = yScale.height / yScale.ticks.length; - var categoryHeight = tickHeight * yScale.options.categoryPercentage; - var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2; - var fullBarHeight = categoryHeight / stackCount; - - var barHeight = fullBarHeight * yScale.options.barPercentage; - var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage); - - return { - stackCount: stackCount, - tickHeight: tickHeight, - categoryHeight: categoryHeight, - categorySpacing: categorySpacing, - fullBarHeight: fullBarHeight, - barHeight: barHeight, - barSpacing: barSpacing - }; - }, - - calculateBarHeight: function(ruler) { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - if (yScale.options.barThickness) { - return yScale.options.barThickness; - } - return ruler.barHeight; - }, - - // Get stack index from the given dataset index accounting for stacks and the fact that not all bars are visible - getStackIndex: function(datasetIndex) { - var me = this; - var meta = me.chart.getDatasetMeta(datasetIndex); - var xScale = me.getScaleForId(meta.xAxisID); - var dsMeta, j; - var stacks = [meta.stack]; - - for (j = 0; j < datasetIndex; ++j) { - dsMeta = this.chart.getDatasetMeta(j); - if (dsMeta.bar && this.chart.isDatasetVisible(j) && - (xScale.options.stacked === false || - (xScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) || - (xScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) { - stacks.push(dsMeta.stack); - } - } - - return stacks.length - 1; - }, - - calculateBarX: function(index, datasetIndex) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var value = Number(me.getDataset().data[index]); - - if (xScale.options.stacked || - (xScale.options.stacked === undefined && meta.stack !== undefined)) { - var base = xScale.getBaseValue(); - var sumPos = base, - sumNeg = base; - - for (var i = 0; i < datasetIndex; i++) { - var ds = me.chart.data.datasets[i]; - var dsMeta = me.chart.getDatasetMeta(i); - if (dsMeta.bar && dsMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i) && - meta.stack === dsMeta.stack) { - var stackedVal = Number(ds.data[index]); - if (stackedVal < 0) { - sumNeg += stackedVal || 0; - } else { - sumPos += stackedVal || 0; - } - } - } - - if (value < 0) { - return xScale.getPixelForValue(sumNeg + value); - } - return xScale.getPixelForValue(sumPos + value); - } - - return xScale.getPixelForValue(value); - }, - - calculateBarY: function(index, datasetIndex, ruler) { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - var stackIndex = me.getStackIndex(datasetIndex); - var topTick = yScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo); - topTick -= me.chart.isCombo ? (ruler.tickHeight / 2) : 0; - - return topTick + - (ruler.barHeight / 2) + - ruler.categorySpacing + - (ruler.barHeight * stackIndex) + - (ruler.barSpacing / 2) + - (ruler.barSpacing * stackIndex); - } - }); - }; - -},{}],16:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.bubble = { - hover: { - mode: 'single' - }, - - scales: { - xAxes: [{ - type: 'linear', // bubble should probably use a linear scale by default - position: 'bottom', - id: 'x-axis-0' // need an ID so datasets can reference the scale - }], - yAxes: [{ - type: 'linear', - position: 'left', - id: 'y-axis-0' - }] - }, - - tooltips: { - callbacks: { - title: function() { - // Title doesn't make sense for scatter since we format the data as a point - return ''; - }, - label: function(tooltipItem, data) { - var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || ''; - var dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; - return datasetLabel + ': (' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ', ' + dataPoint.r + ')'; - } - } - } - }; - - Chart.controllers.bubble = Chart.DatasetController.extend({ - - dataElementType: Chart.elements.Point, - - update: function(reset) { - var me = this; - var meta = me.getMeta(); - var points = meta.data; - - // Update Points - helpers.each(points, function(point, index) { - me.updateElement(point, index, reset); - }); - }, - - updateElement: function(point, index, reset) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var yScale = me.getScaleForId(meta.yAxisID); - - var custom = point.custom || {}; - var dataset = me.getDataset(); - var data = dataset.data[index]; - var pointElementOptions = me.chart.options.elements.point; - var dsIndex = me.index; - - helpers.extend(point, { - // Utility - _xScale: xScale, - _yScale: yScale, - _datasetIndex: dsIndex, - _index: index, - - // Desired view properties - _model: { - x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex, me.chart.isCombo), - y: reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex), - // Appearance - radius: reset ? 0 : custom.radius ? custom.radius : me.getRadius(data), - - // Tooltip - hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius) - } - }); - - // Trick to reset the styles of the point - Chart.DatasetController.prototype.removeHoverStyle.call(me, point, pointElementOptions); - - var model = point._model; - model.skip = custom.skip ? custom.skip : (isNaN(model.x) || isNaN(model.y)); - - point.pivot(); - }, - - getRadius: function(value) { - return value.r || this.chart.options.elements.point.radius; - }, - - setHoverStyle: function(point) { - var me = this; - Chart.DatasetController.prototype.setHoverStyle.call(me, point); - - // Radius - var dataset = me.chart.data.datasets[point._datasetIndex]; - var index = point._index; - var custom = point.custom || {}; - var model = point._model; - model.radius = custom.hoverRadius ? custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, me.chart.options.elements.point.hoverRadius)) + me.getRadius(dataset.data[index]); - }, - - removeHoverStyle: function(point) { - var me = this; - Chart.DatasetController.prototype.removeHoverStyle.call(me, point, me.chart.options.elements.point); - - var dataVal = me.chart.data.datasets[point._datasetIndex].data[point._index]; - var custom = point.custom || {}; - var model = point._model; - - model.radius = custom.radius ? custom.radius : me.getRadius(dataVal); - } - }); - }; - -},{}],17:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers, - defaults = Chart.defaults; - - defaults.doughnut = { - animation: { - // Boolean - Whether we animate the rotation of the Doughnut - animateRotate: true, - // Boolean - Whether we animate scaling the Doughnut from the centre - animateScale: false - }, - aspectRatio: 1, - hover: { - mode: 'single' - }, - legendCallback: function(chart) { - var text = []; - text.push('<ul class="' + chart.id + '-legend">'); - - var data = chart.data; - var datasets = data.datasets; - var labels = data.labels; - - if (datasets.length) { - for (var i = 0; i < datasets[0].data.length; ++i) { - text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>'); - if (labels[i]) { - text.push(labels[i]); - } - text.push('</li>'); - } - } - - text.push('</ul>'); - return text.join(''); - }, - legend: { - labels: { - generateLabels: function(chart) { - var data = chart.data; - if (data.labels.length && data.datasets.length) { - return data.labels.map(function(label, i) { - var meta = chart.getDatasetMeta(0); - var ds = data.datasets[0]; - var arc = meta.data[i]; - var custom = arc && arc.custom || {}; - var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault; - var arcOpts = chart.options.elements.arc; - var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor); - var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor); - var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth); - - return { - text: label, - fillStyle: fill, - strokeStyle: stroke, - lineWidth: bw, - hidden: isNaN(ds.data[i]) || meta.data[i].hidden, - - // Extra data used for toggling the correct item - index: i - }; - }); - } - return []; - } - }, - - onClick: function(e, legendItem) { - var index = legendItem.index; - var chart = this.chart; - var i, ilen, meta; - - for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { - meta = chart.getDatasetMeta(i); - // toggle visibility of index if exists - if (meta.data[index]) { - meta.data[index].hidden = !meta.data[index].hidden; - } - } - - chart.update(); - } - }, - - // The percentage of the chart that we cut out of the middle. - cutoutPercentage: 50, - - // The rotation of the chart, where the first data arc begins. - rotation: Math.PI * -0.5, - - // The total circumference of the chart. - circumference: Math.PI * 2.0, - - // Need to override these to give a nice default - tooltips: { - callbacks: { - title: function() { - return ''; - }, - label: function(tooltipItem, data) { - var dataLabel = data.labels[tooltipItem.index]; - var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; - - if (helpers.isArray(dataLabel)) { - // show value on first line of multiline label - // need to clone because we are changing the value - dataLabel = dataLabel.slice(); - dataLabel[0] += value; - } else { - dataLabel += value; - } - - return dataLabel; - } - } - } - }; - - defaults.pie = helpers.clone(defaults.doughnut); - helpers.extend(defaults.pie, { - cutoutPercentage: 0 - }); - - - Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({ - - dataElementType: Chart.elements.Arc, - - linkScales: helpers.noop, - - // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly - getRingIndex: function(datasetIndex) { - var ringIndex = 0; - - for (var j = 0; j < datasetIndex; ++j) { - if (this.chart.isDatasetVisible(j)) { - ++ringIndex; - } - } - - return ringIndex; - }, - - update: function(reset) { - var me = this; - var chart = me.chart, - chartArea = chart.chartArea, - opts = chart.options, - arcOpts = opts.elements.arc, - availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth, - availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth, - minSize = Math.min(availableWidth, availableHeight), - offset = { - x: 0, - y: 0 - }, - meta = me.getMeta(), - cutoutPercentage = opts.cutoutPercentage, - circumference = opts.circumference; - - // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc - if (circumference < Math.PI * 2.0) { - var startAngle = opts.rotation % (Math.PI * 2.0); - startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0); - var endAngle = startAngle + circumference; - var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)}; - var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)}; - var contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle); - var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle); - var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle); - var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle); - var cutout = cutoutPercentage / 100.0; - var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))}; - var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))}; - var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5}; - minSize = Math.min(availableWidth / size.width, availableHeight / size.height); - offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5}; - } - - chart.borderWidth = me.getMaxBorderWidth(meta.data); - chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0); - chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0); - chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount(); - chart.offsetX = offset.x * chart.outerRadius; - chart.offsetY = offset.y * chart.outerRadius; - - meta.total = me.calculateTotal(); - - me.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index)); - me.innerRadius = Math.max(me.outerRadius - chart.radiusLength, 0); - - helpers.each(meta.data, function(arc, index) { - me.updateElement(arc, index, reset); - }); - }, - - updateElement: function(arc, index, reset) { - var me = this; - var chart = me.chart, - chartArea = chart.chartArea, - opts = chart.options, - animationOpts = opts.animation, - centerX = (chartArea.left + chartArea.right) / 2, - centerY = (chartArea.top + chartArea.bottom) / 2, - startAngle = opts.rotation, // non reset case handled later - endAngle = opts.rotation, // non reset case handled later - dataset = me.getDataset(), - circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)), - innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius, - outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius, - valueAtIndexOrDefault = helpers.getValueAtIndexOrDefault; - - helpers.extend(arc, { - // Utility - _datasetIndex: me.index, - _index: index, - - // Desired view properties - _model: { - x: centerX + chart.offsetX, - y: centerY + chart.offsetY, - startAngle: startAngle, - endAngle: endAngle, - circumference: circumference, - outerRadius: outerRadius, - innerRadius: innerRadius, - label: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index]) - } - }); - - var model = arc._model; - // Resets the visual styles - this.removeHoverStyle(arc); - - // Set correct angles if not resetting - if (!reset || !animationOpts.animateRotate) { - if (index === 0) { - model.startAngle = opts.rotation; - } else { - model.startAngle = me.getMeta().data[index - 1]._model.endAngle; - } - - model.endAngle = model.startAngle + model.circumference; - } - - arc.pivot(); - }, - - removeHoverStyle: function(arc) { - Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc); - }, - - calculateTotal: function() { - var dataset = this.getDataset(); - var meta = this.getMeta(); - var total = 0; - var value; - - helpers.each(meta.data, function(element, index) { - value = dataset.data[index]; - if (!isNaN(value) && !element.hidden) { - total += Math.abs(value); - } - }); - - /* if (total === 0) { - total = NaN; - }*/ - - return total; - }, - - calculateCircumference: function(value) { - var total = this.getMeta().total; - if (total > 0 && !isNaN(value)) { - return (Math.PI * 2.0) * (value / total); - } - return 0; - }, - - // gets the max border or hover width to properly scale pie charts - getMaxBorderWidth: function(elements) { - var max = 0, - index = this.index, - length = elements.length, - borderWidth, - hoverWidth; - - for (var i = 0; i < length; i++) { - borderWidth = elements[i]._model ? elements[i]._model.borderWidth : 0; - hoverWidth = elements[i]._chart ? elements[i]._chart.config.data.datasets[index].hoverBorderWidth : 0; - - max = borderWidth > max ? borderWidth : max; - max = hoverWidth > max ? hoverWidth : max; - } - return max; - } - }); - }; - -},{}],18:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.line = { - showLines: true, - spanGaps: false, - - hover: { - mode: 'label' - }, - - scales: { - xAxes: [{ - type: 'category', - id: 'x-axis-0' - }], - yAxes: [{ - type: 'linear', - id: 'y-axis-0' - }] - } - }; - - function lineEnabled(dataset, options) { - return helpers.getValueOrDefault(dataset.showLine, options.showLines); - } - - Chart.controllers.line = Chart.DatasetController.extend({ - - datasetElementType: Chart.elements.Line, - - dataElementType: Chart.elements.Point, - - update: function(reset) { - var me = this; - var meta = me.getMeta(); - var line = meta.dataset; - var points = meta.data || []; - var options = me.chart.options; - var lineElementOptions = options.elements.line; - var scale = me.getScaleForId(meta.yAxisID); - var i, ilen, custom; - var dataset = me.getDataset(); - var showLine = lineEnabled(dataset, options); - - // Update Line - if (showLine) { - custom = line.custom || {}; - - // Compatibility: If the properties are defined with only the old name, use those values - if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) { - dataset.lineTension = dataset.tension; - } - - // Utility - line._scale = scale; - line._datasetIndex = me.index; - // Data - line._children = points; - // Model - line._model = { - // Appearance - // The default behavior of lines is to break at null values, according - // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158 - // This option gives lines the ability to span gaps - spanGaps: dataset.spanGaps ? dataset.spanGaps : options.spanGaps, - tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension), - backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor), - borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth), - borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor), - borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle), - borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash), - borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset), - borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle), - fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill), - steppedLine: custom.steppedLine ? custom.steppedLine : helpers.getValueOrDefault(dataset.steppedLine, lineElementOptions.stepped), - cubicInterpolationMode: custom.cubicInterpolationMode ? custom.cubicInterpolationMode : helpers.getValueOrDefault(dataset.cubicInterpolationMode, lineElementOptions.cubicInterpolationMode), - // Scale - scaleTop: scale.top, - scaleBottom: scale.bottom, - scaleZero: scale.getBasePixel() - }; - - line.pivot(); - } - - // Update Points - for (i=0, ilen=points.length; i<ilen; ++i) { - me.updateElement(points[i], i, reset); - } - - if (showLine && line._model.tension !== 0) { - me.updateBezierControlPoints(); - } - - // Now pivot the point for animation - for (i=0, ilen=points.length; i<ilen; ++i) { - points[i].pivot(); - } - }, - - getPointBackgroundColor: function(point, index) { - var backgroundColor = this.chart.options.elements.point.backgroundColor; - var dataset = this.getDataset(); - var custom = point.custom || {}; - - if (custom.backgroundColor) { - backgroundColor = custom.backgroundColor; - } else if (dataset.pointBackgroundColor) { - backgroundColor = helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor); - } else if (dataset.backgroundColor) { - backgroundColor = dataset.backgroundColor; - } - - return backgroundColor; - }, - - getPointBorderColor: function(point, index) { - var borderColor = this.chart.options.elements.point.borderColor; - var dataset = this.getDataset(); - var custom = point.custom || {}; - - if (custom.borderColor) { - borderColor = custom.borderColor; - } else if (dataset.pointBorderColor) { - borderColor = helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor); - } else if (dataset.borderColor) { - borderColor = dataset.borderColor; - } - - return borderColor; - }, - - getPointBorderWidth: function(point, index) { - var borderWidth = this.chart.options.elements.point.borderWidth; - var dataset = this.getDataset(); - var custom = point.custom || {}; - - if (!isNaN(custom.borderWidth)) { - borderWidth = custom.borderWidth; - } else if (!isNaN(dataset.pointBorderWidth)) { - borderWidth = helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth); - } else if (!isNaN(dataset.borderWidth)) { - borderWidth = dataset.borderWidth; - } - - return borderWidth; - }, - - updateElement: function(point, index, reset) { - var me = this; - var meta = me.getMeta(); - var custom = point.custom || {}; - var dataset = me.getDataset(); - var datasetIndex = me.index; - var value = dataset.data[index]; - var yScale = me.getScaleForId(meta.yAxisID); - var xScale = me.getScaleForId(meta.xAxisID); - var pointOptions = me.chart.options.elements.point; - var x, y; - var labels = me.chart.data.labels || []; - var includeOffset = (labels.length === 1 || dataset.data.length === 1) || me.chart.isCombo; - - // Compatibility: If the properties are defined with only the old name, use those values - if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) { - dataset.pointRadius = dataset.radius; - } - if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) { - dataset.pointHitRadius = dataset.hitRadius; - } - - x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex, includeOffset); - y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex); - - // Utility - point._xScale = xScale; - point._yScale = yScale; - point._datasetIndex = datasetIndex; - point._index = index; - - // Desired view properties - point._model = { - x: x, - y: y, - skip: custom.skip || isNaN(x) || isNaN(y), - // Appearance - radius: custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius), - pointStyle: custom.pointStyle || helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle), - backgroundColor: me.getPointBackgroundColor(point, index), - borderColor: me.getPointBorderColor(point, index), - borderWidth: me.getPointBorderWidth(point, index), - tension: meta.dataset._model ? meta.dataset._model.tension : 0, - steppedLine: meta.dataset._model ? meta.dataset._model.steppedLine : false, - // Tooltip - hitRadius: custom.hitRadius || helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius) - }; - }, - - calculatePointY: function(value, index, datasetIndex) { - var me = this; - var chart = me.chart; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - var sumPos = 0; - var sumNeg = 0; - var i, ds, dsMeta; - - if (yScale.options.stacked) { - for (i = 0; i < datasetIndex; i++) { - ds = chart.data.datasets[i]; - dsMeta = chart.getDatasetMeta(i); - if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) { - var stackedRightValue = Number(yScale.getRightValue(ds.data[index])); - if (stackedRightValue < 0) { - sumNeg += stackedRightValue || 0; - } else { - sumPos += stackedRightValue || 0; - } - } - } - - var rightValue = Number(yScale.getRightValue(value)); - if (rightValue < 0) { - return yScale.getPixelForValue(sumNeg + rightValue); - } - return yScale.getPixelForValue(sumPos + rightValue); - } - - return yScale.getPixelForValue(value); - }, - - updateBezierControlPoints: function() { - var me = this; - var meta = me.getMeta(); - var area = me.chart.chartArea; - var points = (meta.data || []); - var i, ilen, point, model, controlPoints; - - // Only consider points that are drawn in case the spanGaps option is used - if (meta.dataset._model.spanGaps) { - points = points.filter(function(pt) { - return !pt._model.skip; - }); - } - - function capControlPoint(pt, min, max) { - return Math.max(Math.min(pt, max), min); - } - - if (meta.dataset._model.cubicInterpolationMode === 'monotone') { - helpers.splineCurveMonotone(points); - } else { - for (i = 0, ilen = points.length; i < ilen; ++i) { - point = points[i]; - model = point._model; - controlPoints = helpers.splineCurve( - helpers.previousItem(points, i)._model, - model, - helpers.nextItem(points, i)._model, - meta.dataset._model.tension - ); - model.controlPointPreviousX = controlPoints.previous.x; - model.controlPointPreviousY = controlPoints.previous.y; - model.controlPointNextX = controlPoints.next.x; - model.controlPointNextY = controlPoints.next.y; - } - } - - if (me.chart.options.elements.line.capBezierPoints) { - for (i = 0, ilen = points.length; i < ilen; ++i) { - model = points[i]._model; - model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right); - model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom); - model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right); - model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom); - } - } - }, - - draw: function(ease) { - var me = this; - var meta = me.getMeta(); - var points = meta.data || []; - var easingDecimal = ease || 1; - var i, ilen; - - // Transition Point Locations - for (i=0, ilen=points.length; i<ilen; ++i) { - points[i].transition(easingDecimal); - } - - Chart.canvasHelpers.clipArea(me.chart.chart.ctx, me.chart.chartArea); - // Transition and Draw the line - if (lineEnabled(me.getDataset(), me.chart.options)) { - meta.dataset.transition(easingDecimal).draw(); - } - Chart.canvasHelpers.unclipArea(me.chart.chart.ctx); - - // Draw the points - for (i=0, ilen=points.length; i<ilen; ++i) { - points[i].draw(me.chart.chartArea); - } - }, - - setHoverStyle: function(point) { - // Point - var dataset = this.chart.data.datasets[point._datasetIndex]; - var index = point._index; - var custom = point.custom || {}; - var model = point._model; - - model.radius = custom.hoverRadius || helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius); - model.backgroundColor = custom.hoverBackgroundColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor)); - model.borderColor = custom.hoverBorderColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor)); - model.borderWidth = custom.hoverBorderWidth || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth); - }, - - removeHoverStyle: function(point) { - var me = this; - var dataset = me.chart.data.datasets[point._datasetIndex]; - var index = point._index; - var custom = point.custom || {}; - var model = point._model; - - // Compatibility: If the properties are defined with only the old name, use those values - if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) { - dataset.pointRadius = dataset.radius; - } - - model.radius = custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, me.chart.options.elements.point.radius); - model.backgroundColor = me.getPointBackgroundColor(point, index); - model.borderColor = me.getPointBorderColor(point, index); - model.borderWidth = me.getPointBorderWidth(point, index); - } - }); - }; - -},{}],19:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.polarArea = { - - scale: { - type: 'radialLinear', - lineArc: true, // so that lines are circular - ticks: { - beginAtZero: true - } - }, - - // Boolean - Whether to animate the rotation of the chart - animation: { - animateRotate: true, - animateScale: true - }, - - startAngle: -0.5 * Math.PI, - aspectRatio: 1, - legendCallback: function(chart) { - var text = []; - text.push('<ul class="' + chart.id + '-legend">'); - - var data = chart.data; - var datasets = data.datasets; - var labels = data.labels; - - if (datasets.length) { - for (var i = 0; i < datasets[0].data.length; ++i) { - text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>'); - if (labels[i]) { - text.push(labels[i]); - } - text.push('</li>'); - } - } - - text.push('</ul>'); - return text.join(''); - }, - legend: { - labels: { - generateLabels: function(chart) { - var data = chart.data; - if (data.labels.length && data.datasets.length) { - return data.labels.map(function(label, i) { - var meta = chart.getDatasetMeta(0); - var ds = data.datasets[0]; - var arc = meta.data[i]; - var custom = arc.custom || {}; - var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault; - var arcOpts = chart.options.elements.arc; - var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor); - var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor); - var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth); - - return { - text: label, - fillStyle: fill, - strokeStyle: stroke, - lineWidth: bw, - hidden: isNaN(ds.data[i]) || meta.data[i].hidden, - - // Extra data used for toggling the correct item - index: i - }; - }); - } - return []; - } - }, - - onClick: function(e, legendItem) { - var index = legendItem.index; - var chart = this.chart; - var i, ilen, meta; - - for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { - meta = chart.getDatasetMeta(i); - meta.data[index].hidden = !meta.data[index].hidden; - } - - chart.update(); - } - }, - - // Need to override these to give a nice default - tooltips: { - callbacks: { - title: function() { - return ''; - }, - label: function(tooltipItem, data) { - return data.labels[tooltipItem.index] + ': ' + tooltipItem.yLabel; - } - } - } - }; - - Chart.controllers.polarArea = Chart.DatasetController.extend({ - - dataElementType: Chart.elements.Arc, - - linkScales: helpers.noop, - - update: function(reset) { - var me = this; - var chart = me.chart; - var chartArea = chart.chartArea; - var meta = me.getMeta(); - var opts = chart.options; - var arcOpts = opts.elements.arc; - var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top); - chart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0); - chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0); - chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount(); - - me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index); - me.innerRadius = me.outerRadius - chart.radiusLength; - - meta.count = me.countVisibleElements(); - - helpers.each(meta.data, function(arc, index) { - me.updateElement(arc, index, reset); - }); - }, - - updateElement: function(arc, index, reset) { - var me = this; - var chart = me.chart; - var dataset = me.getDataset(); - var opts = chart.options; - var animationOpts = opts.animation; - var scale = chart.scale; - var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault; - var labels = chart.data.labels; - - var circumference = me.calculateCircumference(dataset.data[index]); - var centerX = scale.xCenter; - var centerY = scale.yCenter; - - // If there is NaN data before us, we need to calculate the starting angle correctly. - // We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data - var visibleCount = 0; - var meta = me.getMeta(); - for (var i = 0; i < index; ++i) { - if (!isNaN(dataset.data[i]) && !meta.data[i].hidden) { - ++visibleCount; - } - } - - // var negHalfPI = -0.5 * Math.PI; - var datasetStartAngle = opts.startAngle; - var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); - var startAngle = datasetStartAngle + (circumference * visibleCount); - var endAngle = startAngle + (arc.hidden ? 0 : circumference); - - var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); - - helpers.extend(arc, { - // Utility - _datasetIndex: me.index, - _index: index, - _scale: scale, - - // Desired view properties - _model: { - x: centerX, - y: centerY, - innerRadius: 0, - outerRadius: reset ? resetRadius : distance, - startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle, - endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle, - label: getValueAtIndexOrDefault(labels, index, labels[index]) - } - }); - - // Apply border and fill style - me.removeHoverStyle(arc); - - arc.pivot(); - }, - - removeHoverStyle: function(arc) { - Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc); - }, - - countVisibleElements: function() { - var dataset = this.getDataset(); - var meta = this.getMeta(); - var count = 0; - - helpers.each(meta.data, function(element, index) { - if (!isNaN(dataset.data[index]) && !element.hidden) { - count++; - } - }); - - return count; - }, - - calculateCircumference: function(value) { - var count = this.getMeta().count; - if (count > 0 && !isNaN(value)) { - return (2 * Math.PI) / count; - } - return 0; - } - }); - }; - -},{}],20:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.radar = { - aspectRatio: 1, - scale: { - type: 'radialLinear' - }, - elements: { - line: { - tension: 0 // no bezier in radar - } - } - }; - - Chart.controllers.radar = Chart.DatasetController.extend({ - - datasetElementType: Chart.elements.Line, - - dataElementType: Chart.elements.Point, - - linkScales: helpers.noop, - - update: function(reset) { - var me = this; - var meta = me.getMeta(); - var line = meta.dataset; - var points = meta.data; - var custom = line.custom || {}; - var dataset = me.getDataset(); - var lineElementOptions = me.chart.options.elements.line; - var scale = me.chart.scale; - - // Compatibility: If the properties are defined with only the old name, use those values - if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) { - dataset.lineTension = dataset.tension; - } - - helpers.extend(meta.dataset, { - // Utility - _datasetIndex: me.index, - // Data - _children: points, - _loop: true, - // Model - _model: { - // Appearance - tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension), - backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor), - borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth), - borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor), - fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill), - borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle), - borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash), - borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset), - borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle), - - // Scale - scaleTop: scale.top, - scaleBottom: scale.bottom, - scaleZero: scale.getBasePosition() - } - }); - - meta.dataset.pivot(); - - // Update Points - helpers.each(points, function(point, index) { - me.updateElement(point, index, reset); - }, me); - - // Update bezier control points - me.updateBezierControlPoints(); - }, - updateElement: function(point, index, reset) { - var me = this; - var custom = point.custom || {}; - var dataset = me.getDataset(); - var scale = me.chart.scale; - var pointElementOptions = me.chart.options.elements.point; - var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]); - - helpers.extend(point, { - // Utility - _datasetIndex: me.index, - _index: index, - _scale: scale, - - // Desired view properties - _model: { - x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales - y: reset ? scale.yCenter : pointPosition.y, - - // Appearance - tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, me.chart.options.elements.line.tension), - radius: custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius), - backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor), - borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor), - borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth), - pointStyle: custom.pointStyle ? custom.pointStyle : helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointElementOptions.pointStyle), - - // Tooltip - hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius) - } - }); - - point._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y)); - }, - updateBezierControlPoints: function() { - var chartArea = this.chart.chartArea; - var meta = this.getMeta(); - - helpers.each(meta.data, function(point, index) { - var model = point._model; - var controlPoints = helpers.splineCurve( - helpers.previousItem(meta.data, index, true)._model, - model, - helpers.nextItem(meta.data, index, true)._model, - model.tension - ); - - // Prevent the bezier going outside of the bounds of the graph - model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left); - model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top); - - model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left); - model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top); - - // Now pivot the point for animation - point.pivot(); - }); - }, - - draw: function(ease) { - var meta = this.getMeta(); - var easingDecimal = ease || 1; - - // Transition Point Locations - helpers.each(meta.data, function(point) { - point.transition(easingDecimal); - }); - - // Transition and Draw the line - meta.dataset.transition(easingDecimal).draw(); - - // Draw the points - helpers.each(meta.data, function(point) { - point.draw(); - }); - }, - - setHoverStyle: function(point) { - // Point - var dataset = this.chart.data.datasets[point._datasetIndex]; - var custom = point.custom || {}; - var index = point._index; - var model = point._model; - - model.radius = custom.hoverRadius ? custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius); - model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor)); - model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor)); - model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth); - }, - - removeHoverStyle: function(point) { - var dataset = this.chart.data.datasets[point._datasetIndex]; - var custom = point.custom || {}; - var index = point._index; - var model = point._model; - var pointElementOptions = this.chart.options.elements.point; - - model.radius = custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.radius, index, pointElementOptions.radius); - model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor); - model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor); - model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth); - } - }); - }; - -},{}],21:[function(require,module,exports){ - /* global window: false */ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.global.animation = { - duration: 1000, - easing: 'easeOutQuart', - onProgress: helpers.noop, - onComplete: helpers.noop - }; - - Chart.Animation = Chart.Element.extend({ - currentStep: null, // the current animation step - numSteps: 60, // default number of steps - easing: '', // the easing to use for this animation - render: null, // render function used by the animation service - - onAnimationProgress: null, // user specified callback to fire on each step of the animation - onAnimationComplete: null // user specified callback to fire when the animation finishes - }); - - Chart.animationService = { - frameDuration: 17, - animations: [], - dropFrames: 0, - request: null, - - /** - * @function Chart.animationService.addAnimation - * @param chartInstance {ChartController} the chart to animate - * @param animationObject {IAnimation} the animation that we will animate - * @param duration {Number} length of animation in ms - * @param lazy {Boolean} if true, the chart is not marked as animating to enable more responsive interactions - */ - addAnimation: function(chartInstance, animationObject, duration, lazy) { - var me = this; - - if (!lazy) { - chartInstance.animating = true; - } - - for (var index = 0; index < me.animations.length; ++index) { - if (me.animations[index].chartInstance === chartInstance) { - // replacing an in progress animation - me.animations[index].animationObject = animationObject; - return; - } - } - - me.animations.push({ - chartInstance: chartInstance, - animationObject: animationObject - }); - - // If there are no animations queued, manually kickstart a digest, for lack of a better word - if (me.animations.length === 1) { - me.requestAnimationFrame(); - } - }, - // Cancel the animation for a given chart instance - cancelAnimation: function(chartInstance) { - var index = helpers.findIndex(this.animations, function(animationWrapper) { - return animationWrapper.chartInstance === chartInstance; - }); - - if (index !== -1) { - this.animations.splice(index, 1); - chartInstance.animating = false; - } - }, - requestAnimationFrame: function() { - var me = this; - if (me.request === null) { - // Skip animation frame requests until the active one is executed. - // This can happen when processing mouse events, e.g. 'mousemove' - // and 'mouseout' events will trigger multiple renders. - me.request = helpers.requestAnimFrame.call(window, function() { - me.request = null; - me.startDigest(); - }); - } - }, - startDigest: function() { - var me = this; - - var startTime = Date.now(); - var framesToDrop = 0; - - if (me.dropFrames > 1) { - framesToDrop = Math.floor(me.dropFrames); - me.dropFrames = me.dropFrames % 1; - } - - var i = 0; - while (i < me.animations.length) { - if (me.animations[i].animationObject.currentStep === null) { - me.animations[i].animationObject.currentStep = 0; - } - - me.animations[i].animationObject.currentStep += 1 + framesToDrop; - - if (me.animations[i].animationObject.currentStep > me.animations[i].animationObject.numSteps) { - me.animations[i].animationObject.currentStep = me.animations[i].animationObject.numSteps; - } - - me.animations[i].animationObject.render(me.animations[i].chartInstance, me.animations[i].animationObject); - if (me.animations[i].animationObject.onAnimationProgress && me.animations[i].animationObject.onAnimationProgress.call) { - me.animations[i].animationObject.onAnimationProgress.call(me.animations[i].chartInstance, me.animations[i]); - } - - if (me.animations[i].animationObject.currentStep === me.animations[i].animationObject.numSteps) { - if (me.animations[i].animationObject.onAnimationComplete && me.animations[i].animationObject.onAnimationComplete.call) { - me.animations[i].animationObject.onAnimationComplete.call(me.animations[i].chartInstance, me.animations[i]); - } - - // executed the last frame. Remove the animation. - me.animations[i].chartInstance.animating = false; - - me.animations.splice(i, 1); - } else { - ++i; - } - } - - var endTime = Date.now(); - var dropFrames = (endTime - startTime) / me.frameDuration; - - me.dropFrames += dropFrames; - - // Do we have more stuff to animate? - if (me.animations.length > 0) { - me.requestAnimationFrame(); - } - } - }; - }; - -},{}],22:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - // Global Chart canvas helpers object for drawing items to canvas - var helpers = Chart.canvasHelpers = {}; - - helpers.drawPoint = function(ctx, pointStyle, radius, x, y) { - var type, edgeLength, xOffset, yOffset, height, size; - - if (typeof pointStyle === 'object') { - type = pointStyle.toString(); - if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') { - ctx.drawImage(pointStyle, x - pointStyle.width / 2, y - pointStyle.height / 2); - return; - } - } - - if (isNaN(radius) || radius <= 0) { - return; - } - - switch (pointStyle) { - // Default includes circle - default: - ctx.beginPath(); - ctx.arc(x, y, radius, 0, Math.PI * 2); - ctx.closePath(); - ctx.fill(); - break; - case 'triangle': - ctx.beginPath(); - edgeLength = 3 * radius / Math.sqrt(3); - height = edgeLength * Math.sqrt(3) / 2; - ctx.moveTo(x - edgeLength / 2, y + height / 3); - ctx.lineTo(x + edgeLength / 2, y + height / 3); - ctx.lineTo(x, y - 2 * height / 3); - ctx.closePath(); - ctx.fill(); - break; - case 'rect': - size = 1 / Math.SQRT2 * radius; - ctx.beginPath(); - ctx.fillRect(x - size, y - size, 2 * size, 2 * size); - ctx.strokeRect(x - size, y - size, 2 * size, 2 * size); - break; - case 'rectRounded': - var offset = radius / Math.SQRT2; - var leftX = x - offset; - var topY = y - offset; - var sideSize = Math.SQRT2 * radius; - Chart.helpers.drawRoundedRectangle(ctx, leftX, topY, sideSize, sideSize, radius / 2); - ctx.fill(); - break; - case 'rectRot': - size = 1 / Math.SQRT2 * radius; - ctx.beginPath(); - ctx.moveTo(x - size, y); - ctx.lineTo(x, y + size); - ctx.lineTo(x + size, y); - ctx.lineTo(x, y - size); - ctx.closePath(); - ctx.fill(); - break; - case 'cross': - ctx.beginPath(); - ctx.moveTo(x, y + radius); - ctx.lineTo(x, y - radius); - ctx.moveTo(x - radius, y); - ctx.lineTo(x + radius, y); - ctx.closePath(); - break; - case 'crossRot': - ctx.beginPath(); - xOffset = Math.cos(Math.PI / 4) * radius; - yOffset = Math.sin(Math.PI / 4) * radius; - ctx.moveTo(x - xOffset, y - yOffset); - ctx.lineTo(x + xOffset, y + yOffset); - ctx.moveTo(x - xOffset, y + yOffset); - ctx.lineTo(x + xOffset, y - yOffset); - ctx.closePath(); - break; - case 'star': - ctx.beginPath(); - ctx.moveTo(x, y + radius); - ctx.lineTo(x, y - radius); - ctx.moveTo(x - radius, y); - ctx.lineTo(x + radius, y); - xOffset = Math.cos(Math.PI / 4) * radius; - yOffset = Math.sin(Math.PI / 4) * radius; - ctx.moveTo(x - xOffset, y - yOffset); - ctx.lineTo(x + xOffset, y + yOffset); - ctx.moveTo(x - xOffset, y + yOffset); - ctx.lineTo(x + xOffset, y - yOffset); - ctx.closePath(); - break; - case 'line': - ctx.beginPath(); - ctx.moveTo(x - radius, y); - ctx.lineTo(x + radius, y); - ctx.closePath(); - break; - case 'dash': - ctx.beginPath(); - ctx.moveTo(x, y); - ctx.lineTo(x + radius, y); - ctx.closePath(); - break; - } - - ctx.stroke(); - }; - - helpers.clipArea = function(ctx, clipArea) { - ctx.save(); - ctx.beginPath(); - ctx.rect(clipArea.left, clipArea.top, clipArea.right - clipArea.left, clipArea.bottom - clipArea.top); - ctx.clip(); - }; - - helpers.unclipArea = function(ctx) { - ctx.restore(); - }; - - }; - -},{}],23:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - var plugins = Chart.plugins; - var platform = Chart.platform; - - // Create a dictionary of chart types, to allow for extension of existing types - Chart.types = {}; - - // Store a reference to each instance - allowing us to globally resize chart instances on window resize. - // Destroy method on the chart will remove the instance of the chart from this reference. - Chart.instances = {}; - - // Controllers available for dataset visualization eg. bar, line, slice, etc. - Chart.controllers = {}; - - /** - * Initializes the given config with global and chart default values. - */ - function initConfig(config) { - config = config || {}; - - // Do NOT use configMerge() for the data object because this method merges arrays - // and so would change references to labels and datasets, preventing data updates. - var data = config.data = config.data || {}; - data.datasets = data.datasets || []; - data.labels = data.labels || []; - - config.options = helpers.configMerge( - Chart.defaults.global, - Chart.defaults[config.type], - config.options || {}); - - return config; - } - - /** - * Updates the config of the chart - * @param chart {Chart.Controller} chart to update the options for - */ - function updateConfig(chart) { - var newOptions = chart.options; - - // Update Scale(s) with options - if (newOptions.scale) { - chart.scale.options = newOptions.scale; - } else if (newOptions.scales) { - newOptions.scales.xAxes.concat(newOptions.scales.yAxes).forEach(function(scaleOptions) { - chart.scales[scaleOptions.id].options = scaleOptions; - }); - } - - // Tooltip - chart.tooltip._options = newOptions.tooltips; - } - - /** - * @class Chart.Controller - * The main controller of a chart. - */ - Chart.Controller = function(item, config, instance) { - var me = this; - - config = initConfig(config); - - var context = platform.acquireContext(item, config); - var canvas = context && context.canvas; - var height = canvas && canvas.height; - var width = canvas && canvas.width; - - instance.ctx = context; - instance.canvas = canvas; - instance.config = config; - instance.width = width; - instance.height = height; - instance.aspectRatio = height? width / height : null; - - me.id = helpers.uid(); - me.chart = instance; - me.config = config; - me.options = config.options; - me._bufferedRender = false; - - // Add the chart instance to the global namespace - Chart.instances[me.id] = me; - - Object.defineProperty(me, 'data', { - get: function() { - return me.config.data; - } - }); - - if (!context || !canvas) { - // The given item is not a compatible context2d element, let's return before finalizing - // the chart initialization but after setting basic chart / controller properties that - // can help to figure out that the chart is not valid (e.g chart.canvas !== null); - // https://github.com/chartjs/Chart.js/issues/2807 - console.error("Failed to create chart: can't acquire context from the given item"); - return me; - } - - me.initialize(); - me.update(); - - return me; - }; - - helpers.extend(Chart.Controller.prototype, /** @lends Chart.Controller.prototype */ { - initialize: function() { - var me = this; - - // Before init plugin notification - plugins.notify(me, 'beforeInit'); - - helpers.retinaScale(me.chart); - - me.bindEvents(); - - if (me.options.responsive) { - // Initial resize before chart draws (must be silent to preserve initial animations). - me.resize(true); - } - - // Make sure scales have IDs and are built before we build any controllers. - me.ensureScalesHaveIDs(); - me.buildScales(); - me.initToolTip(); - - // After init plugin notification - plugins.notify(me, 'afterInit'); - - return me; - }, - - clear: function() { - helpers.clear(this.chart); - return this; - }, - - stop: function() { - // Stops any current animation loop occurring - Chart.animationService.cancelAnimation(this); - return this; - }, - - resize: function(silent) { - var me = this; - var chart = me.chart; - var options = me.options; - var canvas = chart.canvas; - var aspectRatio = (options.maintainAspectRatio && chart.aspectRatio) || null; - - // the canvas render width and height will be casted to integers so make sure that - // the canvas display style uses the same integer values to avoid blurring effect. - var newWidth = Math.floor(helpers.getMaximumWidth(canvas)); - var newHeight = Math.floor(aspectRatio? newWidth / aspectRatio : helpers.getMaximumHeight(canvas)); - - if (chart.width === newWidth && chart.height === newHeight) { - return; - } - - canvas.width = chart.width = newWidth; - canvas.height = chart.height = newHeight; - canvas.style.width = newWidth + 'px'; - canvas.style.height = newHeight + 'px'; - - helpers.retinaScale(chart); - - if (!silent) { - // Notify any plugins about the resize - var newSize = {width: newWidth, height: newHeight}; - plugins.notify(me, 'resize', [newSize]); - - // Notify of resize - if (me.options.onResize) { - me.options.onResize(me, newSize); - } - - me.stop(); - me.update(me.options.responsiveAnimationDuration); - } - }, - - ensureScalesHaveIDs: function() { - var options = this.options; - var scalesOptions = options.scales || {}; - var scaleOptions = options.scale; - - helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) { - xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index); - }); - - helpers.each(scalesOptions.yAxes, function(yAxisOptions, index) { - yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index); - }); - - if (scaleOptions) { - scaleOptions.id = scaleOptions.id || 'scale'; - } - }, - - /** - * Builds a map of scale ID to scale object for future lookup. - */ - buildScales: function() { - var me = this; - var options = me.options; - var scales = me.scales = {}; - var items = []; - - if (options.scales) { - items = items.concat( - (options.scales.xAxes || []).map(function(xAxisOptions) { - return {options: xAxisOptions, dtype: 'category'}; - }), - (options.scales.yAxes || []).map(function(yAxisOptions) { - return {options: yAxisOptions, dtype: 'linear'}; - }) - ); - } - - if (options.scale) { - items.push({options: options.scale, dtype: 'radialLinear', isDefault: true}); - } - - helpers.each(items, function(item) { - var scaleOptions = item.options; - var scaleType = helpers.getValueOrDefault(scaleOptions.type, item.dtype); - var scaleClass = Chart.scaleService.getScaleConstructor(scaleType); - if (!scaleClass) { - return; - } - - var scale = new scaleClass({ - id: scaleOptions.id, - options: scaleOptions, - ctx: me.chart.ctx, - chart: me - }); - - scales[scale.id] = scale; - - // TODO(SB): I think we should be able to remove this custom case (options.scale) - // and consider it as a regular scale part of the "scales"" map only! This would - // make the logic easier and remove some useless? custom code. - if (item.isDefault) { - me.scale = scale; - } - }); - - Chart.scaleService.addScalesToLayout(this); - }, - - buildOrUpdateControllers: function() { - var me = this; - var types = []; - var newControllers = []; - - helpers.each(me.data.datasets, function(dataset, datasetIndex) { - var meta = me.getDatasetMeta(datasetIndex); - if (!meta.type) { - meta.type = dataset.type || me.config.type; - } - - types.push(meta.type); - - if (meta.controller) { - meta.controller.updateIndex(datasetIndex); - } else { - meta.controller = new Chart.controllers[meta.type](me, datasetIndex); - newControllers.push(meta.controller); - } - }, me); - - if (types.length > 1) { - for (var i = 1; i < types.length; i++) { - if (types[i] !== types[i - 1]) { - me.isCombo = true; - break; - } - } - } - - return newControllers; - }, - - /** - * Reset the elements of all datasets - * @private - */ - resetElements: function() { - var me = this; - helpers.each(me.data.datasets, function(dataset, datasetIndex) { - me.getDatasetMeta(datasetIndex).controller.reset(); - }, me); - }, - - /** - * Resets the chart back to it's state before the initial animation - */ - reset: function() { - this.resetElements(); - this.tooltip.initialize(); - }, - - update: function(animationDuration, lazy) { - var me = this; - - updateConfig(me); - - if (plugins.notify(me, 'beforeUpdate') === false) { - return; - } - - // In case the entire data object changed - me.tooltip._data = me.data; - - // Make sure dataset controllers are updated and new controllers are reset - var newControllers = me.buildOrUpdateControllers(); - - // Make sure all dataset controllers have correct meta data counts - helpers.each(me.data.datasets, function(dataset, datasetIndex) { - me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements(); - }, me); - - me.updateLayout(); - - // Can only reset the new controllers after the scales have been updated - helpers.each(newControllers, function(controller) { - controller.reset(); - }); - - me.updateDatasets(); - - // Do this before render so that any plugins that need final scale updates can use it - plugins.notify(me, 'afterUpdate'); - - if (me._bufferedRender) { - me._bufferedRequest = { - lazy: lazy, - duration: animationDuration - }; - } else { - me.render(animationDuration, lazy); - } - }, - - /** - * Updates the chart layout unless a plugin returns `false` to the `beforeLayout` - * hook, in which case, plugins will not be called on `afterLayout`. - * @private - */ - updateLayout: function() { - var me = this; - - if (plugins.notify(me, 'beforeLayout') === false) { - return; - } - - Chart.layoutService.update(this, this.chart.width, this.chart.height); - - /** - * Provided for backward compatibility, use `afterLayout` instead. - * @method IPlugin#afterScaleUpdate - * @deprecated since version 2.5.0 - * @todo remove at version 3 - */ - plugins.notify(me, 'afterScaleUpdate'); - plugins.notify(me, 'afterLayout'); - }, - - /** - * Updates all datasets unless a plugin returns `false` to the `beforeDatasetsUpdate` - * hook, in which case, plugins will not be called on `afterDatasetsUpdate`. - * @private - */ - updateDatasets: function() { - var me = this; - - if (plugins.notify(me, 'beforeDatasetsUpdate') === false) { - return; - } - - for (var i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { - me.getDatasetMeta(i).controller.update(); - } - - plugins.notify(me, 'afterDatasetsUpdate'); - }, - - render: function(duration, lazy) { - var me = this; - - if (plugins.notify(me, 'beforeRender') === false) { - return; - } - - var animationOptions = me.options.animation; - var onComplete = function() { - plugins.notify(me, 'afterRender'); - var callback = animationOptions && animationOptions.onComplete; - if (callback && callback.call) { - callback.call(me); - } - }; - - if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) { - var animation = new Chart.Animation(); - animation.numSteps = (duration || animationOptions.duration) / 16.66; // 60 fps - animation.easing = animationOptions.easing; - - // render function - animation.render = function(chartInstance, animationObject) { - var easingFunction = helpers.easingEffects[animationObject.easing]; - var stepDecimal = animationObject.currentStep / animationObject.numSteps; - var easeDecimal = easingFunction(stepDecimal); - - chartInstance.draw(easeDecimal, stepDecimal, animationObject.currentStep); - }; - - // user events - animation.onAnimationProgress = animationOptions.onProgress; - animation.onAnimationComplete = onComplete; - - Chart.animationService.addAnimation(me, animation, duration, lazy); - } else { - me.draw(); - onComplete(); - } - - return me; - }, - - draw: function(easingValue) { - var me = this; - - me.clear(); - - if (easingValue === undefined || easingValue === null) { - easingValue = 1; - } - - if (plugins.notify(me, 'beforeDraw', [easingValue]) === false) { - return; - } - - // Draw all the scales - helpers.each(me.boxes, function(box) { - box.draw(me.chartArea); - }, me); - - if (me.scale) { - me.scale.draw(); - } - - me.drawDatasets(easingValue); - - // Finally draw the tooltip - me.tooltip.transition(easingValue).draw(); - - plugins.notify(me, 'afterDraw', [easingValue]); - }, - - /** - * Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw` - * hook, in which case, plugins will not be called on `afterDatasetsDraw`. - * @private - */ - drawDatasets: function(easingValue) { - var me = this; - - if (plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) { - return; - } - - // Draw each dataset via its respective controller (reversed to support proper line stacking) - helpers.each(me.data.datasets, function(dataset, datasetIndex) { - if (me.isDatasetVisible(datasetIndex)) { - me.getDatasetMeta(datasetIndex).controller.draw(easingValue); - } - }, me, true); - - plugins.notify(me, 'afterDatasetsDraw', [easingValue]); - }, - - // Get the single element that was clicked on - // @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw - getElementAtEvent: function(e) { - return Chart.Interaction.modes.single(this, e); - }, - - getElementsAtEvent: function(e) { - return Chart.Interaction.modes.label(this, e, {intersect: true}); - }, - - getElementsAtXAxis: function(e) { - return Chart.Interaction.modes['x-axis'](this, e, {intersect: true}); - }, - - getElementsAtEventForMode: function(e, mode, options) { - var method = Chart.Interaction.modes[mode]; - if (typeof method === 'function') { - return method(this, e, options); - } - - return []; - }, - - getDatasetAtEvent: function(e) { - return Chart.Interaction.modes.dataset(this, e, {intersect: true}); - }, - - getDatasetMeta: function(datasetIndex) { - var me = this; - var dataset = me.data.datasets[datasetIndex]; - if (!dataset._meta) { - dataset._meta = {}; - } - - var meta = dataset._meta[me.id]; - if (!meta) { - meta = dataset._meta[me.id] = { - type: null, - data: [], - dataset: null, - controller: null, - hidden: null, // See isDatasetVisible() comment - xAxisID: null, - yAxisID: null - }; - } - - return meta; - }, - - getVisibleDatasetCount: function() { - var count = 0; - for (var i = 0, ilen = this.data.datasets.length; i<ilen; ++i) { - if (this.isDatasetVisible(i)) { - count++; - } - } - return count; - }, - - isDatasetVisible: function(datasetIndex) { - var meta = this.getDatasetMeta(datasetIndex); - - // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false, - // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned. - return typeof meta.hidden === 'boolean'? !meta.hidden : !this.data.datasets[datasetIndex].hidden; - }, - - generateLegend: function() { - return this.options.legendCallback(this); - }, - - destroy: function() { - var me = this; - var canvas = me.chart.canvas; - var meta, i, ilen; - - me.stop(); - - // dataset controllers need to cleanup associated data - for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { - meta = me.getDatasetMeta(i); - if (meta.controller) { - meta.controller.destroy(); - meta.controller = null; - } - } - - if (canvas) { - me.unbindEvents(); - helpers.clear(me.chart); - platform.releaseContext(me.chart.ctx); - me.chart.canvas = null; - me.chart.ctx = null; - } - - plugins.notify(me, 'destroy'); - - delete Chart.instances[me.id]; - }, - - toBase64Image: function() { - return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments); - }, - - initToolTip: function() { - var me = this; - me.tooltip = new Chart.Tooltip({ - _chart: me.chart, - _chartInstance: me, - _data: me.data, - _options: me.options.tooltips - }, me); - me.tooltip.initialize(); - }, - - /** - * @private - */ - bindEvents: function() { - var me = this; - var listeners = me._listeners = {}; - var listener = function() { - me.eventHandler.apply(me, arguments); - }; - - helpers.each(me.options.events, function(type) { - platform.addEventListener(me, type, listener); - listeners[type] = listener; - }); - - // Responsiveness is currently based on the use of an iframe, however this method causes - // performance issues and could be troublesome when used with ad blockers. So make sure - // that the user is still able to create a chart without iframe when responsive is false. - // See https://github.com/chartjs/Chart.js/issues/2210 - if (me.options.responsive) { - listener = function() { - me.resize(); - }; - - platform.addEventListener(me, 'resize', listener); - listeners.resize = listener; - } - }, - - /** - * @private - */ - unbindEvents: function() { - var me = this; - var listeners = me._listeners; - if (!listeners) { - return; - } - - delete me._listeners; - helpers.each(listeners, function(listener, type) { - platform.removeEventListener(me, type, listener); - }); - }, - - updateHoverStyle: function(elements, mode, enabled) { - var method = enabled? 'setHoverStyle' : 'removeHoverStyle'; - var element, i, ilen; - - for (i=0, ilen=elements.length; i<ilen; ++i) { - element = elements[i]; - if (element) { - this.getDatasetMeta(element._datasetIndex).controller[method](element); - } - } - }, - - /** - * @private - */ - eventHandler: function(e) { - var me = this; - var tooltip = me.tooltip; - - if (plugins.notify(me, 'beforeEvent', [e]) === false) { - return; - } - - // Buffer any update calls so that renders do not occur - me._bufferedRender = true; - me._bufferedRequest = null; - - var changed = me.handleEvent(e); - changed |= tooltip && tooltip.handleEvent(e); - - plugins.notify(me, 'afterEvent', [e]); - - var bufferedRequest = me._bufferedRequest; - if (bufferedRequest) { - // If we have an update that was triggered, we need to do a normal render - me.render(bufferedRequest.duration, bufferedRequest.lazy); - } else if (changed && !me.animating) { - // If entering, leaving, or changing elements, animate the change via pivot - me.stop(); - - // We only need to render at this point. Updating will cause scales to be - // recomputed generating flicker & using more memory than necessary. - me.render(me.options.hover.animationDuration, true); - } - - me._bufferedRender = false; - me._bufferedRequest = null; - - return me; - }, - - /** - * Handle an event - * @private - * @param {IEvent} event the event to handle - * @return {Boolean} true if the chart needs to re-render - */ - handleEvent: function(e) { - var me = this; - var options = me.options || {}; - var hoverOptions = options.hover; - var changed = false; - - me.lastActive = me.lastActive || []; - - // Find Active Elements for hover and tooltips - if (e.type === 'mouseout') { - me.active = []; - } else { - me.active = me.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions); - } - - // On Hover hook - if (hoverOptions.onHover) { - // Need to call with native event here to not break backwards compatibility - hoverOptions.onHover.call(me, e.native, me.active); - } - - if (e.type === 'mouseup' || e.type === 'click') { - if (options.onClick) { - // Use e.native here for backwards compatibility - options.onClick.call(me, e.native, me.active); - } - } - - // Remove styling for last active (even if it may still be active) - if (me.lastActive.length) { - me.updateHoverStyle(me.lastActive, hoverOptions.mode, false); - } - - // Built in hover styling - if (me.active.length && hoverOptions.mode) { - me.updateHoverStyle(me.active, hoverOptions.mode, true); - } - - changed = !helpers.arrayEquals(me.active, me.lastActive); - - // Remember Last Actives - me.lastActive = me.active; - - return changed; - } - }); - }; - -},{}],24:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift']; - - /** - * Hooks the array methods that add or remove values ('push', pop', 'shift', 'splice', - * 'unshift') and notify the listener AFTER the array has been altered. Listeners are - * called on the 'onData*' callbacks (e.g. onDataPush, etc.) with same arguments. - */ - function listenArrayEvents(array, listener) { - if (array._chartjs) { - array._chartjs.listeners.push(listener); - return; - } - - Object.defineProperty(array, '_chartjs', { - configurable: true, - enumerable: false, - value: { - listeners: [listener] - } - }); - - arrayEvents.forEach(function(key) { - var method = 'onData' + key.charAt(0).toUpperCase() + key.slice(1); - var base = array[key]; - - Object.defineProperty(array, key, { - configurable: true, - enumerable: false, - value: function() { - var args = Array.prototype.slice.call(arguments); - var res = base.apply(this, args); - - helpers.each(array._chartjs.listeners, function(object) { - if (typeof object[method] === 'function') { - object[method].apply(object, args); - } - }); - - return res; - } - }); - }); - } - - /** - * Removes the given array event listener and cleanup extra attached properties (such as - * the _chartjs stub and overridden methods) if array doesn't have any more listeners. - */ - function unlistenArrayEvents(array, listener) { - var stub = array._chartjs; - if (!stub) { - return; - } - - var listeners = stub.listeners; - var index = listeners.indexOf(listener); - if (index !== -1) { - listeners.splice(index, 1); - } - - if (listeners.length > 0) { - return; - } - - arrayEvents.forEach(function(key) { - delete array[key]; - }); - - delete array._chartjs; - } - - // Base class for all dataset controllers (line, bar, etc) - Chart.DatasetController = function(chart, datasetIndex) { - this.initialize(chart, datasetIndex); - }; - - helpers.extend(Chart.DatasetController.prototype, { - - /** - * Element type used to generate a meta dataset (e.g. Chart.element.Line). - * @type {Chart.core.element} - */ - datasetElementType: null, - - /** - * Element type used to generate a meta data (e.g. Chart.element.Point). - * @type {Chart.core.element} - */ - dataElementType: null, - - initialize: function(chart, datasetIndex) { - var me = this; - me.chart = chart; - me.index = datasetIndex; - me.linkScales(); - me.addElements(); - }, - - updateIndex: function(datasetIndex) { - this.index = datasetIndex; - }, - - linkScales: function() { - var me = this; - var meta = me.getMeta(); - var dataset = me.getDataset(); - - if (meta.xAxisID === null) { - meta.xAxisID = dataset.xAxisID || me.chart.options.scales.xAxes[0].id; - } - if (meta.yAxisID === null) { - meta.yAxisID = dataset.yAxisID || me.chart.options.scales.yAxes[0].id; - } - }, - - getDataset: function() { - return this.chart.data.datasets[this.index]; - }, - - getMeta: function() { - return this.chart.getDatasetMeta(this.index); - }, - - getScaleForId: function(scaleID) { - return this.chart.scales[scaleID]; - }, - - reset: function() { - this.update(true); - }, - - /** - * @private - */ - destroy: function() { - if (this._data) { - unlistenArrayEvents(this._data, this); - } - }, - - createMetaDataset: function() { - var me = this; - var type = me.datasetElementType; - return type && new type({ - _chart: me.chart.chart, - _datasetIndex: me.index - }); - }, - - createMetaData: function(index) { - var me = this; - var type = me.dataElementType; - return type && new type({ - _chart: me.chart.chart, - _datasetIndex: me.index, - _index: index - }); - }, - - addElements: function() { - var me = this; - var meta = me.getMeta(); - var data = me.getDataset().data || []; - var metaData = meta.data; - var i, ilen; - - for (i=0, ilen=data.length; i<ilen; ++i) { - metaData[i] = metaData[i] || me.createMetaData(i); - } - - meta.dataset = meta.dataset || me.createMetaDataset(); - }, - - addElementAndReset: function(index) { - var element = this.createMetaData(index); - this.getMeta().data.splice(index, 0, element); - this.updateElement(element, index, true); - }, - - buildOrUpdateElements: function() { - var me = this; - var dataset = me.getDataset(); - var data = dataset.data || (dataset.data = []); - - // In order to correctly handle data addition/deletion animation (an thus simulate - // real-time charts), we need to monitor these data modifications and synchronize - // the internal meta data accordingly. - if (me._data !== data) { - if (me._data) { - // This case happens when the user replaced the data array instance. - unlistenArrayEvents(me._data, me); - } - - listenArrayEvents(data, me); - me._data = data; - } - - // Re-sync meta data in case the user replaced the data array or if we missed - // any updates and so make sure that we handle number of datapoints changing. - me.resyncElements(); - }, - - update: helpers.noop, - - draw: function(ease) { - var easingDecimal = ease || 1; - var i, len; - var metaData = this.getMeta().data; - for (i = 0, len = metaData.length; i < len; ++i) { - metaData[i].transition(easingDecimal).draw(); - } - }, - - removeHoverStyle: function(element, elementOpts) { - var dataset = this.chart.data.datasets[element._datasetIndex], - index = element._index, - custom = element.custom || {}, - valueOrDefault = helpers.getValueAtIndexOrDefault, - model = element._model; - - model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor); - model.borderColor = custom.borderColor ? custom.borderColor : valueOrDefault(dataset.borderColor, index, elementOpts.borderColor); - model.borderWidth = custom.borderWidth ? custom.borderWidth : valueOrDefault(dataset.borderWidth, index, elementOpts.borderWidth); - }, - - setHoverStyle: function(element) { - var dataset = this.chart.data.datasets[element._datasetIndex], - index = element._index, - custom = element.custom || {}, - valueOrDefault = helpers.getValueAtIndexOrDefault, - getHoverColor = helpers.getHoverColor, - model = element._model; - - model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueOrDefault(dataset.hoverBackgroundColor, index, getHoverColor(model.backgroundColor)); - model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, getHoverColor(model.borderColor)); - model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, model.borderWidth); - }, - - /** - * @private - */ - resyncElements: function() { - var me = this; - var meta = me.getMeta(); - var data = me.getDataset().data; - var numMeta = meta.data.length; - var numData = data.length; - - if (numData < numMeta) { - meta.data.splice(numData, numMeta - numData); - } else if (numData > numMeta) { - me.insertElements(numMeta, numData - numMeta); - } - }, - - /** - * @private - */ - insertElements: function(start, count) { - for (var i=0; i<count; ++i) { - this.addElementAndReset(start + i); - } - }, - - /** - * @private - */ - onDataPush: function() { - this.insertElements(this.getDataset().data.length-1, arguments.length); - }, - - /** - * @private - */ - onDataPop: function() { - this.getMeta().data.pop(); - }, - - /** - * @private - */ - onDataShift: function() { - this.getMeta().data.shift(); - }, - - /** - * @private - */ - onDataSplice: function(start, count) { - this.getMeta().data.splice(start, count); - this.insertElements(start, arguments.length - 2); - }, - - /** - * @private - */ - onDataUnshift: function() { - this.insertElements(0, arguments.length); - } - }); - - Chart.DatasetController.extend = helpers.inherits; - }; - -},{}],25:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.elements = {}; - - Chart.Element = function(configuration) { - helpers.extend(this, configuration); - this.initialize.apply(this, arguments); - }; - - helpers.extend(Chart.Element.prototype, { - - initialize: function() { - this.hidden = false; - }, - - pivot: function() { - var me = this; - if (!me._view) { - me._view = helpers.clone(me._model); - } - me._start = helpers.clone(me._view); - return me; - }, - - transition: function(ease) { - var me = this; - - if (!me._view) { - me._view = helpers.clone(me._model); - } - - // No animation -> No Transition - if (ease === 1) { - me._view = me._model; - me._start = null; - return me; - } - - if (!me._start) { - me.pivot(); - } - - helpers.each(me._model, function(value, key) { - - if (key[0] === '_') { - // Only non-underscored properties - // Init if doesn't exist - } else if (!me._view.hasOwnProperty(key)) { - if (typeof value === 'number' && !isNaN(me._view[key])) { - me._view[key] = value * ease; - } else { - me._view[key] = value; - } - // No unnecessary computations - } else if (value === me._view[key]) { - // It's the same! Woohoo! - // Color transitions if possible - } else if (typeof value === 'string') { - try { - var color = helpers.color(me._model[key]).mix(helpers.color(me._start[key]), ease); - me._view[key] = color.rgbString(); - } catch (err) { - me._view[key] = value; - } - // Number transitions - } else if (typeof value === 'number') { - var startVal = me._start[key] !== undefined && isNaN(me._start[key]) === false ? me._start[key] : 0; - me._view[key] = ((me._model[key] - startVal) * ease) + startVal; - // Everything else - } else { - me._view[key] = value; - } - }, me); - - return me; - }, - - tooltipPosition: function() { - return { - x: this._model.x, - y: this._model.y - }; - }, - - hasValue: function() { - return helpers.isNumber(this._model.x) && helpers.isNumber(this._model.y); - } - }); - - Chart.Element.extend = helpers.inherits; - - }; - -},{}],26:[function(require,module,exports){ - /* global window: false */ - /* global document: false */ - 'use strict'; - - var color = require(3); - - module.exports = function(Chart) { - // Global Chart helpers object for utility methods and classes - var helpers = Chart.helpers = {}; - - // -- Basic js utility methods - helpers.each = function(loopable, callback, self, reverse) { - // Check to see if null or undefined firstly. - var i, len; - if (helpers.isArray(loopable)) { - len = loopable.length; - if (reverse) { - for (i = len - 1; i >= 0; i--) { - callback.call(self, loopable[i], i); - } - } else { - for (i = 0; i < len; i++) { - callback.call(self, loopable[i], i); - } - } - } else if (typeof loopable === 'object') { - var keys = Object.keys(loopable); - len = keys.length; - for (i = 0; i < len; i++) { - callback.call(self, loopable[keys[i]], keys[i]); - } - } - }; - helpers.clone = function(obj) { - var objClone = {}; - helpers.each(obj, function(value, key) { - if (helpers.isArray(value)) { - objClone[key] = value.slice(0); - } else if (typeof value === 'object' && value !== null) { - objClone[key] = helpers.clone(value); - } else { - objClone[key] = value; - } - }); - return objClone; - }; - helpers.extend = function(base) { - var setFn = function(value, key) { - base[key] = value; - }; - for (var i = 1, ilen = arguments.length; i < ilen; i++) { - helpers.each(arguments[i], setFn); - } - return base; - }; - // Need a special merge function to chart configs since they are now grouped - helpers.configMerge = function(_base) { - var base = helpers.clone(_base); - helpers.each(Array.prototype.slice.call(arguments, 1), function(extension) { - helpers.each(extension, function(value, key) { - var baseHasProperty = base.hasOwnProperty(key); - var baseVal = baseHasProperty ? base[key] : {}; - - if (key === 'scales') { - // Scale config merging is complex. Add our own function here for that - base[key] = helpers.scaleMerge(baseVal, value); - } else if (key === 'scale') { - // Used in polar area & radar charts since there is only one scale - base[key] = helpers.configMerge(baseVal, Chart.scaleService.getScaleDefaults(value.type), value); - } else if (baseHasProperty - && typeof baseVal === 'object' - && !helpers.isArray(baseVal) - && baseVal !== null - && typeof value === 'object' - && !helpers.isArray(value)) { - // If we are overwriting an object with an object, do a merge of the properties. - base[key] = helpers.configMerge(baseVal, value); - } else { - // can just overwrite the value in this case - base[key] = value; - } - }); - }); - - return base; - }; - helpers.scaleMerge = function(_base, extension) { - var base = helpers.clone(_base); - - helpers.each(extension, function(value, key) { - if (key === 'xAxes' || key === 'yAxes') { - // These properties are arrays of items - if (base.hasOwnProperty(key)) { - helpers.each(value, function(valueObj, index) { - var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear'); - var axisDefaults = Chart.scaleService.getScaleDefaults(axisType); - if (index >= base[key].length || !base[key][index].type) { - base[key].push(helpers.configMerge(axisDefaults, valueObj)); - } else if (valueObj.type && valueObj.type !== base[key][index].type) { - // Type changed. Bring in the new defaults before we bring in valueObj so that valueObj can override the correct scale defaults - base[key][index] = helpers.configMerge(base[key][index], axisDefaults, valueObj); - } else { - // Type is the same - base[key][index] = helpers.configMerge(base[key][index], valueObj); - } - }); - } else { - base[key] = []; - helpers.each(value, function(valueObj) { - var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear'); - base[key].push(helpers.configMerge(Chart.scaleService.getScaleDefaults(axisType), valueObj)); - }); - } - } else if (base.hasOwnProperty(key) && typeof base[key] === 'object' && base[key] !== null && typeof value === 'object') { - // If we are overwriting an object with an object, do a merge of the properties. - base[key] = helpers.configMerge(base[key], value); - - } else { - // can just overwrite the value in this case - base[key] = value; - } - }); - - return base; - }; - helpers.getValueAtIndexOrDefault = function(value, index, defaultValue) { - if (value === undefined || value === null) { - return defaultValue; - } - - if (helpers.isArray(value)) { - return index < value.length ? value[index] : defaultValue; - } - - return value; - }; - helpers.getValueOrDefault = function(value, defaultValue) { - return value === undefined ? defaultValue : value; - }; - helpers.indexOf = Array.prototype.indexOf? - function(array, item) { - return array.indexOf(item); - }: - function(array, item) { - for (var i = 0, ilen = array.length; i < ilen; ++i) { - if (array[i] === item) { - return i; - } - } - return -1; - }; - helpers.where = function(collection, filterCallback) { - if (helpers.isArray(collection) && Array.prototype.filter) { - return collection.filter(filterCallback); - } - var filtered = []; - - helpers.each(collection, function(item) { - if (filterCallback(item)) { - filtered.push(item); - } - }); - - return filtered; - }; - helpers.findIndex = Array.prototype.findIndex? - function(array, callback, scope) { - return array.findIndex(callback, scope); - } : - function(array, callback, scope) { - scope = scope === undefined? array : scope; - for (var i = 0, ilen = array.length; i < ilen; ++i) { - if (callback.call(scope, array[i], i, array)) { - return i; - } - } - return -1; - }; - helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex) { - // Default to start of the array - if (startIndex === undefined || startIndex === null) { - startIndex = -1; - } - for (var i = startIndex + 1; i < arrayToSearch.length; i++) { - var currentItem = arrayToSearch[i]; - if (filterCallback(currentItem)) { - return currentItem; - } - } - }; - helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) { - // Default to end of the array - if (startIndex === undefined || startIndex === null) { - startIndex = arrayToSearch.length; - } - for (var i = startIndex - 1; i >= 0; i--) { - var currentItem = arrayToSearch[i]; - if (filterCallback(currentItem)) { - return currentItem; - } - } - }; - helpers.inherits = function(extensions) { - // Basic javascript inheritance based on the model created in Backbone.js - var me = this; - var ChartElement = (extensions && extensions.hasOwnProperty('constructor')) ? extensions.constructor : function() { - return me.apply(this, arguments); - }; - - var Surrogate = function() { - this.constructor = ChartElement; - }; - Surrogate.prototype = me.prototype; - ChartElement.prototype = new Surrogate(); - - ChartElement.extend = helpers.inherits; - - if (extensions) { - helpers.extend(ChartElement.prototype, extensions); - } - - ChartElement.__super__ = me.prototype; - - return ChartElement; - }; - helpers.noop = function() {}; - helpers.uid = (function() { - var id = 0; - return function() { - return id++; - }; - }()); - // -- Math methods - helpers.isNumber = function(n) { - return !isNaN(parseFloat(n)) && isFinite(n); - }; - helpers.almostEquals = function(x, y, epsilon) { - return Math.abs(x - y) < epsilon; - }; - helpers.almostWhole = function(x, epsilon) { - var rounded = Math.round(x); - return (((rounded - epsilon) < x) && ((rounded + epsilon) > x)); - }; - helpers.max = function(array) { - return array.reduce(function(max, value) { - if (!isNaN(value)) { - return Math.max(max, value); - } - return max; - }, Number.NEGATIVE_INFINITY); - }; - helpers.min = function(array) { - return array.reduce(function(min, value) { - if (!isNaN(value)) { - return Math.min(min, value); - } - return min; - }, Number.POSITIVE_INFINITY); - }; - helpers.sign = Math.sign? - function(x) { - return Math.sign(x); - } : - function(x) { - x = +x; // convert to a number - if (x === 0 || isNaN(x)) { - return x; - } - return x > 0 ? 1 : -1; - }; - helpers.log10 = Math.log10? - function(x) { - return Math.log10(x); - } : - function(x) { - return Math.log(x) / Math.LN10; - }; - helpers.toRadians = function(degrees) { - return degrees * (Math.PI / 180); - }; - helpers.toDegrees = function(radians) { - return radians * (180 / Math.PI); - }; - // Gets the angle from vertical upright to the point about a centre. - helpers.getAngleFromPoint = function(centrePoint, anglePoint) { - var distanceFromXCenter = anglePoint.x - centrePoint.x, - distanceFromYCenter = anglePoint.y - centrePoint.y, - radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter); - - var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter); - - if (angle < (-0.5 * Math.PI)) { - angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2] - } - - return { - angle: angle, - distance: radialDistanceFromCenter - }; - }; - helpers.distanceBetweenPoints = function(pt1, pt2) { - return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2)); - }; - helpers.aliasPixel = function(pixelWidth) { - return (pixelWidth % 2 === 0) ? 0 : 0.5; - }; - helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) { - // Props to Rob Spencer at scaled innovation for his post on splining between points - // http://scaledinnovation.com/analytics/splines/aboutSplines.html - - // This function must also respect "skipped" points - - var previous = firstPoint.skip ? middlePoint : firstPoint, - current = middlePoint, - next = afterPoint.skip ? middlePoint : afterPoint; - - var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2)); - var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2)); - - var s01 = d01 / (d01 + d12); - var s12 = d12 / (d01 + d12); - - // If all points are the same, s01 & s02 will be inf - s01 = isNaN(s01) ? 0 : s01; - s12 = isNaN(s12) ? 0 : s12; - - var fa = t * s01; // scaling factor for triangle Ta - var fb = t * s12; - - return { - previous: { - x: current.x - fa * (next.x - previous.x), - y: current.y - fa * (next.y - previous.y) - }, - next: { - x: current.x + fb * (next.x - previous.x), - y: current.y + fb * (next.y - previous.y) - } - }; - }; - helpers.EPSILON = Number.EPSILON || 1e-14; - helpers.splineCurveMonotone = function(points) { - // This function calculates Bézier control points in a similar way than |splineCurve|, - // but preserves monotonicity of the provided data and ensures no local extremums are added - // between the dataset discrete points due to the interpolation. - // See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation - - var pointsWithTangents = (points || []).map(function(point) { - return { - model: point._model, - deltaK: 0, - mK: 0 - }; - }); - - // Calculate slopes (deltaK) and initialize tangents (mK) - var pointsLen = pointsWithTangents.length; - var i, pointBefore, pointCurrent, pointAfter; - for (i = 0; i < pointsLen; ++i) { - pointCurrent = pointsWithTangents[i]; - if (pointCurrent.model.skip) { - continue; - } - - pointBefore = i > 0 ? pointsWithTangents[i - 1] : null; - pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null; - if (pointAfter && !pointAfter.model.skip) { - var slopeDeltaX = (pointAfter.model.x - pointCurrent.model.x); - - // In the case of two points that appear at the same x pixel, slopeDeltaX is 0 - pointCurrent.deltaK = slopeDeltaX !== 0 ? (pointAfter.model.y - pointCurrent.model.y) / slopeDeltaX : 0; - } - - if (!pointBefore || pointBefore.model.skip) { - pointCurrent.mK = pointCurrent.deltaK; - } else if (!pointAfter || pointAfter.model.skip) { - pointCurrent.mK = pointBefore.deltaK; - } else if (this.sign(pointBefore.deltaK) !== this.sign(pointCurrent.deltaK)) { - pointCurrent.mK = 0; - } else { - pointCurrent.mK = (pointBefore.deltaK + pointCurrent.deltaK) / 2; - } - } - - // Adjust tangents to ensure monotonic properties - var alphaK, betaK, tauK, squaredMagnitude; - for (i = 0; i < pointsLen - 1; ++i) { - pointCurrent = pointsWithTangents[i]; - pointAfter = pointsWithTangents[i + 1]; - if (pointCurrent.model.skip || pointAfter.model.skip) { - continue; - } - - if (helpers.almostEquals(pointCurrent.deltaK, 0, this.EPSILON)) { - pointCurrent.mK = pointAfter.mK = 0; - continue; - } - - alphaK = pointCurrent.mK / pointCurrent.deltaK; - betaK = pointAfter.mK / pointCurrent.deltaK; - squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2); - if (squaredMagnitude <= 9) { - continue; - } - - tauK = 3 / Math.sqrt(squaredMagnitude); - pointCurrent.mK = alphaK * tauK * pointCurrent.deltaK; - pointAfter.mK = betaK * tauK * pointCurrent.deltaK; - } - - // Compute control points - var deltaX; - for (i = 0; i < pointsLen; ++i) { - pointCurrent = pointsWithTangents[i]; - if (pointCurrent.model.skip) { - continue; - } - - pointBefore = i > 0 ? pointsWithTangents[i - 1] : null; - pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null; - if (pointBefore && !pointBefore.model.skip) { - deltaX = (pointCurrent.model.x - pointBefore.model.x) / 3; - pointCurrent.model.controlPointPreviousX = pointCurrent.model.x - deltaX; - pointCurrent.model.controlPointPreviousY = pointCurrent.model.y - deltaX * pointCurrent.mK; - } - if (pointAfter && !pointAfter.model.skip) { - deltaX = (pointAfter.model.x - pointCurrent.model.x) / 3; - pointCurrent.model.controlPointNextX = pointCurrent.model.x + deltaX; - pointCurrent.model.controlPointNextY = pointCurrent.model.y + deltaX * pointCurrent.mK; - } - } - }; - helpers.nextItem = function(collection, index, loop) { - if (loop) { - return index >= collection.length - 1 ? collection[0] : collection[index + 1]; - } - return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1]; - }; - helpers.previousItem = function(collection, index, loop) { - if (loop) { - return index <= 0 ? collection[collection.length - 1] : collection[index - 1]; - } - return index <= 0 ? collection[0] : collection[index - 1]; - }; - // Implementation of the nice number algorithm used in determining where axis labels will go - helpers.niceNum = function(range, round) { - var exponent = Math.floor(helpers.log10(range)); - var fraction = range / Math.pow(10, exponent); - var niceFraction; - - if (round) { - if (fraction < 1.5) { - niceFraction = 1; - } else if (fraction < 3) { - niceFraction = 2; - } else if (fraction < 7) { - niceFraction = 5; - } else { - niceFraction = 10; - } - } else if (fraction <= 1.0) { - niceFraction = 1; - } else if (fraction <= 2) { - niceFraction = 2; - } else if (fraction <= 5) { - niceFraction = 5; - } else { - niceFraction = 10; - } - - return niceFraction * Math.pow(10, exponent); - }; - // Easing functions adapted from Robert Penner's easing equations - // http://www.robertpenner.com/easing/ - var easingEffects = helpers.easingEffects = { - linear: function(t) { - return t; - }, - easeInQuad: function(t) { - return t * t; - }, - easeOutQuad: function(t) { - return -1 * t * (t - 2); - }, - easeInOutQuad: function(t) { - if ((t /= 1 / 2) < 1) { - return 1 / 2 * t * t; - } - return -1 / 2 * ((--t) * (t - 2) - 1); - }, - easeInCubic: function(t) { - return t * t * t; - }, - easeOutCubic: function(t) { - return 1 * ((t = t / 1 - 1) * t * t + 1); - }, - easeInOutCubic: function(t) { - if ((t /= 1 / 2) < 1) { - return 1 / 2 * t * t * t; - } - return 1 / 2 * ((t -= 2) * t * t + 2); - }, - easeInQuart: function(t) { - return t * t * t * t; - }, - easeOutQuart: function(t) { - return -1 * ((t = t / 1 - 1) * t * t * t - 1); - }, - easeInOutQuart: function(t) { - if ((t /= 1 / 2) < 1) { - return 1 / 2 * t * t * t * t; - } - return -1 / 2 * ((t -= 2) * t * t * t - 2); - }, - easeInQuint: function(t) { - return 1 * (t /= 1) * t * t * t * t; - }, - easeOutQuint: function(t) { - return 1 * ((t = t / 1 - 1) * t * t * t * t + 1); - }, - easeInOutQuint: function(t) { - if ((t /= 1 / 2) < 1) { - return 1 / 2 * t * t * t * t * t; - } - return 1 / 2 * ((t -= 2) * t * t * t * t + 2); - }, - easeInSine: function(t) { - return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1; - }, - easeOutSine: function(t) { - return 1 * Math.sin(t / 1 * (Math.PI / 2)); - }, - easeInOutSine: function(t) { - return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1); - }, - easeInExpo: function(t) { - return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1)); - }, - easeOutExpo: function(t) { - return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1); - }, - easeInOutExpo: function(t) { - if (t === 0) { - return 0; - } - if (t === 1) { - return 1; - } - if ((t /= 1 / 2) < 1) { - return 1 / 2 * Math.pow(2, 10 * (t - 1)); - } - return 1 / 2 * (-Math.pow(2, -10 * --t) + 2); - }, - easeInCirc: function(t) { - if (t >= 1) { - return t; - } - return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1); - }, - easeOutCirc: function(t) { - return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t); - }, - easeInOutCirc: function(t) { - if ((t /= 1 / 2) < 1) { - return -1 / 2 * (Math.sqrt(1 - t * t) - 1); - } - return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1); - }, - easeInElastic: function(t) { - var s = 1.70158; - var p = 0; - var a = 1; - if (t === 0) { - return 0; - } - if ((t /= 1) === 1) { - return 1; - } - if (!p) { - p = 1 * 0.3; - } - if (a < Math.abs(1)) { - a = 1; - s = p / 4; - } else { - s = p / (2 * Math.PI) * Math.asin(1 / a); - } - return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p)); - }, - easeOutElastic: function(t) { - var s = 1.70158; - var p = 0; - var a = 1; - if (t === 0) { - return 0; - } - if ((t /= 1) === 1) { - return 1; - } - if (!p) { - p = 1 * 0.3; - } - if (a < Math.abs(1)) { - a = 1; - s = p / 4; - } else { - s = p / (2 * Math.PI) * Math.asin(1 / a); - } - return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1; - }, - easeInOutElastic: function(t) { - var s = 1.70158; - var p = 0; - var a = 1; - if (t === 0) { - return 0; - } - if ((t /= 1 / 2) === 2) { - return 1; - } - if (!p) { - p = 1 * (0.3 * 1.5); - } - if (a < Math.abs(1)) { - a = 1; - s = p / 4; - } else { - s = p / (2 * Math.PI) * Math.asin(1 / a); - } - if (t < 1) { - return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p)); - } - return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1; - }, - easeInBack: function(t) { - var s = 1.70158; - return 1 * (t /= 1) * t * ((s + 1) * t - s); - }, - easeOutBack: function(t) { - var s = 1.70158; - return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1); - }, - easeInOutBack: function(t) { - var s = 1.70158; - if ((t /= 1 / 2) < 1) { - return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)); - } - return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); - }, - easeInBounce: function(t) { - return 1 - easingEffects.easeOutBounce(1 - t); - }, - easeOutBounce: function(t) { - if ((t /= 1) < (1 / 2.75)) { - return 1 * (7.5625 * t * t); - } else if (t < (2 / 2.75)) { - return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75); - } else if (t < (2.5 / 2.75)) { - return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375); - } - return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375); - }, - easeInOutBounce: function(t) { - if (t < 1 / 2) { - return easingEffects.easeInBounce(t * 2) * 0.5; - } - return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5; - } - }; - // Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ - helpers.requestAnimFrame = (function() { - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function(callback) { - return window.setTimeout(callback, 1000 / 60); - }; - }()); - // -- DOM methods - helpers.getRelativePosition = function(evt, chart) { - var mouseX, mouseY; - var e = evt.originalEvent || evt, - canvas = evt.currentTarget || evt.srcElement, - boundingRect = canvas.getBoundingClientRect(); - - var touches = e.touches; - if (touches && touches.length > 0) { - mouseX = touches[0].clientX; - mouseY = touches[0].clientY; - - } else { - mouseX = e.clientX; - mouseY = e.clientY; - } - - // Scale mouse coordinates into canvas coordinates - // by following the pattern laid out by 'jerryj' in the comments of - // http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/ - var paddingLeft = parseFloat(helpers.getStyle(canvas, 'padding-left')); - var paddingTop = parseFloat(helpers.getStyle(canvas, 'padding-top')); - var paddingRight = parseFloat(helpers.getStyle(canvas, 'padding-right')); - var paddingBottom = parseFloat(helpers.getStyle(canvas, 'padding-bottom')); - var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight; - var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom; - - // We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However - // the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here - mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio); - mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio); - - return { - x: mouseX, - y: mouseY - }; - - }; - helpers.addEvent = function(node, eventType, method) { - if (node.addEventListener) { - node.addEventListener(eventType, method); - } else if (node.attachEvent) { - node.attachEvent('on' + eventType, method); - } else { - node['on' + eventType] = method; - } - }; - helpers.removeEvent = function(node, eventType, handler) { - if (node.removeEventListener) { - node.removeEventListener(eventType, handler, false); - } else if (node.detachEvent) { - node.detachEvent('on' + eventType, handler); - } else { - node['on' + eventType] = helpers.noop; - } - }; - - // Private helper function to convert max-width/max-height values that may be percentages into a number - function parseMaxStyle(styleValue, node, parentProperty) { - var valueInPixels; - if (typeof(styleValue) === 'string') { - valueInPixels = parseInt(styleValue, 10); - - if (styleValue.indexOf('%') !== -1) { - // percentage * size in dimension - valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty]; - } - } else { - valueInPixels = styleValue; - } - - return valueInPixels; - } - - /** - * Returns if the given value contains an effective constraint. - * @private - */ - function isConstrainedValue(value) { - return value !== undefined && value !== null && value !== 'none'; - } - - // Private helper to get a constraint dimension - // @param domNode : the node to check the constraint on - // @param maxStyle : the style that defines the maximum for the direction we are using (maxWidth / maxHeight) - // @param percentageProperty : property of parent to use when calculating width as a percentage - // @see http://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser - function getConstraintDimension(domNode, maxStyle, percentageProperty) { - var view = document.defaultView; - var parentNode = domNode.parentNode; - var constrainedNode = view.getComputedStyle(domNode)[maxStyle]; - var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle]; - var hasCNode = isConstrainedValue(constrainedNode); - var hasCContainer = isConstrainedValue(constrainedContainer); - var infinity = Number.POSITIVE_INFINITY; - - if (hasCNode || hasCContainer) { - return Math.min( - hasCNode? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity, - hasCContainer? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity); - } - - return 'none'; - } - // returns Number or undefined if no constraint - helpers.getConstraintWidth = function(domNode) { - return getConstraintDimension(domNode, 'max-width', 'clientWidth'); - }; - // returns Number or undefined if no constraint - helpers.getConstraintHeight = function(domNode) { - return getConstraintDimension(domNode, 'max-height', 'clientHeight'); - }; - helpers.getMaximumWidth = function(domNode) { - var container = domNode.parentNode; - var paddingLeft = parseInt(helpers.getStyle(container, 'padding-left'), 10); - var paddingRight = parseInt(helpers.getStyle(container, 'padding-right'), 10); - var w = container.clientWidth - paddingLeft - paddingRight; - var cw = helpers.getConstraintWidth(domNode); - return isNaN(cw)? w : Math.min(w, cw); - }; - helpers.getMaximumHeight = function(domNode) { - var container = domNode.parentNode; - var paddingTop = parseInt(helpers.getStyle(container, 'padding-top'), 10); - var paddingBottom = parseInt(helpers.getStyle(container, 'padding-bottom'), 10); - var h = container.clientHeight - paddingTop - paddingBottom; - var ch = helpers.getConstraintHeight(domNode); - return isNaN(ch)? h : Math.min(h, ch); - }; - helpers.getStyle = function(el, property) { - return el.currentStyle ? - el.currentStyle[property] : - document.defaultView.getComputedStyle(el, null).getPropertyValue(property); - }; - helpers.retinaScale = function(chart) { - var pixelRatio = chart.currentDevicePixelRatio = window.devicePixelRatio || 1; - if (pixelRatio === 1) { - return; - } - - var canvas = chart.canvas; - var height = chart.height; - var width = chart.width; - - canvas.height = height * pixelRatio; - canvas.width = width * pixelRatio; - chart.ctx.scale(pixelRatio, pixelRatio); - - // If no style has been set on the canvas, the render size is used as display size, - // making the chart visually bigger, so let's enforce it to the "correct" values. - // See https://github.com/chartjs/Chart.js/issues/3575 - canvas.style.height = height + 'px'; - canvas.style.width = width + 'px'; - }; - // -- Canvas methods - helpers.clear = function(chart) { - chart.ctx.clearRect(0, 0, chart.width, chart.height); - }; - helpers.fontString = function(pixelSize, fontStyle, fontFamily) { - return fontStyle + ' ' + pixelSize + 'px ' + fontFamily; - }; - helpers.longestText = function(ctx, font, arrayOfThings, cache) { - cache = cache || {}; - var data = cache.data = cache.data || {}; - var gc = cache.garbageCollect = cache.garbageCollect || []; - - if (cache.font !== font) { - data = cache.data = {}; - gc = cache.garbageCollect = []; - cache.font = font; - } - - ctx.font = font; - var longest = 0; - helpers.each(arrayOfThings, function(thing) { - // Undefined strings and arrays should not be measured - if (thing !== undefined && thing !== null && helpers.isArray(thing) !== true) { - longest = helpers.measureText(ctx, data, gc, longest, thing); - } else if (helpers.isArray(thing)) { - // if it is an array lets measure each element - // to do maybe simplify this function a bit so we can do this more recursively? - helpers.each(thing, function(nestedThing) { - // Undefined strings and arrays should not be measured - if (nestedThing !== undefined && nestedThing !== null && !helpers.isArray(nestedThing)) { - longest = helpers.measureText(ctx, data, gc, longest, nestedThing); - } - }); - } - }); - - var gcLen = gc.length / 2; - if (gcLen > arrayOfThings.length) { - for (var i = 0; i < gcLen; i++) { - delete data[gc[i]]; - } - gc.splice(0, gcLen); - } - return longest; - }; - helpers.measureText = function(ctx, data, gc, longest, string) { - var textWidth = data[string]; - if (!textWidth) { - textWidth = data[string] = ctx.measureText(string).width; - gc.push(string); - } - if (textWidth > longest) { - longest = textWidth; - } - return longest; - }; - helpers.numberOfLabelLines = function(arrayOfThings) { - var numberOfLines = 1; - helpers.each(arrayOfThings, function(thing) { - if (helpers.isArray(thing)) { - if (thing.length > numberOfLines) { - numberOfLines = thing.length; - } - } - }); - return numberOfLines; - }; - helpers.drawRoundedRectangle = function(ctx, x, y, width, height, radius) { - ctx.beginPath(); - ctx.moveTo(x + radius, y); - ctx.lineTo(x + width - radius, y); - ctx.quadraticCurveTo(x + width, y, x + width, y + radius); - ctx.lineTo(x + width, y + height - radius); - ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); - ctx.lineTo(x + radius, y + height); - ctx.quadraticCurveTo(x, y + height, x, y + height - radius); - ctx.lineTo(x, y + radius); - ctx.quadraticCurveTo(x, y, x + radius, y); - ctx.closePath(); - }; - helpers.color = function(c) { - if (!color) { - console.error('Color.js not found!'); - return c; - } - - /* global CanvasGradient */ - if (c instanceof CanvasGradient) { - return color(Chart.defaults.global.defaultColor); - } - - return color(c); - }; - helpers.isArray = Array.isArray? - function(obj) { - return Array.isArray(obj); - } : - function(obj) { - return Object.prototype.toString.call(obj) === '[object Array]'; - }; - // ! @see http://stackoverflow.com/a/14853974 - helpers.arrayEquals = function(a0, a1) { - var i, ilen, v0, v1; - - if (!a0 || !a1 || a0.length !== a1.length) { - return false; - } - - for (i = 0, ilen=a0.length; i < ilen; ++i) { - v0 = a0[i]; - v1 = a1[i]; - - if (v0 instanceof Array && v1 instanceof Array) { - if (!helpers.arrayEquals(v0, v1)) { - return false; - } - } else if (v0 !== v1) { - // NOTE: two different object instances will never be equal: {x:20} != {x:20} - return false; - } - } - - return true; - }; - helpers.callCallback = function(fn, args, _tArg) { - if (fn && typeof fn.call === 'function') { - fn.apply(_tArg, args); - } - }; - helpers.getHoverColor = function(colorValue) { - /* global CanvasPattern */ - return (colorValue instanceof CanvasPattern) ? - colorValue : - helpers.color(colorValue).saturate(0.5).darken(0.1).rgbString(); - }; - }; - -},{"3":3}],27:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - var helpers = Chart.helpers; - - /** - * Helper function to get relative position for an event - * @param {Event|IEvent} event - The event to get the position for - * @param {Chart} chart - The chart - * @returns {Point} the event position - */ - function getRelativePosition(e, chart) { - if (e.native) { - return { - x: e.x, - y: e.y - }; - } - - return helpers.getRelativePosition(e, chart); - } - - /** - * Helper function to traverse all of the visible elements in the chart - * @param chart {chart} the chart - * @param handler {Function} the callback to execute for each visible item - */ - function parseVisibleItems(chart, handler) { - var datasets = chart.data.datasets; - var meta, i, j, ilen, jlen; - - for (i = 0, ilen = datasets.length; i < ilen; ++i) { - if (!chart.isDatasetVisible(i)) { - continue; - } - - meta = chart.getDatasetMeta(i); - for (j = 0, jlen = meta.data.length; j < jlen; ++j) { - var element = meta.data[j]; - if (!element._view.skip) { - handler(element); - } - } - } - } - - /** - * Helper function to get the items that intersect the event position - * @param items {ChartElement[]} elements to filter - * @param position {Point} the point to be nearest to - * @return {ChartElement[]} the nearest items - */ - function getIntersectItems(chart, position) { - var elements = []; - - parseVisibleItems(chart, function(element) { - if (element.inRange(position.x, position.y)) { - elements.push(element); - } - }); - - return elements; - } - - /** - * Helper function to get the items nearest to the event position considering all visible items in teh chart - * @param chart {Chart} the chart to look at elements from - * @param position {Point} the point to be nearest to - * @param intersect {Boolean} if true, only consider items that intersect the position - * @param distanceMetric {Function} Optional function to provide the distance between - * @return {ChartElement[]} the nearest items - */ - function getNearestItems(chart, position, intersect, distanceMetric) { - var minDistance = Number.POSITIVE_INFINITY; - var nearestItems = []; - - if (!distanceMetric) { - distanceMetric = helpers.distanceBetweenPoints; - } - - parseVisibleItems(chart, function(element) { - if (intersect && !element.inRange(position.x, position.y)) { - return; - } - - var center = element.getCenterPoint(); - var distance = distanceMetric(position, center); - - if (distance < minDistance) { - nearestItems = [element]; - minDistance = distance; - } else if (distance === minDistance) { - // Can have multiple items at the same distance in which case we sort by size - nearestItems.push(element); - } - }); - - return nearestItems; - } - - function indexMode(chart, e, options) { - var position = getRelativePosition(e, chart.chart); - var distanceMetric = function(pt1, pt2) { - return Math.abs(pt1.x - pt2.x); - }; - var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); - var elements = []; - - if (!items.length) { - return []; - } - - chart.data.datasets.forEach(function(dataset, datasetIndex) { - if (chart.isDatasetVisible(datasetIndex)) { - var meta = chart.getDatasetMeta(datasetIndex), - element = meta.data[items[0]._index]; - - // don't count items that are skipped (null data) - if (element && !element._view.skip) { - elements.push(element); - } - } - }); - - return elements; - } - - /** - * @interface IInteractionOptions - */ - /** - * If true, only consider items that intersect the point - * @name IInterfaceOptions#boolean - * @type Boolean - */ - - /** - * Contains interaction related functions - * @namespace Chart.Interaction - */ - Chart.Interaction = { - // Helper function for different modes - modes: { - single: function(chart, e) { - var position = getRelativePosition(e, chart.chart); - var elements = []; - - parseVisibleItems(chart, function(element) { - if (element.inRange(position.x, position.y)) { - elements.push(element); - return elements; - } - }); - - return elements.slice(0, 1); - }, - - /** - * @function Chart.Interaction.modes.label - * @deprecated since version 2.4.0 - */ - label: indexMode, - - /** - * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something - * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item - * @function Chart.Interaction.modes.index - * @since v2.4.0 - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @param options {IInteractionOptions} options to use during interaction - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - index: indexMode, - - /** - * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something - * If the options.intersect is false, we find the nearest item and return the items in that dataset - * @function Chart.Interaction.modes.dataset - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @param options {IInteractionOptions} options to use during interaction - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - dataset: function(chart, e, options) { - var position = getRelativePosition(e, chart.chart); - var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false); - - if (items.length > 0) { - items = chart.getDatasetMeta(items[0]._datasetIndex).data; - } - - return items; - }, - - /** - * @function Chart.Interaction.modes.x-axis - * @deprecated since version 2.4.0. Use index mode and intersect == true - */ - 'x-axis': function(chart, e) { - return indexMode(chart, e, true); - }, - - /** - * Point mode returns all elements that hit test based on the event position - * of the event - * @function Chart.Interaction.modes.intersect - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - point: function(chart, e) { - var position = getRelativePosition(e, chart.chart); - return getIntersectItems(chart, position); - }, - - /** - * nearest mode returns the element closest to the point - * @function Chart.Interaction.modes.intersect - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @param options {IInteractionOptions} options to use - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - nearest: function(chart, e, options) { - var position = getRelativePosition(e, chart.chart); - var nearestItems = getNearestItems(chart, position, options.intersect); - - // We have multiple items at the same distance from the event. Now sort by smallest - if (nearestItems.length > 1) { - nearestItems.sort(function(a, b) { - var sizeA = a.getArea(); - var sizeB = b.getArea(); - var ret = sizeA - sizeB; - - if (ret === 0) { - // if equal sort by dataset index - ret = a._datasetIndex - b._datasetIndex; - } - - return ret; - }); - } - - // Return only 1 item - return nearestItems.slice(0, 1); - }, - - /** - * x mode returns the elements that hit-test at the current x coordinate - * @function Chart.Interaction.modes.x - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @param options {IInteractionOptions} options to use - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - x: function(chart, e, options) { - var position = getRelativePosition(e, chart.chart); - var items = []; - var intersectsItem = false; - - parseVisibleItems(chart, function(element) { - if (element.inXRange(position.x)) { - items.push(element); - } - - if (element.inRange(position.x, position.y)) { - intersectsItem = true; - } - }); - - // If we want to trigger on an intersect and we don't have any items - // that intersect the position, return nothing - if (options.intersect && !intersectsItem) { - items = []; - } - return items; - }, - - /** - * y mode returns the elements that hit-test at the current y coordinate - * @function Chart.Interaction.modes.y - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @param options {IInteractionOptions} options to use - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - y: function(chart, e, options) { - var position = getRelativePosition(e, chart.chart); - var items = []; - var intersectsItem = false; - - parseVisibleItems(chart, function(element) { - if (element.inYRange(position.y)) { - items.push(element); - } - - if (element.inRange(position.x, position.y)) { - intersectsItem = true; - } - }); - - // If we want to trigger on an intersect and we don't have any items - // that intersect the position, return nothing - if (options.intersect && !intersectsItem) { - items = []; - } - return items; - } - } - }; - }; - -},{}],28:[function(require,module,exports){ - 'use strict'; - - module.exports = function() { - - // Occupy the global variable of Chart, and create a simple base class - var Chart = function(item, config) { - this.controller = new Chart.Controller(item, config, this); - return this.controller; - }; - - // Globally expose the defaults to allow for user updating/changing - Chart.defaults = { - global: { - responsive: true, - responsiveAnimationDuration: 0, - maintainAspectRatio: true, - events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'], - hover: { - onHover: null, - mode: 'nearest', - intersect: true, - animationDuration: 400 - }, - onClick: null, - defaultColor: 'rgba(0,0,0,0.1)', - defaultFontColor: '#666', - defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", - defaultFontSize: 12, - defaultFontStyle: 'normal', - showLines: true, - - // Element defaults defined in element extensions - elements: {}, - - // Legend callback string - legendCallback: function(chart) { - var text = []; - text.push('<ul class="' + chart.id + '-legend">'); - for (var i = 0; i < chart.data.datasets.length; i++) { - text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>'); - if (chart.data.datasets[i].label) { - text.push(chart.data.datasets[i].label); - } - text.push('</li>'); - } - text.push('</ul>'); - - return text.join(''); - } - } - }; - - Chart.Chart = Chart; - - return Chart; - }; - -},{}],29:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - // The layout service is very self explanatory. It's responsible for the layout within a chart. - // Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need - // It is this service's responsibility of carrying out that layout. - Chart.layoutService = { - defaults: {}, - - // Register a box to a chartInstance. A box is simply a reference to an object that requires layout. eg. Scales, Legend, Plugins. - addBox: function(chartInstance, box) { - if (!chartInstance.boxes) { - chartInstance.boxes = []; - } - chartInstance.boxes.push(box); - }, - - removeBox: function(chartInstance, box) { - if (!chartInstance.boxes) { - return; - } - chartInstance.boxes.splice(chartInstance.boxes.indexOf(box), 1); - }, - - // The most important function - update: function(chartInstance, width, height) { - - if (!chartInstance) { - return; - } - - var layoutOptions = chartInstance.options.layout; - var padding = layoutOptions ? layoutOptions.padding : null; - - var leftPadding = 0; - var rightPadding = 0; - var topPadding = 0; - var bottomPadding = 0; - - if (!isNaN(padding)) { - // options.layout.padding is a number. assign to all - leftPadding = padding; - rightPadding = padding; - topPadding = padding; - bottomPadding = padding; - } else { - leftPadding = padding.left || 0; - rightPadding = padding.right || 0; - topPadding = padding.top || 0; - bottomPadding = padding.bottom || 0; - } - - var leftBoxes = helpers.where(chartInstance.boxes, function(box) { - return box.options.position === 'left'; - }); - var rightBoxes = helpers.where(chartInstance.boxes, function(box) { - return box.options.position === 'right'; - }); - var topBoxes = helpers.where(chartInstance.boxes, function(box) { - return box.options.position === 'top'; - }); - var bottomBoxes = helpers.where(chartInstance.boxes, function(box) { - return box.options.position === 'bottom'; - }); - - // Boxes that overlay the chartarea such as the radialLinear scale - var chartAreaBoxes = helpers.where(chartInstance.boxes, function(box) { - return box.options.position === 'chartArea'; - }); - - // Ensure that full width boxes are at the very top / bottom - topBoxes.sort(function(a, b) { - return (b.options.fullWidth ? 1 : 0) - (a.options.fullWidth ? 1 : 0); - }); - bottomBoxes.sort(function(a, b) { - return (a.options.fullWidth ? 1 : 0) - (b.options.fullWidth ? 1 : 0); - }); - - // Essentially we now have any number of boxes on each of the 4 sides. - // Our canvas looks like the following. - // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and - // B1 is the bottom axis - // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays - // These locations are single-box locations only, when trying to register a chartArea location that is already taken, - // an error will be thrown. - // - // |----------------------------------------------------| - // | T1 (Full Width) | - // |----------------------------------------------------| - // | | | T2 | | - // | |----|-------------------------------------|----| - // | | | C1 | | C2 | | - // | | |----| |----| | - // | | | | | - // | L1 | L2 | ChartArea (C0) | R1 | - // | | | | | - // | | |----| |----| | - // | | | C3 | | C4 | | - // | |----|-------------------------------------|----| - // | | | B1 | | - // |----------------------------------------------------| - // | B2 (Full Width) | - // |----------------------------------------------------| - // - // What we do to find the best sizing, we do the following - // 1. Determine the minimum size of the chart area. - // 2. Split the remaining width equally between each vertical axis - // 3. Split the remaining height equally between each horizontal axis - // 4. Give each layout the maximum size it can be. The layout will return it's minimum size - // 5. Adjust the sizes of each axis based on it's minimum reported size. - // 6. Refit each axis - // 7. Position each axis in the final location - // 8. Tell the chart the final location of the chart area - // 9. Tell any axes that overlay the chart area the positions of the chart area - - // Step 1 - var chartWidth = width - leftPadding - rightPadding; - var chartHeight = height - topPadding - bottomPadding; - var chartAreaWidth = chartWidth / 2; // min 50% - var chartAreaHeight = chartHeight / 2; // min 50% - - // Step 2 - var verticalBoxWidth = (width - chartAreaWidth) / (leftBoxes.length + rightBoxes.length); - - // Step 3 - var horizontalBoxHeight = (height - chartAreaHeight) / (topBoxes.length + bottomBoxes.length); - - // Step 4 - var maxChartAreaWidth = chartWidth; - var maxChartAreaHeight = chartHeight; - var minBoxSizes = []; - - function getMinimumBoxSize(box) { - var minSize; - var isHorizontal = box.isHorizontal(); - - if (isHorizontal) { - minSize = box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, horizontalBoxHeight); - maxChartAreaHeight -= minSize.height; - } else { - minSize = box.update(verticalBoxWidth, chartAreaHeight); - maxChartAreaWidth -= minSize.width; - } - - minBoxSizes.push({ - horizontal: isHorizontal, - minSize: minSize, - box: box, - }); - } - - helpers.each(leftBoxes.concat(rightBoxes, topBoxes, bottomBoxes), getMinimumBoxSize); - - // If a horizontal box has padding, we move the left boxes over to avoid ugly charts (see issue #2478) - var maxHorizontalLeftPadding = 0; - var maxHorizontalRightPadding = 0; - var maxVerticalTopPadding = 0; - var maxVerticalBottomPadding = 0; - - helpers.each(topBoxes.concat(bottomBoxes), function(horizontalBox) { - if (horizontalBox.getPadding) { - var boxPadding = horizontalBox.getPadding(); - maxHorizontalLeftPadding = Math.max(maxHorizontalLeftPadding, boxPadding.left); - maxHorizontalRightPadding = Math.max(maxHorizontalRightPadding, boxPadding.right); - } - }); - - helpers.each(leftBoxes.concat(rightBoxes), function(verticalBox) { - if (verticalBox.getPadding) { - var boxPadding = verticalBox.getPadding(); - maxVerticalTopPadding = Math.max(maxVerticalTopPadding, boxPadding.top); - maxVerticalBottomPadding = Math.max(maxVerticalBottomPadding, boxPadding.bottom); - } - }); - - // At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could - // be if the axes are drawn at their minimum sizes. - // Steps 5 & 6 - var totalLeftBoxesWidth = leftPadding; - var totalRightBoxesWidth = rightPadding; - var totalTopBoxesHeight = topPadding; - var totalBottomBoxesHeight = bottomPadding; - - // Function to fit a box - function fitBox(box) { - var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBox) { - return minBox.box === box; - }); - - if (minBoxSize) { - if (box.isHorizontal()) { - var scaleMargin = { - left: Math.max(totalLeftBoxesWidth, maxHorizontalLeftPadding), - right: Math.max(totalRightBoxesWidth, maxHorizontalRightPadding), - top: 0, - bottom: 0 - }; - - // Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends - // on the margin. Sometimes they need to increase in size slightly - box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin); - } else { - box.update(minBoxSize.minSize.width, maxChartAreaHeight); - } - } - } - - // Update, and calculate the left and right margins for the horizontal boxes - helpers.each(leftBoxes.concat(rightBoxes), fitBox); - - helpers.each(leftBoxes, function(box) { - totalLeftBoxesWidth += box.width; - }); - - helpers.each(rightBoxes, function(box) { - totalRightBoxesWidth += box.width; - }); - - // Set the Left and Right margins for the horizontal boxes - helpers.each(topBoxes.concat(bottomBoxes), fitBox); - - // Figure out how much margin is on the top and bottom of the vertical boxes - helpers.each(topBoxes, function(box) { - totalTopBoxesHeight += box.height; - }); - - helpers.each(bottomBoxes, function(box) { - totalBottomBoxesHeight += box.height; - }); - - function finalFitVerticalBox(box) { - var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minSize) { - return minSize.box === box; - }); - - var scaleMargin = { - left: 0, - right: 0, - top: totalTopBoxesHeight, - bottom: totalBottomBoxesHeight - }; - - if (minBoxSize) { - box.update(minBoxSize.minSize.width, maxChartAreaHeight, scaleMargin); - } - } - - // Let the left layout know the final margin - helpers.each(leftBoxes.concat(rightBoxes), finalFitVerticalBox); - - // Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance) - totalLeftBoxesWidth = leftPadding; - totalRightBoxesWidth = rightPadding; - totalTopBoxesHeight = topPadding; - totalBottomBoxesHeight = bottomPadding; - - helpers.each(leftBoxes, function(box) { - totalLeftBoxesWidth += box.width; - }); - - helpers.each(rightBoxes, function(box) { - totalRightBoxesWidth += box.width; - }); - - helpers.each(topBoxes, function(box) { - totalTopBoxesHeight += box.height; - }); - helpers.each(bottomBoxes, function(box) { - totalBottomBoxesHeight += box.height; - }); - - // We may be adding some padding to account for rotated x axis labels - var leftPaddingAddition = Math.max(maxHorizontalLeftPadding - totalLeftBoxesWidth, 0); - totalLeftBoxesWidth += leftPaddingAddition; - totalRightBoxesWidth += Math.max(maxHorizontalRightPadding - totalRightBoxesWidth, 0); - - var topPaddingAddition = Math.max(maxVerticalTopPadding - totalTopBoxesHeight, 0); - totalTopBoxesHeight += topPaddingAddition; - totalBottomBoxesHeight += Math.max(maxVerticalBottomPadding - totalBottomBoxesHeight, 0); - - // Figure out if our chart area changed. This would occur if the dataset layout label rotation - // changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do - // without calling `fit` again - var newMaxChartAreaHeight = height - totalTopBoxesHeight - totalBottomBoxesHeight; - var newMaxChartAreaWidth = width - totalLeftBoxesWidth - totalRightBoxesWidth; - - if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) { - helpers.each(leftBoxes, function(box) { - box.height = newMaxChartAreaHeight; - }); - - helpers.each(rightBoxes, function(box) { - box.height = newMaxChartAreaHeight; - }); - - helpers.each(topBoxes, function(box) { - if (!box.options.fullWidth) { - box.width = newMaxChartAreaWidth; - } - }); - - helpers.each(bottomBoxes, function(box) { - if (!box.options.fullWidth) { - box.width = newMaxChartAreaWidth; - } - }); - - maxChartAreaHeight = newMaxChartAreaHeight; - maxChartAreaWidth = newMaxChartAreaWidth; - } - - // Step 7 - Position the boxes - var left = leftPadding + leftPaddingAddition; - var top = topPadding + topPaddingAddition; - - function placeBox(box) { - if (box.isHorizontal()) { - box.left = box.options.fullWidth ? leftPadding : totalLeftBoxesWidth; - box.right = box.options.fullWidth ? width - rightPadding : totalLeftBoxesWidth + maxChartAreaWidth; - box.top = top; - box.bottom = top + box.height; - - // Move to next point - top = box.bottom; - - } else { - - box.left = left; - box.right = left + box.width; - box.top = totalTopBoxesHeight; - box.bottom = totalTopBoxesHeight + maxChartAreaHeight; - - // Move to next point - left = box.right; - } - } - - helpers.each(leftBoxes.concat(topBoxes), placeBox); - - // Account for chart width and height - left += maxChartAreaWidth; - top += maxChartAreaHeight; - - helpers.each(rightBoxes, placeBox); - helpers.each(bottomBoxes, placeBox); - - // Step 8 - chartInstance.chartArea = { - left: totalLeftBoxesWidth, - top: totalTopBoxesHeight, - right: totalLeftBoxesWidth + maxChartAreaWidth, - bottom: totalTopBoxesHeight + maxChartAreaHeight - }; - - // Step 9 - helpers.each(chartAreaBoxes, function(box) { - box.left = chartInstance.chartArea.left; - box.top = chartInstance.chartArea.top; - box.right = chartInstance.chartArea.right; - box.bottom = chartInstance.chartArea.bottom; - - box.update(maxChartAreaWidth, maxChartAreaHeight); - }); - } - }; - }; - -},{}],30:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - var noop = helpers.noop; - - Chart.defaults.global.legend = { - - display: true, - position: 'top', - fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes) - reverse: false, - - // a callback that will handle - onClick: function(e, legendItem) { - var index = legendItem.datasetIndex; - var ci = this.chart; - var meta = ci.getDatasetMeta(index); - - // See controller.isDatasetVisible comment - meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null; - - // We hid a dataset ... rerender the chart - ci.update(); - }, - - onHover: null, - - labels: { - boxWidth: 40, - padding: 10, - // Generates labels shown in the legend - // Valid properties to return: - // text : text to display - // fillStyle : fill of coloured box - // strokeStyle: stroke of coloured box - // hidden : if this legend item refers to a hidden item - // lineCap : cap style for line - // lineDash - // lineDashOffset : - // lineJoin : - // lineWidth : - generateLabels: function(chart) { - var data = chart.data; - return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) { - return { - text: dataset.label, - fillStyle: (!helpers.isArray(dataset.backgroundColor) ? dataset.backgroundColor : dataset.backgroundColor[0]), - hidden: !chart.isDatasetVisible(i), - lineCap: dataset.borderCapStyle, - lineDash: dataset.borderDash, - lineDashOffset: dataset.borderDashOffset, - lineJoin: dataset.borderJoinStyle, - lineWidth: dataset.borderWidth, - strokeStyle: dataset.borderColor, - pointStyle: dataset.pointStyle, - - // Below is extra data used for toggling the datasets - datasetIndex: i - }; - }, this) : []; - } - } - }; - - /** - * Helper function to get the box width based on the usePointStyle option - * @param labelopts {Object} the label options on the legend - * @param fontSize {Number} the label font size - * @return {Number} width of the color box area - */ - function getBoxWidth(labelOpts, fontSize) { - return labelOpts.usePointStyle ? - fontSize * Math.SQRT2 : - labelOpts.boxWidth; - } - - Chart.Legend = Chart.Element.extend({ - - initialize: function(config) { - helpers.extend(this, config); - - // Contains hit boxes for each dataset (in dataset order) - this.legendHitBoxes = []; - - // Are we in doughnut mode which has a different data type - this.doughnutMode = false; - }, - - // These methods are ordered by lifecycle. Utilities then follow. - // Any function defined here is inherited by all legend types. - // Any function can be extended by the legend type - - beforeUpdate: noop, - update: function(maxWidth, maxHeight, margins) { - var me = this; - - // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) - me.beforeUpdate(); - - // Absorb the master measurements - me.maxWidth = maxWidth; - me.maxHeight = maxHeight; - me.margins = margins; - - // Dimensions - me.beforeSetDimensions(); - me.setDimensions(); - me.afterSetDimensions(); - // Labels - me.beforeBuildLabels(); - me.buildLabels(); - me.afterBuildLabels(); - - // Fit - me.beforeFit(); - me.fit(); - me.afterFit(); - // - me.afterUpdate(); - - return me.minSize; - }, - afterUpdate: noop, - - // - - beforeSetDimensions: noop, - setDimensions: function() { - var me = this; - // Set the unconstrained dimension before label rotation - if (me.isHorizontal()) { - // Reset position before calculating rotation - me.width = me.maxWidth; - me.left = 0; - me.right = me.width; - } else { - me.height = me.maxHeight; - - // Reset position before calculating rotation - me.top = 0; - me.bottom = me.height; - } - - // Reset padding - me.paddingLeft = 0; - me.paddingTop = 0; - me.paddingRight = 0; - me.paddingBottom = 0; - - // Reset minSize - me.minSize = { - width: 0, - height: 0 - }; - }, - afterSetDimensions: noop, - - // - - beforeBuildLabels: noop, - buildLabels: function() { - var me = this; - var labelOpts = me.options.labels; - var legendItems = labelOpts.generateLabels.call(me, me.chart); - - if (labelOpts.filter) { - legendItems = legendItems.filter(function(item) { - return labelOpts.filter(item, me.chart.data); - }); - } - - if (me.options.reverse) { - legendItems.reverse(); - } - - me.legendItems = legendItems; - }, - afterBuildLabels: noop, - - // - - beforeFit: noop, - fit: function() { - var me = this; - var opts = me.options; - var labelOpts = opts.labels; - var display = opts.display; - - var ctx = me.ctx; - - var globalDefault = Chart.defaults.global, - itemOrDefault = helpers.getValueOrDefault, - fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize), - fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle), - fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily), - labelFont = helpers.fontString(fontSize, fontStyle, fontFamily); - - // Reset hit boxes - var hitboxes = me.legendHitBoxes = []; - - var minSize = me.minSize; - var isHorizontal = me.isHorizontal(); - - if (isHorizontal) { - minSize.width = me.maxWidth; // fill all the width - minSize.height = display ? 10 : 0; - } else { - minSize.width = display ? 10 : 0; - minSize.height = me.maxHeight; // fill all the height - } - - // Increase sizes here - if (display) { - ctx.font = labelFont; - - if (isHorizontal) { - // Labels - - // Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one - var lineWidths = me.lineWidths = [0]; - var totalHeight = me.legendItems.length ? fontSize + (labelOpts.padding) : 0; - - ctx.textAlign = 'left'; - ctx.textBaseline = 'top'; - - helpers.each(me.legendItems, function(legendItem, i) { - var boxWidth = getBoxWidth(labelOpts, fontSize); - var width = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; - - if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= me.width) { - totalHeight += fontSize + (labelOpts.padding); - lineWidths[lineWidths.length] = me.left; - } - - // Store the hitbox width and height here. Final position will be updated in `draw` - hitboxes[i] = { - left: 0, - top: 0, - width: width, - height: fontSize - }; - - lineWidths[lineWidths.length - 1] += width + labelOpts.padding; - }); - - minSize.height += totalHeight; - - } else { - var vPadding = labelOpts.padding; - var columnWidths = me.columnWidths = []; - var totalWidth = labelOpts.padding; - var currentColWidth = 0; - var currentColHeight = 0; - var itemHeight = fontSize + vPadding; - - helpers.each(me.legendItems, function(legendItem, i) { - var boxWidth = getBoxWidth(labelOpts, fontSize); - var itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; - - // If too tall, go to new column - if (currentColHeight + itemHeight > minSize.height) { - totalWidth += currentColWidth + labelOpts.padding; - columnWidths.push(currentColWidth); // previous column width - - currentColWidth = 0; - currentColHeight = 0; - } - - // Get max width - currentColWidth = Math.max(currentColWidth, itemWidth); - currentColHeight += itemHeight; - - // Store the hitbox width and height here. Final position will be updated in `draw` - hitboxes[i] = { - left: 0, - top: 0, - width: itemWidth, - height: fontSize - }; - }); - - totalWidth += currentColWidth; - columnWidths.push(currentColWidth); - minSize.width += totalWidth; - } - } - - me.width = minSize.width; - me.height = minSize.height; - }, - afterFit: noop, - - // Shared Methods - isHorizontal: function() { - return this.options.position === 'top' || this.options.position === 'bottom'; - }, - - // Actually draw the legend on the canvas - draw: function() { - var me = this; - var opts = me.options; - var labelOpts = opts.labels; - var globalDefault = Chart.defaults.global, - lineDefault = globalDefault.elements.line, - legendWidth = me.width, - lineWidths = me.lineWidths; - - if (opts.display) { - var ctx = me.ctx, - cursor, - itemOrDefault = helpers.getValueOrDefault, - fontColor = itemOrDefault(labelOpts.fontColor, globalDefault.defaultFontColor), - fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize), - fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle), - fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily), - labelFont = helpers.fontString(fontSize, fontStyle, fontFamily); - - // Canvas setup - ctx.textAlign = 'left'; - ctx.textBaseline = 'top'; - ctx.lineWidth = 0.5; - ctx.strokeStyle = fontColor; // for strikethrough effect - ctx.fillStyle = fontColor; // render in correct colour - ctx.font = labelFont; - - var boxWidth = getBoxWidth(labelOpts, fontSize), - hitboxes = me.legendHitBoxes; - - // current position - var drawLegendBox = function(x, y, legendItem) { - if (isNaN(boxWidth) || boxWidth <= 0) { - return; - } - - // Set the ctx for the box - ctx.save(); - - ctx.fillStyle = itemOrDefault(legendItem.fillStyle, globalDefault.defaultColor); - ctx.lineCap = itemOrDefault(legendItem.lineCap, lineDefault.borderCapStyle); - ctx.lineDashOffset = itemOrDefault(legendItem.lineDashOffset, lineDefault.borderDashOffset); - ctx.lineJoin = itemOrDefault(legendItem.lineJoin, lineDefault.borderJoinStyle); - ctx.lineWidth = itemOrDefault(legendItem.lineWidth, lineDefault.borderWidth); - ctx.strokeStyle = itemOrDefault(legendItem.strokeStyle, globalDefault.defaultColor); - var isLineWidthZero = (itemOrDefault(legendItem.lineWidth, lineDefault.borderWidth) === 0); - - if (ctx.setLineDash) { - // IE 9 and 10 do not support line dash - ctx.setLineDash(itemOrDefault(legendItem.lineDash, lineDefault.borderDash)); - } - - if (opts.labels && opts.labels.usePointStyle) { - // Recalculate x and y for drawPoint() because its expecting - // x and y to be center of figure (instead of top left) - var radius = fontSize * Math.SQRT2 / 2; - var offSet = radius / Math.SQRT2; - var centerX = x + offSet; - var centerY = y + offSet; - - // Draw pointStyle as legend symbol - Chart.canvasHelpers.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY); - } else { - // Draw box as legend symbol - if (!isLineWidthZero) { - ctx.strokeRect(x, y, boxWidth, fontSize); - } - ctx.fillRect(x, y, boxWidth, fontSize); - } - - ctx.restore(); - }; - var fillText = function(x, y, legendItem, textWidth) { - ctx.fillText(legendItem.text, boxWidth + (fontSize / 2) + x, y); - - if (legendItem.hidden) { - // Strikethrough the text if hidden - ctx.beginPath(); - ctx.lineWidth = 2; - ctx.moveTo(boxWidth + (fontSize / 2) + x, y + (fontSize / 2)); - ctx.lineTo(boxWidth + (fontSize / 2) + x + textWidth, y + (fontSize / 2)); - ctx.stroke(); - } - }; - - // Horizontal - var isHorizontal = me.isHorizontal(); - if (isHorizontal) { - cursor = { - x: me.left + ((legendWidth - lineWidths[0]) / 2), - y: me.top + labelOpts.padding, - line: 0 - }; - } else { - cursor = { - x: me.left + labelOpts.padding, - y: me.top + labelOpts.padding, - line: 0 - }; - } - - var itemHeight = fontSize + labelOpts.padding; - helpers.each(me.legendItems, function(legendItem, i) { - var textWidth = ctx.measureText(legendItem.text).width, - width = boxWidth + (fontSize / 2) + textWidth, - x = cursor.x, - y = cursor.y; - - if (isHorizontal) { - if (x + width >= legendWidth) { - y = cursor.y += itemHeight; - cursor.line++; - x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2); - } - } else if (y + itemHeight > me.bottom) { - x = cursor.x = x + me.columnWidths[cursor.line] + labelOpts.padding; - y = cursor.y = me.top + labelOpts.padding; - cursor.line++; - } - - drawLegendBox(x, y, legendItem); - - hitboxes[i].left = x; - hitboxes[i].top = y; - - // Fill the actual label - fillText(x, y, legendItem, textWidth); - - if (isHorizontal) { - cursor.x += width + (labelOpts.padding); - } else { - cursor.y += itemHeight; - } - - }); - } - }, - - /** - * Handle an event - * @private - * @param {IEvent} event - The event to handle - * @return {Boolean} true if a change occured - */ - handleEvent: function(e) { - var me = this; - var opts = me.options; - var type = e.type === 'mouseup' ? 'click' : e.type; - var changed = false; - - if (type === 'mousemove') { - if (!opts.onHover) { - return; - } - } else if (type === 'click') { - if (!opts.onClick) { - return; - } - } else { - return; - } - - // Chart event already has relative position in it - var x = e.x, - y = e.y; - - if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) { - // See if we are touching one of the dataset boxes - var lh = me.legendHitBoxes; - for (var i = 0; i < lh.length; ++i) { - var hitBox = lh[i]; - - if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) { - // Touching an element - if (type === 'click') { - // use e.native for backwards compatibility - opts.onClick.call(me, e.native, me.legendItems[i]); - changed = true; - break; - } else if (type === 'mousemove') { - // use e.native for backwards compatibility - opts.onHover.call(me, e.native, me.legendItems[i]); - changed = true; - break; - } - } - } - } - - return changed; - } - }); - - function createNewLegendAndAttach(chartInstance, legendOpts) { - var legend = new Chart.Legend({ - ctx: chartInstance.chart.ctx, - options: legendOpts, - chart: chartInstance - }); - chartInstance.legend = legend; - Chart.layoutService.addBox(chartInstance, legend); - } - - // Register the legend plugin - Chart.plugins.register({ - beforeInit: function(chartInstance) { - var legendOpts = chartInstance.options.legend; - - if (legendOpts) { - createNewLegendAndAttach(chartInstance, legendOpts); - } - }, - beforeUpdate: function(chartInstance) { - var legendOpts = chartInstance.options.legend; - - if (legendOpts) { - legendOpts = helpers.configMerge(Chart.defaults.global.legend, legendOpts); - - if (chartInstance.legend) { - chartInstance.legend.options = legendOpts; - } else { - createNewLegendAndAttach(chartInstance, legendOpts); - } - } else { - Chart.layoutService.removeBox(chartInstance, chartInstance.legend); - delete chartInstance.legend; - } - }, - afterEvent: function(chartInstance, e) { - var legend = chartInstance.legend; - if (legend) { - legend.handleEvent(e); - } - } - }); - }; - -},{}],31:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.global.plugins = {}; - - /** - * The plugin service singleton - * @namespace Chart.plugins - * @since 2.1.0 - */ - Chart.plugins = { - /** - * Globally registered plugins. - * @private - */ - _plugins: [], - - /** - * This identifier is used to invalidate the descriptors cache attached to each chart - * when a global plugin is registered or unregistered. In this case, the cache ID is - * incremented and descriptors are regenerated during following API calls. - * @private - */ - _cacheId: 0, - - /** - * Registers the given plugin(s) if not already registered. - * @param {Array|Object} plugins plugin instance(s). - */ - register: function(plugins) { - var p = this._plugins; - ([]).concat(plugins).forEach(function(plugin) { - if (p.indexOf(plugin) === -1) { - p.push(plugin); - } - }); - - this._cacheId++; - }, - - /** - * Unregisters the given plugin(s) only if registered. - * @param {Array|Object} plugins plugin instance(s). - */ - unregister: function(plugins) { - var p = this._plugins; - ([]).concat(plugins).forEach(function(plugin) { - var idx = p.indexOf(plugin); - if (idx !== -1) { - p.splice(idx, 1); - } - }); - - this._cacheId++; - }, - - /** - * Remove all registered plugins. - * @since 2.1.5 - */ - clear: function() { - this._plugins = []; - this._cacheId++; - }, - - /** - * Returns the number of registered plugins? - * @returns {Number} - * @since 2.1.5 - */ - count: function() { - return this._plugins.length; - }, - - /** - * Returns all registered plugin instances. - * @returns {Array} array of plugin objects. - * @since 2.1.5 - */ - getAll: function() { - return this._plugins; - }, - - /** - * Calls enabled plugins for `chart` on the specified hook and with the given args. - * This method immediately returns as soon as a plugin explicitly returns false. The - * returned value can be used, for instance, to interrupt the current action. - * @param {Object} chart - The chart instance for which plugins should be called. - * @param {String} hook - The name of the plugin method to call (e.g. 'beforeUpdate'). - * @param {Array} [args] - Extra arguments to apply to the hook call. - * @returns {Boolean} false if any of the plugins return false, else returns true. - */ - notify: function(chart, hook, args) { - var descriptors = this.descriptors(chart); - var ilen = descriptors.length; - var i, descriptor, plugin, params, method; - - for (i=0; i<ilen; ++i) { - descriptor = descriptors[i]; - plugin = descriptor.plugin; - method = plugin[hook]; - if (typeof method === 'function') { - params = [chart].concat(args || []); - params.push(descriptor.options); - if (method.apply(plugin, params) === false) { - return false; - } - } - } - - return true; - }, - - /** - * Returns descriptors of enabled plugins for the given chart. - * @returns {Array} [{ plugin, options }] - * @private - */ - descriptors: function(chart) { - var cache = chart._plugins || (chart._plugins = {}); - if (cache.id === this._cacheId) { - return cache.descriptors; - } - - var plugins = []; - var descriptors = []; - var config = (chart && chart.config) || {}; - var defaults = Chart.defaults.global.plugins; - var options = (config.options && config.options.plugins) || {}; - - this._plugins.concat(config.plugins || []).forEach(function(plugin) { - var idx = plugins.indexOf(plugin); - if (idx !== -1) { - return; - } - - var id = plugin.id; - var opts = options[id]; - if (opts === false) { - return; - } - - if (opts === true) { - opts = helpers.clone(defaults[id]); - } - - plugins.push(plugin); - descriptors.push({ - plugin: plugin, - options: opts || {} - }); - }); - - cache.descriptors = descriptors; - cache.id = this._cacheId; - return descriptors; - } - }; - - /** - * Plugin extension hooks. - * @interface IPlugin - * @since 2.1.0 - */ - /** - * @method IPlugin#beforeInit - * @desc Called before initializing `chart`. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#afterInit - * @desc Called after `chart` has been initialized and before the first update. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeUpdate - * @desc Called before updating `chart`. If any plugin returns `false`, the update - * is cancelled (and thus subsequent render(s)) until another `update` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - * @returns {Boolean} `false` to cancel the chart update. - */ - /** - * @method IPlugin#afterUpdate - * @desc Called after `chart` has been updated and before rendering. Note that this - * hook will not be called if the chart update has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeDatasetsUpdate - * @desc Called before updating the `chart` datasets. If any plugin returns `false`, - * the datasets update is cancelled until another `update` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - * @returns {Boolean} false to cancel the datasets update. - * @since version 2.1.5 - */ - /** - * @method IPlugin#afterDatasetsUpdate - * @desc Called after the `chart` datasets have been updated. Note that this hook - * will not be called if the datasets update has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - * @since version 2.1.5 - */ - /** - * @method IPlugin#beforeLayout - * @desc Called before laying out `chart`. If any plugin returns `false`, - * the layout update is cancelled until another `update` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - * @returns {Boolean} `false` to cancel the chart layout. - */ - /** - * @method IPlugin#afterLayout - * @desc Called after the `chart` has been layed out. Note that this hook will not - * be called if the layout update has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeRender - * @desc Called before rendering `chart`. If any plugin returns `false`, - * the rendering is cancelled until another `render` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - * @returns {Boolean} `false` to cancel the chart rendering. - */ - /** - * @method IPlugin#afterRender - * @desc Called after the `chart` has been fully rendered (and animation completed). Note - * that this hook will not be called if the rendering has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeDraw - * @desc Called before drawing `chart` at every animation frame specified by the given - * easing value. If any plugin returns `false`, the frame drawing is cancelled until - * another `render` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. - * @param {Object} options - The plugin options. - * @returns {Boolean} `false` to cancel the chart drawing. - */ - /** - * @method IPlugin#afterDraw - * @desc Called after the `chart` has been drawn for the specific easing value. Note - * that this hook will not be called if the drawing has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeDatasetsDraw - * @desc Called before drawing the `chart` datasets. If any plugin returns `false`, - * the datasets drawing is cancelled until another `render` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. - * @param {Object} options - The plugin options. - * @returns {Boolean} `false` to cancel the chart datasets drawing. - */ - /** - * @method IPlugin#afterDatasetsDraw - * @desc Called after the `chart` datasets have been drawn. Note that this hook - * will not be called if the datasets drawing has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeEvent - * @desc Called before processing the specified `event`. If any plugin returns `false`, - * the event will be discarded. - * @param {Chart.Controller} chart - The chart instance. - * @param {IEvent} event - The event object. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#afterEvent - * @desc Called after the `event` has been consumed. Note that this hook - * will not be called if the `event` has been previously discarded. - * @param {Chart.Controller} chart - The chart instance. - * @param {IEvent} event - The event object. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#resize - * @desc Called after the chart as been resized. - * @param {Chart.Controller} chart - The chart instance. - * @param {Number} size - The new canvas display size (eq. canvas.style width & height). - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#destroy - * @desc Called after the chart as been destroyed. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - - /** - * Provided for backward compatibility, use Chart.plugins instead - * @namespace Chart.pluginService - * @deprecated since version 2.1.5 - * @todo remove at version 3 - * @private - */ - Chart.pluginService = Chart.plugins; - - /** - * Provided for backward compatibility, inheriting from Chart.PlugingBase has no - * effect, instead simply create/register plugins via plain JavaScript objects. - * @interface Chart.PluginBase - * @deprecated since version 2.5.0 - * @todo remove at version 3 - * @private - */ - Chart.PluginBase = helpers.inherits({}); - }; - -},{}],32:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.scale = { - display: true, - position: 'left', - - // grid line settings - gridLines: { - display: true, - color: 'rgba(0, 0, 0, 0.1)', - lineWidth: 1, - drawBorder: true, - drawOnChartArea: true, - drawTicks: true, - tickMarkLength: 10, - zeroLineWidth: 1, - zeroLineColor: 'rgba(0,0,0,0.25)', - offsetGridLines: false, - borderDash: [], - borderDashOffset: 0.0 - }, - - // scale label - scaleLabel: { - // actual label - labelString: '', - - // display property - display: false - }, - - // label settings - ticks: { - beginAtZero: false, - minRotation: 0, - maxRotation: 50, - mirror: false, - padding: 0, - reverse: false, - display: true, - autoSkip: true, - autoSkipPadding: 0, - labelOffset: 0, - // We pass through arrays to be rendered as multiline labels, we convert Others to strings here. - callback: Chart.Ticks.formatters.values - } - }; - - function computeTextSize(context, tick, font) { - return helpers.isArray(tick) ? - helpers.longestText(context, font, tick) : - context.measureText(tick).width; - } - - function parseFontOptions(options) { - var getValueOrDefault = helpers.getValueOrDefault; - var globalDefaults = Chart.defaults.global; - var size = getValueOrDefault(options.fontSize, globalDefaults.defaultFontSize); - var style = getValueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle); - var family = getValueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily); - - return { - size: size, - style: style, - family: family, - font: helpers.fontString(size, style, family) - }; - } - - Chart.Scale = Chart.Element.extend({ - /** - * Get the padding needed for the scale - * @method getPadding - * @private - * @returns {Padding} the necessary padding - */ - getPadding: function() { - var me = this; - return { - left: me.paddingLeft || 0, - top: me.paddingTop || 0, - right: me.paddingRight || 0, - bottom: me.paddingBottom || 0 - }; - }, - - // These methods are ordered by lifecyle. Utilities then follow. - // Any function defined here is inherited by all scale types. - // Any function can be extended by the scale type - - beforeUpdate: function() { - helpers.callCallback(this.options.beforeUpdate, [this]); - }, - update: function(maxWidth, maxHeight, margins) { - var me = this; - - // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) - me.beforeUpdate(); - - // Absorb the master measurements - me.maxWidth = maxWidth; - me.maxHeight = maxHeight; - me.margins = helpers.extend({ - left: 0, - right: 0, - top: 0, - bottom: 0 - }, margins); - me.longestTextCache = me.longestTextCache || {}; - - // Dimensions - me.beforeSetDimensions(); - me.setDimensions(); - me.afterSetDimensions(); - - // Data min/max - me.beforeDataLimits(); - me.determineDataLimits(); - me.afterDataLimits(); - - // Ticks - me.beforeBuildTicks(); - me.buildTicks(); - me.afterBuildTicks(); - - me.beforeTickToLabelConversion(); - me.convertTicksToLabels(); - me.afterTickToLabelConversion(); - - // Tick Rotation - me.beforeCalculateTickRotation(); - me.calculateTickRotation(); - me.afterCalculateTickRotation(); - // Fit - me.beforeFit(); - me.fit(); - me.afterFit(); - // - me.afterUpdate(); - - return me.minSize; - - }, - afterUpdate: function() { - helpers.callCallback(this.options.afterUpdate, [this]); - }, - - // - - beforeSetDimensions: function() { - helpers.callCallback(this.options.beforeSetDimensions, [this]); - }, - setDimensions: function() { - var me = this; - // Set the unconstrained dimension before label rotation - if (me.isHorizontal()) { - // Reset position before calculating rotation - me.width = me.maxWidth; - me.left = 0; - me.right = me.width; - } else { - me.height = me.maxHeight; - - // Reset position before calculating rotation - me.top = 0; - me.bottom = me.height; - } - - // Reset padding - me.paddingLeft = 0; - me.paddingTop = 0; - me.paddingRight = 0; - me.paddingBottom = 0; - }, - afterSetDimensions: function() { - helpers.callCallback(this.options.afterSetDimensions, [this]); - }, - - // Data limits - beforeDataLimits: function() { - helpers.callCallback(this.options.beforeDataLimits, [this]); - }, - determineDataLimits: helpers.noop, - afterDataLimits: function() { - helpers.callCallback(this.options.afterDataLimits, [this]); - }, - - // - beforeBuildTicks: function() { - helpers.callCallback(this.options.beforeBuildTicks, [this]); - }, - buildTicks: helpers.noop, - afterBuildTicks: function() { - helpers.callCallback(this.options.afterBuildTicks, [this]); - }, - - beforeTickToLabelConversion: function() { - helpers.callCallback(this.options.beforeTickToLabelConversion, [this]); - }, - convertTicksToLabels: function() { - var me = this; - // Convert ticks to strings - var tickOpts = me.options.ticks; - me.ticks = me.ticks.map(tickOpts.userCallback || tickOpts.callback); - }, - afterTickToLabelConversion: function() { - helpers.callCallback(this.options.afterTickToLabelConversion, [this]); - }, - - // - - beforeCalculateTickRotation: function() { - helpers.callCallback(this.options.beforeCalculateTickRotation, [this]); - }, - calculateTickRotation: function() { - var me = this; - var context = me.ctx; - var tickOpts = me.options.ticks; - - // Get the width of each grid by calculating the difference - // between x offsets between 0 and 1. - var tickFont = parseFontOptions(tickOpts); - context.font = tickFont.font; - - var labelRotation = tickOpts.minRotation || 0; - - if (me.options.display && me.isHorizontal()) { - var originalLabelWidth = helpers.longestText(context, tickFont.font, me.ticks, me.longestTextCache); - var labelWidth = originalLabelWidth; - var cosRotation; - var sinRotation; - - // Allow 3 pixels x2 padding either side for label readability - var tickWidth = me.getPixelForTick(1) - me.getPixelForTick(0) - 6; - - // Max label rotation can be set or default to 90 - also act as a loop counter - while (labelWidth > tickWidth && labelRotation < tickOpts.maxRotation) { - var angleRadians = helpers.toRadians(labelRotation); - cosRotation = Math.cos(angleRadians); - sinRotation = Math.sin(angleRadians); - - if (sinRotation * originalLabelWidth > me.maxHeight) { - // go back one step - labelRotation--; - break; - } - - labelRotation++; - labelWidth = cosRotation * originalLabelWidth; - } - } - - me.labelRotation = labelRotation; - }, - afterCalculateTickRotation: function() { - helpers.callCallback(this.options.afterCalculateTickRotation, [this]); - }, - - // - - beforeFit: function() { - helpers.callCallback(this.options.beforeFit, [this]); - }, - fit: function() { - var me = this; - // Reset - var minSize = me.minSize = { - width: 0, - height: 0 - }; - - var opts = me.options; - var tickOpts = opts.ticks; - var scaleLabelOpts = opts.scaleLabel; - var gridLineOpts = opts.gridLines; - var display = opts.display; - var isHorizontal = me.isHorizontal(); - - var tickFont = parseFontOptions(tickOpts); - var scaleLabelFontSize = parseFontOptions(scaleLabelOpts).size * 1.5; - var tickMarkLength = opts.gridLines.tickMarkLength; - - // Width - if (isHorizontal) { - // subtract the margins to line up with the chartArea if we are a full width scale - minSize.width = me.isFullWidth() ? me.maxWidth - me.margins.left - me.margins.right : me.maxWidth; - } else { - minSize.width = display && gridLineOpts.drawTicks ? tickMarkLength : 0; - } - - // height - if (isHorizontal) { - minSize.height = display && gridLineOpts.drawTicks ? tickMarkLength : 0; - } else { - minSize.height = me.maxHeight; // fill all the height - } - - // Are we showing a title for the scale? - if (scaleLabelOpts.display && display) { - if (isHorizontal) { - minSize.height += scaleLabelFontSize; - } else { - minSize.width += scaleLabelFontSize; - } - } - - // Don't bother fitting the ticks if we are not showing them - if (tickOpts.display && display) { - var largestTextWidth = helpers.longestText(me.ctx, tickFont.font, me.ticks, me.longestTextCache); - var tallestLabelHeightInLines = helpers.numberOfLabelLines(me.ticks); - var lineSpace = tickFont.size * 0.5; - - if (isHorizontal) { - // A horizontal axis is more constrained by the height. - me.longestLabelWidth = largestTextWidth; - - var angleRadians = helpers.toRadians(me.labelRotation); - var cosRotation = Math.cos(angleRadians); - var sinRotation = Math.sin(angleRadians); - - // TODO - improve this calculation - var labelHeight = (sinRotation * largestTextWidth) - + (tickFont.size * tallestLabelHeightInLines) - + (lineSpace * tallestLabelHeightInLines); - - minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight); - me.ctx.font = tickFont.font; - - var firstTick = me.ticks[0]; - var firstLabelWidth = computeTextSize(me.ctx, firstTick, tickFont.font); - - var lastTick = me.ticks[me.ticks.length - 1]; - var lastLabelWidth = computeTextSize(me.ctx, lastTick, tickFont.font); - - // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned which means that the right padding is dominated - // by the font height - if (me.labelRotation !== 0) { - me.paddingLeft = opts.position === 'bottom'? (cosRotation * firstLabelWidth) + 3: (cosRotation * lineSpace) + 3; // add 3 px to move away from canvas edges - me.paddingRight = opts.position === 'bottom'? (cosRotation * lineSpace) + 3: (cosRotation * lastLabelWidth) + 3; - } else { - me.paddingLeft = firstLabelWidth / 2 + 3; // add 3 px to move away from canvas edges - me.paddingRight = lastLabelWidth / 2 + 3; - } - } else { - // A vertical axis is more constrained by the width. Labels are the dominant factor here, so get that length first - // Account for padding - - if (tickOpts.mirror) { - largestTextWidth = 0; - } else { - largestTextWidth += me.options.ticks.padding; - } - minSize.width += largestTextWidth; - me.paddingTop = tickFont.size / 2; - me.paddingBottom = tickFont.size / 2; - } - } - - me.handleMargins(); - - me.width = minSize.width; - me.height = minSize.height; - }, - - /** - * Handle margins and padding interactions - * @private - */ - handleMargins: function() { - var me = this; - if (me.margins) { - me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0); - me.paddingTop = Math.max(me.paddingTop - me.margins.top, 0); - me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0); - me.paddingBottom = Math.max(me.paddingBottom - me.margins.bottom, 0); - } - }, - - afterFit: function() { - helpers.callCallback(this.options.afterFit, [this]); - }, - - // Shared Methods - isHorizontal: function() { - return this.options.position === 'top' || this.options.position === 'bottom'; - }, - isFullWidth: function() { - return (this.options.fullWidth); - }, - - // Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not - getRightValue: function(rawValue) { - // Null and undefined values first - if (rawValue === null || typeof(rawValue) === 'undefined') { - return NaN; - } - // isNaN(object) returns true, so make sure NaN is checking for a number; Discard Infinite values - if (typeof(rawValue) === 'number' && !isFinite(rawValue)) { - return NaN; - } - // If it is in fact an object, dive in one more level - if (typeof(rawValue) === 'object') { - if ((rawValue instanceof Date) || (rawValue.isValid)) { - return rawValue; - } - return this.getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y); - } - - // Value is good, return it - return rawValue; - }, - - // Used to get the value to display in the tooltip for the data at the given index - // function getLabelForIndex(index, datasetIndex) - getLabelForIndex: helpers.noop, - - // Used to get data value locations. Value can either be an index or a numerical value - getPixelForValue: helpers.noop, - - // Used to get the data value from a given pixel. This is the inverse of getPixelForValue - getValueForPixel: helpers.noop, - - // Used for tick location, should - getPixelForTick: function(index, includeOffset) { - var me = this; - if (me.isHorizontal()) { - var innerWidth = me.width - (me.paddingLeft + me.paddingRight); - var tickWidth = innerWidth / Math.max((me.ticks.length - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1); - var pixel = (tickWidth * index) + me.paddingLeft; - - if (includeOffset) { - pixel += tickWidth / 2; - } - - var finalVal = me.left + Math.round(pixel); - finalVal += me.isFullWidth() ? me.margins.left : 0; - return finalVal; - } - var innerHeight = me.height - (me.paddingTop + me.paddingBottom); - return me.top + (index * (innerHeight / (me.ticks.length - 1))); - }, - - // Utility for getting the pixel location of a percentage of scale - getPixelForDecimal: function(decimal /* , includeOffset*/) { - var me = this; - if (me.isHorizontal()) { - var innerWidth = me.width - (me.paddingLeft + me.paddingRight); - var valueOffset = (innerWidth * decimal) + me.paddingLeft; - - var finalVal = me.left + Math.round(valueOffset); - finalVal += me.isFullWidth() ? me.margins.left : 0; - return finalVal; - } - return me.top + (decimal * me.height); - }, - - getBasePixel: function() { - return this.getPixelForValue(this.getBaseValue()); - }, - - getBaseValue: function() { - var me = this; - var min = me.min; - var max = me.max; - - return me.beginAtZero ? 0: - min < 0 && max < 0? max : - min > 0 && max > 0? min : - 0; - }, - - // Actually draw the scale on the canvas - // @param {rectangle} chartArea : the area of the chart to draw full grid lines on - draw: function(chartArea) { - var me = this; - var options = me.options; - if (!options.display) { - return; - } - - var context = me.ctx; - var globalDefaults = Chart.defaults.global; - var optionTicks = options.ticks; - var gridLines = options.gridLines; - var scaleLabel = options.scaleLabel; - - var isRotated = me.labelRotation !== 0; - var skipRatio; - var useAutoskipper = optionTicks.autoSkip; - var isHorizontal = me.isHorizontal(); - - // figure out the maximum number of gridlines to show - var maxTicks; - if (optionTicks.maxTicksLimit) { - maxTicks = optionTicks.maxTicksLimit; - } - - var tickFontColor = helpers.getValueOrDefault(optionTicks.fontColor, globalDefaults.defaultFontColor); - var tickFont = parseFontOptions(optionTicks); - - var tl = gridLines.drawTicks ? gridLines.tickMarkLength : 0; - var borderDash = helpers.getValueOrDefault(gridLines.borderDash, globalDefaults.borderDash); - var borderDashOffset = helpers.getValueOrDefault(gridLines.borderDashOffset, globalDefaults.borderDashOffset); - - var scaleLabelFontColor = helpers.getValueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor); - var scaleLabelFont = parseFontOptions(scaleLabel); - - var labelRotationRadians = helpers.toRadians(me.labelRotation); - var cosRotation = Math.cos(labelRotationRadians); - var longestRotatedLabel = me.longestLabelWidth * cosRotation; - - // Make sure we draw text in the correct color and font - context.fillStyle = tickFontColor; - - var itemsToDraw = []; - - if (isHorizontal) { - skipRatio = false; - - // Only calculate the skip ratio with the half width of longestRotateLabel if we got an actual rotation - // See #2584 - if (isRotated) { - longestRotatedLabel /= 2; - } - - if ((longestRotatedLabel + optionTicks.autoSkipPadding) * me.ticks.length > (me.width - (me.paddingLeft + me.paddingRight))) { - skipRatio = 1 + Math.floor(((longestRotatedLabel + optionTicks.autoSkipPadding) * me.ticks.length) / (me.width - (me.paddingLeft + me.paddingRight))); - } - - // if they defined a max number of optionTicks, - // increase skipRatio until that number is met - if (maxTicks && me.ticks.length > maxTicks) { - while (!skipRatio || me.ticks.length / (skipRatio || 1) > maxTicks) { - if (!skipRatio) { - skipRatio = 1; - } - skipRatio += 1; - } - } - - if (!useAutoskipper) { - skipRatio = false; - } - } - - - var xTickStart = options.position === 'right' ? me.left : me.right - tl; - var xTickEnd = options.position === 'right' ? me.left + tl : me.right; - var yTickStart = options.position === 'bottom' ? me.top : me.bottom - tl; - var yTickEnd = options.position === 'bottom' ? me.top + tl : me.bottom; - - helpers.each(me.ticks, function(label, index) { - // If the callback returned a null or undefined value, do not draw this line - if (label === undefined || label === null) { - return; - } - - var isLastTick = me.ticks.length === index + 1; - - // Since we always show the last tick,we need may need to hide the last shown one before - var shouldSkip = (skipRatio > 1 && index % skipRatio > 0) || (index % skipRatio === 0 && index + skipRatio >= me.ticks.length); - if (shouldSkip && !isLastTick || (label === undefined || label === null)) { - return; - } - - var lineWidth, lineColor; - if (index === (typeof me.zeroLineIndex !== 'undefined' ? me.zeroLineIndex : 0)) { - // Draw the first index specially - lineWidth = gridLines.zeroLineWidth; - lineColor = gridLines.zeroLineColor; - } else { - lineWidth = helpers.getValueAtIndexOrDefault(gridLines.lineWidth, index); - lineColor = helpers.getValueAtIndexOrDefault(gridLines.color, index); - } - - // Common properties - var tx1, ty1, tx2, ty2, x1, y1, x2, y2, labelX, labelY; - var textAlign = 'middle'; - var textBaseline = 'middle'; - - if (isHorizontal) { - - if (options.position === 'bottom') { - // bottom - textBaseline = !isRotated? 'top':'middle'; - textAlign = !isRotated? 'center': 'right'; - labelY = me.top + tl; - } else { - // top - textBaseline = !isRotated? 'bottom':'middle'; - textAlign = !isRotated? 'center': 'left'; - labelY = me.bottom - tl; - } - - var xLineValue = me.getPixelForTick(index) + helpers.aliasPixel(lineWidth); // xvalues for grid lines - labelX = me.getPixelForTick(index, gridLines.offsetGridLines) + optionTicks.labelOffset; // x values for optionTicks (need to consider offsetLabel option) - - tx1 = tx2 = x1 = x2 = xLineValue; - ty1 = yTickStart; - ty2 = yTickEnd; - y1 = chartArea.top; - y2 = chartArea.bottom; - } else { - var isLeft = options.position === 'left'; - var tickPadding = optionTicks.padding; - var labelXOffset; - - if (optionTicks.mirror) { - textAlign = isLeft ? 'left' : 'right'; - labelXOffset = tickPadding; - } else { - textAlign = isLeft ? 'right' : 'left'; - labelXOffset = tl + tickPadding; - } - - labelX = isLeft ? me.right - labelXOffset : me.left + labelXOffset; - - var yLineValue = me.getPixelForTick(index); // xvalues for grid lines - yLineValue += helpers.aliasPixel(lineWidth); - labelY = me.getPixelForTick(index, gridLines.offsetGridLines); - - tx1 = xTickStart; - tx2 = xTickEnd; - x1 = chartArea.left; - x2 = chartArea.right; - ty1 = ty2 = y1 = y2 = yLineValue; - } - - itemsToDraw.push({ - tx1: tx1, - ty1: ty1, - tx2: tx2, - ty2: ty2, - x1: x1, - y1: y1, - x2: x2, - y2: y2, - labelX: labelX, - labelY: labelY, - glWidth: lineWidth, - glColor: lineColor, - glBorderDash: borderDash, - glBorderDashOffset: borderDashOffset, - rotation: -1 * labelRotationRadians, - label: label, - textBaseline: textBaseline, - textAlign: textAlign - }); - }); - - // Draw all of the tick labels, tick marks, and grid lines at the correct places - helpers.each(itemsToDraw, function(itemToDraw) { - if (gridLines.display) { - context.save(); - context.lineWidth = itemToDraw.glWidth; - context.strokeStyle = itemToDraw.glColor; - if (context.setLineDash) { - context.setLineDash(itemToDraw.glBorderDash); - context.lineDashOffset = itemToDraw.glBorderDashOffset; - } - - context.beginPath(); - - if (gridLines.drawTicks) { - context.moveTo(itemToDraw.tx1, itemToDraw.ty1); - context.lineTo(itemToDraw.tx2, itemToDraw.ty2); - } - - if (gridLines.drawOnChartArea) { - context.moveTo(itemToDraw.x1, itemToDraw.y1); - context.lineTo(itemToDraw.x2, itemToDraw.y2); - } - - context.stroke(); - context.restore(); - } - - if (optionTicks.display) { - context.save(); - context.translate(itemToDraw.labelX, itemToDraw.labelY); - context.rotate(itemToDraw.rotation); - context.font = tickFont.font; - context.textBaseline = itemToDraw.textBaseline; - context.textAlign = itemToDraw.textAlign; - - var label = itemToDraw.label; - if (helpers.isArray(label)) { - for (var i = 0, y = 0; i < label.length; ++i) { - // We just make sure the multiline element is a string here.. - context.fillText('' + label[i], 0, y); - // apply same lineSpacing as calculated @ L#320 - y += (tickFont.size * 1.5); - } - } else { - context.fillText(label, 0, 0); - } - context.restore(); - } - }); - - if (scaleLabel.display) { - // Draw the scale label - var scaleLabelX; - var scaleLabelY; - var rotation = 0; - - if (isHorizontal) { - scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width - scaleLabelY = options.position === 'bottom' ? me.bottom - (scaleLabelFont.size / 2) : me.top + (scaleLabelFont.size / 2); - } else { - var isLeft = options.position === 'left'; - scaleLabelX = isLeft ? me.left + (scaleLabelFont.size / 2) : me.right - (scaleLabelFont.size / 2); - scaleLabelY = me.top + ((me.bottom - me.top) / 2); - rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI; - } - - context.save(); - context.translate(scaleLabelX, scaleLabelY); - context.rotate(rotation); - context.textAlign = 'center'; - context.textBaseline = 'middle'; - context.fillStyle = scaleLabelFontColor; // render in correct colour - context.font = scaleLabelFont.font; - context.fillText(scaleLabel.labelString, 0, 0); - context.restore(); - } - - if (gridLines.drawBorder) { - // Draw the line at the edge of the axis - context.lineWidth = helpers.getValueAtIndexOrDefault(gridLines.lineWidth, 0); - context.strokeStyle = helpers.getValueAtIndexOrDefault(gridLines.color, 0); - var x1 = me.left, - x2 = me.right, - y1 = me.top, - y2 = me.bottom; - - var aliasPixel = helpers.aliasPixel(context.lineWidth); - if (isHorizontal) { - y1 = y2 = options.position === 'top' ? me.bottom : me.top; - y1 += aliasPixel; - y2 += aliasPixel; - } else { - x1 = x2 = options.position === 'left' ? me.right : me.left; - x1 += aliasPixel; - x2 += aliasPixel; - } - - context.beginPath(); - context.moveTo(x1, y1); - context.lineTo(x2, y2); - context.stroke(); - } - } - }); - }; - -},{}],33:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.scaleService = { - // Scale registration object. Extensions can register new scale types (such as log or DB scales) and then - // use the new chart options to grab the correct scale - constructors: {}, - // Use a registration function so that we can move to an ES6 map when we no longer need to support - // old browsers - - // Scale config defaults - defaults: {}, - registerScaleType: function(type, scaleConstructor, defaults) { - this.constructors[type] = scaleConstructor; - this.defaults[type] = helpers.clone(defaults); - }, - getScaleConstructor: function(type) { - return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined; - }, - getScaleDefaults: function(type) { - // Return the scale defaults merged with the global settings so that we always use the latest ones - return this.defaults.hasOwnProperty(type) ? helpers.scaleMerge(Chart.defaults.scale, this.defaults[type]) : {}; - }, - updateScaleDefaults: function(type, additions) { - var defaults = this.defaults; - if (defaults.hasOwnProperty(type)) { - defaults[type] = helpers.extend(defaults[type], additions); - } - }, - addScalesToLayout: function(chartInstance) { - // Adds each scale to the chart.boxes array to be sized accordingly - helpers.each(chartInstance.scales, function(scale) { - Chart.layoutService.addBox(chartInstance, scale); - }); - } - }; - }; - -},{}],34:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - /** - * Namespace to hold static tick generation functions - * @namespace Chart.Ticks - */ - Chart.Ticks = { - /** - * Namespace to hold generators for different types of ticks - * @namespace Chart.Ticks.generators - */ - generators: { - /** - * Interface for the options provided to the numeric tick generator - * @interface INumericTickGenerationOptions - */ - /** - * The maximum number of ticks to display - * @name INumericTickGenerationOptions#maxTicks - * @type Number - */ - /** - * The distance between each tick. - * @name INumericTickGenerationOptions#stepSize - * @type Number - * @optional - */ - /** - * Forced minimum for the ticks. If not specified, the minimum of the data range is used to calculate the tick minimum - * @name INumericTickGenerationOptions#min - * @type Number - * @optional - */ - /** - * The maximum value of the ticks. If not specified, the maximum of the data range is used to calculate the tick maximum - * @name INumericTickGenerationOptions#max - * @type Number - * @optional - */ - - /** - * Generate a set of linear ticks - * @method Chart.Ticks.generators.linear - * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks - * @param dataRange {IRange} the range of the data - * @returns {Array<Number>} array of tick values - */ - linear: function(generationOptions, dataRange) { - var ticks = []; - // To get a "nice" value for the tick spacing, we will use the appropriately named - // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks - // for details. - - var spacing; - if (generationOptions.stepSize && generationOptions.stepSize > 0) { - spacing = generationOptions.stepSize; - } else { - var niceRange = helpers.niceNum(dataRange.max - dataRange.min, false); - spacing = helpers.niceNum(niceRange / (generationOptions.maxTicks - 1), true); - } - var niceMin = Math.floor(dataRange.min / spacing) * spacing; - var niceMax = Math.ceil(dataRange.max / spacing) * spacing; - - // If min, max and stepSize is set and they make an evenly spaced scale use it. - if (generationOptions.min && generationOptions.max && generationOptions.stepSize) { - // If very close to our whole number, use it. - if (helpers.almostWhole((generationOptions.max - generationOptions.min) / generationOptions.stepSize, spacing / 1000)) { - niceMin = generationOptions.min; - niceMax = generationOptions.max; - } - } - - var numSpaces = (niceMax - niceMin) / spacing; - // If very close to our rounded value, use it. - if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) { - numSpaces = Math.round(numSpaces); - } else { - numSpaces = Math.ceil(numSpaces); - } - - // Put the values into the ticks array - ticks.push(generationOptions.min !== undefined ? generationOptions.min : niceMin); - for (var j = 1; j < numSpaces; ++j) { - ticks.push(niceMin + (j * spacing)); - } - ticks.push(generationOptions.max !== undefined ? generationOptions.max : niceMax); - - return ticks; - }, - - /** - * Generate a set of logarithmic ticks - * @method Chart.Ticks.generators.logarithmic - * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks - * @param dataRange {IRange} the range of the data - * @returns {Array<Number>} array of tick values - */ - logarithmic: function(generationOptions, dataRange) { - var ticks = []; - var getValueOrDefault = helpers.getValueOrDefault; - - // Figure out what the max number of ticks we can support it is based on the size of - // the axis area. For now, we say that the minimum tick spacing in pixels must be 50 - // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on - // the graph - var tickVal = getValueOrDefault(generationOptions.min, Math.pow(10, Math.floor(helpers.log10(dataRange.min)))); - - var endExp = Math.floor(helpers.log10(dataRange.max)); - var endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp)); - var exp; - var significand; - - if (tickVal === 0) { - exp = Math.floor(helpers.log10(dataRange.minNotZero)); - significand = Math.floor(dataRange.minNotZero / Math.pow(10, exp)); - - ticks.push(tickVal); - tickVal = significand * Math.pow(10, exp); - } else { - exp = Math.floor(helpers.log10(tickVal)); - significand = Math.floor(tickVal / Math.pow(10, exp)); - } - - do { - ticks.push(tickVal); - - ++significand; - if (significand === 10) { - significand = 1; - ++exp; - } - - tickVal = significand * Math.pow(10, exp); - } while (exp < endExp || (exp === endExp && significand < endSignificand)); - - var lastTick = getValueOrDefault(generationOptions.max, tickVal); - ticks.push(lastTick); - - return ticks; - } - }, - - /** - * Namespace to hold formatters for different types of ticks - * @namespace Chart.Ticks.formatters - */ - formatters: { - /** - * Formatter for value labels - * @method Chart.Ticks.formatters.values - * @param value the value to display - * @return {String|Array} the label to display - */ - values: function(value) { - return helpers.isArray(value) ? value : '' + value; - }, - - /** - * Formatter for linear numeric ticks - * @method Chart.Ticks.formatters.linear - * @param tickValue {Number} the value to be formatted - * @param index {Number} the position of the tickValue parameter in the ticks array - * @param ticks {Array<Number>} the list of ticks being converted - * @return {String} string representation of the tickValue parameter - */ - linear: function(tickValue, index, ticks) { - // If we have lots of ticks, don't use the ones - var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0]; - - // If we have a number like 2.5 as the delta, figure out how many decimal places we need - if (Math.abs(delta) > 1) { - if (tickValue !== Math.floor(tickValue)) { - // not an integer - delta = tickValue - Math.floor(tickValue); - } - } - - var logDelta = helpers.log10(Math.abs(delta)); - var tickString = ''; - - if (tickValue !== 0) { - var numDecimal = -1 * Math.floor(logDelta); - numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places - tickString = tickValue.toFixed(numDecimal); - } else { - tickString = '0'; // never show decimal places for 0 - } - - return tickString; - }, - - logarithmic: function(tickValue, index, ticks) { - var remain = tickValue / (Math.pow(10, Math.floor(helpers.log10(tickValue)))); - - if (tickValue === 0) { - return '0'; - } else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === ticks.length - 1) { - return tickValue.toExponential(); - } - return ''; - } - } - }; - }; - -},{}],35:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.global.title = { - display: false, - position: 'top', - fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes) - - fontStyle: 'bold', - padding: 10, - - // actual title - text: '' - }; - - var noop = helpers.noop; - Chart.Title = Chart.Element.extend({ - - initialize: function(config) { - var me = this; - helpers.extend(me, config); - - // Contains hit boxes for each dataset (in dataset order) - me.legendHitBoxes = []; - }, - - // These methods are ordered by lifecycle. Utilities then follow. - - beforeUpdate: noop, - update: function(maxWidth, maxHeight, margins) { - var me = this; - - // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) - me.beforeUpdate(); - - // Absorb the master measurements - me.maxWidth = maxWidth; - me.maxHeight = maxHeight; - me.margins = margins; - - // Dimensions - me.beforeSetDimensions(); - me.setDimensions(); - me.afterSetDimensions(); - // Labels - me.beforeBuildLabels(); - me.buildLabels(); - me.afterBuildLabels(); - - // Fit - me.beforeFit(); - me.fit(); - me.afterFit(); - // - me.afterUpdate(); - - return me.minSize; - - }, - afterUpdate: noop, - - // - - beforeSetDimensions: noop, - setDimensions: function() { - var me = this; - // Set the unconstrained dimension before label rotation - if (me.isHorizontal()) { - // Reset position before calculating rotation - me.width = me.maxWidth; - me.left = 0; - me.right = me.width; - } else { - me.height = me.maxHeight; - - // Reset position before calculating rotation - me.top = 0; - me.bottom = me.height; - } - - // Reset padding - me.paddingLeft = 0; - me.paddingTop = 0; - me.paddingRight = 0; - me.paddingBottom = 0; - - // Reset minSize - me.minSize = { - width: 0, - height: 0 - }; - }, - afterSetDimensions: noop, - - // - - beforeBuildLabels: noop, - buildLabels: noop, - afterBuildLabels: noop, - - // - - beforeFit: noop, - fit: function() { - var me = this, - valueOrDefault = helpers.getValueOrDefault, - opts = me.options, - globalDefaults = Chart.defaults.global, - display = opts.display, - fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize), - minSize = me.minSize; - - if (me.isHorizontal()) { - minSize.width = me.maxWidth; // fill all the width - minSize.height = display ? fontSize + (opts.padding * 2) : 0; - } else { - minSize.width = display ? fontSize + (opts.padding * 2) : 0; - minSize.height = me.maxHeight; // fill all the height - } - - me.width = minSize.width; - me.height = minSize.height; - - }, - afterFit: noop, - - // Shared Methods - isHorizontal: function() { - var pos = this.options.position; - return pos === 'top' || pos === 'bottom'; - }, - - // Actually draw the title block on the canvas - draw: function() { - var me = this, - ctx = me.ctx, - valueOrDefault = helpers.getValueOrDefault, - opts = me.options, - globalDefaults = Chart.defaults.global; - - if (opts.display) { - var fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize), - fontStyle = valueOrDefault(opts.fontStyle, globalDefaults.defaultFontStyle), - fontFamily = valueOrDefault(opts.fontFamily, globalDefaults.defaultFontFamily), - titleFont = helpers.fontString(fontSize, fontStyle, fontFamily), - rotation = 0, - titleX, - titleY, - top = me.top, - left = me.left, - bottom = me.bottom, - right = me.right, - maxWidth; - - ctx.fillStyle = valueOrDefault(opts.fontColor, globalDefaults.defaultFontColor); // render in correct colour - ctx.font = titleFont; - - // Horizontal - if (me.isHorizontal()) { - titleX = left + ((right - left) / 2); // midpoint of the width - titleY = top + ((bottom - top) / 2); // midpoint of the height - maxWidth = right - left; - } else { - titleX = opts.position === 'left' ? left + (fontSize / 2) : right - (fontSize / 2); - titleY = top + ((bottom - top) / 2); - maxWidth = bottom - top; - rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5); - } - - ctx.save(); - ctx.translate(titleX, titleY); - ctx.rotate(rotation); - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - ctx.fillText(opts.text, 0, 0, maxWidth); - ctx.restore(); - } - } - }); - - function createNewTitleBlockAndAttach(chartInstance, titleOpts) { - var title = new Chart.Title({ - ctx: chartInstance.chart.ctx, - options: titleOpts, - chart: chartInstance - }); - chartInstance.titleBlock = title; - Chart.layoutService.addBox(chartInstance, title); - } - - // Register the title plugin - Chart.plugins.register({ - beforeInit: function(chartInstance) { - var titleOpts = chartInstance.options.title; - - if (titleOpts) { - createNewTitleBlockAndAttach(chartInstance, titleOpts); - } - }, - beforeUpdate: function(chartInstance) { - var titleOpts = chartInstance.options.title; - - if (titleOpts) { - titleOpts = helpers.configMerge(Chart.defaults.global.title, titleOpts); - - if (chartInstance.titleBlock) { - chartInstance.titleBlock.options = titleOpts; - } else { - createNewTitleBlockAndAttach(chartInstance, titleOpts); - } - } else { - Chart.layoutService.removeBox(chartInstance, chartInstance.titleBlock); - delete chartInstance.titleBlock; - } - } - }); - }; - -},{}],36:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - /** - * Helper method to merge the opacity into a color - */ - function mergeOpacity(colorString, opacity) { - var color = helpers.color(colorString); - return color.alpha(opacity * color.alpha()).rgbaString(); - } - - Chart.defaults.global.tooltips = { - enabled: true, - custom: null, - mode: 'nearest', - position: 'average', - intersect: true, - backgroundColor: 'rgba(0,0,0,0.8)', - titleFontStyle: 'bold', - titleSpacing: 2, - titleMarginBottom: 6, - titleFontColor: '#fff', - titleAlign: 'left', - bodySpacing: 2, - bodyFontColor: '#fff', - bodyAlign: 'left', - footerFontStyle: 'bold', - footerSpacing: 2, - footerMarginTop: 6, - footerFontColor: '#fff', - footerAlign: 'left', - yPadding: 6, - xPadding: 6, - caretSize: 5, - cornerRadius: 6, - multiKeyBackground: '#fff', - displayColors: true, - callbacks: { - // Args are: (tooltipItems, data) - beforeTitle: helpers.noop, - title: function(tooltipItems, data) { - // Pick first xLabel for now - var title = ''; - var labels = data.labels; - var labelCount = labels ? labels.length : 0; - - if (tooltipItems.length > 0) { - var item = tooltipItems[0]; - - if (item.xLabel) { - title = item.xLabel; - } else if (labelCount > 0 && item.index < labelCount) { - title = labels[item.index]; - } - } - - return title; - }, - afterTitle: helpers.noop, - - // Args are: (tooltipItems, data) - beforeBody: helpers.noop, - - // Args are: (tooltipItem, data) - beforeLabel: helpers.noop, - label: function(tooltipItem, data) { - var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || ''; - return datasetLabel + ': ' + tooltipItem.yLabel; - }, - labelColor: function(tooltipItem, chartInstance) { - var meta = chartInstance.getDatasetMeta(tooltipItem.datasetIndex); - var activeElement = meta.data[tooltipItem.index]; - var view = activeElement._view; - return { - borderColor: view.borderColor, - backgroundColor: view.backgroundColor - }; - }, - afterLabel: helpers.noop, - - // Args are: (tooltipItems, data) - afterBody: helpers.noop, - - // Args are: (tooltipItems, data) - beforeFooter: helpers.noop, - footer: helpers.noop, - afterFooter: helpers.noop - } - }; - - // Helper to push or concat based on if the 2nd parameter is an array or not - function pushOrConcat(base, toPush) { - if (toPush) { - if (helpers.isArray(toPush)) { - // base = base.concat(toPush); - Array.prototype.push.apply(base, toPush); - } else { - base.push(toPush); - } - } - - return base; - } - - // Private helper to create a tooltip item model - // @param element : the chart element (point, arc, bar) to create the tooltip item for - // @return : new tooltip item - function createTooltipItem(element) { - var xScale = element._xScale; - var yScale = element._yScale || element._scale; // handle radar || polarArea charts - var index = element._index, - datasetIndex = element._datasetIndex; - - return { - xLabel: xScale ? xScale.getLabelForIndex(index, datasetIndex) : '', - yLabel: yScale ? yScale.getLabelForIndex(index, datasetIndex) : '', - index: index, - datasetIndex: datasetIndex, - x: element._model.x, - y: element._model.y - }; - } - - /** - * Helper to get the reset model for the tooltip - * @param tooltipOpts {Object} the tooltip options - */ - function getBaseModel(tooltipOpts) { - var globalDefaults = Chart.defaults.global; - var getValueOrDefault = helpers.getValueOrDefault; - - return { - // Positioning - xPadding: tooltipOpts.xPadding, - yPadding: tooltipOpts.yPadding, - xAlign: tooltipOpts.xAlign, - yAlign: tooltipOpts.yAlign, - - // Body - bodyFontColor: tooltipOpts.bodyFontColor, - _bodyFontFamily: getValueOrDefault(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily), - _bodyFontStyle: getValueOrDefault(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle), - _bodyAlign: tooltipOpts.bodyAlign, - bodyFontSize: getValueOrDefault(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize), - bodySpacing: tooltipOpts.bodySpacing, - - // Title - titleFontColor: tooltipOpts.titleFontColor, - _titleFontFamily: getValueOrDefault(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily), - _titleFontStyle: getValueOrDefault(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle), - titleFontSize: getValueOrDefault(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize), - _titleAlign: tooltipOpts.titleAlign, - titleSpacing: tooltipOpts.titleSpacing, - titleMarginBottom: tooltipOpts.titleMarginBottom, - - // Footer - footerFontColor: tooltipOpts.footerFontColor, - _footerFontFamily: getValueOrDefault(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily), - _footerFontStyle: getValueOrDefault(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle), - footerFontSize: getValueOrDefault(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize), - _footerAlign: tooltipOpts.footerAlign, - footerSpacing: tooltipOpts.footerSpacing, - footerMarginTop: tooltipOpts.footerMarginTop, - - // Appearance - caretSize: tooltipOpts.caretSize, - cornerRadius: tooltipOpts.cornerRadius, - backgroundColor: tooltipOpts.backgroundColor, - opacity: 0, - legendColorBackground: tooltipOpts.multiKeyBackground, - displayColors: tooltipOpts.displayColors - }; - } - - /** - * Get the size of the tooltip - */ - function getTooltipSize(tooltip, model) { - var ctx = tooltip._chart.ctx; - - var height = model.yPadding * 2; // Tooltip Padding - var width = 0; - - // Count of all lines in the body - var body = model.body; - var combinedBodyLength = body.reduce(function(count, bodyItem) { - return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length; - }, 0); - combinedBodyLength += model.beforeBody.length + model.afterBody.length; - - var titleLineCount = model.title.length; - var footerLineCount = model.footer.length; - var titleFontSize = model.titleFontSize, - bodyFontSize = model.bodyFontSize, - footerFontSize = model.footerFontSize; - - height += titleLineCount * titleFontSize; // Title Lines - height += titleLineCount ? (titleLineCount - 1) * model.titleSpacing : 0; // Title Line Spacing - height += titleLineCount ? model.titleMarginBottom : 0; // Title's bottom Margin - height += combinedBodyLength * bodyFontSize; // Body Lines - height += combinedBodyLength ? (combinedBodyLength - 1) * model.bodySpacing : 0; // Body Line Spacing - height += footerLineCount ? model.footerMarginTop : 0; // Footer Margin - height += footerLineCount * (footerFontSize); // Footer Lines - height += footerLineCount ? (footerLineCount - 1) * model.footerSpacing : 0; // Footer Line Spacing - - // Title width - var widthPadding = 0; - var maxLineWidth = function(line) { - width = Math.max(width, ctx.measureText(line).width + widthPadding); - }; - - ctx.font = helpers.fontString(titleFontSize, model._titleFontStyle, model._titleFontFamily); - helpers.each(model.title, maxLineWidth); - - // Body width - ctx.font = helpers.fontString(bodyFontSize, model._bodyFontStyle, model._bodyFontFamily); - helpers.each(model.beforeBody.concat(model.afterBody), maxLineWidth); - - // Body lines may include some extra width due to the color box - widthPadding = model.displayColors ? (bodyFontSize + 2) : 0; - helpers.each(body, function(bodyItem) { - helpers.each(bodyItem.before, maxLineWidth); - helpers.each(bodyItem.lines, maxLineWidth); - helpers.each(bodyItem.after, maxLineWidth); - }); - - // Reset back to 0 - widthPadding = 0; - - // Footer width - ctx.font = helpers.fontString(footerFontSize, model._footerFontStyle, model._footerFontFamily); - helpers.each(model.footer, maxLineWidth); - - // Add padding - width += 2 * model.xPadding; - - return { - width: width, - height: height - }; - } - - /** - * Helper to get the alignment of a tooltip given the size - */ - function determineAlignment(tooltip, size) { - var model = tooltip._model; - var chart = tooltip._chart; - var chartArea = tooltip._chartInstance.chartArea; - var xAlign = 'center'; - var yAlign = 'center'; - - if (model.y < size.height) { - yAlign = 'top'; - } else if (model.y > (chart.height - size.height)) { - yAlign = 'bottom'; - } - - var lf, rf; // functions to determine left, right alignment - var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart - var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges - var midX = (chartArea.left + chartArea.right) / 2; - var midY = (chartArea.top + chartArea.bottom) / 2; - - if (yAlign === 'center') { - lf = function(x) { - return x <= midX; - }; - rf = function(x) { - return x > midX; - }; - } else { - lf = function(x) { - return x <= (size.width / 2); - }; - rf = function(x) { - return x >= (chart.width - (size.width / 2)); - }; - } - - olf = function(x) { - return x + size.width > chart.width; - }; - orf = function(x) { - return x - size.width < 0; - }; - yf = function(y) { - return y <= midY ? 'top' : 'bottom'; - }; - - if (lf(model.x)) { - xAlign = 'left'; - - // Is tooltip too wide and goes over the right side of the chart.? - if (olf(model.x)) { - xAlign = 'center'; - yAlign = yf(model.y); - } - } else if (rf(model.x)) { - xAlign = 'right'; - - // Is tooltip too wide and goes outside left edge of canvas? - if (orf(model.x)) { - xAlign = 'center'; - yAlign = yf(model.y); - } - } - - var opts = tooltip._options; - return { - xAlign: opts.xAlign ? opts.xAlign : xAlign, - yAlign: opts.yAlign ? opts.yAlign : yAlign - }; - } - - /** - * @Helper to get the location a tooltip needs to be placed at given the initial position (via the vm) and the size and alignment - */ - function getBackgroundPoint(vm, size, alignment) { - // Background Position - var x = vm.x; - var y = vm.y; - - var caretSize = vm.caretSize, - caretPadding = vm.caretPadding, - cornerRadius = vm.cornerRadius, - xAlign = alignment.xAlign, - yAlign = alignment.yAlign, - paddingAndSize = caretSize + caretPadding, - radiusAndPadding = cornerRadius + caretPadding; - - if (xAlign === 'right') { - x -= size.width; - } else if (xAlign === 'center') { - x -= (size.width / 2); - } - - if (yAlign === 'top') { - y += paddingAndSize; - } else if (yAlign === 'bottom') { - y -= size.height + paddingAndSize; - } else { - y -= (size.height / 2); - } - - if (yAlign === 'center') { - if (xAlign === 'left') { - x += paddingAndSize; - } else if (xAlign === 'right') { - x -= paddingAndSize; - } - } else if (xAlign === 'left') { - x -= radiusAndPadding; - } else if (xAlign === 'right') { - x += radiusAndPadding; - } - - return { - x: x, - y: y - }; - } - - Chart.Tooltip = Chart.Element.extend({ - initialize: function() { - this._model = getBaseModel(this._options); - }, - - // Get the title - // Args are: (tooltipItem, data) - getTitle: function() { - var me = this; - var opts = me._options; - var callbacks = opts.callbacks; - - var beforeTitle = callbacks.beforeTitle.apply(me, arguments), - title = callbacks.title.apply(me, arguments), - afterTitle = callbacks.afterTitle.apply(me, arguments); - - var lines = []; - lines = pushOrConcat(lines, beforeTitle); - lines = pushOrConcat(lines, title); - lines = pushOrConcat(lines, afterTitle); - - return lines; - }, - - // Args are: (tooltipItem, data) - getBeforeBody: function() { - var lines = this._options.callbacks.beforeBody.apply(this, arguments); - return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : []; - }, - - // Args are: (tooltipItem, data) - getBody: function(tooltipItems, data) { - var me = this; - var callbacks = me._options.callbacks; - var bodyItems = []; - - helpers.each(tooltipItems, function(tooltipItem) { - var bodyItem = { - before: [], - lines: [], - after: [] - }; - pushOrConcat(bodyItem.before, callbacks.beforeLabel.call(me, tooltipItem, data)); - pushOrConcat(bodyItem.lines, callbacks.label.call(me, tooltipItem, data)); - pushOrConcat(bodyItem.after, callbacks.afterLabel.call(me, tooltipItem, data)); - - bodyItems.push(bodyItem); - }); - - return bodyItems; - }, - - // Args are: (tooltipItem, data) - getAfterBody: function() { - var lines = this._options.callbacks.afterBody.apply(this, arguments); - return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : []; - }, - - // Get the footer and beforeFooter and afterFooter lines - // Args are: (tooltipItem, data) - getFooter: function() { - var me = this; - var callbacks = me._options.callbacks; - - var beforeFooter = callbacks.beforeFooter.apply(me, arguments); - var footer = callbacks.footer.apply(me, arguments); - var afterFooter = callbacks.afterFooter.apply(me, arguments); - - var lines = []; - lines = pushOrConcat(lines, beforeFooter); - lines = pushOrConcat(lines, footer); - lines = pushOrConcat(lines, afterFooter); - - return lines; - }, - - update: function(changed) { - var me = this; - var opts = me._options; - - // Need to regenerate the model because its faster than using extend and it is necessary due to the optimization in Chart.Element.transition - // that does _view = _model if ease === 1. This causes the 2nd tooltip update to set properties in both the view and model at the same time - // which breaks any animations. - var existingModel = me._model; - var model = me._model = getBaseModel(opts); - var active = me._active; - - var data = me._data; - var chartInstance = me._chartInstance; - - // In the case where active.length === 0 we need to keep these at existing values for good animations - var alignment = { - xAlign: existingModel.xAlign, - yAlign: existingModel.yAlign - }; - var backgroundPoint = { - x: existingModel.x, - y: existingModel.y - }; - var tooltipSize = { - width: existingModel.width, - height: existingModel.height - }; - var tooltipPosition = { - x: existingModel.caretX, - y: existingModel.caretY - }; - - var i, len; - - if (active.length) { - model.opacity = 1; - - var labelColors = []; - tooltipPosition = Chart.Tooltip.positioners[opts.position](active, me._eventPosition); - - var tooltipItems = []; - for (i = 0, len = active.length; i < len; ++i) { - tooltipItems.push(createTooltipItem(active[i])); - } - - // If the user provided a filter function, use it to modify the tooltip items - if (opts.filter) { - tooltipItems = tooltipItems.filter(function(a) { - return opts.filter(a, data); - }); - } - - // If the user provided a sorting function, use it to modify the tooltip items - if (opts.itemSort) { - tooltipItems = tooltipItems.sort(function(a, b) { - return opts.itemSort(a, b, data); - }); - } - - // Determine colors for boxes - helpers.each(tooltipItems, function(tooltipItem) { - labelColors.push(opts.callbacks.labelColor.call(me, tooltipItem, chartInstance)); - }); - - // Build the Text Lines - model.title = me.getTitle(tooltipItems, data); - model.beforeBody = me.getBeforeBody(tooltipItems, data); - model.body = me.getBody(tooltipItems, data); - model.afterBody = me.getAfterBody(tooltipItems, data); - model.footer = me.getFooter(tooltipItems, data); - - // Initial positioning and colors - model.x = Math.round(tooltipPosition.x); - model.y = Math.round(tooltipPosition.y); - model.caretPadding = helpers.getValueOrDefault(tooltipPosition.padding, 2); - model.labelColors = labelColors; - - // data points - model.dataPoints = tooltipItems; - - // We need to determine alignment of the tooltip - tooltipSize = getTooltipSize(this, model); - alignment = determineAlignment(this, tooltipSize); - // Final Size and Position - backgroundPoint = getBackgroundPoint(model, tooltipSize, alignment); - } else { - model.opacity = 0; - } - - model.xAlign = alignment.xAlign; - model.yAlign = alignment.yAlign; - model.x = backgroundPoint.x; - model.y = backgroundPoint.y; - model.width = tooltipSize.width; - model.height = tooltipSize.height; - - // Point where the caret on the tooltip points to - model.caretX = tooltipPosition.x; - model.caretY = tooltipPosition.y; - - me._model = model; - - if (changed && opts.custom) { - opts.custom.call(me, model); - } - - return me; - }, - drawCaret: function(tooltipPoint, size, opacity) { - var vm = this._view; - var ctx = this._chart.ctx; - var x1, x2, x3; - var y1, y2, y3; - var caretSize = vm.caretSize; - var cornerRadius = vm.cornerRadius; - var xAlign = vm.xAlign, - yAlign = vm.yAlign; - var ptX = tooltipPoint.x, - ptY = tooltipPoint.y; - var width = size.width, - height = size.height; - - if (yAlign === 'center') { - // Left or right side - if (xAlign === 'left') { - x1 = ptX; - x2 = x1 - caretSize; - x3 = x1; - } else { - x1 = ptX + width; - x2 = x1 + caretSize; - x3 = x1; - } - - y2 = ptY + (height / 2); - y1 = y2 - caretSize; - y3 = y2 + caretSize; - } else { - if (xAlign === 'left') { - x1 = ptX + cornerRadius; - x2 = x1 + caretSize; - x3 = x2 + caretSize; - } else if (xAlign === 'right') { - x1 = ptX + width - cornerRadius; - x2 = x1 - caretSize; - x3 = x2 - caretSize; - } else { - x2 = ptX + (width / 2); - x1 = x2 - caretSize; - x3 = x2 + caretSize; - } - - if (yAlign === 'top') { - y1 = ptY; - y2 = y1 - caretSize; - y3 = y1; - } else { - y1 = ptY + height; - y2 = y1 + caretSize; - y3 = y1; - } - } - - ctx.fillStyle = mergeOpacity(vm.backgroundColor, opacity); - ctx.beginPath(); - ctx.moveTo(x1, y1); - ctx.lineTo(x2, y2); - ctx.lineTo(x3, y3); - ctx.closePath(); - ctx.fill(); - }, - drawTitle: function(pt, vm, ctx, opacity) { - var title = vm.title; - - if (title.length) { - ctx.textAlign = vm._titleAlign; - ctx.textBaseline = 'top'; - - var titleFontSize = vm.titleFontSize, - titleSpacing = vm.titleSpacing; - - ctx.fillStyle = mergeOpacity(vm.titleFontColor, opacity); - ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily); - - var i, len; - for (i = 0, len = title.length; i < len; ++i) { - ctx.fillText(title[i], pt.x, pt.y); - pt.y += titleFontSize + titleSpacing; // Line Height and spacing - - if (i + 1 === title.length) { - pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing - } - } - } - }, - drawBody: function(pt, vm, ctx, opacity) { - var bodyFontSize = vm.bodyFontSize; - var bodySpacing = vm.bodySpacing; - var body = vm.body; - - ctx.textAlign = vm._bodyAlign; - ctx.textBaseline = 'top'; - - var textColor = mergeOpacity(vm.bodyFontColor, opacity); - ctx.fillStyle = textColor; - ctx.font = helpers.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily); - - // Before Body - var xLinePadding = 0; - var fillLineOfText = function(line) { - ctx.fillText(line, pt.x + xLinePadding, pt.y); - pt.y += bodyFontSize + bodySpacing; - }; - - // Before body lines - helpers.each(vm.beforeBody, fillLineOfText); - - var drawColorBoxes = vm.displayColors; - xLinePadding = drawColorBoxes ? (bodyFontSize + 2) : 0; - - // Draw body lines now - helpers.each(body, function(bodyItem, i) { - helpers.each(bodyItem.before, fillLineOfText); - - helpers.each(bodyItem.lines, function(line) { - // Draw Legend-like boxes if needed - if (drawColorBoxes) { - // Fill a white rect so that colours merge nicely if the opacity is < 1 - ctx.fillStyle = mergeOpacity(vm.legendColorBackground, opacity); - ctx.fillRect(pt.x, pt.y, bodyFontSize, bodyFontSize); - - // Border - ctx.strokeStyle = mergeOpacity(vm.labelColors[i].borderColor, opacity); - ctx.strokeRect(pt.x, pt.y, bodyFontSize, bodyFontSize); - - // Inner square - ctx.fillStyle = mergeOpacity(vm.labelColors[i].backgroundColor, opacity); - ctx.fillRect(pt.x + 1, pt.y + 1, bodyFontSize - 2, bodyFontSize - 2); - - ctx.fillStyle = textColor; - } - - fillLineOfText(line); - }); - - helpers.each(bodyItem.after, fillLineOfText); - }); - - // Reset back to 0 for after body - xLinePadding = 0; - - // After body lines - helpers.each(vm.afterBody, fillLineOfText); - pt.y -= bodySpacing; // Remove last body spacing - }, - drawFooter: function(pt, vm, ctx, opacity) { - var footer = vm.footer; - - if (footer.length) { - pt.y += vm.footerMarginTop; - - ctx.textAlign = vm._footerAlign; - ctx.textBaseline = 'top'; - - ctx.fillStyle = mergeOpacity(vm.footerFontColor, opacity); - ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily); - - helpers.each(footer, function(line) { - ctx.fillText(line, pt.x, pt.y); - pt.y += vm.footerFontSize + vm.footerSpacing; - }); - } - }, - drawBackground: function(pt, vm, ctx, tooltipSize, opacity) { - ctx.fillStyle = mergeOpacity(vm.backgroundColor, opacity); - helpers.drawRoundedRectangle(ctx, pt.x, pt.y, tooltipSize.width, tooltipSize.height, vm.cornerRadius); - ctx.fill(); - }, - draw: function() { - var ctx = this._chart.ctx; - var vm = this._view; - - if (vm.opacity === 0) { - return; - } - - var tooltipSize = { - width: vm.width, - height: vm.height - }; - var pt = { - x: vm.x, - y: vm.y - }; - - // IE11/Edge does not like very small opacities, so snap to 0 - var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity; - - if (this._options.enabled) { - // Draw Background - this.drawBackground(pt, vm, ctx, tooltipSize, opacity); - - // Draw Caret - this.drawCaret(pt, tooltipSize, opacity); - - // Draw Title, Body, and Footer - pt.x += vm.xPadding; - pt.y += vm.yPadding; - - // Titles - this.drawTitle(pt, vm, ctx, opacity); - - // Body - this.drawBody(pt, vm, ctx, opacity); - - // Footer - this.drawFooter(pt, vm, ctx, opacity); - } - }, - - /** - * Handle an event - * @private - * @param {IEvent} event - The event to handle - * @returns {Boolean} true if the tooltip changed - */ - handleEvent: function(e) { - var me = this; - var options = me._options; - var changed = false; - - me._lastActive = me._lastActive || []; - - // Find Active Elements for tooltips - if (e.type === 'mouseout') { - me._active = []; - } else { - me._active = me._chartInstance.getElementsAtEventForMode(e, options.mode, options); - } - - // Remember Last Actives - changed = !helpers.arrayEquals(me._active, me._lastActive); - me._lastActive = me._active; - - if (options.enabled || options.custom) { - me._eventPosition = { - x: e.x, - y: e.y - }; - - var model = me._model; - me.update(true); - me.pivot(); - - // See if our tooltip position changed - changed |= (model.x !== me._model.x) || (model.y !== me._model.y); - } - - return changed; - } - }); - - /** - * @namespace Chart.Tooltip.positioners - */ - Chart.Tooltip.positioners = { - /** - * Average mode places the tooltip at the average position of the elements shown - * @function Chart.Tooltip.positioners.average - * @param elements {ChartElement[]} the elements being displayed in the tooltip - * @returns {Point} tooltip position - */ - average: function(elements) { - if (!elements.length) { - return false; - } - - var i, len; - var x = 0; - var y = 0; - var count = 0; - - for (i = 0, len = elements.length; i < len; ++i) { - var el = elements[i]; - if (el && el.hasValue()) { - var pos = el.tooltipPosition(); - x += pos.x; - y += pos.y; - ++count; - } - } - - return { - x: Math.round(x / count), - y: Math.round(y / count) - }; - }, - - /** - * Gets the tooltip position nearest of the item nearest to the event position - * @function Chart.Tooltip.positioners.nearest - * @param elements {Chart.Element[]} the tooltip elements - * @param eventPosition {Point} the position of the event in canvas coordinates - * @returns {Point} the tooltip position - */ - nearest: function(elements, eventPosition) { - var x = eventPosition.x; - var y = eventPosition.y; - - var nearestElement; - var minDistance = Number.POSITIVE_INFINITY; - var i, len; - for (i = 0, len = elements.length; i < len; ++i) { - var el = elements[i]; - if (el && el.hasValue()) { - var center = el.getCenterPoint(); - var d = helpers.distanceBetweenPoints(eventPosition, center); - - if (d < minDistance) { - minDistance = d; - nearestElement = el; - } - } - } - - if (nearestElement) { - var tp = nearestElement.tooltipPosition(); - x = tp.x; - y = tp.y; - } - - return { - x: x, - y: y - }; - } - }; - }; - -},{}],37:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers, - globalOpts = Chart.defaults.global; - - globalOpts.elements.arc = { - backgroundColor: globalOpts.defaultColor, - borderColor: '#fff', - borderWidth: 2 - }; - - Chart.elements.Arc = Chart.Element.extend({ - inLabelRange: function(mouseX) { - var vm = this._view; - - if (vm) { - return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2)); - } - return false; - }, - inRange: function(chartX, chartY) { - var vm = this._view; - - if (vm) { - var pointRelativePosition = helpers.getAngleFromPoint(vm, { - x: chartX, - y: chartY - }), - angle = pointRelativePosition.angle, - distance = pointRelativePosition.distance; - - // Sanitise angle range - var startAngle = vm.startAngle; - var endAngle = vm.endAngle; - while (endAngle < startAngle) { - endAngle += 2.0 * Math.PI; - } - while (angle > endAngle) { - angle -= 2.0 * Math.PI; - } - while (angle < startAngle) { - angle += 2.0 * Math.PI; - } - - // Check if within the range of the open/close angle - var betweenAngles = (angle >= startAngle && angle <= endAngle), - withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius); - - return (betweenAngles && withinRadius); - } - return false; - }, - getCenterPoint: function() { - var vm = this._view; - var halfAngle = (vm.startAngle + vm.endAngle) / 2; - var halfRadius = (vm.innerRadius + vm.outerRadius) / 2; - return { - x: vm.x + Math.cos(halfAngle) * halfRadius, - y: vm.y + Math.sin(halfAngle) * halfRadius - }; - }, - getArea: function() { - var vm = this._view; - return Math.PI * ((vm.endAngle - vm.startAngle) / (2 * Math.PI)) * (Math.pow(vm.outerRadius, 2) - Math.pow(vm.innerRadius, 2)); - }, - tooltipPosition: function() { - var vm = this._view; - - var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2), - rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius; - return { - x: vm.x + (Math.cos(centreAngle) * rangeFromCentre), - y: vm.y + (Math.sin(centreAngle) * rangeFromCentre) - }; - }, - draw: function() { - - var ctx = this._chart.ctx, - vm = this._view, - sA = vm.startAngle, - eA = vm.endAngle; - - ctx.beginPath(); - - ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA); - ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true); - - ctx.closePath(); - ctx.strokeStyle = vm.borderColor; - ctx.lineWidth = vm.borderWidth; - - ctx.fillStyle = vm.backgroundColor; - - ctx.fill(); - ctx.lineJoin = 'bevel'; - - if (vm.borderWidth) { - ctx.stroke(); - } - } - }); - }; - -},{}],38:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - var globalDefaults = Chart.defaults.global; - - Chart.defaults.global.elements.line = { - tension: 0.4, - backgroundColor: globalDefaults.defaultColor, - borderWidth: 3, - borderColor: globalDefaults.defaultColor, - borderCapStyle: 'butt', - borderDash: [], - borderDashOffset: 0.0, - borderJoinStyle: 'miter', - capBezierPoints: true, - fill: true, // do we fill in the area between the line and its base axis - }; - - Chart.elements.Line = Chart.Element.extend({ - draw: function() { - var me = this; - var vm = me._view; - var spanGaps = vm.spanGaps; - var fillPoint = vm.scaleZero; - var loop = me._loop; - - // Handle different fill modes for cartesian lines - if (!loop) { - if (vm.fill === 'top') { - fillPoint = vm.scaleTop; - } else if (vm.fill === 'bottom') { - fillPoint = vm.scaleBottom; - } - } - - var ctx = me._chart.ctx; - ctx.save(); - - // Helper function to draw a line to a point - function lineToPoint(previousPoint, point) { - var pointVM = point._view; - if (point._view.steppedLine === true) { - ctx.lineTo(pointVM.x, previousPoint._view.y); - ctx.lineTo(pointVM.x, pointVM.y); - } else if (point._view.tension === 0) { - ctx.lineTo(pointVM.x, pointVM.y); - } else { - ctx.bezierCurveTo( - previousPoint._view.controlPointNextX, - previousPoint._view.controlPointNextY, - pointVM.controlPointPreviousX, - pointVM.controlPointPreviousY, - pointVM.x, - pointVM.y - ); - } - } - - var points = me._children.slice(); // clone array - var lastDrawnIndex = -1; - - // If we are looping, adding the first point again - if (loop && points.length) { - points.push(points[0]); - } - - var index, current, previous, currentVM; - - // Fill Line - if (points.length && vm.fill) { - ctx.beginPath(); - - for (index = 0; index < points.length; ++index) { - current = points[index]; - previous = helpers.previousItem(points, index); - currentVM = current._view; - - // First point moves to it's starting position no matter what - if (index === 0) { - if (loop) { - ctx.moveTo(fillPoint.x, fillPoint.y); - } else { - ctx.moveTo(currentVM.x, fillPoint); - } - - if (!currentVM.skip) { - lastDrawnIndex = index; - ctx.lineTo(currentVM.x, currentVM.y); - } - } else { - previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex]; - - if (currentVM.skip) { - // Only do this if this is the first point that is skipped - if (!spanGaps && lastDrawnIndex === (index - 1)) { - if (loop) { - ctx.lineTo(fillPoint.x, fillPoint.y); - } else { - ctx.lineTo(previous._view.x, fillPoint); - } - } - } else { - if (lastDrawnIndex !== (index - 1)) { - // There was a gap and this is the first point after the gap. If we've never drawn a point, this is a special case. - // If the first data point is NaN, then there is no real gap to skip - if (spanGaps && lastDrawnIndex !== -1) { - // We are spanning the gap, so simple draw a line to this point - lineToPoint(previous, current); - } else if (loop) { - ctx.lineTo(currentVM.x, currentVM.y); - } else { - ctx.lineTo(currentVM.x, fillPoint); - ctx.lineTo(currentVM.x, currentVM.y); - } - } else { - // Line to next point - lineToPoint(previous, current); - } - lastDrawnIndex = index; - } - } - } - - if (!loop && lastDrawnIndex !== -1) { - ctx.lineTo(points[lastDrawnIndex]._view.x, fillPoint); - } - - ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor; - ctx.closePath(); - ctx.fill(); - } - - // Stroke Line Options - var globalOptionLineElements = globalDefaults.elements.line; - ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle; - - // IE 9 and 10 do not support line dash - if (ctx.setLineDash) { - ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash); - } - - ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset; - ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle; - ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth; - ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor; - - // Stroke Line - ctx.beginPath(); - lastDrawnIndex = -1; - - for (index = 0; index < points.length; ++index) { - current = points[index]; - previous = helpers.previousItem(points, index); - currentVM = current._view; - - // First point moves to it's starting position no matter what - if (index === 0) { - if (!currentVM.skip) { - ctx.moveTo(currentVM.x, currentVM.y); - lastDrawnIndex = index; - } - } else { - previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex]; - - if (!currentVM.skip) { - if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) { - // There was a gap and this is the first point after the gap - ctx.moveTo(currentVM.x, currentVM.y); - } else { - // Line to next point - lineToPoint(previous, current); - } - lastDrawnIndex = index; - } - } - } - - ctx.stroke(); - ctx.restore(); - } - }); - }; - -},{}],39:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers, - globalOpts = Chart.defaults.global, - defaultColor = globalOpts.defaultColor; - - globalOpts.elements.point = { - radius: 3, - pointStyle: 'circle', - backgroundColor: defaultColor, - borderWidth: 1, - borderColor: defaultColor, - // Hover - hitRadius: 1, - hoverRadius: 4, - hoverBorderWidth: 1 - }; - - function xRange(mouseX) { - var vm = this._view; - return vm ? (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false; - } - - function yRange(mouseY) { - var vm = this._view; - return vm ? (Math.pow(mouseY - vm.y, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false; - } - - Chart.elements.Point = Chart.Element.extend({ - inRange: function(mouseX, mouseY) { - var vm = this._view; - return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false; - }, - - inLabelRange: xRange, - inXRange: xRange, - inYRange: yRange, - - getCenterPoint: function() { - var vm = this._view; - return { - x: vm.x, - y: vm.y - }; - }, - getArea: function() { - return Math.PI * Math.pow(this._view.radius, 2); - }, - tooltipPosition: function() { - var vm = this._view; - return { - x: vm.x, - y: vm.y, - padding: vm.radius + vm.borderWidth - }; - }, - draw: function(chartArea) { - var vm = this._view; - var model = this._model; - var ctx = this._chart.ctx; - var pointStyle = vm.pointStyle; - var radius = vm.radius; - var x = vm.x; - var y = vm.y; - var color = Chart.helpers.color; - var errMargin = 1.01; // 1.01 is margin for Accumulated error. (Especially Edge, IE.) - var ratio = 0; - - if (vm.skip) { - return; - } - - ctx.strokeStyle = vm.borderColor || defaultColor; - ctx.lineWidth = helpers.getValueOrDefault(vm.borderWidth, globalOpts.elements.point.borderWidth); - ctx.fillStyle = vm.backgroundColor || defaultColor; - - // Cliping for Points. - // going out from inner charArea? - if ((chartArea !== undefined) && ((model.x < chartArea.left) || (chartArea.right*errMargin < model.x) || (model.y < chartArea.top) || (chartArea.bottom*errMargin < model.y))) { - // Point fade out - if (model.x < chartArea.left) { - ratio = (x - model.x) / (chartArea.left - model.x); - } else if (chartArea.right*errMargin < model.x) { - ratio = (model.x - x) / (model.x - chartArea.right); - } else if (model.y < chartArea.top) { - ratio = (y - model.y) / (chartArea.top - model.y); - } else if (chartArea.bottom*errMargin < model.y) { - ratio = (model.y - y) / (model.y - chartArea.bottom); - } - ratio = Math.round(ratio*100) / 100; - ctx.strokeStyle = color(ctx.strokeStyle).alpha(ratio).rgbString(); - ctx.fillStyle = color(ctx.fillStyle).alpha(ratio).rgbString(); - } - - Chart.canvasHelpers.drawPoint(ctx, pointStyle, radius, x, y); - } - }); - }; - -},{}],40:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var globalOpts = Chart.defaults.global; - - globalOpts.elements.rectangle = { - backgroundColor: globalOpts.defaultColor, - borderWidth: 0, - borderColor: globalOpts.defaultColor, - borderSkipped: 'bottom' - }; - - function isVertical(bar) { - return bar._view.width !== undefined; - } - - /** - * Helper function to get the bounds of the bar regardless of the orientation - * @private - * @param bar {Chart.Element.Rectangle} the bar - * @return {Bounds} bounds of the bar - */ - function getBarBounds(bar) { - var vm = bar._view; - var x1, x2, y1, y2; - - if (isVertical(bar)) { - // vertical - var halfWidth = vm.width / 2; - x1 = vm.x - halfWidth; - x2 = vm.x + halfWidth; - y1 = Math.min(vm.y, vm.base); - y2 = Math.max(vm.y, vm.base); - } else { - // horizontal bar - var halfHeight = vm.height / 2; - x1 = Math.min(vm.x, vm.base); - x2 = Math.max(vm.x, vm.base); - y1 = vm.y - halfHeight; - y2 = vm.y + halfHeight; - } - - return { - left: x1, - top: y1, - right: x2, - bottom: y2 - }; - } - - Chart.elements.Rectangle = Chart.Element.extend({ - draw: function() { - var ctx = this._chart.ctx; - var vm = this._view; - var left, right, top, bottom, signX, signY, borderSkipped; - var borderWidth = vm.borderWidth; - - if (!vm.horizontal) { - // bar - left = vm.x - vm.width / 2; - right = vm.x + vm.width / 2; - top = vm.y; - bottom = vm.base; - signX = 1; - signY = bottom > top? 1: -1; - borderSkipped = vm.borderSkipped || 'bottom'; - } else { - // horizontal bar - left = vm.base; - right = vm.x; - top = vm.y - vm.height / 2; - bottom = vm.y + vm.height / 2; - signX = right > left? 1: -1; - signY = 1; - borderSkipped = vm.borderSkipped || 'left'; - } - - // Canvas doesn't allow us to stroke inside the width so we can - // adjust the sizes to fit if we're setting a stroke on the line - if (borderWidth) { - // borderWidth shold be less than bar width and bar height. - var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom)); - borderWidth = borderWidth > barSize? barSize: borderWidth; - var halfStroke = borderWidth / 2; - // Adjust borderWidth when bar top position is near vm.base(zero). - var borderLeft = left + (borderSkipped !== 'left'? halfStroke * signX: 0); - var borderRight = right + (borderSkipped !== 'right'? -halfStroke * signX: 0); - var borderTop = top + (borderSkipped !== 'top'? halfStroke * signY: 0); - var borderBottom = bottom + (borderSkipped !== 'bottom'? -halfStroke * signY: 0); - // not become a vertical line? - if (borderLeft !== borderRight) { - top = borderTop; - bottom = borderBottom; - } - // not become a horizontal line? - if (borderTop !== borderBottom) { - left = borderLeft; - right = borderRight; - } - } - - ctx.beginPath(); - ctx.fillStyle = vm.backgroundColor; - ctx.strokeStyle = vm.borderColor; - ctx.lineWidth = borderWidth; - - // Corner points, from bottom-left to bottom-right clockwise - // | 1 2 | - // | 0 3 | - var corners = [ - [left, bottom], - [left, top], - [right, top], - [right, bottom] - ]; - - // Find first (starting) corner with fallback to 'bottom' - var borders = ['bottom', 'left', 'top', 'right']; - var startCorner = borders.indexOf(borderSkipped, 0); - if (startCorner === -1) { - startCorner = 0; - } - - function cornerAt(index) { - return corners[(startCorner + index) % 4]; - } - - // Draw rectangle from 'startCorner' - var corner = cornerAt(0); - ctx.moveTo(corner[0], corner[1]); - - for (var i = 1; i < 4; i++) { - corner = cornerAt(i); - ctx.lineTo(corner[0], corner[1]); - } - - ctx.fill(); - if (borderWidth) { - ctx.stroke(); - } - }, - height: function() { - var vm = this._view; - return vm.base - vm.y; - }, - inRange: function(mouseX, mouseY) { - var inRange = false; - - if (this._view) { - var bounds = getBarBounds(this); - inRange = mouseX >= bounds.left && mouseX <= bounds.right && mouseY >= bounds.top && mouseY <= bounds.bottom; - } - - return inRange; - }, - inLabelRange: function(mouseX, mouseY) { - var me = this; - if (!me._view) { - return false; - } - - var inRange = false; - var bounds = getBarBounds(me); - - if (isVertical(me)) { - inRange = mouseX >= bounds.left && mouseX <= bounds.right; - } else { - inRange = mouseY >= bounds.top && mouseY <= bounds.bottom; - } - - return inRange; - }, - inXRange: function(mouseX) { - var bounds = getBarBounds(this); - return mouseX >= bounds.left && mouseX <= bounds.right; - }, - inYRange: function(mouseY) { - var bounds = getBarBounds(this); - return mouseY >= bounds.top && mouseY <= bounds.bottom; - }, - getCenterPoint: function() { - var vm = this._view; - var x, y; - if (isVertical(this)) { - x = vm.x; - y = (vm.y + vm.base) / 2; - } else { - x = (vm.x + vm.base) / 2; - y = vm.y; - } - - return {x: x, y: y}; - }, - getArea: function() { - var vm = this._view; - return vm.width * Math.abs(vm.y - vm.base); - }, - tooltipPosition: function() { - var vm = this._view; - return { - x: vm.x, - y: vm.y - }; - } - }); - - }; - -},{}],41:[function(require,module,exports){ - 'use strict'; - -// Chart.Platform implementation for targeting a web browser - module.exports = function(Chart) { - var helpers = Chart.helpers; - - // DOM event types -> Chart.js event types. - // Note: only events with different types are mapped. - // https://developer.mozilla.org/en-US/docs/Web/Events - var eventTypeMap = { - // Touch events - touchstart: 'mousedown', - touchmove: 'mousemove', - touchend: 'mouseup', - - // Pointer events - pointerenter: 'mouseenter', - pointerdown: 'mousedown', - pointermove: 'mousemove', - pointerup: 'mouseup', - pointerleave: 'mouseout', - pointerout: 'mouseout' - }; - - /** - * The "used" size is the final value of a dimension property after all calculations have - * been performed. This method uses the computed style of `element` but returns undefined - * if the computed style is not expressed in pixels. That can happen in some cases where - * `element` has a size relative to its parent and this last one is not yet displayed, - * for example because of `display: none` on a parent node. - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value - * @returns {Number} Size in pixels or undefined if unknown. - */ - function readUsedSize(element, property) { - var value = helpers.getStyle(element, property); - var matches = value && value.match(/(\d+)px/); - return matches? Number(matches[1]) : undefined; - } - - /** - * Initializes the canvas style and render size without modifying the canvas display size, - * since responsiveness is handled by the controller.resize() method. The config is used - * to determine the aspect ratio to apply in case no explicit height has been specified. - */ - function initCanvas(canvas, config) { - var style = canvas.style; - - // NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it - // returns null or '' if no explicit value has been set to the canvas attribute. - var renderHeight = canvas.getAttribute('height'); - var renderWidth = canvas.getAttribute('width'); - - // Chart.js modifies some canvas values that we want to restore on destroy - canvas._chartjs = { - initial: { - height: renderHeight, - width: renderWidth, - style: { - display: style.display, - height: style.height, - width: style.width - } - } - }; - - // Force canvas to display as block to avoid extra space caused by inline - // elements, which would interfere with the responsive resize process. - // https://github.com/chartjs/Chart.js/issues/2538 - style.display = style.display || 'block'; - - if (renderWidth === null || renderWidth === '') { - var displayWidth = readUsedSize(canvas, 'width'); - if (displayWidth !== undefined) { - canvas.width = displayWidth; - } - } - - if (renderHeight === null || renderHeight === '') { - if (canvas.style.height === '') { - // If no explicit render height and style height, let's apply the aspect ratio, - // which one can be specified by the user but also by charts as default option - // (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2. - canvas.height = canvas.width / (config.options.aspectRatio || 2); - } else { - var displayHeight = readUsedSize(canvas, 'height'); - if (displayWidth !== undefined) { - canvas.height = displayHeight; - } - } - } - - return canvas; - } - - function createEvent(type, chart, x, y, native) { - return { - type: type, - chart: chart, - native: native || null, - x: x !== undefined? x : null, - y: y !== undefined? y : null, - }; - } - - function fromNativeEvent(event, chart) { - var type = eventTypeMap[event.type] || event.type; - var pos = helpers.getRelativePosition(event, chart); - return createEvent(type, chart, pos.x, pos.y, event); - } - - function createResizer(handler) { - var iframe = document.createElement('iframe'); - iframe.className = 'chartjs-hidden-iframe'; - iframe.style.cssText = - 'display:block;'+ - 'overflow:hidden;'+ - 'border:0;'+ - 'margin:0;'+ - 'top:0;'+ - 'left:0;'+ - 'bottom:0;'+ - 'right:0;'+ - 'height:100%;'+ - 'width:100%;'+ - 'position:absolute;'+ - 'pointer-events:none;'+ - 'z-index:-1;'; - - // Prevent the iframe to gain focus on tab. - // https://github.com/chartjs/Chart.js/issues/3090 - iframe.tabIndex = -1; - - // If the iframe is re-attached to the DOM, the resize listener is removed because the - // content is reloaded, so make sure to install the handler after the iframe is loaded. - // https://github.com/chartjs/Chart.js/issues/3521 - helpers.addEvent(iframe, 'load', function() { - helpers.addEvent(iframe.contentWindow || iframe, 'resize', handler); - - // The iframe size might have changed while loading, which can also - // happen if the size has been changed while detached from the DOM. - handler(); - }); - - return iframe; - } - - function addResizeListener(node, listener, chart) { - var stub = node._chartjs = { - ticking: false - }; - - // Throttle the callback notification until the next animation frame. - var notify = function() { - if (!stub.ticking) { - stub.ticking = true; - helpers.requestAnimFrame.call(window, function() { - if (stub.resizer) { - stub.ticking = false; - return listener(createEvent('resize', chart)); - } - }); - } - }; - - // Let's keep track of this added iframe and thus avoid DOM query when removing it. - stub.resizer = createResizer(notify); - - node.insertBefore(stub.resizer, node.firstChild); - } - - function removeResizeListener(node) { - if (!node || !node._chartjs) { - return; - } - - var resizer = node._chartjs.resizer; - if (resizer) { - resizer.parentNode.removeChild(resizer); - node._chartjs.resizer = null; - } - - delete node._chartjs; - } - - return { - acquireContext: function(item, config) { - if (typeof item === 'string') { - item = document.getElementById(item); - } else if (item.length) { - // Support for array based queries (such as jQuery) - item = item[0]; - } - - if (item && item.canvas) { - // Support for any object associated to a canvas (including a context2d) - item = item.canvas; - } - - if (item instanceof HTMLCanvasElement) { - // To prevent canvas fingerprinting, some add-ons undefine the getContext - // method, for example: https://github.com/kkapsner/CanvasBlocker - // https://github.com/chartjs/Chart.js/issues/2807 - var context = item.getContext && item.getContext('2d'); - if (context instanceof CanvasRenderingContext2D) { - initCanvas(item, config); - return context; - } - } - - return null; - }, - - releaseContext: function(context) { - var canvas = context.canvas; - if (!canvas._chartjs) { - return; - } - - var initial = canvas._chartjs.initial; - ['height', 'width'].forEach(function(prop) { - var value = initial[prop]; - if (value === undefined || value === null) { - canvas.removeAttribute(prop); - } else { - canvas.setAttribute(prop, value); - } - }); - - helpers.each(initial.style || {}, function(value, key) { - canvas.style[key] = value; - }); - - // The canvas render size might have been changed (and thus the state stack discarded), - // we can't use save() and restore() to restore the initial state. So make sure that at - // least the canvas context is reset to the default state by setting the canvas width. - // https://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html - canvas.width = canvas.width; - - delete canvas._chartjs; - }, - - addEventListener: function(chart, type, listener) { - var canvas = chart.chart.canvas; - if (type === 'resize') { - // Note: the resize event is not supported on all browsers. - addResizeListener(canvas.parentNode, listener, chart.chart); - return; - } - - var stub = listener._chartjs || (listener._chartjs = {}); - var proxies = stub.proxies || (stub.proxies = {}); - var proxy = proxies[chart.id + '_' + type] = function(event) { - listener(fromNativeEvent(event, chart.chart)); - }; - - helpers.addEvent(canvas, type, proxy); - }, - - removeEventListener: function(chart, type, listener) { - var canvas = chart.chart.canvas; - if (type === 'resize') { - // Note: the resize event is not supported on all browsers. - removeResizeListener(canvas.parentNode, listener); - return; - } - - var stub = listener._chartjs || {}; - var proxies = stub.proxies || {}; - var proxy = proxies[chart.id + '_' + type]; - if (!proxy) { - return; - } - - helpers.removeEvent(canvas, type, proxy); - } - }; - }; - -},{}],42:[function(require,module,exports){ - 'use strict'; - -// By default, select the browser (DOM) platform. -// @TODO Make possible to select another platform at build time. - var implementation = require(41); - - module.exports = function(Chart) { - /** - * @namespace Chart.platform - * @see https://chartjs.gitbooks.io/proposals/content/Platform.html - * @since 2.4.0 - */ - Chart.platform = { - /** - * Called at chart construction time, returns a context2d instance implementing - * the [W3C Canvas 2D Context API standard]{@link https://www.w3.org/TR/2dcontext/}. - * @param {*} item - The native item from which to acquire context (platform specific) - * @param {Object} options - The chart options - * @returns {CanvasRenderingContext2D} context2d instance - */ - acquireContext: function() {}, - - /** - * Called at chart destruction time, releases any resources associated to the context - * previously returned by the acquireContext() method. - * @param {CanvasRenderingContext2D} context - The context2d instance - * @returns {Boolean} true if the method succeeded, else false - */ - releaseContext: function() {}, - - /** - * Registers the specified listener on the given chart. - * @param {Chart} chart - Chart from which to listen for event - * @param {String} type - The ({@link IEvent}) type to listen for - * @param {Function} listener - Receives a notification (an object that implements - * the {@link IEvent} interface) when an event of the specified type occurs. - */ - addEventListener: function() {}, - - /** - * Removes the specified listener previously registered with addEventListener. - * @param {Chart} chart -Chart from which to remove the listener - * @param {String} type - The ({@link IEvent}) type to remove - * @param {Function} listener - The listener function to remove from the event target. - */ - removeEventListener: function() {} - }; - - /** - * @interface IPlatform - * Allows abstracting platform dependencies away from the chart - * @borrows Chart.platform.acquireContext as acquireContext - * @borrows Chart.platform.releaseContext as releaseContext - * @borrows Chart.platform.addEventListener as addEventListener - * @borrows Chart.platform.removeEventListener as removeEventListener - */ - - /** - * @interface IEvent - * @prop {String} type - The event type name, possible values are: - * 'contextmenu', 'mouseenter', 'mousedown', 'mousemove', 'mouseup', 'mouseout', - * 'click', 'dblclick', 'keydown', 'keypress', 'keyup' and 'resize' - * @prop {*} native - The original native event (null for emulated events, e.g. 'resize') - * @prop {Number} x - The mouse x position, relative to the canvas (null for incompatible events) - * @prop {Number} y - The mouse y position, relative to the canvas (null for incompatible events) - */ - - Chart.helpers.extend(Chart.platform, implementation(Chart)); - }; - -},{"41":41}],43:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - // Default config for a category scale - var defaultConfig = { - position: 'bottom' - }; - - var DatasetScale = Chart.Scale.extend({ - /** - * Internal function to get the correct labels. If data.xLabels or data.yLabels are defined, use those - * else fall back to data.labels - * @private - */ - getLabels: function() { - var data = this.chart.data; - return (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels; - }, - // Implement this so that - determineDataLimits: function() { - var me = this; - var labels = me.getLabels(); - me.minIndex = 0; - me.maxIndex = labels.length - 1; - var findIndex; - - if (me.options.ticks.min !== undefined) { - // user specified min value - findIndex = helpers.indexOf(labels, me.options.ticks.min); - me.minIndex = findIndex !== -1 ? findIndex : me.minIndex; - } - - if (me.options.ticks.max !== undefined) { - // user specified max value - findIndex = helpers.indexOf(labels, me.options.ticks.max); - me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex; - } - - me.min = labels[me.minIndex]; - me.max = labels[me.maxIndex]; - }, - - buildTicks: function() { - var me = this; - var labels = me.getLabels(); - // If we are viewing some subset of labels, slice the original array - me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1); - }, - - getLabelForIndex: function(index, datasetIndex) { - var me = this; - var data = me.chart.data; - var isHorizontal = me.isHorizontal(); - - if (data.yLabels && !isHorizontal) { - return me.getRightValue(data.datasets[datasetIndex].data[index]); - } - return me.ticks[index - me.minIndex]; - }, - - // Used to get data value locations. Value can either be an index or a numerical value - getPixelForValue: function(value, index, datasetIndex, includeOffset) { - var me = this; - // 1 is added because we need the length but we have the indexes - var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1); - - if (value !== undefined && isNaN(index)) { - var labels = me.getLabels(); - var idx = labels.indexOf(value); - index = idx !== -1 ? idx : index; - } - - if (me.isHorizontal()) { - var valueWidth = me.width / offsetAmt; - var widthOffset = (valueWidth * (index - me.minIndex)); - - if (me.options.gridLines.offsetGridLines && includeOffset || me.maxIndex === me.minIndex && includeOffset) { - widthOffset += (valueWidth / 2); - } - - return me.left + Math.round(widthOffset); - } - var valueHeight = me.height / offsetAmt; - var heightOffset = (valueHeight * (index - me.minIndex)); - - if (me.options.gridLines.offsetGridLines && includeOffset) { - heightOffset += (valueHeight / 2); - } - - return me.top + Math.round(heightOffset); - }, - getPixelForTick: function(index, includeOffset) { - return this.getPixelForValue(this.ticks[index], index + this.minIndex, null, includeOffset); - }, - getValueForPixel: function(pixel) { - var me = this; - var value; - var offsetAmt = Math.max((me.ticks.length - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1); - var horz = me.isHorizontal(); - var valueDimension = (horz ? me.width : me.height) / offsetAmt; - - pixel -= horz ? me.left : me.top; - - if (me.options.gridLines.offsetGridLines) { - pixel -= (valueDimension / 2); - } - - if (pixel <= 0) { - value = 0; - } else { - value = Math.round(pixel / valueDimension); - } - - return value; - }, - getBasePixel: function() { - return this.bottom; - } - }); - - Chart.scaleService.registerScaleType('category', DatasetScale, defaultConfig); - - }; - -},{}],44:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - var defaultConfig = { - position: 'left', - ticks: { - callback: Chart.Ticks.formatters.linear - } - }; - - var LinearScale = Chart.LinearScaleBase.extend({ - determineDataLimits: function() { - var me = this; - var opts = me.options; - var chart = me.chart; - var data = chart.data; - var datasets = data.datasets; - var isHorizontal = me.isHorizontal(); - - function IDMatches(meta) { - return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id; - } - - // First Calculate the range - me.min = null; - me.max = null; - - var hasStacks = opts.stacked; - if (hasStacks === undefined) { - helpers.each(datasets, function(dataset, datasetIndex) { - if (hasStacks) { - return; - } - - var meta = chart.getDatasetMeta(datasetIndex); - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && - meta.stack !== undefined) { - hasStacks = true; - } - }); - } - - if (opts.stacked || hasStacks) { - var valuesPerStack = {}; - - helpers.each(datasets, function(dataset, datasetIndex) { - var meta = chart.getDatasetMeta(datasetIndex); - var key = [ - meta.type, - // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined - ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''), - meta.stack - ].join('.'); - - if (valuesPerStack[key] === undefined) { - valuesPerStack[key] = { - positiveValues: [], - negativeValues: [] - }; - } - - // Store these per type - var positiveValues = valuesPerStack[key].positiveValues; - var negativeValues = valuesPerStack[key].negativeValues; - - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { - helpers.each(dataset.data, function(rawValue, index) { - var value = +me.getRightValue(rawValue); - if (isNaN(value) || meta.data[index].hidden) { - return; - } - - positiveValues[index] = positiveValues[index] || 0; - negativeValues[index] = negativeValues[index] || 0; - - if (opts.relativePoints) { - positiveValues[index] = 100; - } else if (value < 0) { - negativeValues[index] += value; - } else { - positiveValues[index] += value; - } - }); - } - }); - - helpers.each(valuesPerStack, function(valuesForType) { - var values = valuesForType.positiveValues.concat(valuesForType.negativeValues); - var minVal = helpers.min(values); - var maxVal = helpers.max(values); - me.min = me.min === null ? minVal : Math.min(me.min, minVal); - me.max = me.max === null ? maxVal : Math.max(me.max, maxVal); - }); - - } else { - helpers.each(datasets, function(dataset, datasetIndex) { - var meta = chart.getDatasetMeta(datasetIndex); - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { - helpers.each(dataset.data, function(rawValue, index) { - var value = +me.getRightValue(rawValue); - if (isNaN(value) || meta.data[index].hidden) { - return; - } - - if (me.min === null) { - me.min = value; - } else if (value < me.min) { - me.min = value; - } - - if (me.max === null) { - me.max = value; - } else if (value > me.max) { - me.max = value; - } - }); - } - }); - } - - // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero - this.handleTickRangeOptions(); - }, - getTickLimit: function() { - var maxTicks; - var me = this; - var tickOpts = me.options.ticks; - - if (me.isHorizontal()) { - maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.width / 50)); - } else { - // The factor of 2 used to scale the font size has been experimentally determined. - var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize); - maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.height / (2 * tickFontSize))); - } - - return maxTicks; - }, - // Called after the ticks are built. We need - handleDirectionalChanges: function() { - if (!this.isHorizontal()) { - // We are in a vertical orientation. The top value is the highest. So reverse the array - this.ticks.reverse(); - } - }, - getLabelForIndex: function(index, datasetIndex) { - return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); - }, - // Utils - getPixelForValue: function(value) { - // This must be called after fit has been run so that - // this.left, this.top, this.right, and this.bottom have been defined - var me = this; - var start = me.start; - - var rightValue = +me.getRightValue(value); - var pixel; - var range = me.end - start; - - if (me.isHorizontal()) { - pixel = me.left + (me.width / range * (rightValue - start)); - return Math.round(pixel); - } - - pixel = me.bottom - (me.height / range * (rightValue - start)); - return Math.round(pixel); - }, - getValueForPixel: function(pixel) { - var me = this; - var isHorizontal = me.isHorizontal(); - var innerDimension = isHorizontal ? me.width : me.height; - var offset = (isHorizontal ? pixel - me.left : me.bottom - pixel) / innerDimension; - return me.start + ((me.end - me.start) * offset); - }, - getPixelForTick: function(index) { - return this.getPixelForValue(this.ticksAsNumbers[index]); - } - }); - Chart.scaleService.registerScaleType('linear', LinearScale, defaultConfig); - - }; - -},{}],45:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers, - noop = helpers.noop; - - Chart.LinearScaleBase = Chart.Scale.extend({ - handleTickRangeOptions: function() { - var me = this; - var opts = me.options; - var tickOpts = opts.ticks; - - // If we are forcing it to begin at 0, but 0 will already be rendered on the chart, - // do nothing since that would make the chart weird. If the user really wants a weird chart - // axis, they can manually override it - if (tickOpts.beginAtZero) { - var minSign = helpers.sign(me.min); - var maxSign = helpers.sign(me.max); - - if (minSign < 0 && maxSign < 0) { - // move the top up to 0 - me.max = 0; - } else if (minSign > 0 && maxSign > 0) { - // move the bottom down to 0 - me.min = 0; - } - } - - if (tickOpts.min !== undefined) { - me.min = tickOpts.min; - } else if (tickOpts.suggestedMin !== undefined) { - me.min = Math.min(me.min, tickOpts.suggestedMin); - } - - if (tickOpts.max !== undefined) { - me.max = tickOpts.max; - } else if (tickOpts.suggestedMax !== undefined) { - me.max = Math.max(me.max, tickOpts.suggestedMax); - } - - if (me.min === me.max) { - me.max++; - - if (!tickOpts.beginAtZero) { - me.min--; - } - } - }, - getTickLimit: noop, - handleDirectionalChanges: noop, - - buildTicks: function() { - var me = this; - var opts = me.options; - var tickOpts = opts.ticks; - - // Figure out what the max number of ticks we can support it is based on the size of - // the axis area. For now, we say that the minimum tick spacing in pixels must be 50 - // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on - // the graph. Make sure we always have at least 2 ticks - var maxTicks = me.getTickLimit(); - maxTicks = Math.max(2, maxTicks); - - var numericGeneratorOptions = { - maxTicks: maxTicks, - min: tickOpts.min, - max: tickOpts.max, - stepSize: helpers.getValueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize) - }; - var ticks = me.ticks = Chart.Ticks.generators.linear(numericGeneratorOptions, me); - - me.handleDirectionalChanges(); - - // At this point, we need to update our max and min given the tick values since we have expanded the - // range of the scale - me.max = helpers.max(ticks); - me.min = helpers.min(ticks); - - if (tickOpts.reverse) { - ticks.reverse(); - - me.start = me.max; - me.end = me.min; - } else { - me.start = me.min; - me.end = me.max; - } - }, - convertTicksToLabels: function() { - var me = this; - me.ticksAsNumbers = me.ticks.slice(); - me.zeroLineIndex = me.ticks.indexOf(0); - - Chart.Scale.prototype.convertTicksToLabels.call(me); - } - }); - }; - -},{}],46:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - var defaultConfig = { - position: 'left', - - // label settings - ticks: { - callback: Chart.Ticks.formatters.logarithmic - } - }; - - var LogarithmicScale = Chart.Scale.extend({ - determineDataLimits: function() { - var me = this; - var opts = me.options; - var tickOpts = opts.ticks; - var chart = me.chart; - var data = chart.data; - var datasets = data.datasets; - var getValueOrDefault = helpers.getValueOrDefault; - var isHorizontal = me.isHorizontal(); - function IDMatches(meta) { - return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id; - } - - // Calculate Range - me.min = null; - me.max = null; - me.minNotZero = null; - - var hasStacks = opts.stacked; - if (hasStacks === undefined) { - helpers.each(datasets, function(dataset, datasetIndex) { - if (hasStacks) { - return; - } - - var meta = chart.getDatasetMeta(datasetIndex); - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && - meta.stack !== undefined) { - hasStacks = true; - } - }); - } - - if (opts.stacked || hasStacks) { - var valuesPerStack = {}; - - helpers.each(datasets, function(dataset, datasetIndex) { - var meta = chart.getDatasetMeta(datasetIndex); - var key = [ - meta.type, - // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined - ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''), - meta.stack - ].join('.'); - - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { - if (valuesPerStack[key] === undefined) { - valuesPerStack[key] = []; - } - - helpers.each(dataset.data, function(rawValue, index) { - var values = valuesPerStack[key]; - var value = +me.getRightValue(rawValue); - if (isNaN(value) || meta.data[index].hidden) { - return; - } - - values[index] = values[index] || 0; - - if (opts.relativePoints) { - values[index] = 100; - } else { - // Don't need to split positive and negative since the log scale can't handle a 0 crossing - values[index] += value; - } - }); - } - }); - - helpers.each(valuesPerStack, function(valuesForType) { - var minVal = helpers.min(valuesForType); - var maxVal = helpers.max(valuesForType); - me.min = me.min === null ? minVal : Math.min(me.min, minVal); - me.max = me.max === null ? maxVal : Math.max(me.max, maxVal); - }); - - } else { - helpers.each(datasets, function(dataset, datasetIndex) { - var meta = chart.getDatasetMeta(datasetIndex); - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { - helpers.each(dataset.data, function(rawValue, index) { - var value = +me.getRightValue(rawValue); - if (isNaN(value) || meta.data[index].hidden) { - return; - } - - if (me.min === null) { - me.min = value; - } else if (value < me.min) { - me.min = value; - } - - if (me.max === null) { - me.max = value; - } else if (value > me.max) { - me.max = value; - } - - if (value !== 0 && (me.minNotZero === null || value < me.minNotZero)) { - me.minNotZero = value; - } - }); - } - }); - } - - me.min = getValueOrDefault(tickOpts.min, me.min); - me.max = getValueOrDefault(tickOpts.max, me.max); - - if (me.min === me.max) { - if (me.min !== 0 && me.min !== null) { - me.min = Math.pow(10, Math.floor(helpers.log10(me.min)) - 1); - me.max = Math.pow(10, Math.floor(helpers.log10(me.max)) + 1); - } else { - me.min = 1; - me.max = 10; - } - } - }, - buildTicks: function() { - var me = this; - var opts = me.options; - var tickOpts = opts.ticks; - - var generationOptions = { - min: tickOpts.min, - max: tickOpts.max - }; - var ticks = me.ticks = Chart.Ticks.generators.logarithmic(generationOptions, me); - - if (!me.isHorizontal()) { - // We are in a vertical orientation. The top value is the highest. So reverse the array - ticks.reverse(); - } - - // At this point, we need to update our max and min given the tick values since we have expanded the - // range of the scale - me.max = helpers.max(ticks); - me.min = helpers.min(ticks); - - if (tickOpts.reverse) { - ticks.reverse(); - - me.start = me.max; - me.end = me.min; - } else { - me.start = me.min; - me.end = me.max; - } - }, - convertTicksToLabels: function() { - this.tickValues = this.ticks.slice(); - - Chart.Scale.prototype.convertTicksToLabels.call(this); - }, - // Get the correct tooltip label - getLabelForIndex: function(index, datasetIndex) { - return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); - }, - getPixelForTick: function(index) { - return this.getPixelForValue(this.tickValues[index]); - }, - getPixelForValue: function(value) { - var me = this; - var innerDimension; - var pixel; - - var start = me.start; - var newVal = +me.getRightValue(value); - var range; - var opts = me.options; - var tickOpts = opts.ticks; - - if (me.isHorizontal()) { - range = helpers.log10(me.end) - helpers.log10(start); // todo: if start === 0 - if (newVal === 0) { - pixel = me.left; - } else { - innerDimension = me.width; - pixel = me.left + (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start))); - } - } else { - // Bottom - top since pixels increase downward on a screen - innerDimension = me.height; - if (start === 0 && !tickOpts.reverse) { - range = helpers.log10(me.end) - helpers.log10(me.minNotZero); - if (newVal === start) { - pixel = me.bottom; - } else if (newVal === me.minNotZero) { - pixel = me.bottom - innerDimension * 0.02; - } else { - pixel = me.bottom - innerDimension * 0.02 - (innerDimension * 0.98/ range * (helpers.log10(newVal)-helpers.log10(me.minNotZero))); - } - } else if (me.end === 0 && tickOpts.reverse) { - range = helpers.log10(me.start) - helpers.log10(me.minNotZero); - if (newVal === me.end) { - pixel = me.top; - } else if (newVal === me.minNotZero) { - pixel = me.top + innerDimension * 0.02; - } else { - pixel = me.top + innerDimension * 0.02 + (innerDimension * 0.98/ range * (helpers.log10(newVal)-helpers.log10(me.minNotZero))); - } - } else { - range = helpers.log10(me.end) - helpers.log10(start); - innerDimension = me.height; - pixel = me.bottom - (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start))); - } - } - return pixel; - }, - getValueForPixel: function(pixel) { - var me = this; - var range = helpers.log10(me.end) - helpers.log10(me.start); - var value, innerDimension; - - if (me.isHorizontal()) { - innerDimension = me.width; - value = me.start * Math.pow(10, (pixel - me.left) * range / innerDimension); - } else { // todo: if start === 0 - innerDimension = me.height; - value = Math.pow(10, (me.bottom - pixel) * range / innerDimension) / me.start; - } - return value; - } - }); - Chart.scaleService.registerScaleType('logarithmic', LogarithmicScale, defaultConfig); - - }; - -},{}],47:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - var globalDefaults = Chart.defaults.global; - - var defaultConfig = { - display: true, - - // Boolean - Whether to animate scaling the chart from the centre - animate: true, - lineArc: false, - position: 'chartArea', - - angleLines: { - display: true, - color: 'rgba(0, 0, 0, 0.1)', - lineWidth: 1 - }, - - // label settings - ticks: { - // Boolean - Show a backdrop to the scale label - showLabelBackdrop: true, - - // String - The colour of the label backdrop - backdropColor: 'rgba(255,255,255,0.75)', - - // Number - The backdrop padding above & below the label in pixels - backdropPaddingY: 2, - - // Number - The backdrop padding to the side of the label in pixels - backdropPaddingX: 2, - - callback: Chart.Ticks.formatters.linear - }, - - pointLabels: { - // Number - Point label font size in pixels - fontSize: 10, - - // Function - Used to convert point labels - callback: function(label) { - return label; - } - } - }; - - function getValueCount(scale) { - return !scale.options.lineArc ? scale.chart.data.labels.length : 0; - } - - function getPointLabelFontOptions(scale) { - var pointLabelOptions = scale.options.pointLabels; - var fontSize = helpers.getValueOrDefault(pointLabelOptions.fontSize, globalDefaults.defaultFontSize); - var fontStyle = helpers.getValueOrDefault(pointLabelOptions.fontStyle, globalDefaults.defaultFontStyle); - var fontFamily = helpers.getValueOrDefault(pointLabelOptions.fontFamily, globalDefaults.defaultFontFamily); - var font = helpers.fontString(fontSize, fontStyle, fontFamily); - - return { - size: fontSize, - style: fontStyle, - family: fontFamily, - font: font - }; - } - - function measureLabelSize(ctx, fontSize, label) { - if (helpers.isArray(label)) { - return { - w: helpers.longestText(ctx, ctx.font, label), - h: (label.length * fontSize) + ((label.length - 1) * 1.5 * fontSize) - }; - } - - return { - w: ctx.measureText(label).width, - h: fontSize - }; - } - - function determineLimits(angle, pos, size, min, max) { - if (angle === min || angle === max) { - return { - start: pos - (size / 2), - end: pos + (size / 2) - }; - } else if (angle < min || angle > max) { - return { - start: pos - size - 5, - end: pos - }; - } - - return { - start: pos, - end: pos + size + 5 - }; - } - - /** - * Helper function to fit a radial linear scale with point labels - */ - function fitWithPointLabels(scale) { - /* - * Right, this is really confusing and there is a lot of maths going on here - * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9 - * - * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif - * - * Solution: - * - * We assume the radius of the polygon is half the size of the canvas at first - * at each index we check if the text overlaps. - * - * Where it does, we store that angle and that index. - * - * After finding the largest index and angle we calculate how much we need to remove - * from the shape radius to move the point inwards by that x. - * - * We average the left and right distances to get the maximum shape radius that can fit in the box - * along with labels. - * - * Once we have that, we can find the centre point for the chart, by taking the x text protrusion - * on each side, removing that from the size, halving it and adding the left x protrusion width. - * - * This will mean we have a shape fitted to the canvas, as large as it can be with the labels - * and position it in the most space efficient manner - * - * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif - */ - - var plFont = getPointLabelFontOptions(scale); - - // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width. - // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points - var largestPossibleRadius = Math.min(scale.height / 2, scale.width / 2); - var furthestLimits = { - l: scale.width, - r: 0, - t: scale.height, - b: 0 - }; - var furthestAngles = {}; - var i; - var textSize; - var pointPosition; - - scale.ctx.font = plFont.font; - scale._pointLabelSizes = []; - - var valueCount = getValueCount(scale); - for (i = 0; i < valueCount; i++) { - pointPosition = scale.getPointPosition(i, largestPossibleRadius); - textSize = measureLabelSize(scale.ctx, plFont.size, scale.pointLabels[i] || ''); - scale._pointLabelSizes[i] = textSize; - - // Add quarter circle to make degree 0 mean top of circle - var angleRadians = scale.getIndexAngle(i); - var angle = helpers.toDegrees(angleRadians) % 360; - var hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180); - var vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270); - - if (hLimits.start < furthestLimits.l) { - furthestLimits.l = hLimits.start; - furthestAngles.l = angleRadians; - } - - if (hLimits.end > furthestLimits.r) { - furthestLimits.r = hLimits.end; - furthestAngles.r = angleRadians; - } - - if (vLimits.start < furthestLimits.t) { - furthestLimits.t = vLimits.start; - furthestAngles.t = angleRadians; - } - - if (vLimits.end > furthestLimits.b) { - furthestLimits.b = vLimits.end; - furthestAngles.b = angleRadians; - } - } - - scale.setReductions(largestPossibleRadius, furthestLimits, furthestAngles); - } - - /** - * Helper function to fit a radial linear scale with no point labels - */ - function fit(scale) { - var largestPossibleRadius = Math.min(scale.height / 2, scale.width / 2); - scale.drawingArea = Math.round(largestPossibleRadius); - scale.setCenterPoint(0, 0, 0, 0); - } - - function getTextAlignForAngle(angle) { - if (angle === 0 || angle === 180) { - return 'center'; - } else if (angle < 180) { - return 'left'; - } - - return 'right'; - } - - function fillText(ctx, text, position, fontSize) { - if (helpers.isArray(text)) { - var y = position.y; - var spacing = 1.5 * fontSize; - - for (var i = 0; i < text.length; ++i) { - ctx.fillText(text[i], position.x, y); - y+= spacing; - } - } else { - ctx.fillText(text, position.x, position.y); - } - } - - function adjustPointPositionForLabelHeight(angle, textSize, position) { - if (angle === 90 || angle === 270) { - position.y -= (textSize.h / 2); - } else if (angle > 270 || angle < 90) { - position.y -= textSize.h; - } - } - - function drawPointLabels(scale) { - var ctx = scale.ctx; - var getValueOrDefault = helpers.getValueOrDefault; - var opts = scale.options; - var angleLineOpts = opts.angleLines; - var pointLabelOpts = opts.pointLabels; - - ctx.lineWidth = angleLineOpts.lineWidth; - ctx.strokeStyle = angleLineOpts.color; - - var outerDistance = scale.getDistanceFromCenterForValue(opts.reverse ? scale.min : scale.max); - - // Point Label Font - var plFont = getPointLabelFontOptions(scale); - - ctx.textBaseline = 'top'; - - for (var i = getValueCount(scale) - 1; i >= 0; i--) { - if (angleLineOpts.display) { - var outerPosition = scale.getPointPosition(i, outerDistance); - ctx.beginPath(); - ctx.moveTo(scale.xCenter, scale.yCenter); - ctx.lineTo(outerPosition.x, outerPosition.y); - ctx.stroke(); - ctx.closePath(); - } - // Extra 3px out for some label spacing - var pointLabelPosition = scale.getPointPosition(i, outerDistance + 5); - - // Keep this in loop since we may support array properties here - var pointLabelFontColor = getValueOrDefault(pointLabelOpts.fontColor, globalDefaults.defaultFontColor); - ctx.font = plFont.font; - ctx.fillStyle = pointLabelFontColor; - - var angleRadians = scale.getIndexAngle(i); - var angle = helpers.toDegrees(angleRadians); - ctx.textAlign = getTextAlignForAngle(angle); - adjustPointPositionForLabelHeight(angle, scale._pointLabelSizes[i], pointLabelPosition); - fillText(ctx, scale.pointLabels[i] || '', pointLabelPosition, plFont.size); - } - } - - function drawRadiusLine(scale, gridLineOpts, radius, index) { - var ctx = scale.ctx; - ctx.strokeStyle = helpers.getValueAtIndexOrDefault(gridLineOpts.color, index - 1); - ctx.lineWidth = helpers.getValueAtIndexOrDefault(gridLineOpts.lineWidth, index - 1); - - if (scale.options.lineArc) { - // Draw circular arcs between the points - ctx.beginPath(); - ctx.arc(scale.xCenter, scale.yCenter, radius, 0, Math.PI * 2); - ctx.closePath(); - ctx.stroke(); - } else { - // Draw straight lines connecting each index - var valueCount = getValueCount(scale); - - if (valueCount === 0) { - return; - } - - ctx.beginPath(); - var pointPosition = scale.getPointPosition(0, radius); - ctx.moveTo(pointPosition.x, pointPosition.y); - - for (var i = 1; i < valueCount; i++) { - pointPosition = scale.getPointPosition(i, radius); - ctx.lineTo(pointPosition.x, pointPosition.y); - } - - ctx.closePath(); - ctx.stroke(); - } - } - - function numberOrZero(param) { - return helpers.isNumber(param) ? param : 0; - } - - var LinearRadialScale = Chart.LinearScaleBase.extend({ - setDimensions: function() { - var me = this; - var opts = me.options; - var tickOpts = opts.ticks; - // Set the unconstrained dimension before label rotation - me.width = me.maxWidth; - me.height = me.maxHeight; - me.xCenter = Math.round(me.width / 2); - me.yCenter = Math.round(me.height / 2); - - var minSize = helpers.min([me.height, me.width]); - var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize); - me.drawingArea = opts.display ? (minSize / 2) - (tickFontSize / 2 + tickOpts.backdropPaddingY) : (minSize / 2); - }, - determineDataLimits: function() { - var me = this; - var chart = me.chart; - var min = Number.POSITIVE_INFINITY; - var max = Number.NEGATIVE_INFINITY; - - helpers.each(chart.data.datasets, function(dataset, datasetIndex) { - if (chart.isDatasetVisible(datasetIndex)) { - var meta = chart.getDatasetMeta(datasetIndex); - - helpers.each(dataset.data, function(rawValue, index) { - var value = +me.getRightValue(rawValue); - if (isNaN(value) || meta.data[index].hidden) { - return; - } - - min = Math.min(value, min); - max = Math.max(value, max); - }); - } - }); - - me.min = (min === Number.POSITIVE_INFINITY ? 0 : min); - me.max = (max === Number.NEGATIVE_INFINITY ? 0 : max); - - // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero - me.handleTickRangeOptions(); - }, - getTickLimit: function() { - var tickOpts = this.options.ticks; - var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize); - return Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(this.drawingArea / (1.5 * tickFontSize))); - }, - convertTicksToLabels: function() { - var me = this; - Chart.LinearScaleBase.prototype.convertTicksToLabels.call(me); - - // Point labels - me.pointLabels = me.chart.data.labels.map(me.options.pointLabels.callback, me); - }, - getLabelForIndex: function(index, datasetIndex) { - return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); - }, - fit: function() { - if (this.options.lineArc) { - fit(this); - } else { - fitWithPointLabels(this); - } - }, - /** - * Set radius reductions and determine new radius and center point - * @private - */ - setReductions: function(largestPossibleRadius, furthestLimits, furthestAngles) { - var me = this; - var radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l); - var radiusReductionRight = Math.max(furthestLimits.r - me.width, 0) / Math.sin(furthestAngles.r); - var radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t); - var radiusReductionBottom = -Math.max(furthestLimits.b - me.height, 0) / Math.cos(furthestAngles.b); - - radiusReductionLeft = numberOrZero(radiusReductionLeft); - radiusReductionRight = numberOrZero(radiusReductionRight); - radiusReductionTop = numberOrZero(radiusReductionTop); - radiusReductionBottom = numberOrZero(radiusReductionBottom); - - me.drawingArea = Math.min( - Math.round(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2), - Math.round(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2)); - me.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom); - }, - setCenterPoint: function(leftMovement, rightMovement, topMovement, bottomMovement) { - var me = this; - var maxRight = me.width - rightMovement - me.drawingArea, - maxLeft = leftMovement + me.drawingArea, - maxTop = topMovement + me.drawingArea, - maxBottom = me.height - bottomMovement - me.drawingArea; - - me.xCenter = Math.round(((maxLeft + maxRight) / 2) + me.left); - me.yCenter = Math.round(((maxTop + maxBottom) / 2) + me.top); - }, - - getIndexAngle: function(index) { - var angleMultiplier = (Math.PI * 2) / getValueCount(this); - var startAngle = this.chart.options && this.chart.options.startAngle ? - this.chart.options.startAngle : - 0; - - var startAngleRadians = startAngle * Math.PI * 2 / 360; - - // Start from the top instead of right, so remove a quarter of the circle - return index * angleMultiplier + startAngleRadians; - }, - getDistanceFromCenterForValue: function(value) { - var me = this; - - if (value === null) { - return 0; // null always in center - } - - // Take into account half font size + the yPadding of the top value - var scalingFactor = me.drawingArea / (me.max - me.min); - if (me.options.reverse) { - return (me.max - value) * scalingFactor; - } - return (value - me.min) * scalingFactor; - }, - getPointPosition: function(index, distanceFromCenter) { - var me = this; - var thisAngle = me.getIndexAngle(index) - (Math.PI / 2); - return { - x: Math.round(Math.cos(thisAngle) * distanceFromCenter) + me.xCenter, - y: Math.round(Math.sin(thisAngle) * distanceFromCenter) + me.yCenter - }; - }, - getPointPositionForValue: function(index, value) { - return this.getPointPosition(index, this.getDistanceFromCenterForValue(value)); - }, - - getBasePosition: function() { - var me = this; - var min = me.min; - var max = me.max; - - return me.getPointPositionForValue(0, - me.beginAtZero? 0: - min < 0 && max < 0? max : - min > 0 && max > 0? min : - 0); - }, - - draw: function() { - var me = this; - var opts = me.options; - var gridLineOpts = opts.gridLines; - var tickOpts = opts.ticks; - var getValueOrDefault = helpers.getValueOrDefault; - - if (opts.display) { - var ctx = me.ctx; - - // Tick Font - var tickFontSize = getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize); - var tickFontStyle = getValueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle); - var tickFontFamily = getValueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily); - var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily); - - helpers.each(me.ticks, function(label, index) { - // Don't draw a centre value (if it is minimum) - if (index > 0 || opts.reverse) { - var yCenterOffset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]); - var yHeight = me.yCenter - yCenterOffset; - - // Draw circular lines around the scale - if (gridLineOpts.display && index !== 0) { - drawRadiusLine(me, gridLineOpts, yCenterOffset, index); - } - - if (tickOpts.display) { - var tickFontColor = getValueOrDefault(tickOpts.fontColor, globalDefaults.defaultFontColor); - ctx.font = tickLabelFont; - - if (tickOpts.showLabelBackdrop) { - var labelWidth = ctx.measureText(label).width; - ctx.fillStyle = tickOpts.backdropColor; - ctx.fillRect( - me.xCenter - labelWidth / 2 - tickOpts.backdropPaddingX, - yHeight - tickFontSize / 2 - tickOpts.backdropPaddingY, - labelWidth + tickOpts.backdropPaddingX * 2, - tickFontSize + tickOpts.backdropPaddingY * 2 - ); - } - - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - ctx.fillStyle = tickFontColor; - ctx.fillText(label, me.xCenter, yHeight); - } - } - }); - - if (!opts.lineArc) { - drawPointLabels(me); - } - } - } - }); - Chart.scaleService.registerScaleType('radialLinear', LinearRadialScale, defaultConfig); - - }; - -},{}],48:[function(require,module,exports){ - /* global window: false */ - 'use strict'; - - var moment = require(1); - moment = typeof(moment) === 'function' ? moment : window.moment; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - var time = { - units: [{ - name: 'millisecond', - steps: [1, 2, 5, 10, 20, 50, 100, 250, 500] - }, { - name: 'second', - steps: [1, 2, 5, 10, 30] - }, { - name: 'minute', - steps: [1, 2, 5, 10, 30] - }, { - name: 'hour', - steps: [1, 2, 3, 6, 12] - }, { - name: 'day', - steps: [1, 2, 5] - }, { - name: 'week', - maxStep: 4 - }, { - name: 'month', - maxStep: 3 - }, { - name: 'quarter', - maxStep: 4 - }, { - name: 'year', - maxStep: false - }] - }; - - var defaultConfig = { - position: 'bottom', - - time: { - parser: false, // false == a pattern string from http://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment - format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from http://momentjs.com/docs/#/parsing/string-format/ - unit: false, // false == automatic or override with week, month, year, etc. - round: false, // none, or override with week, month, year, etc. - displayFormat: false, // DEPRECATED - isoWeekday: false, // override week start day - see http://momentjs.com/docs/#/get-set/iso-weekday/ - minUnit: 'millisecond', - - // defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/ - displayFormats: { - millisecond: 'h:mm:ss.SSS a', // 11:20:01.123 AM, - second: 'h:mm:ss a', // 11:20:01 AM - minute: 'h:mm:ss a', // 11:20:01 AM - hour: 'MMM D, hA', // Sept 4, 5PM - day: 'll', // Sep 4 2015 - week: 'll', // Week 46, or maybe "[W]WW - YYYY" ? - month: 'MMM YYYY', // Sept 2015 - quarter: '[Q]Q - YYYY', // Q3 - year: 'YYYY' // 2015 - } - }, - ticks: { - autoSkip: false - } - }; - - var TimeScale = Chart.Scale.extend({ - initialize: function() { - if (!moment) { - throw new Error('Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com'); - } - - Chart.Scale.prototype.initialize.call(this); - }, - getLabelMoment: function(datasetIndex, index) { - if (datasetIndex === null || index === null) { - return null; - } - - if (typeof this.labelMoments[datasetIndex] !== 'undefined') { - return this.labelMoments[datasetIndex][index]; - } - - return null; - }, - getLabelDiff: function(datasetIndex, index) { - var me = this; - if (datasetIndex === null || index === null) { - return null; - } - - if (me.labelDiffs === undefined) { - me.buildLabelDiffs(); - } - - if (typeof me.labelDiffs[datasetIndex] !== 'undefined') { - return me.labelDiffs[datasetIndex][index]; - } - - return null; - }, - getMomentStartOf: function(tick) { - var me = this; - if (me.options.time.unit === 'week' && me.options.time.isoWeekday !== false) { - return tick.clone().startOf('isoWeek').isoWeekday(me.options.time.isoWeekday); - } - return tick.clone().startOf(me.tickUnit); - }, - determineDataLimits: function() { - var me = this; - me.labelMoments = []; - - // Only parse these once. If the dataset does not have data as x,y pairs, we will use - // these - var scaleLabelMoments = []; - if (me.chart.data.labels && me.chart.data.labels.length > 0) { - helpers.each(me.chart.data.labels, function(label) { - var labelMoment = me.parseTime(label); - - if (labelMoment.isValid()) { - if (me.options.time.round) { - labelMoment.startOf(me.options.time.round); - } - scaleLabelMoments.push(labelMoment); - } - }, me); - - me.firstTick = moment.min.call(me, scaleLabelMoments); - me.lastTick = moment.max.call(me, scaleLabelMoments); - } else { - me.firstTick = null; - me.lastTick = null; - } - - helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) { - var momentsForDataset = []; - var datasetVisible = me.chart.isDatasetVisible(datasetIndex); - - if (typeof dataset.data[0] === 'object' && dataset.data[0] !== null) { - helpers.each(dataset.data, function(value) { - var labelMoment = me.parseTime(me.getRightValue(value)); - - if (labelMoment.isValid()) { - if (me.options.time.round) { - labelMoment.startOf(me.options.time.round); - } - momentsForDataset.push(labelMoment); - - if (datasetVisible) { - // May have gone outside the scale ranges, make sure we keep the first and last ticks updated - me.firstTick = me.firstTick !== null ? moment.min(me.firstTick, labelMoment) : labelMoment; - me.lastTick = me.lastTick !== null ? moment.max(me.lastTick, labelMoment) : labelMoment; - } - } - }, me); - } else { - // We have no labels. Use the ones from the scale - momentsForDataset = scaleLabelMoments; - } - - me.labelMoments.push(momentsForDataset); - }, me); - - // Set these after we've done all the data - if (me.options.time.min) { - me.firstTick = me.parseTime(me.options.time.min); - } - - if (me.options.time.max) { - me.lastTick = me.parseTime(me.options.time.max); - } - - // We will modify these, so clone for later - me.firstTick = (me.firstTick || moment()).clone(); - me.lastTick = (me.lastTick || moment()).clone(); - }, - buildLabelDiffs: function() { - var me = this; - me.labelDiffs = []; - var scaleLabelDiffs = []; - // Parse common labels once - if (me.chart.data.labels && me.chart.data.labels.length > 0) { - helpers.each(me.chart.data.labels, function(label) { - var labelMoment = me.parseTime(label); - - if (labelMoment.isValid()) { - if (me.options.time.round) { - labelMoment.startOf(me.options.time.round); - } - scaleLabelDiffs.push(labelMoment.diff(me.firstTick, me.tickUnit, true)); - } - }, me); - } - - helpers.each(me.chart.data.datasets, function(dataset) { - var diffsForDataset = []; - - if (typeof dataset.data[0] === 'object' && dataset.data[0] !== null) { - helpers.each(dataset.data, function(value) { - var labelMoment = me.parseTime(me.getRightValue(value)); - - if (labelMoment.isValid()) { - if (me.options.time.round) { - labelMoment.startOf(me.options.time.round); - } - diffsForDataset.push(labelMoment.diff(me.firstTick, me.tickUnit, true)); - } - }, me); - } else { - // We have no labels. Use common ones - diffsForDataset = scaleLabelDiffs; - } - - me.labelDiffs.push(diffsForDataset); - }, me); - }, - buildTicks: function() { - var me = this; - - me.ctx.save(); - var tickFontSize = helpers.getValueOrDefault(me.options.ticks.fontSize, Chart.defaults.global.defaultFontSize); - var tickFontStyle = helpers.getValueOrDefault(me.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle); - var tickFontFamily = helpers.getValueOrDefault(me.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily); - var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily); - me.ctx.font = tickLabelFont; - - me.ticks = []; - me.unitScale = 1; // How much we scale the unit by, ie 2 means 2x unit per step - me.scaleSizeInUnits = 0; // How large the scale is in the base unit (seconds, minutes, etc) - - // Set unit override if applicable - if (me.options.time.unit) { - me.tickUnit = me.options.time.unit || 'day'; - me.displayFormat = me.options.time.displayFormats[me.tickUnit]; - me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true); - me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, 1); - } else { - // Determine the smallest needed unit of the time - var innerWidth = me.isHorizontal() ? me.width : me.height; - - // Crude approximation of what the label length might be - var tempFirstLabel = me.tickFormatFunction(me.firstTick, 0, []); - var tickLabelWidth = me.ctx.measureText(tempFirstLabel).width; - var cosRotation = Math.cos(helpers.toRadians(me.options.ticks.maxRotation)); - var sinRotation = Math.sin(helpers.toRadians(me.options.ticks.maxRotation)); - tickLabelWidth = (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation); - var labelCapacity = innerWidth / (tickLabelWidth); - - // Start as small as possible - me.tickUnit = me.options.time.minUnit; - me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true); - me.displayFormat = me.options.time.displayFormats[me.tickUnit]; - - var unitDefinitionIndex = 0; - var unitDefinition = time.units[unitDefinitionIndex]; - - // While we aren't ideal and we don't have units left - while (unitDefinitionIndex < time.units.length) { - // Can we scale this unit. If `false` we can scale infinitely - me.unitScale = 1; - - if (helpers.isArray(unitDefinition.steps) && Math.ceil(me.scaleSizeInUnits / labelCapacity) < helpers.max(unitDefinition.steps)) { - // Use one of the predefined steps - for (var idx = 0; idx < unitDefinition.steps.length; ++idx) { - if (unitDefinition.steps[idx] >= Math.ceil(me.scaleSizeInUnits / labelCapacity)) { - me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, unitDefinition.steps[idx]); - break; - } - } - - break; - } else if ((unitDefinition.maxStep === false) || (Math.ceil(me.scaleSizeInUnits / labelCapacity) < unitDefinition.maxStep)) { - // We have a max step. Scale this unit - me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, Math.ceil(me.scaleSizeInUnits / labelCapacity)); - break; - } else { - // Move to the next unit up - ++unitDefinitionIndex; - unitDefinition = time.units[unitDefinitionIndex]; - - me.tickUnit = unitDefinition.name; - var leadingUnitBuffer = me.firstTick.diff(me.getMomentStartOf(me.firstTick), me.tickUnit, true); - var trailingUnitBuffer = me.getMomentStartOf(me.lastTick.clone().add(1, me.tickUnit)).diff(me.lastTick, me.tickUnit, true); - me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true) + leadingUnitBuffer + trailingUnitBuffer; - me.displayFormat = me.options.time.displayFormats[unitDefinition.name]; - } - } - } - - var roundedStart; - - // Only round the first tick if we have no hard minimum - if (!me.options.time.min) { - me.firstTick = me.getMomentStartOf(me.firstTick); - roundedStart = me.firstTick; - } else { - roundedStart = me.getMomentStartOf(me.firstTick); - } - - // Only round the last tick if we have no hard maximum - if (!me.options.time.max) { - var roundedEnd = me.getMomentStartOf(me.lastTick); - var delta = roundedEnd.diff(me.lastTick, me.tickUnit, true); - if (delta < 0) { - // Do not use end of because we need me to be in the next time unit - me.lastTick = me.getMomentStartOf(me.lastTick.add(1, me.tickUnit)); - } else if (delta >= 0) { - me.lastTick = roundedEnd; - } - - me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true); - } - - // Tick displayFormat override - if (me.options.time.displayFormat) { - me.displayFormat = me.options.time.displayFormat; - } - - // first tick. will have been rounded correctly if options.time.min is not specified - me.ticks.push(me.firstTick.clone()); - - // For every unit in between the first and last moment, create a moment and add it to the ticks tick - for (var i = me.unitScale; i <= me.scaleSizeInUnits; i += me.unitScale) { - var newTick = roundedStart.clone().add(i, me.tickUnit); - - // Are we greater than the max time - if (me.options.time.max && newTick.diff(me.lastTick, me.tickUnit, true) >= 0) { - break; - } - - me.ticks.push(newTick); - } - - // Always show the right tick - var diff = me.ticks[me.ticks.length - 1].diff(me.lastTick, me.tickUnit); - if (diff !== 0 || me.scaleSizeInUnits === 0) { - // this is a weird case. If the <max> option is the same as the end option, we can't just diff the times because the tick was created from the roundedStart - // but the last tick was not rounded. - if (me.options.time.max) { - me.ticks.push(me.lastTick.clone()); - me.scaleSizeInUnits = me.lastTick.diff(me.ticks[0], me.tickUnit, true); - } else { - me.ticks.push(me.lastTick.clone()); - me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true); - } - } - - me.ctx.restore(); - - // Invalidate label diffs cache - me.labelDiffs = undefined; - }, - // Get tooltip label - getLabelForIndex: function(index, datasetIndex) { - var me = this; - var label = me.chart.data.labels && index < me.chart.data.labels.length ? me.chart.data.labels[index] : ''; - var value = me.chart.data.datasets[datasetIndex].data[index]; - - if (value !== null && typeof value === 'object') { - label = me.getRightValue(value); - } - - // Format nicely - if (me.options.time.tooltipFormat) { - label = me.parseTime(label).format(me.options.time.tooltipFormat); - } - - return label; - }, - // Function to format an individual tick mark - tickFormatFunction: function(tick, index, ticks) { - var formattedTick = tick.format(this.displayFormat); - var tickOpts = this.options.ticks; - var callback = helpers.getValueOrDefault(tickOpts.callback, tickOpts.userCallback); - - if (callback) { - return callback(formattedTick, index, ticks); - } - return formattedTick; - }, - convertTicksToLabels: function() { - var me = this; - me.tickMoments = me.ticks; - me.ticks = me.ticks.map(me.tickFormatFunction, me); - }, - getPixelForValue: function(value, index, datasetIndex) { - var me = this; - var offset = null; - if (index !== undefined && datasetIndex !== undefined) { - offset = me.getLabelDiff(datasetIndex, index); - } - - if (offset === null) { - if (!value || !value.isValid) { - // not already a moment object - value = me.parseTime(me.getRightValue(value)); - } - if (value && value.isValid && value.isValid()) { - offset = value.diff(me.firstTick, me.tickUnit, true); - } - } - - if (offset !== null) { - var decimal = offset !== 0 ? offset / me.scaleSizeInUnits : offset; - - if (me.isHorizontal()) { - var valueOffset = (me.width * decimal); - return me.left + Math.round(valueOffset); - } - - var heightOffset = (me.height * decimal); - return me.top + Math.round(heightOffset); - } - }, - getPixelForTick: function(index) { - return this.getPixelForValue(this.tickMoments[index], null, null); - }, - getValueForPixel: function(pixel) { - var me = this; - var innerDimension = me.isHorizontal() ? me.width : me.height; - var offset = (pixel - (me.isHorizontal() ? me.left : me.top)) / innerDimension; - offset *= me.scaleSizeInUnits; - return me.firstTick.clone().add(moment.duration(offset, me.tickUnit).asSeconds(), 'seconds'); - }, - parseTime: function(label) { - var me = this; - if (typeof me.options.time.parser === 'string') { - return moment(label, me.options.time.parser); - } - if (typeof me.options.time.parser === 'function') { - return me.options.time.parser(label); - } - // Date objects - if (typeof label.getMonth === 'function' || typeof label === 'number') { - return moment(label); - } - // Moment support - if (label.isValid && label.isValid()) { - return label; - } - // Custom parsing (return an instance of moment) - if (typeof me.options.time.format !== 'string' && me.options.time.format.call) { - console.warn('options.time.format is deprecated and replaced by options.time.parser. See http://nnnick.github.io/Chart.js/docs-v2/#scales-time-scale'); - return me.options.time.format(label); - } - // Moment format parsing - return moment(label, me.options.time.format); - } - }); - Chart.scaleService.registerScaleType('time', TimeScale, defaultConfig); - - }; - -},{"1":1}]},{},[7])(7) -}); diff --git a/assets/www/dist/dist_js/app/vendor/aes-js.js b/assets/www/dist/dist_js/app/vendor/aes-js.js deleted file mode 100644 index f18d95436b0d59930703da4e6cde4b3952db1be6..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/aes-js.js +++ /dev/null @@ -1,803 +0,0 @@ -// source: https://github.com/ricmoo/aes-js - version 3.3.1 -(function(root) { - "use strict"; - - function checkInt(value) { - return (parseInt(value) === value); - } - - function checkInts(arrayish) { - if (!checkInt(arrayish.length)) { return false; } - - for (var i = 0; i < arrayish.length; i++) { - if (!checkInt(arrayish[i]) || arrayish[i] < 0 || arrayish[i] > 255) { - return false; - } - } - - return true; - } - - function coerceArray(arg, copy) { - - // ArrayBuffer view - if (arg.buffer && ArrayBuffer.isView(arg) && arg.name === 'Uint8Array') { - - if (copy) { - if (arg.slice) { - arg = arg.slice(); - } else { - arg = Array.prototype.slice.call(arg); - } - } - - return arg; - } - - // It's an array; check it is a valid representation of a byte - if (Array.isArray(arg)) { - if (!checkInts(arg)) { - throw new Error('Array contains invalid value: ' + arg); - } - - return new Uint8Array(arg); - } - - // Something else, but behaves like an array (maybe a Buffer? Arguments?) - if (checkInt(arg.length) && checkInts(arg)) { - return new Uint8Array(arg); - } - - throw new Error('unsupported array-like object'); - } - - function createArray(length) { - return new Uint8Array(length); - } - - function copyArray(sourceArray, targetArray, targetStart, sourceStart, sourceEnd) { - if (sourceStart != null || sourceEnd != null) { - if (sourceArray.slice) { - sourceArray = sourceArray.slice(sourceStart, sourceEnd); - } else { - sourceArray = Array.prototype.slice.call(sourceArray, sourceStart, sourceEnd); - } - } - targetArray.set(sourceArray, targetStart); - } - - - - var convertUtf8 = (function() { - function toBytes(text) { - var result = [], i = 0; - text = encodeURI(text); - while (i < text.length) { - var c = text.charCodeAt(i++); - - // if it is a % sign, encode the following 2 bytes as a hex value - if (c === 37) { - result.push(parseInt(text.substr(i, 2), 16)) - i += 2; - - // otherwise, just the actual byte - } else { - result.push(c) - } - } - - return coerceArray(result); - } - - function fromBytes(bytes) { - var result = [], i = 0; - - while (i < bytes.length) { - var c = bytes[i]; - - if (c < 128) { - result.push(String.fromCharCode(c)); - i++; - } else if (c > 191 && c < 224) { - result.push(String.fromCharCode(((c & 0x1f) << 6) | (bytes[i + 1] & 0x3f))); - i += 2; - } else { - result.push(String.fromCharCode(((c & 0x0f) << 12) | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f))); - i += 3; - } - } - - return result.join(''); - } - - return { - toBytes: toBytes, - fromBytes: fromBytes, - } - })(); - - var convertHex = (function() { - function toBytes(text) { - var result = []; - for (var i = 0; i < text.length; i += 2) { - result.push(parseInt(text.substr(i, 2), 16)); - } - - return result; - } - - // http://ixti.net/development/javascript/2011/11/11/base64-encodedecode-of-utf8-in-browser-with-js.html - var Hex = '0123456789abcdef'; - - function fromBytes(bytes) { - var result = []; - for (var i = 0; i < bytes.length; i++) { - var v = bytes[i]; - result.push(Hex[(v & 0xf0) >> 4] + Hex[v & 0x0f]); - } - return result.join(''); - } - - return { - toBytes: toBytes, - fromBytes: fromBytes, - } - })(); - - - // Number of rounds by keysize - var numberOfRounds = {16: 10, 24: 12, 32: 14} - - // Round constant words - var rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91]; - - // S-box and Inverse S-box (S is for Substitution) - var S = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]; - var Si =[0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]; - - // Transformations for encryption - var T1 = [0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a]; - var T2 = [0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616]; - var T3 = [0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16]; - var T4 = [0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c]; - - // Transformations for decryption - var T5 = [0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742]; - var T6 = [0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857]; - var T7 = [0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8]; - var T8 = [0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0]; - - // Transformations for decryption key expansion - var U1 = [0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]; - var U2 = [0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697]; - var U3 = [0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46]; - var U4 = [0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d]; - - function convertToInt32(bytes) { - var result = []; - for (var i = 0; i < bytes.length; i += 4) { - result.push( - (bytes[i ] << 24) | - (bytes[i + 1] << 16) | - (bytes[i + 2] << 8) | - bytes[i + 3] - ); - } - return result; - } - - var AES = function(key) { - if (!(this instanceof AES)) { - throw Error('AES must be instanitated with `new`'); - } - - Object.defineProperty(this, 'key', { - value: coerceArray(key, true) - }); - - this._prepare(); - } - - - AES.prototype._prepare = function() { - - var rounds = numberOfRounds[this.key.length]; - if (rounds == null) { - throw new Error('invalid key size (must be 16, 24 or 32 bytes)'); - } - - // encryption round keys - this._Ke = []; - - // decryption round keys - this._Kd = []; - - for (var i = 0; i <= rounds; i++) { - this._Ke.push([0, 0, 0, 0]); - this._Kd.push([0, 0, 0, 0]); - } - - var roundKeyCount = (rounds + 1) * 4; - var KC = this.key.length / 4; - - // convert the key into ints - var tk = convertToInt32(this.key); - - // copy values into round key arrays - var index; - for (var i = 0; i < KC; i++) { - index = i >> 2; - this._Ke[index][i % 4] = tk[i]; - this._Kd[rounds - index][i % 4] = tk[i]; - } - - // key expansion (fips-197 section 5.2) - var rconpointer = 0; - var t = KC, tt; - while (t < roundKeyCount) { - tt = tk[KC - 1]; - tk[0] ^= ((S[(tt >> 16) & 0xFF] << 24) ^ - (S[(tt >> 8) & 0xFF] << 16) ^ - (S[ tt & 0xFF] << 8) ^ - S[(tt >> 24) & 0xFF] ^ - (rcon[rconpointer] << 24)); - rconpointer += 1; - - // key expansion (for non-256 bit) - if (KC != 8) { - for (var i = 1; i < KC; i++) { - tk[i] ^= tk[i - 1]; - } - - // key expansion for 256-bit keys is "slightly different" (fips-197) - } else { - for (var i = 1; i < (KC / 2); i++) { - tk[i] ^= tk[i - 1]; - } - tt = tk[(KC / 2) - 1]; - - tk[KC / 2] ^= (S[ tt & 0xFF] ^ - (S[(tt >> 8) & 0xFF] << 8) ^ - (S[(tt >> 16) & 0xFF] << 16) ^ - (S[(tt >> 24) & 0xFF] << 24)); - - for (var i = (KC / 2) + 1; i < KC; i++) { - tk[i] ^= tk[i - 1]; - } - } - - // copy values into round key arrays - var i = 0, r, c; - while (i < KC && t < roundKeyCount) { - r = t >> 2; - c = t % 4; - this._Ke[r][c] = tk[i]; - this._Kd[rounds - r][c] = tk[i++]; - t++; - } - } - - // inverse-cipher-ify the decryption round key (fips-197 section 5.3) - for (var r = 1; r < rounds; r++) { - for (var c = 0; c < 4; c++) { - tt = this._Kd[r][c]; - this._Kd[r][c] = (U1[(tt >> 24) & 0xFF] ^ - U2[(tt >> 16) & 0xFF] ^ - U3[(tt >> 8) & 0xFF] ^ - U4[ tt & 0xFF]); - } - } - } - - AES.prototype.encrypt = function(plaintext) { - if (plaintext.length != 16) { - throw new Error('invalid plaintext size (must be 16 bytes)'); - } - - var rounds = this._Ke.length - 1; - var a = [0, 0, 0, 0]; - - // convert plaintext to (ints ^ key) - var t = convertToInt32(plaintext); - for (var i = 0; i < 4; i++) { - t[i] ^= this._Ke[0][i]; - } - - // apply round transforms - for (var r = 1; r < rounds; r++) { - for (var i = 0; i < 4; i++) { - a[i] = (T1[(t[ i ] >> 24) & 0xff] ^ - T2[(t[(i + 1) % 4] >> 16) & 0xff] ^ - T3[(t[(i + 2) % 4] >> 8) & 0xff] ^ - T4[ t[(i + 3) % 4] & 0xff] ^ - this._Ke[r][i]); - } - t = a.slice(); - } - - // the last round is special - var result = createArray(16), tt; - for (var i = 0; i < 4; i++) { - tt = this._Ke[rounds][i]; - result[4 * i ] = (S[(t[ i ] >> 24) & 0xff] ^ (tt >> 24)) & 0xff; - result[4 * i + 1] = (S[(t[(i + 1) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff; - result[4 * i + 2] = (S[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff; - result[4 * i + 3] = (S[ t[(i + 3) % 4] & 0xff] ^ tt ) & 0xff; - } - - return result; - } - - AES.prototype.decrypt = function(ciphertext) { - if (ciphertext.length != 16) { - throw new Error('invalid ciphertext size (must be 16 bytes)'); - } - - var rounds = this._Kd.length - 1; - var a = [0, 0, 0, 0]; - - // convert plaintext to (ints ^ key) - var t = convertToInt32(ciphertext); - for (var i = 0; i < 4; i++) { - t[i] ^= this._Kd[0][i]; - } - - // apply round transforms - for (var r = 1; r < rounds; r++) { - for (var i = 0; i < 4; i++) { - a[i] = (T5[(t[ i ] >> 24) & 0xff] ^ - T6[(t[(i + 3) % 4] >> 16) & 0xff] ^ - T7[(t[(i + 2) % 4] >> 8) & 0xff] ^ - T8[ t[(i + 1) % 4] & 0xff] ^ - this._Kd[r][i]); - } - t = a.slice(); - } - - // the last round is special - var result = createArray(16), tt; - for (var i = 0; i < 4; i++) { - tt = this._Kd[rounds][i]; - result[4 * i ] = (Si[(t[ i ] >> 24) & 0xff] ^ (tt >> 24)) & 0xff; - result[4 * i + 1] = (Si[(t[(i + 3) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff; - result[4 * i + 2] = (Si[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff; - result[4 * i + 3] = (Si[ t[(i + 1) % 4] & 0xff] ^ tt ) & 0xff; - } - - return result; - } - - - /** - * Mode Of Operation - Electonic Codebook (ECB) - */ - var ModeOfOperationECB = function(key) { - if (!(this instanceof ModeOfOperationECB)) { - throw Error('AES must be instanitated with `new`'); - } - - this.description = "Electronic Code Block"; - this.name = "ecb"; - - this._aes = new AES(key); - } - - ModeOfOperationECB.prototype.encrypt = function(plaintext) { - plaintext = coerceArray(plaintext); - - if ((plaintext.length % 16) !== 0) { - throw new Error('invalid plaintext size (must be multiple of 16 bytes)'); - } - - var ciphertext = createArray(plaintext.length); - var block = createArray(16); - - for (var i = 0; i < plaintext.length; i += 16) { - copyArray(plaintext, block, 0, i, i + 16); - block = this._aes.encrypt(block); - copyArray(block, ciphertext, i); - } - - return ciphertext; - } - - ModeOfOperationECB.prototype.decrypt = function(ciphertext) { - ciphertext = coerceArray(ciphertext); - - if ((ciphertext.length % 16) !== 0) { - throw new Error('invalid ciphertext size (must be multiple of 16 bytes)'); - } - - var plaintext = createArray(ciphertext.length); - var block = createArray(16); - - for (var i = 0; i < ciphertext.length; i += 16) { - copyArray(ciphertext, block, 0, i, i + 16); - block = this._aes.decrypt(block); - copyArray(block, plaintext, i); - } - - return plaintext; - } - - - /** - * Mode Of Operation - Cipher Block Chaining (CBC) - */ - var ModeOfOperationCBC = function(key, iv) { - if (!(this instanceof ModeOfOperationCBC)) { - throw Error('AES must be instanitated with `new`'); - } - - this.description = "Cipher Block Chaining"; - this.name = "cbc"; - - if (!iv) { - iv = createArray(16); - - } else if (iv.length != 16) { - throw new Error('invalid initialation vector size (must be 16 bytes)'); - } - - this._lastCipherblock = coerceArray(iv, true); - - this._aes = new AES(key); - } - - ModeOfOperationCBC.prototype.encrypt = function(plaintext) { - plaintext = coerceArray(plaintext); - - if ((plaintext.length % 16) !== 0) { - throw new Error('invalid plaintext size (must be multiple of 16 bytes)'); - } - - var ciphertext = createArray(plaintext.length); - var block = createArray(16); - - for (var i = 0; i < plaintext.length; i += 16) { - copyArray(plaintext, block, 0, i, i + 16); - - for (var j = 0; j < 16; j++) { - block[j] ^= this._lastCipherblock[j]; - } - - this._lastCipherblock = this._aes.encrypt(block); - copyArray(this._lastCipherblock, ciphertext, i); - } - - return ciphertext; - } - - ModeOfOperationCBC.prototype.decrypt = function(ciphertext) { - ciphertext = coerceArray(ciphertext); - - if ((ciphertext.length % 16) !== 0) { - throw new Error('invalid ciphertext size (must be multiple of 16 bytes)'); - } - - var plaintext = createArray(ciphertext.length); - var block = createArray(16); - - for (var i = 0; i < ciphertext.length; i += 16) { - copyArray(ciphertext, block, 0, i, i + 16); - block = this._aes.decrypt(block); - - for (var j = 0; j < 16; j++) { - plaintext[i + j] = block[j] ^ this._lastCipherblock[j]; - } - - copyArray(ciphertext, this._lastCipherblock, 0, i, i + 16); - } - - return plaintext; - } - - - /** - * Mode Of Operation - Cipher Feedback (CFB) - */ - var ModeOfOperationCFB = function(key, iv, segmentSize) { - if (!(this instanceof ModeOfOperationCFB)) { - throw Error('AES must be instanitated with `new`'); - } - - this.description = "Cipher Feedback"; - this.name = "cfb"; - - if (!iv) { - iv = createArray(16); - - } else if (iv.length != 16) { - throw new Error('invalid initialation vector size (must be 16 size)'); - } - - if (!segmentSize) { segmentSize = 1; } - - this.segmentSize = segmentSize; - - this._shiftRegister = coerceArray(iv, true); - - this._aes = new AES(key); - } - - ModeOfOperationCFB.prototype.encrypt = function(plaintext) { - if ((plaintext.length % this.segmentSize) != 0) { - throw new Error('invalid plaintext size (must be segmentSize bytes)'); - } - - var encrypted = coerceArray(plaintext, true); - - var xorSegment; - for (var i = 0; i < encrypted.length; i += this.segmentSize) { - xorSegment = this._aes.encrypt(this._shiftRegister); - for (var j = 0; j < this.segmentSize; j++) { - encrypted[i + j] ^= xorSegment[j]; - } - - // Shift the register - copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize); - copyArray(encrypted, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize); - } - - return encrypted; - } - - ModeOfOperationCFB.prototype.decrypt = function(ciphertext) { - if ((ciphertext.length % this.segmentSize) != 0) { - throw new Error('invalid ciphertext size (must be segmentSize bytes)'); - } - - var plaintext = coerceArray(ciphertext, true); - - var xorSegment; - for (var i = 0; i < plaintext.length; i += this.segmentSize) { - xorSegment = this._aes.encrypt(this._shiftRegister); - - for (var j = 0; j < this.segmentSize; j++) { - plaintext[i + j] ^= xorSegment[j]; - } - - // Shift the register - copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize); - copyArray(ciphertext, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize); - } - - return plaintext; - } - - /** - * Mode Of Operation - Output Feedback (OFB) - */ - var ModeOfOperationOFB = function(key, iv) { - if (!(this instanceof ModeOfOperationOFB)) { - throw Error('AES must be instanitated with `new`'); - } - - this.description = "Output Feedback"; - this.name = "ofb"; - - if (!iv) { - iv = createArray(16); - - } else if (iv.length != 16) { - throw new Error('invalid initialation vector size (must be 16 bytes)'); - } - - this._lastPrecipher = coerceArray(iv, true); - this._lastPrecipherIndex = 16; - - this._aes = new AES(key); - } - - ModeOfOperationOFB.prototype.encrypt = function(plaintext) { - var encrypted = coerceArray(plaintext, true); - - for (var i = 0; i < encrypted.length; i++) { - if (this._lastPrecipherIndex === 16) { - this._lastPrecipher = this._aes.encrypt(this._lastPrecipher); - this._lastPrecipherIndex = 0; - } - encrypted[i] ^= this._lastPrecipher[this._lastPrecipherIndex++]; - } - - return encrypted; - } - - // Decryption is symetric - ModeOfOperationOFB.prototype.decrypt = ModeOfOperationOFB.prototype.encrypt; - - - /** - * Counter object for CTR common mode of operation - */ - var Counter = function(initialValue) { - if (!(this instanceof Counter)) { - throw Error('Counter must be instanitated with `new`'); - } - - // We allow 0, but anything false-ish uses the default 1 - if (initialValue !== 0 && !initialValue) { initialValue = 1; } - - if (typeof(initialValue) === 'number') { - this._counter = createArray(16); - this.setValue(initialValue); - - } else { - this.setBytes(initialValue); - } - } - - Counter.prototype.setValue = function(value) { - if (typeof(value) !== 'number' || parseInt(value) != value) { - throw new Error('invalid counter value (must be an integer)'); - } - - // We cannot safely handle numbers beyond the safe range for integers - if (value > Number.MAX_SAFE_INTEGER) { - throw new Error('integer value out of safe range'); - } - - for (var index = 15; index >= 0; --index) { - this._counter[index] = value % 256; - value = parseInt(value / 256); - } - } - - Counter.prototype.setBytes = function(bytes) { - bytes = coerceArray(bytes, true); - - if (bytes.length != 16) { - throw new Error('invalid counter bytes size (must be 16 bytes)'); - } - - this._counter = bytes; - }; - - Counter.prototype.increment = function() { - for (var i = 15; i >= 0; i--) { - if (this._counter[i] === 255) { - this._counter[i] = 0; - } else { - this._counter[i]++; - break; - } - } - } - - - /** - * Mode Of Operation - Counter (CTR) - */ - var ModeOfOperationCTR = function(key, counter) { - if (!(this instanceof ModeOfOperationCTR)) { - throw Error('AES must be instanitated with `new`'); - } - - this.description = "Counter"; - this.name = "ctr"; - - if (!(counter instanceof Counter)) { - counter = new Counter(counter) - } - - this._counter = counter; - - this._remainingCounter = null; - this._remainingCounterIndex = 16; - - this._aes = new AES(key); - } - - ModeOfOperationCTR.prototype.encrypt = function(plaintext) { - var encrypted = coerceArray(plaintext, true); - - for (var i = 0; i < encrypted.length; i++) { - if (this._remainingCounterIndex === 16) { - this._remainingCounter = this._aes.encrypt(this._counter._counter); - this._remainingCounterIndex = 0; - this._counter.increment(); - } - encrypted[i] ^= this._remainingCounter[this._remainingCounterIndex++]; - } - - return encrypted; - } - - // Decryption is symetric - ModeOfOperationCTR.prototype.decrypt = ModeOfOperationCTR.prototype.encrypt; - - - /////////////////////// - // Padding - - // See:https://tools.ietf.org/html/rfc2315 - function pkcs7pad(data) { - data = coerceArray(data, true); - var padder = 16 - (data.length % 16); - var result = createArray(data.length + padder); - copyArray(data, result); - for (var i = data.length; i < result.length; i++) { - result[i] = padder; - } - return result; - } - - function pkcs7strip(data) { - data = coerceArray(data, true); - if (data.length < 16) { throw new Error('PKCS#7 invalid length'); } - - var padder = data[data.length - 1]; - if (padder > 16) { throw new Error('PKCS#7 padding byte out of range'); } - - var length = data.length - padder; - for (var i = 0; i < padder; i++) { - if (data[length + i] !== padder) { - throw new Error('PKCS#7 invalid padding byte'); - } - } - - var result = createArray(length); - copyArray(data, result, 0, 0, length); - return result; - } - - /////////////////////// - // Exporting - - - // The block cipher - var aesjs = { - AES: AES, - Counter: Counter, - - ModeOfOperation: { - ecb: ModeOfOperationECB, - cbc: ModeOfOperationCBC, - cfb: ModeOfOperationCFB, - ofb: ModeOfOperationOFB, - ctr: ModeOfOperationCTR - }, - - utils: { - hex: convertHex, - utf8: convertUtf8 - }, - - padding: { - pkcs7: { - pad: pkcs7pad, - strip: pkcs7strip - } - }, - - _arrayTest: { - coerceArray: coerceArray, - createArray: createArray, - copyArray: copyArray, - } - }; - - - // node.js - if (typeof exports !== 'undefined') { - module.exports = aesjs - - // RequireJS/AMD - // http://www.requirejs.org/docs/api.html - // https://github.com/amdjs/amdjs-api/wiki/AMD - } else if (typeof(define) === 'function' && define.amd) { - define(aesjs); - - // Web Browsers - } else { - - // If there was an existing library at "aesjs" make sure it's still available - if (root.aesjs) { - aesjs._aesjs = root.aesjs; - } - - root.aesjs = aesjs; - } - - -})(this); diff --git a/assets/www/dist/dist_js/app/vendor/ion-digit-keyboard.min.js b/assets/www/dist/dist_js/app/vendor/ion-digit-keyboard.min.js deleted file mode 100644 index 629f661888024d2fbd731baffb8b579ed3678ae8..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/ion-digit-keyboard.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){var i=e.createElement("style");if(e.getElementsByTagName("head")[0].appendChild(i),i.styleSheet)i.styleSheet.disabled||(i.styleSheet.cssText=t);else try{i.innerHTML=t}catch(d){i.innerText=t}}(document,".digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters.hidden,.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper.hidden{visibility:hidden}.digit-keyboard{position:absolute;left:0;right:0;bottom:0;background:0 0;font-size:24px;z-index:5000}.digit-keyboard *{box-sizing:border-box}.digit-keyboard .digit-keyboard-row{display:flex;flex-direction:row;border-bottom:1px solid #333}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper{flex:1;text-align:center;position:relative;height:60px}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key{display:block;margin:0 auto;position:absolute;left:0;top:0;right:0;bottom:0;border-right:1px solid #333;border-left:1px solid #333;line-height:60px;-webkit-transition:background-color .1s linear;-moz-transition:background-color .1s linear;-o-transition:background-color .1s linear;-ms-transition:background-color .1s linear;transition:background-color .1s linear}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number{font-size:1em;vertical-align:middle;display:inline-block;line-height:normal;text-align:center;margin-top:-.4em}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters{font-size:9.6px;line-height:9.6px;height:9.6px;margin-top:-.25em}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-action{position:absolute;left:0;top:0;right:0;bottom:0;line-height:60px;font-size:24px}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper:first-child .digit-keyboard-key{border-right:none}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper:last-child .digit-keyboard-key{border-left:none}.digit-keyboard .digit-keyboard-row:first-child{border-top:1px solid #333}.digit-keyboard .digit-keyboard-row:last-child{border:none}.digit-keyboard .digit-keyboard-row:last-child .digit-keyboard-key-wrapper .digit-keyboard-key{border-bottom:1px solid #333}.digit-keyboard.align-center{margin:0 auto}.digit-keyboard.align-left{margin-right:auto}.digit-keyboard.align-right{margin-left:auto}.digit-keyboard.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number{margin-top:-.3em}.digit-keyboard.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters{display:none}.digit-keyboard.round-buttons .digit-keyboard-row{border:none}.digit-keyboard.round-buttons .digit-keyboard-row .digit-keyboard-key-wrapper{margin:10px 0 0}.digit-keyboard.round-buttons .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key{width:60px;-webkit-border-radius:100%;-moz-border-radius:100%;border-radius:100%;border:1px solid #333}.digit-keyboard.round-buttons .digit-keyboard-row:last-child .digit-keyboard-key-wrapper{margin-bottom:10px}.digit-keyboard.round-buttons.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number{height:57.6px;line-height:57.6px}.digit-keyboard.keyboard-light *{border-color:#e6e6e6!important}.digit-keyboard.keyboard-light .digit-keyboard-key{background:#fff;color:#444}.digit-keyboard.keyboard-light .digit-keyboard-key.activated{background:#e6e6e6}.digit-keyboard.keyboard-stable *{border-color:#dfdfdf!important}.digit-keyboard.keyboard-stable .digit-keyboard-key{background:#f8f8f8;color:#444}.digit-keyboard.keyboard-stable .digit-keyboard-key.activated{background:#dfdfdf}.digit-keyboard.keyboard-positive *{border-color:#0c60ee!important}.digit-keyboard.keyboard-positive .digit-keyboard-key{background:#387ef5;color:#fff}.digit-keyboard.keyboard-positive .digit-keyboard-key.activated{background:#0c60ee}.digit-keyboard.keyboard-calm *{border-color:#0a9dc7!important}.digit-keyboard.keyboard-calm .digit-keyboard-key{background:#11c1f3;color:#fff}.digit-keyboard.keyboard-calm .digit-keyboard-key.activated{background:#0a9dc7}.digit-keyboard.keyboard-balanced *{border-color:#28a54c!important}.digit-keyboard.keyboard-balanced .digit-keyboard-key{background:#33cd5f;color:#fff}.digit-keyboard.keyboard-balanced .digit-keyboard-key.activated{background:#28a54c}.digit-keyboard.keyboard-energized *{border-color:#e6b500!important}.digit-keyboard.keyboard-energized .digit-keyboard-key{background:#ffc900;color:#fff}.digit-keyboard.keyboard-energized .digit-keyboard-key.activated{background:#e6b500}.digit-keyboard.keyboard-assertive *{border-color:#e42112!important}.digit-keyboard.keyboard-assertive .digit-keyboard-key{background:#ef473a;color:#fff}.digit-keyboard.keyboard-assertive .digit-keyboard-key.activated{background:#e42112}.digit-keyboard.keyboard-royal *{border-color:#6b46e5!important}.digit-keyboard.keyboard-royal .digit-keyboard-key{background:#886aea;color:#fff}.digit-keyboard.keyboard-royal .digit-keyboard-key.activated{background:#6b46e5}.digit-keyboard.keyboard-dark *{border-color:#2b2b2b!important}.digit-keyboard.keyboard-dark .digit-keyboard-key{background:#444;color:#fff}.digit-keyboard.keyboard-dark .digit-keyboard-key.activated{background:#2b2b2b}.digit-keyboard.keyboard-opaque-black *{border-color:rgba(0,0,0,.75)!important}.digit-keyboard.keyboard-opaque-black .digit-keyboard-key{background:rgba(0,0,0,.15);color:rgba(0,0,0,.75)}.digit-keyboard.keyboard-opaque-black .digit-keyboard-key.activated{background:rgba(0,0,0,.25)}.digit-keyboard.keyboard-opaque-white *{border-color:rgba(255,255,255,.75)!important}.digit-keyboard.keyboard-opaque-white .digit-keyboard-key{background:rgba(255,255,255,.15);color:rgba(255,255,255,.75)}.digit-keyboard.keyboard-opaque-white .digit-keyboard-key.activated{background:rgba(255,255,255,.25)}.digit-keyboard.animation-slide-up{-webkit-transition:transform linear 150ms;transition:transform linear 150ms;transform:translate3d(0,0,0)}.digit-keyboard.animation-slide-up.ng-hide{transform:translate3d(0,100%,0)}.digit-keyboard.animation-pop{-webkit-transition:transform linear 150ms;transition:transform linear 150ms;transform:scale3d(1,1,1)}.digit-keyboard.animation-pop.ng-hide{transform:scale3d(0,0,1)}"),!function(e){try{e=angular.module("ion-digit-keyboard.templates")}catch(t){e=angular.module("ion-digit-keyboard.templates",[])}e.run(["$templateCache",function(e){e.put("keyboard.tpl.html","<div class=\"digit-keyboard align-{{align}} keyboard-{{theme}} animation-{{animation}} {{roundButtons ? 'round-buttons' : ''}} {{showLetters == false ? 'no-letters' : ''}} {{(ngShow == false || ngHide == true) ? 'ng-hide' : ''}}\" style=\"width: {{width}};\"><div class=digit-keyboard-row><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(1)><div class=digit-keyboard-key-number>1<div class=digit-keyboard-key-letters></div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(2)><div class=digit-keyboard-key-number>2<div class=digit-keyboard-key-letters>ABC</div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(3)><div class=digit-keyboard-key-number>3<div class=digit-keyboard-key-letters>DEF</div></div></div></div></div><div class=digit-keyboard-row><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(4)><div class=digit-keyboard-key-number>4<div class=digit-keyboard-key-letters>GHI</div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(5)><div class=digit-keyboard-key-number>5<div class=digit-keyboard-key-letters>JKL</div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(6)><div class=digit-keyboard-key-number>6<div class=digit-keyboard-key-letters>MNO</div></div></div></div></div><div class=digit-keyboard-row><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(7)><div class=digit-keyboard-key-number>7<div class=digit-keyboard-key-letters>PQRS</div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(8)><div class=digit-keyboard-key-number>8<div class=digit-keyboard-key-letters>TUV</div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(9)><div class=digit-keyboard-key-number>9<div class=digit-keyboard-key-letters>WXYZ</div></div></div></div></div><div class=digit-keyboard-row><div class=\"digit-keyboard-key-wrapper {{showLeftAction == false ? 'hidden' : ''}}\"><div class=digit-keyboard-key ng-click=leftAction($event) style={{leftStyle}}><div class=digit-keyboard-key-action ng-bind-html=leftHtml style={{leftFontSize}}></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(0)><div class=digit-keyboard-key-number style=\"margin-top: -0.30em;\">0</div></div></div><div class=\"digit-keyboard-key-wrapper {{showRightAction == false ? 'hidden' : ''}}\"><div class=digit-keyboard-key ng-click=rightAction($event) style={{rightStyle}}><div class=digit-keyboard-key-action ng-bind-html=rightHtml style={{rightFontSize}}></div></div></div></div></div>")}])}(),angular.module("ion-digit-keyboard.directive",[]).directive("ionDigitKeyboard",["$timeout","$ionicScrollDelegate","$templateCache",function(e,t,i){var d=150;return{restrict:"EA",template:i.get("keyboard.tpl.html"),replace:!0,scope:{settings:"=settings",ngShow:"=",ngHide:"="},link:function(i,o,r){function a(){1==b&&(k.style.bottom="0px",k.style.height=s)}function n(){e(function(){if(1==b){var e=o[0].offsetHeight;s=k.style.height,k.style.height="auto",k.style.bottom=e+1+"px"}},d+10)}function y(){i.ngShow===!0?n():i.ngShow===!1&&a(),t.resize()}function g(){i.ngHide===!0?a():i.ngHide===!1&&n(),t.resize()}"undefined"==typeof i.settings&&(i.settings={});var k,s,b=!0,l="ion-content",c={},u={};if(i.leftStyle="",i.rightStyle="",i.leftFontSize="",i.rightFontSize="",i.showLetters="undefined"==typeof i.settings.showLetters?!1:i.settings.showLetters,i.roundButtons="undefined"==typeof i.settings.roundButtons?!1:i.settings.roundButtons,i.numberAction=i.settings.action||function(){},i.width=i.settings.width||"100%",i.align=i.settings.align||"center",i.animation=i.settings.animation||"slide-up",i.theme=i.settings.theme||"stable","undefined"!=typeof i.settings.leftButton&&"object"==typeof i.settings.leftButton.style&&("undefined"!=typeof i.settings.leftButton.style.color&&(i.leftStyle+="color: "+i.settings.leftButton.style.color+";"),"undefined"!=typeof i.settings.leftButton.style.bgColor&&(c["default"]=i.settings.leftButton.style.bgColor,i.leftStyle+="background-color: "+c["default"]+";"),"undefined"!=typeof i.settings.leftButton.style.activeBgColor&&(c.active=i.settings.leftButton.style.activeBgColor),"undefined"!=typeof i.settings.leftButton.style.borderColor&&(i.leftStyle+="border-color: "+i.settings.leftButton.style.borderColor+" !important;"),"undefined"!=typeof i.settings.leftButton.style.fontSize&&(i.leftFontSize="font-size: "+i.settings.leftButton.style.fontSize+" !important;")),"undefined"!=typeof i.settings.rightButton&&"object"==typeof i.settings.rightButton.style&&("undefined"!=typeof i.settings.rightButton.style.color&&(i.rightStyle+="color: "+i.settings.rightButton.style.color+";"),"undefined"!=typeof i.settings.rightButton.style.bgColor&&(u["default"]=i.settings.rightButton.style.bgColor,i.rightStyle+="background-color: "+u["default"]+";"),"undefined"!=typeof i.settings.rightButton.style.activeBgColor&&(u.active=i.settings.rightButton.style.activeBgColor),"undefined"!=typeof i.settings.rightButton.style.borderColor&&(i.rightStyle+="border-color: "+i.settings.rightButton.style.borderColor+" !important;"),"undefined"!=typeof i.settings.rightButton.style.fontSize&&(i.rightFontSize="font-size: "+i.settings.rightButton.style.fontSize+" !important;")),i.showLeftAction=!1,"undefined"!=typeof i.settings.leftButton&&(i.leftHtml=i.settings.leftButton.html,i.showLeftAction=!0,i.leftAction=function(e){if(c.active){var t=e.target;"I"==t.tagName?t=t.parentNode.parentNode:t.className.indexOf("digit-keyboard-key-action")>-1&&(t=t.parentNode),"undefined"==typeof c["default"]&&(c["default"]=t.style.backgroundColor),t.style.backgroundColor=c.active,setTimeout(function(){t.style.backgroundColor=c["default"]},100)}i.settings.leftButton.action()}),i.showRightAction=!1,"undefined"!=typeof i.settings.rightButton&&(i.rightHtml=i.settings.rightButton.html,i.showRightAction=!0,i.rightAction=function(e){if(u.active){var t=e.target;"I"==t.tagName?t=t.parentNode.parentNode:t.className.indexOf("digit-keyboard-key-action")>-1&&(t=t.parentNode),"undefined"==typeof u["default"]&&(u["default"]=t.style.backgroundColor),t.style.backgroundColor=u.active,setTimeout(function(){t.style.backgroundColor=u["default"]},100)}i.settings.rightButton.action()}),"object"==typeof i.settings.resizeContent||"boolean"==typeof i.settings.resizeContent)if("object"==typeof i.settings.resizeContent)var b="undefined"==typeof i.settings.resizeContent.enable?!0:i.settings.resizeContent.enable,l="undefined"==typeof i.settings.resizeContent.element?"ion-content":i.settings.resizeContent.element;else"boolean"==typeof i.settings.resizeContent&&(b=i.settings.resizeContent);k=o[0].parentElement.querySelectorAll(l)[0],i.$watch("ngShow",y),i.$watch("ngHide",g)}}}]),angular.module("ion-digit-keyboard",["ionic","ion-digit-keyboard.templates","ion-digit-keyboard.directive"]); \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/vendor/leaflet-src.js b/assets/www/dist/dist_js/app/vendor/leaflet-src.js deleted file mode 100644 index d3d5635741c2dc68a16e0a3b72ed000ede34e3a4..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/leaflet-src.js +++ /dev/null @@ -1,9168 +0,0 @@ -/* - Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com - (c) 2010-2013, Vladimir Agafonkin - (c) 2010-2011, CloudMade -*/ -(function (window, document, undefined) { -var oldL = window.L, - L = {}; - -L.version = '0.7.7'; - -// define Leaflet for Node module pattern loaders, including Browserify -if (typeof module === 'object' && typeof module.exports === 'object') { - module.exports = L; - -// define Leaflet as an AMD module -} else if (typeof define === 'function' && define.amd) { - define(L); -} - -// define Leaflet as a global L variable, saving the original L to restore later if needed - -L.noConflict = function () { - window.L = oldL; - return this; -}; - -window.L = L; - - -/* - * L.Util contains various utility functions used throughout Leaflet code. - */ - -L.Util = { - extend: function (dest) { // (Object[, Object, ...]) -> - var sources = Array.prototype.slice.call(arguments, 1), - i, j, len, src; - - for (j = 0, len = sources.length; j < len; j++) { - src = sources[j] || {}; - for (i in src) { - if (src.hasOwnProperty(i)) { - dest[i] = src[i]; - } - } - } - return dest; - }, - - bind: function (fn, obj) { // (Function, Object) -> Function - var args = arguments.length > 2 ? Array.prototype.slice.call(arguments, 2) : null; - return function () { - return fn.apply(obj, args || arguments); - }; - }, - - stamp: (function () { - var lastId = 0, - key = '_leaflet_id'; - return function (obj) { - obj[key] = obj[key] || ++lastId; - return obj[key]; - }; - }()), - - invokeEach: function (obj, method, context) { - var i, args; - - if (typeof obj === 'object') { - args = Array.prototype.slice.call(arguments, 3); - - for (i in obj) { - method.apply(context, [i, obj[i]].concat(args)); - } - return true; - } - - return false; - }, - - limitExecByInterval: function (fn, time, context) { - var lock, execOnUnlock; - - return function wrapperFn() { - var args = arguments; - - if (lock) { - execOnUnlock = true; - return; - } - - lock = true; - - setTimeout(function () { - lock = false; - - if (execOnUnlock) { - wrapperFn.apply(context, args); - execOnUnlock = false; - } - }, time); - - fn.apply(context, args); - }; - }, - - falseFn: function () { - return false; - }, - - formatNum: function (num, digits) { - var pow = Math.pow(10, digits || 5); - return Math.round(num * pow) / pow; - }, - - trim: function (str) { - return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); - }, - - splitWords: function (str) { - return L.Util.trim(str).split(/\s+/); - }, - - setOptions: function (obj, options) { - obj.options = L.extend({}, obj.options, options); - return obj.options; - }, - - getParamString: function (obj, existingUrl, uppercase) { - var params = []; - for (var i in obj) { - params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i])); - } - return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&'); - }, - template: function (str, data) { - return str.replace(/\{ *([\w_]+) *\}/g, function (str, key) { - var value = data[key]; - if (value === undefined) { - throw new Error('No value provided for variable ' + str); - } else if (typeof value === 'function') { - value = value(data); - } - return value; - }); - }, - - isArray: Array.isArray || function (obj) { - return (Object.prototype.toString.call(obj) === '[object Array]'); - }, - - emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' -}; - -(function () { - - // inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/ - - function getPrefixed(name) { - var i, fn, - prefixes = ['webkit', 'moz', 'o', 'ms']; - - for (i = 0; i < prefixes.length && !fn; i++) { - fn = window[prefixes[i] + name]; - } - - return fn; - } - - var lastTime = 0; - - function timeoutDefer(fn) { - var time = +new Date(), - timeToCall = Math.max(0, 16 - (time - lastTime)); - - lastTime = time + timeToCall; - return window.setTimeout(fn, timeToCall); - } - - var requestFn = window.requestAnimationFrame || - getPrefixed('RequestAnimationFrame') || timeoutDefer; - - var cancelFn = window.cancelAnimationFrame || - getPrefixed('CancelAnimationFrame') || - getPrefixed('CancelRequestAnimationFrame') || - function (id) { window.clearTimeout(id); }; - - - L.Util.requestAnimFrame = function (fn, context, immediate, element) { - fn = L.bind(fn, context); - - if (immediate && requestFn === timeoutDefer) { - fn(); - } else { - return requestFn.call(window, fn, element); - } - }; - - L.Util.cancelAnimFrame = function (id) { - if (id) { - cancelFn.call(window, id); - } - }; - -}()); - -// shortcuts for most used utility functions -L.extend = L.Util.extend; -L.bind = L.Util.bind; -L.stamp = L.Util.stamp; -L.setOptions = L.Util.setOptions; - - -/* - * L.Class powers the OOP facilities of the library. - * Thanks to John Resig and Dean Edwards for inspiration! - */ - -L.Class = function () {}; - -L.Class.extend = function (props) { - - // extended class with the new prototype - var NewClass = function () { - - // call the constructor - if (this.initialize) { - this.initialize.apply(this, arguments); - } - - // call all constructor hooks - if (this._initHooks) { - this.callInitHooks(); - } - }; - - // instantiate class without calling constructor - var F = function () {}; - F.prototype = this.prototype; - - var proto = new F(); - proto.constructor = NewClass; - - NewClass.prototype = proto; - - //inherit parent's statics - for (var i in this) { - if (this.hasOwnProperty(i) && i !== 'prototype') { - NewClass[i] = this[i]; - } - } - - // mix static properties into the class - if (props.statics) { - L.extend(NewClass, props.statics); - delete props.statics; - } - - // mix includes into the prototype - if (props.includes) { - L.Util.extend.apply(null, [proto].concat(props.includes)); - delete props.includes; - } - - // merge options - if (props.options && proto.options) { - props.options = L.extend({}, proto.options, props.options); - } - - // mix given properties into the prototype - L.extend(proto, props); - - proto._initHooks = []; - - var parent = this; - // jshint camelcase: false - NewClass.__super__ = parent.prototype; - - // add method for calling all hooks - proto.callInitHooks = function () { - - if (this._initHooksCalled) { return; } - - if (parent.prototype.callInitHooks) { - parent.prototype.callInitHooks.call(this); - } - - this._initHooksCalled = true; - - for (var i = 0, len = proto._initHooks.length; i < len; i++) { - proto._initHooks[i].call(this); - } - }; - - return NewClass; -}; - - -// method for adding properties to prototype -L.Class.include = function (props) { - L.extend(this.prototype, props); -}; - -// merge new default options to the Class -L.Class.mergeOptions = function (options) { - L.extend(this.prototype.options, options); -}; - -// add a constructor hook -L.Class.addInitHook = function (fn) { // (Function) || (String, args...) - var args = Array.prototype.slice.call(arguments, 1); - - var init = typeof fn === 'function' ? fn : function () { - this[fn].apply(this, args); - }; - - this.prototype._initHooks = this.prototype._initHooks || []; - this.prototype._initHooks.push(init); -}; - - -/* - * L.Mixin.Events is used to add custom events functionality to Leaflet classes. - */ - -var eventsKey = '_leaflet_events'; - -L.Mixin = {}; - -L.Mixin.Events = { - - addEventListener: function (types, fn, context) { // (String, Function[, Object]) or (Object[, Object]) - - // types can be a map of types/handlers - if (L.Util.invokeEach(types, this.addEventListener, this, fn, context)) { return this; } - - var events = this[eventsKey] = this[eventsKey] || {}, - contextId = context && context !== this && L.stamp(context), - i, len, event, type, indexKey, indexLenKey, typeIndex; - - // types can be a string of space-separated words - types = L.Util.splitWords(types); - - for (i = 0, len = types.length; i < len; i++) { - event = { - action: fn, - context: context || this - }; - type = types[i]; - - if (contextId) { - // store listeners of a particular context in a separate hash (if it has an id) - // gives a major performance boost when removing thousands of map layers - - indexKey = type + '_idx'; - indexLenKey = indexKey + '_len'; - - typeIndex = events[indexKey] = events[indexKey] || {}; - - if (!typeIndex[contextId]) { - typeIndex[contextId] = []; - - // keep track of the number of keys in the index to quickly check if it's empty - events[indexLenKey] = (events[indexLenKey] || 0) + 1; - } - - typeIndex[contextId].push(event); - - - } else { - events[type] = events[type] || []; - events[type].push(event); - } - } - - return this; - }, - - hasEventListeners: function (type) { // (String) -> Boolean - var events = this[eventsKey]; - return !!events && ((type in events && events[type].length > 0) || - (type + '_idx' in events && events[type + '_idx_len'] > 0)); - }, - - removeEventListener: function (types, fn, context) { // ([String, Function, Object]) or (Object[, Object]) - - if (!this[eventsKey]) { - return this; - } - - if (!types) { - return this.clearAllEventListeners(); - } - - if (L.Util.invokeEach(types, this.removeEventListener, this, fn, context)) { return this; } - - var events = this[eventsKey], - contextId = context && context !== this && L.stamp(context), - i, len, type, listeners, j, indexKey, indexLenKey, typeIndex, removed; - - types = L.Util.splitWords(types); - - for (i = 0, len = types.length; i < len; i++) { - type = types[i]; - indexKey = type + '_idx'; - indexLenKey = indexKey + '_len'; - - typeIndex = events[indexKey]; - - if (!fn) { - // clear all listeners for a type if function isn't specified - delete events[type]; - delete events[indexKey]; - delete events[indexLenKey]; - - } else { - listeners = contextId && typeIndex ? typeIndex[contextId] : events[type]; - - if (listeners) { - for (j = listeners.length - 1; j >= 0; j--) { - if ((listeners[j].action === fn) && (!context || (listeners[j].context === context))) { - removed = listeners.splice(j, 1); - // set the old action to a no-op, because it is possible - // that the listener is being iterated over as part of a dispatch - removed[0].action = L.Util.falseFn; - } - } - - if (context && typeIndex && (listeners.length === 0)) { - delete typeIndex[contextId]; - events[indexLenKey]--; - } - } - } - } - - return this; - }, - - clearAllEventListeners: function () { - delete this[eventsKey]; - return this; - }, - - fireEvent: function (type, data) { // (String[, Object]) - if (!this.hasEventListeners(type)) { - return this; - } - - var event = L.Util.extend({}, data, { type: type, target: this }); - - var events = this[eventsKey], - listeners, i, len, typeIndex, contextId; - - if (events[type]) { - // make sure adding/removing listeners inside other listeners won't cause infinite loop - listeners = events[type].slice(); - - for (i = 0, len = listeners.length; i < len; i++) { - listeners[i].action.call(listeners[i].context, event); - } - } - - // fire event for the context-indexed listeners as well - typeIndex = events[type + '_idx']; - - for (contextId in typeIndex) { - listeners = typeIndex[contextId].slice(); - - if (listeners) { - for (i = 0, len = listeners.length; i < len; i++) { - listeners[i].action.call(listeners[i].context, event); - } - } - } - - return this; - }, - - addOneTimeEventListener: function (types, fn, context) { - - if (L.Util.invokeEach(types, this.addOneTimeEventListener, this, fn, context)) { return this; } - - var handler = L.bind(function () { - this - .removeEventListener(types, fn, context) - .removeEventListener(types, handler, context); - }, this); - - return this - .addEventListener(types, fn, context) - .addEventListener(types, handler, context); - } -}; - -L.Mixin.Events.on = L.Mixin.Events.addEventListener; -L.Mixin.Events.off = L.Mixin.Events.removeEventListener; -L.Mixin.Events.once = L.Mixin.Events.addOneTimeEventListener; -L.Mixin.Events.fire = L.Mixin.Events.fireEvent; - - -/* - * L.Browser handles different browser and feature detections for internal Leaflet use. - */ - -(function () { - - var ie = 'ActiveXObject' in window, - ielt9 = ie && !document.addEventListener, - - // terrible browser detection to work around Safari / iOS / Android browser bugs - ua = navigator.userAgent.toLowerCase(), - webkit = ua.indexOf('webkit') !== -1, - chrome = ua.indexOf('chrome') !== -1, - phantomjs = ua.indexOf('phantom') !== -1, - android = ua.indexOf('android') !== -1, - android23 = ua.search('android [23]') !== -1, - gecko = ua.indexOf('gecko') !== -1, - - mobile = typeof orientation !== undefined + '', - msPointer = !window.PointerEvent && window.MSPointerEvent, - pointer = (window.PointerEvent && window.navigator.pointerEnabled) || - msPointer, - retina = ('devicePixelRatio' in window && window.devicePixelRatio > 1) || - ('matchMedia' in window && window.matchMedia('(min-resolution:144dpi)') && - window.matchMedia('(min-resolution:144dpi)').matches), - - doc = document.documentElement, - ie3d = ie && ('transition' in doc.style), - webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23, - gecko3d = 'MozPerspective' in doc.style, - opera3d = 'OTransition' in doc.style, - any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d) && !phantomjs; - - var touch = !window.L_NO_TOUCH && !phantomjs && (pointer || 'ontouchstart' in window || - (window.DocumentTouch && document instanceof window.DocumentTouch)); - - L.Browser = { - ie: ie, - ielt9: ielt9, - webkit: webkit, - gecko: gecko && !webkit && !window.opera && !ie, - - android: android, - android23: android23, - - chrome: chrome, - - ie3d: ie3d, - webkit3d: webkit3d, - gecko3d: gecko3d, - opera3d: opera3d, - any3d: any3d, - - mobile: mobile, - mobileWebkit: mobile && webkit, - mobileWebkit3d: mobile && webkit3d, - mobileOpera: mobile && window.opera, - - touch: touch, - msPointer: msPointer, - pointer: pointer, - - retina: retina - }; - -}()); - - -/* - * L.Point represents a point with x and y coordinates. - */ - -L.Point = function (/*Number*/ x, /*Number*/ y, /*Boolean*/ round) { - this.x = (round ? Math.round(x) : x); - this.y = (round ? Math.round(y) : y); -}; - -L.Point.prototype = { - - clone: function () { - return new L.Point(this.x, this.y); - }, - - // non-destructive, returns a new point - add: function (point) { - return this.clone()._add(L.point(point)); - }, - - // destructive, used directly for performance in situations where it's safe to modify existing point - _add: function (point) { - this.x += point.x; - this.y += point.y; - return this; - }, - - subtract: function (point) { - return this.clone()._subtract(L.point(point)); - }, - - _subtract: function (point) { - this.x -= point.x; - this.y -= point.y; - return this; - }, - - divideBy: function (num) { - return this.clone()._divideBy(num); - }, - - _divideBy: function (num) { - this.x /= num; - this.y /= num; - return this; - }, - - multiplyBy: function (num) { - return this.clone()._multiplyBy(num); - }, - - _multiplyBy: function (num) { - this.x *= num; - this.y *= num; - return this; - }, - - round: function () { - return this.clone()._round(); - }, - - _round: function () { - this.x = Math.round(this.x); - this.y = Math.round(this.y); - return this; - }, - - floor: function () { - return this.clone()._floor(); - }, - - _floor: function () { - this.x = Math.floor(this.x); - this.y = Math.floor(this.y); - return this; - }, - - distanceTo: function (point) { - point = L.point(point); - - var x = point.x - this.x, - y = point.y - this.y; - - return Math.sqrt(x * x + y * y); - }, - - equals: function (point) { - point = L.point(point); - - return point.x === this.x && - point.y === this.y; - }, - - contains: function (point) { - point = L.point(point); - - return Math.abs(point.x) <= Math.abs(this.x) && - Math.abs(point.y) <= Math.abs(this.y); - }, - - toString: function () { - return 'Point(' + - L.Util.formatNum(this.x) + ', ' + - L.Util.formatNum(this.y) + ')'; - } -}; - -L.point = function (x, y, round) { - if (x instanceof L.Point) { - return x; - } - if (L.Util.isArray(x)) { - return new L.Point(x[0], x[1]); - } - if (x === undefined || x === null) { - return x; - } - return new L.Point(x, y, round); -}; - - -/* - * L.Bounds represents a rectangular area on the screen in pixel coordinates. - */ - -L.Bounds = function (a, b) { //(Point, Point) or Point[] - if (!a) { return; } - - var points = b ? [a, b] : a; - - for (var i = 0, len = points.length; i < len; i++) { - this.extend(points[i]); - } -}; - -L.Bounds.prototype = { - // extend the bounds to contain the given point - extend: function (point) { // (Point) - point = L.point(point); - - if (!this.min && !this.max) { - this.min = point.clone(); - this.max = point.clone(); - } else { - this.min.x = Math.min(point.x, this.min.x); - this.max.x = Math.max(point.x, this.max.x); - this.min.y = Math.min(point.y, this.min.y); - this.max.y = Math.max(point.y, this.max.y); - } - return this; - }, - - getCenter: function (round) { // (Boolean) -> Point - return new L.Point( - (this.min.x + this.max.x) / 2, - (this.min.y + this.max.y) / 2, round); - }, - - getBottomLeft: function () { // -> Point - return new L.Point(this.min.x, this.max.y); - }, - - getTopRight: function () { // -> Point - return new L.Point(this.max.x, this.min.y); - }, - - getSize: function () { - return this.max.subtract(this.min); - }, - - contains: function (obj) { // (Bounds) or (Point) -> Boolean - var min, max; - - if (typeof obj[0] === 'number' || obj instanceof L.Point) { - obj = L.point(obj); - } else { - obj = L.bounds(obj); - } - - if (obj instanceof L.Bounds) { - min = obj.min; - max = obj.max; - } else { - min = max = obj; - } - - return (min.x >= this.min.x) && - (max.x <= this.max.x) && - (min.y >= this.min.y) && - (max.y <= this.max.y); - }, - - intersects: function (bounds) { // (Bounds) -> Boolean - bounds = L.bounds(bounds); - - var min = this.min, - max = this.max, - min2 = bounds.min, - max2 = bounds.max, - xIntersects = (max2.x >= min.x) && (min2.x <= max.x), - yIntersects = (max2.y >= min.y) && (min2.y <= max.y); - - return xIntersects && yIntersects; - }, - - isValid: function () { - return !!(this.min && this.max); - } -}; - -L.bounds = function (a, b) { // (Bounds) or (Point, Point) or (Point[]) - if (!a || a instanceof L.Bounds) { - return a; - } - return new L.Bounds(a, b); -}; - - -/* - * L.Transformation is an utility class to perform simple point transformations through a 2d-matrix. - */ - -L.Transformation = function (a, b, c, d) { - this._a = a; - this._b = b; - this._c = c; - this._d = d; -}; - -L.Transformation.prototype = { - transform: function (point, scale) { // (Point, Number) -> Point - return this._transform(point.clone(), scale); - }, - - // destructive transform (faster) - _transform: function (point, scale) { - scale = scale || 1; - point.x = scale * (this._a * point.x + this._b); - point.y = scale * (this._c * point.y + this._d); - return point; - }, - - untransform: function (point, scale) { - scale = scale || 1; - return new L.Point( - (point.x / scale - this._b) / this._a, - (point.y / scale - this._d) / this._c); - } -}; - - -/* - * L.DomUtil contains various utility functions for working with DOM. - */ - -L.DomUtil = { - get: function (id) { - return (typeof id === 'string' ? document.getElementById(id) : id); - }, - - getStyle: function (el, style) { - - var value = el.style[style]; - - if (!value && el.currentStyle) { - value = el.currentStyle[style]; - } - - if ((!value || value === 'auto') && document.defaultView) { - var css = document.defaultView.getComputedStyle(el, null); - value = css ? css[style] : null; - } - - return value === 'auto' ? null : value; - }, - - getViewportOffset: function (element) { - - var top = 0, - left = 0, - el = element, - docBody = document.body, - docEl = document.documentElement, - pos; - - do { - top += el.offsetTop || 0; - left += el.offsetLeft || 0; - - //add borders - top += parseInt(L.DomUtil.getStyle(el, 'borderTopWidth'), 10) || 0; - left += parseInt(L.DomUtil.getStyle(el, 'borderLeftWidth'), 10) || 0; - - pos = L.DomUtil.getStyle(el, 'position'); - - if (el.offsetParent === docBody && pos === 'absolute') { break; } - - if (pos === 'fixed') { - top += docBody.scrollTop || docEl.scrollTop || 0; - left += docBody.scrollLeft || docEl.scrollLeft || 0; - break; - } - - if (pos === 'relative' && !el.offsetLeft) { - var width = L.DomUtil.getStyle(el, 'width'), - maxWidth = L.DomUtil.getStyle(el, 'max-width'), - r = el.getBoundingClientRect(); - - if (width !== 'none' || maxWidth !== 'none') { - left += r.left + el.clientLeft; - } - - //calculate full y offset since we're breaking out of the loop - top += r.top + (docBody.scrollTop || docEl.scrollTop || 0); - - break; - } - - el = el.offsetParent; - - } while (el); - - el = element; - - do { - if (el === docBody) { break; } - - top -= el.scrollTop || 0; - left -= el.scrollLeft || 0; - - el = el.parentNode; - } while (el); - - return new L.Point(left, top); - }, - - documentIsLtr: function () { - if (!L.DomUtil._docIsLtrCached) { - L.DomUtil._docIsLtrCached = true; - L.DomUtil._docIsLtr = L.DomUtil.getStyle(document.body, 'direction') === 'ltr'; - } - return L.DomUtil._docIsLtr; - }, - - create: function (tagName, className, container) { - - var el = document.createElement(tagName); - el.className = className; - - if (container) { - container.appendChild(el); - } - - return el; - }, - - hasClass: function (el, name) { - if (el.classList !== undefined) { - return el.classList.contains(name); - } - var className = L.DomUtil._getClass(el); - return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className); - }, - - addClass: function (el, name) { - if (el.classList !== undefined) { - var classes = L.Util.splitWords(name); - for (var i = 0, len = classes.length; i < len; i++) { - el.classList.add(classes[i]); - } - } else if (!L.DomUtil.hasClass(el, name)) { - var className = L.DomUtil._getClass(el); - L.DomUtil._setClass(el, (className ? className + ' ' : '') + name); - } - }, - - removeClass: function (el, name) { - if (el.classList !== undefined) { - el.classList.remove(name); - } else { - L.DomUtil._setClass(el, L.Util.trim((' ' + L.DomUtil._getClass(el) + ' ').replace(' ' + name + ' ', ' '))); - } - }, - - _setClass: function (el, name) { - if (el.className.baseVal === undefined) { - el.className = name; - } else { - // in case of SVG element - el.className.baseVal = name; - } - }, - - _getClass: function (el) { - return el.className.baseVal === undefined ? el.className : el.className.baseVal; - }, - - setOpacity: function (el, value) { - - if ('opacity' in el.style) { - el.style.opacity = value; - - } else if ('filter' in el.style) { - - var filter = false, - filterName = 'DXImageTransform.Microsoft.Alpha'; - - // filters collection throws an error if we try to retrieve a filter that doesn't exist - try { - filter = el.filters.item(filterName); - } catch (e) { - // don't set opacity to 1 if we haven't already set an opacity, - // it isn't needed and breaks transparent pngs. - if (value === 1) { return; } - } - - value = Math.round(value * 100); - - if (filter) { - filter.Enabled = (value !== 100); - filter.Opacity = value; - } else { - el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')'; - } - } - }, - - testProp: function (props) { - - var style = document.documentElement.style; - - for (var i = 0; i < props.length; i++) { - if (props[i] in style) { - return props[i]; - } - } - return false; - }, - - getTranslateString: function (point) { - // on WebKit browsers (Chrome/Safari/iOS Safari/Android) using translate3d instead of translate - // makes animation smoother as it ensures HW accel is used. Firefox 13 doesn't care - // (same speed either way), Opera 12 doesn't support translate3d - - var is3d = L.Browser.webkit3d, - open = 'translate' + (is3d ? '3d' : '') + '(', - close = (is3d ? ',0' : '') + ')'; - - return open + point.x + 'px,' + point.y + 'px' + close; - }, - - getScaleString: function (scale, origin) { - - var preTranslateStr = L.DomUtil.getTranslateString(origin.add(origin.multiplyBy(-1 * scale))), - scaleStr = ' scale(' + scale + ') '; - - return preTranslateStr + scaleStr; - }, - - setPosition: function (el, point, disable3D) { // (HTMLElement, Point[, Boolean]) - - // jshint camelcase: false - el._leaflet_pos = point; - - if (!disable3D && L.Browser.any3d) { - el.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(point); - } else { - el.style.left = point.x + 'px'; - el.style.top = point.y + 'px'; - } - }, - - getPosition: function (el) { - // this method is only used for elements previously positioned using setPosition, - // so it's safe to cache the position for performance - - // jshint camelcase: false - return el._leaflet_pos; - } -}; - - -// prefix style property names - -L.DomUtil.TRANSFORM = L.DomUtil.testProp( - ['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']); - -// webkitTransition comes first because some browser versions that drop vendor prefix don't do -// the same for the transitionend event, in particular the Android 4.1 stock browser - -L.DomUtil.TRANSITION = L.DomUtil.testProp( - ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']); - -L.DomUtil.TRANSITION_END = - L.DomUtil.TRANSITION === 'webkitTransition' || L.DomUtil.TRANSITION === 'OTransition' ? - L.DomUtil.TRANSITION + 'End' : 'transitionend'; - -(function () { - if ('onselectstart' in document) { - L.extend(L.DomUtil, { - disableTextSelection: function () { - L.DomEvent.on(window, 'selectstart', L.DomEvent.preventDefault); - }, - - enableTextSelection: function () { - L.DomEvent.off(window, 'selectstart', L.DomEvent.preventDefault); - } - }); - } else { - var userSelectProperty = L.DomUtil.testProp( - ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']); - - L.extend(L.DomUtil, { - disableTextSelection: function () { - if (userSelectProperty) { - var style = document.documentElement.style; - this._userSelect = style[userSelectProperty]; - style[userSelectProperty] = 'none'; - } - }, - - enableTextSelection: function () { - if (userSelectProperty) { - document.documentElement.style[userSelectProperty] = this._userSelect; - delete this._userSelect; - } - } - }); - } - - L.extend(L.DomUtil, { - disableImageDrag: function () { - L.DomEvent.on(window, 'dragstart', L.DomEvent.preventDefault); - }, - - enableImageDrag: function () { - L.DomEvent.off(window, 'dragstart', L.DomEvent.preventDefault); - } - }); -})(); - - -/* - * L.LatLng represents a geographical point with latitude and longitude coordinates. - */ - -L.LatLng = function (lat, lng, alt) { // (Number, Number, Number) - lat = parseFloat(lat); - lng = parseFloat(lng); - - if (isNaN(lat) || isNaN(lng)) { - throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); - } - - this.lat = lat; - this.lng = lng; - - if (alt !== undefined) { - this.alt = parseFloat(alt); - } -}; - -L.extend(L.LatLng, { - DEG_TO_RAD: Math.PI / 180, - RAD_TO_DEG: 180 / Math.PI, - MAX_MARGIN: 1.0E-9 // max margin of error for the "equals" check -}); - -L.LatLng.prototype = { - equals: function (obj) { // (LatLng) -> Boolean - if (!obj) { return false; } - - obj = L.latLng(obj); - - var margin = Math.max( - Math.abs(this.lat - obj.lat), - Math.abs(this.lng - obj.lng)); - - return margin <= L.LatLng.MAX_MARGIN; - }, - - toString: function (precision) { // (Number) -> String - return 'LatLng(' + - L.Util.formatNum(this.lat, precision) + ', ' + - L.Util.formatNum(this.lng, precision) + ')'; - }, - - // Haversine distance formula, see http://en.wikipedia.org/wiki/Haversine_formula - // TODO move to projection code, LatLng shouldn't know about Earth - distanceTo: function (other) { // (LatLng) -> Number - other = L.latLng(other); - - var R = 6378137, // earth radius in meters - d2r = L.LatLng.DEG_TO_RAD, - dLat = (other.lat - this.lat) * d2r, - dLon = (other.lng - this.lng) * d2r, - lat1 = this.lat * d2r, - lat2 = other.lat * d2r, - sin1 = Math.sin(dLat / 2), - sin2 = Math.sin(dLon / 2); - - var a = sin1 * sin1 + sin2 * sin2 * Math.cos(lat1) * Math.cos(lat2); - - return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); - }, - - wrap: function (a, b) { // (Number, Number) -> LatLng - var lng = this.lng; - - a = a || -180; - b = b || 180; - - lng = (lng + b) % (b - a) + (lng < a || lng === b ? b : a); - - return new L.LatLng(this.lat, lng); - } -}; - -L.latLng = function (a, b) { // (LatLng) or ([Number, Number]) or (Number, Number) - if (a instanceof L.LatLng) { - return a; - } - if (L.Util.isArray(a)) { - if (typeof a[0] === 'number' || typeof a[0] === 'string') { - return new L.LatLng(a[0], a[1], a[2]); - } else { - return null; - } - } - if (a === undefined || a === null) { - return a; - } - if (typeof a === 'object' && 'lat' in a) { - return new L.LatLng(a.lat, 'lng' in a ? a.lng : a.lon); - } - if (b === undefined) { - return null; - } - return new L.LatLng(a, b); -}; - - - -/* - * L.LatLngBounds represents a rectangular area on the map in geographical coordinates. - */ - -L.LatLngBounds = function (southWest, northEast) { // (LatLng, LatLng) or (LatLng[]) - if (!southWest) { return; } - - var latlngs = northEast ? [southWest, northEast] : southWest; - - for (var i = 0, len = latlngs.length; i < len; i++) { - this.extend(latlngs[i]); - } -}; - -L.LatLngBounds.prototype = { - // extend the bounds to contain the given point or bounds - extend: function (obj) { // (LatLng) or (LatLngBounds) - if (!obj) { return this; } - - var latLng = L.latLng(obj); - if (latLng !== null) { - obj = latLng; - } else { - obj = L.latLngBounds(obj); - } - - if (obj instanceof L.LatLng) { - if (!this._southWest && !this._northEast) { - this._southWest = new L.LatLng(obj.lat, obj.lng); - this._northEast = new L.LatLng(obj.lat, obj.lng); - } else { - this._southWest.lat = Math.min(obj.lat, this._southWest.lat); - this._southWest.lng = Math.min(obj.lng, this._southWest.lng); - - this._northEast.lat = Math.max(obj.lat, this._northEast.lat); - this._northEast.lng = Math.max(obj.lng, this._northEast.lng); - } - } else if (obj instanceof L.LatLngBounds) { - this.extend(obj._southWest); - this.extend(obj._northEast); - } - return this; - }, - - // extend the bounds by a percentage - pad: function (bufferRatio) { // (Number) -> LatLngBounds - var sw = this._southWest, - ne = this._northEast, - heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio, - widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio; - - return new L.LatLngBounds( - new L.LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer), - new L.LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer)); - }, - - getCenter: function () { // -> LatLng - return new L.LatLng( - (this._southWest.lat + this._northEast.lat) / 2, - (this._southWest.lng + this._northEast.lng) / 2); - }, - - getSouthWest: function () { - return this._southWest; - }, - - getNorthEast: function () { - return this._northEast; - }, - - getNorthWest: function () { - return new L.LatLng(this.getNorth(), this.getWest()); - }, - - getSouthEast: function () { - return new L.LatLng(this.getSouth(), this.getEast()); - }, - - getWest: function () { - return this._southWest.lng; - }, - - getSouth: function () { - return this._southWest.lat; - }, - - getEast: function () { - return this._northEast.lng; - }, - - getNorth: function () { - return this._northEast.lat; - }, - - contains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean - if (typeof obj[0] === 'number' || obj instanceof L.LatLng) { - obj = L.latLng(obj); - } else { - obj = L.latLngBounds(obj); - } - - var sw = this._southWest, - ne = this._northEast, - sw2, ne2; - - if (obj instanceof L.LatLngBounds) { - sw2 = obj.getSouthWest(); - ne2 = obj.getNorthEast(); - } else { - sw2 = ne2 = obj; - } - - return (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) && - (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng); - }, - - intersects: function (bounds) { // (LatLngBounds) - bounds = L.latLngBounds(bounds); - - var sw = this._southWest, - ne = this._northEast, - sw2 = bounds.getSouthWest(), - ne2 = bounds.getNorthEast(), - - latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat), - lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng); - - return latIntersects && lngIntersects; - }, - - toBBoxString: function () { - return [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(','); - }, - - equals: function (bounds) { // (LatLngBounds) - if (!bounds) { return false; } - - bounds = L.latLngBounds(bounds); - - return this._southWest.equals(bounds.getSouthWest()) && - this._northEast.equals(bounds.getNorthEast()); - }, - - isValid: function () { - return !!(this._southWest && this._northEast); - } -}; - -//TODO International date line? - -L.latLngBounds = function (a, b) { // (LatLngBounds) or (LatLng, LatLng) - if (!a || a instanceof L.LatLngBounds) { - return a; - } - return new L.LatLngBounds(a, b); -}; - - -/* - * L.Projection contains various geographical projections used by CRS classes. - */ - -L.Projection = {}; - - -/* - * Spherical Mercator is the most popular map projection, used by EPSG:3857 CRS used by default. - */ - -L.Projection.SphericalMercator = { - MAX_LATITUDE: 85.0511287798, - - project: function (latlng) { // (LatLng) -> Point - var d = L.LatLng.DEG_TO_RAD, - max = this.MAX_LATITUDE, - lat = Math.max(Math.min(max, latlng.lat), -max), - x = latlng.lng * d, - y = lat * d; - - y = Math.log(Math.tan((Math.PI / 4) + (y / 2))); - - return new L.Point(x, y); - }, - - unproject: function (point) { // (Point, Boolean) -> LatLng - var d = L.LatLng.RAD_TO_DEG, - lng = point.x * d, - lat = (2 * Math.atan(Math.exp(point.y)) - (Math.PI / 2)) * d; - - return new L.LatLng(lat, lng); - } -}; - - -/* - * Simple equirectangular (Plate Carree) projection, used by CRS like EPSG:4326 and Simple. - */ - -L.Projection.LonLat = { - project: function (latlng) { - return new L.Point(latlng.lng, latlng.lat); - }, - - unproject: function (point) { - return new L.LatLng(point.y, point.x); - } -}; - - -/* - * L.CRS is a base object for all defined CRS (Coordinate Reference Systems) in Leaflet. - */ - -L.CRS = { - latLngToPoint: function (latlng, zoom) { // (LatLng, Number) -> Point - var projectedPoint = this.projection.project(latlng), - scale = this.scale(zoom); - - return this.transformation._transform(projectedPoint, scale); - }, - - pointToLatLng: function (point, zoom) { // (Point, Number[, Boolean]) -> LatLng - var scale = this.scale(zoom), - untransformedPoint = this.transformation.untransform(point, scale); - - return this.projection.unproject(untransformedPoint); - }, - - project: function (latlng) { - return this.projection.project(latlng); - }, - - scale: function (zoom) { - return 256 * Math.pow(2, zoom); - }, - - getSize: function (zoom) { - var s = this.scale(zoom); - return L.point(s, s); - } -}; - - -/* - * A simple CRS that can be used for flat non-Earth maps like panoramas or game maps. - */ - -L.CRS.Simple = L.extend({}, L.CRS, { - projection: L.Projection.LonLat, - transformation: new L.Transformation(1, 0, -1, 0), - - scale: function (zoom) { - return Math.pow(2, zoom); - } -}); - - -/* - * L.CRS.EPSG3857 (Spherical Mercator) is the most common CRS for web mapping - * and is used by Leaflet by default. - */ - -L.CRS.EPSG3857 = L.extend({}, L.CRS, { - code: 'EPSG:3857', - - projection: L.Projection.SphericalMercator, - transformation: new L.Transformation(0.5 / Math.PI, 0.5, -0.5 / Math.PI, 0.5), - - project: function (latlng) { // (LatLng) -> Point - var projectedPoint = this.projection.project(latlng), - earthRadius = 6378137; - return projectedPoint.multiplyBy(earthRadius); - } -}); - -L.CRS.EPSG900913 = L.extend({}, L.CRS.EPSG3857, { - code: 'EPSG:900913' -}); - - -/* - * L.CRS.EPSG4326 is a CRS popular among advanced GIS specialists. - */ - -L.CRS.EPSG4326 = L.extend({}, L.CRS, { - code: 'EPSG:4326', - - projection: L.Projection.LonLat, - transformation: new L.Transformation(1 / 360, 0.5, -1 / 360, 0.5) -}); - - -/* - * L.Map is the central class of the API - it is used to create a map. - */ - -L.Map = L.Class.extend({ - - includes: L.Mixin.Events, - - options: { - crs: L.CRS.EPSG3857, - - /* - center: LatLng, - zoom: Number, - layers: Array, - */ - - fadeAnimation: L.DomUtil.TRANSITION && !L.Browser.android23, - trackResize: true, - markerZoomAnimation: L.DomUtil.TRANSITION && L.Browser.any3d - }, - - initialize: function (id, options) { // (HTMLElement or String, Object) - options = L.setOptions(this, options); - - - this._initContainer(id); - this._initLayout(); - - // hack for https://github.com/Leaflet/Leaflet/issues/1980 - this._onResize = L.bind(this._onResize, this); - - this._initEvents(); - - if (options.maxBounds) { - this.setMaxBounds(options.maxBounds); - } - - if (options.center && options.zoom !== undefined) { - this.setView(L.latLng(options.center), options.zoom, {reset: true}); - } - - this._handlers = []; - - this._layers = {}; - this._zoomBoundLayers = {}; - this._tileLayersNum = 0; - - this.callInitHooks(); - - this._addLayers(options.layers); - }, - - - // public methods that modify map state - - // replaced by animation-powered implementation in Map.PanAnimation.js - setView: function (center, zoom) { - zoom = zoom === undefined ? this.getZoom() : zoom; - this._resetView(L.latLng(center), this._limitZoom(zoom)); - return this; - }, - - setZoom: function (zoom, options) { - if (!this._loaded) { - this._zoom = this._limitZoom(zoom); - return this; - } - return this.setView(this.getCenter(), zoom, {zoom: options}); - }, - - zoomIn: function (delta, options) { - return this.setZoom(this._zoom + (delta || 1), options); - }, - - zoomOut: function (delta, options) { - return this.setZoom(this._zoom - (delta || 1), options); - }, - - setZoomAround: function (latlng, zoom, options) { - var scale = this.getZoomScale(zoom), - viewHalf = this.getSize().divideBy(2), - containerPoint = latlng instanceof L.Point ? latlng : this.latLngToContainerPoint(latlng), - - centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale), - newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset)); - - return this.setView(newCenter, zoom, {zoom: options}); - }, - - fitBounds: function (bounds, options) { - - options = options || {}; - bounds = bounds.getBounds ? bounds.getBounds() : L.latLngBounds(bounds); - - var paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]), - paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]), - - zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR)); - - zoom = (options.maxZoom) ? Math.min(options.maxZoom, zoom) : zoom; - - var paddingOffset = paddingBR.subtract(paddingTL).divideBy(2), - - swPoint = this.project(bounds.getSouthWest(), zoom), - nePoint = this.project(bounds.getNorthEast(), zoom), - center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom); - - return this.setView(center, zoom, options); - }, - - fitWorld: function (options) { - return this.fitBounds([[-90, -180], [90, 180]], options); - }, - - panTo: function (center, options) { // (LatLng) - return this.setView(center, this._zoom, {pan: options}); - }, - - panBy: function (offset) { // (Point) - // replaced with animated panBy in Map.PanAnimation.js - this.fire('movestart'); - - this._rawPanBy(L.point(offset)); - - this.fire('move'); - return this.fire('moveend'); - }, - - setMaxBounds: function (bounds) { - bounds = L.latLngBounds(bounds); - - this.options.maxBounds = bounds; - - if (!bounds) { - return this.off('moveend', this._panInsideMaxBounds, this); - } - - if (this._loaded) { - this._panInsideMaxBounds(); - } - - return this.on('moveend', this._panInsideMaxBounds, this); - }, - - panInsideBounds: function (bounds, options) { - var center = this.getCenter(), - newCenter = this._limitCenter(center, this._zoom, bounds); - - if (center.equals(newCenter)) { return this; } - - return this.panTo(newCenter, options); - }, - - addLayer: function (layer) { - // TODO method is too big, refactor - - var id = L.stamp(layer); - - if (this._layers[id]) { return this; } - - this._layers[id] = layer; - - // TODO getMaxZoom, getMinZoom in ILayer (instead of options) - if (layer.options && (!isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom))) { - this._zoomBoundLayers[id] = layer; - this._updateZoomLevels(); - } - - // TODO looks ugly, refactor!!! - if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) { - this._tileLayersNum++; - this._tileLayersToLoad++; - layer.on('load', this._onTileLayerLoad, this); - } - - if (this._loaded) { - this._layerAdd(layer); - } - - return this; - }, - - removeLayer: function (layer) { - var id = L.stamp(layer); - - if (!this._layers[id]) { return this; } - - if (this._loaded) { - layer.onRemove(this); - } - - delete this._layers[id]; - - if (this._loaded) { - this.fire('layerremove', {layer: layer}); - } - - if (this._zoomBoundLayers[id]) { - delete this._zoomBoundLayers[id]; - this._updateZoomLevels(); - } - - // TODO looks ugly, refactor - if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) { - this._tileLayersNum--; - this._tileLayersToLoad--; - layer.off('load', this._onTileLayerLoad, this); - } - - return this; - }, - - hasLayer: function (layer) { - if (!layer) { return false; } - - return (L.stamp(layer) in this._layers); - }, - - eachLayer: function (method, context) { - for (var i in this._layers) { - method.call(context, this._layers[i]); - } - return this; - }, - - invalidateSize: function (options) { - if (!this._loaded) { return this; } - - options = L.extend({ - animate: false, - pan: true - }, options === true ? {animate: true} : options); - - var oldSize = this.getSize(); - this._sizeChanged = true; - this._initialCenter = null; - - var newSize = this.getSize(), - oldCenter = oldSize.divideBy(2).round(), - newCenter = newSize.divideBy(2).round(), - offset = oldCenter.subtract(newCenter); - - if (!offset.x && !offset.y) { return this; } - - if (options.animate && options.pan) { - this.panBy(offset); - - } else { - if (options.pan) { - this._rawPanBy(offset); - } - - this.fire('move'); - - if (options.debounceMoveend) { - clearTimeout(this._sizeTimer); - this._sizeTimer = setTimeout(L.bind(this.fire, this, 'moveend'), 200); - } else { - this.fire('moveend'); - } - } - - return this.fire('resize', { - oldSize: oldSize, - newSize: newSize - }); - }, - - // TODO handler.addTo - addHandler: function (name, HandlerClass) { - if (!HandlerClass) { return this; } - - var handler = this[name] = new HandlerClass(this); - - this._handlers.push(handler); - - if (this.options[name]) { - handler.enable(); - } - - return this; - }, - - remove: function () { - if (this._loaded) { - this.fire('unload'); - } - - this._initEvents('off'); - - try { - // throws error in IE6-8 - delete this._container._leaflet; - } catch (e) { - this._container._leaflet = undefined; - } - - this._clearPanes(); - if (this._clearControlPos) { - this._clearControlPos(); - } - - this._clearHandlers(); - - return this; - }, - - - // public methods for getting map state - - getCenter: function () { // (Boolean) -> LatLng - this._checkIfLoaded(); - - if (this._initialCenter && !this._moved()) { - return this._initialCenter; - } - return this.layerPointToLatLng(this._getCenterLayerPoint()); - }, - - getZoom: function () { - return this._zoom; - }, - - getBounds: function () { - var bounds = this.getPixelBounds(), - sw = this.unproject(bounds.getBottomLeft()), - ne = this.unproject(bounds.getTopRight()); - - return new L.LatLngBounds(sw, ne); - }, - - getMinZoom: function () { - return this.options.minZoom === undefined ? - (this._layersMinZoom === undefined ? 0 : this._layersMinZoom) : - this.options.minZoom; - }, - - getMaxZoom: function () { - return this.options.maxZoom === undefined ? - (this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) : - this.options.maxZoom; - }, - - getBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number - bounds = L.latLngBounds(bounds); - - var zoom = this.getMinZoom() - (inside ? 1 : 0), - maxZoom = this.getMaxZoom(), - size = this.getSize(), - - nw = bounds.getNorthWest(), - se = bounds.getSouthEast(), - - zoomNotFound = true, - boundsSize; - - padding = L.point(padding || [0, 0]); - - do { - zoom++; - boundsSize = this.project(se, zoom).subtract(this.project(nw, zoom)).add(padding); - zoomNotFound = !inside ? size.contains(boundsSize) : boundsSize.x < size.x || boundsSize.y < size.y; - - } while (zoomNotFound && zoom <= maxZoom); - - if (zoomNotFound && inside) { - return null; - } - - return inside ? zoom : zoom - 1; - }, - - getSize: function () { - if (!this._size || this._sizeChanged) { - this._size = new L.Point( - this._container.clientWidth, - this._container.clientHeight); - - this._sizeChanged = false; - } - return this._size.clone(); - }, - - getPixelBounds: function () { - var topLeftPoint = this._getTopLeftPoint(); - return new L.Bounds(topLeftPoint, topLeftPoint.add(this.getSize())); - }, - - getPixelOrigin: function () { - this._checkIfLoaded(); - return this._initialTopLeftPoint; - }, - - getPanes: function () { - return this._panes; - }, - - getContainer: function () { - return this._container; - }, - - - // TODO replace with universal implementation after refactoring projections - - getZoomScale: function (toZoom) { - var crs = this.options.crs; - return crs.scale(toZoom) / crs.scale(this._zoom); - }, - - getScaleZoom: function (scale) { - return this._zoom + (Math.log(scale) / Math.LN2); - }, - - - // conversion methods - - project: function (latlng, zoom) { // (LatLng[, Number]) -> Point - zoom = zoom === undefined ? this._zoom : zoom; - return this.options.crs.latLngToPoint(L.latLng(latlng), zoom); - }, - - unproject: function (point, zoom) { // (Point[, Number]) -> LatLng - zoom = zoom === undefined ? this._zoom : zoom; - return this.options.crs.pointToLatLng(L.point(point), zoom); - }, - - layerPointToLatLng: function (point) { // (Point) - var projectedPoint = L.point(point).add(this.getPixelOrigin()); - return this.unproject(projectedPoint); - }, - - latLngToLayerPoint: function (latlng) { // (LatLng) - var projectedPoint = this.project(L.latLng(latlng))._round(); - return projectedPoint._subtract(this.getPixelOrigin()); - }, - - containerPointToLayerPoint: function (point) { // (Point) - return L.point(point).subtract(this._getMapPanePos()); - }, - - layerPointToContainerPoint: function (point) { // (Point) - return L.point(point).add(this._getMapPanePos()); - }, - - containerPointToLatLng: function (point) { - var layerPoint = this.containerPointToLayerPoint(L.point(point)); - return this.layerPointToLatLng(layerPoint); - }, - - latLngToContainerPoint: function (latlng) { - return this.layerPointToContainerPoint(this.latLngToLayerPoint(L.latLng(latlng))); - }, - - mouseEventToContainerPoint: function (e) { // (MouseEvent) - return L.DomEvent.getMousePosition(e, this._container); - }, - - mouseEventToLayerPoint: function (e) { // (MouseEvent) - return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e)); - }, - - mouseEventToLatLng: function (e) { // (MouseEvent) - return this.layerPointToLatLng(this.mouseEventToLayerPoint(e)); - }, - - - // map initialization methods - - _initContainer: function (id) { - var container = this._container = L.DomUtil.get(id); - - if (!container) { - throw new Error('Map container not found.'); - } else if (container._leaflet) { - throw new Error('Map container is already initialized.'); - } - - container._leaflet = true; - }, - - _initLayout: function () { - var container = this._container; - - L.DomUtil.addClass(container, 'leaflet-container' + - (L.Browser.touch ? ' leaflet-touch' : '') + - (L.Browser.retina ? ' leaflet-retina' : '') + - (L.Browser.ielt9 ? ' leaflet-oldie' : '') + - (this.options.fadeAnimation ? ' leaflet-fade-anim' : '')); - - var position = L.DomUtil.getStyle(container, 'position'); - - if (position !== 'absolute' && position !== 'relative' && position !== 'fixed') { - container.style.position = 'relative'; - } - - this._initPanes(); - - if (this._initControlPos) { - this._initControlPos(); - } - }, - - _initPanes: function () { - var panes = this._panes = {}; - - this._mapPane = panes.mapPane = this._createPane('leaflet-map-pane', this._container); - - this._tilePane = panes.tilePane = this._createPane('leaflet-tile-pane', this._mapPane); - panes.objectsPane = this._createPane('leaflet-objects-pane', this._mapPane); - panes.shadowPane = this._createPane('leaflet-shadow-pane'); - panes.overlayPane = this._createPane('leaflet-overlay-pane'); - panes.markerPane = this._createPane('leaflet-marker-pane'); - panes.popupPane = this._createPane('leaflet-popup-pane'); - - var zoomHide = ' leaflet-zoom-hide'; - - if (!this.options.markerZoomAnimation) { - L.DomUtil.addClass(panes.markerPane, zoomHide); - L.DomUtil.addClass(panes.shadowPane, zoomHide); - L.DomUtil.addClass(panes.popupPane, zoomHide); - } - }, - - _createPane: function (className, container) { - return L.DomUtil.create('div', className, container || this._panes.objectsPane); - }, - - _clearPanes: function () { - this._container.removeChild(this._mapPane); - }, - - _addLayers: function (layers) { - layers = layers ? (L.Util.isArray(layers) ? layers : [layers]) : []; - - for (var i = 0, len = layers.length; i < len; i++) { - this.addLayer(layers[i]); - } - }, - - - // private methods that modify map state - - _resetView: function (center, zoom, preserveMapOffset, afterZoomAnim) { - - var zoomChanged = (this._zoom !== zoom); - - if (!afterZoomAnim) { - this.fire('movestart'); - - if (zoomChanged) { - this.fire('zoomstart'); - } - } - - this._zoom = zoom; - this._initialCenter = center; - - this._initialTopLeftPoint = this._getNewTopLeftPoint(center); - - if (!preserveMapOffset) { - L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0)); - } else { - this._initialTopLeftPoint._add(this._getMapPanePos()); - } - - this._tileLayersToLoad = this._tileLayersNum; - - var loading = !this._loaded; - this._loaded = true; - - this.fire('viewreset', {hard: !preserveMapOffset}); - - if (loading) { - this.fire('load'); - this.eachLayer(this._layerAdd, this); - } - - this.fire('move'); - - if (zoomChanged || afterZoomAnim) { - this.fire('zoomend'); - } - - this.fire('moveend', {hard: !preserveMapOffset}); - }, - - _rawPanBy: function (offset) { - L.DomUtil.setPosition(this._mapPane, this._getMapPanePos().subtract(offset)); - }, - - _getZoomSpan: function () { - return this.getMaxZoom() - this.getMinZoom(); - }, - - _updateZoomLevels: function () { - var i, - minZoom = Infinity, - maxZoom = -Infinity, - oldZoomSpan = this._getZoomSpan(); - - for (i in this._zoomBoundLayers) { - var layer = this._zoomBoundLayers[i]; - if (!isNaN(layer.options.minZoom)) { - minZoom = Math.min(minZoom, layer.options.minZoom); - } - if (!isNaN(layer.options.maxZoom)) { - maxZoom = Math.max(maxZoom, layer.options.maxZoom); - } - } - - if (i === undefined) { // we have no tilelayers - this._layersMaxZoom = this._layersMinZoom = undefined; - } else { - this._layersMaxZoom = maxZoom; - this._layersMinZoom = minZoom; - } - - if (oldZoomSpan !== this._getZoomSpan()) { - this.fire('zoomlevelschange'); - } - }, - - _panInsideMaxBounds: function () { - this.panInsideBounds(this.options.maxBounds); - }, - - _checkIfLoaded: function () { - if (!this._loaded) { - throw new Error('Set map center and zoom first.'); - } - }, - - // map events - - _initEvents: function (onOff) { - if (!L.DomEvent) { return; } - - onOff = onOff || 'on'; - - L.DomEvent[onOff](this._container, 'click', this._onMouseClick, this); - - var events = ['dblclick', 'mousedown', 'mouseup', 'mouseenter', - 'mouseleave', 'mousemove', 'contextmenu'], - i, len; - - for (i = 0, len = events.length; i < len; i++) { - L.DomEvent[onOff](this._container, events[i], this._fireMouseEvent, this); - } - - if (this.options.trackResize) { - L.DomEvent[onOff](window, 'resize', this._onResize, this); - } - }, - - _onResize: function () { - L.Util.cancelAnimFrame(this._resizeRequest); - this._resizeRequest = L.Util.requestAnimFrame( - function () { this.invalidateSize({debounceMoveend: true}); }, this, false, this._container); - }, - - _onMouseClick: function (e) { - if (!this._loaded || (!e._simulated && - ((this.dragging && this.dragging.moved()) || - (this.boxZoom && this.boxZoom.moved()))) || - L.DomEvent._skipped(e)) { return; } - - this.fire('preclick'); - this._fireMouseEvent(e); - }, - - _fireMouseEvent: function (e) { - if (!this._loaded || L.DomEvent._skipped(e)) { return; } - - var type = e.type; - - type = (type === 'mouseenter' ? 'mouseover' : (type === 'mouseleave' ? 'mouseout' : type)); - - if (!this.hasEventListeners(type)) { return; } - - if (type === 'contextmenu') { - L.DomEvent.preventDefault(e); - } - - var containerPoint = this.mouseEventToContainerPoint(e), - layerPoint = this.containerPointToLayerPoint(containerPoint), - latlng = this.layerPointToLatLng(layerPoint); - - this.fire(type, { - latlng: latlng, - layerPoint: layerPoint, - containerPoint: containerPoint, - originalEvent: e - }); - }, - - _onTileLayerLoad: function () { - this._tileLayersToLoad--; - if (this._tileLayersNum && !this._tileLayersToLoad) { - this.fire('tilelayersload'); - } - }, - - _clearHandlers: function () { - for (var i = 0, len = this._handlers.length; i < len; i++) { - this._handlers[i].disable(); - } - }, - - whenReady: function (callback, context) { - if (this._loaded) { - callback.call(context || this, this); - } else { - this.on('load', callback, context); - } - return this; - }, - - _layerAdd: function (layer) { - layer.onAdd(this); - this.fire('layeradd', {layer: layer}); - }, - - - // private methods for getting map state - - _getMapPanePos: function () { - return L.DomUtil.getPosition(this._mapPane); - }, - - _moved: function () { - var pos = this._getMapPanePos(); - return pos && !pos.equals([0, 0]); - }, - - _getTopLeftPoint: function () { - return this.getPixelOrigin().subtract(this._getMapPanePos()); - }, - - _getNewTopLeftPoint: function (center, zoom) { - var viewHalf = this.getSize()._divideBy(2); - // TODO round on display, not calculation to increase precision? - return this.project(center, zoom)._subtract(viewHalf)._round(); - }, - - _latLngToNewLayerPoint: function (latlng, newZoom, newCenter) { - var topLeft = this._getNewTopLeftPoint(newCenter, newZoom).add(this._getMapPanePos()); - return this.project(latlng, newZoom)._subtract(topLeft); - }, - - // layer point of the current center - _getCenterLayerPoint: function () { - return this.containerPointToLayerPoint(this.getSize()._divideBy(2)); - }, - - // offset of the specified place to the current center in pixels - _getCenterOffset: function (latlng) { - return this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint()); - }, - - // adjust center for view to get inside bounds - _limitCenter: function (center, zoom, bounds) { - - if (!bounds) { return center; } - - var centerPoint = this.project(center, zoom), - viewHalf = this.getSize().divideBy(2), - viewBounds = new L.Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)), - offset = this._getBoundsOffset(viewBounds, bounds, zoom); - - return this.unproject(centerPoint.add(offset), zoom); - }, - - // adjust offset for view to get inside bounds - _limitOffset: function (offset, bounds) { - if (!bounds) { return offset; } - - var viewBounds = this.getPixelBounds(), - newBounds = new L.Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset)); - - return offset.add(this._getBoundsOffset(newBounds, bounds)); - }, - - // returns offset needed for pxBounds to get inside maxBounds at a specified zoom - _getBoundsOffset: function (pxBounds, maxBounds, zoom) { - var nwOffset = this.project(maxBounds.getNorthWest(), zoom).subtract(pxBounds.min), - seOffset = this.project(maxBounds.getSouthEast(), zoom).subtract(pxBounds.max), - - dx = this._rebound(nwOffset.x, -seOffset.x), - dy = this._rebound(nwOffset.y, -seOffset.y); - - return new L.Point(dx, dy); - }, - - _rebound: function (left, right) { - return left + right > 0 ? - Math.round(left - right) / 2 : - Math.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right)); - }, - - _limitZoom: function (zoom) { - var min = this.getMinZoom(), - max = this.getMaxZoom(); - - return Math.max(min, Math.min(max, zoom)); - } -}); - -L.map = function (id, options) { - return new L.Map(id, options); -}; - - -/* - * Mercator projection that takes into account that the Earth is not a perfect sphere. - * Less popular than spherical mercator; used by projections like EPSG:3395. - */ - -L.Projection.Mercator = { - MAX_LATITUDE: 85.0840591556, - - R_MINOR: 6356752.314245179, - R_MAJOR: 6378137, - - project: function (latlng) { // (LatLng) -> Point - var d = L.LatLng.DEG_TO_RAD, - max = this.MAX_LATITUDE, - lat = Math.max(Math.min(max, latlng.lat), -max), - r = this.R_MAJOR, - r2 = this.R_MINOR, - x = latlng.lng * d * r, - y = lat * d, - tmp = r2 / r, - eccent = Math.sqrt(1.0 - tmp * tmp), - con = eccent * Math.sin(y); - - con = Math.pow((1 - con) / (1 + con), eccent * 0.5); - - var ts = Math.tan(0.5 * ((Math.PI * 0.5) - y)) / con; - y = -r * Math.log(ts); - - return new L.Point(x, y); - }, - - unproject: function (point) { // (Point, Boolean) -> LatLng - var d = L.LatLng.RAD_TO_DEG, - r = this.R_MAJOR, - r2 = this.R_MINOR, - lng = point.x * d / r, - tmp = r2 / r, - eccent = Math.sqrt(1 - (tmp * tmp)), - ts = Math.exp(- point.y / r), - phi = (Math.PI / 2) - 2 * Math.atan(ts), - numIter = 15, - tol = 1e-7, - i = numIter, - dphi = 0.1, - con; - - while ((Math.abs(dphi) > tol) && (--i > 0)) { - con = eccent * Math.sin(phi); - dphi = (Math.PI / 2) - 2 * Math.atan(ts * - Math.pow((1.0 - con) / (1.0 + con), 0.5 * eccent)) - phi; - phi += dphi; - } - - return new L.LatLng(phi * d, lng); - } -}; - - - -L.CRS.EPSG3395 = L.extend({}, L.CRS, { - code: 'EPSG:3395', - - projection: L.Projection.Mercator, - - transformation: (function () { - var m = L.Projection.Mercator, - r = m.R_MAJOR, - scale = 0.5 / (Math.PI * r); - - return new L.Transformation(scale, 0.5, -scale, 0.5); - }()) -}); - - -/* - * L.TileLayer is used for standard xyz-numbered tile layers. - */ - -L.TileLayer = L.Class.extend({ - includes: L.Mixin.Events, - - options: { - minZoom: 0, - maxZoom: 18, - tileSize: 256, - subdomains: 'abc', - errorTileUrl: '', - attribution: '', - zoomOffset: 0, - opacity: 1, - /* - maxNativeZoom: null, - zIndex: null, - tms: false, - continuousWorld: false, - noWrap: false, - zoomReverse: false, - detectRetina: false, - reuseTiles: false, - bounds: false, - */ - unloadInvisibleTiles: L.Browser.mobile, - updateWhenIdle: L.Browser.mobile - }, - - initialize: function (url, options) { - options = L.setOptions(this, options); - - // detecting retina displays, adjusting tileSize and zoom levels - if (options.detectRetina && L.Browser.retina && options.maxZoom > 0) { - - options.tileSize = Math.floor(options.tileSize / 2); - options.zoomOffset++; - - if (options.minZoom > 0) { - options.minZoom--; - } - this.options.maxZoom--; - } - - if (options.bounds) { - options.bounds = L.latLngBounds(options.bounds); - } - - this._url = url; - - var subdomains = this.options.subdomains; - - if (typeof subdomains === 'string') { - this.options.subdomains = subdomains.split(''); - } - }, - - onAdd: function (map) { - this._map = map; - this._animated = map._zoomAnimated; - - // create a container div for tiles - this._initContainer(); - - // set up events - map.on({ - 'viewreset': this._reset, - 'moveend': this._update - }, this); - - if (this._animated) { - map.on({ - 'zoomanim': this._animateZoom, - 'zoomend': this._endZoomAnim - }, this); - } - - if (!this.options.updateWhenIdle) { - this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this); - map.on('move', this._limitedUpdate, this); - } - - this._reset(); - this._update(); - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - onRemove: function (map) { - this._container.parentNode.removeChild(this._container); - - map.off({ - 'viewreset': this._reset, - 'moveend': this._update - }, this); - - if (this._animated) { - map.off({ - 'zoomanim': this._animateZoom, - 'zoomend': this._endZoomAnim - }, this); - } - - if (!this.options.updateWhenIdle) { - map.off('move', this._limitedUpdate, this); - } - - this._container = null; - this._map = null; - }, - - bringToFront: function () { - var pane = this._map._panes.tilePane; - - if (this._container) { - pane.appendChild(this._container); - this._setAutoZIndex(pane, Math.max); - } - - return this; - }, - - bringToBack: function () { - var pane = this._map._panes.tilePane; - - if (this._container) { - pane.insertBefore(this._container, pane.firstChild); - this._setAutoZIndex(pane, Math.min); - } - - return this; - }, - - getAttribution: function () { - return this.options.attribution; - }, - - getContainer: function () { - return this._container; - }, - - setOpacity: function (opacity) { - this.options.opacity = opacity; - - if (this._map) { - this._updateOpacity(); - } - - return this; - }, - - setZIndex: function (zIndex) { - this.options.zIndex = zIndex; - this._updateZIndex(); - - return this; - }, - - setUrl: function (url, noRedraw) { - this._url = url; - - if (!noRedraw) { - this.redraw(); - } - - return this; - }, - - redraw: function () { - if (this._map) { - this._reset({hard: true}); - this._update(); - } - return this; - }, - - _updateZIndex: function () { - if (this._container && this.options.zIndex !== undefined) { - this._container.style.zIndex = this.options.zIndex; - } - }, - - _setAutoZIndex: function (pane, compare) { - - var layers = pane.children, - edgeZIndex = -compare(Infinity, -Infinity), // -Infinity for max, Infinity for min - zIndex, i, len; - - for (i = 0, len = layers.length; i < len; i++) { - - if (layers[i] !== this._container) { - zIndex = parseInt(layers[i].style.zIndex, 10); - - if (!isNaN(zIndex)) { - edgeZIndex = compare(edgeZIndex, zIndex); - } - } - } - - this.options.zIndex = this._container.style.zIndex = - (isFinite(edgeZIndex) ? edgeZIndex : 0) + compare(1, -1); - }, - - _updateOpacity: function () { - var i, - tiles = this._tiles; - - if (L.Browser.ielt9) { - for (i in tiles) { - L.DomUtil.setOpacity(tiles[i], this.options.opacity); - } - } else { - L.DomUtil.setOpacity(this._container, this.options.opacity); - } - }, - - _initContainer: function () { - var tilePane = this._map._panes.tilePane; - - if (!this._container) { - this._container = L.DomUtil.create('div', 'leaflet-layer'); - - this._updateZIndex(); - - if (this._animated) { - var className = 'leaflet-tile-container'; - - this._bgBuffer = L.DomUtil.create('div', className, this._container); - this._tileContainer = L.DomUtil.create('div', className, this._container); - - } else { - this._tileContainer = this._container; - } - - tilePane.appendChild(this._container); - - if (this.options.opacity < 1) { - this._updateOpacity(); - } - } - }, - - _reset: function (e) { - for (var key in this._tiles) { - this.fire('tileunload', {tile: this._tiles[key]}); - } - - this._tiles = {}; - this._tilesToLoad = 0; - - if (this.options.reuseTiles) { - this._unusedTiles = []; - } - - this._tileContainer.innerHTML = ''; - - if (this._animated && e && e.hard) { - this._clearBgBuffer(); - } - - this._initContainer(); - }, - - _getTileSize: function () { - var map = this._map, - zoom = map.getZoom() + this.options.zoomOffset, - zoomN = this.options.maxNativeZoom, - tileSize = this.options.tileSize; - - if (zoomN && zoom > zoomN) { - tileSize = Math.round(map.getZoomScale(zoom) / map.getZoomScale(zoomN) * tileSize); - } - - return tileSize; - }, - - _update: function () { - - if (!this._map) { return; } - - var map = this._map, - bounds = map.getPixelBounds(), - zoom = map.getZoom(), - tileSize = this._getTileSize(); - - if (zoom > this.options.maxZoom || zoom < this.options.minZoom) { - return; - } - - var tileBounds = L.bounds( - bounds.min.divideBy(tileSize)._floor(), - bounds.max.divideBy(tileSize)._floor()); - - this._addTilesFromCenterOut(tileBounds); - - if (this.options.unloadInvisibleTiles || this.options.reuseTiles) { - this._removeOtherTiles(tileBounds); - } - }, - - _addTilesFromCenterOut: function (bounds) { - var queue = [], - center = bounds.getCenter(); - - var j, i, point; - - for (j = bounds.min.y; j <= bounds.max.y; j++) { - for (i = bounds.min.x; i <= bounds.max.x; i++) { - point = new L.Point(i, j); - - if (this._tileShouldBeLoaded(point)) { - queue.push(point); - } - } - } - - var tilesToLoad = queue.length; - - if (tilesToLoad === 0) { return; } - - // load tiles in order of their distance to center - queue.sort(function (a, b) { - return a.distanceTo(center) - b.distanceTo(center); - }); - - var fragment = document.createDocumentFragment(); - - // if its the first batch of tiles to load - if (!this._tilesToLoad) { - this.fire('loading'); - } - - this._tilesToLoad += tilesToLoad; - - for (i = 0; i < tilesToLoad; i++) { - this._addTile(queue[i], fragment); - } - - this._tileContainer.appendChild(fragment); - }, - - _tileShouldBeLoaded: function (tilePoint) { - if ((tilePoint.x + ':' + tilePoint.y) in this._tiles) { - return false; // already loaded - } - - var options = this.options; - - if (!options.continuousWorld) { - var limit = this._getWrapTileNum(); - - // don't load if exceeds world bounds - if ((options.noWrap && (tilePoint.x < 0 || tilePoint.x >= limit.x)) || - tilePoint.y < 0 || tilePoint.y >= limit.y) { return false; } - } - - if (options.bounds) { - var tileSize = this._getTileSize(), - nwPoint = tilePoint.multiplyBy(tileSize), - sePoint = nwPoint.add([tileSize, tileSize]), - nw = this._map.unproject(nwPoint), - se = this._map.unproject(sePoint); - - // TODO temporary hack, will be removed after refactoring projections - // https://github.com/Leaflet/Leaflet/issues/1618 - if (!options.continuousWorld && !options.noWrap) { - nw = nw.wrap(); - se = se.wrap(); - } - - if (!options.bounds.intersects([nw, se])) { return false; } - } - - return true; - }, - - _removeOtherTiles: function (bounds) { - var kArr, x, y, key; - - for (key in this._tiles) { - kArr = key.split(':'); - x = parseInt(kArr[0], 10); - y = parseInt(kArr[1], 10); - - // remove tile if it's out of bounds - if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) { - this._removeTile(key); - } - } - }, - - _removeTile: function (key) { - var tile = this._tiles[key]; - - this.fire('tileunload', {tile: tile, url: tile.src}); - - if (this.options.reuseTiles) { - L.DomUtil.removeClass(tile, 'leaflet-tile-loaded'); - this._unusedTiles.push(tile); - - } else if (tile.parentNode === this._tileContainer) { - this._tileContainer.removeChild(tile); - } - - // for https://github.com/CloudMade/Leaflet/issues/137 - if (!L.Browser.android) { - tile.onload = null; - tile.src = L.Util.emptyImageUrl; - } - - delete this._tiles[key]; - }, - - _addTile: function (tilePoint, container) { - var tilePos = this._getTilePos(tilePoint); - - // get unused tile - or create a new tile - var tile = this._getTile(); - - /* - Chrome 20 layouts much faster with top/left (verify with timeline, frames) - Android 4 browser has display issues with top/left and requires transform instead - (other browsers don't currently care) - see debug/hacks/jitter.html for an example - */ - L.DomUtil.setPosition(tile, tilePos, L.Browser.chrome); - - this._tiles[tilePoint.x + ':' + tilePoint.y] = tile; - - this._loadTile(tile, tilePoint); - - if (tile.parentNode !== this._tileContainer) { - container.appendChild(tile); - } - }, - - _getZoomForUrl: function () { - - var options = this.options, - zoom = this._map.getZoom(); - - if (options.zoomReverse) { - zoom = options.maxZoom - zoom; - } - - zoom += options.zoomOffset; - - return options.maxNativeZoom ? Math.min(zoom, options.maxNativeZoom) : zoom; - }, - - _getTilePos: function (tilePoint) { - var origin = this._map.getPixelOrigin(), - tileSize = this._getTileSize(); - - return tilePoint.multiplyBy(tileSize).subtract(origin); - }, - - // image-specific code (override to implement e.g. Canvas or SVG tile layer) - - getTileUrl: function (tilePoint) { - return L.Util.template(this._url, L.extend({ - s: this._getSubdomain(tilePoint), - z: tilePoint.z, - x: tilePoint.x, - y: tilePoint.y - }, this.options)); - }, - - _getWrapTileNum: function () { - var crs = this._map.options.crs, - size = crs.getSize(this._map.getZoom()); - return size.divideBy(this._getTileSize())._floor(); - }, - - _adjustTilePoint: function (tilePoint) { - - var limit = this._getWrapTileNum(); - - // wrap tile coordinates - if (!this.options.continuousWorld && !this.options.noWrap) { - tilePoint.x = ((tilePoint.x % limit.x) + limit.x) % limit.x; - } - - if (this.options.tms) { - tilePoint.y = limit.y - tilePoint.y - 1; - } - - tilePoint.z = this._getZoomForUrl(); - }, - - _getSubdomain: function (tilePoint) { - var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length; - return this.options.subdomains[index]; - }, - - _getTile: function () { - if (this.options.reuseTiles && this._unusedTiles.length > 0) { - var tile = this._unusedTiles.pop(); - this._resetTile(tile); - return tile; - } - return this._createTile(); - }, - - // Override if data stored on a tile needs to be cleaned up before reuse - _resetTile: function (/*tile*/) {}, - - _createTile: function () { - var tile = L.DomUtil.create('img', 'leaflet-tile'); - tile.style.width = tile.style.height = this._getTileSize() + 'px'; - tile.galleryimg = 'no'; - - tile.onselectstart = tile.onmousemove = L.Util.falseFn; - - if (L.Browser.ielt9 && this.options.opacity !== undefined) { - L.DomUtil.setOpacity(tile, this.options.opacity); - } - // without this hack, tiles disappear after zoom on Chrome for Android - // https://github.com/Leaflet/Leaflet/issues/2078 - if (L.Browser.mobileWebkit3d) { - tile.style.WebkitBackfaceVisibility = 'hidden'; - } - return tile; - }, - - _loadTile: function (tile, tilePoint) { - tile._layer = this; - tile.onload = this._tileOnLoad; - tile.onerror = this._tileOnError; - - this._adjustTilePoint(tilePoint); - tile.src = this.getTileUrl(tilePoint); - - this.fire('tileloadstart', { - tile: tile, - url: tile.src - }); - }, - - _tileLoaded: function () { - this._tilesToLoad--; - - if (this._animated) { - L.DomUtil.addClass(this._tileContainer, 'leaflet-zoom-animated'); - } - - if (!this._tilesToLoad) { - this.fire('load'); - - if (this._animated) { - // clear scaled tiles after all new tiles are loaded (for performance) - clearTimeout(this._clearBgBufferTimer); - this._clearBgBufferTimer = setTimeout(L.bind(this._clearBgBuffer, this), 500); - } - } - }, - - _tileOnLoad: function () { - var layer = this._layer; - - //Only if we are loading an actual image - if (this.src !== L.Util.emptyImageUrl) { - L.DomUtil.addClass(this, 'leaflet-tile-loaded'); - - layer.fire('tileload', { - tile: this, - url: this.src - }); - } - - layer._tileLoaded(); - }, - - _tileOnError: function () { - var layer = this._layer; - - layer.fire('tileerror', { - tile: this, - url: this.src - }); - - var newUrl = layer.options.errorTileUrl; - if (newUrl) { - this.src = newUrl; - } - - layer._tileLoaded(); - } -}); - -L.tileLayer = function (url, options) { - return new L.TileLayer(url, options); -}; - - -/* - * L.TileLayer.WMS is used for putting WMS tile layers on the map. - */ - -L.TileLayer.WMS = L.TileLayer.extend({ - - defaultWmsParams: { - service: 'WMS', - request: 'GetMap', - version: '1.1.1', - layers: '', - styles: '', - format: 'image/jpeg', - transparent: false - }, - - initialize: function (url, options) { // (String, Object) - - this._url = url; - - var wmsParams = L.extend({}, this.defaultWmsParams), - tileSize = options.tileSize || this.options.tileSize; - - if (options.detectRetina && L.Browser.retina) { - wmsParams.width = wmsParams.height = tileSize * 2; - } else { - wmsParams.width = wmsParams.height = tileSize; - } - - for (var i in options) { - // all keys that are not TileLayer options go to WMS params - if (!this.options.hasOwnProperty(i) && i !== 'crs') { - wmsParams[i] = options[i]; - } - } - - this.wmsParams = wmsParams; - - L.setOptions(this, options); - }, - - onAdd: function (map) { - - this._crs = this.options.crs || map.options.crs; - - this._wmsVersion = parseFloat(this.wmsParams.version); - - var projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs'; - this.wmsParams[projectionKey] = this._crs.code; - - L.TileLayer.prototype.onAdd.call(this, map); - }, - - getTileUrl: function (tilePoint) { // (Point, Number) -> String - - var map = this._map, - tileSize = this.options.tileSize, - - nwPoint = tilePoint.multiplyBy(tileSize), - sePoint = nwPoint.add([tileSize, tileSize]), - - nw = this._crs.project(map.unproject(nwPoint, tilePoint.z)), - se = this._crs.project(map.unproject(sePoint, tilePoint.z)), - bbox = this._wmsVersion >= 1.3 && this._crs === L.CRS.EPSG4326 ? - [se.y, nw.x, nw.y, se.x].join(',') : - [nw.x, se.y, se.x, nw.y].join(','), - - url = L.Util.template(this._url, {s: this._getSubdomain(tilePoint)}); - - return url + L.Util.getParamString(this.wmsParams, url, true) + '&BBOX=' + bbox; - }, - - setParams: function (params, noRedraw) { - - L.extend(this.wmsParams, params); - - if (!noRedraw) { - this.redraw(); - } - - return this; - } -}); - -L.tileLayer.wms = function (url, options) { - return new L.TileLayer.WMS(url, options); -}; - - -/* - * L.TileLayer.Canvas is a class that you can use as a base for creating - * dynamically drawn Canvas-based tile layers. - */ - -L.TileLayer.Canvas = L.TileLayer.extend({ - options: { - async: false - }, - - initialize: function (options) { - L.setOptions(this, options); - }, - - redraw: function () { - if (this._map) { - this._reset({hard: true}); - this._update(); - } - - for (var i in this._tiles) { - this._redrawTile(this._tiles[i]); - } - return this; - }, - - _redrawTile: function (tile) { - this.drawTile(tile, tile._tilePoint, this._map._zoom); - }, - - _createTile: function () { - var tile = L.DomUtil.create('canvas', 'leaflet-tile'); - tile.width = tile.height = this.options.tileSize; - tile.onselectstart = tile.onmousemove = L.Util.falseFn; - return tile; - }, - - _loadTile: function (tile, tilePoint) { - tile._layer = this; - tile._tilePoint = tilePoint; - - this._redrawTile(tile); - - if (!this.options.async) { - this.tileDrawn(tile); - } - }, - - drawTile: function (/*tile, tilePoint*/) { - // override with rendering code - }, - - tileDrawn: function (tile) { - this._tileOnLoad.call(tile); - } -}); - - -L.tileLayer.canvas = function (options) { - return new L.TileLayer.Canvas(options); -}; - - -/* - * L.ImageOverlay is used to overlay images over the map (to specific geographical bounds). - */ - -L.ImageOverlay = L.Class.extend({ - includes: L.Mixin.Events, - - options: { - opacity: 1 - }, - - initialize: function (url, bounds, options) { // (String, LatLngBounds, Object) - this._url = url; - this._bounds = L.latLngBounds(bounds); - - L.setOptions(this, options); - }, - - onAdd: function (map) { - this._map = map; - - if (!this._image) { - this._initImage(); - } - - map._panes.overlayPane.appendChild(this._image); - - map.on('viewreset', this._reset, this); - - if (map.options.zoomAnimation && L.Browser.any3d) { - map.on('zoomanim', this._animateZoom, this); - } - - this._reset(); - }, - - onRemove: function (map) { - map.getPanes().overlayPane.removeChild(this._image); - - map.off('viewreset', this._reset, this); - - if (map.options.zoomAnimation) { - map.off('zoomanim', this._animateZoom, this); - } - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - setOpacity: function (opacity) { - this.options.opacity = opacity; - this._updateOpacity(); - return this; - }, - - // TODO remove bringToFront/bringToBack duplication from TileLayer/Path - bringToFront: function () { - if (this._image) { - this._map._panes.overlayPane.appendChild(this._image); - } - return this; - }, - - bringToBack: function () { - var pane = this._map._panes.overlayPane; - if (this._image) { - pane.insertBefore(this._image, pane.firstChild); - } - return this; - }, - - setUrl: function (url) { - this._url = url; - this._image.src = this._url; - }, - - getAttribution: function () { - return this.options.attribution; - }, - - _initImage: function () { - this._image = L.DomUtil.create('img', 'leaflet-image-layer'); - - if (this._map.options.zoomAnimation && L.Browser.any3d) { - L.DomUtil.addClass(this._image, 'leaflet-zoom-animated'); - } else { - L.DomUtil.addClass(this._image, 'leaflet-zoom-hide'); - } - - this._updateOpacity(); - - //TODO createImage util method to remove duplication - L.extend(this._image, { - galleryimg: 'no', - onselectstart: L.Util.falseFn, - onmousemove: L.Util.falseFn, - onload: L.bind(this._onImageLoad, this), - src: this._url - }); - }, - - _animateZoom: function (e) { - var map = this._map, - image = this._image, - scale = map.getZoomScale(e.zoom), - nw = this._bounds.getNorthWest(), - se = this._bounds.getSouthEast(), - - topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center), - size = map._latLngToNewLayerPoint(se, e.zoom, e.center)._subtract(topLeft), - origin = topLeft._add(size._multiplyBy((1 / 2) * (1 - 1 / scale))); - - image.style[L.DomUtil.TRANSFORM] = - L.DomUtil.getTranslateString(origin) + ' scale(' + scale + ') '; - }, - - _reset: function () { - var image = this._image, - topLeft = this._map.latLngToLayerPoint(this._bounds.getNorthWest()), - size = this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(topLeft); - - L.DomUtil.setPosition(image, topLeft); - - image.style.width = size.x + 'px'; - image.style.height = size.y + 'px'; - }, - - _onImageLoad: function () { - this.fire('load'); - }, - - _updateOpacity: function () { - L.DomUtil.setOpacity(this._image, this.options.opacity); - } -}); - -L.imageOverlay = function (url, bounds, options) { - return new L.ImageOverlay(url, bounds, options); -}; - - -/* - * L.Icon is an image-based icon class that you can use with L.Marker for custom markers. - */ - -L.Icon = L.Class.extend({ - options: { - /* - iconUrl: (String) (required) - iconRetinaUrl: (String) (optional, used for retina devices if detected) - iconSize: (Point) (can be set through CSS) - iconAnchor: (Point) (centered by default, can be set in CSS with negative margins) - popupAnchor: (Point) (if not specified, popup opens in the anchor point) - shadowUrl: (String) (no shadow by default) - shadowRetinaUrl: (String) (optional, used for retina devices if detected) - shadowSize: (Point) - shadowAnchor: (Point) - */ - className: '' - }, - - initialize: function (options) { - L.setOptions(this, options); - }, - - createIcon: function (oldIcon) { - return this._createIcon('icon', oldIcon); - }, - - createShadow: function (oldIcon) { - return this._createIcon('shadow', oldIcon); - }, - - _createIcon: function (name, oldIcon) { - var src = this._getIconUrl(name); - - if (!src) { - if (name === 'icon') { - throw new Error('iconUrl not set in Icon options (see the docs).'); - } - return null; - } - - var img; - if (!oldIcon || oldIcon.tagName !== 'IMG') { - img = this._createImg(src); - } else { - img = this._createImg(src, oldIcon); - } - this._setIconStyles(img, name); - - return img; - }, - - _setIconStyles: function (img, name) { - var options = this.options, - size = L.point(options[name + 'Size']), - anchor; - - if (name === 'shadow') { - anchor = L.point(options.shadowAnchor || options.iconAnchor); - } else { - anchor = L.point(options.iconAnchor); - } - - if (!anchor && size) { - anchor = size.divideBy(2, true); - } - - img.className = 'leaflet-marker-' + name + ' ' + options.className; - - if (anchor) { - img.style.marginLeft = (-anchor.x) + 'px'; - img.style.marginTop = (-anchor.y) + 'px'; - } - - if (size) { - img.style.width = size.x + 'px'; - img.style.height = size.y + 'px'; - } - }, - - _createImg: function (src, el) { - el = el || document.createElement('img'); - el.src = src; - return el; - }, - - _getIconUrl: function (name) { - if (L.Browser.retina && this.options[name + 'RetinaUrl']) { - return this.options[name + 'RetinaUrl']; - } - return this.options[name + 'Url']; - } -}); - -L.icon = function (options) { - return new L.Icon(options); -}; - - -/* - * L.Icon.Default is the blue marker icon used by default in Leaflet. - */ - -L.Icon.Default = L.Icon.extend({ - - options: { - iconSize: [25, 41], - iconAnchor: [12, 41], - popupAnchor: [1, -34], - - shadowSize: [41, 41] - }, - - _getIconUrl: function (name) { - var key = name + 'Url'; - - if (this.options[key]) { - return this.options[key]; - } - - if (L.Browser.retina && name === 'icon') { - name += '-2x'; - } - - var path = L.Icon.Default.imagePath; - - if (!path) { - throw new Error('Couldn\'t autodetect L.Icon.Default.imagePath, set it manually.'); - } - - return path + '/marker-' + name + '.png'; - } -}); - -L.Icon.Default.imagePath = (function () { - var scripts = document.getElementsByTagName('script'), - leafletRe = /[\/^]leaflet[\-\._]?([\w\-\._]*)\.js\??/; - - var i, len, src, matches, path; - - for (i = 0, len = scripts.length; i < len; i++) { - src = scripts[i].src; - matches = src.match(leafletRe); - - if (matches) { - path = src.split(leafletRe)[0]; - return (path ? path + '/' : '') + 'images'; - } - } -}()); - - -/* - * L.Marker is used to display clickable/draggable icons on the map. - */ - -L.Marker = L.Class.extend({ - - includes: L.Mixin.Events, - - options: { - icon: new L.Icon.Default(), - title: '', - alt: '', - clickable: true, - draggable: false, - keyboard: true, - zIndexOffset: 0, - opacity: 1, - riseOnHover: false, - riseOffset: 250 - }, - - initialize: function (latlng, options) { - L.setOptions(this, options); - this._latlng = L.latLng(latlng); - }, - - onAdd: function (map) { - this._map = map; - - map.on('viewreset', this.update, this); - - this._initIcon(); - this.update(); - this.fire('add'); - - if (map.options.zoomAnimation && map.options.markerZoomAnimation) { - map.on('zoomanim', this._animateZoom, this); - } - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - onRemove: function (map) { - if (this.dragging) { - this.dragging.disable(); - } - - this._removeIcon(); - this._removeShadow(); - - this.fire('remove'); - - map.off({ - 'viewreset': this.update, - 'zoomanim': this._animateZoom - }, this); - - this._map = null; - }, - - getLatLng: function () { - return this._latlng; - }, - - setLatLng: function (latlng) { - this._latlng = L.latLng(latlng); - - this.update(); - - return this.fire('move', { latlng: this._latlng }); - }, - - setZIndexOffset: function (offset) { - this.options.zIndexOffset = offset; - this.update(); - - return this; - }, - - setIcon: function (icon) { - - this.options.icon = icon; - - if (this._map) { - this._initIcon(); - this.update(); - } - - if (this._popup) { - this.bindPopup(this._popup); - } - - return this; - }, - - update: function () { - if (this._icon) { - this._setPos(this._map.latLngToLayerPoint(this._latlng).round()); - } - return this; - }, - - _initIcon: function () { - var options = this.options, - map = this._map, - animation = (map.options.zoomAnimation && map.options.markerZoomAnimation), - classToAdd = animation ? 'leaflet-zoom-animated' : 'leaflet-zoom-hide'; - - var icon = options.icon.createIcon(this._icon), - addIcon = false; - - // if we're not reusing the icon, remove the old one and init new one - if (icon !== this._icon) { - if (this._icon) { - this._removeIcon(); - } - addIcon = true; - - if (options.title) { - icon.title = options.title; - } - - if (options.alt) { - icon.alt = options.alt; - } - } - - L.DomUtil.addClass(icon, classToAdd); - - if (options.keyboard) { - icon.tabIndex = '0'; - } - - this._icon = icon; - - this._initInteraction(); - - if (options.riseOnHover) { - L.DomEvent - .on(icon, 'mouseover', this._bringToFront, this) - .on(icon, 'mouseout', this._resetZIndex, this); - } - - var newShadow = options.icon.createShadow(this._shadow), - addShadow = false; - - if (newShadow !== this._shadow) { - this._removeShadow(); - addShadow = true; - } - - if (newShadow) { - L.DomUtil.addClass(newShadow, classToAdd); - } - this._shadow = newShadow; - - - if (options.opacity < 1) { - this._updateOpacity(); - } - - - var panes = this._map._panes; - - if (addIcon) { - panes.markerPane.appendChild(this._icon); - } - - if (newShadow && addShadow) { - panes.shadowPane.appendChild(this._shadow); - } - }, - - _removeIcon: function () { - if (this.options.riseOnHover) { - L.DomEvent - .off(this._icon, 'mouseover', this._bringToFront) - .off(this._icon, 'mouseout', this._resetZIndex); - } - - this._map._panes.markerPane.removeChild(this._icon); - - this._icon = null; - }, - - _removeShadow: function () { - if (this._shadow) { - this._map._panes.shadowPane.removeChild(this._shadow); - } - this._shadow = null; - }, - - _setPos: function (pos) { - L.DomUtil.setPosition(this._icon, pos); - - if (this._shadow) { - L.DomUtil.setPosition(this._shadow, pos); - } - - this._zIndex = pos.y + this.options.zIndexOffset; - - this._resetZIndex(); - }, - - _updateZIndex: function (offset) { - this._icon.style.zIndex = this._zIndex + offset; - }, - - _animateZoom: function (opt) { - var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round(); - - this._setPos(pos); - }, - - _initInteraction: function () { - - if (!this.options.clickable) { return; } - - // TODO refactor into something shared with Map/Path/etc. to DRY it up - - var icon = this._icon, - events = ['dblclick', 'mousedown', 'mouseover', 'mouseout', 'contextmenu']; - - L.DomUtil.addClass(icon, 'leaflet-clickable'); - L.DomEvent.on(icon, 'click', this._onMouseClick, this); - L.DomEvent.on(icon, 'keypress', this._onKeyPress, this); - - for (var i = 0; i < events.length; i++) { - L.DomEvent.on(icon, events[i], this._fireMouseEvent, this); - } - - if (L.Handler.MarkerDrag) { - this.dragging = new L.Handler.MarkerDrag(this); - - if (this.options.draggable) { - this.dragging.enable(); - } - } - }, - - _onMouseClick: function (e) { - var wasDragged = this.dragging && this.dragging.moved(); - - if (this.hasEventListeners(e.type) || wasDragged) { - L.DomEvent.stopPropagation(e); - } - - if (wasDragged) { return; } - - if ((!this.dragging || !this.dragging._enabled) && this._map.dragging && this._map.dragging.moved()) { return; } - - this.fire(e.type, { - originalEvent: e, - latlng: this._latlng - }); - }, - - _onKeyPress: function (e) { - if (e.keyCode === 13) { - this.fire('click', { - originalEvent: e, - latlng: this._latlng - }); - } - }, - - _fireMouseEvent: function (e) { - - this.fire(e.type, { - originalEvent: e, - latlng: this._latlng - }); - - // TODO proper custom event propagation - // this line will always be called if marker is in a FeatureGroup - if (e.type === 'contextmenu' && this.hasEventListeners(e.type)) { - L.DomEvent.preventDefault(e); - } - if (e.type !== 'mousedown') { - L.DomEvent.stopPropagation(e); - } else { - L.DomEvent.preventDefault(e); - } - }, - - setOpacity: function (opacity) { - this.options.opacity = opacity; - if (this._map) { - this._updateOpacity(); - } - - return this; - }, - - _updateOpacity: function () { - L.DomUtil.setOpacity(this._icon, this.options.opacity); - if (this._shadow) { - L.DomUtil.setOpacity(this._shadow, this.options.opacity); - } - }, - - _bringToFront: function () { - this._updateZIndex(this.options.riseOffset); - }, - - _resetZIndex: function () { - this._updateZIndex(0); - } -}); - -L.marker = function (latlng, options) { - return new L.Marker(latlng, options); -}; - - -/* - * L.DivIcon is a lightweight HTML-based icon class (as opposed to the image-based L.Icon) - * to use with L.Marker. - */ - -L.DivIcon = L.Icon.extend({ - options: { - iconSize: [12, 12], // also can be set through CSS - /* - iconAnchor: (Point) - popupAnchor: (Point) - html: (String) - bgPos: (Point) - */ - className: 'leaflet-div-icon', - html: false - }, - - createIcon: function (oldIcon) { - var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'), - options = this.options; - - if (options.html !== false) { - div.innerHTML = options.html; - } else { - div.innerHTML = ''; - } - - if (options.bgPos) { - div.style.backgroundPosition = - (-options.bgPos.x) + 'px ' + (-options.bgPos.y) + 'px'; - } - - this._setIconStyles(div, 'icon'); - return div; - }, - - createShadow: function () { - return null; - } -}); - -L.divIcon = function (options) { - return new L.DivIcon(options); -}; - - -/* - * L.Popup is used for displaying popups on the map. - */ - -L.Map.mergeOptions({ - closePopupOnClick: true -}); - -L.Popup = L.Class.extend({ - includes: L.Mixin.Events, - - options: { - minWidth: 50, - maxWidth: 300, - // maxHeight: null, - autoPan: true, - closeButton: true, - offset: [0, 7], - autoPanPadding: [5, 5], - // autoPanPaddingTopLeft: null, - // autoPanPaddingBottomRight: null, - keepInView: false, - className: '', - zoomAnimation: true - }, - - initialize: function (options, source) { - L.setOptions(this, options); - - this._source = source; - this._animated = L.Browser.any3d && this.options.zoomAnimation; - this._isOpen = false; - }, - - onAdd: function (map) { - this._map = map; - - if (!this._container) { - this._initLayout(); - } - - var animFade = map.options.fadeAnimation; - - if (animFade) { - L.DomUtil.setOpacity(this._container, 0); - } - map._panes.popupPane.appendChild(this._container); - - map.on(this._getEvents(), this); - - this.update(); - - if (animFade) { - L.DomUtil.setOpacity(this._container, 1); - } - - this.fire('open'); - - map.fire('popupopen', {popup: this}); - - if (this._source) { - this._source.fire('popupopen', {popup: this}); - } - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - openOn: function (map) { - map.openPopup(this); - return this; - }, - - onRemove: function (map) { - map._panes.popupPane.removeChild(this._container); - - L.Util.falseFn(this._container.offsetWidth); // force reflow - - map.off(this._getEvents(), this); - - if (map.options.fadeAnimation) { - L.DomUtil.setOpacity(this._container, 0); - } - - this._map = null; - - this.fire('close'); - - map.fire('popupclose', {popup: this}); - - if (this._source) { - this._source.fire('popupclose', {popup: this}); - } - }, - - getLatLng: function () { - return this._latlng; - }, - - setLatLng: function (latlng) { - this._latlng = L.latLng(latlng); - if (this._map) { - this._updatePosition(); - this._adjustPan(); - } - return this; - }, - - getContent: function () { - return this._content; - }, - - setContent: function (content) { - this._content = content; - this.update(); - return this; - }, - - update: function () { - if (!this._map) { return; } - - this._container.style.visibility = 'hidden'; - - this._updateContent(); - this._updateLayout(); - this._updatePosition(); - - this._container.style.visibility = ''; - - this._adjustPan(); - }, - - _getEvents: function () { - var events = { - viewreset: this._updatePosition - }; - - if (this._animated) { - events.zoomanim = this._zoomAnimation; - } - if ('closeOnClick' in this.options ? this.options.closeOnClick : this._map.options.closePopupOnClick) { - events.preclick = this._close; - } - if (this.options.keepInView) { - events.moveend = this._adjustPan; - } - - return events; - }, - - _close: function () { - if (this._map) { - this._map.closePopup(this); - } - }, - - _initLayout: function () { - var prefix = 'leaflet-popup', - containerClass = prefix + ' ' + this.options.className + ' leaflet-zoom-' + - (this._animated ? 'animated' : 'hide'), - container = this._container = L.DomUtil.create('div', containerClass), - closeButton; - - if (this.options.closeButton) { - closeButton = this._closeButton = - L.DomUtil.create('a', prefix + '-close-button', container); - closeButton.href = '#close'; - closeButton.innerHTML = '×'; - L.DomEvent.disableClickPropagation(closeButton); - - L.DomEvent.on(closeButton, 'click', this._onCloseButtonClick, this); - } - - var wrapper = this._wrapper = - L.DomUtil.create('div', prefix + '-content-wrapper', container); - L.DomEvent.disableClickPropagation(wrapper); - - this._contentNode = L.DomUtil.create('div', prefix + '-content', wrapper); - - L.DomEvent.disableScrollPropagation(this._contentNode); - L.DomEvent.on(wrapper, 'contextmenu', L.DomEvent.stopPropagation); - - this._tipContainer = L.DomUtil.create('div', prefix + '-tip-container', container); - this._tip = L.DomUtil.create('div', prefix + '-tip', this._tipContainer); - }, - - _updateContent: function () { - if (!this._content) { return; } - - if (typeof this._content === 'string') { - this._contentNode.innerHTML = this._content; - } else { - while (this._contentNode.hasChildNodes()) { - this._contentNode.removeChild(this._contentNode.firstChild); - } - this._contentNode.appendChild(this._content); - } - this.fire('contentupdate'); - }, - - _updateLayout: function () { - var container = this._contentNode, - style = container.style; - - style.width = ''; - style.whiteSpace = 'nowrap'; - - var width = container.offsetWidth; - width = Math.min(width, this.options.maxWidth); - width = Math.max(width, this.options.minWidth); - - style.width = (width + 1) + 'px'; - style.whiteSpace = ''; - - style.height = ''; - - var height = container.offsetHeight, - maxHeight = this.options.maxHeight, - scrolledClass = 'leaflet-popup-scrolled'; - - if (maxHeight && height > maxHeight) { - style.height = maxHeight + 'px'; - L.DomUtil.addClass(container, scrolledClass); - } else { - L.DomUtil.removeClass(container, scrolledClass); - } - - this._containerWidth = this._container.offsetWidth; - }, - - _updatePosition: function () { - if (!this._map) { return; } - - var pos = this._map.latLngToLayerPoint(this._latlng), - animated = this._animated, - offset = L.point(this.options.offset); - - if (animated) { - L.DomUtil.setPosition(this._container, pos); - } - - this._containerBottom = -offset.y - (animated ? 0 : pos.y); - this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x + (animated ? 0 : pos.x); - - // bottom position the popup in case the height of the popup changes (images loading etc) - this._container.style.bottom = this._containerBottom + 'px'; - this._container.style.left = this._containerLeft + 'px'; - }, - - _zoomAnimation: function (opt) { - var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center); - - L.DomUtil.setPosition(this._container, pos); - }, - - _adjustPan: function () { - if (!this.options.autoPan) { return; } - - var map = this._map, - containerHeight = this._container.offsetHeight, - containerWidth = this._containerWidth, - - layerPos = new L.Point(this._containerLeft, -containerHeight - this._containerBottom); - - if (this._animated) { - layerPos._add(L.DomUtil.getPosition(this._container)); - } - - var containerPos = map.layerPointToContainerPoint(layerPos), - padding = L.point(this.options.autoPanPadding), - paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding), - paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding), - size = map.getSize(), - dx = 0, - dy = 0; - - if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right - dx = containerPos.x + containerWidth - size.x + paddingBR.x; - } - if (containerPos.x - dx - paddingTL.x < 0) { // left - dx = containerPos.x - paddingTL.x; - } - if (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom - dy = containerPos.y + containerHeight - size.y + paddingBR.y; - } - if (containerPos.y - dy - paddingTL.y < 0) { // top - dy = containerPos.y - paddingTL.y; - } - - if (dx || dy) { - map - .fire('autopanstart') - .panBy([dx, dy]); - } - }, - - _onCloseButtonClick: function (e) { - this._close(); - L.DomEvent.stop(e); - } -}); - -L.popup = function (options, source) { - return new L.Popup(options, source); -}; - - -L.Map.include({ - openPopup: function (popup, latlng, options) { // (Popup) or (String || HTMLElement, LatLng[, Object]) - this.closePopup(); - - if (!(popup instanceof L.Popup)) { - var content = popup; - - popup = new L.Popup(options) - .setLatLng(latlng) - .setContent(content); - } - popup._isOpen = true; - - this._popup = popup; - return this.addLayer(popup); - }, - - closePopup: function (popup) { - if (!popup || popup === this._popup) { - popup = this._popup; - this._popup = null; - } - if (popup) { - this.removeLayer(popup); - popup._isOpen = false; - } - return this; - } -}); - - -/* - * Popup extension to L.Marker, adding popup-related methods. - */ - -L.Marker.include({ - openPopup: function () { - if (this._popup && this._map && !this._map.hasLayer(this._popup)) { - this._popup.setLatLng(this._latlng); - this._map.openPopup(this._popup); - } - - return this; - }, - - closePopup: function () { - if (this._popup) { - this._popup._close(); - } - return this; - }, - - togglePopup: function () { - if (this._popup) { - if (this._popup._isOpen) { - this.closePopup(); - } else { - this.openPopup(); - } - } - return this; - }, - - bindPopup: function (content, options) { - var anchor = L.point(this.options.icon.options.popupAnchor || [0, 0]); - - anchor = anchor.add(L.Popup.prototype.options.offset); - - if (options && options.offset) { - anchor = anchor.add(options.offset); - } - - options = L.extend({offset: anchor}, options); - - if (!this._popupHandlersAdded) { - this - .on('click', this.togglePopup, this) - .on('remove', this.closePopup, this) - .on('move', this._movePopup, this); - this._popupHandlersAdded = true; - } - - if (content instanceof L.Popup) { - L.setOptions(content, options); - this._popup = content; - content._source = this; - } else { - this._popup = new L.Popup(options, this) - .setContent(content); - } - - return this; - }, - - setPopupContent: function (content) { - if (this._popup) { - this._popup.setContent(content); - } - return this; - }, - - unbindPopup: function () { - if (this._popup) { - this._popup = null; - this - .off('click', this.togglePopup, this) - .off('remove', this.closePopup, this) - .off('move', this._movePopup, this); - this._popupHandlersAdded = false; - } - return this; - }, - - getPopup: function () { - return this._popup; - }, - - _movePopup: function (e) { - this._popup.setLatLng(e.latlng); - } -}); - - -/* - * L.LayerGroup is a class to combine several layers into one so that - * you can manipulate the group (e.g. add/remove it) as one layer. - */ - -L.LayerGroup = L.Class.extend({ - initialize: function (layers) { - this._layers = {}; - - var i, len; - - if (layers) { - for (i = 0, len = layers.length; i < len; i++) { - this.addLayer(layers[i]); - } - } - }, - - addLayer: function (layer) { - var id = this.getLayerId(layer); - - this._layers[id] = layer; - - if (this._map) { - this._map.addLayer(layer); - } - - return this; - }, - - removeLayer: function (layer) { - var id = layer in this._layers ? layer : this.getLayerId(layer); - - if (this._map && this._layers[id]) { - this._map.removeLayer(this._layers[id]); - } - - delete this._layers[id]; - - return this; - }, - - hasLayer: function (layer) { - if (!layer) { return false; } - - return (layer in this._layers || this.getLayerId(layer) in this._layers); - }, - - clearLayers: function () { - this.eachLayer(this.removeLayer, this); - return this; - }, - - invoke: function (methodName) { - var args = Array.prototype.slice.call(arguments, 1), - i, layer; - - for (i in this._layers) { - layer = this._layers[i]; - - if (layer[methodName]) { - layer[methodName].apply(layer, args); - } - } - - return this; - }, - - onAdd: function (map) { - this._map = map; - this.eachLayer(map.addLayer, map); - }, - - onRemove: function (map) { - this.eachLayer(map.removeLayer, map); - this._map = null; - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - eachLayer: function (method, context) { - for (var i in this._layers) { - method.call(context, this._layers[i]); - } - return this; - }, - - getLayer: function (id) { - return this._layers[id]; - }, - - getLayers: function () { - var layers = []; - - for (var i in this._layers) { - layers.push(this._layers[i]); - } - return layers; - }, - - setZIndex: function (zIndex) { - return this.invoke('setZIndex', zIndex); - }, - - getLayerId: function (layer) { - return L.stamp(layer); - } -}); - -L.layerGroup = function (layers) { - return new L.LayerGroup(layers); -}; - - -/* - * L.FeatureGroup extends L.LayerGroup by introducing mouse events and additional methods - * shared between a group of interactive layers (like vectors or markers). - */ - -L.FeatureGroup = L.LayerGroup.extend({ - includes: L.Mixin.Events, - - statics: { - EVENTS: 'click dblclick mouseover mouseout mousemove contextmenu popupopen popupclose' - }, - - addLayer: function (layer) { - if (this.hasLayer(layer)) { - return this; - } - - if ('on' in layer) { - layer.on(L.FeatureGroup.EVENTS, this._propagateEvent, this); - } - - L.LayerGroup.prototype.addLayer.call(this, layer); - - if (this._popupContent && layer.bindPopup) { - layer.bindPopup(this._popupContent, this._popupOptions); - } - - return this.fire('layeradd', {layer: layer}); - }, - - removeLayer: function (layer) { - if (!this.hasLayer(layer)) { - return this; - } - if (layer in this._layers) { - layer = this._layers[layer]; - } - - if ('off' in layer) { - layer.off(L.FeatureGroup.EVENTS, this._propagateEvent, this); - } - - L.LayerGroup.prototype.removeLayer.call(this, layer); - - if (this._popupContent) { - this.invoke('unbindPopup'); - } - - return this.fire('layerremove', {layer: layer}); - }, - - bindPopup: function (content, options) { - this._popupContent = content; - this._popupOptions = options; - return this.invoke('bindPopup', content, options); - }, - - openPopup: function (latlng) { - // open popup on the first layer - for (var id in this._layers) { - this._layers[id].openPopup(latlng); - break; - } - return this; - }, - - setStyle: function (style) { - return this.invoke('setStyle', style); - }, - - bringToFront: function () { - return this.invoke('bringToFront'); - }, - - bringToBack: function () { - return this.invoke('bringToBack'); - }, - - getBounds: function () { - var bounds = new L.LatLngBounds(); - - this.eachLayer(function (layer) { - bounds.extend(layer instanceof L.Marker ? layer.getLatLng() : layer.getBounds()); - }); - - return bounds; - }, - - _propagateEvent: function (e) { - e = L.extend({ - layer: e.target, - target: this - }, e); - this.fire(e.type, e); - } -}); - -L.featureGroup = function (layers) { - return new L.FeatureGroup(layers); -}; - - -/* - * L.Path is a base class for rendering vector paths on a map. Inherited by Polyline, Circle, etc. - */ - -L.Path = L.Class.extend({ - includes: [L.Mixin.Events], - - statics: { - // how much to extend the clip area around the map view - // (relative to its size, e.g. 0.5 is half the screen in each direction) - // set it so that SVG element doesn't exceed 1280px (vectors flicker on dragend if it is) - CLIP_PADDING: (function () { - var max = L.Browser.mobile ? 1280 : 2000, - target = (max / Math.max(window.outerWidth, window.outerHeight) - 1) / 2; - return Math.max(0, Math.min(0.5, target)); - })() - }, - - options: { - stroke: true, - color: '#0033ff', - dashArray: null, - lineCap: null, - lineJoin: null, - weight: 5, - opacity: 0.5, - - fill: false, - fillColor: null, //same as color by default - fillOpacity: 0.2, - - clickable: true - }, - - initialize: function (options) { - L.setOptions(this, options); - }, - - onAdd: function (map) { - this._map = map; - - if (!this._container) { - this._initElements(); - this._initEvents(); - } - - this.projectLatlngs(); - this._updatePath(); - - if (this._container) { - this._map._pathRoot.appendChild(this._container); - } - - this.fire('add'); - - map.on({ - 'viewreset': this.projectLatlngs, - 'moveend': this._updatePath - }, this); - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - onRemove: function (map) { - map._pathRoot.removeChild(this._container); - - // Need to fire remove event before we set _map to null as the event hooks might need the object - this.fire('remove'); - this._map = null; - - if (L.Browser.vml) { - this._container = null; - this._stroke = null; - this._fill = null; - } - - map.off({ - 'viewreset': this.projectLatlngs, - 'moveend': this._updatePath - }, this); - }, - - projectLatlngs: function () { - // do all projection stuff here - }, - - setStyle: function (style) { - L.setOptions(this, style); - - if (this._container) { - this._updateStyle(); - } - - return this; - }, - - redraw: function () { - if (this._map) { - this.projectLatlngs(); - this._updatePath(); - } - return this; - } -}); - -L.Map.include({ - _updatePathViewport: function () { - var p = L.Path.CLIP_PADDING, - size = this.getSize(), - panePos = L.DomUtil.getPosition(this._mapPane), - min = panePos.multiplyBy(-1)._subtract(size.multiplyBy(p)._round()), - max = min.add(size.multiplyBy(1 + p * 2)._round()); - - this._pathViewport = new L.Bounds(min, max); - } -}); - - -/* - * Extends L.Path with SVG-specific rendering code. - */ - -L.Path.SVG_NS = 'http://www.w3.org/2000/svg'; - -L.Browser.svg = !!(document.createElementNS && document.createElementNS(L.Path.SVG_NS, 'svg').createSVGRect); - -L.Path = L.Path.extend({ - statics: { - SVG: L.Browser.svg - }, - - bringToFront: function () { - var root = this._map._pathRoot, - path = this._container; - - if (path && root.lastChild !== path) { - root.appendChild(path); - } - return this; - }, - - bringToBack: function () { - var root = this._map._pathRoot, - path = this._container, - first = root.firstChild; - - if (path && first !== path) { - root.insertBefore(path, first); - } - return this; - }, - - getPathString: function () { - // form path string here - }, - - _createElement: function (name) { - return document.createElementNS(L.Path.SVG_NS, name); - }, - - _initElements: function () { - this._map._initPathRoot(); - this._initPath(); - this._initStyle(); - }, - - _initPath: function () { - this._container = this._createElement('g'); - - this._path = this._createElement('path'); - - if (this.options.className) { - L.DomUtil.addClass(this._path, this.options.className); - } - - this._container.appendChild(this._path); - }, - - _initStyle: function () { - if (this.options.stroke) { - this._path.setAttribute('stroke-linejoin', 'round'); - this._path.setAttribute('stroke-linecap', 'round'); - } - if (this.options.fill) { - this._path.setAttribute('fill-rule', 'evenodd'); - } - if (this.options.pointerEvents) { - this._path.setAttribute('pointer-events', this.options.pointerEvents); - } - if (!this.options.clickable && !this.options.pointerEvents) { - this._path.setAttribute('pointer-events', 'none'); - } - this._updateStyle(); - }, - - _updateStyle: function () { - if (this.options.stroke) { - this._path.setAttribute('stroke', this.options.color); - this._path.setAttribute('stroke-opacity', this.options.opacity); - this._path.setAttribute('stroke-width', this.options.weight); - if (this.options.dashArray) { - this._path.setAttribute('stroke-dasharray', this.options.dashArray); - } else { - this._path.removeAttribute('stroke-dasharray'); - } - if (this.options.lineCap) { - this._path.setAttribute('stroke-linecap', this.options.lineCap); - } - if (this.options.lineJoin) { - this._path.setAttribute('stroke-linejoin', this.options.lineJoin); - } - } else { - this._path.setAttribute('stroke', 'none'); - } - if (this.options.fill) { - this._path.setAttribute('fill', this.options.fillColor || this.options.color); - this._path.setAttribute('fill-opacity', this.options.fillOpacity); - } else { - this._path.setAttribute('fill', 'none'); - } - }, - - _updatePath: function () { - var str = this.getPathString(); - if (!str) { - // fix webkit empty string parsing bug - str = 'M0 0'; - } - this._path.setAttribute('d', str); - }, - - // TODO remove duplication with L.Map - _initEvents: function () { - if (this.options.clickable) { - if (L.Browser.svg || !L.Browser.vml) { - L.DomUtil.addClass(this._path, 'leaflet-clickable'); - } - - L.DomEvent.on(this._container, 'click', this._onMouseClick, this); - - var events = ['dblclick', 'mousedown', 'mouseover', - 'mouseout', 'mousemove', 'contextmenu']; - for (var i = 0; i < events.length; i++) { - L.DomEvent.on(this._container, events[i], this._fireMouseEvent, this); - } - } - }, - - _onMouseClick: function (e) { - if (this._map.dragging && this._map.dragging.moved()) { return; } - - this._fireMouseEvent(e); - }, - - _fireMouseEvent: function (e) { - if (!this._map || !this.hasEventListeners(e.type)) { return; } - - var map = this._map, - containerPoint = map.mouseEventToContainerPoint(e), - layerPoint = map.containerPointToLayerPoint(containerPoint), - latlng = map.layerPointToLatLng(layerPoint); - - this.fire(e.type, { - latlng: latlng, - layerPoint: layerPoint, - containerPoint: containerPoint, - originalEvent: e - }); - - if (e.type === 'contextmenu') { - L.DomEvent.preventDefault(e); - } - if (e.type !== 'mousemove') { - L.DomEvent.stopPropagation(e); - } - } -}); - -L.Map.include({ - _initPathRoot: function () { - if (!this._pathRoot) { - this._pathRoot = L.Path.prototype._createElement('svg'); - this._panes.overlayPane.appendChild(this._pathRoot); - - if (this.options.zoomAnimation && L.Browser.any3d) { - L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-animated'); - - this.on({ - 'zoomanim': this._animatePathZoom, - 'zoomend': this._endPathZoom - }); - } else { - L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-hide'); - } - - this.on('moveend', this._updateSvgViewport); - this._updateSvgViewport(); - } - }, - - _animatePathZoom: function (e) { - var scale = this.getZoomScale(e.zoom), - offset = this._getCenterOffset(e.center)._multiplyBy(-scale)._add(this._pathViewport.min); - - this._pathRoot.style[L.DomUtil.TRANSFORM] = - L.DomUtil.getTranslateString(offset) + ' scale(' + scale + ') '; - - this._pathZooming = true; - }, - - _endPathZoom: function () { - this._pathZooming = false; - }, - - _updateSvgViewport: function () { - - if (this._pathZooming) { - // Do not update SVGs while a zoom animation is going on otherwise the animation will break. - // When the zoom animation ends we will be updated again anyway - // This fixes the case where you do a momentum move and zoom while the move is still ongoing. - return; - } - - this._updatePathViewport(); - - var vp = this._pathViewport, - min = vp.min, - max = vp.max, - width = max.x - min.x, - height = max.y - min.y, - root = this._pathRoot, - pane = this._panes.overlayPane; - - // Hack to make flicker on drag end on mobile webkit less irritating - if (L.Browser.mobileWebkit) { - pane.removeChild(root); - } - - L.DomUtil.setPosition(root, min); - root.setAttribute('width', width); - root.setAttribute('height', height); - root.setAttribute('viewBox', [min.x, min.y, width, height].join(' ')); - - if (L.Browser.mobileWebkit) { - pane.appendChild(root); - } - } -}); - - -/* - * Popup extension to L.Path (polylines, polygons, circles), adding popup-related methods. - */ - -L.Path.include({ - - bindPopup: function (content, options) { - - if (content instanceof L.Popup) { - this._popup = content; - } else { - if (!this._popup || options) { - this._popup = new L.Popup(options, this); - } - this._popup.setContent(content); - } - - if (!this._popupHandlersAdded) { - this - .on('click', this._openPopup, this) - .on('remove', this.closePopup, this); - - this._popupHandlersAdded = true; - } - - return this; - }, - - unbindPopup: function () { - if (this._popup) { - this._popup = null; - this - .off('click', this._openPopup) - .off('remove', this.closePopup); - - this._popupHandlersAdded = false; - } - return this; - }, - - openPopup: function (latlng) { - - if (this._popup) { - // open the popup from one of the path's points if not specified - latlng = latlng || this._latlng || - this._latlngs[Math.floor(this._latlngs.length / 2)]; - - this._openPopup({latlng: latlng}); - } - - return this; - }, - - closePopup: function () { - if (this._popup) { - this._popup._close(); - } - return this; - }, - - _openPopup: function (e) { - this._popup.setLatLng(e.latlng); - this._map.openPopup(this._popup); - } -}); - - -/* - * Vector rendering for IE6-8 through VML. - * Thanks to Dmitry Baranovsky and his Raphael library for inspiration! - */ - -L.Browser.vml = !L.Browser.svg && (function () { - try { - var div = document.createElement('div'); - div.innerHTML = '<v:shape adj="1"/>'; - - var shape = div.firstChild; - shape.style.behavior = 'url(#default#VML)'; - - return shape && (typeof shape.adj === 'object'); - - } catch (e) { - return false; - } -}()); - -L.Path = L.Browser.svg || !L.Browser.vml ? L.Path : L.Path.extend({ - statics: { - VML: true, - CLIP_PADDING: 0.02 - }, - - _createElement: (function () { - try { - document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml'); - return function (name) { - return document.createElement('<lvml:' + name + ' class="lvml">'); - }; - } catch (e) { - return function (name) { - return document.createElement( - '<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">'); - }; - } - }()), - - _initPath: function () { - var container = this._container = this._createElement('shape'); - - L.DomUtil.addClass(container, 'leaflet-vml-shape' + - (this.options.className ? ' ' + this.options.className : '')); - - if (this.options.clickable) { - L.DomUtil.addClass(container, 'leaflet-clickable'); - } - - container.coordsize = '1 1'; - - this._path = this._createElement('path'); - container.appendChild(this._path); - - this._map._pathRoot.appendChild(container); - }, - - _initStyle: function () { - this._updateStyle(); - }, - - _updateStyle: function () { - var stroke = this._stroke, - fill = this._fill, - options = this.options, - container = this._container; - - container.stroked = options.stroke; - container.filled = options.fill; - - if (options.stroke) { - if (!stroke) { - stroke = this._stroke = this._createElement('stroke'); - stroke.endcap = 'round'; - container.appendChild(stroke); - } - stroke.weight = options.weight + 'px'; - stroke.color = options.color; - stroke.opacity = options.opacity; - - if (options.dashArray) { - stroke.dashStyle = L.Util.isArray(options.dashArray) ? - options.dashArray.join(' ') : - options.dashArray.replace(/( *, *)/g, ' '); - } else { - stroke.dashStyle = ''; - } - if (options.lineCap) { - stroke.endcap = options.lineCap.replace('butt', 'flat'); - } - if (options.lineJoin) { - stroke.joinstyle = options.lineJoin; - } - - } else if (stroke) { - container.removeChild(stroke); - this._stroke = null; - } - - if (options.fill) { - if (!fill) { - fill = this._fill = this._createElement('fill'); - container.appendChild(fill); - } - fill.color = options.fillColor || options.color; - fill.opacity = options.fillOpacity; - - } else if (fill) { - container.removeChild(fill); - this._fill = null; - } - }, - - _updatePath: function () { - var style = this._container.style; - - style.display = 'none'; - this._path.v = this.getPathString() + ' '; // the space fixes IE empty path string bug - style.display = ''; - } -}); - -L.Map.include(L.Browser.svg || !L.Browser.vml ? {} : { - _initPathRoot: function () { - if (this._pathRoot) { return; } - - var root = this._pathRoot = document.createElement('div'); - root.className = 'leaflet-vml-container'; - this._panes.overlayPane.appendChild(root); - - this.on('moveend', this._updatePathViewport); - this._updatePathViewport(); - } -}); - - -/* - * Vector rendering for all browsers that support canvas. - */ - -L.Browser.canvas = (function () { - return !!document.createElement('canvas').getContext; -}()); - -L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({ - statics: { - //CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value - CANVAS: true, - SVG: false - }, - - redraw: function () { - if (this._map) { - this.projectLatlngs(); - this._requestUpdate(); - } - return this; - }, - - setStyle: function (style) { - L.setOptions(this, style); - - if (this._map) { - this._updateStyle(); - this._requestUpdate(); - } - return this; - }, - - onRemove: function (map) { - map - .off('viewreset', this.projectLatlngs, this) - .off('moveend', this._updatePath, this); - - if (this.options.clickable) { - this._map.off('click', this._onClick, this); - this._map.off('mousemove', this._onMouseMove, this); - } - - this._requestUpdate(); - - this.fire('remove'); - this._map = null; - }, - - _requestUpdate: function () { - if (this._map && !L.Path._updateRequest) { - L.Path._updateRequest = L.Util.requestAnimFrame(this._fireMapMoveEnd, this._map); - } - }, - - _fireMapMoveEnd: function () { - L.Path._updateRequest = null; - this.fire('moveend'); - }, - - _initElements: function () { - this._map._initPathRoot(); - this._ctx = this._map._canvasCtx; - }, - - _updateStyle: function () { - var options = this.options; - - if (options.stroke) { - this._ctx.lineWidth = options.weight; - this._ctx.strokeStyle = options.color; - } - if (options.fill) { - this._ctx.fillStyle = options.fillColor || options.color; - } - - if (options.lineCap) { - this._ctx.lineCap = options.lineCap; - } - if (options.lineJoin) { - this._ctx.lineJoin = options.lineJoin; - } - }, - - _drawPath: function () { - var i, j, len, len2, point, drawMethod; - - this._ctx.beginPath(); - - for (i = 0, len = this._parts.length; i < len; i++) { - for (j = 0, len2 = this._parts[i].length; j < len2; j++) { - point = this._parts[i][j]; - drawMethod = (j === 0 ? 'move' : 'line') + 'To'; - - this._ctx[drawMethod](point.x, point.y); - } - // TODO refactor ugly hack - if (this instanceof L.Polygon) { - this._ctx.closePath(); - } - } - }, - - _checkIfEmpty: function () { - return !this._parts.length; - }, - - _updatePath: function () { - if (this._checkIfEmpty()) { return; } - - var ctx = this._ctx, - options = this.options; - - this._drawPath(); - ctx.save(); - this._updateStyle(); - - if (options.fill) { - ctx.globalAlpha = options.fillOpacity; - ctx.fill(options.fillRule || 'evenodd'); - } - - if (options.stroke) { - ctx.globalAlpha = options.opacity; - ctx.stroke(); - } - - ctx.restore(); - - // TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature - }, - - _initEvents: function () { - if (this.options.clickable) { - this._map.on('mousemove', this._onMouseMove, this); - this._map.on('click dblclick contextmenu', this._fireMouseEvent, this); - } - }, - - _fireMouseEvent: function (e) { - if (this._containsPoint(e.layerPoint)) { - this.fire(e.type, e); - } - }, - - _onMouseMove: function (e) { - if (!this._map || this._map._animatingZoom) { return; } - - // TODO don't do on each move - if (this._containsPoint(e.layerPoint)) { - this._ctx.canvas.style.cursor = 'pointer'; - this._mouseInside = true; - this.fire('mouseover', e); - - } else if (this._mouseInside) { - this._ctx.canvas.style.cursor = ''; - this._mouseInside = false; - this.fire('mouseout', e); - } - } -}); - -L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : { - _initPathRoot: function () { - var root = this._pathRoot, - ctx; - - if (!root) { - root = this._pathRoot = document.createElement('canvas'); - root.style.position = 'absolute'; - ctx = this._canvasCtx = root.getContext('2d'); - - ctx.lineCap = 'round'; - ctx.lineJoin = 'round'; - - this._panes.overlayPane.appendChild(root); - - if (this.options.zoomAnimation) { - this._pathRoot.className = 'leaflet-zoom-animated'; - this.on('zoomanim', this._animatePathZoom); - this.on('zoomend', this._endPathZoom); - } - this.on('moveend', this._updateCanvasViewport); - this._updateCanvasViewport(); - } - }, - - _updateCanvasViewport: function () { - // don't redraw while zooming. See _updateSvgViewport for more details - if (this._pathZooming) { return; } - this._updatePathViewport(); - - var vp = this._pathViewport, - min = vp.min, - size = vp.max.subtract(min), - root = this._pathRoot; - - //TODO check if this works properly on mobile webkit - L.DomUtil.setPosition(root, min); - root.width = size.x; - root.height = size.y; - root.getContext('2d').translate(-min.x, -min.y); - } -}); - - -/* - * L.LineUtil contains different utility functions for line segments - * and polylines (clipping, simplification, distances, etc.) - */ - -/*jshint bitwise:false */ // allow bitwise operations for this file - -L.LineUtil = { - - // Simplify polyline with vertex reduction and Douglas-Peucker simplification. - // Improves rendering performance dramatically by lessening the number of points to draw. - - simplify: function (/*Point[]*/ points, /*Number*/ tolerance) { - if (!tolerance || !points.length) { - return points.slice(); - } - - var sqTolerance = tolerance * tolerance; - - // stage 1: vertex reduction - points = this._reducePoints(points, sqTolerance); - - // stage 2: Douglas-Peucker simplification - points = this._simplifyDP(points, sqTolerance); - - return points; - }, - - // distance from a point to a segment between two points - pointToSegmentDistance: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) { - return Math.sqrt(this._sqClosestPointOnSegment(p, p1, p2, true)); - }, - - closestPointOnSegment: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) { - return this._sqClosestPointOnSegment(p, p1, p2); - }, - - // Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm - _simplifyDP: function (points, sqTolerance) { - - var len = points.length, - ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array, - markers = new ArrayConstructor(len); - - markers[0] = markers[len - 1] = 1; - - this._simplifyDPStep(points, markers, sqTolerance, 0, len - 1); - - var i, - newPoints = []; - - for (i = 0; i < len; i++) { - if (markers[i]) { - newPoints.push(points[i]); - } - } - - return newPoints; - }, - - _simplifyDPStep: function (points, markers, sqTolerance, first, last) { - - var maxSqDist = 0, - index, i, sqDist; - - for (i = first + 1; i <= last - 1; i++) { - sqDist = this._sqClosestPointOnSegment(points[i], points[first], points[last], true); - - if (sqDist > maxSqDist) { - index = i; - maxSqDist = sqDist; - } - } - - if (maxSqDist > sqTolerance) { - markers[index] = 1; - - this._simplifyDPStep(points, markers, sqTolerance, first, index); - this._simplifyDPStep(points, markers, sqTolerance, index, last); - } - }, - - // reduce points that are too close to each other to a single point - _reducePoints: function (points, sqTolerance) { - var reducedPoints = [points[0]]; - - for (var i = 1, prev = 0, len = points.length; i < len; i++) { - if (this._sqDist(points[i], points[prev]) > sqTolerance) { - reducedPoints.push(points[i]); - prev = i; - } - } - if (prev < len - 1) { - reducedPoints.push(points[len - 1]); - } - return reducedPoints; - }, - - // Cohen-Sutherland line clipping algorithm. - // Used to avoid rendering parts of a polyline that are not currently visible. - - clipSegment: function (a, b, bounds, useLastCode) { - var codeA = useLastCode ? this._lastCode : this._getBitCode(a, bounds), - codeB = this._getBitCode(b, bounds), - - codeOut, p, newCode; - - // save 2nd code to avoid calculating it on the next segment - this._lastCode = codeB; - - while (true) { - // if a,b is inside the clip window (trivial accept) - if (!(codeA | codeB)) { - return [a, b]; - // if a,b is outside the clip window (trivial reject) - } else if (codeA & codeB) { - return false; - // other cases - } else { - codeOut = codeA || codeB; - p = this._getEdgeIntersection(a, b, codeOut, bounds); - newCode = this._getBitCode(p, bounds); - - if (codeOut === codeA) { - a = p; - codeA = newCode; - } else { - b = p; - codeB = newCode; - } - } - } - }, - - _getEdgeIntersection: function (a, b, code, bounds) { - var dx = b.x - a.x, - dy = b.y - a.y, - min = bounds.min, - max = bounds.max; - - if (code & 8) { // top - return new L.Point(a.x + dx * (max.y - a.y) / dy, max.y); - } else if (code & 4) { // bottom - return new L.Point(a.x + dx * (min.y - a.y) / dy, min.y); - } else if (code & 2) { // right - return new L.Point(max.x, a.y + dy * (max.x - a.x) / dx); - } else if (code & 1) { // left - return new L.Point(min.x, a.y + dy * (min.x - a.x) / dx); - } - }, - - _getBitCode: function (/*Point*/ p, bounds) { - var code = 0; - - if (p.x < bounds.min.x) { // left - code |= 1; - } else if (p.x > bounds.max.x) { // right - code |= 2; - } - if (p.y < bounds.min.y) { // bottom - code |= 4; - } else if (p.y > bounds.max.y) { // top - code |= 8; - } - - return code; - }, - - // square distance (to avoid unnecessary Math.sqrt calls) - _sqDist: function (p1, p2) { - var dx = p2.x - p1.x, - dy = p2.y - p1.y; - return dx * dx + dy * dy; - }, - - // return closest point on segment or distance to that point - _sqClosestPointOnSegment: function (p, p1, p2, sqDist) { - var x = p1.x, - y = p1.y, - dx = p2.x - x, - dy = p2.y - y, - dot = dx * dx + dy * dy, - t; - - if (dot > 0) { - t = ((p.x - x) * dx + (p.y - y) * dy) / dot; - - if (t > 1) { - x = p2.x; - y = p2.y; - } else if (t > 0) { - x += dx * t; - y += dy * t; - } - } - - dx = p.x - x; - dy = p.y - y; - - return sqDist ? dx * dx + dy * dy : new L.Point(x, y); - } -}; - - -/* - * L.Polyline is used to display polylines on a map. - */ - -L.Polyline = L.Path.extend({ - initialize: function (latlngs, options) { - L.Path.prototype.initialize.call(this, options); - - this._latlngs = this._convertLatLngs(latlngs); - }, - - options: { - // how much to simplify the polyline on each zoom level - // more = better performance and smoother look, less = more accurate - smoothFactor: 1.0, - noClip: false - }, - - projectLatlngs: function () { - this._originalPoints = []; - - for (var i = 0, len = this._latlngs.length; i < len; i++) { - this._originalPoints[i] = this._map.latLngToLayerPoint(this._latlngs[i]); - } - }, - - getPathString: function () { - for (var i = 0, len = this._parts.length, str = ''; i < len; i++) { - str += this._getPathPartStr(this._parts[i]); - } - return str; - }, - - getLatLngs: function () { - return this._latlngs; - }, - - setLatLngs: function (latlngs) { - this._latlngs = this._convertLatLngs(latlngs); - return this.redraw(); - }, - - addLatLng: function (latlng) { - this._latlngs.push(L.latLng(latlng)); - return this.redraw(); - }, - - spliceLatLngs: function () { // (Number index, Number howMany) - var removed = [].splice.apply(this._latlngs, arguments); - this._convertLatLngs(this._latlngs, true); - this.redraw(); - return removed; - }, - - closestLayerPoint: function (p) { - var minDistance = Infinity, parts = this._parts, p1, p2, minPoint = null; - - for (var j = 0, jLen = parts.length; j < jLen; j++) { - var points = parts[j]; - for (var i = 1, len = points.length; i < len; i++) { - p1 = points[i - 1]; - p2 = points[i]; - var sqDist = L.LineUtil._sqClosestPointOnSegment(p, p1, p2, true); - if (sqDist < minDistance) { - minDistance = sqDist; - minPoint = L.LineUtil._sqClosestPointOnSegment(p, p1, p2); - } - } - } - if (minPoint) { - minPoint.distance = Math.sqrt(minDistance); - } - return minPoint; - }, - - getBounds: function () { - return new L.LatLngBounds(this.getLatLngs()); - }, - - _convertLatLngs: function (latlngs, overwrite) { - var i, len, target = overwrite ? latlngs : []; - - for (i = 0, len = latlngs.length; i < len; i++) { - if (L.Util.isArray(latlngs[i]) && typeof latlngs[i][0] !== 'number') { - return; - } - target[i] = L.latLng(latlngs[i]); - } - return target; - }, - - _initEvents: function () { - L.Path.prototype._initEvents.call(this); - }, - - _getPathPartStr: function (points) { - var round = L.Path.VML; - - for (var j = 0, len2 = points.length, str = '', p; j < len2; j++) { - p = points[j]; - if (round) { - p._round(); - } - str += (j ? 'L' : 'M') + p.x + ' ' + p.y; - } - return str; - }, - - _clipPoints: function () { - var points = this._originalPoints, - len = points.length, - i, k, segment; - - if (this.options.noClip) { - this._parts = [points]; - return; - } - - this._parts = []; - - var parts = this._parts, - vp = this._map._pathViewport, - lu = L.LineUtil; - - for (i = 0, k = 0; i < len - 1; i++) { - segment = lu.clipSegment(points[i], points[i + 1], vp, i); - if (!segment) { - continue; - } - - parts[k] = parts[k] || []; - parts[k].push(segment[0]); - - // if segment goes out of screen, or it's the last one, it's the end of the line part - if ((segment[1] !== points[i + 1]) || (i === len - 2)) { - parts[k].push(segment[1]); - k++; - } - } - }, - - // simplify each clipped part of the polyline - _simplifyPoints: function () { - var parts = this._parts, - lu = L.LineUtil; - - for (var i = 0, len = parts.length; i < len; i++) { - parts[i] = lu.simplify(parts[i], this.options.smoothFactor); - } - }, - - _updatePath: function () { - if (!this._map) { return; } - - this._clipPoints(); - this._simplifyPoints(); - - L.Path.prototype._updatePath.call(this); - } -}); - -L.polyline = function (latlngs, options) { - return new L.Polyline(latlngs, options); -}; - - -/* - * L.PolyUtil contains utility functions for polygons (clipping, etc.). - */ - -/*jshint bitwise:false */ // allow bitwise operations here - -L.PolyUtil = {}; - -/* - * Sutherland-Hodgeman polygon clipping algorithm. - * Used to avoid rendering parts of a polygon that are not currently visible. - */ -L.PolyUtil.clipPolygon = function (points, bounds) { - var clippedPoints, - edges = [1, 4, 2, 8], - i, j, k, - a, b, - len, edge, p, - lu = L.LineUtil; - - for (i = 0, len = points.length; i < len; i++) { - points[i]._code = lu._getBitCode(points[i], bounds); - } - - // for each edge (left, bottom, right, top) - for (k = 0; k < 4; k++) { - edge = edges[k]; - clippedPoints = []; - - for (i = 0, len = points.length, j = len - 1; i < len; j = i++) { - a = points[i]; - b = points[j]; - - // if a is inside the clip window - if (!(a._code & edge)) { - // if b is outside the clip window (a->b goes out of screen) - if (b._code & edge) { - p = lu._getEdgeIntersection(b, a, edge, bounds); - p._code = lu._getBitCode(p, bounds); - clippedPoints.push(p); - } - clippedPoints.push(a); - - // else if b is inside the clip window (a->b enters the screen) - } else if (!(b._code & edge)) { - p = lu._getEdgeIntersection(b, a, edge, bounds); - p._code = lu._getBitCode(p, bounds); - clippedPoints.push(p); - } - } - points = clippedPoints; - } - - return points; -}; - - -/* - * L.Polygon is used to display polygons on a map. - */ - -L.Polygon = L.Polyline.extend({ - options: { - fill: true - }, - - initialize: function (latlngs, options) { - L.Polyline.prototype.initialize.call(this, latlngs, options); - this._initWithHoles(latlngs); - }, - - _initWithHoles: function (latlngs) { - var i, len, hole; - if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) { - this._latlngs = this._convertLatLngs(latlngs[0]); - this._holes = latlngs.slice(1); - - for (i = 0, len = this._holes.length; i < len; i++) { - hole = this._holes[i] = this._convertLatLngs(this._holes[i]); - if (hole[0].equals(hole[hole.length - 1])) { - hole.pop(); - } - } - } - - // filter out last point if its equal to the first one - latlngs = this._latlngs; - - if (latlngs.length >= 2 && latlngs[0].equals(latlngs[latlngs.length - 1])) { - latlngs.pop(); - } - }, - - projectLatlngs: function () { - L.Polyline.prototype.projectLatlngs.call(this); - - // project polygon holes points - // TODO move this logic to Polyline to get rid of duplication - this._holePoints = []; - - if (!this._holes) { return; } - - var i, j, len, len2; - - for (i = 0, len = this._holes.length; i < len; i++) { - this._holePoints[i] = []; - - for (j = 0, len2 = this._holes[i].length; j < len2; j++) { - this._holePoints[i][j] = this._map.latLngToLayerPoint(this._holes[i][j]); - } - } - }, - - setLatLngs: function (latlngs) { - if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) { - this._initWithHoles(latlngs); - return this.redraw(); - } else { - return L.Polyline.prototype.setLatLngs.call(this, latlngs); - } - }, - - _clipPoints: function () { - var points = this._originalPoints, - newParts = []; - - this._parts = [points].concat(this._holePoints); - - if (this.options.noClip) { return; } - - for (var i = 0, len = this._parts.length; i < len; i++) { - var clipped = L.PolyUtil.clipPolygon(this._parts[i], this._map._pathViewport); - if (clipped.length) { - newParts.push(clipped); - } - } - - this._parts = newParts; - }, - - _getPathPartStr: function (points) { - var str = L.Polyline.prototype._getPathPartStr.call(this, points); - return str + (L.Browser.svg ? 'z' : 'x'); - } -}); - -L.polygon = function (latlngs, options) { - return new L.Polygon(latlngs, options); -}; - - -/* - * Contains L.MultiPolyline and L.MultiPolygon layers. - */ - -(function () { - function createMulti(Klass) { - - return L.FeatureGroup.extend({ - - initialize: function (latlngs, options) { - this._layers = {}; - this._options = options; - this.setLatLngs(latlngs); - }, - - setLatLngs: function (latlngs) { - var i = 0, - len = latlngs.length; - - this.eachLayer(function (layer) { - if (i < len) { - layer.setLatLngs(latlngs[i++]); - } else { - this.removeLayer(layer); - } - }, this); - - while (i < len) { - this.addLayer(new Klass(latlngs[i++], this._options)); - } - - return this; - }, - - getLatLngs: function () { - var latlngs = []; - - this.eachLayer(function (layer) { - latlngs.push(layer.getLatLngs()); - }); - - return latlngs; - } - }); - } - - L.MultiPolyline = createMulti(L.Polyline); - L.MultiPolygon = createMulti(L.Polygon); - - L.multiPolyline = function (latlngs, options) { - return new L.MultiPolyline(latlngs, options); - }; - - L.multiPolygon = function (latlngs, options) { - return new L.MultiPolygon(latlngs, options); - }; -}()); - - -/* - * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object. - */ - -L.Rectangle = L.Polygon.extend({ - initialize: function (latLngBounds, options) { - L.Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options); - }, - - setBounds: function (latLngBounds) { - this.setLatLngs(this._boundsToLatLngs(latLngBounds)); - }, - - _boundsToLatLngs: function (latLngBounds) { - latLngBounds = L.latLngBounds(latLngBounds); - return [ - latLngBounds.getSouthWest(), - latLngBounds.getNorthWest(), - latLngBounds.getNorthEast(), - latLngBounds.getSouthEast() - ]; - } -}); - -L.rectangle = function (latLngBounds, options) { - return new L.Rectangle(latLngBounds, options); -}; - - -/* - * L.Circle is a circle overlay (with a certain radius in meters). - */ - -L.Circle = L.Path.extend({ - initialize: function (latlng, radius, options) { - L.Path.prototype.initialize.call(this, options); - - this._latlng = L.latLng(latlng); - this._mRadius = radius; - }, - - options: { - fill: true - }, - - setLatLng: function (latlng) { - this._latlng = L.latLng(latlng); - return this.redraw(); - }, - - setRadius: function (radius) { - this._mRadius = radius; - return this.redraw(); - }, - - projectLatlngs: function () { - var lngRadius = this._getLngRadius(), - latlng = this._latlng, - pointLeft = this._map.latLngToLayerPoint([latlng.lat, latlng.lng - lngRadius]); - - this._point = this._map.latLngToLayerPoint(latlng); - this._radius = Math.max(this._point.x - pointLeft.x, 1); - }, - - getBounds: function () { - var lngRadius = this._getLngRadius(), - latRadius = (this._mRadius / 40075017) * 360, - latlng = this._latlng; - - return new L.LatLngBounds( - [latlng.lat - latRadius, latlng.lng - lngRadius], - [latlng.lat + latRadius, latlng.lng + lngRadius]); - }, - - getLatLng: function () { - return this._latlng; - }, - - getPathString: function () { - var p = this._point, - r = this._radius; - - if (this._checkIfEmpty()) { - return ''; - } - - if (L.Browser.svg) { - return 'M' + p.x + ',' + (p.y - r) + - 'A' + r + ',' + r + ',0,1,1,' + - (p.x - 0.1) + ',' + (p.y - r) + ' z'; - } else { - p._round(); - r = Math.round(r); - return 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r + ' 0,' + (65535 * 360); - } - }, - - getRadius: function () { - return this._mRadius; - }, - - // TODO Earth hardcoded, move into projection code! - - _getLatRadius: function () { - return (this._mRadius / 40075017) * 360; - }, - - _getLngRadius: function () { - return this._getLatRadius() / Math.cos(L.LatLng.DEG_TO_RAD * this._latlng.lat); - }, - - _checkIfEmpty: function () { - if (!this._map) { - return false; - } - var vp = this._map._pathViewport, - r = this._radius, - p = this._point; - - return p.x - r > vp.max.x || p.y - r > vp.max.y || - p.x + r < vp.min.x || p.y + r < vp.min.y; - } -}); - -L.circle = function (latlng, radius, options) { - return new L.Circle(latlng, radius, options); -}; - - -/* - * L.CircleMarker is a circle overlay with a permanent pixel radius. - */ - -L.CircleMarker = L.Circle.extend({ - options: { - radius: 10, - weight: 2 - }, - - initialize: function (latlng, options) { - L.Circle.prototype.initialize.call(this, latlng, null, options); - this._radius = this.options.radius; - }, - - projectLatlngs: function () { - this._point = this._map.latLngToLayerPoint(this._latlng); - }, - - _updateStyle : function () { - L.Circle.prototype._updateStyle.call(this); - this.setRadius(this.options.radius); - }, - - setLatLng: function (latlng) { - L.Circle.prototype.setLatLng.call(this, latlng); - if (this._popup && this._popup._isOpen) { - this._popup.setLatLng(latlng); - } - return this; - }, - - setRadius: function (radius) { - this.options.radius = this._radius = radius; - return this.redraw(); - }, - - getRadius: function () { - return this._radius; - } -}); - -L.circleMarker = function (latlng, options) { - return new L.CircleMarker(latlng, options); -}; - - -/* - * Extends L.Polyline to be able to manually detect clicks on Canvas-rendered polylines. - */ - -L.Polyline.include(!L.Path.CANVAS ? {} : { - _containsPoint: function (p, closed) { - var i, j, k, len, len2, dist, part, - w = this.options.weight / 2; - - if (L.Browser.touch) { - w += 10; // polyline click tolerance on touch devices - } - - for (i = 0, len = this._parts.length; i < len; i++) { - part = this._parts[i]; - for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { - if (!closed && (j === 0)) { - continue; - } - - dist = L.LineUtil.pointToSegmentDistance(p, part[k], part[j]); - - if (dist <= w) { - return true; - } - } - } - return false; - } -}); - - -/* - * Extends L.Polygon to be able to manually detect clicks on Canvas-rendered polygons. - */ - -L.Polygon.include(!L.Path.CANVAS ? {} : { - _containsPoint: function (p) { - var inside = false, - part, p1, p2, - i, j, k, - len, len2; - - // TODO optimization: check if within bounds first - - if (L.Polyline.prototype._containsPoint.call(this, p, true)) { - // click on polygon border - return true; - } - - // ray casting algorithm for detecting if point is in polygon - - for (i = 0, len = this._parts.length; i < len; i++) { - part = this._parts[i]; - - for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { - p1 = part[j]; - p2 = part[k]; - - if (((p1.y > p.y) !== (p2.y > p.y)) && - (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) { - inside = !inside; - } - } - } - - return inside; - } -}); - - -/* - * Extends L.Circle with Canvas-specific code. - */ - -L.Circle.include(!L.Path.CANVAS ? {} : { - _drawPath: function () { - var p = this._point; - this._ctx.beginPath(); - this._ctx.arc(p.x, p.y, this._radius, 0, Math.PI * 2, false); - }, - - _containsPoint: function (p) { - var center = this._point, - w2 = this.options.stroke ? this.options.weight / 2 : 0; - - return (p.distanceTo(center) <= this._radius + w2); - } -}); - - -/* - * CircleMarker canvas specific drawing parts. - */ - -L.CircleMarker.include(!L.Path.CANVAS ? {} : { - _updateStyle: function () { - L.Path.prototype._updateStyle.call(this); - } -}); - - -/* - * L.GeoJSON turns any GeoJSON data into a Leaflet layer. - */ - -L.GeoJSON = L.FeatureGroup.extend({ - - initialize: function (geojson, options) { - L.setOptions(this, options); - - this._layers = {}; - - if (geojson) { - this.addData(geojson); - } - }, - - addData: function (geojson) { - var features = L.Util.isArray(geojson) ? geojson : geojson.features, - i, len, feature; - - if (features) { - for (i = 0, len = features.length; i < len; i++) { - // Only add this if geometry or geometries are set and not null - feature = features[i]; - if (feature.geometries || feature.geometry || feature.features || feature.coordinates) { - this.addData(features[i]); - } - } - return this; - } - - var options = this.options; - - if (options.filter && !options.filter(geojson)) { return; } - - var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng, options); - layer.feature = L.GeoJSON.asFeature(geojson); - - layer.defaultOptions = layer.options; - this.resetStyle(layer); - - if (options.onEachFeature) { - options.onEachFeature(geojson, layer); - } - - return this.addLayer(layer); - }, - - resetStyle: function (layer) { - var style = this.options.style; - if (style) { - // reset any custom styles - L.Util.extend(layer.options, layer.defaultOptions); - - this._setLayerStyle(layer, style); - } - }, - - setStyle: function (style) { - this.eachLayer(function (layer) { - this._setLayerStyle(layer, style); - }, this); - }, - - _setLayerStyle: function (layer, style) { - if (typeof style === 'function') { - style = style(layer.feature); - } - if (layer.setStyle) { - layer.setStyle(style); - } - } -}); - -L.extend(L.GeoJSON, { - geometryToLayer: function (geojson, pointToLayer, coordsToLatLng, vectorOptions) { - var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson, - coords = geometry.coordinates, - layers = [], - latlng, latlngs, i, len; - - coordsToLatLng = coordsToLatLng || this.coordsToLatLng; - - switch (geometry.type) { - case 'Point': - latlng = coordsToLatLng(coords); - return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng); - - case 'MultiPoint': - for (i = 0, len = coords.length; i < len; i++) { - latlng = coordsToLatLng(coords[i]); - layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng)); - } - return new L.FeatureGroup(layers); - - case 'LineString': - latlngs = this.coordsToLatLngs(coords, 0, coordsToLatLng); - return new L.Polyline(latlngs, vectorOptions); - - case 'Polygon': - if (coords.length === 2 && !coords[1].length) { - throw new Error('Invalid GeoJSON object.'); - } - latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng); - return new L.Polygon(latlngs, vectorOptions); - - case 'MultiLineString': - latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng); - return new L.MultiPolyline(latlngs, vectorOptions); - - case 'MultiPolygon': - latlngs = this.coordsToLatLngs(coords, 2, coordsToLatLng); - return new L.MultiPolygon(latlngs, vectorOptions); - - case 'GeometryCollection': - for (i = 0, len = geometry.geometries.length; i < len; i++) { - - layers.push(this.geometryToLayer({ - geometry: geometry.geometries[i], - type: 'Feature', - properties: geojson.properties - }, pointToLayer, coordsToLatLng, vectorOptions)); - } - return new L.FeatureGroup(layers); - - default: - throw new Error('Invalid GeoJSON object.'); - } - }, - - coordsToLatLng: function (coords) { // (Array[, Boolean]) -> LatLng - return new L.LatLng(coords[1], coords[0], coords[2]); - }, - - coordsToLatLngs: function (coords, levelsDeep, coordsToLatLng) { // (Array[, Number, Function]) -> Array - var latlng, i, len, - latlngs = []; - - for (i = 0, len = coords.length; i < len; i++) { - latlng = levelsDeep ? - this.coordsToLatLngs(coords[i], levelsDeep - 1, coordsToLatLng) : - (coordsToLatLng || this.coordsToLatLng)(coords[i]); - - latlngs.push(latlng); - } - - return latlngs; - }, - - latLngToCoords: function (latlng) { - var coords = [latlng.lng, latlng.lat]; - - if (latlng.alt !== undefined) { - coords.push(latlng.alt); - } - return coords; - }, - - latLngsToCoords: function (latLngs) { - var coords = []; - - for (var i = 0, len = latLngs.length; i < len; i++) { - coords.push(L.GeoJSON.latLngToCoords(latLngs[i])); - } - - return coords; - }, - - getFeature: function (layer, newGeometry) { - return layer.feature ? L.extend({}, layer.feature, {geometry: newGeometry}) : L.GeoJSON.asFeature(newGeometry); - }, - - asFeature: function (geoJSON) { - if (geoJSON.type === 'Feature') { - return geoJSON; - } - - return { - type: 'Feature', - properties: {}, - geometry: geoJSON - }; - } -}); - -var PointToGeoJSON = { - toGeoJSON: function () { - return L.GeoJSON.getFeature(this, { - type: 'Point', - coordinates: L.GeoJSON.latLngToCoords(this.getLatLng()) - }); - } -}; - -L.Marker.include(PointToGeoJSON); -L.Circle.include(PointToGeoJSON); -L.CircleMarker.include(PointToGeoJSON); - -L.Polyline.include({ - toGeoJSON: function () { - return L.GeoJSON.getFeature(this, { - type: 'LineString', - coordinates: L.GeoJSON.latLngsToCoords(this.getLatLngs()) - }); - } -}); - -L.Polygon.include({ - toGeoJSON: function () { - var coords = [L.GeoJSON.latLngsToCoords(this.getLatLngs())], - i, len, hole; - - coords[0].push(coords[0][0]); - - if (this._holes) { - for (i = 0, len = this._holes.length; i < len; i++) { - hole = L.GeoJSON.latLngsToCoords(this._holes[i]); - hole.push(hole[0]); - coords.push(hole); - } - } - - return L.GeoJSON.getFeature(this, { - type: 'Polygon', - coordinates: coords - }); - } -}); - -(function () { - function multiToGeoJSON(type) { - return function () { - var coords = []; - - this.eachLayer(function (layer) { - coords.push(layer.toGeoJSON().geometry.coordinates); - }); - - return L.GeoJSON.getFeature(this, { - type: type, - coordinates: coords - }); - }; - } - - L.MultiPolyline.include({toGeoJSON: multiToGeoJSON('MultiLineString')}); - L.MultiPolygon.include({toGeoJSON: multiToGeoJSON('MultiPolygon')}); - - L.LayerGroup.include({ - toGeoJSON: function () { - - var geometry = this.feature && this.feature.geometry, - jsons = [], - json; - - if (geometry && geometry.type === 'MultiPoint') { - return multiToGeoJSON('MultiPoint').call(this); - } - - var isGeometryCollection = geometry && geometry.type === 'GeometryCollection'; - - this.eachLayer(function (layer) { - if (layer.toGeoJSON) { - json = layer.toGeoJSON(); - jsons.push(isGeometryCollection ? json.geometry : L.GeoJSON.asFeature(json)); - } - }); - - if (isGeometryCollection) { - return L.GeoJSON.getFeature(this, { - geometries: jsons, - type: 'GeometryCollection' - }); - } - - return { - type: 'FeatureCollection', - features: jsons - }; - } - }); -}()); - -L.geoJson = function (geojson, options) { - return new L.GeoJSON(geojson, options); -}; - - -/* - * L.DomEvent contains functions for working with DOM events. - */ - -L.DomEvent = { - /* inspired by John Resig, Dean Edwards and YUI addEvent implementations */ - addListener: function (obj, type, fn, context) { // (HTMLElement, String, Function[, Object]) - - var id = L.stamp(fn), - key = '_leaflet_' + type + id, - handler, originalHandler, newType; - - if (obj[key]) { return this; } - - handler = function (e) { - return fn.call(context || obj, e || L.DomEvent._getEvent()); - }; - - if (L.Browser.pointer && type.indexOf('touch') === 0) { - return this.addPointerListener(obj, type, handler, id); - } - if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) { - this.addDoubleTapListener(obj, handler, id); - } - - if ('addEventListener' in obj) { - - if (type === 'mousewheel') { - obj.addEventListener('DOMMouseScroll', handler, false); - obj.addEventListener(type, handler, false); - - } else if ((type === 'mouseenter') || (type === 'mouseleave')) { - - originalHandler = handler; - newType = (type === 'mouseenter' ? 'mouseover' : 'mouseout'); - - handler = function (e) { - if (!L.DomEvent._checkMouse(obj, e)) { return; } - return originalHandler(e); - }; - - obj.addEventListener(newType, handler, false); - - } else if (type === 'click' && L.Browser.android) { - originalHandler = handler; - handler = function (e) { - return L.DomEvent._filterClick(e, originalHandler); - }; - - obj.addEventListener(type, handler, false); - } else { - obj.addEventListener(type, handler, false); - } - - } else if ('attachEvent' in obj) { - obj.attachEvent('on' + type, handler); - } - - obj[key] = handler; - - return this; - }, - - removeListener: function (obj, type, fn) { // (HTMLElement, String, Function) - - var id = L.stamp(fn), - key = '_leaflet_' + type + id, - handler = obj[key]; - - if (!handler) { return this; } - - if (L.Browser.pointer && type.indexOf('touch') === 0) { - this.removePointerListener(obj, type, id); - } else if (L.Browser.touch && (type === 'dblclick') && this.removeDoubleTapListener) { - this.removeDoubleTapListener(obj, id); - - } else if ('removeEventListener' in obj) { - - if (type === 'mousewheel') { - obj.removeEventListener('DOMMouseScroll', handler, false); - obj.removeEventListener(type, handler, false); - - } else if ((type === 'mouseenter') || (type === 'mouseleave')) { - obj.removeEventListener((type === 'mouseenter' ? 'mouseover' : 'mouseout'), handler, false); - } else { - obj.removeEventListener(type, handler, false); - } - } else if ('detachEvent' in obj) { - obj.detachEvent('on' + type, handler); - } - - obj[key] = null; - - return this; - }, - - stopPropagation: function (e) { - - if (e.stopPropagation) { - e.stopPropagation(); - } else { - e.cancelBubble = true; - } - L.DomEvent._skipped(e); - - return this; - }, - - disableScrollPropagation: function (el) { - var stop = L.DomEvent.stopPropagation; - - return L.DomEvent - .on(el, 'mousewheel', stop) - .on(el, 'MozMousePixelScroll', stop); - }, - - disableClickPropagation: function (el) { - var stop = L.DomEvent.stopPropagation; - - for (var i = L.Draggable.START.length - 1; i >= 0; i--) { - L.DomEvent.on(el, L.Draggable.START[i], stop); - } - - return L.DomEvent - .on(el, 'click', L.DomEvent._fakeStop) - .on(el, 'dblclick', stop); - }, - - preventDefault: function (e) { - - if (e.preventDefault) { - e.preventDefault(); - } else { - e.returnValue = false; - } - return this; - }, - - stop: function (e) { - return L.DomEvent - .preventDefault(e) - .stopPropagation(e); - }, - - getMousePosition: function (e, container) { - if (!container) { - return new L.Point(e.clientX, e.clientY); - } - - var rect = container.getBoundingClientRect(); - - return new L.Point( - e.clientX - rect.left - container.clientLeft, - e.clientY - rect.top - container.clientTop); - }, - - getWheelDelta: function (e) { - - var delta = 0; - - if (e.wheelDelta) { - delta = e.wheelDelta / 120; - } - if (e.detail) { - delta = -e.detail / 3; - } - return delta; - }, - - _skipEvents: {}, - - _fakeStop: function (e) { - // fakes stopPropagation by setting a special event flag, checked/reset with L.DomEvent._skipped(e) - L.DomEvent._skipEvents[e.type] = true; - }, - - _skipped: function (e) { - var skipped = this._skipEvents[e.type]; - // reset when checking, as it's only used in map container and propagates outside of the map - this._skipEvents[e.type] = false; - return skipped; - }, - - // check if element really left/entered the event target (for mouseenter/mouseleave) - _checkMouse: function (el, e) { - - var related = e.relatedTarget; - - if (!related) { return true; } - - try { - while (related && (related !== el)) { - related = related.parentNode; - } - } catch (err) { - return false; - } - return (related !== el); - }, - - _getEvent: function () { // evil magic for IE - /*jshint noarg:false */ - var e = window.event; - if (!e) { - var caller = arguments.callee.caller; - while (caller) { - e = caller['arguments'][0]; - if (e && window.Event === e.constructor) { - break; - } - caller = caller.caller; - } - } - return e; - }, - - // this is a horrible workaround for a bug in Android where a single touch triggers two click events - _filterClick: function (e, handler) { - var timeStamp = (e.timeStamp || e.originalEvent.timeStamp), - elapsed = L.DomEvent._lastClick && (timeStamp - L.DomEvent._lastClick); - - // are they closer together than 500ms yet more than 100ms? - // Android typically triggers them ~300ms apart while multiple listeners - // on the same event should be triggered far faster; - // or check if click is simulated on the element, and if it is, reject any non-simulated events - - if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) { - L.DomEvent.stop(e); - return; - } - L.DomEvent._lastClick = timeStamp; - - return handler(e); - } -}; - -L.DomEvent.on = L.DomEvent.addListener; -L.DomEvent.off = L.DomEvent.removeListener; - - -/* - * L.Draggable allows you to add dragging capabilities to any element. Supports mobile devices too. - */ - -L.Draggable = L.Class.extend({ - includes: L.Mixin.Events, - - statics: { - START: L.Browser.touch ? ['touchstart', 'mousedown'] : ['mousedown'], - END: { - mousedown: 'mouseup', - touchstart: 'touchend', - pointerdown: 'touchend', - MSPointerDown: 'touchend' - }, - MOVE: { - mousedown: 'mousemove', - touchstart: 'touchmove', - pointerdown: 'touchmove', - MSPointerDown: 'touchmove' - } - }, - - initialize: function (element, dragStartTarget) { - this._element = element; - this._dragStartTarget = dragStartTarget || element; - }, - - enable: function () { - if (this._enabled) { return; } - - for (var i = L.Draggable.START.length - 1; i >= 0; i--) { - L.DomEvent.on(this._dragStartTarget, L.Draggable.START[i], this._onDown, this); - } - - this._enabled = true; - }, - - disable: function () { - if (!this._enabled) { return; } - - for (var i = L.Draggable.START.length - 1; i >= 0; i--) { - L.DomEvent.off(this._dragStartTarget, L.Draggable.START[i], this._onDown, this); - } - - this._enabled = false; - this._moved = false; - }, - - _onDown: function (e) { - this._moved = false; - - if (e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; } - - L.DomEvent.stopPropagation(e); - - if (L.Draggable._disabled) { return; } - - L.DomUtil.disableImageDrag(); - L.DomUtil.disableTextSelection(); - - if (this._moving) { return; } - - var first = e.touches ? e.touches[0] : e; - - this._startPoint = new L.Point(first.clientX, first.clientY); - this._startPos = this._newPos = L.DomUtil.getPosition(this._element); - - L.DomEvent - .on(document, L.Draggable.MOVE[e.type], this._onMove, this) - .on(document, L.Draggable.END[e.type], this._onUp, this); - }, - - _onMove: function (e) { - if (e.touches && e.touches.length > 1) { - this._moved = true; - return; - } - - var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e), - newPoint = new L.Point(first.clientX, first.clientY), - offset = newPoint.subtract(this._startPoint); - - if (!offset.x && !offset.y) { return; } - if (L.Browser.touch && Math.abs(offset.x) + Math.abs(offset.y) < 3) { return; } - - L.DomEvent.preventDefault(e); - - if (!this._moved) { - this.fire('dragstart'); - - this._moved = true; - this._startPos = L.DomUtil.getPosition(this._element).subtract(offset); - - L.DomUtil.addClass(document.body, 'leaflet-dragging'); - this._lastTarget = e.target || e.srcElement; - L.DomUtil.addClass(this._lastTarget, 'leaflet-drag-target'); - } - - this._newPos = this._startPos.add(offset); - this._moving = true; - - L.Util.cancelAnimFrame(this._animRequest); - this._animRequest = L.Util.requestAnimFrame(this._updatePosition, this, true, this._dragStartTarget); - }, - - _updatePosition: function () { - this.fire('predrag'); - L.DomUtil.setPosition(this._element, this._newPos); - this.fire('drag'); - }, - - _onUp: function () { - L.DomUtil.removeClass(document.body, 'leaflet-dragging'); - - if (this._lastTarget) { - L.DomUtil.removeClass(this._lastTarget, 'leaflet-drag-target'); - this._lastTarget = null; - } - - for (var i in L.Draggable.MOVE) { - L.DomEvent - .off(document, L.Draggable.MOVE[i], this._onMove) - .off(document, L.Draggable.END[i], this._onUp); - } - - L.DomUtil.enableImageDrag(); - L.DomUtil.enableTextSelection(); - - if (this._moved && this._moving) { - // ensure drag is not fired after dragend - L.Util.cancelAnimFrame(this._animRequest); - - this.fire('dragend', { - distance: this._newPos.distanceTo(this._startPos) - }); - } - - this._moving = false; - } -}); - - -/* - L.Handler is a base class for handler classes that are used internally to inject - interaction features like dragging to classes like Map and Marker. -*/ - -L.Handler = L.Class.extend({ - initialize: function (map) { - this._map = map; - }, - - enable: function () { - if (this._enabled) { return; } - - this._enabled = true; - this.addHooks(); - }, - - disable: function () { - if (!this._enabled) { return; } - - this._enabled = false; - this.removeHooks(); - }, - - enabled: function () { - return !!this._enabled; - } -}); - - -/* - * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default. - */ - -L.Map.mergeOptions({ - dragging: true, - - inertia: !L.Browser.android23, - inertiaDeceleration: 3400, // px/s^2 - inertiaMaxSpeed: Infinity, // px/s - inertiaThreshold: L.Browser.touch ? 32 : 18, // ms - easeLinearity: 0.25, - - // TODO refactor, move to CRS - worldCopyJump: false -}); - -L.Map.Drag = L.Handler.extend({ - addHooks: function () { - if (!this._draggable) { - var map = this._map; - - this._draggable = new L.Draggable(map._mapPane, map._container); - - this._draggable.on({ - 'dragstart': this._onDragStart, - 'drag': this._onDrag, - 'dragend': this._onDragEnd - }, this); - - if (map.options.worldCopyJump) { - this._draggable.on('predrag', this._onPreDrag, this); - map.on('viewreset', this._onViewReset, this); - - map.whenReady(this._onViewReset, this); - } - } - this._draggable.enable(); - }, - - removeHooks: function () { - this._draggable.disable(); - }, - - moved: function () { - return this._draggable && this._draggable._moved; - }, - - _onDragStart: function () { - var map = this._map; - - if (map._panAnim) { - map._panAnim.stop(); - } - - map - .fire('movestart') - .fire('dragstart'); - - if (map.options.inertia) { - this._positions = []; - this._times = []; - } - }, - - _onDrag: function () { - if (this._map.options.inertia) { - var time = this._lastTime = +new Date(), - pos = this._lastPos = this._draggable._newPos; - - this._positions.push(pos); - this._times.push(time); - - if (time - this._times[0] > 200) { - this._positions.shift(); - this._times.shift(); - } - } - - this._map - .fire('move') - .fire('drag'); - }, - - _onViewReset: function () { - // TODO fix hardcoded Earth values - var pxCenter = this._map.getSize()._divideBy(2), - pxWorldCenter = this._map.latLngToLayerPoint([0, 0]); - - this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x; - this._worldWidth = this._map.project([0, 180]).x; - }, - - _onPreDrag: function () { - // TODO refactor to be able to adjust map pane position after zoom - var worldWidth = this._worldWidth, - halfWidth = Math.round(worldWidth / 2), - dx = this._initialWorldOffset, - x = this._draggable._newPos.x, - newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx, - newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx, - newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2; - - this._draggable._newPos.x = newX; - }, - - _onDragEnd: function (e) { - var map = this._map, - options = map.options, - delay = +new Date() - this._lastTime, - - noInertia = !options.inertia || delay > options.inertiaThreshold || !this._positions[0]; - - map.fire('dragend', e); - - if (noInertia) { - map.fire('moveend'); - - } else { - - var direction = this._lastPos.subtract(this._positions[0]), - duration = (this._lastTime + delay - this._times[0]) / 1000, - ease = options.easeLinearity, - - speedVector = direction.multiplyBy(ease / duration), - speed = speedVector.distanceTo([0, 0]), - - limitedSpeed = Math.min(options.inertiaMaxSpeed, speed), - limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed), - - decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease), - offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round(); - - if (!offset.x || !offset.y) { - map.fire('moveend'); - - } else { - offset = map._limitOffset(offset, map.options.maxBounds); - - L.Util.requestAnimFrame(function () { - map.panBy(offset, { - duration: decelerationDuration, - easeLinearity: ease, - noMoveStart: true - }); - }); - } - } - } -}); - -L.Map.addInitHook('addHandler', 'dragging', L.Map.Drag); - - -/* - * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default. - */ - -L.Map.mergeOptions({ - doubleClickZoom: true -}); - -L.Map.DoubleClickZoom = L.Handler.extend({ - addHooks: function () { - this._map.on('dblclick', this._onDoubleClick, this); - }, - - removeHooks: function () { - this._map.off('dblclick', this._onDoubleClick, this); - }, - - _onDoubleClick: function (e) { - var map = this._map, - zoom = map.getZoom() + (e.originalEvent.shiftKey ? -1 : 1); - - if (map.options.doubleClickZoom === 'center') { - map.setZoom(zoom); - } else { - map.setZoomAround(e.containerPoint, zoom); - } - } -}); - -L.Map.addInitHook('addHandler', 'doubleClickZoom', L.Map.DoubleClickZoom); - - -/* - * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map. - */ - -L.Map.mergeOptions({ - scrollWheelZoom: true -}); - -L.Map.ScrollWheelZoom = L.Handler.extend({ - addHooks: function () { - L.DomEvent.on(this._map._container, 'mousewheel', this._onWheelScroll, this); - L.DomEvent.on(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault); - this._delta = 0; - }, - - removeHooks: function () { - L.DomEvent.off(this._map._container, 'mousewheel', this._onWheelScroll); - L.DomEvent.off(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault); - }, - - _onWheelScroll: function (e) { - var delta = L.DomEvent.getWheelDelta(e); - - this._delta += delta; - this._lastMousePos = this._map.mouseEventToContainerPoint(e); - - if (!this._startTime) { - this._startTime = +new Date(); - } - - var left = Math.max(40 - (+new Date() - this._startTime), 0); - - clearTimeout(this._timer); - this._timer = setTimeout(L.bind(this._performZoom, this), left); - - L.DomEvent.preventDefault(e); - L.DomEvent.stopPropagation(e); - }, - - _performZoom: function () { - var map = this._map, - delta = this._delta, - zoom = map.getZoom(); - - delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta); - delta = Math.max(Math.min(delta, 4), -4); - delta = map._limitZoom(zoom + delta) - zoom; - - this._delta = 0; - this._startTime = null; - - if (!delta) { return; } - - if (map.options.scrollWheelZoom === 'center') { - map.setZoom(zoom + delta); - } else { - map.setZoomAround(this._lastMousePos, zoom + delta); - } - } -}); - -L.Map.addInitHook('addHandler', 'scrollWheelZoom', L.Map.ScrollWheelZoom); - - -/* - * Extends the event handling code with double tap support for mobile browsers. - */ - -L.extend(L.DomEvent, { - - _touchstart: L.Browser.msPointer ? 'MSPointerDown' : L.Browser.pointer ? 'pointerdown' : 'touchstart', - _touchend: L.Browser.msPointer ? 'MSPointerUp' : L.Browser.pointer ? 'pointerup' : 'touchend', - - // inspired by Zepto touch code by Thomas Fuchs - addDoubleTapListener: function (obj, handler, id) { - var last, - doubleTap = false, - delay = 250, - touch, - pre = '_leaflet_', - touchstart = this._touchstart, - touchend = this._touchend, - trackedTouches = []; - - function onTouchStart(e) { - var count; - - if (L.Browser.pointer) { - trackedTouches.push(e.pointerId); - count = trackedTouches.length; - } else { - count = e.touches.length; - } - if (count > 1) { - return; - } - - var now = Date.now(), - delta = now - (last || now); - - touch = e.touches ? e.touches[0] : e; - doubleTap = (delta > 0 && delta <= delay); - last = now; - } - - function onTouchEnd(e) { - if (L.Browser.pointer) { - var idx = trackedTouches.indexOf(e.pointerId); - if (idx === -1) { - return; - } - trackedTouches.splice(idx, 1); - } - - if (doubleTap) { - if (L.Browser.pointer) { - // work around .type being readonly with MSPointer* events - var newTouch = { }, - prop; - - // jshint forin:false - for (var i in touch) { - prop = touch[i]; - if (typeof prop === 'function') { - newTouch[i] = prop.bind(touch); - } else { - newTouch[i] = prop; - } - } - touch = newTouch; - } - touch.type = 'dblclick'; - handler(touch); - last = null; - } - } - obj[pre + touchstart + id] = onTouchStart; - obj[pre + touchend + id] = onTouchEnd; - - // on pointer we need to listen on the document, otherwise a drag starting on the map and moving off screen - // will not come through to us, so we will lose track of how many touches are ongoing - var endElement = L.Browser.pointer ? document.documentElement : obj; - - obj.addEventListener(touchstart, onTouchStart, false); - endElement.addEventListener(touchend, onTouchEnd, false); - - if (L.Browser.pointer) { - endElement.addEventListener(L.DomEvent.POINTER_CANCEL, onTouchEnd, false); - } - - return this; - }, - - removeDoubleTapListener: function (obj, id) { - var pre = '_leaflet_'; - - obj.removeEventListener(this._touchstart, obj[pre + this._touchstart + id], false); - (L.Browser.pointer ? document.documentElement : obj).removeEventListener( - this._touchend, obj[pre + this._touchend + id], false); - - if (L.Browser.pointer) { - document.documentElement.removeEventListener(L.DomEvent.POINTER_CANCEL, obj[pre + this._touchend + id], - false); - } - - return this; - } -}); - - -/* - * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices. - */ - -L.extend(L.DomEvent, { - - //static - POINTER_DOWN: L.Browser.msPointer ? 'MSPointerDown' : 'pointerdown', - POINTER_MOVE: L.Browser.msPointer ? 'MSPointerMove' : 'pointermove', - POINTER_UP: L.Browser.msPointer ? 'MSPointerUp' : 'pointerup', - POINTER_CANCEL: L.Browser.msPointer ? 'MSPointerCancel' : 'pointercancel', - - _pointers: [], - _pointerDocumentListener: false, - - // Provides a touch events wrapper for (ms)pointer events. - // Based on changes by veproza https://github.com/CloudMade/Leaflet/pull/1019 - //ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890 - - addPointerListener: function (obj, type, handler, id) { - - switch (type) { - case 'touchstart': - return this.addPointerListenerStart(obj, type, handler, id); - case 'touchend': - return this.addPointerListenerEnd(obj, type, handler, id); - case 'touchmove': - return this.addPointerListenerMove(obj, type, handler, id); - default: - throw 'Unknown touch event type'; - } - }, - - addPointerListenerStart: function (obj, type, handler, id) { - var pre = '_leaflet_', - pointers = this._pointers; - - var cb = function (e) { - if (e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) { - L.DomEvent.preventDefault(e); - } - - var alreadyInArray = false; - for (var i = 0; i < pointers.length; i++) { - if (pointers[i].pointerId === e.pointerId) { - alreadyInArray = true; - break; - } - } - if (!alreadyInArray) { - pointers.push(e); - } - - e.touches = pointers.slice(); - e.changedTouches = [e]; - - handler(e); - }; - - obj[pre + 'touchstart' + id] = cb; - obj.addEventListener(this.POINTER_DOWN, cb, false); - - // need to also listen for end events to keep the _pointers list accurate - // this needs to be on the body and never go away - if (!this._pointerDocumentListener) { - var internalCb = function (e) { - for (var i = 0; i < pointers.length; i++) { - if (pointers[i].pointerId === e.pointerId) { - pointers.splice(i, 1); - break; - } - } - }; - //We listen on the documentElement as any drags that end by moving the touch off the screen get fired there - document.documentElement.addEventListener(this.POINTER_UP, internalCb, false); - document.documentElement.addEventListener(this.POINTER_CANCEL, internalCb, false); - - this._pointerDocumentListener = true; - } - - return this; - }, - - addPointerListenerMove: function (obj, type, handler, id) { - var pre = '_leaflet_', - touches = this._pointers; - - function cb(e) { - - // don't fire touch moves when mouse isn't down - if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; } - - for (var i = 0; i < touches.length; i++) { - if (touches[i].pointerId === e.pointerId) { - touches[i] = e; - break; - } - } - - e.touches = touches.slice(); - e.changedTouches = [e]; - - handler(e); - } - - obj[pre + 'touchmove' + id] = cb; - obj.addEventListener(this.POINTER_MOVE, cb, false); - - return this; - }, - - addPointerListenerEnd: function (obj, type, handler, id) { - var pre = '_leaflet_', - touches = this._pointers; - - var cb = function (e) { - for (var i = 0; i < touches.length; i++) { - if (touches[i].pointerId === e.pointerId) { - touches.splice(i, 1); - break; - } - } - - e.touches = touches.slice(); - e.changedTouches = [e]; - - handler(e); - }; - - obj[pre + 'touchend' + id] = cb; - obj.addEventListener(this.POINTER_UP, cb, false); - obj.addEventListener(this.POINTER_CANCEL, cb, false); - - return this; - }, - - removePointerListener: function (obj, type, id) { - var pre = '_leaflet_', - cb = obj[pre + type + id]; - - switch (type) { - case 'touchstart': - obj.removeEventListener(this.POINTER_DOWN, cb, false); - break; - case 'touchmove': - obj.removeEventListener(this.POINTER_MOVE, cb, false); - break; - case 'touchend': - obj.removeEventListener(this.POINTER_UP, cb, false); - obj.removeEventListener(this.POINTER_CANCEL, cb, false); - break; - } - - return this; - } -}); - - -/* - * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers. - */ - -L.Map.mergeOptions({ - touchZoom: L.Browser.touch && !L.Browser.android23, - bounceAtZoomLimits: true -}); - -L.Map.TouchZoom = L.Handler.extend({ - addHooks: function () { - L.DomEvent.on(this._map._container, 'touchstart', this._onTouchStart, this); - }, - - removeHooks: function () { - L.DomEvent.off(this._map._container, 'touchstart', this._onTouchStart, this); - }, - - _onTouchStart: function (e) { - var map = this._map; - - if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; } - - var p1 = map.mouseEventToLayerPoint(e.touches[0]), - p2 = map.mouseEventToLayerPoint(e.touches[1]), - viewCenter = map._getCenterLayerPoint(); - - this._startCenter = p1.add(p2)._divideBy(2); - this._startDist = p1.distanceTo(p2); - - this._moved = false; - this._zooming = true; - - this._centerOffset = viewCenter.subtract(this._startCenter); - - if (map._panAnim) { - map._panAnim.stop(); - } - - L.DomEvent - .on(document, 'touchmove', this._onTouchMove, this) - .on(document, 'touchend', this._onTouchEnd, this); - - L.DomEvent.preventDefault(e); - }, - - _onTouchMove: function (e) { - var map = this._map; - - if (!e.touches || e.touches.length !== 2 || !this._zooming) { return; } - - var p1 = map.mouseEventToLayerPoint(e.touches[0]), - p2 = map.mouseEventToLayerPoint(e.touches[1]); - - this._scale = p1.distanceTo(p2) / this._startDist; - this._delta = p1._add(p2)._divideBy(2)._subtract(this._startCenter); - - if (this._scale === 1) { return; } - - if (!map.options.bounceAtZoomLimits) { - if ((map.getZoom() === map.getMinZoom() && this._scale < 1) || - (map.getZoom() === map.getMaxZoom() && this._scale > 1)) { return; } - } - - if (!this._moved) { - L.DomUtil.addClass(map._mapPane, 'leaflet-touching'); - - map - .fire('movestart') - .fire('zoomstart'); - - this._moved = true; - } - - L.Util.cancelAnimFrame(this._animRequest); - this._animRequest = L.Util.requestAnimFrame( - this._updateOnMove, this, true, this._map._container); - - L.DomEvent.preventDefault(e); - }, - - _updateOnMove: function () { - var map = this._map, - origin = this._getScaleOrigin(), - center = map.layerPointToLatLng(origin), - zoom = map.getScaleZoom(this._scale); - - map._animateZoom(center, zoom, this._startCenter, this._scale, this._delta, false, true); - }, - - _onTouchEnd: function () { - if (!this._moved || !this._zooming) { - this._zooming = false; - return; - } - - var map = this._map; - - this._zooming = false; - L.DomUtil.removeClass(map._mapPane, 'leaflet-touching'); - L.Util.cancelAnimFrame(this._animRequest); - - L.DomEvent - .off(document, 'touchmove', this._onTouchMove) - .off(document, 'touchend', this._onTouchEnd); - - var origin = this._getScaleOrigin(), - center = map.layerPointToLatLng(origin), - - oldZoom = map.getZoom(), - floatZoomDelta = map.getScaleZoom(this._scale) - oldZoom, - roundZoomDelta = (floatZoomDelta > 0 ? - Math.ceil(floatZoomDelta) : Math.floor(floatZoomDelta)), - - zoom = map._limitZoom(oldZoom + roundZoomDelta), - scale = map.getZoomScale(zoom) / this._scale; - - map._animateZoom(center, zoom, origin, scale); - }, - - _getScaleOrigin: function () { - var centerOffset = this._centerOffset.subtract(this._delta).divideBy(this._scale); - return this._startCenter.add(centerOffset); - } -}); - -L.Map.addInitHook('addHandler', 'touchZoom', L.Map.TouchZoom); - - -/* - * L.Map.Tap is used to enable mobile hacks like quick taps and long hold. - */ - -L.Map.mergeOptions({ - tap: true, - tapTolerance: 15 -}); - -L.Map.Tap = L.Handler.extend({ - addHooks: function () { - L.DomEvent.on(this._map._container, 'touchstart', this._onDown, this); - }, - - removeHooks: function () { - L.DomEvent.off(this._map._container, 'touchstart', this._onDown, this); - }, - - _onDown: function (e) { - if (!e.touches) { return; } - - L.DomEvent.preventDefault(e); - - this._fireClick = true; - - // don't simulate click or track longpress if more than 1 touch - if (e.touches.length > 1) { - this._fireClick = false; - clearTimeout(this._holdTimeout); - return; - } - - var first = e.touches[0], - el = first.target; - - this._startPos = this._newPos = new L.Point(first.clientX, first.clientY); - - // if touching a link, highlight it - if (el.tagName && el.tagName.toLowerCase() === 'a') { - L.DomUtil.addClass(el, 'leaflet-active'); - } - - // simulate long hold but setting a timeout - this._holdTimeout = setTimeout(L.bind(function () { - if (this._isTapValid()) { - this._fireClick = false; - this._onUp(); - this._simulateEvent('contextmenu', first); - } - }, this), 1000); - - L.DomEvent - .on(document, 'touchmove', this._onMove, this) - .on(document, 'touchend', this._onUp, this); - }, - - _onUp: function (e) { - clearTimeout(this._holdTimeout); - - L.DomEvent - .off(document, 'touchmove', this._onMove, this) - .off(document, 'touchend', this._onUp, this); - - if (this._fireClick && e && e.changedTouches) { - - var first = e.changedTouches[0], - el = first.target; - - if (el && el.tagName && el.tagName.toLowerCase() === 'a') { - L.DomUtil.removeClass(el, 'leaflet-active'); - } - - // simulate click if the touch didn't move too much - if (this._isTapValid()) { - this._simulateEvent('click', first); - } - } - }, - - _isTapValid: function () { - return this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance; - }, - - _onMove: function (e) { - var first = e.touches[0]; - this._newPos = new L.Point(first.clientX, first.clientY); - }, - - _simulateEvent: function (type, e) { - var simulatedEvent = document.createEvent('MouseEvents'); - - simulatedEvent._simulated = true; - e.target._simulatedClick = true; - - simulatedEvent.initMouseEvent( - type, true, true, window, 1, - e.screenX, e.screenY, - e.clientX, e.clientY, - false, false, false, false, 0, null); - - e.target.dispatchEvent(simulatedEvent); - } -}); - -if (L.Browser.touch && !L.Browser.pointer) { - L.Map.addInitHook('addHandler', 'tap', L.Map.Tap); -} - - -/* - * L.Handler.ShiftDragZoom is used to add shift-drag zoom interaction to the map - * (zoom to a selected bounding box), enabled by default. - */ - -L.Map.mergeOptions({ - boxZoom: true -}); - -L.Map.BoxZoom = L.Handler.extend({ - initialize: function (map) { - this._map = map; - this._container = map._container; - this._pane = map._panes.overlayPane; - this._moved = false; - }, - - addHooks: function () { - L.DomEvent.on(this._container, 'mousedown', this._onMouseDown, this); - }, - - removeHooks: function () { - L.DomEvent.off(this._container, 'mousedown', this._onMouseDown); - this._moved = false; - }, - - moved: function () { - return this._moved; - }, - - _onMouseDown: function (e) { - this._moved = false; - - if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; } - - L.DomUtil.disableTextSelection(); - L.DomUtil.disableImageDrag(); - - this._startLayerPoint = this._map.mouseEventToLayerPoint(e); - - L.DomEvent - .on(document, 'mousemove', this._onMouseMove, this) - .on(document, 'mouseup', this._onMouseUp, this) - .on(document, 'keydown', this._onKeyDown, this); - }, - - _onMouseMove: function (e) { - if (!this._moved) { - this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._pane); - L.DomUtil.setPosition(this._box, this._startLayerPoint); - - //TODO refactor: move cursor to styles - this._container.style.cursor = 'crosshair'; - this._map.fire('boxzoomstart'); - } - - var startPoint = this._startLayerPoint, - box = this._box, - - layerPoint = this._map.mouseEventToLayerPoint(e), - offset = layerPoint.subtract(startPoint), - - newPos = new L.Point( - Math.min(layerPoint.x, startPoint.x), - Math.min(layerPoint.y, startPoint.y)); - - L.DomUtil.setPosition(box, newPos); - - this._moved = true; - - // TODO refactor: remove hardcoded 4 pixels - box.style.width = (Math.max(0, Math.abs(offset.x) - 4)) + 'px'; - box.style.height = (Math.max(0, Math.abs(offset.y) - 4)) + 'px'; - }, - - _finish: function () { - if (this._moved) { - this._pane.removeChild(this._box); - this._container.style.cursor = ''; - } - - L.DomUtil.enableTextSelection(); - L.DomUtil.enableImageDrag(); - - L.DomEvent - .off(document, 'mousemove', this._onMouseMove) - .off(document, 'mouseup', this._onMouseUp) - .off(document, 'keydown', this._onKeyDown); - }, - - _onMouseUp: function (e) { - - this._finish(); - - var map = this._map, - layerPoint = map.mouseEventToLayerPoint(e); - - if (this._startLayerPoint.equals(layerPoint)) { return; } - - var bounds = new L.LatLngBounds( - map.layerPointToLatLng(this._startLayerPoint), - map.layerPointToLatLng(layerPoint)); - - map.fitBounds(bounds); - - map.fire('boxzoomend', { - boxZoomBounds: bounds - }); - }, - - _onKeyDown: function (e) { - if (e.keyCode === 27) { - this._finish(); - } - } -}); - -L.Map.addInitHook('addHandler', 'boxZoom', L.Map.BoxZoom); - - -/* - * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default. - */ - -L.Map.mergeOptions({ - keyboard: true, - keyboardPanOffset: 80, - keyboardZoomOffset: 1 -}); - -L.Map.Keyboard = L.Handler.extend({ - - keyCodes: { - left: [37], - right: [39], - down: [40], - up: [38], - zoomIn: [187, 107, 61, 171], - zoomOut: [189, 109, 173] - }, - - initialize: function (map) { - this._map = map; - - this._setPanOffset(map.options.keyboardPanOffset); - this._setZoomOffset(map.options.keyboardZoomOffset); - }, - - addHooks: function () { - var container = this._map._container; - - // make the container focusable by tabbing - if (container.tabIndex === -1) { - container.tabIndex = '0'; - } - - L.DomEvent - .on(container, 'focus', this._onFocus, this) - .on(container, 'blur', this._onBlur, this) - .on(container, 'mousedown', this._onMouseDown, this); - - this._map - .on('focus', this._addHooks, this) - .on('blur', this._removeHooks, this); - }, - - removeHooks: function () { - this._removeHooks(); - - var container = this._map._container; - - L.DomEvent - .off(container, 'focus', this._onFocus, this) - .off(container, 'blur', this._onBlur, this) - .off(container, 'mousedown', this._onMouseDown, this); - - this._map - .off('focus', this._addHooks, this) - .off('blur', this._removeHooks, this); - }, - - _onMouseDown: function () { - if (this._focused) { return; } - - var body = document.body, - docEl = document.documentElement, - top = body.scrollTop || docEl.scrollTop, - left = body.scrollLeft || docEl.scrollLeft; - - this._map._container.focus(); - - window.scrollTo(left, top); - }, - - _onFocus: function () { - this._focused = true; - this._map.fire('focus'); - }, - - _onBlur: function () { - this._focused = false; - this._map.fire('blur'); - }, - - _setPanOffset: function (pan) { - var keys = this._panKeys = {}, - codes = this.keyCodes, - i, len; - - for (i = 0, len = codes.left.length; i < len; i++) { - keys[codes.left[i]] = [-1 * pan, 0]; - } - for (i = 0, len = codes.right.length; i < len; i++) { - keys[codes.right[i]] = [pan, 0]; - } - for (i = 0, len = codes.down.length; i < len; i++) { - keys[codes.down[i]] = [0, pan]; - } - for (i = 0, len = codes.up.length; i < len; i++) { - keys[codes.up[i]] = [0, -1 * pan]; - } - }, - - _setZoomOffset: function (zoom) { - var keys = this._zoomKeys = {}, - codes = this.keyCodes, - i, len; - - for (i = 0, len = codes.zoomIn.length; i < len; i++) { - keys[codes.zoomIn[i]] = zoom; - } - for (i = 0, len = codes.zoomOut.length; i < len; i++) { - keys[codes.zoomOut[i]] = -zoom; - } - }, - - _addHooks: function () { - L.DomEvent.on(document, 'keydown', this._onKeyDown, this); - }, - - _removeHooks: function () { - L.DomEvent.off(document, 'keydown', this._onKeyDown, this); - }, - - _onKeyDown: function (e) { - var key = e.keyCode, - map = this._map; - - if (key in this._panKeys) { - - if (map._panAnim && map._panAnim._inProgress) { return; } - - map.panBy(this._panKeys[key]); - - if (map.options.maxBounds) { - map.panInsideBounds(map.options.maxBounds); - } - - } else if (key in this._zoomKeys) { - map.setZoom(map.getZoom() + this._zoomKeys[key]); - - } else { - return; - } - - L.DomEvent.stop(e); - } -}); - -L.Map.addInitHook('addHandler', 'keyboard', L.Map.Keyboard); - - -/* - * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable. - */ - -L.Handler.MarkerDrag = L.Handler.extend({ - initialize: function (marker) { - this._marker = marker; - }, - - addHooks: function () { - var icon = this._marker._icon; - if (!this._draggable) { - this._draggable = new L.Draggable(icon, icon); - } - - this._draggable - .on('dragstart', this._onDragStart, this) - .on('drag', this._onDrag, this) - .on('dragend', this._onDragEnd, this); - this._draggable.enable(); - L.DomUtil.addClass(this._marker._icon, 'leaflet-marker-draggable'); - }, - - removeHooks: function () { - this._draggable - .off('dragstart', this._onDragStart, this) - .off('drag', this._onDrag, this) - .off('dragend', this._onDragEnd, this); - - this._draggable.disable(); - L.DomUtil.removeClass(this._marker._icon, 'leaflet-marker-draggable'); - }, - - moved: function () { - return this._draggable && this._draggable._moved; - }, - - _onDragStart: function () { - this._marker - .closePopup() - .fire('movestart') - .fire('dragstart'); - }, - - _onDrag: function () { - var marker = this._marker, - shadow = marker._shadow, - iconPos = L.DomUtil.getPosition(marker._icon), - latlng = marker._map.layerPointToLatLng(iconPos); - - // update shadow position - if (shadow) { - L.DomUtil.setPosition(shadow, iconPos); - } - - marker._latlng = latlng; - - marker - .fire('move', {latlng: latlng}) - .fire('drag'); - }, - - _onDragEnd: function (e) { - this._marker - .fire('moveend') - .fire('dragend', e); - } -}); - - -/* - * L.Control is a base class for implementing map controls. Handles positioning. - * All other controls extend from this class. - */ - -L.Control = L.Class.extend({ - options: { - position: 'topright' - }, - - initialize: function (options) { - L.setOptions(this, options); - }, - - getPosition: function () { - return this.options.position; - }, - - setPosition: function (position) { - var map = this._map; - - if (map) { - map.removeControl(this); - } - - this.options.position = position; - - if (map) { - map.addControl(this); - } - - return this; - }, - - getContainer: function () { - return this._container; - }, - - addTo: function (map) { - this._map = map; - - var container = this._container = this.onAdd(map), - pos = this.getPosition(), - corner = map._controlCorners[pos]; - - L.DomUtil.addClass(container, 'leaflet-control'); - - if (pos.indexOf('bottom') !== -1) { - corner.insertBefore(container, corner.firstChild); - } else { - corner.appendChild(container); - } - - return this; - }, - - removeFrom: function (map) { - var pos = this.getPosition(), - corner = map._controlCorners[pos]; - - corner.removeChild(this._container); - this._map = null; - - if (this.onRemove) { - this.onRemove(map); - } - - return this; - }, - - _refocusOnMap: function () { - if (this._map) { - this._map.getContainer().focus(); - } - } -}); - -L.control = function (options) { - return new L.Control(options); -}; - - -// adds control-related methods to L.Map - -L.Map.include({ - addControl: function (control) { - control.addTo(this); - return this; - }, - - removeControl: function (control) { - control.removeFrom(this); - return this; - }, - - _initControlPos: function () { - var corners = this._controlCorners = {}, - l = 'leaflet-', - container = this._controlContainer = - L.DomUtil.create('div', l + 'control-container', this._container); - - function createCorner(vSide, hSide) { - var className = l + vSide + ' ' + l + hSide; - - corners[vSide + hSide] = L.DomUtil.create('div', className, container); - } - - createCorner('top', 'left'); - createCorner('top', 'right'); - createCorner('bottom', 'left'); - createCorner('bottom', 'right'); - }, - - _clearControlPos: function () { - this._container.removeChild(this._controlContainer); - } -}); - - -/* - * L.Control.Zoom is used for the default zoom buttons on the map. - */ - -L.Control.Zoom = L.Control.extend({ - options: { - position: 'topleft', - zoomInText: '+', - zoomInTitle: 'Zoom in', - zoomOutText: '-', - zoomOutTitle: 'Zoom out' - }, - - onAdd: function (map) { - var zoomName = 'leaflet-control-zoom', - container = L.DomUtil.create('div', zoomName + ' leaflet-bar'); - - this._map = map; - - this._zoomInButton = this._createButton( - this.options.zoomInText, this.options.zoomInTitle, - zoomName + '-in', container, this._zoomIn, this); - this._zoomOutButton = this._createButton( - this.options.zoomOutText, this.options.zoomOutTitle, - zoomName + '-out', container, this._zoomOut, this); - - this._updateDisabled(); - map.on('zoomend zoomlevelschange', this._updateDisabled, this); - - return container; - }, - - onRemove: function (map) { - map.off('zoomend zoomlevelschange', this._updateDisabled, this); - }, - - _zoomIn: function (e) { - this._map.zoomIn(e.shiftKey ? 3 : 1); - }, - - _zoomOut: function (e) { - this._map.zoomOut(e.shiftKey ? 3 : 1); - }, - - _createButton: function (html, title, className, container, fn, context) { - var link = L.DomUtil.create('a', className, container); - link.innerHTML = html; - link.href = '#'; - link.title = title; - - var stop = L.DomEvent.stopPropagation; - - L.DomEvent - .on(link, 'click', stop) - .on(link, 'mousedown', stop) - .on(link, 'dblclick', stop) - .on(link, 'click', L.DomEvent.preventDefault) - .on(link, 'click', fn, context) - .on(link, 'click', this._refocusOnMap, context); - - return link; - }, - - _updateDisabled: function () { - var map = this._map, - className = 'leaflet-disabled'; - - L.DomUtil.removeClass(this._zoomInButton, className); - L.DomUtil.removeClass(this._zoomOutButton, className); - - if (map._zoom === map.getMinZoom()) { - L.DomUtil.addClass(this._zoomOutButton, className); - } - if (map._zoom === map.getMaxZoom()) { - L.DomUtil.addClass(this._zoomInButton, className); - } - } -}); - -L.Map.mergeOptions({ - zoomControl: true -}); - -L.Map.addInitHook(function () { - if (this.options.zoomControl) { - this.zoomControl = new L.Control.Zoom(); - this.addControl(this.zoomControl); - } -}); - -L.control.zoom = function (options) { - return new L.Control.Zoom(options); -}; - - - -/* - * L.Control.Attribution is used for displaying attribution on the map (added by default). - */ - -L.Control.Attribution = L.Control.extend({ - options: { - position: 'bottomright', - prefix: '<a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>' - }, - - initialize: function (options) { - L.setOptions(this, options); - - this._attributions = {}; - }, - - onAdd: function (map) { - this._container = L.DomUtil.create('div', 'leaflet-control-attribution'); - L.DomEvent.disableClickPropagation(this._container); - - for (var i in map._layers) { - if (map._layers[i].getAttribution) { - this.addAttribution(map._layers[i].getAttribution()); - } - } - - map - .on('layeradd', this._onLayerAdd, this) - .on('layerremove', this._onLayerRemove, this); - - this._update(); - - return this._container; - }, - - onRemove: function (map) { - map - .off('layeradd', this._onLayerAdd) - .off('layerremove', this._onLayerRemove); - - }, - - setPrefix: function (prefix) { - this.options.prefix = prefix; - this._update(); - return this; - }, - - addAttribution: function (text) { - if (!text) { return; } - - if (!this._attributions[text]) { - this._attributions[text] = 0; - } - this._attributions[text]++; - - this._update(); - - return this; - }, - - removeAttribution: function (text) { - if (!text) { return; } - - if (this._attributions[text]) { - this._attributions[text]--; - this._update(); - } - - return this; - }, - - _update: function () { - if (!this._map) { return; } - - var attribs = []; - - for (var i in this._attributions) { - if (this._attributions[i]) { - attribs.push(i); - } - } - - var prefixAndAttribs = []; - - if (this.options.prefix) { - prefixAndAttribs.push(this.options.prefix); - } - if (attribs.length) { - prefixAndAttribs.push(attribs.join(', ')); - } - - this._container.innerHTML = prefixAndAttribs.join(' | '); - }, - - _onLayerAdd: function (e) { - if (e.layer.getAttribution) { - this.addAttribution(e.layer.getAttribution()); - } - }, - - _onLayerRemove: function (e) { - if (e.layer.getAttribution) { - this.removeAttribution(e.layer.getAttribution()); - } - } -}); - -L.Map.mergeOptions({ - attributionControl: true -}); - -L.Map.addInitHook(function () { - if (this.options.attributionControl) { - this.attributionControl = (new L.Control.Attribution()).addTo(this); - } -}); - -L.control.attribution = function (options) { - return new L.Control.Attribution(options); -}; - - -/* - * L.Control.Scale is used for displaying metric/imperial scale on the map. - */ - -L.Control.Scale = L.Control.extend({ - options: { - position: 'bottomleft', - maxWidth: 100, - metric: true, - imperial: true, - updateWhenIdle: false - }, - - onAdd: function (map) { - this._map = map; - - var className = 'leaflet-control-scale', - container = L.DomUtil.create('div', className), - options = this.options; - - this._addScales(options, className, container); - - map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this); - map.whenReady(this._update, this); - - return container; - }, - - onRemove: function (map) { - map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this); - }, - - _addScales: function (options, className, container) { - if (options.metric) { - this._mScale = L.DomUtil.create('div', className + '-line', container); - } - if (options.imperial) { - this._iScale = L.DomUtil.create('div', className + '-line', container); - } - }, - - _update: function () { - var bounds = this._map.getBounds(), - centerLat = bounds.getCenter().lat, - halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180), - dist = halfWorldMeters * (bounds.getNorthEast().lng - bounds.getSouthWest().lng) / 180, - - size = this._map.getSize(), - options = this.options, - maxMeters = 0; - - if (size.x > 0) { - maxMeters = dist * (options.maxWidth / size.x); - } - - this._updateScales(options, maxMeters); - }, - - _updateScales: function (options, maxMeters) { - if (options.metric && maxMeters) { - this._updateMetric(maxMeters); - } - - if (options.imperial && maxMeters) { - this._updateImperial(maxMeters); - } - }, - - _updateMetric: function (maxMeters) { - var meters = this._getRoundNum(maxMeters); - - this._mScale.style.width = this._getScaleWidth(meters / maxMeters) + 'px'; - this._mScale.innerHTML = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km'; - }, - - _updateImperial: function (maxMeters) { - var maxFeet = maxMeters * 3.2808399, - scale = this._iScale, - maxMiles, miles, feet; - - if (maxFeet > 5280) { - maxMiles = maxFeet / 5280; - miles = this._getRoundNum(maxMiles); - - scale.style.width = this._getScaleWidth(miles / maxMiles) + 'px'; - scale.innerHTML = miles + ' mi'; - - } else { - feet = this._getRoundNum(maxFeet); - - scale.style.width = this._getScaleWidth(feet / maxFeet) + 'px'; - scale.innerHTML = feet + ' ft'; - } - }, - - _getScaleWidth: function (ratio) { - return Math.round(this.options.maxWidth * ratio) - 10; - }, - - _getRoundNum: function (num) { - var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1), - d = num / pow10; - - d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1; - - return pow10 * d; - } -}); - -L.control.scale = function (options) { - return new L.Control.Scale(options); -}; - - -/* - * L.Control.Layers is a control to allow users to switch between different layers on the map. - */ - -L.Control.Layers = L.Control.extend({ - options: { - collapsed: true, - position: 'topright', - autoZIndex: true - }, - - initialize: function (baseLayers, overlays, options) { - L.setOptions(this, options); - - this._layers = {}; - this._lastZIndex = 0; - this._handlingClick = false; - - for (var i in baseLayers) { - this._addLayer(baseLayers[i], i); - } - - for (i in overlays) { - this._addLayer(overlays[i], i, true); - } - }, - - onAdd: function (map) { - this._initLayout(); - this._update(); - - map - .on('layeradd', this._onLayerChange, this) - .on('layerremove', this._onLayerChange, this); - - return this._container; - }, - - onRemove: function (map) { - map - .off('layeradd', this._onLayerChange, this) - .off('layerremove', this._onLayerChange, this); - }, - - addBaseLayer: function (layer, name) { - this._addLayer(layer, name); - this._update(); - return this; - }, - - addOverlay: function (layer, name) { - this._addLayer(layer, name, true); - this._update(); - return this; - }, - - removeLayer: function (layer) { - var id = L.stamp(layer); - delete this._layers[id]; - this._update(); - return this; - }, - - _initLayout: function () { - var className = 'leaflet-control-layers', - container = this._container = L.DomUtil.create('div', className); - - //Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released - container.setAttribute('aria-haspopup', true); - - if (!L.Browser.touch) { - L.DomEvent - .disableClickPropagation(container) - .disableScrollPropagation(container); - } else { - L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation); - } - - var form = this._form = L.DomUtil.create('form', className + '-list'); - - if (this.options.collapsed) { - if (!L.Browser.android) { - L.DomEvent - .on(container, 'mouseover', this._expand, this) - .on(container, 'mouseout', this._collapse, this); - } - var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container); - link.href = '#'; - link.title = 'Layers'; - - if (L.Browser.touch) { - L.DomEvent - .on(link, 'click', L.DomEvent.stop) - .on(link, 'click', this._expand, this); - } - else { - L.DomEvent.on(link, 'focus', this._expand, this); - } - //Work around for Firefox android issue https://github.com/Leaflet/Leaflet/issues/2033 - L.DomEvent.on(form, 'click', function () { - setTimeout(L.bind(this._onInputClick, this), 0); - }, this); - - this._map.on('click', this._collapse, this); - // TODO keyboard accessibility - } else { - this._expand(); - } - - this._baseLayersList = L.DomUtil.create('div', className + '-base', form); - this._separator = L.DomUtil.create('div', className + '-separator', form); - this._overlaysList = L.DomUtil.create('div', className + '-overlays', form); - - container.appendChild(form); - }, - - _addLayer: function (layer, name, overlay) { - var id = L.stamp(layer); - - this._layers[id] = { - layer: layer, - name: name, - overlay: overlay - }; - - if (this.options.autoZIndex && layer.setZIndex) { - this._lastZIndex++; - layer.setZIndex(this._lastZIndex); - } - }, - - _update: function () { - if (!this._container) { - return; - } - - this._baseLayersList.innerHTML = ''; - this._overlaysList.innerHTML = ''; - - var baseLayersPresent = false, - overlaysPresent = false, - i, obj; - - for (i in this._layers) { - obj = this._layers[i]; - this._addItem(obj); - overlaysPresent = overlaysPresent || obj.overlay; - baseLayersPresent = baseLayersPresent || !obj.overlay; - } - - this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none'; - }, - - _onLayerChange: function (e) { - var obj = this._layers[L.stamp(e.layer)]; - - if (!obj) { return; } - - if (!this._handlingClick) { - this._update(); - } - - var type = obj.overlay ? - (e.type === 'layeradd' ? 'overlayadd' : 'overlayremove') : - (e.type === 'layeradd' ? 'baselayerchange' : null); - - if (type) { - this._map.fire(type, obj); - } - }, - - // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe) - _createRadioElement: function (name, checked) { - - var radioHtml = '<input type="radio" class="leaflet-control-layers-selector" name="' + name + '"'; - if (checked) { - radioHtml += ' checked="checked"'; - } - radioHtml += '/>'; - - var radioFragment = document.createElement('div'); - radioFragment.innerHTML = radioHtml; - - return radioFragment.firstChild; - }, - - _addItem: function (obj) { - var label = document.createElement('label'), - input, - checked = this._map.hasLayer(obj.layer); - - if (obj.overlay) { - input = document.createElement('input'); - input.type = 'checkbox'; - input.className = 'leaflet-control-layers-selector'; - input.defaultChecked = checked; - } else { - input = this._createRadioElement('leaflet-base-layers', checked); - } - - input.layerId = L.stamp(obj.layer); - - L.DomEvent.on(input, 'click', this._onInputClick, this); - - var name = document.createElement('span'); - name.innerHTML = ' ' + obj.name; - - label.appendChild(input); - label.appendChild(name); - - var container = obj.overlay ? this._overlaysList : this._baseLayersList; - container.appendChild(label); - - return label; - }, - - _onInputClick: function () { - var i, input, obj, - inputs = this._form.getElementsByTagName('input'), - inputsLen = inputs.length; - - this._handlingClick = true; - - for (i = 0; i < inputsLen; i++) { - input = inputs[i]; - obj = this._layers[input.layerId]; - - if (input.checked && !this._map.hasLayer(obj.layer)) { - this._map.addLayer(obj.layer); - - } else if (!input.checked && this._map.hasLayer(obj.layer)) { - this._map.removeLayer(obj.layer); - } - } - - this._handlingClick = false; - - this._refocusOnMap(); - }, - - _expand: function () { - L.DomUtil.addClass(this._container, 'leaflet-control-layers-expanded'); - }, - - _collapse: function () { - this._container.className = this._container.className.replace(' leaflet-control-layers-expanded', ''); - } -}); - -L.control.layers = function (baseLayers, overlays, options) { - return new L.Control.Layers(baseLayers, overlays, options); -}; - - -/* - * L.PosAnimation is used by Leaflet internally for pan animations. - */ - -L.PosAnimation = L.Class.extend({ - includes: L.Mixin.Events, - - run: function (el, newPos, duration, easeLinearity) { // (HTMLElement, Point[, Number, Number]) - this.stop(); - - this._el = el; - this._inProgress = true; - this._newPos = newPos; - - this.fire('start'); - - el.style[L.DomUtil.TRANSITION] = 'all ' + (duration || 0.25) + - 's cubic-bezier(0,0,' + (easeLinearity || 0.5) + ',1)'; - - L.DomEvent.on(el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this); - L.DomUtil.setPosition(el, newPos); - - // toggle reflow, Chrome flickers for some reason if you don't do this - L.Util.falseFn(el.offsetWidth); - - // there's no native way to track value updates of transitioned properties, so we imitate this - this._stepTimer = setInterval(L.bind(this._onStep, this), 50); - }, - - stop: function () { - if (!this._inProgress) { return; } - - // if we just removed the transition property, the element would jump to its final position, - // so we need to make it stay at the current position - - L.DomUtil.setPosition(this._el, this._getPos()); - this._onTransitionEnd(); - L.Util.falseFn(this._el.offsetWidth); // force reflow in case we are about to start a new animation - }, - - _onStep: function () { - var stepPos = this._getPos(); - if (!stepPos) { - this._onTransitionEnd(); - return; - } - // jshint camelcase: false - // make L.DomUtil.getPosition return intermediate position value during animation - this._el._leaflet_pos = stepPos; - - this.fire('step'); - }, - - // you can't easily get intermediate values of properties animated with CSS3 Transitions, - // we need to parse computed style (in case of transform it returns matrix string) - - _transformRe: /([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/, - - _getPos: function () { - var left, top, matches, - el = this._el, - style = window.getComputedStyle(el); - - if (L.Browser.any3d) { - matches = style[L.DomUtil.TRANSFORM].match(this._transformRe); - if (!matches) { return; } - left = parseFloat(matches[1]); - top = parseFloat(matches[2]); - } else { - left = parseFloat(style.left); - top = parseFloat(style.top); - } - - return new L.Point(left, top, true); - }, - - _onTransitionEnd: function () { - L.DomEvent.off(this._el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this); - - if (!this._inProgress) { return; } - this._inProgress = false; - - this._el.style[L.DomUtil.TRANSITION] = ''; - - // jshint camelcase: false - // make sure L.DomUtil.getPosition returns the final position value after animation - this._el._leaflet_pos = this._newPos; - - clearInterval(this._stepTimer); - - this.fire('step').fire('end'); - } - -}); - - -/* - * Extends L.Map to handle panning animations. - */ - -L.Map.include({ - - setView: function (center, zoom, options) { - - zoom = zoom === undefined ? this._zoom : this._limitZoom(zoom); - center = this._limitCenter(L.latLng(center), zoom, this.options.maxBounds); - options = options || {}; - - if (this._panAnim) { - this._panAnim.stop(); - } - - if (this._loaded && !options.reset && options !== true) { - - if (options.animate !== undefined) { - options.zoom = L.extend({animate: options.animate}, options.zoom); - options.pan = L.extend({animate: options.animate}, options.pan); - } - - // try animating pan or zoom - var animated = (this._zoom !== zoom) ? - this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) : - this._tryAnimatedPan(center, options.pan); - - if (animated) { - // prevent resize handler call, the view will refresh after animation anyway - clearTimeout(this._sizeTimer); - return this; - } - } - - // animation didn't start, just reset the map view - this._resetView(center, zoom); - - return this; - }, - - panBy: function (offset, options) { - offset = L.point(offset).round(); - options = options || {}; - - if (!offset.x && !offset.y) { - return this; - } - - if (!this._panAnim) { - this._panAnim = new L.PosAnimation(); - - this._panAnim.on({ - 'step': this._onPanTransitionStep, - 'end': this._onPanTransitionEnd - }, this); - } - - // don't fire movestart if animating inertia - if (!options.noMoveStart) { - this.fire('movestart'); - } - - // animate pan unless animate: false specified - if (options.animate !== false) { - L.DomUtil.addClass(this._mapPane, 'leaflet-pan-anim'); - - var newPos = this._getMapPanePos().subtract(offset); - this._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity); - } else { - this._rawPanBy(offset); - this.fire('move').fire('moveend'); - } - - return this; - }, - - _onPanTransitionStep: function () { - this.fire('move'); - }, - - _onPanTransitionEnd: function () { - L.DomUtil.removeClass(this._mapPane, 'leaflet-pan-anim'); - this.fire('moveend'); - }, - - _tryAnimatedPan: function (center, options) { - // difference between the new and current centers in pixels - var offset = this._getCenterOffset(center)._floor(); - - // don't animate too far unless animate: true specified in options - if ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; } - - this.panBy(offset, options); - - return true; - } -}); - - -/* - * L.PosAnimation fallback implementation that powers Leaflet pan animations - * in browsers that don't support CSS3 Transitions. - */ - -L.PosAnimation = L.DomUtil.TRANSITION ? L.PosAnimation : L.PosAnimation.extend({ - - run: function (el, newPos, duration, easeLinearity) { // (HTMLElement, Point[, Number, Number]) - this.stop(); - - this._el = el; - this._inProgress = true; - this._duration = duration || 0.25; - this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2); - - this._startPos = L.DomUtil.getPosition(el); - this._offset = newPos.subtract(this._startPos); - this._startTime = +new Date(); - - this.fire('start'); - - this._animate(); - }, - - stop: function () { - if (!this._inProgress) { return; } - - this._step(); - this._complete(); - }, - - _animate: function () { - // animation loop - this._animId = L.Util.requestAnimFrame(this._animate, this); - this._step(); - }, - - _step: function () { - var elapsed = (+new Date()) - this._startTime, - duration = this._duration * 1000; - - if (elapsed < duration) { - this._runFrame(this._easeOut(elapsed / duration)); - } else { - this._runFrame(1); - this._complete(); - } - }, - - _runFrame: function (progress) { - var pos = this._startPos.add(this._offset.multiplyBy(progress)); - L.DomUtil.setPosition(this._el, pos); - - this.fire('step'); - }, - - _complete: function () { - L.Util.cancelAnimFrame(this._animId); - - this._inProgress = false; - this.fire('end'); - }, - - _easeOut: function (t) { - return 1 - Math.pow(1 - t, this._easeOutPower); - } -}); - - -/* - * Extends L.Map to handle zoom animations. - */ - -L.Map.mergeOptions({ - zoomAnimation: true, - zoomAnimationThreshold: 4 -}); - -if (L.DomUtil.TRANSITION) { - - L.Map.addInitHook(function () { - // don't animate on browsers without hardware-accelerated transitions or old Android/Opera - this._zoomAnimated = this.options.zoomAnimation && L.DomUtil.TRANSITION && - L.Browser.any3d && !L.Browser.android23 && !L.Browser.mobileOpera; - - // zoom transitions run with the same duration for all layers, so if one of transitionend events - // happens after starting zoom animation (propagating to the map pane), we know that it ended globally - if (this._zoomAnimated) { - L.DomEvent.on(this._mapPane, L.DomUtil.TRANSITION_END, this._catchTransitionEnd, this); - } - }); -} - -L.Map.include(!L.DomUtil.TRANSITION ? {} : { - - _catchTransitionEnd: function (e) { - if (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) { - this._onZoomTransitionEnd(); - } - }, - - _nothingToAnimate: function () { - return !this._container.getElementsByClassName('leaflet-zoom-animated').length; - }, - - _tryAnimatedZoom: function (center, zoom, options) { - - if (this._animatingZoom) { return true; } - - options = options || {}; - - // don't animate if disabled, not supported or zoom difference is too large - if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() || - Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; } - - // offset is the pixel coords of the zoom origin relative to the current center - var scale = this.getZoomScale(zoom), - offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale), - origin = this._getCenterLayerPoint()._add(offset); - - // don't animate if the zoom origin isn't within one screen from the current center, unless forced - if (options.animate !== true && !this.getSize().contains(offset)) { return false; } - - this - .fire('movestart') - .fire('zoomstart'); - - this._animateZoom(center, zoom, origin, scale, null, true); - - return true; - }, - - _animateZoom: function (center, zoom, origin, scale, delta, backwards, forTouchZoom) { - - if (!forTouchZoom) { - this._animatingZoom = true; - } - - // put transform transition on all layers with leaflet-zoom-animated class - L.DomUtil.addClass(this._mapPane, 'leaflet-zoom-anim'); - - // remember what center/zoom to set after animation - this._animateToCenter = center; - this._animateToZoom = zoom; - - // disable any dragging during animation - if (L.Draggable) { - L.Draggable._disabled = true; - } - - L.Util.requestAnimFrame(function () { - this.fire('zoomanim', { - center: center, - zoom: zoom, - origin: origin, - scale: scale, - delta: delta, - backwards: backwards - }); - // horrible hack to work around a Chrome bug https://github.com/Leaflet/Leaflet/issues/3689 - setTimeout(L.bind(this._onZoomTransitionEnd, this), 250); - }, this); - }, - - _onZoomTransitionEnd: function () { - if (!this._animatingZoom) { return; } - - this._animatingZoom = false; - - L.DomUtil.removeClass(this._mapPane, 'leaflet-zoom-anim'); - - L.Util.requestAnimFrame(function () { - this._resetView(this._animateToCenter, this._animateToZoom, true, true); - - if (L.Draggable) { - L.Draggable._disabled = false; - } - }, this); - } -}); - - -/* - Zoom animation logic for L.TileLayer. -*/ - -L.TileLayer.include({ - _animateZoom: function (e) { - if (!this._animating) { - this._animating = true; - this._prepareBgBuffer(); - } - - var bg = this._bgBuffer, - transform = L.DomUtil.TRANSFORM, - initialTransform = e.delta ? L.DomUtil.getTranslateString(e.delta) : bg.style[transform], - scaleStr = L.DomUtil.getScaleString(e.scale, e.origin); - - bg.style[transform] = e.backwards ? - scaleStr + ' ' + initialTransform : - initialTransform + ' ' + scaleStr; - }, - - _endZoomAnim: function () { - var front = this._tileContainer, - bg = this._bgBuffer; - - front.style.visibility = ''; - front.parentNode.appendChild(front); // Bring to fore - - // force reflow - L.Util.falseFn(bg.offsetWidth); - - var zoom = this._map.getZoom(); - if (zoom > this.options.maxZoom || zoom < this.options.minZoom) { - this._clearBgBuffer(); - } - - this._animating = false; - }, - - _clearBgBuffer: function () { - var map = this._map; - - if (map && !map._animatingZoom && !map.touchZoom._zooming) { - this._bgBuffer.innerHTML = ''; - this._bgBuffer.style[L.DomUtil.TRANSFORM] = ''; - } - }, - - _prepareBgBuffer: function () { - - var front = this._tileContainer, - bg = this._bgBuffer; - - // if foreground layer doesn't have many tiles but bg layer does, - // keep the existing bg layer and just zoom it some more - - var bgLoaded = this._getLoadedTilesPercentage(bg), - frontLoaded = this._getLoadedTilesPercentage(front); - - if (bg && bgLoaded > 0.5 && frontLoaded < 0.5) { - - front.style.visibility = 'hidden'; - this._stopLoadingImages(front); - return; - } - - // prepare the buffer to become the front tile pane - bg.style.visibility = 'hidden'; - bg.style[L.DomUtil.TRANSFORM] = ''; - - // switch out the current layer to be the new bg layer (and vice-versa) - this._tileContainer = bg; - bg = this._bgBuffer = front; - - this._stopLoadingImages(bg); - - //prevent bg buffer from clearing right after zoom - clearTimeout(this._clearBgBufferTimer); - }, - - _getLoadedTilesPercentage: function (container) { - var tiles = container.getElementsByTagName('img'), - i, len, count = 0; - - for (i = 0, len = tiles.length; i < len; i++) { - if (tiles[i].complete) { - count++; - } - } - return count / len; - }, - - // stops loading all tiles in the background layer - _stopLoadingImages: function (container) { - var tiles = Array.prototype.slice.call(container.getElementsByTagName('img')), - i, len, tile; - - for (i = 0, len = tiles.length; i < len; i++) { - tile = tiles[i]; - - if (!tile.complete) { - tile.onload = L.Util.falseFn; - tile.onerror = L.Util.falseFn; - tile.src = L.Util.emptyImageUrl; - - tile.parentNode.removeChild(tile); - } - } - } -}); - - -/* - * Provides L.Map with convenient shortcuts for using browser geolocation features. - */ - -L.Map.include({ - _defaultLocateOptions: { - watch: false, - setView: false, - maxZoom: Infinity, - timeout: 10000, - maximumAge: 0, - enableHighAccuracy: false - }, - - locate: function (/*Object*/ options) { - - options = this._locateOptions = L.extend(this._defaultLocateOptions, options); - - if (!navigator.geolocation) { - this._handleGeolocationError({ - code: 0, - message: 'Geolocation not supported.' - }); - return this; - } - - var onResponse = L.bind(this._handleGeolocationResponse, this), - onError = L.bind(this._handleGeolocationError, this); - - if (options.watch) { - this._locationWatchId = - navigator.geolocation.watchPosition(onResponse, onError, options); - } else { - navigator.geolocation.getCurrentPosition(onResponse, onError, options); - } - return this; - }, - - stopLocate: function () { - if (navigator.geolocation) { - navigator.geolocation.clearWatch(this._locationWatchId); - } - if (this._locateOptions) { - this._locateOptions.setView = false; - } - return this; - }, - - _handleGeolocationError: function (error) { - var c = error.code, - message = error.message || - (c === 1 ? 'permission denied' : - (c === 2 ? 'position unavailable' : 'timeout')); - - if (this._locateOptions.setView && !this._loaded) { - this.fitWorld(); - } - - this.fire('locationerror', { - code: c, - message: 'Geolocation error: ' + message + '.' - }); - }, - - _handleGeolocationResponse: function (pos) { - var lat = pos.coords.latitude, - lng = pos.coords.longitude, - latlng = new L.LatLng(lat, lng), - - latAccuracy = 180 * pos.coords.accuracy / 40075017, - lngAccuracy = latAccuracy / Math.cos(L.LatLng.DEG_TO_RAD * lat), - - bounds = L.latLngBounds( - [lat - latAccuracy, lng - lngAccuracy], - [lat + latAccuracy, lng + lngAccuracy]), - - options = this._locateOptions; - - if (options.setView) { - var zoom = Math.min(this.getBoundsZoom(bounds), options.maxZoom); - this.setView(latlng, zoom); - } - - var data = { - latlng: latlng, - bounds: bounds, - timestamp: pos.timestamp - }; - - for (var i in pos.coords) { - if (typeof pos.coords[i] === 'number') { - data[i] = pos.coords[i]; - } - } - - this.fire('locationfound', data); - } -}); - - -}(window, document)); \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/vendor/leaflet.awesome-markers.min.js b/assets/www/dist/dist_js/app/vendor/leaflet.awesome-markers.min.js deleted file mode 100644 index 376e57e68d6f93c56f4d683bee3cc150926e710b..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/leaflet.awesome-markers.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - Leaflet.AwesomeMarkers, a plugin that adds colorful iconic markers for Leaflet, based on the Font Awesome icons - (c) 2012-2013, Lennard Voogdt - - http://leafletjs.com - https://github.com/lvoogdt -*//*global L*/(function(e,t,n){"use strict";L.AwesomeMarkers={};L.AwesomeMarkers.version="2.0.1";L.AwesomeMarkers.Icon=L.Icon.extend({options:{iconSize:[35,45],iconAnchor:[17,42],popupAnchor:[1,-32],shadowAnchor:[10,12],shadowSize:[36,16],className:"awesome-marker",prefix:"glyphicon",spinClass:"fa-spin",icon:"home",markerColor:"blue",iconColor:"white"},initialize:function(e){e=L.Util.setOptions(this,e)},createIcon:function(){var e=t.createElement("div"),n=this.options;n.icon&&(e.innerHTML=this._createInner());n.bgPos&&(e.style.backgroundPosition=-n.bgPos.x+"px "+ -n.bgPos.y+"px");this._setIconStyles(e,"icon-"+n.markerColor);return e},_createInner:function(){var e,t="",n="",r="",i=this.options;i.icon.slice(0,i.prefix.length+1)===i.prefix+"-"?e=i.icon:e=i.prefix+"-"+i.icon;i.spin&&typeof i.spinClass=="string"&&(t=i.spinClass);i.iconColor&&(i.iconColor==="white"||i.iconColor==="black"?n="icon-"+i.iconColor:r="style='color: "+i.iconColor+"' ");return"<i "+r+"class='"+i.prefix+" "+e+" "+t+" "+n+"'></i>"},_setIconStyles:function(e,t){var n=this.options,r=L.point(n[t==="shadow"?"shadowSize":"iconSize"]),i;t==="shadow"?i=L.point(n.shadowAnchor||n.iconAnchor):i=L.point(n.iconAnchor);!i&&r&&(i=r.divideBy(2,!0));e.className="awesome-marker-"+t+" "+n.className;if(i){e.style.marginLeft=-i.x+"px";e.style.marginTop=-i.y+"px"}if(r){e.style.width=r.x+"px";e.style.height=r.y+"px"}},createShadow:function(){var e=t.createElement("div");this._setIconStyles(e,"shadow");return e}});L.AwesomeMarkers.icon=function(e){return new L.AwesomeMarkers.Icon(e)}})(this,document); diff --git a/assets/www/dist/dist_js/app/vendor/leaflet.easy-button.js b/assets/www/dist/dist_js/app/vendor/leaflet.easy-button.js deleted file mode 100644 index f71e072905c90e5539b66cc1eed7639f5e3bfc8e..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/leaflet.easy-button.js +++ /dev/null @@ -1,379 +0,0 @@ -(function(){ - -// This is for grouping buttons into a bar -// takes an array of `L.easyButton`s and -// then the usual `.addTo(map)` -L.Control.EasyBar = L.Control.extend({ - - options: { - position: 'topleft', // part of leaflet's defaults - id: null, // an id to tag the Bar with - leafletClasses: true // use leaflet classes? - }, - - - initialize: function(buttons, options){ - - if(options){ - L.Util.setOptions( this, options ); - } - - this._buildContainer(); - this._buttons = []; - - for(var i = 0; i < buttons.length; i++){ - buttons[i]._bar = this; - buttons[i]._container = buttons[i].button; - this._buttons.push(buttons[i]); - this.container.appendChild(buttons[i].button); - } - - }, - - - _buildContainer: function(){ - this._container = this.container = L.DomUtil.create('div', ''); - this.options.leafletClasses && L.DomUtil.addClass(this.container, 'leaflet-bar easy-button-container leaflet-control'); - this.options.id && (this.container.id = this.options.id); - }, - - - enable: function(){ - L.DomUtil.addClass(this.container, 'enabled'); - L.DomUtil.removeClass(this.container, 'disabled'); - this.container.setAttribute('aria-hidden', 'false'); - return this; - }, - - - disable: function(){ - L.DomUtil.addClass(this.container, 'disabled'); - L.DomUtil.removeClass(this.container, 'enabled'); - this.container.setAttribute('aria-hidden', 'true'); - return this; - }, - - - onAdd: function () { - return this.container; - }, - - addTo: function (map) { - this._map = map; - - for(var i = 0; i < this._buttons.length; i++){ - this._buttons[i]._map = map; - } - - var container = this._container = this.onAdd(map), - pos = this.getPosition(), - corner = map._controlCorners[pos]; - - L.DomUtil.addClass(container, 'leaflet-control'); - - if (pos.indexOf('bottom') !== -1) { - corner.insertBefore(container, corner.firstChild); - } else { - corner.appendChild(container); - } - - return this; - } - -}); - -L.easyBar = function(){ - var args = [L.Control.EasyBar]; - for(var i = 0; i < arguments.length; i++){ - args.push( arguments[i] ); - } - return new (Function.prototype.bind.apply(L.Control.EasyBar, args)); -}; - -// L.EasyButton is the actual buttons -// can be called without being grouped into a bar -L.Control.EasyButton = L.Control.extend({ - - options: { - position: 'topleft', // part of leaflet's defaults - - id: null, // an id to tag the button with - - type: 'replace', // [(replace|animate)] - // replace swaps out elements - // animate changes classes with all elements inserted - - states: [], // state names look like this - // { - // stateName: 'untracked', - // onClick: function(){ handle_nav_manually(); }; - // title: 'click to make inactive', - // icon: 'fa-circle', // wrapped with <a> - // } - - leafletClasses: true, // use leaflet styles for the button - tagName: 'button', - }, - - - - initialize: function(icon, onClick, title, id){ - - // clear the states manually - this.options.states = []; - - // add id to options - if(id != null){ - this.options.id = id; - } - - // storage between state functions - this.storage = {}; - - // is the last item an object? - if( typeof arguments[arguments.length-1] === 'object' ){ - - // if so, it should be the options - L.Util.setOptions( this, arguments[arguments.length-1] ); - } - - // if there aren't any states in options - // use the early params - if( this.options.states.length === 0 && - typeof icon === 'string' && - typeof onClick === 'function'){ - - // turn the options object into a state - this.options.states.push({ - icon: icon, - onClick: onClick, - title: typeof title === 'string' ? title : '' - }); - } - - // curate and move user's states into - // the _states for internal use - this._states = []; - - for(var i = 0; i < this.options.states.length; i++){ - this._states.push( new State(this.options.states[i], this) ); - } - - this._buildButton(); - - this._activateState(this._states[0]); - - }, - - _buildButton: function(){ - - this.button = L.DomUtil.create(this.options.tagName, ''); - - // the next three if statements should be collapsed into the options - // when it's time for breaking changes. - if (this.tagName === 'button') { - this.button.type = 'button'; - } - - if (this.options.id ){ - this.button.id = this.options.id; - } - - if (this.options.leafletClasses){ - L.DomUtil.addClass(this.button, 'easy-button-button leaflet-bar-part leaflet-interactive'); - } - - // don't let double clicks and mousedown get to the map - L.DomEvent.addListener(this.button, 'dblclick', L.DomEvent.stop); - L.DomEvent.addListener(this.button, 'mousedown', L.DomEvent.stop); - - // take care of normal clicks - L.DomEvent.addListener(this.button,'click', function(e){ - L.DomEvent.stop(e); - this._currentState.onClick(this, this._map ? this._map : null ); - this._map.getContainer().focus(); - }, this); - - // prep the contents of the control - if(this.options.type == 'replace'){ - this.button.appendChild(this._currentState.icon); - } else { - for(var i=0;i<this._states.length;i++){ - this.button.appendChild(this._states[i].icon); - } - } - }, - - - _currentState: { - // placeholder content - stateName: 'unnamed', - icon: (function(){ return document.createElement('span'); })() - }, - - - - _states: null, // populated on init - - - - state: function(newState){ - - // activate by name - if(typeof newState == 'string'){ - - this._activateStateNamed(newState); - - // activate by index - } else if (typeof newState == 'number'){ - - this._activateState(this._states[newState]); - } - - return this; - }, - - - _activateStateNamed: function(stateName){ - for(var i = 0; i < this._states.length; i++){ - if( this._states[i].stateName == stateName ){ - this._activateState( this._states[i] ); - } - } - }, - - _activateState: function(newState){ - - if( newState === this._currentState ){ - - // don't touch the dom if it'll just be the same after - return; - - } else { - - // swap out elements... if you're into that kind of thing - if( this.options.type == 'replace' ){ - this.button.appendChild(newState.icon); - this.button.removeChild(this._currentState.icon); - } - - if( newState.title ){ - this.button.title = newState.title; - } else { - this.button.removeAttribute('title'); - } - - // update classes for animations - for(var i=0;i<this._states.length;i++){ - L.DomUtil.removeClass(this._states[i].icon, this._currentState.stateName + '-active'); - L.DomUtil.addClass(this._states[i].icon, newState.stateName + '-active'); - } - - // update classes for animations - L.DomUtil.removeClass(this.button, this._currentState.stateName + '-active'); - L.DomUtil.addClass(this.button, newState.stateName + '-active'); - - // update the record - this._currentState = newState; - - } - }, - - - - enable: function(){ - L.DomUtil.addClass(this.button, 'enabled'); - L.DomUtil.removeClass(this.button, 'disabled'); - this.button.setAttribute('aria-hidden', 'false'); - return this; - }, - - - - disable: function(){ - L.DomUtil.addClass(this.button, 'disabled'); - L.DomUtil.removeClass(this.button, 'enabled'); - this.button.setAttribute('aria-hidden', 'true'); - return this; - }, - - - removeFrom: function (map) { - - this._container.parentNode.removeChild(this._container); - this._map = null; - - return this; - }, - - onAdd: function(){ - var containerObj = L.easyBar([this], { - position: this.options.position, - leafletClasses: this.options.leafletClasses - }); - this._container = containerObj.container; - return this._container; - } - - -}); - -L.easyButton = function(/* args will pass automatically */){ - var args = Array.prototype.concat.apply([L.Control.EasyButton],arguments); - return new (Function.prototype.bind.apply(L.Control.EasyButton, args)); -}; - -/************************* - * - * util functions - * - *************************/ - -// constructor for states so only curated -// states end up getting called -function State(template, easyButton){ - - this.title = template.title; - this.stateName = template.stateName ? template.stateName : 'unnamed-state'; - - // build the wrapper - this.icon = L.DomUtil.create('span', ''); - - L.DomUtil.addClass(this.icon, 'button-state state-' + this.stateName.replace(/(^\s*|\s*$)/g,'')); - this.icon.innerHTML = buildIcon(template.icon); - this.onClick = L.Util.bind(template.onClick?template.onClick:function(){}, easyButton); -} - -function buildIcon(ambiguousIconString) { - - var tmpIcon; - - // does this look like html? (i.e. not a class) - if( ambiguousIconString.match(/[&;=<>"']/) ){ - - // if so, the user should have put in html - // so move forward as such - tmpIcon = ambiguousIconString; - - // then it wasn't html, so - // it's a class list, figure out what kind - } else { - ambiguousIconString = ambiguousIconString.replace(/(^\s*|\s*$)/g,''); - tmpIcon = L.DomUtil.create('span', ''); - - if( ambiguousIconString.indexOf('fa-') === 0 ){ - L.DomUtil.addClass(tmpIcon, 'fa ' + ambiguousIconString) - } else if ( ambiguousIconString.indexOf('glyphicon-') === 0 ) { - L.DomUtil.addClass(tmpIcon, 'glyphicon ' + ambiguousIconString) - } else { - L.DomUtil.addClass(tmpIcon, /*rollwithit*/ ambiguousIconString) - } - - // make this a string so that it's easy to set innerHTML below - tmpIcon = tmpIcon.outerHTML; - } - - return tmpIcon; -} - -})(); diff --git a/assets/www/dist/dist_js/app/vendor/leaflet.featuregroup.subgroup-src.js b/assets/www/dist/dist_js/app/vendor/leaflet.featuregroup.subgroup-src.js deleted file mode 100644 index 0ce8c355bed261a4f2f1eb8fb77975d7d4f7607d..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/leaflet.featuregroup.subgroup-src.js +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Leaflet.FeatureGroup.SubGroup creates a Feature Group that adds its child - * layers into a parent group when added to a map (e.g. through L.Control.Layers). - * (c) 2015-2016 Boris Seang - * BSD 2-Clause "Simplified" License - */ - -(function (root, factory) { - if (typeof define === "function" && define.amd) { - define(["leaflet"], factory); - } else if (typeof module === "object" && module.exports) { - factory(require("leaflet")); - } else { - factory(root.L); - } -}(this, function (L) { - - L.FeatureGroup.SubGroup = L.FeatureGroup.extend({ - - statics: { - version: '0.1.2' - }, - - /** - * Instantiates a SubGroup. - * @param parentGroup (L.LayerGroup) (optional) - * @param layersArray (L.Layer[]) (optional) - */ - initialize: function (parentGroup, layersArray) { - L.FeatureGroup.prototype.initialize.call(this, layersArray); - - this.setParentGroup(parentGroup); - }, - - /** - * Changes the parent group into which child markers are added to / - * removed from. - * @param parentGroup (L.LayerGroup) - * @returns {SubGroup} this - */ - setParentGroup: function (parentGroup) { - var pgInstanceOfLG = parentGroup instanceof L.LayerGroup; - - this._parentGroup = parentGroup; - - // onAdd - this.onAdd = - pgInstanceOfLG ? - ( - typeof parentGroup.addLayers === "function" ? - this._onAddToGroupBatch : - this._onAddToGroup - ) : - this._onAddToMap; - - // onRemove - this.onRemove = - pgInstanceOfLG ? - ( - typeof parentGroup.removeLayers === "function" ? - this._onRemoveFromGroupBatch : - this._onRemoveFromGroup - ) : - this._onRemoveFromMap; - - // addLayer - this.addLayer = pgInstanceOfLG ? - this._addLayerToGroup : - this._addLayerToMap; - - // removeLayer - this.removeLayer = pgInstanceOfLG ? - this._removeLayerFromGroup : - this._removeLayerFromMap; - - return this; - }, - - /** - * Removes the current sub-group from map before changing the parent - * group. Re-adds the sub-group to map if it was before changing. - * @param parentGroup (L.LayerGroup) - * @returns {SubGroup} this - */ - setParentGroupSafe: function (parentGroup) { - var map = this._map; - - if (map) { - map.removeLayer(this); - } - - this.setParentGroup(parentGroup); - - if (map) { - map.addLayer(this); - } - - return this; - }, - - /** - * Returns the current parent group. - * @returns {*} - */ - getParentGroup: function () { - return this._parentGroup; - }, - - - // For parent groups with batch methods (addLayers and removeLayers) - // like MarkerCluster. - _onAddToGroupBatch: function (map) { - var layersArray = this.getLayers(); - - this._map = map; - this._parentGroup.addLayers(layersArray); - }, - - _onRemoveFromGroupBatch: function () { - var layersArray = this.getLayers(); - - this._parentGroup.removeLayers(layersArray); - this._map = null; - }, - - - // For other parent layer groups. - _onAddToGroup: function (map) { - var parentGroup = this._parentGroup; - - this._map = map; - this.eachLayer(parentGroup.addLayer, parentGroup); - }, - - _onRemoveFromGroup: function () { - var parentGroup = this._parentGroup; - - this.eachLayer(parentGroup.removeLayer, parentGroup); - this._map = null; - }, - - - // Defaults to standard FeatureGroup behaviour when parent group is not - // specified or is not a type of LayerGroup. - _onAddToMap: L.FeatureGroup.prototype.onAdd, - _onRemoveFromMap: L.FeatureGroup.prototype.onRemove, - - - _addLayerToGroup: function (layer) { - if (this.hasLayer(layer)) { - return this; - } - - if (layer.on) { - layer.on(L.FeatureGroup.EVENTS, this._propagateEvent, this); - } - - var id = this.getLayerId(layer); - - this._layers[id] = layer; - - if (this._map) { - // Add to parent group instead of directly to map. - this._parentGroup.addLayer(layer); - } - - if (this._popupContent && layer.bindPopup) { - layer.bindPopup(this._popupContent, this._popupOptions); - } - - return this.fire('layeradd', {layer: layer}); - }, - - _removeLayerFromGroup: function (layer) { - if (!this.hasLayer(layer)) { - return this; - } - if (layer in this._layers) { - layer = this._layers[layer]; - } - - if (layer.off) { - layer.off(L.FeatureGroup.EVENTS, this._propagateEvent, this); - } - - var id = layer in this._layers ? layer : this.getLayerId(layer); - - if (this._map && this._layers[id]) { - // Remove from parent group instead of directly from map. - this._parentGroup.removeLayer(id); - } - - delete this._layers[id]; - - if (this._popupContent) { - this.invoke('unbindPopup'); - } - - return this.fire('layerremove', {layer: layer}); - }, - - // Defaults to standard FeatureGroup behaviour when parent group is not - // specified or is not a type of LayerGroup. - _addLayerToMap: L.FeatureGroup.prototype.addLayer, - _removeLayerFromMap: L.FeatureGroup.prototype.removeLayer - - }); - - - - // Supply with a factory for consistency with Leaflet. - L.featureGroup.subGroup = function (parentGroup, options) { - return new L.FeatureGroup.SubGroup(parentGroup, options); - }; - -})); diff --git a/assets/www/dist/dist_js/app/vendor/leaflet.js b/assets/www/dist/dist_js/app/vendor/leaflet.js deleted file mode 100644 index ee5ff5a1d4bc321e2f521752ecf7c34dc33d3d82..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/leaflet.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com - (c) 2010-2013, Vladimir Agafonkin - (c) 2010-2011, CloudMade -*/ -!function(t,e,i){var n=t.L,o={};o.version="0.7.7","object"==typeof module&&"object"==typeof module.exports?module.exports=o:"function"==typeof define&&define.amd&&define(o),o.noConflict=function(){return t.L=n,this},t.L=o,o.Util={extend:function(t){var e,i,n,o,s=Array.prototype.slice.call(arguments,1);for(i=0,n=s.length;n>i;i++){o=s[i]||{};for(e in o)o.hasOwnProperty(e)&&(t[e]=o[e])}return t},bind:function(t,e){var i=arguments.length>2?Array.prototype.slice.call(arguments,2):null;return function(){return t.apply(e,i||arguments)}},stamp:function(){var t=0,e="_leaflet_id";return function(i){return i[e]=i[e]||++t,i[e]}}(),invokeEach:function(t,e,i){var n,o;if("object"==typeof t){o=Array.prototype.slice.call(arguments,3);for(n in t)e.apply(i,[n,t[n]].concat(o));return!0}return!1},limitExecByInterval:function(t,e,i){var n,o;return function s(){var a=arguments;return n?void(o=!0):(n=!0,setTimeout(function(){n=!1,o&&(s.apply(i,a),o=!1)},e),void t.apply(i,a))}},falseFn:function(){return!1},formatNum:function(t,e){var i=Math.pow(10,e||5);return Math.round(t*i)/i},trim:function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")},splitWords:function(t){return o.Util.trim(t).split(/\s+/)},setOptions:function(t,e){return t.options=o.extend({},t.options,e),t.options},getParamString:function(t,e,i){var n=[];for(var o in t)n.push(encodeURIComponent(i?o.toUpperCase():o)+"="+encodeURIComponent(t[o]));return(e&&-1!==e.indexOf("?")?"&":"?")+n.join("&")},template:function(t,e){return t.replace(/\{ *([\w_]+) *\}/g,function(t,n){var o=e[n];if(o===i)throw new Error("No value provided for variable "+t);return"function"==typeof o&&(o=o(e)),o})},isArray:Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)},emptyImageUrl:"data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="},function(){function e(e){var i,n,o=["webkit","moz","o","ms"];for(i=0;i<o.length&&!n;i++)n=t[o[i]+e];return n}function i(e){var i=+new Date,o=Math.max(0,16-(i-n));return n=i+o,t.setTimeout(e,o)}var n=0,s=t.requestAnimationFrame||e("RequestAnimationFrame")||i,a=t.cancelAnimationFrame||e("CancelAnimationFrame")||e("CancelRequestAnimationFrame")||function(e){t.clearTimeout(e)};o.Util.requestAnimFrame=function(e,n,a,r){return e=o.bind(e,n),a&&s===i?void e():s.call(t,e,r)},o.Util.cancelAnimFrame=function(e){e&&a.call(t,e)}}(),o.extend=o.Util.extend,o.bind=o.Util.bind,o.stamp=o.Util.stamp,o.setOptions=o.Util.setOptions,o.Class=function(){},o.Class.extend=function(t){var e=function(){this.initialize&&this.initialize.apply(this,arguments),this._initHooks&&this.callInitHooks()},i=function(){};i.prototype=this.prototype;var n=new i;n.constructor=e,e.prototype=n;for(var s in this)this.hasOwnProperty(s)&&"prototype"!==s&&(e[s]=this[s]);t.statics&&(o.extend(e,t.statics),delete t.statics),t.includes&&(o.Util.extend.apply(null,[n].concat(t.includes)),delete t.includes),t.options&&n.options&&(t.options=o.extend({},n.options,t.options)),o.extend(n,t),n._initHooks=[];var a=this;return e.__super__=a.prototype,n.callInitHooks=function(){if(!this._initHooksCalled){a.prototype.callInitHooks&&a.prototype.callInitHooks.call(this),this._initHooksCalled=!0;for(var t=0,e=n._initHooks.length;e>t;t++)n._initHooks[t].call(this)}},e},o.Class.include=function(t){o.extend(this.prototype,t)},o.Class.mergeOptions=function(t){o.extend(this.prototype.options,t)},o.Class.addInitHook=function(t){var e=Array.prototype.slice.call(arguments,1),i="function"==typeof t?t:function(){this[t].apply(this,e)};this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(i)};var s="_leaflet_events";o.Mixin={},o.Mixin.Events={addEventListener:function(t,e,i){if(o.Util.invokeEach(t,this.addEventListener,this,e,i))return this;var n,a,r,h,l,u,c,d=this[s]=this[s]||{},p=i&&i!==this&&o.stamp(i);for(t=o.Util.splitWords(t),n=0,a=t.length;a>n;n++)r={action:e,context:i||this},h=t[n],p?(l=h+"_idx",u=l+"_len",c=d[l]=d[l]||{},c[p]||(c[p]=[],d[u]=(d[u]||0)+1),c[p].push(r)):(d[h]=d[h]||[],d[h].push(r));return this},hasEventListeners:function(t){var e=this[s];return!!e&&(t in e&&e[t].length>0||t+"_idx"in e&&e[t+"_idx_len"]>0)},removeEventListener:function(t,e,i){if(!this[s])return this;if(!t)return this.clearAllEventListeners();if(o.Util.invokeEach(t,this.removeEventListener,this,e,i))return this;var n,a,r,h,l,u,c,d,p,_=this[s],m=i&&i!==this&&o.stamp(i);for(t=o.Util.splitWords(t),n=0,a=t.length;a>n;n++)if(r=t[n],u=r+"_idx",c=u+"_len",d=_[u],e){if(h=m&&d?d[m]:_[r]){for(l=h.length-1;l>=0;l--)h[l].action!==e||i&&h[l].context!==i||(p=h.splice(l,1),p[0].action=o.Util.falseFn);i&&d&&0===h.length&&(delete d[m],_[c]--)}}else delete _[r],delete _[u],delete _[c];return this},clearAllEventListeners:function(){return delete this[s],this},fireEvent:function(t,e){if(!this.hasEventListeners(t))return this;var i,n,a,r,h,l=o.Util.extend({},e,{type:t,target:this}),u=this[s];if(u[t])for(i=u[t].slice(),n=0,a=i.length;a>n;n++)i[n].action.call(i[n].context,l);r=u[t+"_idx"];for(h in r)if(i=r[h].slice())for(n=0,a=i.length;a>n;n++)i[n].action.call(i[n].context,l);return this},addOneTimeEventListener:function(t,e,i){if(o.Util.invokeEach(t,this.addOneTimeEventListener,this,e,i))return this;var n=o.bind(function(){this.removeEventListener(t,e,i).removeEventListener(t,n,i)},this);return this.addEventListener(t,e,i).addEventListener(t,n,i)}},o.Mixin.Events.on=o.Mixin.Events.addEventListener,o.Mixin.Events.off=o.Mixin.Events.removeEventListener,o.Mixin.Events.once=o.Mixin.Events.addOneTimeEventListener,o.Mixin.Events.fire=o.Mixin.Events.fireEvent,function(){var n="ActiveXObject"in t,s=n&&!e.addEventListener,a=navigator.userAgent.toLowerCase(),r=-1!==a.indexOf("webkit"),h=-1!==a.indexOf("chrome"),l=-1!==a.indexOf("phantom"),u=-1!==a.indexOf("android"),c=-1!==a.search("android [23]"),d=-1!==a.indexOf("gecko"),p=typeof orientation!=i+"",_=!t.PointerEvent&&t.MSPointerEvent,m=t.PointerEvent&&t.navigator.pointerEnabled||_,f="devicePixelRatio"in t&&t.devicePixelRatio>1||"matchMedia"in t&&t.matchMedia("(min-resolution:144dpi)")&&t.matchMedia("(min-resolution:144dpi)").matches,g=e.documentElement,v=n&&"transition"in g.style,y="WebKitCSSMatrix"in t&&"m11"in new t.WebKitCSSMatrix&&!c,P="MozPerspective"in g.style,L="OTransition"in g.style,x=!t.L_DISABLE_3D&&(v||y||P||L)&&!l,w=!t.L_NO_TOUCH&&!l&&(m||"ontouchstart"in t||t.DocumentTouch&&e instanceof t.DocumentTouch);o.Browser={ie:n,ielt9:s,webkit:r,gecko:d&&!r&&!t.opera&&!n,android:u,android23:c,chrome:h,ie3d:v,webkit3d:y,gecko3d:P,opera3d:L,any3d:x,mobile:p,mobileWebkit:p&&r,mobileWebkit3d:p&&y,mobileOpera:p&&t.opera,touch:w,msPointer:_,pointer:m,retina:f}}(),o.Point=function(t,e,i){this.x=i?Math.round(t):t,this.y=i?Math.round(e):e},o.Point.prototype={clone:function(){return new o.Point(this.x,this.y)},add:function(t){return this.clone()._add(o.point(t))},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(o.point(t))},_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t){return this.clone()._divideBy(t)},_divideBy:function(t){return this.x/=t,this.y/=t,this},multiplyBy:function(t){return this.clone()._multiplyBy(t)},_multiplyBy:function(t){return this.x*=t,this.y*=t,this},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},distanceTo:function(t){t=o.point(t);var e=t.x-this.x,i=t.y-this.y;return Math.sqrt(e*e+i*i)},equals:function(t){return t=o.point(t),t.x===this.x&&t.y===this.y},contains:function(t){return t=o.point(t),Math.abs(t.x)<=Math.abs(this.x)&&Math.abs(t.y)<=Math.abs(this.y)},toString:function(){return"Point("+o.Util.formatNum(this.x)+", "+o.Util.formatNum(this.y)+")"}},o.point=function(t,e,n){return t instanceof o.Point?t:o.Util.isArray(t)?new o.Point(t[0],t[1]):t===i||null===t?t:new o.Point(t,e,n)},o.Bounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},o.Bounds.prototype={extend:function(t){return t=o.point(t),this.min||this.max?(this.min.x=Math.min(t.x,this.min.x),this.max.x=Math.max(t.x,this.max.x),this.min.y=Math.min(t.y,this.min.y),this.max.y=Math.max(t.y,this.max.y)):(this.min=t.clone(),this.max=t.clone()),this},getCenter:function(t){return new o.Point((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2,t)},getBottomLeft:function(){return new o.Point(this.min.x,this.max.y)},getTopRight:function(){return new o.Point(this.max.x,this.min.y)},getSize:function(){return this.max.subtract(this.min)},contains:function(t){var e,i;return t="number"==typeof t[0]||t instanceof o.Point?o.point(t):o.bounds(t),t instanceof o.Bounds?(e=t.min,i=t.max):e=i=t,e.x>=this.min.x&&i.x<=this.max.x&&e.y>=this.min.y&&i.y<=this.max.y},intersects:function(t){t=o.bounds(t);var e=this.min,i=this.max,n=t.min,s=t.max,a=s.x>=e.x&&n.x<=i.x,r=s.y>=e.y&&n.y<=i.y;return a&&r},isValid:function(){return!(!this.min||!this.max)}},o.bounds=function(t,e){return!t||t instanceof o.Bounds?t:new o.Bounds(t,e)},o.Transformation=function(t,e,i,n){this._a=t,this._b=e,this._c=i,this._d=n},o.Transformation.prototype={transform:function(t,e){return this._transform(t.clone(),e)},_transform:function(t,e){return e=e||1,t.x=e*(this._a*t.x+this._b),t.y=e*(this._c*t.y+this._d),t},untransform:function(t,e){return e=e||1,new o.Point((t.x/e-this._b)/this._a,(t.y/e-this._d)/this._c)}},o.DomUtil={get:function(t){return"string"==typeof t?e.getElementById(t):t},getStyle:function(t,i){var n=t.style[i];if(!n&&t.currentStyle&&(n=t.currentStyle[i]),(!n||"auto"===n)&&e.defaultView){var o=e.defaultView.getComputedStyle(t,null);n=o?o[i]:null}return"auto"===n?null:n},getViewportOffset:function(t){var i,n=0,s=0,a=t,r=e.body,h=e.documentElement;do{if(n+=a.offsetTop||0,s+=a.offsetLeft||0,n+=parseInt(o.DomUtil.getStyle(a,"borderTopWidth"),10)||0,s+=parseInt(o.DomUtil.getStyle(a,"borderLeftWidth"),10)||0,i=o.DomUtil.getStyle(a,"position"),a.offsetParent===r&&"absolute"===i)break;if("fixed"===i){n+=r.scrollTop||h.scrollTop||0,s+=r.scrollLeft||h.scrollLeft||0;break}if("relative"===i&&!a.offsetLeft){var l=o.DomUtil.getStyle(a,"width"),u=o.DomUtil.getStyle(a,"max-width"),c=a.getBoundingClientRect();("none"!==l||"none"!==u)&&(s+=c.left+a.clientLeft),n+=c.top+(r.scrollTop||h.scrollTop||0);break}a=a.offsetParent}while(a);a=t;do{if(a===r)break;n-=a.scrollTop||0,s-=a.scrollLeft||0,a=a.parentNode}while(a);return new o.Point(s,n)},documentIsLtr:function(){return o.DomUtil._docIsLtrCached||(o.DomUtil._docIsLtrCached=!0,o.DomUtil._docIsLtr="ltr"===o.DomUtil.getStyle(e.body,"direction")),o.DomUtil._docIsLtr},create:function(t,i,n){var o=e.createElement(t);return o.className=i,n&&n.appendChild(o),o},hasClass:function(t,e){if(t.classList!==i)return t.classList.contains(e);var n=o.DomUtil._getClass(t);return n.length>0&&new RegExp("(^|\\s)"+e+"(\\s|$)").test(n)},addClass:function(t,e){if(t.classList!==i)for(var n=o.Util.splitWords(e),s=0,a=n.length;a>s;s++)t.classList.add(n[s]);else if(!o.DomUtil.hasClass(t,e)){var r=o.DomUtil._getClass(t);o.DomUtil._setClass(t,(r?r+" ":"")+e)}},removeClass:function(t,e){t.classList!==i?t.classList.remove(e):o.DomUtil._setClass(t,o.Util.trim((" "+o.DomUtil._getClass(t)+" ").replace(" "+e+" "," ")))},_setClass:function(t,e){t.className.baseVal===i?t.className=e:t.className.baseVal=e},_getClass:function(t){return t.className.baseVal===i?t.className:t.className.baseVal},setOpacity:function(t,e){if("opacity"in t.style)t.style.opacity=e;else if("filter"in t.style){var i=!1,n="DXImageTransform.Microsoft.Alpha";try{i=t.filters.item(n)}catch(o){if(1===e)return}e=Math.round(100*e),i?(i.Enabled=100!==e,i.Opacity=e):t.style.filter+=" progid:"+n+"(opacity="+e+")"}},testProp:function(t){for(var i=e.documentElement.style,n=0;n<t.length;n++)if(t[n]in i)return t[n];return!1},getTranslateString:function(t){var e=o.Browser.webkit3d,i="translate"+(e?"3d":"")+"(",n=(e?",0":"")+")";return i+t.x+"px,"+t.y+"px"+n},getScaleString:function(t,e){var i=o.DomUtil.getTranslateString(e.add(e.multiplyBy(-1*t))),n=" scale("+t+") ";return i+n},setPosition:function(t,e,i){t._leaflet_pos=e,!i&&o.Browser.any3d?t.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(e):(t.style.left=e.x+"px",t.style.top=e.y+"px")},getPosition:function(t){return t._leaflet_pos}},o.DomUtil.TRANSFORM=o.DomUtil.testProp(["transform","WebkitTransform","OTransform","MozTransform","msTransform"]),o.DomUtil.TRANSITION=o.DomUtil.testProp(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),o.DomUtil.TRANSITION_END="webkitTransition"===o.DomUtil.TRANSITION||"OTransition"===o.DomUtil.TRANSITION?o.DomUtil.TRANSITION+"End":"transitionend",function(){if("onselectstart"in e)o.extend(o.DomUtil,{disableTextSelection:function(){o.DomEvent.on(t,"selectstart",o.DomEvent.preventDefault)},enableTextSelection:function(){o.DomEvent.off(t,"selectstart",o.DomEvent.preventDefault)}});else{var i=o.DomUtil.testProp(["userSelect","WebkitUserSelect","OUserSelect","MozUserSelect","msUserSelect"]);o.extend(o.DomUtil,{disableTextSelection:function(){if(i){var t=e.documentElement.style;this._userSelect=t[i],t[i]="none"}},enableTextSelection:function(){i&&(e.documentElement.style[i]=this._userSelect,delete this._userSelect)}})}o.extend(o.DomUtil,{disableImageDrag:function(){o.DomEvent.on(t,"dragstart",o.DomEvent.preventDefault)},enableImageDrag:function(){o.DomEvent.off(t,"dragstart",o.DomEvent.preventDefault)}})}(),o.LatLng=function(t,e,n){if(t=parseFloat(t),e=parseFloat(e),isNaN(t)||isNaN(e))throw new Error("Invalid LatLng object: ("+t+", "+e+")");this.lat=t,this.lng=e,n!==i&&(this.alt=parseFloat(n))},o.extend(o.LatLng,{DEG_TO_RAD:Math.PI/180,RAD_TO_DEG:180/Math.PI,MAX_MARGIN:1e-9}),o.LatLng.prototype={equals:function(t){if(!t)return!1;t=o.latLng(t);var e=Math.max(Math.abs(this.lat-t.lat),Math.abs(this.lng-t.lng));return e<=o.LatLng.MAX_MARGIN},toString:function(t){return"LatLng("+o.Util.formatNum(this.lat,t)+", "+o.Util.formatNum(this.lng,t)+")"},distanceTo:function(t){t=o.latLng(t);var e=6378137,i=o.LatLng.DEG_TO_RAD,n=(t.lat-this.lat)*i,s=(t.lng-this.lng)*i,a=this.lat*i,r=t.lat*i,h=Math.sin(n/2),l=Math.sin(s/2),u=h*h+l*l*Math.cos(a)*Math.cos(r);return 2*e*Math.atan2(Math.sqrt(u),Math.sqrt(1-u))},wrap:function(t,e){var i=this.lng;return t=t||-180,e=e||180,i=(i+e)%(e-t)+(t>i||i===e?e:t),new o.LatLng(this.lat,i)}},o.latLng=function(t,e){return t instanceof o.LatLng?t:o.Util.isArray(t)?"number"==typeof t[0]||"string"==typeof t[0]?new o.LatLng(t[0],t[1],t[2]):null:t===i||null===t?t:"object"==typeof t&&"lat"in t?new o.LatLng(t.lat,"lng"in t?t.lng:t.lon):e===i?null:new o.LatLng(t,e)},o.LatLngBounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},o.LatLngBounds.prototype={extend:function(t){if(!t)return this;var e=o.latLng(t);return t=null!==e?e:o.latLngBounds(t),t instanceof o.LatLng?this._southWest||this._northEast?(this._southWest.lat=Math.min(t.lat,this._southWest.lat),this._southWest.lng=Math.min(t.lng,this._southWest.lng),this._northEast.lat=Math.max(t.lat,this._northEast.lat),this._northEast.lng=Math.max(t.lng,this._northEast.lng)):(this._southWest=new o.LatLng(t.lat,t.lng),this._northEast=new o.LatLng(t.lat,t.lng)):t instanceof o.LatLngBounds&&(this.extend(t._southWest),this.extend(t._northEast)),this},pad:function(t){var e=this._southWest,i=this._northEast,n=Math.abs(e.lat-i.lat)*t,s=Math.abs(e.lng-i.lng)*t;return new o.LatLngBounds(new o.LatLng(e.lat-n,e.lng-s),new o.LatLng(i.lat+n,i.lng+s))},getCenter:function(){return new o.LatLng((this._southWest.lat+this._northEast.lat)/2,(this._southWest.lng+this._northEast.lng)/2)},getSouthWest:function(){return this._southWest},getNorthEast:function(){return this._northEast},getNorthWest:function(){return new o.LatLng(this.getNorth(),this.getWest())},getSouthEast:function(){return new o.LatLng(this.getSouth(),this.getEast())},getWest:function(){return this._southWest.lng},getSouth:function(){return this._southWest.lat},getEast:function(){return this._northEast.lng},getNorth:function(){return this._northEast.lat},contains:function(t){t="number"==typeof t[0]||t instanceof o.LatLng?o.latLng(t):o.latLngBounds(t);var e,i,n=this._southWest,s=this._northEast;return t instanceof o.LatLngBounds?(e=t.getSouthWest(),i=t.getNorthEast()):e=i=t,e.lat>=n.lat&&i.lat<=s.lat&&e.lng>=n.lng&&i.lng<=s.lng},intersects:function(t){t=o.latLngBounds(t);var e=this._southWest,i=this._northEast,n=t.getSouthWest(),s=t.getNorthEast(),a=s.lat>=e.lat&&n.lat<=i.lat,r=s.lng>=e.lng&&n.lng<=i.lng;return a&&r},toBBoxString:function(){return[this.getWest(),this.getSouth(),this.getEast(),this.getNorth()].join(",")},equals:function(t){return t?(t=o.latLngBounds(t),this._southWest.equals(t.getSouthWest())&&this._northEast.equals(t.getNorthEast())):!1},isValid:function(){return!(!this._southWest||!this._northEast)}},o.latLngBounds=function(t,e){return!t||t instanceof o.LatLngBounds?t:new o.LatLngBounds(t,e)},o.Projection={},o.Projection.SphericalMercator={MAX_LATITUDE:85.0511287798,project:function(t){var e=o.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,n=Math.max(Math.min(i,t.lat),-i),s=t.lng*e,a=n*e;return a=Math.log(Math.tan(Math.PI/4+a/2)),new o.Point(s,a)},unproject:function(t){var e=o.LatLng.RAD_TO_DEG,i=t.x*e,n=(2*Math.atan(Math.exp(t.y))-Math.PI/2)*e;return new o.LatLng(n,i)}},o.Projection.LonLat={project:function(t){return new o.Point(t.lng,t.lat)},unproject:function(t){return new o.LatLng(t.y,t.x)}},o.CRS={latLngToPoint:function(t,e){var i=this.projection.project(t),n=this.scale(e);return this.transformation._transform(i,n)},pointToLatLng:function(t,e){var i=this.scale(e),n=this.transformation.untransform(t,i);return this.projection.unproject(n)},project:function(t){return this.projection.project(t)},scale:function(t){return 256*Math.pow(2,t)},getSize:function(t){var e=this.scale(t);return o.point(e,e)}},o.CRS.Simple=o.extend({},o.CRS,{projection:o.Projection.LonLat,transformation:new o.Transformation(1,0,-1,0),scale:function(t){return Math.pow(2,t)}}),o.CRS.EPSG3857=o.extend({},o.CRS,{code:"EPSG:3857",projection:o.Projection.SphericalMercator,transformation:new o.Transformation(.5/Math.PI,.5,-.5/Math.PI,.5),project:function(t){var e=this.projection.project(t),i=6378137;return e.multiplyBy(i)}}),o.CRS.EPSG900913=o.extend({},o.CRS.EPSG3857,{code:"EPSG:900913"}),o.CRS.EPSG4326=o.extend({},o.CRS,{code:"EPSG:4326",projection:o.Projection.LonLat,transformation:new o.Transformation(1/360,.5,-1/360,.5)}),o.Map=o.Class.extend({includes:o.Mixin.Events,options:{crs:o.CRS.EPSG3857,fadeAnimation:o.DomUtil.TRANSITION&&!o.Browser.android23,trackResize:!0,markerZoomAnimation:o.DomUtil.TRANSITION&&o.Browser.any3d},initialize:function(t,e){e=o.setOptions(this,e),this._initContainer(t),this._initLayout(),this._onResize=o.bind(this._onResize,this),this._initEvents(),e.maxBounds&&this.setMaxBounds(e.maxBounds),e.center&&e.zoom!==i&&this.setView(o.latLng(e.center),e.zoom,{reset:!0}),this._handlers=[],this._layers={},this._zoomBoundLayers={},this._tileLayersNum=0,this.callInitHooks(),this._addLayers(e.layers)},setView:function(t,e){return e=e===i?this.getZoom():e,this._resetView(o.latLng(t),this._limitZoom(e)),this},setZoom:function(t,e){return this._loaded?this.setView(this.getCenter(),t,{zoom:e}):(this._zoom=this._limitZoom(t),this)},zoomIn:function(t,e){return this.setZoom(this._zoom+(t||1),e)},zoomOut:function(t,e){return this.setZoom(this._zoom-(t||1),e)},setZoomAround:function(t,e,i){var n=this.getZoomScale(e),s=this.getSize().divideBy(2),a=t instanceof o.Point?t:this.latLngToContainerPoint(t),r=a.subtract(s).multiplyBy(1-1/n),h=this.containerPointToLatLng(s.add(r));return this.setView(h,e,{zoom:i})},fitBounds:function(t,e){e=e||{},t=t.getBounds?t.getBounds():o.latLngBounds(t);var i=o.point(e.paddingTopLeft||e.padding||[0,0]),n=o.point(e.paddingBottomRight||e.padding||[0,0]),s=this.getBoundsZoom(t,!1,i.add(n));s=e.maxZoom?Math.min(e.maxZoom,s):s;var a=n.subtract(i).divideBy(2),r=this.project(t.getSouthWest(),s),h=this.project(t.getNorthEast(),s),l=this.unproject(r.add(h).divideBy(2).add(a),s);return this.setView(l,s,e)},fitWorld:function(t){return this.fitBounds([[-90,-180],[90,180]],t)},panTo:function(t,e){return this.setView(t,this._zoom,{pan:e})},panBy:function(t){return this.fire("movestart"),this._rawPanBy(o.point(t)),this.fire("move"),this.fire("moveend")},setMaxBounds:function(t){return t=o.latLngBounds(t),this.options.maxBounds=t,t?(this._loaded&&this._panInsideMaxBounds(),this.on("moveend",this._panInsideMaxBounds,this)):this.off("moveend",this._panInsideMaxBounds,this)},panInsideBounds:function(t,e){var i=this.getCenter(),n=this._limitCenter(i,this._zoom,t);return i.equals(n)?this:this.panTo(n,e)},addLayer:function(t){var e=o.stamp(t);return this._layers[e]?this:(this._layers[e]=t,!t.options||isNaN(t.options.maxZoom)&&isNaN(t.options.minZoom)||(this._zoomBoundLayers[e]=t,this._updateZoomLevels()),this.options.zoomAnimation&&o.TileLayer&&t instanceof o.TileLayer&&(this._tileLayersNum++,this._tileLayersToLoad++,t.on("load",this._onTileLayerLoad,this)),this._loaded&&this._layerAdd(t),this)},removeLayer:function(t){var e=o.stamp(t);return this._layers[e]?(this._loaded&&t.onRemove(this),delete this._layers[e],this._loaded&&this.fire("layerremove",{layer:t}),this._zoomBoundLayers[e]&&(delete this._zoomBoundLayers[e],this._updateZoomLevels()),this.options.zoomAnimation&&o.TileLayer&&t instanceof o.TileLayer&&(this._tileLayersNum--,this._tileLayersToLoad--,t.off("load",this._onTileLayerLoad,this)),this):this},hasLayer:function(t){return t?o.stamp(t)in this._layers:!1},eachLayer:function(t,e){for(var i in this._layers)t.call(e,this._layers[i]);return this},invalidateSize:function(t){if(!this._loaded)return this;t=o.extend({animate:!1,pan:!0},t===!0?{animate:!0}:t);var e=this.getSize();this._sizeChanged=!0,this._initialCenter=null;var i=this.getSize(),n=e.divideBy(2).round(),s=i.divideBy(2).round(),a=n.subtract(s);return a.x||a.y?(t.animate&&t.pan?this.panBy(a):(t.pan&&this._rawPanBy(a),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(o.bind(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:e,newSize:i})):this},addHandler:function(t,e){if(!e)return this;var i=this[t]=new e(this);return this._handlers.push(i),this.options[t]&&i.enable(),this},remove:function(){this._loaded&&this.fire("unload"),this._initEvents("off");try{delete this._container._leaflet}catch(t){this._container._leaflet=i}return this._clearPanes(),this._clearControlPos&&this._clearControlPos(),this._clearHandlers(),this},getCenter:function(){return this._checkIfLoaded(),this._initialCenter&&!this._moved()?this._initialCenter:this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds(),e=this.unproject(t.getBottomLeft()),i=this.unproject(t.getTopRight());return new o.LatLngBounds(e,i)},getMinZoom:function(){return this.options.minZoom===i?this._layersMinZoom===i?0:this._layersMinZoom:this.options.minZoom},getMaxZoom:function(){return this.options.maxZoom===i?this._layersMaxZoom===i?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,e,i){t=o.latLngBounds(t);var n,s=this.getMinZoom()-(e?1:0),a=this.getMaxZoom(),r=this.getSize(),h=t.getNorthWest(),l=t.getSouthEast(),u=!0;i=o.point(i||[0,0]);do s++,n=this.project(l,s).subtract(this.project(h,s)).add(i),u=e?n.x<r.x||n.y<r.y:r.contains(n);while(u&&a>=s);return u&&e?null:e?s:s-1},getSize:function(){return(!this._size||this._sizeChanged)&&(this._size=new o.Point(this._container.clientWidth,this._container.clientHeight),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(){var t=this._getTopLeftPoint();return new o.Bounds(t,t.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._initialTopLeftPoint},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t){var e=this.options.crs;return e.scale(t)/e.scale(this._zoom)},getScaleZoom:function(t){return this._zoom+Math.log(t)/Math.LN2},project:function(t,e){return e=e===i?this._zoom:e,this.options.crs.latLngToPoint(o.latLng(t),e)},unproject:function(t,e){return e=e===i?this._zoom:e,this.options.crs.pointToLatLng(o.point(t),e)},layerPointToLatLng:function(t){var e=o.point(t).add(this.getPixelOrigin());return this.unproject(e)},latLngToLayerPoint:function(t){var e=this.project(o.latLng(t))._round();return e._subtract(this.getPixelOrigin())},containerPointToLayerPoint:function(t){return o.point(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return o.point(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var e=this.containerPointToLayerPoint(o.point(t));return this.layerPointToLatLng(e)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(o.latLng(t)))},mouseEventToContainerPoint:function(t){return o.DomEvent.getMousePosition(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var e=this._container=o.DomUtil.get(t);if(!e)throw new Error("Map container not found.");if(e._leaflet)throw new Error("Map container is already initialized.");e._leaflet=!0},_initLayout:function(){var t=this._container;o.DomUtil.addClass(t,"leaflet-container"+(o.Browser.touch?" leaflet-touch":"")+(o.Browser.retina?" leaflet-retina":"")+(o.Browser.ielt9?" leaflet-oldie":"")+(this.options.fadeAnimation?" leaflet-fade-anim":""));var e=o.DomUtil.getStyle(t,"position");"absolute"!==e&&"relative"!==e&&"fixed"!==e&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._mapPane=t.mapPane=this._createPane("leaflet-map-pane",this._container),this._tilePane=t.tilePane=this._createPane("leaflet-tile-pane",this._mapPane),t.objectsPane=this._createPane("leaflet-objects-pane",this._mapPane),t.shadowPane=this._createPane("leaflet-shadow-pane"),t.overlayPane=this._createPane("leaflet-overlay-pane"),t.markerPane=this._createPane("leaflet-marker-pane"),t.popupPane=this._createPane("leaflet-popup-pane");var e=" leaflet-zoom-hide";this.options.markerZoomAnimation||(o.DomUtil.addClass(t.markerPane,e),o.DomUtil.addClass(t.shadowPane,e),o.DomUtil.addClass(t.popupPane,e))},_createPane:function(t,e){return o.DomUtil.create("div",t,e||this._panes.objectsPane)},_clearPanes:function(){this._container.removeChild(this._mapPane)},_addLayers:function(t){t=t?o.Util.isArray(t)?t:[t]:[];for(var e=0,i=t.length;i>e;e++)this.addLayer(t[e])},_resetView:function(t,e,i,n){var s=this._zoom!==e;n||(this.fire("movestart"),s&&this.fire("zoomstart")),this._zoom=e,this._initialCenter=t,this._initialTopLeftPoint=this._getNewTopLeftPoint(t),i?this._initialTopLeftPoint._add(this._getMapPanePos()):o.DomUtil.setPosition(this._mapPane,new o.Point(0,0)),this._tileLayersToLoad=this._tileLayersNum;var a=!this._loaded;this._loaded=!0,this.fire("viewreset",{hard:!i}),a&&(this.fire("load"),this.eachLayer(this._layerAdd,this)),this.fire("move"),(s||n)&&this.fire("zoomend"),this.fire("moveend",{hard:!i})},_rawPanBy:function(t){o.DomUtil.setPosition(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_updateZoomLevels:function(){var t,e=1/0,n=-(1/0),o=this._getZoomSpan();for(t in this._zoomBoundLayers){var s=this._zoomBoundLayers[t];isNaN(s.options.minZoom)||(e=Math.min(e,s.options.minZoom)),isNaN(s.options.maxZoom)||(n=Math.max(n,s.options.maxZoom))}t===i?this._layersMaxZoom=this._layersMinZoom=i:(this._layersMaxZoom=n,this._layersMinZoom=e),o!==this._getZoomSpan()&&this.fire("zoomlevelschange")},_panInsideMaxBounds:function(){this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(e){if(o.DomEvent){e=e||"on",o.DomEvent[e](this._container,"click",this._onMouseClick,this);var i,n,s=["dblclick","mousedown","mouseup","mouseenter","mouseleave","mousemove","contextmenu"];for(i=0,n=s.length;n>i;i++)o.DomEvent[e](this._container,s[i],this._fireMouseEvent,this);this.options.trackResize&&o.DomEvent[e](t,"resize",this._onResize,this)}},_onResize:function(){o.Util.cancelAnimFrame(this._resizeRequest),this._resizeRequest=o.Util.requestAnimFrame(function(){this.invalidateSize({debounceMoveend:!0})},this,!1,this._container)},_onMouseClick:function(t){!this._loaded||!t._simulated&&(this.dragging&&this.dragging.moved()||this.boxZoom&&this.boxZoom.moved())||o.DomEvent._skipped(t)||(this.fire("preclick"),this._fireMouseEvent(t))},_fireMouseEvent:function(t){if(this._loaded&&!o.DomEvent._skipped(t)){var e=t.type;if(e="mouseenter"===e?"mouseover":"mouseleave"===e?"mouseout":e,this.hasEventListeners(e)){"contextmenu"===e&&o.DomEvent.preventDefault(t);var i=this.mouseEventToContainerPoint(t),n=this.containerPointToLayerPoint(i),s=this.layerPointToLatLng(n);this.fire(e,{latlng:s,layerPoint:n,containerPoint:i,originalEvent:t})}}},_onTileLayerLoad:function(){this._tileLayersToLoad--,this._tileLayersNum&&!this._tileLayersToLoad&&this.fire("tilelayersload")},_clearHandlers:function(){for(var t=0,e=this._handlers.length;e>t;t++)this._handlers[t].disable()},whenReady:function(t,e){return this._loaded?t.call(e||this,this):this.on("load",t,e),this},_layerAdd:function(t){t.onAdd(this),this.fire("layeradd",{layer:t})},_getMapPanePos:function(){return o.DomUtil.getPosition(this._mapPane)},_moved:function(){var t=this._getMapPanePos();return t&&!t.equals([0,0])},_getTopLeftPoint:function(){return this.getPixelOrigin().subtract(this._getMapPanePos())},_getNewTopLeftPoint:function(t,e){var i=this.getSize()._divideBy(2);return this.project(t,e)._subtract(i)._round()},_latLngToNewLayerPoint:function(t,e,i){var n=this._getNewTopLeftPoint(i,e).add(this._getMapPanePos());return this.project(t,e)._subtract(n)},_getCenterLayerPoint:function(){return this.containerPointToLayerPoint(this.getSize()._divideBy(2))},_getCenterOffset:function(t){return this.latLngToLayerPoint(t).subtract(this._getCenterLayerPoint())},_limitCenter:function(t,e,i){if(!i)return t;var n=this.project(t,e),s=this.getSize().divideBy(2),a=new o.Bounds(n.subtract(s),n.add(s)),r=this._getBoundsOffset(a,i,e);return this.unproject(n.add(r),e)},_limitOffset:function(t,e){if(!e)return t;var i=this.getPixelBounds(),n=new o.Bounds(i.min.add(t),i.max.add(t));return t.add(this._getBoundsOffset(n,e))},_getBoundsOffset:function(t,e,i){var n=this.project(e.getNorthWest(),i).subtract(t.min),s=this.project(e.getSouthEast(),i).subtract(t.max),a=this._rebound(n.x,-s.x),r=this._rebound(n.y,-s.y);return new o.Point(a,r)},_rebound:function(t,e){return t+e>0?Math.round(t-e)/2:Math.max(0,Math.ceil(t))-Math.max(0,Math.floor(e))},_limitZoom:function(t){var e=this.getMinZoom(),i=this.getMaxZoom();return Math.max(e,Math.min(i,t))}}),o.map=function(t,e){return new o.Map(t,e)},o.Projection.Mercator={MAX_LATITUDE:85.0840591556,R_MINOR:6356752.314245179,R_MAJOR:6378137,project:function(t){var e=o.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,n=Math.max(Math.min(i,t.lat),-i),s=this.R_MAJOR,a=this.R_MINOR,r=t.lng*e*s,h=n*e,l=a/s,u=Math.sqrt(1-l*l),c=u*Math.sin(h);c=Math.pow((1-c)/(1+c),.5*u);var d=Math.tan(.5*(.5*Math.PI-h))/c;return h=-s*Math.log(d),new o.Point(r,h)},unproject:function(t){for(var e,i=o.LatLng.RAD_TO_DEG,n=this.R_MAJOR,s=this.R_MINOR,a=t.x*i/n,r=s/n,h=Math.sqrt(1-r*r),l=Math.exp(-t.y/n),u=Math.PI/2-2*Math.atan(l),c=15,d=1e-7,p=c,_=.1;Math.abs(_)>d&&--p>0;)e=h*Math.sin(u),_=Math.PI/2-2*Math.atan(l*Math.pow((1-e)/(1+e),.5*h))-u,u+=_;return new o.LatLng(u*i,a)}},o.CRS.EPSG3395=o.extend({},o.CRS,{code:"EPSG:3395",projection:o.Projection.Mercator, -transformation:function(){var t=o.Projection.Mercator,e=t.R_MAJOR,i=.5/(Math.PI*e);return new o.Transformation(i,.5,-i,.5)}()}),o.TileLayer=o.Class.extend({includes:o.Mixin.Events,options:{minZoom:0,maxZoom:18,tileSize:256,subdomains:"abc",errorTileUrl:"",attribution:"",zoomOffset:0,opacity:1,unloadInvisibleTiles:o.Browser.mobile,updateWhenIdle:o.Browser.mobile},initialize:function(t,e){e=o.setOptions(this,e),e.detectRetina&&o.Browser.retina&&e.maxZoom>0&&(e.tileSize=Math.floor(e.tileSize/2),e.zoomOffset++,e.minZoom>0&&e.minZoom--,this.options.maxZoom--),e.bounds&&(e.bounds=o.latLngBounds(e.bounds)),this._url=t;var i=this.options.subdomains;"string"==typeof i&&(this.options.subdomains=i.split(""))},onAdd:function(t){this._map=t,this._animated=t._zoomAnimated,this._initContainer(),t.on({viewreset:this._reset,moveend:this._update},this),this._animated&&t.on({zoomanim:this._animateZoom,zoomend:this._endZoomAnim},this),this.options.updateWhenIdle||(this._limitedUpdate=o.Util.limitExecByInterval(this._update,150,this),t.on("move",this._limitedUpdate,this)),this._reset(),this._update()},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this._container.parentNode.removeChild(this._container),t.off({viewreset:this._reset,moveend:this._update},this),this._animated&&t.off({zoomanim:this._animateZoom,zoomend:this._endZoomAnim},this),this.options.updateWhenIdle||t.off("move",this._limitedUpdate,this),this._container=null,this._map=null},bringToFront:function(){var t=this._map._panes.tilePane;return this._container&&(t.appendChild(this._container),this._setAutoZIndex(t,Math.max)),this},bringToBack:function(){var t=this._map._panes.tilePane;return this._container&&(t.insertBefore(this._container,t.firstChild),this._setAutoZIndex(t,Math.min)),this},getAttribution:function(){return this.options.attribution},getContainer:function(){return this._container},setOpacity:function(t){return this.options.opacity=t,this._map&&this._updateOpacity(),this},setZIndex:function(t){return this.options.zIndex=t,this._updateZIndex(),this},setUrl:function(t,e){return this._url=t,e||this.redraw(),this},redraw:function(){return this._map&&(this._reset({hard:!0}),this._update()),this},_updateZIndex:function(){this._container&&this.options.zIndex!==i&&(this._container.style.zIndex=this.options.zIndex)},_setAutoZIndex:function(t,e){var i,n,o,s=t.children,a=-e(1/0,-(1/0));for(n=0,o=s.length;o>n;n++)s[n]!==this._container&&(i=parseInt(s[n].style.zIndex,10),isNaN(i)||(a=e(a,i)));this.options.zIndex=this._container.style.zIndex=(isFinite(a)?a:0)+e(1,-1)},_updateOpacity:function(){var t,e=this._tiles;if(o.Browser.ielt9)for(t in e)o.DomUtil.setOpacity(e[t],this.options.opacity);else o.DomUtil.setOpacity(this._container,this.options.opacity)},_initContainer:function(){var t=this._map._panes.tilePane;if(!this._container){if(this._container=o.DomUtil.create("div","leaflet-layer"),this._updateZIndex(),this._animated){var e="leaflet-tile-container";this._bgBuffer=o.DomUtil.create("div",e,this._container),this._tileContainer=o.DomUtil.create("div",e,this._container)}else this._tileContainer=this._container;t.appendChild(this._container),this.options.opacity<1&&this._updateOpacity()}},_reset:function(t){for(var e in this._tiles)this.fire("tileunload",{tile:this._tiles[e]});this._tiles={},this._tilesToLoad=0,this.options.reuseTiles&&(this._unusedTiles=[]),this._tileContainer.innerHTML="",this._animated&&t&&t.hard&&this._clearBgBuffer(),this._initContainer()},_getTileSize:function(){var t=this._map,e=t.getZoom()+this.options.zoomOffset,i=this.options.maxNativeZoom,n=this.options.tileSize;return i&&e>i&&(n=Math.round(t.getZoomScale(e)/t.getZoomScale(i)*n)),n},_update:function(){if(this._map){var t=this._map,e=t.getPixelBounds(),i=t.getZoom(),n=this._getTileSize();if(!(i>this.options.maxZoom||i<this.options.minZoom)){var s=o.bounds(e.min.divideBy(n)._floor(),e.max.divideBy(n)._floor());this._addTilesFromCenterOut(s),(this.options.unloadInvisibleTiles||this.options.reuseTiles)&&this._removeOtherTiles(s)}}},_addTilesFromCenterOut:function(t){var i,n,s,a=[],r=t.getCenter();for(i=t.min.y;i<=t.max.y;i++)for(n=t.min.x;n<=t.max.x;n++)s=new o.Point(n,i),this._tileShouldBeLoaded(s)&&a.push(s);var h=a.length;if(0!==h){a.sort(function(t,e){return t.distanceTo(r)-e.distanceTo(r)});var l=e.createDocumentFragment();for(this._tilesToLoad||this.fire("loading"),this._tilesToLoad+=h,n=0;h>n;n++)this._addTile(a[n],l);this._tileContainer.appendChild(l)}},_tileShouldBeLoaded:function(t){if(t.x+":"+t.y in this._tiles)return!1;var e=this.options;if(!e.continuousWorld){var i=this._getWrapTileNum();if(e.noWrap&&(t.x<0||t.x>=i.x)||t.y<0||t.y>=i.y)return!1}if(e.bounds){var n=this._getTileSize(),o=t.multiplyBy(n),s=o.add([n,n]),a=this._map.unproject(o),r=this._map.unproject(s);if(e.continuousWorld||e.noWrap||(a=a.wrap(),r=r.wrap()),!e.bounds.intersects([a,r]))return!1}return!0},_removeOtherTiles:function(t){var e,i,n,o;for(o in this._tiles)e=o.split(":"),i=parseInt(e[0],10),n=parseInt(e[1],10),(i<t.min.x||i>t.max.x||n<t.min.y||n>t.max.y)&&this._removeTile(o)},_removeTile:function(t){var e=this._tiles[t];this.fire("tileunload",{tile:e,url:e.src}),this.options.reuseTiles?(o.DomUtil.removeClass(e,"leaflet-tile-loaded"),this._unusedTiles.push(e)):e.parentNode===this._tileContainer&&this._tileContainer.removeChild(e),o.Browser.android||(e.onload=null,e.src=o.Util.emptyImageUrl),delete this._tiles[t]},_addTile:function(t,e){var i=this._getTilePos(t),n=this._getTile();o.DomUtil.setPosition(n,i,o.Browser.chrome),this._tiles[t.x+":"+t.y]=n,this._loadTile(n,t),n.parentNode!==this._tileContainer&&e.appendChild(n)},_getZoomForUrl:function(){var t=this.options,e=this._map.getZoom();return t.zoomReverse&&(e=t.maxZoom-e),e+=t.zoomOffset,t.maxNativeZoom?Math.min(e,t.maxNativeZoom):e},_getTilePos:function(t){var e=this._map.getPixelOrigin(),i=this._getTileSize();return t.multiplyBy(i).subtract(e)},getTileUrl:function(t){return o.Util.template(this._url,o.extend({s:this._getSubdomain(t),z:t.z,x:t.x,y:t.y},this.options))},_getWrapTileNum:function(){var t=this._map.options.crs,e=t.getSize(this._map.getZoom());return e.divideBy(this._getTileSize())._floor()},_adjustTilePoint:function(t){var e=this._getWrapTileNum();this.options.continuousWorld||this.options.noWrap||(t.x=(t.x%e.x+e.x)%e.x),this.options.tms&&(t.y=e.y-t.y-1),t.z=this._getZoomForUrl()},_getSubdomain:function(t){var e=Math.abs(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[e]},_getTile:function(){if(this.options.reuseTiles&&this._unusedTiles.length>0){var t=this._unusedTiles.pop();return this._resetTile(t),t}return this._createTile()},_resetTile:function(){},_createTile:function(){var t=o.DomUtil.create("img","leaflet-tile");return t.style.width=t.style.height=this._getTileSize()+"px",t.galleryimg="no",t.onselectstart=t.onmousemove=o.Util.falseFn,o.Browser.ielt9&&this.options.opacity!==i&&o.DomUtil.setOpacity(t,this.options.opacity),o.Browser.mobileWebkit3d&&(t.style.WebkitBackfaceVisibility="hidden"),t},_loadTile:function(t,e){t._layer=this,t.onload=this._tileOnLoad,t.onerror=this._tileOnError,this._adjustTilePoint(e),t.src=this.getTileUrl(e),this.fire("tileloadstart",{tile:t,url:t.src})},_tileLoaded:function(){this._tilesToLoad--,this._animated&&o.DomUtil.addClass(this._tileContainer,"leaflet-zoom-animated"),this._tilesToLoad||(this.fire("load"),this._animated&&(clearTimeout(this._clearBgBufferTimer),this._clearBgBufferTimer=setTimeout(o.bind(this._clearBgBuffer,this),500)))},_tileOnLoad:function(){var t=this._layer;this.src!==o.Util.emptyImageUrl&&(o.DomUtil.addClass(this,"leaflet-tile-loaded"),t.fire("tileload",{tile:this,url:this.src})),t._tileLoaded()},_tileOnError:function(){var t=this._layer;t.fire("tileerror",{tile:this,url:this.src});var e=t.options.errorTileUrl;e&&(this.src=e),t._tileLoaded()}}),o.tileLayer=function(t,e){return new o.TileLayer(t,e)},o.TileLayer.WMS=o.TileLayer.extend({defaultWmsParams:{service:"WMS",request:"GetMap",version:"1.1.1",layers:"",styles:"",format:"image/jpeg",transparent:!1},initialize:function(t,e){this._url=t;var i=o.extend({},this.defaultWmsParams),n=e.tileSize||this.options.tileSize;e.detectRetina&&o.Browser.retina?i.width=i.height=2*n:i.width=i.height=n;for(var s in e)this.options.hasOwnProperty(s)||"crs"===s||(i[s]=e[s]);this.wmsParams=i,o.setOptions(this,e)},onAdd:function(t){this._crs=this.options.crs||t.options.crs,this._wmsVersion=parseFloat(this.wmsParams.version);var e=this._wmsVersion>=1.3?"crs":"srs";this.wmsParams[e]=this._crs.code,o.TileLayer.prototype.onAdd.call(this,t)},getTileUrl:function(t){var e=this._map,i=this.options.tileSize,n=t.multiplyBy(i),s=n.add([i,i]),a=this._crs.project(e.unproject(n,t.z)),r=this._crs.project(e.unproject(s,t.z)),h=this._wmsVersion>=1.3&&this._crs===o.CRS.EPSG4326?[r.y,a.x,a.y,r.x].join(","):[a.x,r.y,r.x,a.y].join(","),l=o.Util.template(this._url,{s:this._getSubdomain(t)});return l+o.Util.getParamString(this.wmsParams,l,!0)+"&BBOX="+h},setParams:function(t,e){return o.extend(this.wmsParams,t),e||this.redraw(),this}}),o.tileLayer.wms=function(t,e){return new o.TileLayer.WMS(t,e)},o.TileLayer.Canvas=o.TileLayer.extend({options:{async:!1},initialize:function(t){o.setOptions(this,t)},redraw:function(){this._map&&(this._reset({hard:!0}),this._update());for(var t in this._tiles)this._redrawTile(this._tiles[t]);return this},_redrawTile:function(t){this.drawTile(t,t._tilePoint,this._map._zoom)},_createTile:function(){var t=o.DomUtil.create("canvas","leaflet-tile");return t.width=t.height=this.options.tileSize,t.onselectstart=t.onmousemove=o.Util.falseFn,t},_loadTile:function(t,e){t._layer=this,t._tilePoint=e,this._redrawTile(t),this.options.async||this.tileDrawn(t)},drawTile:function(){},tileDrawn:function(t){this._tileOnLoad.call(t)}}),o.tileLayer.canvas=function(t){return new o.TileLayer.Canvas(t)},o.ImageOverlay=o.Class.extend({includes:o.Mixin.Events,options:{opacity:1},initialize:function(t,e,i){this._url=t,this._bounds=o.latLngBounds(e),o.setOptions(this,i)},onAdd:function(t){this._map=t,this._image||this._initImage(),t._panes.overlayPane.appendChild(this._image),t.on("viewreset",this._reset,this),t.options.zoomAnimation&&o.Browser.any3d&&t.on("zoomanim",this._animateZoom,this),this._reset()},onRemove:function(t){t.getPanes().overlayPane.removeChild(this._image),t.off("viewreset",this._reset,this),t.options.zoomAnimation&&t.off("zoomanim",this._animateZoom,this)},addTo:function(t){return t.addLayer(this),this},setOpacity:function(t){return this.options.opacity=t,this._updateOpacity(),this},bringToFront:function(){return this._image&&this._map._panes.overlayPane.appendChild(this._image),this},bringToBack:function(){var t=this._map._panes.overlayPane;return this._image&&t.insertBefore(this._image,t.firstChild),this},setUrl:function(t){this._url=t,this._image.src=this._url},getAttribution:function(){return this.options.attribution},_initImage:function(){this._image=o.DomUtil.create("img","leaflet-image-layer"),this._map.options.zoomAnimation&&o.Browser.any3d?o.DomUtil.addClass(this._image,"leaflet-zoom-animated"):o.DomUtil.addClass(this._image,"leaflet-zoom-hide"),this._updateOpacity(),o.extend(this._image,{galleryimg:"no",onselectstart:o.Util.falseFn,onmousemove:o.Util.falseFn,onload:o.bind(this._onImageLoad,this),src:this._url})},_animateZoom:function(t){var e=this._map,i=this._image,n=e.getZoomScale(t.zoom),s=this._bounds.getNorthWest(),a=this._bounds.getSouthEast(),r=e._latLngToNewLayerPoint(s,t.zoom,t.center),h=e._latLngToNewLayerPoint(a,t.zoom,t.center)._subtract(r),l=r._add(h._multiplyBy(.5*(1-1/n)));i.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(l)+" scale("+n+") "},_reset:function(){var t=this._image,e=this._map.latLngToLayerPoint(this._bounds.getNorthWest()),i=this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(e);o.DomUtil.setPosition(t,e),t.style.width=i.x+"px",t.style.height=i.y+"px"},_onImageLoad:function(){this.fire("load")},_updateOpacity:function(){o.DomUtil.setOpacity(this._image,this.options.opacity)}}),o.imageOverlay=function(t,e,i){return new o.ImageOverlay(t,e,i)},o.Icon=o.Class.extend({options:{className:""},initialize:function(t){o.setOptions(this,t)},createIcon:function(t){return this._createIcon("icon",t)},createShadow:function(t){return this._createIcon("shadow",t)},_createIcon:function(t,e){var i=this._getIconUrl(t);if(!i){if("icon"===t)throw new Error("iconUrl not set in Icon options (see the docs).");return null}var n;return n=e&&"IMG"===e.tagName?this._createImg(i,e):this._createImg(i),this._setIconStyles(n,t),n},_setIconStyles:function(t,e){var i,n=this.options,s=o.point(n[e+"Size"]);i="shadow"===e?o.point(n.shadowAnchor||n.iconAnchor):o.point(n.iconAnchor),!i&&s&&(i=s.divideBy(2,!0)),t.className="leaflet-marker-"+e+" "+n.className,i&&(t.style.marginLeft=-i.x+"px",t.style.marginTop=-i.y+"px"),s&&(t.style.width=s.x+"px",t.style.height=s.y+"px")},_createImg:function(t,i){return i=i||e.createElement("img"),i.src=t,i},_getIconUrl:function(t){return o.Browser.retina&&this.options[t+"RetinaUrl"]?this.options[t+"RetinaUrl"]:this.options[t+"Url"]}}),o.icon=function(t){return new o.Icon(t)},o.Icon.Default=o.Icon.extend({options:{iconSize:[25,41],iconAnchor:[12,41],popupAnchor:[1,-34],shadowSize:[41,41]},_getIconUrl:function(t){var e=t+"Url";if(this.options[e])return this.options[e];o.Browser.retina&&"icon"===t&&(t+="-2x");var i=o.Icon.Default.imagePath;if(!i)throw new Error("Couldn't autodetect L.Icon.Default.imagePath, set it manually.");return i+"/marker-"+t+".png"}}),o.Icon.Default.imagePath=function(){var t,i,n,o,s,a=e.getElementsByTagName("script"),r=/[\/^]leaflet[\-\._]?([\w\-\._]*)\.js\??/;for(t=0,i=a.length;i>t;t++)if(n=a[t].src,o=n.match(r))return s=n.split(r)[0],(s?s+"/":"")+"images"}(),o.Marker=o.Class.extend({includes:o.Mixin.Events,options:{icon:new o.Icon.Default,title:"",alt:"",clickable:!0,draggable:!1,keyboard:!0,zIndexOffset:0,opacity:1,riseOnHover:!1,riseOffset:250},initialize:function(t,e){o.setOptions(this,e),this._latlng=o.latLng(t)},onAdd:function(t){this._map=t,t.on("viewreset",this.update,this),this._initIcon(),this.update(),this.fire("add"),t.options.zoomAnimation&&t.options.markerZoomAnimation&&t.on("zoomanim",this._animateZoom,this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this.dragging&&this.dragging.disable(),this._removeIcon(),this._removeShadow(),this.fire("remove"),t.off({viewreset:this.update,zoomanim:this._animateZoom},this),this._map=null},getLatLng:function(){return this._latlng},setLatLng:function(t){return this._latlng=o.latLng(t),this.update(),this.fire("move",{latlng:this._latlng})},setZIndexOffset:function(t){return this.options.zIndexOffset=t,this.update(),this},setIcon:function(t){return this.options.icon=t,this._map&&(this._initIcon(),this.update()),this._popup&&this.bindPopup(this._popup),this},update:function(){return this._icon&&this._setPos(this._map.latLngToLayerPoint(this._latlng).round()),this},_initIcon:function(){var t=this.options,e=this._map,i=e.options.zoomAnimation&&e.options.markerZoomAnimation,n=i?"leaflet-zoom-animated":"leaflet-zoom-hide",s=t.icon.createIcon(this._icon),a=!1;s!==this._icon&&(this._icon&&this._removeIcon(),a=!0,t.title&&(s.title=t.title),t.alt&&(s.alt=t.alt)),o.DomUtil.addClass(s,n),t.keyboard&&(s.tabIndex="0"),this._icon=s,this._initInteraction(),t.riseOnHover&&o.DomEvent.on(s,"mouseover",this._bringToFront,this).on(s,"mouseout",this._resetZIndex,this);var r=t.icon.createShadow(this._shadow),h=!1;r!==this._shadow&&(this._removeShadow(),h=!0),r&&o.DomUtil.addClass(r,n),this._shadow=r,t.opacity<1&&this._updateOpacity();var l=this._map._panes;a&&l.markerPane.appendChild(this._icon),r&&h&&l.shadowPane.appendChild(this._shadow)},_removeIcon:function(){this.options.riseOnHover&&o.DomEvent.off(this._icon,"mouseover",this._bringToFront).off(this._icon,"mouseout",this._resetZIndex),this._map._panes.markerPane.removeChild(this._icon),this._icon=null},_removeShadow:function(){this._shadow&&this._map._panes.shadowPane.removeChild(this._shadow),this._shadow=null},_setPos:function(t){o.DomUtil.setPosition(this._icon,t),this._shadow&&o.DomUtil.setPosition(this._shadow,t),this._zIndex=t.y+this.options.zIndexOffset,this._resetZIndex()},_updateZIndex:function(t){this._icon.style.zIndex=this._zIndex+t},_animateZoom:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center).round();this._setPos(e)},_initInteraction:function(){if(this.options.clickable){var t=this._icon,e=["dblclick","mousedown","mouseover","mouseout","contextmenu"];o.DomUtil.addClass(t,"leaflet-clickable"),o.DomEvent.on(t,"click",this._onMouseClick,this),o.DomEvent.on(t,"keypress",this._onKeyPress,this);for(var i=0;i<e.length;i++)o.DomEvent.on(t,e[i],this._fireMouseEvent,this);o.Handler.MarkerDrag&&(this.dragging=new o.Handler.MarkerDrag(this),this.options.draggable&&this.dragging.enable())}},_onMouseClick:function(t){var e=this.dragging&&this.dragging.moved();(this.hasEventListeners(t.type)||e)&&o.DomEvent.stopPropagation(t),e||(this.dragging&&this.dragging._enabled||!this._map.dragging||!this._map.dragging.moved())&&this.fire(t.type,{originalEvent:t,latlng:this._latlng})},_onKeyPress:function(t){13===t.keyCode&&this.fire("click",{originalEvent:t,latlng:this._latlng})},_fireMouseEvent:function(t){this.fire(t.type,{originalEvent:t,latlng:this._latlng}),"contextmenu"===t.type&&this.hasEventListeners(t.type)&&o.DomEvent.preventDefault(t),"mousedown"!==t.type?o.DomEvent.stopPropagation(t):o.DomEvent.preventDefault(t)},setOpacity:function(t){return this.options.opacity=t,this._map&&this._updateOpacity(),this},_updateOpacity:function(){o.DomUtil.setOpacity(this._icon,this.options.opacity),this._shadow&&o.DomUtil.setOpacity(this._shadow,this.options.opacity)},_bringToFront:function(){this._updateZIndex(this.options.riseOffset)},_resetZIndex:function(){this._updateZIndex(0)}}),o.marker=function(t,e){return new o.Marker(t,e)},o.DivIcon=o.Icon.extend({options:{iconSize:[12,12],className:"leaflet-div-icon",html:!1},createIcon:function(t){var i=t&&"DIV"===t.tagName?t:e.createElement("div"),n=this.options;return n.html!==!1?i.innerHTML=n.html:i.innerHTML="",n.bgPos&&(i.style.backgroundPosition=-n.bgPos.x+"px "+-n.bgPos.y+"px"),this._setIconStyles(i,"icon"),i},createShadow:function(){return null}}),o.divIcon=function(t){return new o.DivIcon(t)},o.Map.mergeOptions({closePopupOnClick:!0}),o.Popup=o.Class.extend({includes:o.Mixin.Events,options:{minWidth:50,maxWidth:300,autoPan:!0,closeButton:!0,offset:[0,7],autoPanPadding:[5,5],keepInView:!1,className:"",zoomAnimation:!0},initialize:function(t,e){o.setOptions(this,t),this._source=e,this._animated=o.Browser.any3d&&this.options.zoomAnimation,this._isOpen=!1},onAdd:function(t){this._map=t,this._container||this._initLayout();var e=t.options.fadeAnimation;e&&o.DomUtil.setOpacity(this._container,0),t._panes.popupPane.appendChild(this._container),t.on(this._getEvents(),this),this.update(),e&&o.DomUtil.setOpacity(this._container,1),this.fire("open"),t.fire("popupopen",{popup:this}),this._source&&this._source.fire("popupopen",{popup:this})},addTo:function(t){return t.addLayer(this),this},openOn:function(t){return t.openPopup(this),this},onRemove:function(t){t._panes.popupPane.removeChild(this._container),o.Util.falseFn(this._container.offsetWidth),t.off(this._getEvents(),this),t.options.fadeAnimation&&o.DomUtil.setOpacity(this._container,0),this._map=null,this.fire("close"),t.fire("popupclose",{popup:this}),this._source&&this._source.fire("popupclose",{popup:this})},getLatLng:function(){return this._latlng},setLatLng:function(t){return this._latlng=o.latLng(t),this._map&&(this._updatePosition(),this._adjustPan()),this},getContent:function(){return this._content},setContent:function(t){return this._content=t,this.update(),this},update:function(){this._map&&(this._container.style.visibility="hidden",this._updateContent(),this._updateLayout(),this._updatePosition(),this._container.style.visibility="",this._adjustPan())},_getEvents:function(){var t={viewreset:this._updatePosition};return this._animated&&(t.zoomanim=this._zoomAnimation),("closeOnClick"in this.options?this.options.closeOnClick:this._map.options.closePopupOnClick)&&(t.preclick=this._close),this.options.keepInView&&(t.moveend=this._adjustPan),t},_close:function(){this._map&&this._map.closePopup(this)},_initLayout:function(){var t,e="leaflet-popup",i=e+" "+this.options.className+" leaflet-zoom-"+(this._animated?"animated":"hide"),n=this._container=o.DomUtil.create("div",i);this.options.closeButton&&(t=this._closeButton=o.DomUtil.create("a",e+"-close-button",n),t.href="#close",t.innerHTML="×",o.DomEvent.disableClickPropagation(t),o.DomEvent.on(t,"click",this._onCloseButtonClick,this));var s=this._wrapper=o.DomUtil.create("div",e+"-content-wrapper",n);o.DomEvent.disableClickPropagation(s),this._contentNode=o.DomUtil.create("div",e+"-content",s),o.DomEvent.disableScrollPropagation(this._contentNode),o.DomEvent.on(s,"contextmenu",o.DomEvent.stopPropagation),this._tipContainer=o.DomUtil.create("div",e+"-tip-container",n),this._tip=o.DomUtil.create("div",e+"-tip",this._tipContainer)},_updateContent:function(){if(this._content){if("string"==typeof this._content)this._contentNode.innerHTML=this._content;else{for(;this._contentNode.hasChildNodes();)this._contentNode.removeChild(this._contentNode.firstChild);this._contentNode.appendChild(this._content)}this.fire("contentupdate")}},_updateLayout:function(){var t=this._contentNode,e=t.style;e.width="",e.whiteSpace="nowrap";var i=t.offsetWidth;i=Math.min(i,this.options.maxWidth),i=Math.max(i,this.options.minWidth),e.width=i+1+"px",e.whiteSpace="",e.height="";var n=t.offsetHeight,s=this.options.maxHeight,a="leaflet-popup-scrolled";s&&n>s?(e.height=s+"px",o.DomUtil.addClass(t,a)):o.DomUtil.removeClass(t,a),this._containerWidth=this._container.offsetWidth},_updatePosition:function(){if(this._map){var t=this._map.latLngToLayerPoint(this._latlng),e=this._animated,i=o.point(this.options.offset);e&&o.DomUtil.setPosition(this._container,t),this._containerBottom=-i.y-(e?0:t.y),this._containerLeft=-Math.round(this._containerWidth/2)+i.x+(e?0:t.x),this._container.style.bottom=this._containerBottom+"px",this._container.style.left=this._containerLeft+"px"}},_zoomAnimation:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center);o.DomUtil.setPosition(this._container,e)},_adjustPan:function(){if(this.options.autoPan){var t=this._map,e=this._container.offsetHeight,i=this._containerWidth,n=new o.Point(this._containerLeft,-e-this._containerBottom);this._animated&&n._add(o.DomUtil.getPosition(this._container));var s=t.layerPointToContainerPoint(n),a=o.point(this.options.autoPanPadding),r=o.point(this.options.autoPanPaddingTopLeft||a),h=o.point(this.options.autoPanPaddingBottomRight||a),l=t.getSize(),u=0,c=0;s.x+i+h.x>l.x&&(u=s.x+i-l.x+h.x),s.x-u-r.x<0&&(u=s.x-r.x),s.y+e+h.y>l.y&&(c=s.y+e-l.y+h.y),s.y-c-r.y<0&&(c=s.y-r.y),(u||c)&&t.fire("autopanstart").panBy([u,c])}},_onCloseButtonClick:function(t){this._close(),o.DomEvent.stop(t)}}),o.popup=function(t,e){return new o.Popup(t,e)},o.Map.include({openPopup:function(t,e,i){if(this.closePopup(),!(t instanceof o.Popup)){var n=t;t=new o.Popup(i).setLatLng(e).setContent(n)}return t._isOpen=!0,this._popup=t,this.addLayer(t)},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&(this.removeLayer(t),t._isOpen=!1),this}}),o.Marker.include({openPopup:function(){return this._popup&&this._map&&!this._map.hasLayer(this._popup)&&(this._popup.setLatLng(this._latlng),this._map.openPopup(this._popup)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(){return this._popup&&(this._popup._isOpen?this.closePopup():this.openPopup()),this},bindPopup:function(t,e){var i=o.point(this.options.icon.options.popupAnchor||[0,0]);return i=i.add(o.Popup.prototype.options.offset),e&&e.offset&&(i=i.add(e.offset)),e=o.extend({offset:i},e),this._popupHandlersAdded||(this.on("click",this.togglePopup,this).on("remove",this.closePopup,this).on("move",this._movePopup,this),this._popupHandlersAdded=!0),t instanceof o.Popup?(o.setOptions(t,e),this._popup=t,t._source=this):this._popup=new o.Popup(e,this).setContent(t),this},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this.togglePopup,this).off("remove",this.closePopup,this).off("move",this._movePopup,this),this._popupHandlersAdded=!1),this},getPopup:function(){return this._popup},_movePopup:function(t){this._popup.setLatLng(t.latlng)}}),o.LayerGroup=o.Class.extend({initialize:function(t){this._layers={};var e,i;if(t)for(e=0,i=t.length;i>e;e++)this.addLayer(t[e])},addLayer:function(t){var e=this.getLayerId(t);return this._layers[e]=t,this._map&&this._map.addLayer(t),this},removeLayer:function(t){var e=t in this._layers?t:this.getLayerId(t);return this._map&&this._layers[e]&&this._map.removeLayer(this._layers[e]),delete this._layers[e],this},hasLayer:function(t){return t?t in this._layers||this.getLayerId(t)in this._layers:!1},clearLayers:function(){return this.eachLayer(this.removeLayer,this),this},invoke:function(t){var e,i,n=Array.prototype.slice.call(arguments,1);for(e in this._layers)i=this._layers[e],i[t]&&i[t].apply(i,n);return this},onAdd:function(t){this._map=t,this.eachLayer(t.addLayer,t)},onRemove:function(t){this.eachLayer(t.removeLayer,t),this._map=null},addTo:function(t){return t.addLayer(this),this},eachLayer:function(t,e){for(var i in this._layers)t.call(e,this._layers[i]);return this},getLayer:function(t){return this._layers[t]},getLayers:function(){var t=[];for(var e in this._layers)t.push(this._layers[e]);return t},setZIndex:function(t){return this.invoke("setZIndex",t)},getLayerId:function(t){return o.stamp(t)}}),o.layerGroup=function(t){return new o.LayerGroup(t)},o.FeatureGroup=o.LayerGroup.extend({includes:o.Mixin.Events,statics:{EVENTS:"click dblclick mouseover mouseout mousemove contextmenu popupopen popupclose"},addLayer:function(t){return this.hasLayer(t)?this:("on"in t&&t.on(o.FeatureGroup.EVENTS,this._propagateEvent,this),o.LayerGroup.prototype.addLayer.call(this,t),this._popupContent&&t.bindPopup&&t.bindPopup(this._popupContent,this._popupOptions),this.fire("layeradd",{layer:t}))},removeLayer:function(t){return this.hasLayer(t)?(t in this._layers&&(t=this._layers[t]),"off"in t&&t.off(o.FeatureGroup.EVENTS,this._propagateEvent,this),o.LayerGroup.prototype.removeLayer.call(this,t),this._popupContent&&this.invoke("unbindPopup"),this.fire("layerremove",{layer:t})):this},bindPopup:function(t,e){return this._popupContent=t,this._popupOptions=e,this.invoke("bindPopup",t,e)},openPopup:function(t){for(var e in this._layers){this._layers[e].openPopup(t);break}return this},setStyle:function(t){return this.invoke("setStyle",t)},bringToFront:function(){return this.invoke("bringToFront")},bringToBack:function(){return this.invoke("bringToBack")},getBounds:function(){var t=new o.LatLngBounds;return this.eachLayer(function(e){t.extend(e instanceof o.Marker?e.getLatLng():e.getBounds())}),t},_propagateEvent:function(t){t=o.extend({layer:t.target,target:this},t),this.fire(t.type,t)}}),o.featureGroup=function(t){return new o.FeatureGroup(t)},o.Path=o.Class.extend({includes:[o.Mixin.Events],statics:{CLIP_PADDING:function(){var e=o.Browser.mobile?1280:2e3,i=(e/Math.max(t.outerWidth,t.outerHeight)-1)/2;return Math.max(0,Math.min(.5,i))}()},options:{stroke:!0,color:"#0033ff",dashArray:null,lineCap:null,lineJoin:null,weight:5,opacity:.5,fill:!1,fillColor:null,fillOpacity:.2,clickable:!0},initialize:function(t){o.setOptions(this,t)},onAdd:function(t){this._map=t,this._container||(this._initElements(),this._initEvents()),this.projectLatlngs(),this._updatePath(),this._container&&this._map._pathRoot.appendChild(this._container),this.fire("add"),t.on({viewreset:this.projectLatlngs,moveend:this._updatePath},this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){t._pathRoot.removeChild(this._container),this.fire("remove"),this._map=null,o.Browser.vml&&(this._container=null,this._stroke=null,this._fill=null),t.off({viewreset:this.projectLatlngs,moveend:this._updatePath},this)},projectLatlngs:function(){},setStyle:function(t){return o.setOptions(this,t),this._container&&this._updateStyle(),this},redraw:function(){return this._map&&(this.projectLatlngs(),this._updatePath()),this}}),o.Map.include({_updatePathViewport:function(){var t=o.Path.CLIP_PADDING,e=this.getSize(),i=o.DomUtil.getPosition(this._mapPane),n=i.multiplyBy(-1)._subtract(e.multiplyBy(t)._round()),s=n.add(e.multiplyBy(1+2*t)._round());this._pathViewport=new o.Bounds(n,s)}}),o.Path.SVG_NS="http://www.w3.org/2000/svg",o.Browser.svg=!(!e.createElementNS||!e.createElementNS(o.Path.SVG_NS,"svg").createSVGRect),o.Path=o.Path.extend({statics:{SVG:o.Browser.svg},bringToFront:function(){var t=this._map._pathRoot,e=this._container;return e&&t.lastChild!==e&&t.appendChild(e),this},bringToBack:function(){var t=this._map._pathRoot,e=this._container,i=t.firstChild;return e&&i!==e&&t.insertBefore(e,i),this},getPathString:function(){},_createElement:function(t){return e.createElementNS(o.Path.SVG_NS,t)},_initElements:function(){this._map._initPathRoot(),this._initPath(),this._initStyle()},_initPath:function(){this._container=this._createElement("g"),this._path=this._createElement("path"),this.options.className&&o.DomUtil.addClass(this._path,this.options.className),this._container.appendChild(this._path)},_initStyle:function(){this.options.stroke&&(this._path.setAttribute("stroke-linejoin","round"),this._path.setAttribute("stroke-linecap","round")),this.options.fill&&this._path.setAttribute("fill-rule","evenodd"),this.options.pointerEvents&&this._path.setAttribute("pointer-events",this.options.pointerEvents),this.options.clickable||this.options.pointerEvents||this._path.setAttribute("pointer-events","none"),this._updateStyle()},_updateStyle:function(){this.options.stroke?(this._path.setAttribute("stroke",this.options.color),this._path.setAttribute("stroke-opacity",this.options.opacity),this._path.setAttribute("stroke-width",this.options.weight),this.options.dashArray?this._path.setAttribute("stroke-dasharray",this.options.dashArray):this._path.removeAttribute("stroke-dasharray"),this.options.lineCap&&this._path.setAttribute("stroke-linecap",this.options.lineCap),this.options.lineJoin&&this._path.setAttribute("stroke-linejoin",this.options.lineJoin)):this._path.setAttribute("stroke","none"),this.options.fill?(this._path.setAttribute("fill",this.options.fillColor||this.options.color),this._path.setAttribute("fill-opacity",this.options.fillOpacity)):this._path.setAttribute("fill","none")},_updatePath:function(){var t=this.getPathString();t||(t="M0 0"),this._path.setAttribute("d",t)},_initEvents:function(){if(this.options.clickable){(o.Browser.svg||!o.Browser.vml)&&o.DomUtil.addClass(this._path,"leaflet-clickable"),o.DomEvent.on(this._container,"click",this._onMouseClick,this);for(var t=["dblclick","mousedown","mouseover","mouseout","mousemove","contextmenu"],e=0;e<t.length;e++)o.DomEvent.on(this._container,t[e],this._fireMouseEvent,this)}},_onMouseClick:function(t){this._map.dragging&&this._map.dragging.moved()||this._fireMouseEvent(t)},_fireMouseEvent:function(t){if(this._map&&this.hasEventListeners(t.type)){var e=this._map,i=e.mouseEventToContainerPoint(t),n=e.containerPointToLayerPoint(i),s=e.layerPointToLatLng(n);this.fire(t.type,{latlng:s,layerPoint:n,containerPoint:i,originalEvent:t}),"contextmenu"===t.type&&o.DomEvent.preventDefault(t),"mousemove"!==t.type&&o.DomEvent.stopPropagation(t)}}}),o.Map.include({_initPathRoot:function(){this._pathRoot||(this._pathRoot=o.Path.prototype._createElement("svg"),this._panes.overlayPane.appendChild(this._pathRoot),this.options.zoomAnimation&&o.Browser.any3d?(o.DomUtil.addClass(this._pathRoot,"leaflet-zoom-animated"), -this.on({zoomanim:this._animatePathZoom,zoomend:this._endPathZoom})):o.DomUtil.addClass(this._pathRoot,"leaflet-zoom-hide"),this.on("moveend",this._updateSvgViewport),this._updateSvgViewport())},_animatePathZoom:function(t){var e=this.getZoomScale(t.zoom),i=this._getCenterOffset(t.center)._multiplyBy(-e)._add(this._pathViewport.min);this._pathRoot.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(i)+" scale("+e+") ",this._pathZooming=!0},_endPathZoom:function(){this._pathZooming=!1},_updateSvgViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max,n=i.x-e.x,s=i.y-e.y,a=this._pathRoot,r=this._panes.overlayPane;o.Browser.mobileWebkit&&r.removeChild(a),o.DomUtil.setPosition(a,e),a.setAttribute("width",n),a.setAttribute("height",s),a.setAttribute("viewBox",[e.x,e.y,n,s].join(" ")),o.Browser.mobileWebkit&&r.appendChild(a)}}}),o.Path.include({bindPopup:function(t,e){return t instanceof o.Popup?this._popup=t:((!this._popup||e)&&(this._popup=new o.Popup(e,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on("click",this._openPopup,this).on("remove",this.closePopup,this),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this._openPopup).off("remove",this.closePopup),this._popupHandlersAdded=!1),this},openPopup:function(t){return this._popup&&(t=t||this._latlng||this._latlngs[Math.floor(this._latlngs.length/2)],this._openPopup({latlng:t})),this},closePopup:function(){return this._popup&&this._popup._close(),this},_openPopup:function(t){this._popup.setLatLng(t.latlng),this._map.openPopup(this._popup)}}),o.Browser.vml=!o.Browser.svg&&function(){try{var t=e.createElement("div");t.innerHTML='<v:shape adj="1"/>';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(n){return!1}}(),o.Path=o.Browser.svg||!o.Browser.vml?o.Path:o.Path.extend({statics:{VML:!0,CLIP_PADDING:.02},_createElement:function(){try{return e.namespaces.add("lvml","urn:schemas-microsoft-com:vml"),function(t){return e.createElement("<lvml:"+t+' class="lvml">')}}catch(t){return function(t){return e.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),_initPath:function(){var t=this._container=this._createElement("shape");o.DomUtil.addClass(t,"leaflet-vml-shape"+(this.options.className?" "+this.options.className:"")),this.options.clickable&&o.DomUtil.addClass(t,"leaflet-clickable"),t.coordsize="1 1",this._path=this._createElement("path"),t.appendChild(this._path),this._map._pathRoot.appendChild(t)},_initStyle:function(){this._updateStyle()},_updateStyle:function(){var t=this._stroke,e=this._fill,i=this.options,n=this._container;n.stroked=i.stroke,n.filled=i.fill,i.stroke?(t||(t=this._stroke=this._createElement("stroke"),t.endcap="round",n.appendChild(t)),t.weight=i.weight+"px",t.color=i.color,t.opacity=i.opacity,i.dashArray?t.dashStyle=o.Util.isArray(i.dashArray)?i.dashArray.join(" "):i.dashArray.replace(/( *, *)/g," "):t.dashStyle="",i.lineCap&&(t.endcap=i.lineCap.replace("butt","flat")),i.lineJoin&&(t.joinstyle=i.lineJoin)):t&&(n.removeChild(t),this._stroke=null),i.fill?(e||(e=this._fill=this._createElement("fill"),n.appendChild(e)),e.color=i.fillColor||i.color,e.opacity=i.fillOpacity):e&&(n.removeChild(e),this._fill=null)},_updatePath:function(){var t=this._container.style;t.display="none",this._path.v=this.getPathString()+" ",t.display=""}}),o.Map.include(o.Browser.svg||!o.Browser.vml?{}:{_initPathRoot:function(){if(!this._pathRoot){var t=this._pathRoot=e.createElement("div");t.className="leaflet-vml-container",this._panes.overlayPane.appendChild(t),this.on("moveend",this._updatePathViewport),this._updatePathViewport()}}}),o.Browser.canvas=function(){return!!e.createElement("canvas").getContext}(),o.Path=o.Path.SVG&&!t.L_PREFER_CANVAS||!o.Browser.canvas?o.Path:o.Path.extend({statics:{CANVAS:!0,SVG:!1},redraw:function(){return this._map&&(this.projectLatlngs(),this._requestUpdate()),this},setStyle:function(t){return o.setOptions(this,t),this._map&&(this._updateStyle(),this._requestUpdate()),this},onRemove:function(t){t.off("viewreset",this.projectLatlngs,this).off("moveend",this._updatePath,this),this.options.clickable&&(this._map.off("click",this._onClick,this),this._map.off("mousemove",this._onMouseMove,this)),this._requestUpdate(),this.fire("remove"),this._map=null},_requestUpdate:function(){this._map&&!o.Path._updateRequest&&(o.Path._updateRequest=o.Util.requestAnimFrame(this._fireMapMoveEnd,this._map))},_fireMapMoveEnd:function(){o.Path._updateRequest=null,this.fire("moveend")},_initElements:function(){this._map._initPathRoot(),this._ctx=this._map._canvasCtx},_updateStyle:function(){var t=this.options;t.stroke&&(this._ctx.lineWidth=t.weight,this._ctx.strokeStyle=t.color),t.fill&&(this._ctx.fillStyle=t.fillColor||t.color),t.lineCap&&(this._ctx.lineCap=t.lineCap),t.lineJoin&&(this._ctx.lineJoin=t.lineJoin)},_drawPath:function(){var t,e,i,n,s,a;for(this._ctx.beginPath(),t=0,i=this._parts.length;i>t;t++){for(e=0,n=this._parts[t].length;n>e;e++)s=this._parts[t][e],a=(0===e?"move":"line")+"To",this._ctx[a](s.x,s.y);this instanceof o.Polygon&&this._ctx.closePath()}},_checkIfEmpty:function(){return!this._parts.length},_updatePath:function(){if(!this._checkIfEmpty()){var t=this._ctx,e=this.options;this._drawPath(),t.save(),this._updateStyle(),e.fill&&(t.globalAlpha=e.fillOpacity,t.fill(e.fillRule||"evenodd")),e.stroke&&(t.globalAlpha=e.opacity,t.stroke()),t.restore()}},_initEvents:function(){this.options.clickable&&(this._map.on("mousemove",this._onMouseMove,this),this._map.on("click dblclick contextmenu",this._fireMouseEvent,this))},_fireMouseEvent:function(t){this._containsPoint(t.layerPoint)&&this.fire(t.type,t)},_onMouseMove:function(t){this._map&&!this._map._animatingZoom&&(this._containsPoint(t.layerPoint)?(this._ctx.canvas.style.cursor="pointer",this._mouseInside=!0,this.fire("mouseover",t)):this._mouseInside&&(this._ctx.canvas.style.cursor="",this._mouseInside=!1,this.fire("mouseout",t)))}}),o.Map.include(o.Path.SVG&&!t.L_PREFER_CANVAS||!o.Browser.canvas?{}:{_initPathRoot:function(){var t,i=this._pathRoot;i||(i=this._pathRoot=e.createElement("canvas"),i.style.position="absolute",t=this._canvasCtx=i.getContext("2d"),t.lineCap="round",t.lineJoin="round",this._panes.overlayPane.appendChild(i),this.options.zoomAnimation&&(this._pathRoot.className="leaflet-zoom-animated",this.on("zoomanim",this._animatePathZoom),this.on("zoomend",this._endPathZoom)),this.on("moveend",this._updateCanvasViewport),this._updateCanvasViewport())},_updateCanvasViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max.subtract(e),n=this._pathRoot;o.DomUtil.setPosition(n,e),n.width=i.x,n.height=i.y,n.getContext("2d").translate(-e.x,-e.y)}}}),o.LineUtil={simplify:function(t,e){if(!e||!t.length)return t.slice();var i=e*e;return t=this._reducePoints(t,i),t=this._simplifyDP(t,i)},pointToSegmentDistance:function(t,e,i){return Math.sqrt(this._sqClosestPointOnSegment(t,e,i,!0))},closestPointOnSegment:function(t,e,i){return this._sqClosestPointOnSegment(t,e,i)},_simplifyDP:function(t,e){var n=t.length,o=typeof Uint8Array!=i+""?Uint8Array:Array,s=new o(n);s[0]=s[n-1]=1,this._simplifyDPStep(t,s,e,0,n-1);var a,r=[];for(a=0;n>a;a++)s[a]&&r.push(t[a]);return r},_simplifyDPStep:function(t,e,i,n,o){var s,a,r,h=0;for(a=n+1;o-1>=a;a++)r=this._sqClosestPointOnSegment(t[a],t[n],t[o],!0),r>h&&(s=a,h=r);h>i&&(e[s]=1,this._simplifyDPStep(t,e,i,n,s),this._simplifyDPStep(t,e,i,s,o))},_reducePoints:function(t,e){for(var i=[t[0]],n=1,o=0,s=t.length;s>n;n++)this._sqDist(t[n],t[o])>e&&(i.push(t[n]),o=n);return s-1>o&&i.push(t[s-1]),i},clipSegment:function(t,e,i,n){var o,s,a,r=n?this._lastCode:this._getBitCode(t,i),h=this._getBitCode(e,i);for(this._lastCode=h;;){if(!(r|h))return[t,e];if(r&h)return!1;o=r||h,s=this._getEdgeIntersection(t,e,o,i),a=this._getBitCode(s,i),o===r?(t=s,r=a):(e=s,h=a)}},_getEdgeIntersection:function(t,e,i,n){var s=e.x-t.x,a=e.y-t.y,r=n.min,h=n.max;return 8&i?new o.Point(t.x+s*(h.y-t.y)/a,h.y):4&i?new o.Point(t.x+s*(r.y-t.y)/a,r.y):2&i?new o.Point(h.x,t.y+a*(h.x-t.x)/s):1&i?new o.Point(r.x,t.y+a*(r.x-t.x)/s):void 0},_getBitCode:function(t,e){var i=0;return t.x<e.min.x?i|=1:t.x>e.max.x&&(i|=2),t.y<e.min.y?i|=4:t.y>e.max.y&&(i|=8),i},_sqDist:function(t,e){var i=e.x-t.x,n=e.y-t.y;return i*i+n*n},_sqClosestPointOnSegment:function(t,e,i,n){var s,a=e.x,r=e.y,h=i.x-a,l=i.y-r,u=h*h+l*l;return u>0&&(s=((t.x-a)*h+(t.y-r)*l)/u,s>1?(a=i.x,r=i.y):s>0&&(a+=h*s,r+=l*s)),h=t.x-a,l=t.y-r,n?h*h+l*l:new o.Point(a,r)}},o.Polyline=o.Path.extend({initialize:function(t,e){o.Path.prototype.initialize.call(this,e),this._latlngs=this._convertLatLngs(t)},options:{smoothFactor:1,noClip:!1},projectLatlngs:function(){this._originalPoints=[];for(var t=0,e=this._latlngs.length;e>t;t++)this._originalPoints[t]=this._map.latLngToLayerPoint(this._latlngs[t])},getPathString:function(){for(var t=0,e=this._parts.length,i="";e>t;t++)i+=this._getPathPartStr(this._parts[t]);return i},getLatLngs:function(){return this._latlngs},setLatLngs:function(t){return this._latlngs=this._convertLatLngs(t),this.redraw()},addLatLng:function(t){return this._latlngs.push(o.latLng(t)),this.redraw()},spliceLatLngs:function(){var t=[].splice.apply(this._latlngs,arguments);return this._convertLatLngs(this._latlngs,!0),this.redraw(),t},closestLayerPoint:function(t){for(var e,i,n=1/0,s=this._parts,a=null,r=0,h=s.length;h>r;r++)for(var l=s[r],u=1,c=l.length;c>u;u++){e=l[u-1],i=l[u];var d=o.LineUtil._sqClosestPointOnSegment(t,e,i,!0);n>d&&(n=d,a=o.LineUtil._sqClosestPointOnSegment(t,e,i))}return a&&(a.distance=Math.sqrt(n)),a},getBounds:function(){return new o.LatLngBounds(this.getLatLngs())},_convertLatLngs:function(t,e){var i,n,s=e?t:[];for(i=0,n=t.length;n>i;i++){if(o.Util.isArray(t[i])&&"number"!=typeof t[i][0])return;s[i]=o.latLng(t[i])}return s},_initEvents:function(){o.Path.prototype._initEvents.call(this)},_getPathPartStr:function(t){for(var e,i=o.Path.VML,n=0,s=t.length,a="";s>n;n++)e=t[n],i&&e._round(),a+=(n?"L":"M")+e.x+" "+e.y;return a},_clipPoints:function(){var t,e,i,n=this._originalPoints,s=n.length;if(this.options.noClip)return void(this._parts=[n]);this._parts=[];var a=this._parts,r=this._map._pathViewport,h=o.LineUtil;for(t=0,e=0;s-1>t;t++)i=h.clipSegment(n[t],n[t+1],r,t),i&&(a[e]=a[e]||[],a[e].push(i[0]),(i[1]!==n[t+1]||t===s-2)&&(a[e].push(i[1]),e++))},_simplifyPoints:function(){for(var t=this._parts,e=o.LineUtil,i=0,n=t.length;n>i;i++)t[i]=e.simplify(t[i],this.options.smoothFactor)},_updatePath:function(){this._map&&(this._clipPoints(),this._simplifyPoints(),o.Path.prototype._updatePath.call(this))}}),o.polyline=function(t,e){return new o.Polyline(t,e)},o.PolyUtil={},o.PolyUtil.clipPolygon=function(t,e){var i,n,s,a,r,h,l,u,c,d=[1,4,2,8],p=o.LineUtil;for(n=0,l=t.length;l>n;n++)t[n]._code=p._getBitCode(t[n],e);for(a=0;4>a;a++){for(u=d[a],i=[],n=0,l=t.length,s=l-1;l>n;s=n++)r=t[n],h=t[s],r._code&u?h._code&u||(c=p._getEdgeIntersection(h,r,u,e),c._code=p._getBitCode(c,e),i.push(c)):(h._code&u&&(c=p._getEdgeIntersection(h,r,u,e),c._code=p._getBitCode(c,e),i.push(c)),i.push(r));t=i}return t},o.Polygon=o.Polyline.extend({options:{fill:!0},initialize:function(t,e){o.Polyline.prototype.initialize.call(this,t,e),this._initWithHoles(t)},_initWithHoles:function(t){var e,i,n;if(t&&o.Util.isArray(t[0])&&"number"!=typeof t[0][0])for(this._latlngs=this._convertLatLngs(t[0]),this._holes=t.slice(1),e=0,i=this._holes.length;i>e;e++)n=this._holes[e]=this._convertLatLngs(this._holes[e]),n[0].equals(n[n.length-1])&&n.pop();t=this._latlngs,t.length>=2&&t[0].equals(t[t.length-1])&&t.pop()},projectLatlngs:function(){if(o.Polyline.prototype.projectLatlngs.call(this),this._holePoints=[],this._holes){var t,e,i,n;for(t=0,i=this._holes.length;i>t;t++)for(this._holePoints[t]=[],e=0,n=this._holes[t].length;n>e;e++)this._holePoints[t][e]=this._map.latLngToLayerPoint(this._holes[t][e])}},setLatLngs:function(t){return t&&o.Util.isArray(t[0])&&"number"!=typeof t[0][0]?(this._initWithHoles(t),this.redraw()):o.Polyline.prototype.setLatLngs.call(this,t)},_clipPoints:function(){var t=this._originalPoints,e=[];if(this._parts=[t].concat(this._holePoints),!this.options.noClip){for(var i=0,n=this._parts.length;n>i;i++){var s=o.PolyUtil.clipPolygon(this._parts[i],this._map._pathViewport);s.length&&e.push(s)}this._parts=e}},_getPathPartStr:function(t){var e=o.Polyline.prototype._getPathPartStr.call(this,t);return e+(o.Browser.svg?"z":"x")}}),o.polygon=function(t,e){return new o.Polygon(t,e)},function(){function t(t){return o.FeatureGroup.extend({initialize:function(t,e){this._layers={},this._options=e,this.setLatLngs(t)},setLatLngs:function(e){var i=0,n=e.length;for(this.eachLayer(function(t){n>i?t.setLatLngs(e[i++]):this.removeLayer(t)},this);n>i;)this.addLayer(new t(e[i++],this._options));return this},getLatLngs:function(){var t=[];return this.eachLayer(function(e){t.push(e.getLatLngs())}),t}})}o.MultiPolyline=t(o.Polyline),o.MultiPolygon=t(o.Polygon),o.multiPolyline=function(t,e){return new o.MultiPolyline(t,e)},o.multiPolygon=function(t,e){return new o.MultiPolygon(t,e)}}(),o.Rectangle=o.Polygon.extend({initialize:function(t,e){o.Polygon.prototype.initialize.call(this,this._boundsToLatLngs(t),e)},setBounds:function(t){this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=o.latLngBounds(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}}),o.rectangle=function(t,e){return new o.Rectangle(t,e)},o.Circle=o.Path.extend({initialize:function(t,e,i){o.Path.prototype.initialize.call(this,i),this._latlng=o.latLng(t),this._mRadius=e},options:{fill:!0},setLatLng:function(t){return this._latlng=o.latLng(t),this.redraw()},setRadius:function(t){return this._mRadius=t,this.redraw()},projectLatlngs:function(){var t=this._getLngRadius(),e=this._latlng,i=this._map.latLngToLayerPoint([e.lat,e.lng-t]);this._point=this._map.latLngToLayerPoint(e),this._radius=Math.max(this._point.x-i.x,1)},getBounds:function(){var t=this._getLngRadius(),e=this._mRadius/40075017*360,i=this._latlng;return new o.LatLngBounds([i.lat-e,i.lng-t],[i.lat+e,i.lng+t])},getLatLng:function(){return this._latlng},getPathString:function(){var t=this._point,e=this._radius;return this._checkIfEmpty()?"":o.Browser.svg?"M"+t.x+","+(t.y-e)+"A"+e+","+e+",0,1,1,"+(t.x-.1)+","+(t.y-e)+" z":(t._round(),e=Math.round(e),"AL "+t.x+","+t.y+" "+e+","+e+" 0,23592600")},getRadius:function(){return this._mRadius},_getLatRadius:function(){return this._mRadius/40075017*360},_getLngRadius:function(){return this._getLatRadius()/Math.cos(o.LatLng.DEG_TO_RAD*this._latlng.lat)},_checkIfEmpty:function(){if(!this._map)return!1;var t=this._map._pathViewport,e=this._radius,i=this._point;return i.x-e>t.max.x||i.y-e>t.max.y||i.x+e<t.min.x||i.y+e<t.min.y}}),o.circle=function(t,e,i){return new o.Circle(t,e,i)},o.CircleMarker=o.Circle.extend({options:{radius:10,weight:2},initialize:function(t,e){o.Circle.prototype.initialize.call(this,t,null,e),this._radius=this.options.radius},projectLatlngs:function(){this._point=this._map.latLngToLayerPoint(this._latlng)},_updateStyle:function(){o.Circle.prototype._updateStyle.call(this),this.setRadius(this.options.radius)},setLatLng:function(t){return o.Circle.prototype.setLatLng.call(this,t),this._popup&&this._popup._isOpen&&this._popup.setLatLng(t),this},setRadius:function(t){return this.options.radius=this._radius=t,this.redraw()},getRadius:function(){return this._radius}}),o.circleMarker=function(t,e){return new o.CircleMarker(t,e)},o.Polyline.include(o.Path.CANVAS?{_containsPoint:function(t,e){var i,n,s,a,r,h,l,u=this.options.weight/2;for(o.Browser.touch&&(u+=10),i=0,a=this._parts.length;a>i;i++)for(l=this._parts[i],n=0,r=l.length,s=r-1;r>n;s=n++)if((e||0!==n)&&(h=o.LineUtil.pointToSegmentDistance(t,l[s],l[n]),u>=h))return!0;return!1}}:{}),o.Polygon.include(o.Path.CANVAS?{_containsPoint:function(t){var e,i,n,s,a,r,h,l,u=!1;if(o.Polyline.prototype._containsPoint.call(this,t,!0))return!0;for(s=0,h=this._parts.length;h>s;s++)for(e=this._parts[s],a=0,l=e.length,r=l-1;l>a;r=a++)i=e[a],n=e[r],i.y>t.y!=n.y>t.y&&t.x<(n.x-i.x)*(t.y-i.y)/(n.y-i.y)+i.x&&(u=!u);return u}}:{}),o.Circle.include(o.Path.CANVAS?{_drawPath:function(){var t=this._point;this._ctx.beginPath(),this._ctx.arc(t.x,t.y,this._radius,0,2*Math.PI,!1)},_containsPoint:function(t){var e=this._point,i=this.options.stroke?this.options.weight/2:0;return t.distanceTo(e)<=this._radius+i}}:{}),o.CircleMarker.include(o.Path.CANVAS?{_updateStyle:function(){o.Path.prototype._updateStyle.call(this)}}:{}),o.GeoJSON=o.FeatureGroup.extend({initialize:function(t,e){o.setOptions(this,e),this._layers={},t&&this.addData(t)},addData:function(t){var e,i,n,s=o.Util.isArray(t)?t:t.features;if(s){for(e=0,i=s.length;i>e;e++)n=s[e],(n.geometries||n.geometry||n.features||n.coordinates)&&this.addData(s[e]);return this}var a=this.options;if(!a.filter||a.filter(t)){var r=o.GeoJSON.geometryToLayer(t,a.pointToLayer,a.coordsToLatLng,a);return r.feature=o.GeoJSON.asFeature(t),r.defaultOptions=r.options,this.resetStyle(r),a.onEachFeature&&a.onEachFeature(t,r),this.addLayer(r)}},resetStyle:function(t){var e=this.options.style;e&&(o.Util.extend(t.options,t.defaultOptions),this._setLayerStyle(t,e))},setStyle:function(t){this.eachLayer(function(e){this._setLayerStyle(e,t)},this)},_setLayerStyle:function(t,e){"function"==typeof e&&(e=e(t.feature)),t.setStyle&&t.setStyle(e)}}),o.extend(o.GeoJSON,{geometryToLayer:function(t,e,i,n){var s,a,r,h,l="Feature"===t.type?t.geometry:t,u=l.coordinates,c=[];switch(i=i||this.coordsToLatLng,l.type){case"Point":return s=i(u),e?e(t,s):new o.Marker(s);case"MultiPoint":for(r=0,h=u.length;h>r;r++)s=i(u[r]),c.push(e?e(t,s):new o.Marker(s));return new o.FeatureGroup(c);case"LineString":return a=this.coordsToLatLngs(u,0,i),new o.Polyline(a,n);case"Polygon":if(2===u.length&&!u[1].length)throw new Error("Invalid GeoJSON object.");return a=this.coordsToLatLngs(u,1,i),new o.Polygon(a,n);case"MultiLineString":return a=this.coordsToLatLngs(u,1,i),new o.MultiPolyline(a,n);case"MultiPolygon":return a=this.coordsToLatLngs(u,2,i),new o.MultiPolygon(a,n);case"GeometryCollection":for(r=0,h=l.geometries.length;h>r;r++)c.push(this.geometryToLayer({geometry:l.geometries[r],type:"Feature",properties:t.properties},e,i,n));return new o.FeatureGroup(c);default:throw new Error("Invalid GeoJSON object.")}},coordsToLatLng:function(t){return new o.LatLng(t[1],t[0],t[2])},coordsToLatLngs:function(t,e,i){var n,o,s,a=[];for(o=0,s=t.length;s>o;o++)n=e?this.coordsToLatLngs(t[o],e-1,i):(i||this.coordsToLatLng)(t[o]),a.push(n);return a},latLngToCoords:function(t){var e=[t.lng,t.lat];return t.alt!==i&&e.push(t.alt),e},latLngsToCoords:function(t){for(var e=[],i=0,n=t.length;n>i;i++)e.push(o.GeoJSON.latLngToCoords(t[i]));return e},getFeature:function(t,e){return t.feature?o.extend({},t.feature,{geometry:e}):o.GeoJSON.asFeature(e)},asFeature:function(t){return"Feature"===t.type?t:{type:"Feature",properties:{},geometry:t}}});var a={toGeoJSON:function(){return o.GeoJSON.getFeature(this,{type:"Point",coordinates:o.GeoJSON.latLngToCoords(this.getLatLng())})}};o.Marker.include(a),o.Circle.include(a),o.CircleMarker.include(a),o.Polyline.include({toGeoJSON:function(){return o.GeoJSON.getFeature(this,{type:"LineString",coordinates:o.GeoJSON.latLngsToCoords(this.getLatLngs())})}}),o.Polygon.include({toGeoJSON:function(){var t,e,i,n=[o.GeoJSON.latLngsToCoords(this.getLatLngs())];if(n[0].push(n[0][0]),this._holes)for(t=0,e=this._holes.length;e>t;t++)i=o.GeoJSON.latLngsToCoords(this._holes[t]),i.push(i[0]),n.push(i);return o.GeoJSON.getFeature(this,{type:"Polygon",coordinates:n})}}),function(){function t(t){return function(){var e=[];return this.eachLayer(function(t){e.push(t.toGeoJSON().geometry.coordinates)}),o.GeoJSON.getFeature(this,{type:t,coordinates:e})}}o.MultiPolyline.include({toGeoJSON:t("MultiLineString")}),o.MultiPolygon.include({toGeoJSON:t("MultiPolygon")}),o.LayerGroup.include({toGeoJSON:function(){var e,i=this.feature&&this.feature.geometry,n=[];if(i&&"MultiPoint"===i.type)return t("MultiPoint").call(this);var s=i&&"GeometryCollection"===i.type;return this.eachLayer(function(t){t.toGeoJSON&&(e=t.toGeoJSON(),n.push(s?e.geometry:o.GeoJSON.asFeature(e)))}),s?o.GeoJSON.getFeature(this,{geometries:n,type:"GeometryCollection"}):{type:"FeatureCollection",features:n}}})}(),o.geoJson=function(t,e){return new o.GeoJSON(t,e)},o.DomEvent={addListener:function(t,e,i,n){var s,a,r,h=o.stamp(i),l="_leaflet_"+e+h;return t[l]?this:(s=function(e){return i.call(n||t,e||o.DomEvent._getEvent())},o.Browser.pointer&&0===e.indexOf("touch")?this.addPointerListener(t,e,s,h):(o.Browser.touch&&"dblclick"===e&&this.addDoubleTapListener&&this.addDoubleTapListener(t,s,h),"addEventListener"in t?"mousewheel"===e?(t.addEventListener("DOMMouseScroll",s,!1),t.addEventListener(e,s,!1)):"mouseenter"===e||"mouseleave"===e?(a=s,r="mouseenter"===e?"mouseover":"mouseout",s=function(e){return o.DomEvent._checkMouse(t,e)?a(e):void 0},t.addEventListener(r,s,!1)):"click"===e&&o.Browser.android?(a=s,s=function(t){return o.DomEvent._filterClick(t,a)},t.addEventListener(e,s,!1)):t.addEventListener(e,s,!1):"attachEvent"in t&&t.attachEvent("on"+e,s),t[l]=s,this))},removeListener:function(t,e,i){var n=o.stamp(i),s="_leaflet_"+e+n,a=t[s];return a?(o.Browser.pointer&&0===e.indexOf("touch")?this.removePointerListener(t,e,n):o.Browser.touch&&"dblclick"===e&&this.removeDoubleTapListener?this.removeDoubleTapListener(t,n):"removeEventListener"in t?"mousewheel"===e?(t.removeEventListener("DOMMouseScroll",a,!1),t.removeEventListener(e,a,!1)):"mouseenter"===e||"mouseleave"===e?t.removeEventListener("mouseenter"===e?"mouseover":"mouseout",a,!1):t.removeEventListener(e,a,!1):"detachEvent"in t&&t.detachEvent("on"+e,a),t[s]=null,this):this},stopPropagation:function(t){return t.stopPropagation?t.stopPropagation():t.cancelBubble=!0,o.DomEvent._skipped(t),this},disableScrollPropagation:function(t){var e=o.DomEvent.stopPropagation;return o.DomEvent.on(t,"mousewheel",e).on(t,"MozMousePixelScroll",e)},disableClickPropagation:function(t){for(var e=o.DomEvent.stopPropagation,i=o.Draggable.START.length-1;i>=0;i--)o.DomEvent.on(t,o.Draggable.START[i],e);return o.DomEvent.on(t,"click",o.DomEvent._fakeStop).on(t,"dblclick",e)},preventDefault:function(t){return t.preventDefault?t.preventDefault():t.returnValue=!1,this},stop:function(t){return o.DomEvent.preventDefault(t).stopPropagation(t)},getMousePosition:function(t,e){if(!e)return new o.Point(t.clientX,t.clientY);var i=e.getBoundingClientRect();return new o.Point(t.clientX-i.left-e.clientLeft,t.clientY-i.top-e.clientTop)},getWheelDelta:function(t){var e=0;return t.wheelDelta&&(e=t.wheelDelta/120),t.detail&&(e=-t.detail/3),e},_skipEvents:{},_fakeStop:function(t){o.DomEvent._skipEvents[t.type]=!0},_skipped:function(t){var e=this._skipEvents[t.type];return this._skipEvents[t.type]=!1,e},_checkMouse:function(t,e){var i=e.relatedTarget;if(!i)return!0;try{for(;i&&i!==t;)i=i.parentNode}catch(n){return!1}return i!==t},_getEvent:function(){var e=t.event;if(!e)for(var i=arguments.callee.caller;i&&(e=i.arguments[0],!e||t.Event!==e.constructor);)i=i.caller;return e},_filterClick:function(t,e){var i=t.timeStamp||t.originalEvent.timeStamp,n=o.DomEvent._lastClick&&i-o.DomEvent._lastClick;return n&&n>100&&500>n||t.target._simulatedClick&&!t._simulated?void o.DomEvent.stop(t):(o.DomEvent._lastClick=i,e(t))}},o.DomEvent.on=o.DomEvent.addListener,o.DomEvent.off=o.DomEvent.removeListener,o.Draggable=o.Class.extend({includes:o.Mixin.Events,statics:{START:o.Browser.touch?["touchstart","mousedown"]:["mousedown"],END:{mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},MOVE:{mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"}},initialize:function(t,e){this._element=t,this._dragStartTarget=e||t},enable:function(){if(!this._enabled){for(var t=o.Draggable.START.length-1;t>=0;t--)o.DomEvent.on(this._dragStartTarget,o.Draggable.START[t],this._onDown,this);this._enabled=!0}},disable:function(){if(this._enabled){for(var t=o.Draggable.START.length-1;t>=0;t--)o.DomEvent.off(this._dragStartTarget,o.Draggable.START[t],this._onDown,this);this._enabled=!1,this._moved=!1}},_onDown:function(t){if(this._moved=!1,!t.shiftKey&&(1===t.which||1===t.button||t.touches)&&(o.DomEvent.stopPropagation(t),!o.Draggable._disabled&&(o.DomUtil.disableImageDrag(),o.DomUtil.disableTextSelection(),!this._moving))){var i=t.touches?t.touches[0]:t;this._startPoint=new o.Point(i.clientX,i.clientY),this._startPos=this._newPos=o.DomUtil.getPosition(this._element),o.DomEvent.on(e,o.Draggable.MOVE[t.type],this._onMove,this).on(e,o.Draggable.END[t.type],this._onUp,this)}},_onMove:function(t){if(t.touches&&t.touches.length>1)return void(this._moved=!0);var i=t.touches&&1===t.touches.length?t.touches[0]:t,n=new o.Point(i.clientX,i.clientY),s=n.subtract(this._startPoint);(s.x||s.y)&&(o.Browser.touch&&Math.abs(s.x)+Math.abs(s.y)<3||(o.DomEvent.preventDefault(t),this._moved||(this.fire("dragstart"),this._moved=!0,this._startPos=o.DomUtil.getPosition(this._element).subtract(s),o.DomUtil.addClass(e.body,"leaflet-dragging"),this._lastTarget=t.target||t.srcElement,o.DomUtil.addClass(this._lastTarget,"leaflet-drag-target")),this._newPos=this._startPos.add(s),this._moving=!0,o.Util.cancelAnimFrame(this._animRequest),this._animRequest=o.Util.requestAnimFrame(this._updatePosition,this,!0,this._dragStartTarget)))},_updatePosition:function(){this.fire("predrag"),o.DomUtil.setPosition(this._element,this._newPos),this.fire("drag")},_onUp:function(){o.DomUtil.removeClass(e.body,"leaflet-dragging"),this._lastTarget&&(o.DomUtil.removeClass(this._lastTarget,"leaflet-drag-target"),this._lastTarget=null);for(var t in o.Draggable.MOVE)o.DomEvent.off(e,o.Draggable.MOVE[t],this._onMove).off(e,o.Draggable.END[t],this._onUp);o.DomUtil.enableImageDrag(),o.DomUtil.enableTextSelection(),this._moved&&this._moving&&(o.Util.cancelAnimFrame(this._animRequest),this.fire("dragend",{distance:this._newPos.distanceTo(this._startPos)})),this._moving=!1}}),o.Handler=o.Class.extend({initialize:function(t){this._map=t},enable:function(){this._enabled||(this._enabled=!0,this.addHooks())},disable:function(){this._enabled&&(this._enabled=!1,this.removeHooks())},enabled:function(){return!!this._enabled}}),o.Map.mergeOptions({dragging:!0,inertia:!o.Browser.android23,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,inertiaThreshold:o.Browser.touch?32:18,easeLinearity:.25,worldCopyJump:!1}),o.Map.Drag=o.Handler.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new o.Draggable(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDrag,this),t.on("viewreset",this._onViewReset,this),t.whenReady(this._onViewReset,this))}this._draggable.enable()},removeHooks:function(){this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){var t=this._map;t._panAnim&&t._panAnim.stop(),t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(){if(this._map.options.inertia){var t=this._lastTime=+new Date,e=this._lastPos=this._draggable._newPos;this._positions.push(e),this._times.push(t),t-this._times[0]>200&&(this._positions.shift(),this._times.shift())}this._map.fire("move").fire("drag")},_onViewReset:function(){var t=this._map.getSize()._divideBy(2),e=this._map.latLngToLayerPoint([0,0]);this._initialWorldOffset=e.subtract(t).x,this._worldWidth=this._map.project([0,180]).x},_onPreDrag:function(){var t=this._worldWidth,e=Math.round(t/2),i=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-e+i)%t+e-i,s=(n+e+i)%t-e-i,a=Math.abs(o+i)<Math.abs(s+i)?o:s;this._draggable._newPos.x=a},_onDragEnd:function(t){var e=this._map,i=e.options,n=+new Date-this._lastTime,s=!i.inertia||n>i.inertiaThreshold||!this._positions[0];if(e.fire("dragend",t),s)e.fire("moveend");else{var a=this._lastPos.subtract(this._positions[0]),r=(this._lastTime+n-this._times[0])/1e3,h=i.easeLinearity,l=a.multiplyBy(h/r),u=l.distanceTo([0,0]),c=Math.min(i.inertiaMaxSpeed,u),d=l.multiplyBy(c/u),p=c/(i.inertiaDeceleration*h),_=d.multiplyBy(-p/2).round();_.x&&_.y?(_=e._limitOffset(_,e.options.maxBounds),o.Util.requestAnimFrame(function(){e.panBy(_,{duration:p,easeLinearity:h,noMoveStart:!0})})):e.fire("moveend")}}}),o.Map.addInitHook("addHandler","dragging",o.Map.Drag),o.Map.mergeOptions({doubleClickZoom:!0}),o.Map.DoubleClickZoom=o.Handler.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var e=this._map,i=e.getZoom()+(t.originalEvent.shiftKey?-1:1);"center"===e.options.doubleClickZoom?e.setZoom(i):e.setZoomAround(t.containerPoint,i)}}),o.Map.addInitHook("addHandler","doubleClickZoom",o.Map.DoubleClickZoom),o.Map.mergeOptions({scrollWheelZoom:!0}),o.Map.ScrollWheelZoom=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"mousewheel",this._onWheelScroll,this),o.DomEvent.on(this._map._container,"MozMousePixelScroll",o.DomEvent.preventDefault),this._delta=0},removeHooks:function(){o.DomEvent.off(this._map._container,"mousewheel",this._onWheelScroll),o.DomEvent.off(this._map._container,"MozMousePixelScroll",o.DomEvent.preventDefault)},_onWheelScroll:function(t){var e=o.DomEvent.getWheelDelta(t);this._delta+=e,this._lastMousePos=this._map.mouseEventToContainerPoint(t),this._startTime||(this._startTime=+new Date);var i=Math.max(40-(+new Date-this._startTime),0);clearTimeout(this._timer),this._timer=setTimeout(o.bind(this._performZoom,this),i),o.DomEvent.preventDefault(t),o.DomEvent.stopPropagation(t)},_performZoom:function(){var t=this._map,e=this._delta,i=t.getZoom();e=e>0?Math.ceil(e):Math.floor(e),e=Math.max(Math.min(e,4),-4),e=t._limitZoom(i+e)-i,this._delta=0,this._startTime=null,e&&("center"===t.options.scrollWheelZoom?t.setZoom(i+e):t.setZoomAround(this._lastMousePos,i+e))}}),o.Map.addInitHook("addHandler","scrollWheelZoom",o.Map.ScrollWheelZoom),o.extend(o.DomEvent,{_touchstart:o.Browser.msPointer?"MSPointerDown":o.Browser.pointer?"pointerdown":"touchstart",_touchend:o.Browser.msPointer?"MSPointerUp":o.Browser.pointer?"pointerup":"touchend",addDoubleTapListener:function(t,i,n){function s(t){var e;if(o.Browser.pointer?(_.push(t.pointerId),e=_.length):e=t.touches.length,!(e>1)){var i=Date.now(),n=i-(r||i);h=t.touches?t.touches[0]:t,l=n>0&&u>=n,r=i}}function a(t){if(o.Browser.pointer){var e=_.indexOf(t.pointerId);if(-1===e)return;_.splice(e,1)}if(l){if(o.Browser.pointer){var n,s={};for(var a in h)n=h[a],"function"==typeof n?s[a]=n.bind(h):s[a]=n;h=s}h.type="dblclick",i(h),r=null}}var r,h,l=!1,u=250,c="_leaflet_",d=this._touchstart,p=this._touchend,_=[];t[c+d+n]=s,t[c+p+n]=a;var m=o.Browser.pointer?e.documentElement:t;return t.addEventListener(d,s,!1),m.addEventListener(p,a,!1),o.Browser.pointer&&m.addEventListener(o.DomEvent.POINTER_CANCEL,a,!1),this},removeDoubleTapListener:function(t,i){var n="_leaflet_";return t.removeEventListener(this._touchstart,t[n+this._touchstart+i],!1),(o.Browser.pointer?e.documentElement:t).removeEventListener(this._touchend,t[n+this._touchend+i],!1),o.Browser.pointer&&e.documentElement.removeEventListener(o.DomEvent.POINTER_CANCEL,t[n+this._touchend+i],!1),this}}),o.extend(o.DomEvent,{POINTER_DOWN:o.Browser.msPointer?"MSPointerDown":"pointerdown",POINTER_MOVE:o.Browser.msPointer?"MSPointerMove":"pointermove",POINTER_UP:o.Browser.msPointer?"MSPointerUp":"pointerup",POINTER_CANCEL:o.Browser.msPointer?"MSPointerCancel":"pointercancel",_pointers:[],_pointerDocumentListener:!1,addPointerListener:function(t,e,i,n){switch(e){case"touchstart":return this.addPointerListenerStart(t,e,i,n); -case"touchend":return this.addPointerListenerEnd(t,e,i,n);case"touchmove":return this.addPointerListenerMove(t,e,i,n);default:throw"Unknown touch event type"}},addPointerListenerStart:function(t,i,n,s){var a="_leaflet_",r=this._pointers,h=function(t){"mouse"!==t.pointerType&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&o.DomEvent.preventDefault(t);for(var e=!1,i=0;i<r.length;i++)if(r[i].pointerId===t.pointerId){e=!0;break}e||r.push(t),t.touches=r.slice(),t.changedTouches=[t],n(t)};if(t[a+"touchstart"+s]=h,t.addEventListener(this.POINTER_DOWN,h,!1),!this._pointerDocumentListener){var l=function(t){for(var e=0;e<r.length;e++)if(r[e].pointerId===t.pointerId){r.splice(e,1);break}};e.documentElement.addEventListener(this.POINTER_UP,l,!1),e.documentElement.addEventListener(this.POINTER_CANCEL,l,!1),this._pointerDocumentListener=!0}return this},addPointerListenerMove:function(t,e,i,n){function o(t){if(t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&"mouse"!==t.pointerType||0!==t.buttons){for(var e=0;e<a.length;e++)if(a[e].pointerId===t.pointerId){a[e]=t;break}t.touches=a.slice(),t.changedTouches=[t],i(t)}}var s="_leaflet_",a=this._pointers;return t[s+"touchmove"+n]=o,t.addEventListener(this.POINTER_MOVE,o,!1),this},addPointerListenerEnd:function(t,e,i,n){var o="_leaflet_",s=this._pointers,a=function(t){for(var e=0;e<s.length;e++)if(s[e].pointerId===t.pointerId){s.splice(e,1);break}t.touches=s.slice(),t.changedTouches=[t],i(t)};return t[o+"touchend"+n]=a,t.addEventListener(this.POINTER_UP,a,!1),t.addEventListener(this.POINTER_CANCEL,a,!1),this},removePointerListener:function(t,e,i){var n="_leaflet_",o=t[n+e+i];switch(e){case"touchstart":t.removeEventListener(this.POINTER_DOWN,o,!1);break;case"touchmove":t.removeEventListener(this.POINTER_MOVE,o,!1);break;case"touchend":t.removeEventListener(this.POINTER_UP,o,!1),t.removeEventListener(this.POINTER_CANCEL,o,!1)}return this}}),o.Map.mergeOptions({touchZoom:o.Browser.touch&&!o.Browser.android23,bounceAtZoomLimits:!0}),o.Map.TouchZoom=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){o.DomEvent.off(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var n=i.mouseEventToLayerPoint(t.touches[0]),s=i.mouseEventToLayerPoint(t.touches[1]),a=i._getCenterLayerPoint();this._startCenter=n.add(s)._divideBy(2),this._startDist=n.distanceTo(s),this._moved=!1,this._zooming=!0,this._centerOffset=a.subtract(this._startCenter),i._panAnim&&i._panAnim.stop(),o.DomEvent.on(e,"touchmove",this._onTouchMove,this).on(e,"touchend",this._onTouchEnd,this),o.DomEvent.preventDefault(t)}},_onTouchMove:function(t){var e=this._map;if(t.touches&&2===t.touches.length&&this._zooming){var i=e.mouseEventToLayerPoint(t.touches[0]),n=e.mouseEventToLayerPoint(t.touches[1]);this._scale=i.distanceTo(n)/this._startDist,this._delta=i._add(n)._divideBy(2)._subtract(this._startCenter),1!==this._scale&&(e.options.bounceAtZoomLimits||!(e.getZoom()===e.getMinZoom()&&this._scale<1||e.getZoom()===e.getMaxZoom()&&this._scale>1))&&(this._moved||(o.DomUtil.addClass(e._mapPane,"leaflet-touching"),e.fire("movestart").fire("zoomstart"),this._moved=!0),o.Util.cancelAnimFrame(this._animRequest),this._animRequest=o.Util.requestAnimFrame(this._updateOnMove,this,!0,this._map._container),o.DomEvent.preventDefault(t))}},_updateOnMove:function(){var t=this._map,e=this._getScaleOrigin(),i=t.layerPointToLatLng(e),n=t.getScaleZoom(this._scale);t._animateZoom(i,n,this._startCenter,this._scale,this._delta,!1,!0)},_onTouchEnd:function(){if(!this._moved||!this._zooming)return void(this._zooming=!1);var t=this._map;this._zooming=!1,o.DomUtil.removeClass(t._mapPane,"leaflet-touching"),o.Util.cancelAnimFrame(this._animRequest),o.DomEvent.off(e,"touchmove",this._onTouchMove).off(e,"touchend",this._onTouchEnd);var i=this._getScaleOrigin(),n=t.layerPointToLatLng(i),s=t.getZoom(),a=t.getScaleZoom(this._scale)-s,r=a>0?Math.ceil(a):Math.floor(a),h=t._limitZoom(s+r),l=t.getZoomScale(h)/this._scale;t._animateZoom(n,h,i,l)},_getScaleOrigin:function(){var t=this._centerOffset.subtract(this._delta).divideBy(this._scale);return this._startCenter.add(t)}}),o.Map.addInitHook("addHandler","touchZoom",o.Map.TouchZoom),o.Map.mergeOptions({tap:!0,tapTolerance:15}),o.Map.Tap=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){o.DomEvent.off(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if(o.DomEvent.preventDefault(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new o.Point(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.addClass(n,"leaflet-active"),this._holdTimeout=setTimeout(o.bind(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),o.DomEvent.on(e,"touchmove",this._onMove,this).on(e,"touchend",this._onUp,this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),o.DomEvent.off(e,"touchmove",this._onMove,this).off(e,"touchend",this._onUp,this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],n=i.target;n&&n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.removeClass(n,"leaflet-active"),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var e=t.touches[0];this._newPos=new o.Point(e.clientX,e.clientY)},_simulateEvent:function(i,n){var o=e.createEvent("MouseEvents");o._simulated=!0,n.target._simulatedClick=!0,o.initMouseEvent(i,!0,!0,t,1,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null),n.target.dispatchEvent(o)}}),o.Browser.touch&&!o.Browser.pointer&&o.Map.addInitHook("addHandler","tap",o.Map.Tap),o.Map.mergeOptions({boxZoom:!0}),o.Map.BoxZoom=o.Handler.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._moved=!1},addHooks:function(){o.DomEvent.on(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){o.DomEvent.off(this._container,"mousedown",this._onMouseDown),this._moved=!1},moved:function(){return this._moved},_onMouseDown:function(t){return this._moved=!1,!t.shiftKey||1!==t.which&&1!==t.button?!1:(o.DomUtil.disableTextSelection(),o.DomUtil.disableImageDrag(),this._startLayerPoint=this._map.mouseEventToLayerPoint(t),void o.DomEvent.on(e,"mousemove",this._onMouseMove,this).on(e,"mouseup",this._onMouseUp,this).on(e,"keydown",this._onKeyDown,this))},_onMouseMove:function(t){this._moved||(this._box=o.DomUtil.create("div","leaflet-zoom-box",this._pane),o.DomUtil.setPosition(this._box,this._startLayerPoint),this._container.style.cursor="crosshair",this._map.fire("boxzoomstart"));var e=this._startLayerPoint,i=this._box,n=this._map.mouseEventToLayerPoint(t),s=n.subtract(e),a=new o.Point(Math.min(n.x,e.x),Math.min(n.y,e.y));o.DomUtil.setPosition(i,a),this._moved=!0,i.style.width=Math.max(0,Math.abs(s.x)-4)+"px",i.style.height=Math.max(0,Math.abs(s.y)-4)+"px"},_finish:function(){this._moved&&(this._pane.removeChild(this._box),this._container.style.cursor=""),o.DomUtil.enableTextSelection(),o.DomUtil.enableImageDrag(),o.DomEvent.off(e,"mousemove",this._onMouseMove).off(e,"mouseup",this._onMouseUp).off(e,"keydown",this._onKeyDown)},_onMouseUp:function(t){this._finish();var e=this._map,i=e.mouseEventToLayerPoint(t);if(!this._startLayerPoint.equals(i)){var n=new o.LatLngBounds(e.layerPointToLatLng(this._startLayerPoint),e.layerPointToLatLng(i));e.fitBounds(n),e.fire("boxzoomend",{boxZoomBounds:n})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}}),o.Map.addInitHook("addHandler","boxZoom",o.Map.BoxZoom),o.Map.mergeOptions({keyboard:!0,keyboardPanOffset:80,keyboardZoomOffset:1}),o.Map.Keyboard=o.Handler.extend({keyCodes:{left:[37],right:[39],down:[40],up:[38],zoomIn:[187,107,61,171],zoomOut:[189,109,173]},initialize:function(t){this._map=t,this._setPanOffset(t.options.keyboardPanOffset),this._setZoomOffset(t.options.keyboardZoomOffset)},addHooks:function(){var t=this._map._container;-1===t.tabIndex&&(t.tabIndex="0"),o.DomEvent.on(t,"focus",this._onFocus,this).on(t,"blur",this._onBlur,this).on(t,"mousedown",this._onMouseDown,this),this._map.on("focus",this._addHooks,this).on("blur",this._removeHooks,this)},removeHooks:function(){this._removeHooks();var t=this._map._container;o.DomEvent.off(t,"focus",this._onFocus,this).off(t,"blur",this._onBlur,this).off(t,"mousedown",this._onMouseDown,this),this._map.off("focus",this._addHooks,this).off("blur",this._removeHooks,this)},_onMouseDown:function(){if(!this._focused){var i=e.body,n=e.documentElement,o=i.scrollTop||n.scrollTop,s=i.scrollLeft||n.scrollLeft;this._map._container.focus(),t.scrollTo(s,o)}},_onFocus:function(){this._focused=!0,this._map.fire("focus")},_onBlur:function(){this._focused=!1,this._map.fire("blur")},_setPanOffset:function(t){var e,i,n=this._panKeys={},o=this.keyCodes;for(e=0,i=o.left.length;i>e;e++)n[o.left[e]]=[-1*t,0];for(e=0,i=o.right.length;i>e;e++)n[o.right[e]]=[t,0];for(e=0,i=o.down.length;i>e;e++)n[o.down[e]]=[0,t];for(e=0,i=o.up.length;i>e;e++)n[o.up[e]]=[0,-1*t]},_setZoomOffset:function(t){var e,i,n=this._zoomKeys={},o=this.keyCodes;for(e=0,i=o.zoomIn.length;i>e;e++)n[o.zoomIn[e]]=t;for(e=0,i=o.zoomOut.length;i>e;e++)n[o.zoomOut[e]]=-t},_addHooks:function(){o.DomEvent.on(e,"keydown",this._onKeyDown,this)},_removeHooks:function(){o.DomEvent.off(e,"keydown",this._onKeyDown,this)},_onKeyDown:function(t){var e=t.keyCode,i=this._map;if(e in this._panKeys){if(i._panAnim&&i._panAnim._inProgress)return;i.panBy(this._panKeys[e]),i.options.maxBounds&&i.panInsideBounds(i.options.maxBounds)}else{if(!(e in this._zoomKeys))return;i.setZoom(i.getZoom()+this._zoomKeys[e])}o.DomEvent.stop(t)}}),o.Map.addInitHook("addHandler","keyboard",o.Map.Keyboard),o.Handler.MarkerDrag=o.Handler.extend({initialize:function(t){this._marker=t},addHooks:function(){var t=this._marker._icon;this._draggable||(this._draggable=new o.Draggable(t,t)),this._draggable.on("dragstart",this._onDragStart,this).on("drag",this._onDrag,this).on("dragend",this._onDragEnd,this),this._draggable.enable(),o.DomUtil.addClass(this._marker._icon,"leaflet-marker-draggable")},removeHooks:function(){this._draggable.off("dragstart",this._onDragStart,this).off("drag",this._onDrag,this).off("dragend",this._onDragEnd,this),this._draggable.disable(),o.DomUtil.removeClass(this._marker._icon,"leaflet-marker-draggable")},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){this._marker.closePopup().fire("movestart").fire("dragstart")},_onDrag:function(){var t=this._marker,e=t._shadow,i=o.DomUtil.getPosition(t._icon),n=t._map.layerPointToLatLng(i);e&&o.DomUtil.setPosition(e,i),t._latlng=n,t.fire("move",{latlng:n}).fire("drag")},_onDragEnd:function(t){this._marker.fire("moveend").fire("dragend",t)}}),o.Control=o.Class.extend({options:{position:"topright"},initialize:function(t){o.setOptions(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var e=this._map;return e&&e.removeControl(this),this.options.position=t,e&&e.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this._map=t;var e=this._container=this.onAdd(t),i=this.getPosition(),n=t._controlCorners[i];return o.DomUtil.addClass(e,"leaflet-control"),-1!==i.indexOf("bottom")?n.insertBefore(e,n.firstChild):n.appendChild(e),this},removeFrom:function(t){var e=this.getPosition(),i=t._controlCorners[e];return i.removeChild(this._container),this._map=null,this.onRemove&&this.onRemove(t),this},_refocusOnMap:function(){this._map&&this._map.getContainer().focus()}}),o.control=function(t){return new o.Control(t)},o.Map.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.removeFrom(this),this},_initControlPos:function(){function t(t,s){var a=i+t+" "+i+s;e[t+s]=o.DomUtil.create("div",a,n)}var e=this._controlCorners={},i="leaflet-",n=this._controlContainer=o.DomUtil.create("div",i+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){this._container.removeChild(this._controlContainer)}}),o.Control.Zoom=o.Control.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"-",zoomOutTitle:"Zoom out"},onAdd:function(t){var e="leaflet-control-zoom",i=o.DomUtil.create("div",e+" leaflet-bar");return this._map=t,this._zoomInButton=this._createButton(this.options.zoomInText,this.options.zoomInTitle,e+"-in",i,this._zoomIn,this),this._zoomOutButton=this._createButton(this.options.zoomOutText,this.options.zoomOutTitle,e+"-out",i,this._zoomOut,this),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),i},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},_zoomIn:function(t){this._map.zoomIn(t.shiftKey?3:1)},_zoomOut:function(t){this._map.zoomOut(t.shiftKey?3:1)},_createButton:function(t,e,i,n,s,a){var r=o.DomUtil.create("a",i,n);r.innerHTML=t,r.href="#",r.title=e;var h=o.DomEvent.stopPropagation;return o.DomEvent.on(r,"click",h).on(r,"mousedown",h).on(r,"dblclick",h).on(r,"click",o.DomEvent.preventDefault).on(r,"click",s,a).on(r,"click",this._refocusOnMap,a),r},_updateDisabled:function(){var t=this._map,e="leaflet-disabled";o.DomUtil.removeClass(this._zoomInButton,e),o.DomUtil.removeClass(this._zoomOutButton,e),t._zoom===t.getMinZoom()&&o.DomUtil.addClass(this._zoomOutButton,e),t._zoom===t.getMaxZoom()&&o.DomUtil.addClass(this._zoomInButton,e)}}),o.Map.mergeOptions({zoomControl:!0}),o.Map.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new o.Control.Zoom,this.addControl(this.zoomControl))}),o.control.zoom=function(t){return new o.Control.Zoom(t)},o.Control.Attribution=o.Control.extend({options:{position:"bottomright",prefix:'<a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>'},initialize:function(t){o.setOptions(this,t),this._attributions={}},onAdd:function(t){this._container=o.DomUtil.create("div","leaflet-control-attribution"),o.DomEvent.disableClickPropagation(this._container);for(var e in t._layers)t._layers[e].getAttribution&&this.addAttribution(t._layers[e].getAttribution());return t.on("layeradd",this._onLayerAdd,this).on("layerremove",this._onLayerRemove,this),this._update(),this._container},onRemove:function(t){t.off("layeradd",this._onLayerAdd).off("layerremove",this._onLayerRemove)},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):void 0},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):void 0},_update:function(){if(this._map){var t=[];for(var e in this._attributions)this._attributions[e]&&t.push(e);var i=[];this.options.prefix&&i.push(this.options.prefix),t.length&&i.push(t.join(", ")),this._container.innerHTML=i.join(" | ")}},_onLayerAdd:function(t){t.layer.getAttribution&&this.addAttribution(t.layer.getAttribution())},_onLayerRemove:function(t){t.layer.getAttribution&&this.removeAttribution(t.layer.getAttribution())}}),o.Map.mergeOptions({attributionControl:!0}),o.Map.addInitHook(function(){this.options.attributionControl&&(this.attributionControl=(new o.Control.Attribution).addTo(this))}),o.control.attribution=function(t){return new o.Control.Attribution(t)},o.Control.Scale=o.Control.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0,updateWhenIdle:!1},onAdd:function(t){this._map=t;var e="leaflet-control-scale",i=o.DomUtil.create("div",e),n=this.options;return this._addScales(n,e,i),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),i},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,e,i){t.metric&&(this._mScale=o.DomUtil.create("div",e+"-line",i)),t.imperial&&(this._iScale=o.DomUtil.create("div",e+"-line",i))},_update:function(){var t=this._map.getBounds(),e=t.getCenter().lat,i=6378137*Math.PI*Math.cos(e*Math.PI/180),n=i*(t.getNorthEast().lng-t.getSouthWest().lng)/180,o=this._map.getSize(),s=this.options,a=0;o.x>0&&(a=n*(s.maxWidth/o.x)),this._updateScales(s,a)},_updateScales:function(t,e){t.metric&&e&&this._updateMetric(e),t.imperial&&e&&this._updateImperial(e)},_updateMetric:function(t){var e=this._getRoundNum(t);this._mScale.style.width=this._getScaleWidth(e/t)+"px",this._mScale.innerHTML=1e3>e?e+" m":e/1e3+" km"},_updateImperial:function(t){var e,i,n,o=3.2808399*t,s=this._iScale;o>5280?(e=o/5280,i=this._getRoundNum(e),s.style.width=this._getScaleWidth(i/e)+"px",s.innerHTML=i+" mi"):(n=this._getRoundNum(o),s.style.width=this._getScaleWidth(n/o)+"px",s.innerHTML=n+" ft")},_getScaleWidth:function(t){return Math.round(this.options.maxWidth*t)-10},_getRoundNum:function(t){var e=Math.pow(10,(Math.floor(t)+"").length-1),i=t/e;return i=i>=10?10:i>=5?5:i>=3?3:i>=2?2:1,e*i}}),o.control.scale=function(t){return new o.Control.Scale(t)},o.Control.Layers=o.Control.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0},initialize:function(t,e,i){o.setOptions(this,i),this._layers={},this._lastZIndex=0,this._handlingClick=!1;for(var n in t)this._addLayer(t[n],n);for(n in e)this._addLayer(e[n],n,!0)},onAdd:function(t){return this._initLayout(),this._update(),t.on("layeradd",this._onLayerChange,this).on("layerremove",this._onLayerChange,this),this._container},onRemove:function(t){t.off("layeradd",this._onLayerChange,this).off("layerremove",this._onLayerChange,this)},addBaseLayer:function(t,e){return this._addLayer(t,e),this._update(),this},addOverlay:function(t,e){return this._addLayer(t,e,!0),this._update(),this},removeLayer:function(t){var e=o.stamp(t);return delete this._layers[e],this._update(),this},_initLayout:function(){var t="leaflet-control-layers",e=this._container=o.DomUtil.create("div",t);e.setAttribute("aria-haspopup",!0),o.Browser.touch?o.DomEvent.on(e,"click",o.DomEvent.stopPropagation):o.DomEvent.disableClickPropagation(e).disableScrollPropagation(e);var i=this._form=o.DomUtil.create("form",t+"-list");if(this.options.collapsed){o.Browser.android||o.DomEvent.on(e,"mouseover",this._expand,this).on(e,"mouseout",this._collapse,this);var n=this._layersLink=o.DomUtil.create("a",t+"-toggle",e);n.href="#",n.title="Layers",o.Browser.touch?o.DomEvent.on(n,"click",o.DomEvent.stop).on(n,"click",this._expand,this):o.DomEvent.on(n,"focus",this._expand,this),o.DomEvent.on(i,"click",function(){setTimeout(o.bind(this._onInputClick,this),0)},this),this._map.on("click",this._collapse,this)}else this._expand();this._baseLayersList=o.DomUtil.create("div",t+"-base",i),this._separator=o.DomUtil.create("div",t+"-separator",i),this._overlaysList=o.DomUtil.create("div",t+"-overlays",i),e.appendChild(i)},_addLayer:function(t,e,i){var n=o.stamp(t);this._layers[n]={layer:t,name:e,overlay:i},this.options.autoZIndex&&t.setZIndex&&(this._lastZIndex++,t.setZIndex(this._lastZIndex))},_update:function(){if(this._container){this._baseLayersList.innerHTML="",this._overlaysList.innerHTML="";var t,e,i=!1,n=!1;for(t in this._layers)e=this._layers[t],this._addItem(e),n=n||e.overlay,i=i||!e.overlay;this._separator.style.display=n&&i?"":"none"}},_onLayerChange:function(t){var e=this._layers[o.stamp(t.layer)];if(e){this._handlingClick||this._update();var i=e.overlay?"layeradd"===t.type?"overlayadd":"overlayremove":"layeradd"===t.type?"baselayerchange":null;i&&this._map.fire(i,e)}},_createRadioElement:function(t,i){var n='<input type="radio" class="leaflet-control-layers-selector" name="'+t+'"';i&&(n+=' checked="checked"'),n+="/>";var o=e.createElement("div");return o.innerHTML=n,o.firstChild},_addItem:function(t){var i,n=e.createElement("label"),s=this._map.hasLayer(t.layer);t.overlay?(i=e.createElement("input"),i.type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=s):i=this._createRadioElement("leaflet-base-layers",s),i.layerId=o.stamp(t.layer),o.DomEvent.on(i,"click",this._onInputClick,this);var a=e.createElement("span");a.innerHTML=" "+t.name,n.appendChild(i),n.appendChild(a);var r=t.overlay?this._overlaysList:this._baseLayersList;return r.appendChild(n),n},_onInputClick:function(){var t,e,i,n=this._form.getElementsByTagName("input"),o=n.length;for(this._handlingClick=!0,t=0;o>t;t++)e=n[t],i=this._layers[e.layerId],e.checked&&!this._map.hasLayer(i.layer)?this._map.addLayer(i.layer):!e.checked&&this._map.hasLayer(i.layer)&&this._map.removeLayer(i.layer);this._handlingClick=!1,this._refocusOnMap()},_expand:function(){o.DomUtil.addClass(this._container,"leaflet-control-layers-expanded")},_collapse:function(){this._container.className=this._container.className.replace(" leaflet-control-layers-expanded","")}}),o.control.layers=function(t,e,i){return new o.Control.Layers(t,e,i)},o.PosAnimation=o.Class.extend({includes:o.Mixin.Events,run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._newPos=e,this.fire("start"),t.style[o.DomUtil.TRANSITION]="all "+(i||.25)+"s cubic-bezier(0,0,"+(n||.5)+",1)",o.DomEvent.on(t,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),o.DomUtil.setPosition(t,e),o.Util.falseFn(t.offsetWidth),this._stepTimer=setInterval(o.bind(this._onStep,this),50)},stop:function(){this._inProgress&&(o.DomUtil.setPosition(this._el,this._getPos()),this._onTransitionEnd(),o.Util.falseFn(this._el.offsetWidth))},_onStep:function(){var t=this._getPos();return t?(this._el._leaflet_pos=t,void this.fire("step")):void this._onTransitionEnd()},_transformRe:/([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/,_getPos:function(){var e,i,n,s=this._el,a=t.getComputedStyle(s);if(o.Browser.any3d){if(n=a[o.DomUtil.TRANSFORM].match(this._transformRe),!n)return;e=parseFloat(n[1]),i=parseFloat(n[2])}else e=parseFloat(a.left),i=parseFloat(a.top);return new o.Point(e,i,!0)},_onTransitionEnd:function(){o.DomEvent.off(this._el,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),this._inProgress&&(this._inProgress=!1,this._el.style[o.DomUtil.TRANSITION]="",this._el._leaflet_pos=this._newPos,clearInterval(this._stepTimer),this.fire("step").fire("end"))}}),o.Map.include({setView:function(t,e,n){if(e=e===i?this._zoom:this._limitZoom(e),t=this._limitCenter(o.latLng(t),e,this.options.maxBounds),n=n||{},this._panAnim&&this._panAnim.stop(),this._loaded&&!n.reset&&n!==!0){n.animate!==i&&(n.zoom=o.extend({animate:n.animate},n.zoom),n.pan=o.extend({animate:n.animate},n.pan));var s=this._zoom!==e?this._tryAnimatedZoom&&this._tryAnimatedZoom(t,e,n.zoom):this._tryAnimatedPan(t,n.pan);if(s)return clearTimeout(this._sizeTimer),this}return this._resetView(t,e),this},panBy:function(t,e){if(t=o.point(t).round(),e=e||{},!t.x&&!t.y)return this;if(this._panAnim||(this._panAnim=new o.PosAnimation,this._panAnim.on({step:this._onPanTransitionStep,end:this._onPanTransitionEnd},this)),e.noMoveStart||this.fire("movestart"),e.animate!==!1){o.DomUtil.addClass(this._mapPane,"leaflet-pan-anim");var i=this._getMapPanePos().subtract(t);this._panAnim.run(this._mapPane,i,e.duration||.25,e.easeLinearity)}else this._rawPanBy(t),this.fire("move").fire("moveend");return this},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){o.DomUtil.removeClass(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,e){var i=this._getCenterOffset(t)._floor();return(e&&e.animate)===!0||this.getSize().contains(i)?(this.panBy(i,e),!0):!1}}),o.PosAnimation=o.DomUtil.TRANSITION?o.PosAnimation:o.PosAnimation.extend({run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._duration=i||.25,this._easeOutPower=1/Math.max(n||.5,.2),this._startPos=o.DomUtil.getPosition(t),this._offset=e.subtract(this._startPos),this._startTime=+new Date,this.fire("start"),this._animate()},stop:function(){this._inProgress&&(this._step(),this._complete())},_animate:function(){this._animId=o.Util.requestAnimFrame(this._animate,this),this._step()},_step:function(){var t=+new Date-this._startTime,e=1e3*this._duration;e>t?this._runFrame(this._easeOut(t/e)):(this._runFrame(1),this._complete())},_runFrame:function(t){var e=this._startPos.add(this._offset.multiplyBy(t));o.DomUtil.setPosition(this._el,e),this.fire("step")},_complete:function(){o.Util.cancelAnimFrame(this._animId),this._inProgress=!1,this.fire("end")},_easeOut:function(t){return 1-Math.pow(1-t,this._easeOutPower)}}),o.Map.mergeOptions({zoomAnimation:!0,zoomAnimationThreshold:4}),o.DomUtil.TRANSITION&&o.Map.addInitHook(function(){this._zoomAnimated=this.options.zoomAnimation&&o.DomUtil.TRANSITION&&o.Browser.any3d&&!o.Browser.android23&&!o.Browser.mobileOpera,this._zoomAnimated&&o.DomEvent.on(this._mapPane,o.DomUtil.TRANSITION_END,this._catchTransitionEnd,this)}),o.Map.include(o.DomUtil.TRANSITION?{_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,e,i){if(this._animatingZoom)return!0;if(i=i||{},!this._zoomAnimated||i.animate===!1||this._nothingToAnimate()||Math.abs(e-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(e),o=this._getCenterOffset(t)._divideBy(1-1/n),s=this._getCenterLayerPoint()._add(o);return i.animate===!0||this.getSize().contains(o)?(this.fire("movestart").fire("zoomstart"),this._animateZoom(t,e,s,n,null,!0),!0):!1},_animateZoom:function(t,e,i,n,s,a,r){r||(this._animatingZoom=!0),o.DomUtil.addClass(this._mapPane,"leaflet-zoom-anim"),this._animateToCenter=t,this._animateToZoom=e,o.Draggable&&(o.Draggable._disabled=!0),o.Util.requestAnimFrame(function(){this.fire("zoomanim",{center:t,zoom:e,origin:i,scale:n,delta:s,backwards:a}),setTimeout(o.bind(this._onZoomTransitionEnd,this),250)},this)},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._animatingZoom=!1,o.DomUtil.removeClass(this._mapPane,"leaflet-zoom-anim"),o.Util.requestAnimFrame(function(){this._resetView(this._animateToCenter,this._animateToZoom,!0,!0),o.Draggable&&(o.Draggable._disabled=!1)},this))}}:{}),o.TileLayer.include({_animateZoom:function(t){this._animating||(this._animating=!0,this._prepareBgBuffer());var e=this._bgBuffer,i=o.DomUtil.TRANSFORM,n=t.delta?o.DomUtil.getTranslateString(t.delta):e.style[i],s=o.DomUtil.getScaleString(t.scale,t.origin);e.style[i]=t.backwards?s+" "+n:n+" "+s},_endZoomAnim:function(){var t=this._tileContainer,e=this._bgBuffer;t.style.visibility="",t.parentNode.appendChild(t),o.Util.falseFn(e.offsetWidth);var i=this._map.getZoom();(i>this.options.maxZoom||i<this.options.minZoom)&&this._clearBgBuffer(),this._animating=!1},_clearBgBuffer:function(){var t=this._map;!t||t._animatingZoom||t.touchZoom._zooming||(this._bgBuffer.innerHTML="",this._bgBuffer.style[o.DomUtil.TRANSFORM]="")},_prepareBgBuffer:function(){var t=this._tileContainer,e=this._bgBuffer,i=this._getLoadedTilesPercentage(e),n=this._getLoadedTilesPercentage(t);return e&&i>.5&&.5>n?(t.style.visibility="hidden",void this._stopLoadingImages(t)):(e.style.visibility="hidden",e.style[o.DomUtil.TRANSFORM]="",this._tileContainer=e,e=this._bgBuffer=t,this._stopLoadingImages(e),void clearTimeout(this._clearBgBufferTimer))},_getLoadedTilesPercentage:function(t){var e,i,n=t.getElementsByTagName("img"),o=0;for(e=0,i=n.length;i>e;e++)n[e].complete&&o++;return o/i},_stopLoadingImages:function(t){var e,i,n,s=Array.prototype.slice.call(t.getElementsByTagName("img"));for(e=0,i=s.length;i>e;e++)n=s[e],n.complete||(n.onload=o.Util.falseFn,n.onerror=o.Util.falseFn,n.src=o.Util.emptyImageUrl,n.parentNode.removeChild(n))}}),o.Map.include({_defaultLocateOptions:{watch:!1,setView:!1,maxZoom:1/0,timeout:1e4,maximumAge:0,enableHighAccuracy:!1},locate:function(t){if(t=this._locateOptions=o.extend(this._defaultLocateOptions,t),!navigator.geolocation)return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var e=o.bind(this._handleGeolocationResponse,this),i=o.bind(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(e,i,t):navigator.geolocation.getCurrentPosition(e,i,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var e=t.code,i=t.message||(1===e?"permission denied":2===e?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:e,message:"Geolocation error: "+i+"."})},_handleGeolocationResponse:function(t){var e=t.coords.latitude,i=t.coords.longitude,n=new o.LatLng(e,i),s=180*t.coords.accuracy/40075017,a=s/Math.cos(o.LatLng.DEG_TO_RAD*e),r=o.latLngBounds([e-s,i-a],[e+s,i+a]),h=this._locateOptions;if(h.setView){var l=Math.min(this.getBoundsZoom(r),h.maxZoom);this.setView(n,l)}var u={latlng:n,bounds:r,timestamp:t.timestamp};for(var c in t.coords)"number"==typeof t.coords[c]&&(u[c]=t.coords[c]);this.fire("locationfound",u)}})}(window,document); \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/vendor/leaflet.loading.js b/assets/www/dist/dist_js/app/vendor/leaflet.loading.js deleted file mode 100644 index 7fb7b780878440160ccfbdf7f9ca4b3304fd4297..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/leaflet.loading.js +++ /dev/null @@ -1,351 +0,0 @@ -/* - * L.Control.Loading is a control that shows a loading indicator when tiles are - * loading or when map-related AJAX requests are taking place. - */ - -(function () { - - var console = window.console || { - error: function () {}, - warn: function () {} - }; - - function defineLeafletLoading(L) { - L.Control.Loading = L.Control.extend({ - options: { - delayIndicator: null, - position: 'topleft', - separate: false, - zoomControl: null, - spinjs: false, - spin: { - lines: 7, - length: 3, - width: 3, - radius: 5, - rotate: 13, - top: "83%" - } - }, - - initialize: function(options) { - L.setOptions(this, options); - this._dataLoaders = {}; - - // Try to set the zoom control this control is attached to from the - // options - if (this.options.zoomControl !== null) { - this.zoomControl = this.options.zoomControl; - } - }, - - onAdd: function(map) { - if (this.options.spinjs && (typeof Spinner !== 'function')) { - return console.error("Leaflet.loading cannot load because you didn't load spin.js (http://fgnass.github.io/spin.js/), even though you set it in options."); - } - this._addLayerListeners(map); - this._addMapListeners(map); - - // Try to set the zoom control this control is attached to from the map - // the control is being added to - if (!this.options.separate && !this.zoomControl) { - if (map.zoomControl) { - this.zoomControl = map.zoomControl; - } else if (map.zoomsliderControl) { - this.zoomControl = map.zoomsliderControl; - } - } - - // Create the loading indicator - var classes = 'leaflet-control-loading'; - var container; - if (this.zoomControl && !this.options.separate) { - // If there is a zoom control, hook into the bottom of it - container = this.zoomControl._container; - // These classes are no longer used as of Leaflet 0.6 - classes += ' leaflet-bar-part-bottom leaflet-bar-part last'; - - // Loading control will be added to the zoom control. So the visible last element is not the - // last dom element anymore. So add the part-bottom class. - L.DomUtil.addClass(this._getLastControlButton(), 'leaflet-bar-part-bottom'); - } - else { - // Otherwise, create a container for the indicator - container = L.DomUtil.create('div', 'leaflet-control-zoom leaflet-control-layer-container leaflet-bar'); - } - this._indicatorContainer = container; - this._indicator = L.DomUtil.create('a', classes, container); - if (this.options.spinjs) { - this._spinner = new Spinner(this.options.spin).spin(); - this._indicator.appendChild(this._spinner.el); - } - return container; - }, - - onRemove: function(map) { - this._removeLayerListeners(map); - this._removeMapListeners(map); - }, - - removeFrom: function (map) { - if (this.zoomControl && !this.options.separate) { - // Override Control.removeFrom() to avoid clobbering the entire - // _container, which is the same as zoomControl's - this._container.removeChild(this._indicator); - this._map = null; - this.onRemove(map); - return this; - } - else { - // If this control is separate from the zoomControl, call the - // parent method so we don't leave behind an empty container - return L.Control.prototype.removeFrom.call(this, map); - } - }, - - addLoader: function(id) { - this._dataLoaders[id] = true; - if (this.options.delayIndicator && !this.delayIndicatorTimeout) { - // If we are delaying showing the indicator and we're not - // already waiting for that delay, set up a timeout. - var that = this; - this.delayIndicatorTimeout = setTimeout(function () { - that.updateIndicator(); - that.delayIndicatorTimeout = null; - }, this.options.delayIndicator); - } - else { - // Otherwise show the indicator immediately - this.updateIndicator(); - } - }, - - removeLoader: function(id) { - delete this._dataLoaders[id]; - this.updateIndicator(); - - // If removing this loader means we're in no danger of loading, - // clear the timeout. This prevents old delays from instantly - // triggering the indicator. - if (this.options.delayIndicator && this.delayIndicatorTimeout && !this.isLoading()) { - clearTimeout(this.delayIndicatorTimeout); - this.delayIndicatorTimeout = null; - } - }, - - updateIndicator: function() { - if (this.isLoading()) { - this._showIndicator(); - } - else { - this._hideIndicator(); - } - }, - - isLoading: function() { - return this._countLoaders() > 0; - }, - - _countLoaders: function() { - var size = 0, key; - for (key in this._dataLoaders) { - if (this._dataLoaders.hasOwnProperty(key)) size++; - } - return size; - }, - - _showIndicator: function() { - // Show loading indicator - L.DomUtil.addClass(this._indicator, 'is-loading'); - L.DomUtil.addClass(this._indicatorContainer, 'is-loading'); - - // If zoomControl exists, make the zoom-out button not last - if (!this.options.separate) { - if (this.zoomControl instanceof L.Control.Zoom) { - L.DomUtil.removeClass(this._getLastControlButton(), 'leaflet-bar-part-bottom'); - } - else if (typeof L.Control.Zoomslider === 'function' && this.zoomControl instanceof L.Control.Zoomslider) { - L.DomUtil.removeClass(this.zoomControl._ui.zoomOut, 'leaflet-bar-part-bottom'); - } - } - }, - - _hideIndicator: function() { - // Hide loading indicator - L.DomUtil.removeClass(this._indicator, 'is-loading'); - L.DomUtil.removeClass(this._indicatorContainer, 'is-loading'); - - // If zoomControl exists, make the zoom-out button last - if (!this.options.separate) { - if (this.zoomControl instanceof L.Control.Zoom) { - L.DomUtil.addClass(this._getLastControlButton(), 'leaflet-bar-part-bottom'); - } - else if (typeof L.Control.Zoomslider === 'function' && this.zoomControl instanceof L.Control.Zoomslider) { - L.DomUtil.addClass(this.zoomControl._ui.zoomOut, 'leaflet-bar-part-bottom'); - } - } - }, - - _getLastControlButton: function() { - var container = this.zoomControl._container, - index = container.children.length - 1; - - // Find the last visible control button that is not our loading - // indicator - while (index > 0) { - var button = container.children[index]; - if (!(this._indicator === button || button.offsetWidth === 0 || button.offsetHeight === 0)) { - break; - } - index--; - } - - return container.children[index]; - }, - - _handleLoading: function(e) { - this.addLoader(this.getEventId(e)); - }, - - _handleBaseLayerChange: function (e) { - var that = this; - - // Check for a target 'layer' that contains multiple layers, such as - // L.LayerGroup. This will happen if you have an L.LayerGroup in an - // L.Control.Layers. - if (e.layer && e.layer.eachLayer && typeof e.layer.eachLayer === 'function') { - e.layer.eachLayer(function (layer) { - that._handleBaseLayerChange({ layer: layer }); - }); - } - else { - // If we're changing to a canvas layer, don't handle loading - // as canvas layers will not fire load events. - if (!(L.TileLayer.Canvas && e.layer instanceof L.TileLayer.Canvas)) { - that._handleLoading(e); - } - } - }, - - _handleLoad: function(e) { - this.removeLoader(this.getEventId(e)); - }, - - getEventId: function(e) { - if (e.id) { - return e.id; - } - else if (e.layer) { - return e.layer._leaflet_id; - } - return e.target._leaflet_id; - }, - - _layerAdd: function(e) { - if (!e.layer || !e.layer.on) return - try { - e.layer.on({ - loading: this._handleLoading, - load: this._handleLoad - }, this); - } - catch (exception) { - console.warn('L.Control.Loading: Tried and failed to add ' + - ' event handlers to layer', e.layer); - console.warn('L.Control.Loading: Full details', exception); - } - }, - - _layerRemove: function(e) { - if (!e.layer || !e.layer.off) return; - try { - e.layer.off({ - loading: this._handleLoading, - load: this._handleLoad - }, this); - } - catch (exception) { - console.warn('L.Control.Loading: Tried and failed to remove ' + - 'event handlers from layer', e.layer); - console.warn('L.Control.Loading: Full details', exception); - } - }, - - _addLayerListeners: function(map) { - // Add listeners for begin and end of load to any layers already on the - // map - map.eachLayer(function(layer) { - if (!layer.on) return; - layer.on({ - loading: this._handleLoading, - load: this._handleLoad - }, this); - }, this); - - // When a layer is added to the map, add listeners for begin and end - // of load - map.on('layeradd', this._layerAdd, this); - map.on('layerremove', this._layerRemove, this); - }, - - _removeLayerListeners: function(map) { - // Remove listeners for begin and end of load from all layers - map.eachLayer(function(layer) { - if (!layer.off) return; - layer.off({ - loading: this._handleLoading, - load: this._handleLoad - }, this); - }, this); - - // Remove layeradd/layerremove listener from map - map.off('layeradd', this._layerAdd, this); - map.off('layerremove', this._layerRemove, this); - }, - - _addMapListeners: function(map) { - // Add listeners to the map for (custom) dataloading and dataload - // events, eg, for AJAX calls that affect the map but will not be - // reflected in the above layer events. - map.on({ - baselayerchange: this._handleBaseLayerChange, - dataloading: this._handleLoading, - dataload: this._handleLoad, - layerremove: this._handleLoad - }, this); - }, - - _removeMapListeners: function(map) { - map.off({ - baselayerchange: this._handleBaseLayerChange, - dataloading: this._handleLoading, - dataload: this._handleLoad, - layerremove: this._handleLoad - }, this); - } - }); - - L.Map.addInitHook(function () { - if (this.options.loadingControl) { - this.loadingControl = new L.Control.Loading(); - this.addControl(this.loadingControl); - } - }); - - L.Control.loading = function(options) { - return new L.Control.Loading(options); - }; - } - - if (typeof define === 'function' && define.amd) { - // Try to add leaflet.loading to Leaflet using AMD - define(['leaflet'], function (L) { - defineLeafletLoading(L); - }); - } - else { - // Else use the global L - defineLeafletLoading(L); - } - -})(); diff --git a/assets/www/dist/dist_js/app/vendor/leaflet.markercluster.js b/assets/www/dist/dist_js/app/vendor/leaflet.markercluster.js deleted file mode 100644 index c3fa30e302e1d3e403e867fb79c4c870c8b63237..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/leaflet.markercluster.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - Leaflet.markercluster, Provides Beautiful Animated Marker Clustering functionality for Leaflet, a JS library for interactive maps. - https://github.com/Leaflet/Leaflet.markercluster - (c) 2012-2013, Dave Leaver, smartrak -*/ -!function(t,e,i){L.MarkerClusterGroup=L.FeatureGroup.extend({options:{maxClusterRadius:80,iconCreateFunction:null,spiderfyOnMaxZoom:!0,showCoverageOnHover:!0,zoomToBoundsOnClick:!0,singleMarkerMode:!1,disableClusteringAtZoom:null,removeOutsideVisibleBounds:!0,animate:!0,animateAddingMarkers:!1,spiderfyDistanceMultiplier:1,spiderLegPolylineOptions:{weight:1.5,color:"#222",opacity:.5},chunkedLoading:!1,chunkInterval:200,chunkDelay:50,chunkProgress:null,polygonOptions:{}},initialize:function(t){L.Util.setOptions(this,t),this.options.iconCreateFunction||(this.options.iconCreateFunction=this._defaultIconCreateFunction),this._featureGroup=L.featureGroup(),this._featureGroup.on(L.FeatureGroup.EVENTS,this._propagateEvent,this),this._nonPointGroup=L.featureGroup(),this._nonPointGroup.on(L.FeatureGroup.EVENTS,this._propagateEvent,this),this._inZoomAnimation=0,this._needsClustering=[],this._needsRemoving=[],this._currentShownBounds=null,this._queue=[];var e=L.DomUtil.TRANSITION&&this.options.animate;L.extend(this,e?this._withAnimation:this._noAnimation),this._markerCluster=e?L.MarkerCluster:L.MarkerClusterNonAnimated},addLayer:function(t){if(t instanceof L.LayerGroup){var e=[];for(var i in t._layers)e.push(t._layers[i]);return this.addLayers(e)}if(!t.getLatLng)return this._nonPointGroup.addLayer(t),this;if(!this._map)return this._needsClustering.push(t),this;if(this.hasLayer(t))return this;this._unspiderfy&&this._unspiderfy(),this._addLayer(t,this._maxZoom),this._topClusterLevel._recalculateBounds();var n=t,s=this._map.getZoom();if(t.__parent)for(;n.__parent._zoom>=s;)n=n.__parent;return this._currentShownBounds.contains(n.getLatLng())&&(this.options.animateAddingMarkers?this._animationAddLayer(t,n):this._animationAddLayerNonAnimated(t,n)),this},removeLayer:function(t){if(t instanceof L.LayerGroup){var e=[];for(var i in t._layers)e.push(t._layers[i]);return this.removeLayers(e)}return t.getLatLng?this._map?t.__parent?(this._unspiderfy&&(this._unspiderfy(),this._unspiderfyLayer(t)),this._removeLayer(t,!0),this._topClusterLevel._recalculateBounds(),this._featureGroup.hasLayer(t)&&(this._featureGroup.removeLayer(t),t.clusterShow&&t.clusterShow()),this):this:(!this._arraySplice(this._needsClustering,t)&&this.hasLayer(t)&&this._needsRemoving.push(t),this):(this._nonPointGroup.removeLayer(t),this)},addLayers:function(t){var e,i,n,s,r=this._featureGroup,o=this._nonPointGroup,a=this.options.chunkedLoading,h=this.options.chunkInterval,u=this.options.chunkProgress;if(this._map){var _=0,l=(new Date).getTime(),d=L.bind(function(){for(var e=(new Date).getTime();_<t.length;_++){if(a&&0===_%200){var i=(new Date).getTime()-e;if(i>h)break}if(s=t[_],s.getLatLng){if(!this.hasLayer(s)&&(this._addLayer(s,this._maxZoom),s.__parent&&2===s.__parent.getChildCount())){var n=s.__parent.getAllChildMarkers(),c=n[0]===s?n[1]:n[0];r.removeLayer(c)}}else o.addLayer(s)}u&&u(_,t.length,(new Date).getTime()-l),_===t.length?(this._topClusterLevel._recalculateBounds(),this._featureGroup.eachLayer(function(t){t instanceof L.MarkerCluster&&t._iconNeedsUpdate&&t._updateIcon()}),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds)):setTimeout(d,this.options.chunkDelay)},this);d()}else{for(e=[],i=0,n=t.length;n>i;i++)s=t[i],s.getLatLng?this.hasLayer(s)||e.push(s):o.addLayer(s);this._needsClustering=this._needsClustering.concat(e)}return this},removeLayers:function(t){var e,i,n,s=this._featureGroup,r=this._nonPointGroup;if(!this._map){for(e=0,i=t.length;i>e;e++)n=t[e],this._arraySplice(this._needsClustering,n),r.removeLayer(n),this.hasLayer(n)&&this._needsRemoving.push(n);return this}if(this._unspiderfy)for(this._unspiderfy(),e=0,i=t.length;i>e;e++)n=t[e],this._unspiderfyLayer(n);for(e=0,i=t.length;i>e;e++)n=t[e],n.__parent?(this._removeLayer(n,!0,!0),s.hasLayer(n)&&(s.removeLayer(n),n.clusterShow&&n.clusterShow())):r.removeLayer(n);return this._topClusterLevel._recalculateBounds(),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds),s.eachLayer(function(t){t instanceof L.MarkerCluster&&t._updateIcon()}),this},clearLayers:function(){return this._map||(this._needsClustering=[],delete this._gridClusters,delete this._gridUnclustered),this._noanimationUnspiderfy&&this._noanimationUnspiderfy(),this._featureGroup.clearLayers(),this._nonPointGroup.clearLayers(),this.eachLayer(function(t){delete t.__parent}),this._map&&this._generateInitialClusters(),this},getBounds:function(){var t=new L.LatLngBounds;this._topClusterLevel&&t.extend(this._topClusterLevel._bounds);for(var e=this._needsClustering.length-1;e>=0;e--)t.extend(this._needsClustering[e].getLatLng());return t.extend(this._nonPointGroup.getBounds()),t},eachLayer:function(t,e){var i,n=this._needsClustering.slice();for(this._topClusterLevel&&this._topClusterLevel.getAllChildMarkers(n),i=n.length-1;i>=0;i--)t.call(e,n[i]);this._nonPointGroup.eachLayer(t,e)},getLayers:function(){var t=[];return this.eachLayer(function(e){t.push(e)}),t},getLayer:function(t){var e=null;return t=parseInt(t,10),this.eachLayer(function(i){L.stamp(i)===t&&(e=i)}),e},hasLayer:function(t){if(!t)return!1;var e,i=this._needsClustering;for(e=i.length-1;e>=0;e--)if(i[e]===t)return!0;for(i=this._needsRemoving,e=i.length-1;e>=0;e--)if(i[e]===t)return!1;return!(!t.__parent||t.__parent._group!==this)||this._nonPointGroup.hasLayer(t)},zoomToShowLayer:function(t,e){"function"!=typeof e&&(e=function(){});var i=function(){!t._icon&&!t.__parent._icon||this._inZoomAnimation||(this._map.off("moveend",i,this),this.off("animationend",i,this),t._icon?e():t.__parent._icon&&(this.once("spiderfied",e,this),t.__parent.spiderfy()))};if(t._icon&&this._map.getBounds().contains(t.getLatLng()))e();else if(t.__parent._zoom<this._map.getZoom())this._map.on("moveend",i,this),this._map.panTo(t.getLatLng());else{var n=function(){this._map.off("movestart",n,this),n=null};this._map.on("movestart",n,this),this._map.on("moveend",i,this),this.on("animationend",i,this),t.__parent.zoomToBounds(),n&&i.call(this)}},onAdd:function(t){this._map=t;var e,i,n;if(!isFinite(this._map.getMaxZoom()))throw"Map has no maxZoom specified";for(this._featureGroup.onAdd(t),this._nonPointGroup.onAdd(t),this._gridClusters||this._generateInitialClusters(),this._maxLat=t.options.crs.projection.MAX_LATITUDE,e=0,i=this._needsRemoving.length;i>e;e++)n=this._needsRemoving[e],this._removeLayer(n,!0);this._needsRemoving=[],this._zoom=this._map.getZoom(),this._currentShownBounds=this._getExpandedVisibleBounds(),this._map.on("zoomend",this._zoomEnd,this),this._map.on("moveend",this._moveEnd,this),this._spiderfierOnAdd&&this._spiderfierOnAdd(),this._bindEvents(),i=this._needsClustering,this._needsClustering=[],this.addLayers(i)},onRemove:function(t){t.off("zoomend",this._zoomEnd,this),t.off("moveend",this._moveEnd,this),this._unbindEvents(),this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim",""),this._spiderfierOnRemove&&this._spiderfierOnRemove(),delete this._maxLat,this._hideCoverage(),this._featureGroup.onRemove(t),this._nonPointGroup.onRemove(t),this._featureGroup.clearLayers(),this._map=null},getVisibleParent:function(t){for(var e=t;e&&!e._icon;)e=e.__parent;return e||null},_arraySplice:function(t,e){for(var i=t.length-1;i>=0;i--)if(t[i]===e)return t.splice(i,1),!0},_removeFromGridUnclustered:function(t,e){for(var i=this._map,n=this._gridUnclustered;e>=0&&n[e].removeObject(t,i.project(t.getLatLng(),e));e--);},_removeLayer:function(t,e,i){var n=this._gridClusters,s=this._gridUnclustered,r=this._featureGroup,o=this._map;e&&this._removeFromGridUnclustered(t,this._maxZoom);var a,h=t.__parent,u=h._markers;for(this._arraySplice(u,t);h&&(h._childCount--,h._boundsNeedUpdate=!0,!(h._zoom<0));)e&&h._childCount<=1?(a=h._markers[0]===t?h._markers[1]:h._markers[0],n[h._zoom].removeObject(h,o.project(h._cLatLng,h._zoom)),s[h._zoom].addObject(a,o.project(a.getLatLng(),h._zoom)),this._arraySplice(h.__parent._childClusters,h),h.__parent._markers.push(a),a.__parent=h.__parent,h._icon&&(r.removeLayer(h),i||r.addLayer(a))):i&&h._icon||h._updateIcon(),h=h.__parent;delete t.__parent},_isOrIsParent:function(t,e){for(;e;){if(t===e)return!0;e=e.parentNode}return!1},_propagateEvent:function(t){if(t.layer instanceof L.MarkerCluster){if(t.originalEvent&&this._isOrIsParent(t.layer._icon,t.originalEvent.relatedTarget))return;t.type="cluster"+t.type}this.fire(t.type,t)},_defaultIconCreateFunction:function(t){var e=t.getChildCount(),i=" marker-cluster-";return i+=10>e?"small":100>e?"medium":"large",new L.DivIcon({html:"<div><span>"+e+"</span></div>",className:"marker-cluster"+i,iconSize:new L.Point(40,40)})},_bindEvents:function(){var t=this._map,e=this.options.spiderfyOnMaxZoom,i=this.options.showCoverageOnHover,n=this.options.zoomToBoundsOnClick;(e||n)&&this.on("clusterclick",this._zoomOrSpiderfy,this),i&&(this.on("clustermouseover",this._showCoverage,this),this.on("clustermouseout",this._hideCoverage,this),t.on("zoomend",this._hideCoverage,this))},_zoomOrSpiderfy:function(t){for(var e=t.layer,i=e;1===i._childClusters.length;)i=i._childClusters[0];i._zoom===this._maxZoom&&i._childCount===e._childCount?this.options.spiderfyOnMaxZoom&&e.spiderfy():this.options.zoomToBoundsOnClick&&e.zoomToBounds(),t.originalEvent&&13===t.originalEvent.keyCode&&this._map._container.focus()},_showCoverage:function(t){var e=this._map;this._inZoomAnimation||(this._shownPolygon&&e.removeLayer(this._shownPolygon),t.layer.getChildCount()>2&&t.layer!==this._spiderfied&&(this._shownPolygon=new L.Polygon(t.layer.getConvexHull(),this.options.polygonOptions),e.addLayer(this._shownPolygon)))},_hideCoverage:function(){this._shownPolygon&&(this._map.removeLayer(this._shownPolygon),this._shownPolygon=null)},_unbindEvents:function(){var t=this.options.spiderfyOnMaxZoom,e=this.options.showCoverageOnHover,i=this.options.zoomToBoundsOnClick,n=this._map;(t||i)&&this.off("clusterclick",this._zoomOrSpiderfy,this),e&&(this.off("clustermouseover",this._showCoverage,this),this.off("clustermouseout",this._hideCoverage,this),n.off("zoomend",this._hideCoverage,this))},_zoomEnd:function(){this._map&&(this._mergeSplitClusters(),this._zoom=this._map._zoom,this._currentShownBounds=this._getExpandedVisibleBounds())},_moveEnd:function(){if(!this._inZoomAnimation){var t=this._getExpandedVisibleBounds();this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,this._zoom,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._map._zoom,t),this._currentShownBounds=t}},_generateInitialClusters:function(){var t=this._map.getMaxZoom(),e=this.options.maxClusterRadius,i=e;"function"!=typeof e&&(i=function(){return e}),this.options.disableClusteringAtZoom&&(t=this.options.disableClusteringAtZoom-1),this._maxZoom=t,this._gridClusters={},this._gridUnclustered={};for(var n=t;n>=0;n--)this._gridClusters[n]=new L.DistanceGrid(i(n)),this._gridUnclustered[n]=new L.DistanceGrid(i(n));this._topClusterLevel=new this._markerCluster(this,-1)},_addLayer:function(t,e){var i,n,s=this._gridClusters,r=this._gridUnclustered;for(this.options.singleMarkerMode&&this._overrideMarkerIcon(t);e>=0;e--){i=this._map.project(t.getLatLng(),e);var o=s[e].getNearObject(i);if(o)return o._addChild(t),t.__parent=o,void 0;if(o=r[e].getNearObject(i)){var a=o.__parent;a&&this._removeLayer(o,!1);var h=new this._markerCluster(this,e,o,t);s[e].addObject(h,this._map.project(h._cLatLng,e)),o.__parent=h,t.__parent=h;var u=h;for(n=e-1;n>a._zoom;n--)u=new this._markerCluster(this,n,u),s[n].addObject(u,this._map.project(o.getLatLng(),n));return a._addChild(u),this._removeFromGridUnclustered(o,e),void 0}r[e].addObject(t,i)}this._topClusterLevel._addChild(t),t.__parent=this._topClusterLevel},_enqueue:function(t){this._queue.push(t),this._queueTimeout||(this._queueTimeout=setTimeout(L.bind(this._processQueue,this),300))},_processQueue:function(){for(var t=0;t<this._queue.length;t++)this._queue[t].call(this);this._queue.length=0,clearTimeout(this._queueTimeout),this._queueTimeout=null},_mergeSplitClusters:function(){this._processQueue(),this._zoom<this._map._zoom&&this._currentShownBounds.intersects(this._getExpandedVisibleBounds())?(this._animationStart(),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,this._zoom,this._getExpandedVisibleBounds()),this._animationZoomIn(this._zoom,this._map._zoom)):this._zoom>this._map._zoom?(this._animationStart(),this._animationZoomOut(this._zoom,this._map._zoom)):this._moveEnd()},_getExpandedVisibleBounds:function(){return this.options.removeOutsideVisibleBounds?L.Browser.mobile?this._checkBoundsMaxLat(this._map.getBounds()):this._checkBoundsMaxLat(this._map.getBounds().pad(1)):this._mapBoundsInfinite},_checkBoundsMaxLat:function(t){var e=this._maxLat;return e!==i&&(t.getNorth()>=e&&(t._northEast.lat=1/0),t.getSouth()<=-e&&(t._southWest.lat=-1/0)),t},_animationAddLayerNonAnimated:function(t,e){if(e===t)this._featureGroup.addLayer(t);else if(2===e._childCount){e._addToMap();var i=e.getAllChildMarkers();this._featureGroup.removeLayer(i[0]),this._featureGroup.removeLayer(i[1])}else e._updateIcon()},_overrideMarkerIcon:function(t){var e=t.options.icon=this.options.iconCreateFunction({getChildCount:function(){return 1},getAllChildMarkers:function(){return[t]}});return e}}),L.MarkerClusterGroup.include({_mapBoundsInfinite:new L.LatLngBounds(new L.LatLng(-1/0,-1/0),new L.LatLng(1/0,1/0))}),L.MarkerClusterGroup.include({_noAnimation:{_animationStart:function(){},_animationZoomIn:function(t,e){this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds()),this.fire("animationend")},_animationZoomOut:function(t,e){this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds()),this.fire("animationend")},_animationAddLayer:function(t,e){this._animationAddLayerNonAnimated(t,e)}},_withAnimation:{_animationStart:function(){this._map._mapPane.className+=" leaflet-cluster-anim",this._inZoomAnimation++},_animationZoomIn:function(t,e){var i,n=this._getExpandedVisibleBounds(),s=this._featureGroup;this._topClusterLevel._recursively(n,t,0,function(r){var o,a=r._latlng,h=r._markers;for(n.contains(a)||(a=null),r._isSingleParent()&&t+1===e?(s.removeLayer(r),r._recursivelyAddChildrenToMap(null,e,n)):(r.clusterHide(),r._recursivelyAddChildrenToMap(a,e,n)),i=h.length-1;i>=0;i--)o=h[i],n.contains(o._latlng)||s.removeLayer(o)}),this._forceLayout(),this._topClusterLevel._recursivelyBecomeVisible(n,e),s.eachLayer(function(t){t instanceof L.MarkerCluster||!t._icon||t.clusterShow()}),this._topClusterLevel._recursively(n,t,e,function(t){t._recursivelyRestoreChildPositions(e)}),this._enqueue(function(){this._topClusterLevel._recursively(n,t,0,function(t){s.removeLayer(t),t.clusterShow()}),this._animationEnd()})},_animationZoomOut:function(t,e){this._animationZoomOutSingle(this._topClusterLevel,t-1,e),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds()),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t,this._getExpandedVisibleBounds())},_animationAddLayer:function(t,e){var i=this,n=this._featureGroup;n.addLayer(t),e!==t&&(e._childCount>2?(e._updateIcon(),this._forceLayout(),this._animationStart(),t._setPos(this._map.latLngToLayerPoint(e.getLatLng())),t.clusterHide(),this._enqueue(function(){n.removeLayer(t),t.clusterShow(),i._animationEnd()})):(this._forceLayout(),i._animationStart(),i._animationZoomOutSingle(e,this._map.getMaxZoom(),this._map.getZoom())))}},_animationZoomOutSingle:function(t,e,i){var n=this._getExpandedVisibleBounds();t._recursivelyAnimateChildrenInAndAddSelfToMap(n,e+1,i);var s=this;this._forceLayout(),t._recursivelyBecomeVisible(n,i),this._enqueue(function(){if(1===t._childCount){var r=t._markers[0];r.setLatLng(r.getLatLng()),r.clusterShow&&r.clusterShow()}else t._recursively(n,i,0,function(t){t._recursivelyRemoveChildrenFromMap(n,e+1)});s._animationEnd()})},_animationEnd:function(){this._map&&(this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim","")),this._inZoomAnimation--,this.fire("animationend")},_forceLayout:function(){L.Util.falseFn(e.body.offsetWidth)}}),L.markerClusterGroup=function(t){return new L.MarkerClusterGroup(t)},L.MarkerCluster=L.Marker.extend({initialize:function(t,e,i,n){L.Marker.prototype.initialize.call(this,i?i._cLatLng||i.getLatLng():new L.LatLng(0,0),{icon:this}),this._group=t,this._zoom=e,this._markers=[],this._childClusters=[],this._childCount=0,this._iconNeedsUpdate=!0,this._boundsNeedUpdate=!0,this._bounds=new L.LatLngBounds,i&&this._addChild(i),n&&this._addChild(n)},getAllChildMarkers:function(t){t=t||[];for(var e=this._childClusters.length-1;e>=0;e--)this._childClusters[e].getAllChildMarkers(t);for(var i=this._markers.length-1;i>=0;i--)t.push(this._markers[i]);return t},getChildCount:function(){return this._childCount},zoomToBounds:function(){for(var t,e=this._childClusters.slice(),i=this._group._map,n=i.getBoundsZoom(this._bounds),s=this._zoom+1,r=i.getZoom();e.length>0&&n>s;){s++;var o=[];for(t=0;t<e.length;t++)o=o.concat(e[t]._childClusters);e=o}n>s?this._group._map.setView(this._latlng,s):r>=n?this._group._map.setView(this._latlng,r+1):this._group._map.fitBounds(this._bounds)},getBounds:function(){var t=new L.LatLngBounds;return t.extend(this._bounds),t},_updateIcon:function(){this._iconNeedsUpdate=!0,this._icon&&this.setIcon(this)},createIcon:function(){return this._iconNeedsUpdate&&(this._iconObj=this._group.options.iconCreateFunction(this),this._iconNeedsUpdate=!1),this._iconObj.createIcon()},createShadow:function(){return this._iconObj.createShadow()},_addChild:function(t,e){this._iconNeedsUpdate=!0,this._boundsNeedUpdate=!0,this._setClusterCenter(t),t instanceof L.MarkerCluster?(e||(this._childClusters.push(t),t.__parent=this),this._childCount+=t._childCount):(e||this._markers.push(t),this._childCount++),this.__parent&&this.__parent._addChild(t,!0)},_setClusterCenter:function(t){this._cLatLng||(this._cLatLng=t._cLatLng||t._latlng)},_resetBounds:function(){var t=this._bounds;t._southWest&&(t._southWest.lat=1/0,t._southWest.lng=1/0),t._northEast&&(t._northEast.lat=-1/0,t._northEast.lng=-1/0)},_recalculateBounds:function(){var t,e,i,n,s=this._markers,r=this._childClusters,o=0,a=0,h=this._childCount;if(0!==h){for(this._resetBounds(),t=0;t<s.length;t++)i=s[t]._latlng,this._bounds.extend(i),o+=i.lat,a+=i.lng;for(t=0;t<r.length;t++)e=r[t],e._boundsNeedUpdate&&e._recalculateBounds(),this._bounds.extend(e._bounds),i=e._wLatLng,n=e._childCount,o+=i.lat*n,a+=i.lng*n;this._latlng=this._wLatLng=new L.LatLng(o/h,a/h),this._boundsNeedUpdate=!1}},_addToMap:function(t){t&&(this._backupLatlng=this._latlng,this.setLatLng(t)),this._group._featureGroup.addLayer(this)},_recursivelyAnimateChildrenIn:function(t,e,i){this._recursively(t,0,i-1,function(t){var i,n,s=t._markers;for(i=s.length-1;i>=0;i--)n=s[i],n._icon&&(n._setPos(e),n.clusterHide())},function(t){var i,n,s=t._childClusters;for(i=s.length-1;i>=0;i--)n=s[i],n._icon&&(n._setPos(e),n.clusterHide())})},_recursivelyAnimateChildrenInAndAddSelfToMap:function(t,e,i){this._recursively(t,i,0,function(n){n._recursivelyAnimateChildrenIn(t,n._group._map.latLngToLayerPoint(n.getLatLng()).round(),e),n._isSingleParent()&&e-1===i?(n.clusterShow(),n._recursivelyRemoveChildrenFromMap(t,e)):n.clusterHide(),n._addToMap()})},_recursivelyBecomeVisible:function(t,e){this._recursively(t,0,e,null,function(t){t.clusterShow()})},_recursivelyAddChildrenToMap:function(t,e,i){this._recursively(i,-1,e,function(n){if(e!==n._zoom)for(var s=n._markers.length-1;s>=0;s--){var r=n._markers[s];i.contains(r._latlng)&&(t&&(r._backupLatlng=r.getLatLng(),r.setLatLng(t),r.clusterHide&&r.clusterHide()),n._group._featureGroup.addLayer(r))}},function(e){e._addToMap(t)})},_recursivelyRestoreChildPositions:function(t){for(var e=this._markers.length-1;e>=0;e--){var i=this._markers[e];i._backupLatlng&&(i.setLatLng(i._backupLatlng),delete i._backupLatlng)}if(t-1===this._zoom)for(var n=this._childClusters.length-1;n>=0;n--)this._childClusters[n]._restorePosition();else for(var s=this._childClusters.length-1;s>=0;s--)this._childClusters[s]._recursivelyRestoreChildPositions(t)},_restorePosition:function(){this._backupLatlng&&(this.setLatLng(this._backupLatlng),delete this._backupLatlng)},_recursivelyRemoveChildrenFromMap:function(t,e,i){var n,s;this._recursively(t,-1,e-1,function(t){for(s=t._markers.length-1;s>=0;s--)n=t._markers[s],i&&i.contains(n._latlng)||(t._group._featureGroup.removeLayer(n),n.clusterShow&&n.clusterShow())},function(t){for(s=t._childClusters.length-1;s>=0;s--)n=t._childClusters[s],i&&i.contains(n._latlng)||(t._group._featureGroup.removeLayer(n),n.clusterShow&&n.clusterShow())})},_recursively:function(t,e,i,n,s){var r,o,a=this._childClusters,h=this._zoom;if(e>h)for(r=a.length-1;r>=0;r--)o=a[r],t.intersects(o._bounds)&&o._recursively(t,e,i,n,s);else if(n&&n(this),s&&this._zoom===i&&s(this),i>h)for(r=a.length-1;r>=0;r--)o=a[r],t.intersects(o._bounds)&&o._recursively(t,e,i,n,s)},_isSingleParent:function(){return this._childClusters.length>0&&this._childClusters[0]._childCount===this._childCount}}),L.Marker.include({clusterHide:function(){return this.options.opacityWhenUnclustered=this.options.opacity||1,this.setOpacity(0)},clusterShow:function(){var t=this.setOpacity(this.options.opacity||this.options.opacityWhenUnclustered);return delete this.options.opacityWhenUnclustered,t}}),L.DistanceGrid=function(t){this._cellSize=t,this._sqCellSize=t*t,this._grid={},this._objectPoint={}},L.DistanceGrid.prototype={addObject:function(t,e){var i=this._getCoord(e.x),n=this._getCoord(e.y),s=this._grid,r=s[n]=s[n]||{},o=r[i]=r[i]||[],a=L.Util.stamp(t);this._objectPoint[a]=e,o.push(t)},updateObject:function(t,e){this.removeObject(t),this.addObject(t,e)},removeObject:function(t,e){var i,n,s=this._getCoord(e.x),r=this._getCoord(e.y),o=this._grid,a=o[r]=o[r]||{},h=a[s]=a[s]||[];for(delete this._objectPoint[L.Util.stamp(t)],i=0,n=h.length;n>i;i++)if(h[i]===t)return h.splice(i,1),1===n&&delete a[s],!0},eachObject:function(t,e){var i,n,s,r,o,a,h,u=this._grid;for(i in u){o=u[i];for(n in o)for(a=o[n],s=0,r=a.length;r>s;s++)h=t.call(e,a[s]),h&&(s--,r--)}},getNearObject:function(t){var e,i,n,s,r,o,a,h,u=this._getCoord(t.x),_=this._getCoord(t.y),l=this._objectPoint,d=this._sqCellSize,c=null;for(e=_-1;_+1>=e;e++)if(s=this._grid[e])for(i=u-1;u+1>=i;i++)if(r=s[i])for(n=0,o=r.length;o>n;n++)a=r[n],h=this._sqDist(l[L.Util.stamp(a)],t),d>h&&(d=h,c=a);return c},_getCoord:function(t){return Math.floor(t/this._cellSize)},_sqDist:function(t,e){var i=e.x-t.x,n=e.y-t.y;return i*i+n*n}},function(){L.QuickHull={getDistant:function(t,e){var i=e[1].lat-e[0].lat,n=e[0].lng-e[1].lng;return n*(t.lat-e[0].lat)+i*(t.lng-e[0].lng)},findMostDistantPointFromBaseLine:function(t,e){var i,n,s,r=0,o=null,a=[];for(i=e.length-1;i>=0;i--)n=e[i],s=this.getDistant(n,t),s>0&&(a.push(n),s>r&&(r=s,o=n));return{maxPoint:o,newPoints:a}},buildConvexHull:function(t,e){var i=[],n=this.findMostDistantPointFromBaseLine(t,e);return n.maxPoint?(i=i.concat(this.buildConvexHull([t[0],n.maxPoint],n.newPoints)),i=i.concat(this.buildConvexHull([n.maxPoint,t[1]],n.newPoints))):[t[0]]},getConvexHull:function(t){var e,i=!1,n=!1,s=!1,r=!1,o=null,a=null,h=null,u=null,_=null,l=null;for(e=t.length-1;e>=0;e--){var d=t[e];(i===!1||d.lat>i)&&(o=d,i=d.lat),(n===!1||d.lat<n)&&(a=d,n=d.lat),(s===!1||d.lng>s)&&(h=d,s=d.lng),(r===!1||d.lng<r)&&(u=d,r=d.lng)}n!==i?(l=a,_=o):(l=u,_=h);var c=[].concat(this.buildConvexHull([l,_],t),this.buildConvexHull([_,l],t));return c}}}(),L.MarkerCluster.include({getConvexHull:function(){var t,e,i=this.getAllChildMarkers(),n=[];for(e=i.length-1;e>=0;e--)t=i[e].getLatLng(),n.push(t);return L.QuickHull.getConvexHull(n)}}),L.MarkerCluster.include({_2PI:2*Math.PI,_circleFootSeparation:25,_circleStartAngle:Math.PI/6,_spiralFootSeparation:28,_spiralLengthStart:11,_spiralLengthFactor:5,_circleSpiralSwitchover:9,spiderfy:function(){if(this._group._spiderfied!==this&&!this._group._inZoomAnimation){var t,e=this.getAllChildMarkers(),i=this._group,n=i._map,s=n.latLngToLayerPoint(this._latlng);this._group._unspiderfy(),this._group._spiderfied=this,e.length>=this._circleSpiralSwitchover?t=this._generatePointsSpiral(e.length,s):(s.y+=10,t=this._generatePointsCircle(e.length,s)),this._animationSpiderfy(e,t)}},unspiderfy:function(t){this._group._inZoomAnimation||(this._animationUnspiderfy(t),this._group._spiderfied=null)},_generatePointsCircle:function(t,e){var i,n,s=this._group.options.spiderfyDistanceMultiplier*this._circleFootSeparation*(2+t),r=s/this._2PI,o=this._2PI/t,a=[];for(a.length=t,i=t-1;i>=0;i--)n=this._circleStartAngle+i*o,a[i]=new L.Point(e.x+r*Math.cos(n),e.y+r*Math.sin(n))._round();return a},_generatePointsSpiral:function(t,e){var i,n=this._group.options.spiderfyDistanceMultiplier,s=n*this._spiralLengthStart,r=n*this._spiralFootSeparation,o=n*this._spiralLengthFactor*this._2PI,a=0,h=[];for(h.length=t,i=t-1;i>=0;i--)a+=r/s+5e-4*i,h[i]=new L.Point(e.x+s*Math.cos(a),e.y+s*Math.sin(a))._round(),s+=o/a;return h},_noanimationUnspiderfy:function(){var t,e,i=this._group,n=i._map,s=i._featureGroup,r=this.getAllChildMarkers();for(this.setOpacity(1),e=r.length-1;e>=0;e--)t=r[e],s.removeLayer(t),t._preSpiderfyLatlng&&(t.setLatLng(t._preSpiderfyLatlng),delete t._preSpiderfyLatlng),t.setZIndexOffset&&t.setZIndexOffset(0),t._spiderLeg&&(n.removeLayer(t._spiderLeg),delete t._spiderLeg);i.fire("unspiderfied",{cluster:this,markers:r}),i._spiderfied=null}}),L.MarkerClusterNonAnimated=L.MarkerCluster.extend({_animationSpiderfy:function(t,e){var i,n,s,r,o=this._group,a=o._map,h=o._featureGroup,u=this._group.options.spiderLegPolylineOptions;for(i=0;i<t.length;i++)r=a.layerPointToLatLng(e[i]),n=t[i],s=new L.Polyline([this._latlng,r],u),a.addLayer(s),n._spiderLeg=s,n._preSpiderfyLatlng=n._latlng,n.setLatLng(r),n.setZIndexOffset&&n.setZIndexOffset(1e6),h.addLayer(n);this.setOpacity(.3),o.fire("spiderfied",{cluster:this,markers:t})},_animationUnspiderfy:function(){this._noanimationUnspiderfy()}}),L.MarkerCluster.include({_animationSpiderfy:function(t,e){var n,s,r,o,a,h,u=this,_=this._group,l=_._map,d=_._featureGroup,c=this._latlng,p=l.latLngToLayerPoint(c),f=L.Path.SVG,m=L.extend({},this._group.options.spiderLegPolylineOptions),g=m.opacity;for(g===i&&(g=L.MarkerClusterGroup.prototype.options.spiderLegPolylineOptions.opacity),f?(m.opacity=0,m.className=(m.className||"")+" leaflet-cluster-spider-leg"):m.opacity=g,n=0;n<t.length;n++)s=t[n],h=l.layerPointToLatLng(e[n]),r=new L.Polyline([c,h],m),l.addLayer(r),s._spiderLeg=r,f&&(o=r._path,a=o.getTotalLength()+.1,o.style.strokeDasharray=a,o.style.strokeDashoffset=a),s.setZIndexOffset&&s.setZIndexOffset(1e6),s.clusterHide&&s.clusterHide(),d.addLayer(s),s._setPos&&s._setPos(p);for(_._forceLayout(),_._animationStart(),n=t.length-1;n>=0;n--)h=l.layerPointToLatLng(e[n]),s=t[n],s._preSpiderfyLatlng=s._latlng,s.setLatLng(h),s.clusterShow&&s.clusterShow(),f&&(r=s._spiderLeg,o=r._path,o.style.strokeDashoffset=0,r.setStyle({opacity:g}));this.setOpacity(.3),setTimeout(function(){_._animationEnd(),_.fire("spiderfied",{cluster:u,markers:t})},200)},_animationUnspiderfy:function(t){var e,i,n,s,r,o,a=this,h=this._group,u=h._map,_=h._featureGroup,l=t?u._latLngToNewLayerPoint(this._latlng,t.zoom,t.center):u.latLngToLayerPoint(this._latlng),d=this.getAllChildMarkers(),c=L.Path.SVG;for(h._animationStart(),this.setOpacity(1),i=d.length-1;i>=0;i--)e=d[i],e._preSpiderfyLatlng&&(e.setLatLng(e._preSpiderfyLatlng),delete e._preSpiderfyLatlng,o=!0,e._setPos&&(e._setPos(l),o=!1),e.clusterHide&&(e.clusterHide(),o=!1),o&&_.removeLayer(e),c&&(n=e._spiderLeg,s=n._path,r=s.getTotalLength()+.1,s.style.strokeDashoffset=r,n.setStyle({opacity:0})));setTimeout(function(){var t=0;for(i=d.length-1;i>=0;i--)e=d[i],e._spiderLeg&&t++;for(i=d.length-1;i>=0;i--)e=d[i],e._spiderLeg&&(e.clusterShow&&e.clusterShow(),e.setZIndexOffset&&e.setZIndexOffset(0),t>1&&_.removeLayer(e),u.removeLayer(e._spiderLeg),delete e._spiderLeg);h._animationEnd(),h.fire("unspiderfied",{cluster:a,markers:d})},200)}}),L.MarkerClusterGroup.include({_spiderfied:null,_spiderfierOnAdd:function(){this._map.on("click",this._unspiderfyWrapper,this),this._map.options.zoomAnimation&&this._map.on("zoomstart",this._unspiderfyZoomStart,this),this._map.on("zoomend",this._noanimationUnspiderfy,this)},_spiderfierOnRemove:function(){this._map.off("click",this._unspiderfyWrapper,this),this._map.off("zoomstart",this._unspiderfyZoomStart,this),this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._map.off("zoomend",this._noanimationUnspiderfy,this),this._noanimationUnspiderfy()},_unspiderfyZoomStart:function(){this._map&&this._map.on("zoomanim",this._unspiderfyZoomAnim,this)},_unspiderfyZoomAnim:function(t){L.DomUtil.hasClass(this._map._mapPane,"leaflet-touching")||(this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._unspiderfy(t))},_unspiderfyWrapper:function(){this._unspiderfy()},_unspiderfy:function(t){this._spiderfied&&this._spiderfied.unspiderfy(t)},_noanimationUnspiderfy:function(){this._spiderfied&&this._spiderfied._noanimationUnspiderfy()},_unspiderfyLayer:function(t){t._spiderLeg&&(this._featureGroup.removeLayer(t),t.clusterShow&&t.clusterShow(),t.setZIndexOffset&&t.setZIndexOffset(0),this._map.removeLayer(t._spiderLeg),delete t._spiderLeg)}}),L.MarkerClusterGroup.include({refreshClusters:function(t){return t?t instanceof L.MarkerClusterGroup?t=t._topClusterLevel.getAllChildMarkers():t instanceof L.LayerGroup?t=t._layers:t instanceof L.MarkerCluster?t=t.getAllChildMarkers():t instanceof L.Marker&&(t=[t]):t=this._topClusterLevel.getAllChildMarkers(),this._flagParentsIconsNeedUpdate(t),this._refreshClustersIcons(),this.options.singleMarkerMode&&this._refreshSingleMarkerModeMarkers(t),this},_flagParentsIconsNeedUpdate:function(t){var e,i;for(e in t)for(i=t[e].__parent;i;)i._iconNeedsUpdate=!0,i=i.__parent},_refreshClustersIcons:function(){this._featureGroup.eachLayer(function(t){t instanceof L.MarkerCluster&&t._iconNeedsUpdate&&t._updateIcon()})},_refreshSingleMarkerModeMarkers:function(t){var e,i;for(e in t)i=t[e],this.hasLayer(i)&&i.setIcon(this._overrideMarkerIcon(i))}}),L.Marker.include({refreshIconOptions:function(t,e){var i=this.options.icon;return L.setOptions(i,t),this.setIcon(i),e&&this.__parent&&this.__parent._group.refreshClusters(this),this}})}(window,document); \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/vendor/leaflet.search.min.js b/assets/www/dist/dist_js/app/vendor/leaflet.search.min.js deleted file mode 100644 index 97facf7ae056707b251a6cc1ac773e4b8529230d..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/leaflet.search.min.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Leaflet Control Search v2.7.2 - 2017-04-08 - * - * Copyright 2017 Stefano Cudini - * stefano.cudini@gmail.com - * http://labs.easyblog.it/ - * - * Licensed under the MIT license. - * - * Demo: - * http://labs.easyblog.it/maps/leaflet-search/ - * - * Source: - * git@github.com:stefanocudini/leaflet-search.git - * - */ -!function(a){if("function"==typeof define&&define.amd)define(["leaflet"],a);else if("undefined"!=typeof module)module.exports=a(require("leaflet"));else{if("undefined"==typeof window.L)throw"Leaflet must be loaded first";a(window.L)}}(function(a){function b(a,b){var c=b.split("."),d=c.pop(),e=c.length,f=c[0],g=1;if(e>0)for(;(a=a[f])&&e>g;)f=c[g++];return a?a[d]:void 0}function c(a){return"[object Object]"===Object.prototype.toString.call(a)}return a.Control.Search=a.Control.extend({includes:a.Mixin.Events,options:{url:"",layer:null,sourceData:null,jsonpParam:null,propertyLoc:"loc",propertyName:"title",formatData:null,filterData:null,moveToLocation:null,buildTip:null,container:"",zoom:null,minLength:1,initial:!0,casesensitive:!1,autoType:!0,delayType:400,tooltipLimit:-1,tipAutoSubmit:!0,firstTipSubmit:!1,autoResize:!0,collapsed:!0,autoCollapse:!1,autoCollapseTime:1200,textErr:"Location not found",textCancel:"Cancel",textPlaceholder:"Search...",position:"topleft",hideMarkerOnCollapse:!1,marker:{icon:!1,animate:!0,circle:{radius:10,weight:3,color:"#e03",stroke:!0,fill:!1}}},initialize:function(b){a.Util.setOptions(this,b||{}),this._inputMinSize=this.options.textPlaceholder?this.options.textPlaceholder.length:10,this._layer=this.options.layer||new a.LayerGroup,this._filterData=this.options.filterData||this._defaultFilterData,this._formatData=this.options.formatData||this._defaultFormatData,this._moveToLocation=this.options.moveToLocation||this._defaultMoveToLocation,this._autoTypeTmp=this.options.autoType,this._countertips=0,this._recordsCache={},this._curReq=null},onAdd:function(b){return this._map=b,this._container=a.DomUtil.create("div","leaflet-control-search"),this._input=this._createInput(this.options.textPlaceholder,"search-input"),this._tooltip=this._createTooltip("search-tooltip"),this._cancel=this._createCancel(this.options.textCancel,"search-cancel"),this._button=this._createButton(this.options.textPlaceholder,"search-button"),this._alert=this._createAlert("search-alert"),this.options.collapsed===!1&&this.expand(this.options.collapsed),this.options.marker&&(this.options.marker instanceof a.Marker||this.options.marker instanceof a.CircleMarker?this._markerSearch=this.options.marker:c(this.options.marker)&&(this._markerSearch=new a.Control.Search.Marker([0,0],this.options.marker)),this._markerSearch._isMarkerSearch=!0),this.setLayer(this._layer),b.on({resize:this._handleAutoresize},this),this._container},addTo:function(b){return this.options.container?(this._container=this.onAdd(b),this._wrapper=a.DomUtil.get(this.options.container),this._wrapper.style.position="relative",this._wrapper.appendChild(this._container)):a.Control.prototype.addTo.call(this,b),this},onRemove:function(a){this._recordsCache={}},setLayer:function(a){return this._layer=a,this._layer.addTo(this._map),this},showAlert:function(a){a=a||this.options.textErr,this._alert.style.display="block",this._alert.innerHTML=a,clearTimeout(this.timerAlert);var b=this;return this.timerAlert=setTimeout(function(){b.hideAlert()},this.options.autoCollapseTime),this},hideAlert:function(){return this._alert.style.display="none",this},cancel:function(){return this._input.value="",this._handleKeypress({keyCode:8}),this._input.size=this._inputMinSize,this._input.focus(),this._cancel.style.display="none",this._hideTooltip(),this},expand:function(b){return b="boolean"==typeof b?b:!0,this._input.style.display="block",a.DomUtil.addClass(this._container,"search-exp"),b!==!1&&(this._input.focus(),this._map.on("dragstart click",this.collapse,this)),this.fire("search:expanded"),this},collapse:function(){return this._hideTooltip(),this.cancel(),this._alert.style.display="none",this._input.blur(),this.options.collapsed&&(this._input.style.display="none",this._cancel.style.display="none",a.DomUtil.removeClass(this._container,"search-exp"),this.options.hideMarkerOnCollapse&&this._map.removeLayer(this._markerSearch),this._map.off("dragstart click",this.collapse,this)),this.fire("search:collapsed"),this},collapseDelayed:function(){if(!this.options.autoCollapse)return this;var a=this;return clearTimeout(this.timerCollapse),this.timerCollapse=setTimeout(function(){a.collapse()},this.options.autoCollapseTime),this},collapseDelayedStop:function(){return clearTimeout(this.timerCollapse),this},_createAlert:function(b){var c=a.DomUtil.create("div",b,this._container);return c.style.display="none",a.DomEvent.on(c,"click",a.DomEvent.stop,this).on(c,"click",this.hideAlert,this),c},_createInput:function(b,c){var d=a.DomUtil.create("label",c,this._container),e=a.DomUtil.create("input",c,this._container);return e.type="text",e.size=this._inputMinSize,e.value="",e.autocomplete="off",e.autocorrect="off",e.autocapitalize="off",e.placeholder=b,e.style.display="none",e.role="search",e.id=e.role+e.type+e.size,d.htmlFor=e.id,d.style.display="none",d.value=b,a.DomEvent.disableClickPropagation(e).on(e,"keydown",this._handleKeypress,this).on(e,"blur",this.collapseDelayed,this).on(e,"focus",this.collapseDelayedStop,this),e},_createCancel:function(b,c){var d=a.DomUtil.create("a",c,this._container);return d.href="#",d.title=b,d.style.display="none",d.innerHTML="<span>⊗</span>",a.DomEvent.on(d,"click",a.DomEvent.stop,this).on(d,"click",this.cancel,this),d},_createButton:function(b,c){var d=a.DomUtil.create("a",c,this._container);return d.href="#",d.title=b,a.DomEvent.on(d,"click",a.DomEvent.stop,this).on(d,"click",this._handleSubmit,this).on(d,"focus",this.collapseDelayedStop,this).on(d,"blur",this.collapseDelayed,this),d},_createTooltip:function(b){var c=a.DomUtil.create("ul",b,this._container);c.style.display="none";var d=this;return a.DomEvent.disableClickPropagation(c).on(c,"blur",this.collapseDelayed,this).on(c,"mousewheel",function(b){d.collapseDelayedStop(),a.DomEvent.stopPropagation(b)},this).on(c,"mouseover",function(a){d.collapseDelayedStop()},this),c},_createTip:function(b,c){var d;if(this.options.buildTip){if(d=this.options.buildTip.call(this,b,c),"string"==typeof d){var e=a.DomUtil.create("div");e.innerHTML=d,d=e.firstChild}}else d=a.DomUtil.create("li",""),d.innerHTML=b;return a.DomUtil.addClass(d,"search-tip"),d._text=b,this.options.tipAutoSubmit&&a.DomEvent.disableClickPropagation(d).on(d,"click",a.DomEvent.stop,this).on(d,"click",function(a){this._input.value=b,this._handleAutoresize(),this._input.focus(),this._hideTooltip(),this._handleSubmit()},this),d},_getUrl:function(a){return"function"==typeof this.options.url?this.options.url(a):this.options.url},_defaultFilterData:function(a,b){var c,d,e,f={};if(a=a.replace(/[.*+?^${}()|[\]\\]/g,""),""===a)return[];c=this.options.initial?"^":"",d=this.options.casesensitive?void 0:"i",e=new RegExp(c+a,d);for(var g in b)e.test(g)&&(f[g]=b[g]);return f},showTooltip:function(a){if(this._countertips=0,this._tooltip.innerHTML="",this._tooltip.currentSelection=-1,this.options.tooltipLimit)for(var b in a){if(this._countertips===this.options.tooltipLimit)break;this._countertips++,this._tooltip.appendChild(this._createTip(b,a[b]))}return this._countertips>0?(this._tooltip.style.display="block",this._autoTypeTmp&&this._autoType(),this._autoTypeTmp=this.options.autoType):this._hideTooltip(),this._tooltip.scrollTop=0,this._countertips},_hideTooltip:function(){return this._tooltip.style.display="none",this._tooltip.innerHTML="",0},_defaultFormatData:function(c){var d,e=this.options.propertyName,f=this.options.propertyLoc,g={};if(a.Util.isArray(f))for(d in c)g[b(c[d],e)]=a.latLng(c[d][f[0]],c[d][f[1]]);else for(d in c)g[b(c[d],e)]=a.latLng(b(c[d],f));return g},_recordsFromJsonp:function(b,c){a.Control.Search.callJsonp=c;var d=a.DomUtil.create("script","leaflet-search-jsonp",document.getElementsByTagName("body")[0]),e=a.Util.template(this._getUrl(b)+"&"+this.options.jsonpParam+"=L.Control.Search.callJsonp",{s:b});return d.type="text/javascript",d.src=e,{abort:function(){d.parentNode.removeChild(d)}}},_recordsFromAjax:function(b,c){void 0===window.XMLHttpRequest&&(window.XMLHttpRequest=function(){try{return new ActiveXObject("Microsoft.XMLHTTP.6.0")}catch(a){try{return new ActiveXObject("Microsoft.XMLHTTP.3.0")}catch(b){throw new Error("XMLHttpRequest is not supported")}}});var d=a.Browser.ie&&!window.atob&&document.querySelector,e=d?new XDomainRequest:new XMLHttpRequest,f=a.Util.template(this._getUrl(b),{s:b});e.open("GET",f);return e.onload=function(){c(JSON.parse(e.responseText))},e.onreadystatechange=function(){4===e.readyState&&200===e.status&&this.onload()},e.send(),e},_recordsFromLayer:function(){var c,d={},e=this.options.propertyName;return this._layer.eachLayer(function(f){if(!f.hasOwnProperty("_isMarkerSearch"))if(f instanceof a.Marker||f instanceof a.CircleMarker)try{if(b(f.options,e))c=f.getLatLng(),c.layer=f,d[b(f.options,e)]=c;else{if(!b(f.feature.properties,e))throw new Error("propertyName '"+e+"' not found in marker");c=f.getLatLng(),c.layer=f,d[b(f.feature.properties,e)]=c}}catch(g){console}else if(f.hasOwnProperty("feature"))try{if(!f.feature.properties.hasOwnProperty(e))throw new Error("propertyName '"+e+"' not found in feature");c=f.getBounds().getCenter(),c.layer=f,d[f.feature.properties[e]]=c}catch(g){console}else f instanceof a.LayerGroup&&f.eachLayer(function(a){c=a.getLatLng(),c.layer=a,d[a.feature.properties[e]]=c})},this),d},_autoType:function(){var a=this._input.value.length,b=this._tooltip.firstChild?this._tooltip.firstChild._text:"",c=b.length;if(0===b.indexOf(this._input.value))if(this._input.value=b,this._handleAutoresize(),this._input.createTextRange){var d=this._input.createTextRange();d.collapse(!0),d.moveStart("character",a),d.moveEnd("character",c),d.select()}else this._input.setSelectionRange?this._input.setSelectionRange(a,c):this._input.selectionStart&&(this._input.selectionStart=a,this._input.selectionEnd=c)},_hideAutoType:function(){var a;if((a=this._input.selection)&&a.empty)a.empty();else if(this._input.createTextRange){a=this._input.createTextRange(),a.collapse(!0);var b=this._input.value.length;a.moveStart("character",b),a.moveEnd("character",b),a.select()}else this._input.getSelection&&this._input.getSelection().removeAllRanges(),this._input.selectionStart=this._input.selectionEnd},_handleKeypress:function(a){switch(a.keyCode){case 27:this.collapse();break;case 13:(1==this._countertips||this.options.firstTipSubmit&&this._countertips>0)&&this._handleArrowSelect(1),this._handleSubmit();break;case 38:this._handleArrowSelect(-1);break;case 40:this._handleArrowSelect(1);break;case 8:case 45:case 46:this._autoTypeTmp=!1;break;case 37:case 39:case 16:case 17:case 35:case 36:break;default:if(this._input.value.length?this._cancel.style.display="block":this._cancel.style.display="none",this._input.value.length>=this.options.minLength){var b=this;clearTimeout(this.timerKeypress),this.timerKeypress=setTimeout(function(){b._fillRecordsCache()},this.options.delayType)}else this._hideTooltip()}this._handleAutoresize()},searchText:function(b){var c=b.charCodeAt(b.length);this._input.value=b,this._input.style.display="block",a.DomUtil.addClass(this._container,"search-exp"),this._autoTypeTmp=!1,this._handleKeypress({keyCode:c})},_fillRecordsCache:function(){var b,c=this._input.value,d=this;this._curReq&&this._curReq.abort&&this._curReq.abort(),a.DomUtil.addClass(this._container,"search-load"),this.options.layer?(this._recordsCache=this._recordsFromLayer(),b=this._filterData(this._input.value,this._recordsCache),this.showTooltip(b),a.DomUtil.removeClass(this._container,"search-load")):(this.options.sourceData?this._retrieveData=this.options.sourceData:this.options.url&&(this._retrieveData=this.options.jsonpParam?this._recordsFromJsonp:this._recordsFromAjax),this._curReq=this._retrieveData.call(this,c,function(c){d._recordsCache=d._formatData(c),b=d.options.sourceData?d._filterData(d._input.value,d._recordsCache):d._recordsCache,d.showTooltip(b),a.DomUtil.removeClass(d._container,"search-load")}))},_handleAutoresize:function(){this._input.style.maxWidth!=this._map._container.offsetWidth&&(this._input.style.maxWidth=a.DomUtil.getStyle(this._map._container,"width")),this.options.autoResize&&this._container.offsetWidth+45<this._map._container.offsetWidth&&(this._input.size=this._input.value.length<this._inputMinSize?this._inputMinSize:this._input.value.length)},_handleArrowSelect:function(b){var c=this._tooltip.hasChildNodes()?this._tooltip.childNodes:[];for(i=0;i<c.length;i++)a.DomUtil.removeClass(c[i],"search-tip-select");if(1==b&&this._tooltip.currentSelection>=c.length-1)a.DomUtil.addClass(c[this._tooltip.currentSelection],"search-tip-select");else if(-1==b&&this._tooltip.currentSelection<=0)this._tooltip.currentSelection=-1;else if("none"!=this._tooltip.style.display){this._tooltip.currentSelection+=b,a.DomUtil.addClass(c[this._tooltip.currentSelection],"search-tip-select"),this._input.value=c[this._tooltip.currentSelection]._text;var d=c[this._tooltip.currentSelection].offsetTop;d+c[this._tooltip.currentSelection].clientHeight>=this._tooltip.scrollTop+this._tooltip.clientHeight?this._tooltip.scrollTop=d-this._tooltip.clientHeight+c[this._tooltip.currentSelection].clientHeight:d<=this._tooltip.scrollTop&&(this._tooltip.scrollTop=d)}},_handleSubmit:function(){if(this._hideAutoType(),this.hideAlert(),this._hideTooltip(),"none"==this._input.style.display)this.expand();else if(""===this._input.value)this.collapse();else{var a=this._getLocation(this._input.value);a===!1?this.showAlert():(this.showLocation(a,this._input.value),this.fire("search:locationfound",{latlng:a,text:this._input.value,layer:a.layer?a.layer:null}))}},_getLocation:function(a){return this._recordsCache.hasOwnProperty(a)?this._recordsCache[a]:!1},_defaultMoveToLocation:function(a,b,c){this.options.zoom?this._map.setView(a,this.options.zoom):this._map.panTo(a)},showLocation:function(a,b){var c=this;return c._map.once("moveend zoomend",function(b){c._markerSearch&&c._markerSearch.addTo(c._map).setLatLng(a)}),c._moveToLocation(a,b,c._map),c.options.autoCollapse&&c.collapse(),c}}),a.Control.Search.Marker=a.Marker.extend({includes:a.Mixin.Events,options:{icon:new a.Icon.Default,animate:!0,circle:{radius:10,weight:3,color:"#e03",stroke:!0,fill:!1}},initialize:function(b,d){a.setOptions(this,d),d.icon===!0&&(d.icon=new a.Icon.Default),a.Marker.prototype.initialize.call(this,b,d),c(this.options.circle)&&(this._circleLoc=new a.CircleMarker(b,this.options.circle))},onAdd:function(b){a.Marker.prototype.onAdd.call(this,b),this._circleLoc&&(b.addLayer(this._circleLoc),this.options.animate&&this.animate())},onRemove:function(b){a.Marker.prototype.onRemove.call(this,b),this._circleLoc&&b.removeLayer(this._circleLoc)},setLatLng:function(b){return a.Marker.prototype.setLatLng.call(this,b),this._circleLoc&&this._circleLoc.setLatLng(b),this},_initIcon:function(){this.options.icon&&a.Marker.prototype._initIcon.call(this)},_removeIcon:function(){this.options.icon&&a.Marker.prototype._removeIcon.call(this)},animate:function(){if(this._circleLoc){var a=this._circleLoc,b=200,c=5,d=parseInt(a._radius/c),e=this.options.circle.radius,f=2*a._radius,g=0;a._timerAnimLoc=setInterval(function(){g+=.5,d+=g,f-=d,a.setRadius(f),e>f&&(clearInterval(a._timerAnimLoc),a.setRadius(e))},b)}return this}}),a.Map.addInitHook(function(){this.options.searchControl&&(this.searchControl=a.control.search(this.options.searchControl),this.addControl(this.searchControl))}),a.control.search=function(b){return new a.Control.Search(b)},a.Control.Search}); \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/vendor/moment.es.js b/assets/www/dist/dist_js/app/vendor/moment.es.js deleted file mode 100644 index 9b24a1776d7bc6b3100955d47b1366c75df0e232..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/moment.es.js +++ /dev/null @@ -1,61 +0,0 @@ -//! moment.js locale configuration -//! locale : french (es) -//! author : Fiatou: https://github.com/fiatou - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : - typeof define === 'function' && define.amd ? define(['moment'], factory) : - factory(global.moment) -}(this, function (moment) { 'use strict'; - - - var es = moment.defineLocale('es', { - months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'), - monthsShort : 'ener._febr._mar._abr._may._jun._jul._agos_sept._oct._nov._dic.'.split('_'), - weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'), - weekdaysShort : 'dom._lun._mar._mie._jue._vie._sáb.'.split('_'), - weekdaysMin : 'Do_Lu_Ma_Mi_Ju_Vi_Sá'.split('_'), - longDateFormat : { - LT : 'HH:mm', - LTS : 'HH:mm:ss', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY HH:mm', - LLLL : 'dddd D MMMM YYYY HH:mm' - }, - calendar : { - sameDay: '[Hoy a] LT', - nextDay: '[Mañana a] LT', - nextWeek: 'dddd [a] LT', - lastDay: '[Ayer a] LT', - lastWeek: 'dddd [último a] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'en %s', - past : 'hace %s', - s : 'algunas segundas', - m : 'un minuto', - mm : '%d minutos', - h : 'una hora', - hh : '%d horas', - d : 'un dia', - dd : '%d dias', - M : 'un mes', - MM : '%d meses', - y : 'un año', - yy : '%d años' - }, - ordinalParse: /\d{1,2}(er|)/, - ordinal : function (number) { - return number + (number === 1 ? 'ero' : ''); - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); - - return es; - -})); diff --git a/assets/www/dist/dist_js/app/vendor/moment.fr.js b/assets/www/dist/dist_js/app/vendor/moment.fr.js deleted file mode 100644 index 4f60e588f3396e0eb9c968cb14cf172beb51a2c3..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/moment.fr.js +++ /dev/null @@ -1,61 +0,0 @@ -//! moment.js locale configuration -//! locale : french (fr) -//! author : John Fischer : https://github.com/jfroffice - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : - typeof define === 'function' && define.amd ? define(['moment'], factory) : - factory(global.moment) -}(this, function (moment) { 'use strict'; - - - var fr = moment.defineLocale('fr', { - months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), - monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), - weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), - weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), - weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), - longDateFormat : { - LT : 'HH:mm', - LTS : 'HH:mm:ss', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY HH:mm', - LLLL : 'dddd D MMMM YYYY HH:mm' - }, - calendar : { - sameDay: '[Aujourd\'hui à ] LT', - nextDay: '[Demain à ] LT', - nextWeek: 'dddd [à ] LT', - lastDay: '[Hier à ] LT', - lastWeek: 'dddd [dernier à ] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'dans %s', - past : 'il y a %s', - s : 'quelques secondes', - m : 'une minute', - mm : '%d minutes', - h : 'une heure', - hh : '%d heures', - d : 'un jour', - dd : '%d jours', - M : 'un mois', - MM : '%d mois', - y : 'un an', - yy : '%d ans' - }, - ordinalParse: /\d{1,2}(er|)/, - ordinal : function (number) { - return number + (number === 1 ? 'er' : ''); - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); - - return fr; - -})); \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/vendor/moment.min.js b/assets/www/dist/dist_js/app/vendor/moment.min.js deleted file mode 100644 index a049687679c3d43895039554cfe5f477cd92a51d..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/moment.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";function e(){return Qe.apply(null,arguments)}function t(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function n(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function s(e){return void 0===e}function i(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function r(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function a(e,t){var n,s=[];for(n=0;n<e.length;++n)s.push(t(e[n],n));return s}function o(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function u(e,t){for(var n in t)o(t,n)&&(e[n]=t[n]);return o(t,"toString")&&(e.toString=t.toString),o(t,"valueOf")&&(e.valueOf=t.valueOf),e}function l(e,t,n,s){return ge(e,t,n,s,!0).utc()}function d(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function h(e){if(null==e._isValid){var t=d(e),n=Xe.call(t.parsedDateParts,function(e){return null!=e}),s=!isNaN(e._d.getTime())&&t.overflow<0&&!t.empty&&!t.invalidMonth&&!t.invalidWeekday&&!t.weekdayMismatch&&!t.nullInput&&!t.invalidFormat&&!t.userInvalidated&&(!t.meridiem||t.meridiem&&n);if(e._strict&&(s=s&&0===t.charsLeftOver&&0===t.unusedTokens.length&&void 0===t.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return s;e._isValid=s}return e._isValid}function c(e){var t=l(NaN);return null!=e?u(d(t),e):d(t).userInvalidated=!0,t}function f(e,t){var n,i,r;if(s(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),s(t._i)||(e._i=t._i),s(t._f)||(e._f=t._f),s(t._l)||(e._l=t._l),s(t._strict)||(e._strict=t._strict),s(t._tzm)||(e._tzm=t._tzm),s(t._isUTC)||(e._isUTC=t._isUTC),s(t._offset)||(e._offset=t._offset),s(t._pf)||(e._pf=d(t)),s(t._locale)||(e._locale=t._locale),Ke.length>0)for(n=0;n<Ke.length;n++)s(r=t[i=Ke[n]])||(e[i]=r);return e}function m(t){f(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===et&&(et=!0,e.updateOffset(this),et=!1)}function _(e){return e instanceof m||null!=e&&null!=e._isAMomentObject}function y(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function g(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=y(t)),n}function p(e,t,n){var s,i=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),a=0;for(s=0;s<i;s++)(n&&e[s]!==t[s]||!n&&g(e[s])!==g(t[s]))&&a++;return a+r}function w(t){!1===e.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function v(t,n){var s=!0;return u(function(){if(null!=e.deprecationHandler&&e.deprecationHandler(null,t),s){for(var i,r=[],a=0;a<arguments.length;a++){if(i="","object"==typeof arguments[a]){i+="\n["+a+"] ";for(var o in arguments[0])i+=o+": "+arguments[0][o]+", ";i=i.slice(0,-2)}else i=arguments[a];r.push(i)}w(t+"\nArguments: "+Array.prototype.slice.call(r).join("")+"\n"+(new Error).stack),s=!1}return n.apply(this,arguments)},n)}function M(t,n){null!=e.deprecationHandler&&e.deprecationHandler(t,n),tt[t]||(w(n),tt[t]=!0)}function k(e){return e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function S(e,t){var s,i=u({},e);for(s in t)o(t,s)&&(n(e[s])&&n(t[s])?(i[s]={},u(i[s],e[s]),u(i[s],t[s])):null!=t[s]?i[s]=t[s]:delete i[s]);for(s in e)o(e,s)&&!o(t,s)&&n(e[s])&&(i[s]=u({},i[s]));return i}function D(e){null!=e&&this.set(e)}function Y(e,t){var n=e.toLowerCase();st[n]=st[n+"s"]=st[t]=e}function O(e){return"string"==typeof e?st[e]||st[e.toLowerCase()]:void 0}function x(e){var t,n,s={};for(n in e)o(e,n)&&(t=O(n))&&(s[t]=e[n]);return s}function T(e,t){it[e]=t}function b(e,t,n){var s=""+Math.abs(e),i=t-s.length;return(e>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+s}function P(e,t,n,s){var i=s;"string"==typeof s&&(i=function(){return this[s]()}),e&&(ut[e]=i),t&&(ut[t[0]]=function(){return b(i.apply(this,arguments),t[1],t[2])}),n&&(ut[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function W(e){return e.match(/\[[\s\S]/)?e.replace(/^\[|\]$/g,""):e.replace(/\\/g,"")}function R(e,t){return e.isValid()?(t=C(t,e.localeData()),ot[t]=ot[t]||function(e){var t,n,s=e.match(rt);for(t=0,n=s.length;t<n;t++)ut[s[t]]?s[t]=ut[s[t]]:s[t]=W(s[t]);return function(t){var i,r="";for(i=0;i<n;i++)r+=k(s[i])?s[i].call(t,e):s[i];return r}}(t),ot[t](e)):e.localeData().invalidDate()}function C(e,t){function n(e){return t.longDateFormat(e)||e}var s=5;for(at.lastIndex=0;s>=0&&at.test(e);)e=e.replace(at,n),at.lastIndex=0,s-=1;return e}function F(e,t,n){Yt[e]=k(t)?t:function(e,s){return e&&n?n:t}}function U(e,t){return o(Yt,e)?Yt[e](t._strict,t._locale):new RegExp(function(e){return N(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,s,i){return t||n||s||i}))}(e))}function N(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function H(e,t){var n,s=t;for("string"==typeof e&&(e=[e]),i(t)&&(s=function(e,n){n[t]=g(e)}),n=0;n<e.length;n++)Ot[e[n]]=s}function L(e,t){H(e,function(e,n,s,i){s._w=s._w||{},t(e,s._w,s,i)})}function G(e,t,n){null!=t&&o(Ot,e)&&Ot[e](t,n._a,n,e)}function V(e){return j(e)?366:365}function j(e){return e%4==0&&e%100!=0||e%400==0}function I(t,n){return function(s){return null!=s?(A(this,t,s),e.updateOffset(this,n),this):E(this,t)}}function E(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function A(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&j(e.year())&&1===e.month()&&29===e.date()?e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),z(n,e.month())):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function z(e,t){if(isNaN(e)||isNaN(t))return NaN;var n=function(e,t){return(e%t+t)%t}(t,12);return e+=(t-n)/12,1===n?j(e)?29:28:31-n%7%2}function Z(e,t){var n;if(!e.isValid())return e;if("string"==typeof t)if(/^\d+$/.test(t))t=g(t);else if(t=e.localeData().monthsParse(t),!i(t))return e;return n=Math.min(e.date(),z(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n),e}function $(t){return null!=t?(Z(this,t),e.updateOffset(this,!0),this):E(this,"Month")}function q(){function e(e,t){return t.length-e.length}var t,n,s=[],i=[],r=[];for(t=0;t<12;t++)n=l([2e3,t]),s.push(this.monthsShort(n,"")),i.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(s.sort(e),i.sort(e),r.sort(e),t=0;t<12;t++)s[t]=N(s[t]),i[t]=N(i[t]);for(t=0;t<24;t++)r[t]=N(r[t]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+s.join("|")+")","i")}function J(e){var t=new Date(Date.UTC.apply(null,arguments));return e<100&&e>=0&&isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e),t}function B(e,t,n){var s=7+t-n;return-((7+J(e,0,s).getUTCDay()-t)%7)+s-1}function Q(e,t,n,s,i){var r,a,o=1+7*(t-1)+(7+n-s)%7+B(e,s,i);return o<=0?a=V(r=e-1)+o:o>V(e)?(r=e+1,a=o-V(e)):(r=e,a=o),{year:r,dayOfYear:a}}function X(e,t,n){var s,i,r=B(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+K(i=e.year()-1,t,n):a>K(e.year(),t,n)?(s=a-K(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function K(e,t,n){var s=B(e,t,n),i=B(e+1,t,n);return(V(e)-s+i)/7}function ee(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],d=[];for(t=0;t<7;t++)n=l([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),d.push(s),d.push(i),d.push(r);for(a.sort(e),o.sort(e),u.sort(e),d.sort(e),t=0;t<7;t++)o[t]=N(o[t]),u[t]=N(u[t]),d[t]=N(d[t]);this._weekdaysRegex=new RegExp("^("+d.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function te(){return this.hours()%12||12}function ne(e,t){P(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function se(e,t){return t._meridiemParse}function ie(e){return e?e.toLowerCase().replace("_","-"):e}function re(e){var t=null;if(!Xt[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=Jt._abbr;require("./locale/"+e),ae(t)}catch(e){}return Xt[e]}function ae(e,t){var n;return e&&(n=s(t)?ue(e):oe(e,t))&&(Jt=n),Jt._abbr}function oe(e,t){if(null!==t){var n=Qt;if(t.abbr=e,null!=Xt[e])M("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),n=Xt[e]._config;else if(null!=t.parentLocale){if(null==Xt[t.parentLocale])return Kt[t.parentLocale]||(Kt[t.parentLocale]=[]),Kt[t.parentLocale].push({name:e,config:t}),null;n=Xt[t.parentLocale]._config}return Xt[e]=new D(S(n,t)),Kt[e]&&Kt[e].forEach(function(e){oe(e.name,e.config)}),ae(e),Xt[e]}return delete Xt[e],null}function ue(e){var n;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return Jt;if(!t(e)){if(n=re(e))return n;e=[e]}return function(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=ie(e[r]).split("-")).length,n=(n=ie(e[r+1]))?n.split("-"):null;t>0;){if(s=re(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&p(i,n,!0)>=t-1)break;t--}r++}return null}(e)}function le(e){var t,n=e._a;return n&&-2===d(e).overflow&&(t=n[Tt]<0||n[Tt]>11?Tt:n[bt]<1||n[bt]>z(n[xt],n[Tt])?bt:n[Pt]<0||n[Pt]>24||24===n[Pt]&&(0!==n[Wt]||0!==n[Rt]||0!==n[Ct])?Pt:n[Wt]<0||n[Wt]>59?Wt:n[Rt]<0||n[Rt]>59?Rt:n[Ct]<0||n[Ct]>999?Ct:-1,d(e)._overflowDayOfYear&&(t<xt||t>bt)&&(t=bt),d(e)._overflowWeeks&&-1===t&&(t=Ft),d(e)._overflowWeekday&&-1===t&&(t=Ut),d(e).overflow=t),e}function de(e,t,n){return null!=e?e:null!=t?t:n}function he(t){var n,s,i,r,a,o=[];if(!t._d){for(i=function(t){var n=new Date(e.now());return t._useUTC?[n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate()]:[n.getFullYear(),n.getMonth(),n.getDate()]}(t),t._w&&null==t._a[bt]&&null==t._a[Tt]&&function(e){var t,n,s,i,r,a,o,u;if(null!=(t=e._w).GG||null!=t.W||null!=t.E)r=1,a=4,n=de(t.GG,e._a[xt],X(pe(),1,4).year),s=de(t.W,1),((i=de(t.E,1))<1||i>7)&&(u=!0);else{r=e._locale._week.dow,a=e._locale._week.doy;var l=X(pe(),r,a);n=de(t.gg,e._a[xt],l.year),s=de(t.w,l.week),null!=t.d?((i=t.d)<0||i>6)&&(u=!0):null!=t.e?(i=t.e+r,(t.e<0||t.e>6)&&(u=!0)):i=r}s<1||s>K(n,r,a)?d(e)._overflowWeeks=!0:null!=u?d(e)._overflowWeekday=!0:(o=Q(n,s,i,r,a),e._a[xt]=o.year,e._dayOfYear=o.dayOfYear)}(t),null!=t._dayOfYear&&(a=de(t._a[xt],i[xt]),(t._dayOfYear>V(a)||0===t._dayOfYear)&&(d(t)._overflowDayOfYear=!0),s=J(a,0,t._dayOfYear),t._a[Tt]=s.getUTCMonth(),t._a[bt]=s.getUTCDate()),n=0;n<3&&null==t._a[n];++n)t._a[n]=o[n]=i[n];for(;n<7;n++)t._a[n]=o[n]=null==t._a[n]?2===n?1:0:t._a[n];24===t._a[Pt]&&0===t._a[Wt]&&0===t._a[Rt]&&0===t._a[Ct]&&(t._nextDay=!0,t._a[Pt]=0),t._d=(t._useUTC?J:function(e,t,n,s,i,r,a){var o=new Date(e,t,n,s,i,r,a);return e<100&&e>=0&&isFinite(o.getFullYear())&&o.setFullYear(e),o}).apply(null,o),r=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[Pt]=24),t._w&&void 0!==t._w.d&&t._w.d!==r&&(d(t).weekdayMismatch=!0)}}function ce(e){var t,n,s,i,r,a,o=e._i,u=en.exec(o)||tn.exec(o);if(u){for(d(e).iso=!0,t=0,n=sn.length;t<n;t++)if(sn[t][1].exec(u[1])){i=sn[t][0],s=!1!==sn[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=rn.length;t<n;t++)if(rn[t][1].exec(u[3])){r=(u[2]||" ")+rn[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!nn.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),_e(e)}else e._isValid=!1}function fe(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);{if(t<=49)return 2e3+t;if(t<=999)return 1900+t}return t}(e),Vt.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}function me(e){var t=on.exec(function(e){return e.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").trim()}(e._i));if(t){var n=fe(t[4],t[3],t[2],t[5],t[6],t[7]);if(!function(e,t,n){if(e&&At.indexOf(e)!==new Date(t[0],t[1],t[2]).getDay())return d(n).weekdayMismatch=!0,n._isValid=!1,!1;return!0}(t[1],n,e))return;e._a=n,e._tzm=function(e,t,n){if(e)return un[e];if(t)return 0;var s=parseInt(n,10),i=s%100;return(s-i)/100*60+i}(t[8],t[9],t[10]),e._d=J.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),d(e).rfc2822=!0}else e._isValid=!1}function _e(t){if(t._f!==e.ISO_8601)if(t._f!==e.RFC_2822){t._a=[],d(t).empty=!0;var n,s,i,r,a,o=""+t._i,u=o.length,l=0;for(i=C(t._f,t._locale).match(rt)||[],n=0;n<i.length;n++)r=i[n],(s=(o.match(U(r,t))||[])[0])&&((a=o.substr(0,o.indexOf(s))).length>0&&d(t).unusedInput.push(a),o=o.slice(o.indexOf(s)+s.length),l+=s.length),ut[r]?(s?d(t).empty=!1:d(t).unusedTokens.push(r),G(r,s,t)):t._strict&&!s&&d(t).unusedTokens.push(r);d(t).charsLeftOver=u-l,o.length>0&&d(t).unusedInput.push(o),t._a[Pt]<=12&&!0===d(t).bigHour&&t._a[Pt]>0&&(d(t).bigHour=void 0),d(t).parsedDateParts=t._a.slice(0),d(t).meridiem=t._meridiem,t._a[Pt]=function(e,t,n){var s;if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):null!=e.isPM?((s=e.isPM(n))&&t<12&&(t+=12),s||12!==t||(t=0),t):t}(t._locale,t._a[Pt],t._meridiem),he(t),le(t)}else me(t);else ce(t)}function ye(o){var l=o._i,y=o._f;return o._locale=o._locale||ue(o._l),null===l||void 0===y&&""===l?c({nullInput:!0}):("string"==typeof l&&(o._i=l=o._locale.preparse(l)),_(l)?new m(le(l)):(r(l)?o._d=l:t(y)?function(e){var t,n,s,i,r;if(0===e._f.length)return d(e).invalidFormat=!0,void(e._d=new Date(NaN));for(i=0;i<e._f.length;i++)r=0,t=f({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],_e(t),h(t)&&(r+=d(t).charsLeftOver,r+=10*d(t).unusedTokens.length,d(t).score=r,(null==s||r<s)&&(s=r,n=t));u(e,n||t)}(o):y?_e(o):function(o){var u=o._i;s(u)?o._d=new Date(e.now()):r(u)?o._d=new Date(u.valueOf()):"string"==typeof u?function(t){var n=an.exec(t._i);null===n?(ce(t),!1===t._isValid&&(delete t._isValid,me(t),!1===t._isValid&&(delete t._isValid,e.createFromInputFallback(t)))):t._d=new Date(+n[1])}(o):t(u)?(o._a=a(u.slice(0),function(e){return parseInt(e,10)}),he(o)):n(u)?function(e){if(!e._d){var t=x(e._i);e._a=a([t.year,t.month,t.day||t.date,t.hour,t.minute,t.second,t.millisecond],function(e){return e&&parseInt(e,10)}),he(e)}}(o):i(u)?o._d=new Date(u):e.createFromInputFallback(o)}(o),h(o)||(o._d=null),o))}function ge(e,s,i,r,a){var o={};return!0!==i&&!1!==i||(r=i,i=void 0),(n(e)&&function(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0}(e)||t(e)&&0===e.length)&&(e=void 0),o._isAMomentObject=!0,o._useUTC=o._isUTC=a,o._l=i,o._i=e,o._f=s,o._strict=r,function(e){var t=new m(le(ye(e)));return t._nextDay&&(t.add(1,"d"),t._nextDay=void 0),t}(o)}function pe(e,t,n,s){return ge(e,t,n,s,!1)}function we(e,n){var s,i;if(1===n.length&&t(n[0])&&(n=n[0]),!n.length)return pe();for(s=n[0],i=1;i<n.length;++i)n[i].isValid()&&!n[i][e](s)||(s=n[i]);return s}function ve(e){var t=x(e),n=t.year||0,s=t.quarter||0,i=t.month||0,r=t.week||0,a=t.day||0,o=t.hour||0,u=t.minute||0,l=t.second||0,d=t.millisecond||0;this._isValid=function(e){for(var t in e)if(-1===Nt.call(hn,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<hn.length;++s)if(e[hn[s]]){if(n)return!1;parseFloat(e[hn[s]])!==g(e[hn[s]])&&(n=!0)}return!0}(t),this._milliseconds=+d+1e3*l+6e4*u+1e3*o*60*60,this._days=+a+7*r,this._months=+i+3*s+12*n,this._data={},this._locale=ue(),this._bubble()}function Me(e){return e instanceof ve}function ke(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Se(e,t){P(e,0,0,function(){var e=this.utcOffset(),n="+";return e<0&&(e=-e,n="-"),n+b(~~(e/60),2)+t+b(~~e%60,2)})}function De(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(cn)||["-",0,0],i=60*s[1]+g(s[2]);return 0===i?0:"+"===s[0]?i:-i}function Ye(t,n){var s,i;return n._isUTC?(s=n.clone(),i=(_(t)||r(t)?t.valueOf():pe(t).valueOf())-s.valueOf(),s._d.setTime(s._d.valueOf()+i),e.updateOffset(s,!1),s):pe(t).local()}function Oe(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function xe(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function Te(e,t){var n,s,r,a=e,u=null;return Me(e)?a={ms:e._milliseconds,d:e._days,M:e._months}:i(e)?(a={},t?a[t]=e:a.milliseconds=e):(u=fn.exec(e))?(n="-"===u[1]?-1:1,a={y:0,d:g(u[bt])*n,h:g(u[Pt])*n,m:g(u[Wt])*n,s:g(u[Rt])*n,ms:g(ke(1e3*u[Ct]))*n}):(u=mn.exec(e))?(n="-"===u[1]?-1:(u[1],1),a={y:be(u[2],n),M:be(u[3],n),w:be(u[4],n),d:be(u[5],n),h:be(u[6],n),m:be(u[7],n),s:be(u[8],n)}):null==a?a={}:"object"==typeof a&&("from"in a||"to"in a)&&(r=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Ye(t,e),e.isBefore(t)?n=Pe(e,t):((n=Pe(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(pe(a.from),pe(a.to)),(a={}).ms=r.milliseconds,a.M=r.months),s=new ve(a),Me(e)&&o(e,"_locale")&&(s._locale=e._locale),s}function be(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function Pe(e,t){var n={milliseconds:0,months:0};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function We(e,t){return function(n,s){var i,r;return null===s||isNaN(+s)||(M(t,"moment()."+t+"(period, number) is deprecated. Please use moment()."+t+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),r=n,n=s,s=r),n="string"==typeof n?+n:n,i=Te(n,s),Re(this,i,e),this}}function Re(t,n,s,i){var r=n._milliseconds,a=ke(n._days),o=ke(n._months);t.isValid()&&(i=null==i||i,o&&Z(t,E(t,"Month")+o*s),a&&A(t,"Date",E(t,"Date")+a*s),r&&t._d.setTime(t._d.valueOf()+r*s),i&&e.updateOffset(t,a||o))}function Ce(e,t){var n,s=12*(t.year()-e.year())+(t.month()-e.month()),i=e.clone().add(s,"months");return n=t-i<0?(t-i)/(i-e.clone().add(s-1,"months")):(t-i)/(e.clone().add(s+1,"months")-i),-(s+n)||0}function Fe(e){var t;return void 0===e?this._locale._abbr:(null!=(t=ue(e))&&(this._locale=t),this)}function Ue(){return this._locale}function Ne(e,t){P(0,[e,e.length],0,t)}function He(e,t,n,s,i){var r;return null==e?X(this,s,i).year:(r=K(e,s,i),t>r&&(t=r),function(e,t,n,s,i){var r=Q(e,t,n,s,i),a=J(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}.call(this,e,t,n,s,i))}function Le(e,t){t[Ct]=g(1e3*("0."+e))}function Ge(e){return e}function Ve(e,t,n,s){var i=ue(),r=l().set(s,t);return i[n](r,e)}function je(e,t,n){if(i(e)&&(t=e,e=void 0),e=e||"",null!=t)return Ve(e,t,n,"month");var s,r=[];for(s=0;s<12;s++)r[s]=Ve(e,s,n,"month");return r}function Ie(e,t,n,s){"boolean"==typeof e?(i(t)&&(n=t,t=void 0),t=t||""):(n=t=e,e=!1,i(t)&&(n=t,t=void 0),t=t||"");var r=ue(),a=e?r._week.dow:0;if(null!=n)return Ve(t,(n+a)%7,s,"day");var o,u=[];for(o=0;o<7;o++)u[o]=Ve(t,(o+a)%7,s,"day");return u}function Ee(e,t,n,s){var i=Te(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function Ae(e){return e<0?Math.floor(e):Math.ceil(e)}function ze(e){return 4800*e/146097}function Ze(e){return 146097*e/4800}function $e(e){return function(){return this.as(e)}}function qe(e){return function(){return this.isValid()?this._data[e]:NaN}}function Je(e){return(e>0)-(e<0)||+e}function Be(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n=En(this._milliseconds)/1e3,s=En(this._days),i=En(this._months);t=y((e=y(n/60))/60),n%=60,e%=60;var r=y(i/12),a=i%=12,o=s,u=t,l=e,d=n?n.toFixed(3).replace(/\.?0+$/,""):"",h=this.asSeconds();if(!h)return"P0D";var c=h<0?"-":"",f=Je(this._months)!==Je(h)?"-":"",m=Je(this._days)!==Je(h)?"-":"",_=Je(this._milliseconds)!==Je(h)?"-":"";return c+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(o?m+o+"D":"")+(u||l||d?"T":"")+(u?_+u+"H":"")+(l?_+l+"M":"")+(d?_+d+"S":"")}var Qe,Xe;Xe=Array.prototype.some?Array.prototype.some:function(e){for(var t=Object(this),n=t.length>>>0,s=0;s<n;s++)if(s in t&&e.call(this,t[s],s,t))return!0;return!1};var Ke=e.momentProperties=[],et=!1,tt={};e.suppressDeprecationWarnings=!1,e.deprecationHandler=null;var nt;nt=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)o(e,t)&&n.push(t);return n};var st={},it={},rt=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,at=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,ot={},ut={},lt=/\d/,dt=/\d\d/,ht=/\d{3}/,ct=/\d{4}/,ft=/[+-]?\d{6}/,mt=/\d\d?/,_t=/\d\d\d\d?/,yt=/\d\d\d\d\d\d?/,gt=/\d{1,3}/,pt=/\d{1,4}/,wt=/[+-]?\d{1,6}/,vt=/\d+/,Mt=/[+-]?\d+/,kt=/Z|[+-]\d\d:?\d\d/gi,St=/Z|[+-]\d\d(?::?\d\d)?/gi,Dt=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,Yt={},Ot={},xt=0,Tt=1,bt=2,Pt=3,Wt=4,Rt=5,Ct=6,Ft=7,Ut=8;P("Y",0,0,function(){var e=this.year();return e<=9999?""+e:"+"+e}),P(0,["YY",2],0,function(){return this.year()%100}),P(0,["YYYY",4],0,"year"),P(0,["YYYYY",5],0,"year"),P(0,["YYYYYY",6,!0],0,"year"),Y("year","y"),T("year",1),F("Y",Mt),F("YY",mt,dt),F("YYYY",pt,ct),F("YYYYY",wt,ft),F("YYYYYY",wt,ft),H(["YYYYY","YYYYYY"],xt),H("YYYY",function(t,n){n[xt]=2===t.length?e.parseTwoDigitYear(t):g(t)}),H("YY",function(t,n){n[xt]=e.parseTwoDigitYear(t)}),H("Y",function(e,t){t[xt]=parseInt(e,10)}),e.parseTwoDigitYear=function(e){return g(e)+(g(e)>68?1900:2e3)};var Nt,Ht=I("FullYear",!0);Nt=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1},P("M",["MM",2],"Mo",function(){return this.month()+1}),P("MMM",0,0,function(e){return this.localeData().monthsShort(this,e)}),P("MMMM",0,0,function(e){return this.localeData().months(this,e)}),Y("month","M"),T("month",8),F("M",mt),F("MM",mt,dt),F("MMM",function(e,t){return t.monthsShortRegex(e)}),F("MMMM",function(e,t){return t.monthsRegex(e)}),H(["M","MM"],function(e,t){t[Tt]=g(e)-1}),H(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[Tt]=i:d(n).invalidMonth=e});var Lt=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Gt="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Vt="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),jt=Dt,It=Dt;P("w",["ww",2],"wo","week"),P("W",["WW",2],"Wo","isoWeek"),Y("week","w"),Y("isoWeek","W"),T("week",5),T("isoWeek",5),F("w",mt),F("ww",mt,dt),F("W",mt),F("WW",mt,dt),L(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=g(e)});P("d",0,"do","day"),P("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),P("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),P("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),P("e",0,0,"weekday"),P("E",0,0,"isoWeekday"),Y("day","d"),Y("weekday","e"),Y("isoWeekday","E"),T("day",11),T("weekday",11),T("isoWeekday",11),F("d",mt),F("e",mt),F("E",mt),F("dd",function(e,t){return t.weekdaysMinRegex(e)}),F("ddd",function(e,t){return t.weekdaysShortRegex(e)}),F("dddd",function(e,t){return t.weekdaysRegex(e)}),L(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:d(n).invalidWeekday=e}),L(["d","e","E"],function(e,t,n,s){t[s]=g(e)});var Et="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),At="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),zt="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Zt=Dt,$t=Dt,qt=Dt;P("H",["HH",2],0,"hour"),P("h",["hh",2],0,te),P("k",["kk",2],0,function(){return this.hours()||24}),P("hmm",0,0,function(){return""+te.apply(this)+b(this.minutes(),2)}),P("hmmss",0,0,function(){return""+te.apply(this)+b(this.minutes(),2)+b(this.seconds(),2)}),P("Hmm",0,0,function(){return""+this.hours()+b(this.minutes(),2)}),P("Hmmss",0,0,function(){return""+this.hours()+b(this.minutes(),2)+b(this.seconds(),2)}),ne("a",!0),ne("A",!1),Y("hour","h"),T("hour",13),F("a",se),F("A",se),F("H",mt),F("h",mt),F("k",mt),F("HH",mt,dt),F("hh",mt,dt),F("kk",mt,dt),F("hmm",_t),F("hmmss",yt),F("Hmm",_t),F("Hmmss",yt),H(["H","HH"],Pt),H(["k","kk"],function(e,t,n){var s=g(e);t[Pt]=24===s?0:s}),H(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),H(["h","hh"],function(e,t,n){t[Pt]=g(e),d(n).bigHour=!0}),H("hmm",function(e,t,n){var s=e.length-2;t[Pt]=g(e.substr(0,s)),t[Wt]=g(e.substr(s)),d(n).bigHour=!0}),H("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Pt]=g(e.substr(0,s)),t[Wt]=g(e.substr(s,2)),t[Rt]=g(e.substr(i)),d(n).bigHour=!0}),H("Hmm",function(e,t,n){var s=e.length-2;t[Pt]=g(e.substr(0,s)),t[Wt]=g(e.substr(s))}),H("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Pt]=g(e.substr(0,s)),t[Wt]=g(e.substr(s,2)),t[Rt]=g(e.substr(i))});var Jt,Bt=I("Hours",!0),Qt={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Gt,monthsShort:Vt,week:{dow:0,doy:6},weekdays:Et,weekdaysMin:zt,weekdaysShort:At,meridiemParse:/[ap]\.?m?\.?/i},Xt={},Kt={},en=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,tn=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,nn=/Z|[+-]\d\d(?::?\d\d)?/,sn=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],rn=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],an=/^\/?Date\((\-?\d+)/i,on=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,un={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};e.createFromInputFallback=v("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))}),e.ISO_8601=function(){},e.RFC_2822=function(){};var ln=v("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=pe.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:c()}),dn=v("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=pe.apply(null,arguments);return this.isValid()&&e.isValid()?e>this?this:e:c()}),hn=["year","quarter","month","week","day","hour","minute","second","millisecond"];Se("Z",":"),Se("ZZ",""),F("Z",St),F("ZZ",St),H(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=De(St,e)});var cn=/([\+\-]|\d\d)/gi;e.updateOffset=function(){};var fn=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,mn=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;Te.fn=ve.prototype,Te.invalid=function(){return Te(NaN)};var _n=We(1,"add"),yn=We(-1,"subtract");e.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",e.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var gn=v("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)});P(0,["gg",2],0,function(){return this.weekYear()%100}),P(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Ne("gggg","weekYear"),Ne("ggggg","weekYear"),Ne("GGGG","isoWeekYear"),Ne("GGGGG","isoWeekYear"),Y("weekYear","gg"),Y("isoWeekYear","GG"),T("weekYear",1),T("isoWeekYear",1),F("G",Mt),F("g",Mt),F("GG",mt,dt),F("gg",mt,dt),F("GGGG",pt,ct),F("gggg",pt,ct),F("GGGGG",wt,ft),F("ggggg",wt,ft),L(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,s){t[s.substr(0,2)]=g(e)}),L(["gg","GG"],function(t,n,s,i){n[i]=e.parseTwoDigitYear(t)}),P("Q",0,"Qo","quarter"),Y("quarter","Q"),T("quarter",7),F("Q",lt),H("Q",function(e,t){t[Tt]=3*(g(e)-1)}),P("D",["DD",2],"Do","date"),Y("date","D"),T("date",9),F("D",mt),F("DD",mt,dt),F("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),H(["D","DD"],bt),H("Do",function(e,t){t[bt]=g(e.match(mt)[0])});var pn=I("Date",!0);P("DDD",["DDDD",3],"DDDo","dayOfYear"),Y("dayOfYear","DDD"),T("dayOfYear",4),F("DDD",gt),F("DDDD",ht),H(["DDD","DDDD"],function(e,t,n){n._dayOfYear=g(e)}),P("m",["mm",2],0,"minute"),Y("minute","m"),T("minute",14),F("m",mt),F("mm",mt,dt),H(["m","mm"],Wt);var wn=I("Minutes",!1);P("s",["ss",2],0,"second"),Y("second","s"),T("second",15),F("s",mt),F("ss",mt,dt),H(["s","ss"],Rt);var vn=I("Seconds",!1);P("S",0,0,function(){return~~(this.millisecond()/100)}),P(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),P(0,["SSS",3],0,"millisecond"),P(0,["SSSS",4],0,function(){return 10*this.millisecond()}),P(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),P(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),P(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),P(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),P(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),Y("millisecond","ms"),T("millisecond",16),F("S",gt,lt),F("SS",gt,dt),F("SSS",gt,ht);var Mn;for(Mn="SSSS";Mn.length<=9;Mn+="S")F(Mn,vt);for(Mn="S";Mn.length<=9;Mn+="S")H(Mn,Le);var kn=I("Milliseconds",!1);P("z",0,0,"zoneAbbr"),P("zz",0,0,"zoneName");var Sn=m.prototype;Sn.add=_n,Sn.calendar=function(t,n){var s=t||pe(),i=Ye(s,this).startOf("day"),r=e.calendarFormat(this,i)||"sameElse",a=n&&(k(n[r])?n[r].call(this,s):n[r]);return this.format(a||this.localeData().calendar(r,this,pe(s)))},Sn.clone=function(){return new m(this)},Sn.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Ye(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=O(t)){case"year":r=Ce(this,s)/12;break;case"month":r=Ce(this,s);break;case"quarter":r=Ce(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:y(r)},Sn.endOf=function(e){return void 0===(e=O(e))||"millisecond"===e?this:("date"===e&&(e="day"),this.startOf(e).add(1,"isoWeek"===e?"week":e).subtract(1,"ms"))},Sn.format=function(t){t||(t=this.isUtc()?e.defaultFormatUtc:e.defaultFormat);var n=R(this,t);return this.localeData().postformat(n)},Sn.from=function(e,t){return this.isValid()&&(_(e)&&e.isValid()||pe(e).isValid())?Te({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},Sn.fromNow=function(e){return this.from(pe(),e)},Sn.to=function(e,t){return this.isValid()&&(_(e)&&e.isValid()||pe(e).isValid())?Te({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},Sn.toNow=function(e){return this.to(pe(),e)},Sn.get=function(e){return e=O(e),k(this[e])?this[e]():this},Sn.invalidAt=function(){return d(this).overflow},Sn.isAfter=function(e,t){var n=_(e)?e:pe(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=O(s(t)?"millisecond":t))?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},Sn.isBefore=function(e,t){var n=_(e)?e:pe(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=O(s(t)?"millisecond":t))?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},Sn.isBetween=function(e,t,n,s){return("("===(s=s||"()")[0]?this.isAfter(e,n):!this.isBefore(e,n))&&(")"===s[1]?this.isBefore(t,n):!this.isAfter(t,n))},Sn.isSame=function(e,t){var n,s=_(e)?e:pe(e);return!(!this.isValid()||!s.isValid())&&("millisecond"===(t=O(t||"millisecond"))?this.valueOf()===s.valueOf():(n=s.valueOf(),this.clone().startOf(t).valueOf()<=n&&n<=this.clone().endOf(t).valueOf()))},Sn.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},Sn.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},Sn.isValid=function(){return h(this)},Sn.lang=gn,Sn.locale=Fe,Sn.localeData=Ue,Sn.max=dn,Sn.min=ln,Sn.parsingFlags=function(){return u({},d(this))},Sn.set=function(e,t){if("object"==typeof e)for(var n=function(e){var t=[];for(var n in e)t.push({unit:n,priority:it[n]});return t.sort(function(e,t){return e.priority-t.priority}),t}(e=x(e)),s=0;s<n.length;s++)this[n[s].unit](e[n[s].unit]);else if(e=O(e),k(this[e]))return this[e](t);return this},Sn.startOf=function(e){switch(e=O(e)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===e&&this.weekday(0),"isoWeek"===e&&this.isoWeekday(1),"quarter"===e&&this.month(3*Math.floor(this.month()/3)),this},Sn.subtract=yn,Sn.toArray=function(){return[this.year(),this.month(),this.date(),this.hour(),this.minute(),this.second(),this.millisecond()]},Sn.toObject=function(){return{years:this.year(),months:this.month(),date:this.date(),hours:this.hours(),minutes:this.minutes(),seconds:this.seconds(),milliseconds:this.milliseconds()}},Sn.toDate=function(){return new Date(this.valueOf())},Sn.toISOString=function(){if(!this.isValid())return null;var e=this.clone().utc();return e.year()<0||e.year()>9999?R(e,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):k(Date.prototype.toISOString)?this.toDate().toISOString():R(e,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},Sn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',s=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i=t+'[")]';return this.format(n+s+"-MM-DD[T]HH:mm:ss.SSS"+i)},Sn.toJSON=function(){return this.isValid()?this.toISOString():null},Sn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},Sn.unix=function(){return Math.floor(this.valueOf()/1e3)},Sn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},Sn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},Sn.year=Ht,Sn.isLeapYear=function(){return j(this.year())},Sn.weekYear=function(e){return He.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},Sn.isoWeekYear=function(e){return He.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},Sn.quarter=Sn.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},Sn.month=$,Sn.daysInMonth=function(){return z(this.year(),this.month())},Sn.week=Sn.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},Sn.isoWeek=Sn.isoWeeks=function(e){var t=X(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},Sn.weeksInYear=function(){var e=this.localeData()._week;return K(this.year(),e.dow,e.doy)},Sn.isoWeeksInYear=function(){return K(this.year(),1,4)},Sn.date=pn,Sn.day=Sn.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(e=function(e,t){return"string"!=typeof e?e:isNaN(e)?"number"==typeof(e=t.weekdaysParse(e))?e:null:parseInt(e,10)}(e,this.localeData()),this.add(e-t,"d")):t},Sn.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},Sn.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null!=e){var t=function(e,t){return"string"==typeof e?t.weekdaysParse(e)%7||7:isNaN(e)?null:e}(e,this.localeData());return this.day(this.day()%7?t:t-7)}return this.day()||7},Sn.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},Sn.hour=Sn.hours=Bt,Sn.minute=Sn.minutes=wn,Sn.second=Sn.seconds=vn,Sn.millisecond=Sn.milliseconds=kn,Sn.utcOffset=function(t,n,s){var i,r=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(null===(t=De(St,t)))return this}else Math.abs(t)<16&&!s&&(t*=60);return!this._isUTC&&n&&(i=Oe(this)),this._offset=t,this._isUTC=!0,null!=i&&this.add(i,"m"),r!==t&&(!n||this._changeInProgress?Re(this,Te(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,e.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Oe(this)},Sn.utc=function(e){return this.utcOffset(0,e)},Sn.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Oe(this),"m")),this},Sn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=De(kt,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},Sn.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?pe(e).utcOffset():0,(this.utcOffset()-e)%60==0)},Sn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},Sn.isLocal=function(){return!!this.isValid()&&!this._isUTC},Sn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},Sn.isUtc=xe,Sn.isUTC=xe,Sn.zoneAbbr=function(){return this._isUTC?"UTC":""},Sn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},Sn.dates=v("dates accessor is deprecated. Use date instead.",pn),Sn.months=v("months accessor is deprecated. Use month instead",$),Sn.years=v("years accessor is deprecated. Use year instead",Ht),Sn.zone=v("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),Sn.isDSTShifted=v("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!s(this._isDSTShifted))return this._isDSTShifted;var e={};if(f(e,this),(e=ye(e))._a){var t=e._isUTC?l(e._a):pe(e._a);this._isDSTShifted=this.isValid()&&p(e._a,t.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var Dn=D.prototype;Dn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return k(s)?s.call(t,n):s},Dn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.replace(/MMMM|MM|DD|dddd/g,function(e){return e.slice(1)}),this._longDateFormat[e])},Dn.invalidDate=function(){return this._invalidDate},Dn.ordinal=function(e){return this._ordinal.replace("%d",e)},Dn.preparse=Ge,Dn.postformat=Ge,Dn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return k(i)?i(e,t,n,s):i.replace(/%d/i,e)},Dn.pastFuture=function(e,t){var n=this._relativeTime[e>0?"future":"past"];return k(n)?n(t):n.replace(/%s/i,t)},Dn.set=function(e){var t,n;for(n in e)k(t=e[n])?this[n]=t:this["_"+n]=t;this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},Dn.months=function(e,n){return e?t(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||Lt).test(n)?"format":"standalone"][e.month()]:t(this._months)?this._months:this._months.standalone},Dn.monthsShort=function(e,n){return e?t(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[Lt.test(n)?"format":"standalone"][e.month()]:t(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},Dn.monthsParse=function(e,t,n){var s,i,r;if(this._monthsParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=l([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=Nt.call(this._shortMonthsParse,a))?i:null:-1!==(i=Nt.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Nt.call(this._shortMonthsParse,a))?i:-1!==(i=Nt.call(this._longMonthsParse,a))?i:null:-1!==(i=Nt.call(this._longMonthsParse,a))?i:-1!==(i=Nt.call(this._shortMonthsParse,a))?i:null}.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=l([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(r="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},Dn.monthsRegex=function(e){return this._monthsParseExact?(o(this,"_monthsRegex")||q.call(this),e?this._monthsStrictRegex:this._monthsRegex):(o(this,"_monthsRegex")||(this._monthsRegex=It),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},Dn.monthsShortRegex=function(e){return this._monthsParseExact?(o(this,"_monthsRegex")||q.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(o(this,"_monthsShortRegex")||(this._monthsShortRegex=jt),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},Dn.week=function(e){return X(e,this._week.dow,this._week.doy).week},Dn.firstDayOfYear=function(){return this._week.doy},Dn.firstDayOfWeek=function(){return this._week.dow},Dn.weekdays=function(e,n){return e?t(this._weekdays)?this._weekdays[e.day()]:this._weekdays[this._weekdays.isFormat.test(n)?"format":"standalone"][e.day()]:t(this._weekdays)?this._weekdays:this._weekdays.standalone},Dn.weekdaysMin=function(e){return e?this._weekdaysMin[e.day()]:this._weekdaysMin},Dn.weekdaysShort=function(e){return e?this._weekdaysShort[e.day()]:this._weekdaysShort},Dn.weekdaysParse=function(e,t,n){var s,i,r;if(this._weekdaysParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=l([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=Nt.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Nt.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Nt.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Nt.call(this._weekdaysParse,a))?i:-1!==(i=Nt.call(this._shortWeekdaysParse,a))?i:-1!==(i=Nt.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Nt.call(this._shortWeekdaysParse,a))?i:-1!==(i=Nt.call(this._weekdaysParse,a))?i:-1!==(i=Nt.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Nt.call(this._minWeekdaysParse,a))?i:-1!==(i=Nt.call(this._weekdaysParse,a))?i:-1!==(i=Nt.call(this._shortWeekdaysParse,a))?i:null}.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=l([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".",".?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},Dn.weekdaysRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(o(this,"_weekdaysRegex")||(this._weekdaysRegex=Zt),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},Dn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(o(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=$t),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},Dn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(o(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=qt),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},Dn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},Dn.meridiem=function(e,t,n){return e>11?n?"pm":"PM":n?"am":"AM"},ae("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===g(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),e.lang=v("moment.lang is deprecated. Use moment.locale instead.",ae),e.langData=v("moment.langData is deprecated. Use moment.localeData instead.",ue);var Yn=Math.abs,On=$e("ms"),xn=$e("s"),Tn=$e("m"),bn=$e("h"),Pn=$e("d"),Wn=$e("w"),Rn=$e("M"),Cn=$e("y"),Fn=qe("milliseconds"),Un=qe("seconds"),Nn=qe("minutes"),Hn=qe("hours"),Ln=qe("days"),Gn=qe("months"),Vn=qe("years"),jn=Math.round,In={ss:44,s:45,m:45,h:22,d:26,M:11},En=Math.abs,An=ve.prototype;return An.isValid=function(){return this._isValid},An.abs=function(){var e=this._data;return this._milliseconds=Yn(this._milliseconds),this._days=Yn(this._days),this._months=Yn(this._months),e.milliseconds=Yn(e.milliseconds),e.seconds=Yn(e.seconds),e.minutes=Yn(e.minutes),e.hours=Yn(e.hours),e.months=Yn(e.months),e.years=Yn(e.years),this},An.add=function(e,t){return Ee(this,e,t,1)},An.subtract=function(e,t){return Ee(this,e,t,-1)},An.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=O(e))||"year"===e)return t=this._days+s/864e5,n=this._months+ze(t),"month"===e?n:n/12;switch(t=this._days+Math.round(Ze(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},An.asMilliseconds=On,An.asSeconds=xn,An.asMinutes=Tn,An.asHours=bn,An.asDays=Pn,An.asWeeks=Wn,An.asMonths=Rn,An.asYears=Cn,An.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*g(this._months/12):NaN},An._bubble=function(){var e,t,n,s,i,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return r>=0&&a>=0&&o>=0||r<=0&&a<=0&&o<=0||(r+=864e5*Ae(Ze(o)+a),a=0,o=0),u.milliseconds=r%1e3,e=y(r/1e3),u.seconds=e%60,t=y(e/60),u.minutes=t%60,n=y(t/60),u.hours=n%24,a+=y(n/24),i=y(ze(a)),o+=i,a-=Ae(Ze(i)),s=y(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},An.clone=function(){return Te(this)},An.get=function(e){return e=O(e),this.isValid()?this[e+"s"]():NaN},An.milliseconds=Fn,An.seconds=Un,An.minutes=Nn,An.hours=Hn,An.days=Ln,An.weeks=function(){return y(this.days()/7)},An.months=Gn,An.years=Vn,An.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t=this.localeData(),n=function(e,t,n){var s=Te(e).abs(),i=jn(s.as("s")),r=jn(s.as("m")),a=jn(s.as("h")),o=jn(s.as("d")),u=jn(s.as("M")),l=jn(s.as("y")),d=i<=In.ss&&["s",i]||i<In.s&&["ss",i]||r<=1&&["m"]||r<In.m&&["mm",r]||a<=1&&["h"]||a<In.h&&["hh",a]||o<=1&&["d"]||o<In.d&&["dd",o]||u<=1&&["M"]||u<In.M&&["MM",u]||l<=1&&["y"]||["yy",l];return d[2]=t,d[3]=+e>0,d[4]=n,function(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}.apply(null,d)}(this,!e,t);return e&&(n=t.pastFuture(+this,n)),t.postformat(n)},An.toISOString=Be,An.toString=Be,An.toJSON=Be,An.locale=Fe,An.localeData=Ue,An.toIsoString=v("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Be),An.lang=gn,P("X",0,0,"unix"),P("x",0,0,"valueOf"),F("x",Mt),F("X",/[+-]?\d+(\.\d{1,3})?/),H("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))}),H("x",function(e,t,n){n._d=new Date(g(e))}),e.version="2.19.4",function(e){Qe=e}(pe),e.fn=Sn,e.min=function(){return we("isBefore",[].slice.call(arguments,0))},e.max=function(){return we("isAfter",[].slice.call(arguments,0))},e.now=function(){return Date.now?Date.now():+new Date},e.utc=l,e.unix=function(e){return pe(1e3*e)},e.months=function(e,t){return je(e,t,"months")},e.isDate=r,e.locale=ae,e.invalid=c,e.duration=Te,e.isMoment=_,e.weekdays=function(e,t,n){return Ie(e,t,n,"weekdays")},e.parseZone=function(){return pe.apply(null,arguments).parseZone()},e.localeData=ue,e.isDuration=Me,e.monthsShort=function(e,t){return je(e,t,"monthsShort")},e.weekdaysMin=function(e,t,n){return Ie(e,t,n,"weekdaysMin")},e.defineLocale=oe,e.updateLocale=function(e,t){if(null!=t){var n,s,i=Qt;null!=(s=re(e))&&(i=s._config),(n=new D(t=S(i,t))).parentLocale=Xt[e],Xt[e]=n,ae(e)}else null!=Xt[e]&&(null!=Xt[e].parentLocale?Xt[e]=Xt[e].parentLocale:null!=Xt[e]&&delete Xt[e]);return Xt[e]},e.locales=function(){return nt(Xt)},e.weekdaysShort=function(e,t,n){return Ie(e,t,n,"weekdaysShort")},e.normalizeUnits=O,e.relativeTimeRounding=function(e){return void 0===e?jn:"function"==typeof e&&(jn=e,!0)},e.relativeTimeThreshold=function(e,t){return void 0!==In[e]&&(void 0===t?In[e]:(In[e]=t,"s"===e&&(In.ss=t-1),!0))},e.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},e.prototype=Sn,e}); \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/vendor/moment.nl.js b/assets/www/dist/dist_js/app/vendor/moment.nl.js deleted file mode 100644 index 8b47a5d107e4d2463f662078fd263b772b328451..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/moment.nl.js +++ /dev/null @@ -1,59 +0,0 @@ -//! moment.js locale configuration -//! locale : dutch (nl) -//! author : RA van Hagen : https://github.com/RavanH - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : - typeof define === 'function' && define.amd ? define(['moment'], factory) : - factory(global.moment) -}(this, function (moment) { 'use strict'; - - var nl = moment.defineLocale('nl', { - months : 'januari|februari|maart|april|mei|juni|juli|augustus|september|oktober|november|december'.split('|'), - monthsShort : 'jan|feb|mrt|apr|mei|jun|jul|aug|sep|okt|nov|dec'.split('|'), - weekdays : 'zondag|maandag|dinsdag|woensdag|donderdag|vrijdag|zaterdag'.split('|'), - weekdaysShort : 'zo.|ma.|di.|wo.|do.|vr.|za.'.split('|'), - weekdaysMin : 'zo|ma|di|wo|do|vr|za'.split('|'), - longDateFormat : { - LT : 'HH:mm', - LTS : 'HH:mm:ss', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY HH:mm', - LLLL : 'dddd D MMMM YYYY HH:mm' - }, - calendar : { - sameDay: '[Vandaag om] LT', - nextDay: '[Morgen om] LT', - nextWeek: 'dddd [om] LT', - lastDay: '[Gisteren om] LT', - lastWeek: '[afgelopen] dddd [om] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'over %s', - past : '%s geleden', - s : 'enkele seconden', - m : 'een minuut', - mm : '%d minuten', - h : 'een uur', - hh : '%d uren', - d : 'een dag', - dd : '%d dagen', - M : 'een maand', - MM : '%d maanden', - y : 'een jaar', - yy : '%d jaar' - }, - ordinalParse: /\d{1,2}(er|)/, - ordinal : function (number) { - return number + '<sup>e</sup>'; - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); - - return nl; -})); diff --git a/assets/www/dist/dist_js/app/vendor/nacl_factory.js b/assets/www/dist/dist_js/app/vendor/nacl_factory.js deleted file mode 100644 index a01f4205ded63055db8e6b640df6ec1d88bb012b..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/nacl_factory.js +++ /dev/null @@ -1,622 +0,0 @@ -var nacl_factory = { - instantiate: function (on_ready, optionsOpt) { - var options = optionsOpt || {}; - var requested_total_memory = options.requested_total_memory || 33554432; - var undefined_reference_value = (function (v) { return v; })(); - - if (typeof on_ready !== 'function') { - throw new Error("nacl_factory: Expects on_ready callback as first argument. New in v1.1.0."); - } - - return (function (window, document) { - var on_ready_call_needed = false; - var Module = { - TOTAL_MEMORY: requested_total_memory, - onRuntimeInitialized: function () { - if (nacl) { - on_ready(nacl); - } else { - on_ready_call_needed = true; - } - } - }; - if (options.memoryInitializerPrefixURL) { - Module.memoryInitializerPrefixURL = options.memoryInitializerPrefixURL; - } - var nacl_raw = Module; -var Module;if(!Module)Module=(typeof Module!=="undefined"?Module:null)||{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;if(Module["ENVIRONMENT"]){if(Module["ENVIRONMENT"]==="WEB"){ENVIRONMENT_IS_WEB=true}else if(Module["ENVIRONMENT"]==="WORKER"){ENVIRONMENT_IS_WORKER=true}else if(Module["ENVIRONMENT"]==="NODE"){ENVIRONMENT_IS_NODE=true}else if(Module["ENVIRONMENT"]==="SHELL"){ENVIRONMENT_IS_SHELL=true}else{throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.")}}else{ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER}if(ENVIRONMENT_IS_NODE){if(!Module["print"])Module["print"]=console.log;if(!Module["printErr"])Module["printErr"]=console.warn;var nodeFS;var nodePath;Module["read"]=function read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);var ret=nodeFS["readFileSync"](filename);return binary?ret:ret.toString()};Module["readBinary"]=function readBinary(filename){var ret=Module["read"](filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};Module["load"]=function load(f){globalEval(read(f))};if(!Module["thisProgram"]){if(process["argv"].length>1){Module["thisProgram"]=process["argv"][1].replace(/\\/g,"/")}else{Module["thisProgram"]="unknown-program"}}Module["arguments"]=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));Module["inspect"]=(function(){return"[Emscripten Module object]"})}else if(ENVIRONMENT_IS_SHELL){if(!Module["print"])Module["print"]=print;if(typeof printErr!="undefined")Module["printErr"]=printErr;if(typeof read!="undefined"){Module["read"]=read}else{Module["read"]=function read(){throw"no read() available"}}Module["readBinary"]=function readBinary(f){if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}var data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){Module["arguments"]=scriptArgs}else if(typeof arguments!="undefined"){Module["arguments"]=arguments}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module["read"]=function read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};Module["readAsync"]=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response)}else{onerror()}};xhr.onerror=onerror;xhr.send(null)};if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof console!=="undefined"){if(!Module["print"])Module["print"]=function print(x){console.log(x)};if(!Module["printErr"])Module["printErr"]=function printErr(x){console.warn(x)}}else{var TRY_USE_DUMP=false;if(!Module["print"])Module["print"]=TRY_USE_DUMP&&typeof dump!=="undefined"?(function(x){dump(x)}):(function(x){})}if(ENVIRONMENT_IS_WORKER){Module["load"]=importScripts}if(typeof Module["setWindowTitle"]==="undefined"){Module["setWindowTitle"]=(function(title){document.title=title})}}else{throw"Unknown runtime environment. Where are we?"}function globalEval(x){abort("NO_DYNAMIC_EXECUTION=1 was set, cannot eval")}if(!Module["load"]&&Module["read"]){Module["load"]=function load(f){globalEval(Module["read"](f))}}if(!Module["print"]){Module["print"]=(function(){})}if(!Module["printErr"]){Module["printErr"]=Module["print"]}if(!Module["arguments"]){Module["arguments"]=[]}if(!Module["thisProgram"]){Module["thisProgram"]="./this.program"}Module.print=Module["print"];Module.printErr=Module["printErr"];Module["preRun"]=[];Module["postRun"]=[];for(var key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=undefined;var Runtime={setTempRet0:(function(value){tempRet0=value}),getTempRet0:(function(){return tempRet0}),stackSave:(function(){return STACKTOP}),stackRestore:(function(stackTop){STACKTOP=stackTop}),getNativeTypeSize:(function(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return Runtime.QUANTUM_SIZE}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}),getNativeFieldSize:(function(type){return Math.max(Runtime.getNativeTypeSize(type),Runtime.QUANTUM_SIZE)}),STACK_ALIGN:16,prepVararg:(function(ptr,type){if(type==="double"||type==="i64"){if(ptr&7){assert((ptr&7)===4);ptr+=4}}else{assert((ptr&3)===0)}return ptr}),getAlignSize:(function(type,size,vararg){if(!vararg&&(type=="i64"||type=="double"))return 8;if(!type)return Math.min(size,8);return Math.min(size||(type?Runtime.getNativeFieldSize(type):0),Runtime.QUANTUM_SIZE)}),dynCall:(function(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}),functionPointers:[null,null,null,null,null,null,null,null],addFunction:(function(func){for(var i=0;i<Runtime.functionPointers.length;i++){if(!Runtime.functionPointers[i]){Runtime.functionPointers[i]=func;return 1*(1+i)}}throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS."}),removeFunction:(function(index){Runtime.functionPointers[(index-1)/1]=null}),warnOnce:(function(text){if(!Runtime.warnOnce.shown)Runtime.warnOnce.shown={};if(!Runtime.warnOnce.shown[text]){Runtime.warnOnce.shown[text]=1;Module.printErr(text)}}),funcWrappers:{},getFuncWrapper:(function(func,sig){assert(sig);if(!Runtime.funcWrappers[sig]){Runtime.funcWrappers[sig]={}}var sigCache=Runtime.funcWrappers[sig];if(!sigCache[func]){if(sig.length===1){sigCache[func]=function dynCall_wrapper(){return Runtime.dynCall(sig,func)}}else if(sig.length===2){sigCache[func]=function dynCall_wrapper(arg){return Runtime.dynCall(sig,func,[arg])}}else{sigCache[func]=function dynCall_wrapper(){return Runtime.dynCall(sig,func,Array.prototype.slice.call(arguments))}}}return sigCache[func]}),getCompilerSetting:(function(name){throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work"}),stackAlloc:(function(size){var ret=STACKTOP;STACKTOP=STACKTOP+size|0;STACKTOP=STACKTOP+15&-16;return ret}),staticAlloc:(function(size){var ret=STATICTOP;STATICTOP=STATICTOP+size|0;STATICTOP=STATICTOP+15&-16;return ret}),dynamicAlloc:(function(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=(ret+size+15|0)&-16;HEAP32[DYNAMICTOP_PTR>>2]=end;if(end>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){HEAP32[DYNAMICTOP_PTR>>2]=ret;return 0}}return ret}),alignMemory:(function(size,quantum){var ret=size=Math.ceil(size/(quantum?quantum:16))*(quantum?quantum:16);return ret}),makeBigInt:(function(low,high,unsigned){var ret=unsigned?+(low>>>0)+ +(high>>>0)*+4294967296:+(low>>>0)+ +(high|0)*+4294967296;return ret}),GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module["Runtime"]=Runtime;var ABORT=0;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];if(!func){abort("NO_DYNAMIC_EXECUTION=1 was set, cannot eval")}assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)");return func}var cwrap,ccall;((function(){var JSfuncs={"stackSave":(function(){Runtime.stackSave()}),"stackRestore":(function(){Runtime.stackRestore()}),"arrayToC":(function(arr){var ret=Runtime.stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),"stringToC":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=Runtime.stackAlloc(len);stringToUTF8(str,ret,len)}return ret})};var toC={"string":JSfuncs["stringToC"],"array":JSfuncs["arrayToC"]};ccall=function ccallFunc(ident,returnType,argTypes,args,opts){var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=Runtime.stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);if(returnType==="string")ret=Pointer_stringify(ret);if(stack!==0){if(opts&&opts.async){EmterpreterAsync.asyncFinalizers.push((function(){Runtime.stackRestore(stack)}));return}Runtime.stackRestore(stack)}return ret};cwrap=function cwrap(ident,returnType,argTypes){return(function(){return ccall(ident,returnType,argTypes,arguments)})}}))();Module["ccall"]=ccall;Module["cwrap"]=cwrap;function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}Module["setValue"]=setValue;function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for setValue: "+type)}return null}Module["getValue"]=getValue;var ALLOC_NORMAL=0;var ALLOC_STACK=1;var ALLOC_STATIC=2;var ALLOC_DYNAMIC=3;var ALLOC_NONE=4;Module["ALLOC_NORMAL"]=ALLOC_NORMAL;Module["ALLOC_STACK"]=ALLOC_STACK;Module["ALLOC_STATIC"]=ALLOC_STATIC;Module["ALLOC_DYNAMIC"]=ALLOC_DYNAMIC;Module["ALLOC_NONE"]=ALLOC_NONE;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="number"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types==="string"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[typeof _malloc==="function"?_malloc:Runtime.staticAlloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var ptr=ret,stop;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr<stop;ptr+=4){HEAP32[ptr>>2]=0}stop=ret+size;while(ptr<stop){HEAP8[ptr++>>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i<size){var curr=slab[i];if(typeof curr==="function"){curr=Runtime.getFunctionIndex(curr)}type=singleType||types[i];if(type===0){i++;continue}if(type=="i64")type="i32";setValue(ret+i,curr,type);if(previousType!==type){typeSize=Runtime.getNativeTypeSize(type);previousType=type}i+=typeSize}return ret}Module["allocate"]=allocate;function getMemory(size){if(!staticSealed)return Runtime.staticAlloc(size);if(!runtimeInitialized)return Runtime.dynamicAlloc(size);return _malloc(size)}Module["getMemory"]=getMemory;function Pointer_stringify(ptr,length){if(length===0||!ptr)return"";var hasUtf=0;var t;var i=0;while(1){t=HEAPU8[ptr+i>>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret="";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return Module["UTF8ToString"](ptr)}Module["Pointer_stringify"]=Pointer_stringify;function AsciiToString(ptr){var str="";while(1){var ch=HEAP8[ptr++>>0];if(!ch)return str;str+=String.fromCharCode(ch)}}Module["AsciiToString"]=AsciiToString;function stringToAscii(str,outPtr){return writeAsciiToMemory(str,outPtr,false)}Module["stringToAscii"]=stringToAscii;var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(u8Array,idx){var endPtr=idx;while(u8Array[endPtr])++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var u0,u1,u2,u3,u4,u5;var str="";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}}Module["UTF8ArrayToString"]=UTF8ArrayToString;function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}Module["UTF8ToString"]=UTF8ToString;function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}Module["stringToUTF8Array"]=stringToUTF8Array;function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}Module["stringToUTF8"]=stringToUTF8;function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}Module["lengthBytesUTF8"]=lengthBytesUTF8;var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function demangle(func){var hasLibcxxabi=!!Module["___cxa_demangle"];if(hasLibcxxabi){try{var s=func.substr(1);var len=lengthBytesUTF8(s)+1;var buf=_malloc(len);stringToUTF8(s,buf,len);var status=_malloc(4);var ret=Module["___cxa_demangle"](buf,0,0,status);if(getValue(status,"i32")===0&&ret){return Pointer_stringify(ret)}}catch(e){}finally{if(buf)_free(buf);if(status)_free(status);if(ret)_free(ret)}return func}Runtime.warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){return text.replace(/__Z[\w\d_]+/g,(function(x){var y=demangle(x);return x===y?x:x+" ["+y+"]"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}Module["stackTrace"]=stackTrace;var PAGE_SIZE=4096;var HEAP;var buffer;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module["HEAP8"]=HEAP8=new Int8Array(buffer);Module["HEAP16"]=HEAP16=new Int16Array(buffer);Module["HEAP32"]=HEAP32=new Int32Array(buffer);Module["HEAPU8"]=HEAPU8=new Uint8Array(buffer);Module["HEAPU16"]=HEAPU16=new Uint16Array(buffer);Module["HEAPU32"]=HEAPU32=new Uint32Array(buffer);Module["HEAPF32"]=HEAPF32=new Float32Array(buffer);Module["HEAPF64"]=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed;var STACK_BASE,STACKTOP,STACK_MAX;var DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0;staticSealed=false;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which adjusts the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module["TOTAL_STACK"]||5242880;var TOTAL_MEMORY=Module["TOTAL_MEMORY"]||35e6;var WASM_PAGE_SIZE=64*1024;var totalMemory=WASM_PAGE_SIZE;while(totalMemory<TOTAL_MEMORY||totalMemory<2*TOTAL_STACK){if(totalMemory<16*1024*1024){totalMemory*=2}else{totalMemory+=16*1024*1024}}if(totalMemory!==TOTAL_MEMORY){TOTAL_MEMORY=totalMemory}if(Module["buffer"]){buffer=Module["buffer"]}else{{buffer=new ArrayBuffer(TOTAL_MEMORY)}}updateGlobalBufferViews();function getTotalMemory(){return TOTAL_MEMORY}HEAP32[0]=1668509029;HEAP16[1]=25459;if(HEAPU8[2]!==115||HEAPU8[3]!==99)throw"Runtime error: expected the system to be little-endian!";Module["HEAP"]=HEAP;Module["buffer"]=buffer;Module["HEAP8"]=HEAP8;Module["HEAP16"]=HEAP16;Module["HEAP32"]=HEAP32;Module["HEAPU8"]=HEAPU8;Module["HEAPU16"]=HEAPU16;Module["HEAPU32"]=HEAPU32;Module["HEAPF32"]=HEAPF32;Module["HEAPF64"]=HEAPF64;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Runtime.dynCall("v",func)}else{Runtime.dynCall("vi",func,[callback.arg])}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}Module["addOnPreRun"]=addOnPreRun;function addOnInit(cb){__ATINIT__.unshift(cb)}Module["addOnInit"]=addOnInit;function addOnPreMain(cb){__ATMAIN__.unshift(cb)}Module["addOnPreMain"]=addOnPreMain;function addOnExit(cb){__ATEXIT__.unshift(cb)}Module["addOnExit"]=addOnExit;function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}Module["addOnPostRun"]=addOnPostRun;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}Module["intArrayFromString"]=intArrayFromString;function intArrayToString(array){var ret=[];for(var i=0;i<array.length;i++){var chr=array[i];if(chr>255){chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}Module["intArrayToString"]=intArrayToString;function writeStringToMemory(string,buffer,dontAddNull){Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");var lastChar,end;if(dontAddNull){end=buffer+lengthBytesUTF8(string);lastChar=HEAP8[end]}stringToUTF8(string,buffer,Infinity);if(dontAddNull)HEAP8[end]=lastChar}Module["writeStringToMemory"]=writeStringToMemory;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}Module["writeArrayToMemory"]=writeArrayToMemory;function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}Module["writeAsciiToMemory"]=writeAsciiToMemory;if(!Math["imul"]||Math["imul"](4294967295,5)!==-5)Math["imul"]=function imul(a,b){var ah=a>>>16;var al=a&65535;var bh=b>>>16;var bl=b&65535;return al*bl+(ah*bl+al*bh<<16)|0};Math.imul=Math["imul"];if(!Math["clz32"])Math["clz32"]=(function(x){x=x>>>0;for(var i=0;i<32;i++){if(x&1<<31-i)return i}return 32});Math.clz32=Math["clz32"];if(!Math["trunc"])Math["trunc"]=(function(x){return x<0?Math.ceil(x):Math.floor(x)});Math.trunc=Math["trunc"];var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_round=Math.round;var Math_min=Math.min;var Math_clz32=Math.clz32;var Math_trunc=Math.trunc;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}Module["addRunDependency"]=addRunDependency;function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["removeRunDependency"]=removeRunDependency;Module["preloadedImages"]={};Module["preloadedAudios"]={};var ASM_CONSTS=[(function(){{return Module.getRandomValue()}}),(function(){{if(Module.getRandomValue===undefined){try{var window_="object"===typeof window?window:self,crypto_=typeof window_.crypto!=="undefined"?window_.crypto:window_.msCrypto,randomValuesStandard=(function(){var buf=new Uint32Array(1);crypto_.getRandomValues(buf);return buf[0]>>>0});randomValuesStandard();Module.getRandomValue=randomValuesStandard}catch(e){try{var crypto=require("crypto"),randomValueNodeJS=(function(){var buf=crypto.randomBytes(4);return(buf[0]<<24|buf[1]<<16|buf[2]<<8|buf[3])>>>0});randomValueNodeJS();Module.getRandomValue=randomValueNodeJS}catch(e){throw"No secure random number generator found"}}}}})];function _emscripten_asm_const_i(code){return ASM_CONSTS[code]()}function _emscripten_asm_const_v(code){return ASM_CONSTS[code]()}STATIC_BASE=8;STATICTOP=STATIC_BASE+34544;__ATINIT__.push();allocate([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,232,149,143,194,178,39,176,69,195,244,137,242,239,152,240,213,223,172,5,211,198,51,57,177,56,2,136,109,83,252,5,199,23,106,112,61,77,216,79,186,60,11,118,13,16,103,15,42,32,83,250,44,57,204,198,78,199,253,119,146,172,3,122,19,232,149,143,194,178,39,176,69,195,244,137,242,239,152,240,213,223,172,5,211,198,51,57,177,56,2,136,109,83,252,133,180,23,106,112,61,77,216,79,186,60,11,118,13,16,103,15,42,32,83,250,44,57,204,198,78,199,253,119,146,172,3,250,236,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,127,237,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,127,238,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,127,217,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,218,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,219,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,8,201,188,243,103,230,9,106,59,167,202,132,133,174,103,187,43,248,148,254,114,243,110,60,241,54,29,95,58,245,79,165,209,130,230,173,127,82,14,81,31,108,62,43,140,104,5,155,107,189,65,251,171,217,131,31,121,33,126,19,25,205,224,91,182,120,89,255,133,114,211,0,189,110,21,255,15,10,106,0,41,192,1,0,152,232,121,255,188,60,160,255,153,113,206,255,0,183,226,254,180,13,72,255,176,160,14,254,211,201,134,255,158,24,143,0,127,105,53,0,96,12,189,0,167,215,251,255,159,76,128,254,106,101,225,255,30,252,4,0,146,12,174,0,89,241,178,254,10,229,166,255,123,221,42,254,30,20,212,0,82,128,3,0,48,209,243,0,119,121,64,255,50,227,156,255,0,110,197,1,103,27,144,0,133,59,140,1,189,241,36,255,248,37,195,1,96,220,55,0,183,76,62,255,195,66,61,0,50,76,164,1,225,164,76,255,76,61,163,255,117,62,31,0,81,145,64,255,118,65,14,0,162,115,214,255,6,138,46,0,124,230,244,255,10,138,143,0,52,26,194,0,184,244,76,0,129,143,41,1,190,244,19,255,123,170,122,255,98,129,68,0,121,213,147,0,86,101,30,255,161,103,155,0,140,89,67,255,239,229,190,1,67,11,181,0,198,240,137,254,238,69,188,255,67,151,238,0,19,42,108,255,229,85,113,1,50,68,135,255,17,106,9,0,50,103,1,255,80,1,168,1,35,152,30,255,16,168,185,1,56,89,232,255,101,210,252,0,41,250,71,0,204,170,79,255,14,46,239,255,80,77,239,0,189,214,75,255,17,141,249,0,38,80,76,255,190,85,117,0,86,228,170,0,156,216,208,1,195,207,164,255,150,66,76,255,175,225,16,255,141,80,98,1,76,219,242,0,198,162,114,0,46,218,152,0,155,43,241,254,155,160,104,255,51,187,165,0,2,17,175,0,66,84,160,1,247,58,30,0,35,65,53,254,69,236,191,0,45,134,245,1,163,123,221,0,32,110,20,255,52,23,165,0,186,214,71,0,233,176,96,0,242,239,54,1,57,89,138,0,83,0,84,255,136,160,100,0,92,142,120,254,104,124,190,0,181,177,62,255,250,41,85,0,152,130,42,1,96,252,246,0,151,151,63,254,239,133,62,0,32,56,156,0,45,167,189,255,142,133,179,1,131,86,211,0,187,179,150,254,250,170,14,255,210,163,78,0,37,52,151,0,99,77,26,0,238,156,213,255,213,192,209,1,73,46,84,0,20,65,41,1,54,206,79,0,201,131,146,254,170,111,24,255,177,33,50,254,171,38,203,255,78,247,116,0,209,221,153,0,133,128,178,1,58,44,25,0,201,39,59,1,189,19,252,0,49,229,210,1,117,187,117,0,181,179,184,1,0,114,219,0,48,94,147,0,245,41,56,0,125,13,204,254,244,173,119,0,44,221,32,254,84,234,20,0,249,160,198,1,236,126,234,255,47,99,168,254,170,226,153,255,102,179,216,0,226,141,122,255,122,66,153,254,182,245,134,0,227,228,25,1,214,57,235,255,216,173,56,255,181,231,210,0,119,128,157,255,129,95,136,255,110,126,51,0,2,169,183,255,7,130,98,254,69,176,94,255,116,4,227,1,217,242,145,255,202,173,31,1,105,1,39,255,46,175,69,0,228,47,58,255,215,224,69,254,207,56,69,255,16,254,139,255,23,207,212,255,202,20,126,255,95,213,96,255,9,176,33,0,200,5,207,255,241,42,128,254,35,33,192,255,248,229,196,1,129,17,120,0,251,103,151,255,7,52,112,255,140,56,66,255,40,226,245,255,217,70,37,254,172,214,9,255,72,67,134,1,146,192,214,255,44,38,112,0,68,184,75,255,206,90,251,0,149,235,141,0,181,170,58,0,116,244,239,0,92,157,2,0,102,173,98,0,233,137,96,1,127,49,203,0,5,155,148,0,23,148,9,255,211,122,12,0,34,134,26,255,219,204,136,0,134,8,41,255,224,83,43,254,85,25,247,0,109,127,0,254,169,136,48,0,238,119,219,255,231,173,213,0,206,18,254,254,8,186,7,255,126,9,7,1,111,42,72,0,111,52,236,254,96,63,141,0,147,191,127,254,205,78,192,255,14,106,237,1,187,219,76,0,175,243,187,254,105,89,173,0,85,25,89,1,162,243,148,0,2,118,209,254,33,158,9,0,139,163,46,255,93,70,40,0,108,42,142,254,111,252,142,255,155,223,144,0,51,229,167,255,73,252,155,255,94,116,12,255,152,160,218,255,156,238,37,255,179,234,207,255,197,0,179,255,154,164,141,0,225,196,104,0,10,35,25,254,209,212,242,255,97,253,222,254,184,101,229,0,222,18,127,1,164,136,135,255,30,207,140,254,146,97,243,0,129,192,26,254,201,84,33,255,111,10,78,255,147,81,178,255,4,4,24,0,161,238,215,255,6,141,33,0,53,215,14,255,41,181,208,255,231,139,157,0,179,203,221,255,255,185,113,0,189,226,172,255,113,66,214,255,202,62,45,255,102,64,8,255,78,174,16,254,133,117,68,255,133,59,140,1,189,241,36,255,248,37,195,1,96,220,55,0,183,76,62,255,195,66,61,0,50,76,164,1,225,164,76,255,76,61,163,255,117,62,31,0,81,145,64,255,118,65,14,0,162,115,214,255,6,138,46,0,124,230,244,255,10,138,143,0,52,26,194,0,184,244,76,0,129,143,41,1,190,244,19,255,123,170,122,255,98,129,68,0,121,213,147,0,86,101,30,255,161,103,155,0,140,89,67,255,239,229,190,1,67,11,181,0,198,240,137,254,238,69,188,255,234,113,60,255,37,255,57,255,69,178,182,254,128,208,179,0,118,26,125,254,3,7,214,255,241,50,77,255,85,203,197,255,211,135,250,255,25,48,100,255,187,213,180,254,17,88,105,0,83,209,158,1,5,115,98,0,4,174,60,254,171,55,110,255,217,181,17,255,20,188,170,0,146,156,102,254,87,214,174,255,114,122,155,1,233,44,170,0,127,8,239,1,214,236,234,0,175,5,219,0,49,106,61,255,6,66,208,255,2,106,110,255,81,234,19,255,215,107,192,255,67,151,238,0,19,42,108,255,229,85,113,1,50,68,135,255,17,106,9,0,50,103,1,255,80,1,168,1,35,152,30,255,16,168,185,1,56,89,232,255,101,210,252,0,41,250,71,0,204,170,79,255,14,46,239,255,80,77,239,0,189,214,75,255,17,141,249,0,38,80,76,255,190,85,117,0,86,228,170,0,156,216,208,1,195,207,164,255,150,66,76,255,175,225,16,255,141,80,98,1,76,219,242,0,198,162,114,0,46,218,152,0,155,43,241,254,155,160,104,255,178,9,252,254,100,110,212,0,14,5,167,0,233,239,163,255,28,151,157,1,101,146,10,255,254,158,70,254,71,249,228,0,88,30,50,0,68,58,160,255,191,24,104,1,129,66,129,255,192,50,85,255,8,179,138,255,38,250,201,0,115,80,160,0,131,230,113,0,125,88,147,0,90,68,199,0,253,76,158,0,28,255,118,0,113,250,254,0,66,75,46,0,230,218,43,0,229,120,186,1,148,68,43,0,136,124,238,1,187,107,197,255,84,53,246,255,51,116,254,255,51,187,165,0,2,17,175,0,66,84,160,1,247,58,30,0,35,65,53,254,69,236,191,0,45,134,245,1,163,123,221,0,32,110,20,255,52,23,165,0,186,214,71,0,233,176,96,0,242,239,54,1,57,89,138,0,83,0,84,255,136,160,100,0,92,142,120,254,104,124,190,0,181,177,62,255,250,41,85,0,152,130,42,1,96,252,246,0,151,151,63,254,239,133,62,0,32,56,156,0,45,167,189,255,142,133,179,1,131,86,211,0,187,179,150,254,250,170,14,255,68,113,21,255,222,186,59,255,66,7,241,1,69,6,72,0,86,156,108,254,55,167,89,0,109,52,219,254,13,176,23,255,196,44,106,255,239,149,71,255,164,140,125,255,159,173,1,0,51,41,231,0,145,62,33,0,138,111,93,1,185,83,69,0,144,115,46,0,97,151,16,255,24,228,26,0,49,217,226,0,113,75,234,254,193,153,12,255,182,48,96,255,14,13,26,0,128,195,249,254,69,193,59,0,132,37,81,254,125,106,60,0,214,240,169,1,164,227,66,0,210,163,78,0,37,52,151,0,99,77,26,0,238,156,213,255,213,192,209,1,73,46,84,0,20,65,41,1,54,206,79,0,201,131,146,254,170,111,24,255,177,33,50,254,171,38,203,255,78,247,116,0,209,221,153,0,133,128,178,1,58,44,25,0,201,39,59,1,189,19,252,0,49,229,210,1,117,187,117,0,181,179,184,1,0,114,219,0,48,94,147,0,245,41,56,0,125,13,204,254,244,173,119,0,44,221,32,254,84,234,20,0,249,160,198,1,236,126,234,255,143,62,221,0,129,89,214,255,55,139,5,254,68,20,191,255,14,204,178,1,35,195,217,0,47,51,206,1,38,246,165,0,206,27,6,254,158,87,36,0,217,52,146,255,125,123,215,255,85,60,31,255,171,13,7,0,218,245,88,254,252,35,60,0,55,214,160,255,133,101,56,0,224,32,19,254,147,64,234,0,26,145,162,1,114,118,125,0,248,252,250,0,101,94,196,255,198,141,226,254,51,42,182,0,135,12,9,254,109,172,210,255,197,236,194,1,241,65,154,0,48,156,47,255,153,67,55,255,218,165,34,254,74,180,179,0,218,66,71,1,88,122,99,0,212,181,219,255,92,42,231,255,239,0,154,0,245,77,183,255,94,81,170,1,18,213,216,0,171,93,71,0,52,94,248,0,18,151,161,254,197,209,66,255,174,244,15,254,162,48,183,0,49,61,240,254,182,93,195,0,199,228,6,1,200,5,17,255,137,45,237,255,108,148,4,0,90,79,237,255,39,63,77,255,53,82,207,1,142,22,118,255,101,232,18,1,92,26,67,0,5,200,88,255,33,168,138,255,149,225,72,0,2,209,27,255,44,245,168,1,220,237,17,255,30,211,105,254,141,238,221,0,128,80,245,254,111,254,14,0,222,95,190,1,223,9,241,0,146,76,212,255,108,205,104,255,63,117,153,0,144,69,48,0,35,228,111,0,192,33,193,255,112,214,190,254,115,152,151,0,23,102,88,0,51,74,248,0,226,199,143,254,204,162,101,255,208,97,189,1,245,104,18,0,230,246,30,255,23,148,69,0,110,88,52,254,226,181,89,255,208,47,90,254,114,161,80,255,33,116,248,0,179,152,87,255,69,144,177,1,88,238,26,255,58,32,113,1,1,77,69,0,59,121,52,255,152,238,83,0,52,8,193,0,231,39,233,255,199,34,138,0,222,68,173,0,91,57,242,254,220,210,127,255,192,7,246,254,151,35,187,0,195,236,165,0,111,93,206,0,212,247,133,1,154,133,209,255,155,231,10,0,64,78,38,0,122,249,100,1,30,19,97,255,62,91,249,1,248,133,77,0,197,63,168,254,116,10,82,0,184,236,113,254,212,203,194,255,61,100,252,254,36,5,202,255,119,91,153,255,129,79,29,0,103,103,171,254,237,215,111,255,216,53,69,0,239,240,23,0,194,149,221,255,38,225,222,0,232,255,180,254,118,82,133,255,57,209,177,1,139,232,133,0,158,176,46,254,194,115,46,0,88,247,229,1,28,103,191,0,221,222,175,254,149,235,44,0,151,228,25,254,218,105,103,0,142,85,210,0,149,129,190,255,213,65,94,254,117,134,224,255,82,198,117,0,157,221,220,0,163,101,36,0,197,114,37,0,104,172,166,254,11,182,0,0,81,72,188,255,97,188,16,255,69,6,10,0,199,147,145,255,8,9,115,1,65,214,175,255,217,173,209,0,80,127,166,0,247,229,4,254,167,183,124,255,90,28,204,254,175,59,240,255,11,41,248,1,108,40,51,255,144,177,195,254,150,250,126,0,138,91,65,1,120,60,222,255,245,193,239,0,29,214,189,255,128,2,25,0,80,154,162,0,77,220,107,1,234,205,74,255,54,166,103,255,116,72,9,0,228,94,47,255,30,200,25,255,35,214,89,255,61,176,140,255,83,226,163,255,75,130,172,0,128,38,17,0,95,137,152,255,215,124,159,1,79,93,0,0,148,82,157,254,195,130,251,255,40,202,76,255,251,126,224,0,157,99,62,254,207,7,225,255,96,68,195,0,140,186,157,255,131,19,231,255,42,128,254,0,52,219,61,254,102,203,72,0,141,7,11,255,186,164,213,0,31,122,119,0,133,242,145,0,208,252,232,255,91,213,182,255,143,4,250,254,249,215,74,0,165,30,111,1,171,9,223,0,229,123,34,1,92,130,26,255,77,155,45,1,195,139,28,255,59,224,78,0,136,17,247,0,108,121,32,0,79,250,189,255,96,227,252,254,38,241,62,0,62,174,125,255,155,111,93,255,10,230,206,1,97,197,40,255,0,49,57,254,65,250,13,0,18,251,150,255,220,109,210,255,5,174,166,254,44,129,189,0,235,35,147,255,37,247,141,255,72,141,4,255,103,107,255,0,247,90,4,0,53,44,42,0,2,30,240,0,4,59,63,0,88,78,36,0,113,167,180,0,190,71,193,255,199,158,164,255,58,8,172,0,77,33,12,0,65,63,3,0,153,77,33,255,172,254,102,1,228,221,4,255,87,30,254,1,146,41,86,255,138,204,239,254,108,141,17,255,187,242,135,0,210,208,127,0,68,45,14,254,73,96,62,0,81,60,24,255,170,6,36,255,3,249,26,0,35,213,109,0,22,129,54,255,21,35,225,255,234,61,56,255,58,217,6,0,143,124,88,0,236,126,66,0,209,38,183,255,34,238,6,255,174,145,102,0,95,22,211,0,196,15,153,254,46,84,232,255,117,34,146,1,231,250,74,255,27,134,100,1,92,187,195,255,170,198,112,0,120,28,42,0,209,70,67,0,29,81,31,0,29,168,100,1,169,173,160,0,107,35,117,0,62,96,59,255,81,12,69,1,135,239,190,255,220,252,18,0,163,220,58,255,137,137,188,255,83,102,109,0,96,6,76,0,234,222,210,255,185,174,205,1,60,158,213,255,13,241,214,0,172,129,140,0,93,104,242,0,192,156,251,0,43,117,30,0,225,81,158,0,127,232,218,0,226,28,203,0,233,27,151,255,117,43,5,255,242,14,47,255,33,20,6,0,137,251,44,254,27,31,245,255,183,214,125,254,40,121,149,0,186,158,213,255,89,8,227,0,69,88,0,254,203,135,225,0,201,174,203,0,147,71,184,0,18,121,41,254,94,5,78,0,224,214,240,254,36,5,180,0,251,135,231,1,163,138,212,0,210,249,116,254,88,129,187,0,19,8,49,254,62,14,144,255,159,76,211,0,214,51,82,0,109,117,228,254,103,223,203,255,75,252,15,1,154,71,220,255,23,13,91,1,141,168,96,255,181,182,133,0,250,51,55,0,234,234,212,254,175,63,158,0,39,240,52,1,158,189,36,255,213,40,85,1,32,180,247,255,19,102,26,1,84,24,97,255,69,21,222,0,148,139,122,255,220,213,235,1,232,203,255,0,121,57,147,0,227,7,154,0,53,22,147,1,72,1,225,0,82,134,48,254,83,60,157,255,145,72,169,0,34,103,239,0,198,233,47,0,116,19,4,255,184,106,9,255,183,129,83,0,36,176,230,1,34,103,72,0,219,162,134,0,245,42,158,0,32,149,96,254,165,44,144,0,202,239,72,254,215,150,5,0,42,66,36,1,132,215,175,0,86,174,86,255,26,197,156,255,49,232,135,254,103,182,82,0,253,128,176,1,153,178,122,0,245,250,10,0,236,24,178,0,137,106,132,0,40,29,41,0,50,30,152,255,124,105,38,0,230,191,75,0,143,43,170,0,44,131,20,255,44,13,23,255,237,255,155,1,159,109,100,255,112,181,24,255,104,220,108,0,55,211,131,0,99,12,213,255,152,151,145,255,238,5,159,0,97,155,8,0,33,108,81,0,1,3,103,0,62,109,34,255,250,155,180,0,32,71,195,255,38,70,145,1,159,95,245,0,69,229,101,1,136,28,240,0,79,224,25,0,78,110,121,255,248,168,124,0,187,128,247,0,2,147,235,254,79,11,132,0,70,58,12,1,181,8,163,255,79,137,133,255,37,170,11,255,141,243,85,255,176,231,215,255,204,150,164,255,239,215,39,255,46,87,156,254,8,163,88,255,172,34,232,0,66,44,102,255,27,54,41,254,236,99,87,255,41,123,169,1,52,114,43,0,117,134,40,0,155,134,26,0,231,207,91,254,35,132,38,255,19,102,125,254,36,227,133,255,118,3,113,255,29,13,124,0,152,96,74,1,88,146,206,255,167,191,220,254,162,18,88,255,182,100,23,0,31,117,52,0,81,46,106,1,12,2,7,0,69,80,201,1,209,246,172,0,12,48,141,1,224,211,88,0,116,226,159,0,122,98,130,0,65,236,234,1,225,226,9,255,207,226,123,1,89,214,59,0,112,135,88,1,90,244,203,255,49,11,38,1,129,108,186,0,89,112,15,1,101,46,204,255,127,204,45,254,79,255,221,255,51,73,18,255,127,42,101,255,241,21,202,0,160,227,7,0,105,50,236,0,79,52,197,255,104,202,208,1,180,15,16,0,101,197,78,255,98,77,203,0,41,185,241,1,35,193,124,0,35,155,23,255,207,53,192,0,11,125,163,1,249,158,185,255,4,131,48,0,21,93,111,255,61,121,231,1,69,200,36,255,185,48,185,255,111,238,21,255,39,50,25,255,99,215,163,255,87,212,30,255,164,147,5,255,128,6,35,1,108,223,110,255,194,76,178,0,74,101,180,0,243,47,48,0,174,25,43,255,82,173,253,1,54,114,192,255,40,55,91,0,215,108,176,255,11,56,7,0,224,233,76,0,209,98,202,254,242,25,125,0,44,193,93,254,203,8,177,0,135,176,19,0,112,71,213,255,206,59,176,1,4,67,26,0,14,143,213,254,42,55,208,255,60,67,120,0,193,21,163,0,99,164,115,0,10,20,118,0,156,212,222,254,160,7,217,255,114,245,76,1,117,59,123,0,176,194,86,254,213,15,176,0,78,206,207,254,213,129,59,0,233,251,22,1,96,55,152,255,236,255,15,255,197,89,84,255,93,149,133,0,174,160,113,0,234,99,169,255,152,116,88,0,144,164,83,255,95,29,198,255,34,47,15,255,99,120,134,255,5,236,193,0,249,247,126,255,147,187,30,0,50,230,117,255,108,217,219,255,163,81,166,255,72,25,169,254,155,121,79,255,28,155,89,254,7,126,17,0,147,65,33,1,47,234,253,0,26,51,18,0,105,83,199,255,163,196,230,0,113,248,164,0,226,254,218,0,189,209,203,255,164,247,222,254,255,35,165,0,4,188,243,1,127,179,71,0,37,237,254,255,100,186,240,0,5,57,71,254,103,72,73,255,244,18,81,254,229,210,132,255,238,6,180,255,11,229,174,255,227,221,192,1,17,49,28,0,163,215,196,254,9,118,4,255,51,240,71,0,113,129,109,255,76,240,231,0,188,177,127,0,125,71,44,1,26,175,243,0,94,169,25,254,27,230,29,0,15,139,119,1,168,170,186,255,172,197,76,255,252,75,188,0,137,124,196,0,72,22,96,255,45,151,249,1,220,145,100,0,64,192,159,255,120,239,226,0,129,178,146,0,0,192,125,0,235,138,234,0,183,157,146,0,83,199,192,255,184,172,72,255,73,225,128,0,77,6,250,255,186,65,67,0,104,246,207,0,188,32,138,255,218,24,242,0,67,138,81,254,237,129,121,255,20,207,150,1,41,199,16,255,6,20,128,0,159,118,5,0,181,16,143,255,220,38,15,0,23,64,147,254,73,26,13,0,87,228,57,1,204,124,128,0,43,24,223,0,219,99,199,0,22,75,20,255,19,27,126,0,157,62,215,0,110,29,230,0,179,167,255,1,54,252,190,0,221,204,182,254,179,158,65,255,81,157,3,0,194,218,159,0,170,223,0,0,224,11,32,255,38,197,98,0,168,164,37,0,23,88,7,1,164,186,110,0,96,36,134,0,234,242,229,0,250,121,19,0,242,254,112,255,3,47,94,1,9,239,6,255,81,134,153,254,214,253,168,255,67,124,224,0,245,95,74,0,28,30,44,254,1,109,220,255,178,89,89,0,252,36,76,0,24,198,46,255,76,77,111,0,134,234,136,255,39,94,29,0,185,72,234,255,70,68,135,255,231,102,7,254,77,231,140,0,167,47,58,1,148,97,118,255,16,27,225,1,166,206,143,255,110,178,214,255,180,131,162,0,143,141,225,1,13,218,78,255,114,153,33,1,98,104,204,0,175,114,117,1,167,206,75,0,202,196,83,1,58,64,67,0,138,47,111,1,196,247,128,255,137,224,224,254,158,112,207,0,154,100,255,1,134,37,107,0,198,128,79,255,127,209,155,255,163,254,185,254,60,14,243,0,31,219,112,254,29,217,65,0,200,13,116,254,123,60,196,255,224,59,184,254,242,89,196,0,123,16,75,254,149,16,206,0,69,254,48,1,231,116,223,255,209,160,65,1,200,80,98,0,37,194,184,254,148,63,34,0,139,240,65,255,217,144,132,255,56,38,45,254,199,120,210,0,108,177,166,255,160,222,4,0,220,126,119,254,165,107,160,255,82,220,248,1,241,175,136,0,144,141,23,255,169,138,84,0,160,137,78,255,226,118,80,255,52,27,132,255,63,96,139,255,152,250,39,0,188,155,15,0,232,51,150,254,40,15,232,255,240,229,9,255,137,175,27,255,75,73,97,1,218,212,11,0,135,5,162,1,107,185,213,0,2,249,107,255,40,242,70,0,219,200,25,0,25,157,13,0,67,82,80,255,196,249,23,255,145,20,149,0,50,72,146,0,94,76,148,1,24,251,65,0,31,192,23,0,184,212,201,255,123,233,162,1,247,173,72,0,162,87,219,254,126,134,89,0,159,11,12,254,166,105,29,0,73,27,228,1,113,120,183,255,66,163,109,1,212,143,11,255,159,231,168,1,255,128,90,0,57,14,58,254,89,52,10,255,253,8,163,1,0,145,210,255,10,129,85,1,46,181,27,0,103,136,160,254,126,188,209,255,34,35,111,0,215,219,24,255,212,11,214,254,101,5,118,0,232,197,133,255,223,167,109,255,237,80,86,255,70,139,94,0,158,193,191,1,155,15,51,255,15,190,115,0,78,135,207,255,249,10,27,1,181,125,233,0,95,172,13,254,170,213,161,255,39,236,138,255,95,93,87,255,190,128,95,0,125,15,206,0,166,150,159,0,227,15,158,255,206,158,120,255,42,141,128,0,101,178,120,1,156,109,131,0,218,14,44,254,247,168,206,255,212,112,28,0,112,17,228,255,90,16,37,1,197,222,108,0,254,207,83,255,9,90,243,255,243,244,172,0,26,88,115,255,205,116,122,0,191,230,193,0,180,100,11,1,217,37,96,255,154,78,156,0,235,234,31,255,206,178,178,255,149,192,251,0,182,250,135,0,246,22,105,0,124,193,109,255,2,210,149,255,169,17,170,0,0,96,110,255,117,9,8,1,50,123,40,255,193,189,99,0,34,227,160,0,48,80,70,254,211,51,236,0,45,122,245,254,44,174,8,0,173,37,233,255,158,65,171,0,122,69,215,255,90,80,2,255,131,106,96,254,227,114,135,0,205,49,119,254,176,62,64,255,82,51,17,255,241,20,243,255,130,13,8,254,128,217,243,255,162,27,1,254,90,118,241,0,246,198,246,255,55,16,118,255,200,159,157,0,163,17,1,0,140,107,121,0,85,161,118,255,38,0,149,0,156,47,238,0,9,166,166,1,75,98,181,255,50,74,25,0,66,15,47,0,139,225,159,0,76,3,142,255,14,238,184,0,11,207,53,255,183,192,186,1,171,32,174,255,191,76,221,1,247,170,219,0,25,172,50,254,217,9,233,0,203,126,68,255,183,92,48,0,127,167,183,1,65,49,254,0,16,63,127,1,254,21,170,255,59,224,127,254,22,48,63,255,27,78,130,254,40,195,29,0,250,132,112,254,35,203,144,0,104,169,168,0,207,253,30,255,104,40,38,254,94,228,88,0,206,16,128,255,212,55,122,255,223,22,234,0,223,197,127,0,253,181,181,1,145,102,118,0,236,153,36,255,212,217,72,255,20,38,24,254,138,62,62,0,152,140,4,0,230,220,99,255,1,21,212,255,148,201,231,0,244,123,9,254,0,171,210,0,51,58,37,255,1,255,14,255,244,183,145,254,0,242,166,0,22,74,132,0,121,216,41,0,95,195,114,254,133,24,151,255,156,226,231,255,247,5,77,255,246,148,115,254,225,92,81,255,222,80,246,254,170,123,89,255,74,199,141,0,29,20,8,255,138,136,70,255,93,75,92,0,221,147,49,254,52,126,226,0,229,124,23,0,46,9,181,0,205,64,52,1,131,254,28,0,151,158,212,0,131,64,78,0,206,25,171,0,0,230,139,0,191,253,110,254,103,247,167,0,64,40,40,1,42,165,241,255,59,75,228,254,124,243,189,255,196,92,178,255,130,140,86,255,141,89,56,1,147,198,5,255,203,248,158,254,144,162,141,0,11,172,226,0,130,42,21,255,1,167,143,255,144,36,36,255,48,88,164,254,168,170,220,0,98,71,214,0,91,208,79,0,159,76,201,1,166,42,214,255,69,255,0,255,6,128,125,255,190,1,140,0,146,83,218,255,215,238,72,1,122,127,53,0,189,116,165,255,84,8,66,255,214,3,208,255,213,110,133,0,195,168,44,1,158,231,69,0,162,64,200,254,91,58,104,0,182,58,187,254,249,228,136,0,203,134,76,254,99,221,233,0,75,254,214,254,80,69,154,0,64,152,248,254,236,136,202,255,157,105,153,254,149,175,20,0,22,35,19,255,124,121,233,0,186,250,198,254,132,229,139,0,137,80,174,255,165,125,68,0,144,202,148,254,235,239,248,0,135,184,118,0,101,94,17,255,122,72,70,254,69,130,146,0,127,222,248,1,69,127,118,255,30,82,215,254,188,74,19,255,229,167,194,254,117,25,66,255,65,234,56,254,213,22,156,0,151,59,93,254,45,28,27,255,186,126,164,255,32,6,239,0,127,114,99,1,219,52,2,255,99,96,166,254,62,190,126,255,108,222,168,1,75,226,174,0,230,226,199,0,60,117,218,255,252,248,20,1,214,188,204,0,31,194,134,254,123,69,192,255,169,173,36,254,55,98,91,0,223,42,102,254,137,1,102,0,157,90,25,0,239,122,64,255,252,6,233,0,7,54,20,255,82,116,174,0,135,37,54,255,15,186,125,0,227,112,175,255,100,180,225,255,42,237,244,255,244,173,226,254,248,18,33,0,171,99,150,255,74,235,50,255,117,82,32,254,106,168,237,0,207,109,208,1,228,9,186,0,135,60,169,254,179,92,143,0,244,170,104,255,235,45,124,255,70,99,186,0,117,137,183,0,224,31,215,0,40,9,100,0,26,16,95,1,68,217,87,0,8,151,20,255,26,100,58,255,176,165,203,1,52,118,70,0,7,32,254,254,244,254,245,255,167,144,194,255,125,113,23,255,176,121,181,0,136,84,209,0,138,6,30,255,89,48,28,0,33,155,14,255,25,240,154,0,141,205,109,1,70,115,62,255,20,40,107,254,138,154,199,255,94,223,226,255,157,171,38,0,163,177,25,254,45,118,3,255,14,222,23,1,209,190,81,255,118,123,232,1,13,213,101,255,123,55,123,254,27,246,165,0,50,99,76,255,140,214,32,255,97,65,67,255,24,12,28,0,174,86,78,1,64,247,96,0,160,135,67,0,66,55,243,255,147,204,96,255,26,6,33,255,98,51,83,1,153,213,208,255,2,184,54,255,25,218,11,0,49,67,246,254,18,149,72,255,13,25,72,0,42,79,214,0,42,4,38,1,27,139,144,255,149,187,23,0,18,164,132,0,245,84,184,254,120,198,104,255,126,218,96,0,56,117,234,255,13,29,214,254,68,47,10,255,167,154,132,254,152,38,198,0,66,178,89,255,200,46,171,255,13,99,83,255,210,187,253,255,170,45,42,1,138,209,124,0,214,162,141,0,12,230,156,0,102,36,112,254,3,147,67,0,52,215,123,255,233,171,54,255,98,137,62,0,247,218,39,255,231,218,236,0,247,191,127,0,195,146,84,0,165,176,92,255,19,212,94,255,17,74,227,0,88,40,153,1,198,147,1,255,206,67,245,254,240,3,218,255,61,141,213,255,97,183,106,0,195,232,235,254,95,86,154,0,209,48,205,254,118,209,241,255,240,120,223,1,213,29,159,0,163,127,147,255,13,218,93,0,85,24,68,254,70,20,80,255,189,5,140,1,82,97,254,255,99,99,191,255,132,84,133,255,107,218,116,255,112,122,46,0,105,17,32,0,194,160,63,255,68,222,39,1,216,253,92,0,177,105,205,255,149,201,195,0,42,225,11,255,40,162,115,0,9,7,81,0,165,218,219,0,180,22,0,254,29,146,252,255,146,207,225,1,180,135,96,0,31,163,112,0,177,11,219,255,133,12,193,254,43,78,50,0,65,113,121,1,59,217,6,255,110,94,24,1,112,172,111,0,7,15,96,0,36,85,123,0,71,150,21,255,208,73,188,0,192,11,167,1,213,245,34,0,9,230,92,0,162,142,39,255,215,90,27,0,98,97,89,0,94,79,211,0,90,157,240,0,95,220,126,1,102,176,226,0,36,30,224,254,35,31,127,0,231,232,115,1,85,83,130,0,210,73,245,255,47,143,114,255,68,65,197,0,59,72,62,255,183,133,173,254,93,121,118,255,59,177,81,255,234,69,173,255,205,128,177,0,220,244,51,0,26,244,209,1,73,222,77,255,163,8,96,254,150,149,211,0,158,254,203,1,54,127,139,0,161,224,59,0,4,109,22,255,222,42,45,255,208,146,102,255,236,142,187,0,50,205,245,255,10,74,89,254,48,79,142,0,222,76,130,255,30,166,63,0,236,12,13,255,49,184,244,0,187,113,102,0,218,101,253,0,153,57,182,254,32,150,42,0,25,198,146,1,237,241,56,0,140,68,5,0,91,164,172,255,78,145,186,254,67,52,205,0,219,207,129,1,109,115,17,0,54,143,58,1,21,248,120,255,179,255,30,0,193,236,66,255,1,255,7,255,253,192,48,255,19,69,217,1,3,214,0,255,64,101,146,1,223,125,35,255,235,73,179,255,249,167,226,0,225,175,10,1,97,162,58,0,106,112,171,1,84,172,5,255,133,140,178,255,134,245,142,0,97,90,125,255,186,203,185,255,223,77,23,255,192,92,106,0,15,198,115,255,217,152,248,0,171,178,120,255,228,134,53,0,176,54,193,1,250,251,53,0,213,10,100,1,34,199,106,0,151,31,244,254,172,224,87,255,14,237,23,255,253,85,26,255,127,39,116,255,172,104,100,0,251,14,70,255,212,208,138,255,253,211,250,0,176,49,165,0,15,76,123,255,37,218,160,255,92,135,16,1,10,126,114,255,70,5,224,255,247,249,141,0,68,20,60,1,241,210,189,255,195,217,187,1,151,3,113,0,151,92,174,0,231,62,178,255,219,183,225,0,23,23,33,255,205,181,80,0,57,184,248,255,67,180,1,255,90,123,93,255,39,0,162,255,96,248,52,255,84,66,140,0,34,127,228,255,194,138,7,1,166,110,188,0,21,17,155,1,154,190,198,255,214,80,59,255,18,7,143,0,72,29,226,1,199,217,249,0,232,161,71,1,149,190,201,0,217,175,95,254,113,147,67,255,138,143,199,255,127,204,1,0,29,182,83,1,206,230,155,255,186,204,60,0,10,125,85,255,232,96,25,255,255,89,247,255,213,254,175,1,232,193,81,0,28,43,156,254,12,69,8,0,147,24,248,0,18,198,49,0,134,60,35,0,118,246,18,255,49,88,254,254,228,21,186,255,182,65,112,1,219,22,1,255,22,126,52,255,189,53,49,255,112,25,143,0,38,127,55,255,226,101,163,254,208,133,61,255,137,69,174,1,190,118,145,255,60,98,219,255,217,13,245,255,250,136,10,0,84,254,226,0,201,31,125,1,240,51,251,255,31,131,130,255,2,138,50,255,215,215,177,1,223,12,238,255,252,149,56,255,124,91,68,255,72,126,170,254,119,255,100,0,130,135,232,255,14,79,178,0,250,131,197,0,138,198,208,0,121,216,139,254,119,18,36,255,29,193,122,0,16,42,45,255,213,240,235,1,230,190,169,255,198,35,228,254,110,173,72,0,214,221,241,255,56,148,135,0,192,117,78,254,141,93,207,255,143,65,149,0,21,18,98,255,95,44,244,1,106,191,77,0,254,85,8,254,214,110,176,255,73,173,19,254,160,196,199,255,237,90,144,0,193,172,113,255,200,155,136,254,228,90,221,0,137,49,74,1,164,221,215,255,209,189,5,255,105,236,55,255,42,31,129,1,193,255,236,0,46,217,60,0,138,88,187,255,226,82,236,255,81,69,151,255,142,190,16,1,13,134,8,0,127,122,48,255,81,64,156,0,171,243,139,0,237,35,246,0,122,143,193,254,212,122,146,0,95,41,255,1,87,132,77,0,4,212,31,0,17,31,78,0,39,45,173,254,24,142,217,255,95,9,6,255,227,83,6,0,98,59,130,254,62,30,33,0,8,115,211,1,162,97,128,255,7,184,23,254,116,28,168,255,248,138,151,255,98,244,240,0,186,118,130,0,114,248,235,255,105,173,200,1,160,124,71,255,94,36,164,1,175,65,146,255,238,241,170,254,202,198,197,0,228,71,138,254,45,246,109,255,194,52,158,0,133,187,176,0,83,252,154,254,89,189,221,255,170,73,252,0,148,58,125,0,36,68,51,254,42,69,177,255,168,76,86,255,38,100,204,255,38,53,35,0,175,19,97,0,225,238,253,255,81,81,135,0,210,27,255,254,235,73,107,0,8,207,115,0,82,127,136,0,84,99,21,254,207,19,136,0,100,164,101,0,80,208,77,255,132,207,237,255,15,3,15,255,33,166,110,0,156,95,85,255,37,185,111,1,150,106,35,255,166,151,76,0,114,87,135,255,159,194,64,0,12,122,31,255,232,7,101,254,173,119,98,0,154,71,220,254,191,57,53,255,168,232,160,255,224,32,99,255,218,156,165,0,151,153,163,0,217,13,148,1,197,113,89,0,149,28,161,254,207,23,30,0,105,132,227,255,54,230,94,255,133,173,204,255,92,183,157,255,88,144,252,254,102,33,90,0,159,97,3,0,181,218,155,255,240,114,119,0,106,214,53,255,165,190,115,1,152,91,225,255,88,106,44,255,208,61,113,0,151,52,124,0,191,27,156,255,110,54,236,1,14,30,166,255,39,127,207,1,229,199,28,0,188,228,188,254,100,157,235,0,246,218,183,1,107,22,193,255,206,160,95,0,76,239,147,0,207,161,117,0,51,166,2,255,52,117,10,254,73,56,227,255,152,193,225,0,132,94,136,255,101,191,209,0,32,107,229,255,198,43,180,1,100,210,118,0,114,67,153,255,23,88,26,255,89,154,92,1,220,120,140,255,144,114,207,255,252,115,250,255,34,206,72,0,138,133,127,255,8,178,124,1,87,75,97,0,15,229,92,254,240,67,131,255,118,123,227,254,146,120,104,255,145,213,255,1,129,187,70,255,219,119,54,0,1,19,173,0,45,150,148,1,248,83,72,0,203,233,169,1,142,107,56,0,247,249,38,1,45,242,80,255,30,233,103,0,96,82,70,0,23,201,111,0,81,39,30,255,161,183,78,255,194,234,33,255,68,227,140,254,216,206,116,0,70,27,235,255,104,144,79,0,164,230,93,254,214,135,156,0,154,187,242,254,188,20,131,255,36,109,174,0,159,112,241,0,5,110,149,1,36,165,218,0,166,29,19,1,178,46,73,0,93,43,32,254,248,189,237,0,102,155,141,0,201,93,195,255,241,139,253,255,15,111,98,255,108,65,163,254,155,79,190,255,73,174,193,254,246,40,48,255,107,88,11,254,202,97,85,255,253,204,18,255,113,242,66,0,110,160,194,254,208,18,186,0,81,21,60,0,188,104,167,255,124,166,97,254,210,133,142,0,56,242,137,254,41,111,130,0,111,151,58,1,111,213,141,255,183,172,241,255,38,6,196,255,185,7,123,255,46,11,246,0,245,105,119,1,15,2,161,255,8,206,45,255,18,202,74,255,83,124,115,1,212,141,157,0,83,8,209,254,139,15,232,255,172,54,173,254,50,247,132,0,214,189,213,0,144,184,105,0,223,254,248,0,255,147,240,255,23,188,72,0,7,51,54,0,188,25,180,254,220,180,0,255,83,160,20,0,163,189,243,255,58,209,194,255,87,73,60,0,106,24,49,0,245,249,220,0,22,173,167,0,118,11,195,255,19,126,237,0,110,159,37,255,59,82,47,0,180,187,86,0,188,148,208,1,100,37,133,255,7,112,193,0,129,188,156,255,84,106,129,255,133,225,202,0,14,236,111,255,40,20,101,0,172,172,49,254,51,54,74,255,251,185,184,255,93,155,224,255,180,249,224,1,230,178,146,0,72,57,54,254,178,62,184,0,119,205,72,0,185,239,253,255,61,15,218,0,196,67,56,255,234,32,171,1,46,219,228,0,208,108,234,255,20,63,232,255,165,53,199,1,133,228,5,255,52,205,107,0,74,238,140,255,150,156,219,254,239,172,178,255,251,189,223,254,32,142,211,255,218,15,138,1,241,196,80,0,28,36,98,254,22,234,199,0,61,237,220,255,246,57,37,0,142,17,142,255,157,62,26,0,43,238,95,254,3,217,6,255,213,25,240,1,39,220,174,255,154,205,48,254,19,13,192,255,244,34,54,254,140,16,155,0,240,181,5,254,155,193,60,0,166,128,4,255,36,145,56,255,150,240,219,0,120,51,145,0,82,153,42,1,140,236,146,0,107,92,248,1,189,10,3,0,63,136,242,0,211,39,24,0,19,202,161,1,173,27,186,255,210,204,239,254,41,209,162,255,182,254,159,255,172,116,52,0,195,103,222,254,205,69,59,0,53,22,41,1,218,48,194,0,80,210,242,0,210,188,207,0,187,161,161,254,216,17,1,0,136,225,113,0,250,184,63,0,223,30,98,254,77,168,162,0,59,53,175,0,19,201,10,255,139,224,194,0,147,193,154,255,212,189,12,254,1,200,174,255,50,133,113,1,94,179,90,0,173,182,135,0,94,177,113,0,43,89,215,255,136,252,106,255,123,134,83,254,5,245,66,255,82,49,39,1,220,2,224,0,97,129,177,0,77,59,89,0,61,29,155,1,203,171,220,255,92,78,139,0,145,33,181,255,169,24,141,1,55,150,179,0,139,60,80,255,218,39,97,0,2,147,107,255,60,248,72,0,173,230,47,1,6,83,182,255,16,105,162,254,137,212,81,255,180,184,134,1,39,222,164,255,221,105,251,1,239,112,125,0,63,7,97,0,63,104,227,255,148,58,12,0,90,60,224,255,84,212,252,0,79,215,168,0,248,221,199,1,115,121,1,0,36,172,120,0,32,162,187,255,57,107,49,255,147,42,21,0,106,198,43,1,57,74,87,0,126,203,81,255,129,135,195,0,140,31,177,0,221,139,194,0,3,222,215,0,131,68,231,0,177,86,178,254,124,151,180,0,184,124,38,1,70,163,17,0,249,251,181,1,42,55,227,0,226,161,44,0,23,236,110,0,51,149,142,1,93,5,236,0,218,183,106,254,67,24,77,0,40,245,209,255,222,121,153,0,165,57,30,0,83,125,60,0,70,38,82,1,229,6,188,0,109,222,157,255,55,118,63,255,205,151,186,0,227,33,149,255,254,176,246,1,227,177,227,0,34,106,163,254,176,43,79,0,106,95,78,1,185,241,122,255,185,14,61,0,36,1,202,0,13,178,162,255,247,11,132,0,161,230,92,1,65,1,185,255,212,50,165,1,141,146,64,255,158,242,218,0,21,164,125,0,213,139,122,1,67,71,87,0,203,158,178,1,151,92,43,0,152,111,5,255,39,3,239,255,217,255,250,255,176,63,71,255,74,245,77,1,250,174,18,255,34,49,227,255,246,46,251,255,154,35,48,1,125,157,61,255,106,36,78,255,97,236,153,0,136,187,120,255,113,134,171,255,19,213,217,254,216,94,209,255,252,5,61,0,94,3,202,0,3,26,183,255,64,191,43,255,30,23,21,0,129,141,77,255,102,120,7,1,194,76,140,0,188,175,52,255,17,81,148,0,232,86,55,1,225,48,172,0,134,42,42,255,238,50,47,0,169,18,254,0,20,147,87,255,14,195,239,255,69,247,23,0,238,229,128,255,177,49,112,0,168,98,251,255,121,71,248,0,243,8,145,254,246,227,153,255,219,169,177,254,251,139,165,255,12,163,185,255,164,40,171,255,153,159,27,254,243,109,91,255,222,24,112,1,18,214,231,0,107,157,181,254,195,147,0,255,194,99,104,255,89,140,190,255,177,66,126,254,106,185,66,0,49,218,31,0,252,174,158,0,188,79,230,1,238,41,224,0,212,234,8,1,136,11,181,0,166,117,83,255,68,195,94,0,46,132,201,0,240,152,88,0,164,57,69,254,160,224,42,255,59,215,67,255,119,195,141,255,36,180,121,254,207,47,8,255,174,210,223,0,101,197,68,255,255,82,141,1,250,137,233,0,97,86,133,1,16,80,69,0,132,131,159,0,116,93,100,0,45,141,139,0,152,172,157,255,90,43,91,0,71,153,46,0,39,16,112,255,217,136,97,255,220,198,25,254,177,53,49,0,222,88,134,255,128,15,60,0,207,192,169,255,192,116,209,255,106,78,211,1,200,213,183,255,7,12,122,254,222,203,60,255,33,110,199,254,251,106,117,0,228,225,4,1,120,58,7,255,221,193,84,254,112,133,27,0,189,200,201,255,139,135,150,0,234,55,176,255,61,50,65,0,152,108,169,255,220,85,1,255,112,135,227,0,162,26,186,0,207,96,185,254,244,136,107,0,93,153,50,1,198,97,151,0,110,11,86,255,143,117,174,255,115,212,200,0,5,202,183,0,237,164,10,254,185,239,62,0,236,120,18,254,98,123,99,255,168,201,194,254,46,234,214,0,191,133,49,255,99,169,119,0,190,187,35,1,115,21,45,255,249,131,72,0,112,6,123,255,214,49,181,254,166,233,34,0,92,197,102,254,253,228,205,255,3,59,201,1,42,98,46,0,219,37,35,255,169,195,38,0,94,124,193,1,156,43,223,0,95,72,133,254,120,206,191,0,122,197,239,255,177,187,79,255,254,46,2,1,250,167,190,0,84,129,19,0,203,113,166,255,249,31,189,254,72,157,202,255,208,71,73,255,207,24,72,0,10,16,18,1,210,81,76,255,88,208,192,255,126,243,107,255,238,141,120,255,199,121,234,255,137,12,59,255,36,220,123,255,148,179,60,254,240,12,29,0,66,0,97,1,36,30,38,255,115,1,93,255,96,103,231,255,197,158,59,1,192,164,240,0,202,202,57,255,24,174,48,0,89,77,155,1,42,76,215,0,244,151,233,0,23,48,81,0,239,127,52,254,227,130,37,255,248,116,93,1,124,132,118,0,173,254,192,1,6,235,83,255,110,175,231,1,251,28,182,0,129,249,93,254,84,184,128,0,76,181,62,0,175,128,186,0,100,53,136,254,109,29,226,0,221,233,58,1,20,99,74,0,0,22,160,0,134,13,21,0,9,52,55,255,17,89,140,0,175,34,59,0,84,165,119,255,224,226,234,255,7,72,166,255,123,115,255,1,18,214,246,0,250,7,71,1,217,220,185,0,212,35,76,255,38,125,175,0,189,97,210,0,114,238,44,255,41,188,169,254,45,186,154,0,81,92,22,0,132,160,193,0,121,208,98,255,13,81,44,255,203,156,82,0,71,58,21,255,208,114,191,254,50,38,147,0,154,216,195,0,101,25,18,0,60,250,215,255,233,132,235,255,103,175,142,1,16,14,92,0,141,31,110,254,238,241,45,255,153,217,239,1,97,168,47,255,249,85,16,1,28,175,62,255],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);allocate([57,254,54,0,222,231,126,0,166,45,117,254,18,189,96,255,228,76,50,0,200,244,94,0,198,152,120,1,68,34,69,255,12,65,160,254,101,19,90,0,167,197,120,255,68,54,185,255,41,218,188,0,113,168,48,0,88,105,189,1,26,82,32,255,185,93,164,1,228,240,237,255,66,182,53,0,171,197,92,255,107,9,233,1,199,120,144,255,78,49,10,255,109,170,105,255,90,4,31,255,28,244,113,255,74,58,11,0,62,220,246,255,121,154,200,254,144,210,178,255,126,57,129,1,43,250,14,255,101,111,28,1,47,86,241,255,61,70,150,255,53,73,5,255,30,26,158,0,209,26,86,0,138,237,74,0,164,95,188,0,142,60,29,254,162,116,248,255,187,175,160,0,151,18,16,0,209,111,65,254,203,134,39,255,88,108,49,255,131,26,71,255,221,27,215,254,104,105,93,255,31,236,31,254,135,0,211,255,143,127,110,1,212,73,229,0,233,67,167,254,195,1,208,255,132,17,221,255,51,217,90,0,67,235,50,255,223,210,143,0,179,53,130,1,233,106,198,0,217,173,220,255,112,229,24,255,175,154,93,254,71,203,246,255,48,66,133,255,3,136,230,255,23,221,113,254,235,111,213,0,170,120,95,254,251,221,2,0,45,130,158,254,105,94,217,255,242,52,180,254,213,68,45,255,104,38,28,0,244,158,76,0,161,200,96,255,207,53,13,255,187,67,148,0,170,54,248,0,119,162,178,255,83,20,11,0,42,42,192,1,146,159,163,255,183,232,111,0,77,229,21,255,71,53,143,0,27,76,34,0,246,136,47,255,219,39,182,255,92,224,201,1,19,142,14,255,69,182,241,255,163,118,245,0,9,109,106,1,170,181,247,255,78,47,238,255,84,210,176,255,213,107,139,0,39,38,11,0,72,21,150,0,72,130,69,0,205,77,155,254,142,133,21,0,71,111,172,254,226,42,59,255,179,0,215,1,33,128,241,0,234,252,13,1,184,79,8,0,110,30,73,255,246,141,189,0,170,207,218,1,74,154,69,255,138,246,49,255,155,32,100,0,125,74,105,255,90,85,61,255,35,229,177,255,62,125,193,255,153,86,188,1,73,120,212,0,209,123,246,254,135,209,38,255,151,58,44,1,92,69,214,255,14,12,88,255,252,153,166,255,253,207,112,255,60,78,83,255,227,124,110,0,180,96,252,255,53,117,33,254,164,220,82,255,41,1,27,255,38,164,166,255,164,99,169,254,61,144,70,255,192,166,18,0,107,250,66,0,197,65,50,0,1,179,18,255,255,104,1,255,43,153,35,255,80,111,168,0,110,175,168,0,41,105,45,255,219,14,205,255,164,233,140,254,43,1,118,0,233,67,195,0,178,82,159,255,138,87,122,255,212,238,90,255,144,35,124,254,25,140,164,0,251,215,44,254,133,70,107,255,101,227,80,254,92,169,55,0,215,42,49,0,114,180,85,255,33,232,27,1,172,213,25,0,62,176,123,254,32,133,24,255,225,191,62,0,93,70,153,0,181,42,104,1,22,191,224,255,200,200,140,255,249,234,37,0,149,57,141,0,195,56,208,255,254,130,70,255,32,173,240,255,29,220,199,0,110,100,115,255,132,229,249,0,228,233,223,255,37,216,209,254,178,177,209,255,183,45,165,254,224,97,114,0,137,97,168,255,225,222,172,0,165,13,49,1,210,235,204,255,252,4,28,254,70,160,151,0,232,190,52,254,83,248,93,255,62,215,77,1,175,175,179,255,160,50,66,0,121,48,208,0,63,169,209,255,0,210,200,0,224,187,44,1,73,162,82,0,9,176,143,255,19,76,193,255,29,59,167,1,24,43,154,0,28,190,190,0,141,188,129,0,232,235,203,255,234,0,109,255,54,65,159,0,60,88,232,255,121,253,150,254,252,233,131,255,198,110,41,1,83,77,71,255,200,22,59,254,106,253,242,255,21,12,207,255,237,66,189,0,90,198,202,1,225,172,127,0,53,22,202,0,56,230,132,0,1,86,183,0,109,190,42,0,243,68,174,1,109,228,154,0,200,177,122,1,35,160,183,255,177,48,85,255,90,218,169,255,248,152,78,0,202,254,110,0,6,52,43,0,142,98,65,255,63,145,22,0,70,106,93,0,232,138,107,1,110,179,61,255,211,129,218,1,242,209,92,0,35,90,217,1,182,143,106,255,116,101,217,255,114,250,221,255,173,204,6,0,60,150,163,0,73,172,44,255,239,110,80,255,237,76,153,254,161,140,249,0,149,232,229,0,133,31,40,255,174,164,119,0,113,51,214,0,129,228,2,254,64,34,243,0,107,227,244,255,174,106,200,255,84,153,70,1,50,35,16,0,250,74,216,254,236,189,66,255,153,249,13,0,230,178,4,255,221,41,238,0,118,227,121,255,94,87,140,254,254,119,92,0,73,239,246,254,117,87,128,0,19,211,145,255,177,46,252,0,229,91,246,1,69,128,247,255,202,77,54,1,8,11,9,255,153,96,166,0,217,214,173,255,134,192,2,1,0,207,0,0,189,174,107,1,140,134,100,0,158,193,243,1,182,102,171,0,235,154,51,0,142,5,123,255,60,168,89,1,217,14,92,255,19,214,5,1,211,167,254,0,44,6,202,254,120,18,236,255,15,113,184,255,184,223,139,0,40,177,119,254,182,123,90,255,176,165,176,0,247,77,194,0,27,234,120,0,231,0,214,255,59,39,30,0,125,99,145,255,150,68,68,1,141,222,248,0,153,123,210,255,110,127,152,255,229,33,214,1,135,221,197,0,137,97,2,0,12,143,204,255,81,41,188,0,115,79,130,255,94,3,132,0,152,175,187,255,124,141,10,255,126,192,179,255,11,103,198,0,149,6,45,0,219,85,187,1,230,18,178,255,72,182,152,0,3,198,184,255,128,112,224,1,97,161,230,0,254,99,38,255,58,159,197,0,151,66,219,0,59,69,143,255,185,112,249,0,119,136,47,255,123,130,132,0,168,71,95,255,113,176,40,1,232,185,173,0,207,93,117,1,68,157,108,255,102,5,147,254,49,97,33,0,89,65,111,254,247,30,163,255,124,217,221,1,102,250,216,0,198,174,75,254,57,55,18,0,227,5,236,1,229,213,173,0,201,109,218,1,49,233,239,0,30,55,158,1,25,178,106,0,155,111,188,1,94,126,140,0,215,31,238,1,77,240,16,0,213,242,25,1,38,71,168,0,205,186,93,254,49,211,140,255,219,0,180,255,134,118,165,0,160,147,134,255,110,186,35,255,198,243,42,0,243,146,119,0,134,235,163,1,4,241,135,255,193,46,193,254,103,180,79,255,225,4,184,254,242,118,130,0,146,135,176,1,234,111,30,0,69,66,213,254,41,96,123,0,121,94,42,255,178,191,195,255,46,130,42,0,117,84,8,255,233,49,214,254,238,122,109,0,6,71,89,1,236,211,123,0,244,13,48,254,119,148,14,0,114,28,86,255,75,237,25,255,145,229,16,254,129,100,53,255,134,150,120,254,168,157,50,0,23,72,104,255,224,49,14,0,255,123,22,255,151,185,151,255,170,80,184,1,134,182,20,0,41,100,101,1,153,33,16,0,76,154,111,1,86,206,234,255,192,160,164,254,165,123,93,255,1,216,164,254,67,17,175,255,169,11,59,255,158,41,61,255,73,188,14,255,195,6,137,255,22,147,29,255,20,103,3,255,246,130,227,255,122,40,128,0,226,47,24,254,35,36,32,0,152,186,183,255,69,202,20,0,195,133,195,0,222,51,247,0,169,171,94,1,183,0,160,255,64,205,18,1,156,83,15,255,197,58,249,254,251,89,110,255,50,10,88,254,51,43,216,0,98,242,198,1,245,151,113,0,171,236,194,1,197,31,199,255,229,81,38,1,41,59,20,0,253,104,230,0,152,93,14,255,246,242,146,254,214,169,240,255,240,102,108,254,160,167,236,0,154,218,188,0,150,233,202,255,27,19,250,1,2,71,133,255,175,12,63,1,145,183,198,0,104,120,115,255,130,251,247,0,17,212,167,255,62,123,132,255,247,100,189,0,155,223,152,0,143,197,33,0,155,59,44,255,150,93,240,1,127,3,87,255,95,71,207,1,167,85,1,255,188,152,116,255,10,23,23,0,137,195,93,1,54,98,97,0,240,0,168,255,148,188,127,0,134,107,151,0,76,253,171,0,90,132,192,0,146,22,54,0,224,66,54,254,230,186,229,255,39,182,196,0,148,251,130,255,65,131,108,254,128,1,160,0,169,49,167,254,199,254,148,255,251,6,131,0,187,254,129,255,85,82,62,0,178,23,58,255,254,132,5,0,164,213,39,0,134,252,146,254,37,53,81,255,155,134,82,0,205,167,238,255,94,45,180,255,132,40,161,0,254,111,112,1,54,75,217,0,179,230,221,1,235,94,191,255,23,243,48,1,202,145,203,255,39,118,42,255,117,141,253,0,254,0,222,0,43,251,50,0,54,169,234,1,80,68,208,0,148,203,243,254,145,7,135,0,6,254,0,0,252,185,127,0,98,8,129,255,38,35,72,255,211,36,220,1,40,26,89,0,168,64,197,254,3,222,239,255,2,83,215,254,180,159,105,0,58,115,194,0,186,116,106,255,229,247,219,255,129,118,193,0,202,174,183,1,166,161,72,0,201,107,147,254,237,136,74,0,233,230,106,1,105,111,168,0,64,224,30,1,1,229,3,0,102,151,175,255,194,238,228,255,254,250,212,0,187,237,121,0,67,251,96,1,197,30,11,0,183,95,204,0,205,89,138,0,64,221,37,1,255,223,30,255,178,48,211,255,241,200,90,255,167,209,96,255,57,130,221,0,46,114,200,255,61,184,66,0,55,182,24,254,110,182,33,0,171,190,232,255,114,94,31,0,18,221,8,0,47,231,254,0,255,112,83,0,118,15,215,255,173,25,40,254,192,193,31,255,238,21,146,255,171,193,118,255,101,234,53,254,131,212,112,0,89,192,107,1,8,208,27,0,181,217,15,255,231,149,232,0,140,236,126,0,144,9,199,255,12,79,181,254,147,182,202,255,19,109,182,255,49,212,225,0,74,163,203,0,175,233,148,0,26,112,51,0,193,193,9,255,15,135,249,0,150,227,130,0,204,0,219,1,24,242,205,0,238,208,117,255,22,244,112,0,26,229,34,0,37,80,188,255,38,45,206,254,240,90,225,255,29,3,47,255,42,224,76,0,186,243,167,0,32,132,15,255,5,51,125,0,139,135,24,0,6,241,219,0,172,229,133,255,246,214,50,0,231,11,207,255,191,126,83,1,180,163,170,255,245,56,24,1,178,164,211,255,3,16,202,1,98,57,118,255,141,131,89,254,33,51,24,0,243,149,91,255,253,52,14,0,35,169,67,254,49,30,88,255,179,27,36,255,165,140,183,0,58,189,151,0,88,31,0,0,75,169,66,0,66,101,199,255,24,216,199,1,121,196,26,255,14,79,203,254,240,226,81,255,94,28,10,255,83,193,240,255,204,193,131,255,94,15,86,0,218,40,157,0,51,193,209,0,0,242,177,0,102,185,247,0,158,109,116,0,38,135,91,0,223,175,149,0,220,66,1,255,86,60,232,0,25,96,37,255,225,122,162,1,215,187,168,255,158,157,46,0,56,171,162,0,232,240,101,1,122,22,9,0,51,9,21,255,53,25,238,255,217,30,232,254,125,169,148,0,13,232,102,0,148,9,37,0,165,97,141,1,228,131,41,0,222,15,243,255,254,18,17,0,6,60,237,1,106,3,113,0,59,132,189,0,92,112,30,0,105,208,213,0,48,84,179,255,187,121,231,254,27,216,109,255,162,221,107,254,73,239,195,255,250,31,57,255,149,135,89,255,185,23,115,1,3,163,157,255,18,112,250,0,25,57,187,255,161,96,164,0,47,16,243,0,12,141,251,254,67,234,184,255,41,18,161,0,175,6,96,255,160,172,52,254,24,176,183,255,198,193,85,1,124,121,137,255,151,50,114,255,220,203,60,255,207,239,5,1,0,38,107,255,55,238,94,254,70,152,94,0,213,220,77,1,120,17,69,255,85,164,190,255,203,234,81,0,38,49,37,254,61,144,124,0,137,78,49,254,168,247,48,0,95,164,252,0,105,169,135,0,253,228,134,0,64,166,75,0,81,73,20,255,207,210,10,0,234,106,150,255,94,34,90,255,254,159,57,254,220,133,99,0,139,147,180,254,24,23,185,0,41,57,30,255,189,97,76,0,65,187,223,255,224,172,37,255,34,62,95,1,231,144,240,0,77,106,126,254,64,152,91,0,29,98,155,0,226,251,53,255,234,211,5,255,144,203,222,255,164,176,221,254,5,231,24,0,179,122,205,0,36,1,134,255,125,70,151,254,97,228,252,0,172,129,23,254,48,90,209,255,150,224,82,1,84,134,30,0,241,196,46,0,103,113,234,255,46,101,121,254,40,124,250,255,135,45,242,254,9,249,168,255,140,108,131,255,143,163,171,0,50,173,199,255,88,222,142,255,200,95,158,0,142,192,163,255,7,117,135,0,111,124,22,0,236,12,65,254,68,38,65,255,227,174,254,0,244,245,38,0,240,50,208,255,161,63,250,0,60,209,239,0,122,35,19,0,14,33,230,254,2,159,113,0,106,20,127,255,228,205,96,0,137,210,174,254,180,212,144,255,89,98,154,1,34,88,139,0,167,162,112,1,65,110,197,0,241,37,169,0,66,56,131,255,10,201,83,254,133,253,187,255,177,112,45,254,196,251,0,0,196,250,151,255,238,232,214,255,150,209,205,0,28,240,118,0,71,76,83,1,236,99,91,0,42,250,131,1,96,18,64,255,118,222,35,0,113,214,203,255,122,119,184,255,66,19,36,0,204,64,249,0,146,89,139,0,134,62,135,1,104,233,101,0,188,84,26,0,49,249,129,0,208,214,75,255,207,130,77,255,115,175,235,0,171,2,137,255,175,145,186,1,55,245,135,255,154,86,181,1,100,58,246,255,109,199,60,255,82,204,134,255,215,49,230,1,140,229,192,255,222,193,251,255,81,136,15,255,179,149,162,255,23,39,29,255,7,95,75,254,191,81,222,0,241,81,90,255,107,49,201,255,244,211,157,0,222,140,149,255,65,219,56,254,189,246,90,255,178,59,157,1,48,219,52,0,98,34,215,0,28,17,187,255,175,169,24,0,92,79,161,255,236,200,194,1,147,143,234,0,229,225,7,1,197,168,14,0,235,51,53,1,253,120,174,0,197,6,168,255,202,117,171,0,163,21,206,0,114,85,90,255,15,41,10,255,194,19,99,0,65,55,216,254,162,146,116,0,50,206,212,255,64,146,29,255,158,158,131,1,100,165,130,255,172,23,129,255,125,53,9,255,15,193,18,1,26,49,11,255,181,174,201,1,135,201,14,255,100,19,149,0,219,98,79,0,42,99,143,254,96,0,48,255,197,249,83,254,104,149,79,255,235,110,136,254,82,128,44,255,65,41,36,254,88,211,10,0,187,121,187,0,98,134,199,0,171,188,179,254,210,11,238,255,66,123,130,254,52,234,61,0,48,113,23,254,6,86,120,255,119,178,245,0,87,129,201,0,242,141,209,0,202,114,85,0,148,22,161,0,103,195,48,0,25,49,171,255,138,67,130,0,182,73,122,254,148,24,130,0,211,229,154,0,32,155,158,0,84,105,61,0,177,194,9,255,166,89,86,1,54,83,187,0,249,40,117,255,109,3,215,255,53,146,44,1,63,47,179,0,194,216,3,254,14,84,136,0,136,177,13,255,72,243,186,255,117,17,125,255,211,58,211,255,93,79,223,0,90,88,245,255,139,209,111,255,70,222,47,0,10,246,79,255,198,217,178,0,227,225,11,1,78,126,179,255,62,43,126,0,103,148,35,0,129,8,165,254,245,240,148,0,61,51,142,0,81,208,134,0,15,137,115,255,211,119,236,255,159,245,248,255,2,134,136,255,230,139,58,1,160,164,254,0,114,85,141,255,49,166,182,255,144,70,84,1,85,182,7,0,46,53,93,0,9,166,161,255,55,162,178,255,45,184,188,0,146,28,44,254,169,90,49,0,120,178,241,1,14,123,127,255,7,241,199,1,189,66,50,255,198,143,101,254,189,243,135,255,141,24,24,254,75,97,87,0,118,251,154,1,237,54,156,0,171,146,207,255,131,196,246,255,136,64,113,1,151,232,57,0,240,218,115,0,49,61,27,255,64,129,73,1,252,169,27,255,40,132,10,1,90,201,193,255,252,121,240,1,186,206,41,0,43,198,97,0,145,100,183,0,204,216,80,254,172,150,65,0,249,229,196,254,104,123,73,255,77,104,96,254,130,180,8,0,104,123,57,0,220,202,229,255,102,249,211,0,86,14,232,255,182,78,209,0,239,225,164,0,106,13,32,255,120,73,17,255,134,67,233,0,83,254,181,0,183,236,112,1,48,64,131,255,241,216,243,255,65,193,226,0,206,241,100,254,100,134,166,255,237,202,197,0,55,13,81,0,32,124,102,255,40,228,177,0,118,181,31,1,231,160,134,255,119,187,202,0,0,142,60,255,128,38,189,255,166,201,150,0,207,120,26,1,54,184,172,0,12,242,204,254,133,66,230,0,34,38,31,1,184,112,80,0,32,51,165,254,191,243,55,0,58,73,146,254,155,167,205,255,100,104,152,255,197,254,207,255,173,19,247,0,238,10,202,0,239,151,242,0,94,59,39,255,240,29,102,255,10,92,154,255,229,84,219,255,161,129,80,0,208,90,204,1,240,219,174,255,158,102,145,1,53,178,76,255,52,108,168,1,83,222,107,0,211,36,109,0,118,58,56,0,8,29,22,0,237,160,199,0,170,209,157,0,137,71,47,0,143,86,32,0,198,242,2,0,212,48,136,1,92,172,186,0,230,151,105,1,96,191,229,0,138,80,191,254,240,216,130,255,98,43,6,254,168,196,49,0,253,18,91,1,144,73,121,0,61,146,39,1,63,104,24,255,184,165,112,254,126,235,98,0,80,213,98,255,123,60,87,255,82,140,245,1,223,120,173,255,15,198,134,1,206,60,239,0,231,234,92,255,33,238,19,255,165,113,142,1,176,119,38,0,160,43,166,254,239,91,105,0,107,61,194,1,25,4,68,0,15,139,51,0,164,132,106,255,34,116,46,254,168,95,197,0,137,212,23,0,72,156,58,0,137,112,69,254,150,105,154,255,236,201,157,0,23,212,154,255,136,82,227,254,226,59,221,255,95,149,192,0,81,118,52,255,33,43,215,1,14,147,75,255,89,156,121,254,14,18,79,0,147,208,139,1,151,218,62,255,156,88,8,1,210,184,98,255,20,175,123,255,102,83,229,0,220,65,116,1,150,250,4,255,92,142,220,255,34,247,66,255,204,225,179,254,151,81,151,0,71,40,236,255,138,63,62,0,6,79,240,255,183,185,181,0,118,50,27,0,63,227,192,0,123,99,58,1,50,224,155,255,17,225,223,254,220,224,77,255,14,44,123,1,141,128,175,0,248,212,200,0,150,59,183,255,147,97,29,0,150,204,181,0,253,37,71,0,145,85,119,0,154,200,186,0,2,128,249,255,83,24,124,0,14,87,143,0,168,51,245,1,124,151,231,255,208,240,197,1,124,190,185,0,48,58,246,0,20,233,232,0,125,18,98,255,13,254,31,255,245,177,130,255,108,142,35,0,171,125,242,254,140,12,34,255,165,161,162,0,206,205,101,0,247,25,34,1,100,145,57,0,39,70,57,0,118,204,203,255,242,0,162,0,165,244,30,0,198,116,226,0,128,111,153,255,140,54,182,1,60,122,15,255,155,58,57,1,54,50,198,0,171,211,29,255,107,138,167,255,173,107,199,255,109,161,193,0,89,72,242,255,206,115,89,255,250,254,142,254,177,202,94,255,81,89,50,0,7,105,66,255,25,254,255,254,203,64,23,255,79,222,108,255,39,249,75,0,241,124,50,0,239,152,133,0,221,241,105,0,147,151,98,0,213,161,121,254,242,49,137,0,233,37,249,254,42,183,27,0,184,119,230,255,217,32,163,255,208,251,228,1,137,62,131,255,79,64,9,254,94,48,113,0,17,138,50,254,193,255,22,0,247,18,197,1,67,55,104,0,16,205,95,255,48,37,66,0,55,156,63,1,64,82,74,255,200,53,71,254,239,67,125,0,26,224,222,0,223,137,93,255,30,224,202,255,9,220,132,0,198,38,235,1,102,141,86,0,60,43,81,1,136,28,26,0,233,36,8,254,207,242,148,0,164,162,63,0,51,46,224,255,114,48,79,255,9,175,226,0,222,3,193,255,47,160,232,255,255,93,105,254,14,42,230,0,26,138,82,1,208,43,244,0,27,39,38,255,98,208,127,255,64,149,182,255,5,250,209,0,187,60,28,254,49,25,218,255,169,116,205,255,119,18,120,0,156,116,147,255,132,53,109,255,13,10,202,0,110,83,167,0,157,219,137,255,6,3,130,255,50,167,30,255,60,159,47,255,129,128,157,254,94,3,189,0,3,166,68,0,83,223,215,0,150,90,194,1,15,168,65,0,227,83,51,255,205,171,66,255,54,187,60,1,152,102,45,255,119,154,225,0,240,247,136,0,100,197,178,255,139,71,223,255,204,82,16,1,41,206,42,255,156,192,221,255,216,123,244,255,218,218,185,255,187,186,239,255,252,172,160,255,195,52,22,0,144,174,181,254,187,100,115,255,211,78,176,255,27,7,193,0,147,213,104,255,90,201,10,255,80,123,66,1,22,33,186,0,1,7,99,254,30,206,10,0,229,234,5,0,53,30,210,0,138,8,220,254,71,55,167,0,72,225,86,1,118,190,188,0,254,193,101,1,171,249,172,255,94,158,183,254,93,2,108,255,176,93,76,255,73,99,79,255,74,64,129,254,246,46,65,0,99,241,127,254,246,151,102,255,44,53,208,254,59,102,234,0,154,175,164,255,88,242,32,0,111,38,1,0,255,182,190,255,115,176,15,254,169,60,129,0,122,237,241,0,90,76,63,0,62,74,120,255,122,195,110,0,119,4,178,0,222,242,210,0,130,33,46,254,156,40,41,0,167,146,112,1,49,163,111,255,121,176,235,0,76,207,14,255,3,25,198,1,41,235,213,0,85,36,214,1,49,92,109,255,200,24,30,254,168,236,195,0,145,39,124,1,236,195,149,0,90,36,184,255,67,85,170,255,38,35,26,254,131,124,68,255,239,155,35,255,54,201,164,0,196,22,117,255,49,15,205,0,24,224,29,1,126,113,144,0,117,21,182,0,203,159,141,0,223,135,77,0,176,230,176,255,190,229,215,255,99,37,181,255,51,21,138,255,25,189,89,255,49,48,165,254,152,45,247,0,170,108,222,0,80,202,5,0,27,69,103,254,204,22,129,255,180,252,62,254,210,1,91,255,146,110,254,255,219,162,28,0,223,252,213,1,59,8,33,0,206,16,244,0,129,211,48,0,107,160,208,0,112,59,209,0,109,77,216,254,34,21,185,255,246,99,56,255,179,139,19,255,185,29,50,255,84,89,19,0,74,250,98,255,225,42,200,255,192,217,205,255,210,16,167,0,99,132,95,1,43,230,57,0,254,11,203,255,99,188,63,255,119,193,251,254,80,105,54,0,232,181,189,1,183,69,112,255,208,171,165,255,47,109,180,255,123,83,165,0,146,162,52,255,154,11,4,255,151,227,90,255,146,137,97,254,61,233,41,255,94,42,55,255,108,164,236,0,152,68,254,0,10,140,131,255,10,106,79,254,243,158,137,0,67,178,66,254,177,123,198,255,15,62,34,0,197,88,42,255,149,95,177,255,152,0,198,255,149,254,113,255,225,90,163,255,125,217,247,0,18,17,224,0,128,66,120,254,192,25,9,255,50,221,205,0,49,212,70,0,233,255,164,0,2,209,9,0,221,52,219,254,172,224,244,255,94,56,206,1,242,179,2,255,31,91,164,1,230,46,138,255,189,230,220,0,57,47,61,255,111,11,157,0,177,91,152,0,28,230,98,0,97,87,126,0,198,89,145,255,167,79,107,0,249,77,160,1,29,233,230,255,150,21,86,254,60,11,193,0,151,37,36,254,185,150,243,255,228,212,83,1,172,151,180,0,201,169,155,0,244,60,234,0,142,235,4,1,67,218,60,0,192,113,75,1,116,243,207,255,65,172,155,0,81,30,156,255,80,72,33,254,18,231,109,255,142,107,21,254,125,26,132,255,176,16,59,255,150,201,58,0,206,169,201,0,208,121,226,0,40,172,14,255,150,61,94,255,56,57,156,255,141,60,145,255,45,108,149,255,238,145,155,255,209,85,31,254,192,12,210,0,99,98,93,254,152,16,151,0,225,185,220,0,141,235,44,255,160,172,21,254,71,26,31,255,13,64,93,254,28,56,198,0,177,62,248,1,182,8,241,0,166,101,148,255,78,81,133,255,129,222,215,1,188,169,129,255,232,7,97,0,49,112,60,255,217,229,251,0,119,108,138,0,39,19,123,254,131,49,235,0,132,84,145,0,130,230,148,255,25,74,187,0,5,245,54,255,185,219,241,1,18,194,228,255,241,202,102,0,105,113,202,0,155,235,79,0,21,9,178,255,156,1,239,0,200,148,61,0,115,247,210,255,49,221,135,0,58,189,8,1,35,46,9,0,81,65,5,255,52,158,185,255,125,116,46,255,74,140,13,255,210,92,172,254,147,23,71,0,217,224,253,254,115,108,180,255,145,58,48,254,219,177,24,255,156,255,60,1,154,147,242,0,253,134,87,0,53,75,229,0,48,195,222,255,31,175,50,255,156,210,120,255,208,35,222,255,18,248,179,1,2,10,101,255,157,194,248,255,158,204,101,255,104,254,197,255,79,62,4,0,178,172,101,1,96,146,251,255,65,10,156,0,2,137,165,255,116,4,231,0,242,215,1,0,19,35,29,255,43,161,79,0,59,149,246,1,251,66,176,0,200,33,3,255,80,110,142,255,195,161,17,1,228,56,66,255,123,47,145,254,132,4,164,0,67,174,172,0,25,253,114,0,87,97,87,1,250,220,84,0,96,91,200,255,37,125,59,0,19,65,118,0,161,52,241,255,237,172,6,255,176,191,255,255,1,65,130,254,223,190,230,0,101,253,231,255,146,35,109,0,250,29,77,1,49,0,19,0,123,90,155,1,22,86,32,255,218,213,65,0,111,93,127,0,60,93,169,255,8,127,182,0,17,186,14,254,253,137,246,255,213,25,48,254,76,238,0,255,248,92,70,255,99,224,139,0,184,9,255,1,7,164,208,0,205,131,198,1,87,214,199,0,130,214,95,0,221,149,222,0,23,38,171,254,197,110,213,0,43,115,140,254,215,177,118,0,96,52,66,1,117,158,237,0,14,64,182,255,46,63,174,255,158,95,190,255,225,205,177,255,43,5,142,255,172,99,212,255,244,187,147,0,29,51,153,255,228,116,24,254,30,101,207,0,19,246,150,255,134,231,5,0,125,134,226,1,77,65,98,0,236,130,33,255,5,110,62,0,69,108,127,255,7,113,22,0,145,20,83,254,194,161,231,255,131,181,60,0,217,209,177,255,229,148,212,254,3,131,184,0,117,177,187,1,28,14,31,255,176,102,80,0,50,84,151,255,125,31,54,255,21,157,133,255,19,179,139,1,224,232,26,0,34,117,170,255,167,252,171,255,73,141,206,254,129,250,35,0,72,79,236,1,220,229,20,255,41,202,173,255,99,76,238,255,198,22,224,255,108,198,195,255,36,141,96,1,236,158,59,255,106,100,87,0,110,226,2,0,227,234,222,0,154,93,119,255,74,112,164,255,67,91,2,255,21,145,33,255,102,214,137,255,175,230,103,254,163,246,166,0,93,247,116,254,167,224,28,255,220,2,57,1,171,206,84,0,123,228,17,255,27,120,119,0,119,11,147,1,180,47,225,255,104,200,185,254,165,2,114,0,77,78,212,0,45,154,177,255,24,196,121,254,82,157,182,0,90,16,190,1,12,147,197,0,95,239,152,255,11,235,71,0,86,146,119,255,172,134,214,0,60,131,196,0,161,225,129,0,31,130,120,254,95,200,51,0,105,231,210,255,58,9,148,255,43,168,221,255,124,237,142,0,198,211,50,254,46,245,103,0,164,248,84,0,152,70,208,255,180,117,177,0,70,79,185,0,243,74,32,0,149,156,207,0,197,196,161,1,245,53,239,0,15,93,246,254,139,240,49,255,196,88,36,255,162,38,123,0,128,200,157,1,174,76,103,255,173,169,34,254,216,1,171,255,114,51,17,0,136,228,194,0,110,150,56,254,106,246,159,0,19,184,79,255,150,77,240,255,155,80,162,0,0,53,169,255,29,151,86,0,68,94,16,0,92,7,110,254,98,117,149,255,249,77,230,255,253,10,140,0,214,124,92,254,35,118,235,0,89,48,57,1,22,53,166,0,184,144,61,255,179,255,194,0,214,248,61,254,59,110,246,0,121,21,81,254,166,3,228,0,106,64,26,255,69,232,134,255,242,220,53,254,46,220,85,0,113,149,247,255,97,179,103,255,190,127,11,0,135,209,182,0,95,52,129,1,170,144,206,255,122,200,204,255,168,100,146,0,60,144,149,254,70,60,40,0,122,52,177,255,246,211,101,255,174,237,8,0,7,51,120,0,19,31,173,0,126,239,156,255,143,189,203,0,196,128,88,255,233,133,226,255,30,125,173,255,201,108,50,0,123,100,59,255,254,163,3,1,221,148,181,255,214,136,57,254,222,180,137,255,207,88,54,255,28,33,251,255,67,214,52,1,210,208,100,0,81,170,94,0,145,40,53,0,224,111,231,254,35,28,244,255,226,199,195,254,238,17,230,0,217,217,164,254,169,157,221,0,218,46,162,1,199,207,163,255,108,115,162,1,14,96,187,255,118,60,76,0,184,159,152,0,209,231,71,254,42,164,186,255,186,153,51,254,221,171,182,255,162,142,173,0,235,47,193,0,7,139,16,1,95,164,64,255,16,221,166,0,219,197,16,0,132,29,44,255,100,69,117,255,60,235,88,254,40,81,173,0,71,190,61,255,187,88,157,0,231,11,23,0,237,117,164,0,225,168,223,255,154,114,116,255,163,152,242,1,24,32,170,0,125,98,113,254,168,19,76,0,17,157,220,254,155,52,5,0,19,111,161,255,71,90,252,255,173,110,240,0,10,198,121,255,253,255,240,255,66,123,210,0,221,194,215,254,121,163,17,255,225,7,99,0,190,49,182,0,115,9,133,1,232,26,138,255,213,68,132,0,44,119,122,255,179,98,51,0,149,90,106,0,71,50,230,255,10,153,118,255,177,70,25,0,165,87,205,0,55,138,234,0,238,30,97,0,113,155,207,0,98,153,127,0,34,107,219,254,117,114,172,255,76,180,255,254,242,57,179,255,221,34,172,254,56,162,49,255,83,3,255,255,113,221,189,255,188,25,228,254,16,88,89,255,71,28,198,254,22,17,149,255,243,121,254,255,107,202,99,255,9,206,14,1,220,47,153,0,107,137,39,1,97,49,194,255,149,51,197,254,186,58,11,255,107,43,232,1,200,6,14,255,181,133,65,254,221,228,171,255,123,62,231,1,227,234,179,255,34,189,212,254,244,187,249,0,190,13,80,1,130,89,1,0,223,133,173,0,9,222,198,255,66,127,74,0,167,216,93,255,155,168,198,1,66,145,0,0,68,102,46,1,172,90,154,0,216,128,75,255,160,40,51,0,158,17,27,1,124,240,49,0,236,202,176,255,151,124,192,255,38,193,190,0,95,182,61,0,163,147,124,255,255,165,51,255,28,40,17,254,215,96,78,0,86,145,218,254,31,36,202,255,86,9,5,0,111,41,200,255,237,108,97,0,57,62,44,0,117,184,15,1,45,241,116,0,152,1,220,255,157,165,188,0,250,15,131,1,60,44,125,255,65,220,251,255,75,50,184,0,53,90,128,255,231,80,194,255,136,129,127,1,21,18,187,255,45,58,161,255,71,147,34,0,174,249,11,254,35,141,29,0,239,68,177,255,115,110,58,0,238,190,177,1,87,245,166,255,190,49,247,255,146,83,184,255,173,14,39,255,146,215,104,0,142,223,120,0,149,200,155,255,212,207,145,1,16,181,217,0,173,32,87,255,255,35,181,0,119,223,161,1,200,223,94,255,70,6,186,255,192,67,85,255,50,169,152,0,144,26,123,255,56,243,179,254,20,68,136,0,39,140,188,254,253,208,5,255,200,115,135,1,43,172,229,255,156,104,187,0,151,251,167,0,52,135,23,0,151,153,72,0,147,197,107,254,148,158,5,255,238,143,206,0,126,153,137,255,88,152,197,254,7,68,167,0,252,159,165,255,239,78,54,255,24,63,55,255,38,222,94,0,237,183,12,255,206,204,210,0,19,39,246,254,30,74,231,0,135,108,29,1,179,115,0,0,117,118,116,1,132,6,252,255,145,129,161,1,105,67,141,0,82,37,226,255,238,226,228,255,204,214,129,254,162,123,100,255,185,121,234,0,45,108,231,0,66,8,56,255,132,136,128,0,172,224,66,254,175,157,188,0,230,223,226,254,242,219,69,0,184,14,119,1,82,162,56,0,114,123,20,0,162,103,85,255,49,239,99,254,156,135,215,0,111,255,167,254,39,196,214,0,144,38,79,1,249,168,125,0,155,97,156,255,23,52,219,255,150,22,144,0,44,149,165,255,40,127,183,0,196,77,233,255,118,129,210,255,170,135,230,255,214,119,198,0,233,240,35,0,253,52,7,255,117,102,48,255,21,204,154,255,179,136,177,255,23,2,3,1,149,130,89,255,252,17,159,1,70,60,26,0,144,107,17,0,180,190,60,255,56,182,59,255,110,71,54,255,198,18,129,255,149,224,87,255,223,21,152,255,138,22,182,255,250,156,205,0,236,45,208,255,79,148,242,1,101,70,209,0,103,78,174,0,101,144,172,255,152,136,237,1,191,194,136,0,113,80,125,1,152,4,141,0,155,150,53,255,196,116,245,0,239,114,73,254,19,82,17,255,124,125,234,255,40,52,191,0,42,210,158,255,155,132,165,0,178,5,42,1,64,92,40,255,36,85,77,255,178,228,118,0,137,66,96,254,115,226,66,0,110,240,69,254,151,111,80,0,167,174,236,255,227,108,107,255,188,242,65,255,183,81,255,0,57,206,181,255,47,34,181,255,213,240,158,1,71,75,95,0,156,40,24,255,102,210,81,0,171,199,228,255,154,34,41,0,227,175,75,0,21,239,195,0,138,229,95,1,76,192,49,0,117,123,87,1,227,225,130,0,125,62,63,255,2,198,171,0,254,36,13,254,145,186,206,0,148,255,244,255,35,0,166,0,30,150,219,1,92,228,212,0,92,198,60,254,62,133,200,255,201,41,59,0,125,238,109,255,180,163,238,1,140,122,82,0,9,22,88,255,197,157,47,255,153,94,57,0,88,30,182,0,84,161,85,0,178,146,124,0,166,166,7,255,21,208,223,0,156,182,242,0,155,121,185,0,83,156,174,254,154,16,118,255,186,83,232,1,223,58,121,255,29,23,88,0,35,125,127,255,170,5,149,254,164,12,130,255,155,196,29,0,161,96,136,0,7,35,29,1,162,37,251,0,3,46,242,255,0,217,188,0,57,174,226,1,206,233,2,0,57,187,136,254,123,189,9,255,201,117,127,255,186,36,204,0,231,25,216,0,80,78,105,0,19,134,129,255,148,203,68,0,141,81,125,254,248,165,200,255,214,144,135,0,151,55,166,255,38,235,91,0,21,46,154,0,223,254,150,255,35,153,180,255,125,176,29,1,43,98,30,255,216,122,230,255,233,160,12,0,57,185,12,254,240,113,7,255,5,9,16,254,26,91,108,0,109,198,203,0,8,147,40,0,129,134,228,255,124,186,40,255,114,98,132,254,166,132,23,0,99,69,44,0,9,242,238,255,184,53,59,0,132,129,102,255,52,32,243,254,147,223,200,255,123,83,179,254,135,144,201,255,141,37,56,1,151,60,227,255,90,73,156,1,203,172,187,0,80,151,47,255,94,137,231,255,36,191,59,255,225,209,181,255,74,215,213,254,6,118,179,255,153,54,193,1,50,0,231,0,104,157,72,1,140,227,154,255,182,226,16,254,96,225,92,255,115,20,170,254,6,250,78,0,248,75,173,255,53,89,6,255,0,180,118,0,72,173,1,0,64,8,206,1,174,133,223,0,185,62,133,255,214,11,98,0,197,31,208,0,171,167,244,255,22,231,181,1,150,218,185,0,247,169,97,1,165,139,247,255,47,120,149,1,103,248,51,0,60,69,28,254,25,179,196,0,124,7,218,254,58,107,81,0,184,233,156,255,252,74,36,0,118,188,67,0,141,95,53,255,222,94,165,254,46,61,53,0,206,59,115,255,47,236,250,255,74,5,32,1,129,154,238,255,106,32,226,0,121,187,61,255,3,166,241,254,67,170,172,255,29,216,178,255,23,201,252,0,253,110,243,0,200,125,57,0,109,192,96,255,52,115,238,0,38,121,243,255,201,56,33,0,194,118,130,0,75,96,25,255,170,30,230,254,39,63,253,0,36,45,250,255,251,1,239,0,160,212,92,1,45,209,237,0,243,33,87,254,237,84,201,255,212,18,157,254,212,99,127,255,217,98,16,254,139,172,239,0,168,201,130,255,143,193,169,255,238,151,193,1,215,104,41,0,239,61,165,254,2,3,242,0,22,203,177,254,177,204,22,0,149,129,213,254,31,11,41,255,0,159,121,254,160,25,114,255,162,80,200,0,157,151,11,0,154,134,78,1,216,54,252,0,48,103,133,0,105,220,197,0,253,168,77,254,53,179,23,0,24,121,240,1,255,46,96,255,107,60,135,254,98,205,249,255,63,249,119,255,120,59,211,255,114,180,55,254,91,85,237,0,149,212,77,1,56,73,49,0,86,198,150,0,93,209,160,0,69,205,182,255,244,90,43,0,20,36,176,0,122,116,221,0,51,167,39,1,231,1,63,255,13,197,134,0,3,209,34,255,135,59,202,0,167,100,78,0,47,223,76,0,185,60,62,0,178,166,123,1,132,12,161,255,61,174,43,0,195,69,144,0,127,47,191,1,34,44,78,0,57,234,52,1,255,22,40,255,246,94,146,0,83,228,128,0,60,78,224,255,0,96,210,255,153,175,236,0,159,21,73,0,180,115,196,254,131,225,106,0,255,167,134,0,159,8,112,255,120,68,194,255,176,196,198,255,118,48,168,255,93,169,1,0,112,200,102,1,74,24,254,0,19,141,4,254,142,62,63,0,131,179,187,255,77,156,155,255,119,86,164,0,170,208,146,255,208,133,154,255,148,155,58,255,162,120,232,254,252,213,155,0,241,13,42,0,94,50,131,0,179,170,112,0,140,83,151,255,55,119,84,1,140,35,239,255,153,45,67,1,236,175,39,0,54,151,103,255,158,42,65,255,196,239,135,254,86,53,203,0,149,97,47,254,216,35,17,255,70,3,70,1,103,36,90,255,40,26,173,0,184,48,13,0,163,219,217,255,81,6,1,255,221,170,108,254,233,208,93,0,100,201,249,254,86,36,35,255,209,154,30,1,227,201,251,255,2,189,167,254,100,57,3,0,13,128,41,0,197,100,75,0,150,204,235,255,145,174,59,0,120,248,149,255,85,55,225,0,114,210,53,254,199,204,119,0,14,247,74,1,63,251,129,0,67,104,151,1,135,130,80,0,79,89,55,255,117,230,157,255,25,96,143,0,213,145,5,0,69,241,120,1,149,243,95,255,114,42,20,0,131,72,2,0,154,53,20,255,73,62,109,0,196,102,152,0,41,12,204,255,122,38,11,1,250,10,145,0,207,125,148,0,246,244,222,255,41,32,85,1,112,213,126,0,162,249,86,1,71,198,127,255,81,9,21,1,98,39,4,255,204,71,45,1,75,111,137,0,234,59,231,0,32,48,95,255,204,31,114,1,29,196,181,255,51,241,167,254,93,109,142,0,104,144,45,0,235,12,181,255,52,112,164,0,76,254,202,255,174,14,162,0,61,235,147,255,43,64,185,254,233,125,217,0,243,88,167,254,74,49,8,0,156,204,66,0,124,214,123,0,38,221,118,1,146,112,236,0,114,98,177,0,151,89,199,0,87,197,112,0,185,149,161,0,44,96,165,0,248,179,20,255,188,219,216,254,40,62,13,0,243,142,141,0,229,227,206,255,172,202,35,255,117,176,225,255,82,110,38,1,42,245,14,255,20,83,97,0,49,171,10,0,242,119,120,0,25,232,61,0,212,240,147,255,4,115,56,255,145,17,239,254,202,17,251,255,249,18,245,255,99,117,239,0,184,4,179,255,246,237,51,255,37,239,137,255,166,112,166,255,81,188,33,255,185,250,142,255,54,187,173,0,208,112,201,0,246,43,228,1,104,184,88,255,212,52,196,255,51,117,108,255,254,117,155,0,46,91,15,255,87,14,144,255,87,227,204,0,83,26,83,1,159,76,227,0,159,27,213,1,24,151,108,0,117,144,179,254,137,209,82,0,38,159,10,0,115,133,201,0,223,182,156,1,110,196,93,255,57,60,233,0,5,167,105,255,154,197,164,0,96,34,186,255,147,133,37,1,220,99,190,0,1,167,84,255,20,145,171,0,194,197,251,254,95,78,133,255,252,248,243,255,225,93,131,255,187,134,196,255,216,153,170,0,20,118,158,254,140,1,118,0,86,158,15,1,45,211,41,255,147,1,100,254,113,116,76,255,211,127,108,1,103,15,48,0,193,16,102,1,69,51,95,255,107,128,157,0,137,171,233,0,90,124,144,1,106,161,182,0,175,76,236,1,200,141,172,255,163,58,104,0,233,180,52,255,240,253,14,255,162,113,254,255,38,239,138,254,52,46,166,0,241,101,33,254,131,186,156,0,111,208,62,255,124,94,160,255,31,172,254,0,112,174,56,255,188,99,27,255,67,138,251,0,125,58,128,1,156,152,174,255,178,12,247,255,252,84,158,0,82,197,14,254,172,200,83,255,37,39,46,1,106,207,167,0,24,189,34,0,131,178,144,0,206,213,4,0,161,226,210,0,72,51,105,255,97,45,187,255,78,184,223,255,176,29,251,0,79,160,86,255,116,37,178,0,82,77,213,1,82,84,141,255,226,101,212,1,175,88,199,255,245,94,247,1,172,118,109,255,166,185,190,0,131,181,120,0,87,254,93,255,134,240,73,255,32,245,143,255,139,162,103,255,179,98,18,254,217,204,112,0,147,223,120,255,53,10,243,0,166,140,150,0,125,80,200,255,14,109,219,255,91,218,1,255,252,252,47,254,109,156,116,255,115,49,127,1,204,87,211,255,148,202,217,255,26,85,249,255,14,245,134,1,76,89,169,255,242,45,230,0,59,98,172,255,114,73,132,254,78,155,49,255,158,126,84,0,49,175,43,255,16,182,84,255,157,103,35,0,104,193,109,255,67,221,154,0,201,172,1,254,8,162,88,0,165,1,29,255,125,155,229,255,30,154,220,1,103,239,92,0,220,1,109,255,202,198,1,0,94,2,142,1,36,54,44,0,235,226,158,255,170,251,214,255,185,77,9,0,97,74,242,0,219,163,149,255,240,35,118,255,223,114,88,254,192,199,3,0,106,37,24,255,201,161,118,255,97,89,99,1,224,58,103,255,101,199,147,254,222,60,99,0,234,25,59,1,52,135,27,0,102,3,91,254,168,216,235,0,229,232,136,0,104,60,129,0,46,168,238,0,39,191,67,0,75,163,47,0,143,97,98,255,56,216,168,1,168,233,252,255,35,111,22,255,92,84,43,0,26,200,87,1,91,253,152,0,202,56,70,0,142,8,77,0,80,10,175,1,252,199,76,0,22,110,82,255,129,1,194,0,11,128,61,1,87,14,145,255,253,222,190,1,15,72,174,0,85,163,86,254,58,99,44,255,45,24,188,254,26,205,15,0,19,229,210,254,248,67,195,0,99,71,184,0,154,199,37,255,151,243,121,255,38,51,75,255,201,85,130,254,44,65,250,0,57,147,243,254,146,43,59,255,89,28,53,0,33,84,24,255,179,51,18,254,189,70,83,0,11,156,179,1,98,134,119,0,158,111,111,0,119,154,73,255,200,63,140,254,45,13,13,255,154,192,2,254,81,72,42,0,46,160,185,254,44,112,6,0,146,215,149,1,26,176,104,0,68,28,87,1,236,50,153,255,179,128,250,254,206,193,191,255,166,92,137,254,53,40,239,0,210,1,204,254,168,173,35,0,141,243,45,1,36,50,109,255,15,242,194,255,227,159,122,255,176,175,202,254,70,57,72,0,40,223,56,0,208,162,58,255,183,98,93,0,15,111,12,0,30,8,76,255,132,127,246,255,45,242,103,0,69,181,15,255,10,209,30,0,3,179,121,0,241,232,218,1,123,199,88,255,2,210,202,1,188,130,81,255,94,101,208,1,103,36,45,0,76,193,24,1,95,26,241,255,165,162,187,0,36,114,140,0,202,66,5,255,37,56,147,0,152,11,243,1,127,85,232,255,250,135,212,1,185,177,113,0,90,220,75,255,69,248,146,0,50,111,50,0,92,22,80,0,244,36,115,254,163,100,82,255,25,193,6,1,127,61,36,0,253,67,30,254,65,236,170,255,161,17,215,254,63,175,140,0,55,127,4,0,79,112,233,0,109,160,40,0,143,83,7,255,65,26,238,255,217,169,140,255,78,94,189,255,0,147,190,255,147,71,186,254,106,77,127,255,233,157,233,1,135,87,237,255,208,13,236,1,155,109,36,255,180,100,218,0,180,163,18,0,190,110,9,1,17,63,123,255,179,136,180,255,165,123,123,255,144,188,81,254,71,240,108,255,25,112,11,255,227,218,51,255,167,50,234,255,114,79,108,255,31,19,115,255,183,240,99,0,227,87,143,255,72,217,248,255,102,169,95,1,129,149,149,0,238,133,12,1,227,204,35,0,208,115,26,1,102,8,234,0,112,88,143,1,144,249,14,0,240,158,172,254,100,112,119],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+10240);allocate([194,141,153,254,40,56,83,255,121,176,46,0,42,53,76,255,158,191,154,0,91,209,92,0,173,13,16,1,5,72,226,255,204,254,149,0,80,184,207,0,100,9,122,254,118,101,171,255,252,203,0,254,160,207,54,0,56,72,249,1,56,140,13,255,10,64,107,254,91,101,52,255,225,181,248,1,139,255,132,0,230,145,17,0,233,56,23,0,119,1,241,255,213,169,151,255,99,99,9,254,185,15,191,255,173,103,109,1,174,13,251,255,178,88,7,254,27,59,68,255,10,33,2,255,248,97,59,0,26,30,146,1,176,147,10,0,95,121,207,1,188,88,24,0,185,94,254,254,115,55,201,0,24,50,70,0,120,53,6,0,142,66,146,0,228,226,249,255,104,192,222,1,173,68,219,0,162,184,36,255,143,102,137,255,157,11,23,0,125,45,98,0,235,93,225,254,56,112,160,255,70,116,243,1,153,249,55,255,129,39,17,1,241,80,244,0,87,69,21,1,94,228,73,255,78,66,65,255,194,227,231,0,61,146,87,255,173,155,23,255,112,116,219,254,216,38,11,255,131,186,133,0,94,212,187,0,100,47,91,0,204,254,175,255,222,18,215,254,173,68,108,255,227,228,79,255,38,221,213,0,163,227,150,254,31,190,18,0,160,179,11,1,10,90,94,255,220,174,88,0,163,211,229,255,199,136,52,0,130,95,221,255,140,188,231,254,139,113,128,255,117,171,236,254,49,220,20,255,59,20,171,255,228,109,188,0,20,225,32,254,195,16,174,0,227,254,136,1,135,39,105,0,150,77,206,255,210,238,226,0,55,212,132,254,239,57,124,0,170,194,93,255,249,16,247,255,24,151,62,255,10,151,10,0,79,139,178,255,120,242,202,0,26,219,213,0,62,125,35,255,144,2,108,255,230,33,83,255,81,45,216,1,224,62,17,0,214,217,125,0,98,153,153,255,179,176,106,254,131,93,138,255,109,62,36,255,178,121,32,255,120,252,70,0,220,248,37,0,204,88,103,1,128,220,251,255,236,227,7,1,106,49,198,255,60,56,107,0,99,114,238,0,220,204,94,1,73,187,1,0,89,154,34,0,78,217,165,255,14,195,249,255,9,230,253,255,205,135,245,0,26,252,7,255,84,205,27,1,134,2,112,0,37,158,32,0,231,91,237,255,191,170,204,255,152,7,222,0,109,192,49,0,193,166,146,255,232,19,181,255,105,142,52,255,103,16,27,1,253,200,165,0,195,217,4,255,52,189,144,255,123,155,160,254,87,130,54,255,78,120,61,255,14,56,41,0,25,41,125,255,87,168,245,0,214,165,70,0,212,169,6,255,219,211,194,254,72,93,164,255,197,33,103,255,43,142,141,0,131,225,172,0,244,105,28,0,68,68,225,0,136,84,13,255,130,57,40,254,139,77,56,0,84,150,53,0,54,95,157,0,144,13,177,254,95,115,186,0,117,23,118,255,244,166,241,255,11,186,135,0,178,106,203,255,97,218,93,0,43,253,45,0,164,152,4,0,139,118,239,0,96,1,24,254,235,153,211,255,168,110,20,255,50,239,176,0,114,41,232,0,193,250,53,0,254,160,111,254,136,122,41,255,97,108,67,0,215,152,23,255,140,209,212,0,42,189,163,0,202,42,50,255,106,106,189,255,190,68,217,255,233,58,117,0,229,220,243,1,197,3,4,0,37,120,54,254,4,156,134,255,36,61,171,254,165,136,100,255,212,232,14,0,90,174,10,0,216,198,65,255,12,3,64,0,116,113,115,255,248,103,8,0,231,125,18,255,160,28,197,0,30,184,35,1,223,73,249,255,123,20,46,254,135,56,37,255,173,13,229,1,119,161,34,255,245,61,73,0,205,125,112,0,137,104,134,0,217,246,30,255,237,142,143,0,65,159,102,255,108,164,190,0,219,117,173,255,34,37,120,254,200,69,80,0,31,124,218,254,74,27,160,255,186,154,199,255,71,199,252,0,104,81,159,1,17,200,39,0,211,61,192,1,26,238,91,0,148,217,12,0,59,91,213,255,11,81,183,255,129,230,122,255,114,203,145,1,119,180,66,255,72,138,180,0,224,149,106,0,119,82,104,255,208,140,43,0,98,9,182,255,205,101,134,255,18,101,38,0,95,197,166,255,203,241,147,0,62,208,145,255,133,246,251,0,2,169,14,0,13,247,184,0,142,7,254,0,36,200,23,255,88,205,223,0,91,129,52,255,21,186,30,0,143,228,210,1,247,234,248,255,230,69,31,254,176,186,135,255,238,205,52,1,139,79,43,0,17,176,217,254,32,243,67,0,242,111,233,0,44,35,9,255,227,114,81,1,4,71,12,255,38,105,191,0,7,117,50,255,81,79,16,0,63,68,65,255,157,36,110,255,77,241,3,255,226,45,251,1,142,25,206,0,120,123,209,1,28,254,238,255,5,128,126,255,91,222,215,255,162,15,191,0,86,240,73,0,135,185,81,254,44,241,163,0,212,219,210,255,112,162,155,0,207,101,118,0,168,72,56,255,196,5,52,0,72,172,242,255,126,22,157,255,146,96,59,255,162,121,152,254,140,16,95,0,195,254,200,254,82,150,162,0,119,43,145,254,204,172,78,255,166,224,159,0,104,19,237,255,245,126,208,255,226,59,213,0,117,217,197,0,152,72,237,0,220,31,23,254,14,90,231,255,188,212,64,1,60,101,246,255,85,24,86,0,1,177,109,0,146,83,32,1,75,182,192,0,119,241,224,0,185,237,27,255,184,101,82,1,235,37,77,255,253,134,19,0,232,246,122,0,60,106,179,0,195,11,12,0,109,66,235,1,125,113,59,0,61,40,164,0,175,104,240,0,2,47,187,255,50,12,141,0,194,139,181,255,135,250,104,0,97,92,222,255,217,149,201,255,203,241,118,255,79,151,67,0,122,142,218,255,149,245,239,0,138,42,200,254,80,37,97,255,124,112,167,255,36,138,87,255,130,29,147,255,241,87,78,255,204,97,19,1,177,209,22,255,247,227,127,254,99,119,83,255,212,25,198,1,16,179,179,0,145,77,172,254,89,153,14,255,218,189,167,0,107,233,59,255,35,33,243,254,44,112,112,255,161,127,79,1,204,175,10,0,40,21,138,254,104,116,228,0,199,95,137,255,133,190,168,255,146,165,234,1,183,99,39,0,183,220,54,254,255,222,133,0,162,219,121,254,63,239,6,0,225,102,54,255,251,18,246,0,4,34,129,1,135,36,131,0,206,50,59,1,15,97,183,0,171,216,135,255,101,152,43,255,150,251,91,0,38,145,95,0,34,204,38,254,178,140,83,255,25,129,243,255,76,144,37,0,106,36,26,254,118,144,172,255,68,186,229,255,107,161,213,255,46,163,68,255,149,170,253,0,187,17,15,0,218,160,165,255,171,35,246,1,96,13,19,0,165,203,117,0,214,107,192,255,244,123,177,1,100,3,104,0,178,242,97,255,251,76,130,255,211,77,42,1,250,79,70,255,63,244,80,1,105,101,246,0,61,136,58,1,238,91,213,0,14,59,98,255,167,84,77,0,17,132,46,254,57,175,197,255,185,62,184,0,76,64,207,0,172,175,208,254,175,74,37,0,138,27,211,254,148,125,194,0,10,89,81,0,168,203,101,255,43,213,209,1,235,245,54,0,30,35,226,255,9,126,70,0,226,125,94,254,156,117,20,255,57,248,112,1,230,48,64,255,164,92,166,1,224,214,230,255,36,120,143,0,55,8,43,255,251,1,245,1,106,98,165,0,74,107,106,254,53,4,54,255,90,178,150,1,3,120,123,255,244,5,89,1,114,250,61,255,254,153,82,1,77,15,17,0,57,238,90,1,95,223,230,0,236,52,47,254,103,148,164,255,121,207,36,1,18,16,185,255,75,20,74,0,187,11,101,0,46,48,129,255,22,239,210,255,77,236,129,255,111,77,204,255,61,72,97,255,199,217,251,255,42,215,204,0,133,145,201,255,57,230,146,1,235,100,198,0,146,73,35,254,108,198,20,255,182,79,210,255,82,103,136,0,246,108,176,0,34,17,60,255,19,74,114,254,168,170,78,255,157,239,20,255,149,41,168,0,58,121,28,0,79,179,134,255,231,121,135,255,174,209,98,255,243,122,190,0,171,166,205,0,212,116,48,0,29,108,66,255,162,222,182,1,14,119,21,0,213,39,249,255,254,223,228,255,183,165,198,0,133,190,48,0,124,208,109,255,119,175,85,255,9,209,121,1,48,171,189,255,195,71,134,1,136,219,51,255,182,91,141,254,49,159,72,0,35,118,245,255,112,186,227,255,59,137,31,0,137,44,163,0,114,103,60,254,8,213,150,0,162,10,113,255,194,104,72,0,220,131,116,255,178,79,92,0,203,250,213,254,93,193,189,255,130,255,34,254,212,188,151,0,136,17,20,255,20,101,83,255,212,206,166,0,229,238,73,255,151,74,3,255,168,87,215,0,155,188,133,255,166,129,73,0,240,79,133,255,178,211,81,255,203,72,163,254,193,168,165,0,14,164,199,254,30,255,204,0,65,72,91,1,166,74,102,255,200,42,0,255,194,113,227,255,66,23,208,0,229,216,100,255,24,239,26,0,10,233,62,255,123,10,178,1,26,36,174,255,119,219,199,1,45,163,190,0,16,168,42,0,166,57,198,255,28,26,26,0,126,165,231,0,251,108,100,255,61,229,121,255,58,118,138,0,76,207,17,0,13,34,112,254,89,16,168,0,37,208,105,255,35,201,215,255,40,106,101,254,6,239,114,0,40,103,226,254,246,127,110,255,63,167,58,0,132,240,142,0,5,158,88,255,129,73,158,255,94,89,146,0,230,54,146,0,8,45,173,0,79,169,1,0,115,186,247,0,84,64,131,0,67,224,253,255,207,189,64,0,154,28,81,1,45,184,54,255,87,212,224,255,0,96,73,255,129,33,235,1,52,66,80,255,251,174,155,255,4,179,37,0,234,164,93,254,93,175,253,0,198,69,87,255,224,106,46,0,99,29,210,0,62,188,114,255,44,234,8,0,169,175,247,255,23,109,137,255,229,182,39,0,192,165,94,254,245,101,217,0,191,88,96,0,196,94,99,255,106,238,11,254,53,126,243,0,94,1,101,255,46,147,2,0,201,124,124,255,141,12,218,0,13,166,157,1,48,251,237,255,155,250,124,255,106,148,146,255,182,13,202,0,28,61,167,0,217,152,8,254,220,130,45,255,200,230,255,1,55,65,87,255,93,191,97,254,114,251,14,0,32,105,92,1,26,207,141,0,24,207,13,254,21,50,48,255,186,148,116,255,211,43,225,0,37,34,162,254,164,210,42,255,68,23,96,255,182,214,8,255,245,117,137,255,66,195,50,0,75,12,83,254,80,140,164,0,9,165,36,1,228,110,227,0,241,17,90,1,25,52,212,0,6,223,12,255,139,243,57,0,12,113,75,1,246,183,191,255,213,191,69,255,230,15,142,0,1,195,196,255,138,171,47,255,64,63,106,1,16,169,214,255,207,174,56,1,88,73,133,255,182,133,140,0,177,14,25,255,147,184,53,255,10,227,161,255,120,216,244,255,73,77,233,0,157,238,139,1,59,65,233,0,70,251,216,1,41,184,153,255,32,203,112,0,146,147,253,0,87,101,109,1,44,82,133,255,244,150,53,255,94,152,232,255,59,93,39,255,88,147,220,255,78,81,13,1,32,47,252,255,160,19,114,255,93,107,39,255,118,16,211,1,185,119,209,255,227,219,127,254,88,105,236,255,162,110,23,255,36,166,110,255,91,236,221,255,66,234,116,0,111,19,244,254,10,233,26,0,32,183,6,254,2,191,242,0,218,156,53,254,41,60,70,255,168,236,111,0,121,185,126,255,238,142,207,255,55,126,52,0,220,129,208,254,80,204,164,255,67,23,144,254,218,40,108,255,127,202,164,0,203,33,3,255,2,158,0,0,37,96,188,255,192,49,74,0,109,4,0,0,111,167,10,254,91,218,135,255,203,66,173,255,150,194,226,0,201,253,6,255,174,102,121,0,205,191,110,0,53,194,4,0,81,40,45,254,35,102,143,255,12,108,198,255,16,27,232,255,252,71,186,1,176,110,114,0,142,3,117,1,113,77,142,0,19,156,197,1,92,47,252,0,53,232,22,1,54,18,235,0,46,35,189,255,236,212,129,0,2,96,208,254,200,238,199,255,59,175,164,255,146,43,231,0,194,217,52,255,3,223,12,0,138,54,178,254,85,235,207,0,232,207,34,0,49,52,50,255,166,113,89,255,10,45,216,255,62,173,28,0,111,165,246,0,118,115,91,255,128,84,60,0,167,144,203,0,87,13,243,0,22,30,228,1,177,113,146,255,129,170,230,254,252,153,129,255,145,225,43,0,70,231,5,255,122,105,126,254,86,246,148,255,110,37,154,254,209,3,91,0,68,145,62,0,228,16,165,255,55,221,249,254,178,210,91,0,83,146,226,254,69,146,186,0,93,210,104,254,16,25,173,0,231,186,38,0,189,122,140,255,251,13,112,255,105,110,93,0,251,72,170,0,192,23,223,255,24,3,202,1,225,93,228,0,153,147,199,254,109,170,22,0,248,101,246,255,178,124,12,255,178,254,102,254,55,4,65,0,125,214,180,0,183,96,147,0,45,117,23,254,132,191,249,0,143,176,203,254,136,183,54,255,146,234,177,0,146,101,86,255,44,123,143,1,33,209,152,0,192,90,41,254,83,15,125,255,213,172,82,0,215,169,144,0,16,13,34,0,32,209,100,255,84,18,249,1,197,17,236,255,217,186,230,0,49,160,176,255,111,118,97,255,237,104,235,0,79,59,92,254,69,249,11,255,35,172,74,1,19,118,68,0,222,124,165,255,180,66,35,255,86,174,246,0,43,74,111,255,126,144,86,255,228,234,91,0,242,213,24,254,69,44,235,255,220,180,35,0,8,248,7,255,102,47,92,255,240,205,102,255,113,230,171,1,31,185,201,255,194,246,70,255,122,17,187,0,134,70,199,255,149,3,150,255,117,63,103,0,65,104,123,255,212,54,19,1,6,141,88,0,83,134,243,255,136,53,103,0,169,27,180,0,177,49,24,0,111,54,167,0,195,61,215,255,31,1,108,1,60,42,70,0,185,3,162,255,194,149,40,255,246,127,38,254,190,119,38,255,61,119,8,1,96,161,219,255,42,203,221,1,177,242,164,255,245,159,10,0,116,196,0,0,5,93,205,254,128,127,179,0,125,237,246,255,149,162,217,255,87,37,20,254,140,238,192,0,9,9,193,0,97,1,226,0,29,38,10,0,0,136,63,255,229,72,210,254,38,134,92,255,78,218,208,1,104,36,84,255,12,5,193,255,242,175,61,255,191,169,46,1,179,147,147,255,113,190,139,254,125,172,31,0,3,75,252,254,215,36,15,0,193,27,24,1,255,69,149,255,110,129,118,0,203,93,249,0,138,137,64,254,38,70,6,0,153,116,222,0,161,74,123,0,193,99,79,255,118,59,94,255,61,12,43,1,146,177,157,0,46,147,191,0,16,255,38,0,11,51,31,1,60,58,98,255,111,194,77,1,154,91,244,0,140,40,144,1,173,10,251,0,203,209,50,254,108,130,78,0,228,180,90,0,174,7,250,0,31,174,60,0,41,171,30,0,116,99,82,255,118,193,139,255,187,173,198,254,218,111,56,0,185,123,216,0,249,158,52,0,52,180,93,255,201,9,91,255,56,45,166,254,132,155,203,255,58,232,110,0,52,211,89,255,253,0,162,1,9,87,183,0,145,136,44,1,94,122,245,0,85,188,171,1,147,92,198,0,0,8,104,0,30,95,174,0,221,230,52,1,247,247,235,255,137,174,53,255,35,21,204,255,71,227,214,1,232,82,194,0,11,48,227,255,170,73,184,255,198,251,252,254,44,112,34,0,131,101,131,255,72,168,187,0,132,135,125,255,138,104,97,255,238,184,168,255,243,104,84,255,135,216,226,255,139,144,237,0,188,137,150,1,80,56,140,255,86,169,167,255,194,78,25,255,220,17,180,255,17,13,193,0,117,137,212,255,141,224,151,0,49,244,175,0,193,99,175,255,19,99,154,1,255,65,62,255,156,210,55,255,242,244,3,255,250,14,149,0,158,88,217,255,157,207,134,254,251,232,28,0,46,156,251,255,171,56,184,255,239,51,234,0,142,138,131,255,25,254,243,1,10,201,194,0,63,97,75,0,210,239,162,0,192,200,31,1,117,214,243,0,24,71,222,254,54,40,232,255,76,183,111,254,144,14,87,255,214,79,136,255,216,196,212,0,132,27,140,254,131,5,253,0,124,108,19,255,28,215,75,0,76,222,55,254,233,182,63,0,68,171,191,254,52,111,222,255,10,105,77,255,80,170,235,0,143,24,88,255,45,231,121,0,148,129,224,1,61,246,84,0,253,46,219,255,239,76,33,0,49,148,18,254,230,37,69,0,67,134,22,254,142,155,94,0,31,157,211,254,213,42,30,255,4,228,247,254,252,176,13,255,39,0,31,254,241,244,255,255,170,45,10,254,253,222,249,0,222,114,132,0,255,47,6,255,180,163,179,1,84,94,151,255,89,209,82,254,229,52,169,255,213,236,0,1,214,56,228,255,135,119,151,255,112,201,193,0,83,160,53,254,6,151,66,0,18,162,17,0,233,97,91,0,131,5,78,1,181,120,53,255,117,95,63,255,237,117,185,0,191,126,136,255,144,119,233,0,183,57,97,1,47,201,187,255,167,165,119,1,45,100,126,0,21,98,6,254,145,150,95,255,120,54,152,0,209,98,104,0,143,111,30,254,184,148,249,0,235,216,46,0,248,202,148,255,57,95,22,0,242,225,163,0,233,247,232,255,71,171,19,255,103,244,49,255,84,103,93,255,68,121,244,1,82,224,13,0,41,79,43,255,249,206,167,255,215,52,21,254,192,32,22,255,247,111,60,0,101,74,38,255,22,91,84,254,29,28,13,255,198,231,215,254,244,154,200,0,223,137,237,0,211,132,14,0,95,64,206,255,17,62,247,255,233,131,121,1,93,23,77,0,205,204,52,254,81,189,136,0,180,219,138,1,143,18,94,0,204,43,140,254,188,175,219,0,111,98,143,255,151,63,162,255,211,50,71,254,19,146,53,0,146,45,83,254,178,82,238,255,16,133,84,255,226,198,93,255,201,97,20,255,120,118,35,255,114,50,231,255,162,229,156,255,211,26,12,0,114,39,115,255,206,212,134,0,197,217,160,255,116,129,94,254,199,215,219,255,75,223,249,1,253,116,181,255,232,215,104,255,228,130,246,255,185,117,86,0,14,5,8,0,239,29,61,1,237,87,133,255,125,146,137,254,204,168,223,0,46,168,245,0,154,105,22,0,220,212,161,255,107,69,24,255,137,218,181,255,241,84,198,255,130,122,211,255,141,8,153,255,190,177,118,0,96,89,178,0,255,16,48,254,122,96,105,255,117,54,232,255,34,126,105,255,204,67,166,0,232,52,138,255,211,147,12,0,25,54,7,0,44,15,215,254,51,236,45,0,190,68,129,1,106,147,225,0,28,93,45,254,236,141,15,255,17,61,161,0,220,115,192,0,236,145,24,254,111,168,169,0,224,58,63,255,127,164,188,0,82,234,75,1,224,158,134,0,209,68,110,1,217,166,217,0,70,225,166,1,187,193,143,255,16,7,88,255,10,205,140,0,117,192,156,1,17,56,38,0,27,124,108,1,171,215,55,255,95,253,212,0,155,135,168,255,246,178,153,254,154,68,74,0,232,61,96,254,105,132,59,0,33,76,199,1,189,176,130,255,9,104,25,254,75,198,102,255,233,1,112,0,108,220,20,255,114,230,70,0,140,194,133,255,57,158,164,254,146,6,80,255,169,196,97,1,85,183,130,0,70,158,222,1,59,237,234,255,96,25,26,255,232,175,97,255,11,121,248,254,88,35,194,0,219,180,252,254,74,8,227,0,195,227,73,1,184,110,161,255,49,233,164,1,128,53,47,0,82,14,121,255,193,190,58,0,48,174,117,255,132,23,32,0,40,10,134,1,22,51,25,255,240,11,176,255,110,57,146,0,117,143,239,1,157,101,118,255,54,84,76,0,205,184,18,255,47,4,72,255,78,112,85,255,193,50,66,1,93,16,52,255,8,105,134,0,12,109,72,255,58,156,251,0,144,35,204,0,44,160,117,254,50,107,194,0,1,68,165,255,111,110,162,0,158,83,40,254,76,214,234,0,58,216,205,255,171,96,147,255,40,227,114,1,176,227,241,0,70,249,183,1,136,84,139,255,60,122,247,254,143,9,117,255,177,174,137,254,73,247,143,0,236,185,126,255,62,25,247,255,45,64,56,255,161,244,6,0,34,57,56,1,105,202,83,0,128,147,208,0,6,103,10,255,74,138,65,255,97,80,100,255,214,174,33,255,50,134,74,255,110,151,130,254,111,84,172,0,84,199,75,254,248,59,112,255,8,216,178,1,9,183,95,0,238,27,8,254,170,205,220,0,195,229,135,0,98,76,237,255,226,91,26,1,82,219,39,255,225,190,199,1,217,200,121,255,81,179,8,255,140,65,206,0,178,207,87,254,250,252,46,255,104,89,110,1,253,189,158,255,144,214,158,255,160,245,54,255,53,183,92,1,21,200,194,255,146,33,113,1,209,1,255,0,235,106,43,255,167,52,232,0,157,229,221,0,51,30,25,0,250,221,27,1,65,147,87,255,79,123,196,0,65,196,223,255,76,44,17,1,85,241,68,0,202,183,249,255,65,212,212,255,9,33,154,1,71,59,80,0,175,194,59,255,141,72,9,0,100,160,244,0,230,208,56,0,59,25,75,254,80,194,194,0,18,3,200,254,160,159,115,0,132,143,247,1,111,93,57,255,58,237,11,1,134,222,135,255,122,163,108,1,123,43,190,255,251,189,206,254,80,182,72,255,208,246,224,1,17,60,9,0,161,207,38,0,141,109,91,0,216,15,211,255,136,78,110,0,98,163,104,255,21,80,121,255,173,178,183,1,127,143,4,0,104,60,82,254,214,16,13,255,96,238,33,1,158,148,230,255,127,129,62,255,51,255,210,255,62,141,236,254,157,55,224,255,114,39,244,0,192,188,250,255,228,76,53,0,98,84,81,255,173,203,61,254,147,50,55,255,204,235,191,0,52,197,244,0,88,43,211,254,27,191,119,0,188,231,154,0,66,81,161,0,92,193,160,1,250,227,120,0,123,55,226,0,184,17,72,0,133,168,10,254,22,135,156,255,41,25,103,255,48,202,58,0,186,149,81,255,188,134,239,0,235,181,189,254,217,139,188,255,74,48,82,0,46,218,229,0,189,253,251,0,50,229,12,255,211,141,191,1,128,244,25,255,169,231,122,254,86,47,189,255,132,183,23,255,37,178,150,255,51,137,253,0,200,78,31,0,22,105,50,0,130,60,0,0,132,163,91,254,23,231,187,0,192,79,239,0,157,102,164,255,192,82,20,1,24,181,103,255,240,9,234,0,1,123,164,255,133,233,0,255,202,242,242,0,60,186,245,0,241,16,199,255,224,116,158,254,191,125,91,255,224,86,207,0,121,37,231,255,227,9,198,255,15,153,239,255,121,232,217,254,75,112,82,0,95,12,57,254,51,214,105,255,148,220,97,1,199,98,36,0,156,209,12,254,10,212,52,0,217,180,55,254,212,170,232,255,216,20,84,255,157,250,135,0,157,99,127,254,1,206,41,0,149,36,70,1,54,196,201,255,87,116,0,254,235,171,150,0,27,163,234,0,202,135,180,0,208,95,0,254,123,156,93,0,183,62,75,0,137,235,182,0,204,225,255,255,214,139,210,255,2,115,8,255,29,12,111,0,52,156,1,0,253,21,251,255,37,165,31,254,12,130,211,0,106,18,53,254,42,99,154,0,14,217,61,254,216,11,92,255,200,197,112,254,147,38,199,0,36,252,120,254,107,169,77,0,1,123,159,255,207,75,102,0,163,175,196,0,44,1,240,0,120,186,176,254,13,98,76,255,237,124,241,255,232,146,188,255,200,96,224,0,204,31,41,0,208,200,13,0,21,225,96,255,175,156,196,0,247,208,126,0,62,184,244,254,2,171,81,0,85,115,158,0,54,64,45,255,19,138,114,0,135,71,205,0,227,47,147,1,218,231,66,0,253,209,28,0,244,15,173,255,6,15,118,254,16,150,208,255,185,22,50,255,86,112,207,255,75,113,215,1,63,146,43,255,4,225,19,254,227,23,62,255,14,255,214,254,45,8,205,255,87,197,151,254,210,82,215,255,245,248,247,255,128,248,70,0,225,247,87,0,90,120,70,0,213,245,92,0,13,133,226,0,47,181,5,1,92,163,105,255,6,30,133,254,232,178,61,255,230,149,24,255,18,49,158,0,228,100,61,254,116,243,251,255,77,75,92,1,81,219,147,255,76,163,254,254,141,213,246,0,232,37,152,254,97,44,100,0,201,37,50,1,212,244,57,0,174,171,183,255,249,74,112,0,166,156,30,0,222,221,97,255,243,93,73,254,251,101,100,255,216,217,93,255,254,138,187,255,142,190,52,255,59,203,177,255,200,94,52,0,115,114,158,255,165,152,104,1,126,99,226,255,118,157,244,1,107,200,16,0,193,90,229,0,121,6,88,0,156,32,93,254,125,241,211,255,14,237,157,255,165,154,21,255,184,224,22,255,250,24,152,255,113,77,31,0,247,171,23,255,237,177,204,255,52,137,145,255,194,182,114,0,224,234,149,0,10,111,103,1,201,129,4,0,238,142,78,0,52,6,40,255,110,213,165,254,60,207,253,0,62,215,69,0,96,97,0,255,49,45,202,0,120,121,22,255,235,139,48,1,198,45,34,255,182,50,27,1,131,210,91,255,46,54,128,0,175,123,105,255,198,141,78,254,67,244,239,255,245,54,103,254,78,38,242,255,2,92,249,254,251,174,87,255,139,63,144,0,24,108,27,255,34,102,18,1,34,22,152,0,66,229,118,254,50,143,99,0,144,169,149,1,118,30,152,0,178,8,121,1,8,159,18,0,90,101,230,255,129,29,119,0,68,36,11,1,232,183,55,0,23,255,96,255,161,41,193,255,63,139,222,0,15,179,243,0,255,100,15,255,82,53,135,0,137,57,149,1,99,240,170,255,22,230,228,254,49,180,82,255,61,82,43,0,110,245,217,0,199,125,61,0,46,253,52,0,141,197,219,0,211,159,193,0,55,121,105,254,183,20,129,0,169,119,170,255,203,178,139,255,135,40,182,255,172,13,202,255,65,178,148,0,8,207,43,0,122,53,127,1,74,161,48,0,227,214,128,254,86,11,243,255,100,86,7,1,245,68,134,255,61,43,21,1,152,84,94,255,190,60,250,254,239,118,232,255,214,136,37,1,113,76,107,255,93,104,100,1,144,206,23,255,110,150,154,1,228,103,185,0,218,49,50,254,135,77,139,255,185,1,78,0,0,161,148,255,97,29,233,255,207,148,149,255,160,168,0,0,91,128,171,255,6,28,19,254,11,111,247,0,39,187,150,255,138,232,149,0,117,62,68,255,63,216,188,255,235,234,32,254,29,57,160,255,25,12,241,1,169,60,191,0,32,131,141,255,237,159,123,255,94,197,94,254,116,254,3,255,92,179,97,254,121,97,92,255,170,112,14,0,21,149,248,0,248,227,3,0,80,96,109,0,75,192,74,1,12,90,226,255,161,106,68,1,208,114,127,255,114,42,255,254,74,26,74,255,247,179,150,254,121,140,60,0,147,70,200,255,214,40,161,255,161,188,201,255,141,65,135,255,242,115,252,0,62,47,202,0,180,149,255,254,130,55,237,0,165,17,186,255,10,169,194,0,156,109,218,255,112,140,123,255,104,128,223,254,177,142,108,255,121,37,219,255,128,77,18,255,111,108,23,1,91,192,75,0,174,245,22,255,4,236,62,255,43,64,153,1,227,173,254,0,237,122,132,1,127,89,186,255,142,82,128,254,252,84,174,0,90,179,177,1,243,214,87,255,103,60,162,255,208,130,14,255,11,130,139,0,206,129,219,255,94,217,157,255,239,230,230,255,116,115,159,254,164,107,95,0,51,218,2,1,216,125,198,255,140,202,128,254,11,95,68,255,55,9,93,254,174,153,6,255,204,172,96,0,69,160,110,0,213,38,49,254,27,80,213,0,118,125,114,0,70,70,67,255,15,142,73,255,131,122,185,255,243,20,50,254,130,237,40,0,210,159,140,1,197,151,65,255,84,153,66,0,195,126,90,0,16,238,236,1,118,187,102,255,3,24,133,255,187,69,230,0,56,197,92,1,213,69,94,255,80,138,229,1,206,7,230,0,222,111,230,1,91,233,119,255,9,89,7,1,2,98,1,0,148,74,133,255,51,246,180,255,228,177,112,1,58,189,108,255,194,203,237,254,21,209,195,0,147,10,35,1,86,157,226,0,31,163,139,254,56,7,75,255,62,90,116,0,181,60,169,0,138,162,212,254,81,167,31,0,205,90,112,255,33,112,227,0,83,151,117,1,177,224,73,255,174,144,217,255,230,204,79,255,22,77,232,255,114,78,234,0,224,57,126,254,9,49,141,0,242,147,165,1,104,182,140,255,167,132,12,1,123,68,127,0,225,87,39,1,251,108,8,0,198,193,143,1,121,135,207,255,172,22,70,0,50,68,116,255,101,175,40,255,248,105,233,0,166,203,7,0,110,197,218,0,215,254,26,254,168,226,253,0,31,143,96,0,11,103,41,0,183,129,203,254,100,247,74,255,213,126,132,0,210,147,44,0,199,234,27,1,148,47,181,0,155,91,158,1,54,105,175,255,2,78,145,254,102,154,95,0,128,207,127,254,52,124,236,255,130,84,71,0,221,243,211,0,152,170,207,0,222,106,199,0,183,84,94,254,92,200,56,255,138,182,115,1,142,96,146,0,133,136,228,0,97,18,150,0,55,251,66,0,140,102,4,0,202,103,151,0,30,19,248,255,51,184,207,0,202,198,89,0,55,197,225,254,169,95,249,255,66,65,68,255,188,234,126,0,166,223,100,1,112,239,244,0,144,23,194,0,58,39,182,0,244,44,24,254,175,68,179,255,152,118,154,1,176,162,130,0,217,114,204,254,173,126,78,255,33,222,30,255,36,2,91,255,2,143,243,0,9,235,215,0,3,171,151,1,24,215,245,255,168,47,164,254,241,146,207,0,69,129,180,0,68,243,113,0,144,53,72,254,251,45,14,0,23,110,168,0,68,68,79,255,110,70,95,254,174,91,144,255,33,206,95,255,137,41,7,255,19,187,153,254,35,255,112,255,9,145,185,254,50,157,37,0,11,112,49,1,102,8,190,255,234,243,169,1,60,85,23,0,74,39,189,0,116,49,239,0,173,213,210,0,46,161,108,255,159,150,37,0,196,120,185,255,34,98,6,255,153,195,62,255,97,230,71,255,102,61,76,0,26,212,236,255,164,97,16,0,198,59,146,0,163,23,196,0,56,24,61,0,181,98,193,0,251,147,229,255,98,189,24,255,46,54,206,255,234,82,246,0,183,103,38,1,109,62,204,0,10,240,224,0,146,22,117,255,142,154,120,0,69,212,35,0,208,99,118,1,121,255,3,255,72,6,194,0,117,17,197,255,125,15,23,0,154,79,153,0,214,94,197,255,185,55,147,255,62,254,78,254,127,82,153,0,110,102,63,255,108,82,161,255,105,187,212,1,80,138,39,0,60,255,93,255,72,12,186,0,210,251,31,1,190,167,144,255,228,44,19,254,128,67,232,0,214,249,107,254,136,145,86,255,132,46,176,0,189,187,227,255,208,22,140,0,217,211,116,0,50,81,186,254,139,250,31,0,30,64,198,1,135,155,100,0,160,206,23,254,187,162,211,255,16,188,63,0,254,208,49,0,85,84,191,0,241,192,242,255,153,126,145,1,234,162,162,255,230,97,216,1,64,135,126,0,190,148,223,1,52,0,43,255,28,39,189,1,64,136,238,0,175,196,185,0,98,226,213,255,127,159,244,1,226,175,60,0,160,233,142,1,180,243,207,255,69,152,89,1,31,101,21,0,144,25,164,254,139,191,209,0,91,25,121,0,32,147,5,0,39,186,123,255,63,115,230,255,93,167,198,255,143,213,220,255,179,156,19,255,25,66,122,0,214,160,217,255,2,45,62,255,106,79,146,254,51,137,99,255,87,100,231,255,175,145,232,255,101,184,1,255,174,9,125,0,82,37,161,1,36,114,141,255,48,222,142,255,245,186,154,0,5,174,221,254,63,114,155,255,135,55,160,1,80,31,135,0,126,250,179,1,236,218,45,0,20,28,145,1,16,147,73,0,249,189,132,1,17,189,192,255,223,142,198,255,72,20,15,255,250,53,237,254,15,11,18,0,27,211,113,254,213,107,56,255,174,147,146,255,96,126,48,0,23,193,109,1,37,162,94,0,199,157,249,254,24,128,187,255,205,49,178,254,93,164,42,255,43,119,235,1,88,183,237,255,218,210,1,255,107,254,42,0,230,10,99,255,162,0,226,0,219,237,91,0,129,178,203,0,208,50,95,254,206,208,95,255,247,191,89,254,110,234,79,255,165,61,243,0,20,122,112,255,246,246,185,254,103,4,123,0,233,99,230,1,219,91,252,255,199,222,22,255,179,245,233,255,211,241,234,0,111,250,192,255,85,84,136,0,101,58,50,255,131,173,156,254,119,45,51,255,118,233,16,254,242,90,214,0,94,159,219,1,3,3,234,255,98,76,92,254,80,54,230,0,5,228,231,254,53,24,223,255,113,56,118,1,20,132,1,255,171,210,236,0,56,241,158,255,186,115,19,255,8,229,174,0,48,44,0,1,114,114,166,255,6,73,226,255,205,89,244,0,137,227,75,1,248,173,56,0,74,120,246,254,119,3,11,255,81,120,198,255,136,122,98,255,146,241,221,1,109,194,78,255,223,241,70,1,214,200,169,255,97,190,47,255,47,103,174,255,99,92,72,254,118,233,180,255,193,35,233,254,26,229,32,255,222,252,198,0,204,43,71,255,199,84,172,0,134,102,190,0,111,238,97,254,230,40,230,0,227,205,64,254,200,12,225,0,166,25,222,0,113,69,51,255,143,159,24,0,167,184,74,0,29,224,116,254,158,208,233,0,193,116,126,255,212,11,133,255,22,58,140,1,204,36,51,255,232,30,43,0,235,70,181,255,64,56,146,254,169,18,84,255,226,1,13,255,200,50,176,255,52,213,245,254,168,209,97,0,191,71,55,0,34,78,156,0,232,144,58,1,185,74,189,0,186,142,149,254,64,69,127,255,161,203,147,255,176,151,191,0,136,231,203,254,163,182,137,0,161,126,251,254,233,32,66,0,68,207,66,0,30,28,37,0,93,114,96,1,254,92,247,255,44,171,69,0,202,119,11,255,188,118,50,1,255,83,136,255,71,82,26,0,70,227,2,0,32,235,121,1,181,41,154,0,71,134,229,254,202,255,36,0,41,152,5,0,154,63,73,255,34,182,124,0,121,221,150,255,26,204,213,1,41,172,87,0,90,157,146,255,109,130,20,0,71,107,200,255,243,102,189,0,1,195,145,254,46,88,117,0,8,206,227,0,191,110,253,255,109,128,20,254,134,85,51,255,137,177,112,1,216,34,22,255,131,16,208,255,121,149,170,0,114,19,23,1,166,80,31,255,113,240,122,0,232,179,250,0,68,110,180,254,210,170,119,0,223,108,164,255,207,79,233,255,27,229,226,254,209,98,81,255,79,68,7,0,131,185,100,0,170,29,162,255,17,162,107,255,57,21,11,1,100,200,181,255,127,65,166,1,165,134,204,0,104,167,168,0,1,164,79,0,146,135,59,1,70,50,128,255,102,119,13,254,227,6,135,0,162,142,179,255,160,100,222,0,27,224,219,1,158,93,195,255,234,141,137,0,16,24,125,255,238,206,47,255,97,17,98,255,116,110,12,255,96,115,77,0,91,227,232,255,248,254,79,255,92,229,6,254,88,198,139,0,206,75,129,0,250,77,206,255,141,244,123,1,138,69,220,0,32,151,6,1,131,167,22,255,237,68,167,254,199,189,150,0,163,171,138,255,51,188,6,255,95,29,137,254,148,226,179,0,181,107,208,255,134,31,82,255,151,101,45,255,129,202,225,0,224,72,147,0,48,138,151,255,195,64,206,254,237,218,158,0,106,29,137,254,253,189,233,255,103,15,17,255,194,97,255,0,178,45,169,254,198,225,155,0,39,48,117,255,135,106,115,0,97,38,181,0,150,47,65,255,83,130,229,254,246,38,129,0,92,239,154,254,91,99,127,0,161,111,33,255,238,217,242,255,131,185,195,255,213,191,158,255,41,150,218,0,132,169,131,0,89,84,252,1,171,70,128,255,163,248,203,254,1,50,180,255,124,76,85,1,251,111,80,0,99,66,239,255,154,237,182,255,221,126,133,254,74,204,99,255,65,147,119,255,99,56,167,255,79,248,149,255,116,155,228,255,237,43,14,254,69,137,11,255,22,250,241,1,91,122,143,255,205,249,243,0,212,26,60,255,48,182,176,1,48,23,191,255,203,121,152,254,45,74,213,255,62,90,18,254,245,163,230,255,185,106,116,255,83,35,159,0,12,33,2,255,80,34,62,0,16,87,174,255,173,101,85,0,202,36,81,254,160,69,204,255,64,225,187,0,58,206,94,0,86,144,47,0,229,86,245,0,63,145,190,1,37,5,39,0,109,251,26,0,137,147,234,0,162,121,145,255,144,116,206,255,197,232,185,255,183,190,140,255,73,12,254,255,139,20,242,255,170,90,239,255,97,66,187,255,245,181,135,254,222,136,52,0,245,5,51,254,203,47,78,0,152,101,216,0,73,23,125,0,254,96,33,1,235,210,73,255,43,209,88,1,7,129,109,0,122,104,228,254,170,242,203,0,242,204,135,255,202,28,233,255,65,6,127,0,159,144,71,0,100,140,95,0,78,150,13,0,251,107,118,1,182,58,125,255,1,38,108,255,141,189,209,255,8,155,125,1,113,163,91,255,121,79,190,255,134,239,108,255,76,47,248,0,163,228,239,0,17,111,10,0,88,149,75,255,215,235,239,0,167,159,24,255,47,151,108,255,107,209,188,0,233,231,99,254,28,202,148,255,174,35,138,255,110,24,68,255,2,69,181,0,107,102,82,0,102,237,7,0,92,36,237,255,221,162,83,1,55,202,6,255,135,234,135,255,24,250,222,0,65,94,168,254,245,248,210,255,167,108,201,254,255,161,111,0,205,8,254,0,136,13,116,0,100,176,132,255,43,215,126,255,177,133,130,255,158,79,148,0,67,224,37,1,12,206,21,255,62,34,110,1,237,104,175,255,80,132,111,255,142,174,72,0,84,229,180,254,105,179,140,0,64,248,15,255,233,138,16,0,245,67,123,254,218,121,212,255,63,95,218,1,213,133,137,255,143,182,82,255,48,28,11,0,244,114,141,1,209,175,76,255,157,181,150,255,186,229,3,255,164,157,111,1,231,189,139,0,119,202,190,255,218,106,64,255,68,235,63,254,96,26,172,255,187,47,11,1,215,18,251,255,81,84,89,0,68,58,128,0,94,113,5,1,92,129,208,255,97,15,83,254,9,28,188,0,239,9,164,0,60,205,152,0,192,163,98,255,184,18,60,0,217,182,139,0,109,59,120,255,4,192,251,0,169,210,240,255,37,172,92,254,148,211,245,255,179,65,52,0,253,13,115,0,185,174,206,1,114,188,149,255,237,90,173,0,43,199,192,255,88,108,113,0,52,35,76,0,66,25,148,255,221,4,7,255,151,241,114,255,190,209,232,0,98,50,199,0,151,150,213,255,18,74,36,1,53,40,7,0,19,135,65,255,26,172,69,0,174,237,85,0,99,95,41,0,3,56,16,0,39,160,177,255,200,106,218,254,185,68,84,255,91,186,61,254,67,143,141,255,13,244,166,255,99,114,198,0,199,110,163,255,193,18,186,0,124,239,246,1,110,68,22,0,2,235,46,1,212,60,107,0,105,42,105,1,14,230,152,0,7,5,131,0,141,104,154,255,213,3,6,0,131,228,162,255,179,100,28,1,231,123,85,255,206,14,223,1,253,96,230,0,38,152,149,1,98,137,122,0,214,205,3,255,226,152,179,255,6,133,137,0,158,69,140,255,113,162,154,255,180,243,172,255,27,189,115,255,143,46,220,255,213,134,225,255,126,29,69,0,188,43,137,1,242,70,9,0,90,204,255,255,231,170,147,0,23,56,19,254,56,125,157,255,48,179,218,255,79,182,253,255,38,212,191,1,41,235,124,0,96,151,28,0,135,148,190,0,205,249,39,254,52,96,136,255,212,44,136,255,67,209,131,255,252,130,23,255,219,128,20,255,198,129,118,0,108,101,11,0,178,5,146,1,62,7,100,255,181,236,94,254,28,26,164,0,76,22,112,255,120,102,79,0,202,192,229,1,200,176,215,0,41,64,244,255,206,184,78,0,167,45,63,1,160,35,0,255,59,12,142,255,204,9,144,255,219,94,229,1,122,27,112,0,189,105,109,255,64,208,74,255,251,127,55,1,2,226,198,0,44,76,209,0,151,152,77,255,210,23,46,1,201,171,69,255,44,211,231,0,190,37,224,255,245,196,62,255,169,181,222,255,34,211,17,0,119,241,197,255,229,35,152,1,21,69,40,255,178,226,161,0,148,179,193,0,219,194,254,1,40,206,51,255,231,92,250,1,67,153,170,0,21,148,241,0,170,69,82,255,121,18,231,255,92,114,3,0,184,62,230,0,225,201,87,255,146,96,162,255,181,242,220,0,173,187,221,1,226,62,170,255,56,126,217,1,117,13,227,255,179,44,239,0,157,141,155,255,144,221,83,0,235,209,208,0,42,17,165,1,251,81,133,0,124,245,201,254,97,211,24,255,83,214,166,0,154,36,9,255,248,47,127,0,90,219,140,255,161,217,38,254,212,147,63,255,66,84,148,1,207,3,1,0,230,134,89,1,127,78,122,255,224,155,1,255,82,136,74,0,178,156,208,255,186,25,49,255,222,3,210,1,229,150,190,255,85,162,52,255,41,84,141,255,73,123,84,254,93,17,150,0,119,19,28,1,32,22,215,255,28,23,204,255,142,241,52,255,228,52,125,0,29,76,207,0,215,167,250,254,175,164,230,0,55,207,105,1,109,187,245,255,161,44,220,1,41,101,128,255,167,16,94,0,93,214,107,255,118,72,0,254,80,61,234,255,121,175,125,0,139,169,251,0,97,39,147,254,250,196,49,255,165,179,110,254,223,70,187,255,22,142,125,1,154,179,138,255,118,176,42,1,10,174,153,0,156,92,102,0,168,13,161,255,143,16,32,0,250,197,180,255,203,163,44,1,87,32,36,0,161,153,20,255,123,252,15,0,25,227,80,0,60,88,142,0,17,22,201,1,154,205,77,255,39,63,47,0,8,122,141,0,128,23,182,254,204,39,19,255,4,112,29,255,23,36,140,255,210,234,116,254,53,50,63,255,121,171,104,255,160,219,94,0,87,82,14,254,231,42,5,0,165,139,127,254,86,78,38,0,130,60,66,254,203,30,45,255,46,196,122,1,249,53,162,255,136,143,103,254,215,210,114,0,231,7,160,254,169,152,42,255,111,45,246,0,142,131,135,255,131,71,204,255,36,226,11,0,0,28,242,255,225,138,213,255,247,46,216,254,245,3,183,0,108,252,74,1,206,26,48,255,205,54,246,255,211,198,36,255,121,35,50,0,52,216,202,255,38,139,129,254,242,73,148,0,67,231,141,255,42,47,204,0,78,116,25,1,4,225,191,255,6,147,228,0,58,88,177,0,122,165,229,255,252,83,201,255,224,167,96,1,177,184,158,255,242,105,179,1,248,198,240,0,133,66,203,1,254,36,47,0,45,24,115,255,119,62,254,0,196,225,186,254,123,141,172,0,26,85,41,255,226,111,183,0,213,231,151,0,4,59,7,255,238,138,148,0,66,147,33,255,31,246,141,255,209,141,116,255,104,112,31,0,88,161,172,0,83,215,230,254,47,111,151,0,45,38,52,1,132,45,204,0,138,128,109,254,233,117,134,255,243,190,173,254,241,236,240,0,82,127,236,254,40,223,161,255,110,182,225,255,123,174,239,0,135,242,145,1,51,209,154,0,150,3,115,254,217,164,252,255,55,156,69,1,84,94,255,255,232,73,45,1,20,19,212,255,96,197,59,254,96,251,33,0,38,199,73,1,64,172,247,255,117,116,56,255,228,17,18,0,62,138,103,1,246,229,164,255,244,118,201,254,86,32,159,255,109,34,137,1,85,211,186,0,10,193,193,254,122,194,177,0,122,238,102,255,162,218,171,0,108,217,161,1,158,170,34,0,176,47,155,1,181,228,11,255,8,156,0,0,16,75,93,0,206,98,255,1,58,154,35,0,12,243,184,254,67,117,66,255,230,229,123,0,201,42,110,0,134,228,178,254,186,108,118,255,58,19,154,255,82,169,62,255,114,143,115,1,239,196,50,255,173,48,193,255,147,2,84,255,150,134,147,254,95,232,73,0,109,227,52,254,191,137,10,0,40,204,30,254,76,52,97,255,164,235,126,0,254,124,188,0,74,182,21,1,121,29,35,255,241,30,7,254,85,218,214,255,7,84,150,254,81,27,117,255,160,159,152,254,66,24,221,255,227,10,60,1,141,135,102,0,208,189,150,1,117,179,92,0,132,22,136,255,120,199,28,0,21,129,79,254,182,9,65,0,218,163,169,0,246,147,198,255,107,38,144,1,78,175,205,255,214,5,250,254,47,88,29,255,164,47,204,255,43,55,6,255,131,134,207,254,116,100,214,0,96,140,75,1,106,220,144,0,195,32,28,1,172,81,5,255,199,179,52,255,37,84,203,0,170,112,174,0,11,4,91,0,69,244,27,1,117,131,92,0,33,152,175,255,140,153,107,255,251,135,43,254,87,138,4,255,198,234,147,254,121,152,84,255,205,101,155,1,157,9,25,0,72,106,17,254,108,153,0,255],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+20480);allocate([189,229,186,0,193,8,176,255,174,149,209,0,238,130,29,0,233,214,126,1,61,226,102,0,57,163,4,1,198,111,51,255,45,79,78,1,115,210,10,255,218,9,25,255,158,139,198,255,211,82,187,254,80,133,83,0,157,129,230,1,243,133,134,255,40,136,16,0,77,107,79,255,183,85,92,1,177,204,202,0,163,71,147,255,152,69,190,0,172,51,188,1,250,210,172,255,211,242,113,1,89,89,26,255,64,66,111,254,116,152,42,0,161,39,27,255,54,80,254,0,106,209,115,1,103,124,97,0,221,230,98,255,31,231,6,0,178,192,120,254,15,217,203,255,124,158,79,0,112,145,247,0,92,250,48,1,163,181,193,255,37,47,142,254,144,189,165,255,46,146,240,0,6,75,128,0,41,157,200,254,87,121,213,0,1,113,236,0,5,45,250,0,144,12,82,0,31,108,231,0,225,239,119,255,167,7,189,255,187,228,132,255,110,189,34,0,94,44,204,1,162,52,197,0,78,188,241,254,57,20,141,0,244,146,47,1,206,100,51,0,125,107,148,254,27,195,77,0,152,253,90,1,7,143,144,255,51,37,31,0,34,119,38,255,7,197,118,0,153,188,211,0,151,20,116,254,245,65,52,255,180,253,110,1,47,177,209,0,161,99,17,255,118,222,202,0,125,179,252,1,123,54,126,255,145,57,191,0,55,186,121,0,10,243,138,0,205,211,229,255,125,156,241,254,148,156,185,255,227,19,188,255,124,41,32,255,31,34,206,254,17,57,83,0,204,22,37,255,42,96,98,0,119,102,184,1,3,190,28,0,110,82,218,255,200,204,192,255,201,145,118,0,117,204,146,0,132,32,98,1,192,194,121,0,106,161,248,1,237,88,124,0,23,212,26,0,205,171,90,255,248,48,216,1,141,37,230,255,124,203,0,254,158,168,30,255,214,248,21,0,112,187,7,255,75,133,239,255,74,227,243,255,250,147,70,0,214,120,162,0,167,9,179,255,22,158,18,0,218,77,209,1,97,109,81,255,244,33,179,255,57,52,57,255,65,172,210,255,249,71,209,255,142,169,238,0,158,189,153,255,174,254,103,254,98,33,14,0,141,76,230,255,113,139,52,255,15,58,212,0,168,215,201,255,248,204,215,1,223,68,160,255,57,154,183,254,47,231,121,0,106,166,137,0,81,136,138,0,165,43,51,0,231,139,61,0,57,95,59,254,118,98,25,255,151,63,236,1,94,190,250,255,169,185,114,1,5,250,58,255,75,105,97,1,215,223,134,0,113,99,163,1,128,62,112,0,99,106,147,0,163,195,10,0,33,205,182,0,214,14,174,255,129,38,231,255,53,182,223,0,98,42,159,255,247,13,40,0,188,210,177,1,6,21,0,255,255,61,148,254,137,45,129,255,89,26,116,254,126,38,114,0,251,50,242,254,121,134,128,255,204,249,167,254,165,235,215,0,202,177,243,0,133,141,62,0,240,130,190,1,110,175,255,0,0,20,146,1,37,210,121,255,7,39,130,0,142,250,84,255,141,200,207,0,9,95,104,255,11,244,174,0,134,232,126,0,167,1,123,254,16,193,149,255,232,233,239,1,213,70,112,255,252,116,160,254,242,222,220,255,205,85,227,0,7,185,58,0,118,247,63,1,116,77,177,255,62,245,200,254,63,18,37,255,107,53,232,254,50,221,211,0,162,219,7,254,2,94,43,0,182,62,182,254,160,78,200,255,135,140,170,0,235,184,228,0,175,53,138,254,80,58,77,255,152,201,2,1,63,196,34,0,5,30,184,0,171,176,154,0,121,59,206,0,38,99,39,0,172,80,77,254,0,134,151,0,186,33,241,254,94,253,223,255,44,114,252,0,108,126,57,255,201,40,13,255,39,229,27,255,39,239,23,1,151,121,51,255,153,150,248,0,10,234,174,255,118,246,4,254,200,245,38,0,69,161,242,1,16,178,150,0,113,56,130,0,171,31,105,0,26,88,108,255,49,42,106,0,251,169,66,0,69,93,149,0,20,57,254,0,164,25,111,0,90,188,90,255,204,4,197,0,40,213,50,1,212,96,132,255,88,138,180,254,228,146,124,255,184,246,247,0,65,117,86,255,253,102,210,254,254,121,36,0,137,115,3,255,60,24,216,0,134,18,29,0,59,226,97,0,176,142,71,0,7,209,161,0,189,84,51,254,155,250,72,0,213,84,235,255,45,222,224,0,238,148,143,255,170,42,53,255,78,167,117,0,186,0,40,255,125,177,103,255,69,225,66,0,227,7,88,1,75,172,6,0,169,45,227,1,16,36,70,255,50,2,9,255,139,193,22,0,143,183,231,254,218,69,50,0,236,56,161,1,213,131,42,0,138,145,44,254,136,229,40,255,49,63,35,255,61,145,245,255,101,192,2,254,232,167,113,0,152,104,38,1,121,185,218,0,121,139,211,254,119,240,35,0,65,189,217,254,187,179,162,255,160,187,230,0,62,248,14,255,60,78,97,0,255,247,163,255,225,59,91,255,107,71,58,255,241,47,33,1,50,117,236,0,219,177,63,254,244,90,179,0,35,194,215,255,189,67,50,255,23,135,129,0,104,189,37,255,185,57,194,0,35,62,231,255,220,248,108,0,12,231,178,0,143,80,91,1,131,93,101,255,144,39,2,1,255,250,178,0,5,17,236,254,139,32,46,0,204,188,38,254,245,115,52,255,191,113,73,254,191,108,69,255,22,69,245,1,23,203,178,0,170,99,170,0,65,248,111,0,37,108,153,255,64,37,69,0,0,88,62,254,89,148,144,255,191,68,224,1,241,39,53,0,41,203,237,255,145,126,194,255,221,42,253,255,25,99,151,0,97,253,223,1,74,115,49,255,6,175,72,255,59,176,203,0,124,183,249,1,228,228,99,0,129,12,207,254,168,192,195,255,204,176,16,254,152,234,171,0,77,37,85,255,33,120,135,255,142,194,227,1,31,214,58,0,213,187,125,255,232,46,60,255,190,116,42,254,151,178,19,255,51,62,237,254,204,236,193,0,194,232,60,0,172,34,157,255,189,16,184,254,103,3,95,255,141,233,36,254,41,25,11,255,21,195,166,0,118,245,45,0,67,213,149,255,159,12,18,255,187,164,227,1,160,25,5,0,12,78,195,1,43,197,225,0,48,142,41,254,196,155,60,255,223,199,18,1,145,136,156,0,252,117,169,254,145,226,238,0,239,23,107,0,109,181,188,255,230,112,49,254,73,170,237,255,231,183,227,255,80,220,20,0,194,107,127,1,127,205,101,0,46,52,197,1,210,171,36,255,88,3,90,255,56,151,141,0,96,187,255,255,42,78,200,0,254,70,70,1,244,125,168,0,204,68,138,1,124,215,70,0,102,66,200,254,17,52,228,0,117,220,143,254,203,248,123,0,56,18,174,255,186,151,164,255,51,232,208,1,160,228,43,255,249,29,25,1,68,190,63,0,103,230,9,106,133,174,103,187,114,243,110,60,58,245,79,165,127,82,14,81,140,104,5,155,171,217,131,31,25,205,224,91,99,117,114,118,101,50,53,53,49,57,120,115,97,108,115,97,50,48,112,111,108,121,49,51,48,53,0,98,108,97,107,101,50,98,0,83,45,62,98,117,102,108,101,110,32,60,61,32,66,76,65,75,69,50,66,95,66,76,79,67,75,66,89,84,69,83,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,47,98,108,97,107,101,50,47,114,101,102,47,98,108,97,107,101,50,98,45,114,101,102,46,99,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,95,95,102,105,110,97,108,0,111,117,116,108,101,110,32,60,61,32,85,73,78,84,56,95,77,65,88,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,47,98,108,97,107,101,50,47,114,101,102,47,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,46,99,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,0,107,101,121,108,101,110,32,60,61,32,85,73,78,84,56,95,77,65,88,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,95,115,97,108,116,95,112,101,114,115,111,110,97,108,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,95,105,110,105,116,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,95,105,110,105,116,95,115,97,108,116,95,112,101,114,115,111,110,97,108,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,95,102,105,110,97,108,0,115,104,97,53,49,50,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,111,108,121,49,51,48,53,0,36,97,114,103,111,110,50,105,0,36,118,61,0,36,109,61,0,44,116,61,0,44,112,61,0,44,100,97,116,97,61,0,36,97,114,103,111,110,50,105,36,118,61,0,36,97,114,103,111,110,50,105,36,0,97,114,103,111,110,50,105,0,46,47,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,0,36,55,36,0,99,117,114,118,101,50,53,53,49,57,0,120,115,97,108,115,97,50,48,112,111,108,121,49,51,48,53,0,115,105,112,104,97,115,104,50,52,0,101,100,50,53,53,49,57,0,237,211,245,92,26,99,18,88,214,156,247,162,222,249,222,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,120,115,97,108,115,97,50,48,0,106,115,0,123,32,114,101,116,117,114,110,32,77,111,100,117,108,101,46,103,101,116,82,97,110,100,111,109,86,97,108,117,101,40,41,59,32,125,0,123,32,105,102,32,40,77,111,100,117,108,101,46,103,101,116,82,97,110,100,111,109,86,97,108,117,101,32,61,61,61,32,117,110,100,101,102,105,110,101,100,41,32,123,32,116,114,121,32,123,32,118,97,114,32,119,105,110,100,111,119,95,32,61,32,34,111,98,106,101,99,116,34,32,61,61,61,32,116,121,112,101,111,102,32,119,105,110,100,111,119,32,63,32,119,105,110,100,111,119,32,58,32,115,101,108,102,44,32,99,114,121,112,116,111,95,32,61,32,116,121,112,101,111,102,32,119,105,110,100,111,119,95,46,99,114,121,112,116,111,32,33,61,61,32,34,117,110,100,101,102,105,110,101,100,34,32,63,32,119,105,110,100,111,119,95,46,99,114,121,112,116,111,32,58,32,119,105,110,100,111,119,95,46,109,115,67,114,121,112,116,111,44,32,114,97,110,100,111,109,86,97,108,117,101,115,83,116,97,110,100,97,114,100,32,61,32,102,117,110,99,116,105,111,110,40,41,32,123,32,118,97,114,32,98,117,102,32,61,32,110,101,119,32,85,105,110,116,51,50,65,114,114,97,121,40,49,41,59,32,99,114,121,112,116,111,95,46,103,101,116,82,97,110,100,111,109,86,97,108,117,101,115,40,98,117,102,41,59,32,114,101,116,117,114,110,32,98,117,102,91,48,93,32,62,62,62,32,48,59,32,125,59,32,114,97,110,100,111,109,86,97,108,117,101,115,83,116,97,110,100,97,114,100,40,41,59,32,77,111,100,117,108,101,46,103,101,116,82,97,110,100,111,109,86,97,108,117,101,32,61,32,114,97,110,100,111,109,86,97,108,117,101,115,83,116,97,110,100,97,114,100,59,32,125,32,99,97,116,99,104,32,40,101,41,32,123,32,116,114,121,32,123,32,118,97,114,32,99,114,121,112,116,111,32,61,32,114,101,113,117,105,114,101,40,39,99,114,121,112,116,111,39,41,44,32,114,97,110,100,111,109,86,97,108,117,101,78,111,100,101,74,83,32,61,32,102,117,110,99,116,105,111,110,40,41,32,123,32,118,97,114,32,98,117,102,32,61,32,99,114,121,112,116,111,46,114,97,110,100,111,109,66,121,116,101,115,40,52,41,59,32,114,101,116,117,114,110,32,40,98,117,102,91,48,93,32,60,60,32,50,52,32,124,32,98,117,102,91,49,93,32,60,60,32,49,54,32,124,32,98,117,102,91,50,93,32,60,60,32,56,32,124,32,98,117,102,91,51,93,41,32,62,62,62,32,48,59,32,125,59,32,114,97,110,100,111,109,86,97,108,117,101,78,111,100,101,74,83,40,41,59,32,77,111,100,117,108,101,46,103,101,116,82,97,110,100,111,109,86,97,108,117,101,32,61,32,114,97,110,100,111,109,86,97,108,117,101,78,111,100,101,74,83,59,32,125,32,99,97,116,99,104,32,40,101,41,32,123,32,116,104,114,111,119,32,39,78,111,32,115,101,99,117,114,101,32,114,97,110,100,111,109,32,110,117,109,98,101,114,32,103,101,110,101,114,97,116,111,114,32,102,111,117,110,100,39,59,32,125,32,125,32,125,32,125,0,98,117,102,95,108,101,110,32,60,61,32,83,73,90,69,95,77,65,88,0,114,97,110,100,111,109,98,121,116,101,115,47,114,97,110,100,111,109,98,121,116,101,115,46,99,0,114,97,110,100,111,109,98,121,116,101,115,0,49,46,48,46,49,49,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+30720);var tempDoublePtr=STATICTOP;STATICTOP+=16;Module["_bitshift64Ashr"]=_bitshift64Ashr;Module["_i64Subtract"]=_i64Subtract;Module["_i64Add"]=_i64Add;Module["_memset"]=_memset;Module["_bitshift64Lshr"]=_bitshift64Lshr;Module["_bitshift64Shl"]=_bitshift64Shl;function _abort(){Module["abort"]()}function ___assert_fail(condition,filename,line,func){ABORT=true;throw"Assertion failed: "+Pointer_stringify(condition)+", at: "+[filename?Pointer_stringify(filename):"unknown filename",line,func?Pointer_stringify(func):"unknown function"]+" at "+stackTrace()}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest);return dest}Module["_memcpy"]=_memcpy;var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],"i8",ALLOC_STATIC);Module["_llvm_cttz_i32"]=_llvm_cttz_i32;Module["___udivmoddi4"]=___udivmoddi4;Module["___udivdi3"]=___udivdi3;Module["___muldsi3"]=___muldsi3;Module["___muldi3"]=___muldi3;function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function _sysconf(name){switch(name){case 30:return PAGE_SIZE;case 85:return totalMemory/PAGE_SIZE;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:return 200809;case 79:return 0;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}___setErrNo(ERRNO_CODES.EINVAL);return-1}Module["_sbrk"]=_sbrk;Module["_memmove"]=_memmove;Module["___uremdi3"]=___uremdi3;DYNAMICTOP_PTR=allocate(1,"i32",ALLOC_STATIC);STACK_BASE=STACKTOP=Runtime.alignMemory(STATICTOP);STACK_MAX=STACK_BASE+TOTAL_STACK;DYNAMIC_BASE=Runtime.alignMemory(STACK_MAX);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;staticSealed=true;Module.asmGlobalArg={"Math":Math,"Int8Array":Int8Array,"Int16Array":Int16Array,"Int32Array":Int32Array,"Uint8Array":Uint8Array,"Uint16Array":Uint16Array,"Uint32Array":Uint32Array,"Float32Array":Float32Array,"Float64Array":Float64Array,"NaN":NaN,"Infinity":Infinity};Module.asmLibraryArg={"abort":abort,"assert":assert,"enlargeMemory":enlargeMemory,"getTotalMemory":getTotalMemory,"abortOnCannotGrowMemory":abortOnCannotGrowMemory,"_emscripten_asm_const_i":_emscripten_asm_const_i,"_sysconf":_sysconf,"_abort":_abort,"___setErrNo":___setErrNo,"_emscripten_memcpy_big":_emscripten_memcpy_big,"_emscripten_asm_const_v":_emscripten_asm_const_v,"___assert_fail":___assert_fail,"STACKTOP":STACKTOP,"STACK_MAX":STACK_MAX,"DYNAMICTOP_PTR":DYNAMICTOP_PTR,"tempDoublePtr":tempDoublePtr,"ABORT":ABORT,"cttz_i8":cttz_i8};// EMSCRIPTEN_START_ASM -var asm=(function(global,env,buffer) { -"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.DYNAMICTOP_PTR|0;var l=env.tempDoublePtr|0;var m=env.ABORT|0;var n=env.cttz_i8|0;var o=0;var p=0;var q=0;var r=0;var s=global.NaN,t=global.Infinity;var u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0;var D=0;var E=global.Math.floor;var F=global.Math.abs;var G=global.Math.sqrt;var H=global.Math.pow;var I=global.Math.cos;var J=global.Math.sin;var K=global.Math.tan;var L=global.Math.acos;var M=global.Math.asin;var N=global.Math.atan;var O=global.Math.atan2;var P=global.Math.exp;var Q=global.Math.log;var R=global.Math.ceil;var S=global.Math.imul;var T=global.Math.min;var U=global.Math.max;var V=global.Math.clz32;var W=env.abort;var X=env.assert;var Y=env.enlargeMemory;var Z=env.getTotalMemory;var _=env.abortOnCannotGrowMemory;var $=env._emscripten_asm_const_i;var aa=env._sysconf;var ba=env._abort;var ca=env.___setErrNo;var da=env._emscripten_memcpy_big;var ea=env._emscripten_asm_const_v;var fa=env.___assert_fail;var ga=0; -// EMSCRIPTEN_START_FUNCS -function ha(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;g=i;h=i=i+63&-64;i=i+720|0;e=0;do{k=b+(e<<3)|0;p=d[k+7>>0]|0;q=Pd(d[k+6>>0]|0|0,0,8)|0;j=D;o=Pd(d[k+5>>0]|0|0,0,16)|0;j=j|D;n=Pd(d[k+4>>0]|0|0,0,24)|0;j=j|D|(d[k+3>>0]|0);m=Pd(d[k+2>>0]|0|0,0,40)|0;j=j|D;l=Pd(d[k+1>>0]|0|0,0,48)|0;j=j|D;k=Pd(d[k>>0]|0|0,0,56)|0;f=h+80+(e<<3)|0;c[f>>2]=q|p|o|n|m|l|k;c[f+4>>2]=j|D;e=e+1|0}while((e|0)!=16);e=16;b=c[h+80>>2]|0;f=c[h+80+4>>2]|0;do{s=h+80+(e+-2<<3)|0;w=c[s>>2]|0;s=c[s+4>>2]|0;r=Rd(w|0,s|0,19)|0;k=D;j=Pd(w|0,s|0,45)|0;k=k|D;u=Rd(w|0,s|0,61)|0;v=D;t=Pd(w|0,s|0,3)|0;v=v|D;s=Rd(w|0,s|0,6)|0;k=v^D^k;v=h+80+(e+-7<<3)|0;w=c[v>>2]|0;v=c[v+4>>2]|0;o=h+80+(e+-15<<3)|0;y=b;b=c[o>>2]|0;x=f;f=c[o+4>>2]|0;o=Rd(b|0,f|0,1)|0;p=D;q=Pd(b|0,f|0,63)|0;p=p|D;l=Rd(b|0,f|0,8)|0;z=D;m=Pd(b|0,f|0,56)|0;z=z|D;n=Rd(b|0,f|0,7)|0;p=z^D^p;v=oe(y|0,x|0,w|0,v|0)|0;k=oe(v|0,D|0,(u|t)^s^(r|j)|0,k|0)|0;p=oe(k|0,D|0,(l|m)^n^(o|q)|0,p|0)|0;q=h+80+(e<<3)|0;c[q>>2]=p;c[q+4>>2]=D;e=e+1|0}while((e|0)!=80);e=h+16|0;b=a;f=e+64|0;do{c[e>>2]=c[b>>2];e=e+4|0;b=b+4|0}while((e|0)<(f|0));G=h+16+56|0;x=c[G>>2]|0;E=c[G+4>>2]|0;w=h+16+32|0;I=c[w>>2]|0;H=c[w+4>>2]|0;e=Rd(I|0,H|0,14)|0;z=D;F=Pd(I|0,H|0,50)|0;z=z|D;l=Rd(I|0,H|0,18)|0;A=D;L=Pd(I|0,H|0,46)|0;A=z^(A|D);z=Rd(I|0,H|0,41)|0;J=D;K=Pd(I|0,H|0,23)|0;J=A^(J|D);A=h+16+40|0;M=c[A>>2]|0;f=c[A+4>>2]|0;k=h+16+48|0;p=c[k>>2]|0;j=c[k+4>>2]|0;r=c[h+80>>2]|0;y=c[h+80+4>>2]|0;E=oe(x|0,E|0,-685199838,1116352408)|0;y=oe(E|0,D|0,r|0,y|0)|0;J=oe(y|0,D|0,(e|F)^(l|L)^(z|K)|0,J|0)|0;J=oe(J|0,D|0,(p^M)&I^p|0,(j^f)&H^j|0)|0;K=D;z=c[h+16>>2]|0;L=c[h+16+4>>2]|0;l=Rd(z|0,L|0,28)|0;F=D;e=Pd(z|0,L|0,36)|0;F=F|D;y=Rd(z|0,L|0,34)|0;r=D;E=Pd(z|0,L|0,30)|0;r=F^(r|D);F=Rd(z|0,L|0,39)|0;x=D;m=Pd(z|0,L|0,25)|0;C=h+16+8|0;o=c[C>>2]|0;q=c[C+4>>2]|0;B=h+16+16|0;b=c[B>>2]|0;s=c[B+4>>2]|0;x=oe((b|o)&z|b&o|0,(s|q)&L|s&q|0,(l|e)^(y|E)^(F|m)|0,r^(x|D)|0)|0;r=D;m=h+16+24|0;F=oe(c[m>>2]|0,c[m+4>>2]|0,J|0,K|0)|0;E=D;c[m>>2]=F;c[m+4>>2]=E;K=oe(x|0,r|0,J|0,K|0)|0;J=D;c[G>>2]=K;c[G+4>>2]=J;r=Rd(F|0,E|0,14)|0;x=D;y=Pd(F|0,E|0,50)|0;x=x|D;e=Rd(F|0,E|0,18)|0;l=D;u=Pd(F|0,E|0,46)|0;l=x^(l|D);x=Rd(F|0,E|0,41)|0;t=D;v=Pd(F|0,E|0,23)|0;t=l^(t|D);l=c[h+80+8>>2]|0;n=c[h+80+8+4>>2]|0;j=oe(p|0,j|0,602891725,1899447441)|0;t=oe(j|0,D|0,(r|y)^(e|u)^(x|v)|0,t|0)|0;n=oe(t|0,D|0,l|0,n|0)|0;H=oe(n|0,D|0,(M^I)&F^M|0,(f^H)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;u=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;e=oe((o|z)&K|o&z|0,(q|L)&J|q&L|0,(n|t)^(v|u)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[B>>2]=s;c[B+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[k>>2]=I;c[k+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;y=Pd(s|0,b|0,50)|0;e=e|D;l=Rd(s|0,b|0,18)|0;u=D;v=Pd(s|0,b|0,46)|0;u=e^(u|D);e=Rd(s|0,b|0,41)|0;t=D;n=Pd(s|0,b|0,23)|0;t=u^(t|D);u=c[w>>2]|0;r=c[w+4>>2]|0;j=c[h+80+16>>2]|0;p=c[h+80+16+4>>2]|0;f=oe(M|0,f|0,-330482897,-1245643825)|0;t=oe(f|0,D|0,(x|y)^(l|v)^(e|n)|0,t|0)|0;p=oe(t|0,D|0,j|0,p|0)|0;p=oe(p|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;j=D;t=Rd(I|0,H|0,28)|0;n=D;e=Pd(I|0,H|0,36)|0;n=n|D;v=Rd(I|0,H|0,34)|0;l=D;y=Pd(I|0,H|0,30)|0;l=n^(l|D);n=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;x=oe((z|K)&I|z&K|0,(L|J)&H|L&J|0,(t|e)^(v|y)^(n|f)|0,l^(x|D)|0)|0;l=D;q=oe(o|0,q|0,p|0,j|0)|0;o=D;c[C>>2]=q;c[C+4>>2]=o;j=oe(x|0,l|0,p|0,j|0)|0;p=D;c[A>>2]=j;c[A+4>>2]=p;l=Rd(q|0,o|0,14)|0;x=D;f=Pd(q|0,o|0,50)|0;x=x|D;n=Rd(q|0,o|0,18)|0;y=D;v=Pd(q|0,o|0,46)|0;y=x^(y|D);x=Rd(q|0,o|0,41)|0;e=D;t=Pd(q|0,o|0,23)|0;e=y^(e|D);y=c[h+80+24>>2]|0;J=c[h+80+24+4>>2]|0;r=oe(u|0,r|0,-2121671748,-373957723)|0;e=oe(r|0,D|0,(l|f)^(n|v)^(x|t)|0,e|0)|0;J=oe(e|0,D|0,y|0,J|0)|0;J=oe(J|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;y=D;e=Rd(j|0,p|0,28)|0;t=D;x=Pd(j|0,p|0,36)|0;t=t|D;v=Rd(j|0,p|0,34)|0;n=D;f=Pd(j|0,p|0,30)|0;n=t^(n|D);t=Rd(j|0,p|0,39)|0;l=D;r=Pd(j|0,p|0,25)|0;u=c[G>>2]|0;K=c[G+4>>2]|0;l=oe((u|I)&j|u&I|0,(K|H)&p|K&H|0,(e|x)^(v|f)^(t|r)|0,n^(l|D)|0)|0;n=D;L=oe(z|0,L|0,J|0,y|0)|0;z=D;c[h+16>>2]=L;c[h+16+4>>2]=z;y=oe(l|0,n|0,J|0,y|0)|0;J=D;c[w>>2]=y;c[w+4>>2]=J;n=Rd(L|0,z|0,14)|0;l=D;r=Pd(L|0,z|0,50)|0;l=l|D;t=Rd(L|0,z|0,18)|0;f=D;v=Pd(L|0,z|0,46)|0;f=l^(f|D);l=Rd(L|0,z|0,41)|0;x=D;e=Pd(L|0,z|0,23)|0;x=f^(x|D);f=c[h+80+32>>2]|0;H=c[h+80+32+4>>2]|0;E=oe(F|0,E|0,-213338824,961987163)|0;x=oe(E|0,D|0,(n|r)^(t|v)^(l|e)|0,x|0)|0;H=oe(x|0,D|0,f|0,H|0)|0;H=oe(H|0,D|0,(s^q)&L^s|0,(b^o)&z^b|0)|0;f=D;x=Rd(y|0,J|0,28)|0;e=D;l=Pd(y|0,J|0,36)|0;e=e|D;v=Rd(y|0,J|0,34)|0;t=D;r=Pd(y|0,J|0,30)|0;t=e^(t|D);e=Rd(y|0,J|0,39)|0;n=D;E=Pd(y|0,J|0,25)|0;F=c[k>>2]|0;I=c[k+4>>2]|0;n=oe((F|j)&y|F&j|0,(I|p)&J|I&p|0,(x|l)^(v|r)^(e|E)|0,t^(n|D)|0)|0;t=D;K=oe(u|0,K|0,H|0,f|0)|0;u=D;c[G>>2]=K;c[G+4>>2]=u;f=oe(n|0,t|0,H|0,f|0)|0;H=D;c[m>>2]=f;c[m+4>>2]=H;t=Rd(K|0,u|0,14)|0;n=D;E=Pd(K|0,u|0,50)|0;n=n|D;e=Rd(K|0,u|0,18)|0;r=D;v=Pd(K|0,u|0,46)|0;r=n^(r|D);n=Rd(K|0,u|0,41)|0;l=D;x=Pd(K|0,u|0,23)|0;l=r^(l|D);r=c[h+80+40>>2]|0;p=c[h+80+40+4>>2]|0;b=oe(s|0,b|0,-1241133031,1508970993)|0;l=oe(b|0,D|0,(t|E)^(e|v)^(n|x)|0,l|0)|0;p=oe(l|0,D|0,r|0,p|0)|0;p=oe(p|0,D|0,(q^L)&K^q|0,(o^z)&u^o|0)|0;r=D;l=Rd(f|0,H|0,28)|0;x=D;n=Pd(f|0,H|0,36)|0;x=x|D;v=Rd(f|0,H|0,34)|0;e=D;E=Pd(f|0,H|0,30)|0;e=x^(e|D);x=Rd(f|0,H|0,39)|0;t=D;b=Pd(f|0,H|0,25)|0;s=c[A>>2]|0;j=c[A+4>>2]|0;t=oe((s|y)&f|s&y|0,(j|J)&H|j&J|0,(l|n)^(v|E)^(x|b)|0,e^(t|D)|0)|0;e=D;I=oe(F|0,I|0,p|0,r|0)|0;F=D;c[k>>2]=I;c[k+4>>2]=F;r=oe(t|0,e|0,p|0,r|0)|0;p=D;c[B>>2]=r;c[B+4>>2]=p;e=Rd(I|0,F|0,14)|0;t=D;b=Pd(I|0,F|0,50)|0;t=t|D;x=Rd(I|0,F|0,18)|0;E=D;v=Pd(I|0,F|0,46)|0;E=t^(E|D);t=Rd(I|0,F|0,41)|0;n=D;l=Pd(I|0,F|0,23)|0;n=E^(n|D);E=c[h+80+48>>2]|0;J=c[h+80+48+4>>2]|0;o=oe(q|0,o|0,-1357295717,-1841331548)|0;n=oe(o|0,D|0,(e|b)^(x|v)^(t|l)|0,n|0)|0;J=oe(n|0,D|0,E|0,J|0)|0;J=oe(J|0,D|0,(L^K)&I^L|0,(z^u)&F^z|0)|0;E=D;n=Rd(r|0,p|0,28)|0;l=D;t=Pd(r|0,p|0,36)|0;l=l|D;v=Rd(r|0,p|0,34)|0;x=D;b=Pd(r|0,p|0,30)|0;x=l^(x|D);l=Rd(r|0,p|0,39)|0;e=D;o=Pd(r|0,p|0,25)|0;q=c[w>>2]|0;y=c[w+4>>2]|0;e=oe((q|f)&r|q&f|0,(y|H)&p|y&H|0,(n|t)^(v|b)^(l|o)|0,x^(e|D)|0)|0;x=D;j=oe(s|0,j|0,J|0,E|0)|0;s=D;c[A>>2]=j;c[A+4>>2]=s;E=oe(e|0,x|0,J|0,E|0)|0;J=D;c[C>>2]=E;c[C+4>>2]=J;x=Rd(j|0,s|0,14)|0;e=D;o=Pd(j|0,s|0,50)|0;e=e|D;l=Rd(j|0,s|0,18)|0;b=D;v=Pd(j|0,s|0,46)|0;b=e^(b|D);e=Rd(j|0,s|0,41)|0;t=D;n=Pd(j|0,s|0,23)|0;t=b^(t|D);b=c[h+80+56>>2]|0;H=c[h+80+56+4>>2]|0;z=oe(L|0,z|0,-630357736,-1424204075)|0;t=oe(z|0,D|0,(x|o)^(l|v)^(e|n)|0,t|0)|0;H=oe(t|0,D|0,b|0,H|0)|0;H=oe(H|0,D|0,(K^I)&j^K|0,(u^F)&s^u|0)|0;b=D;t=Rd(E|0,J|0,28)|0;n=D;e=Pd(E|0,J|0,36)|0;n=n|D;v=Rd(E|0,J|0,34)|0;l=D;o=Pd(E|0,J|0,30)|0;l=n^(l|D);n=Rd(E|0,J|0,39)|0;x=D;z=Pd(E|0,J|0,25)|0;L=c[m>>2]|0;f=c[m+4>>2]|0;x=oe((L|r)&E|L&r|0,(f|p)&J|f&p|0,(t|e)^(v|o)^(n|z)|0,l^(x|D)|0)|0;l=D;y=oe(q|0,y|0,H|0,b|0)|0;q=D;c[w>>2]=y;c[w+4>>2]=q;b=oe(x|0,l|0,H|0,b|0)|0;H=D;c[h+16>>2]=b;c[h+16+4>>2]=H;l=Rd(y|0,q|0,14)|0;x=D;z=Pd(y|0,q|0,50)|0;x=x|D;n=Rd(y|0,q|0,18)|0;o=D;v=Pd(y|0,q|0,46)|0;o=x^(o|D);x=Rd(y|0,q|0,41)|0;e=D;t=Pd(y|0,q|0,23)|0;e=o^(e|D);o=c[h+80+64>>2]|0;p=c[h+80+64+4>>2]|0;u=oe(K|0,u|0,-1560083902,-670586216)|0;e=oe(u|0,D|0,(l|z)^(n|v)^(x|t)|0,e|0)|0;p=oe(e|0,D|0,o|0,p|0)|0;p=oe(p|0,D|0,(I^j)&y^I|0,(F^s)&q^F|0)|0;o=D;e=Rd(b|0,H|0,28)|0;t=D;x=Pd(b|0,H|0,36)|0;t=t|D;v=Rd(b|0,H|0,34)|0;n=D;z=Pd(b|0,H|0,30)|0;n=t^(n|D);t=Rd(b|0,H|0,39)|0;l=D;u=Pd(b|0,H|0,25)|0;K=c[B>>2]|0;r=c[B+4>>2]|0;l=oe((K|E)&b|K&E|0,(r|J)&H|r&J|0,(e|x)^(v|z)^(t|u)|0,n^(l|D)|0)|0;n=D;f=oe(L|0,f|0,p|0,o|0)|0;L=D;c[m>>2]=f;c[m+4>>2]=L;o=oe(l|0,n|0,p|0,o|0)|0;p=D;c[G>>2]=o;c[G+4>>2]=p;n=Rd(f|0,L|0,14)|0;l=D;u=Pd(f|0,L|0,50)|0;l=l|D;t=Rd(f|0,L|0,18)|0;z=D;v=Pd(f|0,L|0,46)|0;z=l^(z|D);l=Rd(f|0,L|0,41)|0;x=D;e=Pd(f|0,L|0,23)|0;x=z^(x|D);z=c[h+80+72>>2]|0;J=c[h+80+72+4>>2]|0;F=oe(I|0,F|0,1164996542,310598401)|0;x=oe(F|0,D|0,(n|u)^(t|v)^(l|e)|0,x|0)|0;J=oe(x|0,D|0,z|0,J|0)|0;J=oe(J|0,D|0,(j^y)&f^j|0,(s^q)&L^s|0)|0;z=D;x=Rd(o|0,p|0,28)|0;e=D;l=Pd(o|0,p|0,36)|0;e=e|D;v=Rd(o|0,p|0,34)|0;t=D;u=Pd(o|0,p|0,30)|0;t=e^(t|D);e=Rd(o|0,p|0,39)|0;n=D;F=Pd(o|0,p|0,25)|0;I=c[C>>2]|0;E=c[C+4>>2]|0;n=oe((I|b)&o|I&b|0,(E|H)&p|E&H|0,(x|l)^(v|u)^(e|F)|0,t^(n|D)|0)|0;t=D;r=oe(K|0,r|0,J|0,z|0)|0;K=D;c[B>>2]=r;c[B+4>>2]=K;z=oe(n|0,t|0,J|0,z|0)|0;J=D;c[k>>2]=z;c[k+4>>2]=J;t=Rd(r|0,K|0,14)|0;n=D;F=Pd(r|0,K|0,50)|0;n=n|D;e=Rd(r|0,K|0,18)|0;u=D;v=Pd(r|0,K|0,46)|0;u=n^(u|D);n=Rd(r|0,K|0,41)|0;l=D;x=Pd(r|0,K|0,23)|0;l=u^(l|D);u=c[h+80+80>>2]|0;H=c[h+80+80+4>>2]|0;s=oe(j|0,s|0,1323610764,607225278)|0;l=oe(s|0,D|0,(t|F)^(e|v)^(n|x)|0,l|0)|0;H=oe(l|0,D|0,u|0,H|0)|0;H=oe(H|0,D|0,(y^f)&r^y|0,(q^L)&K^q|0)|0;u=D;l=Rd(z|0,J|0,28)|0;x=D;n=Pd(z|0,J|0,36)|0;x=x|D;v=Rd(z|0,J|0,34)|0;e=D;F=Pd(z|0,J|0,30)|0;e=x^(e|D);x=Rd(z|0,J|0,39)|0;t=D;s=Pd(z|0,J|0,25)|0;j=c[h+16>>2]|0;b=c[h+16+4>>2]|0;t=oe((j|o)&z|j&o|0,(b|p)&J|b&p|0,(l|n)^(v|F)^(x|s)|0,e^(t|D)|0)|0;e=D;E=oe(I|0,E|0,H|0,u|0)|0;I=D;c[C>>2]=E;c[C+4>>2]=I;u=oe(t|0,e|0,H|0,u|0)|0;H=D;c[A>>2]=u;c[A+4>>2]=H;e=Rd(E|0,I|0,14)|0;t=D;s=Pd(E|0,I|0,50)|0;t=t|D;x=Rd(E|0,I|0,18)|0;F=D;v=Pd(E|0,I|0,46)|0;F=t^(F|D);t=Rd(E|0,I|0,41)|0;n=D;l=Pd(E|0,I|0,23)|0;n=F^(n|D);F=c[h+80+88>>2]|0;p=c[h+80+88+4>>2]|0;q=oe(y|0,q|0,-704662302,1426881987)|0;n=oe(q|0,D|0,(e|s)^(x|v)^(t|l)|0,n|0)|0;p=oe(n|0,D|0,F|0,p|0)|0;p=oe(p|0,D|0,(f^r)&E^f|0,(L^K)&I^L|0)|0;F=D;n=Rd(u|0,H|0,28)|0;l=D;t=Pd(u|0,H|0,36)|0;l=l|D;v=Rd(u|0,H|0,34)|0;x=D;s=Pd(u|0,H|0,30)|0;x=l^(x|D);l=Rd(u|0,H|0,39)|0;e=D;q=Pd(u|0,H|0,25)|0;y=c[G>>2]|0;o=c[G+4>>2]|0;e=oe((y|z)&u|y&z|0,(o|J)&H|o&J|0,(n|t)^(v|s)^(l|q)|0,x^(e|D)|0)|0;x=D;b=oe(j|0,b|0,p|0,F|0)|0;j=D;c[h+16>>2]=b;c[h+16+4>>2]=j;F=oe(e|0,x|0,p|0,F|0)|0;p=D;c[w>>2]=F;c[w+4>>2]=p;x=Rd(b|0,j|0,14)|0;e=D;q=Pd(b|0,j|0,50)|0;e=e|D;l=Rd(b|0,j|0,18)|0;s=D;v=Pd(b|0,j|0,46)|0;s=e^(s|D);e=Rd(b|0,j|0,41)|0;t=D;n=Pd(b|0,j|0,23)|0;t=s^(t|D);s=c[h+80+96>>2]|0;J=c[h+80+96+4>>2]|0;L=oe(f|0,L|0,-226784913,1925078388)|0;t=oe(L|0,D|0,(x|q)^(l|v)^(e|n)|0,t|0)|0;J=oe(t|0,D|0,s|0,J|0)|0;J=oe(J|0,D|0,(r^E)&b^r|0,(K^I)&j^K|0)|0;s=D;t=Rd(F|0,p|0,28)|0;n=D;e=Pd(F|0,p|0,36)|0;n=n|D;v=Rd(F|0,p|0,34)|0;l=D;q=Pd(F|0,p|0,30)|0;l=n^(l|D);n=Rd(F|0,p|0,39)|0;x=D;L=Pd(F|0,p|0,25)|0;f=c[k>>2]|0;z=c[k+4>>2]|0;x=oe((f|u)&F|f&u|0,(z|H)&p|z&H|0,(t|e)^(v|q)^(n|L)|0,l^(x|D)|0)|0;l=D;o=oe(y|0,o|0,J|0,s|0)|0;y=D;c[G>>2]=o;c[G+4>>2]=y;s=oe(x|0,l|0,J|0,s|0)|0;J=D;c[m>>2]=s;c[m+4>>2]=J;l=Rd(o|0,y|0,14)|0;x=D;L=Pd(o|0,y|0,50)|0;x=x|D;n=Rd(o|0,y|0,18)|0;q=D;v=Pd(o|0,y|0,46)|0;q=x^(q|D);x=Rd(o|0,y|0,41)|0;e=D;t=Pd(o|0,y|0,23)|0;e=q^(e|D);q=c[h+80+104>>2]|0;H=c[h+80+104+4>>2]|0;K=oe(r|0,K|0,991336113,-2132889090)|0;e=oe(K|0,D|0,(l|L)^(n|v)^(x|t)|0,e|0)|0;H=oe(e|0,D|0,q|0,H|0)|0;H=oe(H|0,D|0,(E^b)&o^E|0,(I^j)&y^I|0)|0;q=D;e=Rd(s|0,J|0,28)|0;t=D;x=Pd(s|0,J|0,36)|0;t=t|D;v=Rd(s|0,J|0,34)|0;n=D;L=Pd(s|0,J|0,30)|0;n=t^(n|D);t=Rd(s|0,J|0,39)|0;l=D;K=Pd(s|0,J|0,25)|0;r=c[A>>2]|0;u=c[A+4>>2]|0;l=oe((r|F)&s|r&F|0,(u|p)&J|u&p|0,(e|x)^(v|L)^(t|K)|0,n^(l|D)|0)|0;n=D;z=oe(f|0,z|0,H|0,q|0)|0;f=D;c[k>>2]=z;c[k+4>>2]=f;q=oe(l|0,n|0,H|0,q|0)|0;H=D;c[B>>2]=q;c[B+4>>2]=H;n=Rd(z|0,f|0,14)|0;l=D;K=Pd(z|0,f|0,50)|0;l=l|D;t=Rd(z|0,f|0,18)|0;L=D;v=Pd(z|0,f|0,46)|0;L=l^(L|D);l=Rd(z|0,f|0,41)|0;x=D;e=Pd(z|0,f|0,23)|0;x=L^(x|D);L=c[h+80+112>>2]|0;p=c[h+80+112+4>>2]|0;I=oe(E|0,I|0,633803317,-1680079193)|0;x=oe(I|0,D|0,(n|K)^(t|v)^(l|e)|0,x|0)|0;p=oe(x|0,D|0,L|0,p|0)|0;p=oe(p|0,D|0,(b^o)&z^b|0,(j^y)&f^j|0)|0;L=D;x=Rd(q|0,H|0,28)|0;e=D;l=Pd(q|0,H|0,36)|0;e=e|D;v=Rd(q|0,H|0,34)|0;t=D;K=Pd(q|0,H|0,30)|0;t=e^(t|D);e=Rd(q|0,H|0,39)|0;n=D;I=Pd(q|0,H|0,25)|0;E=c[w>>2]|0;F=c[w+4>>2]|0;n=oe((E|s)&q|E&s|0,(F|J)&H|F&J|0,(x|l)^(v|K)^(e|I)|0,t^(n|D)|0)|0;t=D;u=oe(r|0,u|0,p|0,L|0)|0;r=D;c[A>>2]=u;c[A+4>>2]=r;L=oe(n|0,t|0,p|0,L|0)|0;p=D;c[C>>2]=L;c[C+4>>2]=p;t=Rd(u|0,r|0,14)|0;n=D;I=Pd(u|0,r|0,50)|0;n=n|D;e=Rd(u|0,r|0,18)|0;K=D;v=Pd(u|0,r|0,46)|0;K=n^(K|D);n=Rd(u|0,r|0,41)|0;l=D;x=Pd(u|0,r|0,23)|0;l=K^(l|D);K=c[h+80+120>>2]|0;J=c[h+80+120+4>>2]|0;j=oe(b|0,j|0,-815192428,-1046744716)|0;l=oe(j|0,D|0,(t|I)^(e|v)^(n|x)|0,l|0)|0;J=oe(l|0,D|0,K|0,J|0)|0;J=oe(J|0,D|0,(o^z)&u^o|0,(y^f)&r^y|0)|0;K=D;l=Rd(L|0,p|0,28)|0;x=D;n=Pd(L|0,p|0,36)|0;x=x|D;v=Rd(L|0,p|0,34)|0;e=D;I=Pd(L|0,p|0,30)|0;e=x^(e|D);x=Rd(L|0,p|0,39)|0;t=D;j=Pd(L|0,p|0,25)|0;b=c[m>>2]|0;s=c[m+4>>2]|0;t=oe((b|q)&L|b&q|0,(s|H)&p|s&H|0,(l|n)^(v|I)^(x|j)|0,e^(t|D)|0)|0;e=D;F=oe(E|0,F|0,J|0,K|0)|0;E=D;c[w>>2]=F;c[w+4>>2]=E;K=oe(t|0,e|0,J|0,K|0)|0;J=D;c[h+16>>2]=K;c[h+16+4>>2]=J;e=Rd(F|0,E|0,14)|0;t=D;j=Pd(F|0,E|0,50)|0;t=t|D;x=Rd(F|0,E|0,18)|0;I=D;v=Pd(F|0,E|0,46)|0;I=t^(I|D);t=Rd(F|0,E|0,41)|0;n=D;l=Pd(F|0,E|0,23)|0;n=I^(n|D);I=c[h+80+128>>2]|0;H=c[h+80+128+4>>2]|0;y=oe(o|0,y|0,-1628353838,-459576895)|0;n=oe(y|0,D|0,(e|j)^(x|v)^(t|l)|0,n|0)|0;H=oe(n|0,D|0,I|0,H|0)|0;H=oe(H|0,D|0,(z^u)&F^z|0,(f^r)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;j=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;o=c[B>>2]|0;q=c[B+4>>2]|0;e=oe((o|L)&K|o&L|0,(q|p)&J|q&p|0,(n|t)^(v|j)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[m>>2]=s;c[m+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[G>>2]=I;c[G+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;y=Pd(s|0,b|0,50)|0;e=e|D;l=Rd(s|0,b|0,18)|0;j=D;v=Pd(s|0,b|0,46)|0;j=e^(j|D);e=Rd(s|0,b|0,41)|0;t=D;n=Pd(s|0,b|0,23)|0;t=j^(t|D);j=c[h+80+136>>2]|0;p=c[h+80+136+4>>2]|0;f=oe(z|0,f|0,944711139,-272742522)|0;t=oe(f|0,D|0,(x|y)^(l|v)^(e|n)|0,t|0)|0;p=oe(t|0,D|0,j|0,p|0)|0;p=oe(p|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;j=D;t=Rd(I|0,H|0,28)|0;n=D;e=Pd(I|0,H|0,36)|0;n=n|D;v=Rd(I|0,H|0,34)|0;l=D;y=Pd(I|0,H|0,30)|0;l=n^(l|D);n=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;z=c[C>>2]|0;L=c[C+4>>2]|0;x=oe((z|K)&I|z&K|0,(L|J)&H|L&J|0,(t|e)^(v|y)^(n|f)|0,l^(x|D)|0)|0;l=D;q=oe(o|0,q|0,p|0,j|0)|0;o=D;c[B>>2]=q;c[B+4>>2]=o;j=oe(x|0,l|0,p|0,j|0)|0;p=D;c[k>>2]=j;c[k+4>>2]=p;l=Rd(q|0,o|0,14)|0;x=D;f=Pd(q|0,o|0,50)|0;x=x|D;n=Rd(q|0,o|0,18)|0;y=D;v=Pd(q|0,o|0,46)|0;y=x^(y|D);x=Rd(q|0,o|0,41)|0;e=D;t=Pd(q|0,o|0,23)|0;e=y^(e|D);y=c[h+80+144>>2]|0;J=c[h+80+144+4>>2]|0;r=oe(u|0,r|0,-1953704523,264347078)|0;e=oe(r|0,D|0,(l|f)^(n|v)^(x|t)|0,e|0)|0;J=oe(e|0,D|0,y|0,J|0)|0;J=oe(J|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;y=D;e=Rd(j|0,p|0,28)|0;t=D;x=Pd(j|0,p|0,36)|0;t=t|D;v=Rd(j|0,p|0,34)|0;n=D;f=Pd(j|0,p|0,30)|0;n=t^(n|D);t=Rd(j|0,p|0,39)|0;l=D;r=Pd(j|0,p|0,25)|0;u=c[h+16>>2]|0;K=c[h+16+4>>2]|0;l=oe((u|I)&j|u&I|0,(K|H)&p|K&H|0,(e|x)^(v|f)^(t|r)|0,n^(l|D)|0)|0;n=D;L=oe(z|0,L|0,J|0,y|0)|0;z=D;c[C>>2]=L;c[C+4>>2]=z;y=oe(l|0,n|0,J|0,y|0)|0;J=D;c[A>>2]=y;c[A+4>>2]=J;n=Rd(L|0,z|0,14)|0;l=D;r=Pd(L|0,z|0,50)|0;l=l|D;t=Rd(L|0,z|0,18)|0;f=D;v=Pd(L|0,z|0,46)|0;f=l^(f|D);l=Rd(L|0,z|0,41)|0;x=D;e=Pd(L|0,z|0,23)|0;x=f^(x|D);f=c[h+80+152>>2]|0;H=c[h+80+152+4>>2]|0;E=oe(F|0,E|0,2007800933,604807628)|0;x=oe(E|0,D|0,(n|r)^(t|v)^(l|e)|0,x|0)|0;H=oe(x|0,D|0,f|0,H|0)|0;H=oe(H|0,D|0,(s^q)&L^s|0,(b^o)&z^b|0)|0;f=D;x=Rd(y|0,J|0,28)|0;e=D;l=Pd(y|0,J|0,36)|0;e=e|D;v=Rd(y|0,J|0,34)|0;t=D;r=Pd(y|0,J|0,30)|0;t=e^(t|D);e=Rd(y|0,J|0,39)|0;n=D;E=Pd(y|0,J|0,25)|0;F=c[G>>2]|0;I=c[G+4>>2]|0;n=oe((F|j)&y|F&j|0,(I|p)&J|I&p|0,(x|l)^(v|r)^(e|E)|0,t^(n|D)|0)|0;t=D;K=oe(u|0,K|0,H|0,f|0)|0;u=D;c[h+16>>2]=K;c[h+16+4>>2]=u;f=oe(n|0,t|0,H|0,f|0)|0;H=D;c[w>>2]=f;c[w+4>>2]=H;t=Rd(K|0,u|0,14)|0;n=D;E=Pd(K|0,u|0,50)|0;n=n|D;e=Rd(K|0,u|0,18)|0;r=D;v=Pd(K|0,u|0,46)|0;r=n^(r|D);n=Rd(K|0,u|0,41)|0;l=D;x=Pd(K|0,u|0,23)|0;l=r^(l|D);r=c[h+80+160>>2]|0;p=c[h+80+160+4>>2]|0;b=oe(s|0,b|0,1495990901,770255983)|0;l=oe(b|0,D|0,(t|E)^(e|v)^(n|x)|0,l|0)|0;p=oe(l|0,D|0,r|0,p|0)|0;p=oe(p|0,D|0,(q^L)&K^q|0,(o^z)&u^o|0)|0;r=D;l=Rd(f|0,H|0,28)|0;x=D;n=Pd(f|0,H|0,36)|0;x=x|D;v=Rd(f|0,H|0,34)|0;e=D;E=Pd(f|0,H|0,30)|0;e=x^(e|D);x=Rd(f|0,H|0,39)|0;t=D;b=Pd(f|0,H|0,25)|0;s=c[k>>2]|0;j=c[k+4>>2]|0;t=oe((s|y)&f|s&y|0,(j|J)&H|j&J|0,(l|n)^(v|E)^(x|b)|0,e^(t|D)|0)|0;e=D;I=oe(F|0,I|0,p|0,r|0)|0;F=D;c[G>>2]=I;c[G+4>>2]=F;r=oe(t|0,e|0,p|0,r|0)|0;p=D;c[m>>2]=r;c[m+4>>2]=p;e=Rd(I|0,F|0,14)|0;t=D;b=Pd(I|0,F|0,50)|0;t=t|D;x=Rd(I|0,F|0,18)|0;E=D;v=Pd(I|0,F|0,46)|0;E=t^(E|D);t=Rd(I|0,F|0,41)|0;n=D;l=Pd(I|0,F|0,23)|0;n=E^(n|D);E=c[h+80+168>>2]|0;J=c[h+80+168+4>>2]|0;o=oe(q|0,o|0,1856431235,1249150122)|0;n=oe(o|0,D|0,(e|b)^(x|v)^(t|l)|0,n|0)|0;J=oe(n|0,D|0,E|0,J|0)|0;J=oe(J|0,D|0,(L^K)&I^L|0,(z^u)&F^z|0)|0;E=D;n=Rd(r|0,p|0,28)|0;l=D;t=Pd(r|0,p|0,36)|0;l=l|D;v=Rd(r|0,p|0,34)|0;x=D;b=Pd(r|0,p|0,30)|0;x=l^(x|D);l=Rd(r|0,p|0,39)|0;e=D;o=Pd(r|0,p|0,25)|0;q=c[A>>2]|0;y=c[A+4>>2]|0;e=oe((q|f)&r|q&f|0,(y|H)&p|y&H|0,(n|t)^(v|b)^(l|o)|0,x^(e|D)|0)|0;x=D;j=oe(s|0,j|0,J|0,E|0)|0;s=D;c[k>>2]=j;c[k+4>>2]=s;E=oe(e|0,x|0,J|0,E|0)|0;J=D;c[B>>2]=E;c[B+4>>2]=J;x=Rd(j|0,s|0,14)|0;e=D;o=Pd(j|0,s|0,50)|0;e=e|D;l=Rd(j|0,s|0,18)|0;b=D;v=Pd(j|0,s|0,46)|0;b=e^(b|D);e=Rd(j|0,s|0,41)|0;t=D;n=Pd(j|0,s|0,23)|0;t=b^(t|D);b=c[h+80+176>>2]|0;H=c[h+80+176+4>>2]|0;z=oe(L|0,z|0,-1119749164,1555081692)|0;t=oe(z|0,D|0,(x|o)^(l|v)^(e|n)|0,t|0)|0;H=oe(t|0,D|0,b|0,H|0)|0;H=oe(H|0,D|0,(K^I)&j^K|0,(u^F)&s^u|0)|0;b=D;t=Rd(E|0,J|0,28)|0;n=D;e=Pd(E|0,J|0,36)|0;n=n|D;v=Rd(E|0,J|0,34)|0;l=D;o=Pd(E|0,J|0,30)|0;l=n^(l|D);n=Rd(E|0,J|0,39)|0;x=D;z=Pd(E|0,J|0,25)|0;L=c[w>>2]|0;f=c[w+4>>2]|0;x=oe((L|r)&E|L&r|0,(f|p)&J|f&p|0,(t|e)^(v|o)^(n|z)|0,l^(x|D)|0)|0;l=D;y=oe(q|0,y|0,H|0,b|0)|0;q=D;c[A>>2]=y;c[A+4>>2]=q;b=oe(x|0,l|0,H|0,b|0)|0;H=D;c[C>>2]=b;c[C+4>>2]=H;l=Rd(y|0,q|0,14)|0;x=D;z=Pd(y|0,q|0,50)|0;x=x|D;n=Rd(y|0,q|0,18)|0;o=D;v=Pd(y|0,q|0,46)|0;o=x^(o|D);x=Rd(y|0,q|0,41)|0;e=D;t=Pd(y|0,q|0,23)|0;e=o^(e|D);o=c[h+80+184>>2]|0;p=c[h+80+184+4>>2]|0;u=oe(K|0,u|0,-2096016459,1996064986)|0;e=oe(u|0,D|0,(l|z)^(n|v)^(x|t)|0,e|0)|0;p=oe(e|0,D|0,o|0,p|0)|0;p=oe(p|0,D|0,(I^j)&y^I|0,(F^s)&q^F|0)|0;o=D;e=Rd(b|0,H|0,28)|0;t=D;x=Pd(b|0,H|0,36)|0;t=t|D;v=Rd(b|0,H|0,34)|0;n=D;z=Pd(b|0,H|0,30)|0;n=t^(n|D);t=Rd(b|0,H|0,39)|0;l=D;u=Pd(b|0,H|0,25)|0;K=c[m>>2]|0;r=c[m+4>>2]|0;l=oe((K|E)&b|K&E|0,(r|J)&H|r&J|0,(e|x)^(v|z)^(t|u)|0,n^(l|D)|0)|0;n=D;f=oe(L|0,f|0,p|0,o|0)|0;L=D;c[w>>2]=f;c[w+4>>2]=L;o=oe(l|0,n|0,p|0,o|0)|0;p=D;c[h+16>>2]=o;c[h+16+4>>2]=p;n=Rd(f|0,L|0,14)|0;l=D;u=Pd(f|0,L|0,50)|0;l=l|D;t=Rd(f|0,L|0,18)|0;z=D;v=Pd(f|0,L|0,46)|0;z=l^(z|D);l=Rd(f|0,L|0,41)|0;x=D;e=Pd(f|0,L|0,23)|0;x=z^(x|D);z=c[h+80+192>>2]|0;J=c[h+80+192+4>>2]|0;F=oe(I|0,F|0,-295247957,-1740746414)|0;x=oe(F|0,D|0,(n|u)^(t|v)^(l|e)|0,x|0)|0;J=oe(x|0,D|0,z|0,J|0)|0;J=oe(J|0,D|0,(j^y)&f^j|0,(s^q)&L^s|0)|0;z=D;x=Rd(o|0,p|0,28)|0;e=D;l=Pd(o|0,p|0,36)|0;e=e|D;v=Rd(o|0,p|0,34)|0;t=D;u=Pd(o|0,p|0,30)|0;t=e^(t|D);e=Rd(o|0,p|0,39)|0;n=D;F=Pd(o|0,p|0,25)|0;I=c[B>>2]|0;E=c[B+4>>2]|0;n=oe((I|b)&o|I&b|0,(E|H)&p|E&H|0,(x|l)^(v|u)^(e|F)|0,t^(n|D)|0)|0;t=D;r=oe(K|0,r|0,J|0,z|0)|0;K=D;c[m>>2]=r;c[m+4>>2]=K;z=oe(n|0,t|0,J|0,z|0)|0;J=D;c[G>>2]=z;c[G+4>>2]=J;t=Rd(r|0,K|0,14)|0;n=D;F=Pd(r|0,K|0,50)|0;n=n|D;e=Rd(r|0,K|0,18)|0;u=D;v=Pd(r|0,K|0,46)|0;u=n^(u|D);n=Rd(r|0,K|0,41)|0;l=D;x=Pd(r|0,K|0,23)|0;l=u^(l|D);u=c[h+80+200>>2]|0;H=c[h+80+200+4>>2]|0;s=oe(j|0,s|0,766784016,-1473132947)|0;l=oe(s|0,D|0,(t|F)^(e|v)^(n|x)|0,l|0)|0;H=oe(l|0,D|0,u|0,H|0)|0;H=oe(H|0,D|0,(y^f)&r^y|0,(q^L)&K^q|0)|0;u=D;l=Rd(z|0,J|0,28)|0;x=D;n=Pd(z|0,J|0,36)|0;x=x|D;v=Rd(z|0,J|0,34)|0;e=D;F=Pd(z|0,J|0,30)|0;e=x^(e|D);x=Rd(z|0,J|0,39)|0;t=D;s=Pd(z|0,J|0,25)|0;j=c[C>>2]|0;b=c[C+4>>2]|0;t=oe((j|o)&z|j&o|0,(b|p)&J|b&p|0,(l|n)^(v|F)^(x|s)|0,e^(t|D)|0)|0;e=D;E=oe(I|0,E|0,H|0,u|0)|0;I=D;c[B>>2]=E;c[B+4>>2]=I;u=oe(t|0,e|0,H|0,u|0)|0;H=D;c[k>>2]=u;c[k+4>>2]=H;e=Rd(E|0,I|0,14)|0;t=D;s=Pd(E|0,I|0,50)|0;t=t|D;x=Rd(E|0,I|0,18)|0;F=D;v=Pd(E|0,I|0,46)|0;F=t^(F|D);t=Rd(E|0,I|0,41)|0;n=D;l=Pd(E|0,I|0,23)|0;n=F^(n|D);F=c[h+80+208>>2]|0;p=c[h+80+208+4>>2]|0;q=oe(y|0,q|0,-1728372417,-1341970488)|0;n=oe(q|0,D|0,(e|s)^(x|v)^(t|l)|0,n|0)|0;p=oe(n|0,D|0,F|0,p|0)|0;p=oe(p|0,D|0,(f^r)&E^f|0,(L^K)&I^L|0)|0;F=D;n=Rd(u|0,H|0,28)|0;l=D;t=Pd(u|0,H|0,36)|0;l=l|D;v=Rd(u|0,H|0,34)|0;x=D;s=Pd(u|0,H|0,30)|0;x=l^(x|D);l=Rd(u|0,H|0,39)|0;e=D;q=Pd(u|0,H|0,25)|0;y=c[h+16>>2]|0;o=c[h+16+4>>2]|0;e=oe((y|z)&u|y&z|0,(o|J)&H|o&J|0,(n|t)^(v|s)^(l|q)|0,x^(e|D)|0)|0;x=D;b=oe(j|0,b|0,p|0,F|0)|0;j=D;c[C>>2]=b;c[C+4>>2]=j;F=oe(e|0,x|0,p|0,F|0)|0;p=D;c[A>>2]=F;c[A+4>>2]=p;x=Rd(b|0,j|0,14)|0;e=D;q=Pd(b|0,j|0,50)|0;e=e|D;l=Rd(b|0,j|0,18)|0;s=D;v=Pd(b|0,j|0,46)|0;s=e^(s|D);e=Rd(b|0,j|0,41)|0;t=D;n=Pd(b|0,j|0,23)|0;t=s^(t|D);s=c[h+80+216>>2]|0;J=c[h+80+216+4>>2]|0;L=oe(f|0,L|0,-1091629340,-1084653625)|0;t=oe(L|0,D|0,(x|q)^(l|v)^(e|n)|0,t|0)|0;J=oe(t|0,D|0,s|0,J|0)|0;J=oe(J|0,D|0,(r^E)&b^r|0,(K^I)&j^K|0)|0;s=D;t=Rd(F|0,p|0,28)|0;n=D;e=Pd(F|0,p|0,36)|0;n=n|D;v=Rd(F|0,p|0,34)|0;l=D;q=Pd(F|0,p|0,30)|0;l=n^(l|D);n=Rd(F|0,p|0,39)|0;x=D;L=Pd(F|0,p|0,25)|0;f=c[G>>2]|0;z=c[G+4>>2]|0;x=oe((f|u)&F|f&u|0,(z|H)&p|z&H|0,(t|e)^(v|q)^(n|L)|0,l^(x|D)|0)|0;l=D;o=oe(y|0,o|0,J|0,s|0)|0;y=D;c[h+16>>2]=o;c[h+16+4>>2]=y;s=oe(x|0,l|0,J|0,s|0)|0;J=D;c[w>>2]=s;c[w+4>>2]=J;l=Rd(o|0,y|0,14)|0;x=D;L=Pd(o|0,y|0,50)|0;x=x|D;n=Rd(o|0,y|0,18)|0;q=D;v=Pd(o|0,y|0,46)|0;q=x^(q|D);x=Rd(o|0,y|0,41)|0;e=D;t=Pd(o|0,y|0,23)|0;e=q^(e|D);q=c[h+80+224>>2]|0;H=c[h+80+224+4>>2]|0;K=oe(r|0,K|0,1034457026,-958395405)|0;e=oe(K|0,D|0,(l|L)^(n|v)^(x|t)|0,e|0)|0;H=oe(e|0,D|0,q|0,H|0)|0;H=oe(H|0,D|0,(E^b)&o^E|0,(I^j)&y^I|0)|0;q=D;e=Rd(s|0,J|0,28)|0;t=D;x=Pd(s|0,J|0,36)|0;t=t|D;v=Rd(s|0,J|0,34)|0;n=D;L=Pd(s|0,J|0,30)|0;n=t^(n|D);t=Rd(s|0,J|0,39)|0;l=D;K=Pd(s|0,J|0,25)|0;r=c[k>>2]|0;u=c[k+4>>2]|0;l=oe((r|F)&s|r&F|0,(u|p)&J|u&p|0,(e|x)^(v|L)^(t|K)|0,n^(l|D)|0)|0;n=D;z=oe(f|0,z|0,H|0,q|0)|0;f=D;c[G>>2]=z;c[G+4>>2]=f;q=oe(l|0,n|0,H|0,q|0)|0;H=D;c[m>>2]=q;c[m+4>>2]=H;n=Rd(z|0,f|0,14)|0;l=D;K=Pd(z|0,f|0,50)|0;l=l|D;t=Rd(z|0,f|0,18)|0;L=D;v=Pd(z|0,f|0,46)|0;L=l^(L|D);l=Rd(z|0,f|0,41)|0;x=D;e=Pd(z|0,f|0,23)|0;x=L^(x|D);L=c[h+80+232>>2]|0;p=c[h+80+232+4>>2]|0;I=oe(E|0,I|0,-1828018395,-710438585)|0;x=oe(I|0,D|0,(n|K)^(t|v)^(l|e)|0,x|0)|0;p=oe(x|0,D|0,L|0,p|0)|0;p=oe(p|0,D|0,(b^o)&z^b|0,(j^y)&f^j|0)|0;L=D;x=Rd(q|0,H|0,28)|0;e=D;l=Pd(q|0,H|0,36)|0;e=e|D;v=Rd(q|0,H|0,34)|0;t=D;K=Pd(q|0,H|0,30)|0;t=e^(t|D);e=Rd(q|0,H|0,39)|0;n=D;I=Pd(q|0,H|0,25)|0;E=c[A>>2]|0;F=c[A+4>>2]|0;n=oe((E|s)&q|E&s|0,(F|J)&H|F&J|0,(x|l)^(v|K)^(e|I)|0,t^(n|D)|0)|0;t=D;u=oe(r|0,u|0,p|0,L|0)|0;r=D;c[k>>2]=u;c[k+4>>2]=r;L=oe(n|0,t|0,p|0,L|0)|0;p=D;c[B>>2]=L;c[B+4>>2]=p;t=Rd(u|0,r|0,14)|0;n=D;I=Pd(u|0,r|0,50)|0;n=n|D;e=Rd(u|0,r|0,18)|0;K=D;v=Pd(u|0,r|0,46)|0;K=n^(K|D);n=Rd(u|0,r|0,41)|0;l=D;x=Pd(u|0,r|0,23)|0;l=K^(l|D);K=c[h+80+240>>2]|0;J=c[h+80+240+4>>2]|0;j=oe(b|0,j|0,-536640913,113926993)|0;l=oe(j|0,D|0,(t|I)^(e|v)^(n|x)|0,l|0)|0;J=oe(l|0,D|0,K|0,J|0)|0;J=oe(J|0,D|0,(o^z)&u^o|0,(y^f)&r^y|0)|0;K=D;l=Rd(L|0,p|0,28)|0;x=D;n=Pd(L|0,p|0,36)|0;x=x|D;v=Rd(L|0,p|0,34)|0;e=D;I=Pd(L|0,p|0,30)|0;e=x^(e|D);x=Rd(L|0,p|0,39)|0;t=D;j=Pd(L|0,p|0,25)|0;b=c[w>>2]|0;s=c[w+4>>2]|0;t=oe((b|q)&L|b&q|0,(s|H)&p|s&H|0,(l|n)^(v|I)^(x|j)|0,e^(t|D)|0)|0;e=D;F=oe(E|0,F|0,J|0,K|0)|0;E=D;c[A>>2]=F;c[A+4>>2]=E;K=oe(t|0,e|0,J|0,K|0)|0;J=D;c[C>>2]=K;c[C+4>>2]=J;e=Rd(F|0,E|0,14)|0;t=D;j=Pd(F|0,E|0,50)|0;t=t|D;x=Rd(F|0,E|0,18)|0;I=D;v=Pd(F|0,E|0,46)|0;I=t^(I|D);t=Rd(F|0,E|0,41)|0;n=D;l=Pd(F|0,E|0,23)|0;n=I^(n|D);I=c[h+80+248>>2]|0;H=c[h+80+248+4>>2]|0;y=oe(o|0,y|0,168717936,338241895)|0;n=oe(y|0,D|0,(e|j)^(x|v)^(t|l)|0,n|0)|0;H=oe(n|0,D|0,I|0,H|0)|0;H=oe(H|0,D|0,(z^u)&F^z|0,(f^r)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;j=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;o=c[m>>2]|0;q=c[m+4>>2]|0;e=oe((o|L)&K|o&L|0,(q|p)&J|q&p|0,(n|t)^(v|j)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[w>>2]=s;c[w+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[h+16>>2]=I;c[h+16+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;y=Pd(s|0,b|0,50)|0;e=e|D;l=Rd(s|0,b|0,18)|0;j=D;v=Pd(s|0,b|0,46)|0;j=e^(j|D);e=Rd(s|0,b|0,41)|0;t=D;n=Pd(s|0,b|0,23)|0;t=j^(t|D);j=c[h+80+256>>2]|0;p=c[h+80+256+4>>2]|0;f=oe(z|0,f|0,1188179964,666307205)|0;t=oe(f|0,D|0,(x|y)^(l|v)^(e|n)|0,t|0)|0;p=oe(t|0,D|0,j|0,p|0)|0;p=oe(p|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;j=D;t=Rd(I|0,H|0,28)|0;n=D;e=Pd(I|0,H|0,36)|0;n=n|D;v=Rd(I|0,H|0,34)|0;l=D;y=Pd(I|0,H|0,30)|0;l=n^(l|D);n=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;z=c[B>>2]|0;L=c[B+4>>2]|0;x=oe((z|K)&I|z&K|0,(L|J)&H|L&J|0,(t|e)^(v|y)^(n|f)|0,l^(x|D)|0)|0;l=D;q=oe(o|0,q|0,p|0,j|0)|0;o=D;c[m>>2]=q;c[m+4>>2]=o;j=oe(x|0,l|0,p|0,j|0)|0;p=D;c[G>>2]=j;c[G+4>>2]=p;l=Rd(q|0,o|0,14)|0;x=D;f=Pd(q|0,o|0,50)|0;x=x|D;n=Rd(q|0,o|0,18)|0;y=D;v=Pd(q|0,o|0,46)|0;y=x^(y|D);x=Rd(q|0,o|0,41)|0;e=D;t=Pd(q|0,o|0,23)|0;e=y^(e|D);y=c[h+80+264>>2]|0;J=c[h+80+264+4>>2]|0;r=oe(u|0,r|0,1546045734,773529912)|0;e=oe(r|0,D|0,(l|f)^(n|v)^(x|t)|0,e|0)|0;J=oe(e|0,D|0,y|0,J|0)|0;J=oe(J|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;y=D;e=Rd(j|0,p|0,28)|0;t=D;x=Pd(j|0,p|0,36)|0;t=t|D;v=Rd(j|0,p|0,34)|0;n=D;f=Pd(j|0,p|0,30)|0;n=t^(n|D);t=Rd(j|0,p|0,39)|0;l=D;r=Pd(j|0,p|0,25)|0;u=c[C>>2]|0;K=c[C+4>>2]|0;l=oe((u|I)&j|u&I|0,(K|H)&p|K&H|0,(e|x)^(v|f)^(t|r)|0,n^(l|D)|0)|0;n=D;L=oe(z|0,L|0,J|0,y|0)|0;z=D;c[B>>2]=L;c[B+4>>2]=z;y=oe(l|0,n|0,J|0,y|0)|0;J=D;c[k>>2]=y;c[k+4>>2]=J;n=Rd(L|0,z|0,14)|0;l=D;r=Pd(L|0,z|0,50)|0;l=l|D;t=Rd(L|0,z|0,18)|0;f=D;v=Pd(L|0,z|0,46)|0;f=l^(f|D);l=Rd(L|0,z|0,41)|0;x=D;e=Pd(L|0,z|0,23)|0;x=f^(x|D);f=c[h+80+272>>2]|0;H=c[h+80+272+4>>2]|0;E=oe(F|0,E|0,1522805485,1294757372)|0;x=oe(E|0,D|0,(n|r)^(t|v)^(l|e)|0,x|0)|0;H=oe(x|0,D|0,f|0,H|0)|0;H=oe(H|0,D|0,(s^q)&L^s|0,(b^o)&z^b|0)|0;f=D;x=Rd(y|0,J|0,28)|0;e=D;l=Pd(y|0,J|0,36)|0;e=e|D;v=Rd(y|0,J|0,34)|0;t=D;r=Pd(y|0,J|0,30)|0;t=e^(t|D);e=Rd(y|0,J|0,39)|0;n=D;E=Pd(y|0,J|0,25)|0;F=c[h+16>>2]|0;I=c[h+16+4>>2]|0;n=oe((F|j)&y|F&j|0,(I|p)&J|I&p|0,(x|l)^(v|r)^(e|E)|0,t^(n|D)|0)|0;t=D;K=oe(u|0,K|0,H|0,f|0)|0;u=D;c[C>>2]=K;c[C+4>>2]=u;f=oe(n|0,t|0,H|0,f|0)|0;H=D;c[A>>2]=f;c[A+4>>2]=H;t=Rd(K|0,u|0,14)|0;n=D;E=Pd(K|0,u|0,50)|0;n=n|D;e=Rd(K|0,u|0,18)|0;r=D;v=Pd(K|0,u|0,46)|0;r=n^(r|D);n=Rd(K|0,u|0,41)|0;l=D;x=Pd(K|0,u|0,23)|0;l=r^(l|D);r=c[h+80+280>>2]|0;p=c[h+80+280+4>>2]|0;b=oe(s|0,b|0,-1651133473,1396182291)|0;l=oe(b|0,D|0,(t|E)^(e|v)^(n|x)|0,l|0)|0;p=oe(l|0,D|0,r|0,p|0)|0;p=oe(p|0,D|0,(q^L)&K^q|0,(o^z)&u^o|0)|0;r=D;l=Rd(f|0,H|0,28)|0;x=D;n=Pd(f|0,H|0,36)|0;x=x|D;v=Rd(f|0,H|0,34)|0;e=D;E=Pd(f|0,H|0,30)|0;e=x^(e|D);x=Rd(f|0,H|0,39)|0;t=D;b=Pd(f|0,H|0,25)|0;s=c[G>>2]|0;j=c[G+4>>2]|0;t=oe((s|y)&f|s&y|0,(j|J)&H|j&J|0,(l|n)^(v|E)^(x|b)|0,e^(t|D)|0)|0;e=D;I=oe(F|0,I|0,p|0,r|0)|0;F=D;c[h+16>>2]=I;c[h+16+4>>2]=F;r=oe(t|0,e|0,p|0,r|0)|0;p=D;c[w>>2]=r;c[w+4>>2]=p;e=Rd(I|0,F|0,14)|0;t=D;b=Pd(I|0,F|0,50)|0;t=t|D;x=Rd(I|0,F|0,18)|0;E=D;v=Pd(I|0,F|0,46)|0;E=t^(E|D);t=Rd(I|0,F|0,41)|0;n=D;l=Pd(I|0,F|0,23)|0;n=E^(n|D);E=c[h+80+288>>2]|0;J=c[h+80+288+4>>2]|0;o=oe(q|0,o|0,-1951439906,1695183700)|0;n=oe(o|0,D|0,(e|b)^(x|v)^(t|l)|0,n|0)|0;J=oe(n|0,D|0,E|0,J|0)|0;J=oe(J|0,D|0,(L^K)&I^L|0,(z^u)&F^z|0)|0;E=D;n=Rd(r|0,p|0,28)|0;l=D;t=Pd(r|0,p|0,36)|0;l=l|D;v=Rd(r|0,p|0,34)|0;x=D;b=Pd(r|0,p|0,30)|0;x=l^(x|D);l=Rd(r|0,p|0,39)|0;e=D;o=Pd(r|0,p|0,25)|0;q=c[k>>2]|0;y=c[k+4>>2]|0;e=oe((q|f)&r|q&f|0,(y|H)&p|y&H|0,(n|t)^(v|b)^(l|o)|0,x^(e|D)|0)|0;x=D;j=oe(s|0,j|0,J|0,E|0)|0;s=D;c[G>>2]=j;c[G+4>>2]=s;E=oe(e|0,x|0,J|0,E|0)|0;J=D;c[m>>2]=E;c[m+4>>2]=J;x=Rd(j|0,s|0,14)|0;e=D;o=Pd(j|0,s|0,50)|0;e=e|D;l=Rd(j|0,s|0,18)|0;b=D;v=Pd(j|0,s|0,46)|0;b=e^(b|D);e=Rd(j|0,s|0,41)|0;t=D;n=Pd(j|0,s|0,23)|0;t=b^(t|D);b=c[h+80+296>>2]|0;H=c[h+80+296+4>>2]|0;z=oe(L|0,z|0,1014477480,1986661051)|0;t=oe(z|0,D|0,(x|o)^(l|v)^(e|n)|0,t|0)|0;H=oe(t|0,D|0,b|0,H|0)|0;H=oe(H|0,D|0,(K^I)&j^K|0,(u^F)&s^u|0)|0;b=D;t=Rd(E|0,J|0,28)|0;n=D;e=Pd(E|0,J|0,36)|0;n=n|D;v=Rd(E|0,J|0,34)|0;l=D;o=Pd(E|0,J|0,30)|0;l=n^(l|D);n=Rd(E|0,J|0,39)|0;x=D;z=Pd(E|0,J|0,25)|0;L=c[A>>2]|0;f=c[A+4>>2]|0;x=oe((L|r)&E|L&r|0,(f|p)&J|f&p|0,(t|e)^(v|o)^(n|z)|0,l^(x|D)|0)|0;l=D;y=oe(q|0,y|0,H|0,b|0)|0;q=D;c[k>>2]=y;c[k+4>>2]=q;b=oe(x|0,l|0,H|0,b|0)|0;H=D;c[B>>2]=b;c[B+4>>2]=H;l=Rd(y|0,q|0,14)|0;x=D;z=Pd(y|0,q|0,50)|0;x=x|D;n=Rd(y|0,q|0,18)|0;o=D;v=Pd(y|0,q|0,46)|0;o=x^(o|D);x=Rd(y|0,q|0,41)|0;e=D;t=Pd(y|0,q|0,23)|0;e=o^(e|D);o=c[h+80+304>>2]|0;p=c[h+80+304+4>>2]|0;u=oe(K|0,u|0,1206759142,-2117940946)|0;e=oe(u|0,D|0,(l|z)^(n|v)^(x|t)|0,e|0)|0;p=oe(e|0,D|0,o|0,p|0)|0;p=oe(p|0,D|0,(I^j)&y^I|0,(F^s)&q^F|0)|0;o=D;e=Rd(b|0,H|0,28)|0;t=D;x=Pd(b|0,H|0,36)|0;t=t|D;v=Rd(b|0,H|0,34)|0;n=D;z=Pd(b|0,H|0,30)|0;n=t^(n|D);t=Rd(b|0,H|0,39)|0;l=D;u=Pd(b|0,H|0,25)|0;K=c[w>>2]|0;r=c[w+4>>2]|0;l=oe((K|E)&b|K&E|0,(r|J)&H|r&J|0,(e|x)^(v|z)^(t|u)|0,n^(l|D)|0)|0;n=D;f=oe(L|0,f|0,p|0,o|0)|0;L=D;c[A>>2]=f;c[A+4>>2]=L;o=oe(l|0,n|0,p|0,o|0)|0;p=D;c[C>>2]=o;c[C+4>>2]=p;n=Rd(f|0,L|0,14)|0;l=D;u=Pd(f|0,L|0,50)|0;l=l|D;t=Rd(f|0,L|0,18)|0;z=D;v=Pd(f|0,L|0,46)|0;z=l^(z|D);l=Rd(f|0,L|0,41)|0;x=D;e=Pd(f|0,L|0,23)|0;x=z^(x|D);z=c[h+80+312>>2]|0;J=c[h+80+312+4>>2]|0;F=oe(I|0,F|0,344077627,-1838011259)|0;x=oe(F|0,D|0,(n|u)^(t|v)^(l|e)|0,x|0)|0;J=oe(x|0,D|0,z|0,J|0)|0;J=oe(J|0,D|0,(j^y)&f^j|0,(s^q)&L^s|0)|0;z=D;x=Rd(o|0,p|0,28)|0;e=D;l=Pd(o|0,p|0,36)|0;e=e|D;v=Rd(o|0,p|0,34)|0;t=D;u=Pd(o|0,p|0,30)|0;t=e^(t|D);e=Rd(o|0,p|0,39)|0;n=D;F=Pd(o|0,p|0,25)|0;I=c[m>>2]|0;E=c[m+4>>2]|0;n=oe((I|b)&o|I&b|0,(E|H)&p|E&H|0,(x|l)^(v|u)^(e|F)|0,t^(n|D)|0)|0;t=D;r=oe(K|0,r|0,J|0,z|0)|0;K=D;c[w>>2]=r;c[w+4>>2]=K;z=oe(n|0,t|0,J|0,z|0)|0;J=D;c[h+16>>2]=z;c[h+16+4>>2]=J;t=Rd(r|0,K|0,14)|0;n=D;F=Pd(r|0,K|0,50)|0;n=n|D;e=Rd(r|0,K|0,18)|0;u=D;v=Pd(r|0,K|0,46)|0;u=n^(u|D);n=Rd(r|0,K|0,41)|0;l=D;x=Pd(r|0,K|0,23)|0;l=u^(l|D);u=c[h+80+320>>2]|0;H=c[h+80+320+4>>2]|0;s=oe(j|0,s|0,1290863460,-1564481375)|0;l=oe(s|0,D|0,(t|F)^(e|v)^(n|x)|0,l|0)|0;H=oe(l|0,D|0,u|0,H|0)|0;H=oe(H|0,D|0,(y^f)&r^y|0,(q^L)&K^q|0)|0;u=D;l=Rd(z|0,J|0,28)|0;x=D;n=Pd(z|0,J|0,36)|0;x=x|D;v=Rd(z|0,J|0,34)|0;e=D;F=Pd(z|0,J|0,30)|0;e=x^(e|D);x=Rd(z|0,J|0,39)|0;t=D;s=Pd(z|0,J|0,25)|0;j=c[B>>2]|0;b=c[B+4>>2]|0;t=oe((j|o)&z|j&o|0,(b|p)&J|b&p|0,(l|n)^(v|F)^(x|s)|0,e^(t|D)|0)|0;e=D;E=oe(I|0,E|0,H|0,u|0)|0;I=D;c[m>>2]=E;c[m+4>>2]=I;u=oe(t|0,e|0,H|0,u|0)|0;H=D;c[G>>2]=u;c[G+4>>2]=H;e=Rd(E|0,I|0,14)|0;t=D;s=Pd(E|0,I|0,50)|0;t=t|D;x=Rd(E|0,I|0,18)|0;F=D;v=Pd(E|0,I|0,46)|0;F=t^(F|D);t=Rd(E|0,I|0,41)|0;n=D;l=Pd(E|0,I|0,23)|0;n=F^(n|D);F=c[h+80+328>>2]|0;p=c[h+80+328+4>>2]|0;q=oe(y|0,q|0,-1136513023,-1474664885)|0;n=oe(q|0,D|0,(e|s)^(x|v)^(t|l)|0,n|0)|0;p=oe(n|0,D|0,F|0,p|0)|0;p=oe(p|0,D|0,(f^r)&E^f|0,(L^K)&I^L|0)|0;F=D;n=Rd(u|0,H|0,28)|0;l=D;t=Pd(u|0,H|0,36)|0;l=l|D;v=Rd(u|0,H|0,34)|0;x=D;s=Pd(u|0,H|0,30)|0;x=l^(x|D);l=Rd(u|0,H|0,39)|0;e=D;q=Pd(u|0,H|0,25)|0;y=c[C>>2]|0;o=c[C+4>>2]|0;e=oe((y|z)&u|y&z|0,(o|J)&H|o&J|0,(n|t)^(v|s)^(l|q)|0,x^(e|D)|0)|0;x=D;b=oe(j|0,b|0,p|0,F|0)|0;j=D;c[B>>2]=b;c[B+4>>2]=j;F=oe(e|0,x|0,p|0,F|0)|0;p=D;c[k>>2]=F;c[k+4>>2]=p;x=Rd(b|0,j|0,14)|0;e=D;q=Pd(b|0,j|0,50)|0;e=e|D;l=Rd(b|0,j|0,18)|0;s=D;v=Pd(b|0,j|0,46)|0;s=e^(s|D);e=Rd(b|0,j|0,41)|0;t=D;n=Pd(b|0,j|0,23)|0;t=s^(t|D);s=c[h+80+336>>2]|0;J=c[h+80+336+4>>2]|0;L=oe(f|0,L|0,-789014639,-1035236496)|0;t=oe(L|0,D|0,(x|q)^(l|v)^(e|n)|0,t|0)|0;J=oe(t|0,D|0,s|0,J|0)|0;J=oe(J|0,D|0,(r^E)&b^r|0,(K^I)&j^K|0)|0;s=D;t=Rd(F|0,p|0,28)|0;n=D;e=Pd(F|0,p|0,36)|0;n=n|D;v=Rd(F|0,p|0,34)|0;l=D;q=Pd(F|0,p|0,30)|0;l=n^(l|D);n=Rd(F|0,p|0,39)|0;x=D;L=Pd(F|0,p|0,25)|0;f=c[h+16>>2]|0;z=c[h+16+4>>2]|0;x=oe((f|u)&F|f&u|0,(z|H)&p|z&H|0,(t|e)^(v|q)^(n|L)|0,l^(x|D)|0)|0;l=D;o=oe(y|0,o|0,J|0,s|0)|0;y=D;c[C>>2]=o;c[C+4>>2]=y;s=oe(x|0,l|0,J|0,s|0)|0;J=D;c[A>>2]=s;c[A+4>>2]=J;l=Rd(o|0,y|0,14)|0;x=D;L=Pd(o|0,y|0,50)|0;x=x|D;n=Rd(o|0,y|0,18)|0;q=D;v=Pd(o|0,y|0,46)|0;q=x^(q|D);x=Rd(o|0,y|0,41)|0;e=D;t=Pd(o|0,y|0,23)|0;e=q^(e|D);q=c[h+80+344>>2]|0;H=c[h+80+344+4>>2]|0;K=oe(r|0,K|0,106217008,-949202525)|0;e=oe(K|0,D|0,(l|L)^(n|v)^(x|t)|0,e|0)|0;H=oe(e|0,D|0,q|0,H|0)|0;H=oe(H|0,D|0,(E^b)&o^E|0,(I^j)&y^I|0)|0;q=D;e=Rd(s|0,J|0,28)|0;t=D;x=Pd(s|0,J|0,36)|0;t=t|D;v=Rd(s|0,J|0,34)|0;n=D;L=Pd(s|0,J|0,30)|0;n=t^(n|D);t=Rd(s|0,J|0,39)|0;l=D;K=Pd(s|0,J|0,25)|0;r=c[G>>2]|0;u=c[G+4>>2]|0;l=oe((r|F)&s|r&F|0,(u|p)&J|u&p|0,(e|x)^(v|L)^(t|K)|0,n^(l|D)|0)|0;n=D;z=oe(f|0,z|0,H|0,q|0)|0;f=D;c[h+16>>2]=z;c[h+16+4>>2]=f;q=oe(l|0,n|0,H|0,q|0)|0;H=D;c[w>>2]=q;c[w+4>>2]=H;n=Rd(z|0,f|0,14)|0;l=D;K=Pd(z|0,f|0,50)|0;l=l|D;t=Rd(z|0,f|0,18)|0;L=D;v=Pd(z|0,f|0,46)|0;L=l^(L|D);l=Rd(z|0,f|0,41)|0;x=D;e=Pd(z|0,f|0,23)|0;x=L^(x|D);L=c[h+80+352>>2]|0;p=c[h+80+352+4>>2]|0;I=oe(E|0,I|0,-688958952,-778901479)|0;x=oe(I|0,D|0,(n|K)^(t|v)^(l|e)|0,x|0)|0;p=oe(x|0,D|0,L|0,p|0)|0;p=oe(p|0,D|0,(b^o)&z^b|0,(j^y)&f^j|0)|0;L=D;x=Rd(q|0,H|0,28)|0;e=D;l=Pd(q|0,H|0,36)|0;e=e|D;v=Rd(q|0,H|0,34)|0;t=D;K=Pd(q|0,H|0,30)|0;t=e^(t|D);e=Rd(q|0,H|0,39)|0;n=D;I=Pd(q|0,H|0,25)|0;E=c[k>>2]|0;F=c[k+4>>2]|0;n=oe((E|s)&q|E&s|0,(F|J)&H|F&J|0,(x|l)^(v|K)^(e|I)|0,t^(n|D)|0)|0;t=D;u=oe(r|0,u|0,p|0,L|0)|0;r=D;c[G>>2]=u;c[G+4>>2]=r;L=oe(n|0,t|0,p|0,L|0)|0;p=D;c[m>>2]=L;c[m+4>>2]=p;t=Rd(u|0,r|0,14)|0;n=D;I=Pd(u|0,r|0,50)|0;n=n|D;e=Rd(u|0,r|0,18)|0;K=D;v=Pd(u|0,r|0,46)|0;K=n^(K|D);n=Rd(u|0,r|0,41)|0;l=D;x=Pd(u|0,r|0,23)|0;l=K^(l|D);K=c[h+80+360>>2]|0;J=c[h+80+360+4>>2]|0;j=oe(b|0,j|0,1432725776,-694614492)|0;l=oe(j|0,D|0,(t|I)^(e|v)^(n|x)|0,l|0)|0;J=oe(l|0,D|0,K|0,J|0)|0;J=oe(J|0,D|0,(o^z)&u^o|0,(y^f)&r^y|0)|0;K=D;l=Rd(L|0,p|0,28)|0;x=D;n=Pd(L|0,p|0,36)|0;x=x|D;v=Rd(L|0,p|0,34)|0;e=D;I=Pd(L|0,p|0,30)|0;e=x^(e|D);x=Rd(L|0,p|0,39)|0;t=D;j=Pd(L|0,p|0,25)|0;b=c[A>>2]|0;s=c[A+4>>2]|0;t=oe((b|q)&L|b&q|0,(s|H)&p|s&H|0,(l|n)^(v|I)^(x|j)|0,e^(t|D)|0)|0;e=D;F=oe(E|0,F|0,J|0,K|0)|0;E=D;c[k>>2]=F;c[k+4>>2]=E;K=oe(t|0,e|0,J|0,K|0)|0;J=D;c[B>>2]=K;c[B+4>>2]=J;e=Rd(F|0,E|0,14)|0;t=D;j=Pd(F|0,E|0,50)|0;t=t|D;x=Rd(F|0,E|0,18)|0;I=D;v=Pd(F|0,E|0,46)|0;I=t^(I|D);t=Rd(F|0,E|0,41)|0;n=D;l=Pd(F|0,E|0,23)|0;n=I^(n|D);I=c[h+80+368>>2]|0;H=c[h+80+368+4>>2]|0;y=oe(o|0,y|0,1467031594,-200395387)|0;n=oe(y|0,D|0,(e|j)^(x|v)^(t|l)|0,n|0)|0;H=oe(n|0,D|0,I|0,H|0)|0;H=oe(H|0,D|0,(z^u)&F^z|0,(f^r)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;j=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;o=c[w>>2]|0;q=c[w+4>>2]|0;e=oe((o|L)&K|o&L|0,(q|p)&J|q&p|0,(n|t)^(v|j)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[A>>2]=s;c[A+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[C>>2]=I;c[C+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;y=Pd(s|0,b|0,50)|0;e=e|D;l=Rd(s|0,b|0,18)|0;j=D;v=Pd(s|0,b|0,46)|0;j=e^(j|D);e=Rd(s|0,b|0,41)|0;t=D;n=Pd(s|0,b|0,23)|0;t=j^(t|D);j=c[h+80+376>>2]|0;p=c[h+80+376+4>>2]|0;f=oe(z|0,f|0,851169720,275423344)|0;t=oe(f|0,D|0,(x|y)^(l|v)^(e|n)|0,t|0)|0;p=oe(t|0,D|0,j|0,p|0)|0;p=oe(p|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;j=D;t=Rd(I|0,H|0,28)|0;n=D;e=Pd(I|0,H|0,36)|0;n=n|D;v=Rd(I|0,H|0,34)|0;l=D;y=Pd(I|0,H|0,30)|0;l=n^(l|D);n=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;z=c[m>>2]|0;L=c[m+4>>2]|0;x=oe((z|K)&I|z&K|0,(L|J)&H|L&J|0,(t|e)^(v|y)^(n|f)|0,l^(x|D)|0)|0;l=D;q=oe(o|0,q|0,p|0,j|0)|0;o=D;c[w>>2]=q;c[w+4>>2]=o;j=oe(x|0,l|0,p|0,j|0)|0;p=D;c[h+16>>2]=j;c[h+16+4>>2]=p;l=Rd(q|0,o|0,14)|0;x=D;f=Pd(q|0,o|0,50)|0;x=x|D;n=Rd(q|0,o|0,18)|0;y=D;v=Pd(q|0,o|0,46)|0;y=x^(y|D);x=Rd(q|0,o|0,41)|0;e=D;t=Pd(q|0,o|0,23)|0;e=y^(e|D);y=c[h+80+384>>2]|0;J=c[h+80+384+4>>2]|0;r=oe(u|0,r|0,-1194143544,430227734)|0;e=oe(r|0,D|0,(l|f)^(n|v)^(x|t)|0,e|0)|0;J=oe(e|0,D|0,y|0,J|0)|0;J=oe(J|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;y=D;e=Rd(j|0,p|0,28)|0;t=D;x=Pd(j|0,p|0,36)|0;t=t|D;v=Rd(j|0,p|0,34)|0;n=D;f=Pd(j|0,p|0,30)|0;n=t^(n|D);t=Rd(j|0,p|0,39)|0;l=D;r=Pd(j|0,p|0,25)|0;u=c[B>>2]|0;K=c[B+4>>2]|0;l=oe((u|I)&j|u&I|0,(K|H)&p|K&H|0,(e|x)^(v|f)^(t|r)|0,n^(l|D)|0)|0;n=D;L=oe(z|0,L|0,J|0,y|0)|0;z=D;c[m>>2]=L;c[m+4>>2]=z;y=oe(l|0,n|0,J|0,y|0)|0;J=D;c[G>>2]=y;c[G+4>>2]=J;n=Rd(L|0,z|0,14)|0;l=D;r=Pd(L|0,z|0,50)|0;l=l|D;t=Rd(L|0,z|0,18)|0;f=D;v=Pd(L|0,z|0,46)|0;f=l^(f|D);l=Rd(L|0,z|0,41)|0;x=D;e=Pd(L|0,z|0,23)|0;x=f^(x|D);f=c[h+80+392>>2]|0;H=c[h+80+392+4>>2]|0;E=oe(F|0,E|0,1363258195,506948616)|0;x=oe(E|0,D|0,(n|r)^(t|v)^(l|e)|0,x|0)|0;H=oe(x|0,D|0,f|0,H|0)|0;H=oe(H|0,D|0,(s^q)&L^s|0,(b^o)&z^b|0)|0;f=D;x=Rd(y|0,J|0,28)|0;e=D;l=Pd(y|0,J|0,36)|0;e=e|D;v=Rd(y|0,J|0,34)|0;t=D;r=Pd(y|0,J|0,30)|0;t=e^(t|D);e=Rd(y|0,J|0,39)|0;n=D;E=Pd(y|0,J|0,25)|0;F=c[C>>2]|0;I=c[C+4>>2]|0;n=oe((F|j)&y|F&j|0,(I|p)&J|I&p|0,(x|l)^(v|r)^(e|E)|0,t^(n|D)|0)|0;t=D;K=oe(u|0,K|0,H|0,f|0)|0;u=D;c[B>>2]=K;c[B+4>>2]=u;f=oe(n|0,t|0,H|0,f|0)|0;H=D;c[k>>2]=f;c[k+4>>2]=H;t=Rd(K|0,u|0,14)|0;n=D;E=Pd(K|0,u|0,50)|0;n=n|D;e=Rd(K|0,u|0,18)|0;r=D;v=Pd(K|0,u|0,46)|0;r=n^(r|D);n=Rd(K|0,u|0,41)|0;l=D;x=Pd(K|0,u|0,23)|0;l=r^(l|D);r=c[h+80+400>>2]|0;p=c[h+80+400+4>>2]|0;b=oe(s|0,b|0,-544281703,659060556)|0;l=oe(b|0,D|0,(t|E)^(e|v)^(n|x)|0,l|0)|0;p=oe(l|0,D|0,r|0,p|0)|0;p=oe(p|0,D|0,(q^L)&K^q|0,(o^z)&u^o|0)|0;r=D;l=Rd(f|0,H|0,28)|0;x=D;n=Pd(f|0,H|0,36)|0;x=x|D;v=Rd(f|0,H|0,34)|0;e=D;E=Pd(f|0,H|0,30)|0;e=x^(e|D);x=Rd(f|0,H|0,39)|0;t=D;b=Pd(f|0,H|0,25)|0;s=c[h+16>>2]|0;j=c[h+16+4>>2]|0;t=oe((s|y)&f|s&y|0,(j|J)&H|j&J|0,(l|n)^(v|E)^(x|b)|0,e^(t|D)|0)|0;e=D;I=oe(F|0,I|0,p|0,r|0)|0;F=D;c[C>>2]=I;c[C+4>>2]=F;r=oe(t|0,e|0,p|0,r|0)|0;p=D;c[A>>2]=r;c[A+4>>2]=p;e=Rd(I|0,F|0,14)|0;t=D;b=Pd(I|0,F|0,50)|0;t=t|D;x=Rd(I|0,F|0,18)|0;E=D;v=Pd(I|0,F|0,46)|0;E=t^(E|D);t=Rd(I|0,F|0,41)|0;n=D;l=Pd(I|0,F|0,23)|0;n=E^(n|D);E=c[h+80+408>>2]|0;J=c[h+80+408+4>>2]|0;o=oe(q|0,o|0,-509917016,883997877)|0;n=oe(o|0,D|0,(e|b)^(x|v)^(t|l)|0,n|0)|0;J=oe(n|0,D|0,E|0,J|0)|0;J=oe(J|0,D|0,(L^K)&I^L|0,(z^u)&F^z|0)|0;E=D;n=Rd(r|0,p|0,28)|0;l=D;t=Pd(r|0,p|0,36)|0;l=l|D;v=Rd(r|0,p|0,34)|0;x=D;b=Pd(r|0,p|0,30)|0;x=l^(x|D);l=Rd(r|0,p|0,39)|0;e=D;o=Pd(r|0,p|0,25)|0;q=c[G>>2]|0;y=c[G+4>>2]|0;e=oe((q|f)&r|q&f|0,(y|H)&p|y&H|0,(n|t)^(v|b)^(l|o)|0,x^(e|D)|0)|0;x=D;j=oe(s|0,j|0,J|0,E|0)|0;s=D;c[h+16>>2]=j;c[h+16+4>>2]=s;E=oe(e|0,x|0,J|0,E|0)|0;J=D;c[w>>2]=E;c[w+4>>2]=J;x=Rd(j|0,s|0,14)|0;e=D;o=Pd(j|0,s|0,50)|0;e=e|D;l=Rd(j|0,s|0,18)|0;b=D;v=Pd(j|0,s|0,46)|0;b=e^(b|D);e=Rd(j|0,s|0,41)|0;t=D;n=Pd(j|0,s|0,23)|0;t=b^(t|D);b=c[h+80+416>>2]|0;H=c[h+80+416+4>>2]|0;z=oe(L|0,z|0,-976659869,958139571)|0;t=oe(z|0,D|0,(x|o)^(l|v)^(e|n)|0,t|0)|0;H=oe(t|0,D|0,b|0,H|0)|0;H=oe(H|0,D|0,(K^I)&j^K|0,(u^F)&s^u|0)|0;b=D;t=Rd(E|0,J|0,28)|0;n=D;e=Pd(E|0,J|0,36)|0;n=n|D;v=Rd(E|0,J|0,34)|0;l=D;o=Pd(E|0,J|0,30)|0;l=n^(l|D);n=Rd(E|0,J|0,39)|0;x=D;z=Pd(E|0,J|0,25)|0;L=c[k>>2]|0;f=c[k+4>>2]|0;x=oe((L|r)&E|L&r|0,(f|p)&J|f&p|0,(t|e)^(v|o)^(n|z)|0,l^(x|D)|0)|0;l=D;y=oe(q|0,y|0,H|0,b|0)|0;q=D;c[G>>2]=y;c[G+4>>2]=q;b=oe(x|0,l|0,H|0,b|0)|0;H=D;c[m>>2]=b;c[m+4>>2]=H;l=Rd(y|0,q|0,14)|0;x=D;z=Pd(y|0,q|0,50)|0;x=x|D;n=Rd(y|0,q|0,18)|0;o=D;v=Pd(y|0,q|0,46)|0;o=x^(o|D);x=Rd(y|0,q|0,41)|0;e=D;t=Pd(y|0,q|0,23)|0;e=o^(e|D);o=c[h+80+424>>2]|0;p=c[h+80+424+4>>2]|0;u=oe(K|0,u|0,-482243893,1322822218)|0;e=oe(u|0,D|0,(l|z)^(n|v)^(x|t)|0,e|0)|0;p=oe(e|0,D|0,o|0,p|0)|0;p=oe(p|0,D|0,(I^j)&y^I|0,(F^s)&q^F|0)|0;o=D;e=Rd(b|0,H|0,28)|0;t=D;x=Pd(b|0,H|0,36)|0;t=t|D;v=Rd(b|0,H|0,34)|0;n=D;z=Pd(b|0,H|0,30)|0;n=t^(n|D);t=Rd(b|0,H|0,39)|0;l=D;u=Pd(b|0,H|0,25)|0;K=c[A>>2]|0;r=c[A+4>>2]|0;l=oe((K|E)&b|K&E|0,(r|J)&H|r&J|0,(e|x)^(v|z)^(t|u)|0,n^(l|D)|0)|0;n=D;f=oe(L|0,f|0,p|0,o|0)|0;L=D;c[k>>2]=f;c[k+4>>2]=L;o=oe(l|0,n|0,p|0,o|0)|0;p=D;c[B>>2]=o;c[B+4>>2]=p;n=Rd(f|0,L|0,14)|0;l=D;u=Pd(f|0,L|0,50)|0;l=l|D;t=Rd(f|0,L|0,18)|0;z=D;v=Pd(f|0,L|0,46)|0;z=l^(z|D);l=Rd(f|0,L|0,41)|0;x=D;e=Pd(f|0,L|0,23)|0;x=z^(x|D);z=c[h+80+432>>2]|0;J=c[h+80+432+4>>2]|0;F=oe(I|0,F|0,2003034995,1537002063)|0;x=oe(F|0,D|0,(n|u)^(t|v)^(l|e)|0,x|0)|0;J=oe(x|0,D|0,z|0,J|0)|0;J=oe(J|0,D|0,(j^y)&f^j|0,(s^q)&L^s|0)|0;z=D;x=Rd(o|0,p|0,28)|0;e=D;l=Pd(o|0,p|0,36)|0;e=e|D;v=Rd(o|0,p|0,34)|0;t=D;u=Pd(o|0,p|0,30)|0;t=e^(t|D);e=Rd(o|0,p|0,39)|0;n=D;F=Pd(o|0,p|0,25)|0;I=c[w>>2]|0;E=c[w+4>>2]|0;n=oe((I|b)&o|I&b|0,(E|H)&p|E&H|0,(x|l)^(v|u)^(e|F)|0,t^(n|D)|0)|0;t=D;r=oe(K|0,r|0,J|0,z|0)|0;K=D;c[A>>2]=r;c[A+4>>2]=K;z=oe(n|0,t|0,J|0,z|0)|0;J=D;c[C>>2]=z;c[C+4>>2]=J;t=Rd(r|0,K|0,14)|0;n=D;F=Pd(r|0,K|0,50)|0;n=n|D;e=Rd(r|0,K|0,18)|0;u=D;v=Pd(r|0,K|0,46)|0;u=n^(u|D);n=Rd(r|0,K|0,41)|0;l=D;x=Pd(r|0,K|0,23)|0;l=u^(l|D);u=c[h+80+440>>2]|0;H=c[h+80+440+4>>2]|0;s=oe(j|0,s|0,-692930397,1747873779)|0;l=oe(s|0,D|0,(t|F)^(e|v)^(n|x)|0,l|0)|0;H=oe(l|0,D|0,u|0,H|0)|0;H=oe(H|0,D|0,(y^f)&r^y|0,(q^L)&K^q|0)|0;u=D;l=Rd(z|0,J|0,28)|0;x=D;n=Pd(z|0,J|0,36)|0;x=x|D;v=Rd(z|0,J|0,34)|0;e=D;F=Pd(z|0,J|0,30)|0;e=x^(e|D);x=Rd(z|0,J|0,39)|0;t=D;s=Pd(z|0,J|0,25)|0;j=c[m>>2]|0;b=c[m+4>>2]|0;t=oe((j|o)&z|j&o|0,(b|p)&J|b&p|0,(l|n)^(v|F)^(x|s)|0,e^(t|D)|0)|0;e=D;E=oe(I|0,E|0,H|0,u|0)|0;I=D;c[w>>2]=E;c[w+4>>2]=I;u=oe(t|0,e|0,H|0,u|0)|0;H=D;c[h+16>>2]=u;c[h+16+4>>2]=H;e=Rd(E|0,I|0,14)|0;t=D;s=Pd(E|0,I|0,50)|0;t=t|D;x=Rd(E|0,I|0,18)|0;F=D;v=Pd(E|0,I|0,46)|0;F=t^(F|D);t=Rd(E|0,I|0,41)|0;n=D;l=Pd(E|0,I|0,23)|0;n=F^(n|D);F=c[h+80+448>>2]|0;p=c[h+80+448+4>>2]|0;q=oe(y|0,q|0,1575990012,1955562222)|0;n=oe(q|0,D|0,(e|s)^(x|v)^(t|l)|0,n|0)|0;p=oe(n|0,D|0,F|0,p|0)|0;p=oe(p|0,D|0,(f^r)&E^f|0,(L^K)&I^L|0)|0;F=D;n=Rd(u|0,H|0,28)|0;l=D;t=Pd(u|0,H|0,36)|0;l=l|D;v=Rd(u|0,H|0,34)|0;x=D;s=Pd(u|0,H|0,30)|0;x=l^(x|D);l=Rd(u|0,H|0,39)|0;e=D;q=Pd(u|0,H|0,25)|0;y=c[B>>2]|0;o=c[B+4>>2]|0;e=oe((y|z)&u|y&z|0,(o|J)&H|o&J|0,(n|t)^(v|s)^(l|q)|0,x^(e|D)|0)|0;x=D;b=oe(j|0,b|0,p|0,F|0)|0;j=D;c[m>>2]=b;c[m+4>>2]=j;F=oe(e|0,x|0,p|0,F|0)|0;p=D;c[G>>2]=F;c[G+4>>2]=p;x=Rd(b|0,j|0,14)|0;e=D;q=Pd(b|0,j|0,50)|0;e=e|D;l=Rd(b|0,j|0,18)|0;s=D;v=Pd(b|0,j|0,46)|0;s=e^(s|D);e=Rd(b|0,j|0,41)|0;t=D;n=Pd(b|0,j|0,23)|0;t=s^(t|D);s=c[h+80+456>>2]|0;J=c[h+80+456+4>>2]|0;L=oe(f|0,L|0,1125592928,2024104815)|0;t=oe(L|0,D|0,(x|q)^(l|v)^(e|n)|0,t|0)|0;J=oe(t|0,D|0,s|0,J|0)|0;J=oe(J|0,D|0,(r^E)&b^r|0,(K^I)&j^K|0)|0;s=D;t=Rd(F|0,p|0,28)|0;n=D;e=Pd(F|0,p|0,36)|0;n=n|D;v=Rd(F|0,p|0,34)|0;l=D;q=Pd(F|0,p|0,30)|0;l=n^(l|D);n=Rd(F|0,p|0,39)|0;x=D;L=Pd(F|0,p|0,25)|0;f=c[C>>2]|0;z=c[C+4>>2]|0;x=oe((f|u)&F|f&u|0,(z|H)&p|z&H|0,(t|e)^(v|q)^(n|L)|0,l^(x|D)|0)|0;l=D;o=oe(y|0,o|0,J|0,s|0)|0;y=D;c[B>>2]=o;c[B+4>>2]=y;s=oe(x|0,l|0,J|0,s|0)|0;J=D;c[k>>2]=s;c[k+4>>2]=J;l=Rd(o|0,y|0,14)|0;x=D;L=Pd(o|0,y|0,50)|0;x=x|D;n=Rd(o|0,y|0,18)|0;q=D;v=Pd(o|0,y|0,46)|0;q=x^(q|D);x=Rd(o|0,y|0,41)|0;e=D;t=Pd(o|0,y|0,23)|0;e=q^(e|D);q=c[h+80+464>>2]|0;H=c[h+80+464+4>>2]|0;K=oe(r|0,K|0,-1578062990,-2067236844)|0;e=oe(K|0,D|0,(l|L)^(n|v)^(x|t)|0,e|0)|0;H=oe(e|0,D|0,q|0,H|0)|0;H=oe(H|0,D|0,(E^b)&o^E|0,(I^j)&y^I|0)|0;q=D;e=Rd(s|0,J|0,28)|0;t=D;x=Pd(s|0,J|0,36)|0;t=t|D;v=Rd(s|0,J|0,34)|0;n=D;L=Pd(s|0,J|0,30)|0;n=t^(n|D);t=Rd(s|0,J|0,39)|0;l=D;K=Pd(s|0,J|0,25)|0;r=c[h+16>>2]|0;u=c[h+16+4>>2]|0;l=oe((r|F)&s|r&F|0,(u|p)&J|u&p|0,(e|x)^(v|L)^(t|K)|0,n^(l|D)|0)|0;n=D;z=oe(f|0,z|0,H|0,q|0)|0;f=D;c[C>>2]=z;c[C+4>>2]=f;q=oe(l|0,n|0,H|0,q|0)|0;H=D;c[A>>2]=q;c[A+4>>2]=H;n=Rd(z|0,f|0,14)|0;l=D;K=Pd(z|0,f|0,50)|0;l=l|D;t=Rd(z|0,f|0,18)|0;L=D;v=Pd(z|0,f|0,46)|0;L=l^(L|D);l=Rd(z|0,f|0,41)|0;x=D;e=Pd(z|0,f|0,23)|0;x=L^(x|D);L=c[h+80+472>>2]|0;p=c[h+80+472+4>>2]|0;I=oe(E|0,I|0,442776044,-1933114872)|0;x=oe(I|0,D|0,(n|K)^(t|v)^(l|e)|0,x|0)|0;p=oe(x|0,D|0,L|0,p|0)|0;p=oe(p|0,D|0,(b^o)&z^b|0,(j^y)&f^j|0)|0;L=D;x=Rd(q|0,H|0,28)|0;e=D;l=Pd(q|0,H|0,36)|0;e=e|D;v=Rd(q|0,H|0,34)|0;t=D;K=Pd(q|0,H|0,30)|0;t=e^(t|D);e=Rd(q|0,H|0,39)|0;n=D;I=Pd(q|0,H|0,25)|0;E=c[G>>2]|0;F=c[G+4>>2]|0;n=oe((E|s)&q|E&s|0,(F|J)&H|F&J|0,(x|l)^(v|K)^(e|I)|0,t^(n|D)|0)|0;t=D;u=oe(r|0,u|0,p|0,L|0)|0;r=D;c[h+16>>2]=u;c[h+16+4>>2]=r;L=oe(n|0,t|0,p|0,L|0)|0;p=D;c[w>>2]=L;c[w+4>>2]=p;t=Rd(u|0,r|0,14)|0;n=D;I=Pd(u|0,r|0,50)|0;n=n|D;e=Rd(u|0,r|0,18)|0;K=D;v=Pd(u|0,r|0,46)|0;K=n^(K|D);n=Rd(u|0,r|0,41)|0;l=D;x=Pd(u|0,r|0,23)|0;l=K^(l|D);K=c[h+80+480>>2]|0;J=c[h+80+480+4>>2]|0;j=oe(b|0,j|0,593698344,-1866530822)|0;l=oe(j|0,D|0,(t|I)^(e|v)^(n|x)|0,l|0)|0;J=oe(l|0,D|0,K|0,J|0)|0;J=oe(J|0,D|0,(o^z)&u^o|0,(y^f)&r^y|0)|0;K=D;l=Rd(L|0,p|0,28)|0;x=D;n=Pd(L|0,p|0,36)|0;x=x|D;v=Rd(L|0,p|0,34)|0;e=D;I=Pd(L|0,p|0,30)|0;e=x^(e|D);x=Rd(L|0,p|0,39)|0;t=D;j=Pd(L|0,p|0,25)|0;b=c[k>>2]|0;s=c[k+4>>2]|0;t=oe((b|q)&L|b&q|0,(s|H)&p|s&H|0,(l|n)^(v|I)^(x|j)|0,e^(t|D)|0)|0;e=D;F=oe(E|0,F|0,J|0,K|0)|0;E=D;c[G>>2]=F;c[G+4>>2]=E;K=oe(t|0,e|0,J|0,K|0)|0;J=D;c[m>>2]=K;c[m+4>>2]=J;e=Rd(F|0,E|0,14)|0;t=D;j=Pd(F|0,E|0,50)|0;t=t|D;x=Rd(F|0,E|0,18)|0;I=D;v=Pd(F|0,E|0,46)|0;I=t^(I|D);t=Rd(F|0,E|0,41)|0;n=D;l=Pd(F|0,E|0,23)|0;n=I^(n|D);I=c[h+80+488>>2]|0;H=c[h+80+488+4>>2]|0;y=oe(o|0,y|0,-561857047,-1538233109)|0;n=oe(y|0,D|0,(e|j)^(x|v)^(t|l)|0,n|0)|0;H=oe(n|0,D|0,I|0,H|0)|0;H=oe(H|0,D|0,(z^u)&F^z|0,(f^r)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;j=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;o=c[A>>2]|0;q=c[A+4>>2]|0;e=oe((o|L)&K|o&L|0,(q|p)&J|q&p|0,(n|t)^(v|j)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[k>>2]=s;c[k+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[B>>2]=I;c[B+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;y=Pd(s|0,b|0,50)|0;e=e|D;l=Rd(s|0,b|0,18)|0;j=D;v=Pd(s|0,b|0,46)|0;j=e^(j|D);e=Rd(s|0,b|0,41)|0;t=D;n=Pd(s|0,b|0,23)|0;t=j^(t|D);j=c[h+80+496>>2]|0;p=c[h+80+496+4>>2]|0;f=oe(z|0,f|0,-1295615723,-1090935817)|0;t=oe(f|0,D|0,(x|y)^(l|v)^(e|n)|0,t|0)|0;p=oe(t|0,D|0,j|0,p|0)|0;p=oe(p|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;j=D;t=Rd(I|0,H|0,28)|0;n=D;e=Pd(I|0,H|0,36)|0;n=n|D;v=Rd(I|0,H|0,34)|0;l=D;y=Pd(I|0,H|0,30)|0;l=n^(l|D);n=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;z=c[w>>2]|0;L=c[w+4>>2]|0;x=oe((z|K)&I|z&K|0,(L|J)&H|L&J|0,(t|e)^(v|y)^(n|f)|0,l^(x|D)|0)|0;l=D;q=oe(o|0,q|0,p|0,j|0)|0;o=D;c[A>>2]=q;c[A+4>>2]=o;j=oe(x|0,l|0,p|0,j|0)|0;p=D;c[C>>2]=j;c[C+4>>2]=p;l=Rd(q|0,o|0,14)|0;x=D;f=Pd(q|0,o|0,50)|0;x=x|D;n=Rd(q|0,o|0,18)|0;y=D;v=Pd(q|0,o|0,46)|0;y=x^(y|D);x=Rd(q|0,o|0,41)|0;e=D;t=Pd(q|0,o|0,23)|0;e=y^(e|D);y=c[h+80+504>>2]|0;J=c[h+80+504+4>>2]|0;r=oe(u|0,r|0,-479046869,-965641998)|0;e=oe(r|0,D|0,(l|f)^(n|v)^(x|t)|0,e|0)|0;J=oe(e|0,D|0,y|0,J|0)|0;J=oe(J|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;y=D;e=Rd(j|0,p|0,28)|0;t=D;x=Pd(j|0,p|0,36)|0;t=t|D;v=Rd(j|0,p|0,34)|0;n=D;f=Pd(j|0,p|0,30)|0;n=t^(n|D);t=Rd(j|0,p|0,39)|0;l=D;r=Pd(j|0,p|0,25)|0;u=c[m>>2]|0;K=c[m+4>>2]|0;l=oe((u|I)&j|u&I|0,(K|H)&p|K&H|0,(e|x)^(v|f)^(t|r)|0,n^(l|D)|0)|0;n=D;L=oe(z|0,L|0,J|0,y|0)|0;z=D;c[w>>2]=L;c[w+4>>2]=z;y=oe(l|0,n|0,J|0,y|0)|0;J=D;c[h+16>>2]=y;c[h+16+4>>2]=J;n=Rd(L|0,z|0,14)|0;l=D;r=Pd(L|0,z|0,50)|0;l=l|D;t=Rd(L|0,z|0,18)|0;f=D;v=Pd(L|0,z|0,46)|0;f=l^(f|D);l=Rd(L|0,z|0,41)|0;x=D;e=Pd(L|0,z|0,23)|0;x=f^(x|D);f=c[h+80+512>>2]|0;H=c[h+80+512+4>>2]|0;E=oe(F|0,E|0,-366583396,-903397682)|0;x=oe(E|0,D|0,(n|r)^(t|v)^(l|e)|0,x|0)|0;H=oe(x|0,D|0,f|0,H|0)|0;H=oe(H|0,D|0,(s^q)&L^s|0,(b^o)&z^b|0)|0;f=D;x=Rd(y|0,J|0,28)|0;e=D;l=Pd(y|0,J|0,36)|0;e=e|D;v=Rd(y|0,J|0,34)|0;t=D;r=Pd(y|0,J|0,30)|0;t=e^(t|D);e=Rd(y|0,J|0,39)|0;n=D;E=Pd(y|0,J|0,25)|0;F=c[B>>2]|0;I=c[B+4>>2]|0;n=oe((F|j)&y|F&j|0,(I|p)&J|I&p|0,(x|l)^(v|r)^(e|E)|0,t^(n|D)|0)|0;t=D;K=oe(u|0,K|0,H|0,f|0)|0;u=D;c[m>>2]=K;c[m+4>>2]=u;f=oe(n|0,t|0,H|0,f|0)|0;H=D;c[G>>2]=f;c[G+4>>2]=H;t=Rd(K|0,u|0,14)|0;n=D;E=Pd(K|0,u|0,50)|0;n=n|D;e=Rd(K|0,u|0,18)|0;r=D;v=Pd(K|0,u|0,46)|0;r=n^(r|D);n=Rd(K|0,u|0,41)|0;l=D;x=Pd(K|0,u|0,23)|0;l=r^(l|D);r=c[h+80+520>>2]|0;p=c[h+80+520+4>>2]|0;b=oe(s|0,b|0,566280711,-779700025)|0;l=oe(b|0,D|0,(t|E)^(e|v)^(n|x)|0,l|0)|0;p=oe(l|0,D|0,r|0,p|0)|0;p=oe(p|0,D|0,(q^L)&K^q|0,(o^z)&u^o|0)|0;r=D;l=Rd(f|0,H|0,28)|0;x=D;n=Pd(f|0,H|0,36)|0;x=x|D;v=Rd(f|0,H|0,34)|0;e=D;E=Pd(f|0,H|0,30)|0;e=x^(e|D);x=Rd(f|0,H|0,39)|0;t=D;b=Pd(f|0,H|0,25)|0;s=c[C>>2]|0;j=c[C+4>>2]|0;t=oe((s|y)&f|s&y|0,(j|J)&H|j&J|0,(l|n)^(v|E)^(x|b)|0,e^(t|D)|0)|0;e=D;I=oe(F|0,I|0,p|0,r|0)|0;F=D;c[B>>2]=I;c[B+4>>2]=F;r=oe(t|0,e|0,p|0,r|0)|0;p=D;c[k>>2]=r;c[k+4>>2]=p;e=Rd(I|0,F|0,14)|0;t=D;b=Pd(I|0,F|0,50)|0;t=t|D;x=Rd(I|0,F|0,18)|0;E=D;v=Pd(I|0,F|0,46)|0;E=t^(E|D);t=Rd(I|0,F|0,41)|0;n=D;l=Pd(I|0,F|0,23)|0;n=E^(n|D);E=c[h+80+528>>2]|0;J=c[h+80+528+4>>2]|0;o=oe(q|0,o|0,-840897762,-354779690)|0;n=oe(o|0,D|0,(e|b)^(x|v)^(t|l)|0,n|0)|0;J=oe(n|0,D|0,E|0,J|0)|0;J=oe(J|0,D|0,(L^K)&I^L|0,(z^u)&F^z|0)|0;E=D;n=Rd(r|0,p|0,28)|0;l=D;t=Pd(r|0,p|0,36)|0;l=l|D;v=Rd(r|0,p|0,34)|0;x=D;b=Pd(r|0,p|0,30)|0;x=l^(x|D);l=Rd(r|0,p|0,39)|0;e=D;o=Pd(r|0,p|0,25)|0;q=c[h+16>>2]|0;y=c[h+16+4>>2]|0;e=oe((q|f)&r|q&f|0,(y|H)&p|y&H|0,(n|t)^(v|b)^(l|o)|0,x^(e|D)|0)|0;x=D;j=oe(s|0,j|0,J|0,E|0)|0;s=D;c[C>>2]=j;c[C+4>>2]=s;E=oe(e|0,x|0,J|0,E|0)|0;J=D;c[A>>2]=E;c[A+4>>2]=J;x=Rd(j|0,s|0,14)|0;e=D;o=Pd(j|0,s|0,50)|0;e=e|D;l=Rd(j|0,s|0,18)|0;b=D;v=Pd(j|0,s|0,46)|0;b=e^(b|D);e=Rd(j|0,s|0,41)|0;t=D;n=Pd(j|0,s|0,23)|0;t=b^(t|D);b=c[h+80+536>>2]|0;H=c[h+80+536+4>>2]|0;z=oe(L|0,z|0,-294727304,-176337025)|0;t=oe(z|0,D|0,(x|o)^(l|v)^(e|n)|0,t|0)|0;H=oe(t|0,D|0,b|0,H|0)|0;H=oe(H|0,D|0,(K^I)&j^K|0,(u^F)&s^u|0)|0;b=D;t=Rd(E|0,J|0,28)|0;n=D;e=Pd(E|0,J|0,36)|0;n=n|D;v=Rd(E|0,J|0,34)|0;l=D;o=Pd(E|0,J|0,30)|0;l=n^(l|D);n=Rd(E|0,J|0,39)|0;x=D;z=Pd(E|0,J|0,25)|0;L=c[G>>2]|0;f=c[G+4>>2]|0;x=oe((L|r)&E|L&r|0,(f|p)&J|f&p|0,(t|e)^(v|o)^(n|z)|0,l^(x|D)|0)|0;l=D;y=oe(q|0,y|0,H|0,b|0)|0;q=D;c[h+16>>2]=y;c[h+16+4>>2]=q;b=oe(x|0,l|0,H|0,b|0)|0;H=D;c[w>>2]=b;c[w+4>>2]=H;l=Rd(y|0,q|0,14)|0;x=D;z=Pd(y|0,q|0,50)|0;x=x|D;n=Rd(y|0,q|0,18)|0;o=D;v=Pd(y|0,q|0,46)|0;o=x^(o|D);x=Rd(y|0,q|0,41)|0;e=D;t=Pd(y|0,q|0,23)|0;e=o^(e|D);o=c[h+80+544>>2]|0;p=c[h+80+544+4>>2]|0;u=oe(K|0,u|0,1914138554,116418474)|0;e=oe(u|0,D|0,(l|z)^(n|v)^(x|t)|0,e|0)|0;p=oe(e|0,D|0,o|0,p|0)|0;p=oe(p|0,D|0,(I^j)&y^I|0,(F^s)&q^F|0)|0;o=D;e=Rd(b|0,H|0,28)|0;t=D;x=Pd(b|0,H|0,36)|0;t=t|D;v=Rd(b|0,H|0,34)|0;n=D;z=Pd(b|0,H|0,30)|0;n=t^(n|D);t=Rd(b|0,H|0,39)|0;l=D;u=Pd(b|0,H|0,25)|0;K=c[k>>2]|0;r=c[k+4>>2]|0;l=oe((K|E)&b|K&E|0,(r|J)&H|r&J|0,(e|x)^(v|z)^(t|u)|0,n^(l|D)|0)|0;n=D;f=oe(L|0,f|0,p|0,o|0)|0;L=D;c[G>>2]=f;c[G+4>>2]=L;o=oe(l|0,n|0,p|0,o|0)|0;p=D;c[m>>2]=o;c[m+4>>2]=p;n=Rd(f|0,L|0,14)|0;l=D;u=Pd(f|0,L|0,50)|0;l=l|D;t=Rd(f|0,L|0,18)|0;z=D;v=Pd(f|0,L|0,46)|0;z=l^(z|D);l=Rd(f|0,L|0,41)|0;x=D;e=Pd(f|0,L|0,23)|0;x=z^(x|D);z=c[h+80+552>>2]|0;J=c[h+80+552+4>>2]|0;F=oe(I|0,F|0,-1563912026,174292421)|0;x=oe(F|0,D|0,(n|u)^(t|v)^(l|e)|0,x|0)|0;J=oe(x|0,D|0,z|0,J|0)|0;J=oe(J|0,D|0,(j^y)&f^j|0,(s^q)&L^s|0)|0;z=D;x=Rd(o|0,p|0,28)|0;e=D;l=Pd(o|0,p|0,36)|0;e=e|D;v=Rd(o|0,p|0,34)|0;t=D;u=Pd(o|0,p|0,30)|0;t=e^(t|D);e=Rd(o|0,p|0,39)|0;n=D;F=Pd(o|0,p|0,25)|0;I=c[A>>2]|0;E=c[A+4>>2]|0;n=oe((I|b)&o|I&b|0,(E|H)&p|E&H|0,(x|l)^(v|u)^(e|F)|0,t^(n|D)|0)|0;t=D;r=oe(K|0,r|0,J|0,z|0)|0;K=D;c[k>>2]=r;c[k+4>>2]=K;z=oe(n|0,t|0,J|0,z|0)|0;J=D;c[B>>2]=z;c[B+4>>2]=J;t=Rd(r|0,K|0,14)|0;n=D;F=Pd(r|0,K|0,50)|0;n=n|D;e=Rd(r|0,K|0,18)|0;u=D;v=Pd(r|0,K|0,46)|0;u=n^(u|D);n=Rd(r|0,K|0,41)|0;l=D;x=Pd(r|0,K|0,23)|0;l=u^(l|D);u=c[h+80+560>>2]|0;H=c[h+80+560+4>>2]|0;s=oe(j|0,s|0,-1090974290,289380356)|0;l=oe(s|0,D|0,(t|F)^(e|v)^(n|x)|0,l|0)|0;H=oe(l|0,D|0,u|0,H|0)|0;H=oe(H|0,D|0,(y^f)&r^y|0,(q^L)&K^q|0)|0;u=D;l=Rd(z|0,J|0,28)|0;x=D;n=Pd(z|0,J|0,36)|0;x=x|D;v=Rd(z|0,J|0,34)|0;e=D;F=Pd(z|0,J|0,30)|0;e=x^(e|D);x=Rd(z|0,J|0,39)|0;t=D;s=Pd(z|0,J|0,25)|0;j=c[w>>2]|0;b=c[w+4>>2]|0;t=oe((j|o)&z|j&o|0,(b|p)&J|b&p|0,(l|n)^(v|F)^(x|s)|0,e^(t|D)|0)|0;e=D;E=oe(I|0,E|0,H|0,u|0)|0;I=D;c[A>>2]=E;c[A+4>>2]=I;u=oe(t|0,e|0,H|0,u|0)|0;H=D;c[C>>2]=u;c[C+4>>2]=H;e=Rd(E|0,I|0,14)|0;t=D;s=Pd(E|0,I|0,50)|0;t=t|D;x=Rd(E|0,I|0,18)|0;F=D;v=Pd(E|0,I|0,46)|0;F=t^(F|D);t=Rd(E|0,I|0,41)|0;n=D;l=Pd(E|0,I|0,23)|0;n=F^(n|D);F=c[h+80+568>>2]|0;p=c[h+80+568+4>>2]|0;q=oe(y|0,q|0,320620315,460393269)|0;n=oe(q|0,D|0,(e|s)^(x|v)^(t|l)|0,n|0)|0;p=oe(n|0,D|0,F|0,p|0)|0;p=oe(p|0,D|0,(f^r)&E^f|0,(L^K)&I^L|0)|0;F=D;n=Rd(u|0,H|0,28)|0;l=D;t=Pd(u|0,H|0,36)|0;l=l|D;v=Rd(u|0,H|0,34)|0;x=D;s=Pd(u|0,H|0,30)|0;x=l^(x|D);l=Rd(u|0,H|0,39)|0;e=D;q=Pd(u|0,H|0,25)|0;y=c[m>>2]|0;o=c[m+4>>2]|0;e=oe((y|z)&u|y&z|0,(o|J)&H|o&J|0,(n|t)^(v|s)^(l|q)|0,x^(e|D)|0)|0;x=D;b=oe(j|0,b|0,p|0,F|0)|0;j=D;c[w>>2]=b;c[w+4>>2]=j;F=oe(e|0,x|0,p|0,F|0)|0;p=D;c[h+16>>2]=F;c[h+16+4>>2]=p;x=Rd(b|0,j|0,14)|0;e=D;q=Pd(b|0,j|0,50)|0;e=e|D;l=Rd(b|0,j|0,18)|0;s=D;v=Pd(b|0,j|0,46)|0;s=e^(s|D);e=Rd(b|0,j|0,41)|0;t=D;n=Pd(b|0,j|0,23)|0;t=s^(t|D);s=c[h+80+576>>2]|0;J=c[h+80+576+4>>2]|0;L=oe(f|0,L|0,587496836,685471733)|0;t=oe(L|0,D|0,(x|q)^(l|v)^(e|n)|0,t|0)|0;J=oe(t|0,D|0,s|0,J|0)|0;J=oe(J|0,D|0,(r^E)&b^r|0,(K^I)&j^K|0)|0;s=D;t=Rd(F|0,p|0,28)|0;n=D;e=Pd(F|0,p|0,36)|0;n=n|D;v=Rd(F|0,p|0,34)|0;l=D;q=Pd(F|0,p|0,30)|0;l=n^(l|D);n=Rd(F|0,p|0,39)|0;x=D;L=Pd(F|0,p|0,25)|0;f=c[B>>2]|0;z=c[B+4>>2]|0;x=oe((f|u)&F|f&u|0,(z|H)&p|z&H|0,(t|e)^(v|q)^(n|L)|0,l^(x|D)|0)|0;l=D;o=oe(y|0,o|0,J|0,s|0)|0;y=D;c[m>>2]=o;c[m+4>>2]=y;s=oe(x|0,l|0,J|0,s|0)|0;J=D;c[G>>2]=s;c[G+4>>2]=J;l=Rd(o|0,y|0,14)|0;x=D;L=Pd(o|0,y|0,50)|0;x=x|D;n=Rd(o|0,y|0,18)|0;q=D;v=Pd(o|0,y|0,46)|0;q=x^(q|D);x=Rd(o|0,y|0,41)|0;e=D;t=Pd(o|0,y|0,23)|0;e=q^(e|D);q=c[h+80+584>>2]|0;H=c[h+80+584+4>>2]|0;K=oe(r|0,K|0,1086792851,852142971)|0;e=oe(K|0,D|0,(l|L)^(n|v)^(x|t)|0,e|0)|0;H=oe(e|0,D|0,q|0,H|0)|0;H=oe(H|0,D|0,(E^b)&o^E|0,(I^j)&y^I|0)|0;q=D;e=Rd(s|0,J|0,28)|0;t=D;x=Pd(s|0,J|0,36)|0;t=t|D;v=Rd(s|0,J|0,34)|0;n=D;L=Pd(s|0,J|0,30)|0;n=t^(n|D);t=Rd(s|0,J|0,39)|0;l=D;K=Pd(s|0,J|0,25)|0;r=c[C>>2]|0;u=c[C+4>>2]|0;l=oe((r|F)&s|r&F|0,(u|p)&J|u&p|0,(e|x)^(v|L)^(t|K)|0,n^(l|D)|0)|0;n=D;z=oe(f|0,z|0,H|0,q|0)|0;f=D;c[B>>2]=z;c[B+4>>2]=f;q=oe(l|0,n|0,H|0,q|0)|0;H=D;c[k>>2]=q;c[k+4>>2]=H;n=Rd(z|0,f|0,14)|0;l=D;K=Pd(z|0,f|0,50)|0;l=l|D;t=Rd(z|0,f|0,18)|0;L=D;v=Pd(z|0,f|0,46)|0;L=l^(L|D);l=Rd(z|0,f|0,41)|0;x=D;e=Pd(z|0,f|0,23)|0;x=L^(x|D);L=c[h+80+592>>2]|0;p=c[h+80+592+4>>2]|0;I=oe(E|0,I|0,365543100,1017036298)|0;x=oe(I|0,D|0,(n|K)^(t|v)^(l|e)|0,x|0)|0;p=oe(x|0,D|0,L|0,p|0)|0;p=oe(p|0,D|0,(b^o)&z^b|0,(j^y)&f^j|0)|0;L=D;x=Rd(q|0,H|0,28)|0;e=D;l=Pd(q|0,H|0,36)|0;e=e|D;v=Rd(q|0,H|0,34)|0;t=D;K=Pd(q|0,H|0,30)|0;t=e^(t|D);e=Rd(q|0,H|0,39)|0;n=D;I=Pd(q|0,H|0,25)|0;E=c[h+16>>2]|0;F=c[h+16+4>>2]|0;n=oe((E|s)&q|E&s|0,(F|J)&H|F&J|0,(x|l)^(v|K)^(e|I)|0,t^(n|D)|0)|0;t=D;u=oe(r|0,u|0,p|0,L|0)|0;r=D;c[C>>2]=u;c[C+4>>2]=r;L=oe(n|0,t|0,p|0,L|0)|0;p=D;c[A>>2]=L;c[A+4>>2]=p;t=Rd(u|0,r|0,14)|0;n=D;I=Pd(u|0,r|0,50)|0;n=n|D;e=Rd(u|0,r|0,18)|0;K=D;v=Pd(u|0,r|0,46)|0;K=n^(K|D);n=Rd(u|0,r|0,41)|0;l=D;x=Pd(u|0,r|0,23)|0;l=K^(l|D);K=c[h+80+600>>2]|0;J=c[h+80+600+4>>2]|0;j=oe(b|0,j|0,-1676669620,1126000580)|0;l=oe(j|0,D|0,(t|I)^(e|v)^(n|x)|0,l|0)|0;J=oe(l|0,D|0,K|0,J|0)|0;J=oe(J|0,D|0,(o^z)&u^o|0,(y^f)&r^y|0)|0;K=D;l=Rd(L|0,p|0,28)|0;x=D;n=Pd(L|0,p|0,36)|0;x=x|D;v=Rd(L|0,p|0,34)|0;e=D;I=Pd(L|0,p|0,30)|0;e=x^(e|D);x=Rd(L|0,p|0,39)|0;t=D;j=Pd(L|0,p|0,25)|0;b=c[G>>2]|0;s=c[G+4>>2]|0;t=oe((b|q)&L|b&q|0,(s|H)&p|s&H|0,(l|n)^(v|I)^(x|j)|0,e^(t|D)|0)|0;e=D;F=oe(E|0,F|0,J|0,K|0)|0;E=D;c[h+16>>2]=F;c[h+16+4>>2]=E;K=oe(t|0,e|0,J|0,K|0)|0;J=D;c[w>>2]=K;c[w+4>>2]=J;e=Rd(F|0,E|0,14)|0;t=D;j=Pd(F|0,E|0,50)|0;t=t|D;x=Rd(F|0,E|0,18)|0;I=D;v=Pd(F|0,E|0,46)|0;I=t^(I|D);t=Rd(F|0,E|0,41)|0;n=D;l=Pd(F|0,E|0,23)|0;n=I^(n|D);I=c[h+80+608>>2]|0;H=c[h+80+608+4>>2]|0;y=oe(o|0,y|0,-885112138,1288033470)|0;n=oe(y|0,D|0,(e|j)^(x|v)^(t|l)|0,n|0)|0;H=oe(n|0,D|0,I|0,H|0)|0;H=oe(H|0,D|0,(z^u)&F^z|0,(f^r)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;j=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;o=c[k>>2]|0;q=c[k+4>>2]|0;e=oe((o|L)&K|o&L|0,(q|p)&J|q&p|0,(n|t)^(v|j)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[G>>2]=s;c[G+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[m>>2]=I;c[m+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;G=Pd(s|0,b|0,50)|0;e=e|D;y=Rd(s|0,b|0,18)|0;l=D;j=Pd(s|0,b|0,46)|0;l=e^(l|D);e=Rd(s|0,b|0,41)|0;v=D;t=Pd(s|0,b|0,23)|0;v=l^(v|D);l=c[h+80+616>>2]|0;n=c[h+80+616+4>>2]|0;f=oe(z|0,f|0,-60457430,1501505948)|0;v=oe(f|0,D|0,(x|G)^(y|j)^(e|t)|0,v|0)|0;n=oe(v|0,D|0,l|0,n|0)|0;n=oe(n|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;l=D;v=Rd(I|0,H|0,28)|0;t=D;e=Pd(I|0,H|0,36)|0;t=t|D;j=Rd(I|0,H|0,34)|0;y=D;G=Pd(I|0,H|0,30)|0;y=t^(y|D);t=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;z=c[A>>2]|0;p=c[A+4>>2]|0;x=oe((z|K)&I|z&K|0,(p|J)&H|p&J|0,(v|e)^(j|G)^(t|f)|0,y^(x|D)|0)|0;y=D;q=oe(o|0,q|0,n|0,l|0)|0;o=D;c[k>>2]=q;c[k+4>>2]=o;l=oe(x|0,y|0,n|0,l|0)|0;n=D;c[B>>2]=l;c[B+4>>2]=n;B=Rd(q|0,o|0,14)|0;y=D;x=Pd(q|0,o|0,50)|0;y=y|D;k=Rd(q|0,o|0,18)|0;f=D;t=Pd(q|0,o|0,46)|0;f=y^(f|D);y=Rd(q|0,o|0,41)|0;G=D;j=Pd(q|0,o|0,23)|0;G=f^(G|D);f=c[h+80+624>>2]|0;e=c[h+80+624+4>>2]|0;r=oe(u|0,r|0,987167468,1607167915)|0;G=oe(r|0,D|0,(B|x)^(k|t)^(y|j)|0,G|0)|0;e=oe(G|0,D|0,f|0,e|0)|0;e=oe(e|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;f=D;G=Rd(l|0,n|0,28)|0;j=D;y=Pd(l|0,n|0,36)|0;j=j|D;t=Rd(l|0,n|0,34)|0;k=D;x=Pd(l|0,n|0,30)|0;k=j^(k|D);j=Rd(l|0,n|0,39)|0;B=D;r=Pd(l|0,n|0,25)|0;u=c[w>>2]|0;v=c[w+4>>2]|0;B=oe((u|I)&l|u&I|0,(v|H)&n|v&H|0,(G|y)^(t|x)^(j|r)|0,k^(B|D)|0)|0;k=D;p=oe(z|0,p|0,e|0,f|0)|0;z=D;c[A>>2]=p;c[A+4>>2]=z;f=oe(B|0,k|0,e|0,f|0)|0;e=D;c[C>>2]=f;c[C+4>>2]=e;C=Rd(p|0,z|0,14)|0;k=D;B=Pd(p|0,z|0,50)|0;k=k|D;A=Rd(p|0,z|0,18)|0;r=D;j=Pd(p|0,z|0,46)|0;r=k^(r|D);k=Rd(p|0,z|0,41)|0;x=D;t=Pd(p|0,z|0,23)|0;x=r^(x|D);r=c[h+80+632>>2]|0;y=c[h+80+632+4>>2]|0;E=oe(F|0,E|0,1246189591,1816402316)|0;x=oe(E|0,D|0,(C|B)^(A|j)^(k|t)|0,x|0)|0;y=oe(x|0,D|0,r|0,y|0)|0;b=oe(y|0,D|0,(s^q)&p^s|0,(b^o)&z^b|0)|0;z=D;c[h+8>>2]=b;c[h+8+4>>2]=z;o=Rd(f|0,e|0,28)|0;s=D;p=Pd(f|0,e|0,36)|0;s=s|D;q=Rd(f|0,e|0,34)|0;y=D;r=Pd(f|0,e|0,30)|0;y=s^(y|D);s=Rd(f|0,e|0,39)|0;x=D;t=Pd(f|0,e|0,25)|0;k=c[m>>2]|0;m=c[m+4>>2]|0;x=oe((k|l)&f|k&l|0,(m|n)&e|m&n|0,(o|p)^(q|r)^(s|t)|0,y^(x|D)|0)|0;y=D;c[h>>2]=x;c[h+4>>2]=y;v=oe(u|0,v|0,b|0,z|0)|0;c[w>>2]=v;c[w+4>>2]=D;z=oe(x|0,y|0,b|0,z|0)|0;b=D;c[h+16>>2]=z;c[h+16+4>>2]=b;b=oe(c[a>>2]|0,c[a+4>>2]|0,z|0,b|0)|0;c[a>>2]=b;c[a+4>>2]=D;b=1;while(1){M=a+(b<<3)|0;e=oe(c[M>>2]|0,c[M+4>>2]|0,f|0,e|0)|0;c[M>>2]=e;c[M+4>>2]=D;e=b+1|0;if((e|0)==8)break;b=e;f=c[h+16+(e<<3)>>2]|0;e=c[h+16+(e<<3)+4>>2]|0}fd(h+80|0,640);fd(h+16|0,64);fd(h+8|0,8);fd(h,8);i=g;return}function ia(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0;O=i;P=i=i+63&-64;i=i+128|0;v=d[b>>0]|d[b+1>>0]<<8|d[b+2>>0]<<16|d[b+3>>0]<<24;H=d[b+4>>0]|d[b+4+1>>0]<<8|d[b+4+2>>0]<<16|d[b+4+3>>0]<<24;h=d[b+8>>0]|d[b+8+1>>0]<<8|d[b+8+2>>0]<<16|d[b+8+3>>0]<<24;j=d[b+8+4>>0]|d[b+8+4+1>>0]<<8|d[b+8+4+2>>0]<<16|d[b+8+4+3>>0]<<24;k=d[b+16>>0]|d[b+16+1>>0]<<8|d[b+16+2>>0]<<16|d[b+16+3>>0]<<24;l=d[b+16+4>>0]|d[b+16+4+1>>0]<<8|d[b+16+4+2>>0]<<16|d[b+16+4+3>>0]<<24;m=d[b+24>>0]|d[b+24+1>>0]<<8|d[b+24+2>>0]<<16|d[b+24+3>>0]<<24;n=d[b+24+4>>0]|d[b+24+4+1>>0]<<8|d[b+24+4+2>>0]<<16|d[b+24+4+3>>0]<<24;o=d[b+32>>0]|d[b+32+1>>0]<<8|d[b+32+2>>0]<<16|d[b+32+3>>0]<<24;p=d[b+32+4>>0]|d[b+32+4+1>>0]<<8|d[b+32+4+2>>0]<<16|d[b+32+4+3>>0]<<24;q=d[b+40>>0]|d[b+40+1>>0]<<8|d[b+40+2>>0]<<16|d[b+40+3>>0]<<24;r=d[b+40+4>>0]|d[b+40+4+1>>0]<<8|d[b+40+4+2>>0]<<16|d[b+40+4+3>>0]<<24;s=d[b+48>>0]|d[b+48+1>>0]<<8|d[b+48+2>>0]<<16|d[b+48+3>>0]<<24;t=d[b+48+4>>0]|d[b+48+4+1>>0]<<8|d[b+48+4+2>>0]<<16|d[b+48+4+3>>0]<<24;u=d[b+56>>0]|d[b+56+1>>0]<<8|d[b+56+2>>0]<<16|d[b+56+3>>0]<<24;w=d[b+56+4>>0]|d[b+56+4+1>>0]<<8|d[b+56+4+2>>0]<<16|d[b+56+4+3>>0]<<24;x=d[b+64>>0]|d[b+64+1>>0]<<8|d[b+64+2>>0]<<16|d[b+64+3>>0]<<24;y=d[b+64+4>>0]|d[b+64+4+1>>0]<<8|d[b+64+4+2>>0]<<16|d[b+64+4+3>>0]<<24;z=d[b+72>>0]|d[b+72+1>>0]<<8|d[b+72+2>>0]<<16|d[b+72+3>>0]<<24;A=d[b+72+4>>0]|d[b+72+4+1>>0]<<8|d[b+72+4+2>>0]<<16|d[b+72+4+3>>0]<<24;B=d[b+80>>0]|d[b+80+1>>0]<<8|d[b+80+2>>0]<<16|d[b+80+3>>0]<<24;C=d[b+80+4>>0]|d[b+80+4+1>>0]<<8|d[b+80+4+2>>0]<<16|d[b+80+4+3>>0]<<24;E=d[b+88>>0]|d[b+88+1>>0]<<8|d[b+88+2>>0]<<16|d[b+88+3>>0]<<24;F=d[b+88+4>>0]|d[b+88+4+1>>0]<<8|d[b+88+4+2>>0]<<16|d[b+88+4+3>>0]<<24;G=d[b+96>>0]|d[b+96+1>>0]<<8|d[b+96+2>>0]<<16|d[b+96+3>>0]<<24;I=d[b+96+4>>0]|d[b+96+4+1>>0]<<8|d[b+96+4+2>>0]<<16|d[b+96+4+3>>0]<<24;J=d[b+104>>0]|d[b+104+1>>0]<<8|d[b+104+2>>0]<<16|d[b+104+3>>0]<<24;K=d[b+104+4>>0]|d[b+104+4+1>>0]<<8|d[b+104+4+2>>0]<<16|d[b+104+4+3>>0]<<24;L=d[b+112>>0]|d[b+112+1>>0]<<8|d[b+112+2>>0]<<16|d[b+112+3>>0]<<24;M=d[b+112+4>>0]|d[b+112+4+1>>0]<<8|d[b+112+4+2>>0]<<16|d[b+112+4+3>>0]<<24;N=d[b+120>>0]|d[b+120+1>>0]<<8|d[b+120+2>>0]<<16|d[b+120+3>>0]<<24;b=d[b+120+4>>0]|d[b+120+4+1>>0]<<8|d[b+120+4+2>>0]<<16|d[b+120+4+3>>0]<<24;e=P;f=a;g=e+64|0;do{c[e>>2]=c[f>>2];e=e+4|0;f=f+4|0}while((e|0)<(g|0));c[P+80>>2]=-23791573;c[P+80+4>>2]=1013904242;c[P+88>>2]=1595750129;c[P+88+4>>2]=-1521486534;Y=c[a+64>>2]^-1377402159;ha=c[a+64+4>>2]^1359893119;$=c[a+72>>2]^725511199;R=c[a+72+4>>2]^-1694144372;V=c[a+80>>2]^-79577749;ba=c[a+80+4>>2]^528734635;ka=c[a+88>>2]^327033209;ga=c[a+88+4>>2]^1541459225;c[P+120>>2]=ka;c[P+120+4>>2]=ga;X=c[P+32>>2]|0;da=c[P+32+4>>2]|0;la=oe(X|0,da|0,c[P>>2]|0,c[P+4>>2]|0)|0;la=oe(la|0,D|0,v|0,H|0)|0;ja=D;U=oe(ha^ja|0,Y^la|0,-205731576,1779033703)|0;ea=D;Z=Rd(X^U|0,da^ea|0,24)|0;e=D;da=Pd(X^U|0,da^ea|0,40)|0;e=D|e;X=oe(da|Z|0,e|0,la|0,ja|0)|0;X=oe(X|0,D|0,h|0,j|0)|0;Q=D;c[P>>2]=X;c[P+4>>2]=Q;_=Rd(ha^ja^X|0,Y^la^Q|0,16)|0;g=D;la=Pd(ha^ja^X|0,Y^la^Q|0,48)|0;g=D|g;c[P+96>>2]=la|_;c[P+96+4>>2]=g;ea=oe(la|_|0,g|0,U|0,ea|0)|0;U=D;c[P+64>>2]=ea;c[P+64+4>>2]=U;g=Rd((da|Z)^ea|0,e^U|0,63)|0;_=D;U=Pd((da|Z)^ea|0,e^U|0,1)|0;c[P+32>>2]=U|g;c[P+32+4>>2]=D|_;_=c[P+40>>2]|0;g=c[P+40+4>>2]|0;U=oe(_|0,g|0,c[P+8>>2]|0,c[P+8+4>>2]|0)|0;U=oe(U|0,D|0,k|0,l|0)|0;e=D;ea=oe(R^e|0,$^U|0,-2067093701,-1150833019)|0;Z=D;da=Rd(_^ea|0,g^Z|0,24)|0;la=D;g=Pd(_^ea|0,g^Z|0,40)|0;la=D|la;_=oe(g|da|0,la|0,U|0,e|0)|0;_=oe(_|0,D|0,m|0,n|0)|0;Y=D;c[P+8>>2]=_;c[P+8+4>>2]=Y;ja=Rd(R^e^_|0,$^U^Y|0,16)|0;ha=D;U=Pd(R^e^_|0,$^U^Y|0,48)|0;ha=D|ha;c[P+104>>2]=U|ja;c[P+104+4>>2]=ha;Z=oe(U|ja|0,ha|0,ea|0,Z|0)|0;ea=D;c[P+72>>2]=Z;c[P+72+4>>2]=ea;ha=Rd((g|da)^Z|0,la^ea|0,63)|0;ja=D;ea=Pd((g|da)^Z|0,la^ea|0,1)|0;ja=D|ja;la=c[P+48>>2]|0;Z=c[P+48+4>>2]|0;da=oe(la|0,Z|0,c[P+16>>2]|0,c[P+16+4>>2]|0)|0;da=oe(da|0,D|0,o|0,p|0)|0;g=D;U=oe(ba^g|0,V^da|0,-23791573,1013904242)|0;$=D;e=Rd(la^U|0,Z^$|0,24)|0;R=D;Z=Pd(la^U|0,Z^$|0,40)|0;R=D|R;la=oe(Z|e|0,R|0,da|0,g|0)|0;la=oe(la|0,D|0,q|0,r|0)|0;W=D;c[P+16>>2]=la;c[P+16+4>>2]=W;ia=Rd(ba^g^la|0,V^da^W|0,16)|0;fa=D;da=Pd(ba^g^la|0,V^da^W|0,48)|0;fa=D|fa;c[P+112>>2]=da|ia;c[P+112+4>>2]=fa;$=oe(da|ia|0,fa|0,U|0,$|0)|0;U=D;fa=Rd((Z|e)^$|0,R^U|0,63)|0;ia=D;R=Pd((Z|e)^$|0,R^U|0,1)|0;ia=D|ia;e=c[P+56>>2]|0;Z=c[P+56+4>>2]|0;da=oe(e|0,Z|0,c[P+24>>2]|0,c[P+24+4>>2]|0)|0;da=oe(da|0,D|0,s|0,t|0)|0;V=D;g=oe(ga^V|0,ka^da|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;ba=D;f=Rd(e^g|0,Z^ba|0,24)|0;aa=D;Z=Pd(e^g|0,Z^ba|0,40)|0;aa=D|aa;e=oe(Z|f|0,aa|0,da|0,V|0)|0;e=oe(e|0,D|0,u|0,w|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ca=Rd(ga^V^e|0,ka^da^S|0,16)|0;ma=D;da=Pd(ga^V^e|0,ka^da^S|0,48)|0;ma=D|ma;ba=oe(da|ca|0,ma|0,g|0,ba|0)|0;g=D;ka=Rd((Z|f)^ba|0,aa^g|0,63)|0;V=D;aa=Pd((Z|f)^ba|0,aa^g|0,1)|0;V=D|V;Q=oe(ea|ha|0,ja|0,X|0,Q|0)|0;Q=oe(Q|0,D|0,x|0,y|0)|0;X=D;U=oe(ma^X|0,(da|ca)^Q|0,$|0,U|0)|0;$=D;f=Rd((ea|ha)^U|0,ja^$|0,24)|0;Z=D;ja=Pd((ea|ha)^U|0,ja^$|0,40)|0;Z=D|Z;ha=oe(ja|f|0,Z|0,Q|0,X|0)|0;ha=oe(ha|0,D|0,z|0,A|0)|0;ea=D;c[P>>2]=ha;c[P+4>>2]=ea;ga=Rd(ma^X^ha|0,(da|ca)^Q^ea|0,16)|0;T=D;Q=Pd(ma^X^ha|0,(da|ca)^Q^ea|0,48)|0;T=D|T;c[P+120>>2]=Q|ga;c[P+120+4>>2]=T;$=oe(Q|ga|0,T|0,U|0,$|0)|0;U=D;c[P+80>>2]=$;c[P+80+4>>2]=U;T=Rd((ja|f)^$|0,Z^U|0,63)|0;ga=D;U=Pd((ja|f)^$|0,Z^U|0,1)|0;c[P+40>>2]=U|T;c[P+40+4>>2]=D|ga;Y=oe(R|fa|0,ia|0,_|0,Y|0)|0;Y=oe(Y|0,D|0,B|0,C|0)|0;_=D;ga=c[P+96>>2]^Y;T=c[P+96+4>>2]^_;g=oe(T|0,ga|0,ba|0,g|0)|0;ba=D;U=Rd((R|fa)^g|0,ia^ba|0,24)|0;Z=D;ia=Pd((R|fa)^g|0,ia^ba|0,40)|0;Z=D|Z;_=oe(ia|U|0,Z|0,Y|0,_|0)|0;_=oe(_|0,D|0,E|0,F|0)|0;Y=D;c[P+8>>2]=_;c[P+8+4>>2]=Y;fa=Rd(T^_|0,ga^Y|0,16)|0;R=D;ga=Pd(T^_|0,ga^Y|0,48)|0;R=D|R;ba=oe(ga|fa|0,R|0,g|0,ba|0)|0;g=D;c[P+88>>2]=ba;c[P+88+4>>2]=g;T=Rd((ia|U)^ba|0,Z^g|0,63)|0;$=D;g=Pd((ia|U)^ba|0,Z^g|0,1)|0;c[P+48>>2]=g|T;c[P+48+4>>2]=D|$;W=oe(aa|ka|0,V|0,la|0,W|0)|0;W=oe(W|0,D|0,G|0,I|0)|0;la=D;$=c[P+104>>2]^W;T=c[P+104+4>>2]^la;g=oe(T|0,$|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;Z=D;ba=Rd((aa|ka)^g|0,V^Z|0,24)|0;U=D;V=Pd((aa|ka)^g|0,V^Z|0,40)|0;U=D|U;la=oe(V|ba|0,U|0,W|0,la|0)|0;la=oe(la|0,D|0,J|0,K|0)|0;W=D;c[P+16>>2]=la;c[P+16+4>>2]=W;ka=Rd(T^la|0,$^W|0,16)|0;aa=D;$=Pd(T^la|0,$^W|0,48)|0;aa=D|aa;Z=oe($|ka|0,aa|0,g|0,Z|0)|0;g=D;T=Rd((V|ba)^Z|0,U^g|0,63)|0;ia=D;U=Pd((V|ba)^Z|0,U^g|0,1)|0;c[P+56>>2]=U|T;c[P+56+4>>2]=D|ia;ia=c[P+32>>2]|0;T=c[P+32+4>>2]|0;S=oe(ia|0,T|0,e|0,S|0)|0;S=oe(S|0,D|0,L|0,M|0)|0;e=D;U=c[P+112>>2]^S;ba=c[P+112+4>>2]^e;V=oe(ba|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;f=D;ja=Rd(ia^V|0,T^f|0,24)|0;Q=D;T=Pd(ia^V|0,T^f|0,40)|0;Q=D|Q;e=oe(T|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,N|0,b|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ia=Rd(ba^e|0,U^S|0,16)|0;ca=D;U=Pd(ba^e|0,U^S|0,48)|0;ca=D|ca;f=oe(U|ia|0,ca|0,V|0,f|0)|0;V=D;ba=Rd((T|ja)^f|0,Q^V|0,63)|0;da=D;Q=Pd((T|ja)^f|0,Q^V|0,1)|0;da=D|da;ea=oe(Q|ba|0,da|0,ha|0,ea|0)|0;ea=oe(ea|0,D|0,L|0,M|0)|0;ha=D;g=oe(R^ha|0,(ga|fa)^ea|0,Z|0,g|0)|0;Z=D;ja=Rd((Q|ba)^g|0,da^Z|0,24)|0;T=D;da=Pd((Q|ba)^g|0,da^Z|0,40)|0;T=D|T;ba=oe(da|ja|0,T|0,ea|0,ha|0)|0;ba=oe(ba|0,D|0,B|0,C|0)|0;Q=D;c[P>>2]=ba;c[P+4>>2]=Q;X=Rd(R^ha^ba|0,(ga|fa)^ea^Q|0,16)|0;ma=D;ea=Pd(R^ha^ba|0,(ga|fa)^ea^Q|0,48)|0;ma=D|ma;c[P+96>>2]=ea|X;c[P+96+4>>2]=ma;Z=oe(ea|X|0,ma|0,g|0,Z|0)|0;g=D;c[P+64>>2]=Z;c[P+64+4>>2]=g;ma=Rd((da|ja)^Z|0,T^g|0,63)|0;X=D;g=Pd((da|ja)^Z|0,T^g|0,1)|0;c[P+32>>2]=g|ma;c[P+32+4>>2]=D|X;X=c[P+40>>2]|0;ma=c[P+40+4>>2]|0;Y=oe(X|0,ma|0,_|0,Y|0)|0;Y=oe(Y|0,D|0,o|0,p|0)|0;_=D;V=oe(aa^_|0,($|ka)^Y|0,f|0,V|0)|0;f=D;g=Rd(X^V|0,ma^f|0,24)|0;T=D;ma=Pd(X^V|0,ma^f|0,40)|0;T=D|T;X=oe(ma|g|0,T|0,Y|0,_|0)|0;X=oe(X|0,D|0,x|0,y|0)|0;Z=D;c[P+8>>2]=X;c[P+8+4>>2]=Z;ja=Rd(aa^_^X|0,($|ka)^Y^Z|0,16)|0;da=D;Y=Pd(aa^_^X|0,($|ka)^Y^Z|0,48)|0;da=D|da;c[P+104>>2]=Y|ja;c[P+104+4>>2]=da;f=oe(Y|ja|0,da|0,V|0,f|0)|0;V=D;c[P+72>>2]=f;c[P+72+4>>2]=V;da=Rd((ma|g)^f|0,T^V|0,63)|0;ja=D;V=Pd((ma|g)^f|0,T^V|0,1)|0;ja=D|ja;T=c[P+48>>2]|0;f=c[P+48+4>>2]|0;W=oe(T|0,f|0,la|0,W|0)|0;W=oe(W|0,D|0,z|0,A|0)|0;la=D;g=oe(ca^la|0,(U|ia)^W|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;ma=D;Y=Rd(T^g|0,f^ma|0,24)|0;ka=D;f=Pd(T^g|0,f^ma|0,40)|0;ka=D|ka;T=oe(f|Y|0,ka|0,W|0,la|0)|0;T=oe(T|0,D|0,N|0,b|0)|0;$=D;c[P+16>>2]=T;c[P+16+4>>2]=$;_=Rd(ca^la^T|0,(U|ia)^W^$|0,16)|0;aa=D;W=Pd(ca^la^T|0,(U|ia)^W^$|0,48)|0;aa=D|aa;c[P+112>>2]=W|_;c[P+112+4>>2]=aa;ma=oe(W|_|0,aa|0,g|0,ma|0)|0;g=D;aa=Rd((f|Y)^ma|0,ka^g|0,63)|0;_=D;ka=Pd((f|Y)^ma|0,ka^g|0,1)|0;_=D|_;Y=c[P+56>>2]|0;f=c[P+56+4>>2]|0;S=oe(Y|0,f|0,e|0,S|0)|0;S=oe(S|0,D|0,J|0,K|0)|0;e=D;W=c[P+120>>2]^S;ia=c[P+120+4>>2]^e;U=oe(ia|0,W|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;la=D;ca=Rd(Y^U|0,f^la|0,24)|0;ea=D;f=Pd(Y^U|0,f^la|0,40)|0;ea=D|ea;e=oe(f|ca|0,ea|0,S|0,e|0)|0;e=oe(e|0,D|0,s|0,t|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Y=Rd(ia^e|0,W^S|0,16)|0;fa=D;W=Pd(ia^e|0,W^S|0,48)|0;fa=D|fa;la=oe(W|Y|0,fa|0,U|0,la|0)|0;U=D;ia=Rd((f|ca)^la|0,ea^U|0,63)|0;ga=D;ea=Pd((f|ca)^la|0,ea^U|0,1)|0;ga=D|ga;Q=oe(V|da|0,ja|0,ba|0,Q|0)|0;Q=oe(Q|0,D|0,h|0,j|0)|0;ba=D;g=oe(fa^ba|0,(W|Y)^Q|0,ma|0,g|0)|0;ma=D;ca=Rd((V|da)^g|0,ja^ma|0,24)|0;f=D;ja=Pd((V|da)^g|0,ja^ma|0,40)|0;f=D|f;da=oe(ja|ca|0,f|0,Q|0,ba|0)|0;da=oe(da|0,D|0,G|0,I|0)|0;V=D;c[P>>2]=da;c[P+4>>2]=V;ha=Rd(fa^ba^da|0,(W|Y)^Q^V|0,16)|0;R=D;Q=Pd(fa^ba^da|0,(W|Y)^Q^V|0,48)|0;R=D|R;c[P+120>>2]=Q|ha;c[P+120+4>>2]=R;ma=oe(Q|ha|0,R|0,g|0,ma|0)|0;g=D;c[P+80>>2]=ma;c[P+80+4>>2]=g;R=Rd((ja|ca)^ma|0,f^g|0,63)|0;ha=D;g=Pd((ja|ca)^ma|0,f^g|0,1)|0;c[P+40>>2]=g|R;c[P+40+4>>2]=D|ha;Z=oe(ka|aa|0,_|0,X|0,Z|0)|0;Z=oe(Z|0,D|0,v|0,H|0)|0;X=D;ha=c[P+96>>2]^Z;R=c[P+96+4>>2]^X;U=oe(R|0,ha|0,la|0,U|0)|0;la=D;g=Rd((ka|aa)^U|0,_^la|0,24)|0;f=D;_=Pd((ka|aa)^U|0,_^la|0,40)|0;f=D|f;X=oe(_|g|0,f|0,Z|0,X|0)|0;X=oe(X|0,D|0,k|0,l|0)|0;Z=D;c[P+8>>2]=X;c[P+8+4>>2]=Z;aa=Rd(R^X|0,ha^Z|0,16)|0;ka=D;ha=Pd(R^X|0,ha^Z|0,48)|0;ka=D|ka;la=oe(ha|aa|0,ka|0,U|0,la|0)|0;U=D;c[P+88>>2]=la;c[P+88+4>>2]=U;R=Rd((_|g)^la|0,f^U|0,63)|0;ma=D;U=Pd((_|g)^la|0,f^U|0,1)|0;c[P+48>>2]=U|R;c[P+48+4>>2]=D|ma;$=oe(ea|ia|0,ga|0,T|0,$|0)|0;$=oe($|0,D|0,E|0,F|0)|0;T=D;ma=c[P+104>>2]^$;R=c[P+104+4>>2]^T;U=oe(R|0,ma|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;f=D;la=Rd((ea|ia)^U|0,ga^f|0,24)|0;g=D;ga=Pd((ea|ia)^U|0,ga^f|0,40)|0;g=D|g;T=oe(ga|la|0,g|0,$|0,T|0)|0;T=oe(T|0,D|0,u|0,w|0)|0;$=D;c[P+16>>2]=T;c[P+16+4>>2]=$;ia=Rd(R^T|0,ma^$|0,16)|0;ea=D;ma=Pd(R^T|0,ma^$|0,48)|0;ea=D|ea;f=oe(ma|ia|0,ea|0,U|0,f|0)|0;U=D;R=Rd((ga|la)^f|0,g^U|0,63)|0;_=D;g=Pd((ga|la)^f|0,g^U|0,1)|0;c[P+56>>2]=g|R;c[P+56+4>>2]=D|_;_=c[P+32>>2]|0;R=c[P+32+4>>2]|0;S=oe(_|0,R|0,e|0,S|0)|0;S=oe(S|0,D|0,q|0,r|0)|0;e=D;g=c[P+112>>2]^S;la=c[P+112+4>>2]^e;ga=oe(la|0,g|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;ca=D;ja=Rd(_^ga|0,R^ca|0,24)|0;Q=D;R=Pd(_^ga|0,R^ca|0,40)|0;Q=D|Q;e=oe(R|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,m|0,n|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;_=Rd(la^e|0,g^S|0,16)|0;Y=D;g=Pd(la^e|0,g^S|0,48)|0;Y=D|Y;ca=oe(g|_|0,Y|0,ga|0,ca|0)|0;ga=D;la=Rd((R|ja)^ca|0,Q^ga|0,63)|0;W=D;Q=Pd((R|ja)^ca|0,Q^ga|0,1)|0;W=D|W;V=oe(Q|la|0,W|0,da|0,V|0)|0;V=oe(V|0,D|0,E|0,F|0)|0;da=D;U=oe(ka^da|0,(ha|aa)^V|0,f|0,U|0)|0;f=D;ja=Rd((Q|la)^U|0,W^f|0,24)|0;R=D;W=Pd((Q|la)^U|0,W^f|0,40)|0;R=D|R;la=oe(W|ja|0,R|0,V|0,da|0)|0;la=oe(la|0,D|0,x|0,y|0)|0;Q=D;c[P>>2]=la;c[P+4>>2]=Q;ba=Rd(ka^da^la|0,(ha|aa)^V^Q|0,16)|0;fa=D;V=Pd(ka^da^la|0,(ha|aa)^V^Q|0,48)|0;fa=D|fa;c[P+96>>2]=V|ba;c[P+96+4>>2]=fa;f=oe(V|ba|0,fa|0,U|0,f|0)|0;U=D;c[P+64>>2]=f;c[P+64+4>>2]=U;fa=Rd((W|ja)^f|0,R^U|0,63)|0;ba=D;U=Pd((W|ja)^f|0,R^U|0,1)|0;c[P+32>>2]=U|fa;c[P+32+4>>2]=D|ba;ba=c[P+40>>2]|0;fa=c[P+40+4>>2]|0;Z=oe(ba|0,fa|0,X|0,Z|0)|0;Z=oe(Z|0,D|0,G|0,I|0)|0;X=D;ga=oe(ea^X|0,(ma|ia)^Z|0,ca|0,ga|0)|0;ca=D;U=Rd(ba^ga|0,fa^ca|0,24)|0;R=D;fa=Pd(ba^ga|0,fa^ca|0,40)|0;R=D|R;ba=oe(fa|U|0,R|0,Z|0,X|0)|0;ba=oe(ba|0,D|0,v|0,H|0)|0;f=D;c[P+8>>2]=ba;c[P+8+4>>2]=f;ja=Rd(ea^X^ba|0,(ma|ia)^Z^f|0,16)|0;W=D;Z=Pd(ea^X^ba|0,(ma|ia)^Z^f|0,48)|0;W=D|W;c[P+104>>2]=Z|ja;c[P+104+4>>2]=W;ca=oe(Z|ja|0,W|0,ga|0,ca|0)|0;ga=D;c[P+72>>2]=ca;c[P+72+4>>2]=ga;W=Rd((fa|U)^ca|0,R^ga|0,63)|0;ja=D;ga=Pd((fa|U)^ca|0,R^ga|0,1)|0;ja=D|ja;R=c[P+48>>2]|0;ca=c[P+48+4>>2]|0;$=oe(R|0,ca|0,T|0,$|0)|0;$=oe($|0,D|0,q|0,r|0)|0;T=D;U=oe(Y^T|0,(g|_)^$|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;fa=D;Z=Rd(R^U|0,ca^fa|0,24)|0;ia=D;ca=Pd(R^U|0,ca^fa|0,40)|0;ia=D|ia;R=oe(ca|Z|0,ia|0,$|0,T|0)|0;R=oe(R|0,D|0,k|0,l|0)|0;ma=D;c[P+16>>2]=R;c[P+16+4>>2]=ma;X=Rd(Y^T^R|0,(g|_)^$^ma|0,16)|0;ea=D;$=Pd(Y^T^R|0,(g|_)^$^ma|0,48)|0;ea=D|ea;c[P+112>>2]=$|X;c[P+112+4>>2]=ea;fa=oe($|X|0,ea|0,U|0,fa|0)|0;U=D;ea=Rd((ca|Z)^fa|0,ia^U|0,63)|0;X=D;ia=Pd((ca|Z)^fa|0,ia^U|0,1)|0;X=D|X;Z=c[P+56>>2]|0;ca=c[P+56+4>>2]|0;S=oe(Z|0,ca|0,e|0,S|0)|0;S=oe(S|0,D|0,N|0,b|0)|0;e=D;$=c[P+120>>2]^S;_=c[P+120+4>>2]^e;g=oe(_|0,$|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;T=D;Y=Rd(Z^g|0,ca^T|0,24)|0;V=D;ca=Pd(Z^g|0,ca^T|0,40)|0;V=D|V;e=oe(ca|Y|0,V|0,S|0,e|0)|0;e=oe(e|0,D|0,J|0,K|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Z=Rd(_^e|0,$^S|0,16)|0;aa=D;$=Pd(_^e|0,$^S|0,48)|0;aa=D|aa;T=oe($|Z|0,aa|0,g|0,T|0)|0;g=D;_=Rd((ca|Y)^T|0,V^g|0,63)|0;ha=D;V=Pd((ca|Y)^T|0,V^g|0,1)|0;ha=D|ha;Q=oe(ga|W|0,ja|0,la|0,Q|0)|0;Q=oe(Q|0,D|0,B|0,C|0)|0;la=D;U=oe(aa^la|0,($|Z)^Q|0,fa|0,U|0)|0;fa=D;Y=Rd((ga|W)^U|0,ja^fa|0,24)|0;ca=D;ja=Pd((ga|W)^U|0,ja^fa|0,40)|0;ca=D|ca;W=oe(ja|Y|0,ca|0,Q|0,la|0)|0;W=oe(W|0,D|0,L|0,M|0)|0;ga=D;c[P>>2]=W;c[P+4>>2]=ga;da=Rd(aa^la^W|0,($|Z)^Q^ga|0,16)|0;ka=D;Q=Pd(aa^la^W|0,($|Z)^Q^ga|0,48)|0;ka=D|ka;c[P+120>>2]=Q|da;c[P+120+4>>2]=ka;fa=oe(Q|da|0,ka|0,U|0,fa|0)|0;U=D;c[P+80>>2]=fa;c[P+80+4>>2]=U;ka=Rd((ja|Y)^fa|0,ca^U|0,63)|0;da=D;U=Pd((ja|Y)^fa|0,ca^U|0,1)|0;c[P+40>>2]=U|ka;c[P+40+4>>2]=D|da;f=oe(ia|ea|0,X|0,ba|0,f|0)|0;f=oe(f|0,D|0,m|0,n|0)|0;ba=D;da=c[P+96>>2]^f;ka=c[P+96+4>>2]^ba;g=oe(ka|0,da|0,T|0,g|0)|0;T=D;U=Rd((ia|ea)^g|0,X^T|0,24)|0;ca=D;X=Pd((ia|ea)^g|0,X^T|0,40)|0;ca=D|ca;ba=oe(X|U|0,ca|0,f|0,ba|0)|0;ba=oe(ba|0,D|0,s|0,t|0)|0;f=D;c[P+8>>2]=ba;c[P+8+4>>2]=f;ea=Rd(ka^ba|0,da^f|0,16)|0;ia=D;da=Pd(ka^ba|0,da^f|0,48)|0;ia=D|ia;T=oe(da|ea|0,ia|0,g|0,T|0)|0;g=D;c[P+88>>2]=T;c[P+88+4>>2]=g;ka=Rd((X|U)^T|0,ca^g|0,63)|0;fa=D;g=Pd((X|U)^T|0,ca^g|0,1)|0;c[P+48>>2]=g|ka;c[P+48+4>>2]=D|fa;ma=oe(V|_|0,ha|0,R|0,ma|0)|0;ma=oe(ma|0,D|0,u|0,w|0)|0;R=D;fa=c[P+104>>2]^ma;ka=c[P+104+4>>2]^R;g=oe(ka|0,fa|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;ca=D;T=Rd((V|_)^g|0,ha^ca|0,24)|0;U=D;ha=Pd((V|_)^g|0,ha^ca|0,40)|0;U=D|U;R=oe(ha|T|0,U|0,ma|0,R|0)|0;R=oe(R|0,D|0,h|0,j|0)|0;ma=D;c[P+16>>2]=R;c[P+16+4>>2]=ma;_=Rd(ka^R|0,fa^ma|0,16)|0;V=D;fa=Pd(ka^R|0,fa^ma|0,48)|0;V=D|V;ca=oe(fa|_|0,V|0,g|0,ca|0)|0;g=D;ka=Rd((ha|T)^ca|0,U^g|0,63)|0;X=D;U=Pd((ha|T)^ca|0,U^g|0,1)|0;c[P+56>>2]=U|ka;c[P+56+4>>2]=D|X;X=c[P+32>>2]|0;ka=c[P+32+4>>2]|0;S=oe(X|0,ka|0,e|0,S|0)|0;S=oe(S|0,D|0,z|0,A|0)|0;e=D;U=c[P+112>>2]^S;T=c[P+112+4>>2]^e;ha=oe(T|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;Y=D;ja=Rd(X^ha|0,ka^Y|0,24)|0;Q=D;ka=Pd(X^ha|0,ka^Y|0,40)|0;Q=D|Q;e=oe(ka|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,o|0,p|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;X=Rd(T^e|0,U^S|0,16)|0;Z=D;U=Pd(T^e|0,U^S|0,48)|0;Z=D|Z;Y=oe(U|X|0,Z|0,ha|0,Y|0)|0;ha=D;T=Rd((ka|ja)^Y|0,Q^ha|0,63)|0;$=D;Q=Pd((ka|ja)^Y|0,Q^ha|0,1)|0;$=D|$;ga=oe(Q|T|0,$|0,W|0,ga|0)|0;ga=oe(ga|0,D|0,u|0,w|0)|0;W=D;g=oe(ia^W|0,(da|ea)^ga|0,ca|0,g|0)|0;ca=D;ja=Rd((Q|T)^g|0,$^ca|0,24)|0;ka=D;$=Pd((Q|T)^g|0,$^ca|0,40)|0;ka=D|ka;T=oe($|ja|0,ka|0,ga|0,W|0)|0;T=oe(T|0,D|0,z|0,A|0)|0;Q=D;c[P>>2]=T;c[P+4>>2]=Q;la=Rd(ia^W^T|0,(da|ea)^ga^Q|0,16)|0;aa=D;ga=Pd(ia^W^T|0,(da|ea)^ga^Q|0,48)|0;aa=D|aa;c[P+96>>2]=ga|la;c[P+96+4>>2]=aa;ca=oe(ga|la|0,aa|0,g|0,ca|0)|0;g=D;c[P+64>>2]=ca;c[P+64+4>>2]=g;aa=Rd(($|ja)^ca|0,ka^g|0,63)|0;la=D;g=Pd(($|ja)^ca|0,ka^g|0,1)|0;c[P+32>>2]=g|aa;c[P+32+4>>2]=D|la;la=c[P+40>>2]|0;aa=c[P+40+4>>2]|0;f=oe(la|0,aa|0,ba|0,f|0)|0;f=oe(f|0,D|0,m|0,n|0)|0;ba=D;ha=oe(V^ba|0,(fa|_)^f|0,Y|0,ha|0)|0;Y=D;g=Rd(la^ha|0,aa^Y|0,24)|0;ka=D;aa=Pd(la^ha|0,aa^Y|0,40)|0;ka=D|ka;la=oe(aa|g|0,ka|0,f|0,ba|0)|0;la=oe(la|0,D|0,h|0,j|0)|0;ca=D;c[P+8>>2]=la;c[P+8+4>>2]=ca;ja=Rd(V^ba^la|0,(fa|_)^f^ca|0,16)|0;$=D;f=Pd(V^ba^la|0,(fa|_)^f^ca|0,48)|0;$=D|$;c[P+104>>2]=f|ja;c[P+104+4>>2]=$;Y=oe(f|ja|0,$|0,ha|0,Y|0)|0;ha=D;c[P+72>>2]=Y;c[P+72+4>>2]=ha;$=Rd((aa|g)^Y|0,ka^ha|0,63)|0;ja=D;ha=Pd((aa|g)^Y|0,ka^ha|0,1)|0;ja=D|ja;ka=c[P+48>>2]|0;Y=c[P+48+4>>2]|0;ma=oe(ka|0,Y|0,R|0,ma|0)|0;ma=oe(ma|0,D|0,J|0,K|0)|0;R=D;g=oe(Z^R|0,(U|X)^ma|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;aa=D;f=Rd(ka^g|0,Y^aa|0,24)|0;_=D;Y=Pd(ka^g|0,Y^aa|0,40)|0;_=D|_;ka=oe(Y|f|0,_|0,ma|0,R|0)|0;ka=oe(ka|0,D|0,G|0,I|0)|0;fa=D;c[P+16>>2]=ka;c[P+16+4>>2]=fa;ba=Rd(Z^R^ka|0,(U|X)^ma^fa|0,16)|0;V=D;ma=Pd(Z^R^ka|0,(U|X)^ma^fa|0,48)|0;V=D|V;c[P+112>>2]=ma|ba;c[P+112+4>>2]=V;aa=oe(ma|ba|0,V|0,g|0,aa|0)|0;g=D;V=Rd((Y|f)^aa|0,_^g|0,63)|0;ba=D;_=Pd((Y|f)^aa|0,_^g|0,1)|0;ba=D|ba;f=c[P+56>>2]|0;Y=c[P+56+4>>2]|0;S=oe(f|0,Y|0,e|0,S|0)|0;S=oe(S|0,D|0,E|0,F|0)|0;e=D;ma=c[P+120>>2]^S;X=c[P+120+4>>2]^e;U=oe(X|0,ma|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;R=D;Z=Rd(f^U|0,Y^R|0,24)|0;ga=D;Y=Pd(f^U|0,Y^R|0,40)|0;ga=D|ga;e=oe(Y|Z|0,ga|0,S|0,e|0)|0;e=oe(e|0,D|0,L|0,M|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;f=Rd(X^e|0,ma^S|0,16)|0;ea=D;ma=Pd(X^e|0,ma^S|0,48)|0;ea=D|ea;R=oe(ma|f|0,ea|0,U|0,R|0)|0;U=D;X=Rd((Y|Z)^R|0,ga^U|0,63)|0;da=D;ga=Pd((Y|Z)^R|0,ga^U|0,1)|0;da=D|da;Q=oe(ha|$|0,ja|0,T|0,Q|0)|0;Q=oe(Q|0,D|0,k|0,l|0)|0;T=D;g=oe(ea^T|0,(ma|f)^Q|0,aa|0,g|0)|0;aa=D;Z=Rd((ha|$)^g|0,ja^aa|0,24)|0;Y=D;ja=Pd((ha|$)^g|0,ja^aa|0,40)|0;Y=D|Y;$=oe(ja|Z|0,Y|0,Q|0,T|0)|0;$=oe($|0,D|0,s|0,t|0)|0;ha=D;c[P>>2]=$;c[P+4>>2]=ha;W=Rd(ea^T^$|0,(ma|f)^Q^ha|0,16)|0;ia=D;Q=Pd(ea^T^$|0,(ma|f)^Q^ha|0,48)|0;ia=D|ia;c[P+120>>2]=Q|W;c[P+120+4>>2]=ia;aa=oe(Q|W|0,ia|0,g|0,aa|0)|0;g=D;c[P+80>>2]=aa;c[P+80+4>>2]=g;ia=Rd((ja|Z)^aa|0,Y^g|0,63)|0;W=D;g=Pd((ja|Z)^aa|0,Y^g|0,1)|0;c[P+40>>2]=g|ia;c[P+40+4>>2]=D|W;ca=oe(_|V|0,ba|0,la|0,ca|0)|0;ca=oe(ca|0,D|0,q|0,r|0)|0;la=D;W=c[P+96>>2]^ca;ia=c[P+96+4>>2]^la;U=oe(ia|0,W|0,R|0,U|0)|0;R=D;g=Rd((_|V)^U|0,ba^R|0,24)|0;Y=D;ba=Pd((_|V)^U|0,ba^R|0,40)|0;Y=D|Y;la=oe(ba|g|0,Y|0,ca|0,la|0)|0;la=oe(la|0,D|0,B|0,C|0)|0;ca=D;c[P+8>>2]=la;c[P+8+4>>2]=ca;V=Rd(ia^la|0,W^ca|0,16)|0;_=D;W=Pd(ia^la|0,W^ca|0,48)|0;_=D|_;R=oe(W|V|0,_|0,U|0,R|0)|0;U=D;c[P+88>>2]=R;c[P+88+4>>2]=U;ia=Rd((ba|g)^R|0,Y^U|0,63)|0;aa=D;U=Pd((ba|g)^R|0,Y^U|0,1)|0;c[P+48>>2]=U|ia;c[P+48+4>>2]=D|aa;fa=oe(ga|X|0,da|0,ka|0,fa|0)|0;fa=oe(fa|0,D|0,o|0,p|0)|0;ka=D;aa=c[P+104>>2]^fa;ia=c[P+104+4>>2]^ka;U=oe(ia|0,aa|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;Y=D;R=Rd((ga|X)^U|0,da^Y|0,24)|0;g=D;da=Pd((ga|X)^U|0,da^Y|0,40)|0;g=D|g;ka=oe(da|R|0,g|0,fa|0,ka|0)|0;ka=oe(ka|0,D|0,v|0,H|0)|0;fa=D;c[P+16>>2]=ka;c[P+16+4>>2]=fa;X=Rd(ia^ka|0,aa^fa|0,16)|0;ga=D;aa=Pd(ia^ka|0,aa^fa|0,48)|0;ga=D|ga;Y=oe(aa|X|0,ga|0,U|0,Y|0)|0;U=D;ia=Rd((da|R)^Y|0,g^U|0,63)|0;ba=D;g=Pd((da|R)^Y|0,g^U|0,1)|0;c[P+56>>2]=g|ia;c[P+56+4>>2]=D|ba;ba=c[P+32>>2]|0;ia=c[P+32+4>>2]|0;S=oe(ba|0,ia|0,e|0,S|0)|0;S=oe(S|0,D|0,N|0,b|0)|0;e=D;g=c[P+112>>2]^S;R=c[P+112+4>>2]^e;da=oe(R|0,g|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;Z=D;ja=Rd(ba^da|0,ia^Z|0,24)|0;Q=D;ia=Pd(ba^da|0,ia^Z|0,40)|0;Q=D|Q;e=oe(ia|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,x|0,y|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ba=Rd(R^e|0,g^S|0,16)|0;f=D;g=Pd(R^e|0,g^S|0,48)|0;f=D|f;Z=oe(g|ba|0,f|0,da|0,Z|0)|0;da=D;R=Rd((ia|ja)^Z|0,Q^da|0,63)|0;ma=D;Q=Pd((ia|ja)^Z|0,Q^da|0,1)|0;ma=D|ma;ha=oe(Q|R|0,ma|0,$|0,ha|0)|0;ha=oe(ha|0,D|0,z|0,A|0)|0;$=D;U=oe(_^$|0,(W|V)^ha|0,Y|0,U|0)|0;Y=D;ja=Rd((Q|R)^U|0,ma^Y|0,24)|0;ia=D;ma=Pd((Q|R)^U|0,ma^Y|0,40)|0;ia=D|ia;R=oe(ma|ja|0,ia|0,ha|0,$|0)|0;R=oe(R|0,D|0,v|0,H|0)|0;Q=D;c[P>>2]=R;c[P+4>>2]=Q;T=Rd(_^$^R|0,(W|V)^ha^Q|0,16)|0;ea=D;ha=Pd(_^$^R|0,(W|V)^ha^Q|0,48)|0;ea=D|ea;c[P+96>>2]=ha|T;c[P+96+4>>2]=ea;Y=oe(ha|T|0,ea|0,U|0,Y|0)|0;U=D;c[P+64>>2]=Y;c[P+64+4>>2]=U;ea=Rd((ma|ja)^Y|0,ia^U|0,63)|0;T=D;U=Pd((ma|ja)^Y|0,ia^U|0,1)|0;c[P+32>>2]=U|ea;c[P+32+4>>2]=D|T;T=c[P+40>>2]|0;ea=c[P+40+4>>2]|0;ca=oe(T|0,ea|0,la|0,ca|0)|0;ca=oe(ca|0,D|0,q|0,r|0)|0;la=D;da=oe(ga^la|0,(aa|X)^ca|0,Z|0,da|0)|0;Z=D;U=Rd(T^da|0,ea^Z|0,24)|0;ia=D;ea=Pd(T^da|0,ea^Z|0,40)|0;ia=D|ia;T=oe(ea|U|0,ia|0,ca|0,la|0)|0;T=oe(T|0,D|0,u|0,w|0)|0;Y=D;c[P+8>>2]=T;c[P+8+4>>2]=Y;ja=Rd(ga^la^T|0,(aa|X)^ca^Y|0,16)|0;ma=D;ca=Pd(ga^la^T|0,(aa|X)^ca^Y|0,48)|0;ma=D|ma;c[P+104>>2]=ca|ja;c[P+104+4>>2]=ma;Z=oe(ca|ja|0,ma|0,da|0,Z|0)|0;da=D;c[P+72>>2]=Z;c[P+72+4>>2]=da;ma=Rd((ea|U)^Z|0,ia^da|0,63)|0;ja=D;da=Pd((ea|U)^Z|0,ia^da|0,1)|0;ja=D|ja;ia=c[P+48>>2]|0;Z=c[P+48+4>>2]|0;fa=oe(ia|0,Z|0,ka|0,fa|0)|0;fa=oe(fa|0,D|0,k|0,l|0)|0;ka=D;U=oe(f^ka|0,(g|ba)^fa|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;ea=D;ca=Rd(ia^U|0,Z^ea|0,24)|0;X=D;Z=Pd(ia^U|0,Z^ea|0,40)|0;X=D|X;ia=oe(Z|ca|0,X|0,fa|0,ka|0)|0;ia=oe(ia|0,D|0,o|0,p|0)|0;aa=D;c[P+16>>2]=ia;c[P+16+4>>2]=aa;la=Rd(f^ka^ia|0,(g|ba)^fa^aa|0,16)|0;ga=D;fa=Pd(f^ka^ia|0,(g|ba)^fa^aa|0,48)|0;ga=D|ga;c[P+112>>2]=fa|la;c[P+112+4>>2]=ga;ea=oe(fa|la|0,ga|0,U|0,ea|0)|0;U=D;ga=Rd((Z|ca)^ea|0,X^U|0,63)|0;la=D;X=Pd((Z|ca)^ea|0,X^U|0,1)|0;la=D|la;ca=c[P+56>>2]|0;Z=c[P+56+4>>2]|0;S=oe(ca|0,Z|0,e|0,S|0)|0;S=oe(S|0,D|0,B|0,C|0)|0;e=D;fa=c[P+120>>2]^S;ba=c[P+120+4>>2]^e;g=oe(ba|0,fa|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;ka=D;f=Rd(ca^g|0,Z^ka|0,24)|0;ha=D;Z=Pd(ca^g|0,Z^ka|0,40)|0;ha=D|ha;e=oe(Z|f|0,ha|0,S|0,e|0)|0;e=oe(e|0,D|0,N|0,b|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ca=Rd(ba^e|0,fa^S|0,16)|0;V=D;fa=Pd(ba^e|0,fa^S|0,48)|0;V=D|V;ka=oe(fa|ca|0,V|0,g|0,ka|0)|0;g=D;ba=Rd((Z|f)^ka|0,ha^g|0,63)|0;W=D;ha=Pd((Z|f)^ka|0,ha^g|0,1)|0;W=D|W;Q=oe(da|ma|0,ja|0,R|0,Q|0)|0;Q=oe(Q|0,D|0,L|0,M|0)|0;R=D;U=oe(V^R|0,(fa|ca)^Q|0,ea|0,U|0)|0;ea=D;f=Rd((da|ma)^U|0,ja^ea|0,24)|0;Z=D;ja=Pd((da|ma)^U|0,ja^ea|0,40)|0;Z=D|Z;ma=oe(ja|f|0,Z|0,Q|0,R|0)|0;ma=oe(ma|0,D|0,h|0,j|0)|0;da=D;c[P>>2]=ma;c[P+4>>2]=da;$=Rd(V^R^ma|0,(fa|ca)^Q^da|0,16)|0;_=D;Q=Pd(V^R^ma|0,(fa|ca)^Q^da|0,48)|0;_=D|_;c[P+120>>2]=Q|$;c[P+120+4>>2]=_;ea=oe(Q|$|0,_|0,U|0,ea|0)|0;U=D;c[P+80>>2]=ea;c[P+80+4>>2]=U;_=Rd((ja|f)^ea|0,Z^U|0,63)|0;$=D;U=Pd((ja|f)^ea|0,Z^U|0,1)|0;c[P+40>>2]=U|_;c[P+40+4>>2]=D|$;Y=oe(X|ga|0,la|0,T|0,Y|0)|0;Y=oe(Y|0,D|0,E|0,F|0)|0;T=D;$=c[P+96>>2]^Y;_=c[P+96+4>>2]^T;g=oe(_|0,$|0,ka|0,g|0)|0;ka=D;U=Rd((X|ga)^g|0,la^ka|0,24)|0;Z=D;la=Pd((X|ga)^g|0,la^ka|0,40)|0;Z=D|Z;T=oe(la|U|0,Z|0,Y|0,T|0)|0;T=oe(T|0,D|0,G|0,I|0)|0;Y=D;c[P+8>>2]=T;c[P+8+4>>2]=Y;ga=Rd(_^T|0,$^Y|0,16)|0;X=D;$=Pd(_^T|0,$^Y|0,48)|0;X=D|X;ka=oe($|ga|0,X|0,g|0,ka|0)|0;g=D;c[P+88>>2]=ka;c[P+88+4>>2]=g;_=Rd((la|U)^ka|0,Z^g|0,63)|0;ea=D;g=Pd((la|U)^ka|0,Z^g|0,1)|0;c[P+48>>2]=g|_;c[P+48+4>>2]=D|ea;aa=oe(ha|ba|0,W|0,ia|0,aa|0)|0;aa=oe(aa|0,D|0,s|0,t|0)|0;ia=D;ea=c[P+104>>2]^aa;_=c[P+104+4>>2]^ia;g=oe(_|0,ea|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;Z=D;ka=Rd((ha|ba)^g|0,W^Z|0,24)|0;U=D;W=Pd((ha|ba)^g|0,W^Z|0,40)|0;U=D|U;ia=oe(W|ka|0,U|0,aa|0,ia|0)|0;ia=oe(ia|0,D|0,x|0,y|0)|0;aa=D;c[P+16>>2]=ia;c[P+16+4>>2]=aa;ba=Rd(_^ia|0,ea^aa|0,16)|0;ha=D;ea=Pd(_^ia|0,ea^aa|0,48)|0;ha=D|ha;Z=oe(ea|ba|0,ha|0,g|0,Z|0)|0;g=D;_=Rd((W|ka)^Z|0,U^g|0,63)|0;la=D;U=Pd((W|ka)^Z|0,U^g|0,1)|0;c[P+56>>2]=U|_;c[P+56+4>>2]=D|la;la=c[P+32>>2]|0;_=c[P+32+4>>2]|0;S=oe(la|0,_|0,e|0,S|0)|0;S=oe(S|0,D|0,m|0,n|0)|0;e=D;U=c[P+112>>2]^S;ka=c[P+112+4>>2]^e;W=oe(ka|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;f=D;ja=Rd(la^W|0,_^f|0,24)|0;Q=D;_=Pd(la^W|0,_^f|0,40)|0;Q=D|Q;e=oe(_|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,J|0,K|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;la=Rd(ka^e|0,U^S|0,16)|0;ca=D;U=Pd(ka^e|0,U^S|0,48)|0;ca=D|ca;f=oe(U|la|0,ca|0,W|0,f|0)|0;W=D;ka=Rd((_|ja)^f|0,Q^W|0,63)|0;fa=D;Q=Pd((_|ja)^f|0,Q^W|0,1)|0;fa=D|fa;da=oe(Q|ka|0,fa|0,ma|0,da|0)|0;da=oe(da|0,D|0,k|0,l|0)|0;ma=D;g=oe(X^ma|0,($|ga)^da|0,Z|0,g|0)|0;Z=D;ja=Rd((Q|ka)^g|0,fa^Z|0,24)|0;_=D;fa=Pd((Q|ka)^g|0,fa^Z|0,40)|0;_=D|_;ka=oe(fa|ja|0,_|0,da|0,ma|0)|0;ka=oe(ka|0,D|0,G|0,I|0)|0;Q=D;c[P>>2]=ka;c[P+4>>2]=Q;R=Rd(X^ma^ka|0,($|ga)^da^Q|0,16)|0;V=D;da=Pd(X^ma^ka|0,($|ga)^da^Q|0,48)|0;V=D|V;c[P+96>>2]=da|R;c[P+96+4>>2]=V;Z=oe(da|R|0,V|0,g|0,Z|0)|0;g=D;c[P+64>>2]=Z;c[P+64+4>>2]=g;V=Rd((fa|ja)^Z|0,_^g|0,63)|0;R=D;g=Pd((fa|ja)^Z|0,_^g|0,1)|0;c[P+32>>2]=g|V;c[P+32+4>>2]=D|R;R=c[P+40>>2]|0;V=c[P+40+4>>2]|0;Y=oe(R|0,V|0,T|0,Y|0)|0;Y=oe(Y|0,D|0,s|0,t|0)|0;T=D;W=oe(ha^T|0,(ea|ba)^Y|0,f|0,W|0)|0;f=D;g=Rd(R^W|0,V^f|0,24)|0;_=D;V=Pd(R^W|0,V^f|0,40)|0;_=D|_;R=oe(V|g|0,_|0,Y|0,T|0)|0;R=oe(R|0,D|0,B|0,C|0)|0;Z=D;c[P+8>>2]=R;c[P+8+4>>2]=Z;ja=Rd(ha^T^R|0,(ea|ba)^Y^Z|0,16)|0;fa=D;Y=Pd(ha^T^R|0,(ea|ba)^Y^Z|0,48)|0;fa=D|fa;c[P+104>>2]=Y|ja;c[P+104+4>>2]=fa;f=oe(Y|ja|0,fa|0,W|0,f|0)|0;W=D;c[P+72>>2]=f;c[P+72+4>>2]=W;fa=Rd((V|g)^f|0,_^W|0,63)|0;ja=D;W=Pd((V|g)^f|0,_^W|0,1)|0;ja=D|ja;_=c[P+48>>2]|0;f=c[P+48+4>>2]|0;aa=oe(_|0,f|0,ia|0,aa|0)|0;aa=oe(aa|0,D|0,v|0,H|0)|0;ia=D;g=oe(ca^ia|0,(U|la)^aa|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;V=D;Y=Rd(_^g|0,f^V|0,24)|0;ba=D;f=Pd(_^g|0,f^V|0,40)|0;ba=D|ba;_=oe(f|Y|0,ba|0,aa|0,ia|0)|0;_=oe(_|0,D|0,E|0,F|0)|0;ea=D;c[P+16>>2]=_;c[P+16+4>>2]=ea;T=Rd(ca^ia^_|0,(U|la)^aa^ea|0,16)|0;ha=D;aa=Pd(ca^ia^_|0,(U|la)^aa^ea|0,48)|0;ha=D|ha;c[P+112>>2]=aa|T;c[P+112+4>>2]=ha;V=oe(aa|T|0,ha|0,g|0,V|0)|0;g=D;ha=Rd((f|Y)^V|0,ba^g|0,63)|0;T=D;ba=Pd((f|Y)^V|0,ba^g|0,1)|0;T=D|T;Y=c[P+56>>2]|0;f=c[P+56+4>>2]|0;S=oe(Y|0,f|0,e|0,S|0)|0;S=oe(S|0,D|0,x|0,y|0)|0;e=D;aa=c[P+120>>2]^S;la=c[P+120+4>>2]^e;U=oe(la|0,aa|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;ia=D;ca=Rd(Y^U|0,f^ia|0,24)|0;da=D;f=Pd(Y^U|0,f^ia|0,40)|0;da=D|da;e=oe(f|ca|0,da|0,S|0,e|0)|0;e=oe(e|0,D|0,m|0,n|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Y=Rd(la^e|0,aa^S|0,16)|0;ga=D;aa=Pd(la^e|0,aa^S|0,48)|0;ga=D|ga;ia=oe(aa|Y|0,ga|0,U|0,ia|0)|0;U=D;la=Rd((f|ca)^ia|0,da^U|0,63)|0;$=D;da=Pd((f|ca)^ia|0,da^U|0,1)|0;$=D|$;Q=oe(W|fa|0,ja|0,ka|0,Q|0)|0;Q=oe(Q|0,D|0,o|0,p|0)|0;ka=D;g=oe(ga^ka|0,(aa|Y)^Q|0,V|0,g|0)|0;V=D;ca=Rd((W|fa)^g|0,ja^V|0,24)|0;f=D;ja=Pd((W|fa)^g|0,ja^V|0,40)|0;f=D|f;fa=oe(ja|ca|0,f|0,Q|0,ka|0)|0;fa=oe(fa|0,D|0,J|0,K|0)|0;W=D;c[P>>2]=fa;c[P+4>>2]=W;ma=Rd(ga^ka^fa|0,(aa|Y)^Q^W|0,16)|0;X=D;Q=Pd(ga^ka^fa|0,(aa|Y)^Q^W|0,48)|0;X=D|X;c[P+120>>2]=Q|ma;c[P+120+4>>2]=X;V=oe(Q|ma|0,X|0,g|0,V|0)|0;g=D;c[P+80>>2]=V;c[P+80+4>>2]=g;X=Rd((ja|ca)^V|0,f^g|0,63)|0;ma=D;g=Pd((ja|ca)^V|0,f^g|0,1)|0;c[P+40>>2]=g|X;c[P+40+4>>2]=D|ma;Z=oe(ba|ha|0,T|0,R|0,Z|0)|0;Z=oe(Z|0,D|0,u|0,w|0)|0;R=D;ma=c[P+96>>2]^Z;X=c[P+96+4>>2]^R;U=oe(X|0,ma|0,ia|0,U|0)|0;ia=D;g=Rd((ba|ha)^U|0,T^ia|0,24)|0;f=D;T=Pd((ba|ha)^U|0,T^ia|0,40)|0;f=D|f;R=oe(T|g|0,f|0,Z|0,R|0)|0;R=oe(R|0,D|0,q|0,r|0)|0;Z=D;c[P+8>>2]=R;c[P+8+4>>2]=Z;ha=Rd(X^R|0,ma^Z|0,16)|0;ba=D;ma=Pd(X^R|0,ma^Z|0,48)|0;ba=D|ba;ia=oe(ma|ha|0,ba|0,U|0,ia|0)|0;U=D;c[P+88>>2]=ia;c[P+88+4>>2]=U;X=Rd((T|g)^ia|0,f^U|0,63)|0;V=D;U=Pd((T|g)^ia|0,f^U|0,1)|0;c[P+48>>2]=U|X;c[P+48+4>>2]=D|V;ea=oe(da|la|0,$|0,_|0,ea|0)|0;ea=oe(ea|0,D|0,N|0,b|0)|0;_=D;V=c[P+104>>2]^ea;X=c[P+104+4>>2]^_;U=oe(X|0,V|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;f=D;ia=Rd((da|la)^U|0,$^f|0,24)|0;g=D;$=Pd((da|la)^U|0,$^f|0,40)|0;g=D|g;_=oe($|ia|0,g|0,ea|0,_|0)|0;_=oe(_|0,D|0,L|0,M|0)|0;ea=D;c[P+16>>2]=_;c[P+16+4>>2]=ea;la=Rd(X^_|0,V^ea|0,16)|0;da=D;V=Pd(X^_|0,V^ea|0,48)|0;da=D|da;f=oe(V|la|0,da|0,U|0,f|0)|0;U=D;X=Rd(($|ia)^f|0,g^U|0,63)|0;T=D;g=Pd(($|ia)^f|0,g^U|0,1)|0;c[P+56>>2]=g|X;c[P+56+4>>2]=D|T;T=c[P+32>>2]|0;X=c[P+32+4>>2]|0;S=oe(T|0,X|0,e|0,S|0)|0;S=oe(S|0,D|0,h|0,j|0)|0;e=D;g=c[P+112>>2]^S;ia=c[P+112+4>>2]^e;$=oe(ia|0,g|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;ca=D;ja=Rd(T^$|0,X^ca|0,24)|0;Q=D;X=Pd(T^$|0,X^ca|0,40)|0;Q=D|Q;e=oe(X|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,z|0,A|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;T=Rd(ia^e|0,g^S|0,16)|0;Y=D;g=Pd(ia^e|0,g^S|0,48)|0;Y=D|Y;ca=oe(g|T|0,Y|0,$|0,ca|0)|0;$=D;ia=Rd((X|ja)^ca|0,Q^$|0,63)|0;aa=D;Q=Pd((X|ja)^ca|0,Q^$|0,1)|0;aa=D|aa;W=oe(Q|ia|0,aa|0,fa|0,W|0)|0;W=oe(W|0,D|0,G|0,I|0)|0;fa=D;U=oe(ba^fa|0,(ma|ha)^W|0,f|0,U|0)|0;f=D;ja=Rd((Q|ia)^U|0,aa^f|0,24)|0;X=D;aa=Pd((Q|ia)^U|0,aa^f|0,40)|0;X=D|X;ia=oe(aa|ja|0,X|0,W|0,fa|0)|0;ia=oe(ia|0,D|0,q|0,r|0)|0;Q=D;c[P>>2]=ia;c[P+4>>2]=Q;ka=Rd(ba^fa^ia|0,(ma|ha)^W^Q|0,16)|0;ga=D;W=Pd(ba^fa^ia|0,(ma|ha)^W^Q|0,48)|0;ga=D|ga;c[P+96>>2]=W|ka;c[P+96+4>>2]=ga;f=oe(W|ka|0,ga|0,U|0,f|0)|0;U=D;c[P+64>>2]=f;c[P+64+4>>2]=U;ga=Rd((aa|ja)^f|0,X^U|0,63)|0;ka=D;U=Pd((aa|ja)^f|0,X^U|0,1)|0;c[P+32>>2]=U|ga;c[P+32+4>>2]=D|ka;ka=c[P+40>>2]|0;ga=c[P+40+4>>2]|0;Z=oe(ka|0,ga|0,R|0,Z|0)|0;Z=oe(Z|0,D|0,h|0,j|0)|0;R=D;$=oe(da^R|0,(V|la)^Z|0,ca|0,$|0)|0;ca=D;U=Rd(ka^$|0,ga^ca|0,24)|0;X=D;ga=Pd(ka^$|0,ga^ca|0,40)|0;X=D|X;ka=oe(ga|U|0,X|0,Z|0,R|0)|0;ka=oe(ka|0,D|0,N|0,b|0)|0;f=D;c[P+8>>2]=ka;c[P+8+4>>2]=f;ja=Rd(da^R^ka|0,(V|la)^Z^f|0,16)|0;aa=D;Z=Pd(da^R^ka|0,(V|la)^Z^f|0,48)|0;aa=D|aa;c[P+104>>2]=Z|ja;c[P+104+4>>2]=aa;ca=oe(Z|ja|0,aa|0,$|0,ca|0)|0;$=D;c[P+72>>2]=ca;c[P+72+4>>2]=$;aa=Rd((ga|U)^ca|0,X^$|0,63)|0;ja=D;$=Pd((ga|U)^ca|0,X^$|0,1)|0;ja=D|ja;X=c[P+48>>2]|0;ca=c[P+48+4>>2]|0;ea=oe(X|0,ca|0,_|0,ea|0)|0;ea=oe(ea|0,D|0,L|0,M|0)|0;_=D;U=oe(Y^_|0,(g|T)^ea|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;ga=D;Z=Rd(X^U|0,ca^ga|0,24)|0;la=D;ca=Pd(X^U|0,ca^ga|0,40)|0;la=D|la;X=oe(ca|Z|0,la|0,ea|0,_|0)|0;X=oe(X|0,D|0,J|0,K|0)|0;V=D;c[P+16>>2]=X;c[P+16+4>>2]=V;R=Rd(Y^_^X|0,(g|T)^ea^V|0,16)|0;da=D;ea=Pd(Y^_^X|0,(g|T)^ea^V|0,48)|0;da=D|da;c[P+112>>2]=ea|R;c[P+112+4>>2]=da;ga=oe(ea|R|0,da|0,U|0,ga|0)|0;U=D;da=Rd((ca|Z)^ga|0,la^U|0,63)|0;R=D;la=Pd((ca|Z)^ga|0,la^U|0,1)|0;R=D|R;Z=c[P+56>>2]|0;ca=c[P+56+4>>2]|0;S=oe(Z|0,ca|0,e|0,S|0)|0;S=oe(S|0,D|0,o|0,p|0)|0;e=D;ea=c[P+120>>2]^S;T=c[P+120+4>>2]^e;g=oe(T|0,ea|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;_=D;Y=Rd(Z^g|0,ca^_|0,24)|0;W=D;ca=Pd(Z^g|0,ca^_|0,40)|0;W=D|W;e=oe(ca|Y|0,W|0,S|0,e|0)|0;e=oe(e|0,D|0,B|0,C|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Z=Rd(T^e|0,ea^S|0,16)|0;ha=D;ea=Pd(T^e|0,ea^S|0,48)|0;ha=D|ha;_=oe(ea|Z|0,ha|0,g|0,_|0)|0;g=D;T=Rd((ca|Y)^_|0,W^g|0,63)|0;ma=D;W=Pd((ca|Y)^_|0,W^g|0,1)|0;ma=D|ma;Q=oe($|aa|0,ja|0,ia|0,Q|0)|0;Q=oe(Q|0,D|0,v|0,H|0)|0;ia=D;U=oe(ha^ia|0,(ea|Z)^Q|0,ga|0,U|0)|0;ga=D;Y=Rd(($|aa)^U|0,ja^ga|0,24)|0;ca=D;ja=Pd(($|aa)^U|0,ja^ga|0,40)|0;ca=D|ca;aa=oe(ja|Y|0,ca|0,Q|0,ia|0)|0;aa=oe(aa|0,D|0,u|0,w|0)|0;$=D;c[P>>2]=aa;c[P+4>>2]=$;fa=Rd(ha^ia^aa|0,(ea|Z)^Q^$|0,16)|0;ba=D;Q=Pd(ha^ia^aa|0,(ea|Z)^Q^$|0,48)|0;ba=D|ba;c[P+120>>2]=Q|fa;c[P+120+4>>2]=ba;ga=oe(Q|fa|0,ba|0,U|0,ga|0)|0;U=D;c[P+80>>2]=ga;c[P+80+4>>2]=U;ba=Rd((ja|Y)^ga|0,ca^U|0,63)|0;fa=D;U=Pd((ja|Y)^ga|0,ca^U|0,1)|0;c[P+40>>2]=U|ba;c[P+40+4>>2]=D|fa;f=oe(la|da|0,R|0,ka|0,f|0)|0;f=oe(f|0,D|0,s|0,t|0)|0;ka=D;fa=c[P+96>>2]^f;ba=c[P+96+4>>2]^ka;g=oe(ba|0,fa|0,_|0,g|0)|0;_=D;U=Rd((la|da)^g|0,R^_|0,24)|0;ca=D;R=Pd((la|da)^g|0,R^_|0,40)|0;ca=D|ca;ka=oe(R|U|0,ca|0,f|0,ka|0)|0;ka=oe(ka|0,D|0,m|0,n|0)|0;f=D;c[P+8>>2]=ka;c[P+8+4>>2]=f;da=Rd(ba^ka|0,fa^f|0,16)|0;la=D;fa=Pd(ba^ka|0,fa^f|0,48)|0;la=D|la;_=oe(fa|da|0,la|0,g|0,_|0)|0;g=D;c[P+88>>2]=_;c[P+88+4>>2]=g;ba=Rd((R|U)^_|0,ca^g|0,63)|0;ga=D;g=Pd((R|U)^_|0,ca^g|0,1)|0;c[P+48>>2]=g|ba;c[P+48+4>>2]=D|ga;V=oe(W|T|0,ma|0,X|0,V|0)|0;V=oe(V|0,D|0,z|0,A|0)|0;X=D;ga=c[P+104>>2]^V;ba=c[P+104+4>>2]^X;g=oe(ba|0,ga|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;ca=D;_=Rd((W|T)^g|0,ma^ca|0,24)|0;U=D;ma=Pd((W|T)^g|0,ma^ca|0,40)|0;U=D|U;X=oe(ma|_|0,U|0,V|0,X|0)|0;X=oe(X|0,D|0,k|0,l|0)|0;V=D;c[P+16>>2]=X;c[P+16+4>>2]=V;T=Rd(ba^X|0,ga^V|0,16)|0;W=D;ga=Pd(ba^X|0,ga^V|0,48)|0;W=D|W;ca=oe(ga|T|0,W|0,g|0,ca|0)|0;g=D;ba=Rd((ma|_)^ca|0,U^g|0,63)|0;R=D;U=Pd((ma|_)^ca|0,U^g|0,1)|0;c[P+56>>2]=U|ba;c[P+56+4>>2]=D|R;R=c[P+32>>2]|0;ba=c[P+32+4>>2]|0;S=oe(R|0,ba|0,e|0,S|0)|0;S=oe(S|0,D|0,x|0,y|0)|0;e=D;U=c[P+112>>2]^S;_=c[P+112+4>>2]^e;ma=oe(_|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;Y=D;ja=Rd(R^ma|0,ba^Y|0,24)|0;Q=D;ba=Pd(R^ma|0,ba^Y|0,40)|0;Q=D|Q;e=oe(ba|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,E|0,F|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;R=Rd(_^e|0,U^S|0,16)|0;Z=D;U=Pd(_^e|0,U^S|0,48)|0;Z=D|Z;Y=oe(U|R|0,Z|0,ma|0,Y|0)|0;ma=D;_=Rd((ba|ja)^Y|0,Q^ma|0,63)|0;ea=D;Q=Pd((ba|ja)^Y|0,Q^ma|0,1)|0;ea=D|ea;$=oe(Q|_|0,ea|0,aa|0,$|0)|0;$=oe($|0,D|0,J|0,K|0)|0;aa=D;g=oe(la^aa|0,(fa|da)^$|0,ca|0,g|0)|0;ca=D;ja=Rd((Q|_)^g|0,ea^ca|0,24)|0;ba=D;ea=Pd((Q|_)^g|0,ea^ca|0,40)|0;ba=D|ba;_=oe(ea|ja|0,ba|0,$|0,aa|0)|0;_=oe(_|0,D|0,E|0,F|0)|0;Q=D;c[P>>2]=_;c[P+4>>2]=Q;ia=Rd(la^aa^_|0,(fa|da)^$^Q|0,16)|0;ha=D;$=Pd(la^aa^_|0,(fa|da)^$^Q|0,48)|0;ha=D|ha;c[P+96>>2]=$|ia;c[P+96+4>>2]=ha;ca=oe($|ia|0,ha|0,g|0,ca|0)|0;g=D;c[P+64>>2]=ca;c[P+64+4>>2]=g;ha=Rd((ea|ja)^ca|0,ba^g|0,63)|0;ia=D;g=Pd((ea|ja)^ca|0,ba^g|0,1)|0;c[P+32>>2]=g|ha;c[P+32+4>>2]=D|ia;ia=c[P+40>>2]|0;ha=c[P+40+4>>2]|0;f=oe(ia|0,ha|0,ka|0,f|0)|0;f=oe(f|0,D|0,u|0,w|0)|0;ka=D;ma=oe(W^ka|0,(ga|T)^f|0,Y|0,ma|0)|0;Y=D;g=Rd(ia^ma|0,ha^Y|0,24)|0;ba=D;ha=Pd(ia^ma|0,ha^Y|0,40)|0;ba=D|ba;ia=oe(ha|g|0,ba|0,f|0,ka|0)|0;ia=oe(ia|0,D|0,L|0,M|0)|0;ca=D;c[P+8>>2]=ia;c[P+8+4>>2]=ca;ja=Rd(W^ka^ia|0,(ga|T)^f^ca|0,16)|0;ea=D;f=Pd(W^ka^ia|0,(ga|T)^f^ca|0,48)|0;ea=D|ea;c[P+104>>2]=f|ja;c[P+104+4>>2]=ea;Y=oe(f|ja|0,ea|0,ma|0,Y|0)|0;ma=D;c[P+72>>2]=Y;c[P+72+4>>2]=ma;ea=Rd((ha|g)^Y|0,ba^ma|0,63)|0;ja=D;ma=Pd((ha|g)^Y|0,ba^ma|0,1)|0;ja=D|ja;ba=c[P+48>>2]|0;Y=c[P+48+4>>2]|0;V=oe(ba|0,Y|0,X|0,V|0)|0;V=oe(V|0,D|0,G|0,I|0)|0;X=D;g=oe(Z^X|0,(U|R)^V|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;ha=D;f=Rd(ba^g|0,Y^ha|0,24)|0;T=D;Y=Pd(ba^g|0,Y^ha|0,40)|0;T=D|T;ba=oe(Y|f|0,T|0,V|0,X|0)|0;ba=oe(ba|0,D|0,h|0,j|0)|0;ga=D;c[P+16>>2]=ba;c[P+16+4>>2]=ga;ka=Rd(Z^X^ba|0,(U|R)^V^ga|0,16)|0;W=D;V=Pd(Z^X^ba|0,(U|R)^V^ga|0,48)|0;W=D|W;c[P+112>>2]=V|ka;c[P+112+4>>2]=W;ha=oe(V|ka|0,W|0,g|0,ha|0)|0;g=D;W=Rd((Y|f)^ha|0,T^g|0,63)|0;ka=D;T=Pd((Y|f)^ha|0,T^g|0,1)|0;ka=D|ka;f=c[P+56>>2]|0;Y=c[P+56+4>>2]|0;S=oe(f|0,Y|0,e|0,S|0)|0;S=oe(S|0,D|0,m|0,n|0)|0;e=D;V=c[P+120>>2]^S;R=c[P+120+4>>2]^e;U=oe(R|0,V|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;X=D;Z=Rd(f^U|0,Y^X|0,24)|0;$=D;Y=Pd(f^U|0,Y^X|0,40)|0;$=D|$;e=oe(Y|Z|0,$|0,S|0,e|0)|0;e=oe(e|0,D|0,z|0,A|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;f=Rd(R^e|0,V^S|0,16)|0;da=D;V=Pd(R^e|0,V^S|0,48)|0;da=D|da;X=oe(V|f|0,da|0,U|0,X|0)|0;U=D;R=Rd((Y|Z)^X|0,$^U|0,63)|0;fa=D;$=Pd((Y|Z)^X|0,$^U|0,1)|0;fa=D|fa;Q=oe(ma|ea|0,ja|0,_|0,Q|0)|0;Q=oe(Q|0,D|0,q|0,r|0)|0;_=D;g=oe(da^_|0,(V|f)^Q|0,ha|0,g|0)|0;ha=D;Z=Rd((ma|ea)^g|0,ja^ha|0,24)|0;Y=D;ja=Pd((ma|ea)^g|0,ja^ha|0,40)|0;Y=D|Y;ea=oe(ja|Z|0,Y|0,Q|0,_|0)|0;ea=oe(ea|0,D|0,v|0,H|0)|0;ma=D;c[P>>2]=ea;c[P+4>>2]=ma;aa=Rd(da^_^ea|0,(V|f)^Q^ma|0,16)|0;la=D;Q=Pd(da^_^ea|0,(V|f)^Q^ma|0,48)|0;la=D|la;c[P+120>>2]=Q|aa;c[P+120+4>>2]=la;ha=oe(Q|aa|0,la|0,g|0,ha|0)|0;g=D;c[P+80>>2]=ha;c[P+80+4>>2]=g;la=Rd((ja|Z)^ha|0,Y^g|0,63)|0;aa=D;g=Pd((ja|Z)^ha|0,Y^g|0,1)|0;c[P+40>>2]=g|la;c[P+40+4>>2]=D|aa;ca=oe(T|W|0,ka|0,ia|0,ca|0)|0;ca=oe(ca|0,D|0,N|0,b|0)|0;ia=D;aa=c[P+96>>2]^ca;la=c[P+96+4>>2]^ia;U=oe(la|0,aa|0,X|0,U|0)|0;X=D;g=Rd((T|W)^U|0,ka^X|0,24)|0;Y=D;ka=Pd((T|W)^U|0,ka^X|0,40)|0;Y=D|Y;ia=oe(ka|g|0,Y|0,ca|0,ia|0)|0;ia=oe(ia|0,D|0,o|0,p|0)|0;ca=D;c[P+8>>2]=ia;c[P+8+4>>2]=ca;W=Rd(la^ia|0,aa^ca|0,16)|0;T=D;aa=Pd(la^ia|0,aa^ca|0,48)|0;T=D|T;X=oe(aa|W|0,T|0,U|0,X|0)|0;U=D;c[P+88>>2]=X;c[P+88+4>>2]=U;la=Rd((ka|g)^X|0,Y^U|0,63)|0;ha=D;U=Pd((ka|g)^X|0,Y^U|0,1)|0;c[P+48>>2]=U|la;c[P+48+4>>2]=D|ha;ga=oe($|R|0,fa|0,ba|0,ga|0)|0;ga=oe(ga|0,D|0,x|0,y|0)|0;ba=D;ha=c[P+104>>2]^ga;la=c[P+104+4>>2]^ba;U=oe(la|0,ha|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;Y=D;X=Rd(($|R)^U|0,fa^Y|0,24)|0;g=D;fa=Pd(($|R)^U|0,fa^Y|0,40)|0;g=D|g;ba=oe(fa|X|0,g|0,ga|0,ba|0)|0;ba=oe(ba|0,D|0,s|0,t|0)|0;ga=D;c[P+16>>2]=ba;c[P+16+4>>2]=ga;R=Rd(la^ba|0,ha^ga|0,16)|0;$=D;ha=Pd(la^ba|0,ha^ga|0,48)|0;$=D|$;Y=oe(ha|R|0,$|0,U|0,Y|0)|0;U=D;la=Rd((fa|X)^Y|0,g^U|0,63)|0;ka=D;g=Pd((fa|X)^Y|0,g^U|0,1)|0;c[P+56>>2]=g|la;c[P+56+4>>2]=D|ka;ka=c[P+32>>2]|0;la=c[P+32+4>>2]|0;S=oe(ka|0,la|0,e|0,S|0)|0;S=oe(S|0,D|0,k|0,l|0)|0;e=D;g=c[P+112>>2]^S;X=c[P+112+4>>2]^e;fa=oe(X|0,g|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;Z=D;ja=Rd(ka^fa|0,la^Z|0,24)|0;Q=D;la=Pd(ka^fa|0,la^Z|0,40)|0;Q=D|Q;e=oe(la|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,B|0,C|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ka=Rd(X^e|0,g^S|0,16)|0;f=D;g=Pd(X^e|0,g^S|0,48)|0;f=D|f;Z=oe(g|ka|0,f|0,fa|0,Z|0)|0;fa=D;X=Rd((la|ja)^Z|0,Q^fa|0,63)|0;V=D;Q=Pd((la|ja)^Z|0,Q^fa|0,1)|0;V=D|V;ma=oe(Q|X|0,V|0,ea|0,ma|0)|0;ma=oe(ma|0,D|0,s|0,t|0)|0;ea=D;U=oe(T^ea|0,(aa|W)^ma|0,Y|0,U|0)|0;Y=D;ja=Rd((Q|X)^U|0,V^Y|0,24)|0;la=D;V=Pd((Q|X)^U|0,V^Y|0,40)|0;la=D|la;X=oe(V|ja|0,la|0,ma|0,ea|0)|0;X=oe(X|0,D|0,N|0,b|0)|0;Q=D;c[P>>2]=X;c[P+4>>2]=Q;_=Rd(T^ea^X|0,(aa|W)^ma^Q|0,16)|0;da=D;ma=Pd(T^ea^X|0,(aa|W)^ma^Q|0,48)|0;da=D|da;c[P+96>>2]=ma|_;c[P+96+4>>2]=da;Y=oe(ma|_|0,da|0,U|0,Y|0)|0;U=D;c[P+64>>2]=Y;c[P+64+4>>2]=U;da=Rd((V|ja)^Y|0,la^U|0,63)|0;_=D;U=Pd((V|ja)^Y|0,la^U|0,1)|0;c[P+32>>2]=U|da;c[P+32+4>>2]=D|_;_=c[P+40>>2]|0;da=c[P+40+4>>2]|0;ca=oe(_|0,da|0,ia|0,ca|0)|0;ca=oe(ca|0,D|0,L|0,M|0)|0;ia=D;fa=oe($^ia|0,(ha|R)^ca|0,Z|0,fa|0)|0;Z=D;U=Rd(_^fa|0,da^Z|0,24)|0;la=D;da=Pd(_^fa|0,da^Z|0,40)|0;la=D|la;_=oe(da|U|0,la|0,ca|0,ia|0)|0;_=oe(_|0,D|0,z|0,A|0)|0;Y=D;c[P+8>>2]=_;c[P+8+4>>2]=Y;ja=Rd($^ia^_|0,(ha|R)^ca^Y|0,16)|0;V=D;ca=Pd($^ia^_|0,(ha|R)^ca^Y|0,48)|0;V=D|V;c[P+104>>2]=ca|ja;c[P+104+4>>2]=V;Z=oe(ca|ja|0,V|0,fa|0,Z|0)|0;fa=D;c[P+72>>2]=Z;c[P+72+4>>2]=fa;V=Rd((da|U)^Z|0,la^fa|0,63)|0;ja=D;fa=Pd((da|U)^Z|0,la^fa|0,1)|0;ja=D|ja;la=c[P+48>>2]|0;Z=c[P+48+4>>2]|0;ga=oe(la|0,Z|0,ba|0,ga|0)|0;ga=oe(ga|0,D|0,E|0,F|0)|0;ba=D;U=oe(f^ba|0,(g|ka)^ga|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;da=D;ca=Rd(la^U|0,Z^da|0,24)|0;R=D;Z=Pd(la^U|0,Z^da|0,40)|0;R=D|R;la=oe(Z|ca|0,R|0,ga|0,ba|0)|0;la=oe(la|0,D|0,m|0,n|0)|0;ha=D;c[P+16>>2]=la;c[P+16+4>>2]=ha;ia=Rd(f^ba^la|0,(g|ka)^ga^ha|0,16)|0;$=D;ga=Pd(f^ba^la|0,(g|ka)^ga^ha|0,48)|0;$=D|$;c[P+112>>2]=ga|ia;c[P+112+4>>2]=$;da=oe(ga|ia|0,$|0,U|0,da|0)|0;U=D;$=Rd((Z|ca)^da|0,R^U|0,63)|0;ia=D;R=Pd((Z|ca)^da|0,R^U|0,1)|0;ia=D|ia;ca=c[P+56>>2]|0;Z=c[P+56+4>>2]|0;S=oe(ca|0,Z|0,e|0,S|0)|0;S=oe(S|0,D|0,v|0,H|0)|0;e=D;ga=c[P+120>>2]^S;ka=c[P+120+4>>2]^e;g=oe(ka|0,ga|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;ba=D;f=Rd(ca^g|0,Z^ba|0,24)|0;ma=D;Z=Pd(ca^g|0,Z^ba|0,40)|0;ma=D|ma;e=oe(Z|f|0,ma|0,S|0,e|0)|0;e=oe(e|0,D|0,x|0,y|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ca=Rd(ka^e|0,ga^S|0,16)|0;W=D;ga=Pd(ka^e|0,ga^S|0,48)|0;W=D|W;ba=oe(ga|ca|0,W|0,g|0,ba|0)|0;g=D;ka=Rd((Z|f)^ba|0,ma^g|0,63)|0;aa=D;ma=Pd((Z|f)^ba|0,ma^g|0,1)|0;aa=D|aa;Q=oe(fa|V|0,ja|0,X|0,Q|0)|0;Q=oe(Q|0,D|0,G|0,I|0)|0;X=D;U=oe(W^X|0,(ga|ca)^Q|0,da|0,U|0)|0;da=D;f=Rd((fa|V)^U|0,ja^da|0,24)|0;Z=D;ja=Pd((fa|V)^U|0,ja^da|0,40)|0;Z=D|Z;V=oe(ja|f|0,Z|0,Q|0,X|0)|0;V=oe(V|0,D|0,k|0,l|0)|0;fa=D;c[P>>2]=V;c[P+4>>2]=fa;ea=Rd(W^X^V|0,(ga|ca)^Q^fa|0,16)|0;T=D;Q=Pd(W^X^V|0,(ga|ca)^Q^fa|0,48)|0;T=D|T;c[P+120>>2]=Q|ea;c[P+120+4>>2]=T;da=oe(Q|ea|0,T|0,U|0,da|0)|0;U=D;c[P+80>>2]=da;c[P+80+4>>2]=U;T=Rd((ja|f)^da|0,Z^U|0,63)|0;ea=D;U=Pd((ja|f)^da|0,Z^U|0,1)|0;c[P+40>>2]=U|T;c[P+40+4>>2]=D|ea;Y=oe(R|$|0,ia|0,_|0,Y|0)|0;Y=oe(Y|0,D|0,J|0,K|0)|0;_=D;ea=c[P+96>>2]^Y;T=c[P+96+4>>2]^_;g=oe(T|0,ea|0,ba|0,g|0)|0;ba=D;U=Rd((R|$)^g|0,ia^ba|0,24)|0;Z=D;ia=Pd((R|$)^g|0,ia^ba|0,40)|0;Z=D|Z;_=oe(ia|U|0,Z|0,Y|0,_|0)|0;_=oe(_|0,D|0,u|0,w|0)|0;Y=D;c[P+8>>2]=_;c[P+8+4>>2]=Y;$=Rd(T^_|0,ea^Y|0,16)|0;R=D;ea=Pd(T^_|0,ea^Y|0,48)|0;R=D|R;ba=oe(ea|$|0,R|0,g|0,ba|0)|0;g=D;c[P+88>>2]=ba;c[P+88+4>>2]=g;T=Rd((ia|U)^ba|0,Z^g|0,63)|0;da=D;g=Pd((ia|U)^ba|0,Z^g|0,1)|0;c[P+48>>2]=g|T;c[P+48+4>>2]=D|da;ha=oe(ma|ka|0,aa|0,la|0,ha|0)|0;ha=oe(ha|0,D|0,h|0,j|0)|0;la=D;da=c[P+104>>2]^ha;T=c[P+104+4>>2]^la;g=oe(T|0,da|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;Z=D;ba=Rd((ma|ka)^g|0,aa^Z|0,24)|0;U=D;aa=Pd((ma|ka)^g|0,aa^Z|0,40)|0;U=D|U;la=oe(aa|ba|0,U|0,ha|0,la|0)|0;la=oe(la|0,D|0,o|0,p|0)|0;ha=D;c[P+16>>2]=la;c[P+16+4>>2]=ha;ka=Rd(T^la|0,da^ha|0,16)|0;ma=D;da=Pd(T^la|0,da^ha|0,48)|0;ma=D|ma;Z=oe(da|ka|0,ma|0,g|0,Z|0)|0;g=D;T=Rd((aa|ba)^Z|0,U^g|0,63)|0;ia=D;U=Pd((aa|ba)^Z|0,U^g|0,1)|0;c[P+56>>2]=U|T;c[P+56+4>>2]=D|ia;ia=c[P+32>>2]|0;T=c[P+32+4>>2]|0;S=oe(ia|0,T|0,e|0,S|0)|0;S=oe(S|0,D|0,B|0,C|0)|0;e=D;U=c[P+112>>2]^S;ba=c[P+112+4>>2]^e;aa=oe(ba|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;f=D;ja=Rd(ia^aa|0,T^f|0,24)|0;Q=D;T=Pd(ia^aa|0,T^f|0,40)|0;Q=D|Q;e=oe(T|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,q|0,r|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ia=Rd(ba^e|0,U^S|0,16)|0;ca=D;U=Pd(ba^e|0,U^S|0,48)|0;ca=D|ca;f=oe(U|ia|0,ca|0,aa|0,f|0)|0;aa=D;ba=Rd((T|ja)^f|0,Q^aa|0,63)|0;ga=D;Q=Pd((T|ja)^f|0,Q^aa|0,1)|0;ga=D|ga;fa=oe(Q|ba|0,ga|0,V|0,fa|0)|0;fa=oe(fa|0,D|0,B|0,C|0)|0;V=D;g=oe(R^V|0,(ea|$)^fa|0,Z|0,g|0)|0;Z=D;ja=Rd((Q|ba)^g|0,ga^Z|0,24)|0;T=D;ga=Pd((Q|ba)^g|0,ga^Z|0,40)|0;T=D|T;ba=oe(ga|ja|0,T|0,fa|0,V|0)|0;ba=oe(ba|0,D|0,k|0,l|0)|0;Q=D;c[P>>2]=ba;c[P+4>>2]=Q;X=Rd(R^V^ba|0,(ea|$)^fa^Q|0,16)|0;W=D;fa=Pd(R^V^ba|0,(ea|$)^fa^Q|0,48)|0;W=D|W;c[P+96>>2]=fa|X;c[P+96+4>>2]=W;Z=oe(fa|X|0,W|0,g|0,Z|0)|0;g=D;c[P+64>>2]=Z;c[P+64+4>>2]=g;W=Rd((ga|ja)^Z|0,T^g|0,63)|0;X=D;g=Pd((ga|ja)^Z|0,T^g|0,1)|0;c[P+32>>2]=g|W;c[P+32+4>>2]=D|X;X=c[P+40>>2]|0;W=c[P+40+4>>2]|0;Y=oe(X|0,W|0,_|0,Y|0)|0;Y=oe(Y|0,D|0,x|0,y|0)|0;_=D;aa=oe(ma^_|0,(da|ka)^Y|0,f|0,aa|0)|0;f=D;g=Rd(X^aa|0,W^f|0,24)|0;T=D;W=Pd(X^aa|0,W^f|0,40)|0;T=D|T;X=oe(W|g|0,T|0,Y|0,_|0)|0;X=oe(X|0,D|0,o|0,p|0)|0;Z=D;c[P+8>>2]=X;c[P+8+4>>2]=Z;ja=Rd(ma^_^X|0,(da|ka)^Y^Z|0,16)|0;ga=D;Y=Pd(ma^_^X|0,(da|ka)^Y^Z|0,48)|0;ga=D|ga;c[P+104>>2]=Y|ja;c[P+104+4>>2]=ga;f=oe(Y|ja|0,ga|0,aa|0,f|0)|0;aa=D;c[P+72>>2]=f;c[P+72+4>>2]=aa;ga=Rd((W|g)^f|0,T^aa|0,63)|0;ja=D;aa=Pd((W|g)^f|0,T^aa|0,1)|0;ja=D|ja;T=c[P+48>>2]|0;f=c[P+48+4>>2]|0;ha=oe(T|0,f|0,la|0,ha|0)|0;ha=oe(ha|0,D|0,u|0,w|0)|0;la=D;g=oe(ca^la|0,(U|ia)^ha|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;W=D;Y=Rd(T^g|0,f^W|0,24)|0;ka=D;f=Pd(T^g|0,f^W|0,40)|0;ka=D|ka;T=oe(f|Y|0,ka|0,ha|0,la|0)|0;T=oe(T|0,D|0,s|0,t|0)|0;da=D;c[P+16>>2]=T;c[P+16+4>>2]=da;_=Rd(ca^la^T|0,(U|ia)^ha^da|0,16)|0;ma=D;ha=Pd(ca^la^T|0,(U|ia)^ha^da|0,48)|0;ma=D|ma;c[P+112>>2]=ha|_;c[P+112+4>>2]=ma;W=oe(ha|_|0,ma|0,g|0,W|0)|0;g=D;ma=Rd((f|Y)^W|0,ka^g|0,63)|0;_=D;ka=Pd((f|Y)^W|0,ka^g|0,1)|0;_=D|_;Y=c[P+56>>2]|0;f=c[P+56+4>>2]|0;S=oe(Y|0,f|0,e|0,S|0)|0;S=oe(S|0,D|0,h|0,j|0)|0;e=D;ha=c[P+120>>2]^S;ia=c[P+120+4>>2]^e;U=oe(ia|0,ha|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;la=D;ca=Rd(Y^U|0,f^la|0,24)|0;fa=D;f=Pd(Y^U|0,f^la|0,40)|0;fa=D|fa;e=oe(f|ca|0,fa|0,S|0,e|0)|0;e=oe(e|0,D|0,q|0,r|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Y=Rd(ia^e|0,ha^S|0,16)|0;$=D;ha=Pd(ia^e|0,ha^S|0,48)|0;$=D|$;la=oe(ha|Y|0,$|0,U|0,la|0)|0;U=D;ia=Rd((f|ca)^la|0,fa^U|0,63)|0;ea=D;fa=Pd((f|ca)^la|0,fa^U|0,1)|0;ea=D|ea;Q=oe(aa|ga|0,ja|0,ba|0,Q|0)|0;Q=oe(Q|0,D|0,N|0,b|0)|0;ba=D;g=oe($^ba|0,(ha|Y)^Q|0,W|0,g|0)|0;W=D;ca=Rd((aa|ga)^g|0,ja^W|0,24)|0;f=D;ja=Pd((aa|ga)^g|0,ja^W|0,40)|0;f=D|f;ga=oe(ja|ca|0,f|0,Q|0,ba|0)|0;ga=oe(ga|0,D|0,E|0,F|0)|0;aa=D;c[P>>2]=ga;c[P+4>>2]=aa;V=Rd($^ba^ga|0,(ha|Y)^Q^aa|0,16)|0;R=D;Q=Pd($^ba^ga|0,(ha|Y)^Q^aa|0,48)|0;R=D|R;c[P+120>>2]=Q|V;c[P+120+4>>2]=R;W=oe(Q|V|0,R|0,g|0,W|0)|0;g=D;c[P+80>>2]=W;c[P+80+4>>2]=g;R=Rd((ja|ca)^W|0,f^g|0,63)|0;V=D;g=Pd((ja|ca)^W|0,f^g|0,1)|0;c[P+40>>2]=g|R;c[P+40+4>>2]=D|V;Z=oe(ka|ma|0,_|0,X|0,Z|0)|0;Z=oe(Z|0,D|0,z|0,A|0)|0;X=D;V=c[P+96>>2]^Z;R=c[P+96+4>>2]^X;U=oe(R|0,V|0,la|0,U|0)|0;la=D;g=Rd((ka|ma)^U|0,_^la|0,24)|0;f=D;_=Pd((ka|ma)^U|0,_^la|0,40)|0;f=D|f;X=oe(_|g|0,f|0,Z|0,X|0)|0;X=oe(X|0,D|0,L|0,M|0)|0;Z=D;c[P+8>>2]=X;c[P+8+4>>2]=Z;ma=Rd(R^X|0,V^Z|0,16)|0;ka=D;V=Pd(R^X|0,V^Z|0,48)|0;ka=D|ka;la=oe(V|ma|0,ka|0,U|0,la|0)|0;U=D;c[P+88>>2]=la;c[P+88+4>>2]=U;R=Rd((_|g)^la|0,f^U|0,63)|0;W=D;U=Pd((_|g)^la|0,f^U|0,1)|0;c[P+48>>2]=U|R;c[P+48+4>>2]=D|W;da=oe(fa|ia|0,ea|0,T|0,da|0)|0;da=oe(da|0,D|0,m|0,n|0)|0;T=D;W=c[P+104>>2]^da;R=c[P+104+4>>2]^T;U=oe(R|0,W|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;f=D;la=Rd((fa|ia)^U|0,ea^f|0,24)|0;g=D;ea=Pd((fa|ia)^U|0,ea^f|0,40)|0;g=D|g;T=oe(ea|la|0,g|0,da|0,T|0)|0;T=oe(T|0,D|0,G|0,I|0)|0;da=D;c[P+16>>2]=T;c[P+16+4>>2]=da;ia=Rd(R^T|0,W^da|0,16)|0;fa=D;W=Pd(R^T|0,W^da|0,48)|0;fa=D|fa;f=oe(W|ia|0,fa|0,U|0,f|0)|0;U=D;R=Rd((ea|la)^f|0,g^U|0,63)|0;_=D;g=Pd((ea|la)^f|0,g^U|0,1)|0;c[P+56>>2]=g|R;c[P+56+4>>2]=D|_;_=c[P+32>>2]|0;R=c[P+32+4>>2]|0;S=oe(_|0,R|0,e|0,S|0)|0;S=oe(S|0,D|0,J|0,K|0)|0;e=D;g=c[P+112>>2]^S;la=c[P+112+4>>2]^e;ea=oe(la|0,g|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;ca=D;ja=Rd(_^ea|0,R^ca|0,24)|0;Q=D;R=Pd(_^ea|0,R^ca|0,40)|0;Q=D|Q;e=oe(R|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,v|0,H|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;_=Rd(la^e|0,g^S|0,16)|0;Y=D;g=Pd(la^e|0,g^S|0,48)|0;Y=D|Y;ca=oe(g|_|0,Y|0,ea|0,ca|0)|0;ea=D;la=Rd((R|ja)^ca|0,Q^ea|0,63)|0;ha=D;Q=Pd((R|ja)^ca|0,Q^ea|0,1)|0;ha=D|ha;aa=oe(Q|la|0,ha|0,ga|0,aa|0)|0;aa=oe(aa|0,D|0,v|0,H|0)|0;ga=D;U=oe(ka^ga|0,(V|ma)^aa|0,f|0,U|0)|0;f=D;ja=Rd((Q|la)^U|0,ha^f|0,24)|0;R=D;ha=Pd((Q|la)^U|0,ha^f|0,40)|0;R=D|R;la=oe(ha|ja|0,R|0,aa|0,ga|0)|0;la=oe(la|0,D|0,h|0,j|0)|0;Q=D;c[P>>2]=la;c[P+4>>2]=Q;ba=Rd(ka^ga^la|0,(V|ma)^aa^Q|0,16)|0;$=D;aa=Pd(ka^ga^la|0,(V|ma)^aa^Q|0,48)|0;$=D|$;c[P+96>>2]=aa|ba;c[P+96+4>>2]=$;f=oe(aa|ba|0,$|0,U|0,f|0)|0;U=D;c[P+64>>2]=f;c[P+64+4>>2]=U;$=Rd((ha|ja)^f|0,R^U|0,63)|0;ba=D;U=Pd((ha|ja)^f|0,R^U|0,1)|0;c[P+32>>2]=U|$;c[P+32+4>>2]=D|ba;ba=c[P+40>>2]|0;$=c[P+40+4>>2]|0;Z=oe(ba|0,$|0,X|0,Z|0)|0;Z=oe(Z|0,D|0,k|0,l|0)|0;X=D;ea=oe(fa^X|0,(W|ia)^Z|0,ca|0,ea|0)|0;ca=D;U=Rd(ba^ea|0,$^ca|0,24)|0;R=D;$=Pd(ba^ea|0,$^ca|0,40)|0;R=D|R;ba=oe($|U|0,R|0,Z|0,X|0)|0;ba=oe(ba|0,D|0,m|0,n|0)|0;f=D;c[P+8>>2]=ba;c[P+8+4>>2]=f;ja=Rd(fa^X^ba|0,(W|ia)^Z^f|0,16)|0;ha=D;Z=Pd(fa^X^ba|0,(W|ia)^Z^f|0,48)|0;ha=D|ha;c[P+104>>2]=Z|ja;c[P+104+4>>2]=ha;ca=oe(Z|ja|0,ha|0,ea|0,ca|0)|0;ea=D;c[P+72>>2]=ca;c[P+72+4>>2]=ea;ha=Rd(($|U)^ca|0,R^ea|0,63)|0;ja=D;ea=Pd(($|U)^ca|0,R^ea|0,1)|0;ja=D|ja;R=c[P+48>>2]|0;ca=c[P+48+4>>2]|0;da=oe(R|0,ca|0,T|0,da|0)|0;da=oe(da|0,D|0,o|0,p|0)|0;T=D;U=oe(Y^T|0,(g|_)^da|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;$=D;Z=Rd(R^U|0,ca^$|0,24)|0;ia=D;ca=Pd(R^U|0,ca^$|0,40)|0;ia=D|ia;R=oe(ca|Z|0,ia|0,da|0,T|0)|0;R=oe(R|0,D|0,q|0,r|0)|0;W=D;c[P+16>>2]=R;c[P+16+4>>2]=W;X=Rd(Y^T^R|0,(g|_)^da^W|0,16)|0;fa=D;da=Pd(Y^T^R|0,(g|_)^da^W|0,48)|0;fa=D|fa;c[P+112>>2]=da|X;c[P+112+4>>2]=fa;$=oe(da|X|0,fa|0,U|0,$|0)|0;U=D;fa=Rd((ca|Z)^$|0,ia^U|0,63)|0;X=D;ia=Pd((ca|Z)^$|0,ia^U|0,1)|0;X=D|X;Z=c[P+56>>2]|0;ca=c[P+56+4>>2]|0;S=oe(Z|0,ca|0,e|0,S|0)|0;S=oe(S|0,D|0,s|0,t|0)|0;e=D;da=c[P+120>>2]^S;_=c[P+120+4>>2]^e;g=oe(_|0,da|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;T=D;Y=Rd(Z^g|0,ca^T|0,24)|0;aa=D;ca=Pd(Z^g|0,ca^T|0,40)|0;aa=D|aa;e=oe(ca|Y|0,aa|0,S|0,e|0)|0;e=oe(e|0,D|0,u|0,w|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Z=Rd(_^e|0,da^S|0,16)|0;ma=D;da=Pd(_^e|0,da^S|0,48)|0;ma=D|ma;T=oe(da|Z|0,ma|0,g|0,T|0)|0;g=D;_=Rd((ca|Y)^T|0,aa^g|0,63)|0;V=D;aa=Pd((ca|Y)^T|0,aa^g|0,1)|0;V=D|V;Q=oe(ea|ha|0,ja|0,la|0,Q|0)|0;Q=oe(Q|0,D|0,x|0,y|0)|0;la=D;U=oe(ma^la|0,(da|Z)^Q|0,$|0,U|0)|0;$=D;Y=Rd((ea|ha)^U|0,ja^$|0,24)|0;ca=D;ja=Pd((ea|ha)^U|0,ja^$|0,40)|0;ca=D|ca;ha=oe(ja|Y|0,ca|0,Q|0,la|0)|0;ha=oe(ha|0,D|0,z|0,A|0)|0;ea=D;c[P>>2]=ha;c[P+4>>2]=ea;ga=Rd(ma^la^ha|0,(da|Z)^Q^ea|0,16)|0;ka=D;Q=Pd(ma^la^ha|0,(da|Z)^Q^ea|0,48)|0;ka=D|ka;c[P+120>>2]=Q|ga;c[P+120+4>>2]=ka;$=oe(Q|ga|0,ka|0,U|0,$|0)|0;U=D;c[P+80>>2]=$;c[P+80+4>>2]=U;ka=Rd((ja|Y)^$|0,ca^U|0,63)|0;ga=D;U=Pd((ja|Y)^$|0,ca^U|0,1)|0;c[P+40>>2]=U|ka;c[P+40+4>>2]=D|ga;f=oe(ia|fa|0,X|0,ba|0,f|0)|0;f=oe(f|0,D|0,B|0,C|0)|0;ba=D;ga=c[P+96>>2]^f;ka=c[P+96+4>>2]^ba;g=oe(ka|0,ga|0,T|0,g|0)|0;T=D;U=Rd((ia|fa)^g|0,X^T|0,24)|0;ca=D;X=Pd((ia|fa)^g|0,X^T|0,40)|0;ca=D|ca;ba=oe(X|U|0,ca|0,f|0,ba|0)|0;ba=oe(ba|0,D|0,E|0,F|0)|0;f=D;c[P+8>>2]=ba;c[P+8+4>>2]=f;fa=Rd(ka^ba|0,ga^f|0,16)|0;ia=D;ga=Pd(ka^ba|0,ga^f|0,48)|0;ia=D|ia;T=oe(ga|fa|0,ia|0,g|0,T|0)|0;g=D;c[P+88>>2]=T;c[P+88+4>>2]=g;ka=Rd((X|U)^T|0,ca^g|0,63)|0;$=D;g=Pd((X|U)^T|0,ca^g|0,1)|0;c[P+48>>2]=g|ka;c[P+48+4>>2]=D|$;W=oe(aa|_|0,V|0,R|0,W|0)|0;W=oe(W|0,D|0,G|0,I|0)|0;R=D;$=c[P+104>>2]^W;ka=c[P+104+4>>2]^R;g=oe(ka|0,$|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;ca=D;T=Rd((aa|_)^g|0,V^ca|0,24)|0;U=D;V=Pd((aa|_)^g|0,V^ca|0,40)|0;U=D|U;R=oe(V|T|0,U|0,W|0,R|0)|0;R=oe(R|0,D|0,J|0,K|0)|0;W=D;c[P+16>>2]=R;c[P+16+4>>2]=W;_=Rd(ka^R|0,$^W|0,16)|0;aa=D;$=Pd(ka^R|0,$^W|0,48)|0;aa=D|aa;ca=oe($|_|0,aa|0,g|0,ca|0)|0;g=D;ka=Rd((V|T)^ca|0,U^g|0,63)|0;X=D;U=Pd((V|T)^ca|0,U^g|0,1)|0;c[P+56>>2]=U|ka;c[P+56+4>>2]=D|X;X=c[P+32>>2]|0;ka=c[P+32+4>>2]|0;S=oe(X|0,ka|0,e|0,S|0)|0;S=oe(S|0,D|0,L|0,M|0)|0;e=D;U=c[P+112>>2]^S;T=c[P+112+4>>2]^e;V=oe(T|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;Y=D;ja=Rd(X^V|0,ka^Y|0,24)|0;Q=D;ka=Pd(X^V|0,ka^Y|0,40)|0;Q=D|Q;e=oe(ka|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,N|0,b|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;X=Rd(T^e|0,U^S|0,16)|0;Z=D;U=Pd(T^e|0,U^S|0,48)|0;Z=D|Z;Y=oe(U|X|0,Z|0,V|0,Y|0)|0;V=D;T=Rd((ka|ja)^Y|0,Q^V|0,63)|0;da=D;Q=Pd((ka|ja)^Y|0,Q^V|0,1)|0;da=D|da;ea=oe(Q|T|0,da|0,ha|0,ea|0)|0;ea=oe(ea|0,D|0,L|0,M|0)|0;ha=D;g=oe(ia^ha|0,(ga|fa)^ea|0,ca|0,g|0)|0;L=D;ca=Rd((Q|T)^g|0,da^L|0,24)|0;M=D;da=Pd((Q|T)^g|0,da^L|0,40)|0;M=D|M;T=oe(da|ca|0,M|0,ea|0,ha|0)|0;T=oe(T|0,D|0,B|0,C|0)|0;Q=D;c[P>>2]=T;c[P+4>>2]=Q;B=Rd(ia^ha^T|0,(ga|fa)^ea^Q|0,16)|0;C=D;ea=Pd(ia^ha^T|0,(ga|fa)^ea^Q|0,48)|0;C=D|C;c[P+96>>2]=ea|B;c[P+96+4>>2]=C;C=oe(ea|B|0,C|0,g|0,L|0)|0;L=D;c[P+64>>2]=C;c[P+64+4>>2]=L;B=Rd((da|ca)^C|0,M^L|0,63)|0;g=D;L=Pd((da|ca)^C|0,M^L|0,1)|0;c[P+32>>2]=L|B;c[P+32+4>>2]=D|g;g=c[P+40>>2]|0;B=c[P+40+4>>2]|0;L=oe(g|0,B|0,ba|0,f|0)|0;L=oe(L|0,D|0,o|0,p|0)|0;p=D;V=oe(aa^p|0,($|_)^L|0,Y|0,V|0)|0;Y=D;M=Rd(g^V|0,B^Y|0,24)|0;C=D;B=Pd(g^V|0,B^Y|0,40)|0;C=D|C;o=oe(B|M|0,C|0,L|0,p|0)|0;o=oe(o|0,D|0,x|0,y|0)|0;x=D;c[P+8>>2]=o;c[P+8+4>>2]=x;g=Rd(aa^p^o|0,($|_)^L^x|0,16)|0;f=D;y=Pd(aa^p^o|0,($|_)^L^x|0,48)|0;f=D|f;c[P+104>>2]=y|g;c[P+104+4>>2]=f;Y=oe(y|g|0,f|0,V|0,Y|0)|0;V=D;c[P+72>>2]=Y;c[P+72+4>>2]=V;f=Rd((B|M)^Y|0,C^V|0,63)|0;g=D;V=Pd((B|M)^Y|0,C^V|0,1)|0;g=D|g;C=c[P+48>>2]|0;Y=c[P+48+4>>2]|0;M=oe(C|0,Y|0,R|0,W|0)|0;M=oe(M|0,D|0,z|0,A|0)|0;z=D;y=oe(Z^z|0,(U|X)^M|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;W=D;R=Rd(C^y|0,Y^W|0,24)|0;B=D;Y=Pd(C^y|0,Y^W|0,40)|0;B=D|B;C=oe(Y|R|0,B|0,M|0,z|0)|0;C=oe(C|0,D|0,N|0,b|0)|0;L=D;c[P+16>>2]=C;c[P+16+4>>2]=L;N=Rd(Z^z^C|0,(U|X)^M^L|0,16)|0;b=D;M=Pd(Z^z^C|0,(U|X)^M^L|0,48)|0;b=D|b;c[P+112>>2]=M|N;c[P+112+4>>2]=b;W=oe(M|N|0,b|0,y|0,W|0)|0;b=D;N=Rd((Y|R)^W|0,B^b|0,63)|0;y=D;B=Pd((Y|R)^W|0,B^b|0,1)|0;y=D|y;R=c[P+56>>2]|0;Y=c[P+56+4>>2]|0;M=oe(R|0,Y|0,e|0,S|0)|0;M=oe(M|0,D|0,J|0,K|0)|0;K=D;S=c[P+120>>2]^M;e=c[P+120+4>>2]^K;z=oe(e|0,S|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;p=D;X=Rd(R^z|0,Y^p|0,24)|0;A=D;Y=Pd(R^z|0,Y^p|0,40)|0;A=D|A;K=oe(Y|X|0,A|0,M|0,K|0)|0;K=oe(K|0,D|0,s|0,t|0)|0;M=D;c[P+24>>2]=K;c[P+24+4>>2]=M;R=Rd(e^K|0,S^M|0,16)|0;U=D;S=Pd(e^K|0,S^M|0,48)|0;U=D|U;p=oe(S|R|0,U|0,z|0,p|0)|0;z=D;e=Rd((Y|X)^p|0,A^z|0,63)|0;J=D;A=Pd((Y|X)^p|0,A^z|0,1)|0;J=D|J;Q=oe(V|f|0,g|0,T|0,Q|0)|0;Q=oe(Q|0,D|0,h|0,j|0)|0;T=D;t=oe(U^T|0,(S|R)^Q|0,W|0,b|0)|0;s=D;h=Rd((V|f)^t|0,g^s|0,24)|0;j=D;g=Pd((V|f)^t|0,g^s|0,40)|0;j=D|j;f=oe(g|h|0,j|0,Q|0,T|0)|0;f=oe(f|0,D|0,G|0,I|0)|0;b=D;c[P>>2]=f;c[P+4>>2]=b;I=Rd(U^T^f|0,(S|R)^Q^b|0,16)|0;G=D;Q=Pd(U^T^f|0,(S|R)^Q^b|0,48)|0;G=D|G;c[P+120>>2]=Q|I;c[P+120+4>>2]=G;G=oe(Q|I|0,G|0,t|0,s|0)|0;I=D;c[P+80>>2]=G;c[P+80+4>>2]=I;s=Rd((g|h)^G|0,j^I|0,63)|0;t=D;I=Pd((g|h)^G|0,j^I|0,1)|0;c[P+40>>2]=I|s;c[P+40+4>>2]=D|t;x=oe(B|N|0,y|0,o|0,x|0)|0;x=oe(x|0,D|0,v|0,H|0)|0;t=D;v=c[P+96>>2]^x;s=c[P+96+4>>2]^t;H=oe(s|0,v|0,p|0,z|0)|0;I=D;z=Rd((B|N)^H|0,y^I|0,24)|0;G=D;y=Pd((B|N)^H|0,y^I|0,40)|0;G=D|G;t=oe(y|z|0,G|0,x|0,t|0)|0;t=oe(t|0,D|0,k|0,l|0)|0;x=D;c[P+8>>2]=t;c[P+8+4>>2]=x;N=Rd(s^t|0,v^x|0,16)|0;B=D;x=Pd(s^t|0,v^x|0,48)|0;B=D|B;c[P+96>>2]=x|N;c[P+96+4>>2]=B;I=oe(x|N|0,B|0,H|0,I|0)|0;H=D;c[P+88>>2]=I;c[P+88+4>>2]=H;B=Rd((y|z)^I|0,G^H|0,63)|0;N=D;H=Pd((y|z)^I|0,G^H|0,1)|0;c[P+48>>2]=H|B;c[P+48+4>>2]=D|N;L=oe(A|e|0,J|0,C|0,L|0)|0;L=oe(L|0,D|0,E|0,F|0)|0;C=D;N=c[P+104>>2]^L;B=c[P+104+4>>2]^C;H=oe(B|0,N|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;G=D;E=Rd((A|e)^H|0,J^G|0,24)|0;F=D;J=Pd((A|e)^H|0,J^G|0,40)|0;F=D|F;C=oe(J|E|0,F|0,L|0,C|0)|0;C=oe(C|0,D|0,u|0,w|0)|0;L=D;c[P+16>>2]=C;c[P+16+4>>2]=L;e=Rd(B^C|0,N^L|0,16)|0;I=D;L=Pd(B^C|0,N^L|0,48)|0;I=D|I;c[P+104>>2]=L|e;c[P+104+4>>2]=I;G=oe(L|e|0,I|0,H|0,G|0)|0;H=D;c[P+64>>2]=G;c[P+64+4>>2]=H;I=Rd((J|E)^G|0,F^H|0,63)|0;e=D;H=Pd((J|E)^G|0,F^H|0,1)|0;c[P+56>>2]=H|I;c[P+56+4>>2]=D|e;e=c[P+32>>2]|0;I=c[P+32+4>>2]|0;H=oe(e|0,I|0,K|0,M|0)|0;H=oe(H|0,D|0,q|0,r|0)|0;F=D;G=c[P+112>>2]^H;E=c[P+112+4>>2]^F;M=oe(E|0,G|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;K=D;J=Rd(e^M|0,I^K|0,24)|0;L=D;I=Pd(e^M|0,I^K|0,40)|0;L=D|L;F=oe(I|J|0,L|0,H|0,F|0)|0;F=oe(F|0,D|0,m|0,n|0)|0;H=D;c[P+24>>2]=F;c[P+24+4>>2]=H;e=Rd(E^F|0,G^H|0,16)|0;N=D;H=Pd(E^F|0,G^H|0,48)|0;N=D|N;c[P+112>>2]=H|e;c[P+112+4>>2]=N;K=oe(H|e|0,N|0,M|0,K|0)|0;M=D;c[P+72>>2]=K;c[P+72+4>>2]=M;N=Rd((I|J)^K|0,L^M|0,63)|0;e=D;M=Pd((I|J)^K|0,L^M|0,1)|0;c[P+32>>2]=M|N;c[P+32+4>>2]=D|e;e=0;while(1){ma=a+(e<<3)|0;la=P+(e+8<<3)|0;b=b^c[ma+4>>2]^c[la+4>>2];c[ma>>2]=f^c[ma>>2]^c[la>>2];c[ma+4>>2]=b;b=e+1|0;if((b|0)==8)break;e=b;f=c[P+(b<<3)>>2]|0;b=c[P+(b<<3)+4>>2]|0}i=O;return}function ja(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,fb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0,sc=0,tc=0,uc=0,vc=0,wc=0,xc=0,yc=0,zc=0;O=d[c>>0]|0;P=Pd(d[c+1>>0]|0|0,0,8)|0;jb=D;j=d[c+2>>0]|0;db=Pd(j|0,0,16)|0;Ma=Pd(d[c+3>>0]|0|0,0,8)|0;qb=D;A=Pd(d[c+4>>0]|0|0,0,16)|0;qb=qb|D;nb=d[c+5>>0]|0;z=Pd(nb|0,0,24)|0;qb=Rd(Ma|j|A|z|0,qb|D|0,5)|0;z=Pd(d[c+6>>0]|0|0,0,8)|0;A=D;j=d[c+7>>0]|0;Ma=Pd(j|0,0,16)|0;A=Rd(z|nb|Ma|0,A|D|0,2)|0;Ma=Pd(d[c+8>>0]|0|0,0,8)|0;nb=D;z=Pd(d[c+9>>0]|0|0,0,16)|0;nb=nb|D;ca=d[c+10>>0]|0;lb=Pd(ca|0,0,24)|0;nb=Rd(Ma|j|z|lb|0,nb|D|0,7)|0;lb=Pd(d[c+11>>0]|0|0,0,8)|0;z=D;j=Pd(d[c+12>>0]|0|0,0,16)|0;z=z|D;Ma=d[c+13>>0]|0;ra=Pd(Ma|0,0,24)|0;z=Rd(lb|ca|j|ra|0,z|D|0,4)|0;ra=Pd(d[c+14>>0]|0|0,0,8)|0;j=D;ca=d[c+15>>0]|0;lb=Pd(ca|0,0,16)|0;j=Rd(ra|Ma|lb|0,j|D|0,1)|0;lb=Pd(d[c+16>>0]|0|0,0,8)|0;Ma=D;ra=Pd(d[c+17>>0]|0|0,0,16)|0;Ma=Ma|D;Ca=d[c+18>>0]|0;I=Pd(Ca|0,0,24)|0;Ma=Rd(lb|ca|ra|I|0,Ma|D|0,6)|0;I=Pd(d[c+19>>0]|0|0,0,8)|0;ra=D;ca=Pd(d[c+20>>0]|0|0,0,16)|0;ra=Rd(I|Ca|ca|0,ra|D|0,3)|0;ca=D;Ca=d[c+21>>0]|0;I=Pd(d[c+22>>0]|0|0,0,8)|0;lb=D;eb=d[c+23>>0]|0;Ja=Pd(eb|0,0,16)|0;ba=Pd(d[c+24>>0]|0|0,0,8)|0;La=D;sc=Pd(d[c+25>>0]|0|0,0,16)|0;La=La|D;o=d[c+26>>0]|0;rb=Pd(o|0,0,24)|0;La=Rd(ba|eb|sc|rb|0,La|D|0,5)|0;rb=Pd(d[c+27>>0]|0|0,0,8)|0;sc=D;eb=d[c+28>>0]|0;ba=Pd(eb|0,0,16)|0;sc=Rd(rb|o|ba|0,sc|D|0,2)|0;ba=Pd(d[c+29>>0]|0|0,0,8)|0;o=D;rb=Pd(d[c+30>>0]|0|0,0,16)|0;o=o|D;Da=Pd(d[c+31>>0]|0|0,0,24)|0;o=Rd(ba|eb|rb|Da|0,o|D|0,7)|0;Da=D;rb=d[e>>0]|0;eb=Pd(d[e+1>>0]|0|0,0,8)|0;ba=D;Ta=d[e+2>>0]|0;aa=Pd(Ta|0,0,16)|0;m=Pd(d[e+3>>0]|0|0,0,8)|0;Ya=D;q=Pd(d[e+4>>0]|0|0,0,16)|0;Ya=Ya|D;p=d[e+5>>0]|0;ea=Pd(p|0,0,24)|0;Ya=Rd(m|Ta|q|ea|0,Ya|D|0,5)|0;ea=Pd(d[e+6>>0]|0|0,0,8)|0;q=D;Ta=d[e+7>>0]|0;m=Pd(Ta|0,0,16)|0;q=Rd(ea|p|m|0,q|D|0,2)|0;m=Pd(d[e+8>>0]|0|0,0,8)|0;p=D;ea=Pd(d[e+9>>0]|0|0,0,16)|0;p=p|D;wc=d[e+10>>0]|0;wa=Pd(wc|0,0,24)|0;p=Rd(m|Ta|ea|wa|0,p|D|0,7)|0;wa=Pd(d[e+11>>0]|0|0,0,8)|0;ea=D;Ta=Pd(d[e+12>>0]|0|0,0,16)|0;ea=ea|D;m=d[e+13>>0]|0;zc=Pd(m|0,0,24)|0;ea=Rd(wa|wc|Ta|zc|0,ea|D|0,4)|0;zc=Pd(d[e+14>>0]|0|0,0,8)|0;Ta=D;wc=d[e+15>>0]|0;wa=Pd(wc|0,0,16)|0;Ta=Rd(zc|m|wa|0,Ta|D|0,1)|0;wa=Pd(d[e+16>>0]|0|0,0,8)|0;m=D;zc=Pd(d[e+17>>0]|0|0,0,16)|0;m=m|D;ub=d[e+18>>0]|0;uc=Pd(ub|0,0,24)|0;m=Rd(wa|wc|zc|uc|0,m|D|0,6)|0;uc=Pd(d[e+19>>0]|0|0,0,8)|0;zc=D;wc=Pd(d[e+20>>0]|0|0,0,16)|0;zc=Rd(uc|ub|wc|0,zc|D|0,3)|0;wc=D;ub=d[e+21>>0]|0;uc=Pd(d[e+22>>0]|0|0,0,8)|0;wa=D;pc=d[e+23>>0]|0;na=Pd(pc|0,0,16)|0;W=Pd(d[e+24>>0]|0|0,0,8)|0;Ia=D;K=Pd(d[e+25>>0]|0|0,0,16)|0;Ia=Ia|D;x=d[e+26>>0]|0;qc=Pd(x|0,0,24)|0;Ia=Rd(W|pc|K|qc|0,Ia|D|0,5)|0;qc=Pd(d[e+27>>0]|0|0,0,8)|0;K=D;pc=d[e+28>>0]|0;W=Pd(pc|0,0,16)|0;K=Rd(qc|x|W|0,K|D|0,2)|0;W=Pd(d[e+29>>0]|0|0,0,8)|0;x=D;qc=Pd(d[e+30>>0]|0|0,0,16)|0;x=x|D;Ba=Pd(d[e+31>>0]|0|0,0,24)|0;x=Rd(W|pc|qc|Ba|0,x|D|0,7)|0;Ba=D;qc=d[f>>0]|0;pc=Pd(d[f+1>>0]|0|0,0,8)|0;W=D;y=d[f+2>>0]|0;rc=Pd(y|0,0,16)|0;Qa=Pd(d[f+3>>0]|0|0,0,8)|0;xa=D;Fa=Pd(d[f+4>>0]|0|0,0,16)|0;xa=xa|D;ib=d[f+5>>0]|0;za=Pd(ib|0,0,24)|0;xa=Rd(Qa|y|Fa|za|0,xa|D|0,5)|0;za=Pd(d[f+6>>0]|0|0,0,8)|0;Fa=D;y=d[f+7>>0]|0;Qa=Pd(y|0,0,16)|0;Fa=Rd(za|ib|Qa|0,Fa|D|0,2)|0;Qa=Pd(d[f+8>>0]|0|0,0,8)|0;ib=D;za=Pd(d[f+9>>0]|0|0,0,16)|0;ib=ib|D;h=d[f+10>>0]|0;Y=Pd(h|0,0,24)|0;ib=Rd(Qa|y|za|Y|0,ib|D|0,7)|0;Y=Pd(d[f+11>>0]|0|0,0,8)|0;za=D;y=Pd(d[f+12>>0]|0|0,0,16)|0;za=za|D;Qa=d[f+13>>0]|0;B=Pd(Qa|0,0,24)|0;za=Rd(Y|h|y|B|0,za|D|0,4)|0;B=Pd(d[f+14>>0]|0|0,0,8)|0;y=D;h=d[f+15>>0]|0;Y=Pd(h|0,0,16)|0;y=Rd(B|Qa|Y|0,y|D|0,1)|0;Y=Pd(d[f+16>>0]|0|0,0,8)|0;Qa=D;B=Pd(d[f+17>>0]|0|0,0,16)|0;Qa=Qa|D;sa=d[f+18>>0]|0;H=Pd(sa|0,0,24)|0;Qa=Rd(Y|h|B|H|0,Qa|D|0,6)|0;H=Pd(d[f+19>>0]|0|0,0,8)|0;B=D;h=Pd(d[f+20>>0]|0|0,0,16)|0;B=Rd(H|sa|h|0,B|D|0,3)|0;h=D;sa=d[f+21>>0]|0;H=Pd(d[f+22>>0]|0|0,0,8)|0;Y=D;ma=d[f+23>>0]|0;Z=Pd(ma|0,0,16)|0;ua=Pd(d[f+24>>0]|0|0,0,8)|0;G=D;N=Pd(d[f+25>>0]|0|0,0,16)|0;G=G|D;c=d[f+26>>0]|0;Aa=Pd(c|0,0,24)|0;G=Rd(ua|ma|N|Aa|0,G|D|0,5)|0;Aa=Pd(d[f+27>>0]|0|0,0,8)|0;N=D;ma=d[f+28>>0]|0;ua=Pd(ma|0,0,16)|0;N=Rd(Aa|c|ua|0,N|D|0,2)|0;ua=Pd(d[f+29>>0]|0|0,0,8)|0;c=D;Aa=Pd(d[f+30>>0]|0|0,0,16)|0;c=c|D;i=Pd(d[f+31>>0]|0|0,0,24)|0;c=Rd(ua|ma|Aa|i|0,c|D|0,7)|0;i=D;Aa=Ed(eb|rb|aa&2031616|0,ba|0,P|O|db&2031616|0,jb|0)|0;Aa=oe(pc|qc|rc&2031616|0,W|0,Aa|0,D|0)|0;W=D;rc=Ed(Ya&2097151|0,0,P|O|db&2031616|0,jb|0)|0;qc=D;pc=Ed(eb|rb|aa&2031616|0,ba|0,qb&2097151|0,0)|0;ma=D;ua=Ed(q&2097151|0,0,P|O|db&2031616|0,jb|0)|0;Ea=D;va=Ed(Ya&2097151|0,0,qb&2097151|0,0)|0;kc=D;ia=Ed(eb|rb|aa&2031616|0,ba|0,A&2097151|0,0)|0;ia=oe(va|0,kc|0,ia|0,D|0)|0;Ea=oe(ia|0,D|0,ua|0,Ea|0)|0;Fa=oe(Ea|0,D|0,Fa&2097151|0,0)|0;Ea=D;ua=Ed(p&2097151|0,0,P|O|db&2031616|0,jb|0)|0;ia=D;kc=Ed(q&2097151|0,0,qb&2097151|0,0)|0;va=D;oc=Ed(Ya&2097151|0,0,A&2097151|0,0)|0;nc=D;mc=Ed(eb|rb|aa&2031616|0,ba|0,nb&2097151|0,0)|0;lc=D;Ha=Ed(ea&2097151|0,0,P|O|db&2031616|0,jb|0)|0;ya=D;bc=Ed(p&2097151|0,0,qb&2097151|0,0)|0;u=D;dc=Ed(q&2097151|0,0,A&2097151|0,0)|0;Ga=D;ec=Ed(Ya&2097151|0,0,nb&2097151|0,0)|0;fc=D;cc=Ed(eb|rb|aa&2031616|0,ba|0,z&2097151|0,0)|0;cc=oe(ec|0,fc|0,cc|0,D|0)|0;Ga=oe(cc|0,D|0,dc|0,Ga|0)|0;u=oe(Ga|0,D|0,bc|0,u|0)|0;ya=oe(u|0,D|0,Ha|0,ya|0)|0;za=oe(ya|0,D|0,za&2097151|0,0)|0;ya=D;Ha=Ed(Ta&2097151|0,0,P|O|db&2031616|0,jb|0)|0;u=D;bc=Ed(ea&2097151|0,0,qb&2097151|0,0)|0;Ga=D;dc=Ed(p&2097151|0,0,A&2097151|0,0)|0;cc=D;fc=Ed(q&2097151|0,0,nb&2097151|0,0)|0;ec=D;jc=Ed(Ya&2097151|0,0,z&2097151|0,0)|0;ic=D;hc=Ed(eb|rb|aa&2031616|0,ba|0,j&2097151|0,0)|0;gc=D;X=Ed(m&2097151|0,0,P|O|db&2031616|0,jb|0)|0;Ra=D;Qb=Ed(Ta&2097151|0,0,qb&2097151|0,0)|0;da=D;Sb=Ed(ea&2097151|0,0,A&2097151|0,0)|0;Pb=D;Ub=Ed(p&2097151|0,0,nb&2097151|0,0)|0;Rb=D;Wb=Ed(q&2097151|0,0,z&2097151|0,0)|0;Tb=D;Xb=Ed(Ya&2097151|0,0,j&2097151|0,0)|0;Yb=D;Vb=Ed(eb|rb|aa&2031616|0,ba|0,Ma&2097151|0,0)|0;Vb=oe(Xb|0,Yb|0,Vb|0,D|0)|0;Tb=oe(Vb|0,D|0,Wb|0,Tb|0)|0;Rb=oe(Tb|0,D|0,Ub|0,Rb|0)|0;Pb=oe(Rb|0,D|0,Sb|0,Pb|0)|0;da=oe(Pb|0,D|0,Qb|0,da|0)|0;Ra=oe(da|0,D|0,X|0,Ra|0)|0;Qa=oe(Ra|0,D|0,Qa&2097151|0,0)|0;Ra=D;X=Ed(zc|0,wc|0,P|O|db&2031616|0,jb|0)|0;da=D;Qb=Ed(m&2097151|0,0,qb&2097151|0,0)|0;Pb=D;Sb=Ed(Ta&2097151|0,0,A&2097151|0,0)|0;Rb=D;Ub=Ed(ea&2097151|0,0,nb&2097151|0,0)|0;Tb=D;Wb=Ed(p&2097151|0,0,z&2097151|0,0)|0;Vb=D;Yb=Ed(q&2097151|0,0,j&2097151|0,0)|0;Xb=D;ac=Ed(Ya&2097151|0,0,Ma&2097151|0,0)|0;$b=D;_b=Ed(eb|rb|aa&2031616|0,ba|0,ra|0,ca|0)|0;Zb=D;ta=Ed(uc|ub|na&2031616|0,wa|0,P|O|db&2031616|0,jb|0)|0;yb=D;zb=Ed(zc|0,wc|0,qb&2097151|0,0)|0;Ab=D;Bb=Ed(m&2097151|0,0,A&2097151|0,0)|0;Cb=D;Db=Ed(Ta&2097151|0,0,nb&2097151|0,0)|0;Eb=D;Fb=Ed(ea&2097151|0,0,z&2097151|0,0)|0;Gb=D;Hb=Ed(p&2097151|0,0,j&2097151|0,0)|0;Ib=D;Jb=Ed(q&2097151|0,0,Ma&2097151|0,0)|0;Kb=D;Mb=Ed(Ya&2097151|0,0,ra|0,ca|0)|0;Nb=D;Ob=Ed(eb|rb|aa&2031616|0,ba|0,I|Ca|Ja&2031616|0,lb|0)|0;Ob=oe(Mb|0,Nb|0,Ob|0,D|0)|0;Kb=oe(Ob|0,D|0,Jb|0,Kb|0)|0;Ib=oe(Kb|0,D|0,Hb|0,Ib|0)|0;Gb=oe(Ib|0,D|0,Fb|0,Gb|0)|0;Eb=oe(Gb|0,D|0,Db|0,Eb|0)|0;Cb=oe(Eb|0,D|0,Bb|0,Cb|0)|0;Ab=oe(Cb|0,D|0,zb|0,Ab|0)|0;yb=oe(Ab|0,D|0,ta|0,yb|0)|0;Y=oe(yb|0,D|0,H|sa|Z&2031616|0,Y|0)|0;Z=D;sa=Ed(Ia&2097151|0,0,P|O|db&2031616|0,jb|0)|0;H=D;yb=Ed(uc|ub|na&2031616|0,wa|0,qb&2097151|0,0)|0;ta=D;Ab=Ed(zc|0,wc|0,A&2097151|0,0)|0;zb=D;Cb=Ed(m&2097151|0,0,nb&2097151|0,0)|0;Bb=D;Eb=Ed(Ta&2097151|0,0,z&2097151|0,0)|0;Db=D;Gb=Ed(ea&2097151|0,0,j&2097151|0,0)|0;Fb=D;Ib=Ed(p&2097151|0,0,Ma&2097151|0,0)|0;Hb=D;Kb=Ed(q&2097151|0,0,ra|0,ca|0)|0;Jb=D;Ob=Ed(Ya&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;Nb=D;Mb=Ed(eb|rb|aa&2031616|0,ba|0,La&2097151|0,0)|0;Lb=D;ab=Ed(K&2097151|0,0,P|O|db&2031616|0,jb|0)|0;M=D;Q=Ed(Ia&2097151|0,0,qb&2097151|0,0)|0;bb=D;ob=Ed(uc|ub|na&2031616|0,wa|0,A&2097151|0,0)|0;R=D;J=Ed(zc|0,wc|0,nb&2097151|0,0)|0;pb=D;Oa=Ed(m&2097151|0,0,z&2097151|0,0)|0;C=D;gb=Ed(Ta&2097151|0,0,j&2097151|0,0)|0;Pa=D;U=Ed(ea&2097151|0,0,Ma&2097151|0,0)|0;hb=D;Wa=Ed(p&2097151|0,0,ra|0,ca|0)|0;V=D;xb=Ed(q&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;Xa=D;fa=Ed(Ya&2097151|0,0,La&2097151|0,0)|0;w=D;wb=Ed(eb|rb|aa&2031616|0,ba|0,sc&2097151|0,0)|0;wb=oe(fa|0,w|0,wb|0,D|0)|0;Xa=oe(wb|0,D|0,xb|0,Xa|0)|0;V=oe(Xa|0,D|0,Wa|0,V|0)|0;hb=oe(V|0,D|0,U|0,hb|0)|0;Pa=oe(hb|0,D|0,gb|0,Pa|0)|0;C=oe(Pa|0,D|0,Oa|0,C|0)|0;pb=oe(C|0,D|0,J|0,pb|0)|0;R=oe(pb|0,D|0,ob|0,R|0)|0;bb=oe(R|0,D|0,Q|0,bb|0)|0;M=oe(bb|0,D|0,ab|0,M|0)|0;N=oe(M|0,D|0,N&2097151|0,0)|0;M=D;jb=Ed(x|0,Ba|0,P|O|db&2031616|0,jb|0)|0;db=D;O=Ed(K&2097151|0,0,qb&2097151|0,0)|0;P=D;ab=Ed(Ia&2097151|0,0,A&2097151|0,0)|0;bb=D;Q=Ed(uc|ub|na&2031616|0,wa|0,nb&2097151|0,0)|0;R=D;ob=Ed(zc|0,wc|0,z&2097151|0,0)|0;pb=D;J=Ed(m&2097151|0,0,j&2097151|0,0)|0;C=D;Oa=Ed(Ta&2097151|0,0,Ma&2097151|0,0)|0;Pa=D;gb=Ed(ea&2097151|0,0,ra|0,ca|0)|0;hb=D;U=Ed(p&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;V=D;Wa=Ed(q&2097151|0,0,La&2097151|0,0)|0;Xa=D;xb=Ed(Ya&2097151|0,0,sc&2097151|0,0)|0;wb=D;ba=Ed(eb|rb|aa&2031616|0,ba|0,o|0,Da|0)|0;aa=D;qb=Ed(x|0,Ba|0,qb&2097151|0,0)|0;rb=D;eb=Ed(K&2097151|0,0,A&2097151|0,0)|0;w=D;fa=Ed(Ia&2097151|0,0,nb&2097151|0,0)|0;fb=D;ha=Ed(uc|ub|na&2031616|0,wa|0,z&2097151|0,0)|0;$=D;sb=Ed(zc|0,wc|0,j&2097151|0,0)|0;kb=D;la=Ed(m&2097151|0,0,Ma&2097151|0,0)|0;tb=D;qa=Ed(Ta&2097151|0,0,ra|0,ca|0)|0;ka=D;Na=Ed(ea&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;pa=D;Za=Ed(p&2097151|0,0,La&2097151|0,0)|0;ga=D;mb=Ed(q&2097151|0,0,sc&2097151|0,0)|0;v=D;Ya=Ed(Ya&2097151|0,0,o|0,Da|0)|0;Ya=oe(mb|0,v|0,Ya|0,D|0)|0;ga=oe(Ya|0,D|0,Za|0,ga|0)|0;pa=oe(ga|0,D|0,Na|0,pa|0)|0;ka=oe(pa|0,D|0,qa|0,ka|0)|0;tb=oe(ka|0,D|0,la|0,tb|0)|0;kb=oe(tb|0,D|0,sb|0,kb|0)|0;$=oe(kb|0,D|0,ha|0,$|0)|0;fb=oe($|0,D|0,fa|0,fb|0)|0;w=oe(fb|0,D|0,eb|0,w|0)|0;rb=oe(w|0,D|0,qb|0,rb|0)|0;qb=D;A=Ed(x|0,Ba|0,A&2097151|0,0)|0;w=D;eb=Ed(K&2097151|0,0,nb&2097151|0,0)|0;fb=D;fa=Ed(Ia&2097151|0,0,z&2097151|0,0)|0;$=D;ha=Ed(uc|ub|na&2031616|0,wa|0,j&2097151|0,0)|0;kb=D;sb=Ed(zc|0,wc|0,Ma&2097151|0,0)|0;tb=D;la=Ed(m&2097151|0,0,ra|0,ca|0)|0;ka=D;qa=Ed(Ta&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;pa=D;Na=Ed(ea&2097151|0,0,La&2097151|0,0)|0;ga=D;Za=Ed(p&2097151|0,0,sc&2097151|0,0)|0;Ya=D;q=Ed(q&2097151|0,0,o|0,Da|0)|0;v=D;nb=Ed(x|0,Ba|0,nb&2097151|0,0)|0;mb=D;_a=Ed(K&2097151|0,0,z&2097151|0,0)|0;r=D;E=Ed(Ia&2097151|0,0,j&2097151|0,0)|0;$a=D;n=Ed(uc|ub|na&2031616|0,wa|0,Ma&2097151|0,0)|0;t=D;_=Ed(zc|0,wc|0,ra|0,ca|0)|0;g=D;ja=Ed(m&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;s=D;oa=Ed(Ta&2097151|0,0,La&2097151|0,0)|0;F=D;vb=Ed(ea&2097151|0,0,sc&2097151|0,0)|0;l=D;p=Ed(p&2097151|0,0,o|0,Da|0)|0;p=oe(vb|0,l|0,p|0,D|0)|0;F=oe(p|0,D|0,oa|0,F|0)|0;s=oe(F|0,D|0,ja|0,s|0)|0;g=oe(s|0,D|0,_|0,g|0)|0;t=oe(g|0,D|0,n|0,t|0)|0;$a=oe(t|0,D|0,E|0,$a|0)|0;r=oe($a|0,D|0,_a|0,r|0)|0;mb=oe(r|0,D|0,nb|0,mb|0)|0;nb=D;z=Ed(x|0,Ba|0,z&2097151|0,0)|0;r=D;_a=Ed(K&2097151|0,0,j&2097151|0,0)|0;$a=D;E=Ed(Ia&2097151|0,0,Ma&2097151|0,0)|0;t=D;n=Ed(uc|ub|na&2031616|0,wa|0,ra|0,ca|0)|0;g=D;_=Ed(zc|0,wc|0,I|Ca|Ja&2031616|0,lb|0)|0;s=D;ja=Ed(m&2097151|0,0,La&2097151|0,0)|0;F=D;oa=Ed(Ta&2097151|0,0,sc&2097151|0,0)|0;p=D;ea=Ed(ea&2097151|0,0,o|0,Da|0)|0;l=D;j=Ed(x|0,Ba|0,j&2097151|0,0)|0;vb=D;e=Ed(K&2097151|0,0,Ma&2097151|0,0)|0;L=D;T=Ed(Ia&2097151|0,0,ra|0,ca|0)|0;Ka=D;Va=Ed(uc|ub|na&2031616|0,wa|0,I|Ca|Ja&2031616|0,lb|0)|0;S=D;Sa=Ed(zc|0,wc|0,La&2097151|0,0)|0;Ua=D;f=Ed(m&2097151|0,0,sc&2097151|0,0)|0;k=D;Ta=Ed(Ta&2097151|0,0,o|0,Da|0)|0;Ta=oe(f|0,k|0,Ta|0,D|0)|0;Ua=oe(Ta|0,D|0,Sa|0,Ua|0)|0;S=oe(Ua|0,D|0,Va|0,S|0)|0;Ka=oe(S|0,D|0,T|0,Ka|0)|0;L=oe(Ka|0,D|0,e|0,L|0)|0;vb=oe(L|0,D|0,j|0,vb|0)|0;j=D;Ma=Ed(x|0,Ba|0,Ma&2097151|0,0)|0;L=D;e=Ed(K&2097151|0,0,ra|0,ca|0)|0;Ka=D;T=Ed(Ia&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;S=D;Va=Ed(uc|ub|na&2031616|0,wa|0,La&2097151|0,0)|0;Ua=D;Sa=Ed(zc|0,wc|0,sc&2097151|0,0)|0;Ta=D;m=Ed(m&2097151|0,0,o|0,Da|0)|0;k=D;ca=Ed(x|0,Ba|0,ra|0,ca|0)|0;f=D;ra=Ed(K&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;cb=D;vc=Ed(Ia&2097151|0,0,La&2097151|0,0)|0;tc=D;yc=Ed(uc|ub|na&2031616|0,wa|0,sc&2097151|0,0)|0;xc=D;wc=Ed(zc|0,wc|0,o|0,Da|0)|0;wc=oe(yc|0,xc|0,wc|0,D|0)|0;tc=oe(wc|0,D|0,vc|0,tc|0)|0;cb=oe(tc|0,D|0,ra|0,cb|0)|0;f=oe(cb|0,D|0,ca|0,f|0)|0;ca=D;lb=Ed(x|0,Ba|0,I|Ca|Ja&2031616|0,lb|0)|0;Ja=D;Ca=Ed(K&2097151|0,0,La&2097151|0,0)|0;I=D;cb=Ed(Ia&2097151|0,0,sc&2097151|0,0)|0;ra=D;wa=Ed(uc|ub|na&2031616|0,wa|0,o|0,Da|0)|0;na=D;La=Ed(x|0,Ba|0,La&2097151|0,0)|0;ub=D;uc=Ed(K&2097151|0,0,sc&2097151|0,0)|0;tc=D;Ia=Ed(Ia&2097151|0,0,o|0,Da|0)|0;Ia=oe(uc|0,tc|0,Ia|0,D|0)|0;ub=oe(Ia|0,D|0,La|0,ub|0)|0;La=D;sc=Ed(x|0,Ba|0,sc&2097151|0,0)|0;Ia=D;K=Ed(K&2097151|0,0,o|0,Da|0)|0;K=oe(sc|0,Ia|0,K|0,D|0)|0;Ia=D;Da=Ed(x|0,Ba|0,o|0,Da|0)|0;o=D;Ba=oe(Aa|0,W|0,1048576,0)|0;Ba=Rd(Ba|0,D|0,21)|0;x=D;ma=oe(rc|0,qc|0,pc|0,ma|0)|0;ma=oe(ma|0,D|0,Ba|0,x|0)|0;xa=oe(ma|0,D|0,xa&2097151|0,0)|0;ma=D;x=Pd(Ba|0,x|0,21)|0;x=le(Aa|0,W|0,x|0,D|0)|0;W=D;Aa=oe(Fa|0,Ea|0,1048576,0)|0;Aa=Rd(Aa|0,D|0,21)|0;Ba=D;lc=oe(oc|0,nc|0,mc|0,lc|0)|0;va=oe(lc|0,D|0,kc|0,va|0)|0;ia=oe(va|0,D|0,ua|0,ia|0)|0;ib=oe(ia|0,D|0,ib&2097151|0,0)|0;ib=oe(ib|0,D|0,Aa|0,Ba|0)|0;ia=D;Ba=Pd(Aa|0,Ba|0,21)|0;Aa=D;ua=oe(za|0,ya|0,1048576,0)|0;ua=Dd(ua|0,D|0,21)|0;va=D;gc=oe(jc|0,ic|0,hc|0,gc|0)|0;ec=oe(gc|0,D|0,fc|0,ec|0)|0;cc=oe(ec|0,D|0,dc|0,cc|0)|0;Ga=oe(cc|0,D|0,bc|0,Ga|0)|0;u=oe(Ga|0,D|0,Ha|0,u|0)|0;y=oe(u|0,D|0,y&2097151|0,0)|0;y=oe(y|0,D|0,ua|0,va|0)|0;u=D;va=Pd(ua|0,va|0,21)|0;ua=D;Ha=oe(Qa|0,Ra|0,1048576,0)|0;Ha=Dd(Ha|0,D|0,21)|0;Ga=D;Zb=oe(ac|0,$b|0,_b|0,Zb|0)|0;Xb=oe(Zb|0,D|0,Yb|0,Xb|0)|0;Vb=oe(Xb|0,D|0,Wb|0,Vb|0)|0;Tb=oe(Vb|0,D|0,Ub|0,Tb|0)|0;Rb=oe(Tb|0,D|0,Sb|0,Rb|0)|0;Pb=oe(Rb|0,D|0,Qb|0,Pb|0)|0;da=oe(Pb|0,D|0,X|0,da|0)|0;h=oe(da|0,D|0,B|0,h|0)|0;h=oe(h|0,D|0,Ha|0,Ga|0)|0;B=D;Ga=Pd(Ha|0,Ga|0,21)|0;Ha=D;da=oe(Y|0,Z|0,1048576,0)|0;da=Dd(da|0,D|0,21)|0;X=D;Lb=oe(Ob|0,Nb|0,Mb|0,Lb|0)|0;Jb=oe(Lb|0,D|0,Kb|0,Jb|0)|0;Hb=oe(Jb|0,D|0,Ib|0,Hb|0)|0;Fb=oe(Hb|0,D|0,Gb|0,Fb|0)|0;Db=oe(Fb|0,D|0,Eb|0,Db|0)|0;Bb=oe(Db|0,D|0,Cb|0,Bb|0)|0;zb=oe(Bb|0,D|0,Ab|0,zb|0)|0;ta=oe(zb|0,D|0,yb|0,ta|0)|0;H=oe(ta|0,D|0,sa|0,H|0)|0;G=oe(H|0,D|0,G&2097151|0,0)|0;G=oe(G|0,D|0,da|0,X|0)|0;H=D;X=Pd(da|0,X|0,21)|0;da=D;sa=oe(N|0,M|0,1048576,0)|0;sa=Dd(sa|0,D|0,21)|0;ta=D;aa=oe(xb|0,wb|0,ba|0,aa|0)|0;Xa=oe(aa|0,D|0,Wa|0,Xa|0)|0;V=oe(Xa|0,D|0,U|0,V|0)|0;hb=oe(V|0,D|0,gb|0,hb|0)|0;Pa=oe(hb|0,D|0,Oa|0,Pa|0)|0;C=oe(Pa|0,D|0,J|0,C|0)|0;pb=oe(C|0,D|0,ob|0,pb|0)|0;R=oe(pb|0,D|0,Q|0,R|0)|0;bb=oe(R|0,D|0,ab|0,bb|0)|0;P=oe(bb|0,D|0,O|0,P|0)|0;db=oe(P|0,D|0,jb|0,db|0)|0;i=oe(db|0,D|0,c|0,i|0)|0;i=oe(i|0,D|0,sa|0,ta|0)|0;c=D;ta=Pd(sa|0,ta|0,21)|0;sa=D;db=oe(rb|0,qb|0,1048576,0)|0;db=Dd(db|0,D|0,21)|0;jb=D;v=oe(Za|0,Ya|0,q|0,v|0)|0;ga=oe(v|0,D|0,Na|0,ga|0)|0;pa=oe(ga|0,D|0,qa|0,pa|0)|0;ka=oe(pa|0,D|0,la|0,ka|0)|0;tb=oe(ka|0,D|0,sb|0,tb|0)|0;kb=oe(tb|0,D|0,ha|0,kb|0)|0;$=oe(kb|0,D|0,fa|0,$|0)|0;fb=oe($|0,D|0,eb|0,fb|0)|0;w=oe(fb|0,D|0,A|0,w|0)|0;w=oe(w|0,D|0,db|0,jb|0)|0;A=D;jb=Pd(db|0,jb|0,21)|0;db=D;fb=oe(mb|0,nb|0,1048576,0)|0;fb=Dd(fb|0,D|0,21)|0;eb=D;l=oe(oa|0,p|0,ea|0,l|0)|0;F=oe(l|0,D|0,ja|0,F|0)|0;s=oe(F|0,D|0,_|0,s|0)|0;g=oe(s|0,D|0,n|0,g|0)|0;t=oe(g|0,D|0,E|0,t|0)|0;$a=oe(t|0,D|0,_a|0,$a|0)|0;r=oe($a|0,D|0,z|0,r|0)|0;r=oe(r|0,D|0,fb|0,eb|0)|0;z=D;eb=Pd(fb|0,eb|0,21)|0;fb=D;$a=oe(vb|0,j|0,1048576,0)|0;$a=Dd($a|0,D|0,21)|0;_a=D;k=oe(Sa|0,Ta|0,m|0,k|0)|0;Ua=oe(k|0,D|0,Va|0,Ua|0)|0;S=oe(Ua|0,D|0,T|0,S|0)|0;Ka=oe(S|0,D|0,e|0,Ka|0)|0;L=oe(Ka|0,D|0,Ma|0,L|0)|0;L=oe(L|0,D|0,$a|0,_a|0)|0;Ma=D;_a=Pd($a|0,_a|0,21)|0;$a=D;Ka=oe(f|0,ca|0,1048576,0)|0;Ka=Dd(Ka|0,D|0,21)|0;e=D;na=oe(cb|0,ra|0,wa|0,na|0)|0;I=oe(na|0,D|0,Ca|0,I|0)|0;Ja=oe(I|0,D|0,lb|0,Ja|0)|0;Ja=oe(Ja|0,D|0,Ka|0,e|0)|0;lb=D;e=Pd(Ka|0,e|0,21)|0;e=le(f|0,ca|0,e|0,D|0)|0;ca=D;f=oe(ub|0,La|0,1048576,0)|0;f=Dd(f|0,D|0,21)|0;Ka=D;Ia=oe(K|0,Ia|0,f|0,Ka|0)|0;K=D;Ka=Pd(f|0,Ka|0,21)|0;Ka=le(ub|0,La|0,Ka|0,D|0)|0;La=D;ub=oe(Da|0,o|0,1048576,0)|0;ub=Dd(ub|0,D|0,21)|0;f=D;I=Pd(ub|0,f|0,21)|0;I=le(Da|0,o|0,I|0,D|0)|0;o=D;Da=oe(xa|0,ma|0,1048576,0)|0;Da=Rd(Da|0,D|0,21)|0;Ca=D;na=Pd(Da|0,Ca|0,21)|0;na=le(xa|0,ma|0,na|0,D|0)|0;ma=D;xa=oe(ib|0,ia|0,1048576,0)|0;xa=Dd(xa|0,D|0,21)|0;wa=D;ra=Pd(xa|0,wa|0,21)|0;ra=le(ib|0,ia|0,ra|0,D|0)|0;ia=D;ib=oe(y|0,u|0,1048576,0)|0;ib=Dd(ib|0,D|0,21)|0;cb=D;S=Pd(ib|0,cb|0,21)|0;T=D;Ua=oe(h|0,B|0,1048576,0)|0;Ua=Dd(Ua|0,D|0,21)|0;Va=D;k=Pd(Ua|0,Va|0,21)|0;m=D;Ta=oe(G|0,H|0,1048576,0)|0;Ta=Dd(Ta|0,D|0,21)|0;Sa=D;t=Pd(Ta|0,Sa|0,21)|0;E=D;g=oe(i|0,c|0,1048576,0)|0;g=Dd(g|0,D|0,21)|0;n=D;s=Pd(g|0,n|0,21)|0;_=D;F=oe(w|0,A|0,1048576,0)|0;F=Dd(F|0,D|0,21)|0;ja=D;l=Pd(F|0,ja|0,21)|0;ea=D;p=oe(r|0,z|0,1048576,0)|0;p=Dd(p|0,D|0,21)|0;oa=D;$=Pd(p|0,oa|0,21)|0;fa=D;kb=oe(L|0,Ma|0,1048576,0)|0;kb=Dd(kb|0,D|0,21)|0;ha=D;ca=oe(kb|0,ha|0,e|0,ca|0)|0;e=D;ha=Pd(kb|0,ha|0,21)|0;ha=le(L|0,Ma|0,ha|0,D|0)|0;Ma=D;L=oe(Ja|0,lb|0,1048576,0)|0;L=Dd(L|0,D|0,21)|0;kb=D;La=oe(L|0,kb|0,Ka|0,La|0)|0;Ka=D;kb=Pd(L|0,kb|0,21)|0;kb=le(Ja|0,lb|0,kb|0,D|0)|0;lb=D;Ja=oe(Ia|0,K|0,1048576,0)|0;Ja=Dd(Ja|0,D|0,21)|0;L=D;o=oe(Ja|0,L|0,I|0,o|0)|0;I=D;L=Pd(Ja|0,L|0,21)|0;L=le(Ia|0,K|0,L|0,D|0)|0;K=D;Ia=Ed(ub|0,f|0,666643,0)|0;Ja=D;tb=Ed(ub|0,f|0,470296,0)|0;sb=D;ka=Ed(ub|0,f|0,654183,0)|0;la=D;pa=Ed(ub|0,f|0,-997805,-1)|0;qa=D;ga=Ed(ub|0,f|0,136657,0)|0;Na=D;f=Ed(ub|0,f|0,-683901,-1)|0;f=oe(vb|0,j|0,f|0,D|0)|0;$a=le(f|0,D|0,_a|0,$a|0)|0;oa=oe($a|0,D|0,p|0,oa|0)|0;p=D;$a=Ed(o|0,I|0,666643,0)|0;_a=D;f=Ed(o|0,I|0,470296,0)|0;j=D;vb=Ed(o|0,I|0,654183,0)|0;ub=D;v=Ed(o|0,I|0,-997805,-1)|0;q=D;Ya=Ed(o|0,I|0,136657,0)|0;Za=D;I=Ed(o|0,I|0,-683901,-1)|0;o=D;P=Ed(L|0,K|0,666643,0)|0;O=D;bb=Ed(L|0,K|0,470296,0)|0;ab=D;R=Ed(L|0,K|0,654183,0)|0;Q=D;pb=Ed(L|0,K|0,-997805,-1)|0;ob=D;C=Ed(L|0,K|0,136657,0)|0;J=D;K=Ed(L|0,K|0,-683901,-1)|0;L=D;qa=oe(mb|0,nb|0,pa|0,qa|0)|0;Za=oe(qa|0,D|0,Ya|0,Za|0)|0;L=oe(Za|0,D|0,K|0,L|0)|0;fb=le(L|0,D|0,eb|0,fb|0)|0;ja=oe(fb|0,D|0,F|0,ja|0)|0;F=D;fb=Ed(La|0,Ka|0,666643,0)|0;eb=D;L=Ed(La|0,Ka|0,470296,0)|0;K=D;Za=Ed(La|0,Ka|0,654183,0)|0;Ya=D;qa=Ed(La|0,Ka|0,-997805,-1)|0;pa=D;nb=Ed(La|0,Ka|0,136657,0)|0;mb=D;Ka=Ed(La|0,Ka|0,-683901,-1)|0;La=D;Pa=Ed(kb|0,lb|0,666643,0)|0;Oa=D;hb=Ed(kb|0,lb|0,470296,0)|0;gb=D;V=Ed(kb|0,lb|0,654183,0)|0;U=D;Xa=Ed(kb|0,lb|0,-997805,-1)|0;Wa=D;aa=Ed(kb|0,lb|0,136657,0)|0;ba=D;lb=Ed(kb|0,lb|0,-683901,-1)|0;kb=D;sb=oe(vb|0,ub|0,tb|0,sb|0)|0;qb=oe(sb|0,D|0,rb|0,qb|0)|0;ob=oe(qb|0,D|0,pb|0,ob|0)|0;mb=oe(ob|0,D|0,nb|0,mb|0)|0;kb=oe(mb|0,D|0,lb|0,kb|0)|0;db=le(kb|0,D|0,jb|0,db|0)|0;n=oe(db|0,D|0,g|0,n|0)|0;g=D;db=Ed(ca|0,e|0,666643,0)|0;db=oe(ib|0,cb|0,db|0,D|0)|0;Ra=oe(db|0,D|0,Qa|0,Ra|0)|0;Ha=le(Ra|0,D|0,Ga|0,Ha|0)|0;Ga=D;Ra=Ed(ca|0,e|0,470296,0)|0;Qa=D;db=Ed(ca|0,e|0,654183,0)|0;cb=D;eb=oe(hb|0,gb|0,fb|0,eb|0)|0;cb=oe(eb|0,D|0,db|0,cb|0)|0;Va=oe(cb|0,D|0,Ua|0,Va|0)|0;Z=oe(Va|0,D|0,Y|0,Z|0)|0;da=le(Z|0,D|0,X|0,da|0)|0;X=D;Z=Ed(ca|0,e|0,-997805,-1)|0;Y=D;Va=Ed(ca|0,e|0,136657,0)|0;Ua=D;_a=oe(bb|0,ab|0,$a|0,_a|0)|0;Ya=oe(_a|0,D|0,Za|0,Ya|0)|0;Wa=oe(Ya|0,D|0,Xa|0,Wa|0)|0;Ua=oe(Wa|0,D|0,Va|0,Ua|0)|0;Sa=oe(Ua|0,D|0,Ta|0,Sa|0)|0;M=oe(Sa|0,D|0,N|0,M|0)|0;sa=le(M|0,D|0,ta|0,sa|0)|0;ta=D;e=Ed(ca|0,e|0,-683901,-1)|0;ca=D;M=oe(Ha|0,Ga|0,1048576,0)|0;M=Dd(M|0,D|0,21)|0;N=D;Oa=oe(Ra|0,Qa|0,Pa|0,Oa|0)|0;B=oe(Oa|0,D|0,h|0,B|0)|0;m=le(B|0,D|0,k|0,m|0)|0;m=oe(m|0,D|0,M|0,N|0)|0;k=D;N=Pd(M|0,N|0,21)|0;M=D;B=oe(da|0,X|0,1048576,0)|0;B=Dd(B|0,D|0,21)|0;h=D;O=oe(L|0,K|0,P|0,O|0)|0;U=oe(O|0,D|0,V|0,U|0)|0;Y=oe(U|0,D|0,Z|0,Y|0)|0;H=oe(Y|0,D|0,G|0,H|0)|0;E=le(H|0,D|0,t|0,E|0)|0;E=oe(E|0,D|0,B|0,h|0)|0;t=D;h=Pd(B|0,h|0,21)|0;B=D;H=oe(sa|0,ta|0,1048576,0)|0;H=Dd(H|0,D|0,21)|0;G=D;Ja=oe(f|0,j|0,Ia|0,Ja|0)|0;Q=oe(Ja|0,D|0,R|0,Q|0)|0;pa=oe(Q|0,D|0,qa|0,pa|0)|0;ba=oe(pa|0,D|0,aa|0,ba|0)|0;ca=oe(ba|0,D|0,e|0,ca|0)|0;c=oe(ca|0,D|0,i|0,c|0)|0;_=le(c|0,D|0,s|0,_|0)|0;_=oe(_|0,D|0,H|0,G|0)|0;s=D;G=Pd(H|0,G|0,21)|0;H=D;c=oe(n|0,g|0,1048576,0)|0;c=Dd(c|0,D|0,21)|0;i=D;la=oe(v|0,q|0,ka|0,la|0)|0;J=oe(la|0,D|0,C|0,J|0)|0;La=oe(J|0,D|0,Ka|0,La|0)|0;A=oe(La|0,D|0,w|0,A|0)|0;ea=le(A|0,D|0,l|0,ea|0)|0;ea=oe(ea|0,D|0,c|0,i|0)|0;l=D;i=Pd(c|0,i|0,21)|0;i=le(n|0,g|0,i|0,D|0)|0;g=D;n=oe(ja|0,F|0,1048576,0)|0;n=Dd(n|0,D|0,21)|0;c=D;Na=oe(I|0,o|0,ga|0,Na|0)|0;z=oe(Na|0,D|0,r|0,z|0)|0;fa=le(z|0,D|0,$|0,fa|0)|0;fa=oe(fa|0,D|0,n|0,c|0)|0;$=D;c=Pd(n|0,c|0,21)|0;c=le(ja|0,F|0,c|0,D|0)|0;F=D;ja=oe(oa|0,p|0,1048576,0)|0;ja=Dd(ja|0,D|0,21)|0;n=D;Ma=oe(ja|0,n|0,ha|0,Ma|0)|0;ha=D;n=Pd(ja|0,n|0,21)|0;n=le(oa|0,p|0,n|0,D|0)|0;p=D;oa=oe(m|0,k|0,1048576,0)|0;oa=Dd(oa|0,D|0,21)|0;ja=D;z=Pd(oa|0,ja|0,21)|0;r=D;Na=oe(E|0,t|0,1048576,0)|0;Na=Dd(Na|0,D|0,21)|0;ga=D;o=Pd(Na|0,ga|0,21)|0;I=D;A=oe(_|0,s|0,1048576,0)|0;A=Dd(A|0,D|0,21)|0;w=D;g=oe(A|0,w|0,i|0,g|0)|0;i=D;w=Pd(A|0,w|0,21)|0;w=le(_|0,s|0,w|0,D|0)|0;s=D;_=oe(ea|0,l|0,1048576,0)|0;_=Dd(_|0,D|0,21)|0;A=D;F=oe(_|0,A|0,c|0,F|0)|0;c=D;A=Pd(_|0,A|0,21)|0;A=le(ea|0,l|0,A|0,D|0)|0;l=D;ea=oe(fa|0,$|0,1048576,0)|0;ea=Dd(ea|0,D|0,21)|0;_=D;p=oe(ea|0,_|0,n|0,p|0)|0;n=D;_=Pd(ea|0,_|0,21)|0;_=le(fa|0,$|0,_|0,D|0)|0;$=D;fa=Ed(Ma|0,ha|0,666643,0)|0;ea=D;La=Ed(Ma|0,ha|0,470296,0)|0;Ka=D;J=Ed(Ma|0,ha|0,654183,0)|0;C=D;la=Ed(Ma|0,ha|0,-997805,-1)|0;ka=D;q=Ed(Ma|0,ha|0,136657,0)|0;v=D;ha=Ed(Ma|0,ha|0,-683901,-1)|0;ha=oe(Na|0,ga|0,ha|0,D|0)|0;ta=oe(ha|0,D|0,sa|0,ta|0)|0;H=le(ta|0,D|0,G|0,H|0)|0;G=D;ta=Ed(p|0,n|0,666643,0)|0;sa=D;ha=Ed(p|0,n|0,470296,0)|0;ga=D;Na=Ed(p|0,n|0,654183,0)|0;Ma=D;ca=Ed(p|0,n|0,-997805,-1)|0;e=D;ba=Ed(p|0,n|0,136657,0)|0;aa=D;n=Ed(p|0,n|0,-683901,-1)|0;p=D;pa=Ed(_|0,$|0,666643,0)|0;pa=oe(ra|0,ia|0,pa|0,D|0)|0;ia=D;ra=Ed(_|0,$|0,470296,0)|0;qa=D;Q=Ed(_|0,$|0,654183,0)|0;R=D;Ja=Ed(_|0,$|0,-997805,-1)|0;Ia=D;j=Ed(_|0,$|0,136657,0)|0;f=D;$=Ed(_|0,$|0,-683901,-1)|0;_=D;ka=oe(ba|0,aa|0,la|0,ka|0)|0;_=oe(ka|0,D|0,$|0,_|0)|0;ja=oe(_|0,D|0,oa|0,ja|0)|0;X=oe(ja|0,D|0,da|0,X|0)|0;B=le(X|0,D|0,h|0,B|0)|0;h=D;X=Ed(F|0,c|0,666643,0)|0;da=D;ja=Ed(F|0,c|0,470296,0)|0;ja=oe(pa|0,ia|0,ja|0,D|0)|0;ia=D;pa=Ed(F|0,c|0,654183,0)|0;oa=D;_=Ed(F|0,c|0,-997805,-1)|0;$=D;ka=Ed(F|0,c|0,136657,0)|0;la=D;c=Ed(F|0,c|0,-683901,-1)|0;F=D;aa=Ed(A|0,l|0,666643,0)|0;ba=D;Y=Ed(A|0,l|0,470296,0)|0;Z=D;U=Ed(A|0,l|0,654183,0)|0;V=D;O=Ed(A|0,l|0,-997805,-1)|0;P=D;K=Ed(A|0,l|0,136657,0)|0;L=D;l=Ed(A|0,l|0,-683901,-1)|0;A=D;Ka=oe(Na|0,Ma|0,La|0,Ka|0)|0;Ia=oe(Ka|0,D|0,Ja|0,Ia|0)|0;Ga=oe(Ia|0,D|0,Ha|0,Ga|0)|0;M=le(Ga|0,D|0,N|0,M|0)|0;la=oe(M|0,D|0,ka|0,la|0)|0;A=oe(la|0,D|0,l|0,A|0)|0;l=D;la=Ed(g|0,i|0,666643,0)|0;W=oe(la|0,D|0,x|0,W|0)|0;x=D;la=Ed(g|0,i|0,470296,0)|0;ka=D;M=Ed(g|0,i|0,654183,0)|0;N=D;Ca=oe(Fa|0,Ea|0,Da|0,Ca|0)|0;Aa=le(Ca|0,D|0,Ba|0,Aa|0)|0;da=oe(Aa|0,D|0,X|0,da|0)|0;N=oe(da|0,D|0,M|0,N|0)|0;Z=oe(N|0,D|0,Y|0,Z|0)|0;Y=D;N=Ed(g|0,i|0,-997805,-1)|0;M=D;da=Ed(g|0,i|0,136657,0)|0;X=D;wa=oe(za|0,ya|0,xa|0,wa|0)|0;ua=le(wa|0,D|0,va|0,ua|0)|0;sa=oe(ua|0,D|0,ta|0,sa|0)|0;qa=oe(sa|0,D|0,ra|0,qa|0)|0;oa=oe(qa|0,D|0,pa|0,oa|0)|0;X=oe(oa|0,D|0,da|0,X|0)|0;P=oe(X|0,D|0,O|0,P|0)|0;O=D;i=Ed(g|0,i|0,-683901,-1)|0;g=D;X=oe(W|0,x|0,1048576,0)|0;X=Dd(X|0,D|0,21)|0;da=D;ka=oe(na|0,ma|0,la|0,ka|0)|0;ba=oe(ka|0,D|0,aa|0,ba|0)|0;ba=oe(ba|0,D|0,X|0,da|0)|0;aa=D;da=Pd(X|0,da|0,21)|0;da=le(W|0,x|0,da|0,D|0)|0;x=D;W=oe(Z|0,Y|0,1048576,0)|0;W=Dd(W|0,D|0,21)|0;X=D;M=oe(ja|0,ia|0,N|0,M|0)|0;V=oe(M|0,D|0,U|0,V|0)|0;V=oe(V|0,D|0,W|0,X|0)|0;U=D;X=Pd(W|0,X|0,21)|0;W=D;M=oe(P|0,O|0,1048576,0)|0;M=Dd(M|0,D|0,21)|0;N=D;ea=oe(ha|0,ga|0,fa|0,ea|0)|0;u=oe(ea|0,D|0,y|0,u|0)|0;R=oe(u|0,D|0,Q|0,R|0)|0;T=le(R|0,D|0,S|0,T|0)|0;$=oe(T|0,D|0,_|0,$|0)|0;g=oe($|0,D|0,i|0,g|0)|0;L=oe(g|0,D|0,K|0,L|0)|0;L=oe(L|0,D|0,M|0,N|0)|0;K=D;N=Pd(M|0,N|0,21)|0;M=D;g=oe(A|0,l|0,1048576,0)|0;g=Dd(g|0,D|0,21)|0;i=D;C=oe(ca|0,e|0,J|0,C|0)|0;f=oe(C|0,D|0,j|0,f|0)|0;k=oe(f|0,D|0,m|0,k|0)|0;r=le(k|0,D|0,z|0,r|0)|0;F=oe(r|0,D|0,c|0,F|0)|0;F=oe(F|0,D|0,g|0,i|0)|0;c=D;i=Pd(g|0,i|0,21)|0;i=le(A|0,l|0,i|0,D|0)|0;l=D;A=oe(B|0,h|0,1048576,0)|0;A=Dd(A|0,D|0,21)|0;g=D;v=oe(n|0,p|0,q|0,v|0)|0;t=oe(v|0,D|0,E|0,t|0)|0;I=le(t|0,D|0,o|0,I|0)|0;I=oe(I|0,D|0,A|0,g|0)|0;o=D;g=Pd(A|0,g|0,21)|0;g=le(B|0,h|0,g|0,D|0)|0;h=D;B=oe(H|0,G|0,1048576,0)|0;B=Dd(B|0,D|0,21)|0;A=D;s=oe(w|0,s|0,B|0,A|0)|0;w=D;A=Pd(B|0,A|0,21)|0;B=D;t=oe(ba|0,aa|0,1048576,0)|0;t=Dd(t|0,D|0,21)|0;E=D;v=Pd(t|0,E|0,21)|0;q=D;p=oe(V|0,U|0,1048576,0)|0;p=Dd(p|0,D|0,21)|0;n=D;r=Pd(p|0,n|0,21)|0;z=D;k=oe(L|0,K|0,1048576,0)|0;k=Dd(k|0,D|0,21)|0;m=D;l=oe(i|0,l|0,k|0,m|0)|0;i=D;m=Pd(k|0,m|0,21)|0;k=D;f=oe(F|0,c|0,1048576,0)|0;f=Dd(f|0,D|0,21)|0;j=D;h=oe(g|0,h|0,f|0,j|0)|0;g=D;j=Pd(f|0,j|0,21)|0;j=le(F|0,c|0,j|0,D|0)|0;c=D;F=oe(I|0,o|0,1048576,0)|0;F=Dd(F|0,D|0,21)|0;f=D;C=Pd(F|0,f|0,21)|0;C=le(I|0,o|0,C|0,D|0)|0;o=D;I=oe(s|0,w|0,1048576,0)|0;I=Dd(I|0,D|0,21)|0;J=D;e=Pd(I|0,J|0,21)|0;e=le(s|0,w|0,e|0,D|0)|0;w=D;s=Ed(I|0,J|0,666643,0)|0;s=oe(da|0,x|0,s|0,D|0)|0;x=D;da=Ed(I|0,J|0,470296,0)|0;ca=D;$=Ed(I|0,J|0,654183,0)|0;_=D;T=Ed(I|0,J|0,-997805,-1)|0;S=D;R=Ed(I|0,J|0,136657,0)|0;Q=D;J=Ed(I|0,J|0,-683901,-1)|0;I=D;u=Dd(s|0,x|0,21)|0;y=D;aa=oe(da|0,ca|0,ba|0,aa|0)|0;q=le(aa|0,D|0,v|0,q|0)|0;q=oe(q|0,D|0,u|0,y|0)|0;v=D;y=Pd(u|0,y|0,21)|0;y=le(s|0,x|0,y|0,D|0)|0;x=D;s=Dd(q|0,v|0,21)|0;u=D;Y=oe($|0,_|0,Z|0,Y|0)|0;W=le(Y|0,D|0,X|0,W|0)|0;E=oe(W|0,D|0,t|0,E|0)|0;E=oe(E|0,D|0,s|0,u|0)|0;t=D;u=Pd(s|0,u|0,21)|0;u=le(q|0,v|0,u|0,D|0)|0;v=D;q=Dd(E|0,t|0,21)|0;s=D;S=oe(V|0,U|0,T|0,S|0)|0;z=le(S|0,D|0,r|0,z|0)|0;z=oe(z|0,D|0,q|0,s|0)|0;r=D;s=Pd(q|0,s|0,21)|0;s=le(E|0,t|0,s|0,D|0)|0;t=D;E=Dd(z|0,r|0,21)|0;q=D;O=oe(R|0,Q|0,P|0,O|0)|0;M=le(O|0,D|0,N|0,M|0)|0;n=oe(M|0,D|0,p|0,n|0)|0;n=oe(n|0,D|0,E|0,q|0)|0;p=D;q=Pd(E|0,q|0,21)|0;q=le(z|0,r|0,q|0,D|0)|0;r=D;z=Dd(n|0,p|0,21)|0;E=D;I=oe(L|0,K|0,J|0,I|0)|0;k=le(I|0,D|0,m|0,k|0)|0;k=oe(k|0,D|0,z|0,E|0)|0;m=D;E=Pd(z|0,E|0,21)|0;E=le(n|0,p|0,E|0,D|0)|0;p=D;n=Dd(k|0,m|0,21)|0;z=D;i=oe(l|0,i|0,n|0,z|0)|0;l=D;z=Pd(n|0,z|0,21)|0;z=le(k|0,m|0,z|0,D|0)|0;m=D;k=Dd(i|0,l|0,21)|0;n=D;c=oe(k|0,n|0,j|0,c|0)|0;j=D;n=Pd(k|0,n|0,21)|0;n=le(i|0,l|0,n|0,D|0)|0;l=D;i=Dd(c|0,j|0,21)|0;k=D;g=oe(h|0,g|0,i|0,k|0)|0;h=D;k=Pd(i|0,k|0,21)|0;k=le(c|0,j|0,k|0,D|0)|0;j=D;c=Dd(g|0,h|0,21)|0;i=D;o=oe(c|0,i|0,C|0,o|0)|0;C=D;i=Pd(c|0,i|0,21)|0;i=le(g|0,h|0,i|0,D|0)|0;h=D;g=Dd(o|0,C|0,21)|0;c=D;f=oe(H|0,G|0,F|0,f|0)|0;B=le(f|0,D|0,A|0,B|0)|0;B=oe(B|0,D|0,g|0,c|0)|0;A=D;c=Pd(g|0,c|0,21)|0;c=le(o|0,C|0,c|0,D|0)|0;C=D;o=Dd(B|0,A|0,21)|0;g=D;w=oe(o|0,g|0,e|0,w|0)|0;e=D;g=Pd(o|0,g|0,21)|0;g=le(B|0,A|0,g|0,D|0)|0;A=D;B=Dd(w|0,e|0,21)|0;o=D;f=Pd(B|0,o|0,21)|0;f=le(w|0,e|0,f|0,D|0)|0;e=D;w=Ed(B|0,o|0,666643,0)|0;x=oe(w|0,D|0,y|0,x|0)|0;y=D;w=Ed(B|0,o|0,470296,0)|0;w=oe(u|0,v|0,w|0,D|0)|0;v=D;u=Ed(B|0,o|0,654183,0)|0;u=oe(s|0,t|0,u|0,D|0)|0;t=D;s=Ed(B|0,o|0,-997805,-1)|0;s=oe(q|0,r|0,s|0,D|0)|0;r=D;q=Ed(B|0,o|0,136657,0)|0;q=oe(E|0,p|0,q|0,D|0)|0;p=D;o=Ed(B|0,o|0,-683901,-1)|0;o=oe(z|0,m|0,o|0,D|0)|0;m=D;z=Dd(x|0,y|0,21)|0;B=D;v=oe(w|0,v|0,z|0,B|0)|0;w=D;B=Pd(z|0,B|0,21)|0;B=le(x|0,y|0,B|0,D|0)|0;y=D;x=Dd(v|0,w|0,21)|0;z=D;t=oe(u|0,t|0,x|0,z|0)|0;u=D;z=Pd(x|0,z|0,21)|0;z=le(v|0,w|0,z|0,D|0)|0;w=D;v=Dd(t|0,u|0,21)|0;x=D;r=oe(s|0,r|0,v|0,x|0)|0;s=D;x=Pd(v|0,x|0,21)|0;x=le(t|0,u|0,x|0,D|0)|0;u=D;t=Dd(r|0,s|0,21)|0;v=D;p=oe(q|0,p|0,t|0,v|0)|0;q=D;v=Pd(t|0,v|0,21)|0;v=le(r|0,s|0,v|0,D|0)|0;s=D;r=Dd(p|0,q|0,21)|0;t=D;m=oe(o|0,m|0,r|0,t|0)|0;o=D;t=Pd(r|0,t|0,21)|0;t=le(p|0,q|0,t|0,D|0)|0;q=D;p=Dd(m|0,o|0,21)|0;r=D;l=oe(p|0,r|0,n|0,l|0)|0;n=D;r=Pd(p|0,r|0,21)|0;r=le(m|0,o|0,r|0,D|0)|0;o=D;m=Dd(l|0,n|0,21)|0;p=D;j=oe(m|0,p|0,k|0,j|0)|0;k=D;p=Pd(m|0,p|0,21)|0;p=le(l|0,n|0,p|0,D|0)|0;n=D;l=Dd(j|0,k|0,21)|0;m=D;h=oe(l|0,m|0,i|0,h|0)|0;i=D;m=Pd(l|0,m|0,21)|0;m=le(j|0,k|0,m|0,D|0)|0;k=D;j=Dd(h|0,i|0,21)|0;l=D;C=oe(j|0,l|0,c|0,C|0)|0;c=D;l=Pd(j|0,l|0,21)|0;l=le(h|0,i|0,l|0,D|0)|0;i=D;h=Dd(C|0,c|0,21)|0;j=D;A=oe(h|0,j|0,g|0,A|0)|0;g=D;j=Pd(h|0,j|0,21)|0;j=le(C|0,c|0,j|0,D|0)|0;c=D;C=Dd(A|0,g|0,21)|0;h=D;e=oe(C|0,h|0,f|0,e|0)|0;f=D;h=Pd(C|0,h|0,21)|0;h=le(A|0,g|0,h|0,D|0)|0;g=D;a[b>>0]=B;A=Rd(B|0,y|0,8)|0;a[b+1>>0]=A;y=Rd(B|0,y|0,16)|0;B=D;A=Pd(z|0,w|0,5)|0;a[b+2>>0]=A|y;y=Rd(z|0,w|0,3)|0;a[b+3>>0]=y;y=Rd(z|0,w|0,11)|0;a[b+4>>0]=y;w=Rd(z|0,w|0,19)|0;z=D;y=Pd(x|0,u|0,2)|0;a[b+5>>0]=y|w;w=Rd(x|0,u|0,6)|0;a[b+6>>0]=w;u=Rd(x|0,u|0,14)|0;x=D;w=Pd(v|0,s|0,7)|0;a[b+7>>0]=w|u;u=Rd(v|0,s|0,1)|0;a[b+8>>0]=u;u=Rd(v|0,s|0,9)|0;a[b+9>>0]=u;s=Rd(v|0,s|0,17)|0;v=D;u=Pd(t|0,q|0,4)|0;a[b+10>>0]=u|s;s=Rd(t|0,q|0,4)|0;a[b+11>>0]=s;s=Rd(t|0,q|0,12)|0;a[b+12>>0]=s;q=Rd(t|0,q|0,20)|0;t=D;s=Pd(r|0,o|0,1)|0;a[b+13>>0]=s|q;q=Rd(r|0,o|0,7)|0;a[b+14>>0]=q;o=Rd(r|0,o|0,15)|0;r=D;q=Pd(p|0,n|0,6)|0;a[b+15>>0]=q|o;o=Rd(p|0,n|0,2)|0;a[b+16>>0]=o;o=Rd(p|0,n|0,10)|0;a[b+17>>0]=o;n=Rd(p|0,n|0,18)|0;p=D;o=Pd(m|0,k|0,3)|0;a[b+18>>0]=o|n;n=Rd(m|0,k|0,5)|0;a[b+19>>0]=n;k=Rd(m|0,k|0,13)|0;a[b+20>>0]=k;a[b+21>>0]=l;k=Rd(l|0,i|0,8)|0;a[b+22>>0]=k;i=Rd(l|0,i|0,16)|0;l=D;k=Pd(j|0,c|0,5)|0;a[b+23>>0]=k|i;i=Rd(j|0,c|0,3)|0;a[b+24>>0]=i;i=Rd(j|0,c|0,11)|0;a[b+25>>0]=i;c=Rd(j|0,c|0,19)|0;j=D;i=Pd(h|0,g|0,2)|0;a[b+26>>0]=i|c;c=Rd(h|0,g|0,6)|0;a[b+27>>0]=c;g=Rd(h|0,g|0,14)|0;h=D;c=Pd(e|0,f|0,7)|0;a[b+28>>0]=g|c;c=Rd(e|0,f|0,1)|0;a[b+29>>0]=c;c=Rd(e|0,f|0,9)|0;a[b+30>>0]=c;f=Rd(e|0,f|0,17)|0;a[b+31>>0]=f;return}function ka(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;f=i;g=i=i+63&-64;i=i+304|0;e=0;do{h=b+(e<<2)|0;c[g+40+(e<<2)>>2]=(d[h+2>>0]|0)<<8|(d[h+3>>0]|0)|(d[h+1>>0]|0)<<16|(d[h>>0]|0)<<24;e=e+1|0}while((e|0)!=16);e=16;b=c[g+40>>2]|0;do{h=c[g+40+(e+-2<<2)>>2]|0;j=b;b=c[g+40+(e+-15<<2)>>2]|0;c[g+40+(e<<2)>>2]=j+(c[g+40+(e+-7<<2)>>2]|0)+((h>>>19|h<<13)^h>>>10^(h>>>17|h<<15))+((b>>>18|b<<14)^b>>>3^(b>>>7|b<<25));e=e+1|0}while((e|0)!=64);c[g+8>>2]=c[a>>2];c[g+8+4>>2]=c[a+4>>2];c[g+8+8>>2]=c[a+8>>2];c[g+8+12>>2]=c[a+12>>2];c[g+8+16>>2]=c[a+16>>2];c[g+8+20>>2]=c[a+20>>2];c[g+8+24>>2]=c[a+24>>2];c[g+8+28>>2]=c[a+28>>2];x=g+8+28|0;k=g+8+16|0;p=c[k>>2]|0;v=g+8+20|0;n=c[v>>2]|0;j=g+8+24|0;y=c[j>>2]|0;b=(c[x>>2]|0)+1116352408+(c[g+40>>2]|0)+((p>>>6|p<<26)^(p>>>11|p<<21)^(p>>>25|p<<7))+((y^n)&p^y)|0;l=c[g+8>>2]|0;t=g+8+4|0;o=c[t>>2]|0;w=g+8+8|0;q=c[w>>2]|0;h=g+8+12|0;e=(c[h>>2]|0)+b|0;c[h>>2]=e;c[x>>2]=((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b;p=y+1899447441+((e>>>6|e<<26)^(e>>>11|e<<21)^(e>>>25|e<<7))+(c[g+40+4>>2]|0)+((n^p)&e^n)|0;c[w>>2]=q+p;y=((o|l)&((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b|o&l)+(((((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b|0)>>>2|((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b<<30)^((((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b|0)>>>13|((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b<<19)^((((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b|0)>>>22|((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b<<10))+p|0;c[j>>2]=y;r=c[k>>2]|0;n=n+-1245643825+(((q+p|0)>>>6|q+p<<26)^((q+p|0)>>>11|q+p<<21)^((q+p|0)>>>25|q+p<<7))+(c[g+40+8>>2]|0)+((r^e)&q+p^r)|0;c[t>>2]=o+n;b=((l|((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b)&y|l&((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+n|0;c[v>>2]=b;r=r+-373957723+(((o+n|0)>>>6|o+n<<26)^((o+n|0)>>>11|o+n<<21)^((o+n|0)>>>25|o+n<<7))+(c[g+40+12>>2]|0)+((e^q+p)&o+n^e)|0;s=c[x>>2]|0;c[g+8>>2]=l+r;c[k>>2]=((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r;e=e+961987163+(((l+r|0)>>>6|l+r<<26)^((l+r|0)>>>11|l+r<<21)^((l+r|0)>>>25|l+r<<7))+(c[g+40+16>>2]|0)+((q+p^o+n)&l+r^q+p)|0;m=c[j>>2]|0;c[x>>2]=s+e;u=((m|b)&((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|m&b)+(((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>2|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<30)^((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>13|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<19)^((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>22|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<10))+e|0;c[h>>2]=u;p=q+p+1508970993+(((s+e|0)>>>6|s+e<<26)^((s+e|0)>>>11|s+e<<21)^((s+e|0)>>>25|s+e<<7))+(c[g+40+20>>2]|0)+((o+n^l+r)&s+e^o+n)|0;q=c[v>>2]|0;c[j>>2]=m+p;b=((q|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)&u|q&((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+p|0;c[w>>2]=b;n=o+n+-1841331548+(((m+p|0)>>>6|m+p<<26)^((m+p|0)>>>11|m+p<<21)^((m+p|0)>>>25|m+p<<7))+(c[g+40+24>>2]|0)+((l+r^s+e)&m+p^l+r)|0;o=c[k>>2]|0;c[v>>2]=q+n;c[t>>2]=((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n;r=l+r+-1424204075+(((q+n|0)>>>6|q+n<<26)^((q+n|0)>>>11|q+n<<21)^((q+n|0)>>>25|q+n<<7))+(c[g+40+28>>2]|0)+((s+e^m+p)&q+n^s+e)|0;l=c[h>>2]|0;c[k>>2]=o+r;y=((l|b)&((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|l&b)+(((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>2|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<30)^((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>13|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<19)^((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>22|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<10))+r|0;c[g+8>>2]=y;e=s+e+-670586216+(((o+r|0)>>>6|o+r<<26)^((o+r|0)>>>11|o+r<<21)^((o+r|0)>>>25|o+r<<7))+(c[g+40+32>>2]|0)+((m+p^q+n)&o+r^m+p)|0;s=c[w>>2]|0;c[h>>2]=l+e;b=((s|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)&y|s&((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+e|0;c[x>>2]=b;p=m+p+310598401+(((l+e|0)>>>6|l+e<<26)^((l+e|0)>>>11|l+e<<21)^((l+e|0)>>>25|l+e<<7))+(c[g+40+36>>2]|0)+((q+n^o+r)&l+e^q+n)|0;m=c[t>>2]|0;c[w>>2]=s+p;c[j>>2]=((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p;n=q+n+607225278+(((s+p|0)>>>6|s+p<<26)^((s+p|0)>>>11|s+p<<21)^((s+p|0)>>>25|s+p<<7))+(c[g+40+40>>2]|0)+((o+r^l+e)&s+p^o+r)|0;q=c[g+8>>2]|0;c[t>>2]=m+n;u=((q|b)&((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|q&b)+(((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>2|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<30)^((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>13|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<19)^((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>22|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<10))+n|0;c[v>>2]=u;r=o+r+1426881987+(((m+n|0)>>>6|m+n<<26)^((m+n|0)>>>11|m+n<<21)^((m+n|0)>>>25|m+n<<7))+(c[g+40+44>>2]|0)+((l+e^s+p)&m+n^l+e)|0;o=c[x>>2]|0;c[g+8>>2]=q+r;b=((o|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)&u|o&((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+r|0;c[k>>2]=b;e=l+e+1925078388+(((q+r|0)>>>6|q+r<<26)^((q+r|0)>>>11|q+r<<21)^((q+r|0)>>>25|q+r<<7))+(c[g+40+48>>2]|0)+((s+p^m+n)&q+r^s+p)|0;l=c[j>>2]|0;c[x>>2]=o+e;c[h>>2]=((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e;p=s+p+-2132889090+(((o+e|0)>>>6|o+e<<26)^((o+e|0)>>>11|o+e<<21)^((o+e|0)>>>25|o+e<<7))+(c[g+40+52>>2]|0)+((m+n^q+r)&o+e^m+n)|0;s=c[v>>2]|0;c[j>>2]=l+p;y=((s|b)&((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|s&b)+(((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>2|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<30)^((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>13|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<19)^((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>22|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<10))+p|0;c[w>>2]=y;n=m+n+-1680079193+(((l+p|0)>>>6|l+p<<26)^((l+p|0)>>>11|l+p<<21)^((l+p|0)>>>25|l+p<<7))+(c[g+40+56>>2]|0)+((q+r^o+e)&l+p^q+r)|0;m=c[k>>2]|0;c[v>>2]=s+n;b=((m|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)&y|m&((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+n|0;c[t>>2]=b;r=q+r+-1046744716+(((s+n|0)>>>6|s+n<<26)^((s+n|0)>>>11|s+n<<21)^((s+n|0)>>>25|s+n<<7))+(c[g+40+60>>2]|0)+((o+e^l+p)&s+n^o+e)|0;q=c[h>>2]|0;c[k>>2]=m+r;c[g+8>>2]=((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r;e=o+e+-459576895+(((m+r|0)>>>6|m+r<<26)^((m+r|0)>>>11|m+r<<21)^((m+r|0)>>>25|m+r<<7))+(c[g+40+64>>2]|0)+((l+p^s+n)&m+r^l+p)|0;o=c[w>>2]|0;c[h>>2]=q+e;u=((o|b)&((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|o&b)+(((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>2|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<30)^((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>13|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<19)^((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>22|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<10))+e|0;c[x>>2]=u;p=l+p+-272742522+(((q+e|0)>>>6|q+e<<26)^((q+e|0)>>>11|q+e<<21)^((q+e|0)>>>25|q+e<<7))+(c[g+40+68>>2]|0)+((s+n^m+r)&q+e^s+n)|0;l=c[t>>2]|0;c[w>>2]=o+p;b=((l|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)&u|l&((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+p|0;c[j>>2]=b;n=s+n+264347078+(((o+p|0)>>>6|o+p<<26)^((o+p|0)>>>11|o+p<<21)^((o+p|0)>>>25|o+p<<7))+(c[g+40+72>>2]|0)+((m+r^q+e)&o+p^m+r)|0;s=c[g+8>>2]|0;c[t>>2]=l+n;c[v>>2]=((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n;r=m+r+604807628+(((l+n|0)>>>6|l+n<<26)^((l+n|0)>>>11|l+n<<21)^((l+n|0)>>>25|l+n<<7))+(c[g+40+76>>2]|0)+((q+e^o+p)&l+n^q+e)|0;m=c[x>>2]|0;c[g+8>>2]=s+r;y=((m|b)&((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|m&b)+(((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>2|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<30)^((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>13|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<19)^((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>22|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<10))+r|0;c[k>>2]=y;e=q+e+770255983+(((s+r|0)>>>6|s+r<<26)^((s+r|0)>>>11|s+r<<21)^((s+r|0)>>>25|s+r<<7))+(c[g+40+80>>2]|0)+((o+p^l+n)&s+r^o+p)|0;q=c[j>>2]|0;c[x>>2]=m+e;b=((q|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)&y|q&((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+e|0;c[h>>2]=b;p=o+p+1249150122+(((m+e|0)>>>6|m+e<<26)^((m+e|0)>>>11|m+e<<21)^((m+e|0)>>>25|m+e<<7))+(c[g+40+84>>2]|0)+((l+n^s+r)&m+e^l+n)|0;o=c[v>>2]|0;c[j>>2]=q+p;c[w>>2]=((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p;n=l+n+1555081692+(((q+p|0)>>>6|q+p<<26)^((q+p|0)>>>11|q+p<<21)^((q+p|0)>>>25|q+p<<7))+(c[g+40+88>>2]|0)+((s+r^m+e)&q+p^s+r)|0;l=c[k>>2]|0;c[v>>2]=o+n;u=((l|b)&((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|l&b)+(((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>2|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<30)^((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>13|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<19)^((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>22|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<10))+n|0;c[t>>2]=u;r=s+r+1996064986+(((o+n|0)>>>6|o+n<<26)^((o+n|0)>>>11|o+n<<21)^((o+n|0)>>>25|o+n<<7))+(c[g+40+92>>2]|0)+((m+e^q+p)&o+n^m+e)|0;s=c[h>>2]|0;c[k>>2]=l+r;b=((s|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)&u|s&((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+r|0;c[g+8>>2]=b;e=m+e+-1740746414+(((l+r|0)>>>6|l+r<<26)^((l+r|0)>>>11|l+r<<21)^((l+r|0)>>>25|l+r<<7))+(c[g+40+96>>2]|0)+((q+p^o+n)&l+r^q+p)|0;m=c[w>>2]|0;c[h>>2]=s+e;c[x>>2]=((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e;p=q+p+-1473132947+(((s+e|0)>>>6|s+e<<26)^((s+e|0)>>>11|s+e<<21)^((s+e|0)>>>25|s+e<<7))+(c[g+40+100>>2]|0)+((o+n^l+r)&s+e^o+n)|0;q=c[t>>2]|0;c[w>>2]=m+p;y=((q|b)&((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|q&b)+(((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>2|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<30)^((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>13|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<19)^((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>22|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<10))+p|0;c[j>>2]=y;n=o+n+-1341970488+(((m+p|0)>>>6|m+p<<26)^((m+p|0)>>>11|m+p<<21)^((m+p|0)>>>25|m+p<<7))+(c[g+40+104>>2]|0)+((l+r^s+e)&m+p^l+r)|0;o=c[g+8>>2]|0;c[t>>2]=q+n;b=((o|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)&y|o&((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+n|0;c[v>>2]=b;r=l+r+-1084653625+(((q+n|0)>>>6|q+n<<26)^((q+n|0)>>>11|q+n<<21)^((q+n|0)>>>25|q+n<<7))+(c[g+40+108>>2]|0)+((s+e^m+p)&q+n^s+e)|0;l=c[x>>2]|0;c[g+8>>2]=o+r;c[k>>2]=((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r;e=s+e+-958395405+(((o+r|0)>>>6|o+r<<26)^((o+r|0)>>>11|o+r<<21)^((o+r|0)>>>25|o+r<<7))+(c[g+40+112>>2]|0)+((m+p^q+n)&o+r^m+p)|0;s=c[j>>2]|0;c[x>>2]=l+e;u=((s|b)&((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|s&b)+(((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>2|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<30)^((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>13|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<19)^((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>22|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<10))+e|0;c[h>>2]=u;p=m+p+-710438585+(((l+e|0)>>>6|l+e<<26)^((l+e|0)>>>11|l+e<<21)^((l+e|0)>>>25|l+e<<7))+(c[g+40+116>>2]|0)+((q+n^o+r)&l+e^q+n)|0;m=c[v>>2]|0;c[j>>2]=s+p;b=((m|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)&u|m&((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+p|0;c[w>>2]=b;n=q+n+113926993+(((s+p|0)>>>6|s+p<<26)^((s+p|0)>>>11|s+p<<21)^((s+p|0)>>>25|s+p<<7))+(c[g+40+120>>2]|0)+((o+r^l+e)&s+p^o+r)|0;q=c[k>>2]|0;c[v>>2]=m+n;c[t>>2]=((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n;r=o+r+338241895+(((m+n|0)>>>6|m+n<<26)^((m+n|0)>>>11|m+n<<21)^((m+n|0)>>>25|m+n<<7))+(c[g+40+124>>2]|0)+((l+e^s+p)&m+n^l+e)|0;o=c[h>>2]|0;c[k>>2]=q+r;y=((o|b)&((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|o&b)+(((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>2|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<30)^((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>13|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<19)^((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>22|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<10))+r|0;c[g+8>>2]=y;e=l+e+666307205+(((q+r|0)>>>6|q+r<<26)^((q+r|0)>>>11|q+r<<21)^((q+r|0)>>>25|q+r<<7))+(c[g+40+128>>2]|0)+((s+p^m+n)&q+r^s+p)|0;l=c[w>>2]|0;c[h>>2]=o+e;b=((l|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)&y|l&((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+e|0;c[x>>2]=b;p=s+p+773529912+(((o+e|0)>>>6|o+e<<26)^((o+e|0)>>>11|o+e<<21)^((o+e|0)>>>25|o+e<<7))+(c[g+40+132>>2]|0)+((m+n^q+r)&o+e^m+n)|0;s=c[t>>2]|0;c[w>>2]=l+p;c[j>>2]=((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p;n=m+n+1294757372+(((l+p|0)>>>6|l+p<<26)^((l+p|0)>>>11|l+p<<21)^((l+p|0)>>>25|l+p<<7))+(c[g+40+136>>2]|0)+((q+r^o+e)&l+p^q+r)|0;m=c[g+8>>2]|0;c[t>>2]=s+n;u=((m|b)&((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|m&b)+(((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>2|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<30)^((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>13|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<19)^((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>22|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<10))+n|0;c[v>>2]=u;r=q+r+1396182291+(((s+n|0)>>>6|s+n<<26)^((s+n|0)>>>11|s+n<<21)^((s+n|0)>>>25|s+n<<7))+(c[g+40+140>>2]|0)+((o+e^l+p)&s+n^o+e)|0;q=c[x>>2]|0;c[g+8>>2]=m+r;b=((q|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)&u|q&((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+r|0;c[k>>2]=b;e=o+e+1695183700+(((m+r|0)>>>6|m+r<<26)^((m+r|0)>>>11|m+r<<21)^((m+r|0)>>>25|m+r<<7))+(c[g+40+144>>2]|0)+((l+p^s+n)&m+r^l+p)|0;o=c[j>>2]|0;c[x>>2]=q+e;c[h>>2]=((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e;p=l+p+1986661051+(((q+e|0)>>>6|q+e<<26)^((q+e|0)>>>11|q+e<<21)^((q+e|0)>>>25|q+e<<7))+(c[g+40+148>>2]|0)+((s+n^m+r)&q+e^s+n)|0;l=c[v>>2]|0;c[j>>2]=o+p;y=((l|b)&((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|l&b)+(((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>2|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<30)^((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>13|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<19)^((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>22|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<10))+p|0;c[w>>2]=y;n=s+n+-2117940946+(((o+p|0)>>>6|o+p<<26)^((o+p|0)>>>11|o+p<<21)^((o+p|0)>>>25|o+p<<7))+(c[g+40+152>>2]|0)+((m+r^q+e)&o+p^m+r)|0;s=c[k>>2]|0;c[v>>2]=l+n;b=((s|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)&y|s&((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+n|0;c[t>>2]=b;r=m+r+-1838011259+(((l+n|0)>>>6|l+n<<26)^((l+n|0)>>>11|l+n<<21)^((l+n|0)>>>25|l+n<<7))+(c[g+40+156>>2]|0)+((q+e^o+p)&l+n^q+e)|0;m=c[h>>2]|0;c[k>>2]=s+r;c[g+8>>2]=((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r;e=q+e+-1564481375+(((s+r|0)>>>6|s+r<<26)^((s+r|0)>>>11|s+r<<21)^((s+r|0)>>>25|s+r<<7))+(c[g+40+160>>2]|0)+((o+p^l+n)&s+r^o+p)|0;q=c[w>>2]|0;c[h>>2]=m+e;u=((q|b)&((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|q&b)+(((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>2|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<30)^((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>13|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<19)^((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>22|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<10))+e|0;c[x>>2]=u;p=o+p+-1474664885+(((m+e|0)>>>6|m+e<<26)^((m+e|0)>>>11|m+e<<21)^((m+e|0)>>>25|m+e<<7))+(c[g+40+164>>2]|0)+((l+n^s+r)&m+e^l+n)|0;o=c[t>>2]|0;c[w>>2]=q+p;b=((o|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)&u|o&((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+p|0;c[j>>2]=b;n=l+n+-1035236496+(((q+p|0)>>>6|q+p<<26)^((q+p|0)>>>11|q+p<<21)^((q+p|0)>>>25|q+p<<7))+(c[g+40+168>>2]|0)+((s+r^m+e)&q+p^s+r)|0;l=c[g+8>>2]|0;c[t>>2]=o+n;c[v>>2]=((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n;r=s+r+-949202525+(((o+n|0)>>>6|o+n<<26)^((o+n|0)>>>11|o+n<<21)^((o+n|0)>>>25|o+n<<7))+(c[g+40+172>>2]|0)+((m+e^q+p)&o+n^m+e)|0;s=c[x>>2]|0;c[g+8>>2]=l+r;y=((s|b)&((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|s&b)+(((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>2|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<30)^((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>13|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<19)^((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>22|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<10))+r|0;c[k>>2]=y;e=m+e+-778901479+(((l+r|0)>>>6|l+r<<26)^((l+r|0)>>>11|l+r<<21)^((l+r|0)>>>25|l+r<<7))+(c[g+40+176>>2]|0)+((q+p^o+n)&l+r^q+p)|0;m=c[j>>2]|0;c[x>>2]=s+e;b=((m|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)&y|m&((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+e|0;c[h>>2]=b;p=q+p+-694614492+(((s+e|0)>>>6|s+e<<26)^((s+e|0)>>>11|s+e<<21)^((s+e|0)>>>25|s+e<<7))+(c[g+40+180>>2]|0)+((o+n^l+r)&s+e^o+n)|0;q=c[v>>2]|0;c[j>>2]=m+p;c[w>>2]=((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p;n=o+n+-200395387+(((m+p|0)>>>6|m+p<<26)^((m+p|0)>>>11|m+p<<21)^((m+p|0)>>>25|m+p<<7))+(c[g+40+184>>2]|0)+((l+r^s+e)&m+p^l+r)|0;o=c[k>>2]|0;c[v>>2]=q+n;u=((o|b)&((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|o&b)+(((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>2|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<30)^((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>13|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<19)^((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>22|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<10))+n|0;c[t>>2]=u;r=l+r+275423344+(((q+n|0)>>>6|q+n<<26)^((q+n|0)>>>11|q+n<<21)^((q+n|0)>>>25|q+n<<7))+(c[g+40+188>>2]|0)+((s+e^m+p)&q+n^s+e)|0;l=c[h>>2]|0;c[k>>2]=o+r;b=((l|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)&u|l&((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+r|0;c[g+8>>2]=b;e=s+e+430227734+(((o+r|0)>>>6|o+r<<26)^((o+r|0)>>>11|o+r<<21)^((o+r|0)>>>25|o+r<<7))+(c[g+40+192>>2]|0)+((m+p^q+n)&o+r^m+p)|0;s=c[w>>2]|0;c[h>>2]=l+e;c[x>>2]=((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e;p=m+p+506948616+(((l+e|0)>>>6|l+e<<26)^((l+e|0)>>>11|l+e<<21)^((l+e|0)>>>25|l+e<<7))+(c[g+40+196>>2]|0)+((q+n^o+r)&l+e^q+n)|0;m=c[t>>2]|0;c[w>>2]=s+p;y=((m|b)&((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|m&b)+(((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>2|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<30)^((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>13|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<19)^((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>22|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<10))+p|0;c[j>>2]=y;n=q+n+659060556+(((s+p|0)>>>6|s+p<<26)^((s+p|0)>>>11|s+p<<21)^((s+p|0)>>>25|s+p<<7))+(c[g+40+200>>2]|0)+((o+r^l+e)&s+p^o+r)|0;q=c[g+8>>2]|0;c[t>>2]=m+n;b=((q|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)&y|q&((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+n|0;c[v>>2]=b;r=o+r+883997877+(((m+n|0)>>>6|m+n<<26)^((m+n|0)>>>11|m+n<<21)^((m+n|0)>>>25|m+n<<7))+(c[g+40+204>>2]|0)+((l+e^s+p)&m+n^l+e)|0;o=c[x>>2]|0;c[g+8>>2]=q+r;c[k>>2]=((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r;e=l+e+958139571+(((q+r|0)>>>6|q+r<<26)^((q+r|0)>>>11|q+r<<21)^((q+r|0)>>>25|q+r<<7))+(c[g+40+208>>2]|0)+((s+p^m+n)&q+r^s+p)|0;l=c[j>>2]|0;c[x>>2]=o+e;u=((l|b)&((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|l&b)+(((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>2|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<30)^((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>13|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<19)^((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>22|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<10))+e|0;c[h>>2]=u;p=s+p+1322822218+(((o+e|0)>>>6|o+e<<26)^((o+e|0)>>>11|o+e<<21)^((o+e|0)>>>25|o+e<<7))+(c[g+40+212>>2]|0)+((m+n^q+r)&o+e^m+n)|0;s=c[v>>2]|0;c[j>>2]=l+p;b=((s|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)&u|s&((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+p|0;c[w>>2]=b;n=m+n+1537002063+(((l+p|0)>>>6|l+p<<26)^((l+p|0)>>>11|l+p<<21)^((l+p|0)>>>25|l+p<<7))+(c[g+40+216>>2]|0)+((q+r^o+e)&l+p^q+r)|0;m=c[k>>2]|0;c[v>>2]=s+n;c[t>>2]=((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n;r=q+r+1747873779+(((s+n|0)>>>6|s+n<<26)^((s+n|0)>>>11|s+n<<21)^((s+n|0)>>>25|s+n<<7))+(c[g+40+220>>2]|0)+((o+e^l+p)&s+n^o+e)|0;q=c[h>>2]|0;c[k>>2]=m+r;y=((q|b)&((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|q&b)+(((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>2|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<30)^((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>13|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<19)^((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>22|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<10))+r|0;c[g+8>>2]=y;e=o+e+1955562222+(((m+r|0)>>>6|m+r<<26)^((m+r|0)>>>11|m+r<<21)^((m+r|0)>>>25|m+r<<7))+(c[g+40+224>>2]|0)+((l+p^s+n)&m+r^l+p)|0;o=c[w>>2]|0;c[h>>2]=q+e;b=((o|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)&y|o&((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+e|0;c[x>>2]=b;p=l+p+2024104815+(((q+e|0)>>>6|q+e<<26)^((q+e|0)>>>11|q+e<<21)^((q+e|0)>>>25|q+e<<7))+(c[g+40+228>>2]|0)+((s+n^m+r)&q+e^s+n)|0;l=c[t>>2]|0;c[w>>2]=o+p;c[j>>2]=((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p;n=s+n+-2067236844+(((o+p|0)>>>6|o+p<<26)^((o+p|0)>>>11|o+p<<21)^((o+p|0)>>>25|o+p<<7))+(c[g+40+232>>2]|0)+((m+r^q+e)&o+p^m+r)|0;s=c[g+8>>2]|0;c[t>>2]=l+n;u=((s|b)&((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|s&b)+(((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>2|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<30)^((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>13|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<19)^((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>22|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<10))+n|0;c[v>>2]=u;r=m+r+-1933114872+(((l+n|0)>>>6|l+n<<26)^((l+n|0)>>>11|l+n<<21)^((l+n|0)>>>25|l+n<<7))+(c[g+40+236>>2]|0)+((q+e^o+p)&l+n^q+e)|0;m=c[x>>2]|0;c[g+8>>2]=s+r;b=((m|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)&u|m&((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+r|0;c[k>>2]=b;e=q+e+-1866530822+(((s+r|0)>>>6|s+r<<26)^((s+r|0)>>>11|s+r<<21)^((s+r|0)>>>25|s+r<<7))+(c[g+40+240>>2]|0)+((o+p^l+n)&s+r^o+p)|0;q=c[j>>2]|0;c[x>>2]=m+e;c[h>>2]=((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e;p=o+p+-1538233109+(((m+e|0)>>>6|m+e<<26)^((m+e|0)>>>11|m+e<<21)^((m+e|0)>>>25|m+e<<7))+(c[g+40+244>>2]|0)+((l+n^s+r)&m+e^l+n)|0;o=c[v>>2]|0;c[j>>2]=q+p;j=((o|b)&((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|o&b)+(((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>2|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<30)^((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>13|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<19)^((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>22|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<10))+p|0;c[w>>2]=j;n=l+n+-1090935817+(((q+p|0)>>>6|q+p<<26)^((q+p|0)>>>11|q+p<<21)^((q+p|0)>>>25|q+p<<7))+(c[g+40+248>>2]|0)+((s+r^m+e)&q+p^s+r)|0;l=c[k>>2]|0;c[v>>2]=o+n;b=((l|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)&j|l&((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)+((j>>>2|j<<30)^(j>>>13|j<<19)^(j>>>22|j<<10))+n|0;c[t>>2]=b;e=s+r+-965641998+(((o+n|0)>>>6|o+n<<26)^((o+n|0)>>>11|o+n<<21)^((o+n|0)>>>25|o+n<<7))+(c[g+40+252>>2]|0)+((m+e^q+p)&o+n^m+e)|0;c[g+4>>2]=e;h=c[h>>2]|0;c[g>>2]=((h|j)&b|h&j)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10));c[k>>2]=l+e;e=((h|j)&b|h&j)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0;c[g+8>>2]=e;c[a>>2]=(c[a>>2]|0)+e;e=1;while(1){y=a+(e<<2)|0;c[y>>2]=(c[y>>2]|0)+b;e=e+1|0;if((e|0)==8)break;b=c[g+8+(e<<2)>>2]|0}fd(g+40|0,256);fd(g+8|0,32);fd(g+4|0,4);fd(g,4);i=f;return}function la(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0;r=i;q=i=i+63&-64;i=i+4096|0;if(b){p=na(c[b+12>>2]<<3)|0;if(!p)e=-22;else{kf(q+3072|0);kf(q+2048|0);l=c[d>>2]|0;c[q+2048>>2]=l;c[q+2048+4>>2]=0;j=c[d+4>>2]|0;c[q+2048+8>>2]=j;c[q+2048+8+4>>2]=0;k=a[d+8>>0]|0;c[q+2048+16>>2]=k&255;c[q+2048+16+4>>2]=0;c[q+2048+24>>2]=c[b+8>>2];c[q+2048+24+4>>2]=0;c[q+2048+32>>2]=c[b+4>>2];c[q+2048+32+4>>2]=0;c[q+2048+40>>2]=c[b+28>>2];c[q+2048+40+4>>2]=0;e=c[b+12>>2]|0;if(!e)f=0;else{g=0;do{f=g&127;if(!f){e=oe(c[q+2048+48>>2]|0,c[q+2048+48+4>>2]|0,1,0)|0;c[q+2048+48>>2]=e;c[q+2048+48+4>>2]=D;kf(q);kf(q+1024|0);ma(q+3072|0,q+2048|0,q);ma(q+3072|0,q,q+1024|0);e=c[b+12>>2]|0}n=c[q+1024+(f<<3)+4>>2]|0;o=p+(g<<3)|0;c[o>>2]=c[q+1024+(f<<3)>>2];c[o+4>>2]=n;g=g+1|0}while(g>>>0<e>>>0);f=e}e=(l|0)==0&k<<24>>24==0?2:0;h=c[b+16>>2]|0;g=(S(h,j)|0)+e+(S(k&255,f)|0)|0;a:do if(e>>>0<f>>>0){o=g;f=(((g>>>0)%(h>>>0)|0|0)==0?h+-1|0:-1)+g|0;m=h;g=l;while(1){n=((o>>>0)%(m>>>0)|0|0)==1?o+-1|0:f;f=p+(e<<3)|0;j=c[f>>2]|0;f=Bd(c[f+4>>2]|0,0,c[b+20>>2]|0,0)|0;h=D;l=(g|0)==0;if(l?(a[d+8>>0]|0)==0:0){f=c[d+4>>2]|0;h=0}c[d+12>>2]=e;j=Eb(b,d,j,((h|0)==0?(f|0)==(c[d+4>>2]|0):0)&1)|0;k=c[(c[b>>2]|0)+4>>2]|0;f=Ed(m|0,0,f|0,h|0)|0;g=k+(o<<10)|0;if(l){ef(q+3072|0,k+(f<<10)+(j<<10)|0);gd(q+3072|0,k+(n<<10)|0);ef(q+2048|0,q+3072|0);f=0;do{m=f<<4;z=c[q+3072+(m<<3)>>2]|0;G=c[q+3072+(m<<3)+4>>2]|0;u=c[q+3072+((m|4)<<3)>>2]|0;s=c[q+3072+((m|4)<<3)+4>>2]|0;l=oe(u|0,s|0,z|0,G|0)|0;v=D;G=Pd(z|0,G|0,1)|0;G=Ed(G&-2|0,D&1|0,u|0,0)|0;G=oe(l|0,v|0,G|0,D|0)|0;v=D;l=G^c[q+3072+((m|12)<<3)>>2];z=v^c[q+3072+((m|12)<<3)+4>>2];y=c[q+3072+((m|8)<<3)>>2]|0;A=c[q+3072+((m|8)<<3)+4>>2]|0;C=oe(z|0,l|0,y|0,A|0)|0;j=D;A=Pd(y|0,A|0,1)|0;A=Ed(z|0,0,A&-2|0,D&1|0)|0;A=oe(C|0,j|0,A|0,D|0)|0;j=D;C=Rd(A^u|0,j^s|0,24)|0;y=D;s=Pd(A^u|0,j^s|0,40)|0;y=D|y;u=oe(s|C|0,y|0,G|0,v|0)|0;h=D;v=Pd(G|0,v|0,1)|0;v=Ed(C|0,0,v&-2|0,D&1|0)|0;v=oe(u|0,h|0,v|0,D|0)|0;h=D;c[q+3072+(m<<3)>>2]=v;c[q+3072+(m<<3)+4>>2]=h;u=Rd(v^z|0,h^l|0,16)|0;G=D;l=Pd(v^z|0,h^l|0,48)|0;G=D|G;c[q+3072+((m|12)<<3)>>2]=l|u;c[q+3072+((m|12)<<3)+4>>2]=G;G=oe(l|u|0,G|0,A|0,j|0)|0;l=D;j=Pd(A|0,j|0,1)|0;j=Ed(u|0,0,j&-2|0,D&1|0)|0;j=oe(G|0,l|0,j|0,D|0)|0;l=D;c[q+3072+((m|8)<<3)>>2]=j;c[q+3072+((m|8)<<3)+4>>2]=l;G=Rd(j^(s|C)|0,l^y|0,63)|0;u=D;y=Pd(j^(s|C)|0,l^y|0,1)|0;c[q+3072+((m|4)<<3)>>2]=y|G;c[q+3072+((m|4)<<3)+4>>2]=D|u;u=c[q+3072+((m|1)<<3)>>2]|0;G=c[q+3072+((m|1)<<3)+4>>2]|0;y=c[q+3072+((m|5)<<3)>>2]|0;l=c[q+3072+((m|5)<<3)+4>>2]|0;C=oe(y|0,l|0,u|0,G|0)|0;s=D;G=Pd(u|0,G|0,1)|0;G=Ed(G&-2|0,D&1|0,y|0,0)|0;G=oe(C|0,s|0,G|0,D|0)|0;s=D;C=G^c[q+3072+((m|13)<<3)>>2];u=s^c[q+3072+((m|13)<<3)+4>>2];j=c[q+3072+((m|9)<<3)>>2]|0;A=c[q+3072+((m|9)<<3)+4>>2]|0;h=oe(u|0,C|0,j|0,A|0)|0;z=D;A=Pd(j|0,A|0,1)|0;A=Ed(u|0,0,A&-2|0,D&1|0)|0;A=oe(h|0,z|0,A|0,D|0)|0;z=D;h=Rd(A^y|0,z^l|0,24)|0;j=D;l=Pd(A^y|0,z^l|0,40)|0;j=D|j;y=oe(l|h|0,j|0,G|0,s|0)|0;v=D;s=Pd(G|0,s|0,1)|0;s=Ed(h|0,0,s&-2|0,D&1|0)|0;s=oe(y|0,v|0,s|0,D|0)|0;v=D;c[q+3072+((m|1)<<3)>>2]=s;c[q+3072+((m|1)<<3)+4>>2]=v;y=Rd(s^u|0,v^C|0,16)|0;G=D;C=Pd(s^u|0,v^C|0,48)|0;G=D|G;c[q+3072+((m|13)<<3)>>2]=C|y;c[q+3072+((m|13)<<3)+4>>2]=G;G=oe(C|y|0,G|0,A|0,z|0)|0;C=D;z=Pd(A|0,z|0,1)|0;z=Ed(y|0,0,z&-2|0,D&1|0)|0;z=oe(G|0,C|0,z|0,D|0)|0;C=D;c[q+3072+((m|9)<<3)>>2]=z;c[q+3072+((m|9)<<3)+4>>2]=C;G=Rd(z^(l|h)|0,C^j|0,63)|0;y=D;j=Pd(z^(l|h)|0,C^j|0,1)|0;c[q+3072+((m|5)<<3)>>2]=j|G;c[q+3072+((m|5)<<3)+4>>2]=D|y;y=c[q+3072+((m|2)<<3)>>2]|0;G=c[q+3072+((m|2)<<3)+4>>2]|0;j=c[q+3072+((m|6)<<3)>>2]|0;C=c[q+3072+((m|6)<<3)+4>>2]|0;h=oe(j|0,C|0,y|0,G|0)|0;l=D;G=Pd(y|0,G|0,1)|0;G=Ed(G&-2|0,D&1|0,j|0,0)|0;G=oe(h|0,l|0,G|0,D|0)|0;l=D;h=G^c[q+3072+((m|14)<<3)>>2];y=l^c[q+3072+((m|14)<<3)+4>>2];z=c[q+3072+((m|10)<<3)>>2]|0;A=c[q+3072+((m|10)<<3)+4>>2]|0;v=oe(y|0,h|0,z|0,A|0)|0;u=D;A=Pd(z|0,A|0,1)|0;A=Ed(y|0,0,A&-2|0,D&1|0)|0;A=oe(v|0,u|0,A|0,D|0)|0;u=D;v=Rd(A^j|0,u^C|0,24)|0;z=D;C=Pd(A^j|0,u^C|0,40)|0;z=D|z;j=oe(C|v|0,z|0,G|0,l|0)|0;s=D;l=Pd(G|0,l|0,1)|0;l=Ed(v|0,0,l&-2|0,D&1|0)|0;l=oe(j|0,s|0,l|0,D|0)|0;s=D;c[q+3072+((m|2)<<3)>>2]=l;c[q+3072+((m|2)<<3)+4>>2]=s;j=Rd(l^y|0,s^h|0,16)|0;G=D;h=Pd(l^y|0,s^h|0,48)|0;G=D|G;c[q+3072+((m|14)<<3)>>2]=h|j;c[q+3072+((m|14)<<3)+4>>2]=G;G=oe(h|j|0,G|0,A|0,u|0)|0;h=D;u=Pd(A|0,u|0,1)|0;u=Ed(j|0,0,u&-2|0,D&1|0)|0;u=oe(G|0,h|0,u|0,D|0)|0;h=D;G=Rd(u^(C|v)|0,h^z|0,63)|0;j=D;z=Pd(u^(C|v)|0,h^z|0,1)|0;c[q+3072+((m|6)<<3)>>2]=z|G;c[q+3072+((m|6)<<3)+4>>2]=D|j;j=c[q+3072+((m|3)<<3)>>2]|0;G=c[q+3072+((m|3)<<3)+4>>2]|0;z=c[q+3072+((m|7)<<3)>>2]|0;v=c[q+3072+((m|7)<<3)+4>>2]|0;C=oe(z|0,v|0,j|0,G|0)|0;A=D;G=Pd(j|0,G|0,1)|0;G=Ed(G&-2|0,D&1|0,z|0,0)|0;G=oe(C|0,A|0,G|0,D|0)|0;A=D;C=G^c[q+3072+((m|15)<<3)>>2];j=A^c[q+3072+((m|15)<<3)+4>>2];s=c[q+3072+((m|11)<<3)>>2]|0;y=c[q+3072+((m|11)<<3)+4>>2]|0;l=oe(j|0,C|0,s|0,y|0)|0;t=D;y=Pd(s|0,y|0,1)|0;y=Ed(j|0,0,y&-2|0,D&1|0)|0;y=oe(l|0,t|0,y|0,D|0)|0;t=D;l=Rd(y^z|0,t^v|0,24)|0;s=D;v=Pd(y^z|0,t^v|0,40)|0;s=D|s;z=oe(v|l|0,s|0,G|0,A|0)|0;x=D;A=Pd(G|0,A|0,1)|0;A=Ed(l|0,0,A&-2|0,D&1|0)|0;A=oe(z|0,x|0,A|0,D|0)|0;x=D;c[q+3072+((m|3)<<3)>>2]=A;c[q+3072+((m|3)<<3)+4>>2]=x;z=Rd(A^j|0,x^C|0,16)|0;G=D;C=Pd(A^j|0,x^C|0,48)|0;G=D|G;x=oe(C|z|0,G|0,y|0,t|0)|0;j=D;t=Pd(y|0,t|0,1)|0;t=Ed(z|0,0,t&-2|0,D&1|0)|0;t=oe(x|0,j|0,t|0,D|0)|0;j=D;x=Rd(t^(v|l)|0,j^s|0,63)|0;y=D;s=Pd(t^(v|l)|0,j^s|0,1)|0;y=D|y;c[q+3072+((m|7)<<3)>>2]=s|x;c[q+3072+((m|7)<<3)+4>>2]=y;l=c[q+3072+(m<<3)>>2]|0;v=c[q+3072+(m<<3)+4>>2]|0;A=c[q+3072+((m|5)<<3)>>2]|0;B=c[q+3072+((m|5)<<3)+4>>2]|0;w=oe(A|0,B|0,l|0,v|0)|0;F=D;v=Pd(l|0,v|0,1)|0;v=Ed(v&-2|0,D&1|0,A|0,0)|0;v=oe(w|0,F|0,v|0,D|0)|0;F=D;w=oe(G^F|0,(C|z)^v|0,u|0,h|0)|0;l=D;h=Pd(u|0,h|0,1)|0;h=Ed(G^F|0,0,h&-2|0,D&1|0)|0;h=oe(w|0,l|0,h|0,D|0)|0;l=D;w=Rd(h^A|0,l^B|0,24)|0;u=D;B=Pd(h^A|0,l^B|0,40)|0;u=D|u;A=oe(B|w|0,u|0,v|0,F|0)|0;E=D;H=Pd(v|0,F|0,1)|0;H=Ed(w|0,0,H&-2|0,D&1|0)|0;H=oe(A|0,E|0,H|0,D|0)|0;E=D;c[q+3072+(m<<3)>>2]=H;c[q+3072+(m<<3)+4>>2]=E;A=Rd(H^(G^F)|0,E^((C|z)^v)|0,16)|0;k=D;v=Pd(H^(G^F)|0,E^((C|z)^v)|0,48)|0;k=D|k;c[q+3072+((m|15)<<3)>>2]=v|A;c[q+3072+((m|15)<<3)+4>>2]=k;k=oe(v|A|0,k|0,h|0,l|0)|0;v=D;l=Pd(h|0,l|0,1)|0;l=Ed(A|0,0,l&-2|0,D&1|0)|0;l=oe(k|0,v|0,l|0,D|0)|0;v=D;c[q+3072+((m|10)<<3)>>2]=l;c[q+3072+((m|10)<<3)+4>>2]=v;k=Rd(l^(B|w)|0,v^u|0,63)|0;A=D;u=Pd(l^(B|w)|0,v^u|0,1)|0;c[q+3072+((m|5)<<3)>>2]=u|k;c[q+3072+((m|5)<<3)+4>>2]=D|A;A=c[q+3072+((m|1)<<3)>>2]|0;k=c[q+3072+((m|1)<<3)+4>>2]|0;u=c[q+3072+((m|6)<<3)>>2]|0;v=c[q+3072+((m|6)<<3)+4>>2]|0;w=oe(u|0,v|0,A|0,k|0)|0;B=D;k=Pd(A|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,u|0,0)|0;k=oe(w|0,B|0,k|0,D|0)|0;B=D;w=k^c[q+3072+((m|12)<<3)>>2];A=B^c[q+3072+((m|12)<<3)+4>>2];l=oe(A|0,w|0,t|0,j|0)|0;h=D;j=Pd(t|0,j|0,1)|0;j=Ed(j&-2|0,D&1|0,A|0,0)|0;j=oe(l|0,h|0,j|0,D|0)|0;h=D;l=Rd(j^u|0,h^v|0,24)|0;t=D;v=Pd(j^u|0,h^v|0,40)|0;t=D|t;u=oe(v|l|0,t|0,k|0,B|0)|0;z=D;B=Pd(k|0,B|0,1)|0;B=Ed(l|0,0,B&-2|0,D&1|0)|0;B=oe(u|0,z|0,B|0,D|0)|0;z=D;c[q+3072+((m|1)<<3)>>2]=B;c[q+3072+((m|1)<<3)+4>>2]=z;u=Rd(B^A|0,z^w|0,16)|0;k=D;w=Pd(B^A|0,z^w|0,48)|0;k=D|k;c[q+3072+((m|12)<<3)>>2]=w|u;c[q+3072+((m|12)<<3)+4>>2]=k;k=oe(w|u|0,k|0,j|0,h|0)|0;w=D;h=Pd(j|0,h|0,1)|0;h=Ed(u|0,0,h&-2|0,D&1|0)|0;h=oe(k|0,w|0,h|0,D|0)|0;w=D;c[q+3072+((m|11)<<3)>>2]=h;c[q+3072+((m|11)<<3)+4>>2]=w;k=Rd(h^(v|l)|0,w^t|0,63)|0;u=D;t=Pd(h^(v|l)|0,w^t|0,1)|0;c[q+3072+((m|6)<<3)>>2]=t|k;c[q+3072+((m|6)<<3)+4>>2]=D|u;u=c[q+3072+((m|2)<<3)>>2]|0;k=c[q+3072+((m|2)<<3)+4>>2]|0;t=oe(s|x|0,y|0,u|0,k|0)|0;w=D;k=Pd(u|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,s|x|0,0)|0;k=oe(t|0,w|0,k|0,D|0)|0;w=D;t=k^c[q+3072+((m|13)<<3)>>2];u=w^c[q+3072+((m|13)<<3)+4>>2];l=c[q+3072+((m|8)<<3)>>2]|0;v=c[q+3072+((m|8)<<3)+4>>2]|0;h=oe(u|0,t|0,l|0,v|0)|0;j=D;v=Pd(l|0,v|0,1)|0;v=Ed(u|0,0,v&-2|0,D&1|0)|0;v=oe(h|0,j|0,v|0,D|0)|0;j=D;h=Rd(v^(s|x)|0,j^y|0,24)|0;l=D;y=Pd(v^(s|x)|0,j^y|0,40)|0;l=D|l;x=oe(y|h|0,l|0,k|0,w|0)|0;s=D;w=Pd(k|0,w|0,1)|0;w=Ed(h|0,0,w&-2|0,D&1|0)|0;w=oe(x|0,s|0,w|0,D|0)|0;s=D;c[q+3072+((m|2)<<3)>>2]=w;c[q+3072+((m|2)<<3)+4>>2]=s;x=Rd(w^u|0,s^t|0,16)|0;k=D;t=Pd(w^u|0,s^t|0,48)|0;k=D|k;c[q+3072+((m|13)<<3)>>2]=t|x;c[q+3072+((m|13)<<3)+4>>2]=k;k=oe(t|x|0,k|0,v|0,j|0)|0;t=D;j=Pd(v|0,j|0,1)|0;j=Ed(x|0,0,j&-2|0,D&1|0)|0;j=oe(k|0,t|0,j|0,D|0)|0;t=D;c[q+3072+((m|8)<<3)>>2]=j;c[q+3072+((m|8)<<3)+4>>2]=t;k=Rd(j^(y|h)|0,t^l|0,63)|0;x=D;l=Pd(j^(y|h)|0,t^l|0,1)|0;c[q+3072+((m|7)<<3)>>2]=l|k;c[q+3072+((m|7)<<3)+4>>2]=D|x;x=c[q+3072+((m|3)<<3)>>2]|0;k=c[q+3072+((m|3)<<3)+4>>2]|0;l=c[q+3072+((m|4)<<3)>>2]|0;t=c[q+3072+((m|4)<<3)+4>>2]|0;h=oe(l|0,t|0,x|0,k|0)|0;y=D;k=Pd(x|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,l|0,0)|0;k=oe(h|0,y|0,k|0,D|0)|0;y=D;h=k^c[q+3072+((m|14)<<3)>>2];x=y^c[q+3072+((m|14)<<3)+4>>2];j=c[q+3072+((m|9)<<3)>>2]|0;v=c[q+3072+((m|9)<<3)+4>>2]|0;s=oe(x|0,h|0,j|0,v|0)|0;u=D;v=Pd(j|0,v|0,1)|0;v=Ed(x|0,0,v&-2|0,D&1|0)|0;v=oe(s|0,u|0,v|0,D|0)|0;u=D;s=Rd(v^l|0,u^t|0,24)|0;j=D;t=Pd(v^l|0,u^t|0,40)|0;j=D|j;l=oe(t|s|0,j|0,k|0,y|0)|0;w=D;y=Pd(k|0,y|0,1)|0;y=Ed(s|0,0,y&-2|0,D&1|0)|0;y=oe(l|0,w|0,y|0,D|0)|0;w=D;c[q+3072+((m|3)<<3)>>2]=y;c[q+3072+((m|3)<<3)+4>>2]=w;l=Rd(y^x|0,w^h|0,16)|0;k=D;h=Pd(y^x|0,w^h|0,48)|0;k=D|k;c[q+3072+((m|14)<<3)>>2]=h|l;c[q+3072+((m|14)<<3)+4>>2]=k;k=oe(h|l|0,k|0,v|0,u|0)|0;h=D;u=Pd(v|0,u|0,1)|0;u=Ed(l|0,0,u&-2|0,D&1|0)|0;u=oe(k|0,h|0,u|0,D|0)|0;h=D;c[q+3072+((m|9)<<3)>>2]=u;c[q+3072+((m|9)<<3)+4>>2]=h;k=Rd(u^(t|s)|0,h^j|0,63)|0;l=D;j=Pd(u^(t|s)|0,h^j|0,1)|0;c[q+3072+((m|4)<<3)>>2]=j|k;c[q+3072+((m|4)<<3)+4>>2]=D|l;f=f+1|0}while((f|0)!=8);f=0;do{H=f<<1;A=c[q+3072+(H<<3)>>2]|0;E=c[q+3072+(H<<3)+4>>2]|0;v=q+3072+(H+32<<3)|0;y=c[v>>2]|0;v=c[v+4>>2]|0;s=oe(y|0,v|0,A|0,E|0)|0;j=D;E=Pd(A|0,E|0,1)|0;E=Ed(E&-2|0,D&1|0,y|0,0)|0;E=oe(s|0,j|0,E|0,D|0)|0;j=D;s=q+3072+(H+96<<3)|0;A=E^c[s>>2];s=j^c[s+4>>2];m=q+3072+(H+64<<3)|0;w=c[m>>2]|0;m=c[m+4>>2]|0;F=oe(s|0,A|0,w|0,m|0)|0;u=D;m=Pd(w|0,m|0,1)|0;m=Ed(s|0,0,m&-2|0,D&1|0)|0;m=oe(F|0,u|0,m|0,D|0)|0;u=D;F=Rd(m^y|0,u^v|0,24)|0;w=D;v=Pd(m^y|0,u^v|0,40)|0;w=D|w;y=oe(v|F|0,w|0,E|0,j|0)|0;B=D;j=Pd(E|0,j|0,1)|0;j=Ed(F|0,0,j&-2|0,D&1|0)|0;j=oe(y|0,B|0,j|0,D|0)|0;B=D;c[q+3072+(H<<3)>>2]=j;c[q+3072+(H<<3)+4>>2]=B;y=Rd(j^s|0,B^A|0,16)|0;E=D;A=Pd(j^s|0,B^A|0,48)|0;E=D|E;B=q+3072+(H+96<<3)|0;c[B>>2]=A|y;c[B+4>>2]=E;E=oe(A|y|0,E|0,m|0,u|0)|0;A=D;u=Pd(m|0,u|0,1)|0;u=Ed(y|0,0,u&-2|0,D&1|0)|0;u=oe(E|0,A|0,u|0,D|0)|0;A=D;E=q+3072+(H+64<<3)|0;c[E>>2]=u;c[E+4>>2]=A;E=Rd(u^(v|F)|0,A^w|0,63)|0;y=D;w=Pd(u^(v|F)|0,A^w|0,1)|0;A=q+3072+(H+32<<3)|0;c[A>>2]=w|E;c[A+4>>2]=D|y;A=c[q+3072+((H|1)<<3)>>2]|0;y=c[q+3072+((H|1)<<3)+4>>2]|0;E=q+3072+(H+33<<3)|0;w=c[E>>2]|0;E=c[E+4>>2]|0;F=oe(w|0,E|0,A|0,y|0)|0;v=D;y=Pd(A|0,y|0,1)|0;y=Ed(y&-2|0,D&1|0,w|0,0)|0;y=oe(F|0,v|0,y|0,D|0)|0;v=D;F=q+3072+(H+97<<3)|0;A=y^c[F>>2];F=v^c[F+4>>2];u=q+3072+(H+65<<3)|0;m=c[u>>2]|0;u=c[u+4>>2]|0;B=oe(F|0,A|0,m|0,u|0)|0;s=D;u=Pd(m|0,u|0,1)|0;u=Ed(F|0,0,u&-2|0,D&1|0)|0;u=oe(B|0,s|0,u|0,D|0)|0;s=D;B=Rd(u^w|0,s^E|0,24)|0;m=D;E=Pd(u^w|0,s^E|0,40)|0;m=D|m;w=oe(E|B|0,m|0,y|0,v|0)|0;j=D;v=Pd(y|0,v|0,1)|0;v=Ed(B|0,0,v&-2|0,D&1|0)|0;v=oe(w|0,j|0,v|0,D|0)|0;j=D;c[q+3072+((H|1)<<3)>>2]=v;c[q+3072+((H|1)<<3)+4>>2]=j;w=Rd(v^F|0,j^A|0,16)|0;y=D;A=Pd(v^F|0,j^A|0,48)|0;y=D|y;j=q+3072+(H+97<<3)|0;c[j>>2]=A|w;c[j+4>>2]=y;y=oe(A|w|0,y|0,u|0,s|0)|0;A=D;s=Pd(u|0,s|0,1)|0;s=Ed(w|0,0,s&-2|0,D&1|0)|0;s=oe(y|0,A|0,s|0,D|0)|0;A=D;y=q+3072+(H+65<<3)|0;c[y>>2]=s;c[y+4>>2]=A;y=Rd(s^(E|B)|0,A^m|0,63)|0;w=D;m=Pd(s^(E|B)|0,A^m|0,1)|0;A=q+3072+(H+33<<3)|0;c[A>>2]=m|y;c[A+4>>2]=D|w;A=q+3072+(H+16<<3)|0;w=c[A>>2]|0;A=c[A+4>>2]|0;y=q+3072+(H+48<<3)|0;m=c[y>>2]|0;y=c[y+4>>2]|0;B=oe(m|0,y|0,w|0,A|0)|0;E=D;A=Pd(w|0,A|0,1)|0;A=Ed(A&-2|0,D&1|0,m|0,0)|0;A=oe(B|0,E|0,A|0,D|0)|0;E=D;B=q+3072+(H+112<<3)|0;w=A^c[B>>2];B=E^c[B+4>>2];s=q+3072+(H+80<<3)|0;u=c[s>>2]|0;s=c[s+4>>2]|0;j=oe(B|0,w|0,u|0,s|0)|0;F=D;s=Pd(u|0,s|0,1)|0;s=Ed(B|0,0,s&-2|0,D&1|0)|0;s=oe(j|0,F|0,s|0,D|0)|0;F=D;j=Rd(s^m|0,F^y|0,24)|0;u=D;y=Pd(s^m|0,F^y|0,40)|0;u=D|u;m=oe(y|j|0,u|0,A|0,E|0)|0;v=D;E=Pd(A|0,E|0,1)|0;E=Ed(j|0,0,E&-2|0,D&1|0)|0;E=oe(m|0,v|0,E|0,D|0)|0;v=D;m=q+3072+(H+16<<3)|0;c[m>>2]=E;c[m+4>>2]=v;m=Rd(E^B|0,v^w|0,16)|0;A=D;w=Pd(E^B|0,v^w|0,48)|0;A=D|A;v=q+3072+(H+112<<3)|0;c[v>>2]=w|m;c[v+4>>2]=A;A=oe(w|m|0,A|0,s|0,F|0)|0;w=D;F=Pd(s|0,F|0,1)|0;F=Ed(m|0,0,F&-2|0,D&1|0)|0;F=oe(A|0,w|0,F|0,D|0)|0;w=D;A=Rd(F^(y|j)|0,w^u|0,63)|0;m=D;u=Pd(F^(y|j)|0,w^u|0,1)|0;j=q+3072+(H+48<<3)|0;c[j>>2]=u|A;c[j+4>>2]=D|m;j=q+3072+(H+17<<3)|0;m=c[j>>2]|0;j=c[j+4>>2]|0;A=q+3072+(H+49<<3)|0;u=c[A>>2]|0;A=c[A+4>>2]|0;y=oe(u|0,A|0,m|0,j|0)|0;s=D;j=Pd(m|0,j|0,1)|0;j=Ed(j&-2|0,D&1|0,u|0,0)|0;j=oe(y|0,s|0,j|0,D|0)|0;s=D;y=q+3072+(H+113<<3)|0;m=j^c[y>>2];y=s^c[y+4>>2];v=q+3072+(H+81<<3)|0;B=c[v>>2]|0;v=c[v+4>>2]|0;E=oe(y|0,m|0,B|0,v|0)|0;x=D;v=Pd(B|0,v|0,1)|0;v=Ed(y|0,0,v&-2|0,D&1|0)|0;v=oe(E|0,x|0,v|0,D|0)|0;x=D;E=Rd(v^u|0,x^A|0,24)|0;B=D;A=Pd(v^u|0,x^A|0,40)|0;B=D|B;u=oe(A|E|0,B|0,j|0,s|0)|0;C=D;s=Pd(j|0,s|0,1)|0;s=Ed(E|0,0,s&-2|0,D&1|0)|0;s=oe(u|0,C|0,s|0,D|0)|0;C=D;u=q+3072+(H+17<<3)|0;c[u>>2]=s;c[u+4>>2]=C;u=Rd(s^y|0,C^m|0,16)|0;j=D;m=Pd(s^y|0,C^m|0,48)|0;j=D|j;C=oe(m|u|0,j|0,v|0,x|0)|0;y=D;x=Pd(v|0,x|0,1)|0;x=Ed(u|0,0,x&-2|0,D&1|0)|0;x=oe(C|0,y|0,x|0,D|0)|0;y=D;C=Rd(x^(A|E)|0,y^B|0,63)|0;v=D;B=Pd(x^(A|E)|0,y^B|0,1)|0;v=D|v;E=q+3072+(H+49<<3)|0;c[E>>2]=B|C;c[E+4>>2]=v;E=c[q+3072+(H<<3)>>2]|0;A=c[q+3072+(H<<3)+4>>2]|0;s=q+3072+(H+33<<3)|0;z=c[s>>2]|0;s=c[s+4>>2]|0;t=oe(z|0,s|0,E|0,A|0)|0;k=D;A=Pd(E|0,A|0,1)|0;A=Ed(A&-2|0,D&1|0,z|0,0)|0;A=oe(t|0,k|0,A|0,D|0)|0;k=D;t=oe(j^k|0,(m|u)^A|0,F|0,w|0)|0;E=D;w=Pd(F|0,w|0,1)|0;w=Ed(j^k|0,0,w&-2|0,D&1|0)|0;w=oe(t|0,E|0,w|0,D|0)|0;E=D;t=Rd(w^z|0,E^s|0,24)|0;F=D;s=Pd(w^z|0,E^s|0,40)|0;F=D|F;z=oe(s|t|0,F|0,A|0,k|0)|0;l=D;h=Pd(A|0,k|0,1)|0;h=Ed(t|0,0,h&-2|0,D&1|0)|0;h=oe(z|0,l|0,h|0,D|0)|0;l=D;c[q+3072+(H<<3)>>2]=h;c[q+3072+(H<<3)+4>>2]=l;z=Rd(h^(j^k)|0,l^((m|u)^A)|0,16)|0;G=D;A=Pd(h^(j^k)|0,l^((m|u)^A)|0,48)|0;G=D|G;u=q+3072+(H+113<<3)|0;c[u>>2]=A|z;c[u+4>>2]=G;G=oe(A|z|0,G|0,w|0,E|0)|0;A=D;E=Pd(w|0,E|0,1)|0;E=Ed(z|0,0,E&-2|0,D&1|0)|0;E=oe(G|0,A|0,E|0,D|0)|0;A=D;G=q+3072+(H+80<<3)|0;c[G>>2]=E;c[G+4>>2]=A;G=Rd(E^(s|t)|0,A^F|0,63)|0;z=D;F=Pd(E^(s|t)|0,A^F|0,1)|0;A=q+3072+(H+33<<3)|0;c[A>>2]=F|G;c[A+4>>2]=D|z;A=c[q+3072+((H|1)<<3)>>2]|0;z=c[q+3072+((H|1)<<3)+4>>2]|0;G=q+3072+(H+48<<3)|0;F=c[G>>2]|0;G=c[G+4>>2]|0;t=oe(F|0,G|0,A|0,z|0)|0;s=D;z=Pd(A|0,z|0,1)|0;z=Ed(z&-2|0,D&1|0,F|0,0)|0;z=oe(t|0,s|0,z|0,D|0)|0;s=D;t=q+3072+(H+96<<3)|0;A=z^c[t>>2];t=s^c[t+4>>2];E=oe(t|0,A|0,x|0,y|0)|0;w=D;y=Pd(x|0,y|0,1)|0;y=Ed(y&-2|0,D&1|0,t|0,0)|0;y=oe(E|0,w|0,y|0,D|0)|0;w=D;E=Rd(y^F|0,w^G|0,24)|0;x=D;G=Pd(y^F|0,w^G|0,40)|0;x=D|x;F=oe(G|E|0,x|0,z|0,s|0)|0;u=D;s=Pd(z|0,s|0,1)|0;s=Ed(E|0,0,s&-2|0,D&1|0)|0;s=oe(F|0,u|0,s|0,D|0)|0;u=D;c[q+3072+((H|1)<<3)>>2]=s;c[q+3072+((H|1)<<3)+4>>2]=u;F=Rd(s^t|0,u^A|0,16)|0;z=D;A=Pd(s^t|0,u^A|0,48)|0;z=D|z;u=q+3072+(H+96<<3)|0;c[u>>2]=A|F;c[u+4>>2]=z;z=oe(A|F|0,z|0,y|0,w|0)|0;A=D;w=Pd(y|0,w|0,1)|0;w=Ed(F|0,0,w&-2|0,D&1|0)|0;w=oe(z|0,A|0,w|0,D|0)|0;A=D;z=q+3072+(H+81<<3)|0;c[z>>2]=w;c[z+4>>2]=A;z=Rd(w^(G|E)|0,A^x|0,63)|0;F=D;x=Pd(w^(G|E)|0,A^x|0,1)|0;A=q+3072+(H+48<<3)|0;c[A>>2]=x|z;c[A+4>>2]=D|F;A=q+3072+(H+16<<3)|0;F=c[A>>2]|0;A=c[A+4>>2]|0;z=oe(B|C|0,v|0,F|0,A|0)|0;x=D;A=Pd(F|0,A|0,1)|0;A=Ed(A&-2|0,D&1|0,B|C|0,0)|0;A=oe(z|0,x|0,A|0,D|0)|0;x=D;z=q+3072+(H+97<<3)|0;F=A^c[z>>2];z=x^c[z+4>>2];E=q+3072+(H+64<<3)|0;G=c[E>>2]|0;E=c[E+4>>2]|0;w=oe(z|0,F|0,G|0,E|0)|0;y=D;E=Pd(G|0,E|0,1)|0;E=Ed(z|0,0,E&-2|0,D&1|0)|0;E=oe(w|0,y|0,E|0,D|0)|0;y=D;w=Rd(E^(B|C)|0,y^v|0,24)|0;G=D;v=Pd(E^(B|C)|0,y^v|0,40)|0;G=D|G;C=oe(v|w|0,G|0,A|0,x|0)|0;B=D;x=Pd(A|0,x|0,1)|0;x=Ed(w|0,0,x&-2|0,D&1|0)|0;x=oe(C|0,B|0,x|0,D|0)|0;B=D;C=q+3072+(H+16<<3)|0;c[C>>2]=x;c[C+4>>2]=B;C=Rd(x^z|0,B^F|0,16)|0;A=D;F=Pd(x^z|0,B^F|0,48)|0;A=D|A;B=q+3072+(H+97<<3)|0;c[B>>2]=F|C;c[B+4>>2]=A;A=oe(F|C|0,A|0,E|0,y|0)|0;F=D;y=Pd(E|0,y|0,1)|0;y=Ed(C|0,0,y&-2|0,D&1|0)|0;y=oe(A|0,F|0,y|0,D|0)|0;F=D;A=q+3072+(H+64<<3)|0;c[A>>2]=y;c[A+4>>2]=F;A=Rd(y^(v|w)|0,F^G|0,63)|0;C=D;G=Pd(y^(v|w)|0,F^G|0,1)|0;F=q+3072+(H+49<<3)|0;c[F>>2]=G|A;c[F+4>>2]=D|C;F=q+3072+(H+17<<3)|0;C=c[F>>2]|0;F=c[F+4>>2]|0;A=q+3072+(H+32<<3)|0;G=c[A>>2]|0;A=c[A+4>>2]|0;w=oe(G|0,A|0,C|0,F|0)|0;v=D;F=Pd(C|0,F|0,1)|0;F=Ed(F&-2|0,D&1|0,G|0,0)|0;F=oe(w|0,v|0,F|0,D|0)|0;v=D;w=q+3072+(H+112<<3)|0;C=F^c[w>>2];w=v^c[w+4>>2];y=q+3072+(H+65<<3)|0;E=c[y>>2]|0;y=c[y+4>>2]|0;B=oe(w|0,C|0,E|0,y|0)|0;z=D;y=Pd(E|0,y|0,1)|0;y=Ed(w|0,0,y&-2|0,D&1|0)|0;y=oe(B|0,z|0,y|0,D|0)|0;z=D;B=Rd(y^G|0,z^A|0,24)|0;E=D;A=Pd(y^G|0,z^A|0,40)|0;E=D|E;G=oe(A|B|0,E|0,F|0,v|0)|0;x=D;v=Pd(F|0,v|0,1)|0;v=Ed(B|0,0,v&-2|0,D&1|0)|0;v=oe(G|0,x|0,v|0,D|0)|0;x=D;G=q+3072+(H+17<<3)|0;c[G>>2]=v;c[G+4>>2]=x;G=Rd(v^w|0,x^C|0,16)|0;F=D;C=Pd(v^w|0,x^C|0,48)|0;F=D|F;x=q+3072+(H+112<<3)|0;c[x>>2]=C|G;c[x+4>>2]=F;F=oe(C|G|0,F|0,y|0,z|0)|0;C=D;z=Pd(y|0,z|0,1)|0;z=Ed(G|0,0,z&-2|0,D&1|0)|0;z=oe(F|0,C|0,z|0,D|0)|0;C=D;F=q+3072+(H+65<<3)|0;c[F>>2]=z;c[F+4>>2]=C;F=Rd(z^(A|B)|0,C^E|0,63)|0;G=D;E=Pd(z^(A|B)|0,C^E|0,1)|0;H=q+3072+(H+32<<3)|0;c[H>>2]=E|F;c[H+4>>2]=D|G;f=f+1|0}while((f|0)!=8);ef(g,q+2048|0);gd(g,q+3072|0)}else ma(k+(n<<10)|0,k+(f<<10)+(j<<10)|0,g);e=e+1|0;if(e>>>0>=(c[b+12>>2]|0)>>>0)break a;o=o+1|0;f=n+1|0;m=c[b+16>>2]|0;g=c[d>>2]|0}}while(0);ta(p);e=0}}else e=0;i=r;return e|0}function ma(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;e=i;f=i=i+63&-64;i=i+2048|0;ef(f+1024|0,b);gd(f+1024|0,a);ef(f,f+1024|0);gd(f,d);a=0;do{b=a<<4;o=c[f+1024+(b<<3)>>2]|0;x=c[f+1024+(b<<3)+4>>2]|0;n=c[f+1024+((b|4)<<3)>>2]|0;l=c[f+1024+((b|4)<<3)+4>>2]|0;g=oe(n|0,l|0,o|0,x|0)|0;v=D;x=Pd(o|0,x|0,1)|0;x=Ed(x&-2|0,D&1|0,n|0,0)|0;x=oe(g|0,v|0,x|0,D|0)|0;v=D;g=x^c[f+1024+((b|12)<<3)>>2];o=v^c[f+1024+((b|12)<<3)+4>>2];r=c[f+1024+((b|8)<<3)>>2]|0;t=c[f+1024+((b|8)<<3)+4>>2]|0;s=oe(o|0,g|0,r|0,t|0)|0;j=D;t=Pd(r|0,t|0,1)|0;t=Ed(t&-2|0,D&1|0,o|0,0)|0;t=oe(s|0,j|0,t|0,D|0)|0;j=D;s=Rd(t^n|0,j^l|0,24)|0;r=D;l=Pd(t^n|0,j^l|0,40)|0;r=D|r;n=oe(l|s|0,r|0,x|0,v|0)|0;k=D;v=Pd(x|0,v|0,1)|0;v=Ed(s|0,0,v&-2|0,D&1|0)|0;v=oe(n|0,k|0,v|0,D|0)|0;k=D;c[f+1024+(b<<3)>>2]=v;c[f+1024+(b<<3)+4>>2]=k;n=Rd(v^o|0,k^g|0,16)|0;x=D;g=Pd(v^o|0,k^g|0,48)|0;x=D|x;c[f+1024+((b|12)<<3)>>2]=g|n;c[f+1024+((b|12)<<3)+4>>2]=x;x=oe(g|n|0,x|0,t|0,j|0)|0;g=D;j=Pd(t|0,j|0,1)|0;j=Ed(n|0,0,j&-2|0,D&1|0)|0;j=oe(x|0,g|0,j|0,D|0)|0;g=D;c[f+1024+((b|8)<<3)>>2]=j;c[f+1024+((b|8)<<3)+4>>2]=g;x=Rd(j^(l|s)|0,g^r|0,63)|0;n=D;r=Pd(j^(l|s)|0,g^r|0,1)|0;c[f+1024+((b|4)<<3)>>2]=r|x;c[f+1024+((b|4)<<3)+4>>2]=D|n;n=c[f+1024+((b|1)<<3)>>2]|0;x=c[f+1024+((b|1)<<3)+4>>2]|0;r=c[f+1024+((b|5)<<3)>>2]|0;g=c[f+1024+((b|5)<<3)+4>>2]|0;s=oe(r|0,g|0,n|0,x|0)|0;l=D;x=Pd(n|0,x|0,1)|0;x=Ed(x&-2|0,D&1|0,r|0,0)|0;x=oe(s|0,l|0,x|0,D|0)|0;l=D;s=x^c[f+1024+((b|13)<<3)>>2];n=l^c[f+1024+((b|13)<<3)+4>>2];j=c[f+1024+((b|9)<<3)>>2]|0;t=c[f+1024+((b|9)<<3)+4>>2]|0;k=oe(n|0,s|0,j|0,t|0)|0;o=D;t=Pd(j|0,t|0,1)|0;t=Ed(t&-2|0,D&1|0,n|0,0)|0;t=oe(k|0,o|0,t|0,D|0)|0;o=D;k=Rd(t^r|0,o^g|0,24)|0;j=D;g=Pd(t^r|0,o^g|0,40)|0;j=D|j;r=oe(g|k|0,j|0,x|0,l|0)|0;v=D;l=Pd(x|0,l|0,1)|0;l=Ed(k|0,0,l&-2|0,D&1|0)|0;l=oe(r|0,v|0,l|0,D|0)|0;v=D;c[f+1024+((b|1)<<3)>>2]=l;c[f+1024+((b|1)<<3)+4>>2]=v;r=Rd(l^n|0,v^s|0,16)|0;x=D;s=Pd(l^n|0,v^s|0,48)|0;x=D|x;c[f+1024+((b|13)<<3)>>2]=s|r;c[f+1024+((b|13)<<3)+4>>2]=x;x=oe(s|r|0,x|0,t|0,o|0)|0;s=D;o=Pd(t|0,o|0,1)|0;o=Ed(r|0,0,o&-2|0,D&1|0)|0;o=oe(x|0,s|0,o|0,D|0)|0;s=D;c[f+1024+((b|9)<<3)>>2]=o;c[f+1024+((b|9)<<3)+4>>2]=s;x=Rd(o^(g|k)|0,s^j|0,63)|0;r=D;j=Pd(o^(g|k)|0,s^j|0,1)|0;c[f+1024+((b|5)<<3)>>2]=j|x;c[f+1024+((b|5)<<3)+4>>2]=D|r;r=c[f+1024+((b|2)<<3)>>2]|0;x=c[f+1024+((b|2)<<3)+4>>2]|0;j=c[f+1024+((b|6)<<3)>>2]|0;s=c[f+1024+((b|6)<<3)+4>>2]|0;k=oe(j|0,s|0,r|0,x|0)|0;g=D;x=Pd(r|0,x|0,1)|0;x=Ed(x&-2|0,D&1|0,j|0,0)|0;x=oe(k|0,g|0,x|0,D|0)|0;g=D;k=x^c[f+1024+((b|14)<<3)>>2];r=g^c[f+1024+((b|14)<<3)+4>>2];o=c[f+1024+((b|10)<<3)>>2]|0;t=c[f+1024+((b|10)<<3)+4>>2]|0;v=oe(r|0,k|0,o|0,t|0)|0;n=D;t=Pd(o|0,t|0,1)|0;t=Ed(t&-2|0,D&1|0,r|0,0)|0;t=oe(v|0,n|0,t|0,D|0)|0;n=D;v=Rd(t^j|0,n^s|0,24)|0;o=D;s=Pd(t^j|0,n^s|0,40)|0;o=D|o;j=oe(s|v|0,o|0,x|0,g|0)|0;l=D;g=Pd(x|0,g|0,1)|0;g=Ed(v|0,0,g&-2|0,D&1|0)|0;g=oe(j|0,l|0,g|0,D|0)|0;l=D;c[f+1024+((b|2)<<3)>>2]=g;c[f+1024+((b|2)<<3)+4>>2]=l;j=Rd(g^r|0,l^k|0,16)|0;x=D;k=Pd(g^r|0,l^k|0,48)|0;x=D|x;c[f+1024+((b|14)<<3)>>2]=k|j;c[f+1024+((b|14)<<3)+4>>2]=x;x=oe(k|j|0,x|0,t|0,n|0)|0;k=D;n=Pd(t|0,n|0,1)|0;n=Ed(j|0,0,n&-2|0,D&1|0)|0;n=oe(x|0,k|0,n|0,D|0)|0;k=D;x=Rd(n^(s|v)|0,k^o|0,63)|0;j=D;o=Pd(n^(s|v)|0,k^o|0,1)|0;c[f+1024+((b|6)<<3)>>2]=o|x;c[f+1024+((b|6)<<3)+4>>2]=D|j;j=c[f+1024+((b|3)<<3)>>2]|0;x=c[f+1024+((b|3)<<3)+4>>2]|0;o=c[f+1024+((b|7)<<3)>>2]|0;v=c[f+1024+((b|7)<<3)+4>>2]|0;s=oe(o|0,v|0,j|0,x|0)|0;t=D;x=Pd(j|0,x|0,1)|0;x=Ed(x&-2|0,D&1|0,o|0,0)|0;x=oe(s|0,t|0,x|0,D|0)|0;t=D;s=x^c[f+1024+((b|15)<<3)>>2];j=t^c[f+1024+((b|15)<<3)+4>>2];l=c[f+1024+((b|11)<<3)>>2]|0;r=c[f+1024+((b|11)<<3)+4>>2]|0;g=oe(j|0,s|0,l|0,r|0)|0;m=D;r=Pd(l|0,r|0,1)|0;r=Ed(r&-2|0,D&1|0,j|0,0)|0;r=oe(g|0,m|0,r|0,D|0)|0;m=D;g=Rd(r^o|0,m^v|0,24)|0;l=D;v=Pd(r^o|0,m^v|0,40)|0;l=D|l;o=oe(v|g|0,l|0,x|0,t|0)|0;q=D;t=Pd(x|0,t|0,1)|0;t=Ed(g|0,0,t&-2|0,D&1|0)|0;t=oe(o|0,q|0,t|0,D|0)|0;q=D;c[f+1024+((b|3)<<3)>>2]=t;c[f+1024+((b|3)<<3)+4>>2]=q;o=Rd(t^j|0,q^s|0,16)|0;x=D;s=Pd(t^j|0,q^s|0,48)|0;x=D|x;q=oe(s|o|0,x|0,r|0,m|0)|0;j=D;m=Pd(r|0,m|0,1)|0;m=Ed(o|0,0,m&-2|0,D&1|0)|0;m=oe(q|0,j|0,m|0,D|0)|0;j=D;q=Rd(m^(v|g)|0,j^l|0,63)|0;r=D;l=Pd(m^(v|g)|0,j^l|0,1)|0;r=D|r;c[f+1024+((b|7)<<3)>>2]=l|q;c[f+1024+((b|7)<<3)+4>>2]=r;g=c[f+1024+(b<<3)>>2]|0;v=c[f+1024+(b<<3)+4>>2]|0;t=c[f+1024+((b|5)<<3)>>2]|0;u=c[f+1024+((b|5)<<3)+4>>2]|0;p=oe(t|0,u|0,g|0,v|0)|0;y=D;v=Pd(g|0,v|0,1)|0;v=Ed(v&-2|0,D&1|0,t|0,0)|0;v=oe(p|0,y|0,v|0,D|0)|0;y=D;p=oe(y^x|0,v^(s|o)|0,n|0,k|0)|0;g=D;k=Pd(n|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,y^x|0,0)|0;k=oe(p|0,g|0,k|0,D|0)|0;g=D;p=Rd(k^t|0,g^u|0,24)|0;n=D;u=Pd(k^t|0,g^u|0,40)|0;n=D|n;t=oe(u|p|0,n|0,v|0,y|0)|0;w=D;z=Pd(v|0,y|0,1)|0;z=Ed(p|0,0,z&-2|0,D&1|0)|0;z=oe(t|0,w|0,z|0,D|0)|0;w=D;c[f+1024+(b<<3)>>2]=z;c[f+1024+(b<<3)+4>>2]=w;t=Rd(z^(y^x)|0,w^(v^(s|o))|0,16)|0;h=D;o=Pd(z^(y^x)|0,w^(v^(s|o))|0,48)|0;h=D|h;c[f+1024+((b|15)<<3)>>2]=o|t;c[f+1024+((b|15)<<3)+4>>2]=h;h=oe(o|t|0,h|0,k|0,g|0)|0;o=D;g=Pd(k|0,g|0,1)|0;g=Ed(t|0,0,g&-2|0,D&1|0)|0;g=oe(h|0,o|0,g|0,D|0)|0;o=D;c[f+1024+((b|10)<<3)>>2]=g;c[f+1024+((b|10)<<3)+4>>2]=o;h=Rd(g^(u|p)|0,o^n|0,63)|0;t=D;n=Pd(g^(u|p)|0,o^n|0,1)|0;c[f+1024+((b|5)<<3)>>2]=n|h;c[f+1024+((b|5)<<3)+4>>2]=D|t;t=c[f+1024+((b|1)<<3)>>2]|0;h=c[f+1024+((b|1)<<3)+4>>2]|0;n=c[f+1024+((b|6)<<3)>>2]|0;o=c[f+1024+((b|6)<<3)+4>>2]|0;p=oe(n|0,o|0,t|0,h|0)|0;u=D;h=Pd(t|0,h|0,1)|0;h=Ed(h&-2|0,D&1|0,n|0,0)|0;h=oe(p|0,u|0,h|0,D|0)|0;u=D;p=h^c[f+1024+((b|12)<<3)>>2];t=u^c[f+1024+((b|12)<<3)+4>>2];g=oe(t|0,p|0,m|0,j|0)|0;k=D;j=Pd(m|0,j|0,1)|0;j=Ed(j&-2|0,D&1|0,t|0,0)|0;j=oe(g|0,k|0,j|0,D|0)|0;k=D;g=Rd(j^n|0,k^o|0,24)|0;m=D;o=Pd(j^n|0,k^o|0,40)|0;m=D|m;n=oe(o|g|0,m|0,h|0,u|0)|0;s=D;u=Pd(h|0,u|0,1)|0;u=Ed(g|0,0,u&-2|0,D&1|0)|0;u=oe(n|0,s|0,u|0,D|0)|0;s=D;c[f+1024+((b|1)<<3)>>2]=u;c[f+1024+((b|1)<<3)+4>>2]=s;n=Rd(u^t|0,s^p|0,16)|0;h=D;p=Pd(u^t|0,s^p|0,48)|0;h=D|h;c[f+1024+((b|12)<<3)>>2]=p|n;c[f+1024+((b|12)<<3)+4>>2]=h;h=oe(p|n|0,h|0,j|0,k|0)|0;p=D;k=Pd(j|0,k|0,1)|0;k=Ed(n|0,0,k&-2|0,D&1|0)|0;k=oe(h|0,p|0,k|0,D|0)|0;p=D;c[f+1024+((b|11)<<3)>>2]=k;c[f+1024+((b|11)<<3)+4>>2]=p;h=Rd(k^(o|g)|0,p^m|0,63)|0;n=D;m=Pd(k^(o|g)|0,p^m|0,1)|0;c[f+1024+((b|6)<<3)>>2]=m|h;c[f+1024+((b|6)<<3)+4>>2]=D|n;n=c[f+1024+((b|2)<<3)>>2]|0;h=c[f+1024+((b|2)<<3)+4>>2]|0;m=oe(l|q|0,r|0,n|0,h|0)|0;p=D;h=Pd(n|0,h|0,1)|0;h=Ed(h&-2|0,D&1|0,l|q|0,0)|0;h=oe(m|0,p|0,h|0,D|0)|0;p=D;m=h^c[f+1024+((b|13)<<3)>>2];n=p^c[f+1024+((b|13)<<3)+4>>2];g=c[f+1024+((b|8)<<3)>>2]|0;o=c[f+1024+((b|8)<<3)+4>>2]|0;k=oe(n|0,m|0,g|0,o|0)|0;j=D;o=Pd(g|0,o|0,1)|0;o=Ed(o&-2|0,D&1|0,n|0,0)|0;o=oe(k|0,j|0,o|0,D|0)|0;j=D;k=Rd(o^(l|q)|0,j^r|0,24)|0;g=D;r=Pd(o^(l|q)|0,j^r|0,40)|0;g=D|g;q=oe(r|k|0,g|0,h|0,p|0)|0;l=D;p=Pd(h|0,p|0,1)|0;p=Ed(k|0,0,p&-2|0,D&1|0)|0;p=oe(q|0,l|0,p|0,D|0)|0;l=D;c[f+1024+((b|2)<<3)>>2]=p;c[f+1024+((b|2)<<3)+4>>2]=l;q=Rd(p^n|0,l^m|0,16)|0;h=D;m=Pd(p^n|0,l^m|0,48)|0;h=D|h;c[f+1024+((b|13)<<3)>>2]=m|q;c[f+1024+((b|13)<<3)+4>>2]=h;h=oe(m|q|0,h|0,o|0,j|0)|0;m=D;j=Pd(o|0,j|0,1)|0;j=Ed(q|0,0,j&-2|0,D&1|0)|0;j=oe(h|0,m|0,j|0,D|0)|0;m=D;c[f+1024+((b|8)<<3)>>2]=j;c[f+1024+((b|8)<<3)+4>>2]=m;h=Rd(j^(r|k)|0,m^g|0,63)|0;q=D;g=Pd(j^(r|k)|0,m^g|0,1)|0;c[f+1024+((b|7)<<3)>>2]=g|h;c[f+1024+((b|7)<<3)+4>>2]=D|q;q=c[f+1024+((b|3)<<3)>>2]|0;h=c[f+1024+((b|3)<<3)+4>>2]|0;g=c[f+1024+((b|4)<<3)>>2]|0;m=c[f+1024+((b|4)<<3)+4>>2]|0;k=oe(g|0,m|0,q|0,h|0)|0;r=D;h=Pd(q|0,h|0,1)|0;h=Ed(h&-2|0,D&1|0,g|0,0)|0;h=oe(k|0,r|0,h|0,D|0)|0;r=D;k=h^c[f+1024+((b|14)<<3)>>2];q=r^c[f+1024+((b|14)<<3)+4>>2];j=c[f+1024+((b|9)<<3)>>2]|0;o=c[f+1024+((b|9)<<3)+4>>2]|0;l=oe(q|0,k|0,j|0,o|0)|0;n=D;o=Pd(j|0,o|0,1)|0;o=Ed(o&-2|0,D&1|0,q|0,0)|0;o=oe(l|0,n|0,o|0,D|0)|0;n=D;l=Rd(o^g|0,n^m|0,24)|0;j=D;m=Pd(o^g|0,n^m|0,40)|0;j=D|j;g=oe(m|l|0,j|0,h|0,r|0)|0;p=D;r=Pd(h|0,r|0,1)|0;r=Ed(l|0,0,r&-2|0,D&1|0)|0;r=oe(g|0,p|0,r|0,D|0)|0;p=D;c[f+1024+((b|3)<<3)>>2]=r;c[f+1024+((b|3)<<3)+4>>2]=p;g=Rd(r^q|0,p^k|0,16)|0;h=D;k=Pd(r^q|0,p^k|0,48)|0;h=D|h;c[f+1024+((b|14)<<3)>>2]=k|g;c[f+1024+((b|14)<<3)+4>>2]=h;h=oe(k|g|0,h|0,o|0,n|0)|0;k=D;n=Pd(o|0,n|0,1)|0;n=Ed(g|0,0,n&-2|0,D&1|0)|0;n=oe(h|0,k|0,n|0,D|0)|0;k=D;c[f+1024+((b|9)<<3)>>2]=n;c[f+1024+((b|9)<<3)+4>>2]=k;h=Rd(n^(m|l)|0,k^j|0,63)|0;g=D;j=Pd(n^(m|l)|0,k^j|0,1)|0;c[f+1024+((b|4)<<3)>>2]=j|h;c[f+1024+((b|4)<<3)+4>>2]=D|g;a=a+1|0}while((a|0)!=8);a=0;do{z=a<<1;k=c[f+1024+(z<<3)>>2]|0;w=c[f+1024+(z<<3)+4>>2]|0;o=f+1024+(z+32<<3)|0;r=c[o>>2]|0;o=c[o+4>>2]|0;l=oe(r|0,o|0,k|0,w|0)|0;h=D;w=Pd(k|0,w|0,1)|0;w=Ed(w&-2|0,D&1|0,r|0,0)|0;w=oe(l|0,h|0,w|0,D|0)|0;h=D;l=f+1024+(z+96<<3)|0;k=w^c[l>>2];l=h^c[l+4>>2];n=f+1024+(z+64<<3)|0;p=c[n>>2]|0;n=c[n+4>>2]|0;x=oe(l|0,k|0,p|0,n|0)|0;t=D;n=Pd(p|0,n|0,1)|0;n=Ed(n&-2|0,D&1|0,l|0,0)|0;n=oe(x|0,t|0,n|0,D|0)|0;t=D;x=Rd(n^r|0,t^o|0,24)|0;p=D;o=Pd(n^r|0,t^o|0,40)|0;p=D|p;r=oe(o|x|0,p|0,w|0,h|0)|0;u=D;h=Pd(w|0,h|0,1)|0;h=Ed(x|0,0,h&-2|0,D&1|0)|0;h=oe(r|0,u|0,h|0,D|0)|0;u=D;c[f+1024+(z<<3)>>2]=h;c[f+1024+(z<<3)+4>>2]=u;r=Rd(h^l|0,u^k|0,16)|0;w=D;k=Pd(h^l|0,u^k|0,48)|0;w=D|w;u=f+1024+(z+96<<3)|0;c[u>>2]=k|r;c[u+4>>2]=w;w=oe(k|r|0,w|0,n|0,t|0)|0;k=D;t=Pd(n|0,t|0,1)|0;t=Ed(r|0,0,t&-2|0,D&1|0)|0;t=oe(w|0,k|0,t|0,D|0)|0;k=D;w=f+1024+(z+64<<3)|0;c[w>>2]=t;c[w+4>>2]=k;w=Rd(t^(o|x)|0,k^p|0,63)|0;r=D;p=Pd(t^(o|x)|0,k^p|0,1)|0;k=f+1024+(z+32<<3)|0;c[k>>2]=p|w;c[k+4>>2]=D|r;k=c[f+1024+((z|1)<<3)>>2]|0;r=c[f+1024+((z|1)<<3)+4>>2]|0;w=f+1024+(z+33<<3)|0;p=c[w>>2]|0;w=c[w+4>>2]|0;x=oe(p|0,w|0,k|0,r|0)|0;o=D;r=Pd(k|0,r|0,1)|0;r=Ed(r&-2|0,D&1|0,p|0,0)|0;r=oe(x|0,o|0,r|0,D|0)|0;o=D;x=f+1024+(z+97<<3)|0;k=r^c[x>>2];x=o^c[x+4>>2];t=f+1024+(z+65<<3)|0;n=c[t>>2]|0;t=c[t+4>>2]|0;u=oe(x|0,k|0,n|0,t|0)|0;l=D;t=Pd(n|0,t|0,1)|0;t=Ed(t&-2|0,D&1|0,x|0,0)|0;t=oe(u|0,l|0,t|0,D|0)|0;l=D;u=Rd(t^p|0,l^w|0,24)|0;n=D;w=Pd(t^p|0,l^w|0,40)|0;n=D|n;p=oe(w|u|0,n|0,r|0,o|0)|0;h=D;o=Pd(r|0,o|0,1)|0;o=Ed(u|0,0,o&-2|0,D&1|0)|0;o=oe(p|0,h|0,o|0,D|0)|0;h=D;c[f+1024+((z|1)<<3)>>2]=o;c[f+1024+((z|1)<<3)+4>>2]=h;p=Rd(o^x|0,h^k|0,16)|0;r=D;k=Pd(o^x|0,h^k|0,48)|0;r=D|r;h=f+1024+(z+97<<3)|0;c[h>>2]=k|p;c[h+4>>2]=r;r=oe(k|p|0,r|0,t|0,l|0)|0;k=D;l=Pd(t|0,l|0,1)|0;l=Ed(p|0,0,l&-2|0,D&1|0)|0;l=oe(r|0,k|0,l|0,D|0)|0;k=D;r=f+1024+(z+65<<3)|0;c[r>>2]=l;c[r+4>>2]=k;r=Rd(l^(w|u)|0,k^n|0,63)|0;p=D;n=Pd(l^(w|u)|0,k^n|0,1)|0;k=f+1024+(z+33<<3)|0;c[k>>2]=n|r;c[k+4>>2]=D|p;k=f+1024+(z+16<<3)|0;p=c[k>>2]|0;k=c[k+4>>2]|0;r=f+1024+(z+48<<3)|0;n=c[r>>2]|0;r=c[r+4>>2]|0;u=oe(n|0,r|0,p|0,k|0)|0;w=D;k=Pd(p|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,n|0,0)|0;k=oe(u|0,w|0,k|0,D|0)|0;w=D;u=f+1024+(z+112<<3)|0;p=k^c[u>>2];u=w^c[u+4>>2];l=f+1024+(z+80<<3)|0;t=c[l>>2]|0;l=c[l+4>>2]|0;h=oe(u|0,p|0,t|0,l|0)|0;x=D;l=Pd(t|0,l|0,1)|0;l=Ed(l&-2|0,D&1|0,u|0,0)|0;l=oe(h|0,x|0,l|0,D|0)|0;x=D;h=Rd(l^n|0,x^r|0,24)|0;t=D;r=Pd(l^n|0,x^r|0,40)|0;t=D|t;n=oe(r|h|0,t|0,k|0,w|0)|0;o=D;w=Pd(k|0,w|0,1)|0;w=Ed(h|0,0,w&-2|0,D&1|0)|0;w=oe(n|0,o|0,w|0,D|0)|0;o=D;n=f+1024+(z+16<<3)|0;c[n>>2]=w;c[n+4>>2]=o;n=Rd(w^u|0,o^p|0,16)|0;k=D;p=Pd(w^u|0,o^p|0,48)|0;k=D|k;o=f+1024+(z+112<<3)|0;c[o>>2]=p|n;c[o+4>>2]=k;k=oe(p|n|0,k|0,l|0,x|0)|0;p=D;x=Pd(l|0,x|0,1)|0;x=Ed(n|0,0,x&-2|0,D&1|0)|0;x=oe(k|0,p|0,x|0,D|0)|0;p=D;k=Rd(x^(r|h)|0,p^t|0,63)|0;n=D;t=Pd(x^(r|h)|0,p^t|0,1)|0;h=f+1024+(z+48<<3)|0;c[h>>2]=t|k;c[h+4>>2]=D|n;h=f+1024+(z+17<<3)|0;n=c[h>>2]|0;h=c[h+4>>2]|0;k=f+1024+(z+49<<3)|0;t=c[k>>2]|0;k=c[k+4>>2]|0;r=oe(t|0,k|0,n|0,h|0)|0;l=D;h=Pd(n|0,h|0,1)|0;h=Ed(h&-2|0,D&1|0,t|0,0)|0;h=oe(r|0,l|0,h|0,D|0)|0;l=D;r=f+1024+(z+113<<3)|0;n=h^c[r>>2];r=l^c[r+4>>2];o=f+1024+(z+81<<3)|0;u=c[o>>2]|0;o=c[o+4>>2]|0;w=oe(r|0,n|0,u|0,o|0)|0;q=D;o=Pd(u|0,o|0,1)|0;o=Ed(o&-2|0,D&1|0,r|0,0)|0;o=oe(w|0,q|0,o|0,D|0)|0;q=D;w=Rd(o^t|0,q^k|0,24)|0;u=D;k=Pd(o^t|0,q^k|0,40)|0;u=D|u;t=oe(k|w|0,u|0,h|0,l|0)|0;v=D;l=Pd(h|0,l|0,1)|0;l=Ed(w|0,0,l&-2|0,D&1|0)|0;l=oe(t|0,v|0,l|0,D|0)|0;v=D;t=f+1024+(z+17<<3)|0;c[t>>2]=l;c[t+4>>2]=v;t=Rd(l^r|0,v^n|0,16)|0;h=D;n=Pd(l^r|0,v^n|0,48)|0;h=D|h;v=oe(n|t|0,h|0,o|0,q|0)|0;r=D;q=Pd(o|0,q|0,1)|0;q=Ed(t|0,0,q&-2|0,D&1|0)|0;q=oe(v|0,r|0,q|0,D|0)|0;r=D;v=Rd(q^(k|w)|0,r^u|0,63)|0;o=D;u=Pd(q^(k|w)|0,r^u|0,1)|0;o=D|o;w=f+1024+(z+49<<3)|0;c[w>>2]=u|v;c[w+4>>2]=o;w=c[f+1024+(z<<3)>>2]|0;k=c[f+1024+(z<<3)+4>>2]|0;l=f+1024+(z+33<<3)|0;s=c[l>>2]|0;l=c[l+4>>2]|0;m=oe(s|0,l|0,w|0,k|0)|0;g=D;k=Pd(w|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,s|0,0)|0;k=oe(m|0,g|0,k|0,D|0)|0;g=D;m=oe(g^h|0,k^(n|t)|0,x|0,p|0)|0;w=D;p=Pd(x|0,p|0,1)|0;p=Ed(p&-2|0,D&1|0,g^h|0,0)|0;p=oe(m|0,w|0,p|0,D|0)|0;w=D;m=Rd(p^s|0,w^l|0,24)|0;x=D;l=Pd(p^s|0,w^l|0,40)|0;x=D|x;s=oe(l|m|0,x|0,k|0,g|0)|0;j=D;b=Pd(k|0,g|0,1)|0;b=Ed(m|0,0,b&-2|0,D&1|0)|0;b=oe(s|0,j|0,b|0,D|0)|0;j=D;c[f+1024+(z<<3)>>2]=b;c[f+1024+(z<<3)+4>>2]=j;s=Rd(b^(g^h)|0,j^(k^(n|t))|0,16)|0;y=D;t=Pd(b^(g^h)|0,j^(k^(n|t))|0,48)|0;y=D|y;n=f+1024+(z+113<<3)|0;c[n>>2]=t|s;c[n+4>>2]=y;y=oe(t|s|0,y|0,p|0,w|0)|0;t=D;w=Pd(p|0,w|0,1)|0;w=Ed(s|0,0,w&-2|0,D&1|0)|0;w=oe(y|0,t|0,w|0,D|0)|0;t=D;y=f+1024+(z+80<<3)|0;c[y>>2]=w;c[y+4>>2]=t;y=Rd(w^(l|m)|0,t^x|0,63)|0;s=D;x=Pd(w^(l|m)|0,t^x|0,1)|0;t=f+1024+(z+33<<3)|0;c[t>>2]=x|y;c[t+4>>2]=D|s;t=c[f+1024+((z|1)<<3)>>2]|0;s=c[f+1024+((z|1)<<3)+4>>2]|0;y=f+1024+(z+48<<3)|0;x=c[y>>2]|0;y=c[y+4>>2]|0;m=oe(x|0,y|0,t|0,s|0)|0;l=D;s=Pd(t|0,s|0,1)|0;s=Ed(s&-2|0,D&1|0,x|0,0)|0;s=oe(m|0,l|0,s|0,D|0)|0;l=D;m=f+1024+(z+96<<3)|0;t=s^c[m>>2];m=l^c[m+4>>2];w=oe(m|0,t|0,q|0,r|0)|0;p=D;r=Pd(q|0,r|0,1)|0;r=Ed(r&-2|0,D&1|0,m|0,0)|0;r=oe(w|0,p|0,r|0,D|0)|0;p=D;w=Rd(r^x|0,p^y|0,24)|0;q=D;y=Pd(r^x|0,p^y|0,40)|0;q=D|q;x=oe(y|w|0,q|0,s|0,l|0)|0;n=D;l=Pd(s|0,l|0,1)|0;l=Ed(w|0,0,l&-2|0,D&1|0)|0;l=oe(x|0,n|0,l|0,D|0)|0;n=D;c[f+1024+((z|1)<<3)>>2]=l;c[f+1024+((z|1)<<3)+4>>2]=n;x=Rd(l^m|0,n^t|0,16)|0;s=D;t=Pd(l^m|0,n^t|0,48)|0;s=D|s;n=f+1024+(z+96<<3)|0;c[n>>2]=t|x;c[n+4>>2]=s;s=oe(t|x|0,s|0,r|0,p|0)|0;t=D;p=Pd(r|0,p|0,1)|0;p=Ed(x|0,0,p&-2|0,D&1|0)|0;p=oe(s|0,t|0,p|0,D|0)|0;t=D;s=f+1024+(z+81<<3)|0;c[s>>2]=p;c[s+4>>2]=t;s=Rd(p^(y|w)|0,t^q|0,63)|0;x=D;q=Pd(p^(y|w)|0,t^q|0,1)|0;t=f+1024+(z+48<<3)|0;c[t>>2]=q|s;c[t+4>>2]=D|x;t=f+1024+(z+16<<3)|0;x=c[t>>2]|0;t=c[t+4>>2]|0;s=oe(u|v|0,o|0,x|0,t|0)|0;q=D;t=Pd(x|0,t|0,1)|0;t=Ed(t&-2|0,D&1|0,u|v|0,0)|0;t=oe(s|0,q|0,t|0,D|0)|0;q=D;s=f+1024+(z+97<<3)|0;x=t^c[s>>2];s=q^c[s+4>>2];w=f+1024+(z+64<<3)|0;y=c[w>>2]|0;w=c[w+4>>2]|0;p=oe(s|0,x|0,y|0,w|0)|0;r=D;w=Pd(y|0,w|0,1)|0;w=Ed(w&-2|0,D&1|0,s|0,0)|0;w=oe(p|0,r|0,w|0,D|0)|0;r=D;p=Rd(w^(u|v)|0,r^o|0,24)|0;y=D;o=Pd(w^(u|v)|0,r^o|0,40)|0;y=D|y;v=oe(o|p|0,y|0,t|0,q|0)|0;u=D;q=Pd(t|0,q|0,1)|0;q=Ed(p|0,0,q&-2|0,D&1|0)|0;q=oe(v|0,u|0,q|0,D|0)|0;u=D;v=f+1024+(z+16<<3)|0;c[v>>2]=q;c[v+4>>2]=u;v=Rd(q^s|0,u^x|0,16)|0;t=D;x=Pd(q^s|0,u^x|0,48)|0;t=D|t;u=f+1024+(z+97<<3)|0;c[u>>2]=x|v;c[u+4>>2]=t;t=oe(x|v|0,t|0,w|0,r|0)|0;x=D;r=Pd(w|0,r|0,1)|0;r=Ed(v|0,0,r&-2|0,D&1|0)|0;r=oe(t|0,x|0,r|0,D|0)|0;x=D;t=f+1024+(z+64<<3)|0;c[t>>2]=r;c[t+4>>2]=x;t=Rd(r^(o|p)|0,x^y|0,63)|0;v=D;y=Pd(r^(o|p)|0,x^y|0,1)|0;x=f+1024+(z+49<<3)|0;c[x>>2]=y|t;c[x+4>>2]=D|v;x=f+1024+(z+17<<3)|0;v=c[x>>2]|0;x=c[x+4>>2]|0;t=f+1024+(z+32<<3)|0;y=c[t>>2]|0;t=c[t+4>>2]|0;p=oe(y|0,t|0,v|0,x|0)|0;o=D;x=Pd(v|0,x|0,1)|0;x=Ed(x&-2|0,D&1|0,y|0,0)|0;x=oe(p|0,o|0,x|0,D|0)|0;o=D;p=f+1024+(z+112<<3)|0;v=x^c[p>>2];p=o^c[p+4>>2];r=f+1024+(z+65<<3)|0;w=c[r>>2]|0;r=c[r+4>>2]|0;u=oe(p|0,v|0,w|0,r|0)|0;s=D;r=Pd(w|0,r|0,1)|0;r=Ed(r&-2|0,D&1|0,p|0,0)|0;r=oe(u|0,s|0,r|0,D|0)|0;s=D;u=Rd(r^y|0,s^t|0,24)|0;w=D;t=Pd(r^y|0,s^t|0,40)|0;w=D|w;y=oe(t|u|0,w|0,x|0,o|0)|0;q=D;o=Pd(x|0,o|0,1)|0;o=Ed(u|0,0,o&-2|0,D&1|0)|0;o=oe(y|0,q|0,o|0,D|0)|0;q=D;y=f+1024+(z+17<<3)|0;c[y>>2]=o;c[y+4>>2]=q;y=Rd(o^p|0,q^v|0,16)|0;x=D;v=Pd(o^p|0,q^v|0,48)|0;x=D|x;q=f+1024+(z+112<<3)|0;c[q>>2]=v|y;c[q+4>>2]=x;x=oe(v|y|0,x|0,r|0,s|0)|0;v=D;s=Pd(r|0,s|0,1)|0;s=Ed(y|0,0,s&-2|0,D&1|0)|0;s=oe(x|0,v|0,s|0,D|0)|0;v=D;x=f+1024+(z+65<<3)|0;c[x>>2]=s;c[x+4>>2]=v;x=Rd(s^(t|u)|0,v^w|0,63)|0;y=D;w=Pd(s^(t|u)|0,v^w|0,1)|0;z=f+1024+(z+32<<3)|0;c[z>>2]=w|x;c[z+4>>2]=D|y;a=a+1|0}while((a|0)!=8);ef(d,f);gd(d,f+1024|0);i=e;return}function na(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0;I=i;s=i=i+63&-64;i=i+16|0;do if(a>>>0<245){r=a>>>0<11?16:a+11&-8;q=c[8491]|0;if(q>>>(r>>>3)&3|0){b=34004+((q>>>(r>>>3)&1^1)+(r>>>3)<<1<<2)|0;a=c[b+8>>2]|0;d=c[a+8>>2]|0;do if((b|0)!=(d|0)){if(d>>>0<(c[8495]|0)>>>0)ba();if((c[d+12>>2]|0)==(a|0)){c[d+12>>2]=b;c[b+8>>2]=d;break}else ba()}else c[8491]=q&~(1<<(q>>>(r>>>3)&1^1)+(r>>>3));while(0);H=(q>>>(r>>>3)&1^1)+(r>>>3)<<3;c[a+4>>2]=H|3;c[a+H+4>>2]=c[a+H+4>>2]|1;H=a+8|0;i=I;return H|0}p=c[8493]|0;if(r>>>0>p>>>0){if(q>>>(r>>>3)|0){b=q>>>(r>>>3)<<(r>>>3)&(2<<(r>>>3)|0-(2<<(r>>>3)));e=((b&0-b)+-1|0)>>>(((b&0-b)+-1|0)>>>12&16);d=e>>>(e>>>5&8)>>>(e>>>(e>>>5&8)>>>2&4);d=(e>>>5&8|((b&0-b)+-1|0)>>>12&16|e>>>(e>>>5&8)>>>2&4|d>>>1&2|d>>>(d>>>1&2)>>>1&1)+(d>>>(d>>>1&2)>>>(d>>>(d>>>1&2)>>>1&1))|0;e=c[34004+(d<<1<<2)+8>>2]|0;b=c[e+8>>2]|0;do if((34004+(d<<1<<2)|0)!=(b|0)){if(b>>>0<(c[8495]|0)>>>0)ba();if((c[b+12>>2]|0)==(e|0)){c[b+12>>2]=34004+(d<<1<<2);c[34004+(d<<1<<2)+8>>2]=b;f=q;break}else ba()}else{c[8491]=q&~(1<<d);f=q&~(1<<d)}while(0);c[e+4>>2]=r|3;c[e+r+4>>2]=(d<<3)-r|1;c[e+r+((d<<3)-r)>>2]=(d<<3)-r;if(p|0){a=c[8496]|0;if(f&1<<(p>>>3)){b=c[34004+(p>>>3<<1<<2)+8>>2]|0;if(b>>>0<(c[8495]|0)>>>0)ba();else{h=b;j=34004+(p>>>3<<1<<2)+8|0}}else{c[8491]=f|1<<(p>>>3);h=34004+(p>>>3<<1<<2)|0;j=34004+(p>>>3<<1<<2)+8|0}c[j>>2]=a;c[h+12>>2]=a;c[a+8>>2]=h;c[a+12>>2]=34004+(p>>>3<<1<<2)}c[8493]=(d<<3)-r;c[8496]=e+r;H=e+8|0;i=I;return H|0}l=c[8492]|0;if(l){a=((l&0-l)+-1|0)>>>(((l&0-l)+-1|0)>>>12&16);k=a>>>(a>>>5&8)>>>(a>>>(a>>>5&8)>>>2&4);k=c[34268+((a>>>5&8|((l&0-l)+-1|0)>>>12&16|a>>>(a>>>5&8)>>>2&4|k>>>1&2|k>>>(k>>>1&2)>>>1&1)+(k>>>(k>>>1&2)>>>(k>>>(k>>>1&2)>>>1&1))<<2)>>2]|0;a=k;j=k;k=(c[k+4>>2]&-8)-r|0;while(1){b=c[a+16>>2]|0;if(!b){b=c[a+20>>2]|0;if(!b)break}H=(c[b+4>>2]&-8)-r|0;G=H>>>0<k>>>0;a=b;j=G?b:j;k=G?H:k}f=c[8495]|0;if(j>>>0<f>>>0)ba();h=j+r|0;if(j>>>0>=h>>>0)ba();g=c[j+24>>2]|0;b=c[j+12>>2]|0;do if((b|0)==(j|0)){a=j+20|0;b=c[a>>2]|0;if(!b){a=j+16|0;b=c[a>>2]|0;if(!b){m=0;break}}while(1){d=b+20|0;e=c[d>>2]|0;if(e|0){b=e;a=d;continue}d=b+16|0;e=c[d>>2]|0;if(!e)break;else{b=e;a=d}}if(a>>>0<f>>>0)ba();else{c[a>>2]=0;m=b;break}}else{a=c[j+8>>2]|0;if(a>>>0<f>>>0)ba();if((c[a+12>>2]|0)!=(j|0))ba();if((c[b+8>>2]|0)==(j|0)){c[a+12>>2]=b;c[b+8>>2]=a;m=b;break}else ba()}while(0);do if(g|0){b=c[j+28>>2]|0;if((j|0)==(c[34268+(b<<2)>>2]|0)){c[34268+(b<<2)>>2]=m;if(!m){c[8492]=l&~(1<<b);break}}else{if(g>>>0<(c[8495]|0)>>>0)ba();if((c[g+16>>2]|0)==(j|0))c[g+16>>2]=m;else c[g+20>>2]=m;if(!m)break}a=c[8495]|0;if(m>>>0<a>>>0)ba();c[m+24>>2]=g;b=c[j+16>>2]|0;do if(b|0)if(b>>>0<a>>>0)ba();else{c[m+16>>2]=b;c[b+24>>2]=m;break}while(0);b=c[j+20>>2]|0;if(b|0)if(b>>>0<(c[8495]|0)>>>0)ba();else{c[m+20>>2]=b;c[b+24>>2]=m;break}}while(0);if(k>>>0<16){H=k+r|0;c[j+4>>2]=H|3;H=j+H+4|0;c[H>>2]=c[H>>2]|1}else{c[j+4>>2]=r|3;c[h+4>>2]=k|1;c[h+k>>2]=k;if(p|0){a=c[8496]|0;if(q&1<<(p>>>3)){b=c[34004+(p>>>3<<1<<2)+8>>2]|0;if(b>>>0<(c[8495]|0)>>>0)ba();else{n=b;o=34004+(p>>>3<<1<<2)+8|0}}else{c[8491]=q|1<<(p>>>3);n=34004+(p>>>3<<1<<2)|0;o=34004+(p>>>3<<1<<2)+8|0}c[o>>2]=a;c[n+12>>2]=a;c[a+8>>2]=n;c[a+12>>2]=34004+(p>>>3<<1<<2)}c[8493]=k;c[8496]=h}H=j+8|0;i=I;return H|0}}}else if(a>>>0<=4294967231){r=a+11&-8;l=c[8492]|0;if(l){if((a+11|0)>>>8)if(r>>>0>16777215)k=31;else{k=(a+11|0)>>>8<<((((a+11|0)>>>8)+1048320|0)>>>16&8);k=14-((k+520192|0)>>>16&4|(((a+11|0)>>>8)+1048320|0)>>>16&8|((k<<((k+520192|0)>>>16&4))+245760|0)>>>16&2)+(k<<((k+520192|0)>>>16&4)<<(((k<<((k+520192|0)>>>16&4))+245760|0)>>>16&2)>>>15)|0;k=r>>>(k+7|0)&1|k<<1}else k=0;a=c[34268+(k<<2)>>2]|0;a:do if(!a){a=0;e=0;d=0-r|0;A=86}else{e=0;d=0-r|0;j=r<<((k|0)==31?0:25-(k>>>1)|0);h=0;while(1){f=(c[a+4>>2]&-8)-r|0;if(f>>>0<d>>>0)if(!f){h=a;d=0;e=a;A=90;break a}else{e=a;d=f}f=c[a+20>>2]|0;a=c[a+16+(j>>>31<<2)>>2]|0;h=(f|0)==0|(f|0)==(a|0)?h:f;f=(a|0)==0;if(f){a=h;A=86;break}else j=j<<(f&1^1)}}while(0);if((A|0)==86){if((a|0)==0&(e|0)==0){a=2<<k;if(!(l&(a|0-a)))break;n=(l&(a|0-a)&0-(l&(a|0-a)))+-1|0;o=n>>>(n>>>12&16)>>>(n>>>(n>>>12&16)>>>5&8);a=o>>>(o>>>2&4)>>>(o>>>(o>>>2&4)>>>1&2);a=c[34268+((n>>>(n>>>12&16)>>>5&8|n>>>12&16|o>>>2&4|o>>>(o>>>2&4)>>>1&2|a>>>1&1)+(a>>>(a>>>1&1))<<2)>>2]|0}if(!a){k=e;j=d}else{h=e;e=a;A=90}}if((A|0)==90)while(1){A=0;f=(c[e+4>>2]&-8)-r|0;a=f>>>0<d>>>0;d=a?f:d;a=a?e:h;f=c[e+16>>2]|0;if(f|0){h=a;e=f;A=90;continue}e=c[e+20>>2]|0;if(!e){k=a;j=d;break}else{h=a;A=90}}if((k|0)!=0?j>>>0<((c[8493]|0)-r|0)>>>0:0){f=c[8495]|0;if(k>>>0<f>>>0)ba();h=k+r|0;if(k>>>0>=h>>>0)ba();g=c[k+24>>2]|0;b=c[k+12>>2]|0;do if((b|0)==(k|0)){a=k+20|0;b=c[a>>2]|0;if(!b){a=k+16|0;b=c[a>>2]|0;if(!b){p=0;break}}while(1){d=b+20|0;e=c[d>>2]|0;if(e|0){b=e;a=d;continue}d=b+16|0;e=c[d>>2]|0;if(!e)break;else{b=e;a=d}}if(a>>>0<f>>>0)ba();else{c[a>>2]=0;p=b;break}}else{a=c[k+8>>2]|0;if(a>>>0<f>>>0)ba();if((c[a+12>>2]|0)!=(k|0))ba();if((c[b+8>>2]|0)==(k|0)){c[a+12>>2]=b;c[b+8>>2]=a;p=b;break}else ba()}while(0);do if(g){b=c[k+28>>2]|0;if((k|0)==(c[34268+(b<<2)>>2]|0)){c[34268+(b<<2)>>2]=p;if(!p){c[8492]=l&~(1<<b);y=l&~(1<<b);break}}else{if(g>>>0<(c[8495]|0)>>>0)ba();if((c[g+16>>2]|0)==(k|0))c[g+16>>2]=p;else c[g+20>>2]=p;if(!p){y=l;break}}a=c[8495]|0;if(p>>>0<a>>>0)ba();c[p+24>>2]=g;b=c[k+16>>2]|0;do if(b|0)if(b>>>0<a>>>0)ba();else{c[p+16>>2]=b;c[b+24>>2]=p;break}while(0);b=c[k+20>>2]|0;if(b)if(b>>>0<(c[8495]|0)>>>0)ba();else{c[p+20>>2]=b;c[b+24>>2]=p;y=l;break}else y=l}else y=l;while(0);do if(j>>>0>=16){c[k+4>>2]=r|3;c[h+4>>2]=j|1;c[h+j>>2]=j;a=j>>>3;if(j>>>0<256){b=c[8491]|0;if(b&1<<a){b=c[34004+(a<<1<<2)+8>>2]|0;if(b>>>0<(c[8495]|0)>>>0)ba();else{q=b;v=34004+(a<<1<<2)+8|0}}else{c[8491]=b|1<<a;q=34004+(a<<1<<2)|0;v=34004+(a<<1<<2)+8|0}c[v>>2]=h;c[q+12>>2]=h;c[h+8>>2]=q;c[h+12>>2]=34004+(a<<1<<2);break}b=j>>>8;if(b)if(j>>>0>16777215)b=31;else{H=b<<((b+1048320|0)>>>16&8)<<(((b<<((b+1048320|0)>>>16&8))+520192|0)>>>16&4);b=14-(((b<<((b+1048320|0)>>>16&8))+520192|0)>>>16&4|(b+1048320|0)>>>16&8|(H+245760|0)>>>16&2)+(H<<((H+245760|0)>>>16&2)>>>15)|0;b=j>>>(b+7|0)&1|b<<1}else b=0;d=34268+(b<<2)|0;c[h+28>>2]=b;c[h+16+4>>2]=0;c[h+16>>2]=0;a=1<<b;if(!(y&a)){c[8492]=y|a;c[d>>2]=h;c[h+24>>2]=d;c[h+12>>2]=h;c[h+8>>2]=h;break}a=j<<((b|0)==31?0:25-(b>>>1)|0);e=c[d>>2]|0;while(1){if((c[e+4>>2]&-8|0)==(j|0)){A=148;break}d=e+16+(a>>>31<<2)|0;b=c[d>>2]|0;if(!b){A=145;break}else{a=a<<1;e=b}}if((A|0)==145)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[d>>2]=h;c[h+24>>2]=e;c[h+12>>2]=h;c[h+8>>2]=h;break}else if((A|0)==148){b=e+8|0;a=c[b>>2]|0;H=c[8495]|0;if(a>>>0>=H>>>0&e>>>0>=H>>>0){c[a+12>>2]=h;c[b>>2]=h;c[h+8>>2]=a;c[h+12>>2]=e;c[h+24>>2]=0;break}else ba()}}else{H=j+r|0;c[k+4>>2]=H|3;H=k+H+4|0;c[H>>2]=c[H>>2]|1}while(0);H=k+8|0;i=I;return H|0}}}else r=-1;while(0);d=c[8493]|0;if(d>>>0>=r>>>0){b=d-r|0;a=c[8496]|0;if(b>>>0>15){H=a+r|0;c[8496]=H;c[8493]=b;c[H+4>>2]=b|1;c[H+b>>2]=b;c[a+4>>2]=r|3}else{c[8493]=0;c[8496]=0;c[a+4>>2]=d|3;c[a+d+4>>2]=c[a+d+4>>2]|1}H=a+8|0;i=I;return H|0}f=c[8494]|0;if(f>>>0>r>>>0){F=f-r|0;c[8494]=F;H=c[8497]|0;G=H+r|0;c[8497]=G;c[G+4>>2]=F|1;c[H+4>>2]=r|3;H=H+8|0;i=I;return H|0}if(!(c[8609]|0)){c[8611]=4096;c[8610]=4096;c[8612]=-1;c[8613]=-1;c[8614]=0;c[8602]=0;c[s>>2]=s&-16^1431655768;c[8609]=s&-16^1431655768;a=4096}else a=c[8611]|0;h=r+48|0;j=r+47|0;l=a+j|0;k=0-a|0;if((l&k)>>>0<=r>>>0){H=0;i=I;return H|0}a=c[8601]|0;if(a|0?(y=c[8599]|0,(y+(l&k)|0)>>>0<=y>>>0?1:(y+(l&k)|0)>>>0>a>>>0):0){H=0;i=I;return H|0}b:do if(!(c[8602]&4)){e=c[8497]|0;c:do if(e){d=34412;while(1){a=c[d>>2]|0;if(a>>>0<=e>>>0?(t=d+4|0,(a+(c[t>>2]|0)|0)>>>0>e>>>0):0)break;a=c[d+8>>2]|0;if(!a){A=172;break c}else d=a}if((l-f&k)>>>0<2147483647){a=Pc(l-f&k|0)|0;if((a|0)==((c[d>>2]|0)+(c[t>>2]|0)|0)){if((a|0)!=(-1|0)){h=l-f&k;g=a;A=190;break b}}else{b=l-f&k;A=180}}}else A=172;while(0);do if(((A|0)==172?(g=Pc(0)|0,(g|0)!=(-1|0)):0)?(b=c[8610]|0,b=((b+-1&g|0)==0?0:(b+-1+g&0-b)-g|0)+(l&k)|0,u=c[8599]|0,b>>>0>r>>>0&b>>>0<2147483647):0){y=c[8601]|0;if(y|0?(b+u|0)>>>0<=u>>>0|(b+u|0)>>>0>y>>>0:0)break;a=Pc(b|0)|0;if((a|0)==(g|0)){h=b;A=190;break b}else A=180}while(0);d:do if((A|0)==180){d=0-b|0;do if(h>>>0>b>>>0&(b>>>0<2147483647&(a|0)!=(-1|0))?(w=c[8611]|0,w=j-b+w&0-w,w>>>0<2147483647):0)if((Pc(w|0)|0)==(-1|0)){Pc(d|0)|0;break d}else{b=w+b|0;break}while(0);if((a|0)!=(-1|0)){h=b;g=a;A=190;break b}}while(0);c[8602]=c[8602]|4;A=187}else A=187;while(0);if((((A|0)==187?(l&k)>>>0<2147483647:0)?(z=Pc(l&k|0)|0,x=Pc(0)|0,z>>>0<x>>>0&((z|0)!=(-1|0)&(x|0)!=(-1|0))):0)?(x-z|0)>>>0>(r+40|0)>>>0:0){h=x-z|0;g=z;A=190}if((A|0)==190){b=(c[8599]|0)+h|0;c[8599]=b;if(b>>>0>(c[8600]|0)>>>0)c[8600]=b;j=c[8497]|0;do if(j){b=34412;while(1){a=c[b>>2]|0;d=b+4|0;e=c[d>>2]|0;if((g|0)==(a+e|0)){A=200;break}f=c[b+8>>2]|0;if(!f)break;else b=f}if(((A|0)==200?(c[b+12>>2]&8|0)==0:0)?j>>>0<g>>>0&j>>>0>=a>>>0:0){c[d>>2]=e+h;G=(j+8&7|0)==0?0:0-(j+8)&7;H=h-G+(c[8494]|0)|0;c[8497]=j+G;c[8494]=H;c[j+G+4>>2]=H|1;c[j+G+H+4>>2]=40;c[8498]=c[8613];break}b=c[8495]|0;if(g>>>0<b>>>0){c[8495]=g;k=g}else k=b;a=g+h|0;b=34412;while(1){if((c[b>>2]|0)==(a|0)){A=208;break}b=c[b+8>>2]|0;if(!b){a=34412;break}}if((A|0)==208)if(!(c[b+12>>2]&8)){c[b>>2]=g;m=b+4|0;c[m>>2]=(c[m>>2]|0)+h;m=g+8|0;m=g+((m&7|0)==0?0:0-m&7)|0;b=a+((a+8&7|0)==0?0:0-(a+8)&7)|0;l=m+r|0;f=b-m-r|0;c[m+4>>2]=r|3;do if((b|0)!=(j|0)){if((b|0)==(c[8496]|0)){H=(c[8493]|0)+f|0;c[8493]=H;c[8496]=l;c[l+4>>2]=H|1;c[l+H>>2]=H;break}j=c[b+4>>2]|0;if((j&3|0)==1){e:do if(j>>>0>=256){h=c[b+24>>2]|0;a=c[b+12>>2]|0;do if((a|0)==(b|0)){a=c[b+16+4>>2]|0;if(!a){a=c[b+16>>2]|0;if(!a){F=0;break}else g=b+16|0}else g=b+16+4|0;while(1){d=a+20|0;e=c[d>>2]|0;if(e|0){a=e;g=d;continue}d=a+16|0;e=c[d>>2]|0;if(!e)break;else{a=e;g=d}}if(g>>>0<k>>>0)ba();else{c[g>>2]=0;F=a;break}}else{d=c[b+8>>2]|0;if(d>>>0<k>>>0)ba();if((c[d+12>>2]|0)!=(b|0))ba();if((c[a+8>>2]|0)==(b|0)){c[d+12>>2]=a;c[a+8>>2]=d;F=a;break}else ba()}while(0);if(!h)break;a=c[b+28>>2]|0;do if((b|0)!=(c[34268+(a<<2)>>2]|0)){if(h>>>0<(c[8495]|0)>>>0)ba();if((c[h+16>>2]|0)==(b|0))c[h+16>>2]=F;else c[h+20>>2]=F;if(!F)break e}else{c[34268+(a<<2)>>2]=F;if(F|0)break;c[8492]=c[8492]&~(1<<a);break e}while(0);d=c[8495]|0;if(F>>>0<d>>>0)ba();c[F+24>>2]=h;a=c[b+16>>2]|0;do if(a|0)if(a>>>0<d>>>0)ba();else{c[F+16>>2]=a;c[a+24>>2]=F;break}while(0);a=c[b+16+4>>2]|0;if(!a)break;if(a>>>0<(c[8495]|0)>>>0)ba();else{c[F+20>>2]=a;c[a+24>>2]=F;break}}else{a=c[b+8>>2]|0;d=c[b+12>>2]|0;do if((a|0)!=(34004+(j>>>3<<1<<2)|0)){if(a>>>0<k>>>0)ba();if((c[a+12>>2]|0)==(b|0))break;ba()}while(0);if((d|0)==(a|0)){c[8491]=c[8491]&~(1<<(j>>>3));break}do if((d|0)==(34004+(j>>>3<<1<<2)|0))E=d+8|0;else{if(d>>>0<k>>>0)ba();if((c[d+8>>2]|0)==(b|0)){E=d+8|0;break}ba()}while(0);c[a+12>>2]=d;c[E>>2]=a}while(0);b=b+(j&-8)|0;f=(j&-8)+f|0}a=b+4|0;c[a>>2]=c[a>>2]&-2;c[l+4>>2]=f|1;c[l+f>>2]=f;a=f>>>3;if(f>>>0<256){b=c[8491]|0;do if(!(b&1<<a)){c[8491]=b|1<<a;G=34004+(a<<1<<2)|0;H=34004+(a<<1<<2)+8|0}else{b=c[34004+(a<<1<<2)+8>>2]|0;if(b>>>0>=(c[8495]|0)>>>0){G=b;H=34004+(a<<1<<2)+8|0;break}ba()}while(0);c[H>>2]=l;c[G+12>>2]=l;c[l+8>>2]=G;c[l+12>>2]=34004+(a<<1<<2);break}b=f>>>8;do if(!b)b=0;else{if(f>>>0>16777215){b=31;break}H=b<<((b+1048320|0)>>>16&8)<<(((b<<((b+1048320|0)>>>16&8))+520192|0)>>>16&4);b=14-(((b<<((b+1048320|0)>>>16&8))+520192|0)>>>16&4|(b+1048320|0)>>>16&8|(H+245760|0)>>>16&2)+(H<<((H+245760|0)>>>16&2)>>>15)|0;b=f>>>(b+7|0)&1|b<<1}while(0);e=34268+(b<<2)|0;c[l+28>>2]=b;c[l+16+4>>2]=0;c[l+16>>2]=0;a=c[8492]|0;d=1<<b;if(!(a&d)){c[8492]=a|d;c[e>>2]=l;c[l+24>>2]=e;c[l+12>>2]=l;c[l+8>>2]=l;break}a=f<<((b|0)==31?0:25-(b>>>1)|0);e=c[e>>2]|0;while(1){if((c[e+4>>2]&-8|0)==(f|0)){A=278;break}d=e+16+(a>>>31<<2)|0;b=c[d>>2]|0;if(!b){A=275;break}else{a=a<<1;e=b}}if((A|0)==275)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[d>>2]=l;c[l+24>>2]=e;c[l+12>>2]=l;c[l+8>>2]=l;break}else if((A|0)==278){b=e+8|0;a=c[b>>2]|0;H=c[8495]|0;if(a>>>0>=H>>>0&e>>>0>=H>>>0){c[a+12>>2]=l;c[b>>2]=l;c[l+8>>2]=a;c[l+12>>2]=e;c[l+24>>2]=0;break}else ba()}}else{H=(c[8494]|0)+f|0;c[8494]=H;c[8497]=l;c[l+4>>2]=H|1}while(0);H=m+8|0;i=I;return H|0}else a=34412;while(1){b=c[a>>2]|0;if(b>>>0<=j>>>0?(B=b+(c[a+4>>2]|0)|0,B>>>0>j>>>0):0)break;a=c[a+8>>2]|0}f=B+-47+((B+-47+8&7|0)==0?0:0-(B+-47+8)&7)|0;f=f>>>0<(j+16|0)>>>0?j:f;b=g+8|0;b=(b&7|0)==0?0:0-b&7;H=g+b|0;b=h+-40-b|0;c[8497]=H;c[8494]=b;c[H+4>>2]=b|1;c[H+b+4>>2]=40;c[8498]=c[8613];c[f+4>>2]=27;c[f+8>>2]=c[8603];c[f+8+4>>2]=c[8604];c[f+8+8>>2]=c[8605];c[f+8+12>>2]=c[8606];c[8603]=g;c[8604]=h;c[8606]=0;c[8605]=f+8;b=f+24|0;do{b=b+4|0;c[b>>2]=7}while((b+4|0)>>>0<B>>>0);if((f|0)!=(j|0)){c[f+4>>2]=c[f+4>>2]&-2;c[j+4>>2]=f-j|1;c[f>>2]=f-j;if((f-j|0)>>>0<256){a=34004+((f-j|0)>>>3<<1<<2)|0;b=c[8491]|0;if(b&1<<((f-j|0)>>>3)){b=c[a+8>>2]|0;if(b>>>0<(c[8495]|0)>>>0)ba();else{C=b;D=a+8|0}}else{c[8491]=b|1<<((f-j|0)>>>3);C=a;D=a+8|0}c[D>>2]=j;c[C+12>>2]=j;c[j+8>>2]=C;c[j+12>>2]=a;break}if((f-j|0)>>>8)if((f-j|0)>>>0>16777215)b=31;else{b=(f-j|0)>>>8<<((((f-j|0)>>>8)+1048320|0)>>>16&8);b=14-((b+520192|0)>>>16&4|(((f-j|0)>>>8)+1048320|0)>>>16&8|((b<<((b+520192|0)>>>16&4))+245760|0)>>>16&2)+(b<<((b+520192|0)>>>16&4)<<(((b<<((b+520192|0)>>>16&4))+245760|0)>>>16&2)>>>15)|0;b=(f-j|0)>>>(b+7|0)&1|b<<1}else b=0;e=34268+(b<<2)|0;c[j+28>>2]=b;c[j+20>>2]=0;c[j+16>>2]=0;a=c[8492]|0;d=1<<b;if(!(a&d)){c[8492]=a|d;c[e>>2]=j;c[j+24>>2]=e;c[j+12>>2]=j;c[j+8>>2]=j;break}a=f-j<<((b|0)==31?0:25-(b>>>1)|0);e=c[e>>2]|0;while(1){if((c[e+4>>2]&-8|0)==(f-j|0)){A=304;break}d=e+16+(a>>>31<<2)|0;b=c[d>>2]|0;if(!b){A=301;break}else{a=a<<1;e=b}}if((A|0)==301)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[d>>2]=j;c[j+24>>2]=e;c[j+12>>2]=j;c[j+8>>2]=j;break}else if((A|0)==304){b=e+8|0;a=c[b>>2]|0;H=c[8495]|0;if(a>>>0>=H>>>0&e>>>0>=H>>>0){c[a+12>>2]=j;c[b>>2]=j;c[j+8>>2]=a;c[j+12>>2]=e;c[j+24>>2]=0;break}else ba()}}}else{H=c[8495]|0;if((H|0)==0|g>>>0<H>>>0)c[8495]=g;c[8603]=g;c[8604]=h;c[8606]=0;c[8500]=c[8609];c[8499]=-1;b=0;do{H=34004+(b<<1<<2)|0;c[H+12>>2]=H;c[H+8>>2]=H;b=b+1|0}while((b|0)!=32);H=g+8|0;H=(H&7|0)==0?0:0-H&7;G=g+H|0;H=h+-40-H|0;c[8497]=G;c[8494]=H;c[G+4>>2]=H|1;c[G+H+4>>2]=40;c[8498]=c[8613]}while(0);b=c[8494]|0;if(b>>>0>r>>>0){F=b-r|0;c[8494]=F;H=c[8497]|0;G=H+r|0;c[8497]=G;c[G+4>>2]=F|1;c[H+4>>2]=r|3;H=H+8|0;i=I;return H|0}}c[(Zf()|0)>>2]=12;H=0;i=I;return H|0} -function oa(b){b=b|0;var c=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0;e=d[b>>0]|0;j=Pd(d[b+1>>0]|0|0,0,8)|0;S=D;_=d[b+2>>0]|0;x=Pd(_|0,0,16)|0;Z=Pd(d[b+3>>0]|0|0,0,8)|0;C=D;Y=Pd(d[b+4>>0]|0|0,0,16)|0;C=C|D;m=d[b+5>>0]|0;n=Pd(m|0,0,24)|0;C=Rd(Z|_|Y|n|0,C|D|0,5)|0;n=Pd(d[b+6>>0]|0|0,0,8)|0;Y=D;_=d[b+7>>0]|0;Z=Pd(_|0,0,16)|0;Y=Rd(n|m|Z|0,Y|D|0,2)|0;Z=Pd(d[b+8>>0]|0|0,0,8)|0;m=D;n=Pd(d[b+9>>0]|0|0,0,16)|0;m=m|D;na=d[b+10>>0]|0;va=Pd(na|0,0,24)|0;m=Rd(Z|_|n|va|0,m|D|0,7)|0;va=Pd(d[b+11>>0]|0|0,0,8)|0;n=D;_=Pd(d[b+12>>0]|0|0,0,16)|0;n=n|D;Z=d[b+13>>0]|0;oa=Pd(Z|0,0,24)|0;n=Rd(va|na|_|oa|0,n|D|0,4)|0;oa=Pd(d[b+14>>0]|0|0,0,8)|0;_=D;na=d[b+15>>0]|0;va=Pd(na|0,0,16)|0;_=Rd(oa|Z|va|0,_|D|0,1)|0;va=Pd(d[b+16>>0]|0|0,0,8)|0;Z=D;oa=Pd(d[b+17>>0]|0|0,0,16)|0;Z=Z|D;xa=d[b+18>>0]|0;ya=Pd(xa|0,0,24)|0;Z=Rd(va|na|oa|ya|0,Z|D|0,6)|0;ya=Pd(d[b+19>>0]|0|0,0,8)|0;oa=D;na=Pd(d[b+20>>0]|0|0,0,16)|0;oa=Rd(ya|xa|na|0,oa|D|0,3)|0;na=D;xa=d[b+21>>0]|0;ya=Pd(d[b+22>>0]|0|0,0,8)|0;va=D;N=d[b+23>>0]|0;wa=Pd(N|0,0,16)|0;U=Pd(d[b+24>>0]|0|0,0,8)|0;ka=D;ua=Pd(d[b+25>>0]|0|0,0,16)|0;ka=ka|D;fa=d[b+26>>0]|0;Ca=Pd(fa|0,0,24)|0;ka=Rd(U|N|ua|Ca|0,ka|D|0,5)|0;Ca=Pd(d[b+27>>0]|0|0,0,8)|0;ua=D;N=d[b+28>>0]|0;U=Pd(N|0,0,16)|0;ua=Rd(Ca|fa|U|0,ua|D|0,2)|0;U=Pd(d[b+29>>0]|0|0,0,8)|0;fa=D;Ca=Pd(d[b+30>>0]|0|0,0,16)|0;fa=fa|D;A=d[b+31>>0]|0;g=Pd(A|0,0,24)|0;fa=Rd(U|N|Ca|g|0,fa|D|0,7)|0;g=Pd(d[b+32>>0]|0|0,0,8)|0;Ca=D;N=Pd(d[b+33>>0]|0|0,0,16)|0;Ca=Ca|D;U=d[b+34>>0]|0;I=Pd(U|0,0,24)|0;Ca=Rd(g|A|N|I|0,Ca|D|0,4)|0;I=Pd(d[b+35>>0]|0|0,0,8)|0;N=D;A=d[b+36>>0]|0;g=Pd(A|0,0,16)|0;N=Rd(I|U|g|0,N|D|0,1)|0;g=Pd(d[b+37>>0]|0|0,0,8)|0;U=D;I=Pd(d[b+38>>0]|0|0,0,16)|0;U=U|D;K=d[b+39>>0]|0;L=Pd(K|0,0,24)|0;U=Rd(g|A|I|L|0,U|D|0,6)|0;L=Pd(d[b+40>>0]|0|0,0,8)|0;I=D;A=Pd(d[b+41>>0]|0|0,0,16)|0;I=Rd(L|K|A|0,I|D|0,3)|0;A=D;K=d[b+42>>0]|0;L=Pd(d[b+43>>0]|0|0,0,8)|0;g=D;X=d[b+44>>0]|0;W=Pd(X|0,0,16)|0;G=Pd(d[b+45>>0]|0|0,0,8)|0;t=D;ha=Pd(d[b+46>>0]|0|0,0,16)|0;t=t|D;Da=d[b+47>>0]|0;u=Pd(Da|0,0,24)|0;t=Rd(G|X|ha|u|0,t|D|0,5)|0;u=Pd(d[b+48>>0]|0|0,0,8)|0;ha=D;X=d[b+49>>0]|0;G=Pd(X|0,0,16)|0;ha=Rd(u|Da|G|0,ha|D|0,2)|0;G=Pd(d[b+50>>0]|0|0,0,8)|0;Da=D;u=Pd(d[b+51>>0]|0|0,0,16)|0;Da=Da|D;s=d[b+52>>0]|0;q=Pd(s|0,0,24)|0;Da=Rd(G|X|u|q|0,Da|D|0,7)|0;q=Pd(d[b+53>>0]|0|0,0,8)|0;u=D;X=Pd(d[b+54>>0]|0|0,0,16)|0;u=u|D;G=d[b+55>>0]|0;f=Pd(G|0,0,24)|0;u=Rd(q|s|X|f|0,u|D|0,4)|0;f=Pd(d[b+56>>0]|0|0,0,8)|0;X=D;s=d[b+57>>0]|0;q=Pd(s|0,0,16)|0;X=Rd(f|G|q|0,X|D|0,1)|0;q=Pd(d[b+58>>0]|0|0,0,8)|0;G=D;f=Pd(d[b+59>>0]|0|0,0,16)|0;G=G|D;E=d[b+60>>0]|0;v=Pd(E|0,0,24)|0;G=Rd(q|s|f|v|0,G|D|0,6)|0;v=Pd(d[b+61>>0]|0|0,0,8)|0;f=D;s=Pd(d[b+62>>0]|0|0,0,16)|0;f=f|D;q=Pd(d[b+63>>0]|0|0,0,24)|0;f=Rd(v|E|s|q|0,f|D|0,3)|0;q=D;s=Ed(f|0,q|0,666643,0)|0;E=D;v=Ed(f|0,q|0,470296,0)|0;o=D;B=Ed(f|0,q|0,654183,0)|0;Q=D;$=Ed(f|0,q|0,-997805,-1)|0;i=D;h=Ed(f|0,q|0,136657,0)|0;p=D;q=Ed(f|0,q|0,-683901,-1)|0;g=oe(q|0,D|0,L|K|W&2031616|0,g|0)|0;W=D;K=Ed(G&2097151|0,0,666643,0)|0;L=D;q=Ed(G&2097151|0,0,470296,0)|0;f=D;qa=Ed(G&2097151|0,0,654183,0)|0;l=D;J=Ed(G&2097151|0,0,-997805,-1)|0;w=D;V=Ed(G&2097151|0,0,136657,0)|0;P=D;G=Ed(G&2097151|0,0,-683901,-1)|0;r=D;c=Ed(X&2097151|0,0,666643,0)|0;O=D;T=Ed(X&2097151|0,0,470296,0)|0;ga=D;aa=Ed(X&2097151|0,0,654183,0)|0;y=D;za=Ed(X&2097151|0,0,-997805,-1)|0;pa=D;H=Ed(X&2097151|0,0,136657,0)|0;k=D;X=Ed(X&2097151|0,0,-683901,-1)|0;U=oe(X|0,D|0,U&2097151|0,0)|0;P=oe(U|0,D|0,V|0,P|0)|0;i=oe(P|0,D|0,$|0,i|0)|0;$=D;P=Ed(u&2097151|0,0,666643,0)|0;V=D;U=Ed(u&2097151|0,0,470296,0)|0;X=D;ra=Ed(u&2097151|0,0,654183,0)|0;z=D;ca=Ed(u&2097151|0,0,-997805,-1)|0;ba=D;Ba=Ed(u&2097151|0,0,136657,0)|0;Aa=D;u=Ed(u&2097151|0,0,-683901,-1)|0;M=D;F=Ed(Da&2097151|0,0,666643,0)|0;R=D;la=Ed(Da&2097151|0,0,470296,0)|0;ma=D;ja=Ed(Da&2097151|0,0,654183,0)|0;ia=D;ta=Ed(Da&2097151|0,0,-997805,-1)|0;sa=D;ea=Ed(Da&2097151|0,0,136657,0)|0;da=D;Da=Ed(Da&2097151|0,0,-683901,-1)|0;Ca=oe(Da|0,D|0,Ca&2097151|0,0)|0;Aa=oe(Ca|0,D|0,Ba|0,Aa|0)|0;pa=oe(Aa|0,D|0,za|0,pa|0)|0;l=oe(pa|0,D|0,qa|0,l|0)|0;o=oe(l|0,D|0,v|0,o|0)|0;v=D;l=Ed(ha&2097151|0,0,666643,0)|0;Z=oe(l|0,D|0,Z&2097151|0,0)|0;l=D;qa=Ed(ha&2097151|0,0,470296,0)|0;pa=D;za=Ed(ha&2097151|0,0,654183,0)|0;va=oe(za|0,D|0,ya|xa|wa&2031616|0,va|0)|0;ma=oe(va|0,D|0,la|0,ma|0)|0;V=oe(ma|0,D|0,P|0,V|0)|0;P=D;ma=Ed(ha&2097151|0,0,-997805,-1)|0;la=D;va=Ed(ha&2097151|0,0,136657,0)|0;ua=oe(va|0,D|0,ua&2097151|0,0)|0;sa=oe(ua|0,D|0,ta|0,sa|0)|0;z=oe(sa|0,D|0,ra|0,z|0)|0;ga=oe(z|0,D|0,T|0,ga|0)|0;L=oe(ga|0,D|0,K|0,L|0)|0;K=D;ha=Ed(ha&2097151|0,0,-683901,-1)|0;ga=D;T=oe(Z|0,l|0,1048576,0)|0;T=Rd(T|0,D|0,21)|0;z=D;na=oe(qa|0,pa|0,oa|0,na|0)|0;na=oe(na|0,D|0,T|0,z|0)|0;R=oe(na|0,D|0,F|0,R|0)|0;F=D;z=Pd(T|0,z|0,21)|0;z=le(Z|0,l|0,z|0,D|0)|0;l=D;Z=oe(V|0,P|0,1048576,0)|0;Z=Rd(Z|0,D|0,21)|0;T=D;ka=oe(ma|0,la|0,ka&2097151|0,0)|0;ia=oe(ka|0,D|0,ja|0,ia|0)|0;X=oe(ia|0,D|0,U|0,X|0)|0;O=oe(X|0,D|0,c|0,O|0)|0;O=oe(O|0,D|0,Z|0,T|0)|0;c=D;T=Pd(Z|0,T|0,21)|0;Z=D;X=oe(L|0,K|0,1048576,0)|0;X=Dd(X|0,D|0,21)|0;U=D;fa=oe(ha|0,ga|0,fa&2097151|0,0)|0;da=oe(fa|0,D|0,ea|0,da|0)|0;ba=oe(da|0,D|0,ca|0,ba|0)|0;y=oe(ba|0,D|0,aa|0,y|0)|0;f=oe(y|0,D|0,q|0,f|0)|0;E=oe(f|0,D|0,s|0,E|0)|0;E=oe(E|0,D|0,X|0,U|0)|0;s=D;U=Pd(X|0,U|0,21)|0;X=D;f=oe(o|0,v|0,1048576,0)|0;f=Dd(f|0,D|0,21)|0;q=D;N=oe(u|0,M|0,N&2097151|0,0)|0;k=oe(N|0,D|0,H|0,k|0)|0;w=oe(k|0,D|0,J|0,w|0)|0;Q=oe(w|0,D|0,B|0,Q|0)|0;Q=oe(Q|0,D|0,f|0,q|0)|0;B=D;q=Pd(f|0,q|0,21)|0;q=le(o|0,v|0,q|0,D|0)|0;v=D;o=oe(i|0,$|0,1048576,0)|0;o=Dd(o|0,D|0,21)|0;f=D;A=oe(G|0,r|0,I|0,A|0)|0;p=oe(A|0,D|0,h|0,p|0)|0;p=oe(p|0,D|0,o|0,f|0)|0;h=D;f=Pd(o|0,f|0,21)|0;f=le(i|0,$|0,f|0,D|0)|0;$=D;i=oe(g|0,W|0,1048576,0)|0;i=Dd(i|0,D|0,21)|0;o=D;t=oe(i|0,o|0,t&2097151|0,0)|0;A=D;o=Pd(i|0,o|0,21)|0;o=le(g|0,W|0,o|0,D|0)|0;W=D;g=oe(R|0,F|0,1048576,0)|0;g=Rd(g|0,D|0,21)|0;i=D;I=Pd(g|0,i|0,21)|0;I=le(R|0,F|0,I|0,D|0)|0;F=D;R=oe(O|0,c|0,1048576,0)|0;R=Dd(R|0,D|0,21)|0;r=D;G=Pd(R|0,r|0,21)|0;G=le(O|0,c|0,G|0,D|0)|0;c=D;O=oe(E|0,s|0,1048576,0)|0;O=Dd(O|0,D|0,21)|0;w=D;v=oe(q|0,v|0,O|0,w|0)|0;q=D;w=Pd(O|0,w|0,21)|0;w=le(E|0,s|0,w|0,D|0)|0;s=D;E=oe(Q|0,B|0,1048576,0)|0;E=Dd(E|0,D|0,21)|0;O=D;$=oe(E|0,O|0,f|0,$|0)|0;f=D;O=Pd(E|0,O|0,21)|0;O=le(Q|0,B|0,O|0,D|0)|0;B=D;Q=oe(p|0,h|0,1048576,0)|0;Q=Dd(Q|0,D|0,21)|0;E=D;W=oe(Q|0,E|0,o|0,W|0)|0;o=D;E=Pd(Q|0,E|0,21)|0;E=le(p|0,h|0,E|0,D|0)|0;h=D;p=Ed(t|0,A|0,666643,0)|0;_=oe(p|0,D|0,_&2097151|0,0)|0;p=D;Q=Ed(t|0,A|0,470296,0)|0;Q=oe(z|0,l|0,Q|0,D|0)|0;l=D;z=Ed(t|0,A|0,654183,0)|0;z=oe(I|0,F|0,z|0,D|0)|0;F=D;I=Ed(t|0,A|0,-997805,-1)|0;J=D;k=Ed(t|0,A|0,136657,0)|0;k=oe(G|0,c|0,k|0,D|0)|0;c=D;A=Ed(t|0,A|0,-683901,-1)|0;t=D;r=oe(L|0,K|0,R|0,r|0)|0;X=le(r|0,D|0,U|0,X|0)|0;t=oe(X|0,D|0,A|0,t|0)|0;A=D;X=Ed(W|0,o|0,666643,0)|0;n=oe(X|0,D|0,n&2097151|0,0)|0;X=D;U=Ed(W|0,o|0,470296,0)|0;U=oe(_|0,p|0,U|0,D|0)|0;p=D;_=Ed(W|0,o|0,654183,0)|0;_=oe(Q|0,l|0,_|0,D|0)|0;l=D;Q=Ed(W|0,o|0,-997805,-1)|0;Q=oe(z|0,F|0,Q|0,D|0)|0;F=D;z=Ed(W|0,o|0,136657,0)|0;r=D;o=Ed(W|0,o|0,-683901,-1)|0;o=oe(k|0,c|0,o|0,D|0)|0;c=D;k=Ed(E|0,h|0,666643,0)|0;m=oe(k|0,D|0,m&2097151|0,0)|0;k=D;W=Ed(E|0,h|0,470296,0)|0;W=oe(n|0,X|0,W|0,D|0)|0;X=D;n=Ed(E|0,h|0,654183,0)|0;n=oe(U|0,p|0,n|0,D|0)|0;p=D;U=Ed(E|0,h|0,-997805,-1)|0;U=oe(_|0,l|0,U|0,D|0)|0;l=D;_=Ed(E|0,h|0,136657,0)|0;_=oe(Q|0,F|0,_|0,D|0)|0;F=D;h=Ed(E|0,h|0,-683901,-1)|0;E=D;i=oe(V|0,P|0,g|0,i|0)|0;Z=le(i|0,D|0,T|0,Z|0)|0;J=oe(Z|0,D|0,I|0,J|0)|0;r=oe(J|0,D|0,z|0,r|0)|0;E=oe(r|0,D|0,h|0,E|0)|0;h=D;r=Ed($|0,f|0,666643,0)|0;z=D;J=Ed($|0,f|0,470296,0)|0;I=D;Z=Ed($|0,f|0,654183,0)|0;T=D;i=Ed($|0,f|0,-997805,-1)|0;g=D;P=Ed($|0,f|0,136657,0)|0;P=oe(U|0,l|0,P|0,D|0)|0;l=D;f=Ed($|0,f|0,-683901,-1)|0;f=oe(_|0,F|0,f|0,D|0)|0;F=D;_=Ed(O|0,B|0,666643,0)|0;$=D;U=Ed(O|0,B|0,470296,0)|0;V=D;Q=Ed(O|0,B|0,654183,0)|0;R=D;K=Ed(O|0,B|0,-997805,-1)|0;L=D;G=Ed(O|0,B|0,136657,0)|0;H=D;B=Ed(O|0,B|0,-683901,-1)|0;B=oe(P|0,l|0,B|0,D|0)|0;l=D;P=Ed(v|0,q|0,666643,0)|0;S=oe(P|0,D|0,j|e|x&2031616|0,S|0)|0;x=D;e=Ed(v|0,q|0,470296,0)|0;j=D;P=Ed(v|0,q|0,654183,0)|0;Y=oe(P|0,D|0,Y&2097151|0,0)|0;z=oe(Y|0,D|0,r|0,z|0)|0;V=oe(z|0,D|0,U|0,V|0)|0;U=D;z=Ed(v|0,q|0,-997805,-1)|0;r=D;Y=Ed(v|0,q|0,136657,0)|0;Y=oe(W|0,X|0,Y|0,D|0)|0;T=oe(Y|0,D|0,Z|0,T|0)|0;L=oe(T|0,D|0,K|0,L|0)|0;K=D;q=Ed(v|0,q|0,-683901,-1)|0;v=D;T=oe(S|0,x|0,1048576,0)|0;T=Dd(T|0,D|0,21)|0;Z=D;C=oe(e|0,j|0,C&2097151|0,0)|0;$=oe(C|0,D|0,_|0,$|0)|0;$=oe($|0,D|0,T|0,Z|0)|0;_=D;Z=Pd(T|0,Z|0,21)|0;Z=le(S|0,x|0,Z|0,D|0)|0;x=D;S=oe(V|0,U|0,1048576,0)|0;S=Dd(S|0,D|0,21)|0;T=D;r=oe(m|0,k|0,z|0,r|0)|0;I=oe(r|0,D|0,J|0,I|0)|0;R=oe(I|0,D|0,Q|0,R|0)|0;R=oe(R|0,D|0,S|0,T|0)|0;Q=D;T=Pd(S|0,T|0,21)|0;S=D;I=oe(L|0,K|0,1048576,0)|0;I=Dd(I|0,D|0,21)|0;J=D;v=oe(n|0,p|0,q|0,v|0)|0;g=oe(v|0,D|0,i|0,g|0)|0;H=oe(g|0,D|0,G|0,H|0)|0;H=oe(H|0,D|0,I|0,J|0)|0;G=D;J=Pd(I|0,J|0,21)|0;I=D;g=oe(B|0,l|0,1048576,0)|0;g=Dd(g|0,D|0,21)|0;i=D;F=oe(f|0,F|0,g|0,i|0)|0;f=D;i=Pd(g|0,i|0,21)|0;i=le(B|0,l|0,i|0,D|0)|0;l=D;B=oe(E|0,h|0,1048576,0)|0;B=Dd(B|0,D|0,21)|0;g=D;c=oe(o|0,c|0,B|0,g|0)|0;o=D;g=Pd(B|0,g|0,21)|0;g=le(E|0,h|0,g|0,D|0)|0;h=D;E=oe(t|0,A|0,1048576,0)|0;E=Dd(E|0,D|0,21)|0;B=D;s=oe(w|0,s|0,E|0,B|0)|0;w=D;B=Pd(E|0,B|0,21)|0;B=le(t|0,A|0,B|0,D|0)|0;A=D;t=oe($|0,_|0,1048576,0)|0;t=Dd(t|0,D|0,21)|0;E=D;v=Pd(t|0,E|0,21)|0;q=D;p=oe(R|0,Q|0,1048576,0)|0;p=Dd(p|0,D|0,21)|0;n=D;r=Pd(p|0,n|0,21)|0;z=D;k=oe(H|0,G|0,1048576,0)|0;k=Dd(k|0,D|0,21)|0;m=D;l=oe(i|0,l|0,k|0,m|0)|0;i=D;m=Pd(k|0,m|0,21)|0;k=D;C=oe(F|0,f|0,1048576,0)|0;C=Dd(C|0,D|0,21)|0;j=D;h=oe(g|0,h|0,C|0,j|0)|0;g=D;j=Pd(C|0,j|0,21)|0;j=le(F|0,f|0,j|0,D|0)|0;f=D;F=oe(c|0,o|0,1048576,0)|0;F=Dd(F|0,D|0,21)|0;C=D;A=oe(B|0,A|0,F|0,C|0)|0;B=D;C=Pd(F|0,C|0,21)|0;C=le(c|0,o|0,C|0,D|0)|0;o=D;c=oe(s|0,w|0,1048576,0)|0;c=Dd(c|0,D|0,21)|0;F=D;e=Pd(c|0,F|0,21)|0;e=le(s|0,w|0,e|0,D|0)|0;w=D;s=Ed(c|0,F|0,666643,0)|0;s=oe(Z|0,x|0,s|0,D|0)|0;x=D;Z=Ed(c|0,F|0,470296,0)|0;Y=D;X=Ed(c|0,F|0,654183,0)|0;W=D;P=Ed(c|0,F|0,-997805,-1)|0;O=D;N=Ed(c|0,F|0,136657,0)|0;M=D;F=Ed(c|0,F|0,-683901,-1)|0;c=D;u=Dd(s|0,x|0,21)|0;y=D;Y=oe($|0,_|0,Z|0,Y|0)|0;Y=oe(Y|0,D|0,u|0,y|0)|0;q=le(Y|0,D|0,v|0,q|0)|0;v=D;y=Pd(u|0,y|0,21)|0;y=le(s|0,x|0,y|0,D|0)|0;x=D;s=Dd(q|0,v|0,21)|0;u=D;U=oe(X|0,W|0,V|0,U|0)|0;S=le(U|0,D|0,T|0,S|0)|0;E=oe(S|0,D|0,t|0,E|0)|0;E=oe(E|0,D|0,s|0,u|0)|0;t=D;u=Pd(s|0,u|0,21)|0;u=le(q|0,v|0,u|0,D|0)|0;v=D;q=Dd(E|0,t|0,21)|0;s=D;O=oe(R|0,Q|0,P|0,O|0)|0;z=le(O|0,D|0,r|0,z|0)|0;z=oe(z|0,D|0,q|0,s|0)|0;r=D;s=Pd(q|0,s|0,21)|0;s=le(E|0,t|0,s|0,D|0)|0;t=D;E=Dd(z|0,r|0,21)|0;q=D;K=oe(N|0,M|0,L|0,K|0)|0;I=le(K|0,D|0,J|0,I|0)|0;n=oe(I|0,D|0,p|0,n|0)|0;n=oe(n|0,D|0,E|0,q|0)|0;p=D;q=Pd(E|0,q|0,21)|0;q=le(z|0,r|0,q|0,D|0)|0;r=D;z=Dd(n|0,p|0,21)|0;E=D;c=oe(H|0,G|0,F|0,c|0)|0;k=le(c|0,D|0,m|0,k|0)|0;k=oe(k|0,D|0,z|0,E|0)|0;m=D;E=Pd(z|0,E|0,21)|0;E=le(n|0,p|0,E|0,D|0)|0;p=D;n=Dd(k|0,m|0,21)|0;z=D;i=oe(l|0,i|0,n|0,z|0)|0;l=D;z=Pd(n|0,z|0,21)|0;z=le(k|0,m|0,z|0,D|0)|0;m=D;k=Dd(i|0,l|0,21)|0;n=D;f=oe(k|0,n|0,j|0,f|0)|0;j=D;n=Pd(k|0,n|0,21)|0;n=le(i|0,l|0,n|0,D|0)|0;l=D;i=Dd(f|0,j|0,21)|0;k=D;g=oe(h|0,g|0,i|0,k|0)|0;h=D;k=Pd(i|0,k|0,21)|0;k=le(f|0,j|0,k|0,D|0)|0;j=D;f=Dd(g|0,h|0,21)|0;i=D;o=oe(f|0,i|0,C|0,o|0)|0;C=D;i=Pd(f|0,i|0,21)|0;i=le(g|0,h|0,i|0,D|0)|0;h=D;g=Dd(o|0,C|0,21)|0;f=D;B=oe(A|0,B|0,g|0,f|0)|0;A=D;f=Pd(g|0,f|0,21)|0;f=le(o|0,C|0,f|0,D|0)|0;C=D;o=Dd(B|0,A|0,21)|0;g=D;w=oe(o|0,g|0,e|0,w|0)|0;e=D;g=Pd(o|0,g|0,21)|0;g=le(B|0,A|0,g|0,D|0)|0;A=D;B=Dd(w|0,e|0,21)|0;o=D;c=Pd(B|0,o|0,21)|0;c=le(w|0,e|0,c|0,D|0)|0;e=D;w=Ed(B|0,o|0,666643,0)|0;x=oe(w|0,D|0,y|0,x|0)|0;y=D;w=Ed(B|0,o|0,470296,0)|0;w=oe(u|0,v|0,w|0,D|0)|0;v=D;u=Ed(B|0,o|0,654183,0)|0;u=oe(s|0,t|0,u|0,D|0)|0;t=D;s=Ed(B|0,o|0,-997805,-1)|0;s=oe(q|0,r|0,s|0,D|0)|0;r=D;q=Ed(B|0,o|0,136657,0)|0;q=oe(E|0,p|0,q|0,D|0)|0;p=D;o=Ed(B|0,o|0,-683901,-1)|0;o=oe(z|0,m|0,o|0,D|0)|0;m=D;z=Dd(x|0,y|0,21)|0;B=D;v=oe(w|0,v|0,z|0,B|0)|0;w=D;B=Pd(z|0,B|0,21)|0;B=le(x|0,y|0,B|0,D|0)|0;y=D;x=Dd(v|0,w|0,21)|0;z=D;t=oe(u|0,t|0,x|0,z|0)|0;u=D;z=Pd(x|0,z|0,21)|0;z=le(v|0,w|0,z|0,D|0)|0;w=D;v=Dd(t|0,u|0,21)|0;x=D;r=oe(s|0,r|0,v|0,x|0)|0;s=D;x=Pd(v|0,x|0,21)|0;x=le(t|0,u|0,x|0,D|0)|0;u=D;t=Dd(r|0,s|0,21)|0;v=D;p=oe(q|0,p|0,t|0,v|0)|0;q=D;v=Pd(t|0,v|0,21)|0;v=le(r|0,s|0,v|0,D|0)|0;s=D;r=Dd(p|0,q|0,21)|0;t=D;m=oe(o|0,m|0,r|0,t|0)|0;o=D;t=Pd(r|0,t|0,21)|0;t=le(p|0,q|0,t|0,D|0)|0;q=D;p=Dd(m|0,o|0,21)|0;r=D;l=oe(p|0,r|0,n|0,l|0)|0;n=D;r=Pd(p|0,r|0,21)|0;r=le(m|0,o|0,r|0,D|0)|0;o=D;m=Dd(l|0,n|0,21)|0;p=D;j=oe(m|0,p|0,k|0,j|0)|0;k=D;p=Pd(m|0,p|0,21)|0;p=le(l|0,n|0,p|0,D|0)|0;n=D;l=Dd(j|0,k|0,21)|0;m=D;h=oe(l|0,m|0,i|0,h|0)|0;i=D;m=Pd(l|0,m|0,21)|0;m=le(j|0,k|0,m|0,D|0)|0;k=D;j=Dd(h|0,i|0,21)|0;l=D;C=oe(j|0,l|0,f|0,C|0)|0;f=D;l=Pd(j|0,l|0,21)|0;l=le(h|0,i|0,l|0,D|0)|0;i=D;h=Dd(C|0,f|0,21)|0;j=D;A=oe(h|0,j|0,g|0,A|0)|0;g=D;j=Pd(h|0,j|0,21)|0;j=le(C|0,f|0,j|0,D|0)|0;f=D;C=Dd(A|0,g|0,21)|0;h=D;e=oe(C|0,h|0,c|0,e|0)|0;c=D;h=Pd(C|0,h|0,21)|0;h=le(A|0,g|0,h|0,D|0)|0;g=D;a[b>>0]=B;A=Rd(B|0,y|0,8)|0;a[b+1>>0]=A;y=Rd(B|0,y|0,16)|0;B=D;A=Pd(z|0,w|0,5)|0;a[b+2>>0]=A|y;y=Rd(z|0,w|0,3)|0;a[b+3>>0]=y;y=Rd(z|0,w|0,11)|0;a[b+4>>0]=y;w=Rd(z|0,w|0,19)|0;z=D;y=Pd(x|0,u|0,2)|0;a[b+5>>0]=y|w;w=Rd(x|0,u|0,6)|0;a[b+6>>0]=w;u=Rd(x|0,u|0,14)|0;x=D;w=Pd(v|0,s|0,7)|0;a[b+7>>0]=w|u;u=Rd(v|0,s|0,1)|0;a[b+8>>0]=u;u=Rd(v|0,s|0,9)|0;a[b+9>>0]=u;s=Rd(v|0,s|0,17)|0;v=D;u=Pd(t|0,q|0,4)|0;a[b+10>>0]=u|s;s=Rd(t|0,q|0,4)|0;a[b+11>>0]=s;s=Rd(t|0,q|0,12)|0;a[b+12>>0]=s;q=Rd(t|0,q|0,20)|0;t=D;s=Pd(r|0,o|0,1)|0;a[b+13>>0]=s|q;q=Rd(r|0,o|0,7)|0;a[b+14>>0]=q;o=Rd(r|0,o|0,15)|0;r=D;q=Pd(p|0,n|0,6)|0;a[b+15>>0]=q|o;o=Rd(p|0,n|0,2)|0;a[b+16>>0]=o;o=Rd(p|0,n|0,10)|0;a[b+17>>0]=o;n=Rd(p|0,n|0,18)|0;p=D;o=Pd(m|0,k|0,3)|0;a[b+18>>0]=o|n;n=Rd(m|0,k|0,5)|0;a[b+19>>0]=n;k=Rd(m|0,k|0,13)|0;a[b+20>>0]=k;a[b+21>>0]=l;k=Rd(l|0,i|0,8)|0;a[b+22>>0]=k;i=Rd(l|0,i|0,16)|0;l=D;k=Pd(j|0,f|0,5)|0;a[b+23>>0]=k|i;i=Rd(j|0,f|0,3)|0;a[b+24>>0]=i;i=Rd(j|0,f|0,11)|0;a[b+25>>0]=i;f=Rd(j|0,f|0,19)|0;j=D;i=Pd(h|0,g|0,2)|0;a[b+26>>0]=i|f;f=Rd(h|0,g|0,6)|0;a[b+27>>0]=f;g=Rd(h|0,g|0,14)|0;h=D;f=Pd(e|0,c|0,7)|0;a[b+28>>0]=g|f;f=Rd(e|0,c|0,1)|0;a[b+29>>0]=f;f=Rd(e|0,c|0,9)|0;a[b+30>>0]=f;c=Rd(e|0,c|0,17)|0;a[b+31>>0]=c;return}function pa(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,fb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0,sc=0,tc=0,uc=0,vc=0,wc=0,xc=0,yc=0,zc=0,Ac=0,Bc=0,Cc=0,Dc=0,Ec=0,Fc=0,Gc=0,Hc=0,Ic=0,Jc=0,Kc=0,Lc=0,Mc=0,Nc=0,Oc=0,Pc=0;o=c[b>>2]|0;n=c[b+4>>2]|0;k=c[b+8>>2]|0;fa=c[b+12>>2]|0;N=c[b+16>>2]|0;M=c[b+20>>2]|0;g=c[b+24>>2]|0;ea=c[b+28>>2]|0;L=c[b+32>>2]|0;q=c[b+36>>2]|0;I=c[d>>2]|0;Oc=c[d+4>>2]|0;cc=c[d+8>>2]|0;sb=c[d+12>>2]|0;Ia=c[d+16>>2]|0;jc=c[d+20>>2]|0;Db=c[d+24>>2]|0;Ta=c[d+28>>2]|0;ga=c[d+32>>2]|0;Pc=c[d+36>>2]|0;Mc=Ed(I|0,((I|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;Lc=D;wc=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;vc=D;ub=Ed(cc|0,((cc|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;tb=D;Ka=Ed(sb|0,((sb|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;Ja=D;mc=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;lc=D;Gb=Ed(jc|0,((jc|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;Fb=D;Wa=Ed(Db|0,((Db|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;Va=D;ja=Ed(Ta|0,((Ta|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;ia=D;P=Ed(ga|0,((ga|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;O=D;o=Ed(Pc|0,((Pc|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;l=D;dc=Ed(I|0,((I|0)<0)<<31>>31|0,n|0,((n|0)<0)<<31>>31|0)|0;ec=D;yb=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,n<<1|0,((n<<1|0)<0)<<31>>31|0)|0;xb=D;Ma=Ed(cc|0,((cc|0)<0)<<31>>31|0,n|0,((n|0)<0)<<31>>31|0)|0;La=D;oc=Ed(sb|0,((sb|0)<0)<<31>>31|0,n<<1|0,((n<<1|0)<0)<<31>>31|0)|0;nc=D;Ib=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,n|0,((n|0)<0)<<31>>31|0)|0;Hb=D;Ya=Ed(jc|0,((jc|0)<0)<<31>>31|0,n<<1|0,((n<<1|0)<0)<<31>>31|0)|0;Xa=D;la=Ed(Db|0,((Db|0)<0)<<31>>31|0,n|0,((n|0)<0)<<31>>31|0)|0;ka=D;R=Ed(Ta|0,((Ta|0)<0)<<31>>31|0,n<<1|0,((n<<1|0)<0)<<31>>31|0)|0;Q=D;t=Ed(ga|0,((ga|0)<0)<<31>>31|0,n|0,((n|0)<0)<<31>>31|0)|0;s=D;d=((Pc*19|0)<0)<<31>>31;n=Ed(Pc*19|0,d|0,n<<1|0,((n<<1|0)<0)<<31>>31|0)|0;p=D;wb=Ed(I|0,((I|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;vb=D;Qa=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;Pa=D;qc=Ed(cc|0,((cc|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;pc=D;Kb=Ed(sb|0,((sb|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;Jb=D;_a=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;Za=D;na=Ed(jc|0,((jc|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;ma=D;T=Ed(Db|0,((Db|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;S=D;v=Ed(Ta|0,((Ta|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;u=D;ha=((ga*19|0)<0)<<31>>31;yc=Ed(ga*19|0,ha|0,k|0,((k|0)<0)<<31>>31|0)|0;xc=D;k=Ed(Pc*19|0,d|0,k|0,((k|0)<0)<<31>>31|0)|0;j=D;Oa=Ed(I|0,((I|0)<0)<<31>>31|0,fa|0,((fa|0)<0)<<31>>31|0)|0;Na=D;uc=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,fa<<1|0,((fa<<1|0)<0)<<31>>31|0)|0;tc=D;Mb=Ed(cc|0,((cc|0)<0)<<31>>31|0,fa|0,((fa|0)<0)<<31>>31|0)|0;Lb=D;ab=Ed(sb|0,((sb|0)<0)<<31>>31|0,fa<<1|0,((fa<<1|0)<0)<<31>>31|0)|0;$a=D;pa=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,fa|0,((fa|0)<0)<<31>>31|0)|0;oa=D;V=Ed(jc|0,((jc|0)<0)<<31>>31|0,fa<<1|0,((fa<<1|0)<0)<<31>>31|0)|0;U=D;x=Ed(Db|0,((Db|0)<0)<<31>>31|0,fa|0,((fa|0)<0)<<31>>31|0)|0;w=D;Ua=((Ta*19|0)<0)<<31>>31;Ac=Ed(Ta*19|0,Ua|0,fa<<1|0,((fa<<1|0)<0)<<31>>31|0)|0;zc=D;Sb=Ed(ga*19|0,ha|0,fa|0,((fa|0)<0)<<31>>31|0)|0;Rb=D;fa=Ed(Pc*19|0,d|0,fa<<1|0,((fa<<1|0)<0)<<31>>31|0)|0;f=D;sc=Ed(I|0,((I|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;rc=D;Qb=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;Pb=D;cb=Ed(cc|0,((cc|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;bb=D;ra=Ed(sb|0,((sb|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;qa=D;X=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;W=D;z=Ed(jc|0,((jc|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;y=D;Eb=((Db*19|0)<0)<<31>>31;Cc=Ed(Db*19|0,Eb|0,N|0,((N|0)<0)<<31>>31|0)|0;Bc=D;Ub=Ed(Ta*19|0,Ua|0,N|0,((N|0)<0)<<31>>31|0)|0;Tb=D;ib=Ed(ga*19|0,ha|0,N|0,((N|0)<0)<<31>>31|0)|0;hb=D;N=Ed(Pc*19|0,d|0,N|0,((N|0)<0)<<31>>31|0)|0;e=D;Ob=Ed(I|0,((I|0)<0)<<31>>31|0,M|0,((M|0)<0)<<31>>31|0)|0;Nb=D;gb=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,M<<1|0,((M<<1|0)<0)<<31>>31|0)|0;fb=D;ta=Ed(cc|0,((cc|0)<0)<<31>>31|0,M|0,((M|0)<0)<<31>>31|0)|0;sa=D;Z=Ed(sb|0,((sb|0)<0)<<31>>31|0,M<<1|0,((M<<1|0)<0)<<31>>31|0)|0;Y=D;B=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,M|0,((M|0)<0)<<31>>31|0)|0;A=D;kc=((jc*19|0)<0)<<31>>31;Ec=Ed(jc*19|0,kc|0,M<<1|0,((M<<1|0)<0)<<31>>31|0)|0;Dc=D;Wb=Ed(Db*19|0,Eb|0,M|0,((M|0)<0)<<31>>31|0)|0;Vb=D;kb=Ed(Ta*19|0,Ua|0,M<<1|0,((M<<1|0)<0)<<31>>31|0)|0;jb=D;Aa=Ed(ga*19|0,ha|0,M|0,((M|0)<0)<<31>>31|0)|0;za=D;b=Ed(Pc*19|0,d|0,M<<1|0,((M<<1|0)<0)<<31>>31|0)|0;M=D;eb=Ed(I|0,((I|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;db=D;xa=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;wa=D;$=Ed(cc|0,((cc|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;_=D;E=Ed(sb|0,((sb|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;C=D;Gc=Ed(Ia*19|0,((Ia*19|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;Fc=D;Yb=Ed(jc*19|0,kc|0,g|0,((g|0)<0)<<31>>31|0)|0;Xb=D;mb=Ed(Db*19|0,Eb|0,g|0,((g|0)<0)<<31>>31|0)|0;lb=D;Ca=Ed(Ta*19|0,Ua|0,g|0,((g|0)<0)<<31>>31|0)|0;Ba=D;m=Ed(ga*19|0,ha|0,g|0,((g|0)<0)<<31>>31|0)|0;r=D;g=Ed(Pc*19|0,d|0,g|0,((g|0)<0)<<31>>31|0)|0;ya=D;va=Ed(I|0,((I|0)<0)<<31>>31|0,ea|0,((ea|0)<0)<<31>>31|0)|0;ua=D;da=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,ea<<1|0,((ea<<1|0)<0)<<31>>31|0)|0;ca=D;G=Ed(cc|0,((cc|0)<0)<<31>>31|0,ea|0,((ea|0)<0)<<31>>31|0)|0;F=D;Ic=Ed(sb*19|0,((sb*19|0)<0)<<31>>31|0,ea<<1|0,((ea<<1|0)<0)<<31>>31|0)|0;Hc=D;_b=Ed(Ia*19|0,((Ia*19|0)<0)<<31>>31|0,ea|0,((ea|0)<0)<<31>>31|0)|0;Zb=D;ob=Ed(jc*19|0,kc|0,ea<<1|0,((ea<<1|0)<0)<<31>>31|0)|0;nb=D;Ea=Ed(Db*19|0,Eb|0,ea|0,((ea|0)<0)<<31>>31|0)|0;Da=D;gc=Ed(Ta*19|0,Ua|0,ea<<1|0,((ea<<1|0)<0)<<31>>31|0)|0;fc=D;Ab=Ed(ga*19|0,ha|0,ea|0,((ea|0)<0)<<31>>31|0)|0;zb=D;ea=Ed(Pc*19|0,d|0,ea<<1|0,((ea<<1|0)<0)<<31>>31|0)|0;i=D;ba=Ed(I|0,((I|0)<0)<<31>>31|0,L|0,((L|0)<0)<<31>>31|0)|0;aa=D;K=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,L|0,((L|0)<0)<<31>>31|0)|0;J=D;Kc=Ed(cc*19|0,((cc*19|0)<0)<<31>>31|0,L|0,((L|0)<0)<<31>>31|0)|0;Jc=D;ac=Ed(sb*19|0,((sb*19|0)<0)<<31>>31|0,L|0,((L|0)<0)<<31>>31|0)|0;$b=D;qb=Ed(Ia*19|0,((Ia*19|0)<0)<<31>>31|0,L|0,((L|0)<0)<<31>>31|0)|0;pb=D;Ga=Ed(jc*19|0,kc|0,L|0,((L|0)<0)<<31>>31|0)|0;Fa=D;ic=Ed(Db*19|0,Eb|0,L|0,((L|0)<0)<<31>>31|0)|0;hc=D;Cb=Ed(Ta*19|0,Ua|0,L|0,((L|0)<0)<<31>>31|0)|0;Bb=D;Sa=Ed(ga*19|0,ha|0,L|0,((L|0)<0)<<31>>31|0)|0;Ra=D;L=Ed(Pc*19|0,d|0,L|0,((L|0)<0)<<31>>31|0)|0;h=D;I=Ed(I|0,((I|0)<0)<<31>>31|0,q|0,((q|0)<0)<<31>>31|0)|0;H=D;Oc=Ed(Oc*19|0,((Oc*19|0)<0)<<31>>31|0,q<<1|0,((q<<1|0)<0)<<31>>31|0)|0;Nc=D;cc=Ed(cc*19|0,((cc*19|0)<0)<<31>>31|0,q|0,((q|0)<0)<<31>>31|0)|0;bc=D;sb=Ed(sb*19|0,((sb*19|0)<0)<<31>>31|0,q<<1|0,((q<<1|0)<0)<<31>>31|0)|0;rb=D;Ia=Ed(Ia*19|0,((Ia*19|0)<0)<<31>>31|0,q|0,((q|0)<0)<<31>>31|0)|0;Ha=D;kc=Ed(jc*19|0,kc|0,q<<1|0,((q<<1|0)<0)<<31>>31|0)|0;jc=D;Eb=Ed(Db*19|0,Eb|0,q|0,((q|0)<0)<<31>>31|0)|0;Db=D;Ua=Ed(Ta*19|0,Ua|0,q<<1|0,((q<<1|0)<0)<<31>>31|0)|0;Ta=D;ha=Ed(ga*19|0,ha|0,q|0,((q|0)<0)<<31>>31|0)|0;ga=D;q=Ed(Pc*19|0,d|0,q<<1|0,((q<<1|0)<0)<<31>>31|0)|0;d=D;Lc=oe(Oc|0,Nc|0,Mc|0,Lc|0)|0;Jc=oe(Lc|0,D|0,Kc|0,Jc|0)|0;Hc=oe(Jc|0,D|0,Ic|0,Hc|0)|0;Fc=oe(Hc|0,D|0,Gc|0,Fc|0)|0;Dc=oe(Fc|0,D|0,Ec|0,Dc|0)|0;Bc=oe(Dc|0,D|0,Cc|0,Bc|0)|0;zc=oe(Bc|0,D|0,Ac|0,zc|0)|0;xc=oe(zc|0,D|0,yc|0,xc|0)|0;p=oe(xc|0,D|0,n|0,p|0)|0;n=D;ec=oe(wc|0,vc|0,dc|0,ec|0)|0;dc=D;rc=oe(uc|0,tc|0,sc|0,rc|0)|0;pc=oe(rc|0,D|0,qc|0,pc|0)|0;nc=oe(pc|0,D|0,oc|0,nc|0)|0;lc=oe(nc|0,D|0,mc|0,lc|0)|0;jc=oe(lc|0,D|0,kc|0,jc|0)|0;hc=oe(jc|0,D|0,ic|0,hc|0)|0;fc=oe(hc|0,D|0,gc|0,fc|0)|0;r=oe(fc|0,D|0,m|0,r|0)|0;M=oe(r|0,D|0,b|0,M|0)|0;b=D;r=oe(p|0,n|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;m=D;bc=oe(ec|0,dc|0,cc|0,bc|0)|0;$b=oe(bc|0,D|0,ac|0,$b|0)|0;Zb=oe($b|0,D|0,_b|0,Zb|0)|0;Xb=oe(Zb|0,D|0,Yb|0,Xb|0)|0;Vb=oe(Xb|0,D|0,Wb|0,Vb|0)|0;Tb=oe(Vb|0,D|0,Ub|0,Tb|0)|0;Rb=oe(Tb|0,D|0,Sb|0,Rb|0)|0;j=oe(Rb|0,D|0,k|0,j|0)|0;j=oe(j|0,D|0,r|0,m|0)|0;k=D;m=Pd(r|0,m|0,26)|0;m=le(p|0,n|0,m|0,D|0)|0;n=D;p=oe(M|0,b|0,33554432,0)|0;p=Dd(p|0,D|0,26)|0;r=D;Nb=oe(Qb|0,Pb|0,Ob|0,Nb|0)|0;Lb=oe(Nb|0,D|0,Mb|0,Lb|0)|0;Jb=oe(Lb|0,D|0,Kb|0,Jb|0)|0;Hb=oe(Jb|0,D|0,Ib|0,Hb|0)|0;Fb=oe(Hb|0,D|0,Gb|0,Fb|0)|0;Db=oe(Fb|0,D|0,Eb|0,Db|0)|0;Bb=oe(Db|0,D|0,Cb|0,Bb|0)|0;zb=oe(Bb|0,D|0,Ab|0,zb|0)|0;ya=oe(zb|0,D|0,g|0,ya|0)|0;ya=oe(ya|0,D|0,p|0,r|0)|0;g=D;r=Pd(p|0,r|0,26)|0;r=le(M|0,b|0,r|0,D|0)|0;b=D;M=oe(j|0,k|0,16777216,0)|0;M=Dd(M|0,D|0,25)|0;p=D;vb=oe(yb|0,xb|0,wb|0,vb|0)|0;tb=oe(vb|0,D|0,ub|0,tb|0)|0;rb=oe(tb|0,D|0,sb|0,rb|0)|0;pb=oe(rb|0,D|0,qb|0,pb|0)|0;nb=oe(pb|0,D|0,ob|0,nb|0)|0;lb=oe(nb|0,D|0,mb|0,lb|0)|0;jb=oe(lb|0,D|0,kb|0,jb|0)|0;hb=oe(jb|0,D|0,ib|0,hb|0)|0;f=oe(hb|0,D|0,fa|0,f|0)|0;f=oe(f|0,D|0,M|0,p|0)|0;fa=D;p=Pd(M|0,p|0,25)|0;p=le(j|0,k|0,p|0,D|0)|0;k=D;j=oe(ya|0,g|0,16777216,0)|0;j=Dd(j|0,D|0,25)|0;M=D;db=oe(gb|0,fb|0,eb|0,db|0)|0;bb=oe(db|0,D|0,cb|0,bb|0)|0;$a=oe(bb|0,D|0,ab|0,$a|0)|0;Za=oe($a|0,D|0,_a|0,Za|0)|0;Xa=oe(Za|0,D|0,Ya|0,Xa|0)|0;Va=oe(Xa|0,D|0,Wa|0,Va|0)|0;Ta=oe(Va|0,D|0,Ua|0,Ta|0)|0;Ra=oe(Ta|0,D|0,Sa|0,Ra|0)|0;i=oe(Ra|0,D|0,ea|0,i|0)|0;i=oe(i|0,D|0,j|0,M|0)|0;ea=D;M=Pd(j|0,M|0,25)|0;M=le(ya|0,g|0,M|0,D|0)|0;g=D;ya=oe(f|0,fa|0,33554432,0)|0;ya=Dd(ya|0,D|0,26)|0;j=D;Na=oe(Qa|0,Pa|0,Oa|0,Na|0)|0;La=oe(Na|0,D|0,Ma|0,La|0)|0;Ja=oe(La|0,D|0,Ka|0,Ja|0)|0;Ha=oe(Ja|0,D|0,Ia|0,Ha|0)|0;Fa=oe(Ha|0,D|0,Ga|0,Fa|0)|0;Da=oe(Fa|0,D|0,Ea|0,Da|0)|0;Ba=oe(Da|0,D|0,Ca|0,Ba|0)|0;za=oe(Ba|0,D|0,Aa|0,za|0)|0;e=oe(za|0,D|0,N|0,e|0)|0;e=oe(e|0,D|0,ya|0,j|0)|0;N=D;j=Pd(ya|0,j|0,26)|0;j=le(f|0,fa|0,j|0,D|0)|0;fa=oe(i|0,ea|0,33554432,0)|0;fa=Dd(fa|0,D|0,26)|0;f=D;ua=oe(xa|0,wa|0,va|0,ua|0)|0;sa=oe(ua|0,D|0,ta|0,sa|0)|0;qa=oe(sa|0,D|0,ra|0,qa|0)|0;oa=oe(qa|0,D|0,pa|0,oa|0)|0;ma=oe(oa|0,D|0,na|0,ma|0)|0;ka=oe(ma|0,D|0,la|0,ka|0)|0;ia=oe(ka|0,D|0,ja|0,ia|0)|0;ga=oe(ia|0,D|0,ha|0,ga|0)|0;h=oe(ga|0,D|0,L|0,h|0)|0;h=oe(h|0,D|0,fa|0,f|0)|0;L=D;f=Pd(fa|0,f|0,26)|0;f=le(i|0,ea|0,f|0,D|0)|0;ea=oe(e|0,N|0,16777216,0)|0;ea=Dd(ea|0,D|0,25)|0;i=D;b=oe(ea|0,i|0,r|0,b|0)|0;r=D;i=Pd(ea|0,i|0,25)|0;i=le(e|0,N|0,i|0,D|0)|0;N=oe(h|0,L|0,16777216,0)|0;N=Dd(N|0,D|0,25)|0;e=D;aa=oe(da|0,ca|0,ba|0,aa|0)|0;_=oe(aa|0,D|0,$|0,_|0)|0;Y=oe(_|0,D|0,Z|0,Y|0)|0;W=oe(Y|0,D|0,X|0,W|0)|0;U=oe(W|0,D|0,V|0,U|0)|0;S=oe(U|0,D|0,T|0,S|0)|0;Q=oe(S|0,D|0,R|0,Q|0)|0;O=oe(Q|0,D|0,P|0,O|0)|0;d=oe(O|0,D|0,q|0,d|0)|0;d=oe(d|0,D|0,N|0,e|0)|0;q=D;e=Pd(N|0,e|0,25)|0;e=le(h|0,L|0,e|0,D|0)|0;L=oe(b|0,r|0,33554432,0)|0;L=Dd(L|0,D|0,26)|0;h=D;g=oe(M|0,g|0,L|0,h|0)|0;h=Pd(L|0,h|0,26)|0;h=le(b|0,r|0,h|0,D|0)|0;r=oe(d|0,q|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;b=D;H=oe(K|0,J|0,I|0,H|0)|0;F=oe(H|0,D|0,G|0,F|0)|0;C=oe(F|0,D|0,E|0,C|0)|0;A=oe(C|0,D|0,B|0,A|0)|0;y=oe(A|0,D|0,z|0,y|0)|0;w=oe(y|0,D|0,x|0,w|0)|0;u=oe(w|0,D|0,v|0,u|0)|0;s=oe(u|0,D|0,t|0,s|0)|0;l=oe(s|0,D|0,o|0,l|0)|0;l=oe(l|0,D|0,r|0,b|0)|0;o=D;b=Pd(r|0,b|0,26)|0;b=le(d|0,q|0,b|0,D|0)|0;q=oe(l|0,o|0,16777216,0)|0;q=Dd(q|0,D|0,25)|0;d=D;r=Ed(q|0,d|0,19,0)|0;n=oe(r|0,D|0,m|0,n|0)|0;m=D;d=Pd(q|0,d|0,25)|0;d=le(l|0,o|0,d|0,D|0)|0;o=oe(n|0,m|0,33554432,0)|0;o=Dd(o|0,D|0,26)|0;l=D;k=oe(p|0,k|0,o|0,l|0)|0;l=Pd(o|0,l|0,26)|0;l=le(n|0,m|0,l|0,D|0)|0;c[a>>2]=l;c[a+4>>2]=k;c[a+8>>2]=j;c[a+12>>2]=i;c[a+16>>2]=h;c[a+20>>2]=g;c[a+24>>2]=f;c[a+28>>2]=e;c[a+32>>2]=b;c[a+36>>2]=d;return}function qa(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0;l=c[b>>2]|0;n=c[b+4>>2]|0;k=c[b+8>>2]|0;f=c[b+12>>2]|0;u=c[b+16>>2]|0;t=c[b+20>>2]|0;g=c[b+24>>2]|0;v=c[b+28>>2]|0;s=c[b+32>>2]|0;q=c[b+36>>2]|0;cb=Ed(l|0,((l|0)<0)<<31>>31|0,l|0,((l|0)<0)<<31>>31|0)|0;bb=D;o=((l<<1|0)<0)<<31>>31;Ua=Ed(l<<1|0,o|0,n|0,((n|0)<0)<<31>>31|0)|0;Ta=D;Oa=Ed(k|0,((k|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Na=D;Ea=Ed(f|0,((f|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Da=D;sa=Ed(u|0,((u|0)<0)<<31>>31|0,l<<1|0,o|0)|0;ra=D;ia=Ed(t|0,((t|0)<0)<<31>>31|0,l<<1|0,o|0)|0;ha=D;_=Ed(g|0,((g|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Z=D;Q=Ed(v|0,((v|0)<0)<<31>>31|0,l<<1|0,o|0)|0;P=D;G=Ed(s|0,((s|0)<0)<<31>>31|0,l<<1|0,o|0)|0;F=D;o=Ed(q|0,((q|0)<0)<<31>>31|0,l<<1|0,o|0)|0;l=D;p=((n<<1|0)<0)<<31>>31;Ma=Ed(n<<1|0,p|0,n|0,((n|0)<0)<<31>>31|0)|0;La=D;Ca=Ed(n<<1|0,p|0,k|0,((k|0)<0)<<31>>31|0)|0;Ba=D;w=((f<<1|0)<0)<<31>>31;wa=Ed(f<<1|0,w|0,n<<1|0,p|0)|0;va=D;ma=Ed(u|0,((u|0)<0)<<31>>31|0,n<<1|0,p|0)|0;la=D;aa=Ed(t<<1|0,((t<<1|0)<0)<<31>>31|0,n<<1|0,p|0)|0;$=D;S=Ed(g|0,((g|0)<0)<<31>>31|0,n<<1|0,p|0)|0;R=D;I=Ed(v<<1|0,((v<<1|0)<0)<<31>>31|0,n<<1|0,p|0)|0;H=D;m=Ed(s|0,((s|0)<0)<<31>>31|0,n<<1|0,p|0)|0;r=D;b=((q*38|0)<0)<<31>>31;p=Ed(q*38|0,b|0,n<<1|0,p|0)|0;n=D;ua=Ed(k|0,((k|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;ta=D;ka=Ed(k<<1|0,((k<<1|0)<0)<<31>>31|0,f|0,((f|0)<0)<<31>>31|0)|0;ja=D;ca=Ed(u|0,((u|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;ba=D;W=Ed(t|0,((t|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;V=D;O=Ed(g|0,((g|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;N=D;z=Ed(v|0,((v|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;y=D;Y=((s*19|0)<0)<<31>>31;Ya=Ed(s*19|0,Y|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;Xa=D;k=Ed(q*38|0,b|0,k|0,((k|0)<0)<<31>>31|0)|0;j=D;ea=Ed(f<<1|0,w|0,f|0,((f|0)<0)<<31>>31|0)|0;da=D;U=Ed(f<<1|0,w|0,u|0,((u|0)<0)<<31>>31|0)|0;T=D;K=Ed(t<<1|0,((t<<1|0)<0)<<31>>31|0,f<<1|0,w|0)|0;J=D;E=Ed(g|0,((g|0)<0)<<31>>31|0,f<<1|0,w|0)|0;C=D;qa=((v*38|0)<0)<<31>>31;_a=Ed(v*38|0,qa|0,f<<1|0,w|0)|0;Za=D;Qa=Ed(s*19|0,Y|0,f<<1|0,w|0)|0;Pa=D;w=Ed(q*38|0,b|0,f<<1|0,w|0)|0;f=D;M=Ed(u|0,((u|0)<0)<<31>>31|0,u|0,((u|0)<0)<<31>>31|0)|0;L=D;B=Ed(u<<1|0,((u<<1|0)<0)<<31>>31|0,t|0,((t|0)<0)<<31>>31|0)|0;A=D;ab=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,u<<1|0,((u<<1|0)<0)<<31>>31|0)|0;$a=D;Sa=Ed(v*38|0,qa|0,u|0,((u|0)<0)<<31>>31|0)|0;Ra=D;Ga=Ed(s*19|0,Y|0,u<<1|0,((u<<1|0)<0)<<31>>31|0)|0;Fa=D;u=Ed(q*38|0,b|0,u|0,((u|0)<0)<<31>>31|0)|0;e=D;eb=Ed(t*38|0,((t*38|0)<0)<<31>>31|0,t|0,((t|0)<0)<<31>>31|0)|0;db=D;Wa=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,t<<1|0,((t<<1|0)<0)<<31>>31|0)|0;Va=D;Ia=Ed(v*38|0,qa|0,t<<1|0,((t<<1|0)<0)<<31>>31|0)|0;Ha=D;ya=Ed(s*19|0,Y|0,t<<1|0,((t<<1|0)<0)<<31>>31|0)|0;xa=D;t=Ed(q*38|0,b|0,t<<1|0,((t<<1|0)<0)<<31>>31|0)|0;d=D;Ka=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;Ja=D;Aa=Ed(v*38|0,qa|0,g|0,((g|0)<0)<<31>>31|0)|0;za=D;oa=Ed(s*19|0,Y|0,g<<1|0,((g<<1|0)<0)<<31>>31|0)|0;na=D;g=Ed(q*38|0,b|0,g|0,((g|0)<0)<<31>>31|0)|0;x=D;qa=Ed(v*38|0,qa|0,v|0,((v|0)<0)<<31>>31|0)|0;pa=D;ga=Ed(s*19|0,Y|0,v<<1|0,((v<<1|0)<0)<<31>>31|0)|0;fa=D;v=Ed(q*38|0,b|0,v<<1|0,((v<<1|0)<0)<<31>>31|0)|0;i=D;Y=Ed(s*19|0,Y|0,s|0,((s|0)<0)<<31>>31|0)|0;X=D;s=Ed(q*38|0,b|0,s|0,((s|0)<0)<<31>>31|0)|0;h=D;q=Ed(q*38|0,b|0,q|0,((q|0)<0)<<31>>31|0)|0;b=D;bb=oe(eb|0,db|0,cb|0,bb|0)|0;$a=oe(bb|0,D|0,ab|0,$a|0)|0;Za=oe($a|0,D|0,_a|0,Za|0)|0;Xa=oe(Za|0,D|0,Ya|0,Xa|0)|0;n=oe(Xa|0,D|0,p|0,n|0)|0;p=D;Ta=oe(Wa|0,Va|0,Ua|0,Ta|0)|0;Ra=oe(Ta|0,D|0,Sa|0,Ra|0)|0;Pa=oe(Ra|0,D|0,Qa|0,Pa|0)|0;j=oe(Pa|0,D|0,k|0,j|0)|0;k=D;La=oe(Oa|0,Na|0,Ma|0,La|0)|0;Ja=oe(La|0,D|0,Ka|0,Ja|0)|0;Ha=oe(Ja|0,D|0,Ia|0,Ha|0)|0;Fa=oe(Ha|0,D|0,Ga|0,Fa|0)|0;f=oe(Fa|0,D|0,w|0,f|0)|0;w=D;Ba=oe(Ea|0,Da|0,Ca|0,Ba|0)|0;za=oe(Ba|0,D|0,Aa|0,za|0)|0;xa=oe(za|0,D|0,ya|0,xa|0)|0;e=oe(xa|0,D|0,u|0,e|0)|0;u=D;ta=oe(wa|0,va|0,ua|0,ta|0)|0;ra=oe(ta|0,D|0,sa|0,ra|0)|0;pa=oe(ra|0,D|0,qa|0,pa|0)|0;na=oe(pa|0,D|0,oa|0,na|0)|0;d=oe(na|0,D|0,t|0,d|0)|0;t=D;ja=oe(ma|0,la|0,ka|0,ja|0)|0;ha=oe(ja|0,D|0,ia|0,ha|0)|0;fa=oe(ha|0,D|0,ga|0,fa|0)|0;x=oe(fa|0,D|0,g|0,x|0)|0;g=D;ba=oe(ea|0,da|0,ca|0,ba|0)|0;$=oe(ba|0,D|0,aa|0,$|0)|0;Z=oe($|0,D|0,_|0,Z|0)|0;X=oe(Z|0,D|0,Y|0,X|0)|0;i=oe(X|0,D|0,v|0,i|0)|0;v=D;T=oe(W|0,V|0,U|0,T|0)|0;R=oe(T|0,D|0,S|0,R|0)|0;P=oe(R|0,D|0,Q|0,P|0)|0;h=oe(P|0,D|0,s|0,h|0)|0;s=D;L=oe(O|0,N|0,M|0,L|0)|0;J=oe(L|0,D|0,K|0,J|0)|0;H=oe(J|0,D|0,I|0,H|0)|0;F=oe(H|0,D|0,G|0,F|0)|0;b=oe(F|0,D|0,q|0,b|0)|0;q=D;A=oe(E|0,C|0,B|0,A|0)|0;y=oe(A|0,D|0,z|0,y|0)|0;r=oe(y|0,D|0,m|0,r|0)|0;l=oe(r|0,D|0,o|0,l|0)|0;o=D;p=Pd(n|0,p|0,1)|0;n=D;k=Pd(j|0,k|0,1)|0;j=D;w=Pd(f|0,w|0,1)|0;f=D;u=Pd(e|0,u|0,1)|0;e=D;t=Pd(d|0,t|0,1)|0;d=D;g=Pd(x|0,g|0,1)|0;x=D;v=Pd(i|0,v|0,1)|0;i=D;s=Pd(h|0,s|0,1)|0;h=D;q=Pd(b|0,q|0,1)|0;b=D;o=Pd(l|0,o|0,1)|0;l=D;r=oe(p|0,n|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;m=D;j=oe(r|0,m|0,k|0,j|0)|0;k=D;m=Pd(r|0,m|0,26)|0;m=le(p|0,n|0,m|0,D|0)|0;n=D;p=oe(t|0,d|0,33554432,0)|0;p=Dd(p|0,D|0,26)|0;r=D;x=oe(p|0,r|0,g|0,x|0)|0;g=D;r=Pd(p|0,r|0,26)|0;r=le(t|0,d|0,r|0,D|0)|0;d=D;t=oe(j|0,k|0,16777216,0)|0;t=Dd(t|0,D|0,25)|0;p=D;f=oe(t|0,p|0,w|0,f|0)|0;w=D;p=Pd(t|0,p|0,25)|0;p=le(j|0,k|0,p|0,D|0)|0;k=D;j=oe(x|0,g|0,16777216,0)|0;j=Dd(j|0,D|0,25)|0;t=D;i=oe(j|0,t|0,v|0,i|0)|0;v=D;t=Pd(j|0,t|0,25)|0;t=le(x|0,g|0,t|0,D|0)|0;g=D;x=oe(f|0,w|0,33554432,0)|0;x=Dd(x|0,D|0,26)|0;j=D;e=oe(x|0,j|0,u|0,e|0)|0;u=D;j=Pd(x|0,j|0,26)|0;j=le(f|0,w|0,j|0,D|0)|0;w=oe(i|0,v|0,33554432,0)|0;w=Dd(w|0,D|0,26)|0;f=D;h=oe(w|0,f|0,s|0,h|0)|0;s=D;f=Pd(w|0,f|0,26)|0;f=le(i|0,v|0,f|0,D|0)|0;v=oe(e|0,u|0,16777216,0)|0;v=Dd(v|0,D|0,25)|0;i=D;d=oe(v|0,i|0,r|0,d|0)|0;r=D;i=Pd(v|0,i|0,25)|0;i=le(e|0,u|0,i|0,D|0)|0;u=oe(h|0,s|0,16777216,0)|0;u=Dd(u|0,D|0,25)|0;e=D;b=oe(u|0,e|0,q|0,b|0)|0;q=D;e=Pd(u|0,e|0,25)|0;e=le(h|0,s|0,e|0,D|0)|0;s=oe(d|0,r|0,33554432,0)|0;s=Dd(s|0,D|0,26)|0;h=D;g=oe(t|0,g|0,s|0,h|0)|0;h=Pd(s|0,h|0,26)|0;h=le(d|0,r|0,h|0,D|0)|0;r=oe(b|0,q|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;d=D;l=oe(r|0,d|0,o|0,l|0)|0;o=D;d=Pd(r|0,d|0,26)|0;d=le(b|0,q|0,d|0,D|0)|0;q=oe(l|0,o|0,16777216,0)|0;q=Dd(q|0,D|0,25)|0;b=D;r=Ed(q|0,b|0,19,0)|0;n=oe(r|0,D|0,m|0,n|0)|0;m=D;b=Pd(q|0,b|0,25)|0;b=le(l|0,o|0,b|0,D|0)|0;o=oe(n|0,m|0,33554432,0)|0;o=Dd(o|0,D|0,26)|0;l=D;k=oe(p|0,k|0,o|0,l|0)|0;l=Pd(o|0,l|0,26)|0;l=le(n|0,m|0,l|0,D|0)|0;c[a>>2]=l;c[a+4>>2]=k;c[a+8>>2]=j;c[a+12>>2]=i;c[a+16>>2]=h;c[a+20>>2]=g;c[a+24>>2]=f;c[a+28>>2]=e;c[a+32>>2]=d;c[a+36>>2]=b;return}function ra(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0;l=c[b>>2]|0;p=c[b+4>>2]|0;k=c[b+8>>2]|0;f=c[b+12>>2]|0;C=c[b+16>>2]|0;d=c[b+20>>2]|0;g=c[b+24>>2]|0;O=c[b+28>>2]|0;A=c[b+32>>2]|0;q=c[b+36>>2]|0;cb=Ed(l|0,((l|0)<0)<<31>>31|0,l|0,((l|0)<0)<<31>>31|0)|0;bb=D;o=((l<<1|0)<0)<<31>>31;Ia=Ed(l<<1|0,o|0,p|0,((p|0)<0)<<31>>31|0)|0;Ha=D;Wa=Ed(k|0,((k|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Va=D;Ua=Ed(f|0,((f|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Ta=D;Oa=Ed(C|0,((C|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Na=D;ya=Ed(d|0,((d|0)<0)<<31>>31|0,l<<1|0,o|0)|0;xa=D;ga=Ed(g|0,((g|0)<0)<<31>>31|0,l<<1|0,o|0)|0;fa=D;R=Ed(O|0,((O|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Q=D;F=Ed(A|0,((A|0)<0)<<31>>31|0,l<<1|0,o|0)|0;E=D;o=Ed(q|0,((q|0)<0)<<31>>31|0,l<<1|0,o|0)|0;l=D;n=((p<<1|0)<0)<<31>>31;ta=Ed(p<<1|0,n|0,p|0,((p|0)<0)<<31>>31|0)|0;ua=D;ba=Ed(p<<1|0,n|0,k|0,((k|0)<0)<<31>>31|0)|0;ca=D;P=((f<<1|0)<0)<<31>>31;Sa=Ed(f<<1|0,P|0,p<<1|0,n|0)|0;Ra=D;Ca=Ed(C|0,((C|0)<0)<<31>>31|0,p<<1|0,n|0)|0;Ba=D;ia=Ed(d<<1|0,((d<<1|0)<0)<<31>>31|0,p<<1|0,n|0)|0;ha=D;T=Ed(g|0,((g|0)<0)<<31>>31|0,p<<1|0,n|0)|0;S=D;H=Ed(O<<1|0,((O<<1|0)<0)<<31>>31|0,p<<1|0,n|0)|0;G=D;t=Ed(A|0,((A|0)<0)<<31>>31|0,p<<1|0,n|0)|0;s=D;b=((q*38|0)<0)<<31>>31;n=Ed(q*38|0,b|0,p<<1|0,n|0)|0;p=D;Qa=Ed(k|0,((k|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;Pa=D;Aa=Ed(k<<1|0,((k<<1|0)<0)<<31>>31|0,f|0,((f|0)<0)<<31>>31|0)|0;za=D;ka=Ed(C|0,((C|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;ja=D;X=Ed(d|0,((d|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;W=D;N=Ed(g|0,((g|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;M=D;v=Ed(O|0,((O|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;u=D;ea=((A*19|0)<0)<<31>>31;Ya=Ed(A*19|0,ea|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;Xa=D;k=Ed(q*38|0,b|0,k|0,((k|0)<0)<<31>>31|0)|0;j=D;ma=Ed(f<<1|0,P|0,f|0,((f|0)<0)<<31>>31|0)|0;la=D;V=Ed(f<<1|0,P|0,C|0,((C|0)<0)<<31>>31|0)|0;U=D;J=Ed(d<<1|0,((d<<1|0)<0)<<31>>31|0,f<<1|0,P|0)|0;I=D;z=Ed(g|0,((g|0)<0)<<31>>31|0,f<<1|0,P|0)|0;y=D;Ma=((O*38|0)<0)<<31>>31;_a=Ed(O*38|0,Ma|0,f<<1|0,P|0)|0;Za=D;Ea=Ed(A*19|0,ea|0,f<<1|0,P|0)|0;Da=D;P=Ed(q*38|0,b|0,f<<1|0,P|0)|0;f=D;L=Ed(C|0,((C|0)<0)<<31>>31|0,C|0,((C|0)<0)<<31>>31|0)|0;K=D;x=Ed(C<<1|0,((C<<1|0)<0)<<31>>31|0,d|0,((d|0)<0)<<31>>31|0)|0;w=D;ab=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,C<<1|0,((C<<1|0)<0)<<31>>31|0)|0;$a=D;Ga=Ed(O*38|0,Ma|0,C|0,((C|0)<0)<<31>>31|0)|0;Fa=D;oa=Ed(A*19|0,ea|0,C<<1|0,((C<<1|0)<0)<<31>>31|0)|0;na=D;C=Ed(q*38|0,b|0,C|0,((C|0)<0)<<31>>31|0)|0;e=D;eb=Ed(d*38|0,((d*38|0)<0)<<31>>31|0,d|0,((d|0)<0)<<31>>31|0)|0;db=D;Ka=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,d<<1|0,((d<<1|0)<0)<<31>>31|0)|0;Ja=D;qa=Ed(O*38|0,Ma|0,d<<1|0,((d<<1|0)<0)<<31>>31|0)|0;pa=D;_=Ed(A*19|0,ea|0,d<<1|0,((d<<1|0)<0)<<31>>31|0)|0;Z=D;d=Ed(q*38|0,b|0,d<<1|0,((d<<1|0)<0)<<31>>31|0)|0;B=D;sa=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;ra=D;aa=Ed(O*38|0,Ma|0,g|0,((g|0)<0)<<31>>31|0)|0;$=D;m=Ed(A*19|0,ea|0,g<<1|0,((g<<1|0)<0)<<31>>31|0)|0;r=D;g=Ed(q*38|0,b|0,g|0,((g|0)<0)<<31>>31|0)|0;Y=D;Ma=Ed(O*38|0,Ma|0,O|0,((O|0)<0)<<31>>31|0)|0;La=D;wa=Ed(A*19|0,ea|0,O<<1|0,((O<<1|0)<0)<<31>>31|0)|0;va=D;O=Ed(q*38|0,b|0,O<<1|0,((O<<1|0)<0)<<31>>31|0)|0;i=D;ea=Ed(A*19|0,ea|0,A|0,((A|0)<0)<<31>>31|0)|0;da=D;A=Ed(q*38|0,b|0,A|0,((A|0)<0)<<31>>31|0)|0;h=D;q=Ed(q*38|0,b|0,q|0,((q|0)<0)<<31>>31|0)|0;b=D;bb=oe(eb|0,db|0,cb|0,bb|0)|0;$a=oe(bb|0,D|0,ab|0,$a|0)|0;Za=oe($a|0,D|0,_a|0,Za|0)|0;Xa=oe(Za|0,D|0,Ya|0,Xa|0)|0;p=oe(Xa|0,D|0,n|0,p|0)|0;n=D;ua=oe(Wa|0,Va|0,ta|0,ua|0)|0;ta=D;ca=oe(Ua|0,Ta|0,ba|0,ca|0)|0;ba=D;Pa=oe(Sa|0,Ra|0,Qa|0,Pa|0)|0;Na=oe(Pa|0,D|0,Oa|0,Na|0)|0;La=oe(Na|0,D|0,Ma|0,La|0)|0;r=oe(La|0,D|0,m|0,r|0)|0;B=oe(r|0,D|0,d|0,B|0)|0;d=D;r=oe(p|0,n|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;m=D;Ha=oe(Ka|0,Ja|0,Ia|0,Ha|0)|0;Fa=oe(Ha|0,D|0,Ga|0,Fa|0)|0;Da=oe(Fa|0,D|0,Ea|0,Da|0)|0;j=oe(Da|0,D|0,k|0,j|0)|0;j=oe(j|0,D|0,r|0,m|0)|0;k=D;m=Pd(r|0,m|0,26)|0;m=le(p|0,n|0,m|0,D|0)|0;n=D;p=oe(B|0,d|0,33554432,0)|0;p=Dd(p|0,D|0,26)|0;r=D;za=oe(Ca|0,Ba|0,Aa|0,za|0)|0;xa=oe(za|0,D|0,ya|0,xa|0)|0;va=oe(xa|0,D|0,wa|0,va|0)|0;Y=oe(va|0,D|0,g|0,Y|0)|0;Y=oe(Y|0,D|0,p|0,r|0)|0;g=D;r=Pd(p|0,r|0,26)|0;r=le(B|0,d|0,r|0,D|0)|0;d=D;B=oe(j|0,k|0,16777216,0)|0;B=Dd(B|0,D|0,25)|0;p=D;ra=oe(ua|0,ta|0,sa|0,ra|0)|0;pa=oe(ra|0,D|0,qa|0,pa|0)|0;na=oe(pa|0,D|0,oa|0,na|0)|0;f=oe(na|0,D|0,P|0,f|0)|0;f=oe(f|0,D|0,B|0,p|0)|0;P=D;p=Pd(B|0,p|0,25)|0;p=le(j|0,k|0,p|0,D|0)|0;k=D;j=oe(Y|0,g|0,16777216,0)|0;j=Dd(j|0,D|0,25)|0;B=D;ja=oe(ma|0,la|0,ka|0,ja|0)|0;ha=oe(ja|0,D|0,ia|0,ha|0)|0;fa=oe(ha|0,D|0,ga|0,fa|0)|0;da=oe(fa|0,D|0,ea|0,da|0)|0;i=oe(da|0,D|0,O|0,i|0)|0;i=oe(i|0,D|0,j|0,B|0)|0;O=D;B=Pd(j|0,B|0,25)|0;B=le(Y|0,g|0,B|0,D|0)|0;g=D;Y=oe(f|0,P|0,33554432,0)|0;Y=Dd(Y|0,D|0,26)|0;j=D;$=oe(ca|0,ba|0,aa|0,$|0)|0;Z=oe($|0,D|0,_|0,Z|0)|0;e=oe(Z|0,D|0,C|0,e|0)|0;e=oe(e|0,D|0,Y|0,j|0)|0;C=D;j=Pd(Y|0,j|0,26)|0;j=le(f|0,P|0,j|0,D|0)|0;P=oe(i|0,O|0,33554432,0)|0;P=Dd(P|0,D|0,26)|0;f=D;U=oe(X|0,W|0,V|0,U|0)|0;S=oe(U|0,D|0,T|0,S|0)|0;Q=oe(S|0,D|0,R|0,Q|0)|0;h=oe(Q|0,D|0,A|0,h|0)|0;h=oe(h|0,D|0,P|0,f|0)|0;A=D;f=Pd(P|0,f|0,26)|0;f=le(i|0,O|0,f|0,D|0)|0;O=oe(e|0,C|0,16777216,0)|0;O=Dd(O|0,D|0,25)|0;i=D;d=oe(O|0,i|0,r|0,d|0)|0;r=D;i=Pd(O|0,i|0,25)|0;i=le(e|0,C|0,i|0,D|0)|0;C=oe(h|0,A|0,16777216,0)|0;C=Dd(C|0,D|0,25)|0;e=D;K=oe(N|0,M|0,L|0,K|0)|0;I=oe(K|0,D|0,J|0,I|0)|0;G=oe(I|0,D|0,H|0,G|0)|0;E=oe(G|0,D|0,F|0,E|0)|0;b=oe(E|0,D|0,q|0,b|0)|0;b=oe(b|0,D|0,C|0,e|0)|0;q=D;e=Pd(C|0,e|0,25)|0;e=le(h|0,A|0,e|0,D|0)|0;A=oe(d|0,r|0,33554432,0)|0;A=Dd(A|0,D|0,26)|0;h=D;g=oe(B|0,g|0,A|0,h|0)|0;h=Pd(A|0,h|0,26)|0;h=le(d|0,r|0,h|0,D|0)|0;r=oe(b|0,q|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;d=D;w=oe(z|0,y|0,x|0,w|0)|0;u=oe(w|0,D|0,v|0,u|0)|0;s=oe(u|0,D|0,t|0,s|0)|0;l=oe(s|0,D|0,o|0,l|0)|0;l=oe(l|0,D|0,r|0,d|0)|0;o=D;d=Pd(r|0,d|0,26)|0;d=le(b|0,q|0,d|0,D|0)|0;q=oe(l|0,o|0,16777216,0)|0;q=Dd(q|0,D|0,25)|0;b=D;r=Ed(q|0,b|0,19,0)|0;n=oe(r|0,D|0,m|0,n|0)|0;m=D;b=Pd(q|0,b|0,25)|0;b=le(l|0,o|0,b|0,D|0)|0;o=oe(n|0,m|0,33554432,0)|0;o=Dd(o|0,D|0,26)|0;l=D;k=oe(p|0,k|0,o|0,l|0)|0;l=Pd(o|0,l|0,26)|0;l=le(n|0,m|0,l|0,D|0)|0;c[a>>2]=l;c[a+4>>2]=k;c[a+8>>2]=j;c[a+12>>2]=i;c[a+16>>2]=h;c[a+20>>2]=g;c[a+24>>2]=f;c[a+28>>2]=e;c[a+32>>2]=d;c[a+36>>2]=b;return}function sa(b,c,e,f,g){b=b|0;c=c|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;n=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;p=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;h=d[g+8>>0]|d[g+8+1>>0]<<8|d[g+8+2>>0]<<16|d[g+8+3>>0]<<24;i=d[g+8+4>>0]|d[g+8+4+1>>0]<<8|d[g+8+4+2>>0]<<16|d[g+8+4+3>>0]<<24;f=Pd(e|0,f|0,56)|0;g=D;if((c+e+(0-(e&7))|0)==(c|0)){o=h^2037671283;l=i^1952801890;m=n^1886610805;k=p^1936682341;j=h^1852075885;s=i^1685025377;i=n^1852142177;h=p^1819895653}else{u=c;r=h^2037671283;l=i^1952801890;o=n^1886610805;m=p^1936682341;k=h^1852075885;j=i^1685025377;i=n^1852142177;h=p^1819895653;while(1){v=u;t=d[v>>0]|d[v+1>>0]<<8|d[v+2>>0]<<16|d[v+3>>0]<<24;v=d[v+4>>0]|d[v+4+1>>0]<<8|d[v+4+2>>0]<<16|d[v+4+3>>0]<<24;p=t^r;r=v^l;m=oe(o|0,m|0,k|0,j|0)|0;n=D;q=Pd(k|0,j|0,13)|0;s=D;x=Rd(k|0,j|0,51)|0;s=(s|D)^n;h=oe(p|0,r|0,i|0,h|0)|0;i=D;o=Pd(p|0,r|0,16)|0;j=D;k=Rd(p|0,r|0,48)|0;j=(j|D)^i;n=oe((o|k)^h|0,j|0,n|0,m|0)|0;r=D;l=Pd((o|k)^h|0,j|0,21)|0;p=D;j=Rd((o|k)^h|0,j|0,43)|0;p=(p|D)^r;i=oe(h|0,i|0,(q|x)^m|0,s|0)|0;h=D;k=Pd((q|x)^m|0,s|0,17)|0;o=D;s=Rd((q|x)^m|0,s|0,47)|0;o=h^(o|D);r=oe(n|0,r|0,i^(k|s)|0,o|0)|0;m=D;x=Pd(i^(k|s)|0,o|0,13)|0;q=D;o=Rd(i^(k|s)|0,o|0,51)|0;q=(q|D)^m;i=oe((l|j)^n|0,p|0,h|0,i|0)|0;h=D;s=Pd((l|j)^n|0,p|0,16)|0;k=D;p=Rd((l|j)^n|0,p|0,48)|0;k=(k|D)^h;m=oe((s|p)^i|0,k|0,m|0,r|0)|0;n=D;j=Pd((s|p)^i|0,k|0,21)|0;l=D;k=Rd((s|p)^i|0,k|0,43)|0;l=(l|D)^n;h=oe(i|0,h|0,(x|o)^r|0,q|0)|0;i=D;p=Pd((x|o)^r|0,q|0,17)|0;s=D;q=Rd((x|o)^r|0,q|0,47)|0;s=(s|D)^i;u=u+8|0;if((u|0)==(c+e+(0-(e&7))|0)){c=c+e+(0-(e&7))|0;o=(j|k)^m;m=m^t;k=n^v;j=(p|q)^h;break}else{r=(j|k)^m;o=m^t;m=n^v;k=(p|q)^h;j=s}}}switch(e&7){case 7:{f=Pd(d[c+6>>0]|0|0,0,48)|0|f;g=D|g;w=5;break}case 6:{w=5;break}case 5:{w=6;break}case 4:{w=7;break}case 3:{w=8;break}case 2:{w=9;break}case 1:{w=10;break}default:{}}if((w|0)==5){x=Pd(d[c+5>>0]|0|0,0,40)|0;g=D|g;f=x|f;w=6}if((w|0)==6){g=d[c+4>>0]|0|g;w=7}if((w|0)==7){x=Pd(d[c+3>>0]|0|0,0,24)|0;f=x|f;g=D|g;w=8}if((w|0)==8){x=Pd(d[c+2>>0]|0|0,0,16)|0;f=x|f;g=D|g;w=9}if((w|0)==9){x=Pd(d[c+1>>0]|0|0,0,8)|0;f=x|f;g=D|g;w=10}if((w|0)==10)f=d[c>>0]|0|f;u=f^o;n=g^l;e=oe(m|0,k|0,j|0,s|0)|0;q=D;m=Pd(j|0,s|0,13)|0;r=D;p=Rd(j|0,s|0,51)|0;r=(r|D)^q;v=oe(u|0,n|0,i|0,h|0)|0;c=D;w=Pd(u|0,n|0,16)|0;x=D;n=Rd(u|0,n|0,48)|0;x=(x|D)^c;q=oe((w|n)^v|0,x|0,q|0,e|0)|0;u=D;o=Pd((w|n)^v|0,x|0,21)|0;t=D;x=Rd((w|n)^v|0,x|0,43)|0;t=(t|D)^u;c=oe(v|0,c|0,(m|p)^e|0,r|0)|0;v=D;n=Pd((m|p)^e|0,r|0,17)|0;w=D;r=Rd((m|p)^e|0,r|0,47)|0;w=v^(w|D);u=oe(q|0,u|0,c^(n|r)|0,w|0)|0;e=D;p=Pd(c^(n|r)|0,w|0,13)|0;s=D;w=Rd(c^(n|r)|0,w|0,51)|0;s=(s|D)^e;c=oe((o|x)^q|0,t|0,v|0,c|0)|0;v=D;r=Pd((o|x)^q|0,t|0,16)|0;n=D;t=Rd((o|x)^q|0,t|0,48)|0;n=(n|D)^v;e=oe((r|t)^c|0,n|0,e|0,u|0)|0;q=D;x=Pd((r|t)^c|0,n|0,21)|0;o=D;n=Rd((r|t)^c|0,n|0,43)|0;o=(o|D)^q;v=oe(c|0,v|0,(p|w)^u|0,s|0)|0;c=D;t=Pd((p|w)^u|0,s|0,17)|0;r=D;s=Rd((p|w)^u|0,s|0,47)|0;r=(r|D)^c;q=oe(e^f|0,q^g|0,(t|s)^v|0,r|0)|0;u=D;w=Pd((t|s)^v|0,r|0,13)|0;p=D;r=Rd((t|s)^v|0,r|0,51)|0;p=u^(p|D);v=oe((x|n)^e|0,o|0,c^255|0,v|0)|0;c=D;s=Pd((x|n)^e|0,o|0,16)|0;t=D;o=Rd((x|n)^e|0,o|0,48)|0;t=(t|D)^c;u=oe((s|o)^v|0,t|0,u|0,q|0)|0;e=D;n=Pd((s|o)^v|0,t|0,21)|0;x=D;t=Rd((s|o)^v|0,t|0,43)|0;x=(x|D)^e;c=oe(v|0,c|0,q^(w|r)|0,p|0)|0;v=D;o=Pd(q^(w|r)|0,p|0,17)|0;s=D;p=Rd(q^(w|r)|0,p|0,47)|0;s=(s|D)^v;e=oe(u|0,e|0,(o|p)^c|0,s|0)|0;r=D;w=Pd((o|p)^c|0,s|0,13)|0;q=D;s=Rd((o|p)^c|0,s|0,51)|0;q=(q|D)^r;c=oe((n|t)^u|0,x|0,v|0,c|0)|0;v=D;p=Pd((n|t)^u|0,x|0,16)|0;o=D;x=Rd((n|t)^u|0,x|0,48)|0;o=(o|D)^v;r=oe((p|x)^c|0,o|0,r|0,e|0)|0;u=D;t=Pd((p|x)^c|0,o|0,21)|0;n=D;o=Rd((p|x)^c|0,o|0,43)|0;n=(n|D)^u;v=oe(c|0,v|0,(w|s)^e|0,q|0)|0;c=D;x=Pd((w|s)^e|0,q|0,17)|0;p=D;q=Rd((w|s)^e|0,q|0,47)|0;p=(p|D)^c;u=oe(r|0,u|0,(x|q)^v|0,p|0)|0;e=D;s=Pd((x|q)^v|0,p|0,13)|0;w=D;p=Rd((x|q)^v|0,p|0,51)|0;w=(w|D)^e;v=oe((t|o)^r|0,n|0,c|0,v|0)|0;c=D;q=Pd((t|o)^r|0,n|0,16)|0;x=D;n=Rd((t|o)^r|0,n|0,48)|0;x=(x|D)^c;e=oe((q|n)^v|0,x|0,e|0,u|0)|0;r=D;o=Pd((q|n)^v|0,x|0,21)|0;t=D;x=Rd((q|n)^v|0,x|0,43)|0;t=(t|D)^r;c=oe(v|0,c|0,(s|p)^u|0,w|0)|0;v=D;n=Pd((s|p)^u|0,w|0,17)|0;q=D;w=Rd((s|p)^u|0,w|0,47)|0;q=(q|D)^v;r=oe(e|0,r|0,(n|w)^c|0,q|0)|0;u=D;p=Pd((n|w)^c|0,q|0,13)|0;s=D;q=Rd((n|w)^c|0,q|0,51)|0;u=(s|D)^u;c=oe((o|x)^e|0,t|0,v|0,c|0)|0;v=D;s=Pd((o|x)^e|0,t|0,16)|0;w=D;t=Rd((o|x)^e|0,t|0,48)|0;w=(w|D)^v;e=Pd((s|t)^c|0,w|0,21)|0;x=D;w=Rd((s|t)^c|0,w|0,43)|0;x=x|D;v=oe(c|0,v|0,(p|q)^r|0,u|0)|0;c=D;t=Pd((p|q)^r|0,u|0,17)|0;s=D;u=Rd((p|q)^r|0,u|0,47)|0;x=(s|D)^c^v^x;a[b>>0]=(t|u)^v^c^(e|w);a[b+1>>0]=((t|u)^v^c^(e|w))>>8;a[b+2>>0]=((t|u)^v^c^(e|w))>>16;a[b+3>>0]=((t|u)^v^c^(e|w))>>24;a[b+4>>0]=x;a[b+4+1>>0]=x>>8;a[b+4+2>>0]=x>>16;a[b+4+3>>0]=x>>24;return 0}function ta(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;if(!a)return;h=c[8495]|0;if((a+-8|0)>>>0<h>>>0)ba();b=c[a+-4>>2]|0;if((b&3|0)==1)ba();n=a+-8+(b&-8)|0;do if(!(b&1)){e=c[a+-8>>2]|0;if(!(b&3))return;k=a+-8+(0-e)|0;j=e+(b&-8)|0;if(k>>>0<h>>>0)ba();if((k|0)==(c[8496]|0)){a=c[n+4>>2]|0;if((a&3|0)!=3){q=k;f=j;break}c[8493]=j;c[n+4>>2]=a&-2;c[k+4>>2]=j|1;c[k+j>>2]=j;return}if(e>>>0<256){a=c[k+8>>2]|0;b=c[k+12>>2]|0;if((a|0)!=(34004+(e>>>3<<1<<2)|0)){if(a>>>0<h>>>0)ba();if((c[a+12>>2]|0)!=(k|0))ba()}if((b|0)==(a|0)){c[8491]=c[8491]&~(1<<(e>>>3));q=k;f=j;break}if((b|0)!=(34004+(e>>>3<<1<<2)|0)){if(b>>>0<h>>>0)ba();if((c[b+8>>2]|0)!=(k|0))ba();else d=b+8|0}else d=b+8|0;c[a+12>>2]=b;c[d>>2]=a;q=k;f=j;break}g=c[k+24>>2]|0;a=c[k+12>>2]|0;do if((a|0)==(k|0)){a=c[k+16+4>>2]|0;if(!a){a=c[k+16>>2]|0;if(!a){i=0;break}else e=k+16|0}else e=k+16+4|0;while(1){b=a+20|0;d=c[b>>2]|0;if(d|0){a=d;e=b;continue}b=a+16|0;d=c[b>>2]|0;if(!d)break;else{a=d;e=b}}if(e>>>0<h>>>0)ba();else{c[e>>2]=0;i=a;break}}else{b=c[k+8>>2]|0;if(b>>>0<h>>>0)ba();if((c[b+12>>2]|0)!=(k|0))ba();if((c[a+8>>2]|0)==(k|0)){c[b+12>>2]=a;c[a+8>>2]=b;i=a;break}else ba()}while(0);if(g){a=c[k+28>>2]|0;if((k|0)==(c[34268+(a<<2)>>2]|0)){c[34268+(a<<2)>>2]=i;if(!i){c[8492]=c[8492]&~(1<<a);q=k;f=j;break}}else{if(g>>>0<(c[8495]|0)>>>0)ba();if((c[g+16>>2]|0)==(k|0))c[g+16>>2]=i;else c[g+20>>2]=i;if(!i){q=k;f=j;break}}b=c[8495]|0;if(i>>>0<b>>>0)ba();c[i+24>>2]=g;a=c[k+16>>2]|0;do if(a|0)if(a>>>0<b>>>0)ba();else{c[i+16>>2]=a;c[a+24>>2]=i;break}while(0);a=c[k+16+4>>2]|0;if(a)if(a>>>0<(c[8495]|0)>>>0)ba();else{c[i+20>>2]=a;c[a+24>>2]=i;q=k;f=j;break}else{q=k;f=j}}else{q=k;f=j}}else{q=a+-8|0;f=b&-8}while(0);if(q>>>0>=n>>>0)ba();d=c[n+4>>2]|0;if(!(d&1))ba();if(!(d&2)){if((n|0)==(c[8497]|0)){p=(c[8494]|0)+f|0;c[8494]=p;c[8497]=q;c[q+4>>2]=p|1;if((q|0)!=(c[8496]|0))return;c[8496]=0;c[8493]=0;return}if((n|0)==(c[8496]|0)){p=(c[8493]|0)+f|0;c[8493]=p;c[8496]=q;c[q+4>>2]=p|1;c[q+p>>2]=p;return}f=(d&-8)+f|0;do if(d>>>0>=256){g=c[n+24>>2]|0;a=c[n+12>>2]|0;do if((a|0)==(n|0)){a=c[n+16+4>>2]|0;if(!a){a=c[n+16>>2]|0;if(!a){m=0;break}else e=n+16|0}else e=n+16+4|0;while(1){b=a+20|0;d=c[b>>2]|0;if(d|0){a=d;e=b;continue}b=a+16|0;d=c[b>>2]|0;if(!d)break;else{a=d;e=b}}if(e>>>0<(c[8495]|0)>>>0)ba();else{c[e>>2]=0;m=a;break}}else{b=c[n+8>>2]|0;if(b>>>0<(c[8495]|0)>>>0)ba();if((c[b+12>>2]|0)!=(n|0))ba();if((c[a+8>>2]|0)==(n|0)){c[b+12>>2]=a;c[a+8>>2]=b;m=a;break}else ba()}while(0);if(g|0){a=c[n+28>>2]|0;if((n|0)==(c[34268+(a<<2)>>2]|0)){c[34268+(a<<2)>>2]=m;if(!m){c[8492]=c[8492]&~(1<<a);break}}else{if(g>>>0<(c[8495]|0)>>>0)ba();if((c[g+16>>2]|0)==(n|0))c[g+16>>2]=m;else c[g+20>>2]=m;if(!m)break}b=c[8495]|0;if(m>>>0<b>>>0)ba();c[m+24>>2]=g;a=c[n+16>>2]|0;do if(a|0)if(a>>>0<b>>>0)ba();else{c[m+16>>2]=a;c[a+24>>2]=m;break}while(0);a=c[n+16+4>>2]|0;if(a|0)if(a>>>0<(c[8495]|0)>>>0)ba();else{c[m+20>>2]=a;c[a+24>>2]=m;break}}}else{a=c[n+8>>2]|0;b=c[n+12>>2]|0;if((a|0)!=(34004+(d>>>3<<1<<2)|0)){if(a>>>0<(c[8495]|0)>>>0)ba();if((c[a+12>>2]|0)!=(n|0))ba()}if((b|0)==(a|0)){c[8491]=c[8491]&~(1<<(d>>>3));break}if((b|0)!=(34004+(d>>>3<<1<<2)|0)){if(b>>>0<(c[8495]|0)>>>0)ba();if((c[b+8>>2]|0)!=(n|0))ba();else l=b+8|0}else l=b+8|0;c[a+12>>2]=b;c[l>>2]=a}while(0);c[q+4>>2]=f|1;c[q+f>>2]=f;if((q|0)==(c[8496]|0)){c[8493]=f;return}}else{c[n+4>>2]=d&-2;c[q+4>>2]=f|1;c[q+f>>2]=f}b=f>>>3;if(f>>>0<256){a=c[8491]|0;if(a&1<<b){a=c[34004+(b<<1<<2)+8>>2]|0;if(a>>>0<(c[8495]|0)>>>0)ba();else{o=a;p=34004+(b<<1<<2)+8|0}}else{c[8491]=a|1<<b;o=34004+(b<<1<<2)|0;p=34004+(b<<1<<2)+8|0}c[p>>2]=q;c[o+12>>2]=q;c[q+8>>2]=o;c[q+12>>2]=34004+(b<<1<<2);return}a=f>>>8;if(a)if(f>>>0>16777215)a=31;else{p=a<<((a+1048320|0)>>>16&8)<<(((a<<((a+1048320|0)>>>16&8))+520192|0)>>>16&4);a=14-(((a<<((a+1048320|0)>>>16&8))+520192|0)>>>16&4|(a+1048320|0)>>>16&8|(p+245760|0)>>>16&2)+(p<<((p+245760|0)>>>16&2)>>>15)|0;a=f>>>(a+7|0)&1|a<<1}else a=0;e=34268+(a<<2)|0;c[q+28>>2]=a;c[q+20>>2]=0;c[q+16>>2]=0;b=c[8492]|0;d=1<<a;do if(b&d){b=f<<((a|0)==31?0:25-(a>>>1)|0);e=c[e>>2]|0;while(1){if((c[e+4>>2]&-8|0)==(f|0)){a=130;break}d=e+16+(b>>>31<<2)|0;a=c[d>>2]|0;if(!a){a=127;break}else{b=b<<1;e=a}}if((a|0)==127)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[d>>2]=q;c[q+24>>2]=e;c[q+12>>2]=q;c[q+8>>2]=q;break}else if((a|0)==130){a=e+8|0;b=c[a>>2]|0;p=c[8495]|0;if(b>>>0>=p>>>0&e>>>0>=p>>>0){c[b+12>>2]=q;c[a>>2]=q;c[q+8>>2]=b;c[q+12>>2]=e;c[q+24>>2]=0;break}else ba()}}else{c[8492]=b|d;c[e>>2]=q;c[q+24>>2]=e;c[q+12>>2]=q;c[q+8>>2]=q}while(0);q=(c[8499]|0)+-1|0;c[8499]=q;if(!q)a=34420;else return;while(1){a=c[a>>2]|0;if(!a)break;else a=a+8|0}c[8499]=-1;return}function ua(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;d=c[a+4>>2]|0;do if(!(d&1)){l=c[a>>2]|0;if(!(d&3))return;j=c[8495]|0;if((a+(0-l)|0)>>>0<j>>>0)ba();if((a+(0-l)|0)==(c[8496]|0)){d=c[a+b+4>>2]|0;if((d&3|0)!=3){q=a+(0-l)|0;h=l+b|0;break}c[8493]=l+b;c[a+b+4>>2]=d&-2;c[a+(0-l)+4>>2]=l+b|1;c[a+(0-l)+(l+b)>>2]=l+b;return}if(l>>>0<256){d=c[a+(0-l)+8>>2]|0;e=c[a+(0-l)+12>>2]|0;if((d|0)!=(34004+(l>>>3<<1<<2)|0)){if(d>>>0<j>>>0)ba();if((c[d+12>>2]|0)!=(a+(0-l)|0))ba()}if((e|0)==(d|0)){c[8491]=c[8491]&~(1<<(l>>>3));q=a+(0-l)|0;h=l+b|0;break}if((e|0)!=(34004+(l>>>3<<1<<2)|0)){if(e>>>0<j>>>0)ba();if((c[e+8>>2]|0)!=(a+(0-l)|0))ba();else f=e+8|0}else f=e+8|0;c[d+12>>2]=e;c[f>>2]=d;q=a+(0-l)|0;h=l+b|0;break}i=c[a+(0-l)+24>>2]|0;d=c[a+(0-l)+12>>2]|0;do if((d|0)==(a+(0-l)|0)){e=a+(0-l)+16|0;d=c[e+4>>2]|0;if(!d){d=c[e>>2]|0;if(!d){k=0;break}}else e=e+4|0;while(1){f=d+20|0;g=c[f>>2]|0;if(g|0){d=g;e=f;continue}f=d+16|0;g=c[f>>2]|0;if(!g)break;else{d=g;e=f}}if(e>>>0<j>>>0)ba();else{c[e>>2]=0;k=d;break}}else{e=c[a+(0-l)+8>>2]|0;if(e>>>0<j>>>0)ba();if((c[e+12>>2]|0)!=(a+(0-l)|0))ba();if((c[d+8>>2]|0)==(a+(0-l)|0)){c[e+12>>2]=d;c[d+8>>2]=e;k=d;break}else ba()}while(0);if(i){d=c[a+(0-l)+28>>2]|0;if((a+(0-l)|0)==(c[34268+(d<<2)>>2]|0)){c[34268+(d<<2)>>2]=k;if(!k){c[8492]=c[8492]&~(1<<d);q=a+(0-l)|0;h=l+b|0;break}}else{if(i>>>0<(c[8495]|0)>>>0)ba();if((c[i+16>>2]|0)==(a+(0-l)|0))c[i+16>>2]=k;else c[i+20>>2]=k;if(!k){q=a+(0-l)|0;h=l+b|0;break}}e=c[8495]|0;if(k>>>0<e>>>0)ba();c[k+24>>2]=i;d=c[a+(0-l)+16>>2]|0;do if(d|0)if(d>>>0<e>>>0)ba();else{c[k+16>>2]=d;c[d+24>>2]=k;break}while(0);d=c[a+(0-l)+16+4>>2]|0;if(d)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[k+20>>2]=d;c[d+24>>2]=k;q=a+(0-l)|0;h=l+b|0;break}else{q=a+(0-l)|0;h=l+b|0}}else{q=a+(0-l)|0;h=l+b|0}}else{q=a;h=b}while(0);j=c[8495]|0;if((a+b|0)>>>0<j>>>0)ba();f=c[a+b+4>>2]|0;if(!(f&2)){if((a+b|0)==(c[8497]|0)){p=(c[8494]|0)+h|0;c[8494]=p;c[8497]=q;c[q+4>>2]=p|1;if((q|0)!=(c[8496]|0))return;c[8496]=0;c[8493]=0;return}if((a+b|0)==(c[8496]|0)){p=(c[8493]|0)+h|0;c[8493]=p;c[8496]=q;c[q+4>>2]=p|1;c[q+p>>2]=p;return}h=(f&-8)+h|0;do if(f>>>0>=256){i=c[a+b+24>>2]|0;d=c[a+b+12>>2]|0;do if((d|0)==(a+b|0)){d=c[a+b+16+4>>2]|0;if(!d){d=c[a+b+16>>2]|0;if(!d){n=0;break}else g=a+b+16|0}else g=a+b+16+4|0;while(1){e=d+20|0;f=c[e>>2]|0;if(f|0){d=f;g=e;continue}e=d+16|0;f=c[e>>2]|0;if(!f)break;else{d=f;g=e}}if(g>>>0<j>>>0)ba();else{c[g>>2]=0;n=d;break}}else{e=c[a+b+8>>2]|0;if(e>>>0<j>>>0)ba();if((c[e+12>>2]|0)!=(a+b|0))ba();if((c[d+8>>2]|0)==(a+b|0)){c[e+12>>2]=d;c[d+8>>2]=e;n=d;break}else ba()}while(0);if(i|0){d=c[a+b+28>>2]|0;if((a+b|0)==(c[34268+(d<<2)>>2]|0)){c[34268+(d<<2)>>2]=n;if(!n){c[8492]=c[8492]&~(1<<d);break}}else{if(i>>>0<(c[8495]|0)>>>0)ba();if((c[i+16>>2]|0)==(a+b|0))c[i+16>>2]=n;else c[i+20>>2]=n;if(!n)break}e=c[8495]|0;if(n>>>0<e>>>0)ba();c[n+24>>2]=i;d=c[a+b+16>>2]|0;do if(d|0)if(d>>>0<e>>>0)ba();else{c[n+16>>2]=d;c[d+24>>2]=n;break}while(0);d=c[a+b+16+4>>2]|0;if(d|0)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[n+20>>2]=d;c[d+24>>2]=n;break}}}else{d=c[a+b+8>>2]|0;e=c[a+b+12>>2]|0;if((d|0)!=(34004+(f>>>3<<1<<2)|0)){if(d>>>0<j>>>0)ba();if((c[d+12>>2]|0)!=(a+b|0))ba()}if((e|0)==(d|0)){c[8491]=c[8491]&~(1<<(f>>>3));break}if((e|0)!=(34004+(f>>>3<<1<<2)|0)){if(e>>>0<j>>>0)ba();if((c[e+8>>2]|0)!=(a+b|0))ba();else m=e+8|0}else m=e+8|0;c[d+12>>2]=e;c[m>>2]=d}while(0);c[q+4>>2]=h|1;c[q+h>>2]=h;if((q|0)==(c[8496]|0)){c[8493]=h;return}}else{c[a+b+4>>2]=f&-2;c[q+4>>2]=h|1;c[q+h>>2]=h}e=h>>>3;if(h>>>0<256){d=c[8491]|0;if(d&1<<e){d=c[34004+(e<<1<<2)+8>>2]|0;if(d>>>0<(c[8495]|0)>>>0)ba();else{o=d;p=34004+(e<<1<<2)+8|0}}else{c[8491]=d|1<<e;o=34004+(e<<1<<2)|0;p=34004+(e<<1<<2)+8|0}c[p>>2]=q;c[o+12>>2]=q;c[q+8>>2]=o;c[q+12>>2]=34004+(e<<1<<2);return}d=h>>>8;if(d)if(h>>>0>16777215)d=31;else{p=d<<((d+1048320|0)>>>16&8)<<(((d<<((d+1048320|0)>>>16&8))+520192|0)>>>16&4);d=14-(((d<<((d+1048320|0)>>>16&8))+520192|0)>>>16&4|(d+1048320|0)>>>16&8|(p+245760|0)>>>16&2)+(p<<((p+245760|0)>>>16&2)>>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;g=34268+(d<<2)|0;c[q+28>>2]=d;c[q+20>>2]=0;c[q+16>>2]=0;e=c[8492]|0;f=1<<d;if(!(e&f)){c[8492]=e|f;c[g>>2]=q;c[q+24>>2]=g;c[q+12>>2]=q;c[q+8>>2]=q;return}e=h<<((d|0)==31?0:25-(d>>>1)|0);g=c[g>>2]|0;while(1){if((c[g+4>>2]&-8|0)==(h|0)){d=127;break}f=g+16+(e>>>31<<2)|0;d=c[f>>2]|0;if(!d){d=124;break}else{e=e<<1;g=d}}if((d|0)==124){if(f>>>0<(c[8495]|0)>>>0)ba();c[f>>2]=q;c[q+24>>2]=g;c[q+12>>2]=q;c[q+8>>2]=q;return}else if((d|0)==127){d=g+8|0;e=c[d>>2]|0;p=c[8495]|0;if(!(e>>>0>=p>>>0&g>>>0>=p>>>0))ba();c[e+12>>2]=q;c[d>>2]=q;c[q+8>>2]=e;c[q+12>>2]=g;c[q+24>>2]=0;return}}function va(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0;V=i;U=i=i+63&-64;i=i+64|0;if(!((g|0)==0&(h|0)==0)){if(h>>>0>63|(h|0)==63&g>>>0>4294967232)ba();G=c[b>>2]|0;H=c[b+4>>2]|0;I=c[b+8>>2]|0;J=c[b+12>>2]|0;K=c[b+16>>2]|0;L=c[b+20>>2]|0;M=c[b+24>>2]|0;N=c[b+28>>2]|0;O=c[b+32>>2]|0;P=c[b+36>>2]|0;Q=c[b+40>>2]|0;R=c[b+44>>2]|0;S=c[b+56>>2]|0;T=c[b+60>>2]|0;j=0;C=c[b+52>>2]|0;A=c[b+48>>2]|0;E=h;F=g;while(1){B=E>>>0<0|(E|0)==0&F>>>0<64;if(B){h=U;g=h+64|0;do{a[h>>0]=0;h=h+1|0}while((h|0)<(g|0));h=0;do{a[U+h>>0]=a[e+h>>0]|0;h=h+1|0}while(0<E>>>0|0==(E|0)&h>>>0<F>>>0);j=f;e=U;f=U}h=G;k=H;l=I;m=J;n=K;o=L;p=M;q=N;r=O;s=P;t=Q;u=T;v=S;w=C;x=A;y=R;g=20;do{na=h+n|0;ca=na^x;aa=(ca<<16|ca>>>16)+r|0;ma=aa^n;ca=(ma<<12|ma>>>20)+na^(ca<<16|ca>>>16);z=(ca<<8|ca>>>24)+aa^(ma<<12|ma>>>20);ja=k+o|0;X=ja^w;W=(X<<16|X>>>16)+s|0;ia=W^o;X=(ia<<12|ia>>>20)+ja^(X<<16|X>>>16);ka=(X<<8|X>>>24)+W^(ia<<12|ia>>>20);ea=l+p|0;Y=ea^v;la=(Y<<16|Y>>>16)+t|0;da=la^p;Y=(da<<12|da>>>20)+ea^(Y<<16|Y>>>16);fa=(Y<<8|Y>>>24)+la^(da<<12|da>>>20);Z=m+q|0;ha=Z^u;ga=(ha<<16|ha>>>16)+y|0;_=ga^q;ha=(_<<12|_>>>20)+Z^(ha<<16|ha>>>16);$=(ha<<8|ha>>>24)+ga^(_<<12|_>>>20);na=(ka<<7|ka>>>25)+((ma<<12|ma>>>20)+na)|0;ma=(na^(ha<<8|ha>>>24))<<16|(na^(ha<<8|ha>>>24))>>>16;ka=ma+((Y<<8|Y>>>24)+la)^(ka<<7|ka>>>25);h=(ka<<12|ka>>>20)+na|0;na=h^ma;u=na<<8|na>>>24;t=u+(ma+((Y<<8|Y>>>24)+la))|0;ka=t^(ka<<12|ka>>>20);o=ka<<7|ka>>>25;ja=(fa<<7|fa>>>25)+((ia<<12|ia>>>20)+ja)|0;ia=(ja^(ca<<8|ca>>>24))<<16|(ja^(ca<<8|ca>>>24))>>>16;fa=ia+((ha<<8|ha>>>24)+ga)^(fa<<7|fa>>>25);k=(fa<<12|fa>>>20)+ja|0;ja=k^ia;x=ja<<8|ja>>>24;y=x+(ia+((ha<<8|ha>>>24)+ga))|0;fa=y^(fa<<12|fa>>>20);p=fa<<7|fa>>>25;ea=($<<7|$>>>25)+((da<<12|da>>>20)+ea)|0;da=(ea^(X<<8|X>>>24))<<16|(ea^(X<<8|X>>>24))>>>16;$=da+((ca<<8|ca>>>24)+aa)^($<<7|$>>>25);l=($<<12|$>>>20)+ea|0;ea=l^da;w=ea<<8|ea>>>24;r=w+(da+((ca<<8|ca>>>24)+aa))|0;$=r^($<<12|$>>>20);q=$<<7|$>>>25;Z=(z<<7|z>>>25)+((_<<12|_>>>20)+Z)|0;Y=(Z^(Y<<8|Y>>>24))<<16|(Z^(Y<<8|Y>>>24))>>>16;z=Y+((X<<8|X>>>24)+W)^(z<<7|z>>>25);m=(z<<12|z>>>20)+Z|0;Z=m^Y;v=Z<<8|Z>>>24;s=v+(Y+((X<<8|X>>>24)+W))|0;z=s^(z<<12|z>>>20);n=z<<7|z>>>25;g=g+-2|0}while((g|0)!=0);z=(d[e>>0]|d[e+1>>0]<<8|d[e+2>>0]<<16|d[e+3>>0]<<24)^h+G;Z=e+4|0;Z=(d[Z>>0]|d[Z+1>>0]<<8|d[Z+2>>0]<<16|d[Z+3>>0]<<24)^k+H;_=e+8|0;_=(d[_>>0]|d[_+1>>0]<<8|d[_+2>>0]<<16|d[_+3>>0]<<24)^l+I;$=e+12|0;$=(d[$>>0]|d[$+1>>0]<<8|d[$+2>>0]<<16|d[$+3>>0]<<24)^m+J;aa=e+16|0;aa=(d[aa>>0]|d[aa+1>>0]<<8|d[aa+2>>0]<<16|d[aa+3>>0]<<24)^n+K;ca=e+20|0;ca=(d[ca>>0]|d[ca+1>>0]<<8|d[ca+2>>0]<<16|d[ca+3>>0]<<24)^o+L;da=e+24|0;da=(d[da>>0]|d[da+1>>0]<<8|d[da+2>>0]<<16|d[da+3>>0]<<24)^p+M;ea=e+28|0;ea=(d[ea>>0]|d[ea+1>>0]<<8|d[ea+2>>0]<<16|d[ea+3>>0]<<24)^q+N;fa=e+32|0;fa=(d[fa>>0]|d[fa+1>>0]<<8|d[fa+2>>0]<<16|d[fa+3>>0]<<24)^r+O;ga=e+36|0;ga=(d[ga>>0]|d[ga+1>>0]<<8|d[ga+2>>0]<<16|d[ga+3>>0]<<24)^s+P;ha=e+40|0;ha=(d[ha>>0]|d[ha+1>>0]<<8|d[ha+2>>0]<<16|d[ha+3>>0]<<24)^t+Q;ia=e+44|0;ia=(d[ia>>0]|d[ia+1>>0]<<8|d[ia+2>>0]<<16|d[ia+3>>0]<<24)^y+R;ja=e+48|0;ja=(d[ja>>0]|d[ja+1>>0]<<8|d[ja+2>>0]<<16|d[ja+3>>0]<<24)^x+A;ka=e+52|0;ka=(d[ka>>0]|d[ka+1>>0]<<8|d[ka+2>>0]<<16|d[ka+3>>0]<<24)^w+C;la=e+56|0;la=(d[la>>0]|d[la+1>>0]<<8|d[la+2>>0]<<16|d[la+3>>0]<<24)^v+S;ma=e+60|0;ma=(d[ma>>0]|d[ma+1>>0]<<8|d[ma+2>>0]<<16|d[ma+3>>0]<<24)^u+T;g=A+1|0;h=((g|0)==0&1)+C|0;a[f>>0]=z;a[f+1>>0]=z>>8;a[f+2>>0]=z>>16;a[f+3>>0]=z>>24;na=f+4|0;a[na>>0]=Z;a[na+1>>0]=Z>>8;a[na+2>>0]=Z>>16;a[na+3>>0]=Z>>24;na=f+8|0;a[na>>0]=_;a[na+1>>0]=_>>8;a[na+2>>0]=_>>16;a[na+3>>0]=_>>24;na=f+12|0;a[na>>0]=$;a[na+1>>0]=$>>8;a[na+2>>0]=$>>16;a[na+3>>0]=$>>24;na=f+16|0;a[na>>0]=aa;a[na+1>>0]=aa>>8;a[na+2>>0]=aa>>16;a[na+3>>0]=aa>>24;na=f+20|0;a[na>>0]=ca;a[na+1>>0]=ca>>8;a[na+2>>0]=ca>>16;a[na+3>>0]=ca>>24;na=f+24|0;a[na>>0]=da;a[na+1>>0]=da>>8;a[na+2>>0]=da>>16;a[na+3>>0]=da>>24;na=f+28|0;a[na>>0]=ea;a[na+1>>0]=ea>>8;a[na+2>>0]=ea>>16;a[na+3>>0]=ea>>24;na=f+32|0;a[na>>0]=fa;a[na+1>>0]=fa>>8;a[na+2>>0]=fa>>16;a[na+3>>0]=fa>>24;na=f+36|0;a[na>>0]=ga;a[na+1>>0]=ga>>8;a[na+2>>0]=ga>>16;a[na+3>>0]=ga>>24;na=f+40|0;a[na>>0]=ha;a[na+1>>0]=ha>>8;a[na+2>>0]=ha>>16;a[na+3>>0]=ha>>24;na=f+44|0;a[na>>0]=ia;a[na+1>>0]=ia>>8;a[na+2>>0]=ia>>16;a[na+3>>0]=ia>>24;na=f+48|0;a[na>>0]=ja;a[na+1>>0]=ja>>8;a[na+2>>0]=ja>>16;a[na+3>>0]=ja>>24;na=f+52|0;a[na>>0]=ka;a[na+1>>0]=ka>>8;a[na+2>>0]=ka>>16;a[na+3>>0]=ka>>24;na=f+56|0;a[na>>0]=la;a[na+1>>0]=la>>8;a[na+2>>0]=la>>16;a[na+3>>0]=la>>24;na=f+60|0;a[na>>0]=ma;a[na+1>>0]=ma>>8;a[na+2>>0]=ma>>16;a[na+3>>0]=ma>>24;if(E>>>0<0|(E|0)==0&F>>>0<65)break;na=oe(F|0,E|0,-64,-1)|0;e=e+64|0;f=f+64|0;C=h;A=g;E=D;F=na}if((B?F|0:0)?(a[j>>0]=z,(F|0)!=1):0){e=1;do{a[j+e>>0]=a[f+e>>0]|0;e=e+1|0}while((e|0)!=(F|0))}c[b+48>>2]=g;c[b+52>>2]=h}i=V;return}function wa(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0;j=i;k=i=i+63&-64;i=i+320|0;h=k+280|0;g=h+32|0;do{a[h>>0]=a[e>>0]|0;h=h+1|0;e=e+1|0}while((h|0)<(g|0));a[k+280>>0]=(d[k+280>>0]|0)&248;a[k+280+31>>0]=(d[k+280+31>>0]|0)&63|64;ya(k+240|0,f);Ud(k+200|0);re(k+160|0);hc(k+120|0,k+240|0);Ud(k+80|0);e=0;g=254;while(1){B=e;e=(d[k+280+(g>>>3)>>0]|0)>>>(g&7)&1;B=e^B;db(k+200|0,k+120|0,B);db(k+160|0,k+80|0,B);Jb(k+40|0,k+120|0,k+80|0);Jb(k,k+200|0,k+160|0);Kb(k+200|0,k+200|0,k+160|0);Kb(k+160|0,k+120|0,k+80|0);pa(k+80|0,k+40|0,k+200|0);pa(k+160|0,k+160|0,k);ra(k+40|0,k);ra(k,k+200|0);Kb(k+120|0,k+80|0,k+160|0);Jb(k+160|0,k+80|0,k+160|0);pa(k+200|0,k,k+40|0);Jb(k,k,k+40|0);ra(k+160|0,k+160|0);B=c[k>>2]|0;A=c[k+4>>2]|0;z=c[k+8>>2]|0;y=c[k+12>>2]|0;x=c[k+16>>2]|0;s=c[k+20>>2]|0;v=c[k+24>>2]|0;E=c[k+28>>2]|0;t=c[k+32>>2]|0;C=c[k+36>>2]|0;B=Ed(B|0,((B|0)<0)<<31>>31|0,121666,0)|0;q=D;A=Ed(A|0,((A|0)<0)<<31>>31|0,121666,0)|0;r=D;z=Ed(z|0,((z|0)<0)<<31>>31|0,121666,0)|0;o=D;y=Ed(y|0,((y|0)<0)<<31>>31|0,121666,0)|0;p=D;x=Ed(x|0,((x|0)<0)<<31>>31|0,121666,0)|0;m=D;s=Ed(s|0,((s|0)<0)<<31>>31|0,121666,0)|0;n=D;v=Ed(v|0,((v|0)<0)<<31>>31|0,121666,0)|0;f=D;E=Ed(E|0,((E|0)<0)<<31>>31|0,121666,0)|0;l=D;t=Ed(t|0,((t|0)<0)<<31>>31|0,121666,0)|0;u=D;C=Ed(C|0,((C|0)<0)<<31>>31|0,121666,0)|0;h=D;F=oe(C|0,h|0,16777216,0)|0;F=Dd(F|0,D|0,25)|0;w=D;G=Ed(F|0,w|0,19,0)|0;q=oe(G|0,D|0,B|0,q|0)|0;B=D;w=Pd(F|0,w|0,25)|0;w=le(C|0,h|0,w|0,D|0)|0;h=D;C=oe(A|0,r|0,16777216,0)|0;C=Dd(C|0,D|0,25)|0;F=D;o=oe(C|0,F|0,z|0,o|0)|0;z=D;F=Pd(C|0,F|0,25)|0;F=le(A|0,r|0,F|0,D|0)|0;r=D;A=oe(y|0,p|0,16777216,0)|0;A=Dd(A|0,D|0,25)|0;C=D;m=oe(A|0,C|0,x|0,m|0)|0;x=D;C=Pd(A|0,C|0,25)|0;C=le(y|0,p|0,C|0,D|0)|0;p=D;y=oe(s|0,n|0,16777216,0)|0;y=Dd(y|0,D|0,25)|0;A=D;f=oe(y|0,A|0,v|0,f|0)|0;v=D;A=Pd(y|0,A|0,25)|0;A=le(s|0,n|0,A|0,D|0)|0;n=D;s=oe(E|0,l|0,16777216,0)|0;s=Dd(s|0,D|0,25)|0;y=D;u=oe(s|0,y|0,t|0,u|0)|0;t=D;y=Pd(s|0,y|0,25)|0;y=le(E|0,l|0,y|0,D|0)|0;l=D;E=oe(q|0,B|0,33554432,0)|0;E=Dd(E|0,D|0,26)|0;s=D;r=oe(F|0,r|0,E|0,s|0)|0;s=Pd(E|0,s|0,26)|0;s=le(q|0,B|0,s|0,D|0)|0;B=oe(o|0,z|0,33554432,0)|0;B=Dd(B|0,D|0,26)|0;q=D;p=oe(C|0,p|0,B|0,q|0)|0;q=Pd(B|0,q|0,26)|0;q=le(o|0,z|0,q|0,D|0)|0;z=oe(m|0,x|0,33554432,0)|0;z=Dd(z|0,D|0,26)|0;o=D;n=oe(A|0,n|0,z|0,o|0)|0;o=Pd(z|0,o|0,26)|0;o=le(m|0,x|0,o|0,D|0)|0;x=oe(f|0,v|0,33554432,0)|0;x=Dd(x|0,D|0,26)|0;m=D;l=oe(y|0,l|0,x|0,m|0)|0;m=Pd(x|0,m|0,26)|0;m=le(f|0,v|0,m|0,D|0)|0;v=oe(u|0,t|0,33554432,0)|0;v=Dd(v|0,D|0,26)|0;f=D;h=oe(w|0,h|0,v|0,f|0)|0;f=Pd(v|0,f|0,26)|0;f=le(u|0,t|0,f|0,D|0)|0;c[k+80>>2]=s;c[k+80+4>>2]=r;c[k+80+8>>2]=q;c[k+80+12>>2]=p;c[k+80+16>>2]=o;c[k+80+20>>2]=n;c[k+80+24>>2]=m;c[k+80+28>>2]=l;c[k+80+32>>2]=f;c[k+80+36>>2]=h;ra(k+120|0,k+120|0);Kb(k+40|0,k+40|0,k+80|0);pa(k+80|0,k+240|0,k+160|0);pa(k+160|0,k,k+40|0);if((g|0)<=0)break;else g=g+-1|0}db(k+200|0,k+120|0,e);db(k+160|0,k+80|0,e);Ia(k+160|0,k+160|0);pa(k+200|0,k+200|0,k+160|0);La(b,k+200|0);i=j;return 0}function xa(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0;if(!f){H=857760878;I=2036477234;J=1634760805;G=1797285236}else{H=d[f+4>>0]|d[f+4+1>>0]<<8|d[f+4+2>>0]<<16|d[f+4+3>>0]<<24;I=d[f+8>>0]|d[f+8+1>>0]<<8|d[f+8+2>>0]<<16|d[f+8+3>>0]<<24;J=d[f>>0]|d[f+1>>0]<<8|d[f+2>>0]<<16|d[f+3>>0]<<24;G=d[f+12>>0]|d[f+12+1>>0]<<8|d[f+12+2>>0]<<16|d[f+12+3>>0]<<24}F=d[e>>0]|d[e+1>>0]<<8|d[e+2>>0]<<16|d[e+3>>0]<<24;E=d[e+4>>0]|d[e+4+1>>0]<<8|d[e+4+2>>0]<<16|d[e+4+3>>0]<<24;D=d[e+8>>0]|d[e+8+1>>0]<<8|d[e+8+2>>0]<<16|d[e+8+3>>0]<<24;C=d[e+12>>0]|d[e+12+1>>0]<<8|d[e+12+2>>0]<<16|d[e+12+3>>0]<<24;B=d[c>>0]|d[c+1>>0]<<8|d[c+2>>0]<<16|d[c+3>>0]<<24;A=d[c+4>>0]|d[c+4+1>>0]<<8|d[c+4+2>>0]<<16|d[c+4+3>>0]<<24;z=d[c+8>>0]|d[c+8+1>>0]<<8|d[c+8+2>>0]<<16|d[c+8+3>>0]<<24;y=d[c+12>>0]|d[c+12+1>>0]<<8|d[c+12+2>>0]<<16|d[c+12+3>>0]<<24;x=d[e+16>>0]|d[e+16+1>>0]<<8|d[e+16+2>>0]<<16|d[e+16+3>>0]<<24;w=d[e+20>>0]|d[e+20+1>>0]<<8|d[e+20+2>>0]<<16|d[e+20+3>>0]<<24;v=d[e+24>>0]|d[e+24+1>>0]<<8|d[e+24+2>>0]<<16|d[e+24+3>>0]<<24;f=d[e+28>>0]|d[e+28+1>>0]<<8|d[e+28+2>>0]<<16|d[e+28+3>>0]<<24;c=F;e=E;g=D;h=C;i=B;j=A;k=z;l=y;m=x;n=f;o=v;p=w;q=20;r=H;s=I;t=G;u=J;while(1){T=u+p|0;T=(T>>>25|T<<7)^h;Q=T+u|0;Q=(Q>>>23|Q<<9)^k;N=((Q+T|0)>>>19|Q+T<<13)^p;W=((N+Q|0)>>>14|N+Q<<18)^u;P=c+r|0;P=(P>>>25|P<<7)^l;M=P+r|0;M=(M>>>23|M<<9)^o;Z=((M+P|0)>>>19|M+P<<13)^c;S=((Z+M|0)>>>14|Z+M<<18)^r;L=i+s|0;L=(L>>>25|L<<7)^n;Y=L+s|0;Y=(Y>>>23|Y<<9)^e;V=((Y+L|0)>>>19|Y+L<<13)^i;O=((V+Y|0)>>>14|V+Y<<18)^s;X=m+t|0;X=g^(X>>>25|X<<7);U=X+t|0;U=(U>>>23|U<<9)^j;R=((U+X|0)>>>19|U+X<<13)^m;K=((R+U|0)>>>14|R+U<<18)^t;c=((W+X|0)>>>25|W+X<<7)^Z;Z=c+W|0;e=(Z>>>23|Z<<9)^Y;Y=e+c|0;g=(Y>>>19|Y<<13)^X;X=g+e|0;u=(X>>>14|X<<18)^W;i=((S+T|0)>>>25|S+T<<7)^V;V=i+S|0;j=(V>>>23|V<<9)^U;U=j+i|0;h=(U>>>19|U<<13)^T;T=h+j|0;r=(T>>>14|T<<18)^S;m=((O+P|0)>>>25|O+P<<7)^R;R=m+O|0;k=(R>>>23|R<<9)^Q;Q=k+m|0;l=(Q>>>19|Q<<13)^P;P=l+k|0;s=(P>>>14|P<<18)^O;p=((K+L|0)>>>25|K+L<<7)^N;N=p+K|0;o=(N>>>23|N<<9)^M;M=o+p|0;n=(M>>>19|M<<13)^L;L=n+o|0;t=(L>>>14|L<<18)^K;if((q|0)<=2)break;else q=q+-2|0}K=u+J|0;L=c+F|0;M=e+E|0;N=g+D|0;O=h+C|0;P=r+H|0;Q=i+B|0;R=j+A|0;S=k+z|0;T=l+y|0;U=s+I|0;V=m+x|0;W=p+w|0;X=o+v|0;Y=n+f|0;Z=t+G|0;a[b>>0]=K;a[b+1>>0]=K>>8;a[b+2>>0]=K>>16;a[b+3>>0]=K>>24;a[b+4>>0]=L;a[b+4+1>>0]=L>>8;a[b+4+2>>0]=L>>16;a[b+4+3>>0]=L>>24;a[b+8>>0]=M;a[b+8+1>>0]=M>>8;a[b+8+2>>0]=M>>16;a[b+8+3>>0]=M>>24;a[b+12>>0]=N;a[b+12+1>>0]=N>>8;a[b+12+2>>0]=N>>16;a[b+12+3>>0]=N>>24;a[b+16>>0]=O;a[b+16+1>>0]=O>>8;a[b+16+2>>0]=O>>16;a[b+16+3>>0]=O>>24;a[b+20>>0]=P;a[b+20+1>>0]=P>>8;a[b+20+2>>0]=P>>16;a[b+20+3>>0]=P>>24;a[b+24>>0]=Q;a[b+24+1>>0]=Q>>8;a[b+24+2>>0]=Q>>16;a[b+24+3>>0]=Q>>24;a[b+28>>0]=R;a[b+28+1>>0]=R>>8;a[b+28+2>>0]=R>>16;a[b+28+3>>0]=R>>24;a[b+32>>0]=S;a[b+32+1>>0]=S>>8;a[b+32+2>>0]=S>>16;a[b+32+3>>0]=S>>24;a[b+36>>0]=T;a[b+36+1>>0]=T>>8;a[b+36+2>>0]=T>>16;a[b+36+3>>0]=T>>24;a[b+40>>0]=U;a[b+40+1>>0]=U>>8;a[b+40+2>>0]=U>>16;a[b+40+3>>0]=U>>24;a[b+44>>0]=V;a[b+44+1>>0]=V>>8;a[b+44+2>>0]=V>>16;a[b+44+3>>0]=V>>24;a[b+48>>0]=W;a[b+48+1>>0]=W>>8;a[b+48+2>>0]=W>>16;a[b+48+3>>0]=W>>24;a[b+52>>0]=X;a[b+52+1>>0]=X>>8;a[b+52+2>>0]=X>>16;a[b+52+3>>0]=X>>24;a[b+56>>0]=Y;a[b+56+1>>0]=Y>>8;a[b+56+2>>0]=Y>>16;a[b+56+3>>0]=Y>>24;a[b+60>>0]=Z;a[b+60+1>>0]=Z>>8;a[b+60+2>>0]=Z>>16;a[b+60+3>>0]=Z>>24;return 0}function ya(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0;J=d[b>>0]|0;h=Pd(d[b+1>>0]|0|0,0,8)|0;k=D;F=Pd(d[b+2>>0]|0|0,0,16)|0;k=k|D;E=Pd(d[b+3>>0]|0|0,0,24)|0;k=k|D;B=d[b+4>>0]|0;C=Pd(d[b+5>>0]|0|0,0,8)|0;j=D;l=Pd(d[b+6>>0]|0|0,0,16)|0;j=Pd(C|B|l|0,j|D|0,6)|0;l=D;B=d[b+7>>0]|0;C=Pd(d[b+8>>0]|0|0,0,8)|0;w=D;i=Pd(d[b+9>>0]|0|0,0,16)|0;w=Pd(C|B|i|0,w|D|0,5)|0;i=D;B=d[b+10>>0]|0;C=Pd(d[b+11>>0]|0|0,0,8)|0;H=D;G=Pd(d[b+12>>0]|0|0,0,16)|0;H=Pd(C|B|G|0,H|D|0,3)|0;G=D;B=d[b+13>>0]|0;C=Pd(d[b+14>>0]|0|0,0,8)|0;s=D;g=Pd(d[b+15>>0]|0|0,0,16)|0;s=Pd(C|B|g|0,s|D|0,2)|0;g=D;B=d[b+16>>0]|0;C=Pd(d[b+17>>0]|0|0,0,8)|0;y=D;A=Pd(d[b+18>>0]|0|0,0,16)|0;y=y|D;z=Pd(d[b+19>>0]|0|0,0,24)|0;y=y|D;q=d[b+20>>0]|0;x=Pd(d[b+21>>0]|0|0,0,8)|0;p=D;e=Pd(d[b+22>>0]|0|0,0,16)|0;p=Pd(x|q|e|0,p|D|0,7)|0;e=D;q=d[b+23>>0]|0;x=Pd(d[b+24>>0]|0|0,0,8)|0;v=D;u=Pd(d[b+25>>0]|0|0,0,16)|0;v=Pd(x|q|u|0,v|D|0,5)|0;u=D;q=d[b+26>>0]|0;x=Pd(d[b+27>>0]|0|0,0,8)|0;n=D;o=Pd(d[b+28>>0]|0|0,0,16)|0;n=Pd(x|q|o|0,n|D|0,4)|0;o=D;q=d[b+29>>0]|0;x=Pd(d[b+30>>0]|0|0,0,8)|0;r=D;b=Pd(d[b+31>>0]|0|0,0,16)|0;r=Pd(x|q|b|0,r|D|0,2)|0;b=oe(r&33554428|0,0,16777216,0)|0;b=Rd(b|0,D|0,25)|0;q=D;x=le(0,0,b|0,q|0)|0;k=oe(x&19|0,0,h|J|F|E|0,k|0)|0;E=D;q=Pd(b|0,q|0,25)|0;b=D;F=oe(j|0,l|0,16777216,0)|0;F=Rd(F|0,D|0,25)|0;J=D;i=oe(w|0,i|0,F|0,J|0)|0;w=D;J=Pd(F|0,J|0,25)|0;J=le(j|0,l|0,J|0,D|0)|0;l=D;j=oe(H|0,G|0,16777216,0)|0;j=Rd(j|0,D|0,25)|0;F=D;g=oe(s|0,g|0,j|0,F|0)|0;s=D;F=Pd(j|0,F|0,25)|0;j=D;h=oe(C|B|A|z|0,y|0,16777216,0)|0;h=Rd(h|0,D|0,25)|0;x=D;e=oe(p|0,e|0,h|0,x|0)|0;p=D;x=Pd(h|0,x|0,25)|0;h=D;f=oe(v|0,u|0,16777216,0)|0;f=Rd(f|0,D|0,25)|0;t=D;o=oe(n|0,o|0,f|0,t|0)|0;n=D;t=Pd(f|0,t|0,25)|0;f=D;I=oe(k|0,E|0,33554432,0)|0;I=Dd(I|0,D|0,26)|0;m=D;l=oe(J|0,l|0,I|0,m|0)|0;m=Pd(I|0,m|0,26)|0;m=le(k|0,E|0,m|0,D|0)|0;E=oe(i|0,w|0,33554432,0)|0;E=Dd(E|0,D|0,26)|0;k=D;G=oe(E|0,k|0,H|0,G|0)|0;j=le(G|0,D|0,F|0,j|0)|0;k=Pd(E|0,k|0,26)|0;k=le(i|0,w|0,k|0,D|0)|0;w=oe(g|0,s|0,33554432,0)|0;w=Dd(w|0,D|0,26)|0;i=D;y=oe(w|0,i|0,C|B|A|z|0,y|0)|0;h=le(y|0,D|0,x|0,h|0)|0;i=Pd(w|0,i|0,26)|0;i=le(g|0,s|0,i|0,D|0)|0;s=oe(e|0,p|0,33554432,0)|0;s=Dd(s|0,D|0,26)|0;g=D;u=oe(s|0,g|0,v|0,u|0)|0;f=le(u|0,D|0,t|0,f|0)|0;g=Pd(s|0,g|0,26)|0;g=le(e|0,p|0,g|0,D|0)|0;p=oe(o|0,n|0,33554432,0)|0;p=Dd(p|0,D|0,26)|0;e=D;r=oe(r&33554428|0,0,p|0,e|0)|0;b=le(r|0,D|0,q|0,b|0)|0;e=Pd(p|0,e|0,26)|0;e=le(o|0,n|0,e|0,D|0)|0;c[a>>2]=m;c[a+4>>2]=l;c[a+8>>2]=k;c[a+12>>2]=j;c[a+16>>2]=i;c[a+20>>2]=h;c[a+24>>2]=g;c[a+28>>2]=f;c[a+32>>2]=e;c[a+36>>2]=b;return}function za(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;r=i;p=i=i+63&-64;i=i+240|0;ya(a+40|0,b);c[a+80>>2]=1;e=a+84|0;f=e+36|0;do{c[e>>2]=0;e=e+4|0}while((e|0)<(f|0));ra(p+160|0,a+40|0);pa(p+120|0,p+160|0,464);g=c[a+80>>2]|0;f=c[a+84>>2]|0;e=c[a+88>>2]|0;o=c[a+92>>2]|0;n=c[a+96>>2]|0;m=c[a+100>>2]|0;l=c[a+104>>2]|0;k=c[a+108>>2]|0;j=c[a+112>>2]|0;h=c[a+116>>2]|0;B=(c[p+160>>2]|0)-g|0;A=(c[p+160+4>>2]|0)-f|0;z=(c[p+160+8>>2]|0)-e|0;y=(c[p+160+12>>2]|0)-o|0;x=(c[p+160+16>>2]|0)-n|0;w=(c[p+160+20>>2]|0)-m|0;v=(c[p+160+24>>2]|0)-l|0;u=(c[p+160+28>>2]|0)-k|0;t=(c[p+160+32>>2]|0)-j|0;s=(c[p+160+36>>2]|0)-h|0;c[p+160>>2]=B;c[p+160+4>>2]=A;c[p+160+8>>2]=z;c[p+160+12>>2]=y;c[p+160+16>>2]=x;c[p+160+20>>2]=w;c[p+160+24>>2]=v;c[p+160+28>>2]=u;c[p+160+32>>2]=t;c[p+160+36>>2]=s;f=f+(c[p+120+4>>2]|0)|0;e=e+(c[p+120+8>>2]|0)|0;o=o+(c[p+120+12>>2]|0)|0;n=n+(c[p+120+16>>2]|0)|0;m=m+(c[p+120+20>>2]|0)|0;l=l+(c[p+120+24>>2]|0)|0;k=k+(c[p+120+28>>2]|0)|0;j=j+(c[p+120+32>>2]|0)|0;h=h+(c[p+120+36>>2]|0)|0;c[p+120>>2]=g+(c[p+120>>2]|0);c[p+120+4>>2]=f;c[p+120+8>>2]=e;c[p+120+12>>2]=o;c[p+120+16>>2]=n;c[p+120+20>>2]=m;c[p+120+24>>2]=l;c[p+120+28>>2]=k;c[p+120+32>>2]=j;c[p+120+36>>2]=h;ra(p+80|0,p+120|0);pa(p+80|0,p+80|0,p+120|0);ra(a,p+80|0);pa(a,a,p+120|0);pa(a,a,p+160|0);Ka(a,a);pa(a,a,p+80|0);pa(a,a,p+160|0);ra(p+40|0,a);pa(p+40|0,p+40|0,p+120|0);h=c[p+40>>2]|0;j=c[p+40+4>>2]|0;k=c[p+40+8>>2]|0;l=c[p+40+12>>2]|0;m=c[p+40+16>>2]|0;n=c[p+40+20>>2]|0;o=c[p+40+24>>2]|0;e=c[p+40+28>>2]|0;f=c[p+40+32>>2]|0;g=c[p+40+36>>2]|0;c[p>>2]=h-B;c[p+4>>2]=j-A;c[p+8>>2]=k-z;c[p+12>>2]=l-y;c[p+16>>2]=m-x;c[p+20>>2]=n-w;c[p+24>>2]=o-v;c[p+28>>2]=e-u;c[p+32>>2]=f-t;c[p+36>>2]=g-s;La(p+200|0,p);if(zd(p+200|0,34492)|0){t=(c[p+160+4>>2]|0)+j|0;u=(c[p+160+8>>2]|0)+k|0;v=(c[p+160+12>>2]|0)+l|0;w=(c[p+160+16>>2]|0)+m|0;x=(c[p+160+20>>2]|0)+n|0;y=(c[p+160+24>>2]|0)+o|0;z=(c[p+160+28>>2]|0)+e|0;A=(c[p+160+32>>2]|0)+f|0;B=(c[p+160+36>>2]|0)+g|0;c[p>>2]=(c[p+160>>2]|0)+h;c[p+4>>2]=t;c[p+8>>2]=u;c[p+12>>2]=v;c[p+16>>2]=w;c[p+20>>2]=x;c[p+24>>2]=y;c[p+28>>2]=z;c[p+32>>2]=A;c[p+36>>2]=B;La(p+200|0,p);if(!(zd(p+200|0,34492)|0)){pa(a,a,504);q=4}else e=-1}else q=4;if((q|0)==4){La(p+200|0,a);if(((d[p+200>>0]|0)&1|0)==((d[b+31>>0]|0)>>>7|0))$b(a,a);pa(a+120|0,a,a+40|0);e=0}i=r;return e|0}function Aa(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0;if(!f){o=1797285236;g=2036477234;h=857760878;f=1634760805}else{o=d[f+12>>0]|d[f+12+1>>0]<<8|d[f+12+2>>0]<<16|d[f+12+3>>0]<<24;g=d[f+8>>0]|d[f+8+1>>0]<<8|d[f+8+2>>0]<<16|d[f+8+3>>0]<<24;h=d[f+4>>0]|d[f+4+1>>0]<<8|d[f+4+2>>0]<<16|d[f+4+3>>0]<<24;f=d[f>>0]|d[f+1>>0]<<8|d[f+2>>0]<<16|d[f+3>>0]<<24}p=d[e+28>>0]|d[e+28+1>>0]<<8|d[e+28+2>>0]<<16|d[e+28+3>>0]<<24;q=d[e+24>>0]|d[e+24+1>>0]<<8|d[e+24+2>>0]<<16|d[e+24+3>>0]<<24;r=d[e+20>>0]|d[e+20+1>>0]<<8|d[e+20+2>>0]<<16|d[e+20+3>>0]<<24;s=d[e+16>>0]|d[e+16+1>>0]<<8|d[e+16+2>>0]<<16|d[e+16+3>>0]<<24;t=d[c+12>>0]|d[c+12+1>>0]<<8|d[c+12+2>>0]<<16|d[c+12+3>>0]<<24;u=d[c+8>>0]|d[c+8+1>>0]<<8|d[c+8+2>>0]<<16|d[c+8+3>>0]<<24;v=d[c+4>>0]|d[c+4+1>>0]<<8|d[c+4+2>>0]<<16|d[c+4+3>>0]<<24;k=d[c>>0]|d[c+1>>0]<<8|d[c+2>>0]<<16|d[c+3>>0]<<24;l=d[e+12>>0]|d[e+12+1>>0]<<8|d[e+12+2>>0]<<16|d[e+12+3>>0]<<24;m=d[e+8>>0]|d[e+8+1>>0]<<8|d[e+8+2>>0]<<16|d[e+8+3>>0]<<24;n=d[e+4>>0]|d[e+4+1>>0]<<8|d[e+4+2>>0]<<16|d[e+4+3>>0]<<24;i=d[e>>0]|d[e+1>>0]<<8|d[e+2>>0]<<16|d[e+3>>0]<<24;j=20;e=h;c=f;f=o;while(1){D=r+c|0;D=(D>>>25|D<<7)^l;A=D+c|0;A=(A>>>23|A<<9)^u;x=((A+D|0)>>>19|A+D<<13)^r;G=((x+A|0)>>>14|x+A<<18)^c;z=e+i|0;z=t^(z>>>25|z<<7);w=z+e|0;w=q^(w>>>23|w<<9);J=((w+z|0)>>>19|w+z<<13)^i;C=((J+w|0)>>>14|J+w<<18)^e;h=g+k|0;h=p^(h>>>25|h<<7);I=h+g|0;I=(I>>>23|I<<9)^n;F=((I+h|0)>>>19|I+h<<13)^k;y=((F+I|0)>>>14|F+I<<18)^g;H=f+s|0;H=(H>>>25|H<<7)^m;E=H+f|0;E=(E>>>23|E<<9)^v;B=((E+H|0)>>>19|E+H<<13)^s;o=((B+E|0)>>>14|B+E<<18)^f;i=((G+H|0)>>>25|G+H<<7)^J;J=i+G|0;n=(J>>>23|J<<9)^I;I=n+i|0;m=(I>>>19|I<<13)^H;H=m+n|0;c=(H>>>14|H<<18)^G;k=((C+D|0)>>>25|C+D<<7)^F;F=k+C|0;v=(F>>>23|F<<9)^E;E=v+k|0;l=(E>>>19|E<<13)^D;D=l+v|0;e=(D>>>14|D<<18)^C;s=((y+z|0)>>>25|y+z<<7)^B;B=s+y|0;u=(B>>>23|B<<9)^A;A=u+s|0;t=(A>>>19|A<<13)^z;z=t+u|0;g=(z>>>14|z<<18)^y;r=((o+h|0)>>>25|o+h<<7)^x;x=r+o|0;q=(x>>>23|x<<9)^w;w=q+r|0;p=(w>>>19|w<<13)^h;h=p+q|0;f=(h>>>14|h<<18)^o;if((j|0)<=2)break;else j=j+-2|0}a[b>>0]=c;a[b+1>>0]=c>>8;a[b+2>>0]=c>>16;a[b+3>>0]=c>>24;a[b+4>>0]=e;a[b+4+1>>0]=e>>8;a[b+4+2>>0]=e>>16;a[b+4+3>>0]=e>>24;a[b+8>>0]=g;a[b+8+1>>0]=g>>8;a[b+8+2>>0]=g>>16;a[b+8+3>>0]=g>>24;a[b+12>>0]=f;a[b+12+1>>0]=f>>8;a[b+12+2>>0]=f>>16;a[b+12+3>>0]=f>>24;a[b+16>>0]=k;a[b+16+1>>0]=k>>8;a[b+16+2>>0]=k>>16;a[b+16+3>>0]=k>>24;a[b+20>>0]=v;a[b+20+1>>0]=v>>8;a[b+20+2>>0]=v>>16;a[b+20+3>>0]=v>>24;a[b+24>>0]=u;a[b+24+1>>0]=u>>8;a[b+24+2>>0]=u>>16;a[b+24+3>>0]=u>>24;a[b+28>>0]=t;a[b+28+1>>0]=t>>8;a[b+28+2>>0]=t>>16;a[b+28+3>>0]=t>>24;return 0}function Ba(b,e,f,g){b=b|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;t=a[b+80>>0]|0?0:16777216;u=c[b+4>>2]|0;p=c[b+8>>2]|0;q=c[b+12>>2]|0;r=c[b+16>>2]|0;l=c[b+20>>2]|0;k=c[b+24>>2]|0;j=c[b+28>>2]|0;i=c[b+32>>2]|0;h=c[b+36>>2]|0;if(g>>>0>0|(g|0)==0&f>>>0>15){s=c[b>>2]|0;n=f;while(1){z=((d[e>>0]|d[e+1>>0]<<8|d[e+2>>0]<<16|d[e+3>>0]<<24)&67108863)+l|0;A=e+3|0;A=((d[A>>0]|d[A+1>>0]<<8|d[A+2>>0]<<16|d[A+3>>0]<<24)>>>2&67108863)+k|0;y=e+6|0;y=((d[y>>0]|d[y+1>>0]<<8|d[y+2>>0]<<16|d[y+3>>0]<<24)>>>4&67108863)+j|0;x=e+9|0;x=((d[x>>0]|d[x+1>>0]<<8|d[x+2>>0]<<16|d[x+3>>0]<<24)>>>6)+i|0;l=e+12|0;l=((d[l>>0]|d[l+1>>0]<<8|d[l+2>>0]<<16|d[l+3>>0]<<24)>>>8|t)+h|0;h=Ed(z|0,0,s|0,0)|0;f=D;j=Ed(A|0,0,r*5|0,0)|0;f=oe(j|0,D|0,h|0,f|0)|0;h=D;j=Ed(y|0,0,q*5|0,0)|0;j=oe(f|0,h|0,j|0,D|0)|0;h=D;f=Ed(x|0,0,p*5|0,0)|0;f=oe(j|0,h|0,f|0,D|0)|0;h=D;j=Ed(l|0,0,u*5|0,0)|0;j=oe(f|0,h|0,j|0,D|0)|0;h=D;f=Ed(z|0,0,u|0,0)|0;m=D;w=Ed(A|0,0,s|0,0)|0;m=oe(w|0,D|0,f|0,m|0)|0;f=D;w=Ed(y|0,0,r*5|0,0)|0;w=oe(m|0,f|0,w|0,D|0)|0;f=D;m=Ed(x|0,0,q*5|0,0)|0;m=oe(w|0,f|0,m|0,D|0)|0;f=D;w=Ed(l|0,0,p*5|0,0)|0;w=oe(m|0,f|0,w|0,D|0)|0;f=D;m=Ed(z|0,0,p|0,0)|0;o=D;v=Ed(A|0,0,u|0,0)|0;o=oe(v|0,D|0,m|0,o|0)|0;m=D;v=Ed(y|0,0,s|0,0)|0;v=oe(o|0,m|0,v|0,D|0)|0;m=D;o=Ed(x|0,0,r*5|0,0)|0;o=oe(v|0,m|0,o|0,D|0)|0;m=D;v=Ed(l|0,0,q*5|0,0)|0;v=oe(o|0,m|0,v|0,D|0)|0;m=D;o=Ed(z|0,0,q|0,0)|0;i=D;k=Ed(A|0,0,p|0,0)|0;i=oe(k|0,D|0,o|0,i|0)|0;o=D;k=Ed(y|0,0,u|0,0)|0;k=oe(i|0,o|0,k|0,D|0)|0;o=D;i=Ed(x|0,0,s|0,0)|0;i=oe(k|0,o|0,i|0,D|0)|0;o=D;k=Ed(l|0,0,r*5|0,0)|0;k=oe(i|0,o|0,k|0,D|0)|0;o=D;i=Ed(z|0,0,r|0,0)|0;z=D;A=Ed(A|0,0,q|0,0)|0;z=oe(A|0,D|0,i|0,z|0)|0;i=D;y=Ed(y|0,0,p|0,0)|0;y=oe(z|0,i|0,y|0,D|0)|0;i=D;x=Ed(x|0,0,u|0,0)|0;x=oe(y|0,i|0,x|0,D|0)|0;i=D;l=Ed(l|0,0,s|0,0)|0;l=oe(x|0,i|0,l|0,D|0)|0;i=D;h=Rd(j|0,h|0,26)|0;h=oe(w|0,f|0,h|0,0)|0;f=Rd(h|0,D|0,26)|0;f=oe(v|0,m|0,f|0,0)|0;m=Rd(f|0,D|0,26)|0;m=oe(k|0,o|0,m|0,0)|0;o=Rd(m|0,D|0,26)|0;o=oe(l|0,i|0,o|0,0)|0;i=Rd(o|0,D|0,26)|0;n=oe(n|0,g|0,-16,-1)|0;g=D;if(!(g>>>0>0|(g|0)==0&n>>>0>15)){l=(i*5|0)+j&67108863;k=(((i*5|0)+(j&67108863)|0)>>>26)+(h&67108863)|0;j=f&67108863;i=m&67108863;h=o&67108863;break}else{l=(i*5|0)+j&67108863;k=(((i*5|0)+(j&67108863)|0)>>>26)+(h&67108863)|0;j=f&67108863;i=m&67108863;h=o&67108863;e=e+16|0}}}c[b+20>>2]=l;c[b+24>>2]=k;c[b+28>>2]=j;c[b+32>>2]=i;c[b+36>>2]=h;return}function Ca(b,e,f,g,h,i,j,k,l,m,n){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;var o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;v=Ed(l|0,0,k|0,0)|0;u=D;do if(u>>>0>0|(u|0)==0&v>>>0>1073741823){c[(Zf()|0)>>2]=27;b=-1}else{if(j>>>0>0|(j|0)==0&i>>>0>4294967295){c[(Zf()|0)>>2]=27;b=-1;break}u=oe(i|0,j|0,-1,-1)|0;if(j>>>0<0|(j|0)==0&i>>>0<2|((u&i|0)!=0|(D&j|0)!=0)){c[(Zf()|0)>>2]=22;b=-1;break}if((k|0)==0|(l|0)==0){c[(Zf()|0)>>2]=22;b=-1;break}if(!(k>>>0>16777215?1:(33554431/(l>>>0)|0)>>>0<k>>>0)?!(0<j>>>0|(0==(j|0)?(33554431/(k>>>0)|0)>>>0<i>>>0:0)):0){v=S(k<<7,l)|0;p=Ed(k<<7|0,0,i|0,j|0)|0;if((p+v|0)>>>0<p>>>0){c[(Zf()|0)>>2]=12;b=-1;break}o=p+v+(k<<8|64)|0;if(o>>>0<(k<<8|64)>>>0){c[(Zf()|0)>>2]=12;b=-1;break}if((c[b+8>>2]|0)>>>0<o>>>0?(je(b),(Nc(b,o)|0)==0):0){b=-1;break}t=c[b+4>>2]|0;s=t+v+p|0;Tb(e,f,g,h,t,v);q=s+(k<<5<<2)|0;h=0;do{r=t+(S(k<<7,h)|0)|0;if(k<<5|0){b=0;do{g=r+(b<<2)|0;c[s+(b<<2)>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;b=b+1|0}while((b|0)!=(k<<5|0))}if(!((i|0)==0&(j|0)==0)){p=0;g=0;do{if(!(k<<5&1073741792))wb(s,q,s+(k<<6<<2)|0,k);else{o=Ed(p|0,g|0,k<<5|0,0)|0;b=0;do{c[t+v+(o<<2)+(b<<2)>>2]=c[s+(b<<2)>>2];b=b+1|0}while((b|0)!=(k<<5&1073741792|0));wb(s,q,s+(k<<6<<2)|0,k);o=Ed(p|1|0,g|0,k<<5|0,0)|0;b=0;do{c[t+v+(o<<2)+(b<<2)>>2]=c[q+(b<<2)>>2];b=b+1|0}while((b|0)!=(k<<5&1073741792|0))}wb(q,s,s+(k<<6<<2)|0,k);p=oe(p|0,g|0,2,0)|0;g=D}while(g>>>0<j>>>0|(g|0)==(j|0)&p>>>0<i>>>0);p=0;g=0;do{if(!(k<<5&1073741792))wb(s,q,s+(k<<6<<2)|0,k);else{o=Ed(c[s+((k<<7)+-64)>>2]&u|0,0,k<<5|0,0)|0;b=0;do{w=s+(b<<2)|0;c[w>>2]=c[w>>2]^c[t+v+(o<<2)+(b<<2)>>2];b=b+1|0}while((b|0)!=(k<<5&1073741792|0));wb(s,q,s+(k<<6<<2)|0,k);o=Ed(c[q+((k<<7)+-64)>>2]&u|0,0,k<<5|0,0)|0;b=0;do{w=q+(b<<2)|0;c[w>>2]=c[w>>2]^c[t+v+(o<<2)+(b<<2)>>2];b=b+1|0}while((b|0)!=(k<<5&1073741792|0))}wb(q,s,s+(k<<6<<2)|0,k);p=oe(p|0,g|0,2,0)|0;g=D}while(g>>>0<j>>>0|(g|0)==(j|0)&p>>>0<i>>>0)}if(k<<5|0){b=0;do{w=r+(b<<2)|0;g=c[s+(b<<2)>>2]|0;a[w>>0]=g;a[w+1>>0]=g>>8;a[w+2>>0]=g>>16;a[w+3>>0]=g>>24;b=b+1|0}while((b|0)!=(k<<5|0))}h=h+1|0}while((h|0)!=(l|0));Tb(e,f,t,v,m,n);b=0;break}c[(Zf()|0)>>2]=12;b=-1}while(0);return b|0}function Da(e,f,g){e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;r=i;o=i=i+63&-64;i=i+32|0;do if(f>>>0>=12){h=e;j=32952;k=h+12|0;do{a[h>>0]=a[j>>0]|0;h=h+1|0;j=j+1|0}while((h|0)<(k|0));h=jb(g)|0;if(!h){a[o+12+9>>0]=57;a[o+12+8>>0]=49;b[o>>1]=d[o+12+8>>0]|d[o+12+8+1>>0]<<8;a[o+2>>0]=0;l=kc(o)|0;m=e+11+l|0;if((f+-11|0)>>>0<=l>>>0){h=-31;break}tc(e+11|0,o|0,l+1|0)|0;if((f+-11-l|0)>>>0>=4){a[m>>0]=36;a[m+1>>0]=109;a[m+2>>0]=61;a[m+3>>0]=0;h=10;j=c[g+44>>2]|0;while(1){k=h+-1|0;a[o+12+k>>0]=(j>>>0)%10|0|48;if(j>>>0>9&(k|0)!=0){h=k;j=(j>>>0)/10|0}else break}h=11-h|0;tc(o|0,o+12+k|0,h|0)|0;a[o+h>>0]=0;h=kc(o)|0;e=m+3+h|0;n=f+-11-l+-3-h|0;if((f+-11-l+-3|0)>>>0<=h>>>0){h=-31;break}tc(m+3|0,o|0,h+1|0)|0;if(n>>>0>=4){a[e>>0]=44;a[e+1>>0]=116;a[e+2>>0]=61;a[e+3>>0]=0;h=10;j=c[g+40>>2]|0;while(1){k=h+-1|0;a[o+12+k>>0]=(j>>>0)%10|0|48;if(j>>>0>9&(k|0)!=0){h=k;j=(j>>>0)/10|0}else break}l=11-h|0;tc(o|0,o+12+k|0,l|0)|0;a[o+l>>0]=0;l=kc(o)|0;m=e+3+l|0;if((n+-3|0)>>>0<=l>>>0){h=-31;break}tc(e+3|0,o|0,l+1|0)|0;if((n+-3-l|0)>>>0>=4){a[m>>0]=44;a[m+1>>0]=112;a[m+2>>0]=61;a[m+3>>0]=0;h=10;j=c[g+48>>2]|0;while(1){k=h+-1|0;a[o+12+k>>0]=(j>>>0)%10|0|48;if(j>>>0>9&(k|0)!=0){h=k;j=(j>>>0)/10|0}else break}j=11-h|0;tc(o|0,o+12+k|0,j|0)|0;a[o+j>>0]=0;j=kc(o)|0;e=m+3+j|0;h=n+-3-l+-3-j|0;if((n+-3-l+-3|0)>>>0<=j>>>0){h=-31;break}tc(m+3|0,o|0,j+1|0)|0;if(c[g+36>>2]|0){if(h>>>0<7){h=-31;break}a[e>>0]=a[32945]|0;a[e+1>>0]=a[32946]|0;a[e+2>>0]=a[32947]|0;a[e+3>>0]=a[32948]|0;a[e+4>>0]=a[32949]|0;a[e+5>>0]=a[32950]|0;a[e+6>>0]=a[32951]|0;j=Lb(e+6|0,h+-6|0,c[g+32>>2]|0,c[g+36>>2]|0)|0;if((j|0)==-1){h=-31;break}else{e=e+6+j|0;h=h+-6-((j|0)==-1?0:j)|0}}if(c[g+20>>2]|0){k=e+1|0;j=h+-1|0;if(h>>>0>=2?(a[e>>0]=36,a[e+1>>0]=0,o=Lb(k,j,c[g+16>>2]|0,c[g+20>>2]|0)|0,q=j-((o|0)==-1?0:o)|0,p=(o|0)==-1?k:k+o|0,(o|0)!=-1):0)if(c[g+4>>2]|0)if(q>>>0<2)h=-31;else{a[p>>0]=36;a[p+1>>0]=0;g=(Lb(p+1|0,q+-1|0,c[g>>2]|0,c[g+4>>2]|0)|0)!=-1;i=r;return (g?0:-31)|0}else h=0;else h=-31}else h=0}else h=-31}else h=-31}else h=-31}}else h=-31;while(0);i=r;return h|0}function Ea(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;if(!b)if(!e){if(f|0){c[f>>2]=(a>>>0)%(d>>>0);c[f+4>>2]=0}e=0;f=(a>>>0)/(d>>>0)>>>0;return (D=e,f)|0}else{if(!f){e=0;f=0;return (D=e,f)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;e=0;f=0;return (D=e,f)|0}do if(d){if(e|0){h=(V(e|0)|0)-(V(b|0)|0)|0;if(h>>>0<=31){n=h+1|0;i=a>>>((h+1|0)>>>0)&h-31>>31|b<<31-h;m=b>>>((h+1|0)>>>0)&h-31>>31;g=0;h=a<<31-h;break}if(!f){e=0;f=0;return (D=e,f)|0}c[f>>2]=a|0;c[f+4>>2]=b|b&0;e=0;f=0;return (D=e,f)|0}if(d-1&d|0){h=(V(d|0)|0)+33-(V(b|0)|0)|0;n=h;i=32-h-1>>31&b>>>((h-32|0)>>>0)|(b<<32-h|a>>>(h>>>0))&h-32>>31;m=h-32>>31&b>>>(h>>>0);g=a<<64-h&32-h>>31;h=(b<<64-h|a>>>((h-32|0)>>>0))&32-h>>31|a<<32-h&h-33>>31;break}if(f|0){c[f>>2]=d-1&a;c[f+4>>2]=0}if((d|0)==1){e=b|b&0;f=a|0|0;return (D=e,f)|0}else{f=id(d|0)|0;e=b>>>(f>>>0)|0;f=b<<32-f|a>>>(f>>>0)|0;return (D=e,f)|0}}else{if(!e){if(f|0){c[f>>2]=(b>>>0)%(d>>>0);c[f+4>>2]=0}e=0;f=(b>>>0)/(d>>>0)>>>0;return (D=e,f)|0}if(!a){if(f|0){c[f>>2]=0;c[f+4>>2]=(b>>>0)%(e>>>0)}d=0;f=(b>>>0)/(e>>>0)>>>0;return (D=d,f)|0}if(!(e-1&e)){if(f|0){c[f>>2]=a|0;c[f+4>>2]=e-1&b|b&0}d=0;f=b>>>((id(e|0)|0)>>>0);return (D=d,f)|0}h=(V(e|0)|0)-(V(b|0)|0)|0;if(h>>>0<=30){n=h+1|0;i=b<<31-h|a>>>((h+1|0)>>>0);m=b>>>((h+1|0)>>>0);g=0;h=a<<31-h;break}if(!f){e=0;f=0;return (D=e,f)|0}c[f>>2]=a|0;c[f+4>>2]=b|b&0;e=0;f=0;return (D=e,f)|0}while(0);if(!n){j=h;b=m;a=0;h=0}else{k=oe(d|0|0,e|e&0|0,-1,-1)|0;l=D;j=h;b=m;a=n;h=0;do{p=j;j=g>>>31|j<<1;g=h|g<<1;p=i<<1|p>>>31|0;o=i>>>31|b<<1|0;le(k|0,l|0,p|0,o|0)|0;n=D;m=n>>31|((n|0)<0?-1:0)<<1;h=m&1;i=le(p|0,o|0,m&(d|0)|0,(((n|0)<0?-1:0)>>31|((n|0)<0?-1:0)<<1)&(e|e&0)|0)|0;b=D;a=a-1|0}while((a|0)!=0);a=0}if(f|0){c[f>>2]=i;c[f+4>>2]=b}o=(g|0)>>>31|j<<1|(0<<1|g>>>31)&0|a;p=(g<<1|0>>>31)&-2|h;return (D=o,p)|0}function Fa(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0;g=i;h=i=i+63&-64;i=i+2400|0;Gb(h+2136|0,d);Gb(h+1880|0,f);Rb(h+480|0,e);bb(h+1760|0,e);dc(h+320|0,h+1760|0);Zc(h,h+320|0);Qb(h+320|0,h,h+480|0);Zc(h+160|0,h+320|0);Rb(h+480+160|0,h+160|0);Qb(h+320|0,h,h+480+160|0);Zc(h+160|0,h+320|0);Rb(h+480+320|0,h+160|0);Qb(h+320|0,h,h+480+320|0);Zc(h+160|0,h+320|0);Rb(h+480+480|0,h+160|0);Qb(h+320|0,h,h+480+480|0);Zc(h+160|0,h+320|0);Rb(h+480+640|0,h+160|0);Qb(h+320|0,h,h+480+640|0);Zc(h+160|0,h+320|0);Rb(h+480+800|0,h+160|0);Qb(h+320|0,h,h+480+800|0);Zc(h+160|0,h+320|0);Rb(h+480+960|0,h+160|0);Qb(h+320|0,h,h+480+960|0);Zc(h+160|0,h+320|0);Rb(h+480+1120|0,h+160|0);d=b;e=d+40|0;do{c[d>>2]=0;d=d+4|0}while((d|0)<(e|0));c[b+40>>2]=1;d=b+44|0;e=d+36|0;do{c[d>>2]=0;d=d+4|0}while((d|0)<(e|0));c[b+80>>2]=1;d=b+84|0;e=d+36|0;do{c[d>>2]=0;d=d+4|0}while((d|0)<(e|0));d=255;while(1){if(a[h+2136+d>>0]|0)break;if(a[h+1880+d>>0]|0)break;e=d+-1|0;if((d|0)>0)d=e;else{d=e;break}}if((d|0)>-1)while(1){dc(h+320|0,b);e=a[h+2136+d>>0]|0;if(e<<24>>24<=0){if(e<<24>>24<0){Zc(h+160|0,h+320|0);Pb(h+320|0,h+160|0,h+480+((((e<<24>>24)/-2|0)<<24>>24)*160|0)|0)}}else{Zc(h+160|0,h+320|0);Qb(h+320|0,h+160|0,h+480+(((e&255)>>>1&255)*160|0)|0)}e=a[h+1880+d>>0]|0;if(e<<24>>24<=0){if(e<<24>>24<0){Zc(h+160|0,h+320|0);Ub(h+320|0,h+160|0,584+((((e<<24>>24)/-2|0)<<24>>24)*120|0)|0)}}else{Zc(h+160|0,h+320|0);Vb(h+320|0,h+160|0,584+(((e&255)>>>1&255)*120|0)|0)}ud(b,h+320|0);if((d|0)>0)d=d+-1|0;else break}i=g;return}function Ga(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0;u=i;v=i=i+63&-64;i=i+64|0;b=v;d=a;e=b+64|0;do{c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}while((b|0)<(e|0));b=0;e=c[v+60>>2]|0;f=c[v+44>>2]|0;g=c[v+12>>2]|0;h=c[v+28>>2]|0;j=c[v>>2]|0;k=c[v+48>>2]|0;l=c[v+16>>2]|0;m=c[v+32>>2]|0;n=c[v+20>>2]|0;d=c[v+4>>2]|0;o=c[v+36>>2]|0;p=c[v+52>>2]|0;q=c[v+40>>2]|0;r=c[v+24>>2]|0;s=c[v+56>>2]|0;t=c[v+8>>2]|0;do{F=k+j|0;F=(F<<7|F>>>25)^l;C=F+j|0;C=(C<<9|C>>>23)^m;z=(C+F<<13|(C+F|0)>>>19)^k;I=(z+C<<18|(z+C|0)>>>14)^j;B=d+n|0;B=(B<<7|B>>>25)^o;y=B+n|0;y=(y<<9|y>>>23)^p;L=(y+B<<13|(y+B|0)>>>19)^d;E=(L+y<<18|(L+y|0)>>>14)^n;x=r+q|0;x=(x<<7|x>>>25)^s;K=x+q|0;K=(K<<9|K>>>23)^t;H=(K+x<<13|(K+x|0)>>>19)^r;A=(H+K<<18|(H+K|0)>>>14)^q;J=f+e|0;J=(J<<7|J>>>25)^g;G=J+e|0;G=(G<<9|G>>>23)^h;D=(G+J<<13|(G+J|0)>>>19)^f;w=(D+G<<18|(D+G|0)>>>14)^e;d=(J+I<<7|(J+I|0)>>>25)^L;L=d+I|0;t=(L<<9|L>>>23)^K;K=t+d|0;g=(K<<13|K>>>19)^J;J=g+t|0;j=(J<<18|J>>>14)^I;r=(F+E<<7|(F+E|0)>>>25)^H;H=r+E|0;h=(H<<9|H>>>23)^G;G=h+r|0;l=(G<<13|G>>>19)^F;F=l+h|0;n=(F<<18|F>>>14)^E;f=(B+A<<7|(B+A|0)>>>25)^D;D=f+A|0;m=(D<<9|D>>>23)^C;C=m+f|0;o=(C<<13|C>>>19)^B;B=o+m|0;q=(B<<18|B>>>14)^A;k=(x+w<<7|(x+w|0)>>>25)^z;z=k+w|0;p=(z<<9|z>>>23)^y;y=p+k|0;s=(y<<13|y>>>19)^x;x=s+p|0;e=(x<<18|x>>>14)^w;b=b+2|0}while(b>>>0<8);c[v>>2]=j;c[v+48>>2]=k;c[v+16>>2]=l;c[v+32>>2]=m;c[v+20>>2]=n;c[v+4>>2]=d;c[v+36>>2]=o;c[v+52>>2]=p;c[v+40>>2]=q;c[v+24>>2]=r;c[v+56>>2]=s;c[v+8>>2]=t;c[v+60>>2]=e;c[v+44>>2]=f;c[v+12>>2]=g;c[v+28>>2]=h;c[a>>2]=(c[a>>2]|0)+j;b=1;while(1){L=a+(b<<2)|0;c[L>>2]=(c[L>>2]|0)+d;b=b+1|0;if((b|0)==16)break;d=c[v+(b<<2)>>2]|0}i=u;return}function Ha(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;g=i;h=i=i+63&-64;i=i+128|0;e=Rd(d<<24>>24|0,((d<<24>>24|0)<0)<<31>>31|0,63)|0;c[a>>2]=1;f=a+4|0;j=f+36|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(j|0));c[a+40>>2]=1;f=a+44|0;j=f+76|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(j|0));o=(d<<24>>24)-((d<<24>>24&0-e)<<1)&255;xd(a,1544+(b*960|0)|0,((o^1)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+120|0,((o^2)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+240|0,((o^3)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+360|0,((o^4)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+480|0,((o^5)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+600|0,((o^6)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+720|0,((o^7)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+840|0,((o^8)+-1|0)>>>31&255);o=c[a+44>>2]|0;n=c[a+48>>2]|0;m=c[a+52>>2]|0;l=c[a+56>>2]|0;k=c[a+60>>2]|0;b=c[a+64>>2]|0;d=c[a+68>>2]|0;f=c[a+72>>2]|0;j=c[a+76>>2]|0;c[h>>2]=c[a+40>>2];c[h+4>>2]=o;c[h+8>>2]=n;c[h+12>>2]=m;c[h+16>>2]=l;c[h+20>>2]=k;c[h+24>>2]=b;c[h+28>>2]=d;c[h+32>>2]=f;c[h+36>>2]=j;j=c[a+4>>2]|0;f=c[a+8>>2]|0;d=c[a+12>>2]|0;b=c[a+16>>2]|0;k=c[a+20>>2]|0;l=c[a+24>>2]|0;m=c[a+28>>2]|0;n=c[a+32>>2]|0;o=c[a+36>>2]|0;c[h+40>>2]=c[a>>2];c[h+44>>2]=j;c[h+48>>2]=f;c[h+52>>2]=d;c[h+56>>2]=b;c[h+60>>2]=k;c[h+64>>2]=l;c[h+68>>2]=m;c[h+72>>2]=n;c[h+76>>2]=o;o=0-(c[a+84>>2]|0)|0;n=0-(c[a+88>>2]|0)|0;m=0-(c[a+92>>2]|0)|0;l=0-(c[a+96>>2]|0)|0;k=0-(c[a+100>>2]|0)|0;b=0-(c[a+104>>2]|0)|0;d=0-(c[a+108>>2]|0)|0;f=0-(c[a+112>>2]|0)|0;j=0-(c[a+116>>2]|0)|0;c[h+80>>2]=0-(c[a+80>>2]|0);c[h+84>>2]=o;c[h+88>>2]=n;c[h+92>>2]=m;c[h+96>>2]=l;c[h+100>>2]=k;c[h+104>>2]=b;c[h+108>>2]=d;c[h+112>>2]=f;c[h+116>>2]=j;xd(a,h,e&255);i=g;return}function Ia(a,b){a=a|0;b=b|0;var c=0,d=0;c=i;d=i=i+63&-64;i=i+160|0;ra(d+120|0,b);ra(d+80|0,d+120|0);ra(d+80|0,d+80|0);pa(d+80|0,b,d+80|0);pa(d+120|0,d+120|0,d+80|0);ra(d+40|0,d+120|0);pa(d+80|0,d+80|0,d+40|0);ra(d+40|0,d+80|0);b=1;do{ra(d+40|0,d+40|0);b=b+1|0}while((b|0)!=5);pa(d+80|0,d+40|0,d+80|0);ra(d+40|0,d+80|0);b=1;do{ra(d+40|0,d+40|0);b=b+1|0}while((b|0)!=10);pa(d+40|0,d+40|0,d+80|0);ra(d,d+40|0);b=1;do{ra(d,d);b=b+1|0}while((b|0)!=20);pa(d+40|0,d,d+40|0);ra(d+40|0,d+40|0);b=1;do{ra(d+40|0,d+40|0);b=b+1|0}while((b|0)!=10);pa(d+80|0,d+40|0,d+80|0);ra(d+40|0,d+80|0);b=1;do{ra(d+40|0,d+40|0);b=b+1|0}while((b|0)!=50);pa(d+40|0,d+40|0,d+80|0);ra(d,d+40|0);b=1;do{ra(d,d);b=b+1|0}while((b|0)!=100);pa(d+40|0,d,d+40|0);ra(d+40|0,d+40|0);b=1;do{ra(d+40|0,d+40|0);b=b+1|0}while((b|0)!=50);pa(d+80|0,d+40|0,d+80|0);ra(d+80|0,d+80|0);b=1;do{ra(d+80|0,d+80|0);b=b+1|0}while((b|0)!=5);pa(a,d+80|0,d+120|0);i=c;return}function Ja(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;k=i;j=i=i+63&-64;i=i+16|0;f=c[b+36>>2]|0;g=c[b+20>>2]|0;h=c[b+4>>2]|0;c[b+36>>2]=0;c[b+20>>2]=0;c[b+4>>2]=0;l=(sc(d,32920,8)|0)==0;d=l?d+8|0:d;a:do if((l?(sc(d,32929,3)|0)==0:0)?(e=jc(d+3|0,j)|0,(e|0)!=0):0)if((c[j>>2]|0)==19)if(!(sc(e,32933,3)|0)){d=jc(e+3|0,j)|0;if(!d){d=-32;break}c[b+44>>2]=c[j>>2];if(!(sc(d,32937,3)|0)){d=jc(d+3|0,j)|0;if(!d){d=-32;break}c[b+40>>2]=c[j>>2];if(!(sc(d,32941,3)|0)){d=jc(d+3|0,j)|0;if(!d){d=-32;break}l=c[j>>2]|0;c[b+48>>2]=l;c[b+52>>2]=l;do if(!(sc(d,32945,6)|0)){c[j>>2]=f;d=ub(c[b+32>>2]|0,j,d+6|0)|0;if(!d){d=-32;break a}else{c[b+36>>2]=c[j>>2];break}}while(0);e=a[d>>0]|0;if(e<<24>>24)if(e<<24>>24==36){c[j>>2]=g;d=ub(c[b+16>>2]|0,j,d+1|0)|0;if(!d){d=-32;break}c[b+20>>2]=c[j>>2];e=a[d>>0]|0;if(e<<24>>24)if(e<<24>>24==36){c[j>>2]=h;e=ub(c[b>>2]|0,j,d+1|0)|0;if(!e){d=-32;break}c[b+4>>2]=c[j>>2];d=jb(b)|0;if(!d)d=(a[e>>0]|0)==0?0:-32}else d=-32;else d=0}else d=-32;else d=0}else d=-32}else d=-32}else d=-32;else d=-26;else d=-32;while(0);i=k;return d|0}function Ka(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;d=i;e=i=i+63&-64;i=i+128|0;ra(e+80|0,b);ra(e+40|0,e+80|0);ra(e+40|0,e+40|0);pa(e+40|0,b,e+40|0);pa(e+80|0,e+80|0,e+40|0);ra(e+80|0,e+80|0);pa(e+80|0,e+40|0,e+80|0);ra(e+40|0,e+80|0);c=1;do{ra(e+40|0,e+40|0);c=c+1|0}while((c|0)!=5);pa(e+80|0,e+40|0,e+80|0);ra(e+40|0,e+80|0);c=1;do{ra(e+40|0,e+40|0);c=c+1|0}while((c|0)!=10);pa(e+40|0,e+40|0,e+80|0);ra(e,e+40|0);c=1;do{ra(e,e);c=c+1|0}while((c|0)!=20);pa(e+40|0,e,e+40|0);ra(e+40|0,e+40|0);c=1;do{ra(e+40|0,e+40|0);c=c+1|0}while((c|0)!=10);pa(e+80|0,e+40|0,e+80|0);ra(e+40|0,e+80|0);c=1;do{ra(e+40|0,e+40|0);c=c+1|0}while((c|0)!=50);pa(e+40|0,e+40|0,e+80|0);ra(e,e+40|0);c=1;do{ra(e,e);c=c+1|0}while((c|0)!=100);pa(e+40|0,e,e+40|0);ra(e+40|0,e+40|0);c=1;do{ra(e+40|0,e+40|0);c=c+1|0}while((c|0)!=50);pa(e+80|0,e+40|0,e+80|0);ra(e+80|0,e+80|0);ra(e+80|0,e+80|0);pa(a,e+80|0,b);i=d;return}function La(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;m=c[d>>2]|0;h=c[d+4>>2]|0;i=c[d+8>>2]|0;j=c[d+12>>2]|0;p=c[d+16>>2]|0;f=c[d+20>>2]|0;g=c[d+24>>2]|0;n=c[d+28>>2]|0;e=c[d+32>>2]|0;d=c[d+36>>2]|0;o=((((((((((((((d*19|0)+16777216|0)>>>25)+m>>26)+h>>25)+i>>26)+j>>25)+p>>26)+f>>25)+g>>26)+n>>25)+e>>26)+d>>25)*19|0)+m>>26;m=((((((((((((((d*19|0)+16777216|0)>>>25)+m>>26)+h>>25)+i>>26)+j>>25)+p>>26)+f>>25)+g>>26)+n>>25)+e>>26)+d>>25)*19|0)+m-(o<<26)|0;l=o+h-(o+h>>25<<25)|0;k=(o+h>>25)+i-((o+h>>25)+i>>26<<26)|0;q=((o+h>>25)+i>>26)+j>>25;j=((o+h>>25)+i>>26)+j-(q<<25)|0;i=q+p-(q+p>>26<<26)|0;h=(q+p>>26)+f-((q+p>>26)+f>>25<<25)|0;o=((q+p>>26)+f>>25)+g>>26;g=((q+p>>26)+f>>25)+g-(o<<26)|0;f=o+n-(o+n>>25<<25)|0;d=((o+n>>25)+e>>26)+d|0;e=(o+n>>25)+e-((o+n>>25)+e>>26<<26)|0;a[b>>0]=m;a[b+1>>0]=m>>>8;a[b+2>>0]=m>>>16;a[b+3>>0]=l<<2|m>>>24;a[b+4>>0]=l>>>6;a[b+5>>0]=l>>>14;a[b+6>>0]=k<<3|l>>>22;a[b+7>>0]=k>>>5;a[b+8>>0]=k>>>13;a[b+9>>0]=j<<5|k>>>21;a[b+10>>0]=j>>>3;a[b+11>>0]=j>>>11;a[b+12>>0]=i<<6|j>>>19;a[b+13>>0]=i>>>2;a[b+14>>0]=i>>>10;a[b+15>>0]=i>>>18;a[b+16>>0]=h;a[b+17>>0]=h>>>8;a[b+18>>0]=h>>>16;a[b+19>>0]=g<<1|h>>>24;a[b+20>>0]=g>>>7;a[b+21>>0]=g>>>15;a[b+22>>0]=f<<3|g>>>23;a[b+23>>0]=f>>>5;a[b+24>>0]=f>>>13;a[b+25>>0]=e<<4|f>>>21;a[b+26>>0]=e>>>4;a[b+27>>0]=e>>>12;a[b+28>>0]=e>>>20|(d&33554431)<<6;a[b+29>>0]=d>>>2;a[b+30>>0]=d>>>10;a[b+31>>0]=(d&33554431)>>>18;return}function Ma(b,e,f,g,h,j,k,l){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;var m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;s=i;t=i=i+63&-64;i=i+112|0;if(!((f|0)==0&(g|0)==0)){n=t+16|0;m=n+32|0;do{a[n>>0]=a[l>>0]|0;n=n+1|0;l=l+1|0}while((n|0)<(m|0));n=d[h+4>>0]|d[h+4+1>>0]<<8|d[h+4+2>>0]<<16|d[h+4+3>>0]<<24;c[t>>2]=d[h>>0]|d[h+1>>0]<<8|d[h+2>>0]<<16|d[h+3>>0]<<24;c[t+4>>2]=n;a[t+8>>0]=j;n=Rd(j|0,k|0,8)|0;a[t+9>>0]=n;n=Rd(j|0,k|0,16)|0;a[t+10>>0]=n;n=Rd(j|0,k|0,24)|0;a[t+11>>0]=n;a[t+12>>0]=k;n=Rd(j|0,k|0,40)|0;a[t+13>>0]=n;n=Rd(j|0,k|0,48)|0;a[t+14>>0]=n;n=Rd(j|0,k|0,56)|0;a[t+15>>0]=n;if(g>>>0>0|(g|0)==0&f>>>0>63){do{xa(t+48|0,t,t+16|0,0)|0;l=0;do{a[b+l>>0]=a[t+48+l>>0]^a[e+l>>0];l=l+1|0}while((l|0)!=64);l=1;m=8;while(1){n=t+m|0;l=(d[n>>0]|0)+l|0;a[n>>0]=l;m=m+1|0;if((m|0)==16)break;else l=l>>>8}f=oe(f|0,g|0,-64,-1)|0;g=D;b=b+64|0;e=e+64|0}while(g>>>0>0|(g|0)==0&f>>>0>63);if(!((f|0)==0&(g|0)==0)){p=b;q=f;r=e;o=8}}else{p=b;q=f;r=e;o=8}if((o|0)==8?(xa(t+48|0,t,t+16|0,0)|0,q|0):0){l=0;do{a[p+l>>0]=a[t+48+l>>0]^a[r+l>>0];l=l+1|0}while((l|0)!=(q|0))}fd(t+48|0,64);fd(t+16|0,32)}i=s;return 0}function Na(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;o=c[b+72>>2]|0;m=c[b+72+4>>2]|0;k=Rd(o|0,m|0,3)|0;l=Pd(e|0,f|0,3)|0;n=D;i=Rd(e|0,f|0,61)|0;j=D;m=oe(o|0,m|0,l|0,n|0)|0;o=D;c[b+72>>2]=m;c[b+72+4>>2]=o;g=c[b+64>>2]|0;h=c[b+64+4>>2]|0;if(o>>>0<n>>>0|(o|0)==(n|0)&m>>>0<l>>>0){g=oe(g|0,h|0,1,0)|0;h=D;c[b+64>>2]=g;c[b+64+4>>2]=h}j=oe(g|0,h|0,i|0,j|0)|0;c[b+64>>2]=j;c[b+64+4>>2]=D;j=le(128,0,k&127|0,0)|0;g=D;if(g>>>0>f>>>0|(g|0)==(f|0)&j>>>0>e>>>0){if(!((e|0)==0&(f|0)==0)){g=0;h=0;do{n=a[d+g>>0]|0;o=oe(g|0,h|0,k&127|0,0)|0;a[b+80+o>>0]=n;g=oe(g|0,h|0,1,0)|0;h=D}while(h>>>0<f>>>0|(h|0)==(f|0)&g>>>0<e>>>0)}}else{if(!((j|0)==0&(g|0)==0)){h=0;i=0;do{n=a[d+h>>0]|0;o=oe(h|0,i|0,k&127|0,0)|0;a[b+80+o>>0]=n;h=oe(h|0,i|0,1,0)|0;i=D}while(i>>>0<g>>>0|(i|0)==(g|0)&h>>>0<j>>>0)}ha(b,b+80|0);g=le(e|0,f|0,j|0,g|0)|0;h=D;if(h>>>0>0|(h|0)==0&g>>>0>127){i=d+j|0;do{ha(b,i);i=i+128|0;g=oe(g|0,h|0,-128,-1)|0;h=D}while(h>>>0>0|(h|0)==0&g>>>0>127);j=i}else j=d+j|0;g=g&127;if(!((g|0)==0&0==0)){h=0;i=0;do{a[b+80+h>>0]=a[j+h>>0]|0;h=oe(h|0,i|0,1,0)|0;i=D}while(i>>>0<0|(i|0)==0&h>>>0<g>>>0)}}return 0}function Oa(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;f=c[b+56>>2]|0;g=c[b+56+4>>2]|0;if(!((f|0)==0&(g|0)==0)){a[b+64+f>>0]=1;e=oe(f|0,g|0,1,0)|0;h=D;if(h>>>0<0|(h|0)==0&e>>>0<16){h=le(14,0,f|0,g|0)|0;Hc(b+64+e|0,0,h+1|0)|0}a[b+80>>0]=1;Ba(b,b+64|0,16,0)}g=c[b+24>>2]|0;h=(c[b+28>>2]|0)+(g>>>26)|0;k=(h>>>26)+(c[b+32>>2]|0)|0;i=(k>>>26)+(c[b+36>>2]|0)|0;e=((i>>>26)*5|0)+(c[b+20>>2]|0)|0;l=((((e&67108863)+5|0)>>>26)+((e>>>26)+(g&67108863))|0)>>>26;j=(i|-67108864)+((((l+(h&67108863)|0)>>>26)+(k&67108863)|0)>>>26)|0;g=(((e&67108863)+5|0)>>>26)+((e>>>26)+(g&67108863))&67108863&(j>>>31)+-1|j>>31&(e>>>26)+(g&67108863);k=((l+(h&67108863)|0)>>>26)+k&67108863&(j>>>31)+-1|j>>31&(k&67108863);e=oe(e+5&67108863&(j>>>31)+-1|j>>31&(e&67108863)|g<<26|0,0,c[b+40>>2]|0,0)|0;f=D;g=oe(g>>>6|(l+h&67108863&(j>>>31)+-1|j>>31&(h&67108863))<<20|0,0,c[b+44>>2]|0,0)|0;f=oe(g|0,D|0,f|0,0)|0;g=D;h=oe((l+h&67108863&(j>>>31)+-1|j>>31&(h&67108863))>>>12|k<<14|0,0,c[b+48>>2]|0,0)|0;g=oe(h|0,D|0,g|0,0)|0;h=D;i=oe(k>>>18|((j>>>31)+-1&j|j>>31&i)<<8|0,0,c[b+52>>2]|0,0)|0;h=oe(i|0,D|0,h|0,0)|0;a[d>>0]=e;a[d+1>>0]=e>>8;a[d+2>>0]=e>>16;a[d+3>>0]=e>>24;a[d+4>>0]=f;a[d+4+1>>0]=f>>8;a[d+4+2>>0]=f>>16;a[d+4+3>>0]=f>>24;a[d+8>>0]=g;a[d+8+1>>0]=g>>8;a[d+8+2>>0]=g>>16;a[d+8+3>>0]=g>>24;a[d+12>>0]=h;a[d+12+1>>0]=h>>8;a[d+12+2>>0]=h>>16;a[d+12+3>>0]=h>>24;fd(b,88);return}function Pa(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0;g=i;h=i=i+63&-64;i=i+592|0;f=0;do{k=a[e+f>>0]|0;j=f<<1;a[h+520+j>>0]=k&15;a[h+520+(j|1)>>0]=(k&255)>>>4;f=f+1|0}while((f|0)!=32);f=0;e=0;do{k=h+520+e|0;j=(d[k>>0]|0)+f|0;f=(j<<24)+134217728>>28;a[k>>0]=j-(f<<4);e=e+1|0}while((e|0)!=63);a[h+520+63>>0]=(d[h+520+63>>0]|0)+f;f=b;e=f+40|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(e|0));c[b+40>>2]=1;f=b+44|0;e=f+36|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(e|0));c[b+80>>2]=1;f=b+84|0;e=f+76|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(e|0));f=1;do{Ha(h,(f|0)/2|0,a[h+520+f>>0]|0);Vb(h+240|0,b,h);Zc(b,h+240|0);f=f+2|0}while((f|0)<64);bb(h+400|0,b);dc(h+240|0,h+400|0);ud(h+120|0,h+240|0);dc(h+240|0,h+120|0);ud(h+120|0,h+240|0);dc(h+240|0,h+120|0);ud(h+120|0,h+240|0);dc(h+240|0,h+120|0);Zc(b,h+240|0);f=0;do{Ha(h,(f|0)/2|0,a[h+520+f>>0]|0);Vb(h+240|0,b,h);Zc(b,h+240|0);f=f+2|0}while((f|0)<64);i=g;return}function Qa(b,e,f,g,h,j){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0;m=i;n=i=i+63&-64;i=i+192|0;if((e+-1&255)>63)ba();if((f|0)!=0&g<<24>>24!=0?(g&255)<=64:0){a[n+128>>0]=e;a[n+128+1>>0]=g;a[n+128+2>>0]=1;a[n+128+3>>0]=1;k=n+128+4|0;l=k+28|0;do{a[k>>0]=0;k=k+1|0}while((k|0)<(l|0));if(!h){k=n+128+32|0;l=k+16|0;do{a[k>>0]=0;k=k+1|0}while((k|0)<(l|0))}else{k=n+128+32|0;e=h;l=k+16|0;do{a[k>>0]=a[e>>0]|0;k=k+1|0;e=e+1|0}while((k|0)<(l|0))}if(!j){k=n+128+48|0;l=k+16|0;do{a[k>>0]=0;k=k+1|0}while((k|0)<(l|0))}else{k=n+128+48|0;e=j;l=k+16|0;do{a[k>>0]=a[e>>0]|0;k=k+1|0;e=e+1|0}while((k|0)<(l|0))}Hc(b+64|0,0,293)|0;k=b;e=400;l=k+64|0;do{c[k>>2]=c[e>>2];k=k+4|0;e=e+4|0}while((k|0)<(l|0));e=0;do{k=n+128+(e<<3)|0;j=b+(e<<3)|0;l=c[j+4>>2]^(d[k+4>>0]|d[k+4+1>>0]<<8|d[k+4+2>>0]<<16|d[k+4+3>>0]<<24);c[j>>2]=c[j>>2]^(d[k>>0]|d[k+1>>0]<<8|d[k+2>>0]<<16|d[k+3>>0]<<24);c[j+4>>2]=l;e=e+1|0}while((e|0)!=8);Hc(n+(g&255)|0,0,(g<<24>>24<0?0:128-(g&255)|0)|0)|0;tc(n|0,f|0,g&255|0)|0;ib(b,n,128,0);fd(n,128);i=m;return}ba()}function Ra(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;h=c[b+56>>2]|0;g=c[b+56+4>>2]|0;if(!((h|0)==0&(g|0)==0)){j=le(16,0,h|0,g|0)|0;l=D;k=l>>>0>f>>>0|(l|0)==(f|0)&j>>>0>e>>>0?e:j;l=l>>>0>f>>>0|(l|0)==(f|0)&j>>>0>e>>>0?f:l;if(!((k|0)==0&(l|0)==0)){j=0;i=0;do{n=a[d+j>>0]|0;h=oe(h|0,g|0,j|0,i|0)|0;a[b+64+h>>0]=n;j=oe(j|0,i|0,1,0)|0;i=D;h=c[b+56>>2]|0;g=c[b+56+4>>2]|0}while(i>>>0<l>>>0|(i|0)==(l|0)&j>>>0<k>>>0)}n=oe(h|0,g|0,k|0,l|0)|0;j=D;c[b+56>>2]=n;c[b+56+4>>2]=j;if(!(j>>>0<0|(j|0)==0&n>>>0<16)){e=le(e|0,f|0,k|0,l|0)|0;f=D;Ba(b,b+64|0,16,0);c[b+56>>2]=0;c[b+56+4>>2]=0;d=d+k|0;m=6}}else m=6;if((m|0)==6){g=e&-16;if(f>>>0>0|(f|0)==0&e>>>0>15){h=le(e|0,f|0,g|0,f|0)|0;n=D;Ba(b,d,g,f);i=d+g|0;g=n}else{i=d;h=e;g=f}if(!((h|0)==0&(g|0)==0)){e=0;d=0;do{m=a[i+e>>0]|0;n=oe(c[b+56>>2]|0,c[b+56+4>>2]|0,e|0,d|0)|0;a[b+64+n>>0]=m;e=oe(e|0,d|0,1,0)|0;d=D}while(d>>>0<g>>>0|(d|0)==(g|0)&e>>>0<h>>>0);n=oe(c[b+56>>2]|0,c[b+56+4>>2]|0,h|0,g|0)|0;c[b+56>>2]=n;c[b+56+4>>2]=D}}return}function Sa(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=i;f=i=i+63&-64;i=i+368|0;if(!((a|0)==0|(b|0)==0)){yc(f,0,0,64)|0;c[f+360>>2]=c[b+48>>2];ue(f,f+360|0,4,0)|0;c[f+360>>2]=c[b+4>>2];ue(f,f+360|0,4,0)|0;c[f+360>>2]=c[b+44>>2];ue(f,f+360|0,4,0)|0;c[f+360>>2]=c[b+40>>2];ue(f,f+360|0,4,0)|0;c[f+360>>2]=19;ue(f,f+360|0,4,0)|0;c[f+360>>2]=d;ue(f,f+360|0,4,0)|0;c[f+360>>2]=c[b+12>>2];ue(f,f+360|0,4,0)|0;d=c[b+8>>2]|0;if(d|0?(ue(f,d,c[b+12>>2]|0,0)|0,c[b+56>>2]&1|0):0){fd(c[b+8>>2]|0,c[b+12>>2]|0);c[b+12>>2]=0}c[f+360>>2]=c[b+20>>2];ue(f,f+360|0,4,0)|0;d=c[b+16>>2]|0;if(d|0)ue(f,d,c[b+20>>2]|0,0)|0;c[f+360>>2]=c[b+28>>2];ue(f,f+360|0,4,0)|0;d=c[b+24>>2]|0;if(d|0?(ue(f,d,c[b+28>>2]|0,0)|0,c[b+56>>2]&2|0):0){fd(c[b+24>>2]|0,c[b+28>>2]|0);c[b+28>>2]=0}c[f+360>>2]=c[b+36>>2];ue(f,f+360|0,4,0)|0;d=c[b+32>>2]|0;if(d|0)ue(f,d,c[b+36>>2]|0,0)|0;Fd(f,a,64)|0}i=e;return}function Ta(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0;k=i;l=i=i+63&-64;i=i+496|0;c[l+360>>2]=d;if(d>>>0<65){if((yc(l,0,0,d)|0)>=0){ue(l,l+360|0,4,0)|0;ue(l,e,f,0)|0;Fd(l,b,d)|0}}else a:do if((yc(l,0,0,64)|0)>=0?(ue(l,l+360|0,4,0)|0,ue(l,e,f,0)|0,(Fd(l,l+432|0,64)|0)>=0):0){g=b;h=l+432|0;j=g+32|0;do{a[g>>0]=a[h>>0]|0;g=g+1|0;h=h+1|0}while((g|0)<(j|0));g=l+368|0;h=l+432|0;j=g+64|0;do{a[g>>0]=a[h>>0]|0;g=g+1|0;h=h+1|0}while((g|0)<(j|0));if((d+-32|0)>>>0>64){f=d+-32|0;e=b+32|0;do{if((Cc(l+432|0,64,l+368|0,64,0,0,0)|0)<0)break a;g=e;h=l+432|0;j=g+32|0;do{a[g>>0]=a[h>>0]|0;g=g+1|0;h=h+1|0}while((g|0)<(j|0));f=f+-32|0;e=e+32|0;g=l+368|0;h=l+432|0;j=g+64|0;do{a[g>>0]=a[h>>0]|0;g=g+1|0;h=h+1|0}while((g|0)<(j|0))}while(f>>>0>64)}else{f=d+-32|0;e=b+32|0}if((Cc(l+432|0,f,l+368|0,64,0,0,0)|0)>=0)tc(e|0,l+432|0,f|0)|0}while(0);fd(l,357);i=k;return}function Ua(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0;a:do if(!((e|0)==0&(f|0)==0)){j=c[b+32>>2]|0;g=c[b+32+4>>2]|0;i=Rd(j|0,g|0,3)|0;h=Pd(e|0,f|0,3)|0;h=oe(j|0,g|0,h|0,D|0)|0;c[b+32>>2]=h;c[b+32+4>>2]=D;if(0>f>>>0|0==(f|0)&(64-(i&63)|0)>>>0>e>>>0){g=0;h=0;while(1){k=a[d+g>>0]|0;j=oe(g|0,h|0,i&63|0,0)|0;a[b+40+j>>0]=k;g=oe(g|0,h|0,1,0)|0;h=D;if(!(h>>>0<f>>>0|(h|0)==(f|0)&g>>>0<e>>>0))break a}}if(64-(i&63)|0){g=0;h=0;do{j=a[d+g>>0]|0;k=oe(g|0,h|0,i&63|0,0)|0;a[b+40+k>>0]=j;g=oe(g|0,h|0,1,0)|0;h=D}while(h>>>0<0|(h|0)==0&g>>>0<(64-(i&63)|0)>>>0)}ka(b,b+40|0);g=le(e|0,f|0,64-(i&63)|0,0)|0;h=D;if(h>>>0>0|(h|0)==0&g>>>0>63){e=d+(64-(i&63))|0;do{ka(b,e);e=e+64|0;g=oe(g|0,h|0,-64,-1)|0;h=D}while(h>>>0>0|(h|0)==0&g>>>0>63);f=e}else f=d+(64-(i&63))|0;g=g&63;if(!((g|0)==0&0==0)){h=0;e=0;do{a[b+40+h>>0]=a[f+h>>0]|0;h=oe(h|0,e|0,1,0)|0;e=D}while(e>>>0<0|(e|0)==0&h>>>0<g>>>0)}}while(0);return 0}function Va(a,b,e,f,g,h,j){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0;k=i;l=i=i+63&-64;i=i+64|0;if(!((e|0)==0&(f|0)==0)){c[l>>2]=1634760805;c[l+4>>2]=857760878;c[l+8>>2]=2036477234;c[l+12>>2]=1797285236;c[l+16>>2]=d[j>>0]|d[j+1>>0]<<8|d[j+2>>0]<<16|d[j+3>>0]<<24;c[l+20>>2]=d[j+4>>0]|d[j+4+1>>0]<<8|d[j+4+2>>0]<<16|d[j+4+3>>0]<<24;c[l+24>>2]=d[j+8>>0]|d[j+8+1>>0]<<8|d[j+8+2>>0]<<16|d[j+8+3>>0]<<24;c[l+28>>2]=d[j+12>>0]|d[j+12+1>>0]<<8|d[j+12+2>>0]<<16|d[j+12+3>>0]<<24;c[l+32>>2]=d[j+16>>0]|d[j+16+1>>0]<<8|d[j+16+2>>0]<<16|d[j+16+3>>0]<<24;c[l+36>>2]=d[j+20>>0]|d[j+20+1>>0]<<8|d[j+20+2>>0]<<16|d[j+20+3>>0]<<24;c[l+40>>2]=d[j+24>>0]|d[j+24+1>>0]<<8|d[j+24+2>>0]<<16|d[j+24+3>>0]<<24;c[l+44>>2]=d[j+28>>0]|d[j+28+1>>0]<<8|d[j+28+2>>0]<<16|d[j+28+3>>0]<<24;c[l+48>>2]=h;c[l+52>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;c[l+56>>2]=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;c[l+60>>2]=d[g+8>>0]|d[g+8+1>>0]<<8|d[g+8+2>>0]<<16|d[g+8+3>>0]<<24;va(l,b,a,e,f);fd(l,64)}i=k;return 0}function Wa(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;h=i;j=i=i+63&-64;i=i+64|0;if(!((b|0)==0&(e|0)==0)){c[j>>2]=1634760805;c[j+4>>2]=857760878;c[j+8>>2]=2036477234;c[j+12>>2]=1797285236;c[j+16>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;c[j+20>>2]=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;c[j+24>>2]=d[g+8>>0]|d[g+8+1>>0]<<8|d[g+8+2>>0]<<16|d[g+8+3>>0]<<24;c[j+28>>2]=d[g+12>>0]|d[g+12+1>>0]<<8|d[g+12+2>>0]<<16|d[g+12+3>>0]<<24;c[j+32>>2]=d[g+16>>0]|d[g+16+1>>0]<<8|d[g+16+2>>0]<<16|d[g+16+3>>0]<<24;c[j+36>>2]=d[g+20>>0]|d[g+20+1>>0]<<8|d[g+20+2>>0]<<16|d[g+20+3>>0]<<24;c[j+40>>2]=d[g+24>>0]|d[g+24+1>>0]<<8|d[g+24+2>>0]<<16|d[g+24+3>>0]<<24;c[j+44>>2]=d[g+28>>0]|d[g+28+1>>0]<<8|d[g+28+2>>0]<<16|d[g+28+3>>0]<<24;c[j+48>>2]=0;c[j+52>>2]=d[f>>0]|d[f+1>>0]<<8|d[f+2>>0]<<16|d[f+3>>0]<<24;c[j+56>>2]=d[f+4>>0]|d[f+4+1>>0]<<8|d[f+4+2>>0]<<16|d[f+4+3>>0]<<24;c[j+60>>2]=d[f+8>>0]|d[f+8+1>>0]<<8|d[f+8+2>>0]<<16|d[f+8+3>>0]<<24;Hc(a|0,0,b|0)|0;va(j,a,a,b,e);fd(j,64)}i=h;return 0}function Xa(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0;n=i;m=i=i+63&-64;i=i+592|0;h=32;g=1;j=0;while(1){h=h+-1|0;k=a[b+32+h>>0]|0;l=a[33097+h>>0]|0;g=g&255;j=((k&255)-(l&255)|0)>>>8&g|j&255;if(!h)break;else g=(((l^k)&255)+65535|0)>>>8&g}a:do if(j){h=0;do{g=0;j=0;do{j=a[16+(h<<5)+g>>0]^a[b+g>>0]|j;g=g+1|0}while((g|0)!=32);h=h+1|0;if(!(j<<24>>24)){g=-1;break a}}while(h>>>0<12);if(!(za(m+328|0,f)|0)){g=0;h=0;do{h=a[f+g>>0]|h;g=g+1|0}while((g|0)!=32);if(h<<24>>24){nd(m)|0;Na(m,b,32,0)|0;Na(m,f,32,0)|0;Na(m,c,d,e)|0;rc(m,m+520|0)|0;oa(m+520|0);Fa(m+208|0,m+520|0,m+328|0,b+32|0);vc(m+488|0,m+208|0);g=zd(m+488|0,b)|0;g=((m+488|0)==(b|0)?-1:g)|(Dc(b,m+488|0,32)|0)}else g=-1}else g=-1}else g=-1;while(0);i=n;return g|0}function Ya(b,c,d,e,f,g,h){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0;k=i;l=i=i+63&-64;i=i+352|0;Aa(l+256|0,g,h,0)|0;if(b>>>0>=d>>>0?0<f>>>0|0==(f|0)&(b-d|0)>>>0<e>>>0:0)j=5;else if(d>>>0>=b>>>0?0<f>>>0|0==(f|0)&(d-b|0)>>>0<e>>>0:0)j=5;if((j|0)==5){Xc(b|0,d|0,e|0)|0;d=b}h=l+288|0;j=h+32|0;do{a[h>>0]=0;h=h+1|0}while((h|0)<(j|0));h=f>>>0>0|(f|0)==0&e>>>0>32?32:e;j=f>>>0>0|(f|0)==0&e>>>0>32?0:f;if(!((h|0)==0&(j|0)==0)){m=oe((f>>>0<0|(f|0)==0&e>>>0<32?e:32)|0,(f>>>0<0|(f|0)==0&e>>>0<32?f:0)|0,-1,0)|0;tc(l+288+32|0,d|0,m+1|0)|0}m=oe(h|0,j|0,32,0)|0;Wd(l+288|0,l+288|0,m,D,g+16|0,l+256|0)|0;Se(l,l+288|0)|0;if(!((h|0)==0&(j|0)==0)){m=oe((f>>>0<0|(f|0)==0&e>>>0<32?e:32)|0,(f>>>0<0|(f|0)==0&e>>>0<32?f:0)|0,-1,0)|0;tc(b|0,l+288+32|0,m+1|0)|0}fd(l+288|0,64);if(f>>>0>0|(f|0)==0&e>>>0>32){m=le(e|0,f|0,h|0,j|0)|0;Ma(b+h|0,d+h|0,m,D,g+16|0,1,0,l+256|0)|0}fd(l+256|0,32);ne(l,b,e,f)|0;Re(l,c)|0;fd(l,256);i=k;return 0}function Za(a,b,e,f,g,h,j,k){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0;l=i;m=i=i+63&-64;i=i+64|0;if(!((e|0)==0&(f|0)==0)){c[m>>2]=1634760805;c[m+4>>2]=857760878;c[m+8>>2]=2036477234;c[m+12>>2]=1797285236;c[m+16>>2]=d[k>>0]|d[k+1>>0]<<8|d[k+2>>0]<<16|d[k+3>>0]<<24;c[m+20>>2]=d[k+4>>0]|d[k+4+1>>0]<<8|d[k+4+2>>0]<<16|d[k+4+3>>0]<<24;c[m+24>>2]=d[k+8>>0]|d[k+8+1>>0]<<8|d[k+8+2>>0]<<16|d[k+8+3>>0]<<24;c[m+28>>2]=d[k+12>>0]|d[k+12+1>>0]<<8|d[k+12+2>>0]<<16|d[k+12+3>>0]<<24;c[m+32>>2]=d[k+16>>0]|d[k+16+1>>0]<<8|d[k+16+2>>0]<<16|d[k+16+3>>0]<<24;c[m+36>>2]=d[k+20>>0]|d[k+20+1>>0]<<8|d[k+20+2>>0]<<16|d[k+20+3>>0]<<24;c[m+40>>2]=d[k+24>>0]|d[k+24+1>>0]<<8|d[k+24+2>>0]<<16|d[k+24+3>>0]<<24;c[m+44>>2]=d[k+28>>0]|d[k+28+1>>0]<<8|d[k+28+2>>0]<<16|d[k+28+3>>0]<<24;c[m+48>>2]=h;c[m+52>>2]=j;c[m+56>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;c[m+60>>2]=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;va(m,b,a,e,f);fd(m,64)}i=l;return 0}function _a(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;k=i;l=i=i+63&-64;i=i+1024|0;if(c[e+20>>2]|0){j=0;do{a[b+64>>0]=0;a[b+64+1>>0]=0;a[b+64+2>>0]=0;a[b+64+3>>0]=0;a[b+68>>0]=j;a[b+68+1>>0]=j>>8;a[b+68+2>>0]=j>>16;a[b+68+3>>0]=j>>24;Ta(l,1024,b,72);g=S(c[e+16>>2]|0,j)|0;h=c[(c[e>>2]|0)+4>>2]|0;f=0;do{o=l+(f<<3)|0;n=d[o+4>>0]|d[o+4+1>>0]<<8|d[o+4+2>>0]<<16|d[o+4+3>>0]<<24;m=h+(g<<10)+(f<<3)|0;c[m>>2]=d[o>>0]|d[o+1>>0]<<8|d[o+2>>0]<<16|d[o+3>>0]<<24;c[m+4>>2]=n;f=f+1|0}while((f|0)!=128);a[b+64>>0]=1;a[b+64+1>>0]=0;a[b+64+2>>0]=0;a[b+64+3>>0]=0;Ta(l,1024,b,72);g=(S(c[e+16>>2]|0,j)|0)+1|0;h=c[(c[e>>2]|0)+4>>2]|0;f=0;do{m=l+(f<<3)|0;n=d[m+4>>0]|d[m+4+1>>0]<<8|d[m+4+2>>0]<<16|d[m+4+3>>0]<<24;o=h+(g<<10)+(f<<3)|0;c[o>>2]=d[m>>0]|d[m+1>>0]<<8|d[m+2>>0]<<16|d[m+3>>0]<<24;c[o+4>>2]=n;f=f+1|0}while((f|0)!=128);j=j+1|0}while(j>>>0<(c[e+20>>2]|0)>>>0)}fd(l,1024);i=k;return}function $a(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;h=i;j=i=i+63&-64;i=i+64|0;if(!((b|0)==0&(e|0)==0)){c[j>>2]=1634760805;c[j+4>>2]=857760878;c[j+8>>2]=2036477234;c[j+12>>2]=1797285236;c[j+16>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;c[j+20>>2]=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;c[j+24>>2]=d[g+8>>0]|d[g+8+1>>0]<<8|d[g+8+2>>0]<<16|d[g+8+3>>0]<<24;c[j+28>>2]=d[g+12>>0]|d[g+12+1>>0]<<8|d[g+12+2>>0]<<16|d[g+12+3>>0]<<24;c[j+32>>2]=d[g+16>>0]|d[g+16+1>>0]<<8|d[g+16+2>>0]<<16|d[g+16+3>>0]<<24;c[j+36>>2]=d[g+20>>0]|d[g+20+1>>0]<<8|d[g+20+2>>0]<<16|d[g+20+3>>0]<<24;c[j+40>>2]=d[g+24>>0]|d[g+24+1>>0]<<8|d[g+24+2>>0]<<16|d[g+24+3>>0]<<24;c[j+44>>2]=d[g+28>>0]|d[g+28+1>>0]<<8|d[g+28+2>>0]<<16|d[g+28+3>>0]<<24;c[j+48>>2]=0;c[j+52>>2]=0;c[j+56>>2]=d[f>>0]|d[f+1>>0]<<8|d[f+2>>0]<<16|d[f+3>>0]<<24;c[j+60>>2]=d[f+4>>0]|d[f+4+1>>0]<<8|d[f+4+2>>0]<<16|d[f+4+3>>0]<<24;Hc(a|0,0,b|0)|0;va(j,a,a,b,e);fd(j,64)}i=h;return 0}function ab(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;if(e<<24>>24?(e&255)<=64:0){if((c[b+80>>2]|0)==0?(c[b+80+4>>2]|0)==0:0){f=c[b+352>>2]|0;do if(f>>>0>128){f=c[b+64>>2]|0;i=c[b+64+4>>2]|0;j=oe(f|0,i|0,128,0)|0;c[b+64>>2]=j;c[b+64+4>>2]=D;f=oe((i>>>0>4294967295|(i|0)==-1&f>>>0>4294967167)&1|0,0,c[b+72>>2]|0,c[b+72+4>>2]|0)|0;c[b+72>>2]=f;c[b+72+4>>2]=D;ia(b,b+96|0);f=(c[b+352>>2]|0)+-128|0;c[b+352>>2]=f;if(f>>>0<129){tc(b+96|0,b+224|0,f|0)|0;g=b+72|0;h=c[b+352>>2]|0;break}else fa(32331,32363,343,32407)}else{g=b+72|0;h=f}while(0);j=oe(c[b+64>>2]|0,c[b+64+4>>2]|0,h|0,0)|0;f=D;c[b+64>>2]=j;c[b+64+4>>2]=f;i=g;i=oe((f>>>0<0|(f|0)==0&j>>>0<h>>>0)&1|0,0,c[i>>2]|0,c[i+4>>2]|0)|0;j=g;c[j>>2]=i;c[j+4>>2]=D;if(a[b+356>>0]|0){c[b+88>>2]=-1;c[b+88+4>>2]=-1}c[b+80>>2]=-1;c[b+80+4>>2]=-1;Hc(b+96+h|0,0,256-h|0)|0;ia(b,b+96|0);tc(d|0,b|0,e&255|0)|0;f=0}else f=-1;return f|0}ba();return 0}function bb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;l=c[b+4>>2]|0;k=c[b+8>>2]|0;j=c[b+12>>2]|0;i=c[b+16>>2]|0;h=c[b+20>>2]|0;g=c[b+24>>2]|0;f=c[b+28>>2]|0;e=c[b+32>>2]|0;d=c[b+36>>2]|0;c[a>>2]=c[b>>2];c[a+4>>2]=l;c[a+8>>2]=k;c[a+12>>2]=j;c[a+16>>2]=i;c[a+20>>2]=h;c[a+24>>2]=g;c[a+28>>2]=f;c[a+32>>2]=e;c[a+36>>2]=d;d=c[b+44>>2]|0;e=c[b+48>>2]|0;f=c[b+52>>2]|0;g=c[b+56>>2]|0;h=c[b+60>>2]|0;i=c[b+64>>2]|0;j=c[b+68>>2]|0;k=c[b+72>>2]|0;l=c[b+76>>2]|0;c[a+40>>2]=c[b+40>>2];c[a+44>>2]=d;c[a+48>>2]=e;c[a+52>>2]=f;c[a+56>>2]=g;c[a+60>>2]=h;c[a+64>>2]=i;c[a+68>>2]=j;c[a+72>>2]=k;c[a+76>>2]=l;l=c[b+84>>2]|0;k=c[b+88>>2]|0;j=c[b+92>>2]|0;i=c[b+96>>2]|0;h=c[b+100>>2]|0;g=c[b+104>>2]|0;f=c[b+108>>2]|0;e=c[b+112>>2]|0;d=c[b+116>>2]|0;c[a+80>>2]=c[b+80>>2];c[a+84>>2]=l;c[a+88>>2]=k;c[a+92>>2]=j;c[a+96>>2]=i;c[a+100>>2]=h;c[a+104>>2]=g;c[a+108>>2]=f;c[a+112>>2]=e;c[a+116>>2]=d;return}function cb(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0;j=i;k=i=i+63&-64;i=i+96|0;c[k>>2]=(d[h>>0]|d[h+1>>0]<<8|d[h+2>>0]<<16|d[h+3>>0]<<24)&67108863;c[k+4>>2]=(d[h+3>>0]|d[h+3+1>>0]<<8|d[h+3+2>>0]<<16|d[h+3+3>>0]<<24)>>>2&67108611;c[k+8>>2]=(d[h+6>>0]|d[h+6+1>>0]<<8|d[h+6+2>>0]<<16|d[h+6+3>>0]<<24)>>>4&67092735;c[k+12>>2]=(d[h+9>>0]|d[h+9+1>>0]<<8|d[h+9+2>>0]<<16|d[h+9+3>>0]<<24)>>>6&66076671;c[k+16>>2]=(d[h+12>>0]|d[h+12+1>>0]<<8|d[h+12+2>>0]<<16|d[h+12+3>>0]<<24)>>>8&1048575;c[k+20>>2]=0;c[k+20+4>>2]=0;c[k+20+8>>2]=0;c[k+20+12>>2]=0;c[k+20+16>>2]=0;c[k+40>>2]=d[h+16>>0]|d[h+16+1>>0]<<8|d[h+16+2>>0]<<16|d[h+16+3>>0]<<24;c[k+44>>2]=d[h+20>>0]|d[h+20+1>>0]<<8|d[h+20+2>>0]<<16|d[h+20+3>>0]<<24;c[k+48>>2]=d[h+24>>0]|d[h+24+1>>0]<<8|d[h+24+2>>0]<<16|d[h+24+3>>0]<<24;c[k+52>>2]=d[h+28>>0]|d[h+28+1>>0]<<8|d[h+28+2>>0]<<16|d[h+28+3>>0]<<24;c[k+56>>2]=0;c[k+56+4>>2]=0;a[k+80>>0]=0;Ra(k,e,f,g);Oa(k,b);i=j;return 0}function db(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;x=c[a>>2]|0;v=c[a+4>>2]|0;t=c[a+8>>2]|0;r=c[a+12>>2]|0;p=c[a+16>>2]|0;n=c[a+20>>2]|0;l=c[a+24>>2]|0;j=c[a+28>>2]|0;h=c[a+32>>2]|0;f=c[a+36>>2]|0;w=c[b>>2]|0;u=c[b+4>>2]|0;s=c[b+8>>2]|0;q=c[b+12>>2]|0;o=c[b+16>>2]|0;m=c[b+20>>2]|0;k=c[b+24>>2]|0;i=c[b+28>>2]|0;g=c[b+32>>2]|0;e=c[b+36>>2]|0;c[a>>2]=(w^x)&0-d^x;c[a+4>>2]=(u^v)&0-d^v;c[a+8>>2]=(s^t)&0-d^t;c[a+12>>2]=(q^r)&0-d^r;c[a+16>>2]=(o^p)&0-d^p;c[a+20>>2]=(m^n)&0-d^n;c[a+24>>2]=(k^l)&0-d^l;c[a+28>>2]=(i^j)&0-d^j;c[a+32>>2]=(g^h)&0-d^h;c[a+36>>2]=(e^f)&0-d^f;c[b>>2]=(w^x)&0-d^w;c[b+4>>2]=(u^v)&0-d^u;c[b+8>>2]=(s^t)&0-d^s;c[b+12>>2]=(q^r)&0-d^q;c[b+16>>2]=(o^p)&0-d^o;c[b+20>>2]=(m^n)&0-d^m;c[b+24>>2]=(k^l)&0-d^k;c[b+28>>2]=(i^j)&0-d^i;c[b+32>>2]=(g^h)&0-d^g;c[b+36>>2]=(e^f)&0-d^e;return}function eb(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0;k=i;j=i=i+63&-64;i=i+96|0;Aa(j,f,g,0)|0;fb(j+32|0,32,0,f+16|0,j)|0;if(!($d(c,b,d,e,j+32|0)|0))if(!a)c=0;else{if(b>>>0>=a>>>0?0<e>>>0|0==(e|0)&(b-a|0)>>>0<d>>>0:0)h=8;else if(a>>>0>=b>>>0?0<e>>>0|0==(e|0)&(a-b|0)>>>0<d>>>0:0)h=8;if((h|0)==8){Xc(a|0,b|0,d|0)|0;b=a}c=e>>>0>0|(e|0)==0&d>>>0>32?32:d;g=e>>>0>0|(e|0)==0&d>>>0>32?0:e;if((c|0)==0&(g|0)==0)Wd(j+32|0,j+32|0,32,0,f+16|0,j)|0;else{h=oe((e>>>0<0|(e|0)==0&d>>>0<32?d:32)|0,(e>>>0<0|(e|0)==0&d>>>0<32?e:0)|0,-1,0)|0;tc(j+32+32|0,b|0,h+1|0)|0;l=oe(c|0,g|0,32,0)|0;Wd(j+32|0,j+32|0,l,D,f+16|0,j)|0;tc(a|0,j+32+32|0,h+1|0)|0}if(e>>>0>0|(e|0)==0&d>>>0>32){l=le(d|0,e|0,c|0,g|0)|0;Ma(a+c|0,b+c|0,l,D,f+16|0,1,0,j)|0}fd(j,32);c=0}else{fd(j,32);c=-1}i=k;return c|0}function fb(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0;o=i;p=i=i+63&-64;i=i+112|0;if(!((e|0)==0&(f|0)==0)){k=p+16|0;j=k+32|0;do{a[k>>0]=a[h>>0]|0;k=k+1|0;h=h+1|0}while((k|0)<(j|0));k=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;c[p>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;c[p+4>>2]=k;c[p+8>>2]=0;c[p+8+4>>2]=0;if(f>>>0>0|(f|0)==0&e>>>0>63){do{xa(b,p,p+16|0,0)|0;h=1;j=8;while(1){k=p+j|0;h=(d[k>>0]|0)+h|0;a[k>>0]=h;j=j+1|0;if((j|0)==16)break;else h=h>>>8}e=oe(e|0,f|0,-64,-1)|0;f=D;b=b+64|0}while(f>>>0>0|(f|0)==0&e>>>0>63);if(!((e|0)==0&(f|0)==0)){m=b;n=e;l=7}}else{m=b;n=e;l=7}if((l|0)==7?(xa(p+48|0,p,p+16|0,0)|0,n|0):0){h=0;do{a[m+h>>0]=a[p+48+h>>0]|0;h=h+1|0}while((h|0)!=(n|0))}fd(p+48|0,64);fd(p+16|0,32)}i=o;return 0}function gb(b,e,f,g){b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0;k=i;l=i=i+63&-64;i=i+64|0;if((e+-1&255)>63)ba();a[l>>0]=e;a[l+1>>0]=0;a[l+2>>0]=1;a[l+3>>0]=1;h=l+4|0;j=h+28|0;do{a[h>>0]=0;h=h+1|0}while((h|0)<(j|0));if(!f){h=l+32|0;j=h+16|0;do{a[h>>0]=0;h=h+1|0}while((h|0)<(j|0))}else{h=l+32|0;e=f;j=h+16|0;do{a[h>>0]=a[e>>0]|0;h=h+1|0;e=e+1|0}while((h|0)<(j|0))}if(!g){h=l+48|0;j=h+16|0;do{a[h>>0]=0;h=h+1|0}while((h|0)<(j|0))}else{h=l+48|0;e=g;j=h+16|0;do{a[h>>0]=a[e>>0]|0;h=h+1|0;e=e+1|0}while((h|0)<(j|0))}Hc(b+64|0,0,293)|0;h=b;e=400;j=h+64|0;do{c[h>>2]=c[e>>2];h=h+4|0;e=e+4|0}while((h|0)<(j|0));e=0;do{h=l+(e<<3)|0;g=b+(e<<3)|0;j=c[g+4>>2]^(d[h+4>>0]|d[h+4+1>>0]<<8|d[h+4+2>>0]<<16|d[h+4+3>>0]<<24);c[g>>2]=c[g>>2]^(d[h>>0]|d[h+1>>0]<<8|d[h+2>>0]<<16|d[h+3>>0]<<24);c[g+4>>2]=j;e=e+1|0}while((e|0)!=8);i=k;return}function hb(b,e){b=b|0;e=e|0;c[b>>2]=(d[e>>0]|d[e+1>>0]<<8|d[e+2>>0]<<16|d[e+3>>0]<<24)&67108863;c[b+4>>2]=(d[e+3>>0]|d[e+3+1>>0]<<8|d[e+3+2>>0]<<16|d[e+3+3>>0]<<24)>>>2&67108611;c[b+8>>2]=(d[e+6>>0]|d[e+6+1>>0]<<8|d[e+6+2>>0]<<16|d[e+6+3>>0]<<24)>>>4&67092735;c[b+12>>2]=(d[e+9>>0]|d[e+9+1>>0]<<8|d[e+9+2>>0]<<16|d[e+9+3>>0]<<24)>>>6&66076671;c[b+16>>2]=(d[e+12>>0]|d[e+12+1>>0]<<8|d[e+12+2>>0]<<16|d[e+12+3>>0]<<24)>>>8&1048575;c[b+20>>2]=0;c[b+20+4>>2]=0;c[b+20+8>>2]=0;c[b+20+12>>2]=0;c[b+20+16>>2]=0;c[b+40>>2]=d[e+16>>0]|d[e+16+1>>0]<<8|d[e+16+2>>0]<<16|d[e+16+3>>0]<<24;c[b+44>>2]=d[e+20>>0]|d[e+20+1>>0]<<8|d[e+20+2>>0]<<16|d[e+20+3>>0]<<24;c[b+48>>2]=d[e+24>>0]|d[e+24+1>>0]<<8|d[e+24+2>>0]<<16|d[e+24+3>>0]<<24;c[b+52>>2]=d[e+28>>0]|d[e+28+1>>0]<<8|d[e+28+2>>0]<<16|d[e+28+3>>0]<<24;c[b+56>>2]=0;c[b+56+4>>2]=0;a[b+80>>0]=0;return 0}function ib(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;a:do if(!((e|0)==0&(f|0)==0)){g=c[b+352>>2]|0;j=f;while(1){i=256-g|0;f=b+96+g|0;if(!(j>>>0>0|(j|0)==0&e>>>0>i>>>0))break;tc(f|0,d|0,i|0)|0;c[b+352>>2]=(c[b+352>>2]|0)+i;f=c[b+64>>2]|0;g=c[b+64+4>>2]|0;h=oe(f|0,g|0,128,0)|0;c[b+64>>2]=h;c[b+64+4>>2]=D;f=oe((g>>>0>4294967295|(g|0)==-1&f>>>0>4294967167)&1|0,0,c[b+72>>2]|0,c[b+72+4>>2]|0)|0;c[b+72>>2]=f;c[b+72+4>>2]=D;ia(b,b+96|0);f=b+96|0;g=b+224|0;h=f+128|0;do{a[f>>0]=a[g>>0]|0;f=f+1|0;g=g+1|0}while((f|0)<(h|0));g=(c[b+352>>2]|0)+-128|0;c[b+352>>2]=g;e=le(e|0,j|0,i|0,0)|0;f=D;if((e|0)==0&(f|0)==0)break a;else{d=d+i|0;j=f}}tc(f|0,d|0,e|0)|0;j=oe(c[b+352>>2]|0,0,e|0,j|0)|0;c[b+352>>2]=j}while(0);return}function jb(a){a=a|0;var b=0,d=0;do if(a)if(c[a>>2]|0)if((c[a+4>>2]|0)>>>0>=16){if((c[a+8>>2]|0)==0?c[a+12>>2]|0:0){b=-18;break}b=c[a+20>>2]|0;if(!(c[a+16>>2]|0)){if(b|0){b=-19;break}}else if(b>>>0<8){b=-6;break}if((c[a+24>>2]|0)==0?c[a+28>>2]|0:0){b=-20;break}if((c[a+32>>2]|0)==0?c[a+36>>2]|0:0){b=-21;break}b=c[a+44>>2]|0;if(b>>>0>=8)if(b>>>0<=2097152){d=c[a+48>>2]|0;if(b>>>0>=d<<3>>>0)if((c[a+40>>2]|0)>>>0>=3)if(d)if(d>>>0<=16777215){b=c[a+52>>2]|0;if(!b)b=-28;else b=b>>>0>16777215?-29:0}else b=-17;else b=-16;else b=-12;else b=-14}else b=-15;else b=-14}else b=-2;else b=-1;else b=-25;while(0);return b|0}function kb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;l=i;k=i=i+63&-64;i=i+64|0;e=k+4+4|0;f=e+52|0;do{c[e>>2]=0;e=e+4|0}while((e|0)<(f|0));e=kc(a)|0;c[k+36>>2]=e;c[k+20>>2]=e;c[k+4>>2]=e;h=na(e)|0;c[k+32>>2]=h;f=na(e)|0;c[k+16>>2]=f;g=na(e)|0;c[k>>2]=g;do if((f|0)==0|(g|0)==0|(h|0)==0){ta(h);ta(f);ta(g);e=-22}else{j=na(e)|0;if(!j){ta(h);ta(f);ta(g);e=-22;break}e=Ja(k,a)|0;if(e|0){ta(c[k+32>>2]|0);ta(c[k+16>>2]|0);ta(c[k>>2]|0);ta(j);break}d=xb(c[k+40>>2]|0,c[k+44>>2]|0,c[k+52>>2]|0,b,d,c[k+16>>2]|0,c[k+20>>2]|0,j,c[k+4>>2]|0,0,0)|0;ta(c[k+32>>2]|0);ta(c[k+16>>2]|0);if((d|0)==0?(Dc(j,c[k>>2]|0,c[k+4>>2]|0)|0)==0:0)e=0;else e=-35;ta(j);ta(c[k>>2]|0)}while(0);i=l;return e|0}function lb(a,b,d,e,f,g,h,j,k,l,m){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0;n=i;i=i+352|0;we(n+280|0,64,0,l,m)|0;Se(n,n+280|0)|0;fd(n+280|0,64);ne(n,h,j,k)|0;b=le(0,0,j|0,k|0)|0;ne(n,34460,b&15,0)|0;ne(n,d,e,f)|0;b=le(0,0,e|0,f|0)|0;ne(n,34460,b&15,0)|0;c[n+256>>2]=j;c[n+256+4>>2]=k;ne(n,n+256|0,8,0)|0;c[n+256>>2]=e;c[n+256+4>>2]=f;ne(n,n+256|0,8,0)|0;Re(n,n+264|0)|0;fd(n,256);b=Ad(n+264|0,g)|0;fd(n+264|0,16);do if(a)if(!b){Ld(a,d,e,f,l,1,m)|0;b=0;break}else{Hc(a|0,0,e|0)|0;b=-1;break}while(0);i=n;return b|0}function mb(b,e,f,g,h,i,j){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0;a:do if(!g){n=0;m=0;k=0;l=0}else{n=0;m=0;k=0;q=0;while(1){p=n<<24>>24==0;while(1){l=d[f+k>>0]|0;o=(((l&223)+201&255)+65526^((l&223)+201&255)+65520)>>>8;if((o|((l^48)+65526|0)>>>8)&255|0)break;if(!((h|0)!=0&p)){l=0;break a}if(!(Ke(h,l)|0)){n=0;l=0;break a}k=k+1|0;if(k>>>0>=g>>>0){n=0;l=0;break a}}l=o&(l&223)+201|((l^48)+65526|0)>>>8&(l^48);if(m>>>0>=e>>>0)break;if(p)l=l<<4&255;else{a[b+m>>0]=l|q&255;m=m+1|0;l=q}n=(n&255^255)&255;k=k+1|0;if(k>>>0<g>>>0)q=l;else{l=0;break a}}c[(Zf()|0)>>2]=34;l=-1}while(0);if(j|0)c[j>>2]=f+(((n<<24>>24!=0)<<31>>31)+k);if(i|0)c[i>>2]=m;return l|0}function nb(b,e,f,g){b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0;k=i;l=i=i+63&-64;i=i+192|0;if((e+-1&255)>63)ba();if((f|0)!=0&g<<24>>24!=0?(g&255)<=64:0){a[l+128>>0]=e;a[l+128+1>>0]=g;a[l+128+2>>0]=1;a[l+128+3>>0]=1;e=l+128+4|0;j=e+60|0;do{a[e>>0]=0;e=e+1|0}while((e|0)<(j|0));Hc(b+64|0,0,293)|0;e=b;h=400;j=e+64|0;do{c[e>>2]=c[h>>2];e=e+4|0;h=h+4|0}while((e|0)<(j|0));e=0;do{m=l+128+(e<<3)|0;j=b+(e<<3)|0;h=c[j+4>>2]^(d[m+4>>0]|d[m+4+1>>0]<<8|d[m+4+2>>0]<<16|d[m+4+3>>0]<<24);c[j>>2]=c[j>>2]^(d[m>>0]|d[m+1>>0]<<8|d[m+2>>0]<<16|d[m+3>>0]<<24);c[j+4>>2]=h;e=e+1|0}while((e|0)!=8);Hc(l+(g&255)|0,0,(g<<24>>24<0?0:128-(g&255)|0)|0)|0;tc(l|0,f|0,g&255|0)|0;ib(b,l,128,0);fd(l,128);i=k;return}ba()}function ob(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0;i=b>>>0<0|(b|0)==0&a>>>0<32768?32768:a;h=b>>>0<0|(b|0)==0&a>>>0<32768?0:b;c[g>>2]=8;a:do if(h>>>0<0|(h|0)==0&i>>>0<d>>>5>>>0){c[f>>2]=1;a=Te(i|0,h|0,c[g>>2]<<2|0,0)|0;c[e>>2]=1;a=Rd(a|0,D|0,1)|0;b=D;h=1;do{g=Pd(1,0,h|0)|0;f=D;h=h+1|0;if(f>>>0>b>>>0|(f|0)==(b|0)&g>>>0>a>>>0)break a;c[e>>2]=h}while(h>>>0<63)}else{c[e>>2]=1;b=1;while(1){j=Pd(1,0,b|0)|0;k=D;a=b+1|0;if(k>>>0>0|(k|0)==0&j>>>0>d>>>11>>>0){a=b;break}c[e>>2]=a;if(a>>>0<63)b=a;else break}e=Rd(i|0,h|0,2)|0;e=Rd(e|0,D|0,a|0)|0;j=D;k=j>>>0>0|(j|0)==0&e>>>0>1073741823?1073741823:e;c[f>>2]=(k>>>0)/((c[g>>2]|0)>>>0)|0}while(0);return}function pb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;m=i;l=i=i+63&-64;i=i+2048|0;if((a|0)!=0&(b|0)!=0){k=(c[b>>2]|0)+4|0;f=c[b+16>>2]|0;tc(l|0,(c[k>>2]|0)+(f<<10)+-1024|0,1024)|0;g=c[b+20>>2]|0;if(g>>>0>1){d=1;do{h=f+-1+(S(f,d)|0)|0;j=c[k>>2]|0;e=0;do{p=j+(h<<10)+(e<<3)|0;n=l+(e<<3)|0;o=c[n+4>>2]^c[p+4>>2];c[n>>2]=c[n>>2]^c[p>>2];c[n+4>>2]=o;e=e+1|0}while((e|0)!=128);d=d+1|0}while((d|0)!=(g|0))}tc(l+1024|0,l|0,1024)|0;Ta(c[a>>2]|0,c[a+4>>2]|0,l+1024|0,1024);fd(l,1024);fd(l+1024|0,1024);e=c[b>>2]|0;if(e|0?(c[a+56>>2]&1|0)!=0:0){fd(c[e+4>>2]|0,c[b+8>>2]<<10);e=c[b>>2]|0}d=c[e>>2]|0;if(d|0)ta(d);ta(e)}i=m;return}function qb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;a:do if((e|0)!=0&(b&3|0)!=0){f=e;while(1){if((a[b>>0]|0)==(d&255)<<24>>24)break a;b=b+1|0;e=f+-1|0;if((e|0)!=0&(b&3|0)!=0)f=e;else{f=e;e=(e|0)!=0;g=5;break}}}else{f=e;e=(e|0)!=0;g=5}while(0);b:do if((g|0)==5)if(e){if((a[b>>0]|0)!=(d&255)<<24>>24){e=S(d&255,16843009)|0;c:do if(f>>>0>3)while(1){h=c[b>>2]^e;if((h&-2139062144^-2139062144)&h+-16843009|0)break;b=b+4|0;f=f+-4|0;if(f>>>0<=3){g=11;break c}}else g=11;while(0);if((g|0)==11)if(!f){f=0;break}while(1){if((a[b>>0]|0)==(d&255)<<24>>24)break b;b=b+1|0;f=f+-1|0;if(!f){f=0;break}}}}else f=0;while(0);return (f|0?b:0)|0}function rb(a){a=a|0;var b=0,d=0,e=0,f=0;if(a>>>0>=4294967168){c[(Zf()|0)>>2]=12;f=0;return f|0}f=a>>>0<11?16:a+11&-8;e=na(f+76|0)|0;if(!e){f=0;return f|0}do if(e&63){a=((e+63&-64)+-8-(e+-8)|0)>>>0>15?(e+63&-64)+-8|0:(e+63&-64)+56|0;b=a-(e+-8)|0;d=c[e+-4>>2]|0;if(!(d&3)){c[a>>2]=(c[e+-8>>2]|0)+b;c[a+4>>2]=(d&-8)-b;break}else{c[a+4>>2]=(d&-8)-b|c[a+4>>2]&1|2;c[a+((d&-8)-b)+4>>2]=c[a+((d&-8)-b)+4>>2]|1;c[e+-4>>2]=b|c[e+-4>>2]&1|2;c[a+4>>2]=c[a+4>>2]|1;ua(e+-8|0,b);break}}else a=e+-8|0;while(0);b=a+4|0;d=c[b>>2]|0;if(d&3|0?(d&-8)>>>0>(f+16|0)>>>0:0){e=a+f|0;c[b>>2]=f|d&1|2;c[e+4>>2]=(d&-8)-f|3;c[e+((d&-8)-f)+4>>2]=c[e+((d&-8)-f)+4>>2]|1;ua(e,(d&-8)-f|0)}f=a+8|0;return f|0}function sb(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;h=i;i=i+192|0;if(d>>>0>128){nd(b)|0;Na(b,c,d,0)|0;rc(b,h)|0;d=64;c=h}nd(b)|0;e=h+64|0;f=e+128|0;do{a[e>>0]=54;e=e+1|0}while((e|0)<(f|0));g=(d|0)==0;if(!g?(a[h+64>>0]=a[c>>0]^54,(d|0)!=1):0){e=1;do{f=h+64+e|0;a[f>>0]=a[f>>0]^a[c+e>>0];e=e+1|0}while((e|0)!=(d|0))}Na(b,h+64|0,128,0)|0;nd(b+208|0)|0;e=h+64|0;f=e+128|0;do{a[e>>0]=92;e=e+1|0}while((e|0)<(f|0));if(!g?(a[h+64>>0]=a[c>>0]^92,(d|0)!=1):0){e=1;do{g=h+64+e|0;a[g>>0]=a[g>>0]^a[c+e>>0];e=e+1|0}while((e|0)!=(d|0))}Na(b+208|0,h+64|0,128,0)|0;fd(h+64|0,128);fd(h,64);i=h;return 0}function tb(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;h=i;i=i+96|0;if(d>>>0>64){Sc(b)|0;Ua(b,c,d,0)|0;Fb(b,h)|0;d=32;c=h}Sc(b)|0;e=h+32|0;f=e+64|0;do{a[e>>0]=54;e=e+1|0}while((e|0)<(f|0));g=(d|0)==0;if(!g?(a[h+32>>0]=a[c>>0]^54,(d|0)!=1):0){e=1;do{f=h+32+e|0;a[f>>0]=a[f>>0]^a[c+e>>0];e=e+1|0}while((e|0)!=(d|0))}Ua(b,h+32|0,64,0)|0;Sc(b+104|0)|0;e=h+32|0;f=e+64|0;do{a[e>>0]=92;e=e+1|0}while((e|0)<(f|0));if(!g?(a[h+32>>0]=a[c>>0]^92,(d|0)!=1):0){e=1;do{g=h+32+e|0;a[g>>0]=a[g>>0]^a[c+e>>0];e=e+1|0}while((e|0)!=(d|0))}Ua(b+104|0,h+32|0,64,0)|0;fd(h+32|0,64);fd(h,32);i=h;return 0}function ub(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;f=0;h=0;i=0;a:while(1){while(1){g=a[e>>0]|0;g=((0-((0-(g^47)|0)>>>8&63^63|(0-(g^43)|0)>>>8&62^62|((g+65439|0)>>>8^255)&g+185&((122-g|0)>>>8&255^255)|((g+-65|0)>>>8^255)&g+-65&((90-g|0)>>>8&255^255)|((g+65488|0)>>>8^255)&g+4&((57-g|0)>>>8&255^255))|0)>>>8&255^255)&(0-(g^65)|0)>>>8|((0-(g^47)|0)>>>8&63^63|(0-(g^43)|0)>>>8&62^62|((g+65439|0)>>>8^255)&g+185&((122-g|0)>>>8&255^255)|((g+-65|0)>>>8^255)&g+-65&((90-g|0)>>>8&255^255)|((g+65488|0)>>>8^255)&g+4&((57-g|0)>>>8&255^255));if((g|0)==255){j=7;break a}e=e+1|0;h=g+(h<<6)|0;g=f+6|0;if(g>>>0>7)break;else f=g}f=f+-2|0;if(i>>>0>=(c[d>>2]|0)>>>0){e=0;break}a[b>>0]=h>>>f;b=b+1|0;i=i+1|0}if((j|0)==7)if(f>>>0<=4?((1<<f)+-1&h|0)==0:0)c[d>>2]=i;else e=0;return e|0}function vb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=c[a>>2]|0;u=c[a+4>>2]|0;s=c[a+8>>2]|0;q=c[a+12>>2]|0;o=c[a+16>>2]|0;m=c[a+20>>2]|0;k=c[a+24>>2]|0;i=c[a+28>>2]|0;g=c[a+32>>2]|0;e=c[a+36>>2]|0;v=(c[b+4>>2]^u)&0-d;t=(c[b+8>>2]^s)&0-d;r=(c[b+12>>2]^q)&0-d;p=(c[b+16>>2]^o)&0-d;n=(c[b+20>>2]^m)&0-d;l=(c[b+24>>2]^k)&0-d;j=(c[b+28>>2]^i)&0-d;h=(c[b+32>>2]^g)&0-d;f=(c[b+36>>2]^e)&0-d;c[a>>2]=(c[b>>2]^w)&0-d^w;c[a+4>>2]=v^u;c[a+8>>2]=t^s;c[a+12>>2]=r^q;c[a+16>>2]=p^o;c[a+20>>2]=n^m;c[a+24>>2]=l^k;c[a+28>>2]=j^i;c[a+32>>2]=h^g;c[a+36>>2]=f^e;return}function wb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;f=0;do{c[d+(f<<2)>>2]=c[a+((e<<5)+-16<<2)+(f<<2)>>2];f=f+1|0}while((f|0)!=16);if(e<<1|0){i=0;j=0;while(1){g=i<<4;f=0;do{h=d+(f<<2)|0;c[h>>2]=c[h>>2]^c[a+(g<<2)+(f<<2)>>2];f=f+1|0}while((f|0)!=16);Ga(d);h=i<<3;f=0;do{c[b+(h<<2)+(f<<2)>>2]=c[d+(f<<2)>>2];f=f+1|0}while((f|0)!=16);f=0;do{k=d+(f<<2)|0;c[k>>2]=c[k>>2]^c[a+((g|16)<<2)+(f<<2)>>2];f=f+1|0}while((f|0)!=16);Ga(d);f=0;do{c[b+(h+(e<<4)<<2)+(f<<2)>>2]=c[d+(f<<2)>>2];f=f+1|0}while((f|0)!=16);if((j|0)==(((e<<1)+-1|0)>>>1|0))break;else{i=i+2|0;j=j+1|0}}}return}function xb(a,b,d,e,f,g,h,j,k,l,m){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0,o=0,p=0;p=i;o=i=i+63&-64;i=i+64|0;n=na(k)|0;do if(!n)a=-22;else{c[o>>2]=n;c[o+4>>2]=k;c[o+8>>2]=e;c[o+12>>2]=f;c[o+16>>2]=g;c[o+20>>2]=h;c[o+24>>2]=0;c[o+24+4>>2]=0;c[o+24+8>>2]=0;c[o+24+12>>2]=0;c[o+40>>2]=a;c[o+44>>2]=b;c[o+48>>2]=d;c[o+52>>2]=d;c[o+56>>2]=4;a=_b(o)|0;if(a|0){fd(n,k);ta(n);break}if(j|0)tc(j|0,n|0,k|0)|0;if((l|0)!=0&(m|0)!=0?Da(l,m,o)|0:0){fd(n,k);fd(l,m);ta(n);a=-31;break}fd(n,k);ta(n);a=0}while(0);i=p;return a|0}function yb(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;q=i;p=i=i+63&-64;i=i+48|0;if((((((a[g>>0]|0)==36?(a[g+1>>0]|0)==55:0)?(a[g+2>>0]|0)==36:0)?(k=qb(32982,d[g+3>>0]|0,65)|0,(k|0)!=0):0)?(l=Pd(1,0,k-32982|0)|0,m=D,j=cd(p+4|0,g+4|0)|0,(j|0)!=0):0)?(n=cd(p,j)|0,(n|0)!=0):0){j=gf(n)|0;if(!j)j=kc(n)|0;else j=j-n|0;k=j+(n-g)|0;if((!((k+45|0)>>>0>102|(k+45|0)>>>0<j>>>0)?(Ca(b,e,f,n,j,l,m,c[p+4>>2]|0,c[p>>2]|0,p+8|0,32)|0)==0:0)?(tc(h|0,g|0,k|0)|0,a[h+k>>0]=36,o=Yb(h+k+1|0,h+102-(h+k+1)|0,p+8|0)|0,fd(p+8|0,32),(o|0)!=0&o>>>0<(h+102|0)>>>0):0)a[o>>0]=0;else h=0}else h=0;i=q;return h|0}function zb(b,e,f,g,h,j){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0;k=i;l=i=i+63&-64;i=i+560|0;xc(l+496|0,j,32,0)|0;a[l+496>>0]=(d[l+496>>0]|0)&248;a[l+496+31>>0]=(d[l+496+31>>0]|0)&63|64;nd(l)|0;Na(l,l+496+32|0,32,0)|0;Na(l,f,g,h)|0;rc(l,l+432|0)|0;Xc(b+32|0,j+32|0,32)|0;oa(l+432|0);Pa(l+208|0,l+432|0);vc(b,l+208|0);nd(l)|0;Na(l,b,64,0)|0;Na(l,f,g,h)|0;rc(l,l+368|0)|0;oa(l+368|0);ja(b+32|0,l+368|0,l+496|0,l+432|0);fd(l+496|0,64);if(e|0){c[e>>2]=64;c[e+4>>2]=0}i=k;return 0}function Ab(a,b,d,e,f,g,h,j,k,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;l=i;i=i+336|0;we(l+264|0,64,0,m,n)|0;Se(l,l+264|0)|0;fd(l+264|0,64);ne(l,h,j,k)|0;h=le(0,0,j|0,k|0)|0;ne(l,34460,h&15,0)|0;Ld(a,e,f,g,m,1,n)|0;ne(l,a,f,g)|0;h=le(0,0,f|0,g|0)|0;ne(l,34460,h&15,0)|0;c[l+256>>2]=j;c[l+256+4>>2]=k;ne(l,l+256|0,8,0)|0;c[l+256>>2]=f;c[l+256+4>>2]=g;ne(l,l+256|0,8,0)|0;Re(l,b)|0;fd(l,256);if(d|0){c[d>>2]=16;c[d+4>>2]=0}i=l;return 0}function Bb(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0;a:do if(b>>>0<=63?(g=Ed(d|0,0,c|0,0)|0,i=D,!(i>>>0>0|(i|0)==0&g>>>0>1073741823)):0){a[f>>0]=36;a[f+1>>0]=55;a[f+2>>0]=36;a[f+3>>0]=a[32982+b>>0]|0;b=f+4|0;g=0;while(1){i=b;b=b+1|0;a[i>>0]=a[32982+(c&63)>>0]|0;g=g+6|0;if(g>>>0>=30)break;else c=c>>>6}if(b){g=d;d=f+58-b|0;c=0;while(1){if(!d){f=0;break a}i=b;b=b+1|0;a[i>>0]=a[32982+(g&63)>>0]|0;c=c+6|0;if(c>>>0>=30)break;else{g=g>>>6;d=d+-1|0}}if((b|0)!=0?(h=Yb(b,f+58-b|0,e)|0,(h|0)!=0&h>>>0<(f+58|0)>>>0):0)a[h>>0]=0;else f=0}else f=0}else f=0;while(0);return f|0}function Cb(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0;k=i;j=i=i+63&-64;i=i+32|0;a:do if(((b|0)!=0?(d=c[b+20>>2]|0,(d|0)!=0):0)?(c[b+4>>2]|0)!=0:0){h=0;while(1){g=0;do{if(!d)d=0;else{f=g&255;e=0;do{c[j>>2]=h;c[j+4>>2]=e;a[j+8>>0]=f;c[j+12>>2]=0;c[j+16>>2]=c[j>>2];c[j+16+4>>2]=c[j+4>>2];c[j+16+8>>2]=c[j+8>>2];c[j+16+12>>2]=c[j+12>>2];d=la(b,j+16|0)|0;e=e+1|0;if(d|0)break a;d=c[b+20>>2]|0}while(e>>>0<d>>>0)}g=g+1|0}while(g>>>0<4);h=h+1|0;if(h>>>0>=(c[b+4>>2]|0)>>>0){d=0;break}}}else d=0;while(0);i=k;return d|0}function Db(a,b,d,e,f,g,h,j,k,l,m){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0;n=i;i=i+352|0;Ge(n+280|0,64,0,l,m)|0;Se(n,n+280|0)|0;fd(n+280|0,64);ne(n,h,j,k)|0;c[n+256>>2]=j;c[n+256+4>>2]=k;ne(n,n+256|0,8,0)|0;ne(n,d,e,f)|0;c[n+256>>2]=e;c[n+256+4>>2]=f;ne(n,n+256|0,8,0)|0;Re(n,n+264|0)|0;fd(n,256);b=Ad(n+264|0,g)|0;fd(n+264|0,16);do if(a)if(!b){Id(a,d,e,f,l,1,0,m)|0;b=0;break}else{Hc(a|0,0,e|0)|0;b=-1;break}while(0);i=n;return b|0}function Eb(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;j=(c[d>>2]|0)==0;do if(j){g=a[d+8>>0]|0;if(!(g<<24>>24)){g=(c[d+12>>2]|0)+-1|0;break}g=S(c[b+12>>2]|0,g&255)|0;h=c[d+12>>2]|0;if(!f){g=(((h|0)==0)<<31>>31)+g|0;break}else{g=h+-1+g|0;break}}else{g=(c[b+16>>2]|0)-(c[b+12>>2]|0)|0;h=c[d+12>>2]|0;if(!f){g=(((h|0)==0)<<31>>31)+g|0;break}else{g=h+-1+g|0;break}}while(0);Ed(e|0,0,e|0,0)|0;Ed(g|0,0,D|0,0)|0;f=le(g+-1|0,0,D|0,0)|0;e=D;if(!j?(i=a[d+8>>0]|0,i<<24>>24!=3):0){g=S(c[b+12>>2]|0,(i&255)+1|0)|0;h=0}else{g=0;h=0}j=oe(f|0,e|0,g|0,h|0)|0;b=Bd(j|0,D|0,c[b+16>>2]|0,0)|0;return b|0}function Fb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;f=i;e=i=i+63&-64;i=i+16|0;h=c[b+32>>2]|0;g=c[b+32+4>>2]|0;a[e+7>>0]=h;j=Rd(h|0,g|0,8)|0;a[e+6>>0]=j;j=Rd(h|0,g|0,16)|0;a[e+5>>0]=j;j=Rd(h|0,g|0,24)|0;a[e+4>>0]=j;a[e+3>>0]=g;j=Rd(h|0,g|0,40)|0;a[e+2>>0]=j;j=Rd(h|0,g|0,48)|0;a[e+1>>0]=j;j=Rd(h|0,g|0,56)|0;a[e>>0]=j;g=Rd(h|0,g|0,3)|0;Ua(b,32719,((g&63)>>>0<56?56:120)-(g&63)|0,0)|0;Ua(b,e,8,0)|0;e=0;do{j=d+(e<<2)|0;h=c[b+(e<<2)>>2]|0;a[j+3>>0]=h;a[j+2>>0]=h>>>8;a[j+1>>0]=h>>>16;a[j>>0]=h>>>24;e=e+1|0}while((e|0)!=8);fd(b,104);i=f;return 0}function Gb(b,c){b=b|0;c=c|0;var e=0,f=0,g=0,h=0,i=0;e=0;do{a[b+e>>0]=(d[c+(e>>3)>>0]|0)>>>(e&7)&1;e=e+1|0}while((e|0)!=256);h=0;do{i=b+h|0;a:do if(a[i>>0]|0){g=1;do{e=g+h|0;if((e|0)>=256)break a;c=a[b+e>>0]|0;b:do if(c<<24>>24){f=a[i>>0]|0;c=c<<24>>24<<g;if((f+c|0)<16){a[i>>0]=f+c;a[b+e>>0]=0;break}if((f-c|0)<=-16)break a;a[i>>0]=f-c;while(1){c=b+e|0;if(!(a[c>>0]|0))break;a[c>>0]=0;e=e+1|0;if((e|0)>=256)break b}a[c>>0]=1}while(0);g=g+1|0}while((g|0)<7)}while(0);h=h+1|0}while((h|0)!=256);return}function Hb(b,d,e,f,g,h,j){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0;n=i;l=i=i+63&-64;i=i+128|0;k=b;m=k+102|0;do{a[k>>0]=0;k=k+1|0}while((k|0)<(m|0));do if(!(f>>>0>0|(f|0)==0&e>>>0>4294967295)){ob(g,h,j,l+8|0,l+4|0,l);Gd(l+88|0,32);if(!(Bb(c[l+8>>2]|0,c[l>>2]|0,c[l+4>>2]|0,l+88|0,l+24|0)|0)){c[(Zf()|0)>>2]=22;b=-1;break}We(l+12|0);m=(yb(l+12|0,d,e,l+24|0,b)|0)==0;je(l+12|0);if(m){c[(Zf()|0)>>2]=22;b=-1}else b=0}else{c[(Zf()|0)>>2]=27;b=-1}while(0);i=n;return b|0}function Ib(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0;h=i;j=i=i+63&-64;i=i+64|0;if((e+-1&255)>63)ba();a[j>>0]=e;a[j+1>>0]=0;a[j+2>>0]=1;a[j+3>>0]=1;e=j+4|0;g=e+60|0;do{a[e>>0]=0;e=e+1|0}while((e|0)<(g|0));Hc(b+64|0,0,293)|0;e=b;f=400;g=e+64|0;do{c[e>>2]=c[f>>2];e=e+4|0;f=f+4|0}while((e|0)<(g|0));e=0;do{k=j+(e<<3)|0;g=b+(e<<3)|0;f=c[g+4>>2]^(d[k+4>>0]|d[k+4+1>>0]<<8|d[k+4+2>>0]<<16|d[k+4+3>>0]<<24);c[g>>2]=c[g>>2]^(d[k>>0]|d[k+1>>0]<<8|d[k+2>>0]<<16|d[k+3>>0]<<24);c[g+4>>2]=f;e=e+1|0}while((e|0)!=8);i=h;return}function Jb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;m=(c[b+4>>2]|0)-(c[d+4>>2]|0)|0;l=(c[b+8>>2]|0)-(c[d+8>>2]|0)|0;k=(c[b+12>>2]|0)-(c[d+12>>2]|0)|0;j=(c[b+16>>2]|0)-(c[d+16>>2]|0)|0;i=(c[b+20>>2]|0)-(c[d+20>>2]|0)|0;h=(c[b+24>>2]|0)-(c[d+24>>2]|0)|0;g=(c[b+28>>2]|0)-(c[d+28>>2]|0)|0;f=(c[b+32>>2]|0)-(c[d+32>>2]|0)|0;e=(c[b+36>>2]|0)-(c[d+36>>2]|0)|0;c[a>>2]=(c[b>>2]|0)-(c[d>>2]|0);c[a+4>>2]=m;c[a+8>>2]=l;c[a+12>>2]=k;c[a+16>>2]=j;c[a+20>>2]=i;c[a+24>>2]=h;c[a+28>>2]=g;c[a+32>>2]=f;c[a+36>>2]=e;return}function Kb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;m=(c[d+4>>2]|0)+(c[b+4>>2]|0)|0;l=(c[d+8>>2]|0)+(c[b+8>>2]|0)|0;k=(c[d+12>>2]|0)+(c[b+12>>2]|0)|0;j=(c[d+16>>2]|0)+(c[b+16>>2]|0)|0;i=(c[d+20>>2]|0)+(c[b+20>>2]|0)|0;h=(c[d+24>>2]|0)+(c[b+24>>2]|0)|0;g=(c[d+28>>2]|0)+(c[b+28>>2]|0)|0;f=(c[d+32>>2]|0)+(c[b+32>>2]|0)|0;e=(c[d+36>>2]|0)+(c[b+36>>2]|0)|0;c[a>>2]=(c[d>>2]|0)+(c[b>>2]|0);c[a+4>>2]=m;c[a+8>>2]=l;c[a+12>>2]=k;c[a+16>>2]=j;c[a+20>>2]=i;c[a+24>>2]=h;c[a+28>>2]=g;c[a+32>>2]=f;c[a+36>>2]=e;return}function Lb(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;var g=0,h=0,i=0;switch(((f>>>0)%3|0)&3){case 2:{g=((f>>>0)/3|0)<<2|1;h=3;break}case 1:{g=((f>>>0)/3|0)<<2;h=3;break}default:g=((f>>>0)/3|0)<<2}if((h|0)==3)g=g+2|0;if(g>>>0<c>>>0){if(f){i=0;c=0;do{f=f+-1|0;h=e;e=e+1|0;i=d[h>>0]|0|i<<8;c=c+8|0;if(c>>>0>5)while(1){c=c+-6|0;h=b+1|0;a[b>>0]=td(i>>>c&63)|0;if(c>>>0>5)b=h;else{b=h;break}}}while((f|0)!=0);if(c){a[b>>0]=td(i<<6-c&63)|0;b=b+1|0}}a[b>>0]=0}else g=-1;return g|0}function Mb(b,d){b=b|0;d=d|0;var e=0,f=0;a:do if(!(d&255))b=b+(kc(b)|0)|0;else{if(b&3)do{f=a[b>>0]|0;if(f<<24>>24==0?1:f<<24>>24==(d&255)<<24>>24)break a;b=b+1|0}while((b&3|0)!=0);f=S(d&255,16843009)|0;e=c[b>>2]|0;b:do if(!((e&-2139062144^-2139062144)&e+-16843009))do{e=e^f;if((e&-2139062144^-2139062144)&e+-16843009|0)break b;b=b+4|0;e=c[b>>2]|0}while(!((e&-2139062144^-2139062144)&e+-16843009|0));while(0);while(1){f=a[b>>0]|0;if(f<<24>>24==0?1:f<<24>>24==(d&255)<<24>>24)break;else b=b+1|0}}while(0);return b|0}function Nb(a,b,d,e,f,g,h,j,k,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;l=i;i=i+336|0;Ge(l+264|0,64,0,m,n)|0;Se(l,l+264|0)|0;fd(l+264|0,64);ne(l,h,j,k)|0;c[l+256>>2]=j;c[l+256+4>>2]=k;ne(l,l+256|0,8,0)|0;Id(a,e,f,g,m,1,0,n)|0;ne(l,a,f,g)|0;c[l+256>>2]=f;c[l+256+4>>2]=g;ne(l,l+256|0,8,0)|0;Re(l,b)|0;fd(l,256);if(d|0){c[d>>2]=16;c[d+4>>2]=0}i=l;return 0}function Ob(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;g=i;f=i=i+63&-64;i=i+80|0;a:do if((a|0)==0|(b|0)==0)d=-25;else{e=c[a+8>>2]|0;do if((e|0?((e<<10>>>0)/(e>>>0)|0|0)==1024:0)?(d=na(12)|0,c[a>>2]=d,d|0):0){d=Od(f,e<<10)|0;c[(Zf()|0)>>2]=d;if(d|0){c[f>>2]=0;break}d=c[f>>2]|0;if(d|0){c[c[a>>2]>>2]=d;c[(c[a>>2]|0)+4>>2]=d;c[(c[a>>2]|0)+8>>2]=e<<10;Sa(f+8|0,b,c[a+28>>2]|0);fd(f+8+64|0,8);_a(f+8|0,a);fd(f+8|0,72);d=0;break a}}while(0);d=-22}while(0);i=g;return d|0}function Pb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=i=i+63&-64;i=i+48|0;Kb(a,b+40|0,b);Jb(a+40|0,b+40|0,b);pa(a+80|0,a,c+40|0);pa(a+40|0,a+40|0,c);pa(a+120|0,c+120|0,b+120|0);pa(a,b+80|0,c+80|0);Kb(e,a,a);Jb(a,a+80|0,a+40|0);Kb(a+40|0,a+80|0,a+40|0);Jb(a+80|0,e,a+120|0);Kb(a+120|0,e,a+120|0);i=d;return}function Qb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=i=i+63&-64;i=i+48|0;Kb(a,b+40|0,b);Jb(a+40|0,b+40|0,b);pa(a+80|0,a,c);pa(a+40|0,a+40|0,c+40|0);pa(a+120|0,c+120|0,b+120|0);pa(a,b+80|0,c+80|0);Kb(e,a,a);Jb(a,a+80|0,a+40|0);Kb(a+40|0,a+80|0,a+40|0);Kb(a+80|0,e,a+120|0);Jb(a+120|0,e,a+120|0);i=d;return}function Rb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;Kb(a,b+40|0,b);Jb(a+40|0,b+40|0,b);l=c[b+84>>2]|0;k=c[b+88>>2]|0;j=c[b+92>>2]|0;i=c[b+96>>2]|0;h=c[b+100>>2]|0;g=c[b+104>>2]|0;f=c[b+108>>2]|0;e=c[b+112>>2]|0;d=c[b+116>>2]|0;c[a+80>>2]=c[b+80>>2];c[a+84>>2]=l;c[a+88>>2]=k;c[a+92>>2]=j;c[a+96>>2]=i;c[a+100>>2]=h;c[a+104>>2]=g;c[a+108>>2]=f;c[a+112>>2]=e;c[a+116>>2]=d;pa(a+120|0,b+120|0,544);return}function Sb(b,c){b=b|0;c=c|0;var e=0,f=0,g=0,h=0;g=i;h=i=i+63&-64;i=i+320|0;f=h+280|0;e=f+32|0;do{a[f>>0]=a[c>>0]|0;f=f+1|0;c=c+1|0}while((f|0)<(e|0));a[h+280>>0]=(d[h+280>>0]|0)&248;a[h+280+31>>0]=(d[h+280+31>>0]|0)&63|64;Pa(h+40|0,h+280|0);Kb(h+240|0,h+40+80|0,h+40+40|0);Jb(h+200|0,h+40+80|0,h+40+40|0);Ia(h+200|0,h+200|0);pa(h,h+240|0,h+200|0);La(b,h);i=g;return 0}function Tb(b,c,d,e,f,g){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;h=i;j=i=i+63&-64;i=i+464|0;tb(j+208|0,b,c)|0;De(j+208|0,d,e,0)|0;if(g|0){b=0;c=0;do{b=b+1|0;a[j+448+3>>0]=b;a[j+448+2>>0]=b>>>8;a[j+448+1>>0]=b>>>16;a[j+448>>0]=b>>>24;tc(j|0,j+208|0,208)|0;De(j,j+448|0,4,0)|0;pd(j,j+416|0)|0;e=g-c|0;tc(f+c|0,j+416|0,(e>>>0>32?32:e)|0)|0;c=b<<5}while(c>>>0<g>>>0)}fd(j+208|0,208);i=h;return}function Ub(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=i=i+63&-64;i=i+48|0;Kb(a,b+40|0,b);Jb(a+40|0,b+40|0,b);pa(a+80|0,a,c+40|0);pa(a+40|0,a+40|0,c);pa(a+120|0,c+80|0,b+120|0);Kb(e,b+80|0,b+80|0);Jb(a,a+80|0,a+40|0);Kb(a+40|0,a+80|0,a+40|0);Jb(a+80|0,e,a+120|0);Kb(a+120|0,e,a+120|0);i=d;return}function Vb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=i=i+63&-64;i=i+48|0;Kb(a,b+40|0,b);Jb(a+40|0,b+40|0,b);pa(a+80|0,a,c);pa(a+40|0,a+40|0,c+40|0);pa(a+120|0,c+80|0,b+120|0);Kb(e,b+80|0,b+80|0);Jb(a,a+80|0,a+40|0);Kb(a+40|0,a+80|0,a+40|0);Kb(a+80|0,e,a+120|0);Jb(a+120|0,e,a+120|0);i=d;return}function Wb(b,d,e,f,g,h,j){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0;n=i;l=i=i+63&-64;i=i+16|0;k=b;m=k+128|0;do{a[k>>0]=0;k=k+1|0}while((k|0)<(m|0));do if(!((h|f)>>>0>0|(h|f|0)==0&(g|e)>>>0>4294967295|j>>>0>2147484671))if(h>>>0<0|(h|0)==0&g>>>0<3|j>>>0<8192){c[(Zf()|0)>>2]=22;b=-1;break}else{Gd(l,16);b=((ae(g,j>>>10,d,e,l,b)|0)!=0)<<31>>31;break}else{c[(Zf()|0)>>2]=27;b=-1}while(0);i=n;return b|0}function Xb(a,b,c,d,e,f,g,h,j){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0;k=i;l=i=i+63&-64;i=i+368|0;if((b|0)==0&((e|0)!=0|(f|0)!=0))ba();if(!a)ba();if((d+-1&255)>63)ba();if(!((c|0)!=0|g<<24>>24==0))ba();if((g&255)>64)ba();if(!(g<<24>>24))gb(l,d,h,j);else Qa(l,d,c,g,h,j);ib(l,b,e,f);ab(l,a,d)|0;i=k;return}function Yb(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0;g=0;a:while(1){if(g>>>0<32){k=0;f=0;j=g}else break;do{i=j;j=j+1|0;f=(d[e+i>>0]|0)<<k|f;k=k+8|0}while(j>>>0<32&k>>>0<24);g=c;i=b;h=0;while(1){if(!g){b=0;break a}l=i;i=i+1|0;a[l>>0]=a[32982+(f&63)>>0]|0;h=h+6|0;if(h>>>0>=k>>>0)break;else{f=f>>>6;g=g+-1|0}}l=(i|0)==0;c=(l?0:b-i|0)+c|0;if(l){b=0;break}else{g=j;b=i}}return b|0}function Zb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;if(e>>>3|0){f=0;do{g=b+(f<<3)|0;h=d+(f<<3)|0;i=c[h>>2]|0;h=c[h+4>>2]|0;a[g+7>>0]=i;j=Rd(i|0,h|0,8)|0;a[g+6>>0]=j;j=Rd(i|0,h|0,16)|0;a[g+5>>0]=j;j=Rd(i|0,h|0,24)|0;a[g+4>>0]=j;a[g+3>>0]=h;j=Rd(i|0,h|0,40)|0;a[g+2>>0]=j;j=Rd(i|0,h|0,48)|0;a[g+1>>0]=j;h=Rd(i|0,h|0,56)|0;a[g>>0]=h;f=f+1|0}while((f|0)!=(e>>>3|0))}return}function _b(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;e=i;d=i=i+63&-64;i=i+48|0;b=jb(a)|0;if(!b){f=c[a+44>>2]|0;b=c[a+48>>2]|0;f=((f>>>0<b<<3>>>0?b<<3:f)>>>0)/(b<<2>>>0)|0;g=S(f,b<<2)|0;c[d>>2]=0;c[d+4>>2]=c[a+40>>2];c[d+8>>2]=g;c[d+12>>2]=f;c[d+16>>2]=f<<2;c[d+20>>2]=b;c[d+24>>2]=c[a+52>>2];c[d+28>>2]=1;b=Ob(d,a)|0;if(!b){b=Cb(d)|0;if(!b){pb(a,d);b=0}}}i=e;return b|0}function $b(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;l=0-(c[b+4>>2]|0)|0;k=0-(c[b+8>>2]|0)|0;j=0-(c[b+12>>2]|0)|0;i=0-(c[b+16>>2]|0)|0;h=0-(c[b+20>>2]|0)|0;g=0-(c[b+24>>2]|0)|0;f=0-(c[b+28>>2]|0)|0;e=0-(c[b+32>>2]|0)|0;d=0-(c[b+36>>2]|0)|0;c[a>>2]=0-(c[b>>2]|0);c[a+4>>2]=l;c[a+8>>2]=k;c[a+12>>2]=j;c[a+16>>2]=i;c[a+20>>2]=h;c[a+24>>2]=g;c[a+28>>2]=f;c[a+32>>2]=e;c[a+36>>2]=d;return}function ac(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;do if((l|0)==1){if((g|d|j)>>>0>0|(g|d|j|0)==0&(f|b|i)>>>0>4294967295|k>>>0>2147484671){c[(Zf()|0)>>2]=27;a=-1;break}if(d>>>0<0|(d|0)==0&b>>>0<16|(j>>>0<0|(j|0)==0&i>>>0<3)|k>>>0<8192){c[(Zf()|0)>>2]=22;a=-1;break}else{a=((Xd(i,k>>>10,e,f,h,a,b)|0)!=0)<<31>>31;break}}else a=-1;while(0);return a|0}function bc(a,b,d,e,f,g,h,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;n=i;m=i=i+63&-64;i=i+16|0;Hc(a|0,0,b|0)|0;if((g|d)>>>0>0|(g|d|0)==0&(f|b)>>>0>4294967295){c[(Zf()|0)>>2]=27;a=-1}else{ob(j,k,l,m+8|0,m+4|0,m);l=Pd(1,0,c[m+8>>2]|0)|0;a=Lc(e,f,h,32,l,D,c[m>>2]|0,c[m+4>>2]|0,a,b)|0}i=n;return a|0}function cc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;h=i;j=i=i+63&-64;i=i+368|0;if((b|0)==0&((e|0)!=0|(f|0)!=0))ba();if(!a)ba();if((d+-1&255)>63)ba();if(!((c|0)!=0|g<<24>>24==0))ba();if((g&255)>64)ba();if(!(g<<24>>24))Ib(j,d);else nb(j,d,c,g);ib(j,b,e,f);ab(j,a,d)|0;i=h;return}function dc(a,b){a=a|0;b=b|0;var c=0,d=0;c=i;d=i=i+63&-64;i=i+48|0;ra(a,b);ra(a+80|0,b+40|0);qa(a+120|0,b+80|0);Kb(a+40|0,b,b+40|0);ra(d,a+40|0);Kb(a+40|0,a+80|0,a);Jb(a+80|0,a+80|0,a);Jb(a,d,a+40|0);Jb(a+120|0,a+120|0,a+80|0);i=c;return}function ec(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;h=i;j=i=i+63&-64;i=i+16|0;Xc(a+64|0,d|0,e|0)|0;zb(a,j,a+64|0,e,f,g)|0;if((c[j>>2]|0)==64&(c[j+4>>2]|0)==0)if(b|0){a=oe(e|0,f|0,64,0)|0;c[b>>2]=a;c[b+4>>2]=D;a=0}else a=0;else{if(b|0){c[b>>2]=0;c[b+4>>2]=0}j=oe(e|0,f|0,64,0)|0;Hc(a|0,0,j|0)|0;a=-1}i=h;return a|0}function fc(a,b){a=a|0;b=b|0;var c=0,d=0;d=i;c=i=i+63&-64;i=i+240|0;if(!(za(c+80|0,b)|0)){Ud(c);Jb(c,c,c+80+40|0);Ia(c,c);Ud(c+40|0);Kb(c+40|0,c+40|0,c+80+40|0);pa(c+40|0,c+40|0,c);La(a,c+40|0);a=0}else a=-1;i=d;return a|0}function gc(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0;e=oe(e|0,f|0,-64,-1)|0;f=D;do if(f>>>0>0|(f|0)==0&e>>>0>4294967231)h=7;else{if(Xa(d,d+64|0,e,f,g)|0){Hc(a|0,0,e|0)|0;h=7;break}if(b|0){c[b>>2]=e;c[b+4>>2]=f}Xc(a|0,d+64|0,e|0)|0;e=0}while(0);if((h|0)==7)if(!b)e=-1;else{c[b>>2]=0;c[b+4>>2]=0;e=-1}return e|0}function hc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;l=c[b+4>>2]|0;k=c[b+8>>2]|0;j=c[b+12>>2]|0;i=c[b+16>>2]|0;h=c[b+20>>2]|0;g=c[b+24>>2]|0;f=c[b+28>>2]|0;e=c[b+32>>2]|0;d=c[b+36>>2]|0;c[a>>2]=c[b>>2];c[a+4>>2]=l;c[a+8>>2]=k;c[a+12>>2]=j;c[a+16>>2]=i;c[a+20>>2]=h;c[a+24>>2]=g;c[a+28>>2]=f;c[a+32>>2]=e;c[a+36>>2]=d;return}function ic(b,c,d,e,f,g){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0;j=i;h=i=i+63&-64;i=i+32|0;if(!(e>>>0<0|(e|0)==0&d>>>0<32)?(bd(h,32,0,f,g)|0,k=oe(d|0,e|0,-32,-1)|0,($d(c+16|0,c+32|0,k,D,h)|0)==0):0){Td(b,c,d,e,f,g)|0;c=b+32|0;do{a[b>>0]=0;b=b+1|0}while((b|0)<(c|0));b=0}else b=-1;i=j;return b|0}function jc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;i=a[b>>0]|0;a:do if((i+-48&255)<=9){g=0;h=b;f=i;while(1){e=(f<<24>>24)+-48|0;f=g*10|0;if(g>>>0>429496729|e>>>0>~f>>>0){e=0;break a}g=e+f|0;e=h+1|0;f=a[e>>0]|0;if((f+-48&255)>9)break;else h=e}if((e|0)!=(b|0)?(h|0)==(b|0)|i<<24>>24!=48:0)c[d>>2]=g;else e=0}else e=0;while(0);return e|0}function kc(b){b=b|0;var d=0,e=0,f=0;a:do if(!(b&3)){d=b;f=4}else{d=b;e=b;while(1){if(!(a[d>>0]|0)){d=e;break a}d=d+1|0;e=d;if(!(e&3)){f=4;break}}}while(0);if((f|0)==4){while(1){e=c[d>>2]|0;if(!((e&-2139062144^-2139062144)&e+-16843009))d=d+4|0;else break}if((e&255)<<24>>24)do d=d+1|0;while((a[d>>0]|0)!=0)}return d-b|0}function lc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;k=i;i=i+96|0;if(!(Ve(k+32|0,k)|0)){g=b;h=k+32|0;j=g+32|0;do{a[g>>0]=a[h>>0]|0;g=g+1|0;h=h+1|0}while((g|0)<(j|0));Uc(k+64|0,k+32|0,f);b=qd(b+32|0,c,d,e,k+64|0,f,k)|0;fd(k,32);fd(k+32|0,32);fd(k+64|0,24)}else b=-1;i=k;return b|0}function mc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;h=i;f=i=i+63&-64;i=i+128|0;if((qb(b,0,102)|0)==(b+101|0)){We(f);e=f+12|0;g=e+102|0;do{a[e>>0]=0;e=e+1|0}while((e|0)<(g|0));d=(yb(f,c,d,b,f+12|0)|0)==0;je(f);if(!d){e=Dc(f+12|0,b,102)|0;fd(f+12|0,102)}else e=-1}else e=-1;i=h;return e|0}function nc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;do if(!(c>>>0>64|(d+-1|0)>>>0>63)){if(d>>>0>=256)fa(32441,32461,77,32633);if(c>>>0>=256)fa(32540,32461,78,32633);if((b|0)==0|(c|0)==0){gb(a,d&255,e,f);a=0;break}else{Qa(a,d&255,b,c&255,e,f);a=0;break}}else a=-1;while(0);return a|0}function oc(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;if(g>>>0>0|(g|0)==0&f>>>0>15){d=oe(f|0,g|0,-16,-1)|0;a=lb(a,0,e,d,D,e+f+-16|0,h,i,j,k,l)|0}else a=-1;if(b|0){f=oe(f|0,g|0,-16,-1)|0;g=(a|0)==0;c[b>>2]=g?f:0;c[b+4>>2]=g?D:0}return a|0}function pc(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;if(g>>>0>0|(g|0)==0&f>>>0>15){d=oe(f|0,g|0,-16,-1)|0;a=Db(a,0,e,d,D,e+f+-16|0,h,i,j,k,l)|0}else a=-1;if(b|0){f=oe(f|0,g|0,-16,-1)|0;g=(a|0)==0;c[b>>2]=g?f:0;c[b+4>>2]=g?D:0}return a|0}function qc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=i;g=i=i+63&-64;i=i+112|0;c[g+32>>2]=0;c[g+32+4>>2]=0;c[g>>2]=c[8066];c[g+4>>2]=c[8067];c[g+8>>2]=c[8068];c[g+12>>2]=c[8069];c[g+16>>2]=c[8070];c[g+20>>2]=c[8071];c[g+24>>2]=c[8072];c[g+28>>2]=c[8073];Ua(g,b,d,e)|0;Fb(g,a)|0;i=f;return 0}function rc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;e=i=i+63&-64;i=i+16|0;Zb(e,a+64|0,16);f=Rd(c[a+72>>2]|0,c[a+72+4>>2]|0,3)|0;f=le((0<0|0==0&(f&127)>>>0<112?112:240)|0,(0<0|0==0&(f&127)>>>0<112?0:0)|0,f&127|0,0)|0;Na(a,32783,f,D)|0;Na(a,e,16,0)|0;Zb(b,a,64);fd(a,208);i=d;return 0}function sc(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0;if(!e)f=0;else{f=a[b>>0]|0;a:do if(!(f<<24>>24))f=0;else while(1){e=e+-1|0;g=a[c>>0]|0;if(!(f<<24>>24==g<<24>>24&((e|0)!=0&g<<24>>24!=0)))break a;b=b+1|0;c=c+1|0;f=a[b>>0]|0;if(!(f<<24>>24)){f=0;break}}while(0);f=(f&255)-(d[c>>0]|0)|0}return f|0}function tc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return da(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if(!e)return f|0;a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function uc(a,b,c,d,e,f,g,h,i){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;var j=0;do if(!((b+-1|0)>>>0>63|g>>>0>64)){if(b>>>0>=256)fa(32441,32461,36,32560);if(g>>>0<256){Xb(a,c,f,b&255,d,e,g&255,h,i);j=0;break}else fa(32540,32461,37,32560)}else j=-1;while(0);return j|0}function vc(b,c){b=b|0;c=c|0;var e=0,f=0;e=i;f=i=i+63&-64;i=i+160|0;Ia(f+80|0,c+80|0);pa(f+40|0,c,f+80|0);pa(f,c+40|0,f+80|0);La(b,f);La(f+120|0,f+40|0);a[b+31>>0]=(d[b+31>>0]|0)^(d[f+120>>0]|0)<<7;i=e;return}function wc(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;var g=0,h=0;if(!(f>>>0<2147483647&f<<1>>>0<c>>>0))ba();if(!f)c=0;else{c=0;do{h=d[e+c>>0]|0;g=c<<1;a[b+g>>0]=(h>>>4)+87+(((h>>>4)+65526|0)>>>8&217);a[b+(g|1)>>0]=(((h&15)<<8)+22272+((h&15)+65526&55552)|0)>>>8;c=c+1|0}while((c|0)!=(f|0));c=f<<1}a[b+c>>0]=0;return b|0}function xc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0;g=i;h=i=i+63&-64;i=i+208|0;c[h+64>>2]=0;c[h+64+4>>2]=0;c[h+64+8>>2]=0;c[h+64+12>>2]=0;f=h;j=400;k=f+64|0;do{c[f>>2]=c[j>>2];f=f+4|0;j=j+4|0}while((f|0)<(k|0));Na(h,b,d,e)|0;rc(h,a)|0;i=g;return 0}function yc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;do if(!(c>>>0>64|(d+-1|0)>>>0>63)){if(d>>>0>=256)fa(32441,32461,53,32601);if(c>>>0>=256)fa(32540,32461,54,32601);if((b|0)==0|(c|0)==0){Ib(a,d&255);a=0;break}else{nb(a,d&255,b,c&255);a=0;break}}else a=-1;while(0);return a|0}function zc(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;if(f>>>0>4294967295|(f|0)==-1&e>>>0>4294967279)ba();Ab(a,a+e|0,0,d,e,f,g,h,i,0,k,l)|0;if(b|0){k=oe(e|0,f|0,16,0)|0;c[b>>2]=k;c[b+4>>2]=D}return 0}function Ac(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;if(f>>>0>4294967295|(f|0)==-1&e>>>0>4294967279)ba();Nb(a,a+e|0,0,d,e,f,g,h,i,0,k,l)|0;if(b|0){k=oe(e|0,f|0,16,0)|0;c[b>>2]=k;c[b+4>>2]=D}return 0}function Bc(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0;f=i;g=i=i+63&-64;i=i+160|0;xc(c,e,32,0)|0;a[c>>0]=(d[c>>0]|0)&248;a[c+31>>0]=(d[c+31>>0]|0)&63|64;Pa(g,c);vc(b,g);Xc(c|0,e|0,32)|0;Xc(c+32|0,b|0,32)|0;i=f;return 0}function Cc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0;do if(!((b+-1|0)>>>0>63|g>>>0>64)){if(b>>>0>=256)fa(32441,32461,18,32513);if(g>>>0<256){cc(a,c,f,b&255,d,e,g&255);h=0;break}else fa(32540,32461,19,32513)}else h=-1;while(0);return h|0}function Dc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0;g=i;f=i=i+63&-64;i=i+16|0;c[f+4>>2]=b;c[f>>2]=d;if(!e)b=0;else{d=0;b=0;do{b=a[(c[f>>2]|0)+d>>0]^a[(c[f+4>>2]|0)+d>>0]|b;d=d+1|0}while((d|0)!=(e|0))}i=g;return (((b&255)+511|0)>>>8&1)+-1|0}function Ec(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;g=i;h=i=i+63&-64;i=i+64|0;xc(h,d,32,0)|0;d=c;e=h;f=d+32|0;do{a[d>>0]=a[e>>0]|0;d=d+1|0;e=e+1|0}while((d|0)<(f|0));fd(h,64);h=Qe(b,c)|0;i=g;return h|0}function Fc(b,c){b=b|0;c=c|0;var e=0,f=0,g=0;f=i;g=i=i+63&-64;i=i+64|0;xc(g,c,32,0)|0;a[g>>0]=(d[g>>0]|0)&248;a[g+31>>0]=(d[g+31>>0]|0)&63|64;c=g;e=b+32|0;do{a[b>>0]=a[c>>0]|0;b=b+1|0;c=c+1|0}while((b|0)<(e|0));fd(g,64);i=f;return 0}function Gc(b,c,d,e,f,g){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;if(e>>>0<0|(e|0)==0&d>>>0<32)b=-1;else{Td(b,c,d,e,f,g)|0;c=oe(d|0,e|0,-32,-1)|0;he(b+16|0,b+32|0,c,D,b)|0;c=b+16|0;do{a[b>>0]=0;b=b+1|0}while((b|0)<(c|0));b=0}return b|0}function Hc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=b+e|0;if((e|0)>=20){d=d&255;g=b&3;h=d|d<<8|d<<16|d<<24;if(g){g=b+4-g|0;while((b|0)<(g|0)){a[b>>0]=d;b=b+1|0}}while((b|0)<(f&~3|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b>>0]=d;b=b+1|0}return b-e|0}function Ic(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0;h=i;g=i=i+63&-64;i=i+32|0;if(d>>>0<0|(d|0)==0&c>>>0<48)a=-1;else{c=oe(c|0,d|0,-32,-1)|0;d=D;Uc(g,b,e);a=dd(a,b+32|0,c,d,g,b,f)|0}i=h;return a|0}function Jc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0;g=i;i=i+480|0;sb(g,f,32)|0;Ce(g,c,d,e)|0;od(g,g+416|0)|0;c=g+416|0;d=b+32|0;do{a[b>>0]=a[c>>0]|0;b=b+1|0;c=c+1|0}while((b|0)<(d|0));i=g;return 0}function Kc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;j=i;h=i=i+63&-64;i=i+32|0;if(!(Vc(h,f,g)|0)){a=Yd(a,b,c,d,e,h)|0;fd(h,32)}else a=-1;i=j;return a|0}function Lc(a,b,c,d,e,f,g,h,j,k){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0;l=i;m=i=i+63&-64;i=i+16|0;We(m);k=Ca(m,a,b,c,d,e,f,g,h,j,k)|0;je(m);i=l;return k|0}function Mc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;j=i;h=i=i+63&-64;i=i+32|0;if(!(Vc(h,f,g)|0)){a=ce(a,b,c,d,e,h)|0;fd(h,32)}else a=-1;i=j;return a|0}function Nc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;e=i;d=i=i+63&-64;i=i+16|0;f=Od(d,b)|0;c[(Zf()|0)>>2]=f;if(!f)d=c[d>>2]|0;else{c[d>>2]=0;d=0}c[a>>2]=d;c[a+4>>2]=d;c[a+8>>2]=d|0?b:0;i=e;return d|0}function Oc(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0;j=i;k=i=i+63&-64;i=i+32|0;Aa(k,e,h,0)|0;Ma(a,b,c,d,e+16|0,f,g,k)|0;fd(k,32);i=j;return 0}function Pc(a){a=a|0;var b=0,d=0;d=a+15&-16|0;b=c[k>>2]|0;a=b+d|0;if((d|0)>0&(a|0)<(b|0)|(a|0)<0){_()|0;ca(12);return -1}c[k>>2]=a;if((a|0)>(Z()|0)?(Y()|0)==0:0){ca(12);c[k>>2]=b;return -1}return b|0}function Qc(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0;j=i;i=i+32|0;if(!(Je(j,g,h)|0)){a=eb(a,b,c,d,e,f,j)|0;fd(j,32)}else a=-1;i=j;return a|0}function Rc(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0;j=i;i=i+32|0;if(!(Je(j,g,h)|0)){Ya(a,b,c,d,e,f,j)|0;fd(j,32);a=0}else a=-1;i=j;return a|0}function Sc(a){a=a|0;c[a+32>>2]=0;c[a+32+4>>2]=0;c[a>>2]=c[8066];c[a+4>>2]=c[8067];c[a+8>>2]=c[8068];c[a+12>>2]=c[8069];c[a+16>>2]=c[8070];c[a+20>>2]=c[8071];c[a+24>>2]=c[8072];c[a+28>>2]=c[8073];return 0}function Tc(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;if((l|0)==1)a=ac(a,b,d,e,f,g,h,i,j,k,1)|0;else{c[(Zf()|0)>>2]=22;a=-1}return a|0}function Uc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=i=i+63&-64;i=i+368|0;He(e,0,0,24)|0;xe(e,b,32,0)|0;xe(e,c,32,0)|0;Ne(e,a,24)|0;i=d;return}function Vc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;e=i;d=i=i+63&-64;i=i+32|0;if(!(_c(d,c,b)|0)){Aa(a,34476,d,0)|0;a=0}else a=-1;i=e;return a|0}function Wc(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0;f=i;i=i+32|0;Jc(f,b,c,d,e)|0;e=zd(a,f)|0;e=((f|0)==(a|0)?-1:e)|(Dc(f,a,32)|0);i=f;return e|0}function Xc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0;if((c|0)<(b|0)&(b|0)<(c+d|0)){e=b;c=c+d|0;b=b+d|0;while((d|0)>0){b=b-1|0;c=c-1|0;d=d-1|0;a[b>>0]=a[c>>0]|0}b=e}else tc(b,c,d)|0;return b|0}function Yc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;c=S(b&65535,a&65535)|0;e=(c>>>16)+(S(b&65535,a>>>16)|0)|0;d=S(b>>>16,a&65535)|0;return (D=(e>>>16)+(S(b>>>16,a>>>16)|0)+(((e&65535)+d|0)>>>16)|0,e+d<<16|c&65535|0)|0}function Zc(a,b){a=a|0;b=b|0;pa(a,b,b+120|0);pa(a+40|0,b+40|0,b+80|0);pa(a+80|0,b+80|0,b+120|0);pa(a+120|0,b,b+40|0);return}function _c(b,c,d){b=b|0;c=c|0;d=d|0;if(!(wa(b,c,d)|0)){c=0;d=0;do{d=a[b+c>>0]|d;c=c+1|0}while((c|0)!=32);c=0-(((d&255)+511|0)>>>8&1)|0}else c=-1;return c|0}function $c(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0;f=i;i=i+64|0;ld(f,b,c,d,e)|0;e=yd(a,f)|0;e=((f|0)==(a|0)?-1:e)|(Dc(f,a,64)|0);i=f;return e|0}function ad(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0;f=i;i=i+32|0;md(f,b,c,d,e)|0;e=zd(a,f)|0;e=((f|0)==(a|0)?-1:e)|(Dc(f,a,32)|0);i=f;return e|0}function bd(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;f=i;g=i=i+63&-64;i=i+32|0;Aa(g,d,e,0)|0;fb(a,b,c,d+16|0,g)|0;fd(g,32);i=f;return 0}function cd(a,b){a=a|0;b=b|0;var e=0,f=0,g=0;e=0;g=0;do{f=qb(32982,d[b>>0]|0,65)|0;if(!f){b=0;e=0;break}b=b+1|0;e=f-32982<<g|e;g=g+6|0}while(g>>>0<30);c[a>>2]=e;return b|0}function dd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;if(d>>>0<0|(d|0)==0&c>>>0<16)a=-1;else{d=oe(c|0,d|0,-16,-1)|0;a=Qc(a,b+16|0,b,d,D,e,f,g)|0}return a|0}function ed(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;f=i;g=i=i+63&-64;i=i+16|0;cb(g,b,c,d,e)|0;e=Ad(a,g)|0;i=f;return e|0}function fd(b,d){b=b|0;d=d|0;var e=0,f=0;e=i;f=i=i+63&-64;i=i+16|0;c[f>>2]=b;if(d|0){b=0;do{a[(c[f>>2]|0)+b>>0]=0;b=b+1|0}while((b|0)!=(d|0))}i=e;return}function gd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=0;do{g=b+(d<<3)|0;e=a+(d<<3)|0;f=c[e+4>>2]^c[g+4>>2];c[e>>2]=c[e>>2]^c[g>>2];c[e+4>>2]=f;d=d+1|0}while((d|0)!=128);return}function hd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;if(d>>>0<0|(d|0)==0&c>>>0<16)a=-1;else{d=oe(c|0,d|0,-16,-1)|0;a=eb(a,b+16|0,b,d,D,e,f)|0}return a|0}function id(b){b=b|0;var c=0;c=a[n+(b&255)>>0]|0;if((c|0)<8)return c|0;c=a[n+(b>>8&255)>>0]|0;if((c|0)<8)return c+8|0;c=a[n+(b>>16&255)>>0]|0;if((c|0)<8)return c+16|0;return (a[n+(b>>>24)>>0]|0)+24|0}function jd(b,c){b=b|0;c=c|0;var d=0,e=0;e=i;i=i+64|0;od(b,e)|0;b=e;d=c+32|0;do{a[c>>0]=a[b>>0]|0;c=c+1|0;b=b+1|0}while((c|0)<(d|0));i=e;return 0}function kd(b,c,d){b=b|0;c=c|0;d=d|0;if(!(d>>>0<1|(d|0)==1&c>>>0<0))fa(33884,33904,172,33930);if(c|0){d=0;do{a[b+d>>0]=$(0)|0;d=d+1|0}while((d|0)!=(c|0))}return}function ld(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0;f=i;i=i+416|0;sb(f,e,32)|0;Na(f,b,c,d)|0;od(f,a)|0;i=f;return 0}function md(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0;f=i;i=i+208|0;tb(f,e,32)|0;Ua(f,b,c,d)|0;pd(f,a)|0;i=f;return 0}function nd(a){a=a|0;var b=0,d=0;c[a+64>>2]=0;c[a+64+4>>2]=0;c[a+64+8>>2]=0;c[a+64+12>>2]=0;b=400;d=a+64|0;do{c[a>>2]=c[b>>2];a=a+4|0;b=b+4|0}while((a|0)<(d|0));return 0}function od(a,b){a=a|0;b=b|0;var c=0;c=i;i=i+64|0;rc(a,c)|0;Na(a+208|0,c,64,0)|0;rc(a+208|0,b)|0;fd(c,64);i=c;return 0}function pd(a,b){a=a|0;b=b|0;var c=0;c=i;i=i+32|0;Fb(a,c)|0;Ua(a+104|0,c,32,0)|0;Fb(a+104|0,b)|0;fd(c,32);i=c;return 0}function qd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;if(d>>>0>0|(d|0)==0&c>>>0>4294967279)a=-1;else a=Rc(a+16|0,a,b,c,d,e,f,g)|0;return a|0}function rd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;if(e>>>0>0|(e|0)==0&d>>>0>4294967295){c[(Zf()|0)>>2]=27;a=-1}else a=((df(a,b,d)|0)!=0)<<31>>31;return a|0}function sd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;if(d>>>0>0|(d|0)==0&c>>>0>4294967279)a=-1;else{Ya(a+16|0,a,b,c,d,e,f)|0;a=0}return a|0}function td(a){a=a|0;return (0-(a^62)|0)>>>8&43^43|(a+65510|0)>>>8&255&a+65|(0-(a^63)|0)>>>8&47^47|(a+65484|0)>>>8&a+71&((a+65510|0)>>>8&255^255)|(a+65474|0)>>>8&a+252&((a+65484|0)>>>8&255^255)|0}function ud(a,b){a=a|0;b=b|0;pa(a,b,b+120|0);pa(a+40|0,b+40|0,b+80|0);pa(a+80|0,b+80|0,b+120|0);return}function vd(a,b){a=a|0;b=b|0;var c=0,d=0;c=i;d=i=i+63&-64;i=i+32|0;Gd(d,32);Bc(a,b,d)|0;fd(d,32);i=c;return 0}function wd(a){a=a|0;var b=0;if(a>>>0<2)a=0;else{do b=$(0)|0;while(b>>>0<(((0-a|0)>>>0)%(a>>>0)|0)>>>0);a=(b>>>0)%(a>>>0)|0}return a|0}function xd(a,b,c){a=a|0;b=b|0;c=c|0;vb(a,b,c&255);vb(a+40|0,b+40|0,c&255);vb(a+80|0,b+80|0,c&255);return}function yd(b,c){b=b|0;c=c|0;var d=0,e=0;d=0;e=0;do{d=(a[c+e>>0]^a[b+e>>0])&255|d;e=e+1|0}while((e|0)!=64);return ((d+511|0)>>>8&1)+-1|0}function zd(b,c){b=b|0;c=c|0;var d=0,e=0;d=0;e=0;do{d=(a[c+e>>0]^a[b+e>>0])&255|d;e=e+1|0}while((e|0)!=32);return ((d+511|0)>>>8&1)+-1|0}function Ad(b,c){b=b|0;c=c|0;var d=0,e=0;d=0;e=0;do{d=(a[c+e>>0]^a[b+e>>0])&255|d;e=e+1|0}while((e|0)!=16);return ((d+511|0)>>>8&1)+-1|0}function Bd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=i;i=i+16|0;Ea(a,b,d,e,f|0)|0;i=f;return (D=c[f+4>>2]|0,c[f>>2]|0)|0}function Cd(){}function Dd(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){D=b>>c;return a>>>c|(b&(1<<c)-1)<<32-c}D=(b|0)<0?-1:0;return b>>c-32|0}function Ed(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=Yc(a,c)|0;f=D;return (D=(S(b,c)|0)+(S(d,a)|0)+f|f&0,e|0|0)|0}function Fd(a,b,c){a=a|0;b=b|0;c=c|0;if(c>>>0<256)return ab(a,b,c&255)|0;else fa(32441,32461,106,32679);return 0}function Gd(b,c){b=b|0;c=c|0;var d=0;if(c|0){d=0;do{a[b+d>>0]=$(0)|0;d=d+1|0}while((d|0)!=(c|0))}return}function Hd(b,c){b=b|0;c=c|0;var d=0;d=c;do{if(!d){c=0;break}d=d+-1|0;c=b+d|0}while((a[c>>0]|0)!=36);return c|0}function Id(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;return Za(a,b,c,d,e,f,g,h)|0}function Jd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return eb(a,b,c,d,e,f,g)|0}function Kd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return Kc(a,b,c,d,e,f,g)|0}function Ld(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return Va(a,b,c,d,e,f,g)|0}function Md(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;Ya(a,b,c,d,e,f,g)|0;return 0}function Nd(){var a=0;a=aa(30)|0;if((a|0)>0)c[8489]=a;else a=c[8489]|0;if(a>>>0<16)ba();else{Gd(34524,16);return}}function Od(a,b){a=a|0;b=b|0;var d=0;if(b>>>0<=4294967168?(d=rb(b)|0,(d|0)!=0):0){c[a>>2]=d;a=0}else a=12;return a|0}function Pd(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){D=b<<c|(a&(1<<c)-1<<32-c)>>>32-c;return a<<c}D=a<<c-32;return 0}function Qd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return Mc(a,b,c,d,e,f,g)|0}function Rd(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){D=b>>>c;return a>>>c|(b&(1<<c)-1)<<32-c}D=0;return b>>>c-32|0}function Sd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return Cc(a,b,c,d,e,f,g)|0}function Td(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;Oc(a,b,c,d,e,0,0,f)|0;return 0}function Ud(a){a=a|0;var b=0;c[a>>2]=1;a=a+4|0;b=a+36|0;do{c[a>>2]=0;a=a+4|0}while((a|0)<(b|0));return}function Vd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return Wb(a,b,c,d,e,f,g)|0}function Wd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;Ma(a,b,c,d,e,0,0,f)|0;return 0}function Xd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return xb(a,b,1,c,d,e,16,f,g,0,0)|0}function Yd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return ic(a,b,c,d,e,f)|0}function Zd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return Va(a,b,c,d,e,0,f)|0}function _d(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;zb(a,b,c,d,e,f)|0;return 0}function $d(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return ed(a,b,c,d,e)|0}function ae(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return xb(a,b,1,c,d,e,16,0,32,f,128)|0}function be(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return Za(a,b,c,d,e,0,0,f)|0}function ce(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return Gc(a,b,c,d,e,f)|0}function de(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;Td(a,b,c,d,e,f)|0;return 0}function ee(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return Yd(a,b,c,d,e,f)|0}function fe(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return Xa(a,b,c,d,e)|0}function ge(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return gc(a,b,c,d,e,f)|0}function he(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return cb(a,b,c,d,e)|0}function ie(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return $d(a,b,c,d,e)|0}function je(a){a=a|0;var b=0;b=c[a>>2]|0;if(b|0)ta(b);c[a+4>>2]=0;c[a>>2]=0;c[a+8>>2]=0;return}function ke(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return ce(a,b,c,d,e,f)|0}function le(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;d=b-d-(c>>>0>a>>>0|0)>>>0;return (D=d,a-c>>>0|0)|0}function me(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return ec(a,b,c,d,e,f)|0}function ne(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return Fe(a,b,c,d)|0}function oe(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return (D=b+d+(a+c>>>0>>>0<a>>>0|0)>>>0,a+c>>>0|0)|0}function pe(){var a=0;if(!(c[8488]|0)){pf();Nd();c[8488]=1;a=0}else a=1;return a|0}function qe(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return Wc(a,b,c,d,e)|0}function re(a){a=a|0;var b=0;b=a+40|0;do{c[a>>2]=0;a=a+4|0}while((a|0)<(b|0));return}function se(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;sa(a,b,c,d,e)|0;return 0}function te(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return he(a,b,c,d,e)|0}function ue(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;ib(a,b,c,d);return 0}function ve(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Ce(a,b,c,d)|0;return 0}function we(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return Wa(a,b,c,d,e)|0}function xe(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;ue(a,b,c,d)|0;return 0}function ye(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;Jc(a,b,c,d,e)|0;return 0}function ze(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;bd(a,b,c,d,e)|0;return 0}function Ae(a,b){a=a|0;b=b|0;Gd(b,32);return Qe(a,b)|0}function Be(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return ne(a,b,c,d)|0}function Ce(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Na(a,b,c,d)|0;return 0}function De(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Ua(a,b,c,d)|0;return 0}function Ee(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return rd(a,b,c,d)|0}function Fe(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Ra(a,b,c,d);return 0}function Ge(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return $a(a,b,c,d,e)|0}function He(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return yc(a,b,c,d)|0}function Ie(a,b,c){a=a|0;b=b|0;c=c|0;return Ec(a,b,c)|0}function Je(a,b,c){a=a|0;b=b|0;c=c|0;return Vc(a,b,c)|0}function Ke(b,c){b=b|0;c=c|0;b=Mb(b,c)|0;return ((a[b>>0]|0)==(c&255)<<24>>24?b:0)|0}function Le(a,b,c){a=a|0;b=b|0;c=c|0;sb(a,b,c)|0;return 0}function Me(a,b,c){a=a|0;b=b|0;c=c|0;Bc(a,b,c)|0;return 0}function Ne(a,b,c){a=a|0;b=b|0;c=c|0;return Fd(a,b,c)|0}function Oe(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+15&-16;return b|0}function Pe(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;xc(a,b,c,d)|0;return 0}function Qe(a,b){a=a|0;b=b|0;return Sb(a,b)|0}function Re(a,b){a=a|0;b=b|0;return $e(a,b)|0}function Se(a,b){a=a|0;b=b|0;return hb(a,b)|0}function Te(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return Ea(a,b,c,d,0)|0}function Ue(a,b,c){a=a|0;b=b|0;c=c|0;return _c(a,b,c)|0}function Ve(a,b){a=a|0;b=b|0;return Ae(a,b)|0}function We(a){a=a|0;c[a+4>>2]=0;c[a>>2]=0;c[a+8>>2]=0;return}function Xe(a,b){a=a|0;b=b|0;return Re(a,b)|0}function Ye(a,b){a=a|0;b=b|0;Xc(a|0,b+32|0,32)|0;return 0}function Ze(a,b){a=a|0;b=b|0;return Qe(a,b)|0}function _e(a,b){a=a|0;b=b|0;return Se(a,b)|0}function $e(a,b){a=a|0;b=b|0;Oa(a,b);return 0}function af(a,b){a=a|0;b=b|0;if(!o){o=a;p=b}}function bf(a,b){a=a|0;b=b|0;Xc(a|0,b|0,32)|0;return 0}function cf(a,b){a=a|0;b=b|0;vd(a,b)|0;return 0}function df(a,b,c){a=a|0;b=b|0;c=c|0;return kb(a,b,c)|0}function ef(a,b){a=a|0;b=b|0;tc(a|0,b|0,1024)|0;return}function ff(a,b){a=a|0;b=b|0;i=a;j=b}function gf(a){a=a|0;return Hd(a,(kc(a)|0)+1|0)|0}function hf(){return 1073741824}function jf(){return 16777216}function kf(a){a=a|0;Hc(a|0,0,1024)|0;return}function lf(){return 524288}function mf(){return 33047}function nf(){return $(0)|0}function of(){return 102}function pf(){ea(1);return}function qf(){return 33554432}function rf(){return 536870912}function sf(){return 12}function tf(){return 134217728}function uf(){return 33138}function vf(){return 416}function wf(){return 4}function xf(a){a=a|0;i=a}function yf(){return 32911}function zf(){return 32323}function Af(a){a=a|0;D=a}function Bf(){return 33051}function Cf(){return 6}function Df(){return 256}function Ef(){return 208}function Ff(){return 104}function Gf(){return 384}function Hf(){return 33079}function If(){return 33062}function Jf(){return 3}function Kf(){return 9}function Lf(){return 33129}function Mf(){return 32964}function Nf(){return 32974}function Of(){return 33942}function Pf(){return 33089}function Qf(){return 1}function Rf(){return 32712}function Sf(){return 128}function Tf(){return 32296}function Uf(){return 8}function Vf(){return 24}function Wf(){return D|0}function Xf(){return 48}function Yf(){return 16}function Zf(){return 33960}function _f(){return i|0}function $f(){return 64}function ag(){return 32}function bg(){return 0} - -// EMSCRIPTEN_END_FUNCS -return{_crypto_onetimeauth_poly1305_init:Se,_crypto_hash_sha512_init:nd,_crypto_hash_primitive:Rf,_crypto_onetimeauth_bytes:Yf,_crypto_box_open:Kd,_crypto_stream_chacha20_ietf_noncebytes:sf,_crypto_stream_salsa20_xor:Wd,_randombytes_buf:Gd,_crypto_auth_hmacsha512_verify:$c,_crypto_generichash_blake2b_keybytes_min:Yf,_crypto_sign_open:ge,_crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive:hf,_crypto_sign_ed25519_keypair:vd,_crypto_scalarmult_curve25519_base:Qe,_crypto_stream_salsa20:fb,_crypto_sign_ed25519_open:gc,_sodium_init:pe,_crypto_pwhash_scryptsalsa208sha256:bc,_crypto_scalarmult_primitive:Bf,_crypto_box_noncebytes:Vf,_crypto_aead_chacha20poly1305_ietf_keybytes:ag,_crypto_aead_chacha20poly1305_ietf_encrypt_detached:Ab,_crypto_scalarmult_base:Ze,_crypto_aead_chacha20poly1305_abytes:Yf,_crypto_auth_bytes:ag,_crypto_pwhash_opslimit_sensitive:Uf,_crypto_pwhash_strbytes:Sf,_crypto_auth_hmacsha512256_update:ve,_sbrk:Pc,_memcpy:tc,_crypto_onetimeauth_poly1305:he,_crypto_sign_secretkeybytes:$f,_crypto_generichash_primitive:zf,_crypto_auth_hmacsha512256:Jc,_crypto_box_seed_keypair:Ie,_crypto_auth_hmacsha512_init:sb,_crypto_generichash_blake2b_keybytes_max:$f,_crypto_box_curve25519xsalsa20poly1305_macbytes:Yf,_bitshift64Lshr:Rd,_crypto_pwhash_scryptsalsa208sha256_memlimit_interactive:jf,_crypto_sign_ed25519_sk_to_pk:Ye,_crypto_verify_16_bytes:Yf,_crypto_stream_xsalsa20:bd,_crypto_scalarmult_curve25519:_c,_crypto_box_open_easy_afternm:hd,_crypto_auth_hmacsha512:ld,_crypto_stream_chacha20_ietf_xor_ic:Ld,_crypto_hash:Pe,_crypto_box_curve25519xsalsa20poly1305_seedbytes:ag,_crypto_box_zerobytes:ag,_crypto_stream_salsa20_keybytes:ag,_crypto_auth_hmacsha512256_keybytes:ag,_crypto_aead_chacha20poly1305_keybytes:ag,_crypto_hash_sha512_bytes:$f,_crypto_verify_32:zd,_crypto_generichash_blake2b_final:Fd,_crypto_generichash_blake2b_init_salt_personal:nc,_crypto_box_seal:lc,_crypto_core_hsalsa20_outputbytes:ag,_free:ta,_crypto_sign_ed25519_publickeybytes:ag,_crypto_core_hsalsa20_keybytes:ag,_crypto_sign_primitive:Pf,_crypto_scalarmult_curve25519_bytes:ag,_crypto_auth_keybytes:ag,_crypto_box:Qd,_crypto_stream_xsalsa20_noncebytes:Vf,_crypto_onetimeauth_poly1305_keybytes:ag,_crypto_box_beforenm:Je,_crypto_box_curve25519xsalsa20poly1305_open_afternm:Yd,_crypto_pwhash_scryptsalsa208sha256_saltbytes:ag,_crypto_aead_chacha20poly1305_npubbytes:Uf,_crypto_stream_primitive:Lf,_crypto_pwhash_argon2i_str_verify:rd,_crypto_pwhash_memlimit_sensitive:rf,_crypto_shorthash:se,_crypto_onetimeauth_poly1305_bytes:Yf,_crypto_secretbox_detached:Ya,_crypto_box_curve25519xsalsa20poly1305_seed_keypair:Ec,_crypto_box_primitive:Tf,_crypto_pwhash_str:Vd,_crypto_box_detached_afternm:Md,_crypto_stream_salsa20_xor_ic:Ma,_crypto_secretbox_xsalsa20poly1305_boxzerobytes:Yf,_crypto_core_salsa20_constbytes:Yf,_crypto_auth_hmacsha512_keybytes:ag,_crypto_auth:ye,_crypto_auth_hmacsha512256_final:jd,_randombytes_random:nf,_crypto_stream_chacha20_keybytes:ag,_crypto_pwhash_str_verify:Ee,_crypto_sign_keypair:cf,_crypto_auth_hmacsha256_statebytes:Ef,_crypto_generichash_keybytes_min:Yf,_crypto_generichash_statebytes:Gf,_randombytes:kd,_crypto_aead_chacha20poly1305_encrypt_detached:Nb,_randombytes_implementation_name:uf,_crypto_core_salsa20_keybytes:ag,_sodium_library_version_major:Kf,_crypto_hash_sha256_statebytes:Ff,_crypto_pwhash_strprefix:Mf,_crypto_box_afternm:ke,_crypto_secretbox_primitive:If,_i64Add:oe,_malloc:na,_crypto_scalarmult_curve25519_scalarbytes:ag,_crypto_box_curve25519xsalsa20poly1305_keypair:Ae,_crypto_hash_sha256_init:Sc,_crypto_sign_ed25519_detached:zb,_crypto_pwhash_scryptsalsa208sha256_str_verify:mc,_crypto_generichash_init:He,_crypto_generichash_keybytes_max:$f,_crypto_sign_ed25519_pk_to_curve25519:fc,_crypto_stream_chacha20_ietf_xor:Zd,_crypto_verify_64:yd,_crypto_sign_publickeybytes:ag,_crypto_shorthash_siphash24:sa,_crypto_box_beforenmbytes:ag,_crypto_stream_chacha20_ietf:we,_crypto_generichash:Sd,_crypto_sign_ed25519:ec,_crypto_box_curve25519xsalsa20poly1305_open:Kc,_crypto_pwhash_opslimit_interactive:wf,_sodium_hex2bin:mb,_crypto_onetimeauth_poly1305_final:Re,_crypto_auth_hmacsha256_init:tb,_crypto_aead_chacha20poly1305_ietf_encrypt:zc,_crypto_aead_chacha20poly1305_ietf_nsecbytes:bg,_crypto_box_curve25519xsalsa20poly1305_noncebytes:Vf,_crypto_secretbox:ce,_crypto_box_boxzerobytes:Yf,_crypto_pwhash_argon2i_saltbytes:Yf,_crypto_hash_sha512_update:Na,_crypto_onetimeauth_poly1305_verify:$d,_crypto_box_curve25519xsalsa20poly1305_beforenmbytes:ag,_crypto_generichash_blake2b_init:yc,_crypto_aead_chacha20poly1305_ietf_decrypt:oc,_crypto_auth_hmacsha512256_init:Le,_crypto_pwhash_primitive:Nf,_crypto_onetimeauth_keybytes:ag,_crypto_pwhash_argon2i:ac,_crypto_auth_hmacsha512_final:od,_crypto_sign_ed25519_seedbytes:ag,_crypto_auth_hmacsha512256_verify:Wc,_crypto_auth_hmacsha256_final:pd,_crypto_box_secretkeybytes:ag,_crypto_verify_16:Ad,_crypto_stream_chacha20_noncebytes:Uf,_crypto_onetimeauth_update:Be,_crypto_aead_chacha20poly1305_encrypt:Ac,_crypto_core_salsa20:xa,_crypto_pwhash_scryptsalsa208sha256_ll:Lc,_crypto_box_detached:Rc,_crypto_stream_xsalsa20_xor:Td,_crypto_sign_seedbytes:ag,_memset:Hc,_crypto_pwhash_scryptsalsa208sha256_str:Hb,_crypto_generichash_blake2b_saltbytes:Yf,_bitshift64Ashr:Dd,_bitshift64Shl:Pd,_sodium_version_string:Of,_crypto_box_open_detached:Qc,_crypto_scalarmult_bytes:ag,_crypto_secretbox_xsalsa20poly1305:Gc,_crypto_pwhash:Tc,_crypto_auth_verify:qe,_crypto_sign_ed25519_seed_keypair:Bc,_crypto_secretbox_xsalsa20poly1305_zerobytes:ag,_crypto_onetimeauth_poly1305_update:ne,_crypto_sign_detached:_d,_crypto_verify_32_bytes:ag,_crypto_box_curve25519xsalsa20poly1305_zerobytes:ag,_crypto_generichash_blake2b_keybytes:ag,_crypto_sign_ed25519_secretkeybytes:$f,_crypto_stream_xor:de,_crypto_stream_xsalsa20_xor_ic:Oc,_crypto_verify_64_bytes:$f,_randombytes_stir:pf,_crypto_secretbox_easy:sd,_crypto_pwhash_argon2i_strprefix:Mf,_crypto_auth_hmacsha256_update:De,_crypto_pwhash_scryptsalsa208sha256_strbytes:of,_crypto_stream_chacha20:Ge,_crypto_stream_xsalsa20_keybytes:ag,_crypto_sign:me,_crypto_pwhash_argon2i_str:Wb,_crypto_box_open_detached_afternm:Jd,_crypto_pwhash_argon2i_memlimit_sensitive:rf,_crypto_box_sealbytes:Xf,_crypto_onetimeauth:te,_crypto_auth_hmacsha512_statebytes:vf,_crypto_secretbox_boxzerobytes:Yf,_i64Subtract:le,_crypto_pwhash_alg_default:Qf,_crypto_pwhash_scryptsalsa208sha256_strprefix:mf,_crypto_onetimeauth_primitive:yf,_crypto_box_seedbytes:ag,_crypto_hash_sha256_update:Ua,_crypto_core_hsalsa20_constbytes:Yf,_crypto_box_curve25519xsalsa20poly1305:Mc,_crypto_generichash_blake2b_statebytes:Gf,_crypto_box_curve25519xsalsa20poly1305_boxzerobytes:Yf,_crypto_generichash_blake2b_bytes_min:Yf,_crypto_pwhash_opslimit_moderate:Cf,_crypto_secretbox_open:Yd,_crypto_hash_sha256_bytes:ag,_crypto_core_salsa20_inputbytes:Yf,_crypto_box_macbytes:Yf,_crypto_shorthash_bytes:Uf,_crypto_box_publickeybytes:ag,___udivdi3:Te,_crypto_aead_chacha20poly1305_decrypt_detached:Db,_crypto_auth_hmacsha256_verify:ad,_crypto_pwhash_argon2i_strbytes:Sf,___muldsi3:Yc,_sodium_library_version_minor:Jf,_crypto_scalarmult_scalarbytes:ag,_crypto_onetimeauth_statebytes:Df,_crypto_auth_hmacsha256_bytes:ag,_crypto_sign_seed_keypair:Me,_crypto_pwhash_argon2i_opslimit_interactive:wf,_crypto_stream_salsa20_noncebytes:Uf,_crypto_shorthash_keybytes:Yf,___udivmoddi4:Ea,_crypto_box_curve25519xsalsa20poly1305_afternm:ce,_crypto_stream_noncebytes:Vf,_crypto_aead_chacha20poly1305_decrypt:pc,_sodium_bin2hex:wc,_crypto_secretbox_open_easy:hd,_crypto_aead_chacha20poly1305_ietf_decrypt_detached:lb,_crypto_pwhash_memlimit_interactive:qf,_crypto_hash_sha512_final:rc,_crypto_generichash_final:Ne,_crypto_secretbox_xsalsa20poly1305_keybytes:ag,_crypto_auth_hmacsha512_update:Ce,_crypto_pwhash_saltbytes:Yf,_crypto_auth_hmacsha256:md,_crypto_secretbox_noncebytes:Vf,_crypto_box_keypair:Ve,_crypto_secretbox_xsalsa20poly1305_macbytes:Yf,_crypto_box_open_afternm:ee,_crypto_auth_hmacsha512_bytes:$f,_crypto_generichash_keybytes:ag,_crypto_hash_bytes:$f,_crypto_generichash_bytes_min:Yf,_crypto_pwhash_argon2i_alg_argon2i13:Qf,_crypto_secretbox_macbytes:Yf,_crypto_secretbox_keybytes:ag,_crypto_auth_hmacsha256_keybytes:ag,_crypto_pwhash_argon2i_opslimit_sensitive:Uf,_crypto_aead_chacha20poly1305_ietf_abytes:Yf,_randombytes_close:bg,_crypto_pwhash_argon2i_memlimit_moderate:tf,_crypto_generichash_blake2b_bytes_max:$f,_crypto_generichash_blake2b:Cc,_crypto_generichash_bytes:ag,_crypto_generichash_bytes_max:$f,_crypto_secretbox_open_detached:eb,_crypto_sign_ed25519_sk_to_seed:bf,_crypto_sign_ed25519_sk_to_curve25519:Fc,_crypto_core_salsa20_outputbytes:$f,_crypto_box_easy_afternm:sd,___muldi3:Ed,_crypto_generichash_blake2b_personalbytes:Yf,_crypto_stream_chacha20_xor_ic:Id,___uremdi3:Bd,_crypto_sign_verify_detached:fe,_crypto_pwhash_argon2i_opslimit_moderate:Cf,_crypto_onetimeauth_verify:ie,_crypto_box_open_easy:dd,_crypto_stream:ze,_crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive:qf,_crypto_box_curve25519xsalsa20poly1305_secretkeybytes:ag,_crypto_aead_chacha20poly1305_nsecbytes:bg,_crypto_hash_sha512_statebytes:Ef,_crypto_sign_bytes:$f,_crypto_secretbox_zerobytes:ag,_crypto_generichash_update:xe,_crypto_scalarmult:Ue,_crypto_shorthash_primitive:Hf,_crypto_hash_sha512:xc,_llvm_cttz_i32:id,_crypto_stream_chacha20_xor:be,_crypto_box_seal_open:Ic,_crypto_box_easy:qd,_crypto_sign_ed25519_verify_detached:Xa,_memmove:Xc,_crypto_sign_ed25519_bytes:$f,_crypto_generichash_blake2b_update:ue,_crypto_hash_sha256:qc,_crypto_box_curve25519xsalsa20poly1305_beforenm:Vc,_crypto_pwhash_alg_argon2i13:Qf,_crypto_core_hsalsa20_inputbytes:Yf,_crypto_onetimeauth_final:Xe,_crypto_generichash_blake2b_bytes:ag,_crypto_auth_hmacsha512256_bytes:ag,_crypto_generichash_blake2b_salt_personal:uc,_randombytes_uniform:wd,_crypto_shorthash_siphash24_bytes:Uf,_crypto_auth_hmacsha512256_statebytes:vf,_crypto_shorthash_siphash24_keybytes:Yf,_crypto_secretbox_xsalsa20poly1305_noncebytes:Vf,_crypto_pwhash_scryptsalsa208sha256_opslimit_interactive:lf,_crypto_core_hsalsa20:Aa,_crypto_pwhash_argon2i_memlimit_interactive:qf,_crypto_hash_sha256_final:Fb,_crypto_secretbox_xsalsa20poly1305_open:ic,_crypto_stream_keybytes:ag,_crypto_box_curve25519xsalsa20poly1305_publickeybytes:ag,_crypto_onetimeauth_init:_e,_crypto_aead_chacha20poly1305_ietf_npubbytes:sf,_crypto_pwhash_memlimit_moderate:tf,runPostSets:Cd,stackAlloc:Oe,stackSave:_f,stackRestore:xf,establishStackSpace:ff,setThrew:af,setTempRet0:Af,getTempRet0:Wf}}) - - -// EMSCRIPTEN_END_ASM -(Module.asmGlobalArg,Module.asmLibraryArg,buffer);var _crypto_onetimeauth_poly1305_init=Module["_crypto_onetimeauth_poly1305_init"]=asm["_crypto_onetimeauth_poly1305_init"];var _crypto_hash_sha512_init=Module["_crypto_hash_sha512_init"]=asm["_crypto_hash_sha512_init"];var _crypto_stream_xsalsa20_noncebytes=Module["_crypto_stream_xsalsa20_noncebytes"]=asm["_crypto_stream_xsalsa20_noncebytes"];var _crypto_auth_hmacsha256_verify=Module["_crypto_auth_hmacsha256_verify"]=asm["_crypto_auth_hmacsha256_verify"];var _crypto_onetimeauth_bytes=Module["_crypto_onetimeauth_bytes"]=asm["_crypto_onetimeauth_bytes"];var _crypto_shorthash_primitive=Module["_crypto_shorthash_primitive"]=asm["_crypto_shorthash_primitive"];var _crypto_box_open=Module["_crypto_box_open"]=asm["_crypto_box_open"];var _crypto_stream_chacha20_ietf_noncebytes=Module["_crypto_stream_chacha20_ietf_noncebytes"]=asm["_crypto_stream_chacha20_ietf_noncebytes"];var _crypto_stream_salsa20_xor=Module["_crypto_stream_salsa20_xor"]=asm["_crypto_stream_salsa20_xor"];var _crypto_auth_hmacsha512_verify=Module["_crypto_auth_hmacsha512_verify"]=asm["_crypto_auth_hmacsha512_verify"];var _crypto_generichash_blake2b_keybytes_min=Module["_crypto_generichash_blake2b_keybytes_min"]=asm["_crypto_generichash_blake2b_keybytes_min"];var _crypto_generichash_blake2b_bytes=Module["_crypto_generichash_blake2b_bytes"]=asm["_crypto_generichash_blake2b_bytes"];var _crypto_pwhash_saltbytes=Module["_crypto_pwhash_saltbytes"]=asm["_crypto_pwhash_saltbytes"];var _crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive=Module["_crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive"]=asm["_crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive"];var _crypto_box_seal_open=Module["_crypto_box_seal_open"]=asm["_crypto_box_seal_open"];var _crypto_scalarmult_curve25519_base=Module["_crypto_scalarmult_curve25519_base"]=asm["_crypto_scalarmult_curve25519_base"];var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _sodium_bin2hex=Module["_sodium_bin2hex"]=asm["_sodium_bin2hex"];var _crypto_pwhash_scryptsalsa208sha256=Module["_crypto_pwhash_scryptsalsa208sha256"]=asm["_crypto_pwhash_scryptsalsa208sha256"];var _crypto_scalarmult_primitive=Module["_crypto_scalarmult_primitive"]=asm["_crypto_scalarmult_primitive"];var _crypto_secretbox_xsalsa20poly1305_open=Module["_crypto_secretbox_xsalsa20poly1305_open"]=asm["_crypto_secretbox_xsalsa20poly1305_open"];var _crypto_box_noncebytes=Module["_crypto_box_noncebytes"]=asm["_crypto_box_noncebytes"];var _crypto_aead_chacha20poly1305_ietf_keybytes=Module["_crypto_aead_chacha20poly1305_ietf_keybytes"]=asm["_crypto_aead_chacha20poly1305_ietf_keybytes"];var _crypto_aead_chacha20poly1305_ietf_encrypt_detached=Module["_crypto_aead_chacha20poly1305_ietf_encrypt_detached"]=asm["_crypto_aead_chacha20poly1305_ietf_encrypt_detached"];var _crypto_scalarmult_base=Module["_crypto_scalarmult_base"]=asm["_crypto_scalarmult_base"];var _crypto_aead_chacha20poly1305_abytes=Module["_crypto_aead_chacha20poly1305_abytes"]=asm["_crypto_aead_chacha20poly1305_abytes"];var _crypto_auth_bytes=Module["_crypto_auth_bytes"]=asm["_crypto_auth_bytes"];var _crypto_onetimeauth=Module["_crypto_onetimeauth"]=asm["_crypto_onetimeauth"];var _crypto_stream_chacha20_keybytes=Module["_crypto_stream_chacha20_keybytes"]=asm["_crypto_stream_chacha20_keybytes"];var _crypto_sign_open=Module["_crypto_sign_open"]=asm["_crypto_sign_open"];var _crypto_auth_hmacsha512256_update=Module["_crypto_auth_hmacsha512256_update"]=asm["_crypto_auth_hmacsha512256_update"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _crypto_onetimeauth_poly1305=Module["_crypto_onetimeauth_poly1305"]=asm["_crypto_onetimeauth_poly1305"];var _crypto_sign_ed25519_keypair=Module["_crypto_sign_ed25519_keypair"]=asm["_crypto_sign_ed25519_keypair"];var _crypto_pwhash=Module["_crypto_pwhash"]=asm["_crypto_pwhash"];var _crypto_auth_hmacsha512256=Module["_crypto_auth_hmacsha512256"]=asm["_crypto_auth_hmacsha512256"];var _crypto_shorthash_siphash24_keybytes=Module["_crypto_shorthash_siphash24_keybytes"]=asm["_crypto_shorthash_siphash24_keybytes"];var _crypto_box_seed_keypair=Module["_crypto_box_seed_keypair"]=asm["_crypto_box_seed_keypair"];var _crypto_auth_hmacsha512_init=Module["_crypto_auth_hmacsha512_init"]=asm["_crypto_auth_hmacsha512_init"];var _crypto_generichash_blake2b_keybytes_max=Module["_crypto_generichash_blake2b_keybytes_max"]=asm["_crypto_generichash_blake2b_keybytes_max"];var _crypto_box_beforenmbytes=Module["_crypto_box_beforenmbytes"]=asm["_crypto_box_beforenmbytes"];var _crypto_pwhash_scryptsalsa208sha256_memlimit_interactive=Module["_crypto_pwhash_scryptsalsa208sha256_memlimit_interactive"]=asm["_crypto_pwhash_scryptsalsa208sha256_memlimit_interactive"];var _crypto_sign_ed25519_sk_to_pk=Module["_crypto_sign_ed25519_sk_to_pk"]=asm["_crypto_sign_ed25519_sk_to_pk"];var _crypto_auth_hmacsha512_update=Module["_crypto_auth_hmacsha512_update"]=asm["_crypto_auth_hmacsha512_update"];var ___udivmoddi4=Module["___udivmoddi4"]=asm["___udivmoddi4"];var _crypto_stream_xsalsa20=Module["_crypto_stream_xsalsa20"]=asm["_crypto_stream_xsalsa20"];var _crypto_scalarmult_curve25519=Module["_crypto_scalarmult_curve25519"]=asm["_crypto_scalarmult_curve25519"];var _crypto_box_open_easy_afternm=Module["_crypto_box_open_easy_afternm"]=asm["_crypto_box_open_easy_afternm"];var _crypto_auth_hmacsha512=Module["_crypto_auth_hmacsha512"]=asm["_crypto_auth_hmacsha512"];var _crypto_stream_chacha20_ietf_xor_ic=Module["_crypto_stream_chacha20_ietf_xor_ic"]=asm["_crypto_stream_chacha20_ietf_xor_ic"];var _crypto_hash_sha256_update=Module["_crypto_hash_sha256_update"]=asm["_crypto_hash_sha256_update"];var _crypto_box_curve25519xsalsa20poly1305_seedbytes=Module["_crypto_box_curve25519xsalsa20poly1305_seedbytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_seedbytes"];var _crypto_box_zerobytes=Module["_crypto_box_zerobytes"]=asm["_crypto_box_zerobytes"];var _crypto_stream_salsa20_keybytes=Module["_crypto_stream_salsa20_keybytes"]=asm["_crypto_stream_salsa20_keybytes"];var _crypto_auth_hmacsha512256_keybytes=Module["_crypto_auth_hmacsha512256_keybytes"]=asm["_crypto_auth_hmacsha512256_keybytes"];var _randombytes_uniform=Module["_randombytes_uniform"]=asm["_randombytes_uniform"];var _crypto_aead_chacha20poly1305_keybytes=Module["_crypto_aead_chacha20poly1305_keybytes"]=asm["_crypto_aead_chacha20poly1305_keybytes"];var _crypto_hash_sha512_bytes=Module["_crypto_hash_sha512_bytes"]=asm["_crypto_hash_sha512_bytes"];var _crypto_onetimeauth_statebytes=Module["_crypto_onetimeauth_statebytes"]=asm["_crypto_onetimeauth_statebytes"];var _crypto_generichash_blake2b_final=Module["_crypto_generichash_blake2b_final"]=asm["_crypto_generichash_blake2b_final"];var _crypto_generichash_blake2b_init_salt_personal=Module["_crypto_generichash_blake2b_init_salt_personal"]=asm["_crypto_generichash_blake2b_init_salt_personal"];var _crypto_box_seal=Module["_crypto_box_seal"]=asm["_crypto_box_seal"];var _crypto_sign_ed25519_publickeybytes=Module["_crypto_sign_ed25519_publickeybytes"]=asm["_crypto_sign_ed25519_publickeybytes"];var _free=Module["_free"]=asm["_free"];var runPostSets=Module["runPostSets"]=asm["runPostSets"];var _crypto_core_hsalsa20_keybytes=Module["_crypto_core_hsalsa20_keybytes"]=asm["_crypto_core_hsalsa20_keybytes"];var _crypto_sign_primitive=Module["_crypto_sign_primitive"]=asm["_crypto_sign_primitive"];var ___uremdi3=Module["___uremdi3"]=asm["___uremdi3"];var _crypto_scalarmult_curve25519_bytes=Module["_crypto_scalarmult_curve25519_bytes"]=asm["_crypto_scalarmult_curve25519_bytes"];var _crypto_auth_keybytes=Module["_crypto_auth_keybytes"]=asm["_crypto_auth_keybytes"];var _crypto_box=Module["_crypto_box"]=asm["_crypto_box"];var _crypto_onetimeauth_poly1305_keybytes=Module["_crypto_onetimeauth_poly1305_keybytes"]=asm["_crypto_onetimeauth_poly1305_keybytes"];var _crypto_box_curve25519xsalsa20poly1305_open_afternm=Module["_crypto_box_curve25519xsalsa20poly1305_open_afternm"]=asm["_crypto_box_curve25519xsalsa20poly1305_open_afternm"];var _crypto_pwhash_scryptsalsa208sha256_saltbytes=Module["_crypto_pwhash_scryptsalsa208sha256_saltbytes"]=asm["_crypto_pwhash_scryptsalsa208sha256_saltbytes"];var _crypto_aead_chacha20poly1305_npubbytes=Module["_crypto_aead_chacha20poly1305_npubbytes"]=asm["_crypto_aead_chacha20poly1305_npubbytes"];var _crypto_stream_primitive=Module["_crypto_stream_primitive"]=asm["_crypto_stream_primitive"];var _crypto_pwhash_argon2i_str_verify=Module["_crypto_pwhash_argon2i_str_verify"]=asm["_crypto_pwhash_argon2i_str_verify"];var _crypto_onetimeauth_poly1305_final=Module["_crypto_onetimeauth_poly1305_final"]=asm["_crypto_onetimeauth_poly1305_final"];var _crypto_shorthash=Module["_crypto_shorthash"]=asm["_crypto_shorthash"];var _crypto_onetimeauth_poly1305_bytes=Module["_crypto_onetimeauth_poly1305_bytes"]=asm["_crypto_onetimeauth_poly1305_bytes"];var _crypto_secretbox_detached=Module["_crypto_secretbox_detached"]=asm["_crypto_secretbox_detached"];var _crypto_box_curve25519xsalsa20poly1305_seed_keypair=Module["_crypto_box_curve25519xsalsa20poly1305_seed_keypair"]=asm["_crypto_box_curve25519xsalsa20poly1305_seed_keypair"];var _crypto_box_primitive=Module["_crypto_box_primitive"]=asm["_crypto_box_primitive"];var _crypto_pwhash_str=Module["_crypto_pwhash_str"]=asm["_crypto_pwhash_str"];var _crypto_box_detached_afternm=Module["_crypto_box_detached_afternm"]=asm["_crypto_box_detached_afternm"];var _crypto_stream_salsa20_xor_ic=Module["_crypto_stream_salsa20_xor_ic"]=asm["_crypto_stream_salsa20_xor_ic"];var _crypto_secretbox_xsalsa20poly1305_boxzerobytes=Module["_crypto_secretbox_xsalsa20poly1305_boxzerobytes"]=asm["_crypto_secretbox_xsalsa20poly1305_boxzerobytes"];var _crypto_auth_hmacsha256_init=Module["_crypto_auth_hmacsha256_init"]=asm["_crypto_auth_hmacsha256_init"];var _crypto_auth_hmacsha512_keybytes=Module["_crypto_auth_hmacsha512_keybytes"]=asm["_crypto_auth_hmacsha512_keybytes"];var _crypto_auth=Module["_crypto_auth"]=asm["_crypto_auth"];var _crypto_auth_hmacsha512256_final=Module["_crypto_auth_hmacsha512256_final"]=asm["_crypto_auth_hmacsha512256_final"];var _randombytes_random=Module["_randombytes_random"]=asm["_randombytes_random"];var _crypto_onetimeauth_verify=Module["_crypto_onetimeauth_verify"]=asm["_crypto_onetimeauth_verify"];var _crypto_pwhash_str_verify=Module["_crypto_pwhash_str_verify"]=asm["_crypto_pwhash_str_verify"];var _crypto_sign_keypair=Module["_crypto_sign_keypair"]=asm["_crypto_sign_keypair"];var _crypto_sign_ed25519_open=Module["_crypto_sign_ed25519_open"]=asm["_crypto_sign_ed25519_open"];var _crypto_generichash_keybytes_min=Module["_crypto_generichash_keybytes_min"]=asm["_crypto_generichash_keybytes_min"];var _crypto_generichash_statebytes=Module["_crypto_generichash_statebytes"]=asm["_crypto_generichash_statebytes"];var _crypto_aead_chacha20poly1305_encrypt_detached=Module["_crypto_aead_chacha20poly1305_encrypt_detached"]=asm["_crypto_aead_chacha20poly1305_encrypt_detached"];var _crypto_core_salsa20_keybytes=Module["_crypto_core_salsa20_keybytes"]=asm["_crypto_core_salsa20_keybytes"];var _crypto_aead_chacha20poly1305_ietf_nsecbytes=Module["_crypto_aead_chacha20poly1305_ietf_nsecbytes"]=asm["_crypto_aead_chacha20poly1305_ietf_nsecbytes"];var _crypto_pwhash_strprefix=Module["_crypto_pwhash_strprefix"]=asm["_crypto_pwhash_strprefix"];var _crypto_box_afternm=Module["_crypto_box_afternm"]=asm["_crypto_box_afternm"];var _crypto_auth_hmacsha512256_bytes=Module["_crypto_auth_hmacsha512256_bytes"]=asm["_crypto_auth_hmacsha512256_bytes"];var _crypto_box_curve25519xsalsa20poly1305_keypair=Module["_crypto_box_curve25519xsalsa20poly1305_keypair"]=asm["_crypto_box_curve25519xsalsa20poly1305_keypair"];var _crypto_hash_sha256_init=Module["_crypto_hash_sha256_init"]=asm["_crypto_hash_sha256_init"];var _crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive=Module["_crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive"]=asm["_crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive"];var _crypto_pwhash_scryptsalsa208sha256_str_verify=Module["_crypto_pwhash_scryptsalsa208sha256_str_verify"]=asm["_crypto_pwhash_scryptsalsa208sha256_str_verify"];var _crypto_hash_primitive=Module["_crypto_hash_primitive"]=asm["_crypto_hash_primitive"];var _crypto_scalarmult_curve25519_scalarbytes=Module["_crypto_scalarmult_curve25519_scalarbytes"]=asm["_crypto_scalarmult_curve25519_scalarbytes"];var _crypto_sign_ed25519_pk_to_curve25519=Module["_crypto_sign_ed25519_pk_to_curve25519"]=asm["_crypto_sign_ed25519_pk_to_curve25519"];var _crypto_verify_64=Module["_crypto_verify_64"]=asm["_crypto_verify_64"];var _crypto_aead_chacha20poly1305_nsecbytes=Module["_crypto_aead_chacha20poly1305_nsecbytes"]=asm["_crypto_aead_chacha20poly1305_nsecbytes"];var _crypto_shorthash_siphash24=Module["_crypto_shorthash_siphash24"]=asm["_crypto_shorthash_siphash24"];var _crypto_box_curve25519xsalsa20poly1305_macbytes=Module["_crypto_box_curve25519xsalsa20poly1305_macbytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_macbytes"];var _crypto_stream_chacha20_ietf=Module["_crypto_stream_chacha20_ietf"]=asm["_crypto_stream_chacha20_ietf"];var _crypto_generichash=Module["_crypto_generichash"]=asm["_crypto_generichash"];var _crypto_sign_ed25519=Module["_crypto_sign_ed25519"]=asm["_crypto_sign_ed25519"];var _crypto_core_hsalsa20_outputbytes=Module["_crypto_core_hsalsa20_outputbytes"]=asm["_crypto_core_hsalsa20_outputbytes"];var _crypto_pwhash_opslimit_interactive=Module["_crypto_pwhash_opslimit_interactive"]=asm["_crypto_pwhash_opslimit_interactive"];var _crypto_box_curve25519xsalsa20poly1305_noncebytes=Module["_crypto_box_curve25519xsalsa20poly1305_noncebytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_noncebytes"];var _crypto_pwhash_memlimit_sensitive=Module["_crypto_pwhash_memlimit_sensitive"]=asm["_crypto_pwhash_memlimit_sensitive"];var _crypto_core_salsa20_constbytes=Module["_crypto_core_salsa20_constbytes"]=asm["_crypto_core_salsa20_constbytes"];var _crypto_box_boxzerobytes=Module["_crypto_box_boxzerobytes"]=asm["_crypto_box_boxzerobytes"];var _sodium_library_version_major=Module["_sodium_library_version_major"]=asm["_sodium_library_version_major"];var _crypto_verify_16_bytes=Module["_crypto_verify_16_bytes"]=asm["_crypto_verify_16_bytes"];var _crypto_aead_chacha20poly1305_ietf_encrypt=Module["_crypto_aead_chacha20poly1305_ietf_encrypt"]=asm["_crypto_aead_chacha20poly1305_ietf_encrypt"];var _crypto_pwhash_argon2i_saltbytes=Module["_crypto_pwhash_argon2i_saltbytes"]=asm["_crypto_pwhash_argon2i_saltbytes"];var _crypto_hash_sha512_update=Module["_crypto_hash_sha512_update"]=asm["_crypto_hash_sha512_update"];var _crypto_onetimeauth_poly1305_verify=Module["_crypto_onetimeauth_poly1305_verify"]=asm["_crypto_onetimeauth_poly1305_verify"];var _crypto_box_beforenm=Module["_crypto_box_beforenm"]=asm["_crypto_box_beforenm"];var _crypto_generichash_blake2b_init=Module["_crypto_generichash_blake2b_init"]=asm["_crypto_generichash_blake2b_init"];var _crypto_aead_chacha20poly1305_ietf_decrypt=Module["_crypto_aead_chacha20poly1305_ietf_decrypt"]=asm["_crypto_aead_chacha20poly1305_ietf_decrypt"];var _crypto_stream_chacha20_ietf_xor=Module["_crypto_stream_chacha20_ietf_xor"]=asm["_crypto_stream_chacha20_ietf_xor"];var _crypto_pwhash_primitive=Module["_crypto_pwhash_primitive"]=asm["_crypto_pwhash_primitive"];var _crypto_scalarmult=Module["_crypto_scalarmult"]=asm["_crypto_scalarmult"];var _crypto_onetimeauth_keybytes=Module["_crypto_onetimeauth_keybytes"]=asm["_crypto_onetimeauth_keybytes"];var _crypto_pwhash_argon2i=Module["_crypto_pwhash_argon2i"]=asm["_crypto_pwhash_argon2i"];var _crypto_auth_hmacsha512256_verify=Module["_crypto_auth_hmacsha512256_verify"]=asm["_crypto_auth_hmacsha512256_verify"];var _crypto_auth_hmacsha256_final=Module["_crypto_auth_hmacsha256_final"]=asm["_crypto_auth_hmacsha256_final"];var _crypto_box_secretkeybytes=Module["_crypto_box_secretkeybytes"]=asm["_crypto_box_secretkeybytes"];var _crypto_verify_16=Module["_crypto_verify_16"]=asm["_crypto_verify_16"];var _crypto_aead_chacha20poly1305_ietf_npubbytes=Module["_crypto_aead_chacha20poly1305_ietf_npubbytes"]=asm["_crypto_aead_chacha20poly1305_ietf_npubbytes"];var _crypto_onetimeauth_update=Module["_crypto_onetimeauth_update"]=asm["_crypto_onetimeauth_update"];var _crypto_aead_chacha20poly1305_encrypt=Module["_crypto_aead_chacha20poly1305_encrypt"]=asm["_crypto_aead_chacha20poly1305_encrypt"];var _crypto_secretbox_zerobytes=Module["_crypto_secretbox_zerobytes"]=asm["_crypto_secretbox_zerobytes"];var _crypto_core_salsa20=Module["_crypto_core_salsa20"]=asm["_crypto_core_salsa20"];var _llvm_cttz_i32=Module["_llvm_cttz_i32"]=asm["_llvm_cttz_i32"];var _crypto_box_curve25519xsalsa20poly1305_beforenmbytes=Module["_crypto_box_curve25519xsalsa20poly1305_beforenmbytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_beforenmbytes"];var _crypto_pwhash_scryptsalsa208sha256_ll=Module["_crypto_pwhash_scryptsalsa208sha256_ll"]=asm["_crypto_pwhash_scryptsalsa208sha256_ll"];var _crypto_box_detached=Module["_crypto_box_detached"]=asm["_crypto_box_detached"];var _randombytes_buf=Module["_randombytes_buf"]=asm["_randombytes_buf"];var _crypto_box_open_detached_afternm=Module["_crypto_box_open_detached_afternm"]=asm["_crypto_box_open_detached_afternm"];var _crypto_sign_seedbytes=Module["_crypto_sign_seedbytes"]=asm["_crypto_sign_seedbytes"];var _crypto_pwhash_scryptsalsa208sha256_strbytes=Module["_crypto_pwhash_scryptsalsa208sha256_strbytes"]=asm["_crypto_pwhash_scryptsalsa208sha256_strbytes"];var _crypto_generichash_blake2b_saltbytes=Module["_crypto_generichash_blake2b_saltbytes"]=asm["_crypto_generichash_blake2b_saltbytes"];var _bitshift64Ashr=Module["_bitshift64Ashr"]=asm["_bitshift64Ashr"];var _crypto_box_open_detached=Module["_crypto_box_open_detached"]=asm["_crypto_box_open_detached"];var _crypto_scalarmult_bytes=Module["_crypto_scalarmult_bytes"]=asm["_crypto_scalarmult_bytes"];var _crypto_secretbox_xsalsa20poly1305=Module["_crypto_secretbox_xsalsa20poly1305"]=asm["_crypto_secretbox_xsalsa20poly1305"];var _crypto_auth_verify=Module["_crypto_auth_verify"]=asm["_crypto_auth_verify"];var _crypto_sign_ed25519_seed_keypair=Module["_crypto_sign_ed25519_seed_keypair"]=asm["_crypto_sign_ed25519_seed_keypair"];var _crypto_secretbox_xsalsa20poly1305_zerobytes=Module["_crypto_secretbox_xsalsa20poly1305_zerobytes"]=asm["_crypto_secretbox_xsalsa20poly1305_zerobytes"];var _crypto_onetimeauth_poly1305_update=Module["_crypto_onetimeauth_poly1305_update"]=asm["_crypto_onetimeauth_poly1305_update"];var _crypto_auth_hmacsha512256_init=Module["_crypto_auth_hmacsha512256_init"]=asm["_crypto_auth_hmacsha512256_init"];var _crypto_auth_hmacsha256=Module["_crypto_auth_hmacsha256"]=asm["_crypto_auth_hmacsha256"];var _crypto_pwhash_strbytes=Module["_crypto_pwhash_strbytes"]=asm["_crypto_pwhash_strbytes"];var _crypto_stream_xor=Module["_crypto_stream_xor"]=asm["_crypto_stream_xor"];var _crypto_stream_xsalsa20_xor_ic=Module["_crypto_stream_xsalsa20_xor_ic"]=asm["_crypto_stream_xsalsa20_xor_ic"];var _crypto_verify_64_bytes=Module["_crypto_verify_64_bytes"]=asm["_crypto_verify_64_bytes"];var _randombytes_stir=Module["_randombytes_stir"]=asm["_randombytes_stir"];var _crypto_secretbox_easy=Module["_crypto_secretbox_easy"]=asm["_crypto_secretbox_easy"];var _crypto_box_open_easy=Module["_crypto_box_open_easy"]=asm["_crypto_box_open_easy"];var _crypto_pwhash_argon2i_strprefix=Module["_crypto_pwhash_argon2i_strprefix"]=asm["_crypto_pwhash_argon2i_strprefix"];var _crypto_auth_hmacsha256_update=Module["_crypto_auth_hmacsha256_update"]=asm["_crypto_auth_hmacsha256_update"];var _crypto_pwhash_scryptsalsa208sha256_str=Module["_crypto_pwhash_scryptsalsa208sha256_str"]=asm["_crypto_pwhash_scryptsalsa208sha256_str"];var _memset=Module["_memset"]=asm["_memset"];var _crypto_stream_salsa20=Module["_crypto_stream_salsa20"]=asm["_crypto_stream_salsa20"];var _crypto_pwhash_argon2i_str=Module["_crypto_pwhash_argon2i_str"]=asm["_crypto_pwhash_argon2i_str"];var _crypto_hash=Module["_crypto_hash"]=asm["_crypto_hash"];var _crypto_pwhash_argon2i_memlimit_sensitive=Module["_crypto_pwhash_argon2i_memlimit_sensitive"]=asm["_crypto_pwhash_argon2i_memlimit_sensitive"];var _crypto_pwhash_argon2i_opslimit_sensitive=Module["_crypto_pwhash_argon2i_opslimit_sensitive"]=asm["_crypto_pwhash_argon2i_opslimit_sensitive"];var _crypto_box_sealbytes=Module["_crypto_box_sealbytes"]=asm["_crypto_box_sealbytes"];var _crypto_auth_hmacsha512_final=Module["_crypto_auth_hmacsha512_final"]=asm["_crypto_auth_hmacsha512_final"];var _crypto_auth_hmacsha512_statebytes=Module["_crypto_auth_hmacsha512_statebytes"]=asm["_crypto_auth_hmacsha512_statebytes"];var _crypto_secretbox_boxzerobytes=Module["_crypto_secretbox_boxzerobytes"]=asm["_crypto_secretbox_boxzerobytes"];var _i64Subtract=Module["_i64Subtract"]=asm["_i64Subtract"];var _crypto_pwhash_alg_default=Module["_crypto_pwhash_alg_default"]=asm["_crypto_pwhash_alg_default"];var _crypto_pwhash_scryptsalsa208sha256_strprefix=Module["_crypto_pwhash_scryptsalsa208sha256_strprefix"]=asm["_crypto_pwhash_scryptsalsa208sha256_strprefix"];var _crypto_onetimeauth_primitive=Module["_crypto_onetimeauth_primitive"]=asm["_crypto_onetimeauth_primitive"];var _crypto_box_seedbytes=Module["_crypto_box_seedbytes"]=asm["_crypto_box_seedbytes"];var _crypto_stream_chacha20=Module["_crypto_stream_chacha20"]=asm["_crypto_stream_chacha20"];var _crypto_core_hsalsa20_constbytes=Module["_crypto_core_hsalsa20_constbytes"]=asm["_crypto_core_hsalsa20_constbytes"];var _crypto_generichash_bytes=Module["_crypto_generichash_bytes"]=asm["_crypto_generichash_bytes"];var _crypto_secretbox=Module["_crypto_secretbox"]=asm["_crypto_secretbox"];var _crypto_generichash_blake2b_statebytes=Module["_crypto_generichash_blake2b_statebytes"]=asm["_crypto_generichash_blake2b_statebytes"];var _crypto_box_open_afternm=Module["_crypto_box_open_afternm"]=asm["_crypto_box_open_afternm"];var _crypto_generichash_blake2b_bytes_min=Module["_crypto_generichash_blake2b_bytes_min"]=asm["_crypto_generichash_blake2b_bytes_min"];var _crypto_pwhash_opslimit_moderate=Module["_crypto_pwhash_opslimit_moderate"]=asm["_crypto_pwhash_opslimit_moderate"];var _crypto_secretbox_open=Module["_crypto_secretbox_open"]=asm["_crypto_secretbox_open"];var _crypto_auth_hmacsha512_bytes=Module["_crypto_auth_hmacsha512_bytes"]=asm["_crypto_auth_hmacsha512_bytes"];var _crypto_core_salsa20_inputbytes=Module["_crypto_core_salsa20_inputbytes"]=asm["_crypto_core_salsa20_inputbytes"];var _crypto_box_macbytes=Module["_crypto_box_macbytes"]=asm["_crypto_box_macbytes"];var _crypto_secretbox_macbytes=Module["_crypto_secretbox_macbytes"]=asm["_crypto_secretbox_macbytes"];var _crypto_shorthash_bytes=Module["_crypto_shorthash_bytes"]=asm["_crypto_shorthash_bytes"];var _crypto_box_publickeybytes=Module["_crypto_box_publickeybytes"]=asm["_crypto_box_publickeybytes"];var _crypto_generichash_keybytes=Module["_crypto_generichash_keybytes"]=asm["_crypto_generichash_keybytes"];var _crypto_generichash_primitive=Module["_crypto_generichash_primitive"]=asm["_crypto_generichash_primitive"];var _crypto_sign_secretkeybytes=Module["_crypto_sign_secretkeybytes"]=asm["_crypto_sign_secretkeybytes"];var _crypto_pwhash_argon2i_strbytes=Module["_crypto_pwhash_argon2i_strbytes"]=asm["_crypto_pwhash_argon2i_strbytes"];var ___muldsi3=Module["___muldsi3"]=asm["___muldsi3"];var _crypto_hash_sha512_statebytes=Module["_crypto_hash_sha512_statebytes"]=asm["_crypto_hash_sha512_statebytes"];var _crypto_scalarmult_scalarbytes=Module["_crypto_scalarmult_scalarbytes"]=asm["_crypto_scalarmult_scalarbytes"];var _crypto_verify_32=Module["_crypto_verify_32"]=asm["_crypto_verify_32"];var _crypto_auth_hmacsha256_bytes=Module["_crypto_auth_hmacsha256_bytes"]=asm["_crypto_auth_hmacsha256_bytes"];var _crypto_auth_hmacsha256_statebytes=Module["_crypto_auth_hmacsha256_statebytes"]=asm["_crypto_auth_hmacsha256_statebytes"];var _crypto_pwhash_argon2i_opslimit_interactive=Module["_crypto_pwhash_argon2i_opslimit_interactive"]=asm["_crypto_pwhash_argon2i_opslimit_interactive"];var _crypto_aead_chacha20poly1305_decrypt=Module["_crypto_aead_chacha20poly1305_decrypt"]=asm["_crypto_aead_chacha20poly1305_decrypt"];var _crypto_stream_salsa20_noncebytes=Module["_crypto_stream_salsa20_noncebytes"]=asm["_crypto_stream_salsa20_noncebytes"];var _crypto_shorthash_keybytes=Module["_crypto_shorthash_keybytes"]=asm["_crypto_shorthash_keybytes"];var _malloc=Module["_malloc"]=asm["_malloc"];var _crypto_stream_noncebytes=Module["_crypto_stream_noncebytes"]=asm["_crypto_stream_noncebytes"];var _crypto_generichash_keybytes_max=Module["_crypto_generichash_keybytes_max"]=asm["_crypto_generichash_keybytes_max"];var _sodium_version_string=Module["_sodium_version_string"]=asm["_sodium_version_string"];var _memmove=Module["_memmove"]=asm["_memmove"];var _crypto_aead_chacha20poly1305_ietf_decrypt_detached=Module["_crypto_aead_chacha20poly1305_ietf_decrypt_detached"]=asm["_crypto_aead_chacha20poly1305_ietf_decrypt_detached"];var _crypto_hash_sha512_final=Module["_crypto_hash_sha512_final"]=asm["_crypto_hash_sha512_final"];var _crypto_pwhash_memlimit_interactive=Module["_crypto_pwhash_memlimit_interactive"]=asm["_crypto_pwhash_memlimit_interactive"];var _crypto_secretbox_xsalsa20poly1305_keybytes=Module["_crypto_secretbox_xsalsa20poly1305_keybytes"]=asm["_crypto_secretbox_xsalsa20poly1305_keybytes"];var _crypto_aead_chacha20poly1305_decrypt_detached=Module["_crypto_aead_chacha20poly1305_decrypt_detached"]=asm["_crypto_aead_chacha20poly1305_decrypt_detached"];var _crypto_sign=Module["_crypto_sign"]=asm["_crypto_sign"];var _crypto_box_curve25519xsalsa20poly1305_zerobytes=Module["_crypto_box_curve25519xsalsa20poly1305_zerobytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_zerobytes"];var _crypto_secretbox_noncebytes=Module["_crypto_secretbox_noncebytes"]=asm["_crypto_secretbox_noncebytes"];var _crypto_box_keypair=Module["_crypto_box_keypair"]=asm["_crypto_box_keypair"];var _crypto_secretbox_xsalsa20poly1305_macbytes=Module["_crypto_secretbox_xsalsa20poly1305_macbytes"]=asm["_crypto_secretbox_xsalsa20poly1305_macbytes"];var _crypto_box_curve25519xsalsa20poly1305_boxzerobytes=Module["_crypto_box_curve25519xsalsa20poly1305_boxzerobytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_boxzerobytes"];var _crypto_hash_sha256_bytes=Module["_crypto_hash_sha256_bytes"]=asm["_crypto_hash_sha256_bytes"];var ___udivdi3=Module["___udivdi3"]=asm["___udivdi3"];var _crypto_hash_bytes=Module["_crypto_hash_bytes"]=asm["_crypto_hash_bytes"];var _sodium_hex2bin=Module["_sodium_hex2bin"]=asm["_sodium_hex2bin"];var _sodium_init=Module["_sodium_init"]=asm["_sodium_init"];var _crypto_box_curve25519xsalsa20poly1305_afternm=Module["_crypto_box_curve25519xsalsa20poly1305_afternm"]=asm["_crypto_box_curve25519xsalsa20poly1305_afternm"];var _crypto_auth_hmacsha256_keybytes=Module["_crypto_auth_hmacsha256_keybytes"]=asm["_crypto_auth_hmacsha256_keybytes"];var _crypto_secretbox_keybytes=Module["_crypto_secretbox_keybytes"]=asm["_crypto_secretbox_keybytes"];var _crypto_box_easy=Module["_crypto_box_easy"]=asm["_crypto_box_easy"];var _randombytes=Module["_randombytes"]=asm["_randombytes"];var _crypto_sign_publickeybytes=Module["_crypto_sign_publickeybytes"]=asm["_crypto_sign_publickeybytes"];var _randombytes_close=Module["_randombytes_close"]=asm["_randombytes_close"];var _crypto_pwhash_argon2i_memlimit_moderate=Module["_crypto_pwhash_argon2i_memlimit_moderate"]=asm["_crypto_pwhash_argon2i_memlimit_moderate"];var _crypto_generichash_blake2b_bytes_max=Module["_crypto_generichash_blake2b_bytes_max"]=asm["_crypto_generichash_blake2b_bytes_max"];var _crypto_generichash_blake2b=Module["_crypto_generichash_blake2b"]=asm["_crypto_generichash_blake2b"];var _crypto_stream_chacha20_noncebytes=Module["_crypto_stream_chacha20_noncebytes"]=asm["_crypto_stream_chacha20_noncebytes"];var _crypto_hash_sha256_statebytes=Module["_crypto_hash_sha256_statebytes"]=asm["_crypto_hash_sha256_statebytes"];var _crypto_secretbox_open_detached=Module["_crypto_secretbox_open_detached"]=asm["_crypto_secretbox_open_detached"];var _crypto_sign_ed25519_sk_to_seed=Module["_crypto_sign_ed25519_sk_to_seed"]=asm["_crypto_sign_ed25519_sk_to_seed"];var _crypto_core_salsa20_outputbytes=Module["_crypto_core_salsa20_outputbytes"]=asm["_crypto_core_salsa20_outputbytes"];var _crypto_sign_ed25519_secretkeybytes=Module["_crypto_sign_ed25519_secretkeybytes"]=asm["_crypto_sign_ed25519_secretkeybytes"];var _crypto_pwhash_opslimit_sensitive=Module["_crypto_pwhash_opslimit_sensitive"]=asm["_crypto_pwhash_opslimit_sensitive"];var ___muldi3=Module["___muldi3"]=asm["___muldi3"];var _crypto_generichash_blake2b_personalbytes=Module["_crypto_generichash_blake2b_personalbytes"]=asm["_crypto_generichash_blake2b_personalbytes"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _crypto_box_curve25519xsalsa20poly1305_open=Module["_crypto_box_curve25519xsalsa20poly1305_open"]=asm["_crypto_box_curve25519xsalsa20poly1305_open"];var _crypto_sign_verify_detached=Module["_crypto_sign_verify_detached"]=asm["_crypto_sign_verify_detached"];var _crypto_pwhash_argon2i_opslimit_moderate=Module["_crypto_pwhash_argon2i_opslimit_moderate"]=asm["_crypto_pwhash_argon2i_opslimit_moderate"];var _crypto_pwhash_alg_argon2i13=Module["_crypto_pwhash_alg_argon2i13"]=asm["_crypto_pwhash_alg_argon2i13"];var _randombytes_implementation_name=Module["_randombytes_implementation_name"]=asm["_randombytes_implementation_name"];var _crypto_box_curve25519xsalsa20poly1305=Module["_crypto_box_curve25519xsalsa20poly1305"]=asm["_crypto_box_curve25519xsalsa20poly1305"];var _crypto_stream=Module["_crypto_stream"]=asm["_crypto_stream"];var _crypto_sign_ed25519_detached=Module["_crypto_sign_ed25519_detached"]=asm["_crypto_sign_ed25519_detached"];var _crypto_generichash_init=Module["_crypto_generichash_init"]=asm["_crypto_generichash_init"];var _i64Add=Module["_i64Add"]=asm["_i64Add"];var _crypto_sign_ed25519_sk_to_curve25519=Module["_crypto_sign_ed25519_sk_to_curve25519"]=asm["_crypto_sign_ed25519_sk_to_curve25519"];var _crypto_sign_bytes=Module["_crypto_sign_bytes"]=asm["_crypto_sign_bytes"];var _crypto_secretbox_primitive=Module["_crypto_secretbox_primitive"]=asm["_crypto_secretbox_primitive"];var _crypto_generichash_update=Module["_crypto_generichash_update"]=asm["_crypto_generichash_update"];var _crypto_generichash_blake2b_update=Module["_crypto_generichash_blake2b_update"]=asm["_crypto_generichash_blake2b_update"];var _crypto_verify_32_bytes=Module["_crypto_verify_32_bytes"]=asm["_crypto_verify_32_bytes"];var _crypto_aead_chacha20poly1305_ietf_abytes=Module["_crypto_aead_chacha20poly1305_ietf_abytes"]=asm["_crypto_aead_chacha20poly1305_ietf_abytes"];var _crypto_generichash_blake2b_keybytes=Module["_crypto_generichash_blake2b_keybytes"]=asm["_crypto_generichash_blake2b_keybytes"];var _crypto_generichash_bytes_min=Module["_crypto_generichash_bytes_min"]=asm["_crypto_generichash_bytes_min"];var _crypto_box_curve25519xsalsa20poly1305_secretkeybytes=Module["_crypto_box_curve25519xsalsa20poly1305_secretkeybytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_secretkeybytes"];var _crypto_stream_xsalsa20_xor=Module["_crypto_stream_xsalsa20_xor"]=asm["_crypto_stream_xsalsa20_xor"];var _crypto_sign_detached=Module["_crypto_sign_detached"]=asm["_crypto_sign_detached"];var _crypto_hash_sha512=Module["_crypto_hash_sha512"]=asm["_crypto_hash_sha512"];var _crypto_generichash_bytes_max=Module["_crypto_generichash_bytes_max"]=asm["_crypto_generichash_bytes_max"];var _crypto_box_easy_afternm=Module["_crypto_box_easy_afternm"]=asm["_crypto_box_easy_afternm"];var _crypto_stream_chacha20_xor_ic=Module["_crypto_stream_chacha20_xor_ic"]=asm["_crypto_stream_chacha20_xor_ic"];var _crypto_sign_ed25519_verify_detached=Module["_crypto_sign_ed25519_verify_detached"]=asm["_crypto_sign_ed25519_verify_detached"];var _crypto_sign_ed25519_bytes=Module["_crypto_sign_ed25519_bytes"]=asm["_crypto_sign_ed25519_bytes"];var _crypto_stream_xsalsa20_keybytes=Module["_crypto_stream_xsalsa20_keybytes"]=asm["_crypto_stream_xsalsa20_keybytes"];var _crypto_hash_sha256=Module["_crypto_hash_sha256"]=asm["_crypto_hash_sha256"];var _crypto_sign_ed25519_seedbytes=Module["_crypto_sign_ed25519_seedbytes"]=asm["_crypto_sign_ed25519_seedbytes"];var _sodium_library_version_minor=Module["_sodium_library_version_minor"]=asm["_sodium_library_version_minor"];var _crypto_core_hsalsa20_inputbytes=Module["_crypto_core_hsalsa20_inputbytes"]=asm["_crypto_core_hsalsa20_inputbytes"];var _crypto_onetimeauth_final=Module["_crypto_onetimeauth_final"]=asm["_crypto_onetimeauth_final"];var _crypto_secretbox_open_easy=Module["_crypto_secretbox_open_easy"]=asm["_crypto_secretbox_open_easy"];var _crypto_generichash_final=Module["_crypto_generichash_final"]=asm["_crypto_generichash_final"];var _crypto_generichash_blake2b_salt_personal=Module["_crypto_generichash_blake2b_salt_personal"]=asm["_crypto_generichash_blake2b_salt_personal"];var _crypto_pwhash_argon2i_alg_argon2i13=Module["_crypto_pwhash_argon2i_alg_argon2i13"]=asm["_crypto_pwhash_argon2i_alg_argon2i13"];var _crypto_shorthash_siphash24_bytes=Module["_crypto_shorthash_siphash24_bytes"]=asm["_crypto_shorthash_siphash24_bytes"];var _crypto_auth_hmacsha512256_statebytes=Module["_crypto_auth_hmacsha512256_statebytes"]=asm["_crypto_auth_hmacsha512256_statebytes"];var _crypto_sign_seed_keypair=Module["_crypto_sign_seed_keypair"]=asm["_crypto_sign_seed_keypair"];var _crypto_secretbox_xsalsa20poly1305_noncebytes=Module["_crypto_secretbox_xsalsa20poly1305_noncebytes"]=asm["_crypto_secretbox_xsalsa20poly1305_noncebytes"];var _crypto_pwhash_scryptsalsa208sha256_opslimit_interactive=Module["_crypto_pwhash_scryptsalsa208sha256_opslimit_interactive"]=asm["_crypto_pwhash_scryptsalsa208sha256_opslimit_interactive"];var _crypto_box_curve25519xsalsa20poly1305_beforenm=Module["_crypto_box_curve25519xsalsa20poly1305_beforenm"]=asm["_crypto_box_curve25519xsalsa20poly1305_beforenm"];var _crypto_pwhash_argon2i_memlimit_interactive=Module["_crypto_pwhash_argon2i_memlimit_interactive"]=asm["_crypto_pwhash_argon2i_memlimit_interactive"];var _crypto_hash_sha256_final=Module["_crypto_hash_sha256_final"]=asm["_crypto_hash_sha256_final"];var _crypto_stream_chacha20_xor=Module["_crypto_stream_chacha20_xor"]=asm["_crypto_stream_chacha20_xor"];var _crypto_stream_keybytes=Module["_crypto_stream_keybytes"]=asm["_crypto_stream_keybytes"];var _crypto_box_curve25519xsalsa20poly1305_publickeybytes=Module["_crypto_box_curve25519xsalsa20poly1305_publickeybytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_publickeybytes"];var _crypto_onetimeauth_init=Module["_crypto_onetimeauth_init"]=asm["_crypto_onetimeauth_init"];var _crypto_core_hsalsa20=Module["_crypto_core_hsalsa20"]=asm["_crypto_core_hsalsa20"];var _crypto_pwhash_memlimit_moderate=Module["_crypto_pwhash_memlimit_moderate"]=asm["_crypto_pwhash_memlimit_moderate"];Runtime.stackAlloc=asm["stackAlloc"];Runtime.stackSave=asm["stackSave"];Runtime.stackRestore=asm["stackRestore"];Runtime.establishStackSpace=asm["establishStackSpace"];Runtime.setTempRet0=asm["setTempRet0"];Runtime.getTempRet0=asm["getTempRet0"];function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;var preloadStartTime=null;var calledMain=false;dependenciesFulfilled=function runCaller(){if(!Module["calledRun"])run();if(!Module["calledRun"])dependenciesFulfilled=runCaller};Module["callMain"]=Module.callMain=function callMain(args){args=args||[];ensureInitRuntime();var argc=args.length+1;function pad(){for(var i=0;i<4-1;i++){argv.push(0)}}var argv=[allocate(intArrayFromString(Module["thisProgram"]),"i8",ALLOC_NORMAL)];pad();for(var i=0;i<argc-1;i=i+1){argv.push(allocate(intArrayFromString(args[i]),"i8",ALLOC_NORMAL));pad()}argv.push(0);argv=allocate(argv,"i32",ALLOC_NORMAL);try{var ret=Module["_main"](argc,argv,0);exit(ret,true)}catch(e){if(e instanceof ExitStatus){return}else if(e=="SimulateInfiniteLoop"){Module["noExitRuntime"]=true;return}else{if(e&&typeof e==="object"&&e.stack)Module.printErr("exception thrown: "+[e,e.stack]);throw e}}finally{calledMain=true}};function run(args){args=args||Module["arguments"];if(preloadStartTime===null)preloadStartTime=Date.now();if(runDependencies>0){return}preRun();if(runDependencies>0)return;if(Module["calledRun"])return;function doRun(){if(Module["calledRun"])return;Module["calledRun"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(Module["_main"]&&shouldRunNow)Module["callMain"](args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}Module["run"]=Module.run=run;function exit(status,implicit){if(implicit&&Module["noExitRuntime"]){return}if(Module["noExitRuntime"]){}else{ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(Module["onExit"])Module["onExit"](status)}if(ENVIRONMENT_IS_NODE){process["exit"](status)}else if(ENVIRONMENT_IS_SHELL&&typeof quit==="function"){quit(status)}throw new ExitStatus(status)}Module["exit"]=Module.exit=exit;var abortDecorators=[];function abort(what){if(what!==undefined){Module.print(what);Module.printErr(what);what=JSON.stringify(what)}else{what=""}ABORT=true;EXITSTATUS=1;var extra="\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";var output="abort("+what+") at "+stackTrace()+extra;if(abortDecorators){abortDecorators.forEach((function(decorator){output=decorator(output,what)}))}throw output}Module["abort"]=Module.abort=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"]){shouldRunNow=false}run() - - - - -var nacl = (function () { - 'use strict'; - var exports = {}; - - //--------------------------------------------------------------------------- - // Horrifying UTF-8 and hex codecs - - function encode_utf8(s) { - return encode_latin1(unescape(encodeURIComponent(s))); - } - - function encode_latin1(s) { - var result = new Uint8Array(s.length); - for (var i = 0; i < s.length; i++) { - var c = s.charCodeAt(i); - if ((c & 0xff) !== c) throw {message: "Cannot encode string in Latin1", str: s}; - result[i] = (c & 0xff); - } - return result; - } - - function decode_utf8(bs) { - return decodeURIComponent(escape(decode_latin1(bs))); - } - - function decode_latin1(bs) { - var encoded = []; - for (var i = 0; i < bs.length; i++) { - encoded.push(String.fromCharCode(bs[i])); - } - return encoded.join(''); - } - - function to_hex(bs) { - var encoded = []; - for (var i = 0; i < bs.length; i++) { - encoded.push("0123456789abcdef"[(bs[i] >> 4) & 15]); - encoded.push("0123456789abcdef"[bs[i] & 15]); - } - return encoded.join(''); - } - - function from_hex(s) { - var result = new Uint8Array(s.length / 2); - for (var i = 0; i < s.length / 2; i++) { - result[i] = parseInt(s.substr(2*i,2),16); - } - return result; - } - - //--------------------------------------------------------------------------- - // Allocation - - function MALLOC(nbytes) { - var result = nacl_raw._malloc(nbytes); - if (result === 0) { - throw {message: "malloc() failed", nbytes: nbytes}; - } - return result; - } - - function FREE(pointer) { - nacl_raw._free(pointer); - } - - //--------------------------------------------------------------------------- - - function injectBytes(bs, leftPadding) { - var p = leftPadding || 0; - var address = MALLOC(bs.length + p); - nacl_raw.HEAPU8.set(bs, address + p); - for (var i = address; i < address + p; i++) { - nacl_raw.HEAPU8[i] = 0; - } - return address; - } - - function check_injectBytes(function_name, what, thing, expected_length, leftPadding) { - check_length(function_name, what, thing, expected_length); - return injectBytes(thing, leftPadding); - } - - function extractBytes(address, length) { - var result = new Uint8Array(length); - result.set(nacl_raw.HEAPU8.subarray(address, address + length)); - return result; - } - - //--------------------------------------------------------------------------- - - function check(function_name, result) { - if (result !== 0) { - throw {message: "nacl_raw." + function_name + " signalled an error"}; - } - } - - function check_length(function_name, what, thing, expected_length) { - if (thing.length !== expected_length) { - throw {message: "nacl." + function_name + " expected " + - expected_length + "-byte " + what + " but got length " + thing.length}; - } - } - - function Target(length) { - this.length = length; - this.address = MALLOC(length); - } - - Target.prototype.extractBytes = function (offset) { - var result = extractBytes(this.address + (offset || 0), this.length - (offset || 0)); - FREE(this.address); - this.address = null; - return result; - }; - - function free_all(addresses) { - for (var i = 0; i < addresses.length; i++) { - FREE(addresses[i]); - } - } - - //--------------------------------------------------------------------------- - // Randomness - - function random_bytes(count) { - var bs = new Target(count); - nacl_raw._randombytes_buf(bs.address, count); - return bs.extractBytes(); - } - - nacl_raw._randombytes_stir(); - - //--------------------------------------------------------------------------- - // Boxing - - function crypto_box_keypair() { - var pk = new Target(nacl_raw._crypto_box_publickeybytes()); - var sk = new Target(nacl_raw._crypto_box_secretkeybytes()); - check("_crypto_box_keypair", nacl_raw._crypto_box_keypair(pk.address, sk.address)); - return {boxPk: pk.extractBytes(), boxSk: sk.extractBytes()}; - } - - function crypto_box_random_nonce() { - return random_bytes(nacl_raw._crypto_box_noncebytes()); - } - - function crypto_box(msg, nonce, pk, sk) { - var m = injectBytes(msg, nacl_raw._crypto_box_zerobytes()); - var na = check_injectBytes("crypto_box", "nonce", nonce, nacl_raw._crypto_box_noncebytes()); - var pka = check_injectBytes("crypto_box", "pk", pk, nacl_raw._crypto_box_publickeybytes()); - var ska = check_injectBytes("crypto_box", "sk", sk, nacl_raw._crypto_box_secretkeybytes()); - var c = new Target(msg.length + nacl_raw._crypto_box_zerobytes()); - check("_crypto_box", nacl_raw._crypto_box(c.address, m, c.length, 0, na, pka, ska)); - free_all([m, na, pka, ska]); - return c.extractBytes(nacl_raw._crypto_box_boxzerobytes()); - } - - function crypto_box_open(ciphertext, nonce, pk, sk) { - var c = injectBytes(ciphertext, nacl_raw._crypto_box_boxzerobytes()); - var na = check_injectBytes("crypto_box_open", - "nonce", nonce, nacl_raw._crypto_box_noncebytes()); - var pka = check_injectBytes("crypto_box_open", - "pk", pk, nacl_raw._crypto_box_publickeybytes()); - var ska = check_injectBytes("crypto_box_open", - "sk", sk, nacl_raw._crypto_box_secretkeybytes()); - var m = new Target(ciphertext.length + nacl_raw._crypto_box_boxzerobytes()); - check("_crypto_box_open", nacl_raw._crypto_box_open(m.address, c, m.length, 0, na, pka, ska)); - free_all([c, na, pka, ska]); - return m.extractBytes(nacl_raw._crypto_box_zerobytes()); - } - - function crypto_box_precompute(pk, sk) { - var pka = check_injectBytes("crypto_box_precompute", - "pk", pk, nacl_raw._crypto_box_publickeybytes()); - var ska = check_injectBytes("crypto_box_precompute", - "sk", sk, nacl_raw._crypto_box_secretkeybytes()); - var k = new Target(nacl_raw._crypto_box_beforenmbytes()); - check("_crypto_box_beforenm", - nacl_raw._crypto_box_beforenm(k.address, pka, ska)); - free_all([pka, ska]); - return {boxK: k.extractBytes()}; - } - - function crypto_box_precomputed(msg, nonce, state) { - var m = injectBytes(msg, nacl_raw._crypto_box_zerobytes()); - var na = check_injectBytes("crypto_box_precomputed", - "nonce", nonce, nacl_raw._crypto_box_noncebytes()); - var ka = check_injectBytes("crypto_box_precomputed", - "boxK", state.boxK, nacl_raw._crypto_box_beforenmbytes()); - var c = new Target(msg.length + nacl_raw._crypto_box_zerobytes()); - check("_crypto_box_afternm", - nacl_raw._crypto_box_afternm(c.address, m, c.length, 0, na, ka)); - free_all([m, na, ka]); - return c.extractBytes(nacl_raw._crypto_box_boxzerobytes()); - } - - function crypto_box_open_precomputed(ciphertext, nonce, state) { - var c = injectBytes(ciphertext, nacl_raw._crypto_box_boxzerobytes()); - var na = check_injectBytes("crypto_box_open_precomputed", - "nonce", nonce, nacl_raw._crypto_box_noncebytes()); - var ka = check_injectBytes("crypto_box_open_precomputed", - "boxK", state.boxK, nacl_raw._crypto_box_beforenmbytes()); - var m = new Target(ciphertext.length + nacl_raw._crypto_box_boxzerobytes()); - check("_crypto_box_open_afternm", - nacl_raw._crypto_box_open_afternm(m.address, c, m.length, 0, na, ka)); - free_all([c, na, ka]); - return m.extractBytes(nacl_raw._crypto_box_zerobytes()); - } - - //--------------------------------------------------------------------------- - // Hashing - - function crypto_hash(bs) { - var address = injectBytes(bs); - var hash = new Target(nacl_raw._crypto_hash_bytes()); - check("_crypto_hash", nacl_raw._crypto_hash(hash.address, address, bs.length, 0)); - FREE(address); - return hash.extractBytes(); - } - - function crypto_hash_sha256(bs) { - var address = injectBytes(bs); - var hash = new Target(nacl_raw._crypto_hash_sha256_bytes()); - check("_crypto_hash_sha256", - nacl_raw._crypto_hash_sha256(hash.address, address, bs.length, 0)); - FREE(address); - return hash.extractBytes(); - } - - function crypto_hash_string(s) { - return crypto_hash(encode_utf8(s)); - } - - //--------------------------------------------------------------------------- - // Symmetric-key encryption - - function crypto_stream_random_nonce() { - return random_bytes(nacl_raw._crypto_stream_noncebytes()); - } - - function crypto_stream(len, nonce, key) { - var na = check_injectBytes("crypto_stream", - "nonce", nonce, nacl_raw._crypto_stream_noncebytes()); - var ka = check_injectBytes("crypto_stream", - "key", key, nacl_raw._crypto_stream_keybytes()); - var out = new Target(len); - check("_crypto_stream", nacl_raw._crypto_stream(out.address, len, 0, na, ka)); - free_all([na, ka]); - return out.extractBytes(); - } - - function crypto_stream_xor(msg, nonce, key) { - var na = check_injectBytes("crypto_stream_xor", - "nonce", nonce, nacl_raw._crypto_stream_noncebytes()); - var ka = check_injectBytes("crypto_stream_xor", - "key", key, nacl_raw._crypto_stream_keybytes()); - var ma = injectBytes(msg); - var out = new Target(msg.length); - check("_crypto_stream_xor", - nacl_raw._crypto_stream_xor(out.address, ma, msg.length, 0, na, ka)); - free_all([na, ka, ma]); - return out.extractBytes(); - } - - //--------------------------------------------------------------------------- - // One-time authentication - - function crypto_onetimeauth(msg, key) { - var ka = check_injectBytes("crypto_onetimeauth", - "key", key, nacl_raw._crypto_onetimeauth_keybytes()); - var ma = injectBytes(msg); - var authenticator = new Target(nacl_raw._crypto_onetimeauth_bytes()); - check("_crypto_onetimeauth", - nacl_raw._crypto_onetimeauth(authenticator.address, ma, msg.length, 0, ka)); - free_all([ka, ma]); - return authenticator.extractBytes(); - } - - function crypto_onetimeauth_verify(authenticator, msg, key) { - if (authenticator.length != nacl_raw._crypto_onetimeauth_bytes()) return false; - var ka = check_injectBytes("crypto_onetimeauth_verify", - "key", key, nacl_raw._crypto_onetimeauth_keybytes()); - var ma = injectBytes(msg); - var aa = injectBytes(authenticator); - var result = nacl_raw._crypto_onetimeauth_verify(aa, ma, msg.length, 0, ka); - free_all([ka, ma, aa]); - return (result == 0); - } - - //--------------------------------------------------------------------------- - // Authentication - - function crypto_auth(msg, key) { - var ka = check_injectBytes("crypto_auth", "key", key, nacl_raw._crypto_auth_keybytes()); - var ma = injectBytes(msg); - var authenticator = new Target(nacl_raw._crypto_auth_bytes()); - check("_crypto_auth", nacl_raw._crypto_auth(authenticator.address, ma, msg.length, 0, ka)); - free_all([ka, ma]); - return authenticator.extractBytes(); - } - - function crypto_auth_verify(authenticator, msg, key) { - if (authenticator.length != nacl_raw._crypto_auth_bytes()) return false; - var ka = check_injectBytes("crypto_auth_verify", - "key", key, nacl_raw._crypto_auth_keybytes()); - var ma = injectBytes(msg); - var aa = injectBytes(authenticator); - var result = nacl_raw._crypto_auth_verify(aa, ma, msg.length, 0, ka); - free_all([ka, ma, aa]); - return (result == 0); - } - - //--------------------------------------------------------------------------- - // Authenticated symmetric-key encryption - - function crypto_secretbox_random_nonce() { - return random_bytes(nacl_raw._crypto_secretbox_noncebytes()); - } - - function crypto_secretbox(msg, nonce, key) { - var m = injectBytes(msg, nacl_raw._crypto_secretbox_zerobytes()); - var na = check_injectBytes("crypto_secretbox", - "nonce", nonce, nacl_raw._crypto_secretbox_noncebytes()); - var ka = check_injectBytes("crypto_secretbox", - "key", key, nacl_raw._crypto_secretbox_keybytes()); - var c = new Target(msg.length + nacl_raw._crypto_secretbox_zerobytes()); - check("_crypto_secretbox", nacl_raw._crypto_secretbox(c.address, m, c.length, 0, na, ka)); - free_all([m, na, ka]); - return c.extractBytes(nacl_raw._crypto_secretbox_boxzerobytes()); - } - - function crypto_secretbox_open(ciphertext, nonce, key) { - var c = injectBytes(ciphertext, nacl_raw._crypto_secretbox_boxzerobytes()); - var na = check_injectBytes("crypto_secretbox_open", - "nonce", nonce, nacl_raw._crypto_secretbox_noncebytes()); - var ka = check_injectBytes("crypto_secretbox_open", - "key", key, nacl_raw._crypto_secretbox_keybytes()); - var m = new Target(ciphertext.length + nacl_raw._crypto_secretbox_boxzerobytes()); - check("_crypto_secretbox_open", - nacl_raw._crypto_secretbox_open(m.address, c, m.length, 0, na, ka)); - free_all([c, na, ka]); - return m.extractBytes(nacl_raw._crypto_secretbox_zerobytes()); - } - - //--------------------------------------------------------------------------- - // Signing - - function crypto_sign_keypair() { - var pk = new Target(nacl_raw._crypto_sign_publickeybytes()); - var sk = new Target(nacl_raw._crypto_sign_secretkeybytes()); - check("_crypto_sign_keypair", nacl_raw._crypto_sign_keypair(pk.address, sk.address)); - return {signPk: pk.extractBytes(), signSk: sk.extractBytes()}; - } - - function crypto_sign(msg, sk) { - var ma = injectBytes(msg); - var ska = check_injectBytes("crypto_sign", "sk", sk, nacl_raw._crypto_sign_secretkeybytes()); - var sm = new Target(msg.length + nacl_raw._crypto_sign_bytes()); - var smlen = new Target(8); - check("_crypto_sign", - nacl_raw._crypto_sign(sm.address, smlen.address, ma, msg.length, 0, ska)); - free_all([ma, ska]); - sm.length = nacl_raw.HEAPU32[smlen.address >> 2]; - FREE(smlen.address); - return sm.extractBytes(); - } - - function crypto_sign_detached(msg, sk) { - // WARNING: Experimental. Works for ed25519 but not necessarily other implementations. - var signed_msg = crypto_sign(msg, sk); - return signed_msg.subarray(0, nacl_raw._crypto_sign_bytes()); - } - - function crypto_sign_open(sm, pk) { - var sma = injectBytes(sm); - var pka = check_injectBytes("crypto_sign_open", - "pk", pk, nacl_raw._crypto_sign_publickeybytes()); - var m = new Target(sm.length); - var mlen = new Target(8); - if (nacl_raw._crypto_sign_open(m.address, mlen.address, sma, sm.length, 0, pka) === 0) { - free_all([sma, pka]); - m.length = nacl_raw.HEAPU32[mlen.address >> 2]; - FREE(mlen.address); - return m.extractBytes(); - } else { - free_all([sma, pka, m.address, mlen.address]); - return null; - } - } - - function crypto_sign_verify_detached(detached_signature, msg, pk) { - // WARNING: Experimental. Works for ed25519 but not necessarily other implementations. - var signed_msg = new Uint8Array(detached_signature.length + msg.length); - signed_msg.set(detached_signature, 0); - signed_msg.set(msg, detached_signature.length); - return crypto_sign_open(signed_msg, pk) !== null; - } - - //--------------------------------------------------------------------------- - // Keys - - function crypto_sign_seed_keypair(bs) { - var seeda = check_injectBytes("crypto_sign_seed_keypair", - "seed", bs, nacl_raw._crypto_sign_secretkeybytes() / 2); - var pk = new Target(nacl_raw._crypto_sign_publickeybytes()); - var sk = new Target(nacl_raw._crypto_sign_secretkeybytes()); - check("_crypto_sign_seed_keypair", - nacl_raw._crypto_sign_seed_keypair(pk.address, sk.address, seeda)); - FREE(seeda); - return {signPk: pk.extractBytes(), signSk: sk.extractBytes()}; - } - - function crypto_box_seed_keypair(bs) { - var hash = new Uint8Array(crypto_hash(bs)); - return crypto_box_keypair_from_raw_sk(hash.subarray(0, - nacl_raw._crypto_box_secretkeybytes())); - } - - function crypto_box_keypair_from_raw_sk(sk) { - return {boxPk: crypto_scalarmult_base(sk), boxSk: sk}; - } - - function crypto_box_keypair_from_sign_sk(sk) { - var ska = check_injectBytes("crypto_box_keypair_from_sign_sk", "sk", sk, - nacl_raw._crypto_sign_secretkeybytes()); - var skb = new Target(nacl_raw._crypto_box_secretkeybytes()); - check("_crypto_sign_ed25519_sk_to_curve25519", - nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska)); - FREE(ska); - return crypto_box_keypair_from_raw_sk(skb.extractBytes()); - } - - function crypto_box_sk_from_sign_sk(sk) { - var ska = check_injectBytes("crypto_box_keypair_from_sign_sk", "sk", sk, - nacl_raw._crypto_sign_secretkeybytes()); - var skb = new Target(nacl_raw._crypto_box_secretkeybytes()); - check("_crypto_sign_ed25519_sk_to_curve25519", - nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska)); - FREE(ska); - return skb.extractBytes(); - } - - function crypto_box_pk_from_sign_pk(pk) { - var pka = check_injectBytes("crypto_box_pk_from_sign_pk", "pk", pk, - nacl_raw._crypto_sign_publickeybytes()); - var pkb = new Target(nacl_raw._crypto_box_publickeybytes()); - check("_crypto_sign_ed25519_pk_to_curve25519", - nacl_raw._crypto_sign_ed25519_pk_to_curve25519(pkb.address, pka)); - FREE(pka); - return pkb.extractBytes(); - } - - //--------------------------------------------------------------------------- - // Scalarmult - - function crypto_scalarmult(n,p) { - var na = check_injectBytes("crypto_scalarmult", "n", n, - nacl_raw._crypto_scalarmult_curve25519_scalarbytes()); - var pa = check_injectBytes("crypto_scalarmult", "p", p, - nacl_raw._crypto_scalarmult_curve25519_bytes()); - var q = new Target(nacl_raw._crypto_scalarmult_curve25519_bytes()); - check("_crypto_scalarmult_curve25519", - nacl_raw._crypto_scalarmult_curve25519(q.address, na, pa)); - FREE(na); - FREE(pa); - return q.extractBytes(); - } - - function crypto_scalarmult_base(n) { - var na = check_injectBytes("crypto_scalarmult_base", "n", n, - nacl_raw._crypto_scalarmult_curve25519_scalarbytes()); - var q = new Target(nacl_raw._crypto_scalarmult_curve25519_bytes()); - check("_crypto_scalarmult_curve25519_base", - nacl_raw._crypto_scalarmult_curve25519_base(q.address, na)); - FREE(na); - return q.extractBytes(); - } - - //--------------------------------------------------------------------------- - - exports.crypto_auth_BYTES = nacl_raw._crypto_auth_bytes(); - exports.crypto_auth_KEYBYTES = nacl_raw._crypto_auth_keybytes(); - exports.crypto_box_BEFORENMBYTES = nacl_raw._crypto_box_beforenmbytes(); - exports.crypto_box_BOXZEROBYTES = nacl_raw._crypto_box_boxzerobytes(); - exports.crypto_box_NONCEBYTES = nacl_raw._crypto_box_noncebytes(); - exports.crypto_box_PUBLICKEYBYTES = nacl_raw._crypto_box_publickeybytes(); - exports.crypto_box_SECRETKEYBYTES = nacl_raw._crypto_box_secretkeybytes(); - exports.crypto_box_ZEROBYTES = nacl_raw._crypto_box_zerobytes(); - exports.crypto_hash_BYTES = nacl_raw._crypto_hash_bytes(); - exports.crypto_hash_sha256_BYTES = nacl_raw._crypto_hash_sha256_bytes(); - // exports.crypto_hashblocks_BLOCKBYTES = nacl_raw._crypto_hashblocks_blockbytes(); - // exports.crypto_hashblocks_STATEBYTES = nacl_raw._crypto_hashblocks_statebytes(); - exports.crypto_onetimeauth_BYTES = nacl_raw._crypto_onetimeauth_bytes(); - exports.crypto_onetimeauth_KEYBYTES = nacl_raw._crypto_onetimeauth_keybytes(); - exports.crypto_secretbox_BOXZEROBYTES = nacl_raw._crypto_secretbox_boxzerobytes(); - exports.crypto_secretbox_KEYBYTES = nacl_raw._crypto_secretbox_keybytes(); - exports.crypto_secretbox_NONCEBYTES = nacl_raw._crypto_secretbox_noncebytes(); - exports.crypto_secretbox_ZEROBYTES = nacl_raw._crypto_secretbox_zerobytes(); - exports.crypto_sign_BYTES = nacl_raw._crypto_sign_bytes(); - exports.crypto_sign_PUBLICKEYBYTES = nacl_raw._crypto_sign_publickeybytes(); - exports.crypto_sign_SECRETKEYBYTES = nacl_raw._crypto_sign_secretkeybytes(); - // exports.crypto_stream_BEFORENMBYTES = nacl_raw._crypto_stream_beforenmbytes(); - exports.crypto_stream_KEYBYTES = nacl_raw._crypto_stream_keybytes(); - exports.crypto_stream_NONCEBYTES = nacl_raw._crypto_stream_noncebytes(); - exports.crypto_scalarmult_SCALARBYTES = nacl_raw._crypto_scalarmult_curve25519_scalarbytes(); - exports.crypto_scalarmult_BYTES = nacl_raw._crypto_scalarmult_curve25519_bytes(); - - exports.encode_utf8 = encode_utf8; - exports.encode_latin1 = encode_latin1; - exports.decode_utf8 = decode_utf8; - exports.decode_latin1 = decode_latin1; - exports.to_hex = to_hex; - exports.from_hex = from_hex; - - exports.random_bytes = random_bytes; - - exports.crypto_box_keypair = crypto_box_keypair; - exports.crypto_box_random_nonce = crypto_box_random_nonce; - exports.crypto_box = crypto_box; - exports.crypto_box_open = crypto_box_open; - exports.crypto_box_precompute = crypto_box_precompute; - exports.crypto_box_precomputed = crypto_box_precomputed; - exports.crypto_box_open_precomputed = crypto_box_open_precomputed; - - exports.crypto_stream_random_nonce = crypto_stream_random_nonce; - exports.crypto_stream = crypto_stream; - exports.crypto_stream_xor = crypto_stream_xor; - - exports.crypto_onetimeauth = crypto_onetimeauth; - exports.crypto_onetimeauth_verify = crypto_onetimeauth_verify; - - exports.crypto_auth = crypto_auth; - exports.crypto_auth_verify = crypto_auth_verify; - - exports.crypto_secretbox_random_nonce = crypto_secretbox_random_nonce; - exports.crypto_secretbox = crypto_secretbox; - exports.crypto_secretbox_open = crypto_secretbox_open; - - exports.crypto_sign_keypair = crypto_sign_keypair; - exports.crypto_sign = crypto_sign; - exports.crypto_sign_detached = crypto_sign_detached; - exports.crypto_sign_open = crypto_sign_open; - exports.crypto_sign_verify_detached = crypto_sign_verify_detached; - - exports.crypto_hash = crypto_hash; - exports.crypto_hash_sha256 = crypto_hash_sha256; - exports.crypto_hash_string = crypto_hash_string; - - exports.crypto_sign_seed_keypair = crypto_sign_seed_keypair; - exports.crypto_box_seed_keypair = crypto_box_seed_keypair; - exports.crypto_box_keypair_from_raw_sk = crypto_box_keypair_from_raw_sk; - exports.crypto_box_keypair_from_sign_sk = crypto_box_keypair_from_sign_sk; - exports.crypto_box_pk_from_sign_pk = crypto_box_pk_from_sign_pk; - exports.crypto_box_sk_from_sign_sk = crypto_box_sk_from_sign_sk; - // Backwards-compatibility: - exports.crypto_sign_keypair_from_seed = crypto_sign_seed_keypair; - exports.crypto_box_keypair_from_seed = crypto_box_seed_keypair; - - exports.crypto_scalarmult = crypto_scalarmult; - exports.crypto_scalarmult_base = crypto_scalarmult_base; - - return exports; -})(); - nacl.nacl_raw = nacl_raw; - - if (on_ready_call_needed) { - on_ready(nacl); - } - - return "nacl_factory API has changed -- see js-nacl README"; - })((typeof window !== 'undefined') ? window : undefined_reference_value, - (typeof document !== 'undefined') ? document : undefined_reference_value); - } -}; - -// export common.js module to allow one js file for browser and node.js -if (typeof module !== 'undefined' && module.exports) { - module.exports = nacl_factory; -} diff --git a/assets/www/dist/dist_js/app/vendor/ng-cordova.min.js b/assets/www/dist/dist_js/app/vendor/ng-cordova.min.js deleted file mode 100644 index 4ae32822d7219ee0176b83737f144bc7e320d900..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/ng-cordova.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/*! - * ngCordova - * v0.1.26-alpha - * Copyright 2015 Drifty Co. http://drifty.com/ - * See LICENSE in this repository for license information - */ -!function(){angular.module("ngCordova",["ngCordova.plugins"]),angular.module("ngCordova.plugins.actionSheet",[]).factory("$cordovaActionSheet",["$q","$window",function(e,n){return{show:function(r){var o=e.defer();return n.plugins.actionsheet.show(r,function(e){o.resolve(e)}),o.promise},hide:function(){return n.plugins.actionsheet.hide()}}}]),angular.module("ngCordova.plugins.adMob",[]).factory("$cordovaAdMob",["$q","$window",function(e,n){return{createBannerView:function(r){var o=e.defer();return n.plugins.AdMob.createBannerView(r,function(){o.resolve()},function(){o.reject()}),o.promise},createInterstitialView:function(r){var o=e.defer();return n.plugins.AdMob.createInterstitialView(r,function(){o.resolve()},function(){o.reject()}),o.promise},requestAd:function(r){var o=e.defer();return n.plugins.AdMob.requestAd(r,function(){o.resolve()},function(){o.reject()}),o.promise},showAd:function(r){var o=e.defer();return n.plugins.AdMob.showAd(r,function(){o.resolve()},function(){o.reject()}),o.promise},requestInterstitialAd:function(r){var o=e.defer();return n.plugins.AdMob.requestInterstitialAd(r,function(){o.resolve()},function(){o.reject()}),o.promise}}}]),angular.module("ngCordova.plugins.appAvailability",[]).factory("$cordovaAppAvailability",["$q",function(e){return{check:function(n){var r=e.defer();return appAvailability.check(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.appRate",[]).provider("$cordovaAppRate",[function(){this.setPreferences=function(e){e&&angular.isObject(e)&&(AppRate.preferences.useLanguage=e.language||null,AppRate.preferences.displayAppName=e.appName||"",AppRate.preferences.promptAgainForEachNewVersion=e.promptForNewVersion||!0,AppRate.preferences.openStoreInApp=e.openStoreInApp||!1,AppRate.preferences.usesUntilPrompt=e.usesUntilPrompt||3,AppRate.preferences.useCustomRateDialog=e.useCustomRateDialog||!1,AppRate.preferences.storeAppURL.ios=e.iosURL||null,AppRate.preferences.storeAppURL.android=e.androidURL||null,AppRate.preferences.storeAppURL.blackberry=e.blackberryURL||null,AppRate.preferences.storeAppURL.windows8=e.windowsURL||null)},this.setCustomLocale=function(e){var n={title:"Rate %@",message:"If you enjoy using %@, would you mind taking a moment to rate it? It won’t take more than a minute. Thanks for your support!",cancelButtonLabel:"No, Thanks",laterButtonLabel:"Remind Me Later",rateButtonLabel:"Rate It Now"};n=angular.extend(n,e),AppRate.preferences.customLocale=n},this.$get=["$q",function(e){return{promptForRating:function(n){var r=e.defer(),o=AppRate.promptForRating(n);return r.resolve(o),r.promise},navigateToAppStore:function(){var n=e.defer(),r=AppRate.navigateToAppStore();return n.resolve(r),n.promise},onButtonClicked:function(e){AppRate.onButtonClicked=function(n){e.call(this,n)}},onRateDialogShow:function(e){AppRate.onRateDialogShow=e()}}}]}]),angular.module("ngCordova.plugins.appVersion",[]).factory("$cordovaAppVersion",["$q",function(e){return{getAppName:function(){var n=e.defer();return cordova.getAppVersion.getAppName(function(e){n.resolve(e)}),n.promise},getPackageName:function(){var n=e.defer();return cordova.getAppVersion.getPackageName(function(e){n.resolve(e)}),n.promise},getVersionNumber:function(){var n=e.defer();return cordova.getAppVersion.getVersionNumber(function(e){n.resolve(e)}),n.promise},getVersionCode:function(){var n=e.defer();return cordova.getAppVersion.getVersionCode(function(e){n.resolve(e)}),n.promise}}}]),angular.module("ngCordova.plugins.backgroundGeolocation",[]).factory("$cordovaBackgroundGeolocation",["$q","$window",function(e,n){return{init:function(){n.navigator.geolocation.getCurrentPosition(function(e){return e})},configure:function(r){this.init();var o=e.defer();return n.plugins.backgroundGeoLocation.configure(function(e){o.notify(e),n.plugins.backgroundGeoLocation.finish()},function(e){o.reject(e)},r),this.start(),o.promise},start:function(){var r=e.defer();return n.plugins.backgroundGeoLocation.start(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},stop:function(){var r=e.defer();return n.plugins.backgroundGeoLocation.stop(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.badge",[]).factory("$cordovaBadge",["$q",function(e){return{hasPermission:function(){var n=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?n.resolve(!0):n.reject("You do not have permission")}),n.promise},promptForPermission:function(){return cordova.plugins.notification.badge.promptForPermission()},set:function(n,r,o){var t=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?t.resolve(cordova.plugins.notification.badge.set(n,r,o)):t.reject("You do not have permission to set Badge")}),t.promise},get:function(){var n=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?cordova.plugins.notification.badge.get(function(e){n.resolve(e)}):n.reject("You do not have permission to get Badge")}),n.promise},clear:function(n,r){var o=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?o.resolve(cordova.plugins.notification.badge.clear(n,r)):o.reject("You do not have permission to clear Badge")}),o.promise},increase:function(n,r,o){var t=e.defer();return this.hasPermission().then(function(){t.resolve(cordova.plugins.notification.badge.increase(n,r,o))},function(){t.reject("You do not have permission to increase Badge")}),t.promise},decrease:function(n,r,o){var t=e.defer();return this.hasPermission().then(function(){t.resolve(cordova.plugins.notification.badge.decrease(n,r,o))},function(){t.reject("You do not have permission to decrease Badge")}),t.promise},configure:function(e){return cordova.plugins.notification.badge.configure(e)}}}]),angular.module("ngCordova.plugins.barcodeScanner",[]).factory("$cordovaBarcodeScanner",["$q",function(e){return{scan:function(n){var r=e.defer();return cordova.plugins.barcodeScanner.scan(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},encode:function(n,r){var o=e.defer();return n=n||"TEXT_TYPE",cordova.plugins.barcodeScanner.encode(n,r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.batteryStatus",[]).factory("$cordovaBatteryStatus",["$rootScope","$window","$timeout",function(e,n,r){var o=function(n){r(function(){e.$broadcast("$cordovaBatteryStatus:status",n)})},t=function(n){r(function(){e.$broadcast("$cordovaBatteryStatus:critical",n)})},i=function(n){r(function(){e.$broadcast("$cordovaBatteryStatus:low",n)})};return document.addEventListener("deviceready",function(){navigator.battery&&(n.addEventListener("batterystatus",o,!1),n.addEventListener("batterycritical",t,!1),n.addEventListener("batterylow",i,!1))},!1),!0}]).run(["$injector",function(e){e.get("$cordovaBatteryStatus")}]),angular.module("ngCordova.plugins.beacon",[]).factory("$cordovaBeacon",["$window","$rootScope","$timeout","$q",function(e,n,r,o){var t=null,i=null,a=null,c=null,u=null,s=null,l=null,f=null;return document.addEventListener("deviceready",function(){if(e.cordova&&e.cordova.plugins&&e.cordova.plugins.locationManager){var o=new e.cordova.plugins.locationManager.Delegate;o.didDetermineStateForRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didDetermineStateForRegion",e)}),t&&t(e)},o.didStartMonitoringForRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didStartMonitoringForRegion",e)}),i&&i(e)},o.didExitRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didExitRegion",e)}),a&&a(e)},o.didEnterRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didEnterRegion",e)}),c&&c(e)},o.didRangeBeaconsInRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didRangeBeaconsInRegion",e)}),u&&u(e)},o.peripheralManagerDidStartAdvertising=function(e){r(function(){n.$broadcast("$cordovaBeacon:peripheralManagerDidStartAdvertising",e)}),s&&s(e)},o.peripheralManagerDidUpdateState=function(e){r(function(){n.$broadcast("$cordovaBeacon:peripheralManagerDidUpdateState",e)}),l&&l(e)},o.didChangeAuthorizationStatus=function(e){r(function(){n.$broadcast("$cordovaBeacon:didChangeAuthorizationStatus",e)}),f&&f(e)},e.cordova.plugins.locationManager.setDelegate(o)}},!1),{setCallbackDidDetermineStateForRegion:function(e){t=e},setCallbackDidStartMonitoringForRegion:function(e){i=e},setCallbackDidExitRegion:function(e){a=e},setCallbackDidEnterRegion:function(e){c=e},setCallbackDidRangeBeaconsInRegion:function(e){u=e},setCallbackPeripheralManagerDidStartAdvertising:function(e){s=e},setCallbackPeripheralManagerDidUpdateState:function(e){l=e},setCallbackDidChangeAuthorizationStatus:function(e){f=e},createBeaconRegion:function(n,r,o,t,i){return o=o||void 0,t=t||void 0,new e.cordova.plugins.locationManager.BeaconRegion(n,r,o,t,i)},isBluetoothEnabled:function(){return o.when(e.cordova.plugins.locationManager.isBluetoothEnabled())},enableBluetooth:function(){return o.when(e.cordova.plugins.locationManager.enableBluetooth())},disableBluetooth:function(){return o.when(e.cordova.plugins.locationManager.disableBluetooth())},startMonitoringForRegion:function(n){return o.when(e.cordova.plugins.locationManager.startMonitoringForRegion(n))},stopMonitoringForRegion:function(n){return o.when(e.cordova.plugins.locationManager.stopMonitoringForRegion(n))},requestStateForRegion:function(n){return o.when(e.cordova.plugins.locationManager.requestStateForRegion(n))},startRangingBeaconsInRegion:function(n){return o.when(e.cordova.plugins.locationManager.startRangingBeaconsInRegion(n))},stopRangingBeaconsInRegion:function(n){return o.when(e.cordova.plugins.locationManager.stopRangingBeaconsInRegion(n))},getAuthorizationStatus:function(){return o.when(e.cordova.plugins.locationManager.getAuthorizationStatus())},requestWhenInUseAuthorization:function(){return o.when(e.cordova.plugins.locationManager.requestWhenInUseAuthorization())},requestAlwaysAuthorization:function(){return o.when(e.cordova.plugins.locationManager.requestAlwaysAuthorization())},getMonitoredRegions:function(){return o.when(e.cordova.plugins.locationManager.getMonitoredRegions())},getRangedRegions:function(){return o.when(e.cordova.plugins.locationManager.getRangedRegions())},isRangingAvailable:function(){return o.when(e.cordova.plugins.locationManager.isRangingAvailable())},isMonitoringAvailableForClass:function(n){return o.when(e.cordova.plugins.locationManager.isMonitoringAvailableForClass(n))},startAdvertising:function(n,r){return o.when(e.cordova.plugins.locationManager.startAdvertising(n,r))},stopAdvertising:function(){return o.when(e.cordova.plugins.locationManager.stopAdvertising())},isAdvertisingAvailable:function(){return o.when(e.cordova.plugins.locationManager.isAdvertisingAvailable())},isAdvertising:function(){return o.when(e.cordova.plugins.locationManager.isAdvertising())},disableDebugLogs:function(){return o.when(e.cordova.plugins.locationManager.disableDebugLogs())},enableDebugNotifications:function(){return o.when(e.cordova.plugins.locationManager.enableDebugNotifications())},disableDebugNotifications:function(){return o.when(e.cordova.plugins.locationManager.disableDebugNotifications())},enableDebugLogs:function(){return o.when(e.cordova.plugins.locationManager.enableDebugLogs())},appendToDeviceLog:function(n){return o.when(e.cordova.plugins.locationManager.appendToDeviceLog(n))}}}]),angular.module("ngCordova.plugins.ble",[]).factory("$cordovaBLE",["$q","$timeout","$log",function(e,n,r){return{scan:function(r,o){var t=e.defer();return ble.startScan(r,function(e){t.notify(e)},function(e){t.reject(e)}),n(function(){ble.stopScan(function(){t.resolve()},function(e){t.reject(e)})},1e3*o),t.promise},startScan:function(e,n,r){return ble.startScan(e,n,r)},stopScan:function(){var n=e.defer();return ble.stopScan(function(){n.resolve()},function(e){n.reject(e)}),n.promise},connect:function(n){var r=e.defer();return ble.connect(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},disconnect:function(n){var r=e.defer();return ble.disconnect(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},read:function(n,r,o){var t=e.defer();return ble.read(n,r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},write:function(n,r,o,t){var i=e.defer();return ble.write(n,r,o,t,function(e){i.resolve(e)},function(e){i.reject(e)}),i.promise},writeWithoutResponse:function(n,r,o,t){var i=e.defer();return ble.writeWithoutResponse(n,r,o,t,function(e){i.resolve(e)},function(e){i.reject(e)}),i.promise},writeCommand:function(e,n,o,t){return r.warning("writeCommand is deprecated, use writeWithoutResponse"),this.writeWithoutResponse(e,n,o,t)},startNotification:function(e,n,r,o,t){return ble.startNotification(e,n,r,o,t)},stopNotification:function(n,r,o){var t=e.defer();return ble.stopNotification(n,r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},isConnected:function(n){var r=e.defer();return ble.isConnected(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},enable:function(){var n=e.defer();return ble.enable(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},isEnabled:function(){var n=e.defer();return ble.isEnabled(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.bluetoothSerial",[]).factory("$cordovaBluetoothSerial",["$q","$window",function(e,n){return{connect:function(r){var o=e.defer(),t=e.defer(),i=!1;return n.bluetoothSerial.connect(r,function(){i=!0,o.resolve(t)},function(e){i===!1&&t.reject(e),o.reject(e)}),o.promise},connectInsecure:function(r){var o=e.defer();return n.bluetoothSerial.connectInsecure(r,function(){o.resolve()},function(e){o.reject(e)}),o.promise},disconnect:function(){var r=e.defer();return n.bluetoothSerial.disconnect(function(){r.resolve()},function(e){r.reject(e)}),r.promise},list:function(){var r=e.defer();return n.bluetoothSerial.list(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},discoverUnpaired:function(){var r=e.defer();return n.bluetoothSerial.discoverUnpaired(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},setDeviceDiscoveredListener:function(){var r=e.defer();return n.bluetoothSerial.setDeviceDiscoveredListener(function(e){r.notify(e)}),r.promise},clearDeviceDiscoveredListener:function(){n.bluetoothSerial.clearDeviceDiscoveredListener()},showBluetoothSettings:function(){var r=e.defer();return n.bluetoothSerial.showBluetoothSettings(function(){r.resolve()},function(e){r.reject(e)}),r.promise},isEnabled:function(){var r=e.defer();return n.bluetoothSerial.isEnabled(function(){r.resolve()},function(){r.reject()}),r.promise},enable:function(){var r=e.defer();return n.bluetoothSerial.enable(function(){r.resolve()},function(){r.reject()}),r.promise},isConnected:function(){var r=e.defer();return n.bluetoothSerial.isConnected(function(){r.resolve()},function(){r.reject()}),r.promise},available:function(){var r=e.defer();return n.bluetoothSerial.available(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},read:function(){var r=e.defer();return n.bluetoothSerial.read(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},readUntil:function(r){var o=e.defer();return n.bluetoothSerial.readUntil(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},write:function(r){var o=e.defer();return n.bluetoothSerial.write(r,function(){o.resolve()},function(e){o.reject(e)}),o.promise},subscribe:function(r){var o=e.defer();return n.bluetoothSerial.subscribe(r,function(e){o.notify(e)},function(e){o.reject(e)}),o.promise},subscribeRawData:function(){var r=e.defer();return n.bluetoothSerial.subscribeRawData(function(e){r.notify(e)},function(e){r.reject(e)}),r.promise},unsubscribe:function(){var r=e.defer();return n.bluetoothSerial.unsubscribe(function(){r.resolve()},function(e){r.reject(e)}),r.promise},unsubscribeRawData:function(){var r=e.defer();return n.bluetoothSerial.unsubscribeRawData(function(){r.resolve()},function(e){r.reject(e)}),r.promise},clear:function(){var r=e.defer();return n.bluetoothSerial.clear(function(){r.resolve()},function(e){r.reject(e)}),r.promise},readRSSI:function(){var r=e.defer();return n.bluetoothSerial.readRSSI(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.brightness",[]).factory("$cordovaBrightness",["$q","$window",function(e,n){return{get:function(){var r=e.defer();return n.cordova?n.cordova.plugins.brightness.getBrightness(function(e){r.resolve(e)},function(e){r.reject(e)}):r.reject("Not supported without cordova.js"),r.promise},set:function(r){var o=e.defer();return n.cordova?n.cordova.plugins.brightness.setBrightness(r,function(e){o.resolve(e)},function(e){o.reject(e)}):o.reject("Not supported without cordova.js"),o.promise},setKeepScreenOn:function(r){var o=e.defer();return n.cordova?n.cordova.plugins.brightness.setKeepScreenOn(r,function(e){o.resolve(e)},function(e){o.reject(e)}):o.reject("Not supported without cordova.js"),o.promise}}}]),angular.module("ngCordova.plugins.calendar",[]).factory("$cordovaCalendar",["$q","$window",function(e,n){return{createCalendar:function(r){var o=e.defer(),t=n.plugins.calendar.getCreateCalendarOptions();return"string"==typeof r?t.calendarName=r:t=angular.extend(t,r),n.plugins.calendar.createCalendar(t,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},deleteCalendar:function(r){var o=e.defer();return n.plugins.calendar.deleteCalendar(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEvent:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.createEvent(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEventWithOptions:function(r){var o=e.defer(),t=[],i=window.plugins.calendar.getCalendarOptions(),a={title:null,location:null,notes:null,startDate:null,endDate:null};t=Object.keys(a);for(var c in r)-1===t.indexOf(c)?i[c]=r[c]:a[c]=r[c];return n.plugins.calendar.createEventWithOptions(a.title,a.location,a.notes,new Date(a.startDate),new Date(a.endDate),i,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEventInteractively:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.createEventInteractively(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEventInNamedCalendar:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null,calendarName:null};return t=angular.extend(t,r),n.plugins.calendar.createEventInNamedCalendar(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),t.calendarName,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},findEvent:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.findEvent(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},listEventsInRange:function(r,o){var t=e.defer();return n.plugins.calendar.listEventsInRange(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},listCalendars:function(){var r=e.defer();return n.plugins.calendar.listCalendars(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},findAllEventsInNamedCalendar:function(r){var o=e.defer();return n.plugins.calendar.findAllEventsInNamedCalendar(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},modifyEvent:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null,newTitle:null,newLocation:null,newNotes:null,newStartDate:null,newEndDate:null};return t=angular.extend(t,r),n.plugins.calendar.modifyEvent(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),t.newTitle,t.newLocation,t.newNotes,new Date(t.newStartDate),new Date(t.newEndDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},deleteEvent:function(r){var o=e.defer(),t={newTitle:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.deleteEvent(t.newTitle,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.camera",[]).factory("$cordovaCamera",["$q",function(e){return{getPicture:function(n){var r=e.defer();return navigator.camera?(navigator.camera.getPicture(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)},cleanup:function(){var n=e.defer();return navigator.camera.cleanup(function(){n.resolve()},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.capture",[]).factory("$cordovaCapture",["$q",function(e){return{captureAudio:function(n){var r=e.defer();return navigator.device.capture?(navigator.device.capture.captureAudio(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)},captureImage:function(n){var r=e.defer();return navigator.device.capture?(navigator.device.capture.captureImage(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)},captureVideo:function(n){var r=e.defer();return navigator.device.capture?(navigator.device.capture.captureVideo(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)}}}]),angular.module("ngCordova.plugins.cardIO",[]).provider("$cordovaNgCardIO",[function(){var e=["card_type","redacted_card_number","card_number","expiry_month","expiry_year","short_expiry_year","cvv","zip"],n={expiry:!0,cvv:!0,zip:!1,suppressManual:!1,suppressConfirm:!1,hideLogo:!0};this.setCardIOResponseFields=function(n){n&&angular.isArray(n)&&(e=n)},this.setScanerConfig=function(e){e&&angular.isObject(e)&&(n.expiry=e.expiry||!0,n.cvv=e.cvv||!0,n.zip=e.zip||!1,n.suppressManual=e.suppressManual||!1,n.suppressConfirm=e.suppressConfirm||!1,n.hideLogo=e.hideLogo||!0)},this.$get=["$q",function(r){return{scanCard:function(){var o=r.defer();return CardIO.scan(n,function(n){if(null===n)o.reject(null);else{for(var r={},t=0,i=e.length;i>t;t++){var a=e[t];"short_expiry_year"===a?r[a]=String(n.expiry_year).substr(2,2)||"":r[a]=n[a]||""}o.resolve(r)}},function(){o.reject(null)}),o.promise}}}]}]),angular.module("ngCordova.plugins.clipboard",[]).factory("$cordovaClipboard",["$q","$window",function(e,n){return{copy:function(r){var o=e.defer();return n.cordova.plugins.clipboard.copy(r,function(){o.resolve()},function(){o.reject()}),o.promise},paste:function(){var r=e.defer();return n.cordova.plugins.clipboard.paste(function(e){r.resolve(e)},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.contacts",[]).factory("$cordovaContacts",["$q",function(e){return{save:function(n){var r=e.defer(),o=navigator.contacts.create(n);return o.save(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},remove:function(n){var r=e.defer(),o=navigator.contacts.create(n);return o.remove(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},clone:function(e){var n=navigator.contacts.create(e);return n.clone(e)},find:function(n){var r=e.defer(),o=n.fields||["id","displayName"];return delete n.fields,0===Object.keys(n).length?navigator.contacts.find(o,function(e){r.resolve(e)},function(e){r.reject(e)}):navigator.contacts.find(o,function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},pickContact:function(){var n=e.defer();return navigator.contacts.pickContact(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.datePicker",[]).factory("$cordovaDatePicker",["$window","$q",function(e,n){return{show:function(r){var o=n.defer();return r=r||{date:new Date,mode:"date"},e.datePicker.show(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.device",[]).factory("$cordovaDevice",[function(){return{getDevice:function(){return device},getCordova:function(){return device.cordova},getModel:function(){return device.model},getName:function(){return device.name},getPlatform:function(){return device.platform},getUUID:function(){return device.uuid},getVersion:function(){return device.version},getManufacturer:function(){return device.manufacturer}}}]),angular.module("ngCordova.plugins.deviceMotion",[]).factory("$cordovaDeviceMotion",["$q",function(e){return{getCurrentAcceleration:function(){var n=e.defer();return angular.isUndefined(navigator.accelerometer)||!angular.isFunction(navigator.accelerometer.getCurrentAcceleration)?(n.reject("Device do not support watchAcceleration"),n.promise):(navigator.accelerometer.getCurrentAcceleration(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise)},watchAcceleration:function(n){var r=e.defer();if(angular.isUndefined(navigator.accelerometer)||!angular.isFunction(navigator.accelerometer.watchAcceleration))return r.reject("Device do not support watchAcceleration"),r.promise;var o=navigator.accelerometer.watchAcceleration(function(e){r.notify(e)},function(e){r.reject(e)},n);return r.promise.cancel=function(){navigator.accelerometer.clearWatch(o)},r.promise.clearWatch=function(e){navigator.accelerometer.clearWatch(e||o)},r.promise.watchID=o,r.promise},clearWatch:function(e){return navigator.accelerometer.clearWatch(e)}}}]),angular.module("ngCordova.plugins.deviceOrientation",[]).factory("$cordovaDeviceOrientation",["$q",function(e){var n={frequency:3e3};return{getCurrentHeading:function(){var n=e.defer();return navigator.compass?(navigator.compass.getCurrentHeading(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise):(n.reject("No compass on Device"),n.promise)},watchHeading:function(r){var o=e.defer();if(!navigator.compass)return o.reject("No compass on Device"),o.promise;var t=angular.extend(n,r),i=navigator.compass.watchHeading(function(e){o.notify(e)},function(e){o.reject(e)},t);return o.promise.cancel=function(){navigator.compass.clearWatch(i)},o.promise.clearWatch=function(e){navigator.compass.clearWatch(e||i)},o.promise.watchID=i,o.promise},clearWatch:function(e){return navigator.compass.clearWatch(e)}}}]),angular.module("ngCordova.plugins.dialogs",[]).factory("$cordovaDialogs",["$q","$window",function(e,n){return{alert:function(r,o,t){var i=e.defer();return n.navigator.notification?navigator.notification.alert(r,function(){i.resolve()},o,t):(n.alert(r),i.resolve()),i.promise},confirm:function(r,o,t){var i=e.defer();return n.navigator.notification?navigator.notification.confirm(r,function(e){i.resolve(e)},o,t):n.confirm(r)?i.resolve(1):i.resolve(2),i.promise},prompt:function(r,o,t,i){var a=e.defer();if(n.navigator.notification)navigator.notification.prompt(r,function(e){a.resolve(e)},o,t,i);else{var c=n.prompt(r,i);null!==c?a.resolve({input1:c,buttonIndex:1}):a.resolve({input1:c,buttonIndex:2})}return a.promise},beep:function(e){return navigator.notification.beep(e)},activityStart:function(n,r){var o=e.defer();return"android"===cordova.platformId?(navigator.notification.activityStart(r,n),o.resolve()):o.reject(n,r),o.promise},activityStop:function(){var n=e.defer();return"android"===cordova.platformId?(navigator.notification.activityStop(),n.resolve()):n.reject(),n.promise},progressStart:function(n,r){var o=e.defer();return"android"===cordova.platformId?(navigator.notification.progressStart(r,n),o.resolve()):o.reject(n,r),o.promise},progressStop:function(){var n=e.defer();return"android"===cordova.platformId?(navigator.notification.progressStop(),n.resolve()):n.reject(),n.promise},progressValue:function(n){var r=e.defer();return"android"===cordova.platformId?(navigator.notification.progressValue(n),r.resolve()):r.reject(n),r.promise}}}]),angular.module("ngCordova.plugins.emailComposer",[]).factory("$cordovaEmailComposer",["$q",function(e){return{isAvailable:function(){var n=e.defer();return cordova.plugins.email.isAvailable(function(e){e?n.resolve():n.reject()}),n.promise},open:function(n){var r=e.defer();return cordova.plugins.email.open(n,function(){r.reject()}),r.promise},addAlias:function(e,n){cordova.plugins.email.addAlias(e,n)}}}]),angular.module("ngCordova.plugins.facebook",[]).provider("$cordovaFacebook",[function(){this.browserInit=function(e,n){this.appID=e,this.appVersion=n||"v2.0",facebookConnectPlugin.browserInit(this.appID,this.appVersion)},this.$get=["$q",function(e){return{login:function(n){var r=e.defer();return facebookConnectPlugin.login(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},showDialog:function(n){var r=e.defer();return facebookConnectPlugin.showDialog(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},api:function(n,r){var o=e.defer();return facebookConnectPlugin.api(n,r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},getAccessToken:function(){var n=e.defer();return facebookConnectPlugin.getAccessToken(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getLoginStatus:function(){var n=e.defer();return facebookConnectPlugin.getLoginStatus(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},logout:function(){var n=e.defer();return facebookConnectPlugin.logout(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]}]),angular.module("ngCordova.plugins.facebookAds",[]).factory("$cordovaFacebookAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.FacebookAds.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.FacebookAds.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.FacebookAds.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.FacebookAds.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.FacebookAds.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.FacebookAds.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.FacebookAds.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.FacebookAds.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.file",[]).constant("$cordovaFileError",{1:"NOT_FOUND_ERR",2:"SECURITY_ERR",3:"ABORT_ERR",4:"NOT_READABLE_ERR",5:"ENCODING_ERR",6:"NO_MODIFICATION_ALLOWED_ERR",7:"INVALID_STATE_ERR",8:"SYNTAX_ERR",9:"INVALID_MODIFICATION_ERR",10:"QUOTA_EXCEEDED_ERR",11:"TYPE_MISMATCH_ERR",12:"PATH_EXISTS_ERR"}).provider("$cordovaFile",[function(){this.$get=["$q","$window","$cordovaFileError",function(e,n,r){return{getFreeDiskSpace:function(){var n=e.defer();return cordova.exec(function(e){n.resolve(e)},function(e){n.reject(e)},"File","getFreeDiskSpace",[]),n.promise},checkDir:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("directory cannot start with /");try{var a=o+t;n.resolveLocalFileSystemURL(a,function(e){e.isDirectory===!0?i.resolve(e):i.reject({code:13,message:"input is not a directory"})},function(e){e.message=r[e.code],i.reject(e)})}catch(c){c.message=r[c.code],i.reject(c)}return i.promise},checkFile:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("directory cannot start with /");try{var a=o+t;n.resolveLocalFileSystemURL(a,function(e){e.isFile===!0?i.resolve(e):i.reject({code:13,message:"input is not a file"})},function(e){e.message=r[e.code],i.reject(e)})}catch(c){c.message=r[c.code],i.reject(c)}return i.promise},createDir:function(o,t,i){var a=e.defer();/^\//.test(t)&&a.reject("directory cannot start with /"), -i=i?!1:!0;var c={create:!0,exclusive:i};try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,c,function(e){a.resolve(e)},function(e){e.message=r[e.code],a.reject(e)})},function(e){e.message=r[e.code],a.reject(e)})}catch(u){u.message=r[u.code],a.reject(u)}return a.promise},createFile:function(o,t,i){var a=e.defer();/^\//.test(t)&&a.reject("file-name cannot start with /"),i=i?!1:!0;var c={create:!0,exclusive:i};try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,c,function(e){a.resolve(e)},function(e){e.message=r[e.code],a.reject(e)})},function(e){e.message=r[e.code],a.reject(e)})}catch(u){u.message=r[u.code],a.reject(u)}return a.promise},removeDir:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,{create:!1},function(e){e.remove(function(){i.resolve({success:!0,fileRemoved:e})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},removeFile:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.remove(function(){i.resolve({success:!0,fileRemoved:e})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},removeRecursively:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,{create:!1},function(e){e.removeRecursively(function(){i.resolve({success:!0,fileRemoved:e})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},writeFile:function(o,t,i,a){var c=e.defer();/^\//.test(t)&&c.reject("file-name cannot start with /"),a=a?!1:!0;var u={create:!0,exclusive:a};try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,u,function(e){e.createWriter(function(e){u.append===!0&&e.seek(e.length),u.truncate&&e.truncate(u.truncate),e.onwriteend=function(e){this.error?c.reject(this.error):c.resolve(e)},e.write(i),c.promise.abort=function(){e.abort()}})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})}catch(s){s.message=r[s.code],c.reject(s)}return c.promise},writeExistingFile:function(o,t,i){var a=e.defer();/^\//.test(t)&&a.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.createWriter(function(e){e.seek(e.length),e.onwriteend=function(e){this.error?a.reject(this.error):a.resolve(e)},e.write(i),a.promise.abort=function(){e.abort()}})},function(e){e.message=r[e.code],a.reject(e)})},function(e){e.message=r[e.code],a.reject(e)})}catch(c){c.message=r[c.code],a.reject(c)}return a.promise},readAsText:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsText(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},readAsDataURL:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsDataURL(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},readAsBinaryString:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsBinaryString(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},readAsArrayBuffer:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsArrayBuffer(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},moveFile:function(r,o,t,i){var a=e.defer();i=i||o,(/^\//.test(o)||/^\//.test(i))&&a.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(r,function(e){e.getFile(o,{create:!1},function(e){n.resolveLocalFileSystemURL(t,function(n){e.moveTo(n,i,function(e){a.resolve(e)},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})}catch(c){a.reject(c)}return a.promise},moveDir:function(r,o,t,i){var a=e.defer();i=i||o,(/^\//.test(o)||/^\//.test(i))&&a.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(r,function(e){e.getDirectory(o,{create:!1},function(e){n.resolveLocalFileSystemURL(t,function(n){e.moveTo(n,i,function(e){a.resolve(e)},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})}catch(c){a.reject(c)}return a.promise},copyDir:function(o,t,i,a){var c=e.defer();a=a||t,(/^\//.test(t)||/^\//.test(a))&&c.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,{create:!1,exclusive:!1},function(e){n.resolveLocalFileSystemURL(i,function(n){e.copyTo(n,a,function(e){c.resolve(e)},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})}catch(u){u.message=r[u.code],c.reject(u)}return c.promise},copyFile:function(o,t,i,a){var c=e.defer();a=a||t,/^\//.test(t)&&c.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1,exclusive:!1},function(e){n.resolveLocalFileSystemURL(i,function(n){e.copyTo(n,a,function(e){c.resolve(e)},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})}catch(u){u.message=r[u.code],c.reject(u)}return c.promise},readFileMetadata:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("directory cannot start with /");try{var a=o+t;n.resolveLocalFileSystemURL(a,function(e){e.file(function(e){i.resolve(e)},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(c){c.message=r[c.code],i.reject(c)}return i.promise}}}]}]),angular.module("ngCordova.plugins.fileOpener2",[]).factory("$cordovaFileOpener2",["$q",function(e){return{open:function(n,r){var o=e.defer();return cordova.plugins.fileOpener2.open(n,r,{error:function(e){o.reject(e)},success:function(){o.resolve()}}),o.promise},uninstall:function(n){var r=e.defer();return cordova.plugins.fileOpener2.uninstall(n,{error:function(e){r.reject(e)},success:function(){r.resolve()}}),r.promise},appIsInstalled:function(n){var r=e.defer();return cordova.plugins.fileOpener2.appIsInstalled(n,{success:function(e){r.resolve(e)}}),r.promise}}}]),angular.module("ngCordova.plugins.fileTransfer",[]).factory("$cordovaFileTransfer",["$q","$timeout",function(e,n){return{download:function(r,o,t,i){var a=e.defer(),c=new FileTransfer,u=t&&t.encodeURI===!1?r:encodeURI(r);return t&&void 0!==t.timeout&&null!==t.timeout&&(n(function(){c.abort()},t.timeout),t.timeout=null),c.onprogress=function(e){a.notify(e)},a.promise.abort=function(){c.abort()},c.download(u,o,a.resolve,a.reject,i,t),a.promise},upload:function(r,o,t,i){var a=e.defer(),c=new FileTransfer,u=t&&t.encodeURI===!1?r:encodeURI(r);return t&&void 0!==t.timeout&&null!==t.timeout&&(n(function(){c.abort()},t.timeout),t.timeout=null),c.onprogress=function(e){a.notify(e)},a.promise.abort=function(){c.abort()},c.upload(o,u,a.resolve,a.reject,t,i),a.promise}}}]),angular.module("ngCordova.plugins.flashlight",[]).factory("$cordovaFlashlight",["$q","$window",function(e,n){return{available:function(){var r=e.defer();return n.plugins.flashlight.available(function(e){r.resolve(e)}),r.promise},switchOn:function(){var r=e.defer();return n.plugins.flashlight.switchOn(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},switchOff:function(){var r=e.defer();return n.plugins.flashlight.switchOff(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},toggle:function(){var r=e.defer();return n.plugins.flashlight.toggle(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.flurryAds",[]).factory("$cordovaFlurryAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.FlurryAds.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.FlurryAds.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.FlurryAds.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.FlurryAds.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.FlurryAds.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.FlurryAds.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.FlurryAds.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.FlurryAds.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.ga",[]).factory("$cordovaGA",["$q","$window",function(e,n){return{init:function(r,o){var t=e.defer();return o=o>=0?o:10,n.plugins.gaPlugin.init(function(e){t.resolve(e)},function(e){t.reject(e)},r,o),t.promise},trackEvent:function(r,o,t,i,a,c){var u=e.defer();return n.plugins.gaPlugin.trackEvent(function(e){u.resolve(e)},function(e){u.reject(e)},t,i,a,c),u.promise},trackPage:function(r,o,t){var i=e.defer();return n.plugins.gaPlugin.trackPage(function(e){i.resolve(e)},function(e){i.reject(e)},t),i.promise},setVariable:function(r,o,t,i){var a=e.defer();return n.plugins.gaPlugin.setVariable(function(e){a.resolve(e)},function(e){a.reject(e)},t,i),a.promise},exit:function(){var r=e.defer();return n.plugins.gaPlugin.exit(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.geolocation",[]).factory("$cordovaGeolocation",["$q",function(e){return{getCurrentPosition:function(n){var r=e.defer();return navigator.geolocation.getCurrentPosition(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},watchPosition:function(n){var r=e.defer(),o=navigator.geolocation.watchPosition(function(e){r.notify(e)},function(e){r.reject(e)},n);return r.promise.cancel=function(){navigator.geolocation.clearWatch(o)},r.promise.clearWatch=function(e){navigator.geolocation.clearWatch(e||o)},r.promise.watchID=o,r.promise},clearWatch:function(e){return navigator.geolocation.clearWatch(e)}}}]),angular.module("ngCordova.plugins.globalization",[]).factory("$cordovaGlobalization",["$q",function(e){return{getPreferredLanguage:function(){var n=e.defer();return navigator.globalization.getPreferredLanguage(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getLocaleName:function(){var n=e.defer();return navigator.globalization.getLocaleName(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getFirstDayOfWeek:function(){var n=e.defer();return navigator.globalization.getFirstDayOfWeek(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},dateToString:function(n,r){var o=e.defer();return navigator.globalization.dateToString(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},stringToDate:function(n,r){var o=e.defer();return navigator.globalization.stringToDate(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},getDatePattern:function(n){var r=e.defer();return navigator.globalization.getDatePattern(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},getDateNames:function(n){var r=e.defer();return navigator.globalization.getDateNames(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},isDayLightSavingsTime:function(n){var r=e.defer();return navigator.globalization.isDayLightSavingsTime(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},numberToString:function(n,r){var o=e.defer();return navigator.globalization.numberToString(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},stringToNumber:function(n,r){var o=e.defer();return navigator.globalization.stringToNumber(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},getNumberPattern:function(n){var r=e.defer();return navigator.globalization.getNumberPattern(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},getCurrencyPattern:function(n){var r=e.defer();return navigator.globalization.getCurrencyPattern(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.googleAds",[]).factory("$cordovaGoogleAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.AdMob.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.AdMob.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.AdMob.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.AdMob.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.AdMob.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.AdMob.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.AdMob.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.AdMob.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.googleAnalytics",[]).factory("$cordovaGoogleAnalytics",["$q","$window",function(e,n){return{startTrackerWithId:function(r){var o=e.defer();return n.analytics.startTrackerWithId(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},setUserId:function(r){var o=e.defer();return n.analytics.setUserId(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},debugMode:function(){var r=e.defer();return n.analytics.debugMode(function(e){r.resolve(e)},function(){r.reject()}),r.promise},trackView:function(r){var o=e.defer();return n.analytics.trackView(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},addCustomDimension:function(r,o){var t=e.defer();return n.analytics.addCustomDimension(r,o,function(){t.resolve()},function(e){t.reject(e)}),t.promise},trackEvent:function(r,o,t,i){var a=e.defer();return n.analytics.trackEvent(r,o,t,i,function(e){a.resolve(e)},function(e){a.reject(e)}),a.promise},trackException:function(r,o){var t=e.defer();return n.analytics.trackException(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},trackTiming:function(r,o,t,i){var a=e.defer();return n.analytics.trackTiming(r,o,t,i,function(e){a.resolve(e)},function(e){a.reject(e)}),a.promise},addTransaction:function(r,o,t,i,a,c){var u=e.defer();return n.analytics.addTransaction(r,o,t,i,a,c,function(e){u.resolve(e)},function(e){u.reject(e)}),u.promise},addTransactionItem:function(r,o,t,i,a,c,u){var s=e.defer();return n.analytics.addTransactionItem(r,o,t,i,a,c,u,function(e){s.resolve(e)},function(e){s.reject(e)}),s.promise}}}]),angular.module("ngCordova.plugins.googleMap",[]).factory("$cordovaGoogleMap",["$q","$window",function(e,n){var r=null;return{getMap:function(o){var t=e.defer();if(n.plugin.google.maps){var i=document.getElementById("map_canvas");r=n.plugin.google.maps.Map.getMap(o),r.setDiv(i),t.resolve(r)}else t.reject(null);return t.promise},isMapLoaded:function(){return!!r},addMarker:function(n){var o=e.defer();return r.addMarker(n,function(e){o.resolve(e)}),o.promise},getMapTypeIds:function(){return n.plugin.google.maps.mapTypeId},setVisible:function(n){var o=e.defer();return r.setVisible(n),o.promise},cleanup:function(){r=null}}}]),angular.module("ngCordova.plugins.googlePlayGame",[]).factory("$cordovaGooglePlayGame",["$q",function(e){return{auth:function(){var n=e.defer();return googleplaygame.auth(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},signout:function(){var n=e.defer();return googleplaygame.signout(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},isSignedIn:function(){var n=e.defer();return googleplaygame.isSignedIn(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},showPlayer:function(){var n=e.defer();return googleplaygame.showPlayer(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},submitScore:function(n){var r=e.defer();return googleplaygame.submitScore(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},showAllLeaderboards:function(){var n=e.defer();return googleplaygame.showAllLeaderboards(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},showLeaderboard:function(n){var r=e.defer();return googleplaygame.showLeaderboard(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},unlockAchievement:function(n){var r=e.defer();return googleplaygame.unlockAchievement(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},incrementAchievement:function(n){var r=e.defer();return googleplaygame.incrementAchievement(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},showAchievements:function(){var n=e.defer();return googleplaygame.showAchievements(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.googlePlus",[]).factory("$cordovaGooglePlus",["$q","$window",function(e,n){return{login:function(r){var o=e.defer();return void 0===r&&(r={}),n.plugins.googleplus.login({iOSApiKey:r},function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},silentLogin:function(r){var o=e.defer();return void 0===r&&(r={}),n.plugins.googleplus.trySilentLogin({iOSApiKey:r},function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},logout:function(){var r=e.defer();n.plugins.googleplus.logout(function(e){r.resolve(e)})},disconnect:function(){var r=e.defer();n.plugins.googleplus.disconnect(function(e){r.resolve(e)})},isAvailable:function(){var r=e.defer();return n.plugins.googleplus.isAvailable(function(e){e?r.resolve(e):r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.healthKit",[]).factory("$cordovaHealthKit",["$q","$window",function(e,n){return{isAvailable:function(){var r=e.defer();return n.plugins.healthkit.available(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},checkAuthStatus:function(r){var o=e.defer();return r=r||"HKQuantityTypeIdentifierHeight",n.plugins.healthkit.checkAuthStatus({type:r},function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},requestAuthorization:function(r,o){var t=e.defer();return r=r||["HKCharacteristicTypeIdentifierDateOfBirth","HKQuantityTypeIdentifierActiveEnergyBurned","HKQuantityTypeIdentifierHeight"],o=o||["HKQuantityTypeIdentifierActiveEnergyBurned","HKQuantityTypeIdentifierHeight","HKQuantityTypeIdentifierDistanceCycling"],n.plugins.healthkit.requestAuthorization({readTypes:r,writeTypes:o},function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},readDateOfBirth:function(){var r=e.defer();return n.plugins.healthkit.readDateOfBirth(function(e){r.resolve(e)},function(e){r.resolve(e)}),r.promise},readGender:function(){var r=e.defer();return n.plugins.healthkit.readGender(function(e){r.resolve(e)},function(e){r.resolve(e)}),r.promise},saveWeight:function(r,o,t){var i=e.defer();return n.plugins.healthkit.saveWeight({unit:o||"lb",amount:r,date:t||new Date},function(e){i.resolve(e)},function(e){i.resolve(e)}),i.promise},readWeight:function(r){var o=e.defer();return n.plugins.healthkit.readWeight({unit:r||"lb"},function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise},saveHeight:function(r,o,t){var i=e.defer();return n.plugins.healthkit.saveHeight({unit:o||"in",amount:r,date:t||new Date},function(e){i.resolve(e)},function(e){i.resolve(e)}),i.promise},readHeight:function(r){var o=e.defer();return n.plugins.healthkit.readHeight({unit:r||"in"},function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise},findWorkouts:function(){var r=e.defer();return n.plugins.healthkit.findWorkouts({},function(e){r.resolve(e)},function(e){r.resolve(e)}),r.promise},saveWorkout:function(r){var o=e.defer();return n.plugins.healthkit.saveWorkout(r,function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise},querySampleType:function(r){var o=e.defer();return n.plugins.healthkit.querySampleType(r,function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise}}}]),angular.module("ngCordova.plugins.httpd",[]).factory("$cordovaHttpd",["$q",function(e){return{startServer:function(n){var r=e.defer();return cordova.plugins.CorHttpd.startServer(n,function(){r.resolve()},function(){r.reject()}),r.promise},stopServer:function(){var n=e.defer();return cordova.plugins.CorHttpd.stopServer(function(){n.resolve()},function(){n.reject()}),n.promise},getURL:function(){var n=e.defer();return cordova.plugins.CorHttpd.getURL(function(e){n.resolve(e)},function(){n.reject()}),n.promise},getLocalPath:function(){var n=e.defer();return cordova.plugins.CorHttpd.getLocalPath(function(e){n.resolve(e)},function(){n.reject()}),n.promise}}}]),angular.module("ngCordova.plugins.iAd",[]).factory("$cordovaiAd",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.iAd.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.iAd.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.iAd.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.iAd.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.iAd.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.iAd.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.iAd.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.iAd.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.imagePicker",[]).factory("$cordovaImagePicker",["$q","$window",function(e,n){return{getPictures:function(r){var o=e.defer();return n.imagePicker.getPictures(function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise}}}]),angular.module("ngCordova.plugins.inAppBrowser",[]).provider("$cordovaInAppBrowser",[function(){var e,n=this.defaultOptions={};this.setDefaultOptions=function(e){n=angular.extend(n,e)},this.$get=["$rootScope","$q","$window","$timeout",function(r,o,t,i){return{open:function(a,c,u){var s=o.defer();if(u&&!angular.isObject(u))return s.reject("options must be an object"),s.promise;var l=angular.extend({},n,u),f=[];angular.forEach(l,function(e,n){f.push(n+"="+e)});var d=f.join();return e=t.open(a,c,d),e.addEventListener("loadstart",function(e){i(function(){r.$broadcast("$cordovaInAppBrowser:loadstart",e)})},!1),e.addEventListener("loadstop",function(e){s.resolve(e),i(function(){r.$broadcast("$cordovaInAppBrowser:loadstop",e)})},!1),e.addEventListener("loaderror",function(e){s.reject(e),i(function(){r.$broadcast("$cordovaInAppBrowser:loaderror",e)})},!1),e.addEventListener("exit",function(e){i(function(){r.$broadcast("$cordovaInAppBrowser:exit",e)})},!1),s.promise},close:function(){e.close(),e=null},show:function(){e.show()},executeScript:function(n){var r=o.defer();return e.executeScript(n,function(e){r.resolve(e)}),r.promise},insertCSS:function(n){var r=o.defer();return e.insertCSS(n,function(e){r.resolve(e)}),r.promise}}}]}]),angular.module("ngCordova.plugins.insomnia",[]).factory("$cordovaInsomnia",["$window",function(e){return{keepAwake:function(){return e.plugins.insomnia.keepAwake()},allowSleepAgain:function(){return e.plugins.insomnia.allowSleepAgain()}}}]),angular.module("ngCordova.plugins.instagram",[]).factory("$cordovaInstagram",["$q",function(e){return{share:function(n){var r=e.defer();return window.Instagram?(Instagram.share(n.image,n.caption,function(e){e?r.reject(e):r.resolve(!0)}),r.promise):(console.error("Tried to call Instagram.share but the Instagram plugin isn't installed!"),r.resolve(null),r.promise)},isInstalled:function(){var n=e.defer();return window.Instagram?(Instagram.isInstalled(function(e,r){e?n.reject(e):n.resolve(r)}),n.promise):(console.error("Tried to call Instagram.isInstalled but the Instagram plugin isn't installed!"),n.resolve(null),n.promise)}}}]),angular.module("ngCordova.plugins.keyboard",[]).factory("$cordovaKeyboard",["$rootScope",function(e){var n=function(){e.$evalAsync(function(){e.$broadcast("$cordovaKeyboard:show")})},r=function(){e.$evalAsync(function(){e.$broadcast("$cordovaKeyboard:hide")})};return document.addEventListener("deviceready",function(){cordova.plugins.Keyboard&&(window.addEventListener("native.keyboardshow",n,!1),window.addEventListener("native.keyboardhide",r,!1))}),{hideAccessoryBar:function(e){return cordova.plugins.Keyboard.hideKeyboardAccessoryBar(e)},close:function(){return cordova.plugins.Keyboard.close()},show:function(){return cordova.plugins.Keyboard.show()},disableScroll:function(e){return cordova.plugins.Keyboard.disableScroll(e)},isVisible:function(){return cordova.plugins.Keyboard.isVisible},clearShowWatch:function(){document.removeEventListener("native.keyboardshow",n),e.$$listeners["$cordovaKeyboard:show"]=[]},clearHideWatch:function(){document.removeEventListener("native.keyboardhide",r),e.$$listeners["$cordovaKeyboard:hide"]=[]}}}]),angular.module("ngCordova.plugins.keychain",[]).factory("$cordovaKeychain",["$q",function(e){return{getForKey:function(n,r){var o=e.defer(),t=new Keychain;return t.getForKey(o.resolve,o.reject,n,r),o.promise},setForKey:function(n,r,o){var t=e.defer(),i=new Keychain;return i.setForKey(t.resolve,t.reject,n,r,o),t.promise},removeForKey:function(n,r){var o=e.defer(),t=new Keychain;return t.removeForKey(o.resolve,o.reject,n,r),o.promise}}}]),angular.module("ngCordova.plugins.launchNavigator",[]).factory("$cordovaLaunchNavigator",["$q",function(e){return{navigate:function(n,r,o){var t=e.defer();return launchnavigator.navigate(n,r,function(){t.resolve()},function(e){t.reject(e)},o),t.promise}}}]),angular.module("ngCordova.plugins.localNotification",[]).factory("$cordovaLocalNotification",["$q","$window","$rootScope","$timeout",function(e,n,r,o){return document.addEventListener("deviceready",function(){n.cordova&&n.cordova.plugins&&n.cordova.plugins.notification&&n.cordova.plugins.notification.local&&(n.cordova.plugins.notification.local.on("schedule",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:schedule",e,n)})}),n.cordova.plugins.notification.local.on("trigger",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:trigger",e,n)})}),n.cordova.plugins.notification.local.on("update",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:update",e,n)})}),n.cordova.plugins.notification.local.on("clear",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:clear",e,n)})}),n.cordova.plugins.notification.local.on("clearall",function(e){o(function(){r.$broadcast("$cordovaLocalNotification:clearall",e)})}),n.cordova.plugins.notification.local.on("cancel",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:cancel",e,n)})}),n.cordova.plugins.notification.local.on("cancelall",function(e){o(function(){r.$broadcast("$cordovaLocalNotification:cancelall",e)})}),n.cordova.plugins.notification.local.on("click",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:click",e,n)})}))},!1),{schedule:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.schedule(r,function(e){t.resolve(e)},o),t.promise},add:function(r,o){console.warn('Deprecated: use "schedule" instead.');var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.schedule(r,function(e){t.resolve(e)},o),t.promise},update:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.update(r,function(e){t.resolve(e)},o),t.promise},clear:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.clear(r,function(e){t.resolve(e)},o),t.promise},clearAll:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.clearAll(function(e){o.resolve(e)},r),o.promise},cancel:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.cancel(r,function(e){t.resolve(e)},o),t.promise},cancelAll:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.cancelAll(function(e){o.resolve(e)},r),o.promise},isPresent:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.isPresent(r,function(e){t.resolve(e)},o),t.promise},isScheduled:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.isScheduled(r,function(e){t.resolve(e)},o),t.promise},isTriggered:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.isTriggered(r,function(e){t.resolve(e)},o),t.promise},hasPermission:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.hasPermission(function(e){e?o.resolve(e):o.reject(e)},r),o.promise},registerPermission:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.registerPermission(function(e){e?o.resolve(e):o.reject(e)},r),o.promise},promptForPermission:function(r){console.warn('Deprecated: use "registerPermission" instead.');var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.registerPermission(function(e){ -e?o.resolve(e):o.reject(e)},r),o.promise},getAllIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAllIds(function(e){o.resolve(e)},r),o.promise},getIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getIds(function(e){o.resolve(e)},r),o.promise},getScheduledIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getScheduledIds(function(e){o.resolve(e)},r),o.promise},getTriggeredIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getTriggeredIds(function(e){o.resolve(e)},r),o.promise},get:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.get(r,function(e){t.resolve(e)},o),t.promise},getAll:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAll(function(e){o.resolve(e)},r),o.promise},getScheduled:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.getScheduled(r,function(e){t.resolve(e)},o),t.promise},getAllScheduled:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAllScheduled(function(e){o.resolve(e)},r),o.promise},getTriggered:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.getTriggered(r,function(e){t.resolve(e)},o),t.promise},getAllTriggered:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAllTriggered(function(e){o.resolve(e)},r),o.promise},getDefaults:function(){return n.cordova.plugins.notification.local.getDefaults()},setDefaults:function(e){n.cordova.plugins.notification.local.setDefaults(e)}}}]),angular.module("ngCordova.plugins.mMediaAds",[]).factory("$cordovaMMediaAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.mMedia.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.mMedia.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.mMedia.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.mMedia.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.mMedia.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.mMedia.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.mMedia.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.mMedia.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.media",[]).service("NewMedia",["$q","$interval",function(e,n){function r(e){angular.isDefined(s)||(s=n(function(){0>d&&(d=e.getDuration(),a&&d>0&&a.notify({duration:d})),e.getCurrentPosition(function(e){e>-1&&(f=e)},function(e){console.log("Error getting pos="+e)}),a&&a.notify({position:f})},1e3))}function o(){angular.isDefined(s)&&(n.cancel(s),s=void 0)}function t(){f=-1,d=-1}function i(e){this.media=new Media(e,function(e){o(),t(),a.resolve(e)},function(e){o(),t(),a.reject(e)},function(e){l=e,a.notify({status:l})})}var a,c,u,s,l=null,f=-1,d=-1;return i.prototype.play=function(n){return a=e.defer(),"object"!=typeof n&&(n={}),this.media.play(n),r(this.media),a.promise},i.prototype.pause=function(){o(),this.media.pause()},i.prototype.stop=function(){this.media.stop()},i.prototype.release=function(){this.media.release(),this.media=void 0},i.prototype.seekTo=function(e){this.media.seekTo(e)},i.prototype.setVolume=function(e){this.media.setVolume(e)},i.prototype.startRecord=function(){this.media.startRecord()},i.prototype.stopRecord=function(){this.media.stopRecord()},i.prototype.currentTime=function(){return c=e.defer(),this.media.getCurrentPosition(function(e){c.resolve(e)}),c.promise},i.prototype.getDuration=function(){return u=e.defer(),this.media.getDuration(function(e){u.resolve(e)}),u.promise},i}]).factory("$cordovaMedia",["NewMedia",function(e){return{newMedia:function(n){return new e(n)}}}]),angular.module("ngCordova.plugins.mobfoxAds",[]).factory("$cordovaMobFoxAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.MobFox.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.MobFox.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.MobFox.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.MobFox.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.MobFox.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.MobFox.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.MobFox.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.MobFox.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins",["ngCordova.plugins.actionSheet","ngCordova.plugins.adMob","ngCordova.plugins.appAvailability","ngCordova.plugins.appRate","ngCordova.plugins.appVersion","ngCordova.plugins.backgroundGeolocation","ngCordova.plugins.badge","ngCordova.plugins.barcodeScanner","ngCordova.plugins.batteryStatus","ngCordova.plugins.beacon","ngCordova.plugins.ble","ngCordova.plugins.bluetoothSerial","ngCordova.plugins.brightness","ngCordova.plugins.calendar","ngCordova.plugins.camera","ngCordova.plugins.capture","ngCordova.plugins.clipboard","ngCordova.plugins.contacts","ngCordova.plugins.datePicker","ngCordova.plugins.device","ngCordova.plugins.deviceMotion","ngCordova.plugins.deviceOrientation","ngCordova.plugins.dialogs","ngCordova.plugins.emailComposer","ngCordova.plugins.facebook","ngCordova.plugins.facebookAds","ngCordova.plugins.file","ngCordova.plugins.fileTransfer","ngCordova.plugins.fileOpener2","ngCordova.plugins.flashlight","ngCordova.plugins.flurryAds","ngCordova.plugins.ga","ngCordova.plugins.geolocation","ngCordova.plugins.globalization","ngCordova.plugins.googleAds","ngCordova.plugins.googleAnalytics","ngCordova.plugins.googleMap","ngCordova.plugins.googlePlayGame","ngCordova.plugins.googlePlus","ngCordova.plugins.healthKit","ngCordova.plugins.httpd","ngCordova.plugins.iAd","ngCordova.plugins.imagePicker","ngCordova.plugins.inAppBrowser","ngCordova.plugins.instagram","ngCordova.plugins.keyboard","ngCordova.plugins.keychain","ngCordova.plugins.launchNavigator","ngCordova.plugins.localNotification","ngCordova.plugins.media","ngCordova.plugins.mMediaAds","ngCordova.plugins.mobfoxAds","ngCordova.plugins.mopubAds","ngCordova.plugins.nativeAudio","ngCordova.plugins.network","ngCordova.plugins.pinDialog","ngCordova.plugins.preferences","ngCordova.plugins.printer","ngCordova.plugins.progressIndicator","ngCordova.plugins.push","ngCordova.plugins.push_v5","ngCordova.plugins.sms","ngCordova.plugins.socialSharing","ngCordova.plugins.spinnerDialog","ngCordova.plugins.splashscreen","ngCordova.plugins.sqlite","ngCordova.plugins.statusbar","ngCordova.plugins.toast","ngCordova.plugins.touchid","ngCordova.plugins.vibration","ngCordova.plugins.videoCapturePlus","ngCordova.plugins.zip","ngCordova.plugins.insomnia"]),angular.module("ngCordova.plugins.mopubAds",[]).factory("$cordovaMoPubAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.MoPub.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.MoPub.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.MoPub.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.MoPub.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.MoPub.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.MoPub.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.MoPub.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.MoPub.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.nativeAudio",[]).factory("$cordovaNativeAudio",["$q","$window",function(e,n){return{preloadSimple:function(r,o){var t=e.defer();return n.plugins.NativeAudio.preloadSimple(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},preloadComplex:function(r,o,t,i,a){var c=e.defer();return n.plugins.NativeAudio.preloadComplex(r,o,t,i,a,function(e){c.resolve(e)},function(e){c.reject(e)}),c.promise},play:function(r,o){var t=e.defer();return n.plugins.NativeAudio.play(r,function(e){t.resolve(e)},function(e){t.reject(e)},o),t.promise},stop:function(r){var o=e.defer();return n.plugins.NativeAudio.stop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},loop:function(r){var o=e.defer();return n.plugins.NativeAudio.loop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},unload:function(r){var o=e.defer();return n.plugins.NativeAudio.unload(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},setVolumeForComplexAsset:function(r,o){var t=e.defer();return n.plugins.NativeAudio.setVolumeForComplexAsset(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise}}}]),angular.module("ngCordova.plugins.network",[]).factory("$cordovaNetwork",["$rootScope","$timeout",function(e,n){var r=function(){var r=navigator.connection.type;n(function(){e.$broadcast("$cordovaNetwork:offline",r)})},o=function(){var r=navigator.connection.type;n(function(){e.$broadcast("$cordovaNetwork:online",r)})};return document.addEventListener("deviceready",function(){navigator.connection&&(document.addEventListener("offline",r,!1),document.addEventListener("online",o,!1))}),{getNetwork:function(){return navigator.connection.type},isOnline:function(){var e=navigator.connection.type;return e!==Connection.UNKNOWN&&e!==Connection.NONE},isOffline:function(){var e=navigator.connection.type;return e===Connection.UNKNOWN||e===Connection.NONE},clearOfflineWatch:function(){document.removeEventListener("offline",r),e.$$listeners["$cordovaNetwork:offline"]=[]},clearOnlineWatch:function(){document.removeEventListener("online",o),e.$$listeners["$cordovaNetwork:online"]=[]}}}]).run(["$injector",function(e){e.get("$cordovaNetwork")}]),angular.module("ngCordova.plugins.pinDialog",[]).factory("$cordovaPinDialog",["$q","$window",function(e,n){return{prompt:function(r,o,t){var i=e.defer();return n.plugins.pinDialog.prompt(r,function(e){i.resolve(e)},o,t),i.promise}}}]),angular.module("ngCordova.plugins.preferences",[]).factory("$cordovaPreferences",["$window","$q",function(e,n){return{pluginNotEnabledMessage:"Plugin not enabled",decoratePromise:function(e){e.success=function(n){return e.then(n),e},e.error=function(n){return e.then(null,n),e}},store:function(r,o,t){function i(e){c.resolve(e)}function a(e){c.reject(new Error(e))}var c=n.defer(),u=c.promise;if(e.plugins){var s;s=3===arguments.length?e.plugins.appPreferences.store(t,r,o):e.plugins.appPreferences.store(r,o),s.then(i,a)}else c.reject(new Error(this.pluginNotEnabledMessage));return this.decoratePromise(u),u},fetch:function(r,o){function t(e){a.resolve(e)}function i(e){a.reject(new Error(e))}var a=n.defer(),c=a.promise;if(e.plugins){var u;u=2===arguments.length?e.plugins.appPreferences.fetch(o,r):e.plugins.appPreferences.fetch(r),u.then(t,i)}else a.reject(new Error(this.pluginNotEnabledMessage));return this.decoratePromise(c),c},remove:function(r,o){function t(e){a.resolve(e)}function i(e){a.reject(new Error(e))}var a=n.defer(),c=a.promise;if(e.plugins){var u;u=2===arguments.length?e.plugins.appPreferences.remove(o,r):e.plugins.appPreferences.remove(r),u.then(t,i)}else a.reject(new Error(this.pluginNotEnabledMessage));return this.decoratePromise(c),c},show:function(){function r(e){t.resolve(e)}function o(e){t.reject(new Error(e))}var t=n.defer(),i=t.promise;return e.plugins?e.plugins.appPreferences.show().then(r,o):t.reject(new Error(this.pluginNotEnabledMessage)),this.decoratePromise(i),i}}}]),angular.module("ngCordova.plugins.printer",[]).factory("$cordovaPrinter",["$q","$window",function(e,n){return{isAvailable:function(){var r=e.defer();return n.plugin.printer.isAvailable(function(e){r.resolve(e)}),r.promise},print:function(r,o){var t=e.defer();return n.plugin.printer.print(r,o,function(){t.resolve()}),t.promise}}}]),angular.module("ngCordova.plugins.progressIndicator",[]).factory("$cordovaProgress",[function(){return{show:function(e){var n=e||"Please wait...";return ProgressIndicator.show(n)},showSimple:function(e){var n=e||!1;return ProgressIndicator.showSimple(n)},showSimpleWithLabel:function(e,n){var r=e||!1,o=n||"Loading...";return ProgressIndicator.showSimpleWithLabel(r,o)},showSimpleWithLabelDetail:function(e,n,r){var o=e||!1,t=n||"Loading...",i=r||"Please wait";return ProgressIndicator.showSimpleWithLabelDetail(o,t,i)},showDeterminate:function(e,n){var r=e||!1,o=n||5e4;return ProgressIndicator.showDeterminate(r,o)},showDeterminateWithLabel:function(e,n,r){var o=e||!1,t=n||5e4,i=r||"Loading...";return ProgressIndicator.showDeterminateWithLabel(o,t,i)},showAnnular:function(e,n){var r=e||!1,o=n||5e4;return ProgressIndicator.showAnnular(r,o)},showAnnularWithLabel:function(e,n,r){var o=e||!1,t=n||5e4,i=r||"Loading...";return ProgressIndicator.showAnnularWithLabel(o,t,i)},showBar:function(e,n){var r=e||!1,o=n||5e4;return ProgressIndicator.showBar(r,o)},showBarWithLabel:function(e,n,r){var o=e||!1,t=n||5e4,i=r||"Loading...";return ProgressIndicator.showBarWithLabel(o,t,i)},showSuccess:function(e,n){var r=e||!1,o=n||"Success";return ProgressIndicator.showSuccess(r,o)},showText:function(e,n,r){var o=e||!1,t=n||"Warning",i=r||"center";return ProgressIndicator.showText(o,t,i)},hide:function(){return ProgressIndicator.hide()}}}]),angular.module("ngCordova.plugins.push",[]).factory("$cordovaPush",["$q","$window","$rootScope","$timeout",function(e,n,r,o){return{onNotification:function(e){o(function(){r.$broadcast("$cordovaPush:notificationReceived",e)})},register:function(r){var o,t=e.defer();return void 0!==r&&void 0===r.ecb&&(o=null===document.querySelector("[ng-app]")?"document.body":"document.querySelector('[ng-app]')",r.ecb="angular.element("+o+").injector().get('$cordovaPush').onNotification"),n.plugins.pushNotification.register(function(e){t.resolve(e)},function(e){t.reject(e)},r),t.promise},unregister:function(r){var o=e.defer();return n.plugins.pushNotification.unregister(function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},setBadgeNumber:function(r){var o=e.defer();return n.plugins.pushNotification.setApplicationIconBadgeNumber(function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise}}}]),angular.module("ngCordova.plugins.push_v5",[]).factory("$cordovaPushV5",["$q","$rootScope","$timeout",function(e,n,r){var o;return{initialize:function(n){var r=e.defer();return o=PushNotification.init(n),r.resolve(o),r.promise},onNotification:function(){r(function(){o.on("notification",function(e){n.$emit("$cordovaPushV5:notificationReceived",e)})})},onError:function(){r(function(){o.on("error",function(e){n.$emit("$cordovaPushV5:errorOccurred",e)})})},register:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.on("registration",function(e){n.resolve(e.registrationId)}),n.promise},unregister:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.unregister(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getBadgeNumber:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.getApplicationIconBadgeNumber(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},setBadgeNumber:function(n){var r=e.defer();return void 0===o?r.reject(new Error("init must be called before any other operation")):o.setApplicationIconBadgeNumber(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},finish:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.finish(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.screenshot",[]).factory("$cordovaScreenshot",["$q",function(e){return{captureToFile:function(n){var r=n||{},o=r.extension||"jpg",t=r.quality||"100",i=e.defer();return navigator.screenshot?(navigator.screenshot.save(function(e,n){e?i.reject(e):i.resolve(n.filePath)},o,t,r.filename),i.promise):(i.resolve(null),i.promise)},captureToUri:function(n){var r=n||{},o=r.extension||"jpg",t=r.quality||"100",i=e.defer();return navigator.screenshot?(navigator.screenshot.URI(function(e,n){e?i.reject(e):i.resolve(n.URI)},o,t,r.filename),i.promise):(i.resolve(null),i.promise)}}}]),angular.module("ngCordova.plugins.sms",[]).factory("$cordovaSms",["$q",function(e){return{send:function(n,r,o){var t=e.defer();return sms.send(n,r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise}}}]),angular.module("ngCordova.plugins.socialSharing",[]).factory("$cordovaSocialSharing",["$q","$window",function(e,n){return{share:function(r,o,t,i){var a=e.defer();return o=o||null,t=t||null,i=i||null,n.plugins.socialsharing.share(r,o,t,i,function(){a.resolve(!0)},function(){a.reject(!1)}),a.promise},shareViaTwitter:function(r,o,t){var i=e.defer();return o=o||null,t=t||null,n.plugins.socialsharing.shareViaTwitter(r,o,t,function(){i.resolve(!0)},function(){i.reject(!1)}),i.promise},shareViaWhatsApp:function(r,o,t){var i=e.defer();return o=o||null,t=t||null,n.plugins.socialsharing.shareViaWhatsApp(r,o,t,function(){i.resolve(!0)},function(){i.reject(!1)}),i.promise},shareViaFacebook:function(r,o,t){var i=e.defer();return r=r||null,o=o||null,t=t||null,n.plugins.socialsharing.shareViaFacebook(r,o,t,function(){i.resolve(!0)},function(){i.reject(!1)}),i.promise},shareViaFacebookWithPasteMessageHint:function(r,o,t,i){var a=e.defer();return o=o||null,t=t||null,n.plugins.socialsharing.shareViaFacebookWithPasteMessageHint(r,o,t,i,function(){a.resolve(!0)},function(){a.reject(!1)}),a.promise},shareViaSMS:function(r,o){var t=e.defer();return n.plugins.socialsharing.shareViaSMS(r,o,function(){t.resolve(!0)},function(){t.reject(!1)}),t.promise},shareViaEmail:function(r,o,t,i,a,c){var u=e.defer();return t=t||null,i=i||null,a=a||null,c=c||null,n.plugins.socialsharing.shareViaEmail(r,o,t,i,a,c,function(){u.resolve(!0)},function(){u.reject(!1)}),u.promise},shareVia:function(r,o,t,i,a){var c=e.defer();return o=o||null,t=t||null,i=i||null,a=a||null,n.plugins.socialsharing.shareVia(r,o,t,i,a,function(){c.resolve(!0)},function(){c.reject(!1)}),c.promise},canShareViaEmail:function(){var r=e.defer();return n.plugins.socialsharing.canShareViaEmail(function(){r.resolve(!0)},function(){r.reject(!1)}),r.promise},canShareVia:function(r,o,t,i,a){var c=e.defer();return n.plugins.socialsharing.canShareVia(r,o,t,i,a,function(e){c.resolve(e)},function(e){c.reject(e)}),c.promise},available:function(){var n=e.defer();return window.plugins.socialsharing.available(function(e){e?n.resolve():n.reject()}),n.promise}}}]),angular.module("ngCordova.plugins.spinnerDialog",[]).factory("$cordovaSpinnerDialog",["$window",function(e){return{show:function(n,r,o){return o=o||!1,e.plugins.spinnerDialog.show(n,r,o)},hide:function(){return e.plugins.spinnerDialog.hide()}}}]),angular.module("ngCordova.plugins.splashscreen",[]).factory("$cordovaSplashscreen",[function(){return{hide:function(){return navigator.splashscreen.hide()},show:function(){return navigator.splashscreen.show()}}}]),angular.module("ngCordova.plugins.sqlite",[]).factory("$cordovaSQLite",["$q","$window",function(e,n){return{openDB:function(e,r){return angular.isObject(e)&&!angular.isString(e)?("undefined"!=typeof r&&(e.bgType=r),n.sqlitePlugin.openDatabase(e)):n.sqlitePlugin.openDatabase({name:e,bgType:r})},execute:function(n,r,o){var t=e.defer();return n.transaction(function(e){e.executeSql(r,o,function(e,n){t.resolve(n)},function(e,n){t.reject(n)})}),t.promise},insertCollection:function(n,r,o){var t=e.defer(),i=o.slice(0);return n.transaction(function(e){!function n(){var o=i.splice(0,1)[0];try{e.executeSql(r,o,function(e,r){0===i.length?t.resolve(r):n()},function(e,n){t.reject(n)})}catch(a){t.reject(a)}}()}),t.promise},nestedExecute:function(n,r,o,t,i){var a=e.defer();return n.transaction(function(e){e.executeSql(r,t,function(e,n){a.resolve(n),e.executeSql(o,i,function(e,n){a.resolve(n)})})},function(e,n){a.reject(n)}),a.promise},deleteDB:function(r){var o=e.defer();return n.sqlitePlugin.deleteDatabase(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.statusbar",[]).factory("$cordovaStatusbar",[function(){return{overlaysWebView:function(e){return StatusBar.overlaysWebView(!!e)},STYLES:{DEFAULT:0,LIGHT_CONTENT:1,BLACK_TRANSLUCENT:2,BLACK_OPAQUE:3},style:function(e){switch(e){case 0:return StatusBar.styleDefault();case 1:return StatusBar.styleLightContent();case 2:return StatusBar.styleBlackTranslucent();case 3:return StatusBar.styleBlackOpaque();default:return StatusBar.styleDefault()}},styleColor:function(e){return StatusBar.backgroundColorByName(e)},styleHex:function(e){return StatusBar.backgroundColorByHexString(e)},hide:function(){return StatusBar.hide()},show:function(){return StatusBar.show()},isVisible:function(){return StatusBar.isVisible}}}]),angular.module("ngCordova.plugins.toast",[]).factory("$cordovaToast",["$q","$window",function(e,n){return{showShortTop:function(r){var o=e.defer();return n.plugins.toast.showShortTop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showShortCenter:function(r){var o=e.defer();return n.plugins.toast.showShortCenter(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showShortBottom:function(r){var o=e.defer();return n.plugins.toast.showShortBottom(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showLongTop:function(r){var o=e.defer();return n.plugins.toast.showLongTop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showLongCenter:function(r){var o=e.defer();return n.plugins.toast.showLongCenter(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showLongBottom:function(r){var o=e.defer();return n.plugins.toast.showLongBottom(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},show:function(r,o,t){var i=e.defer();return n.plugins.toast.show(r,o,t,function(e){i.resolve(e)},function(e){i.reject(e)}),i.promise},hide:function(){var r=e.defer();try{n.plugins.toast.hide(),r.resolve()}catch(o){r.reject(o&&o.message)}return r.promise}}}]),angular.module("ngCordova.plugins.touchid",[]).factory("$cordovaTouchID",["$q",function(e){return{checkSupport:function(){var n=e.defer();return window.cordova?touchid.checkSupport(function(e){n.resolve(e)},function(e){n.reject(e)}):n.reject("Not supported without cordova.js"),n.promise},authenticate:function(n){var r=e.defer();return window.cordova?touchid.authenticate(function(e){r.resolve(e)},function(e){r.reject(e)},n):r.reject("Not supported without cordova.js"),r.promise}}}]),angular.module("ngCordova.plugins.upsPush",[]).factory("$cordovaUpsPush",["$q","$window","$rootScope","$timeout",function(e,n,r,o){return{register:function(t){var i=e.defer();return n.push.register(function(e){o(function(){r.$broadcast("$cordovaUpsPush:notificationReceived",e)})},function(){i.resolve()},function(e){i.reject(e)},t),i.promise},unregister:function(r){var o=e.defer();return n.push.unregister(function(){o.resolve()},function(e){o.reject(e)},r),o.promise},setBadgeNumber:function(r){var o=e.defer();return n.push.setApplicationIconBadgeNumber(function(){o.resolve()},r),o.promise}}}]),angular.module("ngCordova.plugins.vibration",[]).factory("$cordovaVibration",[function(){return{vibrate:function(e){return navigator.notification.vibrate(e)},vibrateWithPattern:function(e,n){return navigator.notification.vibrateWithPattern(e,n)},cancelVibration:function(){return navigator.notification.cancelVibration()}}}]),angular.module("ngCordova.plugins.videoCapturePlus",[]).provider("$cordovaVideoCapturePlus",[function(){var e={};this.setLimit=function(n){e.limit=n},this.setMaxDuration=function(n){e.duration=n},this.setHighQuality=function(n){e.highquality=n},this.useFrontCamera=function(n){e.frontcamera=n},this.setPortraitOverlay=function(n){e.portraitOverlay=n},this.setLandscapeOverlay=function(n){e.landscapeOverlay=n},this.setOverlayText=function(n){e.overlayText=n},this.$get=["$q","$window",function(n,r){return{captureVideo:function(o){var t=n.defer();return r.plugins.videocaptureplus?(r.plugins.videocaptureplus.captureVideo(t.resolve,t.reject,angular.extend({},e,o)),t.promise):(t.resolve(null),t.promise)}}}]}]),angular.module("ngCordova.plugins.zip",[]).factory("$cordovaZip",["$q","$window",function(e,n){return{unzip:function(r,o){var t=e.defer();return n.zip.unzip(r,o,function(e){0===e?t.resolve():t.reject()},function(e){t.notify(e)}),t.promise}}}])}(); \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/vendor/numeral.en.js b/assets/www/dist/dist_js/app/vendor/numeral.en.js deleted file mode 100644 index 8e2d6402bcc01ac04a4f9ead620d38587baff58c..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/numeral.en.js +++ /dev/null @@ -1,26 +0,0 @@ -//! moment.js locale configuration -//! locale : english (en) -//! author : Benoit Lavenier : https://github.com/blavenie - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('./numeral')) : - typeof define === 'function' && define.amd ? define(['numeral'], factory) : - factory(global.numeral) -}(this, function (numeral) { 'use strict'; - - numeral.language('en', { - "delimiters": { - "thousands": ",", - "decimal": "." - }, - "abbreviations": { - "thousand": "<small>x10<sup>3</sup></small>", - "million": "<small>x10<sup>6</sup></small>", - "billion": "<small>x10<sup>9</sup></small>", - "trillion": "<small>x10<sup>12</sup></small>" - }, - "currency": { - "symbol": "X" - } - }); -})); diff --git a/assets/www/js/vendor/numeral.fr.js b/assets/www/dist/dist_js/app/vendor/numeral.eo.js similarity index 80% rename from assets/www/js/vendor/numeral.fr.js rename to assets/www/dist/dist_js/app/vendor/numeral.eo.js index 89679d85949df84fd6aea7122d107a0c210a11fe..5ccd37e71a5a7908db44f3e8d6d055379ae51758 100644 --- a/assets/www/js/vendor/numeral.fr.js +++ b/assets/www/dist/dist_js/app/vendor/numeral.eo.js @@ -1,6 +1,6 @@ //! numeral.js locale configuration -//! locale : french (fr) -//! author : blavenie: https://github.com/blavenie +//! locale : esperanto (eo) +//! author : Vivakvo: https://github.com/vivakvo (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../numeral')) : @@ -8,7 +8,7 @@ factory(global.numeral) }(this, function (numeral) { 'use strict'; - numeral.language('fr', { + numeral.language('eo', { "delimiters": { "thousands": " ", "decimal": "," @@ -20,7 +20,7 @@ "trillion": "x10^12" }, "ordinal": function (number) { - return (number === 1) ? 'er' : 'ième'; + return (number === 1) ? 'a' : 'a'; }, "currency": { "symbol": "X" diff --git a/assets/www/dist/dist_js/app/vendor/numeral.es.js b/assets/www/dist/dist_js/app/vendor/numeral.es.js deleted file mode 100644 index 82885185fa168bb52f40e6df4b260d4f7e479ea4..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/numeral.es.js +++ /dev/null @@ -1,47 +0,0 @@ -//! numeral.js locale configuration -//! locale : spanish (es) -//! author : Fiatou: https://github.com/fiatou - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../numeral')) : - typeof define === 'function' && define.amd ? define(['numeral'], factory) : - factory(global.numeral) -}(this, function (numeral) { 'use strict'; - - numeral.language('es', { - "delimiters": { - "thousands": " ", - "decimal": "," - }, - "abbreviations": { - "thousand": "<small>x10<sup>3</sup></small>", - "million": "<small>x10<sup>6</sup></small>", - "billion": "<small>x10<sup>9</sup></small>", - "trillion": "<small>x10<sup>12</sup></small>" - }, - "ordinal": function (number) { - switch(number) { - case 1: - return 'ero'; - case 2: - return 'do'; - case 3: - return 'ro'; - case 4: - case 5: - case 6: - case 7: - return 'to'; - case 8: - return 'vo'; - case 9: - return 'no'; - default: - return 'mo'; - } - }, - "currency": { - "symbol": "X" - } - }); -})); diff --git a/assets/www/dist/dist_js/app/vendor/numeral.js b/assets/www/dist/dist_js/app/vendor/numeral.js deleted file mode 100644 index 9f46ab65574ea436c29b25880725915cdd9737aa..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/numeral.js +++ /dev/null @@ -1,679 +0,0 @@ -/*! - * numeral.js - * version : 1.5.3 - * author : Adam Draper - * license : MIT - * http://adamwdraper.github.com/Numeral-js/ - */ - -(function () { - - /************************************ - Constants - ************************************/ - - var numeral, - VERSION = '1.5.3', - // internal storage for language config files - languages = {}, - currentLanguage = 'en', - zeroFormat = null, - defaultFormat = '0,0', - // check for nodeJS - hasModule = (typeof module !== 'undefined' && module.exports); - - - /************************************ - Constructors - ************************************/ - - - // Numeral prototype object - function Numeral (number) { - this._value = number; - } - - /** - * Implementation of toFixed() that treats floats more like decimals - * - * Fixes binary rounding issues (eg. (0.615).toFixed(2) === '0.61') that present - * problems for accounting- and finance-related software. - */ - function toFixed (value, precision, roundingFunction, optionals) { - var power = Math.pow(10, precision), - optionalsRegExp, - output; - - //roundingFunction = (roundingFunction !== undefined ? roundingFunction : Math.round); - // Multiply up by precision, round accurately, then divide and use native toFixed(): - output = (roundingFunction(value * power) / power).toFixed(precision); - - if (optionals) { - optionalsRegExp = new RegExp('0{1,' + optionals + '}$'); - output = output.replace(optionalsRegExp, ''); - } - - return output; - } - - /************************************ - Formatting - ************************************/ - - // determine what type of formatting we need to do - function formatNumeral (n, format, roundingFunction) { - var output; - - // figure out what kind of format we are dealing with - if (format.indexOf('$') > -1) { // currency!!!!! - output = formatCurrency(n, format, roundingFunction); - } else if (format.indexOf('%') > -1) { // percentage - output = formatPercentage(n, format, roundingFunction); - } else if (format.indexOf(':') > -1) { // time - output = formatTime(n, format); - } else { // plain ol' numbers or bytes - output = formatNumber(n._value, format, roundingFunction); - } - - // return string - return output; - } - - // revert to number - function unformatNumeral (n, string) { - var stringOriginal = string, - thousandRegExp, - millionRegExp, - billionRegExp, - trillionRegExp, - suffixes = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], - bytesMultiplier = false, - power; - - if (string.indexOf(':') > -1) { - n._value = unformatTime(string); - } else { - if (string === zeroFormat) { - n._value = 0; - } else { - if (languages[currentLanguage].delimiters.decimal !== '.') { - string = string.replace(/\./g,'').replace(languages[currentLanguage].delimiters.decimal, '.'); - } - - // see if abbreviations are there so that we can multiply to the correct number - thousandRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.thousand + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'); - millionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.million + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'); - billionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.billion + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'); - trillionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.trillion + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'); - - // see if bytes are there so that we can multiply to the correct number - for (power = 0; power <= suffixes.length; power++) { - bytesMultiplier = (string.indexOf(suffixes[power]) > -1) ? Math.pow(1024, power + 1) : false; - - if (bytesMultiplier) { - break; - } - } - - // do some math to create our number - n._value = ((bytesMultiplier) ? bytesMultiplier : 1) * ((stringOriginal.match(thousandRegExp)) ? Math.pow(10, 3) : 1) * ((stringOriginal.match(millionRegExp)) ? Math.pow(10, 6) : 1) * ((stringOriginal.match(billionRegExp)) ? Math.pow(10, 9) : 1) * ((stringOriginal.match(trillionRegExp)) ? Math.pow(10, 12) : 1) * ((string.indexOf('%') > -1) ? 0.01 : 1) * (((string.split('-').length + Math.min(string.split('(').length-1, string.split(')').length-1)) % 2)? 1: -1) * Number(string.replace(/[^0-9\.]+/g, '')); - - // round if we are talking about bytes - n._value = (bytesMultiplier) ? Math.ceil(n._value) : n._value; - } - } - return n._value; - } - - function formatCurrency (n, format, roundingFunction) { - var symbolIndex = format.indexOf('$'), - openParenIndex = format.indexOf('('), - minusSignIndex = format.indexOf('-'), - space = '', - spliceIndex, - output; - - // check for space before or after currency - if (format.indexOf(' $') > -1) { - space = ' '; - format = format.replace(' $', ''); - } else if (format.indexOf('$ ') > -1) { - space = ' '; - format = format.replace('$ ', ''); - } else { - format = format.replace('$', ''); - } - - // format the number - output = formatNumber(n._value, format, roundingFunction); - - // position the symbol - if (symbolIndex <= 1) { - if (output.indexOf('(') > -1 || output.indexOf('-') > -1) { - output = output.split(''); - spliceIndex = 1; - if (symbolIndex < openParenIndex || symbolIndex < minusSignIndex){ - // the symbol appears before the "(" or "-" - spliceIndex = 0; - } - output.splice(spliceIndex, 0, languages[currentLanguage].currency.symbol + space); - output = output.join(''); - } else { - output = languages[currentLanguage].currency.symbol + space + output; - } - } else { - if (output.indexOf(')') > -1) { - output = output.split(''); - output.splice(-1, 0, space + languages[currentLanguage].currency.symbol); - output = output.join(''); - } else { - output = output + space + languages[currentLanguage].currency.symbol; - } - } - - return output; - } - - function formatPercentage (n, format, roundingFunction) { - var space = '', - output, - value = n._value * 100; - - // check for space before % - if (format.indexOf(' %') > -1) { - space = ' '; - format = format.replace(' %', ''); - } else { - format = format.replace('%', ''); - } - - output = formatNumber(value, format, roundingFunction); - - if (output.indexOf(')') > -1 ) { - output = output.split(''); - output.splice(-1, 0, space + '%'); - output = output.join(''); - } else { - output = output + space + '%'; - } - - return output; - } - - function formatTime (n) { - var hours = Math.floor(n._value/60/60), - minutes = Math.floor((n._value - (hours * 60 * 60))/60), - seconds = Math.round(n._value - (hours * 60 * 60) - (minutes * 60)); - return hours + ':' + ((minutes < 10) ? '0' + minutes : minutes) + ':' + ((seconds < 10) ? '0' + seconds : seconds); - } - - function unformatTime (string) { - var timeArray = string.split(':'), - seconds = 0; - // turn hours and minutes into seconds and add them all up - if (timeArray.length === 3) { - // hours - seconds = seconds + (Number(timeArray[0]) * 60 * 60); - // minutes - seconds = seconds + (Number(timeArray[1]) * 60); - // seconds - seconds = seconds + Number(timeArray[2]); - } else if (timeArray.length === 2) { - // minutes - seconds = seconds + (Number(timeArray[0]) * 60); - // seconds - seconds = seconds + Number(timeArray[1]); - } - return Number(seconds); - } - - function formatNumber (value, format, roundingFunction) { - var negP = false, - signed = false, - optDec = false, - abbr = '', - abbrK = false, // force abbreviation to thousands - abbrM = false, // force abbreviation to millions - abbrB = false, // force abbreviation to billions - abbrT = false, // force abbreviation to trillions - abbrForce = false, // force abbreviation - bytes = '', - ord = '', - abs = Math.abs(value), - suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], - min, - max, - power, - w, - precision, - thousands, - d = '', - neg = false; - - // check if number is zero and a custom zero format has been set - if (value === 0 && zeroFormat !== null) { - return zeroFormat; - } else { - // see if we should use parentheses for negative number or if we should prefix with a sign - // if both are present we default to parentheses - if (format.indexOf('(') > -1) { - negP = true; - format = format.slice(1, -1); - } else if (format.indexOf('+') > -1) { - signed = true; - format = format.replace(/\+/g, ''); - } - - // see if abbreviation is wanted - if (format.indexOf('a') > -1) { - // check if abbreviation is specified - abbrK = format.indexOf('aK') >= 0; - abbrM = format.indexOf('aM') >= 0; - abbrB = format.indexOf('aB') >= 0; - abbrT = format.indexOf('aT') >= 0; - abbrForce = abbrK || abbrM || abbrB || abbrT; - - // check for space before abbreviation - if (format.indexOf(' a') > -1) { - abbr = ' '; - format = format.replace(' a', ''); - } else { - format = format.replace('a', ''); - } - - if (abs >= Math.pow(10, 12) && !abbrForce || abbrT) { - // trillion - abbr = abbr + languages[currentLanguage].abbreviations.trillion; - value = value / Math.pow(10, 12); - } else if (abs < Math.pow(10, 12) && abs >= Math.pow(10, 9) && !abbrForce || abbrB) { - // billion - abbr = abbr + languages[currentLanguage].abbreviations.billion; - value = value / Math.pow(10, 9); - } else if (abs < Math.pow(10, 9) && abs >= Math.pow(10, 6) && !abbrForce || abbrM) { - // million - abbr = abbr + languages[currentLanguage].abbreviations.million; - value = value / Math.pow(10, 6); - } else if (abs < Math.pow(10, 6) && abs >= Math.pow(10, 3) && !abbrForce || abbrK) { - // thousand - abbr = abbr + languages[currentLanguage].abbreviations.thousand; - value = value / Math.pow(10, 3); - } - } - - // see if we are formatting bytes - if (format.indexOf('b') > -1) { - // check for space before - if (format.indexOf(' b') > -1) { - bytes = ' '; - format = format.replace(' b', ''); - } else { - format = format.replace('b', ''); - } - - for (power = 0; power <= suffixes.length; power++) { - min = Math.pow(1024, power); - max = Math.pow(1024, power+1); - - if (value >= min && value < max) { - bytes = bytes + suffixes[power]; - if (min > 0) { - value = value / min; - } - break; - } - } - } - - // see if ordinal is wanted - if (format.indexOf('o') > -1) { - // check for space before - if (format.indexOf(' o') > -1) { - ord = ' '; - format = format.replace(' o', ''); - } else { - format = format.replace('o', ''); - } - - ord = ord + languages[currentLanguage].ordinal(value); - } - - if (format.indexOf('[.]') > -1) { - optDec = true; - format = format.replace('[.]', '.'); - } - - w = value.toString().split('.')[0]; - precision = format.split('.')[1]; - thousands = format.indexOf(','); - - if (precision) { - if (precision.indexOf('[') > -1) { - precision = precision.replace(']', ''); - precision = precision.split('['); - d = toFixed(value, (precision[0].length + precision[1].length), roundingFunction, precision[1].length); - } else { - d = toFixed(value, precision.length, roundingFunction); - } - - w = d.split('.')[0]; - - if (d.split('.')[1].length) { - d = languages[currentLanguage].delimiters.decimal + d.split('.')[1]; - } else { - d = ''; - } - - if (optDec && Number(d.slice(1)) === 0) { - d = ''; - } - } else { - w = toFixed(value, null, roundingFunction); - } - - // format number - if (w.indexOf('-') > -1) { - w = w.slice(1); - neg = true; - } - - if (thousands > -1) { - w = w.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + languages[currentLanguage].delimiters.thousands); - } - - if (format.indexOf('.') === 0) { - w = ''; - } - - return ((negP && neg) ? '(' : '') + ((!negP && neg) ? '-' : '') + ((!neg && signed) ? '+' : '') + w + d + ((ord) ? ord : '') + ((abbr) ? abbr : '') + ((bytes) ? bytes : '') + ((negP && neg) ? ')' : ''); - } - } - - /************************************ - Top Level Functions - ************************************/ - - numeral = function (input) { - if (numeral.isNumeral(input)) { - input = input.value(); - } else if (input === 0 || typeof input === 'undefined') { - input = 0; - } else if (!Number(input)) { - input = numeral.fn.unformat(input); - } - - return new Numeral(Number(input)); - }; - - // version number - numeral.version = VERSION; - - // compare numeral object - numeral.isNumeral = function (obj) { - return obj instanceof Numeral; - }; - - // This function will load languages and then set the global language. If - // no arguments are passed in, it will simply return the current global - // language key. - numeral.language = function (key, values) { - if (!key) { - return currentLanguage; - } - - if (key && !values) { - if(!languages[key]) { - throw new Error('Unknown language : ' + key); - } - currentLanguage = key; - } - - if (values || !languages[key]) { - loadLanguage(key, values); - } - - return numeral; - }; - - // This function provides access to the loaded language data. If - // no arguments are passed in, it will simply return the current - // global language object. - numeral.languageData = function (key) { - if (!key) { - return languages[currentLanguage]; - } - - if (!languages[key]) { - throw new Error('Unknown language : ' + key); - } - - return languages[key]; - }; - - numeral.language('en', { - delimiters: { - thousands: ',', - decimal: '.' - }, - abbreviations: { - thousand: 'k', - million: 'm', - billion: 'b', - trillion: 't' - }, - ordinal: function (number) { - var b = number % 10; - return (~~ (number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : - (b === 3) ? 'rd' : 'th'; - }, - currency: { - symbol: '$' - } - }); - - numeral.zeroFormat = function (format) { - zeroFormat = typeof(format) === 'string' ? format : null; - }; - - numeral.defaultFormat = function (format) { - defaultFormat = typeof(format) === 'string' ? format : '0.0'; - }; - - /************************************ - Helpers - ************************************/ - - function loadLanguage(key, values) { - languages[key] = values; - } - - /************************************ - Floating-point helpers - ************************************/ - - // The floating-point helper functions and implementation - // borrows heavily from sinful.js: http://guipn.github.io/sinful.js/ - - /** - * Array.prototype.reduce for browsers that don't support it - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Compatibility - */ - if ('function' !== typeof Array.prototype.reduce) { - Array.prototype.reduce = function (callback, opt_initialValue) { - 'use strict'; - - if (null === this || 'undefined' === typeof this) { - // At the moment all modern browsers, that support strict mode, have - // native implementation of Array.prototype.reduce. For instance, IE8 - // does not support strict mode, so this check is actually useless. - throw new TypeError('Array.prototype.reduce called on null or undefined'); - } - - if ('function' !== typeof callback) { - throw new TypeError(callback + ' is not a function'); - } - - var index, - value, - length = this.length >>> 0, - isValueSet = false; - - if (1 < arguments.length) { - value = opt_initialValue; - isValueSet = true; - } - - for (index = 0; length > index; ++index) { - if (this.hasOwnProperty(index)) { - if (isValueSet) { - value = callback(value, this[index], index, this); - } else { - value = this[index]; - isValueSet = true; - } - } - } - - if (!isValueSet) { - throw new TypeError('Reduce of empty array with no initial value'); - } - - return value; - }; - } - - - /** - * Computes the multiplier necessary to make x >= 1, - * effectively eliminating miscalculations caused by - * finite precision. - */ - function multiplier(x) { - var parts = x.toString().split('.'); - if (parts.length < 2) { - return 1; - } - return Math.pow(10, parts[1].length); - } - - /** - * Given a variable number of arguments, returns the maximum - * multiplier that must be used to normalize an operation involving - * all of them. - */ - function correctionFactor() { - var args = Array.prototype.slice.call(arguments); - return args.reduce(function (prev, next) { - var mp = multiplier(prev), - mn = multiplier(next); - return mp > mn ? mp : mn; - }, -Infinity); - } - - - /************************************ - Numeral Prototype - ************************************/ - - - numeral.fn = Numeral.prototype = { - - clone : function () { - return numeral(this); - }, - - format : function (inputString, roundingFunction) { - return formatNumeral(this, - inputString ? inputString : defaultFormat, - (roundingFunction !== undefined) ? roundingFunction : Math.round - ); - }, - - unformat : function (inputString) { - if (Object.prototype.toString.call(inputString) === '[object Number]') { - return inputString; - } - return unformatNumeral(this, inputString ? inputString : defaultFormat); - }, - - value : function () { - return this._value; - }, - - valueOf : function () { - return this._value; - }, - - set : function (value) { - this._value = Number(value); - return this; - }, - - add : function (value) { - var corrFactor = correctionFactor.call(null, this._value, value); - function cback(accum, curr, currI, O) { - return accum + corrFactor * curr; - } - this._value = [this._value, value].reduce(cback, 0) / corrFactor; - return this; - }, - - subtract : function (value) { - var corrFactor = correctionFactor.call(null, this._value, value); - function cback(accum, curr, currI, O) { - return accum - corrFactor * curr; - } - this._value = [value].reduce(cback, this._value * corrFactor) / corrFactor; - return this; - }, - - multiply : function (value) { - function cback(accum, curr, currI, O) { - var corrFactor = correctionFactor(accum, curr); - return (accum * corrFactor) * (curr * corrFactor) / - (corrFactor * corrFactor); - } - this._value = [this._value, value].reduce(cback, 1); - return this; - }, - - divide : function (value) { - function cback(accum, curr, currI, O) { - var corrFactor = correctionFactor(accum, curr); - return (accum * corrFactor) / (curr * corrFactor); - } - this._value = [this._value, value].reduce(cback); - return this; - }, - - difference : function (value) { - return Math.abs(numeral(this._value).subtract(value).value()); - } - - }; - - /************************************ - Exposing Numeral - ************************************/ - - // CommonJS module is defined - if (hasModule) { - module.exports = numeral; - } - - /*global ender:false */ - if (typeof ender === 'undefined') { - // here, `this` means `window` in the browser, or `global` on the server - // add `numeral` as a global object via a string identifier, - // for Closure Compiler 'advanced' mode - this['numeral'] = numeral; - } - - /*global define:false */ - if (typeof define === 'function' && define.amd) { - define([], function () { - return numeral; - }); - } -}).call(this); diff --git a/assets/www/dist/dist_js/app/vendor/numeral.nl.js b/assets/www/dist/dist_js/app/vendor/numeral.nl.js deleted file mode 100644 index f1f704a226a8ee16c212f063d347fde976f9d8ea..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/numeral.nl.js +++ /dev/null @@ -1,27 +0,0 @@ -//! numeral.js locale configuration -//! locale : dutch (nl) -//! author : RA van Hagen : https://github.com/RavanH - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../numeral')) : - typeof define === 'function' && define.amd ? define(['numeral'], factory) : - factory(global.numeral) -}(this, function (numeral) { 'use strict'; - - numeral.language('nl', { - "delimiters": { - "thousands": " ", - "decimal": "," - }, - "abbreviations": { - "thousand": "<small>x10<sup>3</sup></small>", - "million": "<small>x10<sup>6</sup></small>", - "billion": "<small>x10<sup>9</sup></small>", - "trillion": "<small>x10<sup>12</sup></small>" - }, - "ordinal": "<sup>e</sup>", - "currency": { - "symbol": "X" - } - }); -})); diff --git a/assets/www/dist/dist_js/app/vendor/qrcode.min.js b/assets/www/dist/dist_js/app/vendor/qrcode.min.js deleted file mode 100644 index 993e88f396640f881b69f98db7a4d17401ef83ca..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/qrcode.min.js +++ /dev/null @@ -1 +0,0 @@ -var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c<a.length&&0==a[c];)c++;this.num=new Array(a.length-c+b);for(var d=0;d<a.length-c;d++)this.num[d]=a[d+c]}function j(a,b){this.totalCount=a,this.dataCount=b}function k(){this.buffer=[],this.length=0}function m(){return"undefined"!=typeof CanvasRenderingContext2D}function n(){var a=!1,b=navigator.userAgent;return/android/i.test(b)&&(a=!0,aMat=b.toString().match(/android ([0-9]\.[0-9])/i),aMat&&aMat[1]&&(a=parseFloat(aMat[1]))),a}function r(a,b){for(var c=1,e=s(a),f=0,g=l.length;g>=f;f++){var h=0;switch(b){case d.L:h=l[f][0];break;case d.M:h=l[f][1];break;case d.Q:h=l[f][2];break;case d.H:h=l[f][3]}if(h>=e)break;c++}if(c>l.length)throw new Error("Too long data");return c}function s(a){var b=encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return b.length+(b.length!=a?3:0)}a.prototype={getLength:function(){return this.parsedData.length},write:function(a){for(var b=0,c=this.parsedData.length;c>b;b++)a.put(this.parsedData[b],8)}},b.prototype={addData:function(b){var c=new a(b);this.dataList.push(c),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d<this.moduleCount;d++){this.modules[d]=new Array(this.moduleCount);for(var e=0;e<this.moduleCount;e++)this.modules[d][e]=null}this.setupPositionProbePattern(0,0),this.setupPositionProbePattern(this.moduleCount-7,0),this.setupPositionProbePattern(0,this.moduleCount-7),this.setupPositionAdjustPattern(),this.setupTimingPattern(),this.setupTypeInfo(a,c),this.typeNumber>=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=f.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;f<this.modules.length;f++)for(var g=f*e,h=0;h<this.modules[f].length;h++){var i=h*e,j=this.modules[f][h];j&&(d.beginFill(0,100),d.moveTo(i,g),d.lineTo(i+e,g),d.lineTo(i+e,g+e),d.lineTo(i,g+e),d.endFill())}return d},setupTimingPattern:function(){for(var a=8;a<this.moduleCount-8;a++)null==this.modules[a][6]&&(this.modules[a][6]=0==a%2);for(var b=8;b<this.moduleCount-8;b++)null==this.modules[6][b]&&(this.modules[6][b]=0==b%2)},setupPositionAdjustPattern:function(){for(var a=f.getPatternPosition(this.typeNumber),b=0;b<a.length;b++)for(var c=0;c<a.length;c++){var d=a[b],e=a[c];if(null==this.modules[d][e])for(var g=-2;2>=g;g++)for(var h=-2;2>=h;h++)this.modules[d+g][e+h]=-2==g||2==g||-2==h||2==h||0==g&&0==h?!0:!1}},setupTypeNumber:function(a){for(var b=f.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=f.getBCHTypeInfo(c),e=0;15>e;e++){var g=!a&&1==(1&d>>e);6>e?this.modules[e][8]=g:8>e?this.modules[e+1][8]=g:this.modules[this.moduleCount-15+e][8]=g}for(var e=0;15>e;e++){var g=!a&&1==(1&d>>e);8>e?this.modules[8][this.moduleCount-e-1]=g:9>e?this.modules[8][15-e-1+1]=g:this.modules[8][15-e-1]=g}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,g=0,h=this.moduleCount-1;h>0;h-=2)for(6==h&&h--;;){for(var i=0;2>i;i++)if(null==this.modules[d][h-i]){var j=!1;g<a.length&&(j=1==(1&a[g]>>>e));var k=f.getMask(b,d,h-i);k&&(j=!j),this.modules[d][h-i]=j,e--,-1==e&&(g++,e=7)}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=j.getRSBlocks(a,c),g=new k,h=0;h<d.length;h++){var i=d[h];g.put(i.mode,4),g.put(i.getLength(),f.getLengthInBits(i.mode,a)),i.write(g)}for(var l=0,h=0;h<e.length;h++)l+=e[h].dataCount;if(g.getLengthInBits()>8*l)throw new Error("code length overflow. ("+g.getLengthInBits()+">"+8*l+")");for(g.getLengthInBits()+4<=8*l&&g.put(0,4);0!=g.getLengthInBits()%8;)g.putBit(!1);for(;;){if(g.getLengthInBits()>=8*l)break;if(g.put(b.PAD0,8),g.getLengthInBits()>=8*l)break;g.put(b.PAD1,8)}return b.createBytes(g,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,g=new Array(b.length),h=new Array(b.length),j=0;j<b.length;j++){var k=b[j].dataCount,l=b[j].totalCount-k;d=Math.max(d,k),e=Math.max(e,l),g[j]=new Array(k);for(var m=0;m<g[j].length;m++)g[j][m]=255&a.buffer[m+c];c+=k;var n=f.getErrorCorrectPolynomial(l),o=new i(g[j],n.getLength()-1),p=o.mod(n);h[j]=new Array(n.getLength()-1);for(var m=0;m<h[j].length;m++){var q=m+p.getLength()-h[j].length;h[j][m]=q>=0?p.get(q):0}}for(var r=0,m=0;m<b.length;m++)r+=b[m].totalCount;for(var s=new Array(r),t=0,m=0;d>m;m++)for(var j=0;j<b.length;j++)m<g[j].length&&(s[t++]=g[j][m]);for(var m=0;e>m;m++)for(var j=0;j<b.length;j++)m<h[j].length&&(s[t++]=h[j][m]);return s};for(var c={MODE_NUMBER:1,MODE_ALPHA_NUM:2,MODE_8BIT_BYTE:4,MODE_KANJI:8},d={L:1,M:0,Q:3,H:2},e={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7},f={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:1335,G18:7973,G15_MASK:21522,getBCHTypeInfo:function(a){for(var b=a<<10;f.getBCHDigit(b)-f.getBCHDigit(f.G15)>=0;)b^=f.G15<<f.getBCHDigit(b)-f.getBCHDigit(f.G15);return(a<<10|b)^f.G15_MASK},getBCHTypeNumber:function(a){for(var b=a<<12;f.getBCHDigit(b)-f.getBCHDigit(f.G18)>=0;)b^=f.G18<<f.getBCHDigit(b)-f.getBCHDigit(f.G18);return a<<12|b},getBCHDigit:function(a){for(var b=0;0!=a;)b++,a>>>=1;return b},getPatternPosition:function(a){return f.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case e.PATTERN000:return 0==(b+c)%2;case e.PATTERN001:return 0==b%2;case e.PATTERN010:return 0==c%3;case e.PATTERN011:return 0==(b+c)%3;case e.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case e.PATTERN101:return 0==b*c%2+b*c%3;case e.PATTERN110:return 0==(b*c%2+b*c%3)%2;case e.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new i([1],0),c=0;a>c;c++)b=b.multiply(new i([1,g.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||d+h>=b))for(var i=-1;1>=i;i++)0>e+i||e+i>=b||(0!=h||0!=i)&&g==a.isDark(d+h,e+i)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b-1>d;d++)for(var e=0;b-1>e;e++){var j=0;a.isDark(d,e)&&j++,a.isDark(d+1,e)&&j++,a.isDark(d,e+1)&&j++,a.isDark(d+1,e+1)&&j++,(0==j||4==j)&&(c+=3)}for(var d=0;b>d;d++)for(var e=0;b-6>e;e++)a.isDark(d,e)&&!a.isDark(d,e+1)&&a.isDark(d,e+2)&&a.isDark(d,e+3)&&a.isDark(d,e+4)&&!a.isDark(d,e+5)&&a.isDark(d,e+6)&&(c+=40);for(var e=0;b>e;e++)for(var d=0;b-6>d;d++)a.isDark(d,e)&&!a.isDark(d+1,e)&&a.isDark(d+2,e)&&a.isDark(d+3,e)&&a.isDark(d+4,e)&&!a.isDark(d+5,e)&&a.isDark(d+6,e)&&(c+=40);for(var k=0,e=0;b>e;e++)for(var d=0;b>d;d++)a.isDark(d,e)&&k++;var l=Math.abs(100*k/b/b-50)/5;return c+=10*l}},g={glog:function(a){if(1>a)throw new Error("glog("+a+")");return g.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return g.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},h=0;8>h;h++)g.EXP_TABLE[h]=1<<h;for(var h=8;256>h;h++)g.EXP_TABLE[h]=g.EXP_TABLE[h-4]^g.EXP_TABLE[h-5]^g.EXP_TABLE[h-6]^g.EXP_TABLE[h-8];for(var h=0;255>h;h++)g.LOG_TABLE[g.EXP_TABLE[h]]=h;i.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;c<this.getLength();c++)for(var d=0;d<a.getLength();d++)b[c+d]^=g.gexp(g.glog(this.get(c))+g.glog(a.get(d)));return new i(b,0)},mod:function(a){if(this.getLength()-a.getLength()<0)return this;for(var b=g.glog(this.get(0))-g.glog(a.get(0)),c=new Array(this.getLength()),d=0;d<this.getLength();d++)c[d]=this.get(d);for(var d=0;d<a.getLength();d++)c[d]^=g.gexp(g.glog(a.get(d))+b);return new i(c,0).mod(a)}},j.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]],j.getRSBlocks=function(a,b){var c=j.getRsBlockTable(a,b);if(void 0==c)throw new Error("bad rs block @ typeNumber:"+a+"/errorCorrectLevel:"+b);for(var d=c.length/3,e=[],f=0;d>f;f++)for(var g=c[3*f+0],h=c[3*f+1],i=c[3*f+2],k=0;g>k;k++)e.push(new j(h,i));return e},j.getRsBlockTable=function(a,b){switch(b){case d.L:return j.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return j.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return j.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return j.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},k.prototype={get:function(a){var b=Math.floor(a/8);return 1==(1&this.buffer[b]>>>7-a%8)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(1&a>>>b-c-1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}};var l=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]],o=function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){function g(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)b.hasOwnProperty(d)&&c.setAttribute(d,b[d]);return c}var b=this._htOption,c=this._el,d=a.getModuleCount();Math.floor(b.width/d),Math.floor(b.height/d),this.clear();var h=g("svg",{viewBox:"0 0 "+String(d)+" "+String(d),width:"100%",height:"100%",fill:b.colorLight});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),c.appendChild(h),h.appendChild(g("rect",{fill:b.colorDark,width:"1",height:"1",id:"template"}));for(var i=0;d>i;i++)for(var j=0;d>j;j++)if(a.isDark(i,j)){var k=g("use",{x:String(i),y:String(j)});k.setAttributeNS("http://www.w3.org/1999/xlink","href","#template"),h.appendChild(k)}},a.prototype.clear=function(){for(;this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild)},a}(),p="svg"===document.documentElement.tagName.toLowerCase(),q=p?o:m()?function(){function a(){this._elImage.src=this._elCanvas.toDataURL("image/png"),this._elImage.style.display="block",this._elCanvas.style.display="none"}function d(a,b){var c=this;if(c._fFail=b,c._fSuccess=a,null===c._bSupportDataURI){var d=document.createElement("img"),e=function(){c._bSupportDataURI=!1,c._fFail&&_fFail.call(c)},f=function(){c._bSupportDataURI=!0,c._fSuccess&&c._fSuccess.call(c)};return d.onabort=e,d.onerror=e,d.onload=f,d.src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",void 0}c._bSupportDataURI===!0&&c._fSuccess?c._fSuccess.call(c):c._bSupportDataURI===!1&&c._fFail&&c._fFail.call(c)}if(this._android&&this._android<=2.1){var b=1/window.devicePixelRatio,c=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(a,d,e,f,g,h,i,j){if("nodeName"in a&&/img/i.test(a.nodeName))for(var l=arguments.length-1;l>=1;l--)arguments[l]=arguments[l]*b;else"undefined"==typeof j&&(arguments[1]*=b,arguments[2]*=b,arguments[3]*=b,arguments[4]*=b);c.apply(this,arguments)}}var e=function(a,b){this._bIsPainted=!1,this._android=n(),this._htOption=b,this._elCanvas=document.createElement("canvas"),this._elCanvas.width=b.width,this._elCanvas.height=b.height,a.appendChild(this._elCanvas),this._el=a,this._oContext=this._elCanvas.getContext("2d"),this._bIsPainted=!1,this._elImage=document.createElement("img"),this._elImage.style.display="none",this._el.appendChild(this._elImage),this._bSupportDataURI=null};return e.prototype.draw=function(a){var b=this._elImage,c=this._oContext,d=this._htOption,e=a.getModuleCount(),f=d.width/e,g=d.height/e,h=Math.round(f),i=Math.round(g);b.style.display="none",this.clear();for(var j=0;e>j;j++)for(var k=0;e>k;k++){var l=a.isDark(j,k),m=k*f,n=j*g;c.strokeStyle=l?d.colorDark:d.colorLight,c.lineWidth=1,c.fillStyle=l?d.colorDark:d.colorLight,c.fillRect(m,n,f,g),c.strokeRect(Math.floor(m)+.5,Math.floor(n)+.5,h,i),c.strokeRect(Math.ceil(m)-.5,Math.ceil(n)-.5,h,i)}this._bIsPainted=!0},e.prototype.makeImage=function(){this._bIsPainted&&d.call(this,a)},e.prototype.isPainted=function(){return this._bIsPainted},e.prototype.clear=function(){this._oContext.clearRect(0,0,this._elCanvas.width,this._elCanvas.height),this._bIsPainted=!1},e.prototype.round=function(a){return a?Math.floor(1e3*a)/1e3:a},e}():function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){for(var b=this._htOption,c=this._el,d=a.getModuleCount(),e=Math.floor(b.width/d),f=Math.floor(b.height/d),g=['<table style="border:0;border-collapse:collapse;">'],h=0;d>h;h++){g.push("<tr>");for(var i=0;d>i;i++)g.push('<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:'+e+"px;height:"+f+"px;background-color:"+(a.isDark(h,i)?b.colorDark:b.colorLight)+';"></td>');g.push("</tr>")}g.push("</table>"),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}(); \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/vendor/scrypt-em.js b/assets/www/dist/dist_js/app/vendor/scrypt-em.js deleted file mode 100644 index a98182e62e3580bfa8dfe9ee91c6235720428067..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/scrypt-em.js +++ /dev/null @@ -1,10306 +0,0 @@ -/* - * #%L - * uCoinj :: UI Wicket - * %% - * Copyright (C) 2014 - 2016 EIS - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/gpl-3.0.html>. - * #L% - */ - - -var scrypt_module_factory = (function (requested_total_memory) { - var Module = {TOTAL_MEMORY: (requested_total_memory || 33554432)}; - var scrypt_raw = Module; -function g(a) { - throw a; -} -var k = void 0, l = !0, m = null, p = !1; -function aa() { - return function() { - } -} -var q, s; -s || (s = eval("(function() { try { return Module || {} } catch(e) { return {} } })()")); -var ba = {}, t; -for(t in s) { - s.hasOwnProperty(t) && (ba[t] = s[t]) -} -var ca = "object" === typeof process && "function" === typeof require, da = "object" === typeof window, ea = "function" === typeof importScripts, fa = !da && !ca && !ea; -if(ca) { - s.print = function(a) { - process.stdout.write(a + "\n") - }; - s.printErr = function(a) { - process.stderr.write(a + "\n") - }; - var ga = require("fs"), ha = require("path"); - s.read = function(a, b) { - var a = ha.normalize(a), c = ga.readFileSync(a); - !c && a != ha.resolve(a) && (a = path.join(__dirname, "..", "src", a), c = ga.readFileSync(a)); - c && !b && (c = c.toString()); - return c - }; - s.readBinary = function(a) { - return s.read(a, l) - }; - s.load = function(a) { - ia(read(a)) - }; - s.arguments = process.argv.slice(2); - module.ee = s -}else { - fa ? (s.print = print, "undefined" != typeof printErr && (s.printErr = printErr), s.read = read, s.readBinary = function(a) { - return read(a, "binary") - }, "undefined" != typeof scriptArgs ? s.arguments = scriptArgs : "undefined" != typeof arguments && (s.arguments = arguments), this.Module = s) : da || ea ? (s.read = function(a) { - var b = new XMLHttpRequest; - b.open("GET", a, p); - b.send(m); - return b.responseText - }, "undefined" != typeof arguments && (s.arguments = arguments), da ? (s.print = function(a) { - console.log(a) - }, s.printErr = function(a) { - console.log(a) - }, this.Module = s) : ea && (s.print = aa(), s.load = importScripts)) : g("Unknown runtime environment. Where are we?") -} -function ia(a) { - eval.call(m, a) -} -"undefined" == !s.load && s.read && (s.load = function(a) { - ia(s.read(a)) -}); -s.print || (s.print = aa()); -s.printErr || (s.printErr = s.print); -s.arguments || (s.arguments = []); -s.print = s.print; -s.P = s.printErr; -s.preRun = []; -s.postRun = []; -for(t in ba) { - ba.hasOwnProperty(t) && (s[t] = ba[t]) -} -function ja() { - return u -} -function ka(a) { - u = a -} -function la(a) { - if(1 == ma) { - return 1 - } - var b = {"%i1":1, "%i8":1, "%i16":2, "%i32":4, "%i64":8, "%float":4, "%double":8}["%" + a]; - b || ("*" == a.charAt(a.length - 1) ? b = ma : "i" == a[0] && (a = parseInt(a.substr(1)), w(0 == a % 8), b = a / 8)); - return b -} -function na(a, b, c) { - c && c.length ? (c.splice || (c = Array.prototype.slice.call(c)), c.splice(0, 0, b), s["dynCall_" + a].apply(m, c)) : s["dynCall_" + a].call(m, b) -} -var oa; -function pa() { - var a = [], b = 0; - this.oa = function(c) { - c &= 255; - b && (a.push(c), b--); - if(0 == a.length) { - if(128 > c) { - return String.fromCharCode(c) - } - a.push(c); - b = 191 < c && 224 > c ? 1 : 2; - return"" - } - if(0 < b) { - return"" - } - var c = a[0], d = a[1], e = a[2], c = 191 < c && 224 > c ? String.fromCharCode((c & 31) << 6 | d & 63) : String.fromCharCode((c & 15) << 12 | (d & 63) << 6 | e & 63); - a.length = 0; - return c - }; - this.yb = function(a) { - for(var a = unescape(encodeURIComponent(a)), b = [], e = 0;e < a.length;e++) { - b.push(a.charCodeAt(e)) - } - return b - } -} -function qa(a) { - var b = u; - u = u + a | 0; - u = u + 7 >> 3 << 3; - return b -} -function ra(a) { - var b = sa; - sa = sa + a | 0; - sa = sa + 7 >> 3 << 3; - return b -} -function ua(a) { - var b = z; - z = z + a | 0; - z = z + 7 >> 3 << 3; - z >= va && wa("Cannot enlarge memory arrays in asm.js. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, or (2) set Module.TOTAL_MEMORY before the program runs."); - return b -} -function xa(a, b) { - return Math.ceil(a / (b ? b : 8)) * (b ? b : 8) -} -var ma = 4, ya = {}, za = p, Aa; -function w(a, b) { - a || wa("Assertion failed: " + b) -} -s.ccall = function(a, b, c, d) { - return Ba(Ca(a), b, c, d) -}; -function Ca(a) { - try { - var b = s["_" + a]; - b || (b = eval("_" + a)) - }catch(c) { - } - w(b, "Cannot call unknown function " + a + " (perhaps LLVM optimizations or closure removed it?)"); - return b -} -function Ba(a, b, c, d) { - function e(a, b) { - if("string" == b) { - if(a === m || a === k || 0 === a) { - return 0 - } - f || (f = ja()); - var c = qa(a.length + 1); - Da(a, c); - return c - } - return"array" == b ? (f || (f = ja()), c = qa(a.length), Ea(a, c), c) : a - } - var f = 0, h = 0, d = d ? d.map(function(a) { - return e(a, c[h++]) - }) : []; - a = a.apply(m, d); - "string" == b ? b = Fa(a) : (w("array" != b), b = a); - f && ka(f); - return b -} -s.cwrap = function(a, b, c) { - var d = Ca(a); - return function() { - return Ba(d, b, c, Array.prototype.slice.call(arguments)) - } -}; -function Ga(a, b, c) { - c = c || "i8"; - "*" === c.charAt(c.length - 1) && (c = "i32"); - switch(c) { - case "i1": - A[a] = b; - break; - case "i8": - A[a] = b; - break; - case "i16": - Ha[a >> 1] = b; - break; - case "i32": - B[a >> 2] = b; - break; - case "i64": - Aa = [b >>> 0, (Math.min(+Math.floor(b / 4294967296), 4294967295) | 0) >>> 0]; - B[a >> 2] = Aa[0]; - B[a + 4 >> 2] = Aa[1]; - break; - case "float": - Ia[a >> 2] = b; - break; - case "double": - Ja[a >> 3] = b; - break; - default: - wa("invalid type for setValue: " + c) - } -} -s.setValue = Ga; -s.getValue = function(a, b) { - b = b || "i8"; - "*" === b.charAt(b.length - 1) && (b = "i32"); - switch(b) { - case "i1": - return A[a]; - case "i8": - return A[a]; - case "i16": - return Ha[a >> 1]; - case "i32": - return B[a >> 2]; - case "i64": - return B[a >> 2]; - case "float": - return Ia[a >> 2]; - case "double": - return Ja[a >> 3]; - default: - wa("invalid type for setValue: " + b) - } - return m -}; -var Ka = 0, La = 1, E = 2, Na = 4; -s.ALLOC_NORMAL = Ka; -s.ALLOC_STACK = La; -s.ALLOC_STATIC = E; -s.ALLOC_DYNAMIC = 3; -s.ALLOC_NONE = Na; -function F(a, b, c, d) { - var e, f; - "number" === typeof a ? (e = l, f = a) : (e = p, f = a.length); - var h = "string" === typeof b ? b : m, c = c == Na ? d : [Oa, qa, ra, ua][c === k ? E : c](Math.max(f, h ? 1 : b.length)); - if(e) { - d = c; - w(0 == (c & 3)); - for(a = c + (f & -4);d < a;d += 4) { - B[d >> 2] = 0 - } - for(a = c + f;d < a;) { - A[d++ | 0] = 0 - } - return c - } - if("i8" === h) { - return a.subarray || a.slice ? G.set(a, c) : G.set(new Uint8Array(a), c), c - } - for(var d = 0, i, j;d < f;) { - var n = a[d]; - "function" === typeof n && (n = ya.fe(n)); - e = h || b[d]; - 0 === e ? d++ : ("i64" == e && (e = "i32"), Ga(c + d, n, e), j !== e && (i = la(e), j = e), d += i) - } - return c -} -s.allocate = F; -function Fa(a, b) { - for(var c = p, d, e = 0;;) { - d = G[a + e | 0]; - if(128 <= d) { - c = l - }else { - if(0 == d && !b) { - break - } - } - e++; - if(b && e == b) { - break - } - } - b || (b = e); - var f = ""; - if(!c) { - for(;0 < b;) { - d = String.fromCharCode.apply(String, G.subarray(a, a + Math.min(b, 1024))), f = f ? f + d : d, a += 1024, b -= 1024 - } - return f - } - c = new pa; - for(e = 0;e < b;e++) { - d = G[a + e | 0], f += c.oa(d) - } - return f -} -s.Pointer_stringify = Fa; -var A, G, Ha, Pa, B, Qa, Ia, Ja, Ra = 0, sa = 0, Sa = 0, u = 0, Ta = 0, Ua = 0, z = 0, va = s.TOTAL_MEMORY || 33554432; -w(!!Int32Array && !!Float64Array && !!(new Int32Array(1)).subarray && !!(new Int32Array(1)).set, "Cannot fallback to non-typed array case: Code is too specialized"); -var I = new ArrayBuffer(va); -A = new Int8Array(I); -Ha = new Int16Array(I); -B = new Int32Array(I); -G = new Uint8Array(I); -Pa = new Uint16Array(I); -Qa = new Uint32Array(I); -Ia = new Float32Array(I); -Ja = new Float64Array(I); -B[0] = 255; -w(255 === G[0] && 0 === G[3], "Typed arrays 2 must be run on a little-endian system"); -s.HEAP = k; -s.HEAP8 = A; -s.HEAP16 = Ha; -s.HEAP32 = B; -s.HEAPU8 = G; -s.HEAPU16 = Pa; -s.HEAPU32 = Qa; -s.HEAPF32 = Ia; -s.HEAPF64 = Ja; -function Va(a) { - for(;0 < a.length;) { - var b = a.shift(); - if("function" == typeof b) { - b() - }else { - var c = b.V; - "number" === typeof c ? b.ha === k ? na("v", c) : na("vi", c, [b.ha]) : c(b.ha === k ? m : b.ha) - } - } -} -var Wa = [], Xa = [], Ya = [], Za = [], $a = [], ab = p; -function bb(a) { - Wa.unshift(a) -} -s.addOnPreRun = s.Vd = bb; -s.addOnInit = s.Sd = function(a) { - Xa.unshift(a) -}; -s.addOnPreMain = s.Ud = function(a) { - Ya.unshift(a) -}; -s.addOnExit = s.Rd = function(a) { - Za.unshift(a) -}; -function cb(a) { - $a.unshift(a) -} -s.addOnPostRun = s.Td = cb; -function J(a, b, c) { - a = (new pa).yb(a); - c && (a.length = c); - b || a.push(0); - return a -} -s.intArrayFromString = J; -s.intArrayToString = function(a) { - for(var b = [], c = 0;c < a.length;c++) { - var d = a[c]; - 255 < d && (d &= 255); - b.push(String.fromCharCode(d)) - } - return b.join("") -}; -function Da(a, b, c) { - a = J(a, c); - for(c = 0;c < a.length;) { - A[b + c | 0] = a[c], c += 1 - } -} -s.writeStringToMemory = Da; -function Ea(a, b) { - for(var c = 0;c < a.length;c++) { - A[b + c | 0] = a[c] - } -} -s.writeArrayToMemory = Ea; -function db(a, b) { - return 0 <= a ? a : 32 >= b ? 2 * Math.abs(1 << b - 1) + a : Math.pow(2, b) + a -} -function eb(a, b) { - if(0 >= a) { - return a - } - var c = 32 >= b ? Math.abs(1 << b - 1) : Math.pow(2, b - 1); - if(a >= c && (32 >= b || a > c)) { - a = -2 * c + a - } - return a -} -Math.imul || (Math.imul = function(a, b) { - var c = a & 65535, d = b & 65535; - return c * d + ((a >>> 16) * d + c * (b >>> 16) << 16) | 0 -}); -Math.ie = Math.imul; -var L = 0, fb = {}, gb = p, hb = m; -function ib(a) { - L++; - s.monitorRunDependencies && s.monitorRunDependencies(L); - a ? (w(!fb[a]), fb[a] = 1) : s.P("warning: run dependency added without ID") -} -s.addRunDependency = ib; -function jb(a) { - L--; - s.monitorRunDependencies && s.monitorRunDependencies(L); - a ? (w(fb[a]), delete fb[a]) : s.P("warning: run dependency removed without ID"); - 0 == L && (hb !== m && (clearInterval(hb), hb = m), !gb && kb && lb()) -} -s.removeRunDependency = jb; -s.preloadedImages = {}; -s.preloadedAudios = {}; -Ra = 8; -sa = Ra + 1312; -Xa.push({V:function() { - mb() -}}); -var nb, ob, pb; -nb = nb = F([0, 0, 0, 0, 0, 0, 0, 0], "i8", E); -ob = ob = F([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "i8", E); -pb = pb = F([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "i8", E); -F([111, 112, 116, 105, 111, 110, 32, 114, 101, 113, 117, 105, 114, 101, 115, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 115, 0, 0, 0, 0, 0, 0, 0, 111, 112, 116, 105, 111, 110, 32, 114, 101, 113, 117, 105, 114, 101, 115, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 64, 0, 0, 0, 0, 0, 0, 89, 64, 0, 0, 0, 0, 0, 136, 195, 64, 0, 0, 0, 0, 132, 215, 151, 65, 0, 128, 224, 55, 121, 195, 65, 67, -23, 110, 5, 181, 181, 184, 147, 70, 245, 249, 63, 233, 3, 79, 56, 77, 50, 29, 48, 249, 72, 119, 130, 90, 60, 191, 115, 127, 221, 79, 21, 117, 56, 3, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 111, 112, 116, 105, 111, 110, 32, 100, 111, 101, 115, 110, 39, 116, 32, 116, 97, 107, 101, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 46, 42, 115, 0, 117, 110, 107, -110, 111, 119, 110, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 115, 0, 0, 0, 0, 117, 110, 107, 110, 111, 119, 110, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 99, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 97, 109, 98, 105, 103, 117, 111, 117, 115, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 46, 42, 115, 0, 0, 0, 0, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 80, 79, 83, 73, 88, 76, 89, 95, 67, 79, 82, 82, 69, 67, 84, 0, 115, 116, 100, 58, 58, 98, 97, 100, 95, 97, 108, -108, 111, 99, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 37, 115, 10, 0, 0, 0, 0, 0, 37, 115, 10, 0, 0, 0, 0, 0, 105, 110, 32, 117, 115, 101, 32, 98, 121, 116, 101, 115, 32, 32, 32, 32, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, 0, 0, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 98, 97, 100, 95, 97, 114, 114, 97, 121, 95, 110, 101, 119, 95, 108, 101, 110, 103, 116, 104, 0, 0, 0, 0, 58, 32, 0, 0, 0, 0, 0, 0, 58, 32, 0, 0, 0, 0, 0, 0, 115, 121, 115, 116, 101, 109, 32, 98, 121, 116, 101, -115, 32, 32, 32, 32, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, 0, 0, 0, 0, 0, 0, 109, 97, 120, 32, 115, 121, 115, 116, 101, 109, 32, 98, 121, 116, 101, 115, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 2, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 2, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 116, 57, 101, 120, 99, 101, 112, 116, 105, 111, 110, 0, 0, 0, 0, 83, 116, 57, 98, 97, -100, 95, 97, 108, 108, 111, 99, 0, 0, 0, 0, 83, 116, 50, 48, 98, 97, 100, 95, 97, 114, 114, 97, 121, 95, 110, 101, 119, 95, 108, 101, 110, 103, 116, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 2, 0, 0, 0, 0, 0, 0, 120, 2, 0, 0, 168, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 2, 0, 0, 176, 2, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], -"i8", Na, 8); -var qb = xa(F(12, "i8", E), 8); -w(0 == qb % 8); -var rb = 0; -function M(a) { - return B[rb >> 2] = a -} -s._memcpy = sb; -s._memset = tb; -var N = {L:1, ca:2, Bd:3, sc:4, I:5, za:6, Jb:7, Sc:8, $:9, Zb:10, ua:11, Ld:11, $a:12, Ya:13, kc:14, ed:15, Wb:16, va:17, Md:18, wa:19, gd:20, aa:21, A:22, Mc:23, Za:24, ld:25, Id:26, lc:27, ad:28, da:29, yd:30, Fc:31, rd:32, hc:33, ab:34, Wc:35, pc:36, $b:37, vc:38, wc:39, xc:40, Ec:41, Jd:42, Qc:43, uc:44, ec:45, Tc:46, Pb:50, Sb:51, Nd:52, Oc:53, Tb:54, Ub:55, fc:56, Vb:57, cd:60, Rc:61, Fd:62, bd:63, Xc:64, Yc:65, xd:66, Uc:67, Mb:68, Cd:69, ac:70, td:71, Hc:74, yc:75, ic:76, Rb:77, mc:79, md:80, -Qb:81, wd:82, zc:83, Ac:84, Dc:85, Cc:86, Bc:87, dd:88, Nc:89, ya:90, Ic:91, ba:92, nd:95, qd:96, dc:104, Pc:105, Nb:106, vd:107, jd:108, Zc:109, zd:110, cc:111, Kb:112, bc:113, Lc:114, Jc:115, Gd:116, nc:117, oc:118, rc:119, Ob:120, gc:121, Gc:122, ud:123, Ad:124, Lb:125, Kc:126, tc:127, fd:128, Hd:129, sd:130, Kd:131, jc:132, Dd:133, kd:134, Vc:135, $c:136, Yb:137, qc:138, od:139, Xb:140, hd:141, pd:142, Ed:143}, ub = {"0":"Success", 1:"Not super-user", 2:"No such file or directory", 3:"No such process", -4:"Interrupted system call", 5:"I/O error", 6:"No such device or address", 7:"Arg list too long", 8:"Exec format error", 9:"Bad file number", 10:"No children", 11:"No more processes", 12:"Not enough core", 13:"Permission denied", 14:"Bad address", 15:"Block device required", 16:"Mount device busy", 17:"File exists", 18:"Cross-device link", 19:"No such device", 20:"Not a directory", 21:"Is a directory", 22:"Invalid argument", 23:"Too many open files in system", 24:"Too many open files", 25:"Not a typewriter", -26:"Text file busy", 27:"File too large", 28:"No space left on device", 29:"Illegal seek", 30:"Read only file system", 31:"Too many links", 32:"Broken pipe", 33:"Math arg out of domain of func", 34:"Math result not representable", 35:"No message of desired type", 36:"Identifier removed", 37:"Channel number out of range", 38:"Level 2 not synchronized", 39:"Level 3 halted", 40:"Level 3 reset", 41:"Link number out of range", 42:"Protocol driver not attached", 43:"No CSI structure available", 44:"Level 2 halted", -45:"Deadlock condition", 46:"No record locks available", 50:"Invalid exchange", 51:"Invalid request descriptor", 52:"Exchange full", 53:"No anode", 54:"Invalid request code", 55:"Invalid slot", 56:"File locking deadlock error", 57:"Bad font file fmt", 60:"Device not a stream", 61:"No data (for no delay io)", 62:"Timer expired", 63:"Out of streams resources", 64:"Machine is not on the network", 65:"Package not installed", 66:"The object is remote", 67:"The link has been severed", 68:"Advertise error", -69:"Srmount error", 70:"Communication error on send", 71:"Protocol error", 74:"Multihop attempted", 75:"Inode is remote (not really error)", 76:"Cross mount point (not really error)", 77:"Trying to read unreadable message", 79:"Inappropriate file type or format", 80:"Given log. name not unique", 81:"f.d. invalid for this operation", 82:"Remote address changed", 83:"Can\t access a needed shared lib", 84:"Accessing a corrupted shared lib", 85:".lib section in a.out corrupted", 86:"Attempting to link in too many libs", -87:"Attempting to exec a shared library", 88:"Function not implemented", 89:"No more files", 90:"Directory not empty", 91:"File or path name too long", 92:"Too many symbolic links", 95:"Operation not supported on transport endpoint", 96:"Protocol family not supported", 104:"Connection reset by peer", 105:"No buffer space available", 106:"Address family not supported by protocol family", 107:"Protocol wrong type for socket", 108:"Socket operation on non-socket", 109:"Protocol not available", 110:"Can't send after socket shutdown", -111:"Connection refused", 112:"Address already in use", 113:"Connection aborted", 114:"Network is unreachable", 115:"Network interface is not configured", 116:"Connection timed out", 117:"Host is down", 118:"Host is unreachable", 119:"Connection already in progress", 120:"Socket already connected", 121:"Destination address required", 122:"Message too long", 123:"Unknown protocol", 124:"Socket type not supported", 125:"Address not available", 126:"ENETRESET", 127:"Socket is already connected", 128:"Socket is not connected", -129:"TOOMANYREFS", 130:"EPROCLIM", 131:"EUSERS", 132:"EDQUOT", 133:"ESTALE", 134:"Not supported", 135:"No medium (in tape drive)", 136:"No such host or network path", 137:"Filename exists with different case", 138:"EILSEQ", 139:"Value too large for defined data type", 140:"Operation canceled", 141:"State not recoverable", 142:"Previous owner died", 143:"Streams pipe error"}; -function vb(a, b, c) { - var d = O(a, {parent:l}).d, a = "/" === a ? "/" : wb(a)[2], e = xb(d, a); - e && g(new Q(e)); - d.l.Ta || g(new Q(N.L)); - return d.l.Ta(d, a, b, c) -} -function yb(a, b) { - b = b & 4095 | 32768; - return vb(a, b, 0) -} -function zb(a, b) { - b = b & 1023 | 16384; - return vb(a, b, 0) -} -function Ab(a, b, c) { - return vb(a, b | 8192, c) -} -function Bb(a, b) { - var c = O(b, {parent:l}).d, d = "/" === b ? "/" : wb(b)[2], e = xb(c, d); - e && g(new Q(e)); - c.l.Wa || g(new Q(N.L)); - return c.l.Wa(c, d, a) -} -function Cb(a, b) { - var c; - c = "string" === typeof a ? O(a, {N:l}).d : a; - c.l.Y || g(new Q(N.L)); - c.l.Y(c, {mode:b & 4095 | c.mode & -4096, timestamp:Date.now()}) -} -function Db(a, b) { - var c, a = Eb(a), d; - "string" === typeof b ? (d = Fb[b], "undefined" === typeof d && g(Error("Unknown file open mode: " + b))) : d = b; - b = d; - c = b & 512 ? c & 4095 | 32768 : 0; - var e; - try { - var f = O(a, {N:!(b & 65536)}); - e = f.d; - a = f.path - }catch(h) { - } - b & 512 && (e ? b & 2048 && g(new Q(N.va)) : e = vb(a, c, 0)); - e || g(new Q(N.ca)); - 8192 === (e.mode & 61440) && (b &= -1025); - e ? 40960 === (e.mode & 61440) ? c = N.ba : 16384 === (e.mode & 61440) && (0 !== (b & 3) || b & 1024) ? c = N.aa : (c = ["r", "w", "rw"][b & 3], b & 1024 && (c += "w"), c = Gb(e, c)) : c = N.ca; - c && g(new Q(c)); - b & 1024 && (c = e, c = "string" === typeof c ? O(c, {N:l}).d : c, c.l.Y || g(new Q(N.L)), 16384 === (c.mode & 61440) && g(new Q(N.aa)), 32768 !== (c.mode & 61440) && g(new Q(N.A)), (f = Gb(c, "w")) && g(new Q(f)), c.l.Y(c, {size:0, timestamp:Date.now()})); - var i = {path:a, d:e, M:b, seekable:l, position:0, e:e.e, Gb:[], error:p}, j; - a: { - e = k || 4096; - for(c = k || 1;c <= e;c++) { - if(!R[c]) { - j = c; - break a - } - } - g(new Q(N.Za)) - } - i.s = j; - Object.defineProperty(i, "object", {get:function() { - return i.d - }, set:function(a) { - i.d = a - }}); - Object.defineProperty(i, "isRead", {get:function() { - return 1 !== (i.M & 3) - }}); - Object.defineProperty(i, "isWrite", {get:function() { - return 0 !== (i.M & 3) - }}); - Object.defineProperty(i, "isAppend", {get:function() { - return i.M & 8 - }}); - R[j] = i; - i.e.open && i.e.open(i); - return i -} -function Hb(a) { - try { - a.e.close && a.e.close(a) - }catch(b) { - g(b) - }finally { - R[a.s] = m - } -} -function Ib(a, b, c, d, e) { - (0 > d || 0 > e) && g(new Q(N.A)); - 0 === (a.M & 3) && g(new Q(N.$)); - 16384 === (a.d.mode & 61440) && g(new Q(N.aa)); - a.e.write || g(new Q(N.A)); - var f = l; - "undefined" === typeof e ? (e = a.position, f = p) : a.seekable || g(new Q(N.da)); - a.M & 8 && ((!a.seekable || !a.e.na) && g(new Q(N.da)), a.e.na(a, 0, 2)); - b = a.e.write(a, b, c, d, e); - f || (a.position += b); - return b -} -function wb(a) { - return/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(a).slice(1) -} -function Jb(a, b) { - for(var c = 0, d = a.length - 1;0 <= d;d--) { - var e = a[d]; - "." === e ? a.splice(d, 1) : ".." === e ? (a.splice(d, 1), c++) : c && (a.splice(d, 1), c--) - } - if(b) { - for(;c--;c) { - a.unshift("..") - } - } - return a -} -function Eb(a) { - var b = "/" === a.charAt(0), c = "/" === a.substr(-1), a = Jb(a.split("/").filter(function(a) { - return!!a - }), !b).join("/"); - !a && !b && (a = "."); - a && c && (a += "/"); - return(b ? "/" : "") + a -} -function S() { - var a = Array.prototype.slice.call(arguments, 0); - return Eb(a.filter(function(a) { - "string" !== typeof a && g(new TypeError("Arguments to path.join must be strings")); - return a - }).join("/")) -} -function Kb() { - for(var a = "", b = p, c = arguments.length - 1;-1 <= c && !b;c--) { - var d = 0 <= c ? arguments[c] : "/"; - "string" !== typeof d && g(new TypeError("Arguments to path.resolve must be strings")); - d && (a = d + "/" + a, b = "/" === d.charAt(0)) - } - a = Jb(a.split("/").filter(function(a) { - return!!a - }), !b).join("/"); - return(b ? "/" : "") + a || "." -} -var Lb = []; -function Mb(a, b) { - Lb[a] = {input:[], H:[], O:b}; - Nb[a] = {e:Ob} -} -var Ob = {open:function(a) { - Pb || (Pb = new pa); - var b = Lb[a.d.X]; - b || g(new Q(N.wa)); - a.q = b; - a.seekable = p -}, close:function(a) { - a.q.H.length && a.q.O.W(a.q, 10) -}, Q:function(a, b, c, d) { - (!a.q || !a.q.O.Na) && g(new Q(N.za)); - for(var e = 0, f = 0;f < d;f++) { - var h; - try { - h = a.q.O.Na(a.q) - }catch(i) { - g(new Q(N.I)) - } - h === k && 0 === e && g(new Q(N.ua)); - if(h === m || h === k) { - break - } - e++; - b[c + f] = h - } - e && (a.d.timestamp = Date.now()); - return e -}, write:function(a, b, c, d) { - (!a.q || !a.q.O.W) && g(new Q(N.za)); - for(var e = 0;e < d;e++) { - try { - a.q.O.W(a.q, b[c + e]) - }catch(f) { - g(new Q(N.I)) - } - } - d && (a.d.timestamp = Date.now()); - return e -}}, Pb, T = {z:function() { - return T.ka(m, "/", 16895, 0) -}, ka:function(a, b, c, d) { - (24576 === (c & 61440) || 4096 === (c & 61440)) && g(new Q(N.L)); - c = Qb(a, b, c, d); - c.l = T.l; - 16384 === (c.mode & 61440) ? (c.e = T.e, c.g = {}) : 32768 === (c.mode & 61440) ? (c.e = T.e, c.g = []) : 40960 === (c.mode & 61440) ? c.e = T.e : 8192 === (c.mode & 61440) && (c.e = Rb); - c.timestamp = Date.now(); - a && (a.g[b] = c); - return c -}, l:{ge:function(a) { - var b = {}; - b.ce = 8192 === (a.mode & 61440) ? a.id : 1; - b.je = a.id; - b.mode = a.mode; - b.pe = 1; - b.uid = 0; - b.he = 0; - b.X = a.X; - b.size = 16384 === (a.mode & 61440) ? 4096 : 32768 === (a.mode & 61440) ? a.g.length : 40960 === (a.mode & 61440) ? a.link.length : 0; - b.Yd = new Date(a.timestamp); - b.oe = new Date(a.timestamp); - b.ae = new Date(a.timestamp); - b.ib = 4096; - b.Zd = Math.ceil(b.size / b.ib); - return b -}, Y:function(a, b) { - b.mode !== k && (a.mode = b.mode); - b.timestamp !== k && (a.timestamp = b.timestamp); - if(b.size !== k) { - var c = a.g; - if(b.size < c.length) { - c.length = b.size - }else { - for(;b.size > c.length;) { - c.push(0) - } - } - } -}, tb:function() { - g(new Q(N.ca)) -}, Ta:function(a, b, c, d) { - return T.ka(a, b, c, d) -}, rename:function(a, b, c) { - if(16384 === (a.mode & 61440)) { - var d; - try { - d = Sb(b, c) - }catch(e) { - } - if(d) { - for(var f in d.g) { - g(new Q(N.ya)) - } - } - } - delete a.parent.g[a.name]; - a.name = c; - b.g[c] = a -}, ze:function(a, b) { - delete a.g[b] -}, ve:function(a, b) { - var c = Sb(a, b), d; - for(d in c.g) { - g(new Q(N.ya)) - } - delete a.g[b] -}, Wa:function(a, b, c) { - a = T.ka(a, b, 41471, 0); - a.link = c; - return a -}, Va:function(a) { - 40960 !== (a.mode & 61440) && g(new Q(N.A)); - return a.link -}}, e:{open:function(a) { - if(16384 === (a.d.mode & 61440)) { - var b = [".", ".."], c; - for(c in a.d.g) { - a.d.g.hasOwnProperty(c) && b.push(c) - } - a.lb = b - } -}, Q:function(a, b, c, d, e) { - a = a.d.g; - d = Math.min(a.length - e, d); - if(a.subarray) { - b.set(a.subarray(e, e + d), c) - }else { - for(var f = 0;f < d;f++) { - b[c + f] = a[e + f] - } - } - return d -}, write:function(a, b, c, d, e) { - for(var f = a.d.g;f.length < e;) { - f.push(0) - } - for(var h = 0;h < d;h++) { - f[e + h] = b[c + h] - } - a.d.timestamp = Date.now(); - return d -}, na:function(a, b, c) { - 1 === c ? b += a.position : 2 === c && 32768 === (a.d.mode & 61440) && (b += a.d.g.length); - 0 > b && g(new Q(N.A)); - a.Gb = []; - return a.position = b -}, ue:function(a) { - return a.lb -}, Wd:function(a, b, c) { - a = a.d.g; - for(b += c;b > a.length;) { - a.push(0) - } -}, ne:function(a, b, c, d, e, f, h) { - 32768 !== (a.d.mode & 61440) && g(new Q(N.wa)); - a = a.d.g; - if(h & 2) { - if(0 < e || e + d < a.length) { - a = a.subarray ? a.subarray(e, e + d) : Array.prototype.slice.call(a, e, e + d) - } - e = l; - (d = Oa(d)) || g(new Q(N.$a)); - b.set(a, d) - }else { - w(a.buffer === b || a.buffer === b.buffer), e = p, d = a.byteOffset - } - return{te:d, Xd:e} -}}}, Tb = F(1, "i32*", E), Ub = F(1, "i32*", E); -nb = F(1, "i32*", E); -var Vb = m, Nb = [m], R = [m], Wb = 1, Xb = [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ], Yb = l; -function Q(a) { - this.mb = a; - for(var b in N) { - if(N[b] === a) { - this.code = b; - break - } - } - this.message = ub[a] -} -function Zb(a) { - a instanceof Q || g(a + " : " + Error().stack); - M(a.mb) -} -function $b(a, b) { - for(var c = 0, d = 0;d < b.length;d++) { - c = (c << 5) - c + b.charCodeAt(d) | 0 - } - return(a + c) % Xb.length -} -function Sb(a, b) { - var c = Gb(a, "x"); - c && g(new Q(c)); - for(c = Xb[$b(a.id, b)];c;c = c.wb) { - if(c.parent.id === a.id && c.name === b) { - return c - } - } - return a.l.tb(a, b) -} -function Qb(a, b, c, d) { - var e = {id:Wb++, name:b, mode:c, l:{}, e:{}, X:d, parent:m, z:m}; - a || (a = e); - e.parent = a; - e.z = a.z; - Object.defineProperty(e, "read", {get:function() { - return 365 === (e.mode & 365) - }, set:function(a) { - a ? e.mode |= 365 : e.mode &= -366 - }}); - Object.defineProperty(e, "write", {get:function() { - return 146 === (e.mode & 146) - }, set:function(a) { - a ? e.mode |= 146 : e.mode &= -147 - }}); - a = $b(e.parent.id, e.name); - e.wb = Xb[a]; - return Xb[a] = e -} -function O(a, b) { - a = Kb("/", a); - b = b || {pa:0}; - 8 < b.pa && g(new Q(N.ba)); - for(var c = Jb(a.split("/").filter(function(a) { - return!!a - }), p), d = Vb, e = "/", f = 0;f < c.length;f++) { - var h = f === c.length - 1; - if(h && b.parent) { - break - } - d = Sb(d, c[f]); - e = S(e, c[f]); - d.ub && (d = d.z.root); - if(!h || b.N) { - for(h = 0;40960 === (d.mode & 61440);) { - d = O(e, {N:p}).d; - d.l.Va || g(new Q(N.A)); - var d = d.l.Va(d), i = Kb; - var j = wb(e), e = j[0], j = j[1]; - !e && !j ? e = "." : (j && (j = j.substr(0, j.length - 1)), e += j); - e = i(e, d); - d = O(e, {pa:b.pa}).d; - 40 < h++ && g(new Q(N.ba)) - } - } - } - return{path:e, d:d} -} -function ac(a) { - for(var b;;) { - if(a === a.parent) { - return b ? S(a.z.Ua, b) : a.z.Ua - } - b = b ? S(a.name, b) : a.name; - a = a.parent - } -} -var Fb = {r:0, rs:8192, "r+":2, w:1537, wx:3585, xw:3585, "w+":1538, "wx+":3586, "xw+":3586, a:521, ax:2569, xa:2569, "a+":522, "ax+":2570, "xa+":2570}; -function Gb(a, b) { - return Yb ? 0 : -1 !== b.indexOf("r") && !(a.mode & 292) || -1 !== b.indexOf("w") && !(a.mode & 146) || -1 !== b.indexOf("x") && !(a.mode & 73) ? N.Ya : 0 -} -function xb(a, b) { - try { - return Sb(a, b), N.va - }catch(c) { - } - return Gb(a, "wx") -} -var Rb = {open:function(a) { - a.e = Nb[a.d.X].e; - a.e.open && a.e.open(a) -}, na:function() { - g(new Q(N.da)) -}}, bc; -function cc(a, b) { - var c = 0; - a && (c |= 365); - b && (c |= 146); - return c -} -function dc(a, b, c, d, e) { - a = S("string" === typeof a ? a : ac(a), b); - d = cc(d, e); - e = yb(a, d); - if(c) { - if("string" === typeof c) { - for(var b = Array(c.length), f = 0, h = c.length;f < h;++f) { - b[f] = c.charCodeAt(f) - } - c = b - } - Cb(a, d | 146); - b = Db(a, "w"); - Ib(b, c, 0, c.length, 0); - Hb(b); - Cb(a, d) - } - return e -} -function ec(a, b, c, d) { - a = S("string" === typeof a ? a : ac(a), b); - ec.Sa || (ec.Sa = 64); - b = ec.Sa++ << 8 | 0; - Nb[b] = {e:{open:function(a) { - a.seekable = p - }, close:function() { - d && (d.buffer && d.buffer.length) && d(10) - }, Q:function(a, b, d, i) { - for(var j = 0, n = 0;n < i;n++) { - var y; - try { - y = c() - }catch(v) { - g(new Q(N.I)) - } - y === k && 0 === j && g(new Q(N.ua)); - if(y === m || y === k) { - break - } - j++; - b[d + n] = y - } - j && (a.d.timestamp = Date.now()); - return j - }, write:function(a, b, c, i) { - for(var j = 0;j < i;j++) { - try { - d(b[c + j]) - }catch(n) { - g(new Q(N.I)) - } - } - i && (a.d.timestamp = Date.now()); - return j - }}}; - return Ab(a, c && d ? 511 : c ? 219 : 365, b) -} -function fc(a, b, c) { - a = R[a]; - if(!a) { - return-1 - } - a.sender(G.subarray(b, b + c)); - return c -} -function gc(a, b, c) { - var d = R[a]; - if(!d) { - return M(N.$), -1 - } - if(d && "socket" in d) { - return fc(a, b, c) - } - try { - return Ib(d, A, b, c) - }catch(e) { - return Zb(e), -1 - } -} -function hc(a, b, c, d) { - c *= b; - if(0 == c) { - return 0 - } - a = gc(d, a, c); - if(-1 == a) { - if(b = R[d]) { - b.error = l - } - return 0 - } - return Math.floor(a / b) -} -s._strlen = ic; -function jc(a) { - return 0 > a || 0 === a && -Infinity === 1 / a -} -function kc(a, b) { - function c(a) { - var c; - "double" === a ? c = Ja[b + e >> 3] : "i64" == a ? (c = [B[b + e >> 2], B[b + (e + 8) >> 2]], e += 8) : (a = "i32", c = B[b + e >> 2]); - e += Math.max(Math.max(la(a), ma), 8); - return c - } - for(var d = a, e = 0, f = [], h, i;;) { - var j = d; - h = A[d]; - if(0 === h) { - break - } - i = A[d + 1 | 0]; - if(37 == h) { - var n = p, y = p, v = p, C = p; - a:for(;;) { - switch(i) { - case 43: - n = l; - break; - case 45: - y = l; - break; - case 35: - v = l; - break; - case 48: - if(C) { - break a - }else { - C = l; - break - } - ; - default: - break a - } - d++; - i = A[d + 1 | 0] - } - var D = 0; - if(42 == i) { - D = c("i32"), d++, i = A[d + 1 | 0] - }else { - for(;48 <= i && 57 >= i;) { - D = 10 * D + (i - 48), d++, i = A[d + 1 | 0] - } - } - var K = p; - if(46 == i) { - var H = 0, K = l; - d++; - i = A[d + 1 | 0]; - if(42 == i) { - H = c("i32"), d++ - }else { - for(;;) { - i = A[d + 1 | 0]; - if(48 > i || 57 < i) { - break - } - H = 10 * H + (i - 48); - d++ - } - } - i = A[d + 1 | 0] - }else { - H = 6 - } - var x; - switch(String.fromCharCode(i)) { - case "h": - i = A[d + 2 | 0]; - 104 == i ? (d++, x = 1) : x = 2; - break; - case "l": - i = A[d + 2 | 0]; - 108 == i ? (d++, x = 8) : x = 4; - break; - case "L": - ; - case "q": - ; - case "j": - x = 8; - break; - case "z": - ; - case "t": - ; - case "I": - x = 4; - break; - default: - x = m - } - x && d++; - i = A[d + 1 | 0]; - switch(String.fromCharCode(i)) { - case "d": - ; - case "i": - ; - case "u": - ; - case "o": - ; - case "x": - ; - case "X": - ; - case "p": - j = 100 == i || 105 == i; - x = x || 4; - var P = h = c("i" + 8 * x), r; - 8 == x && (h = 117 == i ? +(h[0] >>> 0) + 4294967296 * +(h[1] >>> 0) : +(h[0] >>> 0) + 4294967296 * +(h[1] | 0)); - 4 >= x && (h = (j ? eb : db)(h & Math.pow(256, x) - 1, 8 * x)); - var ta = Math.abs(h), j = ""; - if(100 == i || 105 == i) { - r = 8 == x && lc ? lc.stringify(P[0], P[1], m) : eb(h, 8 * x).toString(10) - }else { - if(117 == i) { - r = 8 == x && lc ? lc.stringify(P[0], P[1], l) : db(h, 8 * x).toString(10), h = Math.abs(h) - }else { - if(111 == i) { - r = (v ? "0" : "") + ta.toString(8) - }else { - if(120 == i || 88 == i) { - j = v && 0 != h ? "0x" : ""; - if(8 == x && lc) { - if(P[1]) { - r = (P[1] >>> 0).toString(16); - for(v = (P[0] >>> 0).toString(16);8 > v.length;) { - v = "0" + v - } - r += v - }else { - r = (P[0] >>> 0).toString(16) - } - }else { - if(0 > h) { - h = -h; - r = (ta - 1).toString(16); - P = []; - for(v = 0;v < r.length;v++) { - P.push((15 - parseInt(r[v], 16)).toString(16)) - } - for(r = P.join("");r.length < 2 * x;) { - r = "f" + r - } - }else { - r = ta.toString(16) - } - } - 88 == i && (j = j.toUpperCase(), r = r.toUpperCase()) - }else { - 112 == i && (0 === ta ? r = "(nil)" : (j = "0x", r = ta.toString(16))) - } - } - } - } - if(K) { - for(;r.length < H;) { - r = "0" + r - } - } - for(n && (j = 0 > h ? "-" + j : "+" + j);j.length + r.length < D;) { - y ? r += " " : C ? r = "0" + r : j = " " + j - } - r = j + r; - r.split("").forEach(function(a) { - f.push(a.charCodeAt(0)) - }); - break; - case "f": - ; - case "F": - ; - case "e": - ; - case "E": - ; - case "g": - ; - case "G": - h = c("double"); - if(isNaN(h)) { - r = "nan", C = p - }else { - if(isFinite(h)) { - K = p; - x = Math.min(H, 20); - if(103 == i || 71 == i) { - K = l, H = H || 1, x = parseInt(h.toExponential(x).split("e")[1], 10), H > x && -4 <= x ? (i = (103 == i ? "f" : "F").charCodeAt(0), H -= x + 1) : (i = (103 == i ? "e" : "E").charCodeAt(0), H--), x = Math.min(H, 20) - } - if(101 == i || 69 == i) { - r = h.toExponential(x), /[eE][-+]\d$/.test(r) && (r = r.slice(0, -1) + "0" + r.slice(-1)) - }else { - if(102 == i || 70 == i) { - r = h.toFixed(x), 0 === h && jc(h) && (r = "-" + r) - } - } - j = r.split("e"); - if(K && !v) { - for(;1 < j[0].length && -1 != j[0].indexOf(".") && ("0" == j[0].slice(-1) || "." == j[0].slice(-1));) { - j[0] = j[0].slice(0, -1) - } - }else { - for(v && -1 == r.indexOf(".") && (j[0] += ".");H > x++;) { - j[0] += "0" - } - } - r = j[0] + (1 < j.length ? "e" + j[1] : ""); - 69 == i && (r = r.toUpperCase()); - n && 0 <= h && (r = "+" + r) - }else { - r = (0 > h ? "-" : "") + "inf", C = p - } - } - for(;r.length < D;) { - r = y ? r + " " : C && ("-" == r[0] || "+" == r[0]) ? r[0] + "0" + r.slice(1) : (C ? "0" : " ") + r - } - 97 > i && (r = r.toUpperCase()); - r.split("").forEach(function(a) { - f.push(a.charCodeAt(0)) - }); - break; - case "s": - C = (n = c("i8*")) ? ic(n) : 6; - K && (C = Math.min(C, H)); - if(!y) { - for(;C < D--;) { - f.push(32) - } - } - if(n) { - for(v = 0;v < C;v++) { - f.push(G[n++ | 0]) - } - }else { - f = f.concat(J("(null)".substr(0, C), l)) - } - if(y) { - for(;C < D--;) { - f.push(32) - } - } - break; - case "c": - for(y && f.push(c("i8"));0 < --D;) { - f.push(32) - } - y || f.push(c("i8")); - break; - case "n": - y = c("i32*"); - B[y >> 2] = f.length; - break; - case "%": - f.push(h); - break; - default: - for(v = j;v < d + 2;v++) { - f.push(A[v]) - } - } - d += 2 - }else { - f.push(h), d += 1 - } - } - return f -} -function mc(a, b, c) { - c = kc(b, c); - b = ja(); - a = hc(F(c, "i8", La), 1, c.length, a); - ka(b); - return a -} -function nc(a) { - nc.ia || (z = z + 4095 >> 12 << 12, nc.ia = l, w(ua), nc.hb = ua, ua = function() { - wa("cannot dynamically allocate, sbrk now has control") - }); - var b = z; - 0 != a && nc.hb(a); - return b -} -function U() { - return B[U.m >> 2] -} -function oc() { - return!!oc.ta -} -function pc(a) { - var b = p; - try { - a == __ZTIi && (b = l) - }catch(c) { - } - try { - a == __ZTIj && (b = l) - }catch(d) { - } - try { - a == __ZTIl && (b = l) - }catch(e) { - } - try { - a == __ZTIm && (b = l) - }catch(f) { - } - try { - a == __ZTIx && (b = l) - }catch(h) { - } - try { - a == __ZTIy && (b = l) - }catch(i) { - } - try { - a == __ZTIf && (b = l) - }catch(j) { - } - try { - a == __ZTId && (b = l) - }catch(n) { - } - try { - a == __ZTIe && (b = l) - }catch(y) { - } - try { - a == __ZTIc && (b = l) - }catch(v) { - } - try { - a == __ZTIa && (b = l) - }catch(C) { - } - try { - a == __ZTIh && (b = l) - }catch(D) { - } - try { - a == __ZTIs && (b = l) - }catch(K) { - } - try { - a == __ZTIt && (b = l) - }catch(H) { - } - return b -} -function qc(a, b, c) { - if(0 == c) { - return p - } - if(0 == b || b == a) { - return l - } - switch(pc(b) ? b : B[B[b >> 2] - 8 >> 2]) { - case 0: - return 0 == B[B[a >> 2] - 8 >> 2] ? qc(B[a + 8 >> 2], B[b + 8 >> 2], c) : p; - case 1: - return p; - case 2: - return qc(a, B[b + 8 >> 2], c); - default: - return p - } -} -function rc(a, b, c) { - if(!rc.sb) { - try { - B[__ZTVN10__cxxabiv119__pointer_type_infoE >> 2] = 0 - }catch(d) { - } - try { - B[pb >> 2] = 1 - }catch(e) { - } - try { - B[ob >> 2] = 2 - }catch(f) { - } - rc.sb = l - } - B[U.m >> 2] = a; - B[U.m + 4 >> 2] = b; - B[U.m + 8 >> 2] = c; - "uncaught_exception" in oc ? oc.ta++ : oc.ta = 1; - g(a + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.") -} -function sc(a) { - try { - return tc(a) - }catch(b) { - } -} -function uc() { - if(uc.Bb) { - uc.Bb = p - }else { - V.setThrew(0); - B[U.m + 4 >> 2] = 0; - var a = B[U.m >> 2], b = B[U.m + 8 >> 2]; - b && (na("vi", b, [a]), B[U.m + 8 >> 2] = 0); - a && (sc(a), B[U.m >> 2] = 0) - } -} -var vc = F(1, "i32*", E); -function wc(a) { - var b, c; - wc.ia ? (c = B[vc >> 2], b = B[c >> 2]) : (wc.ia = l, W.USER = "root", W.PATH = "/", W.PWD = "/", W.HOME = "/home/emscripten", W.LANG = "en_US.UTF-8", W._ = "./this.program", b = F(1024, "i8", E), c = F(256, "i8*", E), B[c >> 2] = b, B[vc >> 2] = c); - var d = [], e = 0, f; - for(f in a) { - if("string" === typeof a[f]) { - var h = f + "=" + a[f]; - d.push(h); - e += h.length - } - } - 1024 < e && g(Error("Environment size exceeded TOTAL_ENV_SIZE!")); - for(a = 0;a < d.length;a++) { - h = d[a]; - for(e = 0;e < h.length;e++) { - A[b + e | 0] = h.charCodeAt(e) - } - A[b + e | 0] = 0; - B[c + 4 * a >> 2] = b; - b += h.length + 1 - } - B[c + 4 * d.length >> 2] = 0 -} -var W = {}; -function xc(a) { - if(0 === a) { - return 0 - } - a = Fa(a); - if(!W.hasOwnProperty(a)) { - return 0 - } - xc.J && tc(xc.J); - xc.J = F(J(W[a]), "i8", Ka); - return xc.J -} -function yc(a, b, c) { - if(a in ub) { - if(ub[a].length > c - 1) { - return M(N.ab) - } - a = ub[a]; - for(c = 0;c < a.length;c++) { - A[b + c | 0] = a.charCodeAt(c) - } - return A[b + c | 0] = 0 - } - return M(N.A) -} -function zc(a) { - zc.buffer || (zc.buffer = Oa(256)); - yc(a, zc.buffer, 256); - return zc.buffer -} -function Ac(a) { - s.exit(a) -} -function Bc(a, b) { - var c = db(a & 255); - A[Bc.J | 0] = c; - if(-1 == gc(b, Bc.J, 1)) { - if(c = R[b]) { - c.error = l - } - return-1 - } - return c -} -var Cc = p, Dc = p, Ec = p, Fc = p, Gc = k, Hc = k; -function Ic(a) { - return{jpg:"image/jpeg", jpeg:"image/jpeg", png:"image/png", bmp:"image/bmp", ogg:"audio/ogg", wav:"audio/wav", mp3:"audio/mpeg"}[a.substr(a.lastIndexOf(".") + 1)] -} -var Jc = []; -function Kc() { - var a = s.canvas; - Jc.forEach(function(b) { - b(a.width, a.height) - }) -} -function Lc() { - var a = s.canvas; - this.Ib = a.width; - this.Hb = a.height; - a.width = screen.width; - a.height = screen.height; - "undefined" != typeof SDL && (a = Qa[SDL.screen + 0 * ma >> 2], B[SDL.screen + 0 * ma >> 2] = a | 8388608); - Kc() -} -function Mc() { - var a = s.canvas; - a.width = this.Ib; - a.height = this.Hb; - "undefined" != typeof SDL && (a = Qa[SDL.screen + 0 * ma >> 2], B[SDL.screen + 0 * ma >> 2] = a & -8388609); - Kc() -} -var Nc, Oc, Pc, Qc, rb = ra(4); -B[rb >> 2] = 0; -var Vb = Qb(m, "/", 16895, 0), Rc = T, Sc = {type:Rc, se:{}, Ua:"/", root:m}, Tc; -Tc = O("/", {N:p}); -var Uc = Rc.z(Sc); -Uc.z = Sc; -Sc.root = Uc; -Tc && (Tc.d.z = Sc, Tc.d.ub = l, Vb = Sc.root); -zb("/tmp", 511); -zb("/dev", 511); -Nb[259] = {e:{Q:function() { - return 0 -}, write:function() { - return 0 -}}}; -Ab("/dev/null", 438, 259); -Mb(1280, {Na:function(a) { - if(!a.input.length) { - var b = m; - if(ca) { - if(process.Eb.be) { - return - } - b = process.Eb.Q() - }else { - "undefined" != typeof window && "function" == typeof window.prompt ? (b = window.prompt("Input: "), b !== m && (b += "\n")) : "function" == typeof readline && (b = readline(), b !== m && (b += "\n")) - } - if(!b) { - return m - } - a.input = J(b, l) - } - return a.input.shift() -}, W:function(a, b) { - b === m || 10 === b ? (s.print(a.H.join("")), a.H = []) : a.H.push(Pb.oa(b)) -}}); -Mb(1536, {W:function(a, b) { - b === m || 10 === b ? (s.printErr(a.H.join("")), a.H = []) : a.H.push(Pb.oa(b)) -}}); -Ab("/dev/tty", 438, 1280); -Ab("/dev/tty1", 438, 1536); -zb("/dev/shm", 511); -zb("/dev/shm/tmp", 511); -Xa.unshift({V:function() { - if(!s.noFSInit && !bc) { - w(!bc, "FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)"); - bc = l; - s.stdin = s.stdin; - s.stdout = s.stdout; - s.stderr = s.stderr; - s.stdin ? ec("/dev", "stdin", s.stdin) : Bb("/dev/tty", "/dev/stdin"); - s.stdout ? ec("/dev", "stdout", m, s.stdout) : Bb("/dev/tty", "/dev/stdout"); - s.stderr ? ec("/dev", "stderr", m, s.stderr) : Bb("/dev/tty1", "/dev/stderr"); - var a = Db("/dev/stdin", "r"); - B[Tb >> 2] = a.s; - w(1 === a.s, "invalid handle for stdin (" + a.s + ")"); - a = Db("/dev/stdout", "w"); - B[Ub >> 2] = a.s; - w(2 === a.s, "invalid handle for stdout (" + a.s + ")"); - a = Db("/dev/stderr", "w"); - B[nb >> 2] = a.s; - w(3 === a.s, "invalid handle for stderr (" + a.s + ")") - } -}}); -Ya.push({V:function() { - Yb = p -}}); -Za.push({V:function() { - bc = p; - for(var a = 0;a < R.length;a++) { - var b = R[a]; - b && Hb(b) - } -}}); -s.FS_createFolder = function(a, b, c, d) { - a = S("string" === typeof a ? a : ac(a), b); - return zb(a, cc(c, d)) -}; -s.FS_createPath = function(a, b) { - for(var a = "string" === typeof a ? a : ac(a), c = b.split("/").reverse();c.length;) { - var d = c.pop(); - if(d) { - var e = S(a, d); - try { - zb(e, 511) - }catch(f) { - } - a = e - } - } - return e -}; -s.FS_createDataFile = dc; -s.FS_createPreloadedFile = function(a, b, c, d, e, f, h, i) { - function j() { - Ec = document.pointerLockElement === v || document.mozPointerLockElement === v || document.webkitPointerLockElement === v - } - function n(c) { - function j(c) { - i || dc(a, b, c, d, e); - f && f(); - jb("cp " + C) - } - var n = p; - s.preloadPlugins.forEach(function(a) { - !n && a.canHandle(C) && (a.handle(c, C, j, function() { - h && h(); - jb("cp " + C) - }), n = l) - }); - n || j(c) - } - s.preloadPlugins || (s.preloadPlugins = []); - if(!Nc && !ea) { - Nc = l; - try { - new Blob, Oc = l - }catch(y) { - Oc = p, console.log("warning: no blob constructor, cannot create blobs with mimetypes") - } - Pc = "undefined" != typeof MozBlobBuilder ? MozBlobBuilder : "undefined" != typeof WebKitBlobBuilder ? WebKitBlobBuilder : !Oc ? console.log("warning: no BlobBuilder") : m; - Qc = "undefined" != typeof window ? window.URL ? window.URL : window.webkitURL : console.log("warning: cannot create object URLs"); - s.preloadPlugins.push({canHandle:function(a) { - return!s.re && /\.(jpg|jpeg|png|bmp)$/i.test(a) - }, handle:function(a, b, c, d) { - var e = m; - if(Oc) { - try { - e = new Blob([a], {type:Ic(b)}), e.size !== a.length && (e = new Blob([(new Uint8Array(a)).buffer], {type:Ic(b)})) - }catch(f) { - var h = "Blob constructor present but fails: " + f + "; falling back to blob builder"; - oa || (oa = {}); - oa[h] || (oa[h] = 1, s.P(h)) - } - } - e || (e = new Pc, e.append((new Uint8Array(a)).buffer), e = e.getBlob()); - var i = Qc.createObjectURL(e), j = new Image; - j.onload = function() { - w(j.complete, "Image " + b + " could not be decoded"); - var d = document.createElement("canvas"); - d.width = j.width; - d.height = j.height; - d.getContext("2d").drawImage(j, 0, 0); - s.preloadedImages[b] = d; - Qc.revokeObjectURL(i); - c && c(a) - }; - j.onerror = function() { - console.log("Image " + i + " could not be decoded"); - d && d() - }; - j.src = i - }}); - s.preloadPlugins.push({canHandle:function(a) { - return!s.qe && a.substr(-4) in {".ogg":1, ".wav":1, ".mp3":1} - }, handle:function(a, b, c, d) { - function e(d) { - h || (h = l, s.preloadedAudios[b] = d, c && c(a)) - } - function f() { - h || (h = l, s.preloadedAudios[b] = new Audio, d && d()) - } - var h = p; - if(Oc) { - try { - var i = new Blob([a], {type:Ic(b)}) - }catch(j) { - return f() - } - var i = Qc.createObjectURL(i), n = new Audio; - n.addEventListener("canplaythrough", function() { - e(n) - }, p); - n.onerror = function() { - if(!h) { - console.log("warning: browser could not fully decode audio " + b + ", trying slower base64 approach"); - for(var c = "", d = 0, f = 0, i = 0;i < a.length;i++) { - d = d << 8 | a[i]; - for(f += 8;6 <= f;) { - var j = d >> f - 6 & 63, f = f - 6, c = c + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[j] - } - } - 2 == f ? (c += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(d & 3) << 4], c += "==") : 4 == f && (c += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(d & 15) << 2], c += "="); - n.src = "data:audio/x-" + b.substr(-3) + ";base64," + c; - e(n) - } - }; - n.src = i; - setTimeout(function() { - za || e(n) - }, 1E4) - }else { - return f() - } - }}); - var v = s.canvas; - v.qa = v.requestPointerLock || v.mozRequestPointerLock || v.webkitRequestPointerLock; - v.La = document.exitPointerLock || document.mozExitPointerLock || document.webkitExitPointerLock || aa(); - v.La = v.La.bind(document); - document.addEventListener("pointerlockchange", j, p); - document.addEventListener("mozpointerlockchange", j, p); - document.addEventListener("webkitpointerlockchange", j, p); - s.elementPointerLock && v.addEventListener("click", function(a) { - !Ec && v.qa && (v.qa(), a.preventDefault()) - }, p) - } - var C, D = S.apply(m, [a, b]); - "/" == D[0] && (D = D.substr(1)); - C = D; - ib("cp " + C); - if("string" == typeof c) { - var K = h, H = function() { - K ? K() : g('Loading data file "' + c + '" failed.') - }, x = new XMLHttpRequest; - x.open("GET", c, l); - x.responseType = "arraybuffer"; - x.onload = function() { - if(200 == x.status || 0 == x.status && x.response) { - var a = x.response; - w(a, 'Loading data file "' + c + '" failed (no arrayBuffer).'); - a = new Uint8Array(a); - n(a); - jb("al " + c) - }else { - H() - } - }; - x.onerror = H; - x.send(m); - ib("al " + c) - }else { - n(c) - } -}; -s.FS_createLazyFile = function(a, b, c, d, e) { - var f, h; - "undefined" !== typeof XMLHttpRequest ? (ea || g("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc"), f = function() { - this.ma = p; - this.T = [] - }, f.prototype.get = function(a) { - if(!(a > this.length - 1 || 0 > a)) { - var b = a % this.S; - return this.pb(Math.floor(a / this.S))[b] - } - }, f.prototype.Cb = function(a) { - this.pb = a - }, f.prototype.Fa = function() { - var a = new XMLHttpRequest; - a.open("HEAD", c, p); - a.send(m); - 200 <= a.status && 300 > a.status || 304 === a.status || g(Error("Couldn't load " + c + ". Status: " + a.status)); - var b = Number(a.getResponseHeader("Content-length")), d, e = 1048576; - if(!((d = a.getResponseHeader("Accept-Ranges")) && "bytes" === d)) { - e = b - } - var f = this; - f.Cb(function(a) { - var d = a * e, h = (a + 1) * e - 1, h = Math.min(h, b - 1); - if("undefined" === typeof f.T[a]) { - var i = f.T; - d > h && g(Error("invalid range (" + d + ", " + h + ") or no bytes requested!")); - h > b - 1 && g(Error("only " + b + " bytes available! programmer error!")); - var j = new XMLHttpRequest; - j.open("GET", c, p); - b !== e && j.setRequestHeader("Range", "bytes=" + d + "-" + h); - "undefined" != typeof Uint8Array && (j.responseType = "arraybuffer"); - j.overrideMimeType && j.overrideMimeType("text/plain; charset=x-user-defined"); - j.send(m); - 200 <= j.status && 300 > j.status || 304 === j.status || g(Error("Couldn't load " + c + ". Status: " + j.status)); - d = j.response !== k ? new Uint8Array(j.response || []) : J(j.responseText || "", l); - i[a] = d - } - "undefined" === typeof f.T[a] && g(Error("doXHR failed!")); - return f.T[a] - }); - this.gb = b; - this.fb = e; - this.ma = l - }, f = new f, Object.defineProperty(f, "length", {get:function() { - this.ma || this.Fa(); - return this.gb - }}), Object.defineProperty(f, "chunkSize", {get:function() { - this.ma || this.Fa(); - return this.fb - }}), h = k) : (h = c, f = k); - var i, a = S("string" === typeof a ? a : ac(a), b); - i = yb(a, cc(d, e)); - f ? i.g = f : h && (i.g = m, i.url = h); - var j = {}; - Object.keys(i.e).forEach(function(a) { - var b = i.e[a]; - j[a] = function() { - var a; - if(i.ke || i.le || i.link || i.g) { - a = l - }else { - a = l; - "undefined" !== typeof XMLHttpRequest && g(Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.")); - if(s.read) { - try { - i.g = J(s.read(i.url), l) - }catch(c) { - a = p - } - }else { - g(Error("Cannot load without read() or XMLHttpRequest.")) - } - a || M(N.I) - } - a || g(new Q(N.I)); - return b.apply(m, arguments) - } - }); - j.Q = function(a, b, c, d, e) { - a = a.d.g; - d = Math.min(a.length - e, d); - if(a.slice) { - for(var f = 0;f < d;f++) { - b[c + f] = a[e + f] - } - }else { - for(f = 0;f < d;f++) { - b[c + f] = a.get(e + f) - } - } - return d - }; - i.e = j; - return i -}; -s.FS_createLink = function(a, b, c) { - a = S("string" === typeof a ? a : ac(a), b); - return Bb(c, a) -}; -s.FS_createDevice = ec; -U.m = F(12, "void*", E); -wc(W); -Bc.J = F([0], "i8", E); -s.requestFullScreen = function(a, b) { - function c() { - Dc = p; - (document.webkitFullScreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.mozFullscreenElement || document.fullScreenElement || document.fullscreenElement) === d ? (d.Ga = document.cancelFullScreen || document.mozCancelFullScreen || document.webkitCancelFullScreen, d.Ga = d.Ga.bind(document), Gc && d.qa(), Dc = l, Hc && Lc()) : Hc && Mc(); - if(s.onFullScreen) { - s.onFullScreen(Dc) - } - } - Gc = a; - Hc = b; - "undefined" === typeof Gc && (Gc = l); - "undefined" === typeof Hc && (Hc = p); - var d = s.canvas; - Fc || (Fc = l, document.addEventListener("fullscreenchange", c, p), document.addEventListener("mozfullscreenchange", c, p), document.addEventListener("webkitfullscreenchange", c, p)); - d.Ab = d.requestFullScreen || d.mozRequestFullScreen || (d.webkitRequestFullScreen ? function() { - d.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT) - } : m); - d.Ab() -}; -s.requestAnimationFrame = function(a) { - window.requestAnimationFrame || (window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame || window.setTimeout); - window.requestAnimationFrame(a) -}; -s.pauseMainLoop = aa(); -s.resumeMainLoop = function() { - Cc && (Cc = p, m()) -}; -s.getUserMedia = function() { - window.Ma || (window.Ma = navigator.getUserMedia || navigator.mozGetUserMedia); - window.Ma(k) -}; -Sa = u = xa(sa); -Ta = Sa + 5242880; -Ua = z = xa(Ta); -w(Ua < va); -var Vc = F([8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "i8", 3), Wc = F([8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, -2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, -0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0], "i8", 3), Xc = Math.min; -var V = (function(global,env,buffer) { -// EMSCRIPTEN_START_ASM - "use asm"; - var a = new global.Int8Array(buffer); - var b = new global.Int16Array(buffer); - var c = new global.Int32Array(buffer); - var d = new global.Uint8Array(buffer); - var e = new global.Uint16Array(buffer); - var f = new global.Uint32Array(buffer); - var g = new global.Float32Array(buffer); - var h = new global.Float64Array(buffer); - var i = env.STACKTOP | 0; - var j = env.STACK_MAX | 0; - var k = env.tempDoublePtr | 0; - var l = env.ABORT | 0; - var m = env.cttz_i8 | 0; - var n = env.ctlz_i8 | 0; - var o = env._stderr | 0; - var p = env.__ZTVN10__cxxabiv120__si_class_type_infoE | 0; - var q = env.__ZTVN10__cxxabiv117__class_type_infoE | 0; - var r = env.___progname | 0; - var s = +env.NaN; - var t = +env.Infinity; - var u = 0; - var v = 0; - var w = 0; - var x = 0; - var y = 0, z = 0, A = 0, B = 0, C = 0.0, D = 0, E = 0, F = 0, G = 0.0; - var H = 0; - var I = 0; - var J = 0; - var K = 0; - var L = 0; - var M = 0; - var N = 0; - var O = 0; - var P = 0; - var Q = 0; - var R = global.Math.floor; - var S = global.Math.abs; - var T = global.Math.sqrt; - var U = global.Math.pow; - var V = global.Math.cos; - var W = global.Math.sin; - var X = global.Math.tan; - var Y = global.Math.acos; - var Z = global.Math.asin; - var _ = global.Math.atan; - var $ = global.Math.atan2; - var aa = global.Math.exp; - var ab = global.Math.log; - var ac = global.Math.ceil; - var ad = global.Math.imul; - var ae = env.abort; - var af = env.assert; - var ag = env.asmPrintInt; - var ah = env.asmPrintFloat; - var ai = env.min; - var aj = env.invoke_vi; - var ak = env.invoke_vii; - var al = env.invoke_ii; - var am = env.invoke_viii; - var an = env.invoke_v; - var ao = env.invoke_iii; - var ap = env._strncmp; - var aq = env._llvm_va_end; - var ar = env._sysconf; - var as = env.___cxa_throw; - var at = env._strerror; - var au = env._abort; - var av = env._fprintf; - var aw = env._llvm_eh_exception; - var ax = env.___cxa_free_exception; - var ay = env._fflush; - var az = env.___buildEnvironment; - var aA = env.__reallyNegative; - var aB = env._strchr; - var aC = env._fputc; - var aD = env.___setErrNo; - var aE = env._fwrite; - var aF = env._send; - var aG = env._write; - var aH = env._exit; - var aI = env.___cxa_find_matching_catch; - var aJ = env.___cxa_allocate_exception; - var aK = env._isspace; - var aL = env.__formatString; - var aM = env.___resumeException; - var aN = env._llvm_uadd_with_overflow_i32; - var aO = env.___cxa_does_inherit; - var aP = env._getenv; - var aQ = env._vfprintf; - var aR = env.___cxa_begin_catch; - var aS = env.__ZSt18uncaught_exceptionv; - var aT = env._pwrite; - var aU = env.___cxa_call_unexpected; - var aV = env._sbrk; - var aW = env._strerror_r; - var aX = env.___errno_location; - var aY = env.___gxx_personality_v0; - var aZ = env.___cxa_is_number_type; - var a_ = env._time; - var a$ = env.__exit; - var a0 = env.___cxa_end_catch; -// EMSCRIPTEN_START_FUNCS -function a7(a) { - a = a | 0; - var b = 0; - b = i; - i = i + a | 0; - i = i + 7 >> 3 << 3; - return b | 0; -} -function a8() { - return i | 0; -} -function a9(a) { - a = a | 0; - i = a; -} -function ba(a, b) { - a = a | 0; - b = b | 0; - if ((u | 0) == 0) { - u = a; - v = b; - } -} -function bb(b) { - b = b | 0; - a[k] = a[b]; - a[k + 1 | 0] = a[b + 1 | 0]; - a[k + 2 | 0] = a[b + 2 | 0]; - a[k + 3 | 0] = a[b + 3 | 0]; -} -function bc(b) { - b = b | 0; - a[k] = a[b]; - a[k + 1 | 0] = a[b + 1 | 0]; - a[k + 2 | 0] = a[b + 2 | 0]; - a[k + 3 | 0] = a[b + 3 | 0]; - a[k + 4 | 0] = a[b + 4 | 0]; - a[k + 5 | 0] = a[b + 5 | 0]; - a[k + 6 | 0] = a[b + 6 | 0]; - a[k + 7 | 0] = a[b + 7 | 0]; -} -function bd(a) { - a = a | 0; - H = a; -} -function be(a) { - a = a | 0; - I = a; -} -function bf(a) { - a = a | 0; - J = a; -} -function bg(a) { - a = a | 0; - K = a; -} -function bh(a) { - a = a | 0; - L = a; -} -function bi(a) { - a = a | 0; - M = a; -} -function bj(a) { - a = a | 0; - N = a; -} -function bk(a) { - a = a | 0; - O = a; -} -function bl(a) { - a = a | 0; - P = a; -} -function bm(a) { - a = a | 0; - Q = a; -} -function bn() { - c[170] = q + 8; - c[172] = p + 8; - c[176] = p + 8; -} -function bo(b, c, d) { - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0; - if ((d | 0) == 0) { - return; - } else { - e = 0; - } - do { - a[b + e | 0] = a[c + e | 0] | 0; - e = e + 1 | 0; - } while (e >>> 0 < d >>> 0); - return; -} -function bp(b, c, d) { - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0, f = 0; - if ((d | 0) == 0) { - return; - } else { - e = 0; - } - do { - f = b + e | 0; - a[f] = a[f] ^ a[c + e | 0]; - e = e + 1 | 0; - } while (e >>> 0 < d >>> 0); - return; -} -function bq(a) { - a = a | 0; - var b = 0, c = 0, e = 0, f = 0; - b = d[a + 1 | 0] | 0; - c = d[a + 2 | 0] | 0; - e = d[a + 3 | 0] | 0; - f = cN(b << 8 | 0 >>> 24 | (d[a] | 0) | (c << 16 | 0 >>> 16) | (e << 24 | 0 >>> 8) | (0 << 8 | 0 >>> 24), 0 << 8 | b >>> 24 | (0 << 16 | c >>> 16) | (0 << 24 | e >>> 8) | (d[a + 4 | 0] | 0) | ((d[a + 5 | 0] | 0) << 8 | 0 >>> 24), 0 << 16 | 0 >>> 16, (d[a + 6 | 0] | 0) << 16 | 0 >>> 16) | 0; - e = cN(f, H, 0 << 24 | 0 >>> 8, (d[a + 7 | 0] | 0) << 24 | 0 >>> 8) | 0; - return (H = H, e) | 0; -} -function br(a) { - a = a | 0; - return (d[a + 1 | 0] | 0) << 8 | (d[a] | 0) | (d[a + 2 | 0] | 0) << 16 | (d[a + 3 | 0] | 0) << 24 | 0; -} -function bs(b, c) { - b = b | 0; - c = c | 0; - a[b] = c & 255; - a[b + 1 | 0] = c >>> 8 & 255; - a[b + 2 | 0] = c >>> 16 & 255; - a[b + 3 | 0] = c >>> 24 & 255; - return; -} -function bt(a) { - a = a | 0; - c[a + 36 >> 2] = 0; - c[a + 32 >> 2] = 0; - c[a >> 2] = 1779033703; - c[a + 4 >> 2] = -1150833019; - c[a + 8 >> 2] = 1013904242; - c[a + 12 >> 2] = -1521486534; - c[a + 16 >> 2] = 1359893119; - c[a + 20 >> 2] = -1694144372; - c[a + 24 >> 2] = 528734635; - c[a + 28 >> 2] = 1541459225; - return; -} -function bu(a, b, d, e, f, g, h, i, j, k) { - a = a | 0; - b = b | 0; - d = d | 0; - e = e | 0; - f = f | 0; - g = g | 0; - h = h | 0; - i = i | 0; - j = j | 0; - k = k | 0; - var l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0; - l = cX(i, 0, h, 0) | 0; - m = H; - n = 0; - if (m >>> 0 > n >>> 0 | m >>> 0 == n >>> 0 & l >>> 0 > 1073741823 >>> 0) { - c[(aX() | 0) >> 2] = 27; - o = -1; - return o | 0; - } - l = cN(f, g, -1, -1) | 0; - if ((l & f | 0) != 0 | (H & g | 0) != 0 | (f | 0) == 0 & (g | 0) == 0) { - c[(aX() | 0) >> 2] = 22; - o = -1; - return o | 0; - } - do { - if (!((33554431 / (i >>> 0) | 0) >>> 0 < h >>> 0 | h >>> 0 > 16777215)) { - l = 0; - if (l >>> 0 < g >>> 0 | l >>> 0 == g >>> 0 & (33554431 / (h >>> 0) | 0) >>> 0 < f >>> 0) { - break; - } - l = h << 7; - n = bL(ad(l, i) | 0) | 0; - if ((n | 0) == 0) { - o = -1; - return o | 0; - } - m = bL(h << 8) | 0; - do { - if ((m | 0) != 0) { - p = cX(l, 0, f, g) | 0; - q = bL(p) | 0; - if ((q | 0) == 0) { - bM(m); - break; - } - p = ad(i << 7, h) | 0; - bJ(a, b, d, e, 1, 0, n, p); - if ((i | 0) != 0) { - r = h << 7; - s = 0; - do { - bv(n + (ad(r, s) | 0) | 0, h, f, g, q, m); - s = s + 1 | 0; - } while (s >>> 0 < i >>> 0); - } - bJ(a, b, n, p, 1, 0, j, k); - bM(q); - bM(m); - bM(n); - o = 0; - return o | 0; - } - } while (0); - bM(n); - o = -1; - return o | 0; - } - } while (0); - c[(aX() | 0) >> 2] = 12; - o = -1; - return o | 0; -} -function bv(a, b, c, d, e, f) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - e = e | 0; - f = f | 0; - var g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0; - g = b << 7; - h = f + g | 0; - bo(f, a, g); - if ((c | 0) == 0 & (d | 0) == 0) { - bo(a, f, g); - return; - } - i = g; - j = 0; - k = 0; - l = 0; - do { - m = cX(l, k, i, j) | 0; - bo(e + m | 0, f, g); - bw(f, h, b); - l = cN(l, k, 1, 0) | 0; - k = H; - } while (k >>> 0 < d >>> 0 | k >>> 0 == d >>> 0 & l >>> 0 < c >>> 0); - if ((c | 0) == 0 & (d | 0) == 0) { - bo(a, f, g); - return; - } - l = cN(c, d, -1, -1) | 0; - k = H; - j = g; - i = 0; - m = 0; - n = 0; - do { - o = bx(f, b) | 0; - p = cX(o & l, H & k, j, i) | 0; - bp(f, e + p | 0, g); - bw(f, h, b); - n = cN(n, m, 1, 0) | 0; - m = H; - } while (m >>> 0 < d >>> 0 | m >>> 0 == d >>> 0 & n >>> 0 < c >>> 0); - bo(a, f, g); - return; -} -function bw(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, j = 0, k = 0; - d = i; - i = i + 64 | 0; - e = d | 0; - f = c << 1; - bo(e, a + ((c << 7) - 64) | 0, 64); - if ((f | 0) != 0) { - g = 0; - do { - h = g << 6; - bp(e, a + h | 0, 64); - by(e); - bo(b + h | 0, e, 64); - g = g + 1 | 0; - } while (g >>> 0 < f >>> 0); - } - if ((c | 0) == 0) { - i = d; - return; - } else { - j = 0; - } - do { - bo(a + (j << 6) | 0, b + (j << 7) | 0, 64); - j = j + 1 | 0; - } while (j >>> 0 < c >>> 0); - if ((c | 0) == 0) { - i = d; - return; - } else { - k = 0; - } - do { - bo(a + (k + c << 6) | 0, b + (k << 7 | 64) | 0, 64); - k = k + 1 | 0; - } while (k >>> 0 < c >>> 0); - i = d; - return; -} -function bx(a, b) { - a = a | 0; - b = b | 0; - var c = 0; - c = bq(a + ((b << 7) - 64) | 0) | 0; - return (H = H, c) | 0; -} -function by(a) { - a = a | 0; - var b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0, M = 0, N = 0, O = 0, P = 0, Q = 0, R = 0, S = 0, T = 0, U = 0, V = 0, W = 0, X = 0, Y = 0, Z = 0, _ = 0, $ = 0, aa = 0, ab = 0; - b = i; - i = i + 128 | 0; - d = b | 0; - e = b + 64 | 0; - f = 0; - do { - c[d + (f << 2) >> 2] = br(a + (f << 2) | 0) | 0; - f = f + 1 | 0; - } while (f >>> 0 < 16); - f = d; - g = e; - cK(g | 0, f | 0, 64) | 0; - f = e | 0; - g = e + 48 | 0; - h = e + 16 | 0; - j = e + 32 | 0; - k = e + 20 | 0; - l = e + 4 | 0; - m = e + 36 | 0; - n = e + 52 | 0; - o = e + 40 | 0; - p = e + 24 | 0; - q = e + 56 | 0; - r = e + 8 | 0; - s = e + 60 | 0; - t = e + 44 | 0; - u = e + 12 | 0; - v = e + 28 | 0; - w = 0; - x = c[f >> 2] | 0; - y = c[g >> 2] | 0; - z = c[h >> 2] | 0; - A = c[j >> 2] | 0; - B = c[k >> 2] | 0; - C = c[l >> 2] | 0; - D = c[m >> 2] | 0; - E = c[n >> 2] | 0; - F = c[o >> 2] | 0; - G = c[p >> 2] | 0; - H = c[q >> 2] | 0; - I = c[r >> 2] | 0; - J = c[s >> 2] | 0; - K = c[t >> 2] | 0; - L = c[u >> 2] | 0; - M = c[v >> 2] | 0; - do { - N = y + x | 0; - O = (N << 7 | N >>> 25) ^ z; - N = O + x | 0; - P = (N << 9 | N >>> 23) ^ A; - N = P + O | 0; - Q = (N << 13 | N >>> 19) ^ y; - N = Q + P | 0; - R = (N << 18 | N >>> 14) ^ x; - N = C + B | 0; - S = (N << 7 | N >>> 25) ^ D; - N = S + B | 0; - T = (N << 9 | N >>> 23) ^ E; - N = T + S | 0; - U = (N << 13 | N >>> 19) ^ C; - N = U + T | 0; - V = (N << 18 | N >>> 14) ^ B; - N = G + F | 0; - W = (N << 7 | N >>> 25) ^ H; - N = W + F | 0; - X = (N << 9 | N >>> 23) ^ I; - N = X + W | 0; - Y = (N << 13 | N >>> 19) ^ G; - N = Y + X | 0; - Z = (N << 18 | N >>> 14) ^ F; - N = K + J | 0; - _ = (N << 7 | N >>> 25) ^ L; - N = _ + J | 0; - $ = (N << 9 | N >>> 23) ^ M; - N = $ + _ | 0; - aa = (N << 13 | N >>> 19) ^ K; - N = aa + $ | 0; - ab = (N << 18 | N >>> 14) ^ J; - N = _ + R | 0; - C = (N << 7 | N >>> 25) ^ U; - U = C + R | 0; - I = (U << 9 | U >>> 23) ^ X; - X = I + C | 0; - L = (X << 13 | X >>> 19) ^ _; - _ = L + I | 0; - x = (_ << 18 | _ >>> 14) ^ R; - R = O + V | 0; - G = (R << 7 | R >>> 25) ^ Y; - Y = G + V | 0; - M = (Y << 9 | Y >>> 23) ^ $; - $ = M + G | 0; - z = ($ << 13 | $ >>> 19) ^ O; - O = z + M | 0; - B = (O << 18 | O >>> 14) ^ V; - V = S + Z | 0; - K = (V << 7 | V >>> 25) ^ aa; - aa = K + Z | 0; - A = (aa << 9 | aa >>> 23) ^ P; - P = A + K | 0; - D = (P << 13 | P >>> 19) ^ S; - S = D + A | 0; - F = (S << 18 | S >>> 14) ^ Z; - Z = W + ab | 0; - y = (Z << 7 | Z >>> 25) ^ Q; - Q = y + ab | 0; - E = (Q << 9 | Q >>> 23) ^ T; - T = E + y | 0; - H = (T << 13 | T >>> 19) ^ W; - W = H + E | 0; - J = (W << 18 | W >>> 14) ^ ab; - w = w + 2 | 0; - } while (w >>> 0 < 8); - c[f >> 2] = x; - c[g >> 2] = y; - c[h >> 2] = z; - c[j >> 2] = A; - c[k >> 2] = B; - c[l >> 2] = C; - c[m >> 2] = D; - c[n >> 2] = E; - c[o >> 2] = F; - c[p >> 2] = G; - c[q >> 2] = H; - c[r >> 2] = I; - c[s >> 2] = J; - c[t >> 2] = K; - c[u >> 2] = L; - c[v >> 2] = M; - M = d | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e >> 2] | 0); - M = d + 4 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 4 >> 2] | 0); - M = d + 8 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 8 >> 2] | 0); - M = d + 12 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 12 >> 2] | 0); - M = d + 16 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 16 >> 2] | 0); - M = d + 20 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 20 >> 2] | 0); - M = d + 24 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 24 >> 2] | 0); - M = d + 28 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 28 >> 2] | 0); - M = d + 32 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 32 >> 2] | 0); - M = d + 36 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 36 >> 2] | 0); - M = d + 40 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 40 >> 2] | 0); - M = d + 44 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 44 >> 2] | 0); - M = d + 48 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 48 >> 2] | 0); - M = d + 52 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 52 >> 2] | 0); - M = d + 56 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 56 >> 2] | 0); - M = d + 60 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 60 >> 2] | 0); - e = 0; - do { - bs(a + (e << 2) | 0, c[d + (e << 2) >> 2] | 0); - e = e + 1 | 0; - } while (e >>> 0 < 16); - i = b; - return; -} -function bz(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0; - e = a + 32 | 0; - f = a + 36 | 0; - g = c[f >> 2] | 0; - h = g >>> 3 & 63; - i = aN(g | 0, d << 3 | 0) | 0; - c[f >> 2] = i; - if (H) { - i = e | 0; - c[i >> 2] = (c[i >> 2] | 0) + 1; - } - i = e | 0; - c[i >> 2] = (c[i >> 2] | 0) + (d >>> 29); - i = 64 - h | 0; - e = a + 40 + h | 0; - if (i >>> 0 > d >>> 0) { - cK(e | 0, b | 0, d) | 0; - return; - } - cK(e | 0, b | 0, i) | 0; - e = a | 0; - h = a + 40 | 0; - bA(e, h); - a = b + i | 0; - b = d - i | 0; - if (b >>> 0 > 63) { - i = b; - d = a; - while (1) { - bA(e, d); - f = d + 64 | 0; - g = i - 64 | 0; - if (g >>> 0 > 63) { - i = g; - d = f; - } else { - j = g; - k = f; - break; - } - } - } else { - j = b; - k = a; - } - cK(h | 0, k | 0, j) | 0; - return; -} -function bA(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0; - d = i; - i = i + 288 | 0; - e = d | 0; - f = d + 256 | 0; - g = e | 0; - bK(g, b); - b = 16; - do { - h = c[e + (b - 2 << 2) >> 2] | 0; - j = c[e + (b - 15 << 2) >> 2] | 0; - c[e + (b << 2) >> 2] = (c[e + (b - 16 << 2) >> 2] | 0) + (c[e + (b - 7 << 2) >> 2] | 0) + ((h >>> 19 | h << 13) ^ h >>> 10 ^ (h >>> 17 | h << 15)) + ((j >>> 18 | j << 14) ^ j >>> 3 ^ (j >>> 7 | j << 25)); - b = b + 1 | 0; - } while ((b | 0) < 64); - b = f; - j = a; - cK(b | 0, j | 0, 32) | 0; - j = f + 28 | 0; - b = f + 16 | 0; - h = c[b >> 2] | 0; - k = f + 20 | 0; - l = f + 24 | 0; - m = c[l >> 2] | 0; - n = (c[j >> 2] | 0) + 1116352408 + (c[g >> 2] | 0) + ((h >>> 6 | h << 26) ^ (h >>> 11 | h << 21) ^ (h >>> 25 | h << 7)) + ((m ^ c[k >> 2]) & h ^ m) | 0; - m = f | 0; - h = c[m >> 2] | 0; - g = f + 4 | 0; - o = c[g >> 2] | 0; - p = f + 8 | 0; - q = c[p >> 2] | 0; - r = f + 12 | 0; - c[r >> 2] = (c[r >> 2] | 0) + n; - s = ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + n + ((q | o) & h | q & o) | 0; - c[j >> 2] = s; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - h = (c[l >> 2] | 0) + 1899447441 + (c[e + 4 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[l >> 2] = n; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - s = (c[k >> 2] | 0) - 1245643825 + (c[e + 8 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[k >> 2] = h; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - n = (c[b >> 2] | 0) - 373957723 + (c[e + 12 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[b >> 2] = s; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - h = (c[r >> 2] | 0) + 961987163 + (c[e + 16 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[r >> 2] = n; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - s = (c[p >> 2] | 0) + 1508970993 + (c[e + 20 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[p >> 2] = h; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - n = (c[g >> 2] | 0) - 1841331548 + (c[e + 24 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[g >> 2] = s; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - h = (c[m >> 2] | 0) - 1424204075 + (c[e + 28 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[m >> 2] = n; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - s = (c[j >> 2] | 0) - 670586216 + (c[e + 32 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[j >> 2] = h; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - n = (c[l >> 2] | 0) + 310598401 + (c[e + 36 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[l >> 2] = s; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - h = (c[k >> 2] | 0) + 607225278 + (c[e + 40 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[k >> 2] = n; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - s = (c[b >> 2] | 0) + 1426881987 + (c[e + 44 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[b >> 2] = h; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - n = (c[r >> 2] | 0) + 1925078388 + (c[e + 48 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[r >> 2] = s; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - h = (c[p >> 2] | 0) - 2132889090 + (c[e + 52 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[p >> 2] = n; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - s = (c[g >> 2] | 0) - 1680079193 + (c[e + 56 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[g >> 2] = h; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - n = (c[m >> 2] | 0) - 1046744716 + (c[e + 60 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[m >> 2] = s; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - h = (c[j >> 2] | 0) - 459576895 + (c[e + 64 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[j >> 2] = n; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - s = (c[l >> 2] | 0) - 272742522 + (c[e + 68 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[l >> 2] = h; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - n = (c[k >> 2] | 0) + 264347078 + (c[e + 72 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[k >> 2] = s; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - h = (c[b >> 2] | 0) + 604807628 + (c[e + 76 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[b >> 2] = n; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - s = (c[r >> 2] | 0) + 770255983 + (c[e + 80 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[r >> 2] = h; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - n = (c[p >> 2] | 0) + 1249150122 + (c[e + 84 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[p >> 2] = s; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - h = (c[g >> 2] | 0) + 1555081692 + (c[e + 88 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[g >> 2] = n; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - s = (c[m >> 2] | 0) + 1996064986 + (c[e + 92 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[m >> 2] = h; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - n = (c[j >> 2] | 0) - 1740746414 + (c[e + 96 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[j >> 2] = s; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - h = (c[l >> 2] | 0) - 1473132947 + (c[e + 100 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[l >> 2] = n; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - s = (c[k >> 2] | 0) - 1341970488 + (c[e + 104 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[k >> 2] = h; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - n = (c[b >> 2] | 0) - 1084653625 + (c[e + 108 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[b >> 2] = s; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - h = (c[r >> 2] | 0) - 958395405 + (c[e + 112 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[r >> 2] = n; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - s = (c[p >> 2] | 0) - 710438585 + (c[e + 116 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[p >> 2] = h; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - n = (c[g >> 2] | 0) + 113926993 + (c[e + 120 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[g >> 2] = s; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - h = (c[m >> 2] | 0) + 338241895 + (c[e + 124 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[m >> 2] = n; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - s = (c[j >> 2] | 0) + 666307205 + (c[e + 128 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[j >> 2] = h; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - n = (c[l >> 2] | 0) + 773529912 + (c[e + 132 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[l >> 2] = s; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - h = (c[k >> 2] | 0) + 1294757372 + (c[e + 136 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[k >> 2] = n; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - s = (c[b >> 2] | 0) + 1396182291 + (c[e + 140 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[b >> 2] = h; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - n = (c[r >> 2] | 0) + 1695183700 + (c[e + 144 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[r >> 2] = s; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - h = (c[p >> 2] | 0) + 1986661051 + (c[e + 148 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[p >> 2] = n; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - s = (c[g >> 2] | 0) - 2117940946 + (c[e + 152 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[g >> 2] = h; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - n = (c[m >> 2] | 0) - 1838011259 + (c[e + 156 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[m >> 2] = s; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - h = (c[j >> 2] | 0) - 1564481375 + (c[e + 160 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[j >> 2] = n; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - s = (c[l >> 2] | 0) - 1474664885 + (c[e + 164 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[l >> 2] = h; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - n = (c[k >> 2] | 0) - 1035236496 + (c[e + 168 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[k >> 2] = s; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - h = (c[b >> 2] | 0) - 949202525 + (c[e + 172 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[b >> 2] = n; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - s = (c[r >> 2] | 0) - 778901479 + (c[e + 176 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[r >> 2] = h; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - n = (c[p >> 2] | 0) - 694614492 + (c[e + 180 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[p >> 2] = s; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - h = (c[g >> 2] | 0) - 200395387 + (c[e + 184 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[g >> 2] = n; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - s = (c[m >> 2] | 0) + 275423344 + (c[e + 188 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[m >> 2] = h; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - n = (c[j >> 2] | 0) + 430227734 + (c[e + 192 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[j >> 2] = s; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - h = (c[l >> 2] | 0) + 506948616 + (c[e + 196 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[l >> 2] = n; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - s = (c[k >> 2] | 0) + 659060556 + (c[e + 200 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[k >> 2] = h; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - n = (c[b >> 2] | 0) + 883997877 + (c[e + 204 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[b >> 2] = s; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - h = (c[r >> 2] | 0) + 958139571 + (c[e + 208 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[r >> 2] = n; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - s = (c[p >> 2] | 0) + 1322822218 + (c[e + 212 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[p >> 2] = h; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - n = (c[g >> 2] | 0) + 1537002063 + (c[e + 216 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[g >> 2] = s; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - h = (c[m >> 2] | 0) + 1747873779 + (c[e + 220 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[m >> 2] = n; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - s = (c[j >> 2] | 0) + 1955562222 + (c[e + 224 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[j >> 2] = h; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - n = (c[l >> 2] | 0) + 2024104815 + (c[e + 228 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[l >> 2] = s; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - h = (c[k >> 2] | 0) - 2067236844 + (c[e + 232 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[k >> 2] = n; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - s = (c[b >> 2] | 0) - 1933114872 + (c[e + 236 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[b >> 2] = h; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - n = (c[r >> 2] | 0) - 1866530822 + (c[e + 240 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[r >> 2] = s; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - h = (c[p >> 2] | 0) - 1538233109 + (c[e + 244 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[p >> 2] = n; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - s = (c[g >> 2] | 0) - 1090935817 + (c[e + 248 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[g >> 2] = h; - g = c[k >> 2] | 0; - k = c[j >> 2] | 0; - j = (c[m >> 2] | 0) - 965641998 + (c[e + 252 >> 2] | 0) + ((g >>> 6 | g << 26) ^ (g >>> 11 | g << 21) ^ (g >>> 25 | g << 7)) + ((k ^ c[l >> 2]) & g ^ k) | 0; - k = c[p >> 2] | 0; - p = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + j; - b = j + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((p | k) & h | p & k) | 0; - c[m >> 2] = b; - c[a >> 2] = (c[a >> 2] | 0) + b; - b = a + 4 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 4 >> 2] | 0); - b = a + 8 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 8 >> 2] | 0); - b = a + 12 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 12 >> 2] | 0); - b = a + 16 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 16 >> 2] | 0); - b = a + 20 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 20 >> 2] | 0); - b = a + 24 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 24 >> 2] | 0); - b = a + 28 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 28 >> 2] | 0); - i = d; - return; -} -function bB(b, c) { - b = b | 0; - c = c | 0; - a[b + 3 | 0] = c & 255; - a[b + 2 | 0] = c >>> 8 & 255; - a[b + 1 | 0] = c >>> 16 & 255; - a[b] = c >>> 24 & 255; - return; -} -function bC(a) { - a = a | 0; - return (d[a + 2 | 0] | 0) << 8 | (d[a + 3 | 0] | 0) | (d[a + 1 | 0] | 0) << 16 | (d[a] | 0) << 24 | 0; -} -function bD(a, b) { - a = a | 0; - b = b | 0; - bE(b); - bF(a, b | 0, 32); - cL(b | 0, 0, 104); - return; -} -function bE(a) { - a = a | 0; - var b = 0, d = 0, e = 0; - b = i; - i = i + 8 | 0; - d = b | 0; - bF(d, a + 32 | 0, 8); - e = (c[a + 36 >> 2] | 0) >>> 3 & 63; - bz(a, 720, (e >>> 0 < 56 ? 56 : 120) - e | 0); - bz(a, d, 8); - i = b; - return; -} -function bF(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0; - e = d >>> 2; - if ((e | 0) == 0) { - return; - } else { - f = 0; - } - do { - bB(a + (f << 2) | 0, c[b + (f << 2) >> 2] | 0); - f = f + 1 | 0; - } while (f >>> 0 < e >>> 0); - return; -} -function bG(b, c, d) { - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0, f = 0, g = 0, h = 0, j = 0, k = 0, l = 0; - e = i; - i = i + 96 | 0; - f = e | 0; - if (d >>> 0 > 64) { - g = b | 0; - bt(g); - bz(g, c, d); - h = e + 64 | 0; - bD(h, g); - j = h; - k = 32; - } else { - j = c; - k = d; - } - d = b | 0; - bt(d); - c = f | 0; - cL(c | 0, 54, 64); - if ((k | 0) != 0) { - h = 0; - do { - g = f + h | 0; - a[g] = a[g] ^ a[j + h | 0]; - h = h + 1 | 0; - } while (h >>> 0 < k >>> 0); - } - bz(d, c, 64); - d = b + 104 | 0; - bt(d); - cL(c | 0, 92, 64); - if ((k | 0) == 0) { - bz(d, c, 64); - i = e; - return; - } else { - l = 0; - } - do { - b = f + l | 0; - a[b] = a[b] ^ a[j + l | 0]; - l = l + 1 | 0; - } while (l >>> 0 < k >>> 0); - bz(d, c, 64); - i = e; - return; -} -function bH(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - bz(a | 0, b, c); - return; -} -function bI(a, b) { - a = a | 0; - b = b | 0; - var c = 0, d = 0, e = 0; - c = i; - i = i + 32 | 0; - d = c | 0; - bD(d, b | 0); - e = b + 104 | 0; - bz(e, d, 32); - bD(a, e); - i = c; - return; -} -function bJ(b, c, d, e, f, g, h, j) { - b = b | 0; - c = c | 0; - d = d | 0; - e = e | 0; - f = f | 0; - g = g | 0; - h = h | 0; - j = j | 0; - var k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0; - k = i; - i = i + 488 | 0; - l = k | 0; - m = k + 208 | 0; - n = k + 424 | 0; - o = k + 456 | 0; - bG(l, b, c); - bH(l, d, e); - if ((j | 0) == 0) { - i = k; - return; - } - e = k + 416 | 0; - d = m; - p = l; - l = n | 0; - q = o | 0; - r = 0; - s = g >>> 0 < r >>> 0 | g >>> 0 == r >>> 0 & f >>> 0 < 2 >>> 0; - r = 0; - t = 0; - do { - r = r + 1 | 0; - bB(e, r); - cK(d | 0, p | 0, 208) | 0; - bH(m, e, 4); - bI(l, m); - cK(q | 0, l | 0, 32) | 0; - if (!s) { - u = 0; - v = 2; - do { - bG(m, b, c); - bH(m, l, 32); - bI(l, m); - w = 0; - do { - x = o + w | 0; - a[x] = a[x] ^ a[n + w | 0]; - w = w + 1 | 0; - } while ((w | 0) < 32); - v = cN(v, u, 1, 0) | 0; - u = H; - } while (!(u >>> 0 > g >>> 0 | u >>> 0 == g >>> 0 & v >>> 0 > f >>> 0)); - } - v = j - t | 0; - u = v >>> 0 > 32 ? 32 : v; - v = h + t | 0; - cK(v | 0, q | 0, u) | 0; - t = r << 5; - } while (t >>> 0 < j >>> 0); - i = k; - return; -} -function bK(a, b) { - a = a | 0; - b = b | 0; - var d = 0; - d = 0; - do { - c[a + (d << 2) >> 2] = bC(b + (d << 2) | 0) | 0; - d = d + 1 | 0; - } while (d >>> 0 < 16); - return; -} -function bL(a) { - a = a | 0; - var b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0, M = 0, N = 0, O = 0, P = 0, Q = 0, R = 0, S = 0, T = 0, U = 0, V = 0, W = 0, X = 0, Y = 0, Z = 0, _ = 0, $ = 0, aa = 0, ab = 0, ac = 0, ad = 0, ae = 0, af = 0, ag = 0, ah = 0, ai = 0, aj = 0, ak = 0, al = 0, am = 0, an = 0, ao = 0, ap = 0, aq = 0, as = 0, at = 0, av = 0, aw = 0, ax = 0, ay = 0, az = 0, aA = 0, aB = 0, aC = 0, aD = 0, aE = 0, aF = 0, aG = 0, aH = 0, aI = 0; - do { - if (a >>> 0 < 245) { - if (a >>> 0 < 11) { - b = 16; - } else { - b = a + 11 & -8; - } - d = b >>> 3; - e = c[208] | 0; - f = e >>> (d >>> 0); - if ((f & 3 | 0) != 0) { - g = (f & 1 ^ 1) + d | 0; - h = g << 1; - i = 872 + (h << 2) | 0; - j = 872 + (h + 2 << 2) | 0; - h = c[j >> 2] | 0; - k = h + 8 | 0; - l = c[k >> 2] | 0; - do { - if ((i | 0) == (l | 0)) { - c[208] = e & ~(1 << g); - } else { - if (l >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - m = l + 12 | 0; - if ((c[m >> 2] | 0) == (h | 0)) { - c[m >> 2] = i; - c[j >> 2] = l; - break; - } else { - au(); - return 0; - } - } - } while (0); - l = g << 3; - c[h + 4 >> 2] = l | 3; - j = h + (l | 4) | 0; - c[j >> 2] = c[j >> 2] | 1; - n = k; - return n | 0; - } - if (b >>> 0 <= (c[210] | 0) >>> 0) { - o = b; - break; - } - if ((f | 0) != 0) { - j = 2 << d; - l = f << d & (j | -j); - j = (l & -l) - 1 | 0; - l = j >>> 12 & 16; - i = j >>> (l >>> 0); - j = i >>> 5 & 8; - m = i >>> (j >>> 0); - i = m >>> 2 & 4; - p = m >>> (i >>> 0); - m = p >>> 1 & 2; - q = p >>> (m >>> 0); - p = q >>> 1 & 1; - r = (j | l | i | m | p) + (q >>> (p >>> 0)) | 0; - p = r << 1; - q = 872 + (p << 2) | 0; - m = 872 + (p + 2 << 2) | 0; - p = c[m >> 2] | 0; - i = p + 8 | 0; - l = c[i >> 2] | 0; - do { - if ((q | 0) == (l | 0)) { - c[208] = e & ~(1 << r); - } else { - if (l >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - j = l + 12 | 0; - if ((c[j >> 2] | 0) == (p | 0)) { - c[j >> 2] = q; - c[m >> 2] = l; - break; - } else { - au(); - return 0; - } - } - } while (0); - l = r << 3; - m = l - b | 0; - c[p + 4 >> 2] = b | 3; - q = p; - e = q + b | 0; - c[q + (b | 4) >> 2] = m | 1; - c[q + l >> 2] = m; - l = c[210] | 0; - if ((l | 0) != 0) { - q = c[213] | 0; - d = l >>> 3; - l = d << 1; - f = 872 + (l << 2) | 0; - k = c[208] | 0; - h = 1 << d; - do { - if ((k & h | 0) == 0) { - c[208] = k | h; - s = f; - t = 872 + (l + 2 << 2) | 0; - } else { - d = 872 + (l + 2 << 2) | 0; - g = c[d >> 2] | 0; - if (g >>> 0 >= (c[212] | 0) >>> 0) { - s = g; - t = d; - break; - } - au(); - return 0; - } - } while (0); - c[t >> 2] = q; - c[s + 12 >> 2] = q; - c[q + 8 >> 2] = s; - c[q + 12 >> 2] = f; - } - c[210] = m; - c[213] = e; - n = i; - return n | 0; - } - l = c[209] | 0; - if ((l | 0) == 0) { - o = b; - break; - } - h = (l & -l) - 1 | 0; - l = h >>> 12 & 16; - k = h >>> (l >>> 0); - h = k >>> 5 & 8; - p = k >>> (h >>> 0); - k = p >>> 2 & 4; - r = p >>> (k >>> 0); - p = r >>> 1 & 2; - d = r >>> (p >>> 0); - r = d >>> 1 & 1; - g = c[1136 + ((h | l | k | p | r) + (d >>> (r >>> 0)) << 2) >> 2] | 0; - r = g; - d = g; - p = (c[g + 4 >> 2] & -8) - b | 0; - while (1) { - g = c[r + 16 >> 2] | 0; - if ((g | 0) == 0) { - k = c[r + 20 >> 2] | 0; - if ((k | 0) == 0) { - break; - } else { - u = k; - } - } else { - u = g; - } - g = (c[u + 4 >> 2] & -8) - b | 0; - k = g >>> 0 < p >>> 0; - r = u; - d = k ? u : d; - p = k ? g : p; - } - r = d; - i = c[212] | 0; - if (r >>> 0 < i >>> 0) { - au(); - return 0; - } - e = r + b | 0; - m = e; - if (r >>> 0 >= e >>> 0) { - au(); - return 0; - } - e = c[d + 24 >> 2] | 0; - f = c[d + 12 >> 2] | 0; - do { - if ((f | 0) == (d | 0)) { - q = d + 20 | 0; - g = c[q >> 2] | 0; - if ((g | 0) == 0) { - k = d + 16 | 0; - l = c[k >> 2] | 0; - if ((l | 0) == 0) { - v = 0; - break; - } else { - w = l; - x = k; - } - } else { - w = g; - x = q; - } - while (1) { - q = w + 20 | 0; - g = c[q >> 2] | 0; - if ((g | 0) != 0) { - w = g; - x = q; - continue; - } - q = w + 16 | 0; - g = c[q >> 2] | 0; - if ((g | 0) == 0) { - break; - } else { - w = g; - x = q; - } - } - if (x >>> 0 < i >>> 0) { - au(); - return 0; - } else { - c[x >> 2] = 0; - v = w; - break; - } - } else { - q = c[d + 8 >> 2] | 0; - if (q >>> 0 < i >>> 0) { - au(); - return 0; - } - g = q + 12 | 0; - if ((c[g >> 2] | 0) != (d | 0)) { - au(); - return 0; - } - k = f + 8 | 0; - if ((c[k >> 2] | 0) == (d | 0)) { - c[g >> 2] = f; - c[k >> 2] = q; - v = f; - break; - } else { - au(); - return 0; - } - } - } while (0); - L223 : do { - if ((e | 0) != 0) { - f = d + 28 | 0; - i = 1136 + (c[f >> 2] << 2) | 0; - do { - if ((d | 0) == (c[i >> 2] | 0)) { - c[i >> 2] = v; - if ((v | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[f >> 2]); - break L223; - } else { - if (e >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - q = e + 16 | 0; - if ((c[q >> 2] | 0) == (d | 0)) { - c[q >> 2] = v; - } else { - c[e + 20 >> 2] = v; - } - if ((v | 0) == 0) { - break L223; - } - } - } while (0); - if (v >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - c[v + 24 >> 2] = e; - f = c[d + 16 >> 2] | 0; - do { - if ((f | 0) != 0) { - if (f >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[v + 16 >> 2] = f; - c[f + 24 >> 2] = v; - break; - } - } - } while (0); - f = c[d + 20 >> 2] | 0; - if ((f | 0) == 0) { - break; - } - if (f >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[v + 20 >> 2] = f; - c[f + 24 >> 2] = v; - break; - } - } - } while (0); - if (p >>> 0 < 16) { - e = p + b | 0; - c[d + 4 >> 2] = e | 3; - f = r + (e + 4) | 0; - c[f >> 2] = c[f >> 2] | 1; - } else { - c[d + 4 >> 2] = b | 3; - c[r + (b | 4) >> 2] = p | 1; - c[r + (p + b) >> 2] = p; - f = c[210] | 0; - if ((f | 0) != 0) { - e = c[213] | 0; - i = f >>> 3; - f = i << 1; - q = 872 + (f << 2) | 0; - k = c[208] | 0; - g = 1 << i; - do { - if ((k & g | 0) == 0) { - c[208] = k | g; - y = q; - z = 872 + (f + 2 << 2) | 0; - } else { - i = 872 + (f + 2 << 2) | 0; - l = c[i >> 2] | 0; - if (l >>> 0 >= (c[212] | 0) >>> 0) { - y = l; - z = i; - break; - } - au(); - return 0; - } - } while (0); - c[z >> 2] = e; - c[y + 12 >> 2] = e; - c[e + 8 >> 2] = y; - c[e + 12 >> 2] = q; - } - c[210] = p; - c[213] = m; - } - f = d + 8 | 0; - if ((f | 0) == 0) { - o = b; - break; - } else { - n = f; - } - return n | 0; - } else { - if (a >>> 0 > 4294967231) { - o = -1; - break; - } - f = a + 11 | 0; - g = f & -8; - k = c[209] | 0; - if ((k | 0) == 0) { - o = g; - break; - } - r = -g | 0; - i = f >>> 8; - do { - if ((i | 0) == 0) { - A = 0; - } else { - if (g >>> 0 > 16777215) { - A = 31; - break; - } - f = (i + 1048320 | 0) >>> 16 & 8; - l = i << f; - h = (l + 520192 | 0) >>> 16 & 4; - j = l << h; - l = (j + 245760 | 0) >>> 16 & 2; - B = 14 - (h | f | l) + (j << l >>> 15) | 0; - A = g >>> ((B + 7 | 0) >>> 0) & 1 | B << 1; - } - } while (0); - i = c[1136 + (A << 2) >> 2] | 0; - L271 : do { - if ((i | 0) == 0) { - C = 0; - D = r; - E = 0; - } else { - if ((A | 0) == 31) { - F = 0; - } else { - F = 25 - (A >>> 1) | 0; - } - d = 0; - m = r; - p = i; - q = g << F; - e = 0; - while (1) { - B = c[p + 4 >> 2] & -8; - l = B - g | 0; - if (l >>> 0 < m >>> 0) { - if ((B | 0) == (g | 0)) { - C = p; - D = l; - E = p; - break L271; - } else { - G = p; - H = l; - } - } else { - G = d; - H = m; - } - l = c[p + 20 >> 2] | 0; - B = c[p + 16 + (q >>> 31 << 2) >> 2] | 0; - j = (l | 0) == 0 | (l | 0) == (B | 0) ? e : l; - if ((B | 0) == 0) { - C = G; - D = H; - E = j; - break; - } else { - d = G; - m = H; - p = B; - q = q << 1; - e = j; - } - } - } - } while (0); - if ((E | 0) == 0 & (C | 0) == 0) { - i = 2 << A; - r = k & (i | -i); - if ((r | 0) == 0) { - o = g; - break; - } - i = (r & -r) - 1 | 0; - r = i >>> 12 & 16; - e = i >>> (r >>> 0); - i = e >>> 5 & 8; - q = e >>> (i >>> 0); - e = q >>> 2 & 4; - p = q >>> (e >>> 0); - q = p >>> 1 & 2; - m = p >>> (q >>> 0); - p = m >>> 1 & 1; - I = c[1136 + ((i | r | e | q | p) + (m >>> (p >>> 0)) << 2) >> 2] | 0; - } else { - I = E; - } - if ((I | 0) == 0) { - J = D; - K = C; - } else { - p = I; - m = D; - q = C; - while (1) { - e = (c[p + 4 >> 2] & -8) - g | 0; - r = e >>> 0 < m >>> 0; - i = r ? e : m; - e = r ? p : q; - r = c[p + 16 >> 2] | 0; - if ((r | 0) != 0) { - p = r; - m = i; - q = e; - continue; - } - r = c[p + 20 >> 2] | 0; - if ((r | 0) == 0) { - J = i; - K = e; - break; - } else { - p = r; - m = i; - q = e; - } - } - } - if ((K | 0) == 0) { - o = g; - break; - } - if (J >>> 0 >= ((c[210] | 0) - g | 0) >>> 0) { - o = g; - break; - } - q = K; - m = c[212] | 0; - if (q >>> 0 < m >>> 0) { - au(); - return 0; - } - p = q + g | 0; - k = p; - if (q >>> 0 >= p >>> 0) { - au(); - return 0; - } - e = c[K + 24 >> 2] | 0; - i = c[K + 12 >> 2] | 0; - do { - if ((i | 0) == (K | 0)) { - r = K + 20 | 0; - d = c[r >> 2] | 0; - if ((d | 0) == 0) { - j = K + 16 | 0; - B = c[j >> 2] | 0; - if ((B | 0) == 0) { - L = 0; - break; - } else { - M = B; - N = j; - } - } else { - M = d; - N = r; - } - while (1) { - r = M + 20 | 0; - d = c[r >> 2] | 0; - if ((d | 0) != 0) { - M = d; - N = r; - continue; - } - r = M + 16 | 0; - d = c[r >> 2] | 0; - if ((d | 0) == 0) { - break; - } else { - M = d; - N = r; - } - } - if (N >>> 0 < m >>> 0) { - au(); - return 0; - } else { - c[N >> 2] = 0; - L = M; - break; - } - } else { - r = c[K + 8 >> 2] | 0; - if (r >>> 0 < m >>> 0) { - au(); - return 0; - } - d = r + 12 | 0; - if ((c[d >> 2] | 0) != (K | 0)) { - au(); - return 0; - } - j = i + 8 | 0; - if ((c[j >> 2] | 0) == (K | 0)) { - c[d >> 2] = i; - c[j >> 2] = r; - L = i; - break; - } else { - au(); - return 0; - } - } - } while (0); - L321 : do { - if ((e | 0) != 0) { - i = K + 28 | 0; - m = 1136 + (c[i >> 2] << 2) | 0; - do { - if ((K | 0) == (c[m >> 2] | 0)) { - c[m >> 2] = L; - if ((L | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[i >> 2]); - break L321; - } else { - if (e >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - r = e + 16 | 0; - if ((c[r >> 2] | 0) == (K | 0)) { - c[r >> 2] = L; - } else { - c[e + 20 >> 2] = L; - } - if ((L | 0) == 0) { - break L321; - } - } - } while (0); - if (L >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - c[L + 24 >> 2] = e; - i = c[K + 16 >> 2] | 0; - do { - if ((i | 0) != 0) { - if (i >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[L + 16 >> 2] = i; - c[i + 24 >> 2] = L; - break; - } - } - } while (0); - i = c[K + 20 >> 2] | 0; - if ((i | 0) == 0) { - break; - } - if (i >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[L + 20 >> 2] = i; - c[i + 24 >> 2] = L; - break; - } - } - } while (0); - do { - if (J >>> 0 < 16) { - e = J + g | 0; - c[K + 4 >> 2] = e | 3; - i = q + (e + 4) | 0; - c[i >> 2] = c[i >> 2] | 1; - } else { - c[K + 4 >> 2] = g | 3; - c[q + (g | 4) >> 2] = J | 1; - c[q + (J + g) >> 2] = J; - i = J >>> 3; - if (J >>> 0 < 256) { - e = i << 1; - m = 872 + (e << 2) | 0; - r = c[208] | 0; - j = 1 << i; - do { - if ((r & j | 0) == 0) { - c[208] = r | j; - O = m; - P = 872 + (e + 2 << 2) | 0; - } else { - i = 872 + (e + 2 << 2) | 0; - d = c[i >> 2] | 0; - if (d >>> 0 >= (c[212] | 0) >>> 0) { - O = d; - P = i; - break; - } - au(); - return 0; - } - } while (0); - c[P >> 2] = k; - c[O + 12 >> 2] = k; - c[q + (g + 8) >> 2] = O; - c[q + (g + 12) >> 2] = m; - break; - } - e = p; - j = J >>> 8; - do { - if ((j | 0) == 0) { - Q = 0; - } else { - if (J >>> 0 > 16777215) { - Q = 31; - break; - } - r = (j + 1048320 | 0) >>> 16 & 8; - i = j << r; - d = (i + 520192 | 0) >>> 16 & 4; - B = i << d; - i = (B + 245760 | 0) >>> 16 & 2; - l = 14 - (d | r | i) + (B << i >>> 15) | 0; - Q = J >>> ((l + 7 | 0) >>> 0) & 1 | l << 1; - } - } while (0); - j = 1136 + (Q << 2) | 0; - c[q + (g + 28) >> 2] = Q; - c[q + (g + 20) >> 2] = 0; - c[q + (g + 16) >> 2] = 0; - m = c[209] | 0; - l = 1 << Q; - if ((m & l | 0) == 0) { - c[209] = m | l; - c[j >> 2] = e; - c[q + (g + 24) >> 2] = j; - c[q + (g + 12) >> 2] = e; - c[q + (g + 8) >> 2] = e; - break; - } - if ((Q | 0) == 31) { - R = 0; - } else { - R = 25 - (Q >>> 1) | 0; - } - l = J << R; - m = c[j >> 2] | 0; - while (1) { - if ((c[m + 4 >> 2] & -8 | 0) == (J | 0)) { - break; - } - S = m + 16 + (l >>> 31 << 2) | 0; - j = c[S >> 2] | 0; - if ((j | 0) == 0) { - T = 262; - break; - } else { - l = l << 1; - m = j; - } - } - if ((T | 0) == 262) { - if (S >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[S >> 2] = e; - c[q + (g + 24) >> 2] = m; - c[q + (g + 12) >> 2] = e; - c[q + (g + 8) >> 2] = e; - break; - } - } - l = m + 8 | 0; - j = c[l >> 2] | 0; - i = c[212] | 0; - if (m >>> 0 < i >>> 0) { - au(); - return 0; - } - if (j >>> 0 < i >>> 0) { - au(); - return 0; - } else { - c[j + 12 >> 2] = e; - c[l >> 2] = e; - c[q + (g + 8) >> 2] = j; - c[q + (g + 12) >> 2] = m; - c[q + (g + 24) >> 2] = 0; - break; - } - } - } while (0); - q = K + 8 | 0; - if ((q | 0) == 0) { - o = g; - break; - } else { - n = q; - } - return n | 0; - } - } while (0); - K = c[210] | 0; - if (o >>> 0 <= K >>> 0) { - S = K - o | 0; - J = c[213] | 0; - if (S >>> 0 > 15) { - R = J; - c[213] = R + o; - c[210] = S; - c[R + (o + 4) >> 2] = S | 1; - c[R + K >> 2] = S; - c[J + 4 >> 2] = o | 3; - } else { - c[210] = 0; - c[213] = 0; - c[J + 4 >> 2] = K | 3; - S = J + (K + 4) | 0; - c[S >> 2] = c[S >> 2] | 1; - } - n = J + 8 | 0; - return n | 0; - } - J = c[211] | 0; - if (o >>> 0 < J >>> 0) { - S = J - o | 0; - c[211] = S; - J = c[214] | 0; - K = J; - c[214] = K + o; - c[K + (o + 4) >> 2] = S | 1; - c[J + 4 >> 2] = o | 3; - n = J + 8 | 0; - return n | 0; - } - do { - if ((c[200] | 0) == 0) { - J = ar(8) | 0; - if ((J - 1 & J | 0) == 0) { - c[202] = J; - c[201] = J; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - return 0; - } - } - } while (0); - J = o + 48 | 0; - S = c[202] | 0; - K = o + 47 | 0; - R = S + K | 0; - Q = -S | 0; - S = R & Q; - if (S >>> 0 <= o >>> 0) { - n = 0; - return n | 0; - } - O = c[318] | 0; - do { - if ((O | 0) != 0) { - P = c[316] | 0; - L = P + S | 0; - if (L >>> 0 <= P >>> 0 | L >>> 0 > O >>> 0) { - n = 0; - } else { - break; - } - return n | 0; - } - } while (0); - L413 : do { - if ((c[319] & 4 | 0) == 0) { - O = c[214] | 0; - L415 : do { - if ((O | 0) == 0) { - T = 292; - } else { - L = O; - P = 1280; - while (1) { - U = P | 0; - M = c[U >> 2] | 0; - if (M >>> 0 <= L >>> 0) { - V = P + 4 | 0; - if ((M + (c[V >> 2] | 0) | 0) >>> 0 > L >>> 0) { - break; - } - } - M = c[P + 8 >> 2] | 0; - if ((M | 0) == 0) { - T = 292; - break L415; - } else { - P = M; - } - } - if ((P | 0) == 0) { - T = 292; - break; - } - L = R - (c[211] | 0) & Q; - if (L >>> 0 >= 2147483647) { - W = 0; - break; - } - m = aV(L | 0) | 0; - e = (m | 0) == ((c[U >> 2] | 0) + (c[V >> 2] | 0) | 0); - X = e ? m : -1; - Y = e ? L : 0; - Z = m; - _ = L; - T = 301; - } - } while (0); - do { - if ((T | 0) == 292) { - O = aV(0) | 0; - if ((O | 0) == -1) { - W = 0; - break; - } - g = O; - L = c[201] | 0; - m = L - 1 | 0; - if ((m & g | 0) == 0) { - $ = S; - } else { - $ = S - g + (m + g & -L) | 0; - } - L = c[316] | 0; - g = L + $ | 0; - if (!($ >>> 0 > o >>> 0 & $ >>> 0 < 2147483647)) { - W = 0; - break; - } - m = c[318] | 0; - if ((m | 0) != 0) { - if (g >>> 0 <= L >>> 0 | g >>> 0 > m >>> 0) { - W = 0; - break; - } - } - m = aV($ | 0) | 0; - g = (m | 0) == (O | 0); - X = g ? O : -1; - Y = g ? $ : 0; - Z = m; - _ = $; - T = 301; - } - } while (0); - L435 : do { - if ((T | 0) == 301) { - m = -_ | 0; - if ((X | 0) != -1) { - aa = Y; - ab = X; - T = 312; - break L413; - } - do { - if ((Z | 0) != -1 & _ >>> 0 < 2147483647 & _ >>> 0 < J >>> 0) { - g = c[202] | 0; - O = K - _ + g & -g; - if (O >>> 0 >= 2147483647) { - ac = _; - break; - } - if ((aV(O | 0) | 0) == -1) { - aV(m | 0) | 0; - W = Y; - break L435; - } else { - ac = O + _ | 0; - break; - } - } else { - ac = _; - } - } while (0); - if ((Z | 0) == -1) { - W = Y; - } else { - aa = ac; - ab = Z; - T = 312; - break L413; - } - } - } while (0); - c[319] = c[319] | 4; - ad = W; - T = 309; - } else { - ad = 0; - T = 309; - } - } while (0); - do { - if ((T | 0) == 309) { - if (S >>> 0 >= 2147483647) { - break; - } - W = aV(S | 0) | 0; - Z = aV(0) | 0; - if (!((Z | 0) != -1 & (W | 0) != -1 & W >>> 0 < Z >>> 0)) { - break; - } - ac = Z - W | 0; - Z = ac >>> 0 > (o + 40 | 0) >>> 0; - Y = Z ? W : -1; - if ((Y | 0) != -1) { - aa = Z ? ac : ad; - ab = Y; - T = 312; - } - } - } while (0); - do { - if ((T | 0) == 312) { - ad = (c[316] | 0) + aa | 0; - c[316] = ad; - if (ad >>> 0 > (c[317] | 0) >>> 0) { - c[317] = ad; - } - ad = c[214] | 0; - L455 : do { - if ((ad | 0) == 0) { - S = c[212] | 0; - if ((S | 0) == 0 | ab >>> 0 < S >>> 0) { - c[212] = ab; - } - c[320] = ab; - c[321] = aa; - c[323] = 0; - c[217] = c[200]; - c[216] = -1; - S = 0; - do { - Y = S << 1; - ac = 872 + (Y << 2) | 0; - c[872 + (Y + 3 << 2) >> 2] = ac; - c[872 + (Y + 2 << 2) >> 2] = ac; - S = S + 1 | 0; - } while (S >>> 0 < 32); - S = ab + 8 | 0; - if ((S & 7 | 0) == 0) { - ae = 0; - } else { - ae = -S & 7; - } - S = aa - 40 - ae | 0; - c[214] = ab + ae; - c[211] = S; - c[ab + (ae + 4) >> 2] = S | 1; - c[ab + (aa - 36) >> 2] = 40; - c[215] = c[204]; - } else { - S = 1280; - while (1) { - af = c[S >> 2] | 0; - ag = S + 4 | 0; - ah = c[ag >> 2] | 0; - if ((ab | 0) == (af + ah | 0)) { - T = 324; - break; - } - ac = c[S + 8 >> 2] | 0; - if ((ac | 0) == 0) { - break; - } else { - S = ac; - } - } - do { - if ((T | 0) == 324) { - if ((c[S + 12 >> 2] & 8 | 0) != 0) { - break; - } - ac = ad; - if (!(ac >>> 0 >= af >>> 0 & ac >>> 0 < ab >>> 0)) { - break; - } - c[ag >> 2] = ah + aa; - ac = c[214] | 0; - Y = (c[211] | 0) + aa | 0; - Z = ac; - W = ac + 8 | 0; - if ((W & 7 | 0) == 0) { - ai = 0; - } else { - ai = -W & 7; - } - W = Y - ai | 0; - c[214] = Z + ai; - c[211] = W; - c[Z + (ai + 4) >> 2] = W | 1; - c[Z + (Y + 4) >> 2] = 40; - c[215] = c[204]; - break L455; - } - } while (0); - if (ab >>> 0 < (c[212] | 0) >>> 0) { - c[212] = ab; - } - S = ab + aa | 0; - Y = 1280; - while (1) { - aj = Y | 0; - if ((c[aj >> 2] | 0) == (S | 0)) { - T = 334; - break; - } - Z = c[Y + 8 >> 2] | 0; - if ((Z | 0) == 0) { - break; - } else { - Y = Z; - } - } - do { - if ((T | 0) == 334) { - if ((c[Y + 12 >> 2] & 8 | 0) != 0) { - break; - } - c[aj >> 2] = ab; - S = Y + 4 | 0; - c[S >> 2] = (c[S >> 2] | 0) + aa; - S = ab + 8 | 0; - if ((S & 7 | 0) == 0) { - ak = 0; - } else { - ak = -S & 7; - } - S = ab + (aa + 8) | 0; - if ((S & 7 | 0) == 0) { - al = 0; - } else { - al = -S & 7; - } - S = ab + (al + aa) | 0; - Z = S; - W = ak + o | 0; - ac = ab + W | 0; - _ = ac; - K = S - (ab + ak) - o | 0; - c[ab + (ak + 4) >> 2] = o | 3; - do { - if ((Z | 0) == (c[214] | 0)) { - J = (c[211] | 0) + K | 0; - c[211] = J; - c[214] = _; - c[ab + (W + 4) >> 2] = J | 1; - } else { - if ((Z | 0) == (c[213] | 0)) { - J = (c[210] | 0) + K | 0; - c[210] = J; - c[213] = _; - c[ab + (W + 4) >> 2] = J | 1; - c[ab + (J + W) >> 2] = J; - break; - } - J = aa + 4 | 0; - X = c[ab + (J + al) >> 2] | 0; - if ((X & 3 | 0) == 1) { - $ = X & -8; - V = X >>> 3; - L500 : do { - if (X >>> 0 < 256) { - U = c[ab + ((al | 8) + aa) >> 2] | 0; - Q = c[ab + (aa + 12 + al) >> 2] | 0; - R = 872 + (V << 1 << 2) | 0; - do { - if ((U | 0) != (R | 0)) { - if (U >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - if ((c[U + 12 >> 2] | 0) == (Z | 0)) { - break; - } - au(); - return 0; - } - } while (0); - if ((Q | 0) == (U | 0)) { - c[208] = c[208] & ~(1 << V); - break; - } - do { - if ((Q | 0) == (R | 0)) { - am = Q + 8 | 0; - } else { - if (Q >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - m = Q + 8 | 0; - if ((c[m >> 2] | 0) == (Z | 0)) { - am = m; - break; - } - au(); - return 0; - } - } while (0); - c[U + 12 >> 2] = Q; - c[am >> 2] = U; - } else { - R = S; - m = c[ab + ((al | 24) + aa) >> 2] | 0; - P = c[ab + (aa + 12 + al) >> 2] | 0; - do { - if ((P | 0) == (R | 0)) { - O = al | 16; - g = ab + (J + O) | 0; - L = c[g >> 2] | 0; - if ((L | 0) == 0) { - e = ab + (O + aa) | 0; - O = c[e >> 2] | 0; - if ((O | 0) == 0) { - an = 0; - break; - } else { - ao = O; - ap = e; - } - } else { - ao = L; - ap = g; - } - while (1) { - g = ao + 20 | 0; - L = c[g >> 2] | 0; - if ((L | 0) != 0) { - ao = L; - ap = g; - continue; - } - g = ao + 16 | 0; - L = c[g >> 2] | 0; - if ((L | 0) == 0) { - break; - } else { - ao = L; - ap = g; - } - } - if (ap >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[ap >> 2] = 0; - an = ao; - break; - } - } else { - g = c[ab + ((al | 8) + aa) >> 2] | 0; - if (g >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - L = g + 12 | 0; - if ((c[L >> 2] | 0) != (R | 0)) { - au(); - return 0; - } - e = P + 8 | 0; - if ((c[e >> 2] | 0) == (R | 0)) { - c[L >> 2] = P; - c[e >> 2] = g; - an = P; - break; - } else { - au(); - return 0; - } - } - } while (0); - if ((m | 0) == 0) { - break; - } - P = ab + (aa + 28 + al) | 0; - U = 1136 + (c[P >> 2] << 2) | 0; - do { - if ((R | 0) == (c[U >> 2] | 0)) { - c[U >> 2] = an; - if ((an | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[P >> 2]); - break L500; - } else { - if (m >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - Q = m + 16 | 0; - if ((c[Q >> 2] | 0) == (R | 0)) { - c[Q >> 2] = an; - } else { - c[m + 20 >> 2] = an; - } - if ((an | 0) == 0) { - break L500; - } - } - } while (0); - if (an >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - c[an + 24 >> 2] = m; - R = al | 16; - P = c[ab + (R + aa) >> 2] | 0; - do { - if ((P | 0) != 0) { - if (P >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[an + 16 >> 2] = P; - c[P + 24 >> 2] = an; - break; - } - } - } while (0); - P = c[ab + (J + R) >> 2] | 0; - if ((P | 0) == 0) { - break; - } - if (P >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[an + 20 >> 2] = P; - c[P + 24 >> 2] = an; - break; - } - } - } while (0); - aq = ab + (($ | al) + aa) | 0; - as = $ + K | 0; - } else { - aq = Z; - as = K; - } - J = aq + 4 | 0; - c[J >> 2] = c[J >> 2] & -2; - c[ab + (W + 4) >> 2] = as | 1; - c[ab + (as + W) >> 2] = as; - J = as >>> 3; - if (as >>> 0 < 256) { - V = J << 1; - X = 872 + (V << 2) | 0; - P = c[208] | 0; - m = 1 << J; - do { - if ((P & m | 0) == 0) { - c[208] = P | m; - at = X; - av = 872 + (V + 2 << 2) | 0; - } else { - J = 872 + (V + 2 << 2) | 0; - U = c[J >> 2] | 0; - if (U >>> 0 >= (c[212] | 0) >>> 0) { - at = U; - av = J; - break; - } - au(); - return 0; - } - } while (0); - c[av >> 2] = _; - c[at + 12 >> 2] = _; - c[ab + (W + 8) >> 2] = at; - c[ab + (W + 12) >> 2] = X; - break; - } - V = ac; - m = as >>> 8; - do { - if ((m | 0) == 0) { - aw = 0; - } else { - if (as >>> 0 > 16777215) { - aw = 31; - break; - } - P = (m + 1048320 | 0) >>> 16 & 8; - $ = m << P; - J = ($ + 520192 | 0) >>> 16 & 4; - U = $ << J; - $ = (U + 245760 | 0) >>> 16 & 2; - Q = 14 - (J | P | $) + (U << $ >>> 15) | 0; - aw = as >>> ((Q + 7 | 0) >>> 0) & 1 | Q << 1; - } - } while (0); - m = 1136 + (aw << 2) | 0; - c[ab + (W + 28) >> 2] = aw; - c[ab + (W + 20) >> 2] = 0; - c[ab + (W + 16) >> 2] = 0; - X = c[209] | 0; - Q = 1 << aw; - if ((X & Q | 0) == 0) { - c[209] = X | Q; - c[m >> 2] = V; - c[ab + (W + 24) >> 2] = m; - c[ab + (W + 12) >> 2] = V; - c[ab + (W + 8) >> 2] = V; - break; - } - if ((aw | 0) == 31) { - ax = 0; - } else { - ax = 25 - (aw >>> 1) | 0; - } - Q = as << ax; - X = c[m >> 2] | 0; - while (1) { - if ((c[X + 4 >> 2] & -8 | 0) == (as | 0)) { - break; - } - ay = X + 16 + (Q >>> 31 << 2) | 0; - m = c[ay >> 2] | 0; - if ((m | 0) == 0) { - T = 407; - break; - } else { - Q = Q << 1; - X = m; - } - } - if ((T | 0) == 407) { - if (ay >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[ay >> 2] = V; - c[ab + (W + 24) >> 2] = X; - c[ab + (W + 12) >> 2] = V; - c[ab + (W + 8) >> 2] = V; - break; - } - } - Q = X + 8 | 0; - m = c[Q >> 2] | 0; - $ = c[212] | 0; - if (X >>> 0 < $ >>> 0) { - au(); - return 0; - } - if (m >>> 0 < $ >>> 0) { - au(); - return 0; - } else { - c[m + 12 >> 2] = V; - c[Q >> 2] = V; - c[ab + (W + 8) >> 2] = m; - c[ab + (W + 12) >> 2] = X; - c[ab + (W + 24) >> 2] = 0; - break; - } - } - } while (0); - n = ab + (ak | 8) | 0; - return n | 0; - } - } while (0); - Y = ad; - W = 1280; - while (1) { - az = c[W >> 2] | 0; - if (az >>> 0 <= Y >>> 0) { - aA = c[W + 4 >> 2] | 0; - aB = az + aA | 0; - if (aB >>> 0 > Y >>> 0) { - break; - } - } - W = c[W + 8 >> 2] | 0; - } - W = az + (aA - 39) | 0; - if ((W & 7 | 0) == 0) { - aC = 0; - } else { - aC = -W & 7; - } - W = az + (aA - 47 + aC) | 0; - ac = W >>> 0 < (ad + 16 | 0) >>> 0 ? Y : W; - W = ac + 8 | 0; - _ = ab + 8 | 0; - if ((_ & 7 | 0) == 0) { - aD = 0; - } else { - aD = -_ & 7; - } - _ = aa - 40 - aD | 0; - c[214] = ab + aD; - c[211] = _; - c[ab + (aD + 4) >> 2] = _ | 1; - c[ab + (aa - 36) >> 2] = 40; - c[215] = c[204]; - c[ac + 4 >> 2] = 27; - c[W >> 2] = c[320]; - c[W + 4 >> 2] = c[1284 >> 2]; - c[W + 8 >> 2] = c[1288 >> 2]; - c[W + 12 >> 2] = c[1292 >> 2]; - c[320] = ab; - c[321] = aa; - c[323] = 0; - c[322] = W; - W = ac + 28 | 0; - c[W >> 2] = 7; - if ((ac + 32 | 0) >>> 0 < aB >>> 0) { - _ = W; - while (1) { - W = _ + 4 | 0; - c[W >> 2] = 7; - if ((_ + 8 | 0) >>> 0 < aB >>> 0) { - _ = W; - } else { - break; - } - } - } - if ((ac | 0) == (Y | 0)) { - break; - } - _ = ac - ad | 0; - W = Y + (_ + 4) | 0; - c[W >> 2] = c[W >> 2] & -2; - c[ad + 4 >> 2] = _ | 1; - c[Y + _ >> 2] = _; - W = _ >>> 3; - if (_ >>> 0 < 256) { - K = W << 1; - Z = 872 + (K << 2) | 0; - S = c[208] | 0; - m = 1 << W; - do { - if ((S & m | 0) == 0) { - c[208] = S | m; - aE = Z; - aF = 872 + (K + 2 << 2) | 0; - } else { - W = 872 + (K + 2 << 2) | 0; - Q = c[W >> 2] | 0; - if (Q >>> 0 >= (c[212] | 0) >>> 0) { - aE = Q; - aF = W; - break; - } - au(); - return 0; - } - } while (0); - c[aF >> 2] = ad; - c[aE + 12 >> 2] = ad; - c[ad + 8 >> 2] = aE; - c[ad + 12 >> 2] = Z; - break; - } - K = ad; - m = _ >>> 8; - do { - if ((m | 0) == 0) { - aG = 0; - } else { - if (_ >>> 0 > 16777215) { - aG = 31; - break; - } - S = (m + 1048320 | 0) >>> 16 & 8; - Y = m << S; - ac = (Y + 520192 | 0) >>> 16 & 4; - W = Y << ac; - Y = (W + 245760 | 0) >>> 16 & 2; - Q = 14 - (ac | S | Y) + (W << Y >>> 15) | 0; - aG = _ >>> ((Q + 7 | 0) >>> 0) & 1 | Q << 1; - } - } while (0); - m = 1136 + (aG << 2) | 0; - c[ad + 28 >> 2] = aG; - c[ad + 20 >> 2] = 0; - c[ad + 16 >> 2] = 0; - Z = c[209] | 0; - Q = 1 << aG; - if ((Z & Q | 0) == 0) { - c[209] = Z | Q; - c[m >> 2] = K; - c[ad + 24 >> 2] = m; - c[ad + 12 >> 2] = ad; - c[ad + 8 >> 2] = ad; - break; - } - if ((aG | 0) == 31) { - aH = 0; - } else { - aH = 25 - (aG >>> 1) | 0; - } - Q = _ << aH; - Z = c[m >> 2] | 0; - while (1) { - if ((c[Z + 4 >> 2] & -8 | 0) == (_ | 0)) { - break; - } - aI = Z + 16 + (Q >>> 31 << 2) | 0; - m = c[aI >> 2] | 0; - if ((m | 0) == 0) { - T = 442; - break; - } else { - Q = Q << 1; - Z = m; - } - } - if ((T | 0) == 442) { - if (aI >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[aI >> 2] = K; - c[ad + 24 >> 2] = Z; - c[ad + 12 >> 2] = ad; - c[ad + 8 >> 2] = ad; - break; - } - } - Q = Z + 8 | 0; - _ = c[Q >> 2] | 0; - m = c[212] | 0; - if (Z >>> 0 < m >>> 0) { - au(); - return 0; - } - if (_ >>> 0 < m >>> 0) { - au(); - return 0; - } else { - c[_ + 12 >> 2] = K; - c[Q >> 2] = K; - c[ad + 8 >> 2] = _; - c[ad + 12 >> 2] = Z; - c[ad + 24 >> 2] = 0; - break; - } - } - } while (0); - ad = c[211] | 0; - if (ad >>> 0 <= o >>> 0) { - break; - } - _ = ad - o | 0; - c[211] = _; - ad = c[214] | 0; - Q = ad; - c[214] = Q + o; - c[Q + (o + 4) >> 2] = _ | 1; - c[ad + 4 >> 2] = o | 3; - n = ad + 8 | 0; - return n | 0; - } - } while (0); - c[(aX() | 0) >> 2] = 12; - n = 0; - return n | 0; -} -function bM(a) { - a = a | 0; - var b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0, M = 0, N = 0, O = 0; - if ((a | 0) == 0) { - return; - } - b = a - 8 | 0; - d = b; - e = c[212] | 0; - if (b >>> 0 < e >>> 0) { - au(); - } - f = c[a - 4 >> 2] | 0; - g = f & 3; - if ((g | 0) == 1) { - au(); - } - h = f & -8; - i = a + (h - 8) | 0; - j = i; - L672 : do { - if ((f & 1 | 0) == 0) { - k = c[b >> 2] | 0; - if ((g | 0) == 0) { - return; - } - l = -8 - k | 0; - m = a + l | 0; - n = m; - o = k + h | 0; - if (m >>> 0 < e >>> 0) { - au(); - } - if ((n | 0) == (c[213] | 0)) { - p = a + (h - 4) | 0; - if ((c[p >> 2] & 3 | 0) != 3) { - q = n; - r = o; - break; - } - c[210] = o; - c[p >> 2] = c[p >> 2] & -2; - c[a + (l + 4) >> 2] = o | 1; - c[i >> 2] = o; - return; - } - p = k >>> 3; - if (k >>> 0 < 256) { - k = c[a + (l + 8) >> 2] | 0; - s = c[a + (l + 12) >> 2] | 0; - t = 872 + (p << 1 << 2) | 0; - do { - if ((k | 0) != (t | 0)) { - if (k >>> 0 < e >>> 0) { - au(); - } - if ((c[k + 12 >> 2] | 0) == (n | 0)) { - break; - } - au(); - } - } while (0); - if ((s | 0) == (k | 0)) { - c[208] = c[208] & ~(1 << p); - q = n; - r = o; - break; - } - do { - if ((s | 0) == (t | 0)) { - u = s + 8 | 0; - } else { - if (s >>> 0 < e >>> 0) { - au(); - } - v = s + 8 | 0; - if ((c[v >> 2] | 0) == (n | 0)) { - u = v; - break; - } - au(); - } - } while (0); - c[k + 12 >> 2] = s; - c[u >> 2] = k; - q = n; - r = o; - break; - } - t = m; - p = c[a + (l + 24) >> 2] | 0; - v = c[a + (l + 12) >> 2] | 0; - do { - if ((v | 0) == (t | 0)) { - w = a + (l + 20) | 0; - x = c[w >> 2] | 0; - if ((x | 0) == 0) { - y = a + (l + 16) | 0; - z = c[y >> 2] | 0; - if ((z | 0) == 0) { - A = 0; - break; - } else { - B = z; - C = y; - } - } else { - B = x; - C = w; - } - while (1) { - w = B + 20 | 0; - x = c[w >> 2] | 0; - if ((x | 0) != 0) { - B = x; - C = w; - continue; - } - w = B + 16 | 0; - x = c[w >> 2] | 0; - if ((x | 0) == 0) { - break; - } else { - B = x; - C = w; - } - } - if (C >>> 0 < e >>> 0) { - au(); - } else { - c[C >> 2] = 0; - A = B; - break; - } - } else { - w = c[a + (l + 8) >> 2] | 0; - if (w >>> 0 < e >>> 0) { - au(); - } - x = w + 12 | 0; - if ((c[x >> 2] | 0) != (t | 0)) { - au(); - } - y = v + 8 | 0; - if ((c[y >> 2] | 0) == (t | 0)) { - c[x >> 2] = v; - c[y >> 2] = w; - A = v; - break; - } else { - au(); - } - } - } while (0); - if ((p | 0) == 0) { - q = n; - r = o; - break; - } - v = a + (l + 28) | 0; - m = 1136 + (c[v >> 2] << 2) | 0; - do { - if ((t | 0) == (c[m >> 2] | 0)) { - c[m >> 2] = A; - if ((A | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[v >> 2]); - q = n; - r = o; - break L672; - } else { - if (p >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - k = p + 16 | 0; - if ((c[k >> 2] | 0) == (t | 0)) { - c[k >> 2] = A; - } else { - c[p + 20 >> 2] = A; - } - if ((A | 0) == 0) { - q = n; - r = o; - break L672; - } - } - } while (0); - if (A >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - c[A + 24 >> 2] = p; - t = c[a + (l + 16) >> 2] | 0; - do { - if ((t | 0) != 0) { - if (t >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[A + 16 >> 2] = t; - c[t + 24 >> 2] = A; - break; - } - } - } while (0); - t = c[a + (l + 20) >> 2] | 0; - if ((t | 0) == 0) { - q = n; - r = o; - break; - } - if (t >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[A + 20 >> 2] = t; - c[t + 24 >> 2] = A; - q = n; - r = o; - break; - } - } else { - q = d; - r = h; - } - } while (0); - d = q; - if (d >>> 0 >= i >>> 0) { - au(); - } - A = a + (h - 4) | 0; - e = c[A >> 2] | 0; - if ((e & 1 | 0) == 0) { - au(); - } - do { - if ((e & 2 | 0) == 0) { - if ((j | 0) == (c[214] | 0)) { - B = (c[211] | 0) + r | 0; - c[211] = B; - c[214] = q; - c[q + 4 >> 2] = B | 1; - if ((q | 0) == (c[213] | 0)) { - c[213] = 0; - c[210] = 0; - } - if (B >>> 0 <= (c[215] | 0) >>> 0) { - return; - } - bS(0) | 0; - return; - } - if ((j | 0) == (c[213] | 0)) { - B = (c[210] | 0) + r | 0; - c[210] = B; - c[213] = q; - c[q + 4 >> 2] = B | 1; - c[d + B >> 2] = B; - return; - } - B = (e & -8) + r | 0; - C = e >>> 3; - L777 : do { - if (e >>> 0 < 256) { - u = c[a + h >> 2] | 0; - g = c[a + (h | 4) >> 2] | 0; - b = 872 + (C << 1 << 2) | 0; - do { - if ((u | 0) != (b | 0)) { - if (u >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - if ((c[u + 12 >> 2] | 0) == (j | 0)) { - break; - } - au(); - } - } while (0); - if ((g | 0) == (u | 0)) { - c[208] = c[208] & ~(1 << C); - break; - } - do { - if ((g | 0) == (b | 0)) { - D = g + 8 | 0; - } else { - if (g >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - f = g + 8 | 0; - if ((c[f >> 2] | 0) == (j | 0)) { - D = f; - break; - } - au(); - } - } while (0); - c[u + 12 >> 2] = g; - c[D >> 2] = u; - } else { - b = i; - f = c[a + (h + 16) >> 2] | 0; - t = c[a + (h | 4) >> 2] | 0; - do { - if ((t | 0) == (b | 0)) { - p = a + (h + 12) | 0; - v = c[p >> 2] | 0; - if ((v | 0) == 0) { - m = a + (h + 8) | 0; - k = c[m >> 2] | 0; - if ((k | 0) == 0) { - E = 0; - break; - } else { - F = k; - G = m; - } - } else { - F = v; - G = p; - } - while (1) { - p = F + 20 | 0; - v = c[p >> 2] | 0; - if ((v | 0) != 0) { - F = v; - G = p; - continue; - } - p = F + 16 | 0; - v = c[p >> 2] | 0; - if ((v | 0) == 0) { - break; - } else { - F = v; - G = p; - } - } - if (G >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[G >> 2] = 0; - E = F; - break; - } - } else { - p = c[a + h >> 2] | 0; - if (p >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - v = p + 12 | 0; - if ((c[v >> 2] | 0) != (b | 0)) { - au(); - } - m = t + 8 | 0; - if ((c[m >> 2] | 0) == (b | 0)) { - c[v >> 2] = t; - c[m >> 2] = p; - E = t; - break; - } else { - au(); - } - } - } while (0); - if ((f | 0) == 0) { - break; - } - t = a + (h + 20) | 0; - u = 1136 + (c[t >> 2] << 2) | 0; - do { - if ((b | 0) == (c[u >> 2] | 0)) { - c[u >> 2] = E; - if ((E | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[t >> 2]); - break L777; - } else { - if (f >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - g = f + 16 | 0; - if ((c[g >> 2] | 0) == (b | 0)) { - c[g >> 2] = E; - } else { - c[f + 20 >> 2] = E; - } - if ((E | 0) == 0) { - break L777; - } - } - } while (0); - if (E >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - c[E + 24 >> 2] = f; - b = c[a + (h + 8) >> 2] | 0; - do { - if ((b | 0) != 0) { - if (b >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[E + 16 >> 2] = b; - c[b + 24 >> 2] = E; - break; - } - } - } while (0); - b = c[a + (h + 12) >> 2] | 0; - if ((b | 0) == 0) { - break; - } - if (b >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[E + 20 >> 2] = b; - c[b + 24 >> 2] = E; - break; - } - } - } while (0); - c[q + 4 >> 2] = B | 1; - c[d + B >> 2] = B; - if ((q | 0) != (c[213] | 0)) { - H = B; - break; - } - c[210] = B; - return; - } else { - c[A >> 2] = e & -2; - c[q + 4 >> 2] = r | 1; - c[d + r >> 2] = r; - H = r; - } - } while (0); - r = H >>> 3; - if (H >>> 0 < 256) { - d = r << 1; - e = 872 + (d << 2) | 0; - A = c[208] | 0; - E = 1 << r; - do { - if ((A & E | 0) == 0) { - c[208] = A | E; - I = e; - J = 872 + (d + 2 << 2) | 0; - } else { - r = 872 + (d + 2 << 2) | 0; - h = c[r >> 2] | 0; - if (h >>> 0 >= (c[212] | 0) >>> 0) { - I = h; - J = r; - break; - } - au(); - } - } while (0); - c[J >> 2] = q; - c[I + 12 >> 2] = q; - c[q + 8 >> 2] = I; - c[q + 12 >> 2] = e; - return; - } - e = q; - I = H >>> 8; - do { - if ((I | 0) == 0) { - K = 0; - } else { - if (H >>> 0 > 16777215) { - K = 31; - break; - } - J = (I + 1048320 | 0) >>> 16 & 8; - d = I << J; - E = (d + 520192 | 0) >>> 16 & 4; - A = d << E; - d = (A + 245760 | 0) >>> 16 & 2; - r = 14 - (E | J | d) + (A << d >>> 15) | 0; - K = H >>> ((r + 7 | 0) >>> 0) & 1 | r << 1; - } - } while (0); - I = 1136 + (K << 2) | 0; - c[q + 28 >> 2] = K; - c[q + 20 >> 2] = 0; - c[q + 16 >> 2] = 0; - r = c[209] | 0; - d = 1 << K; - do { - if ((r & d | 0) == 0) { - c[209] = r | d; - c[I >> 2] = e; - c[q + 24 >> 2] = I; - c[q + 12 >> 2] = q; - c[q + 8 >> 2] = q; - } else { - if ((K | 0) == 31) { - L = 0; - } else { - L = 25 - (K >>> 1) | 0; - } - A = H << L; - J = c[I >> 2] | 0; - while (1) { - if ((c[J + 4 >> 2] & -8 | 0) == (H | 0)) { - break; - } - M = J + 16 + (A >>> 31 << 2) | 0; - E = c[M >> 2] | 0; - if ((E | 0) == 0) { - N = 621; - break; - } else { - A = A << 1; - J = E; - } - } - if ((N | 0) == 621) { - if (M >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[M >> 2] = e; - c[q + 24 >> 2] = J; - c[q + 12 >> 2] = q; - c[q + 8 >> 2] = q; - break; - } - } - A = J + 8 | 0; - B = c[A >> 2] | 0; - E = c[212] | 0; - if (J >>> 0 < E >>> 0) { - au(); - } - if (B >>> 0 < E >>> 0) { - au(); - } else { - c[B + 12 >> 2] = e; - c[A >> 2] = e; - c[q + 8 >> 2] = B; - c[q + 12 >> 2] = J; - c[q + 24 >> 2] = 0; - break; - } - } - } while (0); - q = (c[216] | 0) - 1 | 0; - c[216] = q; - if ((q | 0) == 0) { - O = 1288; - } else { - return; - } - while (1) { - q = c[O >> 2] | 0; - if ((q | 0) == 0) { - break; - } else { - O = q + 8 | 0; - } - } - c[216] = -1; - return; -} -function bN(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0; - do { - if ((a | 0) == 0) { - d = 0; - } else { - e = ad(b, a) | 0; - if ((b | a) >>> 0 <= 65535) { - d = e; - break; - } - d = ((e >>> 0) / (a >>> 0) | 0 | 0) == (b | 0) ? e : -1; - } - } while (0); - b = bL(d) | 0; - if ((b | 0) == 0) { - return b | 0; - } - if ((c[b - 4 >> 2] & 3 | 0) == 0) { - return b | 0; - } - cL(b | 0, 0, d | 0); - return b | 0; -} -function bO(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0; - if ((a | 0) == 0) { - d = bL(b) | 0; - return d | 0; - } - if (b >>> 0 > 4294967231) { - c[(aX() | 0) >> 2] = 12; - d = 0; - return d | 0; - } - if (b >>> 0 < 11) { - e = 16; - } else { - e = b + 11 & -8; - } - f = bT(a - 8 | 0, e) | 0; - if ((f | 0) != 0) { - d = f + 8 | 0; - return d | 0; - } - f = bL(b) | 0; - if ((f | 0) == 0) { - d = 0; - return d | 0; - } - e = c[a - 4 >> 2] | 0; - g = (e & -8) - ((e & 3 | 0) == 0 ? 8 : 4) | 0; - e = g >>> 0 < b >>> 0 ? g : b; - cK(f | 0, a | 0, e) | 0; - bM(a); - d = f; - return d | 0; -} -function bP(a, b) { - a = a | 0; - b = b | 0; - var d = 0; - if ((a | 0) == 0) { - return 0; - } - if (b >>> 0 > 4294967231) { - c[(aX() | 0) >> 2] = 12; - return 0; - } - if (b >>> 0 < 11) { - d = 16; - } else { - d = b + 11 & -8; - } - b = a - 8 | 0; - return ((bT(b, d) | 0) == (b | 0) ? a : 0) | 0; -} -function bQ(a, b) { - a = a | 0; - b = b | 0; - var c = 0; - if (a >>> 0 < 9) { - c = bL(b) | 0; - return c | 0; - } else { - c = bR(a, b) | 0; - return c | 0; - } - return 0; -} -function bR(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0; - d = a >>> 0 < 16 ? 16 : a; - if ((d - 1 & d | 0) == 0) { - e = d; - } else { - a = 16; - while (1) { - if (a >>> 0 < d >>> 0) { - a = a << 1; - } else { - e = a; - break; - } - } - } - if ((-64 - e | 0) >>> 0 <= b >>> 0) { - c[(aX() | 0) >> 2] = 12; - f = 0; - return f | 0; - } - if (b >>> 0 < 11) { - g = 16; - } else { - g = b + 11 & -8; - } - b = bL(e + 12 + g | 0) | 0; - if ((b | 0) == 0) { - f = 0; - return f | 0; - } - a = b - 8 | 0; - d = a; - h = e - 1 | 0; - do { - if ((b & h | 0) == 0) { - i = d; - } else { - j = b + h & -e; - k = j - 8 | 0; - l = a; - if ((k - l | 0) >>> 0 > 15) { - m = k; - } else { - m = j + (e - 8) | 0; - } - j = m; - k = m - l | 0; - l = b - 4 | 0; - n = c[l >> 2] | 0; - o = (n & -8) - k | 0; - if ((n & 3 | 0) == 0) { - c[m >> 2] = (c[a >> 2] | 0) + k; - c[m + 4 >> 2] = o; - i = j; - break; - } else { - n = m + 4 | 0; - c[n >> 2] = o | c[n >> 2] & 1 | 2; - n = m + (o + 4) | 0; - c[n >> 2] = c[n >> 2] | 1; - c[l >> 2] = k | c[l >> 2] & 1 | 2; - l = b + (k - 4) | 0; - c[l >> 2] = c[l >> 2] | 1; - b9(d, k); - i = j; - break; - } - } - } while (0); - d = i + 4 | 0; - b = c[d >> 2] | 0; - do { - if ((b & 3 | 0) != 0) { - m = b & -8; - if (m >>> 0 <= (g + 16 | 0) >>> 0) { - break; - } - a = m - g | 0; - e = i; - c[d >> 2] = g | b & 1 | 2; - c[e + (g | 4) >> 2] = a | 3; - h = e + (m | 4) | 0; - c[h >> 2] = c[h >> 2] | 1; - b9(e + g | 0, a); - } - } while (0); - f = i + 8 | 0; - return f | 0; -} -function bS(a) { - a = a | 0; - var b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0; - do { - if ((c[200] | 0) == 0) { - b = ar(8) | 0; - if ((b - 1 & b | 0) == 0) { - c[202] = b; - c[201] = b; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - return 0; - } - } - } while (0); - if (a >>> 0 >= 4294967232) { - d = 0; - return d | 0; - } - b = c[214] | 0; - if ((b | 0) == 0) { - d = 0; - return d | 0; - } - e = c[211] | 0; - do { - if (e >>> 0 > (a + 40 | 0) >>> 0) { - f = c[202] | 0; - g = ad((((-40 - a - 1 + e + f | 0) >>> 0) / (f >>> 0) | 0) - 1 | 0, f) | 0; - h = b; - i = 1280; - while (1) { - j = c[i >> 2] | 0; - if (j >>> 0 <= h >>> 0) { - if ((j + (c[i + 4 >> 2] | 0) | 0) >>> 0 > h >>> 0) { - k = i; - break; - } - } - j = c[i + 8 >> 2] | 0; - if ((j | 0) == 0) { - k = 0; - break; - } else { - i = j; - } - } - if ((c[k + 12 >> 2] & 8 | 0) != 0) { - break; - } - i = aV(0) | 0; - h = k + 4 | 0; - if ((i | 0) != ((c[k >> 2] | 0) + (c[h >> 2] | 0) | 0)) { - break; - } - j = aV(-(g >>> 0 > 2147483646 ? -2147483648 - f | 0 : g) | 0) | 0; - l = aV(0) | 0; - if (!((j | 0) != -1 & l >>> 0 < i >>> 0)) { - break; - } - j = i - l | 0; - if ((i | 0) == (l | 0)) { - break; - } - c[h >> 2] = (c[h >> 2] | 0) - j; - c[316] = (c[316] | 0) - j; - h = c[214] | 0; - m = (c[211] | 0) - j | 0; - j = h; - n = h + 8 | 0; - if ((n & 7 | 0) == 0) { - o = 0; - } else { - o = -n & 7; - } - n = m - o | 0; - c[214] = j + o; - c[211] = n; - c[j + (o + 4) >> 2] = n | 1; - c[j + (m + 4) >> 2] = 40; - c[215] = c[204]; - d = (i | 0) != (l | 0) | 0; - return d | 0; - } - } while (0); - if ((c[211] | 0) >>> 0 <= (c[215] | 0) >>> 0) { - d = 0; - return d | 0; - } - c[215] = -1; - d = 0; - return d | 0; -} -function bT(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0; - d = a + 4 | 0; - e = c[d >> 2] | 0; - f = e & -8; - g = a; - h = g + f | 0; - i = h; - j = c[212] | 0; - if (g >>> 0 < j >>> 0) { - au(); - return 0; - } - k = e & 3; - if (!((k | 0) != 1 & g >>> 0 < h >>> 0)) { - au(); - return 0; - } - l = g + (f | 4) | 0; - m = c[l >> 2] | 0; - if ((m & 1 | 0) == 0) { - au(); - return 0; - } - if ((k | 0) == 0) { - if (b >>> 0 < 256) { - n = 0; - return n | 0; - } - do { - if (f >>> 0 >= (b + 4 | 0) >>> 0) { - if ((f - b | 0) >>> 0 > c[202] << 1 >>> 0) { - break; - } else { - n = a; - } - return n | 0; - } - } while (0); - n = 0; - return n | 0; - } - if (f >>> 0 >= b >>> 0) { - k = f - b | 0; - if (k >>> 0 <= 15) { - n = a; - return n | 0; - } - c[d >> 2] = e & 1 | b | 2; - c[g + (b + 4) >> 2] = k | 3; - c[l >> 2] = c[l >> 2] | 1; - b9(g + b | 0, k); - n = a; - return n | 0; - } - if ((i | 0) == (c[214] | 0)) { - k = (c[211] | 0) + f | 0; - if (k >>> 0 <= b >>> 0) { - n = 0; - return n | 0; - } - l = k - b | 0; - c[d >> 2] = e & 1 | b | 2; - c[g + (b + 4) >> 2] = l | 1; - c[214] = g + b; - c[211] = l; - n = a; - return n | 0; - } - if ((i | 0) == (c[213] | 0)) { - l = (c[210] | 0) + f | 0; - if (l >>> 0 < b >>> 0) { - n = 0; - return n | 0; - } - k = l - b | 0; - if (k >>> 0 > 15) { - c[d >> 2] = e & 1 | b | 2; - c[g + (b + 4) >> 2] = k | 1; - c[g + l >> 2] = k; - o = g + (l + 4) | 0; - c[o >> 2] = c[o >> 2] & -2; - p = g + b | 0; - q = k; - } else { - c[d >> 2] = e & 1 | l | 2; - e = g + (l + 4) | 0; - c[e >> 2] = c[e >> 2] | 1; - p = 0; - q = 0; - } - c[210] = q; - c[213] = p; - n = a; - return n | 0; - } - if ((m & 2 | 0) != 0) { - n = 0; - return n | 0; - } - p = (m & -8) + f | 0; - if (p >>> 0 < b >>> 0) { - n = 0; - return n | 0; - } - q = p - b | 0; - e = m >>> 3; - L1056 : do { - if (m >>> 0 < 256) { - l = c[g + (f + 8) >> 2] | 0; - k = c[g + (f + 12) >> 2] | 0; - o = 872 + (e << 1 << 2) | 0; - do { - if ((l | 0) != (o | 0)) { - if (l >>> 0 < j >>> 0) { - au(); - return 0; - } - if ((c[l + 12 >> 2] | 0) == (i | 0)) { - break; - } - au(); - return 0; - } - } while (0); - if ((k | 0) == (l | 0)) { - c[208] = c[208] & ~(1 << e); - break; - } - do { - if ((k | 0) == (o | 0)) { - r = k + 8 | 0; - } else { - if (k >>> 0 < j >>> 0) { - au(); - return 0; - } - s = k + 8 | 0; - if ((c[s >> 2] | 0) == (i | 0)) { - r = s; - break; - } - au(); - return 0; - } - } while (0); - c[l + 12 >> 2] = k; - c[r >> 2] = l; - } else { - o = h; - s = c[g + (f + 24) >> 2] | 0; - t = c[g + (f + 12) >> 2] | 0; - do { - if ((t | 0) == (o | 0)) { - u = g + (f + 20) | 0; - v = c[u >> 2] | 0; - if ((v | 0) == 0) { - w = g + (f + 16) | 0; - x = c[w >> 2] | 0; - if ((x | 0) == 0) { - y = 0; - break; - } else { - z = x; - A = w; - } - } else { - z = v; - A = u; - } - while (1) { - u = z + 20 | 0; - v = c[u >> 2] | 0; - if ((v | 0) != 0) { - z = v; - A = u; - continue; - } - u = z + 16 | 0; - v = c[u >> 2] | 0; - if ((v | 0) == 0) { - break; - } else { - z = v; - A = u; - } - } - if (A >>> 0 < j >>> 0) { - au(); - return 0; - } else { - c[A >> 2] = 0; - y = z; - break; - } - } else { - u = c[g + (f + 8) >> 2] | 0; - if (u >>> 0 < j >>> 0) { - au(); - return 0; - } - v = u + 12 | 0; - if ((c[v >> 2] | 0) != (o | 0)) { - au(); - return 0; - } - w = t + 8 | 0; - if ((c[w >> 2] | 0) == (o | 0)) { - c[v >> 2] = t; - c[w >> 2] = u; - y = t; - break; - } else { - au(); - return 0; - } - } - } while (0); - if ((s | 0) == 0) { - break; - } - t = g + (f + 28) | 0; - l = 1136 + (c[t >> 2] << 2) | 0; - do { - if ((o | 0) == (c[l >> 2] | 0)) { - c[l >> 2] = y; - if ((y | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[t >> 2]); - break L1056; - } else { - if (s >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - k = s + 16 | 0; - if ((c[k >> 2] | 0) == (o | 0)) { - c[k >> 2] = y; - } else { - c[s + 20 >> 2] = y; - } - if ((y | 0) == 0) { - break L1056; - } - } - } while (0); - if (y >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - c[y + 24 >> 2] = s; - o = c[g + (f + 16) >> 2] | 0; - do { - if ((o | 0) != 0) { - if (o >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[y + 16 >> 2] = o; - c[o + 24 >> 2] = y; - break; - } - } - } while (0); - o = c[g + (f + 20) >> 2] | 0; - if ((o | 0) == 0) { - break; - } - if (o >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[y + 20 >> 2] = o; - c[o + 24 >> 2] = y; - break; - } - } - } while (0); - if (q >>> 0 < 16) { - c[d >> 2] = p | c[d >> 2] & 1 | 2; - y = g + (p | 4) | 0; - c[y >> 2] = c[y >> 2] | 1; - n = a; - return n | 0; - } else { - c[d >> 2] = c[d >> 2] & 1 | b | 2; - c[g + (b + 4) >> 2] = q | 3; - d = g + (p | 4) | 0; - c[d >> 2] = c[d >> 2] | 1; - b9(g + b | 0, q); - n = a; - return n | 0; - } - return 0; -} -function bU() { - return c[316] | 0; -} -function bV() { - return c[317] | 0; -} -function bW() { - var a = 0; - a = c[318] | 0; - return ((a | 0) == 0 ? -1 : a) | 0; -} -function bX(a) { - a = a | 0; - var b = 0, d = 0; - if ((a | 0) == -1) { - b = 0; - } else { - d = c[202] | 0; - b = a - 1 + d & -d; - } - c[318] = b; - return b | 0; -} -function bY(a) { - a = a | 0; - var b = 0, d = 0, e = 0; - do { - if ((a | 0) == 0) { - b = 0; - } else { - d = c[a - 4 >> 2] | 0; - e = d & 3; - if ((e | 0) == 1) { - b = 0; - break; - } - b = (d & -8) - ((e | 0) == 0 ? 8 : 4) | 0; - } - } while (0); - return b | 0; -} -function bZ(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0, g = 0; - do { - if ((b | 0) == 8) { - e = bL(d) | 0; - } else { - f = b >>> 2; - if ((b & 3 | 0) != 0 | (f | 0) == 0) { - g = 22; - return g | 0; - } - if ((f + 1073741823 & f | 0) != 0) { - g = 22; - return g | 0; - } - if ((-64 - b | 0) >>> 0 < d >>> 0) { - g = 12; - return g | 0; - } else { - e = bR(b >>> 0 < 16 ? 16 : b, d) | 0; - break; - } - } - } while (0); - if ((e | 0) == 0) { - g = 12; - return g | 0; - } - c[a >> 2] = e; - g = 0; - return g | 0; -} -function b_(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0; - e = i; - i = i + 8 | 0; - f = e | 0; - c[f >> 2] = b; - b = b2(a, f, 3, d) | 0; - i = e; - return b | 0; -} -function b$(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - return b2(a, b, 0, c) | 0; -} -function b0(a) { - a = a | 0; - var b = 0, d = 0, e = 0; - if ((c[200] | 0) != 0) { - b = c[201] | 0; - d = bQ(b, a) | 0; - return d | 0; - } - e = ar(8) | 0; - if ((e - 1 & e | 0) != 0) { - au(); - return 0; - } - c[202] = e; - c[201] = e; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - b = c[201] | 0; - d = bQ(b, a) | 0; - return d | 0; -} -function b1(a) { - a = a | 0; - var b = 0; - do { - if ((c[200] | 0) == 0) { - b = ar(8) | 0; - if ((b - 1 & b | 0) == 0) { - c[202] = b; - c[201] = b; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - return 0; - } - } - } while (0); - b = c[201] | 0; - return bQ(b, a - 1 + b & -b) | 0; -} -function b2(a, b, d, e) { - a = a | 0; - b = b | 0; - d = d | 0; - e = e | 0; - var f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0; - do { - if ((c[200] | 0) == 0) { - f = ar(8) | 0; - if ((f - 1 & f | 0) == 0) { - c[202] = f; - c[201] = f; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - return 0; - } - } - } while (0); - f = (a | 0) == 0; - do { - if ((e | 0) == 0) { - if (f) { - g = bL(0) | 0; - return g | 0; - } else { - h = a << 2; - if (h >>> 0 < 11) { - i = 0; - j = 16; - break; - } - i = 0; - j = h + 11 & -8; - break; - } - } else { - if (f) { - g = e; - } else { - i = e; - j = 0; - break; - } - return g | 0; - } - } while (0); - do { - if ((d & 1 | 0) == 0) { - if (f) { - k = 0; - l = 0; - break; - } else { - m = 0; - n = 0; - } - while (1) { - e = c[b + (n << 2) >> 2] | 0; - if (e >>> 0 < 11) { - o = 16; - } else { - o = e + 11 & -8; - } - e = o + m | 0; - h = n + 1 | 0; - if ((h | 0) == (a | 0)) { - k = 0; - l = e; - break; - } else { - m = e; - n = h; - } - } - } else { - h = c[b >> 2] | 0; - if (h >>> 0 < 11) { - p = 16; - } else { - p = h + 11 & -8; - } - k = p; - l = ad(p, a) | 0; - } - } while (0); - p = bL(j - 4 + l | 0) | 0; - if ((p | 0) == 0) { - g = 0; - return g | 0; - } - n = p - 8 | 0; - m = c[p - 4 >> 2] & -8; - if ((d & 2 | 0) != 0) { - cL(p | 0, 0, -4 - j + m | 0); - } - if ((i | 0) == 0) { - c[p + (l - 4) >> 2] = m - l | 3; - q = p + l | 0; - r = l; - } else { - q = i; - r = m; - } - c[q >> 2] = p; - p = a - 1 | 0; - L1216 : do { - if ((p | 0) == 0) { - s = n; - t = r; - } else { - if ((k | 0) == 0) { - u = n; - v = r; - w = 0; - } else { - a = n; - m = r; - i = 0; - while (1) { - l = m - k | 0; - c[a + 4 >> 2] = k | 3; - j = a + k | 0; - d = i + 1 | 0; - c[q + (d << 2) >> 2] = a + (k + 8); - if ((d | 0) == (p | 0)) { - s = j; - t = l; - break L1216; - } else { - a = j; - m = l; - i = d; - } - } - } - while (1) { - i = c[b + (w << 2) >> 2] | 0; - if (i >>> 0 < 11) { - x = 16; - } else { - x = i + 11 & -8; - } - i = v - x | 0; - c[u + 4 >> 2] = x | 3; - m = u + x | 0; - a = w + 1 | 0; - c[q + (a << 2) >> 2] = u + (x + 8); - if ((a | 0) == (p | 0)) { - s = m; - t = i; - break; - } else { - u = m; - v = i; - w = a; - } - } - } - } while (0); - c[s + 4 >> 2] = t | 3; - g = q; - return g | 0; -} -function b3(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0; - d = a + (b << 2) | 0; - L1229 : do { - if ((b | 0) != 0) { - e = a; - L1230 : while (1) { - f = c[e >> 2] | 0; - L1232 : do { - if ((f | 0) == 0) { - g = e + 4 | 0; - } else { - h = f - 8 | 0; - i = h; - j = f - 4 | 0; - k = c[j >> 2] & -8; - c[e >> 2] = 0; - if (h >>> 0 < (c[212] | 0) >>> 0) { - l = 935; - break L1230; - } - h = c[j >> 2] | 0; - if ((h & 3 | 0) == 1) { - l = 936; - break L1230; - } - m = e + 4 | 0; - n = h - 8 & -8; - do { - if ((m | 0) != (d | 0)) { - if ((c[m >> 2] | 0) != (f + (n + 8) | 0)) { - break; - } - o = (c[f + (n | 4) >> 2] & -8) + k | 0; - c[j >> 2] = h & 1 | o | 2; - p = f + (o - 4) | 0; - c[p >> 2] = c[p >> 2] | 1; - c[m >> 2] = f; - g = m; - break L1232; - } - } while (0); - b9(i, k); - g = m; - } - } while (0); - if ((g | 0) == (d | 0)) { - break L1229; - } else { - e = g; - } - } - if ((l | 0) == 935) { - au(); - return 0; - } else if ((l | 0) == 936) { - au(); - return 0; - } - } - } while (0); - if ((c[211] | 0) >>> 0 <= (c[215] | 0) >>> 0) { - return 0; - } - bS(0) | 0; - return 0; -} -function b4(a) { - a = a | 0; - var b = 0, d = 0; - if ((c[200] | 0) != 0) { - b = bS(a) | 0; - return b | 0; - } - d = ar(8) | 0; - if ((d - 1 & d | 0) != 0) { - au(); - return 0; - } - c[202] = d; - c[201] = d; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - b = bS(a) | 0; - return b | 0; -} -function b5(a) { - a = a | 0; - var b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0; - do { - if ((c[200] | 0) == 0) { - b = ar(8) | 0; - if ((b - 1 & b | 0) == 0) { - c[202] = b; - c[201] = b; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - } - } - } while (0); - b = c[214] | 0; - if ((b | 0) == 0) { - d = 0; - e = 0; - f = 0; - g = 0; - h = 0; - i = 0; - j = 0; - } else { - k = c[211] | 0; - l = k + 40 | 0; - m = 1; - n = l; - o = l; - l = 1280; - while (1) { - p = c[l >> 2] | 0; - q = p + 8 | 0; - if ((q & 7 | 0) == 0) { - r = 0; - } else { - r = -q & 7; - } - q = p + (c[l + 4 >> 2] | 0) | 0; - s = m; - t = n; - u = o; - v = p + r | 0; - while (1) { - if (v >>> 0 >= q >>> 0 | (v | 0) == (b | 0)) { - w = s; - x = t; - y = u; - break; - } - z = c[v + 4 >> 2] | 0; - if ((z | 0) == 7) { - w = s; - x = t; - y = u; - break; - } - A = z & -8; - B = A + u | 0; - if ((z & 3 | 0) == 1) { - C = A + t | 0; - D = s + 1 | 0; - } else { - C = t; - D = s; - } - z = v + A | 0; - if (z >>> 0 < p >>> 0) { - w = D; - x = C; - y = B; - break; - } else { - s = D; - t = C; - u = B; - v = z; - } - } - v = c[l + 8 >> 2] | 0; - if ((v | 0) == 0) { - break; - } else { - m = w; - n = x; - o = y; - l = v; - } - } - l = c[316] | 0; - d = k; - e = y; - f = w; - g = l - y | 0; - h = c[317] | 0; - i = l - x | 0; - j = x; - } - c[a >> 2] = e; - c[a + 4 >> 2] = f; - f = a + 8 | 0; - c[f >> 2] = 0; - c[f + 4 >> 2] = 0; - c[a + 16 >> 2] = g; - c[a + 20 >> 2] = h; - c[a + 24 >> 2] = 0; - c[a + 28 >> 2] = i; - c[a + 32 >> 2] = j; - c[a + 36 >> 2] = d; - return; -} -function b6() { - var a = 0, b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, j = 0, k = 0, l = 0, m = 0, n = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0; - a = i; - do { - if ((c[200] | 0) == 0) { - b = ar(8) | 0; - if ((b - 1 & b | 0) == 0) { - c[202] = b; - c[201] = b; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - } - } - } while (0); - b = c[214] | 0; - if ((b | 0) == 0) { - d = 0; - e = 0; - f = 0; - } else { - g = c[317] | 0; - h = c[316] | 0; - j = h - 40 - (c[211] | 0) | 0; - k = 1280; - while (1) { - l = c[k >> 2] | 0; - m = l + 8 | 0; - if ((m & 7 | 0) == 0) { - n = 0; - } else { - n = -m & 7; - } - m = l + (c[k + 4 >> 2] | 0) | 0; - p = j; - q = l + n | 0; - while (1) { - if (q >>> 0 >= m >>> 0 | (q | 0) == (b | 0)) { - r = p; - break; - } - s = c[q + 4 >> 2] | 0; - if ((s | 0) == 7) { - r = p; - break; - } - t = s & -8; - u = p - ((s & 3 | 0) == 1 ? t : 0) | 0; - s = q + t | 0; - if (s >>> 0 < l >>> 0) { - r = u; - break; - } else { - p = u; - q = s; - } - } - q = c[k + 8 >> 2] | 0; - if ((q | 0) == 0) { - d = r; - e = h; - f = g; - break; - } else { - j = r; - k = q; - } - } - } - av(c[o >> 2] | 0, 520, (y = i, i = i + 8 | 0, c[y >> 2] = f, y) | 0) | 0; - av(c[o >> 2] | 0, 488, (y = i, i = i + 8 | 0, c[y >> 2] = e, y) | 0) | 0; - av(c[o >> 2] | 0, 400, (y = i, i = i + 8 | 0, c[y >> 2] = d, y) | 0) | 0; - i = a; - return; -} -function b7(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0; - do { - if ((c[200] | 0) == 0) { - d = ar(8) | 0; - if ((d - 1 & d | 0) == 0) { - c[202] = d; - c[201] = d; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - return 0; - } - } - } while (0); - if ((a | 0) == (-1 | 0)) { - c[204] = b; - e = 1; - return e | 0; - } else if ((a | 0) == (-2 | 0)) { - if ((c[201] | 0) >>> 0 > b >>> 0) { - e = 0; - return e | 0; - } - if ((b - 1 & b | 0) != 0) { - e = 0; - return e | 0; - } - c[202] = b; - e = 1; - return e | 0; - } else if ((a | 0) == (-3 | 0)) { - c[203] = b; - e = 1; - return e | 0; - } else { - e = 0; - return e | 0; - } - return 0; -} -function b8() { - return (F = c[328] | 0, c[328] = F + 0, F) | 0; -} -function b9(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0; - d = a; - e = d + b | 0; - f = e; - g = c[a + 4 >> 2] | 0; - L1325 : do { - if ((g & 1 | 0) == 0) { - h = c[a >> 2] | 0; - if ((g & 3 | 0) == 0) { - return; - } - i = d + (-h | 0) | 0; - j = i; - k = h + b | 0; - l = c[212] | 0; - if (i >>> 0 < l >>> 0) { - au(); - } - if ((j | 0) == (c[213] | 0)) { - m = d + (b + 4) | 0; - if ((c[m >> 2] & 3 | 0) != 3) { - n = j; - o = k; - break; - } - c[210] = k; - c[m >> 2] = c[m >> 2] & -2; - c[d + (4 - h) >> 2] = k | 1; - c[e >> 2] = k; - return; - } - m = h >>> 3; - if (h >>> 0 < 256) { - p = c[d + (8 - h) >> 2] | 0; - q = c[d + (12 - h) >> 2] | 0; - r = 872 + (m << 1 << 2) | 0; - do { - if ((p | 0) != (r | 0)) { - if (p >>> 0 < l >>> 0) { - au(); - } - if ((c[p + 12 >> 2] | 0) == (j | 0)) { - break; - } - au(); - } - } while (0); - if ((q | 0) == (p | 0)) { - c[208] = c[208] & ~(1 << m); - n = j; - o = k; - break; - } - do { - if ((q | 0) == (r | 0)) { - s = q + 8 | 0; - } else { - if (q >>> 0 < l >>> 0) { - au(); - } - t = q + 8 | 0; - if ((c[t >> 2] | 0) == (j | 0)) { - s = t; - break; - } - au(); - } - } while (0); - c[p + 12 >> 2] = q; - c[s >> 2] = p; - n = j; - o = k; - break; - } - r = i; - m = c[d + (24 - h) >> 2] | 0; - t = c[d + (12 - h) >> 2] | 0; - do { - if ((t | 0) == (r | 0)) { - u = 16 - h | 0; - v = d + (u + 4) | 0; - w = c[v >> 2] | 0; - if ((w | 0) == 0) { - x = d + u | 0; - u = c[x >> 2] | 0; - if ((u | 0) == 0) { - y = 0; - break; - } else { - z = u; - A = x; - } - } else { - z = w; - A = v; - } - while (1) { - v = z + 20 | 0; - w = c[v >> 2] | 0; - if ((w | 0) != 0) { - z = w; - A = v; - continue; - } - v = z + 16 | 0; - w = c[v >> 2] | 0; - if ((w | 0) == 0) { - break; - } else { - z = w; - A = v; - } - } - if (A >>> 0 < l >>> 0) { - au(); - } else { - c[A >> 2] = 0; - y = z; - break; - } - } else { - v = c[d + (8 - h) >> 2] | 0; - if (v >>> 0 < l >>> 0) { - au(); - } - w = v + 12 | 0; - if ((c[w >> 2] | 0) != (r | 0)) { - au(); - } - x = t + 8 | 0; - if ((c[x >> 2] | 0) == (r | 0)) { - c[w >> 2] = t; - c[x >> 2] = v; - y = t; - break; - } else { - au(); - } - } - } while (0); - if ((m | 0) == 0) { - n = j; - o = k; - break; - } - t = d + (28 - h) | 0; - l = 1136 + (c[t >> 2] << 2) | 0; - do { - if ((r | 0) == (c[l >> 2] | 0)) { - c[l >> 2] = y; - if ((y | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[t >> 2]); - n = j; - o = k; - break L1325; - } else { - if (m >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - i = m + 16 | 0; - if ((c[i >> 2] | 0) == (r | 0)) { - c[i >> 2] = y; - } else { - c[m + 20 >> 2] = y; - } - if ((y | 0) == 0) { - n = j; - o = k; - break L1325; - } - } - } while (0); - if (y >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - c[y + 24 >> 2] = m; - r = 16 - h | 0; - t = c[d + r >> 2] | 0; - do { - if ((t | 0) != 0) { - if (t >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[y + 16 >> 2] = t; - c[t + 24 >> 2] = y; - break; - } - } - } while (0); - t = c[d + (r + 4) >> 2] | 0; - if ((t | 0) == 0) { - n = j; - o = k; - break; - } - if (t >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[y + 20 >> 2] = t; - c[t + 24 >> 2] = y; - n = j; - o = k; - break; - } - } else { - n = a; - o = b; - } - } while (0); - a = c[212] | 0; - if (e >>> 0 < a >>> 0) { - au(); - } - y = d + (b + 4) | 0; - z = c[y >> 2] | 0; - do { - if ((z & 2 | 0) == 0) { - if ((f | 0) == (c[214] | 0)) { - A = (c[211] | 0) + o | 0; - c[211] = A; - c[214] = n; - c[n + 4 >> 2] = A | 1; - if ((n | 0) != (c[213] | 0)) { - return; - } - c[213] = 0; - c[210] = 0; - return; - } - if ((f | 0) == (c[213] | 0)) { - A = (c[210] | 0) + o | 0; - c[210] = A; - c[213] = n; - c[n + 4 >> 2] = A | 1; - c[n + A >> 2] = A; - return; - } - A = (z & -8) + o | 0; - s = z >>> 3; - L1424 : do { - if (z >>> 0 < 256) { - g = c[d + (b + 8) >> 2] | 0; - t = c[d + (b + 12) >> 2] | 0; - h = 872 + (s << 1 << 2) | 0; - do { - if ((g | 0) != (h | 0)) { - if (g >>> 0 < a >>> 0) { - au(); - } - if ((c[g + 12 >> 2] | 0) == (f | 0)) { - break; - } - au(); - } - } while (0); - if ((t | 0) == (g | 0)) { - c[208] = c[208] & ~(1 << s); - break; - } - do { - if ((t | 0) == (h | 0)) { - B = t + 8 | 0; - } else { - if (t >>> 0 < a >>> 0) { - au(); - } - m = t + 8 | 0; - if ((c[m >> 2] | 0) == (f | 0)) { - B = m; - break; - } - au(); - } - } while (0); - c[g + 12 >> 2] = t; - c[B >> 2] = g; - } else { - h = e; - m = c[d + (b + 24) >> 2] | 0; - l = c[d + (b + 12) >> 2] | 0; - do { - if ((l | 0) == (h | 0)) { - i = d + (b + 20) | 0; - p = c[i >> 2] | 0; - if ((p | 0) == 0) { - q = d + (b + 16) | 0; - v = c[q >> 2] | 0; - if ((v | 0) == 0) { - C = 0; - break; - } else { - D = v; - E = q; - } - } else { - D = p; - E = i; - } - while (1) { - i = D + 20 | 0; - p = c[i >> 2] | 0; - if ((p | 0) != 0) { - D = p; - E = i; - continue; - } - i = D + 16 | 0; - p = c[i >> 2] | 0; - if ((p | 0) == 0) { - break; - } else { - D = p; - E = i; - } - } - if (E >>> 0 < a >>> 0) { - au(); - } else { - c[E >> 2] = 0; - C = D; - break; - } - } else { - i = c[d + (b + 8) >> 2] | 0; - if (i >>> 0 < a >>> 0) { - au(); - } - p = i + 12 | 0; - if ((c[p >> 2] | 0) != (h | 0)) { - au(); - } - q = l + 8 | 0; - if ((c[q >> 2] | 0) == (h | 0)) { - c[p >> 2] = l; - c[q >> 2] = i; - C = l; - break; - } else { - au(); - } - } - } while (0); - if ((m | 0) == 0) { - break; - } - l = d + (b + 28) | 0; - g = 1136 + (c[l >> 2] << 2) | 0; - do { - if ((h | 0) == (c[g >> 2] | 0)) { - c[g >> 2] = C; - if ((C | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[l >> 2]); - break L1424; - } else { - if (m >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - t = m + 16 | 0; - if ((c[t >> 2] | 0) == (h | 0)) { - c[t >> 2] = C; - } else { - c[m + 20 >> 2] = C; - } - if ((C | 0) == 0) { - break L1424; - } - } - } while (0); - if (C >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - c[C + 24 >> 2] = m; - h = c[d + (b + 16) >> 2] | 0; - do { - if ((h | 0) != 0) { - if (h >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[C + 16 >> 2] = h; - c[h + 24 >> 2] = C; - break; - } - } - } while (0); - h = c[d + (b + 20) >> 2] | 0; - if ((h | 0) == 0) { - break; - } - if (h >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[C + 20 >> 2] = h; - c[h + 24 >> 2] = C; - break; - } - } - } while (0); - c[n + 4 >> 2] = A | 1; - c[n + A >> 2] = A; - if ((n | 0) != (c[213] | 0)) { - F = A; - break; - } - c[210] = A; - return; - } else { - c[y >> 2] = z & -2; - c[n + 4 >> 2] = o | 1; - c[n + o >> 2] = o; - F = o; - } - } while (0); - o = F >>> 3; - if (F >>> 0 < 256) { - z = o << 1; - y = 872 + (z << 2) | 0; - C = c[208] | 0; - b = 1 << o; - do { - if ((C & b | 0) == 0) { - c[208] = C | b; - G = y; - H = 872 + (z + 2 << 2) | 0; - } else { - o = 872 + (z + 2 << 2) | 0; - d = c[o >> 2] | 0; - if (d >>> 0 >= (c[212] | 0) >>> 0) { - G = d; - H = o; - break; - } - au(); - } - } while (0); - c[H >> 2] = n; - c[G + 12 >> 2] = n; - c[n + 8 >> 2] = G; - c[n + 12 >> 2] = y; - return; - } - y = n; - G = F >>> 8; - do { - if ((G | 0) == 0) { - I = 0; - } else { - if (F >>> 0 > 16777215) { - I = 31; - break; - } - H = (G + 1048320 | 0) >>> 16 & 8; - z = G << H; - b = (z + 520192 | 0) >>> 16 & 4; - C = z << b; - z = (C + 245760 | 0) >>> 16 & 2; - o = 14 - (b | H | z) + (C << z >>> 15) | 0; - I = F >>> ((o + 7 | 0) >>> 0) & 1 | o << 1; - } - } while (0); - G = 1136 + (I << 2) | 0; - c[n + 28 >> 2] = I; - c[n + 20 >> 2] = 0; - c[n + 16 >> 2] = 0; - o = c[209] | 0; - z = 1 << I; - if ((o & z | 0) == 0) { - c[209] = o | z; - c[G >> 2] = y; - c[n + 24 >> 2] = G; - c[n + 12 >> 2] = n; - c[n + 8 >> 2] = n; - return; - } - if ((I | 0) == 31) { - J = 0; - } else { - J = 25 - (I >>> 1) | 0; - } - I = F << J; - J = c[G >> 2] | 0; - while (1) { - if ((c[J + 4 >> 2] & -8 | 0) == (F | 0)) { - break; - } - K = J + 16 + (I >>> 31 << 2) | 0; - G = c[K >> 2] | 0; - if ((G | 0) == 0) { - L = 1120; - break; - } else { - I = I << 1; - J = G; - } - } - if ((L | 0) == 1120) { - if (K >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - c[K >> 2] = y; - c[n + 24 >> 2] = J; - c[n + 12 >> 2] = n; - c[n + 8 >> 2] = n; - return; - } - K = J + 8 | 0; - L = c[K >> 2] | 0; - I = c[212] | 0; - if (J >>> 0 < I >>> 0) { - au(); - } - if (L >>> 0 < I >>> 0) { - au(); - } - c[L + 12 >> 2] = y; - c[K >> 2] = y; - c[n + 8 >> 2] = L; - c[n + 12 >> 2] = J; - c[n + 24 >> 2] = 0; - return; -} -function ca(a) { - a = a | 0; - var b = 0, d = 0, e = 0; - b = (a | 0) == 0 ? 1 : a; - while (1) { - d = bL(b) | 0; - if ((d | 0) != 0) { - e = 1164; - break; - } - a = (F = c[328] | 0, c[328] = F + 0, F); - if ((a | 0) == 0) { - break; - } - a5[a & 1](); - } - if ((e | 0) == 1164) { - return d | 0; - } - d = aJ(4) | 0; - c[d >> 2] = 560; - as(d | 0, 688, 6); - return 0; -} -function cb(a, b) { - a = a | 0; - b = b | 0; - return ca(a) | 0; -} -function cc(a) { - a = a | 0; - return; -} -function cd(a) { - a = a | 0; - return 360 | 0; -} -function ce(a) { - a = a | 0; - return 448 | 0; -} -function cf(a) { - a = a | 0; - return (F = c[328] | 0, c[328] = a, F) | 0; -} -function cg(a) { - a = a | 0; - c[a >> 2] = 560; - return; -} -function ch(a) { - a = a | 0; - c[a >> 2] = 592; - return; -} -function ci(a) { - a = a | 0; - if ((a | 0) != 0) { - bM(a); - } - return; -} -function cj(a, b) { - a = a | 0; - b = b | 0; - ci(a); - return; -} -function ck(a) { - a = a | 0; - ci(a); - return; -} -function cl(a, b) { - a = a | 0; - b = b | 0; - ck(a); - return; -} -function cm(a) { - a = a | 0; - ci(a); - return; -} -function cn(a) { - a = a | 0; - ci(a); - return; -} -function co(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - return cp(a, b, c, 0, 0, 0) | 0; -} -function cp(b, d, e, f, g, h) { - b = b | 0; - d = d | 0; - e = e | 0; - f = f | 0; - g = g | 0; - h = h | 0; - var j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0, M = 0, N = 0, O = 0, P = 0, Q = 0, R = 0, S = 0, T = 0, U = 0, V = 0, W = 0, X = 0, Y = 0, Z = 0, _ = 0, $ = 0, aa = 0, ab = 0, ac = 0, ad = 0; - j = i; - if ((e | 0) == 0) { - k = -1; - i = j; - return k | 0; - } - l = c[44] | 0; - if ((l | 0) == 0) { - c[196] = 1; - c[44] = 1; - m = 1; - n = 1; - o = 1190; - } else { - p = c[196] | 0; - q = c[74] | 0; - if ((q | 0) == -1 | (p | 0) != 0) { - m = p; - n = l; - o = 1190; - } else { - r = q; - s = p; - t = l; - } - } - if ((o | 0) == 1190) { - l = (aP(344) | 0) != 0 | 0; - c[74] = l; - r = l; - s = m; - t = n; - } - n = a[e] | 0; - if (n << 24 >> 24 == 45) { - u = h | 2; - o = 1194; - } else { - m = (r | 0) != 0 | n << 24 >> 24 == 43 ? h & -2 : h; - if (n << 24 >> 24 == 43) { - u = m; - o = 1194; - } else { - v = e; - w = m; - } - } - if ((o | 0) == 1194) { - v = e + 1 | 0; - w = u; - } - c[198] = 0; - if ((s | 0) == 0) { - x = t; - o = 1198; - } else { - c[50] = -1; - c[48] = -1; - z = t; - A = s; - o = 1197; - } - while (1) { - if ((o | 0) == 1197) { - o = 0; - if ((A | 0) == 0) { - x = z; - o = 1198; - continue; - } else { - B = z; - } - } else if ((o | 0) == 1198) { - o = 0; - s = c[40] | 0; - if ((a[s] | 0) == 0) { - B = x; - } else { - C = s; - D = x; - break; - } - } - c[196] = 0; - if ((B | 0) >= (b | 0)) { - o = 1200; - break; - } - E = d + (B << 2) | 0; - F = c[E >> 2] | 0; - c[40] = F; - if ((a[F] | 0) == 45) { - G = F + 1 | 0; - H = a[G] | 0; - if (H << 24 >> 24 != 0) { - o = 1232; - break; - } - if ((aB(v | 0, 45) | 0) != 0) { - o = 1232; - break; - } - } - c[40] = 824; - if ((w & 2 | 0) != 0) { - o = 1217; - break; - } - if ((w & 1 | 0) == 0) { - k = -1; - o = 1298; - break; - } - s = c[48] | 0; - do { - if ((s | 0) == -1) { - c[48] = B; - I = B; - J = 0; - } else { - t = c[50] | 0; - if ((t | 0) == -1) { - I = B; - J = 0; - break; - } - u = t - s | 0; - e = B - t | 0; - m = (u | 0) % (e | 0) | 0; - if ((m | 0) == 0) { - K = e; - } else { - n = e; - h = m; - while (1) { - m = (n | 0) % (h | 0) | 0; - if ((m | 0) == 0) { - K = h; - break; - } else { - n = h; - h = m; - } - } - } - h = (B - s | 0) / (K | 0) | 0; - do { - if ((K | 0) > 0) { - n = -u | 0; - if ((h | 0) > 0) { - L = 0; - } else { - M = B; - N = t; - O = s; - P = 0; - break; - } - do { - m = L + t | 0; - r = d + (m << 2) | 0; - l = 0; - p = m; - m = c[r >> 2] | 0; - while (1) { - q = ((p | 0) < (t | 0) ? e : n) + p | 0; - Q = d + (q << 2) | 0; - R = c[Q >> 2] | 0; - c[Q >> 2] = m; - c[r >> 2] = R; - Q = l + 1 | 0; - if ((Q | 0) < (h | 0)) { - l = Q; - p = q; - m = R; - } else { - break; - } - } - L = L + 1 | 0; - } while ((L | 0) < (K | 0)); - M = c[44] | 0; - N = c[50] | 0; - O = c[48] | 0; - P = c[196] | 0; - } else { - M = B; - N = t; - O = s; - P = 0; - } - } while (0); - c[48] = M - N + O; - c[50] = -1; - I = M; - J = P; - } - } while (0); - s = I + 1 | 0; - c[44] = s; - z = s; - A = J; - o = 1197; - } - do { - if ((o | 0) == 1298) { - i = j; - return k | 0; - } else if ((o | 0) == 1232) { - J = c[48] | 0; - A = c[50] | 0; - if ((J | 0) != -1 & (A | 0) == -1) { - c[50] = B; - S = a[G] | 0; - T = B; - } else { - S = H; - T = A; - } - if (S << 24 >> 24 == 0) { - C = F; - D = B; - break; - } - c[40] = G; - if ((a[G] | 0) != 45) { - C = G; - D = B; - break; - } - if ((a[F + 2 | 0] | 0) != 0) { - C = G; - D = B; - break; - } - A = B + 1 | 0; - c[44] = A; - c[40] = 824; - if ((T | 0) != -1) { - z = T - J | 0; - I = A - T | 0; - P = (z | 0) % (I | 0) | 0; - if ((P | 0) == 0) { - U = I; - } else { - M = I; - O = P; - while (1) { - P = (M | 0) % (O | 0) | 0; - if ((P | 0) == 0) { - U = O; - break; - } else { - M = O; - O = P; - } - } - } - O = (A - J | 0) / (U | 0) | 0; - do { - if ((U | 0) > 0) { - M = -z | 0; - if ((O | 0) > 0) { - V = 0; - } else { - W = T; - X = J; - Y = A; - break; - } - do { - P = V + T | 0; - N = d + (P << 2) | 0; - K = 0; - L = P; - P = c[N >> 2] | 0; - while (1) { - x = ((L | 0) < (T | 0) ? I : M) + L | 0; - s = d + (x << 2) | 0; - t = c[s >> 2] | 0; - c[s >> 2] = P; - c[N >> 2] = t; - s = K + 1 | 0; - if ((s | 0) < (O | 0)) { - K = s; - L = x; - P = t; - } else { - break; - } - } - V = V + 1 | 0; - } while ((V | 0) < (U | 0)); - W = c[50] | 0; - X = c[48] | 0; - Y = c[44] | 0; - } else { - W = T; - X = J; - Y = A; - } - } while (0); - c[44] = X - W + Y; - } - c[50] = -1; - c[48] = -1; - k = -1; - i = j; - return k | 0; - } else if ((o | 0) == 1200) { - c[40] = 824; - A = c[50] | 0; - J = c[48] | 0; - do { - if ((A | 0) == -1) { - if ((J | 0) == -1) { - break; - } - c[44] = J; - } else { - O = A - J | 0; - I = B - A | 0; - z = (O | 0) % (I | 0) | 0; - if ((z | 0) == 0) { - Z = I; - } else { - M = I; - P = z; - while (1) { - z = (M | 0) % (P | 0) | 0; - if ((z | 0) == 0) { - Z = P; - break; - } else { - M = P; - P = z; - } - } - } - P = (B - J | 0) / (Z | 0) | 0; - do { - if ((Z | 0) > 0) { - M = -O | 0; - if ((P | 0) > 0) { - _ = 0; - } else { - $ = A; - aa = J; - ab = B; - break; - } - do { - z = _ + A | 0; - L = d + (z << 2) | 0; - K = 0; - N = z; - z = c[L >> 2] | 0; - while (1) { - t = ((N | 0) < (A | 0) ? I : M) + N | 0; - x = d + (t << 2) | 0; - s = c[x >> 2] | 0; - c[x >> 2] = z; - c[L >> 2] = s; - x = K + 1 | 0; - if ((x | 0) < (P | 0)) { - K = x; - N = t; - z = s; - } else { - break; - } - } - _ = _ + 1 | 0; - } while ((_ | 0) < (Z | 0)); - $ = c[50] | 0; - aa = c[48] | 0; - ab = c[44] | 0; - } else { - $ = A; - aa = J; - ab = B; - } - } while (0); - c[44] = aa - $ + ab; - } - } while (0); - c[50] = -1; - c[48] = -1; - k = -1; - i = j; - return k | 0; - } else if ((o | 0) == 1217) { - c[44] = B + 1; - c[198] = c[E >> 2]; - k = 1; - i = j; - return k | 0; - } - } while (0); - E = (f | 0) != 0; - L1659 : do { - if (E) { - if ((C | 0) == (c[d + (D << 2) >> 2] | 0)) { - ac = C; - break; - } - B = a[C] | 0; - do { - if (B << 24 >> 24 == 45) { - c[40] = C + 1; - ad = 0; - } else { - if ((w & 4 | 0) == 0) { - ac = C; - break L1659; - } - if (B << 24 >> 24 == 58) { - ad = 0; - break; - } - ad = (aB(v | 0, B << 24 >> 24 | 0) | 0) != 0 | 0; - } - } while (0); - B = cv(d, v, f, g, ad) | 0; - if ((B | 0) == -1) { - ac = c[40] | 0; - break; - } - c[40] = 824; - k = B; - i = j; - return k | 0; - } else { - ac = C; - } - } while (0); - C = ac + 1 | 0; - c[40] = C; - ad = a[ac] | 0; - ac = ad << 24 >> 24; - if ((ad << 24 >> 24 | 0) == 45) { - if ((a[C] | 0) == 0) { - o = 1260; - } - } else if ((ad << 24 >> 24 | 0) == 58) { - o = 1263; - } else { - o = 1260; - } - do { - if ((o | 0) == 1260) { - w = aB(v | 0, ac | 0) | 0; - if ((w | 0) == 0) { - if (ad << 24 >> 24 != 45) { - o = 1263; - break; - } - if ((a[C] | 0) == 0) { - k = -1; - } else { - break; - } - i = j; - return k | 0; - } - D = a[w + 1 | 0] | 0; - if (E & ad << 24 >> 24 == 87 & D << 24 >> 24 == 59) { - do { - if ((a[C] | 0) == 0) { - B = (c[44] | 0) + 1 | 0; - c[44] = B; - if ((B | 0) < (b | 0)) { - c[40] = c[d + (B << 2) >> 2]; - break; - } - c[40] = 824; - do { - if ((c[46] | 0) != 0) { - if ((a[v] | 0) == 58) { - break; - } - cx(48, (y = i, i = i + 8 | 0, c[y >> 2] = ac, y) | 0); - } - } while (0); - c[42] = ac; - k = (a[v] | 0) == 58 ? 58 : 63; - i = j; - return k | 0; - } - } while (0); - B = cv(d, v, f, g, 0) | 0; - c[40] = 824; - k = B; - i = j; - return k | 0; - } - if (D << 24 >> 24 != 58) { - if ((a[C] | 0) != 0) { - k = ac; - i = j; - return k | 0; - } - c[44] = (c[44] | 0) + 1; - k = ac; - i = j; - return k | 0; - } - c[198] = 0; - do { - if ((a[C] | 0) == 0) { - if ((a[w + 2 | 0] | 0) == 58) { - break; - } - B = (c[44] | 0) + 1 | 0; - c[44] = B; - if ((B | 0) < (b | 0)) { - c[198] = c[d + (B << 2) >> 2]; - break; - } - c[40] = 824; - do { - if ((c[46] | 0) != 0) { - if ((a[v] | 0) == 58) { - break; - } - cx(48, (y = i, i = i + 8 | 0, c[y >> 2] = ac, y) | 0); - } - } while (0); - c[42] = ac; - k = (a[v] | 0) == 58 ? 58 : 63; - i = j; - return k | 0; - } else { - c[198] = C; - } - } while (0); - c[40] = 824; - c[44] = (c[44] | 0) + 1; - k = ac; - i = j; - return k | 0; - } - } while (0); - do { - if ((o | 0) == 1263) { - if ((a[C] | 0) != 0) { - break; - } - c[44] = (c[44] | 0) + 1; - } - } while (0); - do { - if ((c[46] | 0) != 0) { - if ((a[v] | 0) == 58) { - break; - } - cx(272, (y = i, i = i + 8 | 0, c[y >> 2] = ac, y) | 0); - } - } while (0); - c[42] = ac; - k = 63; - i = j; - return k | 0; -} -function cq(a, b, c, d, e) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - e = e | 0; - return cp(a, b, c, d, e, 1) | 0; -} -function cr(a, b, c, d, e) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - e = e | 0; - return cp(a, b, c, d, e, 5) | 0; -} -function cs(a) { - a = a | 0; - return ca(a) | 0; -} -function ct(a, b) { - a = a | 0; - b = b | 0; - return cs(a) | 0; -} -function cu() { - var a = 0; - a = aJ(4) | 0; - c[a >> 2] = 560; - as(a | 0, 688, 6); -} -function cv(b, d, e, f, g) { - b = b | 0; - d = d | 0; - e = e | 0; - f = f | 0; - g = g | 0; - var h = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, z = 0; - h = i; - j = c[40] | 0; - k = c[44] | 0; - l = k + 1 | 0; - c[44] = l; - m = aB(j | 0, 61) | 0; - if ((m | 0) == 0) { - n = cM(j | 0) | 0; - o = 0; - } else { - n = m - j | 0; - o = m + 1 | 0; - } - m = c[e >> 2] | 0; - L1739 : do { - if ((m | 0) != 0) { - L1741 : do { - if ((g | 0) != 0 & (n | 0) == 1) { - p = 0; - q = m; - while (1) { - if ((a[j] | 0) == (a[q] | 0)) { - if ((cM(q | 0) | 0) == 1) { - r = p; - break L1741; - } - } - p = p + 1 | 0; - q = c[e + (p << 4) >> 2] | 0; - if ((q | 0) == 0) { - break L1739; - } - } - } else { - q = 0; - p = -1; - s = m; - while (1) { - if ((ap(j | 0, s | 0, n | 0) | 0) == 0) { - if ((cM(s | 0) | 0) == (n | 0)) { - r = q; - break L1741; - } - if ((p | 0) == -1) { - t = q; - } else { - break; - } - } else { - t = p; - } - u = q + 1 | 0; - v = c[e + (u << 4) >> 2] | 0; - if ((v | 0) == 0) { - r = t; - break L1741; - } else { - q = u; - p = t; - s = v; - } - } - do { - if ((c[46] | 0) != 0) { - if ((a[d] | 0) == 58) { - break; - } - cx(304, (y = i, i = i + 16 | 0, c[y >> 2] = n, c[y + 8 >> 2] = j, y) | 0); - } - } while (0); - c[42] = 0; - w = 63; - i = h; - return w | 0; - } - } while (0); - if ((r | 0) == -1) { - break; - } - s = e + (r << 4) + 4 | 0; - p = c[s >> 2] | 0; - q = (o | 0) == 0; - if (!((p | 0) != 0 | q)) { - do { - if ((c[46] | 0) != 0) { - if ((a[d] | 0) == 58) { - break; - } - cx(208, (y = i, i = i + 16 | 0, c[y >> 2] = n, c[y + 8 >> 2] = j, y) | 0); - } - } while (0); - if ((c[e + (r << 4) + 8 >> 2] | 0) == 0) { - x = c[e + (r << 4) + 12 >> 2] | 0; - } else { - x = 0; - } - c[42] = x; - w = (a[d] | 0) == 58 ? 58 : 63; - i = h; - return w | 0; - } - do { - if ((p - 1 | 0) >>> 0 < 2) { - if (!q) { - c[198] = o; - break; - } - if ((p | 0) != 1) { - break; - } - c[44] = k + 2; - c[198] = c[b + (l << 2) >> 2]; - } - } while (0); - if (!((c[s >> 2] | 0) == 1 & (c[198] | 0) == 0)) { - if ((f | 0) != 0) { - c[f >> 2] = r; - } - p = c[e + (r << 4) + 8 >> 2] | 0; - q = c[e + (r << 4) + 12 >> 2] | 0; - if ((p | 0) == 0) { - w = q; - i = h; - return w | 0; - } - c[p >> 2] = q; - w = 0; - i = h; - return w | 0; - } - do { - if ((c[46] | 0) != 0) { - if ((a[d] | 0) == 58) { - break; - } - cx(8, (y = i, i = i + 8 | 0, c[y >> 2] = j, y) | 0); - } - } while (0); - if ((c[e + (r << 4) + 8 >> 2] | 0) == 0) { - z = c[e + (r << 4) + 12 >> 2] | 0; - } else { - z = 0; - } - c[42] = z; - c[44] = (c[44] | 0) - 1; - w = (a[d] | 0) == 58 ? 58 : 63; - i = h; - return w | 0; - } - } while (0); - if ((g | 0) != 0) { - c[44] = k; - w = -1; - i = h; - return w | 0; - } - do { - if ((c[46] | 0) != 0) { - if ((a[d] | 0) == 58) { - break; - } - cx(248, (y = i, i = i + 8 | 0, c[y >> 2] = j, y) | 0); - } - } while (0); - c[42] = 0; - w = 63; - i = h; - return w | 0; -} -function cw(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0; - d = i; - i = i + 16 | 0; - e = d | 0; - f = e; - c[f >> 2] = b; - c[f + 4 >> 2] = 0; - cy(a, e | 0); - i = d; - return; -} -function cx(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0; - d = i; - i = i + 16 | 0; - e = d | 0; - f = e; - c[f >> 2] = b; - c[f + 4 >> 2] = 0; - cz(a, e | 0); - i = d; - return; -} -function cy(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0; - d = i; - e = c[(aX() | 0) >> 2] | 0; - f = c[r >> 2] | 0; - av(c[o >> 2] | 0, 432, (y = i, i = i + 8 | 0, c[y >> 2] = f, y) | 0) | 0; - if ((a | 0) != 0) { - f = c[o >> 2] | 0; - aQ(f | 0, a | 0, b | 0) | 0; - b = c[o >> 2] | 0; - aE(472, 2, 1, b | 0) | 0; - } - b = c[o >> 2] | 0; - a = at(e | 0) | 0; - av(b | 0, 384, (y = i, i = i + 8 | 0, c[y >> 2] = a, y) | 0) | 0; - i = d; - return; -} -function cz(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0; - d = i; - e = c[r >> 2] | 0; - av(c[o >> 2] | 0, 376, (y = i, i = i + 8 | 0, c[y >> 2] = e, y) | 0) | 0; - if ((a | 0) != 0) { - e = c[o >> 2] | 0; - aQ(e | 0, a | 0, b | 0) | 0; - } - aC(10, c[o >> 2] | 0) | 0; - i = d; - return; -} -function cA(b, d) { - b = b | 0; - d = d | 0; - var e = 0, f = 0, g = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0.0, r = 0, s = 0, t = 0, u = 0, v = 0.0, w = 0, x = 0, y = 0, z = 0.0, A = 0.0, B = 0, C = 0, D = 0, E = 0.0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0, M = 0, N = 0.0, O = 0, P = 0, Q = 0.0, R = 0.0, S = 0.0; - e = b; - while (1) { - f = e + 1 | 0; - if ((aK(a[e] | 0) | 0) == 0) { - break; - } else { - e = f; - } - } - g = a[e] | 0; - if ((g << 24 >> 24 | 0) == 45) { - i = f; - j = 1; - } else if ((g << 24 >> 24 | 0) == 43) { - i = f; - j = 0; - } else { - i = e; - j = 0; - } - e = -1; - f = 0; - g = i; - while (1) { - k = a[g] | 0; - if (((k << 24 >> 24) - 48 | 0) >>> 0 < 10) { - l = e; - } else { - if (k << 24 >> 24 != 46 | (e | 0) > -1) { - break; - } else { - l = f; - } - } - e = l; - f = f + 1 | 0; - g = g + 1 | 0; - } - l = g + (-f | 0) | 0; - i = (e | 0) < 0; - m = ((i ^ 1) << 31 >> 31) + f | 0; - n = (m | 0) > 18; - o = (n ? -18 : -m | 0) + (i ? f : e) | 0; - e = n ? 18 : m; - do { - if ((e | 0) == 0) { - p = b; - q = 0.0; - } else { - if ((e | 0) > 9) { - m = l; - n = e; - f = 0; - while (1) { - i = a[m] | 0; - r = m + 1 | 0; - if (i << 24 >> 24 == 46) { - s = a[r] | 0; - t = m + 2 | 0; - } else { - s = i; - t = r; - } - u = (f * 10 | 0) - 48 + (s << 24 >> 24) | 0; - r = n - 1 | 0; - if ((r | 0) > 9) { - m = t; - n = r; - f = u; - } else { - break; - } - } - v = +(u | 0) * 1.0e9; - w = 9; - x = t; - y = 1393; - } else { - if ((e | 0) > 0) { - v = 0.0; - w = e; - x = l; - y = 1393; - } else { - z = 0.0; - A = 0.0; - } - } - if ((y | 0) == 1393) { - f = x; - n = w; - m = 0; - while (1) { - r = a[f] | 0; - i = f + 1 | 0; - if (r << 24 >> 24 == 46) { - B = a[i] | 0; - C = f + 2 | 0; - } else { - B = r; - C = i; - } - D = (m * 10 | 0) - 48 + (B << 24 >> 24) | 0; - i = n - 1 | 0; - if ((i | 0) > 0) { - f = C; - n = i; - m = D; - } else { - break; - } - } - z = +(D | 0); - A = v; - } - E = A + z; - do { - if ((k << 24 >> 24 | 0) == 69 | (k << 24 >> 24 | 0) == 101) { - m = g + 1 | 0; - n = a[m] | 0; - if ((n << 24 >> 24 | 0) == 43) { - F = g + 2 | 0; - G = 0; - } else if ((n << 24 >> 24 | 0) == 45) { - F = g + 2 | 0; - G = 1; - } else { - F = m; - G = 0; - } - m = a[F] | 0; - if (((m << 24 >> 24) - 48 | 0) >>> 0 < 10) { - H = F; - I = 0; - J = m; - } else { - K = 0; - L = F; - M = G; - break; - } - while (1) { - m = (I * 10 | 0) - 48 + (J << 24 >> 24) | 0; - n = H + 1 | 0; - f = a[n] | 0; - if (((f << 24 >> 24) - 48 | 0) >>> 0 < 10) { - H = n; - I = m; - J = f; - } else { - K = m; - L = n; - M = G; - break; - } - } - } else { - K = 0; - L = g; - M = 0; - } - } while (0); - n = o + ((M | 0) == 0 ? K : -K | 0) | 0; - m = (n | 0) < 0 ? -n | 0 : n; - if ((m | 0) > 511) { - c[(aX() | 0) >> 2] = 34; - N = 1.0; - O = 88; - P = 511; - y = 1410; - } else { - if ((m | 0) == 0) { - Q = 1.0; - } else { - N = 1.0; - O = 88; - P = m; - y = 1410; - } - } - if ((y | 0) == 1410) { - while (1) { - y = 0; - if ((P & 1 | 0) == 0) { - R = N; - } else { - R = N * +h[O >> 3]; - } - m = P >> 1; - if ((m | 0) == 0) { - Q = R; - break; - } else { - N = R; - O = O + 8 | 0; - P = m; - y = 1410; - } - } - } - if ((n | 0) > -1) { - p = L; - q = E * Q; - break; - } else { - p = L; - q = E / Q; - break; - } - } - } while (0); - if ((d | 0) != 0) { - c[d >> 2] = p; - } - if ((j | 0) == 0) { - S = q; - return +S; - } - S = -0.0 - q; - return +S; -} -function cB(a, b) { - a = a | 0; - b = b | 0; - return +(+cA(a, b)); -} -function cC(a, b) { - a = a | 0; - b = b | 0; - return +(+cA(a, b)); -} -function cD(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - return +(+cA(a, b)); -} -function cE(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - return +(+cA(a, b)); -} -function cF(a) { - a = a | 0; - return +(+cA(a, 0)); -} -function cG(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0; - e = i; - i = i + 16 | 0; - f = e | 0; - e = f; - c[e >> 2] = d; - c[e + 4 >> 2] = 0; - cI(a, b, f | 0); -} -function cH(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0; - e = i; - i = i + 16 | 0; - f = e | 0; - e = f; - c[e >> 2] = d; - c[e + 4 >> 2] = 0; - cJ(a, b, f | 0); -} -function cI(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0; - e = c[(aX() | 0) >> 2] | 0; - f = c[r >> 2] | 0; - av(c[o >> 2] | 0, 336, (y = i, i = i + 8 | 0, c[y >> 2] = f, y) | 0) | 0; - if ((b | 0) != 0) { - f = c[o >> 2] | 0; - aQ(f | 0, b | 0, d | 0) | 0; - d = c[o >> 2] | 0; - aE(480, 2, 1, d | 0) | 0; - } - d = c[o >> 2] | 0; - b = at(e | 0) | 0; - av(d | 0, 392, (y = i, i = i + 8 | 0, c[y >> 2] = b, y) | 0) | 0; - aH(a | 0); -} -function cJ(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0; - e = c[r >> 2] | 0; - av(c[o >> 2] | 0, 440, (y = i, i = i + 8 | 0, c[y >> 2] = e, y) | 0) | 0; - if ((b | 0) != 0) { - e = c[o >> 2] | 0; - aQ(e | 0, b | 0, d | 0) | 0; - } - aC(10, c[o >> 2] | 0) | 0; - aH(a | 0); -} -function cK(b, d, e) { - b = b | 0; - d = d | 0; - e = e | 0; - var f = 0; - f = b | 0; - if ((b & 3) == (d & 3)) { - while (b & 3) { - if ((e | 0) == 0) return f | 0; - a[b] = a[d] | 0; - b = b + 1 | 0; - d = d + 1 | 0; - e = e - 1 | 0; - } - while ((e | 0) >= 4) { - c[b >> 2] = c[d >> 2]; - b = b + 4 | 0; - d = d + 4 | 0; - e = e - 4 | 0; - } - } - while ((e | 0) > 0) { - a[b] = a[d] | 0; - b = b + 1 | 0; - d = d + 1 | 0; - e = e - 1 | 0; - } - return f | 0; -} -function cL(b, d, e) { - b = b | 0; - d = d | 0; - e = e | 0; - var f = 0, g = 0, h = 0; - f = b + e | 0; - if ((e | 0) >= 20) { - d = d & 255; - e = b & 3; - g = d | d << 8 | d << 16 | d << 24; - h = f & ~3; - if (e) { - e = b + 4 - e | 0; - while ((b | 0) < (e | 0)) { - a[b] = d; - b = b + 1 | 0; - } - } - while ((b | 0) < (h | 0)) { - c[b >> 2] = g; - b = b + 4 | 0; - } - } - while ((b | 0) < (f | 0)) { - a[b] = d; - b = b + 1 | 0; - } -} -function cM(b) { - b = b | 0; - var c = 0; - c = b; - while (a[c] | 0) { - c = c + 1 | 0; - } - return c - b | 0; -} -function cN(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0; - e = a + c >>> 0; - return (H = b + d + (e >>> 0 < a >>> 0 | 0) >>> 0, e | 0) | 0; -} -function cO(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0; - e = b - d >>> 0; - e = b - d - (c >>> 0 > a >>> 0 | 0) >>> 0; - return (H = e, a - c >>> 0 | 0) | 0; -} -function cP(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - if ((c | 0) < 32) { - H = b << c | (a & (1 << c) - 1 << 32 - c) >>> 32 - c; - return a << c; - } - H = a << c - 32; - return 0; -} -function cQ(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - if ((c | 0) < 32) { - H = b >>> c; - return a >>> c | (b & (1 << c) - 1) << 32 - c; - } - H = 0; - return b >>> c - 32 | 0; -} -function cR(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - if ((c | 0) < 32) { - H = b >> c; - return a >>> c | (b & (1 << c) - 1) << 32 - c; - } - H = (b | 0) < 0 ? -1 : 0; - return b >> c - 32 | 0; -} -function cS(b) { - b = b | 0; - var c = 0; - c = a[n + (b >>> 24) | 0] | 0; - if ((c | 0) < 8) return c | 0; - c = a[n + (b >> 16 & 255) | 0] | 0; - if ((c | 0) < 8) return c + 8 | 0; - c = a[n + (b >> 8 & 255) | 0] | 0; - if ((c | 0) < 8) return c + 16 | 0; - return (a[n + (b & 255) | 0] | 0) + 24 | 0; -} -function cT(b) { - b = b | 0; - var c = 0; - c = a[m + (b & 255) | 0] | 0; - if ((c | 0) < 8) return c | 0; - c = a[m + (b >> 8 & 255) | 0] | 0; - if ((c | 0) < 8) return c + 8 | 0; - c = a[m + (b >> 16 & 255) | 0] | 0; - if ((c | 0) < 8) return c + 16 | 0; - return (a[m + (b >>> 24) | 0] | 0) + 24 | 0; -} -function cU(a, b) { - a = a | 0; - b = b | 0; - var c = 0, d = 0, e = 0, f = 0; - c = a & 65535; - d = b & 65535; - e = ad(d, c) | 0; - f = a >>> 16; - a = (e >>> 16) + (ad(d, f) | 0) | 0; - d = b >>> 16; - b = ad(d, c) | 0; - return (H = (a >>> 16) + (ad(d, f) | 0) + (((a & 65535) + b | 0) >>> 16) | 0, a + b << 16 | e & 65535 | 0) | 0; -} -function cV(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0, f = 0, g = 0, h = 0, i = 0; - e = b >> 31 | ((b | 0) < 0 ? -1 : 0) << 1; - f = ((b | 0) < 0 ? -1 : 0) >> 31 | ((b | 0) < 0 ? -1 : 0) << 1; - g = d >> 31 | ((d | 0) < 0 ? -1 : 0) << 1; - h = ((d | 0) < 0 ? -1 : 0) >> 31 | ((d | 0) < 0 ? -1 : 0) << 1; - i = cO(e ^ a, f ^ b, e, f) | 0; - b = H; - a = g ^ e; - e = h ^ f; - f = cO((c_(i, b, cO(g ^ c, h ^ d, g, h) | 0, H, 0) | 0) ^ a, H ^ e, a, e) | 0; - return (H = H, f) | 0; -} -function cW(a, b, d, e) { - a = a | 0; - b = b | 0; - d = d | 0; - e = e | 0; - var f = 0, g = 0, h = 0, j = 0, k = 0, l = 0, m = 0; - f = i; - i = i + 8 | 0; - g = f | 0; - h = b >> 31 | ((b | 0) < 0 ? -1 : 0) << 1; - j = ((b | 0) < 0 ? -1 : 0) >> 31 | ((b | 0) < 0 ? -1 : 0) << 1; - k = e >> 31 | ((e | 0) < 0 ? -1 : 0) << 1; - l = ((e | 0) < 0 ? -1 : 0) >> 31 | ((e | 0) < 0 ? -1 : 0) << 1; - m = cO(h ^ a, j ^ b, h, j) | 0; - b = H; - a = cO(k ^ d, l ^ e, k, l) | 0; - c_(m, b, a, H, g) | 0; - a = cO(c[g >> 2] ^ h, c[g + 4 >> 2] ^ j, h, j) | 0; - j = H; - i = f; - return (H = j, a) | 0; -} -function cX(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0, f = 0; - e = a; - a = c; - c = cU(e, a) | 0; - f = H; - return (H = (ad(b, a) | 0) + (ad(d, e) | 0) + f | f & 0, c | 0 | 0) | 0; -} -function cY(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0; - e = c_(a, b, c, d, 0) | 0; - return (H = H, e) | 0; -} -function cZ(a, b, d, e) { - a = a | 0; - b = b | 0; - d = d | 0; - e = e | 0; - var f = 0, g = 0; - f = i; - i = i + 8 | 0; - g = f | 0; - c_(a, b, d, e, g) | 0; - i = f; - return (H = c[g + 4 >> 2] | 0, c[g >> 2] | 0) | 0; -} -function c_(a, b, d, e, f) { - a = a | 0; - b = b | 0; - d = d | 0; - e = e | 0; - f = f | 0; - var g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, I = 0, J = 0, K = 0, L = 0, M = 0; - g = a; - h = b; - i = h; - j = d; - k = e; - l = k; - if ((i | 0) == 0) { - m = (f | 0) != 0; - if ((l | 0) == 0) { - if (m) { - c[f >> 2] = (g >>> 0) % (j >>> 0); - c[f + 4 >> 2] = 0; - } - n = 0; - o = (g >>> 0) / (j >>> 0) >>> 0; - return (H = n, o) | 0; - } else { - if (!m) { - n = 0; - o = 0; - return (H = n, o) | 0; - } - c[f >> 2] = a | 0; - c[f + 4 >> 2] = b & 0; - n = 0; - o = 0; - return (H = n, o) | 0; - } - } - m = (l | 0) == 0; - do { - if ((j | 0) == 0) { - if (m) { - if ((f | 0) != 0) { - c[f >> 2] = (i >>> 0) % (j >>> 0); - c[f + 4 >> 2] = 0; - } - n = 0; - o = (i >>> 0) / (j >>> 0) >>> 0; - return (H = n, o) | 0; - } - if ((g | 0) == 0) { - if ((f | 0) != 0) { - c[f >> 2] = 0; - c[f + 4 >> 2] = (i >>> 0) % (l >>> 0); - } - n = 0; - o = (i >>> 0) / (l >>> 0) >>> 0; - return (H = n, o) | 0; - } - p = l - 1 | 0; - if ((p & l | 0) == 0) { - if ((f | 0) != 0) { - c[f >> 2] = a | 0; - c[f + 4 >> 2] = p & i | b & 0; - } - n = 0; - o = i >>> ((cT(l | 0) | 0) >>> 0); - return (H = n, o) | 0; - } - p = (cS(l | 0) | 0) - (cS(i | 0) | 0) | 0; - if (p >>> 0 <= 30) { - q = p + 1 | 0; - r = 31 - p | 0; - s = q; - t = i << r | g >>> (q >>> 0); - u = i >>> (q >>> 0); - v = 0; - w = g << r; - break; - } - if ((f | 0) == 0) { - n = 0; - o = 0; - return (H = n, o) | 0; - } - c[f >> 2] = a | 0; - c[f + 4 >> 2] = h | b & 0; - n = 0; - o = 0; - return (H = n, o) | 0; - } else { - if (!m) { - r = (cS(l | 0) | 0) - (cS(i | 0) | 0) | 0; - if (r >>> 0 <= 31) { - q = r + 1 | 0; - p = 31 - r | 0; - x = r - 31 >> 31; - s = q; - t = g >>> (q >>> 0) & x | i << p; - u = i >>> (q >>> 0) & x; - v = 0; - w = g << p; - break; - } - if ((f | 0) == 0) { - n = 0; - o = 0; - return (H = n, o) | 0; - } - c[f >> 2] = a | 0; - c[f + 4 >> 2] = h | b & 0; - n = 0; - o = 0; - return (H = n, o) | 0; - } - p = j - 1 | 0; - if ((p & j | 0) != 0) { - x = (cS(j | 0) | 0) + 33 - (cS(i | 0) | 0) | 0; - q = 64 - x | 0; - r = 32 - x | 0; - y = r >> 31; - z = x - 32 | 0; - A = z >> 31; - s = x; - t = r - 1 >> 31 & i >>> (z >>> 0) | (i << r | g >>> (x >>> 0)) & A; - u = A & i >>> (x >>> 0); - v = g << q & y; - w = (i << q | g >>> (z >>> 0)) & y | g << r & x - 33 >> 31; - break; - } - if ((f | 0) != 0) { - c[f >> 2] = p & g; - c[f + 4 >> 2] = 0; - } - if ((j | 0) == 1) { - n = h | b & 0; - o = a | 0 | 0; - return (H = n, o) | 0; - } else { - p = cT(j | 0) | 0; - n = i >>> (p >>> 0) | 0; - o = i << 32 - p | g >>> (p >>> 0) | 0; - return (H = n, o) | 0; - } - } - } while (0); - if ((s | 0) == 0) { - B = w; - C = v; - D = u; - E = t; - F = 0; - G = 0; - } else { - g = d | 0 | 0; - d = k | e & 0; - e = cN(g, d, -1, -1) | 0; - k = H; - i = w; - w = v; - v = u; - u = t; - t = s; - s = 0; - while (1) { - I = w >>> 31 | i << 1; - J = s | w << 1; - j = u << 1 | i >>> 31 | 0; - a = u >>> 31 | v << 1 | 0; - cO(e, k, j, a) | 0; - b = H; - h = b >> 31 | ((b | 0) < 0 ? -1 : 0) << 1; - K = h & 1; - L = cO(j, a, h & g, (((b | 0) < 0 ? -1 : 0) >> 31 | ((b | 0) < 0 ? -1 : 0) << 1) & d) | 0; - M = H; - b = t - 1 | 0; - if ((b | 0) == 0) { - break; - } else { - i = I; - w = J; - v = M; - u = L; - t = b; - s = K; - } - } - B = I; - C = J; - D = M; - E = L; - F = 0; - G = K; - } - K = C; - C = 0; - if ((f | 0) != 0) { - c[f >> 2] = E; - c[f + 4 >> 2] = D; - } - n = (K | 0) >>> 31 | (B | C) << 1 | (C << 1 | K >>> 31) & 0 | F; - o = (K << 1 | 0 >>> 31) & -2 | G; - return (H = n, o) | 0; -} -function c$(a, b) { - a = a | 0; - b = b | 0; - a1[a & 15](b | 0); -} -function c0(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - a2[a & 15](b | 0, c | 0); -} -function c1(a, b) { - a = a | 0; - b = b | 0; - return a3[a & 7](b | 0) | 0; -} -function c2(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - a4[a & 15](b | 0, c | 0, d | 0); -} -function c3(a) { - a = a | 0; - a5[a & 1](); -} -function c4(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - return a6[a & 1](b | 0, c | 0) | 0; -} -function c5(a) { - a = a | 0; - ae(0); -} -function c6(a, b) { - a = a | 0; - b = b | 0; - ae(1); -} -function c7(a) { - a = a | 0; - ae(2); - return 0; -} -function c8(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - ae(3); -} -function c9() { - ae(4); -} -function da(a, b) { - a = a | 0; - b = b | 0; - ae(5); - return 0; -} -// EMSCRIPTEN_END_FUNCS - var a1 = [ c5, c5, ch, c5, cn, c5, cc, c5, cg, c5, cm, c5, c5, c5, c5, c5 ]; - var a2 = [ c6, c6, cw, c6, cy, c6, cx, c6, cz, c6, c6, c6, c6, c6, c6, c6 ]; - var a3 = [ c7, c7, cd, c7, ce, c7, c7, c7 ]; - var a4 = [ c8, c8, cJ, c8, cI, c8, cG, c8, cH, c8, c8, c8, c8, c8, c8, c8 ]; - var a5 = [ c9, c9 ]; - var a6 = [ da, da ]; - return { - _crypto_scrypt: bu, - _strlen: cM, - _free: bM, - _realloc: bO, - _memset: cL, - _malloc: bL, - _memcpy: cK, - _calloc: bN, - runPostSets: bn, - stackAlloc: a7, - stackSave: a8, - stackRestore: a9, - setThrew: ba, - setTempRet0: bd, - setTempRet1: be, - setTempRet2: bf, - setTempRet3: bg, - setTempRet4: bh, - setTempRet5: bi, - setTempRet6: bj, - setTempRet7: bk, - setTempRet8: bl, - setTempRet9: bm, - dynCall_vi: c$, - dynCall_vii: c0, - dynCall_ii: c1, - dynCall_viii: c2, - dynCall_v: c3, - dynCall_iii: c4 - }; -// EMSCRIPTEN_END_ASM -})({Math:Math, Int8Array:Int8Array, Int16Array:Int16Array, Int32Array:Int32Array, Uint8Array:Uint8Array, Uint16Array:Uint16Array, Uint32Array:Uint32Array, Float32Array:Float32Array, Float64Array:Float64Array}, {abort:wa, assert:w, asmPrintInt:function(a, b) { - s.print("int " + a + "," + b) -}, asmPrintFloat:function(a, b) { - s.print("float " + a + "," + b) -}, min:Xc, invoke_vi:function(a, b) { - try { - s.dynCall_vi(a, b) - }catch(c) { - "number" !== typeof c && "longjmp" !== c && g(c), V.setThrew(1, 0) - } -}, invoke_vii:function(a, b, c) { - try { - s.dynCall_vii(a, b, c) - }catch(d) { - "number" !== typeof d && "longjmp" !== d && g(d), V.setThrew(1, 0) - } -}, invoke_ii:function(a, b) { - try { - return s.dynCall_ii(a, b) - }catch(c) { - "number" !== typeof c && "longjmp" !== c && g(c), V.setThrew(1, 0) - } -}, invoke_viii:function(a, b, c, d) { - try { - s.dynCall_viii(a, b, c, d) - }catch(e) { - "number" !== typeof e && "longjmp" !== e && g(e), V.setThrew(1, 0) - } -}, invoke_v:function(a) { - try { - s.dynCall_v(a) - }catch(b) { - "number" !== typeof b && "longjmp" !== b && g(b), V.setThrew(1, 0) - } -}, invoke_iii:function(a, b, c) { - try { - return s.dynCall_iii(a, b, c) - }catch(d) { - "number" !== typeof d && "longjmp" !== d && g(d), V.setThrew(1, 0) - } -}, _strncmp:function(a, b, c) { - for(var d = 0;d < c;) { - var e = G[a + d | 0], f = G[b + d | 0]; - if(e == f && 0 == e) { - break - } - if(0 == e) { - return-1 - } - if(0 == f) { - return 1 - } - if(e == f) { - d++ - }else { - return e > f ? 1 : -1 - } - } - return 0 -}, _llvm_va_end:aa(), _sysconf:function(a) { - switch(a) { - case 8: - return 4096; - case 54: - ; - case 56: - ; - case 21: - ; - case 61: - ; - case 63: - ; - case 22: - ; - case 67: - ; - case 23: - ; - case 24: - ; - case 25: - ; - case 26: - ; - case 27: - ; - case 69: - ; - case 28: - ; - case 101: - ; - case 70: - ; - case 71: - ; - case 29: - ; - case 30: - ; - case 199: - ; - case 75: - ; - case 76: - ; - case 32: - ; - case 43: - ; - case 44: - ; - case 80: - ; - case 46: - ; - case 47: - ; - case 45: - ; - case 48: - ; - case 49: - ; - case 42: - ; - case 82: - ; - case 33: - ; - case 7: - ; - case 108: - ; - case 109: - ; - case 107: - ; - case 112: - ; - case 119: - ; - case 121: - return 200809; - case 13: - ; - case 104: - ; - case 94: - ; - case 95: - ; - case 34: - ; - case 35: - ; - case 77: - ; - case 81: - ; - case 83: - ; - case 84: - ; - case 85: - ; - case 86: - ; - case 87: - ; - case 88: - ; - case 89: - ; - case 90: - ; - case 91: - ; - case 94: - ; - case 95: - ; - case 110: - ; - case 111: - ; - case 113: - ; - case 114: - ; - case 115: - ; - case 116: - ; - case 117: - ; - case 118: - ; - case 120: - ; - case 40: - ; - case 16: - ; - case 79: - ; - case 19: - return-1; - case 92: - ; - case 93: - ; - case 5: - ; - case 72: - ; - case 6: - ; - case 74: - ; - case 92: - ; - case 93: - ; - case 96: - ; - case 97: - ; - case 98: - ; - case 99: - ; - case 102: - ; - case 103: - ; - case 105: - return 1; - case 38: - ; - case 66: - ; - case 50: - ; - case 51: - ; - case 4: - return 1024; - case 15: - ; - case 64: - ; - case 41: - return 32; - case 55: - ; - case 37: - ; - case 17: - return 2147483647; - case 18: - ; - case 1: - return 47839; - case 59: - ; - case 57: - return 99; - case 68: - ; - case 58: - return 2048; - case 0: - return 2097152; - case 3: - return 65536; - case 14: - return 32768; - case 73: - return 32767; - case 39: - return 16384; - case 60: - return 1E3; - case 106: - return 700; - case 52: - return 256; - case 62: - return 255; - case 2: - return 100; - case 65: - return 64; - case 36: - return 20; - case 100: - return 16; - case 20: - return 6; - case 53: - return 4; - case 10: - return 1 - } - M(N.A); - return-1 -}, ___cxa_throw:rc, _strerror:zc, _abort:function() { - s.abort() -}, _fprintf:mc, _llvm_eh_exception:U, ___cxa_free_exception:sc, _fflush:aa(), ___buildEnvironment:wc, __reallyNegative:jc, _strchr:function(a, b) { - a--; - do { - a++; - var c = A[a]; - if(c == b) { - return a - } - }while(c); - return 0 -}, _fputc:Bc, ___setErrNo:M, _fwrite:hc, _send:fc, _write:gc, _exit:function(a) { - Ac(a) -}, ___cxa_find_matching_catch:function(a, b) { - -1 == a && (a = B[U.m >> 2]); - -1 == b && (b = B[U.m + 4 >> 2]); - var c = Array.prototype.slice.call(arguments, 2); - 0 != b && !pc(b) && 0 == B[B[b >> 2] - 8 >> 2] && (a = B[a >> 2]); - for(var d = 0;d < c.length;d++) { - if(qc(c[d], b, a)) { - return(V.setTempRet0(c[d]), a) | 0 - } - } - return(V.setTempRet0(b), a) | 0 -}, ___cxa_allocate_exception:function(a) { - return Oa(a) -}, _isspace:function(a) { - return 32 == a || 9 <= a && 13 >= a -}, __formatString:kc, ___resumeException:function(a) { - 0 == B[U.m >> 2] && (B[U.m >> 2] = a); - g(a + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.") -}, _llvm_uadd_with_overflow_i32:function(a, b) { - a >>>= 0; - b >>>= 0; - return(V.setTempRet0(4294967295 < a + b), a + b >>> 0) | 0 -}, ___cxa_does_inherit:qc, _getenv:xc, _vfprintf:function(a, b, c) { - return mc(a, b, B[c >> 2]) -}, ___cxa_begin_catch:function(a) { - oc.ta--; - return a -}, __ZSt18uncaught_exceptionv:oc, _pwrite:function(a, b, c, d) { - a = R[a]; - if(!a) { - return M(N.$), -1 - } - try { - return Ib(a, A, b, c, d) - }catch(e) { - return Zb(e), -1 - } -}, ___cxa_call_unexpected:function(a) { - s.P("Unexpected exception thrown, this is not properly supported - aborting"); - za = l; - g(a) -}, _sbrk:nc, _strerror_r:yc, ___errno_location:function() { - return rb -}, ___gxx_personality_v0:aa(), ___cxa_is_number_type:pc, _time:function(a) { - var b = Math.floor(Date.now() / 1E3); - a && (B[a >> 2] = b); - return b -}, __exit:Ac, ___cxa_end_catch:uc, STACKTOP:u, STACK_MAX:Ta, tempDoublePtr:qb, ABORT:za, cttz_i8:Wc, ctlz_i8:Vc, NaN:NaN, Infinity:Infinity, _stderr:nb, __ZTVN10__cxxabiv120__si_class_type_infoE:ob, __ZTVN10__cxxabiv117__class_type_infoE:pb, ___progname:k}, I); -s._crypto_scrypt = V._crypto_scrypt; -var ic = s._strlen = V._strlen, tc = s._free = V._free; -s._realloc = V._realloc; -var tb = s._memset = V._memset, Oa = s._malloc = V._malloc, sb = s._memcpy = V._memcpy; -s._calloc = V._calloc; -var mb = s.runPostSets = V.runPostSets; -s.dynCall_vi = V.dynCall_vi; -s.dynCall_vii = V.dynCall_vii; -s.dynCall_ii = V.dynCall_ii; -s.dynCall_viii = V.dynCall_viii; -s.dynCall_v = V.dynCall_v; -s.dynCall_iii = V.dynCall_iii; -var qa = function(a) { - return V.stackAlloc(a) -}, ja = function() { - return V.stackSave() -}, ka = function(a) { - V.stackRestore(a) -}, lc; -function X(a, b) { - a != m && ("number" == typeof a ? this.p(a) : b == m && "string" != typeof a ? this.k(a, 256) : this.k(a, b)) -} -function Yc() { - return new X(m) -} -function Zc(a, b) { - var c = $c[a.charCodeAt(b)]; - return c == m ? -1 : c -} -function ad(a) { - var b = Yc(); - b.D(a); - return b -} -function Y(a, b) { - this.h = a | 0; - this.j = b | 0 -} -Y.Ca = {}; -Y.D = function(a) { - if(-128 <= a && 128 > a) { - var b = Y.Ca[a]; - if(b) { - return b - } - } - b = new Y(a | 0, 0 > a ? -1 : 0); - -128 <= a && 128 > a && (Y.Ca[a] = b); - return b -}; -Y.p = function(a) { - return isNaN(a) || !isFinite(a) ? Y.ZERO : a <= -Y.Ea ? Y.MIN_VALUE : a + 1 >= Y.Ea ? Y.MAX_VALUE : 0 > a ? Y.p(-a).i() : new Y(a % Y.B | 0, a / Y.B | 0) -}; -Y.v = function(a, b) { - return new Y(a, b) -}; -Y.k = function(a, b) { - 0 == a.length && g(Error("number format error: empty string")); - var c = b || 10; - (2 > c || 36 < c) && g(Error("radix out of range: " + c)); - if("-" == a.charAt(0)) { - return Y.k(a.substring(1), c).i() - } - 0 <= a.indexOf("-") && g(Error('number format error: interior "-" character: ' + a)); - for(var d = Y.p(Math.pow(c, 8)), e = Y.ZERO, f = 0;f < a.length;f += 8) { - var h = Math.min(8, a.length - f), i = parseInt(a.substring(f, f + h), c); - 8 > h ? (h = Y.p(Math.pow(c, h)), e = e.multiply(h).add(Y.p(i))) : (e = e.multiply(d), e = e.add(Y.p(i))) - } - return e -}; -Y.ea = 65536; -Y.Od = 16777216; -Y.B = Y.ea * Y.ea; -Y.Pd = Y.B / 2; -Y.Qd = Y.B * Y.ea; -Y.eb = Y.B * Y.B; -Y.Ea = Y.eb / 2; -Y.ZERO = Y.D(0); -Y.ONE = Y.D(1); -Y.Da = Y.D(-1); -Y.MAX_VALUE = Y.v(-1, 2147483647); -Y.MIN_VALUE = Y.v(0, -2147483648); -Y.cb = Y.D(16777216); -q = Y.prototype; -q.Z = function() { - return this.j * Y.B + this.ob() -}; -q.toString = function(a) { - a = a || 10; - (2 > a || 36 < a) && g(Error("radix out of range: " + a)); - if(this.G()) { - return"0" - } - if(this.n()) { - if(this.o(Y.MIN_VALUE)) { - var b = Y.p(a), c = this.F(b), b = c.multiply(b).R(this); - return c.toString(a) + b.h.toString(a) - } - return"-" + this.i().toString(a) - } - for(var c = Y.p(Math.pow(a, 6)), b = this, d = "";;) { - var e = b.F(c), f = b.R(e.multiply(c)).h.toString(a), b = e; - if(b.G()) { - return f + d - } - for(;6 > f.length;) { - f = "0" + f - } - d = "" + f + d - } -}; -q.ob = function() { - return 0 <= this.h ? this.h : Y.B + this.h -}; -q.G = function() { - return 0 == this.j && 0 == this.h -}; -q.n = function() { - return 0 > this.j -}; -q.Pa = function() { - return 1 == (this.h & 1) -}; -q.o = function(a) { - return this.j == a.j && this.h == a.h -}; -q.Ra = function() { - return 0 > this.ja(Y.cb) -}; -q.qb = function(a) { - return 0 < this.ja(a) -}; -q.rb = function(a) { - return 0 <= this.ja(a) -}; -q.ja = function(a) { - if(this.o(a)) { - return 0 - } - var b = this.n(), c = a.n(); - return b && !c ? -1 : !b && c ? 1 : this.R(a).n() ? -1 : 1 -}; -q.i = function() { - return this.o(Y.MIN_VALUE) ? Y.MIN_VALUE : this.xb().add(Y.ONE) -}; -q.add = function(a) { - var b = this.j >>> 16, c = this.j & 65535, d = this.h >>> 16, e = a.j >>> 16, f = a.j & 65535, h = a.h >>> 16, i; - i = 0 + ((this.h & 65535) + (a.h & 65535)); - a = 0 + (i >>> 16); - a += d + h; - d = 0 + (a >>> 16); - d += c + f; - c = 0 + (d >>> 16); - c = c + (b + e) & 65535; - return Y.v((a & 65535) << 16 | i & 65535, c << 16 | d & 65535) -}; -q.R = function(a) { - return this.add(a.i()) -}; -q.multiply = function(a) { - if(this.G() || a.G()) { - return Y.ZERO - } - if(this.o(Y.MIN_VALUE)) { - return a.Pa() ? Y.MIN_VALUE : Y.ZERO - } - if(a.o(Y.MIN_VALUE)) { - return this.Pa() ? Y.MIN_VALUE : Y.ZERO - } - if(this.n()) { - return a.n() ? this.i().multiply(a.i()) : this.i().multiply(a).i() - } - if(a.n()) { - return this.multiply(a.i()).i() - } - if(this.Ra() && a.Ra()) { - return Y.p(this.Z() * a.Z()) - } - var b = this.j >>> 16, c = this.j & 65535, d = this.h >>> 16, e = this.h & 65535, f = a.j >>> 16, h = a.j & 65535, i = a.h >>> 16, a = a.h & 65535, j, n, y, v; - v = 0 + e * a; - y = 0 + (v >>> 16); - y += d * a; - n = 0 + (y >>> 16); - y = (y & 65535) + e * i; - n += y >>> 16; - y &= 65535; - n += c * a; - j = 0 + (n >>> 16); - n = (n & 65535) + d * i; - j += n >>> 16; - n &= 65535; - n += e * h; - j += n >>> 16; - n &= 65535; - j = j + (b * a + c * i + d * h + e * f) & 65535; - return Y.v(y << 16 | v & 65535, j << 16 | n) -}; -q.F = function(a) { - a.G() && g(Error("division by zero")); - if(this.G()) { - return Y.ZERO - } - if(this.o(Y.MIN_VALUE)) { - if(a.o(Y.ONE) || a.o(Y.Da)) { - return Y.MIN_VALUE - } - if(a.o(Y.MIN_VALUE)) { - return Y.ONE - } - var b = this.Db().F(a).shiftLeft(1); - if(b.o(Y.ZERO)) { - return a.n() ? Y.ONE : Y.Da - } - var c = this.R(a.multiply(b)); - return b.add(c.F(a)) - } - if(a.o(Y.MIN_VALUE)) { - return Y.ZERO - } - if(this.n()) { - return a.n() ? this.i().F(a.i()) : this.i().F(a).i() - } - if(a.n()) { - return this.F(a.i()).i() - } - for(var d = Y.ZERO, c = this;c.rb(a);) { - for(var b = Math.max(1, Math.floor(c.Z() / a.Z())), e = Math.ceil(Math.log(b) / Math.LN2), e = 48 >= e ? 1 : Math.pow(2, e - 48), f = Y.p(b), h = f.multiply(a);h.n() || h.qb(c);) { - b -= e, f = Y.p(b), h = f.multiply(a) - } - f.G() && (f = Y.ONE); - d = d.add(f); - c = c.R(h) - } - return d -}; -q.xb = function() { - return Y.v(~this.h, ~this.j) -}; -q.shiftLeft = function(a) { - a &= 63; - if(0 == a) { - return this - } - var b = this.h; - return 32 > a ? Y.v(b << a, this.j << a | b >>> 32 - a) : Y.v(0, b << a - 32) -}; -q.Db = function() { - var a; - a = 1; - if(0 == a) { - return this - } - var b = this.j; - return 32 > a ? Y.v(this.h >>> a | b << 32 - a, b >> a) : Y.v(b >> a - 32, 0 <= b ? 0 : -1) -}; -q = X.prototype; -q.ga = function(a, b, c, d) { - for(var e = 0, f = 0;0 <= --d;) { - var h = a * this[e++] + b[c] + f, f = Math.floor(h / 67108864); - b[c++] = h & 67108863 - } - return f -}; -q.f = 26; -q.u = 67108863; -q.K = 67108864; -q.bb = Math.pow(2, 52); -q.Aa = 26; -q.Ba = 0; -var $c = [], bd, Z; -bd = 48; -for(Z = 0;9 >= Z;++Z) { - $c[bd++] = Z -} -bd = 97; -for(Z = 10;36 > Z;++Z) { - $c[bd++] = Z -} -bd = 65; -for(Z = 10;36 > Z;++Z) { - $c[bd++] = Z -} -q = X.prototype; -q.copyTo = function(a) { - for(var b = this.b - 1;0 <= b;--b) { - a[b] = this[b] - } - a.b = this.b; - a.c = this.c -}; -q.D = function(a) { - this.b = 1; - this.c = 0 > a ? -1 : 0; - 0 < a ? this[0] = a : -1 > a ? this[0] = a + DV : this.b = 0 -}; -q.k = function(a, b) { - var c; - if(16 == b) { - c = 4 - }else { - if(8 == b) { - c = 3 - }else { - if(256 == b) { - c = 8 - }else { - if(2 == b) { - c = 1 - }else { - if(32 == b) { - c = 5 - }else { - if(4 == b) { - c = 2 - }else { - this.nb(a, b); - return - } - } - } - } - } - } - this.c = this.b = 0; - for(var d = a.length, e = p, f = 0;0 <= --d;) { - var h = 8 == c ? a[d] & 255 : Zc(a, d); - 0 > h ? "-" == a.charAt(d) && (e = l) : (e = p, 0 == f ? this[this.b++] = h : f + c > this.f ? (this[this.b - 1] |= (h & (1 << this.f - f) - 1) << f, this[this.b++] = h >> this.f - f) : this[this.b - 1] |= h << f, f += c, f >= this.f && (f -= this.f)) - } - 8 == c && 0 != (a[0] & 128) && (this.c = -1, 0 < f && (this[this.b - 1] |= (1 << this.f - f) - 1 << f)); - this.C(); - e && X.ZERO.t(this, this) -}; -q.C = function() { - for(var a = this.c & this.u;0 < this.b && this[this.b - 1] == a;) { - --this.b - } -}; -q.la = function(a, b) { - var c; - for(c = this.b - 1;0 <= c;--c) { - b[c + a] = this[c] - } - for(c = a - 1;0 <= c;--c) { - b[c] = 0 - } - b.b = this.b + a; - b.c = this.c -}; -q.jb = function(a, b) { - for(var c = a;c < this.b;++c) { - b[c - a] = this[c] - } - b.b = Math.max(this.b - a, 0); - b.c = this.c -}; -q.Qa = function(a, b) { - var c = a % this.f, d = this.f - c, e = (1 << d) - 1, f = Math.floor(a / this.f), h = this.c << c & this.u, i; - for(i = this.b - 1;0 <= i;--i) { - b[i + f + 1] = this[i] >> d | h, h = (this[i] & e) << c - } - for(i = f - 1;0 <= i;--i) { - b[i] = 0 - } - b[f] = h; - b.b = this.b + f + 1; - b.c = this.c; - b.C() -}; -q.zb = function(a, b) { - b.c = this.c; - var c = Math.floor(a / this.f); - if(c >= this.b) { - b.b = 0 - }else { - var d = a % this.f, e = this.f - d, f = (1 << d) - 1; - b[0] = this[c] >> d; - for(var h = c + 1;h < this.b;++h) { - b[h - c - 1] |= (this[h] & f) << e, b[h - c] = this[h] >> d - } - 0 < d && (b[this.b - c - 1] |= (this.c & f) << e); - b.b = this.b - c; - b.C() - } -}; -q.t = function(a, b) { - for(var c = 0, d = 0, e = Math.min(a.b, this.b);c < e;) { - d += this[c] - a[c], b[c++] = d & this.u, d >>= this.f - } - if(a.b < this.b) { - for(d -= a.c;c < this.b;) { - d += this[c], b[c++] = d & this.u, d >>= this.f - } - d += this.c - }else { - for(d += this.c;c < a.b;) { - d -= a[c], b[c++] = d & this.u, d >>= this.f - } - d -= a.c - } - b.c = 0 > d ? -1 : 0; - -1 > d ? b[c++] = this.K + d : 0 < d && (b[c++] = d); - b.b = c; - b.C() -}; -q.vb = function(a) { - var b = $.Xa, c = this.abs(), d = b.abs(), e = c.b; - for(a.b = e + d.b;0 <= --e;) { - a[e] = 0 - } - for(e = 0;e < d.b;++e) { - a[e + c.b] = c.ga(d[e], a, e, c.b) - } - a.c = 0; - a.C(); - this.c != b.c && X.ZERO.t(a, a) -}; -q.Ja = function(a, b, c) { - var d = a.abs(); - if(!(0 >= d.b)) { - var e = this.abs(); - if(e.b < d.b) { - b != m && b.D(0), c != m && this.copyTo(c) - }else { - c == m && (c = Yc()); - var f = Yc(), h = this.c, a = a.c, i = d[d.b - 1], j = 1, n; - if(0 != (n = i >>> 16)) { - i = n, j += 16 - } - if(0 != (n = i >> 8)) { - i = n, j += 8 - } - if(0 != (n = i >> 4)) { - i = n, j += 4 - } - if(0 != (n = i >> 2)) { - i = n, j += 2 - } - 0 != i >> 1 && (j += 1); - i = this.f - j; - 0 < i ? (d.Qa(i, f), e.Qa(i, c)) : (d.copyTo(f), e.copyTo(c)); - d = f.b; - e = f[d - 1]; - if(0 != e) { - n = e * (1 << this.Aa) + (1 < d ? f[d - 2] >> this.Ba : 0); - j = this.bb / n; - n = (1 << this.Aa) / n; - var y = 1 << this.Ba, v = c.b, C = v - d, D = b == m ? Yc() : b; - f.la(C, D); - 0 <= c.U(D) && (c[c.b++] = 1, c.t(D, c)); - X.ONE.la(d, D); - for(D.t(f, f);f.b < d;) { - f[f.b++] = 0 - } - for(;0 <= --C;) { - var K = c[--v] == e ? this.u : Math.floor(c[v] * j + (c[v - 1] + y) * n); - if((c[v] += f.ga(K, c, C, d)) < K) { - f.la(C, D); - for(c.t(D, c);c[v] < --K;) { - c.t(D, c) - } - } - } - b != m && (c.jb(d, b), h != a && X.ZERO.t(b, b)); - c.b = d; - c.C(); - 0 < i && c.zb(i, c); - 0 > h && X.ZERO.t(c, c) - } - } - } -}; -q.toString = function(a) { - if(0 > this.c) { - return"-" + this.i().toString(a) - } - if(16 == a) { - a = 4 - }else { - if(8 == a) { - a = 3 - }else { - if(2 == a) { - a = 1 - }else { - if(32 == a) { - a = 5 - }else { - if(4 == a) { - a = 2 - }else { - return this.Fb(a) - } - } - } - } - } - var b = (1 << a) - 1, c, d = p, e = "", f = this.b, h = this.f - f * this.f % a; - if(0 < f--) { - if(h < this.f && 0 < (c = this[f] >> h)) { - d = l, e = "0123456789abcdefghijklmnopqrstuvwxyz".charAt(c) - } - for(;0 <= f;) { - h < a ? (c = (this[f] & (1 << h) - 1) << a - h, c |= this[--f] >> (h += this.f - a)) : (c = this[f] >> (h -= a) & b, 0 >= h && (h += this.f, --f)), 0 < c && (d = l), d && (e += "0123456789abcdefghijklmnopqrstuvwxyz".charAt(c)) - } - } - return d ? e : "0" -}; -q.i = function() { - var a = Yc(); - X.ZERO.t(this, a); - return a -}; -q.abs = function() { - return 0 > this.c ? this.i() : this -}; -q.U = function(a) { - var b = this.c - a.c; - if(0 != b) { - return b - } - var c = this.b, b = c - a.b; - if(0 != b) { - return 0 > this.c ? -b : b - } - for(;0 <= --c;) { - if(0 != (b = this[c] - a[c])) { - return b - } - } - return 0 -}; -X.ZERO = ad(0); -X.ONE = ad(1); -q = X.prototype; -q.nb = function(a, b) { - this.D(0); - b == m && (b = 10); - for(var c = this.S(b), d = Math.pow(b, c), e = p, f = 0, h = 0, i = 0;i < a.length;++i) { - var j = Zc(a, i); - 0 > j ? "-" == a.charAt(i) && 0 == this.ra() && (e = l) : (h = b * h + j, ++f >= c && (this.Ia(d), this.Ha(h), h = f = 0)) - } - 0 < f && (this.Ia(Math.pow(b, f)), this.Ha(h)); - e && X.ZERO.t(this, this) -}; -q.S = function(a) { - return Math.floor(Math.LN2 * this.f / Math.log(a)) -}; -q.ra = function() { - return 0 > this.c ? -1 : 0 >= this.b || 1 == this.b && 0 >= this[0] ? 0 : 1 -}; -q.Ia = function(a) { - this[this.b] = this.ga(a - 1, this, 0, this.b); - ++this.b; - this.C() -}; -q.Ha = function(a) { - var b = 0; - if(0 != a) { - for(;this.b <= b;) { - this[this.b++] = 0 - } - for(this[b] += a;this[b] >= this.K;) { - this[b] -= this.K, ++b >= this.b && (this[this.b++] = 0), ++this[b] - } - } -}; -q.Fb = function(a) { - a == m && (a = 10); - if(0 == this.ra() || 2 > a || 36 < a) { - return"0" - } - var b = this.S(a), b = Math.pow(a, b), c = ad(b), d = Yc(), e = Yc(), f = ""; - for(this.Ja(c, d, e);0 < d.ra();) { - f = (b + e.Oa()).toString(a).substr(1) + f, d.Ja(c, d, e) - } - return e.Oa().toString(a) + f -}; -q.Oa = function() { - if(0 > this.c) { - if(1 == this.b) { - return this[0] - this.K - } - if(0 == this.b) { - return-1 - } - }else { - if(1 == this.b) { - return this[0] - } - if(0 == this.b) { - return 0 - } - } - return(this[1] & (1 << 32 - this.f) - 1) << this.f | this[0] -}; -q.fa = function(a, b) { - for(var c = 0, d = 0, e = Math.min(a.b, this.b);c < e;) { - d += this[c] + a[c], b[c++] = d & this.u, d >>= this.f - } - if(a.b < this.b) { - for(d += a.c;c < this.b;) { - d += this[c], b[c++] = d & this.u, d >>= this.f - } - d += this.c - }else { - for(d += this.c;c < a.b;) { - d += a[c], b[c++] = d & this.u, d >>= this.f - } - d += a.c - } - b.c = 0 > d ? -1 : 0; - 0 < d ? b[c++] = d : -1 > d && (b[c++] = this.K + d); - b.b = c; - b.C() -}; -var $ = {abs:function(a, b) { - var c = new Y(a, b), c = c.n() ? c.i() : c; - B[qb >> 2] = c.h; - B[qb + 4 >> 2] = c.j -}, Ka:function() { - $.kb || ($.kb = l, $.Xa = new X, $.Xa.k("4294967296", 10), $.sa = new X, $.sa.k("18446744073709551616", 10), $.xe = new X, $.ye = new X) -}, me:function(a, b) { - var c = new X; - c.k(b.toString(), 10); - var d = new X; - c.vb(d); - c = new X; - c.k(a.toString(), 10); - var e = new X; - c.fa(d, e); - return e -}, stringify:function(a, b, c) { - a = (new Y(a, b)).toString(); - c && "-" == a[0] && ($.Ka(), c = new X, c.k(a, 10), a = new X, $.sa.fa(c, a), a = a.toString(10)); - return a -}, k:function(a, b, c, d, e) { - $.Ka(); - var f = new X; - f.k(a, b); - a = new X; - a.k(c, 10); - c = new X; - c.k(d, 10); - e && 0 > f.U(X.ZERO) && (d = new X, f.fa($.sa, d), f = d); - d = p; - 0 > f.U(a) ? (f = a, d = l) : 0 < f.U(c) && (f = c, d = l); - f = Y.k(f.toString()); - B[qb >> 2] = f.h; - B[qb + 4 >> 2] = f.j; - d && g("range error") -}}; -lc = $; -var cd, dd; -s.callMain = s.$d = function(a) { - function b() { - for(var a = 0;3 > a;a++) { - d.push(0) - } - } - w(0 == L, "cannot call main when async dependencies remain! (listen on __ATMAIN__)"); - w(0 == Wa.length, "cannot call main when preRun functions remain to be called"); - a = a || []; - ab || (ab = l, Va(Xa)); - var c = a.length + 1, d = [F(J("/bin/this.program"), "i8", Ka)]; - b(); - for(var e = 0;e < c - 1;e += 1) { - d.push(F(J(a[e]), "i8", Ka)), b() - } - d.push(0); - d = F(d, "i32", Ka); - cd = u; - dd = l; - var f; - try { - f = s._main(c, d, 0) - }catch(h) { - if(h && "object" == typeof h && "ExitStatus" == h.type) { - return s.print("Exit Status: " + h.value), h.value - } - "SimulateInfiniteLoop" == h ? s.noExitRuntime = l : g(h) - }finally { - dd = p - } - s.noExitRuntime || ed(f) -}; -function lb(a) { - function b() { - ab || (ab = l, Va(Xa)); - Va(Ya); - gb = l; - s._main && kb && s.callMain(a); - if(s.postRun) { - for("function" == typeof s.postRun && (s.postRun = [s.postRun]);s.postRun.length;) { - cb(s.postRun.shift()) - } - } - Va($a) - } - a = a || s.arguments; - if(0 < L) { - s.P("run() called, but dependencies remain, so not running") - }else { - if(s.preRun) { - for("function" == typeof s.preRun && (s.preRun = [s.preRun]);s.preRun.length;) { - bb(s.preRun.shift()) - } - } - Va(Wa); - 0 < L || (s.setStatus ? (s.setStatus("Running..."), setTimeout(function() { - setTimeout(function() { - s.setStatus("") - }, 1); - za || b() - }, 1)) : b()) - } -} -s.run = s.we = lb; -function ed(a) { - za = l; - u = cd; - Va(Za); - dd && g({type:"ExitStatus", value:a}) -} -s.exit = s.de = ed; -function wa(a) { - a && s.print(a); - za = l; - g("abort() at " + Error().stack) -} -s.abort = s.abort = wa; -if(s.preInit) { - for("function" == typeof s.preInit && (s.preInit = [s.preInit]);0 < s.preInit.length;) { - s.preInit.pop()() - } -} -var kb = l; -s.noInitialRun && (kb = p); -lb(); -var scrypt = (function () { - var exports = {}; - - //--------------------------------------------------------------------------- - // Horrifying UTF-8 and hex codecs - - function encode_utf8(s) { - return encode_latin1(unescape(encodeURIComponent(s))); - } - - function encode_latin1(s) { - var result = new Uint8Array(s.length); - for (var i = 0; i < s.length; i++) { - var c = s.charCodeAt(i); - if ((c & 0xff) !== c) throw {message: "Cannot encode string in Latin1", str: s}; - result[i] = (c & 0xff); - } - return result; - } - - function decode_utf8(bs) { - return decodeURIComponent(escape(decode_latin1(bs))); - } - - function decode_latin1(bs) { - var encoded = []; - for (var i = 0; i < bs.length; i++) { - encoded.push(String.fromCharCode(bs[i])); - } - return encoded.join(''); - } - - function to_hex(bs) { - var encoded = []; - for (var i = 0; i < bs.length; i++) { - encoded.push("0123456789abcdef"[(bs[i] >> 4) & 15]); - encoded.push("0123456789abcdef"[bs[i] & 15]); - } - return encoded.join(''); - } - - //--------------------------------------------------------------------------- - - function injectBytes(bs, leftPadding) { - var p = leftPadding || 0; - var address = scrypt_raw._malloc(bs.length + p); - scrypt_raw.HEAPU8.set(bs, address + p); - for (var i = address; i < address + p; i++) { - scrypt_raw.HEAPU8[i] = 0; - } - return address; - } - - function check_injectBytes(function_name, what, thing, expected_length, leftPadding) { - check_length(function_name, what, thing, expected_length); - return injectBytes(thing, leftPadding); - } - - function extractBytes(address, length) { - var result = new Uint8Array(length); - result.set(scrypt_raw.HEAPU8.subarray(address, address + length)); - return result; - } - - //--------------------------------------------------------------------------- - - function check(function_name, result) { - if (result !== 0) { - throw {message: "scrypt_raw." + function_name + " signalled an error"}; - } - } - - function check_length(function_name, what, thing, expected_length) { - if (thing.length !== expected_length) { - throw {message: "scrypt." + function_name + " expected " + - expected_length + "-byte " + what + " but got length " + thing.length}; - } - } - - function Target(length) { - this.length = length; - this.address = scrypt_raw._malloc(length); - } - - Target.prototype.extractBytes = function (offset) { - var result = extractBytes(this.address + (offset || 0), this.length - (offset || 0)); - scrypt_raw._free(this.address); - this.address = null; - return result; - }; - - function free_all(addresses) { - for (var i = 0; i < addresses.length; i++) { - scrypt_raw._free(addresses[i]); - } - } - - //--------------------------------------------------------------------------- - - function random_bytes(count) { - var bs = new Uint8Array(count); - if(typeof(window.crypto) !== "undefined") { - if(typeof(window.crypto.getRandomValues) !== "undefined") { - window.crypto.getRandomValues(bs); - return bs; - } - } - if(typeof(window.msCrypto) !== "undefined") { - if(typeof(window.msCrypto.getRandomValues) !== "undefined") { - window.msCrypto.getRandomValues(bs); - return bs; - } - } - throw { message: "No suitable random number generator found!"}; - } - - function crypto_scrypt(passwd, salt, n, r, p, buflen) { - var buf = new Target(buflen); - var pa = injectBytes(passwd); - var sa = injectBytes(salt); - check("_crypto_scrypt", - scrypt_raw._crypto_scrypt(pa, passwd.length, - sa, salt.length, - n, 0, // 64 bits; zero upper half - r, - p, - buf.address, buf.length)); - free_all([pa, sa]); - return buf.extractBytes(); - } - - //--------------------------------------------------------------------------- - - exports.encode_utf8 = encode_utf8; - exports.encode_latin1 = encode_latin1; - exports.decode_utf8 = decode_utf8; - exports.decode_latin1 = decode_latin1; - exports.to_hex = to_hex; - - exports.random_bytes = random_bytes; - exports.crypto_scrypt = crypto_scrypt; - - return exports; -})(); - return scrypt; -}); - diff --git a/assets/www/dist/dist_js/app/vendor/socket-io.js b/assets/www/dist/dist_js/app/vendor/socket-io.js deleted file mode 100644 index b848ccb276b31924469e0d767bdd2aa5e3be0562..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/socket-io.js +++ /dev/null @@ -1,7000 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.io=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ - - module.exports = _dereq_('./lib/'); - -},{"./lib/":2}],2:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var url = _dereq_('./url'); - var parser = _dereq_('socket.io-parser'); - var Manager = _dereq_('./manager'); - var debug = _dereq_('debug')('socket.io-client'); - - /** - * Module exports. - */ - - module.exports = exports = lookup; - - /** - * Managers cache. - */ - - var cache = exports.managers = {}; - - /** - * Looks up an existing `Manager` for multiplexing. - * If the user summons: - * - * `io('http://localhost/a');` - * `io('http://localhost/b');` - * - * We reuse the existing instance based on same scheme/port/host, - * and we initialize sockets for each namespace. - * - * @api public - */ - - function lookup(uri, opts) { - if (typeof uri == 'object') { - opts = uri; - uri = undefined; - } - - opts = opts || {}; - - var parsed = url(uri); - var source = parsed.source; - var id = parsed.id; - var io; - - if (opts.forceNew || opts['force new connection'] || false === opts.multiplex) { - debug('ignoring socket cache for %s', source); - io = Manager(source, opts); - } else { - if (!cache[id]) { - debug('new io instance for %s', source); - cache[id] = Manager(source, opts); - } - io = cache[id]; - } - - return io.socket(parsed.path); - } - - /** - * Protocol version. - * - * @api public - */ - - exports.protocol = parser.protocol; - - /** - * `connect`. - * - * @param {String} uri - * @api public - */ - - exports.connect = lookup; - - /** - * Expose constructors for standalone build. - * - * @api public - */ - - exports.Manager = _dereq_('./manager'); - exports.Socket = _dereq_('./socket'); - -},{"./manager":3,"./socket":5,"./url":6,"debug":10,"socket.io-parser":46}],3:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var url = _dereq_('./url'); - var eio = _dereq_('engine.io-client'); - var Socket = _dereq_('./socket'); - var Emitter = _dereq_('component-emitter'); - var parser = _dereq_('socket.io-parser'); - var on = _dereq_('./on'); - var bind = _dereq_('component-bind'); - var object = _dereq_('object-component'); - var debug = _dereq_('debug')('socket.io-client:manager'); - var indexOf = _dereq_('indexof'); - var Backoff = _dereq_('backo2'); - - /** - * Module exports - */ - - module.exports = Manager; - - /** - * `Manager` constructor. - * - * @param {String} engine instance or engine uri/opts - * @param {Object} options - * @api public - */ - - function Manager(uri, opts){ - if (!(this instanceof Manager)) return new Manager(uri, opts); - if (uri && ('object' == typeof uri)) { - opts = uri; - uri = undefined; - } - opts = opts || {}; - - opts.path = opts.path || '/socket.io'; - this.nsps = {}; - this.subs = []; - this.opts = opts; - this.reconnection(opts.reconnection !== false); - this.reconnectionAttempts(opts.reconnectionAttempts || Infinity); - this.reconnectionDelay(opts.reconnectionDelay || 1000); - this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000); - this.randomizationFactor(opts.randomizationFactor || 0.5); - this.backoff = new Backoff({ - min: this.reconnectionDelay(), - max: this.reconnectionDelayMax(), - jitter: this.randomizationFactor() - }); - this.timeout(null == opts.timeout ? 20000 : opts.timeout); - this.readyState = 'closed'; - this.uri = uri; - this.connected = []; - this.encoding = false; - this.packetBuffer = []; - this.encoder = new parser.Encoder(); - this.decoder = new parser.Decoder(); - this.autoConnect = opts.autoConnect !== false; - if (this.autoConnect) this.open(); - } - - /** - * Propagate given event to sockets and emit on `this` - * - * @api private - */ - - Manager.prototype.emitAll = function() { - this.emit.apply(this, arguments); - for (var nsp in this.nsps) { - this.nsps[nsp].emit.apply(this.nsps[nsp], arguments); - } - }; - - /** - * Update `socket.id` of all sockets - * - * @api private - */ - - Manager.prototype.updateSocketIds = function(){ - for (var nsp in this.nsps) { - this.nsps[nsp].id = this.engine.id; - } - }; - - /** - * Mix in `Emitter`. - */ - - Emitter(Manager.prototype); - - /** - * Sets the `reconnection` config. - * - * @param {Boolean} true/false if it should automatically reconnect - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnection = function(v){ - if (!arguments.length) return this._reconnection; - this._reconnection = !!v; - return this; - }; - - /** - * Sets the reconnection attempts config. - * - * @param {Number} max reconnection attempts before giving up - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnectionAttempts = function(v){ - if (!arguments.length) return this._reconnectionAttempts; - this._reconnectionAttempts = v; - return this; - }; - - /** - * Sets the delay between reconnections. - * - * @param {Number} delay - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnectionDelay = function(v){ - if (!arguments.length) return this._reconnectionDelay; - this._reconnectionDelay = v; - this.backoff && this.backoff.setMin(v); - return this; - }; - - Manager.prototype.randomizationFactor = function(v){ - if (!arguments.length) return this._randomizationFactor; - this._randomizationFactor = v; - this.backoff && this.backoff.setJitter(v); - return this; - }; - - /** - * Sets the maximum delay between reconnections. - * - * @param {Number} delay - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnectionDelayMax = function(v){ - if (!arguments.length) return this._reconnectionDelayMax; - this._reconnectionDelayMax = v; - this.backoff && this.backoff.setMax(v); - return this; - }; - - /** - * Sets the connection timeout. `false` to disable - * - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.timeout = function(v){ - if (!arguments.length) return this._timeout; - this._timeout = v; - return this; - }; - - /** - * Starts trying to reconnect if reconnection is enabled and we have not - * started reconnecting yet - * - * @api private - */ - - Manager.prototype.maybeReconnectOnOpen = function() { - // Only try to reconnect if it's the first time we're connecting - if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) { - // keeps reconnection from firing twice for the same reconnection loop - this.reconnect(); - } - }; - - - /** - * Sets the current transport `socket`. - * - * @param {Function} optional, callback - * @return {Manager} self - * @api public - */ - - Manager.prototype.open = - Manager.prototype.connect = function(fn){ - debug('readyState %s', this.readyState); - if (~this.readyState.indexOf('open')) return this; - - debug('opening %s', this.uri); - this.engine = eio(this.uri, this.opts); - var socket = this.engine; - var self = this; - this.readyState = 'opening'; - this.skipReconnect = false; - - // emit `open` - var openSub = on(socket, 'open', function() { - self.onopen(); - fn && fn(); - }); - - // emit `connect_error` - var errorSub = on(socket, 'error', function(data){ - debug('connect_error'); - self.cleanup(); - self.readyState = 'closed'; - self.emitAll('connect_error', data); - if (fn) { - var err = new Error('Connection error'); - err.data = data; - fn(err); - } else { - // Only do this if there is no fn to handle the error - self.maybeReconnectOnOpen(); - } - }); - - // emit `connect_timeout` - if (false !== this._timeout) { - var timeout = this._timeout; - debug('connect attempt will timeout after %d', timeout); - - // set timer - var timer = setTimeout(function(){ - debug('connect attempt timed out after %d', timeout); - openSub.destroy(); - socket.close(); - socket.emit('error', 'timeout'); - self.emitAll('connect_timeout', timeout); - }, timeout); - - this.subs.push({ - destroy: function(){ - clearTimeout(timer); - } - }); - } - - this.subs.push(openSub); - this.subs.push(errorSub); - - return this; - }; - - /** - * Called upon transport open. - * - * @api private - */ - - Manager.prototype.onopen = function(){ - debug('open'); - - // clear old subs - this.cleanup(); - - // mark as open - this.readyState = 'open'; - this.emit('open'); - - // add new subs - var socket = this.engine; - this.subs.push(on(socket, 'data', bind(this, 'ondata'))); - this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded'))); - this.subs.push(on(socket, 'error', bind(this, 'onerror'))); - this.subs.push(on(socket, 'close', bind(this, 'onclose'))); - }; - - /** - * Called with data. - * - * @api private - */ - - Manager.prototype.ondata = function(data){ - this.decoder.add(data); - }; - - /** - * Called when parser fully decodes a packet. - * - * @api private - */ - - Manager.prototype.ondecoded = function(packet) { - this.emit('packet', packet); - }; - - /** - * Called upon socket error. - * - * @api private - */ - - Manager.prototype.onerror = function(err){ - debug('error', err); - this.emitAll('error', err); - }; - - /** - * Creates a new socket for the given `nsp`. - * - * @return {Socket} - * @api public - */ - - Manager.prototype.socket = function(nsp){ - var socket = this.nsps[nsp]; - if (!socket) { - socket = new Socket(this, nsp); - this.nsps[nsp] = socket; - var self = this; - socket.on('connect', function(){ - socket.id = self.engine.id; - if (!~indexOf(self.connected, socket)) { - self.connected.push(socket); - } - }); - } - return socket; - }; - - /** - * Called upon a socket close. - * - * @param {Socket} socket - */ - - Manager.prototype.destroy = function(socket){ - var index = indexOf(this.connected, socket); - if (~index) this.connected.splice(index, 1); - if (this.connected.length) return; - - this.close(); - }; - - /** - * Writes a packet. - * - * @param {Object} packet - * @api private - */ - - Manager.prototype.packet = function(packet){ - debug('writing packet %j', packet); - var self = this; - - if (!self.encoding) { - // encode, then write to engine with result - self.encoding = true; - this.encoder.encode(packet, function(encodedPackets) { - for (var i = 0; i < encodedPackets.length; i++) { - self.engine.write(encodedPackets[i]); - } - self.encoding = false; - self.processPacketQueue(); - }); - } else { // add packet to the queue - self.packetBuffer.push(packet); - } - }; - - /** - * If packet buffer is non-empty, begins encoding the - * next packet in line. - * - * @api private - */ - - Manager.prototype.processPacketQueue = function() { - if (this.packetBuffer.length > 0 && !this.encoding) { - var pack = this.packetBuffer.shift(); - this.packet(pack); - } - }; - - /** - * Clean up transport subscriptions and packet buffer. - * - * @api private - */ - - Manager.prototype.cleanup = function(){ - var sub; - while (sub = this.subs.shift()) sub.destroy(); - - this.packetBuffer = []; - this.encoding = false; - - this.decoder.destroy(); - }; - - /** - * Close the current socket. - * - * @api private - */ - - Manager.prototype.close = - Manager.prototype.disconnect = function(){ - this.skipReconnect = true; - this.backoff.reset(); - this.readyState = 'closed'; - this.engine && this.engine.close(); - }; - - /** - * Called upon engine close. - * - * @api private - */ - - Manager.prototype.onclose = function(reason){ - debug('close'); - this.cleanup(); - this.backoff.reset(); - this.readyState = 'closed'; - this.emit('close', reason); - if (this._reconnection && !this.skipReconnect) { - this.reconnect(); - } - }; - - /** - * Attempt a reconnection. - * - * @api private - */ - - Manager.prototype.reconnect = function(){ - if (this.reconnecting || this.skipReconnect) return this; - - var self = this; - - if (this.backoff.attempts >= this._reconnectionAttempts) { - debug('reconnect failed'); - this.backoff.reset(); - this.emitAll('reconnect_failed'); - this.reconnecting = false; - } else { - var delay = this.backoff.duration(); - debug('will wait %dms before reconnect attempt', delay); - - this.reconnecting = true; - var timer = setTimeout(function(){ - if (self.skipReconnect) return; - - debug('attempting reconnect'); - self.emitAll('reconnect_attempt', self.backoff.attempts); - self.emitAll('reconnecting', self.backoff.attempts); - - // check again for the case socket closed in above events - if (self.skipReconnect) return; - - self.open(function(err){ - if (err) { - debug('reconnect attempt error'); - self.reconnecting = false; - self.reconnect(); - self.emitAll('reconnect_error', err.data); - } else { - debug('reconnect success'); - self.onreconnect(); - } - }); - }, delay); - - this.subs.push({ - destroy: function(){ - clearTimeout(timer); - } - }); - } - }; - - /** - * Called upon successful reconnect. - * - * @api private - */ - - Manager.prototype.onreconnect = function(){ - var attempt = this.backoff.attempts; - this.reconnecting = false; - this.backoff.reset(); - this.updateSocketIds(); - this.emitAll('reconnect', attempt); - }; - -},{"./on":4,"./socket":5,"./url":6,"backo2":7,"component-bind":8,"component-emitter":9,"debug":10,"engine.io-client":11,"indexof":42,"object-component":43,"socket.io-parser":46}],4:[function(_dereq_,module,exports){ - - /** - * Module exports. - */ - - module.exports = on; - - /** - * Helper for subscriptions. - * - * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter` - * @param {String} event name - * @param {Function} callback - * @api public - */ - - function on(obj, ev, fn) { - obj.on(ev, fn); - return { - destroy: function(){ - obj.removeListener(ev, fn); - } - }; - } - -},{}],5:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var parser = _dereq_('socket.io-parser'); - var Emitter = _dereq_('component-emitter'); - var toArray = _dereq_('to-array'); - var on = _dereq_('./on'); - var bind = _dereq_('component-bind'); - var debug = _dereq_('debug')('socket.io-client:socket'); - var hasBin = _dereq_('has-binary'); - - /** - * Module exports. - */ - - module.exports = exports = Socket; - - /** - * Internal events (blacklisted). - * These events can't be emitted by the user. - * - * @api private - */ - - var events = { - connect: 1, - connect_error: 1, - connect_timeout: 1, - disconnect: 1, - error: 1, - reconnect: 1, - reconnect_attempt: 1, - reconnect_failed: 1, - reconnect_error: 1, - reconnecting: 1 - }; - - /** - * Shortcut to `Emitter#emit`. - */ - - var emit = Emitter.prototype.emit; - - /** - * `Socket` constructor. - * - * @api public - */ - - function Socket(io, nsp){ - this.io = io; - this.nsp = nsp; - this.json = this; // compat - this.ids = 0; - this.acks = {}; - if (this.io.autoConnect) this.open(); - this.receiveBuffer = []; - this.sendBuffer = []; - this.connected = false; - this.disconnected = true; - } - - /** - * Mix in `Emitter`. - */ - - Emitter(Socket.prototype); - - /** - * Subscribe to open, close and packet events - * - * @api private - */ - - Socket.prototype.subEvents = function() { - if (this.subs) return; - - var io = this.io; - this.subs = [ - on(io, 'open', bind(this, 'onopen')), - on(io, 'packet', bind(this, 'onpacket')), - on(io, 'close', bind(this, 'onclose')) - ]; - }; - - /** - * "Opens" the socket. - * - * @api public - */ - - Socket.prototype.open = - Socket.prototype.connect = function(){ - if (this.connected) return this; - - this.subEvents(); - this.io.open(); // ensure open - if ('open' == this.io.readyState) this.onopen(); - return this; - }; - - /** - * Sends a `message` event. - * - * @return {Socket} self - * @api public - */ - - Socket.prototype.send = function(){ - var args = toArray(arguments); - args.unshift('message'); - this.emit.apply(this, args); - return this; - }; - - /** - * Override `emit`. - * If the event is in `events`, it's emitted normally. - * - * @param {String} event name - * @return {Socket} self - * @api public - */ - - Socket.prototype.emit = function(ev){ - if (events.hasOwnProperty(ev)) { - emit.apply(this, arguments); - return this; - } - - var args = toArray(arguments); - var parserType = parser.EVENT; // default - if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary - var packet = { type: parserType, data: args }; - - // event ack callback - if ('function' == typeof args[args.length - 1]) { - debug('emitting packet with ack id %d', this.ids); - this.acks[this.ids] = args.pop(); - packet.id = this.ids++; - } - - if (this.connected) { - this.packet(packet); - } else { - this.sendBuffer.push(packet); - } - - return this; - }; - - /** - * Sends a packet. - * - * @param {Object} packet - * @api private - */ - - Socket.prototype.packet = function(packet){ - packet.nsp = this.nsp; - this.io.packet(packet); - }; - - /** - * Called upon engine `open`. - * - * @api private - */ - - Socket.prototype.onopen = function(){ - debug('transport is open - connecting'); - - // write connect packet if necessary - if ('/' != this.nsp) { - this.packet({ type: parser.CONNECT }); - } - }; - - /** - * Called upon engine `close`. - * - * @param {String} reason - * @api private - */ - - Socket.prototype.onclose = function(reason){ - debug('close (%s)', reason); - this.connected = false; - this.disconnected = true; - delete this.id; - this.emit('disconnect', reason); - }; - - /** - * Called with socket packet. - * - * @param {Object} packet - * @api private - */ - - Socket.prototype.onpacket = function(packet){ - if (packet.nsp != this.nsp) return; - - switch (packet.type) { - case parser.CONNECT: - this.onconnect(); - break; - - case parser.EVENT: - this.onevent(packet); - break; - - case parser.BINARY_EVENT: - this.onevent(packet); - break; - - case parser.ACK: - this.onack(packet); - break; - - case parser.BINARY_ACK: - this.onack(packet); - break; - - case parser.DISCONNECT: - this.ondisconnect(); - break; - - case parser.ERROR: - this.emit('error', packet.data); - break; - } - }; - - /** - * Called upon a server event. - * - * @param {Object} packet - * @api private - */ - - Socket.prototype.onevent = function(packet){ - var args = packet.data || []; - debug('emitting event %j', args); - - if (null != packet.id) { - debug('attaching ack callback to event'); - args.push(this.ack(packet.id)); - } - - if (this.connected) { - emit.apply(this, args); - } else { - this.receiveBuffer.push(args); - } - }; - - /** - * Produces an ack callback to emit with an event. - * - * @api private - */ - - Socket.prototype.ack = function(id){ - var self = this; - var sent = false; - return function(){ - // prevent double callbacks - if (sent) return; - sent = true; - var args = toArray(arguments); - debug('sending ack %j', args); - - var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK; - self.packet({ - type: type, - id: id, - data: args - }); - }; - }; - - /** - * Called upon a server acknowlegement. - * - * @param {Object} packet - * @api private - */ - - Socket.prototype.onack = function(packet){ - debug('calling ack %s with %j', packet.id, packet.data); - var fn = this.acks[packet.id]; - fn.apply(this, packet.data); - delete this.acks[packet.id]; - }; - - /** - * Called upon server connect. - * - * @api private - */ - - Socket.prototype.onconnect = function(){ - this.connected = true; - this.disconnected = false; - this.emit('connect'); - this.emitBuffered(); - }; - - /** - * Emit buffered events (received and emitted). - * - * @api private - */ - - Socket.prototype.emitBuffered = function(){ - var i; - for (i = 0; i < this.receiveBuffer.length; i++) { - emit.apply(this, this.receiveBuffer[i]); - } - this.receiveBuffer = []; - - for (i = 0; i < this.sendBuffer.length; i++) { - this.packet(this.sendBuffer[i]); - } - this.sendBuffer = []; - }; - - /** - * Called upon server disconnect. - * - * @api private - */ - - Socket.prototype.ondisconnect = function(){ - debug('server disconnect (%s)', this.nsp); - this.destroy(); - this.onclose('io server disconnect'); - }; - - /** - * Called upon forced client/server side disconnections, - * this method ensures the manager stops tracking us and - * that reconnections don't get triggered for this. - * - * @api private. - */ - - Socket.prototype.destroy = function(){ - if (this.subs) { - // clean subscriptions to avoid reconnections - for (var i = 0; i < this.subs.length; i++) { - this.subs[i].destroy(); - } - this.subs = null; - } - - this.io.destroy(this); - }; - - /** - * Disconnects the socket manually. - * - * @return {Socket} self - * @api public - */ - - Socket.prototype.close = - Socket.prototype.disconnect = function(){ - if (this.connected) { - debug('performing disconnect (%s)', this.nsp); - this.packet({ type: parser.DISCONNECT }); - } - - // remove socket from pool - this.destroy(); - - if (this.connected) { - // fire events - this.onclose('io client disconnect'); - } - return this; - }; - -},{"./on":4,"component-bind":8,"component-emitter":9,"debug":10,"has-binary":38,"socket.io-parser":46,"to-array":50}],6:[function(_dereq_,module,exports){ - (function (global){ - - /** - * Module dependencies. - */ - - var parseuri = _dereq_('parseuri'); - var debug = _dereq_('debug')('socket.io-client:url'); - - /** - * Module exports. - */ - - module.exports = url; - - /** - * URL parser. - * - * @param {String} url - * @param {Object} An object meant to mimic window.location. - * Defaults to window.location. - * @api public - */ - - function url(uri, loc){ - var obj = uri; - - // default to window.location - var loc = loc || global.location; - if (null == uri) uri = loc.protocol + '//' + loc.host; - - // relative path support - if ('string' == typeof uri) { - if ('/' == uri.charAt(0)) { - if ('/' == uri.charAt(1)) { - uri = loc.protocol + uri; - } else { - uri = loc.hostname + uri; - } - } - - if (!/^(https?|wss?):\/\//.test(uri)) { - debug('protocol-less url %s', uri); - if ('undefined' != typeof loc) { - uri = loc.protocol + '//' + uri; - } else { - uri = 'https://' + uri; - } - } - - // parse - debug('parse %s', uri); - obj = parseuri(uri); - } - - // make sure we treat `localhost:80` and `localhost` equally - if (!obj.port) { - if (/^(http|ws)$/.test(obj.protocol)) { - obj.port = '80'; - } - else if (/^(http|ws)s$/.test(obj.protocol)) { - obj.port = '443'; - } - } - - obj.path = obj.path || '/'; - - // define unique id - obj.id = obj.protocol + '://' + obj.host + ':' + obj.port; - // define href - obj.href = obj.protocol + '://' + obj.host + (loc && loc.port == obj.port ? '' : (':' + obj.port)); - - return obj; - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"debug":10,"parseuri":44}],7:[function(_dereq_,module,exports){ - - /** - * Expose `Backoff`. - */ - - module.exports = Backoff; - - /** - * Initialize backoff timer with `opts`. - * - * - `min` initial timeout in milliseconds [100] - * - `max` max timeout [10000] - * - `jitter` [0] - * - `factor` [2] - * - * @param {Object} opts - * @api public - */ - - function Backoff(opts) { - opts = opts || {}; - this.ms = opts.min || 100; - this.max = opts.max || 10000; - this.factor = opts.factor || 2; - this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0; - this.attempts = 0; - } - - /** - * Return the backoff duration. - * - * @return {Number} - * @api public - */ - - Backoff.prototype.duration = function(){ - var ms = this.ms * Math.pow(this.factor, this.attempts++); - if (this.jitter) { - var rand = Math.random(); - var deviation = Math.floor(rand * this.jitter * ms); - ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation; - } - return Math.min(ms, this.max) | 0; - }; - - /** - * Reset the number of attempts. - * - * @api public - */ - - Backoff.prototype.reset = function(){ - this.attempts = 0; - }; - - /** - * Set the minimum duration - * - * @api public - */ - - Backoff.prototype.setMin = function(min){ - this.ms = min; - }; - - /** - * Set the maximum duration - * - * @api public - */ - - Backoff.prototype.setMax = function(max){ - this.max = max; - }; - - /** - * Set the jitter - * - * @api public - */ - - Backoff.prototype.setJitter = function(jitter){ - this.jitter = jitter; - }; - - -},{}],8:[function(_dereq_,module,exports){ - /** - * Slice reference. - */ - - var slice = [].slice; - - /** - * Bind `obj` to `fn`. - * - * @param {Object} obj - * @param {Function|String} fn or string - * @return {Function} - * @api public - */ - - module.exports = function(obj, fn){ - if ('string' == typeof fn) fn = obj[fn]; - if ('function' != typeof fn) throw new Error('bind() requires a function'); - var args = slice.call(arguments, 2); - return function(){ - return fn.apply(obj, args.concat(slice.call(arguments))); - } - }; - -},{}],9:[function(_dereq_,module,exports){ - - /** - * Expose `Emitter`. - */ - - module.exports = Emitter; - - /** - * Initialize a new `Emitter`. - * - * @api public - */ - - function Emitter(obj) { - if (obj) return mixin(obj); - }; - - /** - * Mixin the emitter properties. - * - * @param {Object} obj - * @return {Object} - * @api private - */ - - function mixin(obj) { - for (var key in Emitter.prototype) { - obj[key] = Emitter.prototype[key]; - } - return obj; - } - - /** - * Listen on the given `event` with `fn`. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - - Emitter.prototype.on = - Emitter.prototype.addEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - (this._callbacks[event] = this._callbacks[event] || []) - .push(fn); - return this; - }; - - /** - * Adds an `event` listener that will be invoked a single - * time then automatically removed. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - - Emitter.prototype.once = function(event, fn){ - var self = this; - this._callbacks = this._callbacks || {}; - - function on() { - self.off(event, on); - fn.apply(this, arguments); - } - - on.fn = fn; - this.on(event, on); - return this; - }; - - /** - * Remove the given callback for `event` or all - * registered callbacks. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - - Emitter.prototype.off = - Emitter.prototype.removeListener = - Emitter.prototype.removeAllListeners = - Emitter.prototype.removeEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - - // all - if (0 == arguments.length) { - this._callbacks = {}; - return this; - } - - // specific event - var callbacks = this._callbacks[event]; - if (!callbacks) return this; - - // remove all handlers - if (1 == arguments.length) { - delete this._callbacks[event]; - return this; - } - - // remove specific handler - var cb; - for (var i = 0; i < callbacks.length; i++) { - cb = callbacks[i]; - if (cb === fn || cb.fn === fn) { - callbacks.splice(i, 1); - break; - } - } - return this; - }; - - /** - * Emit `event` with the given args. - * - * @param {String} event - * @param {Mixed} ... - * @return {Emitter} - */ - - Emitter.prototype.emit = function(event){ - this._callbacks = this._callbacks || {}; - var args = [].slice.call(arguments, 1) - , callbacks = this._callbacks[event]; - - if (callbacks) { - callbacks = callbacks.slice(0); - for (var i = 0, len = callbacks.length; i < len; ++i) { - callbacks[i].apply(this, args); - } - } - - return this; - }; - - /** - * Return array of callbacks for `event`. - * - * @param {String} event - * @return {Array} - * @api public - */ - - Emitter.prototype.listeners = function(event){ - this._callbacks = this._callbacks || {}; - return this._callbacks[event] || []; - }; - - /** - * Check if this emitter has `event` handlers. - * - * @param {String} event - * @return {Boolean} - * @api public - */ - - Emitter.prototype.hasListeners = function(event){ - return !! this.listeners(event).length; - }; - -},{}],10:[function(_dereq_,module,exports){ - - /** - * Expose `debug()` as the module. - */ - - module.exports = debug; - - /** - * Create a debugger with the given `name`. - * - * @param {String} name - * @return {Type} - * @api public - */ - - function debug(name) { - if (!debug.enabled(name)) return function(){}; - - return function(fmt){ - fmt = coerce(fmt); - - var curr = new Date; - var ms = curr - (debug[name] || curr); - debug[name] = curr; - - fmt = name - + ' ' - + fmt - + ' +' + debug.humanize(ms); - - // This hackery is required for IE8 - // where `console.log` doesn't have 'apply' - window.console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); - } - } - - /** - * The currently active debug mode names. - */ - - debug.names = []; - debug.skips = []; - - /** - * Enables a debug mode by name. This can include modes - * separated by a colon and wildcards. - * - * @param {String} name - * @api public - */ - - debug.enable = function(name) { - try { - localStorage.debug = name; - } catch(e){} - - var split = (name || '').split(/[\s,]+/) - , len = split.length; - - for (var i = 0; i < len; i++) { - name = split[i].replace('*', '.*?'); - if (name[0] === '-') { - debug.skips.push(new RegExp('^' + name.substr(1) + '$')); - } - else { - debug.names.push(new RegExp('^' + name + '$')); - } - } - }; - - /** - * Disable debug output. - * - * @api public - */ - - debug.disable = function(){ - debug.enable(''); - }; - - /** - * Humanize the given `ms`. - * - * @param {Number} m - * @return {String} - * @api private - */ - - debug.humanize = function(ms) { - var sec = 1000 - , min = 60 * 1000 - , hour = 60 * min; - - if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; - if (ms >= min) return (ms / min).toFixed(1) + 'm'; - if (ms >= sec) return (ms / sec | 0) + 's'; - return ms + 'ms'; - }; - - /** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - - debug.enabled = function(name) { - for (var i = 0, len = debug.skips.length; i < len; i++) { - if (debug.skips[i].test(name)) { - return false; - } - } - for (var i = 0, len = debug.names.length; i < len; i++) { - if (debug.names[i].test(name)) { - return true; - } - } - return false; - }; - - /** - * Coerce `val`. - */ - - function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; - } - -// persist - - try { - if (window.localStorage) debug.enable(localStorage.debug); - } catch(e){} - -},{}],11:[function(_dereq_,module,exports){ - - module.exports = _dereq_('./lib/'); - -},{"./lib/":12}],12:[function(_dereq_,module,exports){ - - module.exports = _dereq_('./socket'); - - /** - * Exports parser - * - * @api public - * - */ - module.exports.parser = _dereq_('engine.io-parser'); - -},{"./socket":13,"engine.io-parser":25}],13:[function(_dereq_,module,exports){ - (function (global){ - /** - * Module dependencies. - */ - - var transports = _dereq_('./transports'); - var Emitter = _dereq_('component-emitter'); - var debug = _dereq_('debug')('engine.io-client:socket'); - var index = _dereq_('indexof'); - var parser = _dereq_('engine.io-parser'); - var parseuri = _dereq_('parseuri'); - var parsejson = _dereq_('parsejson'); - var parseqs = _dereq_('parseqs'); - - /** - * Module exports. - */ - - module.exports = Socket; - - /** - * Noop function. - * - * @api private - */ - - function noop(){} - - /** - * Socket constructor. - * - * @param {String|Object} uri or options - * @param {Object} options - * @api public - */ - - function Socket(uri, opts){ - if (!(this instanceof Socket)) return new Socket(uri, opts); - - opts = opts || {}; - - if (uri && 'object' == typeof uri) { - opts = uri; - uri = null; - } - - if (uri) { - uri = parseuri(uri); - opts.host = uri.host; - opts.secure = uri.protocol == 'https' || uri.protocol == 'wss'; - opts.port = uri.port; - if (uri.query) opts.query = uri.query; - } - - this.secure = null != opts.secure ? opts.secure : - (global.location && 'https:' == location.protocol); - - if (opts.host) { - var pieces = opts.host.split(':'); - opts.hostname = pieces.shift(); - if (pieces.length) { - opts.port = pieces.pop(); - } else if (!opts.port) { - // if no port is specified manually, use the protocol default - opts.port = this.secure ? '443' : '80'; - } - } - - this.agent = opts.agent || false; - this.hostname = opts.hostname || - (global.location ? location.hostname : 'localhost'); - this.port = opts.port || (global.location && location.port ? - location.port : - (this.secure ? 443 : 80)); - this.query = opts.query || {}; - if ('string' == typeof this.query) this.query = parseqs.decode(this.query); - this.upgrade = false !== opts.upgrade; - this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/'; - this.forceJSONP = !!opts.forceJSONP; - this.jsonp = false !== opts.jsonp; - this.forceBase64 = !!opts.forceBase64; - this.enablesXDR = !!opts.enablesXDR; - this.timestampParam = opts.timestampParam || 't'; - this.timestampRequests = opts.timestampRequests; - this.transports = opts.transports || ['polling', 'websocket']; - this.readyState = ''; - this.writeBuffer = []; - this.callbackBuffer = []; - this.policyPort = opts.policyPort || 843; - this.rememberUpgrade = opts.rememberUpgrade || false; - this.binaryType = null; - this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades; - - // SSL options for Node.js client - this.pfx = opts.pfx || null; - this.key = opts.key || null; - this.passphrase = opts.passphrase || null; - this.cert = opts.cert || null; - this.ca = opts.ca || null; - this.ciphers = opts.ciphers || null; - this.rejectUnauthorized = opts.rejectUnauthorized || null; - - this.open(); - } - - Socket.priorWebsocketSuccess = false; - - /** - * Mix in `Emitter`. - */ - - Emitter(Socket.prototype); - - /** - * Protocol version. - * - * @api public - */ - - Socket.protocol = parser.protocol; // this is an int - - /** - * Expose deps for legacy compatibility - * and standalone browser access. - */ - - Socket.Socket = Socket; - Socket.Transport = _dereq_('./transport'); - Socket.transports = _dereq_('./transports'); - Socket.parser = _dereq_('engine.io-parser'); - - /** - * Creates transport of the given type. - * - * @param {String} transport name - * @return {Transport} - * @api private - */ - - Socket.prototype.createTransport = function (name) { - debug('creating transport "%s"', name); - var query = clone(this.query); - - // append engine.io protocol identifier - query.EIO = parser.protocol; - - // transport name - query.transport = name; - - // session id if we already have one - if (this.id) query.sid = this.id; - - var transport = new transports[name]({ - agent: this.agent, - hostname: this.hostname, - port: this.port, - secure: this.secure, - path: this.path, - query: query, - forceJSONP: this.forceJSONP, - jsonp: this.jsonp, - forceBase64: this.forceBase64, - enablesXDR: this.enablesXDR, - timestampRequests: this.timestampRequests, - timestampParam: this.timestampParam, - policyPort: this.policyPort, - socket: this, - pfx: this.pfx, - key: this.key, - passphrase: this.passphrase, - cert: this.cert, - ca: this.ca, - ciphers: this.ciphers, - rejectUnauthorized: this.rejectUnauthorized - }); - - return transport; - }; - - function clone (obj) { - var o = {}; - for (var i in obj) { - if (obj.hasOwnProperty(i)) { - o[i] = obj[i]; - } - } - return o; - } - - /** - * Initializes transport to use and starts probe. - * - * @api private - */ - Socket.prototype.open = function () { - var transport; - if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') != -1) { - transport = 'websocket'; - } else if (0 == this.transports.length) { - // Emit error on next tick so it can be listened to - var self = this; - setTimeout(function() { - self.emit('error', 'No transports available'); - }, 0); - return; - } else { - transport = this.transports[0]; - } - this.readyState = 'opening'; - - // Retry with the next transport if the transport is disabled (jsonp: false) - var transport; - try { - transport = this.createTransport(transport); - } catch (e) { - this.transports.shift(); - this.open(); - return; - } - - transport.open(); - this.setTransport(transport); - }; - - /** - * Sets the current transport. Disables the existing one (if any). - * - * @api private - */ - - Socket.prototype.setTransport = function(transport){ - debug('setting transport %s', transport.name); - var self = this; - - if (this.transport) { - debug('clearing existing transport %s', this.transport.name); - this.transport.removeAllListeners(); - } - - // set up transport - this.transport = transport; - - // set up transport listeners - transport - .on('drain', function(){ - self.onDrain(); - }) - .on('packet', function(packet){ - self.onPacket(packet); - }) - .on('error', function(e){ - self.onError(e); - }) - .on('close', function(){ - self.onClose('transport close'); - }); - }; - - /** - * Probes a transport. - * - * @param {String} transport name - * @api private - */ - - Socket.prototype.probe = function (name) { - debug('probing transport "%s"', name); - var transport = this.createTransport(name, { probe: 1 }) - , failed = false - , self = this; - - Socket.priorWebsocketSuccess = false; - - function onTransportOpen(){ - if (self.onlyBinaryUpgrades) { - var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary; - failed = failed || upgradeLosesBinary; - } - if (failed) return; - - debug('probe transport "%s" opened', name); - transport.send([{ type: 'ping', data: 'probe' }]); - transport.once('packet', function (msg) { - if (failed) return; - if ('pong' == msg.type && 'probe' == msg.data) { - debug('probe transport "%s" pong', name); - self.upgrading = true; - self.emit('upgrading', transport); - if (!transport) return; - Socket.priorWebsocketSuccess = 'websocket' == transport.name; - - debug('pausing current transport "%s"', self.transport.name); - self.transport.pause(function () { - if (failed) return; - if ('closed' == self.readyState) return; - debug('changing transport and sending upgrade packet'); - - cleanup(); - - self.setTransport(transport); - transport.send([{ type: 'upgrade' }]); - self.emit('upgrade', transport); - transport = null; - self.upgrading = false; - self.flush(); - }); - } else { - debug('probe transport "%s" failed', name); - var err = new Error('probe error'); - err.transport = transport.name; - self.emit('upgradeError', err); - } - }); - } - - function freezeTransport() { - if (failed) return; - - // Any callback called by transport should be ignored since now - failed = true; - - cleanup(); - - transport.close(); - transport = null; - } - - //Handle any error that happens while probing - function onerror(err) { - var error = new Error('probe error: ' + err); - error.transport = transport.name; - - freezeTransport(); - - debug('probe transport "%s" failed because of error: %s', name, err); - - self.emit('upgradeError', error); - } - - function onTransportClose(){ - onerror("transport closed"); - } - - //When the socket is closed while we're probing - function onclose(){ - onerror("socket closed"); - } - - //When the socket is upgraded while we're probing - function onupgrade(to){ - if (transport && to.name != transport.name) { - debug('"%s" works - aborting "%s"', to.name, transport.name); - freezeTransport(); - } - } - - //Remove all listeners on the transport and on self - function cleanup(){ - transport.removeListener('open', onTransportOpen); - transport.removeListener('error', onerror); - transport.removeListener('close', onTransportClose); - self.removeListener('close', onclose); - self.removeListener('upgrading', onupgrade); - } - - transport.once('open', onTransportOpen); - transport.once('error', onerror); - transport.once('close', onTransportClose); - - this.once('close', onclose); - this.once('upgrading', onupgrade); - - transport.open(); - - }; - - /** - * Called when connection is deemed open. - * - * @api public - */ - - Socket.prototype.onOpen = function () { - debug('socket open'); - this.readyState = 'open'; - Socket.priorWebsocketSuccess = 'websocket' == this.transport.name; - this.emit('open'); - this.flush(); - - // we check for `readyState` in case an `open` - // listener already closed the socket - if ('open' == this.readyState && this.upgrade && this.transport.pause) { - debug('starting upgrade probes'); - for (var i = 0, l = this.upgrades.length; i < l; i++) { - this.probe(this.upgrades[i]); - } - } - }; - - /** - * Handles a packet. - * - * @api private - */ - - Socket.prototype.onPacket = function (packet) { - if ('opening' == this.readyState || 'open' == this.readyState) { - debug('socket receive: type "%s", data "%s"', packet.type, packet.data); - - this.emit('packet', packet); - - // Socket is live - any packet counts - this.emit('heartbeat'); - - switch (packet.type) { - case 'open': - this.onHandshake(parsejson(packet.data)); - break; - - case 'pong': - this.setPing(); - break; - - case 'error': - var err = new Error('server error'); - err.code = packet.data; - this.emit('error', err); - break; - - case 'message': - this.emit('data', packet.data); - this.emit('message', packet.data); - break; - } - } else { - debug('packet received with socket readyState "%s"', this.readyState); - } - }; - - /** - * Called upon handshake completion. - * - * @param {Object} handshake obj - * @api private - */ - - Socket.prototype.onHandshake = function (data) { - this.emit('handshake', data); - this.id = data.sid; - this.transport.query.sid = data.sid; - this.upgrades = this.filterUpgrades(data.upgrades); - this.pingInterval = data.pingInterval; - this.pingTimeout = data.pingTimeout; - this.onOpen(); - // In case open handler closes socket - if ('closed' == this.readyState) return; - this.setPing(); - - // Prolong liveness of socket on heartbeat - this.removeListener('heartbeat', this.onHeartbeat); - this.on('heartbeat', this.onHeartbeat); - }; - - /** - * Resets ping timeout. - * - * @api private - */ - - Socket.prototype.onHeartbeat = function (timeout) { - clearTimeout(this.pingTimeoutTimer); - var self = this; - self.pingTimeoutTimer = setTimeout(function () { - if ('closed' == self.readyState) return; - self.onClose('ping timeout'); - }, timeout || (self.pingInterval + self.pingTimeout)); - }; - - /** - * Pings server every `this.pingInterval` and expects response - * within `this.pingTimeout` or closes connection. - * - * @api private - */ - - Socket.prototype.setPing = function () { - var self = this; - clearTimeout(self.pingIntervalTimer); - self.pingIntervalTimer = setTimeout(function () { - debug('writing ping packet - expecting pong within %sms', self.pingTimeout); - self.ping(); - self.onHeartbeat(self.pingTimeout); - }, self.pingInterval); - }; - - /** - * Sends a ping packet. - * - * @api public - */ - - Socket.prototype.ping = function () { - this.sendPacket('ping'); - }; - - /** - * Called on `drain` event - * - * @api private - */ - - Socket.prototype.onDrain = function() { - for (var i = 0; i < this.prevBufferLen; i++) { - if (this.callbackBuffer[i]) { - this.callbackBuffer[i](); - } - } - - this.writeBuffer.splice(0, this.prevBufferLen); - this.callbackBuffer.splice(0, this.prevBufferLen); - - // setting prevBufferLen = 0 is very important - // for example, when upgrading, upgrade packet is sent over, - // and a nonzero prevBufferLen could cause problems on `drain` - this.prevBufferLen = 0; - - if (this.writeBuffer.length == 0) { - this.emit('drain'); - } else { - this.flush(); - } - }; - - /** - * Flush write buffers. - * - * @api private - */ - - Socket.prototype.flush = function () { - if ('closed' != this.readyState && this.transport.writable && - !this.upgrading && this.writeBuffer.length) { - debug('flushing %d packets in socket', this.writeBuffer.length); - this.transport.send(this.writeBuffer); - // keep track of current length of writeBuffer - // splice writeBuffer and callbackBuffer on `drain` - this.prevBufferLen = this.writeBuffer.length; - this.emit('flush'); - } - }; - - /** - * Sends a message. - * - * @param {String} message. - * @param {Function} callback function. - * @return {Socket} for chaining. - * @api public - */ - - Socket.prototype.write = - Socket.prototype.send = function (msg, fn) { - this.sendPacket('message', msg, fn); - return this; - }; - - /** - * Sends a packet. - * - * @param {String} packet type. - * @param {String} data. - * @param {Function} callback function. - * @api private - */ - - Socket.prototype.sendPacket = function (type, data, fn) { - if ('closing' == this.readyState || 'closed' == this.readyState) { - return; - } - - var packet = { type: type, data: data }; - this.emit('packetCreate', packet); - this.writeBuffer.push(packet); - this.callbackBuffer.push(fn); - this.flush(); - }; - - /** - * Closes the connection. - * - * @api private - */ - - Socket.prototype.close = function () { - if ('opening' == this.readyState || 'open' == this.readyState) { - this.readyState = 'closing'; - - var self = this; - - function close() { - self.onClose('forced close'); - debug('socket closing - telling transport to close'); - self.transport.close(); - } - - function cleanupAndClose() { - self.removeListener('upgrade', cleanupAndClose); - self.removeListener('upgradeError', cleanupAndClose); - close(); - } - - function waitForUpgrade() { - // wait for upgrade to finish since we can't send packets while pausing a transport - self.once('upgrade', cleanupAndClose); - self.once('upgradeError', cleanupAndClose); - } - - if (this.writeBuffer.length) { - this.once('drain', function() { - if (this.upgrading) { - waitForUpgrade(); - } else { - close(); - } - }); - } else if (this.upgrading) { - waitForUpgrade(); - } else { - close(); - } - } - - return this; - }; - - /** - * Called upon transport error - * - * @api private - */ - - Socket.prototype.onError = function (err) { - debug('socket error %j', err); - Socket.priorWebsocketSuccess = false; - this.emit('error', err); - this.onClose('transport error', err); - }; - - /** - * Called upon transport close. - * - * @api private - */ - - Socket.prototype.onClose = function (reason, desc) { - if ('opening' == this.readyState || 'open' == this.readyState || 'closing' == this.readyState) { - debug('socket close with reason: "%s"', reason); - var self = this; - - // clear timers - clearTimeout(this.pingIntervalTimer); - clearTimeout(this.pingTimeoutTimer); - - // clean buffers in next tick, so developers can still - // grab the buffers on `close` event - setTimeout(function() { - self.writeBuffer = []; - self.callbackBuffer = []; - self.prevBufferLen = 0; - }, 0); - - // stop event from firing again for transport - this.transport.removeAllListeners('close'); - - // ensure transport won't stay open - this.transport.close(); - - // ignore further transport communication - this.transport.removeAllListeners(); - - // set ready state - this.readyState = 'closed'; - - // clear session id - this.id = null; - - // emit close event - this.emit('close', reason, desc); - } - }; - - /** - * Filters upgrades, returning only those matching client transports. - * - * @param {Array} server upgrades - * @api private - * - */ - - Socket.prototype.filterUpgrades = function (upgrades) { - var filteredUpgrades = []; - for (var i = 0, j = upgrades.length; i<j; i++) { - if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]); - } - return filteredUpgrades; - }; - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./transport":14,"./transports":15,"component-emitter":9,"debug":22,"engine.io-parser":25,"indexof":42,"parsejson":34,"parseqs":35,"parseuri":36}],14:[function(_dereq_,module,exports){ - /** - * Module dependencies. - */ - - var parser = _dereq_('engine.io-parser'); - var Emitter = _dereq_('component-emitter'); - - /** - * Module exports. - */ - - module.exports = Transport; - - /** - * Transport abstract constructor. - * - * @param {Object} options. - * @api private - */ - - function Transport (opts) { - this.path = opts.path; - this.hostname = opts.hostname; - this.port = opts.port; - this.secure = opts.secure; - this.query = opts.query; - this.timestampParam = opts.timestampParam; - this.timestampRequests = opts.timestampRequests; - this.readyState = ''; - this.agent = opts.agent || false; - this.socket = opts.socket; - this.enablesXDR = opts.enablesXDR; - - // SSL options for Node.js client - this.pfx = opts.pfx; - this.key = opts.key; - this.passphrase = opts.passphrase; - this.cert = opts.cert; - this.ca = opts.ca; - this.ciphers = opts.ciphers; - this.rejectUnauthorized = opts.rejectUnauthorized; - } - - /** - * Mix in `Emitter`. - */ - - Emitter(Transport.prototype); - - /** - * A counter used to prevent collisions in the timestamps used - * for cache busting. - */ - - Transport.timestamps = 0; - - /** - * Emits an error. - * - * @param {String} str - * @return {Transport} for chaining - * @api public - */ - - Transport.prototype.onError = function (msg, desc) { - var err = new Error(msg); - err.type = 'TransportError'; - err.description = desc; - this.emit('error', err); - return this; - }; - - /** - * Opens the transport. - * - * @api public - */ - - Transport.prototype.open = function () { - if ('closed' == this.readyState || '' == this.readyState) { - this.readyState = 'opening'; - this.doOpen(); - } - - return this; - }; - - /** - * Closes the transport. - * - * @api private - */ - - Transport.prototype.close = function () { - if ('opening' == this.readyState || 'open' == this.readyState) { - this.doClose(); - this.onClose(); - } - - return this; - }; - - /** - * Sends multiple packets. - * - * @param {Array} packets - * @api private - */ - - Transport.prototype.send = function(packets){ - if ('open' == this.readyState) { - this.write(packets); - } else { - throw new Error('Transport not open'); - } - }; - - /** - * Called upon open - * - * @api private - */ - - Transport.prototype.onOpen = function () { - this.readyState = 'open'; - this.writable = true; - this.emit('open'); - }; - - /** - * Called with data. - * - * @param {String} data - * @api private - */ - - Transport.prototype.onData = function(data){ - var packet = parser.decodePacket(data, this.socket.binaryType); - this.onPacket(packet); - }; - - /** - * Called with a decoded packet. - */ - - Transport.prototype.onPacket = function (packet) { - this.emit('packet', packet); - }; - - /** - * Called upon close. - * - * @api private - */ - - Transport.prototype.onClose = function () { - this.readyState = 'closed'; - this.emit('close'); - }; - -},{"component-emitter":9,"engine.io-parser":25}],15:[function(_dereq_,module,exports){ - (function (global){ - /** - * Module dependencies - */ - - var XMLHttpRequest = _dereq_('xmlhttprequest'); - var XHR = _dereq_('./polling-xhr'); - var JSONP = _dereq_('./polling-jsonp'); - var websocket = _dereq_('./websocket'); - - /** - * Export transports. - */ - - exports.polling = polling; - exports.websocket = websocket; - - /** - * Polling transport polymorphic constructor. - * Decides on xhr vs jsonp based on feature detection. - * - * @api private - */ - - function polling(opts){ - var xhr; - var xd = false; - var xs = false; - var jsonp = false !== opts.jsonp; - - if (global.location) { - var isSSL = 'https:' == location.protocol; - var port = location.port; - - // some user agents have empty `location.port` - if (!port) { - port = isSSL ? 443 : 80; - } - - xd = opts.hostname != location.hostname || port != opts.port; - xs = opts.secure != isSSL; - } - - opts.xdomain = xd; - opts.xscheme = xs; - xhr = new XMLHttpRequest(opts); - - if ('open' in xhr && !opts.forceJSONP) { - return new XHR(opts); - } else { - if (!jsonp) throw new Error('JSONP disabled'); - return new JSONP(opts); - } - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./polling-jsonp":16,"./polling-xhr":17,"./websocket":19,"xmlhttprequest":20}],16:[function(_dereq_,module,exports){ - (function (global){ - - /** - * Module requirements. - */ - - var Polling = _dereq_('./polling'); - var inherit = _dereq_('component-inherit'); - - /** - * Module exports. - */ - - module.exports = JSONPPolling; - - /** - * Cached regular expressions. - */ - - var rNewline = /\n/g; - var rEscapedNewline = /\\n/g; - - /** - * Global JSONP callbacks. - */ - - var callbacks; - - /** - * Callbacks count. - */ - - var index = 0; - - /** - * Noop. - */ - - function empty () { } - - /** - * JSONP Polling constructor. - * - * @param {Object} opts. - * @api public - */ - - function JSONPPolling (opts) { - Polling.call(this, opts); - - this.query = this.query || {}; - - // define global callbacks array if not present - // we do this here (lazily) to avoid unneeded global pollution - if (!callbacks) { - // we need to consider multiple engines in the same page - if (!global.___eio) global.___eio = []; - callbacks = global.___eio; - } - - // callback identifier - this.index = callbacks.length; - - // add callback to jsonp global - var self = this; - callbacks.push(function (msg) { - self.onData(msg); - }); - - // append to query string - this.query.j = this.index; - - // prevent spurious errors from being emitted when the window is unloaded - if (global.document && global.addEventListener) { - global.addEventListener('beforeunload', function () { - if (self.script) self.script.onerror = empty; - }, false); - } - } - - /** - * Inherits from Polling. - */ - - inherit(JSONPPolling, Polling); - - /* - * JSONP only supports binary as base64 encoded strings - */ - - JSONPPolling.prototype.supportsBinary = false; - - /** - * Closes the socket. - * - * @api private - */ - - JSONPPolling.prototype.doClose = function () { - if (this.script) { - this.script.parentNode.removeChild(this.script); - this.script = null; - } - - if (this.form) { - this.form.parentNode.removeChild(this.form); - this.form = null; - this.iframe = null; - } - - Polling.prototype.doClose.call(this); - }; - - /** - * Starts a poll cycle. - * - * @api private - */ - - JSONPPolling.prototype.doPoll = function () { - var self = this; - var script = document.createElement('script'); - - if (this.script) { - this.script.parentNode.removeChild(this.script); - this.script = null; - } - - script.async = true; - script.src = this.uri(); - script.onerror = function(e){ - self.onError('jsonp poll error',e); - }; - - var insertAt = document.getElementsByTagName('script')[0]; - insertAt.parentNode.insertBefore(script, insertAt); - this.script = script; - - var isUAgecko = 'undefined' != typeof navigator && /gecko/i.test(navigator.userAgent); - - if (isUAgecko) { - setTimeout(function () { - var iframe = document.createElement('iframe'); - document.body.appendChild(iframe); - document.body.removeChild(iframe); - }, 100); - } - }; - - /** - * Writes with a hidden iframe. - * - * @param {String} data to send - * @param {Function} called upon flush. - * @api private - */ - - JSONPPolling.prototype.doWrite = function (data, fn) { - var self = this; - - if (!this.form) { - var form = document.createElement('form'); - var area = document.createElement('textarea'); - var id = this.iframeId = 'eio_iframe_' + this.index; - var iframe; - - form.className = 'socketio'; - form.style.position = 'absolute'; - form.style.top = '-1000px'; - form.style.left = '-1000px'; - form.target = id; - form.method = 'POST'; - form.setAttribute('accept-charset', 'utf-8'); - area.name = 'd'; - form.appendChild(area); - document.body.appendChild(form); - - this.form = form; - this.area = area; - } - - this.form.action = this.uri(); - - function complete () { - initIframe(); - fn(); - } - - function initIframe () { - if (self.iframe) { - try { - self.form.removeChild(self.iframe); - } catch (e) { - self.onError('jsonp polling iframe removal error', e); - } - } - - try { - // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) - var html = '<iframe src="javascript:0" name="'+ self.iframeId +'">'; - iframe = document.createElement(html); - } catch (e) { - iframe = document.createElement('iframe'); - iframe.name = self.iframeId; - iframe.src = 'javascript:0'; - } - - iframe.id = self.iframeId; - - self.form.appendChild(iframe); - self.iframe = iframe; - } - - initIframe(); - - // escape \n to prevent it from being converted into \r\n by some UAs - // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side - data = data.replace(rEscapedNewline, '\\\n'); - this.area.value = data.replace(rNewline, '\\n'); - - try { - this.form.submit(); - } catch(e) {} - - if (this.iframe.attachEvent) { - this.iframe.onreadystatechange = function(){ - if (self.iframe.readyState == 'complete') { - complete(); - } - }; - } else { - this.iframe.onload = complete; - } - }; - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./polling":18,"component-inherit":21}],17:[function(_dereq_,module,exports){ - (function (global){ - /** - * Module requirements. - */ - - var XMLHttpRequest = _dereq_('xmlhttprequest'); - var Polling = _dereq_('./polling'); - var Emitter = _dereq_('component-emitter'); - var inherit = _dereq_('component-inherit'); - var debug = _dereq_('debug')('engine.io-client:polling-xhr'); - - /** - * Module exports. - */ - - module.exports = XHR; - module.exports.Request = Request; - - /** - * Empty function - */ - - function empty(){} - - /** - * XHR Polling constructor. - * - * @param {Object} opts - * @api public - */ - - function XHR(opts){ - Polling.call(this, opts); - - if (global.location) { - var isSSL = 'https:' == location.protocol; - var port = location.port; - - // some user agents have empty `location.port` - if (!port) { - port = isSSL ? 443 : 80; - } - - this.xd = opts.hostname != global.location.hostname || - port != opts.port; - this.xs = opts.secure != isSSL; - } - } - - /** - * Inherits from Polling. - */ - - inherit(XHR, Polling); - - /** - * XHR supports binary - */ - - XHR.prototype.supportsBinary = true; - - /** - * Creates a request. - * - * @param {String} method - * @api private - */ - - XHR.prototype.request = function(opts){ - opts = opts || {}; - opts.uri = this.uri(); - opts.xd = this.xd; - opts.xs = this.xs; - opts.agent = this.agent || false; - opts.supportsBinary = this.supportsBinary; - opts.enablesXDR = this.enablesXDR; - - // SSL options for Node.js client - opts.pfx = this.pfx; - opts.key = this.key; - opts.passphrase = this.passphrase; - opts.cert = this.cert; - opts.ca = this.ca; - opts.ciphers = this.ciphers; - opts.rejectUnauthorized = this.rejectUnauthorized; - - return new Request(opts); - }; - - /** - * Sends data. - * - * @param {String} data to send. - * @param {Function} called upon flush. - * @api private - */ - - XHR.prototype.doWrite = function(data, fn){ - var isBinary = typeof data !== 'string' && data !== undefined; - var req = this.request({ method: 'POST', data: data, isBinary: isBinary }); - var self = this; - req.on('success', fn); - req.on('error', function(err){ - self.onError('xhr post error', err); - }); - this.sendXhr = req; - }; - - /** - * Starts a poll cycle. - * - * @api private - */ - - XHR.prototype.doPoll = function(){ - debug('xhr poll'); - var req = this.request(); - var self = this; - req.on('data', function(data){ - self.onData(data); - }); - req.on('error', function(err){ - self.onError('xhr poll error', err); - }); - this.pollXhr = req; - }; - - /** - * Request constructor - * - * @param {Object} options - * @api public - */ - - function Request(opts){ - this.method = opts.method || 'GET'; - this.uri = opts.uri; - this.xd = !!opts.xd; - this.xs = !!opts.xs; - this.async = false !== opts.async; - this.data = undefined != opts.data ? opts.data : null; - this.agent = opts.agent; - this.isBinary = opts.isBinary; - this.supportsBinary = opts.supportsBinary; - this.enablesXDR = opts.enablesXDR; - - // SSL options for Node.js client - this.pfx = opts.pfx; - this.key = opts.key; - this.passphrase = opts.passphrase; - this.cert = opts.cert; - this.ca = opts.ca; - this.ciphers = opts.ciphers; - this.rejectUnauthorized = opts.rejectUnauthorized; - - this.create(); - } - - /** - * Mix in `Emitter`. - */ - - Emitter(Request.prototype); - - /** - * Creates the XHR object and sends the request. - * - * @api private - */ - - Request.prototype.create = function(){ - var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR }; - - // SSL options for Node.js client - opts.pfx = this.pfx; - opts.key = this.key; - opts.passphrase = this.passphrase; - opts.cert = this.cert; - opts.ca = this.ca; - opts.ciphers = this.ciphers; - opts.rejectUnauthorized = this.rejectUnauthorized; - - var xhr = this.xhr = new XMLHttpRequest(opts); - var self = this; - - try { - debug('xhr open %s: %s', this.method, this.uri); - xhr.open(this.method, this.uri, this.async); - if (this.supportsBinary) { - // This has to be done after open because Firefox is stupid - // http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension - xhr.responseType = 'arraybuffer'; - } - - if ('POST' == this.method) { - try { - if (this.isBinary) { - xhr.setRequestHeader('Content-type', 'application/octet-stream'); - } else { - xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8'); - } - } catch (e) {} - } - - // ie6 check - if ('withCredentials' in xhr) { - xhr.withCredentials = true; - } - - if (this.hasXDR()) { - xhr.onload = function(){ - self.onLoad(); - }; - xhr.onerror = function(){ - self.onError(xhr.responseText); - }; - } else { - xhr.onreadystatechange = function(){ - if (4 != xhr.readyState) return; - if (200 == xhr.status || 1223 == xhr.status) { - self.onLoad(); - } else { - // make sure the `error` event handler that's user-set - // does not throw in the same tick and gets caught here - setTimeout(function(){ - self.onError(xhr.status); - }, 0); - } - }; - } - - debug('xhr data %s', this.data); - xhr.send(this.data); - } catch (e) { - // Need to defer since .create() is called directly fhrom the constructor - // and thus the 'error' event can only be only bound *after* this exception - // occurs. Therefore, also, we cannot throw here at all. - setTimeout(function() { - self.onError(e); - }, 0); - return; - } - - if (global.document) { - this.index = Request.requestsCount++; - Request.requests[this.index] = this; - } - }; - - /** - * Called upon successful response. - * - * @api private - */ - - Request.prototype.onSuccess = function(){ - this.emit('success'); - this.cleanup(); - }; - - /** - * Called if we have data. - * - * @api private - */ - - Request.prototype.onData = function(data){ - this.emit('data', data); - this.onSuccess(); - }; - - /** - * Called upon error. - * - * @api private - */ - - Request.prototype.onError = function(err){ - this.emit('error', err); - this.cleanup(true); - }; - - /** - * Cleans up house. - * - * @api private - */ - - Request.prototype.cleanup = function(fromError){ - if ('undefined' == typeof this.xhr || null === this.xhr) { - return; - } - // xmlhttprequest - if (this.hasXDR()) { - this.xhr.onload = this.xhr.onerror = empty; - } else { - this.xhr.onreadystatechange = empty; - } - - if (fromError) { - try { - this.xhr.abort(); - } catch(e) {} - } - - if (global.document) { - delete Request.requests[this.index]; - } - - this.xhr = null; - }; - - /** - * Called upon load. - * - * @api private - */ - - Request.prototype.onLoad = function(){ - var data; - try { - var contentType; - try { - contentType = this.xhr.getResponseHeader('Content-Type').split(';')[0]; - } catch (e) {} - if (contentType === 'application/octet-stream') { - data = this.xhr.response; - } else { - if (!this.supportsBinary) { - data = this.xhr.responseText; - } else { - data = 'ok'; - } - } - } catch (e) { - this.onError(e); - } - if (null != data) { - this.onData(data); - } - }; - - /** - * Check if it has XDomainRequest. - * - * @api private - */ - - Request.prototype.hasXDR = function(){ - return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR; - }; - - /** - * Aborts the request. - * - * @api public - */ - - Request.prototype.abort = function(){ - this.cleanup(); - }; - - /** - * Aborts pending requests when unloading the window. This is needed to prevent - * memory leaks (e.g. when using IE) and to ensure that no spurious error is - * emitted. - */ - - if (global.document) { - Request.requestsCount = 0; - Request.requests = {}; - if (global.attachEvent) { - global.attachEvent('onunload', unloadHandler); - } else if (global.addEventListener) { - global.addEventListener('beforeunload', unloadHandler, false); - } - } - - function unloadHandler() { - for (var i in Request.requests) { - if (Request.requests.hasOwnProperty(i)) { - Request.requests[i].abort(); - } - } - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./polling":18,"component-emitter":9,"component-inherit":21,"debug":22,"xmlhttprequest":20}],18:[function(_dereq_,module,exports){ - /** - * Module dependencies. - */ - - var Transport = _dereq_('../transport'); - var parseqs = _dereq_('parseqs'); - var parser = _dereq_('engine.io-parser'); - var inherit = _dereq_('component-inherit'); - var debug = _dereq_('debug')('engine.io-client:polling'); - - /** - * Module exports. - */ - - module.exports = Polling; - - /** - * Is XHR2 supported? - */ - - var hasXHR2 = (function() { - var XMLHttpRequest = _dereq_('xmlhttprequest'); - var xhr = new XMLHttpRequest({ xdomain: false }); - return null != xhr.responseType; - })(); - - /** - * Polling interface. - * - * @param {Object} opts - * @api private - */ - - function Polling(opts){ - var forceBase64 = (opts && opts.forceBase64); - if (!hasXHR2 || forceBase64) { - this.supportsBinary = false; - } - Transport.call(this, opts); - } - - /** - * Inherits from Transport. - */ - - inherit(Polling, Transport); - - /** - * Transport name. - */ - - Polling.prototype.name = 'polling'; - - /** - * Opens the socket (triggers polling). We write a PING message to determine - * when the transport is open. - * - * @api private - */ - - Polling.prototype.doOpen = function(){ - this.poll(); - }; - - /** - * Pauses polling. - * - * @param {Function} callback upon buffers are flushed and transport is paused - * @api private - */ - - Polling.prototype.pause = function(onPause){ - var pending = 0; - var self = this; - - this.readyState = 'pausing'; - - function pause(){ - debug('paused'); - self.readyState = 'paused'; - onPause(); - } - - if (this.polling || !this.writable) { - var total = 0; - - if (this.polling) { - debug('we are currently polling - waiting to pause'); - total++; - this.once('pollComplete', function(){ - debug('pre-pause polling complete'); - --total || pause(); - }); - } - - if (!this.writable) { - debug('we are currently writing - waiting to pause'); - total++; - this.once('drain', function(){ - debug('pre-pause writing complete'); - --total || pause(); - }); - } - } else { - pause(); - } - }; - - /** - * Starts polling cycle. - * - * @api public - */ - - Polling.prototype.poll = function(){ - debug('polling'); - this.polling = true; - this.doPoll(); - this.emit('poll'); - }; - - /** - * Overloads onData to detect payloads. - * - * @api private - */ - - Polling.prototype.onData = function(data){ - var self = this; - debug('polling got data %s', data); - var callback = function(packet, index, total) { - // if its the first message we consider the transport open - if ('opening' == self.readyState) { - self.onOpen(); - } - - // if its a close packet, we close the ongoing requests - if ('close' == packet.type) { - self.onClose(); - return false; - } - - // otherwise bypass onData and handle the message - self.onPacket(packet); - }; - - // decode payload - parser.decodePayload(data, this.socket.binaryType, callback); - - // if an event did not trigger closing - if ('closed' != this.readyState) { - // if we got data we're not polling - this.polling = false; - this.emit('pollComplete'); - - if ('open' == this.readyState) { - this.poll(); - } else { - debug('ignoring poll - transport state "%s"', this.readyState); - } - } - }; - - /** - * For polling, send a close packet. - * - * @api private - */ - - Polling.prototype.doClose = function(){ - var self = this; - - function close(){ - debug('writing close packet'); - self.write([{ type: 'close' }]); - } - - if ('open' == this.readyState) { - debug('transport open - closing'); - close(); - } else { - // in case we're trying to close while - // handshaking is in progress (GH-164) - debug('transport not open - deferring close'); - this.once('open', close); - } - }; - - /** - * Writes a packets payload. - * - * @param {Array} data packets - * @param {Function} drain callback - * @api private - */ - - Polling.prototype.write = function(packets){ - var self = this; - this.writable = false; - var callbackfn = function() { - self.writable = true; - self.emit('drain'); - }; - - var self = this; - parser.encodePayload(packets, this.supportsBinary, function(data) { - self.doWrite(data, callbackfn); - }); - }; - - /** - * Generates uri for connection. - * - * @api private - */ - - Polling.prototype.uri = function(){ - var query = this.query || {}; - var schema = this.secure ? 'https' : 'http'; - var port = ''; - - // cache busting is forced - if (false !== this.timestampRequests) { - query[this.timestampParam] = +new Date + '-' + Transport.timestamps++; - } - - if (!this.supportsBinary && !query.sid) { - query.b64 = 1; - } - - query = parseqs.encode(query); - - // avoid port if default for schema - if (this.port && (('https' == schema && this.port != 443) || - ('http' == schema && this.port != 80))) { - port = ':' + this.port; - } - - // prepend ? to query - if (query.length) { - query = '?' + query; - } - - return schema + '://' + this.hostname + port + this.path + query; - }; - -},{"../transport":14,"component-inherit":21,"debug":22,"engine.io-parser":25,"parseqs":35,"xmlhttprequest":20}],19:[function(_dereq_,module,exports){ - /** - * Module dependencies. - */ - - var Transport = _dereq_('../transport'); - var parser = _dereq_('engine.io-parser'); - var parseqs = _dereq_('parseqs'); - var inherit = _dereq_('component-inherit'); - var debug = _dereq_('debug')('engine.io-client:websocket'); - - /** - * `ws` exposes a WebSocket-compatible interface in - * Node, or the `WebSocket` or `MozWebSocket` globals - * in the browser. - */ - - var WebSocket = _dereq_('ws'); - - /** - * Module exports. - */ - - module.exports = WS; - - /** - * WebSocket transport constructor. - * - * @api {Object} connection options - * @api public - */ - - function WS(opts){ - var forceBase64 = (opts && opts.forceBase64); - if (forceBase64) { - this.supportsBinary = false; - } - Transport.call(this, opts); - } - - /** - * Inherits from Transport. - */ - - inherit(WS, Transport); - - /** - * Transport name. - * - * @api public - */ - - WS.prototype.name = 'websocket'; - - /* - * WebSockets support binary - */ - - WS.prototype.supportsBinary = true; - - /** - * Opens socket. - * - * @api private - */ - - WS.prototype.doOpen = function(){ - if (!this.check()) { - // let probe timeout - return; - } - - var self = this; - var uri = this.uri(); - var protocols = void(0); - var opts = { agent: this.agent }; - - // SSL options for Node.js client - opts.pfx = this.pfx; - opts.key = this.key; - opts.passphrase = this.passphrase; - opts.cert = this.cert; - opts.ca = this.ca; - opts.ciphers = this.ciphers; - opts.rejectUnauthorized = this.rejectUnauthorized; - - this.ws = new WebSocket(uri, protocols, opts); - - if (this.ws.binaryType === undefined) { - this.supportsBinary = false; - } - - this.ws.binaryType = 'arraybuffer'; - this.addEventListeners(); - }; - - /** - * Adds event listeners to the socket - * - * @api private - */ - - WS.prototype.addEventListeners = function(){ - var self = this; - - this.ws.onopen = function(){ - self.onOpen(); - }; - this.ws.onclose = function(){ - self.onClose(); - }; - this.ws.onmessage = function(ev){ - self.onData(ev.data); - }; - this.ws.onerror = function(e){ - self.onError('websocket error', e); - }; - }; - - /** - * Override `onData` to use a timer on iOS. - * See: https://gist.github.com/mloughran/2052006 - * - * @api private - */ - - if ('undefined' != typeof navigator - && /iPad|iPhone|iPod/i.test(navigator.userAgent)) { - WS.prototype.onData = function(data){ - var self = this; - setTimeout(function(){ - Transport.prototype.onData.call(self, data); - }, 0); - }; - } - - /** - * Writes data to socket. - * - * @param {Array} array of packets. - * @api private - */ - - WS.prototype.write = function(packets){ - var self = this; - this.writable = false; - // encodePacket efficient as it uses WS framing - // no need for encodePayload - for (var i = 0, l = packets.length; i < l; i++) { - parser.encodePacket(packets[i], this.supportsBinary, function(data) { - //Sometimes the websocket has already been closed but the browser didn't - //have a chance of informing us about it yet, in that case send will - //throw an error - try { - self.ws.send(data); - } catch (e){ - debug('websocket closed before onclose event'); - } - }); - } - - function ondrain() { - self.writable = true; - self.emit('drain'); - } - // fake drain - // defer to next tick to allow Socket to clear writeBuffer - setTimeout(ondrain, 0); - }; - - /** - * Called upon close - * - * @api private - */ - - WS.prototype.onClose = function(){ - Transport.prototype.onClose.call(this); - }; - - /** - * Closes socket. - * - * @api private - */ - - WS.prototype.doClose = function(){ - if (typeof this.ws !== 'undefined') { - this.ws.close(); - } - }; - - /** - * Generates uri for connection. - * - * @api private - */ - - WS.prototype.uri = function(){ - var query = this.query || {}; - var schema = this.secure ? 'wss' : 'ws'; - var port = ''; - - // avoid port if default for schema - if (this.port && (('wss' == schema && this.port != 443) - || ('ws' == schema && this.port != 80))) { - port = ':' + this.port; - } - - // append timestamp to URI - if (this.timestampRequests) { - query[this.timestampParam] = +new Date; - } - - // communicate binary support capabilities - if (!this.supportsBinary) { - query.b64 = 1; - } - - query = parseqs.encode(query); - - // prepend ? to query - if (query.length) { - query = '?' + query; - } - - return schema + '://' + this.hostname + port + this.path + query; - }; - - /** - * Feature detection for WebSocket. - * - * @return {Boolean} whether this transport is available. - * @api public - */ - - WS.prototype.check = function(){ - return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name); - }; - -},{"../transport":14,"component-inherit":21,"debug":22,"engine.io-parser":25,"parseqs":35,"ws":37}],20:[function(_dereq_,module,exports){ -// browser shim for xmlhttprequest module - var hasCORS = _dereq_('has-cors'); - - module.exports = function(opts) { - var xdomain = opts.xdomain; - - // scheme must be same when usign XDomainRequest - // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx - var xscheme = opts.xscheme; - - // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default. - // https://github.com/Automattic/engine.io-client/pull/217 - var enablesXDR = opts.enablesXDR; - - // XMLHttpRequest can be disabled on IE - try { - if ('undefined' != typeof XMLHttpRequest && (!xdomain || hasCORS)) { - return new XMLHttpRequest(); - } - } catch (e) { } - - // Use XDomainRequest for IE8 if enablesXDR is true - // because loading bar keeps flashing when using jsonp-polling - // https://github.com/yujiosaka/socke.io-ie8-loading-example - try { - if ('undefined' != typeof XDomainRequest && !xscheme && enablesXDR) { - return new XDomainRequest(); - } - } catch (e) { } - - if (!xdomain) { - try { - return new ActiveXObject('Microsoft.XMLHTTP'); - } catch(e) { } - } - } - -},{"has-cors":40}],21:[function(_dereq_,module,exports){ - - module.exports = function(a, b){ - var fn = function(){}; - fn.prototype = b.prototype; - a.prototype = new fn; - a.prototype.constructor = a; - }; -},{}],22:[function(_dereq_,module,exports){ - - /** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - - exports = module.exports = _dereq_('./debug'); - exports.log = log; - exports.formatArgs = formatArgs; - exports.save = save; - exports.load = load; - exports.useColors = useColors; - - /** - * Colors. - */ - - exports.colors = [ - 'lightseagreen', - 'forestgreen', - 'goldenrod', - 'dodgerblue', - 'darkorchid', - 'crimson' - ]; - - /** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ - - function useColors() { - // is webkit? http://stackoverflow.com/a/16459606/376773 - return ('WebkitAppearance' in document.documentElement.style) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (window.console && (console.firebug || (console.exception && console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); - } - - /** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - - exports.formatters.j = function(v) { - return JSON.stringify(v); - }; - - - /** - * Colorize log arguments if enabled. - * - * @api public - */ - - function formatArgs() { - var args = arguments; - var useColors = this.useColors; - - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - - if (!useColors) return args; - - var c = 'color: ' + this.color; - args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); - - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-z%]/g, function(match) { - if ('%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - - args.splice(lastC, 0, c); - return args; - } - - /** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ - - function log() { - // This hackery is required for IE8, - // where the `console.log` function doesn't have 'apply' - return 'object' == typeof console - && 'function' == typeof console.log - && Function.prototype.apply.call(console.log, console, arguments); - } - - /** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ - - function save(namespaces) { - try { - if (null == namespaces) { - localStorage.removeItem('debug'); - } else { - localStorage.debug = namespaces; - } - } catch(e) {} - } - - /** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ - - function load() { - var r; - try { - r = localStorage.debug; - } catch(e) {} - return r; - } - - /** - * Enable namespaces listed in `localStorage.debug` initially. - */ - - exports.enable(load()); - -},{"./debug":23}],23:[function(_dereq_,module,exports){ - - /** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ - - exports = module.exports = debug; - exports.coerce = coerce; - exports.disable = disable; - exports.enable = enable; - exports.enabled = enabled; - exports.humanize = _dereq_('ms'); - - /** - * The currently active debug mode names, and names to skip. - */ - - exports.names = []; - exports.skips = []; - - /** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lowercased letter, i.e. "n". - */ - - exports.formatters = {}; - - /** - * Previously assigned color. - */ - - var prevColor = 0; - - /** - * Previous log timestamp. - */ - - var prevTime; - - /** - * Select a color. - * - * @return {Number} - * @api private - */ - - function selectColor() { - return exports.colors[prevColor++ % exports.colors.length]; - } - - /** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - - function debug(namespace) { - - // define the `disabled` version - function disabled() { - } - disabled.enabled = false; - - // define the `enabled` version - function enabled() { - - var self = enabled; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - // add the `color` if not set - if (null == self.useColors) self.useColors = exports.useColors(); - if (null == self.color && self.useColors) self.color = selectColor(); - - var args = Array.prototype.slice.call(arguments); - - args[0] = exports.coerce(args[0]); - - if ('string' !== typeof args[0]) { - // anything else let's inspect with %o - args = ['%o'].concat(args); - } - - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); - - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); - - if ('function' === typeof exports.formatArgs) { - args = exports.formatArgs.apply(self, args); - } - var logFn = enabled.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - enabled.enabled = true; - - var fn = exports.enabled(namespace) ? enabled : disabled; - - fn.namespace = namespace; - - return fn; - } - - /** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - - function enable(namespaces) { - exports.save(namespaces); - - var split = (namespaces || '').split(/[\s,]+/); - var len = split.length; - - for (var i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } - } - - /** - * Disable debug output. - * - * @api public - */ - - function disable() { - exports.enable(''); - } - - /** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - - function enabled(name) { - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; - } - } - return false; - } - - /** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - - function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; - } - -},{"ms":24}],24:[function(_dereq_,module,exports){ - /** - * Helpers. - */ - - var s = 1000; - var m = s * 60; - var h = m * 60; - var d = h * 24; - var y = d * 365.25; - - /** - * Parse or format the given `val`. - * - * Options: - * - * - `long` verbose formatting [false] - * - * @param {String|Number} val - * @param {Object} options - * @return {String|Number} - * @api public - */ - - module.exports = function(val, options){ - options = options || {}; - if ('string' == typeof val) return parse(val); - return options.long - ? long(val) - : short(val); - }; - - /** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ - - function parse(str) { - var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); - if (!match) return; - var n = parseFloat(match[1]); - var type = (match[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'y': - return n * y; - case 'days': - case 'day': - case 'd': - return n * d; - case 'hours': - case 'hour': - case 'h': - return n * h; - case 'minutes': - case 'minute': - case 'm': - return n * m; - case 'seconds': - case 'second': - case 's': - return n * s; - case 'ms': - return n; - } - } - - /** - * Short format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - - function short(ms) { - if (ms >= d) return Math.round(ms / d) + 'd'; - if (ms >= h) return Math.round(ms / h) + 'h'; - if (ms >= m) return Math.round(ms / m) + 'm'; - if (ms >= s) return Math.round(ms / s) + 's'; - return ms + 'ms'; - } - - /** - * Long format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - - function long(ms) { - return plural(ms, d, 'day') - || plural(ms, h, 'hour') - || plural(ms, m, 'minute') - || plural(ms, s, 'second') - || ms + ' ms'; - } - - /** - * Pluralization helper. - */ - - function plural(ms, n, name) { - if (ms < n) return; - if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; - return Math.ceil(ms / n) + ' ' + name + 's'; - } - -},{}],25:[function(_dereq_,module,exports){ - (function (global){ - /** - * Module dependencies. - */ - - var keys = _dereq_('./keys'); - var hasBinary = _dereq_('has-binary'); - var sliceBuffer = _dereq_('arraybuffer.slice'); - var base64encoder = _dereq_('base64-arraybuffer'); - var after = _dereq_('after'); - var utf8 = _dereq_('utf8'); - - /** - * Check if we are running an android browser. That requires us to use - * ArrayBuffer with polling transports... - * - * http://ghinda.net/jpeg-blob-ajax-android/ - */ - - var isAndroid = navigator.userAgent.match(/Android/i); - - /** - * Check if we are running in PhantomJS. - * Uploading a Blob with PhantomJS does not work correctly, as reported here: - * https://github.com/ariya/phantomjs/issues/11395 - * @type boolean - */ - var isPhantomJS = /PhantomJS/i.test(navigator.userAgent); - - /** - * When true, avoids using Blobs to encode payloads. - * @type boolean - */ - var dontSendBlobs = isAndroid || isPhantomJS; - - /** - * Current protocol version. - */ - - exports.protocol = 3; - - /** - * Packet types. - */ - - var packets = exports.packets = { - open: 0 // non-ws - , close: 1 // non-ws - , ping: 2 - , pong: 3 - , message: 4 - , upgrade: 5 - , noop: 6 - }; - - var packetslist = keys(packets); - - /** - * Premade error packet. - */ - - var err = { type: 'error', data: 'parser error' }; - - /** - * Create a blob api even for blob builder when vendor prefixes exist - */ - - var Blob = _dereq_('blob'); - - /** - * Encodes a packet. - * - * <packet type id> [ <data> ] - * - * Example: - * - * 5hello world - * 3 - * 4 - * - * Binary is encoded in an identical principle - * - * @api private - */ - - exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) { - if ('function' == typeof supportsBinary) { - callback = supportsBinary; - supportsBinary = false; - } - - if ('function' == typeof utf8encode) { - callback = utf8encode; - utf8encode = null; - } - - var data = (packet.data === undefined) - ? undefined - : packet.data.buffer || packet.data; - - if (global.ArrayBuffer && data instanceof ArrayBuffer) { - return encodeArrayBuffer(packet, supportsBinary, callback); - } else if (Blob && data instanceof global.Blob) { - return encodeBlob(packet, supportsBinary, callback); - } - - // might be an object with { base64: true, data: dataAsBase64String } - if (data && data.base64) { - return encodeBase64Object(packet, callback); - } - - // Sending data as a utf-8 string - var encoded = packets[packet.type]; - - // data fragment is optional - if (undefined !== packet.data) { - encoded += utf8encode ? utf8.encode(String(packet.data)) : String(packet.data); - } - - return callback('' + encoded); - - }; - - function encodeBase64Object(packet, callback) { - // packet data is an object { base64: true, data: dataAsBase64String } - var message = 'b' + exports.packets[packet.type] + packet.data.data; - return callback(message); - } - - /** - * Encode packet helpers for binary types - */ - - function encodeArrayBuffer(packet, supportsBinary, callback) { - if (!supportsBinary) { - return exports.encodeBase64Packet(packet, callback); - } - - var data = packet.data; - var contentArray = new Uint8Array(data); - var resultBuffer = new Uint8Array(1 + data.byteLength); - - resultBuffer[0] = packets[packet.type]; - for (var i = 0; i < contentArray.length; i++) { - resultBuffer[i+1] = contentArray[i]; - } - - return callback(resultBuffer.buffer); - } - - function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) { - if (!supportsBinary) { - return exports.encodeBase64Packet(packet, callback); - } - - var fr = new FileReader(); - fr.onload = function() { - packet.data = fr.result; - exports.encodePacket(packet, supportsBinary, true, callback); - }; - return fr.readAsArrayBuffer(packet.data); - } - - function encodeBlob(packet, supportsBinary, callback) { - if (!supportsBinary) { - return exports.encodeBase64Packet(packet, callback); - } - - if (dontSendBlobs) { - return encodeBlobAsArrayBuffer(packet, supportsBinary, callback); - } - - var length = new Uint8Array(1); - length[0] = packets[packet.type]; - var blob = new Blob([length.buffer, packet.data]); - - return callback(blob); - } - - /** - * Encodes a packet with binary data in a base64 string - * - * @param {Object} packet, has `type` and `data` - * @return {String} base64 encoded message - */ - - exports.encodeBase64Packet = function(packet, callback) { - var message = 'b' + exports.packets[packet.type]; - if (Blob && packet.data instanceof Blob) { - var fr = new FileReader(); - fr.onload = function() { - var b64 = fr.result.split(',')[1]; - callback(message + b64); - }; - return fr.readAsDataURL(packet.data); - } - - var b64data; - try { - b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data)); - } catch (e) { - // iPhone Safari doesn't let you apply with typed arrays - var typed = new Uint8Array(packet.data); - var basic = new Array(typed.length); - for (var i = 0; i < typed.length; i++) { - basic[i] = typed[i]; - } - b64data = String.fromCharCode.apply(null, basic); - } - message += global.btoa(b64data); - return callback(message); - }; - - /** - * Decodes a packet. Changes format to Blob if requested. - * - * @return {Object} with `type` and `data` (if any) - * @api private - */ - - exports.decodePacket = function (data, binaryType, utf8decode) { - // String data - if (typeof data == 'string' || data === undefined) { - if (data.charAt(0) == 'b') { - return exports.decodeBase64Packet(data.substr(1), binaryType); - } - - if (utf8decode) { - try { - data = utf8.decode(data); - } catch (e) { - return err; - } - } - var type = data.charAt(0); - - if (Number(type) != type || !packetslist[type]) { - return err; - } - - if (data.length > 1) { - return { type: packetslist[type], data: data.substring(1) }; - } else { - return { type: packetslist[type] }; - } - } - - var asArray = new Uint8Array(data); - var type = asArray[0]; - var rest = sliceBuffer(data, 1); - if (Blob && binaryType === 'blob') { - rest = new Blob([rest]); - } - return { type: packetslist[type], data: rest }; - }; - - /** - * Decodes a packet encoded in a base64 string - * - * @param {String} base64 encoded message - * @return {Object} with `type` and `data` (if any) - */ - - exports.decodeBase64Packet = function(msg, binaryType) { - var type = packetslist[msg.charAt(0)]; - if (!global.ArrayBuffer) { - return { type: type, data: { base64: true, data: msg.substr(1) } }; - } - - var data = base64encoder.decode(msg.substr(1)); - - if (binaryType === 'blob' && Blob) { - data = new Blob([data]); - } - - return { type: type, data: data }; - }; - - /** - * Encodes multiple messages (payload). - * - * <length>:data - * - * Example: - * - * 11:hello world2:hi - * - * If any contents are binary, they will be encoded as base64 strings. Base64 - * encoded strings are marked with a b before the length specifier - * - * @param {Array} packets - * @api private - */ - - exports.encodePayload = function (packets, supportsBinary, callback) { - if (typeof supportsBinary == 'function') { - callback = supportsBinary; - supportsBinary = null; - } - - var isBinary = hasBinary(packets); - - if (supportsBinary && isBinary) { - if (Blob && !dontSendBlobs) { - return exports.encodePayloadAsBlob(packets, callback); - } - - return exports.encodePayloadAsArrayBuffer(packets, callback); - } - - if (!packets.length) { - return callback('0:'); - } - - function setLengthHeader(message) { - return message.length + ':' + message; - } - - function encodeOne(packet, doneCallback) { - exports.encodePacket(packet, !isBinary ? false : supportsBinary, true, function(message) { - doneCallback(null, setLengthHeader(message)); - }); - } - - map(packets, encodeOne, function(err, results) { - return callback(results.join('')); - }); - }; - - /** - * Async array map using after - */ - - function map(ary, each, done) { - var result = new Array(ary.length); - var next = after(ary.length, done); - - var eachWithIndex = function(i, el, cb) { - each(el, function(error, msg) { - result[i] = msg; - cb(error, result); - }); - }; - - for (var i = 0; i < ary.length; i++) { - eachWithIndex(i, ary[i], next); - } - } - - /* - * Decodes data when a payload is maybe expected. Possible binary contents are - * decoded from their base64 representation - * - * @param {String} data, callback method - * @api public - */ - - exports.decodePayload = function (data, binaryType, callback) { - if (typeof data != 'string') { - return exports.decodePayloadAsBinary(data, binaryType, callback); - } - - if (typeof binaryType === 'function') { - callback = binaryType; - binaryType = null; - } - - var packet; - if (data == '') { - // parser error - ignoring payload - return callback(err, 0, 1); - } - - var length = '' - , n, msg; - - for (var i = 0, l = data.length; i < l; i++) { - var chr = data.charAt(i); - - if (':' != chr) { - length += chr; - } else { - if ('' == length || (length != (n = Number(length)))) { - // parser error - ignoring payload - return callback(err, 0, 1); - } - - msg = data.substr(i + 1, n); - - if (length != msg.length) { - // parser error - ignoring payload - return callback(err, 0, 1); - } - - if (msg.length) { - packet = exports.decodePacket(msg, binaryType, true); - - if (err.type == packet.type && err.data == packet.data) { - // parser error in individual packet - ignoring payload - return callback(err, 0, 1); - } - - var ret = callback(packet, i + n, l); - if (false === ret) return; - } - - // advance cursor - i += n; - length = ''; - } - } - - if (length != '') { - // parser error - ignoring payload - return callback(err, 0, 1); - } - - }; - - /** - * Encodes multiple messages (payload) as binary. - * - * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number - * 255><data> - * - * Example: - * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers - * - * @param {Array} packets - * @return {ArrayBuffer} encoded payload - * @api private - */ - - exports.encodePayloadAsArrayBuffer = function(packets, callback) { - if (!packets.length) { - return callback(new ArrayBuffer(0)); - } - - function encodeOne(packet, doneCallback) { - exports.encodePacket(packet, true, true, function(data) { - return doneCallback(null, data); - }); - } - - map(packets, encodeOne, function(err, encodedPackets) { - var totalLength = encodedPackets.reduce(function(acc, p) { - var len; - if (typeof p === 'string'){ - len = p.length; - } else { - len = p.byteLength; - } - return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2 - }, 0); - - var resultArray = new Uint8Array(totalLength); - - var bufferIndex = 0; - encodedPackets.forEach(function(p) { - var isString = typeof p === 'string'; - var ab = p; - if (isString) { - var view = new Uint8Array(p.length); - for (var i = 0; i < p.length; i++) { - view[i] = p.charCodeAt(i); - } - ab = view.buffer; - } - - if (isString) { // not true binary - resultArray[bufferIndex++] = 0; - } else { // true binary - resultArray[bufferIndex++] = 1; - } - - var lenStr = ab.byteLength.toString(); - for (var i = 0; i < lenStr.length; i++) { - resultArray[bufferIndex++] = parseInt(lenStr[i]); - } - resultArray[bufferIndex++] = 255; - - var view = new Uint8Array(ab); - for (var i = 0; i < view.length; i++) { - resultArray[bufferIndex++] = view[i]; - } - }); - - return callback(resultArray.buffer); - }); - }; - - /** - * Encode as Blob - */ - - exports.encodePayloadAsBlob = function(packets, callback) { - function encodeOne(packet, doneCallback) { - exports.encodePacket(packet, true, true, function(encoded) { - var binaryIdentifier = new Uint8Array(1); - binaryIdentifier[0] = 1; - if (typeof encoded === 'string') { - var view = new Uint8Array(encoded.length); - for (var i = 0; i < encoded.length; i++) { - view[i] = encoded.charCodeAt(i); - } - encoded = view.buffer; - binaryIdentifier[0] = 0; - } - - var len = (encoded instanceof ArrayBuffer) - ? encoded.byteLength - : encoded.size; - - var lenStr = len.toString(); - var lengthAry = new Uint8Array(lenStr.length + 1); - for (var i = 0; i < lenStr.length; i++) { - lengthAry[i] = parseInt(lenStr[i]); - } - lengthAry[lenStr.length] = 255; - - if (Blob) { - var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]); - doneCallback(null, blob); - } - }); - } - - map(packets, encodeOne, function(err, results) { - return callback(new Blob(results)); - }); - }; - - /* - * Decodes data when a payload is maybe expected. Strings are decoded by - * interpreting each byte as a key code for entries marked to start with 0. See - * description of encodePayloadAsBinary - * - * @param {ArrayBuffer} data, callback method - * @api public - */ - - exports.decodePayloadAsBinary = function (data, binaryType, callback) { - if (typeof binaryType === 'function') { - callback = binaryType; - binaryType = null; - } - - var bufferTail = data; - var buffers = []; - - var numberTooLong = false; - while (bufferTail.byteLength > 0) { - var tailArray = new Uint8Array(bufferTail); - var isString = tailArray[0] === 0; - var msgLength = ''; - - for (var i = 1; ; i++) { - if (tailArray[i] == 255) break; - - if (msgLength.length > 310) { - numberTooLong = true; - break; - } - - msgLength += tailArray[i]; - } - - if(numberTooLong) return callback(err, 0, 1); - - bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length); - msgLength = parseInt(msgLength); - - var msg = sliceBuffer(bufferTail, 0, msgLength); - if (isString) { - try { - msg = String.fromCharCode.apply(null, new Uint8Array(msg)); - } catch (e) { - // iPhone Safari doesn't let you apply to typed arrays - var typed = new Uint8Array(msg); - msg = ''; - for (var i = 0; i < typed.length; i++) { - msg += String.fromCharCode(typed[i]); - } - } - } - - buffers.push(msg); - bufferTail = sliceBuffer(bufferTail, msgLength); - } - - var total = buffers.length; - buffers.forEach(function(buffer, i) { - callback(exports.decodePacket(buffer, binaryType, true), i, total); - }); - }; - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./keys":26,"after":27,"arraybuffer.slice":28,"base64-arraybuffer":29,"blob":30,"has-binary":31,"utf8":33}],26:[function(_dereq_,module,exports){ - - /** - * Gets the keys for an object. - * - * @return {Array} keys - * @api private - */ - - module.exports = Object.keys || function keys (obj){ - var arr = []; - var has = Object.prototype.hasOwnProperty; - - for (var i in obj) { - if (has.call(obj, i)) { - arr.push(i); - } - } - return arr; - }; - -},{}],27:[function(_dereq_,module,exports){ - module.exports = after - - function after(count, callback, err_cb) { - var bail = false - err_cb = err_cb || noop - proxy.count = count - - return (count === 0) ? callback() : proxy - - function proxy(err, result) { - if (proxy.count <= 0) { - throw new Error('after called too many times') - } - --proxy.count - - // after first error, rest are passed to err_cb - if (err) { - bail = true - callback(err) - // future error callbacks will go to error handler - callback = err_cb - } else if (proxy.count === 0 && !bail) { - callback(null, result) - } - } - } - - function noop() {} - -},{}],28:[function(_dereq_,module,exports){ - /** - * An abstraction for slicing an arraybuffer even when - * ArrayBuffer.prototype.slice is not supported - * - * @api public - */ - - module.exports = function(arraybuffer, start, end) { - var bytes = arraybuffer.byteLength; - start = start || 0; - end = end || bytes; - - if (arraybuffer.slice) { return arraybuffer.slice(start, end); } - - if (start < 0) { start += bytes; } - if (end < 0) { end += bytes; } - if (end > bytes) { end = bytes; } - - if (start >= bytes || start >= end || bytes === 0) { - return new ArrayBuffer(0); - } - - var abv = new Uint8Array(arraybuffer); - var result = new Uint8Array(end - start); - for (var i = start, ii = 0; i < end; i++, ii++) { - result[ii] = abv[i]; - } - return result.buffer; - }; - -},{}],29:[function(_dereq_,module,exports){ - /* - * base64-arraybuffer - * https://github.com/niklasvh/base64-arraybuffer - * - * Copyright (c) 2012 Niklas von Hertzen - * Licensed under the MIT license. - */ - (function(chars){ - "use strict"; - - exports.encode = function(arraybuffer) { - var bytes = new Uint8Array(arraybuffer), - i, len = bytes.length, base64 = ""; - - for (i = 0; i < len; i+=3) { - base64 += chars[bytes[i] >> 2]; - base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; - base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; - base64 += chars[bytes[i + 2] & 63]; - } - - if ((len % 3) === 2) { - base64 = base64.substring(0, base64.length - 1) + "="; - } else if (len % 3 === 1) { - base64 = base64.substring(0, base64.length - 2) + "=="; - } - - return base64; - }; - - exports.decode = function(base64) { - var bufferLength = base64.length * 0.75, - len = base64.length, i, p = 0, - encoded1, encoded2, encoded3, encoded4; - - if (base64[base64.length - 1] === "=") { - bufferLength--; - if (base64[base64.length - 2] === "=") { - bufferLength--; - } - } - - var arraybuffer = new ArrayBuffer(bufferLength), - bytes = new Uint8Array(arraybuffer); - - for (i = 0; i < len; i+=4) { - encoded1 = chars.indexOf(base64[i]); - encoded2 = chars.indexOf(base64[i+1]); - encoded3 = chars.indexOf(base64[i+2]); - encoded4 = chars.indexOf(base64[i+3]); - - bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); - bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); - bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); - } - - return arraybuffer; - }; - })("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); - -},{}],30:[function(_dereq_,module,exports){ - (function (global){ - /** - * Create a blob builder even when vendor prefixes exist - */ - - var BlobBuilder = global.BlobBuilder - || global.WebKitBlobBuilder - || global.MSBlobBuilder - || global.MozBlobBuilder; - - /** - * Check if Blob constructor is supported - */ - - var blobSupported = (function() { - try { - var b = new Blob(['hi']); - return b.size == 2; - } catch(e) { - return false; - } - })(); - - /** - * Check if BlobBuilder is supported - */ - - var blobBuilderSupported = BlobBuilder - && BlobBuilder.prototype.append - && BlobBuilder.prototype.getBlob; - - function BlobBuilderConstructor(ary, options) { - options = options || {}; - - var bb = new BlobBuilder(); - for (var i = 0; i < ary.length; i++) { - bb.append(ary[i]); - } - return (options.type) ? bb.getBlob(options.type) : bb.getBlob(); - }; - - module.exports = (function() { - if (blobSupported) { - return global.Blob; - } else if (blobBuilderSupported) { - return BlobBuilderConstructor; - } else { - return undefined; - } - })(); - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],31:[function(_dereq_,module,exports){ - (function (global){ - - /* - * Module requirements. - */ - - var isArray = _dereq_('isarray'); - - /** - * Module exports. - */ - - module.exports = hasBinary; - - /** - * Checks for binary data. - * - * Right now only Buffer and ArrayBuffer are supported.. - * - * @param {Object} anything - * @api public - */ - - function hasBinary(data) { - - function _hasBinary(obj) { - if (!obj) return false; - - if ( (global.Buffer && global.Buffer.isBuffer(obj)) || - (global.ArrayBuffer && obj instanceof ArrayBuffer) || - (global.Blob && obj instanceof Blob) || - (global.File && obj instanceof File) - ) { - return true; - } - - if (isArray(obj)) { - for (var i = 0; i < obj.length; i++) { - if (_hasBinary(obj[i])) { - return true; - } - } - } else if (obj && 'object' == typeof obj) { - if (obj.toJSON) { - obj = obj.toJSON(); - } - - for (var key in obj) { - if (obj.hasOwnProperty(key) && _hasBinary(obj[key])) { - return true; - } - } - } - - return false; - } - - return _hasBinary(data); - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"isarray":32}],32:[function(_dereq_,module,exports){ - module.exports = Array.isArray || function (arr) { - return Object.prototype.toString.call(arr) == '[object Array]'; - }; - -},{}],33:[function(_dereq_,module,exports){ - (function (global){ - /*! http://mths.be/utf8js v2.0.0 by @mathias */ - ;(function(root) { - - // Detect free variables `exports` - var freeExports = typeof exports == 'object' && exports; - - // Detect free variable `module` - var freeModule = typeof module == 'object' && module && - module.exports == freeExports && module; - - // Detect free variable `global`, from Node.js or Browserified code, - // and use it as `root` - var freeGlobal = typeof global == 'object' && global; - if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { - root = freeGlobal; - } - - /*--------------------------------------------------------------------------*/ - - var stringFromCharCode = String.fromCharCode; - - // Taken from http://mths.be/punycode - function ucs2decode(string) { - var output = []; - var counter = 0; - var length = string.length; - var value; - var extra; - while (counter < length) { - value = string.charCodeAt(counter++); - if (value >= 0xD800 && value <= 0xDBFF && counter < length) { - // high surrogate, and there is a next character - extra = string.charCodeAt(counter++); - if ((extra & 0xFC00) == 0xDC00) { // low surrogate - output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - // unmatched surrogate; only append this code unit, in case the next - // code unit is the high surrogate of a surrogate pair - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; - } - - // Taken from http://mths.be/punycode - function ucs2encode(array) { - var length = array.length; - var index = -1; - var value; - var output = ''; - while (++index < length) { - value = array[index]; - if (value > 0xFFFF) { - value -= 0x10000; - output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - output += stringFromCharCode(value); - } - return output; - } - - /*--------------------------------------------------------------------------*/ - - function createByte(codePoint, shift) { - return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80); - } - - function encodeCodePoint(codePoint) { - if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence - return stringFromCharCode(codePoint); - } - var symbol = ''; - if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence - symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0); - } - else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence - symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0); - symbol += createByte(codePoint, 6); - } - else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence - symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0); - symbol += createByte(codePoint, 12); - symbol += createByte(codePoint, 6); - } - symbol += stringFromCharCode((codePoint & 0x3F) | 0x80); - return symbol; - } - - function utf8encode(string) { - var codePoints = ucs2decode(string); - - // console.log(JSON.stringify(codePoints.map(function(x) { - // return 'U+' + x.toString(16).toUpperCase(); - // }))); - - var length = codePoints.length; - var index = -1; - var codePoint; - var byteString = ''; - while (++index < length) { - codePoint = codePoints[index]; - byteString += encodeCodePoint(codePoint); - } - return byteString; - } - - /*--------------------------------------------------------------------------*/ - - function readContinuationByte() { - if (byteIndex >= byteCount) { - throw Error('Invalid byte index'); - } - - var continuationByte = byteArray[byteIndex] & 0xFF; - byteIndex++; - - if ((continuationByte & 0xC0) == 0x80) { - return continuationByte & 0x3F; - } - - // If we end up here, it’s not a continuation byte - throw Error('Invalid continuation byte'); - } - - function decodeSymbol() { - var byte1; - var byte2; - var byte3; - var byte4; - var codePoint; - - if (byteIndex > byteCount) { - throw Error('Invalid byte index'); - } - - if (byteIndex == byteCount) { - return false; - } - - // Read first byte - byte1 = byteArray[byteIndex] & 0xFF; - byteIndex++; - - // 1-byte sequence (no continuation bytes) - if ((byte1 & 0x80) == 0) { - return byte1; - } - - // 2-byte sequence - if ((byte1 & 0xE0) == 0xC0) { - var byte2 = readContinuationByte(); - codePoint = ((byte1 & 0x1F) << 6) | byte2; - if (codePoint >= 0x80) { - return codePoint; - } else { - throw Error('Invalid continuation byte'); - } - } - - // 3-byte sequence (may include unpaired surrogates) - if ((byte1 & 0xF0) == 0xE0) { - byte2 = readContinuationByte(); - byte3 = readContinuationByte(); - codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3; - if (codePoint >= 0x0800) { - return codePoint; - } else { - throw Error('Invalid continuation byte'); - } - } - - // 4-byte sequence - if ((byte1 & 0xF8) == 0xF0) { - byte2 = readContinuationByte(); - byte3 = readContinuationByte(); - byte4 = readContinuationByte(); - codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) | - (byte3 << 0x06) | byte4; - if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) { - return codePoint; - } - } - - throw Error('Invalid UTF-8 detected'); - } - - var byteArray; - var byteCount; - var byteIndex; - function utf8decode(byteString) { - byteArray = ucs2decode(byteString); - byteCount = byteArray.length; - byteIndex = 0; - var codePoints = []; - var tmp; - while ((tmp = decodeSymbol()) !== false) { - codePoints.push(tmp); - } - return ucs2encode(codePoints); - } - - /*--------------------------------------------------------------------------*/ - - var utf8 = { - 'version': '2.0.0', - 'encode': utf8encode, - 'decode': utf8decode - }; - - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - typeof define == 'function' && - typeof define.amd == 'object' && - define.amd - ) { - define(function() { - return utf8; - }); - } else if (freeExports && !freeExports.nodeType) { - if (freeModule) { // in Node.js or RingoJS v0.8.0+ - freeModule.exports = utf8; - } else { // in Narwhal or RingoJS v0.7.0- - var object = {}; - var hasOwnProperty = object.hasOwnProperty; - for (var key in utf8) { - hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]); - } - } - } else { // in Rhino or a web browser - root.utf8 = utf8; - } - - }(this)); - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],34:[function(_dereq_,module,exports){ - (function (global){ - /** - * JSON parse. - * - * @see Based on jQuery#parseJSON (MIT) and JSON2 - * @api private - */ - - var rvalidchars = /^[\],:{}\s]*$/; - var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g; - var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g; - var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g; - var rtrimLeft = /^\s+/; - var rtrimRight = /\s+$/; - - module.exports = function parsejson(data) { - if ('string' != typeof data || !data) { - return null; - } - - data = data.replace(rtrimLeft, '').replace(rtrimRight, ''); - - // Attempt to parse using the native JSON parser first - if (global.JSON && JSON.parse) { - return JSON.parse(data); - } - - if (rvalidchars.test(data.replace(rvalidescape, '@') - .replace(rvalidtokens, ']') - .replace(rvalidbraces, ''))) { - return (new Function('return ' + data))(); - } - }; - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],35:[function(_dereq_,module,exports){ - /** - * Compiles a querystring - * Returns string representation of the object - * - * @param {Object} - * @api private - */ - - exports.encode = function (obj) { - var str = ''; - - for (var i in obj) { - if (obj.hasOwnProperty(i)) { - if (str.length) str += '&'; - str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]); - } - } - - return str; - }; - - /** - * Parses a simple querystring into an object - * - * @param {String} qs - * @api private - */ - - exports.decode = function(qs){ - var qry = {}; - var pairs = qs.split('&'); - for (var i = 0, l = pairs.length; i < l; i++) { - var pair = pairs[i].split('='); - qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); - } - return qry; - }; - -},{}],36:[function(_dereq_,module,exports){ - /** - * Parses an URI - * - * @author Steven Levithan <stevenlevithan.com> (MIT license) - * @api private - */ - - var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; - - var parts = [ - 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' - ]; - - module.exports = function parseuri(str) { - var src = str, - b = str.indexOf('['), - e = str.indexOf(']'); - - if (b != -1 && e != -1) { - str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length); - } - - var m = re.exec(str || ''), - uri = {}, - i = 14; - - while (i--) { - uri[parts[i]] = m[i] || ''; - } - - if (b != -1 && e != -1) { - uri.source = src; - uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':'); - uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':'); - uri.ipv6uri = true; - } - - return uri; - }; - -},{}],37:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var global = (function() { return this; })(); - - /** - * WebSocket constructor. - */ - - var WebSocket = global.WebSocket || global.MozWebSocket; - - /** - * Module exports. - */ - - module.exports = WebSocket ? ws : null; - - /** - * WebSocket constructor. - * - * The third `opts` options object gets ignored in web browsers, since it's - * non-standard, and throws a TypeError if passed to the constructor. - * See: https://github.com/einaros/ws/issues/227 - * - * @param {String} uri - * @param {Array} protocols (optional) - * @param {Object) opts (optional) - * @api public - */ - - function ws(uri, protocols, opts) { - var instance; - if (protocols) { - instance = new WebSocket(uri, protocols); - } else { - instance = new WebSocket(uri); - } - return instance; - } - - if (WebSocket) ws.prototype = WebSocket.prototype; - -},{}],38:[function(_dereq_,module,exports){ - (function (global){ - - /* - * Module requirements. - */ - - var isArray = _dereq_('isarray'); - - /** - * Module exports. - */ - - module.exports = hasBinary; - - /** - * Checks for binary data. - * - * Right now only Buffer and ArrayBuffer are supported.. - * - * @param {Object} anything - * @api public - */ - - function hasBinary(data) { - - function _hasBinary(obj) { - if (!obj) return false; - - if ( (global.Buffer && global.Buffer.isBuffer(obj)) || - (global.ArrayBuffer && obj instanceof ArrayBuffer) || - (global.Blob && obj instanceof Blob) || - (global.File && obj instanceof File) - ) { - return true; - } - - if (isArray(obj)) { - for (var i = 0; i < obj.length; i++) { - if (_hasBinary(obj[i])) { - return true; - } - } - } else if (obj && 'object' == typeof obj) { - if (obj.toJSON) { - obj = obj.toJSON(); - } - - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) { - return true; - } - } - } - - return false; - } - - return _hasBinary(data); - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"isarray":39}],39:[function(_dereq_,module,exports){ - module.exports=_dereq_(32) -},{}],40:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var global = _dereq_('global'); - - /** - * Module exports. - * - * Logic borrowed from Modernizr: - * - * - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js - */ - - try { - module.exports = 'XMLHttpRequest' in global && - 'withCredentials' in new global.XMLHttpRequest(); - } catch (err) { - // if XMLHttp support is disabled in IE then it will throw - // when trying to create - module.exports = false; - } - -},{"global":41}],41:[function(_dereq_,module,exports){ - - /** - * Returns `this`. Execute this without a "context" (i.e. without it being - * attached to an object of the left-hand side), and `this` points to the - * "global" scope of the current JS execution. - */ - - module.exports = (function () { return this; })(); - -},{}],42:[function(_dereq_,module,exports){ - - var indexOf = [].indexOf; - - module.exports = function(arr, obj){ - if (indexOf) return arr.indexOf(obj); - for (var i = 0; i < arr.length; ++i) { - if (arr[i] === obj) return i; - } - return -1; - }; -},{}],43:[function(_dereq_,module,exports){ - - /** - * HOP ref. - */ - - var has = Object.prototype.hasOwnProperty; - - /** - * Return own keys in `obj`. - * - * @param {Object} obj - * @return {Array} - * @api public - */ - - exports.keys = Object.keys || function(obj){ - var keys = []; - for (var key in obj) { - if (has.call(obj, key)) { - keys.push(key); - } - } - return keys; - }; - - /** - * Return own values in `obj`. - * - * @param {Object} obj - * @return {Array} - * @api public - */ - - exports.values = function(obj){ - var vals = []; - for (var key in obj) { - if (has.call(obj, key)) { - vals.push(obj[key]); - } - } - return vals; - }; - - /** - * Merge `b` into `a`. - * - * @param {Object} a - * @param {Object} b - * @return {Object} a - * @api public - */ - - exports.merge = function(a, b){ - for (var key in b) { - if (has.call(b, key)) { - a[key] = b[key]; - } - } - return a; - }; - - /** - * Return length of `obj`. - * - * @param {Object} obj - * @return {Number} - * @api public - */ - - exports.length = function(obj){ - return exports.keys(obj).length; - }; - - /** - * Check if `obj` is empty. - * - * @param {Object} obj - * @return {Boolean} - * @api public - */ - - exports.isEmpty = function(obj){ - return 0 == exports.length(obj); - }; -},{}],44:[function(_dereq_,module,exports){ - /** - * Parses an URI - * - * @author Steven Levithan <stevenlevithan.com> (MIT license) - * @api private - */ - - var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; - - var parts = [ - 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host' - , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' - ]; - - module.exports = function parseuri(str) { - var m = re.exec(str || '') - , uri = {} - , i = 14; - - while (i--) { - uri[parts[i]] = m[i] || ''; - } - - return uri; - }; - -},{}],45:[function(_dereq_,module,exports){ - (function (global){ - /*global Blob,File*/ - - /** - * Module requirements - */ - - var isArray = _dereq_('isarray'); - var isBuf = _dereq_('./is-buffer'); - - /** - * Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder. - * Anything with blobs or files should be fed through removeBlobs before coming - * here. - * - * @param {Object} packet - socket.io event packet - * @return {Object} with deconstructed packet and list of buffers - * @api public - */ - - exports.deconstructPacket = function(packet){ - var buffers = []; - var packetData = packet.data; - - function _deconstructPacket(data) { - if (!data) return data; - - if (isBuf(data)) { - var placeholder = { _placeholder: true, num: buffers.length }; - buffers.push(data); - return placeholder; - } else if (isArray(data)) { - var newData = new Array(data.length); - for (var i = 0; i < data.length; i++) { - newData[i] = _deconstructPacket(data[i]); - } - return newData; - } else if ('object' == typeof data && !(data instanceof Date)) { - var newData = {}; - for (var key in data) { - newData[key] = _deconstructPacket(data[key]); - } - return newData; - } - return data; - } - - var pack = packet; - pack.data = _deconstructPacket(packetData); - pack.attachments = buffers.length; // number of binary 'attachments' - return {packet: pack, buffers: buffers}; - }; - - /** - * Reconstructs a binary packet from its placeholder packet and buffers - * - * @param {Object} packet - event packet with placeholders - * @param {Array} buffers - binary buffers to put in placeholder positions - * @return {Object} reconstructed packet - * @api public - */ - - exports.reconstructPacket = function(packet, buffers) { - var curPlaceHolder = 0; - - function _reconstructPacket(data) { - if (data && data._placeholder) { - var buf = buffers[data.num]; // appropriate buffer (should be natural order anyway) - return buf; - } else if (isArray(data)) { - for (var i = 0; i < data.length; i++) { - data[i] = _reconstructPacket(data[i]); - } - return data; - } else if (data && 'object' == typeof data) { - for (var key in data) { - data[key] = _reconstructPacket(data[key]); - } - return data; - } - return data; - } - - packet.data = _reconstructPacket(packet.data); - packet.attachments = undefined; // no longer useful - return packet; - }; - - /** - * Asynchronously removes Blobs or Files from data via - * FileReader's readAsArrayBuffer method. Used before encoding - * data as msgpack. Calls callback with the blobless data. - * - * @param {Object} data - * @param {Function} callback - * @api private - */ - - exports.removeBlobs = function(data, callback) { - function _removeBlobs(obj, curKey, containingObject) { - if (!obj) return obj; - - // convert any blob - if ((global.Blob && obj instanceof Blob) || - (global.File && obj instanceof File)) { - pendingBlobs++; - - // async filereader - var fileReader = new FileReader(); - fileReader.onload = function() { // this.result == arraybuffer - if (containingObject) { - containingObject[curKey] = this.result; - } - else { - bloblessData = this.result; - } - - // if nothing pending its callback time - if(! --pendingBlobs) { - callback(bloblessData); - } - }; - - fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer - } else if (isArray(obj)) { // handle array - for (var i = 0; i < obj.length; i++) { - _removeBlobs(obj[i], i, obj); - } - } else if (obj && 'object' == typeof obj && !isBuf(obj)) { // and object - for (var key in obj) { - _removeBlobs(obj[key], key, obj); - } - } - } - - var pendingBlobs = 0; - var bloblessData = data; - _removeBlobs(bloblessData); - if (!pendingBlobs) { - callback(bloblessData); - } - }; - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./is-buffer":47,"isarray":48}],46:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var debug = _dereq_('debug')('socket.io-parser'); - var json = _dereq_('json3'); - var isArray = _dereq_('isarray'); - var Emitter = _dereq_('component-emitter'); - var binary = _dereq_('./binary'); - var isBuf = _dereq_('./is-buffer'); - - /** - * Protocol version. - * - * @api public - */ - - exports.protocol = 4; - - /** - * Packet types. - * - * @api public - */ - - exports.types = [ - 'CONNECT', - 'DISCONNECT', - 'EVENT', - 'BINARY_EVENT', - 'ACK', - 'BINARY_ACK', - 'ERROR' - ]; - - /** - * Packet type `connect`. - * - * @api public - */ - - exports.CONNECT = 0; - - /** - * Packet type `disconnect`. - * - * @api public - */ - - exports.DISCONNECT = 1; - - /** - * Packet type `event`. - * - * @api public - */ - - exports.EVENT = 2; - - /** - * Packet type `ack`. - * - * @api public - */ - - exports.ACK = 3; - - /** - * Packet type `error`. - * - * @api public - */ - - exports.ERROR = 4; - - /** - * Packet type 'binary event' - * - * @api public - */ - - exports.BINARY_EVENT = 5; - - /** - * Packet type `binary ack`. For acks with binary arguments. - * - * @api public - */ - - exports.BINARY_ACK = 6; - - /** - * Encoder constructor. - * - * @api public - */ - - exports.Encoder = Encoder; - - /** - * Decoder constructor. - * - * @api public - */ - - exports.Decoder = Decoder; - - /** - * A socket.io Encoder instance - * - * @api public - */ - - function Encoder() {} - - /** - * Encode a packet as a single string if non-binary, or as a - * buffer sequence, depending on packet type. - * - * @param {Object} obj - packet object - * @param {Function} callback - function to handle encodings (likely engine.write) - * @return Calls callback with Array of encodings - * @api public - */ - - Encoder.prototype.encode = function(obj, callback){ - debug('encoding packet %j', obj); - - if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) { - encodeAsBinary(obj, callback); - } - else { - var encoding = encodeAsString(obj); - callback([encoding]); - } - }; - - /** - * Encode packet as string. - * - * @param {Object} packet - * @return {String} encoded - * @api private - */ - - function encodeAsString(obj) { - var str = ''; - var nsp = false; - - // first is type - str += obj.type; - - // attachments if we have them - if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) { - str += obj.attachments; - str += '-'; - } - - // if we have a namespace other than `/` - // we append it followed by a comma `,` - if (obj.nsp && '/' != obj.nsp) { - nsp = true; - str += obj.nsp; - } - - // immediately followed by the id - if (null != obj.id) { - if (nsp) { - str += ','; - nsp = false; - } - str += obj.id; - } - - // json data - if (null != obj.data) { - if (nsp) str += ','; - str += json.stringify(obj.data); - } - - debug('encoded %j as %s', obj, str); - return str; - } - - /** - * Encode packet as 'buffer sequence' by removing blobs, and - * deconstructing packet into object with placeholders and - * a list of buffers. - * - * @param {Object} packet - * @return {Buffer} encoded - * @api private - */ - - function encodeAsBinary(obj, callback) { - - function writeEncoding(bloblessData) { - var deconstruction = binary.deconstructPacket(bloblessData); - var pack = encodeAsString(deconstruction.packet); - var buffers = deconstruction.buffers; - - buffers.unshift(pack); // add packet info to beginning of data list - callback(buffers); // write all the buffers - } - - binary.removeBlobs(obj, writeEncoding); - } - - /** - * A socket.io Decoder instance - * - * @return {Object} decoder - * @api public - */ - - function Decoder() { - this.reconstructor = null; - } - - /** - * Mix in `Emitter` with Decoder. - */ - - Emitter(Decoder.prototype); - - /** - * Decodes an ecoded packet string into packet JSON. - * - * @param {String} obj - encoded packet - * @return {Object} packet - * @api public - */ - - Decoder.prototype.add = function(obj) { - var packet; - if ('string' == typeof obj) { - packet = decodeString(obj); - if (exports.BINARY_EVENT == packet.type || exports.BINARY_ACK == packet.type) { // binary packet's json - this.reconstructor = new BinaryReconstructor(packet); - - // no attachments, labeled binary but no binary data to follow - if (this.reconstructor.reconPack.attachments === 0) { - this.emit('decoded', packet); - } - } else { // non-binary full packet - this.emit('decoded', packet); - } - } - else if (isBuf(obj) || obj.base64) { // raw binary data - if (!this.reconstructor) { - throw new Error('got binary data when not reconstructing a packet'); - } else { - packet = this.reconstructor.takeBinaryData(obj); - if (packet) { // received final buffer - this.reconstructor = null; - this.emit('decoded', packet); - } - } - } - else { - throw new Error('Unknown type: ' + obj); - } - }; - - /** - * Decode a packet String (JSON data) - * - * @param {String} str - * @return {Object} packet - * @api private - */ - - function decodeString(str) { - var p = {}; - var i = 0; - - // look up type - p.type = Number(str.charAt(0)); - if (null == exports.types[p.type]) return error(); - - // look up attachments if type binary - if (exports.BINARY_EVENT == p.type || exports.BINARY_ACK == p.type) { - var buf = ''; - while (str.charAt(++i) != '-') { - buf += str.charAt(i); - if (i + 1 == str.length) break; - } - if (buf != Number(buf) || str.charAt(i) != '-') { - throw new Error('Illegal attachments'); - } - p.attachments = Number(buf); - } - - // look up namespace (if any) - if ('/' == str.charAt(i + 1)) { - p.nsp = ''; - while (++i) { - var c = str.charAt(i); - if (',' == c) break; - p.nsp += c; - if (i + 1 == str.length) break; - } - } else { - p.nsp = '/'; - } - - // look up id - var next = str.charAt(i + 1); - if ('' !== next && Number(next) == next) { - p.id = ''; - while (++i) { - var c = str.charAt(i); - if (null == c || Number(c) != c) { - --i; - break; - } - p.id += str.charAt(i); - if (i + 1 == str.length) break; - } - p.id = Number(p.id); - } - - // look up json data - if (str.charAt(++i)) { - try { - p.data = json.parse(str.substr(i)); - } catch(e){ - return error(); - } - } - - debug('decoded %s as %j', str, p); - return p; - } - - /** - * Deallocates a parser's resources - * - * @api public - */ - - Decoder.prototype.destroy = function() { - if (this.reconstructor) { - this.reconstructor.finishedReconstruction(); - } - }; - - /** - * A manager of a binary event's 'buffer sequence'. Should - * be constructed whenever a packet of type BINARY_EVENT is - * decoded. - * - * @param {Object} packet - * @return {BinaryReconstructor} initialized reconstructor - * @api private - */ - - function BinaryReconstructor(packet) { - this.reconPack = packet; - this.buffers = []; - } - - /** - * Method to be called when binary data received from connection - * after a BINARY_EVENT packet. - * - * @param {Buffer | ArrayBuffer} binData - the raw binary data received - * @return {null | Object} returns null if more binary data is expected or - * a reconstructed packet object if all buffers have been received. - * @api private - */ - - BinaryReconstructor.prototype.takeBinaryData = function(binData) { - this.buffers.push(binData); - if (this.buffers.length == this.reconPack.attachments) { // done with buffer list - var packet = binary.reconstructPacket(this.reconPack, this.buffers); - this.finishedReconstruction(); - return packet; - } - return null; - }; - - /** - * Cleans up binary packet reconstruction variables. - * - * @api private - */ - - BinaryReconstructor.prototype.finishedReconstruction = function() { - this.reconPack = null; - this.buffers = []; - }; - - function error(data){ - return { - type: exports.ERROR, - data: 'parser error' - }; - } - -},{"./binary":45,"./is-buffer":47,"component-emitter":9,"debug":10,"isarray":48,"json3":49}],47:[function(_dereq_,module,exports){ - (function (global){ - - module.exports = isBuf; - - /** - * Returns true if obj is a buffer or an arraybuffer. - * - * @api private - */ - - function isBuf(obj) { - return (global.Buffer && global.Buffer.isBuffer(obj)) || - (global.ArrayBuffer && obj instanceof ArrayBuffer); - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],48:[function(_dereq_,module,exports){ - module.exports=_dereq_(32) -},{}],49:[function(_dereq_,module,exports){ - /*! JSON v3.2.6 | http://bestiejs.github.io/json3 | Copyright 2012-2013, Kit Cambridge | http://kit.mit-license.org */ - ;(function (window) { - // Convenience aliases. - var getClass = {}.toString, isProperty, forEach, undef; - - // Detect the `define` function exposed by asynchronous module loaders. The - // strict `define` check is necessary for compatibility with `r.js`. - var isLoader = typeof define === "function" && define.amd; - - // Detect native implementations. - var nativeJSON = typeof JSON == "object" && JSON; - - // Set up the JSON 3 namespace, preferring the CommonJS `exports` object if - // available. - var JSON3 = typeof exports == "object" && exports && !exports.nodeType && exports; - - if (JSON3 && nativeJSON) { - // Explicitly delegate to the native `stringify` and `parse` - // implementations in CommonJS environments. - JSON3.stringify = nativeJSON.stringify; - JSON3.parse = nativeJSON.parse; - } else { - // Export for web browsers, JavaScript engines, and asynchronous module - // loaders, using the global `JSON` object if available. - JSON3 = window.JSON = nativeJSON || {}; - } - - // Test the `Date#getUTC*` methods. Based on work by @Yaffle. - var isExtended = new Date(-3509827334573292); - try { - // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical - // results for certain dates in Opera >= 10.53. - isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 && - // Safari < 2.0.2 stores the internal millisecond time value correctly, - // but clips the values returned by the date methods to the range of - // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]). - isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708; - } catch (exception) {} - - // Internal: Determines whether the native `JSON.stringify` and `parse` - // implementations are spec-compliant. Based on work by Ken Snyder. - function has(name) { - if (has[name] !== undef) { - // Return cached feature test result. - return has[name]; - } - - var isSupported; - if (name == "bug-string-char-index") { - // IE <= 7 doesn't support accessing string characters using square - // bracket notation. IE 8 only supports this for primitives. - isSupported = "a"[0] != "a"; - } else if (name == "json") { - // Indicates whether both `JSON.stringify` and `JSON.parse` are - // supported. - isSupported = has("json-stringify") && has("json-parse"); - } else { - var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'; - // Test `JSON.stringify`. - if (name == "json-stringify") { - var stringify = JSON3.stringify, stringifySupported = typeof stringify == "function" && isExtended; - if (stringifySupported) { - // A test function object with a custom `toJSON` method. - (value = function () { - return 1; - }).toJSON = value; - try { - stringifySupported = - // Firefox 3.1b1 and b2 serialize string, number, and boolean - // primitives as object literals. - stringify(0) === "0" && - // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object - // literals. - stringify(new Number()) === "0" && - stringify(new String()) == '""' && - // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or - // does not define a canonical JSON representation (this applies to - // objects with `toJSON` properties as well, *unless* they are nested - // within an object or array). - stringify(getClass) === undef && - // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and - // FF 3.1b3 pass this test. - stringify(undef) === undef && - // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s, - // respectively, if the value is omitted entirely. - stringify() === undef && - // FF 3.1b1, 2 throw an error if the given value is not a number, - // string, array, object, Boolean, or `null` literal. This applies to - // objects with custom `toJSON` methods as well, unless they are nested - // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON` - // methods entirely. - stringify(value) === "1" && - stringify([value]) == "[1]" && - // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of - // `"[null]"`. - stringify([undef]) == "[null]" && - // YUI 3.0.0b1 fails to serialize `null` literals. - stringify(null) == "null" && - // FF 3.1b1, 2 halts serialization if an array contains a function: - // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3 - // elides non-JSON values from objects and arrays, unless they - // define custom `toJSON` methods. - stringify([undef, getClass, null]) == "[null,null,null]" && - // Simple serialization test. FF 3.1b1 uses Unicode escape sequences - // where character escape codes are expected (e.g., `\b` => `\u0008`). - stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized && - // FF 3.1b1 and b2 ignore the `filter` and `width` arguments. - stringify(null, value) === "1" && - stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" && - // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly - // serialize extended years. - stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' && - // The milliseconds are optional in ES 5, but required in 5.1. - stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' && - // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative - // four-digit years instead of six-digit years. Credits: @Yaffle. - stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' && - // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond - // values less than 1000. Credits: @Yaffle. - stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"'; - } catch (exception) { - stringifySupported = false; - } - } - isSupported = stringifySupported; - } - // Test `JSON.parse`. - if (name == "json-parse") { - var parse = JSON3.parse; - if (typeof parse == "function") { - try { - // FF 3.1b1, b2 will throw an exception if a bare literal is provided. - // Conforming implementations should also coerce the initial argument to - // a string prior to parsing. - if (parse("0") === 0 && !parse(false)) { - // Simple parsing test. - value = parse(serialized); - var parseSupported = value["a"].length == 5 && value["a"][0] === 1; - if (parseSupported) { - try { - // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings. - parseSupported = !parse('"\t"'); - } catch (exception) {} - if (parseSupported) { - try { - // FF 4.0 and 4.0.1 allow leading `+` signs and leading - // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow - // certain octal literals. - parseSupported = parse("01") !== 1; - } catch (exception) {} - } - if (parseSupported) { - try { - // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal - // points. These environments, along with FF 3.1b1 and 2, - // also allow trailing commas in JSON objects and arrays. - parseSupported = parse("1.") !== 1; - } catch (exception) {} - } - } - } - } catch (exception) { - parseSupported = false; - } - } - isSupported = parseSupported; - } - } - return has[name] = !!isSupported; - } - - if (!has("json")) { - // Common `[[Class]]` name aliases. - var functionClass = "[object Function]"; - var dateClass = "[object Date]"; - var numberClass = "[object Number]"; - var stringClass = "[object String]"; - var arrayClass = "[object Array]"; - var booleanClass = "[object Boolean]"; - - // Detect incomplete support for accessing string characters by index. - var charIndexBuggy = has("bug-string-char-index"); - - // Define additional utility methods if the `Date` methods are buggy. - if (!isExtended) { - var floor = Math.floor; - // A mapping between the months of the year and the number of days between - // January 1st and the first of the respective month. - var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; - // Internal: Calculates the number of days between the Unix epoch and the - // first day of the given month. - var getDay = function (year, month) { - return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400); - }; - } - - // Internal: Determines if a property is a direct property of the given - // object. Delegates to the native `Object#hasOwnProperty` method. - if (!(isProperty = {}.hasOwnProperty)) { - isProperty = function (property) { - var members = {}, constructor; - if ((members.__proto__ = null, members.__proto__ = { - // The *proto* property cannot be set multiple times in recent - // versions of Firefox and SeaMonkey. - "toString": 1 - }, members).toString != getClass) { - // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but - // supports the mutable *proto* property. - isProperty = function (property) { - // Capture and break the object's prototype chain (see section 8.6.2 - // of the ES 5.1 spec). The parenthesized expression prevents an - // unsafe transformation by the Closure Compiler. - var original = this.__proto__, result = property in (this.__proto__ = null, this); - // Restore the original prototype chain. - this.__proto__ = original; - return result; - }; - } else { - // Capture a reference to the top-level `Object` constructor. - constructor = members.constructor; - // Use the `constructor` property to simulate `Object#hasOwnProperty` in - // other environments. - isProperty = function (property) { - var parent = (this.constructor || constructor).prototype; - return property in this && !(property in parent && this[property] === parent[property]); - }; - } - members = null; - return isProperty.call(this, property); - }; - } - - // Internal: A set of primitive types used by `isHostType`. - var PrimitiveTypes = { - 'boolean': 1, - 'number': 1, - 'string': 1, - 'undefined': 1 - }; - - // Internal: Determines if the given object `property` value is a - // non-primitive. - var isHostType = function (object, property) { - var type = typeof object[property]; - return type == 'object' ? !!object[property] : !PrimitiveTypes[type]; - }; - - // Internal: Normalizes the `for...in` iteration algorithm across - // environments. Each enumerated key is yielded to a `callback` function. - forEach = function (object, callback) { - var size = 0, Properties, members, property; - - // Tests for bugs in the current environment's `for...in` algorithm. The - // `valueOf` property inherits the non-enumerable flag from - // `Object.prototype` in older versions of IE, Netscape, and Mozilla. - (Properties = function () { - this.valueOf = 0; - }).prototype.valueOf = 0; - - // Iterate over a new instance of the `Properties` class. - members = new Properties(); - for (property in members) { - // Ignore all properties inherited from `Object.prototype`. - if (isProperty.call(members, property)) { - size++; - } - } - Properties = members = null; - - // Normalize the iteration algorithm. - if (!size) { - // A list of non-enumerable properties inherited from `Object.prototype`. - members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"]; - // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable - // properties. - forEach = function (object, callback) { - var isFunction = getClass.call(object) == functionClass, property, length; - var hasProperty = !isFunction && typeof object.constructor != 'function' && isHostType(object, 'hasOwnProperty') ? object.hasOwnProperty : isProperty; - for (property in object) { - // Gecko <= 1.0 enumerates the `prototype` property of functions under - // certain conditions; IE does not. - if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) { - callback(property); - } - } - // Manually invoke the callback for each non-enumerable property. - for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property)); - }; - } else if (size == 2) { - // Safari <= 2.0.4 enumerates shadowed properties twice. - forEach = function (object, callback) { - // Create a set of iterated properties. - var members = {}, isFunction = getClass.call(object) == functionClass, property; - for (property in object) { - // Store each property name to prevent double enumeration. The - // `prototype` property of functions is not enumerated due to cross- - // environment inconsistencies. - if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) { - callback(property); - } - } - }; - } else { - // No bugs detected; use the standard `for...in` algorithm. - forEach = function (object, callback) { - var isFunction = getClass.call(object) == functionClass, property, isConstructor; - for (property in object) { - if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) { - callback(property); - } - } - // Manually invoke the callback for the `constructor` property due to - // cross-environment inconsistencies. - if (isConstructor || isProperty.call(object, (property = "constructor"))) { - callback(property); - } - }; - } - return forEach(object, callback); - }; - - // Public: Serializes a JavaScript `value` as a JSON string. The optional - // `filter` argument may specify either a function that alters how object and - // array members are serialized, or an array of strings and numbers that - // indicates which properties should be serialized. The optional `width` - // argument may be either a string or number that specifies the indentation - // level of the output. - if (!has("json-stringify")) { - // Internal: A map of control characters and their escaped equivalents. - var Escapes = { - 92: "\\\\", - 34: '\\"', - 8: "\\b", - 12: "\\f", - 10: "\\n", - 13: "\\r", - 9: "\\t" - }; - - // Internal: Converts `value` into a zero-padded string such that its - // length is at least equal to `width`. The `width` must be <= 6. - var leadingZeroes = "000000"; - var toPaddedString = function (width, value) { - // The `|| 0` expression is necessary to work around a bug in - // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`. - return (leadingZeroes + (value || 0)).slice(-width); - }; - - // Internal: Double-quotes a string `value`, replacing all ASCII control - // characters (characters with code unit values between 0 and 31) with - // their escaped equivalents. This is an implementation of the - // `Quote(value)` operation defined in ES 5.1 section 15.12.3. - var unicodePrefix = "\\u00"; - var quote = function (value) { - var result = '"', index = 0, length = value.length, isLarge = length > 10 && charIndexBuggy, symbols; - if (isLarge) { - symbols = value.split(""); - } - for (; index < length; index++) { - var charCode = value.charCodeAt(index); - // If the character is a control character, append its Unicode or - // shorthand escape sequence; otherwise, append the character as-is. - switch (charCode) { - case 8: case 9: case 10: case 12: case 13: case 34: case 92: - result += Escapes[charCode]; - break; - default: - if (charCode < 32) { - result += unicodePrefix + toPaddedString(2, charCode.toString(16)); - break; - } - result += isLarge ? symbols[index] : charIndexBuggy ? value.charAt(index) : value[index]; - } - } - return result + '"'; - }; - - // Internal: Recursively serializes an object. Implements the - // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations. - var serialize = function (property, object, callback, properties, whitespace, indentation, stack) { - var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result; - try { - // Necessary for host object support. - value = object[property]; - } catch (exception) {} - if (typeof value == "object" && value) { - className = getClass.call(value); - if (className == dateClass && !isProperty.call(value, "toJSON")) { - if (value > -1 / 0 && value < 1 / 0) { - // Dates are serialized according to the `Date#toJSON` method - // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15 - // for the ISO 8601 date time string format. - if (getDay) { - // Manually compute the year, month, date, hours, minutes, - // seconds, and milliseconds if the `getUTC*` methods are - // buggy. Adapted from @Yaffle's `date-shim` project. - date = floor(value / 864e5); - for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++); - for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++); - date = 1 + date - getDay(year, month); - // The `time` value specifies the time within the day (see ES - // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used - // to compute `A modulo B`, as the `%` operator does not - // correspond to the `modulo` operation for negative numbers. - time = (value % 864e5 + 864e5) % 864e5; - // The hours, minutes, seconds, and milliseconds are obtained by - // decomposing the time within the day. See section 15.9.1.10. - hours = floor(time / 36e5) % 24; - minutes = floor(time / 6e4) % 60; - seconds = floor(time / 1e3) % 60; - milliseconds = time % 1e3; - } else { - year = value.getUTCFullYear(); - month = value.getUTCMonth(); - date = value.getUTCDate(); - hours = value.getUTCHours(); - minutes = value.getUTCMinutes(); - seconds = value.getUTCSeconds(); - milliseconds = value.getUTCMilliseconds(); - } - // Serialize extended years correctly. - value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) + - "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) + - // Months, dates, hours, minutes, and seconds should have two - // digits; milliseconds should have three. - "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) + - // Milliseconds are optional in ES 5.0, but required in 5.1. - "." + toPaddedString(3, milliseconds) + "Z"; - } else { - value = null; - } - } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) { - // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the - // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3 - // ignores all `toJSON` methods on these objects unless they are - // defined directly on an instance. - value = value.toJSON(property); - } - } - if (callback) { - // If a replacement function was provided, call it to obtain the value - // for serialization. - value = callback.call(object, property, value); - } - if (value === null) { - return "null"; - } - className = getClass.call(value); - if (className == booleanClass) { - // Booleans are represented literally. - return "" + value; - } else if (className == numberClass) { - // JSON numbers must be finite. `Infinity` and `NaN` are serialized as - // `"null"`. - return value > -1 / 0 && value < 1 / 0 ? "" + value : "null"; - } else if (className == stringClass) { - // Strings are double-quoted and escaped. - return quote("" + value); - } - // Recursively serialize objects and arrays. - if (typeof value == "object") { - // Check for cyclic structures. This is a linear search; performance - // is inversely proportional to the number of unique nested objects. - for (length = stack.length; length--;) { - if (stack[length] === value) { - // Cyclic structures cannot be serialized by `JSON.stringify`. - throw TypeError(); - } - } - // Add the object to the stack of traversed objects. - stack.push(value); - results = []; - // Save the current indentation level and indent one additional level. - prefix = indentation; - indentation += whitespace; - if (className == arrayClass) { - // Recursively serialize array elements. - for (index = 0, length = value.length; index < length; index++) { - element = serialize(index, value, callback, properties, whitespace, indentation, stack); - results.push(element === undef ? "null" : element); - } - result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]"; - } else { - // Recursively serialize object members. Members are selected from - // either a user-specified list of property names, or the object - // itself. - forEach(properties || value, function (property) { - var element = serialize(property, value, callback, properties, whitespace, indentation, stack); - if (element !== undef) { - // According to ES 5.1 section 15.12.3: "If `gap` {whitespace} - // is not the empty string, let `member` {quote(property) + ":"} - // be the concatenation of `member` and the `space` character." - // The "`space` character" refers to the literal space - // character, not the `space` {width} argument provided to - // `JSON.stringify`. - results.push(quote(property) + ":" + (whitespace ? " " : "") + element); - } - }); - result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}"; - } - // Remove the object from the traversed object stack. - stack.pop(); - return result; - } - }; - - // Public: `JSON.stringify`. See ES 5.1 section 15.12.3. - JSON3.stringify = function (source, filter, width) { - var whitespace, callback, properties, className; - if (typeof filter == "function" || typeof filter == "object" && filter) { - if ((className = getClass.call(filter)) == functionClass) { - callback = filter; - } else if (className == arrayClass) { - // Convert the property names array into a makeshift set. - properties = {}; - for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1)); - } - } - if (width) { - if ((className = getClass.call(width)) == numberClass) { - // Convert the `width` to an integer and create a string containing - // `width` number of space characters. - if ((width -= width % 1) > 0) { - for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " "); - } - } else if (className == stringClass) { - whitespace = width.length <= 10 ? width : width.slice(0, 10); - } - } - // Opera <= 7.54u2 discards the values associated with empty string keys - // (`""`) only if they are used directly within an object member list - // (e.g., `!("" in { "": 1})`). - return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []); - }; - } - - // Public: Parses a JSON source string. - if (!has("json-parse")) { - var fromCharCode = String.fromCharCode; - - // Internal: A map of escaped control characters and their unescaped - // equivalents. - var Unescapes = { - 92: "\\", - 34: '"', - 47: "/", - 98: "\b", - 116: "\t", - 110: "\n", - 102: "\f", - 114: "\r" - }; - - // Internal: Stores the parser state. - var Index, Source; - - // Internal: Resets the parser state and throws a `SyntaxError`. - var abort = function() { - Index = Source = null; - throw SyntaxError(); - }; - - // Internal: Returns the next token, or `"$"` if the parser has reached - // the end of the source string. A token may be a string, number, `null` - // literal, or Boolean literal. - var lex = function () { - var source = Source, length = source.length, value, begin, position, isSigned, charCode; - while (Index < length) { - charCode = source.charCodeAt(Index); - switch (charCode) { - case 9: case 10: case 13: case 32: - // Skip whitespace tokens, including tabs, carriage returns, line - // feeds, and space characters. - Index++; - break; - case 123: case 125: case 91: case 93: case 58: case 44: - // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at - // the current position. - value = charIndexBuggy ? source.charAt(Index) : source[Index]; - Index++; - return value; - case 34: - // `"` delimits a JSON string; advance to the next character and - // begin parsing the string. String tokens are prefixed with the - // sentinel `@` character to distinguish them from punctuators and - // end-of-string tokens. - for (value = "@", Index++; Index < length;) { - charCode = source.charCodeAt(Index); - if (charCode < 32) { - // Unescaped ASCII control characters (those with a code unit - // less than the space character) are not permitted. - abort(); - } else if (charCode == 92) { - // A reverse solidus (`\`) marks the beginning of an escaped - // control character (including `"`, `\`, and `/`) or Unicode - // escape sequence. - charCode = source.charCodeAt(++Index); - switch (charCode) { - case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114: - // Revive escaped control characters. - value += Unescapes[charCode]; - Index++; - break; - case 117: - // `\u` marks the beginning of a Unicode escape sequence. - // Advance to the first character and validate the - // four-digit code point. - begin = ++Index; - for (position = Index + 4; Index < position; Index++) { - charCode = source.charCodeAt(Index); - // A valid sequence comprises four hexdigits (case- - // insensitive) that form a single hexadecimal value. - if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) { - // Invalid Unicode escape sequence. - abort(); - } - } - // Revive the escaped character. - value += fromCharCode("0x" + source.slice(begin, Index)); - break; - default: - // Invalid escape sequence. - abort(); - } - } else { - if (charCode == 34) { - // An unescaped double-quote character marks the end of the - // string. - break; - } - charCode = source.charCodeAt(Index); - begin = Index; - // Optimize for the common case where a string is valid. - while (charCode >= 32 && charCode != 92 && charCode != 34) { - charCode = source.charCodeAt(++Index); - } - // Append the string as-is. - value += source.slice(begin, Index); - } - } - if (source.charCodeAt(Index) == 34) { - // Advance to the next character and return the revived string. - Index++; - return value; - } - // Unterminated string. - abort(); - default: - // Parse numbers and literals. - begin = Index; - // Advance past the negative sign, if one is specified. - if (charCode == 45) { - isSigned = true; - charCode = source.charCodeAt(++Index); - } - // Parse an integer or floating-point value. - if (charCode >= 48 && charCode <= 57) { - // Leading zeroes are interpreted as octal literals. - if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) { - // Illegal octal literal. - abort(); - } - isSigned = false; - // Parse the integer component. - for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++); - // Floats cannot contain a leading decimal point; however, this - // case is already accounted for by the parser. - if (source.charCodeAt(Index) == 46) { - position = ++Index; - // Parse the decimal component. - for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); - if (position == Index) { - // Illegal trailing decimal. - abort(); - } - Index = position; - } - // Parse exponents. The `e` denoting the exponent is - // case-insensitive. - charCode = source.charCodeAt(Index); - if (charCode == 101 || charCode == 69) { - charCode = source.charCodeAt(++Index); - // Skip past the sign following the exponent, if one is - // specified. - if (charCode == 43 || charCode == 45) { - Index++; - } - // Parse the exponential component. - for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); - if (position == Index) { - // Illegal empty exponent. - abort(); - } - Index = position; - } - // Coerce the parsed value to a JavaScript number. - return +source.slice(begin, Index); - } - // A negative sign may only precede numbers. - if (isSigned) { - abort(); - } - // `true`, `false`, and `null` literals. - if (source.slice(Index, Index + 4) == "true") { - Index += 4; - return true; - } else if (source.slice(Index, Index + 5) == "false") { - Index += 5; - return false; - } else if (source.slice(Index, Index + 4) == "null") { - Index += 4; - return null; - } - // Unrecognized token. - abort(); - } - } - // Return the sentinel `$` character if the parser has reached the end - // of the source string. - return "$"; - }; - - // Internal: Parses a JSON `value` token. - var get = function (value) { - var results, hasMembers; - if (value == "$") { - // Unexpected end of input. - abort(); - } - if (typeof value == "string") { - if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") { - // Remove the sentinel `@` character. - return value.slice(1); - } - // Parse object and array literals. - if (value == "[") { - // Parses a JSON array, returning a new JavaScript array. - results = []; - for (;; hasMembers || (hasMembers = true)) { - value = lex(); - // A closing square bracket marks the end of the array literal. - if (value == "]") { - break; - } - // If the array literal contains elements, the current token - // should be a comma separating the previous element from the - // next. - if (hasMembers) { - if (value == ",") { - value = lex(); - if (value == "]") { - // Unexpected trailing `,` in array literal. - abort(); - } - } else { - // A `,` must separate each array element. - abort(); - } - } - // Elisions and leading commas are not permitted. - if (value == ",") { - abort(); - } - results.push(get(value)); - } - return results; - } else if (value == "{") { - // Parses a JSON object, returning a new JavaScript object. - results = {}; - for (;; hasMembers || (hasMembers = true)) { - value = lex(); - // A closing curly brace marks the end of the object literal. - if (value == "}") { - break; - } - // If the object literal contains members, the current token - // should be a comma separator. - if (hasMembers) { - if (value == ",") { - value = lex(); - if (value == "}") { - // Unexpected trailing `,` in object literal. - abort(); - } - } else { - // A `,` must separate each object member. - abort(); - } - } - // Leading commas are not permitted, object property names must be - // double-quoted strings, and a `:` must separate each property - // name and value. - if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") { - abort(); - } - results[value.slice(1)] = get(lex()); - } - return results; - } - // Unexpected token encountered. - abort(); - } - return value; - }; - - // Internal: Updates a traversed object member. - var update = function(source, property, callback) { - var element = walk(source, property, callback); - if (element === undef) { - delete source[property]; - } else { - source[property] = element; - } - }; - - // Internal: Recursively traverses a parsed JSON object, invoking the - // `callback` function for each value. This is an implementation of the - // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2. - var walk = function (source, property, callback) { - var value = source[property], length; - if (typeof value == "object" && value) { - // `forEach` can't be used to traverse an array in Opera <= 8.54 - // because its `Object#hasOwnProperty` implementation returns `false` - // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`). - if (getClass.call(value) == arrayClass) { - for (length = value.length; length--;) { - update(value, length, callback); - } - } else { - forEach(value, function (property) { - update(value, property, callback); - }); - } - } - return callback.call(source, property, value); - }; - - // Public: `JSON.parse`. See ES 5.1 section 15.12.2. - JSON3.parse = function (source, callback) { - var result, value; - Index = 0; - Source = "" + source; - result = get(lex()); - // If a JSON string contains multiple tokens, it is invalid. - if (lex() != "$") { - abort(); - } - // Reset the parser state. - Index = Source = null; - return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result; - }; - } - } - - // Export for asynchronous module loaders. - if (isLoader) { - define(function () { - return JSON3; - }); - } - }(this)); - -},{}],50:[function(_dereq_,module,exports){ - module.exports = toArray - - function toArray(list, index) { - var array = [] - - index = index || 0 - - for (var i = index || 0; i < list.length; i++) { - array[i - index] = list[i] - } - - return array - } - -},{}]},{},[1]) -(1) -}); \ No newline at end of file diff --git a/assets/www/dist/dist_js/app/vendor/underscore.js b/assets/www/dist/dist_js/app/vendor/underscore.js deleted file mode 100644 index f01025b7bcaab18e6b698141c854f95669a5975c..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/app/vendor/underscore.js +++ /dev/null @@ -1,6 +0,0 @@ -// Underscore.js 1.8.3 -// http://underscorejs.org -// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. -(function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.hasOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}},j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])<u?i=a+1:o=a}return i},m.indexOf=r(1,m.findIndex,m.sortedIndex),m.lastIndexOf=r(-1,m.findLastIndex),m.range=function(n,t,r){null==t&&(t=n||0,n=0),r=r||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=Array(e),i=0;e>i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e<arguments.length;)i.push(arguments[e++]);return E(n,r,this,this,i)};return r},m.bindAll=function(n){var t,r,e=arguments.length;if(1>=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this); -//# sourceMappingURL=underscore-min.map \ No newline at end of file diff --git a/assets/www/dist/dist_js/plugins/controllers/app-controllers.js b/assets/www/dist/dist_js/plugins/controllers/app-controllers.js index 30d73bd3956bd53cd5200cd3430a3ecd43cda5af..b2c5c2a7cfde6454066ba10e7cf5a076d0caece8 100644 --- a/assets/www/dist/dist_js/plugins/controllers/app-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/app-controllers.js @@ -1,6 +1,6 @@ ESExtensionController.$inject = ['$scope', 'esSettings', 'PluginService']; -ESMenuExtendController.$inject = ['$scope', '$state', 'PluginService', 'esSettings', 'UIUtils', 'csWallet']; +ESMenuExtendController.$inject = ['$scope', '$state', '$controller', 'UIUtils', 'csWallet']; ESProfilePopoverExtendController.$inject = ['$scope', '$q', '$state', 'esSettings', 'csWallet'];angular.module('cesium.es.app.controllers', ['ngResource', 'cesium.es.services']) // Configure menu items @@ -50,26 +50,35 @@ function ESExtensionController($scope, esSettings, PluginService) { $scope.enable = esSettings.isEnable(); esSettings.api.state.on.changed($scope, function(enable) { $scope.enable = enable; + $scope.$broadcast('$$rebind::state'); }); } /** * Control menu extension */ -function ESMenuExtendController($scope, $state, PluginService, esSettings, UIUtils, csWallet) { +function ESMenuExtendController($scope, $state, $controller, UIUtils, csWallet) { 'ngInject'; - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); + + // Initialize the super class and extend it. + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); $scope.showRegistryLookupView = function() { - $state.go(UIUtils.screen.isSmall() ? 'app.registry_lookup': 'app.registry_lookup_lg'); + $state.go(UIUtils.screen.isSmall() ? 'app.wot_lookup.tab_registry': 'app.registry_lookup_lg'); }; $scope.showNotificationsPopover = function(event) { return UIUtils.popover.show(event, { templateUrl :'plugins/es/templates/notification/popover_notification.html', scope: $scope, - autoremove: false // reuse popover + autoremove: false, // reuse popover + // Auto-close if open when un-authenticate + afterShow: function(popover) { + var listener = csWallet.api.data.on.unauth(popover.scope, function() { + popover.scope.closePopover(); + listener(); + }); + } }); }; @@ -85,7 +94,14 @@ function ESMenuExtendController($scope, $state, PluginService, esSettings, UIUti return UIUtils.popover.show(event, { templateUrl :'plugins/es/templates/message/popover_message.html', scope: $scope, - autoremove: false // reuse popover + autoremove: false, // reuse popover + // Auto-close if open when un-authenticate + afterShow: function(popover) { + var listener = csWallet.api.data.on.unauth(popover.scope, function() { + popover.scope.closePopover(); + listener(); + }); + } }); }; @@ -104,18 +120,13 @@ function ESMenuExtendController($scope, $state, PluginService, esSettings, UIUti autoremove: false, // reuse popover // Auto-close if open when un-authenticate afterShow: function(popover) { - csWallet.api.data.on.unauth(popover.scope, function() { + var listener = csWallet.api.data.on.unauth(popover.scope, function() { popover.scope.closePopover(); + listener(); }); } }); }; - - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; - }); - - } /** @@ -130,7 +141,7 @@ function ESProfilePopoverExtendController($scope, $q, $state, esSettings, csWall $scope.showEditUserProfile = function() { $scope.closeProfilePopover(); - $state.go('app.user_edit_profile'); + $state.go('app.edit_profile'); }; esSettings.api.state.on.changed($scope, $scope.updateView); diff --git a/assets/www/dist/dist_js/plugins/controllers/blockchain-controllers.js b/assets/www/dist/dist_js/plugins/controllers/blockchain-controllers.js index e4222471e67ca0eaffa348103c3370e391d7124e..31d8f805f3340c318c9407e7934a5e0582c1be18 100644 --- a/assets/www/dist/dist_js/plugins/controllers/blockchain-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/blockchain-controllers.js @@ -135,7 +135,7 @@ function ESBlockLookupController($scope, $controller, $ionicPopover, $location, promise = esBlockchain.block.searchText($scope.currency, $scope.search.query, request); } - var time = new Date().getTime(); + var now = Date.now(); return promise .then(function(result) { // Apply transformation need by UI (e.g add avatar and name...) @@ -147,7 +147,7 @@ function ESBlockLookupController($scope, $controller, $ionicPopover, $location, .then(function(result) { $scope.showPubkey = ($scope.search.sort == 'issuer'); // Compute time only once (on first page) - $scope.search.took = (from === 0) ? (new Date().getTime() - time) : $scope.search.took; + $scope.search.took = (from === 0) ? (Date.now() - now) : $scope.search.took; // Keep previous total, when already computed (because of current, that is excluded only in the first page) var total = (from === 0) ? result.total : $scope.search.total; $scope.doDisplayResult(result.hits, from, total); @@ -182,26 +182,20 @@ function ESBlockLookupController($scope, $controller, $ionicPopover, $location, /* -- popups -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/blockchain/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/blockchain/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; diff --git a/assets/www/dist/dist_js/plugins/controllers/common-controllers.js b/assets/www/dist/dist_js/plugins/controllers/common-controllers.js index bd7281b8e73add0f9bfb5b4f1e1b48a7f7dd3e96..ec021c5dc357153d93bab70c7cff1d8befc5ba8a 100644 --- a/assets/www/dist/dist_js/plugins/controllers/common-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/common-controllers.js @@ -2,12 +2,12 @@ ESPicturesEditController.$inject = ['$scope', 'UIUtils', '$q', 'Device']; ESSocialsEditController.$inject = ['$scope', '$focus', '$filter', 'UIUtils', 'SocialUtils']; ESSocialsViewController.$inject = ['$scope']; -ESCommentsController.$inject = ['$scope', '$filter', '$state', '$focus', 'UIUtils']; +ESCommentsController.$inject = ['$scope', '$filter', '$state', '$focus', '$timeout', '$anchorScroll', 'UIUtils']; ESCategoryModalController.$inject = ['$scope', 'UIUtils', '$timeout', 'parameters']; ESAvatarModalController.$inject = ['$scope']; ESPositionEditController.$inject = ['$scope', 'csConfig', 'esGeo', 'ModalUtils']; ESLookupPositionController.$inject = ['$scope', '$q', 'csConfig', 'esGeo', 'ModalUtils']; -ESSearchPositionItemController.$inject = ['$scope', '$q', '$timeout', 'ModalUtils', 'csConfig', 'esGeo']; +ESSearchPositionItemController.$inject = ['$scope', '$timeout', 'ModalUtils', 'csConfig', 'esGeo']; ESSearchPositionModalController.$inject = ['$scope', '$q', '$translate', 'esGeo', 'parameters'];angular.module('cesium.es.common.controllers', ['ngResource', 'cesium.es.services']) .controller('ESPicturesEditCtrl', ESPicturesEditController) @@ -61,19 +61,23 @@ function ESPicturesEditController($scope, UIUtils, $q, Device) { }; $scope.fileChanged = function(event) { + if (!event.target.files || !event.target.files.length) return; UIUtils.loading.show(); - return $q(function(resolve, reject) { - var file = event.target.files[0]; - UIUtils.image.resizeFile(file) - .then(function(imageData) { - $scope.pictures.push({ - src: imageData, - isnew: true // use to prevent visibility hidden (if animation) - }); - UIUtils.loading.hide(100); - resolve(); + var file = event.target.files[0]; + return UIUtils.image.resizeFile(file) + .then(function(imageData) { + $scope.pictures.push({ + src: imageData, + isnew: true // use to prevent visibility hidden (if animation) }); - }); + event.target.value = ""; // reset input[type=file] + UIUtils.loading.hide(100); + }) + .catch(function(err) { + console.error(err); + event.target.value = ""; // reset input[type=file] + UIUtils.loading.hide(); + }); }; $scope.removePicture = function(index){ @@ -151,7 +155,7 @@ function ESCategoryModalController($scope, UIUtils, $timeout, parameters) { -function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { +function ESCommentsController($scope, $filter, $state, $focus, $timeout, $anchorScroll, UIUtils) { 'ngInject'; $scope.loading = true; @@ -160,8 +164,12 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { $scope.comments = {}; $scope.$on('$recordView.enter', function(e, state) { + // First enter + if ($scope.loading) { + $scope.anchor = state && state.stateParams.anchor; + } // second call (when using cached view) - if (!$scope.loading && $scope.id) { + else if (!$scope.loading && $scope.id) { $scope.load($scope.id, {animate: false}); } }); @@ -169,15 +177,21 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { $scope.$on('$recordView.load', function(event, id, service) { $scope.id = id || $scope.id; $scope.service = service || $scope.service; - console.debug("[ES] [comment] Initialized service with: " + service.id); + console.debug("[ES] [comment] Will use {" + service.index + "} service"); if ($scope.id) { - $scope.load($scope.id); + $scope.load($scope.id) + .then(function() { + // Scroll to anchor + $scope.scrollToAnchor(); + }); } }); $scope.load = function(id, options) { options = options || {}; options.from = options.from || 0; + // If anchor has been defined, load all comments + options.size = options.size || ($scope.anchor && -1/*all*/); options.size = options.size || $scope.defaultCommentSize; options.animate = angular.isDefined(options.animate) ? options.animate : true; options.loadAvatarAllParent = angular.isDefined(options.loadAvatarAllParent) ? options.loadAvatarAllParent : true; @@ -212,6 +226,25 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { } }); + $scope.scrollToAnchor = function() { + if (!$scope.anchor) return; + var elemList = document.getElementsByName($scope.anchor); + // Waiting for the element + if (!elemList || !elemList.length) { + return $timeout($scope.scrollToAnchor, 500); + } + // If many, remove all anchor except the last one + for (var i = 0; i<elemList.length-1; i++) { + angular.element(elemList[i]).remove(); + } + // Scroll to the anchor + $anchorScroll($scope.anchor); + // Remove the anchor. This will the CSS class 'positive-100-bg' on the comment + $timeout(function () { + $scope.anchor = null; + }, 1500); + }; + $scope.showMore = function(){ var from = 0; var size = -1; @@ -224,6 +257,14 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { }); }; + $scope.onKeypress = function(event) { + // If Ctrl + Enter: submit + if (event && event.charCode == 10 && event.ctrlKey) { + $scope.save(); + event.preventDefault(); + } + }; + $scope.save = function() { if (!$scope.formData.message || !$scope.formData.message.length) return; @@ -357,8 +398,6 @@ function ESSocialsEditController($scope, $focus, $filter, UIUtils, SocialUtils) selector: '#social-' + $filter('formatSlug')(social.url), startVelocity: 10000 }); - - }; $scope.editSocialNetwork = function(index) { @@ -383,9 +422,8 @@ function ESSocialsEditController($scope, $focus, $filter, UIUtils, SocialUtils) function ESSocialsViewController($scope) { 'ngInject'; - $scope.openSocial = function($event, social) { - $event.stopPropagation(); - return $scope.openLink($event, social.url, { + $scope.openSocial = function(event, social) { + return $scope.openLink(event, social.url, { type: social.type }); }; @@ -484,7 +522,6 @@ function ESPositionEditController($scope, csConfig, esGeo, ModalUtils) { .catch(function(err) { console.error(err); // Silent loadingCurrentPosition = false; - //$scope.form.geoPoint.$setValidity('required', false); }); } @@ -509,22 +546,24 @@ function ESPositionEditController($scope, csConfig, esGeo, ModalUtils) { }); }; - $scope.onCityChanged = function() { - if ($scope.loading) return; - if ($scope.form) { - $scope.form.$valid = undefined; - } - if ($scope.formPosition.enable) { - return $scope.tryToLocalize(); - } - }; + $scope.onCityChanged = function() { + if ($scope.loading) return; + if ($scope.formPosition.enable) { + if ($scope.formData.geoPoint) { + // Invalidate the position + $scope.formData.geoPoint.lat = undefined; + $scope.formData.geoPoint.lon = undefined; + } + return $scope.tryToLocalize(); + } + }; $scope.onUseGeopointChanged = function() { if ($scope.loading) return; if (!$scope.formPosition.enable) { if ($scope.formData.geoPoint) { - $scope.formData.geoPoint = null; - //$scope.form.geoPoint.$setValidity('required', true); + $scope.formData.geoPoint.lat = undefined; + $scope.formData.geoPoint.lon = undefined; $scope.dirty = true; } } @@ -698,7 +737,7 @@ function ESLookupPositionController($scope, $q, csConfig, esGeo, ModalUtils) { }; } -function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConfig, esGeo) { +function ESSearchPositionItemController($scope, $timeout, ModalUtils, csConfig, esGeo) { 'ngInject'; // The default country used for address localisation @@ -782,15 +821,20 @@ function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConf $scope.showDropdown = function() { var text = $scope.search.location && $scope.search.location.trim(); if (!text || text.length < minLength) { - $scope.locations = undefined; - return $q.when(); // nothing to search + return $scope.hideDropdown(true/*force, if still loading*/); } + // Compute a request id, to apply response only if current request + var requestId = ($scope.requestId && $scope.requestId + 1) || 1; + $scope.requestId = requestId; + loadingPosition = true; // Execute the given query return esGeo.point.searchByAddress(text) .then(function(res) { + if ($scope.requestId != requestId) return; // Skip apply if not same request: + loadingPosition = false; $scope.locations = res||[]; $scope.license = res && res.length && res[0].license; @@ -802,6 +846,7 @@ function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConf }; $scope.hideDropdown = function(force) { + // force, even if still loading if (force) { $scope.locations = undefined; $scope.selectLocationIndex = -1; diff --git a/assets/www/dist/dist_js/plugins/controllers/document-controllers.js b/assets/www/dist/dist_js/plugins/controllers/document-controllers.js index 88d65797258848976912c3527b70791822a931df..3dc5ed04a5780eac7090f522067d967450bbcf33 100644 --- a/assets/www/dist/dist_js/plugins/controllers/document-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/document-controllers.js @@ -148,7 +148,7 @@ function ESDocumentLookupController($scope, $ionicPopover, $location, $timeout, }); }; - $scope.remove = function(index) { + $scope.remove = function(index, options) { var doc = $scope.search.results[index]; if (!doc) return; @@ -189,26 +189,20 @@ function ESDocumentLookupController($scope, $ionicPopover, $location, $timeout, /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/document/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/document/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; diff --git a/assets/www/dist/dist_js/plugins/controllers/group-controllers.js b/assets/www/dist/dist_js/plugins/controllers/group-controllers.js index 928e10fbca25aa4153de42b68c5c6559812b7473..a6133666111b113666b54810f975805aef422d9c 100644 --- a/assets/www/dist/dist_js/plugins/controllers/group-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/group-controllers.js @@ -188,7 +188,9 @@ function ESGroupViewController($scope, $state, $ionicPopover, $ionicHistory, $tr $scope.formData = {}; $scope.id = null; $scope.pictures = []; + $scope.canEdit = false; $scope.loading = true; + $scope.motion = UIUtils.motion.fadeSlideIn; $scope.$on('$ionicView.enter', function(e, state) { if (state.stateParams && state.stateParams.id) { // Load by id @@ -211,7 +213,7 @@ function ESGroupViewController($scope, $state, $ionicPopover, $ionicHistory, $tr $scope.id = data.id; $scope.formData = data.record; $scope.issuer= data.issuer; - $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer); + $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer) || csWallet.children.hasPubkey($scope.formData.issuer); $scope.pictures = data.record.pictures || []; delete data.record.pictures; // remove, as already stored in $scope.pictures @@ -265,26 +267,20 @@ function ESGroupViewController($scope, $state, $ionicPopover, $ionicHistory, $tr /* -- modals & popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/group/view_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/group/view_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; @@ -379,7 +375,7 @@ function ESGroupEditController($scope, esGroup, UIUtils, $state, $q, Device, .then(function(){ var json = $scope.formData; - json.time = esHttp.date.now(); + json.time = moment().utc().unix(); // Resize pictures json.picturesCount = $scope.pictures.length; @@ -409,7 +405,7 @@ function ESGroupEditController($scope, esGroup, UIUtils, $state, $q, Device, .then(function(json){ // Create if (!$scope.id) { - json.creationTime = esHttp.date.now(); + json.creationTime = moment().utc().unix(); return esGroup.record.add(json); } // Update diff --git a/assets/www/dist/dist_js/plugins/controllers/invitation-controllers.js b/assets/www/dist/dist_js/plugins/controllers/invitation-controllers.js index 611792dab3fc85244a51ff856af2298c220b1c97..dadd75a992756e73e1feebbfc27a2e67226252ae 100644 --- a/assets/www/dist/dist_js/plugins/controllers/invitation-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/invitation-controllers.js @@ -1,7 +1,7 @@ -InvitationsController.$inject = ['$scope', '$q', '$ionicPopover', '$state', '$timeout', 'UIUtils', 'csSettings', 'csWallet', 'esHttp', 'esModals', 'esNotification', 'esInvitation']; -PopoverInvitationController.$inject = ['$scope', '$controller']; -NewInvitationModalController.$inject = ['$scope', '$q', 'Modals', 'UIUtils', 'csWallet', 'esHttp', 'esWallet', 'esInvitation'];angular.module('cesium.es.invitation.controllers', ['cesium.es.services']) +InvitationsController.$inject = ['$scope', '$q', '$ionicPopover', '$state', '$timeout', 'UIUtils', 'csWallet', 'esHttp', 'esModals', 'esNotification', 'esInvitation']; +PopoverInvitationController.$inject = ['$scope', '$controller', 'csWallet']; +NewInvitationModalController.$inject = ['$scope', '$q', 'Modals', 'UIUtils', 'csWallet', 'esHttp', 'esWallet', 'esInvitation', 'parameters'];angular.module('cesium.es.invitation.controllers', ['cesium.es.services']) .config(['$stateProvider', function($stateProvider) { 'ngInject'; @@ -9,7 +9,7 @@ NewInvitationModalController.$inject = ['$scope', '$q', 'Modals', 'UIUtils', 'cs $stateProvider .state('app.view_invitations', { - url: "/invitations", + url: "/invitations?id", views: { 'menuContent': { templateUrl: "plugins/es/templates/invitation/view_invitations.html", @@ -20,6 +20,19 @@ NewInvitationModalController.$inject = ['$scope', '$q', 'Modals', 'UIUtils', 'cs auth: true } }) + + .state('app.view_invitations_by_id', { + url: "/wallets/:id/invitations", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/invitation/view_invitations.html", + controller: 'InvitationsCtrl' + } + }, + data: { + login: true + } + }) ; }]) @@ -30,7 +43,7 @@ NewInvitationModalController.$inject = ['$scope', '$q', 'Modals', 'UIUtils', 'cs .controller('ESNewInvitationModalCtrl', NewInvitationModalController) ; -function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUtils, csSettings, csWallet, +function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUtils, csWallet, esHttp, esModals, esNotification, esInvitation) { 'ngInject'; @@ -49,16 +62,37 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt } }; - $scope.$on('$ionicView.enter', function() { - if ($scope.search.loading) { - if (esHttp.isAlive()) { - $scope.load(); + var wallet; - // Reset unread counter - $scope.resetUnreadCount(); + $scope.setWallet = function(aWallet) { + wallet = aWallet; + }; + + $scope.$on('$ionicView.enter', function(e, state) { + if ($scope.search.loading) { + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); } - $scope.showFab('fab-new-invitation'); + $scope.loadWallet({ + wallet: wallet, + minData: true + }) + .then(function() { + + $scope.addListeners(); + + if (esHttp.isAlive()) { + $scope.load(); + + // Reset unread counter + $scope.resetUnreadCount(); + + $scope.showFab('fab-new-invitation'); + } + }); } }); @@ -67,7 +101,10 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt options.from = options.from || from || 0; options.size = options.size || size || defaultSearchLimit; - return esInvitation.load(options) + // Make sure wallet is init (need by PopoverInvitationCtrl) + wallet = wallet || csWallet; + + return esInvitation.load(options, wallet.data.keypair) .then(function(invitations) { $scope.search.results = invitations; $scope.search.loading = false; @@ -132,19 +169,18 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt }; $scope.resetUnreadCount = function() { - if ($scope.search.loading || !csWallet.data.invitations) { + if ($scope.search.loading || !wallet.data.invitations) { return $timeout($scope.resetUnreadCount, 2000); } - if (!csWallet.data.invitations.unreadCount) return; + if (!wallet.data.invitations.unreadCount) return; console.debug('[ES] [invitation] Resetting unread count'); - csWallet.data.invitations.unreadCount = 0; + wallet.data.invitations.unreadCount = 0; if (!$scope.search.results || !$scope.search.results.length) return; var lastNotification = $scope.search.results[0]; var readTime = lastNotification.time ? lastNotification.time : 0; - if (readTime && (!csSettings.data.plugins.es.invitations || csSettings.data.plugins.es.invitations.readTime != readTime)) { - csSettings.data.plugins.es.invitations = csSettings.data.plugins.es.invitations || {}; - csSettings.data.plugins.es.invitations.readTime = readTime; - csSettings.store(); + if (readTime && (!wallet.data.invitations.readTime || wallet.data.invitations.readTime != readTime)) { + wallet.data.invitations.readTime = readTime; + wallet.storeData(); } }; @@ -161,7 +197,7 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt return $q.all([ UIUtils.loading.show(), - esInvitation.deleteAll(csWallet.data.pubkey) + esInvitation.deleteAll(wallet.data.pubkey) ]) .then(function() { $scope.search.results.splice(0, $scope.search.results.length); // update list @@ -203,39 +239,44 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/invitation/popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/invitation/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; // Listeners - csWallet.api.data.on.logout($scope, $scope.resetData); - esHttp.api.node.on.stop($scope, $scope.resetData); - esHttp.api.node.on.start($scope, $scope.load); - esInvitation.api.data.on.new($scope, $scope.onNewInvitation); - + $scope.addListeners = function() { + if (!wallet) throw "Controller wallet not set !"; + + $scope.listeners = [ + esHttp.api.node.on.stop($scope, $scope.resetData), + esHttp.api.node.on.start($scope, $scope.load), + wallet.api.data.on.logout($scope, $scope.resetData) + ]; + + if (wallet.isDefault()) { + // Subscribe to new invitation + $scope.listeners.push( + esInvitation.api.data.on.new($scope, $scope.onNewInvitation) + ); + } + }; } -function PopoverInvitationController($scope, $controller) { +function PopoverInvitationController($scope, $controller, csWallet) { 'ngInject'; // Initialize the super class and extend it. @@ -244,8 +285,12 @@ function PopoverInvitationController($scope, $controller) { // Disable list effects $scope.motion = null; + // Set the wallet to use + $scope.setWallet(csWallet); + $scope.$on('popover.shown', function() { if ($scope.search.loading) { + $scope.addListeners(); $scope.load(); } }); @@ -266,14 +311,71 @@ function PopoverInvitationController($scope, $controller) { } -function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esHttp, esWallet, esInvitation) { +function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esHttp, esWallet, esInvitation, parameters) { 'ngInject'; + // Controller var + var wallet; + + // Scope var $scope.recipients = []; $scope.suggestions = []; $scope.formData = { - useComment: false + useComment: false, + walletId: null }; + $scope.enableSelectWallet = true; + + /* -- scope functions -- */ + + $scope.setParameters = function(parameters) { + if (!parameters) return; + if (!parameters.wallet || parameters.wallet === "default") { + $scope.formData.walletId = csWallet.id; + } + else { + $scope.formData.walletId = parameters.wallet; + } + }; + // Read default parameters + $scope.setParameters(parameters); + + $scope.load = function() { + $scope.enableSelectWallet = csWallet.children.count() > 0; + + wallet = $scope.enableSelectWallet && ($scope.formData.walletId ? csWallet.children.get($scope.formData.walletId) : csWallet) || csWallet; + $scope.formData.walletId = wallet.id; // update the walletId (could have changed) + if (!wallet.isDefault()) { + console.debug("[transfer] Using {" + wallet.id + "} wallet"); + } + + // Make to sure to load full wallet data (balance) + return wallet.login({sources: true, silent: true}) + .then(function(data) { + $scope.walletData = data; + UIUtils.ink({selector: '.modal-invitation .ink'}); + + if (!$scope.destPub || $scope.destUid) { + $scope.loading = false; + } + else { + // Fill the uid from the pubkey + return csWot.extend({pubkey: $scope.destPub}) + .then(function(res) { + $scope.destUid = res && (res.name || res.uid); + if ($scope.destUid) { + $scope.destPub = ''; + } + $scope.loading = false; + }); + } + }) + .catch(function(err){ + if (err == 'CANCELLED') return $scope.cancel(); // close the modal + UIUtils.onError('ERROR.LOGIN_FAILED')(err); + }); + }; + $scope.$on('modal.shown', $scope.load); // When changing use comment $scope.onUseCommentChanged = function() { @@ -304,21 +406,24 @@ function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esH return; } - if (!csWallet.isLogin()) return $scope.closeModal(); // should never happen + if (!wallet.isLogin()) return $scope.closeModal(); // should never happen - return $q.all([ - // Get keypair only once (if not done here, certification.send() with compute it many times) - esWallet.box.getKeypair(csWallet.data.keypair), - // Ask confirmation - UIUtils.alert.confirm('INVITATION.CONFIRM.SEND_INVITATIONS_TO_CERTIFY', undefined, {okText: 'COMMON.BTN_SEND'}) - ]) + // Make sure user is still authenticated + return wallet.auth({silent: true}) + .then(function() { + return $q.all([ + // Get keypair only once (if not done here, esInvitation.send() with compute it many times) + esWallet.box.getKeypair(wallet.data.keypair), + // Ask confirmation + UIUtils.alert.confirm('INVITATION.CONFIRM.SEND_INVITATIONS_TO_CERTIFY', undefined, {okText: 'COMMON.BTN_SEND'}) + ]); + }) .then(function(res) { - if (!res) return; - var keypair = res[0]; - var confirm = res[1]; - if (!confirm) return; + var keypair = res && res[0]; + var confirm = res && res[1]; + if (!keypair || !confirm) return; UIUtils.loading.show(); - var time = esHttp.date.now(); // use same date for each invitation + var time = moment().utc().unix(); // use same date for each invitation var comment = $scope.formData.useComment && $scope.formData.comment && $scope.formData.comment.trim(); return $q.all( $scope.recipients.reduce(function (res, recipient) { @@ -328,14 +433,17 @@ function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esH return res; } var invitation = { - issuer: csWallet.data.pubkey, + issuer: wallet.data.pubkey, recipient: recipient.pubkey, time: time, content: [identity.uid, identity.pubkey].join('-'), comment: comment }; return res.concat( - esInvitation.send(invitation, keypair, 'certification')); + esInvitation.send(invitation, { + wallet: wallet, + type: 'certification' + })); }, [])); }, [])) .then(function() { @@ -387,5 +495,20 @@ function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esH $scope.suggestions = res; }); }; + + + $scope.showSelectWalletModal = function() { + if (!$scope.enableSelectWallet) return; + + return Modals.showSelectWallet() + .then(function(wallet) { + if (!wallet || $scope.formData.walletId === wallet.id) return; + console.debug("[transfer] Using {" + wallet.id + "} wallet"); + $scope.wallet = wallet; + $scope.walletData = wallet.data; + $scope.formData.walletId = wallet.id; + $scope.onAmountChanged(); + }); + }; } diff --git a/assets/www/dist/dist_js/plugins/controllers/message-controllers.js b/assets/www/dist/dist_js/plugins/controllers/message-controllers.js index af3292ce0375e35e26b38d1e7f6e30fc8aaae34c..558739d7d579139ca5878132020f9b8f8bfe259f 100644 --- a/assets/www/dist/dist_js/plugins/controllers/message-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/message-controllers.js @@ -1,11 +1,11 @@ -ESMessageAbstractListController.$inject = ['$scope', '$state', '$translate', '$ionicHistory', '$ionicPopover', '$timeout', '$filter', 'csWallet', 'esModals', 'UIUtils', 'esMessage']; +ESMessageAbstractListController.$inject = ['$scope', '$state', '$translate', '$ionicHistory', '$ionicPopover', '$timeout', 'csWallet', 'esModals', 'UIUtils', 'esMessage']; ESMessageInboxListController.$inject = ['$scope', '$controller']; ESMessageOutboxListController.$inject = ['$scope', '$controller']; -ESMessageComposeController.$inject = ['$scope', '$controller', 'UIUtils']; +ESMessageComposeController.$inject = ['$scope', '$controller']; ESMessageComposeModalController.$inject = ['$scope', 'Modals', 'UIUtils', 'csWallet', 'esHttp', 'esMessage', 'parameters']; -ESMessageViewController.$inject = ['$scope', '$state', '$timeout', '$translate', '$ionicHistory', '$ionicPopover', 'UIUtils', 'esModals', 'esMessage']; -PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', 'esHttp', 'esMessage', 'esModals'];angular.module('cesium.es.message.controllers', ['cesium.es.services']) +ESMessageViewController.$inject = ['$scope', '$state', '$timeout', '$translate', '$ionicHistory', '$ionicPopover', 'UIUtils', 'esModals', 'esMessage', 'csWallet']; +PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', 'esHttp', 'esMessage', 'esModals', '$timeout'];angular.module('cesium.es.message.controllers', ['cesium.es.services']) .config(['$stateProvider', function($stateProvider) { 'ngInject'; @@ -65,6 +65,51 @@ PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', ' } }) + .state('app.user_messages_by_id', { + url: "/wallets/:id/message", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/lookup_by_id.html" + } + } + }) + + .state('app.user_messages_by_id.tab_inbox', { + url: "/inbox", + views: { + 'tab_inbox': { + controller: 'ESMessageInboxListCtrl', + templateUrl: "plugins/es/templates/message/tabs/tab_list.html" + } + }, + data: { + large: 'app.user_messages_lg_inbox_by_id' + } + }) + + .state('app.user_messages_by_id.tab_outbox', { + url: "/outbox", + views: { + 'tab_outbox': { + controller: 'ESMessageOutboxListCtrl', + templateUrl: "plugins/es/templates/message/tabs/tab_list.html" + } + }, + data: { + large: 'app.user_messages_lg_outbox_by_id' + } + }) + + .state('app.user_messages_lg_inbox_by_id', { + url: "/wallets/:id/message/lg/inbox", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/lookup_lg.html", + controller: 'ESMessageInboxListCtrl' + } + } + }) + .state('app.user_messages_lg_outbox', { url: "/user/message/lg/outbox", views: { @@ -79,9 +124,19 @@ PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', ' } }) + .state('app.user_messages_lg_outbox_by_id', { + url: "/wallets/:id/message/lg/outbox", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/lookup_lg.html", + controller: 'ESMessageOutboxListCtrl' + } + } + }) + .state('app.user_new_message', { cache: false, - url: "/user/message/new?pubkey&uid&title&content", + url: "/user/message/new?pubkey&uid&title&content&isReply", views: { 'menuContent': { templateUrl: "plugins/es/templates/message/compose.html", @@ -92,7 +147,7 @@ PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', ' .state('app.user_view_message', { cache: false, - url: "/user/message/view/:type/:id", + url: "/user/message/view/:type/:messageId", views: { 'menuContent': { templateUrl: "plugins/es/templates/message/view_message.html", @@ -105,6 +160,17 @@ PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', ' } }) + .state('app.user_view_message_by_id', { + cache: false, + url: "/wallets/:id/message/view/:type/:messageId", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/view_message.html", + controller: 'ESMessageViewCtrl' + } + } + }) + ; }]) @@ -124,11 +190,13 @@ PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', ' ; -function ESMessageAbstractListController($scope, $state, $translate, $ionicHistory, $ionicPopover, $timeout, $filter, +function ESMessageAbstractListController($scope, $state, $translate, $ionicHistory, $ionicPopover, $timeout, csWallet, esModals, UIUtils, esMessage) { 'ngInject'; var defaultSearchLimit = 40; + var wallet; + var selectPrevented = false; $scope.search = { loading: true, @@ -144,33 +212,45 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto $scope.fabButtonNewMessageId = undefined; - $scope.$on('$ionicView.enter', function(e, state) { + $scope.enter = function(s, state) { + // First enter + if ($scope.search.loading) { + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } - $scope.loadWallet({minData: true}) - .then(function() { - if (!$scope.entered) { - $scope.entered = true; - $scope.type = $scope.type || state.stateParams && state.stateParams.type || 'inbox'; - $scope.load(); - } + $scope.isDefaultWallet = wallet.isDefault(); + $scope.walletId = wallet.id; - if ($scope.fabButtonNewMessageId) { - $scope.showFab($scope.fabButtonNewMessageId); - } - }) - .catch(function(err) { - if ('CANCELLED' === err) { - $ionicHistory.nextViewOptions({ - historyRoot: true - }); - $state.go('app.home'); - } - }); - }); + wallet.auth({minData: true}) + .then(function() { + if (!$scope.entered) { + $scope.entered = true; + $scope.type = $scope.type || state.stateParams && state.stateParams.type || 'inbox'; + $scope.load(); + } - $scope.refresh = function(silent) { - return $scope.load(undefined, undefined, silent); + if ($scope.fabButtonNewMessageId) { + $scope.showFab($scope.fabButtonNewMessageId); + } + }) + .catch(function(err) { + if ('CANCELLED' === err) { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + $scope.showHome(); + } + }); + } + // Not first entering: refresh the view + else { + $scope.updateView(); + } }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function(from, size, silent) { @@ -181,6 +261,7 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto options.summary = false; options.filter = ($scope.search.type == 'text' && $scope.search.text && $scope.search.text.trim().length > 0) ? $scope.search.text : undefined; + options.wallet = wallet; $scope.search.loading = !silent; return esMessage.load(options) @@ -208,15 +289,11 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto }); }; - $scope.setType = function(type) { - $scope.type = type; - $scope.load(); - }; - $scope.updateView = function() { if ($scope.motion && $scope.motion.ionListClass && $scope.search.results.length) { $scope.motion.show({selector: '.view-messages .list .item'}); } + $scope.$broadcast('$$rebind::rebind'); // notifier binder }; $scope.showMore = function() { @@ -261,9 +338,10 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE') .then(function(confirm) { if (confirm) { - esMessage.remove(message.id, $scope.type) + esMessage.remove(message.id, $scope.type, {walletId: $scope.walletId}) .then(function () { $scope.search.results.splice(index,1); // remove from messages array + $scope.updateView(); UIUtils.toast.show('MESSAGE.INFO.MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_MESSAGE_FAILED')); @@ -278,9 +356,10 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE_ALL') .then(function(confirm) { if (confirm) { - esMessage.removeAll($scope.type) + esMessage.removeAll($scope.type, {walletId: $scope.walletId}) .then(function () { $scope.search.results.splice(0,$scope.search.results.length); // reset array + $scope.updateView(); UIUtils.toast.show('MESSAGE.INFO.All_MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_All_MESSAGES_FAILED')); @@ -308,12 +387,45 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto return $scope.load(); }; + + $scope.refresh = function(silent) { + selectPrevented = true; // Will disable select() to open the message + return $scope.load(undefined, undefined, silent) + .then(function() { + selectPrevented = false; + }) + .catch(function() { + selectPrevented = false; + }); + }; + + $scope.select = function(message, event) { + if (event.isDefaultPrevented() || $scope.search.loading || selectPrevented) return; // skip + + // Add a timeout, to be sure the refres action was not called before + return $timeout(function() { + if (selectPrevented || event.isDefaultPrevented()) return; // skip + event.preventDefault(); + + if ($scope.walletId === 'default') { + return $state.go('app.user_view_message', {type: $scope.type, messageId:message.id}); + } + else { + return $state.go('app.user_view_message_by_id', {type: $scope.type, messageId:message.id, id: $scope.walletId}); + } + }, 200); + }; + /* -- Modals -- */ $scope.showNewMessageModal = function(parameters) { - return $scope.loadWallet({minData: true}) + return wallet.login({minData: true}) .then(function() { UIUtils.loading.hide(); + + parameters = parameters || {}; + parameters.wallet = $scope.walletId; + return esModals.showMessageCompose(parameters) .then(function(id) { if (id) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT'); @@ -335,7 +447,8 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto destUid: message.name||message.uid, title: prefix + message.title, content: content, - isReply: true + isReply: true, + wallet: $scope.walletId }); }) .then(function(sent) { @@ -346,26 +459,20 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/message/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/message/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; @@ -379,22 +486,23 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto if (index) { $scope.search.results.splice(index,1); // remove from messages array } + $scope.updateView(); }; esMessage.api.data.on.delete($scope, $scope.onMessageDelete); // Watch user sent message $scope.onNewOutboxMessage = function(id) { - if ($scope.type != 'outbox') return; + if ($scope.type !== 'outbox') return; // Add message sent to list - $scope.loading = true; + $scope.search.loading = true; return $timeout(function() { // Load the message sent - return esMessage.get(id, {type: $scope.type, summary: true}); + return esMessage.get(id, $scope.type, {summary: true, wallet: wallet}); }, 500 /*waiting ES propagation*/) .then(function(msg) { $scope.search.results.splice(0,0,msg); - $scope.loading = false; - $scope.motion.show({selector: '.view-messages .list .item'}); + $scope.search.loading = false; + $scope.updateView(); }) .catch(function() { $scope.loading = false; @@ -404,15 +512,15 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto // Watch received message $scope.onNewInboxMessage = function(notification) { - if ($scope.type != 'inbox' || !$scope.entered) return; + if ($scope.type !== 'inbox' || !$scope.entered || !wallet.isUserPubkey(notification.issuer)) return; // Add message sent to list - $scope.loading = true; + $scope.search.loading = true; // Load the the message - return esMessage.get(notification.id, {type: $scope.type, summary: true}) + return esMessage.get(notification.id, $scope.type, {summary: true, wallet: wallet}) .then(function(msg) { $scope.search.results.splice(0,0,msg); $scope.search.loading = false; - $scope.motion.show({selector: '.view-messages .list .item'}); + $scope.updateView(); }) .catch(function() { $scope.search.loading = false; @@ -458,47 +566,28 @@ function ESMessageOutboxListController($scope, $controller) { $scope.fabButtonNewMessageId = 'fab-add-message-record-outbox'; } -function ESMessageComposeController($scope, $controller, UIUtils) { +function ESMessageComposeController($scope, $controller) { 'ngInject'; // Initialize the super class and extend it. angular.extend(this, $controller('ESMessageComposeModalCtrl', {$scope: $scope, parameters: {}})); - $scope.$on('$ionicView.enter', function(e, state) { - if (state.stateParams) { - if (state.stateParams.pubkey) { - $scope.formData.destPub = state.stateParams.pubkey; - if (state.stateParams.uid) { - $scope.destUid = state.stateParams.uid; - $scope.destPub = ''; - } - else { - $scope.destUid = ''; - $scope.destPub = $scope.formData.destPub; - } - } - if (state.stateParams.title) { - $scope.formData.title = state.stateParams.title; - } + $scope.enter = function(e, state) { - if (state.stateParams.content) { - $scope.formData.content = state.stateParams.content; - } + // Apply state parameters + if (state && state.stateParams) { + $scope.setParameters(state.stateParams); } - $scope.loadWallet({minData: true}) - .then(function() { - UIUtils.loading.hide(); - }) - .catch(function(err){ - if (err === 'CANCELLED') { - $scope.showHome(); - } - }); - }); + // Load wallet + return $scope.load() + .then(UIUtils.loading.hide); + }; + $scope.$on('$ionicView.enter',$scope.enter); $scope.cancel = function() { + $scope.sending = false; $scope.showHome(); }; @@ -507,6 +596,7 @@ function ESMessageComposeController($scope, $controller, UIUtils) { }; $scope.closeModal = function() { + $scope.sending = false; $scope.showHome(); }; @@ -515,18 +605,79 @@ function ESMessageComposeController($scope, $controller, UIUtils) { function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHttp, esMessage, parameters) { 'ngInject'; + var wallet; + $scope.formData = { - title: parameters ? parameters.title : null, - content: parameters ? parameters.content : null, - destPub: parameters ? parameters.destPub : null + title: null, + content: null, + destPub: null, + walletId: null + }; + $scope.destUid = null; + $scope.destPub = null; + $scope.isReply = false; + $scope.enableSelectWallet = true; + $scope.sending = false; + + $scope.setParameters = function(parameters) { + if (!parameters) return; + + if (parameters.pubkey || parameters.destPub) { + $scope.formData.destPub = parameters.pubkey || parameters.destPub; + if (parameters.uid || parameters.destUid) { + $scope.destUid = parameters.uid || parameters.destUid; + $scope.destPub = ''; + } + else { + $scope.destUid = ''; + $scope.destPub = $scope.formData.destPub; + } + } + + if (parameters.title) { + $scope.formData.title = parameters.title; + } + + if (parameters.content) { + $scope.formData.content = parameters.content; + } + + $scope.isReply = parameters.isReply || false; + + if (parameters.wallet) { + $scope.formData.walletId = parameters.wallet; + } + }; + + // Read default parameters + $scope.setParameters(parameters); + + $scope.load = function() { + $scope.enableSelectWallet = csWallet.children.count() > 0; + + wallet = $scope.enableSelectWallet && ($scope.formData.walletId ? csWallet.children.get($scope.formData.walletId) : csWallet) || csWallet; + if (!wallet.isDefault()) { + console.debug("[message] Using {" + wallet.id + "} wallet"); + } + else { + console.debug("[message] Using default wallet"); + } + + return wallet.login({minData: true, silent: true}) + .then(function(data) { + $scope.walletData = data; + }) + .catch(function(err){ + if (err === 'CANCELLED') { + $scope.cancel(); + } + }); }; - $scope.destUid = parameters ? parameters.destUid : null; - $scope.destPub = (parameters && !parameters.destUid) ? parameters.destPub : null; - $scope.isResponse = parameters ? parameters.isResponse : false; + $scope.$on('modal.shown', $scope.load); $scope.doSend = function(forceNoContent) { $scope.form.$submitted=true; - if(!$scope.form.$valid /*|| !$scope.formData.destPub*/) { + if(!$scope.form.$valid) { return; } @@ -540,22 +691,36 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt }); } + $scope.sending = true; UIUtils.loading.show(); var data = { - issuer: csWallet.data.pubkey, + issuer: wallet.data.pubkey, recipient: $scope.formData.destPub, title: $scope.formData.title, content: $scope.formData.content, - time: esHttp.date.now() + time: moment().utc().unix() }; - esMessage.send(data) + esMessage.send(data, {wallet: wallet}) .then(function(id) { $scope.id=id; UIUtils.loading.hide(); $scope.closeModal(id); }) - .catch(UIUtils.onError('MESSAGE.ERROR.SEND_MSG_FAILED')); + .catch(function(err) { + $scope.sending = false; + // silent, if user cancelled; + if (err === 'CANCELLED') { + UIUtils.loading.hide(); + return; + } + UIUtils.onError('MESSAGE.ERROR.SEND_MSG_FAILED')(err); + }); + }; + + + $scope.cancel = function() { + $scope.closeModal(); }; /* -- Modals -- */ @@ -572,6 +737,7 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt $scope.destUid = ''; $scope.destPub = result.pubkey; } + $scope.destName = result.name || result.uid; $scope.formData.destPub = result.pubkey; // TODO focus on title field //$focus(''); @@ -579,11 +745,23 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt }); }; - $scope.cancel = function() { - $scope.closeModal(); + $scope.showSelectWalletModal = function() { + if (!$scope.enableSelectWallet) return; + + return Modals.showSelectWallet({ + showDefault: true, + showBalance: false + }) + .then(function(newWallet) { + if (!newWallet || (wallet && wallet.id === newWallet.id)) return; + wallet = newWallet; + $scope.walletData = wallet.data; + console.debug("[message] Using {" + wallet.id + "} wallet"); + }); }; + // TODO : for DEV only /*$timeout(function() { $scope.formData.destPub = 'G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU'; @@ -600,76 +778,96 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHistory, $ionicPopover, - UIUtils, esModals, esMessage) { + UIUtils, esModals, esMessage, csWallet) { 'ngInject'; $scope.formData = {}; $scope.id = null; $scope.loading = true; + var wallet; + $scope.$on('$ionicView.beforeEnter', function (event, viewData) { // Enable back button (workaround need for navigation outside tabs - https://stackoverflow.com/a/35064602) viewData.enableBack = UIUtils.screen.isSmall() ? true : viewData.enableBack; }); - $scope.$on('$ionicView.enter', function (e, state) { - if (state.stateParams && state.stateParams.id) { // Load by id - if ($scope.loading) { // prevent reload if same id - $scope.type = state.stateParams.type || 'inbox'; - - $scope.load(state.stateParams.id, $scope.type) - .then(function(message) { - $scope.loading = false; - UIUtils.loading.hide(); - if (!message) return; - - $scope.id = message.id; - $scope.formData = message; - $scope.canDelete = true; - $scope.motion.show({selector: '.view-message .list .item'}); - // Mark as read - if (!message.read) { - $timeout(function() { - // Message has NOT changed - if ($scope.id === message.id) { - esMessage.markAsRead(message, $scope.type) - .then(function() { - console.debug("[message] marked as read"); - }) - .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED')); - } - }, 2000); // 2s - } - }); + $scope.enter = function(e, state) { + // First enter + if ($scope.loading) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); } - $scope.showFab('fab-view-message-reply'); - } - else { - $state.go('app.user_message'); + $scope.isDefaultWallet = wallet.isDefault(); + $scope.walletId = wallet.id; + + var messageId = state.stateParams && state.stateParams.messageId; + $scope.type = state.stateParams.type || 'inbox'; + + // No message id: redirect + if (angular.isUndefined(messageId)) { + $scope.goBack(); + return; + } + + wallet.auth({minData: true}) + .then(function () { + return $scope.load(messageId, $scope.type); + }) + .then(function(message) { + + UIUtils.loading.hide(); + if (!message) return; // SKip + + $scope.updateView(message); + $scope.showFab('fab-view-message-reply'); + + // Mark as read + if (!message.read) { + $timeout(function() { + // Message has NOT changed + if ($scope.id === message.id) { + esMessage.markAsRead(message, {type: $scope.type, wallet: wallet}) + .then(function() { + console.debug("[message] marked as read"); + }) + .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED')); + } + }, 2000); // 2s + } + }); } - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function(id, type) { type = type || 'inbox'; - - return $scope.loadWallet({minData: true}) - .then(function() { - return esMessage.get(id, {type: type}); - }) + return esMessage.get(id, type, {wallet: wallet}) .catch(UIUtils.onError('MESSAGE.ERROR.LOAD_MESSAGE_FAILED')) .then(function(message) { if (!message.valid) { return UIUtils.alert.error(!$scope.isUserPubkey(message.recipient) ? 'MESSAGE.ERROR.USER_NOT_RECIPIENT' : 'MESSAGE.ERROR.NOT_AUTHENTICATED_MESSAGE', 'MESSAGE.ERROR.MESSAGE_NOT_READABLE') .then(function () { - $state.go('app.user_message', {type: type}); + $scope.goBack(true/*clear cache*/); }); } return message; }); }; + $scope.updateView = function(message) { + $scope.loading = false; + $scope.id = message.id; + $scope.formData = message; + $scope.canDelete = true; + $scope.motion.show({selector: '.view-message .list .item'}); + }; + $scope.delete = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); @@ -678,14 +876,9 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE') .then(function(confirm) { if (confirm) { - return esMessage.remove($scope.id, $scope.type) + return esMessage.remove($scope.id, $scope.type, {wallet: wallet}) .then(function () { - $ionicHistory.nextViewOptions({ - historyRoot: true - }); - $state.go($scope.type == 'inbox' ? 'app.user_message.tab_inbox' : 'app.user_message.tab_outbox', - {type: $scope.type} - ); + $scope.goBack(true/*clear page cache*/); UIUtils.toast.show('MESSAGE.INFO.MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_MESSAGE_FAILED')); @@ -693,36 +886,47 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis }); }; + $scope.goBack = function(clearPageCache) { + if (clearPageCache) { + $ionicHistory.clearCache($ionicHistory.currentView().stateId); // clear current view + } + $ionicHistory.nextViewOptions({historyRoot: true}); + if ($scope.isDefaultWallet) { + if ($scope.type) { + $state.go('app.user_message.tab_' + $scope.type, {type: $scope.type}); + } + } + else { + if ($scope.type) { + $state.go('app.user_messages_by_id.tab_' + $scope.type, {type: $scope.type, id: $scope.walletId}); + } + } + }; + /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/message/view_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/message/view_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; /* -- Modals -- */ $scope.showReplyModal = function() { - var recipientField = ($scope.type == 'inbox') ? 'issuer' : 'recipient'; + var recipientField = ($scope.type === 'inbox') ? 'issuer' : 'recipient'; $translate('MESSAGE.REPLY_TITLE_PREFIX') .then(function (prefix) { var content = $scope.formData.content ? $scope.formData.content.replace(/^/g, ' > ') : null; @@ -733,7 +937,8 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis destUid: $scope.formData.name||$scope.formData.uid, title: prefix + $scope.formData.title, content: content, - isReply: true + isReply: true, + walletId: wallet.id }); }) .then(function(sent) { @@ -748,10 +953,11 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis }; } -function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esMessage, esModals) { +function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esMessage, esModals, $timeout) { 'ngInject'; var defaultSearchLimit = 40; + var wallet; $scope.search = { loading : true, @@ -763,6 +969,15 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM $scope.$on('popover.shown', function() { if ($scope.search.loading) { + // TODO manage secondary wallets + wallet = $scope.walletId && csWallet.children.get($scope.walletId) || csWallet; + + /* -- wallet listeners -- */ + if (wallet.isDefault()) { + wallet.api.data.on.logout($scope, $scope.resetData); + esMessage.api.data.on.new($scope, $scope.onNewMessageNotification); + } + $scope.load(); } }); @@ -818,13 +1033,22 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM // Listen notifications changes $scope.onNewMessageNotification = function(notification) { if ($scope.search.loading || $scope.search.loadingMore) return; + + if (!wallet.isUserPubkey(notification.issuer)) return; // skip + + // Prepend to list $scope.search.results.splice(0,0,notification); $scope.updateView(); }; $scope.select = function(notification) { if (!notification.read) notification.read = true; - $state.go('app.user_view_message', {id: notification.id}); + if ($scope.walletId === 'default') { + $state.go('app.user_view_message', {messageId: notification.id}); + } + else { + $state.go('app.user_view_message_by_id', {messageId: notification.id, id: $scope.walletId}); + } $scope.closePopover(notification); }; @@ -841,18 +1065,23 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM /* -- Modals -- */ $scope.showNewMessageModal = function(parameters) { + $scope.closePopover(); - return esModals.showMessageCompose(parameters) - .then(function(id) { - if (id) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT'); - }); + + $timeout(function() { + parameters = parameters || {}; + parameters.walletId = wallet.id; + + esModals.showMessageCompose(parameters) + .then(function(id) { + if (id) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT'); + }); + }, 500); // Timeout need, to avoid freeze }; /* -- listeners -- */ - csWallet.api.data.on.logout($scope, $scope.resetData); esHttp.api.node.on.stop($scope, $scope.resetData); esHttp.api.node.on.start($scope, $scope.load); - esMessage.api.data.on.new($scope, $scope.onNewMessageNotification); } diff --git a/assets/www/dist/dist_js/plugins/controllers/network-controllers.js b/assets/www/dist/dist_js/plugins/controllers/network-controllers.js index b4a21096bd701064ab948c53e6ef918bcc6eda07..6c63082ec1fbd5b17f2ed515f588fec27212911e 100644 --- a/assets/www/dist/dist_js/plugins/controllers/network-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/network-controllers.js @@ -1,5 +1,4 @@ -ESNetworkViewExtendController.$inject = ['$scope', 'PluginService', 'esSettings']; angular.module('cesium.es.network.controllers', ['cesium.es.services']) .config(['PluginServiceProvider', 'csConfig', function(PluginServiceProvider, csConfig) { @@ -11,25 +10,11 @@ angular.module('cesium.es.network.controllers', ['cesium.es.services']) points: { 'buttons': { templateUrl: "plugins/es/templates/network/view_network_extend.html", - controller: 'ESNetworkViewExtendCtrl' + controller: 'ESExtensionCtrl' } } }) ; } - }]) + }]); - .controller('ESNetworkViewExtendCtrl', ESNetworkViewExtendController) -; - - -function ESNetworkViewExtendController($scope, PluginService, esSettings) { - 'ngInject'; - - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); - - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; - }); -} diff --git a/assets/www/dist/dist_js/plugins/controllers/notification-controllers.js b/assets/www/dist/dist_js/plugins/controllers/notification-controllers.js index 3db09cdfc070609b19b2c7ecda525d38d2a4f0b1..296310db9d77bf10bbb3265472c7346d1c0a866d 100644 --- a/assets/www/dist/dist_js/plugins/controllers/notification-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/notification-controllers.js @@ -1,6 +1,6 @@ -NotificationsController.$inject = ['$scope', '$rootScope', '$ionicPopover', '$state', '$timeout', 'UIUtils', 'esHttp', 'csSettings', 'csWallet', 'esNotification']; -PopoverNotificationsController.$inject = ['$scope', '$timeout', '$controller', 'UIUtils', '$state']; +NotificationsController.$inject = ['$scope', '$ionicPopover', '$state', '$timeout', 'UIUtils', 'esHttp', 'csWallet', 'esNotification']; +PopoverNotificationsController.$inject = ['$scope', '$timeout', '$controller', '$state', 'UIUtils', 'csWallet']; angular.module('cesium.es.notification.controllers', ['cesium.es.services']) @@ -21,6 +21,18 @@ angular.module('cesium.es.notification.controllers', ['cesium.es.services']) login: true } }) + .state('app.view_notifications_by_id', { + url: "/wallets/:id/notifications", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/notification/view_notifications.html", + controller: 'NotificationsCtrl' + } + }, + data: { + login: true + } + }) ; }]) @@ -30,11 +42,12 @@ angular.module('cesium.es.notification.controllers', ['cesium.es.services']) ; -function NotificationsController($scope, $rootScope, $ionicPopover, $state, $timeout, UIUtils, esHttp, csSettings, csWallet, esNotification) { +function NotificationsController($scope, $ionicPopover, $state, $timeout, UIUtils, esHttp, csWallet, esNotification) { 'ngInject'; var defaultSearchLimit = 40; + $scope.preventSelect = false; $scope.search = { loading : true, results: null, @@ -47,14 +60,32 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim } } }; + $scope.listeners = []; - $scope.$on('$ionicView.enter', function() { + var wallet; + + $scope.setWallet = function(aWallet) { + wallet = aWallet; + }; + + $scope.$on('$ionicView.enter', function(e, state) { if ($scope.search.loading) { - $scope.loadWallet({minData: true}) + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + wallet.login({ + minData: true + }) .then(function() { $scope.load(); UIUtils.loading.hide(); + $scope.addListeners(); + // Reset unread counter return $timeout(function() { $scope.resetUnreadCount(); @@ -68,16 +99,22 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim }; $scope.load = function(from, size, silent) { - if (!csWallet.data.pubkey) { + // Make sure wallet is init (need by PopoverInvitationCtrl) + wallet = wallet || csWallet; + + if (!wallet.data.pubkey) { $scope.search.loading = true; return; } + $scope.search.preventSelect = true; + var options = angular.copy($scope.search.options); options.from = options.from || from || 0; options.size = options.size || size || defaultSearchLimit; + options.pubkey = wallet.data.pubkey; $scope.search.loading = !silent; - return esNotification.load(csWallet.data.pubkey, options) + return esNotification.load(options) .then(function(res) { if (!options.from) { $scope.search.results = res || []; @@ -86,6 +123,7 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim $scope.search.results = $scope.search.results.concat(res); } $scope.search.loading = false; + $scope.search.preventSelect = false; $scope.search.hasMore = $scope.search.results.length >= $scope.search.limit; $scope.updateView(); }) @@ -94,6 +132,7 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim if (!options.from) { $scope.search.results = []; } + $scope.search.preventSelect = false; $scope.search.hasMore = false; UIUtils.onError('COMMON.NOTIFICATIONS.LOAD_NOTIFICATIONS_FAILED')(err); }); @@ -106,23 +145,23 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim }; $scope.markAllAsRead = function() { + $scope.hideActionsPopover(); + // Make sure to be auth before doing this - if (!csWallet.isAuth()) { - return csWallet.auth().then(function(){ + if (!wallet.isAuth()) { + return wallet.auth().then(function(){ UIUtils.loading.hide(); return $scope.markAllAsRead(); // loop }); } - $scope.hideActionsPopover(); - if (!$scope.search.results.length) return; UIUtils.loading.show() .then(function() { - $rootScope.walletData.notifications.unreadCount = 0; + wallet.data.notifications.unreadCount = 0; var lastNotification = $scope.search.results[0]; - $rootScope.walletData.notifications.readTime = lastNotification ? lastNotification.time : 0; + wallet.data.notifications.time = lastNotification ? lastNotification.time : 0; _.forEach($scope.search.results, function (item) { if (item.markAsRead && typeof item.markAsRead == 'function') item.markAsRead(); }); @@ -132,18 +171,22 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim }; $scope.resetUnreadCount = function() { - if (!csWallet.data.notifications.unreadCount || !$scope.search.results || !$scope.search.results.length) return; - csWallet.data.notifications.unreadCount = 0; + if ($scope.search.loading || !wallet.data.notifications) { + return $timeout($scope.resetUnreadCount, 2000); + } + if (!wallet.data.notifications.unreadCount || !$scope.search.results || !$scope.search.results.length) return; + wallet.data.notifications.unreadCount = 0; var lastNotification = $scope.search.results[0]; var readTime = lastNotification.time ? lastNotification.time : 0; - if (readTime && (!csSettings.data.wallet || csSettings.data.wallet.notificationReadTime != readTime)) { - csSettings.data.wallet = csSettings.data.wallet || {}; - csSettings.data.wallet.notificationReadTime = readTime; - csSettings.store(); + if (readTime && (!wallet.data.notifications.time || wallet.data.notifications.time != readTime)) { + wallet.data.notifications.time = readTime; + wallet.storeData(); } }; - $scope.select = function(item) { + $scope.select = function(event, item) { + + if ($scope.search.loading || event.preventDefault() || $scope.search.preventSelect) return; if (item.markAsRead && typeof item.markAsRead == 'function') { $timeout(item.markAsRead); @@ -196,38 +239,52 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/notification/popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl :'plugins/es/templates/notification/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; /* -- listeners -- */ - csWallet.api.data.on.logout($scope, $scope.resetData); - esHttp.api.node.on.stop($scope, $scope.resetData); - esHttp.api.node.on.start($scope, $scope.load); - esNotification.api.data.on.new($scope, $scope.onNewNotification); + $scope.addListeners = function() { + if (!wallet) throw "Controller wallet not set !"; + + $scope.listeners = [ + esHttp.api.node.on.stop($scope, $scope.resetData), + esHttp.api.node.on.start($scope, $scope.load), + wallet.api.data.on.logout($scope, $scope.resetData) + ]; + + if (wallet.isDefault()) { + // Subscribe to new notification + $scope.listeners.push( + esNotification.api.data.on.new($scope, $scope.onNewNotification) + ); + } + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; } -function PopoverNotificationsController($scope, $timeout, $controller, UIUtils, $state) { +function PopoverNotificationsController($scope, $timeout, $controller, $state, + UIUtils, csWallet) { 'ngInject'; // Initialize the super class and extend it. @@ -236,8 +293,12 @@ function PopoverNotificationsController($scope, $timeout, $controller, UIUtils, // Disable list motion $scope.motion = null; + // Set the wallet to use + $scope.setWallet(csWallet); + $scope.$on('popover.shown', function() { if ($scope.search.loading) { + $scope.addListeners(); $scope.load(); } }); @@ -253,8 +314,8 @@ function PopoverNotificationsController($scope, $timeout, $controller, UIUtils, $scope.$on('popover.hidden', $scope.resetUnreadCount); - $scope.select = function(notification) { - if (!notification) return; // no selection + $scope.select = function($event, notification) { + if ($event.preventDefault() || !notification) return; // no selection if (notification.markAsRead && typeof notification.markAsRead == 'function') notification.markAsRead(); if (notification.state) { $state.go(notification.state, notification.stateParams); diff --git a/assets/www/dist/dist_js/plugins/controllers/profile-controllers.js b/assets/www/dist/dist_js/plugins/controllers/profile-controllers.js index 2918d91fef806d805278a5619c4a250c30410bb9..338154f229e2ffc230320a2a33a986e56d45602b 100644 --- a/assets/www/dist/dist_js/plugins/controllers/profile-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/profile-controllers.js @@ -1,21 +1,36 @@ -ESViewEditProfileController.$inject = ['$scope', '$rootScope', '$q', '$timeout', '$state', '$focus', '$translate', '$controller', '$ionicHistory', '$ionicPopover', 'UIUtils', 'csWallet', 'esHttp', 'esProfile', 'ModalUtils', 'Device'];angular.module('cesium.es.profile.controllers', ['cesium.es.services']) +ESViewEditProfileController.$inject = ['$scope', '$q', '$timeout', '$state', '$focus', '$translate', '$controller', '$ionicHistory', '$ionicPopover', 'UIUtils', 'csWallet', 'esHttp', 'esProfile', 'ModalUtils', 'Device'];angular.module('cesium.es.profile.controllers', ['cesium.es.services']) .config(['$stateProvider', function($stateProvider) { - $stateProvider.state('app.user_edit_profile', { - url: "/wallet/profile/edit", - views: { - 'menuContent': { - templateUrl: "plugins/es/templates/user/edit_profile.html", - controller: 'ESViewEditProfileCtrl' + $stateProvider + .state('app.edit_profile', { + url: "/wallet/profile/edit", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/user/edit_profile.html", + controller: 'ESViewEditProfileCtrl' + } + }, + cache: false, + data: { + auth: true } - }, - cache: false, - data: { - auth: true - } - }); + }) + + .state('app.edit_profile_by_id', { + url: "/wallets/:id/profile/edit", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/user/edit_profile.html", + controller: 'ESViewEditProfileCtrl' + } + }, + cache: false, + data: { + login: true + } + }); }]) @@ -24,7 +39,7 @@ ESViewEditProfileController.$inject = ['$scope', '$rootScope', '$q', '$timeout', ; -function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $focus, $translate, $controller, +function ESViewEditProfileController($scope, $q, $timeout, $state, $focus, $translate, $controller, $ionicHistory, $ionicPopover, UIUtils, csWallet, esHttp, esProfile, ModalUtils, Device) { 'ngInject'; @@ -48,19 +63,32 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ }; $scope.socialReorder = true; - $scope.$on('$ionicView.enter', function(e) { - $scope.loadWallet() - .then(function(walletData) { - return $scope.load(walletData); + var wallet; + + $scope.enter = function(e, state) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + $scope.walletId = wallet.id; + + return wallet.auth({ + minData: true }) + .then($scope.load) .catch(function(err){ if (err == 'CANCELLED') { - return $scope.close() - .then(UIUtils.loading.hide); + UIUtils.loading.hide(10); + $scope.cancel(); + return; } UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')(err); }); - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.$on('$stateChangeStart', function (event, next, nextParams, fromState) { if ($scope.dirty && !$scope.saving) { @@ -125,31 +153,29 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ $scope.updateView(walletData, {}); } + UIUtils.loading.hide(); + + // Update loading - done with a delay, to avoid trigger onFormDataChanged() + return $timeout(function() { + $scope.loading = false; + }, 1000); + }) + .then(function() { }) - .catch(function(err){ - UIUtils.loading.hide(10); - UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')(err); - }); + .catch(UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')); }; $scope.setForm = function(form) { $scope.form = form; }; - $scope.updateView = function(wallet, profile) { - $scope.walletData = wallet; + $scope.updateView = function(walletData, profile) { + $scope.walletData = walletData; $scope.formData = profile; if (profile.avatar) { $scope.avatarStyle={'background-image':'url("'+$scope.avatar.src+'")'}; } - $scope.motion.show(); - UIUtils.loading.hide(); - - // Update loading - done with a delay, to avoid trigger onFormDataChanged() - $timeout(function() { - $scope.loading = false; - }, 1000); }; $scope.onFormDataChanged = function() { @@ -159,7 +185,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ $scope.$watch('formData', $scope.onFormDataChanged, true); $scope.save = function(silent, hasWaitDebounce) { - if($scope.form.$invalid || !$rootScope.walletData || ($scope.saving && !hasWaitDebounce)) { + if($scope.form.$invalid || !$scope.walletData || ($scope.saving && !hasWaitDebounce)) { return $q.reject(); } @@ -236,7 +262,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ } if (!$scope.existing) { - return esProfile.add(formData) + return esProfile.add(formData, {wallet: wallet}) .then(function() { console.info("[ES] [profile] Successfully created."); $scope.existing = true; @@ -249,7 +275,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ .catch(onError('PROFILE.ERROR.SAVE_PROFILE_FAILED')); } else { - return esProfile.update(formData, {id: $rootScope.walletData.pubkey}) + return esProfile.update(formData, {id: $scope.walletData.pubkey, wallet: wallet}) .then(function() { console.info("[ES] Profile successfully updated."); $scope.saving = false; @@ -289,11 +315,27 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ $scope.cancel = function() { $scope.dirty = false; // force not saved - $scope.close(); + if (wallet.isDefault()) { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + return $state.go('app.view_wallet'); + } + else { + return $state.go('app.view_wallet_by_id', {id: wallet.id}); + } }; $scope.close = function() { - return $state.go('app.view_wallet', {refresh: true}); + if (wallet.isDefault()) { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + return $state.go('app.view_wallet', {refresh: true}); + } + else { + return $state.go('app.view_wallet_by_id', {refresh: true, id: wallet.id}); + } }; $scope.showAvatarModal = function() { @@ -341,7 +383,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ // Hide popover if need $scope.hideActionsPopover(); - return $scope.existing && csWallet.auth({minData: true}) + return $scope.existing && wallet.auth({minData: true}) .then(function(walletData) { UIUtils.loading.hide(); @@ -353,9 +395,11 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ // removeIf(no-device) UIUtils.loading.show(); // endRemoveIf(no-device) - return esProfile.remove(walletData.pubkey) + return esProfile.remove(walletData.pubkey, {wallet: wallet}) .then(function () { - walletData.name=null; + if (wallet.isDefault()) { + walletData.name=null; // keep local name, on children wallets + } walletData.profile = null; walletData.avatar = null; console.debug('[ES] [profile] Successfully deleted'); @@ -376,26 +420,20 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/user/edit_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/user/edit_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; } diff --git a/assets/www/dist/dist_js/plugins/controllers/registry-controllers.js b/assets/www/dist/dist_js/plugins/controllers/registry-controllers.js index 53b2ff4a59717299aea9a8702a0470d700372d6b..c64ecc5a711f68a99f887a70323605a2feb56d4e 100644 --- a/assets/www/dist/dist_js/plugins/controllers/registry-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/registry-controllers.js @@ -1,6 +1,6 @@ ESRegistryLookupController.$inject = ['$scope', '$focus', '$timeout', '$filter', '$controller', '$location', '$translate', '$ionicPopover', 'Device', 'UIUtils', 'ModalUtils', 'BMA', 'csSettings', 'csWallet', 'esModals', 'esRegistry', 'esHttp']; -ESWalletPagesController.$inject = ['$scope', '$controller', '$timeout', 'UIUtils', 'csWallet']; +ESWalletPagesController.$inject = ['$scope', '$controller', '$timeout', 'UIUtils', 'esModals', 'csWallet']; ESRegistryRecordViewController.$inject = ['$scope', '$rootScope', '$state', '$q', '$timeout', '$ionicPopover', '$ionicHistory', '$translate', '$anchorScroll', 'csConfig', 'csWallet', 'esRegistry', 'UIUtils', 'esHttp']; ESRegistryRecordEditController.$inject = ['$scope', '$timeout', '$state', '$q', '$ionicHistory', '$focus', '$translate', '$controller', 'Device', 'UIUtils', 'ModalUtils', 'csWallet', 'esHttp', 'esRegistry'];angular.module('cesium.es.registry.controllers', ['cesium.es.services', 'cesium.es.common.controllers']) @@ -37,7 +37,7 @@ ESRegistryRecordEditController.$inject = ['$scope', '$timeout', '$state', '$q', }) .state('app.wallet_pages', { - url: "/wallet/pages?refresh", + url: "/account/pages?refresh", views: { 'menuContent': { templateUrl: "plugins/es/templates/registry/view_wallet_pages.html", @@ -46,7 +46,23 @@ ESRegistryRecordEditController.$inject = ['$scope', '$timeout', '$state', '$q', }, data: { login: true, - minData: true + minData: true, + silentLocationChange: true + } + }) + + .state('app.wallet_pages_by_id', { + url: "/wallets/:id/pages?refresh", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/registry/view_wallet_pages.html", + controller: 'ESWalletPagesCtrl' + } + }, + data: { + login: true, + minData: true, + silentLocationChange: true } }) @@ -72,7 +88,7 @@ ESRegistryRecordEditController.$inject = ['$scope', '$timeout', '$state', '$q', .state('app.registry_add_record', { cache: false, - url: "/page/add/:type", + url: "/page/add/:type?wallet", views: { 'menuContent': { templateUrl: "plugins/es/templates/registry/edit_record.html", @@ -87,7 +103,7 @@ ESRegistryRecordEditController.$inject = ['$scope', '$timeout', '$state', '$q', .state('app.registry_edit_record', { cache: false, - url: "/page/edit/:id/:title", + url: "/page/edit/:id/:title?wallet", views: { 'menuContent': { templateUrl: "plugins/es/templates/registry/edit_record.html", @@ -206,7 +222,7 @@ function ESRegistryLookupController($scope, $focus, $timeout, $filter, $controll }); } $scope.search.geoPoint = csWallet.data.profile.geoPoint; - $scope.search.location = csWallet.data.profile.city||(csWallet.data.profile.geoPoint ? 'profile position' : undefined); + $scope.search.location = csWallet.data.profile.city||(csWallet.data.profile.geoPoint ? $translate.instant('LOCATION.PROFILE_POSITION') : undefined); } } @@ -627,50 +643,38 @@ function ESRegistryLookupController($scope, $focus, $timeout, $filter, $controll /* -- popovers -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/registry/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl :'plugins/es/templates/registry/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.filtersPopover = null; } }; $scope.showFiltersPopover = function(event) { - if (!$scope.filtersPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/registry/lookup_popover_filters.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl :'plugins/es/templates/registry/lookup_popover_filters.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.filtersPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.filtersPopover.remove(); - }); - $scope.filtersPopover.show(event); - }); - } - else { - $scope.filtersPopover.show(event); - } + } + }); }; $scope.hideFiltersPopover = function() { if ($scope.filtersPopover) { $scope.filtersPopover.hide(); + $scope.filtersPopover = null; } }; @@ -689,7 +693,7 @@ function ESRegistryLookupController($scope, $focus, $timeout, $filter, $controll } -function ESWalletPagesController($scope, $controller, $timeout, UIUtils, csWallet) { +function ESWalletPagesController($scope, $controller, $timeout, UIUtils, esModals, csWallet) { 'ngInject'; // Initialize the super class and extend it. @@ -697,15 +701,25 @@ function ESWalletPagesController($scope, $controller, $timeout, UIUtils, csWalle $scope.searchTextId = undefined; // avoid focus + var wallet; + // Override the default enter $scope.enter = function(e, state) { if (!$scope.entered) { - return csWallet.login({minData: true}) + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + return wallet.login({minData: true}) .then(function(walletData) { UIUtils.loading.hide(); $scope.search.issuer = walletData.pubkey; $scope.search.advanced = true; $timeout($scope.doSearch, 100); + $scope.showFab('fab-wallet-add-registry-record'); }); } else { @@ -717,12 +731,18 @@ function ESWalletPagesController($scope, $controller, $timeout, UIUtils, csWalle }; $scope.doUpdate = function() { - if (!csWallet.isLogin()) return; + if (!wallet || !wallet.isLogin()) return; $scope.search.issuer = csWallet.data.pubkey; $scope.search.advanced = true; return $scope.doSearch(); }; + // Override inherited, to pass the select wallet + $scope.showNewPageModal = function() { + $scope.hidePopovers(); + return esModals.showNewPage({wallet: wallet}); + }; + } @@ -735,6 +755,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.category = {}; $scope.pictures = []; $scope.canEdit = false; + $scope.showTransfer = false; $scope.loading = true; $scope.motion = UIUtils.motion.fadeSlideIn; @@ -751,7 +772,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.$broadcast('$recordView.enter', state); } else { - $state.go('app.registry_lookup'); + $state.go('app.wot_lookup.tab_registry'); } }); @@ -769,7 +790,8 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.id= data.id; $scope.formData = data.record; //console.debug('Loading record', $scope.formData); - $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer); + $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer) || csWallet.children.hasPubkey($scope.formData.issuer); + $scope.showTransfer = !$scope.canEdit && $scope.formData.pubkey; $scope.issuer = data.issuer; // avatar $scope.avatar = $scope.formData.avatar; @@ -792,7 +814,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.loading = false; if (err && err.ucode === 404) { UIUtils.toast.show('REGISTRY.ERROR.RECORD_NOT_EXISTS'); - $state.go('app.registry_lookup'); + $state.go('app.wot_lookup.tab_registry'); } else { UIUtils.onError('REGISTRY.ERROR.LOAD_RECORD_FAILED')(err); @@ -841,13 +863,18 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout // Edit click $scope.edit = function() { + var wallet = csWallet.isUserPubkey($scope.formData.issuer) ? csWallet : csWallet.children.getByPubkey($scope.formData.issuer); + if (!wallet) return; UIUtils.loading.show(); - $state.go('app.registry_edit_record', {id: $scope.id}); + return $state.go('app.registry_edit_record', {id: $scope.id, wallet: wallet.id}); }; $scope.delete = function() { $scope.hideActionsPopover(); + var wallet = csWallet.isUserPubkey($scope.formData.issuer) ? csWallet : csWallet.children.getByPubkey($scope.formData.issuer); + if (!wallet) return; + // translate var translations; $translate(['REGISTRY.VIEW.REMOVE_CONFIRMATION', 'REGISTRY.INFO.RECORD_REMOVED']) @@ -857,15 +884,21 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout }) .then(function(confirm) { if (confirm) { - esRegistry.record.remove($scope.id) + esRegistry.record.remove($scope.id, {wallet: wallet}) .then(function () { - if (csWallet.data.pages && csWallet.data.pages.count) { - csWallet.data.pages.count--; + if (wallet.data.pages && wallet.data.pages.count) { + wallet.data.pages.count--; } $ionicHistory.nextViewOptions({ historyRoot: true }); - $state.go('app.wallet_pages', {refresh: true}); + if (wallet.isDefault()) { + $state.go('app.wallet_pages', {refresh: true}); + } + else { + $state.go('app.wallet_pages_by_id', {refresh: true, id: wallet.id}); + } + UIUtils.toast.show(translations['REGISTRY.INFO.RECORD_REMOVED']); }) .catch(UIUtils.onError('REGISTRY.ERROR.REMOVE_RECORD_FAILED')); @@ -875,27 +908,22 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout /* -- modals & popover -- */ + $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/registry/view_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/registry/view_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; @@ -946,23 +974,34 @@ function ESRegistryRecordEditController($scope, $timeout, $state, $q, $ionicHis $scope.form = form; }; + var wallet; + $scope.$on('$ionicView.enter', function(e, state) { - $scope.loadWallet({minData: true}) - .then(function(walletData) { - $scope.walletData = walletData; - if (state.stateParams && state.stateParams.id) { // Load by id - $scope.load(state.stateParams.id); - } - else { - if (state.stateParams && state.stateParams.type) { - $scope.updateView({ - record: { - type: state.stateParams.type - } - }); + + if ($scope.loading) { + wallet = (state.stateParams && state.stateParams.wallet && state.stateParams.wallet != 'default') ? csWallet.children.get(state.stateParams.wallet) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + return wallet.login({minData: true}) + .then(function(walletData) { + $scope.walletData = walletData; + if (state.stateParams && state.stateParams.id) { // Load by id + $scope.load(state.stateParams.id); } - } - }); + else { + if (state.stateParams && state.stateParams.type) { + $scope.updateView({ + record: { + type: state.stateParams.type + } + }); + } + } + }); + } }); $scope.$on('$stateChangeStart', function (event, next, nextParams, fromState) { @@ -1119,7 +1158,7 @@ function ESRegistryRecordEditController($scope, $timeout, $state, $q, $ionicHis if (!$scope.needCategory()) { delete json.category; } - json.time = esHttp.date.now(); + json.time = moment().utc().unix(); // geo point if (json.geoPoint && json.geoPoint.lat && json.geoPoint.lon) { @@ -1169,15 +1208,15 @@ function ESRegistryRecordEditController($scope, $timeout, $state, $q, $ionicHis .then(function(json){ // Create if (!$scope.id) { - return esRegistry.record.add(json); + return esRegistry.record.add(json, {wallet: wallet}); } // Update - return esRegistry.record.update(json, {id: $scope.id}); + return esRegistry.record.update(json, {id: $scope.id, wallet: wallet}); }) .then(function(id) { console.info("[ES] [page] Record successfully saved."); - if (!$scope.id && csWallet.data.pages && csWallet.data.pages.count) { + if (!$scope.id && wallet.data.pages && wallet.data.pages.count) { csWallet.data.pages.count++; } $scope.id = $scope.id || id; diff --git a/assets/www/dist/dist_js/plugins/controllers/settings-controllers.js b/assets/www/dist/dist_js/plugins/controllers/settings-controllers.js index 0a43e51139f6f85d147fcc40703ffb29a90ea320..f0e7511e811328698bb77f0a8887c5facaa74118 100644 --- a/assets/www/dist/dist_js/plugins/controllers/settings-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/settings-controllers.js @@ -1,6 +1,6 @@ ESExtendSettingsController.$inject = ['$scope', 'PluginService']; -ESPluginSettingsController.$inject = ['$scope', '$q', '$translate', '$ionicPopup', 'UIUtils', 'Modals', 'csHttp', 'csSettings', 'esHttp', 'esSettings'];angular.module('cesium.es.settings.controllers', ['cesium.es.services']) +ESPluginSettingsController.$inject = ['$scope', '$window', '$q', '$translate', '$ionicPopup', 'UIUtils', 'Modals', 'csHttp', 'csConfig', 'csSettings', 'esHttp', 'esSettings'];angular.module('cesium.es.settings.controllers', ['cesium.es.services']) // Configure menu items .config(['PluginServiceProvider', '$stateProvider', 'csConfig', function(PluginServiceProvider, $stateProvider, csConfig) { @@ -13,7 +13,7 @@ ESPluginSettingsController.$inject = ['$scope', '$q', '$translate', '$ionicPopup points: { 'plugins': { templateUrl: "plugins/es/templates/settings/settings_extend.html", - controller: "ESExtendSettingsCtrl" + controller: "ESExtensionCtrl" } } }); @@ -50,9 +50,11 @@ function ESExtendSettingsController ($scope, PluginService) { /* * Settings extend controller */ -function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUtils, Modals, csHttp, csSettings, esHttp, esSettings) { +function ESPluginSettingsController ($scope, $window, $q, $translate, $ionicPopup, + UIUtils, Modals, csHttp, csConfig, csSettings, esHttp, esSettings) { 'ngInject'; + $scope.hasWindowNotification = !!("Notification" in window); $scope.formData = {}; $scope.popupData = {}; // need for the node popup $scope.loading = true; @@ -95,7 +97,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti node = node || { host: $scope.formData.host, port: $scope.formData.port && $scope.formData.port != 80 && $scope.formData.port != 443 ? $scope.formData.port : undefined, - wsPort: $scope.formData.wsPort && $scope.formData.wsPort != $scope.formData.port ? $scope.formData.wsPort : undefined, useSsl: angular.isDefined($scope.formData.useSsl) ? $scope.formData.useSsl : ($scope.formData.port == 443) @@ -105,14 +106,13 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti .then(function(newNode) { if (newNode.host == $scope.formData.host && newNode.port == $scope.formData.port && - newNode.wsPort == $scope.formData.wsPort && newNode.useSsl == $scope.formData.useSsl) { UIUtils.loading.hide(); return; // same node = nothing to do } UIUtils.loading.show(); - var newEsNode = esHttp.instance(newNode.host, newNode.port, newNode.wsPort, newNode.useSsl); + var newEsNode = esHttp.instance(newNode.host, newNode.port, newNode.useSsl); return newEsNode.isAlive() // ping the node .then(function(alive) { if (!alive) { @@ -125,7 +125,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti $scope.formData.host = newEsNode.host; $scope.formData.port = newEsNode.port; - $scope.formData.wsPort = newEsNode.wsPort; $scope.formData.useSsl = newEsNode.useSsl; return esHttp.copy(newEsNode); @@ -140,13 +139,10 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti // Show node popup $scope.showNodePopup = function(node) { + return $q(function(resolve, reject) { var parts = [node.host]; - if (node.wsPort && node.wsPort != (node.port||80)) { - parts.push(node.port||80); - parts.push(node.wsPort); - } - else if (node.port && node.port != 80) { + if (node.port && node.port != 80) { parts.push(node.port); } $scope.popupData.newNode = parts.join(':'); @@ -189,7 +185,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti resolve({ host: parts[0], port: parts[1] || (useSsl ? 443 : 80), - wsPort: parts[2] || parts[1] || (useSsl ? 443 : 80), useSsl: useSsl }); }); @@ -198,10 +193,15 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti }; $scope.showNodeList = function() { + // Check if need a filter on SSL node + var forceUseSsl = (csConfig.httpsMode === 'true' || csConfig.httpsMode === true || csConfig.httpsMode === 'force') || + ($window.location && $window.location.protocol === 'https:') ? true : false; + $ionicPopup._popupStack[0].responseDeferred.promise.close(); return Modals.showNetworkLookup({ enableFilter: true, - endpointFilter: esHttp.constants.ES_USER_API_ENDPOINT + endpoint: esHttp.constants.ES_USER_API_ENDPOINT, + ssl: forceUseSsl ? true: undefined }) .then(function (peer) { if (!peer) return; @@ -214,14 +214,11 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti return { host: (ep.dns ? ep.dns : (peer.hasValid4(ep) ? ep.ipv4 : ep.ipv6)), - port: ep.port || 80 + port: ep.port || 80, + useSsl: ep.useSsl || ep.port == 443 }; }) .then(function(newEsNode) { - if (!newEsNode) { - UIUtils.alert.error('ERROR.INVALID_NODE_SUMMARY'); - return; - } $scope.changeEsNode(newEsNode); }); }; @@ -229,6 +226,16 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti $scope.onFormChanged = function() { if ($scope.loading) return; + if ($scope.hasWindowNotification && + $scope.formData.notifications.emitHtml5 !== (window.Notification.permission === "granted")){ + window.Notification.requestPermission(function (permission) { + // If the user accepts, let's create a notification + $scope.formData.notifications.emitHtml5 = (permission === "granted"); // revert to false if permission not granted + $scope.onFormChanged(); // Loop + }); + return; + } + $scope.loading = true; csSettings.data.plugins = csSettings.data.plugins || {}; csSettings.data.plugins.es = csSettings.data.plugins.es ? @@ -248,7 +255,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti $scope.getServer = function(node) { node = node || $scope.formData; if (!node.host) return undefined; - var server = csHttp.getServer(node.host, node.port); - return server + (node.wsPort && node.wsPort != node.port ? ':' + node.wsPort : ''); + return csHttp.getServer(node.host, node.port); }; } diff --git a/assets/www/dist/dist_js/plugins/controllers/subscription-controllers.js b/assets/www/dist/dist_js/plugins/controllers/subscription-controllers.js index 12d8940874e587b8c6155e63b152ca38e355ad82..e28697ebc0a2ec208dc78115b48c0426ece5977d 100644 --- a/assets/www/dist/dist_js/plugins/controllers/subscription-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/subscription-controllers.js @@ -1,23 +1,39 @@ -ViewSubscriptionsController.$inject = ['$scope', '$rootScope', '$q', 'csWot', 'UIUtils', 'ModalUtils', 'esSubscription']; +ViewSubscriptionsController.$inject = ['$scope', '$q', '$ionicHistory', 'csWot', 'csWallet', 'UIUtils', 'ModalUtils', 'esSubscription']; ModalEmailSubscriptionsController.$inject = ['$scope', 'Modals', 'csSettings', 'esHttp', 'csWot', 'parameters'];angular.module('cesium.es.subscription.controllers', ['cesium.es.services']) .config(['$stateProvider', function($stateProvider) { - $stateProvider.state('app.edit_subscriptions', { - cache: false, - url: "/wallet/subscriptions", - views: { - 'menuContent': { - templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", - controller: 'ViewSubscriptionsCtrl' + $stateProvider + .state('app.edit_subscriptions', { + cache: false, + url: "/wallet/subscriptions", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", + controller: 'ViewSubscriptionsCtrl' + } + }, + data: { + auth: true, + minData: true } - }, - data: { - auth: true, - minData: true - } - }); + }) + + .state('app.edit_subscriptions_by_id', { + cache: false, + url: "/wallets/:id/subscriptions", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", + controller: 'ViewSubscriptionsCtrl' + } + }, + data: { + login: true, + minData: true + } + }); }]) @@ -27,9 +43,10 @@ ModalEmailSubscriptionsController.$inject = ['$scope', 'Modals', 'csSettings', ' ; -function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, ModalUtils, esSubscription) { +function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, UIUtils, ModalUtils, esSubscription) { 'ngInject'; + $scope.loading = true; $scope.popupData = {}; // need for the node popup $scope.search = { results: [], @@ -40,25 +57,44 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod {id: "weekly", label: "weekly"} ]; - $scope.onEnter = function() { - $scope.loading = true; - $scope.loadWallet({minData: true}) - .then(function() { - UIUtils.loading.hide(); - return $scope.load(); - }) - .catch(function(err){ - if (err == 'CANCELLED') { - return UIUtils.loading.hide(); - } - UIUtils.onError('SUBSCRIPTION.ERROR.LOAD_SUBSCRIPTIONS_FAILED')(err); - }); + var wallet; + + $scope.enter = function(e, state) { + + // First load + if ($scope.loading) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + wallet.auth({minData: true}) + .then(function() { + UIUtils.loading.hide(); + return $scope.load(); + }) + .then(function() { + $scope.showFab('fab-add-subscription-record'); + }) + .catch(function(err){ + if (err === 'CANCELLED') { + UIUtils.loading.hide(10); + $scope.loading=true; // reset for force reload next time + $ionicHistory.goBack(); + return; + } + UIUtils.onError('SUBSCRIPTION.ERROR.LOAD_SUBSCRIPTIONS_FAILED')(err); + }); + } + }; - $scope.$on('$ionicView.enter', $scope.onEnter); + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function() { $scope.loading = true; // to avoid the call of doSave() - return esSubscription.record.load($rootScope.walletData.pubkey, $rootScope.walletData.keypair) + return esSubscription.record.load(wallet.data.pubkey, wallet.data.keypair) .then(function(results) { // Group by type var groups = _.groupBy((results || []), function (record) { @@ -76,10 +112,8 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod .then(function(results) { return csWot.extendAll(results, 'recipient'); }) - .then(function(results) { - // Display result - $scope.updateView(results); - }) + // Display result + .then($scope.updateView) .catch(function(err){ UIUtils.loading.hide(10); if (err && err.ucode == 404) { @@ -110,7 +144,7 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod if (!cat) return; type = cat.id; // get subscription parameters - if (type == 'email') { + if (type === 'email') { return $scope.showEmailModal(); } else { @@ -120,11 +154,11 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod .then(function(record) { if (!record) return; UIUtils.loading.show(); - esSubscription.record.add(record) + esSubscription.record.add(record, {wallet: wallet}) .then($scope.addToUI) .then(function() { - $rootScope.walletData.subscriptions = $rootScope.walletData.subscriptions || {count: 0}; - $rootScope.walletData.subscriptions.count++; + wallet.data.subscriptions = wallet.data.subscriptions || {count: 0}; + wallet.data.subscriptions.count++; UIUtils.loading.hide(); $scope.updateView(); }) @@ -137,20 +171,20 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod // get subscription parameters var promise; var oldRecord = angular.copy(record); - if (record.type == 'email') { + if (record.type === 'email') { promise = $scope.showEmailModal(record); } if (!promise) return; return promise - .then(function() { - if (!record) return; + .then(function(res) { + if (!res) return; UIUtils.loading.show(); record.id = oldRecord.id; - return esSubscription.record.update(record) + return esSubscription.record.update(record, wallet) .then(function() { // If recipient change, update in results - if (oldRecord.type != record.type || - oldRecord.recipient != record.recipient) { + if (oldRecord.type !== record.type || + oldRecord.recipient !== record.recipient) { $scope.removeFromUI(oldRecord); return $scope.addToUI(record); } @@ -174,10 +208,10 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod } UIUtils.loading.show(); - esSubscription.record.remove(record.id) + esSubscription.record.remove(record.id, {wallet: wallet}) .then(function() { - $rootScope.walletData.subscriptions = $rootScope.walletData.subscriptions || {count: 1}; - $rootScope.walletData.subscriptions.count--; + wallet.data.subscriptions = wallet.data.subscriptions || {count: 1}; + wallet.data.subscriptions.count--; $scope.removeFromUI(record); UIUtils.loading.hide(); }) @@ -288,7 +322,8 @@ function ModalEmailSubscriptionsController($scope, Modals, csSettings, esHttp, c $scope.showNetworkLookup = function() { return Modals.showNetworkLookup({ enableFilter: true, - endpointFilter: esHttp.constants.ES_USER_API_ENDPOINT + endpoint: esHttp.constants.ES_USER_API_ENDPOINT, + bma: false }) .then(function (peer) { if (peer) { diff --git a/assets/www/dist/dist_js/plugins/controllers/wallet-controllers.js b/assets/www/dist/dist_js/plugins/controllers/wallet-controllers.js index b3595b821b4fad750dd1c5436ca5998cb2d000da..ae2efcabd3ca35b790ef523b8be10f6a056dc12c 100644 --- a/assets/www/dist/dist_js/plugins/controllers/wallet-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/wallet-controllers.js @@ -1,12 +1,13 @@ -ESWalletController.$inject = ['$scope', '$controller', 'esModals'];angular.module('cesium.es.wallet.controllers', ['cesium.es.services']) +ESWalletController.$inject = ['$scope', '$controller', '$state', 'esModals', 'csWallet'];angular.module('cesium.es.wallet.controllers', ['cesium.es.services']) .config(['PluginServiceProvider', 'csConfig', function(PluginServiceProvider, csConfig) { 'ngInject'; var enable = csConfig.plugins && csConfig.plugins.es; if (enable) { - PluginServiceProvider.extendState('app.view_wallet', { + PluginServiceProvider + .extendStates(['app.view_wallet', 'app.view_wallet_by_id'], { points: { 'after-general': { templateUrl: "plugins/es/templates/wallet/view_wallet_extend.html", @@ -14,6 +15,16 @@ ESWalletController.$inject = ['$scope', '$controller', 'esModals'];angular.modul } } }) + + .extendState('app.view_wallets', { + points: { + 'item-wallet': { + templateUrl: "plugins/es/templates/wallet/item_wallet_extend.html", + controller: 'ESExtensionCtrl' + } + } + }) + ; } @@ -24,18 +35,24 @@ ESWalletController.$inject = ['$scope', '$controller', 'esModals'];angular.modul ; -function ESWalletController($scope, $controller, esModals) { +function ESWalletController($scope, $controller, $state, esModals, csWallet) { 'ngInject'; // Initialize the super class and extend it. - angular.extend(this, $controller('ESWotIdentityViewCtrl', {$scope: $scope})); + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); $scope.showProfileHelp = false; /* -- modals -- */ $scope.showNewPageModal = function() { - return esModals.showNewPage(); + var wallet = ($state.params && $state.params.id) ? csWallet.children.get($state.params.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return; + } + + return esModals.showNewPage({wallet: wallet}); }; } diff --git a/assets/www/dist/dist_js/plugins/controllers/wot-controllers.js b/assets/www/dist/dist_js/plugins/controllers/wot-controllers.js index 3388fe55afd5d25cb0728123ccfe044cd7dc7797..ff8003c7328cb8becc35a036d19ef6a207d141be 100644 --- a/assets/www/dist/dist_js/plugins/controllers/wot-controllers.js +++ b/assets/www/dist/dist_js/plugins/controllers/wot-controllers.js @@ -1,6 +1,6 @@ ESWotLookupExtendController.$inject = ['$scope', '$controller', '$state']; -ESWotIdentityViewController.$inject = ['$scope', '$ionicPopover', '$q', 'UIUtils', 'Modals', 'esSettings', 'PluginService', 'csWallet', 'esModals', 'esHttp', 'esWallet', 'esInvitation'];angular.module('cesium.es.wot.controllers', ['cesium.es.services']) +ESWotIdentityViewController.$inject = ['$scope', '$ionicPopover', '$q', '$controller', 'UIUtils', 'Modals', 'csWallet', 'esModals', 'esWallet', 'esInvitation'];angular.module('cesium.es.wot.controllers', ['cesium.es.services']) .config(['$stateProvider', 'PluginServiceProvider', 'csConfig', function($stateProvider, PluginServiceProvider, csConfig) { 'ngInject'; @@ -12,7 +12,8 @@ ESWotIdentityViewController.$inject = ['$scope', '$ionicPopover', '$q', 'UIUtils .extendState('app.wot_lookup', { points: { 'tabs': { - templateUrl: "plugins/es/templates/wot/lookup_extend.html" + templateUrl: "plugins/es/templates/wot/lookup_extend.html", + controller: "ESExtensionCtrl" } } }) @@ -35,6 +36,10 @@ ESWotIdentityViewController.$inject = ['$scope', '$ionicPopover', '$q', 'UIUtils 'buttons': { templateUrl: "plugins/es/templates/wot/view_identity_extend.html", controller: 'ESWotIdentityViewCtrl' + }, + 'buttons-top-fab': { + templateUrl: "plugins/es/templates/wot/view_identity_extend.html", + controller: 'ESWotIdentityViewCtrl' } } }) @@ -80,25 +85,24 @@ function ESWotLookupExtendController($scope, $controller, $state) { location: location.length ? location : undefined }; - $state.go('app.registry_lookup', stateParams); + $state.go('app.wot_lookup.tab_registry', stateParams); }; } -function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, esSettings, PluginService, csWallet, - esModals, esHttp, esWallet, esInvitation) { +function ESWotIdentityViewController($scope, $ionicPopover, $q, $controller, UIUtils, Modals, csWallet, + esModals, esWallet, esInvitation) { 'ngInject'; - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; - }); + // Initialize the super class and extend it. + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); + + $scope.canCertify = false; // disable certity on the popover (by default - override by the wot map controller) /* -- modals -- */ $scope.showNewMessageModal = function(confirm) { - return $scope.loadWallet({minData: true}) + return csWallet.login({minData: true, method: 'default'}) .then(function() { UIUtils.loading.hide(); @@ -135,6 +139,7 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, return csWallet.auth({minData: true}) .then(function(walletData) { UIUtils.loading.hide(); + if (!walletData) return; // Not allow for non-member - issue #561 if (!walletData.isMember) { @@ -164,7 +169,7 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, var keypair = res[0]; var confirm = res[1]; if (!confirm) return; - var time = esHttp.date.now(); // use same date for each invitation + var time = moment().utc().unix(); // use same date for each invitation return $q.all( identities.reduce(function(res, identity){ return res.concat( @@ -191,9 +196,13 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, $scope.hideCertificationActionsPopover(); var identities; - return csWallet.auth({minData: true}) + return (csWallet.children.count() ? Modals.showSelectWallet({displayBalance: false}) : $q.when(csWallet)) + .then(function(wallet) { + return wallet.auth({minData: true}); + }) .then(function(walletData) { UIUtils.loading.hide(); + if (!walletData) return; // Not allow for non-member - issue #561 if (!walletData.isMember) { @@ -219,11 +228,10 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, UIUtils.alert.confirm('WOT.CONFIRM.ASK_CERTIFICATIONS', undefined, {okText: 'COMMON.BTN_SEND'}) ]) .then(function(res) { - if (!res) return; - var keypair = res[0]; - var confirm = res[1]; - if (!confirm) return; - var time = esHttp.date.now(); // use same date for each invitation + var keypair = res && res[0]; + var confirm = res && res[1]; + if (!keypair || !confirm) return; + var time = moment().utc().unix(); // use same date for each invitation return $q.all(identities.reduce(function(res, identity){ return res.concat( esInvitation.send({ @@ -246,25 +254,36 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, $scope.askCertification = function() { $scope.hideCertificationActionsPopover(); - return csWallet.auth({minData: true}) + return (csWallet.children.count() ? Modals.showSelectWallet({displayBalance: false}) : $q.when(csWallet)) + .then(function(wallet) { + return wallet.auth({minData: true}); + }) .then(function(walletData) { UIUtils.loading.hide(); + if (!walletData) return; // Not allow for non-member - issue #561 if (!walletData.isMember) { return UIUtils.alert.error('ERROR.ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION'); } - + // ask confirmation return UIUtils.alert.confirm('WOT.CONFIRM.ASK_CERTIFICATION', undefined, { - okText: 'COMMON.BTN_SEND' - }) + okText: 'COMMON.BTN_SEND' + }) .then(function(confirm) { if (!confirm) return; return esInvitation.send({ issuer: walletData.pubkey, recipient: $scope.formData.pubkey, content: [walletData.uid, walletData.pubkey].join('-') - }, undefined, 'certification') + }, + { + type: 'certification', + keypair: walletData.keypair + }) + .then(function() { + UIUtils.toast.show('INVITATION.INFO.INVITATION_SENT'); + }) .catch(UIUtils.onError('INVITATION.ERROR.SEND_INVITATION_FAILED')); }); }); @@ -273,29 +292,32 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, /* -- Popover -- */ $scope.showCertificationActionsPopover = function(event) { - if (!$scope.certificationActionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/wot/popover_certification_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/wot/popover_certification_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.certificationActionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.certificationActionsPopover.remove(); - }); - $scope.certificationActionsPopover.show(event); - }); - } - else { - $scope.certificationActionsPopover.show(event); - } + } + }); }; $scope.hideCertificationActionsPopover = function() { if ($scope.certificationActionsPopover) { $scope.certificationActionsPopover.hide(); + $scope.certificationActionsPopover = null; } }; + if ($scope.extensionPoint === 'buttons-top-fab') { + // Show fab button, when parent execute motions + $scope.$on('$csExtension.motion', function(event) { + var canCompose = !!$scope.formData.profile; + if (canCompose) { + $scope.showFab('fab-compose-' + $scope.formData.uid); + } + }); + } // TODO : for DEV only /*$timeout(function() { diff --git a/assets/www/dist/dist_js/plugins/entities/notification.js b/assets/www/dist/dist_js/plugins/entities/notification.js index cd564c88c1fceb73773192b3fe5000a88a59a27b..f928c32002304b8ba750b9ab1704920109a9e380 100644 --- a/assets/www/dist/dist_js/plugins/entities/notification.js +++ b/assets/www/dist/dist_js/plugins/entities/notification.js @@ -1,5 +1,5 @@ -function Notification(json, markAsReadCallback) { +function EsNotification(json, markAsReadCallback) { var messagePrefixes = { 'registry': 'EVENT.REGISTRY.' @@ -42,12 +42,15 @@ function Notification(json, markAsReadCallback) { if (json.code.startsWith('MEMBER_')) { that.avatarIcon = 'ion-person'; that.icon = 'ion-information-circled positive'; + that.state = 'app.view_wallet'; + that.medianTime = that.time; } // TX else if (json.code.startsWith('TX_')) { that.avatarIcon = 'ion-card'; that.icon = (json.code == 'TX_SENT') ? 'ion-paper-airplane dark' : 'ion-archive balanced'; + that.medianTime = that.time; pubkeys = json.params.length > 0 ? json.params[0] : null; if (pubkeys && pubkeys.indexOf(',') == -1) { that.pubkey = pubkeys; @@ -61,6 +64,7 @@ function Notification(json, markAsReadCallback) { that.avatarIcon = (json.code == 'CERT_RECEIVED') ? 'ion-ribbon-b' : 'ion-ribbon-a'; that.icon = (json.code == 'CERT_RECEIVED') ? 'ion-ribbon-b balanced' : 'ion-ribbon-a gray'; that.pubkey = json.params.length > 0 ? json.params[0] : null; + that.medianTime = that.time; that.state = 'app.wallet_cert'; that.stateParams = { type: (json.code == 'CERT_RECEIVED') ? 'received' : 'given' @@ -114,4 +118,6 @@ function Notification(json, markAsReadCallback) { that.avatarIcon = 'ion-close'; that.icon = 'ion-close-circled assertive'; } + + return that; } diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/app-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/app-controllers.js index 672c7edc298b4d63d3a7a3c22a54d348632411dd..ea0b8cffded32da4a6a4b85f697592c8aea8c515 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/app-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/app-controllers.js @@ -1,6 +1,6 @@ ESExtensionController.$inject = ['$scope', 'esSettings', 'PluginService']; -ESMenuExtendController.$inject = ['$scope', '$state', 'PluginService', 'esSettings', 'UIUtils', 'csWallet']; +ESMenuExtendController.$inject = ['$scope', '$state', '$controller', 'UIUtils', 'csWallet']; ESProfilePopoverExtendController.$inject = ['$scope', '$q', '$state', 'esSettings', 'csWallet'];angular.module('cesium.es.app.controllers', ['ngResource', 'cesium.es.services']) // Configure menu items @@ -56,26 +56,35 @@ function ESExtensionController($scope, esSettings, PluginService) { $scope.enable = esSettings.isEnable(); esSettings.api.state.on.changed($scope, function(enable) { $scope.enable = enable; + $scope.$broadcast('$$rebind::state'); }); } /** * Control menu extension */ -function ESMenuExtendController($scope, $state, PluginService, esSettings, UIUtils, csWallet) { +function ESMenuExtendController($scope, $state, $controller, UIUtils, csWallet) { 'ngInject'; - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); + + // Initialize the super class and extend it. + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); $scope.showRegistryLookupView = function() { - $state.go(UIUtils.screen.isSmall() ? 'app.registry_lookup': 'app.registry_lookup_lg'); + $state.go(UIUtils.screen.isSmall() ? 'app.wot_lookup.tab_registry': 'app.registry_lookup_lg'); }; $scope.showNotificationsPopover = function(event) { return UIUtils.popover.show(event, { templateUrl :'plugins/es/templates/notification/popover_notification.html', scope: $scope, - autoremove: false // reuse popover + autoremove: false, // reuse popover + // Auto-close if open when un-authenticate + afterShow: function(popover) { + var listener = csWallet.api.data.on.unauth(popover.scope, function() { + popover.scope.closePopover(); + listener(); + }); + } }); }; @@ -91,7 +100,14 @@ function ESMenuExtendController($scope, $state, PluginService, esSettings, UIUti return UIUtils.popover.show(event, { templateUrl :'plugins/es/templates/message/popover_message.html', scope: $scope, - autoremove: false // reuse popover + autoremove: false, // reuse popover + // Auto-close if open when un-authenticate + afterShow: function(popover) { + var listener = csWallet.api.data.on.unauth(popover.scope, function() { + popover.scope.closePopover(); + listener(); + }); + } }); }; @@ -110,18 +126,13 @@ function ESMenuExtendController($scope, $state, PluginService, esSettings, UIUti autoremove: false, // reuse popover // Auto-close if open when un-authenticate afterShow: function(popover) { - csWallet.api.data.on.unauth(popover.scope, function() { + var listener = csWallet.api.data.on.unauth(popover.scope, function() { popover.scope.closePopover(); + listener(); }); } }); }; - - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; - }); - - } /** @@ -136,7 +147,7 @@ function ESProfilePopoverExtendController($scope, $q, $state, esSettings, csWall $scope.showEditUserProfile = function() { $scope.closeProfilePopover(); - $state.go('app.user_edit_profile'); + $state.go('app.edit_profile'); }; esSettings.api.state.on.changed($scope, $scope.updateView); diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/blockchain-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/blockchain-controllers.js index e4222471e67ca0eaffa348103c3370e391d7124e..31d8f805f3340c318c9407e7934a5e0582c1be18 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/blockchain-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/blockchain-controllers.js @@ -135,7 +135,7 @@ function ESBlockLookupController($scope, $controller, $ionicPopover, $location, promise = esBlockchain.block.searchText($scope.currency, $scope.search.query, request); } - var time = new Date().getTime(); + var now = Date.now(); return promise .then(function(result) { // Apply transformation need by UI (e.g add avatar and name...) @@ -147,7 +147,7 @@ function ESBlockLookupController($scope, $controller, $ionicPopover, $location, .then(function(result) { $scope.showPubkey = ($scope.search.sort == 'issuer'); // Compute time only once (on first page) - $scope.search.took = (from === 0) ? (new Date().getTime() - time) : $scope.search.took; + $scope.search.took = (from === 0) ? (Date.now() - now) : $scope.search.took; // Keep previous total, when already computed (because of current, that is excluded only in the first page) var total = (from === 0) ? result.total : $scope.search.total; $scope.doDisplayResult(result.hits, from, total); @@ -182,26 +182,20 @@ function ESBlockLookupController($scope, $controller, $ionicPopover, $location, /* -- popups -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/blockchain/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/blockchain/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/common-controllers.cs.js b/assets/www/dist/dist_js/plugins/es/js/controllers/common-controllers.cs.js deleted file mode 100644 index 1f6de62f48a76fe3ef4dd8160d6493112e42d18a..0000000000000000000000000000000000000000 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/common-controllers.cs.js +++ /dev/null @@ -1,928 +0,0 @@ - -ESPicturesEditController.$inject = ['$scope', 'UIUtils', '$q', 'Device']; -ESSocialsEditController.$inject = ['$scope', '$focus', '$filter', 'UIUtils', 'SocialUtils']; -ESSocialsViewController.$inject = ['$scope']; -ESCommentsController.$inject = ['$scope', '$filter', '$state', '$focus', 'UIUtils']; -ESCategoryModalController.$inject = ['$scope', 'UIUtils', '$timeout', 'parameters']; -ESAvatarModalController.$inject = ['$scope']; -ESPositionEditController.$inject = ['$scope', 'csConfig', 'esGeo', 'ModalUtils']; -ESLookupPositionController.$inject = ['$scope', '$q', 'csConfig', 'esGeo', 'ModalUtils']; -ESSearchPositionItemController.$inject = ['$scope', '$q', '$timeout', 'ModalUtils', 'UIUtils', 'csConfig', 'esGeo']; -ESSearchPositionModalController.$inject = ['$scope', '$q', '$translate', 'esGeo', 'parameters'];angular.module('cesium.es.common.controllers', ['ngResource', 'cesium.es.services']) - - .controller('ESPicturesEditCtrl', ESPicturesEditController) - - .controller('ESPicturesEditCtrl', ESPicturesEditController) - - .controller('ESSocialsEditCtrl', ESSocialsEditController) - - .controller('ESSocialsViewCtrl', ESSocialsViewController) - - .controller('ESCommentsCtrl', ESCommentsController) - - .controller('ESCategoryModalCtrl', ESCategoryModalController) - - .controller('ESAvatarModalCtrl', ESAvatarModalController) - - .controller('ESPositionEditCtrl', ESPositionEditController) - - .controller('ESLookupPositionCtrl', ESLookupPositionController) - - .controller('ESSearchPositionItemCtrl', ESSearchPositionItemController) - - .controller('ESSearchPositionModalCtrl', ESSearchPositionModalController) -; - - -function ESPicturesEditController($scope, UIUtils, $q, Device) { - 'ngInject'; - - $scope.selectNewPicture = function(inputSelector) { - if (Device.enable){ - $scope.openPicturePopup(); - } - else { - var fileInput = angular.element(document.querySelector(inputSelector||'#pictureFile')); - if (fileInput && fileInput.length > 0) { - fileInput[0].click(); - } - } - }; - - $scope.openPicturePopup = function() { - Device.camera.getPicture() - .then(function(imageData) { - $scope.pictures.push({ - src: "data:image/png;base64," + imageData, - isnew: true // use to prevent visibility hidden (if animation) - }); - }) - .catch(UIUtils.onError('ERROR.TAKE_PICTURE_FAILED')); - }; - - $scope.fileChanged = function(event) { - UIUtils.loading.show(); - return $q(function(resolve, reject) { - var file = event.target.files[0]; - UIUtils.image.resizeFile(file) - .then(function(imageData) { - $scope.pictures.push({ - src: imageData, - isnew: true // use to prevent visibility hidden (if animation) - }); - UIUtils.loading.hide(100); - resolve(); - }); - }); - }; - - $scope.removePicture = function(index){ - $scope.pictures.splice(index, 1); - }; - - $scope.favoritePicture = function(index){ - if (index > 0) { - var item = $scope.pictures[index]; - $scope.pictures.splice(index, 1); - $scope.pictures.splice(0, 0, item); - } - }; - - $scope.rotatePicture = function(index){ - var item = $scope.pictures[index]; - UIUtils.image.rotateSrc(item.src) - .then(function(dataURL){ - item.src = dataURL; - }); - }; -} - - -function ESCategoryModalController($scope, UIUtils, $timeout, parameters) { - 'ngInject'; - - $scope.loading = true; - $scope.allCategories = []; - $scope.categories = []; - this.searchText = ''; - - // modal title - this.title = parameters && parameters.title; - - $scope.afterLoad = function(result) { - $scope.categories = result; - $scope.allCategories = result; - $scope.loading = false; - $timeout(function() { - UIUtils.ink(); - }, 10); - }; - - this.doSearch = function() { - var searchText = this.searchText.toLowerCase().trim(); - if (searchText.length > 1) { - $scope.loading = true; - $scope.categories = $scope.allCategories.reduce(function(result, cat) { - if (cat.parent && cat.name.toLowerCase().search(searchText) != -1) { - return result.concat(cat); - } - return result; - }, []); - - $scope.loading = false; - } - else { - $scope.categories = $scope.allCategories; - } - }; - - // load categories - if (parameters && parameters.categories) { - $scope.afterLoad(parameters.categories); - } - else if (parameters && parameters.load) { - parameters.load() - .then(function(res){ - $scope.afterLoad(res); - }); - } - -} - - - -function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { - 'ngInject'; - - $scope.loading = true; - $scope.defaultCommentSize = 5; - $scope.formData = {}; - $scope.comments = {}; - - $scope.$on('$recordView.enter', function(e, state) { - // second call (when using cached view) - if (!$scope.loading && $scope.id) { - $scope.load($scope.id, {animate: false}); - } - }); - - $scope.$on('$recordView.load', function(event, id, service) { - $scope.id = id || $scope.id; - $scope.service = service || $scope.service; - console.debug("[ES] [comment] Initialized service with: " + service.id); - if ($scope.id) { - $scope.load($scope.id); - } - }); - - $scope.load = function(id, options) { - options = options || {}; - options.from = options.from || 0; - options.size = options.size || $scope.defaultCommentSize; - options.animate = angular.isDefined(options.animate) ? options.animate : true; - options.loadAvatarAllParent = angular.isDefined(options.loadAvatarAllParent) ? options.loadAvatarAllParent : true; - $scope.loading = true; - return $scope.service.load(id, options) - .then(function(data) { - if (!options.animate && data.result.length) { - _.forEach(data.result, function(cmt) { - cmt.isnew = true; - }); - } - $scope.comments = data; - $scope.comments.hasMore = (data.total > data.result.length); - $scope.loading = false; - $scope.service.changes.start(id, data, $scope); - - // Set Motion - $scope.motion.show({ - selector: '.comments .item', - ink: false - }); - }); - }; - - $scope.$on('$recordView.beforeLeave', function(){ - if ($scope.comments) { - if (!$scope.service) { - console.error('[comment] Comment controller has no service ! Unable to listen changes...'); - return; - } - $scope.service.changes.stop($scope.comments); - } - }); - - $scope.showMore = function(){ - var from = 0; - var size = -1; - $scope.load($scope.id, {from: from, size: size, loadAvatarAllParent: false}) - .then(function() { - // Set Motion - $scope.motion.show({ - selector: '.card-avatar' - }); - }); - }; - - $scope.save = function() { - if (!$scope.formData.message || !$scope.formData.message.length) return; - - $scope.loadWallet({minData: true, auth: true}) - .then(function() { - UIUtils.loading.hide(); - var comment = $scope.formData; - $scope.formData = {}; - $scope.focusNewComment(); - return $scope.service.save($scope.id, $scope.comments, comment); - }) - .then(function() { - $scope.comments.total++; - }) - .catch(UIUtils.onError('COMMENTS.ERROR.FAILED_SAVE_COMMENT')); - }; - - $scope.share = function(event, comment) { - var params = angular.copy($state.params); - var stateUrl; - if (params.anchor) { - params.anchor= $filter('formatHash')(comment.id); - stateUrl = $state.href($state.current.name, params, {absolute: true}); - } - else { - stateUrl = $state.href($state.current.name, params, {absolute: true}) + '/' + $filter('formatHash')(comment.id); - } - var index = _.findIndex($scope.comments.result, {id: comment.id}); - var url = stateUrl + '?u=' + (comment.uid||$filter('formatPubkey')(comment.issuer)); - UIUtils.popover.show(event, { - templateUrl: 'templates/common/popover_share.html', - scope: $scope, - bindings: { - titleKey: 'COMMENTS.POPOVER_SHARE_TITLE', - titleValues: {number: index ? index + 1 : 1}, - date: comment.creationTime, - value: url, - postUrl: stateUrl, - postMessage: comment.message - }, - autoselect: '.popover-share input' - }); - }; - - $scope.edit = function(comment) { - var newComment = new Comment(); - newComment.copy(comment); - $scope.formData = newComment; - }; - - $scope.remove = function(comment) { - if (!comment) {return;} - comment.remove(); - $scope.comments.total--; - }; - - $scope.reply = function(parent) { - if (!parent || !parent.id) {return;} - - $scope.formData = { - parent: parent - }; - - $scope.focusNewComment(true); - }; - - $scope.cancel = function() { - $scope.formData = {}; - $scope.focusNewComment(); - }; - - $scope.focusNewComment = function(forceIfSmall) { - if (!UIUtils.screen.isSmall()) { - $focus('comment-form-textarea'); - } - else { - if (forceIfSmall) $focus('comment-form-input'); - } - }; - - $scope.removeParentLink = function() { - delete $scope.formData.parent; - delete $scope.formData.reply_to; - $scope.focusNewComment(); - }; - - $scope.toggleExpandedReplies = function(comment, index) { - comment.expandedReplies = comment.expandedReplies || {}; - comment.expandedReplies[index] = !comment.expandedReplies[index]; - }; - - $scope.toggleExpandedParent = function(comment, index) { - comment.expandedParent = comment.expandedParent || {}; - comment.expandedParent[index] = !comment.expandedParent[index]; - }; -} - -function ESSocialsEditController($scope, $focus, $filter, UIUtils, SocialUtils) { - 'ngInject'; - - $scope.socialData = { - url: null - }; - - $scope.addSocialNetwork = function() { - if (!$scope.socialData.url || $scope.socialData.url.trim().length === 0) { - return; - } - $scope.formData.socials = $scope.formData.socials || []; - var url = $scope.socialData.url.trim(); - - var exists = _.findWhere($scope.formData.socials, {url: url}); - if (exists) { // duplicate entry - $scope.socialData.url = ''; - return; - } - - var social = SocialUtils.get(url); - if (!social) { - UIUtils.alert.error('PROFILE.ERROR.INVALID_SOCIAL_NETWORK_FORMAT'); - $focus('socialUrl'); - return; // stop here - } - $scope.formData.socials.push(social); - $scope.socialData.url = ''; - - // Set Motion - $scope.motion.show({ - selector: '#social-' + $filter('formatSlug')(social.url), - startVelocity: 10000 - }); - }; - - $scope.editSocialNetwork = function(index) { - var social = $scope.formData.socials[index]; - $scope.formData.socials.splice(index, 1); - $scope.socialData.url = social.url; - $focus('socialUrl'); - }; - - $scope.filterFn = function(social) { - return !social.recipient || social.valid; - }; -} - -function ESSocialsViewController($scope) { - 'ngInject'; - - $scope.openSocial = function(event, social) { - return $scope.openLink(event, social.url, { - type: social.type - }); - }; - - - $scope.filterFn = function(social) { - return !social.recipient || social.valid; - }; - -} - - - -function ESAvatarModalController($scope) { - - $scope.formData = { - initCrop: false, - imageCropStep: 0, - imgSrc: undefined, - result: undefined, - resultBlob: undefined - }; - - $scope.openFileSelector = function() { - var fileInput = angular.element(document.querySelector('.modal-avatar #fileInput')); - if (fileInput && fileInput.length > 0) { - fileInput[0].click(); - } - }; - - $scope.fileChanged = function(e) { - - var files = e.target.files; - var fileReader = new FileReader(); - fileReader.readAsDataURL(files[0]); - - fileReader.onload = function(e) { - var res = this.result; - $scope.$applyAsync(function() { - $scope.formData.imgSrc = res; - }); - }; - }; - - $scope.doNext = function() { - if ($scope.formData.imageCropStep == 2) { - $scope.doCrop(); - } - else if ($scope.formData.imageCropStep == 3) { - $scope.closeModal($scope.formData.result); - } - }; - - $scope.doCrop = function() { - $scope.formData.initCrop = true; - }; - - $scope.clear = function() { - $scope.formData = { - initCrop: false, - imageCropStep: 1, - imgSrc: undefined, - result: undefined, - resultBlob: undefined - }; - }; - -} - - -function ESPositionEditController($scope, csConfig, esGeo, ModalUtils) { - 'ngInject'; - - // The default country used for address localisation - var defaultCountry = csConfig.plugins && csConfig.plugins.es && csConfig.plugins.es.defaultCountry; - - var loadingCurrentPosition = false; - $scope.formPosition = { - loading: false, - enable: undefined - }; - - $scope.tryToLocalize = function() { - if ($scope.formPosition.loading || loadingCurrentPosition) return; - - var searchText = $scope.getAddressToSearch(); - - // No address, so try to localize by device - if (!searchText) { - loadingCurrentPosition = true; - return esGeo.point.current() - .then($scope.updateGeoPoint) - .then(function() { - loadingCurrentPosition = false; - }) - .catch(function(err) { - console.error(err); // Silent - loadingCurrentPosition = false; - //$scope.form.geoPoint.$setValidity('required', false); - }); - } - - $scope.formPosition.loading = true; - return esGeo.point.searchByAddress(searchText) - .then(function(res) { - if (res && res.length == 1) { - return $scope.updateGeoPoint(res[0]); - } - return $scope.openSearchLocationModal({ - text: searchText, - results: res||[], - forceFallback: !res || !res.length // force fallback search first - }); - }) - .then(function() { - $scope.formPosition.loading = false; - }) - .catch(function(err) { - console.error(err); // Silent - $scope.formPosition.loading = false; - }); - }; - - $scope.onCityChanged = function() { - if ($scope.loading) return; - if ($scope.form) { - $scope.form.$valid = undefined; - } - if ($scope.formPosition.enable) { - return $scope.tryToLocalize(); - } - }; - - $scope.onUseGeopointChanged = function() { - if ($scope.loading) return; - if (!$scope.formPosition.enable) { - if ($scope.formData.geoPoint) { - $scope.formData.geoPoint = null; - //$scope.form.geoPoint.$setValidity('required', true); - $scope.dirty = true; - } - } - else { - $scope.tryToLocalize(); - } - }; - - $scope.onGeopointChanged = function() { - if ($scope.loading) { - $scope.formPosition.enable = $scope.formData.geoPoint && !!$scope.formData.geoPoint.lat && !!$scope.formData.geoPoint.lon; - } - }; - $scope.$watch('formData.geoPoint', $scope.onGeopointChanged); - - $scope.getAddressToSearch = function() { - return $scope.formData.address && $scope.formData.city ? - [$scope.formData.address.trim(), $scope.formData.city.trim()].join(', ') : - $scope.formData.city || $scope.formData.address || $scope.formData.location ; - }; - - $scope.updateGeoPoint = function(res) { - // user cancel - if (!res || !res.lat || !res.lon) { - // nothing to do - return; - } - - $scope.dirty = true; - $scope.formData.geoPoint = $scope.formData.geoPoint || {}; - $scope.formData.geoPoint.lat = parseFloat(res.lat); - $scope.formData.geoPoint.lon = parseFloat(res.lon); - - if (res.address && res.address.city) { - var cityParts = [res.address.city]; - if (res.address.postcode) { - cityParts.push(res.address.postcode); - } - if (res.address.country != defaultCountry) { - cityParts.push(res.address.country); - } - $scope.formData.city = cityParts.join(', '); - } - }; - - /* -- modal -- */ - - $scope.openSearchLocationModal = function(options) { - - options = options || {}; - - var parameters = { - text: options.text || $scope.getAddressToSearch(), - results: options.results, - fallbackText: options.fallbackText || $scope.formData.city, - forceFallback: angular.isDefined(options.forceFallback) ? options.forceFallback : undefined - }; - - return ModalUtils.show( - 'plugins/es/templates/common/modal_location.html', - 'ESSearchPositionModalCtrl', - parameters, - { - focusFirstInput: true - //,scope: $scope - } - ) - .then($scope.updateGeoPoint); - }; -} - - -function ESLookupPositionController($scope, $q, csConfig, esGeo, ModalUtils) { - 'ngInject'; - - // The default country used for address localisation - var defaultCountry = csConfig.plugins && csConfig.plugins.es && csConfig.plugins.es.defaultCountry; - var loadingPosition = false; - - $scope.geoDistanceLabels = [5,10,20,50,100,250,500].reduce(function(res, distance){ - res[distance] = { - labelKey: 'LOCATION.DISTANCE_OPTION', - labelParams: {value: distance} - }; - return res; - }, {}); - $scope.geoDistances = _.keys($scope.geoDistanceLabels); - - $scope.searchPosition = function(searchText) { - if (loadingPosition) return $q.when(); - - loadingPosition = true; - - // No address, so try to localize by device - var promise = !searchText ? - esGeo.point.current() : - esGeo.point.searchByAddress(searchText) - .then(function(res) { - if (res && res.length == 1) { - res[0].exact = true; - return res[0]; - } - return $scope.openSearchLocationModal({ - text: searchText, - results: res||[], - forceFallback: !res || !res.length // force fallback search first - }) - .then(function(res) { - // Compute point name - if (res && res.address && res.address.city) { - var cityParts = [res.address.city]; - if (res.address.postcode) { - cityParts.push(res.address.postcode); - } - if (res.address.country != defaultCountry) { - cityParts.push(res.address.country); - } - res.shortName = cityParts.join(', '); - } - return res; - }); - }); - - promise - .then(function(res) { - - loadingPosition = false; - - // user cancel - if (!res || !res.lat || !res.lon) return; - - return { - lat: parseFloat(res.lat), - lon: parseFloat(res.lon), - name: res.shortName, - exact: res.exact - }; - - }) - .catch(function(err) { - console.error(err); // Silent - loadingPosition = false; - }); - - return promise; - }; - - - /* -- modal -- */ - - $scope.openSearchLocationModal = function(options) { - - options = options || {}; - - var parameters = { - text: options.text || $scope.getAddressToSearch(), - results: options.results, - fallbackText: options.fallbackText || $scope.search.location, - forceFallback: angular.isDefined(options.forceFallback) ? options.forceFallback : undefined - }; - - return ModalUtils.show( - 'plugins/es/templates/common/modal_location.html', - 'ESSearchPositionModalCtrl', - parameters, - { - focusFirstInput: true - //,scope: $scope - } - ); - }; -} - -function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, UIUtils, csConfig, esGeo) { - 'ngInject'; - - // The default country used for address localisation - var defaultCountry = csConfig.plugins && csConfig.plugins.es && csConfig.plugins.es.defaultCountry; - //$scope.smallscreen = angular.isDefined($scope.smallscreen) ? $scope.smallscreen : UIUtils.screen.isSmall(); - - var loadingPosition = false; - var minLength = 3; - $scope.locations = undefined; - $scope.selectLocationIndex = -1; - - $scope.onKeydown = function(e) { - - switch(e.keyCode) - { - case 27://Esc - $scope.hideDropdown(); - break; - case 13://Enter - if($scope.locations && $scope.locations.length) - $scope.onEnter(); - break; - case 38://Up - $scope.onArrowUpOrDown(-1); - e.preventDefault(); - break; - case 40://Down - $scope.onArrowUpOrDown(1); - e.preventDefault(); - break; - case 8://Backspace - case 45://Insert - case 46://Delete - break; - case 37://Left - case 39://Right - case 16://Shift - case 17://Ctrl - case 35://End - case 36://Home - break; - default://All keys - $scope.showDropdown(); - } - }; - - $scope.onEnter = function() { - if ($scope.selectLocationIndex > -1) { - $scope.selectLocation($scope.locations[$scope.selectLocationIndex]); - } - else { - $scope.selectLocation($scope.locations[0]); - } - }; - - $scope.onArrowUpOrDown = function(velocity) { - if (!$scope.locations) return; - - $scope.selectLocationIndex+=velocity; - if ($scope.selectLocationIndex >= $scope.locations.length) { - $scope.selectLocationIndex = 0; - } - if ($scope.selectLocationIndex < 0) { - $scope.selectLocationIndex = $scope.locations.length-1; - } - - _.forEach($scope.locations||[], function(item, index) { - item.selected = (index == $scope.selectLocationIndex); - }); - - // TODO: scroll to item ? - }; - - $scope.onLocationChanged = function() { - if (loadingPosition || $scope.search.loading) return; - $scope.search.geoPoint = undefined; // reset geo point - - $scope.showDropdown(); - }; - - $scope.showDropdown = function() { - var text = $scope.search.location && $scope.search.location.trim(); - if (!text || text.length < minLength) { - $scope.locations = undefined; - return $q.when(); // nothing to search - } - - loadingPosition = true; - - // Execute the given query - return esGeo.point.searchByAddress(text) - .then(function(res) { - loadingPosition = false; - $scope.locations = res||[]; - $scope.license = res && res.length && res[0].license; - }) - .catch(function(err) { - $scope.hideDropdown(); - throw err; - }); - }; - - $scope.hideDropdown = function(force) { - if (force) { - $scope.locations = undefined; - $scope.selectLocationIndex = -1; - $scope.license = undefined; - loadingPosition = false; - return; - } - - return $timeout(function() { - if (loadingPosition) return; - $scope.locations = undefined; - $scope.license = undefined; - loadingPosition = false; - }, 500); - }; - - $scope.selectLocation = function(res, exactMatch) { - loadingPosition = true; // avoid event - if (res) { - // Update position - $scope.search.geoPoint = $scope.search.geoPoint || {}; - $scope.search.geoPoint.lat = parseFloat(res.lat); - $scope.search.geoPoint.lon = parseFloat(res.lon); - - if (exactMatch) { - $scope.search.geoPoint.exact = true; - } - else { - // Update location name - if (res && res.address && res.address.city) { - var cityParts = [res.address.city]; - if (res.address.postcode) { - cityParts.push(res.address.postcode); - } - if (res.address.country != defaultCountry) { - cityParts.push(res.address.country); - } - $scope.search.location = cityParts.join(', '); - } - } - } - - $scope.hideDropdown(true); - }; - - /* -- modal -- */ - - $scope.openSearchLocationModal = function(options) { - - options = options || { - text: $scope.search.location - }; - - var parameters = { - text: options.text || $scope.search.location - }; - - return ModalUtils.show( - 'plugins/es/templates/common/modal_location.html', - 'ESSearchPositionModalCtrl', - parameters, - { - focusFirstInput: true - } - ) - .then($scope.selectLocation); - }; - -} - -function ESSearchPositionModalController($scope, $q, $translate, esGeo, parameters) { - 'ngInject'; - - $scope.search = { - text: parameters.text || '', - fallbackText: parameters.fallbackText || undefined, - forceFallback: angular.isDefined(parameters.forceFallback) ? parameters.forceFallback : false, - loading: false, - results: parameters.results || undefined - }; - - $scope.$on('modal.shown', function() { - // Load search - $scope.doSearch(true/*first search*/); - }); - - $scope.doSearch = function(firstSearch) { - - var text = $scope.search.text && $scope.search.text.trim(); - if (!text) { - return $q.when(); // nothing to search - } - - $scope.search.loading = true; - - // Compute alternative query text - var fallbackText = firstSearch && $scope.search.fallbackText && $scope.search.fallbackText.trim(); - fallbackText = fallbackText && fallbackText != text ? fallbackText : undefined; - - // Execute the given query - return ((firstSearch && $scope.search.forceFallback && $scope.search.results) ? - $q.when($scope.search.results) : - esGeo.point.searchByAddress(text) - ) - .then(function(res) { - if (res && res.length || !fallbackText) return res; - - // Fallback search - return $q.all([ - $translate('LOCATION.MODAL.ALTERNATIVE_RESULT_DIVIDER', {address: fallbackText}), - esGeo.point.searchByAddress(fallbackText) - ]) - .then(function (res) { - var dividerText = res[0]; - res = res[1]; - if (!res || !res.length) return res; - - return [{name: dividerText}].concat(res); - }); - }) - .then(function(res) { - $scope.search.loading = false; - $scope.search.results = res||[]; - - $scope.license = res && res.length && res[0].license; - }) - .catch(function(err) { - $scope.search.loading = false; - $scope.search.results = []; - $scope.license = undefined; - throw err; - }) - ; - }; - -} diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/common-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/common-controllers.js index bd7281b8e73add0f9bfb5b4f1e1b48a7f7dd3e96..ec021c5dc357153d93bab70c7cff1d8befc5ba8a 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/common-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/common-controllers.js @@ -2,12 +2,12 @@ ESPicturesEditController.$inject = ['$scope', 'UIUtils', '$q', 'Device']; ESSocialsEditController.$inject = ['$scope', '$focus', '$filter', 'UIUtils', 'SocialUtils']; ESSocialsViewController.$inject = ['$scope']; -ESCommentsController.$inject = ['$scope', '$filter', '$state', '$focus', 'UIUtils']; +ESCommentsController.$inject = ['$scope', '$filter', '$state', '$focus', '$timeout', '$anchorScroll', 'UIUtils']; ESCategoryModalController.$inject = ['$scope', 'UIUtils', '$timeout', 'parameters']; ESAvatarModalController.$inject = ['$scope']; ESPositionEditController.$inject = ['$scope', 'csConfig', 'esGeo', 'ModalUtils']; ESLookupPositionController.$inject = ['$scope', '$q', 'csConfig', 'esGeo', 'ModalUtils']; -ESSearchPositionItemController.$inject = ['$scope', '$q', '$timeout', 'ModalUtils', 'csConfig', 'esGeo']; +ESSearchPositionItemController.$inject = ['$scope', '$timeout', 'ModalUtils', 'csConfig', 'esGeo']; ESSearchPositionModalController.$inject = ['$scope', '$q', '$translate', 'esGeo', 'parameters'];angular.module('cesium.es.common.controllers', ['ngResource', 'cesium.es.services']) .controller('ESPicturesEditCtrl', ESPicturesEditController) @@ -61,19 +61,23 @@ function ESPicturesEditController($scope, UIUtils, $q, Device) { }; $scope.fileChanged = function(event) { + if (!event.target.files || !event.target.files.length) return; UIUtils.loading.show(); - return $q(function(resolve, reject) { - var file = event.target.files[0]; - UIUtils.image.resizeFile(file) - .then(function(imageData) { - $scope.pictures.push({ - src: imageData, - isnew: true // use to prevent visibility hidden (if animation) - }); - UIUtils.loading.hide(100); - resolve(); + var file = event.target.files[0]; + return UIUtils.image.resizeFile(file) + .then(function(imageData) { + $scope.pictures.push({ + src: imageData, + isnew: true // use to prevent visibility hidden (if animation) }); - }); + event.target.value = ""; // reset input[type=file] + UIUtils.loading.hide(100); + }) + .catch(function(err) { + console.error(err); + event.target.value = ""; // reset input[type=file] + UIUtils.loading.hide(); + }); }; $scope.removePicture = function(index){ @@ -151,7 +155,7 @@ function ESCategoryModalController($scope, UIUtils, $timeout, parameters) { -function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { +function ESCommentsController($scope, $filter, $state, $focus, $timeout, $anchorScroll, UIUtils) { 'ngInject'; $scope.loading = true; @@ -160,8 +164,12 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { $scope.comments = {}; $scope.$on('$recordView.enter', function(e, state) { + // First enter + if ($scope.loading) { + $scope.anchor = state && state.stateParams.anchor; + } // second call (when using cached view) - if (!$scope.loading && $scope.id) { + else if (!$scope.loading && $scope.id) { $scope.load($scope.id, {animate: false}); } }); @@ -169,15 +177,21 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { $scope.$on('$recordView.load', function(event, id, service) { $scope.id = id || $scope.id; $scope.service = service || $scope.service; - console.debug("[ES] [comment] Initialized service with: " + service.id); + console.debug("[ES] [comment] Will use {" + service.index + "} service"); if ($scope.id) { - $scope.load($scope.id); + $scope.load($scope.id) + .then(function() { + // Scroll to anchor + $scope.scrollToAnchor(); + }); } }); $scope.load = function(id, options) { options = options || {}; options.from = options.from || 0; + // If anchor has been defined, load all comments + options.size = options.size || ($scope.anchor && -1/*all*/); options.size = options.size || $scope.defaultCommentSize; options.animate = angular.isDefined(options.animate) ? options.animate : true; options.loadAvatarAllParent = angular.isDefined(options.loadAvatarAllParent) ? options.loadAvatarAllParent : true; @@ -212,6 +226,25 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { } }); + $scope.scrollToAnchor = function() { + if (!$scope.anchor) return; + var elemList = document.getElementsByName($scope.anchor); + // Waiting for the element + if (!elemList || !elemList.length) { + return $timeout($scope.scrollToAnchor, 500); + } + // If many, remove all anchor except the last one + for (var i = 0; i<elemList.length-1; i++) { + angular.element(elemList[i]).remove(); + } + // Scroll to the anchor + $anchorScroll($scope.anchor); + // Remove the anchor. This will the CSS class 'positive-100-bg' on the comment + $timeout(function () { + $scope.anchor = null; + }, 1500); + }; + $scope.showMore = function(){ var from = 0; var size = -1; @@ -224,6 +257,14 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { }); }; + $scope.onKeypress = function(event) { + // If Ctrl + Enter: submit + if (event && event.charCode == 10 && event.ctrlKey) { + $scope.save(); + event.preventDefault(); + } + }; + $scope.save = function() { if (!$scope.formData.message || !$scope.formData.message.length) return; @@ -357,8 +398,6 @@ function ESSocialsEditController($scope, $focus, $filter, UIUtils, SocialUtils) selector: '#social-' + $filter('formatSlug')(social.url), startVelocity: 10000 }); - - }; $scope.editSocialNetwork = function(index) { @@ -383,9 +422,8 @@ function ESSocialsEditController($scope, $focus, $filter, UIUtils, SocialUtils) function ESSocialsViewController($scope) { 'ngInject'; - $scope.openSocial = function($event, social) { - $event.stopPropagation(); - return $scope.openLink($event, social.url, { + $scope.openSocial = function(event, social) { + return $scope.openLink(event, social.url, { type: social.type }); }; @@ -484,7 +522,6 @@ function ESPositionEditController($scope, csConfig, esGeo, ModalUtils) { .catch(function(err) { console.error(err); // Silent loadingCurrentPosition = false; - //$scope.form.geoPoint.$setValidity('required', false); }); } @@ -509,22 +546,24 @@ function ESPositionEditController($scope, csConfig, esGeo, ModalUtils) { }); }; - $scope.onCityChanged = function() { - if ($scope.loading) return; - if ($scope.form) { - $scope.form.$valid = undefined; - } - if ($scope.formPosition.enable) { - return $scope.tryToLocalize(); - } - }; + $scope.onCityChanged = function() { + if ($scope.loading) return; + if ($scope.formPosition.enable) { + if ($scope.formData.geoPoint) { + // Invalidate the position + $scope.formData.geoPoint.lat = undefined; + $scope.formData.geoPoint.lon = undefined; + } + return $scope.tryToLocalize(); + } + }; $scope.onUseGeopointChanged = function() { if ($scope.loading) return; if (!$scope.formPosition.enable) { if ($scope.formData.geoPoint) { - $scope.formData.geoPoint = null; - //$scope.form.geoPoint.$setValidity('required', true); + $scope.formData.geoPoint.lat = undefined; + $scope.formData.geoPoint.lon = undefined; $scope.dirty = true; } } @@ -698,7 +737,7 @@ function ESLookupPositionController($scope, $q, csConfig, esGeo, ModalUtils) { }; } -function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConfig, esGeo) { +function ESSearchPositionItemController($scope, $timeout, ModalUtils, csConfig, esGeo) { 'ngInject'; // The default country used for address localisation @@ -782,15 +821,20 @@ function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConf $scope.showDropdown = function() { var text = $scope.search.location && $scope.search.location.trim(); if (!text || text.length < minLength) { - $scope.locations = undefined; - return $q.when(); // nothing to search + return $scope.hideDropdown(true/*force, if still loading*/); } + // Compute a request id, to apply response only if current request + var requestId = ($scope.requestId && $scope.requestId + 1) || 1; + $scope.requestId = requestId; + loadingPosition = true; // Execute the given query return esGeo.point.searchByAddress(text) .then(function(res) { + if ($scope.requestId != requestId) return; // Skip apply if not same request: + loadingPosition = false; $scope.locations = res||[]; $scope.license = res && res.length && res[0].license; @@ -802,6 +846,7 @@ function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConf }; $scope.hideDropdown = function(force) { + // force, even if still loading if (force) { $scope.locations = undefined; $scope.selectLocationIndex = -1; diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/document-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/document-controllers.js index 88d65797258848976912c3527b70791822a931df..3dc5ed04a5780eac7090f522067d967450bbcf33 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/document-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/document-controllers.js @@ -148,7 +148,7 @@ function ESDocumentLookupController($scope, $ionicPopover, $location, $timeout, }); }; - $scope.remove = function(index) { + $scope.remove = function(index, options) { var doc = $scope.search.results[index]; if (!doc) return; @@ -189,26 +189,20 @@ function ESDocumentLookupController($scope, $ionicPopover, $location, $timeout, /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/document/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/document/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/group-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/group-controllers.js index 8ac8b51239dc03a9d66a7e39d56bfb98384fa4c6..80b24cf84774e9f8d455ea77c4b94eec968226a6 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/group-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/group-controllers.js @@ -188,7 +188,9 @@ function ESGroupViewController($scope, $state, $ionicPopover, $ionicHistory, $tr $scope.formData = {}; $scope.id = null; $scope.pictures = []; + $scope.canEdit = false; $scope.loading = true; + $scope.motion = UIUtils.motion.fadeSlideIn; $scope.$on('$ionicView.enter', function(e, state) { if (state.stateParams && state.stateParams.id) { // Load by id @@ -211,7 +213,7 @@ function ESGroupViewController($scope, $state, $ionicPopover, $ionicHistory, $tr $scope.id = data.id; $scope.formData = data.record; $scope.issuer= data.issuer; - $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer); + $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer) || csWallet.children.hasPubkey($scope.formData.issuer); $scope.pictures = data.record.pictures || []; delete data.record.pictures; // remove, as already stored in $scope.pictures @@ -265,26 +267,20 @@ function ESGroupViewController($scope, $state, $ionicPopover, $ionicHistory, $tr /* -- modals & popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/group/view_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/group/view_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; @@ -382,7 +378,7 @@ function ESGroupEditController($scope, esGroup, UIUtils, $state, $q, Device, .then(function(){ var json = $scope.formData; - json.time = esHttp.date.now(); + json.time = moment().utc().unix(); // Resize pictures json.picturesCount = $scope.pictures.length; @@ -412,7 +408,7 @@ function ESGroupEditController($scope, esGroup, UIUtils, $state, $q, Device, .then(function(json){ // Create if (!$scope.id) { - json.creationTime = esHttp.date.now(); + json.creationTime = moment().utc().unix(); return esGroup.record.add(json); } // Update diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/invitation-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/invitation-controllers.js index 611792dab3fc85244a51ff856af2298c220b1c97..dadd75a992756e73e1feebbfc27a2e67226252ae 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/invitation-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/invitation-controllers.js @@ -1,7 +1,7 @@ -InvitationsController.$inject = ['$scope', '$q', '$ionicPopover', '$state', '$timeout', 'UIUtils', 'csSettings', 'csWallet', 'esHttp', 'esModals', 'esNotification', 'esInvitation']; -PopoverInvitationController.$inject = ['$scope', '$controller']; -NewInvitationModalController.$inject = ['$scope', '$q', 'Modals', 'UIUtils', 'csWallet', 'esHttp', 'esWallet', 'esInvitation'];angular.module('cesium.es.invitation.controllers', ['cesium.es.services']) +InvitationsController.$inject = ['$scope', '$q', '$ionicPopover', '$state', '$timeout', 'UIUtils', 'csWallet', 'esHttp', 'esModals', 'esNotification', 'esInvitation']; +PopoverInvitationController.$inject = ['$scope', '$controller', 'csWallet']; +NewInvitationModalController.$inject = ['$scope', '$q', 'Modals', 'UIUtils', 'csWallet', 'esHttp', 'esWallet', 'esInvitation', 'parameters'];angular.module('cesium.es.invitation.controllers', ['cesium.es.services']) .config(['$stateProvider', function($stateProvider) { 'ngInject'; @@ -9,7 +9,7 @@ NewInvitationModalController.$inject = ['$scope', '$q', 'Modals', 'UIUtils', 'cs $stateProvider .state('app.view_invitations', { - url: "/invitations", + url: "/invitations?id", views: { 'menuContent': { templateUrl: "plugins/es/templates/invitation/view_invitations.html", @@ -20,6 +20,19 @@ NewInvitationModalController.$inject = ['$scope', '$q', 'Modals', 'UIUtils', 'cs auth: true } }) + + .state('app.view_invitations_by_id', { + url: "/wallets/:id/invitations", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/invitation/view_invitations.html", + controller: 'InvitationsCtrl' + } + }, + data: { + login: true + } + }) ; }]) @@ -30,7 +43,7 @@ NewInvitationModalController.$inject = ['$scope', '$q', 'Modals', 'UIUtils', 'cs .controller('ESNewInvitationModalCtrl', NewInvitationModalController) ; -function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUtils, csSettings, csWallet, +function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUtils, csWallet, esHttp, esModals, esNotification, esInvitation) { 'ngInject'; @@ -49,16 +62,37 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt } }; - $scope.$on('$ionicView.enter', function() { - if ($scope.search.loading) { - if (esHttp.isAlive()) { - $scope.load(); + var wallet; - // Reset unread counter - $scope.resetUnreadCount(); + $scope.setWallet = function(aWallet) { + wallet = aWallet; + }; + + $scope.$on('$ionicView.enter', function(e, state) { + if ($scope.search.loading) { + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); } - $scope.showFab('fab-new-invitation'); + $scope.loadWallet({ + wallet: wallet, + minData: true + }) + .then(function() { + + $scope.addListeners(); + + if (esHttp.isAlive()) { + $scope.load(); + + // Reset unread counter + $scope.resetUnreadCount(); + + $scope.showFab('fab-new-invitation'); + } + }); } }); @@ -67,7 +101,10 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt options.from = options.from || from || 0; options.size = options.size || size || defaultSearchLimit; - return esInvitation.load(options) + // Make sure wallet is init (need by PopoverInvitationCtrl) + wallet = wallet || csWallet; + + return esInvitation.load(options, wallet.data.keypair) .then(function(invitations) { $scope.search.results = invitations; $scope.search.loading = false; @@ -132,19 +169,18 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt }; $scope.resetUnreadCount = function() { - if ($scope.search.loading || !csWallet.data.invitations) { + if ($scope.search.loading || !wallet.data.invitations) { return $timeout($scope.resetUnreadCount, 2000); } - if (!csWallet.data.invitations.unreadCount) return; + if (!wallet.data.invitations.unreadCount) return; console.debug('[ES] [invitation] Resetting unread count'); - csWallet.data.invitations.unreadCount = 0; + wallet.data.invitations.unreadCount = 0; if (!$scope.search.results || !$scope.search.results.length) return; var lastNotification = $scope.search.results[0]; var readTime = lastNotification.time ? lastNotification.time : 0; - if (readTime && (!csSettings.data.plugins.es.invitations || csSettings.data.plugins.es.invitations.readTime != readTime)) { - csSettings.data.plugins.es.invitations = csSettings.data.plugins.es.invitations || {}; - csSettings.data.plugins.es.invitations.readTime = readTime; - csSettings.store(); + if (readTime && (!wallet.data.invitations.readTime || wallet.data.invitations.readTime != readTime)) { + wallet.data.invitations.readTime = readTime; + wallet.storeData(); } }; @@ -161,7 +197,7 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt return $q.all([ UIUtils.loading.show(), - esInvitation.deleteAll(csWallet.data.pubkey) + esInvitation.deleteAll(wallet.data.pubkey) ]) .then(function() { $scope.search.results.splice(0, $scope.search.results.length); // update list @@ -203,39 +239,44 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/invitation/popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/invitation/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; // Listeners - csWallet.api.data.on.logout($scope, $scope.resetData); - esHttp.api.node.on.stop($scope, $scope.resetData); - esHttp.api.node.on.start($scope, $scope.load); - esInvitation.api.data.on.new($scope, $scope.onNewInvitation); - + $scope.addListeners = function() { + if (!wallet) throw "Controller wallet not set !"; + + $scope.listeners = [ + esHttp.api.node.on.stop($scope, $scope.resetData), + esHttp.api.node.on.start($scope, $scope.load), + wallet.api.data.on.logout($scope, $scope.resetData) + ]; + + if (wallet.isDefault()) { + // Subscribe to new invitation + $scope.listeners.push( + esInvitation.api.data.on.new($scope, $scope.onNewInvitation) + ); + } + }; } -function PopoverInvitationController($scope, $controller) { +function PopoverInvitationController($scope, $controller, csWallet) { 'ngInject'; // Initialize the super class and extend it. @@ -244,8 +285,12 @@ function PopoverInvitationController($scope, $controller) { // Disable list effects $scope.motion = null; + // Set the wallet to use + $scope.setWallet(csWallet); + $scope.$on('popover.shown', function() { if ($scope.search.loading) { + $scope.addListeners(); $scope.load(); } }); @@ -266,14 +311,71 @@ function PopoverInvitationController($scope, $controller) { } -function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esHttp, esWallet, esInvitation) { +function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esHttp, esWallet, esInvitation, parameters) { 'ngInject'; + // Controller var + var wallet; + + // Scope var $scope.recipients = []; $scope.suggestions = []; $scope.formData = { - useComment: false + useComment: false, + walletId: null }; + $scope.enableSelectWallet = true; + + /* -- scope functions -- */ + + $scope.setParameters = function(parameters) { + if (!parameters) return; + if (!parameters.wallet || parameters.wallet === "default") { + $scope.formData.walletId = csWallet.id; + } + else { + $scope.formData.walletId = parameters.wallet; + } + }; + // Read default parameters + $scope.setParameters(parameters); + + $scope.load = function() { + $scope.enableSelectWallet = csWallet.children.count() > 0; + + wallet = $scope.enableSelectWallet && ($scope.formData.walletId ? csWallet.children.get($scope.formData.walletId) : csWallet) || csWallet; + $scope.formData.walletId = wallet.id; // update the walletId (could have changed) + if (!wallet.isDefault()) { + console.debug("[transfer] Using {" + wallet.id + "} wallet"); + } + + // Make to sure to load full wallet data (balance) + return wallet.login({sources: true, silent: true}) + .then(function(data) { + $scope.walletData = data; + UIUtils.ink({selector: '.modal-invitation .ink'}); + + if (!$scope.destPub || $scope.destUid) { + $scope.loading = false; + } + else { + // Fill the uid from the pubkey + return csWot.extend({pubkey: $scope.destPub}) + .then(function(res) { + $scope.destUid = res && (res.name || res.uid); + if ($scope.destUid) { + $scope.destPub = ''; + } + $scope.loading = false; + }); + } + }) + .catch(function(err){ + if (err == 'CANCELLED') return $scope.cancel(); // close the modal + UIUtils.onError('ERROR.LOGIN_FAILED')(err); + }); + }; + $scope.$on('modal.shown', $scope.load); // When changing use comment $scope.onUseCommentChanged = function() { @@ -304,21 +406,24 @@ function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esH return; } - if (!csWallet.isLogin()) return $scope.closeModal(); // should never happen + if (!wallet.isLogin()) return $scope.closeModal(); // should never happen - return $q.all([ - // Get keypair only once (if not done here, certification.send() with compute it many times) - esWallet.box.getKeypair(csWallet.data.keypair), - // Ask confirmation - UIUtils.alert.confirm('INVITATION.CONFIRM.SEND_INVITATIONS_TO_CERTIFY', undefined, {okText: 'COMMON.BTN_SEND'}) - ]) + // Make sure user is still authenticated + return wallet.auth({silent: true}) + .then(function() { + return $q.all([ + // Get keypair only once (if not done here, esInvitation.send() with compute it many times) + esWallet.box.getKeypair(wallet.data.keypair), + // Ask confirmation + UIUtils.alert.confirm('INVITATION.CONFIRM.SEND_INVITATIONS_TO_CERTIFY', undefined, {okText: 'COMMON.BTN_SEND'}) + ]); + }) .then(function(res) { - if (!res) return; - var keypair = res[0]; - var confirm = res[1]; - if (!confirm) return; + var keypair = res && res[0]; + var confirm = res && res[1]; + if (!keypair || !confirm) return; UIUtils.loading.show(); - var time = esHttp.date.now(); // use same date for each invitation + var time = moment().utc().unix(); // use same date for each invitation var comment = $scope.formData.useComment && $scope.formData.comment && $scope.formData.comment.trim(); return $q.all( $scope.recipients.reduce(function (res, recipient) { @@ -328,14 +433,17 @@ function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esH return res; } var invitation = { - issuer: csWallet.data.pubkey, + issuer: wallet.data.pubkey, recipient: recipient.pubkey, time: time, content: [identity.uid, identity.pubkey].join('-'), comment: comment }; return res.concat( - esInvitation.send(invitation, keypair, 'certification')); + esInvitation.send(invitation, { + wallet: wallet, + type: 'certification' + })); }, [])); }, [])) .then(function() { @@ -387,5 +495,20 @@ function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esH $scope.suggestions = res; }); }; + + + $scope.showSelectWalletModal = function() { + if (!$scope.enableSelectWallet) return; + + return Modals.showSelectWallet() + .then(function(wallet) { + if (!wallet || $scope.formData.walletId === wallet.id) return; + console.debug("[transfer] Using {" + wallet.id + "} wallet"); + $scope.wallet = wallet; + $scope.walletData = wallet.data; + $scope.formData.walletId = wallet.id; + $scope.onAmountChanged(); + }); + }; } diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/message-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/message-controllers.js index af3292ce0375e35e26b38d1e7f6e30fc8aaae34c..558739d7d579139ca5878132020f9b8f8bfe259f 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/message-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/message-controllers.js @@ -1,11 +1,11 @@ -ESMessageAbstractListController.$inject = ['$scope', '$state', '$translate', '$ionicHistory', '$ionicPopover', '$timeout', '$filter', 'csWallet', 'esModals', 'UIUtils', 'esMessage']; +ESMessageAbstractListController.$inject = ['$scope', '$state', '$translate', '$ionicHistory', '$ionicPopover', '$timeout', 'csWallet', 'esModals', 'UIUtils', 'esMessage']; ESMessageInboxListController.$inject = ['$scope', '$controller']; ESMessageOutboxListController.$inject = ['$scope', '$controller']; -ESMessageComposeController.$inject = ['$scope', '$controller', 'UIUtils']; +ESMessageComposeController.$inject = ['$scope', '$controller']; ESMessageComposeModalController.$inject = ['$scope', 'Modals', 'UIUtils', 'csWallet', 'esHttp', 'esMessage', 'parameters']; -ESMessageViewController.$inject = ['$scope', '$state', '$timeout', '$translate', '$ionicHistory', '$ionicPopover', 'UIUtils', 'esModals', 'esMessage']; -PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', 'esHttp', 'esMessage', 'esModals'];angular.module('cesium.es.message.controllers', ['cesium.es.services']) +ESMessageViewController.$inject = ['$scope', '$state', '$timeout', '$translate', '$ionicHistory', '$ionicPopover', 'UIUtils', 'esModals', 'esMessage', 'csWallet']; +PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', 'esHttp', 'esMessage', 'esModals', '$timeout'];angular.module('cesium.es.message.controllers', ['cesium.es.services']) .config(['$stateProvider', function($stateProvider) { 'ngInject'; @@ -65,6 +65,51 @@ PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', ' } }) + .state('app.user_messages_by_id', { + url: "/wallets/:id/message", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/lookup_by_id.html" + } + } + }) + + .state('app.user_messages_by_id.tab_inbox', { + url: "/inbox", + views: { + 'tab_inbox': { + controller: 'ESMessageInboxListCtrl', + templateUrl: "plugins/es/templates/message/tabs/tab_list.html" + } + }, + data: { + large: 'app.user_messages_lg_inbox_by_id' + } + }) + + .state('app.user_messages_by_id.tab_outbox', { + url: "/outbox", + views: { + 'tab_outbox': { + controller: 'ESMessageOutboxListCtrl', + templateUrl: "plugins/es/templates/message/tabs/tab_list.html" + } + }, + data: { + large: 'app.user_messages_lg_outbox_by_id' + } + }) + + .state('app.user_messages_lg_inbox_by_id', { + url: "/wallets/:id/message/lg/inbox", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/lookup_lg.html", + controller: 'ESMessageInboxListCtrl' + } + } + }) + .state('app.user_messages_lg_outbox', { url: "/user/message/lg/outbox", views: { @@ -79,9 +124,19 @@ PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', ' } }) + .state('app.user_messages_lg_outbox_by_id', { + url: "/wallets/:id/message/lg/outbox", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/lookup_lg.html", + controller: 'ESMessageOutboxListCtrl' + } + } + }) + .state('app.user_new_message', { cache: false, - url: "/user/message/new?pubkey&uid&title&content", + url: "/user/message/new?pubkey&uid&title&content&isReply", views: { 'menuContent': { templateUrl: "plugins/es/templates/message/compose.html", @@ -92,7 +147,7 @@ PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', ' .state('app.user_view_message', { cache: false, - url: "/user/message/view/:type/:id", + url: "/user/message/view/:type/:messageId", views: { 'menuContent': { templateUrl: "plugins/es/templates/message/view_message.html", @@ -105,6 +160,17 @@ PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', ' } }) + .state('app.user_view_message_by_id', { + cache: false, + url: "/wallets/:id/message/view/:type/:messageId", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/view_message.html", + controller: 'ESMessageViewCtrl' + } + } + }) + ; }]) @@ -124,11 +190,13 @@ PopoverMessageController.$inject = ['$scope', 'UIUtils', '$state', 'csWallet', ' ; -function ESMessageAbstractListController($scope, $state, $translate, $ionicHistory, $ionicPopover, $timeout, $filter, +function ESMessageAbstractListController($scope, $state, $translate, $ionicHistory, $ionicPopover, $timeout, csWallet, esModals, UIUtils, esMessage) { 'ngInject'; var defaultSearchLimit = 40; + var wallet; + var selectPrevented = false; $scope.search = { loading: true, @@ -144,33 +212,45 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto $scope.fabButtonNewMessageId = undefined; - $scope.$on('$ionicView.enter', function(e, state) { + $scope.enter = function(s, state) { + // First enter + if ($scope.search.loading) { + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } - $scope.loadWallet({minData: true}) - .then(function() { - if (!$scope.entered) { - $scope.entered = true; - $scope.type = $scope.type || state.stateParams && state.stateParams.type || 'inbox'; - $scope.load(); - } + $scope.isDefaultWallet = wallet.isDefault(); + $scope.walletId = wallet.id; - if ($scope.fabButtonNewMessageId) { - $scope.showFab($scope.fabButtonNewMessageId); - } - }) - .catch(function(err) { - if ('CANCELLED' === err) { - $ionicHistory.nextViewOptions({ - historyRoot: true - }); - $state.go('app.home'); - } - }); - }); + wallet.auth({minData: true}) + .then(function() { + if (!$scope.entered) { + $scope.entered = true; + $scope.type = $scope.type || state.stateParams && state.stateParams.type || 'inbox'; + $scope.load(); + } - $scope.refresh = function(silent) { - return $scope.load(undefined, undefined, silent); + if ($scope.fabButtonNewMessageId) { + $scope.showFab($scope.fabButtonNewMessageId); + } + }) + .catch(function(err) { + if ('CANCELLED' === err) { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + $scope.showHome(); + } + }); + } + // Not first entering: refresh the view + else { + $scope.updateView(); + } }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function(from, size, silent) { @@ -181,6 +261,7 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto options.summary = false; options.filter = ($scope.search.type == 'text' && $scope.search.text && $scope.search.text.trim().length > 0) ? $scope.search.text : undefined; + options.wallet = wallet; $scope.search.loading = !silent; return esMessage.load(options) @@ -208,15 +289,11 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto }); }; - $scope.setType = function(type) { - $scope.type = type; - $scope.load(); - }; - $scope.updateView = function() { if ($scope.motion && $scope.motion.ionListClass && $scope.search.results.length) { $scope.motion.show({selector: '.view-messages .list .item'}); } + $scope.$broadcast('$$rebind::rebind'); // notifier binder }; $scope.showMore = function() { @@ -261,9 +338,10 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE') .then(function(confirm) { if (confirm) { - esMessage.remove(message.id, $scope.type) + esMessage.remove(message.id, $scope.type, {walletId: $scope.walletId}) .then(function () { $scope.search.results.splice(index,1); // remove from messages array + $scope.updateView(); UIUtils.toast.show('MESSAGE.INFO.MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_MESSAGE_FAILED')); @@ -278,9 +356,10 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE_ALL') .then(function(confirm) { if (confirm) { - esMessage.removeAll($scope.type) + esMessage.removeAll($scope.type, {walletId: $scope.walletId}) .then(function () { $scope.search.results.splice(0,$scope.search.results.length); // reset array + $scope.updateView(); UIUtils.toast.show('MESSAGE.INFO.All_MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_All_MESSAGES_FAILED')); @@ -308,12 +387,45 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto return $scope.load(); }; + + $scope.refresh = function(silent) { + selectPrevented = true; // Will disable select() to open the message + return $scope.load(undefined, undefined, silent) + .then(function() { + selectPrevented = false; + }) + .catch(function() { + selectPrevented = false; + }); + }; + + $scope.select = function(message, event) { + if (event.isDefaultPrevented() || $scope.search.loading || selectPrevented) return; // skip + + // Add a timeout, to be sure the refres action was not called before + return $timeout(function() { + if (selectPrevented || event.isDefaultPrevented()) return; // skip + event.preventDefault(); + + if ($scope.walletId === 'default') { + return $state.go('app.user_view_message', {type: $scope.type, messageId:message.id}); + } + else { + return $state.go('app.user_view_message_by_id', {type: $scope.type, messageId:message.id, id: $scope.walletId}); + } + }, 200); + }; + /* -- Modals -- */ $scope.showNewMessageModal = function(parameters) { - return $scope.loadWallet({minData: true}) + return wallet.login({minData: true}) .then(function() { UIUtils.loading.hide(); + + parameters = parameters || {}; + parameters.wallet = $scope.walletId; + return esModals.showMessageCompose(parameters) .then(function(id) { if (id) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT'); @@ -335,7 +447,8 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto destUid: message.name||message.uid, title: prefix + message.title, content: content, - isReply: true + isReply: true, + wallet: $scope.walletId }); }) .then(function(sent) { @@ -346,26 +459,20 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/message/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/message/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; @@ -379,22 +486,23 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto if (index) { $scope.search.results.splice(index,1); // remove from messages array } + $scope.updateView(); }; esMessage.api.data.on.delete($scope, $scope.onMessageDelete); // Watch user sent message $scope.onNewOutboxMessage = function(id) { - if ($scope.type != 'outbox') return; + if ($scope.type !== 'outbox') return; // Add message sent to list - $scope.loading = true; + $scope.search.loading = true; return $timeout(function() { // Load the message sent - return esMessage.get(id, {type: $scope.type, summary: true}); + return esMessage.get(id, $scope.type, {summary: true, wallet: wallet}); }, 500 /*waiting ES propagation*/) .then(function(msg) { $scope.search.results.splice(0,0,msg); - $scope.loading = false; - $scope.motion.show({selector: '.view-messages .list .item'}); + $scope.search.loading = false; + $scope.updateView(); }) .catch(function() { $scope.loading = false; @@ -404,15 +512,15 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto // Watch received message $scope.onNewInboxMessage = function(notification) { - if ($scope.type != 'inbox' || !$scope.entered) return; + if ($scope.type !== 'inbox' || !$scope.entered || !wallet.isUserPubkey(notification.issuer)) return; // Add message sent to list - $scope.loading = true; + $scope.search.loading = true; // Load the the message - return esMessage.get(notification.id, {type: $scope.type, summary: true}) + return esMessage.get(notification.id, $scope.type, {summary: true, wallet: wallet}) .then(function(msg) { $scope.search.results.splice(0,0,msg); $scope.search.loading = false; - $scope.motion.show({selector: '.view-messages .list .item'}); + $scope.updateView(); }) .catch(function() { $scope.search.loading = false; @@ -458,47 +566,28 @@ function ESMessageOutboxListController($scope, $controller) { $scope.fabButtonNewMessageId = 'fab-add-message-record-outbox'; } -function ESMessageComposeController($scope, $controller, UIUtils) { +function ESMessageComposeController($scope, $controller) { 'ngInject'; // Initialize the super class and extend it. angular.extend(this, $controller('ESMessageComposeModalCtrl', {$scope: $scope, parameters: {}})); - $scope.$on('$ionicView.enter', function(e, state) { - if (state.stateParams) { - if (state.stateParams.pubkey) { - $scope.formData.destPub = state.stateParams.pubkey; - if (state.stateParams.uid) { - $scope.destUid = state.stateParams.uid; - $scope.destPub = ''; - } - else { - $scope.destUid = ''; - $scope.destPub = $scope.formData.destPub; - } - } - if (state.stateParams.title) { - $scope.formData.title = state.stateParams.title; - } + $scope.enter = function(e, state) { - if (state.stateParams.content) { - $scope.formData.content = state.stateParams.content; - } + // Apply state parameters + if (state && state.stateParams) { + $scope.setParameters(state.stateParams); } - $scope.loadWallet({minData: true}) - .then(function() { - UIUtils.loading.hide(); - }) - .catch(function(err){ - if (err === 'CANCELLED') { - $scope.showHome(); - } - }); - }); + // Load wallet + return $scope.load() + .then(UIUtils.loading.hide); + }; + $scope.$on('$ionicView.enter',$scope.enter); $scope.cancel = function() { + $scope.sending = false; $scope.showHome(); }; @@ -507,6 +596,7 @@ function ESMessageComposeController($scope, $controller, UIUtils) { }; $scope.closeModal = function() { + $scope.sending = false; $scope.showHome(); }; @@ -515,18 +605,79 @@ function ESMessageComposeController($scope, $controller, UIUtils) { function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHttp, esMessage, parameters) { 'ngInject'; + var wallet; + $scope.formData = { - title: parameters ? parameters.title : null, - content: parameters ? parameters.content : null, - destPub: parameters ? parameters.destPub : null + title: null, + content: null, + destPub: null, + walletId: null + }; + $scope.destUid = null; + $scope.destPub = null; + $scope.isReply = false; + $scope.enableSelectWallet = true; + $scope.sending = false; + + $scope.setParameters = function(parameters) { + if (!parameters) return; + + if (parameters.pubkey || parameters.destPub) { + $scope.formData.destPub = parameters.pubkey || parameters.destPub; + if (parameters.uid || parameters.destUid) { + $scope.destUid = parameters.uid || parameters.destUid; + $scope.destPub = ''; + } + else { + $scope.destUid = ''; + $scope.destPub = $scope.formData.destPub; + } + } + + if (parameters.title) { + $scope.formData.title = parameters.title; + } + + if (parameters.content) { + $scope.formData.content = parameters.content; + } + + $scope.isReply = parameters.isReply || false; + + if (parameters.wallet) { + $scope.formData.walletId = parameters.wallet; + } + }; + + // Read default parameters + $scope.setParameters(parameters); + + $scope.load = function() { + $scope.enableSelectWallet = csWallet.children.count() > 0; + + wallet = $scope.enableSelectWallet && ($scope.formData.walletId ? csWallet.children.get($scope.formData.walletId) : csWallet) || csWallet; + if (!wallet.isDefault()) { + console.debug("[message] Using {" + wallet.id + "} wallet"); + } + else { + console.debug("[message] Using default wallet"); + } + + return wallet.login({minData: true, silent: true}) + .then(function(data) { + $scope.walletData = data; + }) + .catch(function(err){ + if (err === 'CANCELLED') { + $scope.cancel(); + } + }); }; - $scope.destUid = parameters ? parameters.destUid : null; - $scope.destPub = (parameters && !parameters.destUid) ? parameters.destPub : null; - $scope.isResponse = parameters ? parameters.isResponse : false; + $scope.$on('modal.shown', $scope.load); $scope.doSend = function(forceNoContent) { $scope.form.$submitted=true; - if(!$scope.form.$valid /*|| !$scope.formData.destPub*/) { + if(!$scope.form.$valid) { return; } @@ -540,22 +691,36 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt }); } + $scope.sending = true; UIUtils.loading.show(); var data = { - issuer: csWallet.data.pubkey, + issuer: wallet.data.pubkey, recipient: $scope.formData.destPub, title: $scope.formData.title, content: $scope.formData.content, - time: esHttp.date.now() + time: moment().utc().unix() }; - esMessage.send(data) + esMessage.send(data, {wallet: wallet}) .then(function(id) { $scope.id=id; UIUtils.loading.hide(); $scope.closeModal(id); }) - .catch(UIUtils.onError('MESSAGE.ERROR.SEND_MSG_FAILED')); + .catch(function(err) { + $scope.sending = false; + // silent, if user cancelled; + if (err === 'CANCELLED') { + UIUtils.loading.hide(); + return; + } + UIUtils.onError('MESSAGE.ERROR.SEND_MSG_FAILED')(err); + }); + }; + + + $scope.cancel = function() { + $scope.closeModal(); }; /* -- Modals -- */ @@ -572,6 +737,7 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt $scope.destUid = ''; $scope.destPub = result.pubkey; } + $scope.destName = result.name || result.uid; $scope.formData.destPub = result.pubkey; // TODO focus on title field //$focus(''); @@ -579,11 +745,23 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt }); }; - $scope.cancel = function() { - $scope.closeModal(); + $scope.showSelectWalletModal = function() { + if (!$scope.enableSelectWallet) return; + + return Modals.showSelectWallet({ + showDefault: true, + showBalance: false + }) + .then(function(newWallet) { + if (!newWallet || (wallet && wallet.id === newWallet.id)) return; + wallet = newWallet; + $scope.walletData = wallet.data; + console.debug("[message] Using {" + wallet.id + "} wallet"); + }); }; + // TODO : for DEV only /*$timeout(function() { $scope.formData.destPub = 'G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU'; @@ -600,76 +778,96 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHistory, $ionicPopover, - UIUtils, esModals, esMessage) { + UIUtils, esModals, esMessage, csWallet) { 'ngInject'; $scope.formData = {}; $scope.id = null; $scope.loading = true; + var wallet; + $scope.$on('$ionicView.beforeEnter', function (event, viewData) { // Enable back button (workaround need for navigation outside tabs - https://stackoverflow.com/a/35064602) viewData.enableBack = UIUtils.screen.isSmall() ? true : viewData.enableBack; }); - $scope.$on('$ionicView.enter', function (e, state) { - if (state.stateParams && state.stateParams.id) { // Load by id - if ($scope.loading) { // prevent reload if same id - $scope.type = state.stateParams.type || 'inbox'; - - $scope.load(state.stateParams.id, $scope.type) - .then(function(message) { - $scope.loading = false; - UIUtils.loading.hide(); - if (!message) return; - - $scope.id = message.id; - $scope.formData = message; - $scope.canDelete = true; - $scope.motion.show({selector: '.view-message .list .item'}); - // Mark as read - if (!message.read) { - $timeout(function() { - // Message has NOT changed - if ($scope.id === message.id) { - esMessage.markAsRead(message, $scope.type) - .then(function() { - console.debug("[message] marked as read"); - }) - .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED')); - } - }, 2000); // 2s - } - }); + $scope.enter = function(e, state) { + // First enter + if ($scope.loading) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); } - $scope.showFab('fab-view-message-reply'); - } - else { - $state.go('app.user_message'); + $scope.isDefaultWallet = wallet.isDefault(); + $scope.walletId = wallet.id; + + var messageId = state.stateParams && state.stateParams.messageId; + $scope.type = state.stateParams.type || 'inbox'; + + // No message id: redirect + if (angular.isUndefined(messageId)) { + $scope.goBack(); + return; + } + + wallet.auth({minData: true}) + .then(function () { + return $scope.load(messageId, $scope.type); + }) + .then(function(message) { + + UIUtils.loading.hide(); + if (!message) return; // SKip + + $scope.updateView(message); + $scope.showFab('fab-view-message-reply'); + + // Mark as read + if (!message.read) { + $timeout(function() { + // Message has NOT changed + if ($scope.id === message.id) { + esMessage.markAsRead(message, {type: $scope.type, wallet: wallet}) + .then(function() { + console.debug("[message] marked as read"); + }) + .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED')); + } + }, 2000); // 2s + } + }); } - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function(id, type) { type = type || 'inbox'; - - return $scope.loadWallet({minData: true}) - .then(function() { - return esMessage.get(id, {type: type}); - }) + return esMessage.get(id, type, {wallet: wallet}) .catch(UIUtils.onError('MESSAGE.ERROR.LOAD_MESSAGE_FAILED')) .then(function(message) { if (!message.valid) { return UIUtils.alert.error(!$scope.isUserPubkey(message.recipient) ? 'MESSAGE.ERROR.USER_NOT_RECIPIENT' : 'MESSAGE.ERROR.NOT_AUTHENTICATED_MESSAGE', 'MESSAGE.ERROR.MESSAGE_NOT_READABLE') .then(function () { - $state.go('app.user_message', {type: type}); + $scope.goBack(true/*clear cache*/); }); } return message; }); }; + $scope.updateView = function(message) { + $scope.loading = false; + $scope.id = message.id; + $scope.formData = message; + $scope.canDelete = true; + $scope.motion.show({selector: '.view-message .list .item'}); + }; + $scope.delete = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); @@ -678,14 +876,9 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE') .then(function(confirm) { if (confirm) { - return esMessage.remove($scope.id, $scope.type) + return esMessage.remove($scope.id, $scope.type, {wallet: wallet}) .then(function () { - $ionicHistory.nextViewOptions({ - historyRoot: true - }); - $state.go($scope.type == 'inbox' ? 'app.user_message.tab_inbox' : 'app.user_message.tab_outbox', - {type: $scope.type} - ); + $scope.goBack(true/*clear page cache*/); UIUtils.toast.show('MESSAGE.INFO.MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_MESSAGE_FAILED')); @@ -693,36 +886,47 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis }); }; + $scope.goBack = function(clearPageCache) { + if (clearPageCache) { + $ionicHistory.clearCache($ionicHistory.currentView().stateId); // clear current view + } + $ionicHistory.nextViewOptions({historyRoot: true}); + if ($scope.isDefaultWallet) { + if ($scope.type) { + $state.go('app.user_message.tab_' + $scope.type, {type: $scope.type}); + } + } + else { + if ($scope.type) { + $state.go('app.user_messages_by_id.tab_' + $scope.type, {type: $scope.type, id: $scope.walletId}); + } + } + }; + /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/message/view_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/message/view_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; /* -- Modals -- */ $scope.showReplyModal = function() { - var recipientField = ($scope.type == 'inbox') ? 'issuer' : 'recipient'; + var recipientField = ($scope.type === 'inbox') ? 'issuer' : 'recipient'; $translate('MESSAGE.REPLY_TITLE_PREFIX') .then(function (prefix) { var content = $scope.formData.content ? $scope.formData.content.replace(/^/g, ' > ') : null; @@ -733,7 +937,8 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis destUid: $scope.formData.name||$scope.formData.uid, title: prefix + $scope.formData.title, content: content, - isReply: true + isReply: true, + walletId: wallet.id }); }) .then(function(sent) { @@ -748,10 +953,11 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis }; } -function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esMessage, esModals) { +function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esMessage, esModals, $timeout) { 'ngInject'; var defaultSearchLimit = 40; + var wallet; $scope.search = { loading : true, @@ -763,6 +969,15 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM $scope.$on('popover.shown', function() { if ($scope.search.loading) { + // TODO manage secondary wallets + wallet = $scope.walletId && csWallet.children.get($scope.walletId) || csWallet; + + /* -- wallet listeners -- */ + if (wallet.isDefault()) { + wallet.api.data.on.logout($scope, $scope.resetData); + esMessage.api.data.on.new($scope, $scope.onNewMessageNotification); + } + $scope.load(); } }); @@ -818,13 +1033,22 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM // Listen notifications changes $scope.onNewMessageNotification = function(notification) { if ($scope.search.loading || $scope.search.loadingMore) return; + + if (!wallet.isUserPubkey(notification.issuer)) return; // skip + + // Prepend to list $scope.search.results.splice(0,0,notification); $scope.updateView(); }; $scope.select = function(notification) { if (!notification.read) notification.read = true; - $state.go('app.user_view_message', {id: notification.id}); + if ($scope.walletId === 'default') { + $state.go('app.user_view_message', {messageId: notification.id}); + } + else { + $state.go('app.user_view_message_by_id', {messageId: notification.id, id: $scope.walletId}); + } $scope.closePopover(notification); }; @@ -841,18 +1065,23 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM /* -- Modals -- */ $scope.showNewMessageModal = function(parameters) { + $scope.closePopover(); - return esModals.showMessageCompose(parameters) - .then(function(id) { - if (id) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT'); - }); + + $timeout(function() { + parameters = parameters || {}; + parameters.walletId = wallet.id; + + esModals.showMessageCompose(parameters) + .then(function(id) { + if (id) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT'); + }); + }, 500); // Timeout need, to avoid freeze }; /* -- listeners -- */ - csWallet.api.data.on.logout($scope, $scope.resetData); esHttp.api.node.on.stop($scope, $scope.resetData); esHttp.api.node.on.start($scope, $scope.load); - esMessage.api.data.on.new($scope, $scope.onNewMessageNotification); } diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/network-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/network-controllers.js index b4a21096bd701064ab948c53e6ef918bcc6eda07..6c63082ec1fbd5b17f2ed515f588fec27212911e 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/network-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/network-controllers.js @@ -1,5 +1,4 @@ -ESNetworkViewExtendController.$inject = ['$scope', 'PluginService', 'esSettings']; angular.module('cesium.es.network.controllers', ['cesium.es.services']) .config(['PluginServiceProvider', 'csConfig', function(PluginServiceProvider, csConfig) { @@ -11,25 +10,11 @@ angular.module('cesium.es.network.controllers', ['cesium.es.services']) points: { 'buttons': { templateUrl: "plugins/es/templates/network/view_network_extend.html", - controller: 'ESNetworkViewExtendCtrl' + controller: 'ESExtensionCtrl' } } }) ; } - }]) + }]); - .controller('ESNetworkViewExtendCtrl', ESNetworkViewExtendController) -; - - -function ESNetworkViewExtendController($scope, PluginService, esSettings) { - 'ngInject'; - - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); - - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; - }); -} diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/notification-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/notification-controllers.js index 3db09cdfc070609b19b2c7ecda525d38d2a4f0b1..296310db9d77bf10bbb3265472c7346d1c0a866d 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/notification-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/notification-controllers.js @@ -1,6 +1,6 @@ -NotificationsController.$inject = ['$scope', '$rootScope', '$ionicPopover', '$state', '$timeout', 'UIUtils', 'esHttp', 'csSettings', 'csWallet', 'esNotification']; -PopoverNotificationsController.$inject = ['$scope', '$timeout', '$controller', 'UIUtils', '$state']; +NotificationsController.$inject = ['$scope', '$ionicPopover', '$state', '$timeout', 'UIUtils', 'esHttp', 'csWallet', 'esNotification']; +PopoverNotificationsController.$inject = ['$scope', '$timeout', '$controller', '$state', 'UIUtils', 'csWallet']; angular.module('cesium.es.notification.controllers', ['cesium.es.services']) @@ -21,6 +21,18 @@ angular.module('cesium.es.notification.controllers', ['cesium.es.services']) login: true } }) + .state('app.view_notifications_by_id', { + url: "/wallets/:id/notifications", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/notification/view_notifications.html", + controller: 'NotificationsCtrl' + } + }, + data: { + login: true + } + }) ; }]) @@ -30,11 +42,12 @@ angular.module('cesium.es.notification.controllers', ['cesium.es.services']) ; -function NotificationsController($scope, $rootScope, $ionicPopover, $state, $timeout, UIUtils, esHttp, csSettings, csWallet, esNotification) { +function NotificationsController($scope, $ionicPopover, $state, $timeout, UIUtils, esHttp, csWallet, esNotification) { 'ngInject'; var defaultSearchLimit = 40; + $scope.preventSelect = false; $scope.search = { loading : true, results: null, @@ -47,14 +60,32 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim } } }; + $scope.listeners = []; - $scope.$on('$ionicView.enter', function() { + var wallet; + + $scope.setWallet = function(aWallet) { + wallet = aWallet; + }; + + $scope.$on('$ionicView.enter', function(e, state) { if ($scope.search.loading) { - $scope.loadWallet({minData: true}) + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + wallet.login({ + minData: true + }) .then(function() { $scope.load(); UIUtils.loading.hide(); + $scope.addListeners(); + // Reset unread counter return $timeout(function() { $scope.resetUnreadCount(); @@ -68,16 +99,22 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim }; $scope.load = function(from, size, silent) { - if (!csWallet.data.pubkey) { + // Make sure wallet is init (need by PopoverInvitationCtrl) + wallet = wallet || csWallet; + + if (!wallet.data.pubkey) { $scope.search.loading = true; return; } + $scope.search.preventSelect = true; + var options = angular.copy($scope.search.options); options.from = options.from || from || 0; options.size = options.size || size || defaultSearchLimit; + options.pubkey = wallet.data.pubkey; $scope.search.loading = !silent; - return esNotification.load(csWallet.data.pubkey, options) + return esNotification.load(options) .then(function(res) { if (!options.from) { $scope.search.results = res || []; @@ -86,6 +123,7 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim $scope.search.results = $scope.search.results.concat(res); } $scope.search.loading = false; + $scope.search.preventSelect = false; $scope.search.hasMore = $scope.search.results.length >= $scope.search.limit; $scope.updateView(); }) @@ -94,6 +132,7 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim if (!options.from) { $scope.search.results = []; } + $scope.search.preventSelect = false; $scope.search.hasMore = false; UIUtils.onError('COMMON.NOTIFICATIONS.LOAD_NOTIFICATIONS_FAILED')(err); }); @@ -106,23 +145,23 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim }; $scope.markAllAsRead = function() { + $scope.hideActionsPopover(); + // Make sure to be auth before doing this - if (!csWallet.isAuth()) { - return csWallet.auth().then(function(){ + if (!wallet.isAuth()) { + return wallet.auth().then(function(){ UIUtils.loading.hide(); return $scope.markAllAsRead(); // loop }); } - $scope.hideActionsPopover(); - if (!$scope.search.results.length) return; UIUtils.loading.show() .then(function() { - $rootScope.walletData.notifications.unreadCount = 0; + wallet.data.notifications.unreadCount = 0; var lastNotification = $scope.search.results[0]; - $rootScope.walletData.notifications.readTime = lastNotification ? lastNotification.time : 0; + wallet.data.notifications.time = lastNotification ? lastNotification.time : 0; _.forEach($scope.search.results, function (item) { if (item.markAsRead && typeof item.markAsRead == 'function') item.markAsRead(); }); @@ -132,18 +171,22 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim }; $scope.resetUnreadCount = function() { - if (!csWallet.data.notifications.unreadCount || !$scope.search.results || !$scope.search.results.length) return; - csWallet.data.notifications.unreadCount = 0; + if ($scope.search.loading || !wallet.data.notifications) { + return $timeout($scope.resetUnreadCount, 2000); + } + if (!wallet.data.notifications.unreadCount || !$scope.search.results || !$scope.search.results.length) return; + wallet.data.notifications.unreadCount = 0; var lastNotification = $scope.search.results[0]; var readTime = lastNotification.time ? lastNotification.time : 0; - if (readTime && (!csSettings.data.wallet || csSettings.data.wallet.notificationReadTime != readTime)) { - csSettings.data.wallet = csSettings.data.wallet || {}; - csSettings.data.wallet.notificationReadTime = readTime; - csSettings.store(); + if (readTime && (!wallet.data.notifications.time || wallet.data.notifications.time != readTime)) { + wallet.data.notifications.time = readTime; + wallet.storeData(); } }; - $scope.select = function(item) { + $scope.select = function(event, item) { + + if ($scope.search.loading || event.preventDefault() || $scope.search.preventSelect) return; if (item.markAsRead && typeof item.markAsRead == 'function') { $timeout(item.markAsRead); @@ -196,38 +239,52 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/notification/popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl :'plugins/es/templates/notification/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; /* -- listeners -- */ - csWallet.api.data.on.logout($scope, $scope.resetData); - esHttp.api.node.on.stop($scope, $scope.resetData); - esHttp.api.node.on.start($scope, $scope.load); - esNotification.api.data.on.new($scope, $scope.onNewNotification); + $scope.addListeners = function() { + if (!wallet) throw "Controller wallet not set !"; + + $scope.listeners = [ + esHttp.api.node.on.stop($scope, $scope.resetData), + esHttp.api.node.on.start($scope, $scope.load), + wallet.api.data.on.logout($scope, $scope.resetData) + ]; + + if (wallet.isDefault()) { + // Subscribe to new notification + $scope.listeners.push( + esNotification.api.data.on.new($scope, $scope.onNewNotification) + ); + } + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; } -function PopoverNotificationsController($scope, $timeout, $controller, UIUtils, $state) { +function PopoverNotificationsController($scope, $timeout, $controller, $state, + UIUtils, csWallet) { 'ngInject'; // Initialize the super class and extend it. @@ -236,8 +293,12 @@ function PopoverNotificationsController($scope, $timeout, $controller, UIUtils, // Disable list motion $scope.motion = null; + // Set the wallet to use + $scope.setWallet(csWallet); + $scope.$on('popover.shown', function() { if ($scope.search.loading) { + $scope.addListeners(); $scope.load(); } }); @@ -253,8 +314,8 @@ function PopoverNotificationsController($scope, $timeout, $controller, UIUtils, $scope.$on('popover.hidden', $scope.resetUnreadCount); - $scope.select = function(notification) { - if (!notification) return; // no selection + $scope.select = function($event, notification) { + if ($event.preventDefault() || !notification) return; // no selection if (notification.markAsRead && typeof notification.markAsRead == 'function') notification.markAsRead(); if (notification.state) { $state.go(notification.state, notification.stateParams); diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/profile-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/profile-controllers.js index 4b1f2d3696ab7e7e191e5cecf211e1540ca45f03..0a3dec64138859bd76e540cf6b7f8e4bc62d663e 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/profile-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/profile-controllers.js @@ -1,21 +1,36 @@ -ESViewEditProfileController.$inject = ['$scope', '$rootScope', '$q', '$timeout', '$state', '$focus', '$translate', '$controller', '$ionicHistory', '$ionicPopover', 'UIUtils', 'csWallet', 'esHttp', 'esProfile', 'ModalUtils', 'Device'];angular.module('cesium.es.profile.controllers', ['cesium.es.services']) +ESViewEditProfileController.$inject = ['$scope', '$q', '$timeout', '$state', '$focus', '$translate', '$controller', '$ionicHistory', '$ionicPopover', 'UIUtils', 'csWallet', 'esHttp', 'esProfile', 'ModalUtils', 'Device'];angular.module('cesium.es.profile.controllers', ['cesium.es.services']) .config(['$stateProvider', function($stateProvider) { - $stateProvider.state('app.user_edit_profile', { - url: "/wallet/profile/edit", - views: { - 'menuContent': { - templateUrl: "plugins/es/templates/user/edit_profile.html", - controller: 'ESViewEditProfileCtrl' + $stateProvider + .state('app.edit_profile', { + url: "/wallet/profile/edit", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/user/edit_profile.html", + controller: 'ESViewEditProfileCtrl' + } + }, + cache: false, + data: { + auth: true } - }, - cache: false, - data: { - auth: true - } - }); + }) + + .state('app.edit_profile_by_id', { + url: "/wallets/:id/profile/edit", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/user/edit_profile.html", + controller: 'ESViewEditProfileCtrl' + } + }, + cache: false, + data: { + login: true + } + }); }]) @@ -24,7 +39,7 @@ ESViewEditProfileController.$inject = ['$scope', '$rootScope', '$q', '$timeout', ; -function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $focus, $translate, $controller, +function ESViewEditProfileController($scope, $q, $timeout, $state, $focus, $translate, $controller, $ionicHistory, $ionicPopover, UIUtils, csWallet, esHttp, esProfile, ModalUtils, Device) { 'ngInject'; @@ -48,19 +63,32 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ }; $scope.socialReorder = true; - $scope.$on('$ionicView.enter', function(e) { - $scope.loadWallet() - .then(function(walletData) { - return $scope.load(walletData); + var wallet; + + $scope.enter = function(e, state) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + $scope.walletId = wallet.id; + + return wallet.auth({ + minData: true }) + .then($scope.load) .catch(function(err){ if (err == 'CANCELLED') { - return $scope.close() - .then(UIUtils.loading.hide); + UIUtils.loading.hide(10); + $scope.cancel(); + return; } UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')(err); }); - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.$on('$stateChangeStart', function (event, next, nextParams, fromState) { if ($scope.dirty && !$scope.saving) { @@ -125,34 +153,32 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ $scope.updateView(walletData, {}); } + UIUtils.loading.hide(); + + // Update loading - done with a delay, to avoid trigger onFormDataChanged() + return $timeout(function() { + $scope.loading = false; + }, 1000); + }) + .then(function() { // removeIf(device) $focus('profile-name'); // endRemoveIf(device) }) - .catch(function(err){ - UIUtils.loading.hide(10); - UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')(err); - }); + .catch(UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')); }; $scope.setForm = function(form) { $scope.form = form; }; - $scope.updateView = function(wallet, profile) { - $scope.walletData = wallet; + $scope.updateView = function(walletData, profile) { + $scope.walletData = walletData; $scope.formData = profile; if (profile.avatar) { $scope.avatarStyle={'background-image':'url("'+$scope.avatar.src+'")'}; } - $scope.motion.show(); - UIUtils.loading.hide(); - - // Update loading - done with a delay, to avoid trigger onFormDataChanged() - $timeout(function() { - $scope.loading = false; - }, 1000); }; $scope.onFormDataChanged = function() { @@ -162,7 +188,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ $scope.$watch('formData', $scope.onFormDataChanged, true); $scope.save = function(silent, hasWaitDebounce) { - if($scope.form.$invalid || !$rootScope.walletData || ($scope.saving && !hasWaitDebounce)) { + if($scope.form.$invalid || !$scope.walletData || ($scope.saving && !hasWaitDebounce)) { return $q.reject(); } @@ -239,7 +265,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ } if (!$scope.existing) { - return esProfile.add(formData) + return esProfile.add(formData, {wallet: wallet}) .then(function() { console.info("[ES] [profile] Successfully created."); $scope.existing = true; @@ -252,7 +278,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ .catch(onError('PROFILE.ERROR.SAVE_PROFILE_FAILED')); } else { - return esProfile.update(formData, {id: $rootScope.walletData.pubkey}) + return esProfile.update(formData, {id: $scope.walletData.pubkey, wallet: wallet}) .then(function() { console.info("[ES] Profile successfully updated."); $scope.saving = false; @@ -292,11 +318,27 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ $scope.cancel = function() { $scope.dirty = false; // force not saved - $scope.close(); + if (wallet.isDefault()) { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + return $state.go('app.view_wallet'); + } + else { + return $state.go('app.view_wallet_by_id', {id: wallet.id}); + } }; $scope.close = function() { - return $state.go('app.view_wallet', {refresh: true}); + if (wallet.isDefault()) { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + return $state.go('app.view_wallet', {refresh: true}); + } + else { + return $state.go('app.view_wallet_by_id', {refresh: true, id: wallet.id}); + } }; $scope.showAvatarModal = function() { @@ -344,7 +386,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ // Hide popover if need $scope.hideActionsPopover(); - return $scope.existing && csWallet.auth({minData: true}) + return $scope.existing && wallet.auth({minData: true}) .then(function(walletData) { UIUtils.loading.hide(); @@ -356,9 +398,11 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ // removeIf(no-device) UIUtils.loading.show(); // endRemoveIf(no-device) - return esProfile.remove(walletData.pubkey) + return esProfile.remove(walletData.pubkey, {wallet: wallet}) .then(function () { - walletData.name=null; + if (wallet.isDefault()) { + walletData.name=null; // keep local name, on children wallets + } walletData.profile = null; walletData.avatar = null; console.debug('[ES] [profile] Successfully deleted'); @@ -379,26 +423,20 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/user/edit_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/user/edit_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; } diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/registry-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/registry-controllers.js index f39b5867e16fd82ec551bf43f4bfe624c970c36f..7ad6f33cbdee9d240f1f205578f50728dd87ca67 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/registry-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/registry-controllers.js @@ -1,6 +1,6 @@ ESRegistryLookupController.$inject = ['$scope', '$focus', '$timeout', '$filter', '$controller', '$location', '$translate', '$ionicPopover', 'Device', 'UIUtils', 'ModalUtils', 'BMA', 'csSettings', 'csWallet', 'esModals', 'esRegistry', 'esHttp']; -ESWalletPagesController.$inject = ['$scope', '$controller', '$timeout', 'UIUtils', 'csWallet']; +ESWalletPagesController.$inject = ['$scope', '$controller', '$timeout', 'UIUtils', 'esModals', 'csWallet']; ESRegistryRecordViewController.$inject = ['$scope', '$rootScope', '$state', '$q', '$timeout', '$ionicPopover', '$ionicHistory', '$translate', '$anchorScroll', 'csConfig', 'csWallet', 'esRegistry', 'UIUtils', 'esHttp']; ESRegistryRecordEditController.$inject = ['$scope', '$timeout', '$state', '$q', '$ionicHistory', '$focus', '$translate', '$controller', 'Device', 'UIUtils', 'ModalUtils', 'csWallet', 'esHttp', 'esRegistry'];angular.module('cesium.es.registry.controllers', ['cesium.es.services', 'cesium.es.common.controllers']) @@ -37,7 +37,7 @@ ESRegistryRecordEditController.$inject = ['$scope', '$timeout', '$state', '$q', }) .state('app.wallet_pages', { - url: "/wallet/pages?refresh", + url: "/account/pages?refresh", views: { 'menuContent': { templateUrl: "plugins/es/templates/registry/view_wallet_pages.html", @@ -46,7 +46,23 @@ ESRegistryRecordEditController.$inject = ['$scope', '$timeout', '$state', '$q', }, data: { login: true, - minData: true + minData: true, + silentLocationChange: true + } + }) + + .state('app.wallet_pages_by_id', { + url: "/wallets/:id/pages?refresh", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/registry/view_wallet_pages.html", + controller: 'ESWalletPagesCtrl' + } + }, + data: { + login: true, + minData: true, + silentLocationChange: true } }) @@ -72,7 +88,7 @@ ESRegistryRecordEditController.$inject = ['$scope', '$timeout', '$state', '$q', .state('app.registry_add_record', { cache: false, - url: "/page/add/:type", + url: "/page/add/:type?wallet", views: { 'menuContent': { templateUrl: "plugins/es/templates/registry/edit_record.html", @@ -87,7 +103,7 @@ ESRegistryRecordEditController.$inject = ['$scope', '$timeout', '$state', '$q', .state('app.registry_edit_record', { cache: false, - url: "/page/edit/:id/:title", + url: "/page/edit/:id/:title?wallet", views: { 'menuContent': { templateUrl: "plugins/es/templates/registry/edit_record.html", @@ -213,7 +229,7 @@ function ESRegistryLookupController($scope, $focus, $timeout, $filter, $controll }); } $scope.search.geoPoint = csWallet.data.profile.geoPoint; - $scope.search.location = csWallet.data.profile.city||(csWallet.data.profile.geoPoint ? 'profile position' : undefined); + $scope.search.location = csWallet.data.profile.city||(csWallet.data.profile.geoPoint ? $translate.instant('LOCATION.PROFILE_POSITION') : undefined); } } @@ -660,50 +676,38 @@ function ESRegistryLookupController($scope, $focus, $timeout, $filter, $controll /* -- popovers -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/registry/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl :'plugins/es/templates/registry/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.filtersPopover = null; } }; $scope.showFiltersPopover = function(event) { - if (!$scope.filtersPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/registry/lookup_popover_filters.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl :'plugins/es/templates/registry/lookup_popover_filters.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.filtersPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.filtersPopover.remove(); - }); - $scope.filtersPopover.show(event); - }); - } - else { - $scope.filtersPopover.show(event); - } + } + }); }; $scope.hideFiltersPopover = function() { if ($scope.filtersPopover) { $scope.filtersPopover.hide(); + $scope.filtersPopover = null; } }; @@ -722,7 +726,7 @@ function ESRegistryLookupController($scope, $focus, $timeout, $filter, $controll } -function ESWalletPagesController($scope, $controller, $timeout, UIUtils, csWallet) { +function ESWalletPagesController($scope, $controller, $timeout, UIUtils, esModals, csWallet) { 'ngInject'; // Initialize the super class and extend it. @@ -730,15 +734,25 @@ function ESWalletPagesController($scope, $controller, $timeout, UIUtils, csWalle $scope.searchTextId = undefined; // avoid focus + var wallet; + // Override the default enter $scope.enter = function(e, state) { if (!$scope.entered) { - return csWallet.login({minData: true}) + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + return wallet.login({minData: true}) .then(function(walletData) { UIUtils.loading.hide(); $scope.search.issuer = walletData.pubkey; $scope.search.advanced = true; $timeout($scope.doSearch, 100); + $scope.showFab('fab-wallet-add-registry-record'); }); } else { @@ -750,12 +764,18 @@ function ESWalletPagesController($scope, $controller, $timeout, UIUtils, csWalle }; $scope.doUpdate = function() { - if (!csWallet.isLogin()) return; + if (!wallet || !wallet.isLogin()) return; $scope.search.issuer = csWallet.data.pubkey; $scope.search.advanced = true; return $scope.doSearch(); }; + // Override inherited, to pass the select wallet + $scope.showNewPageModal = function() { + $scope.hidePopovers(); + return esModals.showNewPage({wallet: wallet}); + }; + } @@ -768,6 +788,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.category = {}; $scope.pictures = []; $scope.canEdit = false; + $scope.showTransfer = false; $scope.loading = true; $scope.motion = UIUtils.motion.fadeSlideIn; @@ -784,7 +805,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.$broadcast('$recordView.enter', state); } else { - $state.go('app.registry_lookup'); + $state.go('app.wot_lookup.tab_registry'); } }); @@ -802,7 +823,8 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.id= data.id; $scope.formData = data.record; //console.debug('Loading record', $scope.formData); - $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer); + $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer) || csWallet.children.hasPubkey($scope.formData.issuer); + $scope.showTransfer = !$scope.canEdit && $scope.formData.pubkey; $scope.issuer = data.issuer; // avatar $scope.avatar = $scope.formData.avatar; @@ -825,7 +847,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.loading = false; if (err && err.ucode === 404) { UIUtils.toast.show('REGISTRY.ERROR.RECORD_NOT_EXISTS'); - $state.go('app.registry_lookup'); + $state.go('app.wot_lookup.tab_registry'); } else { UIUtils.onError('REGISTRY.ERROR.LOAD_RECORD_FAILED')(err); @@ -874,13 +896,18 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout // Edit click $scope.edit = function() { + var wallet = csWallet.isUserPubkey($scope.formData.issuer) ? csWallet : csWallet.children.getByPubkey($scope.formData.issuer); + if (!wallet) return; UIUtils.loading.show(); - $state.go('app.registry_edit_record', {id: $scope.id}); + return $state.go('app.registry_edit_record', {id: $scope.id, wallet: wallet.id}); }; $scope.delete = function() { $scope.hideActionsPopover(); + var wallet = csWallet.isUserPubkey($scope.formData.issuer) ? csWallet : csWallet.children.getByPubkey($scope.formData.issuer); + if (!wallet) return; + // translate var translations; $translate(['REGISTRY.VIEW.REMOVE_CONFIRMATION', 'REGISTRY.INFO.RECORD_REMOVED']) @@ -890,15 +917,21 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout }) .then(function(confirm) { if (confirm) { - esRegistry.record.remove($scope.id) + esRegistry.record.remove($scope.id, {wallet: wallet}) .then(function () { - if (csWallet.data.pages && csWallet.data.pages.count) { - csWallet.data.pages.count--; + if (wallet.data.pages && wallet.data.pages.count) { + wallet.data.pages.count--; } $ionicHistory.nextViewOptions({ historyRoot: true }); - $state.go('app.wallet_pages', {refresh: true}); + if (wallet.isDefault()) { + $state.go('app.wallet_pages', {refresh: true}); + } + else { + $state.go('app.wallet_pages_by_id', {refresh: true, id: wallet.id}); + } + UIUtils.toast.show(translations['REGISTRY.INFO.RECORD_REMOVED']); }) .catch(UIUtils.onError('REGISTRY.ERROR.REMOVE_RECORD_FAILED')); @@ -908,27 +941,22 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout /* -- modals & popover -- */ + $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/registry/view_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/registry/view_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; @@ -979,26 +1007,37 @@ function ESRegistryRecordEditController($scope, $timeout, $state, $q, $ionicHis $scope.form = form; }; + var wallet; + $scope.$on('$ionicView.enter', function(e, state) { - $scope.loadWallet({minData: true}) - .then(function(walletData) { - $scope.walletData = walletData; - if (state.stateParams && state.stateParams.id) { // Load by id - $scope.load(state.stateParams.id); - } - else { - if (state.stateParams && state.stateParams.type) { - $scope.updateView({ - record: { - type: state.stateParams.type - } - }); + + if ($scope.loading) { + wallet = (state.stateParams && state.stateParams.wallet && state.stateParams.wallet != 'default') ? csWallet.children.get(state.stateParams.wallet) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + return wallet.login({minData: true}) + .then(function(walletData) { + $scope.walletData = walletData; + if (state.stateParams && state.stateParams.id) { // Load by id + $scope.load(state.stateParams.id); } - } - // removeIf(device) - $focus('registry-record-title'); - // endRemoveIf(device) - }); + else { + if (state.stateParams && state.stateParams.type) { + $scope.updateView({ + record: { + type: state.stateParams.type + } + }); + } + } + // removeIf(device) + $focus('registry-record-title'); + // endRemoveIf(device) + }); + } }); $scope.$on('$stateChangeStart', function (event, next, nextParams, fromState) { @@ -1155,7 +1194,7 @@ function ESRegistryRecordEditController($scope, $timeout, $state, $q, $ionicHis if (!$scope.needCategory()) { delete json.category; } - json.time = esHttp.date.now(); + json.time = moment().utc().unix(); // geo point if (json.geoPoint && json.geoPoint.lat && json.geoPoint.lon) { @@ -1205,15 +1244,15 @@ function ESRegistryRecordEditController($scope, $timeout, $state, $q, $ionicHis .then(function(json){ // Create if (!$scope.id) { - return esRegistry.record.add(json); + return esRegistry.record.add(json, {wallet: wallet}); } // Update - return esRegistry.record.update(json, {id: $scope.id}); + return esRegistry.record.update(json, {id: $scope.id, wallet: wallet}); }) .then(function(id) { console.info("[ES] [page] Record successfully saved."); - if (!$scope.id && csWallet.data.pages && csWallet.data.pages.count) { + if (!$scope.id && wallet.data.pages && wallet.data.pages.count) { csWallet.data.pages.count++; } $scope.id = $scope.id || id; diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/settings-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/settings-controllers.js index 0a43e51139f6f85d147fcc40703ffb29a90ea320..f0e7511e811328698bb77f0a8887c5facaa74118 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/settings-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/settings-controllers.js @@ -1,6 +1,6 @@ ESExtendSettingsController.$inject = ['$scope', 'PluginService']; -ESPluginSettingsController.$inject = ['$scope', '$q', '$translate', '$ionicPopup', 'UIUtils', 'Modals', 'csHttp', 'csSettings', 'esHttp', 'esSettings'];angular.module('cesium.es.settings.controllers', ['cesium.es.services']) +ESPluginSettingsController.$inject = ['$scope', '$window', '$q', '$translate', '$ionicPopup', 'UIUtils', 'Modals', 'csHttp', 'csConfig', 'csSettings', 'esHttp', 'esSettings'];angular.module('cesium.es.settings.controllers', ['cesium.es.services']) // Configure menu items .config(['PluginServiceProvider', '$stateProvider', 'csConfig', function(PluginServiceProvider, $stateProvider, csConfig) { @@ -13,7 +13,7 @@ ESPluginSettingsController.$inject = ['$scope', '$q', '$translate', '$ionicPopup points: { 'plugins': { templateUrl: "plugins/es/templates/settings/settings_extend.html", - controller: "ESExtendSettingsCtrl" + controller: "ESExtensionCtrl" } } }); @@ -50,9 +50,11 @@ function ESExtendSettingsController ($scope, PluginService) { /* * Settings extend controller */ -function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUtils, Modals, csHttp, csSettings, esHttp, esSettings) { +function ESPluginSettingsController ($scope, $window, $q, $translate, $ionicPopup, + UIUtils, Modals, csHttp, csConfig, csSettings, esHttp, esSettings) { 'ngInject'; + $scope.hasWindowNotification = !!("Notification" in window); $scope.formData = {}; $scope.popupData = {}; // need for the node popup $scope.loading = true; @@ -95,7 +97,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti node = node || { host: $scope.formData.host, port: $scope.formData.port && $scope.formData.port != 80 && $scope.formData.port != 443 ? $scope.formData.port : undefined, - wsPort: $scope.formData.wsPort && $scope.formData.wsPort != $scope.formData.port ? $scope.formData.wsPort : undefined, useSsl: angular.isDefined($scope.formData.useSsl) ? $scope.formData.useSsl : ($scope.formData.port == 443) @@ -105,14 +106,13 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti .then(function(newNode) { if (newNode.host == $scope.formData.host && newNode.port == $scope.formData.port && - newNode.wsPort == $scope.formData.wsPort && newNode.useSsl == $scope.formData.useSsl) { UIUtils.loading.hide(); return; // same node = nothing to do } UIUtils.loading.show(); - var newEsNode = esHttp.instance(newNode.host, newNode.port, newNode.wsPort, newNode.useSsl); + var newEsNode = esHttp.instance(newNode.host, newNode.port, newNode.useSsl); return newEsNode.isAlive() // ping the node .then(function(alive) { if (!alive) { @@ -125,7 +125,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti $scope.formData.host = newEsNode.host; $scope.formData.port = newEsNode.port; - $scope.formData.wsPort = newEsNode.wsPort; $scope.formData.useSsl = newEsNode.useSsl; return esHttp.copy(newEsNode); @@ -140,13 +139,10 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti // Show node popup $scope.showNodePopup = function(node) { + return $q(function(resolve, reject) { var parts = [node.host]; - if (node.wsPort && node.wsPort != (node.port||80)) { - parts.push(node.port||80); - parts.push(node.wsPort); - } - else if (node.port && node.port != 80) { + if (node.port && node.port != 80) { parts.push(node.port); } $scope.popupData.newNode = parts.join(':'); @@ -189,7 +185,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti resolve({ host: parts[0], port: parts[1] || (useSsl ? 443 : 80), - wsPort: parts[2] || parts[1] || (useSsl ? 443 : 80), useSsl: useSsl }); }); @@ -198,10 +193,15 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti }; $scope.showNodeList = function() { + // Check if need a filter on SSL node + var forceUseSsl = (csConfig.httpsMode === 'true' || csConfig.httpsMode === true || csConfig.httpsMode === 'force') || + ($window.location && $window.location.protocol === 'https:') ? true : false; + $ionicPopup._popupStack[0].responseDeferred.promise.close(); return Modals.showNetworkLookup({ enableFilter: true, - endpointFilter: esHttp.constants.ES_USER_API_ENDPOINT + endpoint: esHttp.constants.ES_USER_API_ENDPOINT, + ssl: forceUseSsl ? true: undefined }) .then(function (peer) { if (!peer) return; @@ -214,14 +214,11 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti return { host: (ep.dns ? ep.dns : (peer.hasValid4(ep) ? ep.ipv4 : ep.ipv6)), - port: ep.port || 80 + port: ep.port || 80, + useSsl: ep.useSsl || ep.port == 443 }; }) .then(function(newEsNode) { - if (!newEsNode) { - UIUtils.alert.error('ERROR.INVALID_NODE_SUMMARY'); - return; - } $scope.changeEsNode(newEsNode); }); }; @@ -229,6 +226,16 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti $scope.onFormChanged = function() { if ($scope.loading) return; + if ($scope.hasWindowNotification && + $scope.formData.notifications.emitHtml5 !== (window.Notification.permission === "granted")){ + window.Notification.requestPermission(function (permission) { + // If the user accepts, let's create a notification + $scope.formData.notifications.emitHtml5 = (permission === "granted"); // revert to false if permission not granted + $scope.onFormChanged(); // Loop + }); + return; + } + $scope.loading = true; csSettings.data.plugins = csSettings.data.plugins || {}; csSettings.data.plugins.es = csSettings.data.plugins.es ? @@ -248,7 +255,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti $scope.getServer = function(node) { node = node || $scope.formData; if (!node.host) return undefined; - var server = csHttp.getServer(node.host, node.port); - return server + (node.wsPort && node.wsPort != node.port ? ':' + node.wsPort : ''); + return csHttp.getServer(node.host, node.port); }; } diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/subscription-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/subscription-controllers.js index 12d8940874e587b8c6155e63b152ca38e355ad82..e28697ebc0a2ec208dc78115b48c0426ece5977d 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/subscription-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/subscription-controllers.js @@ -1,23 +1,39 @@ -ViewSubscriptionsController.$inject = ['$scope', '$rootScope', '$q', 'csWot', 'UIUtils', 'ModalUtils', 'esSubscription']; +ViewSubscriptionsController.$inject = ['$scope', '$q', '$ionicHistory', 'csWot', 'csWallet', 'UIUtils', 'ModalUtils', 'esSubscription']; ModalEmailSubscriptionsController.$inject = ['$scope', 'Modals', 'csSettings', 'esHttp', 'csWot', 'parameters'];angular.module('cesium.es.subscription.controllers', ['cesium.es.services']) .config(['$stateProvider', function($stateProvider) { - $stateProvider.state('app.edit_subscriptions', { - cache: false, - url: "/wallet/subscriptions", - views: { - 'menuContent': { - templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", - controller: 'ViewSubscriptionsCtrl' + $stateProvider + .state('app.edit_subscriptions', { + cache: false, + url: "/wallet/subscriptions", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", + controller: 'ViewSubscriptionsCtrl' + } + }, + data: { + auth: true, + minData: true } - }, - data: { - auth: true, - minData: true - } - }); + }) + + .state('app.edit_subscriptions_by_id', { + cache: false, + url: "/wallets/:id/subscriptions", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", + controller: 'ViewSubscriptionsCtrl' + } + }, + data: { + login: true, + minData: true + } + }); }]) @@ -27,9 +43,10 @@ ModalEmailSubscriptionsController.$inject = ['$scope', 'Modals', 'csSettings', ' ; -function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, ModalUtils, esSubscription) { +function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, UIUtils, ModalUtils, esSubscription) { 'ngInject'; + $scope.loading = true; $scope.popupData = {}; // need for the node popup $scope.search = { results: [], @@ -40,25 +57,44 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod {id: "weekly", label: "weekly"} ]; - $scope.onEnter = function() { - $scope.loading = true; - $scope.loadWallet({minData: true}) - .then(function() { - UIUtils.loading.hide(); - return $scope.load(); - }) - .catch(function(err){ - if (err == 'CANCELLED') { - return UIUtils.loading.hide(); - } - UIUtils.onError('SUBSCRIPTION.ERROR.LOAD_SUBSCRIPTIONS_FAILED')(err); - }); + var wallet; + + $scope.enter = function(e, state) { + + // First load + if ($scope.loading) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + wallet.auth({minData: true}) + .then(function() { + UIUtils.loading.hide(); + return $scope.load(); + }) + .then(function() { + $scope.showFab('fab-add-subscription-record'); + }) + .catch(function(err){ + if (err === 'CANCELLED') { + UIUtils.loading.hide(10); + $scope.loading=true; // reset for force reload next time + $ionicHistory.goBack(); + return; + } + UIUtils.onError('SUBSCRIPTION.ERROR.LOAD_SUBSCRIPTIONS_FAILED')(err); + }); + } + }; - $scope.$on('$ionicView.enter', $scope.onEnter); + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function() { $scope.loading = true; // to avoid the call of doSave() - return esSubscription.record.load($rootScope.walletData.pubkey, $rootScope.walletData.keypair) + return esSubscription.record.load(wallet.data.pubkey, wallet.data.keypair) .then(function(results) { // Group by type var groups = _.groupBy((results || []), function (record) { @@ -76,10 +112,8 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod .then(function(results) { return csWot.extendAll(results, 'recipient'); }) - .then(function(results) { - // Display result - $scope.updateView(results); - }) + // Display result + .then($scope.updateView) .catch(function(err){ UIUtils.loading.hide(10); if (err && err.ucode == 404) { @@ -110,7 +144,7 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod if (!cat) return; type = cat.id; // get subscription parameters - if (type == 'email') { + if (type === 'email') { return $scope.showEmailModal(); } else { @@ -120,11 +154,11 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod .then(function(record) { if (!record) return; UIUtils.loading.show(); - esSubscription.record.add(record) + esSubscription.record.add(record, {wallet: wallet}) .then($scope.addToUI) .then(function() { - $rootScope.walletData.subscriptions = $rootScope.walletData.subscriptions || {count: 0}; - $rootScope.walletData.subscriptions.count++; + wallet.data.subscriptions = wallet.data.subscriptions || {count: 0}; + wallet.data.subscriptions.count++; UIUtils.loading.hide(); $scope.updateView(); }) @@ -137,20 +171,20 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod // get subscription parameters var promise; var oldRecord = angular.copy(record); - if (record.type == 'email') { + if (record.type === 'email') { promise = $scope.showEmailModal(record); } if (!promise) return; return promise - .then(function() { - if (!record) return; + .then(function(res) { + if (!res) return; UIUtils.loading.show(); record.id = oldRecord.id; - return esSubscription.record.update(record) + return esSubscription.record.update(record, wallet) .then(function() { // If recipient change, update in results - if (oldRecord.type != record.type || - oldRecord.recipient != record.recipient) { + if (oldRecord.type !== record.type || + oldRecord.recipient !== record.recipient) { $scope.removeFromUI(oldRecord); return $scope.addToUI(record); } @@ -174,10 +208,10 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod } UIUtils.loading.show(); - esSubscription.record.remove(record.id) + esSubscription.record.remove(record.id, {wallet: wallet}) .then(function() { - $rootScope.walletData.subscriptions = $rootScope.walletData.subscriptions || {count: 1}; - $rootScope.walletData.subscriptions.count--; + wallet.data.subscriptions = wallet.data.subscriptions || {count: 1}; + wallet.data.subscriptions.count--; $scope.removeFromUI(record); UIUtils.loading.hide(); }) @@ -288,7 +322,8 @@ function ModalEmailSubscriptionsController($scope, Modals, csSettings, esHttp, c $scope.showNetworkLookup = function() { return Modals.showNetworkLookup({ enableFilter: true, - endpointFilter: esHttp.constants.ES_USER_API_ENDPOINT + endpoint: esHttp.constants.ES_USER_API_ENDPOINT, + bma: false }) .then(function (peer) { if (peer) { diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/wallet-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/wallet-controllers.js index b3595b821b4fad750dd1c5436ca5998cb2d000da..ae2efcabd3ca35b790ef523b8be10f6a056dc12c 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/wallet-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/wallet-controllers.js @@ -1,12 +1,13 @@ -ESWalletController.$inject = ['$scope', '$controller', 'esModals'];angular.module('cesium.es.wallet.controllers', ['cesium.es.services']) +ESWalletController.$inject = ['$scope', '$controller', '$state', 'esModals', 'csWallet'];angular.module('cesium.es.wallet.controllers', ['cesium.es.services']) .config(['PluginServiceProvider', 'csConfig', function(PluginServiceProvider, csConfig) { 'ngInject'; var enable = csConfig.plugins && csConfig.plugins.es; if (enable) { - PluginServiceProvider.extendState('app.view_wallet', { + PluginServiceProvider + .extendStates(['app.view_wallet', 'app.view_wallet_by_id'], { points: { 'after-general': { templateUrl: "plugins/es/templates/wallet/view_wallet_extend.html", @@ -14,6 +15,16 @@ ESWalletController.$inject = ['$scope', '$controller', 'esModals'];angular.modul } } }) + + .extendState('app.view_wallets', { + points: { + 'item-wallet': { + templateUrl: "plugins/es/templates/wallet/item_wallet_extend.html", + controller: 'ESExtensionCtrl' + } + } + }) + ; } @@ -24,18 +35,24 @@ ESWalletController.$inject = ['$scope', '$controller', 'esModals'];angular.modul ; -function ESWalletController($scope, $controller, esModals) { +function ESWalletController($scope, $controller, $state, esModals, csWallet) { 'ngInject'; // Initialize the super class and extend it. - angular.extend(this, $controller('ESWotIdentityViewCtrl', {$scope: $scope})); + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); $scope.showProfileHelp = false; /* -- modals -- */ $scope.showNewPageModal = function() { - return esModals.showNewPage(); + var wallet = ($state.params && $state.params.id) ? csWallet.children.get($state.params.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return; + } + + return esModals.showNewPage({wallet: wallet}); }; } diff --git a/assets/www/dist/dist_js/plugins/es/js/controllers/wot-controllers.js b/assets/www/dist/dist_js/plugins/es/js/controllers/wot-controllers.js index 3388fe55afd5d25cb0728123ccfe044cd7dc7797..ff8003c7328cb8becc35a036d19ef6a207d141be 100644 --- a/assets/www/dist/dist_js/plugins/es/js/controllers/wot-controllers.js +++ b/assets/www/dist/dist_js/plugins/es/js/controllers/wot-controllers.js @@ -1,6 +1,6 @@ ESWotLookupExtendController.$inject = ['$scope', '$controller', '$state']; -ESWotIdentityViewController.$inject = ['$scope', '$ionicPopover', '$q', 'UIUtils', 'Modals', 'esSettings', 'PluginService', 'csWallet', 'esModals', 'esHttp', 'esWallet', 'esInvitation'];angular.module('cesium.es.wot.controllers', ['cesium.es.services']) +ESWotIdentityViewController.$inject = ['$scope', '$ionicPopover', '$q', '$controller', 'UIUtils', 'Modals', 'csWallet', 'esModals', 'esWallet', 'esInvitation'];angular.module('cesium.es.wot.controllers', ['cesium.es.services']) .config(['$stateProvider', 'PluginServiceProvider', 'csConfig', function($stateProvider, PluginServiceProvider, csConfig) { 'ngInject'; @@ -12,7 +12,8 @@ ESWotIdentityViewController.$inject = ['$scope', '$ionicPopover', '$q', 'UIUtils .extendState('app.wot_lookup', { points: { 'tabs': { - templateUrl: "plugins/es/templates/wot/lookup_extend.html" + templateUrl: "plugins/es/templates/wot/lookup_extend.html", + controller: "ESExtensionCtrl" } } }) @@ -35,6 +36,10 @@ ESWotIdentityViewController.$inject = ['$scope', '$ionicPopover', '$q', 'UIUtils 'buttons': { templateUrl: "plugins/es/templates/wot/view_identity_extend.html", controller: 'ESWotIdentityViewCtrl' + }, + 'buttons-top-fab': { + templateUrl: "plugins/es/templates/wot/view_identity_extend.html", + controller: 'ESWotIdentityViewCtrl' } } }) @@ -80,25 +85,24 @@ function ESWotLookupExtendController($scope, $controller, $state) { location: location.length ? location : undefined }; - $state.go('app.registry_lookup', stateParams); + $state.go('app.wot_lookup.tab_registry', stateParams); }; } -function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, esSettings, PluginService, csWallet, - esModals, esHttp, esWallet, esInvitation) { +function ESWotIdentityViewController($scope, $ionicPopover, $q, $controller, UIUtils, Modals, csWallet, + esModals, esWallet, esInvitation) { 'ngInject'; - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; - }); + // Initialize the super class and extend it. + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); + + $scope.canCertify = false; // disable certity on the popover (by default - override by the wot map controller) /* -- modals -- */ $scope.showNewMessageModal = function(confirm) { - return $scope.loadWallet({minData: true}) + return csWallet.login({minData: true, method: 'default'}) .then(function() { UIUtils.loading.hide(); @@ -135,6 +139,7 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, return csWallet.auth({minData: true}) .then(function(walletData) { UIUtils.loading.hide(); + if (!walletData) return; // Not allow for non-member - issue #561 if (!walletData.isMember) { @@ -164,7 +169,7 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, var keypair = res[0]; var confirm = res[1]; if (!confirm) return; - var time = esHttp.date.now(); // use same date for each invitation + var time = moment().utc().unix(); // use same date for each invitation return $q.all( identities.reduce(function(res, identity){ return res.concat( @@ -191,9 +196,13 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, $scope.hideCertificationActionsPopover(); var identities; - return csWallet.auth({minData: true}) + return (csWallet.children.count() ? Modals.showSelectWallet({displayBalance: false}) : $q.when(csWallet)) + .then(function(wallet) { + return wallet.auth({minData: true}); + }) .then(function(walletData) { UIUtils.loading.hide(); + if (!walletData) return; // Not allow for non-member - issue #561 if (!walletData.isMember) { @@ -219,11 +228,10 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, UIUtils.alert.confirm('WOT.CONFIRM.ASK_CERTIFICATIONS', undefined, {okText: 'COMMON.BTN_SEND'}) ]) .then(function(res) { - if (!res) return; - var keypair = res[0]; - var confirm = res[1]; - if (!confirm) return; - var time = esHttp.date.now(); // use same date for each invitation + var keypair = res && res[0]; + var confirm = res && res[1]; + if (!keypair || !confirm) return; + var time = moment().utc().unix(); // use same date for each invitation return $q.all(identities.reduce(function(res, identity){ return res.concat( esInvitation.send({ @@ -246,25 +254,36 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, $scope.askCertification = function() { $scope.hideCertificationActionsPopover(); - return csWallet.auth({minData: true}) + return (csWallet.children.count() ? Modals.showSelectWallet({displayBalance: false}) : $q.when(csWallet)) + .then(function(wallet) { + return wallet.auth({minData: true}); + }) .then(function(walletData) { UIUtils.loading.hide(); + if (!walletData) return; // Not allow for non-member - issue #561 if (!walletData.isMember) { return UIUtils.alert.error('ERROR.ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION'); } - + // ask confirmation return UIUtils.alert.confirm('WOT.CONFIRM.ASK_CERTIFICATION', undefined, { - okText: 'COMMON.BTN_SEND' - }) + okText: 'COMMON.BTN_SEND' + }) .then(function(confirm) { if (!confirm) return; return esInvitation.send({ issuer: walletData.pubkey, recipient: $scope.formData.pubkey, content: [walletData.uid, walletData.pubkey].join('-') - }, undefined, 'certification') + }, + { + type: 'certification', + keypair: walletData.keypair + }) + .then(function() { + UIUtils.toast.show('INVITATION.INFO.INVITATION_SENT'); + }) .catch(UIUtils.onError('INVITATION.ERROR.SEND_INVITATION_FAILED')); }); }); @@ -273,29 +292,32 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, /* -- Popover -- */ $scope.showCertificationActionsPopover = function(event) { - if (!$scope.certificationActionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/wot/popover_certification_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/wot/popover_certification_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.certificationActionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.certificationActionsPopover.remove(); - }); - $scope.certificationActionsPopover.show(event); - }); - } - else { - $scope.certificationActionsPopover.show(event); - } + } + }); }; $scope.hideCertificationActionsPopover = function() { if ($scope.certificationActionsPopover) { $scope.certificationActionsPopover.hide(); + $scope.certificationActionsPopover = null; } }; + if ($scope.extensionPoint === 'buttons-top-fab') { + // Show fab button, when parent execute motions + $scope.$on('$csExtension.motion', function(event) { + var canCompose = !!$scope.formData.profile; + if (canCompose) { + $scope.showFab('fab-compose-' + $scope.formData.uid); + } + }); + } // TODO : for DEV only /*$timeout(function() { diff --git a/assets/www/dist/dist_js/plugins/es/js/entities/notification.js b/assets/www/dist/dist_js/plugins/es/js/entities/notification.js index cd564c88c1fceb73773192b3fe5000a88a59a27b..f928c32002304b8ba750b9ab1704920109a9e380 100644 --- a/assets/www/dist/dist_js/plugins/es/js/entities/notification.js +++ b/assets/www/dist/dist_js/plugins/es/js/entities/notification.js @@ -1,5 +1,5 @@ -function Notification(json, markAsReadCallback) { +function EsNotification(json, markAsReadCallback) { var messagePrefixes = { 'registry': 'EVENT.REGISTRY.' @@ -42,12 +42,15 @@ function Notification(json, markAsReadCallback) { if (json.code.startsWith('MEMBER_')) { that.avatarIcon = 'ion-person'; that.icon = 'ion-information-circled positive'; + that.state = 'app.view_wallet'; + that.medianTime = that.time; } // TX else if (json.code.startsWith('TX_')) { that.avatarIcon = 'ion-card'; that.icon = (json.code == 'TX_SENT') ? 'ion-paper-airplane dark' : 'ion-archive balanced'; + that.medianTime = that.time; pubkeys = json.params.length > 0 ? json.params[0] : null; if (pubkeys && pubkeys.indexOf(',') == -1) { that.pubkey = pubkeys; @@ -61,6 +64,7 @@ function Notification(json, markAsReadCallback) { that.avatarIcon = (json.code == 'CERT_RECEIVED') ? 'ion-ribbon-b' : 'ion-ribbon-a'; that.icon = (json.code == 'CERT_RECEIVED') ? 'ion-ribbon-b balanced' : 'ion-ribbon-a gray'; that.pubkey = json.params.length > 0 ? json.params[0] : null; + that.medianTime = that.time; that.state = 'app.wallet_cert'; that.stateParams = { type: (json.code == 'CERT_RECEIVED') ? 'received' : 'given' @@ -114,4 +118,6 @@ function Notification(json, markAsReadCallback) { that.avatarIcon = 'ion-close'; that.icon = 'ion-close-circled assertive'; } + + return that; } diff --git a/assets/www/dist/dist_js/plugins/es/js/services/blockchain-services.js b/assets/www/dist/dist_js/plugins/es/js/services/blockchain-services.js index afbf7bbd6ef8d62e14908a8ba00031edfee2726e..090f75e8d133a572d16ed1f04007ce4c9eb50dfd 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/blockchain-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/blockchain-services.js @@ -31,22 +31,23 @@ angular.module('cesium.es.blockchain.services', ['cesium.services', 'cesium.es.h block: {}, raw: { block: { - search: esHttp.post('/:currency/block/_search'), + search: esHttp.post('/:currency/block/_search', esHttp.cache.SHORT), searchText: esHttp.get('/:currency/block/_search?q=:text'), - get: esHttp.get('/:currency/block/:number/_source') + get: esHttp.get('/:currency/block/:number/_source', esHttp.cache.SHORT) } }, - regex: { + regexp: { ES_CORE_API_ENDPOINT: exact(CONSTANTS.ES_CORE_API_ENDPOINT) } }; + exports.regex = exports.regexp; // deprecated function exact(regexpContent) { return new RegExp('^' + regexpContent + '$'); } exports.node.parseEndPoint = function(endpoint) { - var matches = REGEX.ES_CORE_API_ENDPOINT.exec(endpoint); + var matches = exports.regexp.ES_CORE_API_ENDPOINT.exec(endpoint); if (!matches) return; return { dns: matches[2] || '', diff --git a/assets/www/dist/dist_js/plugins/es/js/services/comment-services.js b/assets/www/dist/dist_js/plugins/es/js/services/comment-services.js index a3205502dfec75db95be97c20042a3608fb420e1..904856cb289cda43373e88aa64ac0690bbc10be7 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/comment-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/comment-services.js @@ -167,16 +167,19 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', if (index === -1) return; data.result.splice(index, 1); delete data.mapById[comment.id]; + + var wallet = !csWallet.isUserPubkey(comment.issuer) ? csWallet.children.getByPubkey(comment.issuer) : csWallet; + // Send deletion request - if (csWallet.isUserPubkey(comment.issuer)) { + if (wallet) { return exports.raw.remove(comment.id) .catch(function(err){ console.error(err); - throw new Error('MARKET.ERROR.FAILED_REMOVE_COMMENT'); + throw new Error('COMMENTS.ERROR.FAILED_REMOVE_COMMENT'); }); } else { - return $q.reject("User is not the comment issuer"); + return $q.reject("No wallet found corresponding to the comment issuer"); } }; }; @@ -196,7 +199,7 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', }); // Open websocket - var time = new Date().getTime(); + var time = Date.now(); console.info("[ES] [comment] Starting websocket to listen comments on [{0}/record/{1}]".format(index, recordId.substr(0,8))); var wsChanges = exports.raw.wsChanges(); return wsChanges.open() @@ -208,7 +211,7 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', // Listen changes .then(function(){ - console.debug("[ES] [comment] Websocket opened in {0} ms".format(new Date().getTime() - time)); + console.debug("[ES] [comment] Websocket opened in {0} ms".format(Date.now() - time)); wsChanges.on(function(change) { if (!change) return; scope.$applyAsync(function() { @@ -267,7 +270,7 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', // Preparing JSON to sent var id = comment.id; var json = { - creationTime: id ? comment.creationTime || comment.time/*for compat*/ : esHttp.date.now(), + creationTime: id ? comment.creationTime || comment.time/*for compat*/ : moment().utc().unix(), message: comment.message, record: recordId, issuer: csWallet.data.pubkey diff --git a/assets/www/dist/dist_js/plugins/es/js/services/crypto-services.js b/assets/www/dist/dist_js/plugins/es/js/services/crypto-services.js index 1a22c28e3f31bd106a239ba0fcc8155a74bcaf0e..341387dd41bd39e0265150f37e8bf9cffbfb4f66 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/crypto-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/crypto-services.js @@ -92,7 +92,7 @@ angular.module('cesium.es.crypto.services', ['ngResource', 'cesium.services']) cypherFieldNames = [cypherFieldNames]; } - var now = new Date().getTime(); + var now = Date.now(); var issuerBoxPks = {}; // a map used as cache var jobs = [getBoxKeypair(keypair)]; @@ -129,7 +129,7 @@ angular.module('cesium.es.crypto.services', ['ngResource', 'cesium.services']) }, [])); }) .then(function() { - console.debug('[ES] [crypto] All record decrypted in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[ES] [crypto] All record decrypted in ' + (Date.now() - now) + 'ms'); return records; }); diff --git a/assets/www/dist/dist_js/plugins/es/js/services/document-services.js b/assets/www/dist/dist_js/plugins/es/js/services/document-services.js index 4a4d5ad00e1ec17353f74d906a17ba08da5ea239..bb28284a3e238f63af6b3e2e5e2869d939f05ee3 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/document-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/document-services.js @@ -147,7 +147,7 @@ angular.module('cesium.es.document.services', ['ngResource', 'cesium.platform', options.index, options.type )); - var now = new Date().getTime(); + var now = Date.now(); return raw.searchText(request) .then(function(res) { @@ -158,25 +158,27 @@ angular.module('cesium.es.document.services', ['ngResource', 'cesium.platform', options.index, options.type, res && res.hits && res.hits.length || 0, - new Date().getTime() - now + Date.now() - now )); return res; }); } - function remove(document) { + function remove(document, options) { if (!document || !document.index || !document.type || !document.id) return $q.reject('Could not remove document: missing mandatory fields'); - return esHttp.record.remove(document.index, document.type)(document.id); + return esHttp.record.remove(document.index, document.type)(document.id, options); } - function removeAll(documents) { + function removeAll(documents, options) { if (!documents || !documents.length) return; - return csWallet.auth() - .then(function(walletData) { + var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet; + + return wallet.auth() // Auth once + .then(function() { // Remove each doc return $q.all(documents.reduce(function (res, doc) { - return res.concat(esHttp.record.remove(doc.index, doc.type)(doc.id, walletData)); + return res.concat(esHttp.record.remove(doc.index, doc.type)(doc.id, {wallet: wallet})); }, [])); }); } diff --git a/assets/www/dist/dist_js/plugins/es/js/services/geo-services.js b/assets/www/dist/dist_js/plugins/es/js/services/geo-services.js index 051bc6a3a413afb52deed54ba9411a451daeeeae..f2b7c1117b19dc8c66d63be3ac47156f56d272cf 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/geo-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/geo-services.js @@ -29,6 +29,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser search: csHttp.get('maps.google.com', 443, '/maps/api/geocode/json') }, freegeoip: { + //search: csHttp.get('localhost', 8080, '/json/:ip'), search: csHttp.get('freegeoip.net', 443, '/json/:ip'), license: { name: 'freegeoip', @@ -88,7 +89,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser query.addressdetails = 1; // need address field - var now = new Date(); + var now = Date.now(); //console.debug('[ES] [geo] Searching position...', query); return that.raw.osm.search(query) @@ -116,7 +117,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser }); }, []); - console.debug('[ES] [geo] Found {0} address position(s)'.format(res && res.length || 0, new Date().getTime() - now.getTime()), res); + console.debug('[ES] [geo] Found {0} address position(s)'.format(res && res.length || 0, Date.now() - now), res); return res.length ? res : undefined; }) @@ -156,7 +157,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser return that.raw.freegeoip.search({ip: ip}) .then(function(res) { - //console.debug('[ES] [geo] Found IP {0} position in {0}ms'.format(res ? 1 : 0, new Date().getTime() - now.getTime())); + //console.debug('[ES] [geo] Found IP {0} position in {0}ms'.format(res ? 1 : 0, Date.now() - now.getTime())); return res ? { lat: res.latitude, lng: res.longitude diff --git a/assets/www/dist/dist_js/plugins/es/js/services/http-services.js b/assets/www/dist/dist_js/plugins/es/js/services/http-services.js index 5305832e763828ae36a34fa8a8dbe80ef736c6a5..d528149dae91f7eb2270f820cd4cb4a6ad5a55c7 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/http-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/http-services.js @@ -3,8 +3,8 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic /** * Elastic Search Http */ -.factory('esHttp', ['$q', '$timeout', '$rootScope', '$state', '$sce', '$translate', '$window', '$filter', 'CryptoUtils', 'UIUtils', 'csHttp', 'csConfig', 'csSettings', 'BMA', 'csWallet', 'csPlatform', 'Api', function($q, $timeout, $rootScope, $state, $sce, $translate, $window, $filter, - CryptoUtils, UIUtils, csHttp, csConfig, csSettings, BMA, csWallet, csPlatform, Api) { +.factory('esHttp', ['$q', '$timeout', '$rootScope', '$state', '$sce', '$translate', '$window', '$filter', 'CryptoUtils', 'UIUtils', 'csHttp', 'csConfig', 'csSettings', 'csCache', 'BMA', 'csWallet', 'csPlatform', 'Api', function($q, $timeout, $rootScope, $state, $sce, $translate, $window, $filter, + CryptoUtils, UIUtils, csHttp, csConfig, csSettings, csCache, BMA, csWallet, csPlatform, Api) { 'ngInject'; // Allow to force SSL connection with port different from 443 @@ -14,12 +14,14 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic console.debug('[ES] [https] Enable SSL (forced by config or detected in URL)'); } - function Factory(host, port, wsPort, useSsl) { + function EsHttp(host, port, useSsl, useCache) { var that = this, + cachePrefix = 'esHttp-', constants = { - ES_USER_API_ENDPOINT: 'ES_USER_API( ([a-z_][a-z0-9-_.]*))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))' + ES_USER_API_ENDPOINT: 'ES_USER_API( ([a-z_][a-z0-9-_.]*))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))', + MAX_UPLOAD_BODY_SIZE: csConfig.plugins && csConfig.plugins.es && csConfig.plugins.es.maxUploadBodySize || 2097152 /*=2M*/ }, regexp = { IMAGE_SRC: exact('data:([A-Za-z//]+);base64,(.+)'), @@ -41,22 +43,22 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic that.started = false; that.init = init; - init(host, port, wsPort, useSsl); + init(host, port, useSsl, useCache); + that.useCache = angular.isDefined(useCache) ? useCache : false; // need here because used in get() function - function init(host, port, wsPort, useSsl) { + function init(host, port, useSsl, useCache) { // Use settings as default if (!host && csSettings.data) { host = host || (csSettings.data.plugins && csSettings.data.plugins.es ? csSettings.data.plugins.es.host : null); port = port || (host ? csSettings.data.plugins.es.port : null); - wsPort = wsPort || (host ? csSettings.data.plugins.es.wsPort : null); useSsl = angular.isDefined(useSsl) ? useSsl : (port == 443 || csSettings.data.plugins.es.useSsl || forceUseSsl); } that.alive = false; that.host = host; that.port = port || ((useSsl || forceUseSsl) ? 443 : 80); - that.wsPort = wsPort || that.port; that.useSsl = angular.isDefined(useSsl) ? useSsl : (that.port == 443 || forceUseSsl); + that.server = csHttp.getServer(host, port); } @@ -67,15 +69,13 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic var host = data.plugins.es.host; var useSsl = data.plugins.es.port == 443 || data.plugins.es.useSsl || forceUseSsl; var port = data.plugins.es.port || (useSsl ? 443 : 80); - var wsPort = data.plugins.es.wsPort || port; - return isSameNode(host, port, wsPort, useSsl); + return isSameNode(host, port, useSsl); } - function isSameNode(host, port, wsPort, useSsl) { + function isSameNode(host, port, useSsl) { return (that.host == host) && (that.port == port) && - (!wsPort || that.wsPort == wsPort) && (angular.isUndefined(useSsl) || useSsl == that.useSsl); } @@ -129,46 +129,56 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic sock.close(); }); that.cache = _emptyCache(); + + csCache.clear(cachePrefix); }; that.copy = function(otherNode) { if (that.started) that.stop(); - that.init(otherNode.host, otherNode.port, otherNode.wsPort, otherNode.useSsl || otherNode.port == 443); + that.init(otherNode.host, otherNode.port, otherNode.useSsl || otherNode.port == 443); that.data.isTemporary = false; // reset temporary flag return that.start(true /*skipInit*/); }; - - - // Get time (UTC) - that.date = { now : csHttp.date.now }; + that.byteCount = function (s) { + s = (typeof s == 'string') ? s : JSON.stringify(s); + return encodeURI(s).split(/%(?:u[0-9A-F]{2})?[0-9A-F]{2}|./).length - 1; + }; that.getUrl = function(path) { return csHttp.getUrl(that.host, that.port, path, that.useSsl); }; - that.get = function (path) { + that.get = function (path, cacheTime) { + + cacheTime = that.useCache && cacheTime; + var cacheKey = path + (cacheTime ? ('#'+cacheTime) : ''); - var getRequest = function(params) { + var getRequestFn = function(params) { if (!that.started) { if (!that._startPromise) { - console.error('[ES] [http] Trying to get [{0}] before start()...'.format(path)); + console.error('[ES] [http] Trying to get [{0}] before start(). Waiting...'.format(path)); } return that.ready().then(function(start) { if (!start) return $q.reject('ERROR.ES_CONNECTION_ERROR'); - return getRequest(params); // loop + return getRequestFn(params); // loop }); } - var request = that.cache.getByPath[path]; + var request = that.cache.getByPath[cacheKey]; if (!request) { - request = csHttp.get(that.host, that.port, path, that.useSsl); - that.cache.getByPath[path] = request; + if (cacheTime) { + request = csHttp.getWithCache(that.host, that.port, path, that.useSsl, cacheTime, null, null, cachePrefix); + } + else { + request = csHttp.get(that.host, that.port, path, that.useSsl); + } + that.cache.getByPath[cacheKey] = request; } return request(params); }; - return getRequest; + return getRequestFn; }; that.post = function(path) { @@ -197,7 +207,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic return function() { var sock = that.cache.wsByPath[path]; if (!sock) { - sock = csHttp.ws(that.host, that.wsPort, path, that.useSsl); + sock = csHttp.ws(that.host, that.port, path, that.useSsl); that.cache.wsByPath[path] = sock; } return sock; @@ -208,8 +218,8 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic return csHttp.get(that.host, that.port, '/node/summary', that.useSsl)() .then(function(json) { var software = json && json.duniter && json.duniter.software || 'unknown'; - if (software == 'duniter4j-elasticsearch') return true; - console.error("[ES] [http] Not a Duniter4j ES node, but a {0} node".format(software)); + if (software === "cesium-plus-pod" || software === "duniter4j-elasticsearch") return true; + console.error("[ES] [http] Not a Cesium+ Pod, but a {0} node. Please check '/node/summary'".format(software)); return false; }) .catch(function() { @@ -232,8 +242,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Remember the default node defaultSettingsNode = defaultSettingsNode || { host: settings.host, - port: settings.port, - wsPort: settings.wsPort + port: settings.port }; var fallbackNode = settings.fallbackNodes && fallbackNodeIndex < settings.fallbackNodes.length && settings.fallbackNodes[fallbackNodeIndex++]; @@ -251,7 +260,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic that.cleanCache(); - that.init(fallbackNode.host, fallbackNode.port, fallbackNode.wsPort, fallbackNode.useSsl || fallbackNode.port == 443); + that.init(fallbackNode.host, fallbackNode.port, fallbackNode.useSsl || fallbackNode.port == 443); // check is alive then loop return that.isAlive().then(that.checkNodeAlive); @@ -284,7 +293,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic that.server, (that.useSsl ? ' (SSL on)' : '') )); - var now = new Date().getTime(); + var now = Date.now(); return that.checkNodeAlive() .then(function(alive) { @@ -300,7 +309,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Add listeners addListeners(); - console.debug('[ES] [http] Started in '+(new Date().getTime()-now)+'ms'); + console.debug('[ES] [http] Started in '+(Date.now()-now)+'ms'); that.api.node.raise.start(); @@ -343,10 +352,9 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic prefix = prefix || '#'; var reg = prefix === '@' ? regexp.USER_TAG : regexp.HASH_TAG; var matches = value && reg.exec(value); - var tags; + var tags = matches && []; while(matches) { var tag = matches[1]; - tags = tags || []; if (!_.contains(tags, tag)) { tags.push(tag); } @@ -358,10 +366,9 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic function parseUrlsFromText(value) { var matches = value && regexp.URL.exec(value); - var urls; + var urls = matches && []; while(matches) { var url = matches[0]; - urls = urls || []; if (!_.contains(urls, url)) { urls.push(url); } @@ -390,8 +397,10 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Replace URL in description var urls = parseUrlsFromText(content); _.forEach(urls, function(url){ + // Make sure protocol is defined + var href = (url.startsWith('http://') || url.startsWith('https://')) ? url : ('http://' + url); // Redirect URL to the function 'openLink', to open a new window if need (e.g. desktop app) - var link = '<a on-tap=\"openLink($event, \'{0}\')\" href=\"{1}\" target="_blank">{2}</a>'.format(url, url, truncUrlFilter(url)); + var link = '<a on-tap=\"openLink($event, \'{0}\')\" href=\"{1}\" target="_blank">{2}</a>'.format(href, href, truncUrlFilter(url)); content = content.replace(url, link); }); @@ -404,9 +413,9 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Replace user tags var userTags = parseTagsFromText(content, '@'); - _.forEach(userTags, function(uid){ - var link = '<a ui-sref=\"{0}({uid: \'{1}\'})\">@{2}</a>'.format(options.uidState, uid, uid); - content = content.replace('@'+uid, link); + _.forEach(userTags, function(tag){ + var link = '<a ui-sref=\"{0}({uid: \'{1}\'})\">@{2}</a>'.format(options.uidState, tag, tag); + content = content.replace('@'+tag, link); }); } return content; @@ -440,21 +449,40 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic function postRecord(path, options) { options = options || {}; var postRequest = that.post(path); - return function(record, params) { - return csWallet.auth() - .then(function(walletData) { + return function(record, options) { + options = options || {}; + var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) || + ((!options.pubkey || csWallet.isUserPubkey(options.pubkey)) && csWallet) || + (options.pubkey && csWallet.children.getByPubkey(options.pubkey)); + + var keypair = options.keypair || wallet && wallet.data && wallet.data.keypair; + + if (!keypair && !wallet) { + throw new Error('Missing wallet or keypair, to sign record'); + } + + // Create the POSt request params, + // but BEFORE, remove protected options + delete options.wallet; + delete options.walletId; + delete options.keypair; + var params = angular.copy(options); + params.pubkey = params.pubkey || wallet.data.pubkey; + + return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true})) + .then(function() { if (options.creationTime && !record.creationTime) { - record.creationTime = that.date.now(); + record.creationTime = moment().utc().unix(); } // Always update the time - fix #572 // Make sure time is always > previous (required by ES node) - var now = that.date.now(); + var now = moment().utc().unix(); record.time = (!record.time || record.time < now) ? now : (record.time+1); var obj = angular.copy(record); delete obj.signature; delete obj.hash; - obj.issuer = walletData.pubkey; + obj.issuer = params.pubkey; // force keypair pubkey if (!obj.version) { obj.version = 2; } @@ -464,29 +492,41 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic fillRecordTags(obj, options.tagFields); } - //console.debug("Will send obj: ", obj); - var str = JSON.stringify(obj); - - return CryptoUtils.util.hash(str) - .then(function(hash) { - return CryptoUtils.sign(hash, walletData.keypair) - .then(function(signature) { - // Prepend hash+signature - str = '{"hash":"{0}","signature":"{1}",'.format(hash, signature) + str.substring(1); - // Send data - return postRequest(str, params) - .then(function (id){ - return id; - }); - }); - }); - }); + var str = JSON.stringify(obj); + + return CryptoUtils.util.hash(str) + .then(function(hash) { + return CryptoUtils.sign(hash, keypair) + .then(function(signature) { + // Prepend hash+signature + str = '{"hash":"{0}","signature":"{1}",'.format(hash, signature) + str.substring(1); + // Send data + return postRequest(str, params) + .then(function (id){ + + // Clear cache + csCache.clear(cachePrefix); + + return id; + }) + .catch(function(err) { + var bodyLength = that.byteCount(obj); + if (bodyLength > constants.MAX_UPLOAD_BODY_SIZE) { + throw {message: 'ERROR.ES_MAX_UPLOAD_BODY_SIZE', length: bodyLength}; + } + throw err; + }); + }); + }); + }); }; } function removeRecord(index, type) { - return function(id) { - return (csWallet.isAuth() ? $q.when(csWallet.data) : csWallet.auth({silent: true, minData: true})) + return function(id, options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true})) .then(function(walletData) { var obj = { @@ -495,7 +535,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic type: type, id: id, issuer: walletData.pubkey, - time: that.date.now() + time: moment().utc().unix() }; var str = JSON.stringify(obj); return CryptoUtils.util.hash(str) @@ -586,11 +626,13 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic function parseEndPoint(endpoint) { var matches = regexp.ES_USER_API_ENDPOINT.exec(endpoint); if (!matches) return; + var port = matches[8] || 80; return { "dns": matches[2] || '', "ipv4": matches[4] || '', "ipv6": matches[6] || '', - "port": matches[8] || 80 + "port": port, + "useSsl": port == 80 ? false : (port == 443) }; } @@ -631,6 +673,10 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic sameAsSettings: isSameNodeAsSettings, isFallback: isFallbackNode }, + network: { + peering: that.get('/network/peering'), + peers: that.get('/network/peers') + }, record: { post: postRecord, remove: removeRecord @@ -647,6 +693,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic parseAsHtml: parseAsHtml, findObjectInTree: findObjectInTree }, + cache: csHttp.cache, constants: constants }; exports.constants.regexp = regexp; @@ -654,10 +701,10 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic } - var service = new Factory(); + var service = new EsHttp(undefined, undefined, undefined, true); - service.instance = function(host, port, wsPort, useSsl) { - return new Factory(host, port, wsPort, useSsl); + service.instance = function(host, port, useSsl, useCache) { + return new EsHttp(host, port, useSsl, useCache); }; return service; diff --git a/assets/www/dist/dist_js/plugins/es/js/services/invitation-services.js b/assets/www/dist/dist_js/plugins/es/js/services/invitation-services.js index 57f9f15c2899d655621c20e55e6f944ac0119690..7ca0b3dd845c8e0a0de98383580143b19a6d8b67 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/invitation-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/invitation-services.js @@ -39,6 +39,7 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', function onWalletInit(data) { data.invitations = data.invitations || {}; data.invitations.unreadCount = null; + data.invitations.time = null; } function onWalletReset(data) { @@ -47,22 +48,33 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', } } - function onWalletLogin(data, deferred) { + function onWalletLoad(data, deferred) { deferred = deferred || $q.defer(); if (!data || !data.pubkey) { deferred.resolve(); return deferred.promise; } - console.debug('[ES] [invitations] Loading count...'); - var now = new Date().getTime(); + var now = Date.now(); + var time = Math.trunc(now / 1000); - // Count unread messages + // Skip if loaded less than 1 min ago + // (This is need to avoid reload on login AND load phases) + if (data.invitations && data.invitations.time && (time - data.invitations.time < 30 /*=30s*/)) { + console.debug('[ES] [invitation] Skipping load (loaded '+(time - data.invitations.time)+'s ago)'); + deferred.resolve(); + return deferred.promise; + } + + console.debug('[ES] [invitation] Loading count...'); + + // Count unread invitations countUnreadInvitations(data.pubkey) .then(function(unreadCount){ data.invitations = data.invitations || {}; data.invitations.unreadCount = unreadCount; - console.debug('[ES] [invitation] Loaded count (' + unreadCount + ') in '+(new Date().getTime()-now)+'ms'); + data.invitations.time = time; + console.debug('[ES] [invitation] Loaded count (' + unreadCount + ') in '+(Date.now()-now)+'ms'); deferred.resolve(data); }) .catch(function(err){ @@ -142,11 +154,13 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }); } - function sendInvitation(record, keypair, type) { - type = type || 'certification'; + function sendInvitation(record, options) { + options = options || {}; + options.type = options.type || 'certification'; + var keypair = options.keypair || (options.wallet && options.wallet.data.keypair); return esWallet.box.record.pack(record, keypair, 'recipient', ['content', 'comment']) .then(function(record) { - return that.raw[type].add(record); + return that.raw[options.type].add(record, options); }); } @@ -180,16 +194,18 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }); } - function loadInvitations(options) { + function loadInvitations(options, keypair) { if (!csWallet.isLogin()) return $q.when([]); // Should never happen options = options || {}; options.from = options.from || 0; options.size = options.size || constants.DEFAULT_LOAD_SIZE; + + var issuer = options.issuer || csWallet.data.pubkey; var request = { sort: { "time" : "desc" }, - query: {bool: {filter: {term: {recipient: csWallet.data.pubkey}}}}, + query: {bool: {filter: {term: {recipient: issuer}}}}, from: options.from, size: options.size, _source: fields.commons @@ -200,13 +216,8 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', query.bool.must = [{range: {time: {gt: options.readTime}}}]; } - return $q.all([ - esWallet.box.getKeypair(), - that.raw.certification.postSearch(request) - ]) + return that.raw.certification.postSearch(request) .then(function(res) { - var keypair = res[0]; - res = res[1]; if (!res || !res.hits || !res.hits.total) return []; var invitations = res.hits.hits.reduce(function (result, hit) { @@ -264,42 +275,47 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }); } - function deleteInvitation(invitation) { + function deleteInvitation(invitation, options) { if (!invitation || !invitation.id) throw 'Invalid invitation (empty or without id). Could not delete.'; var type = invitation.type || 'certification'; - return that.raw[type].remove(invitation.id) + var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet; + return that.raw[type].remove(invitation.id, {wallet: wallet}) .then(function() { // Always reset unread count - csWallet.data.invitations.unreadCount = 0; + wallet.data.invitations.unreadCount = 0; - if (!csWallet.data.invitations || !csWallet.data.invitations.list) return; + if (!wallet.data.invitations || !wallet.data.invitations.list) return; // Remove form list - csWallet.data.invitations.list.splice(csWallet.data.invitations.list.indexOf(invitation), 1); + wallet.data.invitations.list.splice(wallet.data.invitations.list.indexOf(invitation), 1); }); } - function deleteInvitationsByIds(ids, type) { + function deleteInvitationsByIds(ids, type, options) { if (!ids || !ids.length) return $q.when(); type = type || 'certification'; return $q.all( ids.reduce(function(res, id) { - return res.concat(that.raw[type].remove(id)); + return res.concat(that.raw[type].remove(id, options)); }, []) ); } - function deleteAllInvitations(pubkey, type) { - pubkey = pubkey || csWallet.data.pubkey; + function deleteAllInvitationsByPubkey(type, options) { + type = type || 'certification'; - console.debug('[ES] [invitation] Deleting all invitations...'); - var now = new Date().getTime(); - var countBeforeDeletion = (csWallet.data.invitations && csWallet.data.invitations.count) || 0; - var unreadCountBeforeDeletion = (csWallet.data.invitations && csWallet.data.invitations.unreadCount) || 0; + var now = Date.now(); + console.debug('[ES] [invitation] Deleting all {0} invitations...'.format(type)); + + var wallet = (options && options.pubkey && csWallet.children.getByPubkey(options.pubkey)) || + (options && options.walletId && csWallet.children.getByPubkey(options.walletId)) || + csWallet; + var countBeforeDeletion = (wallet.data.invitations && wallet.data.invitations.count) || 0; + var unreadCountBeforeDeletion = (wallet.data.invitations && wallet.data.invitations.unreadCount) || 0; // Get invitation ids - return that.raw[type].getIds({pubkey: pubkey}) + return that.raw[type].getIds({pubkey: wallet.data.pubkey}) .then(function(res) { if (!res || !res.hits || !res.hits.total) return; var ids = res.hits.hits.reduce(function (res, hit) { @@ -307,26 +323,26 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }, []); // Do deletion by ids - return deleteInvitationsByIds(ids, type) + return deleteInvitationsByIds(ids, type, {walletId: wallet.id}) .then(function() { // Update wallet count - csWallet.data.invitations = csWallet.data.invitations || {}; + wallet.data.invitations = wallet.data.invitations || {}; // Decrement count (warning: could have received new invitations during deletion execution) - if (csWallet.data.invitations.count >= countBeforeDeletion) { - csWallet.data.invitations.count -= countBeforeDeletion || 0; + if (wallet.data.invitations.count >= countBeforeDeletion) { + wallet.data.invitations.count -= countBeforeDeletion || 0; } else { - csWallet.data.invitations.count = 0; + wallet.data.invitations.count = 0; } // Decrement count (warning: could have received new invitations during deletion execution) - if (csWallet.data.invitations.unreadCount >= unreadCountBeforeDeletion) { - csWallet.data.invitations.unreadCount -= unreadCountBeforeDeletion || 0; + if (wallet.data.invitations.unreadCount >= unreadCountBeforeDeletion) { + wallet.data.invitations.unreadCount -= unreadCountBeforeDeletion || 0; } else { - csWallet.data.invitations.unreadCount = 0; + wallet.data.invitations.unreadCount = 0; } - console.debug('[ES] [invitation] All invitations deleted in {0}ms'.format(new Date().getTime()-now)); + console.debug('[ES] [invitation] All {0} invitations deleted in {1}ms'.format(type, Date.now()-now)); }); }); } @@ -342,8 +358,9 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', function addListeners() { // Extend csWallet events listeners = [ - csWallet.api.data.on.login($rootScope, onWalletLogin, this), csWallet.api.data.on.init($rootScope, onWalletInit, this), + csWallet.api.data.on.login($rootScope, onWalletLoad, this), + csWallet.api.data.on.load($rootScope, onWalletLoad, this), csWallet.api.data.on.reset($rootScope, onWalletReset, this), csWallet.api.action.on.certify($rootScope, onWalletCertify, this), esNotification.api.event.on.newInvitation($rootScope, onNewInvitationEvent, this) @@ -363,7 +380,7 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', console.debug("[ES] [invitations] Enable"); addListeners(); if (csWallet.isLogin()) { - onWalletLogin(csWallet.data); + onWalletLoad(csWallet.data); } } } @@ -385,7 +402,7 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', that.send = sendInvitation; that.delete = deleteInvitation; that.deleteByIds = deleteInvitationsByIds; - that.deleteAll = deleteAllInvitations; + that.deleteAll = deleteAllInvitationsByPubkey; that.constants = constants; diff --git a/assets/www/dist/dist_js/plugins/es/js/services/message-services.js b/assets/www/dist/dist_js/plugins/es/js/services/message-services.js index 2a93b158e049d8166b3abacc49758eecc347e0d3..3631fe44d97c30a217ac56e5e65278c3a6372d41 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/message-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/message-services.js @@ -35,6 +35,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', function onWalletInit(data) { data.messages = data.messages || {}; data.messages.unreadCount = null; + data.messages.time = null; } function onWalletReset(data) { @@ -43,35 +44,50 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } } - function onWalletLogin(data, deferred) { + function onWalletLoad(data, deferred) { deferred = deferred || $q.defer(); + if (!data || !data.pubkey) { deferred.resolve(); return deferred.promise; } + var now = Date.now(); + var time = Math.trunc(now / 1000); + + // Skip if loaded less than 1 min ago + // (This is need to avoid reload on login AND load phases) + if (data.messages && data.messages.time && (time - data.messages.time < 30 /*=30s*/)) { + console.debug('[ES] [message] Skipping load (loaded '+(time - data.messages.time)+'s ago)'); + deferred.resolve(); + return deferred.promise; + } + console.debug('[ES] [message] Loading count...'); - var now = new Date().getTime(); // Count unread messages - countUnreadMessages(data.pubkey) - .then(function(unreadCount){ + countUnreadMessages({pubkey: data.pubkey}) + .then(function(unreadCount) { data.messages = data.messages || {}; data.messages.unreadCount = unreadCount; - console.debug('[ES] [message] Loaded count (' + unreadCount + ') in '+(new Date().getTime()-now)+'ms'); + data.messages.time = time; + console.debug('[ES] [message] Loaded count (' + unreadCount + ') in '+(Date.now()-now)+'ms'); deferred.resolve(data); }) .catch(function(err){ - console.error('Error chile counting message: ' + (err.message ? err.message : err)); + console.error('Error while counting messages: ' + (err.message ? err.message : err)); deferred.resolve(data); }); return deferred.promise; } - function countUnreadMessages(pubkey) { - pubkey = pubkey || (csWallet.isLogin() ? csWallet.data.pubkey : pubkey); + function countUnreadMessages(options) { + options = options || {}; + var wallet = options.wallet || + (options.walletId && csWallet.children.get(options.walletId)) || csWallet; + var pubkey = options.pubkey || (wallet && wallet.data && wallet.data.pubkey); if (!pubkey) { - throw new Error('no pubkey, and user not connected.'); + throw new Error('no pubkey or wallet found in options, and user not connected.'); } var request = { @@ -92,33 +108,50 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } // Listen message changes - function onNewMessageEvent(event) { + function onNewMessageEvent(event, wallet) { console.debug("[ES] [message] detected new message (from notification service)"); - var notification = new Notification(event); + var notification = new EsNotification(event); notification.issuer = notification.pubkey; delete notification.pubkey; + if (!notification.issuer) return; // Skip if invalid + + // Get the wallet + wallet = wallet || (notification.issuer && csWallet.isUserPubkey(notification.issuer) && csWallet) || + (notification.issuer && csWallet.children.getByPubkey(notification.issuer)); + + if (!wallet) { + throw new Error("No wallet for pubkey: {0}".format(notification.issuer.substring(0, 6))); + } + csWot.extend(notification, 'issuer') .then(function() { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount++; + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.unreadCount++; // Raise event api.data.raise.new(notification); }); } - function sendMessage(message) { - return csWallet.getKeypair() + function sendMessage(message, options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + delete options.wallet; + message.issuer = message.issuer || wallet.data.pubkey; + return wallet.getKeypair() .then(function(keypair) { + + // Send to recipient inbox return doSendMessage(message, keypair) .then(function (res) { + + // Check if outbox is enable (in settings) var outbox = (csSettings.data.plugins.es.message && angular.isDefined(csSettings.data.plugins.es.message.outbox)) ? csSettings.data.plugins.es.message.outbox : true; - if (!outbox) return res; // Send to outbox @@ -129,7 +162,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }); }) .then(function (res) { - // Raise event + // Raise API event api.data.raise.sent(res); return res; @@ -144,22 +177,25 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', return esWallet.box.record.pack(message, keypair, recipientFieldName, ['title', 'content']) // Send message .then(function(message){ - return esHttp.record.post(boxPath)(message); + return esHttp.record.post(boxPath)(message, {pubkey: message.issuer, keypair: keypair}); }); } function loadMessageNotifications(options) { - if (!csWallet.isLogin()) { - return $q.when([]); // Should never happen - } options = options || {}; options.from = options.from || 0; options.size = options.size || constants.DEFAULT_LOAD_SIZE; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + delete options.wallet; + + if (!wallet.isLogin()) { + return $q.when([]); // Should never happen + } var request = { sort: { "time" : "desc" }, - query: {bool: {filter: {term: {recipient: csWallet.data.pubkey}}}}, + query: {bool: {filter: {term: {recipient: wallet.data.pubkey}}}}, from: options.from, size: options.size, _source: fields.notifications @@ -231,7 +267,10 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', options.filter = angular.isDefined(options.filter) ? options.filter : undefined; options.from = options.from || 0; - var promise = csWallet.auth() + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + delete options.wallet; // avoid error in angular.copy() + + var promise = wallet.auth() .then(function(walletData) { // Get encrypted message (with common fields) @@ -254,12 +293,15 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', if (messages.length && options.filter){ var filteredMessages = filterMessages(messages, options.filter); - // Recursive loop, if need more + // Need more messages: iterate again if (filteredMessages.length < messages.length) { options = angular.copy(options); options.from += options.size; options.size = messages.length - filteredMessages.length; - return loadMessages(options) + // put the wallet again, because it has been removed before the angular.copy() + // To avoid an error + options.wallet = wallet; + return loadMessages(options) // Loop .then(function(messages) { return filteredMessages.concat(messages); }); @@ -267,8 +309,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } if (options.from === 0 && !options.filter) { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = messages.length; + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.count = messages.length; } return messages; @@ -282,19 +324,20 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', return promise; } - function getAndDecrypt(id, options) { + function getAndDecrypt(id, type, options) { + type = type || 'inbox'; options = options || {}; - options.type = options.type || 'inbox'; options.summary = angular.isDefined(options.summary) ? options.summary : false/*summary not need by default*/; + var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) || csWallet; - return csWallet.auth() + return wallet.auth() .then(function(walletData) { - return raw.getByTypeAndId({id: id, type: options.type}) + return raw.getByTypeAndId({id: id, type: type}) .then(function(hit) { if (!hit.found) return; var msg = hit._source; msg.id = hit._id; - msg.read = (options.type == 'outbox') || !!msg.read_signature; + msg.read = (type == 'outbox') || !!msg.read_signature; delete msg.read_signature; // not need anymore // Decrypt message @@ -302,7 +345,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Add avatar .then(function(){ - var avatarField = (options.type == 'inbox') ? 'issuer' : 'recipient'; + var avatarField = (type == 'inbox') ? 'issuer' : 'recipient'; return csWot.extend(msg, avatarField); }); }); @@ -311,7 +354,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', function decryptMessages(messages, keypair, withSummary) { - var now = new Date().getTime(); + var now = Date.now(); var issuerBoxPks = {}; // a map used as cache var jobs = [esWallet.box.getKeypair(keypair)]; @@ -362,7 +405,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }, [])); }) .then(function() { - console.debug('[ES] [message] All messages decrypted in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[ES] [message] All messages decrypted in ' + (Date.now() - now) + 'ms'); return messages; }); @@ -378,26 +421,32 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } } - function removeMessage(id, type) { + function removeMessage(id, type, options) { type = type || 'inbox'; - return esHttp.record.remove('message', type)(id) + + var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) || csWallet; + + return esHttp.record.remove('message', type)(id, {wallet: wallet}) .then(function(res) { - // update message count - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = csWallet.data.messages.count > 0 ? csWallet.data.messages.count-1 : 0; + // Update message count + if (type === 'inbox') { + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.count = wallet.data.messages.count > 0 ? wallet.data.messages.count-1 : 0; } + // Raise event - api.data.raise.delete(id); + if (wallet.isDefault()) { + api.data.raise.delete(id); + } return res; }); } - function removeAllMessages(type) { + function removeAllMessages(type, options) { type = type || 'inbox'; - - return csWallet.auth() + var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet; + return wallet.auth() .then(function(walletData) { // Get all message id return searchMessages(walletData.pubkey, {type: type, from: 0, size: 1000, _source: false}) @@ -408,7 +457,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Remove each messages return $q.all(res.reduce(function (res, msg) { - return res.concat(esHttp.record.remove('message', type)(msg.id, walletData)); + return res.concat(esHttp.record.remove('message', type)(msg.id, {wallet: wallet})); }, [])) .then(function() { return ids; @@ -416,21 +465,25 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }) .then(function (ids) { // update message count - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = 0; - csWallet.data.messages.unreadCount = 0; + if (type === 'inbox') { + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.count = 0; + wallet.data.messages.unreadCount = 0; } // Raise events - _.forEach(ids, api.data.raise.delete); + if (wallet.isDefault()) { + _.forEach(ids, api.data.raise.delete); + } }); }); } // Mark a message as read - function markMessageAsRead(message, type) { - type = type || 'inbox'; + function markMessageAsRead(message, options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + var type = options && options.type || (!wallet.isUserPubkey(message.recipient) ? 'outbox' : 'inbox'); if (message.read) { var deferred = $q.defer(); deferred.resolve(); @@ -438,7 +491,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } message.read = true; - return csWallet.getKeypair() + return wallet.getKeypair() // Prepare the read_signature to sent .then(function(keypair) { @@ -452,16 +505,18 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Update message count .then(function() { - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount = csWallet.data.messages.unreadCount ? csWallet.data.messages.unreadCount - 1 : 0; + if (type === 'inbox') { + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.unreadCount = wallet.data.messages.unreadCount ? wallet.data.messages.unreadCount - 1 : 0; } }); } // Mark all messages as read - function markAllMessageAsRead() { - return csWallet.auth() + function markAllMessageAsRead(options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + return wallet.auth() .then(function(walletData) { // Get all messages hash @@ -491,8 +546,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }) .then(function () { // update message count - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount = 0; + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.unreadCount = 0; }); }); } @@ -574,7 +629,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', console.info("[ES] [message] Sending logs to developers..."); message.issuer = csWallet.data.pubkey; message.title = message.title || 'Sending log'; - message.time = esHttp.date.now(); + message.time = moment().utc().unix(); csWallet.getKeypair() .then(function(keypair) { @@ -598,8 +653,9 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', function addListeners() { // Extend csWallet events listeners = [ - csWallet.api.data.on.login($rootScope, onWalletLogin, this), csWallet.api.data.on.init($rootScope, onWalletInit, this), + csWallet.api.data.on.login($rootScope, onWalletLoad, this), + csWallet.api.data.on.load($rootScope, onWalletLoad, this), // need for secondary wallets csWallet.api.data.on.reset($rootScope, onWalletReset, this), esNotification.api.event.on.newMessage($rootScope, onNewMessageEvent, this), // for issue #524 @@ -620,7 +676,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', console.debug("[ES] [message] Enable"); addListeners(); if (csWallet.isLogin()) { - onWalletLogin(csWallet.data); + onWalletLoad(csWallet.data); } } } diff --git a/assets/www/dist/dist_js/plugins/es/js/services/modal-services.js b/assets/www/dist/dist_js/plugins/es/js/services/modal-services.js index f0619109858741a7051e7bf340ceefecc07b9e53..06e53471f8128dbf001c40746b3cbaf189be8f2d 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/modal-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/modal-services.js @@ -8,25 +8,12 @@ angular.module('cesium.es.modal.services', ['cesium.modal.services', 'cesium.es. parameters, {focusFirstInput: true}); } - function updateNotificationCountAndReadTime() { - csWallet.data.notifications.unreadCount = 0; - if (csWallet.data.notifications && csWallet.data.notifications.history.length) { - var lastNotification = csWallet.data.notifications.history[0]; - var readTime = lastNotification ? lastNotification.time : 0; - csSettings.data.wallet = csSettings.data.wallet || {}; - if (readTime && csSettings.data.wallet.notificationReadTime != readTime) { - csSettings.data.wallet.notificationReadTime = readTime; - csSettings.store(); - } - } - } - function showNotificationsPopover(scope, event) { return UIUtils.popover.show(event, { templateUrl :'plugins/es/templates/common/popover_notification.html', scope: scope, autoremove: false, // reuse popover - afterHidden: updateNotificationCountAndReadTime + afterHidden: scope.resetUnreadCount }) .then(function(notification) { if (!notification) return; // no selection @@ -51,8 +38,9 @@ angular.module('cesium.es.modal.services', ['cesium.modal.services', 'cesium.es. }); } - function showNewPage() { - return csWallet.auth({minData: true}) + function showNewPage(options) { + var wallet = options && options.wallet || csWallet; + return wallet.auth({minData: true}) .then(function() { UIUtils.loading.hide(); @@ -61,7 +49,7 @@ angular.module('cesium.es.modal.services', ['cesium.modal.services', 'cesium.es. }) .then(function(type){ if (type) { - $state.go('app.registry_add_record', {type: type}); + $state.go('app.registry_add_record', {type: type, wallet: wallet.id}); } }); }); diff --git a/assets/www/dist/dist_js/plugins/es/js/services/notification-services.js b/assets/www/dist/dist_js/plugins/es/js/services/notification-services.js index 6fc01d7686361080b77f17bb915a740f38f17da2..a0326e834535fbe6b850dfdec904419d03227c74 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/notification-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/notification-services.js @@ -10,7 +10,9 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es }]) -.factory('esNotification', ['$rootScope', '$q', '$timeout', 'esHttp', 'csConfig', 'csSettings', 'csWallet', 'csWot', 'UIUtils', 'BMA', 'CryptoUtils', 'csPlatform', 'Api', function($rootScope, $q, $timeout, esHttp, csConfig, csSettings, csWallet, csWot, UIUtils, BMA, CryptoUtils, csPlatform, Api) { +.factory('esNotification', ['$rootScope', '$q', '$timeout', '$translate', '$state', 'csHttp', 'csConfig', 'csSettings', 'esHttp', 'esSettings', 'csWallet', 'csWot', 'UIUtils', 'filterTranslations', 'BMA', 'CryptoUtils', 'csPlatform', 'Api', function($rootScope, $q, $timeout, $translate, $state, csHttp, + csConfig, csSettings, esHttp, esSettings, csWallet, csWot, UIUtils, filterTranslations, + BMA, CryptoUtils, csPlatform, Api) { 'ngInject'; var @@ -25,6 +27,7 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es }, that = this, listeners, + wsUserEventCloseFn, api = new Api(this, 'esNotification') ; @@ -105,16 +108,51 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es }); } + function getWalletNotifications(options) { + options = options || {}; + var wallet = options.wallet || csWallet; + + return new Promise(function(resolve) { + if (!wallet.data || !wallet.data.events ||!wallet.data.events.length) return resolve([]); + + // Add some wallet events as notifications + var time = csHttp.date.now() - filterTranslations.MEDIAN_TIME_OFFSET; + var result = (wallet.data.events || []).reduce(function(res, event) { + if (event.type != "warn" && event.type != "error") return res; // Keep only warn and error events + var notification = new EsNotification({}, function(self) { + if (!self.read) { + self.read = true; + if (wallet.data.notifications && wallet.data.notifications.warnCount > 0) { + wallet.data.notifications.warnCount--; + } + } + }); + notification.id=event.code; + notification.read = false; + notification.state = 'app.view_wallet'; + notification.avatarIcon = 'ion-alert-circled'; + notification.icon = 'ion-alert-circled assertive'; + notification.time = time; + notification.message = event.message; + notification.messageParams = event.messageParams; + return res.concat(notification); + }, []); + + resolve(result); + }); + + } + // Load user notifications - function loadNotifications(pubkey, options) { - if (!pubkey) { - return $q.reject('[ES] [notification] Unable to load - missing pubkey'); - } + function loadNotifications(options) { options = options || {}; + if (!options.pubkey) { + return $q.reject('[ES] [notification] Unable to load - missing options.pubkey'); + } options.from = options.from || 0; options.size = options.size || constants.DEFAULT_LOAD_SIZE; var request = { - query: createFilterQuery(pubkey, options), + query: createFilterQuery(options.pubkey, options), sort : [ { "time" : {"order" : "desc"}} ], @@ -123,14 +161,24 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es _source: fields.commons }; - return that.raw.postSearch(request) - .then(function(res) { - if (!res.hits || !res.hits.total) return []; + return $q.all([ + // Get wallet events (as notifications) + getWalletNotifications(options), + + // Load notification from ES node + that.raw.postSearch(request) + ]).then(function(res) { + + var walletNotifs = res[0] || []; + res = res[1]; + + if (!res.hits || !res.hits.total) return walletNotifs; + var notifications = res.hits.hits.reduce(function(res, hit) { - var item = new Notification(hit._source, markNotificationAsRead); + var item = new EsNotification(hit._source, markNotificationAsRead); item.id = hit._id; return res.concat(item); - }, []); + }, walletNotifs); return csWot.extendAll(notifications); }); @@ -151,7 +199,7 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es return; } - var notification = new Notification(event, markNotificationAsRead); + var notification = new EsNotification(event, markNotificationAsRead); // Extend the notification entity return csWot.extendAll([notification]) @@ -164,6 +212,9 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es else { addNewNotification(notification); } + }) + .then(function() { + if (esSettings.notifications.isEmitHtml5Enable()) return emitEsNotification(notification); }); } @@ -171,6 +222,66 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es csWallet.data.notifications = csWallet.data.notifications || {}; csWallet.data.notifications.unreadCount++; api.data.raise.new(notification); + + return notification; + } + + function htmlToPlaintext(text) { + return text ? String(text).replace(/<[^>]*>/gm, '').replace(/&[^;]+;/gm, '') : ''; + } + + function emitEsNotification(notification, title) { + + // If it's okay let's create a notification + $q.all([ + $translate(title||'COMMON.NOTIFICATION.TITLE'), + $translate(notification.message, notification) + ]) + .then(function(res) { + var title = htmlToPlaintext(res[0]); + var body = htmlToPlaintext(res[1]); + var icon = notification.avatar && notification.avatar.src || './img/logo.png'; + emitHtml5Notification(title, { + body: body, + icon: icon, + lang: $translate.use(), + tag: notification.id, + onclick: function() { + $rootScope.$applyAsync(function() { + if (typeof notification.markAsRead === "function") { + notification.markAsRead(); + } + if (notification.state) { + $state.go(notification.state, notification.stateParams); + } + }); + } + }); + }); + } + + function emitHtml5Notification(title, options) { + + // Let's check if the browser supports notifications + if (!("Notification" in window)) return; + + // Let's check whether notification permissions have already been granted + if (Notification.permission === "granted") { + + // If it's okay let's create a notification + var browserNotification = new Notification(title, options); + browserNotification.onclick = options.onclick || browserNotification.onclick; + } + + // Otherwise, we need to ask the user for permission + else if (Notification.permission !== "denied") { + Notification.requestPermission(function (permission) { + // If the user accepts, let's create a notification + if (permission === "granted") { + emitHtml5Notification(title, options); // recursive call + } + }); + } } // Mark a notification as read @@ -202,44 +313,82 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es function onWalletReset(data) { data.notifications = data.notifications || {}; data.notifications.unreadCount = null; + data.notifications.warnCount = null; + data.notifications.time = null; // Stop listening notification - that.raw.ws.getUserEvent().close(); + if (wsUserEventCloseFn) { + console.debug("[ES] [notification] Closing websocket..."); + wsUserEventCloseFn(); + wsUserEventCloseFn = null; + } } - function onWalletLogin(data, deferred) { + function onWalletLoad(data, deferred) { deferred = deferred || $q.defer(); if (!data || !data.pubkey || !data.keypair) { deferred.resolve(); return deferred.promise; } - console.debug('[ES] [notification] Loading count...'); - var now = new Date().getTime(); + var now = Date.now(); + var time = Math.trunc(now / 1000); + + // Skip if loaded less than 1 min ago + // (This is need to avoid reload on login AND load phases) + if (data.notifications && data.notifications.time && (time - data.notifications.time < 30 /*=30s*/)) { + // update warn count + data.notifications.warnCount = countWarnEvents(data); + + console.debug('[ES] [notification] Skipping load (loaded '+(time - data.notifications.time)+'s ago)'); + deferred.resolve(); + return deferred.promise; + } + + var isDefaultWallet = csWallet.isUserPubkey(data.pubkey); + console.debug('[ES] [notification] Loading count...' + data.pubkey.substr(0,8)); // Load unread notifications count loadUnreadNotificationsCount( data.pubkey, { - readTime: csSettings.data.wallet ? csSettings.data.wallet.notificationReadTime : 0, + readTime: data.notifications && data.notifications.time || 0, excludeCodes: constants.EXCLUDED_CODES }) .then(function(unreadCount) { data.notifications = data.notifications || {}; data.notifications.unreadCount = unreadCount; - console.debug('[ES] [notification] Loaded count (' + unreadCount + ') in '+(new Date().getTime()-now)+'ms'); + data.notifications.warnCount = countWarnEvents(data); + + // Emit HTML5 notification (only on main wallet) + if (unreadCount > 0 && esSettings.notifications.isEmitHtml5Enable() && isDefaultWallet) { + $timeout(function() { + emitEsNotification({ + message: 'COMMON.NOTIFICATION.HAS_UNREAD', + count: unreadCount, + state: 'app.view_notifications' + }, data.ui || data.name || data.pubkey && data.pubkey.substr(0,8)); + }, 500); + } + + console.debug('[ES] [notification] Loaded count (' + unreadCount + ') in '+(Date.now()-now)+'ms'); deferred.resolve(data); }) - .catch(function(err){ - deferred.reject(err); - }) + .catch(deferred.reject); - // Listen new events + return deferred.promise; + } + + function onWalletLogin(data, deferred) { + // Call load + return onWalletLoad(data, deferred) + + // then start listening new events .then(function(){ console.debug('[ES] [notification] Starting listen user event...'); - var userEventWs = that.raw.ws.getUserEvent(); - listeners.push(userEventWs.close); - return userEventWs.on(onNewUserEvent, - {pubkey: data.pubkey, locale: csSettings.data.locale.id} - ) + var wsUserEvent = that.raw.ws.getUserEvent(); + wsUserEvent.on( + onNewUserEvent, + {pubkey: data.pubkey, locale: csSettings.data.locale.id} + ) .catch(function(err) { console.error('[ES] [notification] Unable to listen user event', err); @@ -247,15 +396,22 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es // And display such connectivity errors in UI UIUtils.alert.error('ACCOUNT.ERROR.WS_CONNECTION_FAILED'); }); + wsUserEventCloseFn = function() {wsUserEvent.close();}; }); + } - return deferred.promise; + function countWarnEvents(data){ + if (!data.events) return 0; + return data.events.reduce(function(counter, event) { + return (event.type == "warn") ? counter+1 : counter; + }, 0); } function addListeners() { // Listen some events listeners = [ csWallet.api.data.on.login($rootScope, onWalletLogin, this), + csWallet.api.data.on.load($rootScope, onWalletLoad, this), csWallet.api.data.on.init($rootScope, onWalletReset, this), csWallet.api.data.on.reset($rootScope, onWalletReset, this) ]; @@ -301,6 +457,9 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es // Exports that.load = loadNotifications; that.unreadCount = loadUnreadNotificationsCount; + that.html5 = { + emit: emitHtml5Notification + }; that.api = api; that.websocket = { event: that.raw.ws.getUserEvent, diff --git a/assets/www/dist/dist_js/plugins/es/js/services/profile-services.js b/assets/www/dist/dist_js/plugins/es/js/services/profile-services.js index 2655d26294a0cbec671af54dc6aec796dbc6daae..f19747f12f2ac06a85cd23f31195802d6e2dacee 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/profile-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/profile-services.js @@ -19,10 +19,10 @@ angular.module('cesium.es.profile.services', ['cesium.services', 'cesium.es.http that.raw = { getFields: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content&_source=:fields'), - get: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content'), - getAll: esHttp.get('/user/profile/:id'), - search: esHttp.post('/user/profile/_search'), - mixedSearch: esHttp.post('/user,page,group/profile,record/_search') + get: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content', esHttp.cache.MEDIUM), + getAll: esHttp.get('/user/profile/:id', esHttp.cache.MEDIUM), + search: esHttp.post('/user/profile/_search', esHttp.cache.MEDIUM), + mixedSearch: esHttp.post('/user,page,group/profile,record/_search', esHttp.cache.MEDIUM) }; function getAvatarAndName(pubkey) { @@ -192,20 +192,16 @@ angular.module('cesium.es.profile.services', ['cesium.services', 'cesium.es.http }; } else { - request.query.constant_score = { - filter: {bool: {should: [ - {terms : {_id : pubkeys}}, - {bool: { - must: [ - {match: {title: {query: text, boost: 2}}}, - {prefix: {title: text}} - ]} - } - ]}} + request.query.bool = { + should: [ + {terms : {"_id^4" : pubkeys}}, + {match: {title: {query: text, boost: 2}}}, + {prefix: {title: text}} + ] }; if (tags) { - request.query.constant_score.filter.bool.should.push({terms: {tags: tags}}); + request.query.bool.should.push({terms: {tags: tags}}); } } } diff --git a/assets/www/dist/dist_js/plugins/es/js/services/settings-services.js b/assets/www/dist/dist_js/plugins/es/js/services/settings-services.js index 705738cd8bf7d82225a4081c9a14f0d85f5e7463..9cf31455d7d40291fc51678e5247be84faeef223 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/settings-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/settings-services.js @@ -16,27 +16,37 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt var SETTINGS_SAVE_SPEC = { - includes: ['locale', 'showUDHistory', 'useRelative', 'useLocalStorage', 'expertMode', 'logoutIdle'], - excludes: ['timeout', 'cacheTimeMs', 'time', 'login', 'build'], + includes: ['locale', 'showUDHistory', 'useRelative', 'useLocalStorage', 'useLocalStorageEncryption', 'expertMode', 'logoutIdle', 'blockValidityWindow'], + excludes: ['timeout', 'cacheTimeMs', 'version', 'build', 'minVersion', 'fallbackLanguage'], plugins: { es: { - excludes: ['enable', 'host', 'port', 'wsPort', 'fallbackNodes'] + excludes: ['enable', 'host', 'port', 'fallbackNodes', 'enableGoogleApi', 'googleApiKey'], + notifications: { + } } }, + wallet: { + includes: ['alertIfUnusedWallet'], + excludes: ['notificationReadTime'] // deprecated - should be removed later + }, helptip: { excludes: ['installDocUrl'] + }, + notifications: { + excludes: ['time', 'warnCount', 'unreadCount'] } }, defaultSettings = angular.merge({ plugins: { es: { askEnable: false, + useRemoteStorage: true, notifications: { - readTime: true, txSent: true, txReceived: true, certSent: true, - certReceived: true + certReceived: true, + emitHtml5: false }, invitations: { readTime: true @@ -77,6 +87,13 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt !!csSettings.data.plugins.es.host; }; + that.notifications = {}; + that.notifications.isEmitHtml5Enable = function() { + return that.isEnable() && + csSettings.data.plugins.es.notifications && + angular.isDefined(csSettings.data.plugins.es.notifications.emitHtml5) ? csSettings.data.plugins.es.notifications.emitHtml5 : false; + }; + that.wot = {}; that.wot.isMixedSearchEnable = function() { return that.isEnable() && @@ -113,7 +130,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt // Load settings function loadSettings(pubkey, boxKeypair) { - var now = new Date().getTime(); + var now = Date.now(); return that.get({id: pubkey}) .catch(function(err){ if (err && err.ucode && err.ucode == 404) { @@ -130,7 +147,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt var record = res._source; // Do not apply if same version if (record.time === csSettings.data.time) { - console.debug('[ES] [settings] Loaded in '+ (new Date().getTime()-now) +'ms, but already up to date'); + console.debug('[ES] [settings] Loaded in '+ (Date.now()-now) +'ms, but already up to date'); return; } var nonce = CryptoUtils.util.decode_base58(record.nonce); @@ -139,7 +156,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt .then(function(json) { var settings = JSON.parse(json || '{}'); settings.time = record.time; - console.debug('[ES] [settings] Loaded and decrypted in '+ (new Date().getTime()-now) +'ms'); + console.debug('[ES] [settings] Loaded and decrypted in '+ (Date.now()-now) +'ms'); return settings; }) // if error: skip stored content @@ -236,8 +253,13 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt return $q.when(); } - var time = esHttp.date.now(); // always update time - console.debug('[ES] [settings] Saving user settings... at time ' + time); + // Skip remote saving, if remote storage disable + if (!csSettings.data.plugins.es.useRemoteStorage) { + return storeSettingsLocally(); + } + + var time = moment().utc().unix(); // always update time + console.debug('[ES] [settings] Saving user settings remotely...'); return $q.all([ csWallet.getKeypair(), // same result as esWallet.box.getKeypair(), because box keypair computed on auth @@ -266,7 +288,13 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt // create or update return angular.isUndefined(data.time) ? that.add(record) : - that.update(record, {id: record.issuer}); + that.update(record, {id: record.issuer}) + .catch(function(err) { + // Workaround if update failed: try to add() instead + // Can occur when changing the cesium+ pod + if (err && err.ucode == 404) return that.add(record); + throw err; + }); }) .then(function() { return true; @@ -277,7 +305,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt // Update settings version, then store (on local store only) data.time = time; previousRemoteData = filteredData; - console.debug('[ES] [settings] Saved user settings in ' + (esHttp.date.now() - time) + 'ms'); + console.debug('[ES] [settings] Saved user settings remotely in ' + (moment().utc().unix() - time) + 'ms'); return storeSettingsLocally(); }) .catch(function(err) { diff --git a/assets/www/dist/dist_js/plugins/es/js/services/social-services.js b/assets/www/dist/dist_js/plugins/es/js/services/social-services.js index b7336bdef833553e80bb12d42fbccb54dfdb7703..ece8393a7db0945deccec0bfeadc66238bebc075 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/social-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/social-services.js @@ -1,6 +1,6 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) - .factory('SocialUtils', ['$filter', '$q', 'CryptoUtils', 'BMA', 'csWallet', 'esCrypto', function($filter, $q, CryptoUtils, BMA, csWallet, esCrypto) { + .factory('SocialUtils', ['$filter', '$q', 'CryptoUtils', 'BMA', 'csWallet', 'esCrypto', '$timeout', function($filter, $q, CryptoUtils, BMA, csWallet, esCrypto, $timeout) { 'ngInject'; function SocialUtils() { @@ -52,7 +52,7 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) urlToMatch = url.substring(0, slashPathIndex); } } - //console.log("match URI, try to match: " + urlToMatch); + //console.debug("match URI, try to match: " + urlToMatch); _.keys(regexp.socials).forEach(function(key){ if (regexp.socials[key].test(urlToMatch)) { type = key; diff --git a/assets/www/dist/dist_js/plugins/es/js/services/subscription-services.js b/assets/www/dist/dist_js/plugins/es/js/services/subscription-services.js index 7b790fe21f53106d554139f7265b7c04bd76cc54..baec576413673c4cb3bf0d7483d9de2b594cbe9e 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/subscription-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/subscription-services.js @@ -81,12 +81,13 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es }); } - function addRecord(record) { + function addRecord(record, options) { if (!record || !record.type || !record.content || !record.recipient) { return $q.reject("Missing arguments 'record' or 'record.type' or 'record.content' or 'record.recipient'"); } - var issuer = csWallet.data.pubkey; + var wallet = options && options.wallet || (options && options.walletId && csWallet.children.get(options.walletId)) || csWallet; + var issuer = wallet.data.pubkey; var contentStr = JSON.stringify(record.content); @@ -95,8 +96,8 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es // Encrypt contents .then(function(nonce) { return $q.all([ - esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, csWallet.data.keypair, 'issuer', 'issuerContent', nonce), - esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, csWallet.data.keypair, 'recipient', 'recipientContent', nonce) + esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, wallet.data.keypair, 'issuer', 'issuerContent', nonce), + esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, wallet.data.keypair, 'recipient', 'recipientContent', nonce) ]); }) // Merge encrypted record @@ -105,7 +106,7 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es encryptedRecord.type = record.type; // Post subscription - return that.raw.add(encryptedRecord) + return that.raw.add(encryptedRecord, {wallet: wallet}) .then(function(id) { record.id = id; return record; @@ -114,12 +115,13 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es ; } - function updateRecord(record) { + function updateRecord(record, options) { if (!record || !record.content || !record.recipient) { return $q.reject("Missing arguments 'record' or 'record.content', or 'record.recipient'"); } - var issuer = csWallet.data.pubkey; + var wallet = options && options.wallet || (options && options.walletId && csWallet.children.get(options.walletId)) || csWallet; + var issuer = wallet.data.pubkey; var contentStr = JSON.stringify(record.content); // Get a unique nonce @@ -127,8 +129,8 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es // Encrypt contents .then(function(nonce) { return $q.all([ - esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, csWallet.data.keypair, 'issuer', 'issuerContent', nonce), - esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, csWallet.data.keypair, 'recipient', 'recipientContent', nonce) + esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, wallet.data.keypair, 'issuer', 'issuerContent', nonce), + esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, wallet.data.keypair, 'recipient', 'recipientContent', nonce) ]); }) // Merge encrypted record @@ -137,7 +139,7 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es encryptedRecord.type = record.type; // Post subscription - return that.raw.update(encryptedRecord, {id:record.id}) + return that.raw.update(encryptedRecord, {id:record.id, wallet: wallet}) .then(function() { return record; // return original record }); diff --git a/assets/www/dist/dist_js/plugins/es/js/services/tx-services.js b/assets/www/dist/dist_js/plugins/es/js/services/tx-services.js index 806273d393e668ca4cb0a5fbe97ab2408abaa0d3..0423f54a4456799667c756ae3a3005c1d89478e4 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/tx-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/tx-services.js @@ -11,10 +11,11 @@ angular.module('cesium.es.tx.services', ['ngResource', 'cesium.services', 'cesiu }]) - .factory('esTx', ['$q', '$rootScope', 'csCurrency', 'csTx', 'esHttp', 'esWot', function($q, $rootScope, csCurrency, csTx, esHttp, esWot) { + .factory('esTx', ['$q', '$rootScope', 'csPlatform', 'csCurrency', 'csTx', 'esHttp', 'esWot', function($q, $rootScope, csPlatform, csCurrency, csTx, esHttp, esWot) { 'ngInject'; var + listeners, raw = { block: { search: esHttp.post('/:currency/block/_search') @@ -67,7 +68,8 @@ angular.module('cesium.es.tx.services', ['ngResource', 'cesium.services', 'cesiu { range: { medianTime: { - from: membership.joinTime, + // Fix #736: Add 1 second, because when membership begins in a block with DU, the DU is not received + from: membership.joinTime+1, to: membership.leaveTime } } @@ -114,8 +116,38 @@ angular.module('cesium.es.tx.services', ['ngResource', 'cesium.services', 'cesiu return deferred.promise; } - // Register extensions - csTx.api.data.on.loadUDs($rootScope, onLoadUDs, this); + function addListeners() { + // Extend API events + listeners = [ + csTx.api.data.on.loadUDs($rootScope, onLoadUDs, this) + ]; + } + + function removeListeners() { + _.forEach(listeners, function(remove){ + remove(); + }); + listeners = []; + } + + function refreshState() { + var enable = esHttp.alive; + if (!enable && listeners && listeners.length > 0) { + console.debug("[ES] [tx] Disable"); + removeListeners(); + } + else if (enable && (!listeners || listeners.length === 0)) { + console.debug("[ES] [tx] Enable"); + addListeners(); + } + } + + // Default action + csPlatform.ready().then(function() { + esHttp.api.node.on.start($rootScope, refreshState, this); + esHttp.api.node.on.stop($rootScope, refreshState, this); + return refreshState(); + }); // Exports return {}; diff --git a/assets/www/dist/dist_js/plugins/es/js/services/wallet-services.js b/assets/www/dist/dist_js/plugins/es/js/services/wallet-services.js index 427df5d168b7948366f0283ca7b67b62bda408b4..bb3c3edd3e582f3f4185b23fe8551afda8f15526 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/wallet-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/wallet-services.js @@ -1,6 +1,6 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'cesium.es.http.services', 'cesium.es.crypto.services']) - .factory('esWallet', ['$q', '$rootScope', 'CryptoUtils', 'csPlatform', 'csWallet', 'esCrypto', 'esProfile', 'esHttp', function($q, $rootScope, CryptoUtils, csPlatform, csWallet, esCrypto, esProfile, esHttp) { + .factory('esWallet', ['$q', '$rootScope', '$timeout', 'CryptoUtils', 'csPlatform', 'csWallet', 'esCrypto', 'esProfile', 'esHttp', function($q, $rootScope, $timeout, CryptoUtils, csPlatform, csWallet, esCrypto, esProfile, esHttp) { 'ngInject'; var @@ -24,8 +24,8 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c // Generate box keypair esCrypto.box.getKeypair(data.keypair) .then(function(res) { - csWallet.data.keypair.boxSk = res.boxSk; - csWallet.data.keypair.boxPk = res.boxPk; + data.keypair.boxSk = res.boxSk; + data.keypair.boxPk = res.boxPk; console.debug("[ES] [wallet] Box keypair successfully computed"); deferred.resolve(); }); @@ -56,7 +56,7 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c } console.debug('[ES] [wallet] Loading user avatar+name...'); - var now = new Date().getTime(); + var now = Date.now(); esProfile.getAvatarAndName(data.pubkey) .then(function(profile) { @@ -64,7 +64,7 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c data.name = profile.name; data.avatarStyle = profile.avatarStyle; data.avatar = profile.avatar; - console.debug('[ES] [wallet] Loaded user avatar+name in '+ (new Date().getTime()-now) +'ms'); + console.debug('[ES] [wallet] Loaded user avatar+name in '+ (Date.now()-now) +'ms'); } else { console.debug('[ES] [wallet] No user avatar+name found'); @@ -84,13 +84,13 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c // Reset events csWallet.events.cleanByContext('esWallet'); - // If membership pending, but not enough certifications: suggest to fill user profile - if (!data.name && data.requirements.pendingMembership && data.requirements.needCertificationCount > 0) { + // If membership pending and not revocated, but not enough certifications: suggest to fill user profile + if (!data.name && !data.requirements.revoked && data.requirements.pendingMembership && data.requirements.needCertificationCount > 0) { csWallet.events.add({type:'info', message: 'ACCOUNT.EVENT.MEMBER_WITHOUT_PROFILE', context: 'esWallet'}); } console.debug('[ES] [wallet] Loading full user profile...'); - var now = new Date().getTime(); + var now = Date.now(); // Load full profile esProfile.get(data.pubkey) @@ -100,7 +100,7 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c data.avatar = profile.avatar; data.profile = profile.source; data.profile.description = profile.description; - console.debug('[ES] [wallet] Loaded full user profile in '+ (new Date().getTime()-now) +'ms'); + console.debug('[ES] [wallet] Loaded full user profile in '+ (Date.now()-now) +'ms'); } deferred.resolve(); }); @@ -108,23 +108,26 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c return deferred.promise; } - function getBoxKeypair() { - if (!csWallet.isAuth()) { + function getBoxKeypair(keypair) { + if (!keypair && !csWallet.isAuth()) { throw new Error('Unable to get box keypair: user not authenticated !'); } - return csWallet.getKeypair({silent: true}) + return (keypair ? $q.when(keypair) : csWallet.getKeypair({silent: true})) .then(function(keypair) { + // box keypair already computed: use it if (keypair && keypair.boxPk && keypair.boxSk) { - return $q.when(csWallet.data.keypair); + return $q.when(keypair); } - return esCrypto.box.getKeypair(keypair); - }) - .then(function(res) { - csWallet.data.keypair.boxSk = res.boxSk; - csWallet.data.keypair.boxPk = res.boxPk; - console.debug("[ES] [wallet] Box keypair successfully computed"); - return csWallet.data.keypair; + // Compute box keypair + return esCrypto.box.getKeypair(keypair) + .then(function(res) { + // Store in the wallet keypair + keypair.boxSk = res.boxSk; + keypair.boxPk = res.boxPk; + console.debug("[ES] [wallet] Box keypair successfully computed"); + return keypair; + }); }); } @@ -177,15 +180,15 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c getKeypair: getBoxKeypair, record: { pack: function(record, keypair, recipientFieldName, cypherFieldNames, nonce) { - return getBoxKeypair() - .then(function(keypair) { - return esCrypto.box.pack(record, keypair, recipientFieldName, cypherFieldNames, nonce); + return getBoxKeypair(keypair) + .then(function(fullKeypair) { + return esCrypto.box.pack(record, fullKeypair, recipientFieldName, cypherFieldNames, nonce); }); }, open: function(records, keypair, issuerFieldName, cypherFieldNames) { - return getBoxKeypair() - .then(function(keypair) { - return esCrypto.box.open(records, keypair, issuerFieldName, cypherFieldNames); + return getBoxKeypair(keypair) + .then(function(fullKeypair) { + return esCrypto.box.open(records, fullKeypair, issuerFieldName, cypherFieldNames); }); } } diff --git a/assets/www/dist/dist_js/plugins/es/js/services/wot-services.js b/assets/www/dist/dist_js/plugins/es/js/services/wot-services.js index 4a31b0e39b4a338a817648f580cbacdc7529a885..cc60416a87fe1f8fe89200a498a7cd4c082afd58 100644 --- a/assets/www/dist/dist_js/plugins/es/js/services/wot-services.js +++ b/assets/www/dist/dist_js/plugins/es/js/services/wot-services.js @@ -1,16 +1,23 @@ angular.module('cesium.es.wot.services', ['ngResource', 'cesium.es.http.services']) - .factory('esWot', ['$q', 'esHttp', function($q, esHttp) { + .factory('esWot', ['$rootScope', '$q', 'esHttp', 'csCache', function($rootScope, $q, esHttp, csCache) { 'ngInject'; var + cachePrefix = 'esWot-', + membershipsCache = csCache.get(cachePrefix + 'memberships-', csCache.constants.MEDIUM), raw = { user: { - event: esHttp.post('/user/event/_search?pretty') + event: esHttp.post('/user/event/_search') } }, - loadMemberships = function(pubkey) { + + loadMemberships = function(pubkey, options) { + options = options || {}; + + var result = (options.cache !== false) ? membershipsCache.get(pubkey) : null; + if (result) return $q.when(result); // Get user events on membership state var request = { @@ -62,10 +69,21 @@ angular.module('cesium.es.wot.services', ['ngResource', 'cesium.es.http.services }); } + // Put in the cache + membershipsCache.put(pubkey, result); + return result; }); + }, + + cleanCache = function() { + console.debug('[ES] [wot] Clean cache...'); + csCache.clear(cachePrefix); }; + // Listen if node changed + esHttp.api.node.on.stop($rootScope, cleanCache, this); + return { memberships: loadMemberships }; diff --git a/assets/www/dist/dist_js/plugins/graph/js/controllers/account-controllers.js b/assets/www/dist/dist_js/plugins/graph/js/controllers/account-controllers.js index 438d7006a6c9531b6ca2d131af212150161174ba..91bc3057e6efbdab1c78399cf6b3cbedb42988ec 100644 --- a/assets/www/dist/dist_js/plugins/graph/js/controllers/account-controllers.js +++ b/assets/www/dist/dist_js/plugins/graph/js/controllers/account-controllers.js @@ -21,6 +21,15 @@ angular.module('cesium.graph.account.controllers', ['chart.js', 'cesium.graph.se } }) + .extendState('app.view_wallet_tx_by_id', { + points: { + 'buttons': { + templateUrl: "plugins/graph/templates/account/view_wallet_tx_extend.html", + controller: 'GpExtendCtrl' + } + } + }) + .extendState('app.wot_identity', { points: { 'buttons': { @@ -53,6 +62,18 @@ angular.module('cesium.graph.account.controllers', ['chart.js', 'cesium.graph.se } }) + .state('app.view_wallet_stats_by_id', { + url: "/wallets/:id/stats?t&stepUnit&hide&scale", + views: { + 'menuContent': { + templateUrl: "plugins/graph/templates/account/view_stats.html" + } + }, + data: { + auth: true + } + }) + .state('app.wot_identity_stats', { url: "/wot/:pubkey/stats?t&stepUnit&hide&scale", views: { @@ -140,7 +161,7 @@ function GpAccountBalanceController($scope, $controller, $q, $state, $filter, $t var withUD = true; - return csWot.load($scope.formData.pubkey) + return csWot.load($scope.formData.pubkey, null/*uid*/, {cache: true}) .then(function(identity) { $scope.identity = identity; withUD = $scope.identity.isMember || $scope.identity.wasMember; @@ -161,7 +182,7 @@ function GpAccountBalanceController($scope, $controller, $q, $state, $filter, $t 'COMMON.DATE_MONTH_YEAR_PATTERN']), // get data - gpData.blockchain.movement($scope.formData.currency, angular.copy($scope.formData)) + gpData.blockchain.movement($scope.formData.currency, angular.copy($scope.formData, {withUD: withUD})) ]); }) .then(function(result) { @@ -172,8 +193,7 @@ function GpAccountBalanceController($scope, $controller, $q, $state, $filter, $t if (!result || !result.times) return; // no data $scope.times = result.times; - var formatInteger = $filter('formatInteger'); - var formatAmount = $filter('formatDecimal'); + var formatDecimal = $filter('formatDecimal'); $scope.currencySymbol = $filter('currencySymbolNoHtml')($scope.formData.currency, $scope.formData.useRelative); // Data @@ -234,7 +254,7 @@ function GpAccountBalanceController($scope, $controller, $q, $state, $filter, $t return data.datasets[tooltipItems.datasetIndex].label + ': ' + (!tooltipItems.yLabel ? '0' : - (formatAmount(tooltipItems.yLabel) + ' ' + $scope.currencySymbol)); + (formatDecimal(tooltipItems.yLabel) + ' ' + $scope.currencySymbol)); } } } @@ -327,8 +347,6 @@ function GpAccountSumTxController($scope, $controller, $filter, $state, csTx, gp $scope.load = function(e, state) { if (!$scope.pubkey) return; - var formatDecimal = $filter('formatDecimal'); - // Load account TX data return csTx.load($scope.pubkey, -1) .then(function(result) { @@ -358,12 +376,17 @@ function GpAccountSumTxController($scope, $controller, $filter, $state, csTx, gp pubkey: tx.pubkey, sum: 0 }; - sumByPubkeys[tx.pubkey].sum += Math.abs(tx.amount/100); + sumByPubkeys[tx.pubkey].sum += Math.abs(tx.amount); }); // Get values (from the map), then sort (desc) on sum var sumItems = _.sortBy(_.values(sumByPubkeys), 'sum').reverse(); + // Divide total amount by 100 + _.each(sumItems, function(item) { + item.sum = item.sum / 100; + }); + // Return arrays expected by angular-chart return { data: _.pluck(sumItems, 'sum'), diff --git a/assets/www/dist/dist_js/plugins/graph/js/controllers/common-controllers.js b/assets/www/dist/dist_js/plugins/graph/js/controllers/common-controllers.js index 2ab7617a957fba97a00b29dc5d9876da04e70234..a75fb211bb411f80ec6fb2a6be93344f5d4aebf6 100644 --- a/assets/www/dist/dist_js/plugins/graph/js/controllers/common-controllers.js +++ b/assets/www/dist/dist_js/plugins/graph/js/controllers/common-controllers.js @@ -1,11 +1,11 @@ -GpCurrencyAbstractController.$inject = ['$scope', '$filter', '$ionicPopover', '$ionicHistory', '$state', 'csSettings', 'csCurrency', 'esHttp']; +GpCurrencyAbstractController.$inject = ['$scope', '$filter', '$ionicPopover', '$ionicHistory', '$state', 'csSettings', 'csCurrency', 'esHttp', 'UIUtils']; angular.module('cesium.graph.common.controllers', ['cesium.services']) .controller('GpCurrencyAbstractCtrl', GpCurrencyAbstractController) ; -function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHistory, $state, csSettings, csCurrency, esHttp) { +function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHistory, $state, csSettings, csCurrency, esHttp, UIUtils) { 'ngInject'; $scope.loading = true; @@ -15,7 +15,8 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist rangeDuration: 'day', firstBlockTime: 0, scale: 'linear', - hide: [] + hide: [], + beginAtZero: true }; $scope.formData.useRelative = false; /*angular.isDefined($scope.formData.useRelative) ? $scope.formData.useRelative : csSettings.data.useRelative;*/ @@ -72,7 +73,7 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist if (!$scope.formData.firstBlockTime){ console.warn('[graph] currency.firstBlockTime not loaded ! Should have been loaded by currrency service!'); } - $scope.formData.currencyAge = _truncDate(esHttp.date.now()) - $scope.formData.firstBlockTime; + $scope.formData.currencyAge = _truncDate(moment().utc().unix()) - $scope.formData.firstBlockTime; return $scope.enter(e, state); }); @@ -93,6 +94,8 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist $scope.$on('$ionicParentView.enter', $scope.enter); $scope.updateLocation = function() { + if (!$scope.stateName) return; + $ionicHistory.nextViewOptions({ disableAnimate: true, disableBack: true, @@ -151,7 +154,7 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist yAxe.type = scale; yAxe.ticks = yAxe.ticks || {}; if (scale == 'linear') { - yAxe.ticks.beginAtZero = true; + yAxe.ticks.beginAtZero = angular.isDefined($scope.formData.beginAtZero) ? $scope.formData.beginAtZero : true; delete yAxe.ticks.min; yAxe.ticks.callback = function(value) { return format(value); @@ -313,22 +316,21 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist /* -- Popover -- */ $scope.showActionsPopover = function(event) { - $scope.hideActionsPopover(); - $ionicPopover.fromTemplateUrl('plugins/graph/templates/common/popover_range_actions.html', { - scope: $scope - }).then(function(popover) { - $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); + UIUtils.popover.show(event, { + templateUrl: 'plugins/graph/templates/common/popover_range_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; + } diff --git a/assets/www/dist/dist_js/plugins/graph/js/controllers/currency-controllers.js b/assets/www/dist/dist_js/plugins/graph/js/controllers/currency-controllers.js index c02ac1a058a8a45b80c5221568356319dd868231..37d04ba1f5553426a03707ef7174f0cf25f719e6 100644 --- a/assets/www/dist/dist_js/plugins/graph/js/controllers/currency-controllers.js +++ b/assets/www/dist/dist_js/plugins/graph/js/controllers/currency-controllers.js @@ -1,7 +1,7 @@ GpCurrencyViewExtendController.$inject = ['$scope', 'PluginService', 'UIUtils', 'esSettings']; -GpCurrencyMonetaryMassController.$inject = ['$scope', '$controller', '$q', '$state', '$translate', '$ionicPopover', 'gpColor', 'gpData', '$filter', 'csSettings']; -GpCurrencyDUController.$inject = ['$scope', '$q', '$controller', '$translate', 'gpColor', 'gpData', '$filter']; +GpCurrencyMonetaryMassController.$inject = ['$scope', '$controller', '$q', '$state', '$translate', 'UIUtils', 'gpColor', 'gpData', '$filter', 'csSettings']; +GpCurrencyDUController.$inject = ['$scope', '$q', '$controller', '$translate', 'gpColor', 'gpData', '$filter', 'UIUtils']; GpCurrencyMembersCountController.$inject = ['$scope', '$controller', '$q', '$state', '$translate', 'gpColor', 'gpData', '$filter']; angular.module('cesium.graph.currency.controllers', ['chart.js', 'cesium.graph.services', 'cesium.graph.common.controllers']) @@ -13,8 +13,7 @@ angular.module('cesium.graph.currency.controllers', ['chart.js', 'cesium.graph.s url: "/parameters/stats", views: { 'tab-parameters': { - templateUrl: "plugins/graph/templates/currency/tabs/tab_parameters_stats.html", - controller: 'GpCurrencyMonetaryMassCtrl' + templateUrl: "plugins/graph/templates/currency/tabs/tab_parameters_stats.html" } } }) @@ -105,7 +104,7 @@ function GpCurrencyViewExtendController($scope, PluginService, UIUtils, esSettin }); } -function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $translate, $ionicPopover, gpColor, gpData, $filter, csSettings) { +function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $translate, UIUtils, gpColor, gpData, $filter, csSettings) { 'ngInject'; // Initialize the super class and extend it. @@ -155,10 +154,10 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran var blocksPeriod = result.times[result.times.length-1] - result.times[0]; var formatDate; if (blocksPeriod < 31557600/* less than 1 year */) { - formatDate = $filter('formatDateShort'); + formatDate = $filter('medianDateShort'); } else { - formatDate = $filter('formatDateMonth'); + formatDate = $filter('formatDateMonth'); //see #683 } var formatAmount = $filter('formatDecimal'); @@ -168,31 +167,31 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran var data = []; if($scope.formData.useRelative) { - // Mass + // M/N data.push( result.blocks.reduce(function(res, block) { - return res.concat(truncAmount(block.monetaryMass / block.dividend)); + return res.concat(truncAmount(block.monetaryMass / block.dividend / block.membersCount)); }, [])); - // M/N + // Mass data.push( result.blocks.reduce(function(res, block) { - return res.concat(truncAmount(block.monetaryMass / block.dividend / block.membersCount)); + return res.concat(truncAmount(block.monetaryMass / block.dividend)); }, [])); } // Data: quantitative else { - // Mass + // M/N data.push( result.blocks.reduce(function(res, block) { - return res.concat(block.monetaryMass / 100); + return res.concat(truncAmount(block.monetaryMass / block.membersCount / 100)); }, [])); - // M/N + // Mass data.push( result.blocks.reduce(function(res, block) { - return res.concat(truncAmount(block.monetaryMass / block.membersCount / 100)); + return res.concat(block.monetaryMass / 100); }, [])); } $scope.data = data; @@ -220,16 +219,17 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran scales: { yAxes: [ { - id: 'y-axis-mass' + id: 'y-axis-mn' }, { - id: 'y-axis-mn', + id: 'y-axis-mass', display: $scope.displayShareAxis, position: 'right', gridLines: { drawOnChartArea: false } - } + }, + ] }, tooltips: { @@ -247,18 +247,18 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran $scope.datasetOverride = [ { - yAxisID: 'y-axis-mass', + yAxisID: 'y-axis-mn', type: 'line', - label: translations['GRAPH.CURRENCY.MONETARY_MASS_LABEL'], + label: translations['GRAPH.CURRENCY.MONETARY_MASS_SHARE_LABEL'], borderWidth: 2, pointRadius: 0, pointHitRadius: 4, pointHoverRadius: 3 }, { - yAxisID: 'y-axis-mn', + yAxisID: 'y-axis-mass', type: 'line', - label: translations['GRAPH.CURRENCY.MONETARY_MASS_SHARE_LABEL'], + label: translations['GRAPH.CURRENCY.MONETARY_MASS_LABEL'], fill: false, showLine: true, borderColor: gpColor.rgba.energized(), @@ -292,32 +292,38 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran /* -- Popover -- */ $scope.showActionsPopover = function(event) { - $scope.hideActionsPopover(); - $ionicPopover.fromTemplateUrl('plugins/graph/templates/currency/popover_monetary_mass_actions.html', { - scope: $scope - }).then(function(popover) { - $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); + UIUtils.popover.show(event, { + templateUrl: 'plugins/graph/templates/currency/popover_monetary_mass_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; + } -function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gpData, $filter) { +function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gpData, $filter, UIUtils) { 'ngInject'; + + $scope.formData = { + scale: 'linear', + beginAtZero: false + }; + // Initialize the super class and extend it. angular.extend(this, $controller('GpCurrencyMonetaryMassCtrl', {$scope: $scope})); + $scope.load = function(from, size) { from = from || 0; size = size || 10000; @@ -341,7 +347,7 @@ function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gp var blocksPeriod = result.times[result.times.length-1] - result.times[0]; var dateFilter; if (blocksPeriod < 31557600/* less than 1 year */) { - dateFilter = $filter('formatDateShort'); + dateFilter = $filter('medianDateShort'); } else { dateFilter = $filter('formatDateMonth'); @@ -380,7 +386,7 @@ function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gp { id: 'y-axis-ud', ticks: { - beginAtZero: false + beginAtZero: $scope.formData.beginAtZero } } ] @@ -417,6 +423,26 @@ function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gp }); }; + + /* -- Popover -- */ + $scope.showActionsPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/graph/templates/currency/popover_monetary_mass_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } + }); + }; + + $scope.hideActionsPopover = function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + $scope.actionsPopover = null; + } + }; + } @@ -449,7 +475,7 @@ function GpCurrencyMembersCountController($scope, $controller, $q, $state, $tran var blocksPeriod = result.times[result.blocks.length-1] - result.times[0]; var dateFilter; if (blocksPeriod < 31557600/* less than 1 year*/) { - dateFilter = $filter('formatDateShort'); + dateFilter = $filter('medianDateShort'); } else { dateFilter = $filter('formatDateMonth'); @@ -514,4 +540,6 @@ function GpCurrencyMembersCountController($scope, $controller, $q, $state, $tran q: '(_exists_:joiners OR _exists_:leavers OR _exists_:revoked OR _exists_:excluded) AND medianTime:>{0} AND medianTime:<={1}'.format(from, to) }); }; + + } diff --git a/assets/www/dist/dist_js/plugins/graph/js/controllers/docstats-controllers.js b/assets/www/dist/dist_js/plugins/graph/js/controllers/docstats-controllers.js index cb945b15e2631bd29f51e08e5b8058a848eaa82c..61b369c4c996bf722015ec61884ecf7d56066665 100644 --- a/assets/www/dist/dist_js/plugins/graph/js/controllers/docstats-controllers.js +++ b/assets/www/dist/dist_js/plugins/graph/js/controllers/docstats-controllers.js @@ -32,6 +32,7 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol // Initialize the super class and extend it. angular.extend(this, $controller('GpCurrencyAbstractCtrl', {$scope: $scope})); + $scope.displayRightAxis = true; $scope.hiddenDatasets = []; $scope.chartIdPrefix = 'docstats-chart-'; @@ -45,7 +46,7 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol { key: 'user_profile', label: 'GRAPH.DOC_STATS.USER.USER_PROFILE', - color: gpColor.rgba.royal(), + color: gpColor.rgba.royal(0.7), pointHoverBackgroundColor: gpColor.rgba.royal(), clickState: { name: 'app.document_search', @@ -65,6 +66,30 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol ] }, + // User delta + { + id: 'user_delta', + title: 'GRAPH.DOC_STATS.USER_DELTA.TITLE', + series: [ + { + key: 'user_profile_delta', + label: 'GRAPH.DOC_STATS.USER_DELTA.USER_PROFILE', + type: 'line', + yAxisID: 'y-axis-delta', + color: gpColor.rgba.royal(), + pointHoverBackgroundColor: gpColor.rgba.royal() + }, + { + key: 'user_settings_delta', + label: 'GRAPH.DOC_STATS.USER_DELTA.USER_SETTINGS', + type: 'line', + yAxisID: 'y-axis-delta', + color: gpColor.rgba.gray(0.5), + pointHoverBackgroundColor: gpColor.rgba.gray() + } + ] + }, + // Message & Co. { id: 'message', @@ -178,8 +203,21 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol }], yAxes: [ { - stacked: true, - id: 'y-axis' + id: 'y-axis', + stacked: true + }, + { + id: 'y-axis-delta', + stacked: false + }, + { + id: 'y-axis-delta-right', + stacked: false, + display: $scope.displayRightAxis, + position: 'right', + gridLines: { + drawOnChartArea: false + } } ] }, @@ -232,9 +270,9 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol // Labels var labelPattern = datePatterns[$scope.formData.rangeDuration]; - $scope.labels = result.times.reduce(function(res, time) { - return res.concat(moment.unix(time).local().format(labelPattern)); - }, []); + $scope.labels = _.map(result.times, function(time) { + return moment.unix(time).local().format(labelPattern); + }); // Update range options with received values $scope.updateRange(result.times[0], result.times[result.times.length-1], updateTimePct); @@ -244,25 +282,36 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol // For each chart _.forEach($scope.charts, function(chart){ - // Data - chart.data = []; - _.forEach(chart.series, function(serie){ - chart.data.push(result[serie.key]||[]); + // Prepare chart data + var usedYAxisIDs = {}; + chart.data = _.map(chart.series, function(serie) { + usedYAxisIDs[serie.yAxisID||'y-axis'] = true; + // If 'delta' serie, then compute delta from the source serie + if (serie.key.endsWith('_delta')) { + var key = serie.key.substring(0, serie.key.length - '_delta'.length); + return getDeltaFromValueArray(result[key]) || []; + } + return result[serie.key]||[]; }); // Options (with title) chart.options = angular.copy($scope.defaultChartOptions); chart.options.title.text = translations[chart.title]; + // Remove unused yAxis + chart.options.scales.yAxes = chart.options.scales.yAxes.reduce(function(res, yAxe){ + return usedYAxisIDs[yAxe.id] ? res.concat(yAxe) : res; + }, []); + // Series datasets - chart.datasetOverride = chart.series.reduce(function(res, serie) { - return res.concat({ - yAxisID: 'y-axis', + chart.datasetOverride = _.map(chart.series, function(serie) { + return { + yAxisID: serie.yAxisID || 'y-axis', type: serie.type || 'line', label: translations[serie.label], - fill: true, + fill: serie.type !== 'line', borderWidth: 2, - pointRadius: 0, + pointRadius: serie.type !== 'line' ? 0 : 2, pointHitRadius: 4, pointHoverRadius: 3, borderColor: serie.color, @@ -271,8 +320,8 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol pointBorderColor: serie.color, pointHoverBackgroundColor: serie.pointHoverBackgroundColor||serie.color, pointHoverBorderColor: serie.pointHoverBorderColor||gpColor.rgba.white() - }); - }, []); + }; + }); }); }); @@ -301,5 +350,14 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol } }; + function getDeltaFromValueArray(values) { + if (!values) return undefined; + var previousValue; + return _.map(values, function(value) { + var newValue = (value !== undefined) && (value - (previousValue || value)) || undefined; + previousValue = value; + return newValue; + }); + } } diff --git a/assets/www/dist/dist_js/plugins/map/js/controllers/registry-controllers.js b/assets/www/dist/dist_js/plugins/map/js/controllers/registry-controllers.js index 092fb66e4c1bfa530ec44541a8aa191ea7ba5fbc..a23b817deab42e4180b70144da290faf24a31107 100644 --- a/assets/www/dist/dist_js/plugins/map/js/controllers/registry-controllers.js +++ b/assets/www/dist/dist_js/plugins/map/js/controllers/registry-controllers.js @@ -1,5 +1,5 @@ -MapRegistryViewController.$inject = ['$scope', '$filter', '$templateCache', '$interpolate', '$timeout', '$location', '$translate', '$q', 'leafletData', 'UIUtils', 'csSettings', 'csWallet', 'MapUtils', 'mapRegistry']; +MapRegistryViewController.$inject = ['$scope', '$filter', '$templateCache', '$interpolate', '$timeout', '$location', '$translate', '$q', 'ionicReady', 'leafletData', 'UIUtils', 'csSettings', 'csWallet', 'MapUtils', 'mapRegistry']; angular.module('cesium.map.registry.controllers', ['cesium.services', 'cesium.map.services', 'cesium.map.help.controllers']) .config(['$stateProvider', 'PluginServiceProvider', 'csConfig', function($stateProvider, PluginServiceProvider, csConfig) { @@ -51,7 +51,8 @@ angular.module('cesium.map.registry.controllers', ['cesium.services', 'cesium.ma function MapRegistryViewController($scope, $filter, $templateCache, $interpolate, $timeout, $location, $translate, $q, - leafletData, UIUtils, csSettings, csWallet, MapUtils, mapRegistry) { + ionicReady, leafletData, + UIUtils, csSettings, csWallet, MapUtils, mapRegistry) { 'ngInject'; var @@ -82,7 +83,8 @@ function MapRegistryViewController($scope, $filter, $templateCache, $interpolate }; $scope.loading = true; - $scope.mapId = 'map-wot-' + $scope.$id; + $scope.loadingMarker = true; + $scope.mapId = 'map-registry-' + $scope.$id; $scope.map = MapUtils.map({ cache: 'map-registry', @@ -116,6 +118,15 @@ function MapRegistryViewController($scope, $filter, $templateCache, $interpolate loading: true }, $scope.mapId); + // Variables for marker + $scope.formData = {}; + $scope.showDescription = false; + ionicReady().then(function() { + $scope.enableDescription = !UIUtils.screen.isSmall() && ionic.Platform.grade.toLowerCase() === 'a'; + if (!$scope.enableDescription) { + console.debug("[map] [wot] Disable profile description.", ionic.Platform.grade); + } + }); $scope.$on('$ionicView.beforeEnter', function (event, viewData) { // Enable back button (workaround need for navigation outside tabs - https://stackoverflow.com/a/35064602) @@ -169,19 +180,6 @@ function MapRegistryViewController($scope, $filter, $templateCache, $interpolate if (!$scope.map.loading) return map; // already loaded if (!UIUtils.screen.isSmall()) { - // Add a start tour button - /*L.easyButton({ - position: 'topright', // inherited from L.Control -- the corner it goes in - type: 'replace', // set to animate when you're comfy with css - leafletClasses: true, // use leaflet classes to style the button? - states:[{ // specify different icons and responses for your button - stateName: 'show-help-tour', - onClick: $scope.startHelpTour, - title: translations['COMMON.BTN_HELP_TOUR_SCREEN'], - icon: 'icon ion-easel' - }] - } - ).addTo(map);*/ // Add a refresh button L.easyButton({ @@ -292,7 +290,7 @@ function MapRegistryViewController($scope, $filter, $templateCache, $interpolate var options = { fields: { - description: !UIUtils.screen.isSmall() + description: $scope.enableDescription } }; @@ -308,41 +306,44 @@ function MapRegistryViewController($scope, $filter, $templateCache, $interpolate if (res && res.length) { var formatPubkey = $filter('formatPubkey'); - var userMarkerTemplate = $templateCache.get('plugins/map/templates/wot/popup_marker.html'); - var pageMarkerTemplate = $templateCache.get('plugins/map/templates/wot/popup_page_marker.html'); + var pageMarkerTemplate = $templateCache.get('plugins/map/templates/registry/popup_marker.html'); _.forEach(res, function (hit) { - var type = hit.type || (hit.pending ? 'pending' : (hit.uid ? 'member' : 'wallet')); var shortPubkey = formatPubkey(hit.pubkey); - var id = hit.index + '_' + (hit.id || (hit.uid ? (hit.uid + ':' + hit.pubkey) : hit.pubkey)).replace(/-/g, '_'); + var id = hit.index + '_' + (hit.id).replace(/-/g, '_'); var marker = { - layer: type, - icon: icons[type], - opacity: hit.uid || hit.type ? 1 : 0.7, + layer: hit.type, + icon: icons[hit.type], + opacity: 1, title: hit.name + ' | ' + shortPubkey, lat: hit.geoPoint.lat, lng: hit.geoPoint.lon, getMessageScope: function () { var scope = $scope.$new(); - scope.hit = hit; + scope.loadingMarker = true; + scope.formData = {}; + scope.$applyAsync(function() { + angular.extend(scope.formData, hit); + scope.loadingMarker = false; + }); return scope; }, focus: false, - message: hit.type ? pageMarkerTemplate : userMarkerTemplate, + message: pageMarkerTemplate, id: id }; markers[id] = marker; // Create a search marker (will be hide) - var searchText = hit.name + ((hit.uid && hit.uid != hit.name) ? (' | ' + hit.uid) : '') + ' | ' + shortPubkey; + var searchText = hit.name + ' | ' + shortPubkey; var searchMarker = angular.merge({ - type: type, + type: hit.type, opacity: 0, icon: L.divIcon({ - className: type + ' ng-hide', + className: hit.type + ' ng-hide', iconSize: L.point(0, 0) }) - }, {title: searchText, pubkey: hit.pubkey, uid: hit.uid, name: hit.name, pending: hit.pending, popupMarkerId: id}); + }, {title: searchText, pubkey: hit.pubkey, name: hit.name, popupMarkerId: id}); markersSearchLayer.addLayer(new L.Marker({ lat: hit.geoPoint.lat, lng: hit.geoPoint.lon diff --git a/assets/www/dist/dist_js/plugins/map/js/controllers/user-controllers.js b/assets/www/dist/dist_js/plugins/map/js/controllers/user-controllers.js index 0a1c3e2cf26929b4eef3034d08e3c65d5cdd54d7..35a107594ca48c63de1730844f301a240a675699 100644 --- a/assets/www/dist/dist_js/plugins/map/js/controllers/user-controllers.js +++ b/assets/www/dist/dist_js/plugins/map/js/controllers/user-controllers.js @@ -9,7 +9,16 @@ angular.module('cesium.map.user.controllers', ['cesium.services', 'cesium.map.se PluginServiceProvider - .extendState('app.user_edit_profile', { + .extendState('app.edit_profile', { + points: { + 'after-position': { + templateUrl: 'plugins/map/templates/user/edit_profile_extend.html', + controller: 'MapEditProfileViewCtrl' + } + } + }) + + .extendState('app.edit_profile_by_id', { points: { 'after-position': { templateUrl: 'plugins/map/templates/user/edit_profile_extend.html', diff --git a/assets/www/dist/dist_js/plugins/map/js/controllers/wot-controllers.js b/assets/www/dist/dist_js/plugins/map/js/controllers/wot-controllers.js index 64569a4d37d6f01f6f7ffadf54a2ec64d9a76477..a240907306af7a2d6038727e9ab7c1533423998b 100644 --- a/assets/www/dist/dist_js/plugins/map/js/controllers/wot-controllers.js +++ b/assets/www/dist/dist_js/plugins/map/js/controllers/wot-controllers.js @@ -1,5 +1,5 @@ -MapWotViewController.$inject = ['$scope', '$filter', '$templateCache', '$interpolate', '$timeout', '$location', '$translate', '$q', 'leafletData', 'UIUtils', 'csSettings', 'csWallet', 'MapUtils', 'mapWot']; +MapWotViewController.$inject = ['$scope', '$filter', '$templateCache', '$interpolate', '$timeout', '$location', '$translate', '$q', '$controller', 'ionicReady', 'leafletData', 'UIUtils', 'csSettings', 'csWallet', 'MapUtils', 'mapWot']; angular.module('cesium.map.wot.controllers', ['cesium.services', 'cesium.map.services', 'cesium.map.help.controllers']) .config(['$stateProvider', 'PluginServiceProvider', 'csConfig', function($stateProvider, PluginServiceProvider, csConfig) { @@ -51,10 +51,15 @@ angular.module('cesium.map.wot.controllers', ['cesium.services', 'cesium.map.ser ; -function MapWotViewController($scope, $filter, $templateCache, $interpolate, $timeout, $location, $translate, $q, +function MapWotViewController($scope, $filter, $templateCache, $interpolate, $timeout, $location, $translate, $q, $controller, + ionicReady, leafletData, UIUtils, csSettings, csWallet, MapUtils, mapWot) { 'ngInject'; + // Initialize the super classes and extend it. + angular.extend(this, $controller('WotIdentityAbstractCtrl', { $scope: $scope})); + angular.extend(this, $controller('ESWotIdentityViewCtrl', {$scope: $scope})); + var // Create a hidden layer, to hold search markers markersSearchLayer, @@ -78,6 +83,7 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti }; $scope.loading = true; + $scope.loadingMarker = true; $scope.mapId = 'map-wot-' + $scope.$id; $scope.map = MapUtils.map({ @@ -108,6 +114,14 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti loading: true }, $scope.mapId); + // Variables for marker + $scope.showDescription = false; + ionicReady().then(function() { + $scope.enableDescription = !UIUtils.screen.isSmall() && ionic.Platform.grade.toLowerCase() === 'a'; + if (!$scope.enableDescription) { + console.debug("[map] [wot] Disable profile description.", ionic.Platform.grade); + } + }); $scope.$on('$ionicView.beforeEnter', function (event, viewData) { // Enable back button (workaround need for navigation outside tabs - https://stackoverflow.com/a/35064602) @@ -117,6 +131,10 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti $scope.enter = function(e, state) { if ($scope.loading) { + + UIUtils.loading.show({ + noBackdrop: true // avoid a too long release + }); if (state.stateParams && state.stateParams.c) { var cPart = state.stateParams.c.split(':'); $scope.map.center.lat = parseFloat(cPart[0]); @@ -133,20 +151,19 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti }, true); // Load the map (and init if need) + var now = Date.now(); $scope.loadMap() + .then($scope.load) .then(function() { - if (csWallet.isLogin()) { - $scope.showHelpTip(); - } - return $scope.load(); + console.debug("[map] [wot] Loaded in "+ (Date.now() - now) +"ms"); + + $scope.showHelpTip(); }); } else { // Make sure to have previous center coordinate defined in the location URL $scope.updateLocationHref(); - if (csWallet.isLogin()) { - $scope.showHelpTip(); - } + $scope.showHelpTip(); } }; $scope.$on('$ionicView.enter', $scope.enter); @@ -266,6 +283,7 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti //MapUtils.cache.bind($scope, $scope.mapId, $scope.map); $scope.map.loading = false; + return map; }); }; @@ -284,10 +302,17 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti var options = { fields: { - description: !UIUtils.screen.isSmall() + description: $scope.enableDescription } }; + // add bounding box + if ($scope.map.bounds) { + // FIXME - this is not working well + //options.bounds = angular.copy($scope.map.bounds); + //delete options.bounds.options; + } + // Load wot data, from service return mapWot.load(options) @@ -300,8 +325,7 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti if (res && res.length) { var formatPubkey = $filter('formatPubkey'); - var userMarkerTemplate = $templateCache.get('plugins/map/templates/wot/popup_marker.html'); - var pageMarkerTemplate = $templateCache.get('plugins/map/templates/wot/popup_page_marker.html'); + var markerTemplate = $templateCache.get('plugins/map/templates/wot/popup_marker.html'); _.forEach(res, function (hit) { var type = hit.pending ? 'pending' : (hit.uid ? 'member' : 'wallet'); @@ -310,17 +334,27 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti var marker = { layer: type, icon: icons[type], - opacity: hit.uid || hit.type ? 1 : 0.7, + opacity: hit.uid ? 1 : 0.7, title: hit.name + ' | ' + shortPubkey, lat: hit.geoPoint.lat, lng: hit.geoPoint.lon, getMessageScope: function () { var scope = $scope.$new(); - scope.hit = hit; + scope.loadingMarker = true; + scope.formData = {}; + scope.$applyAsync(function() { + scope.formData = { + pubkey: hit.pubkey, + uid: hit.uid, + name: hit.name, + profile: hit + }; + scope.loadingMarker = false; + }); return scope; }, focus: false, - message: hit.type ? pageMarkerTemplate : userMarkerTemplate, + message: markerTemplate, id: id }; markers[id] = marker; @@ -345,10 +379,14 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti $scope.map.markers = markers; - $scope.loading = false; + return $timeout(function(){ + $scope.loading = false; + + // hide loading indicator + map.fire('dataload'); - // hide loading indicator - map.fire('dataload'); + UIUtils.loading.hide(); + }); }) .catch(function(err) { $scope.map.markers = {}; @@ -368,20 +406,6 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti // endRemoveIf(device) }; - // removeIf(device) - // Update the browser location, to be able to refresh the page - // FIXME: not need, should be removed - $scope.$on("centerUrlHash", function(event, centerHash) { - if (!$scope.loading) { - - return $timeout(function() { - $scope.updateLocationHref(centerHash); - }, 300); - } - }); - // endRemoveIf(device) - - /* -- help tip -- */ // Show help tour @@ -391,6 +415,8 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti // Show help tip $scope.showHelpTip = function(index, isTour) { + if (!isTour && !csWallet.isLogin()) return; + index = angular.isDefined(index) ? index : (angular.isNumber(csSettings.data.helptip.mapwot) ? csSettings.data.helptip.mapwot : 0); isTour = angular.isDefined(isTour) ? isTour : false; diff --git a/assets/www/dist/dist_js/plugins/map/js/services/registry-services.js b/assets/www/dist/dist_js/plugins/map/js/services/registry-services.js index 4b2dc907a514abb9c4b9ea6cd3abaf18c5c0ea0c..91473a6f96e67f29fb7c519edb250f399f4b07a9 100644 --- a/assets/www/dist/dist_js/plugins/map/js/services/registry-services.js +++ b/assets/www/dist/dist_js/plugins/map/js/services/registry-services.js @@ -168,7 +168,7 @@ angular.module('cesium.map.registry.services', ['cesium.services']) // Resolve missing positions by addresses (only if google API enable) if (searchAddressItems.length) { - var now = new Date().getTime(); + var now = Date.now(); console.debug('[map] [registry] Search positions of {0} addresses...'.format(searchAddressItems.length)); var counter = 0; @@ -189,7 +189,7 @@ angular.module('cesium.map.registry.services', ['cesium.services']) .catch(function() {/*silent*/})); }, [])) .then(function(){ - console.debug('[map] [registry] Resolved {0}/{1} addresses in {2}ms'.format(counter, searchAddressItems.length, new Date().getTime()-now)); + console.debug('[map] [registry] Resolved {0}/{1} addresses in {2}ms'.format(counter, searchAddressItems.length, Date.now()-now)); return items; }); } diff --git a/assets/www/dist/dist_js/plugins/map/js/services/wot-services.js b/assets/www/dist/dist_js/plugins/map/js/services/wot-services.js index 6f06a637ee61bbc2f0faa7ce099beb7a0752cdf7..59530f0b44acbfe9533f0e9448741c7de996b483 100644 --- a/assets/www/dist/dist_js/plugins/map/js/services/wot-services.js +++ b/assets/www/dist/dist_js/plugins/map/js/services/wot-services.js @@ -10,6 +10,7 @@ angular.module('cesium.map.wot.services', ['cesium.services']) DEFAULT_LOAD_SIZE: 1000 }, fields = { + min: ["title", "geoPoint"], profile: ["title", "geoPoint", "avatar._content_type", "address", "city"] }; @@ -43,8 +44,7 @@ angular.module('cesium.map.wot.services', ['cesium.services']) // Filter on bounding box // see https://www.elastic.co/guide/en/elasticsearch/reference/2.4/geo-point.html if (options.bounds && options.bounds.northEast && options.bounds.southWest) { - query.bool.should = query.bool.should || {}; - query.bool.should.geo_bounding_box = { + var boundingBox = { "geoPoint" : { "top_left" : { "lat" : Math.max(Math.min(options.bounds.northEast.lat, 90), -90), @@ -56,6 +56,9 @@ angular.module('cesium.map.wot.services', ['cesium.services']) } } }; + console.debug("[map] [wot] Filtering on bounds: ", options.bounds); + query.bool.must = query.bool.must || []; + query.bool.must.push({geo_bounding_box: boundingBox}); } return query; } @@ -67,7 +70,7 @@ angular.module('cesium.map.wot.services', ['cesium.services']) options.searchAddress = esGeo.google.isEnable() && (angular.isDefined(options.searchAddress) ? options.searchAddress : true); options.fields = options.fields || {}; - options.fields.description = angular.isDefined(options.fields.description) ? options.fields.description : true; + options.fields.description = angular.isDefined(options.fields.description) ? options.fields.description : false; var request = { query: createFilterQuery(options), @@ -193,7 +196,7 @@ angular.module('cesium.map.wot.services', ['cesium.services']) // Resolve missing positions by addresses (only if google API enable) if (searchAddressItems.length) { - var now = new Date().getTime(); + var now = Date.now(); console.debug('[map] [wot] Search positions of {0} addresses...'.format(searchAddressItems.length)); var counter = 0; @@ -214,7 +217,7 @@ angular.module('cesium.map.wot.services', ['cesium.services']) .catch(function() {/*silent*/})); }, [])) .then(function(){ - console.debug('[map] [wot] Resolved {0}/{1} addresses in {2}ms'.format(counter, searchAddressItems.length, new Date().getTime()-now)); + console.debug('[map] [wot] Resolved {0}/{1} addresses in {2}ms'.format(counter, searchAddressItems.length, Date.now()-now)); return items; }); } diff --git a/assets/www/dist/dist_js/plugins/rml9/plugin-final.js b/assets/www/dist/dist_js/plugins/rml9/plugin-final.js index c4551c4a568e9320fdf5f5dd4cb87f102dc2ba16..e2cd70f41f2460e777cf1ed2519b250cde855730 100644 --- a/assets/www/dist/dist_js/plugins/rml9/plugin-final.js +++ b/assets/www/dist/dist_js/plugins/rml9/plugin-final.js @@ -111,9 +111,7 @@ angular.module('cesium.rml9.plugin', ['ngFileSaver', 'cesium.services']) if (!result || !result.tx || !result.tx.history) return; // no TX var formatDecimal = $filter('formatDecimal'); - var formatPubkey = $filter('formatPubkey'); var formatDate = $filter('formatDate'); - var formatDateForFile = $filter('formatDateForFile'); var headers = [translations['RML9.HEADERS.TIME'], translations['COMMON.UID'], diff --git a/assets/www/dist/dist_js/plugins/services/blockchain-services.js b/assets/www/dist/dist_js/plugins/services/blockchain-services.js index afbf7bbd6ef8d62e14908a8ba00031edfee2726e..090f75e8d133a572d16ed1f04007ce4c9eb50dfd 100644 --- a/assets/www/dist/dist_js/plugins/services/blockchain-services.js +++ b/assets/www/dist/dist_js/plugins/services/blockchain-services.js @@ -31,22 +31,23 @@ angular.module('cesium.es.blockchain.services', ['cesium.services', 'cesium.es.h block: {}, raw: { block: { - search: esHttp.post('/:currency/block/_search'), + search: esHttp.post('/:currency/block/_search', esHttp.cache.SHORT), searchText: esHttp.get('/:currency/block/_search?q=:text'), - get: esHttp.get('/:currency/block/:number/_source') + get: esHttp.get('/:currency/block/:number/_source', esHttp.cache.SHORT) } }, - regex: { + regexp: { ES_CORE_API_ENDPOINT: exact(CONSTANTS.ES_CORE_API_ENDPOINT) } }; + exports.regex = exports.regexp; // deprecated function exact(regexpContent) { return new RegExp('^' + regexpContent + '$'); } exports.node.parseEndPoint = function(endpoint) { - var matches = REGEX.ES_CORE_API_ENDPOINT.exec(endpoint); + var matches = exports.regexp.ES_CORE_API_ENDPOINT.exec(endpoint); if (!matches) return; return { dns: matches[2] || '', diff --git a/assets/www/dist/dist_js/plugins/services/comment-services.js b/assets/www/dist/dist_js/plugins/services/comment-services.js index a3205502dfec75db95be97c20042a3608fb420e1..904856cb289cda43373e88aa64ac0690bbc10be7 100644 --- a/assets/www/dist/dist_js/plugins/services/comment-services.js +++ b/assets/www/dist/dist_js/plugins/services/comment-services.js @@ -167,16 +167,19 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', if (index === -1) return; data.result.splice(index, 1); delete data.mapById[comment.id]; + + var wallet = !csWallet.isUserPubkey(comment.issuer) ? csWallet.children.getByPubkey(comment.issuer) : csWallet; + // Send deletion request - if (csWallet.isUserPubkey(comment.issuer)) { + if (wallet) { return exports.raw.remove(comment.id) .catch(function(err){ console.error(err); - throw new Error('MARKET.ERROR.FAILED_REMOVE_COMMENT'); + throw new Error('COMMENTS.ERROR.FAILED_REMOVE_COMMENT'); }); } else { - return $q.reject("User is not the comment issuer"); + return $q.reject("No wallet found corresponding to the comment issuer"); } }; }; @@ -196,7 +199,7 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', }); // Open websocket - var time = new Date().getTime(); + var time = Date.now(); console.info("[ES] [comment] Starting websocket to listen comments on [{0}/record/{1}]".format(index, recordId.substr(0,8))); var wsChanges = exports.raw.wsChanges(); return wsChanges.open() @@ -208,7 +211,7 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', // Listen changes .then(function(){ - console.debug("[ES] [comment] Websocket opened in {0} ms".format(new Date().getTime() - time)); + console.debug("[ES] [comment] Websocket opened in {0} ms".format(Date.now() - time)); wsChanges.on(function(change) { if (!change) return; scope.$applyAsync(function() { @@ -267,7 +270,7 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', // Preparing JSON to sent var id = comment.id; var json = { - creationTime: id ? comment.creationTime || comment.time/*for compat*/ : esHttp.date.now(), + creationTime: id ? comment.creationTime || comment.time/*for compat*/ : moment().utc().unix(), message: comment.message, record: recordId, issuer: csWallet.data.pubkey diff --git a/assets/www/dist/dist_js/plugins/services/crypto-services.js b/assets/www/dist/dist_js/plugins/services/crypto-services.js index 1a22c28e3f31bd106a239ba0fcc8155a74bcaf0e..341387dd41bd39e0265150f37e8bf9cffbfb4f66 100644 --- a/assets/www/dist/dist_js/plugins/services/crypto-services.js +++ b/assets/www/dist/dist_js/plugins/services/crypto-services.js @@ -92,7 +92,7 @@ angular.module('cesium.es.crypto.services', ['ngResource', 'cesium.services']) cypherFieldNames = [cypherFieldNames]; } - var now = new Date().getTime(); + var now = Date.now(); var issuerBoxPks = {}; // a map used as cache var jobs = [getBoxKeypair(keypair)]; @@ -129,7 +129,7 @@ angular.module('cesium.es.crypto.services', ['ngResource', 'cesium.services']) }, [])); }) .then(function() { - console.debug('[ES] [crypto] All record decrypted in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[ES] [crypto] All record decrypted in ' + (Date.now() - now) + 'ms'); return records; }); diff --git a/assets/www/dist/dist_js/plugins/services/document-services.js b/assets/www/dist/dist_js/plugins/services/document-services.js index 4a4d5ad00e1ec17353f74d906a17ba08da5ea239..bb28284a3e238f63af6b3e2e5e2869d939f05ee3 100644 --- a/assets/www/dist/dist_js/plugins/services/document-services.js +++ b/assets/www/dist/dist_js/plugins/services/document-services.js @@ -147,7 +147,7 @@ angular.module('cesium.es.document.services', ['ngResource', 'cesium.platform', options.index, options.type )); - var now = new Date().getTime(); + var now = Date.now(); return raw.searchText(request) .then(function(res) { @@ -158,25 +158,27 @@ angular.module('cesium.es.document.services', ['ngResource', 'cesium.platform', options.index, options.type, res && res.hits && res.hits.length || 0, - new Date().getTime() - now + Date.now() - now )); return res; }); } - function remove(document) { + function remove(document, options) { if (!document || !document.index || !document.type || !document.id) return $q.reject('Could not remove document: missing mandatory fields'); - return esHttp.record.remove(document.index, document.type)(document.id); + return esHttp.record.remove(document.index, document.type)(document.id, options); } - function removeAll(documents) { + function removeAll(documents, options) { if (!documents || !documents.length) return; - return csWallet.auth() - .then(function(walletData) { + var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet; + + return wallet.auth() // Auth once + .then(function() { // Remove each doc return $q.all(documents.reduce(function (res, doc) { - return res.concat(esHttp.record.remove(doc.index, doc.type)(doc.id, walletData)); + return res.concat(esHttp.record.remove(doc.index, doc.type)(doc.id, {wallet: wallet})); }, [])); }); } diff --git a/assets/www/dist/dist_js/plugins/services/geo-services.js b/assets/www/dist/dist_js/plugins/services/geo-services.js index 051bc6a3a413afb52deed54ba9411a451daeeeae..f2b7c1117b19dc8c66d63be3ac47156f56d272cf 100644 --- a/assets/www/dist/dist_js/plugins/services/geo-services.js +++ b/assets/www/dist/dist_js/plugins/services/geo-services.js @@ -29,6 +29,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser search: csHttp.get('maps.google.com', 443, '/maps/api/geocode/json') }, freegeoip: { + //search: csHttp.get('localhost', 8080, '/json/:ip'), search: csHttp.get('freegeoip.net', 443, '/json/:ip'), license: { name: 'freegeoip', @@ -88,7 +89,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser query.addressdetails = 1; // need address field - var now = new Date(); + var now = Date.now(); //console.debug('[ES] [geo] Searching position...', query); return that.raw.osm.search(query) @@ -116,7 +117,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser }); }, []); - console.debug('[ES] [geo] Found {0} address position(s)'.format(res && res.length || 0, new Date().getTime() - now.getTime()), res); + console.debug('[ES] [geo] Found {0} address position(s)'.format(res && res.length || 0, Date.now() - now), res); return res.length ? res : undefined; }) @@ -156,7 +157,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser return that.raw.freegeoip.search({ip: ip}) .then(function(res) { - //console.debug('[ES] [geo] Found IP {0} position in {0}ms'.format(res ? 1 : 0, new Date().getTime() - now.getTime())); + //console.debug('[ES] [geo] Found IP {0} position in {0}ms'.format(res ? 1 : 0, Date.now() - now.getTime())); return res ? { lat: res.latitude, lng: res.longitude diff --git a/assets/www/dist/dist_js/plugins/services/http-services.js b/assets/www/dist/dist_js/plugins/services/http-services.js index 5305832e763828ae36a34fa8a8dbe80ef736c6a5..d528149dae91f7eb2270f820cd4cb4a6ad5a55c7 100644 --- a/assets/www/dist/dist_js/plugins/services/http-services.js +++ b/assets/www/dist/dist_js/plugins/services/http-services.js @@ -3,8 +3,8 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic /** * Elastic Search Http */ -.factory('esHttp', ['$q', '$timeout', '$rootScope', '$state', '$sce', '$translate', '$window', '$filter', 'CryptoUtils', 'UIUtils', 'csHttp', 'csConfig', 'csSettings', 'BMA', 'csWallet', 'csPlatform', 'Api', function($q, $timeout, $rootScope, $state, $sce, $translate, $window, $filter, - CryptoUtils, UIUtils, csHttp, csConfig, csSettings, BMA, csWallet, csPlatform, Api) { +.factory('esHttp', ['$q', '$timeout', '$rootScope', '$state', '$sce', '$translate', '$window', '$filter', 'CryptoUtils', 'UIUtils', 'csHttp', 'csConfig', 'csSettings', 'csCache', 'BMA', 'csWallet', 'csPlatform', 'Api', function($q, $timeout, $rootScope, $state, $sce, $translate, $window, $filter, + CryptoUtils, UIUtils, csHttp, csConfig, csSettings, csCache, BMA, csWallet, csPlatform, Api) { 'ngInject'; // Allow to force SSL connection with port different from 443 @@ -14,12 +14,14 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic console.debug('[ES] [https] Enable SSL (forced by config or detected in URL)'); } - function Factory(host, port, wsPort, useSsl) { + function EsHttp(host, port, useSsl, useCache) { var that = this, + cachePrefix = 'esHttp-', constants = { - ES_USER_API_ENDPOINT: 'ES_USER_API( ([a-z_][a-z0-9-_.]*))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))' + ES_USER_API_ENDPOINT: 'ES_USER_API( ([a-z_][a-z0-9-_.]*))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))', + MAX_UPLOAD_BODY_SIZE: csConfig.plugins && csConfig.plugins.es && csConfig.plugins.es.maxUploadBodySize || 2097152 /*=2M*/ }, regexp = { IMAGE_SRC: exact('data:([A-Za-z//]+);base64,(.+)'), @@ -41,22 +43,22 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic that.started = false; that.init = init; - init(host, port, wsPort, useSsl); + init(host, port, useSsl, useCache); + that.useCache = angular.isDefined(useCache) ? useCache : false; // need here because used in get() function - function init(host, port, wsPort, useSsl) { + function init(host, port, useSsl, useCache) { // Use settings as default if (!host && csSettings.data) { host = host || (csSettings.data.plugins && csSettings.data.plugins.es ? csSettings.data.plugins.es.host : null); port = port || (host ? csSettings.data.plugins.es.port : null); - wsPort = wsPort || (host ? csSettings.data.plugins.es.wsPort : null); useSsl = angular.isDefined(useSsl) ? useSsl : (port == 443 || csSettings.data.plugins.es.useSsl || forceUseSsl); } that.alive = false; that.host = host; that.port = port || ((useSsl || forceUseSsl) ? 443 : 80); - that.wsPort = wsPort || that.port; that.useSsl = angular.isDefined(useSsl) ? useSsl : (that.port == 443 || forceUseSsl); + that.server = csHttp.getServer(host, port); } @@ -67,15 +69,13 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic var host = data.plugins.es.host; var useSsl = data.plugins.es.port == 443 || data.plugins.es.useSsl || forceUseSsl; var port = data.plugins.es.port || (useSsl ? 443 : 80); - var wsPort = data.plugins.es.wsPort || port; - return isSameNode(host, port, wsPort, useSsl); + return isSameNode(host, port, useSsl); } - function isSameNode(host, port, wsPort, useSsl) { + function isSameNode(host, port, useSsl) { return (that.host == host) && (that.port == port) && - (!wsPort || that.wsPort == wsPort) && (angular.isUndefined(useSsl) || useSsl == that.useSsl); } @@ -129,46 +129,56 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic sock.close(); }); that.cache = _emptyCache(); + + csCache.clear(cachePrefix); }; that.copy = function(otherNode) { if (that.started) that.stop(); - that.init(otherNode.host, otherNode.port, otherNode.wsPort, otherNode.useSsl || otherNode.port == 443); + that.init(otherNode.host, otherNode.port, otherNode.useSsl || otherNode.port == 443); that.data.isTemporary = false; // reset temporary flag return that.start(true /*skipInit*/); }; - - - // Get time (UTC) - that.date = { now : csHttp.date.now }; + that.byteCount = function (s) { + s = (typeof s == 'string') ? s : JSON.stringify(s); + return encodeURI(s).split(/%(?:u[0-9A-F]{2})?[0-9A-F]{2}|./).length - 1; + }; that.getUrl = function(path) { return csHttp.getUrl(that.host, that.port, path, that.useSsl); }; - that.get = function (path) { + that.get = function (path, cacheTime) { + + cacheTime = that.useCache && cacheTime; + var cacheKey = path + (cacheTime ? ('#'+cacheTime) : ''); - var getRequest = function(params) { + var getRequestFn = function(params) { if (!that.started) { if (!that._startPromise) { - console.error('[ES] [http] Trying to get [{0}] before start()...'.format(path)); + console.error('[ES] [http] Trying to get [{0}] before start(). Waiting...'.format(path)); } return that.ready().then(function(start) { if (!start) return $q.reject('ERROR.ES_CONNECTION_ERROR'); - return getRequest(params); // loop + return getRequestFn(params); // loop }); } - var request = that.cache.getByPath[path]; + var request = that.cache.getByPath[cacheKey]; if (!request) { - request = csHttp.get(that.host, that.port, path, that.useSsl); - that.cache.getByPath[path] = request; + if (cacheTime) { + request = csHttp.getWithCache(that.host, that.port, path, that.useSsl, cacheTime, null, null, cachePrefix); + } + else { + request = csHttp.get(that.host, that.port, path, that.useSsl); + } + that.cache.getByPath[cacheKey] = request; } return request(params); }; - return getRequest; + return getRequestFn; }; that.post = function(path) { @@ -197,7 +207,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic return function() { var sock = that.cache.wsByPath[path]; if (!sock) { - sock = csHttp.ws(that.host, that.wsPort, path, that.useSsl); + sock = csHttp.ws(that.host, that.port, path, that.useSsl); that.cache.wsByPath[path] = sock; } return sock; @@ -208,8 +218,8 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic return csHttp.get(that.host, that.port, '/node/summary', that.useSsl)() .then(function(json) { var software = json && json.duniter && json.duniter.software || 'unknown'; - if (software == 'duniter4j-elasticsearch') return true; - console.error("[ES] [http] Not a Duniter4j ES node, but a {0} node".format(software)); + if (software === "cesium-plus-pod" || software === "duniter4j-elasticsearch") return true; + console.error("[ES] [http] Not a Cesium+ Pod, but a {0} node. Please check '/node/summary'".format(software)); return false; }) .catch(function() { @@ -232,8 +242,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Remember the default node defaultSettingsNode = defaultSettingsNode || { host: settings.host, - port: settings.port, - wsPort: settings.wsPort + port: settings.port }; var fallbackNode = settings.fallbackNodes && fallbackNodeIndex < settings.fallbackNodes.length && settings.fallbackNodes[fallbackNodeIndex++]; @@ -251,7 +260,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic that.cleanCache(); - that.init(fallbackNode.host, fallbackNode.port, fallbackNode.wsPort, fallbackNode.useSsl || fallbackNode.port == 443); + that.init(fallbackNode.host, fallbackNode.port, fallbackNode.useSsl || fallbackNode.port == 443); // check is alive then loop return that.isAlive().then(that.checkNodeAlive); @@ -284,7 +293,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic that.server, (that.useSsl ? ' (SSL on)' : '') )); - var now = new Date().getTime(); + var now = Date.now(); return that.checkNodeAlive() .then(function(alive) { @@ -300,7 +309,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Add listeners addListeners(); - console.debug('[ES] [http] Started in '+(new Date().getTime()-now)+'ms'); + console.debug('[ES] [http] Started in '+(Date.now()-now)+'ms'); that.api.node.raise.start(); @@ -343,10 +352,9 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic prefix = prefix || '#'; var reg = prefix === '@' ? regexp.USER_TAG : regexp.HASH_TAG; var matches = value && reg.exec(value); - var tags; + var tags = matches && []; while(matches) { var tag = matches[1]; - tags = tags || []; if (!_.contains(tags, tag)) { tags.push(tag); } @@ -358,10 +366,9 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic function parseUrlsFromText(value) { var matches = value && regexp.URL.exec(value); - var urls; + var urls = matches && []; while(matches) { var url = matches[0]; - urls = urls || []; if (!_.contains(urls, url)) { urls.push(url); } @@ -390,8 +397,10 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Replace URL in description var urls = parseUrlsFromText(content); _.forEach(urls, function(url){ + // Make sure protocol is defined + var href = (url.startsWith('http://') || url.startsWith('https://')) ? url : ('http://' + url); // Redirect URL to the function 'openLink', to open a new window if need (e.g. desktop app) - var link = '<a on-tap=\"openLink($event, \'{0}\')\" href=\"{1}\" target="_blank">{2}</a>'.format(url, url, truncUrlFilter(url)); + var link = '<a on-tap=\"openLink($event, \'{0}\')\" href=\"{1}\" target="_blank">{2}</a>'.format(href, href, truncUrlFilter(url)); content = content.replace(url, link); }); @@ -404,9 +413,9 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Replace user tags var userTags = parseTagsFromText(content, '@'); - _.forEach(userTags, function(uid){ - var link = '<a ui-sref=\"{0}({uid: \'{1}\'})\">@{2}</a>'.format(options.uidState, uid, uid); - content = content.replace('@'+uid, link); + _.forEach(userTags, function(tag){ + var link = '<a ui-sref=\"{0}({uid: \'{1}\'})\">@{2}</a>'.format(options.uidState, tag, tag); + content = content.replace('@'+tag, link); }); } return content; @@ -440,21 +449,40 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic function postRecord(path, options) { options = options || {}; var postRequest = that.post(path); - return function(record, params) { - return csWallet.auth() - .then(function(walletData) { + return function(record, options) { + options = options || {}; + var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) || + ((!options.pubkey || csWallet.isUserPubkey(options.pubkey)) && csWallet) || + (options.pubkey && csWallet.children.getByPubkey(options.pubkey)); + + var keypair = options.keypair || wallet && wallet.data && wallet.data.keypair; + + if (!keypair && !wallet) { + throw new Error('Missing wallet or keypair, to sign record'); + } + + // Create the POSt request params, + // but BEFORE, remove protected options + delete options.wallet; + delete options.walletId; + delete options.keypair; + var params = angular.copy(options); + params.pubkey = params.pubkey || wallet.data.pubkey; + + return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true})) + .then(function() { if (options.creationTime && !record.creationTime) { - record.creationTime = that.date.now(); + record.creationTime = moment().utc().unix(); } // Always update the time - fix #572 // Make sure time is always > previous (required by ES node) - var now = that.date.now(); + var now = moment().utc().unix(); record.time = (!record.time || record.time < now) ? now : (record.time+1); var obj = angular.copy(record); delete obj.signature; delete obj.hash; - obj.issuer = walletData.pubkey; + obj.issuer = params.pubkey; // force keypair pubkey if (!obj.version) { obj.version = 2; } @@ -464,29 +492,41 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic fillRecordTags(obj, options.tagFields); } - //console.debug("Will send obj: ", obj); - var str = JSON.stringify(obj); - - return CryptoUtils.util.hash(str) - .then(function(hash) { - return CryptoUtils.sign(hash, walletData.keypair) - .then(function(signature) { - // Prepend hash+signature - str = '{"hash":"{0}","signature":"{1}",'.format(hash, signature) + str.substring(1); - // Send data - return postRequest(str, params) - .then(function (id){ - return id; - }); - }); - }); - }); + var str = JSON.stringify(obj); + + return CryptoUtils.util.hash(str) + .then(function(hash) { + return CryptoUtils.sign(hash, keypair) + .then(function(signature) { + // Prepend hash+signature + str = '{"hash":"{0}","signature":"{1}",'.format(hash, signature) + str.substring(1); + // Send data + return postRequest(str, params) + .then(function (id){ + + // Clear cache + csCache.clear(cachePrefix); + + return id; + }) + .catch(function(err) { + var bodyLength = that.byteCount(obj); + if (bodyLength > constants.MAX_UPLOAD_BODY_SIZE) { + throw {message: 'ERROR.ES_MAX_UPLOAD_BODY_SIZE', length: bodyLength}; + } + throw err; + }); + }); + }); + }); }; } function removeRecord(index, type) { - return function(id) { - return (csWallet.isAuth() ? $q.when(csWallet.data) : csWallet.auth({silent: true, minData: true})) + return function(id, options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true})) .then(function(walletData) { var obj = { @@ -495,7 +535,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic type: type, id: id, issuer: walletData.pubkey, - time: that.date.now() + time: moment().utc().unix() }; var str = JSON.stringify(obj); return CryptoUtils.util.hash(str) @@ -586,11 +626,13 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic function parseEndPoint(endpoint) { var matches = regexp.ES_USER_API_ENDPOINT.exec(endpoint); if (!matches) return; + var port = matches[8] || 80; return { "dns": matches[2] || '', "ipv4": matches[4] || '', "ipv6": matches[6] || '', - "port": matches[8] || 80 + "port": port, + "useSsl": port == 80 ? false : (port == 443) }; } @@ -631,6 +673,10 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic sameAsSettings: isSameNodeAsSettings, isFallback: isFallbackNode }, + network: { + peering: that.get('/network/peering'), + peers: that.get('/network/peers') + }, record: { post: postRecord, remove: removeRecord @@ -647,6 +693,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic parseAsHtml: parseAsHtml, findObjectInTree: findObjectInTree }, + cache: csHttp.cache, constants: constants }; exports.constants.regexp = regexp; @@ -654,10 +701,10 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic } - var service = new Factory(); + var service = new EsHttp(undefined, undefined, undefined, true); - service.instance = function(host, port, wsPort, useSsl) { - return new Factory(host, port, wsPort, useSsl); + service.instance = function(host, port, useSsl, useCache) { + return new EsHttp(host, port, useSsl, useCache); }; return service; diff --git a/assets/www/dist/dist_js/plugins/services/invitation-services.js b/assets/www/dist/dist_js/plugins/services/invitation-services.js index 57f9f15c2899d655621c20e55e6f944ac0119690..7ca0b3dd845c8e0a0de98383580143b19a6d8b67 100644 --- a/assets/www/dist/dist_js/plugins/services/invitation-services.js +++ b/assets/www/dist/dist_js/plugins/services/invitation-services.js @@ -39,6 +39,7 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', function onWalletInit(data) { data.invitations = data.invitations || {}; data.invitations.unreadCount = null; + data.invitations.time = null; } function onWalletReset(data) { @@ -47,22 +48,33 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', } } - function onWalletLogin(data, deferred) { + function onWalletLoad(data, deferred) { deferred = deferred || $q.defer(); if (!data || !data.pubkey) { deferred.resolve(); return deferred.promise; } - console.debug('[ES] [invitations] Loading count...'); - var now = new Date().getTime(); + var now = Date.now(); + var time = Math.trunc(now / 1000); - // Count unread messages + // Skip if loaded less than 1 min ago + // (This is need to avoid reload on login AND load phases) + if (data.invitations && data.invitations.time && (time - data.invitations.time < 30 /*=30s*/)) { + console.debug('[ES] [invitation] Skipping load (loaded '+(time - data.invitations.time)+'s ago)'); + deferred.resolve(); + return deferred.promise; + } + + console.debug('[ES] [invitation] Loading count...'); + + // Count unread invitations countUnreadInvitations(data.pubkey) .then(function(unreadCount){ data.invitations = data.invitations || {}; data.invitations.unreadCount = unreadCount; - console.debug('[ES] [invitation] Loaded count (' + unreadCount + ') in '+(new Date().getTime()-now)+'ms'); + data.invitations.time = time; + console.debug('[ES] [invitation] Loaded count (' + unreadCount + ') in '+(Date.now()-now)+'ms'); deferred.resolve(data); }) .catch(function(err){ @@ -142,11 +154,13 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }); } - function sendInvitation(record, keypair, type) { - type = type || 'certification'; + function sendInvitation(record, options) { + options = options || {}; + options.type = options.type || 'certification'; + var keypair = options.keypair || (options.wallet && options.wallet.data.keypair); return esWallet.box.record.pack(record, keypair, 'recipient', ['content', 'comment']) .then(function(record) { - return that.raw[type].add(record); + return that.raw[options.type].add(record, options); }); } @@ -180,16 +194,18 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }); } - function loadInvitations(options) { + function loadInvitations(options, keypair) { if (!csWallet.isLogin()) return $q.when([]); // Should never happen options = options || {}; options.from = options.from || 0; options.size = options.size || constants.DEFAULT_LOAD_SIZE; + + var issuer = options.issuer || csWallet.data.pubkey; var request = { sort: { "time" : "desc" }, - query: {bool: {filter: {term: {recipient: csWallet.data.pubkey}}}}, + query: {bool: {filter: {term: {recipient: issuer}}}}, from: options.from, size: options.size, _source: fields.commons @@ -200,13 +216,8 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', query.bool.must = [{range: {time: {gt: options.readTime}}}]; } - return $q.all([ - esWallet.box.getKeypair(), - that.raw.certification.postSearch(request) - ]) + return that.raw.certification.postSearch(request) .then(function(res) { - var keypair = res[0]; - res = res[1]; if (!res || !res.hits || !res.hits.total) return []; var invitations = res.hits.hits.reduce(function (result, hit) { @@ -264,42 +275,47 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }); } - function deleteInvitation(invitation) { + function deleteInvitation(invitation, options) { if (!invitation || !invitation.id) throw 'Invalid invitation (empty or without id). Could not delete.'; var type = invitation.type || 'certification'; - return that.raw[type].remove(invitation.id) + var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet; + return that.raw[type].remove(invitation.id, {wallet: wallet}) .then(function() { // Always reset unread count - csWallet.data.invitations.unreadCount = 0; + wallet.data.invitations.unreadCount = 0; - if (!csWallet.data.invitations || !csWallet.data.invitations.list) return; + if (!wallet.data.invitations || !wallet.data.invitations.list) return; // Remove form list - csWallet.data.invitations.list.splice(csWallet.data.invitations.list.indexOf(invitation), 1); + wallet.data.invitations.list.splice(wallet.data.invitations.list.indexOf(invitation), 1); }); } - function deleteInvitationsByIds(ids, type) { + function deleteInvitationsByIds(ids, type, options) { if (!ids || !ids.length) return $q.when(); type = type || 'certification'; return $q.all( ids.reduce(function(res, id) { - return res.concat(that.raw[type].remove(id)); + return res.concat(that.raw[type].remove(id, options)); }, []) ); } - function deleteAllInvitations(pubkey, type) { - pubkey = pubkey || csWallet.data.pubkey; + function deleteAllInvitationsByPubkey(type, options) { + type = type || 'certification'; - console.debug('[ES] [invitation] Deleting all invitations...'); - var now = new Date().getTime(); - var countBeforeDeletion = (csWallet.data.invitations && csWallet.data.invitations.count) || 0; - var unreadCountBeforeDeletion = (csWallet.data.invitations && csWallet.data.invitations.unreadCount) || 0; + var now = Date.now(); + console.debug('[ES] [invitation] Deleting all {0} invitations...'.format(type)); + + var wallet = (options && options.pubkey && csWallet.children.getByPubkey(options.pubkey)) || + (options && options.walletId && csWallet.children.getByPubkey(options.walletId)) || + csWallet; + var countBeforeDeletion = (wallet.data.invitations && wallet.data.invitations.count) || 0; + var unreadCountBeforeDeletion = (wallet.data.invitations && wallet.data.invitations.unreadCount) || 0; // Get invitation ids - return that.raw[type].getIds({pubkey: pubkey}) + return that.raw[type].getIds({pubkey: wallet.data.pubkey}) .then(function(res) { if (!res || !res.hits || !res.hits.total) return; var ids = res.hits.hits.reduce(function (res, hit) { @@ -307,26 +323,26 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }, []); // Do deletion by ids - return deleteInvitationsByIds(ids, type) + return deleteInvitationsByIds(ids, type, {walletId: wallet.id}) .then(function() { // Update wallet count - csWallet.data.invitations = csWallet.data.invitations || {}; + wallet.data.invitations = wallet.data.invitations || {}; // Decrement count (warning: could have received new invitations during deletion execution) - if (csWallet.data.invitations.count >= countBeforeDeletion) { - csWallet.data.invitations.count -= countBeforeDeletion || 0; + if (wallet.data.invitations.count >= countBeforeDeletion) { + wallet.data.invitations.count -= countBeforeDeletion || 0; } else { - csWallet.data.invitations.count = 0; + wallet.data.invitations.count = 0; } // Decrement count (warning: could have received new invitations during deletion execution) - if (csWallet.data.invitations.unreadCount >= unreadCountBeforeDeletion) { - csWallet.data.invitations.unreadCount -= unreadCountBeforeDeletion || 0; + if (wallet.data.invitations.unreadCount >= unreadCountBeforeDeletion) { + wallet.data.invitations.unreadCount -= unreadCountBeforeDeletion || 0; } else { - csWallet.data.invitations.unreadCount = 0; + wallet.data.invitations.unreadCount = 0; } - console.debug('[ES] [invitation] All invitations deleted in {0}ms'.format(new Date().getTime()-now)); + console.debug('[ES] [invitation] All {0} invitations deleted in {1}ms'.format(type, Date.now()-now)); }); }); } @@ -342,8 +358,9 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', function addListeners() { // Extend csWallet events listeners = [ - csWallet.api.data.on.login($rootScope, onWalletLogin, this), csWallet.api.data.on.init($rootScope, onWalletInit, this), + csWallet.api.data.on.login($rootScope, onWalletLoad, this), + csWallet.api.data.on.load($rootScope, onWalletLoad, this), csWallet.api.data.on.reset($rootScope, onWalletReset, this), csWallet.api.action.on.certify($rootScope, onWalletCertify, this), esNotification.api.event.on.newInvitation($rootScope, onNewInvitationEvent, this) @@ -363,7 +380,7 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', console.debug("[ES] [invitations] Enable"); addListeners(); if (csWallet.isLogin()) { - onWalletLogin(csWallet.data); + onWalletLoad(csWallet.data); } } } @@ -385,7 +402,7 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', that.send = sendInvitation; that.delete = deleteInvitation; that.deleteByIds = deleteInvitationsByIds; - that.deleteAll = deleteAllInvitations; + that.deleteAll = deleteAllInvitationsByPubkey; that.constants = constants; diff --git a/assets/www/dist/dist_js/plugins/services/message-services.js b/assets/www/dist/dist_js/plugins/services/message-services.js index 2a93b158e049d8166b3abacc49758eecc347e0d3..3631fe44d97c30a217ac56e5e65278c3a6372d41 100644 --- a/assets/www/dist/dist_js/plugins/services/message-services.js +++ b/assets/www/dist/dist_js/plugins/services/message-services.js @@ -35,6 +35,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', function onWalletInit(data) { data.messages = data.messages || {}; data.messages.unreadCount = null; + data.messages.time = null; } function onWalletReset(data) { @@ -43,35 +44,50 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } } - function onWalletLogin(data, deferred) { + function onWalletLoad(data, deferred) { deferred = deferred || $q.defer(); + if (!data || !data.pubkey) { deferred.resolve(); return deferred.promise; } + var now = Date.now(); + var time = Math.trunc(now / 1000); + + // Skip if loaded less than 1 min ago + // (This is need to avoid reload on login AND load phases) + if (data.messages && data.messages.time && (time - data.messages.time < 30 /*=30s*/)) { + console.debug('[ES] [message] Skipping load (loaded '+(time - data.messages.time)+'s ago)'); + deferred.resolve(); + return deferred.promise; + } + console.debug('[ES] [message] Loading count...'); - var now = new Date().getTime(); // Count unread messages - countUnreadMessages(data.pubkey) - .then(function(unreadCount){ + countUnreadMessages({pubkey: data.pubkey}) + .then(function(unreadCount) { data.messages = data.messages || {}; data.messages.unreadCount = unreadCount; - console.debug('[ES] [message] Loaded count (' + unreadCount + ') in '+(new Date().getTime()-now)+'ms'); + data.messages.time = time; + console.debug('[ES] [message] Loaded count (' + unreadCount + ') in '+(Date.now()-now)+'ms'); deferred.resolve(data); }) .catch(function(err){ - console.error('Error chile counting message: ' + (err.message ? err.message : err)); + console.error('Error while counting messages: ' + (err.message ? err.message : err)); deferred.resolve(data); }); return deferred.promise; } - function countUnreadMessages(pubkey) { - pubkey = pubkey || (csWallet.isLogin() ? csWallet.data.pubkey : pubkey); + function countUnreadMessages(options) { + options = options || {}; + var wallet = options.wallet || + (options.walletId && csWallet.children.get(options.walletId)) || csWallet; + var pubkey = options.pubkey || (wallet && wallet.data && wallet.data.pubkey); if (!pubkey) { - throw new Error('no pubkey, and user not connected.'); + throw new Error('no pubkey or wallet found in options, and user not connected.'); } var request = { @@ -92,33 +108,50 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } // Listen message changes - function onNewMessageEvent(event) { + function onNewMessageEvent(event, wallet) { console.debug("[ES] [message] detected new message (from notification service)"); - var notification = new Notification(event); + var notification = new EsNotification(event); notification.issuer = notification.pubkey; delete notification.pubkey; + if (!notification.issuer) return; // Skip if invalid + + // Get the wallet + wallet = wallet || (notification.issuer && csWallet.isUserPubkey(notification.issuer) && csWallet) || + (notification.issuer && csWallet.children.getByPubkey(notification.issuer)); + + if (!wallet) { + throw new Error("No wallet for pubkey: {0}".format(notification.issuer.substring(0, 6))); + } + csWot.extend(notification, 'issuer') .then(function() { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount++; + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.unreadCount++; // Raise event api.data.raise.new(notification); }); } - function sendMessage(message) { - return csWallet.getKeypair() + function sendMessage(message, options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + delete options.wallet; + message.issuer = message.issuer || wallet.data.pubkey; + return wallet.getKeypair() .then(function(keypair) { + + // Send to recipient inbox return doSendMessage(message, keypair) .then(function (res) { + + // Check if outbox is enable (in settings) var outbox = (csSettings.data.plugins.es.message && angular.isDefined(csSettings.data.plugins.es.message.outbox)) ? csSettings.data.plugins.es.message.outbox : true; - if (!outbox) return res; // Send to outbox @@ -129,7 +162,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }); }) .then(function (res) { - // Raise event + // Raise API event api.data.raise.sent(res); return res; @@ -144,22 +177,25 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', return esWallet.box.record.pack(message, keypair, recipientFieldName, ['title', 'content']) // Send message .then(function(message){ - return esHttp.record.post(boxPath)(message); + return esHttp.record.post(boxPath)(message, {pubkey: message.issuer, keypair: keypair}); }); } function loadMessageNotifications(options) { - if (!csWallet.isLogin()) { - return $q.when([]); // Should never happen - } options = options || {}; options.from = options.from || 0; options.size = options.size || constants.DEFAULT_LOAD_SIZE; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + delete options.wallet; + + if (!wallet.isLogin()) { + return $q.when([]); // Should never happen + } var request = { sort: { "time" : "desc" }, - query: {bool: {filter: {term: {recipient: csWallet.data.pubkey}}}}, + query: {bool: {filter: {term: {recipient: wallet.data.pubkey}}}}, from: options.from, size: options.size, _source: fields.notifications @@ -231,7 +267,10 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', options.filter = angular.isDefined(options.filter) ? options.filter : undefined; options.from = options.from || 0; - var promise = csWallet.auth() + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + delete options.wallet; // avoid error in angular.copy() + + var promise = wallet.auth() .then(function(walletData) { // Get encrypted message (with common fields) @@ -254,12 +293,15 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', if (messages.length && options.filter){ var filteredMessages = filterMessages(messages, options.filter); - // Recursive loop, if need more + // Need more messages: iterate again if (filteredMessages.length < messages.length) { options = angular.copy(options); options.from += options.size; options.size = messages.length - filteredMessages.length; - return loadMessages(options) + // put the wallet again, because it has been removed before the angular.copy() + // To avoid an error + options.wallet = wallet; + return loadMessages(options) // Loop .then(function(messages) { return filteredMessages.concat(messages); }); @@ -267,8 +309,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } if (options.from === 0 && !options.filter) { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = messages.length; + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.count = messages.length; } return messages; @@ -282,19 +324,20 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', return promise; } - function getAndDecrypt(id, options) { + function getAndDecrypt(id, type, options) { + type = type || 'inbox'; options = options || {}; - options.type = options.type || 'inbox'; options.summary = angular.isDefined(options.summary) ? options.summary : false/*summary not need by default*/; + var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) || csWallet; - return csWallet.auth() + return wallet.auth() .then(function(walletData) { - return raw.getByTypeAndId({id: id, type: options.type}) + return raw.getByTypeAndId({id: id, type: type}) .then(function(hit) { if (!hit.found) return; var msg = hit._source; msg.id = hit._id; - msg.read = (options.type == 'outbox') || !!msg.read_signature; + msg.read = (type == 'outbox') || !!msg.read_signature; delete msg.read_signature; // not need anymore // Decrypt message @@ -302,7 +345,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Add avatar .then(function(){ - var avatarField = (options.type == 'inbox') ? 'issuer' : 'recipient'; + var avatarField = (type == 'inbox') ? 'issuer' : 'recipient'; return csWot.extend(msg, avatarField); }); }); @@ -311,7 +354,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', function decryptMessages(messages, keypair, withSummary) { - var now = new Date().getTime(); + var now = Date.now(); var issuerBoxPks = {}; // a map used as cache var jobs = [esWallet.box.getKeypair(keypair)]; @@ -362,7 +405,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }, [])); }) .then(function() { - console.debug('[ES] [message] All messages decrypted in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[ES] [message] All messages decrypted in ' + (Date.now() - now) + 'ms'); return messages; }); @@ -378,26 +421,32 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } } - function removeMessage(id, type) { + function removeMessage(id, type, options) { type = type || 'inbox'; - return esHttp.record.remove('message', type)(id) + + var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) || csWallet; + + return esHttp.record.remove('message', type)(id, {wallet: wallet}) .then(function(res) { - // update message count - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = csWallet.data.messages.count > 0 ? csWallet.data.messages.count-1 : 0; + // Update message count + if (type === 'inbox') { + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.count = wallet.data.messages.count > 0 ? wallet.data.messages.count-1 : 0; } + // Raise event - api.data.raise.delete(id); + if (wallet.isDefault()) { + api.data.raise.delete(id); + } return res; }); } - function removeAllMessages(type) { + function removeAllMessages(type, options) { type = type || 'inbox'; - - return csWallet.auth() + var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet; + return wallet.auth() .then(function(walletData) { // Get all message id return searchMessages(walletData.pubkey, {type: type, from: 0, size: 1000, _source: false}) @@ -408,7 +457,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Remove each messages return $q.all(res.reduce(function (res, msg) { - return res.concat(esHttp.record.remove('message', type)(msg.id, walletData)); + return res.concat(esHttp.record.remove('message', type)(msg.id, {wallet: wallet})); }, [])) .then(function() { return ids; @@ -416,21 +465,25 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }) .then(function (ids) { // update message count - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = 0; - csWallet.data.messages.unreadCount = 0; + if (type === 'inbox') { + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.count = 0; + wallet.data.messages.unreadCount = 0; } // Raise events - _.forEach(ids, api.data.raise.delete); + if (wallet.isDefault()) { + _.forEach(ids, api.data.raise.delete); + } }); }); } // Mark a message as read - function markMessageAsRead(message, type) { - type = type || 'inbox'; + function markMessageAsRead(message, options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + var type = options && options.type || (!wallet.isUserPubkey(message.recipient) ? 'outbox' : 'inbox'); if (message.read) { var deferred = $q.defer(); deferred.resolve(); @@ -438,7 +491,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } message.read = true; - return csWallet.getKeypair() + return wallet.getKeypair() // Prepare the read_signature to sent .then(function(keypair) { @@ -452,16 +505,18 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Update message count .then(function() { - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount = csWallet.data.messages.unreadCount ? csWallet.data.messages.unreadCount - 1 : 0; + if (type === 'inbox') { + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.unreadCount = wallet.data.messages.unreadCount ? wallet.data.messages.unreadCount - 1 : 0; } }); } // Mark all messages as read - function markAllMessageAsRead() { - return csWallet.auth() + function markAllMessageAsRead(options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + return wallet.auth() .then(function(walletData) { // Get all messages hash @@ -491,8 +546,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }) .then(function () { // update message count - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount = 0; + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.unreadCount = 0; }); }); } @@ -574,7 +629,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', console.info("[ES] [message] Sending logs to developers..."); message.issuer = csWallet.data.pubkey; message.title = message.title || 'Sending log'; - message.time = esHttp.date.now(); + message.time = moment().utc().unix(); csWallet.getKeypair() .then(function(keypair) { @@ -598,8 +653,9 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', function addListeners() { // Extend csWallet events listeners = [ - csWallet.api.data.on.login($rootScope, onWalletLogin, this), csWallet.api.data.on.init($rootScope, onWalletInit, this), + csWallet.api.data.on.login($rootScope, onWalletLoad, this), + csWallet.api.data.on.load($rootScope, onWalletLoad, this), // need for secondary wallets csWallet.api.data.on.reset($rootScope, onWalletReset, this), esNotification.api.event.on.newMessage($rootScope, onNewMessageEvent, this), // for issue #524 @@ -620,7 +676,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', console.debug("[ES] [message] Enable"); addListeners(); if (csWallet.isLogin()) { - onWalletLogin(csWallet.data); + onWalletLoad(csWallet.data); } } } diff --git a/assets/www/dist/dist_js/plugins/services/modal-services.js b/assets/www/dist/dist_js/plugins/services/modal-services.js index f0619109858741a7051e7bf340ceefecc07b9e53..06e53471f8128dbf001c40746b3cbaf189be8f2d 100644 --- a/assets/www/dist/dist_js/plugins/services/modal-services.js +++ b/assets/www/dist/dist_js/plugins/services/modal-services.js @@ -8,25 +8,12 @@ angular.module('cesium.es.modal.services', ['cesium.modal.services', 'cesium.es. parameters, {focusFirstInput: true}); } - function updateNotificationCountAndReadTime() { - csWallet.data.notifications.unreadCount = 0; - if (csWallet.data.notifications && csWallet.data.notifications.history.length) { - var lastNotification = csWallet.data.notifications.history[0]; - var readTime = lastNotification ? lastNotification.time : 0; - csSettings.data.wallet = csSettings.data.wallet || {}; - if (readTime && csSettings.data.wallet.notificationReadTime != readTime) { - csSettings.data.wallet.notificationReadTime = readTime; - csSettings.store(); - } - } - } - function showNotificationsPopover(scope, event) { return UIUtils.popover.show(event, { templateUrl :'plugins/es/templates/common/popover_notification.html', scope: scope, autoremove: false, // reuse popover - afterHidden: updateNotificationCountAndReadTime + afterHidden: scope.resetUnreadCount }) .then(function(notification) { if (!notification) return; // no selection @@ -51,8 +38,9 @@ angular.module('cesium.es.modal.services', ['cesium.modal.services', 'cesium.es. }); } - function showNewPage() { - return csWallet.auth({minData: true}) + function showNewPage(options) { + var wallet = options && options.wallet || csWallet; + return wallet.auth({minData: true}) .then(function() { UIUtils.loading.hide(); @@ -61,7 +49,7 @@ angular.module('cesium.es.modal.services', ['cesium.modal.services', 'cesium.es. }) .then(function(type){ if (type) { - $state.go('app.registry_add_record', {type: type}); + $state.go('app.registry_add_record', {type: type, wallet: wallet.id}); } }); }); diff --git a/assets/www/dist/dist_js/plugins/services/notification-services.js b/assets/www/dist/dist_js/plugins/services/notification-services.js index 6fc01d7686361080b77f17bb915a740f38f17da2..a0326e834535fbe6b850dfdec904419d03227c74 100644 --- a/assets/www/dist/dist_js/plugins/services/notification-services.js +++ b/assets/www/dist/dist_js/plugins/services/notification-services.js @@ -10,7 +10,9 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es }]) -.factory('esNotification', ['$rootScope', '$q', '$timeout', 'esHttp', 'csConfig', 'csSettings', 'csWallet', 'csWot', 'UIUtils', 'BMA', 'CryptoUtils', 'csPlatform', 'Api', function($rootScope, $q, $timeout, esHttp, csConfig, csSettings, csWallet, csWot, UIUtils, BMA, CryptoUtils, csPlatform, Api) { +.factory('esNotification', ['$rootScope', '$q', '$timeout', '$translate', '$state', 'csHttp', 'csConfig', 'csSettings', 'esHttp', 'esSettings', 'csWallet', 'csWot', 'UIUtils', 'filterTranslations', 'BMA', 'CryptoUtils', 'csPlatform', 'Api', function($rootScope, $q, $timeout, $translate, $state, csHttp, + csConfig, csSettings, esHttp, esSettings, csWallet, csWot, UIUtils, filterTranslations, + BMA, CryptoUtils, csPlatform, Api) { 'ngInject'; var @@ -25,6 +27,7 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es }, that = this, listeners, + wsUserEventCloseFn, api = new Api(this, 'esNotification') ; @@ -105,16 +108,51 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es }); } + function getWalletNotifications(options) { + options = options || {}; + var wallet = options.wallet || csWallet; + + return new Promise(function(resolve) { + if (!wallet.data || !wallet.data.events ||!wallet.data.events.length) return resolve([]); + + // Add some wallet events as notifications + var time = csHttp.date.now() - filterTranslations.MEDIAN_TIME_OFFSET; + var result = (wallet.data.events || []).reduce(function(res, event) { + if (event.type != "warn" && event.type != "error") return res; // Keep only warn and error events + var notification = new EsNotification({}, function(self) { + if (!self.read) { + self.read = true; + if (wallet.data.notifications && wallet.data.notifications.warnCount > 0) { + wallet.data.notifications.warnCount--; + } + } + }); + notification.id=event.code; + notification.read = false; + notification.state = 'app.view_wallet'; + notification.avatarIcon = 'ion-alert-circled'; + notification.icon = 'ion-alert-circled assertive'; + notification.time = time; + notification.message = event.message; + notification.messageParams = event.messageParams; + return res.concat(notification); + }, []); + + resolve(result); + }); + + } + // Load user notifications - function loadNotifications(pubkey, options) { - if (!pubkey) { - return $q.reject('[ES] [notification] Unable to load - missing pubkey'); - } + function loadNotifications(options) { options = options || {}; + if (!options.pubkey) { + return $q.reject('[ES] [notification] Unable to load - missing options.pubkey'); + } options.from = options.from || 0; options.size = options.size || constants.DEFAULT_LOAD_SIZE; var request = { - query: createFilterQuery(pubkey, options), + query: createFilterQuery(options.pubkey, options), sort : [ { "time" : {"order" : "desc"}} ], @@ -123,14 +161,24 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es _source: fields.commons }; - return that.raw.postSearch(request) - .then(function(res) { - if (!res.hits || !res.hits.total) return []; + return $q.all([ + // Get wallet events (as notifications) + getWalletNotifications(options), + + // Load notification from ES node + that.raw.postSearch(request) + ]).then(function(res) { + + var walletNotifs = res[0] || []; + res = res[1]; + + if (!res.hits || !res.hits.total) return walletNotifs; + var notifications = res.hits.hits.reduce(function(res, hit) { - var item = new Notification(hit._source, markNotificationAsRead); + var item = new EsNotification(hit._source, markNotificationAsRead); item.id = hit._id; return res.concat(item); - }, []); + }, walletNotifs); return csWot.extendAll(notifications); }); @@ -151,7 +199,7 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es return; } - var notification = new Notification(event, markNotificationAsRead); + var notification = new EsNotification(event, markNotificationAsRead); // Extend the notification entity return csWot.extendAll([notification]) @@ -164,6 +212,9 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es else { addNewNotification(notification); } + }) + .then(function() { + if (esSettings.notifications.isEmitHtml5Enable()) return emitEsNotification(notification); }); } @@ -171,6 +222,66 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es csWallet.data.notifications = csWallet.data.notifications || {}; csWallet.data.notifications.unreadCount++; api.data.raise.new(notification); + + return notification; + } + + function htmlToPlaintext(text) { + return text ? String(text).replace(/<[^>]*>/gm, '').replace(/&[^;]+;/gm, '') : ''; + } + + function emitEsNotification(notification, title) { + + // If it's okay let's create a notification + $q.all([ + $translate(title||'COMMON.NOTIFICATION.TITLE'), + $translate(notification.message, notification) + ]) + .then(function(res) { + var title = htmlToPlaintext(res[0]); + var body = htmlToPlaintext(res[1]); + var icon = notification.avatar && notification.avatar.src || './img/logo.png'; + emitHtml5Notification(title, { + body: body, + icon: icon, + lang: $translate.use(), + tag: notification.id, + onclick: function() { + $rootScope.$applyAsync(function() { + if (typeof notification.markAsRead === "function") { + notification.markAsRead(); + } + if (notification.state) { + $state.go(notification.state, notification.stateParams); + } + }); + } + }); + }); + } + + function emitHtml5Notification(title, options) { + + // Let's check if the browser supports notifications + if (!("Notification" in window)) return; + + // Let's check whether notification permissions have already been granted + if (Notification.permission === "granted") { + + // If it's okay let's create a notification + var browserNotification = new Notification(title, options); + browserNotification.onclick = options.onclick || browserNotification.onclick; + } + + // Otherwise, we need to ask the user for permission + else if (Notification.permission !== "denied") { + Notification.requestPermission(function (permission) { + // If the user accepts, let's create a notification + if (permission === "granted") { + emitHtml5Notification(title, options); // recursive call + } + }); + } } // Mark a notification as read @@ -202,44 +313,82 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es function onWalletReset(data) { data.notifications = data.notifications || {}; data.notifications.unreadCount = null; + data.notifications.warnCount = null; + data.notifications.time = null; // Stop listening notification - that.raw.ws.getUserEvent().close(); + if (wsUserEventCloseFn) { + console.debug("[ES] [notification] Closing websocket..."); + wsUserEventCloseFn(); + wsUserEventCloseFn = null; + } } - function onWalletLogin(data, deferred) { + function onWalletLoad(data, deferred) { deferred = deferred || $q.defer(); if (!data || !data.pubkey || !data.keypair) { deferred.resolve(); return deferred.promise; } - console.debug('[ES] [notification] Loading count...'); - var now = new Date().getTime(); + var now = Date.now(); + var time = Math.trunc(now / 1000); + + // Skip if loaded less than 1 min ago + // (This is need to avoid reload on login AND load phases) + if (data.notifications && data.notifications.time && (time - data.notifications.time < 30 /*=30s*/)) { + // update warn count + data.notifications.warnCount = countWarnEvents(data); + + console.debug('[ES] [notification] Skipping load (loaded '+(time - data.notifications.time)+'s ago)'); + deferred.resolve(); + return deferred.promise; + } + + var isDefaultWallet = csWallet.isUserPubkey(data.pubkey); + console.debug('[ES] [notification] Loading count...' + data.pubkey.substr(0,8)); // Load unread notifications count loadUnreadNotificationsCount( data.pubkey, { - readTime: csSettings.data.wallet ? csSettings.data.wallet.notificationReadTime : 0, + readTime: data.notifications && data.notifications.time || 0, excludeCodes: constants.EXCLUDED_CODES }) .then(function(unreadCount) { data.notifications = data.notifications || {}; data.notifications.unreadCount = unreadCount; - console.debug('[ES] [notification] Loaded count (' + unreadCount + ') in '+(new Date().getTime()-now)+'ms'); + data.notifications.warnCount = countWarnEvents(data); + + // Emit HTML5 notification (only on main wallet) + if (unreadCount > 0 && esSettings.notifications.isEmitHtml5Enable() && isDefaultWallet) { + $timeout(function() { + emitEsNotification({ + message: 'COMMON.NOTIFICATION.HAS_UNREAD', + count: unreadCount, + state: 'app.view_notifications' + }, data.ui || data.name || data.pubkey && data.pubkey.substr(0,8)); + }, 500); + } + + console.debug('[ES] [notification] Loaded count (' + unreadCount + ') in '+(Date.now()-now)+'ms'); deferred.resolve(data); }) - .catch(function(err){ - deferred.reject(err); - }) + .catch(deferred.reject); - // Listen new events + return deferred.promise; + } + + function onWalletLogin(data, deferred) { + // Call load + return onWalletLoad(data, deferred) + + // then start listening new events .then(function(){ console.debug('[ES] [notification] Starting listen user event...'); - var userEventWs = that.raw.ws.getUserEvent(); - listeners.push(userEventWs.close); - return userEventWs.on(onNewUserEvent, - {pubkey: data.pubkey, locale: csSettings.data.locale.id} - ) + var wsUserEvent = that.raw.ws.getUserEvent(); + wsUserEvent.on( + onNewUserEvent, + {pubkey: data.pubkey, locale: csSettings.data.locale.id} + ) .catch(function(err) { console.error('[ES] [notification] Unable to listen user event', err); @@ -247,15 +396,22 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es // And display such connectivity errors in UI UIUtils.alert.error('ACCOUNT.ERROR.WS_CONNECTION_FAILED'); }); + wsUserEventCloseFn = function() {wsUserEvent.close();}; }); + } - return deferred.promise; + function countWarnEvents(data){ + if (!data.events) return 0; + return data.events.reduce(function(counter, event) { + return (event.type == "warn") ? counter+1 : counter; + }, 0); } function addListeners() { // Listen some events listeners = [ csWallet.api.data.on.login($rootScope, onWalletLogin, this), + csWallet.api.data.on.load($rootScope, onWalletLoad, this), csWallet.api.data.on.init($rootScope, onWalletReset, this), csWallet.api.data.on.reset($rootScope, onWalletReset, this) ]; @@ -301,6 +457,9 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es // Exports that.load = loadNotifications; that.unreadCount = loadUnreadNotificationsCount; + that.html5 = { + emit: emitHtml5Notification + }; that.api = api; that.websocket = { event: that.raw.ws.getUserEvent, diff --git a/assets/www/dist/dist_js/plugins/services/profile-services.js b/assets/www/dist/dist_js/plugins/services/profile-services.js index 2655d26294a0cbec671af54dc6aec796dbc6daae..f19747f12f2ac06a85cd23f31195802d6e2dacee 100644 --- a/assets/www/dist/dist_js/plugins/services/profile-services.js +++ b/assets/www/dist/dist_js/plugins/services/profile-services.js @@ -19,10 +19,10 @@ angular.module('cesium.es.profile.services', ['cesium.services', 'cesium.es.http that.raw = { getFields: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content&_source=:fields'), - get: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content'), - getAll: esHttp.get('/user/profile/:id'), - search: esHttp.post('/user/profile/_search'), - mixedSearch: esHttp.post('/user,page,group/profile,record/_search') + get: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content', esHttp.cache.MEDIUM), + getAll: esHttp.get('/user/profile/:id', esHttp.cache.MEDIUM), + search: esHttp.post('/user/profile/_search', esHttp.cache.MEDIUM), + mixedSearch: esHttp.post('/user,page,group/profile,record/_search', esHttp.cache.MEDIUM) }; function getAvatarAndName(pubkey) { @@ -192,20 +192,16 @@ angular.module('cesium.es.profile.services', ['cesium.services', 'cesium.es.http }; } else { - request.query.constant_score = { - filter: {bool: {should: [ - {terms : {_id : pubkeys}}, - {bool: { - must: [ - {match: {title: {query: text, boost: 2}}}, - {prefix: {title: text}} - ]} - } - ]}} + request.query.bool = { + should: [ + {terms : {"_id^4" : pubkeys}}, + {match: {title: {query: text, boost: 2}}}, + {prefix: {title: text}} + ] }; if (tags) { - request.query.constant_score.filter.bool.should.push({terms: {tags: tags}}); + request.query.bool.should.push({terms: {tags: tags}}); } } } diff --git a/assets/www/dist/dist_js/plugins/services/settings-services.js b/assets/www/dist/dist_js/plugins/services/settings-services.js index 705738cd8bf7d82225a4081c9a14f0d85f5e7463..9cf31455d7d40291fc51678e5247be84faeef223 100644 --- a/assets/www/dist/dist_js/plugins/services/settings-services.js +++ b/assets/www/dist/dist_js/plugins/services/settings-services.js @@ -16,27 +16,37 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt var SETTINGS_SAVE_SPEC = { - includes: ['locale', 'showUDHistory', 'useRelative', 'useLocalStorage', 'expertMode', 'logoutIdle'], - excludes: ['timeout', 'cacheTimeMs', 'time', 'login', 'build'], + includes: ['locale', 'showUDHistory', 'useRelative', 'useLocalStorage', 'useLocalStorageEncryption', 'expertMode', 'logoutIdle', 'blockValidityWindow'], + excludes: ['timeout', 'cacheTimeMs', 'version', 'build', 'minVersion', 'fallbackLanguage'], plugins: { es: { - excludes: ['enable', 'host', 'port', 'wsPort', 'fallbackNodes'] + excludes: ['enable', 'host', 'port', 'fallbackNodes', 'enableGoogleApi', 'googleApiKey'], + notifications: { + } } }, + wallet: { + includes: ['alertIfUnusedWallet'], + excludes: ['notificationReadTime'] // deprecated - should be removed later + }, helptip: { excludes: ['installDocUrl'] + }, + notifications: { + excludes: ['time', 'warnCount', 'unreadCount'] } }, defaultSettings = angular.merge({ plugins: { es: { askEnable: false, + useRemoteStorage: true, notifications: { - readTime: true, txSent: true, txReceived: true, certSent: true, - certReceived: true + certReceived: true, + emitHtml5: false }, invitations: { readTime: true @@ -77,6 +87,13 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt !!csSettings.data.plugins.es.host; }; + that.notifications = {}; + that.notifications.isEmitHtml5Enable = function() { + return that.isEnable() && + csSettings.data.plugins.es.notifications && + angular.isDefined(csSettings.data.plugins.es.notifications.emitHtml5) ? csSettings.data.plugins.es.notifications.emitHtml5 : false; + }; + that.wot = {}; that.wot.isMixedSearchEnable = function() { return that.isEnable() && @@ -113,7 +130,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt // Load settings function loadSettings(pubkey, boxKeypair) { - var now = new Date().getTime(); + var now = Date.now(); return that.get({id: pubkey}) .catch(function(err){ if (err && err.ucode && err.ucode == 404) { @@ -130,7 +147,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt var record = res._source; // Do not apply if same version if (record.time === csSettings.data.time) { - console.debug('[ES] [settings] Loaded in '+ (new Date().getTime()-now) +'ms, but already up to date'); + console.debug('[ES] [settings] Loaded in '+ (Date.now()-now) +'ms, but already up to date'); return; } var nonce = CryptoUtils.util.decode_base58(record.nonce); @@ -139,7 +156,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt .then(function(json) { var settings = JSON.parse(json || '{}'); settings.time = record.time; - console.debug('[ES] [settings] Loaded and decrypted in '+ (new Date().getTime()-now) +'ms'); + console.debug('[ES] [settings] Loaded and decrypted in '+ (Date.now()-now) +'ms'); return settings; }) // if error: skip stored content @@ -236,8 +253,13 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt return $q.when(); } - var time = esHttp.date.now(); // always update time - console.debug('[ES] [settings] Saving user settings... at time ' + time); + // Skip remote saving, if remote storage disable + if (!csSettings.data.plugins.es.useRemoteStorage) { + return storeSettingsLocally(); + } + + var time = moment().utc().unix(); // always update time + console.debug('[ES] [settings] Saving user settings remotely...'); return $q.all([ csWallet.getKeypair(), // same result as esWallet.box.getKeypair(), because box keypair computed on auth @@ -266,7 +288,13 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt // create or update return angular.isUndefined(data.time) ? that.add(record) : - that.update(record, {id: record.issuer}); + that.update(record, {id: record.issuer}) + .catch(function(err) { + // Workaround if update failed: try to add() instead + // Can occur when changing the cesium+ pod + if (err && err.ucode == 404) return that.add(record); + throw err; + }); }) .then(function() { return true; @@ -277,7 +305,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt // Update settings version, then store (on local store only) data.time = time; previousRemoteData = filteredData; - console.debug('[ES] [settings] Saved user settings in ' + (esHttp.date.now() - time) + 'ms'); + console.debug('[ES] [settings] Saved user settings remotely in ' + (moment().utc().unix() - time) + 'ms'); return storeSettingsLocally(); }) .catch(function(err) { diff --git a/assets/www/dist/dist_js/plugins/services/social-services.js b/assets/www/dist/dist_js/plugins/services/social-services.js index b7336bdef833553e80bb12d42fbccb54dfdb7703..ece8393a7db0945deccec0bfeadc66238bebc075 100644 --- a/assets/www/dist/dist_js/plugins/services/social-services.js +++ b/assets/www/dist/dist_js/plugins/services/social-services.js @@ -1,6 +1,6 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) - .factory('SocialUtils', ['$filter', '$q', 'CryptoUtils', 'BMA', 'csWallet', 'esCrypto', function($filter, $q, CryptoUtils, BMA, csWallet, esCrypto) { + .factory('SocialUtils', ['$filter', '$q', 'CryptoUtils', 'BMA', 'csWallet', 'esCrypto', '$timeout', function($filter, $q, CryptoUtils, BMA, csWallet, esCrypto, $timeout) { 'ngInject'; function SocialUtils() { @@ -52,7 +52,7 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) urlToMatch = url.substring(0, slashPathIndex); } } - //console.log("match URI, try to match: " + urlToMatch); + //console.debug("match URI, try to match: " + urlToMatch); _.keys(regexp.socials).forEach(function(key){ if (regexp.socials[key].test(urlToMatch)) { type = key; diff --git a/assets/www/dist/dist_js/plugins/services/subscription-services.js b/assets/www/dist/dist_js/plugins/services/subscription-services.js index 7b790fe21f53106d554139f7265b7c04bd76cc54..baec576413673c4cb3bf0d7483d9de2b594cbe9e 100644 --- a/assets/www/dist/dist_js/plugins/services/subscription-services.js +++ b/assets/www/dist/dist_js/plugins/services/subscription-services.js @@ -81,12 +81,13 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es }); } - function addRecord(record) { + function addRecord(record, options) { if (!record || !record.type || !record.content || !record.recipient) { return $q.reject("Missing arguments 'record' or 'record.type' or 'record.content' or 'record.recipient'"); } - var issuer = csWallet.data.pubkey; + var wallet = options && options.wallet || (options && options.walletId && csWallet.children.get(options.walletId)) || csWallet; + var issuer = wallet.data.pubkey; var contentStr = JSON.stringify(record.content); @@ -95,8 +96,8 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es // Encrypt contents .then(function(nonce) { return $q.all([ - esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, csWallet.data.keypair, 'issuer', 'issuerContent', nonce), - esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, csWallet.data.keypair, 'recipient', 'recipientContent', nonce) + esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, wallet.data.keypair, 'issuer', 'issuerContent', nonce), + esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, wallet.data.keypair, 'recipient', 'recipientContent', nonce) ]); }) // Merge encrypted record @@ -105,7 +106,7 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es encryptedRecord.type = record.type; // Post subscription - return that.raw.add(encryptedRecord) + return that.raw.add(encryptedRecord, {wallet: wallet}) .then(function(id) { record.id = id; return record; @@ -114,12 +115,13 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es ; } - function updateRecord(record) { + function updateRecord(record, options) { if (!record || !record.content || !record.recipient) { return $q.reject("Missing arguments 'record' or 'record.content', or 'record.recipient'"); } - var issuer = csWallet.data.pubkey; + var wallet = options && options.wallet || (options && options.walletId && csWallet.children.get(options.walletId)) || csWallet; + var issuer = wallet.data.pubkey; var contentStr = JSON.stringify(record.content); // Get a unique nonce @@ -127,8 +129,8 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es // Encrypt contents .then(function(nonce) { return $q.all([ - esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, csWallet.data.keypair, 'issuer', 'issuerContent', nonce), - esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, csWallet.data.keypair, 'recipient', 'recipientContent', nonce) + esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, wallet.data.keypair, 'issuer', 'issuerContent', nonce), + esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, wallet.data.keypair, 'recipient', 'recipientContent', nonce) ]); }) // Merge encrypted record @@ -137,7 +139,7 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es encryptedRecord.type = record.type; // Post subscription - return that.raw.update(encryptedRecord, {id:record.id}) + return that.raw.update(encryptedRecord, {id:record.id, wallet: wallet}) .then(function() { return record; // return original record }); diff --git a/assets/www/dist/dist_js/plugins/services/tx-services.js b/assets/www/dist/dist_js/plugins/services/tx-services.js index 806273d393e668ca4cb0a5fbe97ab2408abaa0d3..0423f54a4456799667c756ae3a3005c1d89478e4 100644 --- a/assets/www/dist/dist_js/plugins/services/tx-services.js +++ b/assets/www/dist/dist_js/plugins/services/tx-services.js @@ -11,10 +11,11 @@ angular.module('cesium.es.tx.services', ['ngResource', 'cesium.services', 'cesiu }]) - .factory('esTx', ['$q', '$rootScope', 'csCurrency', 'csTx', 'esHttp', 'esWot', function($q, $rootScope, csCurrency, csTx, esHttp, esWot) { + .factory('esTx', ['$q', '$rootScope', 'csPlatform', 'csCurrency', 'csTx', 'esHttp', 'esWot', function($q, $rootScope, csPlatform, csCurrency, csTx, esHttp, esWot) { 'ngInject'; var + listeners, raw = { block: { search: esHttp.post('/:currency/block/_search') @@ -67,7 +68,8 @@ angular.module('cesium.es.tx.services', ['ngResource', 'cesium.services', 'cesiu { range: { medianTime: { - from: membership.joinTime, + // Fix #736: Add 1 second, because when membership begins in a block with DU, the DU is not received + from: membership.joinTime+1, to: membership.leaveTime } } @@ -114,8 +116,38 @@ angular.module('cesium.es.tx.services', ['ngResource', 'cesium.services', 'cesiu return deferred.promise; } - // Register extensions - csTx.api.data.on.loadUDs($rootScope, onLoadUDs, this); + function addListeners() { + // Extend API events + listeners = [ + csTx.api.data.on.loadUDs($rootScope, onLoadUDs, this) + ]; + } + + function removeListeners() { + _.forEach(listeners, function(remove){ + remove(); + }); + listeners = []; + } + + function refreshState() { + var enable = esHttp.alive; + if (!enable && listeners && listeners.length > 0) { + console.debug("[ES] [tx] Disable"); + removeListeners(); + } + else if (enable && (!listeners || listeners.length === 0)) { + console.debug("[ES] [tx] Enable"); + addListeners(); + } + } + + // Default action + csPlatform.ready().then(function() { + esHttp.api.node.on.start($rootScope, refreshState, this); + esHttp.api.node.on.stop($rootScope, refreshState, this); + return refreshState(); + }); // Exports return {}; diff --git a/assets/www/dist/dist_js/plugins/services/wallet-services.js b/assets/www/dist/dist_js/plugins/services/wallet-services.js index 427df5d168b7948366f0283ca7b67b62bda408b4..bb3c3edd3e582f3f4185b23fe8551afda8f15526 100644 --- a/assets/www/dist/dist_js/plugins/services/wallet-services.js +++ b/assets/www/dist/dist_js/plugins/services/wallet-services.js @@ -1,6 +1,6 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'cesium.es.http.services', 'cesium.es.crypto.services']) - .factory('esWallet', ['$q', '$rootScope', 'CryptoUtils', 'csPlatform', 'csWallet', 'esCrypto', 'esProfile', 'esHttp', function($q, $rootScope, CryptoUtils, csPlatform, csWallet, esCrypto, esProfile, esHttp) { + .factory('esWallet', ['$q', '$rootScope', '$timeout', 'CryptoUtils', 'csPlatform', 'csWallet', 'esCrypto', 'esProfile', 'esHttp', function($q, $rootScope, $timeout, CryptoUtils, csPlatform, csWallet, esCrypto, esProfile, esHttp) { 'ngInject'; var @@ -24,8 +24,8 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c // Generate box keypair esCrypto.box.getKeypair(data.keypair) .then(function(res) { - csWallet.data.keypair.boxSk = res.boxSk; - csWallet.data.keypair.boxPk = res.boxPk; + data.keypair.boxSk = res.boxSk; + data.keypair.boxPk = res.boxPk; console.debug("[ES] [wallet] Box keypair successfully computed"); deferred.resolve(); }); @@ -56,7 +56,7 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c } console.debug('[ES] [wallet] Loading user avatar+name...'); - var now = new Date().getTime(); + var now = Date.now(); esProfile.getAvatarAndName(data.pubkey) .then(function(profile) { @@ -64,7 +64,7 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c data.name = profile.name; data.avatarStyle = profile.avatarStyle; data.avatar = profile.avatar; - console.debug('[ES] [wallet] Loaded user avatar+name in '+ (new Date().getTime()-now) +'ms'); + console.debug('[ES] [wallet] Loaded user avatar+name in '+ (Date.now()-now) +'ms'); } else { console.debug('[ES] [wallet] No user avatar+name found'); @@ -84,13 +84,13 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c // Reset events csWallet.events.cleanByContext('esWallet'); - // If membership pending, but not enough certifications: suggest to fill user profile - if (!data.name && data.requirements.pendingMembership && data.requirements.needCertificationCount > 0) { + // If membership pending and not revocated, but not enough certifications: suggest to fill user profile + if (!data.name && !data.requirements.revoked && data.requirements.pendingMembership && data.requirements.needCertificationCount > 0) { csWallet.events.add({type:'info', message: 'ACCOUNT.EVENT.MEMBER_WITHOUT_PROFILE', context: 'esWallet'}); } console.debug('[ES] [wallet] Loading full user profile...'); - var now = new Date().getTime(); + var now = Date.now(); // Load full profile esProfile.get(data.pubkey) @@ -100,7 +100,7 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c data.avatar = profile.avatar; data.profile = profile.source; data.profile.description = profile.description; - console.debug('[ES] [wallet] Loaded full user profile in '+ (new Date().getTime()-now) +'ms'); + console.debug('[ES] [wallet] Loaded full user profile in '+ (Date.now()-now) +'ms'); } deferred.resolve(); }); @@ -108,23 +108,26 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c return deferred.promise; } - function getBoxKeypair() { - if (!csWallet.isAuth()) { + function getBoxKeypair(keypair) { + if (!keypair && !csWallet.isAuth()) { throw new Error('Unable to get box keypair: user not authenticated !'); } - return csWallet.getKeypair({silent: true}) + return (keypair ? $q.when(keypair) : csWallet.getKeypair({silent: true})) .then(function(keypair) { + // box keypair already computed: use it if (keypair && keypair.boxPk && keypair.boxSk) { - return $q.when(csWallet.data.keypair); + return $q.when(keypair); } - return esCrypto.box.getKeypair(keypair); - }) - .then(function(res) { - csWallet.data.keypair.boxSk = res.boxSk; - csWallet.data.keypair.boxPk = res.boxPk; - console.debug("[ES] [wallet] Box keypair successfully computed"); - return csWallet.data.keypair; + // Compute box keypair + return esCrypto.box.getKeypair(keypair) + .then(function(res) { + // Store in the wallet keypair + keypair.boxSk = res.boxSk; + keypair.boxPk = res.boxPk; + console.debug("[ES] [wallet] Box keypair successfully computed"); + return keypair; + }); }); } @@ -177,15 +180,15 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c getKeypair: getBoxKeypair, record: { pack: function(record, keypair, recipientFieldName, cypherFieldNames, nonce) { - return getBoxKeypair() - .then(function(keypair) { - return esCrypto.box.pack(record, keypair, recipientFieldName, cypherFieldNames, nonce); + return getBoxKeypair(keypair) + .then(function(fullKeypair) { + return esCrypto.box.pack(record, fullKeypair, recipientFieldName, cypherFieldNames, nonce); }); }, open: function(records, keypair, issuerFieldName, cypherFieldNames) { - return getBoxKeypair() - .then(function(keypair) { - return esCrypto.box.open(records, keypair, issuerFieldName, cypherFieldNames); + return getBoxKeypair(keypair) + .then(function(fullKeypair) { + return esCrypto.box.open(records, fullKeypair, issuerFieldName, cypherFieldNames); }); } } diff --git a/assets/www/dist/dist_js/plugins/services/wot-services.js b/assets/www/dist/dist_js/plugins/services/wot-services.js index 4a31b0e39b4a338a817648f580cbacdc7529a885..cc60416a87fe1f8fe89200a498a7cd4c082afd58 100644 --- a/assets/www/dist/dist_js/plugins/services/wot-services.js +++ b/assets/www/dist/dist_js/plugins/services/wot-services.js @@ -1,16 +1,23 @@ angular.module('cesium.es.wot.services', ['ngResource', 'cesium.es.http.services']) - .factory('esWot', ['$q', 'esHttp', function($q, esHttp) { + .factory('esWot', ['$rootScope', '$q', 'esHttp', 'csCache', function($rootScope, $q, esHttp, csCache) { 'ngInject'; var + cachePrefix = 'esWot-', + membershipsCache = csCache.get(cachePrefix + 'memberships-', csCache.constants.MEDIUM), raw = { user: { - event: esHttp.post('/user/event/_search?pretty') + event: esHttp.post('/user/event/_search') } }, - loadMemberships = function(pubkey) { + + loadMemberships = function(pubkey, options) { + options = options || {}; + + var result = (options.cache !== false) ? membershipsCache.get(pubkey) : null; + if (result) return $q.when(result); // Get user events on membership state var request = { @@ -62,10 +69,21 @@ angular.module('cesium.es.wot.services', ['ngResource', 'cesium.es.http.services }); } + // Put in the cache + membershipsCache.put(pubkey, result); + return result; }); + }, + + cleanCache = function() { + console.debug('[ES] [wot] Clean cache...'); + csCache.clear(cachePrefix); }; + // Listen if node changed + esHttp.api.node.on.stop($rootScope, cleanCache, this); + return { memberships: loadMemberships }; diff --git a/assets/www/dist/dist_js/plugins/templates.js b/assets/www/dist/dist_js/plugins/templates.js index da75a398d45a4ca22516eede56e7d488d7002743..f9771c21e2649cdc3242c888221b29e99506af48 100644 --- a/assets/www/dist/dist_js/plugins/templates.js +++ b/assets/www/dist/dist_js/plugins/templates.js @@ -1,141 +1,142 @@ -angular.module("cesium.plugins.templates", []).run(["$templateCache", function($templateCache) {$templateCache.put("plugins/es/templates/menu_extend.html","<div ng-if=\"enable && extensionPoint === \'menu-user\'\" class=\"visible-xs visible-sm\"><a menu-close=\"\" class=\"item item-icon-left\" active-link=\"active\" active-link-path-prefix=\"#/app/invitations\" ng-class=\"{\'item-menu-disable\': !login}\" ui-sref=\"app.view_invitations\"><i class=\"icon ion-person-stalker\"></i> <span translate=\"\">MENU.INVITATIONS</span> <span class=\"badge badge-positive\" ng-if=\"$root.walletData.invitations.unreadCount\">{{$root.walletData.invitations.unreadCount}}</span> </a><a menu-close=\"\" class=\"item item-icon-left\" active-link=\"active\" active-link-path-prefix=\"#/app/user/message\" ng-class=\"{\'item-menu-disable\': !login}\" ui-sref=\"app.user_message.tab_inbox\"><i class=\"icon ion-email\"></i> <span translate=\"\">MENU.MESSAGES</span> <span class=\"badge badge-positive\" ng-if=\"$root.walletData.messages.unreadCount\">{{$root.walletData.messages.unreadCount}}</span> </a><a menu-close=\"\" class=\"item item-icon-left\" active-link=\"active\" active-link-path-prefix=\"#/app/notifications\" ng-class=\"{\'item-menu-disable\': !login}\" ui-sref=\"app.view_notifications\"><i class=\"icon ion-android-notifications\"></i> <span translate=\"\">MENU.NOTIFICATIONS</span> <span class=\"badge badge-positive\" ng-if=\"$root.walletData.notifications.unreadCount\">{{$root.walletData.notifications.unreadCount}}</span></a></div>"); -$templateCache.put("plugins/rml9/templates/01-button.html","<!-- Button that call a function of the controller -->\n<button class=\"button button-balanced button-small-padding icon ion-android-archive\"\n ng-click=\"onButtonClick()\"\n title=\"{{\'RML9.BTN_OPEN\' | translate}}\">\n</button>\n\n<!-- Button: Open a view, using `ui-sref` attribute\n<button class=\"button button-balanced button-small-padding icon ion-plus-circled\"\n ui-sref=\"app.rml9({pubkey: formData.pubkey})\"\n title=\"{{\'RML9.BTN_OPEN\' | translate}}\">\n</button> -->\n\n"); -$templateCache.put("plugins/rml9/templates/02-view.html","<ion-view left-buttons=\"leftButtons\">\n <ion-nav-title>\n {{\'RML9.VIEW.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content>\n <div class=\"list\">\n\n <!-- the pubkey -->\n <div class=\"item\">\n {{\'COMMON.PUBKEY\'|translate}}\n <div class=\"badge\">{{pubkey|formatPubkey}}</div>\n </div>\n\n <!-- a text divider-->\n <div class=\"item item-divider\">{{\'RML9.VIEW.DIVIDER\'|translate:{pubkey: pubkey} }}</div>\n\n <!-- iterate on each TX -->\n <div class=\"item\" ng-repeat=\"item in items\">\n <h3>{{item.time|formatDate}}</h3>\n <h4>{{item.pubkey|formatPubkey}}</h4>\n <div class=\"badge\">{{item.amount|formatAmount}}</div>\n </div>\n </div>\n </ion-content>\n</ion-view>\n"); -$templateCache.put("plugins/rml9/templates/03-button.html","<!-- Button: Open a view, using `ui-sref` attribute -->\n<button class=\"button button-balanced button-small-padding icon ion-android-archive\"\n ui-sref=\"app.rml9({pubkey: formData.pubkey})\"\n title=\"{{\'RML9.BTN_SWOW_TX\' | translate}}\">\n</button>\n\n"); -$templateCache.put("plugins/rml9/templates/03-view_with_button.html","<ion-view left-buttons=\"leftButtons\">\n <ion-nav-title>\n {{\'RML9.VIEW.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content>\n <div class=\"list\">\n\n <!-- buttons bar -->\n <div class=\"center padding\">\n <div class=\"buttons\">\n <button class=\"button button-balanced icon-left icon ion-archive\"\n ng-click=\"onExportButtonClick()\">{{\'RML9.BTN_EXPORT\' | translate}}\n </button>\n </div>\n </div>\n\n <!-- the pubkey -->\n <div class=\"item\">\n {{\'COMMON.PUBKEY\'|translate}}\n <div class=\"badge\">{{pubkey|formatPubkey}}</div>\n </div>\n\n <!-- the balance -->\n <div class=\"item\">\n {{\'RML9.VIEW.BALANCE\'|translate}}\n <div class=\"badge badge-calm\">\n {{balance|formatAmount}} <span ng-bind-html=\"$root.currency.name|currencySymbol\"></span>\n </div>\n </div>\n\n <!-- a text divider-->\n <div class=\"item item-divider\">{{\'RML9.VIEW.DIVIDER\'|translate:{pubkey: pubkey} }}</div>\n\n <!-- iterate on each TX -->\n <div class=\"item item-text-wrap\" ng-repeat=\"item in items\">\n\n <h3>\n {{item.time|formatDate}}\n <span ng-if=\"item.comment\" class=\"gray\"> | {{item.comment}}</span>\n </h3>\n\n <h4 ng-if=\"item.uid\" class=\"positive\"><i class=\"icon ion-person\"></i> {{item.name||item.uid}}</h4>\n <h4 ng-if=\"!item.uid\" class=\"gray\"><i class=\"icon ion-key\"></i> {{item.pubkey|formatPubkey}}</h4>\n\n <div class=\"badge\"\n ng-class=\"{\'badge-balanced\': item.amount > 0}\">\n {{item.amount|formatAmount}} <span ng-bind-html=\"$root.currency.name|currencySymbol\"></span>\n </div>\n </div>\n </div>\n </ion-content>\n</ion-view>\n"); -$templateCache.put("plugins/rml9/templates/04-view_chart.html","<ion-view left-buttons=\"leftButtons\">\n <ion-nav-title>\n {{\'RML9.VIEW.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content>\n <div class=\"list\">\n\n <!-- buttons bar -->\n <div class=\"center padding\">\n <div class=\"buttons\">\n <button class=\"button button-balanced icon-left icon ion-archive\"\n ng-click=\"onExportButtonClick()\">{{\'RML9.BTN_EXPORT\' | translate}}\n </button>\n </div>\n </div>\n\n <!-- the pubkey -->\n <div class=\"item\">\n {{\'COMMON.PUBKEY\'|translate}}\n <div class=\"badge\">{{pubkey|formatPubkey}}</div>\n </div>\n\n <!-- the balance -->\n <div class=\"item\">\n {{\'RML9.VIEW.BALANCE\'|translate}}\n <div class=\"badge badge-calm\">\n {{balance|formatAmount}} <span ng-bind-html=\"$root.currency.name|currencySymbol\"></span>\n </div>\n </div>\n\n <!-- a text divider-->\n <div class=\"item item-divider\">{{\'RML9.VIEW.DIVIDER\'|translate:{pubkey: pubkey} }}</div>\n\n\n <div class=\"row\">\n <div class=\"col col-75\">\n <!-- iterate on each TX -->\n <div class=\"item item-text-wrap\" ng-repeat=\"item in items\">\n\n <h3>\n {{item.time|formatDate}}\n <span ng-if=\"item.comment\" class=\"gray\"> | {{item.comment}}</span>\n </h3>\n\n <h4 ng-if=\"item.uid\" class=\"positive\"><i class=\"icon ion-person\"></i> {{item.name||item.uid}}</h4>\n <h4 ng-if=\"!item.uid\" class=\"gray\"><i class=\"icon ion-key\"></i> {{item.pubkey|formatPubkey}}</h4>\n\n <div class=\"badge\"\n ng-class=\"{\'badge-balanced\': item.amount > 0}\">\n {{item.amount|formatAmount}} <span ng-bind-html=\"$root.currency.name|currencySymbol\"></span>\n </div>\n </div>\n </div>\n\n <div class=\"col col-25\">\n\n <!-- [NEW] TX input chart -->\n <p class=\"gray\" translate>RML9.CHART.INPUT_CHART_TITLE</p>\n <canvas id=\"chart-received-pie\" class=\"chart-pie\"\n chart-data=\"inputChart.data\"\n chart-labels=\"inputChart.labels\"\n chart-colors=\"inputChart.colors\">\n </canvas>\n\n <!-- [NEW] TX input chart -->\n <p class=\"gray\" translate>RML9.CHART.OUTPUT_CHART_TITLE</p>\n <canvas id=\"chart-sent-pie\" class=\"chart-pie\"\n chart-data=\"outputChart.data\"\n chart-labels=\"outputChart.labels\"\n chart-colors=\"outputChart.colors\">\n </canvas>\n </div>\n </div>\n </div>\n </ion-content>\n</ion-view>\n"); -$templateCache.put("plugins/rml9/templates/06-button.html","<!-- [NEW] Display only if plugin is enable -->\n\n <!-- Button: call a method from the state controller -->\n <button ng-if=\"enable\" class=\"button button-balanced button-small-padding icon ion-android-archive\"\n ng-click=\"onButtonClick()\"\n title=\"{{\'RML9.BTN_SWOW_TX\' | translate}}\">\n </button>\n\n\n"); -$templateCache.put("plugins/rml9/templates/06-settings_item.html","\n<div class=\"item item-toggle dark\">\n <div class=\"input-label\" translate>RML9.SETTINGS.ENABLE_TOGGLE</div>\n <label class=\"toggle toggle-royal\">\n <input type=\"checkbox\" ng-model=\"formData.plugins.rml9.enable\" >\n <div class=\"track\">\n <div class=\"handle\"></div>\n </div>\n </label>\n</div>\n"); -$templateCache.put("plugins/rml9/templates/07-button.html","<!-- Button: Open a view, using `ui-sref` attribute -->\n<button class=\"button button-balanced button-small-padding icon ion-android-archive\"\n ui-sref=\"app.rml9({pubkey: formData.pubkey})\"\n title=\"{{\'RML9.BTN_SWOW_TX\' | translate}}\">\n</button>\n\n"); -$templateCache.put("plugins/rml9/templates/07-view.html","<leaflet id=\"map-geojson\" center=\"map.center\" geojson=\"map.geojson\"></leaflet>\n"); -$templateCache.put("plugins/rml9/templates/final-button.html","<!-- Button: Open a view, using `ui-sref` attribute -->\n<button ng-if class=\"button button-balanced button-small-padding icon ion-android-archive\"\n ui-sref=\"app.rml9({pubkey: formData.pubkey})\"\n title=\"{{\'RML9.BTN_SWOW_TX\' | translate}}\">\n</button>\n\n"); -$templateCache.put("plugins/rml9/templates/final-view.html","<ion-view left-buttons=\"leftButtons\">\n <ion-nav-title>\n {{\'RML9.VIEW.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content>\n <div class=\"list\">\n\n <!-- buttons bar -->\n <div class=\"center padding\">\n <div class=\"buttons\">\n <button class=\"button button-balanced icon-left icon ion-archive\"\n ng-click=\"onExportButtonClick()\">{{\'RML9.BTN_EXPORT\' | translate}}\n </button>\n </div>\n </div>\n\n <!-- the pubkey -->\n <div class=\"item\">\n {{\'COMMON.PUBKEY\'|translate}}\n <div class=\"badge\">{{pubkey|formatPubkey}}</div>\n </div>\n\n <!-- the balance -->\n <div class=\"item\">\n {{\'RML9.VIEW.BALANCE\'|translate}}\n <div class=\"badge badge-calm\">\n {{balance|formatAmount}} <span ng-bind-html=\"$root.currency.name|currencySymbol\"></span>\n </div>\n </div>\n\n <!-- a text divider-->\n <div class=\"item item-divider\">{{\'RML9.VIEW.DIVIDER\'|translate:{pubkey: pubkey} }}</div>\n\n <!-- iterate on each TX -->\n <div class=\"row\">\n <div class=\"col col-75\">\n <div class=\"item item-text-wrap\" ng-repeat=\"item in items\">\n\n <h3>\n {{item.time|formatDate}}\n <span ng-if=\"item.comment\" class=\"gray\"> | {{item.comment}}</span>\n </h3>\n\n <h4 ng-if=\"item.uid\" class=\"positive\"><i class=\"icon ion-person\"></i> {{item.name||item.uid}}</h4>\n <h4 ng-if=\"!item.uid\" class=\"gray\"><i class=\"icon ion-key\"></i> {{item.pubkey|formatPubkey}}</h4>\n\n <div class=\"badge\"\n ng-class=\"{\'badge-balanced\': item.amount > 0}\">\n {{item.amount|formatAmount}} <span ng-bind-html=\"$root.currency.name|currencySymbol\"></span>\n </div>\n </div>\n\n </div>\n\n <div class=\"col col-25\">\n\n <!-- [NEW] TX input chart -->\n <p class=\"gray\" translate>RML9.CHART.INPUT_CHART_TITLE</p>\n <canvas id=\"chart-received-pie\" class=\"chart-pie\"\n chart-data=\"inputChart.data\"\n chart-labels=\"inputChart.labels\">\n </canvas>\n\n <!-- [NEW] TX input chart -->\n <p class=\"gray\" translate>RML9.CHART.OUTPUT_CHART_TITLE</p>\n <canvas id=\"chart-sent-pie\" class=\"chart-pie\"\n chart-data=\"outputChart.data\"\n chart-labels=\"outputChart.labels\">\n </canvas>\n </div>\n </div>\n </div>\n </ion-content>\n</ion-view>\n"); -$templateCache.put("plugins/es/templates/blockchain/items_blocks.html","<div class=\"padding gray\" ng-if=\":rebind:!search.loading && !search.results.length\" translate=\"\">COMMON.SEARCH_NO_RESULT</div><ng-if ng-if=\":rebind:!smallscreen\"><ng-repeat ng-repeat=\"block in :rebind:search.results track by block.number\" ng-include=\"!block.empty ? \'templates/blockchain/item_block_lg.html\' : \'templates/blockchain/item_block_empty_lg.html\'\"></ng-repeat></ng-if><ng-if ng-if=\":rebind:smallscreen\"><ng-repeat ng-repeat=\"block in :rebind:search.results track by block.number\" ng-include=\"\'templates/blockchain/item_block.html\'\"></ng-repeat></ng-if>"); -$templateCache.put("plugins/es/templates/blockchain/lookup.html","<ion-view><ion-nav-title><span translate>BLOCKCHAIN.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-navicon visible-xs visible-sm\" ng-click=\"toggleCompactMode()\"><b class=\"icon-secondary\" ng-class=\"{\'ion-arrow-down-b\': !compactMode, \'ion-arrow-up-b\': compactMode}\" style=\"top: -12px; left: 11px; font-size: 10px\"></b> <b class=\"icon-secondary\" ng-class=\"{\'ion-arrow-up-b\': !compactMode,\'ion-arrow-down-b\': compactMode}\" style=\"top: 12px; left: 11px; font-size: 10px\"></b></button> <button class=\"button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"></button></ion-nav-buttons><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><ng-include src=\"\'plugins/es/templates/blockchain/lookup_form.html\'\"></ng-include></ion-content></ion-view>"); -$templateCache.put("plugins/es/templates/blockchain/lookup_form.html","<div class=\"lookupForm\"><div class=\"item no-padding\"><div class=\"button button-small button-text button-stable button-icon-event padding no-padding-right ink\" ng-repeat=\"filter in search.filters\" ng-if=\"filter\"><span ng-bind-html=\"\'BLOCKCHAIN.LOOKUP.TX_SEARCH_FILTER.\'+filter.type|translate:filter\"></span> <i class=\"icon ion-close\" ng-click=\"itemRemove($index)\"></i></div><label class=\"item-input\"><i class=\"icon ion-search placeholder-icon\"></i> <input type=\"text\" class=\"visible-xs visible-sm\" placeholder=\"{{\'BLOCKCHAIN.LOOKUP.SEARCH_HELP\'|translate}}\" ng-model=\"search.text\" ng-model-options=\"{ debounce: 650 }\" ng-change=\"doSearchText()\"><div class=\"helptip-anchor-center\"><a id=\"helptip-blockchain-search-text\"></a></div></label></div><div class=\"padding-top padding-xs\" style=\"display: block; height: 60px\"><div class=\"pull-left\"><h4 ng-if=\"search.type==\'last\'\" translate=\"\">BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4><h4 ng-if=\"search.type==\'text\'\">{{\'COMMON.RESULTS_LIST\'|translate}}</h4><h5 class=\"dark\" ng-if=\"!search.loading && search.total\"><span translate=\"COMMON.RESULTS_COUNT\" translate-values=\"{count: search.total}\"></span> <small class=\"gray\" ng-if=\":rebind:search.took && expertMode\">- {{:rebind:\'COMMON.EXECUTION_TIME\'|translate: {duration: search.took} }} </small><small class=\"gray\" ng-if=\":rebind:expertMode && search.filters && search.filters.length\">- <a ng-click=\"toggleShowQuery()\" ng-if=\"!showQuery\">Voir la requête <i class=\"icon ion-arrow-down-b gray\"></i> </a><a ng-click=\"toggleShowQuery()\" ng-if=\"showQuery\">Masquer la requête <i class=\"icon ion-arrow-up-b gray\"></i></a></small></h5><h5 class=\"gray\" ng-if=\"search.loading\"><ion-spinner class=\"icon ion-spinner-small\" icon=\"android\"></ion-spinner><span translate=\"\">COMMON.SEARCHING</span><br></h5></div></div><div class=\"item no-border no-padding\" ng-if=\":rebind:search.filters && search.filters.length && expertMode\"><small class=\"no-padding no-margin\" ng-if=\"showQuery\"><span class=\"gray text-wrap dark\">{{:rebind:search.query}}</span></small></div><ion-list class=\"list list-blocks\" ng-class=\"::motion.ionListClass\"><ng-include src=\"\'plugins/es/templates/blockchain/items_blocks.html\'\"></ng-include></ion-list><ion-infinite-scroll ng-if=\"search.hasMore\" spinner=\"android\" on-infinite=\"showMore()\" distance=\"1%\"></ion-infinite-scroll></div>"); -$templateCache.put("plugins/es/templates/blockchain/lookup_popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>BLOCKCHAIN.LOOKUP.POPOVER_FILTER_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a ng-if=\"enableFilter\" class=\"item item-icon-left item-icon-right ink\" ng-click=\"doSearchLast()\"><i class=\"icon ion-clock\"></i> {{\'BLOCKCHAIN.LOOKUP.BTN_LAST\' | translate}} <i class=\"icon ion-ios-checkmark-empty\" ng-show=\"search.type==\'last\'\"></i></a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/common/edit_pictures.html","<div class=\"gallery\" ng-controller=\"ESPicturesEditCtrl as ctrl\"><div ng-repeat=\"picture in pictures\" class=\"item card card-gallery stable-bg\" ng-class=\"{\'in done\': picture.isnew}\"><div><h2 ng-if=\"picture.title\">{{picture.title}}</h2><img ng-src=\"{{picture.src}}\"></div><div class=\"item done in tabs tabs-secondary tabs-icon-left\"><a class=\"tab-item stable-bg assertive\" ng-click=\"removePicture($index)\" title=\"{{\'COMMON.BTN_PICTURE_DELETE\' | translate}}\"><i class=\"icon ion-trash-a\"></i>{{\'COMMON.BTN_PICTURE_DELETE\'|translate}}</a> <a class=\"tab-item stable-bg dark\" ng-click=\"rotatePicture($index)\" title=\"{{\'COMMON.BTN_PICTURE_ROTATE\' | translate}}\"><i class=\"icon ion-forward\"></i>{{\'COMMON.BTN_PICTURE_ROTATE\'|translate}}</a> <a class=\"tab-item stable-bg\" ng-click=\"favoritePicture($index)\" ng-class=\"{\'gray\': $index !== 0, \'positive\': $index === 0}\" title=\"{{\'COMMON.BTN_PICTURE_FAVORISE\' | translate}}\"><i class=\"icon ion-star\"></i>{{\'COMMON.BTN_PICTURE_FAVORISE\'|translate}}</a></div></div><div class=\"item card card-gallery card-gallery-new text-center padding ink\" ng-click=\"selectNewPicture(\'#pictureFile\')\"><i class=\"ion-image stable\" style=\"font-size:150px\"></i> <b class=\"ion-plus gray\" style=\"font-size:80px; position:absolute; top:25px; right: 5px\"></b><p translate>COMMON.BTN_ADD_PICTURE</p></div><input type=\"file\" id=\"pictureFile\" accept=\"image/*\" onchange=\"angular.element(this).scope().fileChanged(event)\" style=\"visibility:hidden; position:absolute\"></div>"); -$templateCache.put("plugins/es/templates/common/edit_position.html","<div class=\"item item-divider\" translate>LOCATION.LOCATION_DIVIDER</div><ion-item class=\"item-input item-floating-label item-button-right\"><span class=\"input-label\">{{\'LOCATION.ADDRESS\' | translate}}</span><textarea placeholder=\"{{\'LOCATION.ADDRESS_HELP\' | translate}}\" ng-model=\"formData.address\" ng-model-options=\"{ debounce: 350 }\" rows=\"4\" cols=\"10\">\n </textarea></ion-item><div class=\"item item-input item-floating-label\" ng-class=\"{\'item-input-error\': form.$submitted && form.geoPoint.$invalid}\"><span class=\"input-label\" translate>LOCATION.CITY</span> <input type=\"text\" placeholder=\"{{\'LOCATION.CITY_HELP\'|translate}}\" ng-model=\"formData.city\" ng-model-options=\"{ updateOn: \'blur\' }\" ng-change=\"onCityChanged()\"></div><input type=\"hidden\" name=\"geoPoint\" ng-model=\"formData.geoPoint\" required-if=\"formPosition.enable\" geo-point><div class=\"form-errors\" ng-show=\"form.$submitted && form.geoPoint.$error\" ng-messages=\"form.geoPoint.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"LOCATION.ERROR.REQUIRED_FOR_LOCATION\" ng-if=\"!formData.city\"></span> <span translate=\"LOCATION.ERROR.INVALID_FOR_LOCATION\" ng-if=\"formData.city\"></span></div><div class=\"form-error\" ng-message=\"geoPoint\"><span translate=\"LOCATION.ERROR.REQUIRED_FOR_LOCATION\" ng-if=\"!formData.city\"></span> <span translate=\"LOCATION.ERROR.INVALID_FOR_LOCATION\" ng-if=\"formData.city\"></span></div></div><div class=\"item row item-text-wrap no-padding\"><div class=\"col no-padding\"><ion-checkbox ng-model=\"formPosition.enable\" ng-change=\"onUseGeopointChanged()\" class=\"item item-border-large done in\"><div class=\"item-content\"><span translate>LOCATION.USE_GEO_POINT</span><h4 class=\"gray\" ng-if=\"formPosition.loading\"><ion-spinner class=\"icon ion-spinner-small\" icon=\"android\"></ion-spinner>{{\'LOCATION.LOADING_LOCATION\'|translate}}</h4></div></ion-checkbox></div><div class=\"col col-10 no-padding\" style=\"min-width: 60px\"><div class=\"row text-center\"><a class=\"button button-stable button-small-padding\" title=\"{{\'LOCATION.BTN_GEOLOC_ADDRESS\'|translate}}\" ng-disabled=\"!formPosition.enable\" ng-click=\"openSearchLocationModal()\"><i class=\"icon ion-home\" style=\"left: 15px\"></i> <b class=\"icon-secondary ion-search\" style=\"top: -9px; left:32px; font-size: 18px\"></b></a></div></div></div><cs-extension-point name=\"after-position\"></cs-extension-point>"); -$templateCache.put("plugins/es/templates/common/edit_socials.html","<ion-list class=\"no-padding\"><div class=\"item item-divider\"><span>{{\'PROFILE.SOCIAL_NETWORKS_DIVIDER\' | translate}} </span><a class=\"badge button button-text button-small button-small-padding\" ng-class=\"{\'button-text-positive\': socialData.reorder}\" ng-if=\"formData.socials && formData.socials.length > 1\" ng-click=\"socialData.reorder=!socialData.reorder\"><span translate=\"\">PROFILE.BTN_REORDER</span></a></div></ion-list><ion-list show-reorder=\"socialData.reorder\"><ion-item class=\"item-remove-animate item-icon-left\" type=\"no-padding item-text-wrap\" ng-if=\"formData.socials && formData.socials.length\" ng-repeat=\"social in formData.socials | filter:filterFn track by social.url\" id=\"social-{{social.url|formatSlug}}\"><i class=\"icon ion-social-{{social.type}}\" ng-class=\"{\'ion-bookmark\': social.type == \'other\', \'ion-link\': social.type == \'web\', \'ion-email\': social.type == \'email\', \'ion-iphone\': social.type == \'phone\'}\"></i><p ng-if=\"social.type && social.type != \'web\'\">{{social.type}} <i class=\"ion-locked\" ng-if=\"social.recipient\"></i></p><h2><a href=\"{{social.url}}\" ng-if=\"social.type != \'email\' && social.type != \'phone\'\" target=\"_blank\">{{social.url}}</a> <a href=\"mailto:{{social.url}}\" ng-if=\"social.type == \'email\'\">{{social.url}}</a> <a href=\"tel:{{social.url}}\" ng-if=\"social.type == \'phone\'\">{{social.url}}</a></h2><ion-option-button class=\"button-assertive\" ng-if=\"!social.recipient\" ng-click=\"formData.socials.splice($index, 1); dirty = true;\">{{\'COMMON.BTN_DELETE\'|translate}}</ion-option-button><ion-option-button class=\"button-info\" ng-if=\"!social.recipient\" ng-click=\"editSocialNetwork($index)\">{{\'COMMON.BTN_EDIT\'|translate}}</ion-option-button><ion-reorder-button class=\"ion-drag\" on-reorder=\"reorderSocialNetwork(social, $fromIndex, $toIndex)\"></ion-reorder-button></ion-item></ion-list><ion-list class=\"no-padding\"><div class=\"item item-complex item-input-inset\"><label class=\"item-input-wrapper\"><input type=\"text\" style=\"width:100%\" placeholder=\"{{\'PROFILE.SOCIAL_HELP\'|translate}}\" id=\"socialUrl\" on-return=\"addSocialNetwork($event);\" ng-model=\"socialData.url\"></label><button class=\"button button-small hidden-xs\" type=\"button\" ng-click=\"addSocialNetwork($event)\">{{\'COMMON.BTN_ADD\'|translate}}</button> <button class=\"button button-small button-icon icon ion-android-add visible-xs\" type=\"button\" ng-click=\"addSocialNetwork($event)\"></button></div></ion-list>"); -$templateCache.put("plugins/es/templates/common/item_comment.html","<ng-init ng-init=\"level = level + 1\"><a name=\"{{::comment.id|formatHash}}\"></a><ion-item id=\"comment-{{::comment.id|formatHash}}\" class=\"card card-comment card-avatar stable-900-bg item-text-wrap no-padding\" ng-class=\"::{\'in done\': comment.isnew}\"><div class=\"card-header padding-left\" ng-if=\"comment.parent && !hideParent\"><h5 class=\"gray underline\"><ng-if ng-if=\"!comment.parent.issuer\">{{\'COMMENTS.REPLY_TO_DELETED_COMMENT\'|translate}}</ng-if><ng-if ng-if=\"comment.parent.issuer\"><a ng-click=\"toggleExpandedParent(comment, $index)\">{{\'COMMENTS.REPLY_TO_LINK\'|translate}}<ng-if ng-if=\"::comment.parent.uid\">{{::comment.parent.name||comment.parent.uid}}</ng-if><ng-if ng-if=\"::!comment.parent.uid\"><i class=\"ion-key\"></i> {{::comment.parent.name|| (comment.parent.issuer|formatPubkey) }}</ng-if></a><i ng-class=\"{\'ion-arrow-down-b\': !comment.expandedParent[$index], \'ion-arrow-up-b\': comment.expandedParent[$index]}\"></i></ng-if></h5><div class=\"padding-left\" ng-if=\"comment.expandedParent[$index]\"><div class=\"card card-avatar card-avatar-small stable-bg item-text-wrap no-padding in done\"><ng-include ng-init=\"comment = comment.parent\" src=\"\'plugins/es/templates/common/item_comment_content.html\'\"></ng-include></div></div></div><ng-include src=\"\'plugins/es/templates/common/item_comment_content.html\'\"></ng-include><div class=\"card-footer gray\"><small class=\"underline\"><a ng-click=\"share($event, comment, $index)\">{{comment.creationTime | formatFromNow}}</a><ng-if ng-if=\"comment.replyCount\">| <a class=\"dark\" ng-click=\"toggleExpandedReplies(comment, $index)\">{{\'COMMENTS.REPLY_COUNT\'|translate:comment}}</a> <i ng-class=\"{\'ion-arrow-down-b\': !comment.showReplies, \'ion-arrow-up-b\': comment.showReplies}\"></i></ng-if></small><div class=\"pull-right\"><a class=\"ion-android-share-alt\" ng-click=\"share($event, comment)\"></a> <a class=\"ion-edit\" ng-if=\"isUserPubkey(comment.issuer)\" ng-click=\"edit(comment)\"></a> <a class=\"ion-trash-a\" ng-if=\"isUserPubkey(comment.issuer)\" ng-click=\"remove(comment, $index)\"></a> <a class=\"ion-reply\" ng-click=\"reply(comment)\">{{::\'COMMENTS.REPLY\'|translate}}</a></div></div></ion-item><div ng-if=\"comment.expandedReplies[$index]\" class=\"padding-left card-avatar-small expanded\" ng-init=\"hideParent=true\"><ng-include ng-repeat=\"comment in comment.replies track by comment.id\" src=\"\'plugins/es/templates/common/item_comment.html\'\"></ng-include></div></ng-init>"); -$templateCache.put("plugins/es/templates/common/item_comment_content.html","<div class=\"item item-avatar done in\"><span class=\"avatar\" ng-if=\"::!comment.avatar\" ng-class=\"::{\'avatar-member\': comment.uid, \'avatar-wallet\': !comment.uid}\"></span> <span class=\"avatar\" ng-if=\"::comment.avatar\" style=\"background-image: url({{::comment.avatar.src}})\"></span> <a class=\"pull-left\" ui-sref=\"app.wot_identity({pubkey:comment.issuer, uid: comment.uid})\"><span class=\"positive\" ng-if=\"::comment.uid\">{{::comment.name||comment.uid}} </span><span ng-if=\"::!comment.uid\" class=\"gray\"><i class=\"icon ion-key gray\"></i> {{::comment.name || (comment.issuer|formatPubkey)}} </span></a> <span trust-as-html=\"comment.html\"></span></div>"); -$templateCache.put("plugins/es/templates/common/item_location_search.html","<div class=\"item no-padding\"><div class=\"item-input\"><i class=\"icon ion-location placeholder-icon\"></i> <input type=\"text\" placeholder=\"{{(options.location.help||\'LOCATION.SEARCH_HELP\')|translate}}\" ng-model-options=\"{ debounce: 350 }\" ng-model=\"search.location\" ng-keydown=\"onKeydown($event)\" ng-change=\"onLocationChanged()\" ng-blur=\"hideDropdown()\"></div></div><ul class=\"item no-padding list dropdown-list\" ng-if=\"locations\" scroll=\"true\"><div ng-if=\"!locations.length\" class=\"item padding assertive\"><span translate>COMMON.SEARCH_NO_RESULT</span></div><a ng-repeat=\"res in locations\" class=\"item item-border-large item-text-wrap ink done in {{res.selected && \'active\' || \'\'}}\" ng-class=\"::{\'item-divider\': !res.address, \'item-icon-left\': res.address}\" ng-click=\"::res.address ? selectLocation(res) : false\"><h4 class=\"text-italic\" ng-if=\"::!res.address\" ng-bind-html=\"res.name\"></h4><ng-if ng-if=\"::res.address\"><i class=\"icon ion-location\"></i><h3 ng-if=\"res.address.road\">{{::res.address.road}}</h3><h3><span ng-if=\"res.address.postcode\">{{::res.address.postcode}}</span> {{::res.address.city||res.address.village}} <span class=\"gray\">| {{::res.address.country}}</span></h3><h5 class=\"gray\">{{\'LOCATION.MODAL.POSITION\'|translate:res }}</h5></ng-if></a></ul>"); -$templateCache.put("plugins/es/templates/common/modal_category.html","<ion-modal-view><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title\">{{ (ctrl.title || \'COMMON.CATEGORIES\') | translate}}</h1></ion-header-bar><ion-content class=\"categoryModal\"><div class=\"center padding\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></div><div class=\"list\"><label class=\"item item-input\"><i class=\"icon ion-search placeholder-icon\"></i> <input type=\"text\" placeholder=\"{{\'COMMON.CATEGORY_SEARCH_HELP\'|translate}}\" ng-model=\"ctrl.searchText\" ng-model-options=\"{ debounce: 350 }\" ng-change=\"ctrl.doSearch()\"></label><div ng-repeat=\"cat in categories\" class=\"item item-category item-text-wrap\" ng-class=\"{\'item-divider\': !cat.parent}\" ng-click=\"cat.parent ? closeModal(cat) : false\"><h2 ng-bind-html=\"cat.name\"></h2></div></div></ion-content></ion-modal-view>"); -$templateCache.put("plugins/es/templates/common/modal_edit_avatar.html","<ion-modal-view><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear visible-xs visible-sm\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title\" translate>PROFILE.MODAL_AVATAR.TITLE</h1><button class=\"button button-clear icon-right visible-xs\" ng-click=\"doCrop()\" ng-disabled=\"formData.imageCropStep == 1\" ng-if=\"formData.imageCropStep <= 2\"><span translate>COMMON.BTN_NEXT</span> <i class=\"icon ion-ios-arrow-right\"></i></button> <button class=\"button button-clear icon-right visible-xs\" ng-click=\"closeModal(formData.result)\" ng-if=\"formData.imageCropStep == 3\"><i class=\"icon ion-android-done\"></i></button></ion-header-bar><ion-content class=\"modal-avatar padding\"><div ng-show=\"formData.imageCropStep == 1\"><p translate>PROFILE.MODAL_AVATAR.SELECT_FILE_HELP</p><div class=\"item card text-center padding ink\" ng-click=\"openFileSelector()\"><i class=\"ion-image stable\" style=\"font-size:150px\"></i> <b class=\"ion-plus gray\" style=\"position:relative; font-size:80px; top:-51px; right: 19px\"></b><p translate>PROFILE.MODAL_AVATAR.BTN_SELECT_FILE</p></div><input type=\"file\" name=\"fileInput\" accept=\"image/*\" id=\"fileInput\" onchange=\"angular.element(this).scope().fileChanged(event)\" style=\"visibility:hidden; position:absolute\"></div><div ng-show=\"formData.imageCropStep == 2\"><p translate>PROFILE.MODAL_AVATAR.RESIZE_HELP</p><div class=\"item card text-center padding ink\"><image-crop data-height=\"100\" data-width=\"100\" data-shape=\"circle\" data-step=\"formData.imageCropStep\" src=\"formData.imgSrc\" data-result=\"formData.result\" data-result-blob=\"formData.resultBlob\" crop=\"formData.initCrop\" padding=\"150\" max-size=\"1024\"></image-crop></div></div><div ng-show=\"formData.imageCropStep == 3\"><p translate>PROFILE.MODAL_AVATAR.RESULT_HELP</p><div class=\"item card padding hero\" style=\"height: 110px\"><div class=\"content\"><img class=\"avatar\" ng-src=\"{{formData.result}}\" style=\"height: 88px; width: 88px\"></div></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"closeModal()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-calm icon-right ion-chevron-right ink\" ng-click=\"doCrop()\" translate ng-disabled=\"formData.imageCropStep == 1\" ng-if=\"formData.imageCropStep <= 2\">COMMON.BTN_NEXT</button> <button class=\"button button-positive ink\" ng-click=\"closeModal(formData.result)\" translate ng-if=\"formData.imageCropStep == 3\">COMMON.BTN_CONTINUE</button></div></ion-content></ion-modal-view>"); -$templateCache.put("plugins/es/templates/common/modal_location.html","<ion-modal-view class=\"modal-full-height modal-search-location\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear\" ng-click=\"closeModal()\" translate=\"\">COMMON.BTN_CANCEL</button><h1 class=\"title\" translate=\"\">LOCATION.MODAL.TITLE</h1></ion-header-bar><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><div class=\"item item-input\"><i class=\"icon ion-search placeholder-icon\"></i> <input type=\"text\" class=\"visible-xs visible-sm\" placeholder=\"{{\'LOCATION.MODAL.SEARCH_HELP\'|translate}}\" ng-model=\"search.text\" ng-model-options=\"{ debounce: 650 }\" ng-change=\"doSearch()\"></div><div class=\"padding-top padding-xs\" style=\"display: block; height: 60px\"><div class=\"pull-left\" ng-if=\"!search.loading && search.results\"><h4 translate=\"\">COMMON.RESULTS_LIST</h4></div></div><div class=\"center padding\" ng-if=\"search.loading\"><ion-spinner icon=\"android\"></ion-spinner></div><div ng-if=\"!search.loading && search.results && (!search.results.length || !search.results[0].address)\" class=\"assertive padding\"><span translate=\"\">COMMON.SEARCH_NO_RESULT</span></div><ion-list ng-if=\"!search.loading\" class=\"padding-top {{::motion.ionListClass}}\"><div ng-repeat=\"res in search.results\" class=\"item item-border-large item-text-wrap ink\" ng-class=\"::{\'item-divider\': !res.address, \'item-icon-left item-icon-right\': res.address}\" ng-click=\"res.address ? closeModal(res) : false\"><h4 class=\"text-italic\" ng-if=\"::!res.address\" ng-bind-html=\"res.name\"></h4><ng-if ng-if=\"::res.address\"><i class=\"icon ion-location\"></i><h2 ng-if=\"res.address.road\">{{::res.address.road}}</h2><h3><span ng-if=\"res.address.postcode\">{{::res.address.postcode}}</span> {{::res.address.city||res.address.village}} <span class=\"gray\">| {{::res.address.country}}</span></h3><h5 class=\"gray\">{{\'LOCATION.MODAL.POSITION\'|translate:res }}</h5><i class=\"icon ion-ios-arrow-right\"></i></ng-if></div></ion-list></ion-content><ion-footer-bar class=\"stable-bg padding-left padding-right block\" ng-if=\"license\"><div class=\"pull-right copyright\"><span class=\"dark\">© </span><a class=\"positive\" href=\"{{license.url}}\" target=\"_blank\">{{license.name}}</a></div></ion-footer-bar></ion-modal-view>"); -$templateCache.put("plugins/es/templates/common/popover_profile_extend.html","<button ng-if=\"enable && auth\" class=\"button button-positive button-small ink\" ng-click=\"showEditUserProfile()\">{{\'PROFILE.BTN_EDIT\' | translate}}</button>"); -$templateCache.put("plugins/es/templates/common/view_comments.html","<div class=\"comments\" ng-controller=\"ESCommentsCtrl\"><div class=\"item item-divider\"><i class=\"icon ion-chatboxes\"></i> <span translate=\"\">COMMENTS.DIVIDER</span> <span class=\"gray\" ng-if=\"comments.total\">({{comments.total}})</span></div><span class=\"item item-more-comments\" ng-if=\"comments.hasMore\"><small><a ng-click=\"showMore()\" translate=\"\">COMMENTS.SHOW_MORE_COMMENTS</a></small></span><div class=\"padding-right\"><ng-repeat ng-repeat=\"comment in comments.result track by comment.id\" ng-include=\"\'plugins/es/templates/common/item_comment.html\'\"></ng-repeat></div><div class=\"visible-xs visible-sm\" style=\"margin-bottom\"><div class=\"block\"><div class=\"item item-input-inset done in\" ng-if=\"formData.parent\"><div class=\"padding text-right pull-left\" translate=\"\">COMMENTS.REPLY_TO</div><br><div class=\"padding-left expanded\"><div class=\"card card-comment stable-900-bg item-text-wrap no-padding in done\"><ng-include ng-if=\"::formData.parent.message\" ng-init=\"comment = formData.parent\" src=\"\'plugins/es/templates/common/item_comment_content.html\'\"></ng-include><span ng-if=\"::!formData.parent.message\" translate=\"\">COMMENTS.DELETED_COMMENT</span><div class=\"card-footer text-right gray\"><div class=\"pull-right\"><a class=\"ion-close\" ng-click=\"removeParentLink()\">{{::\'COMMON.BTN_CANCEL\'|translate}}</a></div></div></div></div></div><div class=\"item item-input-inset\"><div class=\"item-input-wrapper\"><input type=\"text\" id=\"comment-form-input\" style=\"width: 100%\" placeholder=\"{{\'COMMENTS.COMMENT_HELP\'|translate}}\" on-return=\"save();\" ng-model=\"formData.message\"> <button class=\"button button-small button-small-padding button-icon button-dark button-icon gray\" ng-click=\"save()\"><i class=\"icon ion-android-send\"></i></button></div></div></div></div></div>"); -$templateCache.put("plugins/es/templates/common/view_pictures.html","<div class=\"item gallery done in\" ng-if=\"pictures && pictures.length>0\"><div ng-repeat=\"picture in pictures\" class=\"item card card-gallery\"><div class=\"ink\"><h2 ng-if=\"picture.title\">{{::picture.title}}</h2><img ng-src=\"{{picture.src}}\"></div></div></div>"); -$templateCache.put("plugins/es/templates/currency/tab_blocks_extend.html","<ng-if ng-if=\"enable && extensionPoint === \'nav-buttons\'\"><button class=\"button button-icon button-clear icon ion-android-search visible-xs visible-sm\" ui-sref=\"app.blockchain_search\"></button></ng-if>"); -$templateCache.put("plugins/es/templates/document/item_document.html","<ion-item id=\"doc-{{::doc.id}}\" class=\"item item-document item-icon-left ink {{::ionItemClass}} no-padding-top no-padding-bottom\" ng-click=\"selectDocument($event, doc)\"><i class=\"icon ion-document stable\" ng-if=\":rebind:!doc.avatar\"></i> <i class=\"avatar\" ng-if=\":rebind:doc.avatar\" style=\"background-image: url(\'{{:rebind:doc.avatar.src}}\')\"></i><div class=\"row no-padding\"><div class=\"col\"><h3 class=\"dark\"><i class=\"ion-locked\" ng-if=\":rebind:doc.nonce\"></i> {{:rebind:doc.time|formatDate}}</h3><h4 class=\"gray\">{{:rebind:\'DOCUMENT.HASH\'|translate}} {{:rebind:doc.hash|formatHash}}</h4></div><div class=\"col\"><h3><a ui-sref=\"app.wot_identity({pubkey: doc.pubkey, uid: doc.uid})\"><span class=\"gray\"><i class=\"ion-key\"></i> {{:rebind:doc.pubkey|formatPubkey}} </span><span class=\"positive\" ng-if=\":rebind:doc.uid\"><i class=\"ion-person\"></i> {{:rebind:doc.name||doc.uid}}</span></a></h3></div><div class=\"col\"><a ng-if=\":rebind:login && doc.pubkey==$root.walletData.pubkey\" ng-click=\"remove($index)\" class=\"gray pull-right\" title=\"{{\'DOCUMENT.LOOKUP.BTN_REMOVE\'|translate}}\"><i class=\"ion-trash-a\"></i></a><h3 ng-if=\":rebind:doc.recipient\"><a ui-sref=\"app.wot_identity({pubkey: doc.recipient.pubkey, uid: doc.recipient.uid})\"><span class=\"gray\"><i class=\"ion-key\"></i> {{:rebind:doc.recipient.pubkey|formatPubkey}} </span><span class=\"positive\" ng-if=\":rebind:doc.recipient.uid\"><i class=\"ion-person\"></i> {{:rebind:doc.recipient.name||doc.recipient.uid}}</span></a></h3><h4 class=\"gray\" ng-if=\":rebind:doc.read_signature\"><i class=\"ion-checkmark\"></i> <span translate>DOCUMENT.LOOKUP.READ</span></h4></div></div></ion-item>"); -$templateCache.put("plugins/es/templates/document/items_documents.html","<div class=\"padding gray\" ng-if=\":rebind:!search.loading && !search.results.length\" translate=\"\">COMMON.SEARCH_NO_RESULT</div><ng-repeat ng-repeat=\"doc in :rebind:search.results track by doc.id\" ng-include=\"\'plugins/es/templates/document/item_document.html\'\"></ng-repeat>"); -$templateCache.put("plugins/es/templates/document/lookup.html","<ion-view><ion-nav-title><span translate>DOCUMENT.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"></button></ion-nav-buttons><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><ng-include src=\"\'plugins/es/templates/document/lookup_form.html\'\"></ng-include></ion-content></ion-view>"); -$templateCache.put("plugins/es/templates/document/lookup_form.html","<div class=\"lookupForm\"><div class=\"item no-padding\"><label class=\"item-input\"><i class=\"icon ion-search placeholder-icon\"></i> <input type=\"text\" class=\"visible-xs visible-sm\" placeholder=\"{{\'DOCUMENT.LOOKUP.SEARCH_HELP\'|translate}}\" ng-model=\"search.text\" ng-model-options=\"{ debounce: 650 }\" ng-change=\"doSearchText()\"><div class=\"helptip-anchor-center\"><a id=\"{{helptipPrefix}}-search-text\"></a></div></label></div><div class=\"padding-top padding-xs\" style=\"display: block; height: 60px\"><div class=\"pull-left\"><h4 ng-if=\"search.last\" translate=\"\">DOCUMENT.LOOKUP.LAST_DOCUMENTS</h4><h4 ng-if=\"!search.last\">{{\'COMMON.RESULTS_LIST\'|translate}}</h4><h5 class=\"dark\" ng-if=\"!search.loading && search.total\"><span translate=\"COMMON.RESULTS_COUNT\" translate-values=\"{count: search.total}\"></span> <small class=\"gray\" ng-if=\":rebind:search.took && expertMode\">- {{:rebind:\'COMMON.EXECUTION_TIME\'|translate: {duration: search.took} }} </small><small class=\"gray\" ng-if=\":rebind:expertMode && search.filters && search.filters.length\">- <a ng-click=\"toggleShowQuery()\" ng-if=\"!showQuery\"><span translate=\"\">DOCUMENT.LOOKUP.SHOW_QUERY</span> <i class=\"icon ion-arrow-down-b gray\"></i> </a><a ng-click=\"toggleShowQuery()\" ng-if=\"showQuery\"><span translate=\"\">DOCUMENT.LOOKUP.HIDE_QUERY</span> <i class=\"icon ion-arrow-up-b gray\"></i></a></small></h5><h5 class=\"gray\" ng-if=\"search.loading\"><ion-spinner class=\"icon ion-spinner-small\" icon=\"android\"></ion-spinner><span translate=\"\">COMMON.SEARCHING</span><br></h5></div></div><div class=\"item no-border no-padding\" ng-if=\":rebind:search.filters && search.filters.length && expertMode\"><small class=\"no-padding no-margin\" ng-if=\"showQuery\"><span class=\"gray text-wrap dark\">{{:rebind:search.query}}</span></small></div><ion-list class=\"list\" ng-class=\"::motion.ionListClass\"><ng-include src=\"\'plugins/es/templates/document/items_documents.html\'\"></ng-include></ion-list><ion-infinite-scroll ng-if=\"search.hasMore\" spinner=\"android\" on-infinite=\"showMore()\" distance=\"1%\"></ion-infinite-scroll></div>"); -$templateCache.put("plugins/es/templates/document/lookup_popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>DOCUMENT.LOOKUP.POPOVER_ACTIONS.TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left assertive ink\" ng-class=\"{\'gray\': !search.total}\" ng-click=\"removeAll()\"><i class=\"icon ion-trash-a\"></i> {{\'DOCUMENT.LOOKUP.POPOVER_ACTIONS.REMOVE_ALL\' | translate}}</a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/group/edit_group.html","<ion-view left-buttons=\"leftButtons\"><ion-nav-title><span class=\"visible-xs\" ng-if=\"id\" ng-bind-html=\"formData.title\"></span> <span class=\"visible-xs\" ng-if=\"!loading && !id\" translate=\"\">GROUP.EDIT.TITLE_NEW</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear visible-xs visible-sm\" ng-class=\"{\'ion-android-send\':!id, \'ion-android-done\': id}\" ng-click=\"save()\"></button></ion-nav-buttons><ion-content scroll=\"true\"><div class=\"row no-padding\"><div class=\"col\"><div class=\"center padding\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></div><form name=\"recordForm\" novalidate=\"\" ng-submit=\"save()\"><div class=\"list\" ng-class=\"motion.ionListClass\" ng-init=\"setForm(recordForm)\"><div class=\"item hidden-xs\"><h1 ng-if=\"id\" ng-bind-html=\"formData.title\"></h1><h1 ng-if=\"!id\" translate=\"\">GROUP.EDIT.TITLE_NEW</h1><h2 class=\"balanced\" ng-if=\"!id\"><i class=\"icon ion-android-people\"></i> <i class=\"icon ion-android-lock\" ng-if=\"formData.type==\'managed\'\"></i> {{\'GROUP.TYPE.ENUM.\'+formData.type|upper|translate}}</h2></div><div class=\"item\" ng-if=\"id\"><h4 class=\"gray\"><i class=\"icon ion-calendar\"></i> {{\'COMMON.LAST_MODIFICATION_DATE\'|translate}} {{formData.time | formatDate}}</h4><div class=\"badge badge-balanced badge-editable\" ng-click=\"showRecordTypeModal()\">{{\'GROUP.TYPE.ENUM.\'+formData.type|upper|translate}}</div></div><ng-include src=\"\'plugins/es/templates/common/edit_pictures.html\'\"></ng-include><div class=\"item item-divider\" translate=\"\">GROUP.GENERAL_DIVIDER</div><div class=\"item item-input item-floating-label\" ng-class=\"{\'item-input-error\': form.$submitted && form.title.$invalid}\"><span class=\"input-label\" translate=\"\">GROUP.EDIT.RECORD_TITLE</span> <input type=\"text\" placeholder=\"{{\'GROUP.EDIT.RECORD_TITLE_HELP\'|translate}}\" name=\"title\" id=\"group-record-title\" ng-model=\"formData.title\" ng-minlength=\"3\" ng-required=\"true\"></div><div class=\"form-errors\" ng-if=\"form.$submitted && form.title.$error\" ng-messages=\"form.title.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div><div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT\"></span></div></div><div class=\"item item-input item-floating-label\"><span class=\"input-label\" translate=\"\">GROUP.EDIT.RECORD_DESCRIPTION</span><textarea placeholder=\"{{\'GROUP.EDIT.RECORD_DESCRIPTION_HELP\'|translate}}\" ng-model=\"formData.description\" rows=\"8\" cols=\"10\">\n </textarea></div><ng-include src=\"\'plugins/es/templates/common/edit_socials.html\'\" ng-controller=\"ESSocialsEditCtrl\"></ng-include></div></form></div></div></ion-content></ion-view>"); -$templateCache.put("plugins/es/templates/group/item_group.html","<a name=\"group-{{:rebind:group.hash}}\"></a><div id=\"group-{{:rebind:group.hash}}\" class=\"item item-icon-right item-avatar {{::ionItemClass}} ink\" ng-click=\"select(group)\"><i class=\"item-image avatar\" style=\"background-image: url({{::group.avatar.src}})\" ng-if=\"group.avatar\"></i> <i class=\"item-image icon ion-android-people\" ng-if=\"!group.avatar\"></i> <i class=\"item-image icon-secondary ion-android-lock\" ng-if=\"!group.avatar\" style=\"left: 20px; top: 17px; font-size: 19px; color: #d9d9d9\"></i><h2 ng-bind-html=\":rebind:group.title\"></h2><h4 class=\"gray pull-right\"><i class=\"ion-clock\"></i> {{:rebind:\'GROUP.CREATED_TIME\'|translate: group }}</h4><h4 class=\"dark pull-left\" ng-if=\":rebind:group.membersCount\"><i class=\"dark ion-person\"></i> <span class=\"dark\">+{{:rebind:group.membersCount}}</span></h4><i class=\"icon ion-ios-arrow-right\"></i></div>"); -$templateCache.put("plugins/es/templates/group/items_groups.html","<div class=\"padding gray\" ng-if=\":rebind:!search.loading && !search.results.length\" translate=\"\">COMMON.SEARCH_NO_RESULT</div><ng-repeat ng-repeat=\"group in :rebind:search.results\" ng-include=\"\'plugins/es/templates/group/item_group.html\'\"></ng-repeat>"); -$templateCache.put("plugins/es/templates/group/list.html","<ion-list class=\"{{::motion.ionListClass}}\"><ion-item ng-repeat=\"notification in search.results\" class=\"item-border-large item-text-wrap ink item-avatar\" ng-class=\"{\'unread\': !notification.read}\" ng-click=\"select(notification)\"><i ng-if=\"!notification.avatar\" class=\"item-image icon {{::notification.avatarIcon}}\"></i> <i ng-if=\"notification.avatar\" class=\"item-image avatar\" style=\"background-image: url({{::notification.avatar.src}})\"></i><h3 trust-as-html=\"notification.message | translate:notification\"></h3><h4><i class=\"icon {{notification.icon}}\"></i> <span class=\"dark\">{{notification.time|formatFromNow}}</span> <span class=\"gray\">| {{notification.time|formatDate}}</span></h4></ion-item></ion-list><ion-infinite-scroll ng-if=\"!search.loading && search.hasMore\" spinner=\"android\" on-infinite=\"showMore()\" distance=\"1%\"></ion-infinite-scroll>"); -$templateCache.put("plugins/es/templates/group/lookup.html","<ion-view class=\"view-group\"><ion-nav-title><span translate>GROUP.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"></button></ion-nav-buttons><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><ng-include src=\"\'plugins/es/templates/group/lookup_form.html\'\"></ng-include></ion-content></ion-view>"); -$templateCache.put("plugins/es/templates/group/lookup_form.html","<div class=\"lookupForm\"><label class=\"item item-input\"><i class=\"icon ion-search placeholder-icon\"></i> <input type=\"text\" class=\"visible-xs visible-sm\" placeholder=\"{{\'GROUP.LOOKUP.SEARCH_HELP\'|translate}}\" ng-model=\"search.text\" ng-model-options=\"{ debounce: 650 }\" ng-change=\"doSearchText()\"><div class=\"helptip-anchor-center\"><a id=\"helptip-group-search-text\"></a></div></label><div class=\"padding-top padding-xs\" style=\"display: block; height: 60px\"><div class=\"pull-left\"><h4 ng-if=\"search.type==\'open\'\" translate=\"\">GROUP.LOOKUP.OPEN_RESULTS_LIST</h4><h4 ng-if=\"search.type==\'last\'\" translate=\"\">GROUP.LOOKUP.LAST_RESULTS_LIST</h4><h4 ng-if=\"search.type==\'managed\'\" translate=\"\">GROUP.LOOKUP.MANAGED_RESULTS_LIST</h4><h4 ng-if=\"search.type==\'text\'\">{{\'COMMON.RESULTS_LIST\'|translate}}</h4><h5 class=\"dark\" ng-if=\"!search.loading && search.total\"><span translate=\"COMMON.RESULTS_COUNT\" translate-values=\"{count: search.total}\"></span> <small class=\"gray\" ng-if=\":rebind:search.took && expertMode\">- {{:rebind:\'COMMON.EXECUTION_TIME\'|translate: {duration: search.took} }}</small></h5><h5 class=\"gray\" ng-if=\"search.loading\"><ion-spinner class=\"icon ion-spinner-small\" icon=\"android\"></ion-spinner><span translate=\"\">COMMON.SEARCHING</span><br></h5></div></div><div class=\"list {{::motion.ionListClass}}\" ng-if=\"!$scope.search.loading\"><ng-include src=\"\'plugins/es/templates/group/items_groups.html\'\"></ng-include></div><ion-infinite-scroll ng-if=\"search.hasMore\" spinner=\"android\" on-infinite=\"showMore()\" distance=\"1%\"></ion-infinite-scroll></div>"); -$templateCache.put("plugins/es/templates/group/lookup_item.html","<i class=\"item-image avatar\" style=\"background-image: url({{::item.avatar.src}})\" ng-if=\"item.avatar\"></i> <i class=\"item-image icon ion-android-people\" ng-if=\"!item.avatar\"></i> <i class=\"item-image icon-secondary ion-android-lock\" ng-if=\"!item.avatar\" style=\"left: 20px; top: 17px; font-size: 19px; color: #d9d9d9\"></i><h2 ng-bind-html=\":rebind:item.title\"></h2><h4 class=\"gray pull-right\"><i class=\"ion-clock\"></i> {{:rebind:\'GROUP.CREATED_TIME\'|translate: item }}</h4><h4 class=\"dark pull-left\" ng-if=\":rebind:item.membersCount\"><i class=\"dark ion-person\"></i> <span class=\"dark\">+{{:rebind:item.membersCount}}</span></h4>"); -$templateCache.put("plugins/es/templates/group/modal_record_type.html","<ion-modal-view><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title\" translate>GROUP.TYPE.TITLE</h1></ion-header-bar><ion-content class=\"lookupForm padding\"><h3 translate>GROUP.TYPE.SELECT_TYPE</h3><div class=\"list\"><div class=\"item item-complex card stable-bg item-icon-left ink\" ng-click=\"closeModal(\'open\')\"><div class=\"item-content item-text-wrap\"><i class=\"item-image icon ion-android-people dark\"></i><h2 translate>GROUP.TYPE.OPEN_GROUP</h2><h4 class=\"gray\" translate>GROUP.TYPE.OPEN_GROUP_HELP</h4></div></div><div class=\"item item-complex card stable-bg item-icon-left ink\" ng-click=\"closeModal(\'managed\')\"><div class=\"item-content item-text-wrap\"><i class=\"item-image icon ion-android-people dark\"></i> <i class=\"icon-secondary ion-android-lock dark\" style=\"left: 10px; top: -8px\"></i><h2 translate>GROUP.TYPE.MANAGED_GROUP</h2><h4 class=\"gray\" translate>GROUP.TYPE.MANAGED_GROUP_HELP</h4></div></div></div></ion-content></ion-modal-view>"); -$templateCache.put("plugins/es/templates/group/view_popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>GROUP.VIEW.MENU_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink\" ng-click=\"showSharePopover($event)\"><i class=\"icon ion-android-share-alt\"></i> {{\'COMMON.BTN_SHARE\' | translate}}</a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/group/view_record.html","<ion-view left-buttons=\"leftButtons\"><ion-nav-title></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-bar button-icon button-clear visible-xs visible-sm\" ng-click=\"edit()\" ng-if=\"canEdit\"><i class=\"icon ion-android-create\"></i></button> <button class=\"button button-bar button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"></button></ion-nav-buttons><ion-content scroll=\"true\"><div class=\"positive-900-bg hero\"><div class=\"content\" ng-if=\"!loading\"><i class=\"avatar cion-registry-{{formData.type}}\" ng-if=\"!formData.avatar\"></i> <i class=\"avatar\" style=\"background-image: url({{::formData.avatar.src}})\" ng-if=\"formData.avatar\"></i><h3 ng-bind-html=\"formData.title\"></h3><h4> </h4></div><h4 class=\"content light\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></h4></div><div class=\"row no-padding-xs\"><div class=\"col list item-text-wrap no-padding-xs\" ng-class=\"::motion.ionListClass\"><div class=\"item\"><h2 class=\"gray\"><a ng-if=\"formData.city\" ui-sref=\"app.groups({location:formData.city})\"><i class=\"icon ion-location\"></i> <span ng-bind-html=\"formData.city\"></span> </a><span ng-if=\"formData.city && formData.type\"> | </span> <a ng-if=\"formData.type\" ui-sref=\"app.groups({type:formData.type})\"><i class=\"icon ion-flag\"></i> {{\'GROUP.TYPE.ENUM.\'+formData.type|upper|translate}}</a></h2><h4><i class=\"icon ion-clock\" ng-if=\"formData.time\"></i> <span translate=\"\">COMMON.SUBMIT_BY</span> <a ng-class=\"{\'positive\': issuer.uid, \'gray\': !issuer.uid}\" ui-sref=\"app.wot_identity({pubkey:issuer.pubkey, uid: issuer.name||issuer.uid})\"><ng-if ng-if=\"issuer.uid\"><i class=\"icon ion-person\"></i> {{::issuer.name||issuer.uid}}</ng-if><span ng-if=\"!issuer.uid\"><i class=\"icon ion-key\"></i> {{issuer.pubkey|formatPubkey}} </span></a><span>{{formData.time|formatFromNow}}<h4 class=\"gray hidden-xs\">| {{formData.time | formatDate}}</h4></span></h4></div><a id=\"group-share-anchor-{{id}}\"></a><ion-item><h2><span trust-as-html=\"formData.description\"></span></h2></ion-item><ion-item><h4 ng-if=\"formData.address\"><span class=\"gray\" translate=\"\">REGISTRY.VIEW.LOCATION</span> <a class=\"positive\" target=\"_blank\" href=\"https://www.google.fr/maps/?q={{formData.address}},%20{{formData.city}}\"><span ng-bind-html=\"formData.address\"></span> <span ng-if=\"formData.city\">- </span><span ng-bind-html=\"formData.city\"></span></a></h4></ion-item><ng-if ng-if=\"formData.socials && formData.socials.length>0\"><ion-item class=\"item-icon-left\" type=\"no-padding item-text-wrap\" ng-repeat=\"social in formData.socials track by social.url\" id=\"social-{{social.url|formatSlug}}\"><i class=\"icon ion-social-{{social.type}}\" ng-class=\"{\'ion-bookmark\': social.type == \'other\', \'ion-link\': social.type == \'web\', \'ion-email\': social.type == \'email\'}\"></i><p ng-if=\"social.type && social.type != \'web\'\">{{social.type}}</p><h2><a href=\"{{social.url}}\" ng-if=\"social.type != \'email\'\" target=\"_blank\">{{social.url}}</a> <a href=\"mailto:{{social.url}}\" ng-if=\"social.type == \'email\'\">{{social.url}}</a></h2></ion-item></ng-if><div class=\"lazy-load\"><ng-include src=\"\'plugins/es/templates/common/view_pictures.html\'\"></ng-include><span class=\"item item-divider\" ng-if=\"formData.pubkey\"><span translate=\"\">REGISTRY.TECHNICAL_DIVIDER</span></span><div class=\"item item-icon-left item-text-wrap ink\" ng-if=\"formData.pubkey\" copy-on-click=\"{{::formData.pubkey}}\"><i class=\"icon ion-key\"></i> <span translate=\"\">REGISTRY.EDIT.RECORD_PUBKEY</span><h4 class=\"dark\">{{::formData.pubkey}}</h4></div><ng-include src=\"\'plugins/es/templates/common/view_comments.html\'\"></ng-include></div></div></div></ion-content><button class=\"button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm\" ng-if=\"formData.pubkey && !isUserPubkey(formData.pubkey)\" ng-click=\"showTransferModal({pubkey: formData.pubkey, uid: formData.title})\"></button></ion-view>"); -$templateCache.put("plugins/es/templates/invitation/list_invitation.html","<ion-list class=\"{{::motion.ionListClass}}\"><ion-item ng-repeat=\"invitation in search.results\" class=\"item-border-large item-text-wrap item-avatar\"><i ng-if=\"::!invitation.avatar\" class=\"item-image icon {{::invitation.avatarIcon}}\"></i> <i ng-if=\"::invitation.avatar\" class=\"item-image avatar\" style=\"background-image: url({{::invitation.avatar.src}})\"></i><h3 trust-as-html=\"invitation.message | translate:invitation\"></h3><h3 class=\"dark text-italic\" ng-if=\"invitation.comment\"><i class=\"icon ion-quote\"></i> <span ng-bind-html=\"invitation.comment\"></span></h3><h4><i class=\"icon {{::invitation.icon}}\"></i> <span class=\"dark\" ng-if=\"::invitation.issuer\" trust-as-html=\"\'INVITATION.SUGGESTED_BY\' | translate:invitation\"></span> <span class=\"dark\">{{::invitation.time|formatFromNow}}</span> <span class=\"gray\">| {{::invitation.time|formatDate}}</span></h4><div class=\"block text-right\"><button class=\"button button-positive button-small button-small-padding\" ng-click=\"accept(invitation)\" ng-if=\"::invitation.state\" translate>{{::(invitation.okText||\'COMMON.BTN_SHOW\') |translate}}</button> <button class=\"button button-stable button-small button-small-padding\" ng-click=\"delete($index)\" translate>INVITATION.BTN_DELETE</button></div></ion-item></ion-list><ion-infinite-scroll ng-if=\"!search.loading && search.hasMore\" spinner=\"android\" on-infinite=\"showMore()\" distance=\"1%\"></ion-infinite-scroll>"); -$templateCache.put("plugins/es/templates/invitation/modal_new_invitation.html","<ion-modal-view id=\"transfer\" class=\"modal-full-height\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear visible-xs\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title\" translate>INVITATION.NEW.TITLE</h1><button class=\"button button-icon button-clear icon ion-android-send visible-xs\" ng-click=\"doSend()\"></button></ion-header-bar><ion-content scroll=\"true\"><ng-include src=\"\'plugins/es/templates/invitation/new_invitation_form.html\'\"></ng-include></ion-content></ion-modal-view>"); -$templateCache.put("plugins/es/templates/invitation/new_invitation_form.html","<form name=\"invitationForm\" novalidate=\"\" ng-submit=\"doSend()\"><div class=\"list\" ng-init=\"setForm(invitationForm)\"><a class=\"item item-icon-right gray ink\" ng-class=\"{\'disable-pointer-events\': recipients.length, \'item-input-error\': form.$submitted && !recipients.length}\" ng-click=\"showSelectRecipientModal($event)\"><span class=\"gray\" translate=\"\">INVITATION.NEW.RECIPIENTS</span> <span class=\"item-note\"><span class=\"hidden-xs\" ng-if=\"!recipients.length\" translate=\"\">INVITATION.NEW.RECIPIENTS_HELP</span><ng-repeat ng-repeat=\"identity in recipients track by identity.id\" class=\"button button-small button-text button-stable button-icon-event ink\" ng-class=\"{\'button-text-positive\': identity.selected}\"><ng-bind-html ng-bind-html=\"identity.name||identity.uid||(identity.pubkey|formatPubkey)\"></ng-bind-html><b class=\"enable-pointer-events ion-close\" ng-click=\"removeRecipient($index, $event)\"> </b></ng-repeat></span><i class=\"gray icon enable-pointer-events ion-ios-arrow-right\"></i></a><div class=\"form-errors\" ng-if=\"form.$submitted && !recipients.length\"><div class=\"form-error\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div><a class=\"item item-icon-right gray ink\" ng-class=\"{\'disable-pointer-events\': suggestions.length, \'item-input-error\': form.$submitted && !suggestions.length}\" ng-click=\"showSelectSuggestionModal($event)\"><span class=\"gray enable-pointer-events\" translate=\"\">INVITATION.NEW.SUGGESTION_IDENTITIES</span> <span class=\"item-note\"><span class=\"hidden-xs\" ng-if=\"!suggestions.length\" translate=\"\">INVITATION.NEW.SUGGESTION_IDENTITIES_HELP</span><ng-repeat ng-repeat=\"identity in suggestions track by identity.id\" class=\"button button-small button-text button-stable button-icon-event ink\" ng-class=\"{\'button-text-positive\': identity.selected}\"><ng-bind-html ng-bind-html=\"identity.name||identity.uid||(identity.pubkey|formatPubkey)\"></ng-bind-html><b class=\"enable-pointer-events ion-close\" ng-click=\"removeSuggestion($index, $event)\"> </b></ng-repeat></span><i class=\"gray icon enable-pointer-events ion-ios-arrow-right\"></i></a><div class=\"form-errors\" ng-if=\"form.$submitted && !suggestions.length\"><div class=\"form-error\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div><div class=\"item item-content item-toggle dark visible-xs visible-sm\"><span class=\"input-label gray\">{{\'TRANSFER.BTN_ADD_COMMENT\' | translate}}</span><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.useComment\"><div class=\"track\"><div class=\"handle\"></div></div></label></div><label class=\"item item-input item-floating-label visible-xs visible-sm\" ng-if=\"formData.useComment\" ng-class=\"{\'item-input-error\': form.$submitted && form.comment.$invalid}\"><span class=\"input-label\">{{\'TRANSFER.COMMENT\' | translate}}</span><textarea placeholder=\"{{\'TRANSFER.COMMENT_HELP\' | translate}}\" name=\"comment\" ng-model=\"formData.comment\" ng-maxlength=\"255\">\n </textarea></label><div class=\"form-errors\" ng-show=\"form.$submitted && form.comment.$error\" ng-messages=\"form.comment.$error\"><div class=\"form-error\" ng-message=\"maxlength\"><span translate=\"ERROR.FIELD_TOO_LONG\"></span></div><div class=\"form-error\" ng-message=\"pattern\"><span translate=\"ERROR.FIELD_ACCENT\"></span></div></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-small button-clear button-dark ink\" ng-click=\"cancel()\" type=\"button\" translate=\"\">COMMON.BTN_CANCEL</button> <button class=\"button button-small button-positive ink\" type=\"submit\">{{\'COMMON.BTN_SEND\' | translate}}</button></div></form>"); -$templateCache.put("plugins/es/templates/invitation/popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink\" ng-class=\"{\'gray\': !search.results.length, \'assertive\': search.results.length}\" ng-click=\"deleteAll()\"><i class=\"icon ion-trash-a\"></i> <span translate>INVITATION.BTN_DELETE_ALL</span></a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/invitation/popover_invitation.html",""); -$templateCache.put("plugins/es/templates/invitation/view_invitations.html","<ion-view left-buttons=\"leftButtons\" class=\"view-invitation\"><ion-nav-title>{{\'INVITATION.LIST.TITLE\' | translate}}</ion-nav-title><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><div class=\"row no-padding\"><div class=\"col no-padding-xs\"><div class=\"center padding\" ng-if=\"search.loading\"><ion-spinner icon=\"android\"></ion-spinner></div><div class=\"padding gray\" ng-if=\"!search.loading && !search.results.length\" translate=\"\">INVITATION.NO_RESULT</div><ng-include src=\"\'plugins/es/templates/invitation/list_invitation.html\'\"></ng-include></div></div></ion-content><button id=\"fab-new-invitation\" class=\"button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm spin\" ng-click=\"showNewInvitationModal()\"></button></ion-view>"); -$templateCache.put("plugins/es/templates/join/modal_join_extend.html","<ng-if ng-if=\"enable && extensionPoint === \'select-account-type\'\"><div class=\"item item-complex card stable-bg item-icon-left item-icon-right ink\" ng-class=\"{ activated: accountTypeMember != null && !accountTypeMember }\" ng-click=\"selectAccountType(\'organization\')\"><div class=\"item-content item-text-wrap\"><i class=\"item-image icon dark cion-registry-association\"></i><h2 translate>ACCOUNT.NEW.ORGANIZATION_ACCOUNT</h2><h4 class=\"gray\" translate>ACCOUNT.NEW.ORGANIZATION_ACCOUNT_HELP</h4><i class=\"icon dark ion-ios-arrow-right\"></i></div></div></ng-if><ng-if ng-if=\"enable && extensionPoint === \'last-slide\'\"><ion-slide-page><ion-content class=\"has-header\" scroll=\"false\"><p>TOTO</p></ion-content></ion-slide-page></ng-if>"); -$templateCache.put("plugins/es/templates/message/compose.html","<ion-view left-buttons=\"leftButtons\" id=\"composeMessage\"><ion-nav-title><span class=\"visible-xs visible-sm\" nf-if=\"!isReply\" translate=\"\">MESSAGE.COMPOSE.TITLE</span> <span class=\"visible-xs visible-sm\" nf-if=\"isReply\" translate=\"\">MESSAGE.COMPOSE.TITLE_REPLY</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-android-send visible-xs\" ng-click=\"doSend()\"></button></ion-nav-buttons><ion-content scroll=\"true\"><div class=\"row\"><div class=\"col\"><ng-include src=\"\'plugins/es/templates/message/compose_form.html\'\"></ng-include></div></div></ion-content></ion-view>"); -$templateCache.put("plugins/es/templates/message/compose_form.html","<form name=\"messageForm\" novalidate=\"\" ng-submit=\"doSend()\"><div class=\"list no-margin\" ng-init=\"setForm(messageForm)\"><a class=\"item item-icon-right gray ink\" ng-class=\"{\'item-input-error\': form.$submitted && !formData.destPub}\" ng-click=\"showWotLookupModal()\"><span class=\"gray\" translate>MESSAGE.COMPOSE.TO</span> <span class=\"badge badge-royal\">{{destUid}}{{destPub | formatPubkey}}</span> <i class=\"gray icon ion-ios-arrow-right\"></i></a><div class=\"form-errors\" ng-if=\"form.$submitted && !formData.destPub\"><div class=\"form-error\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div><div class=\"item item-text-wrap\"><span class=\"gray\" translate>TRANSFER.FROM</span> <span class=\"badge badge-balanced\"><ion-spinner icon=\"android\" ng-if=\"!$root.walletData.pubkey\"></ion-spinner><span ng-if=\"$root.walletData.pubkey && !$root.walletData.isMember\">{{$root.walletData.pubkey| formatPubkey}} </span><span ng-if=\"$root.walletData.isMember\">{{$root.walletData.name||$root.walletData.uid}}</span></span></div><div class=\"item item-input\" ng-class=\"{\'item-input-error\': form.$submitted && form.title.$invalid}\"><input type=\"text\" placeholder=\"{{\'MESSAGE.COMPOSE.OBJECT_HELP\' | translate}}\" name=\"title\" ng-model=\"formData.title\" ng-maxlength=\"256\" required></div><div class=\"form-errors\" ng-show=\"form.$submitted && form.title.$error\" ng-messages=\"form.title.$error\"><div class=\"form-error\" ng-message=\"maxlength\"><span translate=\"MESSAGE.ERROR.MESSAGE_CONTENT_TOO_LONG\" translate-values=\"{maxLength: 256}\"></span></div><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div><div class=\"item item-input item-floating-label\" ng-class=\"{\'item-input-error\': form.$submitted && form.content.$invalid}\"><span class=\"input-label\">{{\'MESSAGE.COMPOSE.MESSAGE\' | translate}}</span><textarea placeholder=\"{{\'MESSAGE.COMPOSE.MESSAGE_HELP\' | translate}}\" name=\"content\" ng-model=\"formData.content\" rows=\"8\" ng-maxlength=\"5000\">\n </textarea></div><div class=\"form-errors\" ng-show=\"form.$submitted && form.content.$error\" ng-messages=\"form.content.$error\"><div class=\"form-error\" ng-message=\"maxlength\"><span translate=\"MESSAGE.ERROR.MESSAGE_CONTENT_TOO_LONG\" translate-values=\"{maxLength: 5000}\"></span></div></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-clear button-dark ink\" ng-click=\"cancel()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-positive ink\" type=\"submit\" translate>TRANSFER.BTN_SEND</button></div><div class=\"list no-margin\"><div class=\"item item-icon-left item-text-wrap\"><i class=\"icon ion-ios-information-outline positive\"></i><h4 class=\"positive\" translate>MESSAGE.COMPOSE.ENCRYPTED_HELP</h4></div></div></form>"); -$templateCache.put("plugins/es/templates/message/list.html","<div class=\"padding gray\" ng-if=\"!search.loading && !search.results.length\"><span ng-if=\"search.type==\'last\'\">{{ (\'MESSAGE.NO_MESSAGE_\' + type) | upper | translate }}</span> <span ng-if=\"search.type==\'text\'\" translate=\"\">COMMON.SEARCH_NO_RESULT</span></div><ion-list class=\"{{::motion.ionListClass}}\" can-swipe=\"$root.device.enable\"><ion-item class=\"item item-border-large item-avatar item-icon-right ink\" ng-repeat=\"msg in search.results\" ui-sref=\"app.user_view_message({type:type, id:msg.id})\"><i ng-if=\"::!msg.avatar\" class=\"item-image icon\" ng-class=\"{\'ion-person\': msg.uid, \'ion-email\': !msg.uid}\"></i> <i ng-if=\"::msg.avatar\" class=\"item-image avatar\" style=\"background-image: url({{::msg.avatar.src}})\"></i><h4 class=\"pull-right visible-xs visible-sm dark\"><i class=\"ion-clock\"></i> {{::msg.time|formatFromNow}}</h4><h3><a class=\"positive\" ng-if=\"::msg.name||msg.uid\" ui-sref=\"app.wot_identity({pubkey:msg.issuer, uid:msg.name||msg.uid})\"><i class=\"ion-person\"></i> {{::msg.name||msg.uid}} </a><a class=\"gray\" ng-if=\"::!msg.name && !msg.uid\" ui-sref=\"app.wot_identity({pubkey:msg.issuer})\"><i class=\"ion-key\"></i> {{::msg.issuer|formatPubkey}}</a></h3><h2 ng-class=\"{\'unread\': !msg.read}\" ng-bind-html=\"::msg.title\"></h2><p ng-bind-html=\"::msg.summary||msg.content\"></p><i class=\"icon ion-ios-arrow-right\"></i><ion-option-button class=\"button-stable\" ng-click=\"showReplyModal($index)\" translate=\"\">MESSAGE.BTN_REPLY</ion-option-button><ion-option-button class=\"button-assertive\" ng-click=\"delete($index)\" translate=\"\">COMMON.BTN_DELETE</ion-option-button></ion-item></ion-list><ion-infinite-scroll ng-if=\"!search.loading && search.hasMore\" icon=\"ion-loading-c\" on-infinite=\"showMore()\" distance=\"10%\"></ion-infinite-scroll>"); -$templateCache.put("plugins/es/templates/message/lookup.html","<ion-view left-buttons=\"leftButtons\" class=\"view-messages\"><ion-tabs class=\"tabs-positive tabs-icon-top\"><ion-tab title=\"{{\'MESSAGE.LIST.INBOX\'|translate}}\" icon=\"ion-archive\" ui-sref=\"app.user_message.tab_inbox\"><ion-nav-view name=\"tab_inbox\"></ion-nav-view></ion-tab><ion-tab title=\"{{\'MESSAGE.LIST.OUTBOX\'|translate}}\" icon=\"ion-paper-airplane\" ui-sref=\"app.user_message.tab_outbox\"><ion-nav-view name=\"tab_outbox\"></ion-nav-view></ion-tab></ion-tabs></ion-view>"); -$templateCache.put("plugins/es/templates/message/lookup_lg.html","<ion-view left-buttons=\"leftButtons\" class=\"view-messages\"><ion-nav-title><span translate=\"\">MESSAGE.LIST.TITLE</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"><i class=\"icon ion-android-more-vertical\"></i></button></ion-nav-buttons><ion-content class=\"padding no-padding-xs\"><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"refresh(true)\"></ion-refresher><div class=\"item no-padding\"><div class=\"item-input\"><i class=\"icon ion-search placeholder-icon\"></i> <input type=\"text\" class=\"visible-xs visible-sm\" placeholder=\"{{\'MESSAGE.LIST.SEARCH_HELP\'|translate}}\" ng-model=\"search.text\" ng-model-options=\"{ debounce: 650 }\" ng-change=\"doSearch()\" on-return=\"doSearch()\" select-on-click=\"\"><div class=\"helptip-anchor-center\"><a id=\"helptip-message-search-text\"></a></div></div></div><div class=\"padding-top hidden-xs\" style=\"display: block; height: 60px\"><div class=\"pull-left\" ng-if=\"!search.loading\"><ng-if ng-if=\"search.type==\'last\'\"><h4>{{ (\'MESSAGE.LIST.LAST_\' + type) | upper | translate}}</h4></ng-if><ng-if ng-if=\"search.type==\'text\'\"><h4 translate=\"\">COMMON.RESULTS_LIST</h4></ng-if></div></div><div class=\"center padding\" ng-if=\"search.loading\"><ion-spinner icon=\"android\"></ion-spinner></div><ng-include src=\"\'plugins/es/templates/message/list.html\'\"></ng-include></ion-content><button id=\"fab-add-message-record\" class=\"button button-fab button-fab-bottom-right button-assertive icon ion-compose visible-xs visible-sm spin\" ng-click=\"showNewMessageModal()\"></button></ion-view>"); -$templateCache.put("plugins/es/templates/message/lookup_popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>MESSAGE.LIST.POPOVER_ACTIONS.TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink\" ng-class=\"{\'gray\': (type != \'inbox\' && !messages.length)}\" ng-click=\"markAllAsRead()\"><i class=\"icon ion-android-checkmark-circle\"></i> {{\'COMMON.NOTIFICATIONS.MARK_ALL_AS_READ\' | translate}} </a><a class=\"item item-icon-left assertive ink\" ng-class=\"{\'gray\': !messages.length}\" ng-click=\"deleteAll()\"><i class=\"icon ion-trash-a\"></i> {{\'MESSAGE.LIST.POPOVER_ACTIONS.DELETE_ALL\' | translate}}</a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/message/modal_compose.html","<ion-modal-view id=\"composeMessage\" class=\"modal-full-height\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear visible-xs\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title\" ng-if=\"!isReply\" translate>MESSAGE.COMPOSE.TITLE</h1><h1 class=\"title\" ng-if=\"isReply\" translate>MESSAGE.COMPOSE.TITLE_REPLY</h1><button class=\"button button-icon button-clear icon ion-android-send visible-xs\" ng-click=\"doSend()\"></button></ion-header-bar><ion-content scroll=\"true\"><ng-include src=\"\'plugins/es/templates/message/compose_form.html\'\"></ng-include></ion-content></ion-modal-view>"); -$templateCache.put("plugins/es/templates/message/popover_message.html",""); -$templateCache.put("plugins/es/templates/message/view_message.html","<ion-view left-buttons=\"leftButtons\" class=\"view-message\"><ion-nav-title><span translate=\"\">MESSAGE.VIEW.TITLE</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"></button></ion-nav-buttons><ion-content scroll=\"true\"><div class=\"row no-padding\"><div class=\"col no-padding\"><div class=\"center padding\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></div><ion-list class=\"animate-fade-slide-in item-text-wrap\"><div class=\"item item-avatar\" ng-class=\"{\'item-avatar\': formData.avatar}\"><i ng-if=\"!formData.avatar\" class=\"item-image\" ng-class=\"{\'ion-person\': formData.uid, \'ion-email\': !formData.uid}\"></i> <i ng-if=\"formData.avatar\" class=\"item-image avatar\" style=\"background-image: url({{::formData.avatar.src}})\"></i><h4>{{type == \'inbox\' ? \'MESSAGE.VIEW.SENDER\': \'MESSAGE.VIEW.RECIPIENT\'|translate}} <a class=\"positive\" ui-sref=\"app.wot_identity({pubkey: (type == \'inbox\') ? formData.issuer : formData.recipient, uid: formData.name||formData.uid})\"><span ng-if=\"formData.uid\"><i class=\"ion-person\"></i> {{formData.name||formData.uid}} </span><span ng-if=\"!formData.uid\" class=\"gray\"><i class=\"ion-key gray\"></i> {{formData.name||(formData.issuer|formatPubkey)}}</span></a></h4><h5 class=\"gray visible-xs visible-sm\"><i class=\"ion-clock\"></i> {{formData.time | formatDate}}</h5></div><ion-item class=\"visible-xs visible-sm\"><h1 class=\"title\" ng-bind-html=\"formData.title\"></h1></ion-item><ion-item><p ng-bind-html=\"formData.html\"></p><div class=\"padding gray\" ng-if=\"!formData.content\" translate=\"\">MESSAGE.VIEW.NO_CONTENT</div></ion-item></ion-list></div></div></ion-content><button id=\"fab-view-message-reply\" class=\"button button-fab button-fab-bottom-right button-calm icon ion-reply visible-xs visible-sm spin\" ng-click=\"showReplyModal()\"></button></ion-view>"); -$templateCache.put("plugins/es/templates/message/view_popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left assertive ink\" ng-click=\"delete()\"><i class=\"icon ion-trash-a\"></i> {{\'MESSAGE.VIEW.DELETE\' | translate}}</a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/network/view_network_extend.html","<ng-if ng-if=\"enable && extensionPoint === \'buttons\'\"><a class=\"button button-text button-small ink\" ui-sref=\"app.blockchain_search\"><i class=\"icon ion-android-search\"></i> <span>{{\'COMMON.BTN_SEARCH\'|translate}}</span></a></ng-if>"); -$templateCache.put("plugins/es/templates/notification/list_notification.html","<ion-list class=\"{{::motion.ionListClass}}\"><ion-item ng-repeat=\"notification in search.results\" class=\"item-border-large item-text-wrap ink item-avatar\" ng-class=\"{\'unread\': !notification.read}\" ng-click=\"select(notification)\"><i ng-if=\"!notification.avatar\" class=\"item-image icon {{::notification.avatarIcon}}\"></i> <i ng-if=\"notification.avatar\" class=\"item-image avatar\" style=\"background-image: url({{::notification.avatar.src}})\"></i><h3 trust-as-html=\"notification.message | translate:notification\"></h3><h4><i class=\"icon {{notification.icon}}\"></i> <span class=\"dark\">{{notification.time|formatFromNow}}</span> <span class=\"gray\">| {{notification.time|formatDate}}</span></h4></ion-item></ion-list><ion-infinite-scroll ng-if=\"!search.loading && search.hasMore\" spinner=\"android\" on-infinite=\"showMore()\" distance=\"1%\"></ion-infinite-scroll>"); -$templateCache.put("plugins/es/templates/notification/popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink\" ng-disabled=\"!search.results.length\" ng-click=\"markAllAsRead()\"><i class=\"icon ion-android-checkmark-circle\"></i> {{\'COMMON.NOTIFICATIONS.MARK_ALL_AS_READ\' | translate}}</a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/notification/popover_notification.html",""); -$templateCache.put("plugins/es/templates/notification/view_notifications.html","<ion-view left-buttons=\"leftButtons\" class=\"view-notification\"><ion-nav-title>{{\'COMMON.NOTIFICATIONS.TITLE\' | translate}}</ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"></button></ion-nav-buttons><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"refresh(true)\"></ion-refresher><div class=\"row no-padding\"><div class=\"col no-padding-xs\"><div class=\"center padding\" ng-if=\"search.loading\"><ion-spinner icon=\"android\"></ion-spinner></div><div class=\"padding gray\" ng-if=\"!search.loading && !search.results.length\" translate=\"\">COMMON.NOTIFICATIONS.NO_RESULT</div><ng-include src=\"\'plugins/es/templates/notification/list_notification.html\'\"></ng-include></div></div></ion-content></ion-view>"); -$templateCache.put("plugins/es/templates/registry/edit_record.html","<ion-view left-buttons=\"leftButtons\" class=\"view-page\"><ion-nav-title><span class=\"visible-xs\" ng-if=\"id\" ng-bind-html=\"formData.title\"></span> <span class=\"visible-xs\" ng-if=\"!loading && !id\" translate=\"\">REGISTRY.EDIT.TITLE_NEW</span></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear visible-xs visible-sm\" ng-class=\"{\'ion-android-send\':!id, \'ion-android-done\': id}\" ng-click=\"save()\"></button></ion-nav-buttons><ion-content scroll=\"true\"><div class=\"hero\"><div class=\"content\"><i class=\"avatar\" ng-class=\"avatarClass\" ng-style=\"avatarStyle\"><button class=\"button button-positive button-large button-clear flat icon ion-camera visible-xs visible-sm\" style=\"display: inline-block\" ng-click=\"showAvatarModal()\"></button> <button ng-if=\"avatar.src\" class=\"button button-positive button-large button-clear flat visible-xs visible-sm\" style=\"display: inline-block; left: 85px; bottom:15px\" ng-click=\"rotateAvatar()\"><i class=\"icon-secondary ion-image\" style=\"left: 24px; top: 3px; font-size: 24px\"></i> <i class=\"icon-secondary ion-forward\" style=\"left: 26px; top: -13px\"></i></button></i><h3 class=\"dark\"><span ng-if=\"!loading && formData.title\">{{formData.title}}</span> <span ng-if=\"!loading && !id && !formData.title\" translate=\"\">REGISTRY.EDIT.TITLE_NEW</span></h3><h4 class=\"dark\"><ion-spinner ng-if=\"loading\" icon=\"android\"></ion-spinner></h4></div></div><div class=\"row no-padding\"><div class=\"col no-padding-xs\"><form name=\"recordForm\" novalidate=\"\" ng-submit=\"save()\"><div class=\"list {{::motion.ionListClass}}\" ng-init=\"setForm(recordForm)\"><div class=\"item\" ng-if=\"id\"><h4 class=\"gray\"><i class=\"icon ion-calendar\"></i> {{\'COMMON.LAST_MODIFICATION_DATE\'|translate}} {{formData.time | formatDate}}</h4><div class=\"badge badge-balanced badge-editable\" ng-click=\"showRecordTypeModal()\">{{\'REGISTRY.TYPE.ENUM.\'+formData.type|upper|translate}}</div></div><ng-include src=\"\'plugins/es/templates/common/edit_pictures.html\'\"></ng-include><div class=\"item item-divider\" translate=\"\">REGISTRY.GENERAL_DIVIDER</div><div class=\"item item-input item-floating-label\" ng-class=\"{\'item-input-error\': form.$submitted && form.title.$invalid}\"><span class=\"input-label\" translate=\"\">REGISTRY.EDIT.RECORD_TITLE</span> <input type=\"text\" placeholder=\"{{\'REGISTRY.EDIT.RECORD_TITLE_HELP\'|translate}}\" name=\"title\" id=\"registry-record-title\" ng-model=\"formData.title\" ng-minlength=\"3\" ng-required=\"true\"></div><div class=\"form-errors\" ng-if=\"form.$submitted && form.title.$error\" ng-messages=\"form.title.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div><div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT\"></span></div></div><div class=\"item item-input item-floating-label\"><span class=\"input-label\" translate=\"\">REGISTRY.EDIT.RECORD_DESCRIPTION</span><textarea placeholder=\"{{\'REGISTRY.EDIT.RECORD_DESCRIPTION_HELP\'|translate}}\" ng-model=\"formData.description\" rows=\"8\" cols=\"10\">\n </textarea></div><div class=\"item item-icon-right ink\" ng-if=\"loading || formData.type===\'company\' || formData.type===\'shop\'\" ng-class=\"{\'item-input-error\': form.$submitted && !formData.category.id, \'done in\': !loading}\" ng-click=\"showCategoryModal()\"><span translate=\"\">REGISTRY.CATEGORY</span> <span class=\"badge badge-royal\">{{formData.category.name | formatCategory}}</span> <i class=\"gray icon ion-ios-arrow-right\"></i></div><input type=\"hidden\" name=\"category\" ng-model=\"formData.category.id\" required-if=\"formData.type==\'company\' || formData.type==\'shop\'\"><div class=\"form-errors\" ng-if=\"form.$submitted && form.category.$error\" ng-messages=\"form.category.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div><ng-include src=\"\'plugins/es/templates/common/edit_position.html\'\"></ng-include><ng-include src=\"\'plugins/es/templates/common/edit_socials.html\'\" ng-controller=\"ESSocialsEditCtrl\"></ng-include><div class=\"item item-divider\" translate=\"\">REGISTRY.TECHNICAL_DIVIDER</div><div class=\"item item-input item-floating-label\"><span class=\"input-label\" translate=\"\">REGISTRY.EDIT.RECORD_PUBKEY</span> <input type=\"text\" placeholder=\"{{\'REGISTRY.EDIT.RECORD_PUBKEY_HELP\'|translate}}\" ng-model=\"formData.pubkey\"></div></div></form></div></div></ion-content></ion-view>"); -$templateCache.put("plugins/es/templates/registry/lookup_form.html","<form ng-submit=\"doSearch()\"><div class=\"item no-padding\"><div class=\"item-input\"><i class=\"icon ion-search placeholder-icon\"></i> <input type=\"text\" class=\"visible-xs visible-sm\" placeholder=\"{{\'REGISTRY.SEARCH.SEARCH_HELP\'|translate}}\" ng-model=\"search.text\" ng-model-options=\"{ debounce: 650 }\" ng-change=\"doSearch()\" on-return=\"doSearchText()\" select-on-click=\"\"></div></div><ng-include src=\"::\'plugins/es/templates/common/item_location_search.html\'\" ng-if=\"entered && options.location.show && (!search.geoPoint || smallscreen)\" ng-controller=\"ESSearchPositionItemCtrl\"></ng-include><ng-include src=\"::\'plugins/es/templates/registry/lookup_form_options.html\'\"></ng-include></form><div class=\"padding-xs\" style=\"display: block; height: 60px\"><div class=\"pull-left ng-hide\" ng-show=\"!search.loading && search.results\"><ng-if ng-if=\"search.lastRecords\"><h4 translate=\"\">REGISTRY.SEARCH.LAST_RECORDS</h4><small class=\"gray no-padding\" ng-if=\"search.total\"><span ng-if=\"search.geoPoint && search.total\">{{\'REGISTRY.SEARCH.LAST_RECORD_COUNT_LOCATION\'|translate:{count: search.total, location: search.location} }}</span> <span ng-if=\"!search.geoPoint && search.total\">{{\'REGISTRY.SEARCH.LAST_RECORD_COUNT\'|translate:{count: search.total} }}</span></small></ng-if><ng-if ng-if=\"!search.lastRecords\"><h4 translate=\"\">COMMON.RESULTS_LIST</h4><small class=\"gray no-padding\" ng-if=\"search.total\"><span ng-if=\"search.geoPoint && search.total\">{{\'REGISTRY.SEARCH.RESULT_COUNT_LOCATION\'|translate:{count: search.total, location: search.location} }}</span> <span ng-if=\"!search.geoPoint && search.total\">{{\'REGISTRY.SEARCH.RESULT_COUNT\'|translate:{count: search.total} }}</span></small></ng-if></div></div><div class=\"center padding\" ng-if=\"search.loading\"><ion-spinner icon=\"android\"></ion-spinner></div><div class=\"padding assertive\" ng-if=\"!search.loading && search.results.length===0\" translate=\"\">COMMON.SEARCH_NO_RESULT</div>"); -$templateCache.put("plugins/es/templates/registry/lookup_form_options.html","<div class=\"item item-icon-left item-input item-select stable-bg\" ng-if=\"search.advanced && options.location.show\"><i class=\"icon ion-arrow-resize gray\"></i> <span class=\"input-label item-icon-left-padding\" translate=\"\">LOCATION.DISTANCE</span><label><select ng-model=\"search.geoDistance\" class=\"col-border-left\" ng-options=\"i as (geoDistanceLabels[i].labelKey | translate:geoDistanceLabels[i].labelParams ) for i in geoDistances track by i\"></select></label></div>"); -$templateCache.put("plugins/es/templates/registry/lookup_lg.html","<ion-view left-buttons=\"leftButtons\"><ion-nav-title>{{\'REGISTRY.SEARCH.TITLE\' | translate}}</ion-nav-title><ion-content class=\"lookupForm padding no-padding-xs\"><ng-include src=\"::\'plugins/es/templates/wot/lookup_lg_extend.html\'\" ng-init=\"showNewPageButton=true;\"></ng-include><ng-include src=\"::\'plugins/es/templates/registry/lookup_form.html\'\"></ng-include><ng-include src=\"::\'plugins/es/templates/registry/lookup_list_lg.html\'\"></ng-include></ion-content><button id=\"fab-add-registry-record\" class=\"button button-fab button-fab-bottom-right button-assertive icon ion-plus hidden-md hidden-lg spin\" ng-click=\"showNewPageModal()\"></button></ion-view>"); -$templateCache.put("plugins/es/templates/registry/lookup_list.html","<ion-list class=\"{{::motion.ionListClass}}\" ng-if=\"!search.loading && search.results && search.results.length > 0\"><ion-item ng-repeat=\"item in search.results\" class=\"item item-border-large item-avatar item-icon-right ink\" ng-class=\"::{\'item-icon-left\': !smallscreen}\" ui-sref=\"app.view_page({id: item.id, title: item.urlTitle})\"><i ng-if=\"::!item.avatar\" class=\"item-image icon cion-page-{{::item.type}}\"></i> <i ng-if=\"::item.avatar\" class=\"item-image avatar\" style=\"background-image: url({{::item.avatar.src}})\"></i><h2 ng-bind-html=\"::item.title\"></h2><h4><span class=\"dark\" ng-if=\"::item.city\"><b class=\"ion-location\"></b> <span ng-bind-html=\"::item.city\"></span> </span><span class=\"gray\" ng-if=\"::item.distance\">({{::item.distance|formatDecimal}} {{::geoUnit}})</span></h4><h4 class=\"gray\" ng-if=\"::item.time && search.lastRecords\"><i class=\"ion-clock\"></i> {{::item.time | formatFromNow}}</h4><h4 class=\"gray\" ng-if=\"!search.lastRecords\"><i class=\"cion-page-{{::item.type}}\"></i> <span ng-if=\"item.category\">{{::item.category.name}}</span> <span ng-if=\"!item.category\">{{::\'REGISTRY.TYPE.ENUM.\'+item.type|uppercase|translate}}</span></h4><i class=\"icon ion-ios-arrow-right\"></i></ion-item></ion-list>"); -$templateCache.put("plugins/es/templates/registry/lookup_list_lg.html","<div class=\"list {{::motion.ionListClass}}\" ng-if=\"!search.loading && search.results && search.results.length > 0\"><a ng-repeat=\"item in search.results\" class=\"item item-record item-border-large ink padding-xs\" ui-sref=\"app.view_page({id: item.id, title: item.urlTitle})\"><div class=\"row row-record\"><div class=\"col item-text-wrap item-avatar-left-padding\" ng-class=\"::{\'item-avatar\': item.avatar || item.type}\"><i class=\"item-image icon cion-page-{{::item.type}}\" ng-if=\"::!item.avatar\"></i> <i class=\"item-image avatar\" style=\"background-image: url({{::item.avatar.src}})\" ng-if=\"::item.avatar\"></i><h2 ng-bind-html=\"::item.title\"></h2><h4><span class=\"dark\" ng-if=\"::item.city\"><b class=\"ion-location\"></b> <span ng-bind-html=\"::item.city\"></span> </span><span class=\"gray\" ng-if=\"::item.distance\">({{::item.distance|formatDecimal}} {{::geoUnit}})</span></h4><h4><span class=\"gray\" ng-if=\"::item.time && search.lastRecords\"><b class=\"ion-clock\"></b> {{::item.time | formatFromNow}} </span><span ng-if=\"::item.tags\" class=\"dark\"><ng-repeat ng-repeat=\"tag in ::item.tags\">#<ng-bind-html ng-bind-html=\"::tag\"></ng-bind-html></ng-repeat></span></h4><span ng-if=\"::item.picturesCount > 1\" class=\"badge badge-balanced badge-picture-count\">{{::item.picturesCount}} <i class=\"icon ion-camera\"></i></span></div><div class=\"col hidden-xs\"><h4 class=\"text-wrap\"><span class=\"visible-sm\"><b class=\"ion-flag\"></b><ng-if ng-if=\"::item.category\">{{::item.category.name|truncText:50}}</ng-if><ng-if ng-if=\"::!item.category\">{{::\'REGISTRY.TYPE.ENUM.\'+item.type|uppercase|translate}}</ng-if></span><span class=\"gray text-italic\" ng-if=\"::item.description\"><b class=\"ion-quote\"></b> <span ng-bind-html=\"::item.description|truncText:500\" ng-if=\"::item.description\"></span></span></h4></div></div></a></div><ion-infinite-scroll ng-if=\"!search.loading && search.hasMore\" spinner=\"android\" on-infinite=\"showMore()\" distance=\"10%\"></ion-infinite-scroll>"); -$templateCache.put("plugins/es/templates/registry/lookup_popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink\" ng-click=\"showNewPageModal();\"><i class=\"icon ion-plus\"></i> <span translate>REGISTRY.BTN_NEW</span></a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/registry/lookup_popover_filters.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>COMMON.POPOVER_FILTER_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink\" ng-click=\"doGetLastRecords()\"><i class=\"icon ion-clock\"></i> {{\'REGISTRY.SEARCH.BTN_LAST_RECORDS\' | translate}} </a><a class=\"item item-icon-left ink\" ng-click=\"toggleAdvanced();\"><i class=\"icon ion-android-checkbox-outline-blank\" ng-show=\"!search.advanced\"></i> <i class=\"icon ion-android-checkbox-outline\" ng-show=\"search.advanced\"></i> <span translate>REGISTRY.SEARCH.POPOVER_FILTERS.BTN_ADVANCED_SEARCH</span></a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/registry/modal_record_type.html","<ion-modal-view><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title\" translate>{{getParameters().title||\'REGISTRY.TYPE.TITLE\'|translate}}</h1></ion-header-bar><ion-content class=\"lookupForm\"><div class=\"list padding\"><h3 translate>REGISTRY.TYPE.SELECT_TYPE</h3><button class=\"button button-block button-stable icon-left cion-page-shop\" ng-click=\"closeModal(\'shop\')\" translate>REGISTRY.TYPE.ENUM.SHOP</button> <button class=\"button button-block button-stable icon-left cion-page-association\" ng-click=\"closeModal(\'association\')\" translate>REGISTRY.TYPE.ENUM.ASSOCIATION</button> <button class=\"button button-block button-stable icon-left cion-page-company\" ng-click=\"closeModal(\'company\')\" translate>REGISTRY.TYPE.ENUM.COMPANY</button> <button class=\"button button-block button-stable icon-left cion-page-institution\" ng-click=\"closeModal(\'institution\')\" translate>REGISTRY.TYPE.ENUM.INSTITUTION</button></div></ion-content></ion-modal-view>"); -$templateCache.put("plugins/es/templates/registry/view_popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>REGISTRY.VIEW.MENU_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink\" ng-click=\"showSharePopover($event)\"><i class=\"icon ion-android-share-alt\"></i> {{\'COMMON.BTN_SHARE\' | translate}} </a><a class=\"item item-icon-left assertive ink\" ng-if=\"canEdit\" ng-click=\"delete()\"><i class=\"icon ion-trash-a\"></i> {{\'COMMON.BTN_DELETE\' | translate}}</a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/registry/view_record.html","<ion-view left-buttons=\"leftButtons\" class=\"view-page\"><ion-nav-title></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-bar button-icon button-clear visible-xs visible-sm\" ng-click=\"edit()\" ng-if=\"canEdit\"><i class=\"icon ion-android-create\"></i></button> <button class=\"button button-bar button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"></button></ion-nav-buttons><ion-content scroll=\"true\" class=\"refresher-top-bg\"><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"load()\"></ion-refresher><div class=\"hero\"><div class=\"content\" ng-if=\"!loading\"><i class=\"avatar cion-page-{{formData.type}}\" ng-if=\"!formData.avatar\"></i> <i class=\"avatar\" ng-style=\"{{avatarStyle}}\" ng-if=\"formData.avatar\"></i><h3><span class=\"dark\" ng-bind-html=\"formData.title\"></span></h3><h4> </h4></div><h4 class=\"content dark\" ng-if=\"loading\"><ion-spinner icon=\"android\"></ion-spinner></h4></div><div class=\"row no-padding-xs\"><div class=\"col list animate-fade-slide-in item-text-wrap no-padding-xs\"><div class=\"item\"><h2 class=\"gray\"><a ng-if=\"formData.city\" ui-sref=\"app.wot_lookup.tab_registry({location:formData.city})\"><i class=\"icon ion-location\"></i> <span ng-bind-html=\"formData.city\"></span> </a><span ng-if=\"formData.city && formData.type\"> | </span> <a ng-if=\"formData.type\" ui-sref=\"app.wot_lookup.tab_registry({type:formData.type})\"><i class=\"cion-page-{{formData.type}}\"></i> {{\'REGISTRY.TYPE.ENUM.\'+formData.type|upper|translate}}</a></h2><h4><i class=\"icon ion-clock\" ng-if=\"formData.time\"></i> <span translate=\"\">COMMON.SUBMIT_BY</span> <a ng-class=\"{\'positive\': issuer.uid, \'gray\': !issuer.uid}\" ui-sref=\"app.wot_identity({pubkey:issuer.pubkey, uid: issuer.name||issuer.uid})\"><ng-if ng-if=\"issuer.uid\"><i class=\"icon ion-person\"></i> {{::issuer.name||issuer.uid}}</ng-if><span ng-if=\"!issuer.uid\"><i class=\"icon ion-key\"></i> {{issuer.pubkey|formatPubkey}} </span></a><span>{{formData.time|formatFromNow}}<h4 class=\"gray hidden-xs\">| {{formData.time | formatDate}}</h4></span></h4></div><a id=\"registry-share-anchor-{{id}}\"></a><ion-item><h2 trust-as-html=\"formData.description\"></h2></ion-item><ion-item ng-if=\"formData.category || formData.address\"><h4 ng-if=\"formData.category\"><span class=\"gray\" translate=\"\">REGISTRY.VIEW.CATEGORY</span> <a class=\"positive\" ng-if=\"formData.category\" ui-sref=\"app.wot_lookup.tab_registry({category:formData.category.id})\"><span ng-bind-html=\"formData.category.name\"></span></a></h4><h4 ng-if=\"formData.address\"><span class=\"gray\" translate=\"\">REGISTRY.VIEW.LOCATION</span> <a class=\"positive\" target=\"_system\" href=\"https://www.openstreetmap.org/search?query={{formData.address}},%20{{formData.city}}\"><span ng-bind-html=\"formData.address\"></span> <span ng-if=\"formData.city\">- </span><span ng-bind-html=\"formData.city\"></span></a></h4></ion-item><ng-if ng-if=\"formData.socials && formData.socials.length>0\"><ion-item class=\"item-icon-left\" type=\"no-padding item-text-wrap\" ng-repeat=\"social in formData.socials track by social.url\" id=\"social-{{social.url|formatSlug}}\"><i class=\"icon ion-social-{{social.type}}\" ng-class=\"{\'ion-bookmark\': social.type == \'other\', \'ion-link\': social.type == \'web\', \'ion-email\': social.type == \'email\'}\"></i><p ng-if=\"social.type && social.type != \'web\'\">{{social.type}}</p><h2><a ng-click=\"openLink($event, social.url, social.type)\">{{social.url}}</a></h2></ion-item></ng-if><div class=\"item item-icon-left item-text-wrap ink\" ng-if=\"formData.pubkey\" copy-on-click=\"{{::formData.pubkey}}\"><i class=\"icon ion-key\"></i> <span translate=\"\">REGISTRY.EDIT.RECORD_PUBKEY</span><h4 class=\"dark\">{{::formData.pubkey}}</h4></div><div class=\"lazy-load\"><ng-include src=\"\'plugins/es/templates/common/view_pictures.html\'\"></ng-include><ng-include src=\"\'plugins/es/templates/common/view_comments.html\'\"></ng-include></div></div></div></ion-content><button class=\"button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm\" ng-if=\"formData.pubkey && !isUserPubkey(formData.pubkey)\" ng-click=\"showTransferModal({pubkey: formData.pubkey, uid: formData.title})\"></button></ion-view>"); -$templateCache.put("plugins/es/templates/registry/view_wallet_pages.html","<ion-view left-buttons=\"leftButtons\" class=\"view-notification\"><ion-nav-title>{{\'REGISTRY.MY_PAGES\' | translate}}</ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-loop visible-xs visible-sm\" ng-click=\"load()\"></button> <button class=\"button button-icon button-clear visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"><i class=\"icon ion-android-more-vertical\"></i></button></ion-nav-buttons><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><div class=\"center padding\" ng-if=\"search.loading\"><ion-spinner icon=\"android\"></ion-spinner></div><div class=\"center padding gray\" ng-if=\"!search.loading && !search.results.length\" translate=\"\">REGISTRY.NO_PAGE</div><ng-include src=\"\'plugins/es/templates/registry/lookup_list.html\'\"></ng-include></ion-content></ion-view>"); -$templateCache.put("plugins/es/templates/settings/plugin_settings.html","<ion-view left-buttons=\"leftButtons\" class=\"settings\"><ion-nav-title translate>ES_SETTINGS.PLUGIN_NAME</ion-nav-title><ion-content scroll=\"true\"><div class=\"item item-toggle dark\"><div class=\"input-label\" translate>ES_SETTINGS.ENABLE_TOGGLE</div><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.enable\"><div class=\"track\"><div class=\"handle\"></div></div></label></div><span class=\"item item-divider\" translate>SETTINGS.NETWORK_SETTINGS</span><div class=\"item ink\" ng-click=\"formData.enable && changeEsNode()\" ng-disabled=\"!formData.enable\"><div class=\"input-label\" ng-class=\"{\'gray\': !formData.enable}\">{{\'ES_SETTINGS.PEER\' | translate}}</div><ng-if ng-if=\"isFallbackNode\"><h4 class=\"gray text-wrap assertive\"><i class=\"icon ion-alert-circled\"></i> <span ng-bind-html=\"\'SETTINGS.PEER_CHANGED_TEMPORARY\' | translate \"></span></h4><div class=\"item-note assertive text-italic\">{{server}}</div></ng-if><span ng-if=\"!isFallbackNode\" class=\"item-note\" ng-class=\"{\'dark\': formData.enable}\">{{server}}</span></div><span class=\"item item-divider\" translate>ES_SETTINGS.NOTIFICATIONS.DIVIDER</span> <span class=\"item gray item-text-wrap\" translate>ES_SETTINGS.NOTIFICATIONS.HELP_TEXT</span><label class=\"item item-toggle dark item-text-wrap\"><span ng-class=\"{\'gray\': !formData.enable}\" translate>ES_SETTINGS.NOTIFICATIONS.ENABLE_TX_SENT</span><div class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.notifications.txSent\" ng-disabled=\"!formData.enable\"><div class=\"track\"><div class=\"handle\"></div></div></div></label><label class=\"item item-toggle dark item-text-wrap\"><span ng-class=\"{\'gray\': !formData.enable}\" translate>ES_SETTINGS.NOTIFICATIONS.ENABLE_TX_RECEIVED</span><label class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.notifications.txReceived\" ng-disabled=\"!formData.enable\"><div class=\"track\"><div class=\"handle\"></div></div></label></label><label class=\"item item-toggle dark item-text-wrap\"><span ng-class=\"{\'gray\': !formData.enable}\" translate>ES_SETTINGS.NOTIFICATIONS.ENABLE_CERT_SENT</span><div class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.notifications.certSent\" ng-disabled=\"!formData.enable\"><div class=\"track\"><div class=\"handle\"></div></div></div></label><label class=\"item item-toggle dark item-text-wrap\"><span ng-class=\"{\'gray\': !formData.enable}\" translate>ES_SETTINGS.NOTIFICATIONS.ENABLE_CERT_RECEIVED</span><div class=\"toggle toggle-royal\"><input type=\"checkbox\" ng-model=\"formData.notifications.certReceived\" ng-disabled=\"!formData.enable\"><div class=\"track\"><div class=\"handle\"></div></div></div></label><cs-extension-point name=\"common\"></cs-extension-point></ion-content></ion-view>"); -$templateCache.put("plugins/es/templates/settings/settings_extend.html","<div class=\"item item-text-wrap item-icon-right ink\" ui-sref=\"app.es_settings\"><div class=\"input-label ng-binding\" translate>ES_SETTINGS.PLUGIN_NAME</div><h4 class=\"gray\" translate>ES_SETTINGS.PLUGIN_NAME_HELP</h4><i class=\"icon ion-ios-arrow-right\"></i></div>"); -$templateCache.put("plugins/es/templates/subscription/edit_subscriptions.html","<ion-view left-buttons=\"leftButtons\" class=\"view-notification\"><ion-nav-title>{{\'SUBSCRIPTION.EDIT.TITLE\' | translate}}</ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear icon ion-loop visible-xs visible-sm\" ng-click=\"load()\"></button> <button class=\"button button-icon button-clear visible-xs visible-sm\" ng-click=\"showActionsPopover($event)\"><i class=\"icon ion-android-more-vertical\"></i></button></ion-nav-buttons><ion-content class=\"padding no-padding-xs\" scroll=\"true\"><div class=\"center padding\" ng-if=\"search.loading\"><ion-spinner icon=\"android\"></ion-spinner></div><div class=\"center padding gray\" ng-if=\"!search.loading && !search.results.length\" translate=\"\">SUBSCRIPTION.NO_SUBSCRIPTION</div><div class=\"row no-padding\"><div class=\"col list {{::motion.ionListClass}} item-border-large\"><ng-repeat ng-repeat=\"subscriptions in search.results | filter: { type: \'email\' }\" ng-include=\"\'plugins/es/templates/subscription/item_\' + subscriptions.type.toLowerCase() + \'_subscription.html\'\">></ng-repeat></div></div></ion-content></ion-view>"); -$templateCache.put("plugins/es/templates/subscription/item_email_subscription.html","<div class=\"item item-thumbnail-left\"><i class=\"item-image icon ion-email\"></i><h3>{{\'SUBSCRIPTION.TYPE.ENUM.\' + subscriptions.type.toUpperCase() | translate}}</h3><h4 class=\"gray\">{{\'SUBSCRIPTION.EDIT.PROVIDER\'|translate}} <a ui-sref=\"app.wot_identity({pubkey: subscriptions.recipient, uid: subscriptions.uid})\"><span ng-class=\"{\'positive\': subscriptions.uid, \'dark\': !subscriptions.uid}\" ng-if=\"subscriptions.name||subscriptions.uid\"><i class=\"ion-person\" ng-if=\"subscriptions.uid\"></i> {{subscriptions.name||subscriptions.uid}} </span><span class=\"gray\" ng-if=\"!subscriptions.uid\"><i class=\"ion-key\"></i> {{subscriptions.recipient | formatPubkey}}</span></a></h4><div class=\"item-note text-right\"><span ng-repeat=\"item in subscriptions.items\">{{item.content.email}} <a class=\"ion-trash-a gray padding-left\" ng-click=\"deleteSubscription(item)\"></a> <a class=\"ion-edit gray padding-left\" ng-click=\"editSubscription(item)\"></a><br></span></div></div>"); -$templateCache.put("plugins/es/templates/subscription/modal_email.html","<ion-modal-view id=\"composeMessage\" class=\"modal-full-height\"><ion-header-bar class=\"bar-positive\"><button class=\"button button-clear visible-xs\" ng-click=\"closeModal()\" translate>COMMON.BTN_CANCEL</button><h1 class=\"title\" translate>SUBSCRIPTION.MODAL_EMAIL.TITLE</h1><button class=\"button button-icon button-clear icon ion-android-send visible-xs\" ng-click=\"doSubmit()\"></button></ion-header-bar><ion-content scroll=\"true\"><div class=\"item item-icon-left item-text-wrap\"><i class=\"icon ion-ios-information-outline positive\"></i><h4 class=\"positive\" translate>SUBSCRIPTION.MODAL_EMAIL.HELP</h4></div><form name=\"subscriptionForm\" novalidate=\"\" ng-submit=\"doSubmit()\"><div class=\"list\" ng-init=\"setForm(subscriptionForm)\"><label class=\"item item-input\" ng-class=\"{\'item-input-error\': form.$submitted && (form.email.$invalid || form.email.$error)}\"><span class=\"input-label\" translate>SUBSCRIPTION.MODAL_EMAIL.EMAIL_LABEL</span> <input name=\"email\" type=\"text\" placeholder=\"{{\'SUBSCRIPTION.MODAL_EMAIL.EMAIL_HELP\' | translate}}\" ng-model=\"formData.content.email\" ng-minlength=\"3\" required email></label><div class=\"form-errors\" ng-if=\"form.$submitted && (form.email.$invalid || form.email.$error)\" ng-messages=\"form.email.$error\"><div class=\"form-error\" ng-message=\"minlength\"><span translate=\"ERROR.FIELD_TOO_SHORT\"></span></div><div class=\"form-error\" ng-message=\"email\"><span translate=\"ERROR.FIELD_NOT_EMAIL\"></span></div></div><label class=\"item item-input item-select\" ng-class=\"{\'item-input-error\': form.$submitted && !formData.content.frequency}\"><span class=\"input-label\" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_LABEL</span><select name=\"frequency\" ng-model=\"formData.content.frequency\" style=\"height: 46px;margin-top: 1px\"><option value=\"weekly\" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_WEEKLY</option><option value=\"daily\" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_DAILY</option></select></label><div class=\"form-errors\" ng-if=\"form.$submitted && !formData.content.frequency\"><div class=\"form-error\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div><a class=\"item item-input item-icon-right gray ink\" ng-class=\"{\'item-input-error\': form.$submitted && !formData.recipient}\" ng-click=\"showNetworkLookup()\" style=\"height: 67px\"><span class=\"input-label\" translate>SUBSCRIPTION.MODAL_EMAIL.PROVIDER</span> <span class=\"badge animate-fade-in animate-show-hide ng-hide\" ng-class=\"{\'badge-royal\': recipient.uid, \'badge-stable\': !recipient.uid}\" ng-show=\"recipient && (recipient.name||recipient.uid)\"><i class=\"ion-person\" ng-if=\"recipient.uid\"></i> {{recipient.name||recipient.uid}} </span><span class=\"badge badge-secondary animate-fade-in animate-show-hide ng-hide\" ng-show=\"formData.recipient\"><i class=\"ion-key\"></i> {{formData.recipient | formatPubkey}} </span><i class=\"gray icon ion-ios-arrow-right\"></i></a><div class=\"form-errors\" ng-if=\"form.$submitted && !formData.recipient\"><div class=\"form-error\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div></div></div><div class=\"padding hidden-xs text-right\"><button class=\"button button-small button-clear button-dark ink\" ng-click=\"cancel()\" type=\"button\" translate>COMMON.BTN_CANCEL</button> <button class=\"button button-small button-positive ink\" type=\"submit\">{{\'COMMON.BTN_SEND\' | translate}}</button></div></form></ion-content></ion-modal-view>"); -$templateCache.put("plugins/es/templates/user/edit_popover_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left assertive ink\" ng-click=\"removeProfile()\"><i class=\"icon ion-trash-a\"></i> {{\'PROFILE.BTN_DELETE\' | translate}}</a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/user/edit_profile.html","<ion-view left-buttons=\"leftButtons\"><ion-nav-title></ion-nav-title><ion-nav-buttons side=\"secondary\"><button class=\"button button-icon button-clear button-assertive ion-trash-a visible-xs visible-sm\" ng-click=\"removeProfile()\" ng-if=\"existing\"></button> <button class=\"button button-icon button-clear ion-android-done visible-xs visible-sm\" ng-click=\"submitAndSaveAndClose()\"></button></ion-nav-buttons><ion-content scroll=\"true\"><div class=\"positive-900-bg hero\"><div class=\"content\"><i class=\"avatar\" ng-style=\"avatarStyle\" ng-class=\"{\'avatar-wallet\': !loading && !avatar && walletData && !walletData.isMember, \'avatar-member\': !loading && !avatar && walletData.isMember}\"><button class=\"button button-positive button-large button-clear flat icon ion-camera visible-xs visible-sm\" style=\"display: inline-block\" ng-click=\"showAvatarModal()\"></button> <button ng-if=\"avatar.src\" class=\"button button-positive button-large button-clear flat visible-xs visible-sm\" style=\"display: inline-block; left: 85px; bottom:15px\" ng-click=\"rotateAvatar()\"><i class=\"icon-secondary ion-image\" style=\"left: 24px; top: 3px; font-size: 24px\"></i> <i class=\"icon-secondary ion-forward\" style=\"left: 26px; top: -13px\"></i></button></i><h3 class=\"light\"><ng-if ng-if=\"!loading && !formData.title && walletData && walletData.isMember\">{{walletData.uid}}</ng-if><ng-if ng-if=\"!loading && !formData.title && walletData && !walletData.isMember\">{{::walletData.pubkey | formatPubkey}}</ng-if><ng-if ng-if=\"!loading && formData.title\">{{formData.title}}</ng-if></h3><h4 class=\"light\"><ion-spinner ng-if=\"loading\" icon=\"android\"></ion-spinner></h4></div></div><div class=\"row no-padding\"><div class=\"col\"><form name=\"profileForm\" novalidate=\"\" ng-submit=\"saveAndClose()\"><div class=\"list item-text-wrap {{::motion.ionListClass}}\" ng-init=\"setForm(profileForm)\"><div class=\"item item-icon-left item-text-wrap\"><i class=\"icon ion-ios-information-outline positive\"></i><h4 class=\"positive\" translate=\"\">PROFILE.HELP.WARNING_PUBLIC_DATA</h4></div><div class=\"item item-divider\">{{\'PROFILE.GENERAL_DIVIDER\' | translate}}</div><ion-item class=\"item-input item-floating-label item-button-right\" ng-class=\"{\'item-input-error\': form.$submitted && form.title.$invalid}\"><span class=\"input-label\">{{\'PROFILE.TITLE\' | translate}}</span> <input type=\"text\" name=\"title\" placeholder=\"{{\'PROFILE.TITLE_HELP\' | translate}}\" id=\"profile-name\" ng-model=\"formData.title\" ng-model-options=\"{ debounce: 350 }\" ng-maxlength=\"50\" required></ion-item><div class=\"form-errors\" ng-show=\"form.$submitted && form.title.$error\" ng-messages=\"form.title.$error\"><div class=\"form-error\" ng-message=\"required\"><span translate=\"ERROR.FIELD_REQUIRED\"></span></div><div class=\"form-error\" ng-message=\"maxlength\"><span translate=\"ERROR.FIELD_TOO_LONG_WITH_LENGTH\" translate-values=\"{maxLength: 50}\"></span></div></div><ion-item class=\"item-input item-floating-label item-button-right\"><span class=\"input-label\" style=\"width: 100%\">{{\'PROFILE.DESCRIPTION\' | translate}}</span><textarea placeholder=\"{{\'PROFILE.DESCRIPTION_HELP\' | translate}}\" ng-model=\"formData.description\" ng-model-options=\"{ debounce: 350 }\" rows=\"4\" cols=\"10\">\n </textarea></ion-item><ng-include src=\"\'plugins/es/templates/common/edit_position.html\'\" ng-controller=\"ESPositionEditCtrl as ctrl\"></ng-include></div><ng-include src=\"\'plugins/es/templates/common/edit_socials.html\'\" ng-controller=\"ESSocialsEditCtrl\"></ng-include><div class=\"list item-text-wrap {{::motion.ionListClass}}\"><div class=\"item item-divider\">{{\'PROFILE.TECHNICAL_DIVIDER\' | translate}}</div><ion-item class=\"item-icon-left\" ng-if=\"walletData && walletData.uid\"><span translate=\"\">COMMON.UID</span> <span class=\"badge badge-stable\">{{::walletData.uid}}</span></ion-item><ion-item class=\"item-icon-left item-icon-right item-text-wrap ink\" on-hold=\"copy(formData.pubkey)\" copy-on-click=\"\"><i class=\"icon ion-key\"></i> <span translate=\"\">COMMON.PUBKEY</span><p class=\"gray\">{{walletData.pubkey}}</p></ion-item></div></form></div></div></ion-content></ion-view>"); -$templateCache.put("plugins/es/templates/user/items_profile.html","<div ng-if=\"!formData.profile && !formData.name\" class=\"item gray\" translate>PROFILE.NO_PROFILE_DEFINED</div><div class=\"item\" ng-if=\"formData.name && showName\"><span class=\"gray\" translate>PROFILE.TITLE</span><h3>{{formData.name}}</h3></div><div class=\"item item-text-wrap\" ng-if=\"formData.profile.description\"><span class=\"gray\" translate>PROFILE.DESCRIPTION</span><h3 trust-as-html=\"formData.profile.description\"></h3></div><div class=\"item\" ng-if=\"formData.profile.address || formData.profile.city\" copy-on-click=\"{{formData.profile.address ? formData.profile.address + \' \' : \'\'}}{{formData.profile.city}}\"><span class=\"gray\" translate>LOCATION.LOCATION_DIVIDER</span><h3><span class=\"text-keep-lines\" ng-if=\"formData.profile.address\">{{formData.profile.address}}<br></span>{{formData.profile.city}}</h3></div><div class=\"item\" ng-if=\"formData.profile.socials && formData.profile.socials.length\" ng-controller=\"ESSocialsViewCtrl\"><span class=\"gray\" translate>PROFILE.SOCIAL_NETWORKS_DIVIDER</span><div class=\"list no-padding\"><ion-item ng-repeat=\"social in formData.profile.socials | filter:filterFn track by social.url \" id=\"social-{{::social.url|formatSlug}}\" class=\"item-icon-left item-text-wrap no-padding-bottom ink\" on-tap=\"openSocial($event, social)\"><i class=\"icon ion-social-{{social.type}}\" ng-class=\"{\'ion-bookmark\': social.type == \'other\', \'ion-link\': social.type == \'web\', \'ion-email\': social.type == \'email\', \'ion-iphone\': social.type == \'phone\'}\"></i><p ng-if=\"social.type && social.type != \'web\'\">{{social.type}} <i class=\"ion-locked\" ng-if=\"social.recipient\"></i></p><h4><a on-tap=\"openSocial($event, social)\" href=\"{{::social.url}}\" target=\"_blank\">{{::social.url}}</a></h4></ion-item></div></div>"); -$templateCache.put("plugins/es/templates/wallet/view_wallet_extend.html","<ng-if ng-if=\"enable\"><div class=\"item item-divider item-divider-top-border\"><span>{{\'PROFILE.PROFILE_DIVIDER\' | translate}} <i style=\"font-size: 12pt; cursor: pointer\" ng-click=\"showProfileHelp=!showProfileHelp\" class=\"icon positive ion-ios-help-outline\" title=\"{{\'PROFILE.PROFILE_DIVIDER_HELP\' | translate}}\"></i> </span><a class=\"badge button button-text button-small button-small-padding\" ui-sref=\"app.user_edit_profile\"><i class=\"icon ion-edit\"></i> <span ng-if=\"!formData.profile\" translate>PROFILE.BTN_ADD</span> <span ng-if=\"formData.profile\" translate>PROFILE.BTN_EDIT</span></a></div><div class=\"item item-text-wrap positive item-small-height\" ng-show=\"showProfileHelp\"><small translate>PROFILE.PROFILE_DIVIDER_HELP</small></div><div class=\"double-padding-x padding-bottom\"><ng-include src=\"\'plugins/es/templates/user/items_profile.html\'\" ng-init=\"showName=true;\"></ng-include></div><div class=\"item item-divider item-divider-top-border\"><span>{{\'SUBSCRIPTION.SUBSCRIPTION_DIVIDER\' | translate}} <i style=\"font-size: 12pt; cursor: pointer\" ng-click=\"showSubscriptionHelp=!showSubscriptionHelp\" class=\"icon positive ion-ios-help-outline\" title=\"{{\'SUBSCRIPTION.SUBSCRIPTION_DIVIDER_HELP\' | translate}}\"></i> <span><a class=\"badge button button-text button-small button-small-padding\" ng-if=\"!formData.subscriptions.count\" ui-sref=\"app.edit_subscriptions\"><i class=\"icon ion-edit\"></i> <span translate>SUBSCRIPTION.BTN_ADD</span></a></span></span></div><div class=\"item item-text-wrap positive item-small-height\" ng-show=\"showSubscriptionHelp\"><small translate>SUBSCRIPTION.SUBSCRIPTION_DIVIDER_HELP</small></div><div class=\"double-padding-x padding-bottom\"><div ng-if=\"!formData.subscriptions.count\" class=\"item gray\" translate>SUBSCRIPTION.NO_SUBSCRIPTION</div><a class=\"item item-icon-left item-text-wrap item-icon-right ink\" ng-if=\"formData.subscriptions.count\" ui-sref=\"app.edit_subscriptions\"><i class=\"icon ion-gear-a\"></i> <span translate>SUBSCRIPTION.SUBSCRIPTION_COUNT</span> <span class=\"badge badge-calm\">{{formData.subscriptions.count}}</span> <i class=\"gray icon ion-ios-arrow-right\"></i></a></div><div class=\"item item-divider item-divider-top-border\"><span>{{\'REGISTRY.WALLET.REGISTRY_DIVIDER\' | translate}} <i style=\"font-size: 12pt; cursor: pointer\" ng-click=\"showPagesHelp=!showPagesHelp\" class=\"icon positive ion-ios-help-outline\" title=\"{{\'REGISTRY.WALLET.REGISTRY_HELP\' | translate}}\"></i> <span><a class=\"badge button button-text button-small button-small-padding\" ng-if=\"!formData.pages.count\" ng-click=\"showNewPageModal()\"><i class=\"icon ion-edit\"></i> <span translate>REGISTRY.BTN_NEW</span></a></span></span></div><div class=\"item item-text-wrap positive item-small-height\" ng-show=\"showPagesHelp\"><small translate>REGISTRY.WALLET.REGISTRY_HELP</small></div><div class=\"double-padding-x padding-bottom\"><div ng-if=\"!formData.pages.count\" class=\"item gray\" translate>REGISTRY.NO_PAGE</div><a class=\"item item-icon-left item-text-wrap item-icon-right ink\" ng-if=\"formData.pages.count\" ui-sref=\"app.wallet_pages\"><i class=\"icon ion-social-buffer\"></i> <span translate>REGISTRY.MY_PAGES</span> <span class=\"badge badge-calm\">{{formData.pages.count}}</span> <i class=\"gray icon ion-ios-arrow-right\"></i></a></div></ng-if>"); -$templateCache.put("plugins/es/templates/wot/lookup_extend.html","<ion-tab title=\"{{\'MENU.REGISTRY\'|translate}}\" icon=\"ion-social-buffer\" ui-sref=\"app.wot_lookup.tab_registry\"><ion-nav-view name=\"tab_registry\"></ion-nav-view></ion-tab>"); -$templateCache.put("plugins/es/templates/wot/lookup_item_group.html","<i ng-if=\"::!item.avatar\" class=\"item-image icon ion-android-people\"></i> <i ng-if=\"::!item.avatar\" class=\"item-image icon-secondary ion-android-lock\" style=\"left: 20px; top: 17px; font-size: 19px; color: #d9d9d9\"></i> <i ng-if=\"::item.avatar\" class=\"item-image avatar\" style=\"background-image: url({{::item.avatar.src}})\"></i><h2 ng-bind-html=\":rebind:item.name\"></h2><h4 class=\"gray\"><i class=\"ion-clock\"></i> {{:rebind:\'GROUP.CREATED_TIME\'|translate: item }}</h4><h4 class=\"dark pull-left\" ng-if=\":rebind:item.membersCount\"><i class=\"dark ion-person\"></i> <span class=\"dark\">+{{:rebind:item.membersCount}}</span></h4><h4 class=\"dark\"><span class=\"dark\" ng-if=\"::item.description\"><i class=\"ion-quote\"></i> {{::item.description|truncText}}</span></h4><h4 ng-if=\"::item.tags\"><span ng-if=\"::item.tags\" class=\"dark\"><ng-repeat ng-repeat=\"tag in ::item.tags\">#<ng-bind-html ng-bind-html=\"::tag\"></ng-bind-html></ng-repeat></span></h4>"); -$templateCache.put("plugins/es/templates/wot/lookup_item_page.html","<i ng-if=\"::!item.avatar\" class=\"item-image icon cion-page-{{item.type}}\"></i> <i ng-if=\"::item.avatar\" class=\"item-image avatar\" style=\"background-image: url({{::item.avatar.src}})\"></i><h2 ng-bind-html=\":rebind:item.name\"></h2><h4 class=\"gray\"><span class=\"gray\" ng-if=\"::item.city\"><i class=\"ion-location\"></i> {{::item.city|truncText}} </span><span ng-if=\"::item.city && item.type\">|</span> <span ng-if=\"item.type\"><i class=\"cion-page-{{item.type}}\"></i> {{::\'REGISTRY.TYPE.ENUM.\'+item.type|uppercase|translate}}</span></h4><h4 class=\"dark\"><span class=\"dark\" ng-if=\"::item.description\"><i class=\"ion-quote\"></i> {{::item.description|truncText}}</span></h4><h4 ng-if=\"::item.tags\"><span ng-if=\"::item.tags\" class=\"dark\"><ng-repeat ng-repeat=\"tag in ::item.tags\">#<ng-bind-html ng-bind-html=\"::tag\"></ng-bind-html></ng-repeat></span></h4>"); -$templateCache.put("plugins/es/templates/wot/lookup_lg_extend.html","<div class=\"buttons-tabs\"><div class=\"pull-right\"><div class=\"button button-tab dark\" title=\"{{\'REGISTRY.BTN_SHOW_WOT_HELP\' | translate}}\" nav-transition=\"none\" active-link=\"active\" active-link-path-prefix=\"#/app/wot/lg\" ui-sref=\"app.wot_lookup_lg\"><i class=\"icon ion-person-stalker\"></i> {{\'REGISTRY.BTN_SHOW_WOT\' | translate}}</div><a class=\"button button-tab ink dark\" title=\"{{\'REGISTRY.BTN_SHOW_PAGES_HELP\' | translate}}\" nav-transition=\"none\" active-link=\"active\" active-link-path-prefix=\"#/app/wot/page\" ui-sref=\"app.registry_lookup_lg\"><i class=\"icon ion-social-buffer\"></i> {{\'REGISTRY.BTN_SHOW_PAGES\' | translate}}</a></div><div class=\"pull-right\" ng-if=\"showNewPageButton\"> </div></div>"); -$templateCache.put("plugins/es/templates/wot/popover_certification_actions.html","<ion-popover-view class=\"fit has-header\"><ion-header-bar><h1 class=\"title\" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll=\"false\"><div class=\"list item-text-wrap\"><a class=\"item item-icon-left ink\" ng-if=\"!isUserPubkey(formData.pubkey) && formData.isMember\" ng-click=\"askCertification()\"><i class=\"icon-secondary ion-ribbon-b\" style=\"left: 16px; top: 0px; font-size: 25px\"></i> <b class=\"icon-secondary ion-help\" style=\"left: 35px; top: 0px\"></b> {{\'WOT.BTN_ASK_CERTIFICATION\' | translate}} </a><a class=\"item item-icon-left ink\" ng-if=\"isUserPubkey(formData.pubkey)\" ng-click=\"showAskCertificationModal()\"><i class=\"icon-secondary ion-ribbon-b\" style=\"left: 16px; top: 0px; font-size: 25px\"></i> <b class=\"icon-secondary ion-help\" style=\"left: 35px; top: 0px\"></b> {{\'WOT.BTN_ASK_CERTIFICATIONS_DOTS\' | translate}} </a><a class=\"item item-icon-left ink\" ng-if=\"!isUserPubkey(formData.pubkey)\" ng-click=\"showSuggestCertificationModal()\"><i class=\"icon-secondary ion-person-stalker\" style=\"left: 16px; top: 0px; font-size: 25px\"></i> <b class=\"icon-secondary ion-help\" style=\"left: 37px; top: -4px\"></b> {{\'WOT.BTN_SUGGEST_CERTIFICATIONS_DOTS\' | translate}}</a></div></ion-content></ion-popover-view>"); -$templateCache.put("plugins/es/templates/wot/view_certifications_extend.html","<ng-if ng-if=\"enable && extensionPoint === \'nav-buttons\'\"><button class=\"button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm\" ng-click=\"showCertificationActionsPopover($event)\"></button></ng-if><ng-if ng-if=\"enable && extensionPoint === \'buttons\'\"><button class=\"button button-stable button-small-padding icon ion-android-more-vertical\" ng-click=\"showCertificationActionsPopover($event)\" title=\"{{\'COMMON.POPOVER_ACTIONS_TITLE\' | translate}}\"></button></ng-if>"); -$templateCache.put("plugins/es/templates/wot/view_identity_extend.html","<ng-if ng-if=\"enable && extensionPoint === \'buttons\'\"><button class=\"button button-stable button-small-padding icon ion-compose\" ng-click=\"showNewMessageModal()\" title=\"{{\'MESSAGE.BTN_WRITE\' | translate}}\"></button></ng-if><ng-if ng-if=\"enable && extensionPoint === \'after-general\'\"><span class=\"item item-divider item-divider-top-border\"><span>{{\'PROFILE.PROFILE_DIVIDER\' | translate}} <a style=\"font-size: 12pt; cursor: pointer\" ng-click=\"showProfileHelp=!showProfileHelp\" class=\"icon positive ion-ios-help-outline ink\" title=\"{{\'PROFILE.PROFILE_DIVIDER_HELP\' | translate}}\"></a></span></span><div class=\"item item-text-wrap positive item-small-height\" ng-show=\"showProfileHelp\"><small translate>PROFILE.PROFILE_DIVIDER_HELP</small></div><div class=\"double-padding-x padding-bottom\"><ng-include src=\"\'plugins/es/templates/user/items_profile.html\'\" ng-init=\"showName=false;\"></ng-include></div></ng-if>"); -$templateCache.put("plugins/graph/templates/account/graph_balance.html","\n <!-- button bar -->\n <div class=\"button-bar-inline \"\n style=\"top: 33px; margin-top:-33px; position: relative;\">\n <button\n class=\"button button-stable button-clear no-padding-xs pull-right\"\n ng-click=\"showActionsPopover($event)\">\n <i class=\"icon ion-navicon-round\"></i>\n </button>\n </div>\n\n <div class=\"padding-left padding-right\">\n <canvas id=\"account-balance\" class=\"chart-bar\"\n height=\"{{height}}\" width=\"{{width}}\"\n chart-data=\"data\"\n chart-dataset-override=\"datasetOverride\"\n chart-colors=\"colors\"\n chart-options=\"options\"\n chart-labels=\"labels\"\n chart-click=\"onChartClick\">\n </canvas>\n </div>\n\n <ng-include src=\"\'plugins/graph/templates/common/graph_range_bar.html\'\"></ng-include>\n"); -$templateCache.put("plugins/graph/templates/account/graph_certifications.html","\n <div class=\"padding-left padding-right\">\n <canvas id=\"account-certifications\" class=\"chart-bar\"\n height=\"{{height}}\" width=\"{{width}}\"\n chart-data=\"data\"\n chart-dataset-override=\"datasetOverride\"\n chart-colors=\"colors\"\n chart-options=\"options\"\n chart-labels=\"labels\"\n chart-click=\"onChartClick\">\n </canvas>\n </div>\n"); -$templateCache.put("plugins/graph/templates/account/graph_sum_tx.html","<div class=\"row responsive-sm\" ng-if=\"!loading\">\n\n <div class=\"col col-10 hidden-xs hidden-sm\"> </div>\n\n <div class=\"col text-center\">\n\n <!-- [NEW] TX input chart -->\n <p class=\"gray padding text-wrap\"\n ng-if=\"inputChart.data.length\"\n translate>GRAPH.ACCOUNT.INPUT_CHART_TITLE</p>\n <canvas id=\"chart-received-pie\" class=\"chart-pie\"\n chart-data=\"inputChart.data\"\n chart-labels=\"inputChart.labels\"\n chart-colors=\"inputChart.colors\"\n chart-click=\"onInputChartClick\">\n </canvas>\n\n </div>\n\n <div class=\"col col-10 hidden-xs hidden-sm\"> </div>\n\n <div class=\"col text-center\">\n\n <!-- [NEW] TX input chart -->\n <p class=\"gray padding text-wrap\"\n ng-if=\"outputChart.data.length\"\n translate>GRAPH.ACCOUNT.OUTPUT_CHART_TITLE</p>\n <canvas id=\"chart-sent-pie\" class=\"chart-pie\"\n chart-data=\"outputChart.data\"\n chart-labels=\"outputChart.labels\"\n chart-colors=\"outputChart.colors\"\n chart-click=\"onOutputChartClick\">\n </canvas>\n\n </div>\n\n <div class=\"col col-10 hidden-xs hidden-sm\"> </div>\n\n</div>\n"); -$templateCache.put("plugins/graph/templates/account/view_identity_extend.html","<!-- Buttons section -->\n<ng-if ng-if=\"extensionPoint === \'buttons\'\">\n\n <button class=\"button button-stable button-small-padding icon ion-stats-bars\"\n ng-click=\"showIdentityStats()\"\n title=\"{{\'GRAPH.ACCOUNT.BTN_SHOW_STATS\' | translate}}\">\n </button>\n\n</ng-if>\n"); -$templateCache.put("plugins/graph/templates/account/view_identity_tx_extend.html","<!-- Buttons section -->\n<ng-if ng-if=\"extensionPoint === \'buttons\'\">\n\n <button class=\"button button-stable button-small-padding icon ion-stats-bars\"\n ng-click=\"showIdentityStats()\"\n title=\"{{\'GRAPH.ACCOUNT.BTN_SHOW_STATS\' | translate}}\">\n </button>\n\n</ng-if>\n"); -$templateCache.put("plugins/graph/templates/account/view_stats.html","<ion-view left-buttons=\"leftButtons\"\n cache-view=\"false\">\n <ion-nav-title>\n {{\'GRAPH.ACCOUNT.TITLE\' | translate}}{{id}}\n </ion-nav-title>\n\n <ion-content scroll=\"true\" class=\"no-padding\">\n\n\n\n <div class=\"list\" >\n\n <!-- - - - - Balance - - - - -->\n <ng-controller ng-controller=\"GpAccountBalanceCtrl\">\n <div class=\"center padding\" ng-if=\"loading\">\n <ion-spinner icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"item item-divider\" ng-if=\"!loading\" >\n {{\'GRAPH.ACCOUNT.BALANCE_DIVIDER\'|translate}}\n <ion-spinner ng-if=\"loadingRange\" class=\"ion-spinner-small\" icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"item no-padding-xs\"\n ng-if=\"!loading\"\n ng-include=\"\'plugins/graph/templates/account/graph_balance.html\'\"\n ng-init=\"setSize(350, 1000)\">\n </div>\n </ng-controller>\n\n </div>\n\n <div class=\"item no-padding-xs\"\n ng-include=\"\'plugins/graph/templates/account/graph_sum_tx.html\'\"\n ng-controller=\"GpAccountSumTxCtrl\">\n </div>\n\n <!-- - - - - WOT - - - - -->\n <!--<div class=\"item item-divider\" translate>\n GRAPH.ACCOUNT.WOT_DIVIDER\n </div>\n\n <div class=\"item no-padding-xs\"\n ng-include=\"\'plugins/graph/templates/account/graph_certifications.html\'\"\n ng-controller=\"GpAccountCertificationCtrl\"\n ng-init=\"setSize(350, 1000)\">\n </div>-->\n\n </ion-content>\n\n</ion-view>\n"); -$templateCache.put("plugins/graph/templates/account/view_wallet_tx_extend.html","<!-- Buttons section -->\n<ng-if ng-if=\"extensionPoint === \'buttons\'\">\n\n <button class=\"button button-stable button-small-padding icon ion-stats-bars\"\n ng-click=\"showWalletStats()\"\n title=\"{{\'GRAPH.ACCOUNT.BTN_SHOW_STATS\' | translate}}\">\n </button>\n\n</ng-if>\n"); -$templateCache.put("plugins/graph/templates/blockchain/graph_block_issuers.html","\n <div class=\"row responsive-lg\">\n\n <!-- bar -->\n <div class=\"col col-75\">\n <canvas id=\"bar\" class=\"chart-bar\"\n height=\"{{height}}\" width=\"{{width}}\"\n chart-data=\"data\"\n chart-labels=\"labels\"\n chart-colors=\"colors\"\n chart-options=\"barOptions\"\n chart-click=\"onChartClick\">\n </canvas>\n </div>\n\n <!-- pie -->\n <div class=\"col col-25 padding-top\">\n <canvas id=\"blocksByIssuer-pie\" class=\"chart-pie\"\n chart-data=\"data\"\n chart-labels=\"labels\"\n chart-colors=\"colors\"\n chart-click=\"onChartClick\">\n </canvas>\n\n <div class=\"gray padding-top text-center\">\n <small ng-bind-html=\"\'GRAPH.BLOCKCHAIN.BLOCKS_ISSUERS_HELP\'| translate:{issuerCount: data.length, blockCount: blockCount }\"></small>\n </div>\n </div>\n </div>\n"); -$templateCache.put("plugins/graph/templates/blockchain/graph_tx_count.html","\n <!-- button bar -->\n <div class=\"button-bar-inline \"\n style=\"top: 33px; margin-top:-33px; position: relative;\">\n <button\n class=\"button button-stable button-clear no-padding-xs pull-right\"\n ng-click=\"showActionsPopover($event)\">\n <i class=\"icon ion-navicon-round\"></i>\n </button>\n </div>\n\n <div class=\"padding-left padding-right\">\n <canvas id=\"tx-line\" class=\"chart-bar\"\n height=\"{{height}}\" width=\"{{width}}\"\n chart-data=\"data\"\n chart-dataset-override=\"datasetOverride\"\n chart-colors=\"colors\"\n chart-options=\"options\"\n chart-labels=\"labels\"\n chart-click=\"onChartClick\">\n </canvas>\n </div>\n\n <ng-include src=\"\'plugins/graph/templates/common/graph_range_bar.html\'\"></ng-include>\n"); -$templateCache.put("plugins/graph/templates/blockchain/view_stats.html","<ion-view left-buttons=\"leftButtons\"\n cache-view=\"false\">\n <ion-nav-title>\n {{\'GRAPH.BLOCKCHAIN.TITLE\' | translate}}{{id}}\n </ion-nav-title>\n\n <ion-content scroll=\"true\" class=\"no-padding\">\n\n <div class=\"center padding\" ng-if=\"loading\">\n <ion-spinner icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"list\" ng-if=\"!loading\">\n\n\n <!-- TX count -->\n <ng-controller ng-controller=\"GpBlockchainTxCountCtrl\">\n <div class=\"center padding\" ng-if=\"loading\">\n <ion-spinner icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"item item-divider\" ng-if=\"!loading\" >\n {{\'GRAPH.BLOCKCHAIN.TX_DIVIDER\'|translate}}\n <ion-spinner ng-if=\"loadingRange\" class=\"ion-spinner-small\" icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"item no-padding-xs\"\n ng-if=\"!loading\"\n ng-include=\"\'plugins/graph/templates/blockchain/graph_tx_count.html\'\"\n ng-init=\"setSize(350, 1000)\">\n </div>\n </ng-controller>\n\n\n <!-- Blocks issuer -->\n <ng-controller ng-controller=\"GpBlockchainIssuersCtrl\">\n\n <div class=\"item item-divider\" ng-if=\"!loading\" translate>GRAPH.BLOCKCHAIN.BLOCKS_ISSUERS_DIVIDER</div>\n\n <div class=\"item no-padding-xs\"\n ng-if=\"!loading\"\n ng-include=\"\'plugins/graph/templates/blockchain/graph_block_issuers.html\'\"\n ng-init=\"setSize(300, 750)\">\n </div>\n\n </ng-controller>\n\n </ion-content>\n\n</ion-view>\n"); -$templateCache.put("plugins/graph/templates/common/graph_range_bar.html","\n <div class=\"range range-positive no-padding-left no-padding-right\">\n <a\n class=\"button button-stable button-clear no-padding pull-left\"\n ng-click=\"goPreviousRange($event)\">\n <i class=\"icon ion-chevron-left\"></i>\n </a>\n <input type=\"range\"\n ng-model=\"formData.timePct\"\n name=\"timePct\"\n min=\"0\" max=\"100\"\n value=\"{{formData.timePct}}\"\n ng-change=\"onRangeChanged();\"\n ng-model-options=\"{ debounce: 250 }\">\n <a\n class=\"button button-stable button-clear no-padding pull-right\"\n ng-click=\"goNextRange($event)\">\n <i class=\"icon ion-chevron-right\"></i>\n </a>\n </div>\n"); -$templateCache.put("plugins/graph/templates/common/popover_range_actions.html","<ion-popover-view class=\"has-header popover-graph-currency\">\n <ion-header-bar>\n <h1 class=\"title\" translate>COMMON.POPOVER_ACTIONS_TITLE</h1>\n </ion-header-bar>\n <ion-content scroll=\"false\">\n <div class=\"list item-text-wrap\">\n\n <!-- scale -->\n <a class=\"item item-icon-left ink\"\n ng-click=\"toggleScale()\">\n <i class=\"icon ion-ios-checkmark-empty\" ng-show=\"formData.scale==\'logarithmic\'\"></i>\n <span ng-bind-html=\"\'GRAPH.COMMON.LOGARITHMIC_SCALE\' | translate\"></span>\n </a>\n\n <!-- duration divider -->\n <div class=\"item item-divider\">\n {{\'GRAPH.BLOCKCHAIN.TX_RANGE_DURATION_DIVIDER\'|translate}}\n </div>\n\n <!-- duration: hour -->\n <a class=\"item item-icon-left ink\"\n ng-click=\"setRangeDuration(\'hour\')\">\n <i class=\"icon ion-ios-checkmark-empty\" ng-show=\"formData.rangeDuration==\'hour\'\"></i>\n <span ng-bind-html=\"\'GRAPH.BLOCKCHAIN.TX_RANGE_DURATION.HOUR\' | translate\"></span>\n </a>\n\n <!-- duration: day -->\n <a class=\"item item-icon-left ink\"\n ng-click=\"setRangeDuration(\'day\')\">\n <i class=\"icon ion-ios-checkmark-empty\" ng-show=\"formData.rangeDuration==\'day\'\"></i>\n <span ng-bind-html=\"\'GRAPH.BLOCKCHAIN.TX_RANGE_DURATION.DAY\' | translate\"></span>\n </a>\n\n <!-- duration: month -->\n <a class=\"item item-icon-left ink\"\n ng-click=\"setRangeDuration(\'month\')\">\n <i class=\"icon ion-ios-checkmark-empty\" ng-show=\"formData.rangeDuration==\'month\'\"></i>\n <span ng-bind-html=\"\'GRAPH.BLOCKCHAIN.TX_RANGE_DURATION.MONTH\' | translate\"></span>\n </a>\n\n </div>\n </ion-content>\n</ion-popover-view>\n"); -$templateCache.put("plugins/graph/templates/currency/graph_du.html","\n <!-- graphs button bar -->\n <div class=\"button-bar-inline \"\n style=\"top: 33px; margin-top:-33px; position: relative;\">\n <button\n class=\"button button-stable button-clear no-padding-xs pull-right\"\n ng-click=\"showActionsPopover($event)\">\n <i class=\"icon ion-navicon-round\"></i>\n </button>\n </div>\n\n <canvas id=\"monetaryMass-bar\" class=\"chart-bar\"\n height=\"{{height}}\"\n width=\"{{width}}\"\n chart-data=\"data\"\n chart-labels=\"labels\"\n chart-colors=\"colors\"\n chart-dataset-override=\"datasetOverride\"\n chart-options=\"options\"\n chart-click=\"showBlock\">\n </canvas>\n"); -$templateCache.put("plugins/graph/templates/currency/graph_members_count.html"," <canvas id=\"membersCount-bar\" class=\"chart-line\"\n height=\"{{height}}\"\n width=\"{{width}}\"\n chart-data=\"data\"\n chart-labels=\"labels\"\n chart-colors=\"colors\"\n chart-options=\"options\"\n chart-dataset-override=\"datasetOverride\"\n chart-click=\"onChartClick\">\n </canvas>\n"); -$templateCache.put("plugins/graph/templates/currency/graph_monetary_mass.html","\n <!-- graphs button bar -->\n <div class=\"button-bar-inline \"\n style=\"top: 33px; margin-top:-33px; position: relative;\">\n <button\n class=\"button button-stable button-clear no-padding-xs pull-right\"\n ng-click=\"showActionsPopover($event)\">\n <i class=\"icon ion-navicon-round\"></i>\n </button>\n </div>\n\n <canvas id=\"monetaryMass-bar\"\n class=\"chart-bar\"\n height=\"{{height}}\"\n width=\"{{width}}\"\n chart-data=\"data\"\n chart-labels=\"labels\"\n chart-colors=\"colors\"\n chart-dataset-override=\"datasetOverride\"\n chart-options=\"options\"\n chart-click=\"onChartClick\">\n </canvas>\n"); -$templateCache.put("plugins/graph/templates/currency/popover_monetary_mass_actions.html","<ion-popover-view class=\"fit has-header\">\n <ion-header-bar>\n <h1 class=\"title\" translate>COMMON.POPOVER_ACTIONS_TITLE</h1>\n </ion-header-bar>\n <ion-content scroll=\"false\">\n <div class=\"list item-text-wrap\">\n\n <a class=\"item item-icon-left ink\"\n ng-click=\"toggleScale()\">\n <i class=\"icon ion-ios-checkmark-empty\" ng-show=\"formData.scale==\'logarithmic\'\"></i>\n <span ng-bind-html=\"\'GRAPH.COMMON.LOGARITHMIC_SCALE\' | translate\"></span>\n </a>\n\n </div>\n </ion-content>\n</ion-popover-view>\n"); -$templateCache.put("plugins/graph/templates/currency/tab_blocks_extend.html","<!-- buttons -->\n<ng-if ng-if=\"enable && extensionPoint === \'buttons\'\">\n <div class=\"item item-divider\">\n <a class=\"badge button button-text button-small button-small-padding ink\" ui-sref=\"app.currency.tab_blocks_stats\">\n <i class=\"icon ion-stats-bars\"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_STATS</span>\n </a>\n </div>\n</ng-if>\n"); -$templateCache.put("plugins/graph/templates/currency/view_currency_extend.html","\n<!-- section actual parameters -->\n<ng-if ng-if=\"enable && extensionPoint === \'parameters-actual\'\" >\n\n <ng-if ng-if=\"!smallscreen\">\n <div class=\"item padding-left padding-right no-padding-xs\"\n ng-include=\"\'plugins/graph/templates/currency/graph_monetary_mass.html\'\"\n ng-controller=\"GpCurrencyMonetaryMassCtrl\"\n ng-init=\"displayShareAxis=false;\">\n </div>\n <div class=\"item buttons no-padding-top \">\n <a class=\"pull-right button button-text button-small button-small-padding ink\" ui-sref=\"app.currency_stats_lg\">\n <i class=\"icon ion-stats-bars\"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_DETAILED_STATS</span>\n </a>\n </div>\n </ng-if>\n\n <div class=\"item item-divider\"\n ng-if=\"smallscreen\">\n <a class=\"badge button button-text button-small button-small-padding ink\" ui-sref=\"app.currency.tab_parameters_stats\">\n <i class=\"icon ion-stats-bars\"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_STATS</span>\n </a>\n </div>\n</ng-if>\n\n<!-- section Wot -->\n<ng-if ng-if=\"enable && extensionPoint === \'wot-actual\'\" >\n\n <ng-if ng-if=\"!smallscreen\">\n <div class=\"item padding-left padding-right no-padding-xs\"\n ng-include=\"\'plugins/graph/templates/currency/graph_members_count.html\'\"\n ng-controller=\"GpCurrencyMembersCountCtrl\">\n </div>\n <div class=\"item buttons no-padding-top \">\n <a class=\"pull-right button button-text button-small button-small-padding ink\" ui-sref=\"app.currency_stats_lg\">\n <i class=\"icon ion-stats-bars\"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_DETAILED_STATS</span>\n </a>\n </div>\n </ng-if>\n\n <div class=\"item item-divider\"\n ng-if=\"smallscreen\">\n <a class=\"badge button button-text button-small button-small-padding ink\" ui-sref=\"app.currency.tab_wot_stats\">\n <i class=\"icon ion-stats-bars\"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_STATS</span>\n </a>\n </div>\n</ng-if>\n\n<!-- section Wot -->\n<ng-if ng-if=\"enable && extensionPoint === \'network-actual\'\" >\n\n <div class=\"item padding-left padding-right no-padding-xs\"\n ng-if=\"!smallscreen\"\n ng-include=\"\'plugins/graph/templates/blockchain/graph_block_issuers.html\'\"\n ng-controller=\"GpBlockchainIssuersCtrl\">\n </div>\n\n <div class=\"item item-divider\"\n ng-if=\"smallscreen\">\n <a class=\"badge button button-text button-small button-small-padding ink\" ui-sref=\"app.currency.tab_network_stats\">\n <i class=\"icon ion-stats-bars\"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_STATS</span>\n </a>\n </div>\n</ng-if>\n\n"); -$templateCache.put("plugins/graph/templates/currency/view_parameters_stats.html","<ion-view left-buttons=\"leftButtons\"\n cache-view=\"false\">\n\n <ion-content scroll=\"true\" >\n\n <div class=\"center padding\" ng-if=\"loading\">\n <ion-spinner icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"list no-padding-xs\">\n <div class=\"item no-padding-xs\"\n ng-include=\"\'plugins/graph/templates/currency/graph_monetary_mass.html\'\">\n </div>\n\n <!-- DU -->\n <div class=\"item no-padding-xs\"\n ng-include=\"\'plugins/graph/templates/currency/graph_du.html\'\"\n ng-controller=\"GpCurrencyDUCtrl\"\n ng-init=\"setSize(undefined, undefined)\">\n </div>\n </div>\n </ion-content>\n</ion-view>\n"); -$templateCache.put("plugins/graph/templates/currency/view_stats_lg.html","<ion-view left-buttons=\"leftButtons\"\n cache-view=\"false\">\n <ion-nav-title>\n {{\'GRAPH.BLOCKCHAIN.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content scroll=\"true\" class=\"padding\" >\n\n\n\n <div class=\"list\" >\n\n <!-- Monetary mass -->\n <ng-controller ng-controller=\"GpCurrencyMonetaryMassCtrl\" >\n\n <div class=\"center padding\" ng-if=\"loading\">\n <ion-spinner icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"item no-padding-xs\" ng-if=\"!loading\"\n ng-include=\"\'plugins/graph/templates/currency/graph_monetary_mass.html\'\"\n ng-init=\"setSize(250, 1000)\">\n </div>\n\n <div ng-if=\"!loading\"\n class=\"item item-toggle dark no-border text-right\">\n <span class=\"\" translate>COMMON.BTN_RELATIVE_UNIT</span>\n <label class=\"toggle toggle-royal\" id=\"helptip-currency-change-unit\">\n <input type=\"checkbox\" ng-model=\"formData.useRelative\">\n <div class=\"track\">\n <div class=\"handle\"></div>\n </div>\n </label>\n </div>\n </ng-controller>\n\n <!-- DU -->\n <ng-controller ng-controller=\"GpCurrencyDUCtrl\" >\n <div class=\"item no-padding-xs\"\n ng-if=\"!loading\"\n ng-include=\"\'plugins/graph/templates/currency/graph_du.html\'\"\n ng-init=\"setSize(250, 1000)\">\n </div>\n </ng-controller>\n\n <!-- Member count -->\n <ng-controller ng-controller=\"GpCurrencyMembersCountCtrl\" >\n <div class=\"item no-padding-xs\"\n ng-if=\"!loading\"\n ng-include=\"\'plugins/graph/templates/currency/graph_members_count.html\'\"\n ng-init=\"setSize(250, 1000)\">\n </div>\n\n\n </div>\n\n </ion-content>\n\n</ion-view>\n"); -$templateCache.put("plugins/graph/templates/currency/view_wot_stats.html","<ion-view left-buttons=\"leftButtons\"\n cache-view=\"false\">\n\n <ion-content scroll=\"true\" >\n\n <div class=\"center padding\" ng-if=\"loading\">\n <ion-spinner icon=\"android\"></ion-spinner>\n </div>\n\n <ng-include\n ng-if=\"!loading\"\n src=\"\'plugins/graph/templates/currency/graph_members_count.html\'\" ></ng-include>\n </ion-content>\n </ion-view>\n"); -$templateCache.put("plugins/graph/templates/docstats/graph.html","\n <!-- graphs button bar -->\n <div class=\"button-bar-inline \"\n style=\"top: 33px; margin-top:-33px; position: relative;\">\n <button\n class=\"button button-stable button-clear no-padding-xs pull-right\"\n ng-click=\"showActionsPopover($event)\">\n <i class=\"icon ion-navicon-round\"></i>\n </button>\n </div>\n\n <canvas id=\"{{::chartIdPrefix}}{{chart.id}}\"\n class=\"chart-line\"\n height=\"{{height}}\"\n width=\"{{width}}\"\n chart-data=\"chart.data\"\n chart-labels=\"labels\"\n chart-dataset-override=\"chart.datasetOverride\"\n chart-options=\"chart.options\"\n chart-click=\"onChartClick\">\n </canvas>\n\n <ng-include src=\"\'plugins/graph/templates/common/graph_range_bar.html\'\"></ng-include>\n"); -$templateCache.put("plugins/graph/templates/docstats/view_stats.html","<ion-view left-buttons=\"leftButtons\"\n cache-view=\"false\">\n <ion-nav-title>\n {{\'GRAPH.DOC_STATS.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content scroll=\"true\" class=\"padding\" >\n\n <div class=\"list\" >\n\n <!-- Doc stat -->\n <div class=\"center padding\" ng-if=\"loading\">\n <ion-spinner icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"item no-padding-xs\" ng-if=\"!loading\"\n ng-repeat=\"chart in charts\"\n ng-include=\"\'plugins/graph/templates/docstats/graph.html\'\"\n ng-init=\"setSize(250, 1000)\">\n </div>\n\n </div>\n\n </ion-content>\n\n</ion-view>\n"); -$templateCache.put("plugins/graph/templates/network/view_network_extend.html","<!-- Buttons section -->\n<ng-if ng-if=\"enable && extensionPoint === \'buttons\'\">\n <a class=\"button button-text button-small ink\"\n ui-sref=\"app.blockchain_stats\" >\n <i class=\"icon ion-stats-bars\"></i>\n <span>{{\'NETWORK.VIEW.BTN_GRAPH\'|translate}}</span>\n </a>\n</ng-if>\n"); -$templateCache.put("plugins/graph/templates/network/view_peer_extend.html","<!-- Buttons section -->\n<ng-if ng-if=\"enable && extensionPoint === \'general\'\">\n\n <a class=\"item item-icon-left item-icon-right item-text-wrap ink\"\n ui-sref=\"app.view_peer_stats({pubkey: node.pubkey})\">\n <i class=\"icon ion-stats-bars\"></i>\n <span translate>GRAPH.PEER.VIEW.BLOCK_COUNT_LABEL</span>\n <span class=\"badge\"\n ng-if=\"!loading\"\n ng-class=\"{\'badge-stable\': blockCount > 0, \'badge-assertive\': !blockCount}\">\n {{!blockCount ? \'GRAPH.PEER.VIEW.NO_BLOCK\' : \'GRAPH.PEER.VIEW.BLOCK_COUNT\' | translate:{count: blockCount} }}\n </span>\n <ion-spinner class=\"badge\" icon=\"android\" ng-if=\"loading\"></ion-spinner>\n <i class=\"gray icon ion-ios-arrow-right\"></i>\n </a>\n</ng-if>\n\n"); -$templateCache.put("plugins/graph/templates/network/view_peer_stats.html","<ion-view left-buttons=\"leftButtons\"\n cache-view=\"false\">\n <ion-nav-title>\n {{\'GRAPH.BLOCKCHAIN.TITLE\' | translate}}{{id}}\n </ion-nav-title>\n\n <ion-content scroll=\"true\" class=\"no-padding\">\n\n <div class=\"center padding\" ng-if=\"loading\">\n <ion-spinner icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"list\" ng-if=\"!loading\">\n\n <!-- - - - - TX divider - - - - -->\n <div class=\"item item-divider hidden-xs hidden-sm\" translate>\n GRAPH.BLOCKCHAIN.TX_DIVIDER\n </div>\n\n <div class=\"item no-padding-xs\"\n ng-include=\"\'plugins/graph/templates/blockchain/graph_tx_count.html\'\"\n ng-init=\"setSize(350, 1000)\">\n </div>\n\n </ion-content>\n\n</ion-view>\n"); -$templateCache.put("plugins/graph/templates/synchro/graph.html","\n <!-- graphs button bar -->\n <div class=\"button-bar-inline \"\n style=\"top: 33px; margin-top:-33px; position: relative;\">\n <button\n class=\"button button-stable button-clear no-padding-xs pull-right\"\n ng-click=\"showActionsPopover($event)\">\n <i class=\"icon ion-navicon-round\"></i>\n </button>\n </div>\n\n <canvas id=\"synchro-chart-{{chart.id}}\"\n class=\"chart-bar\"\n height=\"{{height}}\"\n width=\"{{width}}\"\n chart-data=\"chart.data\"\n chart-labels=\"labels\"\n chart-dataset-override=\"chart.datasetOverride\"\n chart-options=\"chart.options\">\n </canvas>\n\n <ng-include src=\"\'plugins/graph/templates/common/graph_range_bar.html\'\"></ng-include>\n"); -$templateCache.put("plugins/graph/templates/synchro/view_stats.html","<ion-view left-buttons=\"leftButtons\"\n cache-view=\"false\">\n <ion-nav-title>\n {{\'GRAPH.SYNCHRO.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content scroll=\"true\" class=\"padding\" >\n\n <div class=\"list\" >\n\n <div class=\"center padding\" ng-if=\"loading\">\n <ion-spinner icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"item no-padding-xs\" ng-if=\"!loading\"\n ng-repeat=\"chart in charts\"\n ng-include=\"\'plugins/graph/templates/synchro/graph.html\'\"\n ng-init=\"setSize(250, 1000)\">\n </div>\n\n </div>\n\n </ion-content>\n\n</ion-view>\n"); -$templateCache.put("plugins/map/templates/network/item_search_tooltip.html","<a href=\"#\">\n {{peer.dns || peer.server}}\n <span class=\"{{peer.uid ? \'positive\' : \'gray\'}}\">\n <i class=\"icon {{peer.uid ? \'ion-person\' : \'ion-key\'}}\"></i>\n {{peer.uid ? (peer.name||peer.uid) : (peer.pubkey|formatPubkey) }}\n </span>\n <span class=\"gray\">{{peer.ipv4 ? (peer.ipv4 + \':\' + peer.port) : \'\'}}</span>\n <span class=\"{{peer.bma.useSsl ? \'\' : \'ng-hide\'}}\"><i class=\"ion-locked\"></i> <small>SSL</small></span>\n</a>\n"); -$templateCache.put("plugins/map/templates/network/lookup_extend.html","<a ng-if=\"enable\"\n class=\"button button-text button-small ink hidden-sm hidden-xs\"\n title=\"{{\'MAP.NETWORK.LOOKUP.BTN_MAP_HELP\' | translate}}\"\n ui-sref=\"app.view_network_map\">\n <i class=\"icon ion-ios-location\"></i>\n {{\'MAP.NETWORK.LOOKUP.BTN_MAP\' | translate}}\n</a>\n"); -$templateCache.put("plugins/map/templates/network/view_map.html","<ion-view left-buttons=\"leftButtons\" class=\"view-map-network\">\n <ion-nav-title>\n <span class=\"hidden-xs\" translate>MAP.NETWORK.VIEW.TITLE</span>\n </ion-nav-title>\n\n <ion-nav-buttons side=\"secondary\">\n </ion-nav-buttons>\n\n <ion-content data-tap-disabled=\"true\">\n <leaflet id=\"{{::mapId}}\"\n height=\"100%\"\n center=\"map.center\"\n markers=\"map.markers\"\n layers=\"map.layers\">\n </leaflet>\n </ion-content>\n</ion-view>\n"); -$templateCache.put("plugins/map/templates/registry/item_search_tooltip.html","<a href=\"#\" class=\"{{type}}\">\n <i class=\"{{\'cion-page-\' + type}}\"></i>\n {{name != uid ? name +\' \' : \'\'}}\n <span class=\"gray\">\n {{pubkey ? (pubkey|formatPubkey) : \'\'}}\n </span>\n</a>\n"); -$templateCache.put("plugins/map/templates/registry/lookup_lg_extend.html","<a class=\"button button-text button-small ink hidden-sm hidden-xs\"\n title=\"{{\'MAP.REGISTRY.LOOKUP.BTN_MAP_HELP\' | translate}}\"\n ui-sref=\"app.view_registry_map\">\n <i class=\"icon ion-ios-location\"></i>\n {{\'MAP.REGISTRY.LOOKUP.BTN_MAP\' | translate}}\n</a>\n"); -$templateCache.put("plugins/map/templates/registry/view_map.html","<ion-view left-buttons=\"leftButtons\" class=\"view-map-registry\">\n <ion-nav-title>\n <span class=\"hidden-xs\" translate>MAP.REGISTRY.VIEW.TITLE</span>\n </ion-nav-title>\n\n <ion-nav-buttons side=\"secondary\">\n <button class=\"button button-icon button-clear icon ion-loop visible-xs visible-sm\" ng-click=\"load()\">\n </button>\n </ion-nav-buttons>\n\n <ion-content data-tap-disabled=\"true\">\n <a id=\"helptip-map-registry\" style=\"left: 150px; top: 50px; position: relative;\"></a>\n <leaflet id=\"{{::mapId}}\"\n height=\"100%\"\n layers=\"map.layers\"\n markers=\"map.markers\"\n lf-center=\"map.center\"\n bounds=\"map.bounds\">\n </leaflet>\n </ion-content>\n</ion-view>\n"); -$templateCache.put("plugins/map/templates/settings/es_settings_extend.html","\n<!--<span class=\"item item-divider\" translate>MAP.SETTINGS.MAP_DIVIDER</span>\n\n<label class=\"item item-toggle dark item-text-wrap\">\n <span translate>MAP.SETTINGS.ENABLE_GOOGLE_API</span>\n <h4 class=\"gray\" translate>MAP.SETTINGS.ENABLE_GOOGLE_API_HELP</h4>\n <div class=\"toggle toggle-royal\">\n <input type=\"checkbox\" ng-model=\"formData.enableGoogleApi\">\n <div class=\"track\">\n <div class=\"handle\"></div>\n </div>\n </div>\n</label>\n\n<ion-item class=\"item-input\"\n ng-if=\"!$root.config.plugins.es.googleApiKey\"\n ng-class=\"{\'item-input-error\': formData.enableGoogleApi && !formData.googleApiKey}\">\n <div class=\"input-label col-33\">\n <span class=\"\" ng-class=\"{\'gray\': !formData.enableGoogleApi}\"translate>MAP.SETTINGS.GOOGLE_API_KEY</span>\n <h4>\n <a ng-click=\"openLink($event, \'https://console.developers.google.com/apis/credentials/key\')\" translate>MAP.SETTINGS.BTN_GOOGLE_API</a>\n <span class=\"gray\"> ({{\'MAP.SETTINGS.BTN_GOOGLE_API_WARNING\'|translate}})</span>\n </h4>\n </div>\n <input type=\"text\"\n placeholder=\"{{\'MAP.SETTINGS.GOOGLE_API_KEY_PLACEHOLDER\' | translate}}\"\n ng-model=\"formData.googleApiKey\"\n ng-if=\"formData.enableGoogleApi\">\n</ion-item>\n<div class=\"form-errors\"\n ng-show=\"formData.enableGoogleApi && !formData.googleApiKey\">\n <div class=\"form-error\">\n <span translate=\"ERROR.FIELD_REQUIRED\"></span>\n </div>\n</div>-->\n"); -$templateCache.put("plugins/map/templates/user/edit_profile_extend.html","<div class=\"item no-padding {{ionItemClass}}\" ng-if=\"formData.geoPoint && formData.geoPoint.lat && formData.geoPoint.lon\">\n <leaflet id=\"{{::mapId}}\"\n height=\"250px\"\n center=\"map.center\"\n markers=\"map.markers\"\n defaults=\"map.defaults\">\n </leaflet>\n</div>\n"); -$templateCache.put("plugins/map/templates/wot/item_search_tooltip.html","<a href=\"#\" class=\"{{type}}\">\n <i class=\"{{pending ? \'ion-clock\': (type ? \'cion-page-\' + type : \'\')}}\"></i>\n {{name != uid ? name +\' \' : \'\'}}\n <span class=\"{{uid ? \'positive\' : \'gray\'}}\">\n <i class=\"{{uid ? \'ion-person\' : \'ion-key\'}}\"></i>\n {{uid ? uid : (pubkey|formatPubkey) }}\n </span>\n</a>\n"); -$templateCache.put("plugins/map/templates/wot/lookup_lg_extend.html","<a ng-if=\"enable\"\n class=\"button button-text button-small ink hidden-sm hidden-xs\"\n title=\"{{\'MAP.WOT.LOOKUP.BTN_MAP_HELP\' | translate}}\"\n ui-sref=\"app.view_wot_map\">\n <i class=\"icon ion-ios-location\"></i>\n {{\'MAP.WOT.LOOKUP.BTN_MAP\' | translate}}\n</a>\n"); -$templateCache.put("plugins/map/templates/wot/popup_marker.html","<div class=\"item no-border no-padding item-avatar\" ng-class=\"::{\'item-avatar\': hit.avatar}\">\n <img ng-if=\"::hit.avatar\" class=\"item-image avatar\" ng-src=\"{{::hit.avatar.src}}\">\n <i ng-if=\"::!hit.avatar\" class=\"item-image icon \" ng-class=\"::{\'ion-person\': hit.uid, \'ion-card\': !hit.uid}\"></i>\n <div class=\"item-content item-avatar-left-padding padding-top\">\n <h2 class=\"dark\"><a ui-sref=\"app.wot_identity({pubkey: hit.pubkey, uid: hit.uid})\">{{::hit.name}}</a></h2>\n <h4>\n <span ng-if=\"::hit.uid\" class=\"positive\">\n <b class=\"ion-person\"></b>\n {{::hit.uid}}\n </span>\n <span class=\"gray\" title=\"{{::hit.pubkey}}\"><b class=\"ion-key\"></b> {{::hit.pubkey|formatPubkey}}</span>\n <span class=\"assertive\" ng-if=\"!hit.uid\">\n {{::\'WOT.NOT_MEMBER_PARENTHESIS\'|translate}}\n </span>\n </h4>\n <h4 ng-if=\"::hit.city\" class=\"gray\" title=\"{{::hit.city}}\">\n <b class=\"ion-location\"></b> {{::hit.city}}\n </h4>\n </div>\n</div>\n<div class=\"item no-border no-padding item-text-wrap hidden-xs\" ng-if=\"::hit.description\">\n <small trust-as-html=\"::hit.description\"></small>\n</div>\n"); -$templateCache.put("plugins/map/templates/wot/popup_page_marker.html","<div class=\"item no-border no-padding item-avatar\" ng-class=\"::{\'item-avatar\': hit.avatar}\">\n <img ng-if=\"::hit.avatar\" class=\"item-image avatar\" ng-src=\"{{::hit.avatar.src}}\">\n <i ng-if=\"::!hit.avatar\" class=\"item-image icon cion-page-{{::hit.type}}\"></i>\n <div class=\"item-content item-avatar-left-padding padding-top\">\n <h2 class=\"dark\"><a ui-sref=\"app.view_page({id: hit.id, title: hit.title})\">{{::hit.name}}</a></h2>\n <h4 ng-if=\"::hit.category\" class=\"gray\" title=\"{{::hit.category.name}}\">\n <a ui-sref=\"app.registry_lookup({category: hit.category.id})\"><b class=\"ion-flag\"></b> {{::hit.category.name}}</a>\n </h4>\n <h4 ng-if=\"::hit.city\" class=\"gray\" title=\"{{::hit.city}}\">\n <b class=\"ion-location\"></b> {{::hit.city}}\n </h4>\n </div>\n</div>\n<div class=\"item no-border no-padding item-text-wrap hidden-xs\" ng-if=\"::hit.description\">\n <small trust-as-html=\"::hit.description\"></small>\n</div>\n"); -$templateCache.put("plugins/map/templates/wot/view_map.html","<ion-view left-buttons=\"leftButtons\" class=\"view-map-wot\">\n <ion-nav-title>\n <span class=\"hidden-xs\" translate>MAP.WOT.VIEW.TITLE</span>\n </ion-nav-title>\n\n <ion-nav-buttons side=\"secondary\">\n <button class=\"button button-icon button-clear icon ion-loop visible-xs visible-sm\" ng-click=\"load()\">\n </button>\n </ion-nav-buttons>\n\n <ion-content data-tap-disabled=\"true\">\n <a id=\"helptip-map-wot\" style=\"left: 150px; top: 50px; position: relative;\"></a>\n <leaflet id=\"{{::mapId}}\"\n height=\"100%\"\n layers=\"map.layers\"\n markers=\"map.markers\"\n lf-center=\"map.center\"\n bounds=\"map.bounds\">\n </leaflet>\n </ion-content>\n</ion-view>\n"); -$templateCache.put("plugins/es/templates/message/tabs/tab_list.html","<ion-view><ion-nav-buttons side=\"secondary\"><cs-extension-point name=\"nav-buttons\"></cs-extension-point><button class=\"button button-icon button-clear icon ion-android-more-vertical\" ng-click=\"showActionsPopover($event)\"></button></ion-nav-buttons><ion-content><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"refresh()\"></ion-refresher><cs-extension-point name=\"buttons\"></cs-extension-point><ng-include src=\"\'plugins/es/templates/message/list.html\'\"></ng-include></ion-content><div class=\"visible-xs visible-sm\"><button ng-if=\"fabButtonNewMessageId\" id=\"{{::fabButtonNewMessageId}}\" class=\"button button-fab button-fab-bottom-right button-assertive spin has-footer\" ng-click=\"showNewMessageModal()\"><i class=\"icon ion-compose\"></i></button></div></ion-view>"); -$templateCache.put("plugins/es/templates/registry/tabs/tab_registry.html","<ion-view><ion-nav-buttons side=\"secondary\"><cs-extension-point name=\"nav-buttons\"></cs-extension-point><button class=\"button button-icon button-clear\" ng-click=\"showFiltersPopover($event)\"><i class=\"icon ion-android-funnel\"></i></button> <button class=\"button button-icon button-clear icon ion-android-more-vertical\" ng-click=\"showActionsPopover($event)\"></button></ion-nav-buttons><ion-content><ion-refresher pulling-text=\"{{\'COMMON.BTN_REFRESH\' | translate}}\" on-refresh=\"doSearch()\"></ion-refresher><cs-extension-point name=\"buttons\"></cs-extension-point><ng-include src=\"::\'plugins/es/templates/registry/lookup_form.html\'\"></ng-include><ng-include src=\"::\'plugins/es/templates/registry/lookup_list.html\'\"></ng-include></ion-content></ion-view>"); -$templateCache.put("plugins/graph/templates/currency/tabs/tab_blocks_stats.html","<ion-view>\n <ion-content>\n <div\n ng-include=\"\'plugins/graph/templates/blockchain/graph_tx_count.html\'\"\n ng-controller=\"GpBlockchainTxCountCtrl\"\n ng-init=\"setSize(500,700,false)\">\n </div>\n </ion-content>\n</ion-view>\n"); -$templateCache.put("plugins/graph/templates/currency/tabs/tab_network_stats.html","<ion-view>\n <ion-content>\n\n <div class=\"list\">\n <div class=\"item\"\n ng-include=\"\'plugins/graph/templates/blockchain/graph_block_issuers.html\'\"\n ng-controller=\"GpBlockchainIssuersCtrl\"\n ng-init=\"setSize(500,700,true)\">\n </div>\n </div>\n </ion-content>\n</ion-view>\n"); -$templateCache.put("plugins/graph/templates/currency/tabs/tab_parameters_stats.html","<ion-view>\n <ion-content>\n <div class=\"center padding\" ng-if=\"loading\">\n <ion-spinner icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"row responsive-sm\">\n <div class=\"col\"\n ng-include=\"\'plugins/graph/templates/currency/graph_monetary_mass.html\'\"\n ng-init=\"setSize(500,700,true)\">\n </div>\n\n <!-- DU -->\n <div class=\"col\"\n ng-include=\"\'plugins/graph/templates/currency/graph_du.html\'\"\n ng-controller=\"GpCurrencyDUCtrl\"\n ng-init=\"setSize(500,700,true)\">\n </div>\n </div>\n </ion-content>\n</ion-view>\n"); -$templateCache.put("plugins/graph/templates/currency/tabs/tab_wot_stats.html","<ion-view>\n <ion-content>\n <div class=\"center padding\" ng-if=\"loading\">\n <ion-spinner icon=\"android\"></ion-spinner>\n </div>\n\n <div class=\"list no-padding\">\n <div class=\"item no-padding-top\"\n ng-include=\"\'plugins/graph/templates/currency/graph_members_count.html\'\"\n ng-init=\"setSize(600,700,false)\">\n </div>\n </div>\n </ion-content>\n</ion-view>\n");}]); \ No newline at end of file +angular.module('cesium.plugins.templates', []).run(['$templateCache', function($templateCache) {$templateCache.put('plugins/es/templates/menu_extend.html','<div ng-if=":state:enable && extensionPoint === \'menu-user\'" class="visible-xs visible-sm"><a menu-close="" class="item item-icon-left" active-link="active" ng-if="login && walletData.isMember" active-link-path-prefix="#/app/invitations" ui-sref="app.view_invitations"><i class="icon ion-person-stalker"></i> <span translate="">MENU.INVITATIONS</span> <span class="badge badge-positive" ng-if="walletData.invitations.unreadCount">{{walletData.invitations.unreadCount}}</span> </a><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/user/message" ng-class="{\'item-menu-disable\': !login}" ui-sref="app.user_message.tab_inbox"><i class="icon ion-email"></i> <span translate="">MENU.MESSAGES</span> <span class="badge badge-positive" ng-if="walletData.messages.unreadCount">{{walletData.messages.unreadCount}}</span> </a><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/notifications" ng-class="{\'item-menu-disable\': !login}" ui-sref="app.view_notifications"><i class="icon ion-android-notifications"></i> <span translate="">MENU.NOTIFICATIONS</span> <span class="badge badge-positive" ng-if="walletData.notifications.unreadCount">{{walletData.notifications.unreadCount}}</span></a></div>'); +$templateCache.put('plugins/rml9/templates/01-button.html','<!-- Button that call a function of the controller -->\n<button class="button button-balanced button-small-padding icon ion-android-archive"\n ng-click="onButtonClick()"\n title="{{\'RML9.BTN_OPEN\' | translate}}">\n</button>\n\n<!-- Button: Open a view, using `ui-sref` attribute\n<button class="button button-balanced button-small-padding icon ion-plus-circled"\n ui-sref="app.rml9({pubkey: formData.pubkey})"\n title="{{\'RML9.BTN_OPEN\' | translate}}">\n</button> -->\n\n'); +$templateCache.put('plugins/rml9/templates/02-view.html','<ion-view left-buttons="leftButtons">\n <ion-nav-title>\n {{\'RML9.VIEW.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content>\n <div class="list">\n\n <!-- the pubkey -->\n <div class="item">\n {{\'COMMON.PUBKEY\'|translate}}\n <div class="badge">{{pubkey|formatPubkey}}</div>\n </div>\n\n <!-- a text divider-->\n <div class="item item-divider">{{\'RML9.VIEW.DIVIDER\'|translate:{pubkey: pubkey} }}</div>\n\n <!-- iterate on each TX -->\n <div class="item" ng-repeat="item in items">\n <h3>{{item.time|formatDate}}</h3>\n <h4>{{item.pubkey|formatPubkey}}</h4>\n <div class="badge">{{item.amount|formatAmount}}</div>\n </div>\n </div>\n </ion-content>\n</ion-view>\n'); +$templateCache.put('plugins/rml9/templates/03-button.html','<!-- Button: Open a view, using `ui-sref` attribute -->\n<button class="button button-balanced button-small-padding icon ion-android-archive"\n ui-sref="app.rml9({pubkey: formData.pubkey})"\n title="{{\'RML9.BTN_SWOW_TX\' | translate}}">\n</button>\n\n'); +$templateCache.put('plugins/rml9/templates/03-view_with_button.html','<ion-view left-buttons="leftButtons">\n <ion-nav-title>\n {{\'RML9.VIEW.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content>\n <div class="list">\n\n <!-- buttons bar -->\n <div class="center padding">\n <div class="buttons">\n <button class="button button-balanced icon-left icon ion-archive"\n ng-click="onExportButtonClick()">{{\'RML9.BTN_EXPORT\' | translate}}\n </button>\n </div>\n </div>\n\n <!-- the pubkey -->\n <div class="item">\n {{\'COMMON.PUBKEY\'|translate}}\n <div class="badge">{{pubkey|formatPubkey}}</div>\n </div>\n\n <!-- the balance -->\n <div class="item">\n {{\'RML9.VIEW.BALANCE\'|translate}}\n <div class="badge badge-calm">\n {{balance|formatAmount}} <span ng-bind-html="$root.currency.name|currencySymbol"></span>\n </div>\n </div>\n\n <!-- a text divider-->\n <div class="item item-divider">{{\'RML9.VIEW.DIVIDER\'|translate:{pubkey: pubkey} }}</div>\n\n <!-- iterate on each TX -->\n <div class="item item-text-wrap" ng-repeat="item in items">\n\n <h3>\n {{item.time|formatDate}}\n <span ng-if="item.comment" class="gray"> | {{item.comment}}</span>\n </h3>\n\n <h4 ng-if="item.uid" class="positive"><i class="icon ion-person"></i> {{item.name||item.uid}}</h4>\n <h4 ng-if="!item.uid" class="gray"><i class="icon ion-key"></i> {{item.pubkey|formatPubkey}}</h4>\n\n <div class="badge"\n ng-class="{\'badge-balanced\': item.amount > 0}">\n {{item.amount|formatAmount}} <span ng-bind-html="$root.currency.name|currencySymbol"></span>\n </div>\n </div>\n </div>\n </ion-content>\n</ion-view>\n'); +$templateCache.put('plugins/rml9/templates/04-view_chart.html','<ion-view left-buttons="leftButtons">\n <ion-nav-title>\n {{\'RML9.VIEW.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content>\n <div class="list">\n\n <!-- buttons bar -->\n <div class="center padding">\n <div class="buttons">\n <button class="button button-balanced icon-left icon ion-archive"\n ng-click="onExportButtonClick()">{{\'RML9.BTN_EXPORT\' | translate}}\n </button>\n </div>\n </div>\n\n <!-- the pubkey -->\n <div class="item">\n {{\'COMMON.PUBKEY\'|translate}}\n <div class="badge">{{pubkey|formatPubkey}}</div>\n </div>\n\n <!-- the balance -->\n <div class="item">\n {{\'RML9.VIEW.BALANCE\'|translate}}\n <div class="badge badge-calm">\n {{balance|formatAmount}} <span ng-bind-html="$root.currency.name|currencySymbol"></span>\n </div>\n </div>\n\n <!-- a text divider-->\n <div class="item item-divider">{{\'RML9.VIEW.DIVIDER\'|translate:{pubkey: pubkey} }}</div>\n\n\n <div class="row">\n <div class="col col-75">\n <!-- iterate on each TX -->\n <div class="item item-text-wrap" ng-repeat="item in items">\n\n <h3>\n {{item.time|formatDate}}\n <span ng-if="item.comment" class="gray"> | {{item.comment}}</span>\n </h3>\n\n <h4 ng-if="item.uid" class="positive"><i class="icon ion-person"></i> {{item.name||item.uid}}</h4>\n <h4 ng-if="!item.uid" class="gray"><i class="icon ion-key"></i> {{item.pubkey|formatPubkey}}</h4>\n\n <div class="badge"\n ng-class="{\'badge-balanced\': item.amount > 0}">\n {{item.amount|formatAmount}} <span ng-bind-html="$root.currency.name|currencySymbol"></span>\n </div>\n </div>\n </div>\n\n <div class="col col-25">\n\n <!-- [NEW] TX input chart -->\n <p class="gray" translate>RML9.CHART.INPUT_CHART_TITLE</p>\n <canvas id="chart-received-pie" class="chart-pie"\n chart-data="inputChart.data"\n chart-labels="inputChart.labels"\n chart-colors="inputChart.colors">\n </canvas>\n\n <!-- [NEW] TX input chart -->\n <p class="gray" translate>RML9.CHART.OUTPUT_CHART_TITLE</p>\n <canvas id="chart-sent-pie" class="chart-pie"\n chart-data="outputChart.data"\n chart-labels="outputChart.labels"\n chart-colors="outputChart.colors">\n </canvas>\n </div>\n </div>\n </div>\n </ion-content>\n</ion-view>\n'); +$templateCache.put('plugins/rml9/templates/06-button.html','<!-- [NEW] Display only if plugin is enable -->\n\n <!-- Button: call a method from the state controller -->\n <button ng-if="enable" class="button button-balanced button-small-padding icon ion-android-archive"\n ng-click="onButtonClick()"\n title="{{\'RML9.BTN_SWOW_TX\' | translate}}">\n </button>\n\n\n'); +$templateCache.put('plugins/rml9/templates/06-settings_item.html','\n<div class="item item-toggle dark">\n <div class="input-label" translate>RML9.SETTINGS.ENABLE_TOGGLE</div>\n <label class="toggle toggle-royal">\n <input type="checkbox" ng-model="formData.plugins.rml9.enable" >\n <div class="track">\n <div class="handle"></div>\n </div>\n </label>\n</div>\n'); +$templateCache.put('plugins/rml9/templates/07-button.html','<!-- Button: Open a view, using `ui-sref` attribute -->\n<button class="button button-balanced button-small-padding icon ion-android-archive"\n ui-sref="app.rml9({pubkey: formData.pubkey})"\n title="{{\'RML9.BTN_SWOW_TX\' | translate}}">\n</button>\n\n'); +$templateCache.put('plugins/rml9/templates/07-view.html','<leaflet id="map-geojson" center="map.center" geojson="map.geojson"></leaflet>\n'); +$templateCache.put('plugins/rml9/templates/final-button.html','<!-- Button: Open a view, using `ui-sref` attribute -->\n<button ng-if class="button button-balanced button-small-padding icon ion-android-archive"\n ui-sref="app.rml9({pubkey: formData.pubkey})"\n title="{{\'RML9.BTN_SWOW_TX\' | translate}}">\n</button>\n\n'); +$templateCache.put('plugins/rml9/templates/final-view.html','<ion-view left-buttons="leftButtons">\n <ion-nav-title>\n {{\'RML9.VIEW.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content>\n <div class="list">\n\n <!-- buttons bar -->\n <div class="center padding">\n <div class="buttons">\n <button class="button button-balanced icon-left icon ion-archive"\n ng-click="onExportButtonClick()">{{\'RML9.BTN_EXPORT\' | translate}}\n </button>\n </div>\n </div>\n\n <!-- the pubkey -->\n <div class="item">\n {{\'COMMON.PUBKEY\'|translate}}\n <div class="badge">{{pubkey|formatPubkey}}</div>\n </div>\n\n <!-- the balance -->\n <div class="item">\n {{\'RML9.VIEW.BALANCE\'|translate}}\n <div class="badge badge-calm">\n {{balance|formatAmount}} <span ng-bind-html="$root.currency.name|currencySymbol"></span>\n </div>\n </div>\n\n <!-- a text divider-->\n <div class="item item-divider">{{\'RML9.VIEW.DIVIDER\'|translate:{pubkey: pubkey} }}</div>\n\n <!-- iterate on each TX -->\n <div class="row">\n <div class="col col-75">\n <div class="item item-text-wrap" ng-repeat="item in items">\n\n <h3>\n {{item.time|formatDate}}\n <span ng-if="item.comment" class="gray"> | {{item.comment}}</span>\n </h3>\n\n <h4 ng-if="item.uid" class="positive"><i class="icon ion-person"></i> {{item.name||item.uid}}</h4>\n <h4 ng-if="!item.uid" class="gray"><i class="icon ion-key"></i> {{item.pubkey|formatPubkey}}</h4>\n\n <div class="badge"\n ng-class="{\'badge-balanced\': item.amount > 0}">\n {{item.amount|formatAmount}} <span ng-bind-html="$root.currency.name|currencySymbol"></span>\n </div>\n </div>\n\n </div>\n\n <div class="col col-25">\n\n <!-- [NEW] TX input chart -->\n <p class="gray" translate>RML9.CHART.INPUT_CHART_TITLE</p>\n <canvas id="chart-received-pie" class="chart-pie"\n chart-data="inputChart.data"\n chart-labels="inputChart.labels">\n </canvas>\n\n <!-- [NEW] TX input chart -->\n <p class="gray" translate>RML9.CHART.OUTPUT_CHART_TITLE</p>\n <canvas id="chart-sent-pie" class="chart-pie"\n chart-data="outputChart.data"\n chart-labels="outputChart.labels">\n </canvas>\n </div>\n </div>\n </div>\n </ion-content>\n</ion-view>\n'); +$templateCache.put('plugins/es/templates/blockchain/items_blocks.html','<div class="padding gray" ng-if=":rebind:!search.loading && !search.results.length" translate="">COMMON.SEARCH_NO_RESULT</div><ng-if ng-if=":rebind:!smallscreen"><ng-repeat ng-repeat="block in :rebind:search.results track by block.number" ng-include="!block.empty ? \'templates/blockchain/item_block_lg.html\' : \'templates/blockchain/item_block_empty_lg.html\'"></ng-repeat></ng-if><ng-if ng-if=":rebind:smallscreen"><ng-repeat ng-repeat="block in :rebind:search.results track by block.number" ng-include="\'templates/blockchain/item_block.html\'"></ng-repeat></ng-if>'); +$templateCache.put('plugins/es/templates/blockchain/lookup.html','<ion-view><ion-nav-title><span translate>BLOCKCHAIN.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-navicon visible-xs visible-sm" ng-click="toggleCompactMode()"><b class="icon-secondary" ng-class="{\'ion-arrow-down-b\': !compactMode, \'ion-arrow-up-b\': compactMode}" style="top: -12px; left: 11px; font-size: 10px"></b> <b class="icon-secondary" ng-class="{\'ion-arrow-up-b\': !compactMode,\'ion-arrow-down-b\': compactMode}" style="top: 12px; left: 11px; font-size: 10px"></b></button> <button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ng-include src="\'plugins/es/templates/blockchain/lookup_form.html\'"></ng-include></ion-content></ion-view>'); +$templateCache.put('plugins/es/templates/blockchain/lookup_form.html','<div class="lookupForm"><div class="item no-padding"><div class="button button-small button-text button-stable button-icon-event padding no-padding-right ink" ng-repeat="filter in search.filters" ng-if="filter"><span ng-bind-html="\'BLOCKCHAIN.LOOKUP.TX_SEARCH_FILTER.\'+filter.type|translate:filter"></span> <i class="icon ion-close" ng-click="itemRemove($index)"></i></div><label class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{\'BLOCKCHAIN.LOOKUP.SEARCH_HELP\'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearchText()"><div class="helptip-anchor-center"><a id="helptip-blockchain-search-text"></a></div></label></div><div class="padding-top padding-xs" style="display: block; height: 60px"><div class="pull-left"><h4 ng-if="search.type==\'last\'" translate="">BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4><h4 ng-if="search.type==\'text\'">{{\'COMMON.RESULTS_LIST\'|translate}}</h4><h5 class="dark" ng-if="!search.loading && search.total"><span translate="COMMON.RESULTS_COUNT" translate-values="{count: search.total}"></span> <small class="gray" ng-if=":rebind:search.took && expertMode">- {{:rebind:\'COMMON.EXECUTION_TIME\'|translate: {duration: search.took} }} </small><small class="gray" ng-if=":rebind:expertMode && search.filters && search.filters.length">- <a ng-click="toggleShowQuery()" ng-if="!showQuery">{{\'DOCUMENT.LOOKUP.SHOW_QUERY\'|translate }} <i class="icon ion-arrow-down-b gray"></i> </a><a ng-click="toggleShowQuery()" ng-if="showQuery">{{\'DOCUMENT.LOOKUP.HIDE_QUERY\'|translate }} <i class="icon ion-arrow-up-b gray"></i></a></small></h5><h5 class="gray" ng-if="search.loading"><ion-spinner class="icon ion-spinner-small" icon="android"></ion-spinner><span translate="">COMMON.SEARCHING</span><br></h5></div></div><div class="item no-border no-padding" ng-if=":rebind:search.filters && search.filters.length && expertMode"><small class="no-padding no-margin" ng-if="showQuery"><span class="gray text-wrap dark">{{:rebind:search.query}}</span></small></div><ion-list class="list list-blocks" ng-class="::motion.ionListClass"><ng-include src="\'plugins/es/templates/blockchain/items_blocks.html\'"></ng-include></ion-list><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll></div>'); +$templateCache.put('plugins/es/templates/blockchain/lookup_popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>BLOCKCHAIN.LOOKUP.POPOVER_FILTER_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a ng-if="enableFilter" class="item item-icon-left item-icon-right ink" ng-click="doSearchLast()"><i class="icon ion-clock"></i> {{\'BLOCKCHAIN.LOOKUP.BTN_LAST\' | translate}} <i class="icon ion-ios-checkmark-empty" ng-show="search.type==\'last\'"></i></a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/common/edit_pictures.html','<div class="gallery" ng-controller="ESPicturesEditCtrl as ctrl"><div ng-repeat="picture in pictures" class="item card card-gallery stable-bg" ng-class="{\'in done\': picture.isnew}"><div><h2 ng-if="picture.title">{{picture.title}}</h2><img ng-src="{{picture.src}}"></div><div class="item done in tabs tabs-secondary tabs-icon-left"><a class="tab-item stable-bg assertive" ng-click="removePicture($index)" title="{{\'COMMON.BTN_PICTURE_DELETE\' | translate}}"><i class="icon ion-trash-a"></i>{{\'COMMON.BTN_PICTURE_DELETE\'|translate}}</a> <a class="tab-item stable-bg dark" ng-click="rotatePicture($index)" title="{{\'COMMON.BTN_PICTURE_ROTATE\' | translate}}"><i class="icon ion-forward"></i>{{\'COMMON.BTN_PICTURE_ROTATE\'|translate}}</a> <a class="tab-item stable-bg" ng-click="favoritePicture($index)" ng-class="{\'gray\': $index !== 0, \'positive\': $index === 0}" title="{{\'COMMON.BTN_PICTURE_FAVORISE\' | translate}}"><i class="icon ion-star"></i>{{\'COMMON.BTN_PICTURE_FAVORISE\'|translate}}</a></div></div><div class="item card card-gallery card-gallery-new text-center padding ink" ng-click="selectNewPicture(\'#pictureFile\')"><i class="ion-image stable" style="font-size:150px"></i> <b class="ion-plus gray" style="font-size:80px; position:absolute; top:25px; right: 5px"></b><p translate>COMMON.BTN_ADD_PICTURE</p></div><input type="file" id="pictureFile" accept="image/*" onchange="angular.element(this).scope().fileChanged(event)" style="visibility:hidden; position:absolute"></div>'); +$templateCache.put('plugins/es/templates/common/edit_position.html','<div class="item item-divider" translate>LOCATION.LOCATION_DIVIDER</div><ion-item class="item-input item-floating-label item-button-right"><span class="input-label">{{\'LOCATION.ADDRESS\' | translate}}</span><textarea placeholder="{{\'LOCATION.ADDRESS_HELP\' | translate}}" ng-model="formData.address" ng-model-options="{ debounce: 350 }" rows="4" cols="10">\n </textarea></ion-item><div class="item item-input item-floating-label" ng-class="{\'item-input-error\': form.$submitted && form.geoPoint.$invalid}"><span class="input-label" translate>LOCATION.CITY</span> <input type="text" placeholder="{{\'LOCATION.CITY_HELP\'|translate}}" ng-model="formData.city" ng-model-options="{ updateOn: \'blur\' }" required-if="formData.address" ng-change="onCityChanged()"></div><input type="hidden" name="geoPoint" ng-model="formData.geoPoint" required-if="formPosition.enable" geo-point><div class="form-errors" ng-show="form.$submitted && form.city.$error" ng-messages="form.city.$error"><div class="form-error" ng-message="required"><span translate="LOCATION.ERROR.CITY_REQUIRED_IF_STREET"></span></div></div><div class="form-errors" ng-show="form.$submitted && form.geoPoint.$error" ng-messages="form.geoPoint.$error"><div class="form-error" ng-message="required"><span translate="LOCATION.ERROR.REQUIRED_FOR_LOCATION" ng-if="!formData.city"></span> <span translate="LOCATION.ERROR.INVALID_FOR_LOCATION" ng-if="formData.city"></span></div><div class="form-error" ng-message="geoPoint"><span translate="LOCATION.ERROR.REQUIRED_FOR_LOCATION" ng-if="!formData.city"></span> <span translate="LOCATION.ERROR.INVALID_FOR_LOCATION" ng-if="formData.city"></span></div></div><div class="item row item-text-wrap no-padding"><div class="col no-padding"><ion-checkbox ng-model="formPosition.enable" ng-change="onUseGeopointChanged()" class="item item-border-large done in"><div class="item-content"><span translate>LOCATION.USE_GEO_POINT</span><h4 class="gray" ng-if="formPosition.loading"><ion-spinner class="icon ion-spinner-small" icon="android"></ion-spinner>{{\'LOCATION.LOADING_LOCATION\'|translate}}</h4></div></ion-checkbox></div><div class="col col-10 no-padding" style="min-width: 60px"><div class="row text-center"><a class="button button-stable button-small-padding" title="{{\'LOCATION.BTN_GEOLOC_ADDRESS\'|translate}}" ng-disabled="!formPosition.enable" ng-click="openSearchLocationModal()"><i class="icon ion-home" style="left: 15px"></i> <b class="icon-secondary ion-search" style="top: -9px; left:32px; font-size: 18px"></b></a></div></div></div><cs-extension-point name="after-position"></cs-extension-point>'); +$templateCache.put('plugins/es/templates/common/edit_socials.html','<ion-list class="no-padding"><div class="item item-divider"><span>{{\'PROFILE.SOCIAL_NETWORKS_DIVIDER\' | translate}} </span><a class="badge button button-text button-small button-small-padding" ng-class="{\'button-text-positive\': socialData.reorder}" ng-if="formData.socials && formData.socials.length > 1" ng-click="socialData.reorder=!socialData.reorder"><span translate="">PROFILE.BTN_REORDER</span></a></div></ion-list><ion-list show-reorder="socialData.reorder"><ion-item class="item-remove-animate item-icon-left" type="no-padding item-text-wrap" ng-if="formData.socials && formData.socials.length" ng-repeat="social in formData.socials | filter:filterFn track by social.url" id="social-{{social.url|formatSlug}}"><i class="icon ion-social-{{social.type}}" ng-class="{\'ion-bookmark\': social.type == \'other\', \'ion-link\': social.type == \'web\', \'ion-email\': social.type == \'email\', \'ion-iphone\': social.type == \'phone\'}"></i><p ng-if="social.type && social.type != \'web\'">{{social.type}} <i class="ion-locked" ng-if="social.recipient"></i></p><h2><a href="{{social.url}}" ng-if="social.type != \'email\' && social.type != \'phone\'" target="_blank">{{social.url}}</a> <a href="mailto:{{social.url}}" ng-if="social.type == \'email\'">{{social.url}}</a> <a href="tel:{{social.url}}" ng-if="social.type == \'phone\'">{{social.url}}</a></h2><ion-option-button class="button-assertive" ng-if="!social.recipient" ng-click="formData.socials.splice($index, 1); dirty = true;">{{\'COMMON.BTN_DELETE\'|translate}}</ion-option-button><ion-option-button class="button-info" ng-if="!social.recipient" ng-click="editSocialNetwork($index)">{{\'COMMON.BTN_EDIT\'|translate}}</ion-option-button><ion-reorder-button class="ion-drag" on-reorder="reorderSocialNetwork(social, $fromIndex, $toIndex)"></ion-reorder-button></ion-item></ion-list><ion-list class="no-padding"><div class="item item-complex item-input-inset"><label class="item-input-wrapper"><input type="text" style="width:100%" placeholder="{{\'PROFILE.SOCIAL_HELP\'|translate}}" id="socialUrl" on-return="addSocialNetwork($event);" ng-model="socialData.url"></label><button class="button button-small hidden-xs" type="button" ng-click="addSocialNetwork($event)">{{\'COMMON.BTN_ADD\'|translate}}</button> <button class="button button-small button-icon icon ion-android-add visible-xs" type="button" ng-click="addSocialNetwork($event)"></button></div></ion-list>'); +$templateCache.put('plugins/es/templates/common/item_comment.html','<ng-init ng-init="level = level + 1"><a name="{{::comment.id|formatHash}}"></a><ion-item id="comment-{{::comment.id|formatHash}}" class="card card-comment card-avatar stable-900-bg item-text-wrap no-padding" ng-class="::{\'in done\': comment.isnew}"><div class="card-header padding-left" ng-if="comment.parent && !hideParent"><h5 class="gray underline"><ng-if ng-if="!comment.parent.issuer">{{\'COMMENTS.REPLY_TO_DELETED_COMMENT\'|translate}}</ng-if><ng-if ng-if="comment.parent.issuer"><a ng-click="toggleExpandedParent(comment, $index)">{{\'COMMENTS.REPLY_TO_LINK\'|translate}}<ng-if ng-if="::comment.parent.uid">{{::comment.parent.name||comment.parent.uid}}</ng-if><ng-if ng-if="::!comment.parent.uid"><i class="ion-key"></i> {{::comment.parent.name|| (comment.parent.issuer|formatPubkey) }}</ng-if></a><i ng-class="{\'ion-arrow-down-b\': !comment.expandedParent[$index], \'ion-arrow-up-b\': comment.expandedParent[$index]}"></i></ng-if></h5><div class="padding-left" ng-if="comment.expandedParent[$index]"><div class="card card-avatar card-avatar-small stable-bg item-text-wrap no-padding in done"><ng-include ng-init="comment = comment.parent" src="\'plugins/es/templates/common/item_comment_content.html\'"></ng-include></div></div></div><ng-include src="\'plugins/es/templates/common/item_comment_content.html\'"></ng-include><div class="card-footer gray"><small class="underline"><a ng-click="share($event, comment, $index)">{{comment.creationTime | formatFromNow}}</a><ng-if ng-if="comment.replyCount">| <a class="dark" ng-click="toggleExpandedReplies(comment, $index)">{{\'COMMENTS.REPLY_COUNT\'|translate:comment}}</a> <i ng-class="{\'ion-arrow-down-b\': !comment.showReplies, \'ion-arrow-up-b\': comment.showReplies}"></i></ng-if></small><div class="pull-right"><a class="ion-android-share-alt" ng-click="share($event, comment)"></a> <a class="ion-edit" ng-if="isUserPubkey(comment.issuer)" ng-click="edit(comment)"></a> <a class="ion-trash-a" ng-if="isUserPubkey(comment.issuer)" ng-click="remove(comment, $index)"></a> <a class="ion-reply" ng-click="reply(comment)">{{::\'COMMENTS.REPLY\'|translate}}</a></div></div></ion-item><div ng-if="comment.expandedReplies[$index]" class="padding-left card-avatar-small expanded" ng-init="hideParent=true"><ng-include ng-repeat="comment in comment.replies track by comment.id" src="\'plugins/es/templates/common/item_comment.html\'"></ng-include></div></ng-init>'); +$templateCache.put('plugins/es/templates/common/item_comment_content.html','<div class="item item-avatar done in"><span class="avatar" ng-if="::!comment.avatar" ng-class="::{\'avatar-member\': comment.uid, \'avatar-wallet\': !comment.uid}"></span> <span class="avatar" ng-if="::comment.avatar" style="background-image: url({{::comment.avatar.src}})"></span> <a class="pull-left" ui-sref="app.wot_identity({pubkey:comment.issuer, uid: comment.uid})"><span class="positive" ng-if="::comment.uid">{{::comment.name||comment.uid}} </span><span ng-if="::!comment.uid" class="gray"><i class="icon ion-key gray"></i> {{::comment.name || (comment.issuer|formatPubkey)}} </span></a> <span trust-as-html="comment.html"></span></div>'); +$templateCache.put('plugins/es/templates/common/item_location_search.html','<div class="item no-padding"><div class="item-input"><i class="icon ion-location placeholder-icon"></i> <input type="text" placeholder="{{(options.location.help||\'LOCATION.SEARCH_HELP\')|translate}}" ng-model-options="{ debounce: 350 }" ng-model="search.location" ng-keydown="onKeydown($event)" ng-change="onLocationChanged()" ng-blur="hideDropdown()"></div></div><ul class="item no-padding list dropdown-list" ng-if="locations" scroll="true"><div ng-if="!locations.length" class="item padding assertive"><span translate>COMMON.SEARCH_NO_RESULT</span></div><a ng-repeat="res in locations" class="item item-border-large item-text-wrap ink done in {{res.selected && \'active\' || \'\'}}" ng-class="::{\'item-divider\': !res.address, \'item-icon-left\': res.address}" ng-click="::res.address ? selectLocation(res) : false"><h4 class="text-italic" ng-if="::!res.address" ng-bind-html="res.name"></h4><ng-if ng-if="::res.address"><i class="icon ion-location"></i><h3 ng-if="res.address.road">{{::res.address.road}}</h3><h3><span ng-if="res.address.postcode">{{::res.address.postcode}}</span> {{::res.address.city||res.address.village}} <span class="gray">| {{::res.address.country}}</span></h3><h5 class="gray">{{\'LOCATION.MODAL.POSITION\'|translate:res }}</h5></ng-if></a></ul>'); +$templateCache.put('plugins/es/templates/common/modal_category.html','<ion-modal-view><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title">{{ (ctrl.title || \'COMMON.CATEGORIES\') | translate}}</h1></ion-header-bar><ion-content class="categoryModal"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="list"><label class="item item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" placeholder="{{\'COMMON.CATEGORY_SEARCH_HELP\'|translate}}" ng-model="ctrl.searchText" ng-model-options="{ debounce: 350 }" ng-change="ctrl.doSearch()"></label><div ng-repeat="cat in categories" class="item item-category item-text-wrap" ng-class="{\'item-divider\': !cat.parent}" ng-click="cat.parent ? closeModal(cat) : false"><h2 ng-bind-html="cat.name"></h2></div></div></ion-content></ion-modal-view>'); +$templateCache.put('plugins/es/templates/common/modal_edit_avatar.html','<ion-modal-view><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs visible-sm" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>PROFILE.MODAL_AVATAR.TITLE</h1><button class="button button-clear icon-right visible-xs" ng-click="doCrop()" ng-disabled="formData.imageCropStep == 1" ng-if="formData.imageCropStep <= 2"><span translate>COMMON.BTN_NEXT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-clear icon-right visible-xs" ng-click="closeModal(formData.result)" ng-if="formData.imageCropStep == 3"><i class="icon ion-android-done"></i></button></ion-header-bar><ion-content class="modal-avatar padding"><div ng-show="formData.imageCropStep == 1"><p translate>PROFILE.MODAL_AVATAR.SELECT_FILE_HELP</p><div class="item card text-center padding ink" ng-click="openFileSelector()"><i class="ion-image stable" style="font-size:150px"></i> <b class="ion-plus gray" style="position:relative; font-size:80px; top:-51px; right: 19px"></b><p translate>PROFILE.MODAL_AVATAR.BTN_SELECT_FILE</p></div><input type="file" name="fileInput" accept="image/*" id="fileInput" onchange="angular.element(this).scope().fileChanged(event)" style="visibility:hidden; position:absolute"></div><div ng-show="formData.imageCropStep == 2"><p translate>PROFILE.MODAL_AVATAR.RESIZE_HELP</p><div class="item card text-center padding ink"><image-crop data-height="200" data-width="200" data-shape="circle" data-step="formData.imageCropStep" src="formData.imgSrc" data-result="formData.result" data-result-blob="formData.resultBlob" crop="formData.initCrop" padding="150" max-size="1024"></image-crop></div></div><div ng-show="formData.imageCropStep == 3"><p translate>PROFILE.MODAL_AVATAR.RESULT_HELP</p><div class="item card padding hero" style="height: 110px"><div class="content"><img class="avatar" ng-src="{{formData.result}}" style="height: 88px; width: 88px"></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" ng-click="doCrop()" translate ng-disabled="formData.imageCropStep == 1" ng-if="formData.imageCropStep <= 2">COMMON.BTN_NEXT</button> <button class="button button-positive ink" ng-click="closeModal(formData.result)" translate ng-if="formData.imageCropStep == 3">COMMON.BTN_CONTINUE</button></div></ion-content></ion-modal-view>'); +$templateCache.put('plugins/es/templates/common/modal_location.html','<ion-modal-view class="modal-full-height modal-search-location"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button><h1 class="title" translate="">LOCATION.MODAL.TITLE</h1></ion-header-bar><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><div class="item item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{\'LOCATION.MODAL.SEARCH_HELP\'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()"></div><div class="padding-top padding-xs" style="display: block; height: 60px"><div class="pull-left" ng-if="!search.loading && search.results"><h4 translate="">COMMON.RESULTS_LIST</h4></div></div><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div ng-if="!search.loading && search.results && (!search.results.length || !search.results[0].address)" class="assertive padding"><span translate="">COMMON.SEARCH_NO_RESULT</span></div><ion-list ng-if="!search.loading" class="padding-top {{::motion.ionListClass}}"><div ng-repeat="res in search.results" class="item item-border-large item-text-wrap ink" ng-class="::{\'item-divider\': !res.address, \'item-icon-left item-icon-right\': res.address}" ng-click="res.address ? closeModal(res) : false"><h4 class="text-italic" ng-if="::!res.address" ng-bind-html="res.name"></h4><ng-if ng-if="::res.address"><i class="icon ion-location"></i><h2 ng-if="res.address.road">{{::res.address.road}}</h2><h3><span ng-if="res.address.postcode">{{::res.address.postcode}}</span> {{::res.address.city||res.address.village}} <span class="gray">| {{::res.address.country}}</span></h3><h5 class="gray">{{\'LOCATION.MODAL.POSITION\'|translate:res }}</h5><i class="icon ion-ios-arrow-right"></i></ng-if></div></ion-list></ion-content><ion-footer-bar class="stable-bg padding-left padding-right block" ng-if="license"><div class="pull-right copyright"><span class="dark">\xA9 </span><a class="positive" href="{{license.url}}" target="_blank">{{license.name}}</a></div></ion-footer-bar></ion-modal-view>'); +$templateCache.put('plugins/es/templates/common/popover_profile_extend.html','<button ng-if=":state:enable && auth" class="button button-positive button-small ink" ng-click="showEditUserProfile()">{{\'PROFILE.BTN_EDIT\' | translate}}</button>'); +$templateCache.put('plugins/es/templates/common/view_comments.html','<form class="comments" ng-controller="ESCommentsCtrl" ng-submit="save()"><div class="item item-divider"><i class="icon ion-chatboxes"></i> <span translate="">COMMENTS.DIVIDER</span> <span class="gray" ng-if="comments.total">({{comments.total}})</span></div><span class="item item-more-comments" ng-if="comments.hasMore"><small><a ng-click="showMore()" translate="">COMMENTS.SHOW_MORE_COMMENTS</a></small></span><div class="padding-right"><ng-repeat ng-repeat="comment in comments.result track by comment.id" ng-include="\'plugins/es/templates/common/item_comment.html\'"></ng-repeat></div><div class="visible-xs visible-sm" style="margin-bottom"><div class="block"><div class="item item-input-inset done in" ng-if="formData.parent"><div class="padding text-right pull-left" translate="">COMMENTS.REPLY_TO</div><br><div class="padding-left expanded"><div class="card card-comment stable-900-bg item-text-wrap no-padding in done"><ng-include ng-if="::formData.parent.message" ng-init="comment = formData.parent" src="\'plugins/es/templates/common/item_comment_content.html\'"></ng-include><span ng-if="::!formData.parent.message" translate="">COMMENTS.DELETED_COMMENT</span><div class="card-footer text-right gray"><div class="pull-right"><a class="ion-close" ng-click="removeParentLink()">{{::\'COMMON.BTN_CANCEL\'|translate}}</a></div></div></div></div></div><div class="item item-input-inset"><div class="item-input-wrapper"><input type="text" id="comment-form-input" style="width: 100%" placeholder="{{\'COMMENTS.COMMENT_HELP\'|translate}}" on-return="save();" ng-model="formData.message"> <button type="submit" class="button button-small button-small-padding button-icon button-dark button-icon gray"><i class="icon ion-android-send"></i></button></div></div></div></div></form>'); +$templateCache.put('plugins/es/templates/common/view_pictures.html','<div class="item gallery done in" ng-if="pictures && pictures.length>0"><div ng-repeat="picture in pictures" class="item card card-gallery"><div class="ink"><h2 ng-if="picture.title">{{::picture.title}}</h2><img ng-src="{{picture.src}}"></div></div></div>'); +$templateCache.put('plugins/es/templates/currency/tab_blocks_extend.html','<ng-if ng-if=":state:enable && extensionPoint === \'nav-buttons\'"><button class="button button-icon button-clear icon ion-android-search visible-xs visible-sm" ui-sref="app.blockchain_search"></button></ng-if>'); +$templateCache.put('plugins/es/templates/document/item_document.html','<ion-item id="doc-{{::doc.id}}" class="item item-document item-icon-left ink {{::ionItemClass}} no-padding-top no-padding-bottom" ng-click="selectDocument($event, doc)"><i class="icon ion-document stable" ng-if=":rebind:!doc.avatar"></i> <i class="avatar" ng-if=":rebind:doc.avatar" style="background-image: url(\'{{:rebind:doc.avatar.src}}\')"></i><div class="row no-padding"><div class="col"><h3 class="dark"><i class="ion-locked" ng-if=":rebind:doc.nonce"></i> {{:rebind:doc.time|formatDate}}</h3><h4 class="gray">{{:rebind:\'DOCUMENT.HASH\'|translate}} {{:rebind:doc.hash|formatHash}}</h4></div><div class="col"><h3><a ui-sref="app.wot_identity({pubkey: doc.pubkey, uid: doc.uid})"><span class="gray"><i class="ion-key"></i> {{:rebind:doc.pubkey|formatPubkey}} </span><span class="positive" ng-if=":rebind:doc.uid"><i class="ion-person"></i> {{:rebind:doc.name||doc.uid}}</span></a></h3></div><div class="col"><a ng-if=":rebind:login && doc.pubkey==walletData.pubkey" ng-click="remove($index)" class="gray pull-right" title="{{\'DOCUMENT.LOOKUP.BTN_REMOVE\'|translate}}"><i class="ion-trash-a"></i></a><h3 ng-if=":rebind:doc.recipient"><a ui-sref="app.wot_identity({pubkey: doc.recipient.pubkey, uid: doc.recipient.uid})"><span class="gray"><i class="ion-key"></i> {{:rebind:doc.recipient.pubkey|formatPubkey}} </span><span class="positive" ng-if=":rebind:doc.recipient.uid"><i class="ion-person"></i> {{:rebind:doc.recipient.name||doc.recipient.uid}}</span></a></h3><h4 class="gray" ng-if=":rebind:doc.read_signature"><i class="ion-checkmark"></i> <span translate>DOCUMENT.LOOKUP.READ</span></h4></div></div></ion-item>'); +$templateCache.put('plugins/es/templates/document/items_documents.html','<div class="padding gray" ng-if=":rebind:!search.loading && !search.results.length" translate="">COMMON.SEARCH_NO_RESULT</div><ng-repeat ng-repeat="doc in :rebind:search.results track by doc.id" ng-include="\'plugins/es/templates/document/item_document.html\'"></ng-repeat>'); +$templateCache.put('plugins/es/templates/document/lookup.html','<ion-view><ion-nav-title><span translate>DOCUMENT.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ng-include src="\'plugins/es/templates/document/lookup_form.html\'"></ng-include></ion-content></ion-view>'); +$templateCache.put('plugins/es/templates/document/lookup_form.html','<div class="lookupForm"><div class="item no-padding"><label class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{\'DOCUMENT.LOOKUP.SEARCH_HELP\'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearchText()"><div class="helptip-anchor-center"><a id="{{helptipPrefix}}-search-text"></a></div></label></div><div class="padding-top padding-xs" style="display: block; height: 60px"><div class="pull-left"><h4 ng-if="search.last" translate="">DOCUMENT.LOOKUP.LAST_DOCUMENTS</h4><h4 ng-if="!search.last">{{\'COMMON.RESULTS_LIST\'|translate}}</h4><h5 class="dark" ng-if="!search.loading && search.total"><span translate="COMMON.RESULTS_COUNT" translate-values="{count: search.total}"></span> <small class="gray" ng-if=":rebind:search.took && expertMode">- {{:rebind:\'COMMON.EXECUTION_TIME\'|translate: {duration: search.took} }} </small><small class="gray" ng-if=":rebind:expertMode && search.filters && search.filters.length">- <a ng-click="toggleShowQuery()" ng-if="!showQuery"><span translate="">DOCUMENT.LOOKUP.SHOW_QUERY</span> <i class="icon ion-arrow-down-b gray"></i> </a><a ng-click="toggleShowQuery()" ng-if="showQuery"><span translate="">DOCUMENT.LOOKUP.HIDE_QUERY</span> <i class="icon ion-arrow-up-b gray"></i></a></small></h5><h5 class="gray" ng-if="search.loading"><ion-spinner class="icon ion-spinner-small" icon="android"></ion-spinner><span translate="">COMMON.SEARCHING</span><br></h5></div></div><div class="item no-border no-padding" ng-if=":rebind:search.filters && search.filters.length && expertMode"><small class="no-padding no-margin" ng-if="showQuery"><span class="gray text-wrap dark">{{:rebind:search.query}}</span></small></div><ion-list class="list" ng-class="::motion.ionListClass"><ng-include src="\'plugins/es/templates/document/items_documents.html\'"></ng-include></ion-list><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll></div>'); +$templateCache.put('plugins/es/templates/document/lookup_popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>DOCUMENT.LOOKUP.POPOVER_ACTIONS.TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left assertive ink" ng-class="{\'gray\': !search.total}" ng-click="removeAll()"><i class="icon ion-trash-a"></i> {{\'DOCUMENT.LOOKUP.POPOVER_ACTIONS.REMOVE_ALL\' | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/group/edit_group.html','<ion-view left-buttons="leftButtons"><ion-nav-title><span class="visible-xs" ng-if="id" ng-bind-html="formData.title"></span> <span class="visible-xs" ng-if="!loading && !id" translate="">GROUP.EDIT.TITLE_NEW</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear visible-xs visible-sm" ng-class="{\'ion-android-send\':!id, \'ion-android-done\': id}" ng-click="save()"></button></ion-nav-buttons><ion-content scroll="true"><div class="row no-padding"><div class="col"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><form name="recordForm" novalidate="" ng-submit="save()"><div class="list" ng-class="motion.ionListClass" ng-init="setForm(recordForm)"><div class="item hidden-xs"><h1 ng-if="id" ng-bind-html="formData.title"></h1><h1 ng-if="!id" translate="">GROUP.EDIT.TITLE_NEW</h1><h2 class="balanced" ng-if="!id"><i class="icon ion-android-people"></i> <i class="icon ion-android-lock" ng-if="formData.type==\'managed\'"></i> {{\'GROUP.TYPE.ENUM.\'+formData.type|upper|translate}}</h2></div><div class="item" ng-if="id"><h4 class="gray"><i class="icon ion-calendar"></i> {{\'COMMON.LAST_MODIFICATION_DATE\'|translate}} {{formData.time | formatDate}}</h4><div class="badge badge-balanced badge-editable" ng-click="showRecordTypeModal()">{{\'GROUP.TYPE.ENUM.\'+formData.type|upper|translate}}</div></div><ng-include src="\'plugins/es/templates/common/edit_pictures.html\'"></ng-include><div class="item item-divider" translate="">GROUP.GENERAL_DIVIDER</div><div class="item item-input item-floating-label" ng-class="{\'item-input-error\': form.$submitted && form.title.$invalid}"><span class="input-label" translate="">GROUP.EDIT.RECORD_TITLE</span> <input type="text" placeholder="{{\'GROUP.EDIT.RECORD_TITLE_HELP\'|translate}}" name="title" id="group-record-title" ng-model="formData.title" ng-minlength="3" ng-required="true"></div><div class="form-errors" ng-if="form.$submitted && form.title.$error" ng-messages="form.title.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div><div class="item item-input item-floating-label"><span class="input-label" translate="">GROUP.EDIT.RECORD_DESCRIPTION</span><textarea placeholder="{{\'GROUP.EDIT.RECORD_DESCRIPTION_HELP\'|translate}}" ng-model="formData.description" rows="8" cols="10">\n </textarea></div><ng-include src="\'plugins/es/templates/common/edit_socials.html\'" ng-controller="ESSocialsEditCtrl"></ng-include></div></form></div></div></ion-content></ion-view>'); +$templateCache.put('plugins/es/templates/group/item_group.html','<a name="group-{{:rebind:group.hash}}"></a><div id="group-{{:rebind:group.hash}}" class="item item-icon-right item-avatar {{::ionItemClass}} ink" ng-click="select(group)"><i class="item-image avatar" style="background-image: url({{::group.avatar.src}})" ng-if="group.avatar"></i> <i class="item-image icon ion-android-people" ng-if="!group.avatar"></i> <i class="item-image icon-secondary ion-android-lock" ng-if="!group.avatar" style="left: 20px; top: 17px; font-size: 19px; color: #d9d9d9"></i><h2 ng-bind-html=":rebind:group.title"></h2><h4 class="gray pull-right"><i class="ion-clock"></i> {{:rebind:\'GROUP.CREATED_TIME\'|translate: group }}</h4><h4 class="dark pull-left" ng-if=":rebind:group.membersCount"><i class="dark ion-person"></i> <span class="dark">+{{:rebind:group.membersCount}}</span></h4><i class="icon ion-ios-arrow-right"></i></div>'); +$templateCache.put('plugins/es/templates/group/items_groups.html','<div class="padding gray" ng-if=":rebind:!search.loading && !search.results.length" translate="">COMMON.SEARCH_NO_RESULT</div><ng-repeat ng-repeat="group in :rebind:search.results" ng-include="\'plugins/es/templates/group/item_group.html\'"></ng-repeat>'); +$templateCache.put('plugins/es/templates/group/list.html','<ion-list class="{{::motion.ionListClass}}"><ion-item ng-repeat="notification in search.results" class="item-border-large item-text-wrap ink item-avatar" ng-class="{\'unread\': !notification.read}" ng-click="select(notification)"><i ng-if="!notification.avatar" class="item-image icon {{::notification.avatarIcon}}"></i> <i ng-if="notification.avatar" class="item-image avatar" style="background-image: url({{::notification.avatar.src}})"></i><h3 trust-as-html="notification.message | translate:notification"></h3><h4><i class="icon {{notification.icon}}"></i> <span class="dark">{{notification.time|formatFromNow}}</span> <span class="gray">| {{notification.time|formatDate}}</span></h4></ion-item></ion-list><ion-infinite-scroll ng-if="!search.loading && search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll>'); +$templateCache.put('plugins/es/templates/group/lookup.html','<ion-view class="view-group"><ion-nav-title><span translate>GROUP.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ng-include src="\'plugins/es/templates/group/lookup_form.html\'"></ng-include></ion-content></ion-view>'); +$templateCache.put('plugins/es/templates/group/lookup_form.html','<div class="lookupForm"><label class="item item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{\'GROUP.LOOKUP.SEARCH_HELP\'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearchText()"><div class="helptip-anchor-center"><a id="helptip-group-search-text"></a></div></label><div class="padding-top padding-xs" style="display: block; height: 60px"><div class="pull-left"><h4 ng-if="search.type==\'open\'" translate="">GROUP.LOOKUP.OPEN_RESULTS_LIST</h4><h4 ng-if="search.type==\'last\'" translate="">GROUP.LOOKUP.LAST_RESULTS_LIST</h4><h4 ng-if="search.type==\'managed\'" translate="">GROUP.LOOKUP.MANAGED_RESULTS_LIST</h4><h4 ng-if="search.type==\'text\'">{{\'COMMON.RESULTS_LIST\'|translate}}</h4><h5 class="dark" ng-if="!search.loading && search.total"><span translate="COMMON.RESULTS_COUNT" translate-values="{count: search.total}"></span> <small class="gray" ng-if=":rebind:search.took && expertMode">- {{:rebind:\'COMMON.EXECUTION_TIME\'|translate: {duration: search.took} }}</small></h5><h5 class="gray" ng-if="search.loading"><ion-spinner class="icon ion-spinner-small" icon="android"></ion-spinner><span translate="">COMMON.SEARCHING</span><br></h5></div></div><div class="list {{::motion.ionListClass}}" ng-if="!$scope.search.loading"><ng-include src="\'plugins/es/templates/group/items_groups.html\'"></ng-include></div><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll></div>'); +$templateCache.put('plugins/es/templates/group/lookup_item.html','<i class="item-image avatar" style="background-image: url({{::item.avatar.src}})" ng-if="item.avatar"></i> <i class="item-image icon ion-android-people" ng-if="!item.avatar"></i> <i class="item-image icon-secondary ion-android-lock" ng-if="!item.avatar" style="left: 20px; top: 17px; font-size: 19px; color: #d9d9d9"></i><h2 ng-bind-html=":rebind:item.title"></h2><h4 class="gray pull-right"><i class="ion-clock"></i> {{:rebind:\'GROUP.CREATED_TIME\'|translate: item }}</h4><h4 class="dark pull-left" ng-if=":rebind:item.membersCount"><i class="dark ion-person"></i> <span class="dark">+{{:rebind:item.membersCount}}</span></h4>'); +$templateCache.put('plugins/es/templates/group/modal_record_type.html','<ion-modal-view><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>GROUP.TYPE.TITLE</h1></ion-header-bar><ion-content class="lookupForm padding"><h3 translate>GROUP.TYPE.SELECT_TYPE</h3><div class="list"><div class="item item-complex card stable-bg item-icon-left ink" ng-click="closeModal(\'open\')"><div class="item-content item-text-wrap"><i class="item-image icon ion-android-people dark"></i><h2 translate>GROUP.TYPE.OPEN_GROUP</h2><h4 class="gray" translate>GROUP.TYPE.OPEN_GROUP_HELP</h4></div></div><div class="item item-complex card stable-bg item-icon-left ink" ng-click="closeModal(\'managed\')"><div class="item-content item-text-wrap"><i class="item-image icon ion-android-people dark"></i> <i class="icon-secondary ion-android-lock dark" style="left: 10px; top: -8px"></i><h2 translate>GROUP.TYPE.MANAGED_GROUP</h2><h4 class="gray" translate>GROUP.TYPE.MANAGED_GROUP_HELP</h4></div></div></div></ion-content></ion-modal-view>'); +$templateCache.put('plugins/es/templates/group/view_popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>GROUP.VIEW.MENU_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-click="showSharePopover($event)"><i class="icon ion-android-share-alt"></i> {{\'COMMON.BTN_SHARE\' | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/group/view_record.html','<ion-view left-buttons="leftButtons"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-bar button-icon button-clear visible-xs visible-sm" ng-click="edit()" ng-if="canEdit"><i class="icon ion-android-create"></i></button> <button class="button button-bar button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true"><div class="positive-900-bg hero"><div class="content" ng-if="!loading"><i class="avatar cion-registry-{{formData.type}}" ng-if="!formData.avatar"></i> <i class="avatar" style="background-image: url({{::formData.avatar.src}})" ng-if="formData.avatar"></i><h3 ng-bind-html="formData.title"></h3><h4> </h4></div><h4 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><div class="row no-padding-xs no-padding-sm"><div class="col list item-text-wrap no-padding-xs no-padding-sm" ng-class="::motion.ionListClass"><div class="item"><h2 class="gray"><a ng-if="formData.city" ui-sref="app.groups({location:formData.city})"><i class="icon ion-location"></i> <span ng-bind-html="formData.city"></span> </a><span ng-if="formData.city && formData.type"> | </span> <a ng-if="formData.type" ui-sref="app.groups({type:formData.type})"><i class="icon ion-flag"></i> {{\'GROUP.TYPE.ENUM.\'+formData.type|upper|translate}}</a></h2><h4><i class="icon ion-clock" ng-if="formData.time"></i> <span translate="">COMMON.SUBMIT_BY</span> <a ng-class="{\'positive\': issuer.uid, \'gray\': !issuer.uid}" ui-sref="app.wot_identity({pubkey:issuer.pubkey, uid: issuer.name||issuer.uid})"><ng-if ng-if="issuer.uid"><i class="icon ion-person"></i> {{::issuer.name||issuer.uid}}</ng-if><span ng-if="!issuer.uid"><i class="icon ion-key"></i> {{issuer.pubkey|formatPubkey}} </span></a><span>{{formData.time|formatFromNow}}<h4 class="gray hidden-xs">| {{formData.time | formatDate}}</h4></span></h4></div><a id="group-share-anchor-{{id}}"></a><ion-item><h2><span trust-as-html="formData.description"></span></h2></ion-item><ion-item><h4 ng-if="formData.address"><span class="gray" translate="">REGISTRY.VIEW.LOCATION</span> <a class="positive" target="_blank" href="https://www.google.fr/maps/?q={{formData.address}},%20{{formData.city}}"><span ng-bind-html="formData.address"></span> <span ng-if="formData.city">- </span><span ng-bind-html="formData.city"></span></a></h4></ion-item><ng-if ng-if="formData.socials && formData.socials.length>0"><ion-item class="item-icon-left" type="no-padding item-text-wrap" ng-repeat="social in formData.socials track by social.url" id="social-{{social.url|formatSlug}}"><i class="icon ion-social-{{social.type}}" ng-class="{\'ion-bookmark\': social.type == \'other\', \'ion-link\': social.type == \'web\', \'ion-email\': social.type == \'email\'}"></i><p ng-if="social.type && social.type != \'web\'">{{social.type}}</p><h2><a href="{{social.url}}" ng-if="social.type != \'email\'" target="_blank">{{social.url}}</a> <a href="mailto:{{social.url}}" ng-if="social.type == \'email\'">{{social.url}}</a></h2></ion-item></ng-if><div class="lazy-load"><ng-include src="\'plugins/es/templates/common/view_pictures.html\'"></ng-include><span class="item item-divider" ng-if="formData.pubkey"><span translate="">REGISTRY.TECHNICAL_DIVIDER</span></span><div class="item item-icon-left item-text-wrap ink" ng-if="formData.pubkey" copy-on-click="{{::formData.pubkey}}"><i class="icon ion-key"></i> <span translate="">REGISTRY.EDIT.RECORD_PUBKEY</span><h4 class="dark">{{::formData.pubkey}}</h4></div><ng-include src="\'plugins/es/templates/common/view_comments.html\'"></ng-include></div></div></div></ion-content><button class="button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm" ng-if="formData.pubkey && !isUserPubkey(formData.pubkey)" ng-click="showTransferModal({pubkey: formData.pubkey, uid: formData.title})"></button></ion-view>'); +$templateCache.put('plugins/es/templates/invitation/list_invitation.html','<ion-list class="{{::motion.ionListClass}}"><ion-item ng-repeat="invitation in search.results" class="item-border-large item-text-wrap item-avatar"><i ng-if="::!invitation.avatar" class="item-image icon {{::invitation.avatarIcon}}"></i> <i ng-if="::invitation.avatar" class="item-image avatar" style="background-image: url({{::invitation.avatar.src}})"></i><h3 trust-as-html="invitation.message | translate:invitation"></h3><h3 class="dark text-italic" ng-if="invitation.comment"><i class="icon ion-quote"></i> <span ng-bind-html="invitation.comment"></span></h3><h4><i class="icon {{::invitation.icon}}"></i> <span class="dark" ng-if="::invitation.issuer" trust-as-html="\'INVITATION.SUGGESTED_BY\' | translate:invitation"></span> <span class="dark">{{::invitation.time|formatFromNow}}</span> <span class="gray">| {{::invitation.time|formatDate}}</span></h4><div class="block text-right"><button class="button button-positive button-small button-small-padding" ng-click="accept(invitation)" ng-if="::invitation.state" translate>{{::(invitation.okText||\'COMMON.BTN_SHOW\') |translate}}</button> <button class="button button-stable button-small button-small-padding" ng-click="delete($index)" translate>INVITATION.BTN_DELETE</button></div></ion-item></ion-list><ion-infinite-scroll ng-if="!search.loading && search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll>'); +$templateCache.put('plugins/es/templates/invitation/modal_new_invitation.html','<ion-modal-view id="transfer" class="modal-invitation modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>INVITATION.NEW.TITLE</h1><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doSend()"></button></ion-header-bar><ion-content scroll="true"><ng-include src="\'plugins/es/templates/invitation/new_invitation_form.html\'"></ng-include></ion-content></ion-modal-view>'); +$templateCache.put('plugins/es/templates/invitation/new_invitation_form.html','<form name="invitationForm" novalidate="" ng-submit="doSend()"><div class="list" ng-init="setForm(invitationForm)"><a class="item item-icon-right gray ink" ng-class="{\'disable-pointer-events\': recipients.length, \'item-input-error\': form.$submitted && !recipients.length}" ng-click="showSelectRecipientModal($event)"><span class="gray" translate="">INVITATION.NEW.RECIPIENTS</span> <span class="item-note"><span class="hidden-xs" ng-if="!recipients.length" translate="">INVITATION.NEW.RECIPIENTS_HELP</span><ng-repeat ng-repeat="identity in recipients track by identity.id" class="button button-small button-text button-stable button-icon-event ink" ng-class="{\'button-text-positive\': identity.selected}"><ng-bind-html ng-bind-html="identity.name||identity.uid||(identity.pubkey|formatPubkey)"></ng-bind-html><b class="enable-pointer-events ion-close" ng-click="removeRecipient($index, $event)"> </b></ng-repeat></span><i class="gray icon enable-pointer-events ion-ios-arrow-right"></i></a><div class="form-errors" ng-if="form.$submitted && !recipients.length"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><a class="item item-icon-right gray ink" ng-class="{\'disable-pointer-events\': suggestions.length, \'item-input-error\': form.$submitted && !suggestions.length}" ng-click="showSelectSuggestionModal($event)"><span class="gray enable-pointer-events" translate="">INVITATION.NEW.SUGGESTION_IDENTITIES</span> <span class="item-note"><span class="hidden-xs" ng-if="!suggestions.length" translate="">INVITATION.NEW.SUGGESTION_IDENTITIES_HELP</span><ng-repeat ng-repeat="identity in suggestions track by identity.id" class="button button-small button-text button-stable button-icon-event ink" ng-class="{\'button-text-positive\': identity.selected}"><ng-bind-html ng-bind-html="identity.name||identity.uid||(identity.pubkey|formatPubkey)"></ng-bind-html><b class="enable-pointer-events ion-close" ng-click="removeSuggestion($index, $event)"> </b></ng-repeat></span><i class="gray icon enable-pointer-events ion-ios-arrow-right"></i></a><div class="form-errors" ng-if="form.$submitted && !suggestions.length"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-content item-toggle dark visible-xs visible-sm"><span class="input-label gray">{{\'TRANSFER.BTN_ADD_COMMENT\' | translate}}</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.useComment"><div class="track"><div class="handle"></div></div></label></div><label class="item item-input item-floating-label visible-xs visible-sm" ng-if="formData.useComment" ng-class="{\'item-input-error\': form.$submitted && form.comment.$invalid}"><span class="input-label">{{\'TRANSFER.COMMENT\' | translate}}</span><textarea placeholder="{{\'TRANSFER.COMMENT_HELP\' | translate}}" name="comment" ng-model="formData.comment" ng-maxlength="255">\n </textarea></label><div class="form-errors" ng-show="form.$submitted && form.comment.$error" ng-messages="form.comment.$error"><div class="form-error" ng-message="maxlength"><span translate="ERROR.FIELD_TOO_LONG"></span></div><div class="form-error" ng-message="pattern"><span translate="ERROR.FIELD_ACCENT"></span></div></div></div><div class="padding hidden-xs text-right"><button class="button button-small button-clear button-dark ink" ng-click="cancel()" type="button" translate="">COMMON.BTN_CANCEL</button> <button class="button button-small button-positive ink" type="submit">{{\'COMMON.BTN_SEND\' | translate}}</button></div></form>'); +$templateCache.put('plugins/es/templates/invitation/popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-class="{\'gray\': !search.results.length, \'assertive\': search.results.length}" ng-click="deleteAll()"><i class="icon ion-trash-a"></i> <span translate>INVITATION.BTN_DELETE_ALL</span></a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/invitation/popover_invitation.html',''); +$templateCache.put('plugins/es/templates/invitation/view_invitations.html','<ion-view left-buttons="leftButtons" class="view-invitation"><ion-nav-title>{{\'INVITATION.LIST.TITLE\' | translate}}</ion-nav-title><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><div class="row no-padding"><div class="col no-padding-xs no-padding-sm"><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="padding gray" ng-if="!search.loading && !search.results.length" translate="">INVITATION.NO_RESULT</div><ng-include src="\'plugins/es/templates/invitation/list_invitation.html\'"></ng-include></div></div></ion-content><button id="fab-new-invitation" class="button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm spin" ng-click="showNewInvitationModal()"></button></ion-view>'); +$templateCache.put('plugins/es/templates/join/modal_join_extend.html','<ng-if ng-if=":state:enable && extensionPoint === \'select-account-type\'"><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-class="{ activated: accountTypeMember != null && !accountTypeMember }" ng-click="selectAccountType(\'organization\')"><div class="item-content item-text-wrap"><i class="item-image icon dark cion-registry-association"></i><h2 translate>ACCOUNT.NEW.ORGANIZATION_ACCOUNT</h2><h4 class="gray" translate>ACCOUNT.NEW.ORGANIZATION_ACCOUNT_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div></ng-if><ng-if ng-if=":state:enable && extensionPoint === \'last-slide\'"><ion-slide-page><ion-content class="has-header" scroll="false"><p>TOTO</p></ion-content></ion-slide-page></ng-if>'); +$templateCache.put('plugins/es/templates/message/compose.html','<ion-view left-buttons="leftButtons" id="composeMessage"><ion-nav-title><span class="visible-xs visible-sm" nf-if="!isReply" translate="">MESSAGE.COMPOSE.TITLE</span> <span class="visible-xs visible-sm" nf-if="isReply" translate="">MESSAGE.COMPOSE.TITLE_REPLY</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doSend()"></button></ion-nav-buttons><ion-content scroll="true"><div class="row"><div class="col"><ng-include src="\'plugins/es/templates/message/compose_form.html\'"></ng-include></div></div></ion-content></ion-view>'); +$templateCache.put('plugins/es/templates/message/compose_form.html','<form name="messageForm" novalidate="" ng-submit="doSend()"><div class="list no-margin" ng-init="setForm(messageForm)"><a class="item item-icon-right gray ink" ng-class="{\'item-input-error\': form.$submitted && !formData.destPub}" ng-click="showWotLookupModal()"><span class="gray" translate>MESSAGE.COMPOSE.TO</span> <span class="badge badge-royal" ng-if="destUid"><i class="ion-person"></i> {{destName||destUid}}</span> <span class="badge badge-stable" ng-if="!destUid && destPub">{{destName}} <span ng-if="!destName"><i class="ion-key"></i>{{destPub | formatPubkey}}</span> </span> <i class="gray icon ion-ios-arrow-right"></i></a><div class="form-errors" ng-if="form.$submitted && !formData.destPub"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><ion-item class="item-text-wrap ink" ng-class="{\'item-icon-right\': enableSelectWallet}" ng-click="showSelectWalletModal()"><span class="gray" translate>TRANSFER.FROM</span> <span class="badge badge-balanced animate-fade-in animate-show-hide" ng-show="!loading"><ion-spinner icon="android" ng-if="!walletData.pubkey"></ion-spinner><span ng-if="walletData.pubkey && !walletData.isMember"><i class="ion-key"></i> {{walletData.pubkey| formatPubkey}} </span><span ng-if="walletData.isMember"><i class="ion-person"></i> {{walletData.name||walletData.uid}} </span></span><i class="gray icon ion-ios-arrow-right" ng-if="enableSelectWallet"></i></ion-item><div class="item item-input" ng-class="{\'item-input-error\': form.$submitted && form.title.$invalid}"><input type="text" autocomplete="off" placeholder="{{\'MESSAGE.COMPOSE.OBJECT_HELP\' | translate}}" name="title" ng-model="formData.title" ng-maxlength="256" required> <span class="badge item-note" ng-if="isReply">({{\'MESSAGE.COMPOSE.OBJECT\' | translate}})</span></div><div class="form-errors" ng-show="form.$submitted && form.title.$error" ng-messages="form.title.$error"><div class="form-error" ng-message="maxlength"><span translate="MESSAGE.ERROR.MESSAGE_CONTENT_TOO_LONG" translate-values="{maxLength: 256}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-input item-floating-label" ng-class="{\'item-input-error\': form.$submitted && form.content.$invalid}"><span class="input-label">{{\'MESSAGE.COMPOSE.MESSAGE\' | translate}}</span><textarea placeholder="{{\'MESSAGE.COMPOSE.MESSAGE_HELP\' | translate}}" autocomplete="off" name="content" ng-model="formData.content" rows="8" ng-maxlength="5000">\n </textarea></div><div class="form-errors" ng-show="form.$submitted && form.content.$error" ng-messages="form.content.$error"><div class="form-error" ng-message="maxlength"><span translate="MESSAGE.ERROR.MESSAGE_CONTENT_TOO_LONG" translate-values="{maxLength: 5000}"></span></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="cancel()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" type="submit" ng-disabled="sending" translate>TRANSFER.BTN_SEND</button></div><div class="list no-margin"><div class="item item-icon-left item-text-wrap"><i class="icon ion-ios-information-outline positive"></i><h4 class="positive" translate>MESSAGE.COMPOSE.ENCRYPTED_HELP</h4></div></div></form>'); +$templateCache.put('plugins/es/templates/message/list.html','<div class="padding gray" ng-if="!search.loading && !search.results.length"><span ng-if="search.type==\'last\'">{{ (\'MESSAGE.NO_MESSAGE_\' + type) | upper | translate }}</span> <span ng-if="search.type==\'text\'" translate="">COMMON.SEARCH_NO_RESULT</span></div><ion-list class="{{::motion.ionListClass}}" can-swipe="$root.device.enable"><ion-item class="item item-border-large item-avatar item-icon-right ink" ng-repeat="msg in :rebind:search.results track by msg.id" ng-click="select(msg, $event)"><i ng-if="::!msg.avatar" class="item-image icon" ng-class="{\'ion-person\': msg.uid, \'ion-email\': !msg.uid}"></i> <i ng-if="::msg.avatar" class="item-image avatar" style="background-image: url({{::msg.avatar.src}})"></i><h4 class="pull-right visible-xs visible-sm dark"><i class="ion-clock"></i> {{::msg.time|formatFromNow}}</h4><h3><a class="positive" ng-if="::msg.name||msg.uid" ui-sref="app.wot_identity({pubkey:msg.issuer, uid:msg.name||msg.uid})"><i class="ion-person"></i> {{::msg.name||msg.uid}} </a><a class="gray" ng-if="::!msg.name && !msg.uid" ui-sref="app.wot_identity({pubkey:msg.issuer})"><i class="ion-key"></i> {{::msg.issuer|formatPubkey}}</a></h3><h2 ng-class="{\'unread\': !msg.read}" ng-bind-html="::msg.title"></h2><p ng-bind-html="::msg.summary||msg.content"></p><i class="icon ion-ios-arrow-right"></i><ion-option-button class="button-stable" ng-click="showReplyModal($index)" translate="">MESSAGE.BTN_REPLY</ion-option-button><ion-option-button class="button-assertive" ng-click="delete($index)" translate="">COMMON.BTN_DELETE</ion-option-button></ion-item></ion-list><ion-infinite-scroll ng-if="!search.loading && search.hasMore" icon="ion-loading-c" on-infinite="showMore()" distance="10%"></ion-infinite-scroll>'); +$templateCache.put('plugins/es/templates/message/lookup.html','<ion-view left-buttons="leftButtons" class="view-messages"><ion-tabs class="tabs-positive tabs-icon-top"><ion-tab title="{{\'MESSAGE.LIST.INBOX\'|translate}}" icon="ion-archive" ui-sref="app.user_message.tab_inbox"><ion-nav-view name="tab_inbox"></ion-nav-view></ion-tab><ion-tab title="{{\'MESSAGE.LIST.OUTBOX\'|translate}}" icon="ion-paper-airplane" ui-sref="app.user_message.tab_outbox"><ion-nav-view name="tab_outbox"></ion-nav-view></ion-tab></ion-tabs></ion-view>'); +$templateCache.put('plugins/es/templates/message/lookup_by_id.html','<ion-view left-buttons="leftButtons" class="view-messages"><ion-tabs class="tabs-positive tabs-icon-top"><ion-tab title="{{\'MESSAGE.LIST.INBOX\'|translate}}" icon="ion-archive" ui-sref="app.user_messages_by_id.tab_inbox"><ion-nav-view name="tab_inbox"></ion-nav-view></ion-tab><ion-tab title="{{\'MESSAGE.LIST.OUTBOX\'|translate}}" icon="ion-paper-airplane" ui-sref="app.user_messages_by_id.tab_outbox"><ion-nav-view name="tab_outbox"></ion-nav-view></ion-tab></ion-tabs></ion-view>'); +$templateCache.put('plugins/es/templates/message/lookup_lg.html','<ion-view left-buttons="leftButtons" class="view-messages"><ion-nav-title><span translate="">MESSAGE.LIST.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear visible-xs visible-sm" ng-click="showActionsPopover($event)"><i class="icon ion-android-more-vertical"></i></button></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm"><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="refresh(true, $event)"></ion-refresher><div class="item no-padding"><div class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{\'MESSAGE.LIST.SEARCH_HELP\'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()" on-return="doSearch()" select-on-click=""><div class="helptip-anchor-center"><a id="helptip-message-search-text"></a></div></div></div><div class="padding-top hidden-xs" style="display: block; height: 60px"><div class="pull-left" ng-if="!search.loading"><ng-if ng-if="search.type==\'last\'"><h4>{{ (\'MESSAGE.LIST.LAST_\' + type) | upper | translate}}</h4></ng-if><ng-if ng-if="search.type==\'text\'"><h4 translate="">COMMON.RESULTS_LIST</h4></ng-if></div></div><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><ng-include src="\'plugins/es/templates/message/list.html\'"></ng-include></ion-content><button id="fab-add-message-record" class="button button-fab button-fab-bottom-right button-assertive icon ion-compose visible-xs visible-sm spin" ng-click="showNewMessageModal()"></button></ion-view>'); +$templateCache.put('plugins/es/templates/message/lookup_popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>MESSAGE.LIST.POPOVER_ACTIONS.TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-class="{\'gray\': (type != \'inbox\' && !messages.length)}" ng-click="markAllAsRead()"><i class="icon ion-android-checkmark-circle"></i> {{\'COMMON.NOTIFICATIONS.MARK_ALL_AS_READ\' | translate}} </a><a class="item item-icon-left assertive ink" ng-class="{\'gray\': !messages.length}" ng-click="deleteAll()"><i class="icon ion-trash-a"></i> {{\'MESSAGE.LIST.POPOVER_ACTIONS.DELETE_ALL\' | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/message/modal_compose.html','<ion-modal-view id="composeMessage" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" ng-if="!isReply" translate>MESSAGE.COMPOSE.TITLE</h1><h1 class="title" ng-if="isReply" translate>MESSAGE.COMPOSE.TITLE_REPLY</h1><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doSend()"></button></ion-header-bar><ion-content scroll="true"><ng-include src="\'plugins/es/templates/message/compose_form.html\'"></ng-include></ion-content></ion-modal-view>'); +$templateCache.put('plugins/es/templates/message/popover_message.html',''); +$templateCache.put('plugins/es/templates/message/view_message.html','<ion-view left-buttons="leftButtons" class="view-message"><ion-nav-title><span translate="">MESSAGE.VIEW.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true"><div class="row no-padding"><div class="col no-padding"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="list animate-fade-slide-in item-text-wrap"><div class="item item-avatar" ng-class="{\'item-avatar\': formData.avatar}"><i ng-if="!formData.avatar" class="item-image" ng-class="{\'ion-person\': formData.uid, \'ion-email\': !formData.uid}"></i> <i ng-if="formData.avatar" class="item-image avatar" style="background-image: url({{::formData.avatar.src}})"></i><h4>{{type == \'inbox\' ? \'MESSAGE.VIEW.SENDER\': \'MESSAGE.VIEW.RECIPIENT\'|translate}} <a class="positive" ui-sref="app.wot_identity({pubkey: (type == \'inbox\') ? formData.issuer : formData.recipient, uid: formData.name||formData.uid})"><span ng-if="formData.uid"><i class="ion-person"></i> {{formData.name||formData.uid}} </span><span ng-if="!formData.uid" class="gray"><i class="ion-key gray"></i> {{formData.name||(formData.issuer|formatPubkey)}}</span></a></h4><h5 class="gray visible-xs visible-sm"><i class="ion-clock"></i> {{formData.time | formatDate}}</h5></div><ion-item class="visible-xs visible-sm"><h1 class="title" ng-bind-html="formData.title"></h1></ion-item><ion-item><p ng-bind-html="formData.html"></p><div class="padding gray" ng-if="!formData.content" translate="">MESSAGE.VIEW.NO_CONTENT</div></ion-item></div></div></div></ion-content><button id="fab-view-message-reply" class="button button-fab button-fab-bottom-right button-calm icon ion-reply visible-xs visible-sm spin" ng-click="showReplyModal()"></button></ion-view>'); +$templateCache.put('plugins/es/templates/message/view_popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left assertive ink" ng-click="delete()"><i class="icon ion-trash-a"></i> {{\'MESSAGE.VIEW.DELETE\' | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/network/view_network_extend.html','<ng-if ng-if=":state:enable"><a class="button button-text button-small ink" ui-sref="app.blockchain_search"><i class="icon ion-android-search"></i> <span>{{\'COMMON.BTN_SEARCH\'|translate}}</span></a></ng-if>'); +$templateCache.put('plugins/es/templates/notification/list_notification.html','<ion-list class="{{::motion.ionListClass}}"><ion-item ng-repeat="notification in search.results track by notification.id" class="item-border-large item-text-wrap ink item-avatar" ng-class="{\'unread\': !notification.read}" ng-click="select($event, notification)"><i ng-if="!notification.avatar" class="item-image icon {{::notification.avatarIcon}}"></i> <i ng-if="notification.avatar" class="item-image avatar" style="background-image: url({{::notification.avatar.src}})"></i><h3 trust-as-html="notification.message | translate:(notification.messageParams||notification)"></h3><h4 ng-if="!notification.medianTime"><i class="icon {{notification.icon}}"></i> <span class="dark">{{notification.time|formatFromNow}}</span> <span class="gray">| {{notification.time|formatDate}}</span></h4><h4 ng-if="notification.medianTime"><i class="icon {{notification.icon}}"></i> <span class="dark">{{notification.medianTime|medianFromNow}}</span> <span class="gray">| {{notification.medianTime|medianDate}}</span></h4></ion-item></ion-list><ion-infinite-scroll ng-if="!search.loading && search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll>'); +$templateCache.put('plugins/es/templates/notification/popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-disabled="!search.results.length" ng-click="markAllAsRead()"><i class="icon ion-android-checkmark-circle"></i> {{\'COMMON.NOTIFICATIONS.MARK_ALL_AS_READ\' | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/notification/popover_notification.html',''); +$templateCache.put('plugins/es/templates/notification/view_notifications.html','<ion-view left-buttons="leftButtons" class="view-notification"><ion-nav-title>{{\'COMMON.NOTIFICATIONS.TITLE\' | translate}}</ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="refresh(true)"></ion-refresher><div class="row no-padding"><div class="col no-padding-xs no-padding-sm"><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="padding gray" ng-if="!search.loading && !search.results.length" translate="">COMMON.NOTIFICATIONS.NO_RESULT</div><ng-include src="\'plugins/es/templates/notification/list_notification.html\'"></ng-include></div></div></ion-content></ion-view>'); +$templateCache.put('plugins/es/templates/registry/edit_record.html','<ion-view left-buttons="leftButtons" class="view-page"><ion-nav-title><span class="visible-xs" ng-if="id" ng-bind-html="formData.title"></span> <span class="visible-xs" ng-if="!loading && !id" translate="">REGISTRY.EDIT.TITLE_NEW</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear visible-xs visible-sm" ng-class="{\'ion-android-send\':!id, \'ion-android-done\': id}" ng-click="save()"></button></ion-nav-buttons><ion-content scroll="true"><div class="hero"><div class="content"><i class="avatar" ng-class="avatarClass" ng-style="avatarStyle"><button class="button button-positive button-large button-clear flat icon ion-camera visible-xs visible-sm" style="display: inline-block" ng-click="showAvatarModal()"></button> <button ng-if="avatar.src" class="button button-positive button-large button-clear flat visible-xs visible-sm" style="display: inline-block; left: 85px; bottom:15px" ng-click="rotateAvatar()"><i class="icon-secondary ion-image" style="left: 24px; top: 3px; font-size: 24px"></i> <i class="icon-secondary ion-forward" style="left: 26px; top: -13px"></i></button></i><h3 class="dark"><span ng-if="!loading && formData.title">{{formData.title}}</span> <span ng-if="!loading && !id && !formData.title" translate="">REGISTRY.EDIT.TITLE_NEW</span></h3><h4 class="dark"><ion-spinner ng-if="loading" icon="android"></ion-spinner></h4></div></div><div class="row no-padding"><div class="col no-padding-xs no-padding-sm"><form name="recordForm" novalidate="" ng-submit="save()"><div class="list {{::motion.ionListClass}}" ng-init="setForm(recordForm)"><div class="item" ng-if="id"><h4 class="gray"><i class="icon ion-calendar"></i> {{\'COMMON.LAST_MODIFICATION_DATE\'|translate}} {{formData.time | formatDate}}</h4><div class="badge badge-balanced badge-editable" ng-click="showRecordTypeModal()">{{\'REGISTRY.TYPE.ENUM.\'+formData.type|upper|translate}}</div></div><ng-include src="\'plugins/es/templates/common/edit_pictures.html\'"></ng-include><div class="item item-divider" translate="">REGISTRY.GENERAL_DIVIDER</div><div class="item item-input item-floating-label" ng-class="{\'item-input-error\': form.$submitted && form.title.$invalid}"><span class="input-label" translate="">REGISTRY.EDIT.RECORD_TITLE</span> <input type="text" placeholder="{{\'REGISTRY.EDIT.RECORD_TITLE_HELP\'|translate}}" name="title" id="registry-record-title" ng-model="formData.title" ng-minlength="3" ng-required="true"></div><div class="form-errors" ng-if="form.$submitted && form.title.$error" ng-messages="form.title.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div><div class="item item-input item-floating-label"><span class="input-label" translate="">REGISTRY.EDIT.RECORD_DESCRIPTION</span><textarea placeholder="{{\'REGISTRY.EDIT.RECORD_DESCRIPTION_HELP\'|translate}}" ng-model="formData.description" rows="8" cols="10">\n </textarea></div><div class="item item-icon-right ink" ng-if="loading || formData.type===\'company\' || formData.type===\'shop\'" ng-class="{\'item-input-error\': form.$submitted && !formData.category.id, \'done in\': !loading}" ng-click="showCategoryModal()"><span translate="">REGISTRY.CATEGORY</span> <span class="badge badge-royal">{{formData.category.name | formatCategory}}</span> <i class="gray icon ion-ios-arrow-right"></i></div><input type="hidden" name="category" ng-model="formData.category.id" required-if="formData.type==\'company\' || formData.type==\'shop\'"><div class="form-errors" ng-if="form.$submitted && form.category.$error" ng-messages="form.category.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><ng-include src="\'plugins/es/templates/common/edit_position.html\'"></ng-include><ng-include src="\'plugins/es/templates/common/edit_socials.html\'" ng-controller="ESSocialsEditCtrl"></ng-include><div class="item item-divider" translate="">REGISTRY.TECHNICAL_DIVIDER</div><div class="item item-input item-floating-label"><span class="input-label" translate="">REGISTRY.EDIT.RECORD_PUBKEY</span> <input type="text" placeholder="{{\'REGISTRY.EDIT.RECORD_PUBKEY_HELP\'|translate}}" ng-model="formData.pubkey"></div></div></form></div></div></ion-content></ion-view>'); +$templateCache.put('plugins/es/templates/registry/lookup_form.html','<form ng-submit="doSearch()"><div class="item no-padding"><div class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{\'REGISTRY.SEARCH.SEARCH_HELP\'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()" on-return="doSearchText()" select-on-click=""></div></div><ng-include src="::\'plugins/es/templates/common/item_location_search.html\'" ng-if="entered && options.location.show && (!search.geoPoint || smallscreen)" ng-controller="ESSearchPositionItemCtrl"></ng-include><ng-include src="::\'plugins/es/templates/registry/lookup_form_options.html\'"></ng-include></form><div class="padding-top padding-xs padding-sm" style="display: block; height: 60px"><div class="pull-left ng-hide" ng-show="!search.loading && search.results"><ng-if ng-if="search.lastRecords"><h4 translate="">REGISTRY.SEARCH.LAST_RECORDS</h4><small class="gray no-padding" ng-if="search.total"><span ng-if="search.geoPoint && search.total">{{\'REGISTRY.SEARCH.LAST_RECORD_COUNT_LOCATION\'|translate:{count: search.total, location: search.location} }}</span> <span ng-if="!search.geoPoint && search.total">{{\'REGISTRY.SEARCH.LAST_RECORD_COUNT\'|translate:{count: search.total} }}</span></small></ng-if><ng-if ng-if="!search.lastRecords"><h4 translate="">COMMON.RESULTS_LIST</h4><small class="gray no-padding" ng-if="search.total"><span ng-if="search.geoPoint && search.total">{{\'REGISTRY.SEARCH.RESULT_COUNT_LOCATION\'|translate:{count: search.total, location: search.location} }}</span> <span ng-if="!search.geoPoint && search.total">{{\'REGISTRY.SEARCH.RESULT_COUNT\'|translate:{count: search.total} }}</span></small></ng-if></div></div><div class="center" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="padding assertive" ng-if="!search.loading && search.results.length===0" translate="">COMMON.SEARCH_NO_RESULT</div>'); +$templateCache.put('plugins/es/templates/registry/lookup_form_options.html','<div class="item item-icon-left item-input item-select stable-bg" ng-if="search.advanced && options.location.show"><i class="icon ion-arrow-resize gray"></i> <span class="input-label item-icon-left-padding" translate="">LOCATION.DISTANCE</span><label><select ng-model="search.geoDistance" class="col-border-left" ng-options="i as (geoDistanceLabels[i].labelKey | translate:geoDistanceLabels[i].labelParams ) for i in geoDistances track by i"></select></label></div>'); +$templateCache.put('plugins/es/templates/registry/lookup_lg.html','<ion-view left-buttons="leftButtons"><ion-nav-title>{{\'REGISTRY.SEARCH.TITLE\' | translate}}</ion-nav-title><ion-content class="lookupForm padding no-padding-xs no-padding-sm"><ng-include src="::\'plugins/es/templates/wot/lookup_lg_extend.html\'" ng-init="enable= true; showNewPageButton=true;"></ng-include><ng-include src="::\'plugins/es/templates/registry/lookup_form.html\'"></ng-include><ng-include src="::\'plugins/es/templates/registry/lookup_list_lg.html\'"></ng-include></ion-content><button id="fab-add-registry-record" class="button button-fab button-fab-bottom-right button-assertive icon ion-plus hidden-md hidden-lg spin" ng-click="showNewPageModal()"></button></ion-view>'); +$templateCache.put('plugins/es/templates/registry/lookup_list.html','<ion-list class="{{::motion.ionListClass}}" ng-if="!search.loading && search.results"><div class="item item-avatar item-icon-right item-border-large ink" ng-repeat="item in search.results" ui-sref="app.view_page({id: item.id, title: item.urlTitle})"><i ng-if="::!item.avatar" class="item-image icon cion-page-{{::item.type}}"></i> <i ng-if="::item.avatar" class="item-image avatar" style="background-image: url({{::item.avatar.src}})"></i><h2 ng-bind-html="::item.title"></h2><h4><span class="dark" ng-if="::item.city"><b class="ion-location"></b> <span ng-bind-html="::item.city"></span> </span><span class="gray" ng-if="::item.distance">({{::item.distance|formatDecimal}} {{::geoUnit}})</span></h4><h4 class="gray" ng-if="::item.time && search.lastRecords"><i class="ion-clock"></i> {{::item.time | formatFromNow}}</h4><h4 class="gray" ng-if="!search.lastRecords"><i class="cion-page-{{::item.type}}"></i> <span ng-if="item.category">{{::item.category.name}}</span> <span ng-if="!item.category">{{::\'REGISTRY.TYPE.ENUM.\'+item.type|uppercase|translate}}</span></h4><i class="icon ion-ios-arrow-right"></i></div></ion-list>'); +$templateCache.put('plugins/es/templates/registry/lookup_list_lg.html','<div class="list {{::motion.ionListClass}}" ng-if="!search.loading && search.results && search.results.length > 0"><a ng-repeat="item in search.results" class="item item-record item-border-large ink padding-xs" ui-sref="app.view_page({id: item.id, title: item.urlTitle})"><div class="row row-record"><div class="col item-text-wrap item-avatar-left-padding" ng-class="::{\'item-avatar\': item.avatar || item.type}"><i class="item-image icon cion-page-{{::item.type}}" ng-if="::!item.avatar"></i> <i class="item-image avatar" style="background-image: url({{::item.avatar.src}})" ng-if="::item.avatar"></i><h2 ng-bind-html="::item.title"></h2><h4><span class="dark" ng-if="::item.city"><b class="ion-location"></b> <span ng-bind-html="::item.city"></span> </span><span class="gray" ng-if="::item.distance">({{::item.distance|formatDecimal}} {{::geoUnit}})</span></h4><h4><span class="gray" ng-if="::item.time && search.lastRecords"><b class="ion-clock"></b> {{::item.time | formatFromNow}} </span><span ng-if="::item.tags" class="dark"><ng-repeat ng-repeat="tag in ::item.tags">#<ng-bind-html ng-bind-html="::tag"></ng-bind-html></ng-repeat></span></h4><span ng-if="::item.picturesCount > 1" class="badge badge-balanced badge-picture-count">{{::item.picturesCount}} <i class="icon ion-camera"></i></span></div><div class="col hidden-xs"><h4 class="text-wrap"><span class="visible-sm"><b class="ion-flag"></b><ng-if ng-if="::item.category">{{::item.category.name|truncText:50}}</ng-if><ng-if ng-if="::!item.category">{{::\'REGISTRY.TYPE.ENUM.\'+item.type|uppercase|translate}}</ng-if></span><span class="gray text-italic" ng-if="::item.description"><b class="ion-quote"></b> <span ng-bind-html="::item.description|truncText:500" ng-if="::item.description"></span></span></h4></div></div></a></div><ion-infinite-scroll ng-if="!search.loading && search.hasMore" spinner="android" on-infinite="showMore()" distance="10%"></ion-infinite-scroll>'); +$templateCache.put('plugins/es/templates/registry/lookup_popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-click="showNewPageModal();"><i class="icon ion-plus"></i> <span translate>REGISTRY.BTN_NEW</span></a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/registry/lookup_popover_filters.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>COMMON.POPOVER_FILTER_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-click="doGetLastRecords()"><i class="icon ion-clock"></i> {{\'REGISTRY.SEARCH.BTN_LAST_RECORDS\' | translate}} </a><a class="item item-icon-left ink" ng-click="toggleAdvanced();"><i class="icon ion-android-checkbox-outline-blank" ng-show="!search.advanced"></i> <i class="icon ion-android-checkbox-outline" ng-show="search.advanced"></i> <span translate>REGISTRY.SEARCH.POPOVER_FILTERS.BTN_ADVANCED_SEARCH</span></a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/registry/modal_record_type.html','<ion-modal-view><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>{{getParameters().title||\'REGISTRY.TYPE.TITLE\'|translate}}</h1></ion-header-bar><ion-content class="lookupForm"><div class="list padding"><h3 translate>REGISTRY.TYPE.SELECT_TYPE</h3><button class="button button-block button-stable icon-left cion-page-shop" ng-click="closeModal(\'shop\')" translate>REGISTRY.TYPE.ENUM.SHOP</button> <button class="button button-block button-stable icon-left cion-page-association" ng-click="closeModal(\'association\')" translate>REGISTRY.TYPE.ENUM.ASSOCIATION</button> <button class="button button-block button-stable icon-left cion-page-company" ng-click="closeModal(\'company\')" translate>REGISTRY.TYPE.ENUM.COMPANY</button> <button class="button button-block button-stable icon-left cion-page-institution" ng-click="closeModal(\'institution\')" translate>REGISTRY.TYPE.ENUM.INSTITUTION</button></div></ion-content></ion-modal-view>'); +$templateCache.put('plugins/es/templates/registry/view_popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>REGISTRY.VIEW.MENU_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-click="showSharePopover($event)"><i class="icon ion-android-share-alt"></i> {{\'COMMON.BTN_SHARE\' | translate}} </a><a class="item item-icon-left assertive ink" ng-if="canEdit" ng-click="delete()"><i class="icon ion-trash-a"></i> {{\'COMMON.BTN_DELETE\' | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/registry/view_record.html','<ion-view left-buttons="leftButtons" class="view-page"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-bar button-icon button-clear visible-xs visible-sm" ng-click="edit()" ng-if="canEdit"><i class="icon ion-android-create"></i></button> <button class="button button-bar button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true" class="refresher-top-bg"><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="load()"></ion-refresher><div class="hero"><div class="content" ng-if="!loading"><i class="avatar cion-page-{{formData.type}}" ng-if="!formData.avatar"></i> <i class="avatar" ng-style="{{avatarStyle}}" ng-if="formData.avatar"></i><h3><span class="dark" ng-bind-html="formData.title"></span></h3><h4> </h4></div><h4 class="content dark" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><div class="row no-padding-xs no-padding-sm"><div class="col list animate-fade-slide-in item-text-wrap no-padding-xs no-padding-sm"><div class="item"><h2 class="gray"><a ng-if="formData.city" ui-sref="app.wot_lookup.tab_registry({location:formData.city})"><i class="icon ion-location"></i> <span ng-bind-html="formData.city"></span> </a><span ng-if="formData.city && formData.type"> | </span> <a ng-if="formData.type" ui-sref="app.wot_lookup.tab_registry({type:formData.type})"><i class="cion-page-{{formData.type}}"></i> {{\'REGISTRY.TYPE.ENUM.\'+formData.type|upper|translate}}</a></h2><h4><i class="icon ion-clock" ng-if="formData.time"></i> <span translate="">COMMON.SUBMIT_BY</span> <a ng-class="{\'positive\': issuer.uid, \'gray\': !issuer.uid}" ui-sref="app.wot_identity({pubkey:issuer.pubkey, uid: issuer.name||issuer.uid})"><ng-if ng-if="issuer.uid"><i class="icon ion-person"></i> {{::issuer.name||issuer.uid}}</ng-if><span ng-if="!issuer.uid"><i class="icon ion-key"></i> {{issuer.pubkey|formatPubkey}} </span></a><span>{{formData.time|formatFromNow}}<h4 class="gray hidden-xs">| {{formData.time | formatDate}}</h4></span></h4></div><a id="registry-share-anchor-{{id}}"></a><div class="item"><h2 trust-as-html="formData.description"></h2></div><div class="item" ng-if="formData.category || formData.address"><h4 ng-if="formData.category"><span class="gray" translate="">REGISTRY.VIEW.CATEGORY</span> <a class="positive" ng-if="formData.category" ui-sref="app.wot_lookup.tab_registry({category:formData.category.id})"><span ng-bind-html="formData.category.name"></span></a></h4><h4 ng-if="formData.address"><span class="gray" translate="">REGISTRY.VIEW.LOCATION</span> <a class="positive" target="_system" href="https://www.openstreetmap.org/search?query={{formData.address}},%20{{formData.city}}"><span ng-bind-html="formData.address"></span> <span ng-if="formData.city">- </span><span ng-bind-html="formData.city"></span></a></h4></div><ng-if ng-if="formData.socials && formData.socials.length>0"><div class="item item-icon-left" type="no-padding item-text-wrap" ng-repeat="social in formData.socials track by social.url" id="social-{{social.url|formatSlug}}"><i class="icon ion-social-{{social.type}}" ng-class="{\'ion-bookmark\': social.type == \'other\', \'ion-link\': social.type == \'web\', \'ion-email\': social.type == \'email\'}"></i><p ng-if="social.type && social.type != \'web\'">{{social.type}}</p><h2><a ng-click="openLink($event, social.url, social.type)">{{social.url}}</a></h2></div></ng-if><div class="item item-icon-left item-text-wrap ink" ng-if="formData.pubkey" copy-on-click="{{::formData.pubkey}}"><i class="icon ion-key"></i> <span translate="">REGISTRY.EDIT.RECORD_PUBKEY</span><h4 class="dark">{{::formData.pubkey}}</h4></div><div class="lazy-load"><ng-include src="\'plugins/es/templates/common/view_pictures.html\'"></ng-include><ng-include src="\'plugins/es/templates/common/view_comments.html\'"></ng-include></div></div></div></ion-content><button class="button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm" ng-if="formData.pubkey && !isUserPubkey(formData.pubkey)" ng-click="showTransferModal({pubkey: formData.pubkey, uid: formData.title})"></button></ion-view>'); +$templateCache.put('plugins/es/templates/registry/view_wallet_pages.html','<ion-view left-buttons="leftButtons" class="view-notification"><ion-nav-title>{{\'REGISTRY.MY_PAGES\' | translate}}</ion-nav-title><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ion-refresher pulling-text="{{:locale:\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="doUpdate()"></ion-refresher><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding gray" ng-if="!search.loading && !search.results.length" translate="">REGISTRY.NO_PAGE</div><ng-include src="\'plugins/es/templates/registry/lookup_list.html\'"></ng-include></ion-content><button id="fab-wallet-add-registry-record" class="button button-fab button-fab-bottom-right button-assertive hidden-md hidden-lg spin" ng-click="showNewPageModal()"><i class="icon ion-plus"></i></button></ion-view>'); +$templateCache.put('plugins/es/templates/settings/plugin_settings.html','<ion-view left-buttons="leftButtons" class="settings"><ion-nav-title translate="">ES_SETTINGS.PLUGIN_NAME</ion-nav-title><ion-content scroll="true"><div class="item item-toggle dark"><div class="input-label" translate="">ES_SETTINGS.ENABLE_TOGGLE</div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.enable"><div class="track"><div class="handle"></div></div></label></div><span class="item item-divider" translate="">SETTINGS.STORAGE_DIVIDER</span><div class="item item-toggle item-text-wrap dark"><div class="input-label" ng-class="{\'gray\': !formData.enable}" translate="">ES_SETTINGS.ENABLE_REMOTE_STORAGE</div><h4 class="gray text-wrap" ng-bind-html="\'ES_SETTINGS.ENABLE_REMOTE_STORAGE_HELP\' | translate"></h4><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.useRemoteStorage" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></label></div><span class="item item-divider" translate="">SETTINGS.NETWORK_SETTINGS</span><ion-item class="ink item-icon-right item-text-wrap visible-xs visible-sm" ng-click="formData.enable && changeEsNode()" ng-disabled="!formData.enable"><div class="input-label" ng-class="{\'gray\': !formData.enable}" translate="">ES_SETTINGS.PEER</div><ng-if ng-if="isFallbackNode"><h4 class="gray text-wrap assertive"><b class="ion-alert-circled"></b> <span ng-bind-html="\'SETTINGS.PEER_CHANGED_TEMPORARY\' | translate "></span></h4><div class="badge badge-assertive">{{server}}</div></ng-if><div class="badge" ng-class="{\'badge-balanced\': formData.enable, \'badge-stable\': !formData.enable}" ng-if="!isFallbackNode">{{server}}</div><i class="icon ion-ios-arrow-right"></i></ion-item><span class="item item-divider" translate="">ES_SETTINGS.NOTIFICATIONS.DIVIDER</span><span class="item gray item-text-wrap" translate="">ES_SETTINGS.NOTIFICATIONS.HELP_TEXT</span><label class="item item-toggle dark item-text-wrap"><span ng-class="{\'gray\': !formData.enable}" translate="">ES_SETTINGS.NOTIFICATIONS.ENABLE_TX_SENT</span><div class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.txSent" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></div></label><label class="item item-toggle dark item-text-wrap"><span ng-class="{\'gray\': !formData.enable}" translate="">ES_SETTINGS.NOTIFICATIONS.ENABLE_TX_RECEIVED</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.txReceived" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></label></label><label class="item item-toggle dark item-text-wrap"><span ng-class="{\'gray\': !formData.enable}" translate="">ES_SETTINGS.NOTIFICATIONS.ENABLE_CERT_SENT</span><div class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.certSent" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></div></label><label class="item item-toggle dark item-text-wrap"><span ng-class="{\'gray\': !formData.enable}" translate="">ES_SETTINGS.NOTIFICATIONS.ENABLE_CERT_RECEIVED</span><div class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.certReceived" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></div></label><cs-extension-point name="common"></cs-extension-point></ion-content></ion-view>'); +$templateCache.put('plugins/es/templates/settings/settings_extend.html','<div class="item item-text-wrap item-icon-right ink" ui-sref="app.es_settings"><div class="input-label ng-binding" translate>ES_SETTINGS.PLUGIN_NAME</div><h4 class="gray" translate>ES_SETTINGS.PLUGIN_NAME_HELP</h4><i class="icon ion-ios-arrow-right"></i></div>'); +$templateCache.put('plugins/es/templates/subscription/edit_subscriptions.html','<ion-view left-buttons="leftButtons" class="view-notification"><ion-nav-title>{{\'SUBSCRIPTION.EDIT.TITLE\' | translate}}</ion-nav-title><ion-nav-buttons side="secondary"></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ion-refresher pulling-text="{{:locale:\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="load()"></ion-refresher><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding gray" ng-if="!search.loading && !search.results.length" translate="">SUBSCRIPTION.NO_SUBSCRIPTION</div><div class="row no-padding"><div class="col list {{::motion.ionListClass}} item-border-large"><ng-repeat ng-repeat="subscriptions in search.results | filter: { type: \'email\' }" ng-include="\'plugins/es/templates/subscription/item_\' + subscriptions.type.toLowerCase() + \'_subscription.html\'">></ng-repeat></div></div></ion-content><button id="fab-add-subscription-record" class="button button-fab button-fab-bottom-right button-assertive icon ion-plus hidden-md hidden-lg spin" ng-click="addSubscription()"></button></ion-view>'); +$templateCache.put('plugins/es/templates/subscription/item_email_subscription.html','<div class="item item-avatar"><i class="item-image icon ion-email"></i><h3>{{\'SUBSCRIPTION.TYPE.ENUM.\' + subscriptions.type.toUpperCase() | translate}}</h3><h4 class="gray">{{\'SUBSCRIPTION.EDIT.PROVIDER\'|translate}} <a ui-sref="app.wot_identity({pubkey: subscriptions.recipient, uid: subscriptions.uid})"><span ng-class="{\'positive\': subscriptions.uid, \'dark\': !subscriptions.uid}" ng-if="subscriptions.name||subscriptions.uid"><i class="ion-person" ng-if="subscriptions.uid"></i> {{subscriptions.name||subscriptions.uid}} </span><span class="gray" ng-if="!subscriptions.uid"><i class="ion-key"></i> {{subscriptions.recipient | formatPubkey}}</span></a></h4><div class="item-note text-right"><span ng-repeat="item in subscriptions.items">{{item.content.email}} <a class="ion-trash-a gray padding-left" ng-click="deleteSubscription(item)"></a> <a class="ion-edit gray padding-left" ng-click="editSubscription(item)"></a><br></span></div></div>'); +$templateCache.put('plugins/es/templates/subscription/modal_email.html','<ion-modal-view id="composeMessage" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>SUBSCRIPTION.MODAL_EMAIL.TITLE</h1><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doSubmit()"></button></ion-header-bar><ion-content scroll="true"><div class="item item-icon-left item-text-wrap"><i class="icon ion-ios-information-outline positive"></i><h4 class="positive" translate>SUBSCRIPTION.MODAL_EMAIL.HELP</h4></div><form name="subscriptionForm" novalidate="" ng-submit="doSubmit()"><div class="list" ng-init="setForm(subscriptionForm)"><label class="item item-input" ng-class="{\'item-input-error\': form.$submitted && (form.email.$invalid || form.email.$error)}"><span class="input-label" translate>SUBSCRIPTION.MODAL_EMAIL.EMAIL_LABEL</span> <input name="email" type="text" placeholder="{{\'SUBSCRIPTION.MODAL_EMAIL.EMAIL_HELP\' | translate}}" ng-model="formData.content.email" ng-minlength="3" required email></label><div class="form-errors" ng-if="form.$submitted && (form.email.$invalid || form.email.$error)" ng-messages="form.email.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div><div class="form-error" ng-message="email"><span translate="ERROR.FIELD_NOT_EMAIL"></span></div></div><label class="item item-input item-select" ng-class="{\'item-input-error\': form.$submitted && !formData.content.frequency}"><span class="input-label" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_LABEL</span><select name="frequency" ng-model="formData.content.frequency" style="height: 46px;margin-top: 1px"><option value="weekly" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_WEEKLY</option><option value="daily" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_DAILY</option></select></label><div class="form-errors" ng-if="form.$submitted && !formData.content.frequency"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><a class="item item-input item-icon-right gray ink" ng-class="{\'item-input-error\': form.$submitted && !formData.recipient}" ng-click="showNetworkLookup()" style="height: 67px"><span class="input-label" translate>SUBSCRIPTION.MODAL_EMAIL.PROVIDER</span> <span class="badge animate-fade-in animate-show-hide ng-hide" ng-class="{\'badge-royal\': recipient.uid, \'badge-stable\': !recipient.uid}" ng-show="recipient && (recipient.name||recipient.uid)"><i class="ion-person" ng-if="recipient.uid"></i> {{recipient.name||recipient.uid}} </span><span class="badge badge-secondary animate-fade-in animate-show-hide ng-hide" ng-show="formData.recipient"><i class="ion-key"></i> {{formData.recipient | formatPubkey}} </span><i class="gray icon ion-ios-arrow-right"></i></a><div class="form-errors" ng-if="form.$submitted && !formData.recipient"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="cancel()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" type="submit">{{\'COMMON.BTN_ADD\' | translate}}</button></div></form></ion-content></ion-modal-view>'); +$templateCache.put('plugins/es/templates/user/edit_popover_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left assertive ink" ng-click="removeProfile()"><i class="icon ion-trash-a"></i> {{\'PROFILE.BTN_DELETE\' | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/user/edit_profile.html','<ion-view left-buttons="leftButtons"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear button-assertive ion-trash-a visible-xs visible-sm" ng-click="removeProfile()" ng-if="existing"></button> <button class="button button-icon button-clear ion-android-done visible-xs visible-sm" ng-click="submitAndSaveAndClose()"></button></ion-nav-buttons><ion-content scroll="true"><div class="positive-900-bg hero"><div class="content"><i class="avatar" ng-style="avatarStyle" ng-class="{\'avatar-wallet\': !loading && !avatar && walletData && !walletData.isMember, \'avatar-member\': !loading && !avatar && walletData.isMember}"><button class="button button-positive button-large button-clear flat icon ion-camera visible-xs visible-sm" style="display: inline-block" ng-click="showAvatarModal()"></button> <button ng-if="avatar.src" class="button button-positive button-large button-clear flat visible-xs visible-sm" style="display: inline-block; left: 85px; bottom:15px" ng-click="rotateAvatar()"><i class="icon-secondary ion-image" style="left: 24px; top: 3px; font-size: 24px"></i> <i class="icon-secondary ion-forward" style="left: 26px; top: -13px"></i></button></i><h3 class="light"><ng-if ng-if="!loading && !formData.title && walletData && walletData.isMember">{{walletData.uid}}</ng-if><ng-if ng-if="!loading && !formData.title && walletData && !walletData.isMember">{{::walletData.pubkey | formatPubkey}}</ng-if><ng-if ng-if="!loading && formData.title">{{formData.title}}</ng-if></h3><h4 class="light"><ion-spinner ng-if="loading" icon="android"></ion-spinner></h4></div></div><div class="row no-padding"><div class="col"><form name="profileForm" novalidate="" ng-submit="saveAndClose()"><div class="list item-text-wrap {{::motion.ionListClass}}" ng-init="setForm(profileForm)"><div class="item item-icon-left item-text-wrap"><i class="icon ion-ios-information-outline positive"></i><h4 class="positive" translate="">PROFILE.HELP.WARNING_PUBLIC_DATA</h4></div><div class="item item-divider">{{\'PROFILE.GENERAL_DIVIDER\' | translate}}</div><ion-item class="item-input item-floating-label item-button-right" ng-class="{\'item-input-error\': form.$submitted && form.title.$invalid}"><span class="input-label">{{\'PROFILE.TITLE\' | translate}}</span> <input type="text" name="title" placeholder="{{\'PROFILE.TITLE_HELP\' | translate}}" id="profile-name" ng-model="formData.title" ng-model-options="{ debounce: 350 }" ng-maxlength="50" required></ion-item><div class="form-errors" ng-show="form.$submitted && form.title.$error" ng-messages="form.title.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="maxlength"><span translate="ERROR.FIELD_TOO_LONG_WITH_LENGTH" translate-values="{maxLength: 50}"></span></div></div><ion-item class="item-input item-floating-label item-button-right"><span class="input-label" style="width: 100%">{{\'PROFILE.DESCRIPTION\' | translate}}</span><textarea placeholder="{{\'PROFILE.DESCRIPTION_HELP\' | translate}}" ng-model="formData.description" ng-model-options="{ debounce: 350 }" rows="4" cols="10">\n </textarea></ion-item><ng-include src="\'plugins/es/templates/common/edit_position.html\'" ng-controller="ESPositionEditCtrl as ctrl"></ng-include></div><ng-include src="\'plugins/es/templates/common/edit_socials.html\'" ng-controller="ESSocialsEditCtrl"></ng-include><div class="list item-text-wrap {{::motion.ionListClass}}"><div class="item item-divider">{{\'PROFILE.TECHNICAL_DIVIDER\' | translate}}</div><ion-item class="item-icon-left" ng-if="walletData && walletData.uid"><span translate="">COMMON.UID</span> <span class="badge badge-stable">{{::walletData.uid}}</span></ion-item><ion-item class="item-icon-left item-icon-right item-text-wrap ink" on-hold="copy(formData.pubkey)" copy-on-click=""><i class="icon ion-key"></i> <span translate="">COMMON.PUBKEY</span><p class="gray">{{walletData.pubkey}}</p></ion-item></div></form></div></div></ion-content></ion-view>'); +$templateCache.put('plugins/es/templates/user/items_profile.html','<div ng-if="!formData.profile" class="item gray" translate>PROFILE.NO_PROFILE_DEFINED</div><div class="item" ng-if="formData.profile && formData.name && showName"><span class="gray" translate>PROFILE.TITLE</span><h3>{{formData.name}}</h3></div><div class="item item-text-wrap" ng-if="formData.profile.description"><span class="gray" translate>PROFILE.DESCRIPTION</span><h3 trust-as-html="formData.profile.description"></h3></div><div class="item" ng-if="formData.profile.address || formData.profile.city" copy-on-click="{{formData.profile.address ? formData.profile.address + \' \' : \'\'}}{{formData.profile.city}}"><span class="gray" translate>LOCATION.LOCATION_DIVIDER</span><h3><span class="text-keep-lines" ng-if="formData.profile.address">{{formData.profile.address}}<br></span>{{formData.profile.city}}</h3></div><div class="item" ng-if="formData.profile.socials && formData.profile.socials.length" ng-controller="ESSocialsViewCtrl"><span class="gray" translate>PROFILE.SOCIAL_NETWORKS_DIVIDER</span><div class="list no-padding"><ion-item ng-repeat="social in formData.profile.socials | filter:filterFn track by social.url " id="social-{{::social.url|formatSlug}}" class="item-icon-left item-text-wrap no-padding-bottom ink" on-tap="openSocial($event, social)"><i class="icon ion-social-{{social.type}}" ng-class="{\'ion-bookmark\': social.type == \'other\', \'ion-link\': social.type == \'web\', \'ion-email\': social.type == \'email\', \'ion-iphone\': social.type == \'phone\'}"></i><p ng-if="social.type && social.type != \'web\'">{{social.type}} <i class="ion-locked" ng-if="social.recipient"></i></p><h4><a on-tap="openSocial($event, social)" href="{{::social.url}}" target="_blank">{{::social.url}}</a></h4></ion-item></div></div>'); +$templateCache.put('plugins/es/templates/wallet/item_wallet_extend.html','<h4 class="dark" ng-if=":state:enable && wallet.id!=\'default\'"><a ng-if="walletData.invitations.unreadCount"><i class="dark ion-person-stalker"></i> {{walletData.invitations.unreadCount}} </a><a ng-if="walletData.messages.unreadCount" ui-sref="app.user_messages_by_id.tab_inbox({id: wallet.id})"><i class="dark ion-email"></i> {{walletData.messages.unreadCount}} </a><a ng-if="walletData.notifications.unreadCount" ui-sref="app.view_notifications_by_id({id: wallet.id})"><i class="dark ion-android-notifications"></i> {{walletData.notifications.unreadCount}}</a></h4>'); +$templateCache.put('plugins/es/templates/wallet/view_wallet_extend.html','<ng-if ng-if=":state:enable"><div class="item item-divider item-divider-top-border"><span>{{\'PROFILE.PROFILE_DIVIDER\' | translate}} <i style="font-size: 12pt; cursor: pointer" ng-click="showProfileHelp=!showProfileHelp" class="icon positive ion-ios-help-outline" title="{{\'PROFILE.PROFILE_DIVIDER_HELP\' | translate}}"></i> </span><a class="badge button button-text button-small button-small-padding" ng-if="isDefaultWallet" ui-sref="app.edit_profile"><i class="icon ion-edit"></i> <span ng-if="!formData.profile" translate>PROFILE.BTN_ADD</span> <span ng-if="formData.profile" translate>PROFILE.BTN_EDIT</span> </a><a class="badge button button-text button-small button-small-padding" ng-if="!isDefaultWallet" ui-sref="app.edit_profile_by_id({id: walletId})"><i class="icon ion-edit"></i> <span ng-if="!formData.profile" translate>PROFILE.BTN_ADD</span> <span ng-if="formData.profile" translate>PROFILE.BTN_EDIT</span></a></div><div class="item item-text-wrap positive item-small-height" ng-show="showProfileHelp"><small translate>PROFILE.PROFILE_DIVIDER_HELP</small></div><ng-include src="\'plugins/es/templates/user/items_profile.html\'" ng-init="showName=true"></ng-include><div class="item item-divider item-divider-top-border"><span>{{\'SUBSCRIPTION.SUBSCRIPTION_DIVIDER\' | translate}} <i style="font-size: 12pt; cursor: pointer" ng-click="showSubscriptionHelp=!showSubscriptionHelp" class="icon positive ion-ios-help-outline" title="{{\'SUBSCRIPTION.SUBSCRIPTION_DIVIDER_HELP\' | translate}}"></i> <span><a class="badge button button-text button-small button-small-padding" ng-if="!formData.subscriptions.count && isDefaultWallet" ui-sref="app.edit_subscriptions"><i class="icon ion-edit"></i> <span translate>SUBSCRIPTION.BTN_ADD</span> </a><a class="badge button button-text button-small button-small-padding" ng-if="!formData.subscriptions.count && !isDefaultWallet" ui-sref="app.edit_subscriptions_by_id({id: walletId})"><i class="icon ion-edit"></i> <span translate>SUBSCRIPTION.BTN_ADD</span></a></span></span></div><div class="item item-text-wrap positive item-small-height" ng-show="showSubscriptionHelp"><small translate>SUBSCRIPTION.SUBSCRIPTION_DIVIDER_HELP</small></div><div ng-if="!formData.subscriptions.count" class="item gray" translate>SUBSCRIPTION.NO_SUBSCRIPTION</div><a class="item item-icon-left item-text-wrap item-icon-right ink" ng-if="formData.subscriptions.count && isDefaultWallet" ui-sref="app.edit_subscriptions"><i class="icon ion-gear-a"></i> <span translate>SUBSCRIPTION.SUBSCRIPTION_COUNT</span> <span class="badge badge-calm">{{formData.subscriptions.count}}</span> <i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-text-wrap item-icon-right ink" ng-if="formData.subscriptions.count && !isDefaultWallet" ui-sref="app.edit_subscriptions_by_id({id: walletId})"><i class="icon ion-gear-a"></i> <span translate>SUBSCRIPTION.SUBSCRIPTION_COUNT</span> <span class="badge badge-calm">{{formData.subscriptions.count}}</span> <i class="gray icon ion-ios-arrow-right"></i></a><div class="item item-divider item-divider-top-border"><span>{{\'REGISTRY.WALLET.REGISTRY_DIVIDER\' | translate}} <i style="font-size: 12pt; cursor: pointer" ng-click="showPagesHelp=!showPagesHelp" class="icon positive ion-ios-help-outline" title="{{\'REGISTRY.WALLET.REGISTRY_HELP\' | translate}}"></i> <span><a class="badge button button-text button-small button-small-padding" ng-if="!formData.pages.count" ng-click="showNewPageModal()"><i class="icon ion-edit"></i> <span translate>REGISTRY.BTN_NEW</span></a></span></span></div><div class="item item-text-wrap positive item-small-height" ng-show="showPagesHelp"><small translate>REGISTRY.WALLET.REGISTRY_HELP</small></div><div ng-if="!formData.pages.count" class="item gray" translate>REGISTRY.NO_PAGE</div><a class="item item-icon-left item-text-wrap item-icon-right ink" ng-if="formData.pages.count && isDefaultWallet" ui-sref="app.wallet_pages"><i class="icon ion-social-buffer"></i> <span translate>REGISTRY.MY_PAGES</span> <span class="badge badge-calm">{{formData.pages.count}}</span> <i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-text-wrap item-icon-right ink" ng-if="formData.pages.count && !isDefaultWallet" ui-sref="app.wallet_pages_by_id({id: walletId})"><i class="icon ion-social-buffer"></i> <span translate>REGISTRY.MY_PAGES</span> <span class="badge badge-calm">{{formData.pages.count}}</span> <i class="gray icon ion-ios-arrow-right"></i></a></ng-if>'); +$templateCache.put('plugins/es/templates/wot/lookup_extend.html','<ion-tab ng-if=":state:enable" title="{{\'MENU.REGISTRY\'|translate}}" icon="ion-social-buffer" ui-sref="app.wot_lookup.tab_registry"><ion-nav-view name="tab_registry"></ion-nav-view></ion-tab>'); +$templateCache.put('plugins/es/templates/wot/lookup_item_group.html','<i ng-if="::!item.avatar" class="item-image icon ion-android-people"></i> <i ng-if="::!item.avatar" class="item-image icon-secondary ion-android-lock" style="left: 20px; top: 17px; font-size: 19px; color: #d9d9d9"></i> <i ng-if="::item.avatar" class="item-image avatar" style="background-image: url({{::item.avatar.src}})"></i><h2 ng-bind-html=":rebind:item.name"></h2><h4 class="gray"><i class="ion-clock"></i> {{:rebind:\'GROUP.CREATED_TIME\'|translate: item }}</h4><h4 class="dark pull-left" ng-if=":rebind:item.membersCount"><i class="dark ion-person"></i> <span class="dark">+{{:rebind:item.membersCount}}</span></h4><h4 class="dark"><span class="dark" ng-if="::item.description"><i class="ion-quote"></i> {{::item.description|truncText}}</span></h4><h4 ng-if="::item.tags"><span ng-if="::item.tags" class="dark"><ng-repeat ng-repeat="tag in ::item.tags">#<ng-bind-html ng-bind-html="::tag"></ng-bind-html></ng-repeat></span></h4>'); +$templateCache.put('plugins/es/templates/wot/lookup_item_page.html','<i ng-if="::!item.avatar" class="item-image icon cion-page-{{item.type}}"></i> <i ng-if="::item.avatar" class="item-image avatar" style="background-image: url({{::item.avatar.src}})"></i><h2 ng-bind-html=":rebind:item.name"></h2><h4 class="gray"><span class="gray" ng-if="::item.city"><i class="ion-location"></i> {{::item.city|truncText}} </span><span ng-if="::item.city && item.type">|</span> <span ng-if="item.type"><i class="cion-page-{{item.type}}"></i> {{::\'REGISTRY.TYPE.ENUM.\'+item.type|uppercase|translate}}</span></h4><h4 class="dark"><span class="dark" ng-if="::item.description"><i class="ion-quote"></i> {{::item.description|truncText}}</span></h4><h4 ng-if="::item.tags"><span ng-if="::item.tags" class="dark"><ng-repeat ng-repeat="tag in ::item.tags">#<ng-bind-html ng-bind-html="::tag"></ng-bind-html></ng-repeat></span></h4>'); +$templateCache.put('plugins/es/templates/wot/lookup_lg_extend.html','<div class="buttons-tabs" ng-if=":state:enable"><div class="pull-right"><div class="button button-tab dark" title="{{\'REGISTRY.BTN_SHOW_WOT_HELP\' | translate}}" nav-transition="none" active-link="active" active-link-path-prefix="#/app/wot/lg" ui-sref="app.wot_lookup_lg"><i class="icon ion-person-stalker"></i> {{\'REGISTRY.BTN_SHOW_WOT\' | translate}}</div><a class="button button-tab ink dark" title="{{\'REGISTRY.BTN_SHOW_PAGES_HELP\' | translate}}" nav-transition="none" active-link="active" active-link-path-prefix="#/app/wot/page" ui-sref="app.registry_lookup_lg"><i class="icon ion-social-buffer"></i> {{\'REGISTRY.BTN_SHOW_PAGES\' | translate}}</a></div><div class="pull-right" ng-if="showNewPageButton"> </div></div>'); +$templateCache.put('plugins/es/templates/wot/popover_certification_actions.html','<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-if="canCertify" ng-click="certify()"><i class="icon ion-ribbon-b"></i> {{\'WOT.BTN_CERTIFY\' | translate}} </a><a class="item item-icon-left ink" ng-if="!isUserPubkey(formData.pubkey) && formData.isMember" ng-click="askCertification()"><i class="icon-secondary ion-ribbon-b" style="left: 16px; top: 0px; font-size: 25px"></i> <b class="icon-secondary ion-help" style="left: 35px; top: 0px"></b> {{\'WOT.BTN_ASK_CERTIFICATION\' | translate}} </a><a class="item item-icon-left ink" ng-if="isUserPubkey(formData.pubkey)" ng-click="showAskCertificationModal()"><i class="icon-secondary ion-ribbon-b" style="left: 16px; top: 0px; font-size: 25px"></i> <b class="icon-secondary ion-help" style="left: 35px; top: 0px"></b> {{\'WOT.BTN_ASK_CERTIFICATIONS_DOTS\' | translate}} </a><a class="item item-icon-left ink" ng-if="!isUserPubkey(formData.pubkey)" ng-click="showSuggestCertificationModal()"><i class="icon-secondary ion-person-stalker" style="left: 16px; top: 0px; font-size: 25px"></i> <b class="icon-secondary ion-help" style="left: 37px; top: -4px"></b> {{\'WOT.BTN_SUGGEST_CERTIFICATIONS_DOTS\' | translate}}</a></div></ion-content></ion-popover-view>'); +$templateCache.put('plugins/es/templates/wot/view_certifications_extend.html','<ng-if ng-if=":state:enable && extensionPoint === \'nav-buttons\'"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showCertificationActionsPopover($event)"></button></ng-if><ng-if ng-if=":state:enable && extensionPoint === \'buttons\'"><button class="button button-stable button-small-padding icon ion-android-more-vertical" ng-click="showCertificationActionsPopover($event)" title="{{\'COMMON.POPOVER_ACTIONS_TITLE\' | translate}}"></button></ng-if>'); +$templateCache.put('plugins/es/templates/wot/view_identity_extend.html','<ng-if ng-if=":state:enable && extensionPoint === \'buttons\'"><button class="button button-stable button-small-padding icon ion-compose" ng-click="showNewMessageModal()" title="{{\'MESSAGE.BTN_WRITE\' | translate}}"></button></ng-if><ng-if ng-if=":state:enable && extensionPoint === \'buttons-top-fab\'"><button id="fab-compose-{{:rebind:formData.uid}}" class="button button-fab button-fab-top-left button-fab-hero mini button-stable spin" style="left: 88px" ng-click="showNewMessageModal()"><i class="icon ion-compose"></i></button></ng-if><ng-if ng-if=":state:enable && extensionPoint === \'after-general\'"><span class="item item-divider item-divider-top-border"><span>{{\'PROFILE.PROFILE_DIVIDER\' | translate}} <a style="font-size: 12pt; cursor: pointer" ng-click="showProfileHelp=!showProfileHelp" class="icon positive ion-ios-help-outline ink" title="{{\'PROFILE.PROFILE_DIVIDER_HELP\' | translate}}"></a></span></span><div class="item item-text-wrap positive item-small-height" ng-show="showProfileHelp"><small translate>PROFILE.PROFILE_DIVIDER_HELP</small></div><ng-include src="\'plugins/es/templates/user/items_profile.html\'" ng-init="showName=false;"></ng-include></ng-if>'); +$templateCache.put('plugins/graph/templates/account/graph_balance.html','\n <!-- button bar -->\n <div class="button-bar-inline "\n style="top: 33px; margin-top:-33px; position: relative;">\n <button\n class="button button-stable button-clear no-padding-xs pull-right"\n ng-click="showActionsPopover($event)">\n <i class="icon ion-navicon-round"></i>\n </button>\n </div>\n\n <div class="padding-left padding-right">\n <canvas id="account-balance" class="chart-bar"\n height="{{height}}" width="{{width}}"\n chart-data="data"\n chart-dataset-override="datasetOverride"\n chart-colors="colors"\n chart-options="options"\n chart-labels="labels"\n chart-click="onChartClick">\n </canvas>\n </div>\n\n <ng-include src="\'plugins/graph/templates/common/graph_range_bar.html\'"></ng-include>\n'); +$templateCache.put('plugins/graph/templates/account/graph_certifications.html','\n <div class="padding-left padding-right">\n <canvas id="account-certifications" class="chart-bar"\n height="{{height}}" width="{{width}}"\n chart-data="data"\n chart-dataset-override="datasetOverride"\n chart-colors="colors"\n chart-options="options"\n chart-labels="labels"\n chart-click="onChartClick">\n </canvas>\n </div>\n'); +$templateCache.put('plugins/graph/templates/account/graph_sum_tx.html','<div class="row responsive-sm" ng-if="!loading">\n\n <div class="col col-10 hidden-xs hidden-sm"> </div>\n\n <div class="col text-center">\n\n <!-- TX input chart -->\n <p class="gray padding text-wrap"\n ng-if="inputChart.data.length"\n translate>GRAPH.ACCOUNT.INPUT_CHART_TITLE</p>\n <canvas id="chart-received-pie" class="chart-pie"\n chart-data="inputChart.data"\n chart-labels="inputChart.labels"\n chart-colors="inputChart.colors"\n chart-click="onInputChartClick">\n </canvas>\n\n </div>\n\n <div class="col col-10 hidden-xs hidden-sm"> </div>\n\n <div class="col text-center">\n\n <!-- TX output chart -->\n <p class="gray padding text-wrap"\n ng-if="outputChart.data.length"\n translate>GRAPH.ACCOUNT.OUTPUT_CHART_TITLE</p>\n <canvas id="chart-sent-pie" class="chart-pie"\n chart-data="outputChart.data"\n chart-labels="outputChart.labels"\n chart-colors="outputChart.colors"\n chart-click="onOutputChartClick">\n </canvas>\n\n </div>\n\n <div class="col col-10 hidden-xs hidden-sm"> </div>\n\n</div>\n'); +$templateCache.put('plugins/graph/templates/account/view_identity_extend.html','<!-- Buttons section -->\n<ng-if ng-if="extensionPoint === \'buttons\'">\n\n <button class="button button-stable button-small-padding icon ion-stats-bars"\n ng-click="showIdentityStats()"\n title="{{\'GRAPH.ACCOUNT.BTN_SHOW_STATS\' | translate}}">\n </button>\n\n</ng-if>\n'); +$templateCache.put('plugins/graph/templates/account/view_identity_tx_extend.html','<!-- Buttons section -->\n<ng-if ng-if="extensionPoint === \'buttons\'">\n\n <button class="button button-stable button-small-padding icon ion-stats-bars"\n ng-click="showIdentityStats()"\n title="{{\'GRAPH.ACCOUNT.BTN_SHOW_STATS\' | translate}}">\n </button>\n\n</ng-if>\n'); +$templateCache.put('plugins/graph/templates/account/view_stats.html','<ion-view left-buttons="leftButtons"\n cache-view="false">\n <ion-nav-title>\n {{\'GRAPH.ACCOUNT.TITLE\' | translate}}{{id}}\n </ion-nav-title>\n\n <ion-content scroll="true" class="no-padding">\n\n\n\n <div class="list" >\n\n <!-- - - - - Balance - - - - -->\n <ng-controller ng-controller="GpAccountBalanceCtrl">\n <div class="center padding" ng-if="loading">\n <ion-spinner icon="android"></ion-spinner>\n </div>\n\n <div class="item item-divider" ng-if="!loading" >\n {{\'GRAPH.ACCOUNT.BALANCE_DIVIDER\'|translate}}\n <ion-spinner ng-if="loadingRange" class="ion-spinner-small" icon="android"></ion-spinner>\n </div>\n\n <div class="item no-padding-xs"\n ng-if="!loading"\n ng-include="\'plugins/graph/templates/account/graph_balance.html\'"\n ng-init="setSize(350, 1000)">\n </div>\n </ng-controller>\n\n </div>\n\n <div class="item no-padding-xs"\n ng-include="\'plugins/graph/templates/account/graph_sum_tx.html\'"\n ng-controller="GpAccountSumTxCtrl">\n </div>\n\n <!-- - - - - WOT - - - -\n <div class="item item-divider" translate>\n GRAPH.ACCOUNT.WOT_DIVIDER\n </div>\n\n <div class="item no-padding-xs"\n ng-include="\'plugins/graph/templates/account/graph_certifications.html\'"\n ng-controller="GpAccountCertificationCtrl"\n ng-init="setSize(350, 1000)">\n </div>-->\n\n </ion-content>\n\n</ion-view>\n'); +$templateCache.put('plugins/graph/templates/account/view_wallet_tx_extend.html','<!-- Buttons section -->\n<ng-if ng-if="extensionPoint === \'buttons\'">\n\n <button class="button button-stable button-small-padding icon ion-stats-bars"\n ng-click="showWalletStats()"\n title="{{\'GRAPH.ACCOUNT.BTN_SHOW_STATS\' | translate}}">\n </button>\n\n</ng-if>\n'); +$templateCache.put('plugins/graph/templates/blockchain/graph_block_issuers.html','\n <div class="row responsive-lg">\n\n <!-- bar -->\n <div class="col col-75">\n <canvas id="bar" class="chart-bar"\n height="{{height}}" width="{{width}}"\n chart-data="data"\n chart-labels="labels"\n chart-colors="colors"\n chart-options="barOptions"\n chart-click="onChartClick">\n </canvas>\n </div>\n\n <!-- pie -->\n <div class="col col-25 padding-top">\n <canvas id="blocksByIssuer-pie" class="chart-pie"\n chart-data="data"\n chart-labels="labels"\n chart-colors="colors"\n chart-click="onChartClick">\n </canvas>\n\n <div class="gray padding-top text-center">\n <small ng-bind-html="\'GRAPH.BLOCKCHAIN.BLOCKS_ISSUERS_HELP\'| translate:{issuerCount: data.length, blockCount: blockCount }"></small>\n </div>\n </div>\n </div>\n'); +$templateCache.put('plugins/graph/templates/blockchain/graph_tx_count.html','\n <!-- button bar -->\n <div class="button-bar-inline "\n style="top: 33px; margin-top:-33px; position: relative;">\n <button\n class="button button-stable button-clear no-padding-xs pull-right"\n ng-click="showActionsPopover($event)">\n <i class="icon ion-navicon-round"></i>\n </button>\n </div>\n\n <div class="padding-left padding-right">\n <canvas id="tx-line" class="chart-bar"\n height="{{height}}" width="{{width}}"\n chart-data="data"\n chart-dataset-override="datasetOverride"\n chart-colors="colors"\n chart-options="options"\n chart-labels="labels"\n chart-click="onChartClick">\n </canvas>\n </div>\n\n <ng-include src="\'plugins/graph/templates/common/graph_range_bar.html\'"></ng-include>\n'); +$templateCache.put('plugins/graph/templates/blockchain/view_stats.html','<ion-view left-buttons="leftButtons"\n cache-view="false">\n <ion-nav-title>\n {{\'GRAPH.BLOCKCHAIN.TITLE\' | translate}}{{id}}\n </ion-nav-title>\n\n <ion-content scroll="true" class="no-padding">\n\n <div class="center padding" ng-if="loading">\n <ion-spinner icon="android"></ion-spinner>\n </div>\n\n <div class="list" ng-if="!loading">\n\n\n <!-- TX count -->\n <ng-controller ng-controller="GpBlockchainTxCountCtrl">\n <div class="center padding" ng-if="loading">\n <ion-spinner icon="android"></ion-spinner>\n </div>\n\n <div class="item item-divider" ng-if="!loading" >\n {{\'GRAPH.BLOCKCHAIN.TX_DIVIDER\'|translate}}\n <ion-spinner ng-if="loadingRange" class="ion-spinner-small" icon="android"></ion-spinner>\n </div>\n\n <div class="item no-padding-xs no-padding-sm"\n ng-if="!loading"\n ng-include="\'plugins/graph/templates/blockchain/graph_tx_count.html\'"\n ng-init="setSize(350, 1000)">\n </div>\n </ng-controller>\n\n\n <!-- Blocks issuer -->\n <ng-controller ng-controller="GpBlockchainIssuersCtrl">\n\n <div class="item item-divider" ng-if="!loading" translate>GRAPH.BLOCKCHAIN.BLOCKS_ISSUERS_DIVIDER</div>\n\n <div class="item no-padding-xs no-padding-sm"\n ng-if="!loading"\n ng-include="\'plugins/graph/templates/blockchain/graph_block_issuers.html\'"\n ng-init="setSize(300, 750)">\n </div>\n\n </ng-controller>\n\n </ion-content>\n\n</ion-view>\n'); +$templateCache.put('plugins/graph/templates/common/graph_range_bar.html','\n <div class="range range-positive no-padding-left no-padding-right">\n <a\n class="button button-stable button-clear no-padding pull-left"\n ng-click="goPreviousRange($event)">\n <i class="icon ion-chevron-left"></i>\n </a>\n <input type="range"\n ng-model="formData.timePct"\n name="timePct"\n min="0" max="100"\n value="{{formData.timePct}}"\n ng-change="onRangeChanged();"\n ng-model-options="{ debounce: 250 }">\n <a\n class="button button-stable button-clear no-padding pull-right"\n ng-click="goNextRange($event)">\n <i class="icon ion-chevron-right"></i>\n </a>\n </div>\n'); +$templateCache.put('plugins/graph/templates/common/popover_range_actions.html','<ion-popover-view class="has-header popover-graph-currency">\n <ion-header-bar>\n <h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1>\n </ion-header-bar>\n <ion-content scroll="false">\n <div class="list item-text-wrap">\n\n <!-- scale -->\n <a class="item item-icon-left ink"\n ng-click="toggleScale()">\n <i class="icon ion-ios-checkmark-empty" ng-show="formData.scale==\'logarithmic\'"></i>\n <span ng-bind-html="\'GRAPH.COMMON.LOGARITHMIC_SCALE\' | translate"></span>\n </a>\n\n <!-- duration divider -->\n <div class="item item-divider">\n {{\'GRAPH.COMMON.RANGE_DURATION_DIVIDER\'|translate}}\n </div>\n\n <!-- duration: hour -->\n <a class="item item-icon-left ink"\n ng-click="setRangeDuration(\'hour\')">\n <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration==\'hour\'"></i>\n <span ng-bind-html="\'GRAPH.COMMON.RANGE_DURATION.HOUR\' | translate"></span>\n </a>\n\n <!-- duration: day -->\n <a class="item item-icon-left ink"\n ng-click="setRangeDuration(\'day\')">\n <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration==\'day\'"></i>\n <span ng-bind-html="\'GRAPH.COMMON.RANGE_DURATION.DAY\' | translate"></span>\n </a>\n\n <!-- duration: month -->\n <a class="item item-icon-left ink"\n ng-click="setRangeDuration(\'month\')">\n <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration==\'month\'"></i>\n <span ng-bind-html="\'GRAPH.COMMON.RANGE_DURATION.MONTH\' | translate"></span>\n </a>\n\n </div>\n </ion-content>\n</ion-popover-view>\n'); +$templateCache.put('plugins/graph/templates/currency/graph_du.html','\n <!-- graphs button bar -->\n <div class="button-bar-inline "\n style="top: 33px; margin-top:-33px; position: relative;">\n <button\n class="button button-stable button-clear no-padding-xs no-padding-sm pull-right"\n ng-click="showActionsPopover($event)">\n <i class="icon ion-navicon-round"></i>\n </button>\n </div>\n\n <canvas id="monetaryMass-bar" class="chart-bar"\n height="{{height}}"\n width="{{width}}"\n chart-data="data"\n chart-labels="labels"\n chart-colors="colors"\n chart-dataset-override="datasetOverride"\n chart-options="options"\n chart-click="showBlock">\n </canvas>\n'); +$templateCache.put('plugins/graph/templates/currency/graph_members_count.html',' <canvas id="membersCount-bar" class="chart-line"\n height="{{height}}"\n width="{{width}}"\n chart-data="data"\n chart-labels="labels"\n chart-colors="colors"\n chart-options="options"\n chart-dataset-override="datasetOverride"\n chart-click="onChartClick">\n </canvas>\n'); +$templateCache.put('plugins/graph/templates/currency/graph_monetary_mass.html','\n <!-- graphs button bar -->\n <div class="button-bar-inline "\n style="top: 33px; margin-top:-33px; position: relative;">\n <button\n class="button button-stable button-clear no-padding-xs pull-right"\n ng-click="showActionsPopover($event)">\n <i class="icon ion-navicon-round"></i>\n </button>\n </div>\n\n <canvas id="monetaryMass-bar"\n class="chart-bar"\n height="{{height}}"\n width="{{width}}"\n chart-data="data"\n chart-labels="labels"\n chart-colors="colors"\n chart-dataset-override="datasetOverride"\n chart-options="options"\n chart-click="onChartClick">\n </canvas>\n'); +$templateCache.put('plugins/graph/templates/currency/popover_monetary_mass_actions.html','<ion-popover-view class="fit has-header">\n <ion-header-bar>\n <h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1>\n </ion-header-bar>\n <ion-content scroll="false">\n <div class="list item-text-wrap">\n\n <a class="item item-icon-left ink"\n ng-click="toggleScale()">\n <i class="icon ion-ios-checkmark-empty" ng-show="formData.scale==\'logarithmic\'"></i>\n <span ng-bind-html="\'GRAPH.COMMON.LOGARITHMIC_SCALE\' | translate"></span>\n </a>\n\n </div>\n </ion-content>\n</ion-popover-view>\n'); +$templateCache.put('plugins/graph/templates/currency/tab_blocks_extend.html','<!-- buttons -->\n<ng-if ng-if="enable && extensionPoint === \'buttons\'">\n <div class="item item-divider">\n <a class="badge button button-text button-small button-small-padding ink" ui-sref="app.currency.tab_blocks_stats">\n <i class="icon ion-stats-bars"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_STATS</span>\n </a>\n </div>\n</ng-if>\n'); +$templateCache.put('plugins/graph/templates/currency/view_currency_extend.html','\n<!-- section actual parameters -->\n<ng-if ng-if="enable && extensionPoint === \'parameters-actual\'" >\n\n <ng-if ng-if="!smallscreen">\n <div class="item padding-left padding-right no-padding-xs no-padding-sm"\n ng-include="\'plugins/graph/templates/currency/graph_monetary_mass.html\'"\n ng-controller="GpCurrencyMonetaryMassCtrl"\n ng-init="displayShareAxis=false;">\n </div>\n <div class="item buttons no-padding-top ">\n <a class="pull-right button button-text button-small button-small-padding ink" ui-sref="app.currency_stats_lg">\n <i class="icon ion-stats-bars"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_DETAILED_STATS</span>\n </a>\n </div>\n </ng-if>\n\n <div class="item item-divider"\n ng-if="smallscreen">\n <a class="badge button button-text button-small button-small-padding ink" ui-sref="app.currency.tab_parameters_stats">\n <i class="icon ion-stats-bars"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_STATS</span>\n </a>\n </div>\n</ng-if>\n\n<!-- section Wot -->\n<ng-if ng-if="enable && extensionPoint === \'wot-actual\'" >\n\n <ng-if ng-if="!smallscreen">\n <div class="item padding-left padding-right no-padding-xs no-padding-sm"\n ng-include="\'plugins/graph/templates/currency/graph_members_count.html\'"\n ng-controller="GpCurrencyMembersCountCtrl">\n </div>\n <div class="item buttons no-padding-top ">\n <a class="pull-right button button-text button-small button-small-padding ink" ui-sref="app.currency_stats_lg">\n <i class="icon ion-stats-bars"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_DETAILED_STATS</span>\n </a>\n </div>\n </ng-if>\n\n <div class="item item-divider"\n ng-if="smallscreen">\n <a class="badge button button-text button-small button-small-padding ink" ui-sref="app.currency.tab_wot_stats">\n <i class="icon ion-stats-bars"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_STATS</span>\n </a>\n </div>\n</ng-if>\n\n<!-- section Wot -->\n<ng-if ng-if="enable && extensionPoint === \'network-actual\'" >\n\n <div class="item padding-left padding-right no-padding-xs no-padding-sm"\n ng-if="!smallscreen"\n ng-include="\'plugins/graph/templates/blockchain/graph_block_issuers.html\'"\n ng-controller="GpBlockchainIssuersCtrl">\n </div>\n\n <div class="item item-divider"\n ng-if="smallscreen">\n <a class="badge button button-text button-small button-small-padding ink" ui-sref="app.currency.tab_network_stats">\n <i class="icon ion-stats-bars"></i>\n <span translate>GRAPH.COMMON.BTN_SHOW_STATS</span>\n </a>\n </div>\n</ng-if>\n\n'); +$templateCache.put('plugins/graph/templates/currency/view_stats_lg.html','<ion-view left-buttons="leftButtons"\n cache-view="false">\n <ion-nav-title>\n {{\'GRAPH.BLOCKCHAIN.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content scroll="true" class="padding" >\n\n\n\n <div class="list" >\n\n <!-- Monetary mass -->\n <ng-controller ng-controller="GpCurrencyMonetaryMassCtrl" >\n\n <div class="center padding" ng-if="loading">\n <ion-spinner icon="android"></ion-spinner>\n </div>\n\n <div class="item no-padding-xs" ng-if="!loading"\n ng-include="\'plugins/graph/templates/currency/graph_monetary_mass.html\'"\n ng-init="setSize(250, 1000)">\n </div>\n\n <div ng-if="!loading"\n class="item item-toggle dark no-border text-right">\n <span class="" translate>COMMON.BTN_RELATIVE_UNIT</span>\n <label class="toggle toggle-royal" id="helptip-currency-change-unit">\n <input type="checkbox" ng-model="formData.useRelative">\n <div class="track">\n <div class="handle"></div>\n </div>\n </label>\n </div>\n </ng-controller>\n\n <!-- DU -->\n <ng-controller ng-controller="GpCurrencyDUCtrl" >\n <div class="item no-padding-xs"\n ng-if="!loading"\n ng-include="\'plugins/graph/templates/currency/graph_du.html\'"\n ng-init="setSize(250, 1000)">\n </div>\n </ng-controller>\n\n <!-- Member count -->\n <ng-controller ng-controller="GpCurrencyMembersCountCtrl" >\n <div class="item no-padding-xs"\n ng-if="!loading"\n ng-include="\'plugins/graph/templates/currency/graph_members_count.html\'"\n ng-init="setSize(250, 1000)">\n </div>\n\n\n </div>\n\n </ion-content>\n\n</ion-view>\n'); +$templateCache.put('plugins/graph/templates/currency/view_wot_stats.html','<ion-view left-buttons="leftButtons"\n cache-view="false">\n\n <ion-content scroll="true" >\n\n <div class="center padding" ng-if="loading">\n <ion-spinner icon="android"></ion-spinner>\n </div>\n\n <ng-include\n ng-if="!loading"\n src="\'plugins/graph/templates/currency/graph_members_count.html\'" ></ng-include>\n </ion-content>\n </ion-view>\n'); +$templateCache.put('plugins/graph/templates/docstats/graph.html','\n <!-- graphs button bar -->\n <div class="button-bar-inline "\n style="top: 33px; margin-top:-33px; position: relative;">\n <button\n class="button button-stable button-clear no-padding-xs no-padding-sm pull-right"\n ng-click="showActionsPopover($event)">\n <i class="icon ion-navicon-round"></i>\n </button>\n </div>\n\n <canvas id="{{::chartIdPrefix}}{{chart.id}}"\n class="chart-line"\n height="{{height}}"\n width="{{width}}"\n chart-data="chart.data"\n chart-labels="labels"\n chart-dataset-override="chart.datasetOverride"\n chart-options="chart.options"\n chart-click="onChartClick">\n </canvas>\n\n <ng-include src="\'plugins/graph/templates/common/graph_range_bar.html\'"></ng-include>\n'); +$templateCache.put('plugins/graph/templates/docstats/view_stats.html','<ion-view left-buttons="leftButtons"\n cache-view="false">\n <ion-nav-title>\n {{\'GRAPH.DOC_STATS.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content scroll="true" class="padding" >\n\n <div class="list" >\n\n <!-- Doc stat -->\n <div class="center padding" ng-if="loading">\n <ion-spinner icon="android"></ion-spinner>\n </div>\n\n <div class="item no-padding-xs no-padding-sm" ng-if="!loading"\n ng-repeat="chart in charts"\n ng-include="\'plugins/graph/templates/docstats/graph.html\'"\n ng-init="setSize(250, 1000)">\n </div>\n\n </div>\n\n </ion-content>\n\n</ion-view>\n'); +$templateCache.put('plugins/graph/templates/network/view_network_extend.html','<!-- Buttons section -->\n<ng-if ng-if="enable && extensionPoint === \'buttons\'">\n <a class="button button-text button-small ink"\n ui-sref="app.blockchain_stats" >\n <i class="icon ion-stats-bars"></i>\n <span>{{\'NETWORK.VIEW.BTN_GRAPH\'|translate}}</span>\n </a>\n</ng-if>\n'); +$templateCache.put('plugins/graph/templates/network/view_peer_extend.html','<!-- Buttons section -->\n<ng-if ng-if="enable && extensionPoint === \'general\'">\n\n <a class="item item-icon-left item-icon-right item-text-wrap ink"\n ui-sref="app.view_peer_stats({pubkey: node.pubkey})">\n <i class="icon ion-stats-bars"></i>\n <span translate>GRAPH.PEER.VIEW.BLOCK_COUNT_LABEL</span>\n <span class="badge"\n ng-if="!loading"\n ng-class="{\'badge-stable\': blockCount > 0, \'badge-assertive\': !blockCount}">\n {{!blockCount ? \'GRAPH.PEER.VIEW.NO_BLOCK\' : \'GRAPH.PEER.VIEW.BLOCK_COUNT\' | translate:{count: blockCount} }}\n </span>\n <ion-spinner class="badge" icon="android" ng-if="loading"></ion-spinner>\n <i class="gray icon ion-ios-arrow-right"></i>\n </a>\n</ng-if>\n\n'); +$templateCache.put('plugins/graph/templates/network/view_peer_stats.html','<ion-view left-buttons="leftButtons"\n cache-view="false">\n <ion-nav-title>\n {{\'GRAPH.BLOCKCHAIN.TITLE\' | translate}}{{id}}\n </ion-nav-title>\n\n <ion-content scroll="true" class="no-padding">\n\n <div class="center padding" ng-if="loading">\n <ion-spinner icon="android"></ion-spinner>\n </div>\n\n <div class="list" ng-if="!loading">\n\n <!-- - - - - TX divider - - - - -->\n <div class="item item-divider hidden-xs hidden-sm" translate>\n GRAPH.BLOCKCHAIN.TX_DIVIDER\n </div>\n\n <div class="item no-padding-xs"\n ng-include="\'plugins/graph/templates/blockchain/graph_tx_count.html\'"\n ng-init="setSize(350, 1000)">\n </div>\n\n </ion-content>\n\n</ion-view>\n'); +$templateCache.put('plugins/graph/templates/synchro/graph.html','\n <!-- graphs button bar -->\n <div class="button-bar-inline "\n style="top: 33px; margin-top:-33px; position: relative;">\n <button\n class="button button-stable button-clear no-padding-xs pull-right"\n ng-click="showActionsPopover($event)">\n <i class="icon ion-navicon-round"></i>\n </button>\n </div>\n\n <canvas id="synchro-chart-{{chart.id}}"\n class="chart-bar"\n height="{{height}}"\n width="{{width}}"\n chart-data="chart.data"\n chart-labels="labels"\n chart-dataset-override="chart.datasetOverride"\n chart-options="chart.options">\n </canvas>\n\n <ng-include src="\'plugins/graph/templates/common/graph_range_bar.html\'"></ng-include>\n'); +$templateCache.put('plugins/graph/templates/synchro/view_stats.html','<ion-view left-buttons="leftButtons"\n cache-view="false">\n <ion-nav-title>\n {{\'GRAPH.SYNCHRO.TITLE\' | translate}}\n </ion-nav-title>\n\n <ion-content scroll="true" class="padding" >\n\n <div class="list" >\n\n <div class="center padding" ng-if="loading">\n <ion-spinner icon="android"></ion-spinner>\n </div>\n\n <div class="item no-padding-xs" ng-if="!loading"\n ng-repeat="chart in charts"\n ng-include="\'plugins/graph/templates/synchro/graph.html\'"\n ng-init="setSize(250, 1000)">\n </div>\n\n </div>\n\n </ion-content>\n\n</ion-view>\n'); +$templateCache.put('plugins/map/templates/network/item_search_tooltip.html','<a href="#">\n {{peer.dns || peer.server}}\n <span class="{{peer.uid ? \'positive\' : \'gray\'}}">\n <i class="icon {{peer.uid ? \'ion-person\' : \'ion-key\'}}"></i>\n {{peer.uid ? (peer.name||peer.uid) : (peer.pubkey|formatPubkey) }}\n </span>\n <span class="gray">{{peer.ipv4 ? (peer.ipv4 + \':\' + peer.port) : \'\'}}</span>\n <span class="{{peer.bma.useSsl ? \'\' : \'ng-hide\'}}"><i class="ion-locked"></i> <small>SSL</small></span>\n</a>\n'); +$templateCache.put('plugins/map/templates/network/lookup_extend.html','<!-- FIXME issue #755 - https://git.duniter.org/clients/cesium-grp/cesium/issues/755\n<a ng-if="enable"\n class="button button-text button-small ink hidden-sm hidden-xs"\n title="{{\'MAP.NETWORK.LOOKUP.BTN_MAP_HELP\' | translate}}"\n ui-sref="app.view_network_map">\n <i class="icon ion-ios-location"></i>\n {{\'MAP.NETWORK.LOOKUP.BTN_MAP\' | translate}}\n</a>\n -->\n'); +$templateCache.put('plugins/map/templates/network/view_map.html','<ion-view left-buttons="leftButtons" class="view-map-network">\n <ion-nav-title>\n <span class="hidden-xs" translate>MAP.NETWORK.VIEW.TITLE</span>\n </ion-nav-title>\n\n <ion-nav-buttons side="secondary">\n </ion-nav-buttons>\n\n <ion-content data-tap-disabled="true">\n <leaflet id="{{::mapId}}"\n height="100%"\n center="map.center"\n markers="map.markers"\n layers="map.layers">\n </leaflet>\n </ion-content>\n</ion-view>\n'); +$templateCache.put('plugins/map/templates/registry/item_search_tooltip.html','<a href="#" class="{{type}}">\n <i class="{{\'cion-page-\' + type}}"></i>\n {{name != uid ? name +\' \' : \'\'}}\n <span class="gray">\n {{pubkey ? (pubkey|formatPubkey) : \'\'}}\n </span>\n</a>\n'); +$templateCache.put('plugins/map/templates/registry/lookup_lg_extend.html','<a class="button button-text button-small ink hidden-sm hidden-xs"\n title="{{\'MAP.REGISTRY.LOOKUP.BTN_MAP_HELP\' | translate}}"\n ui-sref="app.view_registry_map">\n <i class="icon ion-ios-location"></i>\n {{\'MAP.REGISTRY.LOOKUP.BTN_MAP\' | translate}}\n</a>\n'); +$templateCache.put('plugins/map/templates/registry/popup_marker.html','<div class="item no-border no-padding item-avatar "\n ng-if="loadingMarker">\n\n <i class="item-image icon ion-person"></i>\n\n <div class="item-content item-avatar-left-padding padding-top" >\n <h2 class="stable-bg">\n \n </h2>\n <h4 class="stable-bg col-75">\n \n </h4>\n <h4 class="stable-bg col-50">\n \n </h4>\n </div>\n</div>\n\n<a class="item no-border no-padding item-avatar ink animate-fade-in animate-show-hide ng-hide"\n ng-show="!loadingMarker"\n ui-sref="app.view_page({id: formData.id, title: formData.name})">\n <i ng-if="formData.avatar" class="item-image avatar" style="background-image: url({{::formData.avatar.src}}"></i>\n <i ng-if="!formData.avatar" class="item-image icon cion-page-{{::formData.type}}"></i>\n <div class="item-content item-avatar-left-padding padding-top">\n <h2 class="dark">\n {{::formData.name}}\n </h2>\n <h4 ng-if="::formData.category" class="gray" title="{{::formData.category.name}}">\n <b class="ion-flag"></b> {{::formData.category.name}}\n </h4>\n <h4 ng-if="::formData.city" class="gray" title="{{::formData.city}}">\n <b class="ion-location"></b> {{::formData.city}}\n </h4>\n </div>\n</a>\n<!-- buttons -->\n<div class="item no-border no-padding">\n <div class="pull-left gray">\n <!-- show description -->\n <a class="animate-fade-in animate-show-hide gray ng-hide"\n ng-class="{\'ion-arrow-down-b\': !showDescription, \'ion-arrow-up-b\': showDescription}"\n ng-click="showDescription=!showDescription;"\n title="{{\'PROFILE.DESCRIPTION\'|translate}}"\n ng-show="!loadingMarker && formData.description">\n \n </a>\n </div>\n</div>\n<div class="item no-border no-padding item-text-wrap hidden-xs ng-hide" ng-show="showDescription">\n <small trust-as-html="::formData.description|truncText:500"></small>\n</div>\n'); +$templateCache.put('plugins/map/templates/registry/view_map.html','<ion-view left-buttons="leftButtons" class="view-map-registry">\n <ion-nav-title>\n <span class="hidden-xs" translate>MAP.REGISTRY.VIEW.TITLE</span>\n </ion-nav-title>\n\n <ion-nav-buttons side="secondary">\n <button class="button button-icon button-clear icon ion-loop visible-xs visible-sm" ng-click="load()">\n </button>\n </ion-nav-buttons>\n\n <ion-content data-tap-disabled="true">\n <a id="helptip-map-registry" style="left: 150px; top: 50px; position: relative;"></a>\n <leaflet id="{{::mapId}}"\n height="100%"\n layers="map.layers"\n markers="map.markers"\n lf-center="map.center"\n bounds="map.bounds">\n </leaflet>\n </ion-content>\n</ion-view>\n'); +$templateCache.put('plugins/map/templates/settings/es_settings_extend.html','\n<!--<span class="item item-divider" translate>MAP.SETTINGS.MAP_DIVIDER</span>\n\n<label class="item item-toggle dark item-text-wrap">\n <span translate>MAP.SETTINGS.ENABLE_GOOGLE_API</span>\n <h4 class="gray" translate>MAP.SETTINGS.ENABLE_GOOGLE_API_HELP</h4>\n <div class="toggle toggle-royal">\n <input type="checkbox" ng-model="formData.enableGoogleApi">\n <div class="track">\n <div class="handle"></div>\n </div>\n </div>\n</label>\n\n<ion-item class="item-input"\n ng-if="!$root.config.plugins.es.googleApiKey"\n ng-class="{\'item-input-error\': formData.enableGoogleApi && !formData.googleApiKey}">\n <div class="input-label col-33">\n <span class="" ng-class="{\'gray\': !formData.enableGoogleApi}"translate>MAP.SETTINGS.GOOGLE_API_KEY</span>\n <h4>\n <a ng-click="openLink($event, \'https://console.developers.google.com/apis/credentials/key\')" translate>MAP.SETTINGS.BTN_GOOGLE_API</a>\n <span class="gray"> ({{\'MAP.SETTINGS.BTN_GOOGLE_API_WARNING\'|translate}})</span>\n </h4>\n </div>\n <input type="text"\n placeholder="{{\'MAP.SETTINGS.GOOGLE_API_KEY_PLACEHOLDER\' | translate}}"\n ng-model="formData.googleApiKey"\n ng-if="formData.enableGoogleApi">\n</ion-item>\n<div class="form-errors"\n ng-show="formData.enableGoogleApi && !formData.googleApiKey">\n <div class="form-error">\n <span translate="ERROR.FIELD_REQUIRED"></span>\n </div>\n</div>-->\n'); +$templateCache.put('plugins/map/templates/user/edit_profile_extend.html','<div class="item no-padding hidden-xs hidden-sm {{ionItemClass}}" ng-if="formData.geoPoint && formData.geoPoint.lat && formData.geoPoint.lon">\n <leaflet id="{{::mapId}}"\n height="250px"\n center="map.center"\n markers="map.markers"\n defaults="map.defaults">\n </leaflet>\n</div>\n'); +$templateCache.put('plugins/map/templates/wot/item_search_tooltip.html','<a href="#" class="{{type}}">\n <i class="{{pending ? \'ion-clock\': (type ? \'cion-page-\' + type : \'\')}}"></i>\n {{name != uid ? name +\' \' : \'\'}}\n <span class="{{uid ? \'positive\' : \'gray\'}}">\n <i class="{{uid ? \'ion-person\' : \'ion-key\'}}"></i>\n {{uid ? uid : (pubkey|formatPubkey) }}\n </span>\n</a>\n'); +$templateCache.put('plugins/map/templates/wot/lookup_lg_extend.html','<a ng-if="enable"\n class="button button-text button-small ink hidden-sm hidden-xs"\n title="{{\'MAP.WOT.LOOKUP.BTN_MAP_HELP\' | translate}}"\n ui-sref="app.view_wot_map">\n <i class="icon ion-ios-location"></i>\n {{\'MAP.WOT.LOOKUP.BTN_MAP\' | translate}}\n</a>\n'); +$templateCache.put('plugins/map/templates/wot/popup_marker.html','\n<div class="item no-border no-padding item-avatar "\n ng-if="loadingMarker">\n\n <i class="item-image icon ion-person"></i>\n\n <div class="item-content item-avatar-left-padding padding-top" >\n <h2 class="stable-bg">\n \n </h2>\n <h4 class="stable-bg col-75">\n \n </h4>\n <h4 class="stable-bg col-50">\n \n </h4>\n </div>\n</div>\n\n<a class="item no-border no-padding item-avatar ink animate-fade-in animate-show-hide ng-hide"\n ng-show="!loadingMarker"\n ui-sref="app.wot_identity({pubkey: formData.pubkey, uid: formData.uid})">\n\n <i ng-if="formData.avatar" class="item-image avatar" style="background-image: url({{::formData.avatar.src}})"></i>\n <i ng-if="!formData.avatar && formData.uid" class="item-image icon ion-person"></i>\n <i ng-if="!formData.avatar && !formData.uid" class="item-image icon ion-card"></i>\n\n <div class="item-content item-avatar-left-padding padding-top">\n <h2 class="dark">\n {{formData.name}}\n </h2>\n <h4>\n <span ng-if="formData.uid" class="positive">\n <b class="ion-person"></b>\n {{formData.uid}}\n </span>\n <span class="gray" title="{{formData.pubkey}}"><b class="ion-key"></b> {{formData.pubkey|formatPubkey}}</span>\n <span class="assertive" ng-if="!formData.isMember">\n {{::\'WOT.NOT_MEMBER_PARENTHESIS\'|translate}}\n </span>\n </h4>\n <h4 ng-if="formData.profile.city" class="gray" title="{{formData.profile.city}}">\n <b class="ion-location"></b> {{formData.profile.city}}\n </h4>\n </div>\n</a>\n<!-- buttons -->\n<div class="item no-border no-padding">\n <div class="pull-left gray">\n <!-- show description -->\n <a class="animate-fade-in animate-show-hide gray ng-hide"\n ng-class="{\'ion-arrow-down-b\': !showDescription, \'ion-arrow-up-b\': showDescription}"\n ng-click="showDescription=!showDescription;"\n title="{{\'PROFILE.DESCRIPTION\'|translate}}"\n ng-show="!loadingMarker && formData.profile.description">\n \n </a>\n </div>\n <div style="font-size: 18px;" class="pull-right gray">\n <!-- share -->\n <a class="icon ion-android-share-alt "\n ng-click="showSharePopover($event)"\n title="{{\'COMMON.BTN_SHARE\' | translate}}"> </a>\n <!-- certify -->\n <a class="icon ion-ribbon-b"\n ng-click="certify()"\n title="{{\'WOT.BTN_CERTIFY\' | translate}}"\n ng-hide="!canCertify"> </a>\n <!-- compose message -->\n <a class="icon ion-compose"\n ng-click="showNewMessageModal()"\n title="{{\'MESSAGE.BTN_WRITE\' | translate}}"> </a>\n <!-- transfer -->\n <a class="icon ion-card"\n ng-click="showTransferModal({pubkey:formData.pubkey, uid: formData.name||formData.uid})"\n title="{{\'COMMON.BTN_SEND_MONEY\' | translate}}"> </a>\n\n </div>\n</div>\n<div class="item no-border no-padding item-text-wrap hidden-xs ng-hide" ng-show="showDescription">\n <small trust-as-html="formData.profile.description|truncText:500"></small>\n</div>\n'); +$templateCache.put('plugins/map/templates/wot/view_map.html','<ion-view left-buttons="leftButtons" class="view-map-wot">\n <ion-nav-title>\n <span class="hidden-xs" translate>MAP.WOT.VIEW.TITLE</span>\n </ion-nav-title>\n\n <ion-nav-buttons side="secondary">\n <button class="button button-icon button-clear icon ion-loop visible-xs visible-sm" ng-click="load()">\n </button>\n </ion-nav-buttons>\n\n <ion-content data-tap-disabled="true">\n <a id="helptip-map-wot" style="left: 150px; top: 50px; position: relative;"></a>\n <leaflet id="{{::mapId}}"\n height="100%"\n layers="map.layers"\n markers="map.markers"\n lf-center="map.center"\n bounds="map.bounds">\n </leaflet>\n </ion-content>\n</ion-view>\n'); +$templateCache.put('plugins/es/templates/message/tabs/tab_list.html','<ion-view><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point><button class="button button-icon button-clear icon ion-android-more-vertical" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="refresh()"></ion-refresher><cs-extension-point name="buttons"></cs-extension-point><ng-include src="\'plugins/es/templates/message/list.html\'"></ng-include></ion-content><div class="visible-xs visible-sm"><button ng-if="fabButtonNewMessageId" id="{{::fabButtonNewMessageId}}" class="button button-fab button-fab-bottom-right button-assertive spin has-footer" ng-click="showNewMessageModal()"><i class="icon ion-compose"></i></button></div></ion-view>'); +$templateCache.put('plugins/es/templates/registry/tabs/tab_registry.html','<ion-view><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point><button class="button button-icon button-clear" ng-click="showFiltersPopover($event)"><i class="icon ion-android-funnel"></i></button> <button class="button button-icon button-clear icon ion-android-more-vertical" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content><ion-refresher pulling-text="{{\'COMMON.BTN_REFRESH\' | translate}}" on-refresh="doSearch()"></ion-refresher><cs-extension-point name="buttons"></cs-extension-point><ng-include src="::\'plugins/es/templates/registry/lookup_form.html\'"></ng-include><ng-include src="::\'plugins/es/templates/registry/lookup_list.html\'"></ng-include></ion-content></ion-view>'); +$templateCache.put('plugins/graph/templates/currency/tabs/tab_blocks_stats.html','<ion-view>\n <ion-content>\n <div\n ng-include="\'plugins/graph/templates/blockchain/graph_tx_count.html\'"\n ng-controller="GpBlockchainTxCountCtrl"\n ng-init="setSize(500,700,false)">\n </div>\n </ion-content>\n</ion-view>\n'); +$templateCache.put('plugins/graph/templates/currency/tabs/tab_network_stats.html','<ion-view>\n <ion-content>\n\n <div class="list">\n <div class="item"\n ng-include="\'plugins/graph/templates/blockchain/graph_block_issuers.html\'"\n ng-controller="GpBlockchainIssuersCtrl"\n ng-init="setSize(500,700,true)">\n </div>\n </div>\n </ion-content>\n</ion-view>\n'); +$templateCache.put('plugins/graph/templates/currency/tabs/tab_parameters_stats.html','<ion-view>\n <ion-content>\n <div class="list no-padding-xs no-padding-sm">\n\n <ng-container ng-controller="GpCurrencyMonetaryMassCtrl">\n\n <div class="center padding" ng-if="loading">\n <ion-spinner icon="android"></ion-spinner>\n </div>\n\n <!-- Monetary mass -->\n <div class="item"\n ng-include="\'plugins/graph/templates/currency/graph_monetary_mass.html\'"\n ng-init="setSize(500,700,true)">\n </div>\n </ng-container>\n\n <!-- DU -->\n <ng-container ng-controller="GpCurrencyDUCtrl">\n <div class="item"\n ng-include="\'plugins/graph/templates/currency/graph_du.html\'"\n ng-init="setSize(500,700,true)">\n </div>\n </ng-container>\n </div>\n </ion-content>\n</ion-view>\n'); +$templateCache.put('plugins/graph/templates/currency/tabs/tab_wot_stats.html','<ion-view>\n <ion-content>\n <div class="center padding" ng-if="loading">\n <ion-spinner icon="android"></ion-spinner>\n </div>\n\n <div class="list no-padding">\n <div class="item no-padding-top"\n ng-include="\'plugins/graph/templates/currency/graph_members_count.html\'"\n ng-init="setSize(600,700,false)">\n </div>\n </div>\n </ion-content>\n</ion-view>\n');}]); \ No newline at end of file diff --git a/assets/www/dist/dist_js/plugins/translations.js b/assets/www/dist/dist_js/plugins/translations.js index 0368ad9b1b05846c3bedd4e25177891cd2b3315a..dbae81a0c1f4e8c2395a854f5e87f0d6f7e8ea14 100644 --- a/assets/www/dist/dist_js/plugins/translations.js +++ b/assets/www/dist/dist_js/plugins/translations.js @@ -11,6 +11,10 @@ $translateProvider.translations("en-GB", { "BTN_PICTURE_FAVORISE": "Default", "BTN_PICTURE_ROTATE": "Rotate", "BTN_ADD_PICTURE": "Add picture", + "NOTIFICATION": { + "TITLE": "New notification | {{'COMMON.APP_NAME'|translate}}", + "HAS_UNREAD": "You have {{count}} unread notification{{count>0?'s':''}}" + }, "NOTIFICATIONS": { "TITLE": "Notifications", "MARK_ALL_AS_READ": "Mark all as read", @@ -32,7 +36,7 @@ $translateProvider.translations("en-GB", { "ORGANIZATION_ACCOUNT_HELP": "If you represent a company, association, etc.<br/>No universal dividend will be created by this account." }, "EVENT": { - "MEMBER_WITHOUT_PROFILE": "To obtain your certification more quickly, fill in <a ui-sref=\"app.user_edit_profile\">your user profile</a>. Members will more easily put their trust in a verifiable identity." + "MEMBER_WITHOUT_PROFILE": "You can <a ui-sref=\"app.edit_profile\">fill your Cesium+ profile</a> (optional) to provide better visibility of your account. This profile will be stored in <b>a directory independent</b> of the currency, but decentralized." }, "ERROR": { "WS_CONNECTION_FAILED": "Cesium can not receive notifications because of a technical error (connection to the Cesium + data node).<br/><br/>If the problem persists, please <b>choose another data node</b> in Cesium+ settings." @@ -204,7 +208,7 @@ $translateProvider.translations("en-GB", { "TX_SEARCH_FILTER": { "MEMBER_FLOWS": "<b class=\"ion-person\"></b> Members input/output", "EXISTING_TRANSACTION": "<b class=\"ion-card\"></b> Having transactions", - "PERIOD": "<b class=\"ion-clock\"></b> Between <b class=\"gray\">{{params[1]|formatDateShort}}</b> ({{params[1]|formatTime}}) and <b class=\"gray\">{{params[2]|formatDateShort}}</b> ({{params[2]|formatTime}})", + "PERIOD": "<b class=\"ion-clock\"></b> Between <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) and <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", "ISSUER": "<b class=\"ion-android-desktop\"></b> Computed by {{params[1]|formatPubkey}}", "TX_PUBKEY": "<b class=\"ion-card\"></b> Transactions concerning <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" } @@ -227,7 +231,7 @@ $translateProvider.translations("en-GB", { "MY_PAGES": "My pages", "NO_PAGE": "No page", "SEARCH": { - "TITLE": "Professional Directory", + "TITLE": "Pages", "SEARCH_HELP": "What, Who: hairdresser, Lili's restaurant, ...", "BTN_ADD": "New", "BTN_LAST_RECORDS": "Recent pages", @@ -254,7 +258,7 @@ $translateProvider.translations("en-GB", { "REMOVE_CONFIRMATION" : "Are you sure you want to delete this reference?<br/><br/>This is irreversible." }, "TYPE": { - "TITLE": "New reference", + "TITLE": "New page", "SELECT_TYPE": "Kind of organization:", "ENUM": { "SHOP": "Local shops", @@ -265,7 +269,7 @@ $translateProvider.translations("en-GB", { }, "EDIT": { "TITLE": "Edit", - "TITLE_NEW": "New reference", + "TITLE_NEW": "New page", "RECORD_TYPE":"Kind of organization", "RECORD_TITLE": "Name", "RECORD_TITLE_HELP": "Name", @@ -351,7 +355,8 @@ $translateProvider.translations("en-GB", { "DISTANCE": "Maximum distance around the city", "DISTANCE_UNIT": "mi", "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", - "SEARCH_HELP": "Ville, Country", + "SEARCH_HELP": "City, Country", + "PROFILE_POSITION": "Profile position", "MODAL": { "TITLE": "Search address", "SEARCH_HELP": "City, Country", @@ -359,6 +364,7 @@ $translateProvider.translations("en-GB", { "POSITION": "lat/lon : {{lat}} / {{lon}}" }, "ERROR": { + "CITY_REQUIRED_IF_STREET": "Required if a street has been filled", "REQUIRED_FOR_LOCATION": "Required field to appear on the map", "INVALID_FOR_LOCATION": "Unknown address", "GEO_LOCATION_FAILED": "Unable to retrieve your current position. Please use the search button.", @@ -438,8 +444,9 @@ $translateProvider.translations("en-GB", { "PLUGIN_NAME": "Cesium+", "PLUGIN_NAME_HELP": "User profiles, notifications, private messages", "ENABLE_TOGGLE": "Enable extension?", - "ENABLE_MESSAGE_TOGGLE": "Enable messages?", - "ENABLE_SETTINGS_TOGGLE": "Enable remote storage for settings?", + "ENABLE_REMOTE_STORAGE": "Enable remote storage for settings?", + "ENABLE_REMOTE_STORAGE_HELP": "Enables (encrypted) storage of your settings on Cesium + nodes", + "ENABLE_MESSAGE_TOGGLE": "Enable private messages?", "PEER": "Data peer address", "POPUP_PEER": { "TITLE" : "Data peer", @@ -452,7 +459,9 @@ $translateProvider.translations("en-GB", { "ENABLE_TX_SENT": "Notify the validation of <b>sent payments</b>?", "ENABLE_TX_RECEIVED": "Notify the validation of <b>received payments</b>?", "ENABLE_CERT_SENT": "Notify the validation of <b>sent certifications</b>?", - "ENABLE_CERT_RECEIVED": "Notify the validation of <b>received certifications</b>?" + "ENABLE_CERT_RECEIVED": "Notify the validation of <b>received certifications</b>?", + "ENABLE_HTML5_NOTIFICATION": "Warn with each new notification?", + "ENABLE_HTML5_NOTIFICATION_HELP": "Opens a small popup window with each new notification." }, "CONFIRM": { "ASK_ENABLE_TITLE": "Optional features", @@ -508,6 +517,10 @@ $translateProvider.translations("en", { "BTN_PICTURE_FAVORISE": "Default", "BTN_PICTURE_ROTATE": "Rotate", "BTN_ADD_PICTURE": "Add picture", + "NOTIFICATION": { + "TITLE": "New notification | {{'COMMON.APP_NAME'|translate}}", + "HAS_UNREAD": "You have {{count}} unread notification{{count>0?'s':''}}" + }, "NOTIFICATIONS": { "TITLE": "Notifications", "MARK_ALL_AS_READ": "Mark all as read", @@ -529,7 +542,7 @@ $translateProvider.translations("en", { "ORGANIZATION_ACCOUNT_HELP": "If you represent a company, association, etc.<br/>No universal dividend will be created by this account." }, "EVENT": { - "MEMBER_WITHOUT_PROFILE": "To obtain your certification more quickly, fill in <a ui-sref=\"app.user_edit_profile\">your user profile</a>. Members will more easily put their trust in a verifiable identity." + "MEMBER_WITHOUT_PROFILE": "You can <a ui-sref=\"app.edit_profile\">fill your Cesium+ profile</a> (optional) to provide better visibility of your account. This profile will be stored in <b>a directory independent</b> of the currency, but decentralized." }, "ERROR": { "WS_CONNECTION_FAILED": "Cesium can not receive notifications because of a technical error (connection to the Cesium + data node).<br/><br/>If the problem persists, please <b>choose another data node</b> in Cesium+ settings." @@ -701,7 +714,7 @@ $translateProvider.translations("en", { "TX_SEARCH_FILTER": { "MEMBER_FLOWS": "<b class=\"ion-person\"></b> Members input/output", "EXISTING_TRANSACTION": "<b class=\"ion-card\"></b> Having transactions", - "PERIOD": "<b class=\"ion-clock\"></b> Between <b class=\"gray\">{{params[1]|formatDateShort}}</b> ({{params[1]|formatTime}}) and <b class=\"gray\">{{params[2]|formatDateShort}}</b> ({{params[2]|formatTime}})", + "PERIOD": "<b class=\"ion-clock\"></b> Between <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) and <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", "ISSUER": "<b class=\"ion-android-desktop\"></b> Computed by {{params[1]|formatPubkey}}", "TX_PUBKEY": "<b class=\"ion-card\"></b> Transactions concerning <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" } @@ -724,7 +737,7 @@ $translateProvider.translations("en", { "MY_PAGES": "My pages", "NO_PAGE": "No page", "SEARCH": { - "TITLE": "Professional Directory", + "TITLE": "Pages", "SEARCH_HELP": "What, Who: hairdresser, Lili's restaurant, ...", "BTN_ADD": "New", "BTN_LAST_RECORDS": "Recent pages", @@ -751,7 +764,7 @@ $translateProvider.translations("en", { "REMOVE_CONFIRMATION" : "Are you sure you want to delete this reference?<br/><br/>This is irreversible." }, "TYPE": { - "TITLE": "New reference", + "TITLE": "New page", "SELECT_TYPE": "Kind of organization:", "ENUM": { "SHOP": "Local shops", @@ -762,7 +775,7 @@ $translateProvider.translations("en", { }, "EDIT": { "TITLE": "Edit", - "TITLE_NEW": "New reference", + "TITLE_NEW": "New page", "RECORD_TYPE":"Kind of organization", "RECORD_TITLE": "Name", "RECORD_TITLE_HELP": "Name", @@ -848,7 +861,8 @@ $translateProvider.translations("en", { "DISTANCE": "Maximum distance around the city", "DISTANCE_UNIT": "mi", "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", - "SEARCH_HELP": "Ville, Country", + "SEARCH_HELP": "City, Country", + "PROFILE_POSITION": "Profile position", "MODAL": { "TITLE": "Search address", "SEARCH_HELP": "City, Country", @@ -856,6 +870,7 @@ $translateProvider.translations("en", { "POSITION": "lat/lon : {{lat}} / {{lon}}" }, "ERROR": { + "CITY_REQUIRED_IF_STREET": "Required if a street has been filled", "REQUIRED_FOR_LOCATION": "Required field to appear on the map", "INVALID_FOR_LOCATION": "Unknown address", "GEO_LOCATION_FAILED": "Unable to retrieve your current position. Please use the search button.", @@ -935,8 +950,9 @@ $translateProvider.translations("en", { "PLUGIN_NAME": "Cesium+", "PLUGIN_NAME_HELP": "User profiles, notifications, private messages", "ENABLE_TOGGLE": "Enable extension?", - "ENABLE_MESSAGE_TOGGLE": "Enable messages?", - "ENABLE_SETTINGS_TOGGLE": "Enable remote storage for settings?", + "ENABLE_REMOTE_STORAGE": "Enable remote storage for settings?", + "ENABLE_REMOTE_STORAGE_HELP": "Enables (encrypted) storage of your settings on Cesium + nodes", + "ENABLE_MESSAGE_TOGGLE": "Enable private messages?", "PEER": "Data peer address", "POPUP_PEER": { "TITLE" : "Data peer", @@ -949,7 +965,9 @@ $translateProvider.translations("en", { "ENABLE_TX_SENT": "Notify the validation of <b>sent payments</b>?", "ENABLE_TX_RECEIVED": "Notify the validation of <b>received payments</b>?", "ENABLE_CERT_SENT": "Notify the validation of <b>sent certifications</b>?", - "ENABLE_CERT_RECEIVED": "Notify the validation of <b>received certifications</b>?" + "ENABLE_CERT_RECEIVED": "Notify the validation of <b>received certifications</b>?", + "ENABLE_HTML5_NOTIFICATION": "Warn with each new notification?", + "ENABLE_HTML5_NOTIFICATION_HELP": "Opens a small popup window with each new notification." }, "CONFIRM": { "ASK_ENABLE_TITLE": "Optional features", @@ -993,6 +1011,563 @@ $translateProvider.translations("en", { } ); +$translateProvider.translations("eo-EO", { + "COMMON": { + "CATEGORY": "Kategorio", + "CATEGORIES": "Kategorioj", + "CATEGORY_SEARCH_HELP": "Serĉado", + "LAST_MODIFICATION_DATE": "Äœisdatigita la", + "SUBMIT_BY": "Submetita de", + "BTN_PUBLISH": "Publikigi", + "BTN_PICTURE_DELETE": "Forigi", + "BTN_PICTURE_FAVORISE": "Precipa", + "BTN_PICTURE_ROTATE": "Turni", + "BTN_ADD_PICTURE": "Aldoni foton", + "NOTIFICATION": { + "TITLE": "Nova avizo | {{'COMMON.APP_NAME'|translate}}", + "HAS_UNREAD": "Vi havas {{count}} avizo{{count>0?'j':''}}n ne legita{{count>0?'j':''}}n" + }, + "NOTIFICATIONS": { + "TITLE": "Avizoj", + "MARK_ALL_AS_READ": "Ĉion marki legita", + "NO_RESULT": "Neniu avizo", + "SHOW_ALL": "Vidi ĉion", + "LOAD_NOTIFICATIONS_FAILED": "Malsukceso por ÅarÄi la avizojn" + } + }, + "MENU": { + "REGISTRY": "PaÄoj", + "USER_PROFILE": "Mia profilo", + "MESSAGES": "MesaÄoj", + "NOTIFICATIONS": "Avizoj", + "INVITATIONS": "Invitoj" + }, + "ACCOUNT": { + "NEW": { + "ORGANIZATION_ACCOUNT": "Konto por organizaĵo", + "ORGANIZATION_ACCOUNT_HELP": "Se vi reprezentas entreprenon, asocion, ktp.<br/>Neniu universala dividendo estos kreita per tiu ĉi konto." + }, + "EVENT": { + "MEMBER_WITHOUT_PROFILE": "Vi povas <a ui-sref=\"app.edit_profile\">tajpi vian profilon Cesium+</a> (kromebleco) por disponi pli bonan videblecon por via konto." + }, + "ERROR": { + "WS_CONNECTION_FAILED": "Cesium ne povas ricevi la avizojn pro teknika eraro (konekto al la daten-nodo Cesium+).<br/><br/>Se la problemo daÅradas, bonvolu <b>elekti alian daten-nodon</b> ĉe la parametroj Cesium+." + } + }, + "WOT": { + "BTN_SUGGEST_CERTIFICATIONS_DOTS": "Sugesti identecojn atestotajn...", + "BTN_ASK_CERTIFICATIONS_DOTS": "Peti membrojn atesti min...", + "BTN_ASK_CERTIFICATION": "Peti atestaĵon", + "SUGGEST_CERTIFICATIONS_MODAL": { + "TITLE": "Sugesti atestadojn", + "HELP": "Elekti viajn sugestojn" + }, + "ASK_CERTIFICATIONS_MODAL": { + "TITLE": "Peti atestaĵojn", + "HELP": "Elekti la ricevontojn" + }, + "SEARCH": { + "DIVIDER_PROFILE": "Kontoj", + "DIVIDER_PAGE": "PaÄoj", + "DIVIDER_GROUP": "Grupoj" + }, + "CONFIRM": { + "SUGGEST_CERTIFICATIONS": "Ĉu vi certas, ke vi volas <b>sendi tiujn sugestojn por atestado</b>?", + "ASK_CERTIFICATION": "Ĉu vi certas, ke vi volas <b>sendi atesto-peton</b>?", + "ASK_CERTIFICATIONS": "Ĉu vi certas, ke vi volas <b>sendi atesto-peton</b> al tiuj personoj?" + } + }, + "INVITATION": { + "TITLE": "Invitoj", + "NO_RESULT": "Neniu invito atendanta", + "BTN_DELETE_ALL": "Forigi ĉiujn invitojn", + "BTN_DELETE": "Forigi la inviton", + "BTN_NEW_INVITATION": "Nova invito", + "ASK_CERTIFICATION": "<a href=\"#/app/wot/{{pubkey}}/{{::uid}}\">{{::name||uid}}</a> petas vian atestadon", + "SUGGESTION_CERTIFICATION": "<a href=\"#/app/wot/{{::pubkey}}/{{::uid}}\">{{::name||uid}}</a> estas sugestita al vi por atestado", + "SUGGESTED_BY": "Sugesto sendita de <a class=\"positive\" href=\"#/app/wot/{{::issuer.pubkey}}/{{::issuer.uid}}\">{{::issuer.name||issuer.uid}}</a>", + "NOTIFICATIONS": { + "TITLE": "Invitoj" + }, + "LIST": { + "TITLE": "Invitoj" + }, + "NEW": { + "TITLE": "Nova invito", + "RECIPIENTS": "Al", + "RECIPIENTS_HELP": "Ricevontoj de la invito", + "RECIPIENTS_MODAL_TITLE": "Ricevontoj", + "RECIPIENTS_MODAL_HELP": "Bonvolu elekti la ricevontojn:", + "SUGGESTION_IDENTITIES": "Sugestoj por atestado", + "SUGGESTION_IDENTITIES_HELP": "Atestadoj sugestotaj", + "SUGGESTION_IDENTITIES_MODAL_TITLE": "Sugestoj", + "SUGGESTION_IDENTITIES_MODAL_HELP": "Bonvolu elekti viajn sugestojn:" + }, + "CONFIRM": { + "DELETE_ALL_CONFIRMATION": "La forigo de la invitoj estas <b>neinversigebla ago</b>.<br/><br/><b>Ĉu vi certas</b>, ke vi volas daÅrigi?", + "SEND_INVITATIONS_TO_CERTIFY": "Ĉu vi certas, ke vi volas <b>sendi tiun inviton atestotan</b>?" + }, + "INFO": { + "INVITATION_SENT": "Invito sendita" + }, + "ERROR": { + "LOAD_INVITATIONS_FAILED": "Malsukceso por ÅarÄi la invitojn", + "REMOVE_INVITATION_FAILED": "Eraro dum la forigo de la invito", + "REMOVE_ALL_INVITATIONS_FAILED": "Eraro dum la forigo de la invitoj", + "SEND_INVITATION_FAILED": "Eraro dum la sendo de la invito", + "BAD_INVITATION_FORMAT": "<span class=\"assertive\"><i class=\"ion-close-circled\"></i> Invito nelegebla (strukturo nekonata)</span> - sendita de <a ui-sref=\"app.wot_identity({pubkey: '{{::pubkey}}', uid: '{{::uid}}' })\">{{::name||uid}}</a>" + } + }, + "COMMENTS": { + "DIVIDER": "Komentoj", + "SHOW_MORE_COMMENTS": "AfiÅi la antaÅajn komentojn", + "COMMENT_HELP": "Via komento, demando, ktp.", + "COMMENT_HELP_REPLY_TO": "Via respondo...", + "BTN_SEND": "Sendi", + "POPOVER_SHARE_TITLE": "MesaÄo #{{number}}", + "REPLY": "Respondi", + "REPLY_TO": "Respondo al:", + "REPLY_TO_LINK": "Responde al ", + "REPLY_TO_DELETED_COMMENT": "Responde al forigita komento", + "REPLY_COUNT": "{{replyCount}} respondoj", + "DELETED_COMMENT": "Komento forigita", + "ERROR": { + "FAILED_SAVE_COMMENT": "Eraro dum la konservo de la komento", + "FAILED_REMOVE_COMMENT": "Eraro dum la forigo de la komento" + } + }, + "MESSAGE": { + "REPLY_TITLE_PREFIX": "Resp: ", + "FORWARD_TITLE_PREFIX": "Tr: ", + "BTN_REPLY": "Respondi", + "BTN_COMPOSE": "Nova mesaÄo", + "BTN_WRITE": "Skribi", + "NO_MESSAGE_INBOX": "Neniu mesaÄo ricevita", + "NO_MESSAGE_OUTBOX": "Neniu mesaÄo sendita", + "NOTIFICATIONS": { + "TITLE": "MesaÄoj", + "MESSAGE_RECEIVED": "Vi <b>ricevis mesaÄon</b><br/>de" + }, + "LIST": { + "INBOX": "Ricevujo", + "OUTBOX": "Senditaj mesaÄoj", + "LAST_INBOX": "Novaj mesaÄoj", + "LAST_OUTBOX": "Senditaj mesaÄoj", + "BTN_LAST_MESSAGES": "FreÅdataj mesaÄoj", + "TITLE": "MesaÄoj", + "SEARCH_HELP": "Serĉado en la mesaÄoj", + "POPOVER_ACTIONS": { + "TITLE": "Kromaĵoj", + "DELETE_ALL": "Forigi ĉiujn mesaÄojn" + } + }, + "COMPOSE": { + "TITLE": "Nova mesaÄo", + "TITLE_REPLY": "Respondi", + "SUB_TITLE": "Nova mesaÄo", + "TO": "Al", + "OBJECT": "Temo", + "OBJECT_HELP": "Temo", + "ENCRYPTED_HELP": "Bonvolu noti, ke tiu ĉi mesaÄo estos ĉifrita antaÅ sendo, tiel ke nur la adresato povos legi Äin, kaj ke li estos certa, ke vi ja estas ties aÅtoro.", + "MESSAGE": "MesaÄo", + "MESSAGE_HELP": "Enhavo de la mesaÄo", + "CONTENT_CONFIRMATION": "La enhavo de la mesaÄo estas malplena.<br/><br/>Ĉu vi volas tamen sendi la mesaÄon?" + }, + "VIEW": { + "TITLE": "MesaÄo", + "SENDER": "Sendita de", + "RECIPIENT": "Sendita al", + "NO_CONTENT": "MesaÄo malplena", + "DELETE": "Forigi la mesaÄon" + }, + "CONFIRM": { + "REMOVE": "Ĉu vi certas, ke vi volas <b>forigi tiun ĉi mesaÄon</b>?<br/><br/>Tiu ago estas neinversigebla.", + "REMOVE_ALL" : "Ĉu vi certas, ke vi volas <b>forigi ĉiujn mesaÄojn</b>?<br/><br/>Tiu ago estas neinversigebla.", + "MARK_ALL_AS_READ": "Ĉu vi certas, ke vi volas <b>marki ĉiujn mesaÄojn legitaj</b>?", + "USER_HAS_NO_PROFILE": "Tiu identeco havas neniun profilon Cesium+. Eblas ke Äi ne uzas la krom-programon Cesium+, kaj <b>do ne legos vian mesaÄon</b>.<br/><br/>Ĉu vi certas, ke vi volas tamen <b>daÅrigi</b>?" + }, + "INFO": { + "MESSAGE_REMOVED": "MesaÄo forigita", + "All_MESSAGE_REMOVED": "Ĉiuj mesaÄoj estis forigitaj", + "MESSAGE_SENT": "MesaÄo sendita" + }, + "ERROR": { + "SEND_MSG_FAILED": "Eraro dum la sendo de la mesaÄo.", + "LOAD_MESSAGES_FAILED": "Eraro dum la ricevo de la mesaÄoj.", + "LOAD_MESSAGE_FAILED": "Eraro dum la ricevo de la mesaÄo.", + "MESSAGE_NOT_READABLE": "Legado de la mesaÄo neebla.", + "USER_NOT_RECIPIENT": "Vi ne estas la adresato de tiu ĉi mesaÄo: malĉifrado neebla.", + "NOT_AUTHENTICATED_MESSAGE": "La aÅtenteco de la mesaÄo estas dubinda aÅ ties enhavo estas difektita.", + "REMOVE_MESSAGE_FAILED": "Malsukceso por forigi la mesaÄon", + "MESSAGE_CONTENT_TOO_LONG": "Signaro tro longa ({{maxLength}} signoj maksimume).", + "MARK_AS_READ_FAILED": "Neeblas marki la mesaÄon 'legita'.", + "LOAD_NOTIFICATIONS_FAILED": "Eraro dum la ricevo de la mesaÄo-avizoj.", + "REMOVE_All_MESSAGES_FAILED": "Eraro dum la forigo de ĉiuj mesaÄoj.", + "MARK_ALL_AS_READ_FAILED": "Eraro por marki la mesaÄojn legitaj.", + "RECIPIENT_IS_MANDATORY": "La adresato estas deviga." + } + }, + "BLOCKCHAIN": { + "LOOKUP": { + "SEARCH_HELP": "Numero de bloko, haketo, publika Ålosilo, ktp.", + "POPOVER_FILTER_TITLE": "Filtriloj", + "HEADER_MEDIAN_TIME": "Dato / Horo", + "HEADER_BLOCK": "Bloko #", + "HEADER_ISSUER": "Nodo elsendinta", + "BTN_LAST": "Lastaj blokoj", + "DISPLAY_QUERY": "AfiÅi la informpeton", + "HIDE_QUERY": "KaÅi la informpeton", + "TX_SEARCH_FILTER": { + "MEMBER_FLOWS": "<b class=\"ion-person\"></b> Eniroj/eliroj de membroj", + "EXISTING_TRANSACTION": "<b class=\"ion-card\"></b> Kun spezoj", + "PERIOD": "<b class=\"ion-clock\"></b> Inter <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) kaj <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", + "ISSUER": "<b class=\"ion-android-desktop\"></b> Kalkulita de <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}", + "TX_PUBKEY": "<b class=\"ion-card\"></b> Spezoj koncernantaj <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" + } + }, + "ERROR": { + "SEARCH_BLOCKS_FAILED": "Eraro dum la serĉado de la blokoj." + } + }, + "GROUP": { + "GENERAL_DIVIDER": "Äœeneralaj informoj", + "LOCATION_DIVIDER": "Adreso", + "SOCIAL_NETWORKS_DIVIDER": "Sociaj retoj kaj retejo", + "TECHNICAL_DIVIDER": "Teknikaj informoj", + "CREATED_TIME": "Kreita {{creationTime|formatFromNow}}", + "NOTIFICATIONS": { + "TITLE": "Invitoj" + }, + "LOOKUP": { + "TITLE": "Grupoj", + "SEARCH_HELP": "Nomo de grupo, vortoj, loko, ktp.", + "LAST_RESULTS_LIST": "Novaj grupoj:", + "OPEN_RESULTS_LIST": "Malfermitaj grupoj:", + "MANAGED_RESULTS_LIST": "Fermitaj grupoj:", + "BTN_LAST": "Novaj grupoj", + "BTN_NEW": "Mi aldonas grupon" + }, + "TYPE": { + "TITLE": "Nova grupo", + "SELECT_TYPE": "Tipo de grupo:", + "OPEN_GROUP": "Malfermita grupo", + "OPEN_GROUP_HELP": "Malfermita grupo estas alirebla de iu ajn membro de la mono.", + "MANAGED_GROUP": "Administrita grupo", + "MANAGED_GROUP_HELP": "Administrita grupo estas mastrumata de administrantoj kaj moderigantoj, kiuj povas akcepti, rifuzi aÅ eksigi membron.", + "ENUM": { + "OPEN": "Malfermita grupo", + "MANAGED": "Administrita grupo" + } + }, + "VIEW": { + "POPOVER_SHARE_TITLE": "{{title}}", + "MENU_TITLE": "Kromaĵoj", + "REMOVE_CONFIRMATION" : "Ĉu vi certas, ke vi volas forigi tiun ĉi grupon?<br/><br/>Tiu ago estas neinversigebla." + }, + "EDIT": { + "TITLE": "Grupo", + "TITLE_NEW": "Nova grupo", + "RECORD_TITLE": "Titolo", + "RECORD_TITLE_HELP": "Titolo", + "RECORD_DESCRIPTION": "Priskribo", + "RECORD_DESCRIPTION_HELP": "Priskribo" + }, + "ERROR": { + "SEARCH_GROUPS_FAILED": "Malsukceso por traserĉi grupojn", + "REMOVE_RECORD_FAILED": "Malsukceso por forigi la grupon" + }, + "INFO": { + "RECORD_REMOVED" : "Grupo forigita" + } + }, + "REGISTRY": { + "CATEGORY": "Ĉefa agado", + "GENERAL_DIVIDER": "Äœeneralaj informoj", + "LOCATION_DIVIDER": "Adreso", + "SOCIAL_NETWORKS_DIVIDER": "Sociaj retoj kaj retejo", + "TECHNICAL_DIVIDER": "Teknikaj informoj", + "BTN_SHOW_WOT": "Personoj", + "BTN_SHOW_WOT_HELP": "Traserĉi personojn", + "BTN_SHOW_PAGES": "PaÄoj", + "BTN_SHOW_PAGES_HELP": "Traserĉi paÄojn", + "BTN_NEW": "Krei paÄon", + "MY_PAGES": "Miaj paÄoj", + "NO_PAGE": "Neniu paÄo", + "SEARCH": { + "TITLE": "PaÄoj", + "SEARCH_HELP": "Kio, Kiu: restoracio, Ĉe Marcelo, ...", + "BTN_ADD": "Nova", + "BTN_LAST_RECORDS": "FreÅdataj paÄoj", + "BTN_ADVANCED_SEARCH": "Sperta serĉado", + "BTN_OPTIONS": "Sperta serĉado", + "TYPE": "Tipo de paÄo", + "LOCATION_HELP": "Kie: PoÅto-kodo, Urbo", + "RESULTS": "Rezultoj", + "RESULT_COUNT_LOCATION": "{{count}} rezulto{{count>0?'j':''}}, proksime de {{location}}", + "RESULT_COUNT": "{{count}} rezulto{{count>0?'j':''}}", + "LAST_RECORDS": "FreÅdataj paÄoj", + "LAST_RECORD_COUNT_LOCATION": "{{count}} paÄo{{count>0?'j':''}} freÅdata{{count>0?'j':''}}, proksime de {{location}}", + "LAST_RECORD_COUNT": "{{count}} paÄo{{count>0?'j':''}} freÅdata{{count>0?'j':''}}", + "POPOVER_FILTERS": { + "BTN_ADVANCED_SEARCH": "Spertaj kromaĵoj?" + } + }, + "VIEW": { + "TITLE": "Adresaro", + "CATEGORY": "Ĉefa agado:", + "LOCATION": "Adreso:", + "MENU_TITLE": "Kromaĵoj", + "POPOVER_SHARE_TITLE": "{{title}}", + "REMOVE_CONFIRMATION" : "Ĉu vi certas, ke vi volas forigi tiun ĉi paÄon?<br/><br/>Tiu ago estas neinversigebla." + }, + "TYPE": { + "TITLE": "Tipoj", + "SELECT_TYPE": "Tipo de paÄo:", + "ENUM": { + "SHOP": "Loka komerco", + "COMPANY": "Entrepreno", + "ASSOCIATION": "Asocio", + "INSTITUTION": "Institucio" + } + }, + "EDIT": { + "TITLE": "Redaktado", + "TITLE_NEW": "Nova paÄo", + "RECORD_TYPE":"Tipo de paÄo", + "RECORD_TITLE": "Nomo", + "RECORD_TITLE_HELP": "Nomo", + "RECORD_DESCRIPTION": "Priskribo", + "RECORD_DESCRIPTION_HELP": "Priskribo de la agado", + "RECORD_ADDRESS": "Strato", + "RECORD_ADDRESS_HELP": "Strato, konstruaĵo...", + "RECORD_CITY": "Urbo", + "RECORD_CITY_HELP": "Urbo", + "RECORD_SOCIAL_NETWORKS": "Sociaj retoj kaj retejo", + "RECORD_PUBKEY": "Publika Ålosilo", + "RECORD_PUBKEY_HELP": "Publika Ålosilo por ricevi la pagojn" + }, + "WALLET": { + "REGISTRY_DIVIDER": "PaÄoj", + "REGISTRY_HELP": "La paÄoj listigas agadojn, kiuj akceptas la liberan monon aÅ helpas Äin: komercoj, entreprenoj, asocioj, institucioj." + }, + "ERROR": { + "LOAD_CATEGORY_FAILED": "Malsukceso por ÅarÄi la liston de la agadoj", + "LOAD_RECORD_FAILED": "Eraro dum la ÅarÄado de la paÄo", + "LOOKUP_RECORDS_FAILED": "Eraro dum la serĉado", + "REMOVE_RECORD_FAILED": "Malsukceso por forigi la paÄon", + "SAVE_RECORD_FAILED": "Eraro dum la konservado", + "RECORD_NOT_EXISTS": "PaÄo neekzistanta", + "GEO_LOCATION_NOT_FOUND": "Urbo aÅ poÅto-kodo ne trovita" + }, + "INFO": { + "RECORD_REMOVED" : "PaÄo forigita", + "RECORD_SAVED": "PaÄo konservita" + } + }, + "PROFILE": { + "PROFILE_DIVIDER": "Profilo Cesium+", + "PROFILE_DIVIDER_HELP": "Temas pri kromaj datenoj, stokitaj ekster la mon-reto.", + "NO_PROFILE_DEFINED": "Neniu profilo tajpita", + "BTN_ADD": "Tajpi mian profilon", + "BTN_EDIT": "Redakti mian profilon", + "BTN_DELETE": "Forigi mian profilon", + "BTN_REORDER": "Reordigi", + "UID": "PseÅdonimo", + "TITLE": "Familia nomo, Persona nomo", + "TITLE_HELP": "Familia nomo, Persona nomo", + "DESCRIPTION": "Pri mi", + "DESCRIPTION_HELP": "Pri mi...", + "SOCIAL_HELP": "http://...", + "GENERAL_DIVIDER": "Äœeneralaj informoj", + "SOCIAL_NETWORKS_DIVIDER": "Sociaj retoj, retejoj", + "TECHNICAL_DIVIDER": "Teknikaj informoj", + "MODAL_AVATAR": { + "TITLE": "Profil-foto", + "SELECT_FILE_HELP": "Bonvolu <b>elekti bildo-dosieron</b>, alklakante la ĉi-suban butonon:", + "BTN_SELECT_FILE": "Elekti foton", + "RESIZE_HELP": "<b>Rekadri la bildon</b>, laÅbezone. Pluigi klakon sur la bildo ebligas movi Äin. Alklaku la zonon malsupre maldekstre por zomi.", + "RESULT_HELP": "<b>Jen la rezulto</b> tiel videbla ĉe via profilo:" + }, + "CONFIRM": { + "DELETE": "Ĉu vi certas, ke vi volas <b>forigi vian profilon Cesium+ ?</b><br/><br/>Tiu ago estas neinversigebla." + }, + "ERROR": { + "REMOVE_PROFILE_FAILED": "Malsukceso por forigi la profilon", + "LOAD_PROFILE_FAILED": "Malsukceso por ÅarÄi la profilon de la uzanto.", + "SAVE_PROFILE_FAILED": "Eraro dum la konservado", + "INVALID_SOCIAL_NETWORK_FORMAT": "Strukturo ne rekonata: bonvolu tajpi validan adreson.<br/><br/>Ezemploj:<ul><li>- Facebook-paÄo (https://www.facebook.com/uzanto)</li><li>- RetpaÄo (http://www.miaretejo.net)</li><li>- Retadreso (joe@dalton.com)</li></ul>", + "IMAGE_RESIZE_FAILED": "Eraro dum la reformatigo de la bildo" + }, + "INFO": { + "PROFILE_REMOVED": "Profilo forigita", + "PROFILE_SAVED": "Profilo konservita" + }, + "HELP": { + "WARNING_PUBLIC_DATA": "La informoj afiÅitaj en via profilo <b>estas publikaj</b>: videblaj inkluzive de la personoj <b>ne konektitaj</b>.<br/>{{'PROFILE.PROFILE_DIVIDER_HELP'|translate}}" + } + }, + "LOCATION": { + "BTN_GEOLOC_ADDRESS": "Trovi mian adreson surmape", + "USE_GEO_POINT": "Aperi sur la mapoj {{'COMMON.APP_NAME'|translate}}?", + "LOADING_LOCATION": "Serĉado de la adreso...", + "LOCATION_DIVIDER": "Adreso", + "ADDRESS": "Strato", + "ADDRESS_HELP": "Strato, adres-aldonaĵo...", + "CITY": "Urbo", + "CITY_HELP": "PoÅto-kodo, Urbo, Lando", + "DISTANCE": "Maksimuma distanco ĉirkaÅ la urbo", + "DISTANCE_UNIT": "km", + "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", + "SEARCH_HELP": "PoÅto-kodo, Urbo", + "PROFILE_POSITION": "Loko de la profilo", + "MODAL": { + "TITLE": "Serĉado de la adreso", + "SEARCH_HELP": "Urbo, PoÅto-kodo, Lando", + "ALTERNATIVE_RESULT_DIVIDER": "Alternativaj rezultoj por <b>{{address}}</b>:", + "POSITION": "Lat/Lon: {{lat}}/{{lon}}" + }, + "ERROR": { + "CITY_REQUIRED_IF_STREET": "Deviga kampo (ĉar strato estas tajpita)", + "REQUIRED_FOR_LOCATION": "Deviga kampo por aperi sur la mapo", + "INVALID_FOR_LOCATION": "Adreso nekonata", + "GEO_LOCATION_FAILED": "Neeblas ricevi vian lokiÄon. Bonvolu uzi la serĉo-butonon.", + "ADDRESS_LOCATION_FAILED": "Neeblas ricevi la lokon per la adreso" + } + }, + "SUBSCRIPTION": { + "SUBSCRIPTION_DIVIDER": "Retaj servoj", + "SUBSCRIPTION_DIVIDER_HELP": "La retaj servoj proponas pliajn nedevigajn servojn, delegitajn al aliulo.", + "BTN_ADD": "Aldoni servon", + "BTN_EDIT": "Mastrumi miajn servojn", + "NO_SUBSCRIPTION": "Neniu servo uzata", + "SUBSCRIPTION_COUNT": "Servoj / Abonoj", + "EDIT": { + "TITLE": "Retaj servoj", + "HELP_TEXT": "Mastrumu ĉi tie viajn abonojn kaj aliajn retajn servojn", + "PROVIDER": "Provizanto:" + }, + "TYPE": { + "ENUM": { + "EMAIL": "Ricevi la avizojn per retmesaÄo" + } + }, + "CONFIRM": { + "DELETE_SUBSCRIPTION": "Ĉu vi certas, ke vi volas <b>forigi tiun abonon</b>?" + }, + "ERROR": { + "LOAD_SUBSCRIPTIONS_FAILED": "Eraro dum la ÅarÄo de la retaj servoj", + "ADD_SUBSCRIPTION_FAILED": "Malsukceso por sendi la abonon", + "UPDATE_SUBSCRIPTION_FAILED": "Malsukceso por Äisdatigi la abonon", + "DELETE_SUBSCRIPTION_FAILED": "Eraro dum la forigo de la abono" + }, + "MODAL_EMAIL": { + "TITLE" : "Avizo per retmesaÄo", + "HELP" : "Plenigu tiun ĉi formularon por <b>esti avizita per retmesaÄo</b> pri la okazaĵoj ĉe via konto.<br/>Via retadreso estos ĉifrita por esti videbla nur de la servo-provizanto.", + "EMAIL_LABEL" : "Via retadreso:", + "EMAIL_HELP": "johano.stelaro@esperanto.org", + "FREQUENCY_LABEL": "Periodo de la avizoj:", + "FREQUENCY_DAILY": "Ĉiutaga", + "FREQUENCY_WEEKLY": "Ĉiusemajna", + "PROVIDER": "Servo-provizanto:" + } + }, + "DOCUMENT": { + "HASH": "Haketo: ", + "LOOKUP": { + "TITLE": "Serĉado de dokumentoj", + "BTN_ACTIONS": "Agoj", + "SEARCH_HELP": "Sendanto:AAA*, tempo:1508406169", + "LAST_DOCUMENTS": "Lastaj dokumentoj", + "SHOW_QUERY": "Vidi la informpeton", + "HIDE_QUERY": "KaÅi la informpeton", + "HEADER_TIME": "Dato/Horo", + "HEADER_ISSUER": "Sendanto", + "HEADER_RECIPIENT": "Ricevonto", + "READ": "Legita", + "BTN_REMOVE": "Forigi tiun ĉi dokumenton", + "POPOVER_ACTIONS": { + "TITLE": "Agoj", + "REMOVE_ALL": "Forigi tiujn ĉi dokumentojn..." + } + }, + "INFO": { + "REMOVED": "Dokumento forigita" + }, + "CONFIRM": { + "REMOVE": "Ĉu vi certas, ke vi volas <b>forigi tiun ĉi dokumenton</b>?", + "REMOVE_ALL": "Ĉu vi certas, ke vi volas <b>forigi tiujn ĉi dokumentojn</b>?" + }, + "ERROR": { + "LOAD_DOCUMENTS_FAILED": "Eraro dum la serĉado de dokumentoj", + "REMOVE_FAILED": "Eraro dum la forigo de la dokumento", + "REMOVE_ALL_FAILED": "Eraro dum la forigo de la dokumentoj" + } + }, + "ES_SETTINGS": { + "PLUGIN_NAME": "Cesium+", + "PLUGIN_NAME_HELP": "Profiloj, avizoj, privataj mesaÄoj", + "ENABLE_TOGGLE": "Aktivigi la krom-programon?", + "ENABLE_REMOTE_STORAGE": "Aktivigi la foran stokadon?", + "ENABLE_REMOTE_STORAGE_HELP": "Ebligas stoki (ĉifrite) viajn parametrojn ĉe la nodoj Cesium+", + "ENABLE_MESSAGE_TOGGLE": "Aktivigi la privatajn mesaÄojn?", + "PEER": "Adreso de la daten-nodo", + "POPUP_PEER": { + "TITLE" : "Daten-nodo", + "HELP" : "Tajpu la adreson de la nodo, kiun vi volas uzi:", + "PEER_HELP": "servo.domajno.com:port" + }, + "NOTIFICATIONS": { + "DIVIDER": "Avizoj", + "HELP_TEXT": "Aktivigu la avizo-tipojn, kiujn vi deziras ricevi:", + "ENABLE_TX_SENT": "Avizi pri la <b>senditaj pagoj</b>?", + "ENABLE_TX_RECEIVED": "Avizi pri la <b>ricevitaj pagoj</b>?", + "ENABLE_CERT_SENT": "Avizi pri la <b>senditaj atestaĵoj</b>?", + "ENABLE_CERT_RECEIVED": "Avizi pri <b>la ricevitaj atestaĵoj</b>?", + "ENABLE_HTML5_NOTIFICATION": "Anonci ĉiun novan avizon?", + "ENABLE_HTML5_NOTIFICATION_HELP": "Malfermas fenestreton por ĉiu nova avizo." + }, + "CONFIRM": { + "ASK_ENABLE_TITLE": "Kromaj funkcioj", + "ASK_ENABLE": "La krom-programo Cesium+ estas <b>malaktivigita</b> ĉe viaj parametroj, kio senaktivigas la funkciojn: <ul><li> <b><i class=\"icon ion-person\"></i> Profiloj Cesium+</b>;<li> <b><i class=\"icon ion-android-notifications\"></i> Avizoj</b>;<li> <b><i class=\"icon ion-email\"></i> Privataj mesaÄoj</b>.<li> <b><i class=\"icon ion-location\"></i> Mapoj, ktp.</b>.</ul><br/><b>Ĉu vi deziras reaktivigi</b> la krom-programon?" + } + }, + "ES_WALLET": { + "ERROR": { + "RECIPIENT_IS_MANDATORY": "Adresito estas deviga por la ĉifrado." + } + }, + "EVENT": { + "NODE_STARTED": "Via nodo ES API <b>{{params[0]}}</b> ekis", + "NODE_BMA_DOWN": "La nodo <b>{{params[0]}}:{{params[1]}}</b> (uzata de via nodo ES API) estas <b>neatingebla</b>.", + "NODE_BMA_UP": "La nodo <b>{{params[0]}}:{{params[1]}}</b> estas denove alirebla.", + "MEMBER_JOIN": "Vi estas nun <b>membro</b> de la mono <b>{{params[0]}}</b>!", + "MEMBER_LEAVE": "Vi <b>ne plu estas membro</b> de la mono <b>{{params[0]}}</b>!", + "MEMBER_EXCLUDE": "Vi <b>ne plu estas membro</b> de la mono <b>{{params[0]}}</b>, pro ne revalidiÄo aÅ pro manko da atestaĵoj.", + "MEMBER_REVOKE": "La nuligo de via konto efektiviÄis. Äœi ne plu povos esti membro-konto de la mono <b>{{params[0]}}</b>.", + "MEMBER_ACTIVE": "La revalidiÄo de via aliÄo al la mono <b>{{params[0]}}</b> estis <b>ricevita</b>.", + "TX_SENT": "Via <b>pago</b> al <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\" ><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> efektiviÄis.", + "TX_SENT_MULTI": "Via <b>pago</b> al <b>{{params[1]}}</b> efektiviÄis.", + "TX_RECEIVED": "Vi <b>ricevis pagon</b> de <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span>.", + "TX_RECEIVED_MULTI": "Vi <b>ricevis pagon</b> de <b>{{params[1]}}</b>.", + "CERT_SENT": "Via <b>atestado</b> al <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\" ><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> efektiviÄis.", + "CERT_RECEIVED": "Vi <b>ricevis atestaĵon</b> de <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span>.", + "REGISTRY": { + "NEW_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> komentis vian anoncon: <b>{{params[2]}}</b>", + "UPDATE_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> modifis sian komenton pri via anonco: <b>{{params[2]}}</b>", + "NEW_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> respondis al via komento pri la anonco: <b>{{params[2]}}</b>", + "UPDATE_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> modifis sian respondon al via komento pri la anonco: <b>{{params[2]}}</b>" + } + }, + "CONFIRM": { + "ES_USE_FALLBACK_NODE": "Daten-nodo <b>{{old}}</b> neatingebla aÅ adreso nevalida.<br/><br/>Ĉu vi volas provizore uzi la daten-nodon <b>{{new}}</b> ?" + }, + "ERROR": { + "ES_CONNECTION_ERROR": "Daten-nodo <b>{{server}}</b> neatingebla aÅ adreso nevalida.<br/><br/>Cesium daÅrigos funkcii, <b>sen la krom-programo Cesium+</b> (uzanto-profiloj, privataj mesaÄoj, mapoj kaj grafikoj)<br/><br/>Kontrolu vian ret-konekton, aÅ ÅanÄu daten-nodon ĉe la <a class=\"positive\" ng-click=\"doQuickFix('settings')\">parametroj de la krom-programo</a>.", + "ES_MAX_UPLOAD_BODY_SIZE": "La kvanto de datenoj sendotaj superas la limon fiksitan de la servilo.<br/>Bonvolu reprovi post, ekzemple, forigo de fotoj." + } +} +); + $translateProvider.translations("es-ES", { "COMMON": { "CATEGORY": "CategorÃa", @@ -1026,7 +1601,7 @@ $translateProvider.translations("es-ES", { "ORGANIZATION_ACCOUNT_HELP": "Si representa una empresa, una asociación, etc.<br/>Ningún dividendo universal será creÃdo por esta cuenta." }, "EVENT": { - "MEMBER_WITHOUT_PROFILE": "Para obtener sus certificaciónes más rapidamente, completa <a ui-sref=\"app.user_edit_profile\">su perfil usuario</a>. Los miembros concederán más fácilmente su confianza a una identidad verificable." + "MEMBER_WITHOUT_PROFILE": "Para obtener sus certificaciónes más rapidamente, completa <a ui-sref=\"app.edit_profile\">su perfil usuario</a>. Los miembros concederán más fácilmente su confianza a una identidad verificable." }, "ERROR": { "WS_CONNECTION_FAILED": "Cesium no puede recibir las notificaciónes, a causa de un error técnico (conexión al nodo de datos Cesium+).<br/><br/>Si el problema persiste, por favor <b>elige un otro nodo de datos</b> en las configuraciónes Cesium+." @@ -1198,7 +1773,7 @@ $translateProvider.translations("es-ES", { "TX_SEARCH_FILTER": { "MEMBER_FLOWS": "Entradas/salidas de miembros", "EXISTING_TRANSACTION": "Con transacciones", - "PERIOD": "<b class=\"ion-clock\"></b> Entre el <b class=\"gray\">{{params[1]|formatDateShort}}</b> ({{params[1]|formatTime}}) y el <b class=\"gray\">{{params[2]|formatDateShort}}</b> ({{params[2]|formatTime}})", + "PERIOD": "<b class=\"ion-clock\"></b> Entre el <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) y el <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", "ISSUER": "<b class=\"ion-android-desktop\"></b> Calculado por <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}", "TX_PUBKEY": "<b class=\"ion-card\"></b> Transacciones que implican <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" } @@ -1397,6 +1972,7 @@ $translateProvider.translations("es-ES", { "DISTANCE_UNIT": "km", "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", "SEARCH_HELP": "Ciudad, PaÃs", + "PROFILE_POSITION": "Posición del perfil", "MODAL": { "TITLE": "Búsqueda de dirección", "SEARCH_HELP": "Ciudad, PaÃs", @@ -1404,6 +1980,7 @@ $translateProvider.translations("es-ES", { "POSITION": "Latitud/Longitud : {{lat}} / {{lon}}" }, "ERROR": { + "CITY_REQUIRED_IF_STREET": "Requerido si una calle ha sido llenada", "REQUIRED_FOR_LOCATION": "Campo obligatorio para aparecer en el mapa", "INVALID_FOR_LOCATION": "Dirección desconocida", "GEO_LOCATION_FAILED": "No se puede recuperar su ubicación Por favor usa el botón de búsqueda.", @@ -1521,6 +2098,10 @@ $translateProvider.translations("fr-FR", { "BTN_PICTURE_FAVORISE": "Principale", "BTN_PICTURE_ROTATE": "Tourner", "BTN_ADD_PICTURE": "Ajouter une photo", + "NOTIFICATION": { + "TITLE": "Nouvelle notification | {{'COMMON.APP_NAME'|translate}}", + "HAS_UNREAD": "Vous avez {{count}} notification{{count>0?'s':''}} non lue{{count>0?'s':''}}" + }, "NOTIFICATIONS": { "TITLE": "Notifications", "MARK_ALL_AS_READ": "Tout marquer comme lu", @@ -1542,7 +2123,7 @@ $translateProvider.translations("fr-FR", { "ORGANIZATION_ACCOUNT_HELP": "Si vous représentez une entreprise, une association, etc.<br/>Aucun dividende universel ne sera créé par ce compte." }, "EVENT": { - "MEMBER_WITHOUT_PROFILE": "Pour obtenir vos certifications plus rapidement, completez <a ui-sref=\"app.user_edit_profile\">votre profil utilisateur</a>. Les membres accorderont plus facilement leur confiance à une identité vérifiable." + "MEMBER_WITHOUT_PROFILE": "Vous pouvez <a ui-sref=\"app.edit_profile\">saisir votre profil Cesium+</a> (optionnel) pour offrir une meilleure visibilité de votre compte. Ce profil sera stocké dans <b>un annuaire indépendant</b> de la monnaie, mais décentralisé." }, "ERROR": { "WS_CONNECTION_FAILED": "Cesium ne peut pas recevoir les notifications, à cause d'une erreur technique (connexion au noeud de données Cesium+).<br/><br/>Si le problème persiste, veuillez <b>choisir un autre noeud de données</b> dans les paramètres Cesium+." @@ -1566,9 +2147,9 @@ $translateProvider.translations("fr-FR", { "DIVIDER_GROUP": "Groupes" }, "CONFIRM": { - "SUGGEST_CERTIFICATIONS": "Etes-vous sûr de vouloir <b>envoyer ces suggestions de certification</b> ?", - "ASK_CERTIFICATION": "Etes-vous sûr de vouloir <b>envoyer une demande de certification</b> ?", - "ASK_CERTIFICATIONS": "Etes-vous sûr de vouloir <b>envoyer une demande de certification</b> à ces personnes ?" + "SUGGEST_CERTIFICATIONS": "Êtes-vous sûr de vouloir <b>envoyer ces suggestions de certification</b> ?", + "ASK_CERTIFICATION": "Êtes-vous sûr de vouloir <b>envoyer une demande de certification</b> ?", + "ASK_CERTIFICATIONS": "Êtes-vous sûr de vouloir <b>envoyer une demande de certification</b> à ces personnes ?" } }, "INVITATION": { @@ -1598,14 +2179,14 @@ $translateProvider.translations("fr-FR", { "SUGGESTION_IDENTITIES_MODAL_HELP": "Veuillez choisir vos suggestions :" }, "CONFIRM": { - "DELETE_ALL_CONFIRMATION": "La suppression des invitations est une <b>opération irréversible</b>.<br/><br/><b>Etes-vous sûr</b> de vouloir continuer ?", - "SEND_INVITATIONS_TO_CERTIFY": "Etes-vous sûr de vouloir <b>envoyer cette invitation à certfier</b> ?" + "DELETE_ALL_CONFIRMATION": "La suppression des invitations est une <b>opération irréversible</b>.<br/><br/><b>Êtes-vous sûr</b> de vouloir continuer ?", + "SEND_INVITATIONS_TO_CERTIFY": "Êtes-vous sûr de vouloir <b>envoyer cette invitation à certifier</b> ?" }, "INFO": { "INVITATION_SENT": "Invitation envoyée" }, "ERROR": { - "LOAD_INVITATIONS_FAILED": "Echec du chargement des invitations", + "LOAD_INVITATIONS_FAILED": "Échec du chargement des invitations", "REMOVE_INVITATION_FAILED": "Erreur lors de la suppression de l'invitation", "REMOVE_ALL_INVITATIONS_FAILED": "Erreur lors de la suppression des invitations", "SEND_INVITATION_FAILED": "Erreur lors de l'envoi de l'invitation", @@ -1677,12 +2258,12 @@ $translateProvider.translations("fr-FR", { "CONFIRM": { "REMOVE": "Êtes-vous sûr de vouloir <b>supprimer ce message</b> ?<br/><br/>Cette opération est irréversible.", "REMOVE_ALL" : "Êtes-vous sûr de vouloir <b>supprimer tous les messages</b> ?<br/><br/>Cette opération est irréversible.", - "MARK_ALL_AS_READ": "Êtes-vous sûr de vouloir <b>marquer tous les messages comme lu</b> ?", + "MARK_ALL_AS_READ": "Êtes-vous sûr de vouloir <b>marquer tous les messages comme lus</b> ?", "USER_HAS_NO_PROFILE": "Cette identité n'a aucun profil Cesium+. Il se peut qu'elle n'utilise pas l'extension Cesium+, et <b>ne consultera donc pas votre message</b>.<br/><br/>Êtes-vous sûr de vouloir <b>continuer</b> malgré tout ?" }, "INFO": { "MESSAGE_REMOVED": "Message supprimé", - "All_MESSAGE_REMOVED": "Tous les messages ont été supprimé", + "All_MESSAGE_REMOVED": "Tous les messages ont été supprimés", "MESSAGE_SENT": "Message envoyé" }, "ERROR": { @@ -1697,7 +2278,7 @@ $translateProvider.translations("fr-FR", { "MARK_AS_READ_FAILED": "Impossible de marquer le message comme 'lu'.", "LOAD_NOTIFICATIONS_FAILED": "Erreur lors de la récupération des notifications de messages.", "REMOVE_All_MESSAGES_FAILED": "Erreur lors de la suppression de tous les messages.", - "MARK_ALL_AS_READ_FAILED": "Erreur lors du marquage des message comme lu.", + "MARK_ALL_AS_READ_FAILED": "Erreur lors du marquage des messages comme lus.", "RECIPIENT_IS_MANDATORY": "Le destinataire est obligatoire." } }, @@ -1714,7 +2295,7 @@ $translateProvider.translations("fr-FR", { "TX_SEARCH_FILTER": { "MEMBER_FLOWS": "<b class=\"ion-person\"></b> Entrées/sorties de membres", "EXISTING_TRANSACTION": "<b class=\"ion-card\"></b> Avec transactions", - "PERIOD": "<b class=\"ion-clock\"></b> Entre <b class=\"gray\">{{params[1]|formatDateShort}}</b> ({{params[1]|formatTime}}) et <b class=\"gray\">{{params[2]|formatDateShort}}</b> ({{params[2]|formatTime}})", + "PERIOD": "<b class=\"ion-clock\"></b> Entre <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) et <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", "ISSUER": "<b class=\"ion-android-desktop\"></b> Calculé par <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}", "TX_PUBKEY": "<b class=\"ion-card\"></b> Transactions concernant <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" } @@ -1728,7 +2309,7 @@ $translateProvider.translations("fr-FR", { "LOCATION_DIVIDER": "Adresse", "SOCIAL_NETWORKS_DIVIDER": "Réseaux sociaux et site web", "TECHNICAL_DIVIDER": "Informations techniques", - "CREATED_TIME": "Crée {{creationTime|formatFromNow}}", + "CREATED_TIME": "Créé {{creationTime|formatFromNow}}", "NOTIFICATIONS": { "TITLE": "Invitations" }, @@ -1747,7 +2328,7 @@ $translateProvider.translations("fr-FR", { "OPEN_GROUP": "Groupe ouvert", "OPEN_GROUP_HELP": "Un groupe ouvert est accessible par n'importe quel membre de la monnaie.", "MANAGED_GROUP": "Groupe administré", - "MANAGED_GROUP_HELP": "un groupe administré est gérer par des administrateurs et des modérateurs, qui peuvent accepter, refuser ou exclure un membre en son sein.", + "MANAGED_GROUP_HELP": "un groupe administré est géré par des administrateurs et des modérateurs, qui peuvent accepter, refuser ou exclure un membre en son sein.", "ENUM": { "OPEN": "Groupe ouvert", "MANAGED": "Groupe administré" @@ -1767,7 +2348,7 @@ $translateProvider.translations("fr-FR", { "RECORD_DESCRIPTION_HELP": "Description" }, "ERROR": { - "SEARCH_GROUPS_FAILED": "Echec de la recherche de groupes", + "SEARCH_GROUPS_FAILED": "Échec de la recherche de groupes", "REMOVE_RECORD_FAILED": "Erreur de la suppression du groupe" }, "INFO": { @@ -1795,7 +2376,7 @@ $translateProvider.translations("fr-FR", { "BTN_ADVANCED_SEARCH": "Recherche avancée", "BTN_OPTIONS": "Recherche avancée", "TYPE": "Type de page", - "LOCATION_HELP": "Où : Ville, Code postal", + "LOCATION_HELP": "Où : Code postal, Ville", "RESULTS": "Résultats", "RESULT_COUNT_LOCATION": "{{count}} résultat{{count>0?'s':''}}, près de {{location}}", "RESULT_COUNT": "{{count}} résultat{{count>0?'s':''}}", @@ -1833,7 +2414,7 @@ $translateProvider.translations("fr-FR", { "RECORD_DESCRIPTION": "Description", "RECORD_DESCRIPTION_HELP": "Description de l'activité", "RECORD_ADDRESS": "Rue", - "RECORD_ADDRESS_HELP": "Rue, batiment...", + "RECORD_ADDRESS_HELP": "Rue, bâtiment...", "RECORD_CITY": "Ville", "RECORD_CITY_HELP": "Ville", "RECORD_SOCIAL_NETWORKS": "Réseaux sociaux et site web", @@ -1847,7 +2428,7 @@ $translateProvider.translations("fr-FR", { "ERROR": { "LOAD_CATEGORY_FAILED": "Erreur de chargement de la liste des activités", "LOAD_RECORD_FAILED": "Erreur lors du chargement de la page", - "LOOKUP_RECORDS_FAILED": "Erreur lors de l'execution de la recherche.", + "LOOKUP_RECORDS_FAILED": "Erreur lors de l'exécution de la recherche", "REMOVE_RECORD_FAILED": "Erreur de la suppression de la page", "SAVE_RECORD_FAILED": "Erreur lors de la sauvegarde", "RECORD_NOT_EXISTS": "Page inexistante", @@ -1883,11 +2464,11 @@ $translateProvider.translations("fr-FR", { "RESULT_HELP": "<b>Voici le résultat</b> tel que visible sur votre profil :" }, "CONFIRM": { - "DELETE": "Etes-vous sur de vouloir <b>supprimer votre profif Cesium+ ?</b><br/><br/>Cette opération est irréversible." + "DELETE": "Êtes-vous sûr de vouloir <b>supprimer votre profil Cesium+ ?</b><br/><br/>Cette opération est irréversible." }, "ERROR": { "REMOVE_PROFILE_FAILED": "Erreur de suppression du profil", - "LOAD_PROFILE_FAILED": "Erreur de chargement du profil utilisateur.", + "LOAD_PROFILE_FAILED": "Erreur de chargement du profil utilisateur", "SAVE_PROFILE_FAILED": "Erreur lors de la sauvegarde", "INVALID_SOCIAL_NETWORK_FORMAT": "Format non pris en compte : veuillez indiquer une adresse valide.<br/><br/>Exemples :<ul><li>- Une page Facebook (https://www.facebook.com/user)</li><li>- Une page web (http://www.monsite.fr)</li><li>- Une adresse email (joe@dalton.com)</li></ul>", "IMAGE_RESIZE_FAILED": "Erreur lors du redimensionnement de l'image" @@ -1908,11 +2489,12 @@ $translateProvider.translations("fr-FR", { "ADDRESS": "Rue", "ADDRESS_HELP": "Rue, complément d'adresse...", "CITY": "Ville", - "CITY_HELP": "Ville, Pays", + "CITY_HELP": "Code postal, Ville, Pays", "DISTANCE": "Distance maximale autour de la ville", "DISTANCE_UNIT": "km", "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", - "SEARCH_HELP": "Ville, Code postal", + "SEARCH_HELP": "Code postal, Ville", + "PROFILE_POSITION": "Position du profil", "MODAL": { "TITLE": "Recherche de l'adresse", "SEARCH_HELP": "Ville, Code postal, Pays", @@ -1920,6 +2502,7 @@ $translateProvider.translations("fr-FR", { "POSITION": "Lat/Lon : {{lat}}/{{lon}}" }, "ERROR": { + "CITY_REQUIRED_IF_STREET": "Champ obligatoire (car une rue est saisie)", "REQUIRED_FOR_LOCATION": "Champ obligatoire pour apparaître sur la carte", "INVALID_FOR_LOCATION": "Adresse inconnue", "GEO_LOCATION_FAILED": "Impossible de récupérer votre position. Veuillez utiliser le bouton de recherche.", @@ -1934,8 +2517,8 @@ $translateProvider.translations("fr-FR", { "NO_SUBSCRIPTION": "Aucun service utilisé", "SUBSCRIPTION_COUNT": "Services / Abonnements", "EDIT": { - "TITLE": "Services en lignes", - "HELP_TEXT": "Gérer ici vos abonnements et autres services en ligne", + "TITLE": "Services en ligne", + "HELP_TEXT": "Gérez ici vos abonnements et autres services en ligne", "PROVIDER": "Prestataire :" }, "TYPE": { @@ -1944,7 +2527,7 @@ $translateProvider.translations("fr-FR", { } }, "CONFIRM": { - "DELETE_SUBSCRIPTION": "Etes-vous sûr de vouloir <b>supprimer cet abonnement</b> ?" + "DELETE_SUBSCRIPTION": "Êtes-vous sûr de vouloir <b>supprimer cet abonnement</b> ?" }, "ERROR": { "LOAD_SUBSCRIPTIONS_FAILED": "Erreur lors du chargement des services en ligne", @@ -1964,11 +2547,11 @@ $translateProvider.translations("fr-FR", { } }, "DOCUMENT": { - "HASH": "Hash: ", + "HASH": "Hash : ", "LOOKUP": { "TITLE": "Recherche de documents", "BTN_ACTIONS": "Actions", - "SEARCH_HELP": "issuer:AAA*, time:1508406169", + "SEARCH_HELP": "Emetteur:AAA*, temps:1508406169", "LAST_DOCUMENTS": "Derniers documents", "SHOW_QUERY": "Voir la requête", "HIDE_QUERY": "Masquer la requête", @@ -1986,8 +2569,8 @@ $translateProvider.translations("fr-FR", { "REMOVED": "Document supprimé" }, "CONFIRM": { - "REMOVE": "Etes-vous sûr de vouloir <b>supprimer ce document</b> ?", - "REMOVE_ALL": "Etes-vous sûr de vouloir <b>supprimer ces documents</b> ?" + "REMOVE": "Êtes-vous sûr de vouloir <b>supprimer ce document</b> ?", + "REMOVE_ALL": "Êtes-vous sûr de vouloir <b>supprimer ces documents</b> ?" }, "ERROR": { "LOAD_DOCUMENTS_FAILED": "Erreur lors de la recherche de documents", @@ -1999,9 +2582,10 @@ $translateProvider.translations("fr-FR", { "PLUGIN_NAME": "Cesium+", "PLUGIN_NAME_HELP": "Profils, notifications, messages privés", "ENABLE_TOGGLE": "Activer l'extension ?", + "ENABLE_REMOTE_STORAGE": "Activer le stockage distant ?", + "ENABLE_REMOTE_STORAGE_HELP": "Permet de stockage (chiffré) de vos paramètres sur les noeuds Cesium+", "ENABLE_MESSAGE_TOGGLE": "Activer les messages privés ?", - "ENABLE_SETTINGS_TOGGLE": "Activer le stockage distant des paramètres ?", - "PEER": "Addresse du nÅ“ud de données", + "PEER": "Adresse du nÅ“ud de données", "POPUP_PEER": { "TITLE" : "NÅ“ud de données", "HELP" : "Saisissez l'adresse du nÅ“ud que vous voulez utiliser :", @@ -2010,14 +2594,16 @@ $translateProvider.translations("fr-FR", { "NOTIFICATIONS": { "DIVIDER": "Notifications", "HELP_TEXT": "Activez les types de notifications que vous souhaitez recevoir :", - "ENABLE_TX_SENT": "Notifier les <b>paiement émis</b> ?", + "ENABLE_TX_SENT": "Notifier les <b>paiements émis</b> ?", "ENABLE_TX_RECEIVED": "Notifier les <b>paiements reçus</b> ?", "ENABLE_CERT_SENT": "Notifier les <b>certifications émises</b> ?", - "ENABLE_CERT_RECEIVED": "Notifier les <b>certifications reçues</b> ?" + "ENABLE_CERT_RECEIVED": "Notifier les <b>certifications reçues</b> ?", + "ENABLE_HTML5_NOTIFICATION": "Avertir à chaque nouvelle notification ?", + "ENABLE_HTML5_NOTIFICATION_HELP": "Ouvre une petite fenêtre à chaque nouvelle notification." }, "CONFIRM": { "ASK_ENABLE_TITLE": "Fonctionnalités optionnelles", - "ASK_ENABLE": "L'extension Cesium+ est <b>désactivée</b> dans vos paramètres, rendant inactives les fonctionnalités : <ul><li> <b><i class=\"icon ion-person\"></i> Profils Cesium+</b>;<li> <b><i class=\"icon ion-android-notifications\"></i> Notifications</b>;<li> <b><i class=\"icon ion-email\"></i> Messages privés</b>.<li> <b><i class=\"icon ion-location\"></i> Cartes, etc.</b>.</ul><br/><b>Souhaitez-vous la ré-activer</b> l'extension ?" + "ASK_ENABLE": "L'extension Cesium+ est <b>désactivée</b> dans vos paramètres, rendant inactives les fonctionnalités : <ul><li> <b><i class=\"icon ion-person\"></i> Profils Cesium+</b>;<li> <b><i class=\"icon ion-android-notifications\"></i> Notifications</b>;<li> <b><i class=\"icon ion-email\"></i> Messages privés</b>.<li> <b><i class=\"icon ion-location\"></i> Cartes, etc.</b>.</ul><br/><b>Souhaitez-vous ré-activer</b> l'extension ?" } }, "ES_WALLET": { @@ -2030,7 +2616,7 @@ $translateProvider.translations("fr-FR", { "NODE_BMA_DOWN": "Le noeud <b>{{params[0]}}:{{params[1]}}</b> (utilisé par votre noeud ES API) est <b>injoignable</b>.", "NODE_BMA_UP": "Le noeud <b>{{params[0]}}:{{params[1]}}</b> est à nouveau accessible.", "MEMBER_JOIN": "Vous êtes maintenant <b>membre</b> de la monnaie <b>{{params[0]}}</b> !", - "MEMBER_LEAVE": "Vous n'êtes <b>plus membre</b> de la monnaie <b>{{params[0]}}</b>!", + "MEMBER_LEAVE": "Vous n'êtes <b>plus membre</b> de la monnaie <b>{{params[0]}}</b> !", "MEMBER_EXCLUDE": "Vous n'êtes <b>plus membre</b> de la monnaie <b>{{params[0]}}</b>, faute de non renouvellement ou par manque de certifications.", "MEMBER_REVOKE": "La révocation de votre compte a été effectuée. Il ne pourra plus être un compte membre de la monnaie <b>{{params[0]}}</b>.", "MEMBER_ACTIVE": "Votre renouvellement d'adhésion à la monnaie <b>{{params[0]}}</b> a été <b>pris en compte</b>.", @@ -2051,18 +2637,555 @@ $translateProvider.translations("fr-FR", { "ES_USE_FALLBACK_NODE": "NÅ“ud de données <b>{{old}}</b> injoignable ou adresse invalide.<br/><br/>Voulez-vous temporairement utiliser le nÅ“ud de données <b>{{new}}</b> ?" }, "ERROR": { - "ES_CONNECTION_ERROR": "NÅ“ud de données <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Cesium va continuer à fonctionner, <b>sans l'extension Cesium+</b> (profils utilisateur, messages privés, cartes et graphiques)<br/><br/>Vérifiez votre connection Internet, ou changer de nÅ“ud de données dans les <a class=\"positive\" ng-click=\"doQuickFix('settings')\">paramètres de l'extension</a>.", + "ES_CONNECTION_ERROR": "NÅ“ud de données <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Cesium va continuer à fonctionner, <b>sans l'extension Cesium+</b> (profils utilisateur, messages privés, cartes et graphiques)<br/><br/>Vérifiez votre connexion Internet, ou changez de nÅ“ud de données dans les <a class=\"positive\" ng-click=\"doQuickFix('settings')\">paramètres de l'extension</a>.", "ES_MAX_UPLOAD_BODY_SIZE": "Le volume des données à envoyer dépasse la limite fixée par le serveur.<br/>Veuillez ré-essayer après avoir, par exemple, supprimer des photos." } } ); +$translateProvider.translations("it-IT", { + "COMMON": { + "CATEGORY": "Categoria", + "CATEGORIES": "Categorie", + "CATEGORY_SEARCH_HELP": "Ricerca", + "LAST_MODIFICATION_DATE": "Aggiornato il ", + "SUBMIT_BY": "Inviato da", + "BTN_PUBLISH": "Pubblicare", + "BTN_PICTURE_DELETE": "Eliminare", + "BTN_PICTURE_FAVORISE": "Predefinito", + "BTN_PICTURE_ROTATE": "Girare", + "BTN_ADD_PICTURE": "Aggiungere foto", + "NOTIFICATIONS": { + "TITLE": "Notifiche", + "MARK_ALL_AS_READ": "Segna tutte come lette", + "NO_RESULT": "Nessuna notifica", + "SHOW_ALL": "Mostrare tutte", + "LOAD_NOTIFICATIONS_FAILED": "Impossibile caricare le notifiche" + } + }, + "MENU": { + "REGISTRY": "Pagine", + "USER_PROFILE": "Mio profilo", + "MESSAGES": "Messaggi", + "NOTIFICATIONS": "Notifiche", + "INVITATIONS": "Inviti" + }, + "ACCOUNT": { + "NEW": { + "ORGANIZATION_ACCOUNT": "Conto per enti", + "ORGANIZATION_ACCOUNT_HELP": "Se rappresenta un'azienda, un'associazione, etc.<br/>Questo conto non potrà creare il Dividendo Universale." + }, + "EVENT": { + "MEMBER_WITHOUT_PROFILE": "Per ottenere sue certificazioni più velocemente, riempire le informazioni<a ui-sref=\"app.edit_profile\">del suo profilo</a>. I membri della rete si fidano più volontieri di profili verificabili." + }, + "ERROR": { + "WS_CONNECTION_FAILED": "Cesium non può ricevere notifiche a causa di un problema tecnico (di conessione al data node Cesium+).<br/><br/>Se il problema persiste, le chiediamo di <b>scegliere un'altro data node</b> nelle impostazioni di Cesium+." + } + }, + "WOT": { + "BTN_SUGGEST_CERTIFICATIONS_DOTS": "Suggerire delle identità da certificare..", + "BTN_ASK_CERTIFICATIONS_DOTS": "Chiedere una certificazione ai membri...", + "BTN_ASK_CERTIFICATION": "Chiedere una certificazione", + "SUGGEST_CERTIFICATIONS_MODAL": { + "TITLE": "Suggerire delle certificazioni", + "HELP": "Scegliere i suoi suggerimenti, aiuti" + }, + "ASK_CERTIFICATIONS_MODAL": { + "TITLE": "Chiedere delle certificazioni", + "HELP": "Selezionare un ricevente" + }, + "SEARCH": { + "DIVIDER_PROFILE": "Conti", + "DIVIDER_PAGE": "Pagine", + "DIVIDER_GROUP": "Gruppi" + }, + "CONFIRM": { + "SUGGEST_CERTIFICATIONS": "E’ sicuro(a) di voler <b>suggerire queste certificazioni</b> ?", + "ASK_CERTIFICATION": " E’ sicuro(a) di voler <b>chiedere una certificazione</b> ?", + "ASK_CERTIFICATIONS": " E’ sicuro(a) di voler <b>chiedere una certificazione</b> a questi membri ?" + }, + }, + "INVITATION": { + "TITLE": "Invitazioni", + "NO_RESULT": "Nessun invito ricevuto", + "BTN_DELETE_ALL": "Cancellare tutti gli inviti", + "BTN_DELETE": "Cancellare l'invito", + "BTN_NEW_INVITATION": "Nuovo invito", + "ASK_CERTIFICATION": "<a href=\"#/app/wot/{{pubkey}}/{{::uid}}\">{{::name||uid}}</a> ti ha chiesto una certificazione", + "SUGGESTION_CERTIFICATION": "<a href=\"#/app/wot/{{::pubkey}}/{{::uid}}\">{{::name||uid}}</a> è proposto per ricevere una certificazione", + "SUGGESTED_BY": "Suggerimento inviato da by <a class=\"positive\" href=\"#/app/wot/{{::issuer.pubkey}}/{{::issuer.uid}}\">{{::issuer.name||issuer.uid}}</a>", + "NOTIFICATIONS": { + "TITLE": "Inviti" + }, + "LIST": { + "TITLE": "Inviti" + }, + "NEW": { + "TITLE": "Nuovo invito", + "RECIPIENTS": "A", + "RECIPIENTS_HELP": "Riceventi dell'invito", + "RECIPIENTS_MODAL_TITLE": "Riceventi", + "RECIPIENTS_MODAL_HELP": "Scegliere riceventi:", + "SUGGESTION_IDENTITIES": "Suggerimenti di identità da certificare", + "SUGGESTION_IDENTITIES_HELP": "Suggerimenti di certificazioni", + "SUGGESTION_IDENTITIES_MODAL_TITLE": "Suggerimenti", + "SUGGESTION_IDENTITIES_MODAL_HELP": "Scegli tuoi sugerimenti:" + }, + "CONFIRM": { + "DELETE_ALL_CONFIRMATION": "Cancellare degli inviti è <b>una operazione irreversibile</b>.<br/><br/><b>Sei sicuro/a</b> di voler proseguire", + "SEND_INVITATIONS_TO_CERTIFY": "<b>Sei sicuro/a</b> di voler <b>inviare questo suggerimento di certificazione</b> ?" + }, + "INFO": { + "INVITATION_SENT": "Invito inviato" + }, + "ERROR": { + "LOAD_INVITATIONS_FAILED": "Errore nel caricare gli inviti", + "REMOVE_INVITATION_FAILED": "Errore nel cancellare gli inviti", + "REMOVE_ALL_INVITATIONS_FAILED": "Errore nel cancellare inviti", + "SEND_INVITATION_FAILED": "Errore nel invio degli inviti", + "BAD_INVITATION_FORMAT": "<span class=\"assertive\"><i class=\"ion-close-circled\"></i> Invito illegibile (formatto sconosciuto)</span> - inviato da <a ui-sref=\"app.wot_identity({pubkey: '{{::pubkey}}', uid: '{{::uid}}' })\">{{::name||uid}}</a>" + } + }, + "COMMENTS": { + "DIVIDER": "Commenti", + "SHOW_MORE_COMMENTS": "Mostrare commenti precedenti", + "COMMENT_HELP": "Suo commento o domanda...", + "COMMENT_HELP_REPLY_TO": "Sua risposta...", + "BTN_SEND": "Inviare", + "POPOVER_SHARE_TITLE": "Messaggio #{{number}}", + "REPLY": "Rispondere", + "REPLY_TO": "Rispondere a:", + "REPLY_TO_LINK": "In risposta a", + "REPLY_TO_DELETED_COMMENT": "In risposta ad un commento cancellato", + "REPLY_COUNT": "{{replyCount}} risposte", + "DELETED_COMMENT": "Commento cancellato", + "ERROR": { + "FAILED_SAVE_COMMENT": "Salvare il commento cancellato", + "FAILED_REMOVE_COMMENT": "Cancellazione del commento fallita" + } + }, + "MESSAGE": { + "REPLY_TITLE_PREFIX": "Re: ", + "FORWARD_TITLE_PREFIX": "Fw: ", + "BTN_REPLY": "Rispondere", + "BTN_COMPOSE": "Nuovo messaggio", + "BTN_WRITE": "Scrivere", + "NO_MESSAGE_INBOX": "Nessun messaggio ricevuto", + "NO_MESSAGE_OUTBOX": "Nessun messaggio inviato", + "NOTIFICATIONS": { + "TITLE": "Messaggi", + "MESSAGE_RECEIVED": "Hai <b>ricevuto un messaggio/b><br/>da" + }, + "LIST": { + "INBOX": "In entrata", + "OUTBOX": "In uscita", + "TITLE": "Messaggi privati", + "POPOVER_ACTIONS": { + "TITLE": "Opzioni", + "DELETE_ALL": "Eliminare tutti i messaggi" + } + }, + "COMPOSE": { + "TITLE": "Nuovo messaggio", + "TITLE_REPLY": "Rispondere", + "SUB_TITLE": "Nuovo messaggio", + "TO": "A", + "OBJECT": "Oggetto", + "OBJECT_HELP": "Oggetto", + "ENCRYPTED_HELP": "La informiamo che questo messaggio verrà criptato prima della sua spedizione in modo che solo il destinatario lo possa leggere e essere sicuro che ne sia Lei l'autore.", + "MESSAGE": "Messaggio", + "MESSAGE_HELP": "Contenuto del messaggio", + "CONTENT_CONFIRMATION": "Nessun contenuto. <br/><br/>E’ sicura di voler inviare questo messaggio?" + }, + "VIEW": { + "TITLE": "Messaggio", + "SENDER": "Inviato da", + "RECIPIENT": "Inviato a", + "NO_CONTENT": "Messaggio vuoto", + "DELETE": "Cancellare il messaggio" + }, + "CONFIRM": { + "REMOVE": "E’ sicuro/a di voler <b>eliminare il messaggio</b>?<br/><br/> Questa operazione è irreversibile.", + "REMOVE_ALL": "E’ sicuro/a di voler <b>eliminare tutti i messaggi</b>?<br/><br/> Questa operazione è irreversibile.", + "MARK_ALL_AS_READ": "E’ sicuro/a di voler <b>segnare tutti i messaggi come letti/b>?", + "USER_HAS_NO_PROFILE": "Questa identità non ha un profilo Cesium+. Pertanto non può <b>leggere il suo messaggio</b>.<br/><br/>E’ sicuro/a di voler <b>continuare</b>?" + }, + "INFO": { + "MESSAGE_REMOVED": "Messaggio eliminato correttamente", + "All_MESSAGE_REMOVED": "Messaggi eliminati correttamente", + "MESSAGE_SENT": "Messaggio inviato" + }, + "ERROR": { + "SEND_MSG_FAILED": "Errore nella spedizione del messaggio.", + "LOAD_MESSAGES_FAILED": "Errore durante il caricamento dei messaggi.", + "LOAD_MESSAGE_FAILED": "Errore durante il caricamento del messaggio.", + "MESSAGE_NOT_READABLE": "Impossibile leggere il messaggio.", + "USER_NOT_RECIPIENT": "Lei non è il destinatario del messaggio: impossibile leggerlo.", + "NOT_AUTHENTICATED_MESSAGE": "Impossibile verificare l'autenticità del messaggio o contenuto corrotto.", + "REMOVE_MESSAGE_FAILED": "Errore avvenuto durante l'eliminazione del messaggio", + "MESSAGE_CONTENT_TOO_LONG": "Il contenuto supera il limite ({{maxLength}} caratteri ammessi).", + "MARK_AS_READ_FAILED": "Impossibile segnare il messaggio come 'letto'.", + "LOAD_NOTIFICATIONS_FAILED": "Errore nel caricare le notifiche.", + "REMOVE_All_MESSAGES_FAILED": "Errore avvenuto durante l'eliminazione dei messaggi.", + "MARK_ALL_AS_READ_FAILED": "Errore avvenuto nel segnare i messaggi come 'letti", + "RECIPIENT_IS_MANDATORY": "Destinatario obbligatorio" + } + }, + "BLOCKCHAIN": { + "LOOKUP": { + "SEARCH_HELP": "Numero di blocco, hash...", + "POPOVER_FILTER_TITLE": "Filtro", + "HEADER_MEDIAN_TIME": "Data / Ora", + "HEADER_BLOCK": "Blocco #", + "HEADER_ISSUER": "Peer proprietario", + "BTN_LAST": "Ultimi blocchi", + "DISPLAY_QUERY": "Visualizzare query", + "HIDE_QUERY": "Nascondere query", + "TX_SEARCH_FILTER": { + "MEMBER_FLOWS": "<b class=\"ion-person\"></b> Input/output Membri", + "EXISTING_TRANSACTION": "<b class=\"ion-card\"></b> hanno transazioni", + "PERIOD": "<b class=\"ion-clock\"></b> Tra <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) e <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", + "ISSUER": "<b class=\"ion-android-desktop\"></b> Calcolato da {{params[1]|formatPubkey}}", + "TX_PUBKEY": "<b class=\"ion-card\"></b> Transazioni legate a <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" + } + }, + "ERROR": { + "SEARCH_BLOCKS_FAILED": "Errore durante la ricerca dei blocchi." + } + }, + "GROUP": { + "GENERAL_DIVIDER": "Informazioni generali", + "LOCATION_DIVIDER": "Indirizzo", + "SOCIAL_NETWORKS_DIVIDER": "Presenza sui social e/o sito web", + "TECHNICAL_DIVIDER": "Dati tecnici", + "CREATED_TIME": "Creato {{creationTime|formatFromNow}}", + "NOTIFICATIONS": { + "TITLE": "Inviti" + }, + "LOOKUP": { + "TITLE": "Gruppi", + "SEARCH_HELP": "Nome del grupo, parole chiavi, luogo, etc.", + "LAST_RESULTS_LIST": "Nuovi gruppi :", + "OPEN_RESULTS_LIST": "Gruppi aperti :", + "MANAGED_RESULTS_LIST": "Gruppi chiusi :", + "BTN_LAST": "Nuovi gruppi", + "BTN_NEW": "Aggiungo un grupo!" + }, + "TYPE": { + "TITLE": "Nuovo gruppo", + "SELECT_TYPE": "Tipo di gruppo :", + "OPEN_GROUP": "Gruppo aperto", + "OPEN_GROUP_HELP": "Un gruppo aperto è accessibile da qualsiasi membro della moneta.", + "MANAGED_GROUP": "Gruppo amministrato", + "MANAGED_GROUP_HELP": "un gruppo amministrato è gestito da amministratori e moderatori, che possono accetare, rifiutare o escludere membri del gruppo.", + "ENUM": { + "OPEN": "Gruppo aperto", + "MANAGED": "Gruppo amministrato" + } + }, + "VIEW": { + "POPOVER_SHARE_TITLE": "{{title}}", + "MENU_TITLE": "Opzioni", + "REMOVE_CONFIRMATION" : "Sei sicuro/a di voler chiudere questo gruppo ?<br/><br/>Questa operazione è irreversibile." + }, + "EDIT": { + "TITLE": "Gruppo", + "TITLE_NEW": "Nuovo gruppo", + "RECORD_TITLE": "Titolo", + "RECORD_TITLE_HELP": "Titolo", + "RECORD_DESCRIPTION": "Descrizione", + "RECORD_DESCRIPTION_HELP": "Descrizione" + }, + "ERROR": { + "SEARCH_GROUPS_FAILED": "Errore nella ricerca di gruppi", + "REMOVE_RECORD_FAILED": "Errore nel chiudere il gruppo" + }, + "INFO": { + "RECORD_REMOVED" : "Gruppo eliminato" + } + }, + "REGISTRY": { + "CATEGORY": "Attività principale", + "GENERAL_DIVIDER": "Informazioni di base", + "LOCATION_DIVIDER": "Indirizzo", + "SOCIAL_NETWORKS_DIVIDER": "Presenza sui social, sito web", + "TECHNICAL_DIVIDER": "Dati tecnici", + "BTN_SHOW_WOT": "Persone", + "BTN_SHOW_WOT_HELP": "Cercare persone", + "BTN_SHOW_PAGES": "Pagine", + "BTN_SHOW_PAGES_HELP": "Cercare pagine", + "BTN_NEW": "Aggiungere", + "MY_PAGES": "Mie pagine", + "NO_PAGE": "Nessuna pagina", + "SEARCH": { + "TITLE": "Pagine", + "SEARCH_HELP": "Che, chi: parrucchiere, Pizza Efisio, ...", + "BTN_ADD": "Nuovo", + "BTN_LAST_RECORDS": "Pagine recenti", + "BTN_ADVANCED_SEARCH": "Ricerca avanzata", + "BTN_OPTIONS": "Ricerca avanzata", + "TYPE": "Tipo di ente", + "LOCATION_HELP": "Città ", + "RESULTS": "Risultati", + "RESULT_COUNT_LOCATION": "{{count}} risultato{{count>0?'i':''}}, vicino a {{location}}", + "RESULT_COUNT": "{{count}} risultato{{count>0?'i':''}}", + "LAST_RECORDS": "Pagine recenti:", + "LAST_RECORD_COUNT_LOCATION": "{{count}} pagina{{count>0?'e':''}} recente{{count>0?'i':''}}, vicino a{{location}}", + "LAST_RECORD_COUNT": "{{count}} pagina{{count>0?'e':''}} recente{{count>0?'i':''}}", + "POPOVER_FILTERS": { + "BTN_ADVANCED_SEARCH": "Opzioni avanzate ?" + } + }, + "VIEW": { + "TITLE": "Annuario", + "CATEGORY": "Attività principale:", + "LOCATION": "Indirizzo:", + "MENU_TITLE": "Impostazioni", + "POPOVER_SHARE_TITLE": "{{title}}", + "REMOVE_CONFIRMATION" : "E’ sicuro/a di voler eliminare questo riferimento?<br/><br/>Questa operazione è irreversibile." + }, + "TYPE": { + "TITLE": "Nuovo riferimento", + "SELECT_TYPE": "Tipo di ente/organismo:", + "ENUM": { + "SHOP": "Negozi locali", + "COMPANY": "Azienda", + "ASSOCIATION": "Associazione", + "INSTITUTION": "Istituto" + } + }, + "EDIT": { + "TITLE": "Modificare", + "TITLE_NEW": "Nuovo riferimento", + "RECORD_TYPE": "Tipo di ente", + "RECORD_TITLE": "Nome", + "RECORD_TITLE_HELP": "Nome", + "RECORD_DESCRIPTION": "Descrizione", + "RECORD_DESCRIPTION_HELP": "Descrivere l'attività ", + "RECORD_ADDRESS": "Indirizzo", + "RECORD_ADDRESS_HELP": "Indirizzo: Strada, numero civico...", + "RECORD_CITY": "Città ", + "RECORD_CITY_HELP": "Città , Paese", + "RECORD_SOCIAL_NETWORKS": "Presenza sui social e/o sito web", + "RECORD_PUBKEY": "Chiave pubblica", + "RECORD_PUBKEY_HELP": "Chiave pubblica per ricevere pagamenti" + }, + "WALLET": { + "REGISTRY_DIVIDER": "Pagine", + "REGISTRY_HELP": "Le pagine sono un elenco dei profesionisti che accettano o favoriscono: negozi, aziende, associazioni, istituti..." + }, + "ERROR": { + "LOAD_CATEGORY_FAILED": "Errore nel caricamento delle attività principali", + "LOAD_RECORD_FAILED": "Caricamento fallito", + "LOOKUP_RECORDS_FAILED": "Errore nel caricare i dati", + "REMOVE_RECORD_FAILED": "Errore nella cancellazione", + "SAVE_RECORD_FAILED": "Impossibile salvare", + "RECORD_NOT_EXISTS": "Inesistente", + "GEO_LOCATION_NOT_FOUND": "Città o CAP inesistente" + }, + "INFO": { + "RECORD_REMOVED" : "Pagina eliminata con successo.", + "RECORD_SAVED": "Pagina salvata" + } + }, + "PROFILE": { + "PROFILE_DIVIDER": "Profilo Cesium+", + "PROFILE_DIVIDER_HELP": "Si tratta qui di data esterni, salvati fuori della rete della moneta.", + "NO_PROFILE_DEFINED": "Nessun profilo Cesium+", + "BTN_ADD": "Creare mio profilo", + "BTN_EDIT": "Modificare mio profilo", + "UID": "Pseudonimo", + "TITLE": "Cognome, Nome", + "TITLE_HELP": "Nome", + "DESCRIPTION": "A proposito di me", + "DESCRIPTION_HELP": "A proposito di me...", + "SOCIAL_HELP": "http://...", + "GENERAL_DIVIDER": "Informazioni generali", + "SOCIAL_NETWORKS_DIVIDER": "Presenza sui social e sito/i web", + "TECHNICAL_DIVIDER": "Dati tecnici", + "MODAL_AVATAR": { + "TITLE": "Avatar", + "SELECT_FILE_HELP": "<b>Scegliere un'immagine</b>, cliccando sul bottone qui sotto:", + "BTN_SELECT_FILE": "Scegliere un'immagine", + "RESIZE_HELP": "<b>Ritagliare l'immagine</b> se necessario. Cliccare sull'immagine permette di spostarla. Cliccando nella zona a basso sinistra permette di fare uno zoom-in.", + "RESULT_HELP": "<b>Questo è il risultato</b> come visibile sul suo profilo:" + }, + "ERROR": { + "LOAD_PROFILE_FAILED": "Impossibile caricare il profilo dell’utente.", + "SAVE_PROFILE_FAILED": "Impossibile salvare il profilo", + "INVALID_SOCIAL_NETWORK_FORMAT": "Formatto scorretto: URL sbagliato.<br/><br/>Esempi: :<ul><li>- Una pagina Facebook (https://www.facebook.com/user)</li><li>- Un sito: (http://www.domain.com)</li><li>- Un indirizzo mail: (joe@dalton.com)</li></ul>", + "IMAGE_RESIZE_FAILED": "Errore nel ritagliare l'immagine" + }, + "INFO": { + "PROFILE_SAVED": "Profilo salvato" + }, + "HELP": { + "WARNING_PUBLIC_DATA": "La informiamo che le informazioni qui pubblicate <b>sono pubbliche</b>: sono anche visibili <b>da gente non registrata/b>." + } + }, + "LOCATION": { + "BTN_GEOLOC_ADDRESS": "Trovare mio indirizzo sulla mappa", + "USE_GEO_POINT": "Geo-localizzare (raccomandato)?", + "LOADING_LOCATION": "Cercando indirizzo...", + "LOCATION_DIVIDER": "Posizione", + "ADDRESS": "Indirizzo", + "ADDRESS_HELP": "Indirizzo (opzionale)", + "CITY": "Città ", + "CITY_HELP": "Città , Paese", + "DISTANCE": "Distanza massimale intorno alla città ", + "DISTANCE_UNIT": "km", + "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", + "SEARCH_HELP": "Città , CAP", + "MODAL": { + "TITLE": "Cercare indirizzo", + "SEARCH_HELP": "Città , Paese", + "ALTERNATIVE_RESULT_DIVIDER": "Risultati alternativi <b>{{address}}</b>:", + "POSITION": "lat/lon : {{lat}} {{lon}}" + }, + "ERROR": { + "REQUIRED_FOR_LOCATION": "Campo obbligatorio per apparire sulla mappa", + "INVALID_FOR_LOCATION": "Indirizzo sconosciuto", + "GEO_LOCATION_FAILED": "Impossibile trovare sua posizione. Utilizzi il bottone di ricerca.", + "ADDRESS_LOCATION_FAILED": "Indirizzo non trovato" + } + }, + "SUBSCRIPTION": { + "SUBSCRIPTION_DIVIDER": "Servizi online", + "SUBSCRIPTION_DIVIDER_HELP": "I servizi online offrono servizi addizionali opzionali, delegati ad terzi.", + "BTN_ADD": "Aggiungere un servizio", + "BTN_EDIT": "Gestire miei servizi", + "NO_SUBSCRIPTION": "Nessun servizio utilizzato", + "SUBSCRIPTION_COUNT": "Servizi/ Abbonamenti", + "EDIT": { + "TITLE": "Servizi online", + "HELP_TEXT": "Qui si possono gestire gli abbonamenti e/o altri servizi online", + "PROVIDER": "Prestatore :" + }, + "TYPE": { + "ENUM": { + "EMAIL": "Ricevere notifiche per posta elettronica" + } + }, + "CONFIRM": { + "DELETE_SUBSCRIPTION": "Sei sicuro/a di voler <b>cancellare questo abbonamento</b> ?" + }, + "ERROR": { + "LOAD_SUBSCRIPTIONS_FAILED": "Errore nel caricamento dei servizi online", + "ADD_SUBSCRIPTION_FAILED": "Errore nel invio dell' abbonamento", + "UPDATE_SUBSCRIPTION_FAILED": "Errore nel aggiornamento dell' abbonamento", + "DELETE_SUBSCRIPTION_FAILED": "Errore nella cancellazine dell' abbonamento" + }, + "MODAL_EMAIL": { + "TITLE" : "Notifiche per posta elettronica", + "HELP" : "Riempi questo formulario per <b>essere notificato/a per e-mail</b> degli eventi che avvengono sul tuo conto.<br/>Tuo indizzo mail sarà cifrato e solo il prestatore del servizio lo potrà vedere.", + "EMAIL_LABEL" : "Tuo indirizzo mail :", + "EMAIL_HELP": "cristiana.leonardi@dominio.com", + "FREQUENCY_LABEL": "Frequenza delle notifiche :", + "FREQUENCY_DAILY": "Quotidiano", + "FREQUENCY_WEEKLY": "Settimanale", + "PROVIDER": "Prestatore del servizio :" + } + }, + "DOCUMENT": { + "HASH": "Hash: ", + "LOOKUP": { + "TITLE": "Ricerca di documenti", + "BTN_ACTIONS": "Azioni", + "SEARCH_HELP": "issuer:AAA*, time:1508406169", + "LAST_DOCUMENTS": "Ultimi documenti", + "SHOW_QUERY": "Visualizzare la richiesta", + "HIDE_QUERY": "Nacondere la richiesta", + "HEADER_TIME": "Data/Ora", + "HEADER_ISSUER": "Emittente", + "HEADER_RECIPIENT": "Destinatario", + "READ": "Letto", + "BTN_REMOVE": "Eliminare questo documento", + "POPOVER_ACTIONS": { + "TITLE": "Azioni", + "REMOVE_ALL": "Eliminare questi documenti..." + } + }, + "INFO": { + "REMOVED": "Documento eliminato" + }, + "CONFIRM": { + "REMOVE": "Sei sicuro/a di voler <b>eliminare questo documento</b> ?", + "REMOVE_ALL": "Si sicuro/a di voler <b>eliminare questi documenti</b> ?" + }, + "ERROR": { + "LOAD_DOCUMENTS_FAILED": "Errore nella ricerca dei documenti", + "REMOVE_FAILED": "Errore nell'eliminazione del documento", + "REMOVE_ALL_FAILED": "Errore nell'eliminazione dei documenti" + } + }, + "ES_SETTINGS": { + "PLUGIN_NAME": "Cesium+", + "PLUGIN_NAME_HELP": "Profili di utenti, notifiche, messaggi privati", + "ENABLE_TOGGLE": "Abilitare l'estensione ?", + "ENABLE_MESSAGE_TOGGLE": "Abilitare i messaggi? privati", + "ENABLE_SETTINGS_TOGGLE": "Abilitare stoccaggio su dispositivi esterni per le impostazioni?", + "PEER": "Indirizzo di data peers", + "POPUP_PEER": { + "TITLE" : "Data peer", + "HELP" : "Definire l'indirizzo da usare per il peer:", + "PEER_HELP": "server.domain.com:port" + }, + "NOTIFICATIONS": { + "DIVIDER": "Notifiche", + "HELP_TEXT": "Scegliere le notifiche che accetta ricevere:", + "ENABLE_TX_SENT": "Notificarmi di <b>pagamenti inviati</b> con successo?", + "ENABLE_TX_RECEIVED": "Notificarmi di <b>pagamenti in entrata</b>?", + "ENABLE_CERT_SENT": "Notificarmi delle <b>certificazioni inviate</b>?", + "ENABLE_CERT_RECEIVED": "Notificarmi di <b>certificazioni ricevute</b>?" + }, + "CONFIRM": { + "ASK_ENABLE_TITLE": "Nuove funzionalità ", + "ASK_ENABLE": "Sono disponibili nuove funzionalità : <ul><li> <b><i class=\"icon ion-person\"></i>Profili di utenti</b>;<li> <b><i class=\"icon ion-android-notifications\"></i> Notifications</b>;<li> <b><i class=\"icon ion-email\"></i> Messaggi privati/b>.</ul><br/>Sono state <b>disabilitate</b> nelle sue impostazioni.<br/><br/><b>Desidera abilitare</b> queste funzionalità ?" + } + }, + "ES_WALLET": { + "ERROR": { + "RECIPIENT_IS_MANDATORY": "Un destinatario è necessario per il criptaggio." + } + }, + "EVENT": { + "NODE_STARTED": "Suo nodo ES API <b>{{params[0]}}</b> è UP", + "NODE_BMA_DOWN": "Nodo<b>{{params[0]}}:{{params[1]}}</b> (utilizzato dal suo ES API) è <b>indisponibile</b>.", + "NODE_BMA_UP": "Nodo <b>{{params[0]}}:{{params[1]}}</b> è di nuovo attivo.", + "MEMBER_JOIN": "E diventato <b>membro/a</b> della WoT della moneta <b>{{params[0]}}</b>!", + "MEMBER_LEAVE": "Non <b>è più membro/a</b> della WoT della moneta <b>{{params[0]}}</b>!", + "MEMBER_EXCLUDE": "Non è <b>più membro/a</b> della WoT della moneta<b>{{params[0]}}</b>, a causa di certificazioni non rinnovate o soglia di certificazioni non raggiunta.", + "MEMBER_REVOKE": "Il suo conto è stato revocato. Da ora in poi non farà più parte della WoT. <b>{{params[0]}}</b>.", + "MEMBER_ACTIVE": "La sua presenza nella WoT <b>{{params[0]}}</b> è stata <b>rinnovata correttamente</b>.", + "TX_SENT": "Il suo pagamento <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\" ><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> è stato eseguito.", + "TX_SENT_MULTI": "Il suo pagamento <b>{{params[1]}}</b> è stato eseguito.", + "TX_RECEIVED": "Ha ricevuto un pagamento da <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span>.", + "TX_RECEIVED_MULTI": "Ha ricevuto un pagamento da <b>{{params[1]}}</b>.", + "CERT_SENT": "Sua <b>certificazione</b> a favore di <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\" ><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> è stata eseguita.", + "CERT_RECEIVED": "Ha ricevuto <b>una certificazione</b> da parte di <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span>.", + "REGISTRY": { + "NEW_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> ha scritto un commento sul suo riferimento: <b>{{params[2]}}</b>", + "UPDATE_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> ha modificato il suo commento sul suo riferimento: <b>{{params[2]}}</b>", + "NEW_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> ha risposto al suo commento sul riferimento: <b>{{params[2]}}</b>", + "UPDATE_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> ha modificato sua risposta sul suo commento a proposito del riferimento: <b>{{params[2]}}</b>" + } + }, + "CONFIRM": { + "ES_USE_FALLBACK_NODE": "Nodo<b>{{old}}</b> irraggiungibile o indirizzo sbagliato.<br/><br/>Vuoi utilizzare temporaneamente il nodo di dati <b>{{new}}</b> ?" + }, + "ERROR": { + "ES_CONNECTION_ERROR": "Nodo di dati<b>{{server}}</b> irraggiungibile o indirizzo sbagliato.<br/><br/>Cesium continuerà a funzionare <b>senza l'estensione Cesium+</b> (profili utenti, messaggi privati, mappe e grafici)<br/><br/>Verifica tua connessione o cambia nodo <a class=\"positive\" ng-click=\"doQuickFix('settings')\">impostazioni dell'estensione</a>.", + "ES_MAX_UPLOAD_BODY_SIZE": "Il volume di data da inviare supera il limite imposto dal server.<br/><br/>Suggeriamo di riprovare dopo aver eliminato delle foto, per esempio." + } + } +); + $translateProvider.translations("nl-NL", { "COMMON": { "CATEGORY": "Categorie", "CATEGORIES": "Categorieën", "CATEGORY_SEARCH_HELP": "Zoeken", - "LAST_MODIFICATION_DATE": "Vernieuws op ", + "LAST_MODIFICATION_DATE": "Vernieuwd op ", "SUBMIT_BY": "Ingediend door", "BTN_PUBLISH": "Publiceren", "BTN_PICTURE_DELETE": "Wissen", @@ -2077,22 +3200,22 @@ $translateProvider.translations("nl-NL", { } }, "MENU": { - "REGISTRY": "Ondernemingen", + "REGISTRY": "Pagina's", "USER_PROFILE": "Mijn profiel", "MESSAGES": "Berichten" }, "ACCOUNT": { "NEW": { "ORGANIZATION_ACCOUNT": "Ondernemingsrekening", - "ORGANIZATION_ACCOUNT_HELP": "Als je een onderneming, vereniging etc. vertegenwoordigd.<br/>Deze rekening zal geen dividend créeren." + "ORGANIZATION_ACCOUNT_HELP": "Als je een onderneming, vereniging etc. vertegenwoordigt.<br/>Deze rekening zal geen dividend créeren." }, "EVENT": { - "MEMBER_WITHOUT_PROFILE": "Vul <a ui-sref=\"app.user_edit_profile\"je gebruikersprofiel</a> in om sneller een certificering te verkrijgen. Leden zullen een verfifieerbare identiteit eerder vertrouwen." + "MEMBER_WITHOUT_PROFILE": "Vul <a ui-sref=\"app.edit_profile\"je gebruikersprofiel</a> in om sneller een certificering te verkrijgen. Leden zullen een verfifieerbare identiteit eerder vertrouwen." } }, "COMMENTS": { "DIVIDER": "Commentaren", - "SHOW_MORE_COMMENTS": "Toon eerder commentaren", + "SHOW_MORE_COMMENTS": "Toon eerdere commentaren", "COMMENT_HELP": "Jouw commentaar, vraag...", "COMMENT_HELP_REPLY_TO": "Jouw antwoord...", "BTN_SEND": "Verzenden", @@ -2161,7 +3284,7 @@ $translateProvider.translations("nl-NL", { "USER_NOT_RECIPIENT": "Je bent niet de geadresseerde van dit bericht: het kan niet gelezen worden.", "NOT_AUTHENTICATED_MESSAGE": "De authenticiteit van het bericht is onduidelijk of de inhoud is gecorrumpeerd.", "REMOVE_MESSAGE_FAILED": "Kan bericht niet wissen.", - "MESSAGE_CONTENT_TOO_LONG": "Waarde te land (max {{maxLength}} characters).", + "MESSAGE_CONTENT_TOO_LONG": "Waarde te lang (max {{maxLength}} characters).", "MARK_AS_READ_FAILED": "Kan bericht niet als gelezen markeren.", "LOAD_NOTIFICATIONS_FAILED": "Kan niet alle berichtnotificaties laden.", "REMOVE_All_MESSAGES_FAILED": "Kan niet alle berichten wissen.", @@ -2281,14 +3404,14 @@ $translateProvider.translations("nl-NL", { "ENABLE_CERT_RECEIVED": "Bericht bij validatie van <b>ontvangen certificaties</b>?" }, "CONFIRM": { - "ASK_ENABLE_TITLE": "Nieuwe functies", - "ASK_ENABLE": "Er zijn nieuwe functies beschikbaar: <ul><li> <b><i class=\"icon ion-person\"></i> Profile Cesium+</b>;<li> <b><i class=\"icon ion-android-notifcaitions\"></i> Notifications</b>;<li> <b><i class=\"icon ion-email\"></i> Privé berichten</b>.</ul><br/>Deze zijn <b>uitgeschakeld</b> in je instellingen.<br/><br/>Wil je deze functies <b>inschakelen</b>?" + "ASK_ENABLE_TITLE": "Optionele functies", + "ASK_ENABLE": "Cesium+ is <b>uitgeschakeld</b> waardoor deze functies niet beschikbaar zijn: <ul><li> <b><i class=\"icon ion-person\"></i> Gebruikersprofielen</b>;<li> <b><i class=\"icon ion-android-notifcaitions\"></i> Notificaties</b>;<li> <b><i class=\"icon ion-email\"></i> Privéberichten</b>.</ul><br/><br/>Wil je deze functies <b>inschakelen</b>?" } }, "EVENT": { "NODE_STARTED": "Je knoop ES API <b>{{params[0]}}</b> is UP", "NODE_BMA_DOWN": "Knooppunt <b>{{params[0]}}:{{params[1]}}</b> (gebruikt door je ES API) is <b>onbereikbaar</b>.", - "NODE_BMA_UP": "Knooppunt <b>{{p0}}:{{params[1]}}</b> is weer onbereikbaar.", + "NODE_BMA_UP": "Knooppunt <b>{{p0}}:{{params[1]}}</b> is weer bereikbaar.", "MEMBER_JOIN": "Je bent nu <b>lid</b> van valuta <b>{{params[0]}}</b>!", "MEMBER_LEAVE": "Je bent <b>geen lid meer</b> van valuta <b>{{params[0]}}</b>!", "MEMBER_ACTIVE": "Je lidmaatschap bij <b>{{params[0]}}</b> is met <b>succes verlengd</b>.", @@ -2304,6 +3427,13 @@ $translateProvider.translations("nl-NL", { "NEW_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> hheeft gereageerd op jouw commentaar op referentie: <b>{{params[2]}}</b>", "UPDATE_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> heeft zijn/haar reactie op jouw commentaar bewerkt, op referentie: <b>{{params[2]}}</b>" } + }, + "CONFIRM": { + "ES_USE_FALLBACK_NODE": "Knooppunt <b>{{old}}</b> onbereikbaar of ongeldig adres.<br/><br/>Tijdelijk knooppunt <b>{{new}}</b> gebruiken?" + }, + "ERROR": { + "ES_CONNECTION_ERROR": "Knooppunt <b>{{server}}</b> onbereikbaar of ongeldig adres.<br/><br/>Cesium zal verder weken, <b>zonder de Cesium+ uitbreiding</b> (gebruikersprofielens, privéberichten, kaarten en grafieken).<br/><br/>Controleer je internetverbinding, of verander je knooppunt in <a class=\"positive\" ng-click=\"doQuickFix('settings')\">instellingen</a>.", + "ES_MAX_UPLOAD_BODY_SIZE": "De hoveelheid te verzenden gegevens is overschrijdt de serverlimiet.<br/><br/>Probeer het nogmaals na, bijvoorbeeld, het wissen foto's." } } ); @@ -2319,7 +3449,13 @@ $translateProvider.translations("en-GB", { "LINEAR_SCALE" : "Linear scale", "LOGARITHMIC_SCALE" : "Logarithmic scale", "BTN_SHOW_STATS": "See statistics", - "BTN_SHOW_DETAILED_STATS": "Detailed statistics" + "BTN_SHOW_DETAILED_STATS": "Detailed statistics", + "RANGE_DURATION_DIVIDER": "Step unit:", + "RANGE_DURATION": { + "HOUR": "Group by <b>hour</b>", + "DAY": "Group by <b>day</b>", + "MONTH": "Group by <b>month</b>" + } }, "ACCOUNT": { "TITLE": "Statistics", @@ -2345,13 +3481,7 @@ $translateProvider.translations("en-GB", { "TX_AMOUNT_LABEL": "Exchange volume", "TX_COUNT_TITLE": "Number of written transactions", "TX_COUNT_LABEL": "Number of transactions", - "TX_AVG_BY_BLOCK": "Average per block", - "TX_RANGE_DURATION_DIVIDER": "Step unit:", - "TX_RANGE_DURATION": { - "HOUR": "Group by <b>hour</b>", - "DAY": "Group by <b>day</b>", - "MONTH": "Group by <b>month</b>" - } + "TX_AVG_BY_BLOCK": "Average per block" }, "CURRENCY": { "MONETARY_MASS_TITLE": "Evolution of the monetary mass", @@ -2367,6 +3497,35 @@ $translateProvider.translations("en-GB", { "BLOCK_COUNT": "{{count}} blocks", "NO_BLOCK": "No block" } + }, + "DOC_STATS": { + "TITLE": "Data storage statistics (Cesium+)", + "USER": { + "TITLE": "Number of documents linked to an account", + "USER_PROFILE": "User profiles", + "USER_SETTINGS": "Saved settings" + }, + "USER_DELTA": { + "TITLE": "Delta / Number of documents linked to an account", + "USER_PROFILE": "User profiles", + "USER_SETTINGS": "Saved settings" + }, + "MESSAGE": { + "TITLE": "Number of documents related to the communication", + "MESSAGE_INBOX": "Messages in inbox", + "MESSAGE_OUTBOX": "Messages in outbox", + "INVITATION_CERTIFICATION": "Invitations to certify" + }, + "SOCIAL": { + "TITLE": "Number of page or group", + "PAGE_COMMENT": "Comments", + "PAGE_RECORD": "Pages", + "GROUP_RECORD": "Groups" + }, + "OTHER": { + "TITLE": "Other documents", + "HISTORY_DELETE": "Deletion of documents" + } } } } @@ -2383,7 +3542,13 @@ $translateProvider.translations("en", { "LINEAR_SCALE" : "Linear scale", "LOGARITHMIC_SCALE" : "Logarithmic scale", "BTN_SHOW_STATS": "See statistics", - "BTN_SHOW_DETAILED_STATS": "Detailed statistics" + "BTN_SHOW_DETAILED_STATS": "Detailed statistics", + "RANGE_DURATION_DIVIDER": "Step unit:", + "RANGE_DURATION": { + "HOUR": "Group by <b>hour</b>", + "DAY": "Group by <b>day</b>", + "MONTH": "Group by <b>month</b>" + } }, "ACCOUNT": { "TITLE": "Statistics", @@ -2409,13 +3574,7 @@ $translateProvider.translations("en", { "TX_AMOUNT_LABEL": "Exchange volume", "TX_COUNT_TITLE": "Number of written transactions", "TX_COUNT_LABEL": "Number of transactions", - "TX_AVG_BY_BLOCK": "Average per block", - "TX_RANGE_DURATION_DIVIDER": "Step unit:", - "TX_RANGE_DURATION": { - "HOUR": "Group by <b>hour</b>", - "DAY": "Group by <b>day</b>", - "MONTH": "Group by <b>month</b>" - } + "TX_AVG_BY_BLOCK": "Average per block" }, "CURRENCY": { "MONETARY_MASS_TITLE": "Evolution of the monetary mass", @@ -2433,11 +3592,16 @@ $translateProvider.translations("en", { } }, "DOC_STATS": { - "TITLE": "Data storage statistitics", + "TITLE": "Data storage statistics (Cesium+)", "USER": { "TITLE": "Number of documents linked to an account", - "USER_PROFILE": "User profiles utilisateur", - "USER_SETTINGS": "Saved settings", + "USER_PROFILE": "User profiles", + "USER_SETTINGS": "Saved settings" + }, + "USER_DELTA": { + "TITLE": "Delta / Number of documents linked to an account", + "USER_PROFILE": "User profiles", + "USER_SETTINGS": "Saved settings" }, "MESSAGE": { "TITLE": "Number of documents related to the communication", @@ -2449,11 +3613,126 @@ $translateProvider.translations("en", { "TITLE": "Number of page or group", "PAGE_COMMENT": "Comments", "PAGE_RECORD": "Pages", - "GROUP_RECORD": "Groups", + "GROUP_RECORD": "Groups" }, "OTHER": { "TITLE": "Other documents", - "HISTORY_DELETE": "Deletion of documents", + "HISTORY_DELETE": "Deletion of documents" + } + } + } +} +); + +$translateProvider.translations("eo-EO", { + "NETWORK": { + "VIEW": { + "BTN_GRAPH": "Statistikoj" + } + }, + "GRAPH": { + "COMMON": { + "LINEAR_SCALE" : "Lineara skalo", + "LOGARITHMIC_SCALE" : "Logaritma skalo", + "BTN_SHOW_STATS": "Vidi la statistikojn", + "BTN_SHOW_DETAILED_STATS": "Detalaj statistikoj", + "RANGE_DURATION_DIVIDER": "Tempo-unuo:", + "RANGE_DURATION": { + "HOUR": "Horo", + "DAY": "Tago", + "MONTH": "Monato" + } + }, + "ACCOUNT": { + "TITLE": "Statistikoj", + "BTN_SHOW_STATS": "Vidi la statistikojn de la konto", + "BALANCE_DIVIDER": "Stato de la konto", + "BALANCE_TITLE": "Evoluo de la konto {{pubkey|formatPubkey}}", + "TX_RECEIVED_LABEL": "Enspezoj", + "TX_SENT_LABEL": "Elspezoj", + "TX_ACCUMULATION_LABEL": "Bilanco de la spezoj", + "UD_LABEL": "UD", + "UD_ACCUMULATION_LABEL": "Bilanco de la UD", + "BALANCE_LABEL": "Saldo", + "WOT_DIVIDER": "Reto de fido", + "CERTIFICATION_TITLE": "Nombro de atestaĵoj - {{pubkey|formatPubkey}}", + "RECEIVED_CERT_LABEL": "Tuto pri la ricevitaj", + "RECEIVED_CERT_DELTA_LABEL": "Vario pri la ricevitaj", + "GIVEN_CERT_LABEL": "Tuto pri la senditaj", + "GIVEN_CERT_DELTA_LABEL": "Vario pri la senditaj", + "INPUT_CHART_TITLE": "Sumo de la enirantaj fluoj, por ĉiu sendinto:", + "OUTPUT_CHART_TITLE": "Sumo de la elirantaj fluoj, por ĉiu ricevinto:" + }, + "BLOCKCHAIN": { + "TITLE": "Statistikoj", + "BLOCKS_ISSUERS_DIVIDER": "Analizo de la kalkul-distribuo", + "BLOCKS_ISSUERS_HELP": "<b>{{issuerCount|formatInteger}} membroj</b> kalkulis <b>{{blockCount|formatInteger}} blokojn</b>", + "BLOCKS_ISSUERS_TITLE": "Nombro de blokoj kalkulitaj por membro", + "BLOCKS_ISSUERS_LABEL": "Nombro de blokoj", + "TX_DIVIDER": "Analizo de la spezoj", + "TX_AMOUNT_TITLE": "Kvanto de la spezoj", + "TX_AMOUNT_PUBKEY_TITLE": "Kvanto de spezoj kalkulitaj de {{issuer | formatPubkey}}", + "TX_AMOUNT_LABEL": "Kvanto interÅanÄita", + "TX_COUNT_TITLE": "Nombro de spezoj skribitaj", + "TX_COUNT_LABEL": "Nombro de spezoj", + "TX_AVG_BY_BLOCK": "Meza nombro de spezoj / bloko" + + }, + "CURRENCY": { + "MONETARY_MASS_TITLE": "Evoluo de la mona maso", + "MONETARY_MASS_LABEL": "Mona maso", + "MONETARY_MASS_SHARE_LABEL": "Mezumo por membro", + "UD_TITLE": "Evoluo de la universala dividendo", + "MEMBERS_COUNT_TITLE": "Evoluo de la nombro de membroj", + "MEMBERS_COUNT_LABEL": "Nombro de membroj" + }, + "PEER": { + "VIEW": { + "BLOCK_COUNT_LABEL": "Nombro de blokoj kalkulitaj", + "BLOCK_COUNT": "{{count}} blokoj", + "NO_BLOCK": "Neniu bloko" + } + }, + "DOC_STATS": { + "TITLE": "Statistikoj pri stokado", + "USER": { + "TITLE": "Nombro de dokumentoj ligitaj al konto", + "USER_PROFILE": "Uzanto-profiloj", + "USER_SETTINGS": "Parametroj konservitaj" + }, + "MESSAGE": { + "TITLE": "Nombro de dokumentoj ligitaj al komunikado", + "MESSAGE_INBOX": "MesaÄoj en ricevujo", + "MESSAGE_OUTBOX": "Senditaj mesaÄoj konservitaj", + "INVITATION_CERTIFICATION": "Invitoj atestotaj" + }, + "SOCIAL": { + "TITLE": "Nombro de paÄoj aÅ grupoj", + "PAGE_COMMENT": "Komentoj", + "PAGE_RECORD": "PaÄoj", + "GROUP_RECORD": "Grupoj" + }, + "OTHER": { + "TITLE": "Aliaj dokumentoj", + "HISTORY_DELETE": "Forigoj de dokumentoj" + } + }, + "SYNCHRO": { + "TITLE": "Statistikoj pri sinkronigoj", + "COUNT": { + "TITLE": "Kvanto sinkronigita", + "INSERTS": "Enmetoj", + "UPDATES": "Äœisdatigoj", + "DELETES": "Forigoj" + }, + "PEER": { + "TITLE": "Nodoj informpetitaj", + "ES_USER_API": "Nodoj pri datenoj de uzantoj", + "ES_SUBSCRIPTION_API": "Nodoj pri retaj servoj" + }, + "PERFORMANCE": { + "TITLE": "Efikecoj pri efektiviÄo", + "DURATION": "Tempo por efektiviÄo (ms)" } } } @@ -2471,7 +3750,13 @@ $translateProvider.translations("es-ES", { "LINEAR_SCALE" : "Escala lineal", "LOGARITHMIC_SCALE" : "Escala logarÃtmica", "BTN_SHOW_STATS": "Ver estadÃsticas", - "BTN_SHOW_DETAILED_STATS": "EstadÃsticas detalladas" + "BTN_SHOW_DETAILED_STATS": "EstadÃsticas detalladas", + "RANGE_DURATION_DIVIDER": "Unidad de paso:", + "RANGE_DURATION": { + "HOUR": "Grupo por <b>hora</b>", + "DAY": "Grupo por <b>dÃa</b>", + "MONTH": "Grupo por <b>mes</b>" + } }, "ACCOUNT": { "INPUT_CHART_TITLE": "Suma del flujo entrante, por el transmisor:", @@ -2489,12 +3774,7 @@ $translateProvider.translations("es-ES", { "TX_AMOUNT_LABEL": "Volumen negociado", "TX_COUNT_TITLE": "Número de transacciones escritas", "TX_COUNT_LABEL": "Número de transacciones", - "TX_AVG_BY_BLOCK": "Promedio por bloque", - "TX_RANGE_DURATION": { - "HOUR": "Grupo por <b>hora</b>", - "DAY": "Grupo por <b>dÃa</b>", - "MONTH": "Grupo por <b>mes</b>" - } + "TX_AVG_BY_BLOCK": "Promedio por bloque" }, "CURRENCY": { "MONETARY_MASS_TITLE": "Evolución de la masa monetaria", @@ -2526,7 +3806,13 @@ $translateProvider.translations("fr-FR", { "LINEAR_SCALE" : "Echelle linéaire", "LOGARITHMIC_SCALE" : "Echelle logarithmique", "BTN_SHOW_STATS": "Voir les statistiques", - "BTN_SHOW_DETAILED_STATS": "Statistiques détaillées" + "BTN_SHOW_DETAILED_STATS": "Statistiques détaillées", + "RANGE_DURATION_DIVIDER": "Unité de temps :", + "RANGE_DURATION": { + "HOUR": "Heure", + "DAY": "Jour", + "MONTH": "Mois" + } }, "ACCOUNT": { "TITLE": "Statistiques", @@ -2560,13 +3846,8 @@ $translateProvider.translations("fr-FR", { "TX_AMOUNT_LABEL": "Volume échangé", "TX_COUNT_TITLE": "Nombre de transactions écrites", "TX_COUNT_LABEL": "Nombre de transactions", - "TX_AVG_BY_BLOCK": "Nombre moyen de transactions / bloc", - "TX_RANGE_DURATION_DIVIDER": "Unité de temps :", - "TX_RANGE_DURATION": { - "HOUR": "Heure", - "DAY": "Jour", - "MONTH": "Mois" - } + "TX_AVG_BY_BLOCK": "Nombre moyen de transactions / bloc" + }, "CURRENCY": { "MONETARY_MASS_TITLE": "Evolution de la masse monétaire", @@ -2584,15 +3865,20 @@ $translateProvider.translations("fr-FR", { } }, "DOC_STATS": { - "TITLE": "Statistiques de stockage", + "TITLE": "Statistiques de stockage (Cesium+)", "USER": { "TITLE": "Nombre de documents liés à un compte", "USER_PROFILE": "Profils utilisateur", - "USER_SETTINGS": "Paramètres sauvegardés", + "USER_SETTINGS": "Paramètres sauvegardés" + }, + "USER_DELTA": { + "TITLE": "Variation du nombre de documents liés à un compte", + "USER_PROFILE": "Profils utilisateur", + "USER_SETTINGS": "Paramètres sauvegardés" }, "MESSAGE": { - "TITLE": "Nombre de documents lié à la communication", - "MESSAGE_INBOX": "Messages en boite de réception", + "TITLE": "Nombre de documents liés à la communication", + "MESSAGE_INBOX": "Messages en boîte de réception", "MESSAGE_OUTBOX": "Messages envoyés sauvegardés", "INVITATION_CERTIFICATION": "Invitations à certifier" }, @@ -2600,11 +3886,11 @@ $translateProvider.translations("fr-FR", { "TITLE": "Nombre de pages ou groupes", "PAGE_COMMENT": "Commentaires", "PAGE_RECORD": "Pages", - "GROUP_RECORD": "Groupes", + "GROUP_RECORD": "Groupes" }, "OTHER": { "TITLE": "Autres documents", - "HISTORY_DELETE": "Suppressions de documents", + "HISTORY_DELETE": "Suppressions de documents" } }, "SYNCHRO": { @@ -2618,17 +3904,131 @@ $translateProvider.translations("fr-FR", { "PEER": { "TITLE": "Noeuds requêtés", "ES_USER_API": "Noeuds données utilisateurs", - "ES_SUBSCRIPTION_API": "Noeuds services en lignes" + "ES_SUBSCRIPTION_API": "Noeuds services en ligne" }, "PERFORMANCE": { - "TITLE": "Performances d'execution", - "DURATION": "Temps d'execution (ms)" + "TITLE": "Performances d'exécution", + "DURATION": "Temps d'exécution (ms)" } } } } ); +$translateProvider.translations("it-IT", { + "NETWORK": { + "VIEW": { + "BTN_GRAPH": "Statistiche" + } + }, + "GRAPH": { + "COMMON": { + "LINEAR_SCALE" : "Scala lineare", + "LOGARITHMIC_SCALE" : "Scala logaritmica", + "BTN_SHOW_STATS": "Vedere le statistiche", + "BTN_SHOW_DETAILED_STATS": "Statistiche dettagliate", + "RANGE_DURATION_DIVIDER": "Unità di tempo :", + "RANGE_DURATION": { + "HOUR": "Ora", + "DAY": "Giorno", + "MONTH": "Mese" + } + }, + "ACCOUNT": { + "TITLE": "Statistiche", + "BTN_SHOW_STATS": "Visualizzare le statistiche del conto", + "BALANCE_DIVIDER": "Situazione del conto", + "BALANCE_TITLE": "Evoluzione del conto {{pubkey|formatPubkey}}", + "TX_RECEIVED_LABEL": "Incassi", + "TX_SENT_LABEL": "Spese", + "TX_ACCUMULATION_LABEL": "Bilancio delle transazioni", + "UD_LABEL": "DU", + "UD_ACCUMULATION_LABEL": "Bilancio dei DU", + "BALANCE_LABEL": "Saldo", + "WOT_DIVIDER": "Tela di fiducia", + "CERTIFICATION_TITLE": "Numero di certificazioni - {{pubkey|formatPubkey}}", + "RECEIVED_CERT_LABEL": "Totale ricevute", + "RECEIVED_CERT_DELTA_LABEL": "Variazione ricevute", + "GIVEN_CERT_LABEL": "Totale inviate", + "GIVEN_CERT_DELTA_LABEL": "Variazione inviate", + "INPUT_CHART_TITLE": "Somma dei flussi in entrata, par emittente :", + "OUTPUT_CHART_TITLE": "Somma dei flussi in uscita, per destinatario :" + }, + "BLOCKCHAIN": { + "TITLE": "Statistiche", + "BLOCKS_ISSUERS_DIVIDER": "Analisi della ripartizione del calcolo", + "BLOCKS_ISSUERS_HELP": "<b>{{issuerCount|formatInteger}} membri</b> hanno calcolato <b>{{blockCount|formatInteger}} blocchi</b>", + "BLOCKS_ISSUERS_TITLE": "Numero di blocchi calcolati a membro", + "BLOCKS_ISSUERS_LABEL": "Numero di blocchi", + "TX_DIVIDER": "Analisi delle transazioni", + "TX_AMOUNT_TITLE": "Volume delle transazioni", + "TX_AMOUNT_PUBKEY_TITLE": "Volume delle transazioni calcolato da {{issuer | formatPubkey}}", + "TX_AMOUNT_LABEL": "Volume scambiato", + "TX_COUNT_TITLE": "Numero di transazioni scritte", + "TX_COUNT_LABEL": "Numero di transazioni", + "TX_AVG_BY_BLOCK": "Numero medio di transazioni / blocco" + }, + "CURRENCY": { + "MONETARY_MASS_TITLE": "Evoluzione della massa monetaria", + "MONETARY_MASS_LABEL": "Massa monetaria", + "MONETARY_MASS_SHARE_LABEL": "Media a membro", + "UD_TITLE": "Evoluzione del Dividendo Universale", + "MEMBERS_COUNT_TITLE": "Evoluzione del numero di membri", + "MEMBERS_COUNT_LABEL": "Numero di membri" + }, + "PEER": { + "VIEW": { + "BLOCK_COUNT_LABEL": "Numero di blocchi calcolati", + "BLOCK_COUNT": "{{count}} blocchi", + "NO_BLOCK": "Nessun blocco" + } + }, + "DOC_STATS": { + "TITLE": "Statistiche di stoccaggio", + "USER": { + "TITLE": "Numero di documenti legati ad un conto", + "USER_PROFILE": "Profili dell'utente", + "USER_SETTINGS": "Impostazioni salvate", + }, + "MESSAGE": { + "TITLE": "Numero di documenti legati alla conversazione", + "MESSAGE_INBOX": "Messaggi in arrivo", + "MESSAGE_OUTBOX": "Messaggi inviati salvati", + "INVITATION_CERTIFICATION": "Invitazioni da certificare" + }, + "SOCIAL": { + "TITLE": "Numero di pagine o gruppi", + "PAGE_COMMENT": "Commenti", + "PAGE_RECORD": "Pagine", + "GROUP_RECORD": "Gruppi", + }, + "OTHER": { + "TITLE": "Altri documenti", + "HISTORY_DELETE": "Cronologia eliminazione documenti", + } + }, + "SYNCHRO": { + "TITLE": "Statistiche di sincronizzazioni", + "COUNT": { + "TITLE": "Volume sincronizzato", + "INSERTS": "Inserimenti", + "UPDATES": "Aggiornamenti", + "DELETES": "Eliminazioni" + }, + "PEER": { + "TITLE": "Nodi interrogati", + "ES_USER_API": "Nodi dati utenti", + "ES_SUBSCRIPTION_API": "Noeuds servizi online" + }, + "PERFORMANCE": { + "TITLE": "Prestazioni (performance) di esecuzione", + "DURATION": "Tempo di esecuzione (ms)" + } + } + } + } +); + $translateProvider.translations("nl-NL", { "NETWORK": { "VIEW": { @@ -2640,11 +4040,17 @@ $translateProvider.translations("nl-NL", { "LINEAR_SCALE" : "Lineaire schaal", "LOGARITHMIC_SCALE" : "Logaritmische schaal", "BTN_SHOW_STATS": "Zie statistieken", - "BTN_SHOW_DETAILED_STATS": "Gedetailleerde statistieken" + "BTN_SHOW_DETAILED_STATS": "Gedetailleerde statistieken", + "RANGE_DURATION_DIVIDER": "Stap eenheid:", + "RANGE_DURATION": { + "HOUR": "Groep per <b>uur</b>", + "DAY": "Groep per <b>dag</b>", + "MONTH": "Groep per <b>maand</b>" + } }, "ACCOUNT": { - "INPUT_CHART_TITLE": "Som van de binnenkomende stroom, door de zender:", - "OUTPUT_CHART_TITLE": "Som van de uitstroom per bestemming:" + "INPUT_CHART_TITLE": "Som van de binnenkomende stroom, door de zender:", + "OUTPUT_CHART_TITLE": "Som van de uitstroom per bestemming:" }, "BLOCKCHAIN": { "TITLE": "Statistieken", @@ -2658,12 +4064,7 @@ $translateProvider.translations("nl-NL", { "TX_AMOUNT_LABEL": "Verhandeld volume", "TX_COUNT_TITLE": "Aantal schriftelijke transacties", "TX_COUNT_LABEL": "Aantal transacties", - "TX_AVG_BY_BLOCK": "Gemiddeld aantal transacties / blok", - "TX_RANGE_DURATION": { - "HOUR": "Groep per <b>uur</b>", - "DAY": "Groep per <b>dag</b>", - "MONTH": "Groep per <b>maand</b>" - } + "TX_AVG_BY_BLOCK": "Gemiddeld aantal transacties / blok" }, "CURRENCY": { "MONETARY_MASS_TITLE": "Evolutie van de monetaire massa", @@ -2699,7 +4100,7 @@ $translateProvider.translations("en-GB", { }, "WOT": { "LOOKUP": { - "BTN_MAP": "Members map", + "BTN_MAP": "Map", "BTN_MAP_HELP": "Open members map" }, "VIEW": { @@ -2777,7 +4178,7 @@ $translateProvider.translations("en", { }, "WOT": { "LOOKUP": { - "BTN_MAP": "Members map", + "BTN_MAP": "Map", "BTN_MAP_HELP": "Open members map" }, "VIEW": { @@ -2833,6 +4234,84 @@ $translateProvider.translations("en", { } ); +$translateProvider.translations("eo-EO", { + "MAP": { + "COMMON": { + "SEARCH_DOTS": "Traserĉi...", + "BTN_LOCALIZE_ME": "Lokalizi min" + }, + "NETWORK": { + "LOOKUP": { + "BTN_MAP": "Mapo", + "BTN_MAP_HELP": "Malfermi la mapon pri nodoj" + }, + "VIEW": { + "TITLE": "Mapo pri nodoj", + "LAYER": { + "MEMBER": "Membro-nodoj", + "MIRROR": "Spegul-nodoj", + "OFFLINE": "Nekonektitaj nodoj" + } + } + }, + "WOT": { + "LOOKUP": { + "BTN_MAP": "Mapo", + "BTN_MAP_HELP": "Malfermi la mapon pri membroj" + }, + "VIEW": { + "TITLE": "Mapo pri membroj", + "LAYER": { + "MEMBER": "<i class=\"icon ion-person positive\"></i> Membroj", + "PENDING": "<i class=\"icon ion-clock energized\"></i> AliÄoj atendantaj", + "WALLET": "<i class=\"icon ion-card gray\"></i> Simplaj monujoj" + } + }, + "ERROR": { + "LOAD_POSITION_FAILED": "Neeblas ricevi la lokojn afiÅotajn." + } + }, + "REGISTRY": { + "LOOKUP": { + "BTN_MAP": "Mapo", + "BTN_MAP_HELP": "Malfermi la mapon pri paÄoj" + }, + "VIEW": { + "TITLE": "Mapo pri paÄoj", + "LAYER": { + "SHOP": "<i class=\"icon ion-page-shop positive\"></i> Lokaj komercoj", + "COMPANY": "<i class=\"icon ion-page-company positive\"></i> Entreprenoj", + "ASSOCIATION": "<i class=\"icon ion-page-association energized\"></i> Asocioj", + "INSTITUTION": "<i class=\"icon ion-page-institution gray\"></i> Institucioj" + } + } + }, + "PROFILE": { + "MARKER_HELP": "<b>Åœovu-demetu</b> tiun ĉi markilon por <b>aktualigi<br/> vian lokon</b> sur la mapo, aÅ uzu la serĉo-butonon<br/>super la mapo." + }, + "ERROR": { + "LOCALIZE_ME_FAILED": "Neeblas ricevi vian nunan lokon" + }, + "SETTINGS": { + "MAP_DIVIDER": "Mapoj", + "ENABLE_GOOGLE_API": "Aktivigi la Google-API-servojn?", + "ENABLE_GOOGLE_API_HELP": "Ebligas afiÅi sur la <b>mapo pri membroj</b> kontojn kun adreso sed sen iu GPS-lokalizo.", + "GOOGLE_API_KEY": "Google-API-Ålosilo", + "BTN_GOOGLE_API": "Ekhavi Ålosilon", + "BTN_GOOGLE_API_WARNING": "Necesigas havi Google-konton", + "GOOGLE_API_KEY_PLACEHOLDER": "Ekzemple: AIzaqyAgszvWm0tM81x1sMK_ipDHBI7EowLqR7I" + }, + "HELP": { + "TIP": { + "WOT": "Tiu ĉi mapo afiÅas <b>la profilojn kun loko</b>, ĉu ili rilatas al membro-kontoj aÅ ne.<br/><br/>Nur videblas la profiloj, kies kromaĵo "aperi sur la mapo" estis aktivigita.", + "WOT_BTN_LAYERS": "<b>Filtru ĉi tie la afiÅitajn datenojn</b>: membroj, aliÄoj atendantaj, simplaj monujoj, ktp.", + "WOT_BTN_SEARCH": "Vi povas <b>efektivigi serĉadon</b> laÅ nomo, publika Ålosilo aÅ membro-pseÅdonimo." + } + } + } +} +); + $translateProvider.translations("fr-FR", { "MAP": { "COMMON": { @@ -2848,7 +4327,7 @@ $translateProvider.translations("fr-FR", { "TITLE": "Carte des noeuds", "LAYER": { "MEMBER": "NÅ“uds membre", - "MIRROR": "NÅ“uds mirroir", + "MIRROR": "NÅ“uds miroir", "OFFLINE": "NÅ“uds hors ligne" } } @@ -2886,7 +4365,7 @@ $translateProvider.translations("fr-FR", { } }, "PROFILE": { - "MARKER_HELP": "<b>Glissez-déposez</b> ce marqueur pour <b>mettre<br/>à jour votre position</b> sur la carte, ou utilisez le bouton<br/>de recherche au dessus de la carte." + "MARKER_HELP": "<b>Glissez-déposez</b> ce marqueur pour <b>mettre<br/>à jour votre position</b> sur la carte, ou utilisez le bouton<br/>de recherche au-dessus de la carte." }, "ERROR": { "LOCALIZE_ME_FAILED": "Impossible de récupérer votre position actuelle" @@ -2897,13 +4376,13 @@ $translateProvider.translations("fr-FR", { "ENABLE_GOOGLE_API_HELP": "Permet l'affichage dans la <b>carte des membres</b> des comptes ayant une adresse mais aucun positionnement GPS.", "GOOGLE_API_KEY": "Clé d'API Google", "BTN_GOOGLE_API": "Obtenir une clé", - "BTN_GOOGLE_API_WARNING": "nécessite d'avoir un compte Google", - "GOOGLE_API_KEY_PLACEHOLDER": "Exemple: AIzaqyAgszvWm0tM81x1sMK_ipDHBI7EowLqR7I" + "BTN_GOOGLE_API_WARNING": "Nécessite d'avoir un compte Google", + "GOOGLE_API_KEY_PLACEHOLDER": "Exemple : AIzaqyAgszvWm0tM81x1sMK_ipDHBI7EowLqR7I" }, "HELP": { "TIP": { - "WOT": "Cette carte affiche <b>les profils ayant une position</b>, qu'ils correspondent à des comptes membre ou non.<br/><br/>Seuls sont visibles les profils dont l'option "apparaitre sur le carte" a été activée.", - "WOT_BTN_LAYERS": "<b>Filtrez ici les données affichées</b>: membres, inscriptions en attente, simples portefeuilles, etc.", + "WOT": "Cette carte affiche <b>les profils ayant une position</b>, qu'ils correspondent à des comptes membre ou non.<br/><br/>Seuls sont visibles les profils dont l'option "apparaître sur la carte" a été activée.", + "WOT_BTN_LAYERS": "<b>Filtrez ici les données affichées</b> : membres, inscriptions en attente, simples portefeuilles, etc.", "WOT_BTN_SEARCH": "Vous pouvez <b>effectuer une recherche</b> par nom, clef publique ou pseudonyme de membre." } } @@ -2911,6 +4390,84 @@ $translateProvider.translations("fr-FR", { } ); +$translateProvider.translations("it-IT", { + "MAP": { + "COMMON": { + "SEARCH_DOTS": "Ricerca...", + "BTN_LOCALIZE_ME": "Trovami" + }, + "NETWORK": { + "LOOKUP": { + "BTN_MAP": "Mappa dei peers", + "BTN_MAP_HELP": "Aprire mappa dei peers" + }, + "VIEW": { + "TITLE": "Mappa dei peers", + "LAYER": { + "MEMBER": "Peers membri", + "MIRROR": "Peers specchi", + "OFFLINE": "Peers offline" + } + } + }, + "WOT": { + "LOOKUP": { + "BTN_MAP": "Mappa dei membri", + "BTN_MAP_HELP": "Aprire mappa dei membri" + }, + "VIEW": { + "TITLE": "Mappa membri", + "LAYER": { + "MEMBER": "<i class=\"icon ion-person positive\"></i> Membri", + "PENDING": "<i class=\"icon ion-clock energized\"></i> Registrazione pendenti", + "WALLET": "<i class=\"icon ion-card gray\"></i> Portafogli osservatori" + } + }, + "ERROR": { + "LOAD_POSITION_FAILED": "Errore nel caricamento delle posizioni." + } + }, + "REGISTRY": { + "LOOKUP": { + "BTN_MAP": "Mappa", + "BTN_MAP_HELP": "Aprire la mappa delle pagine pro" + }, + "VIEW": { + "TITLE": "Mappa delle pagine pro", + "LAYER": { + "SHOP": "<i class=\"icon ion-page-shop positive\"></i> Negozi locali", + "COMPANY": "<i class=\"icon ion-page-company positive\"></i> Aziende", + "ASSOCIATION": "<i class=\"icon ion-page-association energized\"></i> Associazioni", + "INSTITUTION": "<i class=\"icon ion-page-institution gray\"></i> Instituti" + } + } + }, + "PROFILE": { + "MARKER_HELP": "<b>Drag and drop</b> questo indicatore per <b>aggiornare<br/>tua posizione</b>, o usa i bottoni <br/>sopra la mappa." + }, + "ERROR": { + "LOCALIZE_ME_FAILED": "Impossible trovare tua posizione attuale" + }, + "SETTINGS": { + "MAP_DIVIDER": "Mappe", + "ENABLE_GOOGLE_API": "Abilitare i servizi Google API ?", + "ENABLE_GOOGLE_API_HELP": "Sulla <b>mappa dei membri</b>, ti permette di visualizzare i conti con un indirizzo ma senza geolocalizzazione.", + "GOOGLE_API_KEY": "Chiave Google API", + "BTN_GOOGLE_API": "Ottenere una chiave", + "BTN_GOOGLE_API_WARNING": "necessita un conto Google", + "GOOGLE_API_KEY_PLACEHOLDER": "per es. : AIzaqyAgszvWm0tM81x1sMK_ipDHBI7EowLqR7I" + }, + "HELP": { + "TIP": { + "WOT": "Questa mappa mostra <b>profili che hanno fornito una posizione</b>, che siano conti membri o no.<br/><br/>Solo i profili che hanno attivato l'opzione "apparire sulla mappa" sono stati attivati.", + "WOT_BTN_LAYERS": "<b>Filtrare i dati visibili</b>: membri, registrazioni pendenti, portafogli osservatori, etc.", + "WOT_BTN_SEARCH": "Puoi <b>cercare</b> per nome, chiave pubblica, o pseudonimo del membro." + } + } + } + } + ); + $translateProvider.translations("fr-FR", { "RML9": { "BTN_EXPORT": "Télécharger", diff --git a/assets/www/i18n/locale-en-GB.json b/assets/www/i18n/locale-en-GB.json index f23838522a8a7bf23ddd751b64ee31e802f6738c..60c0deb561146e3e342e5bb16326b4351fc7615a 100644 --- a/assets/www/i18n/locale-en-GB.json +++ b/assets/www/i18n/locale-en-GB.json @@ -17,9 +17,10 @@ "BTN_YES_CONTINUE": "Yes, Continue", "BTN_SHOW": "Show", "BTN_SHOW_PUBKEY": "Show key", - "BTN_RELATIVE_UNIT": "Use relative unit", + "BTN_RELATIVE_UNIT": "Display amounts in UD?", "BTN_BACK": "Back", "BTN_NEXT": "Next", + "BTN_IMPORT": "Import", "BTN_CANCEL": "Cancel", "BTN_CLOSE": "Close", "BTN_LATER": "Later", @@ -36,7 +37,7 @@ "BTN_START": "Start", "BTN_CONTINUE": "Continue", "BTN_CREATE": "Create", - "BTN_UNDERSTOOD": "I understood", + "BTN_UNDERSTOOD": "I understand", "BTN_OPTIONS": "Options", "BTN_HELP_TOUR": "Features tour", "BTN_HELP_TOUR_SCREEN": "Discover this screen", @@ -48,6 +49,7 @@ "NO_ACCOUNT_QUESTION": "Not a member yet? Register now!", "SEARCH_NO_RESULT": "No result found", "LOADING": "Loading...", + "LOADING_WAIT": "Loading...<br/><small>(Waiting for node availability)</small>", "SEARCHING": "Searching...", "FROM": "From", "TO": "To", @@ -77,6 +79,12 @@ "SHARE_ON_FACEBOOK": "Share on Facebook", "SHARE_ON_DIASPORA": "Share on Diaspora*", "SHARE_ON_GOOGLEPLUS": "Share on Google+" + }, + "FILE": { + "DATE" : "Date:", + "TYPE" : "Type:", + "SIZE": "Size:", + "VALIDATING": "Validating..." } }, "SYSTEM": { @@ -89,6 +97,7 @@ "WOT": "Registry", "CURRENCY": "Currency", "ACCOUNT": "My Account", + "WALLETS": "My wallets", "TRANSFER": "Transfer", "SCAN": "Scan", "SETTINGS": "Settings", @@ -97,14 +106,16 @@ }, "ABOUT": { "TITLE": "About", - "LICENSE": "<b>Free/libre software</b> (License GNU GPLv3).", + "LICENSE": "<b>Free/libre software</b> (License GNU AGPLv3).", "LATEST_RELEASE": "There is a <b>newer version</ b> of {{'COMMON.APP_NAME' | translate}} (<b>v{{version}}</b>)", "PLEASE_UPDATE": "Please update {{'COMMON.APP_NAME' | translate}} (latest version: <b>v{{version}}</b>)", "CODE": "Source code:", + "OFFICIAL_WEB_SITE": "Official web site:", "DEVELOPERS": "Developers:", "FORUM": "Forum:", "PLEASE_REPORT_ISSUE": "Please report any issue to us!", - "REPORT_ISSUE": "Report an issue" + "REPORT_ISSUE": "Report an issue", + "BTN_OPEN_DEV_WINDOW": "Open the debug window" }, "HOME": { "TITLE": "Cesium", @@ -120,18 +131,27 @@ }, "SETTINGS": { "TITLE": "Settings", + "DISPLAY_DIVIDER": "Display", + "STORAGE_DIVIDER": "Storage", "NETWORK_SETTINGS": "Network", "PEER": "Duniter peer address", + "PEER_SHORT": "Peer address", "PEER_CHANGED_TEMPORARY": "Address used temporarily", "USE_LOCAL_STORAGE": "Enable local storage", "USE_LOCAL_STORAGE_HELP": "Allows you to save your settings", + "WALLETS_SETTINGS": "My wallets", + "USE_WALLETS_ENCRYPTION": "Secure the list", + "USE_WALLETS_ENCRYPTION_HELP": "Enables you to encrypt the list of your wallets. Authentication required to access it.", "ENABLE_HELPTIP": "Enable contextual help tips", "ENABLE_UI_EFFECTS": "Enable visual effects", "HISTORY_SETTINGS": "Account operations", "DISPLAY_UD_HISTORY": "Display produced dividends?", + "TX_HISTORY_AUTO_REFRESH": "Enable automatic refresh?", + "TX_HISTORY_AUTO_REFRESH_HELP": "Updates the list of operations to each new block.", "AUTHENTICATION_SETTINGS": "Authentication", "KEEP_AUTH": "Expiration of authentication", - "KEEP_AUTH_HELP": "Define when authentication is cleared from memory", + "KEEP_AUTH_SHORT": "Expiration", + "KEEP_AUTH_HELP": "Define when authentication is cleared from memory.", "KEEP_AUTH_OPTION": { "NEVER": "After each operation", "SECONDS": "After {{value}}s of inactivity", @@ -140,12 +160,21 @@ "HOUR": "After {{value}}h of inactivity", "ALWAYS": "At the end of the session" }, + "KEYRING_FILE": "Keyring file", + "KEYRING_FILE_HELP": "Allow auto-connect at startup, or to authenticate (only if \"Expiration of authentication\" is \"at the end of the session\"", "REMEMBER_ME": "Remember me ?", "REMEMBER_ME_HELP": "Allows to remain identified from one session to another, keeping the public key locally.", "PLUGINS_SETTINGS": "Extensions", "BTN_RESET": "Restore default values", "EXPERT_MODE": "Enable expert mode", "EXPERT_MODE_HELP": "Allow to see more details", + "BLOCK_VALIDITY_WINDOW": "Block uncertainty time", + "BLOCK_VALIDITY_WINDOW_SHORT": "Time of uncertainty", + "BLOCK_VALIDITY_WINDOW_HELP": "Time to wait before considering an information is validated", + "BLOCK_VALIDITY_OPTION": { + "NONE": "No delay", + "N": "{{time | formatDuration}} ({{count}} blocks)" + }, "POPUP_PEER": { "TITLE" : "Duniter peer", "HOST" : "Address", @@ -280,15 +309,18 @@ "PEERS": "Peers", "SIGNED_ON_BLOCK": "Signed on block", "MIRROR": "mirror", - "MIRRORS": "Mirror peers", + "MIRRORS": "Mirrors", + "MIRROR_PEERS": "Mirror peers", "PEER_LIST" : "Peer's list", - "MEMBERS" : "Member peers", + "MEMBERS" : "Members", + "MEMBER_PEERS" : "Member peers", "ALL_PEERS" : "All peers", "DIFFICULTY" : "Difficulty", "API" : "API", "CURRENT_BLOCK" : "Block #", "POPOVER_FILTER_TITLE": "Filter", - "OFFLINE": "Offline peers", + "OFFLINE": "Offline", + "OFFLINE_PEERS": "Offline peers", "BTN_SHOW_PEER": "Show peer", "VIEW": { "TITLE": "Peer", @@ -338,7 +370,7 @@ "PENDING": "Pending registrations:", "PENDING_COUNT": "{{count}} pending registrations", "REGISTERED": "Registered {{sigDate | formatFromNow}}", - "MEMBER_FROM": "Member since {{memberDate|formatFromNowShort}}", + "MEMBER_FROM": "Member since {{memberDate|medianFromNowShort}}", "BTN_NEWCOMERS": "Latest members", "BTN_PENDING": "Pending registrations", "SHOW_MORE": "Show more", @@ -380,14 +412,17 @@ "SCRYPT_FORM_HELP": "Please enter your credentials. <br> Remember to check the public key for your account.", "PUBKEY_FORM_HELP": "Please enter a public account key:", "FILE_FORM_HELP": "Choose the keychain file to use:", + "SCAN_FORM_HELP": "Scan the QR code of a wallet.", "SALT": "Secret identifier", "SALT_HELP": "Secret identifier", "SHOW_SALT": "Display secret identifier?", "PASSWORD": "Password", "PASSWORD_HELP": "Password", - "PUBKEY_HELP": "Example: « AbsxSY4qoZRzyV2irfep1V9xw1EMNyKJw2TkuVD4N1mv »", + "PUBKEY_HELP": "Public key or pseudonym", "NO_ACCOUNT_QUESTION": "Don't have an account yet?", + "HAVE_ACCOUNT_QUESTION": "Already have an account ?", "CREATE_ACCOUNT": "Create an account", + "CREATE_FREE_ACCOUNT": "Create a free account", "FORGOTTEN_ID": "Forgot password?", "ASSOCIATED_PUBKEY": "Public key :", "BTN_METHODS": "Other methods", @@ -402,10 +437,11 @@ "IDLE_WARNING": "You will be logout... {{countdown}}" }, "METHOD": { - "SCRYPT_DEFAULT": "Standard salt (default)", + "SCRYPT_DEFAULT": "Secret identifier and password", "SCRYPT_ADVANCED": "Advanced salt", "FILE": "Keychain file", - "PUBKEY": "Public key only" + "PUBKEY": "Public key or pseudonym", + "SCAN": "Scan a QR code" }, "SCRYPT": { "SIMPLE": "Light salt", @@ -419,44 +455,47 @@ "p": "p (CPU):" }, "FILE": { - "DATE" : "Date:", - "TYPE" : "Type:", - "SIZE": "Size:", - "VALIDATING": "Validating...", "HELP": "Expected file format: <b>.dunikey</b> (type PubSec). Other formats are under development (EWIF, WIF)." } }, "AUTH": { "TITLE": "<i class=\"icon ion-locked\"></i> Authentication", - "METHOD_LABEL": "Authentication method", "BTN_AUTH": "Authenticate", - "SCRYPT_FORM_HELP": "Please authenticate yourself:" + "GENERAL_HELP": "Please authenticate yourself:", + "EXPECTED_UID_HELP": "Please authenticate to the account <i class=\"ion-person\"></i> {{uid}}:", + "EXPECTED_PUBKEY_HELP": "Please authenticate to the wallet <i class=\"ion-key\"></i> {{pubkey|formatPubkey}}:", + "SCAN_FORM_HELP": "Scan the QR code of the <b>private key</b> of the wallet." }, "ACCOUNT": { "TITLE": "My Account", "BALANCE": "Balance", - "LAST_TX": "Latest transactions", + "LAST_TX": "Latest validated transactions", "BALANCE_ACCOUNT": "Account balance", "NO_TX": "No transaction", "SHOW_MORE_TX": "Show more", "SHOW_ALL_TX": "Show all", - "TX_FROM_DATE": "(current limit to {{fromTime|formatFromNowShort}})", + "TX_FROM_DATE": "(current limit to {{fromTime|medianFromNowShort}})", "PENDING_TX": "Pending transactions", + "VALIDATING_TX": "Transactions being validated", "ERROR_TX": "Transaction not executed", "ERROR_TX_SENT": "Sent transactions", "PENDING_TX_RECEIVED": "Transactions awaiting receipt", "EVENTS": "Events", + "OUT_DISTANCED": "Your current certifications come from a group too isolated from the <a ng-click=\"showHelpModal('wot')\"> Web of Trust</a> (WoT): the <a ng-click=\"showHelpModal('distance_rule')\">maximum distance rule</a> is violated.<br/>You must obtain certifications from another area of the Web of Trust, or wait for it to tighten.", "WAITING_MEMBERSHIP": "Membership application sent. Waiting validation.", - "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member", + "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member and produce the <a ng-click=\"showHelpModal('ud')\">Universal Dividend</a>. Your account is however already operational, to receive and send payments.", + "WAITING_CERTIFICATIONS_HELP": "To get your certifications, only request members <b>who know you enough</b>, as required by <a ng-click=\"showLicenseModal()\">the currency license</a> that you have accepted.<br/>If you do not know enough members, let them know on <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">the user forum</a>.", "WILL_MISSING_CERTIFICATIONS": "You will <b>lack certifications</b> soon (at least {{willNeedCertificationCount}} more are needed)", "WILL_NEED_RENEW_MEMBERSHIP": "Your membership <b>will expire {{membershipExpiresIn|formatDurationTo}}</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a> before then.", "NEED_RENEW_MEMBERSHIP": "You are no longer a member because your membership <b>has expired</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a>.", + "NEED_RENEW_MEMBERSHIP_AFTER_CANCELLED": "You are no longer a member because your membership <b>has been cancelled</b> for lack of certifications. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a>.", "NO_WAITING_MEMBERSHIP": "No membership application pending. If you'd like to <b>become a member</ b>, please <a ng-click=\"doQuickFix('membership')\">send the membership application</a>.", "CERTIFICATION_COUNT": "Received certifications", "CERTIFICATION_COUNT_SHORT": "Certifications", "SIG_STOCK": "Stock of certifications to give", "BTN_RECEIVE_MONEY": "Receive", "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Switch to another identity...", + "BTN_FIX_MEMBERSHIP": "Resubmit membership request...", "BTN_MEMBERSHIP_RENEW": "Renew membership", "BTN_MEMBERSHIP_RENEW_DOTS": "Renew membership...", "BTN_MEMBERSHIP_OUT_DOTS": "Revoke membership...", @@ -512,12 +551,40 @@ "TITLE": "Identity selection", "HELP": "Several <b>different identities</b> have been sent, for the public key <span class=\"gray\"> <i class=\"ion-key\"></i> {{pubkey | formatPubkey}}</span>.<br/>Please select the identity to use:" }, + "SELECT_WALLET_MODAL": { + "TITLE": "Wallet selection" + }, + "WALLET_LIST": { + "TITLE": "My wallets", + "BTN_NEW": "Add a wallet", + "BTN_DOWNLOAD": "Download the list", + "BTN_IMPORT_FILE_DOTS": "Import from a file...", + "NO_WALLET": "No secondary wallet", + "BTN_DELETE": "Remove a secondary wallet...", + "BTN_RENAME": "Rename the wallet", + "EXPORT_FILENAME": "my_wallets-{{pubkey|formatPubkey}}-{{currency}}.csv", + "TOTAL_DOTS": "Total: ", + "EDIT_POPOVER": { + "TITLE": "Rename the wallet", + "HELP": "Fill in the new name", + "NAME_HELP": "Wallet name" + }, + "IMPORT_MODAL": { + "TITLE": "Import secondary wallets", + "HELP": "To <b>import secodnary wallets</b>, please drag the file in the box below, or click in the box to search for a file.", + "WALLET_COUNT": "<b>{{count}}</b> new wallet{{count > 1 ? 's' : ''}}", + "NO_NEW_WALLET": "No new wallet" + } + }, "SECURITY":{ "ADD_QUESTION" : "Add custom question", "BTN_CLEAN" : "Clean", "BTN_RESET" : "Reset", "DOWNLOAD_REVOKE": "Save a revocation file", "DOWNLOAD_REVOKE_HELP" : "Having a revocation file is important, for example in case of loss of identifiers. It allows you to <b>get this account out of the Web Of Trust</b>, thus becoming a simple wallet.", + "GENERATE_KEYFILE": "Generate my keychain file ...", + "GENERATE_KEYFILE_HELP": "Generate a file allowing you to authenticate without entering your identifiers.<br/><b>Warning:</b> this file will contain your secret key; It is therefore very important to put it in a safe place!", + "KEYFILE_FILENAME": "keychain-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Register as member...", "MEMBERSHIP_IN_HELP": "Allows you to <b>transform </b> a simple wallet account <b>into a member account</b>, by sending a membership request. Useful only if you do not already have another member account.", "SEND_IDENTITY": "Publish identity...", @@ -556,7 +623,24 @@ "SAVE_ID": "Save my credentials...", "SAVE_ID_HELP": "Creating a backup file, to <b>retrieve your password</b> (and the secret identifier) <b> in case of forgetting</b>. The file is <b>secured</ b> (encrypted) using personal questions.", "STRONG_LEVEL": "Strong <span class=\"hidden-xs \">(6 questions minimum)</span>", - "TITLE": "Account and security" + "TITLE": "Account and security", + "KEYFILE": { + "PUBSEC_FORMAT": "PubSec format.", + "PUBSEC_FORMAT_HELP": "This file format is compatible in particular with Cesium and Gannonce. Your keychain is stored <b>without encryption</b>: anyone with a copy of this file will be able to empty your account.", + "WIF_FORMAT": "Wallet Import Format (WIF)", + "WIF_FORMAT_HELP": "This format is used in particular by paper wallets. Your keychain is stored <b>without encryption</b>: anyone with a copy of this file will be able to empty your account.", + "EWIF_FORMAT": "Encrypted Wallet Import Format (WIF)", + "EWIF_FORMAT_HELP": "This format is used in particular by paper wallets. However, <b>the keychain is encrypted</b> from a passphrase of your choice.", + "PASSWORD_POPUP": { + "TITLE": "Keychain file encrypted", + "HELP": "Please enter the passphrase:", + "PASSWORD_HELP": "Passphrase" + }, + "ERROR": { + "BAD_PASSWORD": "Bad passphrase", + "BAD_CHECKSUM": "Bad checksum" + } + } }, "FILE_NAME": "{{currency}} - Account statement {{pubkey|formatPubkey}} to {{currentTime|formatDateForFile}}.csv", "HEADERS": { @@ -568,6 +652,7 @@ "TRANSFER": { "TITLE": "Transfer", "SUB_TITLE": "Transfer money", + "SUB_TITLE_ALL": "Empty the account", "FROM": "From", "TO": "To", "AMOUNT": "Amount", @@ -576,15 +661,20 @@ "COMMENT_HELP": "Comment (optional)", "BTN_SEND": "Send", "BTN_ADD_COMMENT": "Add a comment", + "REST": "Rest of account", + "REST_TO": "to", "WARN_COMMENT_IS_PUBLIC": "Please note that <b>comments are public</b> (not encrypted).", "MODAL": { "TITLE": "Transfer" } }, "ERROR": { + "UNKNOWN_URI_FORMAT": "Unknown URI format", + "PUBKEY_INVALID_CHECKSUM": "Invalid public key (bad checksum).", "POPUP_TITLE": "Error", "UNKNOWN_ERROR": "Unknown error", "CRYPTO_UNKNOWN_ERROR": "Your browser is not compatible with cryptographic features.", + "DOWNLOAD_KEYFILE_FAILED": "Failed to generate the keychain file.", "EQUALS_TO_PSEUDO": "Must be different from pseudonym", "EQUALS_TO_SALT": "Must be different from secret identifier", "FIELD_REQUIRED": "This field is required.", @@ -634,7 +724,9 @@ "INVALID_USER_ID": "Field 'pseudonym' must not contains spaces or special characters.", "INVALID_COMMENT": "Field 'reference' has a bad format.", "INVALID_PUBKEY": "Public key has a bad format.", - "IDENTITY_REVOKED": "This identity <b>has been revoked {{revocationTime|formatFromNow}}</b> ({{revocationTime|formatDate}}). It can no longer become a member.", + "INVALID_PUBKEY_CHECKSUM": "Invalid checksum.", + "IDENTITY_REVOKED": "This identity <b>has been revoked</b>. It can no longer become a member.", + "IDENTITY_REVOKED_WITH_TIME": "This identity <b>has been revoked {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). It can no longer become a member.", "IDENTITY_PENDING_REVOCATION": "The <b>revocation of this identity</b> has been requested and is awaiting processing. Certification is therefore disabled.", "IDENTITY_INVALID_BLOCK_HASH": "This membership application is no longer valid (because it references a block that network peers are cancelled): the person must renew its application for membership <b>before</b> being certified.", "IDENTITY_EXPIRED": "This identity has expired: this person must re-apply <b>before</b> being certified.", @@ -657,6 +749,7 @@ "LOAD_NEWCOMERS_FAILED": "Unable to load new members.", "LOAD_PENDING_FAILED": "Unable to load pending registrations.", "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "You must <b>be a member</b> in order to perform this action.", + "ONLY_MEMBER_OR_WAS_MEMBER_CAN_EXECUTE_THIS_ACTION": "You must <b>be a member (or old member)</b> in order to perform this action.", "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "You must have <b>published your identity</b> in order to perform this action.", "GET_BLOCK_FAILED": "Error while getting block", "INVALID_BLOCK_HASH": "Block not found (incorrect hash)", @@ -672,7 +765,17 @@ "EXISTING_ACCOUNT_REQUEST": "Please modify your credentials so that they correspond to an unused account.", "GET_LICENSE_FILE_FAILED": "Unable to get license file", "CHECK_NETWORK_CONNECTION": "No peer appears to be accessible.<br/><br/>Please <b>check your Internet connection</b>.", - "ISSUE_524_TX_FAILED": "Failed to transfer.<br/><br/>A message has been sent to developers to help solve the problem.<b>Thank you for your help</b>." + "ISSUE_524_TX_FAILED": "Failed to transfer.<br/><br/>A message has been sent to developers to help solve the problem.<b>Thank you for your help</b>.", + "ADD_SECONDARY_WALLET_FAILED": "Unable to add secondary wallet.", + "UPDATE_WALLET_LIST_FAILED": "Unable to refresh the list of wallets.", + "LOAD_WALLET_LIST_FAILED": "Unable to load the list of wallets.", + "SAVE_WALLET_LIST_FAILED": "Unable to save the list of wallets.", + "COULD_NOT_ADD_MAIN_WALLET": "This wallet <b>is the main account</b> with which you are connected. Unable to add it as a secondary wallet.", + "COULD_NOT_ADD_EXISTING_WALLET": "Wallet already existing in the list.", + "UNKNOWN_WALLET_ID": "Unknown secondary wallet.", + "RESTORE_WALLET_LIST_FAILED": "Unable to restore the list of wallets.", + "INVALID_FILE_FORMAT": "Invalid file format.", + "SAME_TX_RECIPIENT": "The recipient must be different from the issuer." }, "INFO": { "POPUP_TITLE": "Information", @@ -684,6 +787,7 @@ "NOT_NEED_MEMBERSHIP": "Already a member.", "IDENTITY_WILL_MISSING_CERTIFICATIONS": "This identity will soon lack certification (at least {{willNeedCertificationCount}}).", "IDENTITY_NEED_MEMBERSHIP": "This identity did not send a membership request. She will have to if she wishes to become a member.", + "HAS_ALTERNATIVE_IDENTITIES": "There are <b>multiple identities</b> attached to this public key. <b>Before any certification</b>, please <a ng-click=\"doQuickFix('showSelectIdentities')\">check other identities</a> to choose the correct one, or contact the wallet owner.", "REVOCATION_SENT": "Revocation sent successfully", "REVOCATION_SENT_WAITING_PROCESS": "Revocation <b>has been sent successfully</b>. It is awaiting processing.", "FEATURES_NOT_IMPLEMENTED": "This features is not implemented yet.<br/><br/>Why not to contribute to get it faster? ;)", @@ -695,7 +799,10 @@ "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Security warning</b>", "CERTIFY_RULES_TITLE_UID": "Certify {{uid}}", "CERTIFY_RULES": "<b class=\"assertive\">Don't certify an account</b> if you believe that: <ul><li>1.) the issuers identity might be faked.<li>2.) the issuer already has another certified account.<li>3.) the issuer purposely or carelessly violates rule 1 or 2 (he certifies faked or double accounts).</ul></small><br/>Are you sure you want to certify this identity?", + "FULLSCREEN": "View the application in full screen?", + "EXIT_APP": "Close the application ?", "TRANSFER": "<b>Transfer summary:</b><br/><br/><ul><li> - From: <b>{{from}}</b></li><li> - To: <b>{{to}}</b></li><li> - Amount: <b>{{amount}} {{unit}}</b></li><li> - Comment: <i>{{comment}}</i></li></ul><br/><b>Are-you sure you want to do this transfer?</b>", + "TRANSFER_ALL": "<b>Transfer summary:</b><br/><br/><ul><li> - From: <b>{{from}}</b></li><li> - To: <b>{{to}}</b></li><li> - Amount: <b>{{amount}} {{unit}}</b></li><li> - Comment: <i>{{comment}}</i></li><br/><li> - Rest : <b>{{restAmount}} {{unit}}</b> to <b>{{restTo}}</b></li></ul><br/><b>Are-you sure you want to do this transfer?</b>", "MEMBERSHIP_OUT": "This operation is <b>irreversible</b>.<br/></br/><b>Are you sure you want to terminate your membership?</b>", "MEMBERSHIP_OUT_2": "This operation is <b>irreversible</b>!<br/><br/>Are you sure you want to <b>terminate your membership</b>?", "LOGIN_UNUSED_WALLET_TITLE": "Typing error?", @@ -741,7 +848,11 @@ "CURRENCY_RULES_DEF": "The currency rules are defined only once, and for all. They set the parameters under which the currency will perform: universal dividend calculation, the amount of certifications needed to become a member, the maximum amount of certifications a member can send, etc.<br/><br/>The parameters cannot be modified because of the use of a <span class=\"text-italic\">Blockchain</span> which carries and executes these rules, and constantly verifies their correct application. <a href=\"#/app/currency\">See current parameters</a>.", "BLOCKCHAIN": "Blockchain", "BLOCKCHAIN_DEF": "The Blockchain is a decentralised system which, in case of Duniter, serves to carry and execute the <span class=\"text-italic\">currency rules</span>.<br/><a href=\"http://en.duniter.org/presentation/\" target=\"_blank\">Read more about Duniter</a> and the working of its blockchain.", - "UNIVERSAL_DIVIDEND_DEF": "The Universal Dividend (UD) is the quantity of money co-created by each member, according to the period and the calculation defined in the <span class=\"text-italic\">currency rules</span>.<br/>Every term, the members receive an equal amount of new money on their account.<br/><br/>The UD undergoes a steady growth, to remain fair under its members (current and future), calculated by an average life expectancy, as demonstrated in the Relative Theory of Money (RTM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Read more about RTM</a> and open money." + "UNIVERSAL_DIVIDEND_DEF": "The Universal Dividend (UD) is the quantity of money co-created by each member, according to the period and the calculation defined in the <span class=\"text-italic\">currency rules</span>.<br/>Every term, the members receive an equal amount of new money on their account.<br/><br/>The UD undergoes a steady growth, to remain fair under its members (current and future), calculated by an average life expectancy, as demonstrated in the Relative Theory of Money (RTM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Read more about RTM</a> and open money.", + "WOT": "Web of Trust (WoT)", + "WOT_DEF": "The Web of Trust is made up of all the members of the currency, and the links of certification which connect them.", + "DISTANCE_RULE": "Distance rule", + "DISTANCE_RULE_DEF": "The rule of distance defines <b>a maximum distance to meet</b> between an applicant and a minimum number of referring member. This distance is calculated using the certification links." }, "TIP": { "MENU_BTN_CURRENCY": "Menu <b>{{'MENU.CURRENCY'|translate}}</b> allows discovery of <b>currency parameters</b> and its state.", @@ -794,7 +905,8 @@ "LINK_DOC": "API documentation", "LINK_DOC_HELP": "API documentation for developers", "LINK_STANDARD_APP": "Standard version", - "LINK_STANDARD_APP_HELP": "Open standard version of {{'COMMON.APP_NAME'|translate}}" + "LINK_STANDARD_APP_HELP": "Open standard version of {{'COMMON.APP_NAME'|translate}}", + "CONNECTION_ERROR": "Peer <b>{{server}}</b> unreachable or invalid address.<br/><br/>Check your Internet connection, or contact the web site administrator." }, "HOME": { "TITLE": "{{'COMMON.APP_NAME'|translate}} API Documentation", @@ -807,9 +919,11 @@ "TITLE_SHORT": "Online payment", "SUMMARY": "Order summary:", "AMOUNT": "Amount:", + "AMOUNTS_HELP": "Please select the amount:", "NAME": "Name:", "PUBKEY": "Public key of the recipient:", "COMMENT": "Order reference:", + "NODE": "Peer address:", "DEMO": { "SALT": "demo", "PASSWORD": "demo", @@ -835,6 +949,7 @@ "DEMO_DIVIDER": "Try it !", "DEMO_HELP": "To test this service, click on this button. The result content will be display below.", "DEMO_RESULT": "Result returned by call:", + "DEMO_RESULT_PEER": "Peer address used:", "DEMO_SUCCEED": "<i class=\"icon ion-checkmark\"></i> Success!", "DEMO_CANCELLED": "<i class=\"icon ion-close\"></i> Canceled by user", "INTEGRATE_DIVIDER": "Website integration", @@ -856,6 +971,8 @@ "PARAM_REDIRECT_URL_HELP": "URL redirection after sending payment, after the payment has been sent. Can contain the following strings, which will be replaced by the values of the transaction: \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\" and \"{pubkey}\".", "PARAM_CANCEL_URL": "URL if cancelled", "PARAM_CANCEL_URL_HELP": "URL in case of cancellation. Can contain the following strings, which will be replaced: \"{comment}\", \"{amount}\" and \"{pubkey}\".", + "PARAM_PREFERRED_NODE": "Preferred Duniter peer", + "PARAM_PREFERRED_NODE_HELP": "Peer address (URL) to use preferably (\"g1.domain.com:443\" or \"https://g1.domain.com\")", "EXAMPLES_HELP": "Examples of integration:", "EXAMPLE_BUTTON": "HTML Button", "EXAMPLE_BUTTON_DEFAULT_TEXT": "Pay in {{currency|abbreviate}}", diff --git a/assets/www/i18n/locale-en.json b/assets/www/i18n/locale-en.json index ce6a86f8565a36770a375354d66c139e78f77844..725db3dbffde55625fbb51841eaffb925306f927 100644 --- a/assets/www/i18n/locale-en.json +++ b/assets/www/i18n/locale-en.json @@ -17,9 +17,10 @@ "BTN_YES_CONTINUE": "Yes, Continue", "BTN_SHOW": "Show", "BTN_SHOW_PUBKEY": "Show key", - "BTN_RELATIVE_UNIT": "Use relative unit", + "BTN_RELATIVE_UNIT": "Display amounts in UD?", "BTN_BACK": "Back", "BTN_NEXT": "Next", + "BTN_IMPORT": "Import", "BTN_CANCEL": "Cancel", "BTN_CLOSE": "Close", "BTN_LATER": "Later", @@ -36,7 +37,7 @@ "BTN_START": "Start", "BTN_CONTINUE": "Continue", "BTN_CREATE": "Create", - "BTN_UNDERSTOOD": "I understood", + "BTN_UNDERSTOOD": "I understand", "BTN_OPTIONS": "Options", "BTN_HELP_TOUR": "Features tour", "BTN_HELP_TOUR_SCREEN": "Discover this screen", @@ -48,6 +49,7 @@ "NO_ACCOUNT_QUESTION": "Not a member yet? Register now!", "SEARCH_NO_RESULT": "No result found", "LOADING": "Loading...", + "LOADING_WAIT": "Loading...<br/><small>(Waiting for node availability)</small>", "SEARCHING": "Searching...", "FROM": "From", "TO": "To", @@ -77,6 +79,12 @@ "SHARE_ON_FACEBOOK": "Share on Facebook", "SHARE_ON_DIASPORA": "Share on Diaspora*", "SHARE_ON_GOOGLEPLUS": "Share on Google+" + }, + "FILE": { + "DATE" : "Date:", + "TYPE" : "Type:", + "SIZE": "Size:", + "VALIDATING": "Validating..." } }, "SYSTEM": { @@ -89,6 +97,7 @@ "WOT": "Registry", "CURRENCY": "Currency", "ACCOUNT": "My Account", + "WALLETS": "My wallets", "TRANSFER": "Transfer", "SCAN": "Scan", "SETTINGS": "Settings", @@ -97,14 +106,16 @@ }, "ABOUT": { "TITLE": "About", - "LICENSE": "<b>Free/libre software</b> (License GNU GPLv3).", + "LICENSE": "<b>Free/libre software</b> (License GNU AGPLv3).", "LATEST_RELEASE": "There is a <b>newer version</ b> of {{'COMMON.APP_NAME' | translate}} (<b>v{{version}}</b>)", "PLEASE_UPDATE": "Please update {{'COMMON.APP_NAME' | translate}} (latest version: <b>v{{version}}</b>)", "CODE": "Source code:", + "OFFICIAL_WEB_SITE": "Official web site:", "DEVELOPERS": "Developers:", "FORUM": "Forum:", "PLEASE_REPORT_ISSUE": "Please report any issue to us!", - "REPORT_ISSUE": "Report an issue" + "REPORT_ISSUE": "Report an issue", + "BTN_OPEN_DEV_WINDOW": "Open the debug window" }, "HOME": { "TITLE": "Cesium", @@ -120,18 +131,27 @@ }, "SETTINGS": { "TITLE": "Settings", + "DISPLAY_DIVIDER": "Display", + "STORAGE_DIVIDER": "Storage", "NETWORK_SETTINGS": "Network", "PEER": "Duniter peer address", + "PEER_SHORT": "Peer address", "PEER_CHANGED_TEMPORARY": "Address used temporarily", "USE_LOCAL_STORAGE": "Enable local storage", "USE_LOCAL_STORAGE_HELP": "Allows you to save your settings", + "WALLETS_SETTINGS": "My wallets", + "USE_WALLETS_ENCRYPTION": "Secure the list", + "USE_WALLETS_ENCRYPTION_HELP": "Enables you to encrypt the list of your wallets. Authentication required to access it.", "ENABLE_HELPTIP": "Enable contextual help tips", "ENABLE_UI_EFFECTS": "Enable visual effects", "HISTORY_SETTINGS": "Account operations", "DISPLAY_UD_HISTORY": "Display produced dividends?", + "TX_HISTORY_AUTO_REFRESH": "Enable automatic refresh?", + "TX_HISTORY_AUTO_REFRESH_HELP": "Updates the list of operations to each new block.", "AUTHENTICATION_SETTINGS": "Authentication", "KEEP_AUTH": "Expiration of authentication", - "KEEP_AUTH_HELP": "Define when authentication is cleared from memory", + "KEEP_AUTH_SHORT": "Expiration", + "KEEP_AUTH_HELP": "Define when authentication is cleared from memory.", "KEEP_AUTH_OPTION": { "NEVER": "After each operation", "SECONDS": "After {{value}}s of inactivity", @@ -140,12 +160,21 @@ "HOUR": "After {{value}}h of inactivity", "ALWAYS": "At the end of the session" }, + "KEYRING_FILE": "Keyring file", + "KEYRING_FILE_HELP": "Allow auto-connect at startup, or to authenticate (only if \"Expiration of authentication\" is \"at the end of the session\"", "REMEMBER_ME": "Remember me ?", "REMEMBER_ME_HELP": "Allows to remain identified from one session to another, keeping the public key locally.", "PLUGINS_SETTINGS": "Extensions", "BTN_RESET": "Restore default values", "EXPERT_MODE": "Enable expert mode", "EXPERT_MODE_HELP": "Allow to see more details", + "BLOCK_VALIDITY_WINDOW": "Block uncertainty time", + "BLOCK_VALIDITY_WINDOW_SHORT": "Time of uncertainty", + "BLOCK_VALIDITY_WINDOW_HELP": "Time to wait before considering an information is validated", + "BLOCK_VALIDITY_OPTION": { + "NONE": "No delay", + "N": "{{time | formatDuration}} ({{count}} blocks)" + }, "POPUP_PEER": { "TITLE" : "Duniter peer", "HOST" : "Address", @@ -280,15 +309,18 @@ "PEERS": "Peers", "SIGNED_ON_BLOCK": "Signed on block", "MIRROR": "mirror", - "MIRRORS": "Mirror peers", + "MIRRORS": "Mirrors", + "MIRROR_PEERS": "Mirror peers", "PEER_LIST" : "Peer's list", - "MEMBERS" : "Member peers", + "MEMBERS" : "Members", + "MEMBER_PEERS" : "Member peers", "ALL_PEERS" : "All peers", "DIFFICULTY" : "Difficulty", "API" : "API", "CURRENT_BLOCK" : "Block #", "POPOVER_FILTER_TITLE": "Filter", - "OFFLINE": "Offline peers", + "OFFLINE": "Offline", + "OFFLINE_PEERS": "Offline peers", "BTN_SHOW_PEER": "Show peer", "VIEW": { "TITLE": "Peer", @@ -338,7 +370,7 @@ "PENDING": "Pending registrations:", "PENDING_COUNT": "{{count}} pending registrations", "REGISTERED": "Registered {{sigDate | formatFromNow}}", - "MEMBER_FROM": "Member since {{memberDate|formatFromNowShort}}", + "MEMBER_FROM": "Member since {{memberDate|medianFromNowShort}}", "BTN_NEWCOMERS": "Latest members", "BTN_PENDING": "Pending registrations", "SHOW_MORE": "Show more", @@ -380,14 +412,17 @@ "SCRYPT_FORM_HELP": "Please enter your credentials. <br> Remember to check the public key for your account.", "PUBKEY_FORM_HELP": "Please enter a public account key:", "FILE_FORM_HELP": "Choose the keychain file to use:", + "SCAN_FORM_HELP": "Scan the QR code of a wallet.", "SALT": "Secret identifier", "SALT_HELP": "Secret identifier", "SHOW_SALT": "Display secret identifier?", "PASSWORD": "Password", "PASSWORD_HELP": "Password", - "PUBKEY_HELP": "Example: « AbsxSY4qoZRzyV2irfep1V9xw1EMNyKJw2TkuVD4N1mv »", + "PUBKEY_HELP": "Public key or pseudonym", "NO_ACCOUNT_QUESTION": "Don't have an account yet?", + "HAVE_ACCOUNT_QUESTION": "Already have an account ?", "CREATE_ACCOUNT": "Create an account", + "CREATE_FREE_ACCOUNT": "Create a free account", "FORGOTTEN_ID": "Forgot password?", "ASSOCIATED_PUBKEY": "Public key :", "BTN_METHODS": "Other methods", @@ -402,10 +437,11 @@ "IDLE_WARNING": "You will be logout... {{countdown}}" }, "METHOD": { - "SCRYPT_DEFAULT": "Standard salt (default)", + "SCRYPT_DEFAULT": "Secret identifier and password", "SCRYPT_ADVANCED": "Advanced salt", "FILE": "Keychain file", - "PUBKEY": "Public key only" + "PUBKEY": "Public key or pseudonym", + "SCAN": "Scan a QR code" }, "SCRYPT": { "SIMPLE": "Light salt", @@ -419,44 +455,47 @@ "p": "p (CPU):" }, "FILE": { - "DATE" : "Date:", - "TYPE" : "Type:", - "SIZE": "Size:", - "VALIDATING": "Validating...", "HELP": "Expected file format: <b>.dunikey</b> (type PubSec). Other formats are under development (EWIF, WIF)." } }, "AUTH": { "TITLE": "<i class=\"icon ion-locked\"></i> Authentication", - "METHOD_LABEL": "Authentication method", "BTN_AUTH": "Authenticate", - "SCRYPT_FORM_HELP": "Please authenticate yourself:" + "GENERAL_HELP": "Please authenticate yourself:", + "EXPECTED_UID_HELP": "Please authenticate to the account <i class=\"ion-person\"></i> {{uid}}:", + "EXPECTED_PUBKEY_HELP": "Please authenticate to the wallet <i class=\"ion-key\"></i> {{pubkey|formatPubkey}}:", + "SCAN_FORM_HELP": "Scan the QR code of the <b>private key</b> of the wallet." }, "ACCOUNT": { "TITLE": "My Account", "BALANCE": "Balance", - "LAST_TX": "Latest transactions", + "LAST_TX": "Latest validated transactions", "BALANCE_ACCOUNT": "Account balance", "NO_TX": "No transaction", "SHOW_MORE_TX": "Show more", "SHOW_ALL_TX": "Show all", - "TX_FROM_DATE": "(current limit to {{fromTime|formatFromNowShort}})", + "TX_FROM_DATE": "(current limit to {{fromTime|medianFromNowShort}})", "PENDING_TX": "Pending transactions", + "VALIDATING_TX": "Transactions being validated", "ERROR_TX": "Transaction not executed", "ERROR_TX_SENT": "Sent transactions", "PENDING_TX_RECEIVED": "Transactions awaiting receipt", "EVENTS": "Events", + "OUT_DISTANCED": "Your current certifications come from a group too isolated from the <a ng-click=\"showHelpModal('wot')\"> Web of Trust</a> (WoT): the <a ng-click=\"showHelpModal('distance_rule')\">maximum distance rule</a> is violated.<br/>You must obtain certifications from another area of the Web of Trust, or wait for it to tighten.", "WAITING_MEMBERSHIP": "Membership application sent. Waiting validation.", - "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member", + "WAITING_CERTIFICATIONS": "You need {{needCertificationCount}} certification(s) to become a member and produce the <a ng-click=\"showHelpModal('ud')\">Universal Dividend</a>. Your account is however already operational, to receive and send payments.", + "WAITING_CERTIFICATIONS_HELP": "To get your certifications, only request members <b>who know you enough</b>, as required by <a ng-click=\"showLicenseModal()\">the currency license</a> that you have accepted.<br/>If you do not know enough members, let them know on <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">the user forum</a>.", "WILL_MISSING_CERTIFICATIONS": "You will <b>lack certifications</b> soon (at least {{willNeedCertificationCount}} more are needed)", "WILL_NEED_RENEW_MEMBERSHIP": "Your membership <b>will expire {{membershipExpiresIn|formatDurationTo}}</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a> before then.", "NEED_RENEW_MEMBERSHIP": "You are no longer a member because your membership <b>has expired</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a>.", + "NEED_RENEW_MEMBERSHIP_AFTER_CANCELLED": "You are no longer a member because your membership <b>has been canceled</b> for lack of certifications. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a>.", "NO_WAITING_MEMBERSHIP": "No membership application pending. If you'd like to <b>become a member</ b>, please <a ng-click=\"doQuickFix('membership')\">send the membership application</a>.", "CERTIFICATION_COUNT": "Received certifications", "CERTIFICATION_COUNT_SHORT": "Certifications", "SIG_STOCK": "Stock of certifications to give", "BTN_RECEIVE_MONEY": "Receive", "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Switch to another identity...", + "BTN_FIX_MEMBERSHIP": "Resubmit membership request...", "BTN_MEMBERSHIP_RENEW": "Renew membership", "BTN_MEMBERSHIP_RENEW_DOTS": "Renew membership...", "BTN_MEMBERSHIP_OUT_DOTS": "Revoke membership...", @@ -512,12 +551,40 @@ "TITLE": "Identity selection", "HELP": "Several <b>different identities</b> have been sent, for the public key <span class=\"gray\"> <i class=\"ion-key\"></i> {{pubkey | formatPubkey}}</span>.<br/>Please select the identity to use:" }, + "SELECT_WALLET_MODAL": { + "TITLE": "Wallet selection" + }, + "WALLET_LIST": { + "TITLE": "My wallets", + "BTN_NEW": "Add a wallet", + "BTN_DOWNLOAD": "Download the list", + "BTN_IMPORT_FILE_DOTS": "Import from a file...", + "NO_WALLET": "No secondary wallet", + "BTN_DELETE": "Remove a secondary wallet...", + "BTN_RENAME": "Rename the wallet", + "EXPORT_FILENAME": "my_wallets-{{pubkey|formatPubkey}}-{{currency}}.csv", + "TOTAL_DOTS": "Total: ", + "EDIT_POPOVER": { + "TITLE": "Rename the wallet", + "HELP": "Fill in the new name", + "NAME_HELP": "Wallet name" + }, + "IMPORT_MODAL": { + "TITLE": "Import secondary wallets", + "HELP": "To <b>import secodnary wallets</b>, please drag the file in the box below, or click in the box to search for a file.", + "WALLET_COUNT": "<b>{{count}}</b> new wallet{{count > 1 ? 's' : ''}}", + "NO_NEW_WALLET": "No new wallet" + } + }, "SECURITY":{ "ADD_QUESTION" : "Add custom question", "BTN_CLEAN" : "Clean", "BTN_RESET" : "Reset", "DOWNLOAD_REVOKE": "Save a revocation file", "DOWNLOAD_REVOKE_HELP" : "Having a revocation file is important, for example in case of loss of identifiers. It allows you to <b>get this account out of the Web Of Trust</b>, thus becoming a simple wallet.", + "GENERATE_KEYFILE": "Generate my keychain file ...", + "GENERATE_KEYFILE_HELP": "Generate a file allowing you to authenticate without entering your identifiers.<br/><b>Warning:</b> this file will contain your secret key; It is therefore very important to put it in a safe place!", + "KEYFILE_FILENAME": "keychain-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Register as member...", "MEMBERSHIP_IN_HELP": "Allows you to <b>transform </b> a simple wallet account <b>into a member account</b>, by sending a membership request. Useful only if you do not already have another member account.", "SEND_IDENTITY": "Publish identity...", @@ -556,7 +623,24 @@ "SAVE_ID": "Save my credentials...", "SAVE_ID_HELP": "Creating a backup file, to <b>retrieve your password</b> (and the secret identifier) <b> in case of forgetting</b>. The file is <b>secured</ b> (encrypted) using personal questions.", "STRONG_LEVEL": "Strong <span class=\"hidden-xs \">(6 questions minimum)</span>", - "TITLE": "Account and security" + "TITLE": "Account and security", + "KEYFILE": { + "PUBSEC_FORMAT": "PubSec format.", + "PUBSEC_FORMAT_HELP": "This file format is compatible in particular with Cesium and Gannonce. Your keychain is stored <b>without encryption</b>: anyone with a copy of this file will be able to empty your account.", + "WIF_FORMAT": "Wallet Import Format (WIF)", + "WIF_FORMAT_HELP": "This format is used in particular by paper wallets. Your keychain is stored <b>without encryption</b>: anyone with a copy of this file will be able to empty your account.", + "EWIF_FORMAT": "Encrypted Wallet Import Format (WIF)", + "EWIF_FORMAT_HELP": "This format is used in particular by paper wallets. However, <b>the keychain is encrypted</b> from a passphrase of your choice.", + "PASSWORD_POPUP": { + "TITLE": "Keychain file encrypted", + "HELP": "Please enter the passphrase:", + "PASSWORD_HELP": "Passphrase" + }, + "ERROR": { + "BAD_PASSWORD": "Bad passphrase", + "BAD_CHECKSUM": "Bad checksum" + } + } }, "FILE_NAME": "{{currency}} - Account statement {{pubkey|formatPubkey}} to {{currentTime|formatDateForFile}}.csv", "HEADERS": { @@ -568,6 +652,7 @@ "TRANSFER": { "TITLE": "Transfer", "SUB_TITLE": "Transfer money", + "SUB_TITLE_ALL": "Empty the account", "FROM": "From", "TO": "To", "AMOUNT": "Amount", @@ -576,15 +661,20 @@ "COMMENT_HELP": "Comment (optional)", "BTN_SEND": "Send", "BTN_ADD_COMMENT": "Add a comment", + "REST": "Rest of account", + "REST_TO": "to", "WARN_COMMENT_IS_PUBLIC": "Please note that <b>comments are public</b> (not encrypted).", "MODAL": { "TITLE": "Transfer" } }, "ERROR": { + "UNKNOWN_URI_FORMAT": "Unknown URI format", + "PUBKEY_INVALID_CHECKSUM": "Invalid public key (bad checksum).", "POPUP_TITLE": "Error", "UNKNOWN_ERROR": "Unknown error", "CRYPTO_UNKNOWN_ERROR": "Your browser is not compatible with cryptographic features.", + "DOWNLOAD_KEYFILE_FAILED": "Failed to generate the keychain file.", "EQUALS_TO_PSEUDO": "Must be different from pseudonym", "EQUALS_TO_SALT": "Must be different from secret identifier", "FIELD_REQUIRED": "This field is required.", @@ -634,7 +724,9 @@ "INVALID_USER_ID": "Field 'pseudonym' must not contains spaces or special characters.", "INVALID_COMMENT": "Field 'reference' has a bad format.", "INVALID_PUBKEY": "Public key has a bad format.", - "IDENTITY_REVOKED": "This identity <b>has been revoked {{revocationTime|formatFromNow}}</b> ({{revocationTime|formatDate}}). It can no longer become a member.", + "INVALID_PUBKEY_CHECKSUM": "Invalid checksum.", + "IDENTITY_REVOKED": "This identity <b>has been revoked</b>. It can no longer become a member.", + "IDENTITY_REVOKED_WITH_TIME": "This identity <b>has been revoked {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). It can no longer become a member.", "IDENTITY_PENDING_REVOCATION": "The <b>revocation of this identity</b> has been requested and is awaiting processing. Certification is therefore disabled.", "IDENTITY_INVALID_BLOCK_HASH": "This membership application is no longer valid (because it references a block that network peers are cancelled): the person must renew its application for membership <b>before</b> being certified.", "IDENTITY_EXPIRED": "This identity has expired: this person must re-apply <b>before</b> being certified.", @@ -657,6 +749,7 @@ "LOAD_NEWCOMERS_FAILED": "Unable to load new members.", "LOAD_PENDING_FAILED": "Unable to load pending registrations.", "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "You must <b>be a member</b> in order to perform this action.", + "ONLY_MEMBER_OR_WAS_MEMBER_CAN_EXECUTE_THIS_ACTION": "You must <b>be a member (or old member)</b> in order to perform this action.", "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "You must have <b>published your identity</b> in order to perform this action.", "GET_BLOCK_FAILED": "Error while getting block", "INVALID_BLOCK_HASH": "Block not found (incorrect hash)", @@ -672,7 +765,17 @@ "EXISTING_ACCOUNT_REQUEST": "Please modify your credentials so that they correspond to an unused account.", "GET_LICENSE_FILE_FAILED": "Unable to get license file", "CHECK_NETWORK_CONNECTION": "No peer appears to be accessible.<br/><br/>Please <b>check your Internet connection</b>.", - "ISSUE_524_TX_FAILED": "Failed to transfer.<br/><br/>A message has been sent to developers to help solve the problem.<b>Thank you for your help</b>." + "ISSUE_524_TX_FAILED": "Failed to transfer.<br/><br/>A message has been sent to developers to help solve the problem.<b>Thank you for your help</b>.", + "ADD_SECONDARY_WALLET_FAILED": "Unable to add secondary wallet.", + "UPDATE_WALLET_LIST_FAILED": "Unable to refresh the list of wallets.", + "LOAD_WALLET_LIST_FAILED": "Unable to load the list of wallets.", + "SAVE_WALLET_LIST_FAILED": "Unable to save the list of wallets.", + "COULD_NOT_ADD_MAIN_WALLET": "This wallet <b>is the main account</b> with which you are connected. Unable to add it as a secondary wallet.", + "COULD_NOT_ADD_EXISTING_WALLET": "Wallet already existing in the list.", + "UNKNOWN_WALLET_ID": "Unknown secondary wallet.", + "RESTORE_WALLET_LIST_FAILED": "Unable to restore the list of wallets.", + "INVALID_FILE_FORMAT": "Invalid file format.", + "SAME_TX_RECIPIENT": "The recipient must be different from the issuer." }, "INFO": { "POPUP_TITLE": "Information", @@ -684,6 +787,7 @@ "NOT_NEED_MEMBERSHIP": "Already a member.", "IDENTITY_WILL_MISSING_CERTIFICATIONS": "This identity will soon lack certification (at least {{willNeedCertificationCount}}).", "IDENTITY_NEED_MEMBERSHIP": "This identity did not send a membership request. She will have to if she wishes to become a member.", + "HAS_ALTERNATIVE_IDENTITIES": "There are <b>multiple identities</b> attached to this public key. <b>Before any certification</b>, please <a ng-click=\"doQuickFix('showSelectIdentities')\">check other identities</a> to choose the correct one, or contact the wallet owner.", "REVOCATION_SENT": "Revocation sent successfully", "REVOCATION_SENT_WAITING_PROCESS": "Revocation <b>has been sent successfully</b>. It is awaiting processing.", "FEATURES_NOT_IMPLEMENTED": "This features is not implemented yet.<br/><br/>Why not to contribute to get it faster? ;)", @@ -695,7 +799,10 @@ "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Security warning</b>", "CERTIFY_RULES_TITLE_UID": "Certify {{uid}}", "CERTIFY_RULES": "<b class=\"assertive\">Don't certify an account</b> if you believe that: <ul><li>1.) the issuers identity might be faked.<li>2.) the issuer already has another certified account.<li>3.) the issuer purposely or carelessly violates rule 1 or 2 (he certifies faked or double accounts).</ul></small><br/>Are you sure you want to certify this identity?", + "FULLSCREEN": "View the application in full screen?", + "EXIT_APP": "Close the application ?", "TRANSFER": "<b>Transfer summary:</b><br/><br/><ul><li> - From: <b>{{from}}</b></li><li> - To: <b>{{to}}</b></li><li> - Amount: <b>{{amount}} {{unit}}</b></li><li> - Comment: <i>{{comment}}</i></li></ul><br/><b>Are-you sure you want to do this transfer?</b>", + "TRANSFER_ALL": "<b>Transfer summary:</b><br/><br/><ul><li> - From: <b>{{from}}</b></li><li> - To: <b>{{to}}</b></li><li> - Amount: <b>{{amount}} {{unit}}</b></li><li> - Comment: <i>{{comment}}</i></li><br/><li> - Rest : <b>{{restAmount}} {{unit}}</b> to <b>{{restTo}}</b></li></ul><br/><b>Are-you sure you want to do this transfer?</b>", "MEMBERSHIP_OUT": "This operation is <b>irreversible</b>.<br/></br/><b>Are you sure you want to terminate your membership?</b>", "MEMBERSHIP_OUT_2": "This operation is <b>irreversible</b>!<br/><br/>Are you sure you want to <b>terminate your membership</b>?", "LOGIN_UNUSED_WALLET_TITLE": "Typing error?", @@ -741,7 +848,11 @@ "CURRENCY_RULES_DEF": "The currency rules are defined only once, and for all. They set the parameters under which the currency will perform: universal dividend calculation, the amount of certifications needed to become a member, the maximum amount of certifications a member can send, etc.<br/><br/>The parameters cannot be modified because of the use of a <span class=\"text-italic\">Blockchain</span> which carries and executes these rules, and constantly verifies their correct application. <a href=\"#/app/currency\">See current parameters</a>.", "BLOCKCHAIN": "Blockchain", "BLOCKCHAIN_DEF": "The Blockchain is a decentralised system which, in case of Duniter, serves to carry and execute the <span class=\"text-italic\">currency rules</span>.<br/><a href=\"http://en.duniter.org/presentation/\" target=\"_blank\">Read more about Duniter</a> and the working of its blockchain.", - "UNIVERSAL_DIVIDEND_DEF": "The Universal Dividend (UD) is the quantity of money co-created by each member, according to the period and the calculation defined in the <span class=\"text-italic\">currency rules</span>.<br/>Every term, the members receive an equal amount of new money on their account.<br/><br/>The UD undergoes a steady growth, to remain fair under its members (current and future), calculated by an average life expectancy, as demonstrated in the Relative Theory of Money (RTM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Read more about RTM</a> and open money." + "UNIVERSAL_DIVIDEND_DEF": "The Universal Dividend (UD) is the quantity of money co-created by each member, according to the period and the calculation defined in the <span class=\"text-italic\">currency rules</span>.<br/>Every term, the members receive an equal amount of new money on their account.<br/><br/>The UD undergoes a steady growth, to remain fair under its members (current and future), calculated by an average life expectancy, as demonstrated in the Relative Theory of Money (RTM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Read more about RTM</a> and open money.", + "WOT": "Web of Trust (WoT)", + "WOT_DEF": "The Web of Trust is made up of all the members of the currency, and the links of certification which connect them.", + "DISTANCE_RULE": "Distance rule", + "DISTANCE_RULE_DEF": "The rule of distance defines <b>a maximum distance to meet</b> between an applicant and a minimum number of referring member. This distance is calculated using the certification links." }, "TIP": { "MENU_BTN_CURRENCY": "Menu <b>{{'MENU.CURRENCY'|translate}}</b> allows discovery of <b>currency parameters</b> and its state.", @@ -794,7 +905,8 @@ "LINK_DOC": "API documentation", "LINK_DOC_HELP": "API documentation for developers", "LINK_STANDARD_APP": "Standard version", - "LINK_STANDARD_APP_HELP": "Open standard version of {{'COMMON.APP_NAME'|translate}}" + "LINK_STANDARD_APP_HELP": "Open standard version of {{'COMMON.APP_NAME'|translate}}", + "CONNECTION_ERROR": "Peer <b>{{server}}</b> unreachable or invalid address.<br/><br/>Check your Internet connection, or contact the web site administrator." }, "HOME": { "TITLE": "{{'COMMON.APP_NAME'|translate}} API Documentation", @@ -807,9 +919,11 @@ "TITLE_SHORT": "Online payment", "SUMMARY": "Order summary:", "AMOUNT": "Amount:", + "AMOUNTS_HELP": "Please select the amount:", "NAME": "Name:", "PUBKEY": "Public key of the recipient:", "COMMENT": "Order reference:", + "NODE": "Peer address:", "DEMO": { "SALT": "demo", "PASSWORD": "demo", @@ -835,6 +949,7 @@ "DEMO_DIVIDER": "Try it !", "DEMO_HELP": "To test this service, click on this button. The result content will be display below.", "DEMO_RESULT": "Result returned by call:", + "DEMO_RESULT_PEER": "Peer address used:", "DEMO_SUCCEED": "<i class=\"icon ion-checkmark\"></i> Success!", "DEMO_CANCELLED": "<i class=\"icon ion-close\"></i> Canceled by user", "INTEGRATE_DIVIDER": "Website integration", @@ -856,6 +971,8 @@ "PARAM_REDIRECT_URL_HELP": "URL redirection after sending payment, after the payment has been sent. Can contain the following strings, which will be replaced by the values of the transaction: \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\" and \"{pubkey}\".", "PARAM_CANCEL_URL": "URL if cancelled", "PARAM_CANCEL_URL_HELP": "URL in case of cancellation. Can contain the following strings, which will be replaced: \"{comment}\", \"{amount}\" and \"{pubkey}\".", + "PARAM_PREFERRED_NODE": "Preferred Duniter peer", + "PARAM_PREFERRED_NODE_HELP": "Peer address (URL) to use preferably (\"g1.domain.com:443\" or \"https://g1.domain.com\")", "EXAMPLES_HELP": "Examples of integration:", "EXAMPLE_BUTTON": "HTML Button", "EXAMPLE_BUTTON_DEFAULT_TEXT": "Pay in {{currency|abbreviate}}", diff --git a/assets/www/i18n/locale-eo-EO.json b/assets/www/i18n/locale-eo-EO.json new file mode 100644 index 0000000000000000000000000000000000000000..e27d28d7e861904aaa2dff8b0effe9b29a623025 --- /dev/null +++ b/assets/www/i18n/locale-eo-EO.json @@ -0,0 +1,995 @@ +{ + "COMMON": { + "APP_NAME": "Cesium", + "APP_VERSION": "v{{version}}", + "APP_BUILD": "date : {{build}}", + "PUBKEY": "Publika Ålosilo", + "MEMBER": "Membro", + "BLOCK" : "Bloko", + "BTN_OK": "OK", + "BTN_YES": "Jes", + "BTN_NO": "Ne", + "BTN_SEND": "Sendi", + "BTN_SEND_MONEY": "Fari elspezon", + "BTN_SEND_MONEY_SHORT": "Elspezo", + "BTN_SAVE": "Konservi", + "BTN_YES_SAVE": "Jes, Konservi", + "BTN_YES_CONTINUE": "Jes, DaÅrigi", + "BTN_SHOW": "Vidi", + "BTN_SHOW_PUBKEY": "AfiÅi la publikan Ålosilon", + "BTN_RELATIVE_UNIT": "AfiÅi la sumojn en UD?", + "BTN_BACK": "Reiro", + "BTN_NEXT": "Sekva", + "BTN_IMPORT": "Enporti", + "BTN_CANCEL": "Nuligi", + "BTN_CLOSE": "Fermi", + "BTN_LATER": "Poste", + "BTN_LOGIN": "KonektiÄi", + "BTN_LOGOUT": "MalkonektiÄo", + "BTN_ADD_ACCOUNT": "Nova konto", + "BTN_SHARE": "Diskonigi", + "BTN_EDIT": "Modifi", + "BTN_DELETE": "Forigi", + "BTN_ADD": "Aldoni", + "BTN_SEARCH": "Serĉi", + "BTN_REFRESH": "Aktualigi", + "BTN_RETRY": "Rekomenci", + "BTN_START": "Komenci", + "BTN_CONTINUE": "DaÅrigi", + "BTN_CREATE": "Krei", + "BTN_UNDERSTOOD": "Mi komprenis", + "BTN_OPTIONS": "Kromeblecoj", + "BTN_HELP_TOUR": "Gvidata vizito", + "BTN_HELP_TOUR_SCREEN": "Malkovri tiun ĉi paÄon", + "BTN_DOWNLOAD": "ElÅuti", + "BTN_DOWNLOAD_ACCOUNT_STATEMENT": "ElÅuti la konto-tabelon", + "BTN_MODIFY": "Modifi", + "CHOOSE_FILE": "Almetu vian dosieron <br/>aÅ klaku por elekti Äin", + "DAYS": "tagoj", + "NO_ACCOUNT_QUESTION": "AnkoraÅ sen konto? Kreu Äin senpage!", + "SEARCH_NO_RESULT": "Neniu rezulto trovita", + "LOADING": "Bonvolu pacienci...", + "LOADING_WAIT": "Bonvolu pacienci...<br/><small>(Atendado pri disponebleco de la nodo)</small>", + "SEARCHING": "Serĉanta...", + "FROM": "De", + "TO": "Al", + "COPY": "Kopii", + "LANGUAGE": "Lingvo", + "UNIVERSAL_DIVIDEND": "Universala dividendo", + "UD": "UD", + "DATE_PATTERN": "DD/MM/YY HH:mm", + "DATE_FILE_PATTERN": "YYYY-MM-DD", + "DATE_SHORT_PATTERN": "DD/MM/YY", + "DATE_MONTH_YEAR_PATTERN": "MM/YYYY", + "EMPTY_PARENTHESIS": "(malplena)", + "UID": "PseÅdonimo", + "ENABLE": "Aktiva", + "DISABLE": "Malaktiva", + "RESULTS_LIST": "Rezultoj", + "RESULTS_COUNT": "{{count}} rezultoj", + "EXECUTION_TIME": "Plenumita en {{duration|formatDurationMs}}", + "SHOW_VALUES": "AfiÅi la signojn klare?", + "POPOVER_ACTIONS_TITLE": "Kromeblecoj", + "POPOVER_FILTER_TITLE": "Filtriloj", + "SHOW_MORE": "AfiÅi pli", + "SHOW_MORE_COUNT": "(nuna limo je {{limit}})", + "POPOVER_SHARE": { + "TITLE": "Diskonigi", + "SHARE_ON_TWITTER": "Diskonigi ĉe Twitter", + "SHARE_ON_FACEBOOK": "Diskonigi ĉe Facebook", + "SHARE_ON_DIASPORA": "Diskonigi ĉe Diaspora*", + "SHARE_ON_GOOGLEPLUS": "Diskonigi ĉe Google+" + }, + "FILE": { + "DATE": "Dato:", + "TYPE": "Tipo:", + "SIZE": "Pezo:", + "VALIDATING": "ValidiÄanta..." + } + }, + "SYSTEM": { + "PICTURE_CHOOSE_TYPE": "Elekti la fonton:", + "BTN_PICTURE_GALLERY": "Bildaro", + "BTN_PICTURE_CAMERA": "<b>Kamerao</b>" + }, + "MENU": { + "HOME": "HejmpaÄo", + "WOT": "Kontaro", + "CURRENCY": "Mono", + "ACCOUNT": "Mia konto", + "WALLETS": "Miaj monujoj", + "TRANSFER": "Elspezo", + "SCAN": "Skani", + "SETTINGS": "Parametroj", + "NETWORK": "Reto", + "TRANSACTIONS": "Miaj spezoj" + }, + "ABOUT": { + "TITLE": "Prie", + "LICENSE": "Programo <b>libera</b> (Licenco GNU AGPLv3).", + "LATEST_RELEASE": "Ekzistas <b>pli freÅdata versio</b> de {{'COMMON.APP_NAME'|translate}} (<b>v{{version}}</b>)", + "PLEASE_UPDATE": "Bonvolu Äisdatigi {{'COMMON.APP_NAME'|translate}} (lasta versio: <b>v{{version}}</b>)", + "CODE": "Fonto-kodo:", + "OFFICIAL_WEB_SITE": "Oficiala retejo:", + "DEVELOPERS": "Programita de:", + "FORUM": "Forumo:", + "PLEASE_REPORT_ISSUE": "Ne hezitu sciigi al ni la renkontitajn fuÅaĵojn", + "REPORT_ISSUE": "Sciigi problemon", + "BTN_OPEN_DEV_WINDOW": "Malfermi la fenestron pri malfuÅigado" + }, + "HOME": { + "TITLE": "Cesium", + "WELCOME": "Bonvenon ĉe la programo Cesium!", + "MESSAGE": "Ricevu kaj sendu liberan monon {{currency|abbreviate}}", + "BTN_CURRENCY": "Esploru la monon {{name|abbreviate}}", + "BTN_ABOUT": "prie", + "BTN_HELP": "Reta helpo", + "REPORT_ISSUE": "fuÅaĵo", + "NOT_YOUR_ACCOUNT_QUESTION" : "Vi ne posedas la konton <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> ?", + "BTN_CHANGE_ACCOUNT": "Malkonektu tiun ĉi konton", + "CONNECTION_ERROR": "Nodo <b>{{server}}</b> neatingebla aÅ adreso nevalida.<br/><br/>Kontrolu vian retkonekton, aÅ elektu alian nodon <a class=\"positive\" ng-click=\"doQuickFix('settings')\">ĉe la parametroj</a>." + }, + "SETTINGS": { + "TITLE": "Parametroj", + "DISPLAY_DIVIDER": "AfiÅado", + "STORAGE_DIVIDER": "Stokado", + "NETWORK_SETTINGS": "Reto", + "PEER": "Adreso de la nodo Duniter", + "PEER_SHORT": "Adreso de la nodo", + "PEER_CHANGED_TEMPORARY": "Adreso provizore uzata", + "USE_LOCAL_STORAGE": "Aktivigi lokan stokadon", + "USE_LOCAL_STORAGE_HELP": "Ebligas konservi viajn parametrojn", + "WALLETS_SETTINGS": "Miaj monujoj", + "USE_WALLETS_ENCRYPTION": "Sekurigi la liston?", + "USE_WALLETS_ENCRYPTION_HELP": "Ebligas sekurigi la liston de viaj monujoj (per ĉifrado), postulante aÅtentigado por aliri ilin.", + "ENABLE_HELPTIP": "Aktivigi la rilatigajn help-vezikojn", + "ENABLE_UI_EFFECTS": "Aktivigi la vid-efikojn", + "HISTORY_SETTINGS": "Miaj spezoj", + "DISPLAY_UD_HISTORY": "AfiÅi la produktitajn dividendojn?", + "TX_HISTORY_AUTO_REFRESH": "Aktualigi aÅtomate", + "TX_HISTORY_AUTO_REFRESH_HELP": "Aktualigas la saldon kaj la spezojn aÅtomate, por ĉiu nova bloko de la reto.", + "AUTHENTICATION_SETTINGS": "AÅtentigado", + "KEEP_AUTH": "AÅtomata malaÅtentigado", + "KEEP_AUTH_SHORT": "MalaÅtentigado", + "KEEP_AUTH_HELP": "Difinas la momenton, kiam la aÅtentigado estas forviÅita de la memoro.", + "KEEP_AUTH_OPTION": { + "NEVER": "Post ĉiu ago", + "SECONDS": "Post {{value}}s de neatktiveco", + "MINUTE": "Post {{value}}min de neatktiveco", + "MINUTES": "Post {{value}}min de neatktiveco", + "HOUR": "Post {{value}}h de neatktiveco", + "ALWAYS": "Fine de la sesio" + }, + "KEYRING_FILE": "Dosiero pri Ålosilaro", + "KEYRING_FILE_HELP": "Ebligas <b>konektiÄi</b> aÅtomate por ĉiu ekuzo<br/>kaj eĉ <b>aÅtentiÄi</b> (nur se \"FiniÄo de la aÅtentiÄo\" estas agordita kiel \"fine de la sesio\").", + "REMEMBER_ME": "Memori min?", + "REMEMBER_ME_HELP": "Ebligas resti identigita de sesio al alia, loke konservante la publikan Ålosilon.", + "PLUGINS_SETTINGS": "Krom-programoj", + "BTN_RESET": "Restarigi la originajn valorojn", + "EXPERT_MODE": "Aktivigi la spertan moduson", + "EXPERT_MODE_HELP": "Ebligas pli detalan afiÅadon.", + "BLOCK_VALIDITY_WINDOW": "Limtempo pri necerteco de la blokoj", + "BLOCK_VALIDITY_WINDOW_SHORT": "Limtempo pri necerteco", + "BLOCK_VALIDITY_WINDOW_HELP": "Limtempo antaÅ ol taksi, ke iu informo estas validigita", + "BLOCK_VALIDITY_OPTION": { + "NONE": "Neniu limtempo", + "N": "{{time | formatDuration}} ({{count}} blokoj)" + }, + "POPUP_PEER": { + "TITLE": "Nodo Duniter", + "HOST": "Adreso", + "HOST_HELP": "Adreso: servilo: konektujo", + "USE_SSL": "Sekurigita?", + "USE_SSL_HELP": "(SSL-ĉifrado)", + "BTN_SHOW_LIST": "Listo de la nodoj" + } + }, + "BLOCKCHAIN": { + "HASH": "Haketo: {{hash}}", + "VIEW": { + "HEADER_TITLE": "Bloko #{{number}}-{{hash|formatHash}}", + "TITLE_CURRENT": "Nuna bloko", + "TITLE": "Bloko #{{number|formatInteger}}", + "COMPUTED_BY": "Kalkulita de la nodo de", + "SHOW_RAW": "Vidi la kompletan dosieron", + "TECHNICAL_DIVIDER": "Teknikaj informoj", + "VERSION": "Versio de la daten-strukturo", + "HASH": "Kalkulita haketo", + "UNIVERSAL_DIVIDEND_HELP": "Mono kunproduktita de ĉiu el la {{membersCount}} membroj", + "EMPTY": "Neniu dateno en tiu ĉi bloko", + "POW_MIN": "Minimuma malfacileco", + "POW_MIN_HELP": "Malfacileco trudita por la haket-kalkulo", + "DATA_DIVIDER": "Datenoj", + "IDENTITIES_COUNT": "Novaj identecoj", + "JOINERS_COUNT": "Novaj membroj", + "ACTIVES_COUNT": "Revalidigoj", + "ACTIVES_COUNT_HELP": "Membroj revalidigintaj sian membrecon", + "LEAVERS_COUNT": "Membroj elirintaj", + "LEAVERS_COUNT_HELP": "Membroj ne plu dezirantaj atestaĵon", + "EXCLUDED_COUNT": "Membroj eksigitaj", + "EXCLUDED_COUNT_HELP": "Malnovaj membroj eksigitaj pro nerevalidiÄo aÅ manko de atestaĵoj", + "REVOKED_COUNT": "Nuligitaj identecoj", + "REVOKED_COUNT_HELP": "Tiuj kontoj ne plu povos esti membroj", + "TX_COUNT": "Spezoj", + "CERT_COUNT": "Atestaĵoj", + "TX_TO_HIMSELF": "Operacio pri monÅanÄo", + "TX_OUTPUT_UNLOCK_CONDITIONS": "Kondiĉoj por malblokado", + "TX_OUTPUT_OPERATOR": { + "AND": "kaj", + "OR": "aÅ" + }, + "TX_OUTPUT_FUNCTION": { + "SIG": "<b>Subskribo</b> de ", + "XHX": "<b>Pasvorto</b>, el kiu SHA256 =", + "CSV": "Blokita dum", + "CLTV": "Blokita Äis" + } + }, + "LOOKUP": { + "TITLE": "Blokoj", + "NO_BLOCK": "Neniu bloko", + "LAST_BLOCKS": "Lastaj blokoj:", + "BTN_COMPACT": "Densigi" + } + }, + "CURRENCY": { + "VIEW": { + "TITLE": "Mono", + "TAB_CURRENCY": "Mono", + "TAB_WOT": "Reto de fido", + "TAB_NETWORK": "Reto", + "TAB_BLOCKS": "Blokoj", + "CURRENCY_SHORT_DESCRIPTION": "{{currency|abbreviate}} estas <b>libera mono</b>, kiu ekis {{firstBlockTime|formatFromNow}}. Äœi nombras nun <b>{{N}} membrojn</b>, kiuj produktas kaj ricevas <a ng-click=\"showHelpModal('ud')\">Universalan Dividendon</a> (UD), ĉiun {{dt|formatPeriod}}n.", + "NETWORK_RULES_DIVIDER": "Reguloj de la reto", + "CURRENCY_NAME": "Nomo de la mono", + "MEMBERS": "Nombro de membroj", + "MEMBERS_VARIATION": "Variado depost la lasta UD", + "MONEY_DIVIDER": "Mono", + "MASS": "Mona maso", + "SHARE": "Maso por membro", + "UD": "Universala Dividendo", + "C_ACTUAL": "Nuna kreskado", + "MEDIAN_TIME": "Horo de la blokĉeno", + "POW_MIN": "Minimuma nivelo pri malfacileco de kalkulo", + "MONEY_RULES_DIVIDER": "Reguloj de la mono", + "C_RULE": "Teoria kreskado celata", + "UD_RULE": "Kalkulo de la universala dividendo", + "DT_REEVAL": "Periodo de revalorigo de la UD", + "REEVAL_SYMBOL": "reval", + "DT_REEVAL_VALUE": "Ĉiuj <b>{{dtReeval|formatDuration}}</b> ({{dtReeval/86400}} {{'COMMON.DAYS'|translate}})", + "UD_REEVAL_TIME0": "Dato de la unua revalorigo", + "SIG_QTY_RULE": "Nombro de necesaj atestaĵoj por fariÄi membro", + "SIG_STOCK": "Maksimuma nombro da senditaj atestaĵoj por membro", + "SIG_PERIOD": "Minimuma daÅro de atendado inter 2 sinsekvaj atestaĵoj senditaj de sama persono", + "SIG_WINDOW": "LimdaÅro por akcepti atestaĵon", + "SIG_VALIDITY": "VivdaÅro de atestaĵo, kiu estis akceptita", + "MS_WINDOW": "LimdaÅro por akcepti aliÄ-peton kiel membron", + "MS_VALIDITY": "VivdaÅro de aliÄo, kiu estis akceptita", + "STEP_MAX": "Maksimuma distanco, per la atestaĵoj, inter nova eniranto kaj la referencaj membroj", + "WOT_RULES_DIVIDER": "Reguloj de la reto de fido", + "SENTRIES": "Nombro de atestaĵoj (senditaj <b>kaj</b> ricevitaj) por fariÄi referenca membro", + "SENTRIES_FORMULA": "Nombro de atestaĵoj (senditaj <b>kaj</b> ricevitaj) por fariÄi referenca membro (formulo)", + "XPERCENT":"Minimuma procento da referencaj membroj atingenda por konformiÄi al la regulo pri distanco", + "AVG_GEN_TIME": "Meza daÅro inter du blokoj", + "CURRENT": "nuna", + "MATH_CEILING": "PLAFONO", + "DISPLAY_ALL_RULES": "AfiÅi ĉiujn regulojn?", + "BTN_SHOW_LICENSE": "Vidi la licencon", + "WOT_DIVIDER": "Reto de fido" + }, + "LICENSE": { + "TITLE": "Licenco de la mono", + "BTN_DOWNLOAD": "ElÅuti la dosieron", + "NO_LICENSE_FILE": "Dosiero pri licenco ne trovita." + } + }, + "NETWORK": { + "VIEW": { + "MEDIAN_TIME": "Horo de la blokĉeno", + "LOADING_PEERS": "Nodoj ÅarÄiÄantaj...", + "NODE_ADDRESS": "Adreso:", + "SOFTWARE": "Programo", + "WARN_PRE_RELEASE": "AntaÅ-versio (lasta stabila versio: <b>{{version}}</b>)", + "WARN_NEW_RELEASE": "Versio <b>{{version}}</b> disponebla", + "WS2PID": "Identigilo:", + "PRIVATE_ACCESS": "Privata aliro", + "POW_PREFIX": "Prefikso pri labor-pruvo:", + "ENDPOINTS": { + "BMAS": "Sekurigita interfaco (SSL)", + "BMATOR": "Reta interfaco TOR", + "WS2P": "Interfaco WS2P", + "ES_USER_API": "Nodo de datenoj Cesium+" + } + }, + "INFO": { + "ONLY_SSL_PEERS": "La nodoj ne-SSL estas mis-afiÅitaj, ĉar Cesium funkcias laÅ moduso HTTPS." + } + }, + "PEER": { + "PEERS": "Nodoj", + "SIGNED_ON_BLOCK": "Skribita en la bloko", + "MIRROR": "spegulo", + "MIRRORS": "Speguloj", + "MIRROR_PEERS": "Spegul-nodoj", + "PEER_LIST" : "Listo de la nodoj", + "MEMBERS" : "Membroj", + "MEMBER_PEERS" : "Membro-nodoj", + "ALL_PEERS" : "Ĉiuj nodoj", + "DIFFICULTY" : "Malfacileco", + "API" : "API", + "CURRENT_BLOCK" : "Bloko #", + "POPOVER_FILTER_TITLE": "Filtrilo", + "OFFLINE": "Nekonektita", + "OFFLINE_PEERS": "Nekonektitaj nodoj", + "BTN_SHOW_PEER": "Vidi la nodon", + "VIEW": { + "TITLE": "Nodo", + "OWNER": "Apartenas al", + "SHOW_RAW_PEERING": "Vidi la samrangan dokumenton", + "SHOW_RAW_CURRENT_BLOCK": "Vidi la lastan blokon (kompleta strukturo)", + "LAST_BLOCKS": "Lastaj blokoj konataj", + "KNOWN_PEERS": "Konataj nodoj:", + "GENERAL_DIVIDER": "Äœeneralaj informoj", + "ERROR": { + "LOADING_TOR_NODE_ERROR": "Neeblas ricevi la informojn de la nodo. La limdaÅro de atendado estas transpasita.", + "LOADING_NODE_ERROR": "Neeblas ricevi la informojn de la nodo" + } + } + }, + "WOT": { + "SEARCH_HELP": "Traserĉado (pseÅdo aÅ publika Ålosilo)", + "SEARCH_INIT_PHASE_WARNING": "Dum la periodo de antaÅ-aliÄo, la traserĉado de la atendantaj aliÄoj <b>povas esti longa</b>. Bonvolu pacienci...", + "REGISTERED_SINCE": "Enskribita la", + "REGISTERED_SINCE_BLOCK": "Enskribita en la bloko #", + "NO_CERTIFICATION": "Neniu atestaĵo validigita", + "NO_GIVEN_CERTIFICATION": "Neniu atestaĵo sendita", + "NOT_MEMBER_PARENTHESIS": "(ne membro)", + "IDENTITY_REVOKED_PARENTHESIS": "(identeco nuligita)", + "MEMBER_PENDING_REVOCATION_PARENTHESIS": "(nuliÄanta)", + "EXPIRE_IN": "FiniÄo", + "NOT_WRITTEN_EXPIRE_IN": "Limdato<br/>de traktado", + "EXPIRED": "FiniÄinta", + "PSEUDO": "PseÅdonimo", + "SIGNED_ON_BLOCK": "Sendita en la bloko #{{block}}", + "WRITTEN_ON_BLOCK": "Enskribita en la bloko #{{block}}", + "GENERAL_DIVIDER": "Äœeneralaj informoj", + "NOT_MEMBER_ACCOUNT": "Simpla konto (ne membro)", + "NOT_MEMBER_ACCOUNT_HELP": "Temas pri simpla monujo, sen aliÄ-peto atendanta.", + "TECHNICAL_DIVIDER": "Teknikaj informoj", + "BTN_CERTIFY": "Atesti", + "BTN_YES_CERTIFY": "Jes, atesti", + "BTN_SELECT_AND_CERTIFY": "Nova atestaĵo", + "ACCOUNT_OPERATIONS": "Spezoj en la konto", + "VIEW": { + "POPOVER_SHARE_TITLE": "Identeco {{title}}" + }, + "LOOKUP": { + "TITLE": "Reto de fido", + "NEWCOMERS": "Novaj membroj", + "NEWCOMERS_COUNT": "{{count}} membroj", + "PENDING": "Atendantaj enskribiÄoj", + "PENDING_COUNT": "{{count}} atendantaj enskribiÄoj", + "REGISTERED": "Enskribita {{sigDate | formatFromNow}}", + "MEMBER_FROM": "Membro depost {{memberDate|medianFromNowShort}}", + "BTN_NEWCOMERS": "Novaj membroj", + "BTN_PENDING": "Atendantaj enskribiÄoj", + "SHOW_MORE": "AfiÅi pli", + "SHOW_MORE_COUNT": "(nuna limo je {{limit}})", + "NO_PENDING": "Neniu enskribiÄo atendanta.", + "NO_NEWCOMERS": "Neniu membro." + }, + "CONTACTS": { + "TITLE": "Kontaktoj" + }, + "MODAL": { + "TITLE": "Traserĉado" + }, + "CERTIFICATIONS": { + "TITLE": "{{uid}} - Atestaĵoj", + "SUMMARY": "Ricevitaj atestaĵoj", + "LIST": "Detalo pri la ricevitaj atestaĵoj", + "PENDING_LIST": "Atestaĵoj atendantaj traktadon", + "RECEIVED": "Ricevitaj atestaĵoj", + "RECEIVED_BY": "Atestaĵoj ricevitaj de {{uid}}", + "ERROR": "Atestaĵoj erare ricevitaj", + "SENTRY_MEMBER": "Referenca membro" + }, + "OPERATIONS": { + "TITLE": "{{uid}} - Spezoj" + }, + "GIVEN_CERTIFICATIONS": { + "TITLE": "{{uid}} - Senditaj atestaĵoj", + "SUMMARY": "Senditaj atestaĵoj", + "LIST": "Detalo pri la senditaj atestaĵoj", + "PENDING_LIST": "Atestaĵoj atendantaj traktadon", + "SENT": "Senditaj atestaĵoj", + "SENT_BY": "Atestaĵoj senditaj de {{uid}}", + "ERROR": "Atestaĵoj erare senditaj" + } + }, + "LOGIN": { + "TITLE": "<i class=\"icon ion-log-in\"></i> KonektiÄo", + "SCRYPT_FORM_HELP": "Bonvolu tajpi viajn identigilojn.<br>Pensu kontroli, ke la publika Ålosilo estas tiu de via konto.", + "PUBKEY_FORM_HELP": "Bonvolu tajpi publikan Ålosilon de konto:", + "FILE_FORM_HELP": "Elektu la Ålosilaro-dosieron uzotan:", + "SCAN_FORM_HELP": "Skani la QR-kodon de monujo.", + "SALT": "Sekreta identigilo", + "SALT_HELP": "Sekreta identigilo", + "SHOW_SALT": "AfiÅi la sekretan identigilon?", + "PASSWORD": "Pasvorto", + "PASSWORD_HELP": "Pasvorto", + "PUBKEY_HELP": "Publika Ålosilo aÅ pseÅdonimo", + "NO_ACCOUNT_QUESTION": "Vi ankoraÅ ne havas konton?", + "HAVE_ACCOUNT_QUESTION": "Vi jam havas konton?", + "CREATE_ACCOUNT": "Krei konton...", + "CREATE_FREE_ACCOUNT": "Krei konton senpage", + "FORGOTTEN_ID": "Pasvorto forgesita?", + "ASSOCIATED_PUBKEY": "Publika Ålosilo de la Ålosilaro:", + "BTN_METHODS": "Aliaj metodoj", + "BTN_METHODS_DOTS": "ÅœanÄi metodon...", + "METHOD_POPOVER_TITLE": "Metodoj", + "MEMORIZE_AUTH_FILE": "Memorigi tiun Ålosilaron por la daÅro de la sesio de retumado", + "SCRYPT_PARAMETERS": "Parametroj (Skripto):", + "AUTO_LOGOUT": { + "TITLE": "Informo", + "MESSAGE": "<i class=\"ion-android-time\"></i> Vi estis <b>malkonektita</b> aÅtomate, pro tro longa senaktiveco.", + "BTN_RELOGIN": "RekonektiÄi", + "IDLE_WARNING": "Vi estos malkonektita... {{countdown}}" + }, + "METHOD": { + "SCRYPT_DEFAULT": "Sekreta identigilo kaj pasvorto", + "SCRYPT_ADVANCED": "Sperta salumado", + "FILE": "Dosiero pri Ålosilaro", + "PUBKEY": "Publika Ålosilo aÅ pseÅdonimo", + "SCAN": "Skani QR-kodon" + }, + "SCRYPT": { + "SIMPLE": "Malpeza salumado", + "DEFAULT": "Kutima salumado", + "SECURE": "Sekura salumado", + "HARDEST": "Plej sekura salumado", + "EXTREME": "Ekstrema salumado", + "USER": "Personigita salumado", + "N": "N (Loop):", + "r": "r (RAM):", + "p": "p (CPU):" + }, + "FILE": { + "HELP": "Atendita strukturo de dosiero: <b>.yml</b> aÅ <b>.dunikey</b> (tipo PubSec, WIF aÅ EWIF)." + } + }, + "AUTH": { + "TITLE": "<i class=\"icon ion-locked\"></i> AÅtentigado", + "BTN_AUTH": "AÅtentiÄi", + "GENERAL_HELP": "Bonvolu aÅtentiÄi:", + "EXPECTED_UID_HELP": "Bonvolu aÅtentiÄi ĉe la konto <i class=\"ion-person\"></i> {{uid}} :", + "EXPECTED_PUBKEY_HELP": "Bonvolu aÅtentiÄi ĉe la monujo <br class=\"visible-xs\"/><i class=\"ion-key\"></i> {{pubkey|formatPubkey}} :", + "SCAN_FORM_HELP": "Skani la QR-kodon de la <b>privata Ålosilo</b> de la monujo." + }, + "ACCOUNT": { + "TITLE": "Mia konto", + "BALANCE": "Saldo", + "LAST_TX": "Lastaj spezoj validigitaj", + "BALANCE_ACCOUNT": "Konto-saldo", + "NO_TX": "Neniu spezo", + "SHOW_MORE_TX": "AfiÅi pli", + "SHOW_ALL_TX": "AfiÅi ĉion", + "TX_FROM_DATE": "(nuna limo je {{fromTime|medianFromNowShort}})", + "PENDING_TX": "Spezoj atendantaj traktadon", + "VALIDATING_TX": "Spezoj traktitaj, ne validigitaj", + "ERROR_TX": "Spezoj ne realigitaj", + "ERROR_TX_SENT": "Spezoj malsukcesintaj", + "PENDING_TX_RECEIVED": "Spezoj atendantaj ricevon", + "EVENTS": "Okazaĵoj", + "OUT_DISTANCED": "Viaj nunaj atestaĵoj venas de tro izolita grupo de la <a ng-click=\"showHelpModal('wot')\">Reto de Fido</a> (RdF): al la <a ng-click=\"showHelpModal('distance_rule')\">regulo de maksimuma distanco</a> vi ne konformiÄas.<br/>Vi devas akiri atestaĵojn venantajn de aliaj lokoj de la RdF, aÅ atendi ke tiu ĉi densiÄos.", + "WAITING_MEMBERSHIP": "AliÄo-peto sendita. Atendanta akcepton.", + "WAITING_CERTIFICATIONS": "Vi devas <b>akiri {{needCertificationCount}} atestaĵo(j)n</b> por fariÄi membro kaj produkti la <a ng-click=\"showHelpModal('ud')\">Universalan Dividendon</a>. Via konto tamen estas jam funkcianta, por ricevi kaj efektivigi pagojn.", + "WAITING_CERTIFICATIONS_HELP": "Por akiri viajn atestaĵojn, petu nur membrojn <b>kiuj sufiĉe konas vin</b>, kiel postulas <a ng-click=\"showLicenseModal()\">la licenco de la mono</a>, kiun vi akceptis.<br/>Se vi ne konas sufiĉe da membroj, sciigu tion ĉe <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">la forumo por uzantoj</a>.", + "WILL_MISSING_CERTIFICATIONS": "BaldaÅ <b>mankos al vi atestaĵoj</b> (almenaÅ {{willNeedCertificationCount}} estas necesaj)", + "WILL_NEED_RENEW_MEMBERSHIP": "Via aliÄo kiel membro <b>estas finiÄonta {{membershipExpiresIn|formatDurationTo}}</b>. Pensu <a ng-click=\"doQuickFix('renew')\">revalidigi vian aliÄon</a> Äis tiam.", + "NEED_RENEW_MEMBERSHIP": "Vi ne plu estas membro de la mono, ĉar <b>via aliÄo finiÄis</b>. Pensu <a ng-click=\"doQuickFix('renew')\">revalidigi vian aliÄon</a>.", + "NEED_RENEW_MEMBERSHIP_AFTER_CANCELLED": "Vi ne plu estas membro de la mono, <b>pro manko da atestaĵoj</b>. Pensu <a ng-click=\"doQuickFix('renew')\">revalidigi vian aliÄon</a>.", + "NO_WAITING_MEMBERSHIP": "Neniu aliÄo-peto atendanta. Se vi deziras <b>fariÄi membro</b>, pensu <a ng-click=\"doQuickFix('membership')\">sendi la aliÄo-peton</a>.", + "CERTIFICATION_COUNT": "Ricevitaj atestaĵoj", + "CERTIFICATION_COUNT_SHORT": "Atestaĵoj", + "SIG_STOCK": "Senditaj atestaĵoj", + "BTN_RECEIVE_MONEY": "Enkasigi", + "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Aliri alian identecon...", + "BTN_FIX_MEMBERSHIP": "Resendi la aliÄo-peton...", + "BTN_MEMBERSHIP_RENEW": "Revalidigi la aliÄon", + "BTN_MEMBERSHIP_RENEW_DOTS": "Revalidigi la aliÄon...", + "BTN_MEMBERSHIP_OUT_DOTS": "Ĉesigi la aliÄon...", + "BTN_SECURITY_DOTS": "Konto kaj sekureco...", + "BTN_SHOW_DETAILS": "AfiÅi la teknikajn informojn", + "LOCKED_OUTPUTS_POPOVER": { + "TITLE": "Sumo blokita", + "DESCRIPTION": "Jen la kondiĉoj de malblokado de tiu sumo:", + "DESCRIPTION_MANY": "Tiu spezo entenas plurajn partojn, pri kiuj la kondiĉoj de malblokado estas:", + "LOCKED_AMOUNT": "Kondiĉoj por la sumo:" + }, + "NEW": { + "TITLE": "Kreado de konto", + "INTRO_WARNING_TIME": "La kreado de konto ĉe {{name|capitalize}} estas tre simpla. Bonvolu tamen dediĉi sufiĉe da tempo por Äuste efektivigi tiun proceduron (por ne forgesi la identigilojn, pasvortojn, ktp.).", + "INTRO_WARNING_SECURITY": "Kontrolu ke la aparatoj, kiujn vi nun uzas (komputilo, tabuleto, telefono), <b>estas sekurigitaj kaj fidindaj</b>.", + "INTRO_WARNING_SECURITY_HELP": "Senvirusigilo Äisdata, fajroÅirmilo aktivigita, sesio protektita per pasvorto aÅ PIN-kodo, ktp.", + "INTRO_HELP": "Alklaku <b>{{'COMMON.BTN_START'|translate}}</b> por ekigi la kreadon de konto. Vi estos gvidata paÅon post paÅo.", + "REGISTRATION_NODE": "Via aliÄo estos registrita tra la nodo Duniter <b>{{server}}</b>, kiu dissendos Äin poste al la cetero de la mon-reto.", + "REGISTRATION_NODE_HELP": "Se vi ne fidas tiun nodon, bonvolu ÅanÄi Äin <a ng-click=\"doQuickFix('settings')\">en la parametroj</a> de Cesium.", + "SELECT_ACCOUNT_TYPE": "Elektu la tipon de konto kreota:", + "MEMBER_ACCOUNT": "Membro-konto", + "MEMBER_ACCOUNT_TITLE": "Kreado de membro-konto", + "MEMBER_ACCOUNT_HELP": "Se vi ankoraÅ ne enskribiÄis kiel individuo (nur unu konto eblas por unu individuo). Tia konto ebligas kunprodukti la monon, ricevante <b> universalan dividendon</b> ĉiun {{parameters.dt|formatPeriod}}n.", + "WALLET_ACCOUNT": "Simpla monujo", + "WALLET_ACCOUNT_TITLE": "Kreado de monujo", + "WALLET_ACCOUNT_HELP": "Por ĉiuj aliaj kazoj, ekzemple se vi bezonas plian konton.<br/>Neniu universala dividendo estos kreita per tia konto.", + "SALT_WARNING": "Elektu vian sekretan identigilon.<br/>Oni petos Äin de vi ĉiufoje, kiam vi konektiÄos al tiu konto.<br/><br/><b>Bone memorigu Äin</b>: kaze de perdo, neniu alia povos aliri vian konton!", + "PASSWORD_WARNING": "Elektu pasvorton.<br/>Oni petos Äin de vi ĉiufoje, kiam vi konektiÄos al tiu konto.<br/><br/><b>Bone memorigu tiun pasvorton</b: kaze de perdo, neniu alia povos aliri vian konton!", + "PSEUDO_WARNING": "Elektu pseÅdonimon.<br/>Äœi utilas al la aliaj membroj, por identigi vin pli facile.<div class='hidden-xs'><br/>Äœi <b>ne povos esti modifita</b>, sen rekrei konton.</div><br/><br/>Äœi entenu <b>nek spacon, nek diakritan literon (kun supersigno, ktp.)</b>.<div class='hidden-xs'><br/>Ekzemple: <span class='gray'>NataljaBelulino, JohanoStelaro, ktp.</span>", + "PSEUDO": "PseÅdonimo", + "PSEUDO_HELP": "PseÅdonimo", + "SALT_CONFIRM": "Konfirmo", + "SALT_CONFIRM_HELP": "Konfirmo de la sekreta identigilo", + "PASSWORD_CONFIRM": "Konfirmo", + "PASSWORD_CONFIRM_HELP": "Konfirmo de la pasvorto", + "SLIDE_6_TITLE": "Konfirmo:", + "COMPUTING_PUBKEY": "Kalkulanta...", + "LAST_SLIDE_CONGRATULATION": "Vi tajpis ĉiujn necesajn informojn: Gratulon!<br/>Vi nun povas <b>sendi la peton por kreado</b> de la konto.</b><br/><br/>Por informo, la publika Ålosilo ĉi-sube identigos vian estontan konton.<br/>Äœi povos estis sciigita al aliuloj por ricevi iliajn pagojn.<br/><b>Ne estas devige</b> noti Äin nun, vi ankaÅ povos fari tion poste.", + "CONFIRMATION_MEMBER_ACCOUNT": "<b class=\"assertive\">Averto:</b> la sekreta identigilo, la pasvorto kaj la pseÅdonimo ne plu povos esti modifitaj.<br/><br/><b>CertiÄu, ke vi ĉiam rememorigos Äin!</b><br/><br/><b>Ĉu vi certas</b>, ke vi deziras sendi tiun ĉi aliÄo-peton?", + "CONFIRMATION_WALLET_ACCOUNT": "<b class=\"assertive\">Averto:</b> la sekreta identigilo kaj la pasvorto ne plu povos esti modifitaj.<br/><br/><b>CertiÄu, ke vi ĉiam rememorigos Äin!</b><br/><br/><b>Ĉu vi certas</b>, ke vi deziras daÅrigi per tiuj ĉi identigiloj?", + "CHECKING_PSEUDO": "Kontrolo...", + "PSEUDO_AVAILABLE": "PseÅdonimo disponebla", + "PSEUDO_NOT_AVAILABLE": "PseÅdonimo ne disponebla", + "INFO_LICENSE": "AntaÅ ol krei membro-konton, <b>bonvolu legi kaj akcepti la licencon</b> pri uzado de la mono:", + "BTN_ACCEPT": "Mi akceptas", + "BTN_ACCEPT_LICENSE": "Mi akceptas la licencon" + }, + "POPUP_REGISTER": { + "TITLE": "Elektu pseÅdonimon", + "HELP": "PseÅdonimo estas deviga por fariÄi membro." + }, + "SELECT_IDENTITY_MODAL": { + "TITLE": "Elekto de la identeco", + "HELP": "Pluraj <b>malsamaj identecoj</b> estis senditaj, por la publika Ålosilo <span class=\"gray\"><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</span>.<br/>Bonvolu elekti la dosierujon uzotan:" + }, + "SELECT_WALLET_MODAL": { + "TITLE": "Elekto de la monujo" + }, + "WALLET_LIST": { + "TITLE": "Miaj monujoj", + "BTN_NEW": "Aldoni monujon", + "BTN_DOWNLOAD": "ElÅuti la liston", + "BTN_IMPORT_FILE_DOTS": "Enporti el dosiero...", + "NO_WALLET": "Neniu kroma monujo", + "BTN_DELETE": "Forigi kroman monujon...", + "BTN_RENAME": "Renomi la monujon", + "EXPORT_FILENAME": "miaj_monujoj-{{pubkey|formatPubkey}}-{{currency}}.csv", + "TOTAL_DOTS": "Sumo: ", + "EDIT_POPOVER": { + "TITLE": "Renomi la monujon", + "HELP": "Sciigu la novan nomon", + "NAME_HELP": "Nomo de la monujo" + }, + "IMPORT_MODAL": { + "TITLE": "Enporti monujojn", + "HELP": "Por <b>enporti monujojn</b>, bonvolu glitigi en la ĉi-suban zonon la dosieron pri la listo de monujoj, aÅ alklaki la zonon por serĉadi dosieron.", + "WALLET_COUNT": "<b>{{count}}</b> nova{{count > 1 ? 'j' : ''}} monujo{{count > 1 ? 'j' : ''}}", + "NO_NEW_WALLET": "Neniu nova monujo" + } + }, + "SECURITY": { + "ADD_QUESTION": "Aldoni personigitan demandon", + "BTN_CLEAN": "Malplenigi", + "BTN_RESET": "Restartigi", + "DOWNLOAD_REVOKE": "Konservi mian dosieron pri nuligo", + "DOWNLOAD_REVOKE_HELP": "Disponi dosieron pri nuligo estas grave, ekzemple kaze de perdo de viaj identigiloj. Äœi ebligas al vi <b>elirigi tiun konton el la reto de fido</b>, tiel ke Äi refariÄu simpla monujo.", + "GENERATE_KEYFILE": "Krei mian dosieron pri Ålosilaro...", + "GENERATE_KEYFILE_HELP": "Kreas dosieron, kiu ebligas al vi aÅtentiÄi sen tajpi viajn identigilojn.<br/><b>Atenton:</b> tiu dosiero entenos vian konto-Ålosilaron (publikan kaj sekretan Ålosilojn); do tre gravas meti Äin en sekuran lokon!", + "KEYFILE_FILENAME": "Ålosilaro-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", + "MEMBERSHIP_IN": "Transformi en membro-konton...", + "MEMBERSHIP_IN_HELP": "Ebligas <b>transformi</b> simplan monujo-konton <b>en membro-konton</b>, sendante aliÄo-peton. Utilas nur se vi ne havas jam alian membro-konton.", + "SEND_IDENTITY": "Publikigi sian identecon...", + "SEND_IDENTITY_HELP": "Ebligas kunligi pseÅdonimon kun tiu ĉi konto, sed <b>sen fari aliÄo-peton</b> por iÄi membro. Tiu kunligo kutime ne utilas, ĉar la valideco de tiu kunligo de pseÅdonimo estas limigita en la tempo.", + "HELP_LEVEL": "Por krei konserv-dosieron pri viaj identigiloj, elektu <strong> almenaÅ {{nb}} demandojn:</strong>", + "LEVEL": "Nivelo de sekureco", + "LOW_LEVEL": "Malforta <span class=\"hidden-xs\">(2 demandoj minimume)</span>", + "MEDIUM_LEVEL": "Meza <span class=\"hidden-xs\">(4 demandoj minimume)</span>", + "QUESTION_1": "Kiel nomiÄis via plej bona amik.in.o, kiam vi estis adoleskant.in.o?", + "QUESTION_2": "Kiel nomiÄis via unua hejm-besto?", + "QUESTION_3": "Kiun pladon vi unue lernis kuiradi?", + "QUESTION_4": "Kiun filmon vi unue spektis en kinejo?", + "QUESTION_5": "Kien vi iris la unuan fojon, kiam vi vojaÄis per aviadilo?", + "QUESTION_6": "Kiel nomiÄis via preferata instruist.i.no en bazlernejo?", + "QUESTION_7": "Kio estus laÅ vi la ideala profesio?", + "QUESTION_8": "Kiun libron por infanoj vi preferas?", + "QUESTION_9": "Kio estis la marko de via unua veturilo?", + "QUESTION_10": "Kio estis via kromnomo, kiam vi estis infano?", + "QUESTION_11": "Kiun rolant.in.on aÅ aktor.in.on vi preferis en kino, kiam vi estis student.in.o?", + "QUESTION_12": "Kiun kanzonist.ino.n aÅ muzikgrupon vi preferis, kiam vi estis student.in.o?", + "QUESTION_13": "En kiu urbo renkontiÄis viaj gepatroj?", + "QUESTION_14": "Kiel nomiÄis via unua ĉefo?", + "QUESTION_15": "Kiel nomiÄas la strato, kie vi kreskis?", + "QUESTION_16": "Kiel nomiÄas la marbordo, kie vi unuafoje baniÄis?", + "QUESTION_17": "Kiun muzik-albumon vi unuafoje aĉetis?", + "QUESTION_18": "Kiel nomiÄas via preferata sporto-teamo?", + "QUESTION_19": "Kio estis la profesio de via avo?", + "RECOVER_ID": "Retrovi mian pasvorton...", + "RECOVER_ID_HELP": "Se vi disponas <b>konserv-dosieron pri viaj identigiloj</b>, vi povas retrovi ilin respondante Äuste viajn personajn demandojn.", + "REVOCATION_WITH_FILE": "Nuligi mian membro-konton...", + "REVOCATION_WITH_FILE_DESCRIPTION": "Se vi <b>definitive perdis viajn identigilojn</b> pri via membro-konto (aÅ ke la sekureco de la konto estas endanÄerigita), vi povas uzi <b>la dosieron pri nuligo</b> de la konto por <b>trudi ties definitivan eliradon el la reto de fido</b>.", + "REVOCATION_WITH_FILE_HELP": "Por <b>definitive nuligi</b> membro-konton, bonvolu glitigi en la ĉi-suban zonon vian dosieron pri nuligo, aÅ alklaki la zonon por serĉadi dosieron.", + "REVOCATION_WALLET": "Nuligi tiun ĉi konton tuj", + "REVOCATION_WALLET_HELP": "Peti la nuligon de via identeco estigas la <b>eliradon el la reto de fido</b> (definitivan por la pseÅdonimo kaj la publika Ålosilo kunligitaj). La konto ne plu povos produkti Universalan Dividendon.<br/>Vi tamen daÅre povos konektiÄi al Äi, kiel al simpla monujo.", + "REVOCATION_FILENAME": "nuligo-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "SAVE_ID": "Konservi miajn identigilojn...", + "SAVE_ID_HELP": "Kreado de konserv-dosiero, por <b>retrovi vian pasvorton</b> (kaj la sekretan identigilon) <b>kaze de forgeso</b>. La dosiero estas <b>sekurigita</b> (ĉifrita) dank'al personaj demandoj.", + "STRONG_LEVEL": "Forta <span class=\"hidden-xs \">(6 demandoj minimume)</span>", + "TITLE": "Konto kaj sekureco", + "KEYFILE": { + "PUBSEC_FORMAT": "Strukturo PubSec.", + "PUBSEC_FORMAT_HELP": "Tiu strukturo stokas vian Ålosilaron laÅ tre simpla maniero. Äœi kongruas aparte kun Cesium, ÄŸannonce kaj Duniter.<br/><b>Atenton:</b>La dosiero <b>ne estas ĉifrita</b> (la sekreta Ålosilo klare aperas en Äi); bonvolu do stoki Äin en sekura loko!", + "WIF_FORMAT": "Strukturo WIF (Wallet Import Format) - v1", + "WIF_FORMAT_HELP": "Tiu strukturo stokas vian Ålosilaron inkluzivante en Äin kontrol-sumon por kontroli la sendifektecon de la dosiero. Äœi kongruas aparte kun la paper-monujoj (Duniter paper wallet).<br/><b>Atenton:</b>La dosiero <b>ne estas ĉifrita</b> (la sekreta Ålosilo klare aperas en Äi); bonvolu do stoki Äin en sekura loko!", + "EWIF_FORMAT": "Strukturo EWIF (Encrypted Wallet Import Format) - v1", + "EWIF_FORMAT_HELP": "Tiu strukturo stokas vian Ålosilaron <b>laŠĉifrita maniero</b> dank'al sekreta frazo elektita de vi. Äœi ankaÅ inkluzivas kontrol-sumon por kontroli la sendifektecon de la dosiero.<br/><b>Atenton:</b> Zorgu, ke vi ĉiam rememoru vian sekretan frazon!", + "PASSWORD_POPUP": { + "TITLE": "Ĉifrita dosiero pri Ålosilaro", + "HELP": "Bonvolu indiki la la sekretan frazon:", + "PASSWORD_HELP": "Sekreta frazo" + }, + "ERROR": { + "BAD_PASSWORD": "Sekreta frazo malÄusta", + "BAD_CHECKSUM": "Kontrol-sumo malÄusta" + } + } + }, + "FILE_NAME": "{{currency}} - Konto-tabelo {{pubkey|formatPubkey}} je {{currentTime|formatDateForFile}}.csv", + "HEADERS": { + "TIME": "Dato", + "AMOUNT": "Sumo", + "COMMENT": "Komento" + } + }, + "TRANSFER": { + "TITLE": "Elspezo", + "SUB_TITLE": "Fari elspezon", + "SUB_TITLE_ALL": "Malplenigi la konton", + "FROM": "De", + "TO": "Al", + "AMOUNT": "Sumo", + "AMOUNT_HELP": "Sumo", + "COMMENT": "Komento", + "COMMENT_HELP": "Komento", + "BTN_SEND": "Sendi", + "BTN_ADD_COMMENT": "Aldoni komenton", + "REST": "Resto de la konto", + "REST_TO": "al", + "WARN_COMMENT_IS_PUBLIC": "Bonvolu noti, ke <b>la komentoj estas publikaj</b> (ne ĉifritaj).", + "MODAL": { + "TITLE": "Elspezo" + } + }, + "ERROR": { + "UNKNOWN_URI_FORMAT": "URI-strukturo nekonata", + "PUBKEY_INVALID_CHECKSUM": "Publika Ålosilo nevalida (bad checksum).", + "POPUP_TITLE": "Eraro", + "UNKNOWN_ERROR": "Eraro nekonata", + "CRYPTO_UNKNOWN_ERROR": "Via retumilo Åajnas ne kongrua kun la kriptografiaj funkcioj.", + "DOWNLOAD_KEYFILE_FAILED": "Malsukceso por la kreado de la dosiero pri Ålosilaro.", + "EQUALS_TO_PSEUDO": "Devas esti malsama ol la pseÅdonimo", + "EQUALS_TO_SALT": "Devas esti malsama ol la sekreta identigilo", + "FIELD_REQUIRED": "Deviga kampo", + "FIELD_TOO_SHORT": "Signaro tro mallonga", + "FIELD_TOO_SHORT_WITH_LENGTH": "Signaro tro mallonga ({{minLength}} signoj minimume)", + "FIELD_TOO_LONG": "Signaro tro longa", + "FIELD_TOO_LONG_WITH_LENGTH": "Signaro tro longa ({{maxLength}} signoj maksimume)", + "FIELD_MIN": "Minimuma longeco: {{min}}", + "FIELD_MAX": "Maksimuma longeco: {{max}}", + "FIELD_ACCENT": "Diakritaj literoj kaj komoj ne permesataj", + "FIELD_NOT_NUMBER": "Nombra valoro atendata", + "FIELD_NOT_INT": "Entjera nombro atendata", + "FIELD_NOT_EMAIL": "Retadreso nevalida", + "PASSWORD_NOT_CONFIRMED": "Ne kongruas kun la pasvorto", + "SALT_NOT_CONFIRMED": "Ne kongruas kun la sekreta identigilo", + "SEND_IDENTITY_FAILED": "AliÄo malsukcesa", + "SEND_CERTIFICATION_FAILED": "Atestado malsukcesa", + "NEED_MEMBER_ACCOUNT_TO_CERTIFY": "Vi ne povas efektivigi atestadon, ĉar via konto <b>ne estas membro</b>.", + "NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF": "Vi ne povas efektivigi atestadon, ĉar via konto ankoraÅ ne estas membro.<br/><br/>AnkoraÅ mankas al vi atestaĵoj, aÅ tiuj ĉi ankoraÅ ne estis validigitaj.", + "NOT_MEMBER_FOR_CERTIFICATION": "Via konto ankoraÅ ne estas membro.", + "IDENTITY_TO_CERTIFY_HAS_NO_SELF": "Konto ne atestebla. Neniu aliÄo-peto estis farita, aÅ la aliÄo ne estis revalidigita.", + "LOGIN_FAILED": "Eraro dum konektiÄo.", + "LOAD_IDENTITY_FAILED": "Eraro por ÅarÄi la identecon.", + "LOAD_REQUIREMENTS_FAILED": "Eraro por ÅarÄi la antaÅ-necesaĵoj de la identeco.", + "SEND_MEMBERSHIP_IN_FAILED": "Malsukceso pri la provado eniri la komunumon.", + "SEND_MEMBERSHIP_OUT_FAILED": "Malsukceso pri la ĉesigo de la aliÄo.", + "REFRESH_WALLET_DATA": "Malsukceso pri la Äisdatigo de la monujo.", + "GET_CURRENCY_PARAMETER": "Malsukceso por ricevi la regulojn de la mono.", + "GET_CURRENCY_FAILED": "Ne eblis ÅarÄi la monon. Bonvolu reprovi pli poste.", + "SEND_TX_FAILED": "Elspezado malsukcesa.", + "ALL_SOURCES_USED": "Bonvolu atendi la kalkulon de la venonta bloko (ĉiuj viaj monfontoj estis uzitaj).", + "NOT_ENOUGH_SOURCES": "Ne sufiĉe da mono por sendi tiun ĉi sumon per ununura spezo.<br/>Maksimuma sumo: {{amount}} {{unit}}<sub>{{subUnit}}</sub>.", + "ACCOUNT_CREATION_FAILED": "Malsukceso por krei la membro-konton.", + "RESTORE_WALLET_DATA_ERROR": "Malsukceso por reÅarÄi la parametrojn de la loka stokaĵo", + "LOAD_WALLET_DATA_ERROR": "Malsukceso por ÅarÄi la datenojn de la monujo.", + "COPY_CLIPBOARD_FAILED": "Ne eblis kopii la valoron.", + "TAKE_PICTURE_FAILED": "Malsukceso por ricevi la foton.", + "SCAN_FAILED": "Malsukceso por skani la QR-kodon.", + "SCAN_UNKNOWN_FORMAT": "Kodo nerekonata.", + "WOT_LOOKUP_FAILED": "Serĉado malsukcesa.", + "LOAD_PEER_DATA_FAILED": "Ne eblis legi la nodon Duniter. Bonvolu reprovi poste.", + "NEED_LOGIN_FIRST": "Bonvolu unue konektiÄi.", + "AMOUNT_REQUIRED": "La monsumo estas deviga.", + "AMOUNT_NEGATIVE": "Negativa sumo nepermesata.", + "NOT_ENOUGH_CREDIT": "Saldo nesufiĉa.", + "INVALID_NODE_SUMMARY": "Nodo neatingebla aÅ adreso nevalida.", + "INVALID_USER_ID": "La pseÅdonimo devas enteni nek spacon nek signon specialan aÅ kun supersigno.", + "INVALID_COMMENT": "La kampo 'referenco' ne devas enteni literojn kun supersigno.", + "INVALID_PUBKEY": "La publika Ålosilo ne havas la atenditan strukturon.", + "INVALID_PUBKEY_CHECKSUM": "Kontrol-sumo nevalida.", + "IDENTITY_REVOKED": "Tiu ĉi identeco <b>estis nuligita</b>. Äœi ne plu povas fariÄi membro.", + "IDENTITY_REVOKED_WITH_TIME": "Tiu ĉi identeco <b>estis nuligita {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). Äœi ne plu povas fariÄi membro.", + "IDENTITY_PENDING_REVOCATION": "La <b>nuligo de tiu ĉi identeco</b> estis petita kaj atendas traktadon. La atestado estas do malaktivigita.", + "IDENTITY_INVALID_BLOCK_HASH": "Tiu ĉi aliÄo-peto ne plu validas (ĉar Äi rilatas al bloko, kiun nuligis la nodoj de la reto): tiu persono devas refari sian aliÄo-peton <b>antaÅ ol</b> esti atestita.", + "IDENTITY_EXPIRED": "La publikigo de tiu ĉi identeco finiÄis: tiu persono devas fari novan aliÄo-peton <b>antaÅ ol</b> esti atestita.", + "IDENTITY_SANDBOX_FULL": "La nodo Duniter uzata de Cesium ne plu povas ricevi novajn identecojn, ĉar Äia atendo-vico estas plena.<br/><br/>Bonvolu reprovi poste aÅ ÅanÄi la nodon (per la menuo <b>Parametroj</b>).", + "IDENTITY_NOT_FOUND": "Identeco ne trovita.", + "IDENTITY_TX_FAILED": "Malsukceso por ÅarÄi la spezojn.", + "WOT_PENDING_INVALID_BLOCK_HASH": "AliÄo ne valida.", + "WALLET_INVALID_BLOCK_HASH": "Via aliÄo-peto ne plu validas (ĉar Äi rilatas al bloko, kiun nuligis la nodoj de la reto).<br/>Vi devas <a ng-click=\"doQuickFix('fixMembership')\">sendi novan peton</a> por solvi tiun ĉi problemon.", + "WALLET_IDENTITY_EXPIRED": "La publikigo de <b>via identeco finiÄis</b>.<br/>Vi devas <a ng-click=\"doQuickFix('fixIdentity')\">publikigi denove vian identecon</a> por solvi tiun ĉi problemon.", + "WALLET_REVOKED": "Via identeco estis <b>nuligita</b>: nek via pseÅdonimo nek via publika Ålosilo povos esti uzata en la estonteco por membro-konto.", + "WALLET_HAS_NO_SELF": "Via identeco devas unue esti publikigita, kaj ne esti finiÄinta.", + "AUTH_REQUIRED": "AÅtentigado necesa.", + "AUTH_INVALID_PUBKEY": "La atendata Ålosilo estas <i class=\"ion-key\"></i> {{pubkey|formatPubkey}}...", + "AUTH_INVALID_SCRYPT": "Identigilo aÅ pasvorto nevalida.", + "AUTH_INVALID_FILE": "Dosiero pri Ålosilaro nevalida.", + "AUTH_FILE_ERROR": "Malsukceso por malfermi la dosieron pri Ålosilaro.", + "IDENTITY_ALREADY_CERTIFY": "Vi <b>jam atestis</b> tiun identecon.<br/><br/>Tiu atestado daÅre validas (finiÄo {{expiresIn|formatDurationTo}}).", + "IDENTITY_ALREADY_CERTIFY_PENDING": "Vi <b>jam atestis</b> tiun identecon.<br/><br/>Tiu atestado atendas traktadon (limdato de traktado {{expiresIn|formatDurationTo}}).", + "UNABLE_TO_CERTIFY_TITLE": "Atestado neebla", + "LOAD_NEWCOMERS_FAILED": "Malsukceso por ÅarÄi la novajn membrojn.", + "LOAD_PENDING_FAILED": "Malsukceso por ÅarÄi la atendantajn aliÄojn.", + "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "Vi devas <b>esti membro</b> por rajti efektivigi tiun ĉi agon.", + "ONLY_MEMBER_OR_WAS_MEMBER_CAN_EXECUTE_THIS_ACTION": "Vi devas <b>esti membro (aÅ eksa membro)</b> por rajti efektivigi tiun ĉi agon.", + "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "Via identeco devas <b>jam esti publikigita</b>, por ke vi rajtu efektivigi tiun ĉi agon.", + "GET_BLOCK_FAILED": "Malsukceso por ricevi la blokon.", + "INVALID_BLOCK_HASH": "Bloko ne trovita (haketo malsama)", + "DOWNLOAD_REVOCATION_FAILED": "Malsukceso por elÅuti la dosieron pri nuligo.", + "REVOCATION_FAILED": "Malsukceso pri nuligo.", + "SALT_OR_PASSWORD_NOT_CONFIRMED": "Sekreta identigilo aÅ pasvorto malÄusta.", + "RECOVER_ID_FAILED": "Malsukceso por ricevi la identigilojn", + "LOAD_FILE_FAILED" : "Malsukceso por ÅarÄi la dosieron", + "NOT_VALID_REVOCATION_FILE": "Dosiero pri nuligo ne valida (malÄusta strukturo de dosiero)", + "NOT_VALID_SAVE_ID_FILE": "Dosiero pri konservado ne valida (malÄusta strukturo de dosiero)", + "NOT_VALID_KEY_FILE": "Dosiero pri Ålosilaro ne valida (strukturo ne rekonata)", + "EXISTING_ACCOUNT": "Viaj identigiloj rilatas al jam ekzistanta konto, kies <a ng-click=\"showHelpModal('pubkey')\">publika Ålosilo</a> estas:", + "EXISTING_ACCOUNT_REQUEST": "Bonvolu modifi viajn identigilojn, por ke ili rilatu al ne uzata konto.", + "GET_LICENSE_FILE_FAILED": "La ricevo de la dosiero pri licenco ne eblis.", + "CHECK_NETWORK_CONNECTION": "Neniu nodo Åajnas atingebla.<br/><br/>Bonvolu <b>kontroli vian retkonekton</b>.", + "ISSUE_524_TX_FAILED": "Malsukcesa elspezo.<br/><br/>MesaÄo estis sendita al la programistoj por faciligi la solvadon de la problemo. <b>Dankon pro via helpo</b>.", + "ADD_SECONDARY_WALLET_FAILED": "Malsukceso por aldoni kroman monujon.", + "UPDATE_WALLET_LIST_FAILED": "Malsukceso por Äisdatigi la kromajn monujojn.", + "LOAD_WALLET_LIST_FAILED": "Malsukceso por ÅarÄi la kromajn monujojn.", + "SAVE_WALLET_LIST_FAILED": "Malsukceso por konservi la kromajn monujojn.", + "COULD_NOT_ADD_MAIN_WALLET": "Tiu ĉi monujo <b>rilatas al la ĉefa konto</b>, kun kiu vi estas konektita.<br/>Ne eblas aldoni Äin kiel kroman monujon.", + "COULD_NOT_ADD_EXISTING_WALLET": "Monujo jam ekzistanta en la listo.", + "UNKNOWN_WALLET_ID": "Kroma monujo nekonata.", + "RESTORE_WALLET_LIST_FAILED": "Malsukceso por restarigi la kromajn monujojn.", + "INVALID_FILE_FORMAT": "Strukturo de dosiero nevalida." + }, + "INFO": { + "POPUP_TITLE": "Informo", + "CERTIFICATION_DONE": "Atestaĵo sendita", + "NOT_ENOUGH_CREDIT": "Saldo nesufiĉa", + "TRANSFER_SENT": "Elspezo sendita", + "COPY_TO_CLIPBOARD_DONE": "Kopiita en la memoreto", + "MEMBERSHIP_OUT_SENT": "EksiÄo sendita", + "NOT_NEED_MEMBERSHIP": "Vi jam estas membro.", + "IDENTITY_WILL_MISSING_CERTIFICATIONS": "Al tiu ĉi identeco baldaÅ mankos atestaĵoj (almenaÅ {{willNeedCertificationCount}}).", + "IDENTITY_NEED_MEMBERSHIP": "Tiu ĉi identeco ne sendis aliÄo-peton. Tion Äi devos fari, se Äi deziras fariÄi membro.", + "HAS_ALTERNATIVE_IDENTITIES": "Ekzistas <b>pluraj identecoj</b> ligitaj kun tiu ĉi publika Ålosilo. <b>AntaŠĉia atestado</b>, pensu <a ng-click=\"doQuickFix('showSelectIdentities')\">trarigardi la aliajn identecojn</a> por elekti la Äustan, aÅ kontaktu la posedanton de la konto.", + "REVOCATION_SENT": "Nuligo sendita", + "REVOCATION_SENT_WAITING_PROCESS": "La <b>nuligo de tiu ĉi identeco</b> estis petita kaj atendas traktadon.", + "FEATURES_NOT_IMPLEMENTED": "Tiu ĉi funkciaro ankoraÅ estas programiÄanta.<br/>Kial ne <b>kontribui al Cesium</b>, por ekhavi Äin pli rapide? ;)", + "EMPTY_TX_HISTORY": "Neniu spezo elportota" + }, + "CONFIRM": { + "POPUP_TITLE": "<b>Konfirmo</b>", + "POPUP_WARNING_TITLE": "<b>Averto</b>", + "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Averto pri sekureco</b>", + "CERTIFY_RULES_TITLE_UID": "Atesti {{uid}}", + "CERTIFY_RULES": "<b class=\"assertive\">NE atestu</b> konton, se vi pensas ke:<br/><br/><ul><li>1.) Äi ne rilatas al persono <b>fizika kaj vivanta</b>.<li>2.) Äia posedanto <b>havas alian konton</b> jam atestitan.<li>3.) Äia posedanto malobservas (vole aÅ ne) la regulon 1 aÅ 2 (ekzemple atestante falsajn kontojn aÅ duoblajn).</ul><br/><b>Ĉu vi certas,</b> ke vi tamen volas atesti tiun ĉi identecon?", + "FULLSCREEN": "AfiÅi la programon plen-ekrane?", + "EXIT_APP": "Fermi la programon?", + "TRANSFER": "<b>Resumo de la elspezo</b> :<br/><br/><ul><li> - De: {{from}}</li><li> - Al: <b>{{to}}</b></li><li> - Sumo: <b>{{amount}} {{unit}}</b></li><li> - Komento: <i>{{comment}}</i></li></ul><br/><b>Ĉu vi certas, ke vi volas efektivigi tiun ĉi elspezon?</b>", + "TRANSFER_ALL": "<b>Resumo de la elspezo</b>:<br/><br/><ul><li> - De : {{from}}</li><li> - Al : <b>{{to}}</b></li><li> - Sumo: <b>{{amount}} {{unit}}</b></li><li> - Komento: <i>{{comment}}</i></li><br/><li> - Resto: <b>{{restAmount}} {{unit}}</b> al <b>{{restTo}}</b></li></ul><br/><b>Ĉu vi certas, ke vi volas efektivigi tiun ĉi elspezon?</b>", + "MEMBERSHIP_OUT": "Tiu ĉi ago estas <b>neinversigebla</b>.<br/></br/>Ĉu vi certas, ke vi volas <b>nuligi vian membro-konton</b>?", + "MEMBERSHIP_OUT_2": "Tiu ĉi ago estas <b>neinversigebla</b> !<br/><br/>Ĉu vi vere certas, ke vi volas <b>nuligi vian aliÄon</b> kiel membron?", + "LOGIN_UNUSED_WALLET_TITLE": "Tajperaro?", + "LOGIN_UNUSED_WALLET": "La konektita konto Åajnas <b>neaktiva</b>.<br/><br/>Temas probable pri <b>tajperaro</b> en viaj konekto-identigiloj. Bonvolu rekomenci, kontrolante ke <b>la publika Ålosilo estas tiu de via konto</b>.", + "FIX_IDENTITY": "La pseÅdonimo <b>{{uid}}</b> estos denove publikigita, anstataÅigante la malnovan publikigon, kiu finiÄis.<br/></br/><b>Ĉu vi certas</b>, ke vi volas daÅrigi?", + "FIX_MEMBERSHIP": "Via aliÄo-peto kiel membro tuj estos resendita.<br/></br/><b>Ĉu vi certas</b>, ke vi volas daÅrigi?", + "MEMBERSHIP": "Via aliÄo-peto kiel membro tuj estos sendita.<br/></br/><b>Ĉu vi certas</b>, ke vi volas daÅrigi?", + "RENEW_MEMBERSHIP": "Via aliÄo kiel membro tuj estos revalidigita.<br/></br/><b>Ĉu vi certas</b>, ke vi volas daÅrigi?", + "REVOKE_IDENTITY": "Vi estas <b>nuligonta definitive tiun ĉi identecon</b>.<br/><br/>La publika Ålosilo kaj la ligita pseÅdonimo <b>neniam plu povos esti uzataj</b> (por membro-konto). <br/></br/><b>Ĉu vi certas</b>, ke vi volas definitive nuligi tiun ĉi konton?", + "REVOKE_IDENTITY_2": "Tiu ĉi ago estas <b>neinversigebla</b>!<br/><br/>Ĉu vi vere certas, ke vi volas <b>definitive nuligi</b> tiun ĉi konton?", + "NOT_NEED_RENEW_MEMBERSHIP": "Via aliÄo ne bezonas esti revalidigita (Äi finiÄos nur post {{membershipExpiresIn|formatDuration}}).<br/></br/><b>Ĉu vi certas</b>, ke vi volas revalidigi vian aliÄon?", + "SAVE_BEFORE_LEAVE": "Ĉu vi volas <b>konservi viajn modifojn</b> antaÅ ol eliri el la paÄo?", + "SAVE_BEFORE_LEAVE_TITLE": "Modifoj ne registritaj", + "LOGOUT": "Ĉu vi certas, ke vi volas malkonektiÄi?", + "USE_FALLBACK_NODE": "Nodo <b>{{old}}</b> neatingebla aÅ adreso nevalida.<br/><br/>Ĉu vi volas provizore uzi la nodon <b>{{new}}</b> ?", + "ISSUE_524_SEND_LOG": "La spezo estis forĵetita, pro konata anomalio (petslipo #524) sed <b>ne ripetita</b>.<br/><br/>Por helpi la programistojn korekti tiun eraron, <b>ĉu vi akceptas la sendadon de viaj protokolaj dosieroj</b> per mesaÄo?<br/><small>(neniu konfidenca dateno estas sendita)</small>." + }, + "DOWNLOAD": { + "POPUP_TITLE": "<b>Dosiero pri nuligo</b>", + "POPUP_REVOKE_MESSAGE": "Por sekurigi vian konton, bonvolu elÅuti la <b>dokumenton pri konto-nuligo</b>. Äœi ebligos al vi eventuale nuligi vian konton (kaze de konto-Åtelo, ÅanÄo de identigilo, konto erare kreita, ktp.).<br/><br/><b>Bonvolu stoki Äin en sekura loko.</b>" + }, + "HELP": { + "TITLE": "Ret-helpo", + "JOIN": { + "SECTION": "EnskribiÄo", + "SALT": "La sekreta identigilo estas tre grava. Äœi utilas por miksi la pasvorton, antaÅ ol Äi servos por kalkuli la <span class=\"text-italic\">publikan Ålosilon</span> de via konto (ties numeron) kaj la sekretan Ålosilon por aliri Äin.<br/><b>Zorgu pri Äia bona memorigado</b>, ĉar neniu rimedo estas nuntempe planita por retrovi Äin kaze de perdo.<br/>Krom tio, Äi ne povas esti modifita sen devige krei novan konton.<br/><br/>Bona sekreta identigilo devas esti sufiĉe longa (kun almenaÅ 8 signoj) kaj kiel eble plej originala.", + "PASSWORD": "La pasvorto estas tre grava. Kun la sekreta identigilo, Äi servas por kalkuli la numeron (la publikan Ålosilon) de via konto, kaj la sekretan Ålosilon por aliri Äin.<br/><b>Zorgu pri Äia bona memorigado</b>, ĉar neniu rimedo estas planita por retrovi Äin kaze de perdo (krom se oni generas konserv-dosieron).<br/>Krom tio, Äi ne povas esti modifita sen devige krei novan konton.<br/><br/>Bona pasvorto entenas (ideale) almenaÅ 8 signojn, inter kiuj estas almenaÅ unu majusklo kaj unu cifero.", + "PSEUDO": "La pseÅdonimo estas utila nur kaze de enskribiÄo kiel <span class=\"text-italic\">membro</span>. Äœi ĉiam estas ligita kun monujo (tra Äia <span class=\"text-italic\">publika Ålosilo</span>).<br/>Äœi estas publikigita en la reto, tiel ke la aliaj uzantoj povu identigi Äin, atesti Äin aÅ sendi monon al Äia konto.<br/>PseÅdonimo devas esti unika ene de la membroj (<u>nunaj</u> kaj eksaj)." + }, + "LOGIN": { + "SECTION": "Konekto", + "PUBKEY": "Publika Ålosilo de la Ålosilaro", + "PUBKEY_DEF": "La publika Ålosilo de la Ålosilaro estas kreita per la tajpitaj identigiloj (iuj ajn), sen ke ili necese rilatu al konto jam uzata.<br/><b>Atente kontrolu, ke la publika Ålosilo estas tiu de via konto</b>. Alikaze, vi estos konektita al konto probable neniam uzita, la risko de kolizio kun ekzistanta konto estante tre eta.<br/><a href=\"https://fr.wikipedia.org/wiki/Cryptographie_asym%C3%A9trique\" target=\"_system\">Scii pli pri kriptografio</a> per publika Ålosilo.", + "METHOD": "Konekto-metodoj", + "METHOD_DEF": "Pluraj eblecoj disponeblas por konekti vin al monujo:<br/> - La konekto <b>per salumado (simpla aÅ sperta)</b> miksas vian pasvorton dank'al la sekreta identigilo, por limigi la provojn de <a href=\"https://fr.wikipedia.org/wiki/Attaque_par_force_brute\" target=\"_system\">kodrompado per kruda forto</a> (ekzemple per konataj vortoj.<br/> - La konekto <b>per publika Ålosilo</b> evitigas tajpi viajn identigilojn, kiuj estos petataj de vi, nur kiam venos la momento dum operacio ĉe la konto.<br/> - La konekto <b>per dosiero pri Ålosilaro</b> legas la Ålosilojn (publikan kaj privatan) de la konto, per dosiero, sen la bezono tajpi identigilojn. Pluraj strukturoj de dosiero eblas." + }, + "GLOSSARY": { + "SECTION": "Glosaro", + "PUBKEY_DEF": "Publika Ålosilo identigas monujon, kiu povas identigi membron aÅ rilati al anonima monujo. Ĉe Cesium la publika Ålosilo estas kalkulita (implicite) dank'al la sekreta identigilo kaj la pasvorto.<br/><a href=\"https://fr.wikipedia.org/wiki/Cryptographie_asym%C3%A9trique\" target=\"_system\">Scii pli pri kriptografio</a> per publika Ålosilo.", + "MEMBER": "Membro", + "MEMBER_DEF": "Membro estas homa persono fizika kaj vivanta, kiu deziras libere partopreni en la mona komunumo. Li/Åi kunproduktas universalan dividendon, laÅ periodo kaj sumo tiel difinitaj kiel en la <span class=\"text-italic\">reguloj de la mono</span>", + "CURRENCY_RULES": "Reguloj de la mono", + "CURRENCY_RULES_DEF": "La reguloj de la mono estas difinitaj definitive. Ili fiksas la funkciadon de la mono: la kalkulon de la universala dividendo, la nombron de necesaj atestaĵoj por esti membro, la maksimuman nombron da atestaĵoj, kiujn povas doni unu membro, ktp. <a href=\"#/app/currency\">Vidi la nuntempajn regulojn</a>.<br/>La nemodifo de la reguloj tra la tempo eblas per uzado de <span class=\"text-italic\">Blokĉeno</span>, kiu entenas kaj plenumas tiujn regulojn, kaj konstante kontrolas ties Äustan aplikadon.", + "BLOCKCHAIN": "Ĉeno de blokoj (<span class=\"text-italic\">Blokchain/Blokĉeno</span>)", + "BLOCKCHAIN_DEF": "La Blokĉeno estas malcentrigita sistemo, kiu, kaze de Duniter, servas por enteni kaj plenumi la <span class=\"text-italic\">regulojn de la mono</span>.<br/><a href=\"https://duniter.org/fr/comprendre/\" target=\"_system\">Scii pli pri Duniter</a> kaj la funkciado de ties blokĉeno.", + "UNIVERSAL_DIVIDEND_DEF": "La Universala Dividendo (UD) estas la kvanto de mono kunkreita de ĉiu membro, laÅ la periodo kaj kalkulo difinitaj en la <span class=\"text-italic\">reguloj de la mono</span>.<br/>Por ĉiu perioda dato, la membroj ricevas en sian konton la saman kvanton da nova mono.<br/><br/>La UD spertas regulan kreskon, por resti justa inter la membroj (nunaj kaj venontaj), kalkulitan depende de la meza vivespero, kiel estas demonstrite en la Teorio Relativa pri la Mono (TRM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Scii pli pri la TRM</a> kaj la liberaj monoj.", + "WOT": "Reto de Fido (RdF)", + "WOT_DEF": "La Reto de Fido konsistas el la tuto de la membroj de la mono, kaj el la atesto-ligoj, kiuj kunligas ilin.", + "DISTANCE_RULE": "Regulo pri distanco", + "DISTANCE_RULE_DEF": "La regulo pri distanco de la Reto de Fido difinas <b>maksimuman distancon nepran</b> inter petanto kaj minimuma nombro da referencaj membroj (aÅ centraj membroj). Tiu distanco estas kalkulita uzante la ligojn inter atestaĵoj." + }, + "TIP": { + "MENU_BTN_CURRENCY": "La menuo <b>{{'MENU.CURRENCY'|translate}}</b> ebligas konsulti la <b>regulojn de la mono</b> kaj ties staton.", + "CURRENCY_WOT": "La <b>nombro de membroj</b> montras la gravecon de la komunumo kaj ebligas <b>sekvi ties evoluon</b>.", + "CURRENCY_MASS": "Sekvu ĉi tie la <b>ĉioman kvanton da mono</b> ekzistanta kaj ties <b>mezan distribuon</b> por membro.<br/><br/>Tio ĉi ebligas taksi la <b>gravecon de iu sumo</b>, kompare kun tio, kion <b>posedas la aliuloj</b> en sia konto (mezume).", + "CURRENCY_UNIT_RELATIVE": "La unuo uzata (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) signifas, ke la sumoj en {{currency|capitalize}} estis dividitaj per la <b> Universala Dividendo</b> (UD).<br/><br/><small>Tiu relativa unuo estas <b>trafa</b>, ĉar stabila malgraÅ la kvanto de mono, kiu kreskas seninterrompe.</small>", + "CURRENCY_CHANGE_UNIT": "La kromaĵo <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> ebligas <b>ÅanÄi la unuon</b>, por vidigi la sumojn <b>rekte en {{currency|capitalize}}</b> (prefere ol en “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”).", + "CURRENCY_CHANGE_UNIT_TO_RELATIVE": "La kromaĵo <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> ebligas <b>ÅanÄi la unuon</b>, por vidigi la sumojn en “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”, tio estas rilate al la Universala Dividendo (la sumo kunproduktita de ĉiu membro).", + "CURRENCY_RULES": "La <b>reguloj</b> de la mono fiksas ties funkciadon <b>Äustan kaj antaÅvideblan</b>.<br/><br/>Vera DNA de la mono, ili igas sian monan kodon <b>legebla kaj travidebla</b>.", + "MENU_BTN_NETWORK": "La menuo <b>{{'MENU.NETWORK'|translate}}</b> ebligas konsulti la staton de la reto.", + "NETWORK_BLOCKCHAIN": "Ĉiuj operacioj pri la mono estas registritaj en granda konto-libro <b>publika kaj nefalsigebla</b>, ankaÅ nomata <b>blokĉeno</b> (<em>BlockChain</em> en la angla).", + "NETWORK_PEERS": "La <b>nodoj</b> videblaj ĉi tie rilatas al la <b>komputiloj, kiuj Äisdatigas kaj kontrolas</b> la blokĉenon.<br/><br/>Ju pli estas nodoj, des pli la mono havas administradon <b>malcentrigitan</b> kaj fidindan.", + "NETWORK_PEERS_BLOCK_NUMBER": "Tiu ĉi <b>numero</b> (verda) indikas la <b>lastan blokon validigitan</b> por tiu ĉi nodo (lasta paÄo skribita en la granda konto-libro).<br/><br/>La verda koloro indikas, ke tiu ĉi bloko estas validigita ankaÅ de <b>la plej multaj el la aliaj nodoj</b>.", + "NETWORK_PEERS_PARTICIPATE": "<b>Ĉiu membro</b>, ekipita per komputilo kun interreto, <b>povas partopreni aldonante nodon</b>. Sufiĉas <b>instali la programon Duniter</b> (libera kaj senpaga). <a href=\"{{installDocUrl}}\" target=\"_system\">Vidi la gvidilon pri instalado >></a>.", + "MENU_BTN_ACCOUNT": "La menuo <b>{{'ACCOUNT.TITLE'|translate}}</b> ebligas aliri la administradon de via konto.", + "MENU_BTN_ACCOUNT_MEMBER": "Konsultu ĉi tie la staton de via konto kaj la informojn pri viaj atestaĵoj.", + "WALLET_CERTIFICATIONS": "Alklaku ĉi tien por konsulti la detalon pri viaj atestaĵoj (ricevitaj kaj senditaj).", + "WALLET_RECEIVED_CERTIFICATIONS": "Alklaku ĉi tien por konsulti la detalon pri viaj <b>ricevitaj atestaĵoj</b>.", + "WALLET_GIVEN_CERTIFICATIONS": "Alklaku ĉi tien por konsulti la detalon pri viaj <b>senditaj atestaĵoj</b>.", + "WALLET_BALANCE": "La <b>saldo</b> de via konto afiÅiÄas tie ĉi.", + "WALLET_BALANCE_RELATIVE": "{{'HELP.TIP.WALLET_BALANCE'|translate}}<br/><br/>La uzata unuo (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) signifas, ke la sumo en {{currency|capitalize}} estis dividita per la <b>Universala Dividendo</b> (UD) kunkreita de ĉiu membro.<br/><br/>Nuntempe 1 UD valoras {{currentUD|formatInteger}} {{currency|capitalize}}j.", + "WALLET_BALANCE_CHANGE_UNIT": "Vi povos <b>ÅanÄi la unuon</b> afiÅitan por la sumoj en la <b><i class=\"icon ion-android-settings\"></i> {{'MENU.SETTINGS'|translate}}</b>.<br/><br/>Ekzemple por vidigi la sumojn <b>rekte en {{currency|capitalize}}</b>, prefere ol en relativa unuo.", + "WALLET_PUBKEY": "Jen la publika Ålosilo de via konto. Vi povas sciigi Äin al aliulo, por ke li identigu pli simple vian konton.", + "WALLET_SEND": "Efektivigi pagon per kelkaj klakoj.", + "WALLET_SEND_NO_MONEY": "Efektivigi pagon per kelkaj klakoj.<br/>(Via saldo ankoraÅ ne permesas tion)", + "WALLET_OPTIONS": "Tiu ĉi butono ebligas aliri la <b>agojn pri aliÄo</b> kaj sekureco.<br/><br/>Ne forgesu okulumi al Äi!", + "WALLET_RECEIVED_CERTS": "AfiÅiÄos ĉi tie la listo de la personoj, kiuj atestis vin.", + "WALLET_CERTIFY": "La butono <b>{{'WOT.BTN_SELECT_AND_CERTIFY'|translate}}</b> ebligas elekti identecon kaj atesti Äin.<br/><br/>Nur uzantoj <b>jam membroj</b> povas atesti aliajn.", + "WALLET_CERT_STOCK": "Via stoko da atestaĵoj (senditaj) estas limigita je <b>{{sigStock}} atestaĵoj</b>.<br/><br/>Tiu stoko plu evoluas laÅ la tempo, samtempe kiam la atestaĵoj malvalidiÄas.", + "MENU_BTN_TX_MEMBER": "La menuo <b>{{'MENU.TRANSACTIONS'|translate}}</b> ebligas konsulti vian konton, la liston de viaj spezoj, kaj sendi pagon.", + "MENU_BTN_TX": "Konsultu ĉi tie <b>la liston de viaj spezoj</b> kaj efektivigu novajn operaciojn.", + "MENU_BTN_WOT": "La menuo <b>{{'MENU.WOT'|translate}}</b> ebligas traserĉi inter la <b>uzantoj</b> de la mono (membroj aÅ ne).", + "WOT_SEARCH_TEXT_XS": "Por traserĉi en la kontaro, tajpu la <b>unuajn literojn de pseÅdonimo</b> (aÅ de publika Ålosilo).<br/><br/>La serĉado ekos aÅtomate.", + "WOT_SEARCH_TEXT": "Por traserĉi en la kontaro, tajpu la <b>unuajn literojn de de pseÅdonimo</b> (aÅ de publika Ålosilo). <br/><br/>Premu poste sur la klavon <b>Enigi</b> por ekigi la serĉadon.", + "WOT_SEARCH_RESULT": "Vidigu la detalan slipon simple <b>alklakante</b> linion.", + "WOT_VIEW_CERTIFICATIONS": "La linio <b>{{'ACCOUNT.CERTIFICATION_COUNT'|translate}}</b> montras kiom da membroj validigis tiun ĉi identecon.<br/><br/>Tiuj atestaĵoj pruvas, ke la konto apartenas al <b>persono homa kaj vivanta</b>, havanta <b>neniun alian membro-konton</b>.", + "WOT_VIEW_CERTIFICATIONS_COUNT": "Necesas almenaÅ <b>{{sigQty}} atestaĵoj</b> por fariÄi membro kaj ricevi la <b>Universalan Dividendon</b>.", + "WOT_VIEW_CERTIFICATIONS_CLICK": "Alklaki ĉi tien ebligas malfermi <b>la liston de ĉiuj atestaĵoj</b> de la identeco (ricevitaj kaj senditaj).", + "WOT_VIEW_CERTIFY": "La butono <b>{{'WOT.BTN_CERTIFY'|translate}}</b> ebligas aldoni vian atestaĵon al tiu identeco.", + "CERTIFY_RULES": "<b>Atenton:</b> Atestu nur <b>personojn fizikajn vivantajn</b>, posedantajn neniun alian membro-konton.<br/><br/>La sekureco de la mono dependas de ĉies atentego!", + "MENU_BTN_SETTINGS": "La <b>{{'MENU.SETTINGS'|translate}}</b> ebligos al vi agordi la programon.", + "HEADER_BAR_BTN_PROFILE": "Alklaku ĉi tien por aliri vian <b>uzanto-profilon.</b>", + "SETTINGS_CHANGE_UNIT": "Vi povos <b>ÅanÄi la afiÅ-unuon</b> de la sumoj alklakante ĉi-supren.<br/><br/>- Malaktivigu la kromaĵon por afiÅi sumojn en {{currency|capitalize}}.<br/>- Aktivigu la kromaĵon por relativa afiÅado en {{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub> (ĉiuj sumoj estos <b>dividitaj</b> per la Universala Dividendo aktuala).", + "END_LOGIN": "Tiu ĉi gvidata vizito <b>finiÄis</b>!<br/><br/>Bonan daÅrigon al vi, en la nova mondo de la<b>libera ekonomio</b>!", + "END_NOT_LOGIN": "Tiu ĉi gvidata vizito <b>finiÄis</b>!<br/><br/>Se vi deziras partopreni en la mono {{currency|capitalize}}, sufiĉos al vi alklaki <b>{{'LOGIN.CREATE_ACCOUNT'|translate}}</b> ĉi-sube." + } + }, + "API" :{ + "COMMON": { + "LINK_DOC": "Dokumentaro API", + "LINK_DOC_HELP": "Dokumentaro por la programistoj", + "LINK_STANDARD_APP": "Klasika versio", + "LINK_STANDARD_APP_HELP": "Malfermi la klasikan version de {{'COMMON.APP_NAME'|translate}}", + "CONNECTION_ERROR": "Nodo <b>{{server}}</b> neatingebla aÅ adreso nevalida.<br/><br/>Kontrolu vian interretan konekton, aÅ kontaktu la administranton de la retejo</a>." + }, + "HOME": { + "TITLE": "Dokumentaro API {{'COMMON.APP_NAME'|translate}}", + "MESSAGE": "Bonvenon en la <b>dokumentaro de la API</b> {{'COMMON.APP_NAME'|translate}}.<br/>Konektu viajn retejojn al <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> tre simple!", + "MESSAGE_SHORT": "Konektu viajn retejojn al <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> tre simple!", + "DOC_HEADER": "Servoj disponeblaj:" + }, + "TRANSFER": { + "TITLE": "{{'COMMON.APP_NAME'|translate}} - Reta pago", + "TITLE_SHORT": "Reta pago", + "SUMMARY": "Resumo de la pago:", + "AMOUNT": "Sumo:", + "AMOUNTS_HELP": "Bonvolu elekti la sumon:", + "NAME": "Nomo:", + "PUBKEY": "Publika Ålosilo de la ricevonto:", + "COMMENT": "Referenco de la spezo:", + "NODE": "Adreso de la nodo:", + "DEMO": { + "SALT": "demo", + "PASSWORD": "demo", + "PUBKEY": "3G28bL6deXQBYpPBpLFuECo46d3kfYMJwst7uhdVBnD1", + "HELP": "<b>Demonstra moduso</b>: Neniu pago reale estos sendita dum tiu simulado.<br/>Bonvolu uzi la identigilojn: <b>{{'API.TRANSFER.DEMO.SALT'|translate}} / {{'API.TRANSFER.DEMO.PASSWORD'|translate}}</b>", + "BAD_CREDENTIALS": "Kontrolu vian tajpaĵon.<br/>En demonstra moduso, la identigiloj estas: {{'API.TRANSFER.DEMO.SALT'|translate}} / {{'API.TRANSFER.DEMO.PASSWORD'|translate}}" + }, + "INFO": { + "SUCCESS_REDIRECTING_WITH_NAME": "Pago sendita.<br/>RedirektiÄo al <b>{{name}}</b>...", + "SUCCESS_REDIRECTING": "Pago sendita.<br/>RedirektiÄo al la retejo de la vendanto...", + "CANCEL_REDIRECTING_WITH_NAME": "Pago nuligita.<br/>RedirektiÄo al <b>{{name}}</b>...", + "CANCEL_REDIRECTING": "Pago nuligita.<br/>RedirektiÄo al la retejo de la vendanto..." + }, + "ERROR": { + "TRANSFER_FAILED": "Pago malsukcesa" + } + }, + "DOC": { + "DESCRIPTION_DIVIDER": "Priskribo", + "URL_DIVIDER": "Adreso alvokita", + "PARAMETERS_DIVIDER": "Parametroj", + "AVAILABLE_PARAMETERS": "Jen la listo de la eblaj parametroj:", + "DEMO_DIVIDER": "Testi", + "DEMO_HELP": "Por testi tiun servon, alklaku la butonon ĉi-apude. La rezulto afiÅiÄos sube.", + "DEMO_RESULT": "Rezulto sendita de la alvoko:", + "DEMO_RESULT_PEER": "Adreso de la uzata nodo:", + "DEMO_SUCCEED": "<i class=\"icon ion-checkmark\"></i> Sukceso!", + "DEMO_CANCELLED": "<i class=\"icon ion-close\"></i> Nuligita de la uzanto", + "INTEGRATE_DIVIDER": "Integri", + "INTEGRATE_CODE": "Kodo:", + "INTEGRATE_RESULT": "AntaÅvidigo de la rezulto:", + "INTEGRATE_PARAMETERS": "Parametroj", + "TRANSFER": { + "TITLE": "Pagoj", + "DESCRIPTION": "De retejo (ekz.: ret-vendado) vi povas komisii la pagon en libera mono al Cesium API. Por tio, sufiĉas al vi ekigi la malfermon de paÄo ĉe la sekvanta adreso:", + "PARAM_PUBKEY": "Publika Ålosilo de la ricevonto", + "PARAM_PUBKEY_HELP": "Publika Ålosilo de la ricevonto (devige)", + "PARAM_AMOUNT": "Sumo", + "PARAM_AMOUNT_HELP": "Sumo de la spezo (devige). Pluraj valoroj permesataj, uzante apartigilon (punkto-komo, vertikala streko aÅ spaco).", + "PARAM_COMMENT": "Referenco (aÅ komento)", + "PARAM_COMMENT_HELP": "Referenco aÅ komento. Tio ekzemple ebligos al vi identigi la pagon en la blokĉeno.", + "PARAM_NAME": "Nomo (de la ricevonto aÅ de la retejo)", + "PARAM_NAME_HELP": "La nomo de la ricevonto, aÅ de la retejo alvokanta. Tio povas estis legebla nomo (\"Mia retejo\"), aÅ alie pseÅdo-retadreso (\"MiaRetejo.com\").", + "PARAM_REDIRECT_URL": "Retadreso por redirektiÄo", + "PARAM_REDIRECT_URL_HELP": "Retadreso (URL) por redirektiÄo, alvokita kiam la pago estis sendita. Äœi povas enteni la sekvantajn signojn, kiuj estos anstataÅigitaj per la valoroj de la spezo: \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\", \"{pubkey}\" kaj \"{node}\".", + "PARAM_CANCEL_URL": "Retadreso por nuligo", + "PARAM_CANCEL_URL_HELP": "Retadreso (URL) kaze de nuligo de la pago, fare de la uzanto. Äœi povas enteni la sekvantajn signojn, kiuj estos anstataÅigitaj lastmomente: \"{comment}\", \"{amount}\" kaj {pubkey}.", + "PARAM_PREFERRED_NODE": "Adreso de la preferata nodo", + "PARAM_PREFERRED_NODE_HELP": "Adreso (URL) de la nodo Duniter preferinde uzota (\"g1.domaine.com:443\" aÅ \"https://g1.domaine.com\").", + "EXAMPLES_HELP": "Jen ekzemploj pri integrado:", + "EXAMPLE_BUTTON": "Butono HTML", + "EXAMPLE_BUTTON_DEFAULT_TEXT": "Pagi en {{currency|currencySymbol}}", + "EXAMPLE_BUTTON_DEFAULT_STYLE": "Personigita stilo", + "EXAMPLE_BUTTON_TEXT_HELP": "Buton-teksto", + "EXAMPLE_BUTTON_BG_COLOR": "Fon-koloro", + "EXAMPLE_BUTTON_BG_COLOR_HELP": "Ekzemplo: #fbc14c, nigra, helgriza, rgb(180,180,180)", + "EXAMPLE_BUTTON_FONT_COLOR": "Teksto-koloro", + "EXAMPLE_BUTTON_FONT_COLOR_HELP": "Ekzemplo: nigra, oranÄa, rgb(180,180,180)", + "EXAMPLE_BUTTON_TEXT_ICON": "Ikono", + "EXAMPLE_BUTTON_TEXT_WIDTH": "LarÄeco", + "EXAMPLE_BUTTON_TEXT_WIDTH_HELP": "Ekzemplo: 200px, 50%", + "EXAMPLE_BUTTON_ICON_NONE": "Neniu", + "EXAMPLE_BUTTON_ICON_DUNITER": "Insigno Duniter", + "EXAMPLE_BUTTON_ICON_CESIUM": "Insigno Cesium", + "EXAMPLE_BUTTON_ICON_G1_COLOR": "Insigno Äž1", + "EXAMPLE_BUTTON_ICON_G1_BLACK": "Insigno Äž1 (nigra)" + } + } + } +} diff --git a/assets/www/i18n/locale-es-ES.json b/assets/www/i18n/locale-es-ES.json index eacfbe28214d2f0777d2a504ac6b829d458117c4..b34ee808529324ebdaa0bc8ef42caa6248bd825d 100644 --- a/assets/www/i18n/locale-es-ES.json +++ b/assets/www/i18n/locale-es-ES.json @@ -17,9 +17,10 @@ "BTN_YES_CONTINUE": "SÃ, continuar", "BTN_SHOW": "Ver", "BTN_SHOW_PUBKEY": "Ver la llave", - "BTN_RELATIVE_UNIT": "¿Visualizar en unidad relativa?", + "BTN_RELATIVE_UNIT": "¿Mostrar las importes en DU?", "BTN_BACK": "Anterior", "BTN_NEXT": "Siguiente", + "BTN_IMPORT": "Importar", "BTN_CANCEL": "Cancelar", "BTN_CLOSE": "Cerrar", "BTN_LATER": "Más tarde", @@ -48,6 +49,7 @@ "NO_ACCOUNT_QUESTION": "¿TodavÃa no es miembro? ¡Crear una cuenta!", "SEARCH_NO_RESULT": "Ningún resultado encontrado", "LOADING": "Espere por favor...", + "LOADING_WAIT": "Espere por favor...<br/><small>(Esperando disponibilidad de nodo)</small>", "SEARCHING": "Búsqueda en proceso...", "FROM": "De", "TO": "A", @@ -77,6 +79,12 @@ "SHARE_ON_FACEBOOK": "Compartir en Facebook", "SHARE_ON_DIASPORA": "Compartir en Diaspora*", "SHARE_ON_GOOGLEPLUS": "Compartir en Google+" + }, + "FILE": { + "DATE" : "Fecha:", + "TYPE" : "Tipo:", + "SIZE": "Tamaño:", + "VALIDATING": "Validación en progreso..." } }, "SYSTEM": { @@ -89,6 +97,7 @@ "WOT": "Directorio", "CURRENCY": "Moneda", "ACCOUNT": "Mi cuenta", + "WALLETS": "Mis monederos", "TRANSFER": "Transferencia", "SCAN": "Escáner", "SETTINGS": "Configuraciones", @@ -97,7 +106,7 @@ }, "ABOUT": { "TITLE": "A propósito ", - "LICENSE": "Aplicación <b>libre</b> (licencia GNU GPLv3).", + "LICENSE": "Aplicación <b>libre</b> (licencia GNU AGPLv3).", "LATEST_RELEASE": "Hay una <b>versión más nueva</b> de {{'COMMON.APP_NAME' | translate}} (<b>v{{version}}</b>)", "PLEASE_UPDATE": "Por favor actualice {{'COMMON.APP_NAME' | translate}} (última versión: <b>v{{version}}</b>)", "CODE": "Código fuente:", @@ -120,18 +129,25 @@ }, "SETTINGS": { "TITLE": "Configuración", + "DISPLAY_DIVIDER": "Visualización", + "STORAGE_DIVIDER": "Almacenamiento", "NETWORK_SETTINGS": "Red", "PEER": "Dirección del nodo Duniter", "PEER_CHANGED_TEMPORARY": "Dirección utilizada temporalmente", "USE_LOCAL_STORAGE": "Activar el almacenamiento local", "USE_LOCAL_STORAGE_HELP": "Permitir el ahorro de almacenamiento local", + "WALLETS_SETTINGS": "Mis monederos", + "USE_WALLETS_ENCRYPTION": "¿Asegurar la lista?", "ENABLE_HELPTIP": "Activar las ayudas contextuales", "ENABLE_UI_EFFECTS": "Activar los efectos visuales", "HISTORY_SETTINGS": "Operaciones de cuentas", "DISPLAY_UD_HISTORY": "¿Publicar los dividendos producidos?", + "TX_HISTORY_AUTO_REFRESH": "Activar actualización automática?", + "TX_HISTORY_AUTO_REFRESH_HELP": "Actualice el saldo y las operaciones automáticamente, en cada nuevo bloque.", "AUTHENTICATION_SETTINGS": "Autenticación", "KEEP_AUTH": "Caducidad de la autenticación", - "KEEP_AUTH_HELP": "Definir cuándo limpiar la memoria de autenticación", + "KEEP_AUTH_SHORT": "Caducidad", + "KEEP_AUTH_HELP": "Definir cuándo limpiar la memoria de autenticación.", "KEEP_AUTH_OPTION": { "NEVER": "Después de cada operación", "SECONDS": "Después de {{value}} segundos de inactividad", @@ -140,6 +156,7 @@ "HOUR": "Después de {{value}}h de inactividad", "ALWAYS": "Al finalizar la sesión" }, + "KEYRING_FILE": "Archivo de llavero", "REMEMBER_ME": "Recordarme", "REMEMBER_ME_HELP": "Permite mantenerse siempre conectado (no recomendado), conservando localmente la llave pública.", "PLUGINS_SETTINGS": "Extensiones", @@ -210,7 +227,7 @@ "TAB_WOT": "Red de confianza", "TAB_NETWORK": "Red", "TAB_BLOCKS": "Bloques", - "CURRENCY_SHORT_DESCRIPTION": "{{currency|capitalizar}} es una <b>moneda libre</b>, originada el {{firstBlockTime|formatFromNow}}. Ella cuenta actualmente <b>{{N}} miembros</b>, que producen y recibir un <a ng-click=\"showHelpModal('ud')\">Dividendo universal</a> (DU), cada {{dt|formatPeriod}}.", + "CURRENCY_SHORT_DESCRIPTION": "{{currency|abbreviate}} es una <b>moneda libre</b>, originada el {{firstBlockTime|formatFromNow}}. Ella cuenta actualmente <b>{{N}} miembros</b>, que producen y recibir un <a ng-click=\"showHelpModal('ud')\">Dividendo universal</a> (DU), cada {{dt|formatPeriod}}.", "NETWORK_RULES_DIVIDER": "Reglas de la red", "CURRENCY_NAME": "Nombre de la moneda", "MEMBERS": "Cantidad de miembros", @@ -263,6 +280,7 @@ "WARN_PRE_RELEASE": "prelanzamiento (última versión estable: <b>{{version}}</b>)", "WARN_NEW_RELEASE": "Versión <b>{{version}}</b> disponible", "WS2PID": "ID:", + "PRIVATE_ACCESS": "Acceso privado", "POW_PREFIX": "Prefijo de la prueba de trabajo:", "ENDPOINTS": { "BMAS": "Interfaz segura (SSL)", @@ -279,20 +297,23 @@ "PEERS": "Nodos", "SIGNED_ON_BLOCK": "Firmado sobre el bloque", "MIRROR": "espejo", - "MIRRORS": "Nodos espejo", + "MIRRORS": "Espejo", + "MIRROR_PEERS": "Nodos espejo", "PEER_LIST": "Lista de nodos", - "MEMBERS": "Nodos miembro", + "MEMBERS": "Miembro", + "MEMBER_PEERS": "Nodos miembro", "ALL_PEERS": "Todos los nodos", "DIFFICULTY": "Dificultad", "API": "API", "CURRENT_BLOCK": "Bloque #", "POPOVER_FILTER_TITLE": "Filtro", - "OFFLINE": "Nodos fuera de lÃnea", + "OFFLINE": "Fuera de lÃnea", + "OFFLINE_PEERS": "Nodos fuera de lÃnea", "BTN_SHOW_PEER": "Ver nodo", "VIEW": { "TITLE": "Nodo", "OWNER": "Propiedad de", - "SHOW_RAW_PEERING": "Ver la tarjeta de red", + "SHOW_RAW_PEERING": "Ver la mapa de red", "SHOW_RAW_CURRENT_BLOCK": "Ver el último bloque (formato bruto)", "LAST_BLOCKS": "Bloques recientes", "KNOWN_PEERS": "Nodos conocidos:", @@ -337,7 +358,7 @@ "PENDING": "Inscripciones en espera:", "PENDING_COUNT": "{{count}} inscripciones en espera", "REGISTERED": "Inscrito {{sigDate | formatFromNow}}", - "MEMBER_FROM": "Miembro desde {{memberDate|formatFromNowShort}}", + "MEMBER_FROM": "Miembro desde {{memberDate|medianFromNowShort}}", "BTN_NEWCOMERS": "Nuevos miembros", "BTN_PENDING": "Inscripciones en espera", "SHOW_MORE": "Mostrar más", @@ -376,38 +397,74 @@ }, "LOGIN": { "TITLE": "<i class=\"icon ion-locked\"></i> Conexión", + "SCRYPT_FORM_HELP": "Ingrese sus credenciales.<br>Recuerde verificar que la clave pública es su cuenta.", + "PUBKEY_FORM_HELP": "Por favor ingrese una clave de cuenta pública:", + "FILE_FORM_HELP": "Elija el archivo de llavero para usar:", + "SCAN_FORM_HELP": "Escanee el código QR de la monedero.", "SALT": "Identificador secreto", "SALT_HELP": "Identificador secreto", "SHOW_SALT": "¿Visualizar el identificador secreto?", "PASSWORD": "Frase secreta", "PASSWORD_HELP": "Frase secreta", - "PUBKEY_HELP": "Ejemplo: «AbsxSY4qoZRzyV2irfep1V9xw1EMNyKJw2TkuVD4N1mv»", + "PUBKEY_HELP": "llave pública", "NO_ACCOUNT_QUESTION": "¿Aún no tiene cuenta?", + "HAVE_ACCOUNT_QUESTION": "¿Ya tienes una cuenta?", "CREATE_ACCOUNT": "Crear una cuenta", + "CREATE_FREE_ACCOUNT": "Crear una cuenta gratis", "FORGOTTEN_ID": "¿Olvidó su frase secreta?", + "ASSOCIATED_PUBKEY": "Clave pública del llavero:", + "BTN_METHODS": "Otros métodos", + "BTN_METHODS_DOTS": "Método de cambio...", + "METHOD_POPOVER_TITLE": "Métodos", + "MEMORIZE_AUTH_FILE": "Recuerda este llavero al momento de la sesión de navegación", + "SCRYPT_PARAMETERS": "Configuraciones (Scrypt) :", "AUTO_LOGOUT": { "TITLE": "Información", "MESSAGE": "<i class=\"ion-android-time\"></i> Se ha <b>desconectado</b> de forma automática, después de un periodo de inactividad prolongada.", "BTN_RELOGIN": "Volver a conectarme", "IDLE_WARNING": "Se desconectará en... {{countdown}}" + }, + "METHOD": { + "SCRYPT_DEFAULT": "Identificación predeterminada", + "SCRYPT_ADVANCED": "Sallaje avanzado", + "FILE": "Archivo llavero", + "PUBKEY": "Solo clave pública", + "SCAN": "Escanear un código QR" + }, + "SCRYPT": { + "SIMPLE": "Ligero", + "DEFAULT": "Predeterminado", + "SECURE": "Seguro", + "HARDEST": "El más seguro", + "EXTREME": "Extremo", + "USER": "Personalizado", + "N": "N (Loop):", + "r": "r (RAM):", + "p": "p (CPU):" + }, + "FILE": { + "HELP": "Formato de archivo esperado: <b>.yml</b> o <b>.dunikey</b> (tipo PubSec, WIF o EWIF)." } }, "AUTH": { "TITLE": "<i class=\"icon ion-locked\"></i> AAutenticación", - "METHOD_LABEL": "Método de autenticación", "BTN_AUTH": "Autenticar", - "SCRYPT_FORM_HELP": "Por favor, autentÃquese:" + "GENERAL_HELP": "Por favor, autentÃquese:", + "EXPECTED_UID_HELP": "Por favor inicie sesión en la cuenta de <i class=\"ion-person\"></i> {{uid}}:", + "EXPECTED_PUBKEY_HELP": "Por favor, autentifÃquese en la monedero <i class=\"ion-key\"></i> {{pubkey|formatPubkey}} :", + "SCAN_FORM_HELP": "Escanee el código QR de la <b>clave privada</b> de la monedero." }, "ACCOUNT": { "TITLE": "Mi cuenta", "BALANCE": "Saldo", - "LAST_TX": "última transacción", + "LAST_TX": "última validadas transacción", "BALANCE_ACCOUNT": "Saldo de la cuenta", "NO_TX": "Ninguna transacción", "SHOW_MORE_TX": "Mostrar más", "SHOW_ALL_TX": "Mostrar todo", - "TX_FROM_DATE": "(lÃmite actual a {{fromTime|formatFromNowShort}})", + "TX_FROM_DATE": "(lÃmite actual a {{fromTime|medianFromNowShort}})", "PENDING_TX": "Transacciones en proceso de se procesadas", + "VALIDATING_TX": "Transacciones validadas", "ERROR_TX": "Transacciones no ejecutadas", "ERROR_TX_SENT": "Transacciones ejecutadas fallidas", "PENDING_TX_RECEIVED": "Tansacciones en espera de recepción", @@ -423,11 +480,10 @@ "SIG_STOCK": "Certificaciones emitidas", "BTN_RECEIVE_MONEY": "Recibir", "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Cambiar a otra identidad...", - "BTN_MEMBERSHIP_IN_DOTS": "Volverse miembro...", + "BTN_FIX_MEMBERSHIP": "Volver a enviar la adhesión...", "BTN_MEMBERSHIP_RENEW": "Renovar la adhesión", "BTN_MEMBERSHIP_RENEW_DOTS": "Renovar la adhesión...", "BTN_MEMBERSHIP_OUT_DOTS": "Cancelar la adhesión...", - "BTN_SEND_IDENTITY_DOTS": "Publicar su identidad...", "BTN_SECURITY_DOTS": "Cuenta y securidad...", "BTN_SHOW_DETAILS": "Publicar la información técnica", "LOCKED_OUTPUTS_POPOVER": { @@ -450,7 +506,7 @@ "MEMBER_ACCOUNT_HELP": "Si aún no está inscrito como un individuo (Solamente una cuenta posible por individuo).", "WALLET_ACCOUNT": "Simple monedero", "WALLET_ACCOUNT_TITLE": "Crear una cuenta simple", - "WALLET_ACCOUNT_HELP": "Cartera simple para todos los otros casos, por ejemplo si necesita una cuenta suplementaria.<br/>El Dividendo Universal no será producido para esta cuenta.", + "WALLET_ACCOUNT_HELP": "Monedero simple para todos los otros casos, por ejemplo si necesita una cuenta suplementaria.<br/>El Dividendo Universal no será producido para esta cuenta.", "SALT_WARNING": "Elija su identificador secreto.<br/>Se solicitará cada vez que se conectará con esta cuenta.<br/><br/><b>Retenga bien este identificador secreto</b>.<br/>¡En caso de pérdida, nadie podrá acceder a su cuenta!", "PASSWORD_WARNING": "Elija su frase secreta.<br/>Se solicitará cada vez que se conectará con esta cuenta.<br/><br/><b>Retenga bien esta frase secreta</b>.<br/>¡En caso de pérdida, nadie podrá acceder su cuenta!", "PSEUDO_WARNING": "Elija un seudónimo.<br/>Sirve para que los otros miembros puedan encontrarlo más fácilmente.<br/><br/>No debe contener <b>ni espacios ni caracteres acentuados</b>.<div class='hidden-xs'><br/>Ejemplo: <span class='gray'>SophieDupond, MarcelChemin, etc.</span>", @@ -480,6 +536,24 @@ "TITLE": "Selección de identidad", "HELP": "Se han enviado varias <b>identidades diferentes</b> para la clave pública <span class=\"gray\"><i class=\"ion-key\"></i>{{pubkey | formatPubkey}}</span>.<br/>Por favor, selecciona la carpeta para usar:" }, + "SELECT_WALLET_MODAL": { + "TITLE": "Selección de monedero" + }, + "WALLET_LIST": { + "TITLE": "Mis monederos", + "BTN_NEW": "Añadir un monedero", + "BTN_DOWNLOAD": "Descargue la lista", + "BTN_IMPORT_FILE_DOTS": "Importar desde un archivo...", + "NO_WALLET": "Sin monedero secundaria", + "BTN_DELETE": "Eliminar una monedero secundaria...", + "BTN_RENAME": "Renombrar el monedero", + "EXPORT_FILENAME": "monederos-{{pubkey|formatPubkey}}-{{currency}}.csv", + "EDIT_POPOVER": { + "TITLE": "Renombrar el monedero", + "HELP": "Completa el nuevo nombre", + "NAME_HELP": "Nombre de la monedero" + } + }, "SECURITY": { "ADD_QUESTION": "Añadir una pregunta personalizada", "BTN_CLEAN": "Limpiar", @@ -536,15 +610,20 @@ "COMMENT_HELP": "Comentario", "BTN_SEND": "Enviar", "BTN_ADD_COMMENT": "Añadir un comentario", + "REST": "Resto de cuenta", + "REST_TO": "a", "WARN_COMMENT_IS_PUBLIC": "Tenga en cuenta que los <b>comentarios son públicos</b> (sin encriptar).", "MODAL": { "TITLE": "Transferencia" } }, "ERROR": { + "UNKNOWN_URI_FORMAT": "Formato URI desconocido", + "PUBKEY_INVALID_CHECKSUM": "Clave pública no válida (suma de comprobación incorrecta).", "POPUP_TITLE": "Error", "UNKNOWN_ERROR": "Error desconocido", "CRYPTO_UNKNOWN_ERROR": "Su navegador parece incompatible con las funcionalidades de cryptografÃa.", + "DOWNLOAD_KEYFILE_FAILED": "Error al generar el archivo de llavero.", "EQUALS_TO_PSEUDO": "Debe ser diferente del seudónimo.", "EQUALS_TO_SALT": "Debe ser diferente del identificador secreto.", "FIELD_REQUIRED": "Campo obligatorio.", @@ -593,8 +672,10 @@ "INVALID_NODE_SUMMARY": "Nodo ilocalizable o dirección inválida.", "INVALID_USER_ID": "El seudónimo no debe contener ni espacios ni caracteres especiales o acentuado.", "INVALID_COMMENT": "El campo 'referencia’ no debe contener carácteres acentuados.", - "INVALID_PUBKEY": "La llave pública no tiene el formato esperado.", - "IDENTITY_REVOKED": "Esta identidad <b>fue revocada {{revocationTime|formatFromNow}}</b> ({{revocationTime|formatDate}}). No puede estar miembro.", + "INVALID_PUBKEY": "La clave pública no tiene el formato esperado.", + "INVALID_PUBKEY_CHECKSUM": "Suma de comprobación inválida.", + "IDENTITY_REVOKED": "Esta identidad <b>fue revocada</b>. No puede estar miembro.", + "IDENTITY_REVOKED_WITH_TIME": "Esta identidad <b>fue revocada {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). No puede estar miembro.", "IDENTITY_PENDING_REVOCATION": "La <b>revocación de esta identidad</b> fue solicitado y esta en espera de tratamiento. Por lo que, la certificación es desactivada.", "IDENTITY_INVALID_BLOCK_HASH": "Esta solicitud de adhesión no es valida (porque denomina un bloque los nodos de la red han anulado): esta persona debe renovelar su solicitud de adhesión <b>antes que</b> estar certificada.", "IDENTITY_EXPIRED": "La publicación de esta identidad ha caducada: esta persona debe realizar una nueva solicitud de adhesión <b>antes que</b> estar certificada.", @@ -631,7 +712,9 @@ "EXISTING_ACCOUNT": "Su frase secreta corresponde a una cuenta existente, la <a ng-click=\"showHelpModal('pubkey')\">clave pública</a> es:", "EXISTING_ACCOUNT_REQUEST": "Por favor, cambie su frase secreta para que coincida con una cuenta sin usar.", "GET_LICENSE_FILE_FAILED": "Error al obtener el archivo de licencia", - "CHECK_NETWORK_CONNECTION": "Ningún nodo parece alcanzable.<br/><br/><b>Compruebe la conexión a Internet</b>." + "CHECK_NETWORK_CONNECTION": "Ningún nodo parece alcanzable.<br/><br/><b>Compruebe la conexión a Internet</b>.", + "INVALID_FILE_FORMAT": "Formato de archivo inválido.", + "SAME_TX_RECIPIENT": "El destinatario debe ser diferente del emisor." }, "INFO": { "POPUP_TITLE": "Información", @@ -642,6 +725,8 @@ "MEMBERSHIP_OUT_SENT": "Anulación enviada", "NOT_NEED_MEMBERSHIP": "Ya es miembro.", "IDENTITY_WILL_MISSING_CERTIFICATIONS": "Esta identidad pronto va a necesitar certificaciones (al menos {{willNeedCertificationCount}}).", + "IDENTITY_NEED_MEMBERSHIP": "Esta identidad no envió una solicitud de membresÃa. Ella tendrá que hacerlo si desea hacerse miembro.", + "HAS_ALTERNATIVE_IDENTITIES": "Hay <b>identidades múltiples</b> adjuntas a esta clave pública. <b>Antes de cualquier certificación</b>, <a ng-click=\"doQuickFix('showSelectIdentities')\">verifique otras identidades</a> para elegir la correcta o comunÃquese con el propietario de la cuenta.", "REVOCATION_SENT": "Revocación enviada", "REVOCATION_SENT_WAITING_PROCESS": "La <b>revocación de esta identidad</b> fue solicitada y está en espera de ser procesada.", "FEATURES_NOT_IMPLEMENTED": "Esta funcionalidad todavÃa está en proceso de desarrollo.<br/><br/>¿Por qué no <b>contribuir a Cesium</b>, para obtenerla más rápido? ;)", @@ -653,12 +738,14 @@ "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Advertencia de seguridad</b>", "CERTIFY_RULES_TITLE_UID": "Certificar {{uid}}", "CERTIFY_RULES": "<b class=\"assertive\">NO CERTIFICAR</b> una cuenta si piense que :<br/><br/><ul><li>1.) no corresponde a una persona <b>fÃsica y viviente</b>.<li>2.) su propietario <b>posee una otra cuenta</b> ya certificada.<li>3.) su propietario viola (voluntariamente o no) la regla 1 o 2 (por ejemplo certificando cuentas falsas o duplicadas).</ul><br/><b>¿Está usted seguro</b> sin embargo querer certificar esta identidad?", "TRANSFER": "<b>Recapitulativo de la transferencia</b>:<br/><br/><ul><li> - De: {{from}}</li><li> - A: <b>{{to}}</b></li><li> - Importe: <b>{{amount}} {{unit}}</b></li><li> - Comentario: <i>{{comment}}</i></li></ul><br/><b>¿Está usted seguro de querer realizar esta transferencia?</b>", + "TRANSFER_ALL": "<b>Recapitulativo de la transferencia</b>:<br/><br/><ul><li> - De: {{from}}</li><li> - A: <b>{{to}}</b></li><li> - Importe: <b>{{amount}} {{unit}}</b></li><li> - Comentario: <i>{{comment}}</i></li><br/><li> - Resto: <b>{{restAmount}} {{unit}}</b> para <b>{{restTo}}</b></li></ul><br/><b>¿Está usted seguro de querer realizar esta transferencia?</b>", "MEMBERSHIP_OUT": "Esta operación es <b>irreversible</b>.<br/></br/>¿Está usted seguro querer <b>anular su cuenta miembro</b>?", "MEMBERSHIP_OUT_2": "¡Esta operación es <b>irreversible</b>!<br/><br/>¿Está usted seguro querer <b>anular su adhesión</b> como miembro?", "LOGIN_UNUSED_WALLET_TITLE": "¿Error de introducción de datos?", "LOGIN_UNUSED_WALLET": "Está usted conectado a une cuenta que parece <b>inactiva</b>.<br/><br/>Si esta cuenta no corresponde a la suya, se trata probablemente de un <b>error al introducir los datos</b> de sus identificadores de conexión.<br/></br/><b>¿Quiere usted sin embargo continuar con esta cuenta?</b>", "FIX_IDENTITY": "El seudónimo <b>{{uid}}</b> va a ser publicado de nuevo, en reemplazo del antiguo que caducó.<br/></br/><b>¿Está usted seguro</b> de querer continuar?", "FIX_MEMBERSHIP": "Su solicitud de adhesión como miembro va a ser enviada de nuevo.<br/></br/><b>¿Está usted seguro</b>de querer continuar?", + "MEMBERSHIP": "Se enviará su solicitud de membresÃa como miembro.<br/></br/><b>¿Está usted seguro</b>de querer continuar?", "RENEW_MEMBERSHIP": "Su adhesión como miembro va a estar renovada.<br/></br/><b>¿Está usted seguro</b>de querer continuar?", "REVOKE_IDENTITY": "Va a <b>revocar definitivamente esta identidad</b>.<br/><br/>La llave pública y el seudónimo asociados <b>jamás podrán ser utilizados</b> (para una cuenta miembro). <br/></br/><b>¿Está usted seguro</b> de querer revocar definitivamente esta cuenta?", "REVOKE_IDENTITY_2": "¡Esta operación es <b>irreversible</b>!<br/><br/>¿Está usted seguro de querer <b>revocar definitivamente</b> esta cuenta?", diff --git a/assets/www/i18n/locale-fr-FR.json b/assets/www/i18n/locale-fr-FR.json index 4e5aa18963bb275cc145375726306566a295dce6..1ba9781ba5796ddd1e8aa0cbc1a01da7b08a2002 100644 --- a/assets/www/i18n/locale-fr-FR.json +++ b/assets/www/i18n/locale-fr-FR.json @@ -17,9 +17,10 @@ "BTN_YES_CONTINUE": "Oui, Continuer", "BTN_SHOW": "Voir", "BTN_SHOW_PUBKEY": "Afficher la clé publique", - "BTN_RELATIVE_UNIT": "Afficher en unité relative ?", + "BTN_RELATIVE_UNIT": "Afficher les montants en DU ?", "BTN_BACK": "Retour", "BTN_NEXT": "Suivant", + "BTN_IMPORT": "Importer", "BTN_CANCEL": "Annuler", "BTN_CLOSE": "Fermer", "BTN_LATER": "Plus tard", @@ -45,9 +46,10 @@ "BTN_MODIFY": "Modifier", "CHOOSE_FILE": "Déposez votre fichier <br/>ou cliquez pour le sélectionner", "DAYS": "jours", - "NO_ACCOUNT_QUESTION": "Pas de encore membre ? Créer un compte !", + "NO_ACCOUNT_QUESTION": "Pas encore de compte ? Créez-en un gratuitement !", "SEARCH_NO_RESULT": "Aucun résultat trouvé", "LOADING": "Veuillez patienter...", + "LOADING_WAIT": "Veuillez patienter...<br/><small>(Attente de disponibilité du noeud)</small>", "SEARCHING": "Recherche en cours...", "FROM": "De", "TO": "À", @@ -65,7 +67,7 @@ "DISABLE": "Désactivé", "RESULTS_LIST": "Résultats", "RESULTS_COUNT": "{{count}} résultats", - "EXECUTION_TIME": "executé en {{duration|formatDurationMs}}", + "EXECUTION_TIME": "exécuté en {{duration|formatDurationMs}}", "SHOW_VALUES": "Afficher les valeurs en clair ?", "POPOVER_ACTIONS_TITLE": "Options", "POPOVER_FILTER_TITLE": "Filtres", @@ -77,6 +79,12 @@ "SHARE_ON_FACEBOOK": "Partager sur Facebook", "SHARE_ON_DIASPORA": "Partager sur Diaspora*", "SHARE_ON_GOOGLEPLUS": "Partager sur Google+" + }, + "FILE": { + "DATE": "Date :", + "TYPE": "Type :", + "SIZE": "Taille :", + "VALIDATING": "Validation en cours..." } }, "SYSTEM": { @@ -89,6 +97,7 @@ "WOT": "Annuaire", "CURRENCY": "Monnaie", "ACCOUNT": "Mon compte", + "WALLETS": "Mes portefeuilles", "TRANSFER": "Virement", "SCAN": "Scanner", "SETTINGS": "Paramètres", @@ -97,41 +106,52 @@ }, "ABOUT": { "TITLE": "À propos", - "LICENSE": "Application <b>libre</b> (licence GNU GPLv3).", + "LICENSE": "Application <b>libre</b> (Licence GNU AGPLv3).", "LATEST_RELEASE": "Il existe une <b>version plus récente</b> de {{'COMMON.APP_NAME'|translate}} (<b>v{{version}}</b>)", "PLEASE_UPDATE": "Veuillez mettre à jour {{'COMMON.APP_NAME'|translate}} (dernière version : <b>v{{version}}</b>)", "CODE": "Code source :", + "OFFICIAL_WEB_SITE": "Site web officiel :", "DEVELOPERS": "Développé par :", "FORUM": "Forum :", "PLEASE_REPORT_ISSUE": "N'hésitez pas à nous remonter les anomalies rencontrées", - "REPORT_ISSUE": "Remonter un problème" + "REPORT_ISSUE": "Remonter un problème", + "BTN_OPEN_DEV_WINDOW": "Ouvrir la fenêtre de debuggage" }, "HOME": { "TITLE": "Cesium", "WELCOME": "Bienvenue dans l'application Cesium !", - "MESSAGE": "Suivez vos comptes {{currency|abbreviate}} en toute simplicité", + "MESSAGE": "Recevez et envoyez de la monnaie libre {{currency|abbreviate}}", "BTN_CURRENCY": "Explorer la monnaie {{name|abbreviate}}", "BTN_ABOUT": "à propos", "BTN_HELP": "Aide en ligne", "REPORT_ISSUE": "anomalie", "NOT_YOUR_ACCOUNT_QUESTION" : "Vous n'êtes pas propriétaire du compte <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> ?", "BTN_CHANGE_ACCOUNT": "Déconnecter ce compte", - "CONNECTION_ERROR": "NÅ“ud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifiez votre connection Internet, ou changer de nÅ“ud <a class=\"positive\" ng-click=\"doQuickFix('settings')\">dans les paramètres</a>." + "CONNECTION_ERROR": "NÅ“ud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifiez votre connexion Internet, ou changer de nÅ“ud <a class=\"positive\" ng-click=\"doQuickFix('settings')\">dans les paramètres</a>." }, "SETTINGS": { "TITLE": "Paramètres", + "DISPLAY_DIVIDER": "Affichage", + "STORAGE_DIVIDER": "Stockage", "NETWORK_SETTINGS": "Réseau", "PEER": "Adresse du nÅ“ud Duniter", + "PEER_SHORT": "Adresse du nÅ“ud", "PEER_CHANGED_TEMPORARY": "Adresse utilisée temporairement", "USE_LOCAL_STORAGE": "Activer le stockage local", "USE_LOCAL_STORAGE_HELP": "Permet de sauvegarder vos paramètres", + "WALLETS_SETTINGS": "Mes portefeuilles", + "USE_WALLETS_ENCRYPTION": "Sécuriser la liste ?", + "USE_WALLETS_ENCRYPTION_HELP": "Permet de sécuriser la liste de vos portefeuilles (par chiffrement), en exigeant une authentification pour y accéder.", "ENABLE_HELPTIP": "Activer les bulles d'aide contextuelles", "ENABLE_UI_EFFECTS": "Activer les effets visuels", - "HISTORY_SETTINGS": "Liste des opérations", + "HISTORY_SETTINGS": "Mes opérations", "DISPLAY_UD_HISTORY": "Afficher les dividendes produits ?", + "TX_HISTORY_AUTO_REFRESH": "Rafraîchir automatiquement", + "TX_HISTORY_AUTO_REFRESH_HELP": "Rafraîchit le solde et les opérations automatiquement, à chaque nouveau bloc du réseau.", "AUTHENTICATION_SETTINGS": "Authentification", - "KEEP_AUTH": "Expiration de l'authentification", - "KEEP_AUTH_HELP": "Défini le moment où l'authentification est nettoyée de la mémoire", + "KEEP_AUTH": "Désauthentification automatique", + "KEEP_AUTH_SHORT": "Désauthentification", + "KEEP_AUTH_HELP": "Définit le moment où l'authentification est nettoyée de la mémoire.", "KEEP_AUTH_OPTION": { "NEVER": "Après chaque opération", "SECONDS": "Après {{value}}s d'inactivité", @@ -140,19 +160,28 @@ "HOUR": "Après {{value}}h d'inactivité", "ALWAYS": "A la fin de la session" }, + "KEYRING_FILE": "Fichier de trousseau", + "KEYRING_FILE_HELP": "Permet de vous <b>connecter</b> automatiquement à chaque lancement<br/>et même de vous <b>authentifier</b> (seulement si \"Expiration de l'authentification\" est configurée \"à la fin de la session\").", "REMEMBER_ME": "Se souvenir de moi ?", "REMEMBER_ME_HELP": "Permet de rester identifié d'une session à l'autre, en conservant localement la clé publique.", "PLUGINS_SETTINGS": "Extensions", "BTN_RESET": "Restaurer les valeurs par défaut", "EXPERT_MODE": "Activer le mode expert", - "EXPERT_MODE_HELP": "Permet un affichage plus détaillé", + "EXPERT_MODE_HELP": "Permet un affichage plus détaillé.", + "BLOCK_VALIDITY_WINDOW": "Délai d'incertitude des blocs", + "BLOCK_VALIDITY_WINDOW_SHORT": "Délai d'incertitude", + "BLOCK_VALIDITY_WINDOW_HELP": "Délai avant de considérer qu'une information est validée", + "BLOCK_VALIDITY_OPTION": { + "NONE": "Aucun délai", + "N": "{{time | formatDuration}} ({{count}} blocs)" + }, "POPUP_PEER": { - "TITLE" : "NÅ“ud Duniter", - "HOST" : "Adresse", + "TITLE": "NÅ“ud Duniter", + "HOST": "Adresse", "HOST_HELP": "Adresse : serveur:port", - "USE_SSL" : "Sécurisé ?", - "USE_SSL_HELP" : "(Chiffrement SSL)", - "BTN_SHOW_LIST" : "Liste des noeuds" + "USE_SSL": "Sécurisé ?", + "USE_SSL_HELP": "(Chiffrement SSL)", + "BTN_SHOW_LIST": "Liste des noeuds" } }, "BLOCKCHAIN": { @@ -174,12 +203,12 @@ "IDENTITIES_COUNT": "Nouvelles identités", "JOINERS_COUNT": "Nouveaux membres", "ACTIVES_COUNT": "Renouvellements", - "ACTIVES_COUNT_HELP": "Membres ayant renouvellés leur adhésion", + "ACTIVES_COUNT_HELP": "Membres ayant renouvelé leur adhésion", "LEAVERS_COUNT": "Membres sortants", "LEAVERS_COUNT_HELP": "Membres ne souhaitant plus de certification", "EXCLUDED_COUNT": "Membres exclus", "EXCLUDED_COUNT_HELP": "Anciens membres exclus par non renouvellement ou manque de certifications", - "REVOKED_COUNT": "Identités revoquées", + "REVOKED_COUNT": "Identités révoquées", "REVOKED_COUNT_HELP": "Ces comptes ne pourront plus être membres", "TX_COUNT": "Transactions", "CERT_COUNT": "Certifications", @@ -239,7 +268,7 @@ "STEP_MAX": "Distance maximale, par les certifications, entre un nouvel entrant et les membres référents", "WOT_RULES_DIVIDER": "Règles de la toile de confiance", "SENTRIES": "Nombre de certifications (émises <b>et</b> reçues) pour devenir membre référent", - "SENTRIES_FORMULA": "Nombre de certification (émises <b>et</b> reçues) pour devenir membre référent (formule)", + "SENTRIES_FORMULA": "Nombre de certifications (émises <b>et</b> reçues) pour devenir membre référent (formule)", "XPERCENT":"Pourcentage minimum de membres référents à atteindre pour respecter la règle de distance", "AVG_GEN_TIME": "Temps moyen entre deux blocs", "CURRENT": "actuel", @@ -280,15 +309,18 @@ "PEERS": "NÅ“uds", "SIGNED_ON_BLOCK": "Signé sur le bloc", "MIRROR": "miroir", - "MIRRORS": "NÅ“uds miroirs", + "MIRRORS": "Miroirs", + "MIRROR_PEERS": "NÅ“uds miroirs", "PEER_LIST" : "Liste des nÅ“uds", - "MEMBERS" : "NÅ“uds membres", + "MEMBERS" : "Membres", + "MEMBER_PEERS" : "NÅ“uds membres", "ALL_PEERS" : "Tous les nÅ“uds", "DIFFICULTY" : "Difficulté", "API" : "API", "CURRENT_BLOCK" : "Bloc #", "POPOVER_FILTER_TITLE": "Filtre", - "OFFLINE": "NÅ“uds hors ligne", + "OFFLINE": "Hors ligne", + "OFFLINE_PEERS": "NÅ“uds hors ligne", "BTN_SHOW_PEER": "Voir le nÅ“ud", "VIEW": { "TITLE": "NÅ“ud", @@ -306,13 +338,13 @@ }, "WOT": { "SEARCH_HELP": "Recherche (pseudo ou clé publique)", - "SEARCH_INIT_PHASE_WARNING": "Durant la phase de pré-inscription, la recherche des inscriptions en attente <b>peut-être longue</b>. Merci de patienter...", + "SEARCH_INIT_PHASE_WARNING": "Durant la phase de pré-inscription, la recherche des inscriptions en attente <b>peut être longue</b>. Merci de patienter...", "REGISTERED_SINCE": "Inscrit le", - "REGISTERED_SINCE_BLOCK": "Inscrit au block #", + "REGISTERED_SINCE_BLOCK": "Inscrit au bloc #", "NO_CERTIFICATION": "Aucune certification validée", "NO_GIVEN_CERTIFICATION": "Aucune certification émise", "NOT_MEMBER_PARENTHESIS": "(non membre)", - "IDENTITY_REVOKED_PARENTHESIS": "(identité revoquée)", + "IDENTITY_REVOKED_PARENTHESIS": "(identité révoquée)", "MEMBER_PENDING_REVOCATION_PARENTHESIS": "(en cours de révocation)", "EXPIRE_IN": "Expiration", "NOT_WRITTEN_EXPIRE_IN": "Date limite<br/>de traitement", @@ -338,7 +370,7 @@ "PENDING": "Inscriptions en attente", "PENDING_COUNT": "{{count}} inscriptions en attente", "REGISTERED": "Inscrit {{sigDate | formatFromNow}}", - "MEMBER_FROM": "Membre depuis {{memberDate|formatFromNowShort}}", + "MEMBER_FROM": "Membre depuis {{memberDate|medianFromNowShort}}", "BTN_NEWCOMERS": "Nouveaux membres", "BTN_PENDING": "Inscriptions en attente", "SHOW_MORE": "Afficher plus", @@ -380,14 +412,17 @@ "SCRYPT_FORM_HELP": "Veuillez saisir vos identifiants.<br>Pensez à vérifier que la clé publique est celle de votre compte.", "PUBKEY_FORM_HELP": "Veuillez saisir une clé publique de compte :", "FILE_FORM_HELP": "Choisissez le fichier de trousseau à utiliser :", + "SCAN_FORM_HELP": "Scanner le QR code d'un portefeuille.", "SALT": "Identifiant secret", "SALT_HELP": "Identifiant secret", "SHOW_SALT": "Afficher l'identifiant secret ?", "PASSWORD": "Mot de passe", "PASSWORD_HELP": "Mot de passe", - "PUBKEY_HELP": "Exemple : « AbsxSY4qoZRzyV2irfep1V9xw1EMNyKJw2TkuVD4N1mv »", + "PUBKEY_HELP": "Clé publique ou pseudonyme", "NO_ACCOUNT_QUESTION": "Vous n'avez pas encore de compte ?", + "HAVE_ACCOUNT_QUESTION": "Vous avez déjà un compte ?", "CREATE_ACCOUNT": "Créer un compte...", + "CREATE_FREE_ACCOUNT": "Créer un compte gratuitement", "FORGOTTEN_ID": "Mot de passe oublié ?", "ASSOCIATED_PUBKEY": "Clé publique du trousseau :", "BTN_METHODS": "Autres méthodes", @@ -402,61 +437,65 @@ "IDLE_WARNING": "Vous allez être déconnecté... {{countdown}}" }, "METHOD": { - "SCRYPT_DEFAULT": "Sallage standard (par défaut)", - "SCRYPT_ADVANCED": "Sallage avancé", + "SCRYPT_DEFAULT": "Identifiant secret et mot de passe", + "SCRYPT_ADVANCED": "Salage avancé", "FILE": "Fichier de trousseau", - "PUBKEY": "Clé publique seule" + "PUBKEY": "Clé publique ou pseudonyme", + "SCAN": "Scanner un QR code" }, "SCRYPT": { - "SIMPLE": "Sallage léger", - "DEFAULT": "Sallage standard", - "SECURE": "Sallage sûr", - "HARDEST": "Sallage le plus sûr", - "EXTREME": "Sallage extrème", - "USER": "Sallage personnalisé", + "SIMPLE": "Salage léger", + "DEFAULT": "Salage standard", + "SECURE": "Salage sûr", + "HARDEST": "Salage le plus sûr", + "EXTREME": "Salage extrême", + "USER": "Salage personnalisé", "N": "N (Loop):", "r": "r (RAM):", "p": "p (CPU):" }, "FILE": { - "DATE" : "Date :", - "TYPE" : "Type :", - "SIZE": "Taille :", - "VALIDATING": "Validation en cours...", - "HELP": "Format de fichier attendu : <b>.dunikey</b> (type PubSec). D'autres formats sont en cours de développement (EWIF, WIF)." + "HELP": "Format de fichier attendu : <b>.yml</b> ou <b>.dunikey</b> (type PubSec, WIF ou EWIF)." } }, "AUTH": { "TITLE": "<i class=\"icon ion-locked\"></i> Authentification", - "METHOD_LABEL": "Méthode d'authentification", "BTN_AUTH": "S'authentifier", - "SCRYPT_FORM_HELP": "Veuillez vous authentifier :" + "GENERAL_HELP": "Veuillez vous authentifier :", + "EXPECTED_UID_HELP": "Veuillez vous authentifier sur le compte <i class=\"ion-person\"></i> {{uid}} :", + "EXPECTED_PUBKEY_HELP": "Veuillez vous authentifier sur le portefeuille <br class=\"visible-xs\"/><i class=\"ion-key\"></i> {{pubkey|formatPubkey}} :", + "SCAN_FORM_HELP": "Scanner le QR code de la <b>clef privée</b> du portefeuille." }, "ACCOUNT": { "TITLE": "Mon compte", "BALANCE": "Solde", - "LAST_TX": "Dernières transactions", + "LAST_TX": "Dernières transactions validées", "BALANCE_ACCOUNT": "Solde du compte", "NO_TX": "Aucune transaction", "SHOW_MORE_TX": "Afficher plus", "SHOW_ALL_TX": "Afficher tout", - "TX_FROM_DATE": "(limite actuelle à {{fromTime|formatFromNowShort}})", - "PENDING_TX": "Transactions en cours de traitement", + "TX_FROM_DATE": "(limite actuelle à {{fromTime|medianFromNowShort}})", + "PENDING_TX": "Transactions en attente de traitement", + "VALIDATING_TX": "Transactions traitées, non validées", "ERROR_TX": "Transactions non executées", "ERROR_TX_SENT": "Transactions envoyées en échec", "PENDING_TX_RECEIVED": "Transactions en attente de réception", "EVENTS": "Evénements", + "OUT_DISTANCED": "Vos certifications actuelles proviennent d'un groupe trop isolé de la <a ng-click=\"showHelpModal('wot')\">Toile de Confiance</a> (TdC) : la <a ng-click=\"showHelpModal('distance_rule')\">règle de distance maximale</a> n'est pas respectée.<br/>Vous devez obtenir des certifications provenant d'autres secteurs de la TdC, ou bien attendre que celle-ci se resserre.", "WAITING_MEMBERSHIP": "Demande d'adhésion envoyée. En attente d'acceptation.", - "WAITING_CERTIFICATIONS": "Vous devez obtenir {{needCertificationCount}} certification(s) pour devenir membre.", - "WILL_MISSING_CERTIFICATIONS": "Vous allez bientôt <b>manquer de certification</b> (au moins {{willNeedCertificationCount}} sont requises)", + "WAITING_CERTIFICATIONS": "Vous devez <b>obtenir {{needCertificationCount}} certification(s)</b> pour devenir membre et produire le <a ng-click=\"showHelpModal('ud')\">Dividende Universel</a>. Votre compte est cependant déjà opérationnel, pour recevoir et effectuer des paiements.", + "WAITING_CERTIFICATIONS_HELP": "Pour obtenir vos certifications, sollicitez uniquement des membres <b>qui vous connaissent suffisamment</b>, comme l'exige <a ng-click=\"showLicenseModal()\">la licence de la monnaie</a> que vous avez acceptée.<br/>Si vous ne connaissez pas suffisamment de membres, faites-le savoir sur <a ng-click=\"openLink($event, $root.settings.userForumUrl)\">le forum utilisateur</a>.", + "WILL_MISSING_CERTIFICATIONS": "Vous allez bientôt <b>manquer de certifications</b> (au moins {{willNeedCertificationCount}} sont requises)", "WILL_NEED_RENEW_MEMBERSHIP": "Votre adhésion comme membre <b>va expirer {{membershipExpiresIn|formatDurationTo}}</b>. Pensez à <a ng-click=\"doQuickFix('renew')\">renouveler votre adhésion</a> d'ici là .", - "NEED_RENEW_MEMBERSHIP": "Vous n'êtes plus membre, car votre adhésion <b>a expiré</b>. Pensez à <a ng-click=\"doQuickFix('renew')\">renouveler votre adhésion</a>.", + "NEED_RENEW_MEMBERSHIP": "Vous n'êtes plus membre de la monnaie, car <b>votre adhésion a expiré</b>. Pensez à <a ng-click=\"doQuickFix('renew')\">renouveler votre adhésion</a>.", + "NEED_RENEW_MEMBERSHIP_AFTER_CANCELLED": "Vous n'êtes plus membre de la monnaie, <b>pour manque de certifications</b>. Pensez à <a ng-click=\"doQuickFix('renew')\">renouveler votre adhésion</a>.", "NO_WAITING_MEMBERSHIP": "Aucune demande d'adhésion en attente. Si vous souhaitez <b>devenir membre</b>, pensez à <a ng-click=\"doQuickFix('membership')\">envoyer la demande d'adhésion</a>.", "CERTIFICATION_COUNT": "Certifications reçues", "CERTIFICATION_COUNT_SHORT": "Certifications", "SIG_STOCK": "Certifications envoyées", "BTN_RECEIVE_MONEY": "Encaisser", "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Basculer vers une autre identité...", + "BTN_FIX_MEMBERSHIP": "Renvoyer la demande d'adhésion...", "BTN_MEMBERSHIP_RENEW": "Renouveler l'adhésion", "BTN_MEMBERSHIP_RENEW_DOTS": "Renouveler l'adhésion...", "BTN_MEMBERSHIP_OUT_DOTS": "Arrêter l'adhésion...", @@ -471,7 +510,7 @@ "NEW": { "TITLE": "Création de compte", "INTRO_WARNING_TIME": "La création d'un compte sur {{name|capitalize}} est très simple. Veuillez néanmoins prendre suffisament de temps pour faire correctement cette formalité (pour ne pas oublier les identifiants, mots de passe, etc.).", - "INTRO_WARNING_SECURITY": "Vérifier que le matériel que vous utilisez actuellement (ordinateur, tablette, téléphone) <b>est sécurisé et digne de confiance</b>.", + "INTRO_WARNING_SECURITY": "Vérifiez que le matériel que vous utilisez actuellement (ordinateur, tablette, téléphone) <b>est sécurisé et digne de confiance</b>.", "INTRO_WARNING_SECURITY_HELP": "Anti-virus à jour, pare-feu activé, session protégée par mot de passe ou code pin, etc.", "INTRO_HELP": "Cliquez sur <b>{{'COMMON.BTN_START'|translate}}</b> pour débuter la création de compte. Vous serez guidé étape par étape.", "REGISTRATION_NODE": "Votre inscription sera enregistrée via le noeud Duniter <b>{{server}}</b>, qui le diffusera ensuite au reste du réseau de la monnaie.", @@ -494,9 +533,9 @@ "PASSWORD_CONFIRM_HELP": "Confirmation du mot de passe", "SLIDE_6_TITLE": "Confirmation :", "COMPUTING_PUBKEY": "Calcul en cours...", - "LAST_SLIDE_CONGRATULATION": "Vous avez saisi toutes les informations nécessaires : Bravo !<br/>Vous pouvez maintenant <b>envoyer la demande de création</b> de compte.</b><br/><br/>Pour information, la clé publique ci-dessous identifiera votre futur compte.<br/>Elle pourra être communiquée à des tiers pour recevoir leur paiement.<br/><b>Il n'est pas obligatoire</b> de la noter ici, vous pourrez également le faire plus tard.", - "CONFIRMATION_MEMBER_ACCOUNT": "<b class=\"assertive\">Avertissement :</b> l'identifiant secret, le mot de passe et le pseudonyme ne pourront plus être modifiés.<br/><br/><b>Assurez-vous de toujours vous en rappeller !</b><br/><br/><b>Etes-vous sûr</b> de vouloir envoyer cette demande d'inscription ?", - "CONFIRMATION_WALLET_ACCOUNT": "<b class=\"assertive\">Avertissement :</b> l'identifiant secret et le mot de passe ne pourront plus être modifiés.<br/><br/><b>Assurez-vous de toujours vous en rappeller !</b><br/><br/><b>Etes-vous sûr</b> de vouloir continuer avec ces identifiants ?", + "LAST_SLIDE_CONGRATULATION": "Vous avez saisi toutes les informations nécessaires : Bravo !<br/>Vous pouvez maintenant <b>envoyer la demande de création</b> de compte.</b><br/><br/>Pour information, la clé publique ci-dessous identifiera votre futur compte.<br/>Elle pourra être communiquée à des tiers pour recevoir leurs paiements.<br/><b>Il n'est pas obligatoire</b> de la noter ici, vous pourrez également le faire plus tard.", + "CONFIRMATION_MEMBER_ACCOUNT": "<b class=\"assertive\">Avertissement :</b> l'identifiant secret, le mot de passe et le pseudonyme ne pourront plus être modifiés.<br/><br/><b>Assurez-vous de toujours vous en rappeler !</b><br/><br/><b>Êtes-vous sûr</b> de vouloir envoyer cette demande d'inscription ?", + "CONFIRMATION_WALLET_ACCOUNT": "<b class=\"assertive\">Avertissement :</b> l'identifiant secret et le mot de passe ne pourront plus être modifiés.<br/><br/><b>Assurez-vous de toujours vous en rappeler !</b><br/><br/><b>Êtes-vous sûr</b> de vouloir continuer avec ces identifiants ?", "CHECKING_PSEUDO": "Vérification...", "PSEUDO_AVAILABLE": "Pseudonyme disponible", "PSEUDO_NOT_AVAILABLE": "Pseudonyme non disponible", @@ -512,17 +551,42 @@ "TITLE": "Sélection de l'identité", "HELP": "Plusieurs <b>identités différentes</b> ont été envoyées, pour la clé publique <span class=\"gray\"><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</span>.<br/>Veuillez sélectionner le dossier à utiliser :" }, + "SELECT_WALLET_MODAL": { + "TITLE": "Sélection du portefeuille" + }, + "WALLET_LIST": { + "TITLE": "Mes portefeuilles", + "BTN_NEW": "Ajouter un portefeuille", + "BTN_DOWNLOAD": "Télécharger la liste", + "BTN_IMPORT_FILE_DOTS": "Importer depuis un fichier...", + "NO_WALLET": "Aucun portefeuille secondaire", + "BTN_DELETE": "Retirer un portefeuille secondaire...", + "BTN_RENAME": "Renommer le portefeuille", + "EXPORT_FILENAME": "mes_portefeuilles-{{pubkey|formatPubkey}}-{{currency}}.csv", + "TOTAL_DOTS": "Total : ", + "EDIT_POPOVER": { + "TITLE": "Renommer le portefeuille", + "HELP": "Renseignez le nouveau nom", + "NAME_HELP": "Nom du portefeuille" + }, + "IMPORT_MODAL": { + "TITLE": "Importer des portefeuilles", + "HELP": "Pour <b>importer des porftefeuilles</b>, veuillez glisser dans la zone ci-dessous le fichier de la liste des portefeuilles, ou bien cliquer dans la zone pour rechercher un fichier.", + "WALLET_COUNT": "<b>{{count}}</b> nouveau{{count > 1 ? 'x' : ''}} portefeuille{{count > 1 ? 's' : ''}}", + "NO_NEW_WALLET": "Aucun nouveau portefeuille" + } + }, "SECURITY": { - "ADD_QUESTION": "Ajouter une question personnalisée ", + "ADD_QUESTION": "Ajouter une question personnalisée", "BTN_CLEAN": "Vider", "BTN_RESET": "Réinitialiser", "DOWNLOAD_REVOKE": "Sauvegarder mon fichier de révocation", "DOWNLOAD_REVOKE_HELP": "Disposer d'un fichier de révocation est important, par exemple en cas de perte de vos identifiants. Il vous permet de <b>sortir ce compte de la toile de confiance</b>, en redevenant ainsi un simple portefeuille.", "GENERATE_KEYFILE": "Générer mon fichier de trousseau...", - "GENERATE_KEYFILE_HELP": "Génère un fichier permettant de vous authentifier sans saisir vos identifiants.<br/><b>Attention :</b> ce fichier contiendra votre clef secrète : il est donc très important de le mettre en lieu sûr !", + "GENERATE_KEYFILE_HELP": "Génère un fichier permettant de vous authentifier sans saisir vos identifiants.<br/><b>Attention :</b> ce fichier contiendra votre trousseau de compte (clefs publique et secrète) ; il est donc très important de le mettre en lieu sûr !", "KEYFILE_FILENAME": "trousseau-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Transformer en compte membre...", - "MEMBERSHIP_IN_HELP": "Permet de <b>transformer</b> un compte simple portefeuille <b>en compte membre</b>, en envoyant une demande d'adhésion. Utile uniquement si vous n'avez pas déjà une autre compte membre.", + "MEMBERSHIP_IN_HELP": "Permet de <b>transformer</b> un compte simple portefeuille <b>en compte membre</b>, en envoyant une demande d'adhésion. Utile uniquement si vous n'avez pas déjà un autre compte membre.", "SEND_IDENTITY": "Publier son identité...", "SEND_IDENTITY_HELP": "Permet d'associer un pseudonyme à ce compte, mais <b>sans faire de demande d'adhésion</b> pour devenir membre. Cette association n'est généralement pas utile, car la validité de cette association de pseudonyme est limitée dans le temps.", "HELP_LEVEL": "Pour générer un fichier de sauvegarde de vos identifiants, choisissez <strong> au moins {{nb}} questions :</strong>", @@ -554,7 +618,7 @@ "REVOCATION_WITH_FILE_DESCRIPTION": "Si vous avez <b>définitivement perdus vos identifiants</b> de compte membre (ou que la sécurité du compte est compromise), vous pouvez utiliser <b>le fichier de révocation</b> du compte pour <b>forcer sa sortie définitive de la toile de confiance</b>.", "REVOCATION_WITH_FILE_HELP": "Pour <b>révoquer définitivement</b> un compte membre, veuillez glisser dans la zone ci-dessous votre fichier de révocation, ou bien cliquer dans la zone pour rechercher un fichier.", "REVOCATION_WALLET": "Révoquer immédiatement ce compte", - "REVOCATION_WALLET_HELP": "Demander la révocation de votre identité entraine la <b>sortie de la toile de confiance</b> (définitive pour le pseudonyme et la clé publique associés). Le compte ne pourra plus produire de Dividende Universel.<br/>Vous pourrez toutefois encore vous y connecter, comme à un simple portefeuille.", + "REVOCATION_WALLET_HELP": "Demander la révocation de votre identité entraîne la <b>sortie de la toile de confiance</b> (définitive pour le pseudonyme et la clé publique associés). Le compte ne pourra plus produire de Dividende Universel.<br/>Vous pourrez toutefois encore vous y connecter, comme à un simple portefeuille.", "REVOCATION_FILENAME": "revocation-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", "SAVE_ID": "Sauvegarder mes identifiants...", "SAVE_ID_HELP": "Création d'un fichier de sauvegarde, pour <b>retrouver votre mot de passe</b> (et l'identifiant secret) <b>en cas de d'oubli</b>. Le fichier est <b>sécurisé</b> (chiffré) à l'aide de questions personnelles.", @@ -562,15 +626,19 @@ "TITLE": "Compte et sécurité", "KEYFILE": { "PUBSEC_FORMAT": "Format PubSec.", - "PUBSEC_FORMAT_HELP": "Ce format de fichier est compatible notamment avec Cesium et gannonce.", - "WIF_FORMAT": "Format WIF", - "WIF_FORMAT_HELP": "Ce format permet notamment la génération de portefeuilles papier (Paper Wallet).", - "EWIF_FORMAT": "Format EWIF", - "EWIF_FORMAT_HELP": "Ce format protège le trousseau par un mot de passe. Il permet notamment la génération de portefeuilles papier (Paper Wallet).", + "PUBSEC_FORMAT_HELP": "Ce format stocke votre trousseau de manière très simple. Il est compatible notamment avec Cesium, ÄŸannonce et Duniter.<br/><b>Attention :</b>Le fichier <b>n'est pas chiffré</b> (la clef secrète y apparaît en clair) ; veuillez donc le stocker en lieu sûr !", + "WIF_FORMAT": "Format WIF (Wallet Import Format) - v1", + "WIF_FORMAT_HELP": "Ce format stocke votre trousseau en y intégrant une somme de contrôle pour vérifier l'intégrité du fichier. Il est compatible notamment avec les portefeuilles papier (Duniter paper wallet).<br/><b>Attention :</b>Le fichier <b>n'est pas chiffré</b> (la clef secrète y apparaît en clair) ; veuillez donc le stocker en lieu sûr !", + "EWIF_FORMAT": "Format EWIF (Encrypted Wallet Import Format) - v1", + "EWIF_FORMAT_HELP": "Ce format stocke votre trousseau <b>de manière chiffrée</b> à partir d'une phrase secrète de votre choix. Il intègre aussi une somme de contrôle pour vérifier l'intégrité du fichier.<br/><b>Attention :</b> Veillez à toujours vous souvenir de votre phrase secrète !", "PASSWORD_POPUP": { "TITLE": "Fichier de trousseau chiffré", - "HELP": "Veuillez indiquer le mot de passe:", - "PASSWORD_HELP": "Mot de passe" + "HELP": "Veuillez indiquer la phrase secrète :", + "PASSWORD_HELP": "Phrase secrète" + }, + "ERROR": { + "BAD_PASSWORD": "Phrase secrète incorrecte", + "BAD_CHECKSUM": "Somme de contrôle incorrecte" } } }, @@ -584,6 +652,7 @@ "TRANSFER": { "TITLE": "Virement", "SUB_TITLE": "Faire un virement", + "SUB_TITLE_ALL": "Vider le compte", "FROM": "De", "TO": "À", "AMOUNT": "Montant", @@ -592,22 +661,24 @@ "COMMENT_HELP": "Commentaire", "BTN_SEND": "Envoyer", "BTN_ADD_COMMENT": "Ajouter un commentaire", - "WARN_COMMENT_IS_PUBLIC": "Veuillez noter que <b>les commentaires sont publiques</b> (non chiffré).", + "REST": "Reste du compte", + "REST_TO": "à ", + "WARN_COMMENT_IS_PUBLIC": "Veuillez noter que <b>les commentaires sont publics</b> (non chiffrés).", "MODAL": { "TITLE": "Virement" } }, "ERROR": { - "UNKNOWN_URI_FORMAT": "Format inconnu (unknown URI)", + "UNKNOWN_URI_FORMAT": "Format d'URI inconnu", "PUBKEY_INVALID_CHECKSUM": "Clé publique invalide (bad checksum).", "POPUP_TITLE": "Erreur", "UNKNOWN_ERROR": "Erreur inconnue", "CRYPTO_UNKNOWN_ERROR": "Votre navigateur ne semble pas compatible avec les fonctionnalités de cryptographie.", - "DOWNLOAD_KEYFILE_FAILED": "Echec de le génération du fichier de trousseau.", + "DOWNLOAD_KEYFILE_FAILED": "Échec de la génération du fichier de trousseau.", "EQUALS_TO_PSEUDO": "Doit être différent du pseudonyme", "EQUALS_TO_SALT": "Doit être différent de l'identifiant secret", - "FIELD_REQUIRED": "Champ obligatoire.", - "FIELD_TOO_SHORT": "Valeur trop courte.", + "FIELD_REQUIRED": "Champ obligatoire", + "FIELD_TOO_SHORT": "Valeur trop courte", "FIELD_TOO_SHORT_WITH_LENGTH": "Valeur trop courte ({{minLength}} caractères min)", "FIELD_TOO_LONG": "Valeur trop longue", "FIELD_TOO_LONG_WITH_LENGTH": "Valeur trop longue ({{maxLength}} caractères max)", @@ -617,81 +688,94 @@ "FIELD_NOT_NUMBER": "Valeur numérique attendue", "FIELD_NOT_INT": "Valeur entière attendue", "FIELD_NOT_EMAIL": "Adresse email non valide", - "PASSWORD_NOT_CONFIRMED": "Ne correspond pas au mot de passe.", - "SALT_NOT_CONFIRMED": "Ne correspond pas à l'identifiant secret.", - "SEND_IDENTITY_FAILED": "Echec de l'inscription.", - "SEND_CERTIFICATION_FAILED": "Echec de la certification.", + "PASSWORD_NOT_CONFIRMED": "Ne correspond pas au mot de passe", + "SALT_NOT_CONFIRMED": "Ne correspond pas à l'identifiant secret", + "SEND_IDENTITY_FAILED": "Échec de l'inscription", + "SEND_CERTIFICATION_FAILED": "Échec de la certification", "NEED_MEMBER_ACCOUNT_TO_CERTIFY": "Vous ne pouvez pas effectuer de certification, car votre compte n'est <b>pas membre</b>.", "NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF": "Vous ne pouvez pas effectuer de certification, car votre compte n'est pas encore membre.<br/><br/>Il vous manque encore des certifications, ou bien celles-ci n'ont pas encore été validées.", "NOT_MEMBER_FOR_CERTIFICATION": "Votre compte n'est pas encore membre.", - "IDENTITY_TO_CERTIFY_HAS_NO_SELF": "Compte non certifiable. Aucune demande d'adhésion n'a été faite, ou bien elle n'a pas été renouvellée.", + "IDENTITY_TO_CERTIFY_HAS_NO_SELF": "Compte non certifiable. Aucune demande d'adhésion n'a été faite, ou bien elle n'a pas été renouvelée.", "LOGIN_FAILED": "Erreur lors de la connexion.", "LOAD_IDENTITY_FAILED": "Erreur de chargement de l'identité.", "LOAD_REQUIREMENTS_FAILED": "Erreur de chargement des prérequis de l'identité.", - "SEND_MEMBERSHIP_IN_FAILED": "Echec de la tentative d'entrée dans la communauté.", - "SEND_MEMBERSHIP_OUT_FAILED": "Echec de l'arret de l'adhésion.", - "REFRESH_WALLET_DATA": "Echec du rafraichissement du portefeuille.", - "GET_CURRENCY_PARAMETER": "Echec de la récupération des règles de la monnaie.", - "GET_CURRENCY_FAILED": "Chargement de la monnaie impossible. Veuillez ressayer plus tard.", - "SEND_TX_FAILED": "Echec du virement.", - "ALL_SOURCES_USED": "Veuillez attendre le calcul du prochain bloc (Toutes vos sources de monnaie ont été utilisées).", + "SEND_MEMBERSHIP_IN_FAILED": "Échec de la tentative d'entrée dans la communauté.", + "SEND_MEMBERSHIP_OUT_FAILED": "Échec de l'arrêt de l'adhésion.", + "REFRESH_WALLET_DATA": "Échec du rafraîchissement du portefeuille.", + "GET_CURRENCY_PARAMETER": "Échec de la récupération des règles de la monnaie.", + "GET_CURRENCY_FAILED": "Chargement de la monnaie impossible. Veuillez réessayer plus tard.", + "SEND_TX_FAILED": "Échec du virement.", + "ALL_SOURCES_USED": "Veuillez attendre le calcul du prochain bloc (toutes vos sources de monnaie ont été utilisées).", "NOT_ENOUGH_SOURCES": "Pas assez de change pour envoyer ce montant en une seule transaction.<br/>Montant maximum : {{amount}} {{unit}}<sub>{{subUnit}}</sub>.", - "ACCOUNT_CREATION_FAILED": "Echec de la création du compte membre.", - "RESTORE_WALLET_DATA_ERROR": "Echec du rechargement des paramètres depuis le stockage local", - "LOAD_WALLET_DATA_ERROR": "Echec du chargement des données du portefeuille.", + "ACCOUNT_CREATION_FAILED": "Échec de la création du compte membre.", + "RESTORE_WALLET_DATA_ERROR": "Échec du rechargement des paramètres depuis le stockage local", + "LOAD_WALLET_DATA_ERROR": "Échec du chargement des données du portefeuille.", "COPY_CLIPBOARD_FAILED": "Copie de la valeur impossible.", - "TAKE_PICTURE_FAILED": "Echec de la récupération de la photo.", - "SCAN_FAILED": "Echec du scan de QR Code", + "TAKE_PICTURE_FAILED": "Échec de la récupération de la photo.", + "SCAN_FAILED": "Échec du scan de QR-code.", "SCAN_UNKNOWN_FORMAT": "Code non reconnu.", - "WOT_LOOKUP_FAILED": "Echec de la recherche", + "WOT_LOOKUP_FAILED": "Échec de la recherche.", "LOAD_PEER_DATA_FAILED": "Lecture du nÅ“ud Duniter impossible. Veuillez réessayer ultérieurement.", "NEED_LOGIN_FIRST": "Veuillez d'abord vous connecter.", "AMOUNT_REQUIRED": "Le montant est obligatoire.", "AMOUNT_NEGATIVE": "Montant négatif non autorisé.", - "NOT_ENOUGH_CREDIT": "Crédit insufisant.", + "NOT_ENOUGH_CREDIT": "Crédit insuffisant.", "INVALID_NODE_SUMMARY": "NÅ“ud injoignable ou adresse invalide.", "INVALID_USER_ID": "Le pseudonyme ne doit contenir ni espace ni caractère spécial ou accentué.", "INVALID_COMMENT": "Le champ 'référence' ne doit pas contenir de caractères accentués.", "INVALID_PUBKEY": "La clé publique n'a pas le format attendu.", - "IDENTITY_REVOKED": "Cette identité <b>a été révoquée {{revocationTime|formatFromNow}}</b> ({{revocationTime|formatDate}}). Elle ne peut plus devenir membre.", + "INVALID_PUBKEY_CHECKSUM": "Somme de contrôle invalide.", + "IDENTITY_REVOKED": "Cette identité <b>a été révoquée</b>. Elle ne peut plus devenir membre.", + "IDENTITY_REVOKED_WITH_TIME": "Cette identité <b>a été révoquée {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). Elle ne peut plus devenir membre.", "IDENTITY_PENDING_REVOCATION": "La <b>révocation de cette identité</b> a été demandée et est en attente de traitement. La certification est donc désactivée.", "IDENTITY_INVALID_BLOCK_HASH": "Cette demande d'adhésion n'est plus valide (car elle référence un bloc que les nÅ“uds du réseau ont annulé) : cette personne doit renouveler sa demande d'adhésion <b>avant</b> d'être certifiée.", - "IDENTITY_EXPIRED": "La publication de cette identité a expirée : cette personne doit effectuer une nouvelle demande d'adhésion <b>avant</b> d'être certifiée.", + "IDENTITY_EXPIRED": "La publication de cette identité a expiré : cette personne doit effectuer une nouvelle demande d'adhésion <b>avant</b> d'être certifiée.", "IDENTITY_SANDBOX_FULL": "Le nÅ“ud Duniter utilisé par Cesium ne peut plus recevoir de nouvelles identités, car sa file d'attente est pleine.<br/><br/>Veuillez réessayer ultérieurement ou changer de nÅ“ud (via le menu <b>Paramètres</b>).", - "IDENTITY_NOT_FOUND": "Identité non trouvée", - "IDENTITY_TX_FAILED": "Echec du chargement des opérations", + "IDENTITY_NOT_FOUND": "Identité non trouvée.", + "IDENTITY_TX_FAILED": "Échec du chargement des opérations.", "WOT_PENDING_INVALID_BLOCK_HASH": "Adhésion non valide.", "WALLET_INVALID_BLOCK_HASH": "Votre demande d'adhésion n'est plus valide (car elle référence un bloc que les nÅ“uds du réseau ont annulé).<br/>Vous devez <a ng-click=\"doQuickFix('fixMembership')\">envoyer une nouvelle demande</a> pour résoudre ce problème.", "WALLET_IDENTITY_EXPIRED": "La publication de <b>votre identité a expirée</b>.<br/>Vous devez <a ng-click=\"doQuickFix('fixIdentity')\">publier à nouveau votre identité</a> pour résoudre ce problème.", - "WALLET_REVOKED": "Votre identité a été <b>révoquée</b> : ni votre pseudonyme ni votre clef publique ne pourront être utilisés à l'avenir pour un compte membre.", + "WALLET_REVOKED": "Votre identité a été <b>révoquée</b> : ni votre pseudonyme ni votre clef publique ne pourra être utilisé à l'avenir pour un compte membre.", "WALLET_HAS_NO_SELF": "Votre identité doit d'abord avoir été publiée, et ne pas être expirée.", "AUTH_REQUIRED": "Authentification requise.", "AUTH_INVALID_PUBKEY": "La clef attendue est <i class=\"ion-key\"></i> {{pubkey|formatPubkey}}...", "AUTH_INVALID_SCRYPT": "Identifiant ou mot de passe invalide.", "AUTH_INVALID_FILE": "Fichier de trousseau invalide.", - "AUTH_FILE_ERROR": "Echec de l'ouverture du fichier de trousseau", + "AUTH_FILE_ERROR": "Échec de l'ouverture du fichier de trousseau.", "IDENTITY_ALREADY_CERTIFY": "Vous avez <b>déjà certifié</b> cette identité.<br/><br/>Cette certification est encore valide (expiration {{expiresIn|formatDurationTo}}).", "IDENTITY_ALREADY_CERTIFY_PENDING": "Vous avez <b>déjà certifié</b> cette identité.<br/><br/>Cette certification est en attente de traitement (date limite de traitement {{expiresIn|formatDurationTo}}).", "UNABLE_TO_CERTIFY_TITLE": "Certification impossible", - "LOAD_NEWCOMERS_FAILED": "Echec du chargement des nouveaux membres.", - "LOAD_PENDING_FAILED": "Echec du chargement des inscriptions en attente.", + "LOAD_NEWCOMERS_FAILED": "Échec du chargement des nouveaux membres.", + "LOAD_PENDING_FAILED": "Échec du chargement des inscriptions en attente.", "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "Vous devez <b>être membre</b> pour pouvoir effectuer cette action.", + "ONLY_MEMBER_OR_WAS_MEMBER_CAN_EXECUTE_THIS_ACTION": "Vous devez <b>être membre (ou ancien membre)</b> pour pouvoir effectuer cette action.", "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "Vous devez avoir <b>publié votre identité</b> pour pouvoir effectuer cette action.", - "GET_BLOCK_FAILED": "Echec de la récupération du bloc", - "INVALID_BLOCK_HASH": "Bloc non trouvé (hash différent)", - "DOWNLOAD_REVOCATION_FAILED": "Echec du téléchargement du fichier de révocation.", - "REVOCATION_FAILED": "Echec de la révocation.", - "SALT_OR_PASSWORD_NOT_CONFIRMED": "Identifiant secret ou mot de passe incorrects", - "RECOVER_ID_FAILED": "Echec de la récupération des identifiants", - "LOAD_FILE_FAILED" : "Echec du chargement du fichier", - "NOT_VALID_REVOCATION_FILE": "Fichier de revocation non valide (mauvais format de fichier)", + "GET_BLOCK_FAILED": "Échec de la récupération du bloc.", + "INVALID_BLOCK_HASH": "Bloc non trouvé (hash différent).", + "DOWNLOAD_REVOCATION_FAILED": "Échec du téléchargement du fichier de révocation.", + "REVOCATION_FAILED": "Échec de la révocation.", + "SALT_OR_PASSWORD_NOT_CONFIRMED": "Identifiant secret ou mot de passe incorrect.", + "RECOVER_ID_FAILED": "Échec de la récupération des identifiants", + "LOAD_FILE_FAILED" : "Échec du chargement du fichier", + "NOT_VALID_REVOCATION_FILE": "Fichier de révocation non valide (mauvais format de fichier)", "NOT_VALID_SAVE_ID_FILE": "Fichier de récupération non valide (mauvais format de fichier)", "NOT_VALID_KEY_FILE": "Fichier de trousseau non valide (format non reconnu)", "EXISTING_ACCOUNT": "Vos identifiants correspondent à un compte déjà existant, dont la <a ng-click=\"showHelpModal('pubkey')\">clef publique</a> est :", "EXISTING_ACCOUNT_REQUEST": "Veuillez modifier vos identifiants afin qu'ils correspondent à un compte non utilisé.", - "GET_LICENSE_FILE_FAILED": "Récupérer du fichier de licence impossible", - "CHECK_NETWORK_CONNECTION": "Aucun nÅ“ud ne semble accessible.<br/><br/>Veuillez <b>vérifier votre connection Internet</b>.", - "ISSUE_524_TX_FAILED": "Echec du virement.<br/><br/>Un message a été envoyé aux développeurs pour faciliter la résolution du problème. <b>Merci de votre aide</b>." + "GET_LICENSE_FILE_FAILED": "Récupération du fichier de licence impossible.", + "CHECK_NETWORK_CONNECTION": "Aucun nÅ“ud ne semble accessible.<br/><br/>Veuillez <b>vérifier votre connexion Internet</b>.", + "ISSUE_524_TX_FAILED": "Échec du virement.<br/><br/>Un message a été envoyé aux développeurs pour faciliter la résolution du problème. <b>Merci de votre aide</b>.", + "ADD_SECONDARY_WALLET_FAILED": "Échec de l'ajout du portefeuille secondaire.", + "UPDATE_WALLET_LIST_FAILED": "Échec du rafraîchissement des portefeuilles secondaires.", + "LOAD_WALLET_LIST_FAILED": "Échec du chargement des portefeuilles secondaires.", + "SAVE_WALLET_LIST_FAILED": "Échec de la sauvegarde des portefeuilles secondaires.", + "COULD_NOT_ADD_MAIN_WALLET": "Ce portefeuille <b>correspond au compte principal</b> avec lequel vous êtes connecté.<br/>Impossible de l'ajouter comme portefeuille secondaire.", + "COULD_NOT_ADD_EXISTING_WALLET": "Portefeuille déjà existant dans la liste.", + "UNKNOWN_WALLET_ID": "Portefeuille secondaire inconnu.", + "RESTORE_WALLET_LIST_FAILED": "Échec de la restauration des portefeuilles secondaires.", + "INVALID_FILE_FORMAT": "Format de fichier invalide.", + "SAME_TX_RECIPIENT": "Le destinataire doit être différent de l'émetteur." }, "INFO": { "POPUP_TITLE": "Information", @@ -701,9 +785,10 @@ "COPY_TO_CLIPBOARD_DONE": "Copié dans le presse-papier", "MEMBERSHIP_OUT_SENT": "Résiliation envoyée", "NOT_NEED_MEMBERSHIP": "Vous êtes déjà membre.", - "IDENTITY_WILL_MISSING_CERTIFICATIONS": "Cette identité va bientôt manquer de certification (au moins {{willNeedCertificationCount}}).", - "IDENTITY_NEED_MEMBERSHIP": "Cette identité n'a pas envoyée de demande d'adhésion. Elle devra si elle souhaite devenir membre.", - "REVOCATION_SENT": "Revocation envoyée", + "IDENTITY_WILL_MISSING_CERTIFICATIONS": "Cette identité va bientôt manquer de certifications (au moins {{willNeedCertificationCount}}).", + "IDENTITY_NEED_MEMBERSHIP": "Cette identité n'a pas envoyée de demande d'adhésion. Elle le devra si elle souhaite devenir membre.", + "HAS_ALTERNATIVE_IDENTITIES": "Il existe <b>plusieurs identités</b> rattachées à cette clé publique. <b>Avant toute certification</b>, pensez à <a ng-click=\"doQuickFix('showSelectIdentities')\">consulter les autres identités</a> pour choisir la bonne, ou bien contacter le propriétaire du compte.", + "REVOCATION_SENT": "Révocation envoyée", "REVOCATION_SENT_WAITING_PROCESS": "La <b>révocation de cette identité</b> a été demandée et est en attente de traitement.", "FEATURES_NOT_IMPLEMENTED": "Cette fonctionnalité est encore en cours de développement.<br/>Pourquoi ne pas <b>contribuer à Cesium</b>, pour l'obtenir plus rapidement ? ;)", "EMPTY_TX_HISTORY": "Aucune opération à exporter" @@ -713,24 +798,27 @@ "POPUP_WARNING_TITLE": "<b>Avertissement</b>", "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Avertissement de sécurité</b>", "CERTIFY_RULES_TITLE_UID": "Certifier {{uid}}", - "CERTIFY_RULES": "<b class=\"assertive\">Ne PAS certifier</b> un compte si vous pensez que :<br/><br/><ul><li>1.) il ne correspond pas à une personne <b>physique et vivante</b>.<li>2.) son propriétaire <b>possède un autre compte</b> déjà certifié.<li>3.) son propriétaire viole (volontairement ou non) la règle 1 ou 2 (par exemple en certifiant des comptes factices ou en double).</ul><br/><b>Etes-vous sûr</b> de vouloir néanmoins certifier cette identité ?", - "TRANSFER": "<b>Récapitulatif du virement</b> :<br/><br/><ul><li> - De : {{from}}</li><li> - A : <b>{{to}}</b></li><li> - Montant : <b>{{amount}} {{unit}}</b></li><li> - Commentaire : <i>{{comment}}</i></li></ul><br/><b>Etes-vous sûr de vouloir effectuer ce virement ?</b>", - "MEMBERSHIP_OUT": "Cette opération est <b>irréversible</b>.<br/></br/>Etes-vous sûr de vouloir <b>résilier votre compte membre</b> ?", - "MEMBERSHIP_OUT_2": "Cette opération est <b>irreversible</b> !<br/><br/>Etes-vous vraiment sûr de vouloir <b>résilier votre adhésion</b> comme membre ?", + "CERTIFY_RULES": "<b class=\"assertive\">Ne PAS certifier</b> un compte si vous pensez que :<br/><br/><ul><li>1.) il ne correspond pas à une personne <b>physique et vivante</b>.<li>2.) son propriétaire <b>possède un autre compte</b> déjà certifié.<li>3.) son propriétaire viole (volontairement ou non) la règle 1 ou 2 (par exemple en certifiant des comptes factices ou en double).</ul><br/><b>Êtes-vous sûr</b> de vouloir néanmoins certifier cette identité ?", + "FULLSCREEN": "Afficher l'application en plein écran ?", + "EXIT_APP": "Fermer l'application ?", + "TRANSFER": "<b>Récapitulatif du virement</b> :<br/><br/><ul><li> - De : {{from}}</li><li> - A : <b>{{to}}</b></li><li> - Montant : <b>{{amount}} {{unit}}</b></li><li> - Commentaire : <i>{{comment}}</i></li></ul><br/><b>Êtes-vous sûr de vouloir effectuer ce virement ?</b>", + "TRANSFER_ALL": "<b>Récapitulatif du virement</b> :<br/><br/><ul><li> - De : {{from}}</li><li> - A : <b>{{to}}</b></li><li> - Montant : <b>{{amount}} {{unit}}</b></li><li> - Commentaire : <i>{{comment}}</i></li><br/><li> - Reste : <b>{{restAmount}} {{unit}}</b> à <b>{{restTo}}</b></li></ul><br/><b>Êtes-vous sûr de vouloir effectuer ce virement ?</b>", + "MEMBERSHIP_OUT": "Cette opération est <b>irréversible</b>.<br/></br/>Êtes-vous sûr de vouloir <b>résilier votre compte membre</b> ?", + "MEMBERSHIP_OUT_2": "Cette opération est <b>irreversible</b> !<br/><br/>Êtes-vous vraiment sûr de vouloir <b>résilier votre adhésion</b> comme membre ?", "LOGIN_UNUSED_WALLET_TITLE": "Erreur de saisie ?", "LOGIN_UNUSED_WALLET": "Le compte connecté semble <b>inactif</b>.<br/><br/>Il s'agit probablement d'une <b>erreur de saisie</b> dans vos identifiants de connexion. Veuillez recommencer, en vérifiant que <b>la clé publique est celle de votre compte</b>.", - "FIX_IDENTITY": "Le pseudonyme <b>{{uid}}</b> va être publiée à nouveau, en remplacement de l'ancienne publication qui a expirée.<br/></br/><b>Etes-vous sûr</b> de vouloir continuer ?", - "FIX_MEMBERSHIP": "Votre demande d'adhésion comme membre va être renvoyée.<br/></br/><b>Etes-vous sûr</b> de vouloir continuer ?", - "MEMBERSHIP": "Votre demande d'adhésion comme membre va être envoyée.<br/></br/><b>Etes-vous sûr</b> de vouloir continuer ?", - "RENEW_MEMBERSHIP": "Votre adhésion comme membre va être renouvellée.<br/></br/><b>Etes-vous sûr</b> de vouloir continuer ?", - "REVOKE_IDENTITY": "Vous allez <b>revoquer définitivement cette identité</b>.<br/><br/>La clé publique et le pseudonyme associés <b>ne pourront plus jamais être utilisés</b> (pour un compte membre). <br/></br/><b>Etes-vous sûr</b> de vouloir révoquer définitivement ce compte ?", - "REVOKE_IDENTITY_2": "Cette opération est <b>irreversible</b> !<br/><br/>Etes-vous vraiment sûr de vouloir <b>révoquer définitivement</b> ce compte ?", - "NOT_NEED_RENEW_MEMBERSHIP": "Votre adhésion n'a pas besoin d'être renouvellée (elle n'expirera que dans {{membershipExpiresIn|formatDuration}}).<br/></br/><b>Etes-vous sûr</b> de vouloir renouveler votre adhésion ?", + "FIX_IDENTITY": "Le pseudonyme <b>{{uid}}</b> va être publiée à nouveau, en remplacement de l'ancienne publication qui a expirée.<br/></br/><b>Êtes-vous sûr</b> de vouloir continuer ?", + "FIX_MEMBERSHIP": "Votre demande d'adhésion comme membre va être renvoyée.<br/></br/><b>Êtes-vous sûr</b> de vouloir continuer ?", + "MEMBERSHIP": "Votre demande d'adhésion comme membre va être envoyée.<br/></br/><b>Êtes-vous sûr</b> de vouloir continuer ?", + "RENEW_MEMBERSHIP": "Votre adhésion comme membre va être renouvelée.<br/></br/><b>Êtes-vous sûr</b> de vouloir continuer ?", + "REVOKE_IDENTITY": "Vous allez <b>revoquer définitivement cette identité</b>.<br/><br/>La clé publique et le pseudonyme associés <b>ne pourront plus jamais être utilisés</b> (pour un compte membre). <br/></br/><b>Êtes-vous sûr</b> de vouloir révoquer définitivement ce compte ?", + "REVOKE_IDENTITY_2": "Cette opération est <b>irreversible</b> !<br/><br/>Êtes-vous vraiment sûr de vouloir <b>révoquer définitivement</b> ce compte ?", + "NOT_NEED_RENEW_MEMBERSHIP": "Votre adhésion n'a pas besoin d'être renouvelée (elle n'expirera que dans {{membershipExpiresIn|formatDuration}}).<br/></br/><b>Êtes-vous sûr</b> de vouloir renouveler votre adhésion ?", "SAVE_BEFORE_LEAVE": "Voulez-vous <b>sauvegarder vos modifications</b> avant de quitter la page ?", "SAVE_BEFORE_LEAVE_TITLE": "Modifications non enregistrées", - "LOGOUT": "Etes-vous sûr de vouloir vous déconnecter ?", + "LOGOUT": "Êtes-vous sûr de vouloir vous déconnecter ?", "USE_FALLBACK_NODE": "NÅ“ud <b>{{old}}</b> injoignable ou adresse invalide.<br/><br/>Voulez-vous temporairement utiliser le nÅ“ud <b>{{new}}</b> ?", - "ISSUE_524_SEND_LOG": "La transaction a été rejettée, à cause d'une anomalie connue (ticket #524) mais <b>non reproduite</b>.<br/><br/>Pour nous aider les développeurs à corriger cette erreur, <b>acceptez-vous la transmission de vos logs</b> par message ?<br/><small>(Aucune donnée confidentielle n'est envoyée)</small>." + "ISSUE_524_SEND_LOG": "La transaction a été rejetée, à cause d'une anomalie connue (ticket #524) mais <b>non reproduite</b>.<br/><br/>Pour aider les développeurs à corriger cette erreur, <b>acceptez-vous la transmission de vos logs</b> par message ?<br/><small>(aucune donnée confidentielle n'est envoyée)</small>." }, "DOWNLOAD": { "POPUP_TITLE": "<b>Fichier de révocation</b>", @@ -740,27 +828,31 @@ "TITLE": "Aide en ligne", "JOIN": { "SECTION": "Inscription", - "SALT": "L'identifiant secret est très important. Il sert à mélanger le mot de passe, avant qu'il ne servent à calculer la <span class=\"text-italic\">clé publique</span> de votre compte (son numéro) et la clé secrète pour y accéder.<br/><b>Veuillez à bien la mémoriser</b>, car aucun moyen n'est actuellement prévu pour la retrouver en cas de perte.<br/>Par ailleurs, il ne peut pas être modifié sans devoir créer un nouveau compte.<br/><br/>Un bon identifiant secret doit être suffisamment long (au moins 8 caractères) et le plus original possible.", - "PASSWORD": "Le mot de passe est très important. Avec l'identifiant secret, il sert à à calculer le numéro (la clé publique) de votre compte, et la clé secrète pour y accéder.<br/><b>Veuillez à bien le mémoriser</b>, car aucun moyen n'est de le retrouver en cas de perte (sauf à générer un fichier de sauvegarde).<br/>Par ailleurs, il ne peut pas être modifié sans devoir créer un nouveau compte.<br/><br/>Un bon mot de passe contient (idéalement) au moins 8 caractères, dont au moins une majuscule et un chiffre.", - "PSEUDO": "Le pseudonyme utilisé uniquement dans le cas d'inscription comme <span class=\"text-italic\">membre</span>. Il est toujours associé à un portefeuille (via sa <span class=\"text-italic\">clé publique</span>).<br/>Il est publié sur le réseau, afin que les autres utilisateurs puisse l'identifier, le certifier ou envoyer de la monnaie sur le compte.<br/>Un pseudonyme doit être unique au sein des membres (<u>actuels</u> et anciens)." + "SALT": "L'identifiant secret est très important. Il sert à mélanger le mot de passe, avant qu'il ne serve à calculer la <span class=\"text-italic\">clé publique</span> de votre compte (son numéro) et la clé secrète pour y accéder.<br/><b>Veillez à bien la mémoriser</b>, car aucun moyen n'est actuellement prévu pour la retrouver en cas de perte.<br/>Par ailleurs, il ne peut pas être modifié sans devoir créer un nouveau compte.<br/><br/>Un bon identifiant secret doit être suffisamment long (au moins 8 caractères) et le plus original possible.", + "PASSWORD": "Le mot de passe est très important. Avec l'identifiant secret, il sert à calculer le numéro (la clé publique) de votre compte, et la clé secrète pour y accéder.<br/><b>Veillez à bien le mémoriser</b>, car aucun moyen n'est prévu de le retrouver en cas de perte (sauf à générer un fichier de sauvegarde).<br/>Par ailleurs, il ne peut pas être modifié sans devoir créer un nouveau compte.<br/><br/>Un bon mot de passe contient (idéalement) au moins 8 caractères, dont au moins une majuscule et un chiffre.", + "PSEUDO": "Le pseudonyme est utilisé uniquement dans le cas d'inscription comme <span class=\"text-italic\">membre</span>. Il est toujours associé à un portefeuille (via sa <span class=\"text-italic\">clé publique</span>).<br/>Il est publié sur le réseau, afin que les autres utilisateurs puisse l'identifier, le certifier ou envoyer de la monnaie sur le compte.<br/>Un pseudonyme doit être unique au sein des membres (<u>actuels</u> et anciens)." }, "LOGIN": { "SECTION": "Connexion", "PUBKEY": "Clé publique du trousseau", "PUBKEY_DEF": "La clef publique du trousseau est générée à partir des identifiants saisis (n'importe lesquels), sans pour autant qu'ils correspondent à un compte déjà utilisé.<br/><b>Vérifiez attentivement que la clé publique est celle de votre compte</b>. Dans le cas contraire, vous serez connecté à un compte probablement jamais utilisé, le risque de collision avec un compte existant étant infime.<br/><a href=\"https://fr.wikipedia.org/wiki/Cryptographie_asym%C3%A9trique\" target=\"_system\">En savoir plus sur la cryptographie</a> par clé publique.", "METHOD": "Méthodes de connexion", - "METHOD_DEF": "Plusieurs options sont disponibles pour vous connecter à un portfeuille :<br/> - La connexion <b>par sallage (simple ou avancé)</b> mélange votre mot de passe grâce à l'identifiant secret, pour limiter les tentatives de <a href=\"https://fr.wikipedia.org/wiki/Attaque_par_force_brute\" target=\"_system\">piratage par force brute</a> (par exemple à partir de mots connus).<br/> - La connexion <b>par clé publique</b> évite de saisir vos identifiants, qui vous seront demandé seulement le moment venu lors d'une opération sur le compte.<br/> - La connexion <b>par fichier de trousseau</b> va lire les clés (publique et privée) du compte, depuis un fichier, sans besoin de saisir d'identifiants. Plusieurs formats de fichier sont possibles." + "METHOD_DEF": "Plusieurs options sont disponibles pour vous connecter à un portefeuille :<br/> - La connexion <b>par salage (simple ou avancé)</b> mélange votre mot de passe grâce à l'identifiant secret, pour limiter les tentatives de <a href=\"https://fr.wikipedia.org/wiki/Attaque_par_force_brute\" target=\"_system\">piratage par force brute</a> (par exemple à partir de mots connus).<br/> - La connexion <b>par clé publique</b> évite de saisir vos identifiants, qui vous seront demandé seulement le moment venu lors d'une opération sur le compte.<br/> - La connexion <b>par fichier de trousseau</b> va lire les clés (publique et privée) du compte, depuis un fichier, sans besoin de saisir d'identifiants. Plusieurs formats de fichier sont possibles." }, "GLOSSARY": { "SECTION": "Glossaire", "PUBKEY_DEF": "Une clé publique identifie un portefeuille de monnaie, qui peut identifier un membre ou correspondre à un portefeuille anonyme. Dans Cesium la clé publique est calculée (par défaut) grâce à l'identifiant secret et au mot de passe.<br/><a href=\"https://fr.wikipedia.org/wiki/Cryptographie_asym%C3%A9trique\" target=\"_system\">En savoir plus sur la cryptographie</a> par clé publique.", "MEMBER": "Membre", - "MEMBER_DEF": "Un membre est une personne humaine physique et vivante, désireuse de participer librement à la communauté monétaire. Elle percoit un dividende universel, suivant une période et un montant tels que définis dans les <span class=\"text-italic\">règles de la monnaie</span>", + "MEMBER_DEF": "Un membre est une personne humaine physique et vivante, désireuse de participer librement à la communauté monétaire. Elle co-produit un dividende universel, suivant une période et un montant tels que définis dans les <span class=\"text-italic\">règles de la monnaie</span>", "CURRENCY_RULES": "Règles de la monnaie", - "CURRENCY_RULES_DEF": "Les règles de la monnaie sont définies une fois pour toute. Elle fixe le fonctionnement de la monnaie : le calcul du dividend universel, le nombre de certifications nécessaire pour être membre, le nombre de certification maximum qu'un membre peut donner, etc. <a href=\"#/app/currency\">Voir les règles actuelles</a>.<br/>La non modification des règles dans le temps est possible par l'utilisation d'une <span class=\"text-italic\">BlockChain</span> qui porte et execute ces règles, et en vérifie constamment la bonne application.", + "CURRENCY_RULES_DEF": "Les règles de la monnaie sont définies une fois pour toutes. Elle fixe le fonctionnement de la monnaie : le calcul du dividende universel, le nombre de certifications nécessaire pour être membre, le nombre de certification maximum qu'un membre peut donner, etc. <a href=\"#/app/currency\">Voir les règles actuelles</a>.<br/>La non modification des règles dans le temps est possible par l'utilisation d'une <span class=\"text-italic\">BlockChain</span> qui porte et exécute ces règles, et en vérifie constamment la bonne application.", "BLOCKCHAIN": "Chaîne de blocs (<span class=\"text-italic\">Blockchain</span>)", - "BLOCKCHAIN_DEF": "La BlockChain est un système décentralisé, qui, dans le cas de Duniter, sert à porter et executer les <span class=\"text-italic\">règles de la monnaie</span>.<br/><a href=\"https://duniter.org/fr/comprendre/\" target=\"_system\">En savoir plus sur Duniter</a> et le fonctionnement de sa blockchain.", - "UNIVERSAL_DIVIDEND_DEF": "Le Dividende Universel (DU) est la quantité de monnaie co-créée par chaque membre, suivant la période et le calcul définie dans les <span class=\"text-italic\">règles de la monnaie</span>.<br/>A chaque échéance, les membres recoivent sur leur compte la meme quantité de nouvelle monnaie.<br/><br/>Le DU subit une croissance régulière, pour rester juste entre les membres (actuels et à venir), calculée en fonction de l'espérance de vie moyenne, telle que démontré dans la Thérorie Relative de la Monnaie (TRM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">En savoir plus sur la TRM</a> et les monnaies libres." + "BLOCKCHAIN_DEF": "La BlockChain est un système décentralisé, qui, dans le cas de Duniter, sert à porter et exécuter les <span class=\"text-italic\">règles de la monnaie</span>.<br/><a href=\"https://duniter.org/fr/comprendre/\" target=\"_system\">En savoir plus sur Duniter</a> et le fonctionnement de sa blockchain.", + "UNIVERSAL_DIVIDEND_DEF": "Le Dividende Universel (DU) est la quantité de monnaie co-créée par chaque membre, suivant la période et le calcul définis dans les <span class=\"text-italic\">règles de la monnaie</span>.<br/>A chaque échéance, les membres recoivent sur leur compte la meme quantité de nouvelle monnaie.<br/><br/>Le DU subit une croissance régulière, pour rester juste entre les membres (actuels et à venir), calculée en fonction de l'espérance de vie moyenne, telle que démontré dans la Thérorie Relative de la Monnaie (TRM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">En savoir plus sur la TRM</a> et les monnaies libres.", + "WOT": "Toile de Confiance (TdC)", + "WOT_DEF": "La Toile de Confiance est constituée de l'ensemble des membres de la monnaie, et des liens de certification qui les relient.", + "DISTANCE_RULE": "Règle de distance", + "DISTANCE_RULE_DEF": "La règle de distance de la Toile de Confiance définie <b>une distance maximale à respecter</b> entre un postulant et un nombre minimum de membres référents (ou membres centraux). Cette distance est calculée en utilisant les liens de certification." }, "TIP": { "MENU_BTN_CURRENCY": "Le menu <b>{{'MENU.CURRENCY'|translate}}</b> permet la consultation des <b>règles de la monnaie</b> et de son état.", @@ -768,11 +860,11 @@ "CURRENCY_MASS": "Suivez ici la <b>quantité totale de monnaie</b> existante et sa <b>répartition moyenne</b> par membre.<br/><br/>Ceci permet de juger de l'<b>importance d'un montant</b>, vis à vis de ce que <b>possède les autres</b> sur leur compte (en moyenne).", "CURRENCY_UNIT_RELATIVE": "L'unité utilisée (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) signifie que les montants en {{currency|capitalize}} ont été divisés par le <b>Dividende Universel</b> (DU).<br/><br/><small>Cette unité relative est <b>pertinente</b>, car stable malgré la quantitié de monnaie qui augmente en permanence.</small>", "CURRENCY_CHANGE_UNIT": "L'option <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> permet de <b>changer d'unité</b>, pour visualiser les montants <b>directement en {{currency|capitalize}}</b> (plutôt qu'en “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”).", - "CURRENCY_CHANGE_UNIT_TO_RELATIVE": "L'option <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> permet de <b>changer d'unité</b>, pour visualiser les montants en “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”, c'est à dire relativement au Dividende Universel (le montant co-produit par chaque membre).", + "CURRENCY_CHANGE_UNIT_TO_RELATIVE": "L'option <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> permet de <b>changer d'unité</b>, pour visualiser les montants en “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”, c'est-à -dire relativement au Dividende Universel (le montant co-produit par chaque membre).", "CURRENCY_RULES": "Les <b>règles</b> de la monnaie fixent son fonctionnement <b>exact et prévisible</b>.<br/><br/>Véritable ADN de la monnaie, elles rendent son code monétaire <b>lisible et transparent</b>.", "MENU_BTN_NETWORK": "Le menu <b>{{'MENU.NETWORK'|translate}}</b> permet la consultation de l'état du réseau.", - "NETWORK_BLOCKCHAIN": "Toutes les opérations de la monnaie sont enregistrées dans un grand livre de compte <b>public et infalsifiable</b>, appellé aussi <b>chaine de blocs</b> (<em>BlockChain</em> en anglais).", - "NETWORK_PEERS": "Les <b>nÅ“uds</b> visibles ici correspondent aux <b>ordinateurs qui actualisent et contrôlent</b> la chaine de blocs.<br/><br/>Plus il y a de nÅ“uds, plus la monnaie à une gestion <b>décentralisée</b> et digne de confiance.", + "NETWORK_BLOCKCHAIN": "Toutes les opérations de la monnaie sont enregistrées dans un grand livre de compte <b>public et infalsifiable</b>, appelé aussi <b>chaine de blocs</b> (<em>BlockChain</em> en anglais).", + "NETWORK_PEERS": "Les <b>nÅ“uds</b> visibles ici correspondent aux <b>ordinateurs qui actualisent et contrôlent</b> la chaine de blocs.<br/><br/>Plus il y a de nÅ“uds, plus la monnaie a une gestion <b>décentralisée</b> et digne de confiance.", "NETWORK_PEERS_BLOCK_NUMBER": "Ce <b>numéro</b> (en vert) indique le <b>dernier bloc validé</b> pour ce nÅ“ud (dernière page écrite dans le grand livre de comptes).<br/><br/>La couleur verte indique que ce bloc est également validé par <b>la plupart des autres nÅ“uds</b>.", "NETWORK_PEERS_PARTICIPATE": "<b>Chaque membre</b>, équipé d'un ordinateur avec Internet, <b>peut participer en ajoutant un nÅ“ud</b>. Il suffit d'<b>installer le logiciel Duniter</b> (libre et gratuit). <a href=\"{{installDocUrl}}\" target=\"_system\">Voir le manuel d'installation >></a>.", "MENU_BTN_ACCOUNT": "Le menu <b>{{'ACCOUNT.TITLE'|translate}}</b> permet d'accéder à la gestion de votre compte.", @@ -784,25 +876,25 @@ "WALLET_BALANCE_RELATIVE": "{{'HELP.TIP.WALLET_BALANCE'|translate}}<br/><br/>L'unité utilisée (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) signifie que le montant en {{currency|capitalize}} a été divisé par le <b>Dividende Universel</b> (DU) co-créé par chaque membre.<br/><br/>Actuellement 1 DU vaut {{currentUD|formatInteger}} {{currency|capitalize}}s.", "WALLET_BALANCE_CHANGE_UNIT": "Vous pourrez <b>changer l'unité</b> d'affichage des montants dans les <b><i class=\"icon ion-android-settings\"></i> {{'MENU.SETTINGS'|translate}}</b>.<br/><br/>Par exemple pour visualiser les montants <b>directement en {{currency|capitalize}}</b>, plutôt qu'en unité relative.", "WALLET_PUBKEY": "Voici la clé publique de votre compte. Vous pouvez la communiquer à un tiers afin qu'il identifie plus simplement votre compte.", - "WALLET_SEND": "Effectuer un paiement en quelques clics", + "WALLET_SEND": "Effectuer un paiement en quelques clics.", "WALLET_SEND_NO_MONEY": "Effectuer un paiement en quelques clics.<br/>(Votre solde ne le permet pas encore)", "WALLET_OPTIONS": "Ce bouton permet l'accès aux <b>actions d'adhésion</b> et de sécurité.<br/><br/>N'oubliez pas d'y jeter un oeil !", "WALLET_RECEIVED_CERTS": "S'affichera ici la liste des personnes qui vous ont certifié.", - "WALLET_CERTIFY": "Le bouton <b>{{'WOT.BTN_SELECT_AND_CERTIFY'|translate}}</b> permet de sélectionner une identitié et de la certifier.<br/><br/>Seuls des utilisateurs <b>déjà membre</b> peuvent en certifier d'autres.", - "WALLET_CERT_STOCK": "Votre stock de certification (émises) est limité à <b>{{sigStock}} certifications</b>.<br/><br/>Ce stock se renouvelle avec le temps, au fur et à mesure que les certifications s'invalident.", + "WALLET_CERTIFY": "Le bouton <b>{{'WOT.BTN_SELECT_AND_CERTIFY'|translate}}</b> permet de sélectionner une identité et de la certifier.<br/><br/>Seuls des utilisateurs <b>déjà membres</b> peuvent en certifier d'autres.", + "WALLET_CERT_STOCK": "Votre stock de certifications (émises) est limité à <b>{{sigStock}} certifications</b>.<br/><br/>Ce stock se renouvelle avec le temps, au fur et à mesure que les certifications s'invalident.", "MENU_BTN_TX_MEMBER": "Le menu <b>{{'MENU.TRANSACTIONS'|translate}}</b> permet de consulter votre solde, l'historique vos transactions et d'envoyer un paiement.", - "MENU_BTN_TX": "Consultez ici <b>l'historique de vos transactions</b> et effectuer de nouvelles opérations.", - "MENU_BTN_WOT": "Le menu <b>{{'MENU.WOT'|translate}}</b> permet de rechercher parmi les <b>utilisateurs</b> de la monnaie (membre ou non).", + "MENU_BTN_TX": "Consultez ici <b>l'historique de vos transactions</b> et effectuez de nouvelles opérations.", + "MENU_BTN_WOT": "Le menu <b>{{'MENU.WOT'|translate}}</b> permet de rechercher parmi les <b>utilisateurs</b> de la monnaie (membres ou non).", "WOT_SEARCH_TEXT_XS": "Pour rechercher dans l'annuaire, tapez les <b>premières lettres d'un pseudonyme</b> (ou d'une clé publique).<br/><br/>La recherche se lancera automatiquement.", "WOT_SEARCH_TEXT": "Pour rechercher dans l'annuaire, tapez les <b>premières lettres d'un pseudonyme</b> (ou d'une clé publique). <br/><br/>Appuyer ensuite sur <b>Entrée</b> pour lancer la recherche.", "WOT_SEARCH_RESULT": "Visualisez la fiche détaillée simplement en <b>cliquant</b> sur une ligne.", - "WOT_VIEW_CERTIFICATIONS": "La ligne <b>{{'ACCOUNT.CERTIFICATION_COUNT'|translate}}</b> montre combien de membres ont validés cette identité.<br/><br/>Ces certifications attestent que le compte appartient à <b>une personne humaine vivante</b> n'ayant <b>aucun autre compte membre</b>.", + "WOT_VIEW_CERTIFICATIONS": "La ligne <b>{{'ACCOUNT.CERTIFICATION_COUNT'|translate}}</b> montre combien de membres ont validé cette identité.<br/><br/>Ces certifications attestent que le compte appartient à <b>une personne humaine vivante</b> n'ayant <b>aucun autre compte membre</b>.", "WOT_VIEW_CERTIFICATIONS_COUNT": "Il faut au moins <b>{{sigQty}} certifications</b> pour devenir membre et recevoir le <b>Dividende Universel</b>.", "WOT_VIEW_CERTIFICATIONS_CLICK": "Un clic ici permet d'ouvrir <b>la liste de toutes les certifications</b> de l'identité (reçues et émises).", "WOT_VIEW_CERTIFY": "Le bouton <b>{{'WOT.BTN_CERTIFY'|translate}}</b> permet d'ajouter votre certification à cette identité.", - "CERTIFY_RULES": "<b>Attention :</b> Ne certifier que des <b>personnes physiques vivantes</b>, ne possèdant aucun autre compte membre.<br/><br/>La sécurité de la monnaie dépend de la vigilance de chacun !", + "CERTIFY_RULES": "<b>Attention :</b> Ne certifiez que des <b>personnes physiques vivantes</b>, ne possédant aucun autre compte membre.<br/><br/>La sécurité de la monnaie dépend de la vigilance de chacun !", "MENU_BTN_SETTINGS": "Les <b>{{'MENU.SETTINGS'|translate}}</b> vous permettront de configurer l'application.", - "HEADER_BAR_BTN_PROFILE": "Cliquez ici pour accéder à votre <b>profil utilisateur</b>", + "HEADER_BAR_BTN_PROFILE": "Cliquez ici pour accéder à votre <b>profil utilisateur.</b>", "SETTINGS_CHANGE_UNIT": "Vous pourrez <b>changer d'unité d'affichage</b> des montants en cliquant ci-dessus.<br/><br/>- Désactivez l'option pour un affichage des montants en {{currency|capitalize}}.<br/>- Activez l'option pour un affichage relatif en {{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub> (tous les montants seront <b>divisés</b> par le Dividende Universel courant).", "END_LOGIN": "Cette visite guidée est <b>terminée</b> !<br/><br/>Bonne continuation à vous, dans le nouveau monde de l'<b>économie libre</b> !", "END_NOT_LOGIN": "Cette visite guidée est <b>terminée</b> !<br/><br/>Si vous souhaitez rejoindre la monnaie {{currency|capitalize}}, il vous suffira de cliquer sur <b>{{'LOGIN.CREATE_ACCOUNT'|translate}}</b> ci-dessous." @@ -810,25 +902,28 @@ }, "API" :{ "COMMON": { - "LINK_DOC": "documentation API", + "LINK_DOC": "Documentation API", "LINK_DOC_HELP": "Documentation pour les développeurs", - "LINK_STANDARD_APP": "version classique", - "LINK_STANDARD_APP_HELP": "Ouvrir la version classique de {{'COMMON.APP_NAME'|translate}}" + "LINK_STANDARD_APP": "Version classique", + "LINK_STANDARD_APP_HELP": "Ouvrir la version classique de {{'COMMON.APP_NAME'|translate}}", + "CONNECTION_ERROR": "NÅ“ud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifiez votre connexion Internet, ou contactez l'administrateur du site</a>." }, "HOME": { "TITLE": "Documentation API {{'COMMON.APP_NAME'|translate}}", - "MESSAGE": "Bienvenue dans la <b>documentation de l'API</b> {{'COMMON.APP_NAME'|translate}}.<br/>Connecter vos sites web à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", - "MESSAGE_SHORT": "Connecter vos sites à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", + "MESSAGE": "Bienvenue dans la <b>documentation de l'API</b> {{'COMMON.APP_NAME'|translate}}.<br/>Connectez vos sites web à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", + "MESSAGE_SHORT": "Connectez vos sites à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", "DOC_HEADER": "Services disponibles :" }, "TRANSFER": { "TITLE": "{{'COMMON.APP_NAME'|translate}} - Paiement en ligne", "TITLE_SHORT": "Paiement en ligne", - "SUMMARY": "Récapitulatif de la commande :", + "SUMMARY": "Récapitulatif du paiement :", "AMOUNT": "Montant :", + "AMOUNTS_HELP": "Veuillez choisir le montant :", "NAME": "Nom :", - "PUBKEY": "Clé publique du destinaire :", - "COMMENT": "Référence de la commande :", + "PUBKEY": "Clé publique du destinataire :", + "COMMENT": "Référence de l'opération :", + "NODE": "Adresse du nÅ“ud :", "DEMO": { "SALT": "demo", "PASSWORD": "demo", @@ -843,7 +938,7 @@ "CANCEL_REDIRECTING": "Paiement annulé.<br/>Redirection vers le site du vendeur..." }, "ERROR": { - "TRANSFER_FAILED": "Echec du paiement" + "TRANSFER_FAILED": "Échec du paiement" } }, "DOC": { @@ -854,6 +949,7 @@ "DEMO_DIVIDER": "Tester", "DEMO_HELP": "Pour tester ce service, cliquez sur le bouton ci-contre. Le résultat s'affichera en dessous.", "DEMO_RESULT": "Résultat retourné par l'appel :", + "DEMO_RESULT_PEER": "Adresse du nÅ“ud utilisé :", "DEMO_SUCCEED": "<i class=\"icon ion-checkmark\"></i> Succès !", "DEMO_CANCELLED": "<i class=\"icon ion-close\"></i> Annulé par l'utilisateur", "INTEGRATE_DIVIDER": "Intégrer", @@ -862,31 +958,33 @@ "INTEGRATE_PARAMETERS": "Paramètres", "TRANSFER": { "TITLE": "Paiements", - "DESCRIPTION": "Depuis un site (ex: vente en ligne) vous pouvez déléguer le paiement en monnaie libre à Cesium API. Pour cela, il vous suffit de déclencher l'ouveture d'un page sur l'adresse suivante :", + "DESCRIPTION": "Depuis un site (ex: vente en ligne) vous pouvez déléguer le paiement en monnaie libre à Cesium API. Pour cela, il vous suffit de déclencher l'ouverture d'une page sur l'adresse suivante :", "PARAM_PUBKEY": "Clé publique du destinataire", "PARAM_PUBKEY_HELP": "Clé publique du destinataire (obligatoire)", "PARAM_AMOUNT": "Montant", - "PARAM_AMOUNT_HELP": "Montant de la transaction (obligatoire)", + "PARAM_AMOUNT_HELP": "Montant de la transaction (obligatoire). Valeurs multiples autorisées, en utilisant un séparateur (point-virgule, barre verticale ou espace).", "PARAM_COMMENT": "Référence (ou commentaire)", "PARAM_COMMENT_HELP": "Référence ou commentaire. Vous permettra par exemple d'identifier le paiement dans la BlockChain.", "PARAM_NAME": "Nom (du destinataire ou du site web)", - "PARAM_NAME_HELP": "Le nom du destinataire, ou du site web appellant. Cela peut-etre un nom lisible (\"Mon site en ligne\"), ou encore une pseudo-adresse web (\"MonSite.com\").", + "PARAM_NAME_HELP": "Le nom du destinataire, ou du site web appelant. Cela peut être un nom lisible (\"Mon site en ligne\"), ou encore une pseudo-adresse web (\"MonSite.com\").", "PARAM_REDIRECT_URL": "Adresse web de redirection", - "PARAM_REDIRECT_URL_HELP": "Adresse web (URL) de redirection, appellé quand le paiement a été envoyé. Peut contenir les chaines suivantes, qui seront remplacée par les valeurs de la transaction : \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\" et {pubkey}.", + "PARAM_REDIRECT_URL_HELP": "Adresse web (URL) de redirection, appelé quand le paiement a été envoyé. Peut contenir les chaînes suivantes, qui seront remplacées par les valeurs de la transaction : \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\", \"{pubkey}\" et \"{node}\".", "PARAM_CANCEL_URL": "Adresse web d'annulation", - "PARAM_CANCEL_URL_HELP": "Adresse web (URL) en cas d'annulation du paiement, par l'utilisateur. Peut contenir les chaines suivantes, qui seront remplacée dynamiquement: \"{comment}\", \"{amount}\" et {pubkey}.", + "PARAM_CANCEL_URL_HELP": "Adresse web (URL) en cas d'annulation du paiement, par l'utilisateur. Peut contenir les chaînes suivantes, qui seront remplacées dynamiquement : \"{comment}\", \"{amount}\" et {pubkey}.", + "PARAM_PREFERRED_NODE": "Adresse du nÅ“ud préféré", + "PARAM_PREFERRED_NODE_HELP": "Adresse (URL) du nÅ“ud Duniter à utiliser de préférence (\"g1.domaine.com:443\" ou \"https://g1.domaine.com\").", "EXAMPLES_HELP": "Voici des exemples d'intégration :", "EXAMPLE_BUTTON": "Bouton HTML", "EXAMPLE_BUTTON_DEFAULT_TEXT": "Payer en {{currency|currencySymbol}}", "EXAMPLE_BUTTON_DEFAULT_STYLE": "Style personnalisé", "EXAMPLE_BUTTON_TEXT_HELP": "Texte du bouton", "EXAMPLE_BUTTON_BG_COLOR": "Couleur du fond", - "EXAMPLE_BUTTON_BG_COLOR_HELP": "Exemple: #fbc14c, black, lightgrey, rgb(180,180,180)", + "EXAMPLE_BUTTON_BG_COLOR_HELP": "Exemple : #fbc14c, black, lightgrey, rgb(180,180,180)", "EXAMPLE_BUTTON_FONT_COLOR": "Couleur du texte", - "EXAMPLE_BUTTON_FONT_COLOR_HELP": "Exemple: black, orange, rgb(180,180,180)", + "EXAMPLE_BUTTON_FONT_COLOR_HELP": "Exemple : black, orange, rgb(180,180,180)", "EXAMPLE_BUTTON_TEXT_ICON": "Icône", "EXAMPLE_BUTTON_TEXT_WIDTH": "Largeur", - "EXAMPLE_BUTTON_TEXT_WIDTH_HELP": "Exemple: 200px, 50%", + "EXAMPLE_BUTTON_TEXT_WIDTH_HELP": "Exemple : 200px, 50%", "EXAMPLE_BUTTON_ICON_NONE": "Aucune", "EXAMPLE_BUTTON_ICON_DUNITER": "Logo Duniter", "EXAMPLE_BUTTON_ICON_CESIUM": "Logo Cesium", diff --git a/assets/www/i18n/locale-it-IT.json b/assets/www/i18n/locale-it-IT.json new file mode 100644 index 0000000000000000000000000000000000000000..4d3f3407d0b4b475b004a7a50c58d6c2ddef8ff7 --- /dev/null +++ b/assets/www/i18n/locale-it-IT.json @@ -0,0 +1,906 @@ +{ + "COMMON": { + "APP_NAME": "Cesium", + "APP_VERSION": "v{{version}}", + "APP_BUILD": "build {{build}}", + "PUBKEY": "Chiave privata", + "MEMBER": "Membro", + "BLOCK" : "Blocco", + "BTN_OK": "OK", + "BTN_YES": "Si", + "BTN_NO": "No", + "BTN_SEND": "Inviare", + "BTN_SEND_MONEY": "Trasferire soldi", + "BTN_SEND_MONEY_SHORT": "Trasferire", + "BTN_SAVE": "Salvare", + "BTN_YES_SAVE": "Si, salvare", + "BTN_YES_CONTINUE": "Si, continuare", + "BTN_SHOW": "Mostrare", + "BTN_SHOW_PUBKEY": "Mostrare chiave pubblica", + "BTN_RELATIVE_UNIT": "Mostra importi in DU?", + "BTN_BACK": "Indietro", + "BTN_NEXT": "Avanti", + "BTN_CANCEL": "Cancellare", + "BTN_CLOSE": "Chiudere", + "BTN_LATER": "Più tardi", + "BTN_LOGIN": "Accedi", + "BTN_LOGOUT": "Log out", + "BTN_ADD_ACCOUNT": "Nuovo conto", + "BTN_SHARE": "Condividere", + "BTN_EDIT": "Modificare", + "BTN_DELETE": "Eliminare", + "BTN_ADD": "Aggiungere", + "BTN_SEARCH": "Cercare", + "BTN_REFRESH": "Aggiornare", + "BTN_RETRY": "Riprovare", + "BTN_START": "Iniziare", + "BTN_CONTINUE": "Continuare", + "BTN_CREATE": "Creare", + "BTN_UNDERSTOOD": "Ho capito", + "BTN_OPTIONS": "Opzioni", + "BTN_HELP_TOUR": "Mostrami le funzionalità ", + "BTN_HELP_TOUR_SCREEN": "Scoprire questo schermo", + "BTN_DOWNLOAD": "Scaricare", + "BTN_DOWNLOAD_ACCOUNT_STATEMENT": "Scaricare estratto conto", + "BTN_MODIFY": "Modificare", + "CHOOSE_FILE": "Trascini un file <br/>o cliccare per selezionare", + "DAYS": "giorni", + "NO_ACCOUNT_QUESTION": "Non sei ancora membro? Registrati subito!", + "SEARCH_NO_RESULT": "Nessun risultato trovato", + "LOADING": "Caricando...", + "SEARCHING": "Cercando...", + "FROM": "Da", + "TO": "A", + "COPY": "Copiare", + "LANGUAGE": "Lingua", + "UNIVERSAL_DIVIDEND": "Dividendo universale", + "UD": "UD", + "DATE_PATTERN": "DD/MM/YYYY HH:mm", + "DATE_FILE_PATTERN": "YYYY-MM-DD", + "DATE_SHORT_PATTERN": "DD/MM/YY", + "DATE_MONTH_YEAR_PATTERN": "MM/YYYY", + "EMPTY_PARENTHESIS": "(empty)", + "UID": "Pseudonimo", + "ENABLE": "Attivato", + "DISABLE": "Disattivato", + "RESULTS_LIST": "Risultati:", + "RESULTS_COUNT": "{{count}} risultati", + "EXECUTION_TIME": "eeseguit in {{duration|formatDurationMs}}", + "SHOW_VALUES": "Mostrare valori in modo trasparente?", + "POPOVER_ACTIONS_TITLE": "Opzioni", + "POPOVER_FILTER_TITLE": "Filtri", + "SHOW_MORE": "Mostrare di più", + "SHOW_MORE_COUNT": "(limite attuale di {{limit}})", + "POPOVER_SHARE": { + "TITLE": "Condividere", + "SHARE_ON_TWITTER": "Condividere su Twitter", + "SHARE_ON_FACEBOOK": "Condividere su Facebook", + "SHARE_ON_DIASPORA": "Condividere su Diaspora*", + "SHARE_ON_GOOGLEPLUS":"Condividere su Google+" + }, + "FILE": { + "DATE" : "Data:", + "TYPE" : "Tipo:", + "SIZE": "Dimensioni del file:", + "VALIDATING": "Validazione in corso..." + } + }, + "SYSTEM": { + "PICTURE_CHOOSE_TYPE": "Scegliere un file:", + "BTN_PICTURE_GALLERY": "Galleria", + "BTN_PICTURE_CAMERA": "<b>Camera</b>" + }, + "MENU": { + "HOME": "Home", + "WOT": "Annuario", + "CURRENCY": "Moneta", + "ACCOUNT": "Mio conto", + "WALLETS": "I miei portafogli", + "TRANSFER": "Trasferire", + "SCAN": "Scansionare", + "SETTINGS": "Impostazioni", + "NETWORK": "Rete", + "TRANSACTIONS": "Miei pagamenti" + }, + "ABOUT": { + "TITLE": "A proposito", + "LICENSE": "<b>Free/libre software</b> (License GNU AGPLv3).", + "CODE": "Codice sorgente:", + "DEVELOPERS": "Sviluppatori:", + "FORUM": "Forum:", + "DEV_WARNING": "Attenzione!", + "DEV_WARNING_MESSAGE": "Questa app è ancora in sviluppo attivo.<br/>Facci sapere se trovi dei bugs!", + "DEV_WARNING_MESSAGE_SHORT": "Questa app è tutt'ora instabile (in sviluppo)", + "REPORT_ISSUE": "Segnalare un bug" + }, + "HOME": { + "TITLE": "Cesium", + "WELCOME": "Benvenuti nell'{{'COMMON.APP_NAME'|translate}} App!", + "MESSAGE": "Scambiate in moneta libera. {{currency|abbreviate}}!", + "BTN_CURRENCY": "Esplorare la moneta", + "BTN_ABOUT": "a proposito", + "BTN_HELP": "Aiuto", + "REPORT_ISSUE": "Segnalare un bug", + "NOT_YOUR_ACCOUNT_QUESTION" : "Non sei proprietario del conto <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b>?", + "BTN_CHANGE_ACCOUNT": "Disconettere questo conto", + "CONNECTION_ERROR": "Peer <b>{{server}}</b> irraggiungibile o indirizzo invalido. <br/><br/> Verifica tua connessione or cambia nodo. <a class=\"positive\" ng-click=\"doQuickFix('settings')\">nell impostazioni. </a>." + }, + "SETTINGS": { + "TITLE": "Impostazioni", + "NETWORK_SETTINGS": "Rete", + "PEER": "Indirizzo peer Duniter", + "PEER_CHANGED_TEMPORARY": "Indirizzo usato per un tempo determinato", + "USE_LOCAL_STORAGE": "Abilitare local storage", + "USE_LOCAL_STORAGE_HELP": "Permette di salvare tue impostazioni", + "ENABLE_HELPTIP": "Abilitare consigli dinamici", + "ENABLE_UI_EFFECTS": "Abilitare effetti visivi", + "HISTORY_SETTINGS": "Mio conto", + "DISPLAY_UD_HISTORY": "Mostrare dividendi prodotti?", + "AUTHENTICATION_SETTINGS": "Autenticazione", + "KEEP_AUTH": "Scadenza dell'autenticazione", + "KEEP_AUTH_SHORT": "Scadenza", + "KEEP_AUTH_HELP": "Definire quando l'autenticazione verrà eliminata dalla memoria.", + "KEEP_AUTH_OPTION": { + "NEVER": "Dopo ogni operazione", + "SECONDS": "Dopo {{value}}s d'inattività ", + "MINUTE": "Dopo{{value}}min d'inattività ", + "MINUTES": "Dopo {{value}}min d'inattività ", + "HOUR": "Dopo {{value}}h d'inattività ", + "ALWAYS": "Alla fine della sessione" + }, + "REMEMBER_ME": "Ricordarsi di me?", + "REMEMBER_ME_HELP": "Rimanere identificato/a da una sessione all'altra, conservando la chiave localmente.", + "PLUGINS_SETTINGS": "Estensioni", + "BTN_RESET": "Ripristini valori predefiniti", + "EXPERT_MODE": "Abilitare modlità eseperto", + "EXPERT_MODE_HELP": "Permette di vedere più dettagli", + "POPUP_PEER": { + "TITLE" : "Peer Duniter", + "HOST" : "Indirizzo", + "HOST_HELP": "Indirizzo: server:port", + "USE_SSL" : "Securizzato?", + "USE_SSL_HELP" : "(SSL Encryption)", + "BTN_SHOW_LIST" : "Lista dei peers" + } + }, + "BLOCKCHAIN": { + "HASH": "Hash: {{hash}}", + "VIEW": { + "HEADER_TITLE": "Blocco #{{number}}-{{hash|formatHash}}", + "TITLE_CURRENT": "Blocco attuale", + "TITLE": "Blocco #{{number|formatInteger}}", + "COMPUTED_BY": "Calcolato da", + "SHOW_RAW": "Mostrare dati grezzi", + "TECHNICAL_DIVIDER": "Informazioni tecniche", + "VERSION": "Versione di formatto", + "HASH": "Hash calcolato", + "UNIVERSAL_DIVIDEND_HELP": "Moneta co-prodotta da ciasciun dei {{membersCount}} membri", + "EMPTY": "Nessun dati in questo blocco", + "POW_MIN": "Difficoltà minimale", + "POW_MIN_HELP": "Difficoltà imposta nel calcolo del hash", + "DATA_DIVIDER": "Dati", + "IDENTITIES_COUNT": "Nuove identità ", + "JOINERS_COUNT": "Nuovi membri", + "ACTIVES_COUNT": "Rinnovi", + "ACTIVES_COUNT_HELP": "Membri che hanno rinnovato la loro presenza nella rete", + "LEAVERS_COUNT": "", + "LEAVERS_COUNT_HELP": "Membri che si sono fatti escludere dalla rete", + "EXCLUDED_COUNT": "Membri esclusi", + "EXCLUDED_COUNT_HELP": "Vecchi membri, esclusi per certificazione non rinnovata o soglia di certificazioni non raggiunta.", + "REVOKED_COUNT": "Identità revocate", + "REVOKED_COUNT_HELP": "Può essere che questi conti non siano più attivi", + "TX_COUNT": "Transazioni", + "CERT_COUNT": "Certificazioni", + "TX_TO_HIMSELF": "Cambio", + "TX_OUTPUT_UNLOCK_CONDITIONS": "Sbloccare condizioni", + "TX_OUTPUT_OPERATOR": { + "AND": "e", + "OR": "o" + }, + "TX_OUTPUT_FUNCTION": { + "SIG": "<b>Firma</b> della chive pubblica", + "XHX": "<b>Password</b>, incluso SHA256 =", + "CSV": "Bloccato per", + "CLTV": "Bloccato fino a" + } + }, + "LOOKUP": { + "TITLE": "Blocchi", + "NO_BLOCK": "Nessun blocco", + "LAST_BLOCKS": "Ultimi blocchi:", + "BTN_COMPACT": "Compact" + } + }, + "CURRENCY": { + "VIEW": { + "TITLE": "Moneta", + "TAB_CURRENCY": "Moneta", + "TAB_WOT": "Web of trust", + "TAB_NETWORK": "Rete", + "TAB_BLOCKS": "Blocchi", + "CURRENCY_SHORT_DESCRIPTION": "{{currency|capitalize}} è <b>una moneta libera</b>, {{firstBlockTime | formatFromNow}}. La rete comprende <b>{{N}} membri </b>, che produccono e ricevono un <a ng-click=\"showHelpModal('ud')\">Dividendo Universale</a> (DU), ogni {{dt | formatPeriod}}.", + "NETWORK_RULES_DIVIDER": "Regole della rete", + "CURRENCY_NAME": "Nome della moneta", + "MEMBERS": "Numero di membri", + "MEMBERS_VARIATION": "Variazione da {{duration|formatDuration}} (dall' ultimo UD)", + "MONEY_DIVIDER": "Moneta", + "MASS": "Massa monetaria", + "SHARE": "Quantità a testa", + "UD": "Dividendo universale", + "C_ACTUAL": "Crescita attuale", + "MEDIAN_TIME": "Current blockchain time", + "POW_MIN": "Difficoltà commune", + "MONEY_RULES_DIVIDER": "Regole della moneta", + "C_RULE": "Obbietivo teorico di crescità ", + "UD_RULE": "Dividendo universale (formula)", + "DT_REEVAL": "Periodo tra due re-evaluazioni del UD", + "REEVAL_SYMBOL": "reeval", + "DT_REEVAL_VALUE": "Ogni <b>{{dtReeval|formatDuration}}</b> ({{dtReeval/86400}} {{'COMMON.DAYS'|translate}})", + "UD_REEVAL_TIME0": "Data della prima re-evaluzione del UD", + "SIG_QTY_RULE": "Numero di certificazioni requisiti per diventare membro", + "SIG_STOCK": "Numero massimo di certificazioni inviate da un membro", + "SIG_PERIOD": "Tempo minimo tra 2 certificazioni inviate da un unico membro.", + "SIG_WINDOW": "Periodo massimo prima che una certificazione venga studiata", + "SIG_VALIDITY": "Durata di vita di una certificazione che è state presa in conto", + "MS_WINDOW": "Periodo massimo prima che una certificazione pendente sia validata", + "MS_VALIDITY": "Durata di vita di un'adesione che è state presa in conto", + "STEP_MAX": "Distanza massima tra un nuovo membro e ogni membro referente.", + "WOT_RULES_DIVIDER": "Regole della Web of Trust", + "SENTRIES": "Numero di certificazioni (date <b>e</b> ricevute) per diventare membro referente ", + "SENTRIES_FORMULA": "Numero di certificazioni necessarie per diventare membro (formula)", + "XPERCENT":"Percentaggio minimino di membri referenti per rispettare la regola di distanza tra i membri", + "AVG_GEN_TIME": "Tempo medio tra due blocchi", + "CURRENT": "attuale", + "MATH_CEILING": "CEILING", + "DISPLAY_ALL_RULES": "Mostrare tutte le regole?", + "BTN_SHOW_LICENSE": "Mostrare licenza", + "WOT_DIVIDER": "Web of trust" + }, + "LICENSE": { + "TITLE": "Licensa attuale", + "BTN_DOWNLOAD": "Scaricare il file", + "NO_LICENSE_FILE": "File di licenza non trovato ." + } + }, + "NETWORK": { + "VIEW": { + "MEDIAN_TIME": "Blockchain time", + "LOADING_PEERS": "Caricando peers...", + "NODE_ADDRESS": "Indirizzo del peer", + "SOFTWARE": "Software", + "WARN_PRE_RELEASE": "Pre-versione (ultima versione stabile: <b>{{version}}</b>)", + "WARN_NEW_RELEASE": "Versione <b>{{version}}</b> disponibile", + "WS2PID": "Identificativo :", + "PRIVATE_ACCESS": "Accesso privato", + "POW_PREFIX": "Prefisso Prova di Lavoro :", + "ENDPOINTS": { + "BMAS": "Endpoint sicuro (SSL)", + "BMATOR": "Interfaccia rete TOR", + "WS2P": "Interfaccia WS2P", + "ES_USER_API": "Cesium+ data node" + } + }, + "INFO": { + "ONLY_SSL_PEERS": "I nodi non-SSL hanno un display semplificato perche Cesium funziona in modalità HTTPS." + } + }, + "PEER": { + "PEERS": "Peers-Nodi", + "SIGNED_ON_BLOCK": "Firmato nel blocco", + "MIRROR": "Specchio", + "MIRRORS": "Specchio", + "MIRROR_PEERS": "Peers specchio", + "PEER_LIST" : "Lista dei peers", + "MEMBERS" : "Membri", + "MEMBER_PEERS" : "Peers membri", + "ALL_PEERS" : "Tutti i peers", + "DIFFICULTY" : "Difficoltà ", + "API" : "API", + "CURRENT_BLOCK" : "Blocco #", + "POPOVER_FILTER_TITLE": "Filtro", + "OFFLINE": "Sconessi", + "OFFLINE_PEERS": "Peers sconessi", + "BTN_SHOW_PEER": "Mostrare peer", + "VIEW": { + "TITLE": "Peer", + "OWNER": "Proprietà di ", + "SHOW_RAW_PEERING": "Vedere il documento di peering", + "SHOW_RAW_CURRENT_BLOCK": "Vedere l'utimo blocco (formatto grezzo)", + "LAST_BLOCKS": "Ultimi blocchi", + "KNOWN_PEERS": "Peers conosciuti :", + "GENERAL_DIVIDER": "Informazioni generali", + "ERROR": { + "LOADING_TOR_NODE_ERROR": "Impossibile ottenere i dati del peer, periodo di attesa scaduto.", + "LOADING_NODE_ERROR": "Impossibile ottenere i dati del peer" + } + } + }, + "WOT": { + "SEARCH_HELP": "Cercare (membro o chiave pubblica)", + "SEARCH_INIT_PHASE_WARNING": "La ricerca per le certificazioni pendenti <b>può essere lunga</b> durante la fase di pre-certificazione. La preghiamo di attendere...", + "REGISTERED_SINCE": "Certificato/a dal", + "REGISTERED_SINCE_BLOCK": "Certificato/a dal blocco #", + "NO_CERTIFICATION": "Nessuna certificazione valida", + "NO_GIVEN_CERTIFICATION": "Nessuna certificazione data", + "NOT_MEMBER_PARENTHESIS": "(non-membro)", + "IDENTITY_REVOKED_PARENTHESIS": "(identità revocata)", + "MEMBER_PENDING_REVOCATION_PARENTHESIS": "(Cancellazione dell'identità pendente)", + "EXPIRE_IN": "Scade", + "NOT_WRITTEN_EXPIRE_IN": "Scadenza <br/> ", + "EXPIRED": "Scaduto", + "PSEUDO": "Pseudonimo", + "SIGNED_ON_BLOCK": "Emessa nel blocco #{{block}}", + "WRITTEN_ON_BLOCK": "Scritta nel blocco #{{block}}", + "GENERAL_DIVIDER": "Informazioni generali", + "NOT_MEMBER_ACCOUNT": "Conto non-membro", + "NOT_MEMBER_ACCOUNT_HELP": "Questo è un semplice portafoglio osservatore, senza richiesta di certificazione emessa.", + "TECHNICAL_DIVIDER": "Dati tecnici", + "BTN_CERTIFY": "Certificare", + "BTN_YES_CERTIFY": "Si, certificare", + "BTN_SELECT_AND_CERTIFY": "Nuova certificazione", + "ACCOUNT_OPERATIONS": "Operazioni sul conto", + "VIEW": { + "POPOVER_SHARE_TITLE": "Identità {{title}}" + }, + "LOOKUP": { + "TITLE": "Annuario", + "NEWCOMERS": "Nuovi membri:", + "NEWCOMERS_COUNT": "{{count}} membri", + "PENDING": "Registrazioni pendenti", + "PENDING_COUNT": "{{count}} inscrizioni pendenti", + "REGISTERED": "Registrato {{sigDate | formatFromNow}}", + "MEMBER_FROM": "Membro dal {{memberDate|medianFromNowShort}}", + "BTN_NEWCOMERS": "Ultimi membri", + "BTN_PENDING": "Registrazioni pendenti", + "SHOW_MORE": "Vedere di più", + "SHOW_MORE_COUNT": "(limite attuale di {{limit}})", + "NO_PENDING": "Nessuna certificazione pendente.", + "NO_NEWCOMERS": "Nessun membro." + }, + "CONTACTS": { + "TITLE": "Contatti" + }, + "MODAL": { + "TITLE": "Ricerca" + }, + "CERTIFICATIONS": { + "TITLE": "{{uid}} - Certificazioni", + "SUMMARY": "Certificazioni ricevute", + "LIST": "Dettagli delle certificazioni ricevute", + "PENDING_LIST": "Certificazioni pendenti", + "RECEIVED": "Certificazioni ricevute", + "RECEIVED_BY": "Certifications ricevute da {{uid}}", + "ERROR": "Certificazioni ricevute per errore", + "SENTRY_MEMBER": "Membro referente" + }, + "OPERATIONS": { + "TITLE": "{{uid}} - Operazioni" + }, + "GIVEN_CERTIFICATIONS": { + "TITLE": "{{uid}} - Certificazioni inviate", + "SUMMARY": "Certificazioni inviate", + "LIST": "Dettagli delle certificazioni inviate", + "PENDING_LIST": "Certificazioni ", + "SENT": "Certificazioni inviate", + "SENT_BY": "Certificazioni inviate da {{uid}}", + "ERROR": "Certificazioni inviate per errore" + } + }, + "LOGIN": { + "TITLE": "<i class=\"icon ion-log-in\"></i> Accedi", + "SCRYPT_FORM_HELP": "Accedi con tuoi dati <br> Ricordati di verificare che stai utilizzando la chiave del tuo conto.", + "PUBKEY_FORM_HELP": "Scrivi qui la tua chiave privata:", + "FILE_FORM_HELP": "Scegliere un portachiavi da utilizzare:", + "SCAN_FORM_HELP": "Scansiona il codice QR di un portafoglio.", + "SALT": "Identificativo segreto", + "SALT_HELP": "Identificativo segreto", + "SHOW_SALT": "Mostrare identificativo segreto?", + "PASSWORD": "Passsord", + "PASSWORD_HELP": "Password", + "PUBKEY_HELP": "Chiave pubblica, pseudonimo", + "NO_ACCOUNT_QUESTION": "Ancora non hai un conto?", + "HAVE_ACCOUNT_QUESTION": "Hai già un account?", + "CREATE_ACCOUNT": "Creare un conto", + "CREATE_FREE_ACCOUNT": "Crea un conto gratuito", + "FORGOTTEN_ID": "Non ricordi la password?", + "ASSOCIATED_PUBKEY": "Chiave pubblica:", + "BTN_METHODS": "Altri metodi", + "BTN_METHODS_DOTS": "Cambiare metodo...", + "METHOD_POPOVER_TITLE": "Metodi", + "MEMORIZE_AUTH_FILE": "Memorizzare questo portachiavi per la durata di questa sessione", + "SCRYPT_PARAMETERS": "Parametri (Scrypt) :", + "AUTO_LOGOUT": { + "TITLE": "Informazioni", + "MESSAGE": "<i class=\"ion-android-time\"></i> Sei stato <b>sconesso/ b> automaticamente, per un periodo di inattività prolongata", + "BTN_RELOGIN": "Accedi", + "IDLE_WARNING": "Sarai disconesso in... {{countdown}}" + }, + "METHOD": { + "SCRYPT_DEFAULT": "Salatura standard (imp. predefinita)", + "SCRYPT_ADVANCED": "Salatura avanzata", + "FILE": "File del portachiavi", + "PUBKEY": "Chiave pubblica soltanto", + "SCAN": "Scansiona un codice QR" + }, + "SCRYPT": { + "SIMPLE": "Salatura leggera", + "DEFAULT": "Salatura standard", + "SECURE": "Salatura sicura", + "HARDEST": "Salatura più sicura", + "EXTREME": "Salatura estrema", + "USER": "Salatura personalizzata", + "N": "N (Loop):", + "r": "r (RAM):", + "p": "p (CPU):" + }, + "FILE": { + "HELP": "Format del file atteso: <b>.dunikey</b> (type PubSec). Altri formati in sviluppo (EWIF, WIF)." + } + }, + "AUTH": { + "TITLE": "<i class=\"icon ion-locked\"></i> Autenticazione", + "BTN_AUTH": "Autenticarsi", + "GENERAL_HELP": "Autenticati :", + "EXPECTED_UID_HELP": "Effettua il login nell'account <i class=\"ion-person\"></i> {{uid}}:", + "EXPECTED_PUBKEY_HELP": "Si prega di autenticarsi sul portafoglio <i class=\"ion-key\"></i> {{pubkey|formatPubkey}}:", + "SCAN_FORM_HELP": "Scansiona il codice QR della <b>chiave privata</b> del portafoglio." + }, + "ACCOUNT": { + "TITLE": "Mio conto", + "BALANCE": "Saldo", + "LAST_TX": "Ultime transazioni", + "BALANCE_ACCOUNT": "Saldo del conto", + "NO_TX": "Nessuna transazione", + "SHOW_MORE_TX": "Mostrare di più", + "SHOW_ALL_TX": "Mostrare tutte", + "TX_FROM_DATE": "(limite attuale del {{fromTime|medianFromNowShort}})", + "PENDING_TX": "Transazioni pendenti", + "VALIDATING_TX": "Transazioni in corso di convalida", + "ERROR_TX": "Transaction non eseguite", + "ERROR_TX_SENT": "Transazioni inviate", + "PENDING_TX_RECEIVED": "Transazioni in attesa di recezione", + "EVENTS": "Eventi", + "WAITING_MEMBERSHIP": "Richiesta di certificazione inviata. In attesa di validazione.", + "WAITING_CERTIFICATIONS": "Hai bisogno di {{needCertificationCount}} certificazione(i) per diventare membro.", + "WILL_MISSING_CERTIFICATIONS": "Mancherai a breve <b>di certificazioni</b> (occorrono almeno {{willNeedCertificationCount}} altre certificazioni)", + "WILL_NEED_RENEW_MEMBERSHIP": "Tua certificazione <b>scaderà {{membershipExpiresIn|formatDurationTo}}</b>. Ricordati di <a ng-click=\"doQuickFix('renew')\">rinnovarla</a> prima.", + "NEED_RENEW_MEMBERSHIP": "You are no longer a member because your membership <b>has expired</b>. Remember to <a ng-click=\"doQuickFix('renew')\">renew your membership</a>.", + "NO_WAITING_MEMBERSHIP": "Nessuna domanda di adesione pendente. Se desideri <b>diventare membro</b>, ricordati di <a ng-click=\"doQuickFix('membership')\">inviare tua domanda di adesione</a>.", + "CERTIFICATION_COUNT": "Certificazioni ricevute", + "CERTIFICATION_COUNT_SHORT": "Certificazioni", + "SIG_STOCK": "Stock di certificazioni da inviare", + "BTN_RECEIVE_MONEY": "Ricevere", + "BTN_SELECT_ALTERNATIVES_IDENTITIES": "Usare un'altra identità ..", + "BTN_FIX_MEMBERSHIP": "Invia nuovamente di adesione...", + "BTN_MEMBERSHIP_RENEW": "Rinnovare adesione", + "BTN_MEMBERSHIP_RENEW_DOTS": "Rinnovare adesione ...", + "BTN_MEMBERSHIP_OUT_DOTS": "Revocare adesione...", + "BTN_SECURITY_DOTS": "Login e securità ...", + "BTN_SHOW_DETAILS": "Visualizzare dati tecnici", + "LOCKED_OUTPUTS_POPOVER": { + "TITLE": "Importo bloccata", + "DESCRIPTION": "Ecco le condizioni per sbloccare questo importo:", + "DESCRIPTION_MANY": "Questa transazione è fatta da diverse parti, di cui queste sono le condizioni di sblocco:", + "LOCKED_AMOUNT": "Condizioni per l'importo:" + }, + "NEW": { + "TITLE": "Registrazione", + "INTRO_WARNING_TIME": "Crearsi un conto su {{name|capitalize}} è molto semplice. E consigliato prendere il giusto tempo per farlo correttamente (per evitare di dimenticare passwords, pseudonimi etc.).", + "INTRO_WARNING_SECURITY": "Occorre verificare che il hardware che stai utilizzando (computer, tablet, cellulare) <b>è sicuro e affidabile</b>.", + "INTRO_WARNING_SECURITY_HELP": "Anti-virus aggiornato, firewall abilitato, session protteta da un password o codice PIN...", + "INTRO_HELP": "Cliccare <b> {{'COMMON.BTN_START'|translate}}</b> per avviare la creazione del conto. Ti accompagniamo passo alla volta.", + "REGISTRATION_NODE": "Tua iscrizione verrà salvata dal nodo peer Duniter <b>{{server}}</b>, è verrà poi condivisa nella rete della moneta.", + "REGISTRATION_NODE_HELP": "Se non ti fidi di questo peer, per favore cambialo <a ng-click=\"doQuickFix('settings')\">nelle impostazioni/a> di Cesium.", + "SELECT_ACCOUNT_TYPE": "Scegliere un tipo di conto:", + "MEMBER_ACCOUNT": "Conto membro", + "MEMBER_ACCOUNT_TITLE": "Creare un conto membro", + "MEMBER_ACCOUNT_HELP": "Se non sei ancora registrato come individuo (un conto a persona soltanto).", + "WALLET_ACCOUNT": "Semplice portafoglio", + "WALLET_ACCOUNT_TITLE": "Creare un portafoglio", + "WALLET_ACCOUNT_HELP": "Se rappresenti un'azienda, associazione, altra ente o hai necessita di un altro portafoglio. Nessun Dividendo Universale sarà prodotto da questo conto.", + "SALT_WARNING": "Scegliere un identificativo segreto.<br/>E necessario per ogni connessione a questo conto.<br/><br/><b>Accertati di ricordarlo!</b>.<br/>Se lo dimentichi non ti potrà aiutare nessuno!", + "PASSWORD_WARNING": "Scegliere una password.<br/>E necessario per ogni connessione a questo conto.<br/><br/><b>Accertati di ricordarla!</b>.<br/>Se la dimentichi non ti potrà aiutare nessuno!", + "PSEUDO_WARNING": "Segliere uno pseudonimo.<br/>Puo essere utile per chi ti cerca nella rete.<br/><br/>.L'utilizzo delle<b>virgole, spazi e accenti</b> è vietato.<br/><div class='hidden-xs'><br/>Esempio: <span class='gray'>JohnDalton, JackieChan, etc.</span>", + "PSEUDO": "Pseudonimo", + "PSEUDO_HELP": "joe123", + "SALT_CONFIRM": "Confermare", + "SALT_CONFIRM_HELP": "Confermare l'identificativo segreto", + "PASSWORD_CONFIRM": "Confermare", + "PASSWORD_CONFIRM_HELP": "Confermare la password", + "SLIDE_6_TITLE": "Conferma:", + "COMPUTING_PUBKEY": "Calcolando...", + "LAST_SLIDE_CONGRATULATION": "Hai riempito tutti i campi richiesti.<br/><b>Puoi inviare la richiesta di creazione del conto</b>.<br/><br/>Per tua informazione, la chiave pubblica qui sotto identifica il tuo futuro conto.<br/>Puo essere communicata a chi ti deve pagare per esempio.<br/>Quando tuo conto verrà approvato potrai trovare la chiave qui <b>{{'ACCOUNT.TITLE'|translate}}</b>.", + "CONFIRMATION_MEMBER_ACCOUNT": "<b class=\"assertive\">Warning:</b> tuo identificare segreto, tua password e tuo pseudonimo non si possono cambiare.<br/><b>Ricordali per sempre!</b><br/><b>Sei sicuro/a</b>di voler inviare questa richiesta di creazione di conto?", + "CONFIRMATION_WALLET_ACCOUNT": "<b class=\"assertive\">Warning:</b> tuo identificare segreto, tua password e tuo pseudonimo non si possono cambiare..<br/><b>Ricordali per sempre!</b><br/><b>Sei sicuro/a</b> di voler continuare?", + "CHECKING_PSEUDO": "Verificazione in corso...", + "PSEUDO_AVAILABLE": "Pseudonimo disponibile", + "PSEUDO_NOT_AVAILABLE": "Pseudonimo indisponibile", + "INFO_LICENSE": "TPer aderire alla moneta, ti chiediamo di leggere e accetare le condizioni della licenza.", + "BTN_ACCEPT": "Accetto", + "BTN_ACCEPT_LICENSE": "Accetto la licenza" + }, + "POPUP_REGISTER": { + "TITLE": "Pseudonimo", + "HELP": "Un pseudonimo è necessario per che gli altri ti possino trovare." + }, + "SELECT_IDENTITY_MODAL": { + "TITLE": "Selezionare una identità ", + "HELP": "Più <b>identità diverse</b> sono state inviate per la chiave pubblica <span class=\"gray\"><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</span>.<br/>Seleziona un dossier da usare :" + }, + "SELECT_WALLET_MODAL": { + "TITLE": "Selezione del portafoglio" + }, + "WALLET_LIST": { + "TITLE": "Portafoglio secondario", + "BTN_NEW": "Aggiungi un portfolio", + "NO_WALLET": "Nessun portafoglio secondario", + "BTN_DELETE": "Rimuovi un portafoglio secondario ...", + "BTN_RENAME": "Rinominare il portafoglio", + "EDIT_POPOVER": { + "TITLE": "Rinominare il portafoglio", + "HELP": "Compila il nuovo nome", + "NAME_HELP": "Nome del portafoglio" + } + }, + "SECURITY":{ + "ADD_QUESTION" : "Aggiungere domanda personalizzata", + "BTN_CLEAN" : "Svuotare", + "BTN_RESET" : "Reset", + "DOWNLOAD_REVOKE": "Salvare un file di revoca", + "DOWNLOAD_REVOKE_HELP" : "Avere une file di revoca è necessario in caso di smarrimento dei tuoi credenziali. Ti permette <b> di rimuovere tuo conto dalla Web Of Trust</b>, per farlo tornare ad essere un semplice portafoglio.", + "HELP_LEVEL": "Scegliere <strong> almeno{{nb}} domande </strong> :", + "LEVEL": "Livello di sicurezza", + "LOW_LEVEL": "Basso <span class=\"hidden-xs\">(minimo di 2 domande)</span>", + "MEDIUM_LEVEL": "Medio <span class=\"hidden-xs\">(minimo di 4 domande)</span>", + "QUESTION_1": "Qual'era il nome del tuo miglior amico quando eri adolescente ?", + "QUESTION_2": "Qual'era il nome del tuo primo animale domestico?", + "QUESTION_3": "Qual'è il primo piatto che imparasti a cucinare?", + "QUESTION_4": "Qual'è il primo film che hai visto al cinema?", + "QUESTION_5": "Qual'era la destinazione del tuo primo volo?", + "QUESTION_6": "Qual'era il nome del tuo professore preferito in scuola ?", + "QUESTION_7": "Quale sarebbe il tuo lavoro preferito?", + "QUESTION_8": "Qual'è il tuo libro per bimbi preferito?", + "QUESTION_9": "Qual'era il marchio della tua prima macchina?", + "QUESTION_10": "Qual'era il tuo nomignolo da ragazzino/a ?", + "QUESTION_11": "Qual'era il tuo personaggio di film o attore preferito quand eri studente?", + "QUESTION_12": "Qual'era il tuo musicista/cantante/grupo preferito quand eri studente ?", + "QUESTION_13": "In che città si sono conosciuti tuoi genitori ?", + "QUESTION_14": "Qual'era il nome del tuo primo capo ?", + "QUESTION_15": "Qual'è il nome della strada dove sei cresciuto/a ?", + "QUESTION_16": "Qual'è il nome della tua spiaggia preferita ?", + "QUESTION_17": "Qual'è il primo album che ti sei comprato ?", + "QUESTION_18": "Qual'è il nome della squadra di sport preferita ?", + "QUESTION_19": "Cosa faceva tuo nonno ?", + "RECOVER_ID": "Ricuperare mia password...", + "RECOVER_ID_HELP": "Se hai un<b<file di backup dei tuoi credenziali</b>, li puoi trovare rispondendo correttamente alle tue domande personalizzate.", + "REVOCATION_WITH_FILE" : "Revocare il mio conto membro...", + "REVOCATION_WITH_FILE_DESCRIPTION": "Se pensi di aver perso <b>definitivamente tuoi credenziali</b> di conto membro (o che la sicurezza del tuo conto è compromessa), puoi usare <b>il file di revoca</b> del conto <b>per forzare la sua uscita permanente dalla Tela di Fiducia</b>.", + "REVOCATION_WITH_FILE_HELP": "Se hai <b>definitivamente perso tuoi credenziali (o se la sicurezza del tuo conto è compromessa), puoi usare <b>il file di revoca</b> del conto <b>per uscire dalla Web Of Trust</b>.", + "REVOCATION_WALLET": "Revocare questo conto subito", + "REVOCATION_WALLET_HELP": "Richiedere la cancellazione dell'identità <b>revocherà la tua adesione alla tua rete</ b> (con certezza per il pseudonimo e la chiave pubblica associata). Il conto non potrà più produrre il Dividendo Universale.<br/>Nonostante ciò, puoi ancora usare il conto come semplice portafoglio.", + "REVOCATION_FILENAME": "revocation-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "SAVE_ID": "Salvare miei credenziali...", + "SAVE_ID_HELP": "Creare un file di backup, per <b>ricuperare vostra password</b> (e l'identificativo segreto) <b> in caso di smarrimento</b>. Il file è <b>sicuro</ b> (cryptato) utilizzando le domande personalizzate.", + "STRONG_LEVEL": "Alto <span class=\"hidden-xs \">(minimo di 6 domande)</span>", + "TITLE": "Conto e sicurezza" + }, + "FILE_NAME": "{{currency}} - Account statement {{pubkey|formatPubkey}} to {{currentTime|formatDateForFile}}.csv", + "HEADERS": { + "TIME": "Date", + "AMOUNT": "Amount", + "COMMENT": "Comment" + } + }, + "TRANSFER": { + "TITLE": "Bonifico", + "SUB_TITLE": "Fare un bonifico", + "FROM": "Da", + "TO": "A", + "AMOUNT": "Importo", + "AMOUNT_HELP": "Importo", + "COMMENT": "Commenti", + "COMMENT_HELP": "Commenti", + "BTN_SEND": "Inviare", + "BTN_ADD_COMMENT": "Scrivere un comento ?", + "WARN_COMMENT_IS_PUBLIC": "Ti avvertiamo <b>che i commenti sono pubblici</b> (non cifrati).", + "MODAL": { + "TITLE": "Bonifico" + } + }, + "ERROR": { + "POPUP_TITLE": "Errore", + "UNKNOWN_ERROR": "Errore", + "CRYPTO_UNKNOWN_ERROR": "Suo navigatore non sembra compatibile con le funzionalità di cryptografia.", + "EQUALS_TO_PSEUDO": "Deve essere diverso dal pseudonimo", + "EQUALS_TO_SALT": "Deve essere diverso dal identificativo segreto", + "FIELD_REQUIRED": "Campo obbligatorio.", + "FIELD_TOO_SHORT": "Valore troppo corto.", + "FIELD_TOO_SHORT_WITH_LENGTH": "Valore troppo corto ({{minLength}} caratteri min)", + "FIELD_TOO_LONG": "Valore troppo lungo", + "FIELD_TOO_LONG_WITH_LENGTH": "Valore troppo lungo ({{maxLength}} caractteri max)", + "FIELD_MIN": "Valore minimo : {{min}}", + "FIELD_MAX": "Valore massimo : {{max}}", + "FIELD_ACCENT": "Virgole e caratteri accentati vietati", + "FIELD_NOT_NUMBER": "Valore numerico atteso", + "FIELD_NOT_INT": "Valore intero atteso", + "FIELD_NOT_EMAIL": "Indirizzo mail non valido", + "PASSWORD_NOT_CONFIRMED": "Non corrisponde alla password.", + "SALT_NOT_CONFIRMED": "Non corrisponde al identificativo segreto.", + "SEND_IDENTITY_FAILED": "Iscrizione fallita.", + "SEND_CERTIFICATION_FAILED": "Certificazione fallita.", + "NEED_MEMBER_ACCOUNT_TO_CERTIFY": "Non puoi inviare certificazioni perche tuo conto <b>non è ancora un conto membro</b>.", + "NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF": "Non puoi inviare certificazioni adesso perche <b>non sei ancora membro</b>.<br/><br/>Devi ancora entrare nella WOT.", + "NOT_MEMBER_FOR_CERTIFICATION": "Tuo conto non è ancora un conto membro.", + "IDENTITY_TO_CERTIFY_HAS_NO_SELF": "Impossibile certificare questo conto. Nessuna richiesta di certificazione trovata o bisogna rinnovarla.", + "LOGIN_FAILED": "Errore di login.", + "LOAD_IDENTITY_FAILED": "Impossibile caricare la tua identità .", + "LOAD_REQUIREMENTS_FAILED": "Impossibile caricare i prerequisiti dell'identità .", + "SEND_MEMBERSHIP_IN_FAILED": "Ingresso nella WOT fallito.", + "SEND_MEMBERSHIP_OUT_FAILED": "Errore nel invio della revocazione.", + "REFRESH_WALLET_DATA": "Impossibile aggiornare il portafoglio.", + "GET_CURRENCY_PARAMETER": "Impossibile ricuperare i parametri della moneta.", + "GET_CURRENCY_FAILED": "Impossibile caricare la moneta. Riprovare più tardi.", + "SEND_TX_FAILED": "Impossibile eseguire la transazione.", + "ALL_SOURCES_USED": "Per favore aspetta il calcolo del prossimo blocco (Tutte le tue fonti di moneta sono state utilizzate).", + "NOT_ENOUGH_SOURCES": "Non hai abbastanza cambio per inviare questo importo in una sola transazione.<br/>Importo massimo: {{amount}} {{unit}}<sub>{{subUnit}}</sub>.", + "ACCOUNT_CREATION_FAILED": "Errore nella creazione del tuo conto membro.", + "RESTORE_WALLET_DATA_ERROR": "Errore nel aggiornamento delle impostazioni definite in local storage.", + "LOAD_WALLET_DATA_ERROR": "Errore nel caricamento dei dati del portafoglio.", + "COPY_CLIPBOARD_FAILED": "Impossibile copiare al clipboard", + "TAKE_PICTURE_FAILED": "Impossibile ricuperare foto.", + "SCAN_FAILED": "Impossibile scansionare il codice QR.", + "SCAN_UNKNOWN_FORMAT": "Codice non riconosciuto.", + "WOT_LOOKUP_FAILED": "Ricerca fallita.", + "LOAD_PEER_DATA_FAILED": "Peer Duniter non accessibile. Riprovare più tardi.", + "NEED_LOGIN_FIRST": "Accedi al tuo conto prima.", + "AMOUNT_REQUIRED": "Importo necessario.", + "AMOUNT_NEGATIVE": "Importo negativo non consentito.", + "NOT_ENOUGH_CREDIT": "Saldo insufficiente", + "INVALID_NODE_SUMMARY": "Impossibile comunicare col peer o indirizzo non valido", + "INVALID_USER_ID": "Il campo del 'pseudonimo' non deve avere spazi vuoti o caratteri speciali.", + "INVALID_COMMENT": "Il formato del campo 'reference' è errato.", + "INVALID_PUBKEY": "If formato della chiave pubblica è errato.", + "IDENTITY_REVOKED": "Questa identità <b>è stata revocata</b>. Non puo più diventare membro.", + "IDENTITY_REVOKED_WITH_TIME": "Questa identità <b>è stata revocata {{revocationTime|medianFromNow}}</b> ({{revocationTime|medianDate}}). Non puo più diventare membro.", + "IDENTITY_PENDING_REVOCATION": "L'<b>annulamento di questa identità </b> è stata richiesta ed è in corso di evaluazione. Capacità ad inviare certificazioni disabilitata", + "IDENTITY_INVALID_BLOCK_HASH": "Questa richiesta di certificazione non è più valida (perche si riferisce ad un blocco che è stato eliminato dai peers): la persona deve rinnovare la sua domanda di certificazione <b>prima</b> di essere certificata.", + "IDENTITY_EXPIRED": "Questa identità è scaduta: la persona deve fare una nuova domanda di certificazione <b>prima di</b> essere certificata.", + "IDENTITY_SANDBOX_FULL": "Il nodo Duniter utilizzato da Cesium non puo ricevere altre domande di certificazione per ora, la lista d'attesa è piena.<br/><br/>Riprova più tardi o scegli un'altro peer Duniter (nelle <b>Impostazioni</b>).", + "IDENTITY_NOT_FOUND": "Identità non trovata", + "IDENTITY_TX_FAILED": "Impossibile caricare le operazioni", + "WOT_PENDING_INVALID_BLOCK_HASH": "Adesione non valida.", + "WALLET_INVALID_BLOCK_HASH": "Tua domanda di certificazione non è più valida (perche si riferisce ad un blocco che è stato eliminato dai peers).<br/>Devi <a ng-click=\"doQuickFix('renew')\">rinnvoare la tua richiesta di adesione alla WOT</a> per risolvere il problema.", + "WALLET_IDENTITY_EXPIRED": "La pubblicazione della tua identità <b>è scaduta</b>.<br/>Devi <a ng-click=\"doQuickFix('fixIdentity')\">ripubblicare la tua identità </a> per risolvere il problema.", + "WALLET_REVOKED": "La tua identità è stata <b>revocata</b>: ne tuo pseudonimo ne tua chiave pubblica sarano utilizzati in futuro.", + "WALLET_HAS_NO_SELF": "La tua identità deve prima essere stata pubblicata e non essere ancora scaduta.", + "AUTH_REQUIRED": "Autenticazione necessaria.", + "AUTH_INVALID_PUBKEY": "La chiave pubblica non corrisponde al conto conesso.", + "AUTH_INVALID_SCRYPT": "Password o nome di utente non valido.", + "AUTH_INVALID_FILE": "File di portachiavi non valido.", + "AUTH_FILE_ERROR": "Impossibile aprire il file di portachiavi", + "IDENTITY_ALREADY_CERTIFY": "Hai <b>già certificato</b> questa identità .<br/><br/>Tuo certificato è ancora valido (scade {{expiresIn|formatDuration}}).", + "IDENTITY_ALREADY_CERTIFY_PENDING": "Hai <b>già certificato</b> questa identità .<br/><br/>Tua certificazione è ancora pendente (Scadenza del periodo di treatment {{expiresIn|formatDuration}}).", + "UNABLE_TO_CERTIFY_TITLE": "Impossibile certificare", + "LOAD_NEWCOMERS_FAILED": "Impossibile caricare i nuovi membri.", + "LOAD_PENDING_FAILED": "Impossibile caricare le certificazioni pendenti.", + "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "Devi <b>essere membro</b> per poter fare questo.", + "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "Devi aver <b>publiccato tua identità </b> per poter fare questo.", + "GET_BLOCK_FAILED": "Impossibile caricare il blocco", + "INVALID_BLOCK_HASH": "Blocco non trovato (hash errato)", + "DOWNLOAD_REVOCATION_FAILED": "Errore avvenuto nel download del file di cancellazione d'identità .", + "REVOCATION_FAILED": "Errore avvenuto durante la richiesta di cancellazione dell'identità .", + "SALT_OR_PASSWORD_NOT_CONFIRMED": "identificativo segreto o password sbagliati", + "RECOVER_ID_FAILED": "Impossibile ricuperare la password", + "LOAD_FILE_FAILED" : "Impossibile caricare il file", + "NOT_VALID_REVOCATION_FILE": "File di cancellazione dell'identità errato (formato di file incorreto)", + "NOT_VALID_SAVE_ID_FILE": "File di backup dei credenziali errato (formato di file incorreto)", + "NOT_VALID_KEY_FILE": "File di portachiavi non valido (formato non riconosciuto)", + "EXISTING_ACCOUNT": "Tuoi credenziali corrispondono a quelli di un conto già esistente,di cui <a ng-click=\"showHelpModal('pubkey')\">la chiave pubblica</a> è:", + "EXISTING_ACCOUNT_REQUEST": "Per favore cambi tuoi credenziali in modo che corrispondino ad un conto non utilizzato.", + "GET_LICENSE_FILE_FAILED": "Impossibile caricare il file della licenza", + "CHECK_NETWORK_CONNECTION": "Nessun peer sembra disponibile.<br/><br/>Per favore <b>verifica la tua connessione Internet</b>.", + "ISSUE_524_TX_FAILED": "Bonifico .<br/><br/>Un message a été envoyé aux développeurs pour faciliter la résolution du problème. <b>Merci de votre aide</b>." + }, + "INFO": { + "POPUP_TITLE": "Informazioni", + "CERTIFICATION_DONE": "Identità firmata con successo", + "NOT_ENOUGH_CREDIT": "Saldo insufficiente", + "TRANSFER_SENT": "Transazione inviata con successo", + "COPY_TO_CLIPBOARD_DONE": "Copiato con successo", + "MEMBERSHIP_OUT_SENT": "Revoca dell'identità inviata", + "NOT_NEED_MEMBERSHIP": "Già un membro.", + "IDENTITY_WILL_MISSING_CERTIFICATIONS": "Questa identità mancherà a breve di certificazioni (almeno {{willNeedCertificationCount}}).", + "REVOCATION_SENT": "Revoca dell'identità inviata", + "REVOCATION_SENT_WAITING_PROCESS": "Cancellazione dell'identità <b>inviata con successo</b>. In attesa di validazione.", + "FEATURES_NOT_IMPLEMENTED": "Questa funzionalità non è ancora disponibile.<br/><br/>Vuoi contribuire per velocizzarne la disponibilità ? ;)", + "EMPTY_TX_HISTORY": "Nessuna operazione da esportare" + }, + "CONFIRM": { + "POPUP_TITLE": "<b>Conferma</b>", + "POPUP_WARNING_TITLE": "<b>Avviso</b>", + "POPUP_SECURITY_WARNING_TITLE": "<i class=\"icon ion-alert-circled\"></i> <b>Avvertimento di sicurezza</b>", + "CERTIFY_RULES_TITLE_UID": "Certificare {{uid}}", + "CERTIFY_RULES": "<b class=\"assertive\">Non certificare un conto</b> se credi che: <ul><li>1.) l'identità della persona potrebbe essere finta.<li>2.) la oersona ha già un conto certicato.<li>3.) la persona trasgredisce la regola 1 o 2 o entrambe. (Certifica conti finti o gemelli).</ul></small><br/>Sei sicuro/a di voler certificare questa identità ?", + "TRANSFER": "<b>Resoconto del bonifico:</b><br/><br/><ul><li> - Inviato da: <b>{{from}}</b></li><li> - A: <b>{{to}}</b></li><li> - Importo: <b>{{amount}} {{unit}}</b></li><li> - Comento: <i>{{comment}}</i></li></ul><br/><b>Sei sicuro di voler procedere con questo bonifico?</b>", + "MEMBERSHIP_OUT": "Questa operazione è <b>irreversibile</b>.<br/></br/><b>Sei sicuro/a di voler cancellare la tua presenza nella WOT?</b>", + "MEMBERSHIP_OUT_2": "Questa operazione è <b>irreversibile</b>!<br/><br/>Sei sicuro/a <b>di voler revocare la tua identità </b>?", + "LOGIN_UNUSED_WALLET_TITLE": "Errore di battitura?", + "LOGIN_UNUSED_WALLET": "Il conto sembra <b>inattivo</b>.<br/><br/>Probabilmente è un<b>errore di battitura</b> mientre digitavi i tuoi credenziali. Per favore riprova, verificando che la <b>chiave pubblica sia tua<b/>.", + "FIX_IDENTITY": "Lo pseudonimo <b>{{uid}}</b> verrà pubblicato nuovamente. Si sostituirà alla precedente pubblicazione che è scaduta.<br/></br/><b>Sei sicuro/a</b> di voler procedere?", + "FIX_MEMBERSHIP": "Tua domanda di certificazione sarà inviata alla rete.<br/></br/><b>Sei sicuro/a?</b>", + "MEMBERSHIP": "Tua domanda per diventare membro sta per essere inviata alla rete.<br/></br/><b>Sei sicuro/a/b> di voler continuare ?", + "RENEW_MEMBERSHIP": "Tua adesione verrà rinnovata.<br/></br/><b>Sei sicuro/a?</b>", + "REVOKE_IDENTITY": "Stai per <b>revocare definitivamente questa identità </b>.<br/><br/>La chiave pubblica e lo pseudonimo associato <b>non saranno mai più utilizzati</b> (per un conto membro).<br/></br/><b>Sei sicuro/a</b> di voler revocare questa identità ?", + "REVOKE_IDENTITY_2": "Questa operazione è <b>irreversibile</b>!<br/><br/>Sei sicuro/a di volern<b>revocare questa identità </b>?", + "NOT_NEED_RENEW_MEMBERSHIP": "Tua presenza nella rete non deve ancora essere rinnovata (scaderà tra {{membershipExpiresIn|formatDuration}}).<br/></br/><b>Sei sicuro/a</b> di voler rinnovare la tua presenza?", + "SAVE_BEFORE_LEAVE": "Vuoi <b>salvare tue modifiche</b> prima di uscira dalla pagina?", + "SAVE_BEFORE_LEAVE_TITLE": "Modifiche non salvate", + "LOGOUT": "Sei sicuro/a di voler chiudere la sessione?", + "USE_FALLBACK_NODE": "Peer <b>{{old}}</b> indisponibile o indirizzo errato.<br/><br/>Vuoi utilizzare temporanemante il <b>{{new}}</b> nodo?", + "INVALID_FILE_FORMAT": "Formato file non valido.", + "SAME_TX_RECIPIENT": "Il destinatario deve essere diverso dall'emittente." + }, + "DOWNLOAD": { + "POPUP_TITLE": "<b>File di cancellazione dell'identità /b>", + "POPUP_REVOKE_MESSAGE": "Per migliorare la sicurezza del tuo conto, scarica <b>il documento di revoca del conto</b>. Ti consentirà di revocare tuo conto (nel caso di violazione del conto, della tua identità , conto creato con errori, etc.).<br/><br/><b>Tiene questo document al sicuro.</b>" + }, + "HELP": { + "TITLE": "Aiuto online", + "JOIN": { + "SECTION": "Entrare nella rete", + "SALT": "Il tuo identificativo segreto è molto importante. E utilizzato per cryptare tua password che permette poi di calcolare tua <span class=\"text-italic\">chiave pubblica</span> (suo numero) è la chiave privata che ne consenta l'accesso.<br/><b>Ricordati bene di questo identificativo</b>, perche non ti potrà aiutare nessuno se lo perdi.<br/>Tra l'altro, non puo essere cambiato senza dover creare un conto nuovo.<br/><br/>Raccomandiamo che sia abbastanza lungo (8 caratteri almeno) è il più originale possibile. (buona entropia)", + "PASSWORD": "La password è molto importante, è utilizzata per calcolare tuo numero di conto (tua chiave pubblica) e la chiave privata che ne consento l'accesso.<br/><b>Ricordatila bene</b>, perche non ti potrà aiutare nessuno se lo perdi.<br/>Tra l'altro, non puo essere cambiata senza dover creare un conto nuovo.<br/><br/>Una buona password (preferibilmente) è composta da almeno 8 caratteri, con almeno una maiuscola e un numero.", + "PSEUDO": "Un pseudonimo è utilizzato quando ti iscrivi come <span class=\"text-italic\">membro</span>. E sempre associato ad un portafoglio (con sua <span class=\"text-italic\">chiave pubblica</span>).<br/>E pubblicato sulla rete perche gli altri membri possino identificarla, certificarla o invarle soldi. <br/> Lo pseudonimo deve essere unico nella rete (tra quelli utilizzati adesso e in passato)." + }, + "LOGIN": { + "SECTION": "Accedi", + "PUBKEY": "Chiave pubblica del conto", + "PUBKEY_DEF": "La chiave pubblica del portachiavi è generata dai credenziali, ma non corrispode ad un conto già utilizzato.<br/><b>Accertati che tua chiave pubblica corrisponda al tuo conto</b>. Nel caso contrario, sarai conesso/a ad un conto probabilmente mai usato, datto che il rischio di collisione con un conto esistente è molto ridotto.<br/><a href=\"https://en.wikipedia.org/wiki/Elliptic_curve_cryptography\" target=\"_ system\">Saperne di più sulla cryptografia </a> con chiave pubblica.", + "METHOD": "Metodi di connessione", + "METHOD_DEF": "Hai diverse opzioni per accedere ad un portafoglio:<br/> - Accedendo con <b>salatura (leggera o sicura)</b> tua password sarà cryptata dal tuo identificativo segreto per scoraggiare tentativi di attachi di 'brute force' (per esempio con passwords conosciute).<br/> - Accedendo con la <b>chiave pubblica</b> ti evita di dover digitare tuoi credenziali che ti saranno chiesti solo quando vorrai fare una operazione col conto.<br/> - Accedendo <b>con un portachiavi</b> che leggerà tue chiave pubbliche e private da un file esterno, senza che tu li debba entrare." + }, + "GLOSSARY": { + "SECTION": "Glossario", + "PUBKEY_DEF": "Una chiave pubblica permette di identificare un portafoglio. Puo anche identificare un membro. In Cesium è calcolata con la password e lo pseudonimo.", + "MEMBER": "Membro", + "MEMBER_DEF": "Un membro è una persona reale e viva, che desidera participare liberamente alla communità monetaria. Questo membro riceverà un Dividendo Universale, a secondo delle regole definite <span class=\"text-italic\">nei parametri della moneta</span>.", + "CURRENCY_RULES": "Regole della moneta", + "CURRENCY_RULES_DEF": "I parametri delle moneta sono state definite per sempre e per tutti. I parametri con i quali la moneta si comporta: il calcolo del Dividendo Universale, il numero di certificazioni necessarie per diventare membro, il numero massimo di certificazioni che un membro puo inviare, etc.<br/><br/>I parametri non possono essere modificati perche c'è una<span class=\"text-italic\">Blockchain</span> che implementa e esegue queste regole e verifica costantemente la loro applicazione. <a href=\"#/app/currency\">Vedere i parametri </a>.", + "BLOCKCHAIN": "Blockchain", + "BLOCKCHAIN_DEF": "La Blockchain è un sistema decentralizzato che, nel caso di Duniter, permette di rispettare e implementare <span class=\"text-italic\">le regole della moneta</span>.<br/><a href=\"http://en.duniter.org/presentation/\" target=\"_blank\">Saperne di più su Duniter</a> e il funzionamento della blockchain.", + "UNIVERSAL_DIVIDEND_DEF": "Il Dividendo Universale (UD) è la quantità di moneta co-creata da ogni membro, seguendo le formule mathematiche definite nelle <span class=\"text-italic\">regole della moneta</span>.<br/>Al inizio di ogni periodo, il conto di ogni membro riceve una quantità uguale della nuova moneta creata. <br/><br/>Il DU conosce una crescita costante per rimanere equo nei confronti dei membri (attuali e passati). Viene calcolato tenendo in conto la speranza di vità media, cosi come dimostrato nella Teoria Relativa della Moneta (TRM).<br/><a href=\"http://trm.creationmonetaire.info\" target=\"_system\">Saperne di più sulla TRM</a> e la moneta libera." + }, + "TIP": { + "MENU_BTN_CURRENCY": "Menu <b>{{'MENU.CURRENCY'|translate}}</b> permette la scoperta dei <b>parametri della moneta</b> e la sua condizione presente.", + "CURRENCY_WOT": "Il <b>numero di membri</b> mostra <b>le dimensioni della WoT e la sua evoluzione </b>.", + "CURRENCY_MASS": "In evidenza qui è <b>l'importo totale</b> attualmente in circolazione e la sua <b> ripartizione media </b> a testa.<br/><br/>Questa cifra permette di avere un'idea <b>del valore di qualsiasi importo</b>, in base a quello <b>hanno gli altri</b> sul loro conto (in media).", + "CURRENCY_UNIT_RELATIVE": "L'unità usata qui (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) significa che gli importi in {{currency|capitalize}} sono stati divisi dal <b>Dividendo Universale</b> (DU).<br/><br/><small>Questa unità relativa <b>ha senso</b> perche è stabile in contrasto con la massa monetaria che cresce costantemente.</small>", + "CURRENCY_CHANGE_UNIT": "Questa opzione <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> permette di <b>permutare unità </b> per vedere gli importi in <b>{{currency|capitalize}}</b>, non divisi dal Dividendo Universale (piuttosto che in “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”).", + "CURRENCY_CHANGE_UNIT_TO_RELATIVE": "Questa opzione <b>{{'COMMON.BTN_RELATIVE_UNIT'|translate}}</b> permette <b>di permutare unità </b> per vedere gli importi in “<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”, che è relativo al Dividendo Universale (l'importo co-prodotto da ogni membro).", + "CURRENCY_RULES": "Le<b>regole</b> della moneta determinano il suo <b>esatto e previdibile</b> comportamento.<br/><br/> Considerate come il proprio DNA della moneta, queste regole rendono il codice monetario <b>trasparente e comprensibile</b>.", + "MENU_BTN_NETWORK": "Menu <b>{{'MENU.NETWORK'|translate}}</b> permette la scopertà dello <b>stato della rete<b>.", + "NETWORK_BLOCKCHAIN": "Tutte le transazioni monetarie sono registrate in <b>registro sicuro e a prova di manomissione</b>, spesso chiamato <b>blockchain</b>.", + "NETWORK_PEERS": "I<b>peers</b> mostrati qui corrispondono a <b>dei computers che aggiornano e monitorano</b> la blockchain.<br/><br/>Più peers ci sono, più <b>decentralizzata</b> e più affidabile diventa la moneta.", + "NETWORK_PEERS_BLOCK_NUMBER": "Questo <b>numero</b> (in verda) indica <b>l'ultimo blocco validato</b> dal peer (ultima pagina scritta nel regitro).<br/><br/>Il verda indica che il blocco è stato validato anche dalla <b>maggioranza degli altri peers</b>.", + "NETWORK_PEERS_PARTICIPATE": "<b>Ogni membro</b>, che dispone di un computer connesso a Internet <b>puo partecipare, aggiungendosi come peer installando il software Duniter</b> (free/libre). <a target=\"_new\" href=\"{{installDocUrl}}\" target=\"_system\">Leggi il manuale d'installazione >></a>.", + "MENU_BTN_ACCOUNT": "<b>{{'ACCOUNT.TITLE'|translate}}</b> permette l'accesso al saldo del conto e la cronologia delle transazioni.", + "MENU_BTN_ACCOUNT_MEMBER": "Qui puoi consultare lo stato del tuo conto, la cronologia delle transazioni e le tue certificazioni.", + "WALLET_CERTIFICATIONS": "Clicca qui per vedere i dettagli delle tue certificazioni (date o ricevute).", + "WALLET_RECEIVED_CERTIFICATIONS": "Clicca qui per vedere i dettagli delle <b>certificazioni che hai ricevuto</b>.", + "WALLET_GIVEN_CERTIFICATIONS": "Clicca qui per vedere i dettagli delle <b>certificazioni che hai date</b>.", + "WALLET_BALANCE": "Il <b>soldo</b> del tuo conto è visibile qui.", + "WALLET_BALANCE_RELATIVE": "{{'HELP.TIP.WALLET_BALANCE'|translate}}<br/><br/>L'unità utilizzata (“<b>{{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub></b>”) significa che questo importo in {{currency|capitalize}} è stato diviso dal <b>Dividendo Universale</b> (DU) co-creato da ogni membro.<br/>Ad oggi, 1 DU equivale a {{currentUD}} {{currency|capitalize}}.", + "WALLET_BALANCE_CHANGE_UNIT": "Puoi <b>cambiare l'unità </b> in cui sono mostrati gli importi in <b><i class=\"icon ion-android-settings\"></i> {{'MENU.SETTINGS'|translate}}</b>.<br/><br/>Per esempio, per mostrare gli importi <b>direttamente in {{currency|capitalize}}</b> piuttosto che in unità relativa.", + "WALLET_PUBKEY": "Questa è la chiave pubblica del tuo conto. La puoi dare ad un terzo perche possa identificare tuo conto.", + "WALLET_SEND": "Paghi in pochi clics.", + "WALLET_SEND_NO_MONEY": "Paghi in pochi clics.<br/>(Tuo saldo ancora non lo permette)", + "WALLET_OPTIONS": "Questo bottone permette di fare <b>altre, meno frequenti azioni</b>.<br/><br/> Non dimenticarti di fare il tour guidato di Cesium quando hai un attimo!", + "WALLET_RECEIVED_CERTS": "Questo mostra l'elenco delle persone che ti hanno fatto entrare nella WoT.", + "WALLET_CERTIFY": "Questo bottone <b>{{'WOT.BTN_SELECT_AND_CERTIFY'|translate}}</b> permette di selezionare e certificare una identità .<br/><br/>Solo gli utenti <b>che sono già membri</b> possono certificare gli altri.", + "WALLET_CERT_STOCK": "Tuo stock di certificazioni da dare è limitato a <b>{{sigStock}} certificazioni</b>.<br/><br/>Questo stock si rifornisce col tempo, man mano che le certificazioni inviate scadono.", + "MENU_BTN_TX_MEMBER": "<b>{{'MENU.TRANSACTIONS'|translate}}</b> permette l'accesso alla cronologia delle transazioni, e permette di fare nuovi bonifici.", + "MENU_BTN_TX": "Visualizza la cronologia <b>delle tue transazioni</b> qui e fai nuovi bonifici.", + "MENU_BTN_WOT": "Il menu<b>{{'MENU.WOT'|translate}}</b> permette di cercare <b>utenti</b> della moneta (membri o non).", + "WOT_SEARCH_TEXT_XS": "Per fare una ricerca nel annuario, digita <b>le prime lettere dello pseudonimo o della chiave pubblica di un utente</b>.<br/><br/>La ricerca inizierà automaticamente.", + "WOT_SEARCH_TEXT": "Per cercare nel annuario, digita <b>le prime lettere dello pseudonimo o della chiave pubblica di un utente</b>.<br/><br/>Dopodichè calca <b>Enter</b> per avviare la ricerca.", + "WOT_SEARCH_RESULT": "Visualizza la scheda dettagliata di un utente con un semplice click sulla linea.", + "WOT_VIEW_CERTIFICATIONS": "La linea <b>{{'ACCOUNT.CERTIFICATION_COUNT'|translate}}</b> mostra quanti membri hanno certificato questa identità .<br/><br/>Queste certificazioni dimostrano che il conto appartiene ad <b>una persona viva</b> e che questa persona non ha <b>nessun altro conto membro</b>.", + "WOT_VIEW_CERTIFICATIONS_COUNT": "Ci vogliono almeno <b>{{sigQty}} certificazioni</b> per diventare membro e co-produrre il <b>Dividendo Universale</b>.", + "WOT_VIEW_CERTIFICATIONS_CLICK": "Clicca qui per aprire <b>una lista di tutte le certificazioni</b> ricevute e date da questa identità .", + "WOT_VIEW_CERTIFY": "Il bottone <b>{{'WOT.BTN_CERTIFY'|translate}}</b> permette di aggiungere tua certificazione a questa identità .", + "CERTIFY_RULES": "<b>Attenzione:</b> Certifichi <b> solo persone reali e vive</b> che non hanno nessun altro conto membro.<br/><br/>L'affidabilità della moneta dipende della vigilanza di ciascuno.", + "MENU_BTN_SETTINGS": "Les <b>{{'MENU.SETTINGS'|translate}}</b> ti permettono di configurare Cesium.<br/><br/>Per esempio, puoi <b>cambiare l'unità </b> in cui visualizzi la moneta.", + "HEADER_BAR_BTN_PROFILE": "Clicca qui per entrare nel <b>tuo profilo utente</b>", + "SETTINGS_CHANGE_UNIT": "Puoi cambiare <b>l'unità </b> della moneta cliccando qui.<br/><br/>- Disabilita questa opzione per vedere gli importi in {{currency|capitalize}}.<br/>- Abilita l'opzione per importi relativi in {{'COMMON.UD'|translate}}<sub>{{currency|abbreviate}}</sub> (<b>divisi</b> dal attuale Dividendo Universale).", + "END_LOGIN": "Il tour guidato <b>è finito</b>.<br/><br/>Benvenuto nel <b>economia libera</b>!", + "END_NOT_LOGIN": "Il tour guidato <b>è finito</b>.<br/><br/>Se desideri entrare nella Web of Trust {{currency|capitalize}}, basta cliccare <b>{{'LOGIN.CREATE_ACCOUNT'|translate}}</b> qui sotto." + } + }, + "API" :{ + "COMMON": { + "LINK_DOC": "documentazione API", + "LINK_DOC_HELP": "Documentazione dello sviluppatore", + "LINK_STANDARD_APP": "versione classica", + "LINK_STANDARD_APP_HELP": "Apri la versione classica di {{'COMMON.APP_NAME'|translate}}" + }, + "HOME": { + "TITLE": "Documentazione API {{'COMMON.APP_NAME'|translate}}", + "MESSAGE": "Bienvenue dans la <b>documentation de l'API</b> {{'COMMON.APP_NAME'|translate}}.<br/>Connecter vos sites web à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", + "MESSAGE_SHORT": "Connecter vos sites à <a href=\"http://duniter.org\" target=\"_system\">Duniter</a> très simplement !", + "DOC_HEADER": "Services disponibles :" + }, + "TRANSFER": { + "TITLE": "{{'COMMON.APP_NAME'|translate}} - Paiement en ligne", + "TITLE_SHORT": "Pagamento online", + "SUMMARY": "Récapitulatif de la commande :", + "AMOUNT": "Montant :", + "NAME": "Nom :", + "PUBKEY": "Clé publique du destinaire :", + "COMMENT": "Référence de la commande :", + "DEMO": { + "SALT": "demo", + "PASSWORD": "demo", + "PUBKEY": "3G28bL6deXQBYpPBpLFuECo46d3kfYMJwst7uhdVBnD1", + "HELP": "<b>Mode démonstration</b> : Aucun paiement ne sera réellement envoyé pendant cette simulation.<br/>Veuillez utiliser les identifiants : <b>{{'API.TRANSFER.DEMO.SALT'|translate}} / {{'API.TRANSFER.DEMO.PASSWORD'|translate}}</b>", + "BAD_CREDENTIALS": "Vérifiez votre saisie.<br/>En mode démonstration, les identifiants sont : {{'API.TRANSFER.DEMO.SALT'|translate}} / {{'API.TRANSFER.DEMO.PASSWORD'|translate}}" + }, + "INFO": { + "SUCCESS_REDIRECTING_WITH_NAME": "Paiement envoyé.<br/>Redirection vers <b>{{name}}</b>...", + "SUCCESS_REDIRECTING": "Paiement envoyé.<br/>Redirection vers le site du vendeur...", + "CANCEL_REDIRECTING_WITH_NAME": "Paiement annulé.<br/>Redirection vers <b>{{name}}</b>...", + "CANCEL_REDIRECTING": "Paiement annulé.<br/>Redirection vers le site du vendeur..." + }, + "ERROR": { + "TRANSFER_FAILED": "Mancato pagamento" + } + }, + "DOC": { + "DESCRIPTION_DIVIDER": "Descrizione", + "URL_DIVIDER": "Indirizzo chiamata", + "PARAMETERS_DIVIDER": "Impostazioni", + "AVAILABLE_PARAMETERS": "Ecco l'elenco dei parametri disponibili :", + "DEMO_DIVIDER": "Provare", + "DEMO_HELP": "Per provare questo servizio, clicca sul bottone qui a fianco. Il risultato apparirà qui sotto .", + "DEMO_RESULT": "Risultato della chiamata :", + "DEMO_SUCCEED": "<i class=\"icon ion-checkmark\"></i> Successo !", + "DEMO_CANCELLED": "<i class=\"icon ion-close\"></i> Annulato dal utente", + "INTEGRATE_DIVIDER": "Integrare", + "INTEGRATE_CODE": "Codice :", + "INTEGRATE_RESULT": "Previsualizzare il risultato :", + "INTEGRATE_PARAMETERS": "Parametri", + "TRANSFER": { + "TITLE": "Pagamenti", + "DESCRIPTION": "Da un sito (per es. : un sito e-commerce) si può delegare il pagamento in moneta libera a Cesium API. Per invocare l'API, basta innescare l'apertura di una pagina con questo indirizzo:", + "PARAM_PUBKEY": "Chiave pubblica del destinatario", + "PARAM_PUBKEY_HELP": "Chiave pubblica del destinatario (obliggatoria)", + "PARAM_AMOUNT": "Importo", + "PARAM_AMOUNT_HELP": "Importo della transazione (obligatorio)", + "PARAM_COMMENT": "Riferimento (o commento)", + "PARAM_COMMENT_HELP": "Riferimento o commento. Ti può aiutare per esempio a trovare tuo pagamento nella blockchain.", + "PARAM_NAME": "Nome (de destinatario o del sito web)", + "PARAM_NAME_HELP": "Nom del sito web o del destinatario chiamando l'API. Può essere un nome leggibile (\"Mio sito\"), oppure l'indirizzo http del sito (\"MioSito.com\").", + "PARAM_REDIRECT_URL": "Indirizzo web di redirezione", + "PARAM_REDIRECT_URL_HELP": "Indirizzo web (URL) di redirezione, chiamato dopo aver inviato il pagamento. Può includere le seguenti stringe, che saranno sostituite con i valori della transazione : \"{tx}\", \"{hash}\", \"{comment}\", \"{amount}\" e {pubkey}.", + "PARAM_CANCEL_URL": "Indirizzo web della cancellazione", + "PARAM_CANCEL_URL_HELP": "Indirizzo web (URL) in caso dell'annullamento del pagamento dall'utente. Può includere le seguenti stringe, che saranno sostituite dinamicamente : \"{comment}\", \"{amount}\" e {pubkey}.", + "EXAMPLES_HELP": "Ecco esempi di integrazione :", + "EXAMPLE_BUTTON": "Bottone HTML", + "EXAMPLE_BUTTON_DEFAULT_TEXT": "Pagare in {{currency|currencySymbol}}", + "EXAMPLE_BUTTON_DEFAULT_STYLE": "Stile personnalizzato", + "EXAMPLE_BUTTON_TEXT_HELP": "Testo del bottone", + "EXAMPLE_BUTTON_BG_COLOR": "Colore del fondo", + "EXAMPLE_BUTTON_BG_COLOR_HELP": "Per esempio: #fbc14c, black, lightgrey, rgb(180,180,180)", + "EXAMPLE_BUTTON_FONT_COLOR": "Colore del testo", + "EXAMPLE_BUTTON_FONT_COLOR_HELP": "Esempio: black, orange, rgb(180,180,180)", + "EXAMPLE_BUTTON_TEXT_ICON": "Icona", + "EXAMPLE_BUTTON_TEXT_WIDTH": "Larghezza", + "EXAMPLE_BUTTON_TEXT_WIDTH_HELP": "Esempio: 200px, 50%", + "EXAMPLE_BUTTON_ICON_NONE": "Nessuna", + "EXAMPLE_BUTTON_ICON_DUNITER": "Logo Duniter", + "EXAMPLE_BUTTON_ICON_CESIUM": "Logo Cesium", + "EXAMPLE_BUTTON_ICON_G1_COLOR": "Logo Äž1", + "EXAMPLE_BUTTON_ICON_G1_BLACK": "Logo Äž1 (nero)" + } + } + } +} diff --git a/assets/www/i18n/locale-nl-NL.json b/assets/www/i18n/locale-nl-NL.json index c34abead66580f7e3b5e3c855674eaffb3ce6da3..1384445ccedc94524f50e41d838e8e3086146cec 100644 --- a/assets/www/i18n/locale-nl-NL.json +++ b/assets/www/i18n/locale-nl-NL.json @@ -95,7 +95,7 @@ }, "ABOUT": { "TITLE": "Over", - "LICENSE": "<b>Vrije</b> software (GNU GPLv3 licentie).", + "LICENSE": "<b>Vrije</b> software (GNU AGPLv3 licentie).", "CODE": "Broncode:", "DEVELOPERS": "Ontwikkelaars:", "FORUM": "Forum:", @@ -113,8 +113,8 @@ "BTN_ABOUT": "over", "BTN_HELP": "Help", "REPORT_ISSUE": "Meld een probleem", - "NOT_YOUR_ACCOUNT_QUESTION" : "Je hoeft niet de rekening <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> in uw bezit?", - "BTN_CHANGE_ACCOUNT": "Dit account ontkoppelen", + "NOT_YOUR_ACCOUNT_QUESTION" : "Is rekening <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> niet van jou?", + "BTN_CHANGE_ACCOUNT": "Dze rekening ontkoppelen", "CONNECTION_ERROR": "Node <b>{{server}}</b> onbereikbaar of ongeldig adres.<br/><br/>Controleer de internetverbinding, of schakel knooppunt <a class=\"positive\" ng-click=\"doQuickFix('settings')\">in parameters</a>." }, "SETTINGS": { @@ -123,7 +123,7 @@ "PEER": "Duniter knooppunt adres", "PEER_CHANGED_TEMPORARY": "Adres tijdelijk worden gebruikt", "USE_LOCAL_STORAGE": "Lokale opslag inschakelen", - "USE_LOCAL_STORAGE_HELP": "Slaat uw instellingen", + "USE_LOCAL_STORAGE_HELP": "Laat je instellingen opslaan", "ENABLE_HELPTIP": "Contextgebonden hulp inschakelen", "ENABLE_UI_EFFECTS": "Schakel visuele effecten", "HISTORY_SETTINGS": "Mijn rekening", @@ -266,7 +266,7 @@ "NO_GIVEN_CERTIFICATION": "Geen uitgegeven certificaties", "NOT_MEMBER_PARENTHESIS": "(niet-lid)", "IDENTITY_REVOKED_PARENTHESIS": "(ingetrokken identiteit)", - "MEMBER_PENDING_REVOCATION_PARENTHESIS": "(en cours de révocation)", + "MEMBER_PENDING_REVOCATION_PARENTHESIS": "(intrekking in behandeling)", "EXPIRE_IN": "Verloopt", "NOT_WRITTEN_EXPIRE_IN": "Uiterlijke<br/>behandeling", "EXPIRED": "Verlopen", @@ -274,9 +274,9 @@ "SIGNED_ON_BLOCK": "Uitgegeven op block #{{block}}", "WRITTEN_ON_BLOCK": "Geschreven op block #{{block}}", "GENERAL_DIVIDER": "Algemene informatie", - "NOT_MEMBER_ACCOUNT": "Geen lidaccount", - "NOT_MEMBER_ACCOUNT_HELP": "Dit is een eenvoudige account zonder te wachten lidmaatschap aanvragen.", - "TECHNICAL_DIVIDER": "Technishe informatie", + "NOT_MEMBER_ACCOUNT": "Simpele rekening (geen lid)", + "NOT_MEMBER_ACCOUNT_HELP": "Dit is een eenvoudige rekening, zonder dat er een aanvraag voor lidmaatschap in de wacht wordt gezet.", + "TECHNICAL_DIVIDER": "Technische informatie", "BTN_CERTIFY": "Certificeren", "BTN_YES_CERTIFY": "Ja, Certificeren", "BTN_SELECT_AND_CERTIFY": "Nieuwe certificatie", @@ -289,7 +289,7 @@ "NEWCOMERS": "Nieuwe leden:", "PENDING": "Aspirant leden:", "REGISTERED": "Geregistreerd {{sigDate | formatFromNow}}", - "MEMBER_FROM": "Lid sinds {{memberDate|formatFromNowShort}}", + "MEMBER_FROM": "Lid sinds {{memberDate|medianFromNowShort}}", "BTN_NEWCOMERS": "Nieuwste leden", "BTN_PENDING": "Registraties in afwachting", "SHOW_MORE": "Toon meer", @@ -323,10 +323,10 @@ "LOGIN": { "TITLE": "<i class=\"icon ion-locked\"></i> Inloggen", "SALT": "Beveiligingszin", - "SALT_HELP": "Zin ter beveiliging van uw rekening", + "SALT_HELP": "Zin ter beveiliging van je rekening", "SHOW_SALT": "Toon de beveiligingszin", "PASSWORD": "Wachtwoord", - "PASSWORD_HELP": "Wachtwoord ter beveiliging van uw rekening", + "PASSWORD_HELP": "Wachtwoord ter beveiliging van je rekening", "NO_ACCOUNT_QUESTION": "Nog geen rekening?", "CREATE_ACCOUNT": "Open een rekening", "FORGOTTEN_ID": "Wachtwoord vergeten?" @@ -339,7 +339,7 @@ "NO_TX": "Geen transacties", "SHOW_MORE_TX": "Show more", "SHOW_ALL_TX": "Show all", - "TX_FROM_DATE": "(huidige limiet op {{fromTime|formatFromNowShort}})", + "TX_FROM_DATE": "(huidige limiet op {{fromTime|medianFromNowShort}})", "PENDING_TX": "Transacties in afwachting", "ERROR_TX": "Niet uitgevoerde transacties", "ERROR_TX_SENT": "Verzonden transacties", @@ -358,7 +358,7 @@ "BTN_MEMBERSHIP_RENEW_DOTS": "Lidmaatschap verlengen...", "BTN_MEMBERSHIP_OUT_DOTS": "Lidmaatschap opzeggen...", "BTN_SEND_IDENTITY_DOTS": "Identiteit publiceren...", - "BTN_SECURITY_DOTS": "Account en veiligheid...", + "BTN_SECURITY_DOTS": "Rekening en veiligheid...", "BTN_SHOW_DETAILS": "Tonen technische informatie", "BTN_REVOKE": "Deze identiteit<span class='hidden-xs hidden-sm'> definitief</span> opzeggen...", "NEW": { @@ -369,8 +369,8 @@ "MEMBER_ACCOUNT_HELP": "Als je nog niet als individu geregistreerd bent (één rekening per individu mogelijk).", "WALLET_ACCOUNT": "Eenvoudige portefeille", "WALLET_ACCOUNT_HELP": "Als je een onderneming, stichting etc. vertegenwoordigd of eenvoudigweg een additionele portefeille nodig hebt. Geen individueel universeel dividend zal door deze rekening gecréeerd worden.", - "SALT_WARNING": "Kies een beveiligingszin.<br/>Deze heb je nodig voor ieder verbinding met je account.<br/><br/><b>Zorg dat je deze zin goed onthoud</b>.<br/>Eenmaal verloren, is er geen mogelijkheid om hem te achterhalen!", - "PASSWORD_WARNING": "Kies een wachtwoord.<br/>Deze heb je nodig voor ieder verbinding met je account.<br/><br/><b>Zorg dat je dit woord goed onthoud</b>.<br/>Eenmaal verloren, is er geen mogelijkheid om hem te achterhalen!", + "SALT_WARNING": "Kies een beveiligingszin.<br/>Deze heb je nodig voor ieder verbinding met je rekening.<br/><br/><b>Zorg dat je deze zin goed onthoud</b>.<br/>Eenmaal verloren, is er geen mogelijkheid om hem te achterhalen!", + "PASSWORD_WARNING": "Kies een wachtwoord.<br/>Deze heb je nodig voor ieder verbinding met je rekening.<br/><br/><b>Zorg dat je dit woord goed onthoud</b>.<br/>Eenmaal verloren, is er geen mogelijkheid om hem te achterhalen!", "PSEUDO_WARNING": "Kies een pseudoniem.<br/>Het dient om makkelijker gevonden te worden door anderen.<br/><br/>.Gebruik van spaties, komma's en accenten is niet toegestaan.<br/><div class='hidden-xs'><br/>Voorbeeld: <span class='gray'>JulesDeelder, JohanVermeer, etc.</span>", "PSEUDO": "Pseudoniem", "PSEUDO_HELP": "joe123", @@ -478,8 +478,8 @@ "LOAD_PENDING_FAILED": "Unable to load pending registrations.", "ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION": "You must <b>be a member</b> in order to perform this action.", "ONLY_SELF_CAN_EXECUTE_THIS_ACTION": "You must have <b>published your identity</b> in order to perform this action.", - "EXISTING_ACCOUNT": "Uw wachtwoord overeenkomen met een bestaande account, de <a ng-click=\"showHelpModal('pubkey')\">publieke sleutel</a> is:", - "EXISTING_ACCOUNT_REQUEST": "Gelieve uw wachtwoord wijzigen om een ongebruikte account." + "EXISTING_ACCOUNT": "Je gegevens komen overeen met een bestaande rekening, met de <a ng-click=\"showHelpModal('pubkey')\">publieke sleutel</a>:", + "EXISTING_ACCOUNT_REQUEST": "Gelieve je gegevens te wijzigen zodat ze met een niet gebruikte rekening overeenkomen." }, "INFO": { "POPUP_TITLE": "Informatie", @@ -499,7 +499,7 @@ "TRANSFER": "<b>Samenvatting van de overboeking:</b><br/><br/><ul><li> - Van: <b>{{from}}</b></li><li> - Aan: <b>{{to}}</b></li><li> - Bedrag: <b>{{amount}} {{unit}}</b></li><li> - Opmerking: <i>{{comment}}</i></li></ul><br/><b>Weet je zeker dat je deze overboeking wil doen?</b>", "MEMBERSHIP_OUT": "<b>Waarschuwing</b>:<br/>Je staat op het punt je lidmaatschap te beëindigen. Dit kan <b>niet ongedaan</b> worden gemaakt.<br/></br/><b>Weet je zeker dat je door wil gaan?</b>", "LOGIN_UNUSED_WALLET_TITLE": "Typefout?", - "LOGIN_UNUSED_WALLET": "Je bent ingelogged op een rekening die <b>inactief</b> lijkt te zijn.<br/><br/>Als deze rekening niet met de uwe overeenkomt, komt dat waarschijnlijk door een <b>typefout</b> bij het inloggen.<br/><br/><b>Wilt u toch doorgaan met deze rekening?</b>", + "LOGIN_UNUSED_WALLET": "Je bent ingelogged op een rekening die <b>inactief</b> lijkt te zijn.<br/><br/>Als deze rekening niet met de jouwe overeenkomt, komt dat waarschijnlijk door een <b>typefout</b> bij het inloggen.<br/><br/><b>Wilt u toch doorgaan met deze rekening?</b>", "FIX_IDENTITY": "De pseudoniem <b>{{uid}}</b> zal opnieuw gepubliceerd worden, waarmee de oude verlopen publicatie wordt vervangen.<br/></br/><bWeet je zeker</b> dat je door wil gaan?", "FIX_MEMBERSHIP": "Je verzoek to lidmaatschap zal verstuurd worden.<br/></br/><b>Weet je het zeker?</b>", "RENEW_MEMBERSHIP": "Je lidmaatschap zal verlengd worden.<br/></br/><b>Weet je het zeker?</b>", @@ -511,8 +511,8 @@ "LICENCE": "Ik heb gelezen en geaccepteerd de voorwaarden van de vergunning G1" }, "DOWNLOAD": { - "POPUP_TITLE": "<b>Intrekking File</b>", - "POPUP_REVOKE_MESSAGE": "Om uw account te beveiligen, het downloaden van de <b>Account intrekking document</b>. U zult indien nodig om uw account (annuleren in het geval van de rekening van diefstal, een verandering van de identifier, een ten onrechte gemaakte account, etc.).<br/><br/><b>Bewaar deze op een veilige plaats.</b>" + "POPUP_TITLE": "<b>Intrekkingsdocument</b>", + "POPUP_REVOKE_MESSAGE": "Om je rekening te beveiligen, download het <b>rekening intrekkingsdocument</b>. Dit heb je nodig om je rekening op te heffen (in het geval van diefstal, een verandering van ID, een ten onrechte gemaakte rekening, etc.).<br/><br/><b>Bewaar deze op een veilige plaats.</b>" }, "HELP": { "TITLE": "Online help", diff --git a/assets/www/img/layers-2x.png b/assets/www/img/layers-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a2cf7f9efef65d2e021f382f47ef50d51d51a0df Binary files /dev/null and b/assets/www/img/layers-2x.png differ diff --git a/assets/www/img/layers.png b/assets/www/img/layers.png new file mode 100644 index 0000000000000000000000000000000000000000..bca0a0e4296b0d871be09d463fd68876126155d0 Binary files /dev/null and b/assets/www/img/layers.png differ diff --git a/assets/www/img/loader.gif b/assets/www/img/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..d3ef195d52dad8449e21eb58817dcb3ae8a9ba73 Binary files /dev/null and b/assets/www/img/loader.gif differ diff --git a/assets/www/img/markers-shadow.png b/assets/www/img/markers-shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..33cf95504706aa9d06ad40dbcd2fa168cbd43d13 Binary files /dev/null and b/assets/www/img/markers-shadow.png differ diff --git a/assets/www/img/markers-shadow@2x.png b/assets/www/img/markers-shadow@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1116503f6a572bec04496f164270dbbdffaefb84 Binary files /dev/null and b/assets/www/img/markers-shadow@2x.png differ diff --git a/assets/www/img/search-icon-mobile.png b/assets/www/img/search-icon-mobile.png new file mode 100644 index 0000000000000000000000000000000000000000..920fa27585cee993fe284a272c38f1a5a724cc09 Binary files /dev/null and b/assets/www/img/search-icon-mobile.png differ diff --git a/assets/www/img/search-icon.png b/assets/www/img/search-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..231df745b290ab38816a19972be5d3cb0fe6bbca Binary files /dev/null and b/assets/www/img/search-icon.png differ diff --git a/assets/www/index.html b/assets/www/index.html index 74f2969db484d5da57a99268dda00503bebbf8ef..899d7bb2beec59a29c3fe870a4d3df713d3e8375 100644 --- a/assets/www/index.html +++ b/assets/www/index.html @@ -1,243 +1,255 @@ <!DOCTYPE html> <html> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,width=device-width,minimal-ui"> - <meta name="apple-mobile-web-app-capable" content="yes"> - <title>Cesium</title> - <link rel="icon" href="./img/favicon.ico"> - <link rel="apple-touch-icon" href="./img/logo_57px.png"> - <link rel="manifest" href="./manifest.json"> - <!-- build:css dist_css/cesium.css --> - <link rel="stylesheet" type="text/css" href="css/ionic.app.min.css"> - <link rel="stylesheet" type="text/css" href="css/style.css"> - <link rel="stylesheet" type="text/css" href="css/angular-image-crop.css"> - - - <!--removeIf(no-plugin)--> - <link rel="stylesheet" type="text/css" href="css/leaflet.app.min.css"> - <link rel="stylesheet" type="text/css" href="dist/dist_css/plugins/es/css/style.css"> - <link rel="stylesheet" type="text/css" href="dist/dist_css/plugins/graph/css/style.css"> - <link rel="stylesheet" type="text/css" href="dist/dist_css/plugins/map/css/style.css"> - <!--endRemoveIf(no-plugin)--> - <!-- endbuild --> - -</head> - -<body ng-app="cesium" id="cesium" ng-strict-di="true" window-exit-unauth="true" ng-class="{'nobackdrop': $root.tour, 'expert-mode': $root.settings.expertMode}"> -<ion-nav-view> - <div class="loader"> - <h3 style="text-align: center; padding-top: 25px"><b>Cesium</b></h3> - <h4 style="text-align: center"><i class="icon ion-load-a"></i></h4> - </div> -</ion-nav-view> - -<!-- build:js dist_js/vendor.js --> -<!-- vendor js --> -<script src="js/vendor/moment.min.js"></script> -<script src="js/vendor/moment.fr.js"></script> -<script src="js/vendor/moment.nl.js"></script> -<script src="js/vendor/moment.es.js"></script> -<script src="js/vendor/numeral.js"></script> -<script src="js/vendor/numeral.fr.js"></script> -<script src="js/vendor/numeral.en.js"></script> -<script src="js/vendor/numeral.nl.js"></script> -<script src="js/vendor/numeral.es.js"></script> -<script src="js/vendor/socket-io.js"></script> -<script src="js/vendor/underscore.js"></script> -<script src="js/vendor/qrcode.min.js"></script> -<script src="js/vendor/aes-js.js"></script> -<!--removeIf(ubuntu)--> <!-- FIXME: issue #463 --> -<script src="js/vendor/Chart.js"></script> -<!--endRemoveIf(ubuntu)--> - -<!-- ionic/angularjs js --> -<script src="lib/ionic/js/ionic.bundle.js"></script> -<script src="lib/ionic/js/ionic.material.js"></script> -<script src="lib/ionic/js/angular/angular-resource.js"></script> -<script src="lib/ionic/js/angular/angular-translate.js"></script> -<script src="lib/ionic/js/angular/angular-messages.js"></script> -<script src="lib/ionic/js/angular/angular-api.js"></script> -<script src="lib/ionic/js/angular/angular-cache.js"></script> -<script src="lib/ionic/js/angular/angular-screenmatch.min.js"></script> -<script src="lib/ionic/js/angular/angular-bind-notifier.min.js"></script> -<script src="lib/ionic/js/angular/angular-image-crop.js"></script> -<script src="lib/ionic/js/angular/angular-file-saver.bundle.js"></script> -<script src="lib/ionic/js/angular/angular-idle.js"></script> -<script src="lib/ionic/js/angular/angular-simple-logger.light.js"></script> -<script src="lib/ionic/js/angular/ui-leaflet.js"></script> -<script src="js/vendor/ion-digit-keyboard.min.js"></script> - -<!--removeIf(ubuntu)--> <!-- FIXME: issue #463 under ubuntu OS --> -<script src="lib/ionic/js/angular/angular-chart.min.js"></script> -<!--endRemoveIf(ubuntu)--> - - <script src="js/vendor/base58.js" async></script> - - <!--removeIf(no-device)--> - <script src="js/vendor/sha256.min.js" async></script> - <script src="js/vendor/ng-cordova.min.js"></script> - <!--endRemoveIf(no-device)--> - -<!--removeIf(no-plugin)--> -<script src="js/vendor/leaflet.js"></script> -<script src="js/vendor/leaflet.awesome-markers.min.js"></script> -<script src="js/vendor/leaflet.search.min.js"></script> -<script src="js/vendor/leaflet.easy-button.js"></script> -<script src="js/vendor/leaflet.loading.js"></script> -<script src="js/vendor/leaflet.markercluster.js"></script> -<script src="js/vendor/leaflet.featuregroup.subgroup-src.js"></script> -<!--endRemoveIf(no-plugin)--> - -<!-- endbuild --> - -<!--removeIf(no-device)--> -<script src="cordova.js"></script> -<!--endRemoveIf(no-device)--> - -<!-- build:js dist_js/cesium.js --> -<!-- services --> -<script src="dist/dist_js/app/services/settings-services.js"></script> -<script src="dist/dist_js/app/services/network-services.js"></script> -<script src="dist/dist_js/app/services/crypto-services.js"></script> -<script src="dist/dist_js/app/services/utils-services.js"></script> -<script src="dist/dist_js/app/services/cache-services.js"></script> -<script src="dist/dist_js/app/services/modal-services.js"></script> -<script src="dist/dist_js/app/services/http-services.js"></script> -<script src="dist/dist_js/app/services/storage-services.js"></script> -<script src="dist/dist_js/app/services/device-services.js"></script> -<script src="dist/dist_js/app/services/currency-services.js"></script> -<script src="dist/dist_js/app/services/bma-services.js"></script> -<script src="dist/dist_js/app/services/wot-services.js"></script> -<script src="dist/dist_js/app/services/tx-services.js"></script> -<script src="dist/dist_js/app/services/wallet-services.js"></script> -<script src="dist/dist_js/app/services/help-services.js"></script> -<script src="dist/dist_js/app/services/plugin-services.js"></script> -<script src="dist/dist_js/app/services.js"></script> - -<!-- entities --> -<script src="dist/dist_js/app/entities/peer.js"></script> -<script src="dist/dist_js/app/entities/block.js"></script> -<script src="dist/dist_js/app/entities/ws2pmessage.js"></script> - - -<!-- controllers --> -<script src="dist/dist_js/app/controllers/app-controllers.js"></script> -<script src="dist/dist_js/app/controllers/join-controllers.js"></script> -<script src="dist/dist_js/app/controllers/login-controllers.js"></script> -<script src="dist/dist_js/app/controllers/help-controllers.js"></script> -<script src="dist/dist_js/app/controllers/wallet-controllers.js"></script> -<script src="dist/dist_js/app/controllers/wot-controllers.js"></script> -<script src="dist/dist_js/app/controllers/network-controllers.js"></script> -<script src="dist/dist_js/app/controllers/currency-controllers.js"></script> -<script src="dist/dist_js/app/controllers/transfer-controllers.js"></script> -<script src="dist/dist_js/app/controllers/settings-controllers.js"></script> -<script src="dist/dist_js/app/controllers/blockchain-controllers.js"></script> -<script src="dist/dist_js/app/controllers.js"></script> - -<!-- templates --> -<script src="dist/dist_js/app/templates.js"></script> -<script src="dist/dist_js/app/translations.js"></script> - -<!--removeIf(no-plugin)--> -<!-- Plugins --> -<script src="dist/dist_js/app/plugins.js"></script> -<script src="dist/dist_js/plugins/translations.js"></script> -<script src="dist/dist_js/plugins/templates.js"></script> - -<!-- ES plugin --> -<script src="dist/dist_js/plugins/es/js/plugin.js"></script> -<script src="dist/dist_js/plugins/es/js/entities/notification.js"></script> -<script src="dist/dist_js/plugins/es/js/entities/comment.js"></script> -<script src="dist/dist_js/plugins/es/js/entities/invitation.js"></script> -<script src="dist/dist_js/plugins/es/js/services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/comment-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/http-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/settings-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/registry-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/social-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/crypto-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/profile-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/notification-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/message-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/modal-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/blockchain-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/group-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/invitation-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/subscription-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/wallet-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/wot-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/tx-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/geo-services.js"></script> -<script src="dist/dist_js/plugins/es/js/services/document-services.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/common-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/app-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/settings-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/currency-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/wallet-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/wot-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/registry-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/profile-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/message-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/notification-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/blockchain-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/network-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/group-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/invitation-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/subscription-controllers.js"></script> -<script src="dist/dist_js/plugins/es/js/controllers/document-controllers.js"></script> - -<!-- Graph plugin --> -<!--removeIf(ubuntu)--> <!-- FIXME: issue #463 --> -<script src="dist/dist_js/plugins/graph/js/plugin.js"></script> -<script src="dist/dist_js/plugins/graph/js/services.js"></script> -<script src="dist/dist_js/plugins/graph/js/services/data-services.js"></script> -<script src="dist/dist_js/plugins/graph/js/services/color-services.js"></script> -<script src="dist/dist_js/plugins/graph/js/controllers/common-controllers.js"></script> -<script src="dist/dist_js/plugins/graph/js/controllers/blockchain-controllers.js"></script> -<script src="dist/dist_js/plugins/graph/js/controllers/network-controllers.js"></script> -<script src="dist/dist_js/plugins/graph/js/controllers/currency-controllers.js"></script> -<script src="dist/dist_js/plugins/graph/js/controllers/account-controllers.js"></script> -<script src="dist/dist_js/plugins/graph/js/controllers/docstats-controllers.js"></script> -<script src="dist/dist_js/plugins/graph/js/controllers/synchro-controllers.js"></script> -<!--endRemoveIf(ubuntu)--> - -<!-- Map plugin --> -<script src="dist/dist_js/plugins/map/js/plugin.js"></script> -<script src="dist/dist_js/plugins/map/js/services.js"></script> -<script src="dist/dist_js/plugins/map/js/services/wot-services.js"></script> -<script src="dist/dist_js/plugins/map/js/services/registry-services.js"></script> -<script src="dist/dist_js/plugins/map/js/services/utils-services.js"></script> -<script src="dist/dist_js/plugins/map/js/controllers/wot-controllers.js"></script> -<script src="dist/dist_js/plugins/map/js/controllers/registry-controllers.js"></script> -<script src="dist/dist_js/plugins/map/js/controllers/network-controllers.js"></script> -<script src="dist/dist_js/plugins/map/js/controllers/user-controllers.js"></script> -<script src="dist/dist_js/plugins/map/js/controllers/settings-controllers.js"></script> -<script src="dist/dist_js/plugins/map/js/controllers/help-controllers.js"></script> - -<!-- RML9 plugin --> -<!--<script src="dist/dist_js/plugins/rml9/plugin-01-add_button.js"></script>--> -<!--<script src="dist/dist_js/plugins/rml9/plugin-02-add_view.js"></script>--> -<!--<script src="dist/dist_js/plugins/rml9/plugin-03-file_export.js"></script>--> -<!--<script src="dist/dist_js/plugins/rml9/plugin-04-chart.js"></script>--> -<!--<script src="dist/dist_js/plugins/rml9/plugin-05-service_api.js"></script>--> -<!--<script src="dist/dist_js/plugins/rml9/plugin-06-settings.js"></script>--> -<!--<script src="dist/dist_js/plugins/rml9/plugin-07-add_map.js"></script>--> -<!--<script src="dist/dist_js/plugins/rml9/plugin-final.js"></script>--> - -<!--endRemoveIf(no-plugin)--> - -<!-- App --> -<script src="dist/dist_js/app/app.js"></script> -<script src="dist/dist_js/app/components.js"></script> -<script src="dist/dist_js/app/directives.js"></script> -<script src="dist/dist_js/app/filters.js"></script> -<script src="dist/dist_js/app/platform.js"></script> -<!-- endbuild --> - -<!-- build:js config.js --> -<!-- config --> -<script src="dist/dist_js/app/config.js"></script> -<!-- endbuild --> -</body> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="viewport-fit=cover,width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=yes,width=device-width,minimal-ui"> + + <title>Cesium</title> + <link rel="icon" href="img/favicon.ico"> + + <meta name="theme-color" content="black"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black"> + <link rel="apple-touch-icon" href="img/logo_57px.png"> + + <link rel="manifest" href="manifest.json"> + <!-- build:css dist_css/cesium.css --> + <link rel="stylesheet" type="text/css" href="css/ionic.app.css"> + <link rel="stylesheet" type="text/css" href="css/style.css"> + <link rel="stylesheet" type="text/css" href="lib/angular-image-crop/image-crop-styles.css"> + + + <!-- removeIf(no-plugin) --> + <link rel="stylesheet" type="text/css" href="css/leaflet.app.min.css"> + <link rel="stylesheet" type="text/css" href="lib/chart.js/dist/Chart.min.css"> + <link rel="stylesheet" type="text/css" href="dist/dist_css/plugins/es/css/style.css"> + <link rel="stylesheet" type="text/css" href="dist/dist_css/plugins/graph/css/style.css"> + <link rel="stylesheet" type="text/css" href="dist/dist_css/plugins/graph/css/style.css"> + <link rel="stylesheet" type="text/css" href="dist/dist_css/plugins/map/css/style.css"> + <!--endRemoveIf(no-plugin)--> + <!-- endbuild --> + + + + </head> + <body id="cesium" ng-strict-di="true" window-exit-unauth="true" ng-class="{'nobackdrop': $root.tour, 'expert-mode': $root.settings.expertMode}"> + <ion-nav-view> + <div class="loader"> + <h3 style="text-align: center; padding-top: 25px"><b>Cesium</b></h3> + <h4 style="text-align: center"><i class="icon ion-load-a"></i></h4> + </div> + </ion-nav-view> + + <!-- build:js dist_js/vendor.js --> + <!-- vendor js --> + <script src="lib/moment/min/moment-with-locales.min.js"></script> + + <script src="lib/numeral/numeral.js"></script> + <script src="lib/numeral/languages/fr.js"></script> + <script src="lib/numeral/languages/en-gb.js"></script> + <script src="lib/numeral/languages/nl-nl.js"></script> + <script src="lib/numeral/languages/es.js"></script> + <script src="lib/numeral/languages/it.js"></script> + <script src="js/vendor/numeral.eo.js"></script> + + <script src="lib/socket.io-client/dist/socket.io.min.js"></script> + <script src="lib/underscore/underscore-min.js"></script> + <script src="lib/qrcode.js/qrcode.js"></script> + + <script src="lib/aes-js/index.js"></script> + <script src="lib/chart.js/dist/Chart.min.js"></script> + + <!-- ionic/angular js --> + <script src="lib/ionic/js/ionic.js"></script> + <script src="lib/angular/angular.js"></script> + <script src="lib/angular-animate/angular-animate.js"></script> + <script src="lib/angular-sanitize/angular-sanitize.js"></script> + <script src="lib/angular-ui-router/release/angular-ui-router.js"></script> + <script src="lib/ionic/js/ionic-angular.js"></script> + <script src="lib/ionic-material/dist/ionic.material.js"></script> + <script src="lib/angular-resource/angular-resource.js"></script> + <script src="lib/angular-translate/angular-translate.js"></script> + <script src="lib/angular-messages/angular-messages.js"></script> + <script src="lib/angular-api/angular-api.js"></script> + <script src="lib/angular-cache/dist/angular-cache.js"></script> + <script src="lib/angular-screenmatch/dist/angular-screenmatch.min.js"></script> + <script src="lib/angular-bind-notifier/dist/angular-bind-notifier.min.js"></script> + <script src="lib/angular-image-crop/image-crop.js"></script> + <script src="lib/angular-file-saver/dist/angular-file-saver.bundle.js"></script> + <script src="lib/ng-idle/angular-idle.js"></script> + <script src="lib/angular-simple-logger/dist/angular-simple-logger.light.js"></script> + <script src="lib/ui-leaflet/dist/ui-leaflet.js"></script> + <script src="lib/ion-digit-keyboard/dist/ion-digit-keyboard.min.js"></script> + <script src="lib/angular-chart.js/dist/angular-chart.min.js"></script> + <script src="lib/angular-fullscreen/src/angular-fullscreen.js"></script> + + <script src="js/vendor/base58.js" async></script> + + <!--removeIf(no-device)--> + <script src="js/vendor/sha256.min.js" async></script> + <script src="lib/ngCordova/dist/ng-cordova.min.js"></script> + <!--endRemoveIf(no-device)--> + + <!--removeIf(no-plugin)--> + <script src="lib/leaflet/dist/leaflet.js"></script> + <script src="lib/leaflet.awesome-markers/dist/leaflet.awesome-markers.min.js"></script> + <script src="lib/leaflet-search/dist/leaflet-search.src.js"></script> + <script src="lib/Leaflet.EasyButton/src/easy-button.js"></script> + <script src="lib/leaflet.loading/src/Control.Loading.js"></script> + <script src="lib/leaflet.markercluster/dist/leaflet.markercluster.js"></script> + <script src="lib/Leaflet.FeatureGroup.SubGroup/leaflet.featuregroup.subgroup-src.js"></script> + <!--endRemoveIf(no-plugin)--> + + <!-- endbuild --> + + <!--removeIf(no-device)--> + <script src="cordova.js"></script> + <!--endRemoveIf(no-device)--> + + <!-- build:js dist_js/cesium.js --> + <!-- services --> + <script src="dist/dist_js/app/services/settings-services.js"></script> + <script src="dist/dist_js/app/services/network-services.js"></script> + <script src="dist/dist_js/app/services/crypto-services.js"></script> + <script src="dist/dist_js/app/services/utils-services.js"></script> + <script src="dist/dist_js/app/services/cache-services.js"></script> + <script src="dist/dist_js/app/services/modal-services.js"></script> + <script src="dist/dist_js/app/services/http-services.js"></script> + <script src="dist/dist_js/app/services/storage-services.js"></script> + <script src="dist/dist_js/app/services/device-services.js"></script> + <script src="dist/dist_js/app/services/currency-services.js"></script> + <script src="dist/dist_js/app/services/bma-services.js"></script> + <script src="dist/dist_js/app/services/wot-services.js"></script> + <script src="dist/dist_js/app/services/tx-services.js"></script> + <script src="dist/dist_js/app/services/wallet-services.js"></script> + <script src="dist/dist_js/app/services/help-services.js"></script> + <script src="dist/dist_js/app/services/plugin-services.js"></script> + + <script src="dist/dist_js/app/services.js"></script> + + <!-- entities --> + <script src="dist/dist_js/app/entities/peer.js"></script> + <script src="dist/dist_js/app/entities/block.js"></script> + <script src="dist/dist_js/app/entities/ws2pmessage.js"></script> + + <!-- controllers --> + <script src="dist/dist_js/app/controllers/app-controllers.js"></script> + <script src="dist/dist_js/app/controllers/join-controllers.js"></script> + <script src="dist/dist_js/app/controllers/login-controllers.js"></script> + <script src="dist/dist_js/app/controllers/help-controllers.js"></script> + <script src="dist/dist_js/app/controllers/wallet-controllers.js"></script> + <script src="dist/dist_js/app/controllers/wallets-controllers.js"></script> + <script src="dist/dist_js/app/controllers/wot-controllers.js"></script> + <script src="dist/dist_js/app/controllers/network-controllers.js"></script> + <script src="dist/dist_js/app/controllers/currency-controllers.js"></script> + <script src="dist/dist_js/app/controllers/transfer-controllers.js"></script> + <script src="dist/dist_js/app/controllers/settings-controllers.js"></script> + <script src="dist/dist_js/app/controllers/blockchain-controllers.js"></script> + <script src="dist/dist_js/app/controllers.js"></script> + + <!-- templates --> + <script src="dist/dist_js/app/templates.js"></script> + <script src="dist/dist_js/app/translations.js"></script> + + <!--removeIf(no-plugin)--> + <!-- Plugins --> + <script src="dist/dist_js/app/plugins.js"></script> + <script src="dist/dist_js/plugins/translations.js"></script> + <script src="dist/dist_js/plugins/templates.js"></script> + + <!-- ES plugin --> + <script src="dist/dist_js/plugins/es/js/plugin.js"></script> + <script src="dist/dist_js/plugins/es/js/entities/notification.js"></script> + <script src="dist/dist_js/plugins/es/js/entities/comment.js"></script> + <script src="dist/dist_js/plugins/es/js/entities/invitation.js"></script> + <script src="dist/dist_js/plugins/es/js/services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/comment-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/http-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/settings-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/registry-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/social-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/crypto-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/profile-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/notification-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/message-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/modal-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/blockchain-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/group-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/invitation-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/subscription-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/wallet-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/wot-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/tx-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/geo-services.js"></script> + <script src="dist/dist_js/plugins/es/js/services/document-services.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/common-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/app-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/settings-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/currency-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/wallet-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/wot-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/registry-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/profile-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/message-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/notification-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/blockchain-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/network-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/group-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/invitation-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/subscription-controllers.js"></script> + <script src="dist/dist_js/plugins/es/js/controllers/document-controllers.js"></script> + + <!-- Graph plugin --> + <!--removeIf(ubuntu)--> <!-- FIXME: issue #463 --> + <script src="dist/dist_js/plugins/graph/js/plugin.js"></script> + <script src="dist/dist_js/plugins/graph/js/services.js"></script> + <script src="dist/dist_js/plugins/graph/js/services/data-services.js"></script> + <script src="dist/dist_js/plugins/graph/js/services/color-services.js"></script> + <script src="dist/dist_js/plugins/graph/js/controllers/common-controllers.js"></script> + <script src="dist/dist_js/plugins/graph/js/controllers/blockchain-controllers.js"></script> + <script src="dist/dist_js/plugins/graph/js/controllers/network-controllers.js"></script> + <script src="dist/dist_js/plugins/graph/js/controllers/currency-controllers.js"></script> + <script src="dist/dist_js/plugins/graph/js/controllers/account-controllers.js"></script> + <script src="dist/dist_js/plugins/graph/js/controllers/docstats-controllers.js"></script> + <script src="dist/dist_js/plugins/graph/js/controllers/synchro-controllers.js"></script> + <!--endRemoveIf(ubuntu)--> + + <!-- Map plugin --> + <script src="dist/dist_js/plugins/map/js/plugin.js"></script> + <script src="dist/dist_js/plugins/map/js/services.js"></script> + <script src="dist/dist_js/plugins/map/js/services/wot-services.js"></script> + <script src="dist/dist_js/plugins/map/js/services/registry-services.js"></script> + <script src="dist/dist_js/plugins/map/js/services/utils-services.js"></script> + <script src="dist/dist_js/plugins/map/js/controllers/wot-controllers.js"></script> + <script src="dist/dist_js/plugins/map/js/controllers/registry-controllers.js"></script> + <script src="dist/dist_js/plugins/map/js/controllers/network-controllers.js"></script> + <script src="dist/dist_js/plugins/map/js/controllers/user-controllers.js"></script> + <script src="dist/dist_js/plugins/map/js/controllers/settings-controllers.js"></script> + <script src="dist/dist_js/plugins/map/js/controllers/help-controllers.js"></script> + + <!-- RML9 plugin --> + <!--<script src="dist/dist_js/plugins/rml9/plugin-01-add_button.js"></script>--> + <!--<script src="dist/dist_js/plugins/rml9/plugin-02-add_view.js"></script>--> + <!--<script src="dist/dist_js/plugins/rml9/plugin-03-file_export.js"></script>--> + <!--<script src="dist/dist_js/plugins/rml9/plugin-04-chart.js"></script>--> + <!--<script src="dist/dist_js/plugins/rml9/plugin-05-service_api.js"></script>--> + <!--<script src="dist/dist_js/plugins/rml9/plugin-06-settings.js"></script>--> + <!--<script src="dist/dist_js/plugins/rml9/plugin-07-add_map.js"></script>--> + <!--<script src="dist/dist_js/plugins/rml9/plugin-final.js"></script>--> + + <!--endRemoveIf(no-plugin)--> + + <!-- App --> + <script src="dist/dist_js/app/app.js"></script> + <script src="dist/dist_js/app/components.js"></script> + <script src="dist/dist_js/app/directives.js"></script> + <script src="dist/dist_js/app/filters.js"></script> + <script src="dist/dist_js/app/platform.js"></script> + <!-- endbuild --> + + <!-- build:js config.js --> + <!-- config --> + <script src="dist/dist_js/app/config.js"></script> + <!-- endbuild --> + </body> </html> diff --git a/assets/www/js/api/app.js b/assets/www/js/api/app.js index 44aa8a1af6b5bf037eed4a2d4d000d01ae5f33bc..cf809a253e7cff1303fd06760bec2faeefd23496 100644 --- a/assets/www/js/api/app.js +++ b/assets/www/js/api/app.js @@ -5,6 +5,7 @@ // the 2nd parameter is an array of 'requires' // 'starter.controllers' is found in controllers.js angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht.translate', 'ngApi', 'angular-cache', 'angular.screenmatch', + 'FBAngular', // = angular-fullscreen // removeIf(no-device) 'ngCordova', // endRemoveIf(no-device) @@ -25,7 +26,7 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr }) .state('app.home', { - url: "/home?result&service&cancel", + url: "/home?result&service&cancel&node", views: { 'menuContent': { templateUrl: "templates/api/home.html", @@ -43,7 +44,7 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr .state('api.transfer', { cache: false, - url: "/payment/:pubkey?name&amount&udAmount&comment&redirect_url&cancel_url&demo", + url: "/payment/:pubkey?name&amount&udAmount&comment&preferred_node&redirect_url&cancel_url&demo&error", views: { 'menuContent': { templateUrl: "templates/api/transfer.html", @@ -56,9 +57,11 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr $urlRouterProvider.otherwise('/app/home'); }) - .controller('ApiCtrl', function ($scope, $state, $translate, $ionicPopover, Modals, csSettings){ + .controller('ApiCtrl', function ($scope, $state, $translate, $ionicPopover, UIUtils, Modals, csSettings){ 'ngInject'; + // Fill locales + $scope.locales = angular.copy(csSettings.locales); $scope.showAboutModal = function(e) { e.preventDefault(); // avoid to open link href @@ -78,29 +81,20 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr /* -- show/hide locales popup -- */ $scope.showLocalesPopover = function(event) { - if (!$scope.localesPopover) { - // Fill locales - $scope.locales = angular.copy(csSettings.locales); - - $ionicPopover.fromTemplateUrl('templates/api/locales_popover.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/api/locales_popover.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.localesPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.localesPopover.remove(); - }); - $scope.localesPopover.show(event); - }); - } - else { - $scope.localesPopover.show(event); - } + } + }); }; $scope.hideLocalesPopover = function() { if ($scope.localesPopover) { $scope.localesPopover.hide(); + $scope.localesPopover = null; } }; }) @@ -114,7 +108,8 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr amount: 100, comment: 'REFERENCE', name: 'www.domain.com', - redirect_url: 'http://www.domain.com/payment?ref={comment}&tx={tx}', + preferred_node: undefined, + redirect_url: 'http://www.domain.com/payment?ref={comment}&tx={tx}&node={node}', cancel_url: 'http://www.domain.com/payment?ref={comment}&cancel' }; $scope.transferButton = { @@ -152,7 +147,7 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr $scope.transferButton.style.icon = $scope.transferButton.icons[1/*Duniter icon*/]; $scope.transferDemoUrl = $rootScope.rootPath + $state.href('api.transfer', angular.merge({}, $scope.transferData, { demo: true, - redirect_url: $rootScope.rootPath + '#/app/home?service=payment&result={tx}', + redirect_url: $rootScope.rootPath + '#/app/home?service=payment&result={tx}&node={node}', cancel_url: $rootScope.rootPath + '#/app/home?service=payment&cancel' })); @@ -169,6 +164,9 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr if (state.stateParams && state.stateParams.cancel) { $scope.result.cancelled = true; } + if (state.stateParams && state.stateParams.node) { + $scope.result.node = state.stateParams.node; + } csCurrency.get() .then(function(currency) { @@ -231,7 +229,8 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr }) .controller('ApiTransferCtrl', function ($scope, $rootScope, $timeout, $controller, $state, $q, $translate, $filter, - BMA, CryptoUtils, UIUtils, csCurrency, csTx, csWallet, csDemoWallet){ + $window, $ionicHistory, BMA, CryptoUtils, UIUtils, csSettings, csCurrency, + csPlatform, csTx, csWallet, csDemoWallet){ 'ngInject'; // Initialize the super class and extend it. @@ -240,16 +239,41 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr $scope.loading = true; $scope.transferData = { amount: undefined, + amounts: undefined, comment: undefined, pubkey: undefined, name: undefined, redirect_url: undefined, - cancel_url: undefined + cancel_url: undefined, + node: undefined }; $scope.enter = function(e, state) { + $rootScope.errorState = state.stateName; + + if (!$scope.loading) return; // already enter + if (state.stateParams && state.stateParams.amount) { - $scope.transferData.amount = parseFloat(state.stateParams.amount.replace(new RegExp('[.,]'), '.')).toFixed(2) * 100; + var amountStr = state.stateParams.amount.trim(); + var amounts = ((amountStr.indexOf('|') !== -1) && amountStr.split('|')) + || ((amountStr.indexOf(' ') !== -1) && amountStr.split(' ')) + || ((amountStr.indexOf(';') !== -1) && amountStr.split(';')); + if (amounts){ + $scope.transferData.amounts = amounts.reduce(function(res, amountStr) { + var amount = normalizeAmount(amountStr); + return amount > 0 ? res.concat(amount) : res; + }, []); + if ($scope.transferData.amounts.length === 1) { + $scope.transferData.amount = $scope.transferData.amounts[0]; + delete $scope.transferData.amounts; + } + else { + $scope.transferData.amounts.sort(); + } + } + else { + $scope.transferData.amount = normalizeAmount(amountStr); + } } if (state.stateParams && state.stateParams.pubkey) { $scope.transferData.pubkey = state.stateParams.pubkey; @@ -269,27 +293,127 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr if (state.stateParams && state.stateParams.demo) { $scope.demo = true; } + + if (state.stateParams && state.stateParams.preferred_node) { + var + isHttpsMode = $window.location.protocol === 'https:', + useSsl = isHttpsMode, + preferredNode = state.stateParams.preferred_node; + var matches = /^(?:(http[s]?:)\/\/)(.*)$/.exec(preferredNode); + if (matches) { + useSsl = matches[1] === 'https:'; + preferredNode = matches[2]; + } + var parts = preferredNode.split(':'); + if (parts.length >= 1) { + var port = parts[1] || (useSsl ? 443 : 80); + $scope.node = { + host: parts[0], + port: port, + useSsl: useSsl || (port == 443) + }; + + // Add a fallback node that use SSL + if (!$scope.node.useSsl) { + var node = angular.copy($scope.node); + node.useSsl = true; + node.port = 443; + csSettings.data.fallbackNodes = csSettings.data.fallbackNodes || []; + csSettings.data.fallbackNodes.splice(0,0,node); + } + } + else { + console.warn("[api] Invalid preferred node address: {0}. Using default node." + state.stateParams.preferred_node); + } + } + + // Start + return $scope.start(); }; $scope.$on('$ionicView.enter', $scope.enter); + + $scope.start = function() { + if ($scope.starting) return; + + $scope.starting = true; + $scope.loading = true; + + // Set BMA node + if (!$scope.error && $scope.node && !BMA.node.same($scope.node.host, $scope.node.port)) { + console.debug("[api] Using preferred node: {0}:{1}".format($scope.node.host, $scope.node.port)); + BMA.stop(); + BMA.copy($scope.node); + $scope.node.server = BMA.server; + } + + // Start platform (or restart) platform + // This will start the BMA node + return csPlatform.restart() + .then(csCurrency.get) + .then(function(currency) { + $scope.currency = currency; + $scope.node = currency.node; + $scope.loading = false; + $scope.error = false; + $scope.starting = false; + // Reset history cache + $ionicHistory.clearCache(); + }) + // Error during load (BMA not alive ?) + .catch(function(err) { + console.error(err && err.message || err); + $scope.error = true; + $scope.loading = false; + $scope.starting = false; + + // Make sure to retry if user choose a fallback node + var unsubscribe = BMA.api.node.on.start($scope, function() { + $scope.start(); + unsubscribe(); + }); + }) + ; + }; + + function normalizeAmount(amountStr) { + return parseFloat((amountStr||'0').trim().replace(new RegExp('[.,]'), '.')).toFixed(2) * 100; + } + function onLogin(authData) { // User cancelled if (!authData) return $scope.onCancel(); + // Make sure amount require fields + if (!$scope.transferData.amount || !$scope.transferData.pubkey) { + $scope.form.$submitted=true; + UIUtils.loading.hide(); + return $q.reject(); + } + // Avoid multiple click if ($scope.sending) return; $scope.sending = true; + delete $scope.transferData.error; var wallet = $scope.demo ? csDemoWallet.instance(authData) : csWallet.instance('api', BMA); UIUtils.loading.show(); - wallet.start({restore: false}/*skip restore from local storage*/) + wallet.start({restore: false/*skip restore from local storage*/}) .then(function() { - return wallet.login({auth: true, authData: authData}); + return wallet.login({ + auth: true, + authData: authData, + minData: true, + sources: true, + tx: {enable: false} + }); }) .then(function(walletData) { + if (!walletData) return; + $scope.login = true; UIUtils.loading.hide(); @@ -367,8 +491,9 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr url = url.replace(/\{pubkey\}/g, $scope.transferData.pubkey); url = url.replace(/\{hash\}/g, txRes.hash||''); url = url.replace(/\{comment\}/g, $scope.transferData.comment||''); - url = url.replace(/\{amount\}/g, $scope.transferData.amount.toString()); + url = url.replace(/\{amount\}/g, $scope.transferData.amount && ($scope.transferData.amount/100).toString() || ''); url = url.replace(/\{tx\}/g, encodeURI(txRes.tx)); + url = url.replace(/\{node\}/g, encodeURI(BMA.host+':'+BMA.port)); return $scope.redirectToUrl(url, 2500); }); @@ -390,7 +515,7 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr // Make replacements - fix #548 url = url.replace(/\{pubkey\}/g, $scope.transferData.pubkey); url = url.replace(/\{comment\}/g, $scope.transferData.comment||''); - url = url.replace(/\{amount\}/g, $scope.transferData.amount.toString()); + url = url.replace(/\{amount\}/g, $scope.transferData.amount && ($scope.transferData.amount/100).toString() || ''); return $scope.redirectToUrl(url, 1500); }); @@ -416,16 +541,18 @@ angular.module('cesium-api', ['ionic', 'ionic-material', 'ngMessages', 'pascalpr /* -- methods need by Login controller -- */ - $scope.setForm = function(form) { - $scope.form = form; - }; $scope.closeModal = onLogin; }) - .run(function(csPlatform) { + .run(function(csSettings) { 'ngInject'; - csPlatform.start(); + csSettings.data.rememberMe = false; + csSettings.data.useLocalStorage = false; + // Force auth idle to 30s + csSettings.data.keepAuthIdle = 30; + + //csPlatform.start(); }) ; diff --git a/assets/www/js/app.js b/assets/www/js/app.js index ae3b11533a95fd58b83c51db4c8e0b2a817bd751..2c8db1246555b2660c1bdfc0c854adbb49de1518 100644 --- a/assets/www/js/app.js +++ b/assets/www/js/app.js @@ -4,8 +4,9 @@ // 'starter' is the name of this angular module example (also set in a <body> attribute in index.html) // the 2nd parameter is an array of 'requires' // 'starter.controllers' is found in controllers.js -angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht.translate', +angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'ngSanitize', 'pascalprecht.translate', 'ngApi', 'angular-cache', 'angular.screenmatch', 'angular.bind.notifier', 'ImageCropper', 'ion-digit-keyboard', + 'FBAngular', // = angular-fullscreen // removeIf(no-device) 'ngCordova', // endRemoveIf(no-device) @@ -27,9 +28,6 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht Device, UIUtils, $ionicConfig, PluginService, csPlatform, csWallet) { 'ngInject'; - // Allow access to service data, from HTML templates - $rootScope.walletData = csWallet.data; - // Must be done before any other $stateChangeStart listeners csPlatform.disableChangeState(); @@ -60,8 +58,12 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht // endRemoveIf(ios) // endRemoveIf(android) + var wallet = nextParams.wallet && nextParams.wallet != "default" ? csWallet.children.get(nextParams.wallet) : csWallet; + if (nextParams.wallet && !wallet) { + console.warn("[app] Unable to find the children wallet: " + nextParams.wallet); + } // If state need auth - if (next.data.auth && !csWallet.isAuth()) { + if (next.data.auth && !wallet.isAuth()) { event.preventDefault(); options = next.data.minData ? {minData: true} : undefined; preventStateChange = true; @@ -73,7 +75,7 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht .catch(function(err) { preventStateChange = false; // If cancel, redirect to home, if no current state - if (err == 'CANCELLED' && !$state.current.name) { + if (err === 'CANCELLED' && !$state.current.name) { return $state.go('app.home'); } }); @@ -92,7 +94,7 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht .catch(function(err) { preventStateChange = false; // If cancel, redirect to home, if no current state - if (err == 'CANCELLED' && !$state.current.name) { + if (err === 'CANCELLED' && !$state.current.name) { return $state.go('app.home'); } }); @@ -101,11 +103,11 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht // If state need login or auth, make sure to load wallet data else if (next.data.login || next.data.auth) { options = next.data.minData ? {minData: true} : undefined; - if (!csWallet.isDataLoaded(options)) { + if (!wallet.isDataLoaded(options)) { event.preventDefault(); // Show loading message, when full load if (!options || !options.minData) UIUtils.loading.show(); - return csWallet.loadData(options) + return wallet.loadData(options) .then(function() { preventStateChange = false; return $state.go(next.name, nextParams); @@ -129,10 +131,24 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht if (sameUrl) event.preventDefault(); } }); + // Configures $urlRouter's listener *after* the previous listener $urlRouter.listen(); // Start plugins eager services PluginService.start(); + + ionicReady().then(function() { + if (ionic.Platform.isIOS()) { + if(window.StatusBar) { + // fix font color not white on iOS 11+ + StatusBar.styleLightContent(); + } + } + }); }) ; + +window.ionic.Platform.ready(function() { + angular.bootstrap(document, ['cesium']); +}); diff --git a/assets/www/js/config.js b/assets/www/js/config.js index 79a743c695ec21539ae6ca89ff9aa02f96101444..57d256481f63d4c50d46fafce1e5412a3e99c9cf 100644 --- a/assets/www/js/config.js +++ b/assets/www/js/config.js @@ -13,10 +13,10 @@ angular.module("cesium.config", []) "fallbackLanguage": "en", "rememberMe": true, "showUDHistory": true, - "timeout": 30000, + "timeout": 40000, "timeWarningExpireMembership": 5184000, "timeWarningExpire": 7776000, - "keepAuthIlde": 600, + "keepAuthIdle": 600, "useLocalStorage": true, "useRelative": false, "expertMode": false, @@ -31,21 +31,34 @@ angular.module("cesium.config", []) } }, "license": { + "en": "license/license_g1-en", "fr-FR": "license/license_g1-fr-FR", - "en": "license/license_g1-en" + "es-ES": "license/license_g1-es-ES" }, "node": { "host": "g1.duniter.org", - "port": "443" + "port": 443 }, "fallbackNodes": [ { - "host": "g1.duniter.fr", - "port": "443" + "host": "g1.nordstrom.duniter.org", + "port": 443 + }, + { + "host": "g1.cgeek.fr", + "port": 443 + }, + { + "host": "g1.monnaielibreoccitanie.org", + "port": 443 + }, + { + "host": "g1.le-sou.org", + "port": 443 }, { - "host": "g1.duniter.org", - "port": "443" + "host": "g1.duniter.fr", + "port": 443 } ], "developers": [ @@ -58,16 +71,17 @@ angular.module("cesium.config", []) "es": { "enable": true, "askEnable": true, + "useRemoteStorage": true, "host": "g1.data.duniter.fr", - "port": "443", + "port": 443, "fallbackNodes": [ { "host": "g1.data.le-sou.org", - "port": "443" + "port": 443 }, { "host": "g1.data.duniter.fr", - "port": "443" + "port": 443 } ], "notifications": { @@ -79,9 +93,9 @@ angular.module("cesium.config", []) "defaultCountry": "France" } }, - "version": "1.0.6", - "build": "2018-05-09T15:28:09.984Z", - "newIssueUrl": "https://git.duniter.org/clients/cesium/cesium/issues/new" + "version": "1.4.15", + "build": "2019-12-27T19:43:48.157Z", + "newIssueUrl": "https://git.duniter.org/clients/cesium-grp/cesium/issues/new" }) ; \ No newline at end of file diff --git a/assets/www/js/controllers.js b/assets/www/js/controllers.js index a612166287398398363b2d659baf4dfc0c8f2367..5ed49c51576e0032ddf87bf2b62cfbc130b8b201 100644 --- a/assets/www/js/controllers.js +++ b/assets/www/js/controllers.js @@ -5,6 +5,7 @@ angular.module('cesium.controllers', [ 'cesium.login.controllers', 'cesium.help.controllers', 'cesium.wallet.controllers', + 'cesium.wallets.controllers', 'cesium.currency.controllers', 'cesium.wot.controllers', 'cesium.transfer.controllers', diff --git a/assets/www/js/controllers/app-controllers.js b/assets/www/js/controllers/app-controllers.js index 7a5c7f6b617f6f38c148b0a2893744db5214ba55..c2e765ce192f42574ed5c979a603fd8b709374b0 100644 --- a/assets/www/js/controllers/app-controllers.js +++ b/assets/www/js/controllers/app-controllers.js @@ -64,15 +64,17 @@ function PluginExtensionPointController($scope, PluginService) { * Abstract controller (inherited by other controllers) */ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $timeout, - $ionicHistory, $controller, $window, csPlatform, CryptoUtils, + $ionicHistory, $controller, $window, csPlatform, CryptoUtils, csCrypto, UIUtils, BMA, csWallet, Device, Modals, csConfig, csHttp ) { 'ngInject'; + $scope.walletData = csWallet.data; $scope.search = {}; $scope.login = csWallet.isLogin(); $scope.auth = csWallet.isAuth(); $scope.motion = UIUtils.motion.default; + $scope.fullscreen = UIUtils.screen.fullscreen.isEnabled(); $scope.showHome = function() { $ionicHistory.nextViewOptions({ @@ -82,78 +84,81 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ .then(UIUtils.loading.hide); }; + // removeIf(no-device) //////////////////////////////////////// - // Device Methods + // Device only methods + // (code removed when NO device) //////////////////////////////////////// $scope.scanQrCodeAndGo = function() { - if (!Device.barcode.enable) { - return; - } - Device.barcode.scan() + + if (!Device.barcode.enable) return; + + // Run scan cordova plugin, on device + return Device.barcode.scan() .then(function(data) { if (!data) return; - BMA.uri.parse(data) - .then(function(result){ - // If pubkey - if (result && result.pubkey) { - $state.go('app.wot_identity', { - pubkey: result.pubkey, - node: result.host ? result.host: null} - ); - } - else { - UIUtils.alert.error(result, 'ERROR.SCAN_UNKNOWN_FORMAT'); - } + + // Try to parse as an URI + return BMA.uri.parse(data) + .then(function(res){ + if (!res || !res.pubkey) throw {message: 'ERROR.SCAN_UNKNOWN_FORMAT'}; + // If pubkey: open the identity + return $state.go('app.wot_identity', { + pubkey: res.pubkey, + node: res.host ? res.host: null} + ); }) + + // Not an URI: try WIF or EWIF format .catch(function(err) { + console.debug("[app] Scan data is not an URI (get error: " + (err && err.message || err) + "). Trying to decode as a WIF or EWIF format..."); // Try to read as WIF format - var keypairPromise; - try { - keypairPromise = Promise.resolve(CryptoUtils.keypair_from_wif_v1(data)); - } catch(err2) { /*silent*/ } - - // Try to read as EWIF format - if (!keypairPromise) { - try { - CryptoUtils.keypair_from_ewif_v1(data); - } catch(err2) { - if (err && (err == 'NEED_PASSWORD' || (err == 'BAD_PASSWORD'))) { - keypairPromise = Modals.showPassword({ - title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', - subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP' - }) - .then(function(password) { - if (!password) throw 'CANCELLED'; - return CryptoUtils.keypair_from_ewif_v1(data, password); + return csCrypto.keyfile.parseData(data) + .then(function(keypair) { + if (!keypair || !keypair.signPk || !keypair.signSk) throw err; // rethrow the first error (e.g. Bad URI) + + var pubkey = CryptoUtils.base58.encode(keypair.signPk); + console.debug("[app] Detected WIF/EWIF format. Will login to wallet {" + pubkey.substring(0, 8) + "}"); + + // Create a new wallet (if default wallet is already used) + var wallet = !csWallet.isLogin() ? csWallet : csWallet.children.create({store: false}); + + // Login using keypair + return wallet.login({ + silent: true, + forceAuth: true, + minData: false, + authData: { + pubkey: pubkey, + keypair: keypair + } + }) + .then(function () { + + // Open transfer all wallet + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + return $state.go('app.new_transfer', { + all: true, // transfer all sources + wallet: !wallet.isDefault() ? wallet.id : undefined }); - } - } - } - if (keypairPromise) { - keypairPromise.then(function(keypair) { - return csWallet.login({ - forceAuth: true, - authData: { - pubkey: CryptoUtils.base58.encode(keypair.signPk), - keypair: keypair - } - }) - .catch(UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')) - .then(function (res) { - if (res) return $state.go('app.view_wallet'); - }); - }); - } - else { - UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')(err); - } + }); + }) + // Unknown format (nor URI, nor WIF/EWIF) + .catch(UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')); }); }) .catch(UIUtils.onError('ERROR.SCAN_FAILED')); }; + //////////////////////////////////////// + // End of device only methods + //////////////////////////////////////// + // endRemoveIf(no-device) + //////////////////////////////////////// // Show Help tour //////////////////////////////////////// @@ -199,44 +204,27 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ return $scope.login; }; - $scope.showProfilePopover = function(event) { - return UIUtils.popover.show(event, { - templateUrl :'templates/common/popover_profile.html', - scope: $scope, - autoremove: true, - afterShow: function(popover) { - $scope.profilePopover = popover; - $timeout(function() { - UIUtils.ink({selector: '#profile-popover .ink, #profile-popover .ink-dark'}); - }, 100); - } - }); - }; - - $scope.closeProfilePopover = function() { - if ($scope.profilePopover && $scope.profilePopover.isShown()) { - $timeout(function(){$scope.profilePopover.hide();}); - } - }; - // Load wallet data (after login) $scope.loadWalletData = function(options) { - return csWallet.loadData(options) + + console.warn("[app-controller] DEPRECATED - Please use csWallet.load() instead of $scope.loadWalletData()", new Error()); + + options = options || {}; + var wallet = options.wallet || csWallet; + return wallet.loadData(options) .then(function(walletData) { - if (walletData) { - $rootScope.walletData = walletData; - return walletData; - } - else { // cancel login - throw 'CANCELLED'; - } + // cancel login + if (!walletData) throw 'CANCELLED'; + return walletData; }); }; // Login and load wallet $scope.loadWallet = function(options) { + console.warn("[app-controller] DEPRECATED - Please use csWallet.loginOrLoad() instead of $scope.loadWallet()", new Error()); + // Make sure the platform is ready if (!csPlatform.isStarted()) { return csPlatform.ready().then(function(){ @@ -246,9 +234,11 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ options = options || {}; + var wallet = options.wallet || csWallet; + // If need auth - if (options.auth && !csWallet.isAuth()) { - return csWallet.auth(options) + if (options.auth && !wallet.isAuth()) { + return wallet.auth(options) .then(function (walletData) { if (walletData) return walletData; // failed to auth @@ -257,8 +247,8 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ } // If need login - else if (!csWallet.isLogin()) { - return csWallet.login(options) + else if (!wallet.isLogin()) { + return wallet.login(options) .then(function (walletData) { if (walletData) return walletData; // failed to login @@ -267,21 +257,24 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ } // Already login or auth - else if (!csWallet.isDataLoaded(options)) { + else if (!wallet.isDataLoaded(options)) { return $scope.loadWalletData(options); } else { - return $q.when(csWallet.data); + return $q.when(wallet.data); } }; // Login and go to a state (or wallet if not) $scope.loginAndGo = function(state, options) { $scope.closeProfilePopover(); + options = options || {}; + var wallet = options.wallet || csWallet; + delete options.wallet; state = state || 'app.view_wallet'; - if (!csWallet.isLogin()) { + if (!wallet.isLogin()) { // Make sure to protect login modal, if HTTPS enable - fix #340 if (csConfig.httpsMode && $window.location && $window.location.protocol !== 'https:') { @@ -291,17 +284,16 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ rootPath = 'https' + rootPath.substr(4); href = rootPath + $state.href(state); if (csConfig.httpsModeDebug) { + // Debug mode: just log, then continue console.debug('[httpsMode] --- Should redirect to: ' + href); - // continue } else { $window.location.href = href; return; } - } - return csWallet.login(options) + return wallet.login(options) .then(function(){ return $state.go(state, options); }) @@ -315,6 +307,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ // Logout $scope.logout = function(options) { options = options || {}; + var wallet = options.wallet || csWallet; if (!options.force && $scope.profilePopover) { // Make the popover if really closed, to avoid UI refresh on popover buttons return $scope.profilePopover.hide() @@ -334,28 +327,33 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ } UIUtils.loading.show(); - return csWallet.logout() + return wallet.logout() .then(function() { // Close left menu if open if ($ionicSideMenuDelegate.isOpenLeft()) { $ionicSideMenuDelegate.toggleLeft(); } - $ionicHistory.clearHistory(); - return $ionicHistory.clearCache() - .then(function() { - return $scope.showHome(); - }); + // If default wallet: clear navigation history, then go back to home + if (wallet.isDefault()) { + $ionicHistory.clearHistory(); + + return $ionicHistory.clearCache() + .then(function() { + return $scope.showHome(); + }); + } + else { + + } }) .catch(UIUtils.onError()); }; - - // Login and go to a state (or wallet if not) - $scope.doAuth = function() { - return $scope.loadWallet({auth: true}) - .then(function() { - UIUtils.loading.hide(); - }); + // Do authentification + $scope.doAuth = function(options) { + var wallet = options && options.wallet || csWallet; + return wallet.auth() + .then(UIUtils.loading.hide); }; // If connected and same pubkey @@ -364,20 +362,16 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }; // add listener on wallet event - csWallet.api.data.on.login($scope, function(walletData, deferred) { + csWallet.api.data.on.login($scope, function(data, deferred) { $scope.login = true; - $rootScope.walletData = walletData || {}; return deferred ? deferred.resolve() : $q.when(); }); csWallet.api.data.on.logout($scope, function() { $scope.login = false; - $rootScope.walletData = {}; }); csWallet.api.data.on.auth($scope, function(data, deferred) { - deferred = deferred || $q.defer(); $scope.auth = true; - deferred.resolve(); - return deferred.promise; + return deferred ? deferred.resolve() : $q.when(); }); csWallet.api.data.on.unauth($scope, function() { $scope.auth = false; @@ -411,10 +405,30 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }; //////////////////////////////////////// - // Change node (expert mode) + // Useful popovers //////////////////////////////////////// - $scope.showNodeListPopover = function(event) { + $scope.showProfilePopover = function(event) { + return UIUtils.popover.show(event, { + templateUrl :'templates/common/popover_profile.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.profilePopover = popover; + $timeout(function() { + UIUtils.ink({selector: '#profile-popover .ink, #profile-popover .ink-dark'}); + }, 100); + } + }); + }; + + $scope.closeProfilePopover = function() { + if ($scope.profilePopover && $scope.profilePopover.isShown()) { + $timeout(function(){$scope.profilePopover.hide();}); + } + }; + // Change peer info + $scope.showPeerInfoPopover = function(event) { return UIUtils.popover.show(event, { templateUrl: 'templates/network/popover_peer_info.html', autoremove: true, @@ -423,10 +437,13 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }; //////////////////////////////////////// - // Link managment (fix issue #) + // Link management (fix issue #) //////////////////////////////////////// $scope.openLink = function($event, uri, options) { + $event.stopPropagation(); + $event.preventDefault(); + options = options || {}; // If unable to open, just copy value @@ -434,8 +451,9 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ return UIUtils.popover.copy($event, uri); }; - $event.stopPropagation(); - return csHttp.uri.open(uri, options); + csHttp.uri.open(uri, options); + + return false; }; //////////////////////////////////////// @@ -454,16 +472,54 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ return $scope.motion.show(options); }; + + //////////////////////////////////////// + // Fullscreen mode + //////////////////////////////////////// + + $scope.askFullscreen = function() { + var skip = $scope.fullscreen || !UIUtils.screen.isSmall() || !Device.isWeb(); + if (skip) return; + + return UIUtils.alert.confirm('CONFIRM.FULLSCREEN', null, { + cancelText: 'COMMON.BTN_NO', + okText: 'COMMON.BTN_YES' + }) + .then(function(confirm) { + if (!confirm) return; + $scope.toggleFullscreen(); + }); + }; + + $scope.toggleFullscreen = function() { + $scope.fullscreen = !UIUtils.screen.fullscreen.isEnabled(); + UIUtils.screen.fullscreen.toggleAll(); + }; + + // removeIf(device) + // Ask switching fullscreen + $scope.askFullscreen(); + // endRemoveIf(device) } -function HomeController($scope, $state, $timeout, $ionicHistory, csPlatform, csCurrency) { +function HomeController($scope, $state, $timeout, $ionicHistory, $translate, UIUtils, csPlatform, csCurrency, csSettings) { 'ngInject'; $scope.loading = true; + $scope.locales = angular.copy(csSettings.locales); $scope.enter = function(e, state) { - if (state && state.stateParams && state.stateParams.error) { // Query parameter + if (ionic.Platform.isIOS()) { + if(window.StatusBar) { + // needed to fix Xcode 9 / iOS 11 issue with blank space at bottom of webview + // https://github.com/meteor/meteor/issues/9041 + StatusBar.overlaysWebView(false); + StatusBar.overlaysWebView(true); + } + } + + if (state && state.stateParams && state.stateParams.error) { // Error query parameter $scope.error = state.stateParams.error; $scope.node = csCurrency.data.node; $scope.loading = false; @@ -512,6 +568,32 @@ function HomeController($scope, $state, $timeout, $ionicHistory, csPlatform, csC } }; + $scope.changeLanguage = function(langKey) { + $translate.use(langKey); + $scope.hideLocalesPopover(); + csSettings.data.locale = _.findWhere($scope.locales, {id: langKey}); + }; + + /* -- show/hide locales popup -- */ + + $scope.showLocalesPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'templates/api/locales_popover.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.localesPopover = popover; + } + }); + }; + + $scope.hideLocalesPopover = function() { + if ($scope.localesPopover) { + $scope.localesPopover.hide(); + $scope.localesPopover = null; + } + }; + // For DEV ONLY /*$timeout(function() { $scope.loginAndGo(); diff --git a/assets/www/js/controllers/blockchain-controllers.js b/assets/www/js/controllers/blockchain-controllers.js index d821f1acf6f83089a5c7248e9ec6090ff0d8a6a3..efd8e141c1b8840d7b480972446c3d2957ae466a 100644 --- a/assets/www/js/controllers/blockchain-controllers.js +++ b/assets/www/js/controllers/blockchain-controllers.js @@ -107,6 +107,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho $scope.ionItemClass = 'item-border-large'; $scope.defaultSizeLimit = UIUtils.screen.isSmall() ? 50 : 100; $scope.helptipPrefix = 'helptip-network'; + $scope.listeners = []; /** * Enter into the view @@ -185,14 +186,14 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho } // endRemoveIf(device) - $scope.startListenBlock(); + $scope.addListeners(); $scope.entered = true; $scope.showHelpTip(); } else { - $scope.startListenBlock(); + $scope.addListeners(); } }; //$scope.$on('$ionicView.enter', $scope.enter); @@ -205,11 +206,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho * @param state */ $scope.leave = function() { - if ($scope.wsBlock) { - console.debug('[block] Stopping websocket [/ws/block]'); - $scope.wsBlock.close(); - delete $scope.wsBlock; - } + $scope.removeListeners(); }; //$scope.$on('$ionicView.leave', $scope.leave); $scope.$on('$ionicParentView.leave', $scope.leave); @@ -235,7 +232,7 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho var size = current.number < $scope.defaultSizeLimit ? current.number : $scope.defaultSizeLimit; return $scope.node.blockchain.blocksSlice({count: size, from: current.number-size}) .then(function(blocks) { - blocks.splice(0,0,current); + if (!!blocks) blocks.splice(0,0,current); return blocks; }); }) @@ -334,12 +331,12 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho $scope.smallscreen = UIUtils.screen.isSmall(); + $scope.$broadcast('$$rebind::rebind'); // notify binder + // Set Motion if (res && res.length) { $scope.motion.show({selector: '.list-blocks .item-block'}); } - - $scope.$broadcast('$$rebind::rebind'); // notify binder }; $scope.showMore = function() { @@ -360,22 +357,35 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho }); }; - $scope.startListenBlock = function() { - if (!$scope.wsBlock) { - if ($scope.node == BMA) { - csCurrency.api.data.on.newBlock($scope, $scope.onBlock); - } - else { - console.debug('[block] Listening on websocket [/ws/block]'); - $scope.wsBlock = $scope.node.websocket.block(); - $scope.wsBlock.on(function(json) { + $scope.removeListeners = function() { + if ($scope.listeners.length) { + console.debug("[block] Closing listeners"); + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + } + }; + + $scope.addListeners = function() { + if ($scope.listeners.length) return; // already started + + console.debug("[block] Starting listeners"); + if ($scope.node === BMA) { + $scope.listeners = [ + csCurrency.api.data.on.newBlock($scope, $scope.onBlock) + ]; + } + else { + $scope.listeners = [ + $scope.node.websocket.block().onListener(function(json) { // Skip if WS closed (after leave view - should never happen) or invalid json - if (!$scope.wsBlock || !json) return; + if (!json) return; var block = new Block(json); block.cleanData(); // Remove unused content (arrays...) $scope.onBlock(block); - }); - } + }) + ]; } }; @@ -692,29 +702,20 @@ function BlockViewController($scope, $ionicPopover, $state, UIUtils, BMA, csCurr $scope.popoverData.unlockConditions = $scope.toUnlockUIArray(output.unlockTree); // Open popover - if (!$scope.unlockConditionPopover) { - $ionicPopover.fromTemplateUrl('templates/blockchain/unlock_condition_popover.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/blockchain/unlock_condition_popover.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.unlockConditionPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.unlockConditionPopover.remove(); - }); - $scope.unlockConditionPopover.show(event); - }); - } - else { - $scope.unlockConditionPopover.show(event); - } + } + }); }; $scope.hideUnlockConditionsPopover = function() { if ($scope.unlockConditionPopover) { $scope.unlockConditionPopover.hide(); - if ($scope.popoverData) { - delete $scope.popoverData.unlockConditions; - } + $scope.unlockConditionPopover = null; } }; diff --git a/assets/www/js/controllers/currency-controllers.js b/assets/www/js/controllers/currency-controllers.js index af06607b2b4852e2ecfd215e188fe6cd6bcc9ba2..985276bed83d6228a889182210340a4832666980 100644 --- a/assets/www/js/controllers/currency-controllers.js +++ b/assets/www/js/controllers/currency-controllers.js @@ -77,9 +77,10 @@ angular.module('cesium.currency.controllers', ['ngFileSaver', 'cesium.services'] ; function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA, UIUtils, csSettings, csCurrency, csNetwork, ModalUtils) { + 'ngInject'; $scope.formData = { - useRelative: csSettings.data.useRelative, + useRelative: false, // Override in enter() currency: '', M: 0, MoverN: 0, @@ -117,7 +118,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA $scope.enter = function(e, state) { if ($scope.loading) { // run only once (first enter) - + $scope.formData.useRelative = csSettings.data.useRelative; csCurrency.get() .then($scope.load) .then(function() { @@ -143,7 +144,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA $scope.load = function() { // Load data from node - var data = {}, M, lastUDTime, now = new Date().getTime(); + var data = {}, M, lastUDTime, now = Date.now(); return $q.all([ // Get the currency parameters @@ -186,7 +187,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA if (err && err.ucode == BMA.errorCodes.NO_CURRENT_BLOCK) { M = 0; data.N = 0; - data.medianTime = Math.trunc(new Date().getTime() / 1000); + data.medianTime = moment().utc().unix(); data.difficulty = 0; data.blockUid = null; return; @@ -232,9 +233,9 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA // Apply to formData angular.extend($scope.formData, data); - console.debug("[currency] Parameters loaded in " + (new Date().getTime() - now) + 'ms' ); + console.debug("[currency] Parameters loaded in " + (Date.now() - now) + 'ms' ); $scope.loading = false; - $scope.$broadcast('$$rebind::' + 'rebind'); // force bind of currency name + $scope.$broadcast('$$rebind::rebind'); // force bind of currency name // Set Ink UIUtils.ink(); @@ -277,7 +278,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA csSettings.store(); } }; - $scope.$watch('formData.allRules', $scope.onAllRulesChange, true); + $scope.$watch('formData.allRules', $scope.onAllRulesChange); $scope.onAllWotRulesChange = function() { csSettings.data.currency = csSettings.data.currency || {}; @@ -286,7 +287,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA csSettings.store(); } }; - $scope.$watch('formData.allWotRules', $scope.onAllWotRulesChange, true); + $scope.$watch('formData.allWotRules', $scope.onAllWotRulesChange); /* -- help tip -- */ @@ -327,26 +328,20 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA /* -- popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('templates/currency/popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/currency/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; } diff --git a/assets/www/js/controllers/help-controllers.js b/assets/www/js/controllers/help-controllers.js index baea4ccf4b5625cea95eedd468622ba9446661a3..860dda14572b132abca105f4ee804b93d7232b48 100644 --- a/assets/www/js/controllers/help-controllers.js +++ b/assets/www/js/controllers/help-controllers.js @@ -1072,10 +1072,10 @@ function HelpTipController($scope, $state, $window, $ionicSideMenuDelegate, $tim bindings: { content: 'HELP.TIP.SETTINGS_CHANGE_UNIT', contentParams: contentParams, - icon: { + icon: UIUtils.screen.isSmall() ? { position: 'right', style: 'margin-right: 60px' - }, + } : {position: 'center'}, hasNext: hasNext }, timeout: 1000 @@ -1105,11 +1105,12 @@ function HelpTipController($scope, $state, $window, $ionicSideMenuDelegate, $tim if (csWallet.isLogin()) { return $state.go('app.view_wallet') .then(function(){ - return $scope.showHelpTip('helptip-wallet-certifications', { + return $scope.showHelpTip('helptip-wallet-pubkey', { bindings: { content: 'HELP.TIP.END_LOGIN', hasNext: false - } + }, + timeout: 1200 }); }); } diff --git a/assets/www/js/controllers/join-controllers.js b/assets/www/js/controllers/join-controllers.js index 21a5401547807323c7111755cb9da786f9dd6025..0cfa56f3c7e8d218b8048512d315e6baacf34269 100644 --- a/assets/www/js/controllers/join-controllers.js +++ b/assets/www/js/controllers/join-controllers.js @@ -23,13 +23,21 @@ angular.module('cesium.join.controllers', ['cesium.services']) .controller('JoinModalCtrl', JoinModalController) ; -function JoinController($timeout, Modals) { +function JoinController($scope, $timeout, $controller, Modals, csWallet) { 'ngInject'; - // Open join modal - $timeout(function() { - Modals.showJoin(); - }, 100); + // Initialize the super class and extend it. + angular.extend(this, $controller('HomeCtrl', {$scope: $scope})); + + $scope.showJoinModal = function() { + if ($scope.loading) return $timeout($scope.showJoinModal, 500); // recursive call + + if (!csWallet.isLogin() && !$scope.error) { + return $timeout(Modals.showJoin, 300); + } + }; + $scope.$on('$ionicView.enter', $scope.showJoinModal); + } function JoinChooseAccountTypeModalController($scope, $state, Modals, UIUtils, csCurrency) { @@ -105,18 +113,21 @@ function JoinChooseAccountTypeModalController($scope, $state, Modals, UIUtils, c } -function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtils, CryptoUtils, csSettings, Modals, csWallet, BMA, parameters) { +function JoinModalController($scope, $state, $interval, $q, $timeout, Device, UIUtils, CryptoUtils, csSettings, Modals, csWallet, BMA, parameters) { 'ngInject'; $scope.formData = { - pseudo: '' + pseudo: parameters.uid || '', + pubkey: parameters.pubkey || undefined }; $scope.slides = { slider: null, options: { loop: false, effect: 'slide', - speed: 500 + speed: 500, + pager: false, + showPager: false } }; $scope.slideBehavior = {}; @@ -127,16 +138,27 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil $scope.showPassword = false; $scope.formData.computing=false; $scope.smallscreen = UIUtils.screen.isSmall(); - $scope.userIdPattern = BMA.constants.regex.USER_ID; + $scope.userIdPattern = BMA.constants.regexp.USER_ID; + $scope.accountAvailable = !!parameters.pubkey; // Read input parameters $scope.currency = parameters.currency; $scope.accountType = parameters.accountType || 'member'; + var wallet; + $scope.load = function() { if ($scope.loading) { - if ($scope.accountType == 'member') { + // Get the wallet + wallet = (parameters.walletId && csWallet.children.get(parameters.walletId)) || + (parameters.pubkey && csWallet.children.getByPubkey(parameters.pubkey)) || + ((!parameters.pubkey || csWallet.isUserPubkey(parameters.pubkey)) && csWallet); + if (!wallet) throw new Error("Cannot found the corresponding wallet, from parameters.pubkey or parameters.walletId"); + + console.debug("[join] Starting join modal on wallet {0}".format(wallet.id)); + + if ($scope.accountType === 'member') { $scope.licenseFileUrl = csSettings.getLicenseUrl(); if ($scope.licenseFileUrl) { // Use HTML in iframe, when original file is markdown (fix #538) @@ -180,17 +202,27 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil }; $scope.showAccountPubkey = function() { + if (parameters.pubkey && parameters.pseudo === $scope.formData.pseudo) { + $scope.formData.pubkey = parameters.pubkey; + $scope.formData.computing = false; + return; + } + $scope.formData.computing=true; CryptoUtils.scryptKeypair($scope.formData.username, $scope.formData.password) .then(function(keypair) { $scope.formData.pubkey = CryptoUtils.util.encode_base58(keypair.signPk); - $scope.formData.computing=false; - $scope.checkAccountAvailable(); + return $scope.checkAccountAvailable(); + }) + .then(function() { + return $timeout(function(){ + $scope.formData.computing=false; + }, 400); }) .catch(function(err) { - $scope.formData.computing=false; $scope.formData.pubkey = undefined; + $scope.formData.computing=false; UIUtils.onError('ERROR.CRYPTO_UNKNOWN_ERROR')(err); }); }; @@ -204,6 +236,7 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil var index = $scope.slides.slider.activeIndex; if($scope.accountType === 'member') { index += ($scope.licenseFileUrl ? 0 : 1); // skip index 0, when no license file + index += (parameters.pubkey && index >= 2 ? 2 : 0); // skip salt+pass, if already a pubkey if (index === 0) return "licenseForm"; if (index === 1) return "pseudoForm"; if (index === 2) return "saltForm"; @@ -221,14 +254,14 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil var formName = $scope.getCurrentFormName(); var behavior; - if (formName == "licenseForm") { + if (formName === "licenseForm") { behavior = { hasPreviousButton: false, hasNextButton: false, hasAcceptButton: true }; } - else if (formName == "pseudoForm") { + else if (formName === "pseudoForm") { behavior = { helpAnchor: 'join-pseudo', hasPreviousButton: $scope.licenseFileUrl && true, @@ -236,15 +269,15 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil focus: 'pseudo' }; } - else if (formName == "saltForm") { + else if (formName === "saltForm") { behavior = { helpAnchor: 'join-salt', - hasPreviousButton: true, + hasPreviousButton: $scope.accountType === 'member', hasNextButton: true, focus: 'salt' }; } - else if (formName == "passwordForm") { + else if (formName === "passwordForm") { behavior = { helpAnchor: 'join-password', hasPreviousButton: true, @@ -252,7 +285,7 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil focus: 'password' }; } - else if (formName == "confirmForm") { + else if (formName === "confirmForm") { behavior = { hasPreviousButton: true, hasNextButton: false, @@ -301,6 +334,11 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil $scope.slideBehavior = $scope.computeSlideBehavior(); }; + $scope.doPrev = function() { + $scope.slidePrev(); + $scope.slideBehavior = $scope.computeSlideBehavior(); + }; + $scope.doNewAccount = function(confirm) { if (!confirm) { @@ -323,16 +361,25 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil var onErrorLogout = function(message) { return function(err) { - csWallet.logout() - .then(function(){ - UIUtils.onError(message)(err); - }); + if (parameter.uid) { + wallet.unauth() + .then(function(){ + UIUtils.onError(message)(err); + }); + } + else { + wallet.logout() + .then(function(){ + UIUtils.onError(message)(err); + }); + } + throw new Error('CANCELLED'); }; }; UIUtils.loading.show(); - return csWallet.login({ + return wallet.login({ auth: true, isNew: true, method: 'SCRYPT_DEFAULT', @@ -345,44 +392,74 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil csSettings.data.wallet = csSettings.data.wallet || {}; csSettings.data.wallet.alertIfUnusedWallet = false; // do not alert if empty - // Send self - return csWallet.self($scope.formData.pseudo, false/*do NOT load membership here*/) + var needSelf = angular.isUndefined(parameters.uid) || angular.isUndefined(parameters.blockUid) || + (parameters.uid.toUpperCase() !== $scope.formData.pseudo.toUpperCase()); + if (!needSelf) { + wallet.setSelf(parameters.uid, parameters.blockUid); + } + + // Self promise (if need) + var selfPromise = needSelf ? + wallet.self($scope.formData.pseudo, false/*do NOT load membership here*/) + .catch(onErrorLogout('ERROR.SEND_IDENTITY_FAILED')) : + $q.when(); + + return selfPromise .then(function() { // Send membership IN - csWallet.membership.inside() - .then(function() { - - $scope.closeModal(); - - // Redirect to wallet - $state.go('app.view_wallet') - .then(function() { - // Wait 12s (for wallet load) - // then ask to download revocation file - return $timeout( - $scope.downloadRevocationRegistration, - 2000); - }); - }) - .catch(function(err) { - if (err && err.ucode != BMA.errorCodes.MEMBERSHIP_ALREADY_SEND) return; - onErrorLogout('ERROR.SEND_MEMBERSHIP_IN_FAILED')(err); - }); + return wallet.membership.inside() + .catch(function(err) { + if (err && err.ucode != BMA.errorCodes.MEMBERSHIP_ALREADY_SEND) return; + onErrorLogout('ERROR.SEND_MEMBERSHIP_IN_FAILED')(err); + }); + }) + .then(function() { + + $scope.closeModal(); + + // Redirect to wallet + if (wallet.isDefault()) { + return $state.go('app.view_wallet'); + } else { + return $state.go('app.view_wallet_by_id', {id: wallet.id}); + } }) - .catch(onErrorLogout('ERROR.SEND_IDENTITY_FAILED')); + .then(function() { + // Wait 2s (for wallet load) + // then ask to download revocation file + return $timeout(function() { + // Hide the loading indicator, if wallet already loaded + if (wallet.isDataLoaded({requirements: true})) { + UIUtils.loading.hide(); + } + return $scope.downloadRevocationRegistration(); + }, + 2000); + }); } else{ $scope.closeModal(); // Redirect to wallet - $state.go('app.view_wallet'); + if (wallet.isDefault()) { + $state.go('app.view_wallet'); + } + else { + $state.go('app.view_wallet_by_id', {id: wallet.id}); + } } }) .catch(function(err) { UIUtils.loading.hide(); - console.error('>>>>>>>' , err); - UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); + if (err === 'CANCELLED') return; + if (err && err.ucode != BMA.errorCodes.MEMBERSHIP_ALREADY_SEND) { + console.error("[wallet] Node: already membership", err); + return; // OK + } + else { + UIUtils.alert.error('ERROR.UNKNOWN_ERROR'); + } }); }; @@ -395,7 +472,7 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil }) .then(function(confirm) { if (!confirm) return; - return csWallet.downloadRevocation(); + return wallet.downloadRevocation(); }); }; @@ -441,48 +518,59 @@ function JoinModalController($scope, $state, $interval, $timeout, Device, UIUtil var uid = $scope.formData.pseudo.toUpperCase(); $scope.formData.computing=true; - // search on uid - BMA.wot.lookup({ search: uid }) - .then(function(res) { - $scope.uiAlreadyUsed = (res.results || []).some(function(pub){ - return (pub.uids || []).some(function(idty) { - return (idty.uid.toUpperCase() === uid); // same Uid - }); - }); - $scope.formData.computing=false; - }) - .catch(function(err){ - console.error(err); - $scope.formData.computing=false; - $scope.uiAlreadyUsed = false; - }); + // Same has given uid + self block: skip control + if (parameters.uid && uid === parameters.uid.toUpperCase()) { + $scope.formData.computing=false; + $scope.uiAlreadyUsed = false; + return; + } + else { + // search on uid + BMA.wot.lookup({ search: uid }) + .then(function(res) { + $scope.uiAlreadyUsed = (res.results || []).some(function(pub){ + return (pub.uids || []).some(function(idty) { + return (idty.uid.toUpperCase() === uid); // same Uid + }); + }); + $scope.formData.computing=false; + }) + .catch(function(err){ + console.error(err); + $scope.formData.computing=false; + $scope.uiAlreadyUsed = false; + }); + } }; $scope.$watch('formData.pseudo', $scope.checkUid, true); $scope.checkAccountAvailable = function() { + if (parameters.pubkey) { + $scope.accountAvailable = true; + return; + } + delete $scope.accountAvailable; // Search for tx source, from pubkey - BMA.tx.sources({ pubkey: $scope.formData.pubkey }) + return BMA.tx.sources({ pubkey: $scope.formData.pubkey }) .then(function(res) { - if(!res.sources.length) { - $scope.formData.computing=false; - $scope.accountAvailable = true; - } - else{ - $scope.formData.computing=false; - $scope.accountAvailable = false; - } + $scope.accountAvailable = !res || !res.sources.length; }) .catch(function(err) { console.error(err); - $scope.formData.computing=false; $scope.accountAvailable = false; }); }; $scope.identifierRecovery = function() { - for (var i = 0; i < 2; i++) - $scope.slidePrev(); + // Go back + $scope.slides.slider.unlockSwipes(); + for (var i = 0; i < 2; i++) { + $scope.slides.slider.slidePrev(); + } + $scope.slides.slider.lockSwipes(); + // Recompute behavior + $scope.slideBehavior = $scope.computeSlideBehavior(); }; // TODO: remove auto add account when done diff --git a/assets/www/js/controllers/login-controllers.js b/assets/www/js/controllers/login-controllers.js index cf0ca1d33cd587b2fd10abf4fbc0cbee907bf135..3f5e21a9210b3c8f972b1c639da0fc91ce0a3fbe 100644 --- a/assets/www/js/controllers/login-controllers.js +++ b/assets/www/js/controllers/login-controllers.js @@ -1,14 +1,50 @@ angular.module('cesium.login.controllers', ['cesium.services']) + .config(function($stateProvider) { + 'ngInject'; + + $stateProvider + .state('app.login', { + url: "/login", + views: { + 'menuContent': { + templateUrl: "templates/home/home.html", + controller: 'LoginCtrl' + } + } + }) + ; + }) + + .controller('LoginCtrl', LoginController) + .controller('LoginModalCtrl', LoginModalController) .controller('AuthCtrl', AuthController) ; -function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, $translate, - CryptoUtils, UIUtils, BMA, Modals, csSettings, Device, parameters) { + +function LoginController($scope, $timeout, $controller, csWallet) { + 'ngInject'; + + // Initialize the super class and extend it. + angular.extend(this, $controller('HomeCtrl', {$scope: $scope})); + + $scope.showLoginModal = function() { + if ($scope.loading) return $timeout($scope.showLoginModal, 500); // recursive call + + if (!csWallet.isLogin() && !$scope.error) { + return $timeout(csWallet.login, 300); + } + }; + $scope.$on('$ionicView.enter', $scope.showLoginModal); + +} + +function LoginModalController($scope, $timeout, $q, $ionicPopover, CryptoUtils, csCrypto, ionicReady, + UIUtils, BMA, Modals, csSettings, Device, parameters) { 'ngInject'; parameters = parameters || {}; @@ -19,11 +55,15 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, $scope.showPubkey = false; $scope.showComputePubkeyButton = false; $scope.autoComputePubkey = false; - $scope.pubkeyPattern = '^' + BMA.constants.regexp.PUBKEY + '$'; + $scope.pubkeyPattern = '^(:?{0}|{1})$'.format(BMA.constants.regexp.PUBKEY, BMA.constants.regexp.PUBKEY_WITH_CHECKSUM); $scope.isAuth = parameters.auth; + $scope.okText = parameters.okText; + $scope.title = parameters.title || ($scope.isAuth ? 'AUTH.TITLE' : 'LOGIN.TITLE'); $scope.showMethods = angular.isDefined(parameters.showMethods) ? parameters.showMethods : true; + $scope.showNewAccountLink = angular.isDefined(parameters.showNewAccountLink) ? parameters.showNewAccountLink : true; $scope.expectedPubkey = parameters.expectedPubkey; + $scope.expectedUid = parameters.uid; $scope.scryptParamsValues = _.keys(CryptoUtils.constants.SCRYPT_PARAMS) .reduce(function(res, key) { @@ -32,9 +72,12 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, // modal init $scope.init = function() { - // Should auto-compute pubkey ? - $scope.autoComputePubkey = ionic.Platform.grade.toLowerCase()==='a' && - !UIUtils.screen.isSmall(); + + ionicReady().then(function(){ + // Should auto-compute pubkey ? + $scope.autoComputePubkey = ionic.Platform.grade.toLowerCase()==='a' && + !UIUtils.screen.isSmall(); + }); // Init remember me $scope.formData.rememberMe = csSettings.data.rememberMe; @@ -46,8 +89,9 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, // Init method var method = parameters.method || csSettings.data.login && csSettings.data.login.method || 'SCRYPT_DEFAULT'; var params = csSettings.data.login && csSettings.data.login.params; - if ($scope.isAuth && method == 'PUBKEY') { - method = 'SCRYPT_DEFAULT'; // PUBKEY not enable if auth need + // used default method, when PUBKEY + auth, or SCAN, or if ask for 'default' + if (($scope.isAuth && method === 'PUBKEY') || (method === 'SCAN') || (method === 'default')) { + method = 'SCRYPT_DEFAULT'; } $scope.changeMethod(method, params); }; @@ -70,15 +114,15 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, $scope.$on('modal.hide', $scope.leave); // Login form submit - $scope.doLogin = function() { - if(!$scope.form.$valid) { - return; - } + $scope.doLogin = function(skipForm) { + var method = $scope.formData.method; + + if(!$scope.form.$valid && method !== 'SCAN') return; + // removeIf(no-device) Device.keyboard.close(); // endRemoveIf(no-device) - var method = $scope.formData.method; var keepAuthIdle = $scope.formData.keepAuthIdle; var promise; @@ -117,9 +161,12 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, // If checkbox keep auth checked: set idle time to session keepAuthIdle = ($scope.formData.keepAuth && csSettings.constants.KEEP_AUTH_IDLE_SESSION) || keepAuthIdle; - UIUtils.loading.show(); - promise = $scope.readKeyFile($scope.formData.file, { - withSecret: ($scope.isAuth||$scope.formData.keepAuth) + promise = + UIUtils.loading.show() + .then(function() { + return $scope.readKeyFile($scope.formData.file, { + withSecret: ($scope.isAuth || $scope.formData.keepAuth) + }); }) .then(function(keypair) { if (!keypair) return UIUtils.loading.hide(10); @@ -138,18 +185,67 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, keypair: keypair }; }) - .catch(function(err) { - - UIUtils.onError('ERROR.AUTH_FILE_ERROR')(err); - }); + .catch(UIUtils.onError('ERROR.AUTH_FILE_ERROR')); } // Pubkey else if (method === 'PUBKEY') { - if (!$scope.formData.pubkey) return; - promise = $q.when({ - pubkey: $scope.formData.pubkey - }); + var pubkey = $scope.formData.pubkey && $scope.formData.pubkey.trim(); + var uid = $scope.formData.uid && $scope.formData.uid.trim() || undefined; + if (!pubkey) return; + var matches = BMA.regexp.PUBKEY.exec(pubkey); + // valid pubkey: use it + if (matches) { + promise = UIUtils.loading.show() + .then(function() { + return { + pubkey: pubkey, + uid : uid + }; + }); + } + + // Check checksum + else { + + matches = BMA.regexp.PUBKEY_WITH_CHECKSUM.exec(pubkey); + if (matches) { + + pubkey = matches[1]; + var checksum = matches[2]; + var expectedChecksum = csCrypto.util.pkChecksum(pubkey); + if (checksum != expectedChecksum) { + $scope.form.pubkey.$error = {checksum: true}; + } + else { + promise = UIUtils.loading.show() + .then(function() { + return { + pubkey: pubkey, + uid : uid + }; + }); + } + } + // Not a pubkey: launch search on + else { + return $scope.showWotLookupModal(pubkey); + } + } + } + + // Scan QR code + else if (method === 'SCAN') { + var valid = $scope.formData.pubkey && (!$scope.isAuth || !!$scope.formData.keypair); + if (!valid) return; + + promise = UIUtils.loading.show() + .then(function() { + return { + pubkey: $scope.formData.pubkey, + keypair: $scope.formData.keypair + }; + }); } if (!promise) { @@ -231,6 +327,7 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, .catch(function (err) { UIUtils.onError('ERROR.CRYPTO_UNKNOWN_ERROR')(err); $scope.computing = false; + $scope.autoComputePubkey = false; // Avoid a infinite loop (computePubkey -> onScryptFormChanged -> computePubkey) $scope.onScryptFormChanged(); }); }, 100); @@ -254,12 +351,79 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, return Modals.showHelp(parameters); }; + $scope.doScan = function() { + if ($scope.computing) return; + + $scope.computing = true; + $scope.formData.pubkey = null; + $scope.formData.keypair = null; + + // Run scan cordova plugin, on device + return Device.barcode.scan() + .then(function(data) { + if (!data) return; + + // Skip simple parsing, if auth if need + if ($scope.isAuth) return $q.when(data); + + // Try to parse as an URI + return BMA.uri.parse(data) + .then(function (res) { + if (!res || !res.pubkey) throw {message: 'ERROR.SCAN_UNKNOWN_FORMAT'}; + // If simple pubkey + return res; + }) + .catch(function(err) { + console.debug('[login] Error while parsing as URI: ' + (err && err.message || err)); + return data; + }); + }) + .then(function(data) { + if (!data) return; + // Parse success: continue + if (data && data.pubkey) return data; + + // Try to read as WIF format + return csCrypto.keyfile.parseData(data, {silent: true}) + .then(function(keypair) { + if (!keypair || !keypair.signPk || !keypair.signSk) throw {message: 'ERROR.SCAN_UNKNOWN_FORMAT'}; // rethrow an error + + var pubkey = CryptoUtils.base58.encode(keypair.signPk); + + // Login using keypair + return { + pubkey: pubkey, + keypair: keypair + }; + }) + // Unknown format (nor URI, nor WIF/EWIF) + .catch(UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')); + }) + .then(function(res) { + if (!res || !res.pubkey) return; // no data + + $scope.pubkeyError = $scope.expectedPubkey && $scope.expectedPubkey != res.pubkey; + $scope.formData.pubkey = res.pubkey; + $scope.formData.keypair = res.keypair; + }) + .then(function() { + $scope.computing = false; + UIUtils.loading.hide(10); + }) + .catch(function(err) { + $scope.computing = false; + UIUtils.onError('ERROR.SCAN_FAILED')(err); + }); + }; + $scope.changeMethod = function(method, params){ $scope.hideMethodsPopover(); - if (method == $scope.formData.method) return; // same method + + if (!method || method == $scope.formData.method) return; // same method console.debug("[login] method is: " + method); $scope.formData.method = method; + $scope.formData.uid = null; if ($scope.form) { // hide form's fields errors on the form @@ -268,6 +432,9 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, // Scrypt (advanced or not) if (method == 'SCRYPT_DEFAULT' || method == 'SCRYPT_ADVANCED') { + $scope.pubkey = null; + + // Search scrypt object var scrypt; if (params) { @@ -286,11 +453,15 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, $scope.autoComputePubkey = $scope.autoComputePubkey && (method == 'SCRYPT_DEFAULT'); } + else if (method == 'SCAN') { + return $scope.doScan(); + } else { $scope.formData.username = null; $scope.formData.password = null; $scope.formData.pubkey = null; - $scope.formData.computing = false; + $scope.pubkey = null; + $scope.computing = false; } }; @@ -302,23 +473,34 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, $scope.readKeyFile = function(file, options) { options = options || {}; - options.password = options.password || $scope.formData.file.password; - return CryptoUtils.readKeyFile($scope.formData.file, options) + + options.password = options.password || $scope.formData.file.password || function() { + $scope.formData.file.password = undefined; + return Modals.showPassword({ + title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', + subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP', + error: options.error, + scope: $scope + }) + .then(function (password) { + // Remember password (for validation) + $scope.formData.file.password = password; + // Timeout is need to force popup to be hide + return $timeout(function() { + return password; + }, 150); + }); + }; + + return csCrypto.keyfile.read($scope.formData.file, options) .catch(function(err) { - if (err && (err == 'NEED_PASSWORD' || err == 'BAD_PASSWORD')) { - $scope.formData.file.password = undefined; // reset password - options.password = undefined; // reset password - return Modals.showPassword({ - title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', - subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP' - }) - .then(function (password) { - if (!password) throw 'CANCELLED'; - - // Set password, then retry - $scope.formData.file.password = password; - return $scope.readKeyFile($scope.formData.file, options); - }); + $scope.formData.file.password = undefined; + if (err === 'CANCELLED') { + UIUtils.loading.hide(10); + } + if (err && err.ucode == csCrypto.errorCodes.BAD_PASSWORD) { + // Recursive call + return $scope.readKeyFile($scope.formData.file, {withSecret: options.withSecret, error: 'ACCOUNT.SECURITY.KEYFILE.ERROR.BAD_PASSWORD'}); } throw err; }); @@ -350,7 +532,7 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, }) .catch(function(err) { - if (err && err == 'CANCELLED') { + if (err && err === 'CANCELLED') { $scope.removeKeyFile(); return; } @@ -403,48 +585,38 @@ function LoginModalController($scope, $timeout, $q, $ionicPopover, $ionicPopup, /* -- modals -- */ - $scope.showWotLookupModal = function() { - return Modals.showWotLookup() + $scope.showWotLookupModal = function(searchText) { + return Modals.showWotLookup({q: searchText}) .then(function(res){ if (res && res.pubkey) { $scope.formData.pubkey = res.pubkey; + $scope.formData.uid = res.uid || undefined; + return $timeout($scope.doLogin, 300); } }); }; /* -- popover -- */ - $scope.showMethodsPopover = function(event) { if (event.defaultPrevented) return; - if (!$scope.methodsPopover) { - - $ionicPopover.fromTemplateUrl('templates/login/popover_methods.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl :'templates/login/popover_methods.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.methodsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.methodsPopover.remove(); - }); - $scope.methodsPopover.show(event) - .then(function() { - UIUtils.ink({selector: '.popover-login-methods .item'}); - }); - }); - } - else { - $scope.methodsPopover.show(event); - } + UIUtils.ink({selector: '.popover-login-methods .item'}); + } + }); }; $scope.hideMethodsPopover = function() { if ($scope.methodsPopover) { $scope.methodsPopover.hide(); + $scope.methodsPopover = null; } }; - - // Default action $scope.init(); diff --git a/assets/www/js/controllers/network-controllers.js b/assets/www/js/controllers/network-controllers.js index a381b096572658f89253a4d6041ef1764a1fe131..0fdbb64ea890aebab28ba3d786e140a83113a3c5 100644 --- a/assets/www/js/controllers/network-controllers.js +++ b/assets/www/js/controllers/network-controllers.js @@ -8,7 +8,7 @@ angular.module('cesium.network.controllers', ['cesium.services']) .state('app.network', { url: "/network?type&expert", - cache: false, + cache: false, // fix #766 views: { 'menuContent': { templateUrl: "templates/network/view_network.html", @@ -60,12 +60,27 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win loading: true, type: undefined, results: [], - endpointFilter: null, + endpoint: null, + bma: undefined, + ssl: undefined, + ws2p: undefined, sort : undefined, asc: true }; + $scope.compactMode = true; + $scope.listeners = []; $scope.helptipPrefix = 'helptip-network'; - $scope.eanbleLocationHref = true; // can be overrided by sub-controler (e.g. popup) + $scope.enableLocationHref = true; // can be overrided by sub-controler (e.g. popup) + + $scope.removeListeners = function() { + if ($scope.listeners.length) { + console.debug("[network] Closing listeners"); + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + } + }; /** * Enter in view @@ -102,6 +117,7 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win */ $scope.leave = function() { if (!$scope.networkStarted) return; + $scope.removeListeners(); csNetwork.close(); $scope.networkStarted = false; $scope.search.loading = true; @@ -110,12 +126,16 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.$on('$ionicParentView.beforeLeave', $scope.leave); $scope.$on('$destroy', $scope.leave); + $scope.computeOptions = function() { var options = { filter: { member: (!$scope.search.type || $scope.search.type === 'member'), mirror: (!$scope.search.type || $scope.search.type === 'mirror'), - endpointFilter : (angular.isDefined($scope.search.endpointFilter) ? $scope.search.endpointFilter : null), + endpoint : (angular.isDefined($scope.search.endpoint) ? $scope.search.endpoint : null), + bma : $scope.search.bma, + ssl : $scope.search.ssl, + ws2p : $scope.search.ws2p, online: !($scope.search.type && $scope.search.type === 'offline') }, sort: { @@ -132,23 +152,25 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.load = function() { if ($scope.search.loading){ + // Start network scan csNetwork.start($scope.node, $scope.computeOptions()); // Catch event on new peers $scope.refreshing = false; - csNetwork.api.data.on.changed($scope, function(data){ - if (!$scope.refreshing) { - $scope.refreshing = true; - csWot.extendAll(data.peers) - .then(function() { - // Avoid to refresh if view has been leaving - if ($scope.networkStarted) { - $scope.updateView(data); - } - $scope.refreshing = false; - }); - } - }); + $scope.listeners.push( + csNetwork.api.data.on.changed($scope, function(data){ + if (!$scope.refreshing) { + $scope.refreshing = true; + csWot.extendAll(data.peers) + .then(function() { + // Avoid to refresh if view has been leaving + if ($scope.networkStarted) { + $scope.updateView(data); + } + $scope.refreshing = false; + }); + } + })); } // Show help tip @@ -157,17 +179,17 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.updateView = function(data) { console.debug("[peers] Updating UI"); - $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding + $scope.$broadcast('$$rebind::rebind'); // force data binding $scope.search.results = data.peers; $scope.search.memberPeersCount = data.memberPeersCount; // Always tru if network not started (e.g. after leave+renter the view) $scope.search.loading = !$scope.networkStarted || csNetwork.isBusy(); + if (!$scope.loading) { + $scope.$broadcast('$$rebind::rebind'); // force data binding + } if ($scope.motion && $scope.search.results && $scope.search.results.length > 0) { $scope.motion.show({selector: '.item-peer'}); } - if (!$scope.loading) { - $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding - } }; $scope.refresh = function() { @@ -196,18 +218,18 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.load(); // Update location href - if ($scope.eanbleLocationHref) { + if ($scope.enableLocationHref) { $location.search({type: $scope.search.type}).replace(); } }; $scope.toggleSearchEndpoint = function(endpoint){ $scope.hideActionsPopover(); - if ($scope.search.endpointFilter === endpoint || endpoint === null) { - $scope.search.endpointFilter = null; + if ($scope.search.endpoint === endpoint || endpoint === null) { + $scope.search.endpoint = null; } else { - $scope.search.endpointFilter = endpoint; + $scope.search.endpoint = endpoint; } $scope.sort(); }; @@ -224,9 +246,19 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.sort(); }; + $scope.toggleCompactMode = function() { + $scope.compactMode = !$scope.compactMode; + $scope.$broadcast('$$rebind::rebind'); // force data binding + }; + $scope.selectPeer = function(peer) { - // Skipp offline or WS2P node - if (!peer.online || peer.isWs2p()) return; + if (peer.compacted && $scope.compactMode) { + $scope.toggleCompactMode(); + return; + } + + // Skipp offline or not a BMA peer + if (!peer.online || !peer.hasBma()) return; var stateParams = {server: peer.getServer()}; if (peer.isSsl()) { @@ -239,7 +271,7 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win }; $scope.$on('csView.action.refresh', function(event, context) { - if (context == 'peers') { + if (context === 'peers') { $scope.refresh(); } }); @@ -251,48 +283,45 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win /* -- popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('templates/network/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/network/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; - $scope.showEndpointsPopover = function($event, peer, endpointFilter) { - var endpoints = peer.getEndpoints(endpointFilter); + $scope.showEndpointsPopover = function($event, peer, endpointName) { + $event.preventDefault(); + $event.stopPropagation(); + + var endpoints = peer.getEndpoints(endpointName); endpoints = (endpoints||[]).reduce(function(res, ep) { - var bma = BMA.node.parseEndPoint(ep); + var bma = BMA.node.parseEndPoint(ep) || BMA.node.parseEndPoint(ep, endpointName); return res.concat({ label: 'NETWORK.VIEW.NODE_ADDRESS', - value: peer.getServer() + (bma.path||'') + value: peer.getServer(bma) + (bma && bma.path||'') }); }, []); if (!endpoints.length) return; + // Call extension points UIUtils.popover.show($event, { templateUrl: 'templates/network/popover_endpoints.html', bindings: { - titleKey: 'NETWORK.VIEW.ENDPOINTS.' + endpointFilter, + titleKey: 'NETWORK.VIEW.ENDPOINTS.' + endpointName, items: endpoints } }); - $event.stopPropagation(); }; $scope.showWs2pPopover = function($event, peer) { @@ -360,10 +389,13 @@ function NetworkLookupModalController($scope, $controller, parameters) { parameters = parameters || {}; $scope.enableFilter = angular.isDefined(parameters.enableFilter) ? parameters.enableFilter : true; $scope.search.type = angular.isDefined(parameters.type) ? parameters.type : $scope.search.type; - $scope.search.endpointFilter = angular.isDefined(parameters.endpointFilter) ? parameters.endpointFilter : $scope.search.endpointFilter; + $scope.search.endpoint = angular.isDefined(parameters.endpoint) ? parameters.endpoint : $scope.search.endpoint; + $scope.search.bma = angular.isDefined(parameters.bma) ? parameters.bma : $scope.search.bma; + $scope.search.ssl = angular.isDefined(parameters.ssl) ? parameters.ssl : $scope.search.ssl; + $scope.search.ws2p = angular.isDefined(parameters.ws2p) ? parameters.ws2p : $scope.search.ws2p; $scope.expertMode = angular.isDefined(parameters.expertMode) ? parameters.expertMode : $scope.expertMode; $scope.ionItemClass = parameters.ionItemClass || 'item-border-large'; - $scope.eanbleLocationHref = false; + $scope.enableLocationHref = false; $scope.helptipPrefix = ''; $scope.selectPeer = function(peer) { @@ -392,7 +424,7 @@ function NetworkLookupPopoverController($scope, $controller) { var parameters = parameters || {}; $scope.enableFilter = angular.isDefined(parameters.enableFilter) ? parameters.enableFilter : true; $scope.search.type = angular.isDefined(parameters.type) ? parameters.type : $scope.search.type; - $scope.search.endpointFilter = angular.isDefined(parameters.endpointFilter) ? parameters.endpointFilter : $scope.search.endpointFilter; + $scope.search.endpoint = angular.isDefined(parameters.endpoint) ? parameters.endpoint : $scope.search.endpoint; $scope.expertMode = angular.isDefined(parameters.expertMode) ? parameters.expertMode : $scope.expertMode; $scope.ionItemClass = parameters.ionItemClass || 'item-border-large'; $scope.helptipPrefix = ''; @@ -443,7 +475,6 @@ function PeerInfoPopoverController($scope, $q, csSettings, csCurrency, csHttp, B // Get node current version BMA.node.summary() .then(function(res){ - console.log(res); $scope.formData.version = res && res.duniter && res.duniter.version; $scope.formData.software = res && res.duniter && res.duniter.software; }) @@ -475,7 +506,7 @@ function PeerInfoPopoverController($scope, $q, csSettings, csCurrency, csHttp, B $scope.formData.hasNewRelease = false; } $scope.loading = false; - $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding + $scope.$broadcast('$$rebind::rebind'); // force data binding }); }; @@ -522,6 +553,9 @@ function PeerViewController($scope, $q, $window, $state, UIUtils, csWot, BMA) { }) .then(function(){ $scope.loading = false; + }) + .catch(function() { + $scope.loading = false; }); }); @@ -584,15 +618,19 @@ function PeerViewController($scope, $q, $window, $state, UIUtils, csWot, BMA) { .then(function(json) { $scope.node.pubkey = json.pubkey; $scope.node.currency = json.currency; + }) + .catch(function(err){ + console.error(err && err.message || err); }), // Get known peers $scope.node.network.peers() .then(function(json) { - var peers = json.peers.map(function (p) { + var peers = (json && json.peers || []).map(function (p) { var peer = new Peer(p); - peer.online = p.status == 'UP'; - peer.blockNumber = peer.block.replace(/-.+$/, ''); + peer.online = p.status === 'UP'; + peer.buid = peer.block; + peer.blockNumber = peer.buid && peer.buid.split('-')[0]; peer.dns = peer.getDns(); peer.id = peer.keyID(); peer.server = peer.getServer(); @@ -620,7 +658,11 @@ function PeerViewController($scope, $q, $window, $state, UIUtils, csWot, BMA) { $scope.current = json; }) ]) - .catch(UIUtils.onError(useTor ? "PEER.VIEW.ERROR.LOADING_TOR_NODE_ERROR" : "PEER.VIEW.ERROR.LOADING_NODE_ERROR")); + .catch(function(err) { + console.error(err && err.message || err); + UIUtils.onError(useTor ? "PEER.VIEW.ERROR.LOADING_TOR_NODE_ERROR" : "PEER.VIEW.ERROR.LOADING_NODE_ERROR")(err); + throw err; + }); }; $scope.selectPeer = function(peer) { diff --git a/assets/www/js/controllers/settings-controllers.js b/assets/www/js/controllers/settings-controllers.js index f128bb3159aa28d556f5edb7013a9580b6e9ed26..4981f8e68c5b3b1137e79074f71d2dda6f7205f3 100644 --- a/assets/www/js/controllers/settings-controllers.js +++ b/assets/www/js/controllers/settings-controllers.js @@ -20,8 +20,8 @@ angular.module('cesium.settings.controllers', ['cesium.services', 'cesium.curren .controller('SettingsCtrl', SettingsController) ; -function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $translate, csHttp, - UIUtils, BMA, csSettings, csPlatform, $ionicPopover, Modals) { +function SettingsController($scope, $q, $window, $ionicHistory, $ionicPopup, $timeout, $translate, $ionicPopover, + UIUtils, Modals, BMA, csHttp, csConfig, csCurrency, csSettings, csPlatform) { 'ngInject'; $scope.formData = angular.copy(csSettings.data); @@ -61,8 +61,47 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t }; $scope.keepAuthIdles = _.keys($scope.keepAuthIdleLabels); + $scope.blockValidityWindowLabels = { + 0: { + labelKey: 'SETTINGS.BLOCK_VALIDITY_OPTION.NONE' + }, + 6: { + labelKey: 'SETTINGS.BLOCK_VALIDITY_OPTION.N', + labelParams: {count: 6, time: undefined /*defined in enter*/} + }, + 12: { + labelKey: 'SETTINGS.BLOCK_VALIDITY_OPTION.N', + labelParams: {count: 12, time: undefined /*defined in enter*/} + }, + 24: { + labelKey: 'SETTINGS.BLOCK_VALIDITY_OPTION.N', + labelParams: {count: 24, time: undefined /*defined in enter*/} + } + }; + $scope.blockValidityWindows = _.keys($scope.blockValidityWindowLabels); + $scope.$on('$ionicView.enter', function() { - csSettings.ready().then($scope.load); + $q.all([ + csSettings.ready(), + csCurrency.parameters() + .then(function(parameters) { + return parameters && parameters.avgGenTime; + }) + // Make sure to continue even if node is down - Fix #788 + .catch(function(err) { + console.error("[settings] Could not not currency parameters. Using default 'avgGenTime' (300)", err); + return {avgGenTime: 300}; + }) + .then(function(parameters) { + _.each($scope.blockValidityWindows, function(blockCount) { + if (blockCount > 0) { + $scope.blockValidityWindowLabels[blockCount].labelParams.time= parameters.avgGenTime * blockCount; + } + }); + }) + ]) + .then($scope.load) + ; }); $scope.setPopupForm = function(popupForm) { @@ -82,9 +121,9 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t $scope.formData.locale = (csSettings.data.locale && csSettings.data.locale.id && _.findWhere($scope.locales, {id: csSettings.data.locale.id})) || _.findWhere($scope.locales, {id: csSettings.defaultSettings.locale.id}); - $scope.loading = false; - $timeout(function() { + return $timeout(function() { + $scope.loading = false; // Set Ink UIUtils.ink({selector: '.item'}); $scope.showHelpTip(); @@ -111,9 +150,10 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t // Change node $scope.changeNode= function(node) { + var port = !!$scope.formData.node.port && $scope.formData.node.port != 80 && $scope.formData.node.port != 443 ? $scope.formData.node.port : undefined; node = node || { host: $scope.formData.node.host, - port: $scope.formData.node.port && $scope.formData.node.port != 80 && $scope.formData.node.port != 443 ? $scope.formData.node.port : undefined, + port: port, useSsl: angular.isDefined($scope.formData.node.useSsl) ? $scope.formData.node.useSsl : ($scope.formData.node.port == 443) @@ -122,7 +162,7 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t .then(function(newNode) { if (newNode.host === $scope.formData.node.host && newNode.port === $scope.formData.node.port && - newNode.useSsl === $scope.formData.node.useSsl) { + newNode.useSsl === $scope.formData.node.useSsl && !$scope.formData.node.temporary) { return; // same node = nothing to do } UIUtils.loading.show(); @@ -138,12 +178,12 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t }); } UIUtils.loading.hide(); - $scope.formData.node = newNode; - delete $scope.formData.temporary; + angular.merge($scope.formData.node, newNode); + delete $scope.formData.node.temporary; BMA.copy(nodeBMA); $scope.bma = BMA; - // Start platform is not already started + // Restart platform (or start if not already started) csPlatform.restart(); // Reset history cache @@ -153,8 +193,16 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t }; $scope.showNodeList = function() { + // Check if need a filter on SSL node + var forceUseSsl = (csConfig.httpsMode === 'true' || csConfig.httpsMode === true || csConfig.httpsMode === 'force') || + ($window.location && $window.location.protocol === 'https:') ? true : false; + $ionicPopup._popupStack[0].responseDeferred.promise.close(); - return Modals.showNetworkLookup({enableFilter: true, type: 'member'}) + return Modals.showNetworkLookup({ + enableFilter: true, // enable filter button + bma: true, // only BMA node + ssl: forceUseSsl ? true : undefined + }) .then(function (peer) { if (peer) { var bma = peer.getBMA(); @@ -162,7 +210,7 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t host: (bma.dns ? bma.dns : (peer.hasValid4(bma) ? bma.ipv4 : bma.ipv6)), port: bma.port || 80, - useSsl: bma.useSsl + useSsl: bma.useSsl || bma.port == 443 }; } }) @@ -236,17 +284,22 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t $scope.saving = true; // Async - to avoid UI lock - $timeout(function() { + return $timeout(function() { // Make sure to format helptip $scope.cleanupHelpTip(); - angular.merge(csSettings.data, $scope.formData); - // Manually removed some attributes - if (!$scope.formData.temporary) { - delete csSettings.data.node.temporary; - } - csSettings.store(); - $scope.saving = false; - }, 100); + + // Applying + csSettings.apply($scope.formData); + + // Store + return csSettings.store(); + + }, 100) + .then(function() { + //return $timeout(function() { + $scope.saving = false; + //}, 100); + }); }; $scope.onDataChanged = function(oldValue, newValue, scope) { @@ -260,14 +313,24 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t }, 500); } - var updated = !angular.equals(oldValue, newValue); - if (updated) { - //console.debug('Detected settings update: will save it'); + // Changes from the current scope: save changes + if ((scope === $scope) && !angular.equals(oldValue, newValue)) { $scope.save(); } }; $scope.$watch('formData', $scope.onDataChanged, true); + // Detected changes from outside (e.g. enabling encryption on wallet can be rollback if user cancel auth) + csSettings.api.data.on.changed($scope, function(data) { + if ($scope.loading || $scope.saving || $scope.pendingSaving) return; + + var updated = !angular.equals(data.useLocalStorageEncryption, $scope.formData.useLocalStorageEncryption); + if (updated) { + console.debug('[settings] Settings changed (outside the settings page). Reloading...'); + $scope.load(); + } + }); + $scope.getServer = function() { if (!$scope.formData.node || !$scope.formData.node.host) return ''; return csHttp.getServer($scope.formData.node.host, $scope.formData.node.port); @@ -287,26 +350,20 @@ function SettingsController($scope, $q, $ionicHistory, $ionicPopup, $timeout, $t /* -- modals & popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('templates/settings/popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/settings/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; diff --git a/assets/www/js/controllers/transfer-controllers.js b/assets/www/js/controllers/transfer-controllers.js index 5419f124207e129d8bb25820c15cd8639857d966..cedbccf90a3554a822429829010abc576dac59a0 100644 --- a/assets/www/js/controllers/transfer-controllers.js +++ b/assets/www/js/controllers/transfer-controllers.js @@ -6,7 +6,7 @@ angular.module('cesium.transfer.controllers', ['cesium.services', 'cesium.curren .state('app.new_transfer', { cache: false, - url: "/transfer?amount&udAmount&comment", + url: "/transfer?amount&udAmount&comment&restPub&all&wallet", views: { 'menuContent': { templateUrl: "templates/wallet/new_transfer.html", @@ -17,7 +17,7 @@ angular.module('cesium.transfer.controllers', ['cesium.services', 'cesium.curren .state('app.new_transfer_pubkey_uid', { cache: false, - url: "/transfer/:pubkey/:uid?amount&udAmount&comment", + url: "/transfer/:pubkey/:uid?amount&udAmount&comment&restPub&all&wallet", views: { 'menuContent': { templateUrl: "templates/wallet/new_transfer.html", @@ -28,7 +28,7 @@ angular.module('cesium.transfer.controllers', ['cesium.services', 'cesium.curren .state('app.new_transfer_pubkey', { cache: false, - url: "/transfer/:pubkey?amount&udAmount&comment", + url: "/transfer/:pubkey?amount&udAmount&comment&restPub&all&wallet", views: { 'menuContent': { templateUrl: "templates/wallet/new_transfer.html", @@ -44,7 +44,7 @@ angular.module('cesium.transfer.controllers', ['cesium.services', 'cesium.curren .controller('TransferModalCtrl', TransferModalController) ; -function TransferController($scope, $controller, Device, UIUtils, csWot, csWallet) { +function TransferController($scope, $controller, UIUtils) { 'ngInject'; // Initialize the super class and extend it. @@ -52,49 +52,14 @@ function TransferController($scope, $controller, Device, UIUtils, csWot, csWalle $scope.enter = function(e, state) { - // Compute parameters - var parameters = {}; + // Apply state parameters if (state && state.stateParams) { - if (state.stateParams.pubkey) { - parameters.pubkey = state.stateParams.pubkey; - } - if (state.stateParams.amount) { - parameters.useRelative = false; - parameters.amount = state.stateParams.amount; - } - else if (state.stateParams.udAmount) { - parameters.useRelative = true; - parameters.udAmount = state.stateParams.udAmount; - } - if (state.stateParams.comment) { - parameters.comment = state.stateParams.comment; - } + $scope.setParameters(state.stateParams); } - // Make sure wallet is loaded - csWallet.login({sources: true}) - - // If pubkey, get the uid (+ name, avatar) - .then(function(data) { - $scope.walletData = data; - if (parameters.pubkey) { - return csWot.extend({pubkey: parameters.pubkey}) - .then(function(dest) { - if (dest && dest.uid) { - parameters.uid = dest.name || dest.uid; - } - }); - } - }) - - // Apply parameters, then recompute relative amount - .then(function() { - $scope.setParameters(parameters); - $scope.onUseRelativeChanged(); - UIUtils.loading.hide(); - $scope.loading = false; - UIUtils.ink({selector: '.modal-transfer .ink'}); - }); + // Load wallet + return $scope.load() + .then(UIUtils.loading.hide); }; $scope.$on('$ionicView.enter', $scope.enter); @@ -108,18 +73,25 @@ function TransferController($scope, $controller, Device, UIUtils, csWot, csWalle }; } -function TransferModalController($scope, $q, $translate, $timeout, $filter, $focus, Device, BMA, csWallet, UIUtils, Modals, - csCurrency, csSettings, parameters) { +function TransferModalController($scope, $q, $translate, $timeout, $filter, $focus, Device, BMA, UIUtils, Modals, + csWallet, csWot, csCurrency, csSettings, parameters) { 'ngInject'; - var minQuantitativeAmount = 0.01; + var + wallet, + minQuantitativeAmount = 0.01; + $scope.convertedBalance = 0; $scope.formData = { destPub: null, amount: null, comment: null, useRelative: csSettings.data.useRelative, - useComment: false + useComment: false, + all: false, + restPub: null, + restAmount: null, + walletId: null }; $scope.udAmount = null; $scope.minAmount = minQuantitativeAmount; @@ -127,6 +99,7 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc $scope.currency = csCurrency.data.name; $scope.loading = true; $scope.commentInputId = 'transferComment-' + $scope.$id; + $scope.enableSelectWallet = true; // Define keyboard settings, to bind with model (If small screen AND mobile devices) $scope.smallscreen = angular.isDefined($scope.smallscreen) ? $scope.smallscreen : UIUtils.screen.isSmall(); @@ -137,7 +110,7 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc { decimal: true, decimalSeparator: '.', - resizeContent: true + resizeContent:false }); $scope.digitKeyboardVisible = false; } @@ -167,69 +140,149 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc $scope.formData.useComment=true; $scope.formData.comment = parameters.comment; } + if (parameters.restPub || parameters.all) { + $scope.restUid = ''; + $scope.restPub = parameters.restPub; + $scope.formData.restPub = parameters.restPub; + $scope.formData.all = true; + } + else { + $scope.formData.all = false; + } + if (!parameters.wallet || parameters.wallet === "default") { + $scope.formData.walletId = csWallet.id; + } + else { + $scope.formData.walletId = parameters.wallet; + } }; // Read default parameters $scope.setParameters(parameters); - $scope.enter = function() { + $scope.load = function() { + $scope.enableSelectWallet = csWallet.children.count() > 0; + + wallet = $scope.enableSelectWallet && ($scope.formData.walletId ? csWallet.children.get($scope.formData.walletId) : csWallet) || csWallet; + if (!wallet.isDefault()) { + console.debug("[transfer] Using wallet {" + wallet.id + "}"); + } // Make to sure to load full wallet data (balance) - return csWallet.login({sources: true, silent: true}) + return wallet.login({sources: true, silent: true}) .then(function(data) { - $scope.walletData = data; - $scope.onUseRelativeChanged(); + if (!wallet || $scope.$$destroyed) return; // user have cancelled before end of load + $scope.walletData = data; + $scope.formData.walletId = wallet.id; + $scope.onUseRelativeChanged(); + $scope.onAmountChanged(); + + $scope.$watch('walletData.balance', $scope.onAmountChanged, true); + $scope.$watch('formData.amount', $scope.onAmountChanged, true); + + $scope.$watch('formData.useRelative', $scope.onUseRelativeChanged, true); + $scope.$watch('walletData.balance', $scope.onUseRelativeChanged, true); + + UIUtils.ink({selector: '.modal-transfer .ink'}); + + if (!$scope.destPub || $scope.destUid) { $scope.loading = false; - UIUtils.ink({selector: '.modal-transfer .ink'}); - }) - .catch(function(err){ - if (err == 'CANCELLED') return $scope.cancel(); // close the modal - UIUtils.onError('ERROR.LOGIN_FAILED')(err); - }); + } + else { + // Fill the uid from the pubkey + return csWot.extend({pubkey: $scope.destPub}) + .then(function(res) { + $scope.destUid = res && (res.name || res.uid); + if ($scope.destUid) { + $scope.destPub = ''; + } + $scope.loading = false; + }); + } + }) + .catch(function(err){ + if (err === 'CANCELLED') return $scope.cancel(); // close the modal + UIUtils.onError('ERROR.LOGIN_FAILED')(err); + }); }; - $scope.$on('modal.shown', $scope.enter); + $scope.$on('modal.shown', $scope.load); $scope.cancel = function() { $scope.closeModal(); + wallet = null; }; // When changing use relative UD $scope.onUseRelativeChanged = function() { $scope.currency = csCurrency.data.name; if ($scope.formData.useRelative) { - $scope.convertedBalance = csWallet.data.balance / csCurrency.data.currentUD; + $scope.convertedBalance = $scope.walletData.balance / csCurrency.data.currentUD; $scope.minAmount = minQuantitativeAmount / (csCurrency.data.currentUD / 100); } else { - $scope.convertedBalance = csWallet.data.balance / 100; + $scope.convertedBalance = $scope.walletData.balance / 100; $scope.minAmount = minQuantitativeAmount; } - if ($scope.form) { - $scope.form.$valid = undefined; + if ($scope.form && !$scope.loading) { + $scope.form.$setPristine(true); } }; - $scope.$watch('formData.useRelative', $scope.onUseRelativeChanged, true); - $scope.$watch('walletData.balance', $scope.onUseRelativeChanged, true); - $scope.doTransfer = function() { - $scope.form.$submitted=true; + $scope.onAmountChanged = function() { + if ($scope.sending) return; // skip if sending TX - if(!$scope.form.$valid || !$scope.formData.destPub || !$scope.formData.amount) { - return; - } var amount = $scope.formData.amount; - if (typeof amount === "string") { + if (amount && typeof amount === "string") { amount = parseFloat(amount.replace(new RegExp('[.,]'), '.')); } + var valid = true; + // Avoid amount less than the minimal - fix #373 - if (amount < $scope.minAmount) { + if (amount && amount < $scope.minAmount) { + valid = false; + $scope.form.amount.$error = $scope.form.amount.$error || {}; + $scope.form.amount.$error.min = true; + } + else if ($scope.form.amount && $scope.form.amount.$error && $scope.form.amount.$error.min){ + delete $scope.form.amount.$error.min; + } + + // Avoid amount greater than the balance + if (amount && amount > $scope.convertedBalance){ $scope.form.$valid = false; $scope.form.amount.$invalid = true; $scope.form.amount.$error = $scope.form.amount.$error || {}; - $scope.form.amount.$error.min = true; + $scope.form.amount.$error = {max: true}; + } + else if ($scope.form.amount && $scope.form.amount.$error && $scope.form.amount.$error.max){ + delete $scope.form.amount.$error.max; + } + + $scope.form.$valid = valid; + if ($scope.form.amount) $scope.form.amount.$invalid = !valid; + + if (!valid || !$scope.formData.all || !amount) { + $scope.formData.restAmount = undefined; + } + else { + if ($scope.formData.useRelative) { + $scope.formData.restAmount = $scope.walletData.balance - amount * csCurrency.data.currentUD; + if ($scope.formData.restAmount < minQuantitativeAmount) { + $scope.formData.restAmount = 0; + } + } else { + $scope.formData.restAmount = $scope.walletData.balance - amount * 100; + } + } + }; + + $scope.doTransfer = function() { + $scope.form.$submitted=true; + + if(!$scope.form.$valid || !$scope.formData.destPub || !$scope.formData.amount) { return; } - else if ($scope.form.amount.$error && $scope.form.amount.$error.min){ - $scope.form.amount.$invalid = false; - delete $scope.form.amount.$error.min; + var amount = $scope.formData.amount; + if (typeof amount === "string") { + amount = parseFloat(amount.replace(new RegExp('[.,]'), '.')); } // Avoid multiple call @@ -239,7 +292,7 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc var currentUD; return $q.all([ // Make sure user is auth - csWallet.auth({silent: true}), + wallet.auth({silent: true}), // Get current UD csCurrency.currentUD() @@ -272,36 +325,46 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc if (comment && !comment.length) { comment = null; } - - return csWallet.transfer($scope.formData.destPub, amount, comment, $scope.formData.useRelative); + var hasRest = $scope.formData.all && $scope.formData.restAmount > 0; + if (hasRest) { + return wallet.transferAll($scope.formData.destPub, amount, comment, $scope.formData.useRelative, $scope.formData.restPub); + } + else { + return wallet.transfer($scope.formData.destPub, amount, comment, $scope.formData.useRelative); + } }) .then(function() { - $scope.sending = false; UIUtils.loading.hide(); return $scope.closeModal(true); }) .then(function(res) { $timeout(function() { + $scope.sending = false; UIUtils.toast.show('INFO.TRANSFER_SENT'); }, 500); return res; - }) - .catch(function(err) { - $scope.sending = false; - UIUtils.onError('ERROR.SEND_TX_FAILED')(err); }); + }) + .catch(function(err) { + $scope.sending = false; + // Wallet auth cancelled by user + if (err === 'CANCELLED') return; + UIUtils.onError('ERROR.SEND_TX_FAILED')(err); }); }; $scope.askTransferConfirm = function() { return $translate(['COMMON.UD', 'COMMON.EMPTY_PARENTHESIS']) .then(function(translations) { - return $translate('CONFIRM.TRANSFER', { - from: csWallet.data.isMember ? csWallet.data.uid : $filter('formatPubkey')(csWallet.data.pubkey), - to: $scope.destUid ? $scope.destUid : $scope.destPub, + var hasRest = $scope.formData.all && $scope.formData.restAmount > 0; + return $translate(hasRest ? 'CONFIRM.TRANSFER_ALL' : 'CONFIRM.TRANSFER', { + from: $scope.walletData.isMember ? $scope.walletData.uid : $filter('formatPubkey')($scope.walletData.pubkey), + to: $scope.destUid || $scope.destPub, amount: $scope.formData.amount, unit: $scope.formData.useRelative ? translations['COMMON.UD'] : $filter('abbreviate')($scope.currency), - comment: (!$scope.formData.comment || $scope.formData.comment.trim().length === 0) ? translations['COMMON.EMPTY_PARENTHESIS'] : $scope.formData.comment + comment: (!$scope.formData.comment || $scope.formData.comment.trim().length === 0) ? translations['COMMON.EMPTY_PARENTHESIS'] : $scope.formData.comment, + restAmount: hasRest && $filter('formatAmount')($scope.formData.restAmount, {useRelative: $scope.formData.useRelative}), + restTo: hasRest && ($scope.restUid || $scope.restPub) }); }) .then(UIUtils.alert.confirm); @@ -310,34 +373,57 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc $scope.addComment = function() { $scope.formData.useComment = true; // Focus on comment field + // removeIf(device) if ($scope.commentInputId) { $timeout(function() { $focus($scope.commentInputId); }, 200); } + // endRemoveIf(device) }; /* -- modals -- */ - $scope.showWotLookupModal = function() { + $scope.showWotLookupModal = function(formDataField) { + + formDataField = formDataField || 'destPub'; + // Hide numerical keyboard $scope.hideDigitKeyboard(0); - return Modals.showWotLookup() + return Modals.showWotLookup({enableWallets: true}) .then(function(result){ if (result) { - if (result.uid) { + if (formDataField == 'destPub') { $scope.destUid = result.uid; - $scope.destPub = ''; + $scope.destPub = result.uid ? '' : result.pubkey; + $scope.formData.destPub = result.pubkey; } - else { - $scope.destUid = ''; - $scope.destPub = result.pubkey; + else if (formDataField == 'restPub') { + $scope.restUid = result.uid; + $scope.restPub = result.uid ? '' : result.pubkey; + $scope.formData.restPub = result.pubkey; } - $scope.formData.destPub = result.pubkey; } }); }; + $scope.showSelectWalletModal = function() { + if (!$scope.enableSelectWallet) return; + + return Modals.showSelectWallet({ + useRelative: $scope.formData.useRelative, + showDefault: true, + showBalance: true + }) + .then(function(newWallet) { + if (!newWallet || (wallet && wallet.id === newWallet.id)) return; + wallet = newWallet; + $scope.walletData = wallet.data; + console.debug("[transfer] Using wallet {" + wallet.id + "}"); + $scope.onAmountChanged(); + }); + }; + /* -- popover -- */ $scope.showUnitPopover = function($event) { @@ -372,7 +458,6 @@ function TransferModalController($scope, $q, $translate, $timeout, $filter, $foc return $q.when(); }; - $scope.hideDigitKeyboard = function(timeout) { if (!$scope.digitKeyboardVisible) return $q.when(); $scope.digitKeyboardVisible = false; diff --git a/assets/www/js/controllers/wallet-controllers.js b/assets/www/js/controllers/wallet-controllers.js index d07251642417d202a6016426eb15af5b2fc7e052..c2143bd4e8ed7083ae6e15809898b91b3b083748 100644 --- a/assets/www/js/controllers/wallet-controllers.js +++ b/assets/www/js/controllers/wallet-controllers.js @@ -6,7 +6,7 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency .state('app.view_wallet', { - url: "/wallet?refresh", + url: "/account?refresh", views: { 'menuContent': { templateUrl: "templates/wallet/view_wallet.html", @@ -14,12 +14,13 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency } }, data: { - login: true + login: true, + silentLocationChange: true } }) .state('app.view_wallet_tx', { - url: "/history?refresh", + url: "/history/account?refresh", views: { 'menuContent': { templateUrl: "templates/wallet/view_wallet_tx.html", @@ -33,7 +34,7 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency }) .state('app.view_wallet_tx_errors', { - url: "/wallet/tx/errors", + url: "/history/account/errors", views: { 'menuContent': { templateUrl: "templates/wallet/view_wallet_tx_error.html", @@ -47,7 +48,6 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency ; }) - .controller('WalletCtrl', WalletController) .controller('WalletTxCtrl', WalletTxController) @@ -57,17 +57,33 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency .controller('WalletSecurityModalCtrl', WalletSecurityModalController) ; -function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $translate, $ionicPopover, - UIUtils, Modals, BMA, csConfig, csSettings, csWallet, csHelp) { +function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $translate, $ionicPopover, $location, + UIUtils, ModalUtils, Modals, csPopovers, BMA, csConfig, csSettings, csWallet, csHelp) { 'ngInject'; $scope.loading = true; $scope.settings = csSettings.data; $scope.qrcodeId = 'qrcode-wallet-' + $scope.$id; + $scope.toggleQRCode = false; - $scope.$on('$ionicView.enter', function(e, state) { + + var wallet; + + $scope.enter = function(e, state) { $scope.loading = $scope.loading || (state.stateParams && state.stateParams.refresh); + $scope.enableSelectWallet = csWallet.children.count() > 0; if ($scope.loading) { // load once + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + $scope.isDefaultWallet = wallet.isDefault(); + $scope.walletId = wallet.id; + + $scope.cleanLocationHref(state); + return $scope.load(); } else { @@ -75,20 +91,24 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, UIUtils.loading.hide(); $timeout($scope.updateView, 300); } - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function() { - return $scope.loadWallet() + if (!wallet) return; + + return wallet.login() .then(function(walletData) { $scope.formData = walletData; $scope.loading=false; // very important, to avoid TX to be display before wallet.currentUd is loaded $scope.updateView(); $scope.showQRCode(); - $scope.showHelpTip(); + if (wallet.isDefault()) $scope.showHelpTip(); + $scope.addListeners(); UIUtils.loading.hide(); // loading could have be open (e.g. new account) }) .catch(function(err){ - if (err == 'CANCELLED') { + if (err === 'CANCELLED') { $scope.showHome(); } }); @@ -96,13 +116,9 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.updateView = function() { $scope.motion.show({selector: '#wallet .item'}); - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind + $scope.$broadcast('$$rebind::rebind'); // force rebind }; - // Listen new events (can appears from security wizard also) - $scope.$watchCollection('formData.events', function(newEvents, oldEvents) { - if (!oldEvents || $scope.loading || angular.equals(newEvents, oldEvents)) return; - $scope.updateView(); - }); + $scope.setRegisterForm = function(registerForm) { $scope.registerForm = registerForm; @@ -111,22 +127,43 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, // Clean controller data when logout $scope.onWalletLogout = function() { // clean QRcode - $scope.hideQRCode('qrcode'); + $scope.hideQRCode(); + $scope.removeListeners(); delete $scope.formData; + wallet = null; $scope.loading = true; }; - csWallet.api.data.on.logout($scope, $scope.onWalletLogout); + + $scope.addListeners = function() { + $scope.listeners = [ + // Reset the view on logout + wallet.api.data.on.logout($scope, $scope.onWalletLogout), + + // Listen new events (can appears from security wizard also) + $scope.$watchCollection('formData.events', function(newEvents, oldEvents) { + if (!oldEvents || $scope.loading || angular.equals(newEvents, oldEvents)) return; + $scope.updateView(); + }) + ]; + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; // Ask uid $scope.showUidPopup = function() { return $q(function(resolve, reject) { - $translate(['ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP', 'COMMON.BTN_OK', 'COMMON.BTN_CANCEL']) + $translate(['ACCOUNT.NEW.TITLE', 'ACCOUNT.POPUP_REGISTER.TITLE', 'ACCOUNT.POPUP_REGISTER.HELP', 'COMMON.BTN_OK', 'COMMON.BTN_CANCEL']) .then(function (translations) { $scope.formData.newUid = (!!$scope.formData.uid ? ''+$scope.formData.uid : ''); // Choose UID popup $ionicPopup.show({ - templateUrl: 'templates/login/popup_register.html', + templateUrl: 'templates/wallet/popup_register.html', title: translations['ACCOUNT.POPUP_REGISTER.TITLE'], subTitle: translations['ACCOUNT.POPUP_REGISTER.HELP'], scope: $scope, @@ -167,7 +204,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, .then(function(uid) { UIUtils.loading.show(); - return csWallet.self(uid) + return wallet.self(uid) .then(function() { $scope.updateView(); UIUtils.loading.hide(); @@ -182,17 +219,21 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, }; $scope.doMembershipIn = function(retryCount) { - return csWallet.membership.inside() + return wallet.membership.inside() .then(function() { $scope.updateView(); UIUtils.loading.hide(); }) .catch(function(err) { - if (err == 'CANCELLED') throw err; - if (err && err.ucode != BMA.errorCodes.MEMBERSHIP_ALREADY_SEND) return; + if (err === 'CANCELLED') throw err; + if (err && err.ucode != BMA.errorCodes.MEMBERSHIP_ALREADY_SEND) { + console.error("[wallet] Node: already membership", err); + UIUtils.loading.hide(); + return; // OK + } if (!retryCount || retryCount <= 2) { return $timeout(function() { - $scope.doMembershipIn(retryCount ? retryCount+1 : 1); + return $scope.doMembershipIn((retryCount||0) + 1); }, 1000); } throw err; @@ -204,48 +245,27 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.membershipIn = function(keepSelf) { $scope.hideActionsPopover(); - if (csWallet.isMember()) { + if (wallet.isMember()) { return UIUtils.alert.info("INFO.NOT_NEED_MEMBERSHIP"); } - // Select uid (or reuse it) - return ((keepSelf && !!$scope.formData.blockUid) ? - $q.when($scope.formData.uid) : - $scope.showUidPopup()) - - // Ask user confirmation - .then(function(uid) { - return UIUtils.alert.confirm("CONFIRM.MEMBERSHIP") - .then(function(confirm) { - if (!confirm) throw 'CANCELLED'; - return uid; - }); - }) - - // Send self (identity) - if need - .then(function (uid) { - UIUtils.loading.show(); - - // If uid changed, or self blockUid not retrieve : do self() first - if (!$scope.formData.blockUid || uid != $scope.formData.uid) { - $scope.formData.blockUid = null; - $scope.formData.uid = uid; - - return csWallet.self(uid, false/*do NOT load membership here*/); - } - }) + var uid = angular.isDefined($scope.formData.blockUid) && $scope.formData.uid || undefined; - // Send membership - .then($scope.doMembershipIn) - .catch(function(err) { - if (err == 'CANCELLED') return; - if (!csWallet.data.uid) { - UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')(err); - } - else { - UIUtils.onError('ERROR.SEND_MEMBERSHIP_IN_FAILED')(err); - } - }); + // Approve the license + return Modals.showJoinMember({ + uid : uid, + blockUid: uid && $scope.formData.blockUid, + pubkey: $scope.formData.pubkey + }) + .catch(function(err) { + if (err === 'CANCELLED') return; + if (!wallet.data.uid) { + UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')(err); + } + else { + UIUtils.onError('ERROR.SEND_MEMBERSHIP_IN_FAILED')(err); + } + }); }; // Send membership OUT @@ -276,7 +296,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, } UIUtils.loading.show(); - return csWallet.membership.out() + return wallet.membership.out() .then(function() { UIUtils.loading.hide(); UIUtils.toast.show('INFO.MEMBERSHIP_OUT_SENT'); @@ -288,9 +308,9 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.doUpdate = function(silent) { console.debug('[wallet] Refreshing data...'); return (silent ? - csWallet.refreshData() : + wallet.refreshData() : UIUtils.loading.show() - .then(csWallet.refreshData) + .then(wallet.refreshData) .then(UIUtils.loading.hide) ) .then($scope.updateView) @@ -302,20 +322,26 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, */ $scope.renewMembership = function(confirm) { - if (!$scope.formData.isMember && !$scope.formData.requirements.wasMember) { + // Make sure user is (or was) a member + if (!wallet.isMember() && !$scope.formData.requirements.wasMember) { return UIUtils.alert.error("ERROR.ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION"); } + + // If renew is not need, ask confirmation if (!confirm && !$scope.formData.requirements.needRenew) { return $translate("CONFIRM.NOT_NEED_RENEW_MEMBERSHIP", {membershipExpiresIn: $scope.formData.requirements.membershipExpiresIn}) .then(function(message) { return UIUtils.alert.confirm(message); }) .then(function(confirm) { - if (confirm) $scope.renewMembership(true); // loop with confirm + if (confirm) { + // loop with confirm + return $scope.renewMembership(true); + } }); } - return csWallet.auth({minData: true}) // Ask user to auth, before confirmation - fix #508 + return wallet.auth({minData: true}) // Ask user to auth, before confirmation - fix #508 .then(function() { UIUtils.loading.hide(); return UIUtils.alert.confirm("CONFIRM.RENEW_MEMBERSHIP"); @@ -327,7 +353,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, } }) .catch(function(err){ - if (err == 'CANCELLED') return; + if (err === 'CANCELLED') return; UIUtils.loading.hide(); UIUtils.alert.error(err); }); @@ -341,7 +367,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, if (!$scope.formData.uid) return; return $q.all([ - csWallet.auth(), + wallet.auth(), $translate('CONFIRM.FIX_IDENTITY', {uid: $scope.formData.uid}) ]) .then(function(res) { @@ -354,11 +380,11 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.formData.blockUid = null; // Reset membership data $scope.formData.sigDate = null; - return csWallet.self($scope.formData.uid); + return wallet.self($scope.formData.uid); }) .then($scope.doMembershipIn) .catch(function(err){ - if (err == 'CANCELLED') return; + if (err === 'CANCELLED') return; UIUtils.loading.hide(); UIUtils.alert.error(err); }); @@ -370,11 +396,13 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.fixMembership = function() { if (!$scope.formData.uid) return; - if (csWallet.isMember()) { + if (wallet.isMember()) { return UIUtils.alert.info("INFO.NOT_NEED_MEMBERSHIP"); } - return csWallet.auth() + $scope.hideActionsPopover(); + + return wallet.auth({silent: true}) .then(function() { UIUtils.alert.confirm("CONFIRM.FIX_MEMBERSHIP"); }) @@ -385,11 +413,11 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.formData.blockUid = null; // Reset membership data $scope.formData.sigDate = null; - return csWallet.self($scope.formData.uid, false/*do NOT load membership here*/); + return wallet.self($scope.formData.uid, false/*do NOT load membership here*/); }) .then($scope.doMembershipIn) .catch(function(err){ - if (err == 'CANCELLED') return; + if (err === 'CANCELLED') return; UIUtils.loading.hide(); UIUtils.alert.error(err); }); @@ -400,37 +428,27 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, * @param fix */ $scope.doQuickFix = function(event) { - if (event == 'renew') { + if (event === 'renew') { $scope.renewMembership(); } - else if (event == 'membership') { + else if (event === 'membership') { $scope.membershipIn(true/*keep self*/); } - else if (event == 'fixMembership') { - $scope.fixMembership(); + else if (event === 'fixMembership') { + $scope.fixMembership(false); } - else if (event == 'fixIdentity') { + else if (event === 'fixIdentity') { $scope.fixIdentity(); } }; - /* -- popup / UI -- */ + /* -- UI actions -- */ - // Transfer - $scope.showTransferModal = function() { - var hasCredit = (!!$scope.formData.balance && $scope.formData.balance > 0); - if (!hasCredit) { - UIUtils.alert.info('INFO.NOT_ENOUGH_CREDIT'); - return; + var inheritedLogout = $scope.logout; + $scope.logout = function(options) { + if ($scope.isDefaultWallet) { + return inheritedLogout(options); } - Modals.showTransfer() - .then(function(done){ - if (done) { - UIUtils.toast.show('INFO.TRANSFER_SENT'); - $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance - $scope.motion.show({selector: '.item-pending'}); - } - }); }; $scope.startWalletTour = function() { @@ -448,8 +466,8 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.qrcodeId, { text: $scope.formData.pubkey, - width: 200, - height: 200, + width: 180, + height: 180, correctLevel: QRCode.CorrectLevel.L }); UIUtils.motion.toggleOn({selector: '#'+$scope.qrcodeId}, timeout || 1100); @@ -461,7 +479,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, } }; - $scope.hideQRCode = function(id) { + $scope.hideQRCode = function() { if ($scope.qrcode) { $scope.qrcode.clear(); UIUtils.motion.toggleOff({selector: '#'+$scope.qrcodeId}); @@ -470,71 +488,66 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.showCertifications = function() { // Warn: do not use a simple link here (a ng-click is mandatory for help tour) - $state.go(UIUtils.screen.isSmall() ? 'app.wallet_cert' : 'app.wallet_cert_lg', { - pubkey: $scope.formData.pubkey, - uid: $scope.formData.name || $scope.formData.uid, - type: 'received' - }); + if ($scope.isDefaultWallet) { + $state.go(UIUtils.screen.isSmall() ? 'app.wallet_cert' : 'app.wallet_cert_lg', { + type: 'received' + }); + } + else { + $state.go(UIUtils.screen.isSmall() ? 'app.wallet_cert_by_id' : 'app.wallet_cert_by_id_lg', { + id: $scope.walletId, + type: 'received' + }); + } }; $scope.showGivenCertifications = function() { // Warn: do not use a simple link here (a ng-click is mandatory for help tour) + if ($scope.isDefaultWallet) { $state.go(UIUtils.screen.isSmall() ? 'app.wallet_cert' : 'app.wallet_cert_lg', { - pubkey: $scope.formData.pubkey, - uid: $scope.formData.name || $scope.formData.uid, type: 'given' - }); - }; - - $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('templates/wallet/popover_actions.html', { - scope: $scope - }).then(function(popover) { - $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); }); } else { - $scope.actionsPopover.show(event); + $state.go(UIUtils.screen.isSmall() ? 'app.wallet_cert_by_id' : 'app.wallet_cert_by_id_lg', { + id: $scope.walletId, + type: 'given' + }); } }; - $scope.hideActionsPopover = function() { - if ($scope.actionsPopover) { - $scope.actionsPopover.hide(); - } + $scope.showTxHistory = function() { + $state.go($scope.isDefaultWallet ? 'app.view_wallet_tx' : 'app.view_wallet_tx_by_id', { + id: $scope.walletId + }); }; - $scope.showSharePopover = function(event) { - $scope.hideActionsPopover(); + $scope.showLicenseModal = function() { + return ModalUtils.show('templates/currency/modal_license.html','CurrencyLicenseModalCtrl'); + }; - var title = $scope.formData.name || $scope.formData.uid || $scope.formData.pubkey; - // Use shareBasePath (fix #530) or rootPath (fix #390) - var url = (csConfig.shareBaseUrl || $rootScope.rootPath) + $state.href('app.wot_identity', {pubkey: $scope.formData.pubkey, uid: $scope.formData.name || $scope.formData.uid}); + /* -- modals -- */ - // Override default position, is small screen - fix #545 - if (UIUtils.screen.isSmall()) { - event = angular.element(document.querySelector('#wallet-share-anchor')) || event; + // Transfer + $scope.showTransferModal = function() { + var hasCredit = (!!$scope.formData.balance && $scope.formData.balance > 0); + if (!hasCredit && !csWallet.children.count()) { + UIUtils.alert.info('INFO.NOT_ENOUGH_CREDIT'); + return; } - - UIUtils.popover.share(event, { - bindings: { - url: url, - titleKey: 'WOT.VIEW.POPOVER_SHARE_TITLE', - titleValues: {title: title}, - postMessage: title - } - }); + return Modals.showTransfer({wallet: wallet.id}) + .then(function(done){ + if (done) { + UIUtils.toast.show('INFO.TRANSFER_SENT'); + $scope.$broadcast('$$rebind::balance'); // force rebind balance + $scope.motion.show({selector: '.item-pending'}); + } + }); }; $scope.showSecurityModal = function(){ $scope.hideActionsPopover(); - return Modals.showAccountSecurity() + return Modals.showAccountSecurity({wallet: wallet}) .then(function(res) { if (!res) return; @@ -559,7 +572,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.loading = true; // Set self (= uid + blockUid) - return csWallet.setSelf(idty.uid, idty.blockUid) + return wallet.setSelf(idty.uid, idty.blockUid) .then(function() { $scope.loading=false; $scope.updateView(); @@ -568,51 +581,185 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, }); }; + $scope.showSelectWalletModal = function() { + if (!csWallet.children.count()) return; + + return Modals.showSelectWallet({ + parameters: { + showDefault: true, + showBalance: false, + excludedWalletId: $scope.walletId + } + }) + .then(function(newWallet) { + if (!newWallet || wallet && newWallet.id === wallet.id) return; + $scope.removeListeners(); + $scope.loading = true; + wallet = newWallet; + console.debug("[transfer] Using wallet {" + wallet.id + "}"); + $scope.formData = {}; + return $scope.load(); + }); + }; + + /* -- popovers -- */ + + $scope.showActionsPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'templates/wallet/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } + }); + }; + + $scope.hideActionsPopover = function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + $scope.actionsPopover = null; + } + }; + + $scope.showSharePopover = function(event) { + $scope.hideActionsPopover(); + + var title = $scope.formData.name || $scope.formData.uid || $scope.formData.pubkey; + // Use shareBasePath (fix #530) or rootPath (fix #390) + var url = (csConfig.shareBaseUrl || $rootScope.rootPath) + $state.href('app.wot_identity', {pubkey: $scope.formData.pubkey, uid: $scope.formData.uid}); + + // Override default position, is small screen - fix #545 + if (UIUtils.screen.isSmall()) { + event = angular.element(document.querySelector('#wallet-share-anchor')) || event; + } + + UIUtils.popover.share(event, { + bindings: { + url: url, + titleKey: 'WOT.VIEW.POPOVER_SHARE_TITLE', + titleValues: {title: title}, + postMessage: title + } + }); + }; + + $scope.showSelectWalletPopover = function(event) { + + return csPopovers.showSelectWallet(event, { + parameters: { + excludedWalletId: $scope.walletId + }}) + .then(function(newWallet) { + if (!newWallet || newWallet.id === $scope.walletId) return; // nothing changed + if (newWallet.isDefault()) { + return $state.go('app.view_wallet'); + } + return $state.go('app.view_wallet_by_id', {id: newWallet.id}); + }); + }; + + // remove '?refresh' from the location URI + $scope.cleanLocationHref = function(state) { + if (state && state.stateParams && state.stateParams.refresh) { + $timeout(function() { + var stateParams = angular.copy(state.stateParams); + delete stateParams.refresh; + delete stateParams.id; + $location.search(stateParams).replace(); + }, 300); + } + }; } function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, - UIUtils, Modals, BMA, csSettings, csWallet, csTx) { + UIUtils, Modals, csPopovers, BMA, csHttp, csSettings, csCurrency, csWallet, csTx) { 'ngInject'; $scope.loading = true; $scope.settings = csSettings.data; + $scope.listeners = []; - $scope.$on('$ionicView.enter', function(e, state) { + var wallet; + + $scope.enter = function(e, state) { $scope.loading = $scope.loading || (state.stateParams && state.stateParams.refresh); + $scope.enableSelectWallet = csWallet.children.count() > 0; if ($scope.loading) { - $scope.loadWallet() - .then(function (res) { - $scope.formData = res; - $scope.loading = false; // very important, to avoid TX to be display before wallet.currentUd is loaded - $scope.updateView(); - $scope.showFab('fab-transfer'); - $scope.showHelpTip(); - UIUtils.loading.hide(); // loading could have be open (e.g. new account) - - // remove the stateParams - if (state.stateParams && state.stateParams.refresh) { - $location.search({}).replace(); - } - }) - .catch(function (err) { - if (err == 'CANCELLED') { - $scope.showHome(); - } - }); + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + $scope.walletId = wallet.id; + + $scope.cleanLocationHref(state); + + return $scope.load(); } else { + $scope.addListeners(); // Make sure to display new pending (e.g. sending using another screen button) $timeout($scope.updateView, 300); } - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); + + $scope.leave = function() { + $scope.removeListeners(); + }; + $scope.$on('$ionicView.leave', $scope.leave); + + $scope.load = function() { + if (!wallet) return; + + var hasMinData = wallet.isDataLoaded({minData: true}); + var options = { + requirements: !hasMinData, // load requirements (=minData) once + minData: !hasMinData, + sources: true, + tx: { + enable: true + } + }; + + return wallet.login(options) + .then(function(walletData) { + $scope.formData = walletData; + $scope.loading = false; // very important, to avoid TX to be display before wallet.currentUd is loaded + $scope.updateView(); + $scope.showFab('fab-transfer'); + if (wallet.isDefault()) $scope.showHelpTip(); + $scope.addListeners(); + UIUtils.loading.hide(); // loading could have be open (e.g. during login phase) + }) + .catch(function(err){ + if (err === 'CANCELLED') { + $scope.showHome(); + } + }); + }; + // remove '?refresh' from the location URI + $scope.cleanLocationHref = function(state) { + if (state && state.stateParams && state.stateParams.refresh) { + $timeout(function() { + var stateParams = angular.copy(state.stateParams); + delete stateParams.refresh; + delete stateParams.id; + $location.search(stateParams).replace(); + }, 300); + } + }; // Update view $scope.updateView = function() { if (!$scope.formData || $scope.loading) return; - $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind + $scope.$broadcast('$$rebind::balance'); // force rebind balance + $scope.$broadcast('$$rebind::rebind'); // force rebind $scope.motion.show({selector: '.view-wallet-tx .item', ink: false}); }; @@ -626,10 +773,23 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, // Updating wallet data $scope.doUpdate = function(silent) { console.debug('[wallet] TX history reloading...'); + var fromTime = $scope.formData && $scope.formData.tx && $scope.formData.tx.fromTime || undefined; + var options = { + sources: true, + tx: { + enable: true, + fromTime: fromTime + }, + api: false + }; return (silent ? - csWallet.refreshData() : + // If silent: just refresh + wallet.refreshData(options) : + // If not silent: show/hide loading indicator UIUtils.loading.show() - .then(csWallet.refreshData) + .then(function() { + return wallet.refreshData(options); + }) .then(UIUtils.loading.hide) ) .then($scope.updateView) @@ -638,38 +798,78 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, /* -- add listeners -- */ - csWallet.api.data.on.balanceChanged($scope, $scope.updateView); - $scope.$watch('settings.useRelative', $scope.updateView); - $scope.$watch('settings.showUDHistory', function() { - // Reload if show UD changed - if (!$scope.formData || $scope.loading) return; - $scope.doUpdate(); - }, true); + $scope.addListeners = function() { + $scope.listeners = [ + // Reload if wallet balanced changed + wallet.api.data.on.balanceChanged($scope, $scope.updateView), + // Reload if useRelative changed + $scope.$watch('settings.useRelative', $scope.updateView, true), + // Reload if showUDHistory changed + $scope.$watch('settings.showUDHistory', function(newVal, oldVal) { + if (!$scope.formData || $scope.loading || (newVal === oldVal)) return; + $scope.doUpdate(); + }, true) + ]; + + // Listening new block (if auto refresh enable) + if ($scope.settings.walletHistoryAutoRefresh) { + $scope.listeners.push( + csCurrency.api.data.on.newBlock($scope, function(block) { + if ($scope.loading) return; + console.debug("[wallet] Received new block. Will reload history."); + $timeout(function() { + $scope.doUpdate(true); + }, 500/*waiting for block propagation*/); + }) + ); + } + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; /* -- popup / UI -- */ // Transfer $scope.showTransferModal = function() { var hasCredit = (!!$scope.formData.balance && $scope.formData.balance > 0); - if (!hasCredit) { + if (!hasCredit && !csWallet.children.count()) { UIUtils.alert.info('INFO.NOT_ENOUGH_CREDIT'); return; } - return Modals.showTransfer(); + return Modals.showTransfer({wallet: wallet.id}) + .then(function(done){ + if (done) { + UIUtils.toast.show('INFO.TRANSFER_SENT'); + $scope.$broadcast('$$rebind::balance'); // force rebind balance + $scope.motion.show({selector: '.item-pending'}); + } + }); }; $scope.showHelpTip = function(index, isTour) { // TODO }; + $scope.showTxErrors = function(event) { + if (wallet.isDefault()) { + return $scope.goState('app.view_wallet_tx_errors'); + } + return $scope.goState('app.view_wallet_tx_errors_by_id', {id: wallet.id}); + }; + $scope.showMoreTx = function(fromTime) { fromTime = fromTime || ($scope.formData.tx.fromTime - csSettings.data.walletHistoryTimeSecond) || - (Math.trunc(new Date().getTime() / 1000) - 2 * csSettings.data.walletHistoryTimeSecond); + (csHttp.date.now() - 2 * csSettings.data.walletHistoryTimeSecond); UIUtils.loading.show(); - return csWallet.refreshData({tx: {enable: true,fromTime: fromTime}}) + return wallet.refreshData({tx: {enable: true, fromTime: fromTime}}) .then(function() { $scope.updateView(); UIUtils.loading.hide(); @@ -687,6 +887,27 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, }); }; + $scope.showSelectWalletModal = function() { + if (!csWallet.children.count()) return; + + return Modals.showSelectWallet({ + parameters: { + showDefault: true, + showBalance: false, + excludedWalletId: $scope.walletId + } + }) + .then(function(newWallet) { + if (!newWallet || wallet && newWallet.id === wallet.id) return; + $scope.removeListeners(); + $scope.loading = true; + wallet = newWallet; + console.debug("[transfer] Using wallet {" + wallet.id + "}"); + $scope.formData = {}; + return $scope.load(); + }); + }; + /* -- popover -- */ var paddingIndent = 10; @@ -738,21 +959,14 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, }, []); // Open popover - if (!$scope.lockedOutputsPopover) { - $ionicPopover.fromTemplateUrl('templates/wallet/tx_locked_outputs_popover.html', { - scope: $scope - }).then(function(popover) { - $scope.lockedOutputsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.lockedOutputsPopover.remove(); - }); - $scope.lockedOutputsPopover.show(event); - }); - } - else { - $scope.lockedOutputsPopover.show(event); - } + UIUtils.popover.show(event, { + templateUrl: 'templates/wallet/tx_locked_outputs_popover.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } + }); }; $scope.hideLockedOutputsPopover = function() { @@ -761,41 +975,79 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, if ($scope.popoverData) { delete $scope.popoverData.unlockConditions; } + $scope.lockedOutputsPopover = null; } }; + $scope.showSelectWalletPopover = function(event) { + return csPopovers.showSelectWallet(event, { + scope: $scope + }) + .then(function(newWallet) { + if (!newWallet || newWallet.id === wallet.id) return; + if (newWallet.isDefault()) { + return $scope.goState('app.view_wallet_tx'); + } + return $scope.goState('app.view_wallet_tx_by_id', {id: newWallet.id}); + }); + }; + $scope.goState = function(stateName, stateParams) { $scope.hideLockedOutputsPopover(); - $state.go(stateName, stateParams); + return $state.go(stateName, stateParams); }; } -function WalletTxErrorController($scope, UIUtils, csWallet) { +function WalletTxErrorController($scope, UIUtils, csSettings, csWallet) { 'ngInject'; + var wallet; + $scope.settings = csSettings.data; + $scope.loading = true; $scope.formData = {}; - $scope.$on('$ionicView.enter', function(e) { - $scope.loadWallet() + $scope.$on('$ionicView.enter', function(e, state) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + return $scope.load(); + }); + + $scope.load = function() { + if (!wallet) return; + + return wallet.login() .then(function(walletData) { $scope.formData = walletData; + $scope.loading = false; $scope.doMotion(); - $scope.showFab('fab-redo-transfer'); + //$scope.showFab('fab-redo-transfer'); UIUtils.loading.hide(); }); - }); + }; // Updating wallet data $scope.doUpdate = function(silent) { + $scope.loading = true; return (silent ? - csWallet.refreshData() : + wallet.refreshData() : UIUtils.loading.show() .then(csWallet.refreshData) .then(UIUtils.loading.hide) ) - .then($scope.doMotion) - .catch(UIUtils.onError('ERROR.REFRESH_WALLET_DATA')); + .then(function() { + $scope.doMotion(); + $scope.loading = false; + }) + .catch(function(err) { + UIUtils.onError('ERROR.REFRESH_WALLET_DATA')(err); + $scope.loading = false; + }); }; $scope.filterReceivedTx = function(tx){ @@ -806,9 +1058,19 @@ function WalletTxErrorController($scope, UIUtils, csWallet) { return tx.amount && tx.amount < 0; }; + $scope.hasReceivedTx = function(){ + return $scope.formData.tx && _($scope.formData.tx.errors || []).find($scope.filterReceivedTx) && true; + }; + + $scope.hasSentTx = function(){ + return $scope.formData.tx && _($scope.formData.tx.errors || []).find($scope.filterSentTx) && true; + }; + } -function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ +function WalletSecurityModalController($scope, UIUtils, csWallet, $translate, parameters){ + + var wallet = parameters && parameters.wallet || csWallet; $scope.slides = { slider: null, @@ -824,11 +1086,13 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ $scope.recover = {}; $scope.isValidFile = false; - $scope.isLogin = csWallet.isLogin(); - $scope.hasSelf = csWallet.hasSelf(); - $scope.needSelf = $scope.isLogin && csWallet.data.requirements.needSelf; - $scope.needMembership = $scope.isLogin && csWallet.data.requirements.needMembership; - $scope.option = $scope.isLogin ? 'saveID' : 'recoverID'; + + $scope.login = wallet.isLogin(); + $scope.hasSelf = wallet.hasSelf(); + $scope.needSelf = $scope.login && wallet.data.requirements.needSelf; + $scope.canRevoke = $scope.login && $scope.hasSelf && !wallet.data.requirements.revoked; + $scope.needMembership = $scope.login && wallet.data.requirements.needMembership; + $scope.option = $scope.login ? 'saveID' : 'recoverID'; $scope.formData = { addQuestion: '', @@ -1011,7 +1275,7 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ $scope.recover.answer += element.answer; }); - return csWallet.recoverId($scope.recover) + return wallet.recoverId($scope.recover) .then(function (recover){ if (angular.isDefined(recover)) { $scope.recover = recover; @@ -1037,7 +1301,7 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ $scope.downloadSaveIDFile = function(){ // Force user re-auth var loginData; - return csWallet.auth({ + return wallet.auth({ forceAuth: true, expectedPubkey: $scope.pubkey, silent: true, @@ -1046,7 +1310,7 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ } }) .catch(function(err) { - if (err && err == 'CANCELLED') return; + if (err && err === 'CANCELLED') return; UIUtils.alert.error('ERROR.SALT_OR_PASSWORD_NOT_CONFIRMED', 'ERROR.LOGIN_FAILED'); return; }) @@ -1068,9 +1332,9 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ record.answer += question.answer; }); - return csWallet.getCryptedId(record) + return wallet.getCryptedId(record) .then(function(record){ - csWallet.downloadSaveId(record); + wallet.downloadSaveId(record); $scope.closeModal(); }); }) @@ -1098,11 +1362,11 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ */ $scope.downloadRevokeFile = function () { // Force re-authentication - return csWallet.auth({forceAuth: true}) + return wallet.auth({forceAuth: true}) // Download file .then(function() { - return csWallet.downloadRevocation(); + return wallet.downloadRevocation(); }) .then(function() { @@ -1110,7 +1374,7 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ }) .catch(function(err){ - if (err && err == 'CANCELLED') return; + if (err && err === 'CANCELLED') return; UIUtils.onError('ERROR.DOWNLOAD_REVOCATION_FAILED')(err); }) ; @@ -1126,14 +1390,14 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ } // Make sure user re-auth - return csWallet.auth({forceAuth: true}) + return wallet.auth({forceAuth: true}) .then(function(confirm) { UIUtils.loading.hide(); if (!confirm) return; return $scope.revokeIdentity(); }) .catch(function (err) { - if (err == 'CANCELLED') return; + if (err === 'CANCELLED') return; UIUtils.onError('ERROR.REVOCATION_FAILED')(err); }); }; @@ -1166,10 +1430,10 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ return UIUtils.loading.show() .then(function () { if (!$scope.revocation){ - return csWallet.revoke(); + return wallet.revoke(); } else { - return csWallet.revokeWithFile($scope.revocation); + return wallet.revokeWithFile($scope.revocation); } }) .then(function () { @@ -1200,11 +1464,11 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ */ $scope.downloadKeyFile = function (format) { // Force re-authentication - return csWallet.auth({forceAuth: true}) + return wallet.auth({forceAuth: true}) // Download file .then(function() { - return csWallet.downloadKeyFile(format); + return wallet.downloadKeyFile(format); }) .then(function() { @@ -1213,12 +1477,12 @@ function WalletSecurityModalController($scope, UIUtils, csWallet, $translate){ }) .catch(function(err){ - if (err && err == 'CANCELLED') return; + if (err && err === 'CANCELLED') { + UIUtils.loading.hide(); + return; + } UIUtils.onError('ERROR.DOWNLOAD_KEYFILE_FAILED')(err); }) ; }; - } - - diff --git a/assets/www/js/controllers/wallets-controllers.js b/assets/www/js/controllers/wallets-controllers.js new file mode 100644 index 0000000000000000000000000000000000000000..5e9a7cfc0eb3307091d9f4ab64b46199a399ffd8 --- /dev/null +++ b/assets/www/js/controllers/wallets-controllers.js @@ -0,0 +1,833 @@ +angular.module('cesium.wallets.controllers', ['cesium.services', 'cesium.currency.controllers']) + + .config(function($stateProvider) { + 'ngInject'; + $stateProvider + + .state('app.view_wallets', { + url: "/wallets", + views: { + 'menuContent': { + templateUrl: "templates/wallet/list/view_wallets.html", + controller: 'WalletListViewCtrl' + } + }, + data: { + login: true + } + }) + + .state('app.view_wallet_by_id', { + url: "/wallets/:id?refresh", + views: { + 'menuContent': { + templateUrl: "templates/wallet/view_wallet.html", + controller: 'WalletCtrl' + } + }, + data: { + login: true, + silentLocationChange: true + } + }) + + .state('app.view_wallet_tx_by_id', { + url: "/history/wallets/:id?refresh", + views: { + 'menuContent': { + templateUrl: "templates/wallet/view_wallet_tx.html", + controller: 'WalletTxCtrl' + } + }, + data: { + login: true, + silentLocationChange: true + } + }) + + .state('app.view_wallet_tx_errors_by_id', { + url: "/history/wallets/:id/errors", + views: { + 'menuContent': { + templateUrl: "templates/wallet/view_wallet_tx_error.html", + controller: 'WalletTxErrorCtrl' + } + }, + data: { + login: true + } + }) + ; + }) + .controller('WalletListAbstractCtrl', WalletListAbstractController) + + .controller('WalletListViewCtrl', WalletListViewController) + + .controller('WalletSelectModalCtrl', WalletSelectModalController) + + .controller('WalletListImportModalCtrl', WalletListImportModalController) + + .controller('WalletSelectPopoverCtrl', WalletSelectPopoverController) +; + + +function WalletListAbstractController($scope, $q, $timeout, UIUtils, filterTranslations, csSettings, csCurrency, csWallet) { + 'ngInject'; + + $scope.loading = true; + $scope.wallets = null; + $scope.formData = { + useRelative: csSettings.data.useRelative, + showDefault: true, + showBalance: false, + balance: undefined, + updatingWalletId: undefined, + stopped: false, + minData: true + }; + $scope.motion = null; // no animation + + $scope.setParameters = function(parameters) { + parameters = parameters || {}; + + $scope.formData.useRelative = angular.isDefined(parameters.useRelative) ? parameters.useRelative : $scope.formData.useRelative; + $scope.formData.showBalance = angular.isDefined(parameters.showBalance) ? parameters.showBalance : $scope.formData.showBalance; + $scope.formData.minData = angular.isDefined(parameters.minData) ? parameters.minData : $scope.formData.minData; + $scope.formData.excludedWalletId = parameters.excludedWalletId; + $scope.formData.showDefault = (angular.isDefined(parameters.showDefault) ? parameters.showDefault : $scope.formData.showDefault) && + ($scope.formData.excludedWalletId !== 'default'); + + }; + + $scope.load = function(options) { + + options = options || {}; + $scope.loading = (options.silent !== false); + $scope.formData.balance = undefined; + $scope.formData.updatingWalletId = undefined; + $scope.formData.stopped = false; + + // Load currency, and filter translations (need by 'formatAmount' filter) + var jobs = []; + + jobs.push(csCurrency.name() + .then(function(currency) { + $scope.currency = currency; + return filterTranslations.ready(); + })); + + // Get children wallets + $scope.defaultWallet = $scope.formData.showDefault ? csWallet : undefined; + if (!$scope.wallets) { + jobs.push( + csWallet.children.all() + .then(function(children) { + $scope.wallets=children; + UIUtils.loading.hide(); + }) + ); + } + + // Prepare load options + var walletLoadOptions = { + silent: true, + minData: $scope.formData.minData, + sources: $scope.formData.showBalance, + tx: { + enable: false + }, + api: true + }; + var hasLoadError = false; + var loadCounter = 0; + var now = Date.now(); + var balance = 0; + return (jobs.length ? $q.all(jobs) : $q.when()) + // Load wallet data (apply a timeout between each wallet) + .then(function() { + var wallets = $scope.formData.showDefault ? [csWallet].concat($scope.wallets) : $scope.wallets; + if (!wallets.length) return; + console.debug("[wallets] Loading {0} wallets...".format(wallets.length)); + return wallets.reduce(function(res, wallet) { + var skip= !options.refresh && wallet.isDataLoaded(walletLoadOptions); + if (skip) { + console.debug("[wallets] Wallet #{0} already loaded. Skipping".format(wallet.id)); + return res.then(function(){ + balance += wallet.data.balance; + $scope.updateWalletView(wallet.id); + }); + } + loadCounter++; + return res.then(function() { + if ($scope.formData.stopped) return; // skip if stopped + // Loading next wallet, after waiting some time + $scope.formData.updatingWalletId = wallet.id; + var loadPromise; + if (options.refresh && wallet.data.loaded) { + var refreshOptions = angular.merge({ + // Refresh requirements if member account + requirements: (!wallet.data.requirements.loaded || wallet.data.requirements.isMember || wallet.data.requirements.wasMember || wallet.data.requirements.pendingMembership) + }, walletLoadOptions); + loadPromise = wallet.refreshData(refreshOptions); + } + else { + loadPromise = wallet.loadData(walletLoadOptions); + } + + loadPromise.then(function(walletData) { + balance += walletData.balance; + $scope.updateWalletView(wallet.id); + }) + .catch(function(err) { + console.error("[wallets] Error while loading data of wallet #{0}".format(wallet.id), err); + hasLoadError = true; + }); + return loadPromise; + }); + }, $q.when()); + }) + .then(function() { + if (hasLoadError) { + return UIUtils.alert.error('ERROR.LOAD_WALLET_LIST_FAILED') + .then(function() { + $scope.resetData(); + $scope.cancel(); + }); + } + // Stop + if ($scope.formData.stopped) return; + if (loadCounter) { + console.debug("[wallets] Loaded data of {0} wallet(s) in {1}ms".format(loadCounter, (Date.now() - now))); + } + $scope.formData.balance = balance; + $scope.formData.updatingWalletId = undefined; + $scope.loading = false; + UIUtils.loading.hide(); + $scope.updateView(); + }) + .catch(function(err) { + $scope.resetData(); + if (err && err === 'CANCELLED') { + $scope.cancel(); + throw err; + } + return UIUtils.onError('ERROR.LOAD_WALLET_LIST_FAILED')(err); + }); + }; + + $scope.filterFn = function(parameters) { + return function(wallet) { + return !parameters || wallet.id !== parameters.excludedWalletId; + }; + }; + + + // Clean controller data + $scope.resetData = function() { + console.debug("[wallets] Cleaning wallet list"); + $scope.wallets = null; + $scope.loading = true; + $scope.entered = false; + $scope.formData.balance = undefined; + $scope.formData.updatingWalletId = undefined; + }; + + $scope.updateView = function(walletId) { + if (!$scope.wallets || !$scope.wallets.length) return; + + var selectorSuffix = walletId && (' #wallet-' + walletId) || ''; + + if ($scope.motion) { + $scope.motion.show({selector: '.list .item.item-wallet' + selectorSuffix, ink: true}); + } + else { + UIUtils.ink({selector: '.list .item.item-wallet' + selectorSuffix}); + } + }; + + $scope.updateWalletView = function(walletId) { + if ($scope.motion) { + $scope.motion.show({selector: '.list #wallet-' + walletId, ink: true}); + } + else { + UIUtils.ink({selector: '.list #wallet-' + walletId}); + } + }; + + $scope.doUpdate = function(silent) { + if ($scope.loading || !$scope.wallets || !$scope.wallets.length || $scope.formData.updatingWalletId) return $q.when(); + + $scope.selectPrevented = true; + $timeout(function() { + $scope.selectPrevented = false; + }, 1000); + + return $scope.load({silent: silent, refresh: true}) + .then(function() { + $scope.loading = false; + $scope.selectPrevented = false; + if (silent) { + $scope.$broadcast('$$rebind::rebind'); // force rebind + } + $scope.updateView(); + }); + }; + + $scope.addNewWallet = function(wallet) { + + if (!wallet) return $q.reject("Missing 'wallet' argument"); + + // Make sure auth on the main wallet + if (csSettings.data.useLocalStorageEncryption && !csWallet.isAuth()) { + return csWallet.auth({minData: true}) + .then(function() { + return $scope.addNewWallet(wallet); // loop + }) + .catch(function(err) { + if (err === 'CANCELLED') { + return UIUtils.loading.hide(); + } + UIUtils.onError('ERROR.ADD_SECONDARY_WALLET_FAILED')(err); + }); + } + + // Call API extension on child wallet + return csWallet.api.data.raisePromise.load(wallet.data) + // continue, when plugins extension failed (just log in console) + .catch(console.error) + .then(function() { + $scope.addListenersOnWallet(wallet); + csWallet.children.add(wallet); + }); + }; + + /* -- modals -- */ + + $scope.showNewWalletModal = function() { + + var wallet = csWallet.children.instance(); + return wallet.login({ + showNewAccountLink: false, + title: 'ACCOUNT.WALLET_LIST.BTN_NEW', + okText: 'COMMON.BTN_ADD', + // Load data options : + minData: true, + sources: true, + api: false, + success: UIUtils.loading.show, + method: 'PUBKEY' // Default method - fix #767 + }) + .then(function(walletData) { + if (!walletData) { // User cancelled + UIUtils.loading.hide(100); + return; + } + + // Avoid to add main wallet again + if (csWallet.isUserPubkey(walletData.pubkey)) { + UIUtils.loading.hide(); + UIUtils.alert.error('ERROR.COULD_NOT_ADD_MAIN_WALLET'); + return; + } + + // Avoid to add exists wallet again + if (csWallet.children.hasPubkey(walletData.pubkey)) { + UIUtils.loading.hide(); + UIUtils.alert.error('ERROR.COULD_NOT_ADD_EXISTING_WALLET'); + return; + } + + console.debug("[wallet] Adding secondary wallet {"+walletData.pubkey.substring(0,8)+"}"); + + // Add the child wallet + return $scope.addNewWallet(wallet) + .then(function() { + UIUtils.loading.hide(); + $scope.updateView(); + }); + }) + .catch(function(err) { + if (err === 'CANCELLED') { + // Silent + UIUtils.loading.hide(); + } + }); + }; + + /* -- Method to override by subclasses-- */ + + $scope.addListenersOnWallet = function(wallet) { + // Can be override by subclass + }; + + $scope.cancel = function() { + console.warn("cancel() must be implement by subclass"); + }; + + $scope.select = function(event, wallet) { + console.warn("select() must be implement by subclass"); + }; +} + +function WalletSelectModalController($scope, $controller, parameters) { + 'ngInject'; + + // Initialize the super class and extend it. + angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope})); + + $scope.$on('modal.shown', function() { + $scope.setParameters(parameters); + $scope.load(); + }); + + $scope.cancel = function() { + $scope.closeModal(); + }; + + $scope.select = function(event, wallet) { + if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; + $scope.closeModal(wallet); + }; + + // Default actions + if (parameters) { + $scope.setParameters(parameters); + } +} + +function WalletListViewController($scope, $controller, $state, $timeout, $q, $translate, $ionicPopover, $ionicPopup, + ModalUtils, UIUtils, Modals, csCurrency, csSettings, csWallet){ + 'ngInject'; + + $scope.settings = csSettings.data; + $scope.listeners = []; + + // Initialize the super class and extend it. + angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope, parameters: {}})); + + // Override defaults + $scope.formData.name = undefined; + $scope.motion = UIUtils.motion.default; + $scope.entered = false; + + $scope.enter = function(e, state) { + // First enter + if (!$scope.entered) { + $scope.entered = true; + $scope.setParameters({ + showDefault: true, + showBalance: true, + minData: false + }); + + return $scope.load() + .then(function() { + UIUtils.loading.hide(); + if (!$scope.wallets) return; // user cancel, or error + $scope.addListeners(); + $scope.showFab('fab-add-wallet'); + }); + } + // If already enter + else { + // Re-add listeners + $scope.addListeners(); + if ($scope.formData.stopped) { + $scope.loading = false; + $scope.formData.stopped = false; + $scope.formData.updatingWalletId = undefined; + $scope.updateView(); + } + } + }; + $scope.$on('$ionicView.enter', $scope.enter); + + $scope.leave = function() { + $scope.formData.stopped = true; + $scope.formData.updatingWalletId = undefined; + $scope.loading = false; + $scope.removeListeners(); + }; + $scope.$on('$ionicView.leave', $scope.leave); + + $scope.cancel = function() { + $scope.showHome(); + }; + + $scope.select = function(event, wallet) { + if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; + if (wallet.isDefault()) { + $state.go('app.view_wallet'); + } + else { + $state.go('app.view_wallet_by_id', {id: wallet.id}); + } + event.preventDefault(); + }; + + $scope.editWallet = function(event, wallet) { + + event.preventDefault(); + + return $scope.showEditPopup(wallet) + .then(function(newName) { + if (!newName) return; + + // Auth (if encryption is need) + return (csSettings.data.useLocalStorageEncryption ? csWallet.auth({minData: true}) : $q.when()) + + // Save changes + .then(function() { + wallet.data.localName = newName; + csWallet.storeData(); + UIUtils.loading.hide(); + $scope.updateView(); + }) + .catch(function(err) { + if (err === 'CANCELLED') { + return UIUtils.loading.hide(); + } + UIUtils.onError('ERROR.SAVE_WALLET_LIST_FAILED')(err); + }); + }); + }; + + $scope.downloadAsFile = function() { + if (!$scope.wallets) return; // user cancel + return csWallet.children.downloadFile(); + }; + + + + $scope.selectAndRemoveWallet = function() { + $scope.hideActionsPopover(); + return Modals.showSelectWallet({ + wallets: $scope.wallets, + showDefault: false + }) + .then(function(wallet) { + if (!wallet || !wallet.id) return; + + // Auth (if encryption is need)) + return (csSettings.data.useLocalStorageEncryption ? csWallet.auth({minData: true}) : $q.when()) + + // Remove the wallet + .then(function() { + csWallet.children.remove(wallet.id); + UIUtils.loading.hide(); + $scope.updateView(); + }) + .catch(function(err) { + if (err === 'CANCELLED') { + return UIUtils.loading.hide(); + } + UIUtils.onError('ERROR.ADD_SECONDARY_WALLET_FAILED')(err); + }); + }); + }; + + $scope.showImportFileModal = function() { + $scope.hideActionsPopover(); + + var loginAndAddWallet = function(authData) { + console.debug("[wallet] Adding secondary wallet {"+authData.pubkey.substring(0,8)+"}"); + var wallet = csWallet.children.instance(); + return wallet.login({ + authData: authData, + // Load data options : + minData: true, + sources: true, + api: false, + success: UIUtils.loading.show + }) + .then(function(walletData) { + walletData.localName = authData.localName; + return $scope.addNewWallet(wallet); + }); + }; + + return ModalUtils.show( + 'templates/wallet/list/modal_import_file.html', + 'WalletListImportModalCtrl' + ) + .then(function(items){ + if (!items || !items.length) return; // User cancel + + UIUtils.loading.show(); + + // Auth (if encryption is need) + return (csSettings.data.useLocalStorageEncryption ? csWallet.auth({minData: true}) : $q.when()) + .then(function() { + // Add wallet one after one + return items.reduce(function(promise, authData){ + return promise.then(function() { + return loginAndAddWallet(authData); + }); + }, $q.when()); + }) + .then(function() { + UIUtils.loading.hide(); + $scope.updateView(); + }) + .catch(function(err) { + if (err === 'CANCELLED') { + return UIUtils.loading.hide(); + } + UIUtils.onError('ERROR.ADD_SECONDARY_WALLET_FAILED')(err); + }); + }); + }; + + /* -- popups -- */ + + $scope.setEditForm = function(editForm) { + $scope.editForm = editForm; + }; + + $scope.showEditPopup = function(wallet) { + return $q(function(resolve, reject) { + $translate(['ACCOUNT.WALLET_LIST.EDIT_POPOVER.TITLE', 'ACCOUNT.WALLET_LIST.EDIT_POPOVER.HELP', 'COMMON.BTN_OK', 'COMMON.BTN_CANCEL']) + .then(function (translations) { + $scope.formData.name = wallet.data.localName || wallet.data.name || wallet.data.uid || wallet.data.pubkey.substring(0, 8); + + // Choose UID popup + $ionicPopup.show({ + templateUrl: 'templates/wallet/list/popup_edit_name.html', + title: translations['ACCOUNT.WALLET_LIST.EDIT_POPOVER.TITLE'], + subTitle: translations['ACCOUNT.WALLET_LIST.EDIT_POPOVER.HELP'], + scope: $scope, + buttons: [ + { text: translations['COMMON.BTN_CANCEL'] }, + { + text: translations['COMMON.BTN_OK'], + type: 'button-positive', + onTap: function(e) { + $scope.editForm.$submitted=true; + if(!$scope.editForm.$valid || !$scope.formData.name) { + //don't allow the user to close unless he enters a name + e.preventDefault(); + } else { + return $scope.formData.name; + } + } + } + ] + }) + .then(function(name) { + if (!name) { // user cancel + delete $scope.formData.name; + UIUtils.loading.hide(); + return; + } + resolve(name); + }); + }); + }); + }; + + /* -- popovers -- */ + + $scope.showActionsPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'templates/wallet/list/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } + }); + }; + + $scope.hideActionsPopover = function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + $scope.actionsPopover = null; + } + }; + + /* -- listeners -- */ + + // Clean controller data when logout + $scope.onWalletLogout = function() { + $scope.resetData(); + $scope.removeListeners(); + }; + + $scope.addListeners = function() { + + // First remove lod listeners, if any + $scope.removeListeners(); + + $scope.listeners = [ + csWallet.api.data.on.logout($scope, $scope.onWalletLogout) + ]; + + // Auto-update on new block + if (csSettings.data.walletHistoryAutoRefresh) { + $scope.listeners.push( + csCurrency.api.data.on.newBlock($scope, function (block) { + if ($scope.loading) return; + console.debug("[wallet-list] Received new block. Will reload list."); + $timeout(function () { + $scope.doUpdate(true); + }, 300/*waiting for node cache propagation*/); + })); + } + + // Listen auth events on each wallet + _.forEach($scope.wallets||[], $scope.addListenersOnWallet); + }; + + $scope.addListenersOnWallet = function(wallet) { + if (!wallet) return; + $scope.listeners.push(wallet.api.data.on.unauth($scope, $scope.updateView)); + $scope.listeners.push(wallet.api.data.on.auth($scope, function (data, deferred) { + $timeout($scope.updateView); + return deferred ? deferred.resolve() : $q.when(); + })); + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; + + var inheritedUpdateView = $scope.updateView; + $scope.updateView = function() { + inheritedUpdateView(); + $scope.$broadcast('$$rebind::rebind'); // force rebind + }; + + var inheritedUpdateWalletView = $scope.updateWalletView; + $scope.updateWalletView = function(walletId) { + inheritedUpdateWalletView(walletId); + $scope.$broadcast('$$rebind::rebind'); // force rebind + }; + + // Detect changes in settings useRelative + $scope.$watch('settings.useRelative', function(newVal, oldVal) { + if (!$scope.formData || $scope.loading || (newVal === oldVal)) return; + $scope.formData.useRelative = csSettings.data.useRelative; + $scope.updateView(); + }, true); +} + + +function WalletSelectPopoverController($scope, $controller, UIUtils, parameters) { + 'ngInject'; + + // Initialize the super class and extend it. + angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope})); + + // Disable list motion + $scope.motion = null; + + $scope.$on('popover.shown', function() { + if ($scope.loading) { + $scope.setParameters(parameters); + $scope.load(); + } + }); + + $scope.updateView = function() { + if (!$scope.wallets || !$scope.wallets.length) return; + + UIUtils.ink({selector: '.popover-wallets .list .item'}); + $scope.$broadcast('$$rebind::rebind'); // force rebind + }; + + $scope.select = function(event, wallet) { + if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; // no selection + $scope.closePopover(wallet); + }; + +} + +function WalletListImportModalController($scope, $timeout, BMA, csWallet) { + 'ngInject'; + + $scope.hasContent = false; + $scope.content = null; + $scope.fileData = ''; + $scope.isValidFile = false; + $scope.validatingFile = false; + + $scope.importFromFile = function(file) { + $scope.validatingFile = true; + + $scope.hasContent = angular.isDefined(file) && file !== ''; + $scope.fileData = file.fileData ? file.fileData : ''; + var isValidFile = $scope.fileData !== '' && + ($scope.fileData.type == 'text/csv' || $scope.fileData.type == 'text/plain' || 'application/vnd.ms-excel' /*fix issue #810*/); + + // Bad file type: invalid file + if (!isValidFile) { + console.error("[wallet] Import failed. Invalid file type: " + $scope.fileData.type); + $scope.isValidFile = false; + $scope.validatingFile = false; + return; + } + + // Parse file + console.debug("[wallet] Parsing file to import..."); + var rows = file.fileContent.split('\n'); + $scope.content = rows.reduce(function(res, row) { + // Skip empty row + if (!row || !row.trim().length) return res; + + // Split + var cols = row.split('\t', 3) || undefined; + + // Invalid column count: mark file as invalid + if (cols && cols.length != 3) { + console.debug("[wallet] Import: skip invalid row: " + row); + isValidFile = false; + return res; + } + + var item = { + pubkey: cols[0], + uid: cols[1], + localName: cols[2] + }; + + // Check pubkey validity + if (!BMA.regexp.PUBKEY.test(item.pubkey)) { + console.debug("[wallet] Invalid pubkey, found in this row: ", row); + isValidFile = false; + return res; + } + + // Ignore if same as current wallet + if (csWallet.isUserPubkey(item.pubkey)) { + console.debug("[wallet] Pubkey equals to main wallet. Skip this row: ", row); + return res; + } + + // Ignore if already in children wallet + if (csWallet.children.hasPubkey(item.pubkey)) { + console.debug("[wallet] Pubkey already in wallet list. Skip this row", row); + return res; + } + + // OK: add it to result + return res.concat(item); + }, []); + + $scope.isValidFile = isValidFile; + + $timeout(function() { + $scope.validatingFile = false; + }, 250); // need to have a loading effect + }; + + $scope.removeFile = function() { + $scope.hasContent = false; + $scope.content = null; + $scope.fileData = ''; + $scope.isValidFile = false; + $scope.validatingFile = false; + }; +} diff --git a/assets/www/js/controllers/wot-controllers.js b/assets/www/js/controllers/wot-controllers.js index 51de6d7650232fccd515c1b1b150885ad651ce9f..2e95963f74a1644840268045ae74858a5d77a452 100644 --- a/assets/www/js/controllers/wot-controllers.js +++ b/assets/www/js/controllers/wot-controllers.js @@ -43,7 +43,7 @@ angular.module('cesium.wot.controllers', ['cesium.services']) }) .state('app.wot_identity', { - url: "/wot/:pubkey/:uid?action", + url: "/wot/:pubkey/:uid?action&block", views: { 'menuContent': { templateUrl: "templates/wot/view_identity.html", @@ -64,19 +64,6 @@ angular.module('cesium.wot.controllers', ['cesium.services']) .state('app.wot_identity_tx_uid', { url: "/wot/tx/:pubkey/:uid?action", - views: { - 'menuContent': { - templateUrl: "templates/wot/view_identity_tx.html", - controller: 'WotIdentityTxViewCtrl' - }, - data: { - large: 'app.wot_identity_tx_uid_lg' - } - } - }) - - .state('app.wot_identity_tx_uid_lg', { - url: "/wot/tx/lg/:pubkey/:uid?action", views: { 'menuContent': { templateUrl: "templates/wot/view_identity_tx.html", @@ -86,7 +73,7 @@ angular.module('cesium.wot.controllers', ['cesium.services']) }) .state('app.wot_cert', { - url: "/wot/:pubkey/:uid/:type", + url: "/wot/:pubkey/:uid/:type?block", views: { 'menuContent': { templateUrl: "templates/wot/view_certifications.html", @@ -99,7 +86,7 @@ angular.module('cesium.wot.controllers', ['cesium.services']) }) .state('app.wot_cert_lg', { - url: "/wot/cert/lg/:pubkey/:uid", + url: "/wot/cert/lg/:pubkey/:uid?block", views: { 'menuContent': { templateUrl: "templates/wot/view_certifications.html", @@ -110,7 +97,7 @@ angular.module('cesium.wot.controllers', ['cesium.services']) // wallet cert .state('app.wallet_cert', { - url: "/wallet/cert/:type", + url: "/account/cert/:type", views: { 'menuContent': { templateUrl: "templates/wot/view_certifications.html", @@ -123,7 +110,31 @@ angular.module('cesium.wot.controllers', ['cesium.services']) }) .state('app.wallet_cert_lg', { - url: "/wallet/cert/lg", + url: "/account/cert/lg", + views: { + 'menuContent': { + templateUrl: "templates/wot/view_certifications.html", + controller: 'WotCertificationsViewCtrl' + } + } + }) + + // wallet cert + .state('app.wallet_cert_by_id', { + url: "/wallets/:id/cert/:type", + views: { + 'menuContent': { + templateUrl: "templates/wot/view_certifications.html", + controller: 'WotCertificationsViewCtrl' + } + }, + data: { + large: 'app.wallet_cert_lg_by_id' + } + }) + + .state('app.wallet_cert_lg_by_id', { + url: "/wallets/:id/cert/lg", views: { 'menuContent': { templateUrl: "templates/wot/view_certifications.html", @@ -165,21 +176,23 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i $scope.entered = false; $scope.wotSearchTextId = 'wotSearchText'; $scope.enableFilter = true; + $scope.enableWallets = false; $scope.allowMultiple = false; $scope.selection = []; $scope.showResultLabel = true; $scope.parameters = {}; // override in the modal controller - $scope.$on('$ionicView.enter', function(e, state) { + $scope.enter = function(e, state) { if (!$scope.entered) { - if (state.stateParams && state.stateParams.q) { // Query parameter - $scope.search.text = state.stateParams.q; + var params = angular.merge({}, $scope.parameters, state && state.stateParams); + if (params && params.q) { // Query parameter + $scope.search.text = params.q; $timeout(function() { $scope.doSearch(); }, 100); } - else if (state.stateParams && state.stateParams.hash) { // hash tag parameter - $scope.search.text = '#' + state.stateParams.hash; + else if (params && params.hash) { // hash tag parameter + $scope.search.text = '#' + params.hash; $timeout(function() { $scope.doSearch(); }, 100); @@ -187,16 +200,19 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i else { $timeout(function() { // Init phase - if (csCurrency.data.initPhase && !state.stateParams.type) { + if (csCurrency.data.initPhase && !params.type) { $scope.doGetPending(0, undefined, true/*skipLocationUpdate*/); } // get new comers - else if (state.stateParams.type == 'newcomers' || (!csConfig.initPhase && !state.stateParams.type)) { + else if (params.type == 'newcomers' || (!csConfig.initPhase && !params.type)) { $scope.doGetNewcomers(0, undefined, true/*skipLocationUpdate*/); } - else if (state.stateParams.type == 'pending') { + else if (params.type == 'pending') { $scope.doGetPending(0, undefined, true/*skipLocationUpdate*/); } + else if (params.type == 'wallets') { + $scope.doGetWallets(0, undefined, true/*skipLocationUpdate*/); + } }, 100); } @@ -218,7 +234,8 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i $scope.motion.show({selector: '.lookupForm .list .item', ink: true}); } } - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.resetWotSearch = function() { $scope.search = { @@ -317,7 +334,7 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i return csWot.newcomers(offset, size) .then(function(res){ - if ($scope.search.type != 'newcomers') return false; // could have change + if ($scope.search.type !== 'newcomers') return false; // could have change $scope.doDisplayResult(res && res.hits, offset, size, res && res.total); return true; }) @@ -365,6 +382,42 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i }); }; + $scope.doGetWallets = function(offset, size, skipLocationUpdate) { + offset = offset || 0; + size = size || defaultSearchLimit; + if (size < defaultSearchLimit) size = defaultSearchLimit; + + $scope.hideActionsPopover(); + $scope.search.loading = (offset === 0); + $scope.search.type = 'wallets'; + + // Update location href + if (!offset && !skipLocationUpdate) { + $scope.updateLocationHref(); + } + + return csWallet.children.all() + .then(function(children) { + if (!children || $scope.search.type != 'wallets') return false; // could have change + var res = [csWallet].concat(children).reduce(function(res, wallet, index) { + var item = { + id: index, + pubkey: wallet.data.pubkey, + uid: wallet.data.uid, + name: wallet.data.localName || wallet.data.name, + avatar: wallet.data.avatar + }; + return res.concat(item); + }, []); + + $scope.doDisplayResult(res, offset, size, res.length); + $scope.search.hasMore = false; + return true; + }); + + + }; + $scope.showMore = function() { var offset = $scope.search.results ? $scope.search.results.length : 0; @@ -537,32 +590,25 @@ function WotLookupController($scope, $state, $q, $timeout, $focus, $location, $i /* -- show/hide popup -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('templates/wot/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'templates/wot/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; - } -function WotLookupModalController($scope, $controller, $focus, parameters){ +function WotLookupModalController($scope, $controller, $focus, csWallet, parameters){ 'ngInject'; // Initialize the super class and extend it. @@ -571,6 +617,7 @@ function WotLookupModalController($scope, $controller, $focus, parameters){ parameters = parameters || {}; $scope.search.loading = false; $scope.enableFilter = angular.isDefined(parameters.enableFilter) ? parameters.enableFilter : false; + $scope.enableWallets = angular.isDefined(parameters.enableWallets) ? (csWallet.isLogin() && csWallet.children.count() && parameters.enableWallets) : false; $scope.allowMultiple = angular.isDefined(parameters.allowMultiple) ? parameters.allowMultiple : false; $scope.parameters = parameters; $scope.showResultLabel = false; @@ -581,6 +628,17 @@ function WotLookupModalController($scope, $controller, $focus, parameters){ $scope.selection = parameters.selection; } + var superEnter = $scope.enter; + $scope.enter = function(e) { + if ($scope.parameters && $scope.parameters.q) { + $scope.search.text=$scope.parameters.q; + if ($scope.parameters.q.trim().length > 2) { + superEnter(e); // call enter, that launch the search + } + } + }; + $scope.$on('modal.shown', $scope.enter); + $scope.cancel = function(){ $scope.closeModal(); }; @@ -588,7 +646,8 @@ function WotLookupModalController($scope, $controller, $focus, parameters){ $scope.select = function(identity){ $scope.closeModal({ pubkey: identity.pubkey, - uid: identity.uid + uid: identity.uid, + name: identity.name && identity.name.replace(/<\/?em>/ig, '') }); }; @@ -622,8 +681,8 @@ function WotLookupModalController($scope, $controller, $focus, parameters){ * @param csWallet * @constructor */ -function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ionicHistory, - UIUtils, Modals, csConfig, csCurrency, csWot, csWallet) { +function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ionicHistory, $q, + UIUtils, Modals, csConfig, csSettings, csCurrency, csWot, csWallet) { 'ngInject'; $scope.formData = { @@ -637,17 +696,19 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ viewData.enableBack = UIUtils.screen.isSmall() ? true : viewData.enableBack; }); - $scope.load = function(pubkey, withCache, uid) { - return csWot.load(pubkey, withCache, uid) + $scope.load = function(pubkey, uid, options) { + return csWot.load(pubkey, uid, options) .then(function(identity){ if (!identity) return UIUtils.onError('ERROR.IDENTITY_NOT_FOUND')().then($scope.showHome); $scope.formData = identity; + var isLogin = csWallet.isLogin(); $scope.revoked = identity.requirements && (identity.requirements.revoked || identity.requirements.pendingRevocation); - $scope.canCertify = identity.hasSelf && (!csWallet.isLogin() || (!csWallet.isUserPubkey(pubkey))) && !$scope.revoked; - $scope.canSelectAndCertify = identity.hasSelf && csWallet.isUserPubkey(pubkey); - $scope.alreadyCertified = !$scope.canCertify || !csWallet.isLogin() ? false : - (!!_.findWhere(identity.received_cert, { pubkey: csWallet.data.pubkey, valid: true }) || - !!_.findWhere(identity.received_cert_pending, { pubkey: csWallet.data.pubkey, valid: true })); + $scope.canCertify = identity.hasSelf && !$scope.revoked && (!isLogin || !csWallet.isUserPubkey(pubkey) || csWallet.children.count() > 0); + $scope.canSelectAndCertify = identity.hasSelf && (csWallet.isUserPubkey(pubkey) || csWallet.children.hasPubkey(pubkey)); + var cert = isLogin && _.find((identity.received_cert||[]).concat(identity.received_cert_pending||[]), function (cert) { + return cert.pubkey === csWallet.data.pubkey && cert.valid && cert.expiresIn > csSettings.data.timeWarningExpire; + }); + $scope.alreadyCertified = (!$scope.canCertify || !isLogin || csWallet.children.count() > 0) ? false : !!cert; $scope.disableCertifyButton = $scope.alreadyCertified || $scope.revoked; $scope.loading = false; }) @@ -663,201 +724,217 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ $scope.loading = true; UIUtils.loading.show(); } - return $scope.load($scope.formData.pubkey, false/*no cache*/, $scope.formData.uid) + var options = { + cache: false, // No cache + blockUid: $scope.formData.blockUid || undefined + }; + return $scope.load($scope.formData.pubkey, $scope.formData.uid, options) .then(UIUtils.loading.hide); }; // Certify the current identity $scope.certify = function() { - // Need user auth - fix #513 - return csWallet.auth({minData: true}) - .then(function(walletData) { - UIUtils.loading.hide(); + // Select wallet, if many + return (csWallet.children.count() ? Modals.showSelectWallet({displayBalance: false}) : $q.when(csWallet)) + .then(function(wallet) { + if (!wallet) return; // user cancelled - if (!csCurrency.data.initPhase && !walletData.isMember) { - UIUtils.alert.error(walletData.requirements.needSelf ? - 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY' : 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF'); - return; - } + // Need user auth - fix #513 + return wallet.auth({minData: true}) + .then(function(walletData) { + UIUtils.loading.hide(); - if (!csCurrency.data.initPhase && !$scope.formData.hasSelf) { - UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); - return; - } + if (!csCurrency.data.initPhase && !walletData.isMember) { + UIUtils.alert.error(walletData.requirements.needSelf ? + 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY' : 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF'); + return; + } - // Check identity not expired - if ($scope.formData.requirements.expired) { - UIUtils.alert.error('ERROR.IDENTITY_EXPIRED'); - return; - } + if (!csCurrency.data.initPhase && !$scope.formData.hasSelf) { + UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); + return; + } - // Check not already certified - var previousCert = _.findWhere($scope.formData.received_cert, { pubkey: walletData.pubkey, valid: true}); - if (previousCert) { - $translate('ERROR.IDENTITY_ALREADY_CERTIFY', previousCert) - .then(function(message) { - UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); - }); - return; - } + // Check identity not expired + if ($scope.formData.requirements.expired) { + UIUtils.alert.error('ERROR.IDENTITY_EXPIRED'); + return; + } - // Check not pending certification - previousCert = _.findWhere($scope.formData.received_cert_pending, { pubkey: walletData.pubkey, valid: true}); - if (previousCert) { - $translate('ERROR.IDENTITY_ALREADY_CERTIFY_PENDING', previousCert) - .then(function(message) { - UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + // Check not already certified + var previousCert = _.find($scope.formData.received_cert, function(cert) { + return cert.pubkey === wallet.data.pubkey && cert.valid && cert.expiresIn > csSettings.data.timeWarningExpire; }); - return; - } + if (previousCert) { + $translate('ERROR.IDENTITY_ALREADY_CERTIFY', previousCert) + .then(function(message) { + UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + }); + return; + } - UIUtils.alert.confirm('CONFIRM.CERTIFY_RULES', 'CONFIRM.POPUP_SECURITY_WARNING_TITLE', { - cssClass: 'warning', - okText: 'WOT.BTN_YES_CERTIFY', - okType: 'button-assertive' - }) - .then(function(confirm){ - if (!confirm) { + // Check no pending certification + previousCert = _.findWhere($scope.formData.received_cert_pending, { pubkey: wallet.data.pubkey, valid: true}); + if (previousCert) { + $translate('ERROR.IDENTITY_ALREADY_CERTIFY_PENDING', previousCert) + .then(function(message) { + UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + }); return; } - UIUtils.loading.show(); - csWallet.certify($scope.formData.uid, - $scope.formData.pubkey, - $scope.formData.timestamp, - $scope.formData.sig, - $scope.formData.isMember, - $scope.formData.wasMember) - .then(function(cert) { - UIUtils.loading.hide(); - if (cert) { - $scope.prepareNewCert(cert); - $scope.alreadyCertified = true; - UIUtils.alert.info('INFO.CERTIFICATION_DONE'); - $scope.formData.received_cert_pending.unshift(cert); - $scope.formData.requirements.pendingCertificationCount++; - $scope.doMotion(); + + UIUtils.alert.confirm('CONFIRM.CERTIFY_RULES', 'CONFIRM.POPUP_SECURITY_WARNING_TITLE', { + cssClass: 'warning', + okText: 'WOT.BTN_YES_CERTIFY', + okType: 'button-assertive' + }) + .then(function(confirm){ + if (!confirm) { + return; } - }) - .catch(UIUtils.onError('ERROR.SEND_CERTIFICATION_FAILED')); + UIUtils.loading.show(); + wallet.certify($scope.formData.uid, + $scope.formData.pubkey, + $scope.formData.blockUid || ($scope.formData.requirements && $scope.formData.requirements.meta && $scope.formData.requirements.meta.timestamp), + $scope.formData.requirements && $scope.formData.requirements.meta && $scope.formData.requirements.meta.sig, + $scope.formData.isMember, + $scope.formData.wasMember) + .then(function(cert) { + UIUtils.loading.hide(); + if (cert) { + $scope.prepareNewCert(wallet, cert); + $scope.alreadyCertified = true; + UIUtils.toast.show('INFO.CERTIFICATION_DONE'); + $scope.formData.received_cert_pending.unshift(cert); + $scope.formData.requirements.pendingCertificationCount++; + $scope.doMotion(); + } + }) + .catch(UIUtils.onError('ERROR.SEND_CERTIFICATION_FAILED')); + }); + }) + .catch(function(err) { + if (err === 'CANCELLED') return; + UIUtils.onError('ERROR.LOGIN_FAILED')(err); }); - }) - .catch(function(err) { - if (err == 'CANCELLED') return; - UIUtils.onError('ERROR.LOGIN_FAILED')(err); }); }; // Select an identity and certify $scope.selectAndCertify = function() { - // Need user auth - fix #513 - return csWallet.auth({minData: true}) - - .then(function(walletData) { - if (!csCurrency.data.initPhase && !walletData.isMember) { - UIUtils.alert.error(walletData.requirements.needSelf || walletData.requirements.needMembership ? - 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY' : 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF'); - return; - } - UIUtils.loading.hide(); - // Open Wot lookup modal - return Modals.showWotLookup(); - }) - .then(function(idty) { - if (!idty || !idty.pubkey) { - return; // cancelled - } - if (!idty.uid) { // not a member - UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); - return; - } + // Select wallet, if many + return (csWallet.children.count() ? Modals.showSelectWallet({displayBalance: false}) : $q.when(csWallet)) + .then(function(wallet) { + // Need user auth - fix #513 + return wallet.auth({minData: true}) + .then(function (walletData) { + if (!csCurrency.data.initPhase && !walletData.isMember) { + UIUtils.alert.error(walletData.requirements.needSelf || walletData.requirements.needMembership ? + 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY' : 'ERROR.NEED_MEMBER_ACCOUNT_TO_CERTIFY_HAS_SELF'); + return; + } + UIUtils.loading.hide(); + // Open Wot lookup modal + return Modals.showWotLookup(); + }) + .then(function (idty) { + if (!idty || !idty.pubkey) { + return; // cancelled + } + if (!idty.uid) { // not a member + UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); + return; + } - UIUtils.loading.show(); + UIUtils.loading.show(); - // load selected identity - return csWot.load(idty.pubkey, false /*no cache*/); - }) + var options = {cache: false, blockUid: idty.blockUid}; - .then(function(identity) { - if (!identity) return; // cancelled - UIUtils.loading.hide(); - if (!identity || !identity.hasSelf) { - UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); - return; - } + // load selected identity + return csWot.load(idty.pubkey, idty.uid, options); + }) - // Check identity not expired - if (identity.requirements.expired) { - UIUtils.alert.error('ERROR.IDENTITY_EXPIRED'); - return; - } + .then(function (identity) { + if (!identity) return; // cancelled + UIUtils.loading.hide(); + if (!identity || !identity.hasSelf) { + UIUtils.alert.error('ERROR.IDENTITY_TO_CERTIFY_HAS_NO_SELF'); + return; + } - // Check not already certified - var previousCert = _.findWhere(identity.received_cert, { pubkey: csWallet.data.pubkey, valid: true}); - if (previousCert) { - $translate('ERROR.IDENTITY_ALREADY_CERTIFY', previousCert) - .then(function(message) { - UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); - }); - return; - } + // Check identity not expired + if (identity.requirements.expired) { + UIUtils.alert.error('ERROR.IDENTITY_EXPIRED'); + return; + } - // Check not pending certification - previousCert = _.findWhere(identity.received_cert_pending, { pubkey: csWallet.data.pubkey, valid: true}); - if (previousCert) { - $translate('ERROR.IDENTITY_ALREADY_CERTIFY_PENDING', previousCert) - .then(function(message) { - UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); - }); - return; - } + // Check not already certified + var previousCert = _.findWhere(identity.received_cert, {pubkey: wallet.data.pubkey, valid: true}); + if (previousCert) { + $translate('ERROR.IDENTITY_ALREADY_CERTIFY', previousCert) + .then(function (message) { + UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + }); + return; + } - // Ask confirmation - $translate('CONFIRM.CERTIFY_RULES_TITLE_UID', {uid: identity.uid}) - .then(function(confirmTitle) { - return UIUtils.alert.confirm('CONFIRM.CERTIFY_RULES', confirmTitle); - }) - .then(function(confirm){ - if (!confirm) { + // Check not pending certification + previousCert = _.findWhere(identity.received_cert_pending, {pubkey: wallet.data.pubkey, valid: true}); + if (previousCert) { + $translate('ERROR.IDENTITY_ALREADY_CERTIFY_PENDING', previousCert) + .then(function (message) { + UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + }); return; } - UIUtils.loading.show(); - // Send certification - csWallet.certify(identity.uid, - identity.pubkey, - identity.timestamp, - identity.sig, - identity.isMember, - identity.wasMember) - .then(function(cert) { - UIUtils.loading.hide(); - if (!cert) return; - return csWot.extendAll([cert], 'pubkey') - .then(function(){ - UIUtils.toast.show('INFO.CERTIFICATION_DONE'); - $scope.formData.given_cert_pending.unshift(cert); - $scope.doMotion(); - }); + // Ask confirmation + $translate('CONFIRM.CERTIFY_RULES_TITLE_UID', {uid: identity.uid}) + .then(function (confirmTitle) { + return UIUtils.alert.confirm('CONFIRM.CERTIFY_RULES', confirmTitle); }) - .catch(UIUtils.onError('ERROR.SEND_CERTIFICATION_FAILED')); + .then(function (confirm) { + if (!confirm) { + return; + } + UIUtils.loading.show(); + + // Send certification + wallet.certify(identity.uid, + identity.pubkey, + identity.blockUid || (identity.requirements && identity.requirements.meta && identity.requirements.meta.timestamp), + identity.requirements && identity.requirements.meta && identity.requirements.meta.sig, + identity.isMember, + identity.wasMember) + .then(function (cert) { + UIUtils.loading.hide(); + if (!cert) return; + return csWot.extendAll([cert], 'pubkey') + .then(function () { + UIUtils.toast.show('INFO.CERTIFICATION_DONE'); + $scope.formData.given_cert_pending.unshift(cert); + $scope.doMotion(); + }); + }) + .catch(UIUtils.onError('ERROR.SEND_CERTIFICATION_FAILED')); + }); + }) + .catch(function (err) { + if (err === 'CANCELLED') return; + UIUtils.onError('ERROR.LOAD_IDENTITY_FAILED')(err); }); - }) - .catch(function(err) { - if (err == 'CANCELLED') return; - UIUtils.onError('ERROR.LOAD_IDENTITY_FAILED')(err); }); - }; // Add wallet's data to a new cert - $scope.prepareNewCert = function(cert) { - cert.uid = csWallet.data.uid; - cert.pubkey = csWallet.data.pubkey; - cert.isMember = csWallet.data.isMember; - cert.avatar = csWallet.data.avatar; - cert.name = csWallet.data.name; + $scope.prepareNewCert = function(wallet, cert) { + cert.uid = wallet.data.uid; + cert.pubkey = wallet.data.pubkey; + cert.isMember = wallet.data.isMember; + cert.avatar = wallet.data.avatar; + cert.name = wallet.data.name; }; $scope.removeActionParamInLocationHref = function(state) { @@ -894,35 +971,41 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ /* -- open screens -- */ $scope.showCertifications = function() { + var block = $scope.formData.requirements && $scope.formData.requirements.alternatives && $scope.formData.blockUid || undefined; // Warn: do not use a simple link here (a ng-click is mandatory for help tour) if (UIUtils.screen.isSmall() ) { $state.go('app.wot_cert', { pubkey: $scope.formData.pubkey, uid: $scope.formData.uid, - type: 'received' + type: 'received', + block: block }); } else { $state.go('app.wot_cert_lg', { pubkey: $scope.formData.pubkey, - uid: $scope.formData.uid + uid: $scope.formData.uid, + block: block }); } }; $scope.showGivenCertifications = function() { + var block = $scope.formData.requirements && $scope.formData.requirements.alternatives && $scope.formData.blockUid || undefined; // Warn: do not use a simple link here (a ng-click is mandatory for help tour) if (UIUtils.screen.isSmall() ) { $state.go('app.wot_cert', { pubkey: $scope.formData.pubkey, uid: $scope.formData.uid, - type: 'given' + type: 'given', + block: block }); } else { $state.go('app.wot_cert_lg', { pubkey: $scope.formData.pubkey, - uid: $scope.formData.uid + uid: $scope.formData.uid, + block: block }); } }; @@ -949,15 +1032,15 @@ function WotIdentityAbstractController($scope, $rootScope, $state, $translate, $ /** * Identity view controller - should extend WotIdentityAbstractCtrl */ -function WotIdentityViewController($scope, $rootScope, $controller, $timeout, UIUtils, csWallet) { +function WotIdentityViewController($scope, $rootScope, $controller, $timeout, $state, UIUtils, Modals, csWallet) { 'ngInject'; // Initialize the super class and extend it. angular.extend(this, $controller('WotIdentityAbstractCtrl', {$scope: $scope})); $scope.motion = UIUtils.motion.fadeSlideInRight; + $scope.qrcodeId = 'qrcode-wot-' + $scope.$id; $scope.$on('$ionicView.enter', function(e, state) { - var onLoadSuccess = function() { $scope.doMotion(); if (state.stateParams && state.stateParams.action) { @@ -967,13 +1050,20 @@ function WotIdentityViewController($scope, $rootScope, $controller, $timeout, UI $scope.removeActionParamInLocationHref(state); } + + $scope.showQRCode(); + }; + var options = { + cache: true, + blockUid: state.stateParams && state.stateParams.block || undefined }; if (state.stateParams && state.stateParams.pubkey && state.stateParams.pubkey.trim().length > 0) { if ($scope.loading) { // load once - return $scope.load(state.stateParams.pubkey.trim(), true /*withCache*/, state.stateParams.uid) + + return $scope.load(state.stateParams.pubkey.trim(), state.stateParams.uid, options) .then(onLoadSuccess); } } @@ -982,16 +1072,7 @@ function WotIdentityViewController($scope, $rootScope, $controller, $timeout, UI state.stateParams.uid && state.stateParams.uid.trim().length > 0) { if ($scope.loading) { // load once - return $scope.load(null, true /*withCache*/, state.stateParams.uid) - .then(onLoadSuccess); - } - } - - // Load from wallet pubkey - else if (csWallet.isLogin()){ - - if ($scope.loading) { - return $scope.load(csWallet.data.pubkey, true /*withCache*/, csWallet.data.uid) + return $scope.load(null, state.stateParams.uid, options) .then(onLoadSuccess); } } @@ -1013,6 +1094,57 @@ function WotIdentityViewController($scope, $rootScope, $controller, $timeout, UI if (($scope.canCertify && !$scope.alreadyCertified) || $rootScope.tour) { $scope.showFab('fab-certify-' + $scope.formData.uid); } + + $scope.$broadcast('$csExtension.motion'); + }; + + $scope.doQuickFix = function(event) { + if (event === 'showSelectIdentities') { + return $scope.showSelectIdentities(); + } + }; + + $scope.showSelectIdentities = function() { + if (!$scope.formData.requirements || !$scope.formData.requirements.alternatives) return; + + return Modals.showSelectPubkeyIdentity({ + identities: [$scope.formData.requirements].concat($scope.formData.requirements.alternatives) + }) + .then(function(res) { + if (!res || !res.pubkey) return; // Skip if cancelled + // open the identity + return $state.go('app.wot_identity', { + pubkey: res.pubkey, + uid: res.uid, + block: res.meta && res.meta.timestamp || res.blockUid + }); + }); + }; + + $scope.showQRCode = function(timeout) { + if (!$scope.qrcode) { + $scope.qrcode = new QRCode( + $scope.qrcodeId, + { + text: $scope.formData.pubkey, + width: 180, + height: 180, + correctLevel: QRCode.CorrectLevel.L + }); + UIUtils.motion.toggleOn({selector: '#'+$scope.qrcodeId}, timeout || 1100); + } + else { + $scope.qrcode.clear(); + $scope.qrcode.makeCode($scope.formData.pubkey); + UIUtils.motion.toggleOn({selector: '#'+$scope.qrcodeId}, timeout || 1100); + } + }; + + $scope.hideQRCode = function() { + if ($scope.qrcode) { + $scope.qrcode.clear(); + UIUtils.motion.toggleOff({selector: '#'+$scope.qrcodeId}); + } }; } @@ -1067,8 +1199,8 @@ function WotIdentityTxViewController($scope, $timeout, $q, BMA, csSettings, csWo // Update view $scope.updateView = function() { - $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind + $scope.$broadcast('$$rebind::balance'); // force rebind balance + $scope.$broadcast('$$rebind::rebind'); // force rebind $scope.motion.show(); }; @@ -1082,7 +1214,7 @@ function WotIdentityTxViewController($scope, $timeout, $q, BMA, csSettings, csWo fromTime = fromTime || ($scope.formData.tx.fromTime - csSettings.data.walletHistoryTimeSecond) || - (Math.trunc(new Date().getTime() / 1000) - 2 * csSettings.data.walletHistoryTimeSecond); + (moment().utc().unix() - 2 * csSettings.data.walletHistoryTimeSecond); UIUtils.loading.show(); return csTx.load($scope.pubkey, fromTime) @@ -1112,6 +1244,9 @@ function WotIdentityTxViewController($scope, $timeout, $q, BMA, csSettings, csWo */ function WotCertificationsViewController($scope, $rootScope, $controller, csSettings, csWallet, UIUtils) { 'ngInject'; + + var wallet; + // Initialize the super class and extend it. angular.extend(this, $controller('WotIdentityAbstractCtrl', {$scope: $scope})); @@ -1132,39 +1267,43 @@ function WotCertificationsViewController($scope, $rootScope, $controller, csSett $scope.motions.avatar.enable = false; } - if (state.stateParams && - state.stateParams.pubkey && - state.stateParams.pubkey.trim().length > 0) { + // First load + if ($scope.loading) { + var options = { + cache: true, + blockUid: state.stateParams && state.stateParams.block || undefined + }; - if ($scope.loading) { // load once - return $scope.load(state.stateParams.pubkey.trim(), true /*withCache*/, state.stateParams.uid) - .then(function() { + if (state.stateParams && + state.stateParams.pubkey && + state.stateParams.pubkey.trim().length > 0) { + + return $scope.load(state.stateParams.pubkey.trim(), state.stateParams.uid, options) + .then(function () { $scope.doMotion(); $scope.showHelpTip(); }); } - else { - $scope.doMotion(); - } - } - // Load from wallet pubkey - else if (csWallet.isLogin()){ - if ($scope.loading) { - return $scope.load(csWallet.data.pubkey, true /*withCache*/, csWallet.data.uid) - .then(function() { + else { + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + if (!wallet.isLogin()) { + return $scope.showHome(); + } + return $scope.load(wallet.data.pubkey, wallet.data.uid, options) + .then(function () { $scope.doMotion(); $scope.showHelpTip(); }); } - else { - $scope.doMotion(); - } } - // Redirect to home else { - $scope.showHome(); + $scope.doMotion(); } }); @@ -1174,7 +1313,11 @@ function WotCertificationsViewController($scope, $rootScope, $controller, csSett // Updating data $scope.doUpdate = function() { - return $scope.load($scope.formData.pubkey, false /*no cache*/, $scope.formData.uid) + var options = { + cache: false, // No cache + blockUid: $scope.formData.blockUid || undefined + }; + return $scope.load($scope.formData.pubkey, $scope.formData.uid, options) .then(function() { $scope.doMotion(); $scope.showHelpTip(); @@ -1182,6 +1325,7 @@ function WotCertificationsViewController($scope, $rootScope, $controller, csSett }; $scope.doMotion = function(skipItems) { + // Motions received certifications part $scope.doMotionReceivedCertifications(0, skipItems); @@ -1269,7 +1413,7 @@ function WotCertificationsViewController($scope, $rootScope, $controller, csSett /** - * Select identities from a pubkey (yusfull when many self on the same pubkey) + * Select identities from a pubkey (useful when many self on the same pubkey) * @param $scope * @param $q * @param csWot diff --git a/assets/www/js/directives.js b/assets/www/js/directives.js index 297fc02d7b386f4da678a22cf785bd9e7b605871..c5ffb69b63a08a72024d360f2ce5ed1cc392c66e 100644 --- a/assets/www/js/directives.js +++ b/assets/www/js/directives.js @@ -102,7 +102,11 @@ angular.module('cesium.directives', []) link: function(scope, element, attributes, ngModel) { if (ngModel) { ngModel.$validators.geoPoint = function(value) { - return ngModel.$isEmpty(value) || (angular.isDefined(value.lat) && angular.isDefined(value.lon)); + return ngModel.$isEmpty(value) || + // twice are defined + (angular.isDefined(value.lat) && angular.isDefined(value.lon)) || + // or twice are NOT defined (=empty object - can be useful to override data in ES node) + (angular.isUndefined(value.lat) && angular.isUndefined(value.lon)); }; } } @@ -110,7 +114,7 @@ angular.module('cesium.directives', []) }) // Add a copy-on-click directive - .directive('copyOnClick', function ($window, $document, Device, UIUtils) { + .directive('copyOnClick', function ($window, Device, UIUtils) { 'ngInject'; return { restrict: 'A', @@ -409,15 +413,17 @@ angular.module('cesium.directives', []) // Un-authenticate when window closed // see: https://stackoverflow.com/questions/28197316/javascript-or-angularjs-defer-browser-close-or-tab-close-between-refresh - .directive('windowExitUnauth', function($window, csWallet) { + .directive('windowExitUnauth', function($window, csSettings, csWallet) { return { restrict: 'AE', link: function(element, attrs){ var myEvent = $window.attachEvent || $window.addEventListener, - chkevent = $window.attachEvent ? 'onunload' : 'unload'; /// make IE7, IE8 compatable + chkevent = $window.attachEvent ? 'onunload' : 'unload'; /// make IE7, IE8 compatible myEvent(chkevent, function (e) { // For >=IE7, Chrome, Firefox - return csWallet.unauth(); + if (csSettings.data && csSettings.data.keepAuthIdle != csSettings.constants.KEEP_AUTH_IDLE_SESSION) { + return csWallet.unauth(); + } }); } }; diff --git a/assets/www/js/entities/peer.js b/assets/www/js/entities/peer.js index 0800c571386f74ec4ddc493ec1d510c5be0a4489..6672ba834b6a773841df4ab1c56084b8e21b7f84 100644 --- a/assets/www/js/entities/peer.js +++ b/assets/www/js/entities/peer.js @@ -9,7 +9,6 @@ function Peer(json) { }); that.endpoints = that.endpoints || []; - that.statusTS = that.statusTS || 0; } @@ -34,7 +33,7 @@ Peer.prototype.keyID = function () { Peer.prototype.copyValues = function(to) { var obj = this; - ["version", "currency", "pub", "endpoints", "hash", "status", "statusTS", "block", "signature"].forEach(function (key) { + ["version", "currency", "pub", "endpoints", "hash", "status", "block", "signature"].forEach(function (key) { to[key] = obj[key]; }); }; @@ -60,7 +59,8 @@ Peer.prototype.json = function() { Peer.prototype.getBMA = function() { if (this.bma) return this.bma; var bma = null; - var bmaRegex = this.regex.BMA_REGEXP; + var bmaRegex = this.regexp.BMA_REGEXP; + var bmasRegex = this.regexp.BMAS_REGEXP; this.endpoints.forEach(function(ep){ var matches = !bma && bmaRegex.exec(ep); if (matches) { @@ -68,7 +68,20 @@ Peer.prototype.getBMA = function() { "dns": matches[2] || '', "ipv4": matches[4] || '', "ipv6": matches[6] || '', - "port": matches[8] || 80 + "port": matches[8] || 80, + "useSsl": matches[8] == 443, + "useBma": true + }; + } + matches = !bma && bmasRegex.exec(ep); + if (matches) { + bma = { + "dns": matches[2] || '', + "ipv4": matches[4] || '', + "ipv6": matches[6] || '', + "port": matches[8] || 80, + "useSsl": true, + "useBma": true }; } }); @@ -88,7 +101,6 @@ Peer.prototype.hasEndpoint = function(endpoint){ var endpoints = this.getEndpoints(regExp); if (!endpoints.length) return false; else return true; - }; Peer.prototype.getDns = function() { @@ -111,24 +123,24 @@ Peer.prototype.getPort = function() { return bma.port ? bma.port : null; }; -Peer.prototype.getHost = function() { - var bma = this.bma || this.getBMA(); +Peer.prototype.getHost = function(getHost) { + bma = getHost || this.bma || this.getBMA(); return ((bma.port == 443 || bma.useSsl) && bma.dns) ? bma.dns : (this.hasValid4(bma) ? bma.ipv4 : (bma.dns ? bma.dns : (bma.ipv6 ? '[' + bma.ipv6 + ']' :''))); }; -Peer.prototype.getURL = function() { - var bma = this.bma || this.getBMA(); - var host = this.getHost(); +Peer.prototype.getURL = function(bma) { + bma = bma || this.bma || this.getBMA(); + var host = this.getHost(bma); var protocol = (bma.port == 443 || bma.useSsl) ? 'https' : 'http'; return protocol + '://' + host + (bma.port ? (':' + bma.port) : ''); }; -Peer.prototype.getServer = function() { - var bma = this.bma || this.getBMA(); - var host = this.getHost(); +Peer.prototype.getServer = function(bma) { + bma = bma || this.bma || this.getBMA(); + var host = this.getHost(bma); return host + (host && bma.port ? (':' + bma.port) : ''); }; @@ -153,8 +165,16 @@ Peer.prototype.isTor = function() { return bma.useTor; }; - Peer.prototype.isWs2p = function() { var bma = this.bma || this.getBMA(); return bma.useWs2p; }; + +Peer.prototype.isBma = function() { + var bma = this.bma || this.getBMA(); + return !bma.useWs2p && !bma.useTor; +}; + +Peer.prototype.hasBma = function() { + return this.hasEndpoint('(BASIC_MERKLE_API|BMAS|BMATOR)'); +}; diff --git a/assets/www/js/filters.js b/assets/www/js/filters.js index 72e9d1671a861985e34c481a5b0e207281cc430f..3cf9060aecc3d0cda3b9b53604dc0d5d8c1a9635 100644 --- a/assets/www/js/filters.js +++ b/assets/www/js/filters.js @@ -2,7 +2,7 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalprecht.translate', 'cesium.translations' ]) - .factory('filterTranslations', function($rootScope, csPlatform, csSettings, $translate) { + .factory('filterTranslations', function($rootScope, $q, csPlatform, csSettings, csCurrency, $translate, $timeout) { 'ngInject'; var @@ -10,6 +10,8 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre startPromise, that = this; + that.MEDIAN_TIME_OFFSET = 3600 /*G1 default value*/; + // Update some translations, when locale changed function onLocaleChange() { console.debug('[filter] Loading translations for locale [{0}]'.format($translate.use())); @@ -38,8 +40,14 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre }); } + // Update some translations, when locale changed + function onCurrencyChange() { + console.debug('[filter] Computing constants from currency parameters'); + that.MEDIAN_TIME_OFFSET = csCurrency.data.medianTimeOffset || that.MEDIAN_TIME_OFFSET; + } + that.ready = function() { - if (started) return $q.when(data); + if (started) return $q.when(); return startPromise || that.start(); }; @@ -47,15 +55,20 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre startPromise = csPlatform.ready() .then(onLocaleChange) .then(function() { + onCurrencyChange(); started = true; csSettings.api.locale.on.changed($rootScope, onLocaleChange, this); + csCurrency.api.data.on.ready($rootScope, onCurrencyChange, this); }); return startPromise; }; // Default action - that.start(); + // Must be started with a delay, to allow settings override, before starting platform (need by Cesium API) + $timeout(function() { + that.start(); + }); return that; }) @@ -150,7 +163,6 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre }; }) - .filter('currencySymbol', function(filterTranslations, $filter, csSettings) { return function(input, useRelative) { if (!input) return ''; @@ -169,7 +181,6 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre }; }) - .filter('formatDecimal', function(csConfig, csCurrency) { var minValue = 1 / Math.pow(10, csConfig.decimalCount || 4); var format = '0,0.0' + Array(csConfig.decimalCount || 4).join('0'); @@ -233,6 +244,12 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre }; }) + .filter('formatFromNowAndDate', function(filterTranslations) { + return function(input, options) { + var m = input && moment.unix(parseInt(input)); + return m && (m.fromNow() + (options && options.separator || ' | ') + m.local().format(filterTranslations.DATE_PATTERN || 'YYYY-MM-DD HH:mm')) || ''; + }; + }) .filter('formatDurationTo', function() { return function(input) { @@ -281,10 +298,53 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre .filter('formatFromNowShort', function() { return function(input) { - return input ? moment.unix(parseInt(input)).fromNow(true) : ''; + return input ? moment.unix(parseInt(input)+offset).fromNow(true) : ''; }; }) + /* -- median time (apply currency offset)-- */ + + .filter('medianDate', function(filterTranslations) { + return function(input) { + return input ? moment.unix(parseInt(input) + filterTranslations.MEDIAN_TIME_OFFSET).local().format(filterTranslations.DATE_PATTERN || 'YYYY-MM-DD HH:mm') : ''; + }; + }) + + .filter('medianDateShort', function(filterTranslations) { + return function(input) { + return input ? moment.unix(parseInt(input) + filterTranslations.MEDIAN_TIME_OFFSET).local().format(filterTranslations.DATE_SHORT_PATTERN || 'YYYY-MM-DD') : ''; + }; + }) + + + .filter('medianTime', function(filterTranslations) { + return function(input) { + return input ? moment.unix(parseInt(input)+filterTranslations.MEDIAN_TIME_OFFSET).local().format('HH:mm') : ''; + }; + }) + + .filter('medianFromNow', function(filterTranslations) { + return function(input) { + return input ? moment.unix(parseInt(input) + filterTranslations.MEDIAN_TIME_OFFSET).fromNow() : ''; + }; + }) + + .filter('medianFromNowShort', function(filterTranslations) { + return function(input) { + return input ? moment.unix(parseInt(input)+filterTranslations.MEDIAN_TIME_OFFSET).fromNow(true) : ''; + }; + }) + + .filter('medianFromNowAndDate', function(filterTranslations) { + return function(input, options) { + var m = input && moment.unix(parseInt(input)+filterTranslations.MEDIAN_TIME_OFFSET); + return m && (m.fromNow() + (options && options.separator || ' | ') + m.local().format(filterTranslations.DATE_PATTERN || 'YYYY-MM-DD HH:mm')) || ''; + }; + }) + + + /* -- text filter -- */ + .filter('capitalize', function() { return function(input) { if (!input) return ''; @@ -378,6 +438,7 @@ angular.module('cesium.filters', ['cesium.config', 'cesium.platform', 'pascalpre return function(input, size) { size = size || 25; var startIndex = input.startsWith('http://') ? 7 : (input.startsWith('https://') ? 8 : 0); + startIndex = input.startsWith('www.', startIndex) ? startIndex + 4 : startIndex; // Remove sequence 'www.' return !input || (input.length-startIndex) <= size ? input.substr(startIndex) : (input.substr(startIndex, size) + '...'); }; }) diff --git a/assets/www/js/platform.js b/assets/www/js/platform.js index 2271ad05d6d8ab29cd60e159d83506851134b5c1..af22cfe12c8934c1431c3285452314e99217dbc6 100644 --- a/assets/www/js/platform.js +++ b/assets/www/js/platform.js @@ -77,12 +77,12 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] IdleProvider.timeout(csConfig.logoutTimeout||15); // display warning during 15s }) - .factory('$exceptionHandler', function() { + .factory('$exceptionHandler', function($log) { 'ngInject'; return function(exception, cause) { - if (cause) console.error(exception, cause); - else console.error(exception); + if (cause) $log.error(exception, cause); + else $log.error(exception); }; }) @@ -137,23 +137,52 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] throw 'ERROR.CHECK_NETWORK_CONNECTION'; } var newServer = fallbackNode.host + ((!fallbackNode.port && fallbackNode.port != 80 && fallbackNode.port != 443) ? (':' + fallbackNode.port) : ''); - return $translate('CONFIRM.USE_FALLBACK_NODE', {old: BMA.server, new: newServer}) - .then(function(msg) { - return UIUtils.alert.confirm(msg); + + // Skip is same as actual node + if (BMA.node.same(fallbackNode.host, fallbackNode.port)) { + console.debug('[platform] Skipping fallback node [{0}]: same as actual node'.format(newServer)); + return checkBmaNodeAlive(); // loop (= go to next node) + } + + // Try to get summary + return csHttp.get(fallbackNode.host, fallbackNode.port, '/node/summary', fallbackNode.port==443 || BMA.node.forceUseSsl)() + .catch(function(err) { + console.error('[platform] Could not reach fallback node [{0}]: skipping'.format(newServer)); + // silent, but return no result (will loop to the next fallback node) }) - .then(function (confirm) { - if (!confirm) return; + .then(function(res) { + if (!res) return checkBmaNodeAlive(); // Loop + + // Force to show port/ssl, if this is the only difference + var messageParam = {old: BMA.server, new: newServer}; + if (messageParam.old === messageParam.new) { + if (BMA.port != fallbackNode.port) { + messageParam.new += ':' + fallbackNode.port; + } + else if (BMA.useSsl == false && (fallbackNode.useSsl || fallbackNode.port==443)) { + messageParam.new += ' (SSL)'; + } + } + + return $translate('CONFIRM.USE_FALLBACK_NODE', messageParam) + .then(function(msg) { + return UIUtils.alert.confirm(msg); + }) + .then(function (confirm) { + if (!confirm) return; - // FIXME: should not change settings, but only tha BMA content - // in UI, display data form BMA object - csSettings.data.node = fallbackNode; + // Only change BMA node in settings + csSettings.data.node = fallbackNode; - csSettings.data.node.temporary = true; - csHttp.cache.clear(); + // Add a marker, for UI + csSettings.data.node.temporary = true; - // loop - return BMA.copy(fallbackNode) - .then(checkBmaNodeAlive); + csHttp.cache.clear(); + + // loop + return BMA.copy(fallbackNode) + .then(checkBmaNodeAlive); + }); }); } @@ -161,7 +190,6 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] return started; } - function getLatestRelease() { var latestRelease = csSettings.data.latestReleaseUrl && csHttp.uri.parse(csSettings.data.latestReleaseUrl); if (latestRelease) { @@ -247,8 +275,8 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] .catch(function(err) { startPromise = null; started = false; - if($state.current.name !== 'app.home') { - $state.go('app.home', {error: 'peer'}); + if($state.current.name !== $rootScope.errorState) { + $state.go($rootScope.errorState, {error: 'peer'}); } throw err; }); @@ -284,7 +312,7 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] }; }) - .run(function($rootScope, $translate, $state, $window, $urlRouter, ionicReady, + .run(function($rootScope, $state, $window, $urlRouter, ionicReady, $ionicPlatform, $ionicHistory, Device, UIUtils, $ionicConfig, PluginService, csPlatform, csWallet, csSettings, csConfig, csCurrency) { 'ngInject'; @@ -293,6 +321,8 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] $rootScope.settings = csSettings.data; $rootScope.currency = csCurrency.data; $rootScope.device = Device; + $rootScope.errorState = 'app.home'; + $rootScope.smallscreen = UIUtils.screen.isSmall(); // Compute the root path var hashIndex = $window.location.href.indexOf('#'); @@ -333,15 +363,14 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] } // Ionic Platform Grade is not A, disabling views transitions - if (ionic.Platform.grade.toLowerCase() != 'a') { + if (ionic.Platform.grade.toLowerCase() !== 'a') { console.info('[app] Disabling UI effects, because plateform\'s grade is [' + ionic.Platform.grade + ']'); UIUtils.setEffects(false); } // Status bar style if (window.StatusBar) { - // org.apache.cordova.statusbar required - StatusBar.styleDefault(); + console.debug("[app] Status bar plugin enable"); } // Get latest release @@ -356,17 +385,33 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services'] } }); + // Prevent BACK button to exit without confirmation + $ionicPlatform.registerBackButtonAction(function(event) { + if ($ionicHistory.backView()) { + return $ionicHistory.goBack(); + } + event.preventDefault(); + return UIUtils.alert.confirm('CONFIRM.EXIT_APP') + .then(function (confirm) { + if (!confirm) return; // user cancelled + ionic.Platform.exitApp(); + }); + }, 100); + // Make sure platform is started return csPlatform.ready(); }); + + + }) ; // Workaround to add "".startsWith() if not present if (typeof String.prototype.startsWith !== 'function') { console.debug("Adding String.prototype.startsWith() -> was missing on this platform"); - String.prototype.startsWith = function(prefix) { - return this.indexOf(prefix) === 0; + String.prototype.startsWith = function(prefix, position) { + return this.indexOf(prefix, position) === 0; }; } diff --git a/assets/www/js/services.js b/assets/www/js/services.js index 91d3c4d515cfd9a605635d5227cb01b5381c97eb..5fde0394e561b6dd0b705d11fefd0739445c12fe 100644 --- a/assets/www/js/services.js +++ b/assets/www/js/services.js @@ -1,4 +1,7 @@ angular.module('cesium.services', [ + // removeIf(device) + 'cesium.desktop.services', + // endRemoveIf(device) 'cesium.settings.services', 'cesium.http.services', 'cesium.network.services', diff --git a/assets/www/js/services/bma-services.js b/assets/www/js/services/bma-services.js index 6ab8529207fcd2d224f8400ec0fece63c619b5a3..8c19c2e9b83cef421fc88db6535970894ea19f2b 100644 --- a/assets/www/js/services/bma-services.js +++ b/assets/www/js/services/bma-services.js @@ -2,7 +2,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.settings.services']) -.factory('BMA', function($q, $window, $rootScope, $timeout, CryptoUtils, Api, Device, csConfig, csSettings, csHttp) { +.factory('BMA', function($q, $window, $rootScope, $timeout, csCrypto, Api, Device, UIUtils, csConfig, csSettings, csHttp) { 'ngInject'; function BMA(host, port, useSsl, useCache) { @@ -20,20 +20,28 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. OUTPUT_OBJ = 'OBJ\\(([0-9]+)\\)', OUTPUT_OBJ_OPERATOR = OUTPUT_OBJ + '[ ]*' + OUTPUT_OPERATOR + '[ ]*' + OUTPUT_OBJ, REGEX_ENDPOINT_PARAMS = "( ([a-z_][a-z0-9-_.ÄŸÄž]*))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))( (.+))?", + api = { + BMA: 'BASIC_MERKLED_API', + BMAS: 'BMAS', + WS2P: 'WS2P', + BMATOR: 'BMATOR', + WS2PTOR: 'WS2PTOR' + }, regexp = { - USER_ID: "[A-Za-z0-9_-]+", - CURRENCY: "[A-Za-z0-9_-]+", + USER_ID: "[0-9a-zA-Z-_]+", + CURRENCY: "[0-9a-zA-Z-_]+", PUBKEY: pubkey, - PUBKEY_WITH_CHECKSUM: "(" + pubkey +")" + ":([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{3})", + PUBKEY_WITH_CHECKSUM: "(" + pubkey +"):([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{3})", COMMENT: "[ a-zA-Z0-9-_:/;*\\[\\]()?!^\\+=@&~#{}|\\\\<>%.]*", + INVALID_COMMENT_CHARS: "[^ a-zA-Z0-9-_:/;*\\[\\]()?!^\\+=@&~#{}|\\\\<>%.]*", // duniter://[uid]:[pubkey]@[host]:[port] URI_WITH_AT: "duniter://(?:([A-Za-z0-9_-]+):)?("+pubkey+"@([a-zA-Z0-9-.]+.[ a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+)", URI_WITH_PATH: "duniter://([a-zA-Z0-9-.]+.[a-zA-Z0-9-_:.]+)/("+pubkey+")(?:/([A-Za-z0-9_-]+))?", - BMA_ENDPOINT: "BASIC_MERKLED_API" + REGEX_ENDPOINT_PARAMS, - BMAS_ENDPOINT: "BMAS" + REGEX_ENDPOINT_PARAMS, - WS2P_ENDPOINT: "WS2P ([a-f0-9]{8})"+ REGEX_ENDPOINT_PARAMS, - BMATOR_ENDPOINT: "BMATOR ([a-z0-9-_.]*|[0-9.]+|[0-9a-f:]+.onion)(?: ([0-9]+))?", - WS2PTOR_ENDPOINT: "WS2PTOR ([a-f0-9]{8}) ([a-z0-9-_.]*|[0-9.]+|[0-9a-f:]+.onion)(?: ([0-9]+))?(?: (.+))?" + BMA_ENDPOINT: api.BMA + REGEX_ENDPOINT_PARAMS, + BMAS_ENDPOINT: api.BMAS + REGEX_ENDPOINT_PARAMS, + WS2P_ENDPOINT: api.WS2P + " ([a-f0-9]{8})"+ REGEX_ENDPOINT_PARAMS, + BMATOR_ENDPOINT: api.BMATOR + " ([a-z0-9-_.]*|[0-9.]+|[0-9a-f:]+.onion)(?: ([0-9]+))?", + WS2PTOR_ENDPOINT: api.WS2PTOR + " ([a-f0-9]{8}) ([a-z0-9-_.]*|[0-9.]+|[0-9a-f:]+.onion)(?: ([0-9]+))?(?: (.+))?" }, errorCodes = { REVOCATION_ALREADY_REGISTERED: 1002, @@ -57,13 +65,12 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. ROOT_BLOCK_HASH: 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855', LIMIT_REQUEST_COUNT: 5, // simultaneous async request to a Duniter node LIMIT_REQUEST_DELAY: 1000, // time (in second) to wait between to call of a rest request - regex: regexp, // deprecated - regexp: regexp + regexp: regexp, + api: api }, listeners, that = this; - that.date = {now: csHttp.date.now}; that.api = new Api(this, 'BMA-' + that.server); that.started = false; that.init = init; @@ -75,7 +82,6 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. console.debug('[BMA] Enable SSL (forced by config or detected in URL)'); } - if (host) { init(host, port, useSsl, useCache); } @@ -123,8 +129,10 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. } function closeWs() { + if (!that.cache) return; + console.warn('[BMA] Closing all websockets...'); - _.keys(that.cache.wsByPath).forEach(function(key) { + _.keys(that.cache.wsByPath||{}).forEach(function(key) { var sock = that.cache.wsByPath[key]; sock.close(); }); @@ -142,14 +150,14 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. cacheTime = that.useCache && cacheTime; var cacheKey = path + (cacheTime ? ('#'+cacheTime) : ''); - var getRequest = function(params) { + var getRequestFn = function(params) { if (!that.started) { if (!that._startPromise) { - console.error('[BMA] Trying to get [{0}] before start()...'.format(path)); + console.warn('[BMA] Trying to get [{0}] before start(). Waiting...'.format(path)); } return that.ready().then(function() { - return getRequest(params); + return getRequestFn(params); }); } @@ -163,10 +171,30 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. } that.cache.getByPath[cacheKey] = request; } - return request(params); + var execCount = 1; + return request(params) + .catch(function(err){ + // If node return too many requests error + if (err && err.ucode == exports.errorCodes.HTTP_LIMITATION) { + // If max number of retry not reach + if (execCount <= exports.constants.LIMIT_REQUEST_COUNT) { + if (execCount === 1) { + console.warn("[BMA] Too many HTTP requests: Will wait then retry..."); + // Update the loading message (if exists) + UIUtils.loading.update({template: "COMMON.LOADING_WAIT"}); + } + // Wait 1s then retry + return $timeout(function() { + execCount++; + return request(params); + }, exports.constants.LIMIT_REQUEST_DELAY); + } + } + throw err; + }); }; - return getRequest; + return getRequestFn; }; post = function(path) { @@ -194,26 +222,16 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. ws = function(path) { return function() { var sock = that.cache.wsByPath[path]; - if (!sock) { + if (!sock || sock.isClosed()) { sock = csHttp.ws(that.host, that.port, path, that.useSsl); - // Override close methods (add a usage counter) - sock._counter = 1; - var inheritedClose = sock.close; - sock.close = function() { - sock._counter--; - if (sock._counter <= 0) { - console.debug('[BMA] Closing websocket ['+path+']'); - inheritedClose(); - delete that.cache.wsByPath[path]; - } + // When close, remove from cache + sock.onclose = function() { + delete that.cache.wsByPath[path]; }; that.cache.wsByPath[path] = sock; } - else { - sock._counter++; - } return sock; }; }; @@ -221,10 +239,19 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. that.isAlive = function() { return csHttp.get(that.host, that.port, '/node/summary', that.useSsl)() .then(function(json) { - var isDuniter = json && json.duniter && json.duniter.software == 'duniter' && json.duniter.version; - var isCompatible = isDuniter && csHttp.version.isCompatible(csSettings.data.minVersion, json.duniter.version); - if (isDuniter && !isCompatible) { - console.error('[BMA] Uncompatible version [{0}] - expected at least [{1}]'.format(json.duniter.version, csSettings.data.minVersion)); + var software = json && json.duniter && json.duniter.software; + var isCompatible = true; + + // Check duniter min version + if (software === 'duniter' && json.duniter.version && true) { + isCompatible = csHttp.version.isCompatible(csSettings.data.minVersion, json.duniter.version); + } + // TODO: check other software (DURS, Juniter, etc.) + else { + console.debug('[BMA] Unknown node software [{0} v{1}]: could not check compatibility.'.format(software || '?', json.duniter.version || '?')); + } + if (!isCompatible) { + console.error('[BMA] Incompatible node [{0} v{1}]: expected at least v{2}'.format(software, json.duniter.version, csSettings.data.minVersion)); } return isCompatible; }) @@ -289,7 +316,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. console.debug('[BMA] Starting [{0}]...'.format(that.server)); } - var now = new Date().getTime(); + var now = Date.now(); that._startPromise = $q.all([ csSettings.ready, @@ -308,7 +335,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. if (!listeners || listeners.length === 0) { addListeners(); } - console.debug('[BMA] Started in '+(new Date().getTime()-now)+'ms'); + console.debug('[BMA] Started in '+(Date.now()-now)+'ms'); that.api.node.raise.start(); that.started = true; @@ -372,8 +399,9 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. node: { summary: get('/node/summary', csHttp.cache.LONG), same: function(host2, port2) { - return host2 == that.host && ((!that.port && !port2) || (that.port == port2||80)); + return host2 === that.host && ((!that.port && !port2) || (that.port == port2||80)) && (that.useSsl == (port2 && port2 === 443)); }, + forceUseSsl: that.forceUseSsl }, network: { peering: { @@ -387,34 +415,38 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. } }, wot: { - lookup: get('/wot/lookup/:search'), + lookup: get('/wot/lookup/:search', csHttp.cache.MEDIUM), certifiedBy: get('/wot/certified-by/:pubkey'), certifiersOf: get('/wot/certifiers-of/:pubkey'), member: { all: get('/wot/members', csHttp.cache.LONG), pending: get('/wot/pending', csHttp.cache.SHORT) }, - requirements: get('/wot/requirements/:pubkey'), + requirements: function(params, withCache) { + // No cache by default + if (withCache !== true) return exports.raw.requirementsNoCache(params); + return exports.raw.requirementsWithCache(params); + }, add: post('/wot/add'), certify: post('/wot/certify'), revoke: post('/wot/revoke') }, blockchain: { - parameters: get('/blockchain/parameters', csHttp.cache.LONG), + parameters: get('/blockchain/parameters', csHttp.cache.VERY_LONG), block: get('/blockchain/block/:block', csHttp.cache.SHORT), blocksSlice: get('/blockchain/blocks/:count/:from'), - current: get('/blockchain/current'), + current: get('/blockchain/current', csHttp.cache.SHORT), membership: post('/blockchain/membership'), stats: { - ud: get('/blockchain/with/ud', csHttp.cache.SHORT), + ud: get('/blockchain/with/ud', csHttp.cache.MEDIUM), tx: get('/blockchain/with/tx'), - newcomers: get('/blockchain/with/newcomers'), + newcomers: get('/blockchain/with/newcomers', csHttp.cache.MEDIUM), hardship: get('/blockchain/hardship/:pubkey'), difficulties: get('/blockchain/difficulties') } }, tx: { - sources: get('/tx/sources/:pubkey'), + sources: get('/tx/sources/:pubkey', csHttp.cache.SHORT), process: post('/tx/process'), history: { all: get('/tx/history/:pubkey'), @@ -429,7 +461,10 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. }, uri: {}, version: {}, - raw: {} + raw: { + requirementsWithCache: get('/wot/requirements/:pubkey', csHttp.cache.LONG), + requirementsNoCache: get('/wot/requirements/:pubkey') + } }; exports.regex = exports.regexp; // deprecated @@ -528,7 +563,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. }; }; - exports.node.parseEndPoint = function(endpoint) { + exports.node.parseEndPoint = function(endpoint, epPrefix) { // Try BMA var matches = exports.regexp.BMA_ENDPOINT.exec(endpoint); if (matches) { @@ -593,12 +628,35 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. "useWs2p": true }; } + + // Use generic match + if (epPrefix) { + matches = exact(epPrefix + REGEX_ENDPOINT_PARAMS).exec(endpoint); + if (matches) { + return { + "dns": matches[2] || '', + "ipv4": matches[4] || '', + "ipv6": matches[6] || '', + "port": matches[8] || 80, + "useSsl": matches[8] && matches[8] == 443, + "path": matches[10], + "useBma": false + }; + } + } + }; exports.copy = function(otherNode) { - if (that.started) that.stop(); - that.init(otherNode.host, otherNode.port, otherNode.useSsl, that.useCache/*keep original value*/); - return that.start(); + var wasStarted = that.started; + + var server = csHttp.getUrl(otherNode.host, otherNode.port, ''/*path*/, otherNode.useSsl); + var hasChanged = (server !== that.url); + if (hasChanged) { + that.init(otherNode.host, otherNode.port, otherNode.useSsl, that.useCache/*keep original value*/); + // Restart (only if was already started) + return wasStarted ? that.restart() : $q.when(); + } }; exports.wot.member.uids = function() { @@ -642,10 +700,10 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. * @param blockNumbers a rray of block number */ exports.network.peering.peersByLeaves = function(leaves){ - return exports.raw.getHttpRecursive(exports.network.peering.peers, 'leaf', leaves, 0, 10, callbackFlush); + return exports.raw.getHttpRecursive(exports.network.peering.peers, 'leaf', leaves, 0, 10); }; - exports.raw.getHttpRecursive = function(httpGetRequest, paramName, paramValues, offset, size, callbackFlush) { + exports.raw.getHttpRecursive = function(httpGetRequest, paramName, paramValues, offset, size) { offset = angular.isDefined(offset) ? offset : 0; size = size || exports.constants.LIMIT_REQUEST_COUNT; return $q(function(resolve, reject) { @@ -726,6 +784,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. exports.uri.parse = function(uri) { return $q(function(resolve, reject) { var pubkey; + // If pubkey: not need to parse if (exact(regexp.PUBKEY).test(uri)) { resolve({ @@ -734,14 +793,21 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. } // If pubkey+checksum else if (exact(regexp.PUBKEY_WITH_CHECKSUM).test(uri)) { + console.debug("[BMA.parse] Detecting a pubkey with checksum: " + uri); var matches = exports.regexp.PUBKEY_WITH_CHECKSUM.exec(uri); pubkey = matches[1]; var checksum = matches[2]; - var expectedChecksum = CryptoUtils.checksum_from_sign_pk(CryptoUtils.base58.decode(pubkey)); - if (checksum != expectedChecksum) throw {message: 'ERROR.PUBKEY_INVALID_CHECKSUM'}; - resolve({ - pubkey: pubkey - }); + console.debug("[BMA.parse] Detecting a pubkey {"+pubkey+"} with checksum {" + checksum + "}"); + var expectedChecksum = csCrypto.util.pkChecksum(pubkey); + console.debug("[BMA.parse] Expecting checksum for pubkey is {" + expectedChecksum + "}"); + if (checksum != expectedChecksum) { + reject( {message: 'ERROR.PUBKEY_INVALID_CHECKSUM'}); + } + else { + resolve({ + pubkey: pubkey + }); + } } else if(uri.startsWith('duniter://')) { var parser = csHttp.uri.parse(uri), @@ -787,6 +853,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. }); }) .catch(function(err) { + console.error(err); reject({message: 'Could not get node parameter. Currency could not be retrieve'}); }); } @@ -815,25 +882,30 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. host: host, currency: currency }); + }) + .catch(function(err) { + console.error(err); + reject({message: 'Could not get node parameter. Currency could not be retrieve'}); }); } } else { - console.warn('Unknown URI format: ' + uri); - throw {message: 'ERROR.UNKNOWN_URI_FORMAT'}; + console.debug("[BMA.parse] Could not parse URI: " + uri); + reject({message: 'ERROR.UNKNOWN_URI_FORMAT'}); } }) // Check values against regex .then(function(result) { + if (!result) return; if (result.pubkey && !(exact(regexp.PUBKEY).test(result.pubkey))) { - reject({message: "Invalid pubkey format [" + result.pubkey + "]"}); return; + throw {message: "Invalid pubkey format [" + result.pubkey + "]"}; } if (result.uid && !(exact(regexp.USER_ID).test(result.uid))) { - reject({message: "Invalid uid format [" + result.uid + "]"}); return; + throw {message: "Invalid uid format [" + result.uid + "]"}; } if (result.currency && !(exact(regexp.CURRENCY).test(result.currency))) { - reject({message: "Invalid currency format ["+result.currency+"]"}); return; + throw {message: "Invalid currency format ["+result.currency+"]"}; } return result; }); @@ -888,9 +960,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. var service = new BMA(undefined, undefined, undefined, true); service.instance = function(host, port, useSsl, useCache) { - var bma = new BMA(); - bma.init(host, port, useSsl, useCache); - return bma; + return new BMA(host, port, useSsl, useCache); }; service.lightInstance = function(host, port, useSsl, timeout) { diff --git a/assets/www/js/services/cache-services.js b/assets/www/js/services/cache-services.js index 310d58a23a40de888a74e24719ace0e9be6e82bc..08921d8bde5ee4a73c84d8de86867979821bb5cd 100644 --- a/assets/www/js/services/cache-services.js +++ b/assets/www/js/services/cache-services.js @@ -1,12 +1,14 @@ angular.module('cesium.cache.services', ['angular-cache']) -.factory('csCache', function($http, csSettings, CacheFactory) { +.factory('csCache', function($http, $window, csSettings, CacheFactory) { 'ngInject'; var constants = { - LONG: 1 * 60 * 60 * 1000 /*5 min*/, - SHORT: csSettings.defaultSettings.cacheTimeMs + VERY_LONG: 54000000, /*15 days*/ + LONG: 1 * 60 * 60 * 1000 /*1 hour*/, + MEDIUM: 5 * 60 * 1000 /*5 min*/, + SHORT: csSettings.defaultSettings.cacheTimeMs // around 1min }, cacheNames = [] ; @@ -15,19 +17,22 @@ angular.module('cesium.cache.services', ['angular-cache']) prefix = prefix || 'csCache-'; maxAge = maxAge || constants.SHORT; var cacheName = prefix + maxAge; + + // FIXME : enable this when cache is cleaning on rollback + var storageMode = csSettings.data.useLocalStorage && $window.localStorage ? 'localStorage' : 'memory'; + if (!onExpire) { if (!cacheNames[cacheName]) { cacheNames[cacheName] = true; + console.debug("[cache] Creating cache {0}...".format(cacheName)); } return CacheFactory.get(cacheName) || CacheFactory.createCache(cacheName, { maxAge: maxAge, - deleteOnExpire: 'aggressive', + deleteOnExpire: 'passive', //cacheFlushInterval: 60 * 60 * 1000, // clear itself every hour recycleFreq: Math.max(maxAge - 1000, 5 * 60 * 1000 /*5min*/), - storageMode: 'memory' - // FIXME : enable this when cache is cleaning on rollback - //csSettings.data.useLocalStorage ? 'localStorage' : 'memory' + storageMode: storageMode }); } else { @@ -39,15 +44,14 @@ angular.module('cesium.cache.services', ['angular-cache']) if (!cacheNames[cacheName]) { cacheNames[cacheName] = true; } + console.debug("[cache] Creating cache {0} with 'onExpire' option...".format(cacheName)); return CacheFactory.createCache(cacheName, { maxAge: maxAge, deleteOnExpire: 'aggressive', //cacheFlushInterval: 60 * 60 * 1000, // This cache will clear itself every hour recycleFreq: maxAge, onExpire: onExpire, - storageMode: 'memory' - // FIXME : enable this when cache is cleaning on rollback - //csSettings.data.useLocalStorage ? 'localStorage' : 'memory' + storageMode: storageMode }); } } @@ -65,7 +69,7 @@ angular.module('cesium.cache.services', ['angular-cache']) function clearFromPrefix(cachePrefix) { _.forEach(_.keys(cacheNames), function(cacheName) { if (cacheName.startsWith(cachePrefix)) { - var cache = CacheFactory.get(cacheNames); + var cache = CacheFactory.get(cacheName); if (cache) { cache.removeAll(); } @@ -77,10 +81,7 @@ angular.module('cesium.cache.services', ['angular-cache']) get: getOrCreateCache, clear: clearFromPrefix, clearAll: clearAllCaches, - constants: { - LONG : constants.LONG, - SHORT: constants.SHORT - } + constants: constants }; }) ; diff --git a/assets/www/js/services/crypto-services.js b/assets/www/js/services/crypto-services.js index f417d7f4abbbd7aac90b8c8c5ca25be330b3b175..e60613a0dd7205da164783c8e00a838f198d3d92 100644 --- a/assets/www/js/services/crypto-services.js +++ b/assets/www/js/services/crypto-services.js @@ -5,26 +5,6 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) .factory('CryptoUtils', function($q, $timeout, ionicReady) { 'ngInject'; - function xor(a, b) { - var length = Math.max(a.length, b.length); - var buffer = new Uint8Array(length); - for (var i = 0; i < length; ++i) { - buffer[i] = a[i] ^ b[i]; - } - return buffer; - } - - function concat_Uint8Array( buffer1, buffer2 ) { - var tmp = new Uint8Array( buffer1.byteLength + buffer2.byteLength ); - tmp.set( new Uint8Array( buffer1 ), 0 ); - tmp.set( new Uint8Array( buffer2 ), buffer1.byteLength ); - return tmp; - } - - function test(regexpContent) { - return new RegExp(regexpContent); - } - /** * CryptoAbstract, abstract class with useful methods * @type {number} @@ -80,48 +60,26 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) p: 1, memory: -1 // default }, + // removeIf(no-device) SECURE: { N: 16384, r: 32, p: 2, - memory: -1 // default + memory: 33554432 }, HARDEST: { N: 65536, r: 32, p: 4, - memory: -1 // default + memory: 134217728 }, EXTREME: { N: 262144, r: 64, p: 8, - memory: -1 // default - } - }, - EWIF: { - SALT_LENGTH: 4, - DERIVED_HALF_LENGTH: 16, - }, - REGEXP: { - PUBKEY: '[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44}', - SECKEY: '[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{86,88}', - FILE: { - TYPE_LINE: '^Type: ([a-zA-Z0-9]+)\n', - VERSION: 'Version: ([0-9]+)\n', - PUB: '[Pp]ub: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44})\n', - SEC: '[Ss]ec: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{86,88})(\n|$)', - DATA: '[Dd]ata: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)(\n|$)' + memory: 536870912 } - } - }; - - CryptoAbstractService.prototype.regexp = { - FILE: { - TYPE_LINE: test(CryptoAbstractService.prototype.constants.REGEXP.FILE.TYPE_LINE), - PUB: test(CryptoAbstractService.prototype.constants.REGEXP.FILE.PUB), - SEC: test(CryptoAbstractService.prototype.constants.REGEXP.FILE.SEC), - DATA: test(CryptoAbstractService.prototype.constants.REGEXP.FILE.DATA) + // endRemoveIf(no-device) } }; @@ -133,11 +91,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) CryptoAbstractService.prototype.async_load_scrypt = function(on_ready, options) { var that = this; - if (scrypt_module_factory !== null){ - on_ready(scrypt_module_factory(options.requested_total_memory)); - that.scrypt.requested_total_memory = options.requested_total_memory; - //console.log('inside async_load_scrypt', that); // TODO manage memory changes - } + if (scrypt_module_factory !== null){scrypt_module_factory(on_ready, options);} else {$timeout(function(){that.async_load_scrypt(on_ready, options);}, 100);} }; @@ -159,290 +113,18 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) else {$timeout(function(){that.async_load_sha256(on_ready);}, 100);} }; - CryptoAbstractService.prototype.readKeyFile = function(file, options) { - var that = this; - - if (file && file.content) { - return that.parseKeyFileContent(file.content, options); - } - - return $q(function(resolve, reject) { - if (!file) { - return reject('Argument [file] is missing'); - } - - console.debug('[crypto] [keypair] reading file: ', file); - var reader = new FileReader(); - reader.onload = function (event) { - that.parseKeyFileContent(event.target.result, options) - .then(resolve) - .catch(reject); - }; - reader.readAsText(file, 'utf8'); - }); - }; - - CryptoAbstractService.prototype.parseKeyFileContent = function(content, options) { - options = options || {}; - options.withSecret = angular.isDefined(options.withSecret) ? options.withSecret : false; - options.defaultType = options.defaultType || 'PubSec'; - - var that = this; - return $q(function(resolve, reject) { - if (!content) { - return reject('Argument [content] is missing'); - } - var typeMatch = that.regexp.FILE.TYPE_LINE.exec(content); - - // no Type (first line) - if (!typeMatch && options.defaultType) { - // Add default type, then retry - return resolve(that.parseKeyFileContent('Type: {0}\n{1}'.format(options.defaultType, content), options)); - } - - var type = typeMatch[1]; - - // Type: PubSec - if (type == 'PubSec') { - var pubMatch = that.regexp.FILE.PUB.exec(content); - if (!pubMatch) { - return reject('Missing [pub] field in file, or invalid public key value'); - } - if (!options.withSecret) { - return resolve({ - signPk: that.base58.decode(pubMatch[1]) - }); - } - var secMatch = that.regexp.FILE.SEC.exec(content); - if (!secMatch) { - return reject('Missing [sec] field in file, or invalid secret key value'); - } - return resolve({ - signPk: that.base58.decode(pubMatch[1]), - signSk: that.base58.decode(secMatch[1]) - }); - } - - var signKeypair; - var matches; - - // Type: WIF - if (type == 'WIF') { - matches = that.regexp.FILE.DATA.exec(content); - if (!matches) { - return reject('Missing [Data] field in file, or invalid public key value'); - } - signKeypair = that.keypair_from_wif_v1(matches[1]); - } - - // Type: EWIF - else if (type == 'EWIF') { - matches = that.regexp.FILE.DATA.exec(content); - if (!matches) { - return reject('Missing [Data] field in file, or invalid public key value'); - } - if (!options.password) { - reject('NEED_PASSWORD'); - return; - } - try { - signKeypair = that.keypair_from_ewif_v1(matches[1], options.password); - } - catch(err) { - reject(err); - } - } - - // Unknown type - else { - if (options.defaultType) { - return reject('Bad file format: missing Type field'); - } - else { - return reject('Bad file format, unknown type [' + type + ']'); - } - } - - if (signKeypair && !options.withSecret) { - resolve({ - signPk: signKeypair.signPk - }); - } - else { - resolve(signKeypair); - } - }); - }; - - CryptoAbstractService.prototype.keypair_from_wif_v1 = function(wif_base58) { - var that = this; - var i; - var wif_int8 = that.base58.decode(wif_base58); - - if (wif_int8[0] != 1) { - throw 'Invalid WIF format: The first byte of data must be [0x01].'; - } - + CryptoAbstractService.prototype.seed_from_signSk = function(signSk) { var seed = new Uint8Array(that.constants.SEED_LENGTH); - for (i = 0; i < seed.length; i++) seed[i] = wif_int8[i+1]; - var signKeypair = that.nacl.crypto_sign_seed_keypair(seed); - - // Compute expected checksum - var checksumContent = new Uint8Array(that.constants.SEED_LENGTH + 1); - for (i = 0; i < checksumContent.length; i++) checksumContent[i] = wif_int8[i]; - var checksumHash = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(checksumContent)); - var expectedChecksum = new Uint8Array(2); - for (i = 0; i < expectedChecksum.length; i++) expectedChecksum[i] = checksumHash[i]; - expectedChecksum = that.base58.encode(expectedChecksum); - - var checksum = new Uint8Array(2); - for (i = 0; i < checksum.length; i++) checksum[i] = wif_int8[i+33]; - checksum = that.base58.encode(checksum); - - if (expectedChecksum !== checksum) { - throw 'Invalid WIF format: bad checksum'; - } - - return { - signPk: signKeypair.signPk, - signSk: signKeypair.signSk - }; - }; - - CryptoAbstractService.prototype.checksum_from_sign_pk = function(signPk) { - return this.base58.encode(this.nacl.crypto_hash_sha256(this.nacl.crypto_hash_sha256(signPk))).substring(0,3); - }; - - CryptoAbstractService.prototype.keypair_from_ewif_v1 = function(ewif_base58, password) { - var that = this; - var ewif_int8 = that.base58.decode(ewif_base58); - if (ewif_int8.length != 39) { - throw 'Invalid EWIF format: Data must be a 39 bytes array, encoded in base 58.'; - } - var fi = ewif_int8.slice(0,1); - if (fi != 0x02) { - throw 'Invalid EWIF format: The first byte of data must be [0x02].'; - } - - var ewif_int8_no_checksum = ewif_int8.slice(0,-2); - var checksum = ewif_int8.slice(-2); - var salt = ewif_int8.slice(1,5); - var encryptedhalf1 = ewif_int8.slice(5,21); - var encryptedhalf2 = ewif_int8.slice(21,37); - - var scrypt_seed = that.scrypt.crypto_scrypt( - that.util.encode_utf8(password), - salt, - 16384, - 8,8,64); - var derivedhalf1 = scrypt_seed.subarray(0,32); - var derivedhalf2 = scrypt_seed.subarray(32,64); - - //AES - var aesEcb = new aesjs.ModeOfOperation.ecb(derivedhalf2); - var decryptedhalf1 = aesEcb.decrypt(encryptedhalf1); - var decryptedhalf2 = aesEcb.decrypt(encryptedhalf2); - - decryptedhalf1 = new Uint8Array(decryptedhalf1); - decryptedhalf2 = new Uint8Array(decryptedhalf2); - - //xor - var seed1 = xor(decryptedhalf1, derivedhalf1.subarray(0,16)); - var seed2 = xor(decryptedhalf2, derivedhalf1.subarray(16,32)); - var seed = concat_Uint8Array(seed1,seed2); - var signKeypair = that.nacl.crypto_sign_seed_keypair(seed); - - // check salt - var salt_from_seed = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(signKeypair.signPk)).subarray(0,4); - if(that.base58.encode(salt) !== that.base58.encode(salt_from_seed)) { - throw 'BAD_PASSWORD'; //"Invalid password to encrypt EWIF data"; - } - - // Compute expected checksum - var expectedChecksum = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(ewif_int8_no_checksum)).subarray(0,2); - expectedChecksum = that.base58.encode(expectedChecksum); - checksum = that.base58.encode(checksum); - - if (expectedChecksum !== checksum) { - throw "Invalid EWIF format: bad checksum"; - } - - return { - signPk: signKeypair.signPk, - signSk: signKeypair.signSk - }; + for (var i = 0; i < seed.length; i++) seed[i] = signSk[i]; + return seed; }; - CryptoAbstractService.prototype.seed_from_signSk = function(signSk) { - var that = this; var seed = new Uint8Array(that.constants.SEED_LENGTH); for (var i = 0; i < seed.length; i++) seed[i] = signSk[i]; return seed; }; - CryptoAbstractService.prototype.wif_v1_from_keypair = function(keypair) { - - var that = this; - - var seed = that.seed_from_signSk(keypair.signSk); - if (!seed || seed.byteLength !== that.constants.SEED_LENGTH) - throw "Bad see format. Expected {0} bytes".format(that.constants.SEED_LENGTH); - - var fi = new Uint8Array(1); - fi[0] = 0x01; - var seed_fi = concat_Uint8Array(fi, seed); - - // checksum - var checksum = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(seed_fi)).subarray(0,2); - - var wif_int8 = concat_Uint8Array(seed_fi, checksum); - return that.base58.encode(wif_int8); - }; - - CryptoAbstractService.prototype.ewif_v1_from_keypair = function(keypair, password) { - - var that = this; - - var seed = that.seed_from_signSk(keypair.signSk); - if (!seed || seed.byteLength !== that.constants.SEED_LENGTH) - throw "Bad see format. Expected {0} bytes".format(that.constants.SEED_LENGTH); - - // salt - var salt = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(keypair.signPk)).subarray(0,4); - - // scrypt_seed - var scrypt_seed = that.scrypt.crypto_scrypt( - that.util.encode_utf8(password), - that.util.encode_utf8(salt), - 16384,8,8,64); - var derivedhalf1 = scrypt_seed.subarray(0,32); - var derivedhalf2 = scrypt_seed.subarray(32,64); - - //XOR & AES - var seed1_xor_derivedhalf1_1 = xor(seed.subarray(0,16), derivedhalf1.subarray(0,16)); - var seed2_xor_derivedhalf1_2 = xor(seed.subarray(16,32), derivedhalf1.subarray(16,32)); - - var aesEcb = new aesjs.ModeOfOperation.ecb(derivedhalf2); - var encryptedhalf1 = aesEcb.encrypt(seed1_xor_derivedhalf1_1); - var encryptedhalf2 = aesEcb.encrypt(seed2_xor_derivedhalf1_2); - - encryptedhalf1 = new Uint8Array(encryptedhalf1); - encryptedhalf2 = new Uint8Array(encryptedhalf2); - - // concatenate ewif - var ewif_int8 = new Uint8Array(1); - ewif_int8[0] = 0x02; - ewif_int8 = concat_Uint8Array(ewif_int8,salt); - ewif_int8 = concat_Uint8Array(ewif_int8,encryptedhalf1); - ewif_int8 = concat_Uint8Array(ewif_int8,encryptedhalf2); - - var checksum = that.nacl.crypto_hash_sha256(that.nacl.crypto_hash_sha256(ewif_int8)).subarray(0,2); - ewif_int8 = concat_Uint8Array(ewif_int8,checksum); - - return that.base58.encode(ewif_int8); - }; - // Web crypto API - see https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API var crypto = window.crypto || window.msCrypto || window.Crypto; if (crypto && crypto.getRandomValues) { @@ -454,16 +136,6 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) return $q.when(nonce); }; } - else { - // TODO: add a default function ? - //CryptoAbstractService.prototype.random_nonce = function() { - // var nonce = new Uint8Array(crypto_secretbox_NONCEBYTES); - // var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - // for(var i = 0; i < length; i++) { - // text += possible.charAt(Math.floor(Math.random() * possible.length)); - // } - //} - } function FullJSServiceFactory() { this.id = 'FullJS'; @@ -489,9 +161,9 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) }; this.util.decode_base58 = function (a) { // TODO : move to abstract factory var i; - a = that.base58.decode(a); - var b = new Uint8Array(a.length); - for (i = 0; i < a.length; i++) b[i] = a[i]; + var d = that.base58.decode(a); + var b = new Uint8Array(d.length); + for (i = 0; i < d.length; i++) b[i] = d[i]; return b; }; this.util.decode_base64 = function (a) { @@ -518,24 +190,74 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) return $q.when(that.nacl.crypto_box_random_nonce()); } }; + this.util.crypto_hash_sha256 = function(msg_int8) { + return that.nacl.crypto_hash_sha256(msg_int8); + }; + this.util.crypto_scrypt = function(password, salt, N, r, p, seedLength) { + + return $q(function(resolve, reject) { + try { + var seed = that.scrypt.crypto_scrypt( + password, + salt, + N, + r, + p, + seedLength); + resolve(seed); + } + catch(err) { + reject(err); + } + }); + }; /** * Compute the box key pair, from a sign key pair */ this.box_keypair_from_sign = function (signKeyPair) { - if (signKeyPair.bokSk && signKeyPair.boxPk) return $q.when(signKeyPair); - return $q.when(that.nacl.crypto_box_keypair_from_sign_sk(signKeyPair.signSk)); + if (signKeyPair.boxSk && signKeyPair.boxPk) return $q.when(signKeyPair); + return $q(function (resolve, reject) { + try { + // TODO: waiting for a new version of js-nacl, with missing functions expose + //resolve(that.nacl.crypto_box_keypair_from_sign_sk(signPk); + + resolve(crypto_box_keypair_from_sign_sk(signPk)); + } + catch(err) { + reject(err); + } + }); }; /** * Compute the box public key, from a sign public key */ this.box_pk_from_sign = function (signPk) { - return $q.when(that.nacl.crypto_box_pk_from_sign_pk(signPk)); + return $q(function(resolve, reject) { + try { + // TODO: waiting for a new version of js-nacl, with missing functions expose + //resolve(that.nacl.crypto_box_pk_from_sign_pk(signPk)); + + resolve(crypto_box_pk_from_sign_pk(signPk)); + } + catch(err) { + reject(err); + } + }); }; this.box_sk_from_sign = function (signSk) { - return $q.when(that.nacl.crypto_box_sk_from_sign_sk(signSk)); + return $q(function(resolve, reject) { + try { + // TODO: waiting for a new version of js-nacl, with missing functions expose + //resolve(that.nacl.crypto_box_sk_from_sign_sk(signSk)); + resolve(crypto_box_sk_from_sign_sk(signSk)); + } + catch(err) { + reject(err); + } + }); }; /** @@ -547,17 +269,14 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) resolve(message); return; } - var messageBin = that.util.decode_utf8(message); + var messageBin = that.nacl.encode_utf8(message); if (typeof recipientPk === "string") { recipientPk = that.util.decode_base58(recipientPk); } - //console.debug('Original message: ' + message); try { var ciphertextBin = that.nacl.crypto_box(messageBin, nonce, recipientPk, senderSk); var ciphertext = that.util.encode_base64(ciphertextBin); - - //console.debug('Encrypted message: ' + ciphertext); resolve(ciphertext); } catch (err) { @@ -575,6 +294,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) resolve(cypherText); return; } + var ciphertextBin = that.util.decode_base64(cypherText); if (typeof senderPk === "string") { senderPk = that.util.decode_base58(senderPk); @@ -582,10 +302,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) try { var message = that.nacl.crypto_box_open(ciphertextBin, nonce, senderPk, recipientSk); - that.util.array_to_string(message, function (result) { - //console.debug('Decrypted text: ' + result); - resolve(result); - }); + resolve(that.nacl.decode_utf8(message)); } catch (err) { reject(err); @@ -598,14 +315,30 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) * Create key pairs (sign and box), from salt+password (Scrypt auth) */ this.scryptKeypair = function(salt, password, scryptParams) { + return that.util.crypto_scrypt( + that.util.encode_utf8(password), + that.util.encode_utf8(salt), + scryptParams && scryptParams.N || that.constants.SCRYPT_PARAMS.DEFAULT.N, + scryptParams && scryptParams.r || that.constants.SCRYPT_PARAMS.DEFAULT.r, + scryptParams && scryptParams.p || that.constants.SCRYPT_PARAMS.DEFAULT.p, + that.constants.SEED_LENGTH) + .then(function(seed){ + var signKeypair = that.nacl.crypto_sign_seed_keypair(seed); + var boxKeypair = that.nacl.crypto_box_seed_keypair(seed); + return { + signPk: signKeypair.signPk, + signSk: signKeypair.signSk, + boxPk: boxKeypair.boxPk, + boxSk: boxKeypair.boxSk + }; + }); + }; + + /** + * Create key pairs from a seed + */ + this.seedKeypair = function(seed) { return $q(function(resolve, reject) { - var seed = that.scrypt.crypto_scrypt( - that.util.encode_utf8(password), - that.util.encode_utf8(salt), - scryptParams && scryptParams.N || that.constants.SCRYPT_PARAMS.DEFAULT.N, - scryptParams && scryptParams.r || that.constants.SCRYPT_PARAMS.DEFAULT.r, - scryptParams && scryptParams.p || that.constants.SCRYPT_PARAMS.DEFAULT.p, - that.constants.SEED_LENGTH); var signKeypair = that.nacl.crypto_sign_seed_keypair(seed); var boxKeypair = that.nacl.crypto_box_seed_keypair(seed); resolve({ @@ -678,7 +411,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) var naclOptions = {}; var scryptOptions = {}; if (ionic.Platform.grade.toLowerCase()!='a') { - console.info('Reduce NaCl memory because plateform grade is not [a] but [' + ionic.Platform.grade + ']'); + console.info('Reduce NaCl memory to 16mb, because plateform grade is not [a] but [{0}]'.format(ionic.Platform.grade)); naclOptions.requested_total_memory = 16 * 1048576; // 16 Mo } var loadedLib = 0; @@ -695,13 +428,14 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) }, naclOptions); this.async_load_scrypt(function(lib) { that.scrypt = lib; + that.scrypt.requested_total_memory = scryptOptions.requested_total_memory; checkAllLibLoaded(); }, scryptOptions); this.async_load_base58(function(lib) { that.base58 = lib; checkAllLibLoaded(); }); - this.async_load_base64(function(lib) { + that.async_load_base64(function(lib) { that.base64 = lib; checkAllLibLoaded(); }); @@ -719,6 +453,109 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) pack: that.box, open: that.box_open }; + + /*-- + start WORKAROUND - Publish missing functions (see PR js-nacl: https://github.com/tonyg/js-nacl/pull/54) + -- */ + + function crypto_box_keypair_from_sign_sk(sk) { + var ska = check_injectBytes("crypto_box_keypair_from_sign_sk", "sk", sk, + that.nacl.nacl_raw._crypto_sign_secretkeybytes()); + var skb = new Target(that.nacl.nacl_raw._crypto_box_secretkeybytes()); + check("_crypto_sign_ed25519_sk_to_curve25519", + that.nacl.nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska)); + FREE(ska); + return that.nacl.crypto_box_keypair_from_raw_sk(skb.extractBytes()); + } + + function crypto_box_pk_from_sign_pk(pk) { + var pka = check_injectBytes("crypto_box_pk_from_sign_pk", "pk", pk, + that.nacl.nacl_raw._crypto_sign_publickeybytes()); + var pkb = new Target(that.nacl.nacl_raw._crypto_box_publickeybytes()); + check("_crypto_sign_ed25519_pk_to_curve25519", + that.nacl.nacl_raw._crypto_sign_ed25519_pk_to_curve25519(pkb.address, pka)); + FREE(pka); + return pkb.extractBytes(); + } + + function crypto_box_sk_from_sign_sk(sk) { + var ska = check_injectBytes("crypto_box_sk_from_sign_sk", "sk", sk, + that.nacl.nacl_raw._crypto_sign_secretkeybytes()); + var skb = new Target(that.nacl.nacl_raw._crypto_box_secretkeybytes()); + check("_crypto_sign_ed25519_sk_to_curve25519", + that.nacl.nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska)); + FREE(ska); + return skb.extractBytes(); + } + + function check_length(function_name, what, thing, expected_length) { + if (thing.length !== expected_length) { + throw {message: "nacl." + function_name + " expected " + + expected_length + "-byte " + what + " but got length " + thing.length}; + } + } + + function check(function_name, result) { + if (result !== 0) { + throw {message: "nacl_raw." + function_name + " signalled an error"}; + } + } + + function check_injectBytes(function_name, what, thing, expected_length, leftPadding) { + check_length(function_name, what, thing, expected_length); + return injectBytes(thing, leftPadding); + } + + function injectBytes(bs, leftPadding) { + var p = leftPadding || 0; + var address = MALLOC(bs.length + p); + that.nacl.nacl_raw.HEAPU8.set(bs, address + p); + for (var i = address; i < address + p; i++) { + that.nacl.nacl_raw.HEAPU8[i] = 0; + } + return address; + } + + function MALLOC(nbytes) { + var result = that.nacl.nacl_raw._malloc(nbytes); + if (result === 0) { + throw {message: "malloc() failed", nbytes: nbytes}; + } + return result; + } + + function FREE(pointer) { + that.nacl.nacl_raw._free(pointer); + } + + function free_all(addresses) { + for (var i = 0; i < addresses.length; i++) { + FREE(addresses[i]); + } + } + + function extractBytes(address, length) { + var result = new Uint8Array(length); + result.set(that.nacl.nacl_raw.HEAPU8.subarray(address, address + length)); + return result; + } + + function Target(length) { + this.length = length; + this.address = MALLOC(length); + } + + Target.prototype.extractBytes = function (offset) { + var result = extractBytes(this.address + (offset || 0), this.length - (offset || 0)); + FREE(this.address); + this.address = null; + return result; + }; + + /*-- + end of WORKAROUND + -- */ + } FullJSServiceFactory.prototype = new CryptoAbstractService(); @@ -753,9 +590,9 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) }; this.util.decode_base58 = function(a) { var i; - a = that.base58.decode(a); - var b = new Uint8Array(a.length); - for (i = 0; i < a.length; i++) b[i] = a[i]; + var d = that.base58.decode(a); + var b = new Uint8Array(d.length); + for (i = 0; i < d.length; i++) b[i] = d[i]; return b; }; this.util.decode_base64 = function (a) { @@ -772,6 +609,26 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) that.crypto.getRandomValues(nonce); return $q.when(nonce); }; + this.util.crypto_hash_sha256 = function (message) { + return that.nacl.from_hex(that.sha256(message)); + }; + + this.util.crypto_scrypt = function(password, salt, N, r, p, seedLength) { + var deferred = $q.defer(); + that.nacl.crypto_pwhash_scryptsalsa208sha256_ll( + password, + salt, + N, + r, + p, + seedLength, + function (err, seed) { + if (err) { deferred.reject(err); return;} + deferred.resolve(seed); + } + ); + return deferred.promise; + }; /** * Create key pairs (sign and box), from salt+password (Scrypt), using cordova @@ -812,6 +669,23 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) return deferred.promise; }; + /** + * Create key pairs from a seed + */ + this.seedKeypair = function(seed) { + var deferred = $q.defer(); + + that.nacl.crypto_sign_seed_keypair(seed, function (err, signKeypair) { + if (err) { deferred.reject(err); return;} + deferred.resolve({ + signPk: signKeypair.pk, + signSk: signKeypair.sk + }); + }); + return deferred.promise; + }; + + /** * Get sign PK from salt+password (Scrypt), using cordova */ @@ -885,7 +759,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) * Compute the box key pair, from a sign key pair */ this.box_keypair_from_sign = function(signKeyPair) { - if (signKeyPair.bokSk && signKeyPair.boxPk) return $q.when(signKeyPair); + if (signKeyPair.boxSk && signKeyPair.boxPk) return $q.when(signKeyPair); var deferred = $q.defer(); var result = {}; that.nacl.crypto_sign_ed25519_pk_to_curve25519(signKeyPair.signPk, function(err, boxPk) { @@ -987,6 +861,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) } else { that.nacl = window.plugins.MiniSodium; + var loadedLib = 0; var checkAllLibLoaded = function() { loadedLib++; @@ -1040,17 +915,17 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) ionicReady().then(function() { console.debug('[crypto] Starting...'); - var now = new Date().getTime(); + var now = Date.now(); var serviceImpl; // Use Cordova plugin implementation, when exists if (isDevice && window.plugins && window.plugins.MiniSodium && crypto && crypto.getRandomValues) { - console.debug('[crypto] Loading Cordova MiniSodium implementation...'); + console.debug('[crypto] Loading \'MiniSodium\' implementation...'); serviceImpl = new CordovaServiceFactory(); } else { - console.debug('[crypto] Loading FullJS implementation...'); + console.debug('[crypto] Loading \'FullJS\' implementation...'); serviceImpl = new FullJSServiceFactory(); } @@ -1062,12 +937,651 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) }) .then(function() { service.copy(serviceImpl); - console.debug('[crypto] Loaded \'{0}\' implementation in {1}ms'.format(service.id, new Date().getTime() - now)); + console.debug('[crypto] Loaded \'{0}\' implementation in {1}ms'.format(service.id, Date.now() - now)); }); }); - return service; }) + + + /* ----------------------------- + Crypto advanced service for Cesium + */ + + .factory('csCrypto', function($q, $rootScope, $timeout, CryptoUtils, UIUtils, Modals) { + 'ngInject'; + + function test(regexpContent) { + return new RegExp(regexpContent); + } + + function xor(a, b) { + var length = Math.max(a.length, b.length); + var buffer = new Uint8Array(length); + for (var i = 0; i < length; ++i) { + buffer[i] = a[i] ^ b[i]; + } + return buffer; + } + + function concat_Uint8Array( buffer1, buffer2 ) { + var tmp = new Uint8Array( buffer1.byteLength + buffer2.byteLength ); + tmp.set( new Uint8Array( buffer1 ), 0 ); + tmp.set( new Uint8Array( buffer2 ), buffer1.byteLength ); + return tmp; + } + + var constants = { + WIF: { + DATA_LENGTH: 35 + }, + EWIF: { + SALT_LENGTH: 4, + DERIVED_HALF_LENGTH: 16, + DATA_LENGTH: 39, + SCRYPT_PARAMS: { + N: 16384, + r: 8, + p: 8 + } + }, + REGEXP: { + PUBKEY: '[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44}', + SECKEY: '[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{86,88}', + FILE: { + TYPE_LINE: '^Type: ([a-zA-Z0-9]+)\n', + VERSION: 'Version: ([0-9]+)\n', + PUB: '[Pp]ub: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{43,44})\n', + SEC: '[Ss]ec: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{86,88})(\n|$)', + DATA: '[Dd]ata: ([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)(\n|$)' + } + } + }, + regexp = { + FILE: { + TYPE_LINE: test(constants.REGEXP.FILE.TYPE_LINE), + VERSION: test(constants.REGEXP.FILE.VERSION), + PUB: test(constants.REGEXP.FILE.PUB), + SEC: test(constants.REGEXP.FILE.SEC), + DATA: test(constants.REGEXP.FILE.DATA) + } + }, + errorCodes = { + BAD_PASSWORD: 3001, + BAD_CHECKSUM: 3002 + }; + + /* -- keyfile -- */ + + function readKeyFile(file, options) { + + if (file && file.content) { + return parseKeyFileContent(file.content, options); + } + + return $q(function(resolve, reject) { + if (!file) { + return reject('Argument [file] is missing'); + } + + //console.debug('[crypto] [keypair] reading file: ', file); + var reader = new FileReader(); + reader.onload = function (event) { + parseKeyFileContent(event.target.result, options) + .then(resolve) + .catch(reject); + }; + reader.readAsText(file, 'utf8'); + }); + } + + function parseKeyFileContent(content, options) { + + if (!content) return $q.reject('Argument [content] is missing'); + + options = options || {}; + options.withSecret = angular.isDefined(options.withSecret) ? options.withSecret : false; + options.defaultType = options.defaultType || 'PubSec'; + + var matches; + + var typeMatch = regexp.FILE.TYPE_LINE.exec(content); + + // If no Type field: add default type + var type = typeMatch && typeMatch[1]; + if (!type && options.defaultType) { + return parseKeyFileContent('Type: {0}\n{1}'.format(options.defaultType, content), options); + } + + // Type: PubSec + if (type == 'PubSec') { + + // Read Pub field + matches = regexp.FILE.PUB.exec(content); + if (!matches) return $q.reject('Missing [pub] field in file, or invalid public key value'); + var signKeypair = { + signPk: CryptoUtils.base58.decode(matches[1]) + }; + if (!options.withSecret) return $q.resolve(signKeypair); + + // Read Sec field + matches= regexp.FILE.SEC.exec(content); + if (!matches) return $q.reject('Missing [sec] field in file, or invalid secret key value'); + signKeypair.signSk = CryptoUtils.base58.decode(matches[1]); + return $q.resolve(signKeypair); + } + + // Type: WIF or EWIF + else if (type == 'WIF' || type == 'EWIF') { + matches = regexp.FILE.DATA.exec(content); + if (!matches) { + return $q.reject('Missing [Data] field in file. This is required for WIF or EWIF format'); + } + + return parseWIF_or_EWIF(matches[1], { + type: type, + password: options.password + }) + .then(function(signKeypair) { + return signKeypair && !options.withSecret ? {signPk: signKeypair.signPk} : signKeypair; + }); + } + + // Type: unknown + if (options.defaultType) { + return $q.reject('Bad file format: missing Type field'); + } + else { + return $q.reject('Bad file format, unknown type [' + type + ']'); + } + } + + + /** + * + * @param data_base58 + * @param options + * @returns {*} + */ + function parseWIF_or_EWIF(data_base58, options) { + options = options || {}; + + var data_int8 = data_base58 && CryptoUtils.base58.decode(data_base58); + if (!data_int8 || data_int8.length != constants.EWIF.DATA_LENGTH && data_int8.length != constants.WIF.DATA_LENGTH) { + return $q.reject('Invalid WIF or EWIF format (invalid bytes count).'); + } + + // Detect the type from the first byte + options.type = options.type || (data_int8[0] == 1 && 'WIF') || (data_int8[0] == 2 && 'EWIF'); + + // Type: WIF + if (options.type == 'WIF') { + return parseWIF_v1(data_base58); + } + + // Type: EWIF + if (options.type == 'EWIF') { + + // If not set, resolve password using the given callback + if (typeof options.password == "function") { + //console.debug("[crypto] [EWIF] Executing 'options.password()' to resolve the password..."); + options.password = options.password(); + if (!options.password) { + return $q.reject({message: "Invalid callback result for 'options.password()': must return a promise or a string."}); + } + } + + // If password is a promise, get the result then read data + if (typeof options.password === "object" && options.password.then) { + return options.password.then(function(password) { + if (!password) throw 'CANCELLED'; + return parseEWIF_v1(data_base58, password); + }); + } + + // If password is a valid string, read data + if (typeof options.password == "string") { + return parseEWIF_v1(data_base58, options.password); + } + + return $q.reject({message: 'Invalid EWIF options.password. Waiting a callback function, a promise or a string.'}); + } + + // Unknown type + return $q.reject({message: 'Invalid WIF or EWIF format: unknown first byte identifier.'}); + } + + + function parseWIF_v1(wif_base58) { + var wif_int8 = CryptoUtils.util.decode_base58(wif_base58); + + // Check identifier byte = 0x01 + if (wif_int8[0] != 1) { + return $q.reject({message: 'Invalid WIF v1 format: expected [0x01] as first byte'}); + } + + // Check length + if (wif_int8.length != constants.WIF.DATA_LENGTH) { + return $q.reject({message: 'Invalid WIF v1 format: Data must be a '+constants.WIF.DATA_LENGTH+' bytes array, encoded in base 58.'}); + } + + var wif_int8_no_checksum = wif_int8.slice(0, -2), + seed = wif_int8.slice(1, -2), + checksum = wif_int8.slice(-2); + + // Compute expected checksum + var expectedChecksum = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(wif_int8_no_checksum)).slice(0,2); + if (CryptoUtils.util.encode_base58(checksum) != CryptoUtils.util.encode_base58(expectedChecksum)) { + $q.reject({message: 'Invalid WIF format: bad checksum'}); + } + + // Generate keypair from seed + return CryptoUtils.seedKeypair(seed); + } + + function parseEWIF_v1(ewif_base58, password) { + var ewif_int8 = CryptoUtils.util.decode_base58(ewif_base58); + + // Check identifier byte = 0x02 + if (ewif_int8[0] != 2) { + return $q.reject({message: 'Invalid EWIF v1 format: Expected [0x02] as first byte'}); + } + + // Check length + if (ewif_int8.length != constants.EWIF.DATA_LENGTH) { + return $q.reject({message: 'Invalid EWIF v1 format: Expected {0} bytes, encoded in base 58.'.format(constants.EWIF.DATA_LENGTH)}); + } + + var ewif_int8_no_checksum = ewif_int8.slice(0,-2); + var checksum = ewif_int8.slice(-2); + var salt = ewif_int8.slice(1,5); + var encryptedhalf1 = ewif_int8.slice(5,21); + var encryptedhalf2 = ewif_int8.slice(21,37); + + // Retrieve the scrypt_seed + return CryptoUtils.util.crypto_scrypt( + CryptoUtils.util.encode_utf8(password), + salt, + constants.EWIF.SCRYPT_PARAMS.N, + constants.EWIF.SCRYPT_PARAMS.r, + constants.EWIF.SCRYPT_PARAMS.p, + 64) + + // Compute the final seed + .then(function(scrypt_seed) { + + var derivedhalf1 = scrypt_seed.slice(0, 32); + var derivedhalf2 = scrypt_seed.slice(32, 64); + + //AES + var aesEcb = new aesjs.ModeOfOperation.ecb(derivedhalf2); + var decryptedhalf1 = aesEcb.decrypt(encryptedhalf1); + var decryptedhalf2 = aesEcb.decrypt(encryptedhalf2); + + decryptedhalf1 = new Uint8Array(decryptedhalf1); + decryptedhalf2 = new Uint8Array(decryptedhalf2); + + //xor + var seed1 = xor(decryptedhalf1, derivedhalf1.slice(0, 16)); + var seed2 = xor(decryptedhalf2, derivedhalf1.slice(16, 32)); + var seed = concat_Uint8Array(seed1, seed2); + + return seed; + }) + + // Get the keypair, from the seed + .then(CryptoUtils.seedKeypair) + + // Do some controls + .then(function(keypair) { + + // Check salt + var expectedSalt = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(keypair.signPk)).slice(0,4); + if(CryptoUtils.util.encode_base58(salt) !== CryptoUtils.util.encode_base58(expectedSalt)) { + throw {ucode: errorCodes.BAD_PASSWORD, message: 'ACCOUNT.SECURITY.KEYFILE.ERROR.BAD_PASSWORD'}; + } + + // Check checksum + var expectedChecksum = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(ewif_int8_no_checksum)).slice(0,2); + if (CryptoUtils.util.encode_base58(checksum) != CryptoUtils.util.encode_base58(expectedChecksum)) { + throw {ucode: errorCodes.BAD_CHECKSUM, message: 'ACCOUNT.SECURITY.KEYFILE.ERROR.BAD_CHECKSUM'}; + } + + return keypair; + }); + } + + + function wif_v1_from_keypair(keypair) { + + var seed = CryptoUtils.seed_from_signSk(keypair.signSk); + if (!seed || seed.byteLength !== CryptoUtils.constants.SEED_LENGTH) + throw "Bad see format. Expected {0} bytes".format(CryptoUtils.constants.SEED_LENGTH); + + var fi = new Uint8Array(1); + fi[0] = 0x01; + var seed_fi = concat_Uint8Array(fi, seed); + + // checksum + var checksum = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(seed_fi)).slice(0,2); + + var wif_int8 = concat_Uint8Array(seed_fi, checksum); + return $q.when(CryptoUtils.util.encode_base58(wif_int8)); + } + + function ewif_v1_from_keypair(keypair, password) { + + var seed = CryptoUtils.seed_from_signSk(keypair.signSk); + if (!seed || seed.byteLength !== CryptoUtils.constants.SEED_LENGTH) + return $q.reject({message: "Bad see format. Expected {0} bytes".format(CryptoUtils.constants.SEED_LENGTH)}); + + // salt + var salt = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(keypair.signPk)).slice(0,4); + + // scrypt_seed + return CryptoUtils.util.crypto_scrypt( + CryptoUtils.util.encode_utf8(password), + salt, + constants.EWIF.SCRYPT_PARAMS.N, + constants.EWIF.SCRYPT_PARAMS.r, + constants.EWIF.SCRYPT_PARAMS.p, + 64) + .then(function(scrypt_seed) { + var derivedhalf1 = scrypt_seed.slice(0,32); + var derivedhalf2 = scrypt_seed.slice(32,64); + + //XOR & AES + var seed1_xor_derivedhalf1_1 = xor(seed.slice(0,16), derivedhalf1.slice(0,16)); + var seed2_xor_derivedhalf1_2 = xor(seed.slice(16,32), derivedhalf1.slice(16,32)); + + var aesEcb = new aesjs.ModeOfOperation.ecb(derivedhalf2); + var encryptedhalf1 = aesEcb.encrypt(seed1_xor_derivedhalf1_1); + var encryptedhalf2 = aesEcb.encrypt(seed2_xor_derivedhalf1_2); + + encryptedhalf1 = new Uint8Array(encryptedhalf1); + encryptedhalf2 = new Uint8Array(encryptedhalf2); + + // concatenate ewif + var ewif_int8 = new Uint8Array(1); + ewif_int8[0] = 0x02; + ewif_int8 = concat_Uint8Array(ewif_int8,salt); + ewif_int8 = concat_Uint8Array(ewif_int8,encryptedhalf1); + ewif_int8 = concat_Uint8Array(ewif_int8,encryptedhalf2); + + var checksum = CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(ewif_int8)).slice(0,2); + ewif_int8 = concat_Uint8Array(ewif_int8,checksum); + + return CryptoUtils.util.encode_base58(ewif_int8); + }); + } + + function generateKeyFileContent(keypair, options) { + options = options || {}; + options.type = options.type || "PubSec"; + + switch(options.type) { + + // PubSec + case "PubSec" : + return $q.resolve( + "Type: PubSec\n" + + "Version: 1\n" + + "pub: " + CryptoUtils.base58.encode(keypair.signPk) + "\n" + + "sec: " + CryptoUtils.base58.encode(keypair.signSk) + "\n"); + + // WIF - v1 + case "WIF" : + return wif_v1_from_keypair(keypair) + .then(function(data) { + return "Type: WIF\n" + + "Version: 1\n" + + "Data: " + data + "\n"; + }); + + // EWIF - v1 + case "EWIF" : + + if (!options.password) return $q.reject({message: 'Missing EWIF options.password.'}); + + // If not set, resolve password using the given callback + if (options.password && typeof options.password == "function") { + console.debug("[crypto] [EWIF] Executing 'options.password()' to resolve the password..."); + options.password = options.password(); + if (!options.password) { + return $q.reject({message: "Invalid callback result for 'options.password()': must return a promise or a string."}); + } + } + + // If password is a promise, get the result then read data + if (options.password && typeof options.password == "object" && options.password.then) { + return options.password.then(function(password) { + if (!password) throw 'CANCELLED'; + // Recursive call, with the string password in options + return generateKeyFileContent(keypair, angular.merge({}, options, {password: password})); + }); + } + + // If password is a valid string, read data + if (options.password && typeof options.password == "string") { + return ewif_v1_from_keypair(keypair, options.password) + .then(function(data) { + return "Type: EWIF\n" + + "Version: 1\n" + + "Data: " + data + "\n"; + }); + } + + return $q.reject({message: 'Invalid EWIF options.password. Waiting a callback function, a promise or a string.'}); + + default: + return $q.reject({message: "Unknown keyfile format: " + options.type}); + } + } + + + + /* -- usefull methods -- */ + + function pkChecksum(pubkey) { + var signPk_int8 = CryptoUtils.util.decode_base58(pubkey); + return CryptoUtils.util.encode_base58(CryptoUtils.util.crypto_hash_sha256(CryptoUtils.util.crypto_hash_sha256(signPk_int8))).substring(0,3); + } + + /* -- box (pack/unpack a record) -- */ + + function getBoxKeypair(keypair) { + if (!keypair) { + throw new Error('Missing keypair'); + } + if (keypair.boxPk && keypair.boxSk) { + return $q.when(keypair); + } + + return $q.all([ + CryptoUtils.box.keypair.skFromSignSk(keypair.signSk), + CryptoUtils.box.keypair.pkFromSignPk(keypair.signPk) + ]) + .then(function(res) { + return { + boxSk: res[0], + boxPk: res[1] + }; + }); + } + + function packRecordFields(record, keypair, recipientFieldName, cypherFieldNames, nonce) { + + recipientFieldName = recipientFieldName || 'recipient'; + if (!record[recipientFieldName]) { + return $q.reject({message:'ES_WALLET.ERROR.RECIPIENT_IS_MANDATORY'}); + } + + cypherFieldNames = cypherFieldNames || 'content'; + if (typeof cypherFieldNames == 'string') { + cypherFieldNames = [cypherFieldNames]; + } + + // Work on a copy, to keep the original record (as it could be use again - fix #382) + record = angular.copy(record); + + // Get recipient + var recipientPk = CryptoUtils.util.decode_base58(record[recipientFieldName]); + + return $q.all([ + getBoxKeypair(keypair), + CryptoUtils.box.keypair.pkFromSignPk(recipientPk), + nonce ? $q.when(nonce) : CryptoUtils.util.random_nonce() + ]) + .then(function(res) { + //var senderSk = res[0]; + var boxKeypair = res[0]; + var senderSk = boxKeypair.boxSk; + var boxRecipientPk = res[1]; + var nonce = res[2]; + + return $q.all( + cypherFieldNames.reduce(function(res, fieldName) { + if (!record[fieldName]) return res; // skip undefined fields + return res.concat( + CryptoUtils.box.pack(record[fieldName], nonce, boxRecipientPk, senderSk) + ); + }, [])) + + .then(function(cypherTexts){ + // Replace field values with cypher texts + var i = 0; + _.forEach(cypherFieldNames, function(cypherFieldName) { + if (!record[cypherFieldName]) { + // Force undefined fields to be present in object + // This is better for ES storage, that always works on lazy update mode + record[cypherFieldName] = null; + } + else { + record[cypherFieldName] = cypherTexts[i++]; + } + }); + + // Set nonce + record.nonce = CryptoUtils.util.encode_base58(nonce); + + return record; + }); + }); + } + + function openRecordFields(records, keypair, issuerFieldName, cypherFieldNames) { + + issuerFieldName = issuerFieldName || 'issuer'; + cypherFieldNames = cypherFieldNames || 'content'; + if (typeof cypherFieldNames == 'string') { + cypherFieldNames = [cypherFieldNames]; + } + + var now = Date.now(); + var issuerBoxPks = {}; // a map used as cache + + var jobs = [getBoxKeypair(keypair)]; + return $q.all(records.reduce(function(jobs, message) { + var issuer = message[issuerFieldName]; + if (!issuer) {throw 'Record has no ' + issuerFieldName;} + if (issuerBoxPks[issuer]) return res; + return jobs.concat( + CryptoUtils.box.keypair.pkFromSignPk(CryptoUtils.util.decode_base58(issuer)) + .then(function(issuerBoxPk) { + issuerBoxPks[issuer] = issuerBoxPk; // fill box pk cache + })); + }, jobs)) + .then(function(res){ + var boxKeypair = res[0]; + return $q.all(records.reduce(function(jobs, record) { + var issuerBoxPk = issuerBoxPks[record[issuerFieldName]]; + var nonce = CryptoUtils.util.decode_base58(record.nonce); + record.valid = true; + + return jobs.concat( + cypherFieldNames.reduce(function(res, cypherFieldName) { + if (!record[cypherFieldName]) return res; + return res.concat(CryptoUtils.box.open(record[cypherFieldName], nonce, issuerBoxPk, boxKeypair.boxSk) + .then(function(text) { + record[cypherFieldName] = text; + }) + .catch(function(err){ + console.error(err); + console.warn('[ES] [crypto] a record may have invalid cypher ' + cypherFieldName); + record.valid = false; + })); + }, [])); + }, [])); + }) + .then(function() { + console.debug('[ES] [crypto] All record decrypted in ' + (Date.now() - now) + 'ms'); + return records; + }); + + } + + function parseKeyFileData(data, options){ + options = options || {}; + options.withSecret = angular.isDefined(options.withSecret) ? options.withSecret : true; + options.silent = angular.isDefined(options.withSecret) ? options.silent : false; + options.password = function() { + return UIUtils.loading.hide(100) + .then(function() { + return Modals.showPassword({ + title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', + subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP', + error: options.error, + scope: options.scope + }); + }) + .then(function(password) { + // Timeout is need to force popup to be hide + return $timeout(function() { + if (password) UIUtils.loading.show(); + return password; + }, 150); + }); + }; + + if (!options.silent) { + UIUtils.loading.show(); + } + + return parseWIF_or_EWIF(data, options) + .then(function(res){ + return res; + }) + .catch(function(err) { + if (err && err === 'CANCELLED') return; + if (err && err.ucode == errorCodes.BAD_PASSWORD) { + // recursive call + return parseKeyFileData(data, {withSecret: options.withSecret, error: 'ACCOUNT.SECURITY.KEYFILE.ERROR.BAD_PASSWORD'}); + } + console.error("[crypto] Unable to parse as WIF or EWIF format: " + (err && err.message || err)); + throw err; // rethrow + }); + } + + // exports + return { + errorCodes: errorCodes, + constants: constants, + // copy CryptoUtils + util: angular.extend({ + pkChecksum: pkChecksum + }, CryptoUtils.util), + keyfile: { + read: readKeyFile, + parseData: parseKeyFileData, + generateContent: generateKeyFileContent + }, + box: { + getKeypair: getBoxKeypair, + pack: packRecordFields, + open: openRecordFields + } + }; + }) ; diff --git a/assets/www/js/services/currency-services.js b/assets/www/js/services/currency-services.js index ad1d994a0cc3b5f0391e5a683b0e4867ffb129ec..1b3888305fd6b32a1b1736953a21d25ecefb5acc 100644 --- a/assets/www/js/services/currency-services.js +++ b/assets/www/js/services/currency-services.js @@ -1,16 +1,22 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) -.factory('csCurrency', function($rootScope, $q, $timeout, BMA, Api) { +.factory('csCurrency', function($rootScope, $q, $timeout, BMA, Api, csSettings) { 'ngInject'; - function factory(id, BMA) { + var defaultBMA = BMA; + + function CsCurrency(id, BMA) { + + BMA = BMA || defaultBMA; + var constants = { // Avoid to many call on well known currencies WELL_KNOWN_CURRENCIES: { g1: { - firstBlockTime: 1488987127 + firstBlockTime: 1488987127, + medianTimeOffset: 3600 } } }, @@ -33,6 +39,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) data.cache = {}; data.node = BMA; data.currentUD = null; + data.medianTimeOffset = 0; started = false; startPromise = undefined; api.data.raise.reset(data); @@ -67,6 +74,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) .then(function(res){ data.name = res.currency; data.parameters = res; + data.medianTimeOffset = res.avgGenTime * res.medianTimeBlocks / 2; return res; }); } @@ -97,25 +105,13 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) function loadCurrentUD() { return BMA.blockchain.stats.ud() - .then(function(res){ + .then(function(res) { // Special case for currency init if (!res.result.blocks.length) { data.currentUD = data.parameters ? data.parameters.ud0 : -1; return data.currentUD ; } - else { - var lastBlockWithUD = res.result.blocks[res.result.blocks.length - 1]; - return BMA.blockchain.block({ block: lastBlockWithUD }) - .then(function(block){ - data.currentUD = powBase(block.dividend, block.unitbase); - return data.currentUD; - }) - .catch(function(err) { - console.error("[currency] Unable to load last block with UD, with number {0}".format(lastBlockWithUD)); - data.currentUD = null; - throw err; - }); - } + return _safeLoadCurrentUD(res, res.result.blocks.length - 1); }) .catch(function(err) { data.currentUD = null; @@ -123,6 +119,38 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) }); } + /** + * Load the last UD, with a workaround if last block with UD is not found in the node + * @param res + * @param blockIndex + * @returns {*} + * @private + */ + function _safeLoadCurrentUD(res, blockIndex) { + // Special case for currency init + if (!res.result.blocks.length || blockIndex < 0) { + data.currentUD = data.parameters ? data.parameters.ud0 : -1; + return data.currentUD ; + } + else { + var lastBlockWithUD = res.result.blocks[blockIndex]; + return BMA.blockchain.block({ block: lastBlockWithUD }) + .then(function(block){ + data.currentUD = powBase(block.dividend, block.unitbase); + return data.currentUD; + }) + .catch(function(err) { + console.error("[currency] Unable to load last block with UD, with number {0}".format(lastBlockWithUD)); + if (blockIndex > 0) { + console.error("[currency] Retrying to load UD from a previous block..."); + return _safeLoadCurrentUD(res, blockIndex-1); + } + data.currentUD = null; + throw err; + }); + } + } + function getData() { if (started) { // load only once @@ -152,10 +180,10 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) block.cleanData(); // Remove unused content (arrays...) and keep items count //console.debug('[currency] Received new block', block); - console.debug('[currency] Received new block [' + block.number + '-' + block.hash + ']'); + console.debug('[currency] Received new block {' + block.number + '-' + block.hash + '}'); data.currentBlock = block; - data.currentBlock.receivedAt = new Date().getTime() / 1000; + data.currentBlock.receivedAt = moment().utc().unix(); data.medianTime = block.medianTime; data.membersCount = block.membersCount; @@ -170,14 +198,11 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) } function addListeners() { - // open web socket on block - var wsBlock = BMA.websocket.block(); - wsBlock.on(onBlock); - listeners = [ // Listen if node changed BMA.api.node.on.restart($rootScope, restart, this), - wsBlock.close + // open web socket on block + BMA.websocket.block().onListener(onBlock) ]; } @@ -206,7 +231,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) function start() { console.debug('[currency] Starting...'); - var now = new Date().getTime(); + var now = Date.now(); startPromise = BMA.ready() @@ -217,7 +242,7 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) .then(function() { addListeners(); - console.debug('[currency] Started in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[currency] Started in ' + (Date.now() - now) + 'ms'); started = true; startPromise = null; @@ -239,22 +264,26 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) return currentBlockField() .then(function(currentBlock) { + + var now = moment().utc().unix(); + if (cache) { - var now = new Date().getTime() / 1000; - if (currentBlock && (currentBlock.receivedAt - now) < 60/*1min*/) { - console.debug('[currency] find current block in cache: use it'); + if (currentBlock && (now - currentBlock.receivedAt) < 60/*1min*/) { + //console.debug('[currency] Use current block #'+ currentBlock.number +' from cache (age='+ (now - currentBlock.receivedAt) + 's)'); return currentBlock; } - // TODO : Should never occured if block event listener works ! - console.warn('[currency] No current block in cache: get it from network'); + if (!currentBlock) { + // Should never occur, if websocket /ws/block works ! + console.warn('[currency] No current block in cache: get it from network. Websocket [/ws/block] may not be started ?'); + } } return BMA.blockchain.current() .catch(function(err){ // Special case for currency init (root block not exists): use fixed values if (err && err.ucode == BMA.errorCodes.NO_CURRENT_BLOCK) { - return {number: 0, hash: BMA.constants.ROOT_BLOCK_HASH, medianTime: Math.trunc(new Date().getTime() / 1000)}; + return {number: 0, hash: BMA.constants.ROOT_BLOCK_HASH, medianTime: moment().utc().unix()}; } throw err; }) @@ -266,6 +295,23 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) }); } + function getLastValidBlock() { + if (csSettings.data.blockValidityWindow <= 0) { + return getCurrent(true); + } + + return getCurrent(true) + .then(function(current) { + var number = current.number - csSettings.data.blockValidityWindow; + return (number > 0) ? BMA.blockchain.block({block: number}) : current; + }); + } + + // Get time in second (UTC - medianTimeOffset) + function getDateNow() { + return moment().utc().unix() - (data.medianTimeOffset || constants.WELL_KNOWN_CURRENCIES.g1.medianTimeOffset); + } + // TODO register new block event, to get new UD value // Register extension points @@ -286,10 +332,16 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) stop: stop, data: data, get: getData, + name: getDataField('name'), parameters: getDataField('parameters'), currentUD: getDataField('currentUD'), + medianTimeOffset: getDataField('medianTimeOffset'), blockchain: { - current: getCurrent + current: getCurrent, + lastValid: getLastValidBlock + }, + date: { + now: getDateNow }, // api extension api: api, @@ -301,7 +353,9 @@ angular.module('cesium.currency.services', ['ngApi', 'cesium.bma.services']) }; } - var service = factory('default', BMA); - service.instance = factory; + var service = new CsCurrency('default'); + service.instance = function(id, bma) { + return new CsCurrency(id, bma); + }; return service; }); diff --git a/assets/www/js/services/desktop-services.js b/assets/www/js/services/desktop-services.js new file mode 100644 index 0000000000000000000000000000000000000000..51a5a760cb5583ee68709e2ab4c1f5c10a36de7c --- /dev/null +++ b/assets/www/js/services/desktop-services.js @@ -0,0 +1,11 @@ +var App, nw; + +angular.module('cesium.desktop.services', ['cesium.device.services', 'cesium.settings.services']) + + .factory('csDesktop', function($rootScope, Device) { + 'ngInject'; + + if (!Device.isDesktop()) return; + + console.info("Starting desktop mode..."); + }); diff --git a/assets/www/js/services/device-services.js b/assets/www/js/services/device-services.js index db928b7e33a30a92d22b5ae03cdcabf015156b4c..cdb1df2078ec8cb56580c78c93c8a78bf4170bf7 100644 --- a/assets/www/js/services/device-services.js +++ b/assets/www/js/services/device-services.js @@ -87,16 +87,17 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti var deferred = $q.defer(); cordova.plugins.barcodeScanner.scan( function(result) { - console.debug('[device] bar code result', result); if (!result.cancelled) { + console.debug('[device] barcode scanner scan: ' + result.text); deferred.resolve(result.text); // make sure to convert into String } else { + console.debug('[device] barcode scanner scan: CANCELLED'); deferred.resolve(); } }, function(err) { - console.error('[device] Error while using barcode scanner -> ' + err); + console.error('[device] Error while using barcode scanner: ' + err); deferred.reject(err); }, n); @@ -166,12 +167,13 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti }, modelScope); }; + settings.animation = settings.animation || 'pop'; settings.action = settings.action || function(number) { setModelValue((getModelValue() ||'') + number); }; if (settings.decimal) { settings.decimalSeparator = settings.decimalSeparator || '.'; - settings.leftButton = settings.leftButton = { + settings.leftButton = { html: '<span>.</span>', action: function () { var text = getModelValue() || ''; @@ -204,11 +206,15 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti return !!navigator.userAgent.match(/iPhone | iPad | iPod/i) || ionic.Platform.isIOS(); }; + exports.isOSX = function() { + return !!navigator.userAgent.match(/Macintosh/i) || ionic.Platform.is("osx"); + }; + exports.isDesktop = function() { if (!angular.isDefined(cache.isDesktop)) { try { // Should have NodeJs and NW - cache.isDesktop = !exports.enable && !!process && !!App; + cache.isDesktop = !exports.enable && !!process && !!nw && !!nw.App; } catch (err) { cache.isDesktop = false; } @@ -235,7 +241,7 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti if (exports.enable){ exports.camera.enable = !!navigator.camera; exports.keyboard.enable = cordova && cordova.plugins && !!cordova.plugins.Keyboard; - exports.barcode.enable = cordova && cordova.plugins && !!cordova.plugins.barcodeScanner; + exports.barcode.enable = cordova && cordova.plugins && !!cordova.plugins.barcodeScanner && !exports.isOSX(); exports.clipboard.enable = cordova && cordova.plugins && !!cordova.plugins.clipboard; if (exports.keyboard.enable) { diff --git a/assets/www/js/services/http-services.js b/assets/www/js/services/http-services.js index 892cf86a4bcffaef557043b843b0a6ba0e168c36..94e57bfc2ef75b81a3063c1dca0002bb3d55c101 100644 --- a/assets/www/js/services/http-services.js +++ b/assets/www/js/services/http-services.js @@ -7,7 +7,7 @@ angular.module('cesium.http.services', ['cesium.cache.services']) var sockets = [], - cachePrefix = 'csHttp' + cachePrefix = 'csHttp-' ; if (!timeout) { @@ -48,14 +48,14 @@ angular.module('cesium.http.services', ['cesium.cache.services']) function prepare(url, params, config, callback) { var pkeys = [], queryParams = {}, newUri = url; - if (typeof params == 'object') { + if (typeof params === 'object') { pkeys = _.keys(params); } _.forEach(pkeys, function(pkey){ var prevURI = newUri; newUri = newUri.replace(':' + pkey, params[pkey]); - if (prevURI == newUri) { + if (prevURI === newUri) { queryParams[pkey] = params[pkey]; } }); @@ -89,7 +89,7 @@ angular.module('cesium.http.services', ['cesium.cache.services']) }; } - function getResourceWithCache(host, port, path, useSsl, maxAge, autoRefresh, forcedTimeout) { + function getResourceWithCache(host, port, path, useSsl, maxAge, autoRefresh, forcedTimeout, cachePrefix) { var url = getUrl(host, port, path, useSsl); maxAge = maxAge || csCache.constants.LONG; //console.debug('[http] will cache ['+url+'] ' + maxAge + 'ms' + (autoRefresh ? ' with auto-refresh' : '')); @@ -101,11 +101,12 @@ angular.module('cesium.http.services', ['cesium.cache.services']) responseType: 'json' }; if (autoRefresh) { // redo the request if need - config.cache = csCache.get(cachePrefix, maxAge, function (key, value) { + config.cache = csCache.get(cachePrefix, maxAge, function (key, value, done) { console.debug('[http] Refreshing cache for ['+key+'] '); $http.get(key, config) .success(function (data) { config.cache.put(key, data); + if (done) done(key, data); }); }); } @@ -164,11 +165,13 @@ angular.module('cesium.http.services', ['cesium.cache.services']) if (self.delegate.readyState == 3) { return $q.reject('Unable to connect to websocket ['+self.delegate.url+']'); } - console.debug('[http] Waiting websocket ['+self.path+'] opening...'); if (self.waitDuration >= timeout) { - console.debug("[http] Will retry openning websocket later..."); - self.waitRetryDelay = 2000; // 2 seconds + self.waitRetryDelay = self.waitRetryDelay && Math.min(self.waitRetryDelay + 2000, 30000) || 2000; // add 2 seconds, until 30s) + console.debug("[http] Will retry websocket [{0}] in {1}s...".format(self.path, Math.round(self.waitRetryDelay/1000))); + } + else if (Math.round(self.waitDuration / 1000) % 10 === 0){ + console.debug('[http] Waiting websocket ['+self.path+']...'); } return $timeout(function(){ @@ -198,9 +201,9 @@ angular.module('cesium.http.services', ['cesium.cache.services']) self.delegate.onopen = function(e) { console.debug('[http] Listening on websocket ['+self.path+']...'); sockets.push(self); - self.delegate.openTime = new Date().getTime(); + self.delegate.openTime = Date.now(); }; - self.delegate.onclose = function() { + self.delegate.onclose = function(closeEvent) { // Remove from sockets arrays var index = _.findIndex(sockets, function(socket){return socket.path === self.path;}); @@ -215,20 +218,52 @@ angular.module('cesium.http.services', ['cesium.cache.services']) // If unexpected close event, reopen the socket (fix #535) else { - console.debug('[http] Unexpected close of websocket ['+path+'] (open '+ (new Date().getTime() - self.delegate.openTime) +'ms ago): re-opening...'); + if (self.delegate.openTime) { + console.debug('[http] Unexpected close of websocket [{0}] (open {1} ms ago): re-opening...', path, (Date.now() - self.delegate.openTime)); - self.delegate = null; + // Force new connection + self.delegate = null; + + // Loop, but without the already registered callback + _open(self, null, params); + } + else if (closeEvent) { + console.debug('[http] TODO -- Unexpected close of websocket [{0}]: error code: '.format(path), closeEvent); - // Loop, but without the already registered callback - _open(self, null, params); + // Force new connection + self.delegate = null; + + // Loop, but without the already registered callback + _open(self, null, params); + } } }; }); } + if (callback) self.callbacks.push(callback); return _waitOpen(self); } + function _close(self) { + if (self.delegate) { + self.delegate.closing = true; + console.debug('[http] Closing websocket ['+self.path+']...'); + self.delegate.close(); + self.callbacks = []; + if (self.onclose) self.onclose(); + } + } + + function _remove(self, callback) { + self.callbacks = _.reject(self.callbacks, function(item) { + return item === callback; + }); + if (!self.callbacks.length) { + _close(self); + } + } + return { open: function(params) { return _open(this, null, params); @@ -236,21 +271,27 @@ angular.module('cesium.http.services', ['cesium.cache.services']) on: function(callback, params) { return _open(this, callback, params); }, + onListener: function(callback, params) { + var self = this; + _open(self, callback, params); + return function() { + _remove(self, callback); + }; + }, send: function(data) { var self = this; return _waitOpen(self) .then(function(){ - self.delegate.send(data); + if (self.delegate) self.delegate.send(data); }); }, close: function() { var self = this; - if (self.delegate) { - self.delegate.closing = true; - console.debug('[http] Closing websocket ['+self.path+']...'); - self.delegate.close(); - self.callbacks = []; - } + _close(self); + }, + isClosed: function() { + var self = this; + return !self.delegate || self.delegate.closing; } }; } @@ -314,7 +355,18 @@ angular.module('cesium.http.services', ['cesium.cache.services']) uri = parts.protocol + uri; } - // Check if device is enable, on spcial tel: or mailto: protocole + // On desktop, open into external tool + if (parts.protocol == 'mailto:' && Device.isDesktop()) { + try { + nw.Shell.openExternal(uri); + return; + } + catch(err) { + console.error("[http] Failed not open 'mailto:' URI into external tool."); + } + } + + // Check if device is enable, on special tel: or mailto: protocole var validProtocol = (parts.protocol == 'mailto:' || parts.protocol == 'tel:') && Device.enable; if (!validProtocol) { if (options.onError && typeof options.onError == 'function') { @@ -326,24 +378,49 @@ angular.module('cesium.http.services', ['cesium.cache.services']) // Note: If device enable, then target=_system will use InAppBrowser cordova plugin var openTarget = (options.target || (Device.enable ? '_system' : '_blank')); - var openOptions; + + // If desktop, try to open into external browser + if (openTarget === '_blank' || openTarget === '_system' && Device.isDesktop()) { + try { + nw.Shell.openExternal(uri); + return; + } + catch(err) { + console.error("[http] Failed not open URI into external browser."); + } + } + // If desktop, should always open in new window (no tabs) - if (openTarget == '_blank' && Device.isDesktop() && $window.screen && $window.screen.width && $window.screen.height) { - openOptions= "width={0},height={1},location=1,menubar=1,toolbar=1,resizable=1,scrollbars=1".format($window.screen.width/2, $window.screen.height/2); + var openOptions; + if (openTarget === '_blank' && Device.isDesktop()) { + + if (nw && nw.Shell) { + nw.Shell.openExternal(uri); + return false; + } + // Override default options + openOptions= "location=1,titlebar=1,status=1,menubar=1,toolbar=1,resizable=1,scrollbars=1"; + // Add width/height + if ($window.screen && $window.screen.width && $window.screen.height) { + openOptions += ",width={0},height={1}".format(Math.trunc($window.screen.width/2), Math.trunc($window.screen.height/2)); + } } + var win = $window.open(uri, openTarget, openOptions); - if (openOptions) { + + // Center the opened window + if (openOptions && $window.screen && $window.screen.width && $window.screen.height) { win.moveTo($window.screen.width/2/2, $window.screen.height/2/2); win.focus(); } } - // Get time (UTC) + // Get time in second (UTC) function getDateNow() { - return Math.floor(moment().utc().valueOf() / 1000); + return moment().utc().unix(); } function isPositiveInteger(x) { @@ -408,8 +485,7 @@ angular.module('cesium.http.services', ['cesium.cache.services']) } function isVersionCompatible(minVersion, actualVersion) { - // TODO: add implementation - console.debug('[http] TODO: implement check version [{0}] compatible with [{1}]'.format(actualVersion, minVersion)); + console.debug('[http] Checking actual version [{0}] is compatible with min expected version [{1}]'.format(actualVersion, minVersion)); return compareVersionNumbers(minVersion, actualVersion) <= 0; } diff --git a/assets/www/js/services/modal-services.js b/assets/www/js/services/modal-services.js index e6aff2dafde9f21293dd6bf2b263235e34792c3f..fd024fff98d7910057a61dcd06102da8b91c7039 100644 --- a/assets/www/js/services/modal-services.js +++ b/assets/www/js/services/modal-services.js @@ -1,4 +1,4 @@ -angular.module('cesium.modal.services', []) +angular.module('cesium.modal.services', ['cesium.utils.services']) // Useful for modal with no controller .controller('EmptyModalCtrl', function () { @@ -21,7 +21,7 @@ angular.module('cesium.modal.services', []) }; }) -.factory('ModalUtils', function($ionicModal, $rootScope, $q, $injector, $controller, $timeout) { +.factory('ModalUtils', function($ionicModal, $rootScope, $q, $injector, $controller, $timeout, Device) { 'ngInject'; @@ -58,8 +58,15 @@ angular.module('cesium.modal.services', []) $scope.closeModal = function (result) { $scope.resolved = true; + + // removeIf(no-device) + if (Device.enable) Device.keyboard.close(); + // endRemoveIf(no-device) + return $scope.modal.remove() .then(function() { + // Workaround modal-open not removed + document.body.classList.remove('modal-open'); $scope.deferred.resolve(result); return result; }); @@ -89,7 +96,10 @@ angular.module('cesium.modal.services', []) $timeout(function() { $scope.deferred.resolve(); - return $scope.modal.remove(); + return $scope.modal.remove().then(function() { + // Workaround modal-open not removed + document.body.classList.remove('modal-open'); + }); }, ($scope.modal.hideDelay || 320) + 20); } }); @@ -101,6 +111,12 @@ angular.module('cesium.modal.services', []) options = options ? options : {} ; options.animation = options.animation || 'slide-in-up'; + var focusFirstInput = false; + // removeIf(device) + focusFirstInput = angular.isDefined(options.focusFirstInput) ? options.focusFirstInput : false; + // endRemoveIf(device) + options.focusFirstInput = focusFirstInput; + // If modal has a controller if (controller) { // If a controller defined, always use a new scope @@ -146,7 +162,7 @@ angular.module('cesium.modal.services', []) }; }) -.factory('Modals', function($rootScope, $translate, $ionicPopup, ModalUtils, UIUtils) { +.factory('Modals', function($rootScope, $translate, $ionicPopup, $timeout, ModalUtils, UIUtils) { 'ngInject'; function showTransfer(parameters) { @@ -159,15 +175,9 @@ angular.module('cesium.modal.services', []) function showLogin(parameters) { return ModalUtils.show('templates/login/modal_login.html','LoginModalCtrl', - parameters, {focusFirstInput: true}); - } - - function showAdvancedLogin(parameters) { - return ModalUtils.show('templates/login/modal_advanced_login.html','LoginModalCtrl', - parameters, {focusFirstInput: true}); + parameters, {focusFirstInput: true, backdropClickToClose: false}); } - function showWotLookup(parameters) { return ModalUtils.show('templates/wot/modal_lookup.html','WotLookupModalCtrl', parameters || {}, {focusFirstInput: true}); @@ -224,6 +234,11 @@ angular.module('cesium.modal.services', []) parameters); } + function showSelectWallet(parameters) { + return ModalUtils.show('templates/wallet/list/modal_wallets.html','WalletSelectModalCtrl', + parameters); + } + function showPassword(options) { options = options || {}; options.title = options.title || 'COMMON.SET_PASSWORD_TITLE'; @@ -235,14 +250,14 @@ angular.module('cesium.modal.services', []) }; scope.submit = function(e) { scope.form.$submitted=true; - if(!scope.form.$valid || !scope.formData.password) { - //don't allow the user to close unless he enters a uid - if (e && e.preventDefault) e.preventDefault(); - } else { + if (e && e.preventDefault) e.preventDefault(); + if(scope.form.$valid && scope.formData.password) { options.popup.close(scope.formData.password); } }; + scope.error = options.error || undefined; + // Choose password popup return $translate([options.title, options.subTitle, 'COMMON.BTN_OK', 'COMMON.BTN_CANCEL']) .then(function (translations) { @@ -264,11 +279,9 @@ angular.module('cesium.modal.services', []) } - return { showTransfer: showTransfer, showLogin: showLogin, - showAdvancedLogin: showAdvancedLogin, showWotLookup: showWotLookup, showNetworkLookup: showNetworkLookup, showAbout: showAbout, @@ -279,7 +292,51 @@ angular.module('cesium.modal.services', []) showAccountSecurity: showAccountSecurity, showLicense: showLicense, showSelectPubkeyIdentity: showSelectPubkeyIdentity, + showSelectWallet: showSelectWallet, showPassword: showPassword }; -}); +}) + +.factory('csPopovers', function($rootScope, $translate, $ionicPopup, $timeout, UIUtils, $controller) { + 'ngInject'; + + function showSelectWallet(event, options) { + options = options || {}; + + var parameters = options.parameters || {}; + delete options.parameters; + + var scope = options.scope && options.scope.$new() || $rootScope.$new(true); + options.scope = scope; + options.templateUrl = 'templates/wallet/list/popover_wallets.html'; + options.autoremove = true; + + // Initialize the popover controller, with parameters + angular.extend(this, $controller('WalletSelectPopoverCtrl', {$scope: options.scope, parameters: parameters})); + + var afterShowSaved = options.afterShow; + options.afterShow = function(popover) { + + // Add a missing method, to close the popover + scope.closePopover = function(res) { + popover.scope.closePopover(res); + }; + + // Execute default afterShow fn, if any + if (afterShowSaved) afterShowSaved(popover); + }; + // Show the popover + return UIUtils.popover.show(event, options) + .then(function(res) { + // Then destroy the scope + scope.$destroy(); + return res; + }); + } + + return { + showSelectWallet: showSelectWallet + }; + + }); diff --git a/assets/www/js/services/network-services.js b/assets/www/js/services/network-services.js index 726cb2337399bf32b0008a6d564c0a11f7df749d..dbf0b26c991cb7b5773e61c642af6986edaf4dd9 100644 --- a/assets/www/js/services/network-services.js +++ b/assets/www/js/services/network-services.js @@ -1,39 +1,44 @@ -angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesium.http.services']) +angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services', 'cesium.http.services']) -.factory('csNetwork', function($rootScope, $q, $interval, $timeout, $window, csConfig, BMA, csHttp, Api) { +.factory('csNetwork', function($rootScope, $q, $interval, $timeout, $window, csConfig, BMA, csHttp, csCurrency, Api) { 'ngInject'; - factory = function(id) { + function CsNetwork(id) { var interval, constants = { - UNKNOWN_BUID: -1 + UNKNOWN_BUID: -1, + MAX_BLOCK_OFFSET: 1000 }, isHttpsMode = $window.location.protocol === 'https:', api = new Api(this, "csNetwork-" + id), data = { bma: null, - websockets: [], + listeners: [], loading: true, peers: [], filter: { member: true, mirror: true, - endpointFilter: null, + endpoint: null, online: false, + bma: false, ssl: undefined, tor: undefined }, sort:{ type: null, - asc: true + asc: true, + compact: true }, + groupBy: 'pubkey', expertMode: false, knownBlocks: [], mainBlock: null, + minOnlineBlockNumber: 0, uidsByPubkeys: null, searchingPeersOnNetwork: false, difficulties: null, @@ -48,22 +53,27 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi resetData = function() { data.bma = null; - data.websockets = []; + data.listeners = []; data.peers.splice(0); data.filter = { member: true, mirror: true, - endpointFilter: null, - online: true + endpoint: null, + online: true, + bma: false, + ssl: undefined, + tor: undefined }; data.sort = { type: null, asc: true }; + data.groupBy = 'pubkey'; data.expertMode = false; data.memberPeersCount = 0; data.knownBlocks = []; data.mainBlock = null; + data.minOnlineBlockNumber = 0; data.uidsByPubkeys = {}; data.loading = true; data.searchingPeersOnNetwork = false; @@ -172,8 +182,8 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi data.uidsByPubkeys = uids; }) .catch(function(err) { + console.error(err); data.uidsByPubkeys = {}; - //throw err; }), // Load WS2P heads @@ -186,99 +196,96 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi } return $q.all(initJobs) - .then(function(){ - // online nodes + .then(function() { + return data.bma.network.peers(); + }) + .then(function(res){ + if (!res || !res.peers || !res.peers.length) return; + + // If filter online peers if (data.filter.online) { - /*return data.bma.network.peering.peers({leaves: true}) - .then(function(res){ - return $q.all(res.leaves.map(function(leaf) { - return data.bma.network.peering.peers({ leaf: leaf }) - .then(function(subres){ - return addOrRefreshPeerFromJson(subres.leaf.value, newPeers); - }); - })); - });*/ - return data.bma.network.peers() - .then(function(res){ - var jobs = []; - _.forEach(res.peers, function(json) { - if (json.status == 'UP') { - jobs.push(addOrRefreshPeerFromJson(json, newPeers)); - - // Mark WS2P - _.forEach(json.endpoints||[], function(ep) { - if (ep.startsWith('WS2P')) { - var key = json.pubkey + '-' + ep.split(' ')[1]; - if (data.ws2pHeads[key]) { - data.ws2pHeads[key].hasEndpoint = true; - } - } - }); - } - }); - - // Add private WS2P endpoints - var privateWs2pHeads = _.values(data.ws2pHeads); - if (privateWs2pHeads && privateWs2pHeads.length) { - var privateEPCount = 0; - //console.debug("[http] Found WS2P endpoints without endpoint:", data.ws2pHeads); - _.forEach(privateWs2pHeads, function(head) { - if (!head.hasEndPoint) { - var peer = new Peer({ - buid: head.buid, - currentNumber: head.buid && head.buid.split('-')[0], - pubkey: head.pubkey, - version: head.version, - powPrefix: head.powPrefix, - online: true, - uid: data.uidsByPubkeys[head.pubkey], - bma: { - useWs2p: true, - private: true, - ws2pid: head.ws2pid - }, - endpoints: [ - // fake endpoint - 'WS2P ' + head.ws2pid - ] - }); - peer.id = peer.keyID(); - if (peer.uid && data.expertMode && data.difficulties) { - peer.difficulty = data.difficulties[peer.uid]; - } - if (applyPeerFilter(peer)) { - newPeers.push(peer); - privateEPCount++; - } - } - }); + var jobs = []; + _.forEach(res.peers, function(json) { + // Exclude, if not UP or on a too old block + if (json.status !== 'UP') return; + json.blockNumber = json.block && parseInt(json.block.split('-')[0]); + if (json.blockNumber && json.blockNumber < data.minOnlineBlockNumber) { + console.debug("[network] Exclude a too old peer document, on pubkey {0}".format(json.pubkey.substring(0,6))); + return; + } + + jobs.push(addOrRefreshPeerFromJson(json, newPeers)); - if (privateEPCount) { - console.debug("[http] Found {0} WS2P endpoints without endpoint (private ?)".format(privateEPCount)); + // Mark WS2P + _.forEach(json.endpoints||[], function(ep) { + if (ep.startsWith('WS2P')) { + var key = json.pubkey + '-' + ep.split(' ')[1]; + if (data.ws2pHeads[key]) { + data.ws2pHeads[key].hasEndpoint = true; } } - - if (jobs.length) return $q.all(jobs); - }) - .catch(function(err) { - // Log and continue - console.error(err); }); - } + }); - // offline nodes - return data.bma.network.peers() - .then(function(res){ - var jobs = []; - _.forEach(res.peers, function(json) { - if (json.status !== 'UP') { - jobs.push(addOrRefreshPeerFromJson(json, newPeers)); + // Add private WS2P endpoints + var privateWs2pHeads = _.values(data.ws2pHeads); + if (privateWs2pHeads && privateWs2pHeads.length) { + var privateEPCount = 0; + //console.debug("[http] Found WS2P endpoints without endpoint:", data.ws2pHeads); + _.forEach(privateWs2pHeads, function(head) { + + if (!head.hasEndPoint) { + var currentNumber = head.buid && parseInt(head.buid.split('-')[0]); + // Exclude if on a too old block + if (currentNumber && currentNumber < data.minOnlineBlockNumber) { + console.debug("[network] Exclude a too old WS2P message, on pubkey {0}".format(head.pubkey.substring(0,6))); + return; + } + + var peer = new Peer({ + buid: head.buid, + currentNumber: currentNumber, + pubkey: head.pubkey, + version: head.version, + powPrefix: head.powPrefix, + online: true, + uid: data.uidsByPubkeys[head.pubkey], + bma: { + useWs2p: true, + private: true, + ws2pid: head.ws2pid + }, + endpoints: [ + // fake endpoint + 'WS2P ' + head.ws2pid + ] + }); + peer.id = peer.keyID(); + if (peer.uid && data.expertMode && data.difficulties) { + peer.difficulty = data.difficulties[peer.uid]; + } + if (applyPeerFilter(peer)) { + newPeers.push(peer); + privateEPCount++; + } } }); - if (jobs.length) return $q.all(jobs); - }); - }) + if (privateEPCount) { + console.debug("[http] Found {0} WS2P endpoints without endpoint (private ?)".format(privateEPCount)); + } + } + + if (jobs.length) return $q.all(jobs); + } + + // If filter offline peers + else { + return $q.all(_(res && res.peers || []).reduce(function(res, json) { + return res.concat(addOrRefreshPeerFromJson(json, newPeers)); + }, [])); + } + }) .then(function(){ data.searchingPeersOnNetwork = false; }) @@ -301,13 +308,23 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi return false; } - // Filter on endpoints - if (data.filter.endpointFilter && !peer.hasEndpoint(data.filter.endpointFilter)) { + // Filter on endpoint + if (data.filter.endpoint && !peer.hasEndpoint(data.filter.endpoint)) { return false; } // Filter on status - if (!data.filter.online && peer.status == 'UP') { + if ((data.filter.online && peer.status !== 'UP' && peer.oldBlock) || (!data.filter.online && peer.status === 'UP' && !peer.oldBlock)) { + return false; + } + + // Filter on bma + if (angular.isDefined(data.filter.bma) && peer.isBma() != data.filter.bma) { + return false; + } + + // Filter on ws2p + if (angular.isDefined(data.filter.ws2p) && peer.isWs2p() != data.filter.ws2p) { return false; } @@ -327,6 +344,10 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi addOrRefreshPeerFromJson = function(json, list) { list = list || data.newPeers; + // Analyze the peer document, and exclude using the online filter + json.blockNumber = json.block && parseInt(json.block.split('-')[0]); + json.oldBlock = (json.status === 'UP' && json.blockNumber && json.blockNumber < data.minOnlineBlockNumber); + var peers = createPeerEntities(json); var hasUpdates = false; @@ -347,26 +368,26 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi } else if (refreshedPeer.buid !== existingMainBuid){ console.debug('[network] {0} endpoint [{1}] new current block'.format( - refreshedPeer.bma.useBma ? 'BMA' : 'WS2P', + refreshedPeer.bma && (refreshedPeer.bma.useBma ? 'BMA' : 'WS2P') || 'null', refreshedPeer.server)); hasUpdates = true; } else if (existingOnline !== refreshedPeer.online){ console.debug('[network] {0} endpoint [{1}] is now {2}'.format( - refreshedPeer.bma.useBma ? 'BMA' : 'WS2P', + refreshedPeer.bma && (refreshedPeer.bma.useBma ? 'BMA' : 'WS2P') || 'null', refreshedPeer.server, refreshedPeer.online ? 'UP' : 'DOWN')); hasUpdates = true; } else { console.debug("[network] {0} endpoint [{1}] unchanged".format( - refreshedPeer.bma.useBma ? 'BMA' : 'WS2P', + refreshedPeer.bma && (refreshedPeer.bma.useBma ? 'BMA' : 'WS2P') || 'null', refreshedPeer.server)); } } else if (refreshedPeer && (refreshedPeer.online === data.filter.online || data.filter.online === 'all')) { console.debug("[network] {0} endpoint [{1}] is {2}".format( - refreshedPeer.bma.useBma ? 'BMA' : 'WS2P', + refreshedPeer.bma && (refreshedPeer.bma.useBma ? 'BMA' : 'WS2P') || 'null', refreshedPeer.server, refreshedPeer.online ? 'UP' : 'DOWN' )); @@ -402,15 +423,17 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi return res.concat(createPeerEntities(json, ep)); }, []); } - - // if only one bma endpoint: use it and continue - ep = endpoints[0]; + else { + // if only one endpoint: use it and continue + ep = endpoints[0]; + } } peer.bma = ep; peer.server = peer.getServer(); peer.dns = peer.getDns(); - peer.blockNumber = peer.block.replace(/-.+$/, ''); - peer.uid = data.uidsByPubkeys[peer.pubkey]; + peer.buid = peer.buid || peer.block; + peer.blockNumber = peer.buid && parseInt(peer.buid.split('-')[0]); + peer.uid = peer.pubkey && data.uidsByPubkeys[peer.pubkey]; peer.id = peer.keyID(); return [peer]; }, @@ -420,7 +443,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi // Apply filter if (!applyPeerFilter(peer)) return $q.when(); - if (!data.filter.online || (data.filter.online === 'all' && peer.status === 'DOWN') || !peer.getHost() /*fix #537*/) { + if (!data.filter.online || (!data.filter.online && peer.status === 'DOWN') || !peer.getHost() /*fix #537*/) { peer.online = false; return $q.when(peer); } @@ -431,7 +454,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi delete data.ws2pHeads[ws2pHeadKey]; if (head) { peer.buid = head.buid; - peer.currentNumber=peer.buid && peer.buid.split('-')[0]; + peer.currentNumber=head.buid && parseInt(head.buid.split('-')[0]); peer.version = head.version; peer.powPrefix = head.powPrefix; } @@ -459,7 +482,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi // Do not try to access TOR or WS2P endpoints if (peer.bma.useTor || peer.bma.useWs2p) { - peer.online = (peer.status == 'UP'); + peer.online = (peer.status === 'UP'); peer.buid = constants.UNKNOWN_BUID; delete peer.version; @@ -493,7 +516,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi } if (!peer.secondTry) { var bma = peer.bma || peer.getBMA(); - if (bma.dns && peer.server.indexOf(bma.dns) == -1) { + if (bma.dns && peer.server.indexOf(bma.dns) === -1) { // try again, using DNS instead of IPv4 / IPV6 peer.secondTry = true; peer.api = BMA.lightInstance(bma.dns, bma.port, bma.useSsl); @@ -501,9 +524,10 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi } } - peer.online=false; - peer.currentNumber = null; peer.buid = null; + peer.blockNumber = null; + peer.currentNumber = null; + peer.online=false; peer.uid = data.uidsByPubkeys[peer.pubkey]; return peer; }) @@ -526,9 +550,11 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi // Get Version jobs.push(peer.api.node.summary() .then(function(res){ - peer.version = res && res.duniter && res.duniter.version; + peer.software = res && res.duniter && res.duniter.software || undefined; + peer.version = res && res.duniter && res.duniter.version || '?'; }) .catch(function() { + peer.software = undefined; peer.version = '?'; // continue })); @@ -585,8 +611,8 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi if (!buid || !buid.medianTime) { buid = { buid: peer.buid, - count: 0, - medianTime: peer.medianTime + medianTime: peer.medianTime, + count: 0 }; buids[peer.buid] = buid; } @@ -594,42 +620,44 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi else if (!buid.medianTime && peer.medianTime) { buid.medianTime = peer.medianTime; } - if (buid.buid != constants.UNKNOWN_BUID) { + if (buid.buid !== constants.UNKNOWN_BUID) { buid.count++; } } data.memberPeersCount += peer.uid ? 1 : 0; }); - // Compute pct of use, per buid - _.forEach(_.values(buids), function(buid) { - buid.pct = buid.count * 100 / data.peers.length; - }); - var mainBlock = _.max(buids, function(obj) { - return obj.count; - }); - _.forEach(data.peers, function(peer){ - peer.hasMainConsensusBlock = peer.buid == mainBlock.buid; - peer.hasConsensusBlock = peer.buid && !peer.hasMainConsensusBlock && buids[peer.buid].count > 1; - if (peer.hasConsensusBlock) { - peer.consensusBlockDelta = buids[peer.buid].medianTime - mainBlock.medianTime; - } - }); + var mainBlock = data.mainBlock; + if (data.filter.online) { + // Compute pct of use, per buid + _.forEach(_.values(buids), function(buid) { + buid.pct = buid.count * 100 / data.peers.length; + }); + mainBlock = _.max(buids, function(obj) { + return obj.count; + }); + _.forEach(data.peers, function(peer){ + peer.hasMainConsensusBlock = peer.buid === mainBlock.buid; + peer.hasConsensusBlock = peer.buid && !peer.hasMainConsensusBlock && buids[peer.buid].count > 1; + if (peer.hasConsensusBlock) { + peer.consensusBlockDelta = buids[peer.buid].medianTime - mainBlock.medianTime; + } + }); + } data.peers = _.uniq(data.peers, false, function(peer) { return peer.id; }); data.peers = _.sortBy(data.peers, function(peer) { var score = 0; if (data.sort.type) { - var sortScore = 0; - sortScore += (data.sort.type == 'uid' ? computeScoreAlphaValue(peer.uid||peer.pubkey, 3, data.sort.asc) : 0); - sortScore += (data.sort.type == 'api') && + score += (data.sort.type === 'uid' ? computeScoreAlphaValue(peer.uid||peer.pubkey, 3, data.sort.asc) : 0); + score += (data.sort.type === 'api') && ((peer.isWs2p() && (data.sort.asc ? 1 : -1) || 0) + (peer.hasEndpoint('ES_USER_API') && (data.sort.asc ? 0.01 : -0.01) || 0) + (peer.isSsl() && (data.sort.asc ? 0.75 : -0.75) || 0)) || 0; - sortScore += (data.sort.type == 'difficulty' ? (peer.difficulty ? (data.sort.asc ? (10000-peer.difficulty) : peer.difficulty): 0) : 0); - sortScore += (data.sort.type == 'current_block' ? (peer.currentNumber ? (data.sort.asc ? (1000000000 - peer.currentNumber) : peer.currentNumber) : 0) : 0); - score += (10000000000 * sortScore); + score += (data.sort.type === 'difficulty' ? (peer.difficulty ? (data.sort.asc ? (10000-peer.difficulty) : peer.difficulty): 0) : 0); + score += (data.sort.type === 'current_block' ? (peer.currentNumber ? (data.sort.asc ? (1000000000 - peer.currentNumber) : peer.currentNumber) : 0) : 0); } + score = (10000000000 * score); score += (1000000000 * (peer.online ? 1 : 0)); score += (100000000 * (peer.hasMainConsensusBlock ? 1 : 0)); score += (1000000 * (peer.hasConsensusBlock ? buids[peer.buid].pct : 0)); @@ -641,9 +669,18 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi score += (100 * (peer.uid ? computeScoreAlphaValue(peer.uid, 2, true) : 0)); score += (1 * (!peer.uid ? computeScoreAlphaValue(peer.pubkey, 2, true) : 0)); } + score += (peer.isBma() ? (peer.isSsl() ? 0.01 : 0.001) :0); // If many endpoints: BMAS first, then BMA return -score; }); + if (data.groupBy) { + var previousPeer; + data.peers.forEach(function(peer) { + peer.compacted = (previousPeer && peer[data.groupBy] && peer[data.groupBy] === previousPeer[data.groupBy]); + previousPeer = peer; + }); + } + // Raise event on new main block if (updateMainBuid && mainBlock.buid && (!data.mainBlock || data.mainBlock.buid !== mainBlock.buid)) { data.mainBlock = mainBlock; @@ -654,46 +691,53 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi api.data.raise.changed(data); // raise event }, - startListeningOnSocket = function() { - // Listen for new block - var wsBlock = data.bma.websocket.block(); - data.websockets.push(wsBlock); - wsBlock.on(function(block) { - if (!block || data.loading) return; - var buid = [block.number, block.hash].join('-'); - if (data.knownBlocks.indexOf(buid) === -1) { - console.debug('[network] Receiving block: ' + buid.substring(0, 20)); - data.knownBlocks.push(buid); - // If first block: do NOT refresh peers (will be done in start() method) - var skipRefreshPeers = data.knownBlocks.length === 1; - if (!skipRefreshPeers) { - data.loading = true; - // We wait 2s when a new block is received, just to wait for network propagation - $timeout(function() { - console.debug('[network] new block received by WS: will refresh peers'); - loadPeers(); - }, 2000, false /*invokeApply*/); - } - } + removeListeners = function() { + _.forEach(data.listeners, function(remove){ + remove(); }); - // Listen for new peer - var wsPeer = data.bma.websocket.peer(); - data.websockets.push(wsPeer); - wsPeer.on(function(json) { - if (!json || data.loading) return; - var newPeers = []; - addOrRefreshPeerFromJson(json, newPeers) - .then(function(hasUpdates) { - if (!hasUpdates) return; - if (newPeers.length>0) { - flushNewPeersAndSort(newPeers, true); - } - else { - console.debug('[network] [ws] Peers updated received'); - sortPeers(true); + data.listeners = []; + }, + + addListeners = function() { + data.listeners = [ + + // Listen for new block + data.bma.websocket.block().onListener(function(block) { + if (!block || data.loading) return; + var buid = [block.number, block.hash].join('-'); + if (data.knownBlocks.indexOf(buid) === -1) { + console.debug('[network] Receiving block: ' + buid.substring(0, 20)); + data.knownBlocks.push(buid); + // If first block: do NOT refresh peers (will be done in start() method) + var skipRefreshPeers = data.knownBlocks.length === 1; + if (!skipRefreshPeers) { + data.loading = true; + // We wait 2s when a new block is received, just to wait for network propagation + $timeout(function() { + console.debug('[network] new block received by WS: will refresh peers'); + loadPeers(); + }, 2000, false /*invokeApply*/); } - }); - }); + } + }), + + // Listen for new peer + data.bma.websocket.peer().onListener(function(json) { + if (!json || data.loading) return; + var newPeers = []; + addOrRefreshPeerFromJson(json, newPeers) + .then(function(hasUpdates) { + if (!hasUpdates) return; + if (newPeers.length>0) { + flushNewPeersAndSort(newPeers, true); + } + else { + console.debug('[network] [ws] Peers updated received'); + sortPeers(true); + } + }); + }) + ]; }, sort = function(options) { @@ -708,19 +752,31 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi return BMA.ready() .then(function() { close(); + data.bma = bma ? bma : BMA; data.filter = options.filter ? angular.merge(data.filter, options.filter) : data.filter; data.sort = options.sort ? angular.merge(data.sort, options.sort) : data.sort; data.expertMode = angular.isDefined(options.expertMode) ? options.expertMode : data.expertMode; data.timeout = angular.isDefined(options.timeout) ? options.timeout : csConfig.timeout; + + // Init a min block number + data.minOnlineBlockNumber = data.mainBlock && data.mainBlock.buid && (parseInt(data.mainBlock.buid.split('-')[0]) - constants.MAX_BLOCK_OFFSET) || undefined; + if (data.minOnlineBlockNumber === undefined) { + return csCurrency.blockchain.current(true/*use cache*/) + .then(function(current) { + data.minOnlineBlockNumber = current.number - constants.MAX_BLOCK_OFFSET; + }); + } + }) + .then(function() { console.info('[network] Starting network from [{0}]'.format(bma.server)); - var now = new Date(); + var now = Date.now(); - startListeningOnSocket(); + addListeners(); return loadPeers() .then(function(peers){ - console.debug('[network] Started in '+(new Date().getTime() - now.getTime())+'ms'); + console.debug('[network] Started in '+(Date.now() - now)+'ms'); return peers; }); }); @@ -728,11 +784,8 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi close = function() { if (data.bma) { - console.info('[network] Stopping'); - - _.forEach(data.websockets, function(ws){ - ws.close(); - }); + console.info('[network-service] Stopping...'); + removeListeners(); resetData(); } }, @@ -790,10 +843,13 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi // api extension api: api }; - }; + } - var service = factory('default'); + var service = new CsNetwork('default'); + + service.instance = function(id) { + return new CsNetwork(id); + }; - service.instance = factory; return service; }); diff --git a/assets/www/js/services/settings-services.js b/assets/www/js/services/settings-services.js index fa0c35413e9215d24697d5fc01ab12db07db779d..6ac96e2e07b87f77af1f20544f489b389d96de89 100644 --- a/assets/www/js/services/settings-services.js +++ b/assets/www/js/services/settings-services.js @@ -6,11 +6,13 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) // Define app locales var locales = [ - {id:'en', label:'English'}, - {id:'en-GB', label:'English (UK)'}, - {id:'fr-FR', label:'Français'}, - {id:'nl-NL', label:'Nederlands'}, - {id:'es-ES', label:'Spanish'} + {id:'en', label:'English', country: 'us'}, + {id:'en-GB', label:'English (UK)', country: 'gb'}, + {id:'eo-EO', label:'Esperanto'}, + {id:'fr-FR', label:'Français' , country: 'fr'}, + {id:'nl-NL', label:'Nederlands', country: 'nl'}, + {id:'es-ES', label:'Spanish', country: 'es'}, + {id:'it-IT', label:'Italiano', country: 'it'} ]; var fallbackLocale = csConfig.fallbackLanguage ? fixLocale(csConfig.fallbackLanguage) : 'en'; @@ -21,7 +23,7 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) // exists in app locales: use it if (_.findWhere(locales, {id: locale})) return locale; - // not exists: reiterate with the root(e.g. 'fr-XX' -> 'fr') + // not exists: reiterate with the root (e.g. 'fr-XX' -> 'fr') var localeParts = locale.split('-'); if (localeParts.length > 1) { return fixLocale(localeParts[0]); @@ -47,30 +49,36 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) var constants = { - STORAGE_KEY: 'CESIUM_SETTINGS', + STORAGE_KEY: 'settings', // for version >= v1.1.0 KEEP_AUTH_IDLE_SESSION: 9999 }, - defaultSettings = angular.merge({ + // Settings that user cannot change himself (only config can override this values) + fixedSettings = { timeout : 4000, cacheTimeMs: 60000, /*1 min*/ - useRelative: false, timeWarningExpireMembership: 2592000 * 2 /*=2 mois*/, timeWarningExpire: 2592000 * 3 /*=3 mois*/, + minVersion: '1.1.0', + newIssueUrl: "https://git.duniter.org/clients/cesium-grp/cesium/issues/new", + userForumUrl: "https://forum.monnaie-libre.fr", + latestReleaseUrl: "https://api.github.com/repos/duniter/cesium/releases/latest", + duniterLatestReleaseUrl: "https://api.github.com/repos/duniter/duniter/releases/latest", + httpsMode: false + }, + defaultSettings = angular.merge({ + useRelative: false, useLocalStorage: true, // override to false if no device + useLocalStorageEncryption: false, walletHistoryTimeSecond: 30 * 24 * 60 * 60 /*30 days*/, walletHistorySliceSecond: 5 * 24 * 60 * 60 /*download using 5 days slice*/, + walletHistoryAutoRefresh: true, // override to false if device rememberMe: true, - keepAuthIdle: 10 * 60, // 10min - override to false if no device + keepAuthIdle: 10 * 60, showUDHistory: true, - httpsMode: false, expertMode: false, decimalCount: 4, uiEffects: true, - minVersion: '1.1.0', - newIssueUrl: "https://git.duniter.org/clients/cesium/cesium/issues/new", - userForumUrl: "https://forum.monnaie-libre.fr", - latestReleaseUrl: "https://api.github.com/repos/duniter/cesium/releases/latest", - duniterLatestReleaseUrl: "https://api.github.com/repos/duniter/duniter/releases/latest", + blockValidityWindow: 6, helptip: { enable: true, installDocUrl: "https://duniter.org/en/wiki/duniter/install/", @@ -90,13 +98,19 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) }, wallet: { showPubkey: true, - alertIfUnusedWallet: true, - notificationReadTime: 0 + alertIfUnusedWallet: true }, locale: { id: fixLocaleWithLog(csConfig.defaultLanguage || $translate.use()) // use config locale if set, or browser default + }, + license: { + "en": "license/license_g1-en", + "fr-FR": "license/license_g1-fr-FR", + "es-ES": "license/license_g1-es-ES" } - }, csConfig), + }, + fixedSettings, + csConfig), data = {}, previousData, @@ -104,6 +118,11 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) startPromise, api = new Api(this, "csSettings"); + // removeIf(no-device) + // set defaults for device + defaultSettings.walletHistoryAutoRefresh = false; + // endRemoveIf(no-device) + var reset = function() { _.keys(data).forEach(function(key){ @@ -130,10 +149,10 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) }, emitChangedEvent = function() { - var hasChanged = previousData && !angular.equals(previousData, data); - previousData = angular.copy(data); + var hasChanged = angular.isUndefined(previousData) || !angular.equals(previousData, data); if (hasChanged) { - api.data.raise.changed(data); + previousData = angular.copy(data); + return api.data.raise.changed(data); } }, @@ -177,38 +196,43 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) .then(emitChangedEvent); }, + /** + * Apply new settings (can be partial) + * @param newData + */ applyData = function(newData) { + if (!newData) return; // skip empty + var localeChanged = false; if (newData.locale && newData.locale.id) { // Fix previously stored locale (could use bad format) - newData.locale.id = fixLocale(newData.locale.id); + var localeId = fixLocale(newData.locale.id); + newData.locale = _.findWhere(locales, {id: localeId}); localeChanged = !data.locale || newData.locale.id !== data.locale.id || newData.locale.id !== $translate.use(); } - // Apply stored settings + // Force some fixed settings, before merging + _.keys(fixedSettings).forEach(function(key) { + newData[key] = defaultSettings[key]; // This will apply fixed value (override by config.js file) + }); + + // Apply new settings angular.merge(data, newData); - // Always force the usage of default settings - // This is a workaround for DEV (TODO: implement edition in settings ?) - data.timeWarningExpire = defaultSettings.timeWarningExpire; - data.timeWarningExpireMembership = defaultSettings.timeWarningExpireMembership; - data.cacheTimeMs = defaultSettings.cacheTimeMs; - data.timeout = defaultSettings.timeout; - data.minVersion = defaultSettings.minVersion; - data.latestReleaseUrl = defaultSettings.latestReleaseUrl; - data.duniterLatestReleaseUrl = defaultSettings.duniterLatestReleaseUrl; - data.newIssueUrl = defaultSettings.newIssueUrl; - data.userForumUrl = defaultSettings.userForumUrl; + // Delete temporary properties, if false + if (newData && newData.node && !newData.node.temporary || !data.node.temporary) delete data.node.temporary; // Apply the new locale (only if need) + // will produce an event cached by onLocaleChange(); if (localeChanged) { - $translate.use(fixLocale(data.locale.id)); // will produce an event cached by onLocaleChange(); + $translate.use(data.locale.id); } }, restore = function() { - var now = new Date().getTime(); + var now = Date.now(); + return localStorage.getObject(constants.STORAGE_KEY) .then(function(storedData) { // No settings stored @@ -219,15 +243,10 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) return; } - // Workaround, to turn on 'rememberMe', but only once (at version 0.13.2) - if (!storedData.rememberMe && (!storedData.login || !storedData.login.method)) { - storedData.rememberMe = true; - } - // Apply stored data applyData(storedData); - console.debug('[settings] Loaded from local storage in '+(new Date().getTime()-now)+'ms'); + console.debug('[settings] Loaded from local storage in '+(Date.now()-now)+'ms'); emitChangedEvent(); }); }, @@ -235,30 +254,40 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) getLicenseUrl = function() { var locale = data.locale && data.locale.id || csConfig.defaultLanguage || 'en'; return (csConfig.license) ? - (csConfig.license[locale] ? csConfig.license[locale] : csConfig.license[csConfig.defaultLanguage || 'en'] || csConfig.license) : undefined; + (csConfig.license[locale] ? csConfig.license[locale] : defaultSettings.license[csConfig.defaultLanguage || 'en'] || csConfig.license) : undefined; }, - // Detect locale sucessuf changes, then apply to vendor libs + // Detect locale successful changes, then apply to vendor libs onLocaleChange = function() { var locale = $translate.use(); console.debug('[settings] Locale ['+locale+']'); // config moment lib try { - moment.locale(locale.substr(0,2)); + moment.locale(locale.toLowerCase()); } catch(err) { - moment.locale('en'); - console.warn('[settings] Unknown local for moment lib. Using default [en]'); + try { + moment.locale(locale.substr(0,2)); + } + catch(err) { + moment.locale('en-gb'); + console.warn('[settings] Unknown local for moment lib. Using default [en]'); + } } // config numeral lib try { - numeral.language(locale.substr(0,2)); + numeral.language(locale.toLowerCase()); } catch(err) { - numeral.language('en'); - console.warn('[settings] Unknown local for numeral lib. Using default [en]'); + try { + numeral.language(locale.substring(0, 2)); + } + catch(err) { + numeral.language('en-gb'); + console.warn('[settings] Unknown local for numeral lib. Using default [en]'); + } } // Emit event @@ -309,6 +338,7 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config']) ready: ready, start: start, data: data, + apply: applyData, getByPath: getByPath, reset: reset, store: store, diff --git a/assets/www/js/services/storage-services.js b/assets/www/js/services/storage-services.js index 1830fc0cd0ee59fd40d0a37fee1626484c0faae3..4f92253dddd5269e880a68435f3a34f17c6b8176 100644 --- a/assets/www/js/services/storage-services.js +++ b/assets/www/js/services/storage-services.js @@ -24,13 +24,13 @@ angular.module('cesium.storage.services', [ 'cesium.config']) }; exports.getObject = function(key) { - return $q.when(JSON.parse(exports.storage[key] || '{}')); + return $q.when(JSON.parse(exports.storage[key] || 'null')); }; return exports; }) - .factory('localStorage', function($window, $q, sessionStorage) { + .factory('localStorage', function($window, $q, $log, sessionStorage) { 'ngInject'; var @@ -55,7 +55,17 @@ angular.module('cesium.storage.services', [ 'cesium.config']) /* -- Use standard browser implementation -- */ exports.standard.put = function(key, value) { - exports.standard.storage[key] = value; + if (angular.isDefined(value) && value != null) { + exports.standard.storage[key] = value; + } + else { + exports.standard.storage.removeItem(key); + } + return $q.when(); + }; + + exports.standard.remove = function(key, value) { + exports.standard.storage.removeItem(key); return $q.when(); }; @@ -69,58 +79,84 @@ angular.module('cesium.storage.services', [ 'cesium.config']) }; exports.standard.getObject = function(key) { - return $q.when(JSON.parse(exports.standard.storage[key] || '{}')); + return $q.when(JSON.parse(exports.standard.storage[key] || 'null')); }; /* -- Use secure storage (using a cordova plugin) -- */ // Set a value to the secure storage (or remove if value is not defined) exports.secure.put = function(key, value) { - var deferred = $q.defer(); - if (angular.isDefined(value)) { - exports.secure.storage.set( - function (key) { deferred.resolve(); }, - function (err) { deferred.reject(err); }, - key, value); - } - // Remove - else { - exports.secure.storage.remove( - function (key) { deferred.resolve(); }, - function (err) { deferred.reject(err); }, - key); - } - return deferred.promise; + return $q(function(resolve, reject) { + if (value !== undefined && value !== null) { + exports.secure.storage.set( + function (key) { + resolve(); + }, + function (err) { + $log.error(err); + reject(err); + }, + key, value); + } + // Remove + else { + exports.secure.storage.remove( + function () { + resolve(); + }, + function (err) { + $log.error(err); + resolve(); // Error = not found + }, + key); + } + }); }; // Get a value from the secure storage exports.secure.get = function(key, defaultValue) { - var deferred = $q.defer(); - exports.secure.storage.get( - function (value) { - if (!value && defaultValue) { - deferred.resolve(defaultValue); - } - else { - deferred.resolve(value); - } - }, - function (err) { deferred.reject(err); }, - key); - return deferred.promise; + return $q(function(resolve, reject) { + exports.secure.storage.get( + function (value) { + if (!value && defaultValue) { + resolve(defaultValue); + } + else { + resolve(value); + } + }, + function (err) { + $log.error(err); + resolve(); // Error = not found + }, + key); + }); }; // Set a object to the secure storage exports.secure.setObject = function(key, value) { - return exports.secure.put(key, value ? JSON.stringify(value) : undefined); + $log.debug("[storage] Setting object into secure storage, using key=" + key); + return $q(function(resolve, reject){ + exports.secure.storage.set( + resolve, + reject, + key, + value ? JSON.stringify(value) : undefined); + }); }; // Get a object from the secure storage exports.secure.getObject = function(key) { - return exports.secure.storage.get(key) - .then(function(value) { - return (value && JSON.parse(value)) || {}; - }); + $log.debug("[storage] Getting object from secure storage, using key=" + key); + return $q(function(resolve, reject){ + exports.secure.storage.get( + function(value) {resolve(JSON.parse(value||'null'));}, + function(err) { + $log.error(err); + resolve(); // Error = not found + }, + key); + }); }; function initStandardStorage() { @@ -134,7 +170,7 @@ angular.module('cesium.storage.services', [ 'cesium.config']) }); } - // Fallback to session storage (locaStorage could have been disabled on some browser) + // Fallback to session storage (localStorage could have been disabled on some browser) else { console.debug('[storage] Starting {session} storage...'); // Set standard storage as default @@ -187,11 +223,10 @@ angular.module('cesium.storage.services', [ 'cesium.config']) function start() { if (startPromise) return startPromise; - var now = new Date().getTime(); + var now = Date.now(); // Use Cordova secure storage plugin if (isDevice) { - console.debug("[storage] Starting secure storage..."); startPromise = initSecureStorage(); } @@ -202,7 +237,7 @@ angular.module('cesium.storage.services', [ 'cesium.config']) return startPromise .then(function() { - console.debug('[storage] Started in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[storage] Started in ' + (Date.now() - now) + 'ms'); started = true; startPromise = null; }); diff --git a/assets/www/js/services/tx-services.js b/assets/www/js/services/tx-services.js index 6c27fe449fe8e7319f960c269656fd5b68034b3c..2572c44b2df78496f7acd51089fa345f278596ee 100644 --- a/assets/www/js/services/tx-services.js +++ b/assets/www/js/services/tx-services.js @@ -6,21 +6,22 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', csConfig, csSettings, csWot, csCurrency) { 'ngInject'; - function factory(id, BMA) { + var defaultBMA = BMA; + function CsTx(id, BMA) { + + BMA = BMA || defaultBMA; var api = new Api(this, "csTx-" + id), _reduceTxAndPush = function(pubkey, txArray, result, processedTxMap, allowPendings) { - if (!txArray || txArray.length === 0) { - return; - } + if (!txArray || !txArray.length) return; // Skip if empty _.forEach(txArray, function(tx) { if (tx.block_number || allowPendings) { var walletIsIssuer = false; var otherIssuer = tx.issuers.reduce(function(issuer, res) { - walletIsIssuer = (res === pubkey) ? true : walletIsIssuer; + walletIsIssuer = walletIsIssuer || (res === pubkey); return issuer + ((res !== pubkey) ? ', ' + res : ''); }, ''); if (otherIssuer.length > 0) { @@ -126,112 +127,119 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', loadTx = function(pubkey, fromTime) { return $q(function(resolve, reject) { - var txHistory = []; - var udHistory = []; - var txPendings = []; - var nowInSec = Math.trunc(new Date().getTime() / 1000); // TODO test to replace using moment().utc().unix() + var nowInSec = moment().utc().unix(); fromTime = fromTime || (nowInSec - csSettings.data.walletHistoryTimeSecond); - var processedTxMap = {}; var tx = { - pendings: [] + pendings: [], + validating: [], + history: [], + errors: [] }; - var _reduceTx = function(res){ - _reduceTxAndPush(pubkey, res.history.sent, txHistory, processedTxMap); - _reduceTxAndPush(pubkey, res.history.received, txHistory, processedTxMap); - _reduceTxAndPush(pubkey, res.history.sending, txPendings, processedTxMap, true /*allow pendings*/); - _reduceTxAndPush(pubkey, res.history.pending, txPendings, processedTxMap, true /*allow pendings*/); + var processedTxMap = {}; + var _reduceTx = function (res) { + _reduceTxAndPush(pubkey, res.history.sent, tx.history, processedTxMap); + _reduceTxAndPush(pubkey, res.history.received, tx.history, processedTxMap); + _reduceTxAndPush(pubkey, res.history.sending, tx.pendings, processedTxMap, true /*allow pendings*/); + _reduceTxAndPush(pubkey, res.history.pending, tx.pendings, processedTxMap, true /*allow pendings*/); }; var jobs = [ - // get pendings history + // get current block + csCurrency.blockchain.current(true), + + // get pending tx BMA.tx.history.pending({pubkey: pubkey}) .then(_reduceTx) ]; // get TX history since - if (fromTime !== -1) { - var sliceTime = csSettings.data.walletHistorySliceSecond; - fromTime = fromTime - (fromTime % sliceTime); - for(var i = fromTime; i - sliceTime < nowInSec; i += sliceTime) { - var startTime = Math.max(i, fromTime); - jobs.push(BMA.tx.history.times({pubkey: pubkey, from: i, to: i+sliceTime-1}) + if (fromTime !== 'pending') { + + // get TX from a given time + if (fromTime > 0) { + // Use slice, to be able to cache requests result + var sliceTime = csSettings.data.walletHistorySliceSecond; + fromTime = fromTime - (fromTime % sliceTime); + for(var i = fromTime; i - sliceTime < nowInSec; i += sliceTime) { + jobs.push(BMA.tx.history.times({pubkey: pubkey, from: i, to: i+sliceTime-1}) + .then(_reduceTx) + ); + } + + jobs.push(BMA.tx.history.timesNoCache({pubkey: pubkey, from: nowInSec - (nowInSec % sliceTime), to: nowInSec+999999999}) + .then(_reduceTx)); + } + + // get all TX + else { + jobs.push(BMA.tx.history.all({pubkey: pubkey}) .then(_reduceTx) ); } - jobs.push(BMA.tx.history.timesNoCache({pubkey: pubkey, from: nowInSec - (nowInSec % sliceTime), to: nowInSec+999999999}) - .then(_reduceTx)); - } - - // get all TX - else { - jobs.push(BMA.tx.history.all({pubkey: pubkey}) - .then(_reduceTx) - ); - } - - // get UD history - if (csSettings.data.showUDHistory) { - /*jobs.push( - BMA.ud.history({pubkey: pubkey}) - .then(function(res){ - udHistory = !res.history || !res.history.history ? [] : - res.history.history.reduce(function(res, ud){ - if (ud.time < fromTime) return res; // skip to old UD - var amount = powBase(ud.amount, ud.base); - return res.concat({ - time: ud.time, - amount: amount, - isUD: true, - block_number: ud.block_number + // get UD history + if (csSettings.data.showUDHistory && fromTime > 0) { + /*jobs.push( + BMA.ud.history({pubkey: pubkey}) + .then(function(res){ + udHistory = !res.history || !res.history.history ? [] : + _.forEach(res.history.history, function(ud){ + if (ud.time < fromTime) return res; // skip to old UD + var amount = powBase(ud.amount, ud.base); + udHistory.push({ + time: ud.time, + amount: amount, + isUD: true, + block_number: ud.block_number + }); }); - }, []); - }));*/ - // API extension - jobs.push( - api.data.raisePromise.loadUDs({ - pubkey: pubkey, - fromTime: fromTime - }) - .then(function(res) { - if (!res || !res.length) return; - udHistory = res.reduce(function(res, hits) { - return res.concat(hits); - }, udHistory); + }));*/ + // API extension + jobs.push( + api.data.raisePromise.loadUDs({ + pubkey: pubkey, + fromTime: fromTime }) + .then(function(res) { + if (!res || !res.length) return; + _.forEach(res, function(hits) { + tx.history.push(hits); + }); + }) - .catch(function(err) { - console.debug('Error while loading UDs history, on extension point.'); - console.error(err); - }) - ); + .catch(function(err) { + console.debug('Error while loading UDs history, on extension point.'); + console.error(err); + }) + ); + } } // Execute jobs $q.all(jobs) - .then(function(){ + .then(function(res){ + var current = res[0]; + // sort by time desc - tx.history = txHistory.concat(udHistory).sort(function(tx1, tx2) { + tx.history.sort(function(tx1, tx2) { return (tx2.time - tx1.time); }); - tx.pendings = txPendings; - - tx.fromTime = fromTime; - tx.toTime = tx.history.length ? tx.history[0].time /*=max(tx.time)*/: fromTime; + tx.validating = tx.history.filter(function(tx) { + return (tx.block_number > current.number - csSettings.data.blockValidityWindow); + }); + // remove validating from history + if (tx.validating.length) { + tx.history.splice(0, tx.validating.length); + } + tx.fromTime = fromTime !== 'pending' && fromTime || undefined; + tx.toTime = tx.history.length ? tx.history[0].time /*=max(tx.time)*/: tx.fromTime; resolve(tx); }) - .catch(function(err) { - tx.history = []; - tx.pendings = []; - tx.errors = []; - delete tx.fromTime; - delete tx.toTime; - reject(err); - }); + .catch(reject); }); }, @@ -256,7 +264,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', loadSourcesAndBalance = function(pubkey) { return BMA.tx.sources({pubkey: pubkey}) .then(function(res){ - var result = { + var data = { sources: [], sourcesIndexByKey: [], balance: 0 @@ -264,19 +272,23 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', if (res.sources && res.sources.length) { _.forEach(res.sources, function(src) { src.consumed = false; - result.balance += powBase(src.amount, src.base); + data.balance += powBase(src.amount, src.base); }); - addSources(result, res.sources); + addSources(data, res.sources); } - return result; + return data; + }) + .catch(function(err) { + console.warn("[tx] Error while getting sources...", err); + throw err; }); }, loadData = function(pubkey, fromTime) { - var now = new Date().getTime(); + var now = Date.now(); - var data = {}; return $q.all([ + // Load Sources loadSourcesAndBalance(pubkey), @@ -285,12 +297,14 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', ]) .then(function(res) { - angular.merge(data, res[0]); + // Copy sources and balance + var data = res[0]; data.tx = res[1]; var txPendings = []; var txErrors = []; - var balance = data.balance; + var balanceFromSource = data.balance; + var balanceWithPending = data.balance; function _processPendingTx(tx) { var consumedSources = []; @@ -318,7 +332,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', delete tx.inputs; } if (valid) { - balance += tx.amount; // update balance + balanceWithPending += tx.amount; // update balance txPendings.push(tx); _.forEach(consumedSources, function(src) { src.consumed=true; @@ -331,7 +345,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', var txs = data.tx.pendings; var retry = true; - while(txs && txs.length > 0) { + while(txs && txs.length) { // process TX pendings _.forEach(txs, _processPendingTx); @@ -346,18 +360,30 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', } } - data.tx.pendings = txPendings; - data.tx.errors = txErrors; - data.balance = balance; + data.tx = data.tx || {}; + data.tx.pendings = txPendings.sort(function(tx1, tx2) { + return (tx2.time - tx1.time); + }); + data.tx.errors = txErrors.sort(function(tx1, tx2) { + return (tx2.time - tx1.time); + }); + // Negative balance not allow (use only source's balance) - fix #769 + data.balance = (balanceWithPending < 0) ? balanceFromSource : balanceWithPending; // Will add uid (+ plugin will add name, avatar, etc. if enable) - return csWot.extendAll((data.tx.history || []).concat(data.tx.pendings||[]), 'pubkey'); - }) - .then(function() { - console.debug('[tx] TX and sources loaded in '+ (new Date().getTime()-now) +'ms'); - return data; + var allTx = (data.tx.history || []).concat(data.tx.validating||[], data.tx.pendings||[], data.tx.errors||[]); + return csWot.extendAll(allTx, 'pubkey') + .then(function() { + console.debug('[tx] TX and sources loaded in '+ (Date.now()-now) +'ms'); + return data; + }); }); - }; + }, + + loadSources = function(pubkey) { + console.debug("[tx] Loading sources for " + pubkey.substring(0,8)); + return loadData(pubkey, 'pending'); + }; // Download TX history file downloadHistoryFile = function(pubkey, options) { @@ -378,17 +404,15 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', loadData(pubkey, options.fromTime) ]) .then(function(result){ - var translations = result[0]; - var currentBlock = result[1]; var currentTime = (currentBlock && currentBlock.medianTime) || moment().utc().unix(); var currency = currentBlock && currentBlock.currency; - result = result[2]; + var data = result[2]; // no TX - if (!result || !result.tx || !result.tx.history) { + if (!data || !data.tx || !data.tx.history) { return UIUtils.toast.show('INFO.EMPTY_TX_HISTORY'); } @@ -396,9 +420,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', .then(function(filename){ var formatDecimal = $filter('formatDecimal'); - var formatPubkey = $filter('formatPubkey'); - var formatDate = $filter('formatDate'); - var formatDateForFile = $filter('formatDateForFile'); + var medianDate = $filter('medianDate'); var formatSymbol = $filter('currencySymbolNoHtml'); var headers = [ @@ -408,9 +430,9 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', translations['ACCOUNT.HEADERS.AMOUNT'] + ' (' + formatSymbol(currency) + ')', translations['ACCOUNT.HEADERS.COMMENT'] ]; - var content = result.tx.history.reduce(function(res, tx){ + var content = data.tx.history.concat(data.tx.validating).reduce(function(res, tx){ return res.concat([ - formatDate(tx.time), + medianDate(tx.time), tx.uid, tx.pubkey, formatDecimal(tx.amount/100), @@ -430,14 +452,17 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', return { id: id, load: loadData, + loadSources: loadSources, downloadHistoryFile: downloadHistoryFile, // api extension api: api }; } - var service = factory('default', BMA); + var service = new CsTx('default'); - service.instance = factory; + service.instance = function(id, bma) { + return new CsTx(id, bma); + }; return service; }); diff --git a/assets/www/js/services/utils-services.js b/assets/www/js/services/utils-services.js index dafea9adbc3c91fedc8e9dc0f456b756004f7c2f..3c18ed4f932b202b9ccb08b38b83f6b171404b4f 100644 --- a/assets/www/js/services/utils-services.js +++ b/assets/www/js/services/utils-services.js @@ -15,28 +15,29 @@ angular.module('cesium.utils.services', []) }; }) -.factory('UIUtils', function($ionicLoading, $ionicPopup, $ionicConfig, $translate, $q, ionicMaterialInk, ionicMaterialMotion, $window, $timeout, +.factory('UIUtils', function($ionicLoading, $ionicPopup, $ionicConfig, $ionicHistory, $translate, $q, + ionicMaterialInk, ionicMaterialMotion, $window, $timeout, Fullscreen, // removeIf(no-device) $cordovaToast, // endRemoveIf(no-device) - $ionicPopover, $state, $rootScope, screenmatch, csSettings) { + $ionicPopover, $state, $rootScope, screenmatch) { 'ngInject'; var loadingTextCache=null, CONST = { - MAX_HEIGHT: 400, - MAX_WIDTH: 400, - THUMB_MAX_HEIGHT: 100, - THUMB_MAX_WIDTH: 100 + MAX_HEIGHT: 480, + MAX_WIDTH: 640, + THUMB_MAX_HEIGHT: 200, + THUMB_MAX_WIDTH: 200 }, data = { smallscreen: screenmatch.bind('xs, sm', $rootScope) }, exports, raw = {} - ; + ; function alertError(err, subtitle) { if (!err) { @@ -45,45 +46,45 @@ angular.module('cesium.utils.services', []) return $q(function(resolve) { $translate([err, subtitle, 'ERROR.POPUP_TITLE', 'ERROR.UNKNOWN_ERROR', 'COMMON.BTN_OK']) - .then(function (translations) { - var message = err.message || translations[err]; - return $ionicPopup.show({ - template: '<p>' + (message || translations['ERROR.UNKNOWN_ERROR']) + '</p>', - title: translations['ERROR.POPUP_TITLE'], - subTitle: translations[subtitle], - buttons: [ - { - text: '<b>'+translations['COMMON.BTN_OK']+'</b>', - type: 'button-assertive', - onTap: function(e) { - resolve(e); + .then(function (translations) { + var message = err.message || translations[err]; + return $ionicPopup.show({ + template: '<p>' + (message || translations['ERROR.UNKNOWN_ERROR']) + '</p>', + title: translations['ERROR.POPUP_TITLE'], + subTitle: translations[subtitle], + buttons: [ + { + text: '<b>'+translations['COMMON.BTN_OK']+'</b>', + type: 'button-assertive', + onTap: function(e) { + resolve(e); + } } - } - ] + ] + }); }); - }); }); } function alertInfo(message, subtitle) { return $q(function(resolve) { $translate([message, subtitle, 'INFO.POPUP_TITLE', 'COMMON.BTN_OK']) - .then(function (translations) { - $ionicPopup.show({ - template: '<p>' + translations[message] + '</p>', - title: translations['INFO.POPUP_TITLE'], - subTitle: translations[subtitle], - buttons: [ - { - text: translations['COMMON.BTN_OK'], - type: 'button-positive', - onTap: function(e) { - resolve(e); + .then(function (translations) { + $ionicPopup.show({ + template: '<p>' + translations[message] + '</p>', + title: translations['INFO.POPUP_TITLE'], + subTitle: translations[subtitle], + buttons: [ + { + text: translations['COMMON.BTN_OK'], + type: 'button-positive', + onTap: function(e) { + resolve(e); + } } - } - ] + ] + }); }); - }); }); } @@ -138,6 +139,23 @@ angular.module('cesium.utils.services', []) return $ionicLoading.show(options); } + function updateLoading(options) { + return $ionicLoading._getLoader().then(function(loader) { + if (!loader || !loader.isShown) return; + // Translate template (if exists) + if (options && options.template) { + return $translate(options && options.template) + .then(function(template) { + options.template = template; + return loader; + }); + } + }) + .then(function(loader) { + if (loader && loader.isShown) return showLoading(options); + }); + } + function showToast(message, duration, position) { duration = duration || 'short'; position = position || 'bottom'; @@ -226,41 +244,82 @@ angular.module('cesium.utils.services', []) function getSelectionText(){ var selectedText = ""; if (window.getSelection){ // all modern browsers and IE9+ - selectedText = $window.getSelection().toString(); + selectedText = $window.getSelection().toString(); } return selectedText; } function imageOnLoadResize(resolve, reject, thumbnail) { return function(event) { - var width = event.target.width; - var height = event.target.height; - var maxWidth = (thumbnail ? CONST.THUMB_MAX_WIDTH : CONST.MAX_WIDTH); - var maxHeight = (thumbnail ? CONST.THUMB_MAX_HEIGHT : CONST.MAX_HEIGHT); - - if (width > height) { - if (width > maxWidth) { - height *= maxWidth / width; - width = maxWidth; - } - } else { - if (height > maxHeight) { - width *= maxHeight / height; - height = maxHeight; - } + var width = event.target.width, + height = event.target.height, + maxWidth = (thumbnail ? CONST.THUMB_MAX_WIDTH : CONST.MAX_WIDTH), + maxHeight = (thumbnail ? CONST.THUMB_MAX_HEIGHT : CONST.MAX_HEIGHT) + ; + + var canvas = document.createElement("canvas"); + var ctx; + + // Thumbnail: resize and crop (to the expected size) + if (thumbnail) { + + // landscape + if (width > height) { + width *= maxHeight / height; + height = maxHeight; + } + + // portrait + else { + height *= maxWidth / width; + width = maxWidth; + } + canvas.width = maxWidth; + canvas.height = maxHeight; + ctx = canvas.getContext("2d"); + var xoffset = Math.trunc((maxWidth - width) / 2 + 0.5); + var yoffset = Math.trunc((maxHeight - height) / 2 + 0.5); + ctx.drawImage(event.target, + xoffset, // x1 + yoffset, // y1 + maxWidth + -2 * xoffset, // x2 + maxHeight + -2 * yoffset // y2 + ); + } + + // Resize, but keep the full image + else { + + // landscape + if (width > height) { + if (width > maxWidth) { + height *= maxWidth / width; + width = maxWidth; } - var canvas = document.createElement("canvas"); - canvas.width = width; - canvas.height = height; - var ctx = canvas.getContext("2d"); - ctx.drawImage(event.target, 0, 0, canvas.width, canvas.height); + } - var dataurl = canvas.toDataURL(); + // portrait + else { + if (height > maxHeight) { + width *= maxHeight / height; + height = maxHeight; + } + } - canvas.remove(); + canvas.width = width; + canvas.height = height; + ctx = canvas.getContext("2d"); - resolve(dataurl); - }; + // Resize the whole image + ctx.drawImage(event.target, 0, 0, canvas.width, canvas.height); + } + + var dataurl = canvas.toDataURL(); + + canvas.remove(); + + resolve(dataurl); + }; } function resizeImageFromFile(file, thumbnail) { @@ -356,7 +415,6 @@ angular.module('cesium.utils.services', []) options.scope = options.scope || $rootScope; options.scope.popovers = options.scope.popovers || {}; options.autoselect = options.autoselect || false; - options.bindings = options.bindings || {}; options.autoremove = angular.isDefined(options.autoremove) ? options.autoremove : true; options.backdropClickToClose = angular.isDefined(options.backdropClickToClose) ? options.backdropClickToClose : true; options.focusFirstInput = angular.isDefined(options.focusFirstInput) ? options.focusFirstInput : false; @@ -367,37 +425,39 @@ angular.module('cesium.utils.services', []) popover.deferred=deferred; popover.options=options; // Fill the popover scope - angular.merge(popover.scope, options.bindings); + if (options.bindings) { + angular.merge(popover.scope, options.bindings); + } $timeout(function() { // This is need for Firefox popover.show(event) - .then(function() { - var element; - // Auto select text - if (options.autoselect) { - element = document.querySelectorAll(options.autoselect)[0]; - if (element) { - if ($window.getSelection && !$window.getSelection().toString()) { - element.setSelectionRange(0, element.value.length); - element.focus(); - } - else { - element.focus(); + .then(function() { + var element; + // Auto select text + if (options.autoselect) { + element = document.querySelectorAll(options.autoselect)[0]; + if (element) { + if ($window.getSelection && !$window.getSelection().toString()) { + element.setSelectionRange(0, element.value.length); + element.focus(); + } + else { + element.focus(); + } } } - } - else { - // Auto focus on a element - if (options.autofocus) { - element = document.querySelectorAll(options.autofocus)[0]; - if (element) element.focus(); + else { + // Auto focus on a element + if (options.autofocus) { + element = document.querySelectorAll(options.autofocus)[0]; + if (element) element.focus(); + } } - } - popover.scope.$parent.$emit('popover.shown'); + popover.scope.$parent.$emit('popover.shown'); - // Callback 'afterShow' - if (options.afterShow) options.afterShow(popover); - }); + // Callback 'afterShow' + if (options.afterShow) options.afterShow(popover); + }); }); }; @@ -407,9 +467,9 @@ angular.module('cesium.utils.services', []) delete options.scope.popovers[options.templateUrl]; // Remove the popover popover.remove() - // Workaround for issue #244 - // See also https://github.com/driftyco/ionic-v1/issues/71 - // and https://github.com/driftyco/ionic/issues/9069 + // Workaround for issue #244 + // See also https://github.com/driftyco/ionic-v1/issues/71 + // and https://github.com/driftyco/ionic/issues/9069 .then(function() { var bodyEl = angular.element($window.document.querySelectorAll('body')[0]); bodyEl.removeClass('popover-open'); @@ -428,8 +488,8 @@ angular.module('cesium.utils.services', []) popover.isResolved = false; popover.scope.closePopover = function(result) { - var autoremove = popover.options.autoremove; - delete popover.options.autoremove; // remove to avoid to trigger 'popover.hidden' + var autoremove = popover.options && popover.options.autoremove; + if (popover.options) delete popover.options.autoremove; // remove to avoid to trigger 'popover.hidden' popover.hide() .then(function() { if (autoremove) { @@ -611,7 +671,7 @@ angular.module('cesium.utils.services', []) function motionDelegate(delegate, ionListClass) { var motionTimeout = isSmallScreen() ? 100 : 10; var defaultSelector = '.list.{0} .item, .list .{0} .item'.format(ionListClass, ionListClass); - return { + return { ionListClass: ionListClass, show: function(options) { options = options || {}; @@ -634,9 +694,10 @@ angular.module('cesium.utils.services', []) if (exports.motion.enable === enable) return; // same console.debug('[UI] [effects] ' + (enable ? 'Enable' : 'Disable')); + exports.motion.enable = enable; if (enable) { $ionicConfig.views.transition('platform'); - exports.motion = raw.motion; + angular.merge(exports.motion, raw.motion); } else { $ionicConfig.views.transition('none'); @@ -644,7 +705,7 @@ angular.module('cesium.utils.services', []) class: undefined, show: function(){} }; - exports.motion = { + angular.merge(exports.motion, { enable : false, default: nothing, fadeSlideIn: nothing, @@ -656,8 +717,10 @@ angular.module('cesium.utils.services', []) fadeIn: nothing, toggleOn: toggleOn, toggleOff: toggleOff - }; + }); + $rootScope.motion = nothing; } + $ionicHistory.clearCache(); } raw.motion = { @@ -671,8 +734,8 @@ angular.module('cesium.utils.services', []) ripple: motionDelegate(ionicMaterialMotion.ripple, 'animate-ripple'), slideUp: motionDelegate(ionicMaterialMotion.slideUp, 'slide-up'), fadeIn: motionDelegate(function(options) { - toggleOn(options); - }, 'fade-in'), + toggleOn(options); + }, 'fade-in'), toggleOn: toggleOn, toggleOff: toggleOff }; @@ -726,12 +789,6 @@ angular.module('cesium.utils.services', []) }, timeout || 900); } - - - csSettings.api.data.on.changed($rootScope, function(data) { - setEffects(data.uiEffects); - }); - exports = { alert: { error: alertError, @@ -741,14 +798,16 @@ angular.module('cesium.utils.services', []) }, loading: { show: showLoading, - hide: hideLoading + hide: hideLoading, + update: updateLoading }, toast: { show: showToast }, onError: onError, screen: { - isSmall: isSmallScreen + isSmall: isSmallScreen, + fullscreen: Fullscreen }, ink: ionicMaterialInk.displayEffect, motion: raw.motion, diff --git a/assets/www/js/services/wallet-services.js b/assets/www/js/services/wallet-services.js index 7ab19bab03675798b8531a41eacfb7c2c0d2092a..5477306815f9bc1dd31b1aff27b77ac9c353b528 100644 --- a/assets/www/js/services/wallet-services.js +++ b/assets/www/js/services/wallet-services.js @@ -5,27 +5,32 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se .factory('csWallet', function($q, $rootScope, $timeout, $translate, $filter, $ionicHistory, UIUtils, Api, Idle, localStorage, sessionStorage, Modals, - CryptoUtils, BMA, csConfig, csSettings, FileSaver, Blob, csWot, csTx, csCurrency) { + CryptoUtils, csCrypto, BMA, csConfig, csSettings, FileSaver, Blob, csWot, csTx, csCurrency) { 'ngInject'; + var defaultBMA = BMA; + var service; + function factory(id, BMA) { + BMA = BMA || defaultBMA; var + exports, constants = { - // @Deprecated - OLD_STORAGE_KEY: 'CESIUM_DATA', STORAGE_PUBKEY: 'pubkey', STORAGE_UID: 'uid', + STORAGE_DATA_PREFIX: 'data-', STORAGE_SECKEY: 'seckey', /* Need for compat with old currencies (test_net and sou) */ - TX_VERSION: csConfig.compatProtocol_0_80 ? 3 : BMA.constants.PROTOCOL_VERSION, - IDTY_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION, - MS_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION, - CERT_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION, - REVOKE_VERSION: csConfig.compatProtocol_0_80 ? 2 : BMA.constants.PROTOCOL_VERSION, + TX_VERSION: BMA.constants.PROTOCOL_VERSION, + IDTY_VERSION: BMA.constants.PROTOCOL_VERSION, + MS_VERSION: BMA.constants.PROTOCOL_VERSION, + CERT_VERSION: BMA.constants.PROTOCOL_VERSION, + REVOKE_VERSION: BMA.constants.PROTOCOL_VERSION, TX_MAX_INPUTS_COUNT: 40 // Allow to get a TX with less than 100 rows (=max row count in Duniter protocol) }, data = {}, + settings, listeners, started, startPromise, @@ -38,15 +43,23 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se data.pubkey= null; data.uid = null; + data.localName = null; data.isNew = null; data.sourcesIndexByKey = null; data.medianTime = null; data.requirements = {}; data.blockUid = null; data.sigDate = null; + data.sigStock = null; data.isMember = false; data.events = []; + // children's wallets + data.children = []; + + // Encrypted (need auth() to be encrypted) + data.encryptedData = null; + resetKeypair(); resetTxAndSources(); @@ -57,7 +70,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se api.data.raise.init(data); } else { - if (!csSettings.data.useLocalStorage) { + if (isDefault() && settings && !settings.useLocalStorage) { csSettings.reset(); } api.data.raise.reset(data); @@ -71,20 +84,39 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }; }, - resetTxAndSources = function(){ + resetSources = function(){ // reset sources data data.sources = undefined; data.sourcesIndexByKey = undefined; data.balance = 0; + }, + + resetTx = function(){ // reset TX data data.tx = data.tx || {}; data.tx.history = []; data.tx.pendings = []; + data.tx.validating = []; data.tx.errors = []; delete data.tx.fromTime; delete data.tx.toTime; }, + resetTxAndSources = function(){ + // reset sources data + resetSources(); + // reset TX data + resetTx(); + }, + + isDefault = function(){ + return id === 'default'; + }, + + hasEncryptedData = function(){ + return data.encryptedData && data.encryptedData.nonce && data.encryptedData.content; + }, + addSource = function(src, sources, sourcesIndexByKey) { var srcKey = src.type+':'+src.identifier+':'+src.noffset; if (angular.isUndefined(sourcesIndexByKey[srcKey])) { @@ -133,10 +165,11 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se } // invalid data authData = res; - data.pubkey = res.pubkey; + data.pubkey = authData.pubkey; + data.uid = authData.uid || data.uid; data.isNew = options && angular.isDefined(options.isNew) ? options.isNew : data.isNew; if (keepAuth) { - data.keypair = res.keypair || { + data.keypair = authData.keypair || { signSk: null, signPk: null }; @@ -163,8 +196,20 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }) .then(function() { - // store wallet if need - if (csSettings.data.useLocalStorage) { + // Read data from pubkey (when first login) + if (needLogin) { + return restoreData(); + } + // Or the was login but now auth: just try to decrypt data + else if (needAuth) { + return openEncryptedData(); + } + }) + + .then(function() { + if (needLogin) { + + // store wallet store(); } @@ -175,7 +220,8 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return api.data.raisePromise.auth(keepAuth ? data : authData); } - }).then(function() { + }) + .then(function() { // Load data if need // If user just login, force data full load (even if min data asked) // because the user can wait (after the login modal) @@ -206,8 +252,9 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return $q(function(resolve, reject) { + var pubkey = data.pubkey; resetData(); // will reset keypair - store(); // store (if local storage enable) + resetStore(pubkey); // reset store // Send logout event api.data.raise.logout(); @@ -264,7 +311,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }, isAuth = function() { - return !!(data.pubkey && data.keypair && data.keypair.signSk); + return data.pubkey && data.keypair && data.keypair.signSk && true; }, getKeypair = function(options) { @@ -287,12 +334,17 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }, hasSelf = function() { - return !!data.pubkey && data.requirements && !data.requirements.needSelf; + return !!data.pubkey && !data.requirements.needSelf; }, isDataLoaded = function(options) { - if (options && options.minData) return data.loaded; - return data.loaded && data.sources; + if (options) { + if (options.minData && !options.sources) return data.loaded && true; + if (options.requirements && !data.requirements.loaded) return false; + if (options.tx && options.tx.enable && (!data.tx.fromTime || data.tx.fromTime == 'pending')) return false; + if (options.sigStock && !data.sigStock) return false; + } + return data.loaded && data.sources && true; }, isNeverUsed = function() { @@ -301,6 +353,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se // Check registration data.isMember || data.requirements.pendingMembership || + data.requirements.revoked || !data.requirements.needSelf || data.requirements.wasMember || @@ -309,6 +362,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se data.tx.pendings.length || // Check extended data (name+avatar) + data.localName || data.name || data.avatar ); @@ -321,16 +375,21 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return isLogin() && data.pubkey === pubkey; }, - store = function() { - if (csSettings.data.useLocalStorage) { + // store pubkey and uid + store = function(pubkey) { + pubkey = pubkey && typeof pubkey == 'string' ? pubkey : data.pubkey; + if (settings.useLocalStorage) { - if (isLogin() && csSettings.data.rememberMe) { + if (isLogin() && settings.rememberMe) { + + var now = Date.now(); + console.debug("[wallet] Storing..."); var jobs = []; // Use session storage for secret key - fix #372 - if (csSettings.data.keepAuthIdle == constants.KEEP_AUTH_IDLE_SESSION && isAuth()) { - jobs.push(sessionStorage.put(constants.STORAGE_SECKEY, CryptoUtils.base58.encode(data.keypair.signSk))); + if (settings.keepAuthIdle == csSettings.constants.KEEP_AUTH_IDLE_SESSION && isAuth()) { + jobs.push(sessionStorage.put(constants.STORAGE_SECKEY, CryptoUtils.util.encode_base58(data.keypair.signSk))); } else { jobs.push(sessionStorage.put(constants.STORAGE_SECKEY, null)); @@ -347,20 +406,19 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se jobs.push(localStorage.put(constants.STORAGE_UID, null)); } - // Clean old storage - jobs.push(localStorage.put(constants.OLD_STORAGE_KEY, null)); - - return $q.all(jobs).then(function() { - console.debug('[wallet] Saved locally'); - }); + return $q.all(jobs) + .then(function() { + console.debug("[wallet] Stored in "+ (Date.now() - now) +"ms"); + }); } else { + // Resetting local storage return $q.all([ sessionStorage.put(constants.STORAGE_SECKEY, null), localStorage.put(constants.STORAGE_PUBKEY, null), localStorage.put(constants.STORAGE_UID, null), - // Clean old storage - localStorage.put(constants.OLD_STORAGE_KEY, null) + // Clean data (only in the session storage - keep local) + pubkey ? sessionStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when() ]); } } @@ -369,13 +427,117 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se sessionStorage.put(constants.STORAGE_SECKEY, null), localStorage.put(constants.STORAGE_PUBKEY, null), localStorage.put(constants.STORAGE_UID, null), - // Clean old storage - localStorage.put(constants.OLD_STORAGE_KEY, null) + // Clean data + pubkey ? sessionStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when(), + pubkey ? localStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when() ]); + } + }, + + // reset data store for this pubkey + resetStore = function(pubkey) { + + console.debug("[wallet] Resetting stored pubkey (and uid) in local storage..."); + + sessionStorage.put(constants.STORAGE_SECKEY, null); + localStorage.put(constants.STORAGE_PUBKEY, null); + localStorage.put(constants.STORAGE_UID, null); + if (settings.useLocalStorage) { + // Clean data (only in the session storage - keep local) + return pubkey ? sessionStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when(); + } + else { + console.debug("[wallet] Resetting stored data in local storage..."); + return $q.all([ + pubkey ? sessionStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when(), + pubkey ? localStorage.put(constants.STORAGE_DATA_PREFIX + pubkey, null) : $q.when() + ]); } }, + // store children wallet, notifications read Time, ... + storeData = function() { + if (!isLogin()) throw {message:'ERROR.NEED_LOGIN_FIRST'}; + + var useEncryption = settings.useLocalStorageEncryption; + var storageKey = constants.STORAGE_DATA_PREFIX + data.pubkey; + + var content; // Init only if used + var secureContent; // Init only if used + + // Add time + if (data.notifications && data.notifications.time) { + content = content || {}; + content.notifications = { + time: data.notifications.time + }; + } + if (data.invitations && data.invitations.time) { + content = content || {}; + content.invitations = { + time: data.invitations.time + }; + } + + // Add children wallets + if (data.children && data.children.length) { + // remember children count - need when data still encrypted, by method getChildrenCount() + content = content || {}; + content.childrenCount = data.children.length; + + secureContent = secureContent || {}; // Init th secured content + // Add children wallet + secureContent.children = _.map(data.children, function(wallet) { + return { + pubkey: wallet.data.pubkey, + uid: wallet.data.uid, + localName: wallet.data.localName + }; + }); + } + var contentStr = (content || secureContent) && JSON.stringify(angular.merge({}, content||{}, secureContent||{})); + + // Not encryption (or nothing to secure content): store without encryption + if (!useEncryption || !secureContent) { + return $q.all([ + sessionStorage.put(storageKey, null), // clear session storage (not used if no encryption) + localStorage.put(storageKey, contentStr || null) + ]); + } + + // Encryption is enable, but user not auth: use the session storage + // (and keep the local storage value) + if (!isAuth()) { + return sessionStorage.put(storageKey, contentStr||null); + } + + return $q.all([ + // Get a unique nonce + CryptoUtils.util.random_nonce(), + // Get box keypair + CryptoUtils.box.keypair.fromSignKeypair(data.keypair), + // Put also (without encryption) in the session storage + sessionStorage.put(storageKey, contentStr || null) + ]) + .then(function(res) { + var nonce = res[0]; + var keypair = res[1]; + + return CryptoUtils.box.pack(JSON.stringify(secureContent), nonce, keypair.boxPk, keypair.boxSk) + .then(function(cypherContent) { + content = angular.merge(content||{}, { + encryptedData: { + nonce: CryptoUtils.util.encode_base58(nonce), + content: cypherContent + } + }); + //console.debug("[wallet] Storing with encryption: ", content); + return localStorage.put(storageKey, JSON.stringify(content)); + }); + }); + }, + restore = function() { return $q.all([ sessionStorage.get(constants.STORAGE_SECKEY), @@ -388,6 +550,8 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se var uid = res[2]; if (!pubkey || pubkey == 'null') return; + console.debug('[wallet] Restore {' + pubkey.substring(0, 8) + '} from local storage'); + var keypair; if (seckey && seckey.length && seckey != 'null') { try { @@ -396,7 +560,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se signSk: CryptoUtils.util.decode_base58(seckey) }; } - catch(err) { + catch (err) { console.warn('[wallet] Secret key restoration failed: ', err); keypair = undefined; } @@ -406,60 +570,130 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se data.uid = uid && uid != 'null' ? uid : undefined; data.keypair = keypair || {signPk: undefined, signSk: undefined}; - console.debug('[wallet] Restore \'{0}\' from local storage.'.format(pubkey.substring(0,8))); + // Get pubkey's data + return restoreData(); + }) - // Call extend api - return api.data.raisePromise.login(data); + .then(function() { + // Successful restored: raise API events + if (isAuth()) { + return $q.all([ + api.data.raisePromise.login(data), + checkAuthIdle(true), + api.data.raisePromise.auth(data) + ]) + .catch(function(err) { + console.warn('Error during extension call [wallet.api.data.on.auth]', err); + // continue + }); + } + else if (isLogin()) { + return api.data.raisePromise.login(data) + .catch(function(err) { + console.warn('Error during extension call [wallet.api.data.on.login]', err); + // continue + }); + } }) + .then(function(){ return data; }); }, + restoreData = function() { + if (!isLogin()) throw {message:'ERROR.NEED_LOGIN_FIRST'}; + if (isNew()) return $q.when(data); // Skip restore + // Get pubkey's data + return $q.all([ + sessionStorage.getObject(constants.STORAGE_DATA_PREFIX + data.pubkey), + localStorage.getObject(constants.STORAGE_DATA_PREFIX + data.pubkey) + ]) + // Apply data, first from the session storage, then from local storage + .then(function (res) { + var sessionStorageData = res[0]; + var localStorageData = res[1]; + if (sessionStorageData && sessionStorageData.children && sessionStorageData.children.length === localStorageData.childrenCount) { + return applyRestoredData(sessionStorageData) + .catch(function(err) { + console.error("[wallet] Failed to restore from the session storage ! Retrying from the local storage...", err); + // Retry using another storage + return applyRestoredData(localStorageData); + }); + } + return applyRestoredData(localStorageData); + }); + }, + + applyRestoredData = function(content) { + if (!content) return $q.when(); // skip + + // Apply children + if (content.children) { + var oldChildrenCount = data.childrenCount; + var oldChildren = removeAllChildrenWallets({ + stop: false, /*do not stop wallet*/ + store: false/*skip store*/ + }); + + try { + var pubkeys = {}; + _.forEach(content.children, function(child) { + if (!pubkeys[child.pubkey]) { // make sure wallet is unique by pubkey + pubkeys[child.pubkey] = true; + var wallet = getNewChildrenInstance(); + wallet.data.pubkey = child.pubkey; + wallet.data.localName = child.localName; + wallet.data.uid = child.uid; + addChildWallet(wallet, {store: false/*skip store*/}); + } + }); + delete content.children; + // childrenCount not need anymore + delete data.childrenCount; + } + catch(err) { + console.error("[wallet] Failed to restore children wallet.", err); + // Restore removed values + data.childrenCount = oldChildrenCount; + data.children = oldChildren; + return $q.reject({message:'ERROR.RESTORE_WALLET_LIST_FAILED'}); + } + + // Restoration succeed: stop old children + _.forEach(oldChildren||[], function(child) { + child.stop(); + }); + } + + // make sure to remove pubkey before copy + delete content.pubkey; + delete content.uid; + + // Copy to data + angular.merge(data, content); + + // If auth: open encrypted data + if (hasEncryptedData() && isAuth()) { + return openEncryptedData({store: false}) + .then(function(){ + return data; // Important: return the data + }); + } + + return $q.when(data); // Important: return the data + }, + getData = function() { return data; }, - loadRequirements = function() { + loadRequirements = function(withCache) { // Clean existing events cleanEventsByContext('requirements'); // Get requirements - return csWot.loadRequirements(data) - .then(function(){ - - if (!data.requirements.uid) return; - - // Get sigDate - var blockParts = data.requirements.blockUid.split('-', 2); - var blockNumber = parseInt(blockParts[0]); - var blockHash = blockParts[1]; - // Retrieve registration date - return BMA.blockchain.block({block: blockNumber}) - .then(function(block) { - data.sigDate = block.medianTime; - - // Check if self has been done on a valid block - if (!data.isMember && blockNumber !== 0 && blockHash !== block.hash) { - addEvent({type: 'error', message: 'ERROR.WALLET_INVALID_BLOCK_HASH', context: 'requirements'}); - console.debug("Invalid membership for uid={0}: block hash changed".format(data.uid)); - } - // Check if self expired - else if (!data.isMember && data.requirements.expired) { - addEvent({type: 'error', message: 'ERROR.WALLET_IDENTITY_EXPIRED', context: 'requirements'}); - console.debug("Identity expired for uid={0}.".format(data.uid)); - } - }) - .catch(function(err){ - // Special case for currency init (root block not exists): use now - if (err && err.ucode == BMA.errorCodes.BLOCK_NOT_FOUND && blockNumber === 0) { - data.sigDate = Math.trunc(new Date().getTime() / 1000); - } - else { - throw err; - } - }); - }); + return csWot.loadRequirements(data, withCache); }, loadTxAndSources = function(fromTime) { @@ -474,65 +708,126 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }); }, - // Generate events from requirements - addEvents = function() { + loadSources = function() { + return csTx.loadSources(data.pubkey) + .then(function(res){ + resetSources(); + angular.merge(data, res); + }) + .catch(function(err) { + resetSources(); + throw err; + }); + }, - // Add user events + /** + * Add user events (generate events from requirements) + */ + addEvents = function() { if (data.requirements.revoked) { - addEvent({type:'warn', message: 'ERROR.WALLET_REVOKED', context: 'requirements'}); + delete data.requirements.meta.invalid; + addEvent({type:'info', message: 'ERROR.WALLET_REVOKED', context: 'requirements'}); } else if (data.requirements.pendingRevocation) { + delete data.requirements.meta.invalid; addEvent({type:'pending', message: 'INFO.REVOCATION_SENT_WAITING_PROCESS', context: 'requirements'}); } + + // If not revoked else { - if (data.requirements.pendingMembership) { + if (!data.isMember && data.requirements.meta && data.requirements.meta.invalid) { + addEvent({type: 'error', message: 'ERROR.WALLET_INVALID_BLOCK_HASH', context: 'requirements'}); + console.debug("Invalid membership for uid={0}: block hash changed".format(data.uid)); + } + // Check if self expired + else if (!data.isMember && data.requirements.expired) { + addEvent({type: 'error', message: 'ERROR.WALLET_IDENTITY_EXPIRED', context: 'requirements'}); + console.debug("Identity expired for uid={0}.".format(data.uid)); + } + // Pending membership + else if (data.requirements.pendingMembership) { addEvent({type:'pending', message: 'ACCOUNT.WAITING_MEMBERSHIP', context: 'requirements'}); + + // Add a warning when out distanced + // (only if has enough certification - fix #808) + if (!data.requirements.needCertificationCount && data.requirements.outdistanced) { + addEvent({type:'warn', message: 'ACCOUNT.OUT_DISTANCED', context: 'requirements'}); + } } // If user has send a SELF, ask for membership - fix #625 else if (!data.requirements.needSelf && data.requirements.needMembership){ addEvent({type:'warn', message: 'ACCOUNT.NO_WAITING_MEMBERSHIP', context: 'requirements'}); } - if (data.requirements.needCertificationCount > 0) { - addEvent({type:'warn', message: 'ACCOUNT.WAITING_CERTIFICATIONS', messageParams: data.requirements, context: 'requirements'}); - } - if (data.requirements.willNeedCertificationCount > 0) { - addEvent({type:'warn', message: 'ACCOUNT.WILL_MISSING_CERTIFICATIONS', messageParams: data.requirements, context: 'requirements'}); - } + if (data.requirements.needRenew) { - addEvent({type:'warn', message: 'ACCOUNT.WILL_NEED_RENEW_MEMBERSHIP', messageParams: data.requirements, context: 'requirements'}); + // Still a member: WILL need renew + if (data.isMember && data.requirements.membershipExpiresIn > 0) { + addEvent({type:'warn', message: 'ACCOUNT.WILL_NEED_RENEW_MEMBERSHIP', messageParams: data.requirements, context: 'requirements'}); + } + // Fix #649: Not a member anymore, even if membership NOT expired, because membersjip cancelled for lack of certifications + else if (!data.isMember && data.requirements.membershipExpiresIn > 0 && data.requirements.needCertificationCount > 0) { + addEvent({type:'warn', message: 'ACCOUNT.NEED_RENEW_MEMBERSHIP_AFTER_CANCELLED', messageParams: data.requirements, context: 'requirements'}); + } + // Not a member anymore + else { + addEvent({type:'warn', message: 'ACCOUNT.NEED_RENEW_MEMBERSHIP', messageParams: data.requirements, context: 'requirements'}); + } } - else if (data.requirements.wasMember && data.requirements.needMembership) { - addEvent({type:'warn', message: 'ACCOUNT.NEED_RENEW_MEMBERSHIP', messageParams: data.requirements, context: 'requirements'}); + else + { + if (data.requirements.needCertificationCount > 0) { + addEvent({type:'info', message: 'ACCOUNT.WAITING_CERTIFICATIONS', messageParams: data.requirements, context: 'requirements'}); + // Add a help message, if user has never been a member + if (!data.requirements.wasMember) { + addEvent({ + type: 'help', + message: 'ACCOUNT.WAITING_CERTIFICATIONS_HELP', + messageParams: data.requirements, + context: 'requirements' + }); + } + } + if (data.requirements.willNeedCertificationCount > 0) { + addEvent({type:'warn', message: 'ACCOUNT.WILL_MISSING_CERTIFICATIONS', messageParams: data.requirements, context: 'requirements'}); + } + if (data.requirements.wasMember && data.requirements.needMembership) { + addEvent({type:'warn', message: 'ACCOUNT.NEED_RENEW_MEMBERSHIP', messageParams: data.requirements, context: 'requirements'}); + } + // Add a warning when out distanced - fix #777 + if (!data.requirements.needCertificationCount && !data.requirements.willNeedCertificationCount && data.requirements.outdistanced) { + addEvent({type:'warn', message: 'ACCOUNT.OUT_DISTANCED', context: 'requirements'}); + } } } }, loadSigStock = function() { - return $q(function(resolve, reject) { - // Get certified by, then count written certification - BMA.wot.certifiedBy({pubkey: data.pubkey}) - .then(function(res){ - data.sigStock = !res.certifications ? 0 : res.certifications.reduce(function(res, cert) { - return cert.written === null ? res : res+1; - }, 0); - resolve(); - }) - .catch(function(err) { - if (!!err && err.ucode == BMA.errorCodes.NO_MATCHING_MEMBER) { - data.sigStock = 0; - resolve(); // not found - } - else { - reject(err); - } - }); - }); + // Get certified by, then count written certification + return BMA.wot.certifiedBy({pubkey: data.pubkey}) + .then(function(res){ + data.sigStock = !res.certifications ? 0 : res.certifications.reduce(function(res, cert) { + return cert.written === null ? res : res+1; + }, 0); + }) + .catch(function(err) { + if (!!err && err.ucode == BMA.errorCodes.NO_MATCHING_MEMBER) { + data.sigStock = 0; + } + /*FIXME: workaround for Duniter issue #1309 */ + else if (!!err && err.ucode == 1002) { + console.warn("[wallet-service] Detecting Duniter issue #1309 ! Applying workaround... "); + data.sigStock = 0; + } + else { + throw err; + } + }); }, loadData = function(options) { var alertIfUnusedWallet = !csCurrency.data.initPhase && (!csSettings.data.wallet || csSettings.data.wallet.alertIfUnusedWallet) && - !data.loaded && (!options || !options.minData); + !data.loaded && (!options || !options.minData || !options.silent); // Make sure to load once at a time if (loadPromise) { @@ -601,13 +896,19 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return $q.all([ // Get requirements - loadRequirements(), + loadRequirements(true) + .then(function(data) { + if (data.requirements && (data.requirements.isMember || data.requirements.wasMember)) { + // Load sigStock + return loadSigStock(); + } + else { + data.sigStock = 0; + } + }), // Get TX and sources - loadTxAndSources(), - - // Load sigStock - loadSigStock() + loadTxAndSources() ]) .then(function() { @@ -633,7 +934,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se loadMinData = function(options) { options = options || {}; options.requirements = angular.isDefined(options.requirements) ? options.requirements : - (!data.requirements || angular.isUndefined(data.requirements.needSelf)); + (!data.requirements.loaded || angular.isUndefined(data.requirements.needSelf)); if (!options.requirements) { return $q.when(data); } @@ -657,7 +958,12 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }; // Force some load (requirements) if not already loaded - options.requirements = angular.isDefined(options.requirements) ? options.requirements : angular.isDefined(data.requirements.needSelf); + options.requirements = angular.isDefined(options.requirements) ? options.requirements : !data.requirements.loaded; + + // Force sources when TX enable + if (angular.isUndefined(options.sources) && options.tx && options.tx.enable) { + options.sources = true; + } var jobs = []; @@ -667,29 +973,43 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se cleanEventsByContext('requirements'); jobs.push( - loadRequirements() + loadRequirements(true) // Add wallet events .then(addEvents) ); } - if (options.sources || (options.tx && options.tx.enable)) { + if (options.sources && (!options.tx || options.tx.enable)) { // Get TX and sources jobs.push(loadTxAndSources(options.tx ? options.tx.fromTime: undefined)); } + else if (options.sources && (options.tx && !options.tx.enable)) { + // Get sources (no TX) + jobs.push(loadSources()); + } + // Load sigStock if (options.sigStock) jobs.push(loadSigStock()); return (jobs.length ? $q.all(jobs) : $q.when()) - .then(function(){ - // API extension (after all other jobs) - return api.data.raisePromise.load(data); - }) - .then(function(){ - return data; - }); + .then(function(){ + // Skip api + if (angular.isDefined(options.api) && !options.api) return data; + + // API extension (after all other jobs) + return api.data.raisePromise.load(data) + .then(function(){ + + // Compute if full loaded + if (!data.loaded) { + data.loaded = data.requirements.loaded && data.sources; + } + + return data; + }); + }); }, setSelf = function(uid, blockUid){ @@ -712,8 +1032,10 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se // Refresh requirements return refreshData({requirements: true, sigStock: true}) - // Store (to remember the new uid) - .then(store); + .then(function() { + // Store (to remember the new uid) + return store({skipData: true}); + }); }, isBase = function(amount, base) { @@ -748,8 +1070,11 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se var sources = []; var minBase = filterBase; var maxBase = filterBase; - _.find(data.sources, function(source) { - if (!source.consumed && source.base == filterBase){ + _.find(data.sources || [], function(source) { + if (!source.consumed && source.base === filterBase && + // Filter on simple SIG output condition - fix #845 + BMA.regexp.TX_OUTPUT_SIG.exec(source.conditions) + ) { sourcesAmount += powBase(source.amount, source.base); sources.push(source); } @@ -782,16 +1107,16 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se /** * Send a new transaction */ - transfer = function(destPub, amount, comments, useRelative) { + transfer = function(destPub, amount, comments, useRelative, restPub, block) { return $q.all([ getKeypair(), csCurrency.get(), - csCurrency.blockchain.current() + block && $q.when(block) || csCurrency.blockchain.current() ]) .then(function(res) { var keypair = res[0]; var currency = res[1]; - var block = res[2]; + block = res[2]; if (!BMA.regexp.PUBKEY.test(destPub)){ throw {message:'ERROR.INVALID_PUBKEY'}; } @@ -801,6 +1126,9 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se if (!isLogin()){ throw {message:'ERROR.NEED_LOGIN_FIRST'}; } + if (destPub === data.pubkey){ + throw {message:'ERROR.SAME_TX_RECIPIENT'}; + } if (!amount) { throw {message:'ERROR.AMOUNT_REQUIRED'}; } @@ -878,21 +1206,23 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se } // Send tx - return createAndSendTx(currency, block, keypair, destPub, amount, inputs, comments, logs) + return createAndSendTx(currency, block, keypair, destPub, amount, inputs, comments, restPub||data.pubkey, logs) .then(function(res) { - data.balance -= amount; + data.balance -= res.amount; + if (data.balance < 0) data.balance = 0; // fix #712 _.forEach(inputs.sources, function(source) { source.consumed=true; }); // Add new sources if (res && res.sources.length) { + console.debug("[wallet-service] New sources to be add after the TX: ", res.sources); addSources(res.sources); } // Add TX to pendings var pendingTx = { - time: (Math.floor(moment().utc().valueOf() / 1000)), + time: csCurrency.date.now(), amount: -amount, pubkey: destPub, comment: comments, @@ -922,7 +1252,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se console.debug('[wallet] TX rejected by node with error [{0}]. Reloading sources then retry...'.format(err.message||'Source already consumed')); return $timeout(loadTxAndSources, 500) .then(function() { - return transfer(destPub, amount, comments, useRelative); + return transfer(destPub, amount, comments, useRelative, restPub, block); }); } @@ -958,6 +1288,33 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }); }, + /** + * Send a WIF wallet + */ + transferAll = function(destPub, amount, comments, useRelative, restPub) { + if (!isLogin()) return $q.reject({message:'ERROR.NEED_LOGIN_FIRST'}); + + if (!restPub || destPub == restPub) { + return $q.reject({message: "Could not have same pubkey for 'destPub' and 'restPub'"}); + } + + return csCurrency.blockchain.lastValid() + .then(function(block) { + console.debug("[wallet] Using last valid block as TX reference (to avoid network fork): ", block); + + return transfer(destPub, amount, comments, useRelative, restPub, block) + .then(function() { + // If more money: transfer all to restPub + if (data.balance > 0 && restPub) { + console.debug("[wallet] Wallet has some more money: transfering fund to [{0}]".format(restPub.substring(0,8))); + return transfer(restPub, data.balance, undefined/*comments*/, false/*useRelative*/, restPub, block); + } + }); + + }); + + }, + /** * Create TX doc and send it * @param block the current block @@ -967,7 +1324,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se * @param comments * @return the hash of the sent TX */ - createAndSendTx = function(currency, block, keypair, destPub, amount, inputs, comments, logs) { + createAndSendTx = function(currency, block, keypair, destPub, amount, inputs, comments, restPub, logs) { // Make sure a TX in compact mode has no more than 100 lines (fix #118) // (If more than 100 lines, send to TX to himself first, then its result as sources for the final TX) @@ -988,7 +1345,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }); // Send inputs first slice - return createAndSendTx(currency, block, keypair, data.pubkey/*to himself*/, firstSlice.amount, firstSlice, undefined/*comment not need*/, logs) + return createAndSendTx(currency, block, keypair, data.pubkey/*to himself*/, firstSlice.amount, firstSlice, undefined/*comment not need*/, data.pubkey/*rest to himself*/, logs) .then(function(res) { _.forEach(firstSlice.sources, function(source) { source.consumed=true; @@ -1004,11 +1361,11 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se _.forEach(secondSlice.sources, function(source) { if (source.base < secondSlice.minBase) secondSlice.minBase = source.base; if (source.base > secondSlice.maxBase) secondSlice.maxBase = source.base; - secondSlice.amount += source.amount; + secondSlice.amount += powBase(source.amount, source.base); }); // Send inputs second slice (recursive call) - return createAndSendTx(currency, block, keypair, destPub, amount, secondSlice, comments, logs); + return createAndSendTx(currency, block, keypair, destPub, amount, secondSlice, comments, restPub, logs); }); } @@ -1055,19 +1412,22 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se rest = inputs.amount - amount; outputBase = inputs.maxBase; } - // Outputs to himself + // Outputs to restPub while(rest > 0) { outputAmount = truncBase(rest, outputBase); rest -= outputAmount; if (outputAmount > 0) { outputAmount = outputBase === 0 ? outputAmount : outputAmount / Math.pow(10, outputBase); - tx += outputAmount +':'+outputBase+':SIG('+data.pubkey+')\n'; - newSources.push({ - type: 'T', - noffset: outputOffset, - amount: outputAmount, - base: outputBase - }); + tx += outputAmount +':'+outputBase+':SIG('+restPub+')\n'; + // If rest to himself: add new sources + if (data.pubkey === restPub) { + newSources.push({ + type: 'T', + noffset: outputOffset, + amount: outputAmount, + base: outputBase + }); + } outputOffset++; } outputBase--; @@ -1110,6 +1470,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se output.pending = true; }); return { + amount: (data.pubkey === destPub) ? 0 : ((data.pubkey === restPub) ? amount : inputs.amount), tx: signedTx, hash: txHash, sources: newSources @@ -1124,7 +1485,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se if (!uid || !blockUid) { throw {message: 'ERROR.WALLET_HAS_NO_SELF'}; } - if (data.requirements && data.requirements.expired) { + if (data.requirements.expired) { throw {message: 'ERROR.WALLET_IDENTITY_EXPIRED'}; } @@ -1153,7 +1514,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return $q.all([ getKeypair(), csCurrency.get(), - csCurrency.blockchain.current() + csCurrency.blockchain.lastValid() ]) // Create identity document .then(function(res) { @@ -1171,7 +1532,10 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se .then(function () { if (!!needToLoadRequirements) { // Refresh membership data (if need) - return loadRequirements(); + return loadRequirements(false/*no cache*/) + + // Add wallet events + .then(addEvents); } else { data.uid = uid; @@ -1195,7 +1559,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return $q.all([ getKeypair(), - csCurrency.blockchain.current() + csCurrency.blockchain.lastValid() ]) .then(function(res) { var keypair = res[0]; @@ -1219,7 +1583,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }) .then(function() { return $timeout(function() { - return loadRequirements(); + return loadRequirements(false /*no cache*/); }, 1000); // waiting for node to process membership doc }) @@ -1311,20 +1675,17 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se getCryptedId = function(record){ return getkeypairSaveId(record) - .then(function() { - return CryptoUtils.util.random_nonce(); - }) + .then(CryptoUtils.util.random_nonce) .then(function(nonce) { - record.nonce = nonce; - return CryptoUtils.box.pack(record.salt, record.nonce, record.keypair.boxPk, record.keypair.boxSk); - }) - .then(function (cypherSalt) { - record.salt = cypherSalt; - return CryptoUtils.box.pack(record.pwd, record.nonce, record.keypair.boxPk, record.keypair.boxSk); + record.nonce = CryptoUtils.util.encode_base58(nonce); + return $q.all([ + CryptoUtils.box.pack(record.salt, nonce, record.keypair.boxPk, record.keypair.boxSk), + CryptoUtils.box.pack(record.pwd, nonce, record.keypair.boxPk, record.keypair.boxSk) + ]); }) - .then(function (cypherPwd) { - record.pwd = cypherPwd; - record.nonce = CryptoUtils.util.encode_base58(record.nonce); + .then(function (res) { + record.salt = res[0]; + record.pwd = res[1]; return record; }); }, @@ -1373,46 +1734,35 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return getSaveIDDocument(record) .then(function(saveId) { var saveIdFile = new Blob([saveId], {type: 'text/plain; charset=utf-8'}); - FileSaver.saveAs(saveIdFile, 'saveID-{0}.txt'.format(data.pubkey.substring(0,6))); + FileSaver.saveAs(saveIdFile, '{0}-recover_ID.txt'.format(data.pubkey.substring(0,8))); }); }, - getKeyFileDocument =function(format) { - - var document; - switch(format) { - case "PubSec" : - document = "Type: PubSec\n" + - "Version: 1\n" + - "pub: " + data.pubkey + "\n" + - "sec: " + CryptoUtils.base58.encode(data.keypair.signSk) + "\n"; - break; - case "WIF" : - document = "Type: WIF\n" + - "Version: 1\n" + - "Data: " + CryptoUtils.wif_v1_from_keypair(data.keypair)+ "\n"; - break; - case "EWIF" : - document = "Type: EWIF\n" + - "Version: 1\n" + - "Data: " + CryptoUtils.ewif_v1_from_keypair(data.keypair, "bonjour") + "\n"; - break; - default: - return Promise.reject("Unknown keyfile format: " + format); - } - if (document) { - return Promise.resolve(document); - } - }, downloadKeyFile = function(format){ - if (!isAuth()) return Promise.reject('user not authenticated'); + if (!isAuth()) return $q.reject('user not authenticated'); return $q.all([ csCurrency.get(), - getKeyFileDocument(format) + csCrypto.keyfile.generateContent(data.keypair, + { + type: format, + password: function() { + UIUtils.loading.hide(); + return Modals.showPassword({ + title: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.TITLE', + subTitle: 'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.HELP' + }) + .then(function(password) { + return UIUtils.loading.show(10) + .then(function(){ + return password; + }); + }); + } + }) ]) .then(function(res) { var currency = res[0]; @@ -1488,7 +1838,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se .then(function() { return $timeout(function() { - return loadRequirements(); + return loadRequirements(false/*no cache*/); }, 1000); // waiting for node to process membership doc }) @@ -1515,7 +1865,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se .then(function(res) { if (isLogin()) { return $timeout(function () { - return loadRequirements(); + return loadRequirements(false/*no cache*/); }, 1000) // waiting for node to process membership doc // Add wallet events @@ -1539,24 +1889,24 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }, downloadRevocation = function(){ - return $q.all([ - csCurrency.get(), - getRevocationDocument() - ]) - .then(function(res) { - var currency = res[0]; - var revocation = res[1]; - var revocationFile = new Blob([revocation], {type: 'text/plain; charset=utf-8'}); - return $translate('ACCOUNT.SECURITY.REVOCATION_FILENAME', { - uid: data.uid, - currency: currency.name, - pubkey: data.pubkey - }) - .then(function (fileName) { - FileSaver.saveAs(revocationFile, fileName); - }); + return $q.all([ + csCurrency.get(), + getRevocationDocument() + ]) + .then(function(res) { + var currency = res[0]; + var revocation = res[1]; + var revocationFile = new Blob([revocation], {type: 'text/plain; charset=utf-8'}); + return $translate('ACCOUNT.SECURITY.REVOCATION_FILENAME', { + uid: data.uid, + currency: currency.name, + pubkey: data.pubkey + }) + .then(function (fileName) { + FileSaver.saveAs(revocationFile, fileName); }); - }, + }); + }, cleanEventsByContext = function(context){ data.events = data.events.reduce(function(res, event) { @@ -1565,6 +1915,169 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se },[]); }, + /* -- children wallets -- */ + + setParentWallet = function(parentWallet) { + listeners = listeners || []; + var listener; + _.forEach(['load', 'reset'], function(method) { + listener = api.data.on[method]($rootScope, function(data, deferred) { + deferred = deferred || $q.defer(); + parentWallet.api.data.raisePromise[method](data) + .then(deferred.resolve) + .catch(deferred.reject); + return deferred.promise; + }, this); + listeners.push(listener); + }); + + // Unauth when parent wallet unauth + listener = parentWallet.api.data.on.unauth($rootScope, function() { + if (isAuth()) unauth(); + }, this); + listeners.push(listener); + }, + + createNewChildWallet = function(options) { + var walletId = getChildrenWalletCount()+1; + var wallet = service.instance(walletId); + addChildWallet(wallet, options); + return wallet; + }, + + addChildWallet = function(wallet, options) { + // Link to parent + wallet.children.setParent(exports); // = link to self wallet + + data.children = data.children || []; + data.children.push(wallet); + + // Store (store children locally) + if (!options || angular.isUndefined(options.store) || options.store) { + return storeData(); + } + return $q.when(); + }, + + removeAllChildrenWallets = function(options) { + + // stop/unauth all existing wallets + if (!options || options.stop) { + _.forEach(data.children || [], function(wallet){ + wallet.stop(); + }); + } + var removedChildren = data.children.splice(0, data.children.length); + + // Store (store children locally) + if (!options || angular.isUndefined(options.store) || options.store) { + return storeData(); + } + return removedChildren; + + }, + + removeChildWalletById = function(id, options) { + data.children = data.children || []; + var childIndex = _.findIndex(data.children, function(child) {return child.id == id;}); + if (childIndex === -1) { + console.warn('[wallet] Unable to remove child wallet {'+id+'} (not found)'); + return; + } + // Remove the wallet, and return it + var wallet = data.children.splice(childIndex, 1)[0]; + + // Force to stop without calling api + wallet.stop(); + + // Store (store children locally) + if (!options || angular.isUndefined(options.store) || options.store) { + return storeData(); + } + }, + + getChildWalletById = function(id) { + return (id !== 'default') && _.find(data.children|| [], function(child) {return child.id == id;}) || undefined; + }, + + getChildWalletByPubkey = function(pubkey) { + return _.find(data.children|| [], function(child) {return child.isUserPubkey(pubkey);}); + }, + + hasChildrenWithPubkey = function(pubkey) { + return !!getChildWalletByPubkey(pubkey); + }, + + getChildrenWalletCount = function() { + return angular.isDefined(data.childrenCount) ? data.childrenCount : (data.children && data.children.length || 0); + }, + + getNewChildrenInstance = function() { + // Return max(id) + 1 + var walletId = (data.children && data.children.reduce(function(res, wallet) { + return Math.max(res, wallet.id); + }, 0) || data.childrenCount || 0 )+ 1; + return service.instance(walletId, BMA); + }, + + getAllChildrenWallet = function() { + return openEncryptedData() + .then(function() { + return data.children; + }); + }, + + downloadChildrenWalletFile = function() { + return $q.all([ + getAllChildrenWallet(), + csCurrency.get() + ]) + .then(function(res) { + var children = res[0]; + var currency = res[1]; + var content = (children||[]).reduce(function(res, wallet) { + return res + [wallet.data.pubkey, wallet.data.uid, wallet.data.localName||wallet.data.name].join('\t') + '\n'; + }, ''); + var file = new Blob([content], {type: 'text/plain; charset=utf-8'}); + return $translate('ACCOUNT.WALLET_LIST.EXPORT_FILENAME', { + pubkey: data.pubkey, + currency: currency.name, + }) + .then(function (fileName) { + FileSaver.saveAs(file, fileName); + }); + }); + }, + + /* -- END children wallets -- */ + + openEncryptedData = function(options) { + if (!hasEncryptedData()) return $q.when(); + if (!isAuth()) return auth().then(openEncryptedData); // Force auth if need + + // Open encrypted data + return CryptoUtils.box.keypair.fromSignKeypair(data.keypair) + .then(function(keypair) { + var nonce = CryptoUtils.util.decode_base58(data.encryptedData.nonce); + return CryptoUtils.box.open(data.encryptedData.content, nonce, keypair.boxPk, keypair.boxSk); + }) + // Then apply + .then(function(content) { + data.encryptedData = null; // reset encrypted data + var promise = applyRestoredData(JSON.parse(content)); + + // Store (store data into session storage) + if (!options || angular.isUndefined(options.store) || options.store) { + promise.then(function() { + return storeData(); + }); + } + + return promise; + }) + ; + }, + /** * De-serialize from JSON string */ @@ -1620,39 +2133,107 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }); }, - checkAuthIdle = function(isAuth) { - isAuth = angular.isDefined(isAuth) ? isAuth : isAuth(); - var enable = isAuth && csSettings.data.keepAuthIdle > 0 && csSettings.data.keepAuthIdle != csSettings.constants.KEEP_AUTH_IDLE_SESSION; - var changed = (enableAuthIdle != enable); + checkAuthIdle = function(isAuthResult) { + isAuthResult = angular.isDefined(isAuthResult) ? isAuthResult : isAuth(); + var newEnableAuthIdle = isAuthResult && settings.keepAuthIdle > 0 && settings.keepAuthIdle != csSettings.constants.KEEP_AUTH_IDLE_SESSION; + var changed = (enableAuthIdle != newEnableAuthIdle); // need start/top watching if (changed) { // start idle - if (enable) { - console.debug("[wallet] Start idle (delay: {0}s)".format(csSettings.data.keepAuthIdle)); - Idle.setIdle(csSettings.data.keepAuthIdle); + if (newEnableAuthIdle) { + console.debug("[wallet] Start idle (delay: {0}s)".format(settings.keepAuthIdle)); + Idle.setIdle(settings.keepAuthIdle); Idle.watch(); } - // stop idle, if need + // stop idle, if was enable else if (enableAuthIdle){ console.debug("[wallet] Stop idle"); Idle.unwatch(); } - enableAuthIdle = enable; + enableAuthIdle = newEnableAuthIdle; } // if idle time changed: apply it - else if (enable && Idle.getIdle() !== csSettings.data.keepAuthIdle) { - console.debug("[idle] Updating auth idle (delay: {0}s)".format(csSettings.data.keepAuthIdle)); - Idle.setIdle(csSettings.data.keepAuthIdle); + else if (newEnableAuthIdle && Idle.getIdle() !== settings.keepAuthIdle) { + console.debug("[idle] Updating auth idle (delay: {0}s)".format(settings.keepAuthIdle)); + Idle.setIdle(settings.keepAuthIdle); + } + + // Make sure to store seckey, in the session storage for secret key -fix #372 + var storeSecKey = isAuthResult && settings.keepAuthIdle == csSettings.constants.KEEP_AUTH_IDLE_SESSION && true; + if (storeSecKey) { + sessionStorage.put(constants.STORAGE_SECKEY, CryptoUtils.util.encode_base58(data.keypair.signSk)); + } + // Make sure to clean previous seckey, if exists in session storage + else if (changed) { + sessionStorage.put(constants.STORAGE_SECKEY, null); } }; + function getWalletSettings(settings) { + return { + useLocalStorage: settings.useLocalStorage, + useLocalStorageEncryption: settings.useLocalStorageEncryption, + rememberMe: settings.rememberMe, + keepAuthIdle: settings.keepAuthIdle + }; + } + + function onSettingsChanged(allSettings) { + var newSettings = getWalletSettings(allSettings); + var hasChanged = !angular.equals(settings, newSettings); + if (!hasChanged) return; // skip + + var useEncryptionChanged = !angular.equals(settings.useLocalStorageEncryption, newSettings.useLocalStorageEncryption); + var useStorageChanged = !angular.equals(settings.useLocalStorage, newSettings.useLocalStorage) || useEncryptionChanged; + var keepAuthIdleChanged = !angular.equals(settings.keepAuthIdle, newSettings.keepAuthIdle); + + settings = newSettings; + + if (keepAuthIdleChanged) { + checkAuthIdle(); + } + + // Local storage option changed + if (useStorageChanged) { + + // If disabled, then reset the store + if (!settings.useLocalStorage) { + resetStore(data.pubkey); + } + // If storage enable + else { + // Store login data + return store() + .then(function() { + + // Encryption enable: auth before saving data + if (data.childrenCount > 0 && useEncryptionChanged && settings.useLocalStorageEncryption) { + return auth({minData: true, silent: true}) + .catch(function(err){ + // user not auth: revert encryption to false + if (err === 'CANCELLED') { + csSettings.apply({useLocalStorageEncryption: false}); + return csSettings.store(); + } + else { + throw err; + } + }); + } + }) + + // Store other data (children wallet, ...) + .then(storeData); + } + } + } + function addListeners() { listeners = [ // Listen if settings changed - csSettings.api.data.on.changed($rootScope, store, this), - csSettings.api.data.on.changed($rootScope, checkAuthIdle, this), + csSettings.api.data.on.changed($rootScope, onSettingsChanged, this), // Listen if node changed BMA.api.node.on.restart($rootScope, restart, this) ]; @@ -1660,6 +2241,11 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se $rootScope.$on('IdleStart', unauth); } + function addListener(listener) { + listeners = listeners || []; + listeners.push(listener); + } + function removeListeners() { _.forEach(listeners, function(remove){ remove(); @@ -1689,10 +2275,13 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se options.restore = angular.isDefined(options.restore) ? options.restore : (id === 'default'); console.debug('[wallet] Starting...'); - var now = new Date().getTime(); + var now = Date.now(); startPromise = $q.all([ - csSettings.ready(), + csSettings.ready() + .then(function() { + settings = getWalletSettings(csSettings.data); + }), csCurrency.ready(), BMA.ready() ]); @@ -1704,7 +2293,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se startPromise.then(function() { addListeners(); - console.debug('[wallet] Started in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[wallet] Started in ' + (Date.now() - now) + 'ms'); started = true; startPromise = null; @@ -1725,6 +2314,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se api.registerEvent('data', 'load'); api.registerEvent('data', 'logout'); api.registerEvent('data', 'reset'); + api.registerEvent('data', 'store'); api.registerEvent('error', 'send'); @@ -1738,7 +2328,17 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se // init data resetData(true); - return { + // Override default store/restore function, when not the 'default' wallet + if (id !== "default") { + //start = $q.when; + //started = true; + store = $q.when; + restore = $q.when; + restoreData = $q.when; + //checkAuthIdle = function(){}; + } + + exports = { id: id, data: data, ready: ready, @@ -1758,14 +2358,24 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se return data.isMember; }, isDataLoaded : isDataLoaded, + isDefault: isDefault, isNeverUsed: isNeverUsed, isNew: isNew, isUserPubkey: isUserPubkey, getData: getData, loadData: loadData, refreshData: refreshData, + // internal + internal: { + addListener: addListener, + removeListeners: removeListeners + }, + // local storage + store: store, + storeData: storeData, // store children wallet, readTime, etc. // operations transfer: transfer, + transferAll: transferAll, self: self, revoke: revoke, revokeWithFile: revokeWithFile, @@ -1783,11 +2393,25 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se add: addEvent, cleanByContext: cleanEventsByContext }, + children: { + create: createNewChildWallet, + add: addChildWallet, + remove: removeChildWalletById, + get: getChildWalletById, + getByPubkey: getChildWalletByPubkey, + all: getAllChildrenWallet, + setParent: setParentWallet, + count: getChildrenWalletCount, + hasPubkey: hasChildrenWithPubkey, + instance: getNewChildrenInstance, + downloadFile: downloadChildrenWalletFile + }, api: api }; + return exports; } - var service = factory('default', BMA); + service = factory('default', BMA); service.instance = factory; return service; diff --git a/assets/www/js/services/wot-services.js b/assets/www/js/services/wot-services.js index eaf473c83121e9a140ee1b9a6aa7fdfc26358453..1ddfd428bde89a793e2f95bd4e38992a7302649e 100644 --- a/assets/www/js/services/wot-services.js +++ b/assets/www/js/services/wot-services.js @@ -2,14 +2,16 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.crypto.services', 'cesium.utils.services', 'cesium.settings.services']) -.factory('csWot', function($q, $timeout, BMA, Api, CacheFactory, csConfig, csCurrency, csSettings, csCache) { +.factory('csWot', function($rootScope, $q, $timeout, BMA, Api, CacheFactory, csConfig, csCurrency, csSettings, csCache) { 'ngInject'; function factory(id) { var api = new Api(this, "csWot-" + id), - identityCache = csCache.get('csWot-idty-', csCache.constants.SHORT), + cachePrefix = 'csWot-', + identityCache = csCache.get(cachePrefix + 'idty-', csCache.constants.MEDIUM), + requirementsCache = csCache.get(cachePrefix + 'requirements-', csCache.constants.MEDIUM), // Add id, and remove duplicated id _addUniqueIds = function(idties) { @@ -58,11 +60,15 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c _resetRequirements = function(data) { data.requirements = { + loaded: false, + meta: {}, + hasSelf: false, needSelf: true, needMembership: true, canMembershipOut: false, needRenew: false, pendingMembership: false, + isMember: false, wasMember: false, certificationCount: 0, needCertifications: false, @@ -73,30 +79,32 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c data.blockUid = null; data.isMember = false; data.sigDate = null; + data.hasSelf = false; }, _fillRequirements = function(requirements, currencyParameters) { // Add useful custom fields - requirements.hasSelf = true; - requirements.needSelf = false; + requirements.hasSelf = !!requirements.meta.timestamp; + requirements.needSelf = !requirements.hasSelf || requirements.meta.invalid; requirements.wasMember = angular.isDefined(requirements.wasMember) ? requirements.wasMember : false; // Compat with Duniter 0.9 - requirements.needMembership = (requirements.membershipExpiresIn <= 0 && requirements.membershipPendingExpiresIn <= 0 && !requirements.wasMember); - requirements.needRenew = (!requirements.needMembership && + requirements.needMembership = (!requirements.revoked && requirements.membershipExpiresIn <= 0 && requirements.membershipPendingExpiresIn <= 0 && !requirements.wasMember); + requirements.needRenew = (!requirements.needMembership && !requirements.revoked && requirements.membershipExpiresIn <= csSettings.data.timeWarningExpireMembership && requirements.membershipPendingExpiresIn <= 0) || - (requirements.wasMember && requirements.membershipExpiresIn === 0 && + (requirements.wasMember && !requirements.revoked && requirements.membershipExpiresIn === 0 && requirements.membershipPendingExpiresIn === 0); - requirements.canMembershipOut = (requirements.membershipExpiresIn > 0); - requirements.pendingMembership = (requirements.membershipExpiresIn <= 0 && requirements.membershipPendingExpiresIn > 0); - requirements.isMember = (requirements.membershipExpiresIn > 0); + requirements.canMembershipOut = (!requirements.revoked && requirements.membershipExpiresIn > 0); + requirements.pendingMembership = (!requirements.revoked && requirements.membershipExpiresIn <= 0 && requirements.membershipPendingExpiresIn > 0); + requirements.isMember = (!requirements.revoked && requirements.membershipExpiresIn > 0); requirements.blockUid = requirements.meta.timestamp; // Force certification count to 0, is not a member yet - fix #269 - requirements.certificationCount = (requirements.isMember && requirements.certifications) ? requirements.certifications.length : 0; + requirements.certificationCount = ((requirements.isMember || (requirements.wasMember && !requirements.expired)) && requirements.certifications) ? requirements.certifications.length : 0; requirements.willExpireCertificationCount = requirements.certifications ? requirements.certifications.reduce(function(count, cert){ return count + (cert.expiresIn <= csSettings.data.timeWarningExpire ? 1 : 0); }, 0) : 0; requirements.willExpire = requirements.willExpireCertificationCount > 0; requirements.pendingRevocation = !requirements.revoked && !!requirements.revocation_sig; + //requirements.outdistanced = requirements.outdistanced; // outdistanced is always present in requirement - see #777 // Fix pending certifications count - Fix #624 if (!requirements.isMember && !requirements.wasMember) { @@ -117,28 +125,90 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c (requirements.certificationCount - requirements.willExpireCertificationCount) < currencyParameters.sigQty) ? (currencyParameters.sigQty - requirements.certificationCount + requirements.willExpireCertificationCount) : 0; + // Mark as loaded - need by csWallet.isDataLoaded() + requirements.loaded = true; + return requirements; }, - loadRequirements = function(data) { - if (!data || (!data.pubkey && !data.uid)) return $q.when(data); + _fillIdentitiesMeta = function(identities) { + if (!identities) return $q.when(identities); + + var blocks = []; + _.forEach(identities, function(identity) { + var blockUid = identity.meta.timestamp.split('-', 2); + identity.meta.number = parseInt(blockUid[0]); + identity.meta.hash = blockUid[1]; + identity.meta.sig = identity.meta.sig || identity.sig; + delete identity.sig; + blocks.push(identity.meta.number); + }); + + // Get identities blocks, to fill self and revocation time + return BMA.blockchain.blocks(_.uniq(blocks)) + .then(function(blocks) { + _.forEach(identities, function(identity) { + var block = _.findWhere(blocks, {number: identity.meta.number}); + identity.meta.time = block && block.medianTime; + + // Check if self has been done on a valid block + if (block && identity.meta.number !== 0 && identity.meta.hash !== block.hash) { + identity.meta.invalid = true; + } + }); + + return identities; + }) + .catch(function(err){ + // Special case for currency init (root block not exists): use now + if (err && err.ucode == BMA.errorCodes.BLOCK_NOT_FOUND) { + _.forEach(identities, function(identity) { + if (identity.number === 0) { + identity.meta.time = moment().utc().unix(); + } + }); + return identities; + } + else { + throw err; + } + }); + }, + + loadRequirements = function(inputData, withCache) { + if (!inputData || (!inputData.pubkey && !inputData.uid)) return $q.when(inputData); + + var cacheKey = inputData.pubkey||inputData.uid; + var data = (withCache !== false) ? requirementsCache.get(cacheKey) : null; + if (data) { + console.debug("[wot] Requirements " + cacheKey + " found in cache"); + // Update data with cache + angular.merge(inputData, data); + return $q.when(data); + } + data = {pubkey: inputData.pubkey, uid: inputData.uid}; + + var now = Date.now(); return $q.all([ // Get currency csCurrency.get(), + // Get requirements - BMA.wot.requirements({pubkey: data.pubkey||data.uid}) + BMA.wot.requirements({pubkey: data.pubkey||data.uid}, false/*no cache*/) + .then(function(res) { + return _fillIdentitiesMeta(res && res.identities); + }) ]) .then(function(res){ var currency = res[0]; + var identities = res[1]; - res = res[1]; - - if (!res.identities || !res.identities.length) return; + if (!identities || !identities.length) return; // Sort to select the best identity - if (res.identities.length > 1) { + if (identities.length > 1) { // Select the best identity, by sorting using this order // - same wallet uid // - is member @@ -149,101 +219,153 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c // max(count(certification) // else // max(membershipPendingExpiresIn) = must recent membership - res.identities = _.sortBy(res.identities, function(idty) { + identities = _.sortBy(identities, function(idty) { var score = 0; - score += (10000000000 * ((data.uid && idty.uid === data.uid) ? 1 : 0)); - score += (10000000000 * ((data.blockUid && idty.meta && idty.meta.timestamp === data.blockUid) ? 1 : 0)); - score += (1000000000 * (idty.membershipExpiresIn > 0 ? 1 : 0)); - score += (100000000 * (idty.membershipPendingExpiresIn > 0 ? 1 : 0)); - score += (10000000 * (!idty.expired ? 1 : 0)); - score += (1000000 * (!idty.outdistanced ? 1 : 0)); - score += (100000 * (idty.wasMember ? 1 : 0)); + score += (1000000000000* ((data.uid && idty.uid === data.uid) ? 1 : 0)); + score += (100000000000 * (!idty.meta.invalid ? 1 : 0)); + score += (10000000000 * ((data.blockUid && idty.meta.timestamp && idty.meta.timestamp === data.blockUid) ? 1 : 0)); + score += (1000000000 * (idty.membershipExpiresIn > 0 ? 1 : 0)); + score += (100000000 * (idty.membershipPendingExpiresIn > 0 ? 1 : 0)); + score += (10000000 * (!idty.expired ? 1 : 0)); + score += (1000000 * (!idty.outdistanced ? 1 : 0)); + score += (100000 * (idty.wasMember ? 1 : 0)); var certCount = !idty.expired && idty.certifications ? idty.certifications.length : 0; - score += (1 * (certCount ? certCount : 0)); - score += (1 * (!certCount && idty.membershipPendingExpiresIn > 0 ? idty.membershipPendingExpiresIn/1000 : 0)); + score += (1 * (certCount ? certCount : 0)); + score += (1 * (!certCount && idty.membershipPendingExpiresIn > 0 ? idty.membershipPendingExpiresIn/1000 : 0)); return -score; }); - console.debug('[wot] Found {0} identities. Will selected the best one'.format(res.identities.length)); + console.debug('[wot] Found {0} identities (in requirements). Will selected the best one'.format(identities.length)); } // Select the first identity - var requirements = _fillRequirements(res.identities[0], currency.parameters); + data.requirements = _fillRequirements(identities[0], currency.parameters); - data.requirements = requirements; - data.pubkey = requirements.pubkey; - data.uid = requirements.uid; - data.isMember = requirements.isMember; - data.blockUid = requirements.blockUid; + // Copy some useful properties into data + data.pubkey = data.requirements.pubkey; + data.uid = data.requirements.uid; + data.isMember = data.requirements.isMember; + data.blockUid = data.requirements.meta && data.requirements.meta.timestamp; + data.hasSelf = data.requirements.hasSelf; + data.sigDate = data.requirements.meta && data.requirements.meta.time; // Prepare alternatives identities if any - if (!requirements.isMember && !requirements.wasMember && res.identities.length > 1) { - requirements.alternatives = res.identities.splice(1); - _.forEach(requirements.alternatives, function(requirements) { + if (!data.requirements.isMember && !data.requirements.wasMember && identities.length > 1) { + data.requirements.alternatives = identities.splice(1); + _.forEach(data.requirements.alternatives, function(requirements) { _fillRequirements(requirements, currency.parameters); }); } - // TODO : get sigDate from blockUid ?? + /// Save to cache + requirementsCache.put(cacheKey, data); - return data; + angular.merge(inputData, data); // Update the input data + + console.debug("[wot] Requirements for '{0}' loaded in {1}ms".format((data.pubkey && data.pubkey.substring(0,8))||data.uid, Date.now() - now)); + + return inputData; }) .catch(function(err) { - _resetRequirements(data); + _resetRequirements(inputData); // If not a member: continue if (!!err && (err.ucode == BMA.errorCodes.NO_MATCHING_MEMBER || err.ucode == BMA.errorCodes.NO_IDTY_MATCHING_PUB_OR_UID)) { - return data; + inputData.requirements.loaded = true; + return inputData; } throw err; - }) - ; + }); }, + + loadIdentityByLookup = function(pubkey, uid) { + var data = { + pubkey: pubkey, + uid: uid, + hasSelf: false + }; return BMA.wot.lookup({ search: pubkey||uid }) .then(function(res){ var identities = res.results.reduce(function(idties, res) { return idties.concat(res.uids.reduce(function(uids, idty) { var blockUid = idty.meta.timestamp.split('-', 2); + var blockNumber = parseInt(blockUid[0]); return uids.concat({ uid: idty.uid, pubkey: res.pubkey, - timestamp: idty.meta.timestamp, - number: parseInt(blockUid[0]), - hash: blockUid[1], + meta: { + timestamp: idty.meta.timestamp, + number: blockNumber, + hash: blockUid[1], + sig: idty.self + }, revoked: idty.revoked, - revocationNumber: idty.revoked_on, - sig: idty.self + revoked_on: idty.revoked_on }); }, [])); }, []); + // Fill identities meta (self) + return _fillIdentitiesMeta(identities) + .then(function(identities) { + return { + identities: identities, + results: res.results + }; + }); + }) + .then(function(res){ + var identities = res.identities; + // Sort identities if need - if (identities.length) { + if (identities.length > 1) { // Select the best identity, by sorting using this order + // - valid block // - same given uid // - not revoked // - max(block_number) - identities = _.sortBy(identities, function(idty) { + res.identities = _.sortBy(identities, function(idty) { var score = 0; - score += (10000000000 * ((uid && idty.uid === uid) ? 1 : 0)); - score += (1000000000 * (!idty.revoked ? 1 : 0)); - score += (1 * (idty.number ? idty.number : 0)); + score += (100000000000 * ((data.uid && idty.uid === data.uid) ? 1 : 0)); + score += (10000000000 * (!idty.meta.invalid ? 1 : 0)); + score += (1000000000 * ((data.blockUid && idty.meta.timestamp && idty.meta.timestamp === data.blockUid) ? 1 : 0)); + score += (100000000 * (!idty.revoked ? 1 : 0)); + score += (1 * (idty.meta.number ? idty.meta.number : 0) / 1000); return -score; }); + console.debug('[wot] Found {0} identities (in lookup). Will selected the best one'.format(identities.length)); } - var identity = identities[0]; - identity.hasSelf = !!(identity.uid && identity.timestamp && identity.sig); - identity.lookup = {}; + // Prepare alternatives identities + _.forEach(identities, function(idty) { + idty.hasSelf = !!(idty.uid && idty.meta.timestamp && idty.meta.sig); + }); + + // Select the first identity + data.requirements = identities[0]; + + // Copy some useful properties into data + data.pubkey = data.requirements.pubkey; + data.uid = data.requirements.uid; + data.blockUid = data.requirements.meta && data.requirements.meta.timestamp; + data.hasSelf = data.requirements.hasSelf; + data.sigDate = data.requirements.meta && data.requirements.meta.time; + + if (identities.length > 1) { + data.requirements.alternatives = identities.splice(1); + } - // Store received certifications - var certPubkeys = []; - identity.lookup.certifications = !res.results ? {} : res.results.reduce(function(certsMap, res) { + // Store additional data (e.g. certs) + data.lookup = {}; + + // Store received certifications (can be usefull later) + var certPubkeys = {}; + data.lookup.certifications = (res.results || []).reduce(function(certsMap, res) { return res.uids.reduce(function(certsMap, idty) { var idtyFullKey = idty.uid + '-' + (idty.meta ? idty.meta.timestamp : ''); - certsMap[idtyFullKey] = idty.others.reduce(function(certs, cert) { + certsMap[idtyFullKey] = (idty.others||[]).reduce(function(certs, cert) { var certFullKey = idtyFullKey + '-' + cert.pubkey; var result = { pubkey: cert.pubkey, @@ -275,9 +397,9 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c }, {}); // Store given certifications - certPubkeys = []; - identity.lookup.givenCertifications = !res.results ? [] : res.results.reduce(function(certs, res) { - return res.signed.reduce(function(certs, cert) { + certPubkeys = {}; + data.lookup.givenCertifications = (res.results || []).reduce(function(certs, res) { + return (res.signed || []).reduce(function(certs, cert) { var result = { pubkey: cert.pubkey, uid: cert.uid, @@ -291,60 +413,30 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c }; if (!certPubkeys[cert.pubkey]) { certPubkeys[cert.pubkey] = result; - // TODO : to not add, but replace the old one } else { // if duplicated cert: keep the most recent if (result.block > certPubkeys[cert.pubkey].block) { certPubkeys[cert.pubkey] = result; + // TODO: Replace the existing one ? May be not, to be able to see renewal + // (see issue #806) + // If yes (need to replace), check this code works: + //certs.splice(_.findIndex(certs, {pubkey: cert.pubkey}), 1, result); + //return certs; } else { - return certs; // skip this result + return certs; // skip this cert } } return certs.concat(result); }, certs); }, []); - // Retrieve time (self and revocation) - var blocks = [identity.number]; - if (identity.revocationNumber) { - blocks.push(identity.revocationNumber); - } - return BMA.blockchain.blocks(blocks) - .then(function(blocks){ - identity.sigDate = blocks[0].medianTime; - - // Check if self has been done on a valid block - if (identity.number !== 0 && identity.hash !== blocks[0].hash) { - identity.hasBadSelfBlock = true; - } - - // Set revocation time - if (identity.revocationNumber) { - identity.revocationTime = blocks[1].medianTime; - } - - return identity; - }) - .catch(function(err){ - // Special case for currency init (root block not exists): use now - if (err && err.ucode == BMA.errorCodes.BLOCK_NOT_FOUND && identity.number === 0) { - identity.sigDate = Math.trunc(new Date().getTime() / 1000); - return identity; - } - else { - throw err; - } - }); + return data; }) .catch(function(err) { if (!!err && err.ucode == BMA.errorCodes.NO_MATCHING_IDENTITY) { // Identity not found (if no self) - var identity = { - uid: null, - pubkey: pubkey, - hasSelf: false - }; - return identity; + _resetRequirements(data); + return data; } else { throw err; @@ -371,7 +463,7 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c return getFunction({ pubkey: pubkey }) .then(function(res) { - return res.certifications.reduce(function (res, cert) { + return (res && res.certifications || []).reduce(function (res, cert) { // Rappel : // cert.sigDate = blockstamp de l'identité // cert.cert_time.block : block au moment de la certification @@ -408,6 +500,12 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c isMember = false; return []; // continue (append pendings cert if exists in lookup) } + /*FIXME: workaround for Duniter issue #1309 */ + else if (!!err && err.ucode == 1002) { + console.warn("[wallet-service] Detecting Duniter issue #1309 ! Applying workaround... "); + isMember = false; + return []; // not found + } else { throw err; } @@ -523,19 +621,25 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c addEvents = function(data) { if (data.requirements.revoked) { - delete data.hasBadSelfBlock; - addEvent(data, {type: 'error', message: 'ERROR.IDENTITY_REVOKED', messageParams: {revocationTime: data.revocationTime}}); - console.debug("[wot] Identity [{0}] has been revoked".format(data.uid)); + delete data.requirements.meta.invalid; + if (data.requirements.revoked_on) { + addEvent(data, {type: 'error', message: 'ERROR.IDENTITY_REVOKED_WITH_TIME', messageParams: {revocationTime: data.requirements.revoked_on}}); + console.debug("[wot] Identity [{0}] has been revoked on {1}".format(data.uid, data.requirements.revoked_on)); + } + else { + addEvent(data, {type: 'error', message: 'ERROR.IDENTITY_REVOKED'}); + console.debug("[wot] Identity [{0}] has been revoked".format(data.uid)); + } } else if (data.requirements.pendingRevocation) { + delete data.requirements.meta.invalid; addEvent(data, {type:'error', message: 'ERROR.IDENTITY_PENDING_REVOCATION'}); console.debug("[wot] Identity [{0}] has pending revocation".format(data.uid)); } - else if (data.hasBadSelfBlock) { - delete data.hasBadSelfBlock; + else if (data.requirements.meta && data.requirements.meta.invalid) { if (!data.isMember) { addEvent(data, {type: 'error', message: 'ERROR.IDENTITY_INVALID_BLOCK_HASH'}); - console.debug("[wot] Invalid membership for {0}: block hash changed".format(data.uid)); + console.debug("[wot] Invalid membership for uid {0}: block hash changed".format(data.uid)); } } else if (data.requirements.expired) { @@ -550,25 +654,31 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c addEvent(data, {type: 'error', message: 'INFO.IDENTITY_NEED_MEMBERSHIP'}); console.debug("[wot] Identity {0} has a self but no membership".format(data.uid)); } + if (!data.isMember && data.requirements.alternatives) { + addEvent(data, {type: 'info', message: 'INFO.HAS_ALTERNATIVE_IDENTITIES'}); + } }, - loadData = function(pubkey, withCache, uid, force) { + loadData = function(pubkey, uid, options) { + options = options || {}; var data; - if (!pubkey && uid && !force) { + if (!pubkey && uid && !options.force) { return BMA.wot.member.getByUid(uid) .then(function(member) { - if (member) return loadData(member.pubkey, withCache, member.uid); // recursive call + if (member) return loadData(member.pubkey, member.uid, options); // recursive call, with a pubkey //throw {message: 'NOT_A_MEMBER'}; - return loadData(pubkey, withCache, uid, true/*force*/); + var options = angular.copy(options || {}); + options.force = true; + return loadData(pubkey, uid, options); // Loop with force=true }); } // Check cached data if (pubkey) { - data = withCache ? identityCache.get(pubkey) : null; - if (data && (!uid || data.uid == uid)) { + data = (options.cache !== false) ? identityCache.get(pubkey) : null; + if (data && (!uid || data.uid === uid) && (!options.blockUid || data.blockUid === options.blockUid)) { console.debug("[wot] Identity " + pubkey.substring(0, 8) + " found in cache"); return $q.when(data); } @@ -584,28 +694,29 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c uid: uid }; } + if (options.blockUid) { + data.blockUid = options.blockUid; + } - var now = new Date().getTime(); - + var now = Date.now(); var parameters; var medianTime; return $q.all([ // Get parameters - BMA.blockchain.parameters() + csCurrency.parameters() .then(function(res) { parameters = res; - }), // Get current time - BMA.blockchain.current() + csCurrency.blockchain.current() .then(function(current) { medianTime = current.medianTime; }) .catch(function(err){ // Special case for currency init (root block not exists): use now if (err && err.ucode == BMA.errorCodes.NO_CURRENT_BLOCK) { - medianTime = Math.trunc(new Date().getTime()/1000); + medianTime = moment.utc().unix(); } else { throw err; @@ -613,22 +724,28 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c }), // Get requirements - loadRequirements(data), + loadRequirements(data, options.cache !== false), // Get identity using lookup loadIdentityByLookup(pubkey, uid) - .then(function (identity) { - angular.merge(data, identity); - }) + ]) - .then(function() { - if (!data.requirements.uid) return; + .then(function(res) { + var dataByLookup = res[3]; + + // If no requirements found: copy from lookup data + if (!data.requirements.uid) { + console.debug("[wot] No requirements found: using data from lookup"); + angular.merge(data, dataByLookup); + delete data.lookup; // not need + return; + } var idtyFullKey = data.requirements.uid + '-' + data.requirements.meta.timestamp; return $q.all([ // Get received certifications - loadCertifications(BMA.wot.certifiersOf, data.pubkey, data.lookup ? data.lookup.certifications[idtyFullKey] : null, parameters, medianTime, true /*certifiersOf*/) + loadCertifications(BMA.wot.certifiersOf, data.pubkey, dataByLookup.lookup ? dataByLookup.lookup.certifications[idtyFullKey] : null, parameters, medianTime, true /*certifiersOf*/) .then(function (res) { data.received_cert = res.valid; data.received_cert_pending = res.pending; @@ -636,7 +753,7 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c }), // Get given certifications - loadCertifications(BMA.wot.certifiedBy, data.pubkey, data.lookup ? data.lookup.givenCertifications : null, parameters, medianTime, false/*certifiersOf*/) + loadCertifications(BMA.wot.certifiedBy, data.pubkey, dataByLookup.lookup ? dataByLookup.lookup.givenCertifications : null, parameters, medianTime, false/*certifiersOf*/) .then(function (res) { data.given_cert = res.valid; data.given_cert_pending = res.pending; @@ -663,9 +780,8 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c }) .then(function() { if (!data.pubkey) return undefined; // not found - delete data.lookup; // not need anymore identityCache.put(data.pubkey, data); // add to cache - console.debug('[wot] Identity '+ data.pubkey.substring(0, 8) +' loaded in '+ (new Date().getTime()-now) +'ms'); + console.debug('[wot] Identity '+ data.pubkey.substring(0, 8) +' loaded in '+ (Date.now()-now) +'ms'); return data; }); }, @@ -767,15 +883,13 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c return $q.all([ csCurrency.blockchain.current(true) .then(function(block) { - total = block.membersCount; + total = block.membersCount || 0; }), BMA.blockchain.stats.newcomers() ]) .then(function(res) { res = res[1]; - if (!res.result.blocks || !res.result.blocks.length) { - return null; - } + if (!res || !res.result || !res.result.blocks || !res.result.blocks.length) return null; // no result var blocks = _.sortBy(res.result.blocks, function (n) { return -n; }); @@ -790,13 +904,12 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c // Extension point return extendAll(idties, 'pubkey', true/*skipAddUid*/); }) - .then(function(idties) { - return { - hits: idties, - total: total - }; - }) - ; + .then(function(idties) { + return { + hits: idties, + total: total + }; + }); }, @@ -855,7 +968,7 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c getPending = function(offset, size) { offset = offset || 0; size = size || 20; - var now = new Date().getTime(); + var now = Date.now(); return $q.all([ BMA.wot.member.uids(), BMA.wot.member.pending() @@ -931,7 +1044,7 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c extendAll(idties, 'pubkey', true/*skipAddUid*/) ]) .then(function() { - console.debug("[ES] [wot] Loaded {0}/{1} pending identities in {2} ms".format(idties && idties.length || 0, total, new Date().getTime() - now)); + console.debug("[ES] [wot] Loaded {0}/{1} pending identities in {2} ms".format(idties && idties.length || 0, total, Date.now() - now)); return { hits: idties, total: total @@ -1064,6 +1177,11 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c event.messageParams = event.messageParams || {}; data.events = data.events || []; data.events.push(event); + }, + + cleanCache = function() { + console.debug("[wot] Cleaning cache..."); + csCache.clear(cachePrefix); } ; @@ -1071,6 +1189,9 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c api.registerEvent('data', 'load'); api.registerEvent('data', 'search'); + // Listen if node changed + BMA.api.node.on.stop($rootScope, cleanCache, this); + return { id: id, load: loadData, diff --git a/assets/www/js/vendor/Chart.js b/assets/www/js/vendor/Chart.js deleted file mode 100644 index bfd195ff09b5e2ae1def1892f71c019541d4864f..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/Chart.js +++ /dev/null @@ -1,12269 +0,0 @@ -/*! - * Chart.js - * http://chartjs.org/ - * Version: 2.5.0 - * - * Copyright 2017 Nick Downie - * Released under the MIT license - * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md - */ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Chart = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ - -},{}],2:[function(require,module,exports){ - /* MIT license */ - var colorNames = require(6); - - module.exports = { - getRgba: getRgba, - getHsla: getHsla, - getRgb: getRgb, - getHsl: getHsl, - getHwb: getHwb, - getAlpha: getAlpha, - - hexString: hexString, - rgbString: rgbString, - rgbaString: rgbaString, - percentString: percentString, - percentaString: percentaString, - hslString: hslString, - hslaString: hslaString, - hwbString: hwbString, - keyword: keyword - } - - function getRgba(string) { - if (!string) { - return; - } - var abbr = /^#([a-fA-F0-9]{3})$/, - hex = /^#([a-fA-F0-9]{6})$/, - rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/, - per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/, - keyword = /(\w+)/; - - var rgb = [0, 0, 0], - a = 1, - match = string.match(abbr); - if (match) { - match = match[1]; - for (var i = 0; i < rgb.length; i++) { - rgb[i] = parseInt(match[i] + match[i], 16); - } - } - else if (match = string.match(hex)) { - match = match[1]; - for (var i = 0; i < rgb.length; i++) { - rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16); - } - } - else if (match = string.match(rgba)) { - for (var i = 0; i < rgb.length; i++) { - rgb[i] = parseInt(match[i + 1]); - } - a = parseFloat(match[4]); - } - else if (match = string.match(per)) { - for (var i = 0; i < rgb.length; i++) { - rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); - } - a = parseFloat(match[4]); - } - else if (match = string.match(keyword)) { - if (match[1] == "transparent") { - return [0, 0, 0, 0]; - } - rgb = colorNames[match[1]]; - if (!rgb) { - return; - } - } - - for (var i = 0; i < rgb.length; i++) { - rgb[i] = scale(rgb[i], 0, 255); - } - if (!a && a != 0) { - a = 1; - } - else { - a = scale(a, 0, 1); - } - rgb[3] = a; - return rgb; - } - - function getHsla(string) { - if (!string) { - return; - } - var hsl = /^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; - var match = string.match(hsl); - if (match) { - var alpha = parseFloat(match[4]); - var h = scale(parseInt(match[1]), 0, 360), - s = scale(parseFloat(match[2]), 0, 100), - l = scale(parseFloat(match[3]), 0, 100), - a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); - return [h, s, l, a]; - } - } - - function getHwb(string) { - if (!string) { - return; - } - var hwb = /^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; - var match = string.match(hwb); - if (match) { - var alpha = parseFloat(match[4]); - var h = scale(parseInt(match[1]), 0, 360), - w = scale(parseFloat(match[2]), 0, 100), - b = scale(parseFloat(match[3]), 0, 100), - a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); - return [h, w, b, a]; - } - } - - function getRgb(string) { - var rgba = getRgba(string); - return rgba && rgba.slice(0, 3); - } - - function getHsl(string) { - var hsla = getHsla(string); - return hsla && hsla.slice(0, 3); - } - - function getAlpha(string) { - var vals = getRgba(string); - if (vals) { - return vals[3]; - } - else if (vals = getHsla(string)) { - return vals[3]; - } - else if (vals = getHwb(string)) { - return vals[3]; - } - } - -// generators - function hexString(rgb) { - return "#" + hexDouble(rgb[0]) + hexDouble(rgb[1]) - + hexDouble(rgb[2]); - } - - function rgbString(rgba, alpha) { - if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { - return rgbaString(rgba, alpha); - } - return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")"; - } - - function rgbaString(rgba, alpha) { - if (alpha === undefined) { - alpha = (rgba[3] !== undefined ? rgba[3] : 1); - } - return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] - + ", " + alpha + ")"; - } - - function percentString(rgba, alpha) { - if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { - return percentaString(rgba, alpha); - } - var r = Math.round(rgba[0]/255 * 100), - g = Math.round(rgba[1]/255 * 100), - b = Math.round(rgba[2]/255 * 100); - - return "rgb(" + r + "%, " + g + "%, " + b + "%)"; - } - - function percentaString(rgba, alpha) { - var r = Math.round(rgba[0]/255 * 100), - g = Math.round(rgba[1]/255 * 100), - b = Math.round(rgba[2]/255 * 100); - return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 1) + ")"; - } - - function hslString(hsla, alpha) { - if (alpha < 1 || (hsla[3] && hsla[3] < 1)) { - return hslaString(hsla, alpha); - } - return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)"; - } - - function hslaString(hsla, alpha) { - if (alpha === undefined) { - alpha = (hsla[3] !== undefined ? hsla[3] : 1); - } - return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " - + alpha + ")"; - } - -// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax -// (hwb have alpha optional & 1 is default value) - function hwbString(hwb, alpha) { - if (alpha === undefined) { - alpha = (hwb[3] !== undefined ? hwb[3] : 1); - } - return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%" - + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")"; - } - - function keyword(rgb) { - return reverseNames[rgb.slice(0, 3)]; - } - -// helpers - function scale(num, min, max) { - return Math.min(Math.max(min, num), max); - } - - function hexDouble(num) { - var str = num.toString(16).toUpperCase(); - return (str.length < 2) ? "0" + str : str; - } - - -//create a list of reverse color names - var reverseNames = {}; - for (var name in colorNames) { - reverseNames[colorNames[name]] = name; - } - -},{"6":6}],3:[function(require,module,exports){ - /* MIT license */ - var convert = require(5); - var string = require(2); - - var Color = function (obj) { - if (obj instanceof Color) { - return obj; - } - if (!(this instanceof Color)) { - return new Color(obj); - } - - this.values = { - rgb: [0, 0, 0], - hsl: [0, 0, 0], - hsv: [0, 0, 0], - hwb: [0, 0, 0], - cmyk: [0, 0, 0, 0], - alpha: 1 - }; - - // parse Color() argument - var vals; - if (typeof obj === 'string') { - vals = string.getRgba(obj); - if (vals) { - this.setValues('rgb', vals); - } else if (vals = string.getHsla(obj)) { - this.setValues('hsl', vals); - } else if (vals = string.getHwb(obj)) { - this.setValues('hwb', vals); - } else { - throw new Error('Unable to parse color from string "' + obj + '"'); - } - } else if (typeof obj === 'object') { - vals = obj; - if (vals.r !== undefined || vals.red !== undefined) { - this.setValues('rgb', vals); - } else if (vals.l !== undefined || vals.lightness !== undefined) { - this.setValues('hsl', vals); - } else if (vals.v !== undefined || vals.value !== undefined) { - this.setValues('hsv', vals); - } else if (vals.w !== undefined || vals.whiteness !== undefined) { - this.setValues('hwb', vals); - } else if (vals.c !== undefined || vals.cyan !== undefined) { - this.setValues('cmyk', vals); - } else { - throw new Error('Unable to parse color from object ' + JSON.stringify(obj)); - } - } - }; - - Color.prototype = { - rgb: function () { - return this.setSpace('rgb', arguments); - }, - hsl: function () { - return this.setSpace('hsl', arguments); - }, - hsv: function () { - return this.setSpace('hsv', arguments); - }, - hwb: function () { - return this.setSpace('hwb', arguments); - }, - cmyk: function () { - return this.setSpace('cmyk', arguments); - }, - - rgbArray: function () { - return this.values.rgb; - }, - hslArray: function () { - return this.values.hsl; - }, - hsvArray: function () { - return this.values.hsv; - }, - hwbArray: function () { - var values = this.values; - if (values.alpha !== 1) { - return values.hwb.concat([values.alpha]); - } - return values.hwb; - }, - cmykArray: function () { - return this.values.cmyk; - }, - rgbaArray: function () { - var values = this.values; - return values.rgb.concat([values.alpha]); - }, - hslaArray: function () { - var values = this.values; - return values.hsl.concat([values.alpha]); - }, - alpha: function (val) { - if (val === undefined) { - return this.values.alpha; - } - this.setValues('alpha', val); - return this; - }, - - red: function (val) { - return this.setChannel('rgb', 0, val); - }, - green: function (val) { - return this.setChannel('rgb', 1, val); - }, - blue: function (val) { - return this.setChannel('rgb', 2, val); - }, - hue: function (val) { - if (val) { - val %= 360; - val = val < 0 ? 360 + val : val; - } - return this.setChannel('hsl', 0, val); - }, - saturation: function (val) { - return this.setChannel('hsl', 1, val); - }, - lightness: function (val) { - return this.setChannel('hsl', 2, val); - }, - saturationv: function (val) { - return this.setChannel('hsv', 1, val); - }, - whiteness: function (val) { - return this.setChannel('hwb', 1, val); - }, - blackness: function (val) { - return this.setChannel('hwb', 2, val); - }, - value: function (val) { - return this.setChannel('hsv', 2, val); - }, - cyan: function (val) { - return this.setChannel('cmyk', 0, val); - }, - magenta: function (val) { - return this.setChannel('cmyk', 1, val); - }, - yellow: function (val) { - return this.setChannel('cmyk', 2, val); - }, - black: function (val) { - return this.setChannel('cmyk', 3, val); - }, - - hexString: function () { - return string.hexString(this.values.rgb); - }, - rgbString: function () { - return string.rgbString(this.values.rgb, this.values.alpha); - }, - rgbaString: function () { - return string.rgbaString(this.values.rgb, this.values.alpha); - }, - percentString: function () { - return string.percentString(this.values.rgb, this.values.alpha); - }, - hslString: function () { - return string.hslString(this.values.hsl, this.values.alpha); - }, - hslaString: function () { - return string.hslaString(this.values.hsl, this.values.alpha); - }, - hwbString: function () { - return string.hwbString(this.values.hwb, this.values.alpha); - }, - keyword: function () { - return string.keyword(this.values.rgb, this.values.alpha); - }, - - rgbNumber: function () { - var rgb = this.values.rgb; - return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]; - }, - - luminosity: function () { - // http://www.w3.org/TR/WCAG20/#relativeluminancedef - var rgb = this.values.rgb; - var lum = []; - for (var i = 0; i < rgb.length; i++) { - var chan = rgb[i] / 255; - lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4); - } - return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; - }, - - contrast: function (color2) { - // http://www.w3.org/TR/WCAG20/#contrast-ratiodef - var lum1 = this.luminosity(); - var lum2 = color2.luminosity(); - if (lum1 > lum2) { - return (lum1 + 0.05) / (lum2 + 0.05); - } - return (lum2 + 0.05) / (lum1 + 0.05); - }, - - level: function (color2) { - var contrastRatio = this.contrast(color2); - if (contrastRatio >= 7.1) { - return 'AAA'; - } - - return (contrastRatio >= 4.5) ? 'AA' : ''; - }, - - dark: function () { - // YIQ equation from http://24ways.org/2010/calculating-color-contrast - var rgb = this.values.rgb; - var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; - return yiq < 128; - }, - - light: function () { - return !this.dark(); - }, - - negate: function () { - var rgb = []; - for (var i = 0; i < 3; i++) { - rgb[i] = 255 - this.values.rgb[i]; - } - this.setValues('rgb', rgb); - return this; - }, - - lighten: function (ratio) { - var hsl = this.values.hsl; - hsl[2] += hsl[2] * ratio; - this.setValues('hsl', hsl); - return this; - }, - - darken: function (ratio) { - var hsl = this.values.hsl; - hsl[2] -= hsl[2] * ratio; - this.setValues('hsl', hsl); - return this; - }, - - saturate: function (ratio) { - var hsl = this.values.hsl; - hsl[1] += hsl[1] * ratio; - this.setValues('hsl', hsl); - return this; - }, - - desaturate: function (ratio) { - var hsl = this.values.hsl; - hsl[1] -= hsl[1] * ratio; - this.setValues('hsl', hsl); - return this; - }, - - whiten: function (ratio) { - var hwb = this.values.hwb; - hwb[1] += hwb[1] * ratio; - this.setValues('hwb', hwb); - return this; - }, - - blacken: function (ratio) { - var hwb = this.values.hwb; - hwb[2] += hwb[2] * ratio; - this.setValues('hwb', hwb); - return this; - }, - - greyscale: function () { - var rgb = this.values.rgb; - // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale - var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; - this.setValues('rgb', [val, val, val]); - return this; - }, - - clearer: function (ratio) { - var alpha = this.values.alpha; - this.setValues('alpha', alpha - (alpha * ratio)); - return this; - }, - - opaquer: function (ratio) { - var alpha = this.values.alpha; - this.setValues('alpha', alpha + (alpha * ratio)); - return this; - }, - - rotate: function (degrees) { - var hsl = this.values.hsl; - var hue = (hsl[0] + degrees) % 360; - hsl[0] = hue < 0 ? 360 + hue : hue; - this.setValues('hsl', hsl); - return this; - }, - - /** - * Ported from sass implementation in C - * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 - */ - mix: function (mixinColor, weight) { - var color1 = this; - var color2 = mixinColor; - var p = weight === undefined ? 0.5 : weight; - - var w = 2 * p - 1; - var a = color1.alpha() - color2.alpha(); - - var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - return this - .rgb( - w1 * color1.red() + w2 * color2.red(), - w1 * color1.green() + w2 * color2.green(), - w1 * color1.blue() + w2 * color2.blue() - ) - .alpha(color1.alpha() * p + color2.alpha() * (1 - p)); - }, - - toJSON: function () { - return this.rgb(); - }, - - clone: function () { - // NOTE(SB): using node-clone creates a dependency to Buffer when using browserify, - // making the final build way to big to embed in Chart.js. So let's do it manually, - // assuming that values to clone are 1 dimension arrays containing only numbers, - // except 'alpha' which is a number. - var result = new Color(); - var source = this.values; - var target = result.values; - var value, type; - - for (var prop in source) { - if (source.hasOwnProperty(prop)) { - value = source[prop]; - type = ({}).toString.call(value); - if (type === '[object Array]') { - target[prop] = value.slice(0); - } else if (type === '[object Number]') { - target[prop] = value; - } else { - console.error('unexpected color value:', value); - } - } - } - - return result; - } - }; - - Color.prototype.spaces = { - rgb: ['red', 'green', 'blue'], - hsl: ['hue', 'saturation', 'lightness'], - hsv: ['hue', 'saturation', 'value'], - hwb: ['hue', 'whiteness', 'blackness'], - cmyk: ['cyan', 'magenta', 'yellow', 'black'] - }; - - Color.prototype.maxes = { - rgb: [255, 255, 255], - hsl: [360, 100, 100], - hsv: [360, 100, 100], - hwb: [360, 100, 100], - cmyk: [100, 100, 100, 100] - }; - - Color.prototype.getValues = function (space) { - var values = this.values; - var vals = {}; - - for (var i = 0; i < space.length; i++) { - vals[space.charAt(i)] = values[space][i]; - } - - if (values.alpha !== 1) { - vals.a = values.alpha; - } - - // {r: 255, g: 255, b: 255, a: 0.4} - return vals; - }; - - Color.prototype.setValues = function (space, vals) { - var values = this.values; - var spaces = this.spaces; - var maxes = this.maxes; - var alpha = 1; - var i; - - if (space === 'alpha') { - alpha = vals; - } else if (vals.length) { - // [10, 10, 10] - values[space] = vals.slice(0, space.length); - alpha = vals[space.length]; - } else if (vals[space.charAt(0)] !== undefined) { - // {r: 10, g: 10, b: 10} - for (i = 0; i < space.length; i++) { - values[space][i] = vals[space.charAt(i)]; - } - - alpha = vals.a; - } else if (vals[spaces[space][0]] !== undefined) { - // {red: 10, green: 10, blue: 10} - var chans = spaces[space]; - - for (i = 0; i < space.length; i++) { - values[space][i] = vals[chans[i]]; - } - - alpha = vals.alpha; - } - - values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha))); - - if (space === 'alpha') { - return false; - } - - var capped; - - // cap values of the space prior converting all values - for (i = 0; i < space.length; i++) { - capped = Math.max(0, Math.min(maxes[space][i], values[space][i])); - values[space][i] = Math.round(capped); - } - - // convert to all the other color spaces - for (var sname in spaces) { - if (sname !== space) { - values[sname] = convert[space][sname](values[space]); - } - } - - return true; - }; - - Color.prototype.setSpace = function (space, args) { - var vals = args[0]; - - if (vals === undefined) { - // color.rgb() - return this.getValues(space); - } - - // color.rgb(10, 10, 10) - if (typeof vals === 'number') { - vals = Array.prototype.slice.call(args); - } - - this.setValues(space, vals); - return this; - }; - - Color.prototype.setChannel = function (space, index, val) { - var svalues = this.values[space]; - if (val === undefined) { - // color.red() - return svalues[index]; - } else if (val === svalues[index]) { - // color.red(color.red()) - return this; - } - - // color.red(100) - svalues[index] = val; - this.setValues(space, svalues); - - return this; - }; - - if (typeof window !== 'undefined') { - window.Color = Color; - } - - module.exports = Color; - -},{"2":2,"5":5}],4:[function(require,module,exports){ - /* MIT license */ - - module.exports = { - rgb2hsl: rgb2hsl, - rgb2hsv: rgb2hsv, - rgb2hwb: rgb2hwb, - rgb2cmyk: rgb2cmyk, - rgb2keyword: rgb2keyword, - rgb2xyz: rgb2xyz, - rgb2lab: rgb2lab, - rgb2lch: rgb2lch, - - hsl2rgb: hsl2rgb, - hsl2hsv: hsl2hsv, - hsl2hwb: hsl2hwb, - hsl2cmyk: hsl2cmyk, - hsl2keyword: hsl2keyword, - - hsv2rgb: hsv2rgb, - hsv2hsl: hsv2hsl, - hsv2hwb: hsv2hwb, - hsv2cmyk: hsv2cmyk, - hsv2keyword: hsv2keyword, - - hwb2rgb: hwb2rgb, - hwb2hsl: hwb2hsl, - hwb2hsv: hwb2hsv, - hwb2cmyk: hwb2cmyk, - hwb2keyword: hwb2keyword, - - cmyk2rgb: cmyk2rgb, - cmyk2hsl: cmyk2hsl, - cmyk2hsv: cmyk2hsv, - cmyk2hwb: cmyk2hwb, - cmyk2keyword: cmyk2keyword, - - keyword2rgb: keyword2rgb, - keyword2hsl: keyword2hsl, - keyword2hsv: keyword2hsv, - keyword2hwb: keyword2hwb, - keyword2cmyk: keyword2cmyk, - keyword2lab: keyword2lab, - keyword2xyz: keyword2xyz, - - xyz2rgb: xyz2rgb, - xyz2lab: xyz2lab, - xyz2lch: xyz2lch, - - lab2xyz: lab2xyz, - lab2rgb: lab2rgb, - lab2lch: lab2lch, - - lch2lab: lch2lab, - lch2xyz: lch2xyz, - lch2rgb: lch2rgb - } - - - function rgb2hsl(rgb) { - var r = rgb[0]/255, - g = rgb[1]/255, - b = rgb[2]/255, - min = Math.min(r, g, b), - max = Math.max(r, g, b), - delta = max - min, - h, s, l; - - if (max == min) - h = 0; - else if (r == max) - h = (g - b) / delta; - else if (g == max) - h = 2 + (b - r) / delta; - else if (b == max) - h = 4 + (r - g)/ delta; - - h = Math.min(h * 60, 360); - - if (h < 0) - h += 360; - - l = (min + max) / 2; - - if (max == min) - s = 0; - else if (l <= 0.5) - s = delta / (max + min); - else - s = delta / (2 - max - min); - - return [h, s * 100, l * 100]; - } - - function rgb2hsv(rgb) { - var r = rgb[0], - g = rgb[1], - b = rgb[2], - min = Math.min(r, g, b), - max = Math.max(r, g, b), - delta = max - min, - h, s, v; - - if (max == 0) - s = 0; - else - s = (delta/max * 1000)/10; - - if (max == min) - h = 0; - else if (r == max) - h = (g - b) / delta; - else if (g == max) - h = 2 + (b - r) / delta; - else if (b == max) - h = 4 + (r - g) / delta; - - h = Math.min(h * 60, 360); - - if (h < 0) - h += 360; - - v = ((max / 255) * 1000) / 10; - - return [h, s, v]; - } - - function rgb2hwb(rgb) { - var r = rgb[0], - g = rgb[1], - b = rgb[2], - h = rgb2hsl(rgb)[0], - w = 1/255 * Math.min(r, Math.min(g, b)), - b = 1 - 1/255 * Math.max(r, Math.max(g, b)); - - return [h, w * 100, b * 100]; - } - - function rgb2cmyk(rgb) { - var r = rgb[0] / 255, - g = rgb[1] / 255, - b = rgb[2] / 255, - c, m, y, k; - - k = Math.min(1 - r, 1 - g, 1 - b); - c = (1 - r - k) / (1 - k) || 0; - m = (1 - g - k) / (1 - k) || 0; - y = (1 - b - k) / (1 - k) || 0; - return [c * 100, m * 100, y * 100, k * 100]; - } - - function rgb2keyword(rgb) { - return reverseKeywords[JSON.stringify(rgb)]; - } - - function rgb2xyz(rgb) { - var r = rgb[0] / 255, - g = rgb[1] / 255, - b = rgb[2] / 255; - - // assume sRGB - r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); - g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); - b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); - - var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); - var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); - var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); - - return [x * 100, y *100, z * 100]; - } - - function rgb2lab(rgb) { - var xyz = rgb2xyz(rgb), - x = xyz[0], - y = xyz[1], - z = xyz[2], - l, a, b; - - x /= 95.047; - y /= 100; - z /= 108.883; - - x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116); - - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); - - return [l, a, b]; - } - - function rgb2lch(args) { - return lab2lch(rgb2lab(args)); - } - - function hsl2rgb(hsl) { - var h = hsl[0] / 360, - s = hsl[1] / 100, - l = hsl[2] / 100, - t1, t2, t3, rgb, val; - - if (s == 0) { - val = l * 255; - return [val, val, val]; - } - - if (l < 0.5) - t2 = l * (1 + s); - else - t2 = l + s - l * s; - t1 = 2 * l - t2; - - rgb = [0, 0, 0]; - for (var i = 0; i < 3; i++) { - t3 = h + 1 / 3 * - (i - 1); - t3 < 0 && t3++; - t3 > 1 && t3--; - - if (6 * t3 < 1) - val = t1 + (t2 - t1) * 6 * t3; - else if (2 * t3 < 1) - val = t2; - else if (3 * t3 < 2) - val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; - else - val = t1; - - rgb[i] = val * 255; - } - - return rgb; - } - - function hsl2hsv(hsl) { - var h = hsl[0], - s = hsl[1] / 100, - l = hsl[2] / 100, - sv, v; - - if(l === 0) { - // no need to do calc on black - // also avoids divide by 0 error - return [0, 0, 0]; - } - - l *= 2; - s *= (l <= 1) ? l : 2 - l; - v = (l + s) / 2; - sv = (2 * s) / (l + s); - return [h, sv * 100, v * 100]; - } - - function hsl2hwb(args) { - return rgb2hwb(hsl2rgb(args)); - } - - function hsl2cmyk(args) { - return rgb2cmyk(hsl2rgb(args)); - } - - function hsl2keyword(args) { - return rgb2keyword(hsl2rgb(args)); - } - - - function hsv2rgb(hsv) { - var h = hsv[0] / 60, - s = hsv[1] / 100, - v = hsv[2] / 100, - hi = Math.floor(h) % 6; - - var f = h - Math.floor(h), - p = 255 * v * (1 - s), - q = 255 * v * (1 - (s * f)), - t = 255 * v * (1 - (s * (1 - f))), - v = 255 * v; - - switch(hi) { - case 0: - return [v, t, p]; - case 1: - return [q, v, p]; - case 2: - return [p, v, t]; - case 3: - return [p, q, v]; - case 4: - return [t, p, v]; - case 5: - return [v, p, q]; - } - } - - function hsv2hsl(hsv) { - var h = hsv[0], - s = hsv[1] / 100, - v = hsv[2] / 100, - sl, l; - - l = (2 - s) * v; - sl = s * v; - sl /= (l <= 1) ? l : 2 - l; - sl = sl || 0; - l /= 2; - return [h, sl * 100, l * 100]; - } - - function hsv2hwb(args) { - return rgb2hwb(hsv2rgb(args)) - } - - function hsv2cmyk(args) { - return rgb2cmyk(hsv2rgb(args)); - } - - function hsv2keyword(args) { - return rgb2keyword(hsv2rgb(args)); - } - -// http://dev.w3.org/csswg/css-color/#hwb-to-rgb - function hwb2rgb(hwb) { - var h = hwb[0] / 360, - wh = hwb[1] / 100, - bl = hwb[2] / 100, - ratio = wh + bl, - i, v, f, n; - - // wh + bl cant be > 1 - if (ratio > 1) { - wh /= ratio; - bl /= ratio; - } - - i = Math.floor(6 * h); - v = 1 - bl; - f = 6 * h - i; - if ((i & 0x01) != 0) { - f = 1 - f; - } - n = wh + f * (v - wh); // linear interpolation - - switch (i) { - default: - case 6: - case 0: r = v; g = n; b = wh; break; - case 1: r = n; g = v; b = wh; break; - case 2: r = wh; g = v; b = n; break; - case 3: r = wh; g = n; b = v; break; - case 4: r = n; g = wh; b = v; break; - case 5: r = v; g = wh; b = n; break; - } - - return [r * 255, g * 255, b * 255]; - } - - function hwb2hsl(args) { - return rgb2hsl(hwb2rgb(args)); - } - - function hwb2hsv(args) { - return rgb2hsv(hwb2rgb(args)); - } - - function hwb2cmyk(args) { - return rgb2cmyk(hwb2rgb(args)); - } - - function hwb2keyword(args) { - return rgb2keyword(hwb2rgb(args)); - } - - function cmyk2rgb(cmyk) { - var c = cmyk[0] / 100, - m = cmyk[1] / 100, - y = cmyk[2] / 100, - k = cmyk[3] / 100, - r, g, b; - - r = 1 - Math.min(1, c * (1 - k) + k); - g = 1 - Math.min(1, m * (1 - k) + k); - b = 1 - Math.min(1, y * (1 - k) + k); - return [r * 255, g * 255, b * 255]; - } - - function cmyk2hsl(args) { - return rgb2hsl(cmyk2rgb(args)); - } - - function cmyk2hsv(args) { - return rgb2hsv(cmyk2rgb(args)); - } - - function cmyk2hwb(args) { - return rgb2hwb(cmyk2rgb(args)); - } - - function cmyk2keyword(args) { - return rgb2keyword(cmyk2rgb(args)); - } - - - function xyz2rgb(xyz) { - var x = xyz[0] / 100, - y = xyz[1] / 100, - z = xyz[2] / 100, - r, g, b; - - r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); - g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); - b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); - - // assume sRGB - r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) - : r = (r * 12.92); - - g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) - : g = (g * 12.92); - - b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) - : b = (b * 12.92); - - r = Math.min(Math.max(0, r), 1); - g = Math.min(Math.max(0, g), 1); - b = Math.min(Math.max(0, b), 1); - - return [r * 255, g * 255, b * 255]; - } - - function xyz2lab(xyz) { - var x = xyz[0], - y = xyz[1], - z = xyz[2], - l, a, b; - - x /= 95.047; - y /= 100; - z /= 108.883; - - x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116); - y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116); - z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116); - - l = (116 * y) - 16; - a = 500 * (x - y); - b = 200 * (y - z); - - return [l, a, b]; - } - - function xyz2lch(args) { - return lab2lch(xyz2lab(args)); - } - - function lab2xyz(lab) { - var l = lab[0], - a = lab[1], - b = lab[2], - x, y, z, y2; - - if (l <= 8) { - y = (l * 100) / 903.3; - y2 = (7.787 * (y / 100)) + (16 / 116); - } else { - y = 100 * Math.pow((l + 16) / 116, 3); - y2 = Math.pow(y / 100, 1/3); - } - - x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 7.787 : 95.047 * Math.pow((a / 500) + y2, 3); - - z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) / 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3); - - return [x, y, z]; - } - - function lab2lch(lab) { - var l = lab[0], - a = lab[1], - b = lab[2], - hr, h, c; - - hr = Math.atan2(b, a); - h = hr * 360 / 2 / Math.PI; - if (h < 0) { - h += 360; - } - c = Math.sqrt(a * a + b * b); - return [l, c, h]; - } - - function lab2rgb(args) { - return xyz2rgb(lab2xyz(args)); - } - - function lch2lab(lch) { - var l = lch[0], - c = lch[1], - h = lch[2], - a, b, hr; - - hr = h / 360 * 2 * Math.PI; - a = c * Math.cos(hr); - b = c * Math.sin(hr); - return [l, a, b]; - } - - function lch2xyz(args) { - return lab2xyz(lch2lab(args)); - } - - function lch2rgb(args) { - return lab2rgb(lch2lab(args)); - } - - function keyword2rgb(keyword) { - return cssKeywords[keyword]; - } - - function keyword2hsl(args) { - return rgb2hsl(keyword2rgb(args)); - } - - function keyword2hsv(args) { - return rgb2hsv(keyword2rgb(args)); - } - - function keyword2hwb(args) { - return rgb2hwb(keyword2rgb(args)); - } - - function keyword2cmyk(args) { - return rgb2cmyk(keyword2rgb(args)); - } - - function keyword2lab(args) { - return rgb2lab(keyword2rgb(args)); - } - - function keyword2xyz(args) { - return rgb2xyz(keyword2rgb(args)); - } - - var cssKeywords = { - aliceblue: [240,248,255], - antiquewhite: [250,235,215], - aqua: [0,255,255], - aquamarine: [127,255,212], - azure: [240,255,255], - beige: [245,245,220], - bisque: [255,228,196], - black: [0,0,0], - blanchedalmond: [255,235,205], - blue: [0,0,255], - blueviolet: [138,43,226], - brown: [165,42,42], - burlywood: [222,184,135], - cadetblue: [95,158,160], - chartreuse: [127,255,0], - chocolate: [210,105,30], - coral: [255,127,80], - cornflowerblue: [100,149,237], - cornsilk: [255,248,220], - crimson: [220,20,60], - cyan: [0,255,255], - darkblue: [0,0,139], - darkcyan: [0,139,139], - darkgoldenrod: [184,134,11], - darkgray: [169,169,169], - darkgreen: [0,100,0], - darkgrey: [169,169,169], - darkkhaki: [189,183,107], - darkmagenta: [139,0,139], - darkolivegreen: [85,107,47], - darkorange: [255,140,0], - darkorchid: [153,50,204], - darkred: [139,0,0], - darksalmon: [233,150,122], - darkseagreen: [143,188,143], - darkslateblue: [72,61,139], - darkslategray: [47,79,79], - darkslategrey: [47,79,79], - darkturquoise: [0,206,209], - darkviolet: [148,0,211], - deeppink: [255,20,147], - deepskyblue: [0,191,255], - dimgray: [105,105,105], - dimgrey: [105,105,105], - dodgerblue: [30,144,255], - firebrick: [178,34,34], - floralwhite: [255,250,240], - forestgreen: [34,139,34], - fuchsia: [255,0,255], - gainsboro: [220,220,220], - ghostwhite: [248,248,255], - gold: [255,215,0], - goldenrod: [218,165,32], - gray: [128,128,128], - green: [0,128,0], - greenyellow: [173,255,47], - grey: [128,128,128], - honeydew: [240,255,240], - hotpink: [255,105,180], - indianred: [205,92,92], - indigo: [75,0,130], - ivory: [255,255,240], - khaki: [240,230,140], - lavender: [230,230,250], - lavenderblush: [255,240,245], - lawngreen: [124,252,0], - lemonchiffon: [255,250,205], - lightblue: [173,216,230], - lightcoral: [240,128,128], - lightcyan: [224,255,255], - lightgoldenrodyellow: [250,250,210], - lightgray: [211,211,211], - lightgreen: [144,238,144], - lightgrey: [211,211,211], - lightpink: [255,182,193], - lightsalmon: [255,160,122], - lightseagreen: [32,178,170], - lightskyblue: [135,206,250], - lightslategray: [119,136,153], - lightslategrey: [119,136,153], - lightsteelblue: [176,196,222], - lightyellow: [255,255,224], - lime: [0,255,0], - limegreen: [50,205,50], - linen: [250,240,230], - magenta: [255,0,255], - maroon: [128,0,0], - mediumaquamarine: [102,205,170], - mediumblue: [0,0,205], - mediumorchid: [186,85,211], - mediumpurple: [147,112,219], - mediumseagreen: [60,179,113], - mediumslateblue: [123,104,238], - mediumspringgreen: [0,250,154], - mediumturquoise: [72,209,204], - mediumvioletred: [199,21,133], - midnightblue: [25,25,112], - mintcream: [245,255,250], - mistyrose: [255,228,225], - moccasin: [255,228,181], - navajowhite: [255,222,173], - navy: [0,0,128], - oldlace: [253,245,230], - olive: [128,128,0], - olivedrab: [107,142,35], - orange: [255,165,0], - orangered: [255,69,0], - orchid: [218,112,214], - palegoldenrod: [238,232,170], - palegreen: [152,251,152], - paleturquoise: [175,238,238], - palevioletred: [219,112,147], - papayawhip: [255,239,213], - peachpuff: [255,218,185], - peru: [205,133,63], - pink: [255,192,203], - plum: [221,160,221], - powderblue: [176,224,230], - purple: [128,0,128], - rebeccapurple: [102, 51, 153], - red: [255,0,0], - rosybrown: [188,143,143], - royalblue: [65,105,225], - saddlebrown: [139,69,19], - salmon: [250,128,114], - sandybrown: [244,164,96], - seagreen: [46,139,87], - seashell: [255,245,238], - sienna: [160,82,45], - silver: [192,192,192], - skyblue: [135,206,235], - slateblue: [106,90,205], - slategray: [112,128,144], - slategrey: [112,128,144], - snow: [255,250,250], - springgreen: [0,255,127], - steelblue: [70,130,180], - tan: [210,180,140], - teal: [0,128,128], - thistle: [216,191,216], - tomato: [255,99,71], - turquoise: [64,224,208], - violet: [238,130,238], - wheat: [245,222,179], - white: [255,255,255], - whitesmoke: [245,245,245], - yellow: [255,255,0], - yellowgreen: [154,205,50] - }; - - var reverseKeywords = {}; - for (var key in cssKeywords) { - reverseKeywords[JSON.stringify(cssKeywords[key])] = key; - } - -},{}],5:[function(require,module,exports){ - var conversions = require(4); - - var convert = function() { - return new Converter(); - } - - for (var func in conversions) { - // export Raw versions - convert[func + "Raw"] = (function(func) { - // accept array or plain args - return function(arg) { - if (typeof arg == "number") - arg = Array.prototype.slice.call(arguments); - return conversions[func](arg); - } - })(func); - - var pair = /(\w+)2(\w+)/.exec(func), - from = pair[1], - to = pair[2]; - - // export rgb2hsl and ["rgb"]["hsl"] - convert[from] = convert[from] || {}; - - convert[from][to] = convert[func] = (function(func) { - return function(arg) { - if (typeof arg == "number") - arg = Array.prototype.slice.call(arguments); - - var val = conversions[func](arg); - if (typeof val == "string" || val === undefined) - return val; // keyword - - for (var i = 0; i < val.length; i++) - val[i] = Math.round(val[i]); - return val; - } - })(func); - } - - - /* Converter does lazy conversion and caching */ - var Converter = function() { - this.convs = {}; - }; - - /* Either get the values for a space or - set the values for a space, depending on args */ - Converter.prototype.routeSpace = function(space, args) { - var values = args[0]; - if (values === undefined) { - // color.rgb() - return this.getValues(space); - } - // color.rgb(10, 10, 10) - if (typeof values == "number") { - values = Array.prototype.slice.call(args); - } - - return this.setValues(space, values); - }; - - /* Set the values for a space, invalidating cache */ - Converter.prototype.setValues = function(space, values) { - this.space = space; - this.convs = {}; - this.convs[space] = values; - return this; - }; - - /* Get the values for a space. If there's already - a conversion for the space, fetch it, otherwise - compute it */ - Converter.prototype.getValues = function(space) { - var vals = this.convs[space]; - if (!vals) { - var fspace = this.space, - from = this.convs[fspace]; - vals = convert[fspace][space](from); - - this.convs[space] = vals; - } - return vals; - }; - - ["rgb", "hsl", "hsv", "cmyk", "keyword"].forEach(function(space) { - Converter.prototype[space] = function(vals) { - return this.routeSpace(space, arguments); - } - }); - - module.exports = convert; -},{"4":4}],6:[function(require,module,exports){ - module.exports = { - "aliceblue": [240, 248, 255], - "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], - "aquamarine": [127, 255, 212], - "azure": [240, 255, 255], - "beige": [245, 245, 220], - "bisque": [255, 228, 196], - "black": [0, 0, 0], - "blanchedalmond": [255, 235, 205], - "blue": [0, 0, 255], - "blueviolet": [138, 43, 226], - "brown": [165, 42, 42], - "burlywood": [222, 184, 135], - "cadetblue": [95, 158, 160], - "chartreuse": [127, 255, 0], - "chocolate": [210, 105, 30], - "coral": [255, 127, 80], - "cornflowerblue": [100, 149, 237], - "cornsilk": [255, 248, 220], - "crimson": [220, 20, 60], - "cyan": [0, 255, 255], - "darkblue": [0, 0, 139], - "darkcyan": [0, 139, 139], - "darkgoldenrod": [184, 134, 11], - "darkgray": [169, 169, 169], - "darkgreen": [0, 100, 0], - "darkgrey": [169, 169, 169], - "darkkhaki": [189, 183, 107], - "darkmagenta": [139, 0, 139], - "darkolivegreen": [85, 107, 47], - "darkorange": [255, 140, 0], - "darkorchid": [153, 50, 204], - "darkred": [139, 0, 0], - "darksalmon": [233, 150, 122], - "darkseagreen": [143, 188, 143], - "darkslateblue": [72, 61, 139], - "darkslategray": [47, 79, 79], - "darkslategrey": [47, 79, 79], - "darkturquoise": [0, 206, 209], - "darkviolet": [148, 0, 211], - "deeppink": [255, 20, 147], - "deepskyblue": [0, 191, 255], - "dimgray": [105, 105, 105], - "dimgrey": [105, 105, 105], - "dodgerblue": [30, 144, 255], - "firebrick": [178, 34, 34], - "floralwhite": [255, 250, 240], - "forestgreen": [34, 139, 34], - "fuchsia": [255, 0, 255], - "gainsboro": [220, 220, 220], - "ghostwhite": [248, 248, 255], - "gold": [255, 215, 0], - "goldenrod": [218, 165, 32], - "gray": [128, 128, 128], - "green": [0, 128, 0], - "greenyellow": [173, 255, 47], - "grey": [128, 128, 128], - "honeydew": [240, 255, 240], - "hotpink": [255, 105, 180], - "indianred": [205, 92, 92], - "indigo": [75, 0, 130], - "ivory": [255, 255, 240], - "khaki": [240, 230, 140], - "lavender": [230, 230, 250], - "lavenderblush": [255, 240, 245], - "lawngreen": [124, 252, 0], - "lemonchiffon": [255, 250, 205], - "lightblue": [173, 216, 230], - "lightcoral": [240, 128, 128], - "lightcyan": [224, 255, 255], - "lightgoldenrodyellow": [250, 250, 210], - "lightgray": [211, 211, 211], - "lightgreen": [144, 238, 144], - "lightgrey": [211, 211, 211], - "lightpink": [255, 182, 193], - "lightsalmon": [255, 160, 122], - "lightseagreen": [32, 178, 170], - "lightskyblue": [135, 206, 250], - "lightslategray": [119, 136, 153], - "lightslategrey": [119, 136, 153], - "lightsteelblue": [176, 196, 222], - "lightyellow": [255, 255, 224], - "lime": [0, 255, 0], - "limegreen": [50, 205, 50], - "linen": [250, 240, 230], - "magenta": [255, 0, 255], - "maroon": [128, 0, 0], - "mediumaquamarine": [102, 205, 170], - "mediumblue": [0, 0, 205], - "mediumorchid": [186, 85, 211], - "mediumpurple": [147, 112, 219], - "mediumseagreen": [60, 179, 113], - "mediumslateblue": [123, 104, 238], - "mediumspringgreen": [0, 250, 154], - "mediumturquoise": [72, 209, 204], - "mediumvioletred": [199, 21, 133], - "midnightblue": [25, 25, 112], - "mintcream": [245, 255, 250], - "mistyrose": [255, 228, 225], - "moccasin": [255, 228, 181], - "navajowhite": [255, 222, 173], - "navy": [0, 0, 128], - "oldlace": [253, 245, 230], - "olive": [128, 128, 0], - "olivedrab": [107, 142, 35], - "orange": [255, 165, 0], - "orangered": [255, 69, 0], - "orchid": [218, 112, 214], - "palegoldenrod": [238, 232, 170], - "palegreen": [152, 251, 152], - "paleturquoise": [175, 238, 238], - "palevioletred": [219, 112, 147], - "papayawhip": [255, 239, 213], - "peachpuff": [255, 218, 185], - "peru": [205, 133, 63], - "pink": [255, 192, 203], - "plum": [221, 160, 221], - "powderblue": [176, 224, 230], - "purple": [128, 0, 128], - "rebeccapurple": [102, 51, 153], - "red": [255, 0, 0], - "rosybrown": [188, 143, 143], - "royalblue": [65, 105, 225], - "saddlebrown": [139, 69, 19], - "salmon": [250, 128, 114], - "sandybrown": [244, 164, 96], - "seagreen": [46, 139, 87], - "seashell": [255, 245, 238], - "sienna": [160, 82, 45], - "silver": [192, 192, 192], - "skyblue": [135, 206, 235], - "slateblue": [106, 90, 205], - "slategray": [112, 128, 144], - "slategrey": [112, 128, 144], - "snow": [255, 250, 250], - "springgreen": [0, 255, 127], - "steelblue": [70, 130, 180], - "tan": [210, 180, 140], - "teal": [0, 128, 128], - "thistle": [216, 191, 216], - "tomato": [255, 99, 71], - "turquoise": [64, 224, 208], - "violet": [238, 130, 238], - "wheat": [245, 222, 179], - "white": [255, 255, 255], - "whitesmoke": [245, 245, 245], - "yellow": [255, 255, 0], - "yellowgreen": [154, 205, 50] - }; -},{}],7:[function(require,module,exports){ - /** - * @namespace Chart - */ - var Chart = require(28)(); - - require(26)(Chart); - require(42)(Chart); - require(22)(Chart); - require(31)(Chart); - require(25)(Chart); - require(21)(Chart); - require(23)(Chart); - require(24)(Chart); - require(29)(Chart); - require(33)(Chart); - require(34)(Chart); - require(32)(Chart); - require(35)(Chart); - require(30)(Chart); - require(27)(Chart); - require(36)(Chart); - - require(37)(Chart); - require(38)(Chart); - require(39)(Chart); - require(40)(Chart); - - require(45)(Chart); - require(43)(Chart); - require(44)(Chart); - require(46)(Chart); - require(47)(Chart); - require(48)(Chart); - -// Controllers must be loaded after elements -// See Chart.core.datasetController.dataElementType - require(15)(Chart); - require(16)(Chart); - require(17)(Chart); - require(18)(Chart); - require(19)(Chart); - require(20)(Chart); - - require(8)(Chart); - require(9)(Chart); - require(10)(Chart); - require(11)(Chart); - require(12)(Chart); - require(13)(Chart); - require(14)(Chart); - - window.Chart = module.exports = Chart; - -},{"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16,"17":17,"18":18,"19":19,"20":20,"21":21,"22":22,"23":23,"24":24,"25":25,"26":26,"27":27,"28":28,"29":29,"30":30,"31":31,"32":32,"33":33,"34":34,"35":35,"36":36,"37":37,"38":38,"39":39,"40":40,"42":42,"43":43,"44":44,"45":45,"46":46,"47":47,"48":48,"8":8,"9":9}],8:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.Bar = function(context, config) { - config.type = 'bar'; - - return new Chart(context, config); - }; - - }; - -},{}],9:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.Bubble = function(context, config) { - config.type = 'bubble'; - return new Chart(context, config); - }; - - }; - -},{}],10:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.Doughnut = function(context, config) { - config.type = 'doughnut'; - - return new Chart(context, config); - }; - - }; - -},{}],11:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.Line = function(context, config) { - config.type = 'line'; - - return new Chart(context, config); - }; - - }; - -},{}],12:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.PolarArea = function(context, config) { - config.type = 'polarArea'; - - return new Chart(context, config); - }; - - }; - -},{}],13:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - Chart.Radar = function(context, config) { - config.type = 'radar'; - - return new Chart(context, config); - }; - - }; - -},{}],14:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var defaultConfig = { - hover: { - mode: 'single' - }, - - scales: { - xAxes: [{ - type: 'linear', // scatter should not use a category axis - position: 'bottom', - id: 'x-axis-1' // need an ID so datasets can reference the scale - }], - yAxes: [{ - type: 'linear', - position: 'left', - id: 'y-axis-1' - }] - }, - - tooltips: { - callbacks: { - title: function() { - // Title doesn't make sense for scatter since we format the data as a point - return ''; - }, - label: function(tooltipItem) { - return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')'; - } - } - } - }; - - // Register the default config for this type - Chart.defaults.scatter = defaultConfig; - - // Scatter charts use line controllers - Chart.controllers.scatter = Chart.controllers.line; - - Chart.Scatter = function(context, config) { - config.type = 'scatter'; - return new Chart(context, config); - }; - - }; - -},{}],15:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.bar = { - hover: { - mode: 'label' - }, - - scales: { - xAxes: [{ - type: 'category', - - // Specific to Bar Controller - categoryPercentage: 0.8, - barPercentage: 0.9, - - // grid line settings - gridLines: { - offsetGridLines: true - } - }], - yAxes: [{ - type: 'linear' - }] - } - }; - - Chart.controllers.bar = Chart.DatasetController.extend({ - - dataElementType: Chart.elements.Rectangle, - - initialize: function(chart, datasetIndex) { - Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex); - - var me = this; - var meta = me.getMeta(); - var dataset = me.getDataset(); - - meta.stack = dataset.stack; - // Use this to indicate that this is a bar dataset. - meta.bar = true; - }, - - // Correctly calculate the bar width accounting for stacks and the fact that not all bars are visible - getStackCount: function() { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - - var stacks = []; - helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) { - var dsMeta = me.chart.getDatasetMeta(datasetIndex); - if (dsMeta.bar && me.chart.isDatasetVisible(datasetIndex) && - (yScale.options.stacked === false || - (yScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) || - (yScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) { - stacks.push(dsMeta.stack); - } - }, me); - - return stacks.length; - }, - - update: function(reset) { - var me = this; - helpers.each(me.getMeta().data, function(rectangle, index) { - me.updateElement(rectangle, index, reset); - }, me); - }, - - updateElement: function(rectangle, index, reset) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var yScale = me.getScaleForId(meta.yAxisID); - var scaleBase = yScale.getBasePixel(); - var rectangleElementOptions = me.chart.options.elements.rectangle; - var custom = rectangle.custom || {}; - var dataset = me.getDataset(); - - rectangle._xScale = xScale; - rectangle._yScale = yScale; - rectangle._datasetIndex = me.index; - rectangle._index = index; - - var ruler = me.getRuler(index); // The index argument for compatible - rectangle._model = { - x: me.calculateBarX(index, me.index, ruler), - y: reset ? scaleBase : me.calculateBarY(index, me.index), - - // Tooltip - label: me.chart.data.labels[index], - datasetLabel: dataset.label, - - // Appearance - horizontal: false, - base: reset ? scaleBase : me.calculateBarBase(me.index, index), - width: me.calculateBarWidth(ruler), - backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor), - borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped, - borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor), - borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth) - }; - - rectangle.pivot(); - }, - - calculateBarBase: function(datasetIndex, index) { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - var base = yScale.getBaseValue(); - var original = base; - - if ((yScale.options.stacked === true) || - (yScale.options.stacked === undefined && meta.stack !== undefined)) { - var chart = me.chart; - var datasets = chart.data.datasets; - var value = Number(datasets[datasetIndex].data[index]); - - for (var i = 0; i < datasetIndex; i++) { - var currentDs = datasets[i]; - var currentDsMeta = chart.getDatasetMeta(i); - if (currentDsMeta.bar && currentDsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i) && - meta.stack === currentDsMeta.stack) { - var currentVal = Number(currentDs.data[index]); - base += value < 0 ? Math.min(currentVal, original) : Math.max(currentVal, original); - } - } - - return yScale.getPixelForValue(base); - } - - return yScale.getBasePixel(); - }, - - getRuler: function() { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var stackCount = me.getStackCount(); - - var tickWidth = xScale.width / xScale.ticks.length; - var categoryWidth = tickWidth * xScale.options.categoryPercentage; - var categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2; - var fullBarWidth = categoryWidth / stackCount; - - var barWidth = fullBarWidth * xScale.options.barPercentage; - var barSpacing = fullBarWidth - (fullBarWidth * xScale.options.barPercentage); - - return { - stackCount: stackCount, - tickWidth: tickWidth, - categoryWidth: categoryWidth, - categorySpacing: categorySpacing, - fullBarWidth: fullBarWidth, - barWidth: barWidth, - barSpacing: barSpacing - }; - }, - - calculateBarWidth: function(ruler) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - if (xScale.options.barThickness) { - return xScale.options.barThickness; - } - return ruler.barWidth; - }, - - // Get stack index from the given dataset index accounting for stacks and the fact that not all bars are visible - getStackIndex: function(datasetIndex) { - var me = this; - var meta = me.chart.getDatasetMeta(datasetIndex); - var yScale = me.getScaleForId(meta.yAxisID); - var dsMeta, j; - var stacks = [meta.stack]; - - for (j = 0; j < datasetIndex; ++j) { - dsMeta = this.chart.getDatasetMeta(j); - if (dsMeta.bar && this.chart.isDatasetVisible(j) && - (yScale.options.stacked === false || - (yScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) || - (yScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) { - stacks.push(dsMeta.stack); - } - } - - return stacks.length - 1; - }, - - calculateBarX: function(index, datasetIndex, ruler) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var stackIndex = me.getStackIndex(datasetIndex); - var leftTick = xScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo); - leftTick -= me.chart.isCombo ? (ruler.tickWidth / 2) : 0; - - return leftTick + - (ruler.barWidth / 2) + - ruler.categorySpacing + - (ruler.barWidth * stackIndex) + - (ruler.barSpacing / 2) + - (ruler.barSpacing * stackIndex); - }, - - calculateBarY: function(index, datasetIndex) { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - var value = Number(me.getDataset().data[index]); - - if (yScale.options.stacked || - (yScale.options.stacked === undefined && meta.stack !== undefined)) { - var base = yScale.getBaseValue(); - var sumPos = base, - sumNeg = base; - - for (var i = 0; i < datasetIndex; i++) { - var ds = me.chart.data.datasets[i]; - var dsMeta = me.chart.getDatasetMeta(i); - if (dsMeta.bar && dsMeta.yAxisID === yScale.id && me.chart.isDatasetVisible(i) && - meta.stack === dsMeta.stack) { - var stackedVal = Number(ds.data[index]); - if (stackedVal < 0) { - sumNeg += stackedVal || 0; - } else { - sumPos += stackedVal || 0; - } - } - } - - if (value < 0) { - return yScale.getPixelForValue(sumNeg + value); - } - return yScale.getPixelForValue(sumPos + value); - } - - return yScale.getPixelForValue(value); - }, - - draw: function(ease) { - var me = this; - var easingDecimal = ease || 1; - var metaData = me.getMeta().data; - var dataset = me.getDataset(); - var i, len; - - Chart.canvasHelpers.clipArea(me.chart.chart.ctx, me.chart.chartArea); - for (i = 0, len = metaData.length; i < len; ++i) { - var d = dataset.data[i]; - if (d !== null && d !== undefined && !isNaN(d)) { - metaData[i].transition(easingDecimal).draw(); - } - } - Chart.canvasHelpers.unclipArea(me.chart.chart.ctx); - }, - - setHoverStyle: function(rectangle) { - var dataset = this.chart.data.datasets[rectangle._datasetIndex]; - var index = rectangle._index; - - var custom = rectangle.custom || {}; - var model = rectangle._model; - model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor)); - model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor)); - model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth); - }, - - removeHoverStyle: function(rectangle) { - var dataset = this.chart.data.datasets[rectangle._datasetIndex]; - var index = rectangle._index; - var custom = rectangle.custom || {}; - var model = rectangle._model; - var rectangleElementOptions = this.chart.options.elements.rectangle; - - model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor); - model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor); - model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth); - } - - }); - - - // including horizontalBar in the bar file, instead of a file of its own - // it extends bar (like pie extends doughnut) - Chart.defaults.horizontalBar = { - hover: { - mode: 'label' - }, - - scales: { - xAxes: [{ - type: 'linear', - position: 'bottom' - }], - yAxes: [{ - position: 'left', - type: 'category', - - // Specific to Horizontal Bar Controller - categoryPercentage: 0.8, - barPercentage: 0.9, - - // grid line settings - gridLines: { - offsetGridLines: true - } - }] - }, - elements: { - rectangle: { - borderSkipped: 'left' - } - }, - tooltips: { - callbacks: { - title: function(tooltipItems, data) { - // Pick first xLabel for now - var title = ''; - - if (tooltipItems.length > 0) { - if (tooltipItems[0].yLabel) { - title = tooltipItems[0].yLabel; - } else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) { - title = data.labels[tooltipItems[0].index]; - } - } - - return title; - }, - label: function(tooltipItem, data) { - var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || ''; - return datasetLabel + ': ' + tooltipItem.xLabel; - } - } - } - }; - - Chart.controllers.horizontalBar = Chart.controllers.bar.extend({ - - // Correctly calculate the bar width accounting for stacks and the fact that not all bars are visible - getStackCount: function() { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - - var stacks = []; - helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) { - var dsMeta = me.chart.getDatasetMeta(datasetIndex); - if (dsMeta.bar && me.chart.isDatasetVisible(datasetIndex) && - (xScale.options.stacked === false || - (xScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) || - (xScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) { - stacks.push(dsMeta.stack); - } - }, me); - - return stacks.length; - }, - - updateElement: function(rectangle, index, reset) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var yScale = me.getScaleForId(meta.yAxisID); - var scaleBase = xScale.getBasePixel(); - var custom = rectangle.custom || {}; - var dataset = me.getDataset(); - var rectangleElementOptions = me.chart.options.elements.rectangle; - - rectangle._xScale = xScale; - rectangle._yScale = yScale; - rectangle._datasetIndex = me.index; - rectangle._index = index; - - var ruler = me.getRuler(index); // The index argument for compatible - rectangle._model = { - x: reset ? scaleBase : me.calculateBarX(index, me.index), - y: me.calculateBarY(index, me.index, ruler), - - // Tooltip - label: me.chart.data.labels[index], - datasetLabel: dataset.label, - - // Appearance - horizontal: true, - base: reset ? scaleBase : me.calculateBarBase(me.index, index), - height: me.calculateBarHeight(ruler), - backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor), - borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped, - borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor), - borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth) - }; - - rectangle.pivot(); - }, - - calculateBarBase: function(datasetIndex, index) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var base = xScale.getBaseValue(); - var originalBase = base; - - if (xScale.options.stacked || - (xScale.options.stacked === undefined && meta.stack !== undefined)) { - var chart = me.chart; - var datasets = chart.data.datasets; - var value = Number(datasets[datasetIndex].data[index]); - - for (var i = 0; i < datasetIndex; i++) { - var currentDs = datasets[i]; - var currentDsMeta = chart.getDatasetMeta(i); - if (currentDsMeta.bar && currentDsMeta.xAxisID === xScale.id && chart.isDatasetVisible(i) && - meta.stack === currentDsMeta.stack) { - var currentVal = Number(currentDs.data[index]); - base += value < 0 ? Math.min(currentVal, originalBase) : Math.max(currentVal, originalBase); - } - } - - return xScale.getPixelForValue(base); - } - - return xScale.getBasePixel(); - }, - - getRuler: function() { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - var stackCount = me.getStackCount(); - - var tickHeight = yScale.height / yScale.ticks.length; - var categoryHeight = tickHeight * yScale.options.categoryPercentage; - var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2; - var fullBarHeight = categoryHeight / stackCount; - - var barHeight = fullBarHeight * yScale.options.barPercentage; - var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage); - - return { - stackCount: stackCount, - tickHeight: tickHeight, - categoryHeight: categoryHeight, - categorySpacing: categorySpacing, - fullBarHeight: fullBarHeight, - barHeight: barHeight, - barSpacing: barSpacing - }; - }, - - calculateBarHeight: function(ruler) { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - if (yScale.options.barThickness) { - return yScale.options.barThickness; - } - return ruler.barHeight; - }, - - // Get stack index from the given dataset index accounting for stacks and the fact that not all bars are visible - getStackIndex: function(datasetIndex) { - var me = this; - var meta = me.chart.getDatasetMeta(datasetIndex); - var xScale = me.getScaleForId(meta.xAxisID); - var dsMeta, j; - var stacks = [meta.stack]; - - for (j = 0; j < datasetIndex; ++j) { - dsMeta = this.chart.getDatasetMeta(j); - if (dsMeta.bar && this.chart.isDatasetVisible(j) && - (xScale.options.stacked === false || - (xScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) || - (xScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) { - stacks.push(dsMeta.stack); - } - } - - return stacks.length - 1; - }, - - calculateBarX: function(index, datasetIndex) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var value = Number(me.getDataset().data[index]); - - if (xScale.options.stacked || - (xScale.options.stacked === undefined && meta.stack !== undefined)) { - var base = xScale.getBaseValue(); - var sumPos = base, - sumNeg = base; - - for (var i = 0; i < datasetIndex; i++) { - var ds = me.chart.data.datasets[i]; - var dsMeta = me.chart.getDatasetMeta(i); - if (dsMeta.bar && dsMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i) && - meta.stack === dsMeta.stack) { - var stackedVal = Number(ds.data[index]); - if (stackedVal < 0) { - sumNeg += stackedVal || 0; - } else { - sumPos += stackedVal || 0; - } - } - } - - if (value < 0) { - return xScale.getPixelForValue(sumNeg + value); - } - return xScale.getPixelForValue(sumPos + value); - } - - return xScale.getPixelForValue(value); - }, - - calculateBarY: function(index, datasetIndex, ruler) { - var me = this; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - var stackIndex = me.getStackIndex(datasetIndex); - var topTick = yScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo); - topTick -= me.chart.isCombo ? (ruler.tickHeight / 2) : 0; - - return topTick + - (ruler.barHeight / 2) + - ruler.categorySpacing + - (ruler.barHeight * stackIndex) + - (ruler.barSpacing / 2) + - (ruler.barSpacing * stackIndex); - } - }); - }; - -},{}],16:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.bubble = { - hover: { - mode: 'single' - }, - - scales: { - xAxes: [{ - type: 'linear', // bubble should probably use a linear scale by default - position: 'bottom', - id: 'x-axis-0' // need an ID so datasets can reference the scale - }], - yAxes: [{ - type: 'linear', - position: 'left', - id: 'y-axis-0' - }] - }, - - tooltips: { - callbacks: { - title: function() { - // Title doesn't make sense for scatter since we format the data as a point - return ''; - }, - label: function(tooltipItem, data) { - var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || ''; - var dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; - return datasetLabel + ': (' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ', ' + dataPoint.r + ')'; - } - } - } - }; - - Chart.controllers.bubble = Chart.DatasetController.extend({ - - dataElementType: Chart.elements.Point, - - update: function(reset) { - var me = this; - var meta = me.getMeta(); - var points = meta.data; - - // Update Points - helpers.each(points, function(point, index) { - me.updateElement(point, index, reset); - }); - }, - - updateElement: function(point, index, reset) { - var me = this; - var meta = me.getMeta(); - var xScale = me.getScaleForId(meta.xAxisID); - var yScale = me.getScaleForId(meta.yAxisID); - - var custom = point.custom || {}; - var dataset = me.getDataset(); - var data = dataset.data[index]; - var pointElementOptions = me.chart.options.elements.point; - var dsIndex = me.index; - - helpers.extend(point, { - // Utility - _xScale: xScale, - _yScale: yScale, - _datasetIndex: dsIndex, - _index: index, - - // Desired view properties - _model: { - x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex, me.chart.isCombo), - y: reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex), - // Appearance - radius: reset ? 0 : custom.radius ? custom.radius : me.getRadius(data), - - // Tooltip - hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius) - } - }); - - // Trick to reset the styles of the point - Chart.DatasetController.prototype.removeHoverStyle.call(me, point, pointElementOptions); - - var model = point._model; - model.skip = custom.skip ? custom.skip : (isNaN(model.x) || isNaN(model.y)); - - point.pivot(); - }, - - getRadius: function(value) { - return value.r || this.chart.options.elements.point.radius; - }, - - setHoverStyle: function(point) { - var me = this; - Chart.DatasetController.prototype.setHoverStyle.call(me, point); - - // Radius - var dataset = me.chart.data.datasets[point._datasetIndex]; - var index = point._index; - var custom = point.custom || {}; - var model = point._model; - model.radius = custom.hoverRadius ? custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, me.chart.options.elements.point.hoverRadius)) + me.getRadius(dataset.data[index]); - }, - - removeHoverStyle: function(point) { - var me = this; - Chart.DatasetController.prototype.removeHoverStyle.call(me, point, me.chart.options.elements.point); - - var dataVal = me.chart.data.datasets[point._datasetIndex].data[point._index]; - var custom = point.custom || {}; - var model = point._model; - - model.radius = custom.radius ? custom.radius : me.getRadius(dataVal); - } - }); - }; - -},{}],17:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers, - defaults = Chart.defaults; - - defaults.doughnut = { - animation: { - // Boolean - Whether we animate the rotation of the Doughnut - animateRotate: true, - // Boolean - Whether we animate scaling the Doughnut from the centre - animateScale: false - }, - aspectRatio: 1, - hover: { - mode: 'single' - }, - legendCallback: function(chart) { - var text = []; - text.push('<ul class="' + chart.id + '-legend">'); - - var data = chart.data; - var datasets = data.datasets; - var labels = data.labels; - - if (datasets.length) { - for (var i = 0; i < datasets[0].data.length; ++i) { - text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>'); - if (labels[i]) { - text.push(labels[i]); - } - text.push('</li>'); - } - } - - text.push('</ul>'); - return text.join(''); - }, - legend: { - labels: { - generateLabels: function(chart) { - var data = chart.data; - if (data.labels.length && data.datasets.length) { - return data.labels.map(function(label, i) { - var meta = chart.getDatasetMeta(0); - var ds = data.datasets[0]; - var arc = meta.data[i]; - var custom = arc && arc.custom || {}; - var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault; - var arcOpts = chart.options.elements.arc; - var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor); - var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor); - var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth); - - return { - text: label, - fillStyle: fill, - strokeStyle: stroke, - lineWidth: bw, - hidden: isNaN(ds.data[i]) || meta.data[i].hidden, - - // Extra data used for toggling the correct item - index: i - }; - }); - } - return []; - } - }, - - onClick: function(e, legendItem) { - var index = legendItem.index; - var chart = this.chart; - var i, ilen, meta; - - for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { - meta = chart.getDatasetMeta(i); - // toggle visibility of index if exists - if (meta.data[index]) { - meta.data[index].hidden = !meta.data[index].hidden; - } - } - - chart.update(); - } - }, - - // The percentage of the chart that we cut out of the middle. - cutoutPercentage: 50, - - // The rotation of the chart, where the first data arc begins. - rotation: Math.PI * -0.5, - - // The total circumference of the chart. - circumference: Math.PI * 2.0, - - // Need to override these to give a nice default - tooltips: { - callbacks: { - title: function() { - return ''; - }, - label: function(tooltipItem, data) { - var dataLabel = data.labels[tooltipItem.index]; - var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; - - if (helpers.isArray(dataLabel)) { - // show value on first line of multiline label - // need to clone because we are changing the value - dataLabel = dataLabel.slice(); - dataLabel[0] += value; - } else { - dataLabel += value; - } - - return dataLabel; - } - } - } - }; - - defaults.pie = helpers.clone(defaults.doughnut); - helpers.extend(defaults.pie, { - cutoutPercentage: 0 - }); - - - Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({ - - dataElementType: Chart.elements.Arc, - - linkScales: helpers.noop, - - // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly - getRingIndex: function(datasetIndex) { - var ringIndex = 0; - - for (var j = 0; j < datasetIndex; ++j) { - if (this.chart.isDatasetVisible(j)) { - ++ringIndex; - } - } - - return ringIndex; - }, - - update: function(reset) { - var me = this; - var chart = me.chart, - chartArea = chart.chartArea, - opts = chart.options, - arcOpts = opts.elements.arc, - availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth, - availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth, - minSize = Math.min(availableWidth, availableHeight), - offset = { - x: 0, - y: 0 - }, - meta = me.getMeta(), - cutoutPercentage = opts.cutoutPercentage, - circumference = opts.circumference; - - // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc - if (circumference < Math.PI * 2.0) { - var startAngle = opts.rotation % (Math.PI * 2.0); - startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0); - var endAngle = startAngle + circumference; - var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)}; - var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)}; - var contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle); - var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle); - var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle); - var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle); - var cutout = cutoutPercentage / 100.0; - var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))}; - var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))}; - var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5}; - minSize = Math.min(availableWidth / size.width, availableHeight / size.height); - offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5}; - } - - chart.borderWidth = me.getMaxBorderWidth(meta.data); - chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0); - chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0); - chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount(); - chart.offsetX = offset.x * chart.outerRadius; - chart.offsetY = offset.y * chart.outerRadius; - - meta.total = me.calculateTotal(); - - me.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index)); - me.innerRadius = Math.max(me.outerRadius - chart.radiusLength, 0); - - helpers.each(meta.data, function(arc, index) { - me.updateElement(arc, index, reset); - }); - }, - - updateElement: function(arc, index, reset) { - var me = this; - var chart = me.chart, - chartArea = chart.chartArea, - opts = chart.options, - animationOpts = opts.animation, - centerX = (chartArea.left + chartArea.right) / 2, - centerY = (chartArea.top + chartArea.bottom) / 2, - startAngle = opts.rotation, // non reset case handled later - endAngle = opts.rotation, // non reset case handled later - dataset = me.getDataset(), - circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)), - innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius, - outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius, - valueAtIndexOrDefault = helpers.getValueAtIndexOrDefault; - - helpers.extend(arc, { - // Utility - _datasetIndex: me.index, - _index: index, - - // Desired view properties - _model: { - x: centerX + chart.offsetX, - y: centerY + chart.offsetY, - startAngle: startAngle, - endAngle: endAngle, - circumference: circumference, - outerRadius: outerRadius, - innerRadius: innerRadius, - label: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index]) - } - }); - - var model = arc._model; - // Resets the visual styles - this.removeHoverStyle(arc); - - // Set correct angles if not resetting - if (!reset || !animationOpts.animateRotate) { - if (index === 0) { - model.startAngle = opts.rotation; - } else { - model.startAngle = me.getMeta().data[index - 1]._model.endAngle; - } - - model.endAngle = model.startAngle + model.circumference; - } - - arc.pivot(); - }, - - removeHoverStyle: function(arc) { - Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc); - }, - - calculateTotal: function() { - var dataset = this.getDataset(); - var meta = this.getMeta(); - var total = 0; - var value; - - helpers.each(meta.data, function(element, index) { - value = dataset.data[index]; - if (!isNaN(value) && !element.hidden) { - total += Math.abs(value); - } - }); - - /* if (total === 0) { - total = NaN; - }*/ - - return total; - }, - - calculateCircumference: function(value) { - var total = this.getMeta().total; - if (total > 0 && !isNaN(value)) { - return (Math.PI * 2.0) * (value / total); - } - return 0; - }, - - // gets the max border or hover width to properly scale pie charts - getMaxBorderWidth: function(elements) { - var max = 0, - index = this.index, - length = elements.length, - borderWidth, - hoverWidth; - - for (var i = 0; i < length; i++) { - borderWidth = elements[i]._model ? elements[i]._model.borderWidth : 0; - hoverWidth = elements[i]._chart ? elements[i]._chart.config.data.datasets[index].hoverBorderWidth : 0; - - max = borderWidth > max ? borderWidth : max; - max = hoverWidth > max ? hoverWidth : max; - } - return max; - } - }); - }; - -},{}],18:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.line = { - showLines: true, - spanGaps: false, - - hover: { - mode: 'label' - }, - - scales: { - xAxes: [{ - type: 'category', - id: 'x-axis-0' - }], - yAxes: [{ - type: 'linear', - id: 'y-axis-0' - }] - } - }; - - function lineEnabled(dataset, options) { - return helpers.getValueOrDefault(dataset.showLine, options.showLines); - } - - Chart.controllers.line = Chart.DatasetController.extend({ - - datasetElementType: Chart.elements.Line, - - dataElementType: Chart.elements.Point, - - update: function(reset) { - var me = this; - var meta = me.getMeta(); - var line = meta.dataset; - var points = meta.data || []; - var options = me.chart.options; - var lineElementOptions = options.elements.line; - var scale = me.getScaleForId(meta.yAxisID); - var i, ilen, custom; - var dataset = me.getDataset(); - var showLine = lineEnabled(dataset, options); - - // Update Line - if (showLine) { - custom = line.custom || {}; - - // Compatibility: If the properties are defined with only the old name, use those values - if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) { - dataset.lineTension = dataset.tension; - } - - // Utility - line._scale = scale; - line._datasetIndex = me.index; - // Data - line._children = points; - // Model - line._model = { - // Appearance - // The default behavior of lines is to break at null values, according - // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158 - // This option gives lines the ability to span gaps - spanGaps: dataset.spanGaps ? dataset.spanGaps : options.spanGaps, - tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension), - backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor), - borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth), - borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor), - borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle), - borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash), - borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset), - borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle), - fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill), - steppedLine: custom.steppedLine ? custom.steppedLine : helpers.getValueOrDefault(dataset.steppedLine, lineElementOptions.stepped), - cubicInterpolationMode: custom.cubicInterpolationMode ? custom.cubicInterpolationMode : helpers.getValueOrDefault(dataset.cubicInterpolationMode, lineElementOptions.cubicInterpolationMode), - // Scale - scaleTop: scale.top, - scaleBottom: scale.bottom, - scaleZero: scale.getBasePixel() - }; - - line.pivot(); - } - - // Update Points - for (i=0, ilen=points.length; i<ilen; ++i) { - me.updateElement(points[i], i, reset); - } - - if (showLine && line._model.tension !== 0) { - me.updateBezierControlPoints(); - } - - // Now pivot the point for animation - for (i=0, ilen=points.length; i<ilen; ++i) { - points[i].pivot(); - } - }, - - getPointBackgroundColor: function(point, index) { - var backgroundColor = this.chart.options.elements.point.backgroundColor; - var dataset = this.getDataset(); - var custom = point.custom || {}; - - if (custom.backgroundColor) { - backgroundColor = custom.backgroundColor; - } else if (dataset.pointBackgroundColor) { - backgroundColor = helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor); - } else if (dataset.backgroundColor) { - backgroundColor = dataset.backgroundColor; - } - - return backgroundColor; - }, - - getPointBorderColor: function(point, index) { - var borderColor = this.chart.options.elements.point.borderColor; - var dataset = this.getDataset(); - var custom = point.custom || {}; - - if (custom.borderColor) { - borderColor = custom.borderColor; - } else if (dataset.pointBorderColor) { - borderColor = helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor); - } else if (dataset.borderColor) { - borderColor = dataset.borderColor; - } - - return borderColor; - }, - - getPointBorderWidth: function(point, index) { - var borderWidth = this.chart.options.elements.point.borderWidth; - var dataset = this.getDataset(); - var custom = point.custom || {}; - - if (!isNaN(custom.borderWidth)) { - borderWidth = custom.borderWidth; - } else if (!isNaN(dataset.pointBorderWidth)) { - borderWidth = helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth); - } else if (!isNaN(dataset.borderWidth)) { - borderWidth = dataset.borderWidth; - } - - return borderWidth; - }, - - updateElement: function(point, index, reset) { - var me = this; - var meta = me.getMeta(); - var custom = point.custom || {}; - var dataset = me.getDataset(); - var datasetIndex = me.index; - var value = dataset.data[index]; - var yScale = me.getScaleForId(meta.yAxisID); - var xScale = me.getScaleForId(meta.xAxisID); - var pointOptions = me.chart.options.elements.point; - var x, y; - var labels = me.chart.data.labels || []; - var includeOffset = (labels.length === 1 || dataset.data.length === 1) || me.chart.isCombo; - - // Compatibility: If the properties are defined with only the old name, use those values - if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) { - dataset.pointRadius = dataset.radius; - } - if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) { - dataset.pointHitRadius = dataset.hitRadius; - } - - x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex, includeOffset); - y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex); - - // Utility - point._xScale = xScale; - point._yScale = yScale; - point._datasetIndex = datasetIndex; - point._index = index; - - // Desired view properties - point._model = { - x: x, - y: y, - skip: custom.skip || isNaN(x) || isNaN(y), - // Appearance - radius: custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius), - pointStyle: custom.pointStyle || helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle), - backgroundColor: me.getPointBackgroundColor(point, index), - borderColor: me.getPointBorderColor(point, index), - borderWidth: me.getPointBorderWidth(point, index), - tension: meta.dataset._model ? meta.dataset._model.tension : 0, - steppedLine: meta.dataset._model ? meta.dataset._model.steppedLine : false, - // Tooltip - hitRadius: custom.hitRadius || helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius) - }; - }, - - calculatePointY: function(value, index, datasetIndex) { - var me = this; - var chart = me.chart; - var meta = me.getMeta(); - var yScale = me.getScaleForId(meta.yAxisID); - var sumPos = 0; - var sumNeg = 0; - var i, ds, dsMeta; - - if (yScale.options.stacked) { - for (i = 0; i < datasetIndex; i++) { - ds = chart.data.datasets[i]; - dsMeta = chart.getDatasetMeta(i); - if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) { - var stackedRightValue = Number(yScale.getRightValue(ds.data[index])); - if (stackedRightValue < 0) { - sumNeg += stackedRightValue || 0; - } else { - sumPos += stackedRightValue || 0; - } - } - } - - var rightValue = Number(yScale.getRightValue(value)); - if (rightValue < 0) { - return yScale.getPixelForValue(sumNeg + rightValue); - } - return yScale.getPixelForValue(sumPos + rightValue); - } - - return yScale.getPixelForValue(value); - }, - - updateBezierControlPoints: function() { - var me = this; - var meta = me.getMeta(); - var area = me.chart.chartArea; - var points = (meta.data || []); - var i, ilen, point, model, controlPoints; - - // Only consider points that are drawn in case the spanGaps option is used - if (meta.dataset._model.spanGaps) { - points = points.filter(function(pt) { - return !pt._model.skip; - }); - } - - function capControlPoint(pt, min, max) { - return Math.max(Math.min(pt, max), min); - } - - if (meta.dataset._model.cubicInterpolationMode === 'monotone') { - helpers.splineCurveMonotone(points); - } else { - for (i = 0, ilen = points.length; i < ilen; ++i) { - point = points[i]; - model = point._model; - controlPoints = helpers.splineCurve( - helpers.previousItem(points, i)._model, - model, - helpers.nextItem(points, i)._model, - meta.dataset._model.tension - ); - model.controlPointPreviousX = controlPoints.previous.x; - model.controlPointPreviousY = controlPoints.previous.y; - model.controlPointNextX = controlPoints.next.x; - model.controlPointNextY = controlPoints.next.y; - } - } - - if (me.chart.options.elements.line.capBezierPoints) { - for (i = 0, ilen = points.length; i < ilen; ++i) { - model = points[i]._model; - model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right); - model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom); - model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right); - model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom); - } - } - }, - - draw: function(ease) { - var me = this; - var meta = me.getMeta(); - var points = meta.data || []; - var easingDecimal = ease || 1; - var i, ilen; - - // Transition Point Locations - for (i=0, ilen=points.length; i<ilen; ++i) { - points[i].transition(easingDecimal); - } - - Chart.canvasHelpers.clipArea(me.chart.chart.ctx, me.chart.chartArea); - // Transition and Draw the line - if (lineEnabled(me.getDataset(), me.chart.options)) { - meta.dataset.transition(easingDecimal).draw(); - } - Chart.canvasHelpers.unclipArea(me.chart.chart.ctx); - - // Draw the points - for (i=0, ilen=points.length; i<ilen; ++i) { - points[i].draw(me.chart.chartArea); - } - }, - - setHoverStyle: function(point) { - // Point - var dataset = this.chart.data.datasets[point._datasetIndex]; - var index = point._index; - var custom = point.custom || {}; - var model = point._model; - - model.radius = custom.hoverRadius || helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius); - model.backgroundColor = custom.hoverBackgroundColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor)); - model.borderColor = custom.hoverBorderColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor)); - model.borderWidth = custom.hoverBorderWidth || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth); - }, - - removeHoverStyle: function(point) { - var me = this; - var dataset = me.chart.data.datasets[point._datasetIndex]; - var index = point._index; - var custom = point.custom || {}; - var model = point._model; - - // Compatibility: If the properties are defined with only the old name, use those values - if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) { - dataset.pointRadius = dataset.radius; - } - - model.radius = custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, me.chart.options.elements.point.radius); - model.backgroundColor = me.getPointBackgroundColor(point, index); - model.borderColor = me.getPointBorderColor(point, index); - model.borderWidth = me.getPointBorderWidth(point, index); - } - }); - }; - -},{}],19:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.polarArea = { - - scale: { - type: 'radialLinear', - lineArc: true, // so that lines are circular - ticks: { - beginAtZero: true - } - }, - - // Boolean - Whether to animate the rotation of the chart - animation: { - animateRotate: true, - animateScale: true - }, - - startAngle: -0.5 * Math.PI, - aspectRatio: 1, - legendCallback: function(chart) { - var text = []; - text.push('<ul class="' + chart.id + '-legend">'); - - var data = chart.data; - var datasets = data.datasets; - var labels = data.labels; - - if (datasets.length) { - for (var i = 0; i < datasets[0].data.length; ++i) { - text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>'); - if (labels[i]) { - text.push(labels[i]); - } - text.push('</li>'); - } - } - - text.push('</ul>'); - return text.join(''); - }, - legend: { - labels: { - generateLabels: function(chart) { - var data = chart.data; - if (data.labels.length && data.datasets.length) { - return data.labels.map(function(label, i) { - var meta = chart.getDatasetMeta(0); - var ds = data.datasets[0]; - var arc = meta.data[i]; - var custom = arc.custom || {}; - var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault; - var arcOpts = chart.options.elements.arc; - var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor); - var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor); - var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth); - - return { - text: label, - fillStyle: fill, - strokeStyle: stroke, - lineWidth: bw, - hidden: isNaN(ds.data[i]) || meta.data[i].hidden, - - // Extra data used for toggling the correct item - index: i - }; - }); - } - return []; - } - }, - - onClick: function(e, legendItem) { - var index = legendItem.index; - var chart = this.chart; - var i, ilen, meta; - - for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { - meta = chart.getDatasetMeta(i); - meta.data[index].hidden = !meta.data[index].hidden; - } - - chart.update(); - } - }, - - // Need to override these to give a nice default - tooltips: { - callbacks: { - title: function() { - return ''; - }, - label: function(tooltipItem, data) { - return data.labels[tooltipItem.index] + ': ' + tooltipItem.yLabel; - } - } - } - }; - - Chart.controllers.polarArea = Chart.DatasetController.extend({ - - dataElementType: Chart.elements.Arc, - - linkScales: helpers.noop, - - update: function(reset) { - var me = this; - var chart = me.chart; - var chartArea = chart.chartArea; - var meta = me.getMeta(); - var opts = chart.options; - var arcOpts = opts.elements.arc; - var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top); - chart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0); - chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0); - chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount(); - - me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index); - me.innerRadius = me.outerRadius - chart.radiusLength; - - meta.count = me.countVisibleElements(); - - helpers.each(meta.data, function(arc, index) { - me.updateElement(arc, index, reset); - }); - }, - - updateElement: function(arc, index, reset) { - var me = this; - var chart = me.chart; - var dataset = me.getDataset(); - var opts = chart.options; - var animationOpts = opts.animation; - var scale = chart.scale; - var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault; - var labels = chart.data.labels; - - var circumference = me.calculateCircumference(dataset.data[index]); - var centerX = scale.xCenter; - var centerY = scale.yCenter; - - // If there is NaN data before us, we need to calculate the starting angle correctly. - // We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data - var visibleCount = 0; - var meta = me.getMeta(); - for (var i = 0; i < index; ++i) { - if (!isNaN(dataset.data[i]) && !meta.data[i].hidden) { - ++visibleCount; - } - } - - // var negHalfPI = -0.5 * Math.PI; - var datasetStartAngle = opts.startAngle; - var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); - var startAngle = datasetStartAngle + (circumference * visibleCount); - var endAngle = startAngle + (arc.hidden ? 0 : circumference); - - var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); - - helpers.extend(arc, { - // Utility - _datasetIndex: me.index, - _index: index, - _scale: scale, - - // Desired view properties - _model: { - x: centerX, - y: centerY, - innerRadius: 0, - outerRadius: reset ? resetRadius : distance, - startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle, - endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle, - label: getValueAtIndexOrDefault(labels, index, labels[index]) - } - }); - - // Apply border and fill style - me.removeHoverStyle(arc); - - arc.pivot(); - }, - - removeHoverStyle: function(arc) { - Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc); - }, - - countVisibleElements: function() { - var dataset = this.getDataset(); - var meta = this.getMeta(); - var count = 0; - - helpers.each(meta.data, function(element, index) { - if (!isNaN(dataset.data[index]) && !element.hidden) { - count++; - } - }); - - return count; - }, - - calculateCircumference: function(value) { - var count = this.getMeta().count; - if (count > 0 && !isNaN(value)) { - return (2 * Math.PI) / count; - } - return 0; - } - }); - }; - -},{}],20:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.radar = { - aspectRatio: 1, - scale: { - type: 'radialLinear' - }, - elements: { - line: { - tension: 0 // no bezier in radar - } - } - }; - - Chart.controllers.radar = Chart.DatasetController.extend({ - - datasetElementType: Chart.elements.Line, - - dataElementType: Chart.elements.Point, - - linkScales: helpers.noop, - - update: function(reset) { - var me = this; - var meta = me.getMeta(); - var line = meta.dataset; - var points = meta.data; - var custom = line.custom || {}; - var dataset = me.getDataset(); - var lineElementOptions = me.chart.options.elements.line; - var scale = me.chart.scale; - - // Compatibility: If the properties are defined with only the old name, use those values - if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) { - dataset.lineTension = dataset.tension; - } - - helpers.extend(meta.dataset, { - // Utility - _datasetIndex: me.index, - // Data - _children: points, - _loop: true, - // Model - _model: { - // Appearance - tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension), - backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor), - borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth), - borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor), - fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill), - borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle), - borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash), - borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset), - borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle), - - // Scale - scaleTop: scale.top, - scaleBottom: scale.bottom, - scaleZero: scale.getBasePosition() - } - }); - - meta.dataset.pivot(); - - // Update Points - helpers.each(points, function(point, index) { - me.updateElement(point, index, reset); - }, me); - - // Update bezier control points - me.updateBezierControlPoints(); - }, - updateElement: function(point, index, reset) { - var me = this; - var custom = point.custom || {}; - var dataset = me.getDataset(); - var scale = me.chart.scale; - var pointElementOptions = me.chart.options.elements.point; - var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]); - - helpers.extend(point, { - // Utility - _datasetIndex: me.index, - _index: index, - _scale: scale, - - // Desired view properties - _model: { - x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales - y: reset ? scale.yCenter : pointPosition.y, - - // Appearance - tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, me.chart.options.elements.line.tension), - radius: custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius), - backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor), - borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor), - borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth), - pointStyle: custom.pointStyle ? custom.pointStyle : helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointElementOptions.pointStyle), - - // Tooltip - hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius) - } - }); - - point._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y)); - }, - updateBezierControlPoints: function() { - var chartArea = this.chart.chartArea; - var meta = this.getMeta(); - - helpers.each(meta.data, function(point, index) { - var model = point._model; - var controlPoints = helpers.splineCurve( - helpers.previousItem(meta.data, index, true)._model, - model, - helpers.nextItem(meta.data, index, true)._model, - model.tension - ); - - // Prevent the bezier going outside of the bounds of the graph - model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left); - model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top); - - model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left); - model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top); - - // Now pivot the point for animation - point.pivot(); - }); - }, - - draw: function(ease) { - var meta = this.getMeta(); - var easingDecimal = ease || 1; - - // Transition Point Locations - helpers.each(meta.data, function(point) { - point.transition(easingDecimal); - }); - - // Transition and Draw the line - meta.dataset.transition(easingDecimal).draw(); - - // Draw the points - helpers.each(meta.data, function(point) { - point.draw(); - }); - }, - - setHoverStyle: function(point) { - // Point - var dataset = this.chart.data.datasets[point._datasetIndex]; - var custom = point.custom || {}; - var index = point._index; - var model = point._model; - - model.radius = custom.hoverRadius ? custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius); - model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor)); - model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor)); - model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth); - }, - - removeHoverStyle: function(point) { - var dataset = this.chart.data.datasets[point._datasetIndex]; - var custom = point.custom || {}; - var index = point._index; - var model = point._model; - var pointElementOptions = this.chart.options.elements.point; - - model.radius = custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.radius, index, pointElementOptions.radius); - model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor); - model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor); - model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth); - } - }); - }; - -},{}],21:[function(require,module,exports){ - /* global window: false */ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.global.animation = { - duration: 1000, - easing: 'easeOutQuart', - onProgress: helpers.noop, - onComplete: helpers.noop - }; - - Chart.Animation = Chart.Element.extend({ - currentStep: null, // the current animation step - numSteps: 60, // default number of steps - easing: '', // the easing to use for this animation - render: null, // render function used by the animation service - - onAnimationProgress: null, // user specified callback to fire on each step of the animation - onAnimationComplete: null // user specified callback to fire when the animation finishes - }); - - Chart.animationService = { - frameDuration: 17, - animations: [], - dropFrames: 0, - request: null, - - /** - * @function Chart.animationService.addAnimation - * @param chartInstance {ChartController} the chart to animate - * @param animationObject {IAnimation} the animation that we will animate - * @param duration {Number} length of animation in ms - * @param lazy {Boolean} if true, the chart is not marked as animating to enable more responsive interactions - */ - addAnimation: function(chartInstance, animationObject, duration, lazy) { - var me = this; - - if (!lazy) { - chartInstance.animating = true; - } - - for (var index = 0; index < me.animations.length; ++index) { - if (me.animations[index].chartInstance === chartInstance) { - // replacing an in progress animation - me.animations[index].animationObject = animationObject; - return; - } - } - - me.animations.push({ - chartInstance: chartInstance, - animationObject: animationObject - }); - - // If there are no animations queued, manually kickstart a digest, for lack of a better word - if (me.animations.length === 1) { - me.requestAnimationFrame(); - } - }, - // Cancel the animation for a given chart instance - cancelAnimation: function(chartInstance) { - var index = helpers.findIndex(this.animations, function(animationWrapper) { - return animationWrapper.chartInstance === chartInstance; - }); - - if (index !== -1) { - this.animations.splice(index, 1); - chartInstance.animating = false; - } - }, - requestAnimationFrame: function() { - var me = this; - if (me.request === null) { - // Skip animation frame requests until the active one is executed. - // This can happen when processing mouse events, e.g. 'mousemove' - // and 'mouseout' events will trigger multiple renders. - me.request = helpers.requestAnimFrame.call(window, function() { - me.request = null; - me.startDigest(); - }); - } - }, - startDigest: function() { - var me = this; - - var startTime = Date.now(); - var framesToDrop = 0; - - if (me.dropFrames > 1) { - framesToDrop = Math.floor(me.dropFrames); - me.dropFrames = me.dropFrames % 1; - } - - var i = 0; - while (i < me.animations.length) { - if (me.animations[i].animationObject.currentStep === null) { - me.animations[i].animationObject.currentStep = 0; - } - - me.animations[i].animationObject.currentStep += 1 + framesToDrop; - - if (me.animations[i].animationObject.currentStep > me.animations[i].animationObject.numSteps) { - me.animations[i].animationObject.currentStep = me.animations[i].animationObject.numSteps; - } - - me.animations[i].animationObject.render(me.animations[i].chartInstance, me.animations[i].animationObject); - if (me.animations[i].animationObject.onAnimationProgress && me.animations[i].animationObject.onAnimationProgress.call) { - me.animations[i].animationObject.onAnimationProgress.call(me.animations[i].chartInstance, me.animations[i]); - } - - if (me.animations[i].animationObject.currentStep === me.animations[i].animationObject.numSteps) { - if (me.animations[i].animationObject.onAnimationComplete && me.animations[i].animationObject.onAnimationComplete.call) { - me.animations[i].animationObject.onAnimationComplete.call(me.animations[i].chartInstance, me.animations[i]); - } - - // executed the last frame. Remove the animation. - me.animations[i].chartInstance.animating = false; - - me.animations.splice(i, 1); - } else { - ++i; - } - } - - var endTime = Date.now(); - var dropFrames = (endTime - startTime) / me.frameDuration; - - me.dropFrames += dropFrames; - - // Do we have more stuff to animate? - if (me.animations.length > 0) { - me.requestAnimationFrame(); - } - } - }; - }; - -},{}],22:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - // Global Chart canvas helpers object for drawing items to canvas - var helpers = Chart.canvasHelpers = {}; - - helpers.drawPoint = function(ctx, pointStyle, radius, x, y) { - var type, edgeLength, xOffset, yOffset, height, size; - - if (typeof pointStyle === 'object') { - type = pointStyle.toString(); - if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') { - ctx.drawImage(pointStyle, x - pointStyle.width / 2, y - pointStyle.height / 2); - return; - } - } - - if (isNaN(radius) || radius <= 0) { - return; - } - - switch (pointStyle) { - // Default includes circle - default: - ctx.beginPath(); - ctx.arc(x, y, radius, 0, Math.PI * 2); - ctx.closePath(); - ctx.fill(); - break; - case 'triangle': - ctx.beginPath(); - edgeLength = 3 * radius / Math.sqrt(3); - height = edgeLength * Math.sqrt(3) / 2; - ctx.moveTo(x - edgeLength / 2, y + height / 3); - ctx.lineTo(x + edgeLength / 2, y + height / 3); - ctx.lineTo(x, y - 2 * height / 3); - ctx.closePath(); - ctx.fill(); - break; - case 'rect': - size = 1 / Math.SQRT2 * radius; - ctx.beginPath(); - ctx.fillRect(x - size, y - size, 2 * size, 2 * size); - ctx.strokeRect(x - size, y - size, 2 * size, 2 * size); - break; - case 'rectRounded': - var offset = radius / Math.SQRT2; - var leftX = x - offset; - var topY = y - offset; - var sideSize = Math.SQRT2 * radius; - Chart.helpers.drawRoundedRectangle(ctx, leftX, topY, sideSize, sideSize, radius / 2); - ctx.fill(); - break; - case 'rectRot': - size = 1 / Math.SQRT2 * radius; - ctx.beginPath(); - ctx.moveTo(x - size, y); - ctx.lineTo(x, y + size); - ctx.lineTo(x + size, y); - ctx.lineTo(x, y - size); - ctx.closePath(); - ctx.fill(); - break; - case 'cross': - ctx.beginPath(); - ctx.moveTo(x, y + radius); - ctx.lineTo(x, y - radius); - ctx.moveTo(x - radius, y); - ctx.lineTo(x + radius, y); - ctx.closePath(); - break; - case 'crossRot': - ctx.beginPath(); - xOffset = Math.cos(Math.PI / 4) * radius; - yOffset = Math.sin(Math.PI / 4) * radius; - ctx.moveTo(x - xOffset, y - yOffset); - ctx.lineTo(x + xOffset, y + yOffset); - ctx.moveTo(x - xOffset, y + yOffset); - ctx.lineTo(x + xOffset, y - yOffset); - ctx.closePath(); - break; - case 'star': - ctx.beginPath(); - ctx.moveTo(x, y + radius); - ctx.lineTo(x, y - radius); - ctx.moveTo(x - radius, y); - ctx.lineTo(x + radius, y); - xOffset = Math.cos(Math.PI / 4) * radius; - yOffset = Math.sin(Math.PI / 4) * radius; - ctx.moveTo(x - xOffset, y - yOffset); - ctx.lineTo(x + xOffset, y + yOffset); - ctx.moveTo(x - xOffset, y + yOffset); - ctx.lineTo(x + xOffset, y - yOffset); - ctx.closePath(); - break; - case 'line': - ctx.beginPath(); - ctx.moveTo(x - radius, y); - ctx.lineTo(x + radius, y); - ctx.closePath(); - break; - case 'dash': - ctx.beginPath(); - ctx.moveTo(x, y); - ctx.lineTo(x + radius, y); - ctx.closePath(); - break; - } - - ctx.stroke(); - }; - - helpers.clipArea = function(ctx, clipArea) { - ctx.save(); - ctx.beginPath(); - ctx.rect(clipArea.left, clipArea.top, clipArea.right - clipArea.left, clipArea.bottom - clipArea.top); - ctx.clip(); - }; - - helpers.unclipArea = function(ctx) { - ctx.restore(); - }; - - }; - -},{}],23:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - var plugins = Chart.plugins; - var platform = Chart.platform; - - // Create a dictionary of chart types, to allow for extension of existing types - Chart.types = {}; - - // Store a reference to each instance - allowing us to globally resize chart instances on window resize. - // Destroy method on the chart will remove the instance of the chart from this reference. - Chart.instances = {}; - - // Controllers available for dataset visualization eg. bar, line, slice, etc. - Chart.controllers = {}; - - /** - * Initializes the given config with global and chart default values. - */ - function initConfig(config) { - config = config || {}; - - // Do NOT use configMerge() for the data object because this method merges arrays - // and so would change references to labels and datasets, preventing data updates. - var data = config.data = config.data || {}; - data.datasets = data.datasets || []; - data.labels = data.labels || []; - - config.options = helpers.configMerge( - Chart.defaults.global, - Chart.defaults[config.type], - config.options || {}); - - return config; - } - - /** - * Updates the config of the chart - * @param chart {Chart.Controller} chart to update the options for - */ - function updateConfig(chart) { - var newOptions = chart.options; - - // Update Scale(s) with options - if (newOptions.scale) { - chart.scale.options = newOptions.scale; - } else if (newOptions.scales) { - newOptions.scales.xAxes.concat(newOptions.scales.yAxes).forEach(function(scaleOptions) { - chart.scales[scaleOptions.id].options = scaleOptions; - }); - } - - // Tooltip - chart.tooltip._options = newOptions.tooltips; - } - - /** - * @class Chart.Controller - * The main controller of a chart. - */ - Chart.Controller = function(item, config, instance) { - var me = this; - - config = initConfig(config); - - var context = platform.acquireContext(item, config); - var canvas = context && context.canvas; - var height = canvas && canvas.height; - var width = canvas && canvas.width; - - instance.ctx = context; - instance.canvas = canvas; - instance.config = config; - instance.width = width; - instance.height = height; - instance.aspectRatio = height? width / height : null; - - me.id = helpers.uid(); - me.chart = instance; - me.config = config; - me.options = config.options; - me._bufferedRender = false; - - // Add the chart instance to the global namespace - Chart.instances[me.id] = me; - - Object.defineProperty(me, 'data', { - get: function() { - return me.config.data; - } - }); - - if (!context || !canvas) { - // The given item is not a compatible context2d element, let's return before finalizing - // the chart initialization but after setting basic chart / controller properties that - // can help to figure out that the chart is not valid (e.g chart.canvas !== null); - // https://github.com/chartjs/Chart.js/issues/2807 - console.error("Failed to create chart: can't acquire context from the given item"); - return me; - } - - me.initialize(); - me.update(); - - return me; - }; - - helpers.extend(Chart.Controller.prototype, /** @lends Chart.Controller.prototype */ { - initialize: function() { - var me = this; - - // Before init plugin notification - plugins.notify(me, 'beforeInit'); - - helpers.retinaScale(me.chart); - - me.bindEvents(); - - if (me.options.responsive) { - // Initial resize before chart draws (must be silent to preserve initial animations). - me.resize(true); - } - - // Make sure scales have IDs and are built before we build any controllers. - me.ensureScalesHaveIDs(); - me.buildScales(); - me.initToolTip(); - - // After init plugin notification - plugins.notify(me, 'afterInit'); - - return me; - }, - - clear: function() { - helpers.clear(this.chart); - return this; - }, - - stop: function() { - // Stops any current animation loop occurring - Chart.animationService.cancelAnimation(this); - return this; - }, - - resize: function(silent) { - var me = this; - var chart = me.chart; - var options = me.options; - var canvas = chart.canvas; - var aspectRatio = (options.maintainAspectRatio && chart.aspectRatio) || null; - - // the canvas render width and height will be casted to integers so make sure that - // the canvas display style uses the same integer values to avoid blurring effect. - var newWidth = Math.floor(helpers.getMaximumWidth(canvas)); - var newHeight = Math.floor(aspectRatio? newWidth / aspectRatio : helpers.getMaximumHeight(canvas)); - - if (chart.width === newWidth && chart.height === newHeight) { - return; - } - - canvas.width = chart.width = newWidth; - canvas.height = chart.height = newHeight; - canvas.style.width = newWidth + 'px'; - canvas.style.height = newHeight + 'px'; - - helpers.retinaScale(chart); - - if (!silent) { - // Notify any plugins about the resize - var newSize = {width: newWidth, height: newHeight}; - plugins.notify(me, 'resize', [newSize]); - - // Notify of resize - if (me.options.onResize) { - me.options.onResize(me, newSize); - } - - me.stop(); - me.update(me.options.responsiveAnimationDuration); - } - }, - - ensureScalesHaveIDs: function() { - var options = this.options; - var scalesOptions = options.scales || {}; - var scaleOptions = options.scale; - - helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) { - xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index); - }); - - helpers.each(scalesOptions.yAxes, function(yAxisOptions, index) { - yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index); - }); - - if (scaleOptions) { - scaleOptions.id = scaleOptions.id || 'scale'; - } - }, - - /** - * Builds a map of scale ID to scale object for future lookup. - */ - buildScales: function() { - var me = this; - var options = me.options; - var scales = me.scales = {}; - var items = []; - - if (options.scales) { - items = items.concat( - (options.scales.xAxes || []).map(function(xAxisOptions) { - return {options: xAxisOptions, dtype: 'category'}; - }), - (options.scales.yAxes || []).map(function(yAxisOptions) { - return {options: yAxisOptions, dtype: 'linear'}; - }) - ); - } - - if (options.scale) { - items.push({options: options.scale, dtype: 'radialLinear', isDefault: true}); - } - - helpers.each(items, function(item) { - var scaleOptions = item.options; - var scaleType = helpers.getValueOrDefault(scaleOptions.type, item.dtype); - var scaleClass = Chart.scaleService.getScaleConstructor(scaleType); - if (!scaleClass) { - return; - } - - var scale = new scaleClass({ - id: scaleOptions.id, - options: scaleOptions, - ctx: me.chart.ctx, - chart: me - }); - - scales[scale.id] = scale; - - // TODO(SB): I think we should be able to remove this custom case (options.scale) - // and consider it as a regular scale part of the "scales"" map only! This would - // make the logic easier and remove some useless? custom code. - if (item.isDefault) { - me.scale = scale; - } - }); - - Chart.scaleService.addScalesToLayout(this); - }, - - buildOrUpdateControllers: function() { - var me = this; - var types = []; - var newControllers = []; - - helpers.each(me.data.datasets, function(dataset, datasetIndex) { - var meta = me.getDatasetMeta(datasetIndex); - if (!meta.type) { - meta.type = dataset.type || me.config.type; - } - - types.push(meta.type); - - if (meta.controller) { - meta.controller.updateIndex(datasetIndex); - } else { - meta.controller = new Chart.controllers[meta.type](me, datasetIndex); - newControllers.push(meta.controller); - } - }, me); - - if (types.length > 1) { - for (var i = 1; i < types.length; i++) { - if (types[i] !== types[i - 1]) { - me.isCombo = true; - break; - } - } - } - - return newControllers; - }, - - /** - * Reset the elements of all datasets - * @private - */ - resetElements: function() { - var me = this; - helpers.each(me.data.datasets, function(dataset, datasetIndex) { - me.getDatasetMeta(datasetIndex).controller.reset(); - }, me); - }, - - /** - * Resets the chart back to it's state before the initial animation - */ - reset: function() { - this.resetElements(); - this.tooltip.initialize(); - }, - - update: function(animationDuration, lazy) { - var me = this; - - updateConfig(me); - - if (plugins.notify(me, 'beforeUpdate') === false) { - return; - } - - // In case the entire data object changed - me.tooltip._data = me.data; - - // Make sure dataset controllers are updated and new controllers are reset - var newControllers = me.buildOrUpdateControllers(); - - // Make sure all dataset controllers have correct meta data counts - helpers.each(me.data.datasets, function(dataset, datasetIndex) { - me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements(); - }, me); - - me.updateLayout(); - - // Can only reset the new controllers after the scales have been updated - helpers.each(newControllers, function(controller) { - controller.reset(); - }); - - me.updateDatasets(); - - // Do this before render so that any plugins that need final scale updates can use it - plugins.notify(me, 'afterUpdate'); - - if (me._bufferedRender) { - me._bufferedRequest = { - lazy: lazy, - duration: animationDuration - }; - } else { - me.render(animationDuration, lazy); - } - }, - - /** - * Updates the chart layout unless a plugin returns `false` to the `beforeLayout` - * hook, in which case, plugins will not be called on `afterLayout`. - * @private - */ - updateLayout: function() { - var me = this; - - if (plugins.notify(me, 'beforeLayout') === false) { - return; - } - - Chart.layoutService.update(this, this.chart.width, this.chart.height); - - /** - * Provided for backward compatibility, use `afterLayout` instead. - * @method IPlugin#afterScaleUpdate - * @deprecated since version 2.5.0 - * @todo remove at version 3 - */ - plugins.notify(me, 'afterScaleUpdate'); - plugins.notify(me, 'afterLayout'); - }, - - /** - * Updates all datasets unless a plugin returns `false` to the `beforeDatasetsUpdate` - * hook, in which case, plugins will not be called on `afterDatasetsUpdate`. - * @private - */ - updateDatasets: function() { - var me = this; - - if (plugins.notify(me, 'beforeDatasetsUpdate') === false) { - return; - } - - for (var i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { - me.getDatasetMeta(i).controller.update(); - } - - plugins.notify(me, 'afterDatasetsUpdate'); - }, - - render: function(duration, lazy) { - var me = this; - - if (plugins.notify(me, 'beforeRender') === false) { - return; - } - - var animationOptions = me.options.animation; - var onComplete = function() { - plugins.notify(me, 'afterRender'); - var callback = animationOptions && animationOptions.onComplete; - if (callback && callback.call) { - callback.call(me); - } - }; - - if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) { - var animation = new Chart.Animation(); - animation.numSteps = (duration || animationOptions.duration) / 16.66; // 60 fps - animation.easing = animationOptions.easing; - - // render function - animation.render = function(chartInstance, animationObject) { - var easingFunction = helpers.easingEffects[animationObject.easing]; - var stepDecimal = animationObject.currentStep / animationObject.numSteps; - var easeDecimal = easingFunction(stepDecimal); - - chartInstance.draw(easeDecimal, stepDecimal, animationObject.currentStep); - }; - - // user events - animation.onAnimationProgress = animationOptions.onProgress; - animation.onAnimationComplete = onComplete; - - Chart.animationService.addAnimation(me, animation, duration, lazy); - } else { - me.draw(); - onComplete(); - } - - return me; - }, - - draw: function(easingValue) { - var me = this; - - me.clear(); - - if (easingValue === undefined || easingValue === null) { - easingValue = 1; - } - - if (plugins.notify(me, 'beforeDraw', [easingValue]) === false) { - return; - } - - // Draw all the scales - helpers.each(me.boxes, function(box) { - box.draw(me.chartArea); - }, me); - - if (me.scale) { - me.scale.draw(); - } - - me.drawDatasets(easingValue); - - // Finally draw the tooltip - me.tooltip.transition(easingValue).draw(); - - plugins.notify(me, 'afterDraw', [easingValue]); - }, - - /** - * Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw` - * hook, in which case, plugins will not be called on `afterDatasetsDraw`. - * @private - */ - drawDatasets: function(easingValue) { - var me = this; - - if (plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) { - return; - } - - // Draw each dataset via its respective controller (reversed to support proper line stacking) - helpers.each(me.data.datasets, function(dataset, datasetIndex) { - if (me.isDatasetVisible(datasetIndex)) { - me.getDatasetMeta(datasetIndex).controller.draw(easingValue); - } - }, me, true); - - plugins.notify(me, 'afterDatasetsDraw', [easingValue]); - }, - - // Get the single element that was clicked on - // @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw - getElementAtEvent: function(e) { - return Chart.Interaction.modes.single(this, e); - }, - - getElementsAtEvent: function(e) { - return Chart.Interaction.modes.label(this, e, {intersect: true}); - }, - - getElementsAtXAxis: function(e) { - return Chart.Interaction.modes['x-axis'](this, e, {intersect: true}); - }, - - getElementsAtEventForMode: function(e, mode, options) { - var method = Chart.Interaction.modes[mode]; - if (typeof method === 'function') { - return method(this, e, options); - } - - return []; - }, - - getDatasetAtEvent: function(e) { - return Chart.Interaction.modes.dataset(this, e, {intersect: true}); - }, - - getDatasetMeta: function(datasetIndex) { - var me = this; - var dataset = me.data.datasets[datasetIndex]; - if (!dataset._meta) { - dataset._meta = {}; - } - - var meta = dataset._meta[me.id]; - if (!meta) { - meta = dataset._meta[me.id] = { - type: null, - data: [], - dataset: null, - controller: null, - hidden: null, // See isDatasetVisible() comment - xAxisID: null, - yAxisID: null - }; - } - - return meta; - }, - - getVisibleDatasetCount: function() { - var count = 0; - for (var i = 0, ilen = this.data.datasets.length; i<ilen; ++i) { - if (this.isDatasetVisible(i)) { - count++; - } - } - return count; - }, - - isDatasetVisible: function(datasetIndex) { - var meta = this.getDatasetMeta(datasetIndex); - - // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false, - // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned. - return typeof meta.hidden === 'boolean'? !meta.hidden : !this.data.datasets[datasetIndex].hidden; - }, - - generateLegend: function() { - return this.options.legendCallback(this); - }, - - destroy: function() { - var me = this; - var canvas = me.chart.canvas; - var meta, i, ilen; - - me.stop(); - - // dataset controllers need to cleanup associated data - for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { - meta = me.getDatasetMeta(i); - if (meta.controller) { - meta.controller.destroy(); - meta.controller = null; - } - } - - if (canvas) { - me.unbindEvents(); - helpers.clear(me.chart); - platform.releaseContext(me.chart.ctx); - me.chart.canvas = null; - me.chart.ctx = null; - } - - plugins.notify(me, 'destroy'); - - delete Chart.instances[me.id]; - }, - - toBase64Image: function() { - return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments); - }, - - initToolTip: function() { - var me = this; - me.tooltip = new Chart.Tooltip({ - _chart: me.chart, - _chartInstance: me, - _data: me.data, - _options: me.options.tooltips - }, me); - me.tooltip.initialize(); - }, - - /** - * @private - */ - bindEvents: function() { - var me = this; - var listeners = me._listeners = {}; - var listener = function() { - me.eventHandler.apply(me, arguments); - }; - - helpers.each(me.options.events, function(type) { - platform.addEventListener(me, type, listener); - listeners[type] = listener; - }); - - // Responsiveness is currently based on the use of an iframe, however this method causes - // performance issues and could be troublesome when used with ad blockers. So make sure - // that the user is still able to create a chart without iframe when responsive is false. - // See https://github.com/chartjs/Chart.js/issues/2210 - if (me.options.responsive) { - listener = function() { - me.resize(); - }; - - platform.addEventListener(me, 'resize', listener); - listeners.resize = listener; - } - }, - - /** - * @private - */ - unbindEvents: function() { - var me = this; - var listeners = me._listeners; - if (!listeners) { - return; - } - - delete me._listeners; - helpers.each(listeners, function(listener, type) { - platform.removeEventListener(me, type, listener); - }); - }, - - updateHoverStyle: function(elements, mode, enabled) { - var method = enabled? 'setHoverStyle' : 'removeHoverStyle'; - var element, i, ilen; - - for (i=0, ilen=elements.length; i<ilen; ++i) { - element = elements[i]; - if (element) { - this.getDatasetMeta(element._datasetIndex).controller[method](element); - } - } - }, - - /** - * @private - */ - eventHandler: function(e) { - var me = this; - var tooltip = me.tooltip; - - if (plugins.notify(me, 'beforeEvent', [e]) === false) { - return; - } - - // Buffer any update calls so that renders do not occur - me._bufferedRender = true; - me._bufferedRequest = null; - - var changed = me.handleEvent(e); - changed |= tooltip && tooltip.handleEvent(e); - - plugins.notify(me, 'afterEvent', [e]); - - var bufferedRequest = me._bufferedRequest; - if (bufferedRequest) { - // If we have an update that was triggered, we need to do a normal render - me.render(bufferedRequest.duration, bufferedRequest.lazy); - } else if (changed && !me.animating) { - // If entering, leaving, or changing elements, animate the change via pivot - me.stop(); - - // We only need to render at this point. Updating will cause scales to be - // recomputed generating flicker & using more memory than necessary. - me.render(me.options.hover.animationDuration, true); - } - - me._bufferedRender = false; - me._bufferedRequest = null; - - return me; - }, - - /** - * Handle an event - * @private - * @param {IEvent} event the event to handle - * @return {Boolean} true if the chart needs to re-render - */ - handleEvent: function(e) { - var me = this; - var options = me.options || {}; - var hoverOptions = options.hover; - var changed = false; - - me.lastActive = me.lastActive || []; - - // Find Active Elements for hover and tooltips - if (e.type === 'mouseout') { - me.active = []; - } else { - me.active = me.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions); - } - - // On Hover hook - if (hoverOptions.onHover) { - // Need to call with native event here to not break backwards compatibility - hoverOptions.onHover.call(me, e.native, me.active); - } - - if (e.type === 'mouseup' || e.type === 'click') { - if (options.onClick) { - // Use e.native here for backwards compatibility - options.onClick.call(me, e.native, me.active); - } - } - - // Remove styling for last active (even if it may still be active) - if (me.lastActive.length) { - me.updateHoverStyle(me.lastActive, hoverOptions.mode, false); - } - - // Built in hover styling - if (me.active.length && hoverOptions.mode) { - me.updateHoverStyle(me.active, hoverOptions.mode, true); - } - - changed = !helpers.arrayEquals(me.active, me.lastActive); - - // Remember Last Actives - me.lastActive = me.active; - - return changed; - } - }); - }; - -},{}],24:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift']; - - /** - * Hooks the array methods that add or remove values ('push', pop', 'shift', 'splice', - * 'unshift') and notify the listener AFTER the array has been altered. Listeners are - * called on the 'onData*' callbacks (e.g. onDataPush, etc.) with same arguments. - */ - function listenArrayEvents(array, listener) { - if (array._chartjs) { - array._chartjs.listeners.push(listener); - return; - } - - Object.defineProperty(array, '_chartjs', { - configurable: true, - enumerable: false, - value: { - listeners: [listener] - } - }); - - arrayEvents.forEach(function(key) { - var method = 'onData' + key.charAt(0).toUpperCase() + key.slice(1); - var base = array[key]; - - Object.defineProperty(array, key, { - configurable: true, - enumerable: false, - value: function() { - var args = Array.prototype.slice.call(arguments); - var res = base.apply(this, args); - - helpers.each(array._chartjs.listeners, function(object) { - if (typeof object[method] === 'function') { - object[method].apply(object, args); - } - }); - - return res; - } - }); - }); - } - - /** - * Removes the given array event listener and cleanup extra attached properties (such as - * the _chartjs stub and overridden methods) if array doesn't have any more listeners. - */ - function unlistenArrayEvents(array, listener) { - var stub = array._chartjs; - if (!stub) { - return; - } - - var listeners = stub.listeners; - var index = listeners.indexOf(listener); - if (index !== -1) { - listeners.splice(index, 1); - } - - if (listeners.length > 0) { - return; - } - - arrayEvents.forEach(function(key) { - delete array[key]; - }); - - delete array._chartjs; - } - - // Base class for all dataset controllers (line, bar, etc) - Chart.DatasetController = function(chart, datasetIndex) { - this.initialize(chart, datasetIndex); - }; - - helpers.extend(Chart.DatasetController.prototype, { - - /** - * Element type used to generate a meta dataset (e.g. Chart.element.Line). - * @type {Chart.core.element} - */ - datasetElementType: null, - - /** - * Element type used to generate a meta data (e.g. Chart.element.Point). - * @type {Chart.core.element} - */ - dataElementType: null, - - initialize: function(chart, datasetIndex) { - var me = this; - me.chart = chart; - me.index = datasetIndex; - me.linkScales(); - me.addElements(); - }, - - updateIndex: function(datasetIndex) { - this.index = datasetIndex; - }, - - linkScales: function() { - var me = this; - var meta = me.getMeta(); - var dataset = me.getDataset(); - - if (meta.xAxisID === null) { - meta.xAxisID = dataset.xAxisID || me.chart.options.scales.xAxes[0].id; - } - if (meta.yAxisID === null) { - meta.yAxisID = dataset.yAxisID || me.chart.options.scales.yAxes[0].id; - } - }, - - getDataset: function() { - return this.chart.data.datasets[this.index]; - }, - - getMeta: function() { - return this.chart.getDatasetMeta(this.index); - }, - - getScaleForId: function(scaleID) { - return this.chart.scales[scaleID]; - }, - - reset: function() { - this.update(true); - }, - - /** - * @private - */ - destroy: function() { - if (this._data) { - unlistenArrayEvents(this._data, this); - } - }, - - createMetaDataset: function() { - var me = this; - var type = me.datasetElementType; - return type && new type({ - _chart: me.chart.chart, - _datasetIndex: me.index - }); - }, - - createMetaData: function(index) { - var me = this; - var type = me.dataElementType; - return type && new type({ - _chart: me.chart.chart, - _datasetIndex: me.index, - _index: index - }); - }, - - addElements: function() { - var me = this; - var meta = me.getMeta(); - var data = me.getDataset().data || []; - var metaData = meta.data; - var i, ilen; - - for (i=0, ilen=data.length; i<ilen; ++i) { - metaData[i] = metaData[i] || me.createMetaData(i); - } - - meta.dataset = meta.dataset || me.createMetaDataset(); - }, - - addElementAndReset: function(index) { - var element = this.createMetaData(index); - this.getMeta().data.splice(index, 0, element); - this.updateElement(element, index, true); - }, - - buildOrUpdateElements: function() { - var me = this; - var dataset = me.getDataset(); - var data = dataset.data || (dataset.data = []); - - // In order to correctly handle data addition/deletion animation (an thus simulate - // real-time charts), we need to monitor these data modifications and synchronize - // the internal meta data accordingly. - if (me._data !== data) { - if (me._data) { - // This case happens when the user replaced the data array instance. - unlistenArrayEvents(me._data, me); - } - - listenArrayEvents(data, me); - me._data = data; - } - - // Re-sync meta data in case the user replaced the data array or if we missed - // any updates and so make sure that we handle number of datapoints changing. - me.resyncElements(); - }, - - update: helpers.noop, - - draw: function(ease) { - var easingDecimal = ease || 1; - var i, len; - var metaData = this.getMeta().data; - for (i = 0, len = metaData.length; i < len; ++i) { - metaData[i].transition(easingDecimal).draw(); - } - }, - - removeHoverStyle: function(element, elementOpts) { - var dataset = this.chart.data.datasets[element._datasetIndex], - index = element._index, - custom = element.custom || {}, - valueOrDefault = helpers.getValueAtIndexOrDefault, - model = element._model; - - model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor); - model.borderColor = custom.borderColor ? custom.borderColor : valueOrDefault(dataset.borderColor, index, elementOpts.borderColor); - model.borderWidth = custom.borderWidth ? custom.borderWidth : valueOrDefault(dataset.borderWidth, index, elementOpts.borderWidth); - }, - - setHoverStyle: function(element) { - var dataset = this.chart.data.datasets[element._datasetIndex], - index = element._index, - custom = element.custom || {}, - valueOrDefault = helpers.getValueAtIndexOrDefault, - getHoverColor = helpers.getHoverColor, - model = element._model; - - model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueOrDefault(dataset.hoverBackgroundColor, index, getHoverColor(model.backgroundColor)); - model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, getHoverColor(model.borderColor)); - model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, model.borderWidth); - }, - - /** - * @private - */ - resyncElements: function() { - var me = this; - var meta = me.getMeta(); - var data = me.getDataset().data; - var numMeta = meta.data.length; - var numData = data.length; - - if (numData < numMeta) { - meta.data.splice(numData, numMeta - numData); - } else if (numData > numMeta) { - me.insertElements(numMeta, numData - numMeta); - } - }, - - /** - * @private - */ - insertElements: function(start, count) { - for (var i=0; i<count; ++i) { - this.addElementAndReset(start + i); - } - }, - - /** - * @private - */ - onDataPush: function() { - this.insertElements(this.getDataset().data.length-1, arguments.length); - }, - - /** - * @private - */ - onDataPop: function() { - this.getMeta().data.pop(); - }, - - /** - * @private - */ - onDataShift: function() { - this.getMeta().data.shift(); - }, - - /** - * @private - */ - onDataSplice: function(start, count) { - this.getMeta().data.splice(start, count); - this.insertElements(start, arguments.length - 2); - }, - - /** - * @private - */ - onDataUnshift: function() { - this.insertElements(0, arguments.length); - } - }); - - Chart.DatasetController.extend = helpers.inherits; - }; - -},{}],25:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.elements = {}; - - Chart.Element = function(configuration) { - helpers.extend(this, configuration); - this.initialize.apply(this, arguments); - }; - - helpers.extend(Chart.Element.prototype, { - - initialize: function() { - this.hidden = false; - }, - - pivot: function() { - var me = this; - if (!me._view) { - me._view = helpers.clone(me._model); - } - me._start = helpers.clone(me._view); - return me; - }, - - transition: function(ease) { - var me = this; - - if (!me._view) { - me._view = helpers.clone(me._model); - } - - // No animation -> No Transition - if (ease === 1) { - me._view = me._model; - me._start = null; - return me; - } - - if (!me._start) { - me.pivot(); - } - - helpers.each(me._model, function(value, key) { - - if (key[0] === '_') { - // Only non-underscored properties - // Init if doesn't exist - } else if (!me._view.hasOwnProperty(key)) { - if (typeof value === 'number' && !isNaN(me._view[key])) { - me._view[key] = value * ease; - } else { - me._view[key] = value; - } - // No unnecessary computations - } else if (value === me._view[key]) { - // It's the same! Woohoo! - // Color transitions if possible - } else if (typeof value === 'string') { - try { - var color = helpers.color(me._model[key]).mix(helpers.color(me._start[key]), ease); - me._view[key] = color.rgbString(); - } catch (err) { - me._view[key] = value; - } - // Number transitions - } else if (typeof value === 'number') { - var startVal = me._start[key] !== undefined && isNaN(me._start[key]) === false ? me._start[key] : 0; - me._view[key] = ((me._model[key] - startVal) * ease) + startVal; - // Everything else - } else { - me._view[key] = value; - } - }, me); - - return me; - }, - - tooltipPosition: function() { - return { - x: this._model.x, - y: this._model.y - }; - }, - - hasValue: function() { - return helpers.isNumber(this._model.x) && helpers.isNumber(this._model.y); - } - }); - - Chart.Element.extend = helpers.inherits; - - }; - -},{}],26:[function(require,module,exports){ - /* global window: false */ - /* global document: false */ - 'use strict'; - - var color = require(3); - - module.exports = function(Chart) { - // Global Chart helpers object for utility methods and classes - var helpers = Chart.helpers = {}; - - // -- Basic js utility methods - helpers.each = function(loopable, callback, self, reverse) { - // Check to see if null or undefined firstly. - var i, len; - if (helpers.isArray(loopable)) { - len = loopable.length; - if (reverse) { - for (i = len - 1; i >= 0; i--) { - callback.call(self, loopable[i], i); - } - } else { - for (i = 0; i < len; i++) { - callback.call(self, loopable[i], i); - } - } - } else if (typeof loopable === 'object') { - var keys = Object.keys(loopable); - len = keys.length; - for (i = 0; i < len; i++) { - callback.call(self, loopable[keys[i]], keys[i]); - } - } - }; - helpers.clone = function(obj) { - var objClone = {}; - helpers.each(obj, function(value, key) { - if (helpers.isArray(value)) { - objClone[key] = value.slice(0); - } else if (typeof value === 'object' && value !== null) { - objClone[key] = helpers.clone(value); - } else { - objClone[key] = value; - } - }); - return objClone; - }; - helpers.extend = function(base) { - var setFn = function(value, key) { - base[key] = value; - }; - for (var i = 1, ilen = arguments.length; i < ilen; i++) { - helpers.each(arguments[i], setFn); - } - return base; - }; - // Need a special merge function to chart configs since they are now grouped - helpers.configMerge = function(_base) { - var base = helpers.clone(_base); - helpers.each(Array.prototype.slice.call(arguments, 1), function(extension) { - helpers.each(extension, function(value, key) { - var baseHasProperty = base.hasOwnProperty(key); - var baseVal = baseHasProperty ? base[key] : {}; - - if (key === 'scales') { - // Scale config merging is complex. Add our own function here for that - base[key] = helpers.scaleMerge(baseVal, value); - } else if (key === 'scale') { - // Used in polar area & radar charts since there is only one scale - base[key] = helpers.configMerge(baseVal, Chart.scaleService.getScaleDefaults(value.type), value); - } else if (baseHasProperty - && typeof baseVal === 'object' - && !helpers.isArray(baseVal) - && baseVal !== null - && typeof value === 'object' - && !helpers.isArray(value)) { - // If we are overwriting an object with an object, do a merge of the properties. - base[key] = helpers.configMerge(baseVal, value); - } else { - // can just overwrite the value in this case - base[key] = value; - } - }); - }); - - return base; - }; - helpers.scaleMerge = function(_base, extension) { - var base = helpers.clone(_base); - - helpers.each(extension, function(value, key) { - if (key === 'xAxes' || key === 'yAxes') { - // These properties are arrays of items - if (base.hasOwnProperty(key)) { - helpers.each(value, function(valueObj, index) { - var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear'); - var axisDefaults = Chart.scaleService.getScaleDefaults(axisType); - if (index >= base[key].length || !base[key][index].type) { - base[key].push(helpers.configMerge(axisDefaults, valueObj)); - } else if (valueObj.type && valueObj.type !== base[key][index].type) { - // Type changed. Bring in the new defaults before we bring in valueObj so that valueObj can override the correct scale defaults - base[key][index] = helpers.configMerge(base[key][index], axisDefaults, valueObj); - } else { - // Type is the same - base[key][index] = helpers.configMerge(base[key][index], valueObj); - } - }); - } else { - base[key] = []; - helpers.each(value, function(valueObj) { - var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear'); - base[key].push(helpers.configMerge(Chart.scaleService.getScaleDefaults(axisType), valueObj)); - }); - } - } else if (base.hasOwnProperty(key) && typeof base[key] === 'object' && base[key] !== null && typeof value === 'object') { - // If we are overwriting an object with an object, do a merge of the properties. - base[key] = helpers.configMerge(base[key], value); - - } else { - // can just overwrite the value in this case - base[key] = value; - } - }); - - return base; - }; - helpers.getValueAtIndexOrDefault = function(value, index, defaultValue) { - if (value === undefined || value === null) { - return defaultValue; - } - - if (helpers.isArray(value)) { - return index < value.length ? value[index] : defaultValue; - } - - return value; - }; - helpers.getValueOrDefault = function(value, defaultValue) { - return value === undefined ? defaultValue : value; - }; - helpers.indexOf = Array.prototype.indexOf? - function(array, item) { - return array.indexOf(item); - }: - function(array, item) { - for (var i = 0, ilen = array.length; i < ilen; ++i) { - if (array[i] === item) { - return i; - } - } - return -1; - }; - helpers.where = function(collection, filterCallback) { - if (helpers.isArray(collection) && Array.prototype.filter) { - return collection.filter(filterCallback); - } - var filtered = []; - - helpers.each(collection, function(item) { - if (filterCallback(item)) { - filtered.push(item); - } - }); - - return filtered; - }; - helpers.findIndex = Array.prototype.findIndex? - function(array, callback, scope) { - return array.findIndex(callback, scope); - } : - function(array, callback, scope) { - scope = scope === undefined? array : scope; - for (var i = 0, ilen = array.length; i < ilen; ++i) { - if (callback.call(scope, array[i], i, array)) { - return i; - } - } - return -1; - }; - helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex) { - // Default to start of the array - if (startIndex === undefined || startIndex === null) { - startIndex = -1; - } - for (var i = startIndex + 1; i < arrayToSearch.length; i++) { - var currentItem = arrayToSearch[i]; - if (filterCallback(currentItem)) { - return currentItem; - } - } - }; - helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) { - // Default to end of the array - if (startIndex === undefined || startIndex === null) { - startIndex = arrayToSearch.length; - } - for (var i = startIndex - 1; i >= 0; i--) { - var currentItem = arrayToSearch[i]; - if (filterCallback(currentItem)) { - return currentItem; - } - } - }; - helpers.inherits = function(extensions) { - // Basic javascript inheritance based on the model created in Backbone.js - var me = this; - var ChartElement = (extensions && extensions.hasOwnProperty('constructor')) ? extensions.constructor : function() { - return me.apply(this, arguments); - }; - - var Surrogate = function() { - this.constructor = ChartElement; - }; - Surrogate.prototype = me.prototype; - ChartElement.prototype = new Surrogate(); - - ChartElement.extend = helpers.inherits; - - if (extensions) { - helpers.extend(ChartElement.prototype, extensions); - } - - ChartElement.__super__ = me.prototype; - - return ChartElement; - }; - helpers.noop = function() {}; - helpers.uid = (function() { - var id = 0; - return function() { - return id++; - }; - }()); - // -- Math methods - helpers.isNumber = function(n) { - return !isNaN(parseFloat(n)) && isFinite(n); - }; - helpers.almostEquals = function(x, y, epsilon) { - return Math.abs(x - y) < epsilon; - }; - helpers.almostWhole = function(x, epsilon) { - var rounded = Math.round(x); - return (((rounded - epsilon) < x) && ((rounded + epsilon) > x)); - }; - helpers.max = function(array) { - return array.reduce(function(max, value) { - if (!isNaN(value)) { - return Math.max(max, value); - } - return max; - }, Number.NEGATIVE_INFINITY); - }; - helpers.min = function(array) { - return array.reduce(function(min, value) { - if (!isNaN(value)) { - return Math.min(min, value); - } - return min; - }, Number.POSITIVE_INFINITY); - }; - helpers.sign = Math.sign? - function(x) { - return Math.sign(x); - } : - function(x) { - x = +x; // convert to a number - if (x === 0 || isNaN(x)) { - return x; - } - return x > 0 ? 1 : -1; - }; - helpers.log10 = Math.log10? - function(x) { - return Math.log10(x); - } : - function(x) { - return Math.log(x) / Math.LN10; - }; - helpers.toRadians = function(degrees) { - return degrees * (Math.PI / 180); - }; - helpers.toDegrees = function(radians) { - return radians * (180 / Math.PI); - }; - // Gets the angle from vertical upright to the point about a centre. - helpers.getAngleFromPoint = function(centrePoint, anglePoint) { - var distanceFromXCenter = anglePoint.x - centrePoint.x, - distanceFromYCenter = anglePoint.y - centrePoint.y, - radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter); - - var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter); - - if (angle < (-0.5 * Math.PI)) { - angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2] - } - - return { - angle: angle, - distance: radialDistanceFromCenter - }; - }; - helpers.distanceBetweenPoints = function(pt1, pt2) { - return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2)); - }; - helpers.aliasPixel = function(pixelWidth) { - return (pixelWidth % 2 === 0) ? 0 : 0.5; - }; - helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) { - // Props to Rob Spencer at scaled innovation for his post on splining between points - // http://scaledinnovation.com/analytics/splines/aboutSplines.html - - // This function must also respect "skipped" points - - var previous = firstPoint.skip ? middlePoint : firstPoint, - current = middlePoint, - next = afterPoint.skip ? middlePoint : afterPoint; - - var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2)); - var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2)); - - var s01 = d01 / (d01 + d12); - var s12 = d12 / (d01 + d12); - - // If all points are the same, s01 & s02 will be inf - s01 = isNaN(s01) ? 0 : s01; - s12 = isNaN(s12) ? 0 : s12; - - var fa = t * s01; // scaling factor for triangle Ta - var fb = t * s12; - - return { - previous: { - x: current.x - fa * (next.x - previous.x), - y: current.y - fa * (next.y - previous.y) - }, - next: { - x: current.x + fb * (next.x - previous.x), - y: current.y + fb * (next.y - previous.y) - } - }; - }; - helpers.EPSILON = Number.EPSILON || 1e-14; - helpers.splineCurveMonotone = function(points) { - // This function calculates Bézier control points in a similar way than |splineCurve|, - // but preserves monotonicity of the provided data and ensures no local extremums are added - // between the dataset discrete points due to the interpolation. - // See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation - - var pointsWithTangents = (points || []).map(function(point) { - return { - model: point._model, - deltaK: 0, - mK: 0 - }; - }); - - // Calculate slopes (deltaK) and initialize tangents (mK) - var pointsLen = pointsWithTangents.length; - var i, pointBefore, pointCurrent, pointAfter; - for (i = 0; i < pointsLen; ++i) { - pointCurrent = pointsWithTangents[i]; - if (pointCurrent.model.skip) { - continue; - } - - pointBefore = i > 0 ? pointsWithTangents[i - 1] : null; - pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null; - if (pointAfter && !pointAfter.model.skip) { - var slopeDeltaX = (pointAfter.model.x - pointCurrent.model.x); - - // In the case of two points that appear at the same x pixel, slopeDeltaX is 0 - pointCurrent.deltaK = slopeDeltaX !== 0 ? (pointAfter.model.y - pointCurrent.model.y) / slopeDeltaX : 0; - } - - if (!pointBefore || pointBefore.model.skip) { - pointCurrent.mK = pointCurrent.deltaK; - } else if (!pointAfter || pointAfter.model.skip) { - pointCurrent.mK = pointBefore.deltaK; - } else if (this.sign(pointBefore.deltaK) !== this.sign(pointCurrent.deltaK)) { - pointCurrent.mK = 0; - } else { - pointCurrent.mK = (pointBefore.deltaK + pointCurrent.deltaK) / 2; - } - } - - // Adjust tangents to ensure monotonic properties - var alphaK, betaK, tauK, squaredMagnitude; - for (i = 0; i < pointsLen - 1; ++i) { - pointCurrent = pointsWithTangents[i]; - pointAfter = pointsWithTangents[i + 1]; - if (pointCurrent.model.skip || pointAfter.model.skip) { - continue; - } - - if (helpers.almostEquals(pointCurrent.deltaK, 0, this.EPSILON)) { - pointCurrent.mK = pointAfter.mK = 0; - continue; - } - - alphaK = pointCurrent.mK / pointCurrent.deltaK; - betaK = pointAfter.mK / pointCurrent.deltaK; - squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2); - if (squaredMagnitude <= 9) { - continue; - } - - tauK = 3 / Math.sqrt(squaredMagnitude); - pointCurrent.mK = alphaK * tauK * pointCurrent.deltaK; - pointAfter.mK = betaK * tauK * pointCurrent.deltaK; - } - - // Compute control points - var deltaX; - for (i = 0; i < pointsLen; ++i) { - pointCurrent = pointsWithTangents[i]; - if (pointCurrent.model.skip) { - continue; - } - - pointBefore = i > 0 ? pointsWithTangents[i - 1] : null; - pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null; - if (pointBefore && !pointBefore.model.skip) { - deltaX = (pointCurrent.model.x - pointBefore.model.x) / 3; - pointCurrent.model.controlPointPreviousX = pointCurrent.model.x - deltaX; - pointCurrent.model.controlPointPreviousY = pointCurrent.model.y - deltaX * pointCurrent.mK; - } - if (pointAfter && !pointAfter.model.skip) { - deltaX = (pointAfter.model.x - pointCurrent.model.x) / 3; - pointCurrent.model.controlPointNextX = pointCurrent.model.x + deltaX; - pointCurrent.model.controlPointNextY = pointCurrent.model.y + deltaX * pointCurrent.mK; - } - } - }; - helpers.nextItem = function(collection, index, loop) { - if (loop) { - return index >= collection.length - 1 ? collection[0] : collection[index + 1]; - } - return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1]; - }; - helpers.previousItem = function(collection, index, loop) { - if (loop) { - return index <= 0 ? collection[collection.length - 1] : collection[index - 1]; - } - return index <= 0 ? collection[0] : collection[index - 1]; - }; - // Implementation of the nice number algorithm used in determining where axis labels will go - helpers.niceNum = function(range, round) { - var exponent = Math.floor(helpers.log10(range)); - var fraction = range / Math.pow(10, exponent); - var niceFraction; - - if (round) { - if (fraction < 1.5) { - niceFraction = 1; - } else if (fraction < 3) { - niceFraction = 2; - } else if (fraction < 7) { - niceFraction = 5; - } else { - niceFraction = 10; - } - } else if (fraction <= 1.0) { - niceFraction = 1; - } else if (fraction <= 2) { - niceFraction = 2; - } else if (fraction <= 5) { - niceFraction = 5; - } else { - niceFraction = 10; - } - - return niceFraction * Math.pow(10, exponent); - }; - // Easing functions adapted from Robert Penner's easing equations - // http://www.robertpenner.com/easing/ - var easingEffects = helpers.easingEffects = { - linear: function(t) { - return t; - }, - easeInQuad: function(t) { - return t * t; - }, - easeOutQuad: function(t) { - return -1 * t * (t - 2); - }, - easeInOutQuad: function(t) { - if ((t /= 1 / 2) < 1) { - return 1 / 2 * t * t; - } - return -1 / 2 * ((--t) * (t - 2) - 1); - }, - easeInCubic: function(t) { - return t * t * t; - }, - easeOutCubic: function(t) { - return 1 * ((t = t / 1 - 1) * t * t + 1); - }, - easeInOutCubic: function(t) { - if ((t /= 1 / 2) < 1) { - return 1 / 2 * t * t * t; - } - return 1 / 2 * ((t -= 2) * t * t + 2); - }, - easeInQuart: function(t) { - return t * t * t * t; - }, - easeOutQuart: function(t) { - return -1 * ((t = t / 1 - 1) * t * t * t - 1); - }, - easeInOutQuart: function(t) { - if ((t /= 1 / 2) < 1) { - return 1 / 2 * t * t * t * t; - } - return -1 / 2 * ((t -= 2) * t * t * t - 2); - }, - easeInQuint: function(t) { - return 1 * (t /= 1) * t * t * t * t; - }, - easeOutQuint: function(t) { - return 1 * ((t = t / 1 - 1) * t * t * t * t + 1); - }, - easeInOutQuint: function(t) { - if ((t /= 1 / 2) < 1) { - return 1 / 2 * t * t * t * t * t; - } - return 1 / 2 * ((t -= 2) * t * t * t * t + 2); - }, - easeInSine: function(t) { - return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1; - }, - easeOutSine: function(t) { - return 1 * Math.sin(t / 1 * (Math.PI / 2)); - }, - easeInOutSine: function(t) { - return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1); - }, - easeInExpo: function(t) { - return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1)); - }, - easeOutExpo: function(t) { - return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1); - }, - easeInOutExpo: function(t) { - if (t === 0) { - return 0; - } - if (t === 1) { - return 1; - } - if ((t /= 1 / 2) < 1) { - return 1 / 2 * Math.pow(2, 10 * (t - 1)); - } - return 1 / 2 * (-Math.pow(2, -10 * --t) + 2); - }, - easeInCirc: function(t) { - if (t >= 1) { - return t; - } - return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1); - }, - easeOutCirc: function(t) { - return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t); - }, - easeInOutCirc: function(t) { - if ((t /= 1 / 2) < 1) { - return -1 / 2 * (Math.sqrt(1 - t * t) - 1); - } - return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1); - }, - easeInElastic: function(t) { - var s = 1.70158; - var p = 0; - var a = 1; - if (t === 0) { - return 0; - } - if ((t /= 1) === 1) { - return 1; - } - if (!p) { - p = 1 * 0.3; - } - if (a < Math.abs(1)) { - a = 1; - s = p / 4; - } else { - s = p / (2 * Math.PI) * Math.asin(1 / a); - } - return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p)); - }, - easeOutElastic: function(t) { - var s = 1.70158; - var p = 0; - var a = 1; - if (t === 0) { - return 0; - } - if ((t /= 1) === 1) { - return 1; - } - if (!p) { - p = 1 * 0.3; - } - if (a < Math.abs(1)) { - a = 1; - s = p / 4; - } else { - s = p / (2 * Math.PI) * Math.asin(1 / a); - } - return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1; - }, - easeInOutElastic: function(t) { - var s = 1.70158; - var p = 0; - var a = 1; - if (t === 0) { - return 0; - } - if ((t /= 1 / 2) === 2) { - return 1; - } - if (!p) { - p = 1 * (0.3 * 1.5); - } - if (a < Math.abs(1)) { - a = 1; - s = p / 4; - } else { - s = p / (2 * Math.PI) * Math.asin(1 / a); - } - if (t < 1) { - return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p)); - } - return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1; - }, - easeInBack: function(t) { - var s = 1.70158; - return 1 * (t /= 1) * t * ((s + 1) * t - s); - }, - easeOutBack: function(t) { - var s = 1.70158; - return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1); - }, - easeInOutBack: function(t) { - var s = 1.70158; - if ((t /= 1 / 2) < 1) { - return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)); - } - return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); - }, - easeInBounce: function(t) { - return 1 - easingEffects.easeOutBounce(1 - t); - }, - easeOutBounce: function(t) { - if ((t /= 1) < (1 / 2.75)) { - return 1 * (7.5625 * t * t); - } else if (t < (2 / 2.75)) { - return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75); - } else if (t < (2.5 / 2.75)) { - return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375); - } - return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375); - }, - easeInOutBounce: function(t) { - if (t < 1 / 2) { - return easingEffects.easeInBounce(t * 2) * 0.5; - } - return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5; - } - }; - // Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ - helpers.requestAnimFrame = (function() { - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function(callback) { - return window.setTimeout(callback, 1000 / 60); - }; - }()); - // -- DOM methods - helpers.getRelativePosition = function(evt, chart) { - var mouseX, mouseY; - var e = evt.originalEvent || evt, - canvas = evt.currentTarget || evt.srcElement, - boundingRect = canvas.getBoundingClientRect(); - - var touches = e.touches; - if (touches && touches.length > 0) { - mouseX = touches[0].clientX; - mouseY = touches[0].clientY; - - } else { - mouseX = e.clientX; - mouseY = e.clientY; - } - - // Scale mouse coordinates into canvas coordinates - // by following the pattern laid out by 'jerryj' in the comments of - // http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/ - var paddingLeft = parseFloat(helpers.getStyle(canvas, 'padding-left')); - var paddingTop = parseFloat(helpers.getStyle(canvas, 'padding-top')); - var paddingRight = parseFloat(helpers.getStyle(canvas, 'padding-right')); - var paddingBottom = parseFloat(helpers.getStyle(canvas, 'padding-bottom')); - var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight; - var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom; - - // We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However - // the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here - mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio); - mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio); - - return { - x: mouseX, - y: mouseY - }; - - }; - helpers.addEvent = function(node, eventType, method) { - if (node.addEventListener) { - node.addEventListener(eventType, method); - } else if (node.attachEvent) { - node.attachEvent('on' + eventType, method); - } else { - node['on' + eventType] = method; - } - }; - helpers.removeEvent = function(node, eventType, handler) { - if (node.removeEventListener) { - node.removeEventListener(eventType, handler, false); - } else if (node.detachEvent) { - node.detachEvent('on' + eventType, handler); - } else { - node['on' + eventType] = helpers.noop; - } - }; - - // Private helper function to convert max-width/max-height values that may be percentages into a number - function parseMaxStyle(styleValue, node, parentProperty) { - var valueInPixels; - if (typeof(styleValue) === 'string') { - valueInPixels = parseInt(styleValue, 10); - - if (styleValue.indexOf('%') !== -1) { - // percentage * size in dimension - valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty]; - } - } else { - valueInPixels = styleValue; - } - - return valueInPixels; - } - - /** - * Returns if the given value contains an effective constraint. - * @private - */ - function isConstrainedValue(value) { - return value !== undefined && value !== null && value !== 'none'; - } - - // Private helper to get a constraint dimension - // @param domNode : the node to check the constraint on - // @param maxStyle : the style that defines the maximum for the direction we are using (maxWidth / maxHeight) - // @param percentageProperty : property of parent to use when calculating width as a percentage - // @see http://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser - function getConstraintDimension(domNode, maxStyle, percentageProperty) { - var view = document.defaultView; - var parentNode = domNode.parentNode; - var constrainedNode = view.getComputedStyle(domNode)[maxStyle]; - var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle]; - var hasCNode = isConstrainedValue(constrainedNode); - var hasCContainer = isConstrainedValue(constrainedContainer); - var infinity = Number.POSITIVE_INFINITY; - - if (hasCNode || hasCContainer) { - return Math.min( - hasCNode? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity, - hasCContainer? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity); - } - - return 'none'; - } - // returns Number or undefined if no constraint - helpers.getConstraintWidth = function(domNode) { - return getConstraintDimension(domNode, 'max-width', 'clientWidth'); - }; - // returns Number or undefined if no constraint - helpers.getConstraintHeight = function(domNode) { - return getConstraintDimension(domNode, 'max-height', 'clientHeight'); - }; - helpers.getMaximumWidth = function(domNode) { - var container = domNode.parentNode; - var paddingLeft = parseInt(helpers.getStyle(container, 'padding-left'), 10); - var paddingRight = parseInt(helpers.getStyle(container, 'padding-right'), 10); - var w = container.clientWidth - paddingLeft - paddingRight; - var cw = helpers.getConstraintWidth(domNode); - return isNaN(cw)? w : Math.min(w, cw); - }; - helpers.getMaximumHeight = function(domNode) { - var container = domNode.parentNode; - var paddingTop = parseInt(helpers.getStyle(container, 'padding-top'), 10); - var paddingBottom = parseInt(helpers.getStyle(container, 'padding-bottom'), 10); - var h = container.clientHeight - paddingTop - paddingBottom; - var ch = helpers.getConstraintHeight(domNode); - return isNaN(ch)? h : Math.min(h, ch); - }; - helpers.getStyle = function(el, property) { - return el.currentStyle ? - el.currentStyle[property] : - document.defaultView.getComputedStyle(el, null).getPropertyValue(property); - }; - helpers.retinaScale = function(chart) { - var pixelRatio = chart.currentDevicePixelRatio = window.devicePixelRatio || 1; - if (pixelRatio === 1) { - return; - } - - var canvas = chart.canvas; - var height = chart.height; - var width = chart.width; - - canvas.height = height * pixelRatio; - canvas.width = width * pixelRatio; - chart.ctx.scale(pixelRatio, pixelRatio); - - // If no style has been set on the canvas, the render size is used as display size, - // making the chart visually bigger, so let's enforce it to the "correct" values. - // See https://github.com/chartjs/Chart.js/issues/3575 - canvas.style.height = height + 'px'; - canvas.style.width = width + 'px'; - }; - // -- Canvas methods - helpers.clear = function(chart) { - chart.ctx.clearRect(0, 0, chart.width, chart.height); - }; - helpers.fontString = function(pixelSize, fontStyle, fontFamily) { - return fontStyle + ' ' + pixelSize + 'px ' + fontFamily; - }; - helpers.longestText = function(ctx, font, arrayOfThings, cache) { - cache = cache || {}; - var data = cache.data = cache.data || {}; - var gc = cache.garbageCollect = cache.garbageCollect || []; - - if (cache.font !== font) { - data = cache.data = {}; - gc = cache.garbageCollect = []; - cache.font = font; - } - - ctx.font = font; - var longest = 0; - helpers.each(arrayOfThings, function(thing) { - // Undefined strings and arrays should not be measured - if (thing !== undefined && thing !== null && helpers.isArray(thing) !== true) { - longest = helpers.measureText(ctx, data, gc, longest, thing); - } else if (helpers.isArray(thing)) { - // if it is an array lets measure each element - // to do maybe simplify this function a bit so we can do this more recursively? - helpers.each(thing, function(nestedThing) { - // Undefined strings and arrays should not be measured - if (nestedThing !== undefined && nestedThing !== null && !helpers.isArray(nestedThing)) { - longest = helpers.measureText(ctx, data, gc, longest, nestedThing); - } - }); - } - }); - - var gcLen = gc.length / 2; - if (gcLen > arrayOfThings.length) { - for (var i = 0; i < gcLen; i++) { - delete data[gc[i]]; - } - gc.splice(0, gcLen); - } - return longest; - }; - helpers.measureText = function(ctx, data, gc, longest, string) { - var textWidth = data[string]; - if (!textWidth) { - textWidth = data[string] = ctx.measureText(string).width; - gc.push(string); - } - if (textWidth > longest) { - longest = textWidth; - } - return longest; - }; - helpers.numberOfLabelLines = function(arrayOfThings) { - var numberOfLines = 1; - helpers.each(arrayOfThings, function(thing) { - if (helpers.isArray(thing)) { - if (thing.length > numberOfLines) { - numberOfLines = thing.length; - } - } - }); - return numberOfLines; - }; - helpers.drawRoundedRectangle = function(ctx, x, y, width, height, radius) { - ctx.beginPath(); - ctx.moveTo(x + radius, y); - ctx.lineTo(x + width - radius, y); - ctx.quadraticCurveTo(x + width, y, x + width, y + radius); - ctx.lineTo(x + width, y + height - radius); - ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); - ctx.lineTo(x + radius, y + height); - ctx.quadraticCurveTo(x, y + height, x, y + height - radius); - ctx.lineTo(x, y + radius); - ctx.quadraticCurveTo(x, y, x + radius, y); - ctx.closePath(); - }; - helpers.color = function(c) { - if (!color) { - console.error('Color.js not found!'); - return c; - } - - /* global CanvasGradient */ - if (c instanceof CanvasGradient) { - return color(Chart.defaults.global.defaultColor); - } - - return color(c); - }; - helpers.isArray = Array.isArray? - function(obj) { - return Array.isArray(obj); - } : - function(obj) { - return Object.prototype.toString.call(obj) === '[object Array]'; - }; - // ! @see http://stackoverflow.com/a/14853974 - helpers.arrayEquals = function(a0, a1) { - var i, ilen, v0, v1; - - if (!a0 || !a1 || a0.length !== a1.length) { - return false; - } - - for (i = 0, ilen=a0.length; i < ilen; ++i) { - v0 = a0[i]; - v1 = a1[i]; - - if (v0 instanceof Array && v1 instanceof Array) { - if (!helpers.arrayEquals(v0, v1)) { - return false; - } - } else if (v0 !== v1) { - // NOTE: two different object instances will never be equal: {x:20} != {x:20} - return false; - } - } - - return true; - }; - helpers.callCallback = function(fn, args, _tArg) { - if (fn && typeof fn.call === 'function') { - fn.apply(_tArg, args); - } - }; - helpers.getHoverColor = function(colorValue) { - /* global CanvasPattern */ - return (colorValue instanceof CanvasPattern) ? - colorValue : - helpers.color(colorValue).saturate(0.5).darken(0.1).rgbString(); - }; - }; - -},{"3":3}],27:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - var helpers = Chart.helpers; - - /** - * Helper function to get relative position for an event - * @param {Event|IEvent} event - The event to get the position for - * @param {Chart} chart - The chart - * @returns {Point} the event position - */ - function getRelativePosition(e, chart) { - if (e.native) { - return { - x: e.x, - y: e.y - }; - } - - return helpers.getRelativePosition(e, chart); - } - - /** - * Helper function to traverse all of the visible elements in the chart - * @param chart {chart} the chart - * @param handler {Function} the callback to execute for each visible item - */ - function parseVisibleItems(chart, handler) { - var datasets = chart.data.datasets; - var meta, i, j, ilen, jlen; - - for (i = 0, ilen = datasets.length; i < ilen; ++i) { - if (!chart.isDatasetVisible(i)) { - continue; - } - - meta = chart.getDatasetMeta(i); - for (j = 0, jlen = meta.data.length; j < jlen; ++j) { - var element = meta.data[j]; - if (!element._view.skip) { - handler(element); - } - } - } - } - - /** - * Helper function to get the items that intersect the event position - * @param items {ChartElement[]} elements to filter - * @param position {Point} the point to be nearest to - * @return {ChartElement[]} the nearest items - */ - function getIntersectItems(chart, position) { - var elements = []; - - parseVisibleItems(chart, function(element) { - if (element.inRange(position.x, position.y)) { - elements.push(element); - } - }); - - return elements; - } - - /** - * Helper function to get the items nearest to the event position considering all visible items in teh chart - * @param chart {Chart} the chart to look at elements from - * @param position {Point} the point to be nearest to - * @param intersect {Boolean} if true, only consider items that intersect the position - * @param distanceMetric {Function} Optional function to provide the distance between - * @return {ChartElement[]} the nearest items - */ - function getNearestItems(chart, position, intersect, distanceMetric) { - var minDistance = Number.POSITIVE_INFINITY; - var nearestItems = []; - - if (!distanceMetric) { - distanceMetric = helpers.distanceBetweenPoints; - } - - parseVisibleItems(chart, function(element) { - if (intersect && !element.inRange(position.x, position.y)) { - return; - } - - var center = element.getCenterPoint(); - var distance = distanceMetric(position, center); - - if (distance < minDistance) { - nearestItems = [element]; - minDistance = distance; - } else if (distance === minDistance) { - // Can have multiple items at the same distance in which case we sort by size - nearestItems.push(element); - } - }); - - return nearestItems; - } - - function indexMode(chart, e, options) { - var position = getRelativePosition(e, chart.chart); - var distanceMetric = function(pt1, pt2) { - return Math.abs(pt1.x - pt2.x); - }; - var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); - var elements = []; - - if (!items.length) { - return []; - } - - chart.data.datasets.forEach(function(dataset, datasetIndex) { - if (chart.isDatasetVisible(datasetIndex)) { - var meta = chart.getDatasetMeta(datasetIndex), - element = meta.data[items[0]._index]; - - // don't count items that are skipped (null data) - if (element && !element._view.skip) { - elements.push(element); - } - } - }); - - return elements; - } - - /** - * @interface IInteractionOptions - */ - /** - * If true, only consider items that intersect the point - * @name IInterfaceOptions#boolean - * @type Boolean - */ - - /** - * Contains interaction related functions - * @namespace Chart.Interaction - */ - Chart.Interaction = { - // Helper function for different modes - modes: { - single: function(chart, e) { - var position = getRelativePosition(e, chart.chart); - var elements = []; - - parseVisibleItems(chart, function(element) { - if (element.inRange(position.x, position.y)) { - elements.push(element); - return elements; - } - }); - - return elements.slice(0, 1); - }, - - /** - * @function Chart.Interaction.modes.label - * @deprecated since version 2.4.0 - */ - label: indexMode, - - /** - * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something - * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item - * @function Chart.Interaction.modes.index - * @since v2.4.0 - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @param options {IInteractionOptions} options to use during interaction - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - index: indexMode, - - /** - * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something - * If the options.intersect is false, we find the nearest item and return the items in that dataset - * @function Chart.Interaction.modes.dataset - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @param options {IInteractionOptions} options to use during interaction - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - dataset: function(chart, e, options) { - var position = getRelativePosition(e, chart.chart); - var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false); - - if (items.length > 0) { - items = chart.getDatasetMeta(items[0]._datasetIndex).data; - } - - return items; - }, - - /** - * @function Chart.Interaction.modes.x-axis - * @deprecated since version 2.4.0. Use index mode and intersect == true - */ - 'x-axis': function(chart, e) { - return indexMode(chart, e, true); - }, - - /** - * Point mode returns all elements that hit test based on the event position - * of the event - * @function Chart.Interaction.modes.intersect - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - point: function(chart, e) { - var position = getRelativePosition(e, chart.chart); - return getIntersectItems(chart, position); - }, - - /** - * nearest mode returns the element closest to the point - * @function Chart.Interaction.modes.intersect - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @param options {IInteractionOptions} options to use - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - nearest: function(chart, e, options) { - var position = getRelativePosition(e, chart.chart); - var nearestItems = getNearestItems(chart, position, options.intersect); - - // We have multiple items at the same distance from the event. Now sort by smallest - if (nearestItems.length > 1) { - nearestItems.sort(function(a, b) { - var sizeA = a.getArea(); - var sizeB = b.getArea(); - var ret = sizeA - sizeB; - - if (ret === 0) { - // if equal sort by dataset index - ret = a._datasetIndex - b._datasetIndex; - } - - return ret; - }); - } - - // Return only 1 item - return nearestItems.slice(0, 1); - }, - - /** - * x mode returns the elements that hit-test at the current x coordinate - * @function Chart.Interaction.modes.x - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @param options {IInteractionOptions} options to use - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - x: function(chart, e, options) { - var position = getRelativePosition(e, chart.chart); - var items = []; - var intersectsItem = false; - - parseVisibleItems(chart, function(element) { - if (element.inXRange(position.x)) { - items.push(element); - } - - if (element.inRange(position.x, position.y)) { - intersectsItem = true; - } - }); - - // If we want to trigger on an intersect and we don't have any items - // that intersect the position, return nothing - if (options.intersect && !intersectsItem) { - items = []; - } - return items; - }, - - /** - * y mode returns the elements that hit-test at the current y coordinate - * @function Chart.Interaction.modes.y - * @param chart {chart} the chart we are returning items from - * @param e {Event} the event we are find things at - * @param options {IInteractionOptions} options to use - * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned - */ - y: function(chart, e, options) { - var position = getRelativePosition(e, chart.chart); - var items = []; - var intersectsItem = false; - - parseVisibleItems(chart, function(element) { - if (element.inYRange(position.y)) { - items.push(element); - } - - if (element.inRange(position.x, position.y)) { - intersectsItem = true; - } - }); - - // If we want to trigger on an intersect and we don't have any items - // that intersect the position, return nothing - if (options.intersect && !intersectsItem) { - items = []; - } - return items; - } - } - }; - }; - -},{}],28:[function(require,module,exports){ - 'use strict'; - - module.exports = function() { - - // Occupy the global variable of Chart, and create a simple base class - var Chart = function(item, config) { - this.controller = new Chart.Controller(item, config, this); - return this.controller; - }; - - // Globally expose the defaults to allow for user updating/changing - Chart.defaults = { - global: { - responsive: true, - responsiveAnimationDuration: 0, - maintainAspectRatio: true, - events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'], - hover: { - onHover: null, - mode: 'nearest', - intersect: true, - animationDuration: 400 - }, - onClick: null, - defaultColor: 'rgba(0,0,0,0.1)', - defaultFontColor: '#666', - defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", - defaultFontSize: 12, - defaultFontStyle: 'normal', - showLines: true, - - // Element defaults defined in element extensions - elements: {}, - - // Legend callback string - legendCallback: function(chart) { - var text = []; - text.push('<ul class="' + chart.id + '-legend">'); - for (var i = 0; i < chart.data.datasets.length; i++) { - text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>'); - if (chart.data.datasets[i].label) { - text.push(chart.data.datasets[i].label); - } - text.push('</li>'); - } - text.push('</ul>'); - - return text.join(''); - } - } - }; - - Chart.Chart = Chart; - - return Chart; - }; - -},{}],29:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - // The layout service is very self explanatory. It's responsible for the layout within a chart. - // Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need - // It is this service's responsibility of carrying out that layout. - Chart.layoutService = { - defaults: {}, - - // Register a box to a chartInstance. A box is simply a reference to an object that requires layout. eg. Scales, Legend, Plugins. - addBox: function(chartInstance, box) { - if (!chartInstance.boxes) { - chartInstance.boxes = []; - } - chartInstance.boxes.push(box); - }, - - removeBox: function(chartInstance, box) { - if (!chartInstance.boxes) { - return; - } - chartInstance.boxes.splice(chartInstance.boxes.indexOf(box), 1); - }, - - // The most important function - update: function(chartInstance, width, height) { - - if (!chartInstance) { - return; - } - - var layoutOptions = chartInstance.options.layout; - var padding = layoutOptions ? layoutOptions.padding : null; - - var leftPadding = 0; - var rightPadding = 0; - var topPadding = 0; - var bottomPadding = 0; - - if (!isNaN(padding)) { - // options.layout.padding is a number. assign to all - leftPadding = padding; - rightPadding = padding; - topPadding = padding; - bottomPadding = padding; - } else { - leftPadding = padding.left || 0; - rightPadding = padding.right || 0; - topPadding = padding.top || 0; - bottomPadding = padding.bottom || 0; - } - - var leftBoxes = helpers.where(chartInstance.boxes, function(box) { - return box.options.position === 'left'; - }); - var rightBoxes = helpers.where(chartInstance.boxes, function(box) { - return box.options.position === 'right'; - }); - var topBoxes = helpers.where(chartInstance.boxes, function(box) { - return box.options.position === 'top'; - }); - var bottomBoxes = helpers.where(chartInstance.boxes, function(box) { - return box.options.position === 'bottom'; - }); - - // Boxes that overlay the chartarea such as the radialLinear scale - var chartAreaBoxes = helpers.where(chartInstance.boxes, function(box) { - return box.options.position === 'chartArea'; - }); - - // Ensure that full width boxes are at the very top / bottom - topBoxes.sort(function(a, b) { - return (b.options.fullWidth ? 1 : 0) - (a.options.fullWidth ? 1 : 0); - }); - bottomBoxes.sort(function(a, b) { - return (a.options.fullWidth ? 1 : 0) - (b.options.fullWidth ? 1 : 0); - }); - - // Essentially we now have any number of boxes on each of the 4 sides. - // Our canvas looks like the following. - // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and - // B1 is the bottom axis - // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays - // These locations are single-box locations only, when trying to register a chartArea location that is already taken, - // an error will be thrown. - // - // |----------------------------------------------------| - // | T1 (Full Width) | - // |----------------------------------------------------| - // | | | T2 | | - // | |----|-------------------------------------|----| - // | | | C1 | | C2 | | - // | | |----| |----| | - // | | | | | - // | L1 | L2 | ChartArea (C0) | R1 | - // | | | | | - // | | |----| |----| | - // | | | C3 | | C4 | | - // | |----|-------------------------------------|----| - // | | | B1 | | - // |----------------------------------------------------| - // | B2 (Full Width) | - // |----------------------------------------------------| - // - // What we do to find the best sizing, we do the following - // 1. Determine the minimum size of the chart area. - // 2. Split the remaining width equally between each vertical axis - // 3. Split the remaining height equally between each horizontal axis - // 4. Give each layout the maximum size it can be. The layout will return it's minimum size - // 5. Adjust the sizes of each axis based on it's minimum reported size. - // 6. Refit each axis - // 7. Position each axis in the final location - // 8. Tell the chart the final location of the chart area - // 9. Tell any axes that overlay the chart area the positions of the chart area - - // Step 1 - var chartWidth = width - leftPadding - rightPadding; - var chartHeight = height - topPadding - bottomPadding; - var chartAreaWidth = chartWidth / 2; // min 50% - var chartAreaHeight = chartHeight / 2; // min 50% - - // Step 2 - var verticalBoxWidth = (width - chartAreaWidth) / (leftBoxes.length + rightBoxes.length); - - // Step 3 - var horizontalBoxHeight = (height - chartAreaHeight) / (topBoxes.length + bottomBoxes.length); - - // Step 4 - var maxChartAreaWidth = chartWidth; - var maxChartAreaHeight = chartHeight; - var minBoxSizes = []; - - function getMinimumBoxSize(box) { - var minSize; - var isHorizontal = box.isHorizontal(); - - if (isHorizontal) { - minSize = box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, horizontalBoxHeight); - maxChartAreaHeight -= minSize.height; - } else { - minSize = box.update(verticalBoxWidth, chartAreaHeight); - maxChartAreaWidth -= minSize.width; - } - - minBoxSizes.push({ - horizontal: isHorizontal, - minSize: minSize, - box: box, - }); - } - - helpers.each(leftBoxes.concat(rightBoxes, topBoxes, bottomBoxes), getMinimumBoxSize); - - // If a horizontal box has padding, we move the left boxes over to avoid ugly charts (see issue #2478) - var maxHorizontalLeftPadding = 0; - var maxHorizontalRightPadding = 0; - var maxVerticalTopPadding = 0; - var maxVerticalBottomPadding = 0; - - helpers.each(topBoxes.concat(bottomBoxes), function(horizontalBox) { - if (horizontalBox.getPadding) { - var boxPadding = horizontalBox.getPadding(); - maxHorizontalLeftPadding = Math.max(maxHorizontalLeftPadding, boxPadding.left); - maxHorizontalRightPadding = Math.max(maxHorizontalRightPadding, boxPadding.right); - } - }); - - helpers.each(leftBoxes.concat(rightBoxes), function(verticalBox) { - if (verticalBox.getPadding) { - var boxPadding = verticalBox.getPadding(); - maxVerticalTopPadding = Math.max(maxVerticalTopPadding, boxPadding.top); - maxVerticalBottomPadding = Math.max(maxVerticalBottomPadding, boxPadding.bottom); - } - }); - - // At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could - // be if the axes are drawn at their minimum sizes. - // Steps 5 & 6 - var totalLeftBoxesWidth = leftPadding; - var totalRightBoxesWidth = rightPadding; - var totalTopBoxesHeight = topPadding; - var totalBottomBoxesHeight = bottomPadding; - - // Function to fit a box - function fitBox(box) { - var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBox) { - return minBox.box === box; - }); - - if (minBoxSize) { - if (box.isHorizontal()) { - var scaleMargin = { - left: Math.max(totalLeftBoxesWidth, maxHorizontalLeftPadding), - right: Math.max(totalRightBoxesWidth, maxHorizontalRightPadding), - top: 0, - bottom: 0 - }; - - // Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends - // on the margin. Sometimes they need to increase in size slightly - box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin); - } else { - box.update(minBoxSize.minSize.width, maxChartAreaHeight); - } - } - } - - // Update, and calculate the left and right margins for the horizontal boxes - helpers.each(leftBoxes.concat(rightBoxes), fitBox); - - helpers.each(leftBoxes, function(box) { - totalLeftBoxesWidth += box.width; - }); - - helpers.each(rightBoxes, function(box) { - totalRightBoxesWidth += box.width; - }); - - // Set the Left and Right margins for the horizontal boxes - helpers.each(topBoxes.concat(bottomBoxes), fitBox); - - // Figure out how much margin is on the top and bottom of the vertical boxes - helpers.each(topBoxes, function(box) { - totalTopBoxesHeight += box.height; - }); - - helpers.each(bottomBoxes, function(box) { - totalBottomBoxesHeight += box.height; - }); - - function finalFitVerticalBox(box) { - var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minSize) { - return minSize.box === box; - }); - - var scaleMargin = { - left: 0, - right: 0, - top: totalTopBoxesHeight, - bottom: totalBottomBoxesHeight - }; - - if (minBoxSize) { - box.update(minBoxSize.minSize.width, maxChartAreaHeight, scaleMargin); - } - } - - // Let the left layout know the final margin - helpers.each(leftBoxes.concat(rightBoxes), finalFitVerticalBox); - - // Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance) - totalLeftBoxesWidth = leftPadding; - totalRightBoxesWidth = rightPadding; - totalTopBoxesHeight = topPadding; - totalBottomBoxesHeight = bottomPadding; - - helpers.each(leftBoxes, function(box) { - totalLeftBoxesWidth += box.width; - }); - - helpers.each(rightBoxes, function(box) { - totalRightBoxesWidth += box.width; - }); - - helpers.each(topBoxes, function(box) { - totalTopBoxesHeight += box.height; - }); - helpers.each(bottomBoxes, function(box) { - totalBottomBoxesHeight += box.height; - }); - - // We may be adding some padding to account for rotated x axis labels - var leftPaddingAddition = Math.max(maxHorizontalLeftPadding - totalLeftBoxesWidth, 0); - totalLeftBoxesWidth += leftPaddingAddition; - totalRightBoxesWidth += Math.max(maxHorizontalRightPadding - totalRightBoxesWidth, 0); - - var topPaddingAddition = Math.max(maxVerticalTopPadding - totalTopBoxesHeight, 0); - totalTopBoxesHeight += topPaddingAddition; - totalBottomBoxesHeight += Math.max(maxVerticalBottomPadding - totalBottomBoxesHeight, 0); - - // Figure out if our chart area changed. This would occur if the dataset layout label rotation - // changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do - // without calling `fit` again - var newMaxChartAreaHeight = height - totalTopBoxesHeight - totalBottomBoxesHeight; - var newMaxChartAreaWidth = width - totalLeftBoxesWidth - totalRightBoxesWidth; - - if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) { - helpers.each(leftBoxes, function(box) { - box.height = newMaxChartAreaHeight; - }); - - helpers.each(rightBoxes, function(box) { - box.height = newMaxChartAreaHeight; - }); - - helpers.each(topBoxes, function(box) { - if (!box.options.fullWidth) { - box.width = newMaxChartAreaWidth; - } - }); - - helpers.each(bottomBoxes, function(box) { - if (!box.options.fullWidth) { - box.width = newMaxChartAreaWidth; - } - }); - - maxChartAreaHeight = newMaxChartAreaHeight; - maxChartAreaWidth = newMaxChartAreaWidth; - } - - // Step 7 - Position the boxes - var left = leftPadding + leftPaddingAddition; - var top = topPadding + topPaddingAddition; - - function placeBox(box) { - if (box.isHorizontal()) { - box.left = box.options.fullWidth ? leftPadding : totalLeftBoxesWidth; - box.right = box.options.fullWidth ? width - rightPadding : totalLeftBoxesWidth + maxChartAreaWidth; - box.top = top; - box.bottom = top + box.height; - - // Move to next point - top = box.bottom; - - } else { - - box.left = left; - box.right = left + box.width; - box.top = totalTopBoxesHeight; - box.bottom = totalTopBoxesHeight + maxChartAreaHeight; - - // Move to next point - left = box.right; - } - } - - helpers.each(leftBoxes.concat(topBoxes), placeBox); - - // Account for chart width and height - left += maxChartAreaWidth; - top += maxChartAreaHeight; - - helpers.each(rightBoxes, placeBox); - helpers.each(bottomBoxes, placeBox); - - // Step 8 - chartInstance.chartArea = { - left: totalLeftBoxesWidth, - top: totalTopBoxesHeight, - right: totalLeftBoxesWidth + maxChartAreaWidth, - bottom: totalTopBoxesHeight + maxChartAreaHeight - }; - - // Step 9 - helpers.each(chartAreaBoxes, function(box) { - box.left = chartInstance.chartArea.left; - box.top = chartInstance.chartArea.top; - box.right = chartInstance.chartArea.right; - box.bottom = chartInstance.chartArea.bottom; - - box.update(maxChartAreaWidth, maxChartAreaHeight); - }); - } - }; - }; - -},{}],30:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - var noop = helpers.noop; - - Chart.defaults.global.legend = { - - display: true, - position: 'top', - fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes) - reverse: false, - - // a callback that will handle - onClick: function(e, legendItem) { - var index = legendItem.datasetIndex; - var ci = this.chart; - var meta = ci.getDatasetMeta(index); - - // See controller.isDatasetVisible comment - meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null; - - // We hid a dataset ... rerender the chart - ci.update(); - }, - - onHover: null, - - labels: { - boxWidth: 40, - padding: 10, - // Generates labels shown in the legend - // Valid properties to return: - // text : text to display - // fillStyle : fill of coloured box - // strokeStyle: stroke of coloured box - // hidden : if this legend item refers to a hidden item - // lineCap : cap style for line - // lineDash - // lineDashOffset : - // lineJoin : - // lineWidth : - generateLabels: function(chart) { - var data = chart.data; - return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) { - return { - text: dataset.label, - fillStyle: (!helpers.isArray(dataset.backgroundColor) ? dataset.backgroundColor : dataset.backgroundColor[0]), - hidden: !chart.isDatasetVisible(i), - lineCap: dataset.borderCapStyle, - lineDash: dataset.borderDash, - lineDashOffset: dataset.borderDashOffset, - lineJoin: dataset.borderJoinStyle, - lineWidth: dataset.borderWidth, - strokeStyle: dataset.borderColor, - pointStyle: dataset.pointStyle, - - // Below is extra data used for toggling the datasets - datasetIndex: i - }; - }, this) : []; - } - } - }; - - /** - * Helper function to get the box width based on the usePointStyle option - * @param labelopts {Object} the label options on the legend - * @param fontSize {Number} the label font size - * @return {Number} width of the color box area - */ - function getBoxWidth(labelOpts, fontSize) { - return labelOpts.usePointStyle ? - fontSize * Math.SQRT2 : - labelOpts.boxWidth; - } - - Chart.Legend = Chart.Element.extend({ - - initialize: function(config) { - helpers.extend(this, config); - - // Contains hit boxes for each dataset (in dataset order) - this.legendHitBoxes = []; - - // Are we in doughnut mode which has a different data type - this.doughnutMode = false; - }, - - // These methods are ordered by lifecycle. Utilities then follow. - // Any function defined here is inherited by all legend types. - // Any function can be extended by the legend type - - beforeUpdate: noop, - update: function(maxWidth, maxHeight, margins) { - var me = this; - - // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) - me.beforeUpdate(); - - // Absorb the master measurements - me.maxWidth = maxWidth; - me.maxHeight = maxHeight; - me.margins = margins; - - // Dimensions - me.beforeSetDimensions(); - me.setDimensions(); - me.afterSetDimensions(); - // Labels - me.beforeBuildLabels(); - me.buildLabels(); - me.afterBuildLabels(); - - // Fit - me.beforeFit(); - me.fit(); - me.afterFit(); - // - me.afterUpdate(); - - return me.minSize; - }, - afterUpdate: noop, - - // - - beforeSetDimensions: noop, - setDimensions: function() { - var me = this; - // Set the unconstrained dimension before label rotation - if (me.isHorizontal()) { - // Reset position before calculating rotation - me.width = me.maxWidth; - me.left = 0; - me.right = me.width; - } else { - me.height = me.maxHeight; - - // Reset position before calculating rotation - me.top = 0; - me.bottom = me.height; - } - - // Reset padding - me.paddingLeft = 0; - me.paddingTop = 0; - me.paddingRight = 0; - me.paddingBottom = 0; - - // Reset minSize - me.minSize = { - width: 0, - height: 0 - }; - }, - afterSetDimensions: noop, - - // - - beforeBuildLabels: noop, - buildLabels: function() { - var me = this; - var labelOpts = me.options.labels; - var legendItems = labelOpts.generateLabels.call(me, me.chart); - - if (labelOpts.filter) { - legendItems = legendItems.filter(function(item) { - return labelOpts.filter(item, me.chart.data); - }); - } - - if (me.options.reverse) { - legendItems.reverse(); - } - - me.legendItems = legendItems; - }, - afterBuildLabels: noop, - - // - - beforeFit: noop, - fit: function() { - var me = this; - var opts = me.options; - var labelOpts = opts.labels; - var display = opts.display; - - var ctx = me.ctx; - - var globalDefault = Chart.defaults.global, - itemOrDefault = helpers.getValueOrDefault, - fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize), - fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle), - fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily), - labelFont = helpers.fontString(fontSize, fontStyle, fontFamily); - - // Reset hit boxes - var hitboxes = me.legendHitBoxes = []; - - var minSize = me.minSize; - var isHorizontal = me.isHorizontal(); - - if (isHorizontal) { - minSize.width = me.maxWidth; // fill all the width - minSize.height = display ? 10 : 0; - } else { - minSize.width = display ? 10 : 0; - minSize.height = me.maxHeight; // fill all the height - } - - // Increase sizes here - if (display) { - ctx.font = labelFont; - - if (isHorizontal) { - // Labels - - // Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one - var lineWidths = me.lineWidths = [0]; - var totalHeight = me.legendItems.length ? fontSize + (labelOpts.padding) : 0; - - ctx.textAlign = 'left'; - ctx.textBaseline = 'top'; - - helpers.each(me.legendItems, function(legendItem, i) { - var boxWidth = getBoxWidth(labelOpts, fontSize); - var width = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; - - if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= me.width) { - totalHeight += fontSize + (labelOpts.padding); - lineWidths[lineWidths.length] = me.left; - } - - // Store the hitbox width and height here. Final position will be updated in `draw` - hitboxes[i] = { - left: 0, - top: 0, - width: width, - height: fontSize - }; - - lineWidths[lineWidths.length - 1] += width + labelOpts.padding; - }); - - minSize.height += totalHeight; - - } else { - var vPadding = labelOpts.padding; - var columnWidths = me.columnWidths = []; - var totalWidth = labelOpts.padding; - var currentColWidth = 0; - var currentColHeight = 0; - var itemHeight = fontSize + vPadding; - - helpers.each(me.legendItems, function(legendItem, i) { - var boxWidth = getBoxWidth(labelOpts, fontSize); - var itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; - - // If too tall, go to new column - if (currentColHeight + itemHeight > minSize.height) { - totalWidth += currentColWidth + labelOpts.padding; - columnWidths.push(currentColWidth); // previous column width - - currentColWidth = 0; - currentColHeight = 0; - } - - // Get max width - currentColWidth = Math.max(currentColWidth, itemWidth); - currentColHeight += itemHeight; - - // Store the hitbox width and height here. Final position will be updated in `draw` - hitboxes[i] = { - left: 0, - top: 0, - width: itemWidth, - height: fontSize - }; - }); - - totalWidth += currentColWidth; - columnWidths.push(currentColWidth); - minSize.width += totalWidth; - } - } - - me.width = minSize.width; - me.height = minSize.height; - }, - afterFit: noop, - - // Shared Methods - isHorizontal: function() { - return this.options.position === 'top' || this.options.position === 'bottom'; - }, - - // Actually draw the legend on the canvas - draw: function() { - var me = this; - var opts = me.options; - var labelOpts = opts.labels; - var globalDefault = Chart.defaults.global, - lineDefault = globalDefault.elements.line, - legendWidth = me.width, - lineWidths = me.lineWidths; - - if (opts.display) { - var ctx = me.ctx, - cursor, - itemOrDefault = helpers.getValueOrDefault, - fontColor = itemOrDefault(labelOpts.fontColor, globalDefault.defaultFontColor), - fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize), - fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle), - fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily), - labelFont = helpers.fontString(fontSize, fontStyle, fontFamily); - - // Canvas setup - ctx.textAlign = 'left'; - ctx.textBaseline = 'top'; - ctx.lineWidth = 0.5; - ctx.strokeStyle = fontColor; // for strikethrough effect - ctx.fillStyle = fontColor; // render in correct colour - ctx.font = labelFont; - - var boxWidth = getBoxWidth(labelOpts, fontSize), - hitboxes = me.legendHitBoxes; - - // current position - var drawLegendBox = function(x, y, legendItem) { - if (isNaN(boxWidth) || boxWidth <= 0) { - return; - } - - // Set the ctx for the box - ctx.save(); - - ctx.fillStyle = itemOrDefault(legendItem.fillStyle, globalDefault.defaultColor); - ctx.lineCap = itemOrDefault(legendItem.lineCap, lineDefault.borderCapStyle); - ctx.lineDashOffset = itemOrDefault(legendItem.lineDashOffset, lineDefault.borderDashOffset); - ctx.lineJoin = itemOrDefault(legendItem.lineJoin, lineDefault.borderJoinStyle); - ctx.lineWidth = itemOrDefault(legendItem.lineWidth, lineDefault.borderWidth); - ctx.strokeStyle = itemOrDefault(legendItem.strokeStyle, globalDefault.defaultColor); - var isLineWidthZero = (itemOrDefault(legendItem.lineWidth, lineDefault.borderWidth) === 0); - - if (ctx.setLineDash) { - // IE 9 and 10 do not support line dash - ctx.setLineDash(itemOrDefault(legendItem.lineDash, lineDefault.borderDash)); - } - - if (opts.labels && opts.labels.usePointStyle) { - // Recalculate x and y for drawPoint() because its expecting - // x and y to be center of figure (instead of top left) - var radius = fontSize * Math.SQRT2 / 2; - var offSet = radius / Math.SQRT2; - var centerX = x + offSet; - var centerY = y + offSet; - - // Draw pointStyle as legend symbol - Chart.canvasHelpers.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY); - } else { - // Draw box as legend symbol - if (!isLineWidthZero) { - ctx.strokeRect(x, y, boxWidth, fontSize); - } - ctx.fillRect(x, y, boxWidth, fontSize); - } - - ctx.restore(); - }; - var fillText = function(x, y, legendItem, textWidth) { - ctx.fillText(legendItem.text, boxWidth + (fontSize / 2) + x, y); - - if (legendItem.hidden) { - // Strikethrough the text if hidden - ctx.beginPath(); - ctx.lineWidth = 2; - ctx.moveTo(boxWidth + (fontSize / 2) + x, y + (fontSize / 2)); - ctx.lineTo(boxWidth + (fontSize / 2) + x + textWidth, y + (fontSize / 2)); - ctx.stroke(); - } - }; - - // Horizontal - var isHorizontal = me.isHorizontal(); - if (isHorizontal) { - cursor = { - x: me.left + ((legendWidth - lineWidths[0]) / 2), - y: me.top + labelOpts.padding, - line: 0 - }; - } else { - cursor = { - x: me.left + labelOpts.padding, - y: me.top + labelOpts.padding, - line: 0 - }; - } - - var itemHeight = fontSize + labelOpts.padding; - helpers.each(me.legendItems, function(legendItem, i) { - var textWidth = ctx.measureText(legendItem.text).width, - width = boxWidth + (fontSize / 2) + textWidth, - x = cursor.x, - y = cursor.y; - - if (isHorizontal) { - if (x + width >= legendWidth) { - y = cursor.y += itemHeight; - cursor.line++; - x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2); - } - } else if (y + itemHeight > me.bottom) { - x = cursor.x = x + me.columnWidths[cursor.line] + labelOpts.padding; - y = cursor.y = me.top + labelOpts.padding; - cursor.line++; - } - - drawLegendBox(x, y, legendItem); - - hitboxes[i].left = x; - hitboxes[i].top = y; - - // Fill the actual label - fillText(x, y, legendItem, textWidth); - - if (isHorizontal) { - cursor.x += width + (labelOpts.padding); - } else { - cursor.y += itemHeight; - } - - }); - } - }, - - /** - * Handle an event - * @private - * @param {IEvent} event - The event to handle - * @return {Boolean} true if a change occured - */ - handleEvent: function(e) { - var me = this; - var opts = me.options; - var type = e.type === 'mouseup' ? 'click' : e.type; - var changed = false; - - if (type === 'mousemove') { - if (!opts.onHover) { - return; - } - } else if (type === 'click') { - if (!opts.onClick) { - return; - } - } else { - return; - } - - // Chart event already has relative position in it - var x = e.x, - y = e.y; - - if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) { - // See if we are touching one of the dataset boxes - var lh = me.legendHitBoxes; - for (var i = 0; i < lh.length; ++i) { - var hitBox = lh[i]; - - if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) { - // Touching an element - if (type === 'click') { - // use e.native for backwards compatibility - opts.onClick.call(me, e.native, me.legendItems[i]); - changed = true; - break; - } else if (type === 'mousemove') { - // use e.native for backwards compatibility - opts.onHover.call(me, e.native, me.legendItems[i]); - changed = true; - break; - } - } - } - } - - return changed; - } - }); - - function createNewLegendAndAttach(chartInstance, legendOpts) { - var legend = new Chart.Legend({ - ctx: chartInstance.chart.ctx, - options: legendOpts, - chart: chartInstance - }); - chartInstance.legend = legend; - Chart.layoutService.addBox(chartInstance, legend); - } - - // Register the legend plugin - Chart.plugins.register({ - beforeInit: function(chartInstance) { - var legendOpts = chartInstance.options.legend; - - if (legendOpts) { - createNewLegendAndAttach(chartInstance, legendOpts); - } - }, - beforeUpdate: function(chartInstance) { - var legendOpts = chartInstance.options.legend; - - if (legendOpts) { - legendOpts = helpers.configMerge(Chart.defaults.global.legend, legendOpts); - - if (chartInstance.legend) { - chartInstance.legend.options = legendOpts; - } else { - createNewLegendAndAttach(chartInstance, legendOpts); - } - } else { - Chart.layoutService.removeBox(chartInstance, chartInstance.legend); - delete chartInstance.legend; - } - }, - afterEvent: function(chartInstance, e) { - var legend = chartInstance.legend; - if (legend) { - legend.handleEvent(e); - } - } - }); - }; - -},{}],31:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.global.plugins = {}; - - /** - * The plugin service singleton - * @namespace Chart.plugins - * @since 2.1.0 - */ - Chart.plugins = { - /** - * Globally registered plugins. - * @private - */ - _plugins: [], - - /** - * This identifier is used to invalidate the descriptors cache attached to each chart - * when a global plugin is registered or unregistered. In this case, the cache ID is - * incremented and descriptors are regenerated during following API calls. - * @private - */ - _cacheId: 0, - - /** - * Registers the given plugin(s) if not already registered. - * @param {Array|Object} plugins plugin instance(s). - */ - register: function(plugins) { - var p = this._plugins; - ([]).concat(plugins).forEach(function(plugin) { - if (p.indexOf(plugin) === -1) { - p.push(plugin); - } - }); - - this._cacheId++; - }, - - /** - * Unregisters the given plugin(s) only if registered. - * @param {Array|Object} plugins plugin instance(s). - */ - unregister: function(plugins) { - var p = this._plugins; - ([]).concat(plugins).forEach(function(plugin) { - var idx = p.indexOf(plugin); - if (idx !== -1) { - p.splice(idx, 1); - } - }); - - this._cacheId++; - }, - - /** - * Remove all registered plugins. - * @since 2.1.5 - */ - clear: function() { - this._plugins = []; - this._cacheId++; - }, - - /** - * Returns the number of registered plugins? - * @returns {Number} - * @since 2.1.5 - */ - count: function() { - return this._plugins.length; - }, - - /** - * Returns all registered plugin instances. - * @returns {Array} array of plugin objects. - * @since 2.1.5 - */ - getAll: function() { - return this._plugins; - }, - - /** - * Calls enabled plugins for `chart` on the specified hook and with the given args. - * This method immediately returns as soon as a plugin explicitly returns false. The - * returned value can be used, for instance, to interrupt the current action. - * @param {Object} chart - The chart instance for which plugins should be called. - * @param {String} hook - The name of the plugin method to call (e.g. 'beforeUpdate'). - * @param {Array} [args] - Extra arguments to apply to the hook call. - * @returns {Boolean} false if any of the plugins return false, else returns true. - */ - notify: function(chart, hook, args) { - var descriptors = this.descriptors(chart); - var ilen = descriptors.length; - var i, descriptor, plugin, params, method; - - for (i=0; i<ilen; ++i) { - descriptor = descriptors[i]; - plugin = descriptor.plugin; - method = plugin[hook]; - if (typeof method === 'function') { - params = [chart].concat(args || []); - params.push(descriptor.options); - if (method.apply(plugin, params) === false) { - return false; - } - } - } - - return true; - }, - - /** - * Returns descriptors of enabled plugins for the given chart. - * @returns {Array} [{ plugin, options }] - * @private - */ - descriptors: function(chart) { - var cache = chart._plugins || (chart._plugins = {}); - if (cache.id === this._cacheId) { - return cache.descriptors; - } - - var plugins = []; - var descriptors = []; - var config = (chart && chart.config) || {}; - var defaults = Chart.defaults.global.plugins; - var options = (config.options && config.options.plugins) || {}; - - this._plugins.concat(config.plugins || []).forEach(function(plugin) { - var idx = plugins.indexOf(plugin); - if (idx !== -1) { - return; - } - - var id = plugin.id; - var opts = options[id]; - if (opts === false) { - return; - } - - if (opts === true) { - opts = helpers.clone(defaults[id]); - } - - plugins.push(plugin); - descriptors.push({ - plugin: plugin, - options: opts || {} - }); - }); - - cache.descriptors = descriptors; - cache.id = this._cacheId; - return descriptors; - } - }; - - /** - * Plugin extension hooks. - * @interface IPlugin - * @since 2.1.0 - */ - /** - * @method IPlugin#beforeInit - * @desc Called before initializing `chart`. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#afterInit - * @desc Called after `chart` has been initialized and before the first update. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeUpdate - * @desc Called before updating `chart`. If any plugin returns `false`, the update - * is cancelled (and thus subsequent render(s)) until another `update` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - * @returns {Boolean} `false` to cancel the chart update. - */ - /** - * @method IPlugin#afterUpdate - * @desc Called after `chart` has been updated and before rendering. Note that this - * hook will not be called if the chart update has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeDatasetsUpdate - * @desc Called before updating the `chart` datasets. If any plugin returns `false`, - * the datasets update is cancelled until another `update` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - * @returns {Boolean} false to cancel the datasets update. - * @since version 2.1.5 - */ - /** - * @method IPlugin#afterDatasetsUpdate - * @desc Called after the `chart` datasets have been updated. Note that this hook - * will not be called if the datasets update has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - * @since version 2.1.5 - */ - /** - * @method IPlugin#beforeLayout - * @desc Called before laying out `chart`. If any plugin returns `false`, - * the layout update is cancelled until another `update` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - * @returns {Boolean} `false` to cancel the chart layout. - */ - /** - * @method IPlugin#afterLayout - * @desc Called after the `chart` has been layed out. Note that this hook will not - * be called if the layout update has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeRender - * @desc Called before rendering `chart`. If any plugin returns `false`, - * the rendering is cancelled until another `render` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - * @returns {Boolean} `false` to cancel the chart rendering. - */ - /** - * @method IPlugin#afterRender - * @desc Called after the `chart` has been fully rendered (and animation completed). Note - * that this hook will not be called if the rendering has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeDraw - * @desc Called before drawing `chart` at every animation frame specified by the given - * easing value. If any plugin returns `false`, the frame drawing is cancelled until - * another `render` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. - * @param {Object} options - The plugin options. - * @returns {Boolean} `false` to cancel the chart drawing. - */ - /** - * @method IPlugin#afterDraw - * @desc Called after the `chart` has been drawn for the specific easing value. Note - * that this hook will not be called if the drawing has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeDatasetsDraw - * @desc Called before drawing the `chart` datasets. If any plugin returns `false`, - * the datasets drawing is cancelled until another `render` is triggered. - * @param {Chart.Controller} chart - The chart instance. - * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. - * @param {Object} options - The plugin options. - * @returns {Boolean} `false` to cancel the chart datasets drawing. - */ - /** - * @method IPlugin#afterDatasetsDraw - * @desc Called after the `chart` datasets have been drawn. Note that this hook - * will not be called if the datasets drawing has been previously cancelled. - * @param {Chart.Controller} chart - The chart instance. - * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#beforeEvent - * @desc Called before processing the specified `event`. If any plugin returns `false`, - * the event will be discarded. - * @param {Chart.Controller} chart - The chart instance. - * @param {IEvent} event - The event object. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#afterEvent - * @desc Called after the `event` has been consumed. Note that this hook - * will not be called if the `event` has been previously discarded. - * @param {Chart.Controller} chart - The chart instance. - * @param {IEvent} event - The event object. - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#resize - * @desc Called after the chart as been resized. - * @param {Chart.Controller} chart - The chart instance. - * @param {Number} size - The new canvas display size (eq. canvas.style width & height). - * @param {Object} options - The plugin options. - */ - /** - * @method IPlugin#destroy - * @desc Called after the chart as been destroyed. - * @param {Chart.Controller} chart - The chart instance. - * @param {Object} options - The plugin options. - */ - - /** - * Provided for backward compatibility, use Chart.plugins instead - * @namespace Chart.pluginService - * @deprecated since version 2.1.5 - * @todo remove at version 3 - * @private - */ - Chart.pluginService = Chart.plugins; - - /** - * Provided for backward compatibility, inheriting from Chart.PlugingBase has no - * effect, instead simply create/register plugins via plain JavaScript objects. - * @interface Chart.PluginBase - * @deprecated since version 2.5.0 - * @todo remove at version 3 - * @private - */ - Chart.PluginBase = helpers.inherits({}); - }; - -},{}],32:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.scale = { - display: true, - position: 'left', - - // grid line settings - gridLines: { - display: true, - color: 'rgba(0, 0, 0, 0.1)', - lineWidth: 1, - drawBorder: true, - drawOnChartArea: true, - drawTicks: true, - tickMarkLength: 10, - zeroLineWidth: 1, - zeroLineColor: 'rgba(0,0,0,0.25)', - offsetGridLines: false, - borderDash: [], - borderDashOffset: 0.0 - }, - - // scale label - scaleLabel: { - // actual label - labelString: '', - - // display property - display: false - }, - - // label settings - ticks: { - beginAtZero: false, - minRotation: 0, - maxRotation: 50, - mirror: false, - padding: 0, - reverse: false, - display: true, - autoSkip: true, - autoSkipPadding: 0, - labelOffset: 0, - // We pass through arrays to be rendered as multiline labels, we convert Others to strings here. - callback: Chart.Ticks.formatters.values - } - }; - - function computeTextSize(context, tick, font) { - return helpers.isArray(tick) ? - helpers.longestText(context, font, tick) : - context.measureText(tick).width; - } - - function parseFontOptions(options) { - var getValueOrDefault = helpers.getValueOrDefault; - var globalDefaults = Chart.defaults.global; - var size = getValueOrDefault(options.fontSize, globalDefaults.defaultFontSize); - var style = getValueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle); - var family = getValueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily); - - return { - size: size, - style: style, - family: family, - font: helpers.fontString(size, style, family) - }; - } - - Chart.Scale = Chart.Element.extend({ - /** - * Get the padding needed for the scale - * @method getPadding - * @private - * @returns {Padding} the necessary padding - */ - getPadding: function() { - var me = this; - return { - left: me.paddingLeft || 0, - top: me.paddingTop || 0, - right: me.paddingRight || 0, - bottom: me.paddingBottom || 0 - }; - }, - - // These methods are ordered by lifecyle. Utilities then follow. - // Any function defined here is inherited by all scale types. - // Any function can be extended by the scale type - - beforeUpdate: function() { - helpers.callCallback(this.options.beforeUpdate, [this]); - }, - update: function(maxWidth, maxHeight, margins) { - var me = this; - - // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) - me.beforeUpdate(); - - // Absorb the master measurements - me.maxWidth = maxWidth; - me.maxHeight = maxHeight; - me.margins = helpers.extend({ - left: 0, - right: 0, - top: 0, - bottom: 0 - }, margins); - me.longestTextCache = me.longestTextCache || {}; - - // Dimensions - me.beforeSetDimensions(); - me.setDimensions(); - me.afterSetDimensions(); - - // Data min/max - me.beforeDataLimits(); - me.determineDataLimits(); - me.afterDataLimits(); - - // Ticks - me.beforeBuildTicks(); - me.buildTicks(); - me.afterBuildTicks(); - - me.beforeTickToLabelConversion(); - me.convertTicksToLabels(); - me.afterTickToLabelConversion(); - - // Tick Rotation - me.beforeCalculateTickRotation(); - me.calculateTickRotation(); - me.afterCalculateTickRotation(); - // Fit - me.beforeFit(); - me.fit(); - me.afterFit(); - // - me.afterUpdate(); - - return me.minSize; - - }, - afterUpdate: function() { - helpers.callCallback(this.options.afterUpdate, [this]); - }, - - // - - beforeSetDimensions: function() { - helpers.callCallback(this.options.beforeSetDimensions, [this]); - }, - setDimensions: function() { - var me = this; - // Set the unconstrained dimension before label rotation - if (me.isHorizontal()) { - // Reset position before calculating rotation - me.width = me.maxWidth; - me.left = 0; - me.right = me.width; - } else { - me.height = me.maxHeight; - - // Reset position before calculating rotation - me.top = 0; - me.bottom = me.height; - } - - // Reset padding - me.paddingLeft = 0; - me.paddingTop = 0; - me.paddingRight = 0; - me.paddingBottom = 0; - }, - afterSetDimensions: function() { - helpers.callCallback(this.options.afterSetDimensions, [this]); - }, - - // Data limits - beforeDataLimits: function() { - helpers.callCallback(this.options.beforeDataLimits, [this]); - }, - determineDataLimits: helpers.noop, - afterDataLimits: function() { - helpers.callCallback(this.options.afterDataLimits, [this]); - }, - - // - beforeBuildTicks: function() { - helpers.callCallback(this.options.beforeBuildTicks, [this]); - }, - buildTicks: helpers.noop, - afterBuildTicks: function() { - helpers.callCallback(this.options.afterBuildTicks, [this]); - }, - - beforeTickToLabelConversion: function() { - helpers.callCallback(this.options.beforeTickToLabelConversion, [this]); - }, - convertTicksToLabels: function() { - var me = this; - // Convert ticks to strings - var tickOpts = me.options.ticks; - me.ticks = me.ticks.map(tickOpts.userCallback || tickOpts.callback); - }, - afterTickToLabelConversion: function() { - helpers.callCallback(this.options.afterTickToLabelConversion, [this]); - }, - - // - - beforeCalculateTickRotation: function() { - helpers.callCallback(this.options.beforeCalculateTickRotation, [this]); - }, - calculateTickRotation: function() { - var me = this; - var context = me.ctx; - var tickOpts = me.options.ticks; - - // Get the width of each grid by calculating the difference - // between x offsets between 0 and 1. - var tickFont = parseFontOptions(tickOpts); - context.font = tickFont.font; - - var labelRotation = tickOpts.minRotation || 0; - - if (me.options.display && me.isHorizontal()) { - var originalLabelWidth = helpers.longestText(context, tickFont.font, me.ticks, me.longestTextCache); - var labelWidth = originalLabelWidth; - var cosRotation; - var sinRotation; - - // Allow 3 pixels x2 padding either side for label readability - var tickWidth = me.getPixelForTick(1) - me.getPixelForTick(0) - 6; - - // Max label rotation can be set or default to 90 - also act as a loop counter - while (labelWidth > tickWidth && labelRotation < tickOpts.maxRotation) { - var angleRadians = helpers.toRadians(labelRotation); - cosRotation = Math.cos(angleRadians); - sinRotation = Math.sin(angleRadians); - - if (sinRotation * originalLabelWidth > me.maxHeight) { - // go back one step - labelRotation--; - break; - } - - labelRotation++; - labelWidth = cosRotation * originalLabelWidth; - } - } - - me.labelRotation = labelRotation; - }, - afterCalculateTickRotation: function() { - helpers.callCallback(this.options.afterCalculateTickRotation, [this]); - }, - - // - - beforeFit: function() { - helpers.callCallback(this.options.beforeFit, [this]); - }, - fit: function() { - var me = this; - // Reset - var minSize = me.minSize = { - width: 0, - height: 0 - }; - - var opts = me.options; - var tickOpts = opts.ticks; - var scaleLabelOpts = opts.scaleLabel; - var gridLineOpts = opts.gridLines; - var display = opts.display; - var isHorizontal = me.isHorizontal(); - - var tickFont = parseFontOptions(tickOpts); - var scaleLabelFontSize = parseFontOptions(scaleLabelOpts).size * 1.5; - var tickMarkLength = opts.gridLines.tickMarkLength; - - // Width - if (isHorizontal) { - // subtract the margins to line up with the chartArea if we are a full width scale - minSize.width = me.isFullWidth() ? me.maxWidth - me.margins.left - me.margins.right : me.maxWidth; - } else { - minSize.width = display && gridLineOpts.drawTicks ? tickMarkLength : 0; - } - - // height - if (isHorizontal) { - minSize.height = display && gridLineOpts.drawTicks ? tickMarkLength : 0; - } else { - minSize.height = me.maxHeight; // fill all the height - } - - // Are we showing a title for the scale? - if (scaleLabelOpts.display && display) { - if (isHorizontal) { - minSize.height += scaleLabelFontSize; - } else { - minSize.width += scaleLabelFontSize; - } - } - - // Don't bother fitting the ticks if we are not showing them - if (tickOpts.display && display) { - var largestTextWidth = helpers.longestText(me.ctx, tickFont.font, me.ticks, me.longestTextCache); - var tallestLabelHeightInLines = helpers.numberOfLabelLines(me.ticks); - var lineSpace = tickFont.size * 0.5; - - if (isHorizontal) { - // A horizontal axis is more constrained by the height. - me.longestLabelWidth = largestTextWidth; - - var angleRadians = helpers.toRadians(me.labelRotation); - var cosRotation = Math.cos(angleRadians); - var sinRotation = Math.sin(angleRadians); - - // TODO - improve this calculation - var labelHeight = (sinRotation * largestTextWidth) - + (tickFont.size * tallestLabelHeightInLines) - + (lineSpace * tallestLabelHeightInLines); - - minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight); - me.ctx.font = tickFont.font; - - var firstTick = me.ticks[0]; - var firstLabelWidth = computeTextSize(me.ctx, firstTick, tickFont.font); - - var lastTick = me.ticks[me.ticks.length - 1]; - var lastLabelWidth = computeTextSize(me.ctx, lastTick, tickFont.font); - - // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned which means that the right padding is dominated - // by the font height - if (me.labelRotation !== 0) { - me.paddingLeft = opts.position === 'bottom'? (cosRotation * firstLabelWidth) + 3: (cosRotation * lineSpace) + 3; // add 3 px to move away from canvas edges - me.paddingRight = opts.position === 'bottom'? (cosRotation * lineSpace) + 3: (cosRotation * lastLabelWidth) + 3; - } else { - me.paddingLeft = firstLabelWidth / 2 + 3; // add 3 px to move away from canvas edges - me.paddingRight = lastLabelWidth / 2 + 3; - } - } else { - // A vertical axis is more constrained by the width. Labels are the dominant factor here, so get that length first - // Account for padding - - if (tickOpts.mirror) { - largestTextWidth = 0; - } else { - largestTextWidth += me.options.ticks.padding; - } - minSize.width += largestTextWidth; - me.paddingTop = tickFont.size / 2; - me.paddingBottom = tickFont.size / 2; - } - } - - me.handleMargins(); - - me.width = minSize.width; - me.height = minSize.height; - }, - - /** - * Handle margins and padding interactions - * @private - */ - handleMargins: function() { - var me = this; - if (me.margins) { - me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0); - me.paddingTop = Math.max(me.paddingTop - me.margins.top, 0); - me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0); - me.paddingBottom = Math.max(me.paddingBottom - me.margins.bottom, 0); - } - }, - - afterFit: function() { - helpers.callCallback(this.options.afterFit, [this]); - }, - - // Shared Methods - isHorizontal: function() { - return this.options.position === 'top' || this.options.position === 'bottom'; - }, - isFullWidth: function() { - return (this.options.fullWidth); - }, - - // Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not - getRightValue: function(rawValue) { - // Null and undefined values first - if (rawValue === null || typeof(rawValue) === 'undefined') { - return NaN; - } - // isNaN(object) returns true, so make sure NaN is checking for a number; Discard Infinite values - if (typeof(rawValue) === 'number' && !isFinite(rawValue)) { - return NaN; - } - // If it is in fact an object, dive in one more level - if (typeof(rawValue) === 'object') { - if ((rawValue instanceof Date) || (rawValue.isValid)) { - return rawValue; - } - return this.getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y); - } - - // Value is good, return it - return rawValue; - }, - - // Used to get the value to display in the tooltip for the data at the given index - // function getLabelForIndex(index, datasetIndex) - getLabelForIndex: helpers.noop, - - // Used to get data value locations. Value can either be an index or a numerical value - getPixelForValue: helpers.noop, - - // Used to get the data value from a given pixel. This is the inverse of getPixelForValue - getValueForPixel: helpers.noop, - - // Used for tick location, should - getPixelForTick: function(index, includeOffset) { - var me = this; - if (me.isHorizontal()) { - var innerWidth = me.width - (me.paddingLeft + me.paddingRight); - var tickWidth = innerWidth / Math.max((me.ticks.length - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1); - var pixel = (tickWidth * index) + me.paddingLeft; - - if (includeOffset) { - pixel += tickWidth / 2; - } - - var finalVal = me.left + Math.round(pixel); - finalVal += me.isFullWidth() ? me.margins.left : 0; - return finalVal; - } - var innerHeight = me.height - (me.paddingTop + me.paddingBottom); - return me.top + (index * (innerHeight / (me.ticks.length - 1))); - }, - - // Utility for getting the pixel location of a percentage of scale - getPixelForDecimal: function(decimal /* , includeOffset*/) { - var me = this; - if (me.isHorizontal()) { - var innerWidth = me.width - (me.paddingLeft + me.paddingRight); - var valueOffset = (innerWidth * decimal) + me.paddingLeft; - - var finalVal = me.left + Math.round(valueOffset); - finalVal += me.isFullWidth() ? me.margins.left : 0; - return finalVal; - } - return me.top + (decimal * me.height); - }, - - getBasePixel: function() { - return this.getPixelForValue(this.getBaseValue()); - }, - - getBaseValue: function() { - var me = this; - var min = me.min; - var max = me.max; - - return me.beginAtZero ? 0: - min < 0 && max < 0? max : - min > 0 && max > 0? min : - 0; - }, - - // Actually draw the scale on the canvas - // @param {rectangle} chartArea : the area of the chart to draw full grid lines on - draw: function(chartArea) { - var me = this; - var options = me.options; - if (!options.display) { - return; - } - - var context = me.ctx; - var globalDefaults = Chart.defaults.global; - var optionTicks = options.ticks; - var gridLines = options.gridLines; - var scaleLabel = options.scaleLabel; - - var isRotated = me.labelRotation !== 0; - var skipRatio; - var useAutoskipper = optionTicks.autoSkip; - var isHorizontal = me.isHorizontal(); - - // figure out the maximum number of gridlines to show - var maxTicks; - if (optionTicks.maxTicksLimit) { - maxTicks = optionTicks.maxTicksLimit; - } - - var tickFontColor = helpers.getValueOrDefault(optionTicks.fontColor, globalDefaults.defaultFontColor); - var tickFont = parseFontOptions(optionTicks); - - var tl = gridLines.drawTicks ? gridLines.tickMarkLength : 0; - var borderDash = helpers.getValueOrDefault(gridLines.borderDash, globalDefaults.borderDash); - var borderDashOffset = helpers.getValueOrDefault(gridLines.borderDashOffset, globalDefaults.borderDashOffset); - - var scaleLabelFontColor = helpers.getValueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor); - var scaleLabelFont = parseFontOptions(scaleLabel); - - var labelRotationRadians = helpers.toRadians(me.labelRotation); - var cosRotation = Math.cos(labelRotationRadians); - var longestRotatedLabel = me.longestLabelWidth * cosRotation; - - // Make sure we draw text in the correct color and font - context.fillStyle = tickFontColor; - - var itemsToDraw = []; - - if (isHorizontal) { - skipRatio = false; - - // Only calculate the skip ratio with the half width of longestRotateLabel if we got an actual rotation - // See #2584 - if (isRotated) { - longestRotatedLabel /= 2; - } - - if ((longestRotatedLabel + optionTicks.autoSkipPadding) * me.ticks.length > (me.width - (me.paddingLeft + me.paddingRight))) { - skipRatio = 1 + Math.floor(((longestRotatedLabel + optionTicks.autoSkipPadding) * me.ticks.length) / (me.width - (me.paddingLeft + me.paddingRight))); - } - - // if they defined a max number of optionTicks, - // increase skipRatio until that number is met - if (maxTicks && me.ticks.length > maxTicks) { - while (!skipRatio || me.ticks.length / (skipRatio || 1) > maxTicks) { - if (!skipRatio) { - skipRatio = 1; - } - skipRatio += 1; - } - } - - if (!useAutoskipper) { - skipRatio = false; - } - } - - - var xTickStart = options.position === 'right' ? me.left : me.right - tl; - var xTickEnd = options.position === 'right' ? me.left + tl : me.right; - var yTickStart = options.position === 'bottom' ? me.top : me.bottom - tl; - var yTickEnd = options.position === 'bottom' ? me.top + tl : me.bottom; - - helpers.each(me.ticks, function(label, index) { - // If the callback returned a null or undefined value, do not draw this line - if (label === undefined || label === null) { - return; - } - - var isLastTick = me.ticks.length === index + 1; - - // Since we always show the last tick,we need may need to hide the last shown one before - var shouldSkip = (skipRatio > 1 && index % skipRatio > 0) || (index % skipRatio === 0 && index + skipRatio >= me.ticks.length); - if (shouldSkip && !isLastTick || (label === undefined || label === null)) { - return; - } - - var lineWidth, lineColor; - if (index === (typeof me.zeroLineIndex !== 'undefined' ? me.zeroLineIndex : 0)) { - // Draw the first index specially - lineWidth = gridLines.zeroLineWidth; - lineColor = gridLines.zeroLineColor; - } else { - lineWidth = helpers.getValueAtIndexOrDefault(gridLines.lineWidth, index); - lineColor = helpers.getValueAtIndexOrDefault(gridLines.color, index); - } - - // Common properties - var tx1, ty1, tx2, ty2, x1, y1, x2, y2, labelX, labelY; - var textAlign = 'middle'; - var textBaseline = 'middle'; - - if (isHorizontal) { - - if (options.position === 'bottom') { - // bottom - textBaseline = !isRotated? 'top':'middle'; - textAlign = !isRotated? 'center': 'right'; - labelY = me.top + tl; - } else { - // top - textBaseline = !isRotated? 'bottom':'middle'; - textAlign = !isRotated? 'center': 'left'; - labelY = me.bottom - tl; - } - - var xLineValue = me.getPixelForTick(index) + helpers.aliasPixel(lineWidth); // xvalues for grid lines - labelX = me.getPixelForTick(index, gridLines.offsetGridLines) + optionTicks.labelOffset; // x values for optionTicks (need to consider offsetLabel option) - - tx1 = tx2 = x1 = x2 = xLineValue; - ty1 = yTickStart; - ty2 = yTickEnd; - y1 = chartArea.top; - y2 = chartArea.bottom; - } else { - var isLeft = options.position === 'left'; - var tickPadding = optionTicks.padding; - var labelXOffset; - - if (optionTicks.mirror) { - textAlign = isLeft ? 'left' : 'right'; - labelXOffset = tickPadding; - } else { - textAlign = isLeft ? 'right' : 'left'; - labelXOffset = tl + tickPadding; - } - - labelX = isLeft ? me.right - labelXOffset : me.left + labelXOffset; - - var yLineValue = me.getPixelForTick(index); // xvalues for grid lines - yLineValue += helpers.aliasPixel(lineWidth); - labelY = me.getPixelForTick(index, gridLines.offsetGridLines); - - tx1 = xTickStart; - tx2 = xTickEnd; - x1 = chartArea.left; - x2 = chartArea.right; - ty1 = ty2 = y1 = y2 = yLineValue; - } - - itemsToDraw.push({ - tx1: tx1, - ty1: ty1, - tx2: tx2, - ty2: ty2, - x1: x1, - y1: y1, - x2: x2, - y2: y2, - labelX: labelX, - labelY: labelY, - glWidth: lineWidth, - glColor: lineColor, - glBorderDash: borderDash, - glBorderDashOffset: borderDashOffset, - rotation: -1 * labelRotationRadians, - label: label, - textBaseline: textBaseline, - textAlign: textAlign - }); - }); - - // Draw all of the tick labels, tick marks, and grid lines at the correct places - helpers.each(itemsToDraw, function(itemToDraw) { - if (gridLines.display) { - context.save(); - context.lineWidth = itemToDraw.glWidth; - context.strokeStyle = itemToDraw.glColor; - if (context.setLineDash) { - context.setLineDash(itemToDraw.glBorderDash); - context.lineDashOffset = itemToDraw.glBorderDashOffset; - } - - context.beginPath(); - - if (gridLines.drawTicks) { - context.moveTo(itemToDraw.tx1, itemToDraw.ty1); - context.lineTo(itemToDraw.tx2, itemToDraw.ty2); - } - - if (gridLines.drawOnChartArea) { - context.moveTo(itemToDraw.x1, itemToDraw.y1); - context.lineTo(itemToDraw.x2, itemToDraw.y2); - } - - context.stroke(); - context.restore(); - } - - if (optionTicks.display) { - context.save(); - context.translate(itemToDraw.labelX, itemToDraw.labelY); - context.rotate(itemToDraw.rotation); - context.font = tickFont.font; - context.textBaseline = itemToDraw.textBaseline; - context.textAlign = itemToDraw.textAlign; - - var label = itemToDraw.label; - if (helpers.isArray(label)) { - for (var i = 0, y = 0; i < label.length; ++i) { - // We just make sure the multiline element is a string here.. - context.fillText('' + label[i], 0, y); - // apply same lineSpacing as calculated @ L#320 - y += (tickFont.size * 1.5); - } - } else { - context.fillText(label, 0, 0); - } - context.restore(); - } - }); - - if (scaleLabel.display) { - // Draw the scale label - var scaleLabelX; - var scaleLabelY; - var rotation = 0; - - if (isHorizontal) { - scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width - scaleLabelY = options.position === 'bottom' ? me.bottom - (scaleLabelFont.size / 2) : me.top + (scaleLabelFont.size / 2); - } else { - var isLeft = options.position === 'left'; - scaleLabelX = isLeft ? me.left + (scaleLabelFont.size / 2) : me.right - (scaleLabelFont.size / 2); - scaleLabelY = me.top + ((me.bottom - me.top) / 2); - rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI; - } - - context.save(); - context.translate(scaleLabelX, scaleLabelY); - context.rotate(rotation); - context.textAlign = 'center'; - context.textBaseline = 'middle'; - context.fillStyle = scaleLabelFontColor; // render in correct colour - context.font = scaleLabelFont.font; - context.fillText(scaleLabel.labelString, 0, 0); - context.restore(); - } - - if (gridLines.drawBorder) { - // Draw the line at the edge of the axis - context.lineWidth = helpers.getValueAtIndexOrDefault(gridLines.lineWidth, 0); - context.strokeStyle = helpers.getValueAtIndexOrDefault(gridLines.color, 0); - var x1 = me.left, - x2 = me.right, - y1 = me.top, - y2 = me.bottom; - - var aliasPixel = helpers.aliasPixel(context.lineWidth); - if (isHorizontal) { - y1 = y2 = options.position === 'top' ? me.bottom : me.top; - y1 += aliasPixel; - y2 += aliasPixel; - } else { - x1 = x2 = options.position === 'left' ? me.right : me.left; - x1 += aliasPixel; - x2 += aliasPixel; - } - - context.beginPath(); - context.moveTo(x1, y1); - context.lineTo(x2, y2); - context.stroke(); - } - } - }); - }; - -},{}],33:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.scaleService = { - // Scale registration object. Extensions can register new scale types (such as log or DB scales) and then - // use the new chart options to grab the correct scale - constructors: {}, - // Use a registration function so that we can move to an ES6 map when we no longer need to support - // old browsers - - // Scale config defaults - defaults: {}, - registerScaleType: function(type, scaleConstructor, defaults) { - this.constructors[type] = scaleConstructor; - this.defaults[type] = helpers.clone(defaults); - }, - getScaleConstructor: function(type) { - return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined; - }, - getScaleDefaults: function(type) { - // Return the scale defaults merged with the global settings so that we always use the latest ones - return this.defaults.hasOwnProperty(type) ? helpers.scaleMerge(Chart.defaults.scale, this.defaults[type]) : {}; - }, - updateScaleDefaults: function(type, additions) { - var defaults = this.defaults; - if (defaults.hasOwnProperty(type)) { - defaults[type] = helpers.extend(defaults[type], additions); - } - }, - addScalesToLayout: function(chartInstance) { - // Adds each scale to the chart.boxes array to be sized accordingly - helpers.each(chartInstance.scales, function(scale) { - Chart.layoutService.addBox(chartInstance, scale); - }); - } - }; - }; - -},{}],34:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - /** - * Namespace to hold static tick generation functions - * @namespace Chart.Ticks - */ - Chart.Ticks = { - /** - * Namespace to hold generators for different types of ticks - * @namespace Chart.Ticks.generators - */ - generators: { - /** - * Interface for the options provided to the numeric tick generator - * @interface INumericTickGenerationOptions - */ - /** - * The maximum number of ticks to display - * @name INumericTickGenerationOptions#maxTicks - * @type Number - */ - /** - * The distance between each tick. - * @name INumericTickGenerationOptions#stepSize - * @type Number - * @optional - */ - /** - * Forced minimum for the ticks. If not specified, the minimum of the data range is used to calculate the tick minimum - * @name INumericTickGenerationOptions#min - * @type Number - * @optional - */ - /** - * The maximum value of the ticks. If not specified, the maximum of the data range is used to calculate the tick maximum - * @name INumericTickGenerationOptions#max - * @type Number - * @optional - */ - - /** - * Generate a set of linear ticks - * @method Chart.Ticks.generators.linear - * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks - * @param dataRange {IRange} the range of the data - * @returns {Array<Number>} array of tick values - */ - linear: function(generationOptions, dataRange) { - var ticks = []; - // To get a "nice" value for the tick spacing, we will use the appropriately named - // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks - // for details. - - var spacing; - if (generationOptions.stepSize && generationOptions.stepSize > 0) { - spacing = generationOptions.stepSize; - } else { - var niceRange = helpers.niceNum(dataRange.max - dataRange.min, false); - spacing = helpers.niceNum(niceRange / (generationOptions.maxTicks - 1), true); - } - var niceMin = Math.floor(dataRange.min / spacing) * spacing; - var niceMax = Math.ceil(dataRange.max / spacing) * spacing; - - // If min, max and stepSize is set and they make an evenly spaced scale use it. - if (generationOptions.min && generationOptions.max && generationOptions.stepSize) { - // If very close to our whole number, use it. - if (helpers.almostWhole((generationOptions.max - generationOptions.min) / generationOptions.stepSize, spacing / 1000)) { - niceMin = generationOptions.min; - niceMax = generationOptions.max; - } - } - - var numSpaces = (niceMax - niceMin) / spacing; - // If very close to our rounded value, use it. - if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) { - numSpaces = Math.round(numSpaces); - } else { - numSpaces = Math.ceil(numSpaces); - } - - // Put the values into the ticks array - ticks.push(generationOptions.min !== undefined ? generationOptions.min : niceMin); - for (var j = 1; j < numSpaces; ++j) { - ticks.push(niceMin + (j * spacing)); - } - ticks.push(generationOptions.max !== undefined ? generationOptions.max : niceMax); - - return ticks; - }, - - /** - * Generate a set of logarithmic ticks - * @method Chart.Ticks.generators.logarithmic - * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks - * @param dataRange {IRange} the range of the data - * @returns {Array<Number>} array of tick values - */ - logarithmic: function(generationOptions, dataRange) { - var ticks = []; - var getValueOrDefault = helpers.getValueOrDefault; - - // Figure out what the max number of ticks we can support it is based on the size of - // the axis area. For now, we say that the minimum tick spacing in pixels must be 50 - // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on - // the graph - var tickVal = getValueOrDefault(generationOptions.min, Math.pow(10, Math.floor(helpers.log10(dataRange.min)))); - - var endExp = Math.floor(helpers.log10(dataRange.max)); - var endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp)); - var exp; - var significand; - - if (tickVal === 0) { - exp = Math.floor(helpers.log10(dataRange.minNotZero)); - significand = Math.floor(dataRange.minNotZero / Math.pow(10, exp)); - - ticks.push(tickVal); - tickVal = significand * Math.pow(10, exp); - } else { - exp = Math.floor(helpers.log10(tickVal)); - significand = Math.floor(tickVal / Math.pow(10, exp)); - } - - do { - ticks.push(tickVal); - - ++significand; - if (significand === 10) { - significand = 1; - ++exp; - } - - tickVal = significand * Math.pow(10, exp); - } while (exp < endExp || (exp === endExp && significand < endSignificand)); - - var lastTick = getValueOrDefault(generationOptions.max, tickVal); - ticks.push(lastTick); - - return ticks; - } - }, - - /** - * Namespace to hold formatters for different types of ticks - * @namespace Chart.Ticks.formatters - */ - formatters: { - /** - * Formatter for value labels - * @method Chart.Ticks.formatters.values - * @param value the value to display - * @return {String|Array} the label to display - */ - values: function(value) { - return helpers.isArray(value) ? value : '' + value; - }, - - /** - * Formatter for linear numeric ticks - * @method Chart.Ticks.formatters.linear - * @param tickValue {Number} the value to be formatted - * @param index {Number} the position of the tickValue parameter in the ticks array - * @param ticks {Array<Number>} the list of ticks being converted - * @return {String} string representation of the tickValue parameter - */ - linear: function(tickValue, index, ticks) { - // If we have lots of ticks, don't use the ones - var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0]; - - // If we have a number like 2.5 as the delta, figure out how many decimal places we need - if (Math.abs(delta) > 1) { - if (tickValue !== Math.floor(tickValue)) { - // not an integer - delta = tickValue - Math.floor(tickValue); - } - } - - var logDelta = helpers.log10(Math.abs(delta)); - var tickString = ''; - - if (tickValue !== 0) { - var numDecimal = -1 * Math.floor(logDelta); - numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places - tickString = tickValue.toFixed(numDecimal); - } else { - tickString = '0'; // never show decimal places for 0 - } - - return tickString; - }, - - logarithmic: function(tickValue, index, ticks) { - var remain = tickValue / (Math.pow(10, Math.floor(helpers.log10(tickValue)))); - - if (tickValue === 0) { - return '0'; - } else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === ticks.length - 1) { - return tickValue.toExponential(); - } - return ''; - } - } - }; - }; - -},{}],35:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - Chart.defaults.global.title = { - display: false, - position: 'top', - fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes) - - fontStyle: 'bold', - padding: 10, - - // actual title - text: '' - }; - - var noop = helpers.noop; - Chart.Title = Chart.Element.extend({ - - initialize: function(config) { - var me = this; - helpers.extend(me, config); - - // Contains hit boxes for each dataset (in dataset order) - me.legendHitBoxes = []; - }, - - // These methods are ordered by lifecycle. Utilities then follow. - - beforeUpdate: noop, - update: function(maxWidth, maxHeight, margins) { - var me = this; - - // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) - me.beforeUpdate(); - - // Absorb the master measurements - me.maxWidth = maxWidth; - me.maxHeight = maxHeight; - me.margins = margins; - - // Dimensions - me.beforeSetDimensions(); - me.setDimensions(); - me.afterSetDimensions(); - // Labels - me.beforeBuildLabels(); - me.buildLabels(); - me.afterBuildLabels(); - - // Fit - me.beforeFit(); - me.fit(); - me.afterFit(); - // - me.afterUpdate(); - - return me.minSize; - - }, - afterUpdate: noop, - - // - - beforeSetDimensions: noop, - setDimensions: function() { - var me = this; - // Set the unconstrained dimension before label rotation - if (me.isHorizontal()) { - // Reset position before calculating rotation - me.width = me.maxWidth; - me.left = 0; - me.right = me.width; - } else { - me.height = me.maxHeight; - - // Reset position before calculating rotation - me.top = 0; - me.bottom = me.height; - } - - // Reset padding - me.paddingLeft = 0; - me.paddingTop = 0; - me.paddingRight = 0; - me.paddingBottom = 0; - - // Reset minSize - me.minSize = { - width: 0, - height: 0 - }; - }, - afterSetDimensions: noop, - - // - - beforeBuildLabels: noop, - buildLabels: noop, - afterBuildLabels: noop, - - // - - beforeFit: noop, - fit: function() { - var me = this, - valueOrDefault = helpers.getValueOrDefault, - opts = me.options, - globalDefaults = Chart.defaults.global, - display = opts.display, - fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize), - minSize = me.minSize; - - if (me.isHorizontal()) { - minSize.width = me.maxWidth; // fill all the width - minSize.height = display ? fontSize + (opts.padding * 2) : 0; - } else { - minSize.width = display ? fontSize + (opts.padding * 2) : 0; - minSize.height = me.maxHeight; // fill all the height - } - - me.width = minSize.width; - me.height = minSize.height; - - }, - afterFit: noop, - - // Shared Methods - isHorizontal: function() { - var pos = this.options.position; - return pos === 'top' || pos === 'bottom'; - }, - - // Actually draw the title block on the canvas - draw: function() { - var me = this, - ctx = me.ctx, - valueOrDefault = helpers.getValueOrDefault, - opts = me.options, - globalDefaults = Chart.defaults.global; - - if (opts.display) { - var fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize), - fontStyle = valueOrDefault(opts.fontStyle, globalDefaults.defaultFontStyle), - fontFamily = valueOrDefault(opts.fontFamily, globalDefaults.defaultFontFamily), - titleFont = helpers.fontString(fontSize, fontStyle, fontFamily), - rotation = 0, - titleX, - titleY, - top = me.top, - left = me.left, - bottom = me.bottom, - right = me.right, - maxWidth; - - ctx.fillStyle = valueOrDefault(opts.fontColor, globalDefaults.defaultFontColor); // render in correct colour - ctx.font = titleFont; - - // Horizontal - if (me.isHorizontal()) { - titleX = left + ((right - left) / 2); // midpoint of the width - titleY = top + ((bottom - top) / 2); // midpoint of the height - maxWidth = right - left; - } else { - titleX = opts.position === 'left' ? left + (fontSize / 2) : right - (fontSize / 2); - titleY = top + ((bottom - top) / 2); - maxWidth = bottom - top; - rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5); - } - - ctx.save(); - ctx.translate(titleX, titleY); - ctx.rotate(rotation); - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - ctx.fillText(opts.text, 0, 0, maxWidth); - ctx.restore(); - } - } - }); - - function createNewTitleBlockAndAttach(chartInstance, titleOpts) { - var title = new Chart.Title({ - ctx: chartInstance.chart.ctx, - options: titleOpts, - chart: chartInstance - }); - chartInstance.titleBlock = title; - Chart.layoutService.addBox(chartInstance, title); - } - - // Register the title plugin - Chart.plugins.register({ - beforeInit: function(chartInstance) { - var titleOpts = chartInstance.options.title; - - if (titleOpts) { - createNewTitleBlockAndAttach(chartInstance, titleOpts); - } - }, - beforeUpdate: function(chartInstance) { - var titleOpts = chartInstance.options.title; - - if (titleOpts) { - titleOpts = helpers.configMerge(Chart.defaults.global.title, titleOpts); - - if (chartInstance.titleBlock) { - chartInstance.titleBlock.options = titleOpts; - } else { - createNewTitleBlockAndAttach(chartInstance, titleOpts); - } - } else { - Chart.layoutService.removeBox(chartInstance, chartInstance.titleBlock); - delete chartInstance.titleBlock; - } - } - }); - }; - -},{}],36:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - /** - * Helper method to merge the opacity into a color - */ - function mergeOpacity(colorString, opacity) { - var color = helpers.color(colorString); - return color.alpha(opacity * color.alpha()).rgbaString(); - } - - Chart.defaults.global.tooltips = { - enabled: true, - custom: null, - mode: 'nearest', - position: 'average', - intersect: true, - backgroundColor: 'rgba(0,0,0,0.8)', - titleFontStyle: 'bold', - titleSpacing: 2, - titleMarginBottom: 6, - titleFontColor: '#fff', - titleAlign: 'left', - bodySpacing: 2, - bodyFontColor: '#fff', - bodyAlign: 'left', - footerFontStyle: 'bold', - footerSpacing: 2, - footerMarginTop: 6, - footerFontColor: '#fff', - footerAlign: 'left', - yPadding: 6, - xPadding: 6, - caretSize: 5, - cornerRadius: 6, - multiKeyBackground: '#fff', - displayColors: true, - callbacks: { - // Args are: (tooltipItems, data) - beforeTitle: helpers.noop, - title: function(tooltipItems, data) { - // Pick first xLabel for now - var title = ''; - var labels = data.labels; - var labelCount = labels ? labels.length : 0; - - if (tooltipItems.length > 0) { - var item = tooltipItems[0]; - - if (item.xLabel) { - title = item.xLabel; - } else if (labelCount > 0 && item.index < labelCount) { - title = labels[item.index]; - } - } - - return title; - }, - afterTitle: helpers.noop, - - // Args are: (tooltipItems, data) - beforeBody: helpers.noop, - - // Args are: (tooltipItem, data) - beforeLabel: helpers.noop, - label: function(tooltipItem, data) { - var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || ''; - return datasetLabel + ': ' + tooltipItem.yLabel; - }, - labelColor: function(tooltipItem, chartInstance) { - var meta = chartInstance.getDatasetMeta(tooltipItem.datasetIndex); - var activeElement = meta.data[tooltipItem.index]; - var view = activeElement._view; - return { - borderColor: view.borderColor, - backgroundColor: view.backgroundColor - }; - }, - afterLabel: helpers.noop, - - // Args are: (tooltipItems, data) - afterBody: helpers.noop, - - // Args are: (tooltipItems, data) - beforeFooter: helpers.noop, - footer: helpers.noop, - afterFooter: helpers.noop - } - }; - - // Helper to push or concat based on if the 2nd parameter is an array or not - function pushOrConcat(base, toPush) { - if (toPush) { - if (helpers.isArray(toPush)) { - // base = base.concat(toPush); - Array.prototype.push.apply(base, toPush); - } else { - base.push(toPush); - } - } - - return base; - } - - // Private helper to create a tooltip item model - // @param element : the chart element (point, arc, bar) to create the tooltip item for - // @return : new tooltip item - function createTooltipItem(element) { - var xScale = element._xScale; - var yScale = element._yScale || element._scale; // handle radar || polarArea charts - var index = element._index, - datasetIndex = element._datasetIndex; - - return { - xLabel: xScale ? xScale.getLabelForIndex(index, datasetIndex) : '', - yLabel: yScale ? yScale.getLabelForIndex(index, datasetIndex) : '', - index: index, - datasetIndex: datasetIndex, - x: element._model.x, - y: element._model.y - }; - } - - /** - * Helper to get the reset model for the tooltip - * @param tooltipOpts {Object} the tooltip options - */ - function getBaseModel(tooltipOpts) { - var globalDefaults = Chart.defaults.global; - var getValueOrDefault = helpers.getValueOrDefault; - - return { - // Positioning - xPadding: tooltipOpts.xPadding, - yPadding: tooltipOpts.yPadding, - xAlign: tooltipOpts.xAlign, - yAlign: tooltipOpts.yAlign, - - // Body - bodyFontColor: tooltipOpts.bodyFontColor, - _bodyFontFamily: getValueOrDefault(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily), - _bodyFontStyle: getValueOrDefault(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle), - _bodyAlign: tooltipOpts.bodyAlign, - bodyFontSize: getValueOrDefault(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize), - bodySpacing: tooltipOpts.bodySpacing, - - // Title - titleFontColor: tooltipOpts.titleFontColor, - _titleFontFamily: getValueOrDefault(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily), - _titleFontStyle: getValueOrDefault(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle), - titleFontSize: getValueOrDefault(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize), - _titleAlign: tooltipOpts.titleAlign, - titleSpacing: tooltipOpts.titleSpacing, - titleMarginBottom: tooltipOpts.titleMarginBottom, - - // Footer - footerFontColor: tooltipOpts.footerFontColor, - _footerFontFamily: getValueOrDefault(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily), - _footerFontStyle: getValueOrDefault(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle), - footerFontSize: getValueOrDefault(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize), - _footerAlign: tooltipOpts.footerAlign, - footerSpacing: tooltipOpts.footerSpacing, - footerMarginTop: tooltipOpts.footerMarginTop, - - // Appearance - caretSize: tooltipOpts.caretSize, - cornerRadius: tooltipOpts.cornerRadius, - backgroundColor: tooltipOpts.backgroundColor, - opacity: 0, - legendColorBackground: tooltipOpts.multiKeyBackground, - displayColors: tooltipOpts.displayColors - }; - } - - /** - * Get the size of the tooltip - */ - function getTooltipSize(tooltip, model) { - var ctx = tooltip._chart.ctx; - - var height = model.yPadding * 2; // Tooltip Padding - var width = 0; - - // Count of all lines in the body - var body = model.body; - var combinedBodyLength = body.reduce(function(count, bodyItem) { - return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length; - }, 0); - combinedBodyLength += model.beforeBody.length + model.afterBody.length; - - var titleLineCount = model.title.length; - var footerLineCount = model.footer.length; - var titleFontSize = model.titleFontSize, - bodyFontSize = model.bodyFontSize, - footerFontSize = model.footerFontSize; - - height += titleLineCount * titleFontSize; // Title Lines - height += titleLineCount ? (titleLineCount - 1) * model.titleSpacing : 0; // Title Line Spacing - height += titleLineCount ? model.titleMarginBottom : 0; // Title's bottom Margin - height += combinedBodyLength * bodyFontSize; // Body Lines - height += combinedBodyLength ? (combinedBodyLength - 1) * model.bodySpacing : 0; // Body Line Spacing - height += footerLineCount ? model.footerMarginTop : 0; // Footer Margin - height += footerLineCount * (footerFontSize); // Footer Lines - height += footerLineCount ? (footerLineCount - 1) * model.footerSpacing : 0; // Footer Line Spacing - - // Title width - var widthPadding = 0; - var maxLineWidth = function(line) { - width = Math.max(width, ctx.measureText(line).width + widthPadding); - }; - - ctx.font = helpers.fontString(titleFontSize, model._titleFontStyle, model._titleFontFamily); - helpers.each(model.title, maxLineWidth); - - // Body width - ctx.font = helpers.fontString(bodyFontSize, model._bodyFontStyle, model._bodyFontFamily); - helpers.each(model.beforeBody.concat(model.afterBody), maxLineWidth); - - // Body lines may include some extra width due to the color box - widthPadding = model.displayColors ? (bodyFontSize + 2) : 0; - helpers.each(body, function(bodyItem) { - helpers.each(bodyItem.before, maxLineWidth); - helpers.each(bodyItem.lines, maxLineWidth); - helpers.each(bodyItem.after, maxLineWidth); - }); - - // Reset back to 0 - widthPadding = 0; - - // Footer width - ctx.font = helpers.fontString(footerFontSize, model._footerFontStyle, model._footerFontFamily); - helpers.each(model.footer, maxLineWidth); - - // Add padding - width += 2 * model.xPadding; - - return { - width: width, - height: height - }; - } - - /** - * Helper to get the alignment of a tooltip given the size - */ - function determineAlignment(tooltip, size) { - var model = tooltip._model; - var chart = tooltip._chart; - var chartArea = tooltip._chartInstance.chartArea; - var xAlign = 'center'; - var yAlign = 'center'; - - if (model.y < size.height) { - yAlign = 'top'; - } else if (model.y > (chart.height - size.height)) { - yAlign = 'bottom'; - } - - var lf, rf; // functions to determine left, right alignment - var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart - var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges - var midX = (chartArea.left + chartArea.right) / 2; - var midY = (chartArea.top + chartArea.bottom) / 2; - - if (yAlign === 'center') { - lf = function(x) { - return x <= midX; - }; - rf = function(x) { - return x > midX; - }; - } else { - lf = function(x) { - return x <= (size.width / 2); - }; - rf = function(x) { - return x >= (chart.width - (size.width / 2)); - }; - } - - olf = function(x) { - return x + size.width > chart.width; - }; - orf = function(x) { - return x - size.width < 0; - }; - yf = function(y) { - return y <= midY ? 'top' : 'bottom'; - }; - - if (lf(model.x)) { - xAlign = 'left'; - - // Is tooltip too wide and goes over the right side of the chart.? - if (olf(model.x)) { - xAlign = 'center'; - yAlign = yf(model.y); - } - } else if (rf(model.x)) { - xAlign = 'right'; - - // Is tooltip too wide and goes outside left edge of canvas? - if (orf(model.x)) { - xAlign = 'center'; - yAlign = yf(model.y); - } - } - - var opts = tooltip._options; - return { - xAlign: opts.xAlign ? opts.xAlign : xAlign, - yAlign: opts.yAlign ? opts.yAlign : yAlign - }; - } - - /** - * @Helper to get the location a tooltip needs to be placed at given the initial position (via the vm) and the size and alignment - */ - function getBackgroundPoint(vm, size, alignment) { - // Background Position - var x = vm.x; - var y = vm.y; - - var caretSize = vm.caretSize, - caretPadding = vm.caretPadding, - cornerRadius = vm.cornerRadius, - xAlign = alignment.xAlign, - yAlign = alignment.yAlign, - paddingAndSize = caretSize + caretPadding, - radiusAndPadding = cornerRadius + caretPadding; - - if (xAlign === 'right') { - x -= size.width; - } else if (xAlign === 'center') { - x -= (size.width / 2); - } - - if (yAlign === 'top') { - y += paddingAndSize; - } else if (yAlign === 'bottom') { - y -= size.height + paddingAndSize; - } else { - y -= (size.height / 2); - } - - if (yAlign === 'center') { - if (xAlign === 'left') { - x += paddingAndSize; - } else if (xAlign === 'right') { - x -= paddingAndSize; - } - } else if (xAlign === 'left') { - x -= radiusAndPadding; - } else if (xAlign === 'right') { - x += radiusAndPadding; - } - - return { - x: x, - y: y - }; - } - - Chart.Tooltip = Chart.Element.extend({ - initialize: function() { - this._model = getBaseModel(this._options); - }, - - // Get the title - // Args are: (tooltipItem, data) - getTitle: function() { - var me = this; - var opts = me._options; - var callbacks = opts.callbacks; - - var beforeTitle = callbacks.beforeTitle.apply(me, arguments), - title = callbacks.title.apply(me, arguments), - afterTitle = callbacks.afterTitle.apply(me, arguments); - - var lines = []; - lines = pushOrConcat(lines, beforeTitle); - lines = pushOrConcat(lines, title); - lines = pushOrConcat(lines, afterTitle); - - return lines; - }, - - // Args are: (tooltipItem, data) - getBeforeBody: function() { - var lines = this._options.callbacks.beforeBody.apply(this, arguments); - return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : []; - }, - - // Args are: (tooltipItem, data) - getBody: function(tooltipItems, data) { - var me = this; - var callbacks = me._options.callbacks; - var bodyItems = []; - - helpers.each(tooltipItems, function(tooltipItem) { - var bodyItem = { - before: [], - lines: [], - after: [] - }; - pushOrConcat(bodyItem.before, callbacks.beforeLabel.call(me, tooltipItem, data)); - pushOrConcat(bodyItem.lines, callbacks.label.call(me, tooltipItem, data)); - pushOrConcat(bodyItem.after, callbacks.afterLabel.call(me, tooltipItem, data)); - - bodyItems.push(bodyItem); - }); - - return bodyItems; - }, - - // Args are: (tooltipItem, data) - getAfterBody: function() { - var lines = this._options.callbacks.afterBody.apply(this, arguments); - return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : []; - }, - - // Get the footer and beforeFooter and afterFooter lines - // Args are: (tooltipItem, data) - getFooter: function() { - var me = this; - var callbacks = me._options.callbacks; - - var beforeFooter = callbacks.beforeFooter.apply(me, arguments); - var footer = callbacks.footer.apply(me, arguments); - var afterFooter = callbacks.afterFooter.apply(me, arguments); - - var lines = []; - lines = pushOrConcat(lines, beforeFooter); - lines = pushOrConcat(lines, footer); - lines = pushOrConcat(lines, afterFooter); - - return lines; - }, - - update: function(changed) { - var me = this; - var opts = me._options; - - // Need to regenerate the model because its faster than using extend and it is necessary due to the optimization in Chart.Element.transition - // that does _view = _model if ease === 1. This causes the 2nd tooltip update to set properties in both the view and model at the same time - // which breaks any animations. - var existingModel = me._model; - var model = me._model = getBaseModel(opts); - var active = me._active; - - var data = me._data; - var chartInstance = me._chartInstance; - - // In the case where active.length === 0 we need to keep these at existing values for good animations - var alignment = { - xAlign: existingModel.xAlign, - yAlign: existingModel.yAlign - }; - var backgroundPoint = { - x: existingModel.x, - y: existingModel.y - }; - var tooltipSize = { - width: existingModel.width, - height: existingModel.height - }; - var tooltipPosition = { - x: existingModel.caretX, - y: existingModel.caretY - }; - - var i, len; - - if (active.length) { - model.opacity = 1; - - var labelColors = []; - tooltipPosition = Chart.Tooltip.positioners[opts.position](active, me._eventPosition); - - var tooltipItems = []; - for (i = 0, len = active.length; i < len; ++i) { - tooltipItems.push(createTooltipItem(active[i])); - } - - // If the user provided a filter function, use it to modify the tooltip items - if (opts.filter) { - tooltipItems = tooltipItems.filter(function(a) { - return opts.filter(a, data); - }); - } - - // If the user provided a sorting function, use it to modify the tooltip items - if (opts.itemSort) { - tooltipItems = tooltipItems.sort(function(a, b) { - return opts.itemSort(a, b, data); - }); - } - - // Determine colors for boxes - helpers.each(tooltipItems, function(tooltipItem) { - labelColors.push(opts.callbacks.labelColor.call(me, tooltipItem, chartInstance)); - }); - - // Build the Text Lines - model.title = me.getTitle(tooltipItems, data); - model.beforeBody = me.getBeforeBody(tooltipItems, data); - model.body = me.getBody(tooltipItems, data); - model.afterBody = me.getAfterBody(tooltipItems, data); - model.footer = me.getFooter(tooltipItems, data); - - // Initial positioning and colors - model.x = Math.round(tooltipPosition.x); - model.y = Math.round(tooltipPosition.y); - model.caretPadding = helpers.getValueOrDefault(tooltipPosition.padding, 2); - model.labelColors = labelColors; - - // data points - model.dataPoints = tooltipItems; - - // We need to determine alignment of the tooltip - tooltipSize = getTooltipSize(this, model); - alignment = determineAlignment(this, tooltipSize); - // Final Size and Position - backgroundPoint = getBackgroundPoint(model, tooltipSize, alignment); - } else { - model.opacity = 0; - } - - model.xAlign = alignment.xAlign; - model.yAlign = alignment.yAlign; - model.x = backgroundPoint.x; - model.y = backgroundPoint.y; - model.width = tooltipSize.width; - model.height = tooltipSize.height; - - // Point where the caret on the tooltip points to - model.caretX = tooltipPosition.x; - model.caretY = tooltipPosition.y; - - me._model = model; - - if (changed && opts.custom) { - opts.custom.call(me, model); - } - - return me; - }, - drawCaret: function(tooltipPoint, size, opacity) { - var vm = this._view; - var ctx = this._chart.ctx; - var x1, x2, x3; - var y1, y2, y3; - var caretSize = vm.caretSize; - var cornerRadius = vm.cornerRadius; - var xAlign = vm.xAlign, - yAlign = vm.yAlign; - var ptX = tooltipPoint.x, - ptY = tooltipPoint.y; - var width = size.width, - height = size.height; - - if (yAlign === 'center') { - // Left or right side - if (xAlign === 'left') { - x1 = ptX; - x2 = x1 - caretSize; - x3 = x1; - } else { - x1 = ptX + width; - x2 = x1 + caretSize; - x3 = x1; - } - - y2 = ptY + (height / 2); - y1 = y2 - caretSize; - y3 = y2 + caretSize; - } else { - if (xAlign === 'left') { - x1 = ptX + cornerRadius; - x2 = x1 + caretSize; - x3 = x2 + caretSize; - } else if (xAlign === 'right') { - x1 = ptX + width - cornerRadius; - x2 = x1 - caretSize; - x3 = x2 - caretSize; - } else { - x2 = ptX + (width / 2); - x1 = x2 - caretSize; - x3 = x2 + caretSize; - } - - if (yAlign === 'top') { - y1 = ptY; - y2 = y1 - caretSize; - y3 = y1; - } else { - y1 = ptY + height; - y2 = y1 + caretSize; - y3 = y1; - } - } - - ctx.fillStyle = mergeOpacity(vm.backgroundColor, opacity); - ctx.beginPath(); - ctx.moveTo(x1, y1); - ctx.lineTo(x2, y2); - ctx.lineTo(x3, y3); - ctx.closePath(); - ctx.fill(); - }, - drawTitle: function(pt, vm, ctx, opacity) { - var title = vm.title; - - if (title.length) { - ctx.textAlign = vm._titleAlign; - ctx.textBaseline = 'top'; - - var titleFontSize = vm.titleFontSize, - titleSpacing = vm.titleSpacing; - - ctx.fillStyle = mergeOpacity(vm.titleFontColor, opacity); - ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily); - - var i, len; - for (i = 0, len = title.length; i < len; ++i) { - ctx.fillText(title[i], pt.x, pt.y); - pt.y += titleFontSize + titleSpacing; // Line Height and spacing - - if (i + 1 === title.length) { - pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing - } - } - } - }, - drawBody: function(pt, vm, ctx, opacity) { - var bodyFontSize = vm.bodyFontSize; - var bodySpacing = vm.bodySpacing; - var body = vm.body; - - ctx.textAlign = vm._bodyAlign; - ctx.textBaseline = 'top'; - - var textColor = mergeOpacity(vm.bodyFontColor, opacity); - ctx.fillStyle = textColor; - ctx.font = helpers.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily); - - // Before Body - var xLinePadding = 0; - var fillLineOfText = function(line) { - ctx.fillText(line, pt.x + xLinePadding, pt.y); - pt.y += bodyFontSize + bodySpacing; - }; - - // Before body lines - helpers.each(vm.beforeBody, fillLineOfText); - - var drawColorBoxes = vm.displayColors; - xLinePadding = drawColorBoxes ? (bodyFontSize + 2) : 0; - - // Draw body lines now - helpers.each(body, function(bodyItem, i) { - helpers.each(bodyItem.before, fillLineOfText); - - helpers.each(bodyItem.lines, function(line) { - // Draw Legend-like boxes if needed - if (drawColorBoxes) { - // Fill a white rect so that colours merge nicely if the opacity is < 1 - ctx.fillStyle = mergeOpacity(vm.legendColorBackground, opacity); - ctx.fillRect(pt.x, pt.y, bodyFontSize, bodyFontSize); - - // Border - ctx.strokeStyle = mergeOpacity(vm.labelColors[i].borderColor, opacity); - ctx.strokeRect(pt.x, pt.y, bodyFontSize, bodyFontSize); - - // Inner square - ctx.fillStyle = mergeOpacity(vm.labelColors[i].backgroundColor, opacity); - ctx.fillRect(pt.x + 1, pt.y + 1, bodyFontSize - 2, bodyFontSize - 2); - - ctx.fillStyle = textColor; - } - - fillLineOfText(line); - }); - - helpers.each(bodyItem.after, fillLineOfText); - }); - - // Reset back to 0 for after body - xLinePadding = 0; - - // After body lines - helpers.each(vm.afterBody, fillLineOfText); - pt.y -= bodySpacing; // Remove last body spacing - }, - drawFooter: function(pt, vm, ctx, opacity) { - var footer = vm.footer; - - if (footer.length) { - pt.y += vm.footerMarginTop; - - ctx.textAlign = vm._footerAlign; - ctx.textBaseline = 'top'; - - ctx.fillStyle = mergeOpacity(vm.footerFontColor, opacity); - ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily); - - helpers.each(footer, function(line) { - ctx.fillText(line, pt.x, pt.y); - pt.y += vm.footerFontSize + vm.footerSpacing; - }); - } - }, - drawBackground: function(pt, vm, ctx, tooltipSize, opacity) { - ctx.fillStyle = mergeOpacity(vm.backgroundColor, opacity); - helpers.drawRoundedRectangle(ctx, pt.x, pt.y, tooltipSize.width, tooltipSize.height, vm.cornerRadius); - ctx.fill(); - }, - draw: function() { - var ctx = this._chart.ctx; - var vm = this._view; - - if (vm.opacity === 0) { - return; - } - - var tooltipSize = { - width: vm.width, - height: vm.height - }; - var pt = { - x: vm.x, - y: vm.y - }; - - // IE11/Edge does not like very small opacities, so snap to 0 - var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity; - - if (this._options.enabled) { - // Draw Background - this.drawBackground(pt, vm, ctx, tooltipSize, opacity); - - // Draw Caret - this.drawCaret(pt, tooltipSize, opacity); - - // Draw Title, Body, and Footer - pt.x += vm.xPadding; - pt.y += vm.yPadding; - - // Titles - this.drawTitle(pt, vm, ctx, opacity); - - // Body - this.drawBody(pt, vm, ctx, opacity); - - // Footer - this.drawFooter(pt, vm, ctx, opacity); - } - }, - - /** - * Handle an event - * @private - * @param {IEvent} event - The event to handle - * @returns {Boolean} true if the tooltip changed - */ - handleEvent: function(e) { - var me = this; - var options = me._options; - var changed = false; - - me._lastActive = me._lastActive || []; - - // Find Active Elements for tooltips - if (e.type === 'mouseout') { - me._active = []; - } else { - me._active = me._chartInstance.getElementsAtEventForMode(e, options.mode, options); - } - - // Remember Last Actives - changed = !helpers.arrayEquals(me._active, me._lastActive); - me._lastActive = me._active; - - if (options.enabled || options.custom) { - me._eventPosition = { - x: e.x, - y: e.y - }; - - var model = me._model; - me.update(true); - me.pivot(); - - // See if our tooltip position changed - changed |= (model.x !== me._model.x) || (model.y !== me._model.y); - } - - return changed; - } - }); - - /** - * @namespace Chart.Tooltip.positioners - */ - Chart.Tooltip.positioners = { - /** - * Average mode places the tooltip at the average position of the elements shown - * @function Chart.Tooltip.positioners.average - * @param elements {ChartElement[]} the elements being displayed in the tooltip - * @returns {Point} tooltip position - */ - average: function(elements) { - if (!elements.length) { - return false; - } - - var i, len; - var x = 0; - var y = 0; - var count = 0; - - for (i = 0, len = elements.length; i < len; ++i) { - var el = elements[i]; - if (el && el.hasValue()) { - var pos = el.tooltipPosition(); - x += pos.x; - y += pos.y; - ++count; - } - } - - return { - x: Math.round(x / count), - y: Math.round(y / count) - }; - }, - - /** - * Gets the tooltip position nearest of the item nearest to the event position - * @function Chart.Tooltip.positioners.nearest - * @param elements {Chart.Element[]} the tooltip elements - * @param eventPosition {Point} the position of the event in canvas coordinates - * @returns {Point} the tooltip position - */ - nearest: function(elements, eventPosition) { - var x = eventPosition.x; - var y = eventPosition.y; - - var nearestElement; - var minDistance = Number.POSITIVE_INFINITY; - var i, len; - for (i = 0, len = elements.length; i < len; ++i) { - var el = elements[i]; - if (el && el.hasValue()) { - var center = el.getCenterPoint(); - var d = helpers.distanceBetweenPoints(eventPosition, center); - - if (d < minDistance) { - minDistance = d; - nearestElement = el; - } - } - } - - if (nearestElement) { - var tp = nearestElement.tooltipPosition(); - x = tp.x; - y = tp.y; - } - - return { - x: x, - y: y - }; - } - }; - }; - -},{}],37:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers, - globalOpts = Chart.defaults.global; - - globalOpts.elements.arc = { - backgroundColor: globalOpts.defaultColor, - borderColor: '#fff', - borderWidth: 2 - }; - - Chart.elements.Arc = Chart.Element.extend({ - inLabelRange: function(mouseX) { - var vm = this._view; - - if (vm) { - return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2)); - } - return false; - }, - inRange: function(chartX, chartY) { - var vm = this._view; - - if (vm) { - var pointRelativePosition = helpers.getAngleFromPoint(vm, { - x: chartX, - y: chartY - }), - angle = pointRelativePosition.angle, - distance = pointRelativePosition.distance; - - // Sanitise angle range - var startAngle = vm.startAngle; - var endAngle = vm.endAngle; - while (endAngle < startAngle) { - endAngle += 2.0 * Math.PI; - } - while (angle > endAngle) { - angle -= 2.0 * Math.PI; - } - while (angle < startAngle) { - angle += 2.0 * Math.PI; - } - - // Check if within the range of the open/close angle - var betweenAngles = (angle >= startAngle && angle <= endAngle), - withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius); - - return (betweenAngles && withinRadius); - } - return false; - }, - getCenterPoint: function() { - var vm = this._view; - var halfAngle = (vm.startAngle + vm.endAngle) / 2; - var halfRadius = (vm.innerRadius + vm.outerRadius) / 2; - return { - x: vm.x + Math.cos(halfAngle) * halfRadius, - y: vm.y + Math.sin(halfAngle) * halfRadius - }; - }, - getArea: function() { - var vm = this._view; - return Math.PI * ((vm.endAngle - vm.startAngle) / (2 * Math.PI)) * (Math.pow(vm.outerRadius, 2) - Math.pow(vm.innerRadius, 2)); - }, - tooltipPosition: function() { - var vm = this._view; - - var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2), - rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius; - return { - x: vm.x + (Math.cos(centreAngle) * rangeFromCentre), - y: vm.y + (Math.sin(centreAngle) * rangeFromCentre) - }; - }, - draw: function() { - - var ctx = this._chart.ctx, - vm = this._view, - sA = vm.startAngle, - eA = vm.endAngle; - - ctx.beginPath(); - - ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA); - ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true); - - ctx.closePath(); - ctx.strokeStyle = vm.borderColor; - ctx.lineWidth = vm.borderWidth; - - ctx.fillStyle = vm.backgroundColor; - - ctx.fill(); - ctx.lineJoin = 'bevel'; - - if (vm.borderWidth) { - ctx.stroke(); - } - } - }); - }; - -},{}],38:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - var globalDefaults = Chart.defaults.global; - - Chart.defaults.global.elements.line = { - tension: 0.4, - backgroundColor: globalDefaults.defaultColor, - borderWidth: 3, - borderColor: globalDefaults.defaultColor, - borderCapStyle: 'butt', - borderDash: [], - borderDashOffset: 0.0, - borderJoinStyle: 'miter', - capBezierPoints: true, - fill: true, // do we fill in the area between the line and its base axis - }; - - Chart.elements.Line = Chart.Element.extend({ - draw: function() { - var me = this; - var vm = me._view; - var spanGaps = vm.spanGaps; - var fillPoint = vm.scaleZero; - var loop = me._loop; - - // Handle different fill modes for cartesian lines - if (!loop) { - if (vm.fill === 'top') { - fillPoint = vm.scaleTop; - } else if (vm.fill === 'bottom') { - fillPoint = vm.scaleBottom; - } - } - - var ctx = me._chart.ctx; - ctx.save(); - - // Helper function to draw a line to a point - function lineToPoint(previousPoint, point) { - var pointVM = point._view; - if (point._view.steppedLine === true) { - ctx.lineTo(pointVM.x, previousPoint._view.y); - ctx.lineTo(pointVM.x, pointVM.y); - } else if (point._view.tension === 0) { - ctx.lineTo(pointVM.x, pointVM.y); - } else { - ctx.bezierCurveTo( - previousPoint._view.controlPointNextX, - previousPoint._view.controlPointNextY, - pointVM.controlPointPreviousX, - pointVM.controlPointPreviousY, - pointVM.x, - pointVM.y - ); - } - } - - var points = me._children.slice(); // clone array - var lastDrawnIndex = -1; - - // If we are looping, adding the first point again - if (loop && points.length) { - points.push(points[0]); - } - - var index, current, previous, currentVM; - - // Fill Line - if (points.length && vm.fill) { - ctx.beginPath(); - - for (index = 0; index < points.length; ++index) { - current = points[index]; - previous = helpers.previousItem(points, index); - currentVM = current._view; - - // First point moves to it's starting position no matter what - if (index === 0) { - if (loop) { - ctx.moveTo(fillPoint.x, fillPoint.y); - } else { - ctx.moveTo(currentVM.x, fillPoint); - } - - if (!currentVM.skip) { - lastDrawnIndex = index; - ctx.lineTo(currentVM.x, currentVM.y); - } - } else { - previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex]; - - if (currentVM.skip) { - // Only do this if this is the first point that is skipped - if (!spanGaps && lastDrawnIndex === (index - 1)) { - if (loop) { - ctx.lineTo(fillPoint.x, fillPoint.y); - } else { - ctx.lineTo(previous._view.x, fillPoint); - } - } - } else { - if (lastDrawnIndex !== (index - 1)) { - // There was a gap and this is the first point after the gap. If we've never drawn a point, this is a special case. - // If the first data point is NaN, then there is no real gap to skip - if (spanGaps && lastDrawnIndex !== -1) { - // We are spanning the gap, so simple draw a line to this point - lineToPoint(previous, current); - } else if (loop) { - ctx.lineTo(currentVM.x, currentVM.y); - } else { - ctx.lineTo(currentVM.x, fillPoint); - ctx.lineTo(currentVM.x, currentVM.y); - } - } else { - // Line to next point - lineToPoint(previous, current); - } - lastDrawnIndex = index; - } - } - } - - if (!loop && lastDrawnIndex !== -1) { - ctx.lineTo(points[lastDrawnIndex]._view.x, fillPoint); - } - - ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor; - ctx.closePath(); - ctx.fill(); - } - - // Stroke Line Options - var globalOptionLineElements = globalDefaults.elements.line; - ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle; - - // IE 9 and 10 do not support line dash - if (ctx.setLineDash) { - ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash); - } - - ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset; - ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle; - ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth; - ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor; - - // Stroke Line - ctx.beginPath(); - lastDrawnIndex = -1; - - for (index = 0; index < points.length; ++index) { - current = points[index]; - previous = helpers.previousItem(points, index); - currentVM = current._view; - - // First point moves to it's starting position no matter what - if (index === 0) { - if (!currentVM.skip) { - ctx.moveTo(currentVM.x, currentVM.y); - lastDrawnIndex = index; - } - } else { - previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex]; - - if (!currentVM.skip) { - if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) { - // There was a gap and this is the first point after the gap - ctx.moveTo(currentVM.x, currentVM.y); - } else { - // Line to next point - lineToPoint(previous, current); - } - lastDrawnIndex = index; - } - } - } - - ctx.stroke(); - ctx.restore(); - } - }); - }; - -},{}],39:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers, - globalOpts = Chart.defaults.global, - defaultColor = globalOpts.defaultColor; - - globalOpts.elements.point = { - radius: 3, - pointStyle: 'circle', - backgroundColor: defaultColor, - borderWidth: 1, - borderColor: defaultColor, - // Hover - hitRadius: 1, - hoverRadius: 4, - hoverBorderWidth: 1 - }; - - function xRange(mouseX) { - var vm = this._view; - return vm ? (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false; - } - - function yRange(mouseY) { - var vm = this._view; - return vm ? (Math.pow(mouseY - vm.y, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false; - } - - Chart.elements.Point = Chart.Element.extend({ - inRange: function(mouseX, mouseY) { - var vm = this._view; - return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false; - }, - - inLabelRange: xRange, - inXRange: xRange, - inYRange: yRange, - - getCenterPoint: function() { - var vm = this._view; - return { - x: vm.x, - y: vm.y - }; - }, - getArea: function() { - return Math.PI * Math.pow(this._view.radius, 2); - }, - tooltipPosition: function() { - var vm = this._view; - return { - x: vm.x, - y: vm.y, - padding: vm.radius + vm.borderWidth - }; - }, - draw: function(chartArea) { - var vm = this._view; - var model = this._model; - var ctx = this._chart.ctx; - var pointStyle = vm.pointStyle; - var radius = vm.radius; - var x = vm.x; - var y = vm.y; - var color = Chart.helpers.color; - var errMargin = 1.01; // 1.01 is margin for Accumulated error. (Especially Edge, IE.) - var ratio = 0; - - if (vm.skip) { - return; - } - - ctx.strokeStyle = vm.borderColor || defaultColor; - ctx.lineWidth = helpers.getValueOrDefault(vm.borderWidth, globalOpts.elements.point.borderWidth); - ctx.fillStyle = vm.backgroundColor || defaultColor; - - // Cliping for Points. - // going out from inner charArea? - if ((chartArea !== undefined) && ((model.x < chartArea.left) || (chartArea.right*errMargin < model.x) || (model.y < chartArea.top) || (chartArea.bottom*errMargin < model.y))) { - // Point fade out - if (model.x < chartArea.left) { - ratio = (x - model.x) / (chartArea.left - model.x); - } else if (chartArea.right*errMargin < model.x) { - ratio = (model.x - x) / (model.x - chartArea.right); - } else if (model.y < chartArea.top) { - ratio = (y - model.y) / (chartArea.top - model.y); - } else if (chartArea.bottom*errMargin < model.y) { - ratio = (model.y - y) / (model.y - chartArea.bottom); - } - ratio = Math.round(ratio*100) / 100; - ctx.strokeStyle = color(ctx.strokeStyle).alpha(ratio).rgbString(); - ctx.fillStyle = color(ctx.fillStyle).alpha(ratio).rgbString(); - } - - Chart.canvasHelpers.drawPoint(ctx, pointStyle, radius, x, y); - } - }); - }; - -},{}],40:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var globalOpts = Chart.defaults.global; - - globalOpts.elements.rectangle = { - backgroundColor: globalOpts.defaultColor, - borderWidth: 0, - borderColor: globalOpts.defaultColor, - borderSkipped: 'bottom' - }; - - function isVertical(bar) { - return bar._view.width !== undefined; - } - - /** - * Helper function to get the bounds of the bar regardless of the orientation - * @private - * @param bar {Chart.Element.Rectangle} the bar - * @return {Bounds} bounds of the bar - */ - function getBarBounds(bar) { - var vm = bar._view; - var x1, x2, y1, y2; - - if (isVertical(bar)) { - // vertical - var halfWidth = vm.width / 2; - x1 = vm.x - halfWidth; - x2 = vm.x + halfWidth; - y1 = Math.min(vm.y, vm.base); - y2 = Math.max(vm.y, vm.base); - } else { - // horizontal bar - var halfHeight = vm.height / 2; - x1 = Math.min(vm.x, vm.base); - x2 = Math.max(vm.x, vm.base); - y1 = vm.y - halfHeight; - y2 = vm.y + halfHeight; - } - - return { - left: x1, - top: y1, - right: x2, - bottom: y2 - }; - } - - Chart.elements.Rectangle = Chart.Element.extend({ - draw: function() { - var ctx = this._chart.ctx; - var vm = this._view; - var left, right, top, bottom, signX, signY, borderSkipped; - var borderWidth = vm.borderWidth; - - if (!vm.horizontal) { - // bar - left = vm.x - vm.width / 2; - right = vm.x + vm.width / 2; - top = vm.y; - bottom = vm.base; - signX = 1; - signY = bottom > top? 1: -1; - borderSkipped = vm.borderSkipped || 'bottom'; - } else { - // horizontal bar - left = vm.base; - right = vm.x; - top = vm.y - vm.height / 2; - bottom = vm.y + vm.height / 2; - signX = right > left? 1: -1; - signY = 1; - borderSkipped = vm.borderSkipped || 'left'; - } - - // Canvas doesn't allow us to stroke inside the width so we can - // adjust the sizes to fit if we're setting a stroke on the line - if (borderWidth) { - // borderWidth shold be less than bar width and bar height. - var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom)); - borderWidth = borderWidth > barSize? barSize: borderWidth; - var halfStroke = borderWidth / 2; - // Adjust borderWidth when bar top position is near vm.base(zero). - var borderLeft = left + (borderSkipped !== 'left'? halfStroke * signX: 0); - var borderRight = right + (borderSkipped !== 'right'? -halfStroke * signX: 0); - var borderTop = top + (borderSkipped !== 'top'? halfStroke * signY: 0); - var borderBottom = bottom + (borderSkipped !== 'bottom'? -halfStroke * signY: 0); - // not become a vertical line? - if (borderLeft !== borderRight) { - top = borderTop; - bottom = borderBottom; - } - // not become a horizontal line? - if (borderTop !== borderBottom) { - left = borderLeft; - right = borderRight; - } - } - - ctx.beginPath(); - ctx.fillStyle = vm.backgroundColor; - ctx.strokeStyle = vm.borderColor; - ctx.lineWidth = borderWidth; - - // Corner points, from bottom-left to bottom-right clockwise - // | 1 2 | - // | 0 3 | - var corners = [ - [left, bottom], - [left, top], - [right, top], - [right, bottom] - ]; - - // Find first (starting) corner with fallback to 'bottom' - var borders = ['bottom', 'left', 'top', 'right']; - var startCorner = borders.indexOf(borderSkipped, 0); - if (startCorner === -1) { - startCorner = 0; - } - - function cornerAt(index) { - return corners[(startCorner + index) % 4]; - } - - // Draw rectangle from 'startCorner' - var corner = cornerAt(0); - ctx.moveTo(corner[0], corner[1]); - - for (var i = 1; i < 4; i++) { - corner = cornerAt(i); - ctx.lineTo(corner[0], corner[1]); - } - - ctx.fill(); - if (borderWidth) { - ctx.stroke(); - } - }, - height: function() { - var vm = this._view; - return vm.base - vm.y; - }, - inRange: function(mouseX, mouseY) { - var inRange = false; - - if (this._view) { - var bounds = getBarBounds(this); - inRange = mouseX >= bounds.left && mouseX <= bounds.right && mouseY >= bounds.top && mouseY <= bounds.bottom; - } - - return inRange; - }, - inLabelRange: function(mouseX, mouseY) { - var me = this; - if (!me._view) { - return false; - } - - var inRange = false; - var bounds = getBarBounds(me); - - if (isVertical(me)) { - inRange = mouseX >= bounds.left && mouseX <= bounds.right; - } else { - inRange = mouseY >= bounds.top && mouseY <= bounds.bottom; - } - - return inRange; - }, - inXRange: function(mouseX) { - var bounds = getBarBounds(this); - return mouseX >= bounds.left && mouseX <= bounds.right; - }, - inYRange: function(mouseY) { - var bounds = getBarBounds(this); - return mouseY >= bounds.top && mouseY <= bounds.bottom; - }, - getCenterPoint: function() { - var vm = this._view; - var x, y; - if (isVertical(this)) { - x = vm.x; - y = (vm.y + vm.base) / 2; - } else { - x = (vm.x + vm.base) / 2; - y = vm.y; - } - - return {x: x, y: y}; - }, - getArea: function() { - var vm = this._view; - return vm.width * Math.abs(vm.y - vm.base); - }, - tooltipPosition: function() { - var vm = this._view; - return { - x: vm.x, - y: vm.y - }; - } - }); - - }; - -},{}],41:[function(require,module,exports){ - 'use strict'; - -// Chart.Platform implementation for targeting a web browser - module.exports = function(Chart) { - var helpers = Chart.helpers; - - // DOM event types -> Chart.js event types. - // Note: only events with different types are mapped. - // https://developer.mozilla.org/en-US/docs/Web/Events - var eventTypeMap = { - // Touch events - touchstart: 'mousedown', - touchmove: 'mousemove', - touchend: 'mouseup', - - // Pointer events - pointerenter: 'mouseenter', - pointerdown: 'mousedown', - pointermove: 'mousemove', - pointerup: 'mouseup', - pointerleave: 'mouseout', - pointerout: 'mouseout' - }; - - /** - * The "used" size is the final value of a dimension property after all calculations have - * been performed. This method uses the computed style of `element` but returns undefined - * if the computed style is not expressed in pixels. That can happen in some cases where - * `element` has a size relative to its parent and this last one is not yet displayed, - * for example because of `display: none` on a parent node. - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value - * @returns {Number} Size in pixels or undefined if unknown. - */ - function readUsedSize(element, property) { - var value = helpers.getStyle(element, property); - var matches = value && value.match(/(\d+)px/); - return matches? Number(matches[1]) : undefined; - } - - /** - * Initializes the canvas style and render size without modifying the canvas display size, - * since responsiveness is handled by the controller.resize() method. The config is used - * to determine the aspect ratio to apply in case no explicit height has been specified. - */ - function initCanvas(canvas, config) { - var style = canvas.style; - - // NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it - // returns null or '' if no explicit value has been set to the canvas attribute. - var renderHeight = canvas.getAttribute('height'); - var renderWidth = canvas.getAttribute('width'); - - // Chart.js modifies some canvas values that we want to restore on destroy - canvas._chartjs = { - initial: { - height: renderHeight, - width: renderWidth, - style: { - display: style.display, - height: style.height, - width: style.width - } - } - }; - - // Force canvas to display as block to avoid extra space caused by inline - // elements, which would interfere with the responsive resize process. - // https://github.com/chartjs/Chart.js/issues/2538 - style.display = style.display || 'block'; - - if (renderWidth === null || renderWidth === '') { - var displayWidth = readUsedSize(canvas, 'width'); - if (displayWidth !== undefined) { - canvas.width = displayWidth; - } - } - - if (renderHeight === null || renderHeight === '') { - if (canvas.style.height === '') { - // If no explicit render height and style height, let's apply the aspect ratio, - // which one can be specified by the user but also by charts as default option - // (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2. - canvas.height = canvas.width / (config.options.aspectRatio || 2); - } else { - var displayHeight = readUsedSize(canvas, 'height'); - if (displayWidth !== undefined) { - canvas.height = displayHeight; - } - } - } - - return canvas; - } - - function createEvent(type, chart, x, y, native) { - return { - type: type, - chart: chart, - native: native || null, - x: x !== undefined? x : null, - y: y !== undefined? y : null, - }; - } - - function fromNativeEvent(event, chart) { - var type = eventTypeMap[event.type] || event.type; - var pos = helpers.getRelativePosition(event, chart); - return createEvent(type, chart, pos.x, pos.y, event); - } - - function createResizer(handler) { - var iframe = document.createElement('iframe'); - iframe.className = 'chartjs-hidden-iframe'; - iframe.style.cssText = - 'display:block;'+ - 'overflow:hidden;'+ - 'border:0;'+ - 'margin:0;'+ - 'top:0;'+ - 'left:0;'+ - 'bottom:0;'+ - 'right:0;'+ - 'height:100%;'+ - 'width:100%;'+ - 'position:absolute;'+ - 'pointer-events:none;'+ - 'z-index:-1;'; - - // Prevent the iframe to gain focus on tab. - // https://github.com/chartjs/Chart.js/issues/3090 - iframe.tabIndex = -1; - - // If the iframe is re-attached to the DOM, the resize listener is removed because the - // content is reloaded, so make sure to install the handler after the iframe is loaded. - // https://github.com/chartjs/Chart.js/issues/3521 - helpers.addEvent(iframe, 'load', function() { - helpers.addEvent(iframe.contentWindow || iframe, 'resize', handler); - - // The iframe size might have changed while loading, which can also - // happen if the size has been changed while detached from the DOM. - handler(); - }); - - return iframe; - } - - function addResizeListener(node, listener, chart) { - var stub = node._chartjs = { - ticking: false - }; - - // Throttle the callback notification until the next animation frame. - var notify = function() { - if (!stub.ticking) { - stub.ticking = true; - helpers.requestAnimFrame.call(window, function() { - if (stub.resizer) { - stub.ticking = false; - return listener(createEvent('resize', chart)); - } - }); - } - }; - - // Let's keep track of this added iframe and thus avoid DOM query when removing it. - stub.resizer = createResizer(notify); - - node.insertBefore(stub.resizer, node.firstChild); - } - - function removeResizeListener(node) { - if (!node || !node._chartjs) { - return; - } - - var resizer = node._chartjs.resizer; - if (resizer) { - resizer.parentNode.removeChild(resizer); - node._chartjs.resizer = null; - } - - delete node._chartjs; - } - - return { - acquireContext: function(item, config) { - if (typeof item === 'string') { - item = document.getElementById(item); - } else if (item.length) { - // Support for array based queries (such as jQuery) - item = item[0]; - } - - if (item && item.canvas) { - // Support for any object associated to a canvas (including a context2d) - item = item.canvas; - } - - if (item instanceof HTMLCanvasElement) { - // To prevent canvas fingerprinting, some add-ons undefine the getContext - // method, for example: https://github.com/kkapsner/CanvasBlocker - // https://github.com/chartjs/Chart.js/issues/2807 - var context = item.getContext && item.getContext('2d'); - if (context instanceof CanvasRenderingContext2D) { - initCanvas(item, config); - return context; - } - } - - return null; - }, - - releaseContext: function(context) { - var canvas = context.canvas; - if (!canvas._chartjs) { - return; - } - - var initial = canvas._chartjs.initial; - ['height', 'width'].forEach(function(prop) { - var value = initial[prop]; - if (value === undefined || value === null) { - canvas.removeAttribute(prop); - } else { - canvas.setAttribute(prop, value); - } - }); - - helpers.each(initial.style || {}, function(value, key) { - canvas.style[key] = value; - }); - - // The canvas render size might have been changed (and thus the state stack discarded), - // we can't use save() and restore() to restore the initial state. So make sure that at - // least the canvas context is reset to the default state by setting the canvas width. - // https://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html - canvas.width = canvas.width; - - delete canvas._chartjs; - }, - - addEventListener: function(chart, type, listener) { - var canvas = chart.chart.canvas; - if (type === 'resize') { - // Note: the resize event is not supported on all browsers. - addResizeListener(canvas.parentNode, listener, chart.chart); - return; - } - - var stub = listener._chartjs || (listener._chartjs = {}); - var proxies = stub.proxies || (stub.proxies = {}); - var proxy = proxies[chart.id + '_' + type] = function(event) { - listener(fromNativeEvent(event, chart.chart)); - }; - - helpers.addEvent(canvas, type, proxy); - }, - - removeEventListener: function(chart, type, listener) { - var canvas = chart.chart.canvas; - if (type === 'resize') { - // Note: the resize event is not supported on all browsers. - removeResizeListener(canvas.parentNode, listener); - return; - } - - var stub = listener._chartjs || {}; - var proxies = stub.proxies || {}; - var proxy = proxies[chart.id + '_' + type]; - if (!proxy) { - return; - } - - helpers.removeEvent(canvas, type, proxy); - } - }; - }; - -},{}],42:[function(require,module,exports){ - 'use strict'; - -// By default, select the browser (DOM) platform. -// @TODO Make possible to select another platform at build time. - var implementation = require(41); - - module.exports = function(Chart) { - /** - * @namespace Chart.platform - * @see https://chartjs.gitbooks.io/proposals/content/Platform.html - * @since 2.4.0 - */ - Chart.platform = { - /** - * Called at chart construction time, returns a context2d instance implementing - * the [W3C Canvas 2D Context API standard]{@link https://www.w3.org/TR/2dcontext/}. - * @param {*} item - The native item from which to acquire context (platform specific) - * @param {Object} options - The chart options - * @returns {CanvasRenderingContext2D} context2d instance - */ - acquireContext: function() {}, - - /** - * Called at chart destruction time, releases any resources associated to the context - * previously returned by the acquireContext() method. - * @param {CanvasRenderingContext2D} context - The context2d instance - * @returns {Boolean} true if the method succeeded, else false - */ - releaseContext: function() {}, - - /** - * Registers the specified listener on the given chart. - * @param {Chart} chart - Chart from which to listen for event - * @param {String} type - The ({@link IEvent}) type to listen for - * @param {Function} listener - Receives a notification (an object that implements - * the {@link IEvent} interface) when an event of the specified type occurs. - */ - addEventListener: function() {}, - - /** - * Removes the specified listener previously registered with addEventListener. - * @param {Chart} chart -Chart from which to remove the listener - * @param {String} type - The ({@link IEvent}) type to remove - * @param {Function} listener - The listener function to remove from the event target. - */ - removeEventListener: function() {} - }; - - /** - * @interface IPlatform - * Allows abstracting platform dependencies away from the chart - * @borrows Chart.platform.acquireContext as acquireContext - * @borrows Chart.platform.releaseContext as releaseContext - * @borrows Chart.platform.addEventListener as addEventListener - * @borrows Chart.platform.removeEventListener as removeEventListener - */ - - /** - * @interface IEvent - * @prop {String} type - The event type name, possible values are: - * 'contextmenu', 'mouseenter', 'mousedown', 'mousemove', 'mouseup', 'mouseout', - * 'click', 'dblclick', 'keydown', 'keypress', 'keyup' and 'resize' - * @prop {*} native - The original native event (null for emulated events, e.g. 'resize') - * @prop {Number} x - The mouse x position, relative to the canvas (null for incompatible events) - * @prop {Number} y - The mouse y position, relative to the canvas (null for incompatible events) - */ - - Chart.helpers.extend(Chart.platform, implementation(Chart)); - }; - -},{"41":41}],43:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - // Default config for a category scale - var defaultConfig = { - position: 'bottom' - }; - - var DatasetScale = Chart.Scale.extend({ - /** - * Internal function to get the correct labels. If data.xLabels or data.yLabels are defined, use those - * else fall back to data.labels - * @private - */ - getLabels: function() { - var data = this.chart.data; - return (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels; - }, - // Implement this so that - determineDataLimits: function() { - var me = this; - var labels = me.getLabels(); - me.minIndex = 0; - me.maxIndex = labels.length - 1; - var findIndex; - - if (me.options.ticks.min !== undefined) { - // user specified min value - findIndex = helpers.indexOf(labels, me.options.ticks.min); - me.minIndex = findIndex !== -1 ? findIndex : me.minIndex; - } - - if (me.options.ticks.max !== undefined) { - // user specified max value - findIndex = helpers.indexOf(labels, me.options.ticks.max); - me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex; - } - - me.min = labels[me.minIndex]; - me.max = labels[me.maxIndex]; - }, - - buildTicks: function() { - var me = this; - var labels = me.getLabels(); - // If we are viewing some subset of labels, slice the original array - me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1); - }, - - getLabelForIndex: function(index, datasetIndex) { - var me = this; - var data = me.chart.data; - var isHorizontal = me.isHorizontal(); - - if (data.yLabels && !isHorizontal) { - return me.getRightValue(data.datasets[datasetIndex].data[index]); - } - return me.ticks[index - me.minIndex]; - }, - - // Used to get data value locations. Value can either be an index or a numerical value - getPixelForValue: function(value, index, datasetIndex, includeOffset) { - var me = this; - // 1 is added because we need the length but we have the indexes - var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1); - - if (value !== undefined && isNaN(index)) { - var labels = me.getLabels(); - var idx = labels.indexOf(value); - index = idx !== -1 ? idx : index; - } - - if (me.isHorizontal()) { - var valueWidth = me.width / offsetAmt; - var widthOffset = (valueWidth * (index - me.minIndex)); - - if (me.options.gridLines.offsetGridLines && includeOffset || me.maxIndex === me.minIndex && includeOffset) { - widthOffset += (valueWidth / 2); - } - - return me.left + Math.round(widthOffset); - } - var valueHeight = me.height / offsetAmt; - var heightOffset = (valueHeight * (index - me.minIndex)); - - if (me.options.gridLines.offsetGridLines && includeOffset) { - heightOffset += (valueHeight / 2); - } - - return me.top + Math.round(heightOffset); - }, - getPixelForTick: function(index, includeOffset) { - return this.getPixelForValue(this.ticks[index], index + this.minIndex, null, includeOffset); - }, - getValueForPixel: function(pixel) { - var me = this; - var value; - var offsetAmt = Math.max((me.ticks.length - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1); - var horz = me.isHorizontal(); - var valueDimension = (horz ? me.width : me.height) / offsetAmt; - - pixel -= horz ? me.left : me.top; - - if (me.options.gridLines.offsetGridLines) { - pixel -= (valueDimension / 2); - } - - if (pixel <= 0) { - value = 0; - } else { - value = Math.round(pixel / valueDimension); - } - - return value; - }, - getBasePixel: function() { - return this.bottom; - } - }); - - Chart.scaleService.registerScaleType('category', DatasetScale, defaultConfig); - - }; - -},{}],44:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - var defaultConfig = { - position: 'left', - ticks: { - callback: Chart.Ticks.formatters.linear - } - }; - - var LinearScale = Chart.LinearScaleBase.extend({ - determineDataLimits: function() { - var me = this; - var opts = me.options; - var chart = me.chart; - var data = chart.data; - var datasets = data.datasets; - var isHorizontal = me.isHorizontal(); - - function IDMatches(meta) { - return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id; - } - - // First Calculate the range - me.min = null; - me.max = null; - - var hasStacks = opts.stacked; - if (hasStacks === undefined) { - helpers.each(datasets, function(dataset, datasetIndex) { - if (hasStacks) { - return; - } - - var meta = chart.getDatasetMeta(datasetIndex); - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && - meta.stack !== undefined) { - hasStacks = true; - } - }); - } - - if (opts.stacked || hasStacks) { - var valuesPerStack = {}; - - helpers.each(datasets, function(dataset, datasetIndex) { - var meta = chart.getDatasetMeta(datasetIndex); - var key = [ - meta.type, - // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined - ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''), - meta.stack - ].join('.'); - - if (valuesPerStack[key] === undefined) { - valuesPerStack[key] = { - positiveValues: [], - negativeValues: [] - }; - } - - // Store these per type - var positiveValues = valuesPerStack[key].positiveValues; - var negativeValues = valuesPerStack[key].negativeValues; - - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { - helpers.each(dataset.data, function(rawValue, index) { - var value = +me.getRightValue(rawValue); - if (isNaN(value) || meta.data[index].hidden) { - return; - } - - positiveValues[index] = positiveValues[index] || 0; - negativeValues[index] = negativeValues[index] || 0; - - if (opts.relativePoints) { - positiveValues[index] = 100; - } else if (value < 0) { - negativeValues[index] += value; - } else { - positiveValues[index] += value; - } - }); - } - }); - - helpers.each(valuesPerStack, function(valuesForType) { - var values = valuesForType.positiveValues.concat(valuesForType.negativeValues); - var minVal = helpers.min(values); - var maxVal = helpers.max(values); - me.min = me.min === null ? minVal : Math.min(me.min, minVal); - me.max = me.max === null ? maxVal : Math.max(me.max, maxVal); - }); - - } else { - helpers.each(datasets, function(dataset, datasetIndex) { - var meta = chart.getDatasetMeta(datasetIndex); - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { - helpers.each(dataset.data, function(rawValue, index) { - var value = +me.getRightValue(rawValue); - if (isNaN(value) || meta.data[index].hidden) { - return; - } - - if (me.min === null) { - me.min = value; - } else if (value < me.min) { - me.min = value; - } - - if (me.max === null) { - me.max = value; - } else if (value > me.max) { - me.max = value; - } - }); - } - }); - } - - // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero - this.handleTickRangeOptions(); - }, - getTickLimit: function() { - var maxTicks; - var me = this; - var tickOpts = me.options.ticks; - - if (me.isHorizontal()) { - maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.width / 50)); - } else { - // The factor of 2 used to scale the font size has been experimentally determined. - var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize); - maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.height / (2 * tickFontSize))); - } - - return maxTicks; - }, - // Called after the ticks are built. We need - handleDirectionalChanges: function() { - if (!this.isHorizontal()) { - // We are in a vertical orientation. The top value is the highest. So reverse the array - this.ticks.reverse(); - } - }, - getLabelForIndex: function(index, datasetIndex) { - return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); - }, - // Utils - getPixelForValue: function(value) { - // This must be called after fit has been run so that - // this.left, this.top, this.right, and this.bottom have been defined - var me = this; - var start = me.start; - - var rightValue = +me.getRightValue(value); - var pixel; - var range = me.end - start; - - if (me.isHorizontal()) { - pixel = me.left + (me.width / range * (rightValue - start)); - return Math.round(pixel); - } - - pixel = me.bottom - (me.height / range * (rightValue - start)); - return Math.round(pixel); - }, - getValueForPixel: function(pixel) { - var me = this; - var isHorizontal = me.isHorizontal(); - var innerDimension = isHorizontal ? me.width : me.height; - var offset = (isHorizontal ? pixel - me.left : me.bottom - pixel) / innerDimension; - return me.start + ((me.end - me.start) * offset); - }, - getPixelForTick: function(index) { - return this.getPixelForValue(this.ticksAsNumbers[index]); - } - }); - Chart.scaleService.registerScaleType('linear', LinearScale, defaultConfig); - - }; - -},{}],45:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers, - noop = helpers.noop; - - Chart.LinearScaleBase = Chart.Scale.extend({ - handleTickRangeOptions: function() { - var me = this; - var opts = me.options; - var tickOpts = opts.ticks; - - // If we are forcing it to begin at 0, but 0 will already be rendered on the chart, - // do nothing since that would make the chart weird. If the user really wants a weird chart - // axis, they can manually override it - if (tickOpts.beginAtZero) { - var minSign = helpers.sign(me.min); - var maxSign = helpers.sign(me.max); - - if (minSign < 0 && maxSign < 0) { - // move the top up to 0 - me.max = 0; - } else if (minSign > 0 && maxSign > 0) { - // move the bottom down to 0 - me.min = 0; - } - } - - if (tickOpts.min !== undefined) { - me.min = tickOpts.min; - } else if (tickOpts.suggestedMin !== undefined) { - me.min = Math.min(me.min, tickOpts.suggestedMin); - } - - if (tickOpts.max !== undefined) { - me.max = tickOpts.max; - } else if (tickOpts.suggestedMax !== undefined) { - me.max = Math.max(me.max, tickOpts.suggestedMax); - } - - if (me.min === me.max) { - me.max++; - - if (!tickOpts.beginAtZero) { - me.min--; - } - } - }, - getTickLimit: noop, - handleDirectionalChanges: noop, - - buildTicks: function() { - var me = this; - var opts = me.options; - var tickOpts = opts.ticks; - - // Figure out what the max number of ticks we can support it is based on the size of - // the axis area. For now, we say that the minimum tick spacing in pixels must be 50 - // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on - // the graph. Make sure we always have at least 2 ticks - var maxTicks = me.getTickLimit(); - maxTicks = Math.max(2, maxTicks); - - var numericGeneratorOptions = { - maxTicks: maxTicks, - min: tickOpts.min, - max: tickOpts.max, - stepSize: helpers.getValueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize) - }; - var ticks = me.ticks = Chart.Ticks.generators.linear(numericGeneratorOptions, me); - - me.handleDirectionalChanges(); - - // At this point, we need to update our max and min given the tick values since we have expanded the - // range of the scale - me.max = helpers.max(ticks); - me.min = helpers.min(ticks); - - if (tickOpts.reverse) { - ticks.reverse(); - - me.start = me.max; - me.end = me.min; - } else { - me.start = me.min; - me.end = me.max; - } - }, - convertTicksToLabels: function() { - var me = this; - me.ticksAsNumbers = me.ticks.slice(); - me.zeroLineIndex = me.ticks.indexOf(0); - - Chart.Scale.prototype.convertTicksToLabels.call(me); - } - }); - }; - -},{}],46:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - - var defaultConfig = { - position: 'left', - - // label settings - ticks: { - callback: Chart.Ticks.formatters.logarithmic - } - }; - - var LogarithmicScale = Chart.Scale.extend({ - determineDataLimits: function() { - var me = this; - var opts = me.options; - var tickOpts = opts.ticks; - var chart = me.chart; - var data = chart.data; - var datasets = data.datasets; - var getValueOrDefault = helpers.getValueOrDefault; - var isHorizontal = me.isHorizontal(); - function IDMatches(meta) { - return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id; - } - - // Calculate Range - me.min = null; - me.max = null; - me.minNotZero = null; - - var hasStacks = opts.stacked; - if (hasStacks === undefined) { - helpers.each(datasets, function(dataset, datasetIndex) { - if (hasStacks) { - return; - } - - var meta = chart.getDatasetMeta(datasetIndex); - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && - meta.stack !== undefined) { - hasStacks = true; - } - }); - } - - if (opts.stacked || hasStacks) { - var valuesPerStack = {}; - - helpers.each(datasets, function(dataset, datasetIndex) { - var meta = chart.getDatasetMeta(datasetIndex); - var key = [ - meta.type, - // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined - ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''), - meta.stack - ].join('.'); - - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { - if (valuesPerStack[key] === undefined) { - valuesPerStack[key] = []; - } - - helpers.each(dataset.data, function(rawValue, index) { - var values = valuesPerStack[key]; - var value = +me.getRightValue(rawValue); - if (isNaN(value) || meta.data[index].hidden) { - return; - } - - values[index] = values[index] || 0; - - if (opts.relativePoints) { - values[index] = 100; - } else { - // Don't need to split positive and negative since the log scale can't handle a 0 crossing - values[index] += value; - } - }); - } - }); - - helpers.each(valuesPerStack, function(valuesForType) { - var minVal = helpers.min(valuesForType); - var maxVal = helpers.max(valuesForType); - me.min = me.min === null ? minVal : Math.min(me.min, minVal); - me.max = me.max === null ? maxVal : Math.max(me.max, maxVal); - }); - - } else { - helpers.each(datasets, function(dataset, datasetIndex) { - var meta = chart.getDatasetMeta(datasetIndex); - if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { - helpers.each(dataset.data, function(rawValue, index) { - var value = +me.getRightValue(rawValue); - if (isNaN(value) || meta.data[index].hidden) { - return; - } - - if (me.min === null) { - me.min = value; - } else if (value < me.min) { - me.min = value; - } - - if (me.max === null) { - me.max = value; - } else if (value > me.max) { - me.max = value; - } - - if (value !== 0 && (me.minNotZero === null || value < me.minNotZero)) { - me.minNotZero = value; - } - }); - } - }); - } - - me.min = getValueOrDefault(tickOpts.min, me.min); - me.max = getValueOrDefault(tickOpts.max, me.max); - - if (me.min === me.max) { - if (me.min !== 0 && me.min !== null) { - me.min = Math.pow(10, Math.floor(helpers.log10(me.min)) - 1); - me.max = Math.pow(10, Math.floor(helpers.log10(me.max)) + 1); - } else { - me.min = 1; - me.max = 10; - } - } - }, - buildTicks: function() { - var me = this; - var opts = me.options; - var tickOpts = opts.ticks; - - var generationOptions = { - min: tickOpts.min, - max: tickOpts.max - }; - var ticks = me.ticks = Chart.Ticks.generators.logarithmic(generationOptions, me); - - if (!me.isHorizontal()) { - // We are in a vertical orientation. The top value is the highest. So reverse the array - ticks.reverse(); - } - - // At this point, we need to update our max and min given the tick values since we have expanded the - // range of the scale - me.max = helpers.max(ticks); - me.min = helpers.min(ticks); - - if (tickOpts.reverse) { - ticks.reverse(); - - me.start = me.max; - me.end = me.min; - } else { - me.start = me.min; - me.end = me.max; - } - }, - convertTicksToLabels: function() { - this.tickValues = this.ticks.slice(); - - Chart.Scale.prototype.convertTicksToLabels.call(this); - }, - // Get the correct tooltip label - getLabelForIndex: function(index, datasetIndex) { - return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); - }, - getPixelForTick: function(index) { - return this.getPixelForValue(this.tickValues[index]); - }, - getPixelForValue: function(value) { - var me = this; - var innerDimension; - var pixel; - - var start = me.start; - var newVal = +me.getRightValue(value); - var range; - var opts = me.options; - var tickOpts = opts.ticks; - - if (me.isHorizontal()) { - range = helpers.log10(me.end) - helpers.log10(start); // todo: if start === 0 - if (newVal === 0) { - pixel = me.left; - } else { - innerDimension = me.width; - pixel = me.left + (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start))); - } - } else { - // Bottom - top since pixels increase downward on a screen - innerDimension = me.height; - if (start === 0 && !tickOpts.reverse) { - range = helpers.log10(me.end) - helpers.log10(me.minNotZero); - if (newVal === start) { - pixel = me.bottom; - } else if (newVal === me.minNotZero) { - pixel = me.bottom - innerDimension * 0.02; - } else { - pixel = me.bottom - innerDimension * 0.02 - (innerDimension * 0.98/ range * (helpers.log10(newVal)-helpers.log10(me.minNotZero))); - } - } else if (me.end === 0 && tickOpts.reverse) { - range = helpers.log10(me.start) - helpers.log10(me.minNotZero); - if (newVal === me.end) { - pixel = me.top; - } else if (newVal === me.minNotZero) { - pixel = me.top + innerDimension * 0.02; - } else { - pixel = me.top + innerDimension * 0.02 + (innerDimension * 0.98/ range * (helpers.log10(newVal)-helpers.log10(me.minNotZero))); - } - } else { - range = helpers.log10(me.end) - helpers.log10(start); - innerDimension = me.height; - pixel = me.bottom - (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start))); - } - } - return pixel; - }, - getValueForPixel: function(pixel) { - var me = this; - var range = helpers.log10(me.end) - helpers.log10(me.start); - var value, innerDimension; - - if (me.isHorizontal()) { - innerDimension = me.width; - value = me.start * Math.pow(10, (pixel - me.left) * range / innerDimension); - } else { // todo: if start === 0 - innerDimension = me.height; - value = Math.pow(10, (me.bottom - pixel) * range / innerDimension) / me.start; - } - return value; - } - }); - Chart.scaleService.registerScaleType('logarithmic', LogarithmicScale, defaultConfig); - - }; - -},{}],47:[function(require,module,exports){ - 'use strict'; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - var globalDefaults = Chart.defaults.global; - - var defaultConfig = { - display: true, - - // Boolean - Whether to animate scaling the chart from the centre - animate: true, - lineArc: false, - position: 'chartArea', - - angleLines: { - display: true, - color: 'rgba(0, 0, 0, 0.1)', - lineWidth: 1 - }, - - // label settings - ticks: { - // Boolean - Show a backdrop to the scale label - showLabelBackdrop: true, - - // String - The colour of the label backdrop - backdropColor: 'rgba(255,255,255,0.75)', - - // Number - The backdrop padding above & below the label in pixels - backdropPaddingY: 2, - - // Number - The backdrop padding to the side of the label in pixels - backdropPaddingX: 2, - - callback: Chart.Ticks.formatters.linear - }, - - pointLabels: { - // Number - Point label font size in pixels - fontSize: 10, - - // Function - Used to convert point labels - callback: function(label) { - return label; - } - } - }; - - function getValueCount(scale) { - return !scale.options.lineArc ? scale.chart.data.labels.length : 0; - } - - function getPointLabelFontOptions(scale) { - var pointLabelOptions = scale.options.pointLabels; - var fontSize = helpers.getValueOrDefault(pointLabelOptions.fontSize, globalDefaults.defaultFontSize); - var fontStyle = helpers.getValueOrDefault(pointLabelOptions.fontStyle, globalDefaults.defaultFontStyle); - var fontFamily = helpers.getValueOrDefault(pointLabelOptions.fontFamily, globalDefaults.defaultFontFamily); - var font = helpers.fontString(fontSize, fontStyle, fontFamily); - - return { - size: fontSize, - style: fontStyle, - family: fontFamily, - font: font - }; - } - - function measureLabelSize(ctx, fontSize, label) { - if (helpers.isArray(label)) { - return { - w: helpers.longestText(ctx, ctx.font, label), - h: (label.length * fontSize) + ((label.length - 1) * 1.5 * fontSize) - }; - } - - return { - w: ctx.measureText(label).width, - h: fontSize - }; - } - - function determineLimits(angle, pos, size, min, max) { - if (angle === min || angle === max) { - return { - start: pos - (size / 2), - end: pos + (size / 2) - }; - } else if (angle < min || angle > max) { - return { - start: pos - size - 5, - end: pos - }; - } - - return { - start: pos, - end: pos + size + 5 - }; - } - - /** - * Helper function to fit a radial linear scale with point labels - */ - function fitWithPointLabels(scale) { - /* - * Right, this is really confusing and there is a lot of maths going on here - * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9 - * - * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif - * - * Solution: - * - * We assume the radius of the polygon is half the size of the canvas at first - * at each index we check if the text overlaps. - * - * Where it does, we store that angle and that index. - * - * After finding the largest index and angle we calculate how much we need to remove - * from the shape radius to move the point inwards by that x. - * - * We average the left and right distances to get the maximum shape radius that can fit in the box - * along with labels. - * - * Once we have that, we can find the centre point for the chart, by taking the x text protrusion - * on each side, removing that from the size, halving it and adding the left x protrusion width. - * - * This will mean we have a shape fitted to the canvas, as large as it can be with the labels - * and position it in the most space efficient manner - * - * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif - */ - - var plFont = getPointLabelFontOptions(scale); - - // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width. - // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points - var largestPossibleRadius = Math.min(scale.height / 2, scale.width / 2); - var furthestLimits = { - l: scale.width, - r: 0, - t: scale.height, - b: 0 - }; - var furthestAngles = {}; - var i; - var textSize; - var pointPosition; - - scale.ctx.font = plFont.font; - scale._pointLabelSizes = []; - - var valueCount = getValueCount(scale); - for (i = 0; i < valueCount; i++) { - pointPosition = scale.getPointPosition(i, largestPossibleRadius); - textSize = measureLabelSize(scale.ctx, plFont.size, scale.pointLabels[i] || ''); - scale._pointLabelSizes[i] = textSize; - - // Add quarter circle to make degree 0 mean top of circle - var angleRadians = scale.getIndexAngle(i); - var angle = helpers.toDegrees(angleRadians) % 360; - var hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180); - var vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270); - - if (hLimits.start < furthestLimits.l) { - furthestLimits.l = hLimits.start; - furthestAngles.l = angleRadians; - } - - if (hLimits.end > furthestLimits.r) { - furthestLimits.r = hLimits.end; - furthestAngles.r = angleRadians; - } - - if (vLimits.start < furthestLimits.t) { - furthestLimits.t = vLimits.start; - furthestAngles.t = angleRadians; - } - - if (vLimits.end > furthestLimits.b) { - furthestLimits.b = vLimits.end; - furthestAngles.b = angleRadians; - } - } - - scale.setReductions(largestPossibleRadius, furthestLimits, furthestAngles); - } - - /** - * Helper function to fit a radial linear scale with no point labels - */ - function fit(scale) { - var largestPossibleRadius = Math.min(scale.height / 2, scale.width / 2); - scale.drawingArea = Math.round(largestPossibleRadius); - scale.setCenterPoint(0, 0, 0, 0); - } - - function getTextAlignForAngle(angle) { - if (angle === 0 || angle === 180) { - return 'center'; - } else if (angle < 180) { - return 'left'; - } - - return 'right'; - } - - function fillText(ctx, text, position, fontSize) { - if (helpers.isArray(text)) { - var y = position.y; - var spacing = 1.5 * fontSize; - - for (var i = 0; i < text.length; ++i) { - ctx.fillText(text[i], position.x, y); - y+= spacing; - } - } else { - ctx.fillText(text, position.x, position.y); - } - } - - function adjustPointPositionForLabelHeight(angle, textSize, position) { - if (angle === 90 || angle === 270) { - position.y -= (textSize.h / 2); - } else if (angle > 270 || angle < 90) { - position.y -= textSize.h; - } - } - - function drawPointLabels(scale) { - var ctx = scale.ctx; - var getValueOrDefault = helpers.getValueOrDefault; - var opts = scale.options; - var angleLineOpts = opts.angleLines; - var pointLabelOpts = opts.pointLabels; - - ctx.lineWidth = angleLineOpts.lineWidth; - ctx.strokeStyle = angleLineOpts.color; - - var outerDistance = scale.getDistanceFromCenterForValue(opts.reverse ? scale.min : scale.max); - - // Point Label Font - var plFont = getPointLabelFontOptions(scale); - - ctx.textBaseline = 'top'; - - for (var i = getValueCount(scale) - 1; i >= 0; i--) { - if (angleLineOpts.display) { - var outerPosition = scale.getPointPosition(i, outerDistance); - ctx.beginPath(); - ctx.moveTo(scale.xCenter, scale.yCenter); - ctx.lineTo(outerPosition.x, outerPosition.y); - ctx.stroke(); - ctx.closePath(); - } - // Extra 3px out for some label spacing - var pointLabelPosition = scale.getPointPosition(i, outerDistance + 5); - - // Keep this in loop since we may support array properties here - var pointLabelFontColor = getValueOrDefault(pointLabelOpts.fontColor, globalDefaults.defaultFontColor); - ctx.font = plFont.font; - ctx.fillStyle = pointLabelFontColor; - - var angleRadians = scale.getIndexAngle(i); - var angle = helpers.toDegrees(angleRadians); - ctx.textAlign = getTextAlignForAngle(angle); - adjustPointPositionForLabelHeight(angle, scale._pointLabelSizes[i], pointLabelPosition); - fillText(ctx, scale.pointLabels[i] || '', pointLabelPosition, plFont.size); - } - } - - function drawRadiusLine(scale, gridLineOpts, radius, index) { - var ctx = scale.ctx; - ctx.strokeStyle = helpers.getValueAtIndexOrDefault(gridLineOpts.color, index - 1); - ctx.lineWidth = helpers.getValueAtIndexOrDefault(gridLineOpts.lineWidth, index - 1); - - if (scale.options.lineArc) { - // Draw circular arcs between the points - ctx.beginPath(); - ctx.arc(scale.xCenter, scale.yCenter, radius, 0, Math.PI * 2); - ctx.closePath(); - ctx.stroke(); - } else { - // Draw straight lines connecting each index - var valueCount = getValueCount(scale); - - if (valueCount === 0) { - return; - } - - ctx.beginPath(); - var pointPosition = scale.getPointPosition(0, radius); - ctx.moveTo(pointPosition.x, pointPosition.y); - - for (var i = 1; i < valueCount; i++) { - pointPosition = scale.getPointPosition(i, radius); - ctx.lineTo(pointPosition.x, pointPosition.y); - } - - ctx.closePath(); - ctx.stroke(); - } - } - - function numberOrZero(param) { - return helpers.isNumber(param) ? param : 0; - } - - var LinearRadialScale = Chart.LinearScaleBase.extend({ - setDimensions: function() { - var me = this; - var opts = me.options; - var tickOpts = opts.ticks; - // Set the unconstrained dimension before label rotation - me.width = me.maxWidth; - me.height = me.maxHeight; - me.xCenter = Math.round(me.width / 2); - me.yCenter = Math.round(me.height / 2); - - var minSize = helpers.min([me.height, me.width]); - var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize); - me.drawingArea = opts.display ? (minSize / 2) - (tickFontSize / 2 + tickOpts.backdropPaddingY) : (minSize / 2); - }, - determineDataLimits: function() { - var me = this; - var chart = me.chart; - var min = Number.POSITIVE_INFINITY; - var max = Number.NEGATIVE_INFINITY; - - helpers.each(chart.data.datasets, function(dataset, datasetIndex) { - if (chart.isDatasetVisible(datasetIndex)) { - var meta = chart.getDatasetMeta(datasetIndex); - - helpers.each(dataset.data, function(rawValue, index) { - var value = +me.getRightValue(rawValue); - if (isNaN(value) || meta.data[index].hidden) { - return; - } - - min = Math.min(value, min); - max = Math.max(value, max); - }); - } - }); - - me.min = (min === Number.POSITIVE_INFINITY ? 0 : min); - me.max = (max === Number.NEGATIVE_INFINITY ? 0 : max); - - // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero - me.handleTickRangeOptions(); - }, - getTickLimit: function() { - var tickOpts = this.options.ticks; - var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize); - return Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(this.drawingArea / (1.5 * tickFontSize))); - }, - convertTicksToLabels: function() { - var me = this; - Chart.LinearScaleBase.prototype.convertTicksToLabels.call(me); - - // Point labels - me.pointLabels = me.chart.data.labels.map(me.options.pointLabels.callback, me); - }, - getLabelForIndex: function(index, datasetIndex) { - return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); - }, - fit: function() { - if (this.options.lineArc) { - fit(this); - } else { - fitWithPointLabels(this); - } - }, - /** - * Set radius reductions and determine new radius and center point - * @private - */ - setReductions: function(largestPossibleRadius, furthestLimits, furthestAngles) { - var me = this; - var radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l); - var radiusReductionRight = Math.max(furthestLimits.r - me.width, 0) / Math.sin(furthestAngles.r); - var radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t); - var radiusReductionBottom = -Math.max(furthestLimits.b - me.height, 0) / Math.cos(furthestAngles.b); - - radiusReductionLeft = numberOrZero(radiusReductionLeft); - radiusReductionRight = numberOrZero(radiusReductionRight); - radiusReductionTop = numberOrZero(radiusReductionTop); - radiusReductionBottom = numberOrZero(radiusReductionBottom); - - me.drawingArea = Math.min( - Math.round(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2), - Math.round(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2)); - me.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom); - }, - setCenterPoint: function(leftMovement, rightMovement, topMovement, bottomMovement) { - var me = this; - var maxRight = me.width - rightMovement - me.drawingArea, - maxLeft = leftMovement + me.drawingArea, - maxTop = topMovement + me.drawingArea, - maxBottom = me.height - bottomMovement - me.drawingArea; - - me.xCenter = Math.round(((maxLeft + maxRight) / 2) + me.left); - me.yCenter = Math.round(((maxTop + maxBottom) / 2) + me.top); - }, - - getIndexAngle: function(index) { - var angleMultiplier = (Math.PI * 2) / getValueCount(this); - var startAngle = this.chart.options && this.chart.options.startAngle ? - this.chart.options.startAngle : - 0; - - var startAngleRadians = startAngle * Math.PI * 2 / 360; - - // Start from the top instead of right, so remove a quarter of the circle - return index * angleMultiplier + startAngleRadians; - }, - getDistanceFromCenterForValue: function(value) { - var me = this; - - if (value === null) { - return 0; // null always in center - } - - // Take into account half font size + the yPadding of the top value - var scalingFactor = me.drawingArea / (me.max - me.min); - if (me.options.reverse) { - return (me.max - value) * scalingFactor; - } - return (value - me.min) * scalingFactor; - }, - getPointPosition: function(index, distanceFromCenter) { - var me = this; - var thisAngle = me.getIndexAngle(index) - (Math.PI / 2); - return { - x: Math.round(Math.cos(thisAngle) * distanceFromCenter) + me.xCenter, - y: Math.round(Math.sin(thisAngle) * distanceFromCenter) + me.yCenter - }; - }, - getPointPositionForValue: function(index, value) { - return this.getPointPosition(index, this.getDistanceFromCenterForValue(value)); - }, - - getBasePosition: function() { - var me = this; - var min = me.min; - var max = me.max; - - return me.getPointPositionForValue(0, - me.beginAtZero? 0: - min < 0 && max < 0? max : - min > 0 && max > 0? min : - 0); - }, - - draw: function() { - var me = this; - var opts = me.options; - var gridLineOpts = opts.gridLines; - var tickOpts = opts.ticks; - var getValueOrDefault = helpers.getValueOrDefault; - - if (opts.display) { - var ctx = me.ctx; - - // Tick Font - var tickFontSize = getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize); - var tickFontStyle = getValueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle); - var tickFontFamily = getValueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily); - var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily); - - helpers.each(me.ticks, function(label, index) { - // Don't draw a centre value (if it is minimum) - if (index > 0 || opts.reverse) { - var yCenterOffset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]); - var yHeight = me.yCenter - yCenterOffset; - - // Draw circular lines around the scale - if (gridLineOpts.display && index !== 0) { - drawRadiusLine(me, gridLineOpts, yCenterOffset, index); - } - - if (tickOpts.display) { - var tickFontColor = getValueOrDefault(tickOpts.fontColor, globalDefaults.defaultFontColor); - ctx.font = tickLabelFont; - - if (tickOpts.showLabelBackdrop) { - var labelWidth = ctx.measureText(label).width; - ctx.fillStyle = tickOpts.backdropColor; - ctx.fillRect( - me.xCenter - labelWidth / 2 - tickOpts.backdropPaddingX, - yHeight - tickFontSize / 2 - tickOpts.backdropPaddingY, - labelWidth + tickOpts.backdropPaddingX * 2, - tickFontSize + tickOpts.backdropPaddingY * 2 - ); - } - - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - ctx.fillStyle = tickFontColor; - ctx.fillText(label, me.xCenter, yHeight); - } - } - }); - - if (!opts.lineArc) { - drawPointLabels(me); - } - } - } - }); - Chart.scaleService.registerScaleType('radialLinear', LinearRadialScale, defaultConfig); - - }; - -},{}],48:[function(require,module,exports){ - /* global window: false */ - 'use strict'; - - var moment = require(1); - moment = typeof(moment) === 'function' ? moment : window.moment; - - module.exports = function(Chart) { - - var helpers = Chart.helpers; - var time = { - units: [{ - name: 'millisecond', - steps: [1, 2, 5, 10, 20, 50, 100, 250, 500] - }, { - name: 'second', - steps: [1, 2, 5, 10, 30] - }, { - name: 'minute', - steps: [1, 2, 5, 10, 30] - }, { - name: 'hour', - steps: [1, 2, 3, 6, 12] - }, { - name: 'day', - steps: [1, 2, 5] - }, { - name: 'week', - maxStep: 4 - }, { - name: 'month', - maxStep: 3 - }, { - name: 'quarter', - maxStep: 4 - }, { - name: 'year', - maxStep: false - }] - }; - - var defaultConfig = { - position: 'bottom', - - time: { - parser: false, // false == a pattern string from http://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment - format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from http://momentjs.com/docs/#/parsing/string-format/ - unit: false, // false == automatic or override with week, month, year, etc. - round: false, // none, or override with week, month, year, etc. - displayFormat: false, // DEPRECATED - isoWeekday: false, // override week start day - see http://momentjs.com/docs/#/get-set/iso-weekday/ - minUnit: 'millisecond', - - // defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/ - displayFormats: { - millisecond: 'h:mm:ss.SSS a', // 11:20:01.123 AM, - second: 'h:mm:ss a', // 11:20:01 AM - minute: 'h:mm:ss a', // 11:20:01 AM - hour: 'MMM D, hA', // Sept 4, 5PM - day: 'll', // Sep 4 2015 - week: 'll', // Week 46, or maybe "[W]WW - YYYY" ? - month: 'MMM YYYY', // Sept 2015 - quarter: '[Q]Q - YYYY', // Q3 - year: 'YYYY' // 2015 - } - }, - ticks: { - autoSkip: false - } - }; - - var TimeScale = Chart.Scale.extend({ - initialize: function() { - if (!moment) { - throw new Error('Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com'); - } - - Chart.Scale.prototype.initialize.call(this); - }, - getLabelMoment: function(datasetIndex, index) { - if (datasetIndex === null || index === null) { - return null; - } - - if (typeof this.labelMoments[datasetIndex] !== 'undefined') { - return this.labelMoments[datasetIndex][index]; - } - - return null; - }, - getLabelDiff: function(datasetIndex, index) { - var me = this; - if (datasetIndex === null || index === null) { - return null; - } - - if (me.labelDiffs === undefined) { - me.buildLabelDiffs(); - } - - if (typeof me.labelDiffs[datasetIndex] !== 'undefined') { - return me.labelDiffs[datasetIndex][index]; - } - - return null; - }, - getMomentStartOf: function(tick) { - var me = this; - if (me.options.time.unit === 'week' && me.options.time.isoWeekday !== false) { - return tick.clone().startOf('isoWeek').isoWeekday(me.options.time.isoWeekday); - } - return tick.clone().startOf(me.tickUnit); - }, - determineDataLimits: function() { - var me = this; - me.labelMoments = []; - - // Only parse these once. If the dataset does not have data as x,y pairs, we will use - // these - var scaleLabelMoments = []; - if (me.chart.data.labels && me.chart.data.labels.length > 0) { - helpers.each(me.chart.data.labels, function(label) { - var labelMoment = me.parseTime(label); - - if (labelMoment.isValid()) { - if (me.options.time.round) { - labelMoment.startOf(me.options.time.round); - } - scaleLabelMoments.push(labelMoment); - } - }, me); - - me.firstTick = moment.min.call(me, scaleLabelMoments); - me.lastTick = moment.max.call(me, scaleLabelMoments); - } else { - me.firstTick = null; - me.lastTick = null; - } - - helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) { - var momentsForDataset = []; - var datasetVisible = me.chart.isDatasetVisible(datasetIndex); - - if (typeof dataset.data[0] === 'object' && dataset.data[0] !== null) { - helpers.each(dataset.data, function(value) { - var labelMoment = me.parseTime(me.getRightValue(value)); - - if (labelMoment.isValid()) { - if (me.options.time.round) { - labelMoment.startOf(me.options.time.round); - } - momentsForDataset.push(labelMoment); - - if (datasetVisible) { - // May have gone outside the scale ranges, make sure we keep the first and last ticks updated - me.firstTick = me.firstTick !== null ? moment.min(me.firstTick, labelMoment) : labelMoment; - me.lastTick = me.lastTick !== null ? moment.max(me.lastTick, labelMoment) : labelMoment; - } - } - }, me); - } else { - // We have no labels. Use the ones from the scale - momentsForDataset = scaleLabelMoments; - } - - me.labelMoments.push(momentsForDataset); - }, me); - - // Set these after we've done all the data - if (me.options.time.min) { - me.firstTick = me.parseTime(me.options.time.min); - } - - if (me.options.time.max) { - me.lastTick = me.parseTime(me.options.time.max); - } - - // We will modify these, so clone for later - me.firstTick = (me.firstTick || moment()).clone(); - me.lastTick = (me.lastTick || moment()).clone(); - }, - buildLabelDiffs: function() { - var me = this; - me.labelDiffs = []; - var scaleLabelDiffs = []; - // Parse common labels once - if (me.chart.data.labels && me.chart.data.labels.length > 0) { - helpers.each(me.chart.data.labels, function(label) { - var labelMoment = me.parseTime(label); - - if (labelMoment.isValid()) { - if (me.options.time.round) { - labelMoment.startOf(me.options.time.round); - } - scaleLabelDiffs.push(labelMoment.diff(me.firstTick, me.tickUnit, true)); - } - }, me); - } - - helpers.each(me.chart.data.datasets, function(dataset) { - var diffsForDataset = []; - - if (typeof dataset.data[0] === 'object' && dataset.data[0] !== null) { - helpers.each(dataset.data, function(value) { - var labelMoment = me.parseTime(me.getRightValue(value)); - - if (labelMoment.isValid()) { - if (me.options.time.round) { - labelMoment.startOf(me.options.time.round); - } - diffsForDataset.push(labelMoment.diff(me.firstTick, me.tickUnit, true)); - } - }, me); - } else { - // We have no labels. Use common ones - diffsForDataset = scaleLabelDiffs; - } - - me.labelDiffs.push(diffsForDataset); - }, me); - }, - buildTicks: function() { - var me = this; - - me.ctx.save(); - var tickFontSize = helpers.getValueOrDefault(me.options.ticks.fontSize, Chart.defaults.global.defaultFontSize); - var tickFontStyle = helpers.getValueOrDefault(me.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle); - var tickFontFamily = helpers.getValueOrDefault(me.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily); - var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily); - me.ctx.font = tickLabelFont; - - me.ticks = []; - me.unitScale = 1; // How much we scale the unit by, ie 2 means 2x unit per step - me.scaleSizeInUnits = 0; // How large the scale is in the base unit (seconds, minutes, etc) - - // Set unit override if applicable - if (me.options.time.unit) { - me.tickUnit = me.options.time.unit || 'day'; - me.displayFormat = me.options.time.displayFormats[me.tickUnit]; - me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true); - me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, 1); - } else { - // Determine the smallest needed unit of the time - var innerWidth = me.isHorizontal() ? me.width : me.height; - - // Crude approximation of what the label length might be - var tempFirstLabel = me.tickFormatFunction(me.firstTick, 0, []); - var tickLabelWidth = me.ctx.measureText(tempFirstLabel).width; - var cosRotation = Math.cos(helpers.toRadians(me.options.ticks.maxRotation)); - var sinRotation = Math.sin(helpers.toRadians(me.options.ticks.maxRotation)); - tickLabelWidth = (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation); - var labelCapacity = innerWidth / (tickLabelWidth); - - // Start as small as possible - me.tickUnit = me.options.time.minUnit; - me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true); - me.displayFormat = me.options.time.displayFormats[me.tickUnit]; - - var unitDefinitionIndex = 0; - var unitDefinition = time.units[unitDefinitionIndex]; - - // While we aren't ideal and we don't have units left - while (unitDefinitionIndex < time.units.length) { - // Can we scale this unit. If `false` we can scale infinitely - me.unitScale = 1; - - if (helpers.isArray(unitDefinition.steps) && Math.ceil(me.scaleSizeInUnits / labelCapacity) < helpers.max(unitDefinition.steps)) { - // Use one of the predefined steps - for (var idx = 0; idx < unitDefinition.steps.length; ++idx) { - if (unitDefinition.steps[idx] >= Math.ceil(me.scaleSizeInUnits / labelCapacity)) { - me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, unitDefinition.steps[idx]); - break; - } - } - - break; - } else if ((unitDefinition.maxStep === false) || (Math.ceil(me.scaleSizeInUnits / labelCapacity) < unitDefinition.maxStep)) { - // We have a max step. Scale this unit - me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, Math.ceil(me.scaleSizeInUnits / labelCapacity)); - break; - } else { - // Move to the next unit up - ++unitDefinitionIndex; - unitDefinition = time.units[unitDefinitionIndex]; - - me.tickUnit = unitDefinition.name; - var leadingUnitBuffer = me.firstTick.diff(me.getMomentStartOf(me.firstTick), me.tickUnit, true); - var trailingUnitBuffer = me.getMomentStartOf(me.lastTick.clone().add(1, me.tickUnit)).diff(me.lastTick, me.tickUnit, true); - me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true) + leadingUnitBuffer + trailingUnitBuffer; - me.displayFormat = me.options.time.displayFormats[unitDefinition.name]; - } - } - } - - var roundedStart; - - // Only round the first tick if we have no hard minimum - if (!me.options.time.min) { - me.firstTick = me.getMomentStartOf(me.firstTick); - roundedStart = me.firstTick; - } else { - roundedStart = me.getMomentStartOf(me.firstTick); - } - - // Only round the last tick if we have no hard maximum - if (!me.options.time.max) { - var roundedEnd = me.getMomentStartOf(me.lastTick); - var delta = roundedEnd.diff(me.lastTick, me.tickUnit, true); - if (delta < 0) { - // Do not use end of because we need me to be in the next time unit - me.lastTick = me.getMomentStartOf(me.lastTick.add(1, me.tickUnit)); - } else if (delta >= 0) { - me.lastTick = roundedEnd; - } - - me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true); - } - - // Tick displayFormat override - if (me.options.time.displayFormat) { - me.displayFormat = me.options.time.displayFormat; - } - - // first tick. will have been rounded correctly if options.time.min is not specified - me.ticks.push(me.firstTick.clone()); - - // For every unit in between the first and last moment, create a moment and add it to the ticks tick - for (var i = me.unitScale; i <= me.scaleSizeInUnits; i += me.unitScale) { - var newTick = roundedStart.clone().add(i, me.tickUnit); - - // Are we greater than the max time - if (me.options.time.max && newTick.diff(me.lastTick, me.tickUnit, true) >= 0) { - break; - } - - me.ticks.push(newTick); - } - - // Always show the right tick - var diff = me.ticks[me.ticks.length - 1].diff(me.lastTick, me.tickUnit); - if (diff !== 0 || me.scaleSizeInUnits === 0) { - // this is a weird case. If the <max> option is the same as the end option, we can't just diff the times because the tick was created from the roundedStart - // but the last tick was not rounded. - if (me.options.time.max) { - me.ticks.push(me.lastTick.clone()); - me.scaleSizeInUnits = me.lastTick.diff(me.ticks[0], me.tickUnit, true); - } else { - me.ticks.push(me.lastTick.clone()); - me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true); - } - } - - me.ctx.restore(); - - // Invalidate label diffs cache - me.labelDiffs = undefined; - }, - // Get tooltip label - getLabelForIndex: function(index, datasetIndex) { - var me = this; - var label = me.chart.data.labels && index < me.chart.data.labels.length ? me.chart.data.labels[index] : ''; - var value = me.chart.data.datasets[datasetIndex].data[index]; - - if (value !== null && typeof value === 'object') { - label = me.getRightValue(value); - } - - // Format nicely - if (me.options.time.tooltipFormat) { - label = me.parseTime(label).format(me.options.time.tooltipFormat); - } - - return label; - }, - // Function to format an individual tick mark - tickFormatFunction: function(tick, index, ticks) { - var formattedTick = tick.format(this.displayFormat); - var tickOpts = this.options.ticks; - var callback = helpers.getValueOrDefault(tickOpts.callback, tickOpts.userCallback); - - if (callback) { - return callback(formattedTick, index, ticks); - } - return formattedTick; - }, - convertTicksToLabels: function() { - var me = this; - me.tickMoments = me.ticks; - me.ticks = me.ticks.map(me.tickFormatFunction, me); - }, - getPixelForValue: function(value, index, datasetIndex) { - var me = this; - var offset = null; - if (index !== undefined && datasetIndex !== undefined) { - offset = me.getLabelDiff(datasetIndex, index); - } - - if (offset === null) { - if (!value || !value.isValid) { - // not already a moment object - value = me.parseTime(me.getRightValue(value)); - } - if (value && value.isValid && value.isValid()) { - offset = value.diff(me.firstTick, me.tickUnit, true); - } - } - - if (offset !== null) { - var decimal = offset !== 0 ? offset / me.scaleSizeInUnits : offset; - - if (me.isHorizontal()) { - var valueOffset = (me.width * decimal); - return me.left + Math.round(valueOffset); - } - - var heightOffset = (me.height * decimal); - return me.top + Math.round(heightOffset); - } - }, - getPixelForTick: function(index) { - return this.getPixelForValue(this.tickMoments[index], null, null); - }, - getValueForPixel: function(pixel) { - var me = this; - var innerDimension = me.isHorizontal() ? me.width : me.height; - var offset = (pixel - (me.isHorizontal() ? me.left : me.top)) / innerDimension; - offset *= me.scaleSizeInUnits; - return me.firstTick.clone().add(moment.duration(offset, me.tickUnit).asSeconds(), 'seconds'); - }, - parseTime: function(label) { - var me = this; - if (typeof me.options.time.parser === 'string') { - return moment(label, me.options.time.parser); - } - if (typeof me.options.time.parser === 'function') { - return me.options.time.parser(label); - } - // Date objects - if (typeof label.getMonth === 'function' || typeof label === 'number') { - return moment(label); - } - // Moment support - if (label.isValid && label.isValid()) { - return label; - } - // Custom parsing (return an instance of moment) - if (typeof me.options.time.format !== 'string' && me.options.time.format.call) { - console.warn('options.time.format is deprecated and replaced by options.time.parser. See http://nnnick.github.io/Chart.js/docs-v2/#scales-time-scale'); - return me.options.time.format(label); - } - // Moment format parsing - return moment(label, me.options.time.format); - } - }); - Chart.scaleService.registerScaleType('time', TimeScale, defaultConfig); - - }; - -},{"1":1}]},{},[7])(7) -}); diff --git a/assets/www/js/vendor/aes-js.js b/assets/www/js/vendor/aes-js.js deleted file mode 100644 index f18d95436b0d59930703da4e6cde4b3952db1be6..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/aes-js.js +++ /dev/null @@ -1,803 +0,0 @@ -// source: https://github.com/ricmoo/aes-js - version 3.3.1 -(function(root) { - "use strict"; - - function checkInt(value) { - return (parseInt(value) === value); - } - - function checkInts(arrayish) { - if (!checkInt(arrayish.length)) { return false; } - - for (var i = 0; i < arrayish.length; i++) { - if (!checkInt(arrayish[i]) || arrayish[i] < 0 || arrayish[i] > 255) { - return false; - } - } - - return true; - } - - function coerceArray(arg, copy) { - - // ArrayBuffer view - if (arg.buffer && ArrayBuffer.isView(arg) && arg.name === 'Uint8Array') { - - if (copy) { - if (arg.slice) { - arg = arg.slice(); - } else { - arg = Array.prototype.slice.call(arg); - } - } - - return arg; - } - - // It's an array; check it is a valid representation of a byte - if (Array.isArray(arg)) { - if (!checkInts(arg)) { - throw new Error('Array contains invalid value: ' + arg); - } - - return new Uint8Array(arg); - } - - // Something else, but behaves like an array (maybe a Buffer? Arguments?) - if (checkInt(arg.length) && checkInts(arg)) { - return new Uint8Array(arg); - } - - throw new Error('unsupported array-like object'); - } - - function createArray(length) { - return new Uint8Array(length); - } - - function copyArray(sourceArray, targetArray, targetStart, sourceStart, sourceEnd) { - if (sourceStart != null || sourceEnd != null) { - if (sourceArray.slice) { - sourceArray = sourceArray.slice(sourceStart, sourceEnd); - } else { - sourceArray = Array.prototype.slice.call(sourceArray, sourceStart, sourceEnd); - } - } - targetArray.set(sourceArray, targetStart); - } - - - - var convertUtf8 = (function() { - function toBytes(text) { - var result = [], i = 0; - text = encodeURI(text); - while (i < text.length) { - var c = text.charCodeAt(i++); - - // if it is a % sign, encode the following 2 bytes as a hex value - if (c === 37) { - result.push(parseInt(text.substr(i, 2), 16)) - i += 2; - - // otherwise, just the actual byte - } else { - result.push(c) - } - } - - return coerceArray(result); - } - - function fromBytes(bytes) { - var result = [], i = 0; - - while (i < bytes.length) { - var c = bytes[i]; - - if (c < 128) { - result.push(String.fromCharCode(c)); - i++; - } else if (c > 191 && c < 224) { - result.push(String.fromCharCode(((c & 0x1f) << 6) | (bytes[i + 1] & 0x3f))); - i += 2; - } else { - result.push(String.fromCharCode(((c & 0x0f) << 12) | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f))); - i += 3; - } - } - - return result.join(''); - } - - return { - toBytes: toBytes, - fromBytes: fromBytes, - } - })(); - - var convertHex = (function() { - function toBytes(text) { - var result = []; - for (var i = 0; i < text.length; i += 2) { - result.push(parseInt(text.substr(i, 2), 16)); - } - - return result; - } - - // http://ixti.net/development/javascript/2011/11/11/base64-encodedecode-of-utf8-in-browser-with-js.html - var Hex = '0123456789abcdef'; - - function fromBytes(bytes) { - var result = []; - for (var i = 0; i < bytes.length; i++) { - var v = bytes[i]; - result.push(Hex[(v & 0xf0) >> 4] + Hex[v & 0x0f]); - } - return result.join(''); - } - - return { - toBytes: toBytes, - fromBytes: fromBytes, - } - })(); - - - // Number of rounds by keysize - var numberOfRounds = {16: 10, 24: 12, 32: 14} - - // Round constant words - var rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91]; - - // S-box and Inverse S-box (S is for Substitution) - var S = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]; - var Si =[0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]; - - // Transformations for encryption - var T1 = [0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a]; - var T2 = [0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616]; - var T3 = [0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16]; - var T4 = [0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c]; - - // Transformations for decryption - var T5 = [0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742]; - var T6 = [0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857]; - var T7 = [0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8]; - var T8 = [0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0]; - - // Transformations for decryption key expansion - var U1 = [0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]; - var U2 = [0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697]; - var U3 = [0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46]; - var U4 = [0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d]; - - function convertToInt32(bytes) { - var result = []; - for (var i = 0; i < bytes.length; i += 4) { - result.push( - (bytes[i ] << 24) | - (bytes[i + 1] << 16) | - (bytes[i + 2] << 8) | - bytes[i + 3] - ); - } - return result; - } - - var AES = function(key) { - if (!(this instanceof AES)) { - throw Error('AES must be instanitated with `new`'); - } - - Object.defineProperty(this, 'key', { - value: coerceArray(key, true) - }); - - this._prepare(); - } - - - AES.prototype._prepare = function() { - - var rounds = numberOfRounds[this.key.length]; - if (rounds == null) { - throw new Error('invalid key size (must be 16, 24 or 32 bytes)'); - } - - // encryption round keys - this._Ke = []; - - // decryption round keys - this._Kd = []; - - for (var i = 0; i <= rounds; i++) { - this._Ke.push([0, 0, 0, 0]); - this._Kd.push([0, 0, 0, 0]); - } - - var roundKeyCount = (rounds + 1) * 4; - var KC = this.key.length / 4; - - // convert the key into ints - var tk = convertToInt32(this.key); - - // copy values into round key arrays - var index; - for (var i = 0; i < KC; i++) { - index = i >> 2; - this._Ke[index][i % 4] = tk[i]; - this._Kd[rounds - index][i % 4] = tk[i]; - } - - // key expansion (fips-197 section 5.2) - var rconpointer = 0; - var t = KC, tt; - while (t < roundKeyCount) { - tt = tk[KC - 1]; - tk[0] ^= ((S[(tt >> 16) & 0xFF] << 24) ^ - (S[(tt >> 8) & 0xFF] << 16) ^ - (S[ tt & 0xFF] << 8) ^ - S[(tt >> 24) & 0xFF] ^ - (rcon[rconpointer] << 24)); - rconpointer += 1; - - // key expansion (for non-256 bit) - if (KC != 8) { - for (var i = 1; i < KC; i++) { - tk[i] ^= tk[i - 1]; - } - - // key expansion for 256-bit keys is "slightly different" (fips-197) - } else { - for (var i = 1; i < (KC / 2); i++) { - tk[i] ^= tk[i - 1]; - } - tt = tk[(KC / 2) - 1]; - - tk[KC / 2] ^= (S[ tt & 0xFF] ^ - (S[(tt >> 8) & 0xFF] << 8) ^ - (S[(tt >> 16) & 0xFF] << 16) ^ - (S[(tt >> 24) & 0xFF] << 24)); - - for (var i = (KC / 2) + 1; i < KC; i++) { - tk[i] ^= tk[i - 1]; - } - } - - // copy values into round key arrays - var i = 0, r, c; - while (i < KC && t < roundKeyCount) { - r = t >> 2; - c = t % 4; - this._Ke[r][c] = tk[i]; - this._Kd[rounds - r][c] = tk[i++]; - t++; - } - } - - // inverse-cipher-ify the decryption round key (fips-197 section 5.3) - for (var r = 1; r < rounds; r++) { - for (var c = 0; c < 4; c++) { - tt = this._Kd[r][c]; - this._Kd[r][c] = (U1[(tt >> 24) & 0xFF] ^ - U2[(tt >> 16) & 0xFF] ^ - U3[(tt >> 8) & 0xFF] ^ - U4[ tt & 0xFF]); - } - } - } - - AES.prototype.encrypt = function(plaintext) { - if (plaintext.length != 16) { - throw new Error('invalid plaintext size (must be 16 bytes)'); - } - - var rounds = this._Ke.length - 1; - var a = [0, 0, 0, 0]; - - // convert plaintext to (ints ^ key) - var t = convertToInt32(plaintext); - for (var i = 0; i < 4; i++) { - t[i] ^= this._Ke[0][i]; - } - - // apply round transforms - for (var r = 1; r < rounds; r++) { - for (var i = 0; i < 4; i++) { - a[i] = (T1[(t[ i ] >> 24) & 0xff] ^ - T2[(t[(i + 1) % 4] >> 16) & 0xff] ^ - T3[(t[(i + 2) % 4] >> 8) & 0xff] ^ - T4[ t[(i + 3) % 4] & 0xff] ^ - this._Ke[r][i]); - } - t = a.slice(); - } - - // the last round is special - var result = createArray(16), tt; - for (var i = 0; i < 4; i++) { - tt = this._Ke[rounds][i]; - result[4 * i ] = (S[(t[ i ] >> 24) & 0xff] ^ (tt >> 24)) & 0xff; - result[4 * i + 1] = (S[(t[(i + 1) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff; - result[4 * i + 2] = (S[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff; - result[4 * i + 3] = (S[ t[(i + 3) % 4] & 0xff] ^ tt ) & 0xff; - } - - return result; - } - - AES.prototype.decrypt = function(ciphertext) { - if (ciphertext.length != 16) { - throw new Error('invalid ciphertext size (must be 16 bytes)'); - } - - var rounds = this._Kd.length - 1; - var a = [0, 0, 0, 0]; - - // convert plaintext to (ints ^ key) - var t = convertToInt32(ciphertext); - for (var i = 0; i < 4; i++) { - t[i] ^= this._Kd[0][i]; - } - - // apply round transforms - for (var r = 1; r < rounds; r++) { - for (var i = 0; i < 4; i++) { - a[i] = (T5[(t[ i ] >> 24) & 0xff] ^ - T6[(t[(i + 3) % 4] >> 16) & 0xff] ^ - T7[(t[(i + 2) % 4] >> 8) & 0xff] ^ - T8[ t[(i + 1) % 4] & 0xff] ^ - this._Kd[r][i]); - } - t = a.slice(); - } - - // the last round is special - var result = createArray(16), tt; - for (var i = 0; i < 4; i++) { - tt = this._Kd[rounds][i]; - result[4 * i ] = (Si[(t[ i ] >> 24) & 0xff] ^ (tt >> 24)) & 0xff; - result[4 * i + 1] = (Si[(t[(i + 3) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff; - result[4 * i + 2] = (Si[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff; - result[4 * i + 3] = (Si[ t[(i + 1) % 4] & 0xff] ^ tt ) & 0xff; - } - - return result; - } - - - /** - * Mode Of Operation - Electonic Codebook (ECB) - */ - var ModeOfOperationECB = function(key) { - if (!(this instanceof ModeOfOperationECB)) { - throw Error('AES must be instanitated with `new`'); - } - - this.description = "Electronic Code Block"; - this.name = "ecb"; - - this._aes = new AES(key); - } - - ModeOfOperationECB.prototype.encrypt = function(plaintext) { - plaintext = coerceArray(plaintext); - - if ((plaintext.length % 16) !== 0) { - throw new Error('invalid plaintext size (must be multiple of 16 bytes)'); - } - - var ciphertext = createArray(plaintext.length); - var block = createArray(16); - - for (var i = 0; i < plaintext.length; i += 16) { - copyArray(plaintext, block, 0, i, i + 16); - block = this._aes.encrypt(block); - copyArray(block, ciphertext, i); - } - - return ciphertext; - } - - ModeOfOperationECB.prototype.decrypt = function(ciphertext) { - ciphertext = coerceArray(ciphertext); - - if ((ciphertext.length % 16) !== 0) { - throw new Error('invalid ciphertext size (must be multiple of 16 bytes)'); - } - - var plaintext = createArray(ciphertext.length); - var block = createArray(16); - - for (var i = 0; i < ciphertext.length; i += 16) { - copyArray(ciphertext, block, 0, i, i + 16); - block = this._aes.decrypt(block); - copyArray(block, plaintext, i); - } - - return plaintext; - } - - - /** - * Mode Of Operation - Cipher Block Chaining (CBC) - */ - var ModeOfOperationCBC = function(key, iv) { - if (!(this instanceof ModeOfOperationCBC)) { - throw Error('AES must be instanitated with `new`'); - } - - this.description = "Cipher Block Chaining"; - this.name = "cbc"; - - if (!iv) { - iv = createArray(16); - - } else if (iv.length != 16) { - throw new Error('invalid initialation vector size (must be 16 bytes)'); - } - - this._lastCipherblock = coerceArray(iv, true); - - this._aes = new AES(key); - } - - ModeOfOperationCBC.prototype.encrypt = function(plaintext) { - plaintext = coerceArray(plaintext); - - if ((plaintext.length % 16) !== 0) { - throw new Error('invalid plaintext size (must be multiple of 16 bytes)'); - } - - var ciphertext = createArray(plaintext.length); - var block = createArray(16); - - for (var i = 0; i < plaintext.length; i += 16) { - copyArray(plaintext, block, 0, i, i + 16); - - for (var j = 0; j < 16; j++) { - block[j] ^= this._lastCipherblock[j]; - } - - this._lastCipherblock = this._aes.encrypt(block); - copyArray(this._lastCipherblock, ciphertext, i); - } - - return ciphertext; - } - - ModeOfOperationCBC.prototype.decrypt = function(ciphertext) { - ciphertext = coerceArray(ciphertext); - - if ((ciphertext.length % 16) !== 0) { - throw new Error('invalid ciphertext size (must be multiple of 16 bytes)'); - } - - var plaintext = createArray(ciphertext.length); - var block = createArray(16); - - for (var i = 0; i < ciphertext.length; i += 16) { - copyArray(ciphertext, block, 0, i, i + 16); - block = this._aes.decrypt(block); - - for (var j = 0; j < 16; j++) { - plaintext[i + j] = block[j] ^ this._lastCipherblock[j]; - } - - copyArray(ciphertext, this._lastCipherblock, 0, i, i + 16); - } - - return plaintext; - } - - - /** - * Mode Of Operation - Cipher Feedback (CFB) - */ - var ModeOfOperationCFB = function(key, iv, segmentSize) { - if (!(this instanceof ModeOfOperationCFB)) { - throw Error('AES must be instanitated with `new`'); - } - - this.description = "Cipher Feedback"; - this.name = "cfb"; - - if (!iv) { - iv = createArray(16); - - } else if (iv.length != 16) { - throw new Error('invalid initialation vector size (must be 16 size)'); - } - - if (!segmentSize) { segmentSize = 1; } - - this.segmentSize = segmentSize; - - this._shiftRegister = coerceArray(iv, true); - - this._aes = new AES(key); - } - - ModeOfOperationCFB.prototype.encrypt = function(plaintext) { - if ((plaintext.length % this.segmentSize) != 0) { - throw new Error('invalid plaintext size (must be segmentSize bytes)'); - } - - var encrypted = coerceArray(plaintext, true); - - var xorSegment; - for (var i = 0; i < encrypted.length; i += this.segmentSize) { - xorSegment = this._aes.encrypt(this._shiftRegister); - for (var j = 0; j < this.segmentSize; j++) { - encrypted[i + j] ^= xorSegment[j]; - } - - // Shift the register - copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize); - copyArray(encrypted, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize); - } - - return encrypted; - } - - ModeOfOperationCFB.prototype.decrypt = function(ciphertext) { - if ((ciphertext.length % this.segmentSize) != 0) { - throw new Error('invalid ciphertext size (must be segmentSize bytes)'); - } - - var plaintext = coerceArray(ciphertext, true); - - var xorSegment; - for (var i = 0; i < plaintext.length; i += this.segmentSize) { - xorSegment = this._aes.encrypt(this._shiftRegister); - - for (var j = 0; j < this.segmentSize; j++) { - plaintext[i + j] ^= xorSegment[j]; - } - - // Shift the register - copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize); - copyArray(ciphertext, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize); - } - - return plaintext; - } - - /** - * Mode Of Operation - Output Feedback (OFB) - */ - var ModeOfOperationOFB = function(key, iv) { - if (!(this instanceof ModeOfOperationOFB)) { - throw Error('AES must be instanitated with `new`'); - } - - this.description = "Output Feedback"; - this.name = "ofb"; - - if (!iv) { - iv = createArray(16); - - } else if (iv.length != 16) { - throw new Error('invalid initialation vector size (must be 16 bytes)'); - } - - this._lastPrecipher = coerceArray(iv, true); - this._lastPrecipherIndex = 16; - - this._aes = new AES(key); - } - - ModeOfOperationOFB.prototype.encrypt = function(plaintext) { - var encrypted = coerceArray(plaintext, true); - - for (var i = 0; i < encrypted.length; i++) { - if (this._lastPrecipherIndex === 16) { - this._lastPrecipher = this._aes.encrypt(this._lastPrecipher); - this._lastPrecipherIndex = 0; - } - encrypted[i] ^= this._lastPrecipher[this._lastPrecipherIndex++]; - } - - return encrypted; - } - - // Decryption is symetric - ModeOfOperationOFB.prototype.decrypt = ModeOfOperationOFB.prototype.encrypt; - - - /** - * Counter object for CTR common mode of operation - */ - var Counter = function(initialValue) { - if (!(this instanceof Counter)) { - throw Error('Counter must be instanitated with `new`'); - } - - // We allow 0, but anything false-ish uses the default 1 - if (initialValue !== 0 && !initialValue) { initialValue = 1; } - - if (typeof(initialValue) === 'number') { - this._counter = createArray(16); - this.setValue(initialValue); - - } else { - this.setBytes(initialValue); - } - } - - Counter.prototype.setValue = function(value) { - if (typeof(value) !== 'number' || parseInt(value) != value) { - throw new Error('invalid counter value (must be an integer)'); - } - - // We cannot safely handle numbers beyond the safe range for integers - if (value > Number.MAX_SAFE_INTEGER) { - throw new Error('integer value out of safe range'); - } - - for (var index = 15; index >= 0; --index) { - this._counter[index] = value % 256; - value = parseInt(value / 256); - } - } - - Counter.prototype.setBytes = function(bytes) { - bytes = coerceArray(bytes, true); - - if (bytes.length != 16) { - throw new Error('invalid counter bytes size (must be 16 bytes)'); - } - - this._counter = bytes; - }; - - Counter.prototype.increment = function() { - for (var i = 15; i >= 0; i--) { - if (this._counter[i] === 255) { - this._counter[i] = 0; - } else { - this._counter[i]++; - break; - } - } - } - - - /** - * Mode Of Operation - Counter (CTR) - */ - var ModeOfOperationCTR = function(key, counter) { - if (!(this instanceof ModeOfOperationCTR)) { - throw Error('AES must be instanitated with `new`'); - } - - this.description = "Counter"; - this.name = "ctr"; - - if (!(counter instanceof Counter)) { - counter = new Counter(counter) - } - - this._counter = counter; - - this._remainingCounter = null; - this._remainingCounterIndex = 16; - - this._aes = new AES(key); - } - - ModeOfOperationCTR.prototype.encrypt = function(plaintext) { - var encrypted = coerceArray(plaintext, true); - - for (var i = 0; i < encrypted.length; i++) { - if (this._remainingCounterIndex === 16) { - this._remainingCounter = this._aes.encrypt(this._counter._counter); - this._remainingCounterIndex = 0; - this._counter.increment(); - } - encrypted[i] ^= this._remainingCounter[this._remainingCounterIndex++]; - } - - return encrypted; - } - - // Decryption is symetric - ModeOfOperationCTR.prototype.decrypt = ModeOfOperationCTR.prototype.encrypt; - - - /////////////////////// - // Padding - - // See:https://tools.ietf.org/html/rfc2315 - function pkcs7pad(data) { - data = coerceArray(data, true); - var padder = 16 - (data.length % 16); - var result = createArray(data.length + padder); - copyArray(data, result); - for (var i = data.length; i < result.length; i++) { - result[i] = padder; - } - return result; - } - - function pkcs7strip(data) { - data = coerceArray(data, true); - if (data.length < 16) { throw new Error('PKCS#7 invalid length'); } - - var padder = data[data.length - 1]; - if (padder > 16) { throw new Error('PKCS#7 padding byte out of range'); } - - var length = data.length - padder; - for (var i = 0; i < padder; i++) { - if (data[length + i] !== padder) { - throw new Error('PKCS#7 invalid padding byte'); - } - } - - var result = createArray(length); - copyArray(data, result, 0, 0, length); - return result; - } - - /////////////////////// - // Exporting - - - // The block cipher - var aesjs = { - AES: AES, - Counter: Counter, - - ModeOfOperation: { - ecb: ModeOfOperationECB, - cbc: ModeOfOperationCBC, - cfb: ModeOfOperationCFB, - ofb: ModeOfOperationOFB, - ctr: ModeOfOperationCTR - }, - - utils: { - hex: convertHex, - utf8: convertUtf8 - }, - - padding: { - pkcs7: { - pad: pkcs7pad, - strip: pkcs7strip - } - }, - - _arrayTest: { - coerceArray: coerceArray, - createArray: createArray, - copyArray: copyArray, - } - }; - - - // node.js - if (typeof exports !== 'undefined') { - module.exports = aesjs - - // RequireJS/AMD - // http://www.requirejs.org/docs/api.html - // https://github.com/amdjs/amdjs-api/wiki/AMD - } else if (typeof(define) === 'function' && define.amd) { - define(aesjs); - - // Web Browsers - } else { - - // If there was an existing library at "aesjs" make sure it's still available - if (root.aesjs) { - aesjs._aesjs = root.aesjs; - } - - root.aesjs = aesjs; - } - - -})(this); diff --git a/assets/www/js/vendor/ion-digit-keyboard.min.js b/assets/www/js/vendor/ion-digit-keyboard.min.js deleted file mode 100644 index 629f661888024d2fbd731baffb8b579ed3678ae8..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/ion-digit-keyboard.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){var i=e.createElement("style");if(e.getElementsByTagName("head")[0].appendChild(i),i.styleSheet)i.styleSheet.disabled||(i.styleSheet.cssText=t);else try{i.innerHTML=t}catch(d){i.innerText=t}}(document,".digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters.hidden,.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper.hidden{visibility:hidden}.digit-keyboard{position:absolute;left:0;right:0;bottom:0;background:0 0;font-size:24px;z-index:5000}.digit-keyboard *{box-sizing:border-box}.digit-keyboard .digit-keyboard-row{display:flex;flex-direction:row;border-bottom:1px solid #333}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper{flex:1;text-align:center;position:relative;height:60px}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key{display:block;margin:0 auto;position:absolute;left:0;top:0;right:0;bottom:0;border-right:1px solid #333;border-left:1px solid #333;line-height:60px;-webkit-transition:background-color .1s linear;-moz-transition:background-color .1s linear;-o-transition:background-color .1s linear;-ms-transition:background-color .1s linear;transition:background-color .1s linear}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number{font-size:1em;vertical-align:middle;display:inline-block;line-height:normal;text-align:center;margin-top:-.4em}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters{font-size:9.6px;line-height:9.6px;height:9.6px;margin-top:-.25em}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-action{position:absolute;left:0;top:0;right:0;bottom:0;line-height:60px;font-size:24px}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper:first-child .digit-keyboard-key{border-right:none}.digit-keyboard .digit-keyboard-row .digit-keyboard-key-wrapper:last-child .digit-keyboard-key{border-left:none}.digit-keyboard .digit-keyboard-row:first-child{border-top:1px solid #333}.digit-keyboard .digit-keyboard-row:last-child{border:none}.digit-keyboard .digit-keyboard-row:last-child .digit-keyboard-key-wrapper .digit-keyboard-key{border-bottom:1px solid #333}.digit-keyboard.align-center{margin:0 auto}.digit-keyboard.align-left{margin-right:auto}.digit-keyboard.align-right{margin-left:auto}.digit-keyboard.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number{margin-top:-.3em}.digit-keyboard.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number .digit-keyboard-key-letters{display:none}.digit-keyboard.round-buttons .digit-keyboard-row{border:none}.digit-keyboard.round-buttons .digit-keyboard-row .digit-keyboard-key-wrapper{margin:10px 0 0}.digit-keyboard.round-buttons .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key{width:60px;-webkit-border-radius:100%;-moz-border-radius:100%;border-radius:100%;border:1px solid #333}.digit-keyboard.round-buttons .digit-keyboard-row:last-child .digit-keyboard-key-wrapper{margin-bottom:10px}.digit-keyboard.round-buttons.no-letters .digit-keyboard-row .digit-keyboard-key-wrapper .digit-keyboard-key .digit-keyboard-key-number{height:57.6px;line-height:57.6px}.digit-keyboard.keyboard-light *{border-color:#e6e6e6!important}.digit-keyboard.keyboard-light .digit-keyboard-key{background:#fff;color:#444}.digit-keyboard.keyboard-light .digit-keyboard-key.activated{background:#e6e6e6}.digit-keyboard.keyboard-stable *{border-color:#dfdfdf!important}.digit-keyboard.keyboard-stable .digit-keyboard-key{background:#f8f8f8;color:#444}.digit-keyboard.keyboard-stable .digit-keyboard-key.activated{background:#dfdfdf}.digit-keyboard.keyboard-positive *{border-color:#0c60ee!important}.digit-keyboard.keyboard-positive .digit-keyboard-key{background:#387ef5;color:#fff}.digit-keyboard.keyboard-positive .digit-keyboard-key.activated{background:#0c60ee}.digit-keyboard.keyboard-calm *{border-color:#0a9dc7!important}.digit-keyboard.keyboard-calm .digit-keyboard-key{background:#11c1f3;color:#fff}.digit-keyboard.keyboard-calm .digit-keyboard-key.activated{background:#0a9dc7}.digit-keyboard.keyboard-balanced *{border-color:#28a54c!important}.digit-keyboard.keyboard-balanced .digit-keyboard-key{background:#33cd5f;color:#fff}.digit-keyboard.keyboard-balanced .digit-keyboard-key.activated{background:#28a54c}.digit-keyboard.keyboard-energized *{border-color:#e6b500!important}.digit-keyboard.keyboard-energized .digit-keyboard-key{background:#ffc900;color:#fff}.digit-keyboard.keyboard-energized .digit-keyboard-key.activated{background:#e6b500}.digit-keyboard.keyboard-assertive *{border-color:#e42112!important}.digit-keyboard.keyboard-assertive .digit-keyboard-key{background:#ef473a;color:#fff}.digit-keyboard.keyboard-assertive .digit-keyboard-key.activated{background:#e42112}.digit-keyboard.keyboard-royal *{border-color:#6b46e5!important}.digit-keyboard.keyboard-royal .digit-keyboard-key{background:#886aea;color:#fff}.digit-keyboard.keyboard-royal .digit-keyboard-key.activated{background:#6b46e5}.digit-keyboard.keyboard-dark *{border-color:#2b2b2b!important}.digit-keyboard.keyboard-dark .digit-keyboard-key{background:#444;color:#fff}.digit-keyboard.keyboard-dark .digit-keyboard-key.activated{background:#2b2b2b}.digit-keyboard.keyboard-opaque-black *{border-color:rgba(0,0,0,.75)!important}.digit-keyboard.keyboard-opaque-black .digit-keyboard-key{background:rgba(0,0,0,.15);color:rgba(0,0,0,.75)}.digit-keyboard.keyboard-opaque-black .digit-keyboard-key.activated{background:rgba(0,0,0,.25)}.digit-keyboard.keyboard-opaque-white *{border-color:rgba(255,255,255,.75)!important}.digit-keyboard.keyboard-opaque-white .digit-keyboard-key{background:rgba(255,255,255,.15);color:rgba(255,255,255,.75)}.digit-keyboard.keyboard-opaque-white .digit-keyboard-key.activated{background:rgba(255,255,255,.25)}.digit-keyboard.animation-slide-up{-webkit-transition:transform linear 150ms;transition:transform linear 150ms;transform:translate3d(0,0,0)}.digit-keyboard.animation-slide-up.ng-hide{transform:translate3d(0,100%,0)}.digit-keyboard.animation-pop{-webkit-transition:transform linear 150ms;transition:transform linear 150ms;transform:scale3d(1,1,1)}.digit-keyboard.animation-pop.ng-hide{transform:scale3d(0,0,1)}"),!function(e){try{e=angular.module("ion-digit-keyboard.templates")}catch(t){e=angular.module("ion-digit-keyboard.templates",[])}e.run(["$templateCache",function(e){e.put("keyboard.tpl.html","<div class=\"digit-keyboard align-{{align}} keyboard-{{theme}} animation-{{animation}} {{roundButtons ? 'round-buttons' : ''}} {{showLetters == false ? 'no-letters' : ''}} {{(ngShow == false || ngHide == true) ? 'ng-hide' : ''}}\" style=\"width: {{width}};\"><div class=digit-keyboard-row><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(1)><div class=digit-keyboard-key-number>1<div class=digit-keyboard-key-letters></div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(2)><div class=digit-keyboard-key-number>2<div class=digit-keyboard-key-letters>ABC</div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(3)><div class=digit-keyboard-key-number>3<div class=digit-keyboard-key-letters>DEF</div></div></div></div></div><div class=digit-keyboard-row><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(4)><div class=digit-keyboard-key-number>4<div class=digit-keyboard-key-letters>GHI</div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(5)><div class=digit-keyboard-key-number>5<div class=digit-keyboard-key-letters>JKL</div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(6)><div class=digit-keyboard-key-number>6<div class=digit-keyboard-key-letters>MNO</div></div></div></div></div><div class=digit-keyboard-row><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(7)><div class=digit-keyboard-key-number>7<div class=digit-keyboard-key-letters>PQRS</div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(8)><div class=digit-keyboard-key-number>8<div class=digit-keyboard-key-letters>TUV</div></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(9)><div class=digit-keyboard-key-number>9<div class=digit-keyboard-key-letters>WXYZ</div></div></div></div></div><div class=digit-keyboard-row><div class=\"digit-keyboard-key-wrapper {{showLeftAction == false ? 'hidden' : ''}}\"><div class=digit-keyboard-key ng-click=leftAction($event) style={{leftStyle}}><div class=digit-keyboard-key-action ng-bind-html=leftHtml style={{leftFontSize}}></div></div></div><div class=digit-keyboard-key-wrapper><div class=digit-keyboard-key ng-click=numberAction(0)><div class=digit-keyboard-key-number style=\"margin-top: -0.30em;\">0</div></div></div><div class=\"digit-keyboard-key-wrapper {{showRightAction == false ? 'hidden' : ''}}\"><div class=digit-keyboard-key ng-click=rightAction($event) style={{rightStyle}}><div class=digit-keyboard-key-action ng-bind-html=rightHtml style={{rightFontSize}}></div></div></div></div></div>")}])}(),angular.module("ion-digit-keyboard.directive",[]).directive("ionDigitKeyboard",["$timeout","$ionicScrollDelegate","$templateCache",function(e,t,i){var d=150;return{restrict:"EA",template:i.get("keyboard.tpl.html"),replace:!0,scope:{settings:"=settings",ngShow:"=",ngHide:"="},link:function(i,o,r){function a(){1==b&&(k.style.bottom="0px",k.style.height=s)}function n(){e(function(){if(1==b){var e=o[0].offsetHeight;s=k.style.height,k.style.height="auto",k.style.bottom=e+1+"px"}},d+10)}function y(){i.ngShow===!0?n():i.ngShow===!1&&a(),t.resize()}function g(){i.ngHide===!0?a():i.ngHide===!1&&n(),t.resize()}"undefined"==typeof i.settings&&(i.settings={});var k,s,b=!0,l="ion-content",c={},u={};if(i.leftStyle="",i.rightStyle="",i.leftFontSize="",i.rightFontSize="",i.showLetters="undefined"==typeof i.settings.showLetters?!1:i.settings.showLetters,i.roundButtons="undefined"==typeof i.settings.roundButtons?!1:i.settings.roundButtons,i.numberAction=i.settings.action||function(){},i.width=i.settings.width||"100%",i.align=i.settings.align||"center",i.animation=i.settings.animation||"slide-up",i.theme=i.settings.theme||"stable","undefined"!=typeof i.settings.leftButton&&"object"==typeof i.settings.leftButton.style&&("undefined"!=typeof i.settings.leftButton.style.color&&(i.leftStyle+="color: "+i.settings.leftButton.style.color+";"),"undefined"!=typeof i.settings.leftButton.style.bgColor&&(c["default"]=i.settings.leftButton.style.bgColor,i.leftStyle+="background-color: "+c["default"]+";"),"undefined"!=typeof i.settings.leftButton.style.activeBgColor&&(c.active=i.settings.leftButton.style.activeBgColor),"undefined"!=typeof i.settings.leftButton.style.borderColor&&(i.leftStyle+="border-color: "+i.settings.leftButton.style.borderColor+" !important;"),"undefined"!=typeof i.settings.leftButton.style.fontSize&&(i.leftFontSize="font-size: "+i.settings.leftButton.style.fontSize+" !important;")),"undefined"!=typeof i.settings.rightButton&&"object"==typeof i.settings.rightButton.style&&("undefined"!=typeof i.settings.rightButton.style.color&&(i.rightStyle+="color: "+i.settings.rightButton.style.color+";"),"undefined"!=typeof i.settings.rightButton.style.bgColor&&(u["default"]=i.settings.rightButton.style.bgColor,i.rightStyle+="background-color: "+u["default"]+";"),"undefined"!=typeof i.settings.rightButton.style.activeBgColor&&(u.active=i.settings.rightButton.style.activeBgColor),"undefined"!=typeof i.settings.rightButton.style.borderColor&&(i.rightStyle+="border-color: "+i.settings.rightButton.style.borderColor+" !important;"),"undefined"!=typeof i.settings.rightButton.style.fontSize&&(i.rightFontSize="font-size: "+i.settings.rightButton.style.fontSize+" !important;")),i.showLeftAction=!1,"undefined"!=typeof i.settings.leftButton&&(i.leftHtml=i.settings.leftButton.html,i.showLeftAction=!0,i.leftAction=function(e){if(c.active){var t=e.target;"I"==t.tagName?t=t.parentNode.parentNode:t.className.indexOf("digit-keyboard-key-action")>-1&&(t=t.parentNode),"undefined"==typeof c["default"]&&(c["default"]=t.style.backgroundColor),t.style.backgroundColor=c.active,setTimeout(function(){t.style.backgroundColor=c["default"]},100)}i.settings.leftButton.action()}),i.showRightAction=!1,"undefined"!=typeof i.settings.rightButton&&(i.rightHtml=i.settings.rightButton.html,i.showRightAction=!0,i.rightAction=function(e){if(u.active){var t=e.target;"I"==t.tagName?t=t.parentNode.parentNode:t.className.indexOf("digit-keyboard-key-action")>-1&&(t=t.parentNode),"undefined"==typeof u["default"]&&(u["default"]=t.style.backgroundColor),t.style.backgroundColor=u.active,setTimeout(function(){t.style.backgroundColor=u["default"]},100)}i.settings.rightButton.action()}),"object"==typeof i.settings.resizeContent||"boolean"==typeof i.settings.resizeContent)if("object"==typeof i.settings.resizeContent)var b="undefined"==typeof i.settings.resizeContent.enable?!0:i.settings.resizeContent.enable,l="undefined"==typeof i.settings.resizeContent.element?"ion-content":i.settings.resizeContent.element;else"boolean"==typeof i.settings.resizeContent&&(b=i.settings.resizeContent);k=o[0].parentElement.querySelectorAll(l)[0],i.$watch("ngShow",y),i.$watch("ngHide",g)}}}]),angular.module("ion-digit-keyboard",["ionic","ion-digit-keyboard.templates","ion-digit-keyboard.directive"]); \ No newline at end of file diff --git a/assets/www/js/vendor/leaflet-src.js b/assets/www/js/vendor/leaflet-src.js deleted file mode 100644 index d3d5635741c2dc68a16e0a3b72ed000ede34e3a4..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/leaflet-src.js +++ /dev/null @@ -1,9168 +0,0 @@ -/* - Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com - (c) 2010-2013, Vladimir Agafonkin - (c) 2010-2011, CloudMade -*/ -(function (window, document, undefined) { -var oldL = window.L, - L = {}; - -L.version = '0.7.7'; - -// define Leaflet for Node module pattern loaders, including Browserify -if (typeof module === 'object' && typeof module.exports === 'object') { - module.exports = L; - -// define Leaflet as an AMD module -} else if (typeof define === 'function' && define.amd) { - define(L); -} - -// define Leaflet as a global L variable, saving the original L to restore later if needed - -L.noConflict = function () { - window.L = oldL; - return this; -}; - -window.L = L; - - -/* - * L.Util contains various utility functions used throughout Leaflet code. - */ - -L.Util = { - extend: function (dest) { // (Object[, Object, ...]) -> - var sources = Array.prototype.slice.call(arguments, 1), - i, j, len, src; - - for (j = 0, len = sources.length; j < len; j++) { - src = sources[j] || {}; - for (i in src) { - if (src.hasOwnProperty(i)) { - dest[i] = src[i]; - } - } - } - return dest; - }, - - bind: function (fn, obj) { // (Function, Object) -> Function - var args = arguments.length > 2 ? Array.prototype.slice.call(arguments, 2) : null; - return function () { - return fn.apply(obj, args || arguments); - }; - }, - - stamp: (function () { - var lastId = 0, - key = '_leaflet_id'; - return function (obj) { - obj[key] = obj[key] || ++lastId; - return obj[key]; - }; - }()), - - invokeEach: function (obj, method, context) { - var i, args; - - if (typeof obj === 'object') { - args = Array.prototype.slice.call(arguments, 3); - - for (i in obj) { - method.apply(context, [i, obj[i]].concat(args)); - } - return true; - } - - return false; - }, - - limitExecByInterval: function (fn, time, context) { - var lock, execOnUnlock; - - return function wrapperFn() { - var args = arguments; - - if (lock) { - execOnUnlock = true; - return; - } - - lock = true; - - setTimeout(function () { - lock = false; - - if (execOnUnlock) { - wrapperFn.apply(context, args); - execOnUnlock = false; - } - }, time); - - fn.apply(context, args); - }; - }, - - falseFn: function () { - return false; - }, - - formatNum: function (num, digits) { - var pow = Math.pow(10, digits || 5); - return Math.round(num * pow) / pow; - }, - - trim: function (str) { - return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); - }, - - splitWords: function (str) { - return L.Util.trim(str).split(/\s+/); - }, - - setOptions: function (obj, options) { - obj.options = L.extend({}, obj.options, options); - return obj.options; - }, - - getParamString: function (obj, existingUrl, uppercase) { - var params = []; - for (var i in obj) { - params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i])); - } - return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&'); - }, - template: function (str, data) { - return str.replace(/\{ *([\w_]+) *\}/g, function (str, key) { - var value = data[key]; - if (value === undefined) { - throw new Error('No value provided for variable ' + str); - } else if (typeof value === 'function') { - value = value(data); - } - return value; - }); - }, - - isArray: Array.isArray || function (obj) { - return (Object.prototype.toString.call(obj) === '[object Array]'); - }, - - emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' -}; - -(function () { - - // inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/ - - function getPrefixed(name) { - var i, fn, - prefixes = ['webkit', 'moz', 'o', 'ms']; - - for (i = 0; i < prefixes.length && !fn; i++) { - fn = window[prefixes[i] + name]; - } - - return fn; - } - - var lastTime = 0; - - function timeoutDefer(fn) { - var time = +new Date(), - timeToCall = Math.max(0, 16 - (time - lastTime)); - - lastTime = time + timeToCall; - return window.setTimeout(fn, timeToCall); - } - - var requestFn = window.requestAnimationFrame || - getPrefixed('RequestAnimationFrame') || timeoutDefer; - - var cancelFn = window.cancelAnimationFrame || - getPrefixed('CancelAnimationFrame') || - getPrefixed('CancelRequestAnimationFrame') || - function (id) { window.clearTimeout(id); }; - - - L.Util.requestAnimFrame = function (fn, context, immediate, element) { - fn = L.bind(fn, context); - - if (immediate && requestFn === timeoutDefer) { - fn(); - } else { - return requestFn.call(window, fn, element); - } - }; - - L.Util.cancelAnimFrame = function (id) { - if (id) { - cancelFn.call(window, id); - } - }; - -}()); - -// shortcuts for most used utility functions -L.extend = L.Util.extend; -L.bind = L.Util.bind; -L.stamp = L.Util.stamp; -L.setOptions = L.Util.setOptions; - - -/* - * L.Class powers the OOP facilities of the library. - * Thanks to John Resig and Dean Edwards for inspiration! - */ - -L.Class = function () {}; - -L.Class.extend = function (props) { - - // extended class with the new prototype - var NewClass = function () { - - // call the constructor - if (this.initialize) { - this.initialize.apply(this, arguments); - } - - // call all constructor hooks - if (this._initHooks) { - this.callInitHooks(); - } - }; - - // instantiate class without calling constructor - var F = function () {}; - F.prototype = this.prototype; - - var proto = new F(); - proto.constructor = NewClass; - - NewClass.prototype = proto; - - //inherit parent's statics - for (var i in this) { - if (this.hasOwnProperty(i) && i !== 'prototype') { - NewClass[i] = this[i]; - } - } - - // mix static properties into the class - if (props.statics) { - L.extend(NewClass, props.statics); - delete props.statics; - } - - // mix includes into the prototype - if (props.includes) { - L.Util.extend.apply(null, [proto].concat(props.includes)); - delete props.includes; - } - - // merge options - if (props.options && proto.options) { - props.options = L.extend({}, proto.options, props.options); - } - - // mix given properties into the prototype - L.extend(proto, props); - - proto._initHooks = []; - - var parent = this; - // jshint camelcase: false - NewClass.__super__ = parent.prototype; - - // add method for calling all hooks - proto.callInitHooks = function () { - - if (this._initHooksCalled) { return; } - - if (parent.prototype.callInitHooks) { - parent.prototype.callInitHooks.call(this); - } - - this._initHooksCalled = true; - - for (var i = 0, len = proto._initHooks.length; i < len; i++) { - proto._initHooks[i].call(this); - } - }; - - return NewClass; -}; - - -// method for adding properties to prototype -L.Class.include = function (props) { - L.extend(this.prototype, props); -}; - -// merge new default options to the Class -L.Class.mergeOptions = function (options) { - L.extend(this.prototype.options, options); -}; - -// add a constructor hook -L.Class.addInitHook = function (fn) { // (Function) || (String, args...) - var args = Array.prototype.slice.call(arguments, 1); - - var init = typeof fn === 'function' ? fn : function () { - this[fn].apply(this, args); - }; - - this.prototype._initHooks = this.prototype._initHooks || []; - this.prototype._initHooks.push(init); -}; - - -/* - * L.Mixin.Events is used to add custom events functionality to Leaflet classes. - */ - -var eventsKey = '_leaflet_events'; - -L.Mixin = {}; - -L.Mixin.Events = { - - addEventListener: function (types, fn, context) { // (String, Function[, Object]) or (Object[, Object]) - - // types can be a map of types/handlers - if (L.Util.invokeEach(types, this.addEventListener, this, fn, context)) { return this; } - - var events = this[eventsKey] = this[eventsKey] || {}, - contextId = context && context !== this && L.stamp(context), - i, len, event, type, indexKey, indexLenKey, typeIndex; - - // types can be a string of space-separated words - types = L.Util.splitWords(types); - - for (i = 0, len = types.length; i < len; i++) { - event = { - action: fn, - context: context || this - }; - type = types[i]; - - if (contextId) { - // store listeners of a particular context in a separate hash (if it has an id) - // gives a major performance boost when removing thousands of map layers - - indexKey = type + '_idx'; - indexLenKey = indexKey + '_len'; - - typeIndex = events[indexKey] = events[indexKey] || {}; - - if (!typeIndex[contextId]) { - typeIndex[contextId] = []; - - // keep track of the number of keys in the index to quickly check if it's empty - events[indexLenKey] = (events[indexLenKey] || 0) + 1; - } - - typeIndex[contextId].push(event); - - - } else { - events[type] = events[type] || []; - events[type].push(event); - } - } - - return this; - }, - - hasEventListeners: function (type) { // (String) -> Boolean - var events = this[eventsKey]; - return !!events && ((type in events && events[type].length > 0) || - (type + '_idx' in events && events[type + '_idx_len'] > 0)); - }, - - removeEventListener: function (types, fn, context) { // ([String, Function, Object]) or (Object[, Object]) - - if (!this[eventsKey]) { - return this; - } - - if (!types) { - return this.clearAllEventListeners(); - } - - if (L.Util.invokeEach(types, this.removeEventListener, this, fn, context)) { return this; } - - var events = this[eventsKey], - contextId = context && context !== this && L.stamp(context), - i, len, type, listeners, j, indexKey, indexLenKey, typeIndex, removed; - - types = L.Util.splitWords(types); - - for (i = 0, len = types.length; i < len; i++) { - type = types[i]; - indexKey = type + '_idx'; - indexLenKey = indexKey + '_len'; - - typeIndex = events[indexKey]; - - if (!fn) { - // clear all listeners for a type if function isn't specified - delete events[type]; - delete events[indexKey]; - delete events[indexLenKey]; - - } else { - listeners = contextId && typeIndex ? typeIndex[contextId] : events[type]; - - if (listeners) { - for (j = listeners.length - 1; j >= 0; j--) { - if ((listeners[j].action === fn) && (!context || (listeners[j].context === context))) { - removed = listeners.splice(j, 1); - // set the old action to a no-op, because it is possible - // that the listener is being iterated over as part of a dispatch - removed[0].action = L.Util.falseFn; - } - } - - if (context && typeIndex && (listeners.length === 0)) { - delete typeIndex[contextId]; - events[indexLenKey]--; - } - } - } - } - - return this; - }, - - clearAllEventListeners: function () { - delete this[eventsKey]; - return this; - }, - - fireEvent: function (type, data) { // (String[, Object]) - if (!this.hasEventListeners(type)) { - return this; - } - - var event = L.Util.extend({}, data, { type: type, target: this }); - - var events = this[eventsKey], - listeners, i, len, typeIndex, contextId; - - if (events[type]) { - // make sure adding/removing listeners inside other listeners won't cause infinite loop - listeners = events[type].slice(); - - for (i = 0, len = listeners.length; i < len; i++) { - listeners[i].action.call(listeners[i].context, event); - } - } - - // fire event for the context-indexed listeners as well - typeIndex = events[type + '_idx']; - - for (contextId in typeIndex) { - listeners = typeIndex[contextId].slice(); - - if (listeners) { - for (i = 0, len = listeners.length; i < len; i++) { - listeners[i].action.call(listeners[i].context, event); - } - } - } - - return this; - }, - - addOneTimeEventListener: function (types, fn, context) { - - if (L.Util.invokeEach(types, this.addOneTimeEventListener, this, fn, context)) { return this; } - - var handler = L.bind(function () { - this - .removeEventListener(types, fn, context) - .removeEventListener(types, handler, context); - }, this); - - return this - .addEventListener(types, fn, context) - .addEventListener(types, handler, context); - } -}; - -L.Mixin.Events.on = L.Mixin.Events.addEventListener; -L.Mixin.Events.off = L.Mixin.Events.removeEventListener; -L.Mixin.Events.once = L.Mixin.Events.addOneTimeEventListener; -L.Mixin.Events.fire = L.Mixin.Events.fireEvent; - - -/* - * L.Browser handles different browser and feature detections for internal Leaflet use. - */ - -(function () { - - var ie = 'ActiveXObject' in window, - ielt9 = ie && !document.addEventListener, - - // terrible browser detection to work around Safari / iOS / Android browser bugs - ua = navigator.userAgent.toLowerCase(), - webkit = ua.indexOf('webkit') !== -1, - chrome = ua.indexOf('chrome') !== -1, - phantomjs = ua.indexOf('phantom') !== -1, - android = ua.indexOf('android') !== -1, - android23 = ua.search('android [23]') !== -1, - gecko = ua.indexOf('gecko') !== -1, - - mobile = typeof orientation !== undefined + '', - msPointer = !window.PointerEvent && window.MSPointerEvent, - pointer = (window.PointerEvent && window.navigator.pointerEnabled) || - msPointer, - retina = ('devicePixelRatio' in window && window.devicePixelRatio > 1) || - ('matchMedia' in window && window.matchMedia('(min-resolution:144dpi)') && - window.matchMedia('(min-resolution:144dpi)').matches), - - doc = document.documentElement, - ie3d = ie && ('transition' in doc.style), - webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23, - gecko3d = 'MozPerspective' in doc.style, - opera3d = 'OTransition' in doc.style, - any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d || opera3d) && !phantomjs; - - var touch = !window.L_NO_TOUCH && !phantomjs && (pointer || 'ontouchstart' in window || - (window.DocumentTouch && document instanceof window.DocumentTouch)); - - L.Browser = { - ie: ie, - ielt9: ielt9, - webkit: webkit, - gecko: gecko && !webkit && !window.opera && !ie, - - android: android, - android23: android23, - - chrome: chrome, - - ie3d: ie3d, - webkit3d: webkit3d, - gecko3d: gecko3d, - opera3d: opera3d, - any3d: any3d, - - mobile: mobile, - mobileWebkit: mobile && webkit, - mobileWebkit3d: mobile && webkit3d, - mobileOpera: mobile && window.opera, - - touch: touch, - msPointer: msPointer, - pointer: pointer, - - retina: retina - }; - -}()); - - -/* - * L.Point represents a point with x and y coordinates. - */ - -L.Point = function (/*Number*/ x, /*Number*/ y, /*Boolean*/ round) { - this.x = (round ? Math.round(x) : x); - this.y = (round ? Math.round(y) : y); -}; - -L.Point.prototype = { - - clone: function () { - return new L.Point(this.x, this.y); - }, - - // non-destructive, returns a new point - add: function (point) { - return this.clone()._add(L.point(point)); - }, - - // destructive, used directly for performance in situations where it's safe to modify existing point - _add: function (point) { - this.x += point.x; - this.y += point.y; - return this; - }, - - subtract: function (point) { - return this.clone()._subtract(L.point(point)); - }, - - _subtract: function (point) { - this.x -= point.x; - this.y -= point.y; - return this; - }, - - divideBy: function (num) { - return this.clone()._divideBy(num); - }, - - _divideBy: function (num) { - this.x /= num; - this.y /= num; - return this; - }, - - multiplyBy: function (num) { - return this.clone()._multiplyBy(num); - }, - - _multiplyBy: function (num) { - this.x *= num; - this.y *= num; - return this; - }, - - round: function () { - return this.clone()._round(); - }, - - _round: function () { - this.x = Math.round(this.x); - this.y = Math.round(this.y); - return this; - }, - - floor: function () { - return this.clone()._floor(); - }, - - _floor: function () { - this.x = Math.floor(this.x); - this.y = Math.floor(this.y); - return this; - }, - - distanceTo: function (point) { - point = L.point(point); - - var x = point.x - this.x, - y = point.y - this.y; - - return Math.sqrt(x * x + y * y); - }, - - equals: function (point) { - point = L.point(point); - - return point.x === this.x && - point.y === this.y; - }, - - contains: function (point) { - point = L.point(point); - - return Math.abs(point.x) <= Math.abs(this.x) && - Math.abs(point.y) <= Math.abs(this.y); - }, - - toString: function () { - return 'Point(' + - L.Util.formatNum(this.x) + ', ' + - L.Util.formatNum(this.y) + ')'; - } -}; - -L.point = function (x, y, round) { - if (x instanceof L.Point) { - return x; - } - if (L.Util.isArray(x)) { - return new L.Point(x[0], x[1]); - } - if (x === undefined || x === null) { - return x; - } - return new L.Point(x, y, round); -}; - - -/* - * L.Bounds represents a rectangular area on the screen in pixel coordinates. - */ - -L.Bounds = function (a, b) { //(Point, Point) or Point[] - if (!a) { return; } - - var points = b ? [a, b] : a; - - for (var i = 0, len = points.length; i < len; i++) { - this.extend(points[i]); - } -}; - -L.Bounds.prototype = { - // extend the bounds to contain the given point - extend: function (point) { // (Point) - point = L.point(point); - - if (!this.min && !this.max) { - this.min = point.clone(); - this.max = point.clone(); - } else { - this.min.x = Math.min(point.x, this.min.x); - this.max.x = Math.max(point.x, this.max.x); - this.min.y = Math.min(point.y, this.min.y); - this.max.y = Math.max(point.y, this.max.y); - } - return this; - }, - - getCenter: function (round) { // (Boolean) -> Point - return new L.Point( - (this.min.x + this.max.x) / 2, - (this.min.y + this.max.y) / 2, round); - }, - - getBottomLeft: function () { // -> Point - return new L.Point(this.min.x, this.max.y); - }, - - getTopRight: function () { // -> Point - return new L.Point(this.max.x, this.min.y); - }, - - getSize: function () { - return this.max.subtract(this.min); - }, - - contains: function (obj) { // (Bounds) or (Point) -> Boolean - var min, max; - - if (typeof obj[0] === 'number' || obj instanceof L.Point) { - obj = L.point(obj); - } else { - obj = L.bounds(obj); - } - - if (obj instanceof L.Bounds) { - min = obj.min; - max = obj.max; - } else { - min = max = obj; - } - - return (min.x >= this.min.x) && - (max.x <= this.max.x) && - (min.y >= this.min.y) && - (max.y <= this.max.y); - }, - - intersects: function (bounds) { // (Bounds) -> Boolean - bounds = L.bounds(bounds); - - var min = this.min, - max = this.max, - min2 = bounds.min, - max2 = bounds.max, - xIntersects = (max2.x >= min.x) && (min2.x <= max.x), - yIntersects = (max2.y >= min.y) && (min2.y <= max.y); - - return xIntersects && yIntersects; - }, - - isValid: function () { - return !!(this.min && this.max); - } -}; - -L.bounds = function (a, b) { // (Bounds) or (Point, Point) or (Point[]) - if (!a || a instanceof L.Bounds) { - return a; - } - return new L.Bounds(a, b); -}; - - -/* - * L.Transformation is an utility class to perform simple point transformations through a 2d-matrix. - */ - -L.Transformation = function (a, b, c, d) { - this._a = a; - this._b = b; - this._c = c; - this._d = d; -}; - -L.Transformation.prototype = { - transform: function (point, scale) { // (Point, Number) -> Point - return this._transform(point.clone(), scale); - }, - - // destructive transform (faster) - _transform: function (point, scale) { - scale = scale || 1; - point.x = scale * (this._a * point.x + this._b); - point.y = scale * (this._c * point.y + this._d); - return point; - }, - - untransform: function (point, scale) { - scale = scale || 1; - return new L.Point( - (point.x / scale - this._b) / this._a, - (point.y / scale - this._d) / this._c); - } -}; - - -/* - * L.DomUtil contains various utility functions for working with DOM. - */ - -L.DomUtil = { - get: function (id) { - return (typeof id === 'string' ? document.getElementById(id) : id); - }, - - getStyle: function (el, style) { - - var value = el.style[style]; - - if (!value && el.currentStyle) { - value = el.currentStyle[style]; - } - - if ((!value || value === 'auto') && document.defaultView) { - var css = document.defaultView.getComputedStyle(el, null); - value = css ? css[style] : null; - } - - return value === 'auto' ? null : value; - }, - - getViewportOffset: function (element) { - - var top = 0, - left = 0, - el = element, - docBody = document.body, - docEl = document.documentElement, - pos; - - do { - top += el.offsetTop || 0; - left += el.offsetLeft || 0; - - //add borders - top += parseInt(L.DomUtil.getStyle(el, 'borderTopWidth'), 10) || 0; - left += parseInt(L.DomUtil.getStyle(el, 'borderLeftWidth'), 10) || 0; - - pos = L.DomUtil.getStyle(el, 'position'); - - if (el.offsetParent === docBody && pos === 'absolute') { break; } - - if (pos === 'fixed') { - top += docBody.scrollTop || docEl.scrollTop || 0; - left += docBody.scrollLeft || docEl.scrollLeft || 0; - break; - } - - if (pos === 'relative' && !el.offsetLeft) { - var width = L.DomUtil.getStyle(el, 'width'), - maxWidth = L.DomUtil.getStyle(el, 'max-width'), - r = el.getBoundingClientRect(); - - if (width !== 'none' || maxWidth !== 'none') { - left += r.left + el.clientLeft; - } - - //calculate full y offset since we're breaking out of the loop - top += r.top + (docBody.scrollTop || docEl.scrollTop || 0); - - break; - } - - el = el.offsetParent; - - } while (el); - - el = element; - - do { - if (el === docBody) { break; } - - top -= el.scrollTop || 0; - left -= el.scrollLeft || 0; - - el = el.parentNode; - } while (el); - - return new L.Point(left, top); - }, - - documentIsLtr: function () { - if (!L.DomUtil._docIsLtrCached) { - L.DomUtil._docIsLtrCached = true; - L.DomUtil._docIsLtr = L.DomUtil.getStyle(document.body, 'direction') === 'ltr'; - } - return L.DomUtil._docIsLtr; - }, - - create: function (tagName, className, container) { - - var el = document.createElement(tagName); - el.className = className; - - if (container) { - container.appendChild(el); - } - - return el; - }, - - hasClass: function (el, name) { - if (el.classList !== undefined) { - return el.classList.contains(name); - } - var className = L.DomUtil._getClass(el); - return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className); - }, - - addClass: function (el, name) { - if (el.classList !== undefined) { - var classes = L.Util.splitWords(name); - for (var i = 0, len = classes.length; i < len; i++) { - el.classList.add(classes[i]); - } - } else if (!L.DomUtil.hasClass(el, name)) { - var className = L.DomUtil._getClass(el); - L.DomUtil._setClass(el, (className ? className + ' ' : '') + name); - } - }, - - removeClass: function (el, name) { - if (el.classList !== undefined) { - el.classList.remove(name); - } else { - L.DomUtil._setClass(el, L.Util.trim((' ' + L.DomUtil._getClass(el) + ' ').replace(' ' + name + ' ', ' '))); - } - }, - - _setClass: function (el, name) { - if (el.className.baseVal === undefined) { - el.className = name; - } else { - // in case of SVG element - el.className.baseVal = name; - } - }, - - _getClass: function (el) { - return el.className.baseVal === undefined ? el.className : el.className.baseVal; - }, - - setOpacity: function (el, value) { - - if ('opacity' in el.style) { - el.style.opacity = value; - - } else if ('filter' in el.style) { - - var filter = false, - filterName = 'DXImageTransform.Microsoft.Alpha'; - - // filters collection throws an error if we try to retrieve a filter that doesn't exist - try { - filter = el.filters.item(filterName); - } catch (e) { - // don't set opacity to 1 if we haven't already set an opacity, - // it isn't needed and breaks transparent pngs. - if (value === 1) { return; } - } - - value = Math.round(value * 100); - - if (filter) { - filter.Enabled = (value !== 100); - filter.Opacity = value; - } else { - el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')'; - } - } - }, - - testProp: function (props) { - - var style = document.documentElement.style; - - for (var i = 0; i < props.length; i++) { - if (props[i] in style) { - return props[i]; - } - } - return false; - }, - - getTranslateString: function (point) { - // on WebKit browsers (Chrome/Safari/iOS Safari/Android) using translate3d instead of translate - // makes animation smoother as it ensures HW accel is used. Firefox 13 doesn't care - // (same speed either way), Opera 12 doesn't support translate3d - - var is3d = L.Browser.webkit3d, - open = 'translate' + (is3d ? '3d' : '') + '(', - close = (is3d ? ',0' : '') + ')'; - - return open + point.x + 'px,' + point.y + 'px' + close; - }, - - getScaleString: function (scale, origin) { - - var preTranslateStr = L.DomUtil.getTranslateString(origin.add(origin.multiplyBy(-1 * scale))), - scaleStr = ' scale(' + scale + ') '; - - return preTranslateStr + scaleStr; - }, - - setPosition: function (el, point, disable3D) { // (HTMLElement, Point[, Boolean]) - - // jshint camelcase: false - el._leaflet_pos = point; - - if (!disable3D && L.Browser.any3d) { - el.style[L.DomUtil.TRANSFORM] = L.DomUtil.getTranslateString(point); - } else { - el.style.left = point.x + 'px'; - el.style.top = point.y + 'px'; - } - }, - - getPosition: function (el) { - // this method is only used for elements previously positioned using setPosition, - // so it's safe to cache the position for performance - - // jshint camelcase: false - return el._leaflet_pos; - } -}; - - -// prefix style property names - -L.DomUtil.TRANSFORM = L.DomUtil.testProp( - ['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']); - -// webkitTransition comes first because some browser versions that drop vendor prefix don't do -// the same for the transitionend event, in particular the Android 4.1 stock browser - -L.DomUtil.TRANSITION = L.DomUtil.testProp( - ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']); - -L.DomUtil.TRANSITION_END = - L.DomUtil.TRANSITION === 'webkitTransition' || L.DomUtil.TRANSITION === 'OTransition' ? - L.DomUtil.TRANSITION + 'End' : 'transitionend'; - -(function () { - if ('onselectstart' in document) { - L.extend(L.DomUtil, { - disableTextSelection: function () { - L.DomEvent.on(window, 'selectstart', L.DomEvent.preventDefault); - }, - - enableTextSelection: function () { - L.DomEvent.off(window, 'selectstart', L.DomEvent.preventDefault); - } - }); - } else { - var userSelectProperty = L.DomUtil.testProp( - ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']); - - L.extend(L.DomUtil, { - disableTextSelection: function () { - if (userSelectProperty) { - var style = document.documentElement.style; - this._userSelect = style[userSelectProperty]; - style[userSelectProperty] = 'none'; - } - }, - - enableTextSelection: function () { - if (userSelectProperty) { - document.documentElement.style[userSelectProperty] = this._userSelect; - delete this._userSelect; - } - } - }); - } - - L.extend(L.DomUtil, { - disableImageDrag: function () { - L.DomEvent.on(window, 'dragstart', L.DomEvent.preventDefault); - }, - - enableImageDrag: function () { - L.DomEvent.off(window, 'dragstart', L.DomEvent.preventDefault); - } - }); -})(); - - -/* - * L.LatLng represents a geographical point with latitude and longitude coordinates. - */ - -L.LatLng = function (lat, lng, alt) { // (Number, Number, Number) - lat = parseFloat(lat); - lng = parseFloat(lng); - - if (isNaN(lat) || isNaN(lng)) { - throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); - } - - this.lat = lat; - this.lng = lng; - - if (alt !== undefined) { - this.alt = parseFloat(alt); - } -}; - -L.extend(L.LatLng, { - DEG_TO_RAD: Math.PI / 180, - RAD_TO_DEG: 180 / Math.PI, - MAX_MARGIN: 1.0E-9 // max margin of error for the "equals" check -}); - -L.LatLng.prototype = { - equals: function (obj) { // (LatLng) -> Boolean - if (!obj) { return false; } - - obj = L.latLng(obj); - - var margin = Math.max( - Math.abs(this.lat - obj.lat), - Math.abs(this.lng - obj.lng)); - - return margin <= L.LatLng.MAX_MARGIN; - }, - - toString: function (precision) { // (Number) -> String - return 'LatLng(' + - L.Util.formatNum(this.lat, precision) + ', ' + - L.Util.formatNum(this.lng, precision) + ')'; - }, - - // Haversine distance formula, see http://en.wikipedia.org/wiki/Haversine_formula - // TODO move to projection code, LatLng shouldn't know about Earth - distanceTo: function (other) { // (LatLng) -> Number - other = L.latLng(other); - - var R = 6378137, // earth radius in meters - d2r = L.LatLng.DEG_TO_RAD, - dLat = (other.lat - this.lat) * d2r, - dLon = (other.lng - this.lng) * d2r, - lat1 = this.lat * d2r, - lat2 = other.lat * d2r, - sin1 = Math.sin(dLat / 2), - sin2 = Math.sin(dLon / 2); - - var a = sin1 * sin1 + sin2 * sin2 * Math.cos(lat1) * Math.cos(lat2); - - return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); - }, - - wrap: function (a, b) { // (Number, Number) -> LatLng - var lng = this.lng; - - a = a || -180; - b = b || 180; - - lng = (lng + b) % (b - a) + (lng < a || lng === b ? b : a); - - return new L.LatLng(this.lat, lng); - } -}; - -L.latLng = function (a, b) { // (LatLng) or ([Number, Number]) or (Number, Number) - if (a instanceof L.LatLng) { - return a; - } - if (L.Util.isArray(a)) { - if (typeof a[0] === 'number' || typeof a[0] === 'string') { - return new L.LatLng(a[0], a[1], a[2]); - } else { - return null; - } - } - if (a === undefined || a === null) { - return a; - } - if (typeof a === 'object' && 'lat' in a) { - return new L.LatLng(a.lat, 'lng' in a ? a.lng : a.lon); - } - if (b === undefined) { - return null; - } - return new L.LatLng(a, b); -}; - - - -/* - * L.LatLngBounds represents a rectangular area on the map in geographical coordinates. - */ - -L.LatLngBounds = function (southWest, northEast) { // (LatLng, LatLng) or (LatLng[]) - if (!southWest) { return; } - - var latlngs = northEast ? [southWest, northEast] : southWest; - - for (var i = 0, len = latlngs.length; i < len; i++) { - this.extend(latlngs[i]); - } -}; - -L.LatLngBounds.prototype = { - // extend the bounds to contain the given point or bounds - extend: function (obj) { // (LatLng) or (LatLngBounds) - if (!obj) { return this; } - - var latLng = L.latLng(obj); - if (latLng !== null) { - obj = latLng; - } else { - obj = L.latLngBounds(obj); - } - - if (obj instanceof L.LatLng) { - if (!this._southWest && !this._northEast) { - this._southWest = new L.LatLng(obj.lat, obj.lng); - this._northEast = new L.LatLng(obj.lat, obj.lng); - } else { - this._southWest.lat = Math.min(obj.lat, this._southWest.lat); - this._southWest.lng = Math.min(obj.lng, this._southWest.lng); - - this._northEast.lat = Math.max(obj.lat, this._northEast.lat); - this._northEast.lng = Math.max(obj.lng, this._northEast.lng); - } - } else if (obj instanceof L.LatLngBounds) { - this.extend(obj._southWest); - this.extend(obj._northEast); - } - return this; - }, - - // extend the bounds by a percentage - pad: function (bufferRatio) { // (Number) -> LatLngBounds - var sw = this._southWest, - ne = this._northEast, - heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio, - widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio; - - return new L.LatLngBounds( - new L.LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer), - new L.LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer)); - }, - - getCenter: function () { // -> LatLng - return new L.LatLng( - (this._southWest.lat + this._northEast.lat) / 2, - (this._southWest.lng + this._northEast.lng) / 2); - }, - - getSouthWest: function () { - return this._southWest; - }, - - getNorthEast: function () { - return this._northEast; - }, - - getNorthWest: function () { - return new L.LatLng(this.getNorth(), this.getWest()); - }, - - getSouthEast: function () { - return new L.LatLng(this.getSouth(), this.getEast()); - }, - - getWest: function () { - return this._southWest.lng; - }, - - getSouth: function () { - return this._southWest.lat; - }, - - getEast: function () { - return this._northEast.lng; - }, - - getNorth: function () { - return this._northEast.lat; - }, - - contains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean - if (typeof obj[0] === 'number' || obj instanceof L.LatLng) { - obj = L.latLng(obj); - } else { - obj = L.latLngBounds(obj); - } - - var sw = this._southWest, - ne = this._northEast, - sw2, ne2; - - if (obj instanceof L.LatLngBounds) { - sw2 = obj.getSouthWest(); - ne2 = obj.getNorthEast(); - } else { - sw2 = ne2 = obj; - } - - return (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) && - (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng); - }, - - intersects: function (bounds) { // (LatLngBounds) - bounds = L.latLngBounds(bounds); - - var sw = this._southWest, - ne = this._northEast, - sw2 = bounds.getSouthWest(), - ne2 = bounds.getNorthEast(), - - latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat), - lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng); - - return latIntersects && lngIntersects; - }, - - toBBoxString: function () { - return [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(','); - }, - - equals: function (bounds) { // (LatLngBounds) - if (!bounds) { return false; } - - bounds = L.latLngBounds(bounds); - - return this._southWest.equals(bounds.getSouthWest()) && - this._northEast.equals(bounds.getNorthEast()); - }, - - isValid: function () { - return !!(this._southWest && this._northEast); - } -}; - -//TODO International date line? - -L.latLngBounds = function (a, b) { // (LatLngBounds) or (LatLng, LatLng) - if (!a || a instanceof L.LatLngBounds) { - return a; - } - return new L.LatLngBounds(a, b); -}; - - -/* - * L.Projection contains various geographical projections used by CRS classes. - */ - -L.Projection = {}; - - -/* - * Spherical Mercator is the most popular map projection, used by EPSG:3857 CRS used by default. - */ - -L.Projection.SphericalMercator = { - MAX_LATITUDE: 85.0511287798, - - project: function (latlng) { // (LatLng) -> Point - var d = L.LatLng.DEG_TO_RAD, - max = this.MAX_LATITUDE, - lat = Math.max(Math.min(max, latlng.lat), -max), - x = latlng.lng * d, - y = lat * d; - - y = Math.log(Math.tan((Math.PI / 4) + (y / 2))); - - return new L.Point(x, y); - }, - - unproject: function (point) { // (Point, Boolean) -> LatLng - var d = L.LatLng.RAD_TO_DEG, - lng = point.x * d, - lat = (2 * Math.atan(Math.exp(point.y)) - (Math.PI / 2)) * d; - - return new L.LatLng(lat, lng); - } -}; - - -/* - * Simple equirectangular (Plate Carree) projection, used by CRS like EPSG:4326 and Simple. - */ - -L.Projection.LonLat = { - project: function (latlng) { - return new L.Point(latlng.lng, latlng.lat); - }, - - unproject: function (point) { - return new L.LatLng(point.y, point.x); - } -}; - - -/* - * L.CRS is a base object for all defined CRS (Coordinate Reference Systems) in Leaflet. - */ - -L.CRS = { - latLngToPoint: function (latlng, zoom) { // (LatLng, Number) -> Point - var projectedPoint = this.projection.project(latlng), - scale = this.scale(zoom); - - return this.transformation._transform(projectedPoint, scale); - }, - - pointToLatLng: function (point, zoom) { // (Point, Number[, Boolean]) -> LatLng - var scale = this.scale(zoom), - untransformedPoint = this.transformation.untransform(point, scale); - - return this.projection.unproject(untransformedPoint); - }, - - project: function (latlng) { - return this.projection.project(latlng); - }, - - scale: function (zoom) { - return 256 * Math.pow(2, zoom); - }, - - getSize: function (zoom) { - var s = this.scale(zoom); - return L.point(s, s); - } -}; - - -/* - * A simple CRS that can be used for flat non-Earth maps like panoramas or game maps. - */ - -L.CRS.Simple = L.extend({}, L.CRS, { - projection: L.Projection.LonLat, - transformation: new L.Transformation(1, 0, -1, 0), - - scale: function (zoom) { - return Math.pow(2, zoom); - } -}); - - -/* - * L.CRS.EPSG3857 (Spherical Mercator) is the most common CRS for web mapping - * and is used by Leaflet by default. - */ - -L.CRS.EPSG3857 = L.extend({}, L.CRS, { - code: 'EPSG:3857', - - projection: L.Projection.SphericalMercator, - transformation: new L.Transformation(0.5 / Math.PI, 0.5, -0.5 / Math.PI, 0.5), - - project: function (latlng) { // (LatLng) -> Point - var projectedPoint = this.projection.project(latlng), - earthRadius = 6378137; - return projectedPoint.multiplyBy(earthRadius); - } -}); - -L.CRS.EPSG900913 = L.extend({}, L.CRS.EPSG3857, { - code: 'EPSG:900913' -}); - - -/* - * L.CRS.EPSG4326 is a CRS popular among advanced GIS specialists. - */ - -L.CRS.EPSG4326 = L.extend({}, L.CRS, { - code: 'EPSG:4326', - - projection: L.Projection.LonLat, - transformation: new L.Transformation(1 / 360, 0.5, -1 / 360, 0.5) -}); - - -/* - * L.Map is the central class of the API - it is used to create a map. - */ - -L.Map = L.Class.extend({ - - includes: L.Mixin.Events, - - options: { - crs: L.CRS.EPSG3857, - - /* - center: LatLng, - zoom: Number, - layers: Array, - */ - - fadeAnimation: L.DomUtil.TRANSITION && !L.Browser.android23, - trackResize: true, - markerZoomAnimation: L.DomUtil.TRANSITION && L.Browser.any3d - }, - - initialize: function (id, options) { // (HTMLElement or String, Object) - options = L.setOptions(this, options); - - - this._initContainer(id); - this._initLayout(); - - // hack for https://github.com/Leaflet/Leaflet/issues/1980 - this._onResize = L.bind(this._onResize, this); - - this._initEvents(); - - if (options.maxBounds) { - this.setMaxBounds(options.maxBounds); - } - - if (options.center && options.zoom !== undefined) { - this.setView(L.latLng(options.center), options.zoom, {reset: true}); - } - - this._handlers = []; - - this._layers = {}; - this._zoomBoundLayers = {}; - this._tileLayersNum = 0; - - this.callInitHooks(); - - this._addLayers(options.layers); - }, - - - // public methods that modify map state - - // replaced by animation-powered implementation in Map.PanAnimation.js - setView: function (center, zoom) { - zoom = zoom === undefined ? this.getZoom() : zoom; - this._resetView(L.latLng(center), this._limitZoom(zoom)); - return this; - }, - - setZoom: function (zoom, options) { - if (!this._loaded) { - this._zoom = this._limitZoom(zoom); - return this; - } - return this.setView(this.getCenter(), zoom, {zoom: options}); - }, - - zoomIn: function (delta, options) { - return this.setZoom(this._zoom + (delta || 1), options); - }, - - zoomOut: function (delta, options) { - return this.setZoom(this._zoom - (delta || 1), options); - }, - - setZoomAround: function (latlng, zoom, options) { - var scale = this.getZoomScale(zoom), - viewHalf = this.getSize().divideBy(2), - containerPoint = latlng instanceof L.Point ? latlng : this.latLngToContainerPoint(latlng), - - centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale), - newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset)); - - return this.setView(newCenter, zoom, {zoom: options}); - }, - - fitBounds: function (bounds, options) { - - options = options || {}; - bounds = bounds.getBounds ? bounds.getBounds() : L.latLngBounds(bounds); - - var paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]), - paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]), - - zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR)); - - zoom = (options.maxZoom) ? Math.min(options.maxZoom, zoom) : zoom; - - var paddingOffset = paddingBR.subtract(paddingTL).divideBy(2), - - swPoint = this.project(bounds.getSouthWest(), zoom), - nePoint = this.project(bounds.getNorthEast(), zoom), - center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom); - - return this.setView(center, zoom, options); - }, - - fitWorld: function (options) { - return this.fitBounds([[-90, -180], [90, 180]], options); - }, - - panTo: function (center, options) { // (LatLng) - return this.setView(center, this._zoom, {pan: options}); - }, - - panBy: function (offset) { // (Point) - // replaced with animated panBy in Map.PanAnimation.js - this.fire('movestart'); - - this._rawPanBy(L.point(offset)); - - this.fire('move'); - return this.fire('moveend'); - }, - - setMaxBounds: function (bounds) { - bounds = L.latLngBounds(bounds); - - this.options.maxBounds = bounds; - - if (!bounds) { - return this.off('moveend', this._panInsideMaxBounds, this); - } - - if (this._loaded) { - this._panInsideMaxBounds(); - } - - return this.on('moveend', this._panInsideMaxBounds, this); - }, - - panInsideBounds: function (bounds, options) { - var center = this.getCenter(), - newCenter = this._limitCenter(center, this._zoom, bounds); - - if (center.equals(newCenter)) { return this; } - - return this.panTo(newCenter, options); - }, - - addLayer: function (layer) { - // TODO method is too big, refactor - - var id = L.stamp(layer); - - if (this._layers[id]) { return this; } - - this._layers[id] = layer; - - // TODO getMaxZoom, getMinZoom in ILayer (instead of options) - if (layer.options && (!isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom))) { - this._zoomBoundLayers[id] = layer; - this._updateZoomLevels(); - } - - // TODO looks ugly, refactor!!! - if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) { - this._tileLayersNum++; - this._tileLayersToLoad++; - layer.on('load', this._onTileLayerLoad, this); - } - - if (this._loaded) { - this._layerAdd(layer); - } - - return this; - }, - - removeLayer: function (layer) { - var id = L.stamp(layer); - - if (!this._layers[id]) { return this; } - - if (this._loaded) { - layer.onRemove(this); - } - - delete this._layers[id]; - - if (this._loaded) { - this.fire('layerremove', {layer: layer}); - } - - if (this._zoomBoundLayers[id]) { - delete this._zoomBoundLayers[id]; - this._updateZoomLevels(); - } - - // TODO looks ugly, refactor - if (this.options.zoomAnimation && L.TileLayer && (layer instanceof L.TileLayer)) { - this._tileLayersNum--; - this._tileLayersToLoad--; - layer.off('load', this._onTileLayerLoad, this); - } - - return this; - }, - - hasLayer: function (layer) { - if (!layer) { return false; } - - return (L.stamp(layer) in this._layers); - }, - - eachLayer: function (method, context) { - for (var i in this._layers) { - method.call(context, this._layers[i]); - } - return this; - }, - - invalidateSize: function (options) { - if (!this._loaded) { return this; } - - options = L.extend({ - animate: false, - pan: true - }, options === true ? {animate: true} : options); - - var oldSize = this.getSize(); - this._sizeChanged = true; - this._initialCenter = null; - - var newSize = this.getSize(), - oldCenter = oldSize.divideBy(2).round(), - newCenter = newSize.divideBy(2).round(), - offset = oldCenter.subtract(newCenter); - - if (!offset.x && !offset.y) { return this; } - - if (options.animate && options.pan) { - this.panBy(offset); - - } else { - if (options.pan) { - this._rawPanBy(offset); - } - - this.fire('move'); - - if (options.debounceMoveend) { - clearTimeout(this._sizeTimer); - this._sizeTimer = setTimeout(L.bind(this.fire, this, 'moveend'), 200); - } else { - this.fire('moveend'); - } - } - - return this.fire('resize', { - oldSize: oldSize, - newSize: newSize - }); - }, - - // TODO handler.addTo - addHandler: function (name, HandlerClass) { - if (!HandlerClass) { return this; } - - var handler = this[name] = new HandlerClass(this); - - this._handlers.push(handler); - - if (this.options[name]) { - handler.enable(); - } - - return this; - }, - - remove: function () { - if (this._loaded) { - this.fire('unload'); - } - - this._initEvents('off'); - - try { - // throws error in IE6-8 - delete this._container._leaflet; - } catch (e) { - this._container._leaflet = undefined; - } - - this._clearPanes(); - if (this._clearControlPos) { - this._clearControlPos(); - } - - this._clearHandlers(); - - return this; - }, - - - // public methods for getting map state - - getCenter: function () { // (Boolean) -> LatLng - this._checkIfLoaded(); - - if (this._initialCenter && !this._moved()) { - return this._initialCenter; - } - return this.layerPointToLatLng(this._getCenterLayerPoint()); - }, - - getZoom: function () { - return this._zoom; - }, - - getBounds: function () { - var bounds = this.getPixelBounds(), - sw = this.unproject(bounds.getBottomLeft()), - ne = this.unproject(bounds.getTopRight()); - - return new L.LatLngBounds(sw, ne); - }, - - getMinZoom: function () { - return this.options.minZoom === undefined ? - (this._layersMinZoom === undefined ? 0 : this._layersMinZoom) : - this.options.minZoom; - }, - - getMaxZoom: function () { - return this.options.maxZoom === undefined ? - (this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) : - this.options.maxZoom; - }, - - getBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number - bounds = L.latLngBounds(bounds); - - var zoom = this.getMinZoom() - (inside ? 1 : 0), - maxZoom = this.getMaxZoom(), - size = this.getSize(), - - nw = bounds.getNorthWest(), - se = bounds.getSouthEast(), - - zoomNotFound = true, - boundsSize; - - padding = L.point(padding || [0, 0]); - - do { - zoom++; - boundsSize = this.project(se, zoom).subtract(this.project(nw, zoom)).add(padding); - zoomNotFound = !inside ? size.contains(boundsSize) : boundsSize.x < size.x || boundsSize.y < size.y; - - } while (zoomNotFound && zoom <= maxZoom); - - if (zoomNotFound && inside) { - return null; - } - - return inside ? zoom : zoom - 1; - }, - - getSize: function () { - if (!this._size || this._sizeChanged) { - this._size = new L.Point( - this._container.clientWidth, - this._container.clientHeight); - - this._sizeChanged = false; - } - return this._size.clone(); - }, - - getPixelBounds: function () { - var topLeftPoint = this._getTopLeftPoint(); - return new L.Bounds(topLeftPoint, topLeftPoint.add(this.getSize())); - }, - - getPixelOrigin: function () { - this._checkIfLoaded(); - return this._initialTopLeftPoint; - }, - - getPanes: function () { - return this._panes; - }, - - getContainer: function () { - return this._container; - }, - - - // TODO replace with universal implementation after refactoring projections - - getZoomScale: function (toZoom) { - var crs = this.options.crs; - return crs.scale(toZoom) / crs.scale(this._zoom); - }, - - getScaleZoom: function (scale) { - return this._zoom + (Math.log(scale) / Math.LN2); - }, - - - // conversion methods - - project: function (latlng, zoom) { // (LatLng[, Number]) -> Point - zoom = zoom === undefined ? this._zoom : zoom; - return this.options.crs.latLngToPoint(L.latLng(latlng), zoom); - }, - - unproject: function (point, zoom) { // (Point[, Number]) -> LatLng - zoom = zoom === undefined ? this._zoom : zoom; - return this.options.crs.pointToLatLng(L.point(point), zoom); - }, - - layerPointToLatLng: function (point) { // (Point) - var projectedPoint = L.point(point).add(this.getPixelOrigin()); - return this.unproject(projectedPoint); - }, - - latLngToLayerPoint: function (latlng) { // (LatLng) - var projectedPoint = this.project(L.latLng(latlng))._round(); - return projectedPoint._subtract(this.getPixelOrigin()); - }, - - containerPointToLayerPoint: function (point) { // (Point) - return L.point(point).subtract(this._getMapPanePos()); - }, - - layerPointToContainerPoint: function (point) { // (Point) - return L.point(point).add(this._getMapPanePos()); - }, - - containerPointToLatLng: function (point) { - var layerPoint = this.containerPointToLayerPoint(L.point(point)); - return this.layerPointToLatLng(layerPoint); - }, - - latLngToContainerPoint: function (latlng) { - return this.layerPointToContainerPoint(this.latLngToLayerPoint(L.latLng(latlng))); - }, - - mouseEventToContainerPoint: function (e) { // (MouseEvent) - return L.DomEvent.getMousePosition(e, this._container); - }, - - mouseEventToLayerPoint: function (e) { // (MouseEvent) - return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e)); - }, - - mouseEventToLatLng: function (e) { // (MouseEvent) - return this.layerPointToLatLng(this.mouseEventToLayerPoint(e)); - }, - - - // map initialization methods - - _initContainer: function (id) { - var container = this._container = L.DomUtil.get(id); - - if (!container) { - throw new Error('Map container not found.'); - } else if (container._leaflet) { - throw new Error('Map container is already initialized.'); - } - - container._leaflet = true; - }, - - _initLayout: function () { - var container = this._container; - - L.DomUtil.addClass(container, 'leaflet-container' + - (L.Browser.touch ? ' leaflet-touch' : '') + - (L.Browser.retina ? ' leaflet-retina' : '') + - (L.Browser.ielt9 ? ' leaflet-oldie' : '') + - (this.options.fadeAnimation ? ' leaflet-fade-anim' : '')); - - var position = L.DomUtil.getStyle(container, 'position'); - - if (position !== 'absolute' && position !== 'relative' && position !== 'fixed') { - container.style.position = 'relative'; - } - - this._initPanes(); - - if (this._initControlPos) { - this._initControlPos(); - } - }, - - _initPanes: function () { - var panes = this._panes = {}; - - this._mapPane = panes.mapPane = this._createPane('leaflet-map-pane', this._container); - - this._tilePane = panes.tilePane = this._createPane('leaflet-tile-pane', this._mapPane); - panes.objectsPane = this._createPane('leaflet-objects-pane', this._mapPane); - panes.shadowPane = this._createPane('leaflet-shadow-pane'); - panes.overlayPane = this._createPane('leaflet-overlay-pane'); - panes.markerPane = this._createPane('leaflet-marker-pane'); - panes.popupPane = this._createPane('leaflet-popup-pane'); - - var zoomHide = ' leaflet-zoom-hide'; - - if (!this.options.markerZoomAnimation) { - L.DomUtil.addClass(panes.markerPane, zoomHide); - L.DomUtil.addClass(panes.shadowPane, zoomHide); - L.DomUtil.addClass(panes.popupPane, zoomHide); - } - }, - - _createPane: function (className, container) { - return L.DomUtil.create('div', className, container || this._panes.objectsPane); - }, - - _clearPanes: function () { - this._container.removeChild(this._mapPane); - }, - - _addLayers: function (layers) { - layers = layers ? (L.Util.isArray(layers) ? layers : [layers]) : []; - - for (var i = 0, len = layers.length; i < len; i++) { - this.addLayer(layers[i]); - } - }, - - - // private methods that modify map state - - _resetView: function (center, zoom, preserveMapOffset, afterZoomAnim) { - - var zoomChanged = (this._zoom !== zoom); - - if (!afterZoomAnim) { - this.fire('movestart'); - - if (zoomChanged) { - this.fire('zoomstart'); - } - } - - this._zoom = zoom; - this._initialCenter = center; - - this._initialTopLeftPoint = this._getNewTopLeftPoint(center); - - if (!preserveMapOffset) { - L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0)); - } else { - this._initialTopLeftPoint._add(this._getMapPanePos()); - } - - this._tileLayersToLoad = this._tileLayersNum; - - var loading = !this._loaded; - this._loaded = true; - - this.fire('viewreset', {hard: !preserveMapOffset}); - - if (loading) { - this.fire('load'); - this.eachLayer(this._layerAdd, this); - } - - this.fire('move'); - - if (zoomChanged || afterZoomAnim) { - this.fire('zoomend'); - } - - this.fire('moveend', {hard: !preserveMapOffset}); - }, - - _rawPanBy: function (offset) { - L.DomUtil.setPosition(this._mapPane, this._getMapPanePos().subtract(offset)); - }, - - _getZoomSpan: function () { - return this.getMaxZoom() - this.getMinZoom(); - }, - - _updateZoomLevels: function () { - var i, - minZoom = Infinity, - maxZoom = -Infinity, - oldZoomSpan = this._getZoomSpan(); - - for (i in this._zoomBoundLayers) { - var layer = this._zoomBoundLayers[i]; - if (!isNaN(layer.options.minZoom)) { - minZoom = Math.min(minZoom, layer.options.minZoom); - } - if (!isNaN(layer.options.maxZoom)) { - maxZoom = Math.max(maxZoom, layer.options.maxZoom); - } - } - - if (i === undefined) { // we have no tilelayers - this._layersMaxZoom = this._layersMinZoom = undefined; - } else { - this._layersMaxZoom = maxZoom; - this._layersMinZoom = minZoom; - } - - if (oldZoomSpan !== this._getZoomSpan()) { - this.fire('zoomlevelschange'); - } - }, - - _panInsideMaxBounds: function () { - this.panInsideBounds(this.options.maxBounds); - }, - - _checkIfLoaded: function () { - if (!this._loaded) { - throw new Error('Set map center and zoom first.'); - } - }, - - // map events - - _initEvents: function (onOff) { - if (!L.DomEvent) { return; } - - onOff = onOff || 'on'; - - L.DomEvent[onOff](this._container, 'click', this._onMouseClick, this); - - var events = ['dblclick', 'mousedown', 'mouseup', 'mouseenter', - 'mouseleave', 'mousemove', 'contextmenu'], - i, len; - - for (i = 0, len = events.length; i < len; i++) { - L.DomEvent[onOff](this._container, events[i], this._fireMouseEvent, this); - } - - if (this.options.trackResize) { - L.DomEvent[onOff](window, 'resize', this._onResize, this); - } - }, - - _onResize: function () { - L.Util.cancelAnimFrame(this._resizeRequest); - this._resizeRequest = L.Util.requestAnimFrame( - function () { this.invalidateSize({debounceMoveend: true}); }, this, false, this._container); - }, - - _onMouseClick: function (e) { - if (!this._loaded || (!e._simulated && - ((this.dragging && this.dragging.moved()) || - (this.boxZoom && this.boxZoom.moved()))) || - L.DomEvent._skipped(e)) { return; } - - this.fire('preclick'); - this._fireMouseEvent(e); - }, - - _fireMouseEvent: function (e) { - if (!this._loaded || L.DomEvent._skipped(e)) { return; } - - var type = e.type; - - type = (type === 'mouseenter' ? 'mouseover' : (type === 'mouseleave' ? 'mouseout' : type)); - - if (!this.hasEventListeners(type)) { return; } - - if (type === 'contextmenu') { - L.DomEvent.preventDefault(e); - } - - var containerPoint = this.mouseEventToContainerPoint(e), - layerPoint = this.containerPointToLayerPoint(containerPoint), - latlng = this.layerPointToLatLng(layerPoint); - - this.fire(type, { - latlng: latlng, - layerPoint: layerPoint, - containerPoint: containerPoint, - originalEvent: e - }); - }, - - _onTileLayerLoad: function () { - this._tileLayersToLoad--; - if (this._tileLayersNum && !this._tileLayersToLoad) { - this.fire('tilelayersload'); - } - }, - - _clearHandlers: function () { - for (var i = 0, len = this._handlers.length; i < len; i++) { - this._handlers[i].disable(); - } - }, - - whenReady: function (callback, context) { - if (this._loaded) { - callback.call(context || this, this); - } else { - this.on('load', callback, context); - } - return this; - }, - - _layerAdd: function (layer) { - layer.onAdd(this); - this.fire('layeradd', {layer: layer}); - }, - - - // private methods for getting map state - - _getMapPanePos: function () { - return L.DomUtil.getPosition(this._mapPane); - }, - - _moved: function () { - var pos = this._getMapPanePos(); - return pos && !pos.equals([0, 0]); - }, - - _getTopLeftPoint: function () { - return this.getPixelOrigin().subtract(this._getMapPanePos()); - }, - - _getNewTopLeftPoint: function (center, zoom) { - var viewHalf = this.getSize()._divideBy(2); - // TODO round on display, not calculation to increase precision? - return this.project(center, zoom)._subtract(viewHalf)._round(); - }, - - _latLngToNewLayerPoint: function (latlng, newZoom, newCenter) { - var topLeft = this._getNewTopLeftPoint(newCenter, newZoom).add(this._getMapPanePos()); - return this.project(latlng, newZoom)._subtract(topLeft); - }, - - // layer point of the current center - _getCenterLayerPoint: function () { - return this.containerPointToLayerPoint(this.getSize()._divideBy(2)); - }, - - // offset of the specified place to the current center in pixels - _getCenterOffset: function (latlng) { - return this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint()); - }, - - // adjust center for view to get inside bounds - _limitCenter: function (center, zoom, bounds) { - - if (!bounds) { return center; } - - var centerPoint = this.project(center, zoom), - viewHalf = this.getSize().divideBy(2), - viewBounds = new L.Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)), - offset = this._getBoundsOffset(viewBounds, bounds, zoom); - - return this.unproject(centerPoint.add(offset), zoom); - }, - - // adjust offset for view to get inside bounds - _limitOffset: function (offset, bounds) { - if (!bounds) { return offset; } - - var viewBounds = this.getPixelBounds(), - newBounds = new L.Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset)); - - return offset.add(this._getBoundsOffset(newBounds, bounds)); - }, - - // returns offset needed for pxBounds to get inside maxBounds at a specified zoom - _getBoundsOffset: function (pxBounds, maxBounds, zoom) { - var nwOffset = this.project(maxBounds.getNorthWest(), zoom).subtract(pxBounds.min), - seOffset = this.project(maxBounds.getSouthEast(), zoom).subtract(pxBounds.max), - - dx = this._rebound(nwOffset.x, -seOffset.x), - dy = this._rebound(nwOffset.y, -seOffset.y); - - return new L.Point(dx, dy); - }, - - _rebound: function (left, right) { - return left + right > 0 ? - Math.round(left - right) / 2 : - Math.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right)); - }, - - _limitZoom: function (zoom) { - var min = this.getMinZoom(), - max = this.getMaxZoom(); - - return Math.max(min, Math.min(max, zoom)); - } -}); - -L.map = function (id, options) { - return new L.Map(id, options); -}; - - -/* - * Mercator projection that takes into account that the Earth is not a perfect sphere. - * Less popular than spherical mercator; used by projections like EPSG:3395. - */ - -L.Projection.Mercator = { - MAX_LATITUDE: 85.0840591556, - - R_MINOR: 6356752.314245179, - R_MAJOR: 6378137, - - project: function (latlng) { // (LatLng) -> Point - var d = L.LatLng.DEG_TO_RAD, - max = this.MAX_LATITUDE, - lat = Math.max(Math.min(max, latlng.lat), -max), - r = this.R_MAJOR, - r2 = this.R_MINOR, - x = latlng.lng * d * r, - y = lat * d, - tmp = r2 / r, - eccent = Math.sqrt(1.0 - tmp * tmp), - con = eccent * Math.sin(y); - - con = Math.pow((1 - con) / (1 + con), eccent * 0.5); - - var ts = Math.tan(0.5 * ((Math.PI * 0.5) - y)) / con; - y = -r * Math.log(ts); - - return new L.Point(x, y); - }, - - unproject: function (point) { // (Point, Boolean) -> LatLng - var d = L.LatLng.RAD_TO_DEG, - r = this.R_MAJOR, - r2 = this.R_MINOR, - lng = point.x * d / r, - tmp = r2 / r, - eccent = Math.sqrt(1 - (tmp * tmp)), - ts = Math.exp(- point.y / r), - phi = (Math.PI / 2) - 2 * Math.atan(ts), - numIter = 15, - tol = 1e-7, - i = numIter, - dphi = 0.1, - con; - - while ((Math.abs(dphi) > tol) && (--i > 0)) { - con = eccent * Math.sin(phi); - dphi = (Math.PI / 2) - 2 * Math.atan(ts * - Math.pow((1.0 - con) / (1.0 + con), 0.5 * eccent)) - phi; - phi += dphi; - } - - return new L.LatLng(phi * d, lng); - } -}; - - - -L.CRS.EPSG3395 = L.extend({}, L.CRS, { - code: 'EPSG:3395', - - projection: L.Projection.Mercator, - - transformation: (function () { - var m = L.Projection.Mercator, - r = m.R_MAJOR, - scale = 0.5 / (Math.PI * r); - - return new L.Transformation(scale, 0.5, -scale, 0.5); - }()) -}); - - -/* - * L.TileLayer is used for standard xyz-numbered tile layers. - */ - -L.TileLayer = L.Class.extend({ - includes: L.Mixin.Events, - - options: { - minZoom: 0, - maxZoom: 18, - tileSize: 256, - subdomains: 'abc', - errorTileUrl: '', - attribution: '', - zoomOffset: 0, - opacity: 1, - /* - maxNativeZoom: null, - zIndex: null, - tms: false, - continuousWorld: false, - noWrap: false, - zoomReverse: false, - detectRetina: false, - reuseTiles: false, - bounds: false, - */ - unloadInvisibleTiles: L.Browser.mobile, - updateWhenIdle: L.Browser.mobile - }, - - initialize: function (url, options) { - options = L.setOptions(this, options); - - // detecting retina displays, adjusting tileSize and zoom levels - if (options.detectRetina && L.Browser.retina && options.maxZoom > 0) { - - options.tileSize = Math.floor(options.tileSize / 2); - options.zoomOffset++; - - if (options.minZoom > 0) { - options.minZoom--; - } - this.options.maxZoom--; - } - - if (options.bounds) { - options.bounds = L.latLngBounds(options.bounds); - } - - this._url = url; - - var subdomains = this.options.subdomains; - - if (typeof subdomains === 'string') { - this.options.subdomains = subdomains.split(''); - } - }, - - onAdd: function (map) { - this._map = map; - this._animated = map._zoomAnimated; - - // create a container div for tiles - this._initContainer(); - - // set up events - map.on({ - 'viewreset': this._reset, - 'moveend': this._update - }, this); - - if (this._animated) { - map.on({ - 'zoomanim': this._animateZoom, - 'zoomend': this._endZoomAnim - }, this); - } - - if (!this.options.updateWhenIdle) { - this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this); - map.on('move', this._limitedUpdate, this); - } - - this._reset(); - this._update(); - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - onRemove: function (map) { - this._container.parentNode.removeChild(this._container); - - map.off({ - 'viewreset': this._reset, - 'moveend': this._update - }, this); - - if (this._animated) { - map.off({ - 'zoomanim': this._animateZoom, - 'zoomend': this._endZoomAnim - }, this); - } - - if (!this.options.updateWhenIdle) { - map.off('move', this._limitedUpdate, this); - } - - this._container = null; - this._map = null; - }, - - bringToFront: function () { - var pane = this._map._panes.tilePane; - - if (this._container) { - pane.appendChild(this._container); - this._setAutoZIndex(pane, Math.max); - } - - return this; - }, - - bringToBack: function () { - var pane = this._map._panes.tilePane; - - if (this._container) { - pane.insertBefore(this._container, pane.firstChild); - this._setAutoZIndex(pane, Math.min); - } - - return this; - }, - - getAttribution: function () { - return this.options.attribution; - }, - - getContainer: function () { - return this._container; - }, - - setOpacity: function (opacity) { - this.options.opacity = opacity; - - if (this._map) { - this._updateOpacity(); - } - - return this; - }, - - setZIndex: function (zIndex) { - this.options.zIndex = zIndex; - this._updateZIndex(); - - return this; - }, - - setUrl: function (url, noRedraw) { - this._url = url; - - if (!noRedraw) { - this.redraw(); - } - - return this; - }, - - redraw: function () { - if (this._map) { - this._reset({hard: true}); - this._update(); - } - return this; - }, - - _updateZIndex: function () { - if (this._container && this.options.zIndex !== undefined) { - this._container.style.zIndex = this.options.zIndex; - } - }, - - _setAutoZIndex: function (pane, compare) { - - var layers = pane.children, - edgeZIndex = -compare(Infinity, -Infinity), // -Infinity for max, Infinity for min - zIndex, i, len; - - for (i = 0, len = layers.length; i < len; i++) { - - if (layers[i] !== this._container) { - zIndex = parseInt(layers[i].style.zIndex, 10); - - if (!isNaN(zIndex)) { - edgeZIndex = compare(edgeZIndex, zIndex); - } - } - } - - this.options.zIndex = this._container.style.zIndex = - (isFinite(edgeZIndex) ? edgeZIndex : 0) + compare(1, -1); - }, - - _updateOpacity: function () { - var i, - tiles = this._tiles; - - if (L.Browser.ielt9) { - for (i in tiles) { - L.DomUtil.setOpacity(tiles[i], this.options.opacity); - } - } else { - L.DomUtil.setOpacity(this._container, this.options.opacity); - } - }, - - _initContainer: function () { - var tilePane = this._map._panes.tilePane; - - if (!this._container) { - this._container = L.DomUtil.create('div', 'leaflet-layer'); - - this._updateZIndex(); - - if (this._animated) { - var className = 'leaflet-tile-container'; - - this._bgBuffer = L.DomUtil.create('div', className, this._container); - this._tileContainer = L.DomUtil.create('div', className, this._container); - - } else { - this._tileContainer = this._container; - } - - tilePane.appendChild(this._container); - - if (this.options.opacity < 1) { - this._updateOpacity(); - } - } - }, - - _reset: function (e) { - for (var key in this._tiles) { - this.fire('tileunload', {tile: this._tiles[key]}); - } - - this._tiles = {}; - this._tilesToLoad = 0; - - if (this.options.reuseTiles) { - this._unusedTiles = []; - } - - this._tileContainer.innerHTML = ''; - - if (this._animated && e && e.hard) { - this._clearBgBuffer(); - } - - this._initContainer(); - }, - - _getTileSize: function () { - var map = this._map, - zoom = map.getZoom() + this.options.zoomOffset, - zoomN = this.options.maxNativeZoom, - tileSize = this.options.tileSize; - - if (zoomN && zoom > zoomN) { - tileSize = Math.round(map.getZoomScale(zoom) / map.getZoomScale(zoomN) * tileSize); - } - - return tileSize; - }, - - _update: function () { - - if (!this._map) { return; } - - var map = this._map, - bounds = map.getPixelBounds(), - zoom = map.getZoom(), - tileSize = this._getTileSize(); - - if (zoom > this.options.maxZoom || zoom < this.options.minZoom) { - return; - } - - var tileBounds = L.bounds( - bounds.min.divideBy(tileSize)._floor(), - bounds.max.divideBy(tileSize)._floor()); - - this._addTilesFromCenterOut(tileBounds); - - if (this.options.unloadInvisibleTiles || this.options.reuseTiles) { - this._removeOtherTiles(tileBounds); - } - }, - - _addTilesFromCenterOut: function (bounds) { - var queue = [], - center = bounds.getCenter(); - - var j, i, point; - - for (j = bounds.min.y; j <= bounds.max.y; j++) { - for (i = bounds.min.x; i <= bounds.max.x; i++) { - point = new L.Point(i, j); - - if (this._tileShouldBeLoaded(point)) { - queue.push(point); - } - } - } - - var tilesToLoad = queue.length; - - if (tilesToLoad === 0) { return; } - - // load tiles in order of their distance to center - queue.sort(function (a, b) { - return a.distanceTo(center) - b.distanceTo(center); - }); - - var fragment = document.createDocumentFragment(); - - // if its the first batch of tiles to load - if (!this._tilesToLoad) { - this.fire('loading'); - } - - this._tilesToLoad += tilesToLoad; - - for (i = 0; i < tilesToLoad; i++) { - this._addTile(queue[i], fragment); - } - - this._tileContainer.appendChild(fragment); - }, - - _tileShouldBeLoaded: function (tilePoint) { - if ((tilePoint.x + ':' + tilePoint.y) in this._tiles) { - return false; // already loaded - } - - var options = this.options; - - if (!options.continuousWorld) { - var limit = this._getWrapTileNum(); - - // don't load if exceeds world bounds - if ((options.noWrap && (tilePoint.x < 0 || tilePoint.x >= limit.x)) || - tilePoint.y < 0 || tilePoint.y >= limit.y) { return false; } - } - - if (options.bounds) { - var tileSize = this._getTileSize(), - nwPoint = tilePoint.multiplyBy(tileSize), - sePoint = nwPoint.add([tileSize, tileSize]), - nw = this._map.unproject(nwPoint), - se = this._map.unproject(sePoint); - - // TODO temporary hack, will be removed after refactoring projections - // https://github.com/Leaflet/Leaflet/issues/1618 - if (!options.continuousWorld && !options.noWrap) { - nw = nw.wrap(); - se = se.wrap(); - } - - if (!options.bounds.intersects([nw, se])) { return false; } - } - - return true; - }, - - _removeOtherTiles: function (bounds) { - var kArr, x, y, key; - - for (key in this._tiles) { - kArr = key.split(':'); - x = parseInt(kArr[0], 10); - y = parseInt(kArr[1], 10); - - // remove tile if it's out of bounds - if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) { - this._removeTile(key); - } - } - }, - - _removeTile: function (key) { - var tile = this._tiles[key]; - - this.fire('tileunload', {tile: tile, url: tile.src}); - - if (this.options.reuseTiles) { - L.DomUtil.removeClass(tile, 'leaflet-tile-loaded'); - this._unusedTiles.push(tile); - - } else if (tile.parentNode === this._tileContainer) { - this._tileContainer.removeChild(tile); - } - - // for https://github.com/CloudMade/Leaflet/issues/137 - if (!L.Browser.android) { - tile.onload = null; - tile.src = L.Util.emptyImageUrl; - } - - delete this._tiles[key]; - }, - - _addTile: function (tilePoint, container) { - var tilePos = this._getTilePos(tilePoint); - - // get unused tile - or create a new tile - var tile = this._getTile(); - - /* - Chrome 20 layouts much faster with top/left (verify with timeline, frames) - Android 4 browser has display issues with top/left and requires transform instead - (other browsers don't currently care) - see debug/hacks/jitter.html for an example - */ - L.DomUtil.setPosition(tile, tilePos, L.Browser.chrome); - - this._tiles[tilePoint.x + ':' + tilePoint.y] = tile; - - this._loadTile(tile, tilePoint); - - if (tile.parentNode !== this._tileContainer) { - container.appendChild(tile); - } - }, - - _getZoomForUrl: function () { - - var options = this.options, - zoom = this._map.getZoom(); - - if (options.zoomReverse) { - zoom = options.maxZoom - zoom; - } - - zoom += options.zoomOffset; - - return options.maxNativeZoom ? Math.min(zoom, options.maxNativeZoom) : zoom; - }, - - _getTilePos: function (tilePoint) { - var origin = this._map.getPixelOrigin(), - tileSize = this._getTileSize(); - - return tilePoint.multiplyBy(tileSize).subtract(origin); - }, - - // image-specific code (override to implement e.g. Canvas or SVG tile layer) - - getTileUrl: function (tilePoint) { - return L.Util.template(this._url, L.extend({ - s: this._getSubdomain(tilePoint), - z: tilePoint.z, - x: tilePoint.x, - y: tilePoint.y - }, this.options)); - }, - - _getWrapTileNum: function () { - var crs = this._map.options.crs, - size = crs.getSize(this._map.getZoom()); - return size.divideBy(this._getTileSize())._floor(); - }, - - _adjustTilePoint: function (tilePoint) { - - var limit = this._getWrapTileNum(); - - // wrap tile coordinates - if (!this.options.continuousWorld && !this.options.noWrap) { - tilePoint.x = ((tilePoint.x % limit.x) + limit.x) % limit.x; - } - - if (this.options.tms) { - tilePoint.y = limit.y - tilePoint.y - 1; - } - - tilePoint.z = this._getZoomForUrl(); - }, - - _getSubdomain: function (tilePoint) { - var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length; - return this.options.subdomains[index]; - }, - - _getTile: function () { - if (this.options.reuseTiles && this._unusedTiles.length > 0) { - var tile = this._unusedTiles.pop(); - this._resetTile(tile); - return tile; - } - return this._createTile(); - }, - - // Override if data stored on a tile needs to be cleaned up before reuse - _resetTile: function (/*tile*/) {}, - - _createTile: function () { - var tile = L.DomUtil.create('img', 'leaflet-tile'); - tile.style.width = tile.style.height = this._getTileSize() + 'px'; - tile.galleryimg = 'no'; - - tile.onselectstart = tile.onmousemove = L.Util.falseFn; - - if (L.Browser.ielt9 && this.options.opacity !== undefined) { - L.DomUtil.setOpacity(tile, this.options.opacity); - } - // without this hack, tiles disappear after zoom on Chrome for Android - // https://github.com/Leaflet/Leaflet/issues/2078 - if (L.Browser.mobileWebkit3d) { - tile.style.WebkitBackfaceVisibility = 'hidden'; - } - return tile; - }, - - _loadTile: function (tile, tilePoint) { - tile._layer = this; - tile.onload = this._tileOnLoad; - tile.onerror = this._tileOnError; - - this._adjustTilePoint(tilePoint); - tile.src = this.getTileUrl(tilePoint); - - this.fire('tileloadstart', { - tile: tile, - url: tile.src - }); - }, - - _tileLoaded: function () { - this._tilesToLoad--; - - if (this._animated) { - L.DomUtil.addClass(this._tileContainer, 'leaflet-zoom-animated'); - } - - if (!this._tilesToLoad) { - this.fire('load'); - - if (this._animated) { - // clear scaled tiles after all new tiles are loaded (for performance) - clearTimeout(this._clearBgBufferTimer); - this._clearBgBufferTimer = setTimeout(L.bind(this._clearBgBuffer, this), 500); - } - } - }, - - _tileOnLoad: function () { - var layer = this._layer; - - //Only if we are loading an actual image - if (this.src !== L.Util.emptyImageUrl) { - L.DomUtil.addClass(this, 'leaflet-tile-loaded'); - - layer.fire('tileload', { - tile: this, - url: this.src - }); - } - - layer._tileLoaded(); - }, - - _tileOnError: function () { - var layer = this._layer; - - layer.fire('tileerror', { - tile: this, - url: this.src - }); - - var newUrl = layer.options.errorTileUrl; - if (newUrl) { - this.src = newUrl; - } - - layer._tileLoaded(); - } -}); - -L.tileLayer = function (url, options) { - return new L.TileLayer(url, options); -}; - - -/* - * L.TileLayer.WMS is used for putting WMS tile layers on the map. - */ - -L.TileLayer.WMS = L.TileLayer.extend({ - - defaultWmsParams: { - service: 'WMS', - request: 'GetMap', - version: '1.1.1', - layers: '', - styles: '', - format: 'image/jpeg', - transparent: false - }, - - initialize: function (url, options) { // (String, Object) - - this._url = url; - - var wmsParams = L.extend({}, this.defaultWmsParams), - tileSize = options.tileSize || this.options.tileSize; - - if (options.detectRetina && L.Browser.retina) { - wmsParams.width = wmsParams.height = tileSize * 2; - } else { - wmsParams.width = wmsParams.height = tileSize; - } - - for (var i in options) { - // all keys that are not TileLayer options go to WMS params - if (!this.options.hasOwnProperty(i) && i !== 'crs') { - wmsParams[i] = options[i]; - } - } - - this.wmsParams = wmsParams; - - L.setOptions(this, options); - }, - - onAdd: function (map) { - - this._crs = this.options.crs || map.options.crs; - - this._wmsVersion = parseFloat(this.wmsParams.version); - - var projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs'; - this.wmsParams[projectionKey] = this._crs.code; - - L.TileLayer.prototype.onAdd.call(this, map); - }, - - getTileUrl: function (tilePoint) { // (Point, Number) -> String - - var map = this._map, - tileSize = this.options.tileSize, - - nwPoint = tilePoint.multiplyBy(tileSize), - sePoint = nwPoint.add([tileSize, tileSize]), - - nw = this._crs.project(map.unproject(nwPoint, tilePoint.z)), - se = this._crs.project(map.unproject(sePoint, tilePoint.z)), - bbox = this._wmsVersion >= 1.3 && this._crs === L.CRS.EPSG4326 ? - [se.y, nw.x, nw.y, se.x].join(',') : - [nw.x, se.y, se.x, nw.y].join(','), - - url = L.Util.template(this._url, {s: this._getSubdomain(tilePoint)}); - - return url + L.Util.getParamString(this.wmsParams, url, true) + '&BBOX=' + bbox; - }, - - setParams: function (params, noRedraw) { - - L.extend(this.wmsParams, params); - - if (!noRedraw) { - this.redraw(); - } - - return this; - } -}); - -L.tileLayer.wms = function (url, options) { - return new L.TileLayer.WMS(url, options); -}; - - -/* - * L.TileLayer.Canvas is a class that you can use as a base for creating - * dynamically drawn Canvas-based tile layers. - */ - -L.TileLayer.Canvas = L.TileLayer.extend({ - options: { - async: false - }, - - initialize: function (options) { - L.setOptions(this, options); - }, - - redraw: function () { - if (this._map) { - this._reset({hard: true}); - this._update(); - } - - for (var i in this._tiles) { - this._redrawTile(this._tiles[i]); - } - return this; - }, - - _redrawTile: function (tile) { - this.drawTile(tile, tile._tilePoint, this._map._zoom); - }, - - _createTile: function () { - var tile = L.DomUtil.create('canvas', 'leaflet-tile'); - tile.width = tile.height = this.options.tileSize; - tile.onselectstart = tile.onmousemove = L.Util.falseFn; - return tile; - }, - - _loadTile: function (tile, tilePoint) { - tile._layer = this; - tile._tilePoint = tilePoint; - - this._redrawTile(tile); - - if (!this.options.async) { - this.tileDrawn(tile); - } - }, - - drawTile: function (/*tile, tilePoint*/) { - // override with rendering code - }, - - tileDrawn: function (tile) { - this._tileOnLoad.call(tile); - } -}); - - -L.tileLayer.canvas = function (options) { - return new L.TileLayer.Canvas(options); -}; - - -/* - * L.ImageOverlay is used to overlay images over the map (to specific geographical bounds). - */ - -L.ImageOverlay = L.Class.extend({ - includes: L.Mixin.Events, - - options: { - opacity: 1 - }, - - initialize: function (url, bounds, options) { // (String, LatLngBounds, Object) - this._url = url; - this._bounds = L.latLngBounds(bounds); - - L.setOptions(this, options); - }, - - onAdd: function (map) { - this._map = map; - - if (!this._image) { - this._initImage(); - } - - map._panes.overlayPane.appendChild(this._image); - - map.on('viewreset', this._reset, this); - - if (map.options.zoomAnimation && L.Browser.any3d) { - map.on('zoomanim', this._animateZoom, this); - } - - this._reset(); - }, - - onRemove: function (map) { - map.getPanes().overlayPane.removeChild(this._image); - - map.off('viewreset', this._reset, this); - - if (map.options.zoomAnimation) { - map.off('zoomanim', this._animateZoom, this); - } - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - setOpacity: function (opacity) { - this.options.opacity = opacity; - this._updateOpacity(); - return this; - }, - - // TODO remove bringToFront/bringToBack duplication from TileLayer/Path - bringToFront: function () { - if (this._image) { - this._map._panes.overlayPane.appendChild(this._image); - } - return this; - }, - - bringToBack: function () { - var pane = this._map._panes.overlayPane; - if (this._image) { - pane.insertBefore(this._image, pane.firstChild); - } - return this; - }, - - setUrl: function (url) { - this._url = url; - this._image.src = this._url; - }, - - getAttribution: function () { - return this.options.attribution; - }, - - _initImage: function () { - this._image = L.DomUtil.create('img', 'leaflet-image-layer'); - - if (this._map.options.zoomAnimation && L.Browser.any3d) { - L.DomUtil.addClass(this._image, 'leaflet-zoom-animated'); - } else { - L.DomUtil.addClass(this._image, 'leaflet-zoom-hide'); - } - - this._updateOpacity(); - - //TODO createImage util method to remove duplication - L.extend(this._image, { - galleryimg: 'no', - onselectstart: L.Util.falseFn, - onmousemove: L.Util.falseFn, - onload: L.bind(this._onImageLoad, this), - src: this._url - }); - }, - - _animateZoom: function (e) { - var map = this._map, - image = this._image, - scale = map.getZoomScale(e.zoom), - nw = this._bounds.getNorthWest(), - se = this._bounds.getSouthEast(), - - topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center), - size = map._latLngToNewLayerPoint(se, e.zoom, e.center)._subtract(topLeft), - origin = topLeft._add(size._multiplyBy((1 / 2) * (1 - 1 / scale))); - - image.style[L.DomUtil.TRANSFORM] = - L.DomUtil.getTranslateString(origin) + ' scale(' + scale + ') '; - }, - - _reset: function () { - var image = this._image, - topLeft = this._map.latLngToLayerPoint(this._bounds.getNorthWest()), - size = this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(topLeft); - - L.DomUtil.setPosition(image, topLeft); - - image.style.width = size.x + 'px'; - image.style.height = size.y + 'px'; - }, - - _onImageLoad: function () { - this.fire('load'); - }, - - _updateOpacity: function () { - L.DomUtil.setOpacity(this._image, this.options.opacity); - } -}); - -L.imageOverlay = function (url, bounds, options) { - return new L.ImageOverlay(url, bounds, options); -}; - - -/* - * L.Icon is an image-based icon class that you can use with L.Marker for custom markers. - */ - -L.Icon = L.Class.extend({ - options: { - /* - iconUrl: (String) (required) - iconRetinaUrl: (String) (optional, used for retina devices if detected) - iconSize: (Point) (can be set through CSS) - iconAnchor: (Point) (centered by default, can be set in CSS with negative margins) - popupAnchor: (Point) (if not specified, popup opens in the anchor point) - shadowUrl: (String) (no shadow by default) - shadowRetinaUrl: (String) (optional, used for retina devices if detected) - shadowSize: (Point) - shadowAnchor: (Point) - */ - className: '' - }, - - initialize: function (options) { - L.setOptions(this, options); - }, - - createIcon: function (oldIcon) { - return this._createIcon('icon', oldIcon); - }, - - createShadow: function (oldIcon) { - return this._createIcon('shadow', oldIcon); - }, - - _createIcon: function (name, oldIcon) { - var src = this._getIconUrl(name); - - if (!src) { - if (name === 'icon') { - throw new Error('iconUrl not set in Icon options (see the docs).'); - } - return null; - } - - var img; - if (!oldIcon || oldIcon.tagName !== 'IMG') { - img = this._createImg(src); - } else { - img = this._createImg(src, oldIcon); - } - this._setIconStyles(img, name); - - return img; - }, - - _setIconStyles: function (img, name) { - var options = this.options, - size = L.point(options[name + 'Size']), - anchor; - - if (name === 'shadow') { - anchor = L.point(options.shadowAnchor || options.iconAnchor); - } else { - anchor = L.point(options.iconAnchor); - } - - if (!anchor && size) { - anchor = size.divideBy(2, true); - } - - img.className = 'leaflet-marker-' + name + ' ' + options.className; - - if (anchor) { - img.style.marginLeft = (-anchor.x) + 'px'; - img.style.marginTop = (-anchor.y) + 'px'; - } - - if (size) { - img.style.width = size.x + 'px'; - img.style.height = size.y + 'px'; - } - }, - - _createImg: function (src, el) { - el = el || document.createElement('img'); - el.src = src; - return el; - }, - - _getIconUrl: function (name) { - if (L.Browser.retina && this.options[name + 'RetinaUrl']) { - return this.options[name + 'RetinaUrl']; - } - return this.options[name + 'Url']; - } -}); - -L.icon = function (options) { - return new L.Icon(options); -}; - - -/* - * L.Icon.Default is the blue marker icon used by default in Leaflet. - */ - -L.Icon.Default = L.Icon.extend({ - - options: { - iconSize: [25, 41], - iconAnchor: [12, 41], - popupAnchor: [1, -34], - - shadowSize: [41, 41] - }, - - _getIconUrl: function (name) { - var key = name + 'Url'; - - if (this.options[key]) { - return this.options[key]; - } - - if (L.Browser.retina && name === 'icon') { - name += '-2x'; - } - - var path = L.Icon.Default.imagePath; - - if (!path) { - throw new Error('Couldn\'t autodetect L.Icon.Default.imagePath, set it manually.'); - } - - return path + '/marker-' + name + '.png'; - } -}); - -L.Icon.Default.imagePath = (function () { - var scripts = document.getElementsByTagName('script'), - leafletRe = /[\/^]leaflet[\-\._]?([\w\-\._]*)\.js\??/; - - var i, len, src, matches, path; - - for (i = 0, len = scripts.length; i < len; i++) { - src = scripts[i].src; - matches = src.match(leafletRe); - - if (matches) { - path = src.split(leafletRe)[0]; - return (path ? path + '/' : '') + 'images'; - } - } -}()); - - -/* - * L.Marker is used to display clickable/draggable icons on the map. - */ - -L.Marker = L.Class.extend({ - - includes: L.Mixin.Events, - - options: { - icon: new L.Icon.Default(), - title: '', - alt: '', - clickable: true, - draggable: false, - keyboard: true, - zIndexOffset: 0, - opacity: 1, - riseOnHover: false, - riseOffset: 250 - }, - - initialize: function (latlng, options) { - L.setOptions(this, options); - this._latlng = L.latLng(latlng); - }, - - onAdd: function (map) { - this._map = map; - - map.on('viewreset', this.update, this); - - this._initIcon(); - this.update(); - this.fire('add'); - - if (map.options.zoomAnimation && map.options.markerZoomAnimation) { - map.on('zoomanim', this._animateZoom, this); - } - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - onRemove: function (map) { - if (this.dragging) { - this.dragging.disable(); - } - - this._removeIcon(); - this._removeShadow(); - - this.fire('remove'); - - map.off({ - 'viewreset': this.update, - 'zoomanim': this._animateZoom - }, this); - - this._map = null; - }, - - getLatLng: function () { - return this._latlng; - }, - - setLatLng: function (latlng) { - this._latlng = L.latLng(latlng); - - this.update(); - - return this.fire('move', { latlng: this._latlng }); - }, - - setZIndexOffset: function (offset) { - this.options.zIndexOffset = offset; - this.update(); - - return this; - }, - - setIcon: function (icon) { - - this.options.icon = icon; - - if (this._map) { - this._initIcon(); - this.update(); - } - - if (this._popup) { - this.bindPopup(this._popup); - } - - return this; - }, - - update: function () { - if (this._icon) { - this._setPos(this._map.latLngToLayerPoint(this._latlng).round()); - } - return this; - }, - - _initIcon: function () { - var options = this.options, - map = this._map, - animation = (map.options.zoomAnimation && map.options.markerZoomAnimation), - classToAdd = animation ? 'leaflet-zoom-animated' : 'leaflet-zoom-hide'; - - var icon = options.icon.createIcon(this._icon), - addIcon = false; - - // if we're not reusing the icon, remove the old one and init new one - if (icon !== this._icon) { - if (this._icon) { - this._removeIcon(); - } - addIcon = true; - - if (options.title) { - icon.title = options.title; - } - - if (options.alt) { - icon.alt = options.alt; - } - } - - L.DomUtil.addClass(icon, classToAdd); - - if (options.keyboard) { - icon.tabIndex = '0'; - } - - this._icon = icon; - - this._initInteraction(); - - if (options.riseOnHover) { - L.DomEvent - .on(icon, 'mouseover', this._bringToFront, this) - .on(icon, 'mouseout', this._resetZIndex, this); - } - - var newShadow = options.icon.createShadow(this._shadow), - addShadow = false; - - if (newShadow !== this._shadow) { - this._removeShadow(); - addShadow = true; - } - - if (newShadow) { - L.DomUtil.addClass(newShadow, classToAdd); - } - this._shadow = newShadow; - - - if (options.opacity < 1) { - this._updateOpacity(); - } - - - var panes = this._map._panes; - - if (addIcon) { - panes.markerPane.appendChild(this._icon); - } - - if (newShadow && addShadow) { - panes.shadowPane.appendChild(this._shadow); - } - }, - - _removeIcon: function () { - if (this.options.riseOnHover) { - L.DomEvent - .off(this._icon, 'mouseover', this._bringToFront) - .off(this._icon, 'mouseout', this._resetZIndex); - } - - this._map._panes.markerPane.removeChild(this._icon); - - this._icon = null; - }, - - _removeShadow: function () { - if (this._shadow) { - this._map._panes.shadowPane.removeChild(this._shadow); - } - this._shadow = null; - }, - - _setPos: function (pos) { - L.DomUtil.setPosition(this._icon, pos); - - if (this._shadow) { - L.DomUtil.setPosition(this._shadow, pos); - } - - this._zIndex = pos.y + this.options.zIndexOffset; - - this._resetZIndex(); - }, - - _updateZIndex: function (offset) { - this._icon.style.zIndex = this._zIndex + offset; - }, - - _animateZoom: function (opt) { - var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round(); - - this._setPos(pos); - }, - - _initInteraction: function () { - - if (!this.options.clickable) { return; } - - // TODO refactor into something shared with Map/Path/etc. to DRY it up - - var icon = this._icon, - events = ['dblclick', 'mousedown', 'mouseover', 'mouseout', 'contextmenu']; - - L.DomUtil.addClass(icon, 'leaflet-clickable'); - L.DomEvent.on(icon, 'click', this._onMouseClick, this); - L.DomEvent.on(icon, 'keypress', this._onKeyPress, this); - - for (var i = 0; i < events.length; i++) { - L.DomEvent.on(icon, events[i], this._fireMouseEvent, this); - } - - if (L.Handler.MarkerDrag) { - this.dragging = new L.Handler.MarkerDrag(this); - - if (this.options.draggable) { - this.dragging.enable(); - } - } - }, - - _onMouseClick: function (e) { - var wasDragged = this.dragging && this.dragging.moved(); - - if (this.hasEventListeners(e.type) || wasDragged) { - L.DomEvent.stopPropagation(e); - } - - if (wasDragged) { return; } - - if ((!this.dragging || !this.dragging._enabled) && this._map.dragging && this._map.dragging.moved()) { return; } - - this.fire(e.type, { - originalEvent: e, - latlng: this._latlng - }); - }, - - _onKeyPress: function (e) { - if (e.keyCode === 13) { - this.fire('click', { - originalEvent: e, - latlng: this._latlng - }); - } - }, - - _fireMouseEvent: function (e) { - - this.fire(e.type, { - originalEvent: e, - latlng: this._latlng - }); - - // TODO proper custom event propagation - // this line will always be called if marker is in a FeatureGroup - if (e.type === 'contextmenu' && this.hasEventListeners(e.type)) { - L.DomEvent.preventDefault(e); - } - if (e.type !== 'mousedown') { - L.DomEvent.stopPropagation(e); - } else { - L.DomEvent.preventDefault(e); - } - }, - - setOpacity: function (opacity) { - this.options.opacity = opacity; - if (this._map) { - this._updateOpacity(); - } - - return this; - }, - - _updateOpacity: function () { - L.DomUtil.setOpacity(this._icon, this.options.opacity); - if (this._shadow) { - L.DomUtil.setOpacity(this._shadow, this.options.opacity); - } - }, - - _bringToFront: function () { - this._updateZIndex(this.options.riseOffset); - }, - - _resetZIndex: function () { - this._updateZIndex(0); - } -}); - -L.marker = function (latlng, options) { - return new L.Marker(latlng, options); -}; - - -/* - * L.DivIcon is a lightweight HTML-based icon class (as opposed to the image-based L.Icon) - * to use with L.Marker. - */ - -L.DivIcon = L.Icon.extend({ - options: { - iconSize: [12, 12], // also can be set through CSS - /* - iconAnchor: (Point) - popupAnchor: (Point) - html: (String) - bgPos: (Point) - */ - className: 'leaflet-div-icon', - html: false - }, - - createIcon: function (oldIcon) { - var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'), - options = this.options; - - if (options.html !== false) { - div.innerHTML = options.html; - } else { - div.innerHTML = ''; - } - - if (options.bgPos) { - div.style.backgroundPosition = - (-options.bgPos.x) + 'px ' + (-options.bgPos.y) + 'px'; - } - - this._setIconStyles(div, 'icon'); - return div; - }, - - createShadow: function () { - return null; - } -}); - -L.divIcon = function (options) { - return new L.DivIcon(options); -}; - - -/* - * L.Popup is used for displaying popups on the map. - */ - -L.Map.mergeOptions({ - closePopupOnClick: true -}); - -L.Popup = L.Class.extend({ - includes: L.Mixin.Events, - - options: { - minWidth: 50, - maxWidth: 300, - // maxHeight: null, - autoPan: true, - closeButton: true, - offset: [0, 7], - autoPanPadding: [5, 5], - // autoPanPaddingTopLeft: null, - // autoPanPaddingBottomRight: null, - keepInView: false, - className: '', - zoomAnimation: true - }, - - initialize: function (options, source) { - L.setOptions(this, options); - - this._source = source; - this._animated = L.Browser.any3d && this.options.zoomAnimation; - this._isOpen = false; - }, - - onAdd: function (map) { - this._map = map; - - if (!this._container) { - this._initLayout(); - } - - var animFade = map.options.fadeAnimation; - - if (animFade) { - L.DomUtil.setOpacity(this._container, 0); - } - map._panes.popupPane.appendChild(this._container); - - map.on(this._getEvents(), this); - - this.update(); - - if (animFade) { - L.DomUtil.setOpacity(this._container, 1); - } - - this.fire('open'); - - map.fire('popupopen', {popup: this}); - - if (this._source) { - this._source.fire('popupopen', {popup: this}); - } - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - openOn: function (map) { - map.openPopup(this); - return this; - }, - - onRemove: function (map) { - map._panes.popupPane.removeChild(this._container); - - L.Util.falseFn(this._container.offsetWidth); // force reflow - - map.off(this._getEvents(), this); - - if (map.options.fadeAnimation) { - L.DomUtil.setOpacity(this._container, 0); - } - - this._map = null; - - this.fire('close'); - - map.fire('popupclose', {popup: this}); - - if (this._source) { - this._source.fire('popupclose', {popup: this}); - } - }, - - getLatLng: function () { - return this._latlng; - }, - - setLatLng: function (latlng) { - this._latlng = L.latLng(latlng); - if (this._map) { - this._updatePosition(); - this._adjustPan(); - } - return this; - }, - - getContent: function () { - return this._content; - }, - - setContent: function (content) { - this._content = content; - this.update(); - return this; - }, - - update: function () { - if (!this._map) { return; } - - this._container.style.visibility = 'hidden'; - - this._updateContent(); - this._updateLayout(); - this._updatePosition(); - - this._container.style.visibility = ''; - - this._adjustPan(); - }, - - _getEvents: function () { - var events = { - viewreset: this._updatePosition - }; - - if (this._animated) { - events.zoomanim = this._zoomAnimation; - } - if ('closeOnClick' in this.options ? this.options.closeOnClick : this._map.options.closePopupOnClick) { - events.preclick = this._close; - } - if (this.options.keepInView) { - events.moveend = this._adjustPan; - } - - return events; - }, - - _close: function () { - if (this._map) { - this._map.closePopup(this); - } - }, - - _initLayout: function () { - var prefix = 'leaflet-popup', - containerClass = prefix + ' ' + this.options.className + ' leaflet-zoom-' + - (this._animated ? 'animated' : 'hide'), - container = this._container = L.DomUtil.create('div', containerClass), - closeButton; - - if (this.options.closeButton) { - closeButton = this._closeButton = - L.DomUtil.create('a', prefix + '-close-button', container); - closeButton.href = '#close'; - closeButton.innerHTML = '×'; - L.DomEvent.disableClickPropagation(closeButton); - - L.DomEvent.on(closeButton, 'click', this._onCloseButtonClick, this); - } - - var wrapper = this._wrapper = - L.DomUtil.create('div', prefix + '-content-wrapper', container); - L.DomEvent.disableClickPropagation(wrapper); - - this._contentNode = L.DomUtil.create('div', prefix + '-content', wrapper); - - L.DomEvent.disableScrollPropagation(this._contentNode); - L.DomEvent.on(wrapper, 'contextmenu', L.DomEvent.stopPropagation); - - this._tipContainer = L.DomUtil.create('div', prefix + '-tip-container', container); - this._tip = L.DomUtil.create('div', prefix + '-tip', this._tipContainer); - }, - - _updateContent: function () { - if (!this._content) { return; } - - if (typeof this._content === 'string') { - this._contentNode.innerHTML = this._content; - } else { - while (this._contentNode.hasChildNodes()) { - this._contentNode.removeChild(this._contentNode.firstChild); - } - this._contentNode.appendChild(this._content); - } - this.fire('contentupdate'); - }, - - _updateLayout: function () { - var container = this._contentNode, - style = container.style; - - style.width = ''; - style.whiteSpace = 'nowrap'; - - var width = container.offsetWidth; - width = Math.min(width, this.options.maxWidth); - width = Math.max(width, this.options.minWidth); - - style.width = (width + 1) + 'px'; - style.whiteSpace = ''; - - style.height = ''; - - var height = container.offsetHeight, - maxHeight = this.options.maxHeight, - scrolledClass = 'leaflet-popup-scrolled'; - - if (maxHeight && height > maxHeight) { - style.height = maxHeight + 'px'; - L.DomUtil.addClass(container, scrolledClass); - } else { - L.DomUtil.removeClass(container, scrolledClass); - } - - this._containerWidth = this._container.offsetWidth; - }, - - _updatePosition: function () { - if (!this._map) { return; } - - var pos = this._map.latLngToLayerPoint(this._latlng), - animated = this._animated, - offset = L.point(this.options.offset); - - if (animated) { - L.DomUtil.setPosition(this._container, pos); - } - - this._containerBottom = -offset.y - (animated ? 0 : pos.y); - this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x + (animated ? 0 : pos.x); - - // bottom position the popup in case the height of the popup changes (images loading etc) - this._container.style.bottom = this._containerBottom + 'px'; - this._container.style.left = this._containerLeft + 'px'; - }, - - _zoomAnimation: function (opt) { - var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center); - - L.DomUtil.setPosition(this._container, pos); - }, - - _adjustPan: function () { - if (!this.options.autoPan) { return; } - - var map = this._map, - containerHeight = this._container.offsetHeight, - containerWidth = this._containerWidth, - - layerPos = new L.Point(this._containerLeft, -containerHeight - this._containerBottom); - - if (this._animated) { - layerPos._add(L.DomUtil.getPosition(this._container)); - } - - var containerPos = map.layerPointToContainerPoint(layerPos), - padding = L.point(this.options.autoPanPadding), - paddingTL = L.point(this.options.autoPanPaddingTopLeft || padding), - paddingBR = L.point(this.options.autoPanPaddingBottomRight || padding), - size = map.getSize(), - dx = 0, - dy = 0; - - if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right - dx = containerPos.x + containerWidth - size.x + paddingBR.x; - } - if (containerPos.x - dx - paddingTL.x < 0) { // left - dx = containerPos.x - paddingTL.x; - } - if (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom - dy = containerPos.y + containerHeight - size.y + paddingBR.y; - } - if (containerPos.y - dy - paddingTL.y < 0) { // top - dy = containerPos.y - paddingTL.y; - } - - if (dx || dy) { - map - .fire('autopanstart') - .panBy([dx, dy]); - } - }, - - _onCloseButtonClick: function (e) { - this._close(); - L.DomEvent.stop(e); - } -}); - -L.popup = function (options, source) { - return new L.Popup(options, source); -}; - - -L.Map.include({ - openPopup: function (popup, latlng, options) { // (Popup) or (String || HTMLElement, LatLng[, Object]) - this.closePopup(); - - if (!(popup instanceof L.Popup)) { - var content = popup; - - popup = new L.Popup(options) - .setLatLng(latlng) - .setContent(content); - } - popup._isOpen = true; - - this._popup = popup; - return this.addLayer(popup); - }, - - closePopup: function (popup) { - if (!popup || popup === this._popup) { - popup = this._popup; - this._popup = null; - } - if (popup) { - this.removeLayer(popup); - popup._isOpen = false; - } - return this; - } -}); - - -/* - * Popup extension to L.Marker, adding popup-related methods. - */ - -L.Marker.include({ - openPopup: function () { - if (this._popup && this._map && !this._map.hasLayer(this._popup)) { - this._popup.setLatLng(this._latlng); - this._map.openPopup(this._popup); - } - - return this; - }, - - closePopup: function () { - if (this._popup) { - this._popup._close(); - } - return this; - }, - - togglePopup: function () { - if (this._popup) { - if (this._popup._isOpen) { - this.closePopup(); - } else { - this.openPopup(); - } - } - return this; - }, - - bindPopup: function (content, options) { - var anchor = L.point(this.options.icon.options.popupAnchor || [0, 0]); - - anchor = anchor.add(L.Popup.prototype.options.offset); - - if (options && options.offset) { - anchor = anchor.add(options.offset); - } - - options = L.extend({offset: anchor}, options); - - if (!this._popupHandlersAdded) { - this - .on('click', this.togglePopup, this) - .on('remove', this.closePopup, this) - .on('move', this._movePopup, this); - this._popupHandlersAdded = true; - } - - if (content instanceof L.Popup) { - L.setOptions(content, options); - this._popup = content; - content._source = this; - } else { - this._popup = new L.Popup(options, this) - .setContent(content); - } - - return this; - }, - - setPopupContent: function (content) { - if (this._popup) { - this._popup.setContent(content); - } - return this; - }, - - unbindPopup: function () { - if (this._popup) { - this._popup = null; - this - .off('click', this.togglePopup, this) - .off('remove', this.closePopup, this) - .off('move', this._movePopup, this); - this._popupHandlersAdded = false; - } - return this; - }, - - getPopup: function () { - return this._popup; - }, - - _movePopup: function (e) { - this._popup.setLatLng(e.latlng); - } -}); - - -/* - * L.LayerGroup is a class to combine several layers into one so that - * you can manipulate the group (e.g. add/remove it) as one layer. - */ - -L.LayerGroup = L.Class.extend({ - initialize: function (layers) { - this._layers = {}; - - var i, len; - - if (layers) { - for (i = 0, len = layers.length; i < len; i++) { - this.addLayer(layers[i]); - } - } - }, - - addLayer: function (layer) { - var id = this.getLayerId(layer); - - this._layers[id] = layer; - - if (this._map) { - this._map.addLayer(layer); - } - - return this; - }, - - removeLayer: function (layer) { - var id = layer in this._layers ? layer : this.getLayerId(layer); - - if (this._map && this._layers[id]) { - this._map.removeLayer(this._layers[id]); - } - - delete this._layers[id]; - - return this; - }, - - hasLayer: function (layer) { - if (!layer) { return false; } - - return (layer in this._layers || this.getLayerId(layer) in this._layers); - }, - - clearLayers: function () { - this.eachLayer(this.removeLayer, this); - return this; - }, - - invoke: function (methodName) { - var args = Array.prototype.slice.call(arguments, 1), - i, layer; - - for (i in this._layers) { - layer = this._layers[i]; - - if (layer[methodName]) { - layer[methodName].apply(layer, args); - } - } - - return this; - }, - - onAdd: function (map) { - this._map = map; - this.eachLayer(map.addLayer, map); - }, - - onRemove: function (map) { - this.eachLayer(map.removeLayer, map); - this._map = null; - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - eachLayer: function (method, context) { - for (var i in this._layers) { - method.call(context, this._layers[i]); - } - return this; - }, - - getLayer: function (id) { - return this._layers[id]; - }, - - getLayers: function () { - var layers = []; - - for (var i in this._layers) { - layers.push(this._layers[i]); - } - return layers; - }, - - setZIndex: function (zIndex) { - return this.invoke('setZIndex', zIndex); - }, - - getLayerId: function (layer) { - return L.stamp(layer); - } -}); - -L.layerGroup = function (layers) { - return new L.LayerGroup(layers); -}; - - -/* - * L.FeatureGroup extends L.LayerGroup by introducing mouse events and additional methods - * shared between a group of interactive layers (like vectors or markers). - */ - -L.FeatureGroup = L.LayerGroup.extend({ - includes: L.Mixin.Events, - - statics: { - EVENTS: 'click dblclick mouseover mouseout mousemove contextmenu popupopen popupclose' - }, - - addLayer: function (layer) { - if (this.hasLayer(layer)) { - return this; - } - - if ('on' in layer) { - layer.on(L.FeatureGroup.EVENTS, this._propagateEvent, this); - } - - L.LayerGroup.prototype.addLayer.call(this, layer); - - if (this._popupContent && layer.bindPopup) { - layer.bindPopup(this._popupContent, this._popupOptions); - } - - return this.fire('layeradd', {layer: layer}); - }, - - removeLayer: function (layer) { - if (!this.hasLayer(layer)) { - return this; - } - if (layer in this._layers) { - layer = this._layers[layer]; - } - - if ('off' in layer) { - layer.off(L.FeatureGroup.EVENTS, this._propagateEvent, this); - } - - L.LayerGroup.prototype.removeLayer.call(this, layer); - - if (this._popupContent) { - this.invoke('unbindPopup'); - } - - return this.fire('layerremove', {layer: layer}); - }, - - bindPopup: function (content, options) { - this._popupContent = content; - this._popupOptions = options; - return this.invoke('bindPopup', content, options); - }, - - openPopup: function (latlng) { - // open popup on the first layer - for (var id in this._layers) { - this._layers[id].openPopup(latlng); - break; - } - return this; - }, - - setStyle: function (style) { - return this.invoke('setStyle', style); - }, - - bringToFront: function () { - return this.invoke('bringToFront'); - }, - - bringToBack: function () { - return this.invoke('bringToBack'); - }, - - getBounds: function () { - var bounds = new L.LatLngBounds(); - - this.eachLayer(function (layer) { - bounds.extend(layer instanceof L.Marker ? layer.getLatLng() : layer.getBounds()); - }); - - return bounds; - }, - - _propagateEvent: function (e) { - e = L.extend({ - layer: e.target, - target: this - }, e); - this.fire(e.type, e); - } -}); - -L.featureGroup = function (layers) { - return new L.FeatureGroup(layers); -}; - - -/* - * L.Path is a base class for rendering vector paths on a map. Inherited by Polyline, Circle, etc. - */ - -L.Path = L.Class.extend({ - includes: [L.Mixin.Events], - - statics: { - // how much to extend the clip area around the map view - // (relative to its size, e.g. 0.5 is half the screen in each direction) - // set it so that SVG element doesn't exceed 1280px (vectors flicker on dragend if it is) - CLIP_PADDING: (function () { - var max = L.Browser.mobile ? 1280 : 2000, - target = (max / Math.max(window.outerWidth, window.outerHeight) - 1) / 2; - return Math.max(0, Math.min(0.5, target)); - })() - }, - - options: { - stroke: true, - color: '#0033ff', - dashArray: null, - lineCap: null, - lineJoin: null, - weight: 5, - opacity: 0.5, - - fill: false, - fillColor: null, //same as color by default - fillOpacity: 0.2, - - clickable: true - }, - - initialize: function (options) { - L.setOptions(this, options); - }, - - onAdd: function (map) { - this._map = map; - - if (!this._container) { - this._initElements(); - this._initEvents(); - } - - this.projectLatlngs(); - this._updatePath(); - - if (this._container) { - this._map._pathRoot.appendChild(this._container); - } - - this.fire('add'); - - map.on({ - 'viewreset': this.projectLatlngs, - 'moveend': this._updatePath - }, this); - }, - - addTo: function (map) { - map.addLayer(this); - return this; - }, - - onRemove: function (map) { - map._pathRoot.removeChild(this._container); - - // Need to fire remove event before we set _map to null as the event hooks might need the object - this.fire('remove'); - this._map = null; - - if (L.Browser.vml) { - this._container = null; - this._stroke = null; - this._fill = null; - } - - map.off({ - 'viewreset': this.projectLatlngs, - 'moveend': this._updatePath - }, this); - }, - - projectLatlngs: function () { - // do all projection stuff here - }, - - setStyle: function (style) { - L.setOptions(this, style); - - if (this._container) { - this._updateStyle(); - } - - return this; - }, - - redraw: function () { - if (this._map) { - this.projectLatlngs(); - this._updatePath(); - } - return this; - } -}); - -L.Map.include({ - _updatePathViewport: function () { - var p = L.Path.CLIP_PADDING, - size = this.getSize(), - panePos = L.DomUtil.getPosition(this._mapPane), - min = panePos.multiplyBy(-1)._subtract(size.multiplyBy(p)._round()), - max = min.add(size.multiplyBy(1 + p * 2)._round()); - - this._pathViewport = new L.Bounds(min, max); - } -}); - - -/* - * Extends L.Path with SVG-specific rendering code. - */ - -L.Path.SVG_NS = 'http://www.w3.org/2000/svg'; - -L.Browser.svg = !!(document.createElementNS && document.createElementNS(L.Path.SVG_NS, 'svg').createSVGRect); - -L.Path = L.Path.extend({ - statics: { - SVG: L.Browser.svg - }, - - bringToFront: function () { - var root = this._map._pathRoot, - path = this._container; - - if (path && root.lastChild !== path) { - root.appendChild(path); - } - return this; - }, - - bringToBack: function () { - var root = this._map._pathRoot, - path = this._container, - first = root.firstChild; - - if (path && first !== path) { - root.insertBefore(path, first); - } - return this; - }, - - getPathString: function () { - // form path string here - }, - - _createElement: function (name) { - return document.createElementNS(L.Path.SVG_NS, name); - }, - - _initElements: function () { - this._map._initPathRoot(); - this._initPath(); - this._initStyle(); - }, - - _initPath: function () { - this._container = this._createElement('g'); - - this._path = this._createElement('path'); - - if (this.options.className) { - L.DomUtil.addClass(this._path, this.options.className); - } - - this._container.appendChild(this._path); - }, - - _initStyle: function () { - if (this.options.stroke) { - this._path.setAttribute('stroke-linejoin', 'round'); - this._path.setAttribute('stroke-linecap', 'round'); - } - if (this.options.fill) { - this._path.setAttribute('fill-rule', 'evenodd'); - } - if (this.options.pointerEvents) { - this._path.setAttribute('pointer-events', this.options.pointerEvents); - } - if (!this.options.clickable && !this.options.pointerEvents) { - this._path.setAttribute('pointer-events', 'none'); - } - this._updateStyle(); - }, - - _updateStyle: function () { - if (this.options.stroke) { - this._path.setAttribute('stroke', this.options.color); - this._path.setAttribute('stroke-opacity', this.options.opacity); - this._path.setAttribute('stroke-width', this.options.weight); - if (this.options.dashArray) { - this._path.setAttribute('stroke-dasharray', this.options.dashArray); - } else { - this._path.removeAttribute('stroke-dasharray'); - } - if (this.options.lineCap) { - this._path.setAttribute('stroke-linecap', this.options.lineCap); - } - if (this.options.lineJoin) { - this._path.setAttribute('stroke-linejoin', this.options.lineJoin); - } - } else { - this._path.setAttribute('stroke', 'none'); - } - if (this.options.fill) { - this._path.setAttribute('fill', this.options.fillColor || this.options.color); - this._path.setAttribute('fill-opacity', this.options.fillOpacity); - } else { - this._path.setAttribute('fill', 'none'); - } - }, - - _updatePath: function () { - var str = this.getPathString(); - if (!str) { - // fix webkit empty string parsing bug - str = 'M0 0'; - } - this._path.setAttribute('d', str); - }, - - // TODO remove duplication with L.Map - _initEvents: function () { - if (this.options.clickable) { - if (L.Browser.svg || !L.Browser.vml) { - L.DomUtil.addClass(this._path, 'leaflet-clickable'); - } - - L.DomEvent.on(this._container, 'click', this._onMouseClick, this); - - var events = ['dblclick', 'mousedown', 'mouseover', - 'mouseout', 'mousemove', 'contextmenu']; - for (var i = 0; i < events.length; i++) { - L.DomEvent.on(this._container, events[i], this._fireMouseEvent, this); - } - } - }, - - _onMouseClick: function (e) { - if (this._map.dragging && this._map.dragging.moved()) { return; } - - this._fireMouseEvent(e); - }, - - _fireMouseEvent: function (e) { - if (!this._map || !this.hasEventListeners(e.type)) { return; } - - var map = this._map, - containerPoint = map.mouseEventToContainerPoint(e), - layerPoint = map.containerPointToLayerPoint(containerPoint), - latlng = map.layerPointToLatLng(layerPoint); - - this.fire(e.type, { - latlng: latlng, - layerPoint: layerPoint, - containerPoint: containerPoint, - originalEvent: e - }); - - if (e.type === 'contextmenu') { - L.DomEvent.preventDefault(e); - } - if (e.type !== 'mousemove') { - L.DomEvent.stopPropagation(e); - } - } -}); - -L.Map.include({ - _initPathRoot: function () { - if (!this._pathRoot) { - this._pathRoot = L.Path.prototype._createElement('svg'); - this._panes.overlayPane.appendChild(this._pathRoot); - - if (this.options.zoomAnimation && L.Browser.any3d) { - L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-animated'); - - this.on({ - 'zoomanim': this._animatePathZoom, - 'zoomend': this._endPathZoom - }); - } else { - L.DomUtil.addClass(this._pathRoot, 'leaflet-zoom-hide'); - } - - this.on('moveend', this._updateSvgViewport); - this._updateSvgViewport(); - } - }, - - _animatePathZoom: function (e) { - var scale = this.getZoomScale(e.zoom), - offset = this._getCenterOffset(e.center)._multiplyBy(-scale)._add(this._pathViewport.min); - - this._pathRoot.style[L.DomUtil.TRANSFORM] = - L.DomUtil.getTranslateString(offset) + ' scale(' + scale + ') '; - - this._pathZooming = true; - }, - - _endPathZoom: function () { - this._pathZooming = false; - }, - - _updateSvgViewport: function () { - - if (this._pathZooming) { - // Do not update SVGs while a zoom animation is going on otherwise the animation will break. - // When the zoom animation ends we will be updated again anyway - // This fixes the case where you do a momentum move and zoom while the move is still ongoing. - return; - } - - this._updatePathViewport(); - - var vp = this._pathViewport, - min = vp.min, - max = vp.max, - width = max.x - min.x, - height = max.y - min.y, - root = this._pathRoot, - pane = this._panes.overlayPane; - - // Hack to make flicker on drag end on mobile webkit less irritating - if (L.Browser.mobileWebkit) { - pane.removeChild(root); - } - - L.DomUtil.setPosition(root, min); - root.setAttribute('width', width); - root.setAttribute('height', height); - root.setAttribute('viewBox', [min.x, min.y, width, height].join(' ')); - - if (L.Browser.mobileWebkit) { - pane.appendChild(root); - } - } -}); - - -/* - * Popup extension to L.Path (polylines, polygons, circles), adding popup-related methods. - */ - -L.Path.include({ - - bindPopup: function (content, options) { - - if (content instanceof L.Popup) { - this._popup = content; - } else { - if (!this._popup || options) { - this._popup = new L.Popup(options, this); - } - this._popup.setContent(content); - } - - if (!this._popupHandlersAdded) { - this - .on('click', this._openPopup, this) - .on('remove', this.closePopup, this); - - this._popupHandlersAdded = true; - } - - return this; - }, - - unbindPopup: function () { - if (this._popup) { - this._popup = null; - this - .off('click', this._openPopup) - .off('remove', this.closePopup); - - this._popupHandlersAdded = false; - } - return this; - }, - - openPopup: function (latlng) { - - if (this._popup) { - // open the popup from one of the path's points if not specified - latlng = latlng || this._latlng || - this._latlngs[Math.floor(this._latlngs.length / 2)]; - - this._openPopup({latlng: latlng}); - } - - return this; - }, - - closePopup: function () { - if (this._popup) { - this._popup._close(); - } - return this; - }, - - _openPopup: function (e) { - this._popup.setLatLng(e.latlng); - this._map.openPopup(this._popup); - } -}); - - -/* - * Vector rendering for IE6-8 through VML. - * Thanks to Dmitry Baranovsky and his Raphael library for inspiration! - */ - -L.Browser.vml = !L.Browser.svg && (function () { - try { - var div = document.createElement('div'); - div.innerHTML = '<v:shape adj="1"/>'; - - var shape = div.firstChild; - shape.style.behavior = 'url(#default#VML)'; - - return shape && (typeof shape.adj === 'object'); - - } catch (e) { - return false; - } -}()); - -L.Path = L.Browser.svg || !L.Browser.vml ? L.Path : L.Path.extend({ - statics: { - VML: true, - CLIP_PADDING: 0.02 - }, - - _createElement: (function () { - try { - document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml'); - return function (name) { - return document.createElement('<lvml:' + name + ' class="lvml">'); - }; - } catch (e) { - return function (name) { - return document.createElement( - '<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">'); - }; - } - }()), - - _initPath: function () { - var container = this._container = this._createElement('shape'); - - L.DomUtil.addClass(container, 'leaflet-vml-shape' + - (this.options.className ? ' ' + this.options.className : '')); - - if (this.options.clickable) { - L.DomUtil.addClass(container, 'leaflet-clickable'); - } - - container.coordsize = '1 1'; - - this._path = this._createElement('path'); - container.appendChild(this._path); - - this._map._pathRoot.appendChild(container); - }, - - _initStyle: function () { - this._updateStyle(); - }, - - _updateStyle: function () { - var stroke = this._stroke, - fill = this._fill, - options = this.options, - container = this._container; - - container.stroked = options.stroke; - container.filled = options.fill; - - if (options.stroke) { - if (!stroke) { - stroke = this._stroke = this._createElement('stroke'); - stroke.endcap = 'round'; - container.appendChild(stroke); - } - stroke.weight = options.weight + 'px'; - stroke.color = options.color; - stroke.opacity = options.opacity; - - if (options.dashArray) { - stroke.dashStyle = L.Util.isArray(options.dashArray) ? - options.dashArray.join(' ') : - options.dashArray.replace(/( *, *)/g, ' '); - } else { - stroke.dashStyle = ''; - } - if (options.lineCap) { - stroke.endcap = options.lineCap.replace('butt', 'flat'); - } - if (options.lineJoin) { - stroke.joinstyle = options.lineJoin; - } - - } else if (stroke) { - container.removeChild(stroke); - this._stroke = null; - } - - if (options.fill) { - if (!fill) { - fill = this._fill = this._createElement('fill'); - container.appendChild(fill); - } - fill.color = options.fillColor || options.color; - fill.opacity = options.fillOpacity; - - } else if (fill) { - container.removeChild(fill); - this._fill = null; - } - }, - - _updatePath: function () { - var style = this._container.style; - - style.display = 'none'; - this._path.v = this.getPathString() + ' '; // the space fixes IE empty path string bug - style.display = ''; - } -}); - -L.Map.include(L.Browser.svg || !L.Browser.vml ? {} : { - _initPathRoot: function () { - if (this._pathRoot) { return; } - - var root = this._pathRoot = document.createElement('div'); - root.className = 'leaflet-vml-container'; - this._panes.overlayPane.appendChild(root); - - this.on('moveend', this._updatePathViewport); - this._updatePathViewport(); - } -}); - - -/* - * Vector rendering for all browsers that support canvas. - */ - -L.Browser.canvas = (function () { - return !!document.createElement('canvas').getContext; -}()); - -L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({ - statics: { - //CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value - CANVAS: true, - SVG: false - }, - - redraw: function () { - if (this._map) { - this.projectLatlngs(); - this._requestUpdate(); - } - return this; - }, - - setStyle: function (style) { - L.setOptions(this, style); - - if (this._map) { - this._updateStyle(); - this._requestUpdate(); - } - return this; - }, - - onRemove: function (map) { - map - .off('viewreset', this.projectLatlngs, this) - .off('moveend', this._updatePath, this); - - if (this.options.clickable) { - this._map.off('click', this._onClick, this); - this._map.off('mousemove', this._onMouseMove, this); - } - - this._requestUpdate(); - - this.fire('remove'); - this._map = null; - }, - - _requestUpdate: function () { - if (this._map && !L.Path._updateRequest) { - L.Path._updateRequest = L.Util.requestAnimFrame(this._fireMapMoveEnd, this._map); - } - }, - - _fireMapMoveEnd: function () { - L.Path._updateRequest = null; - this.fire('moveend'); - }, - - _initElements: function () { - this._map._initPathRoot(); - this._ctx = this._map._canvasCtx; - }, - - _updateStyle: function () { - var options = this.options; - - if (options.stroke) { - this._ctx.lineWidth = options.weight; - this._ctx.strokeStyle = options.color; - } - if (options.fill) { - this._ctx.fillStyle = options.fillColor || options.color; - } - - if (options.lineCap) { - this._ctx.lineCap = options.lineCap; - } - if (options.lineJoin) { - this._ctx.lineJoin = options.lineJoin; - } - }, - - _drawPath: function () { - var i, j, len, len2, point, drawMethod; - - this._ctx.beginPath(); - - for (i = 0, len = this._parts.length; i < len; i++) { - for (j = 0, len2 = this._parts[i].length; j < len2; j++) { - point = this._parts[i][j]; - drawMethod = (j === 0 ? 'move' : 'line') + 'To'; - - this._ctx[drawMethod](point.x, point.y); - } - // TODO refactor ugly hack - if (this instanceof L.Polygon) { - this._ctx.closePath(); - } - } - }, - - _checkIfEmpty: function () { - return !this._parts.length; - }, - - _updatePath: function () { - if (this._checkIfEmpty()) { return; } - - var ctx = this._ctx, - options = this.options; - - this._drawPath(); - ctx.save(); - this._updateStyle(); - - if (options.fill) { - ctx.globalAlpha = options.fillOpacity; - ctx.fill(options.fillRule || 'evenodd'); - } - - if (options.stroke) { - ctx.globalAlpha = options.opacity; - ctx.stroke(); - } - - ctx.restore(); - - // TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature - }, - - _initEvents: function () { - if (this.options.clickable) { - this._map.on('mousemove', this._onMouseMove, this); - this._map.on('click dblclick contextmenu', this._fireMouseEvent, this); - } - }, - - _fireMouseEvent: function (e) { - if (this._containsPoint(e.layerPoint)) { - this.fire(e.type, e); - } - }, - - _onMouseMove: function (e) { - if (!this._map || this._map._animatingZoom) { return; } - - // TODO don't do on each move - if (this._containsPoint(e.layerPoint)) { - this._ctx.canvas.style.cursor = 'pointer'; - this._mouseInside = true; - this.fire('mouseover', e); - - } else if (this._mouseInside) { - this._ctx.canvas.style.cursor = ''; - this._mouseInside = false; - this.fire('mouseout', e); - } - } -}); - -L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : { - _initPathRoot: function () { - var root = this._pathRoot, - ctx; - - if (!root) { - root = this._pathRoot = document.createElement('canvas'); - root.style.position = 'absolute'; - ctx = this._canvasCtx = root.getContext('2d'); - - ctx.lineCap = 'round'; - ctx.lineJoin = 'round'; - - this._panes.overlayPane.appendChild(root); - - if (this.options.zoomAnimation) { - this._pathRoot.className = 'leaflet-zoom-animated'; - this.on('zoomanim', this._animatePathZoom); - this.on('zoomend', this._endPathZoom); - } - this.on('moveend', this._updateCanvasViewport); - this._updateCanvasViewport(); - } - }, - - _updateCanvasViewport: function () { - // don't redraw while zooming. See _updateSvgViewport for more details - if (this._pathZooming) { return; } - this._updatePathViewport(); - - var vp = this._pathViewport, - min = vp.min, - size = vp.max.subtract(min), - root = this._pathRoot; - - //TODO check if this works properly on mobile webkit - L.DomUtil.setPosition(root, min); - root.width = size.x; - root.height = size.y; - root.getContext('2d').translate(-min.x, -min.y); - } -}); - - -/* - * L.LineUtil contains different utility functions for line segments - * and polylines (clipping, simplification, distances, etc.) - */ - -/*jshint bitwise:false */ // allow bitwise operations for this file - -L.LineUtil = { - - // Simplify polyline with vertex reduction and Douglas-Peucker simplification. - // Improves rendering performance dramatically by lessening the number of points to draw. - - simplify: function (/*Point[]*/ points, /*Number*/ tolerance) { - if (!tolerance || !points.length) { - return points.slice(); - } - - var sqTolerance = tolerance * tolerance; - - // stage 1: vertex reduction - points = this._reducePoints(points, sqTolerance); - - // stage 2: Douglas-Peucker simplification - points = this._simplifyDP(points, sqTolerance); - - return points; - }, - - // distance from a point to a segment between two points - pointToSegmentDistance: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) { - return Math.sqrt(this._sqClosestPointOnSegment(p, p1, p2, true)); - }, - - closestPointOnSegment: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) { - return this._sqClosestPointOnSegment(p, p1, p2); - }, - - // Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm - _simplifyDP: function (points, sqTolerance) { - - var len = points.length, - ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array, - markers = new ArrayConstructor(len); - - markers[0] = markers[len - 1] = 1; - - this._simplifyDPStep(points, markers, sqTolerance, 0, len - 1); - - var i, - newPoints = []; - - for (i = 0; i < len; i++) { - if (markers[i]) { - newPoints.push(points[i]); - } - } - - return newPoints; - }, - - _simplifyDPStep: function (points, markers, sqTolerance, first, last) { - - var maxSqDist = 0, - index, i, sqDist; - - for (i = first + 1; i <= last - 1; i++) { - sqDist = this._sqClosestPointOnSegment(points[i], points[first], points[last], true); - - if (sqDist > maxSqDist) { - index = i; - maxSqDist = sqDist; - } - } - - if (maxSqDist > sqTolerance) { - markers[index] = 1; - - this._simplifyDPStep(points, markers, sqTolerance, first, index); - this._simplifyDPStep(points, markers, sqTolerance, index, last); - } - }, - - // reduce points that are too close to each other to a single point - _reducePoints: function (points, sqTolerance) { - var reducedPoints = [points[0]]; - - for (var i = 1, prev = 0, len = points.length; i < len; i++) { - if (this._sqDist(points[i], points[prev]) > sqTolerance) { - reducedPoints.push(points[i]); - prev = i; - } - } - if (prev < len - 1) { - reducedPoints.push(points[len - 1]); - } - return reducedPoints; - }, - - // Cohen-Sutherland line clipping algorithm. - // Used to avoid rendering parts of a polyline that are not currently visible. - - clipSegment: function (a, b, bounds, useLastCode) { - var codeA = useLastCode ? this._lastCode : this._getBitCode(a, bounds), - codeB = this._getBitCode(b, bounds), - - codeOut, p, newCode; - - // save 2nd code to avoid calculating it on the next segment - this._lastCode = codeB; - - while (true) { - // if a,b is inside the clip window (trivial accept) - if (!(codeA | codeB)) { - return [a, b]; - // if a,b is outside the clip window (trivial reject) - } else if (codeA & codeB) { - return false; - // other cases - } else { - codeOut = codeA || codeB; - p = this._getEdgeIntersection(a, b, codeOut, bounds); - newCode = this._getBitCode(p, bounds); - - if (codeOut === codeA) { - a = p; - codeA = newCode; - } else { - b = p; - codeB = newCode; - } - } - } - }, - - _getEdgeIntersection: function (a, b, code, bounds) { - var dx = b.x - a.x, - dy = b.y - a.y, - min = bounds.min, - max = bounds.max; - - if (code & 8) { // top - return new L.Point(a.x + dx * (max.y - a.y) / dy, max.y); - } else if (code & 4) { // bottom - return new L.Point(a.x + dx * (min.y - a.y) / dy, min.y); - } else if (code & 2) { // right - return new L.Point(max.x, a.y + dy * (max.x - a.x) / dx); - } else if (code & 1) { // left - return new L.Point(min.x, a.y + dy * (min.x - a.x) / dx); - } - }, - - _getBitCode: function (/*Point*/ p, bounds) { - var code = 0; - - if (p.x < bounds.min.x) { // left - code |= 1; - } else if (p.x > bounds.max.x) { // right - code |= 2; - } - if (p.y < bounds.min.y) { // bottom - code |= 4; - } else if (p.y > bounds.max.y) { // top - code |= 8; - } - - return code; - }, - - // square distance (to avoid unnecessary Math.sqrt calls) - _sqDist: function (p1, p2) { - var dx = p2.x - p1.x, - dy = p2.y - p1.y; - return dx * dx + dy * dy; - }, - - // return closest point on segment or distance to that point - _sqClosestPointOnSegment: function (p, p1, p2, sqDist) { - var x = p1.x, - y = p1.y, - dx = p2.x - x, - dy = p2.y - y, - dot = dx * dx + dy * dy, - t; - - if (dot > 0) { - t = ((p.x - x) * dx + (p.y - y) * dy) / dot; - - if (t > 1) { - x = p2.x; - y = p2.y; - } else if (t > 0) { - x += dx * t; - y += dy * t; - } - } - - dx = p.x - x; - dy = p.y - y; - - return sqDist ? dx * dx + dy * dy : new L.Point(x, y); - } -}; - - -/* - * L.Polyline is used to display polylines on a map. - */ - -L.Polyline = L.Path.extend({ - initialize: function (latlngs, options) { - L.Path.prototype.initialize.call(this, options); - - this._latlngs = this._convertLatLngs(latlngs); - }, - - options: { - // how much to simplify the polyline on each zoom level - // more = better performance and smoother look, less = more accurate - smoothFactor: 1.0, - noClip: false - }, - - projectLatlngs: function () { - this._originalPoints = []; - - for (var i = 0, len = this._latlngs.length; i < len; i++) { - this._originalPoints[i] = this._map.latLngToLayerPoint(this._latlngs[i]); - } - }, - - getPathString: function () { - for (var i = 0, len = this._parts.length, str = ''; i < len; i++) { - str += this._getPathPartStr(this._parts[i]); - } - return str; - }, - - getLatLngs: function () { - return this._latlngs; - }, - - setLatLngs: function (latlngs) { - this._latlngs = this._convertLatLngs(latlngs); - return this.redraw(); - }, - - addLatLng: function (latlng) { - this._latlngs.push(L.latLng(latlng)); - return this.redraw(); - }, - - spliceLatLngs: function () { // (Number index, Number howMany) - var removed = [].splice.apply(this._latlngs, arguments); - this._convertLatLngs(this._latlngs, true); - this.redraw(); - return removed; - }, - - closestLayerPoint: function (p) { - var minDistance = Infinity, parts = this._parts, p1, p2, minPoint = null; - - for (var j = 0, jLen = parts.length; j < jLen; j++) { - var points = parts[j]; - for (var i = 1, len = points.length; i < len; i++) { - p1 = points[i - 1]; - p2 = points[i]; - var sqDist = L.LineUtil._sqClosestPointOnSegment(p, p1, p2, true); - if (sqDist < minDistance) { - minDistance = sqDist; - minPoint = L.LineUtil._sqClosestPointOnSegment(p, p1, p2); - } - } - } - if (minPoint) { - minPoint.distance = Math.sqrt(minDistance); - } - return minPoint; - }, - - getBounds: function () { - return new L.LatLngBounds(this.getLatLngs()); - }, - - _convertLatLngs: function (latlngs, overwrite) { - var i, len, target = overwrite ? latlngs : []; - - for (i = 0, len = latlngs.length; i < len; i++) { - if (L.Util.isArray(latlngs[i]) && typeof latlngs[i][0] !== 'number') { - return; - } - target[i] = L.latLng(latlngs[i]); - } - return target; - }, - - _initEvents: function () { - L.Path.prototype._initEvents.call(this); - }, - - _getPathPartStr: function (points) { - var round = L.Path.VML; - - for (var j = 0, len2 = points.length, str = '', p; j < len2; j++) { - p = points[j]; - if (round) { - p._round(); - } - str += (j ? 'L' : 'M') + p.x + ' ' + p.y; - } - return str; - }, - - _clipPoints: function () { - var points = this._originalPoints, - len = points.length, - i, k, segment; - - if (this.options.noClip) { - this._parts = [points]; - return; - } - - this._parts = []; - - var parts = this._parts, - vp = this._map._pathViewport, - lu = L.LineUtil; - - for (i = 0, k = 0; i < len - 1; i++) { - segment = lu.clipSegment(points[i], points[i + 1], vp, i); - if (!segment) { - continue; - } - - parts[k] = parts[k] || []; - parts[k].push(segment[0]); - - // if segment goes out of screen, or it's the last one, it's the end of the line part - if ((segment[1] !== points[i + 1]) || (i === len - 2)) { - parts[k].push(segment[1]); - k++; - } - } - }, - - // simplify each clipped part of the polyline - _simplifyPoints: function () { - var parts = this._parts, - lu = L.LineUtil; - - for (var i = 0, len = parts.length; i < len; i++) { - parts[i] = lu.simplify(parts[i], this.options.smoothFactor); - } - }, - - _updatePath: function () { - if (!this._map) { return; } - - this._clipPoints(); - this._simplifyPoints(); - - L.Path.prototype._updatePath.call(this); - } -}); - -L.polyline = function (latlngs, options) { - return new L.Polyline(latlngs, options); -}; - - -/* - * L.PolyUtil contains utility functions for polygons (clipping, etc.). - */ - -/*jshint bitwise:false */ // allow bitwise operations here - -L.PolyUtil = {}; - -/* - * Sutherland-Hodgeman polygon clipping algorithm. - * Used to avoid rendering parts of a polygon that are not currently visible. - */ -L.PolyUtil.clipPolygon = function (points, bounds) { - var clippedPoints, - edges = [1, 4, 2, 8], - i, j, k, - a, b, - len, edge, p, - lu = L.LineUtil; - - for (i = 0, len = points.length; i < len; i++) { - points[i]._code = lu._getBitCode(points[i], bounds); - } - - // for each edge (left, bottom, right, top) - for (k = 0; k < 4; k++) { - edge = edges[k]; - clippedPoints = []; - - for (i = 0, len = points.length, j = len - 1; i < len; j = i++) { - a = points[i]; - b = points[j]; - - // if a is inside the clip window - if (!(a._code & edge)) { - // if b is outside the clip window (a->b goes out of screen) - if (b._code & edge) { - p = lu._getEdgeIntersection(b, a, edge, bounds); - p._code = lu._getBitCode(p, bounds); - clippedPoints.push(p); - } - clippedPoints.push(a); - - // else if b is inside the clip window (a->b enters the screen) - } else if (!(b._code & edge)) { - p = lu._getEdgeIntersection(b, a, edge, bounds); - p._code = lu._getBitCode(p, bounds); - clippedPoints.push(p); - } - } - points = clippedPoints; - } - - return points; -}; - - -/* - * L.Polygon is used to display polygons on a map. - */ - -L.Polygon = L.Polyline.extend({ - options: { - fill: true - }, - - initialize: function (latlngs, options) { - L.Polyline.prototype.initialize.call(this, latlngs, options); - this._initWithHoles(latlngs); - }, - - _initWithHoles: function (latlngs) { - var i, len, hole; - if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) { - this._latlngs = this._convertLatLngs(latlngs[0]); - this._holes = latlngs.slice(1); - - for (i = 0, len = this._holes.length; i < len; i++) { - hole = this._holes[i] = this._convertLatLngs(this._holes[i]); - if (hole[0].equals(hole[hole.length - 1])) { - hole.pop(); - } - } - } - - // filter out last point if its equal to the first one - latlngs = this._latlngs; - - if (latlngs.length >= 2 && latlngs[0].equals(latlngs[latlngs.length - 1])) { - latlngs.pop(); - } - }, - - projectLatlngs: function () { - L.Polyline.prototype.projectLatlngs.call(this); - - // project polygon holes points - // TODO move this logic to Polyline to get rid of duplication - this._holePoints = []; - - if (!this._holes) { return; } - - var i, j, len, len2; - - for (i = 0, len = this._holes.length; i < len; i++) { - this._holePoints[i] = []; - - for (j = 0, len2 = this._holes[i].length; j < len2; j++) { - this._holePoints[i][j] = this._map.latLngToLayerPoint(this._holes[i][j]); - } - } - }, - - setLatLngs: function (latlngs) { - if (latlngs && L.Util.isArray(latlngs[0]) && (typeof latlngs[0][0] !== 'number')) { - this._initWithHoles(latlngs); - return this.redraw(); - } else { - return L.Polyline.prototype.setLatLngs.call(this, latlngs); - } - }, - - _clipPoints: function () { - var points = this._originalPoints, - newParts = []; - - this._parts = [points].concat(this._holePoints); - - if (this.options.noClip) { return; } - - for (var i = 0, len = this._parts.length; i < len; i++) { - var clipped = L.PolyUtil.clipPolygon(this._parts[i], this._map._pathViewport); - if (clipped.length) { - newParts.push(clipped); - } - } - - this._parts = newParts; - }, - - _getPathPartStr: function (points) { - var str = L.Polyline.prototype._getPathPartStr.call(this, points); - return str + (L.Browser.svg ? 'z' : 'x'); - } -}); - -L.polygon = function (latlngs, options) { - return new L.Polygon(latlngs, options); -}; - - -/* - * Contains L.MultiPolyline and L.MultiPolygon layers. - */ - -(function () { - function createMulti(Klass) { - - return L.FeatureGroup.extend({ - - initialize: function (latlngs, options) { - this._layers = {}; - this._options = options; - this.setLatLngs(latlngs); - }, - - setLatLngs: function (latlngs) { - var i = 0, - len = latlngs.length; - - this.eachLayer(function (layer) { - if (i < len) { - layer.setLatLngs(latlngs[i++]); - } else { - this.removeLayer(layer); - } - }, this); - - while (i < len) { - this.addLayer(new Klass(latlngs[i++], this._options)); - } - - return this; - }, - - getLatLngs: function () { - var latlngs = []; - - this.eachLayer(function (layer) { - latlngs.push(layer.getLatLngs()); - }); - - return latlngs; - } - }); - } - - L.MultiPolyline = createMulti(L.Polyline); - L.MultiPolygon = createMulti(L.Polygon); - - L.multiPolyline = function (latlngs, options) { - return new L.MultiPolyline(latlngs, options); - }; - - L.multiPolygon = function (latlngs, options) { - return new L.MultiPolygon(latlngs, options); - }; -}()); - - -/* - * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object. - */ - -L.Rectangle = L.Polygon.extend({ - initialize: function (latLngBounds, options) { - L.Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options); - }, - - setBounds: function (latLngBounds) { - this.setLatLngs(this._boundsToLatLngs(latLngBounds)); - }, - - _boundsToLatLngs: function (latLngBounds) { - latLngBounds = L.latLngBounds(latLngBounds); - return [ - latLngBounds.getSouthWest(), - latLngBounds.getNorthWest(), - latLngBounds.getNorthEast(), - latLngBounds.getSouthEast() - ]; - } -}); - -L.rectangle = function (latLngBounds, options) { - return new L.Rectangle(latLngBounds, options); -}; - - -/* - * L.Circle is a circle overlay (with a certain radius in meters). - */ - -L.Circle = L.Path.extend({ - initialize: function (latlng, radius, options) { - L.Path.prototype.initialize.call(this, options); - - this._latlng = L.latLng(latlng); - this._mRadius = radius; - }, - - options: { - fill: true - }, - - setLatLng: function (latlng) { - this._latlng = L.latLng(latlng); - return this.redraw(); - }, - - setRadius: function (radius) { - this._mRadius = radius; - return this.redraw(); - }, - - projectLatlngs: function () { - var lngRadius = this._getLngRadius(), - latlng = this._latlng, - pointLeft = this._map.latLngToLayerPoint([latlng.lat, latlng.lng - lngRadius]); - - this._point = this._map.latLngToLayerPoint(latlng); - this._radius = Math.max(this._point.x - pointLeft.x, 1); - }, - - getBounds: function () { - var lngRadius = this._getLngRadius(), - latRadius = (this._mRadius / 40075017) * 360, - latlng = this._latlng; - - return new L.LatLngBounds( - [latlng.lat - latRadius, latlng.lng - lngRadius], - [latlng.lat + latRadius, latlng.lng + lngRadius]); - }, - - getLatLng: function () { - return this._latlng; - }, - - getPathString: function () { - var p = this._point, - r = this._radius; - - if (this._checkIfEmpty()) { - return ''; - } - - if (L.Browser.svg) { - return 'M' + p.x + ',' + (p.y - r) + - 'A' + r + ',' + r + ',0,1,1,' + - (p.x - 0.1) + ',' + (p.y - r) + ' z'; - } else { - p._round(); - r = Math.round(r); - return 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r + ' 0,' + (65535 * 360); - } - }, - - getRadius: function () { - return this._mRadius; - }, - - // TODO Earth hardcoded, move into projection code! - - _getLatRadius: function () { - return (this._mRadius / 40075017) * 360; - }, - - _getLngRadius: function () { - return this._getLatRadius() / Math.cos(L.LatLng.DEG_TO_RAD * this._latlng.lat); - }, - - _checkIfEmpty: function () { - if (!this._map) { - return false; - } - var vp = this._map._pathViewport, - r = this._radius, - p = this._point; - - return p.x - r > vp.max.x || p.y - r > vp.max.y || - p.x + r < vp.min.x || p.y + r < vp.min.y; - } -}); - -L.circle = function (latlng, radius, options) { - return new L.Circle(latlng, radius, options); -}; - - -/* - * L.CircleMarker is a circle overlay with a permanent pixel radius. - */ - -L.CircleMarker = L.Circle.extend({ - options: { - radius: 10, - weight: 2 - }, - - initialize: function (latlng, options) { - L.Circle.prototype.initialize.call(this, latlng, null, options); - this._radius = this.options.radius; - }, - - projectLatlngs: function () { - this._point = this._map.latLngToLayerPoint(this._latlng); - }, - - _updateStyle : function () { - L.Circle.prototype._updateStyle.call(this); - this.setRadius(this.options.radius); - }, - - setLatLng: function (latlng) { - L.Circle.prototype.setLatLng.call(this, latlng); - if (this._popup && this._popup._isOpen) { - this._popup.setLatLng(latlng); - } - return this; - }, - - setRadius: function (radius) { - this.options.radius = this._radius = radius; - return this.redraw(); - }, - - getRadius: function () { - return this._radius; - } -}); - -L.circleMarker = function (latlng, options) { - return new L.CircleMarker(latlng, options); -}; - - -/* - * Extends L.Polyline to be able to manually detect clicks on Canvas-rendered polylines. - */ - -L.Polyline.include(!L.Path.CANVAS ? {} : { - _containsPoint: function (p, closed) { - var i, j, k, len, len2, dist, part, - w = this.options.weight / 2; - - if (L.Browser.touch) { - w += 10; // polyline click tolerance on touch devices - } - - for (i = 0, len = this._parts.length; i < len; i++) { - part = this._parts[i]; - for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { - if (!closed && (j === 0)) { - continue; - } - - dist = L.LineUtil.pointToSegmentDistance(p, part[k], part[j]); - - if (dist <= w) { - return true; - } - } - } - return false; - } -}); - - -/* - * Extends L.Polygon to be able to manually detect clicks on Canvas-rendered polygons. - */ - -L.Polygon.include(!L.Path.CANVAS ? {} : { - _containsPoint: function (p) { - var inside = false, - part, p1, p2, - i, j, k, - len, len2; - - // TODO optimization: check if within bounds first - - if (L.Polyline.prototype._containsPoint.call(this, p, true)) { - // click on polygon border - return true; - } - - // ray casting algorithm for detecting if point is in polygon - - for (i = 0, len = this._parts.length; i < len; i++) { - part = this._parts[i]; - - for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { - p1 = part[j]; - p2 = part[k]; - - if (((p1.y > p.y) !== (p2.y > p.y)) && - (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) { - inside = !inside; - } - } - } - - return inside; - } -}); - - -/* - * Extends L.Circle with Canvas-specific code. - */ - -L.Circle.include(!L.Path.CANVAS ? {} : { - _drawPath: function () { - var p = this._point; - this._ctx.beginPath(); - this._ctx.arc(p.x, p.y, this._radius, 0, Math.PI * 2, false); - }, - - _containsPoint: function (p) { - var center = this._point, - w2 = this.options.stroke ? this.options.weight / 2 : 0; - - return (p.distanceTo(center) <= this._radius + w2); - } -}); - - -/* - * CircleMarker canvas specific drawing parts. - */ - -L.CircleMarker.include(!L.Path.CANVAS ? {} : { - _updateStyle: function () { - L.Path.prototype._updateStyle.call(this); - } -}); - - -/* - * L.GeoJSON turns any GeoJSON data into a Leaflet layer. - */ - -L.GeoJSON = L.FeatureGroup.extend({ - - initialize: function (geojson, options) { - L.setOptions(this, options); - - this._layers = {}; - - if (geojson) { - this.addData(geojson); - } - }, - - addData: function (geojson) { - var features = L.Util.isArray(geojson) ? geojson : geojson.features, - i, len, feature; - - if (features) { - for (i = 0, len = features.length; i < len; i++) { - // Only add this if geometry or geometries are set and not null - feature = features[i]; - if (feature.geometries || feature.geometry || feature.features || feature.coordinates) { - this.addData(features[i]); - } - } - return this; - } - - var options = this.options; - - if (options.filter && !options.filter(geojson)) { return; } - - var layer = L.GeoJSON.geometryToLayer(geojson, options.pointToLayer, options.coordsToLatLng, options); - layer.feature = L.GeoJSON.asFeature(geojson); - - layer.defaultOptions = layer.options; - this.resetStyle(layer); - - if (options.onEachFeature) { - options.onEachFeature(geojson, layer); - } - - return this.addLayer(layer); - }, - - resetStyle: function (layer) { - var style = this.options.style; - if (style) { - // reset any custom styles - L.Util.extend(layer.options, layer.defaultOptions); - - this._setLayerStyle(layer, style); - } - }, - - setStyle: function (style) { - this.eachLayer(function (layer) { - this._setLayerStyle(layer, style); - }, this); - }, - - _setLayerStyle: function (layer, style) { - if (typeof style === 'function') { - style = style(layer.feature); - } - if (layer.setStyle) { - layer.setStyle(style); - } - } -}); - -L.extend(L.GeoJSON, { - geometryToLayer: function (geojson, pointToLayer, coordsToLatLng, vectorOptions) { - var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson, - coords = geometry.coordinates, - layers = [], - latlng, latlngs, i, len; - - coordsToLatLng = coordsToLatLng || this.coordsToLatLng; - - switch (geometry.type) { - case 'Point': - latlng = coordsToLatLng(coords); - return pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng); - - case 'MultiPoint': - for (i = 0, len = coords.length; i < len; i++) { - latlng = coordsToLatLng(coords[i]); - layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new L.Marker(latlng)); - } - return new L.FeatureGroup(layers); - - case 'LineString': - latlngs = this.coordsToLatLngs(coords, 0, coordsToLatLng); - return new L.Polyline(latlngs, vectorOptions); - - case 'Polygon': - if (coords.length === 2 && !coords[1].length) { - throw new Error('Invalid GeoJSON object.'); - } - latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng); - return new L.Polygon(latlngs, vectorOptions); - - case 'MultiLineString': - latlngs = this.coordsToLatLngs(coords, 1, coordsToLatLng); - return new L.MultiPolyline(latlngs, vectorOptions); - - case 'MultiPolygon': - latlngs = this.coordsToLatLngs(coords, 2, coordsToLatLng); - return new L.MultiPolygon(latlngs, vectorOptions); - - case 'GeometryCollection': - for (i = 0, len = geometry.geometries.length; i < len; i++) { - - layers.push(this.geometryToLayer({ - geometry: geometry.geometries[i], - type: 'Feature', - properties: geojson.properties - }, pointToLayer, coordsToLatLng, vectorOptions)); - } - return new L.FeatureGroup(layers); - - default: - throw new Error('Invalid GeoJSON object.'); - } - }, - - coordsToLatLng: function (coords) { // (Array[, Boolean]) -> LatLng - return new L.LatLng(coords[1], coords[0], coords[2]); - }, - - coordsToLatLngs: function (coords, levelsDeep, coordsToLatLng) { // (Array[, Number, Function]) -> Array - var latlng, i, len, - latlngs = []; - - for (i = 0, len = coords.length; i < len; i++) { - latlng = levelsDeep ? - this.coordsToLatLngs(coords[i], levelsDeep - 1, coordsToLatLng) : - (coordsToLatLng || this.coordsToLatLng)(coords[i]); - - latlngs.push(latlng); - } - - return latlngs; - }, - - latLngToCoords: function (latlng) { - var coords = [latlng.lng, latlng.lat]; - - if (latlng.alt !== undefined) { - coords.push(latlng.alt); - } - return coords; - }, - - latLngsToCoords: function (latLngs) { - var coords = []; - - for (var i = 0, len = latLngs.length; i < len; i++) { - coords.push(L.GeoJSON.latLngToCoords(latLngs[i])); - } - - return coords; - }, - - getFeature: function (layer, newGeometry) { - return layer.feature ? L.extend({}, layer.feature, {geometry: newGeometry}) : L.GeoJSON.asFeature(newGeometry); - }, - - asFeature: function (geoJSON) { - if (geoJSON.type === 'Feature') { - return geoJSON; - } - - return { - type: 'Feature', - properties: {}, - geometry: geoJSON - }; - } -}); - -var PointToGeoJSON = { - toGeoJSON: function () { - return L.GeoJSON.getFeature(this, { - type: 'Point', - coordinates: L.GeoJSON.latLngToCoords(this.getLatLng()) - }); - } -}; - -L.Marker.include(PointToGeoJSON); -L.Circle.include(PointToGeoJSON); -L.CircleMarker.include(PointToGeoJSON); - -L.Polyline.include({ - toGeoJSON: function () { - return L.GeoJSON.getFeature(this, { - type: 'LineString', - coordinates: L.GeoJSON.latLngsToCoords(this.getLatLngs()) - }); - } -}); - -L.Polygon.include({ - toGeoJSON: function () { - var coords = [L.GeoJSON.latLngsToCoords(this.getLatLngs())], - i, len, hole; - - coords[0].push(coords[0][0]); - - if (this._holes) { - for (i = 0, len = this._holes.length; i < len; i++) { - hole = L.GeoJSON.latLngsToCoords(this._holes[i]); - hole.push(hole[0]); - coords.push(hole); - } - } - - return L.GeoJSON.getFeature(this, { - type: 'Polygon', - coordinates: coords - }); - } -}); - -(function () { - function multiToGeoJSON(type) { - return function () { - var coords = []; - - this.eachLayer(function (layer) { - coords.push(layer.toGeoJSON().geometry.coordinates); - }); - - return L.GeoJSON.getFeature(this, { - type: type, - coordinates: coords - }); - }; - } - - L.MultiPolyline.include({toGeoJSON: multiToGeoJSON('MultiLineString')}); - L.MultiPolygon.include({toGeoJSON: multiToGeoJSON('MultiPolygon')}); - - L.LayerGroup.include({ - toGeoJSON: function () { - - var geometry = this.feature && this.feature.geometry, - jsons = [], - json; - - if (geometry && geometry.type === 'MultiPoint') { - return multiToGeoJSON('MultiPoint').call(this); - } - - var isGeometryCollection = geometry && geometry.type === 'GeometryCollection'; - - this.eachLayer(function (layer) { - if (layer.toGeoJSON) { - json = layer.toGeoJSON(); - jsons.push(isGeometryCollection ? json.geometry : L.GeoJSON.asFeature(json)); - } - }); - - if (isGeometryCollection) { - return L.GeoJSON.getFeature(this, { - geometries: jsons, - type: 'GeometryCollection' - }); - } - - return { - type: 'FeatureCollection', - features: jsons - }; - } - }); -}()); - -L.geoJson = function (geojson, options) { - return new L.GeoJSON(geojson, options); -}; - - -/* - * L.DomEvent contains functions for working with DOM events. - */ - -L.DomEvent = { - /* inspired by John Resig, Dean Edwards and YUI addEvent implementations */ - addListener: function (obj, type, fn, context) { // (HTMLElement, String, Function[, Object]) - - var id = L.stamp(fn), - key = '_leaflet_' + type + id, - handler, originalHandler, newType; - - if (obj[key]) { return this; } - - handler = function (e) { - return fn.call(context || obj, e || L.DomEvent._getEvent()); - }; - - if (L.Browser.pointer && type.indexOf('touch') === 0) { - return this.addPointerListener(obj, type, handler, id); - } - if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) { - this.addDoubleTapListener(obj, handler, id); - } - - if ('addEventListener' in obj) { - - if (type === 'mousewheel') { - obj.addEventListener('DOMMouseScroll', handler, false); - obj.addEventListener(type, handler, false); - - } else if ((type === 'mouseenter') || (type === 'mouseleave')) { - - originalHandler = handler; - newType = (type === 'mouseenter' ? 'mouseover' : 'mouseout'); - - handler = function (e) { - if (!L.DomEvent._checkMouse(obj, e)) { return; } - return originalHandler(e); - }; - - obj.addEventListener(newType, handler, false); - - } else if (type === 'click' && L.Browser.android) { - originalHandler = handler; - handler = function (e) { - return L.DomEvent._filterClick(e, originalHandler); - }; - - obj.addEventListener(type, handler, false); - } else { - obj.addEventListener(type, handler, false); - } - - } else if ('attachEvent' in obj) { - obj.attachEvent('on' + type, handler); - } - - obj[key] = handler; - - return this; - }, - - removeListener: function (obj, type, fn) { // (HTMLElement, String, Function) - - var id = L.stamp(fn), - key = '_leaflet_' + type + id, - handler = obj[key]; - - if (!handler) { return this; } - - if (L.Browser.pointer && type.indexOf('touch') === 0) { - this.removePointerListener(obj, type, id); - } else if (L.Browser.touch && (type === 'dblclick') && this.removeDoubleTapListener) { - this.removeDoubleTapListener(obj, id); - - } else if ('removeEventListener' in obj) { - - if (type === 'mousewheel') { - obj.removeEventListener('DOMMouseScroll', handler, false); - obj.removeEventListener(type, handler, false); - - } else if ((type === 'mouseenter') || (type === 'mouseleave')) { - obj.removeEventListener((type === 'mouseenter' ? 'mouseover' : 'mouseout'), handler, false); - } else { - obj.removeEventListener(type, handler, false); - } - } else if ('detachEvent' in obj) { - obj.detachEvent('on' + type, handler); - } - - obj[key] = null; - - return this; - }, - - stopPropagation: function (e) { - - if (e.stopPropagation) { - e.stopPropagation(); - } else { - e.cancelBubble = true; - } - L.DomEvent._skipped(e); - - return this; - }, - - disableScrollPropagation: function (el) { - var stop = L.DomEvent.stopPropagation; - - return L.DomEvent - .on(el, 'mousewheel', stop) - .on(el, 'MozMousePixelScroll', stop); - }, - - disableClickPropagation: function (el) { - var stop = L.DomEvent.stopPropagation; - - for (var i = L.Draggable.START.length - 1; i >= 0; i--) { - L.DomEvent.on(el, L.Draggable.START[i], stop); - } - - return L.DomEvent - .on(el, 'click', L.DomEvent._fakeStop) - .on(el, 'dblclick', stop); - }, - - preventDefault: function (e) { - - if (e.preventDefault) { - e.preventDefault(); - } else { - e.returnValue = false; - } - return this; - }, - - stop: function (e) { - return L.DomEvent - .preventDefault(e) - .stopPropagation(e); - }, - - getMousePosition: function (e, container) { - if (!container) { - return new L.Point(e.clientX, e.clientY); - } - - var rect = container.getBoundingClientRect(); - - return new L.Point( - e.clientX - rect.left - container.clientLeft, - e.clientY - rect.top - container.clientTop); - }, - - getWheelDelta: function (e) { - - var delta = 0; - - if (e.wheelDelta) { - delta = e.wheelDelta / 120; - } - if (e.detail) { - delta = -e.detail / 3; - } - return delta; - }, - - _skipEvents: {}, - - _fakeStop: function (e) { - // fakes stopPropagation by setting a special event flag, checked/reset with L.DomEvent._skipped(e) - L.DomEvent._skipEvents[e.type] = true; - }, - - _skipped: function (e) { - var skipped = this._skipEvents[e.type]; - // reset when checking, as it's only used in map container and propagates outside of the map - this._skipEvents[e.type] = false; - return skipped; - }, - - // check if element really left/entered the event target (for mouseenter/mouseleave) - _checkMouse: function (el, e) { - - var related = e.relatedTarget; - - if (!related) { return true; } - - try { - while (related && (related !== el)) { - related = related.parentNode; - } - } catch (err) { - return false; - } - return (related !== el); - }, - - _getEvent: function () { // evil magic for IE - /*jshint noarg:false */ - var e = window.event; - if (!e) { - var caller = arguments.callee.caller; - while (caller) { - e = caller['arguments'][0]; - if (e && window.Event === e.constructor) { - break; - } - caller = caller.caller; - } - } - return e; - }, - - // this is a horrible workaround for a bug in Android where a single touch triggers two click events - _filterClick: function (e, handler) { - var timeStamp = (e.timeStamp || e.originalEvent.timeStamp), - elapsed = L.DomEvent._lastClick && (timeStamp - L.DomEvent._lastClick); - - // are they closer together than 500ms yet more than 100ms? - // Android typically triggers them ~300ms apart while multiple listeners - // on the same event should be triggered far faster; - // or check if click is simulated on the element, and if it is, reject any non-simulated events - - if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) { - L.DomEvent.stop(e); - return; - } - L.DomEvent._lastClick = timeStamp; - - return handler(e); - } -}; - -L.DomEvent.on = L.DomEvent.addListener; -L.DomEvent.off = L.DomEvent.removeListener; - - -/* - * L.Draggable allows you to add dragging capabilities to any element. Supports mobile devices too. - */ - -L.Draggable = L.Class.extend({ - includes: L.Mixin.Events, - - statics: { - START: L.Browser.touch ? ['touchstart', 'mousedown'] : ['mousedown'], - END: { - mousedown: 'mouseup', - touchstart: 'touchend', - pointerdown: 'touchend', - MSPointerDown: 'touchend' - }, - MOVE: { - mousedown: 'mousemove', - touchstart: 'touchmove', - pointerdown: 'touchmove', - MSPointerDown: 'touchmove' - } - }, - - initialize: function (element, dragStartTarget) { - this._element = element; - this._dragStartTarget = dragStartTarget || element; - }, - - enable: function () { - if (this._enabled) { return; } - - for (var i = L.Draggable.START.length - 1; i >= 0; i--) { - L.DomEvent.on(this._dragStartTarget, L.Draggable.START[i], this._onDown, this); - } - - this._enabled = true; - }, - - disable: function () { - if (!this._enabled) { return; } - - for (var i = L.Draggable.START.length - 1; i >= 0; i--) { - L.DomEvent.off(this._dragStartTarget, L.Draggable.START[i], this._onDown, this); - } - - this._enabled = false; - this._moved = false; - }, - - _onDown: function (e) { - this._moved = false; - - if (e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; } - - L.DomEvent.stopPropagation(e); - - if (L.Draggable._disabled) { return; } - - L.DomUtil.disableImageDrag(); - L.DomUtil.disableTextSelection(); - - if (this._moving) { return; } - - var first = e.touches ? e.touches[0] : e; - - this._startPoint = new L.Point(first.clientX, first.clientY); - this._startPos = this._newPos = L.DomUtil.getPosition(this._element); - - L.DomEvent - .on(document, L.Draggable.MOVE[e.type], this._onMove, this) - .on(document, L.Draggable.END[e.type], this._onUp, this); - }, - - _onMove: function (e) { - if (e.touches && e.touches.length > 1) { - this._moved = true; - return; - } - - var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e), - newPoint = new L.Point(first.clientX, first.clientY), - offset = newPoint.subtract(this._startPoint); - - if (!offset.x && !offset.y) { return; } - if (L.Browser.touch && Math.abs(offset.x) + Math.abs(offset.y) < 3) { return; } - - L.DomEvent.preventDefault(e); - - if (!this._moved) { - this.fire('dragstart'); - - this._moved = true; - this._startPos = L.DomUtil.getPosition(this._element).subtract(offset); - - L.DomUtil.addClass(document.body, 'leaflet-dragging'); - this._lastTarget = e.target || e.srcElement; - L.DomUtil.addClass(this._lastTarget, 'leaflet-drag-target'); - } - - this._newPos = this._startPos.add(offset); - this._moving = true; - - L.Util.cancelAnimFrame(this._animRequest); - this._animRequest = L.Util.requestAnimFrame(this._updatePosition, this, true, this._dragStartTarget); - }, - - _updatePosition: function () { - this.fire('predrag'); - L.DomUtil.setPosition(this._element, this._newPos); - this.fire('drag'); - }, - - _onUp: function () { - L.DomUtil.removeClass(document.body, 'leaflet-dragging'); - - if (this._lastTarget) { - L.DomUtil.removeClass(this._lastTarget, 'leaflet-drag-target'); - this._lastTarget = null; - } - - for (var i in L.Draggable.MOVE) { - L.DomEvent - .off(document, L.Draggable.MOVE[i], this._onMove) - .off(document, L.Draggable.END[i], this._onUp); - } - - L.DomUtil.enableImageDrag(); - L.DomUtil.enableTextSelection(); - - if (this._moved && this._moving) { - // ensure drag is not fired after dragend - L.Util.cancelAnimFrame(this._animRequest); - - this.fire('dragend', { - distance: this._newPos.distanceTo(this._startPos) - }); - } - - this._moving = false; - } -}); - - -/* - L.Handler is a base class for handler classes that are used internally to inject - interaction features like dragging to classes like Map and Marker. -*/ - -L.Handler = L.Class.extend({ - initialize: function (map) { - this._map = map; - }, - - enable: function () { - if (this._enabled) { return; } - - this._enabled = true; - this.addHooks(); - }, - - disable: function () { - if (!this._enabled) { return; } - - this._enabled = false; - this.removeHooks(); - }, - - enabled: function () { - return !!this._enabled; - } -}); - - -/* - * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default. - */ - -L.Map.mergeOptions({ - dragging: true, - - inertia: !L.Browser.android23, - inertiaDeceleration: 3400, // px/s^2 - inertiaMaxSpeed: Infinity, // px/s - inertiaThreshold: L.Browser.touch ? 32 : 18, // ms - easeLinearity: 0.25, - - // TODO refactor, move to CRS - worldCopyJump: false -}); - -L.Map.Drag = L.Handler.extend({ - addHooks: function () { - if (!this._draggable) { - var map = this._map; - - this._draggable = new L.Draggable(map._mapPane, map._container); - - this._draggable.on({ - 'dragstart': this._onDragStart, - 'drag': this._onDrag, - 'dragend': this._onDragEnd - }, this); - - if (map.options.worldCopyJump) { - this._draggable.on('predrag', this._onPreDrag, this); - map.on('viewreset', this._onViewReset, this); - - map.whenReady(this._onViewReset, this); - } - } - this._draggable.enable(); - }, - - removeHooks: function () { - this._draggable.disable(); - }, - - moved: function () { - return this._draggable && this._draggable._moved; - }, - - _onDragStart: function () { - var map = this._map; - - if (map._panAnim) { - map._panAnim.stop(); - } - - map - .fire('movestart') - .fire('dragstart'); - - if (map.options.inertia) { - this._positions = []; - this._times = []; - } - }, - - _onDrag: function () { - if (this._map.options.inertia) { - var time = this._lastTime = +new Date(), - pos = this._lastPos = this._draggable._newPos; - - this._positions.push(pos); - this._times.push(time); - - if (time - this._times[0] > 200) { - this._positions.shift(); - this._times.shift(); - } - } - - this._map - .fire('move') - .fire('drag'); - }, - - _onViewReset: function () { - // TODO fix hardcoded Earth values - var pxCenter = this._map.getSize()._divideBy(2), - pxWorldCenter = this._map.latLngToLayerPoint([0, 0]); - - this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x; - this._worldWidth = this._map.project([0, 180]).x; - }, - - _onPreDrag: function () { - // TODO refactor to be able to adjust map pane position after zoom - var worldWidth = this._worldWidth, - halfWidth = Math.round(worldWidth / 2), - dx = this._initialWorldOffset, - x = this._draggable._newPos.x, - newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx, - newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx, - newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2; - - this._draggable._newPos.x = newX; - }, - - _onDragEnd: function (e) { - var map = this._map, - options = map.options, - delay = +new Date() - this._lastTime, - - noInertia = !options.inertia || delay > options.inertiaThreshold || !this._positions[0]; - - map.fire('dragend', e); - - if (noInertia) { - map.fire('moveend'); - - } else { - - var direction = this._lastPos.subtract(this._positions[0]), - duration = (this._lastTime + delay - this._times[0]) / 1000, - ease = options.easeLinearity, - - speedVector = direction.multiplyBy(ease / duration), - speed = speedVector.distanceTo([0, 0]), - - limitedSpeed = Math.min(options.inertiaMaxSpeed, speed), - limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed), - - decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease), - offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round(); - - if (!offset.x || !offset.y) { - map.fire('moveend'); - - } else { - offset = map._limitOffset(offset, map.options.maxBounds); - - L.Util.requestAnimFrame(function () { - map.panBy(offset, { - duration: decelerationDuration, - easeLinearity: ease, - noMoveStart: true - }); - }); - } - } - } -}); - -L.Map.addInitHook('addHandler', 'dragging', L.Map.Drag); - - -/* - * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default. - */ - -L.Map.mergeOptions({ - doubleClickZoom: true -}); - -L.Map.DoubleClickZoom = L.Handler.extend({ - addHooks: function () { - this._map.on('dblclick', this._onDoubleClick, this); - }, - - removeHooks: function () { - this._map.off('dblclick', this._onDoubleClick, this); - }, - - _onDoubleClick: function (e) { - var map = this._map, - zoom = map.getZoom() + (e.originalEvent.shiftKey ? -1 : 1); - - if (map.options.doubleClickZoom === 'center') { - map.setZoom(zoom); - } else { - map.setZoomAround(e.containerPoint, zoom); - } - } -}); - -L.Map.addInitHook('addHandler', 'doubleClickZoom', L.Map.DoubleClickZoom); - - -/* - * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map. - */ - -L.Map.mergeOptions({ - scrollWheelZoom: true -}); - -L.Map.ScrollWheelZoom = L.Handler.extend({ - addHooks: function () { - L.DomEvent.on(this._map._container, 'mousewheel', this._onWheelScroll, this); - L.DomEvent.on(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault); - this._delta = 0; - }, - - removeHooks: function () { - L.DomEvent.off(this._map._container, 'mousewheel', this._onWheelScroll); - L.DomEvent.off(this._map._container, 'MozMousePixelScroll', L.DomEvent.preventDefault); - }, - - _onWheelScroll: function (e) { - var delta = L.DomEvent.getWheelDelta(e); - - this._delta += delta; - this._lastMousePos = this._map.mouseEventToContainerPoint(e); - - if (!this._startTime) { - this._startTime = +new Date(); - } - - var left = Math.max(40 - (+new Date() - this._startTime), 0); - - clearTimeout(this._timer); - this._timer = setTimeout(L.bind(this._performZoom, this), left); - - L.DomEvent.preventDefault(e); - L.DomEvent.stopPropagation(e); - }, - - _performZoom: function () { - var map = this._map, - delta = this._delta, - zoom = map.getZoom(); - - delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta); - delta = Math.max(Math.min(delta, 4), -4); - delta = map._limitZoom(zoom + delta) - zoom; - - this._delta = 0; - this._startTime = null; - - if (!delta) { return; } - - if (map.options.scrollWheelZoom === 'center') { - map.setZoom(zoom + delta); - } else { - map.setZoomAround(this._lastMousePos, zoom + delta); - } - } -}); - -L.Map.addInitHook('addHandler', 'scrollWheelZoom', L.Map.ScrollWheelZoom); - - -/* - * Extends the event handling code with double tap support for mobile browsers. - */ - -L.extend(L.DomEvent, { - - _touchstart: L.Browser.msPointer ? 'MSPointerDown' : L.Browser.pointer ? 'pointerdown' : 'touchstart', - _touchend: L.Browser.msPointer ? 'MSPointerUp' : L.Browser.pointer ? 'pointerup' : 'touchend', - - // inspired by Zepto touch code by Thomas Fuchs - addDoubleTapListener: function (obj, handler, id) { - var last, - doubleTap = false, - delay = 250, - touch, - pre = '_leaflet_', - touchstart = this._touchstart, - touchend = this._touchend, - trackedTouches = []; - - function onTouchStart(e) { - var count; - - if (L.Browser.pointer) { - trackedTouches.push(e.pointerId); - count = trackedTouches.length; - } else { - count = e.touches.length; - } - if (count > 1) { - return; - } - - var now = Date.now(), - delta = now - (last || now); - - touch = e.touches ? e.touches[0] : e; - doubleTap = (delta > 0 && delta <= delay); - last = now; - } - - function onTouchEnd(e) { - if (L.Browser.pointer) { - var idx = trackedTouches.indexOf(e.pointerId); - if (idx === -1) { - return; - } - trackedTouches.splice(idx, 1); - } - - if (doubleTap) { - if (L.Browser.pointer) { - // work around .type being readonly with MSPointer* events - var newTouch = { }, - prop; - - // jshint forin:false - for (var i in touch) { - prop = touch[i]; - if (typeof prop === 'function') { - newTouch[i] = prop.bind(touch); - } else { - newTouch[i] = prop; - } - } - touch = newTouch; - } - touch.type = 'dblclick'; - handler(touch); - last = null; - } - } - obj[pre + touchstart + id] = onTouchStart; - obj[pre + touchend + id] = onTouchEnd; - - // on pointer we need to listen on the document, otherwise a drag starting on the map and moving off screen - // will not come through to us, so we will lose track of how many touches are ongoing - var endElement = L.Browser.pointer ? document.documentElement : obj; - - obj.addEventListener(touchstart, onTouchStart, false); - endElement.addEventListener(touchend, onTouchEnd, false); - - if (L.Browser.pointer) { - endElement.addEventListener(L.DomEvent.POINTER_CANCEL, onTouchEnd, false); - } - - return this; - }, - - removeDoubleTapListener: function (obj, id) { - var pre = '_leaflet_'; - - obj.removeEventListener(this._touchstart, obj[pre + this._touchstart + id], false); - (L.Browser.pointer ? document.documentElement : obj).removeEventListener( - this._touchend, obj[pre + this._touchend + id], false); - - if (L.Browser.pointer) { - document.documentElement.removeEventListener(L.DomEvent.POINTER_CANCEL, obj[pre + this._touchend + id], - false); - } - - return this; - } -}); - - -/* - * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices. - */ - -L.extend(L.DomEvent, { - - //static - POINTER_DOWN: L.Browser.msPointer ? 'MSPointerDown' : 'pointerdown', - POINTER_MOVE: L.Browser.msPointer ? 'MSPointerMove' : 'pointermove', - POINTER_UP: L.Browser.msPointer ? 'MSPointerUp' : 'pointerup', - POINTER_CANCEL: L.Browser.msPointer ? 'MSPointerCancel' : 'pointercancel', - - _pointers: [], - _pointerDocumentListener: false, - - // Provides a touch events wrapper for (ms)pointer events. - // Based on changes by veproza https://github.com/CloudMade/Leaflet/pull/1019 - //ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890 - - addPointerListener: function (obj, type, handler, id) { - - switch (type) { - case 'touchstart': - return this.addPointerListenerStart(obj, type, handler, id); - case 'touchend': - return this.addPointerListenerEnd(obj, type, handler, id); - case 'touchmove': - return this.addPointerListenerMove(obj, type, handler, id); - default: - throw 'Unknown touch event type'; - } - }, - - addPointerListenerStart: function (obj, type, handler, id) { - var pre = '_leaflet_', - pointers = this._pointers; - - var cb = function (e) { - if (e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) { - L.DomEvent.preventDefault(e); - } - - var alreadyInArray = false; - for (var i = 0; i < pointers.length; i++) { - if (pointers[i].pointerId === e.pointerId) { - alreadyInArray = true; - break; - } - } - if (!alreadyInArray) { - pointers.push(e); - } - - e.touches = pointers.slice(); - e.changedTouches = [e]; - - handler(e); - }; - - obj[pre + 'touchstart' + id] = cb; - obj.addEventListener(this.POINTER_DOWN, cb, false); - - // need to also listen for end events to keep the _pointers list accurate - // this needs to be on the body and never go away - if (!this._pointerDocumentListener) { - var internalCb = function (e) { - for (var i = 0; i < pointers.length; i++) { - if (pointers[i].pointerId === e.pointerId) { - pointers.splice(i, 1); - break; - } - } - }; - //We listen on the documentElement as any drags that end by moving the touch off the screen get fired there - document.documentElement.addEventListener(this.POINTER_UP, internalCb, false); - document.documentElement.addEventListener(this.POINTER_CANCEL, internalCb, false); - - this._pointerDocumentListener = true; - } - - return this; - }, - - addPointerListenerMove: function (obj, type, handler, id) { - var pre = '_leaflet_', - touches = this._pointers; - - function cb(e) { - - // don't fire touch moves when mouse isn't down - if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; } - - for (var i = 0; i < touches.length; i++) { - if (touches[i].pointerId === e.pointerId) { - touches[i] = e; - break; - } - } - - e.touches = touches.slice(); - e.changedTouches = [e]; - - handler(e); - } - - obj[pre + 'touchmove' + id] = cb; - obj.addEventListener(this.POINTER_MOVE, cb, false); - - return this; - }, - - addPointerListenerEnd: function (obj, type, handler, id) { - var pre = '_leaflet_', - touches = this._pointers; - - var cb = function (e) { - for (var i = 0; i < touches.length; i++) { - if (touches[i].pointerId === e.pointerId) { - touches.splice(i, 1); - break; - } - } - - e.touches = touches.slice(); - e.changedTouches = [e]; - - handler(e); - }; - - obj[pre + 'touchend' + id] = cb; - obj.addEventListener(this.POINTER_UP, cb, false); - obj.addEventListener(this.POINTER_CANCEL, cb, false); - - return this; - }, - - removePointerListener: function (obj, type, id) { - var pre = '_leaflet_', - cb = obj[pre + type + id]; - - switch (type) { - case 'touchstart': - obj.removeEventListener(this.POINTER_DOWN, cb, false); - break; - case 'touchmove': - obj.removeEventListener(this.POINTER_MOVE, cb, false); - break; - case 'touchend': - obj.removeEventListener(this.POINTER_UP, cb, false); - obj.removeEventListener(this.POINTER_CANCEL, cb, false); - break; - } - - return this; - } -}); - - -/* - * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers. - */ - -L.Map.mergeOptions({ - touchZoom: L.Browser.touch && !L.Browser.android23, - bounceAtZoomLimits: true -}); - -L.Map.TouchZoom = L.Handler.extend({ - addHooks: function () { - L.DomEvent.on(this._map._container, 'touchstart', this._onTouchStart, this); - }, - - removeHooks: function () { - L.DomEvent.off(this._map._container, 'touchstart', this._onTouchStart, this); - }, - - _onTouchStart: function (e) { - var map = this._map; - - if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; } - - var p1 = map.mouseEventToLayerPoint(e.touches[0]), - p2 = map.mouseEventToLayerPoint(e.touches[1]), - viewCenter = map._getCenterLayerPoint(); - - this._startCenter = p1.add(p2)._divideBy(2); - this._startDist = p1.distanceTo(p2); - - this._moved = false; - this._zooming = true; - - this._centerOffset = viewCenter.subtract(this._startCenter); - - if (map._panAnim) { - map._panAnim.stop(); - } - - L.DomEvent - .on(document, 'touchmove', this._onTouchMove, this) - .on(document, 'touchend', this._onTouchEnd, this); - - L.DomEvent.preventDefault(e); - }, - - _onTouchMove: function (e) { - var map = this._map; - - if (!e.touches || e.touches.length !== 2 || !this._zooming) { return; } - - var p1 = map.mouseEventToLayerPoint(e.touches[0]), - p2 = map.mouseEventToLayerPoint(e.touches[1]); - - this._scale = p1.distanceTo(p2) / this._startDist; - this._delta = p1._add(p2)._divideBy(2)._subtract(this._startCenter); - - if (this._scale === 1) { return; } - - if (!map.options.bounceAtZoomLimits) { - if ((map.getZoom() === map.getMinZoom() && this._scale < 1) || - (map.getZoom() === map.getMaxZoom() && this._scale > 1)) { return; } - } - - if (!this._moved) { - L.DomUtil.addClass(map._mapPane, 'leaflet-touching'); - - map - .fire('movestart') - .fire('zoomstart'); - - this._moved = true; - } - - L.Util.cancelAnimFrame(this._animRequest); - this._animRequest = L.Util.requestAnimFrame( - this._updateOnMove, this, true, this._map._container); - - L.DomEvent.preventDefault(e); - }, - - _updateOnMove: function () { - var map = this._map, - origin = this._getScaleOrigin(), - center = map.layerPointToLatLng(origin), - zoom = map.getScaleZoom(this._scale); - - map._animateZoom(center, zoom, this._startCenter, this._scale, this._delta, false, true); - }, - - _onTouchEnd: function () { - if (!this._moved || !this._zooming) { - this._zooming = false; - return; - } - - var map = this._map; - - this._zooming = false; - L.DomUtil.removeClass(map._mapPane, 'leaflet-touching'); - L.Util.cancelAnimFrame(this._animRequest); - - L.DomEvent - .off(document, 'touchmove', this._onTouchMove) - .off(document, 'touchend', this._onTouchEnd); - - var origin = this._getScaleOrigin(), - center = map.layerPointToLatLng(origin), - - oldZoom = map.getZoom(), - floatZoomDelta = map.getScaleZoom(this._scale) - oldZoom, - roundZoomDelta = (floatZoomDelta > 0 ? - Math.ceil(floatZoomDelta) : Math.floor(floatZoomDelta)), - - zoom = map._limitZoom(oldZoom + roundZoomDelta), - scale = map.getZoomScale(zoom) / this._scale; - - map._animateZoom(center, zoom, origin, scale); - }, - - _getScaleOrigin: function () { - var centerOffset = this._centerOffset.subtract(this._delta).divideBy(this._scale); - return this._startCenter.add(centerOffset); - } -}); - -L.Map.addInitHook('addHandler', 'touchZoom', L.Map.TouchZoom); - - -/* - * L.Map.Tap is used to enable mobile hacks like quick taps and long hold. - */ - -L.Map.mergeOptions({ - tap: true, - tapTolerance: 15 -}); - -L.Map.Tap = L.Handler.extend({ - addHooks: function () { - L.DomEvent.on(this._map._container, 'touchstart', this._onDown, this); - }, - - removeHooks: function () { - L.DomEvent.off(this._map._container, 'touchstart', this._onDown, this); - }, - - _onDown: function (e) { - if (!e.touches) { return; } - - L.DomEvent.preventDefault(e); - - this._fireClick = true; - - // don't simulate click or track longpress if more than 1 touch - if (e.touches.length > 1) { - this._fireClick = false; - clearTimeout(this._holdTimeout); - return; - } - - var first = e.touches[0], - el = first.target; - - this._startPos = this._newPos = new L.Point(first.clientX, first.clientY); - - // if touching a link, highlight it - if (el.tagName && el.tagName.toLowerCase() === 'a') { - L.DomUtil.addClass(el, 'leaflet-active'); - } - - // simulate long hold but setting a timeout - this._holdTimeout = setTimeout(L.bind(function () { - if (this._isTapValid()) { - this._fireClick = false; - this._onUp(); - this._simulateEvent('contextmenu', first); - } - }, this), 1000); - - L.DomEvent - .on(document, 'touchmove', this._onMove, this) - .on(document, 'touchend', this._onUp, this); - }, - - _onUp: function (e) { - clearTimeout(this._holdTimeout); - - L.DomEvent - .off(document, 'touchmove', this._onMove, this) - .off(document, 'touchend', this._onUp, this); - - if (this._fireClick && e && e.changedTouches) { - - var first = e.changedTouches[0], - el = first.target; - - if (el && el.tagName && el.tagName.toLowerCase() === 'a') { - L.DomUtil.removeClass(el, 'leaflet-active'); - } - - // simulate click if the touch didn't move too much - if (this._isTapValid()) { - this._simulateEvent('click', first); - } - } - }, - - _isTapValid: function () { - return this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance; - }, - - _onMove: function (e) { - var first = e.touches[0]; - this._newPos = new L.Point(first.clientX, first.clientY); - }, - - _simulateEvent: function (type, e) { - var simulatedEvent = document.createEvent('MouseEvents'); - - simulatedEvent._simulated = true; - e.target._simulatedClick = true; - - simulatedEvent.initMouseEvent( - type, true, true, window, 1, - e.screenX, e.screenY, - e.clientX, e.clientY, - false, false, false, false, 0, null); - - e.target.dispatchEvent(simulatedEvent); - } -}); - -if (L.Browser.touch && !L.Browser.pointer) { - L.Map.addInitHook('addHandler', 'tap', L.Map.Tap); -} - - -/* - * L.Handler.ShiftDragZoom is used to add shift-drag zoom interaction to the map - * (zoom to a selected bounding box), enabled by default. - */ - -L.Map.mergeOptions({ - boxZoom: true -}); - -L.Map.BoxZoom = L.Handler.extend({ - initialize: function (map) { - this._map = map; - this._container = map._container; - this._pane = map._panes.overlayPane; - this._moved = false; - }, - - addHooks: function () { - L.DomEvent.on(this._container, 'mousedown', this._onMouseDown, this); - }, - - removeHooks: function () { - L.DomEvent.off(this._container, 'mousedown', this._onMouseDown); - this._moved = false; - }, - - moved: function () { - return this._moved; - }, - - _onMouseDown: function (e) { - this._moved = false; - - if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; } - - L.DomUtil.disableTextSelection(); - L.DomUtil.disableImageDrag(); - - this._startLayerPoint = this._map.mouseEventToLayerPoint(e); - - L.DomEvent - .on(document, 'mousemove', this._onMouseMove, this) - .on(document, 'mouseup', this._onMouseUp, this) - .on(document, 'keydown', this._onKeyDown, this); - }, - - _onMouseMove: function (e) { - if (!this._moved) { - this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._pane); - L.DomUtil.setPosition(this._box, this._startLayerPoint); - - //TODO refactor: move cursor to styles - this._container.style.cursor = 'crosshair'; - this._map.fire('boxzoomstart'); - } - - var startPoint = this._startLayerPoint, - box = this._box, - - layerPoint = this._map.mouseEventToLayerPoint(e), - offset = layerPoint.subtract(startPoint), - - newPos = new L.Point( - Math.min(layerPoint.x, startPoint.x), - Math.min(layerPoint.y, startPoint.y)); - - L.DomUtil.setPosition(box, newPos); - - this._moved = true; - - // TODO refactor: remove hardcoded 4 pixels - box.style.width = (Math.max(0, Math.abs(offset.x) - 4)) + 'px'; - box.style.height = (Math.max(0, Math.abs(offset.y) - 4)) + 'px'; - }, - - _finish: function () { - if (this._moved) { - this._pane.removeChild(this._box); - this._container.style.cursor = ''; - } - - L.DomUtil.enableTextSelection(); - L.DomUtil.enableImageDrag(); - - L.DomEvent - .off(document, 'mousemove', this._onMouseMove) - .off(document, 'mouseup', this._onMouseUp) - .off(document, 'keydown', this._onKeyDown); - }, - - _onMouseUp: function (e) { - - this._finish(); - - var map = this._map, - layerPoint = map.mouseEventToLayerPoint(e); - - if (this._startLayerPoint.equals(layerPoint)) { return; } - - var bounds = new L.LatLngBounds( - map.layerPointToLatLng(this._startLayerPoint), - map.layerPointToLatLng(layerPoint)); - - map.fitBounds(bounds); - - map.fire('boxzoomend', { - boxZoomBounds: bounds - }); - }, - - _onKeyDown: function (e) { - if (e.keyCode === 27) { - this._finish(); - } - } -}); - -L.Map.addInitHook('addHandler', 'boxZoom', L.Map.BoxZoom); - - -/* - * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default. - */ - -L.Map.mergeOptions({ - keyboard: true, - keyboardPanOffset: 80, - keyboardZoomOffset: 1 -}); - -L.Map.Keyboard = L.Handler.extend({ - - keyCodes: { - left: [37], - right: [39], - down: [40], - up: [38], - zoomIn: [187, 107, 61, 171], - zoomOut: [189, 109, 173] - }, - - initialize: function (map) { - this._map = map; - - this._setPanOffset(map.options.keyboardPanOffset); - this._setZoomOffset(map.options.keyboardZoomOffset); - }, - - addHooks: function () { - var container = this._map._container; - - // make the container focusable by tabbing - if (container.tabIndex === -1) { - container.tabIndex = '0'; - } - - L.DomEvent - .on(container, 'focus', this._onFocus, this) - .on(container, 'blur', this._onBlur, this) - .on(container, 'mousedown', this._onMouseDown, this); - - this._map - .on('focus', this._addHooks, this) - .on('blur', this._removeHooks, this); - }, - - removeHooks: function () { - this._removeHooks(); - - var container = this._map._container; - - L.DomEvent - .off(container, 'focus', this._onFocus, this) - .off(container, 'blur', this._onBlur, this) - .off(container, 'mousedown', this._onMouseDown, this); - - this._map - .off('focus', this._addHooks, this) - .off('blur', this._removeHooks, this); - }, - - _onMouseDown: function () { - if (this._focused) { return; } - - var body = document.body, - docEl = document.documentElement, - top = body.scrollTop || docEl.scrollTop, - left = body.scrollLeft || docEl.scrollLeft; - - this._map._container.focus(); - - window.scrollTo(left, top); - }, - - _onFocus: function () { - this._focused = true; - this._map.fire('focus'); - }, - - _onBlur: function () { - this._focused = false; - this._map.fire('blur'); - }, - - _setPanOffset: function (pan) { - var keys = this._panKeys = {}, - codes = this.keyCodes, - i, len; - - for (i = 0, len = codes.left.length; i < len; i++) { - keys[codes.left[i]] = [-1 * pan, 0]; - } - for (i = 0, len = codes.right.length; i < len; i++) { - keys[codes.right[i]] = [pan, 0]; - } - for (i = 0, len = codes.down.length; i < len; i++) { - keys[codes.down[i]] = [0, pan]; - } - for (i = 0, len = codes.up.length; i < len; i++) { - keys[codes.up[i]] = [0, -1 * pan]; - } - }, - - _setZoomOffset: function (zoom) { - var keys = this._zoomKeys = {}, - codes = this.keyCodes, - i, len; - - for (i = 0, len = codes.zoomIn.length; i < len; i++) { - keys[codes.zoomIn[i]] = zoom; - } - for (i = 0, len = codes.zoomOut.length; i < len; i++) { - keys[codes.zoomOut[i]] = -zoom; - } - }, - - _addHooks: function () { - L.DomEvent.on(document, 'keydown', this._onKeyDown, this); - }, - - _removeHooks: function () { - L.DomEvent.off(document, 'keydown', this._onKeyDown, this); - }, - - _onKeyDown: function (e) { - var key = e.keyCode, - map = this._map; - - if (key in this._panKeys) { - - if (map._panAnim && map._panAnim._inProgress) { return; } - - map.panBy(this._panKeys[key]); - - if (map.options.maxBounds) { - map.panInsideBounds(map.options.maxBounds); - } - - } else if (key in this._zoomKeys) { - map.setZoom(map.getZoom() + this._zoomKeys[key]); - - } else { - return; - } - - L.DomEvent.stop(e); - } -}); - -L.Map.addInitHook('addHandler', 'keyboard', L.Map.Keyboard); - - -/* - * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable. - */ - -L.Handler.MarkerDrag = L.Handler.extend({ - initialize: function (marker) { - this._marker = marker; - }, - - addHooks: function () { - var icon = this._marker._icon; - if (!this._draggable) { - this._draggable = new L.Draggable(icon, icon); - } - - this._draggable - .on('dragstart', this._onDragStart, this) - .on('drag', this._onDrag, this) - .on('dragend', this._onDragEnd, this); - this._draggable.enable(); - L.DomUtil.addClass(this._marker._icon, 'leaflet-marker-draggable'); - }, - - removeHooks: function () { - this._draggable - .off('dragstart', this._onDragStart, this) - .off('drag', this._onDrag, this) - .off('dragend', this._onDragEnd, this); - - this._draggable.disable(); - L.DomUtil.removeClass(this._marker._icon, 'leaflet-marker-draggable'); - }, - - moved: function () { - return this._draggable && this._draggable._moved; - }, - - _onDragStart: function () { - this._marker - .closePopup() - .fire('movestart') - .fire('dragstart'); - }, - - _onDrag: function () { - var marker = this._marker, - shadow = marker._shadow, - iconPos = L.DomUtil.getPosition(marker._icon), - latlng = marker._map.layerPointToLatLng(iconPos); - - // update shadow position - if (shadow) { - L.DomUtil.setPosition(shadow, iconPos); - } - - marker._latlng = latlng; - - marker - .fire('move', {latlng: latlng}) - .fire('drag'); - }, - - _onDragEnd: function (e) { - this._marker - .fire('moveend') - .fire('dragend', e); - } -}); - - -/* - * L.Control is a base class for implementing map controls. Handles positioning. - * All other controls extend from this class. - */ - -L.Control = L.Class.extend({ - options: { - position: 'topright' - }, - - initialize: function (options) { - L.setOptions(this, options); - }, - - getPosition: function () { - return this.options.position; - }, - - setPosition: function (position) { - var map = this._map; - - if (map) { - map.removeControl(this); - } - - this.options.position = position; - - if (map) { - map.addControl(this); - } - - return this; - }, - - getContainer: function () { - return this._container; - }, - - addTo: function (map) { - this._map = map; - - var container = this._container = this.onAdd(map), - pos = this.getPosition(), - corner = map._controlCorners[pos]; - - L.DomUtil.addClass(container, 'leaflet-control'); - - if (pos.indexOf('bottom') !== -1) { - corner.insertBefore(container, corner.firstChild); - } else { - corner.appendChild(container); - } - - return this; - }, - - removeFrom: function (map) { - var pos = this.getPosition(), - corner = map._controlCorners[pos]; - - corner.removeChild(this._container); - this._map = null; - - if (this.onRemove) { - this.onRemove(map); - } - - return this; - }, - - _refocusOnMap: function () { - if (this._map) { - this._map.getContainer().focus(); - } - } -}); - -L.control = function (options) { - return new L.Control(options); -}; - - -// adds control-related methods to L.Map - -L.Map.include({ - addControl: function (control) { - control.addTo(this); - return this; - }, - - removeControl: function (control) { - control.removeFrom(this); - return this; - }, - - _initControlPos: function () { - var corners = this._controlCorners = {}, - l = 'leaflet-', - container = this._controlContainer = - L.DomUtil.create('div', l + 'control-container', this._container); - - function createCorner(vSide, hSide) { - var className = l + vSide + ' ' + l + hSide; - - corners[vSide + hSide] = L.DomUtil.create('div', className, container); - } - - createCorner('top', 'left'); - createCorner('top', 'right'); - createCorner('bottom', 'left'); - createCorner('bottom', 'right'); - }, - - _clearControlPos: function () { - this._container.removeChild(this._controlContainer); - } -}); - - -/* - * L.Control.Zoom is used for the default zoom buttons on the map. - */ - -L.Control.Zoom = L.Control.extend({ - options: { - position: 'topleft', - zoomInText: '+', - zoomInTitle: 'Zoom in', - zoomOutText: '-', - zoomOutTitle: 'Zoom out' - }, - - onAdd: function (map) { - var zoomName = 'leaflet-control-zoom', - container = L.DomUtil.create('div', zoomName + ' leaflet-bar'); - - this._map = map; - - this._zoomInButton = this._createButton( - this.options.zoomInText, this.options.zoomInTitle, - zoomName + '-in', container, this._zoomIn, this); - this._zoomOutButton = this._createButton( - this.options.zoomOutText, this.options.zoomOutTitle, - zoomName + '-out', container, this._zoomOut, this); - - this._updateDisabled(); - map.on('zoomend zoomlevelschange', this._updateDisabled, this); - - return container; - }, - - onRemove: function (map) { - map.off('zoomend zoomlevelschange', this._updateDisabled, this); - }, - - _zoomIn: function (e) { - this._map.zoomIn(e.shiftKey ? 3 : 1); - }, - - _zoomOut: function (e) { - this._map.zoomOut(e.shiftKey ? 3 : 1); - }, - - _createButton: function (html, title, className, container, fn, context) { - var link = L.DomUtil.create('a', className, container); - link.innerHTML = html; - link.href = '#'; - link.title = title; - - var stop = L.DomEvent.stopPropagation; - - L.DomEvent - .on(link, 'click', stop) - .on(link, 'mousedown', stop) - .on(link, 'dblclick', stop) - .on(link, 'click', L.DomEvent.preventDefault) - .on(link, 'click', fn, context) - .on(link, 'click', this._refocusOnMap, context); - - return link; - }, - - _updateDisabled: function () { - var map = this._map, - className = 'leaflet-disabled'; - - L.DomUtil.removeClass(this._zoomInButton, className); - L.DomUtil.removeClass(this._zoomOutButton, className); - - if (map._zoom === map.getMinZoom()) { - L.DomUtil.addClass(this._zoomOutButton, className); - } - if (map._zoom === map.getMaxZoom()) { - L.DomUtil.addClass(this._zoomInButton, className); - } - } -}); - -L.Map.mergeOptions({ - zoomControl: true -}); - -L.Map.addInitHook(function () { - if (this.options.zoomControl) { - this.zoomControl = new L.Control.Zoom(); - this.addControl(this.zoomControl); - } -}); - -L.control.zoom = function (options) { - return new L.Control.Zoom(options); -}; - - - -/* - * L.Control.Attribution is used for displaying attribution on the map (added by default). - */ - -L.Control.Attribution = L.Control.extend({ - options: { - position: 'bottomright', - prefix: '<a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>' - }, - - initialize: function (options) { - L.setOptions(this, options); - - this._attributions = {}; - }, - - onAdd: function (map) { - this._container = L.DomUtil.create('div', 'leaflet-control-attribution'); - L.DomEvent.disableClickPropagation(this._container); - - for (var i in map._layers) { - if (map._layers[i].getAttribution) { - this.addAttribution(map._layers[i].getAttribution()); - } - } - - map - .on('layeradd', this._onLayerAdd, this) - .on('layerremove', this._onLayerRemove, this); - - this._update(); - - return this._container; - }, - - onRemove: function (map) { - map - .off('layeradd', this._onLayerAdd) - .off('layerremove', this._onLayerRemove); - - }, - - setPrefix: function (prefix) { - this.options.prefix = prefix; - this._update(); - return this; - }, - - addAttribution: function (text) { - if (!text) { return; } - - if (!this._attributions[text]) { - this._attributions[text] = 0; - } - this._attributions[text]++; - - this._update(); - - return this; - }, - - removeAttribution: function (text) { - if (!text) { return; } - - if (this._attributions[text]) { - this._attributions[text]--; - this._update(); - } - - return this; - }, - - _update: function () { - if (!this._map) { return; } - - var attribs = []; - - for (var i in this._attributions) { - if (this._attributions[i]) { - attribs.push(i); - } - } - - var prefixAndAttribs = []; - - if (this.options.prefix) { - prefixAndAttribs.push(this.options.prefix); - } - if (attribs.length) { - prefixAndAttribs.push(attribs.join(', ')); - } - - this._container.innerHTML = prefixAndAttribs.join(' | '); - }, - - _onLayerAdd: function (e) { - if (e.layer.getAttribution) { - this.addAttribution(e.layer.getAttribution()); - } - }, - - _onLayerRemove: function (e) { - if (e.layer.getAttribution) { - this.removeAttribution(e.layer.getAttribution()); - } - } -}); - -L.Map.mergeOptions({ - attributionControl: true -}); - -L.Map.addInitHook(function () { - if (this.options.attributionControl) { - this.attributionControl = (new L.Control.Attribution()).addTo(this); - } -}); - -L.control.attribution = function (options) { - return new L.Control.Attribution(options); -}; - - -/* - * L.Control.Scale is used for displaying metric/imperial scale on the map. - */ - -L.Control.Scale = L.Control.extend({ - options: { - position: 'bottomleft', - maxWidth: 100, - metric: true, - imperial: true, - updateWhenIdle: false - }, - - onAdd: function (map) { - this._map = map; - - var className = 'leaflet-control-scale', - container = L.DomUtil.create('div', className), - options = this.options; - - this._addScales(options, className, container); - - map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this); - map.whenReady(this._update, this); - - return container; - }, - - onRemove: function (map) { - map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this); - }, - - _addScales: function (options, className, container) { - if (options.metric) { - this._mScale = L.DomUtil.create('div', className + '-line', container); - } - if (options.imperial) { - this._iScale = L.DomUtil.create('div', className + '-line', container); - } - }, - - _update: function () { - var bounds = this._map.getBounds(), - centerLat = bounds.getCenter().lat, - halfWorldMeters = 6378137 * Math.PI * Math.cos(centerLat * Math.PI / 180), - dist = halfWorldMeters * (bounds.getNorthEast().lng - bounds.getSouthWest().lng) / 180, - - size = this._map.getSize(), - options = this.options, - maxMeters = 0; - - if (size.x > 0) { - maxMeters = dist * (options.maxWidth / size.x); - } - - this._updateScales(options, maxMeters); - }, - - _updateScales: function (options, maxMeters) { - if (options.metric && maxMeters) { - this._updateMetric(maxMeters); - } - - if (options.imperial && maxMeters) { - this._updateImperial(maxMeters); - } - }, - - _updateMetric: function (maxMeters) { - var meters = this._getRoundNum(maxMeters); - - this._mScale.style.width = this._getScaleWidth(meters / maxMeters) + 'px'; - this._mScale.innerHTML = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km'; - }, - - _updateImperial: function (maxMeters) { - var maxFeet = maxMeters * 3.2808399, - scale = this._iScale, - maxMiles, miles, feet; - - if (maxFeet > 5280) { - maxMiles = maxFeet / 5280; - miles = this._getRoundNum(maxMiles); - - scale.style.width = this._getScaleWidth(miles / maxMiles) + 'px'; - scale.innerHTML = miles + ' mi'; - - } else { - feet = this._getRoundNum(maxFeet); - - scale.style.width = this._getScaleWidth(feet / maxFeet) + 'px'; - scale.innerHTML = feet + ' ft'; - } - }, - - _getScaleWidth: function (ratio) { - return Math.round(this.options.maxWidth * ratio) - 10; - }, - - _getRoundNum: function (num) { - var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1), - d = num / pow10; - - d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1; - - return pow10 * d; - } -}); - -L.control.scale = function (options) { - return new L.Control.Scale(options); -}; - - -/* - * L.Control.Layers is a control to allow users to switch between different layers on the map. - */ - -L.Control.Layers = L.Control.extend({ - options: { - collapsed: true, - position: 'topright', - autoZIndex: true - }, - - initialize: function (baseLayers, overlays, options) { - L.setOptions(this, options); - - this._layers = {}; - this._lastZIndex = 0; - this._handlingClick = false; - - for (var i in baseLayers) { - this._addLayer(baseLayers[i], i); - } - - for (i in overlays) { - this._addLayer(overlays[i], i, true); - } - }, - - onAdd: function (map) { - this._initLayout(); - this._update(); - - map - .on('layeradd', this._onLayerChange, this) - .on('layerremove', this._onLayerChange, this); - - return this._container; - }, - - onRemove: function (map) { - map - .off('layeradd', this._onLayerChange, this) - .off('layerremove', this._onLayerChange, this); - }, - - addBaseLayer: function (layer, name) { - this._addLayer(layer, name); - this._update(); - return this; - }, - - addOverlay: function (layer, name) { - this._addLayer(layer, name, true); - this._update(); - return this; - }, - - removeLayer: function (layer) { - var id = L.stamp(layer); - delete this._layers[id]; - this._update(); - return this; - }, - - _initLayout: function () { - var className = 'leaflet-control-layers', - container = this._container = L.DomUtil.create('div', className); - - //Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released - container.setAttribute('aria-haspopup', true); - - if (!L.Browser.touch) { - L.DomEvent - .disableClickPropagation(container) - .disableScrollPropagation(container); - } else { - L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation); - } - - var form = this._form = L.DomUtil.create('form', className + '-list'); - - if (this.options.collapsed) { - if (!L.Browser.android) { - L.DomEvent - .on(container, 'mouseover', this._expand, this) - .on(container, 'mouseout', this._collapse, this); - } - var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container); - link.href = '#'; - link.title = 'Layers'; - - if (L.Browser.touch) { - L.DomEvent - .on(link, 'click', L.DomEvent.stop) - .on(link, 'click', this._expand, this); - } - else { - L.DomEvent.on(link, 'focus', this._expand, this); - } - //Work around for Firefox android issue https://github.com/Leaflet/Leaflet/issues/2033 - L.DomEvent.on(form, 'click', function () { - setTimeout(L.bind(this._onInputClick, this), 0); - }, this); - - this._map.on('click', this._collapse, this); - // TODO keyboard accessibility - } else { - this._expand(); - } - - this._baseLayersList = L.DomUtil.create('div', className + '-base', form); - this._separator = L.DomUtil.create('div', className + '-separator', form); - this._overlaysList = L.DomUtil.create('div', className + '-overlays', form); - - container.appendChild(form); - }, - - _addLayer: function (layer, name, overlay) { - var id = L.stamp(layer); - - this._layers[id] = { - layer: layer, - name: name, - overlay: overlay - }; - - if (this.options.autoZIndex && layer.setZIndex) { - this._lastZIndex++; - layer.setZIndex(this._lastZIndex); - } - }, - - _update: function () { - if (!this._container) { - return; - } - - this._baseLayersList.innerHTML = ''; - this._overlaysList.innerHTML = ''; - - var baseLayersPresent = false, - overlaysPresent = false, - i, obj; - - for (i in this._layers) { - obj = this._layers[i]; - this._addItem(obj); - overlaysPresent = overlaysPresent || obj.overlay; - baseLayersPresent = baseLayersPresent || !obj.overlay; - } - - this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none'; - }, - - _onLayerChange: function (e) { - var obj = this._layers[L.stamp(e.layer)]; - - if (!obj) { return; } - - if (!this._handlingClick) { - this._update(); - } - - var type = obj.overlay ? - (e.type === 'layeradd' ? 'overlayadd' : 'overlayremove') : - (e.type === 'layeradd' ? 'baselayerchange' : null); - - if (type) { - this._map.fire(type, obj); - } - }, - - // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe) - _createRadioElement: function (name, checked) { - - var radioHtml = '<input type="radio" class="leaflet-control-layers-selector" name="' + name + '"'; - if (checked) { - radioHtml += ' checked="checked"'; - } - radioHtml += '/>'; - - var radioFragment = document.createElement('div'); - radioFragment.innerHTML = radioHtml; - - return radioFragment.firstChild; - }, - - _addItem: function (obj) { - var label = document.createElement('label'), - input, - checked = this._map.hasLayer(obj.layer); - - if (obj.overlay) { - input = document.createElement('input'); - input.type = 'checkbox'; - input.className = 'leaflet-control-layers-selector'; - input.defaultChecked = checked; - } else { - input = this._createRadioElement('leaflet-base-layers', checked); - } - - input.layerId = L.stamp(obj.layer); - - L.DomEvent.on(input, 'click', this._onInputClick, this); - - var name = document.createElement('span'); - name.innerHTML = ' ' + obj.name; - - label.appendChild(input); - label.appendChild(name); - - var container = obj.overlay ? this._overlaysList : this._baseLayersList; - container.appendChild(label); - - return label; - }, - - _onInputClick: function () { - var i, input, obj, - inputs = this._form.getElementsByTagName('input'), - inputsLen = inputs.length; - - this._handlingClick = true; - - for (i = 0; i < inputsLen; i++) { - input = inputs[i]; - obj = this._layers[input.layerId]; - - if (input.checked && !this._map.hasLayer(obj.layer)) { - this._map.addLayer(obj.layer); - - } else if (!input.checked && this._map.hasLayer(obj.layer)) { - this._map.removeLayer(obj.layer); - } - } - - this._handlingClick = false; - - this._refocusOnMap(); - }, - - _expand: function () { - L.DomUtil.addClass(this._container, 'leaflet-control-layers-expanded'); - }, - - _collapse: function () { - this._container.className = this._container.className.replace(' leaflet-control-layers-expanded', ''); - } -}); - -L.control.layers = function (baseLayers, overlays, options) { - return new L.Control.Layers(baseLayers, overlays, options); -}; - - -/* - * L.PosAnimation is used by Leaflet internally for pan animations. - */ - -L.PosAnimation = L.Class.extend({ - includes: L.Mixin.Events, - - run: function (el, newPos, duration, easeLinearity) { // (HTMLElement, Point[, Number, Number]) - this.stop(); - - this._el = el; - this._inProgress = true; - this._newPos = newPos; - - this.fire('start'); - - el.style[L.DomUtil.TRANSITION] = 'all ' + (duration || 0.25) + - 's cubic-bezier(0,0,' + (easeLinearity || 0.5) + ',1)'; - - L.DomEvent.on(el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this); - L.DomUtil.setPosition(el, newPos); - - // toggle reflow, Chrome flickers for some reason if you don't do this - L.Util.falseFn(el.offsetWidth); - - // there's no native way to track value updates of transitioned properties, so we imitate this - this._stepTimer = setInterval(L.bind(this._onStep, this), 50); - }, - - stop: function () { - if (!this._inProgress) { return; } - - // if we just removed the transition property, the element would jump to its final position, - // so we need to make it stay at the current position - - L.DomUtil.setPosition(this._el, this._getPos()); - this._onTransitionEnd(); - L.Util.falseFn(this._el.offsetWidth); // force reflow in case we are about to start a new animation - }, - - _onStep: function () { - var stepPos = this._getPos(); - if (!stepPos) { - this._onTransitionEnd(); - return; - } - // jshint camelcase: false - // make L.DomUtil.getPosition return intermediate position value during animation - this._el._leaflet_pos = stepPos; - - this.fire('step'); - }, - - // you can't easily get intermediate values of properties animated with CSS3 Transitions, - // we need to parse computed style (in case of transform it returns matrix string) - - _transformRe: /([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/, - - _getPos: function () { - var left, top, matches, - el = this._el, - style = window.getComputedStyle(el); - - if (L.Browser.any3d) { - matches = style[L.DomUtil.TRANSFORM].match(this._transformRe); - if (!matches) { return; } - left = parseFloat(matches[1]); - top = parseFloat(matches[2]); - } else { - left = parseFloat(style.left); - top = parseFloat(style.top); - } - - return new L.Point(left, top, true); - }, - - _onTransitionEnd: function () { - L.DomEvent.off(this._el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this); - - if (!this._inProgress) { return; } - this._inProgress = false; - - this._el.style[L.DomUtil.TRANSITION] = ''; - - // jshint camelcase: false - // make sure L.DomUtil.getPosition returns the final position value after animation - this._el._leaflet_pos = this._newPos; - - clearInterval(this._stepTimer); - - this.fire('step').fire('end'); - } - -}); - - -/* - * Extends L.Map to handle panning animations. - */ - -L.Map.include({ - - setView: function (center, zoom, options) { - - zoom = zoom === undefined ? this._zoom : this._limitZoom(zoom); - center = this._limitCenter(L.latLng(center), zoom, this.options.maxBounds); - options = options || {}; - - if (this._panAnim) { - this._panAnim.stop(); - } - - if (this._loaded && !options.reset && options !== true) { - - if (options.animate !== undefined) { - options.zoom = L.extend({animate: options.animate}, options.zoom); - options.pan = L.extend({animate: options.animate}, options.pan); - } - - // try animating pan or zoom - var animated = (this._zoom !== zoom) ? - this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) : - this._tryAnimatedPan(center, options.pan); - - if (animated) { - // prevent resize handler call, the view will refresh after animation anyway - clearTimeout(this._sizeTimer); - return this; - } - } - - // animation didn't start, just reset the map view - this._resetView(center, zoom); - - return this; - }, - - panBy: function (offset, options) { - offset = L.point(offset).round(); - options = options || {}; - - if (!offset.x && !offset.y) { - return this; - } - - if (!this._panAnim) { - this._panAnim = new L.PosAnimation(); - - this._panAnim.on({ - 'step': this._onPanTransitionStep, - 'end': this._onPanTransitionEnd - }, this); - } - - // don't fire movestart if animating inertia - if (!options.noMoveStart) { - this.fire('movestart'); - } - - // animate pan unless animate: false specified - if (options.animate !== false) { - L.DomUtil.addClass(this._mapPane, 'leaflet-pan-anim'); - - var newPos = this._getMapPanePos().subtract(offset); - this._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity); - } else { - this._rawPanBy(offset); - this.fire('move').fire('moveend'); - } - - return this; - }, - - _onPanTransitionStep: function () { - this.fire('move'); - }, - - _onPanTransitionEnd: function () { - L.DomUtil.removeClass(this._mapPane, 'leaflet-pan-anim'); - this.fire('moveend'); - }, - - _tryAnimatedPan: function (center, options) { - // difference between the new and current centers in pixels - var offset = this._getCenterOffset(center)._floor(); - - // don't animate too far unless animate: true specified in options - if ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; } - - this.panBy(offset, options); - - return true; - } -}); - - -/* - * L.PosAnimation fallback implementation that powers Leaflet pan animations - * in browsers that don't support CSS3 Transitions. - */ - -L.PosAnimation = L.DomUtil.TRANSITION ? L.PosAnimation : L.PosAnimation.extend({ - - run: function (el, newPos, duration, easeLinearity) { // (HTMLElement, Point[, Number, Number]) - this.stop(); - - this._el = el; - this._inProgress = true; - this._duration = duration || 0.25; - this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2); - - this._startPos = L.DomUtil.getPosition(el); - this._offset = newPos.subtract(this._startPos); - this._startTime = +new Date(); - - this.fire('start'); - - this._animate(); - }, - - stop: function () { - if (!this._inProgress) { return; } - - this._step(); - this._complete(); - }, - - _animate: function () { - // animation loop - this._animId = L.Util.requestAnimFrame(this._animate, this); - this._step(); - }, - - _step: function () { - var elapsed = (+new Date()) - this._startTime, - duration = this._duration * 1000; - - if (elapsed < duration) { - this._runFrame(this._easeOut(elapsed / duration)); - } else { - this._runFrame(1); - this._complete(); - } - }, - - _runFrame: function (progress) { - var pos = this._startPos.add(this._offset.multiplyBy(progress)); - L.DomUtil.setPosition(this._el, pos); - - this.fire('step'); - }, - - _complete: function () { - L.Util.cancelAnimFrame(this._animId); - - this._inProgress = false; - this.fire('end'); - }, - - _easeOut: function (t) { - return 1 - Math.pow(1 - t, this._easeOutPower); - } -}); - - -/* - * Extends L.Map to handle zoom animations. - */ - -L.Map.mergeOptions({ - zoomAnimation: true, - zoomAnimationThreshold: 4 -}); - -if (L.DomUtil.TRANSITION) { - - L.Map.addInitHook(function () { - // don't animate on browsers without hardware-accelerated transitions or old Android/Opera - this._zoomAnimated = this.options.zoomAnimation && L.DomUtil.TRANSITION && - L.Browser.any3d && !L.Browser.android23 && !L.Browser.mobileOpera; - - // zoom transitions run with the same duration for all layers, so if one of transitionend events - // happens after starting zoom animation (propagating to the map pane), we know that it ended globally - if (this._zoomAnimated) { - L.DomEvent.on(this._mapPane, L.DomUtil.TRANSITION_END, this._catchTransitionEnd, this); - } - }); -} - -L.Map.include(!L.DomUtil.TRANSITION ? {} : { - - _catchTransitionEnd: function (e) { - if (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) { - this._onZoomTransitionEnd(); - } - }, - - _nothingToAnimate: function () { - return !this._container.getElementsByClassName('leaflet-zoom-animated').length; - }, - - _tryAnimatedZoom: function (center, zoom, options) { - - if (this._animatingZoom) { return true; } - - options = options || {}; - - // don't animate if disabled, not supported or zoom difference is too large - if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() || - Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; } - - // offset is the pixel coords of the zoom origin relative to the current center - var scale = this.getZoomScale(zoom), - offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale), - origin = this._getCenterLayerPoint()._add(offset); - - // don't animate if the zoom origin isn't within one screen from the current center, unless forced - if (options.animate !== true && !this.getSize().contains(offset)) { return false; } - - this - .fire('movestart') - .fire('zoomstart'); - - this._animateZoom(center, zoom, origin, scale, null, true); - - return true; - }, - - _animateZoom: function (center, zoom, origin, scale, delta, backwards, forTouchZoom) { - - if (!forTouchZoom) { - this._animatingZoom = true; - } - - // put transform transition on all layers with leaflet-zoom-animated class - L.DomUtil.addClass(this._mapPane, 'leaflet-zoom-anim'); - - // remember what center/zoom to set after animation - this._animateToCenter = center; - this._animateToZoom = zoom; - - // disable any dragging during animation - if (L.Draggable) { - L.Draggable._disabled = true; - } - - L.Util.requestAnimFrame(function () { - this.fire('zoomanim', { - center: center, - zoom: zoom, - origin: origin, - scale: scale, - delta: delta, - backwards: backwards - }); - // horrible hack to work around a Chrome bug https://github.com/Leaflet/Leaflet/issues/3689 - setTimeout(L.bind(this._onZoomTransitionEnd, this), 250); - }, this); - }, - - _onZoomTransitionEnd: function () { - if (!this._animatingZoom) { return; } - - this._animatingZoom = false; - - L.DomUtil.removeClass(this._mapPane, 'leaflet-zoom-anim'); - - L.Util.requestAnimFrame(function () { - this._resetView(this._animateToCenter, this._animateToZoom, true, true); - - if (L.Draggable) { - L.Draggable._disabled = false; - } - }, this); - } -}); - - -/* - Zoom animation logic for L.TileLayer. -*/ - -L.TileLayer.include({ - _animateZoom: function (e) { - if (!this._animating) { - this._animating = true; - this._prepareBgBuffer(); - } - - var bg = this._bgBuffer, - transform = L.DomUtil.TRANSFORM, - initialTransform = e.delta ? L.DomUtil.getTranslateString(e.delta) : bg.style[transform], - scaleStr = L.DomUtil.getScaleString(e.scale, e.origin); - - bg.style[transform] = e.backwards ? - scaleStr + ' ' + initialTransform : - initialTransform + ' ' + scaleStr; - }, - - _endZoomAnim: function () { - var front = this._tileContainer, - bg = this._bgBuffer; - - front.style.visibility = ''; - front.parentNode.appendChild(front); // Bring to fore - - // force reflow - L.Util.falseFn(bg.offsetWidth); - - var zoom = this._map.getZoom(); - if (zoom > this.options.maxZoom || zoom < this.options.minZoom) { - this._clearBgBuffer(); - } - - this._animating = false; - }, - - _clearBgBuffer: function () { - var map = this._map; - - if (map && !map._animatingZoom && !map.touchZoom._zooming) { - this._bgBuffer.innerHTML = ''; - this._bgBuffer.style[L.DomUtil.TRANSFORM] = ''; - } - }, - - _prepareBgBuffer: function () { - - var front = this._tileContainer, - bg = this._bgBuffer; - - // if foreground layer doesn't have many tiles but bg layer does, - // keep the existing bg layer and just zoom it some more - - var bgLoaded = this._getLoadedTilesPercentage(bg), - frontLoaded = this._getLoadedTilesPercentage(front); - - if (bg && bgLoaded > 0.5 && frontLoaded < 0.5) { - - front.style.visibility = 'hidden'; - this._stopLoadingImages(front); - return; - } - - // prepare the buffer to become the front tile pane - bg.style.visibility = 'hidden'; - bg.style[L.DomUtil.TRANSFORM] = ''; - - // switch out the current layer to be the new bg layer (and vice-versa) - this._tileContainer = bg; - bg = this._bgBuffer = front; - - this._stopLoadingImages(bg); - - //prevent bg buffer from clearing right after zoom - clearTimeout(this._clearBgBufferTimer); - }, - - _getLoadedTilesPercentage: function (container) { - var tiles = container.getElementsByTagName('img'), - i, len, count = 0; - - for (i = 0, len = tiles.length; i < len; i++) { - if (tiles[i].complete) { - count++; - } - } - return count / len; - }, - - // stops loading all tiles in the background layer - _stopLoadingImages: function (container) { - var tiles = Array.prototype.slice.call(container.getElementsByTagName('img')), - i, len, tile; - - for (i = 0, len = tiles.length; i < len; i++) { - tile = tiles[i]; - - if (!tile.complete) { - tile.onload = L.Util.falseFn; - tile.onerror = L.Util.falseFn; - tile.src = L.Util.emptyImageUrl; - - tile.parentNode.removeChild(tile); - } - } - } -}); - - -/* - * Provides L.Map with convenient shortcuts for using browser geolocation features. - */ - -L.Map.include({ - _defaultLocateOptions: { - watch: false, - setView: false, - maxZoom: Infinity, - timeout: 10000, - maximumAge: 0, - enableHighAccuracy: false - }, - - locate: function (/*Object*/ options) { - - options = this._locateOptions = L.extend(this._defaultLocateOptions, options); - - if (!navigator.geolocation) { - this._handleGeolocationError({ - code: 0, - message: 'Geolocation not supported.' - }); - return this; - } - - var onResponse = L.bind(this._handleGeolocationResponse, this), - onError = L.bind(this._handleGeolocationError, this); - - if (options.watch) { - this._locationWatchId = - navigator.geolocation.watchPosition(onResponse, onError, options); - } else { - navigator.geolocation.getCurrentPosition(onResponse, onError, options); - } - return this; - }, - - stopLocate: function () { - if (navigator.geolocation) { - navigator.geolocation.clearWatch(this._locationWatchId); - } - if (this._locateOptions) { - this._locateOptions.setView = false; - } - return this; - }, - - _handleGeolocationError: function (error) { - var c = error.code, - message = error.message || - (c === 1 ? 'permission denied' : - (c === 2 ? 'position unavailable' : 'timeout')); - - if (this._locateOptions.setView && !this._loaded) { - this.fitWorld(); - } - - this.fire('locationerror', { - code: c, - message: 'Geolocation error: ' + message + '.' - }); - }, - - _handleGeolocationResponse: function (pos) { - var lat = pos.coords.latitude, - lng = pos.coords.longitude, - latlng = new L.LatLng(lat, lng), - - latAccuracy = 180 * pos.coords.accuracy / 40075017, - lngAccuracy = latAccuracy / Math.cos(L.LatLng.DEG_TO_RAD * lat), - - bounds = L.latLngBounds( - [lat - latAccuracy, lng - lngAccuracy], - [lat + latAccuracy, lng + lngAccuracy]), - - options = this._locateOptions; - - if (options.setView) { - var zoom = Math.min(this.getBoundsZoom(bounds), options.maxZoom); - this.setView(latlng, zoom); - } - - var data = { - latlng: latlng, - bounds: bounds, - timestamp: pos.timestamp - }; - - for (var i in pos.coords) { - if (typeof pos.coords[i] === 'number') { - data[i] = pos.coords[i]; - } - } - - this.fire('locationfound', data); - } -}); - - -}(window, document)); \ No newline at end of file diff --git a/assets/www/js/vendor/leaflet.awesome-markers.min.js b/assets/www/js/vendor/leaflet.awesome-markers.min.js deleted file mode 100644 index 376e57e68d6f93c56f4d683bee3cc150926e710b..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/leaflet.awesome-markers.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - Leaflet.AwesomeMarkers, a plugin that adds colorful iconic markers for Leaflet, based on the Font Awesome icons - (c) 2012-2013, Lennard Voogdt - - http://leafletjs.com - https://github.com/lvoogdt -*//*global L*/(function(e,t,n){"use strict";L.AwesomeMarkers={};L.AwesomeMarkers.version="2.0.1";L.AwesomeMarkers.Icon=L.Icon.extend({options:{iconSize:[35,45],iconAnchor:[17,42],popupAnchor:[1,-32],shadowAnchor:[10,12],shadowSize:[36,16],className:"awesome-marker",prefix:"glyphicon",spinClass:"fa-spin",icon:"home",markerColor:"blue",iconColor:"white"},initialize:function(e){e=L.Util.setOptions(this,e)},createIcon:function(){var e=t.createElement("div"),n=this.options;n.icon&&(e.innerHTML=this._createInner());n.bgPos&&(e.style.backgroundPosition=-n.bgPos.x+"px "+ -n.bgPos.y+"px");this._setIconStyles(e,"icon-"+n.markerColor);return e},_createInner:function(){var e,t="",n="",r="",i=this.options;i.icon.slice(0,i.prefix.length+1)===i.prefix+"-"?e=i.icon:e=i.prefix+"-"+i.icon;i.spin&&typeof i.spinClass=="string"&&(t=i.spinClass);i.iconColor&&(i.iconColor==="white"||i.iconColor==="black"?n="icon-"+i.iconColor:r="style='color: "+i.iconColor+"' ");return"<i "+r+"class='"+i.prefix+" "+e+" "+t+" "+n+"'></i>"},_setIconStyles:function(e,t){var n=this.options,r=L.point(n[t==="shadow"?"shadowSize":"iconSize"]),i;t==="shadow"?i=L.point(n.shadowAnchor||n.iconAnchor):i=L.point(n.iconAnchor);!i&&r&&(i=r.divideBy(2,!0));e.className="awesome-marker-"+t+" "+n.className;if(i){e.style.marginLeft=-i.x+"px";e.style.marginTop=-i.y+"px"}if(r){e.style.width=r.x+"px";e.style.height=r.y+"px"}},createShadow:function(){var e=t.createElement("div");this._setIconStyles(e,"shadow");return e}});L.AwesomeMarkers.icon=function(e){return new L.AwesomeMarkers.Icon(e)}})(this,document); diff --git a/assets/www/js/vendor/leaflet.easy-button.js b/assets/www/js/vendor/leaflet.easy-button.js deleted file mode 100644 index f71e072905c90e5539b66cc1eed7639f5e3bfc8e..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/leaflet.easy-button.js +++ /dev/null @@ -1,379 +0,0 @@ -(function(){ - -// This is for grouping buttons into a bar -// takes an array of `L.easyButton`s and -// then the usual `.addTo(map)` -L.Control.EasyBar = L.Control.extend({ - - options: { - position: 'topleft', // part of leaflet's defaults - id: null, // an id to tag the Bar with - leafletClasses: true // use leaflet classes? - }, - - - initialize: function(buttons, options){ - - if(options){ - L.Util.setOptions( this, options ); - } - - this._buildContainer(); - this._buttons = []; - - for(var i = 0; i < buttons.length; i++){ - buttons[i]._bar = this; - buttons[i]._container = buttons[i].button; - this._buttons.push(buttons[i]); - this.container.appendChild(buttons[i].button); - } - - }, - - - _buildContainer: function(){ - this._container = this.container = L.DomUtil.create('div', ''); - this.options.leafletClasses && L.DomUtil.addClass(this.container, 'leaflet-bar easy-button-container leaflet-control'); - this.options.id && (this.container.id = this.options.id); - }, - - - enable: function(){ - L.DomUtil.addClass(this.container, 'enabled'); - L.DomUtil.removeClass(this.container, 'disabled'); - this.container.setAttribute('aria-hidden', 'false'); - return this; - }, - - - disable: function(){ - L.DomUtil.addClass(this.container, 'disabled'); - L.DomUtil.removeClass(this.container, 'enabled'); - this.container.setAttribute('aria-hidden', 'true'); - return this; - }, - - - onAdd: function () { - return this.container; - }, - - addTo: function (map) { - this._map = map; - - for(var i = 0; i < this._buttons.length; i++){ - this._buttons[i]._map = map; - } - - var container = this._container = this.onAdd(map), - pos = this.getPosition(), - corner = map._controlCorners[pos]; - - L.DomUtil.addClass(container, 'leaflet-control'); - - if (pos.indexOf('bottom') !== -1) { - corner.insertBefore(container, corner.firstChild); - } else { - corner.appendChild(container); - } - - return this; - } - -}); - -L.easyBar = function(){ - var args = [L.Control.EasyBar]; - for(var i = 0; i < arguments.length; i++){ - args.push( arguments[i] ); - } - return new (Function.prototype.bind.apply(L.Control.EasyBar, args)); -}; - -// L.EasyButton is the actual buttons -// can be called without being grouped into a bar -L.Control.EasyButton = L.Control.extend({ - - options: { - position: 'topleft', // part of leaflet's defaults - - id: null, // an id to tag the button with - - type: 'replace', // [(replace|animate)] - // replace swaps out elements - // animate changes classes with all elements inserted - - states: [], // state names look like this - // { - // stateName: 'untracked', - // onClick: function(){ handle_nav_manually(); }; - // title: 'click to make inactive', - // icon: 'fa-circle', // wrapped with <a> - // } - - leafletClasses: true, // use leaflet styles for the button - tagName: 'button', - }, - - - - initialize: function(icon, onClick, title, id){ - - // clear the states manually - this.options.states = []; - - // add id to options - if(id != null){ - this.options.id = id; - } - - // storage between state functions - this.storage = {}; - - // is the last item an object? - if( typeof arguments[arguments.length-1] === 'object' ){ - - // if so, it should be the options - L.Util.setOptions( this, arguments[arguments.length-1] ); - } - - // if there aren't any states in options - // use the early params - if( this.options.states.length === 0 && - typeof icon === 'string' && - typeof onClick === 'function'){ - - // turn the options object into a state - this.options.states.push({ - icon: icon, - onClick: onClick, - title: typeof title === 'string' ? title : '' - }); - } - - // curate and move user's states into - // the _states for internal use - this._states = []; - - for(var i = 0; i < this.options.states.length; i++){ - this._states.push( new State(this.options.states[i], this) ); - } - - this._buildButton(); - - this._activateState(this._states[0]); - - }, - - _buildButton: function(){ - - this.button = L.DomUtil.create(this.options.tagName, ''); - - // the next three if statements should be collapsed into the options - // when it's time for breaking changes. - if (this.tagName === 'button') { - this.button.type = 'button'; - } - - if (this.options.id ){ - this.button.id = this.options.id; - } - - if (this.options.leafletClasses){ - L.DomUtil.addClass(this.button, 'easy-button-button leaflet-bar-part leaflet-interactive'); - } - - // don't let double clicks and mousedown get to the map - L.DomEvent.addListener(this.button, 'dblclick', L.DomEvent.stop); - L.DomEvent.addListener(this.button, 'mousedown', L.DomEvent.stop); - - // take care of normal clicks - L.DomEvent.addListener(this.button,'click', function(e){ - L.DomEvent.stop(e); - this._currentState.onClick(this, this._map ? this._map : null ); - this._map.getContainer().focus(); - }, this); - - // prep the contents of the control - if(this.options.type == 'replace'){ - this.button.appendChild(this._currentState.icon); - } else { - for(var i=0;i<this._states.length;i++){ - this.button.appendChild(this._states[i].icon); - } - } - }, - - - _currentState: { - // placeholder content - stateName: 'unnamed', - icon: (function(){ return document.createElement('span'); })() - }, - - - - _states: null, // populated on init - - - - state: function(newState){ - - // activate by name - if(typeof newState == 'string'){ - - this._activateStateNamed(newState); - - // activate by index - } else if (typeof newState == 'number'){ - - this._activateState(this._states[newState]); - } - - return this; - }, - - - _activateStateNamed: function(stateName){ - for(var i = 0; i < this._states.length; i++){ - if( this._states[i].stateName == stateName ){ - this._activateState( this._states[i] ); - } - } - }, - - _activateState: function(newState){ - - if( newState === this._currentState ){ - - // don't touch the dom if it'll just be the same after - return; - - } else { - - // swap out elements... if you're into that kind of thing - if( this.options.type == 'replace' ){ - this.button.appendChild(newState.icon); - this.button.removeChild(this._currentState.icon); - } - - if( newState.title ){ - this.button.title = newState.title; - } else { - this.button.removeAttribute('title'); - } - - // update classes for animations - for(var i=0;i<this._states.length;i++){ - L.DomUtil.removeClass(this._states[i].icon, this._currentState.stateName + '-active'); - L.DomUtil.addClass(this._states[i].icon, newState.stateName + '-active'); - } - - // update classes for animations - L.DomUtil.removeClass(this.button, this._currentState.stateName + '-active'); - L.DomUtil.addClass(this.button, newState.stateName + '-active'); - - // update the record - this._currentState = newState; - - } - }, - - - - enable: function(){ - L.DomUtil.addClass(this.button, 'enabled'); - L.DomUtil.removeClass(this.button, 'disabled'); - this.button.setAttribute('aria-hidden', 'false'); - return this; - }, - - - - disable: function(){ - L.DomUtil.addClass(this.button, 'disabled'); - L.DomUtil.removeClass(this.button, 'enabled'); - this.button.setAttribute('aria-hidden', 'true'); - return this; - }, - - - removeFrom: function (map) { - - this._container.parentNode.removeChild(this._container); - this._map = null; - - return this; - }, - - onAdd: function(){ - var containerObj = L.easyBar([this], { - position: this.options.position, - leafletClasses: this.options.leafletClasses - }); - this._container = containerObj.container; - return this._container; - } - - -}); - -L.easyButton = function(/* args will pass automatically */){ - var args = Array.prototype.concat.apply([L.Control.EasyButton],arguments); - return new (Function.prototype.bind.apply(L.Control.EasyButton, args)); -}; - -/************************* - * - * util functions - * - *************************/ - -// constructor for states so only curated -// states end up getting called -function State(template, easyButton){ - - this.title = template.title; - this.stateName = template.stateName ? template.stateName : 'unnamed-state'; - - // build the wrapper - this.icon = L.DomUtil.create('span', ''); - - L.DomUtil.addClass(this.icon, 'button-state state-' + this.stateName.replace(/(^\s*|\s*$)/g,'')); - this.icon.innerHTML = buildIcon(template.icon); - this.onClick = L.Util.bind(template.onClick?template.onClick:function(){}, easyButton); -} - -function buildIcon(ambiguousIconString) { - - var tmpIcon; - - // does this look like html? (i.e. not a class) - if( ambiguousIconString.match(/[&;=<>"']/) ){ - - // if so, the user should have put in html - // so move forward as such - tmpIcon = ambiguousIconString; - - // then it wasn't html, so - // it's a class list, figure out what kind - } else { - ambiguousIconString = ambiguousIconString.replace(/(^\s*|\s*$)/g,''); - tmpIcon = L.DomUtil.create('span', ''); - - if( ambiguousIconString.indexOf('fa-') === 0 ){ - L.DomUtil.addClass(tmpIcon, 'fa ' + ambiguousIconString) - } else if ( ambiguousIconString.indexOf('glyphicon-') === 0 ) { - L.DomUtil.addClass(tmpIcon, 'glyphicon ' + ambiguousIconString) - } else { - L.DomUtil.addClass(tmpIcon, /*rollwithit*/ ambiguousIconString) - } - - // make this a string so that it's easy to set innerHTML below - tmpIcon = tmpIcon.outerHTML; - } - - return tmpIcon; -} - -})(); diff --git a/assets/www/js/vendor/leaflet.featuregroup.subgroup-src.js b/assets/www/js/vendor/leaflet.featuregroup.subgroup-src.js deleted file mode 100644 index 0ce8c355bed261a4f2f1eb8fb77975d7d4f7607d..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/leaflet.featuregroup.subgroup-src.js +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Leaflet.FeatureGroup.SubGroup creates a Feature Group that adds its child - * layers into a parent group when added to a map (e.g. through L.Control.Layers). - * (c) 2015-2016 Boris Seang - * BSD 2-Clause "Simplified" License - */ - -(function (root, factory) { - if (typeof define === "function" && define.amd) { - define(["leaflet"], factory); - } else if (typeof module === "object" && module.exports) { - factory(require("leaflet")); - } else { - factory(root.L); - } -}(this, function (L) { - - L.FeatureGroup.SubGroup = L.FeatureGroup.extend({ - - statics: { - version: '0.1.2' - }, - - /** - * Instantiates a SubGroup. - * @param parentGroup (L.LayerGroup) (optional) - * @param layersArray (L.Layer[]) (optional) - */ - initialize: function (parentGroup, layersArray) { - L.FeatureGroup.prototype.initialize.call(this, layersArray); - - this.setParentGroup(parentGroup); - }, - - /** - * Changes the parent group into which child markers are added to / - * removed from. - * @param parentGroup (L.LayerGroup) - * @returns {SubGroup} this - */ - setParentGroup: function (parentGroup) { - var pgInstanceOfLG = parentGroup instanceof L.LayerGroup; - - this._parentGroup = parentGroup; - - // onAdd - this.onAdd = - pgInstanceOfLG ? - ( - typeof parentGroup.addLayers === "function" ? - this._onAddToGroupBatch : - this._onAddToGroup - ) : - this._onAddToMap; - - // onRemove - this.onRemove = - pgInstanceOfLG ? - ( - typeof parentGroup.removeLayers === "function" ? - this._onRemoveFromGroupBatch : - this._onRemoveFromGroup - ) : - this._onRemoveFromMap; - - // addLayer - this.addLayer = pgInstanceOfLG ? - this._addLayerToGroup : - this._addLayerToMap; - - // removeLayer - this.removeLayer = pgInstanceOfLG ? - this._removeLayerFromGroup : - this._removeLayerFromMap; - - return this; - }, - - /** - * Removes the current sub-group from map before changing the parent - * group. Re-adds the sub-group to map if it was before changing. - * @param parentGroup (L.LayerGroup) - * @returns {SubGroup} this - */ - setParentGroupSafe: function (parentGroup) { - var map = this._map; - - if (map) { - map.removeLayer(this); - } - - this.setParentGroup(parentGroup); - - if (map) { - map.addLayer(this); - } - - return this; - }, - - /** - * Returns the current parent group. - * @returns {*} - */ - getParentGroup: function () { - return this._parentGroup; - }, - - - // For parent groups with batch methods (addLayers and removeLayers) - // like MarkerCluster. - _onAddToGroupBatch: function (map) { - var layersArray = this.getLayers(); - - this._map = map; - this._parentGroup.addLayers(layersArray); - }, - - _onRemoveFromGroupBatch: function () { - var layersArray = this.getLayers(); - - this._parentGroup.removeLayers(layersArray); - this._map = null; - }, - - - // For other parent layer groups. - _onAddToGroup: function (map) { - var parentGroup = this._parentGroup; - - this._map = map; - this.eachLayer(parentGroup.addLayer, parentGroup); - }, - - _onRemoveFromGroup: function () { - var parentGroup = this._parentGroup; - - this.eachLayer(parentGroup.removeLayer, parentGroup); - this._map = null; - }, - - - // Defaults to standard FeatureGroup behaviour when parent group is not - // specified or is not a type of LayerGroup. - _onAddToMap: L.FeatureGroup.prototype.onAdd, - _onRemoveFromMap: L.FeatureGroup.prototype.onRemove, - - - _addLayerToGroup: function (layer) { - if (this.hasLayer(layer)) { - return this; - } - - if (layer.on) { - layer.on(L.FeatureGroup.EVENTS, this._propagateEvent, this); - } - - var id = this.getLayerId(layer); - - this._layers[id] = layer; - - if (this._map) { - // Add to parent group instead of directly to map. - this._parentGroup.addLayer(layer); - } - - if (this._popupContent && layer.bindPopup) { - layer.bindPopup(this._popupContent, this._popupOptions); - } - - return this.fire('layeradd', {layer: layer}); - }, - - _removeLayerFromGroup: function (layer) { - if (!this.hasLayer(layer)) { - return this; - } - if (layer in this._layers) { - layer = this._layers[layer]; - } - - if (layer.off) { - layer.off(L.FeatureGroup.EVENTS, this._propagateEvent, this); - } - - var id = layer in this._layers ? layer : this.getLayerId(layer); - - if (this._map && this._layers[id]) { - // Remove from parent group instead of directly from map. - this._parentGroup.removeLayer(id); - } - - delete this._layers[id]; - - if (this._popupContent) { - this.invoke('unbindPopup'); - } - - return this.fire('layerremove', {layer: layer}); - }, - - // Defaults to standard FeatureGroup behaviour when parent group is not - // specified or is not a type of LayerGroup. - _addLayerToMap: L.FeatureGroup.prototype.addLayer, - _removeLayerFromMap: L.FeatureGroup.prototype.removeLayer - - }); - - - - // Supply with a factory for consistency with Leaflet. - L.featureGroup.subGroup = function (parentGroup, options) { - return new L.FeatureGroup.SubGroup(parentGroup, options); - }; - -})); diff --git a/assets/www/js/vendor/leaflet.js b/assets/www/js/vendor/leaflet.js deleted file mode 100644 index ee5ff5a1d4bc321e2f521752ecf7c34dc33d3d82..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/leaflet.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com - (c) 2010-2013, Vladimir Agafonkin - (c) 2010-2011, CloudMade -*/ -!function(t,e,i){var n=t.L,o={};o.version="0.7.7","object"==typeof module&&"object"==typeof module.exports?module.exports=o:"function"==typeof define&&define.amd&&define(o),o.noConflict=function(){return t.L=n,this},t.L=o,o.Util={extend:function(t){var e,i,n,o,s=Array.prototype.slice.call(arguments,1);for(i=0,n=s.length;n>i;i++){o=s[i]||{};for(e in o)o.hasOwnProperty(e)&&(t[e]=o[e])}return t},bind:function(t,e){var i=arguments.length>2?Array.prototype.slice.call(arguments,2):null;return function(){return t.apply(e,i||arguments)}},stamp:function(){var t=0,e="_leaflet_id";return function(i){return i[e]=i[e]||++t,i[e]}}(),invokeEach:function(t,e,i){var n,o;if("object"==typeof t){o=Array.prototype.slice.call(arguments,3);for(n in t)e.apply(i,[n,t[n]].concat(o));return!0}return!1},limitExecByInterval:function(t,e,i){var n,o;return function s(){var a=arguments;return n?void(o=!0):(n=!0,setTimeout(function(){n=!1,o&&(s.apply(i,a),o=!1)},e),void t.apply(i,a))}},falseFn:function(){return!1},formatNum:function(t,e){var i=Math.pow(10,e||5);return Math.round(t*i)/i},trim:function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")},splitWords:function(t){return o.Util.trim(t).split(/\s+/)},setOptions:function(t,e){return t.options=o.extend({},t.options,e),t.options},getParamString:function(t,e,i){var n=[];for(var o in t)n.push(encodeURIComponent(i?o.toUpperCase():o)+"="+encodeURIComponent(t[o]));return(e&&-1!==e.indexOf("?")?"&":"?")+n.join("&")},template:function(t,e){return t.replace(/\{ *([\w_]+) *\}/g,function(t,n){var o=e[n];if(o===i)throw new Error("No value provided for variable "+t);return"function"==typeof o&&(o=o(e)),o})},isArray:Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)},emptyImageUrl:"data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="},function(){function e(e){var i,n,o=["webkit","moz","o","ms"];for(i=0;i<o.length&&!n;i++)n=t[o[i]+e];return n}function i(e){var i=+new Date,o=Math.max(0,16-(i-n));return n=i+o,t.setTimeout(e,o)}var n=0,s=t.requestAnimationFrame||e("RequestAnimationFrame")||i,a=t.cancelAnimationFrame||e("CancelAnimationFrame")||e("CancelRequestAnimationFrame")||function(e){t.clearTimeout(e)};o.Util.requestAnimFrame=function(e,n,a,r){return e=o.bind(e,n),a&&s===i?void e():s.call(t,e,r)},o.Util.cancelAnimFrame=function(e){e&&a.call(t,e)}}(),o.extend=o.Util.extend,o.bind=o.Util.bind,o.stamp=o.Util.stamp,o.setOptions=o.Util.setOptions,o.Class=function(){},o.Class.extend=function(t){var e=function(){this.initialize&&this.initialize.apply(this,arguments),this._initHooks&&this.callInitHooks()},i=function(){};i.prototype=this.prototype;var n=new i;n.constructor=e,e.prototype=n;for(var s in this)this.hasOwnProperty(s)&&"prototype"!==s&&(e[s]=this[s]);t.statics&&(o.extend(e,t.statics),delete t.statics),t.includes&&(o.Util.extend.apply(null,[n].concat(t.includes)),delete t.includes),t.options&&n.options&&(t.options=o.extend({},n.options,t.options)),o.extend(n,t),n._initHooks=[];var a=this;return e.__super__=a.prototype,n.callInitHooks=function(){if(!this._initHooksCalled){a.prototype.callInitHooks&&a.prototype.callInitHooks.call(this),this._initHooksCalled=!0;for(var t=0,e=n._initHooks.length;e>t;t++)n._initHooks[t].call(this)}},e},o.Class.include=function(t){o.extend(this.prototype,t)},o.Class.mergeOptions=function(t){o.extend(this.prototype.options,t)},o.Class.addInitHook=function(t){var e=Array.prototype.slice.call(arguments,1),i="function"==typeof t?t:function(){this[t].apply(this,e)};this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(i)};var s="_leaflet_events";o.Mixin={},o.Mixin.Events={addEventListener:function(t,e,i){if(o.Util.invokeEach(t,this.addEventListener,this,e,i))return this;var n,a,r,h,l,u,c,d=this[s]=this[s]||{},p=i&&i!==this&&o.stamp(i);for(t=o.Util.splitWords(t),n=0,a=t.length;a>n;n++)r={action:e,context:i||this},h=t[n],p?(l=h+"_idx",u=l+"_len",c=d[l]=d[l]||{},c[p]||(c[p]=[],d[u]=(d[u]||0)+1),c[p].push(r)):(d[h]=d[h]||[],d[h].push(r));return this},hasEventListeners:function(t){var e=this[s];return!!e&&(t in e&&e[t].length>0||t+"_idx"in e&&e[t+"_idx_len"]>0)},removeEventListener:function(t,e,i){if(!this[s])return this;if(!t)return this.clearAllEventListeners();if(o.Util.invokeEach(t,this.removeEventListener,this,e,i))return this;var n,a,r,h,l,u,c,d,p,_=this[s],m=i&&i!==this&&o.stamp(i);for(t=o.Util.splitWords(t),n=0,a=t.length;a>n;n++)if(r=t[n],u=r+"_idx",c=u+"_len",d=_[u],e){if(h=m&&d?d[m]:_[r]){for(l=h.length-1;l>=0;l--)h[l].action!==e||i&&h[l].context!==i||(p=h.splice(l,1),p[0].action=o.Util.falseFn);i&&d&&0===h.length&&(delete d[m],_[c]--)}}else delete _[r],delete _[u],delete _[c];return this},clearAllEventListeners:function(){return delete this[s],this},fireEvent:function(t,e){if(!this.hasEventListeners(t))return this;var i,n,a,r,h,l=o.Util.extend({},e,{type:t,target:this}),u=this[s];if(u[t])for(i=u[t].slice(),n=0,a=i.length;a>n;n++)i[n].action.call(i[n].context,l);r=u[t+"_idx"];for(h in r)if(i=r[h].slice())for(n=0,a=i.length;a>n;n++)i[n].action.call(i[n].context,l);return this},addOneTimeEventListener:function(t,e,i){if(o.Util.invokeEach(t,this.addOneTimeEventListener,this,e,i))return this;var n=o.bind(function(){this.removeEventListener(t,e,i).removeEventListener(t,n,i)},this);return this.addEventListener(t,e,i).addEventListener(t,n,i)}},o.Mixin.Events.on=o.Mixin.Events.addEventListener,o.Mixin.Events.off=o.Mixin.Events.removeEventListener,o.Mixin.Events.once=o.Mixin.Events.addOneTimeEventListener,o.Mixin.Events.fire=o.Mixin.Events.fireEvent,function(){var n="ActiveXObject"in t,s=n&&!e.addEventListener,a=navigator.userAgent.toLowerCase(),r=-1!==a.indexOf("webkit"),h=-1!==a.indexOf("chrome"),l=-1!==a.indexOf("phantom"),u=-1!==a.indexOf("android"),c=-1!==a.search("android [23]"),d=-1!==a.indexOf("gecko"),p=typeof orientation!=i+"",_=!t.PointerEvent&&t.MSPointerEvent,m=t.PointerEvent&&t.navigator.pointerEnabled||_,f="devicePixelRatio"in t&&t.devicePixelRatio>1||"matchMedia"in t&&t.matchMedia("(min-resolution:144dpi)")&&t.matchMedia("(min-resolution:144dpi)").matches,g=e.documentElement,v=n&&"transition"in g.style,y="WebKitCSSMatrix"in t&&"m11"in new t.WebKitCSSMatrix&&!c,P="MozPerspective"in g.style,L="OTransition"in g.style,x=!t.L_DISABLE_3D&&(v||y||P||L)&&!l,w=!t.L_NO_TOUCH&&!l&&(m||"ontouchstart"in t||t.DocumentTouch&&e instanceof t.DocumentTouch);o.Browser={ie:n,ielt9:s,webkit:r,gecko:d&&!r&&!t.opera&&!n,android:u,android23:c,chrome:h,ie3d:v,webkit3d:y,gecko3d:P,opera3d:L,any3d:x,mobile:p,mobileWebkit:p&&r,mobileWebkit3d:p&&y,mobileOpera:p&&t.opera,touch:w,msPointer:_,pointer:m,retina:f}}(),o.Point=function(t,e,i){this.x=i?Math.round(t):t,this.y=i?Math.round(e):e},o.Point.prototype={clone:function(){return new o.Point(this.x,this.y)},add:function(t){return this.clone()._add(o.point(t))},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(o.point(t))},_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t){return this.clone()._divideBy(t)},_divideBy:function(t){return this.x/=t,this.y/=t,this},multiplyBy:function(t){return this.clone()._multiplyBy(t)},_multiplyBy:function(t){return this.x*=t,this.y*=t,this},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},distanceTo:function(t){t=o.point(t);var e=t.x-this.x,i=t.y-this.y;return Math.sqrt(e*e+i*i)},equals:function(t){return t=o.point(t),t.x===this.x&&t.y===this.y},contains:function(t){return t=o.point(t),Math.abs(t.x)<=Math.abs(this.x)&&Math.abs(t.y)<=Math.abs(this.y)},toString:function(){return"Point("+o.Util.formatNum(this.x)+", "+o.Util.formatNum(this.y)+")"}},o.point=function(t,e,n){return t instanceof o.Point?t:o.Util.isArray(t)?new o.Point(t[0],t[1]):t===i||null===t?t:new o.Point(t,e,n)},o.Bounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},o.Bounds.prototype={extend:function(t){return t=o.point(t),this.min||this.max?(this.min.x=Math.min(t.x,this.min.x),this.max.x=Math.max(t.x,this.max.x),this.min.y=Math.min(t.y,this.min.y),this.max.y=Math.max(t.y,this.max.y)):(this.min=t.clone(),this.max=t.clone()),this},getCenter:function(t){return new o.Point((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2,t)},getBottomLeft:function(){return new o.Point(this.min.x,this.max.y)},getTopRight:function(){return new o.Point(this.max.x,this.min.y)},getSize:function(){return this.max.subtract(this.min)},contains:function(t){var e,i;return t="number"==typeof t[0]||t instanceof o.Point?o.point(t):o.bounds(t),t instanceof o.Bounds?(e=t.min,i=t.max):e=i=t,e.x>=this.min.x&&i.x<=this.max.x&&e.y>=this.min.y&&i.y<=this.max.y},intersects:function(t){t=o.bounds(t);var e=this.min,i=this.max,n=t.min,s=t.max,a=s.x>=e.x&&n.x<=i.x,r=s.y>=e.y&&n.y<=i.y;return a&&r},isValid:function(){return!(!this.min||!this.max)}},o.bounds=function(t,e){return!t||t instanceof o.Bounds?t:new o.Bounds(t,e)},o.Transformation=function(t,e,i,n){this._a=t,this._b=e,this._c=i,this._d=n},o.Transformation.prototype={transform:function(t,e){return this._transform(t.clone(),e)},_transform:function(t,e){return e=e||1,t.x=e*(this._a*t.x+this._b),t.y=e*(this._c*t.y+this._d),t},untransform:function(t,e){return e=e||1,new o.Point((t.x/e-this._b)/this._a,(t.y/e-this._d)/this._c)}},o.DomUtil={get:function(t){return"string"==typeof t?e.getElementById(t):t},getStyle:function(t,i){var n=t.style[i];if(!n&&t.currentStyle&&(n=t.currentStyle[i]),(!n||"auto"===n)&&e.defaultView){var o=e.defaultView.getComputedStyle(t,null);n=o?o[i]:null}return"auto"===n?null:n},getViewportOffset:function(t){var i,n=0,s=0,a=t,r=e.body,h=e.documentElement;do{if(n+=a.offsetTop||0,s+=a.offsetLeft||0,n+=parseInt(o.DomUtil.getStyle(a,"borderTopWidth"),10)||0,s+=parseInt(o.DomUtil.getStyle(a,"borderLeftWidth"),10)||0,i=o.DomUtil.getStyle(a,"position"),a.offsetParent===r&&"absolute"===i)break;if("fixed"===i){n+=r.scrollTop||h.scrollTop||0,s+=r.scrollLeft||h.scrollLeft||0;break}if("relative"===i&&!a.offsetLeft){var l=o.DomUtil.getStyle(a,"width"),u=o.DomUtil.getStyle(a,"max-width"),c=a.getBoundingClientRect();("none"!==l||"none"!==u)&&(s+=c.left+a.clientLeft),n+=c.top+(r.scrollTop||h.scrollTop||0);break}a=a.offsetParent}while(a);a=t;do{if(a===r)break;n-=a.scrollTop||0,s-=a.scrollLeft||0,a=a.parentNode}while(a);return new o.Point(s,n)},documentIsLtr:function(){return o.DomUtil._docIsLtrCached||(o.DomUtil._docIsLtrCached=!0,o.DomUtil._docIsLtr="ltr"===o.DomUtil.getStyle(e.body,"direction")),o.DomUtil._docIsLtr},create:function(t,i,n){var o=e.createElement(t);return o.className=i,n&&n.appendChild(o),o},hasClass:function(t,e){if(t.classList!==i)return t.classList.contains(e);var n=o.DomUtil._getClass(t);return n.length>0&&new RegExp("(^|\\s)"+e+"(\\s|$)").test(n)},addClass:function(t,e){if(t.classList!==i)for(var n=o.Util.splitWords(e),s=0,a=n.length;a>s;s++)t.classList.add(n[s]);else if(!o.DomUtil.hasClass(t,e)){var r=o.DomUtil._getClass(t);o.DomUtil._setClass(t,(r?r+" ":"")+e)}},removeClass:function(t,e){t.classList!==i?t.classList.remove(e):o.DomUtil._setClass(t,o.Util.trim((" "+o.DomUtil._getClass(t)+" ").replace(" "+e+" "," ")))},_setClass:function(t,e){t.className.baseVal===i?t.className=e:t.className.baseVal=e},_getClass:function(t){return t.className.baseVal===i?t.className:t.className.baseVal},setOpacity:function(t,e){if("opacity"in t.style)t.style.opacity=e;else if("filter"in t.style){var i=!1,n="DXImageTransform.Microsoft.Alpha";try{i=t.filters.item(n)}catch(o){if(1===e)return}e=Math.round(100*e),i?(i.Enabled=100!==e,i.Opacity=e):t.style.filter+=" progid:"+n+"(opacity="+e+")"}},testProp:function(t){for(var i=e.documentElement.style,n=0;n<t.length;n++)if(t[n]in i)return t[n];return!1},getTranslateString:function(t){var e=o.Browser.webkit3d,i="translate"+(e?"3d":"")+"(",n=(e?",0":"")+")";return i+t.x+"px,"+t.y+"px"+n},getScaleString:function(t,e){var i=o.DomUtil.getTranslateString(e.add(e.multiplyBy(-1*t))),n=" scale("+t+") ";return i+n},setPosition:function(t,e,i){t._leaflet_pos=e,!i&&o.Browser.any3d?t.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(e):(t.style.left=e.x+"px",t.style.top=e.y+"px")},getPosition:function(t){return t._leaflet_pos}},o.DomUtil.TRANSFORM=o.DomUtil.testProp(["transform","WebkitTransform","OTransform","MozTransform","msTransform"]),o.DomUtil.TRANSITION=o.DomUtil.testProp(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),o.DomUtil.TRANSITION_END="webkitTransition"===o.DomUtil.TRANSITION||"OTransition"===o.DomUtil.TRANSITION?o.DomUtil.TRANSITION+"End":"transitionend",function(){if("onselectstart"in e)o.extend(o.DomUtil,{disableTextSelection:function(){o.DomEvent.on(t,"selectstart",o.DomEvent.preventDefault)},enableTextSelection:function(){o.DomEvent.off(t,"selectstart",o.DomEvent.preventDefault)}});else{var i=o.DomUtil.testProp(["userSelect","WebkitUserSelect","OUserSelect","MozUserSelect","msUserSelect"]);o.extend(o.DomUtil,{disableTextSelection:function(){if(i){var t=e.documentElement.style;this._userSelect=t[i],t[i]="none"}},enableTextSelection:function(){i&&(e.documentElement.style[i]=this._userSelect,delete this._userSelect)}})}o.extend(o.DomUtil,{disableImageDrag:function(){o.DomEvent.on(t,"dragstart",o.DomEvent.preventDefault)},enableImageDrag:function(){o.DomEvent.off(t,"dragstart",o.DomEvent.preventDefault)}})}(),o.LatLng=function(t,e,n){if(t=parseFloat(t),e=parseFloat(e),isNaN(t)||isNaN(e))throw new Error("Invalid LatLng object: ("+t+", "+e+")");this.lat=t,this.lng=e,n!==i&&(this.alt=parseFloat(n))},o.extend(o.LatLng,{DEG_TO_RAD:Math.PI/180,RAD_TO_DEG:180/Math.PI,MAX_MARGIN:1e-9}),o.LatLng.prototype={equals:function(t){if(!t)return!1;t=o.latLng(t);var e=Math.max(Math.abs(this.lat-t.lat),Math.abs(this.lng-t.lng));return e<=o.LatLng.MAX_MARGIN},toString:function(t){return"LatLng("+o.Util.formatNum(this.lat,t)+", "+o.Util.formatNum(this.lng,t)+")"},distanceTo:function(t){t=o.latLng(t);var e=6378137,i=o.LatLng.DEG_TO_RAD,n=(t.lat-this.lat)*i,s=(t.lng-this.lng)*i,a=this.lat*i,r=t.lat*i,h=Math.sin(n/2),l=Math.sin(s/2),u=h*h+l*l*Math.cos(a)*Math.cos(r);return 2*e*Math.atan2(Math.sqrt(u),Math.sqrt(1-u))},wrap:function(t,e){var i=this.lng;return t=t||-180,e=e||180,i=(i+e)%(e-t)+(t>i||i===e?e:t),new o.LatLng(this.lat,i)}},o.latLng=function(t,e){return t instanceof o.LatLng?t:o.Util.isArray(t)?"number"==typeof t[0]||"string"==typeof t[0]?new o.LatLng(t[0],t[1],t[2]):null:t===i||null===t?t:"object"==typeof t&&"lat"in t?new o.LatLng(t.lat,"lng"in t?t.lng:t.lon):e===i?null:new o.LatLng(t,e)},o.LatLngBounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},o.LatLngBounds.prototype={extend:function(t){if(!t)return this;var e=o.latLng(t);return t=null!==e?e:o.latLngBounds(t),t instanceof o.LatLng?this._southWest||this._northEast?(this._southWest.lat=Math.min(t.lat,this._southWest.lat),this._southWest.lng=Math.min(t.lng,this._southWest.lng),this._northEast.lat=Math.max(t.lat,this._northEast.lat),this._northEast.lng=Math.max(t.lng,this._northEast.lng)):(this._southWest=new o.LatLng(t.lat,t.lng),this._northEast=new o.LatLng(t.lat,t.lng)):t instanceof o.LatLngBounds&&(this.extend(t._southWest),this.extend(t._northEast)),this},pad:function(t){var e=this._southWest,i=this._northEast,n=Math.abs(e.lat-i.lat)*t,s=Math.abs(e.lng-i.lng)*t;return new o.LatLngBounds(new o.LatLng(e.lat-n,e.lng-s),new o.LatLng(i.lat+n,i.lng+s))},getCenter:function(){return new o.LatLng((this._southWest.lat+this._northEast.lat)/2,(this._southWest.lng+this._northEast.lng)/2)},getSouthWest:function(){return this._southWest},getNorthEast:function(){return this._northEast},getNorthWest:function(){return new o.LatLng(this.getNorth(),this.getWest())},getSouthEast:function(){return new o.LatLng(this.getSouth(),this.getEast())},getWest:function(){return this._southWest.lng},getSouth:function(){return this._southWest.lat},getEast:function(){return this._northEast.lng},getNorth:function(){return this._northEast.lat},contains:function(t){t="number"==typeof t[0]||t instanceof o.LatLng?o.latLng(t):o.latLngBounds(t);var e,i,n=this._southWest,s=this._northEast;return t instanceof o.LatLngBounds?(e=t.getSouthWest(),i=t.getNorthEast()):e=i=t,e.lat>=n.lat&&i.lat<=s.lat&&e.lng>=n.lng&&i.lng<=s.lng},intersects:function(t){t=o.latLngBounds(t);var e=this._southWest,i=this._northEast,n=t.getSouthWest(),s=t.getNorthEast(),a=s.lat>=e.lat&&n.lat<=i.lat,r=s.lng>=e.lng&&n.lng<=i.lng;return a&&r},toBBoxString:function(){return[this.getWest(),this.getSouth(),this.getEast(),this.getNorth()].join(",")},equals:function(t){return t?(t=o.latLngBounds(t),this._southWest.equals(t.getSouthWest())&&this._northEast.equals(t.getNorthEast())):!1},isValid:function(){return!(!this._southWest||!this._northEast)}},o.latLngBounds=function(t,e){return!t||t instanceof o.LatLngBounds?t:new o.LatLngBounds(t,e)},o.Projection={},o.Projection.SphericalMercator={MAX_LATITUDE:85.0511287798,project:function(t){var e=o.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,n=Math.max(Math.min(i,t.lat),-i),s=t.lng*e,a=n*e;return a=Math.log(Math.tan(Math.PI/4+a/2)),new o.Point(s,a)},unproject:function(t){var e=o.LatLng.RAD_TO_DEG,i=t.x*e,n=(2*Math.atan(Math.exp(t.y))-Math.PI/2)*e;return new o.LatLng(n,i)}},o.Projection.LonLat={project:function(t){return new o.Point(t.lng,t.lat)},unproject:function(t){return new o.LatLng(t.y,t.x)}},o.CRS={latLngToPoint:function(t,e){var i=this.projection.project(t),n=this.scale(e);return this.transformation._transform(i,n)},pointToLatLng:function(t,e){var i=this.scale(e),n=this.transformation.untransform(t,i);return this.projection.unproject(n)},project:function(t){return this.projection.project(t)},scale:function(t){return 256*Math.pow(2,t)},getSize:function(t){var e=this.scale(t);return o.point(e,e)}},o.CRS.Simple=o.extend({},o.CRS,{projection:o.Projection.LonLat,transformation:new o.Transformation(1,0,-1,0),scale:function(t){return Math.pow(2,t)}}),o.CRS.EPSG3857=o.extend({},o.CRS,{code:"EPSG:3857",projection:o.Projection.SphericalMercator,transformation:new o.Transformation(.5/Math.PI,.5,-.5/Math.PI,.5),project:function(t){var e=this.projection.project(t),i=6378137;return e.multiplyBy(i)}}),o.CRS.EPSG900913=o.extend({},o.CRS.EPSG3857,{code:"EPSG:900913"}),o.CRS.EPSG4326=o.extend({},o.CRS,{code:"EPSG:4326",projection:o.Projection.LonLat,transformation:new o.Transformation(1/360,.5,-1/360,.5)}),o.Map=o.Class.extend({includes:o.Mixin.Events,options:{crs:o.CRS.EPSG3857,fadeAnimation:o.DomUtil.TRANSITION&&!o.Browser.android23,trackResize:!0,markerZoomAnimation:o.DomUtil.TRANSITION&&o.Browser.any3d},initialize:function(t,e){e=o.setOptions(this,e),this._initContainer(t),this._initLayout(),this._onResize=o.bind(this._onResize,this),this._initEvents(),e.maxBounds&&this.setMaxBounds(e.maxBounds),e.center&&e.zoom!==i&&this.setView(o.latLng(e.center),e.zoom,{reset:!0}),this._handlers=[],this._layers={},this._zoomBoundLayers={},this._tileLayersNum=0,this.callInitHooks(),this._addLayers(e.layers)},setView:function(t,e){return e=e===i?this.getZoom():e,this._resetView(o.latLng(t),this._limitZoom(e)),this},setZoom:function(t,e){return this._loaded?this.setView(this.getCenter(),t,{zoom:e}):(this._zoom=this._limitZoom(t),this)},zoomIn:function(t,e){return this.setZoom(this._zoom+(t||1),e)},zoomOut:function(t,e){return this.setZoom(this._zoom-(t||1),e)},setZoomAround:function(t,e,i){var n=this.getZoomScale(e),s=this.getSize().divideBy(2),a=t instanceof o.Point?t:this.latLngToContainerPoint(t),r=a.subtract(s).multiplyBy(1-1/n),h=this.containerPointToLatLng(s.add(r));return this.setView(h,e,{zoom:i})},fitBounds:function(t,e){e=e||{},t=t.getBounds?t.getBounds():o.latLngBounds(t);var i=o.point(e.paddingTopLeft||e.padding||[0,0]),n=o.point(e.paddingBottomRight||e.padding||[0,0]),s=this.getBoundsZoom(t,!1,i.add(n));s=e.maxZoom?Math.min(e.maxZoom,s):s;var a=n.subtract(i).divideBy(2),r=this.project(t.getSouthWest(),s),h=this.project(t.getNorthEast(),s),l=this.unproject(r.add(h).divideBy(2).add(a),s);return this.setView(l,s,e)},fitWorld:function(t){return this.fitBounds([[-90,-180],[90,180]],t)},panTo:function(t,e){return this.setView(t,this._zoom,{pan:e})},panBy:function(t){return this.fire("movestart"),this._rawPanBy(o.point(t)),this.fire("move"),this.fire("moveend")},setMaxBounds:function(t){return t=o.latLngBounds(t),this.options.maxBounds=t,t?(this._loaded&&this._panInsideMaxBounds(),this.on("moveend",this._panInsideMaxBounds,this)):this.off("moveend",this._panInsideMaxBounds,this)},panInsideBounds:function(t,e){var i=this.getCenter(),n=this._limitCenter(i,this._zoom,t);return i.equals(n)?this:this.panTo(n,e)},addLayer:function(t){var e=o.stamp(t);return this._layers[e]?this:(this._layers[e]=t,!t.options||isNaN(t.options.maxZoom)&&isNaN(t.options.minZoom)||(this._zoomBoundLayers[e]=t,this._updateZoomLevels()),this.options.zoomAnimation&&o.TileLayer&&t instanceof o.TileLayer&&(this._tileLayersNum++,this._tileLayersToLoad++,t.on("load",this._onTileLayerLoad,this)),this._loaded&&this._layerAdd(t),this)},removeLayer:function(t){var e=o.stamp(t);return this._layers[e]?(this._loaded&&t.onRemove(this),delete this._layers[e],this._loaded&&this.fire("layerremove",{layer:t}),this._zoomBoundLayers[e]&&(delete this._zoomBoundLayers[e],this._updateZoomLevels()),this.options.zoomAnimation&&o.TileLayer&&t instanceof o.TileLayer&&(this._tileLayersNum--,this._tileLayersToLoad--,t.off("load",this._onTileLayerLoad,this)),this):this},hasLayer:function(t){return t?o.stamp(t)in this._layers:!1},eachLayer:function(t,e){for(var i in this._layers)t.call(e,this._layers[i]);return this},invalidateSize:function(t){if(!this._loaded)return this;t=o.extend({animate:!1,pan:!0},t===!0?{animate:!0}:t);var e=this.getSize();this._sizeChanged=!0,this._initialCenter=null;var i=this.getSize(),n=e.divideBy(2).round(),s=i.divideBy(2).round(),a=n.subtract(s);return a.x||a.y?(t.animate&&t.pan?this.panBy(a):(t.pan&&this._rawPanBy(a),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(o.bind(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:e,newSize:i})):this},addHandler:function(t,e){if(!e)return this;var i=this[t]=new e(this);return this._handlers.push(i),this.options[t]&&i.enable(),this},remove:function(){this._loaded&&this.fire("unload"),this._initEvents("off");try{delete this._container._leaflet}catch(t){this._container._leaflet=i}return this._clearPanes(),this._clearControlPos&&this._clearControlPos(),this._clearHandlers(),this},getCenter:function(){return this._checkIfLoaded(),this._initialCenter&&!this._moved()?this._initialCenter:this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds(),e=this.unproject(t.getBottomLeft()),i=this.unproject(t.getTopRight());return new o.LatLngBounds(e,i)},getMinZoom:function(){return this.options.minZoom===i?this._layersMinZoom===i?0:this._layersMinZoom:this.options.minZoom},getMaxZoom:function(){return this.options.maxZoom===i?this._layersMaxZoom===i?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,e,i){t=o.latLngBounds(t);var n,s=this.getMinZoom()-(e?1:0),a=this.getMaxZoom(),r=this.getSize(),h=t.getNorthWest(),l=t.getSouthEast(),u=!0;i=o.point(i||[0,0]);do s++,n=this.project(l,s).subtract(this.project(h,s)).add(i),u=e?n.x<r.x||n.y<r.y:r.contains(n);while(u&&a>=s);return u&&e?null:e?s:s-1},getSize:function(){return(!this._size||this._sizeChanged)&&(this._size=new o.Point(this._container.clientWidth,this._container.clientHeight),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(){var t=this._getTopLeftPoint();return new o.Bounds(t,t.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._initialTopLeftPoint},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t){var e=this.options.crs;return e.scale(t)/e.scale(this._zoom)},getScaleZoom:function(t){return this._zoom+Math.log(t)/Math.LN2},project:function(t,e){return e=e===i?this._zoom:e,this.options.crs.latLngToPoint(o.latLng(t),e)},unproject:function(t,e){return e=e===i?this._zoom:e,this.options.crs.pointToLatLng(o.point(t),e)},layerPointToLatLng:function(t){var e=o.point(t).add(this.getPixelOrigin());return this.unproject(e)},latLngToLayerPoint:function(t){var e=this.project(o.latLng(t))._round();return e._subtract(this.getPixelOrigin())},containerPointToLayerPoint:function(t){return o.point(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return o.point(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var e=this.containerPointToLayerPoint(o.point(t));return this.layerPointToLatLng(e)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(o.latLng(t)))},mouseEventToContainerPoint:function(t){return o.DomEvent.getMousePosition(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var e=this._container=o.DomUtil.get(t);if(!e)throw new Error("Map container not found.");if(e._leaflet)throw new Error("Map container is already initialized.");e._leaflet=!0},_initLayout:function(){var t=this._container;o.DomUtil.addClass(t,"leaflet-container"+(o.Browser.touch?" leaflet-touch":"")+(o.Browser.retina?" leaflet-retina":"")+(o.Browser.ielt9?" leaflet-oldie":"")+(this.options.fadeAnimation?" leaflet-fade-anim":""));var e=o.DomUtil.getStyle(t,"position");"absolute"!==e&&"relative"!==e&&"fixed"!==e&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._mapPane=t.mapPane=this._createPane("leaflet-map-pane",this._container),this._tilePane=t.tilePane=this._createPane("leaflet-tile-pane",this._mapPane),t.objectsPane=this._createPane("leaflet-objects-pane",this._mapPane),t.shadowPane=this._createPane("leaflet-shadow-pane"),t.overlayPane=this._createPane("leaflet-overlay-pane"),t.markerPane=this._createPane("leaflet-marker-pane"),t.popupPane=this._createPane("leaflet-popup-pane");var e=" leaflet-zoom-hide";this.options.markerZoomAnimation||(o.DomUtil.addClass(t.markerPane,e),o.DomUtil.addClass(t.shadowPane,e),o.DomUtil.addClass(t.popupPane,e))},_createPane:function(t,e){return o.DomUtil.create("div",t,e||this._panes.objectsPane)},_clearPanes:function(){this._container.removeChild(this._mapPane)},_addLayers:function(t){t=t?o.Util.isArray(t)?t:[t]:[];for(var e=0,i=t.length;i>e;e++)this.addLayer(t[e])},_resetView:function(t,e,i,n){var s=this._zoom!==e;n||(this.fire("movestart"),s&&this.fire("zoomstart")),this._zoom=e,this._initialCenter=t,this._initialTopLeftPoint=this._getNewTopLeftPoint(t),i?this._initialTopLeftPoint._add(this._getMapPanePos()):o.DomUtil.setPosition(this._mapPane,new o.Point(0,0)),this._tileLayersToLoad=this._tileLayersNum;var a=!this._loaded;this._loaded=!0,this.fire("viewreset",{hard:!i}),a&&(this.fire("load"),this.eachLayer(this._layerAdd,this)),this.fire("move"),(s||n)&&this.fire("zoomend"),this.fire("moveend",{hard:!i})},_rawPanBy:function(t){o.DomUtil.setPosition(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_updateZoomLevels:function(){var t,e=1/0,n=-(1/0),o=this._getZoomSpan();for(t in this._zoomBoundLayers){var s=this._zoomBoundLayers[t];isNaN(s.options.minZoom)||(e=Math.min(e,s.options.minZoom)),isNaN(s.options.maxZoom)||(n=Math.max(n,s.options.maxZoom))}t===i?this._layersMaxZoom=this._layersMinZoom=i:(this._layersMaxZoom=n,this._layersMinZoom=e),o!==this._getZoomSpan()&&this.fire("zoomlevelschange")},_panInsideMaxBounds:function(){this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(e){if(o.DomEvent){e=e||"on",o.DomEvent[e](this._container,"click",this._onMouseClick,this);var i,n,s=["dblclick","mousedown","mouseup","mouseenter","mouseleave","mousemove","contextmenu"];for(i=0,n=s.length;n>i;i++)o.DomEvent[e](this._container,s[i],this._fireMouseEvent,this);this.options.trackResize&&o.DomEvent[e](t,"resize",this._onResize,this)}},_onResize:function(){o.Util.cancelAnimFrame(this._resizeRequest),this._resizeRequest=o.Util.requestAnimFrame(function(){this.invalidateSize({debounceMoveend:!0})},this,!1,this._container)},_onMouseClick:function(t){!this._loaded||!t._simulated&&(this.dragging&&this.dragging.moved()||this.boxZoom&&this.boxZoom.moved())||o.DomEvent._skipped(t)||(this.fire("preclick"),this._fireMouseEvent(t))},_fireMouseEvent:function(t){if(this._loaded&&!o.DomEvent._skipped(t)){var e=t.type;if(e="mouseenter"===e?"mouseover":"mouseleave"===e?"mouseout":e,this.hasEventListeners(e)){"contextmenu"===e&&o.DomEvent.preventDefault(t);var i=this.mouseEventToContainerPoint(t),n=this.containerPointToLayerPoint(i),s=this.layerPointToLatLng(n);this.fire(e,{latlng:s,layerPoint:n,containerPoint:i,originalEvent:t})}}},_onTileLayerLoad:function(){this._tileLayersToLoad--,this._tileLayersNum&&!this._tileLayersToLoad&&this.fire("tilelayersload")},_clearHandlers:function(){for(var t=0,e=this._handlers.length;e>t;t++)this._handlers[t].disable()},whenReady:function(t,e){return this._loaded?t.call(e||this,this):this.on("load",t,e),this},_layerAdd:function(t){t.onAdd(this),this.fire("layeradd",{layer:t})},_getMapPanePos:function(){return o.DomUtil.getPosition(this._mapPane)},_moved:function(){var t=this._getMapPanePos();return t&&!t.equals([0,0])},_getTopLeftPoint:function(){return this.getPixelOrigin().subtract(this._getMapPanePos())},_getNewTopLeftPoint:function(t,e){var i=this.getSize()._divideBy(2);return this.project(t,e)._subtract(i)._round()},_latLngToNewLayerPoint:function(t,e,i){var n=this._getNewTopLeftPoint(i,e).add(this._getMapPanePos());return this.project(t,e)._subtract(n)},_getCenterLayerPoint:function(){return this.containerPointToLayerPoint(this.getSize()._divideBy(2))},_getCenterOffset:function(t){return this.latLngToLayerPoint(t).subtract(this._getCenterLayerPoint())},_limitCenter:function(t,e,i){if(!i)return t;var n=this.project(t,e),s=this.getSize().divideBy(2),a=new o.Bounds(n.subtract(s),n.add(s)),r=this._getBoundsOffset(a,i,e);return this.unproject(n.add(r),e)},_limitOffset:function(t,e){if(!e)return t;var i=this.getPixelBounds(),n=new o.Bounds(i.min.add(t),i.max.add(t));return t.add(this._getBoundsOffset(n,e))},_getBoundsOffset:function(t,e,i){var n=this.project(e.getNorthWest(),i).subtract(t.min),s=this.project(e.getSouthEast(),i).subtract(t.max),a=this._rebound(n.x,-s.x),r=this._rebound(n.y,-s.y);return new o.Point(a,r)},_rebound:function(t,e){return t+e>0?Math.round(t-e)/2:Math.max(0,Math.ceil(t))-Math.max(0,Math.floor(e))},_limitZoom:function(t){var e=this.getMinZoom(),i=this.getMaxZoom();return Math.max(e,Math.min(i,t))}}),o.map=function(t,e){return new o.Map(t,e)},o.Projection.Mercator={MAX_LATITUDE:85.0840591556,R_MINOR:6356752.314245179,R_MAJOR:6378137,project:function(t){var e=o.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,n=Math.max(Math.min(i,t.lat),-i),s=this.R_MAJOR,a=this.R_MINOR,r=t.lng*e*s,h=n*e,l=a/s,u=Math.sqrt(1-l*l),c=u*Math.sin(h);c=Math.pow((1-c)/(1+c),.5*u);var d=Math.tan(.5*(.5*Math.PI-h))/c;return h=-s*Math.log(d),new o.Point(r,h)},unproject:function(t){for(var e,i=o.LatLng.RAD_TO_DEG,n=this.R_MAJOR,s=this.R_MINOR,a=t.x*i/n,r=s/n,h=Math.sqrt(1-r*r),l=Math.exp(-t.y/n),u=Math.PI/2-2*Math.atan(l),c=15,d=1e-7,p=c,_=.1;Math.abs(_)>d&&--p>0;)e=h*Math.sin(u),_=Math.PI/2-2*Math.atan(l*Math.pow((1-e)/(1+e),.5*h))-u,u+=_;return new o.LatLng(u*i,a)}},o.CRS.EPSG3395=o.extend({},o.CRS,{code:"EPSG:3395",projection:o.Projection.Mercator, -transformation:function(){var t=o.Projection.Mercator,e=t.R_MAJOR,i=.5/(Math.PI*e);return new o.Transformation(i,.5,-i,.5)}()}),o.TileLayer=o.Class.extend({includes:o.Mixin.Events,options:{minZoom:0,maxZoom:18,tileSize:256,subdomains:"abc",errorTileUrl:"",attribution:"",zoomOffset:0,opacity:1,unloadInvisibleTiles:o.Browser.mobile,updateWhenIdle:o.Browser.mobile},initialize:function(t,e){e=o.setOptions(this,e),e.detectRetina&&o.Browser.retina&&e.maxZoom>0&&(e.tileSize=Math.floor(e.tileSize/2),e.zoomOffset++,e.minZoom>0&&e.minZoom--,this.options.maxZoom--),e.bounds&&(e.bounds=o.latLngBounds(e.bounds)),this._url=t;var i=this.options.subdomains;"string"==typeof i&&(this.options.subdomains=i.split(""))},onAdd:function(t){this._map=t,this._animated=t._zoomAnimated,this._initContainer(),t.on({viewreset:this._reset,moveend:this._update},this),this._animated&&t.on({zoomanim:this._animateZoom,zoomend:this._endZoomAnim},this),this.options.updateWhenIdle||(this._limitedUpdate=o.Util.limitExecByInterval(this._update,150,this),t.on("move",this._limitedUpdate,this)),this._reset(),this._update()},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this._container.parentNode.removeChild(this._container),t.off({viewreset:this._reset,moveend:this._update},this),this._animated&&t.off({zoomanim:this._animateZoom,zoomend:this._endZoomAnim},this),this.options.updateWhenIdle||t.off("move",this._limitedUpdate,this),this._container=null,this._map=null},bringToFront:function(){var t=this._map._panes.tilePane;return this._container&&(t.appendChild(this._container),this._setAutoZIndex(t,Math.max)),this},bringToBack:function(){var t=this._map._panes.tilePane;return this._container&&(t.insertBefore(this._container,t.firstChild),this._setAutoZIndex(t,Math.min)),this},getAttribution:function(){return this.options.attribution},getContainer:function(){return this._container},setOpacity:function(t){return this.options.opacity=t,this._map&&this._updateOpacity(),this},setZIndex:function(t){return this.options.zIndex=t,this._updateZIndex(),this},setUrl:function(t,e){return this._url=t,e||this.redraw(),this},redraw:function(){return this._map&&(this._reset({hard:!0}),this._update()),this},_updateZIndex:function(){this._container&&this.options.zIndex!==i&&(this._container.style.zIndex=this.options.zIndex)},_setAutoZIndex:function(t,e){var i,n,o,s=t.children,a=-e(1/0,-(1/0));for(n=0,o=s.length;o>n;n++)s[n]!==this._container&&(i=parseInt(s[n].style.zIndex,10),isNaN(i)||(a=e(a,i)));this.options.zIndex=this._container.style.zIndex=(isFinite(a)?a:0)+e(1,-1)},_updateOpacity:function(){var t,e=this._tiles;if(o.Browser.ielt9)for(t in e)o.DomUtil.setOpacity(e[t],this.options.opacity);else o.DomUtil.setOpacity(this._container,this.options.opacity)},_initContainer:function(){var t=this._map._panes.tilePane;if(!this._container){if(this._container=o.DomUtil.create("div","leaflet-layer"),this._updateZIndex(),this._animated){var e="leaflet-tile-container";this._bgBuffer=o.DomUtil.create("div",e,this._container),this._tileContainer=o.DomUtil.create("div",e,this._container)}else this._tileContainer=this._container;t.appendChild(this._container),this.options.opacity<1&&this._updateOpacity()}},_reset:function(t){for(var e in this._tiles)this.fire("tileunload",{tile:this._tiles[e]});this._tiles={},this._tilesToLoad=0,this.options.reuseTiles&&(this._unusedTiles=[]),this._tileContainer.innerHTML="",this._animated&&t&&t.hard&&this._clearBgBuffer(),this._initContainer()},_getTileSize:function(){var t=this._map,e=t.getZoom()+this.options.zoomOffset,i=this.options.maxNativeZoom,n=this.options.tileSize;return i&&e>i&&(n=Math.round(t.getZoomScale(e)/t.getZoomScale(i)*n)),n},_update:function(){if(this._map){var t=this._map,e=t.getPixelBounds(),i=t.getZoom(),n=this._getTileSize();if(!(i>this.options.maxZoom||i<this.options.minZoom)){var s=o.bounds(e.min.divideBy(n)._floor(),e.max.divideBy(n)._floor());this._addTilesFromCenterOut(s),(this.options.unloadInvisibleTiles||this.options.reuseTiles)&&this._removeOtherTiles(s)}}},_addTilesFromCenterOut:function(t){var i,n,s,a=[],r=t.getCenter();for(i=t.min.y;i<=t.max.y;i++)for(n=t.min.x;n<=t.max.x;n++)s=new o.Point(n,i),this._tileShouldBeLoaded(s)&&a.push(s);var h=a.length;if(0!==h){a.sort(function(t,e){return t.distanceTo(r)-e.distanceTo(r)});var l=e.createDocumentFragment();for(this._tilesToLoad||this.fire("loading"),this._tilesToLoad+=h,n=0;h>n;n++)this._addTile(a[n],l);this._tileContainer.appendChild(l)}},_tileShouldBeLoaded:function(t){if(t.x+":"+t.y in this._tiles)return!1;var e=this.options;if(!e.continuousWorld){var i=this._getWrapTileNum();if(e.noWrap&&(t.x<0||t.x>=i.x)||t.y<0||t.y>=i.y)return!1}if(e.bounds){var n=this._getTileSize(),o=t.multiplyBy(n),s=o.add([n,n]),a=this._map.unproject(o),r=this._map.unproject(s);if(e.continuousWorld||e.noWrap||(a=a.wrap(),r=r.wrap()),!e.bounds.intersects([a,r]))return!1}return!0},_removeOtherTiles:function(t){var e,i,n,o;for(o in this._tiles)e=o.split(":"),i=parseInt(e[0],10),n=parseInt(e[1],10),(i<t.min.x||i>t.max.x||n<t.min.y||n>t.max.y)&&this._removeTile(o)},_removeTile:function(t){var e=this._tiles[t];this.fire("tileunload",{tile:e,url:e.src}),this.options.reuseTiles?(o.DomUtil.removeClass(e,"leaflet-tile-loaded"),this._unusedTiles.push(e)):e.parentNode===this._tileContainer&&this._tileContainer.removeChild(e),o.Browser.android||(e.onload=null,e.src=o.Util.emptyImageUrl),delete this._tiles[t]},_addTile:function(t,e){var i=this._getTilePos(t),n=this._getTile();o.DomUtil.setPosition(n,i,o.Browser.chrome),this._tiles[t.x+":"+t.y]=n,this._loadTile(n,t),n.parentNode!==this._tileContainer&&e.appendChild(n)},_getZoomForUrl:function(){var t=this.options,e=this._map.getZoom();return t.zoomReverse&&(e=t.maxZoom-e),e+=t.zoomOffset,t.maxNativeZoom?Math.min(e,t.maxNativeZoom):e},_getTilePos:function(t){var e=this._map.getPixelOrigin(),i=this._getTileSize();return t.multiplyBy(i).subtract(e)},getTileUrl:function(t){return o.Util.template(this._url,o.extend({s:this._getSubdomain(t),z:t.z,x:t.x,y:t.y},this.options))},_getWrapTileNum:function(){var t=this._map.options.crs,e=t.getSize(this._map.getZoom());return e.divideBy(this._getTileSize())._floor()},_adjustTilePoint:function(t){var e=this._getWrapTileNum();this.options.continuousWorld||this.options.noWrap||(t.x=(t.x%e.x+e.x)%e.x),this.options.tms&&(t.y=e.y-t.y-1),t.z=this._getZoomForUrl()},_getSubdomain:function(t){var e=Math.abs(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[e]},_getTile:function(){if(this.options.reuseTiles&&this._unusedTiles.length>0){var t=this._unusedTiles.pop();return this._resetTile(t),t}return this._createTile()},_resetTile:function(){},_createTile:function(){var t=o.DomUtil.create("img","leaflet-tile");return t.style.width=t.style.height=this._getTileSize()+"px",t.galleryimg="no",t.onselectstart=t.onmousemove=o.Util.falseFn,o.Browser.ielt9&&this.options.opacity!==i&&o.DomUtil.setOpacity(t,this.options.opacity),o.Browser.mobileWebkit3d&&(t.style.WebkitBackfaceVisibility="hidden"),t},_loadTile:function(t,e){t._layer=this,t.onload=this._tileOnLoad,t.onerror=this._tileOnError,this._adjustTilePoint(e),t.src=this.getTileUrl(e),this.fire("tileloadstart",{tile:t,url:t.src})},_tileLoaded:function(){this._tilesToLoad--,this._animated&&o.DomUtil.addClass(this._tileContainer,"leaflet-zoom-animated"),this._tilesToLoad||(this.fire("load"),this._animated&&(clearTimeout(this._clearBgBufferTimer),this._clearBgBufferTimer=setTimeout(o.bind(this._clearBgBuffer,this),500)))},_tileOnLoad:function(){var t=this._layer;this.src!==o.Util.emptyImageUrl&&(o.DomUtil.addClass(this,"leaflet-tile-loaded"),t.fire("tileload",{tile:this,url:this.src})),t._tileLoaded()},_tileOnError:function(){var t=this._layer;t.fire("tileerror",{tile:this,url:this.src});var e=t.options.errorTileUrl;e&&(this.src=e),t._tileLoaded()}}),o.tileLayer=function(t,e){return new o.TileLayer(t,e)},o.TileLayer.WMS=o.TileLayer.extend({defaultWmsParams:{service:"WMS",request:"GetMap",version:"1.1.1",layers:"",styles:"",format:"image/jpeg",transparent:!1},initialize:function(t,e){this._url=t;var i=o.extend({},this.defaultWmsParams),n=e.tileSize||this.options.tileSize;e.detectRetina&&o.Browser.retina?i.width=i.height=2*n:i.width=i.height=n;for(var s in e)this.options.hasOwnProperty(s)||"crs"===s||(i[s]=e[s]);this.wmsParams=i,o.setOptions(this,e)},onAdd:function(t){this._crs=this.options.crs||t.options.crs,this._wmsVersion=parseFloat(this.wmsParams.version);var e=this._wmsVersion>=1.3?"crs":"srs";this.wmsParams[e]=this._crs.code,o.TileLayer.prototype.onAdd.call(this,t)},getTileUrl:function(t){var e=this._map,i=this.options.tileSize,n=t.multiplyBy(i),s=n.add([i,i]),a=this._crs.project(e.unproject(n,t.z)),r=this._crs.project(e.unproject(s,t.z)),h=this._wmsVersion>=1.3&&this._crs===o.CRS.EPSG4326?[r.y,a.x,a.y,r.x].join(","):[a.x,r.y,r.x,a.y].join(","),l=o.Util.template(this._url,{s:this._getSubdomain(t)});return l+o.Util.getParamString(this.wmsParams,l,!0)+"&BBOX="+h},setParams:function(t,e){return o.extend(this.wmsParams,t),e||this.redraw(),this}}),o.tileLayer.wms=function(t,e){return new o.TileLayer.WMS(t,e)},o.TileLayer.Canvas=o.TileLayer.extend({options:{async:!1},initialize:function(t){o.setOptions(this,t)},redraw:function(){this._map&&(this._reset({hard:!0}),this._update());for(var t in this._tiles)this._redrawTile(this._tiles[t]);return this},_redrawTile:function(t){this.drawTile(t,t._tilePoint,this._map._zoom)},_createTile:function(){var t=o.DomUtil.create("canvas","leaflet-tile");return t.width=t.height=this.options.tileSize,t.onselectstart=t.onmousemove=o.Util.falseFn,t},_loadTile:function(t,e){t._layer=this,t._tilePoint=e,this._redrawTile(t),this.options.async||this.tileDrawn(t)},drawTile:function(){},tileDrawn:function(t){this._tileOnLoad.call(t)}}),o.tileLayer.canvas=function(t){return new o.TileLayer.Canvas(t)},o.ImageOverlay=o.Class.extend({includes:o.Mixin.Events,options:{opacity:1},initialize:function(t,e,i){this._url=t,this._bounds=o.latLngBounds(e),o.setOptions(this,i)},onAdd:function(t){this._map=t,this._image||this._initImage(),t._panes.overlayPane.appendChild(this._image),t.on("viewreset",this._reset,this),t.options.zoomAnimation&&o.Browser.any3d&&t.on("zoomanim",this._animateZoom,this),this._reset()},onRemove:function(t){t.getPanes().overlayPane.removeChild(this._image),t.off("viewreset",this._reset,this),t.options.zoomAnimation&&t.off("zoomanim",this._animateZoom,this)},addTo:function(t){return t.addLayer(this),this},setOpacity:function(t){return this.options.opacity=t,this._updateOpacity(),this},bringToFront:function(){return this._image&&this._map._panes.overlayPane.appendChild(this._image),this},bringToBack:function(){var t=this._map._panes.overlayPane;return this._image&&t.insertBefore(this._image,t.firstChild),this},setUrl:function(t){this._url=t,this._image.src=this._url},getAttribution:function(){return this.options.attribution},_initImage:function(){this._image=o.DomUtil.create("img","leaflet-image-layer"),this._map.options.zoomAnimation&&o.Browser.any3d?o.DomUtil.addClass(this._image,"leaflet-zoom-animated"):o.DomUtil.addClass(this._image,"leaflet-zoom-hide"),this._updateOpacity(),o.extend(this._image,{galleryimg:"no",onselectstart:o.Util.falseFn,onmousemove:o.Util.falseFn,onload:o.bind(this._onImageLoad,this),src:this._url})},_animateZoom:function(t){var e=this._map,i=this._image,n=e.getZoomScale(t.zoom),s=this._bounds.getNorthWest(),a=this._bounds.getSouthEast(),r=e._latLngToNewLayerPoint(s,t.zoom,t.center),h=e._latLngToNewLayerPoint(a,t.zoom,t.center)._subtract(r),l=r._add(h._multiplyBy(.5*(1-1/n)));i.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(l)+" scale("+n+") "},_reset:function(){var t=this._image,e=this._map.latLngToLayerPoint(this._bounds.getNorthWest()),i=this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(e);o.DomUtil.setPosition(t,e),t.style.width=i.x+"px",t.style.height=i.y+"px"},_onImageLoad:function(){this.fire("load")},_updateOpacity:function(){o.DomUtil.setOpacity(this._image,this.options.opacity)}}),o.imageOverlay=function(t,e,i){return new o.ImageOverlay(t,e,i)},o.Icon=o.Class.extend({options:{className:""},initialize:function(t){o.setOptions(this,t)},createIcon:function(t){return this._createIcon("icon",t)},createShadow:function(t){return this._createIcon("shadow",t)},_createIcon:function(t,e){var i=this._getIconUrl(t);if(!i){if("icon"===t)throw new Error("iconUrl not set in Icon options (see the docs).");return null}var n;return n=e&&"IMG"===e.tagName?this._createImg(i,e):this._createImg(i),this._setIconStyles(n,t),n},_setIconStyles:function(t,e){var i,n=this.options,s=o.point(n[e+"Size"]);i="shadow"===e?o.point(n.shadowAnchor||n.iconAnchor):o.point(n.iconAnchor),!i&&s&&(i=s.divideBy(2,!0)),t.className="leaflet-marker-"+e+" "+n.className,i&&(t.style.marginLeft=-i.x+"px",t.style.marginTop=-i.y+"px"),s&&(t.style.width=s.x+"px",t.style.height=s.y+"px")},_createImg:function(t,i){return i=i||e.createElement("img"),i.src=t,i},_getIconUrl:function(t){return o.Browser.retina&&this.options[t+"RetinaUrl"]?this.options[t+"RetinaUrl"]:this.options[t+"Url"]}}),o.icon=function(t){return new o.Icon(t)},o.Icon.Default=o.Icon.extend({options:{iconSize:[25,41],iconAnchor:[12,41],popupAnchor:[1,-34],shadowSize:[41,41]},_getIconUrl:function(t){var e=t+"Url";if(this.options[e])return this.options[e];o.Browser.retina&&"icon"===t&&(t+="-2x");var i=o.Icon.Default.imagePath;if(!i)throw new Error("Couldn't autodetect L.Icon.Default.imagePath, set it manually.");return i+"/marker-"+t+".png"}}),o.Icon.Default.imagePath=function(){var t,i,n,o,s,a=e.getElementsByTagName("script"),r=/[\/^]leaflet[\-\._]?([\w\-\._]*)\.js\??/;for(t=0,i=a.length;i>t;t++)if(n=a[t].src,o=n.match(r))return s=n.split(r)[0],(s?s+"/":"")+"images"}(),o.Marker=o.Class.extend({includes:o.Mixin.Events,options:{icon:new o.Icon.Default,title:"",alt:"",clickable:!0,draggable:!1,keyboard:!0,zIndexOffset:0,opacity:1,riseOnHover:!1,riseOffset:250},initialize:function(t,e){o.setOptions(this,e),this._latlng=o.latLng(t)},onAdd:function(t){this._map=t,t.on("viewreset",this.update,this),this._initIcon(),this.update(),this.fire("add"),t.options.zoomAnimation&&t.options.markerZoomAnimation&&t.on("zoomanim",this._animateZoom,this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this.dragging&&this.dragging.disable(),this._removeIcon(),this._removeShadow(),this.fire("remove"),t.off({viewreset:this.update,zoomanim:this._animateZoom},this),this._map=null},getLatLng:function(){return this._latlng},setLatLng:function(t){return this._latlng=o.latLng(t),this.update(),this.fire("move",{latlng:this._latlng})},setZIndexOffset:function(t){return this.options.zIndexOffset=t,this.update(),this},setIcon:function(t){return this.options.icon=t,this._map&&(this._initIcon(),this.update()),this._popup&&this.bindPopup(this._popup),this},update:function(){return this._icon&&this._setPos(this._map.latLngToLayerPoint(this._latlng).round()),this},_initIcon:function(){var t=this.options,e=this._map,i=e.options.zoomAnimation&&e.options.markerZoomAnimation,n=i?"leaflet-zoom-animated":"leaflet-zoom-hide",s=t.icon.createIcon(this._icon),a=!1;s!==this._icon&&(this._icon&&this._removeIcon(),a=!0,t.title&&(s.title=t.title),t.alt&&(s.alt=t.alt)),o.DomUtil.addClass(s,n),t.keyboard&&(s.tabIndex="0"),this._icon=s,this._initInteraction(),t.riseOnHover&&o.DomEvent.on(s,"mouseover",this._bringToFront,this).on(s,"mouseout",this._resetZIndex,this);var r=t.icon.createShadow(this._shadow),h=!1;r!==this._shadow&&(this._removeShadow(),h=!0),r&&o.DomUtil.addClass(r,n),this._shadow=r,t.opacity<1&&this._updateOpacity();var l=this._map._panes;a&&l.markerPane.appendChild(this._icon),r&&h&&l.shadowPane.appendChild(this._shadow)},_removeIcon:function(){this.options.riseOnHover&&o.DomEvent.off(this._icon,"mouseover",this._bringToFront).off(this._icon,"mouseout",this._resetZIndex),this._map._panes.markerPane.removeChild(this._icon),this._icon=null},_removeShadow:function(){this._shadow&&this._map._panes.shadowPane.removeChild(this._shadow),this._shadow=null},_setPos:function(t){o.DomUtil.setPosition(this._icon,t),this._shadow&&o.DomUtil.setPosition(this._shadow,t),this._zIndex=t.y+this.options.zIndexOffset,this._resetZIndex()},_updateZIndex:function(t){this._icon.style.zIndex=this._zIndex+t},_animateZoom:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center).round();this._setPos(e)},_initInteraction:function(){if(this.options.clickable){var t=this._icon,e=["dblclick","mousedown","mouseover","mouseout","contextmenu"];o.DomUtil.addClass(t,"leaflet-clickable"),o.DomEvent.on(t,"click",this._onMouseClick,this),o.DomEvent.on(t,"keypress",this._onKeyPress,this);for(var i=0;i<e.length;i++)o.DomEvent.on(t,e[i],this._fireMouseEvent,this);o.Handler.MarkerDrag&&(this.dragging=new o.Handler.MarkerDrag(this),this.options.draggable&&this.dragging.enable())}},_onMouseClick:function(t){var e=this.dragging&&this.dragging.moved();(this.hasEventListeners(t.type)||e)&&o.DomEvent.stopPropagation(t),e||(this.dragging&&this.dragging._enabled||!this._map.dragging||!this._map.dragging.moved())&&this.fire(t.type,{originalEvent:t,latlng:this._latlng})},_onKeyPress:function(t){13===t.keyCode&&this.fire("click",{originalEvent:t,latlng:this._latlng})},_fireMouseEvent:function(t){this.fire(t.type,{originalEvent:t,latlng:this._latlng}),"contextmenu"===t.type&&this.hasEventListeners(t.type)&&o.DomEvent.preventDefault(t),"mousedown"!==t.type?o.DomEvent.stopPropagation(t):o.DomEvent.preventDefault(t)},setOpacity:function(t){return this.options.opacity=t,this._map&&this._updateOpacity(),this},_updateOpacity:function(){o.DomUtil.setOpacity(this._icon,this.options.opacity),this._shadow&&o.DomUtil.setOpacity(this._shadow,this.options.opacity)},_bringToFront:function(){this._updateZIndex(this.options.riseOffset)},_resetZIndex:function(){this._updateZIndex(0)}}),o.marker=function(t,e){return new o.Marker(t,e)},o.DivIcon=o.Icon.extend({options:{iconSize:[12,12],className:"leaflet-div-icon",html:!1},createIcon:function(t){var i=t&&"DIV"===t.tagName?t:e.createElement("div"),n=this.options;return n.html!==!1?i.innerHTML=n.html:i.innerHTML="",n.bgPos&&(i.style.backgroundPosition=-n.bgPos.x+"px "+-n.bgPos.y+"px"),this._setIconStyles(i,"icon"),i},createShadow:function(){return null}}),o.divIcon=function(t){return new o.DivIcon(t)},o.Map.mergeOptions({closePopupOnClick:!0}),o.Popup=o.Class.extend({includes:o.Mixin.Events,options:{minWidth:50,maxWidth:300,autoPan:!0,closeButton:!0,offset:[0,7],autoPanPadding:[5,5],keepInView:!1,className:"",zoomAnimation:!0},initialize:function(t,e){o.setOptions(this,t),this._source=e,this._animated=o.Browser.any3d&&this.options.zoomAnimation,this._isOpen=!1},onAdd:function(t){this._map=t,this._container||this._initLayout();var e=t.options.fadeAnimation;e&&o.DomUtil.setOpacity(this._container,0),t._panes.popupPane.appendChild(this._container),t.on(this._getEvents(),this),this.update(),e&&o.DomUtil.setOpacity(this._container,1),this.fire("open"),t.fire("popupopen",{popup:this}),this._source&&this._source.fire("popupopen",{popup:this})},addTo:function(t){return t.addLayer(this),this},openOn:function(t){return t.openPopup(this),this},onRemove:function(t){t._panes.popupPane.removeChild(this._container),o.Util.falseFn(this._container.offsetWidth),t.off(this._getEvents(),this),t.options.fadeAnimation&&o.DomUtil.setOpacity(this._container,0),this._map=null,this.fire("close"),t.fire("popupclose",{popup:this}),this._source&&this._source.fire("popupclose",{popup:this})},getLatLng:function(){return this._latlng},setLatLng:function(t){return this._latlng=o.latLng(t),this._map&&(this._updatePosition(),this._adjustPan()),this},getContent:function(){return this._content},setContent:function(t){return this._content=t,this.update(),this},update:function(){this._map&&(this._container.style.visibility="hidden",this._updateContent(),this._updateLayout(),this._updatePosition(),this._container.style.visibility="",this._adjustPan())},_getEvents:function(){var t={viewreset:this._updatePosition};return this._animated&&(t.zoomanim=this._zoomAnimation),("closeOnClick"in this.options?this.options.closeOnClick:this._map.options.closePopupOnClick)&&(t.preclick=this._close),this.options.keepInView&&(t.moveend=this._adjustPan),t},_close:function(){this._map&&this._map.closePopup(this)},_initLayout:function(){var t,e="leaflet-popup",i=e+" "+this.options.className+" leaflet-zoom-"+(this._animated?"animated":"hide"),n=this._container=o.DomUtil.create("div",i);this.options.closeButton&&(t=this._closeButton=o.DomUtil.create("a",e+"-close-button",n),t.href="#close",t.innerHTML="×",o.DomEvent.disableClickPropagation(t),o.DomEvent.on(t,"click",this._onCloseButtonClick,this));var s=this._wrapper=o.DomUtil.create("div",e+"-content-wrapper",n);o.DomEvent.disableClickPropagation(s),this._contentNode=o.DomUtil.create("div",e+"-content",s),o.DomEvent.disableScrollPropagation(this._contentNode),o.DomEvent.on(s,"contextmenu",o.DomEvent.stopPropagation),this._tipContainer=o.DomUtil.create("div",e+"-tip-container",n),this._tip=o.DomUtil.create("div",e+"-tip",this._tipContainer)},_updateContent:function(){if(this._content){if("string"==typeof this._content)this._contentNode.innerHTML=this._content;else{for(;this._contentNode.hasChildNodes();)this._contentNode.removeChild(this._contentNode.firstChild);this._contentNode.appendChild(this._content)}this.fire("contentupdate")}},_updateLayout:function(){var t=this._contentNode,e=t.style;e.width="",e.whiteSpace="nowrap";var i=t.offsetWidth;i=Math.min(i,this.options.maxWidth),i=Math.max(i,this.options.minWidth),e.width=i+1+"px",e.whiteSpace="",e.height="";var n=t.offsetHeight,s=this.options.maxHeight,a="leaflet-popup-scrolled";s&&n>s?(e.height=s+"px",o.DomUtil.addClass(t,a)):o.DomUtil.removeClass(t,a),this._containerWidth=this._container.offsetWidth},_updatePosition:function(){if(this._map){var t=this._map.latLngToLayerPoint(this._latlng),e=this._animated,i=o.point(this.options.offset);e&&o.DomUtil.setPosition(this._container,t),this._containerBottom=-i.y-(e?0:t.y),this._containerLeft=-Math.round(this._containerWidth/2)+i.x+(e?0:t.x),this._container.style.bottom=this._containerBottom+"px",this._container.style.left=this._containerLeft+"px"}},_zoomAnimation:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center);o.DomUtil.setPosition(this._container,e)},_adjustPan:function(){if(this.options.autoPan){var t=this._map,e=this._container.offsetHeight,i=this._containerWidth,n=new o.Point(this._containerLeft,-e-this._containerBottom);this._animated&&n._add(o.DomUtil.getPosition(this._container));var s=t.layerPointToContainerPoint(n),a=o.point(this.options.autoPanPadding),r=o.point(this.options.autoPanPaddingTopLeft||a),h=o.point(this.options.autoPanPaddingBottomRight||a),l=t.getSize(),u=0,c=0;s.x+i+h.x>l.x&&(u=s.x+i-l.x+h.x),s.x-u-r.x<0&&(u=s.x-r.x),s.y+e+h.y>l.y&&(c=s.y+e-l.y+h.y),s.y-c-r.y<0&&(c=s.y-r.y),(u||c)&&t.fire("autopanstart").panBy([u,c])}},_onCloseButtonClick:function(t){this._close(),o.DomEvent.stop(t)}}),o.popup=function(t,e){return new o.Popup(t,e)},o.Map.include({openPopup:function(t,e,i){if(this.closePopup(),!(t instanceof o.Popup)){var n=t;t=new o.Popup(i).setLatLng(e).setContent(n)}return t._isOpen=!0,this._popup=t,this.addLayer(t)},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&(this.removeLayer(t),t._isOpen=!1),this}}),o.Marker.include({openPopup:function(){return this._popup&&this._map&&!this._map.hasLayer(this._popup)&&(this._popup.setLatLng(this._latlng),this._map.openPopup(this._popup)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(){return this._popup&&(this._popup._isOpen?this.closePopup():this.openPopup()),this},bindPopup:function(t,e){var i=o.point(this.options.icon.options.popupAnchor||[0,0]);return i=i.add(o.Popup.prototype.options.offset),e&&e.offset&&(i=i.add(e.offset)),e=o.extend({offset:i},e),this._popupHandlersAdded||(this.on("click",this.togglePopup,this).on("remove",this.closePopup,this).on("move",this._movePopup,this),this._popupHandlersAdded=!0),t instanceof o.Popup?(o.setOptions(t,e),this._popup=t,t._source=this):this._popup=new o.Popup(e,this).setContent(t),this},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this.togglePopup,this).off("remove",this.closePopup,this).off("move",this._movePopup,this),this._popupHandlersAdded=!1),this},getPopup:function(){return this._popup},_movePopup:function(t){this._popup.setLatLng(t.latlng)}}),o.LayerGroup=o.Class.extend({initialize:function(t){this._layers={};var e,i;if(t)for(e=0,i=t.length;i>e;e++)this.addLayer(t[e])},addLayer:function(t){var e=this.getLayerId(t);return this._layers[e]=t,this._map&&this._map.addLayer(t),this},removeLayer:function(t){var e=t in this._layers?t:this.getLayerId(t);return this._map&&this._layers[e]&&this._map.removeLayer(this._layers[e]),delete this._layers[e],this},hasLayer:function(t){return t?t in this._layers||this.getLayerId(t)in this._layers:!1},clearLayers:function(){return this.eachLayer(this.removeLayer,this),this},invoke:function(t){var e,i,n=Array.prototype.slice.call(arguments,1);for(e in this._layers)i=this._layers[e],i[t]&&i[t].apply(i,n);return this},onAdd:function(t){this._map=t,this.eachLayer(t.addLayer,t)},onRemove:function(t){this.eachLayer(t.removeLayer,t),this._map=null},addTo:function(t){return t.addLayer(this),this},eachLayer:function(t,e){for(var i in this._layers)t.call(e,this._layers[i]);return this},getLayer:function(t){return this._layers[t]},getLayers:function(){var t=[];for(var e in this._layers)t.push(this._layers[e]);return t},setZIndex:function(t){return this.invoke("setZIndex",t)},getLayerId:function(t){return o.stamp(t)}}),o.layerGroup=function(t){return new o.LayerGroup(t)},o.FeatureGroup=o.LayerGroup.extend({includes:o.Mixin.Events,statics:{EVENTS:"click dblclick mouseover mouseout mousemove contextmenu popupopen popupclose"},addLayer:function(t){return this.hasLayer(t)?this:("on"in t&&t.on(o.FeatureGroup.EVENTS,this._propagateEvent,this),o.LayerGroup.prototype.addLayer.call(this,t),this._popupContent&&t.bindPopup&&t.bindPopup(this._popupContent,this._popupOptions),this.fire("layeradd",{layer:t}))},removeLayer:function(t){return this.hasLayer(t)?(t in this._layers&&(t=this._layers[t]),"off"in t&&t.off(o.FeatureGroup.EVENTS,this._propagateEvent,this),o.LayerGroup.prototype.removeLayer.call(this,t),this._popupContent&&this.invoke("unbindPopup"),this.fire("layerremove",{layer:t})):this},bindPopup:function(t,e){return this._popupContent=t,this._popupOptions=e,this.invoke("bindPopup",t,e)},openPopup:function(t){for(var e in this._layers){this._layers[e].openPopup(t);break}return this},setStyle:function(t){return this.invoke("setStyle",t)},bringToFront:function(){return this.invoke("bringToFront")},bringToBack:function(){return this.invoke("bringToBack")},getBounds:function(){var t=new o.LatLngBounds;return this.eachLayer(function(e){t.extend(e instanceof o.Marker?e.getLatLng():e.getBounds())}),t},_propagateEvent:function(t){t=o.extend({layer:t.target,target:this},t),this.fire(t.type,t)}}),o.featureGroup=function(t){return new o.FeatureGroup(t)},o.Path=o.Class.extend({includes:[o.Mixin.Events],statics:{CLIP_PADDING:function(){var e=o.Browser.mobile?1280:2e3,i=(e/Math.max(t.outerWidth,t.outerHeight)-1)/2;return Math.max(0,Math.min(.5,i))}()},options:{stroke:!0,color:"#0033ff",dashArray:null,lineCap:null,lineJoin:null,weight:5,opacity:.5,fill:!1,fillColor:null,fillOpacity:.2,clickable:!0},initialize:function(t){o.setOptions(this,t)},onAdd:function(t){this._map=t,this._container||(this._initElements(),this._initEvents()),this.projectLatlngs(),this._updatePath(),this._container&&this._map._pathRoot.appendChild(this._container),this.fire("add"),t.on({viewreset:this.projectLatlngs,moveend:this._updatePath},this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){t._pathRoot.removeChild(this._container),this.fire("remove"),this._map=null,o.Browser.vml&&(this._container=null,this._stroke=null,this._fill=null),t.off({viewreset:this.projectLatlngs,moveend:this._updatePath},this)},projectLatlngs:function(){},setStyle:function(t){return o.setOptions(this,t),this._container&&this._updateStyle(),this},redraw:function(){return this._map&&(this.projectLatlngs(),this._updatePath()),this}}),o.Map.include({_updatePathViewport:function(){var t=o.Path.CLIP_PADDING,e=this.getSize(),i=o.DomUtil.getPosition(this._mapPane),n=i.multiplyBy(-1)._subtract(e.multiplyBy(t)._round()),s=n.add(e.multiplyBy(1+2*t)._round());this._pathViewport=new o.Bounds(n,s)}}),o.Path.SVG_NS="http://www.w3.org/2000/svg",o.Browser.svg=!(!e.createElementNS||!e.createElementNS(o.Path.SVG_NS,"svg").createSVGRect),o.Path=o.Path.extend({statics:{SVG:o.Browser.svg},bringToFront:function(){var t=this._map._pathRoot,e=this._container;return e&&t.lastChild!==e&&t.appendChild(e),this},bringToBack:function(){var t=this._map._pathRoot,e=this._container,i=t.firstChild;return e&&i!==e&&t.insertBefore(e,i),this},getPathString:function(){},_createElement:function(t){return e.createElementNS(o.Path.SVG_NS,t)},_initElements:function(){this._map._initPathRoot(),this._initPath(),this._initStyle()},_initPath:function(){this._container=this._createElement("g"),this._path=this._createElement("path"),this.options.className&&o.DomUtil.addClass(this._path,this.options.className),this._container.appendChild(this._path)},_initStyle:function(){this.options.stroke&&(this._path.setAttribute("stroke-linejoin","round"),this._path.setAttribute("stroke-linecap","round")),this.options.fill&&this._path.setAttribute("fill-rule","evenodd"),this.options.pointerEvents&&this._path.setAttribute("pointer-events",this.options.pointerEvents),this.options.clickable||this.options.pointerEvents||this._path.setAttribute("pointer-events","none"),this._updateStyle()},_updateStyle:function(){this.options.stroke?(this._path.setAttribute("stroke",this.options.color),this._path.setAttribute("stroke-opacity",this.options.opacity),this._path.setAttribute("stroke-width",this.options.weight),this.options.dashArray?this._path.setAttribute("stroke-dasharray",this.options.dashArray):this._path.removeAttribute("stroke-dasharray"),this.options.lineCap&&this._path.setAttribute("stroke-linecap",this.options.lineCap),this.options.lineJoin&&this._path.setAttribute("stroke-linejoin",this.options.lineJoin)):this._path.setAttribute("stroke","none"),this.options.fill?(this._path.setAttribute("fill",this.options.fillColor||this.options.color),this._path.setAttribute("fill-opacity",this.options.fillOpacity)):this._path.setAttribute("fill","none")},_updatePath:function(){var t=this.getPathString();t||(t="M0 0"),this._path.setAttribute("d",t)},_initEvents:function(){if(this.options.clickable){(o.Browser.svg||!o.Browser.vml)&&o.DomUtil.addClass(this._path,"leaflet-clickable"),o.DomEvent.on(this._container,"click",this._onMouseClick,this);for(var t=["dblclick","mousedown","mouseover","mouseout","mousemove","contextmenu"],e=0;e<t.length;e++)o.DomEvent.on(this._container,t[e],this._fireMouseEvent,this)}},_onMouseClick:function(t){this._map.dragging&&this._map.dragging.moved()||this._fireMouseEvent(t)},_fireMouseEvent:function(t){if(this._map&&this.hasEventListeners(t.type)){var e=this._map,i=e.mouseEventToContainerPoint(t),n=e.containerPointToLayerPoint(i),s=e.layerPointToLatLng(n);this.fire(t.type,{latlng:s,layerPoint:n,containerPoint:i,originalEvent:t}),"contextmenu"===t.type&&o.DomEvent.preventDefault(t),"mousemove"!==t.type&&o.DomEvent.stopPropagation(t)}}}),o.Map.include({_initPathRoot:function(){this._pathRoot||(this._pathRoot=o.Path.prototype._createElement("svg"),this._panes.overlayPane.appendChild(this._pathRoot),this.options.zoomAnimation&&o.Browser.any3d?(o.DomUtil.addClass(this._pathRoot,"leaflet-zoom-animated"), -this.on({zoomanim:this._animatePathZoom,zoomend:this._endPathZoom})):o.DomUtil.addClass(this._pathRoot,"leaflet-zoom-hide"),this.on("moveend",this._updateSvgViewport),this._updateSvgViewport())},_animatePathZoom:function(t){var e=this.getZoomScale(t.zoom),i=this._getCenterOffset(t.center)._multiplyBy(-e)._add(this._pathViewport.min);this._pathRoot.style[o.DomUtil.TRANSFORM]=o.DomUtil.getTranslateString(i)+" scale("+e+") ",this._pathZooming=!0},_endPathZoom:function(){this._pathZooming=!1},_updateSvgViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max,n=i.x-e.x,s=i.y-e.y,a=this._pathRoot,r=this._panes.overlayPane;o.Browser.mobileWebkit&&r.removeChild(a),o.DomUtil.setPosition(a,e),a.setAttribute("width",n),a.setAttribute("height",s),a.setAttribute("viewBox",[e.x,e.y,n,s].join(" ")),o.Browser.mobileWebkit&&r.appendChild(a)}}}),o.Path.include({bindPopup:function(t,e){return t instanceof o.Popup?this._popup=t:((!this._popup||e)&&(this._popup=new o.Popup(e,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on("click",this._openPopup,this).on("remove",this.closePopup,this),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this._openPopup).off("remove",this.closePopup),this._popupHandlersAdded=!1),this},openPopup:function(t){return this._popup&&(t=t||this._latlng||this._latlngs[Math.floor(this._latlngs.length/2)],this._openPopup({latlng:t})),this},closePopup:function(){return this._popup&&this._popup._close(),this},_openPopup:function(t){this._popup.setLatLng(t.latlng),this._map.openPopup(this._popup)}}),o.Browser.vml=!o.Browser.svg&&function(){try{var t=e.createElement("div");t.innerHTML='<v:shape adj="1"/>';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(n){return!1}}(),o.Path=o.Browser.svg||!o.Browser.vml?o.Path:o.Path.extend({statics:{VML:!0,CLIP_PADDING:.02},_createElement:function(){try{return e.namespaces.add("lvml","urn:schemas-microsoft-com:vml"),function(t){return e.createElement("<lvml:"+t+' class="lvml">')}}catch(t){return function(t){return e.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),_initPath:function(){var t=this._container=this._createElement("shape");o.DomUtil.addClass(t,"leaflet-vml-shape"+(this.options.className?" "+this.options.className:"")),this.options.clickable&&o.DomUtil.addClass(t,"leaflet-clickable"),t.coordsize="1 1",this._path=this._createElement("path"),t.appendChild(this._path),this._map._pathRoot.appendChild(t)},_initStyle:function(){this._updateStyle()},_updateStyle:function(){var t=this._stroke,e=this._fill,i=this.options,n=this._container;n.stroked=i.stroke,n.filled=i.fill,i.stroke?(t||(t=this._stroke=this._createElement("stroke"),t.endcap="round",n.appendChild(t)),t.weight=i.weight+"px",t.color=i.color,t.opacity=i.opacity,i.dashArray?t.dashStyle=o.Util.isArray(i.dashArray)?i.dashArray.join(" "):i.dashArray.replace(/( *, *)/g," "):t.dashStyle="",i.lineCap&&(t.endcap=i.lineCap.replace("butt","flat")),i.lineJoin&&(t.joinstyle=i.lineJoin)):t&&(n.removeChild(t),this._stroke=null),i.fill?(e||(e=this._fill=this._createElement("fill"),n.appendChild(e)),e.color=i.fillColor||i.color,e.opacity=i.fillOpacity):e&&(n.removeChild(e),this._fill=null)},_updatePath:function(){var t=this._container.style;t.display="none",this._path.v=this.getPathString()+" ",t.display=""}}),o.Map.include(o.Browser.svg||!o.Browser.vml?{}:{_initPathRoot:function(){if(!this._pathRoot){var t=this._pathRoot=e.createElement("div");t.className="leaflet-vml-container",this._panes.overlayPane.appendChild(t),this.on("moveend",this._updatePathViewport),this._updatePathViewport()}}}),o.Browser.canvas=function(){return!!e.createElement("canvas").getContext}(),o.Path=o.Path.SVG&&!t.L_PREFER_CANVAS||!o.Browser.canvas?o.Path:o.Path.extend({statics:{CANVAS:!0,SVG:!1},redraw:function(){return this._map&&(this.projectLatlngs(),this._requestUpdate()),this},setStyle:function(t){return o.setOptions(this,t),this._map&&(this._updateStyle(),this._requestUpdate()),this},onRemove:function(t){t.off("viewreset",this.projectLatlngs,this).off("moveend",this._updatePath,this),this.options.clickable&&(this._map.off("click",this._onClick,this),this._map.off("mousemove",this._onMouseMove,this)),this._requestUpdate(),this.fire("remove"),this._map=null},_requestUpdate:function(){this._map&&!o.Path._updateRequest&&(o.Path._updateRequest=o.Util.requestAnimFrame(this._fireMapMoveEnd,this._map))},_fireMapMoveEnd:function(){o.Path._updateRequest=null,this.fire("moveend")},_initElements:function(){this._map._initPathRoot(),this._ctx=this._map._canvasCtx},_updateStyle:function(){var t=this.options;t.stroke&&(this._ctx.lineWidth=t.weight,this._ctx.strokeStyle=t.color),t.fill&&(this._ctx.fillStyle=t.fillColor||t.color),t.lineCap&&(this._ctx.lineCap=t.lineCap),t.lineJoin&&(this._ctx.lineJoin=t.lineJoin)},_drawPath:function(){var t,e,i,n,s,a;for(this._ctx.beginPath(),t=0,i=this._parts.length;i>t;t++){for(e=0,n=this._parts[t].length;n>e;e++)s=this._parts[t][e],a=(0===e?"move":"line")+"To",this._ctx[a](s.x,s.y);this instanceof o.Polygon&&this._ctx.closePath()}},_checkIfEmpty:function(){return!this._parts.length},_updatePath:function(){if(!this._checkIfEmpty()){var t=this._ctx,e=this.options;this._drawPath(),t.save(),this._updateStyle(),e.fill&&(t.globalAlpha=e.fillOpacity,t.fill(e.fillRule||"evenodd")),e.stroke&&(t.globalAlpha=e.opacity,t.stroke()),t.restore()}},_initEvents:function(){this.options.clickable&&(this._map.on("mousemove",this._onMouseMove,this),this._map.on("click dblclick contextmenu",this._fireMouseEvent,this))},_fireMouseEvent:function(t){this._containsPoint(t.layerPoint)&&this.fire(t.type,t)},_onMouseMove:function(t){this._map&&!this._map._animatingZoom&&(this._containsPoint(t.layerPoint)?(this._ctx.canvas.style.cursor="pointer",this._mouseInside=!0,this.fire("mouseover",t)):this._mouseInside&&(this._ctx.canvas.style.cursor="",this._mouseInside=!1,this.fire("mouseout",t)))}}),o.Map.include(o.Path.SVG&&!t.L_PREFER_CANVAS||!o.Browser.canvas?{}:{_initPathRoot:function(){var t,i=this._pathRoot;i||(i=this._pathRoot=e.createElement("canvas"),i.style.position="absolute",t=this._canvasCtx=i.getContext("2d"),t.lineCap="round",t.lineJoin="round",this._panes.overlayPane.appendChild(i),this.options.zoomAnimation&&(this._pathRoot.className="leaflet-zoom-animated",this.on("zoomanim",this._animatePathZoom),this.on("zoomend",this._endPathZoom)),this.on("moveend",this._updateCanvasViewport),this._updateCanvasViewport())},_updateCanvasViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max.subtract(e),n=this._pathRoot;o.DomUtil.setPosition(n,e),n.width=i.x,n.height=i.y,n.getContext("2d").translate(-e.x,-e.y)}}}),o.LineUtil={simplify:function(t,e){if(!e||!t.length)return t.slice();var i=e*e;return t=this._reducePoints(t,i),t=this._simplifyDP(t,i)},pointToSegmentDistance:function(t,e,i){return Math.sqrt(this._sqClosestPointOnSegment(t,e,i,!0))},closestPointOnSegment:function(t,e,i){return this._sqClosestPointOnSegment(t,e,i)},_simplifyDP:function(t,e){var n=t.length,o=typeof Uint8Array!=i+""?Uint8Array:Array,s=new o(n);s[0]=s[n-1]=1,this._simplifyDPStep(t,s,e,0,n-1);var a,r=[];for(a=0;n>a;a++)s[a]&&r.push(t[a]);return r},_simplifyDPStep:function(t,e,i,n,o){var s,a,r,h=0;for(a=n+1;o-1>=a;a++)r=this._sqClosestPointOnSegment(t[a],t[n],t[o],!0),r>h&&(s=a,h=r);h>i&&(e[s]=1,this._simplifyDPStep(t,e,i,n,s),this._simplifyDPStep(t,e,i,s,o))},_reducePoints:function(t,e){for(var i=[t[0]],n=1,o=0,s=t.length;s>n;n++)this._sqDist(t[n],t[o])>e&&(i.push(t[n]),o=n);return s-1>o&&i.push(t[s-1]),i},clipSegment:function(t,e,i,n){var o,s,a,r=n?this._lastCode:this._getBitCode(t,i),h=this._getBitCode(e,i);for(this._lastCode=h;;){if(!(r|h))return[t,e];if(r&h)return!1;o=r||h,s=this._getEdgeIntersection(t,e,o,i),a=this._getBitCode(s,i),o===r?(t=s,r=a):(e=s,h=a)}},_getEdgeIntersection:function(t,e,i,n){var s=e.x-t.x,a=e.y-t.y,r=n.min,h=n.max;return 8&i?new o.Point(t.x+s*(h.y-t.y)/a,h.y):4&i?new o.Point(t.x+s*(r.y-t.y)/a,r.y):2&i?new o.Point(h.x,t.y+a*(h.x-t.x)/s):1&i?new o.Point(r.x,t.y+a*(r.x-t.x)/s):void 0},_getBitCode:function(t,e){var i=0;return t.x<e.min.x?i|=1:t.x>e.max.x&&(i|=2),t.y<e.min.y?i|=4:t.y>e.max.y&&(i|=8),i},_sqDist:function(t,e){var i=e.x-t.x,n=e.y-t.y;return i*i+n*n},_sqClosestPointOnSegment:function(t,e,i,n){var s,a=e.x,r=e.y,h=i.x-a,l=i.y-r,u=h*h+l*l;return u>0&&(s=((t.x-a)*h+(t.y-r)*l)/u,s>1?(a=i.x,r=i.y):s>0&&(a+=h*s,r+=l*s)),h=t.x-a,l=t.y-r,n?h*h+l*l:new o.Point(a,r)}},o.Polyline=o.Path.extend({initialize:function(t,e){o.Path.prototype.initialize.call(this,e),this._latlngs=this._convertLatLngs(t)},options:{smoothFactor:1,noClip:!1},projectLatlngs:function(){this._originalPoints=[];for(var t=0,e=this._latlngs.length;e>t;t++)this._originalPoints[t]=this._map.latLngToLayerPoint(this._latlngs[t])},getPathString:function(){for(var t=0,e=this._parts.length,i="";e>t;t++)i+=this._getPathPartStr(this._parts[t]);return i},getLatLngs:function(){return this._latlngs},setLatLngs:function(t){return this._latlngs=this._convertLatLngs(t),this.redraw()},addLatLng:function(t){return this._latlngs.push(o.latLng(t)),this.redraw()},spliceLatLngs:function(){var t=[].splice.apply(this._latlngs,arguments);return this._convertLatLngs(this._latlngs,!0),this.redraw(),t},closestLayerPoint:function(t){for(var e,i,n=1/0,s=this._parts,a=null,r=0,h=s.length;h>r;r++)for(var l=s[r],u=1,c=l.length;c>u;u++){e=l[u-1],i=l[u];var d=o.LineUtil._sqClosestPointOnSegment(t,e,i,!0);n>d&&(n=d,a=o.LineUtil._sqClosestPointOnSegment(t,e,i))}return a&&(a.distance=Math.sqrt(n)),a},getBounds:function(){return new o.LatLngBounds(this.getLatLngs())},_convertLatLngs:function(t,e){var i,n,s=e?t:[];for(i=0,n=t.length;n>i;i++){if(o.Util.isArray(t[i])&&"number"!=typeof t[i][0])return;s[i]=o.latLng(t[i])}return s},_initEvents:function(){o.Path.prototype._initEvents.call(this)},_getPathPartStr:function(t){for(var e,i=o.Path.VML,n=0,s=t.length,a="";s>n;n++)e=t[n],i&&e._round(),a+=(n?"L":"M")+e.x+" "+e.y;return a},_clipPoints:function(){var t,e,i,n=this._originalPoints,s=n.length;if(this.options.noClip)return void(this._parts=[n]);this._parts=[];var a=this._parts,r=this._map._pathViewport,h=o.LineUtil;for(t=0,e=0;s-1>t;t++)i=h.clipSegment(n[t],n[t+1],r,t),i&&(a[e]=a[e]||[],a[e].push(i[0]),(i[1]!==n[t+1]||t===s-2)&&(a[e].push(i[1]),e++))},_simplifyPoints:function(){for(var t=this._parts,e=o.LineUtil,i=0,n=t.length;n>i;i++)t[i]=e.simplify(t[i],this.options.smoothFactor)},_updatePath:function(){this._map&&(this._clipPoints(),this._simplifyPoints(),o.Path.prototype._updatePath.call(this))}}),o.polyline=function(t,e){return new o.Polyline(t,e)},o.PolyUtil={},o.PolyUtil.clipPolygon=function(t,e){var i,n,s,a,r,h,l,u,c,d=[1,4,2,8],p=o.LineUtil;for(n=0,l=t.length;l>n;n++)t[n]._code=p._getBitCode(t[n],e);for(a=0;4>a;a++){for(u=d[a],i=[],n=0,l=t.length,s=l-1;l>n;s=n++)r=t[n],h=t[s],r._code&u?h._code&u||(c=p._getEdgeIntersection(h,r,u,e),c._code=p._getBitCode(c,e),i.push(c)):(h._code&u&&(c=p._getEdgeIntersection(h,r,u,e),c._code=p._getBitCode(c,e),i.push(c)),i.push(r));t=i}return t},o.Polygon=o.Polyline.extend({options:{fill:!0},initialize:function(t,e){o.Polyline.prototype.initialize.call(this,t,e),this._initWithHoles(t)},_initWithHoles:function(t){var e,i,n;if(t&&o.Util.isArray(t[0])&&"number"!=typeof t[0][0])for(this._latlngs=this._convertLatLngs(t[0]),this._holes=t.slice(1),e=0,i=this._holes.length;i>e;e++)n=this._holes[e]=this._convertLatLngs(this._holes[e]),n[0].equals(n[n.length-1])&&n.pop();t=this._latlngs,t.length>=2&&t[0].equals(t[t.length-1])&&t.pop()},projectLatlngs:function(){if(o.Polyline.prototype.projectLatlngs.call(this),this._holePoints=[],this._holes){var t,e,i,n;for(t=0,i=this._holes.length;i>t;t++)for(this._holePoints[t]=[],e=0,n=this._holes[t].length;n>e;e++)this._holePoints[t][e]=this._map.latLngToLayerPoint(this._holes[t][e])}},setLatLngs:function(t){return t&&o.Util.isArray(t[0])&&"number"!=typeof t[0][0]?(this._initWithHoles(t),this.redraw()):o.Polyline.prototype.setLatLngs.call(this,t)},_clipPoints:function(){var t=this._originalPoints,e=[];if(this._parts=[t].concat(this._holePoints),!this.options.noClip){for(var i=0,n=this._parts.length;n>i;i++){var s=o.PolyUtil.clipPolygon(this._parts[i],this._map._pathViewport);s.length&&e.push(s)}this._parts=e}},_getPathPartStr:function(t){var e=o.Polyline.prototype._getPathPartStr.call(this,t);return e+(o.Browser.svg?"z":"x")}}),o.polygon=function(t,e){return new o.Polygon(t,e)},function(){function t(t){return o.FeatureGroup.extend({initialize:function(t,e){this._layers={},this._options=e,this.setLatLngs(t)},setLatLngs:function(e){var i=0,n=e.length;for(this.eachLayer(function(t){n>i?t.setLatLngs(e[i++]):this.removeLayer(t)},this);n>i;)this.addLayer(new t(e[i++],this._options));return this},getLatLngs:function(){var t=[];return this.eachLayer(function(e){t.push(e.getLatLngs())}),t}})}o.MultiPolyline=t(o.Polyline),o.MultiPolygon=t(o.Polygon),o.multiPolyline=function(t,e){return new o.MultiPolyline(t,e)},o.multiPolygon=function(t,e){return new o.MultiPolygon(t,e)}}(),o.Rectangle=o.Polygon.extend({initialize:function(t,e){o.Polygon.prototype.initialize.call(this,this._boundsToLatLngs(t),e)},setBounds:function(t){this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=o.latLngBounds(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}}),o.rectangle=function(t,e){return new o.Rectangle(t,e)},o.Circle=o.Path.extend({initialize:function(t,e,i){o.Path.prototype.initialize.call(this,i),this._latlng=o.latLng(t),this._mRadius=e},options:{fill:!0},setLatLng:function(t){return this._latlng=o.latLng(t),this.redraw()},setRadius:function(t){return this._mRadius=t,this.redraw()},projectLatlngs:function(){var t=this._getLngRadius(),e=this._latlng,i=this._map.latLngToLayerPoint([e.lat,e.lng-t]);this._point=this._map.latLngToLayerPoint(e),this._radius=Math.max(this._point.x-i.x,1)},getBounds:function(){var t=this._getLngRadius(),e=this._mRadius/40075017*360,i=this._latlng;return new o.LatLngBounds([i.lat-e,i.lng-t],[i.lat+e,i.lng+t])},getLatLng:function(){return this._latlng},getPathString:function(){var t=this._point,e=this._radius;return this._checkIfEmpty()?"":o.Browser.svg?"M"+t.x+","+(t.y-e)+"A"+e+","+e+",0,1,1,"+(t.x-.1)+","+(t.y-e)+" z":(t._round(),e=Math.round(e),"AL "+t.x+","+t.y+" "+e+","+e+" 0,23592600")},getRadius:function(){return this._mRadius},_getLatRadius:function(){return this._mRadius/40075017*360},_getLngRadius:function(){return this._getLatRadius()/Math.cos(o.LatLng.DEG_TO_RAD*this._latlng.lat)},_checkIfEmpty:function(){if(!this._map)return!1;var t=this._map._pathViewport,e=this._radius,i=this._point;return i.x-e>t.max.x||i.y-e>t.max.y||i.x+e<t.min.x||i.y+e<t.min.y}}),o.circle=function(t,e,i){return new o.Circle(t,e,i)},o.CircleMarker=o.Circle.extend({options:{radius:10,weight:2},initialize:function(t,e){o.Circle.prototype.initialize.call(this,t,null,e),this._radius=this.options.radius},projectLatlngs:function(){this._point=this._map.latLngToLayerPoint(this._latlng)},_updateStyle:function(){o.Circle.prototype._updateStyle.call(this),this.setRadius(this.options.radius)},setLatLng:function(t){return o.Circle.prototype.setLatLng.call(this,t),this._popup&&this._popup._isOpen&&this._popup.setLatLng(t),this},setRadius:function(t){return this.options.radius=this._radius=t,this.redraw()},getRadius:function(){return this._radius}}),o.circleMarker=function(t,e){return new o.CircleMarker(t,e)},o.Polyline.include(o.Path.CANVAS?{_containsPoint:function(t,e){var i,n,s,a,r,h,l,u=this.options.weight/2;for(o.Browser.touch&&(u+=10),i=0,a=this._parts.length;a>i;i++)for(l=this._parts[i],n=0,r=l.length,s=r-1;r>n;s=n++)if((e||0!==n)&&(h=o.LineUtil.pointToSegmentDistance(t,l[s],l[n]),u>=h))return!0;return!1}}:{}),o.Polygon.include(o.Path.CANVAS?{_containsPoint:function(t){var e,i,n,s,a,r,h,l,u=!1;if(o.Polyline.prototype._containsPoint.call(this,t,!0))return!0;for(s=0,h=this._parts.length;h>s;s++)for(e=this._parts[s],a=0,l=e.length,r=l-1;l>a;r=a++)i=e[a],n=e[r],i.y>t.y!=n.y>t.y&&t.x<(n.x-i.x)*(t.y-i.y)/(n.y-i.y)+i.x&&(u=!u);return u}}:{}),o.Circle.include(o.Path.CANVAS?{_drawPath:function(){var t=this._point;this._ctx.beginPath(),this._ctx.arc(t.x,t.y,this._radius,0,2*Math.PI,!1)},_containsPoint:function(t){var e=this._point,i=this.options.stroke?this.options.weight/2:0;return t.distanceTo(e)<=this._radius+i}}:{}),o.CircleMarker.include(o.Path.CANVAS?{_updateStyle:function(){o.Path.prototype._updateStyle.call(this)}}:{}),o.GeoJSON=o.FeatureGroup.extend({initialize:function(t,e){o.setOptions(this,e),this._layers={},t&&this.addData(t)},addData:function(t){var e,i,n,s=o.Util.isArray(t)?t:t.features;if(s){for(e=0,i=s.length;i>e;e++)n=s[e],(n.geometries||n.geometry||n.features||n.coordinates)&&this.addData(s[e]);return this}var a=this.options;if(!a.filter||a.filter(t)){var r=o.GeoJSON.geometryToLayer(t,a.pointToLayer,a.coordsToLatLng,a);return r.feature=o.GeoJSON.asFeature(t),r.defaultOptions=r.options,this.resetStyle(r),a.onEachFeature&&a.onEachFeature(t,r),this.addLayer(r)}},resetStyle:function(t){var e=this.options.style;e&&(o.Util.extend(t.options,t.defaultOptions),this._setLayerStyle(t,e))},setStyle:function(t){this.eachLayer(function(e){this._setLayerStyle(e,t)},this)},_setLayerStyle:function(t,e){"function"==typeof e&&(e=e(t.feature)),t.setStyle&&t.setStyle(e)}}),o.extend(o.GeoJSON,{geometryToLayer:function(t,e,i,n){var s,a,r,h,l="Feature"===t.type?t.geometry:t,u=l.coordinates,c=[];switch(i=i||this.coordsToLatLng,l.type){case"Point":return s=i(u),e?e(t,s):new o.Marker(s);case"MultiPoint":for(r=0,h=u.length;h>r;r++)s=i(u[r]),c.push(e?e(t,s):new o.Marker(s));return new o.FeatureGroup(c);case"LineString":return a=this.coordsToLatLngs(u,0,i),new o.Polyline(a,n);case"Polygon":if(2===u.length&&!u[1].length)throw new Error("Invalid GeoJSON object.");return a=this.coordsToLatLngs(u,1,i),new o.Polygon(a,n);case"MultiLineString":return a=this.coordsToLatLngs(u,1,i),new o.MultiPolyline(a,n);case"MultiPolygon":return a=this.coordsToLatLngs(u,2,i),new o.MultiPolygon(a,n);case"GeometryCollection":for(r=0,h=l.geometries.length;h>r;r++)c.push(this.geometryToLayer({geometry:l.geometries[r],type:"Feature",properties:t.properties},e,i,n));return new o.FeatureGroup(c);default:throw new Error("Invalid GeoJSON object.")}},coordsToLatLng:function(t){return new o.LatLng(t[1],t[0],t[2])},coordsToLatLngs:function(t,e,i){var n,o,s,a=[];for(o=0,s=t.length;s>o;o++)n=e?this.coordsToLatLngs(t[o],e-1,i):(i||this.coordsToLatLng)(t[o]),a.push(n);return a},latLngToCoords:function(t){var e=[t.lng,t.lat];return t.alt!==i&&e.push(t.alt),e},latLngsToCoords:function(t){for(var e=[],i=0,n=t.length;n>i;i++)e.push(o.GeoJSON.latLngToCoords(t[i]));return e},getFeature:function(t,e){return t.feature?o.extend({},t.feature,{geometry:e}):o.GeoJSON.asFeature(e)},asFeature:function(t){return"Feature"===t.type?t:{type:"Feature",properties:{},geometry:t}}});var a={toGeoJSON:function(){return o.GeoJSON.getFeature(this,{type:"Point",coordinates:o.GeoJSON.latLngToCoords(this.getLatLng())})}};o.Marker.include(a),o.Circle.include(a),o.CircleMarker.include(a),o.Polyline.include({toGeoJSON:function(){return o.GeoJSON.getFeature(this,{type:"LineString",coordinates:o.GeoJSON.latLngsToCoords(this.getLatLngs())})}}),o.Polygon.include({toGeoJSON:function(){var t,e,i,n=[o.GeoJSON.latLngsToCoords(this.getLatLngs())];if(n[0].push(n[0][0]),this._holes)for(t=0,e=this._holes.length;e>t;t++)i=o.GeoJSON.latLngsToCoords(this._holes[t]),i.push(i[0]),n.push(i);return o.GeoJSON.getFeature(this,{type:"Polygon",coordinates:n})}}),function(){function t(t){return function(){var e=[];return this.eachLayer(function(t){e.push(t.toGeoJSON().geometry.coordinates)}),o.GeoJSON.getFeature(this,{type:t,coordinates:e})}}o.MultiPolyline.include({toGeoJSON:t("MultiLineString")}),o.MultiPolygon.include({toGeoJSON:t("MultiPolygon")}),o.LayerGroup.include({toGeoJSON:function(){var e,i=this.feature&&this.feature.geometry,n=[];if(i&&"MultiPoint"===i.type)return t("MultiPoint").call(this);var s=i&&"GeometryCollection"===i.type;return this.eachLayer(function(t){t.toGeoJSON&&(e=t.toGeoJSON(),n.push(s?e.geometry:o.GeoJSON.asFeature(e)))}),s?o.GeoJSON.getFeature(this,{geometries:n,type:"GeometryCollection"}):{type:"FeatureCollection",features:n}}})}(),o.geoJson=function(t,e){return new o.GeoJSON(t,e)},o.DomEvent={addListener:function(t,e,i,n){var s,a,r,h=o.stamp(i),l="_leaflet_"+e+h;return t[l]?this:(s=function(e){return i.call(n||t,e||o.DomEvent._getEvent())},o.Browser.pointer&&0===e.indexOf("touch")?this.addPointerListener(t,e,s,h):(o.Browser.touch&&"dblclick"===e&&this.addDoubleTapListener&&this.addDoubleTapListener(t,s,h),"addEventListener"in t?"mousewheel"===e?(t.addEventListener("DOMMouseScroll",s,!1),t.addEventListener(e,s,!1)):"mouseenter"===e||"mouseleave"===e?(a=s,r="mouseenter"===e?"mouseover":"mouseout",s=function(e){return o.DomEvent._checkMouse(t,e)?a(e):void 0},t.addEventListener(r,s,!1)):"click"===e&&o.Browser.android?(a=s,s=function(t){return o.DomEvent._filterClick(t,a)},t.addEventListener(e,s,!1)):t.addEventListener(e,s,!1):"attachEvent"in t&&t.attachEvent("on"+e,s),t[l]=s,this))},removeListener:function(t,e,i){var n=o.stamp(i),s="_leaflet_"+e+n,a=t[s];return a?(o.Browser.pointer&&0===e.indexOf("touch")?this.removePointerListener(t,e,n):o.Browser.touch&&"dblclick"===e&&this.removeDoubleTapListener?this.removeDoubleTapListener(t,n):"removeEventListener"in t?"mousewheel"===e?(t.removeEventListener("DOMMouseScroll",a,!1),t.removeEventListener(e,a,!1)):"mouseenter"===e||"mouseleave"===e?t.removeEventListener("mouseenter"===e?"mouseover":"mouseout",a,!1):t.removeEventListener(e,a,!1):"detachEvent"in t&&t.detachEvent("on"+e,a),t[s]=null,this):this},stopPropagation:function(t){return t.stopPropagation?t.stopPropagation():t.cancelBubble=!0,o.DomEvent._skipped(t),this},disableScrollPropagation:function(t){var e=o.DomEvent.stopPropagation;return o.DomEvent.on(t,"mousewheel",e).on(t,"MozMousePixelScroll",e)},disableClickPropagation:function(t){for(var e=o.DomEvent.stopPropagation,i=o.Draggable.START.length-1;i>=0;i--)o.DomEvent.on(t,o.Draggable.START[i],e);return o.DomEvent.on(t,"click",o.DomEvent._fakeStop).on(t,"dblclick",e)},preventDefault:function(t){return t.preventDefault?t.preventDefault():t.returnValue=!1,this},stop:function(t){return o.DomEvent.preventDefault(t).stopPropagation(t)},getMousePosition:function(t,e){if(!e)return new o.Point(t.clientX,t.clientY);var i=e.getBoundingClientRect();return new o.Point(t.clientX-i.left-e.clientLeft,t.clientY-i.top-e.clientTop)},getWheelDelta:function(t){var e=0;return t.wheelDelta&&(e=t.wheelDelta/120),t.detail&&(e=-t.detail/3),e},_skipEvents:{},_fakeStop:function(t){o.DomEvent._skipEvents[t.type]=!0},_skipped:function(t){var e=this._skipEvents[t.type];return this._skipEvents[t.type]=!1,e},_checkMouse:function(t,e){var i=e.relatedTarget;if(!i)return!0;try{for(;i&&i!==t;)i=i.parentNode}catch(n){return!1}return i!==t},_getEvent:function(){var e=t.event;if(!e)for(var i=arguments.callee.caller;i&&(e=i.arguments[0],!e||t.Event!==e.constructor);)i=i.caller;return e},_filterClick:function(t,e){var i=t.timeStamp||t.originalEvent.timeStamp,n=o.DomEvent._lastClick&&i-o.DomEvent._lastClick;return n&&n>100&&500>n||t.target._simulatedClick&&!t._simulated?void o.DomEvent.stop(t):(o.DomEvent._lastClick=i,e(t))}},o.DomEvent.on=o.DomEvent.addListener,o.DomEvent.off=o.DomEvent.removeListener,o.Draggable=o.Class.extend({includes:o.Mixin.Events,statics:{START:o.Browser.touch?["touchstart","mousedown"]:["mousedown"],END:{mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},MOVE:{mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"}},initialize:function(t,e){this._element=t,this._dragStartTarget=e||t},enable:function(){if(!this._enabled){for(var t=o.Draggable.START.length-1;t>=0;t--)o.DomEvent.on(this._dragStartTarget,o.Draggable.START[t],this._onDown,this);this._enabled=!0}},disable:function(){if(this._enabled){for(var t=o.Draggable.START.length-1;t>=0;t--)o.DomEvent.off(this._dragStartTarget,o.Draggable.START[t],this._onDown,this);this._enabled=!1,this._moved=!1}},_onDown:function(t){if(this._moved=!1,!t.shiftKey&&(1===t.which||1===t.button||t.touches)&&(o.DomEvent.stopPropagation(t),!o.Draggable._disabled&&(o.DomUtil.disableImageDrag(),o.DomUtil.disableTextSelection(),!this._moving))){var i=t.touches?t.touches[0]:t;this._startPoint=new o.Point(i.clientX,i.clientY),this._startPos=this._newPos=o.DomUtil.getPosition(this._element),o.DomEvent.on(e,o.Draggable.MOVE[t.type],this._onMove,this).on(e,o.Draggable.END[t.type],this._onUp,this)}},_onMove:function(t){if(t.touches&&t.touches.length>1)return void(this._moved=!0);var i=t.touches&&1===t.touches.length?t.touches[0]:t,n=new o.Point(i.clientX,i.clientY),s=n.subtract(this._startPoint);(s.x||s.y)&&(o.Browser.touch&&Math.abs(s.x)+Math.abs(s.y)<3||(o.DomEvent.preventDefault(t),this._moved||(this.fire("dragstart"),this._moved=!0,this._startPos=o.DomUtil.getPosition(this._element).subtract(s),o.DomUtil.addClass(e.body,"leaflet-dragging"),this._lastTarget=t.target||t.srcElement,o.DomUtil.addClass(this._lastTarget,"leaflet-drag-target")),this._newPos=this._startPos.add(s),this._moving=!0,o.Util.cancelAnimFrame(this._animRequest),this._animRequest=o.Util.requestAnimFrame(this._updatePosition,this,!0,this._dragStartTarget)))},_updatePosition:function(){this.fire("predrag"),o.DomUtil.setPosition(this._element,this._newPos),this.fire("drag")},_onUp:function(){o.DomUtil.removeClass(e.body,"leaflet-dragging"),this._lastTarget&&(o.DomUtil.removeClass(this._lastTarget,"leaflet-drag-target"),this._lastTarget=null);for(var t in o.Draggable.MOVE)o.DomEvent.off(e,o.Draggable.MOVE[t],this._onMove).off(e,o.Draggable.END[t],this._onUp);o.DomUtil.enableImageDrag(),o.DomUtil.enableTextSelection(),this._moved&&this._moving&&(o.Util.cancelAnimFrame(this._animRequest),this.fire("dragend",{distance:this._newPos.distanceTo(this._startPos)})),this._moving=!1}}),o.Handler=o.Class.extend({initialize:function(t){this._map=t},enable:function(){this._enabled||(this._enabled=!0,this.addHooks())},disable:function(){this._enabled&&(this._enabled=!1,this.removeHooks())},enabled:function(){return!!this._enabled}}),o.Map.mergeOptions({dragging:!0,inertia:!o.Browser.android23,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,inertiaThreshold:o.Browser.touch?32:18,easeLinearity:.25,worldCopyJump:!1}),o.Map.Drag=o.Handler.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new o.Draggable(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDrag,this),t.on("viewreset",this._onViewReset,this),t.whenReady(this._onViewReset,this))}this._draggable.enable()},removeHooks:function(){this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){var t=this._map;t._panAnim&&t._panAnim.stop(),t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(){if(this._map.options.inertia){var t=this._lastTime=+new Date,e=this._lastPos=this._draggable._newPos;this._positions.push(e),this._times.push(t),t-this._times[0]>200&&(this._positions.shift(),this._times.shift())}this._map.fire("move").fire("drag")},_onViewReset:function(){var t=this._map.getSize()._divideBy(2),e=this._map.latLngToLayerPoint([0,0]);this._initialWorldOffset=e.subtract(t).x,this._worldWidth=this._map.project([0,180]).x},_onPreDrag:function(){var t=this._worldWidth,e=Math.round(t/2),i=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-e+i)%t+e-i,s=(n+e+i)%t-e-i,a=Math.abs(o+i)<Math.abs(s+i)?o:s;this._draggable._newPos.x=a},_onDragEnd:function(t){var e=this._map,i=e.options,n=+new Date-this._lastTime,s=!i.inertia||n>i.inertiaThreshold||!this._positions[0];if(e.fire("dragend",t),s)e.fire("moveend");else{var a=this._lastPos.subtract(this._positions[0]),r=(this._lastTime+n-this._times[0])/1e3,h=i.easeLinearity,l=a.multiplyBy(h/r),u=l.distanceTo([0,0]),c=Math.min(i.inertiaMaxSpeed,u),d=l.multiplyBy(c/u),p=c/(i.inertiaDeceleration*h),_=d.multiplyBy(-p/2).round();_.x&&_.y?(_=e._limitOffset(_,e.options.maxBounds),o.Util.requestAnimFrame(function(){e.panBy(_,{duration:p,easeLinearity:h,noMoveStart:!0})})):e.fire("moveend")}}}),o.Map.addInitHook("addHandler","dragging",o.Map.Drag),o.Map.mergeOptions({doubleClickZoom:!0}),o.Map.DoubleClickZoom=o.Handler.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var e=this._map,i=e.getZoom()+(t.originalEvent.shiftKey?-1:1);"center"===e.options.doubleClickZoom?e.setZoom(i):e.setZoomAround(t.containerPoint,i)}}),o.Map.addInitHook("addHandler","doubleClickZoom",o.Map.DoubleClickZoom),o.Map.mergeOptions({scrollWheelZoom:!0}),o.Map.ScrollWheelZoom=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"mousewheel",this._onWheelScroll,this),o.DomEvent.on(this._map._container,"MozMousePixelScroll",o.DomEvent.preventDefault),this._delta=0},removeHooks:function(){o.DomEvent.off(this._map._container,"mousewheel",this._onWheelScroll),o.DomEvent.off(this._map._container,"MozMousePixelScroll",o.DomEvent.preventDefault)},_onWheelScroll:function(t){var e=o.DomEvent.getWheelDelta(t);this._delta+=e,this._lastMousePos=this._map.mouseEventToContainerPoint(t),this._startTime||(this._startTime=+new Date);var i=Math.max(40-(+new Date-this._startTime),0);clearTimeout(this._timer),this._timer=setTimeout(o.bind(this._performZoom,this),i),o.DomEvent.preventDefault(t),o.DomEvent.stopPropagation(t)},_performZoom:function(){var t=this._map,e=this._delta,i=t.getZoom();e=e>0?Math.ceil(e):Math.floor(e),e=Math.max(Math.min(e,4),-4),e=t._limitZoom(i+e)-i,this._delta=0,this._startTime=null,e&&("center"===t.options.scrollWheelZoom?t.setZoom(i+e):t.setZoomAround(this._lastMousePos,i+e))}}),o.Map.addInitHook("addHandler","scrollWheelZoom",o.Map.ScrollWheelZoom),o.extend(o.DomEvent,{_touchstart:o.Browser.msPointer?"MSPointerDown":o.Browser.pointer?"pointerdown":"touchstart",_touchend:o.Browser.msPointer?"MSPointerUp":o.Browser.pointer?"pointerup":"touchend",addDoubleTapListener:function(t,i,n){function s(t){var e;if(o.Browser.pointer?(_.push(t.pointerId),e=_.length):e=t.touches.length,!(e>1)){var i=Date.now(),n=i-(r||i);h=t.touches?t.touches[0]:t,l=n>0&&u>=n,r=i}}function a(t){if(o.Browser.pointer){var e=_.indexOf(t.pointerId);if(-1===e)return;_.splice(e,1)}if(l){if(o.Browser.pointer){var n,s={};for(var a in h)n=h[a],"function"==typeof n?s[a]=n.bind(h):s[a]=n;h=s}h.type="dblclick",i(h),r=null}}var r,h,l=!1,u=250,c="_leaflet_",d=this._touchstart,p=this._touchend,_=[];t[c+d+n]=s,t[c+p+n]=a;var m=o.Browser.pointer?e.documentElement:t;return t.addEventListener(d,s,!1),m.addEventListener(p,a,!1),o.Browser.pointer&&m.addEventListener(o.DomEvent.POINTER_CANCEL,a,!1),this},removeDoubleTapListener:function(t,i){var n="_leaflet_";return t.removeEventListener(this._touchstart,t[n+this._touchstart+i],!1),(o.Browser.pointer?e.documentElement:t).removeEventListener(this._touchend,t[n+this._touchend+i],!1),o.Browser.pointer&&e.documentElement.removeEventListener(o.DomEvent.POINTER_CANCEL,t[n+this._touchend+i],!1),this}}),o.extend(o.DomEvent,{POINTER_DOWN:o.Browser.msPointer?"MSPointerDown":"pointerdown",POINTER_MOVE:o.Browser.msPointer?"MSPointerMove":"pointermove",POINTER_UP:o.Browser.msPointer?"MSPointerUp":"pointerup",POINTER_CANCEL:o.Browser.msPointer?"MSPointerCancel":"pointercancel",_pointers:[],_pointerDocumentListener:!1,addPointerListener:function(t,e,i,n){switch(e){case"touchstart":return this.addPointerListenerStart(t,e,i,n); -case"touchend":return this.addPointerListenerEnd(t,e,i,n);case"touchmove":return this.addPointerListenerMove(t,e,i,n);default:throw"Unknown touch event type"}},addPointerListenerStart:function(t,i,n,s){var a="_leaflet_",r=this._pointers,h=function(t){"mouse"!==t.pointerType&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&o.DomEvent.preventDefault(t);for(var e=!1,i=0;i<r.length;i++)if(r[i].pointerId===t.pointerId){e=!0;break}e||r.push(t),t.touches=r.slice(),t.changedTouches=[t],n(t)};if(t[a+"touchstart"+s]=h,t.addEventListener(this.POINTER_DOWN,h,!1),!this._pointerDocumentListener){var l=function(t){for(var e=0;e<r.length;e++)if(r[e].pointerId===t.pointerId){r.splice(e,1);break}};e.documentElement.addEventListener(this.POINTER_UP,l,!1),e.documentElement.addEventListener(this.POINTER_CANCEL,l,!1),this._pointerDocumentListener=!0}return this},addPointerListenerMove:function(t,e,i,n){function o(t){if(t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&"mouse"!==t.pointerType||0!==t.buttons){for(var e=0;e<a.length;e++)if(a[e].pointerId===t.pointerId){a[e]=t;break}t.touches=a.slice(),t.changedTouches=[t],i(t)}}var s="_leaflet_",a=this._pointers;return t[s+"touchmove"+n]=o,t.addEventListener(this.POINTER_MOVE,o,!1),this},addPointerListenerEnd:function(t,e,i,n){var o="_leaflet_",s=this._pointers,a=function(t){for(var e=0;e<s.length;e++)if(s[e].pointerId===t.pointerId){s.splice(e,1);break}t.touches=s.slice(),t.changedTouches=[t],i(t)};return t[o+"touchend"+n]=a,t.addEventListener(this.POINTER_UP,a,!1),t.addEventListener(this.POINTER_CANCEL,a,!1),this},removePointerListener:function(t,e,i){var n="_leaflet_",o=t[n+e+i];switch(e){case"touchstart":t.removeEventListener(this.POINTER_DOWN,o,!1);break;case"touchmove":t.removeEventListener(this.POINTER_MOVE,o,!1);break;case"touchend":t.removeEventListener(this.POINTER_UP,o,!1),t.removeEventListener(this.POINTER_CANCEL,o,!1)}return this}}),o.Map.mergeOptions({touchZoom:o.Browser.touch&&!o.Browser.android23,bounceAtZoomLimits:!0}),o.Map.TouchZoom=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){o.DomEvent.off(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var n=i.mouseEventToLayerPoint(t.touches[0]),s=i.mouseEventToLayerPoint(t.touches[1]),a=i._getCenterLayerPoint();this._startCenter=n.add(s)._divideBy(2),this._startDist=n.distanceTo(s),this._moved=!1,this._zooming=!0,this._centerOffset=a.subtract(this._startCenter),i._panAnim&&i._panAnim.stop(),o.DomEvent.on(e,"touchmove",this._onTouchMove,this).on(e,"touchend",this._onTouchEnd,this),o.DomEvent.preventDefault(t)}},_onTouchMove:function(t){var e=this._map;if(t.touches&&2===t.touches.length&&this._zooming){var i=e.mouseEventToLayerPoint(t.touches[0]),n=e.mouseEventToLayerPoint(t.touches[1]);this._scale=i.distanceTo(n)/this._startDist,this._delta=i._add(n)._divideBy(2)._subtract(this._startCenter),1!==this._scale&&(e.options.bounceAtZoomLimits||!(e.getZoom()===e.getMinZoom()&&this._scale<1||e.getZoom()===e.getMaxZoom()&&this._scale>1))&&(this._moved||(o.DomUtil.addClass(e._mapPane,"leaflet-touching"),e.fire("movestart").fire("zoomstart"),this._moved=!0),o.Util.cancelAnimFrame(this._animRequest),this._animRequest=o.Util.requestAnimFrame(this._updateOnMove,this,!0,this._map._container),o.DomEvent.preventDefault(t))}},_updateOnMove:function(){var t=this._map,e=this._getScaleOrigin(),i=t.layerPointToLatLng(e),n=t.getScaleZoom(this._scale);t._animateZoom(i,n,this._startCenter,this._scale,this._delta,!1,!0)},_onTouchEnd:function(){if(!this._moved||!this._zooming)return void(this._zooming=!1);var t=this._map;this._zooming=!1,o.DomUtil.removeClass(t._mapPane,"leaflet-touching"),o.Util.cancelAnimFrame(this._animRequest),o.DomEvent.off(e,"touchmove",this._onTouchMove).off(e,"touchend",this._onTouchEnd);var i=this._getScaleOrigin(),n=t.layerPointToLatLng(i),s=t.getZoom(),a=t.getScaleZoom(this._scale)-s,r=a>0?Math.ceil(a):Math.floor(a),h=t._limitZoom(s+r),l=t.getZoomScale(h)/this._scale;t._animateZoom(n,h,i,l)},_getScaleOrigin:function(){var t=this._centerOffset.subtract(this._delta).divideBy(this._scale);return this._startCenter.add(t)}}),o.Map.addInitHook("addHandler","touchZoom",o.Map.TouchZoom),o.Map.mergeOptions({tap:!0,tapTolerance:15}),o.Map.Tap=o.Handler.extend({addHooks:function(){o.DomEvent.on(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){o.DomEvent.off(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if(o.DomEvent.preventDefault(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new o.Point(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.addClass(n,"leaflet-active"),this._holdTimeout=setTimeout(o.bind(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),o.DomEvent.on(e,"touchmove",this._onMove,this).on(e,"touchend",this._onUp,this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),o.DomEvent.off(e,"touchmove",this._onMove,this).off(e,"touchend",this._onUp,this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],n=i.target;n&&n.tagName&&"a"===n.tagName.toLowerCase()&&o.DomUtil.removeClass(n,"leaflet-active"),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var e=t.touches[0];this._newPos=new o.Point(e.clientX,e.clientY)},_simulateEvent:function(i,n){var o=e.createEvent("MouseEvents");o._simulated=!0,n.target._simulatedClick=!0,o.initMouseEvent(i,!0,!0,t,1,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null),n.target.dispatchEvent(o)}}),o.Browser.touch&&!o.Browser.pointer&&o.Map.addInitHook("addHandler","tap",o.Map.Tap),o.Map.mergeOptions({boxZoom:!0}),o.Map.BoxZoom=o.Handler.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._moved=!1},addHooks:function(){o.DomEvent.on(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){o.DomEvent.off(this._container,"mousedown",this._onMouseDown),this._moved=!1},moved:function(){return this._moved},_onMouseDown:function(t){return this._moved=!1,!t.shiftKey||1!==t.which&&1!==t.button?!1:(o.DomUtil.disableTextSelection(),o.DomUtil.disableImageDrag(),this._startLayerPoint=this._map.mouseEventToLayerPoint(t),void o.DomEvent.on(e,"mousemove",this._onMouseMove,this).on(e,"mouseup",this._onMouseUp,this).on(e,"keydown",this._onKeyDown,this))},_onMouseMove:function(t){this._moved||(this._box=o.DomUtil.create("div","leaflet-zoom-box",this._pane),o.DomUtil.setPosition(this._box,this._startLayerPoint),this._container.style.cursor="crosshair",this._map.fire("boxzoomstart"));var e=this._startLayerPoint,i=this._box,n=this._map.mouseEventToLayerPoint(t),s=n.subtract(e),a=new o.Point(Math.min(n.x,e.x),Math.min(n.y,e.y));o.DomUtil.setPosition(i,a),this._moved=!0,i.style.width=Math.max(0,Math.abs(s.x)-4)+"px",i.style.height=Math.max(0,Math.abs(s.y)-4)+"px"},_finish:function(){this._moved&&(this._pane.removeChild(this._box),this._container.style.cursor=""),o.DomUtil.enableTextSelection(),o.DomUtil.enableImageDrag(),o.DomEvent.off(e,"mousemove",this._onMouseMove).off(e,"mouseup",this._onMouseUp).off(e,"keydown",this._onKeyDown)},_onMouseUp:function(t){this._finish();var e=this._map,i=e.mouseEventToLayerPoint(t);if(!this._startLayerPoint.equals(i)){var n=new o.LatLngBounds(e.layerPointToLatLng(this._startLayerPoint),e.layerPointToLatLng(i));e.fitBounds(n),e.fire("boxzoomend",{boxZoomBounds:n})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}}),o.Map.addInitHook("addHandler","boxZoom",o.Map.BoxZoom),o.Map.mergeOptions({keyboard:!0,keyboardPanOffset:80,keyboardZoomOffset:1}),o.Map.Keyboard=o.Handler.extend({keyCodes:{left:[37],right:[39],down:[40],up:[38],zoomIn:[187,107,61,171],zoomOut:[189,109,173]},initialize:function(t){this._map=t,this._setPanOffset(t.options.keyboardPanOffset),this._setZoomOffset(t.options.keyboardZoomOffset)},addHooks:function(){var t=this._map._container;-1===t.tabIndex&&(t.tabIndex="0"),o.DomEvent.on(t,"focus",this._onFocus,this).on(t,"blur",this._onBlur,this).on(t,"mousedown",this._onMouseDown,this),this._map.on("focus",this._addHooks,this).on("blur",this._removeHooks,this)},removeHooks:function(){this._removeHooks();var t=this._map._container;o.DomEvent.off(t,"focus",this._onFocus,this).off(t,"blur",this._onBlur,this).off(t,"mousedown",this._onMouseDown,this),this._map.off("focus",this._addHooks,this).off("blur",this._removeHooks,this)},_onMouseDown:function(){if(!this._focused){var i=e.body,n=e.documentElement,o=i.scrollTop||n.scrollTop,s=i.scrollLeft||n.scrollLeft;this._map._container.focus(),t.scrollTo(s,o)}},_onFocus:function(){this._focused=!0,this._map.fire("focus")},_onBlur:function(){this._focused=!1,this._map.fire("blur")},_setPanOffset:function(t){var e,i,n=this._panKeys={},o=this.keyCodes;for(e=0,i=o.left.length;i>e;e++)n[o.left[e]]=[-1*t,0];for(e=0,i=o.right.length;i>e;e++)n[o.right[e]]=[t,0];for(e=0,i=o.down.length;i>e;e++)n[o.down[e]]=[0,t];for(e=0,i=o.up.length;i>e;e++)n[o.up[e]]=[0,-1*t]},_setZoomOffset:function(t){var e,i,n=this._zoomKeys={},o=this.keyCodes;for(e=0,i=o.zoomIn.length;i>e;e++)n[o.zoomIn[e]]=t;for(e=0,i=o.zoomOut.length;i>e;e++)n[o.zoomOut[e]]=-t},_addHooks:function(){o.DomEvent.on(e,"keydown",this._onKeyDown,this)},_removeHooks:function(){o.DomEvent.off(e,"keydown",this._onKeyDown,this)},_onKeyDown:function(t){var e=t.keyCode,i=this._map;if(e in this._panKeys){if(i._panAnim&&i._panAnim._inProgress)return;i.panBy(this._panKeys[e]),i.options.maxBounds&&i.panInsideBounds(i.options.maxBounds)}else{if(!(e in this._zoomKeys))return;i.setZoom(i.getZoom()+this._zoomKeys[e])}o.DomEvent.stop(t)}}),o.Map.addInitHook("addHandler","keyboard",o.Map.Keyboard),o.Handler.MarkerDrag=o.Handler.extend({initialize:function(t){this._marker=t},addHooks:function(){var t=this._marker._icon;this._draggable||(this._draggable=new o.Draggable(t,t)),this._draggable.on("dragstart",this._onDragStart,this).on("drag",this._onDrag,this).on("dragend",this._onDragEnd,this),this._draggable.enable(),o.DomUtil.addClass(this._marker._icon,"leaflet-marker-draggable")},removeHooks:function(){this._draggable.off("dragstart",this._onDragStart,this).off("drag",this._onDrag,this).off("dragend",this._onDragEnd,this),this._draggable.disable(),o.DomUtil.removeClass(this._marker._icon,"leaflet-marker-draggable")},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){this._marker.closePopup().fire("movestart").fire("dragstart")},_onDrag:function(){var t=this._marker,e=t._shadow,i=o.DomUtil.getPosition(t._icon),n=t._map.layerPointToLatLng(i);e&&o.DomUtil.setPosition(e,i),t._latlng=n,t.fire("move",{latlng:n}).fire("drag")},_onDragEnd:function(t){this._marker.fire("moveend").fire("dragend",t)}}),o.Control=o.Class.extend({options:{position:"topright"},initialize:function(t){o.setOptions(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var e=this._map;return e&&e.removeControl(this),this.options.position=t,e&&e.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this._map=t;var e=this._container=this.onAdd(t),i=this.getPosition(),n=t._controlCorners[i];return o.DomUtil.addClass(e,"leaflet-control"),-1!==i.indexOf("bottom")?n.insertBefore(e,n.firstChild):n.appendChild(e),this},removeFrom:function(t){var e=this.getPosition(),i=t._controlCorners[e];return i.removeChild(this._container),this._map=null,this.onRemove&&this.onRemove(t),this},_refocusOnMap:function(){this._map&&this._map.getContainer().focus()}}),o.control=function(t){return new o.Control(t)},o.Map.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.removeFrom(this),this},_initControlPos:function(){function t(t,s){var a=i+t+" "+i+s;e[t+s]=o.DomUtil.create("div",a,n)}var e=this._controlCorners={},i="leaflet-",n=this._controlContainer=o.DomUtil.create("div",i+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){this._container.removeChild(this._controlContainer)}}),o.Control.Zoom=o.Control.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"-",zoomOutTitle:"Zoom out"},onAdd:function(t){var e="leaflet-control-zoom",i=o.DomUtil.create("div",e+" leaflet-bar");return this._map=t,this._zoomInButton=this._createButton(this.options.zoomInText,this.options.zoomInTitle,e+"-in",i,this._zoomIn,this),this._zoomOutButton=this._createButton(this.options.zoomOutText,this.options.zoomOutTitle,e+"-out",i,this._zoomOut,this),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),i},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},_zoomIn:function(t){this._map.zoomIn(t.shiftKey?3:1)},_zoomOut:function(t){this._map.zoomOut(t.shiftKey?3:1)},_createButton:function(t,e,i,n,s,a){var r=o.DomUtil.create("a",i,n);r.innerHTML=t,r.href="#",r.title=e;var h=o.DomEvent.stopPropagation;return o.DomEvent.on(r,"click",h).on(r,"mousedown",h).on(r,"dblclick",h).on(r,"click",o.DomEvent.preventDefault).on(r,"click",s,a).on(r,"click",this._refocusOnMap,a),r},_updateDisabled:function(){var t=this._map,e="leaflet-disabled";o.DomUtil.removeClass(this._zoomInButton,e),o.DomUtil.removeClass(this._zoomOutButton,e),t._zoom===t.getMinZoom()&&o.DomUtil.addClass(this._zoomOutButton,e),t._zoom===t.getMaxZoom()&&o.DomUtil.addClass(this._zoomInButton,e)}}),o.Map.mergeOptions({zoomControl:!0}),o.Map.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new o.Control.Zoom,this.addControl(this.zoomControl))}),o.control.zoom=function(t){return new o.Control.Zoom(t)},o.Control.Attribution=o.Control.extend({options:{position:"bottomright",prefix:'<a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>'},initialize:function(t){o.setOptions(this,t),this._attributions={}},onAdd:function(t){this._container=o.DomUtil.create("div","leaflet-control-attribution"),o.DomEvent.disableClickPropagation(this._container);for(var e in t._layers)t._layers[e].getAttribution&&this.addAttribution(t._layers[e].getAttribution());return t.on("layeradd",this._onLayerAdd,this).on("layerremove",this._onLayerRemove,this),this._update(),this._container},onRemove:function(t){t.off("layeradd",this._onLayerAdd).off("layerremove",this._onLayerRemove)},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):void 0},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):void 0},_update:function(){if(this._map){var t=[];for(var e in this._attributions)this._attributions[e]&&t.push(e);var i=[];this.options.prefix&&i.push(this.options.prefix),t.length&&i.push(t.join(", ")),this._container.innerHTML=i.join(" | ")}},_onLayerAdd:function(t){t.layer.getAttribution&&this.addAttribution(t.layer.getAttribution())},_onLayerRemove:function(t){t.layer.getAttribution&&this.removeAttribution(t.layer.getAttribution())}}),o.Map.mergeOptions({attributionControl:!0}),o.Map.addInitHook(function(){this.options.attributionControl&&(this.attributionControl=(new o.Control.Attribution).addTo(this))}),o.control.attribution=function(t){return new o.Control.Attribution(t)},o.Control.Scale=o.Control.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0,updateWhenIdle:!1},onAdd:function(t){this._map=t;var e="leaflet-control-scale",i=o.DomUtil.create("div",e),n=this.options;return this._addScales(n,e,i),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),i},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,e,i){t.metric&&(this._mScale=o.DomUtil.create("div",e+"-line",i)),t.imperial&&(this._iScale=o.DomUtil.create("div",e+"-line",i))},_update:function(){var t=this._map.getBounds(),e=t.getCenter().lat,i=6378137*Math.PI*Math.cos(e*Math.PI/180),n=i*(t.getNorthEast().lng-t.getSouthWest().lng)/180,o=this._map.getSize(),s=this.options,a=0;o.x>0&&(a=n*(s.maxWidth/o.x)),this._updateScales(s,a)},_updateScales:function(t,e){t.metric&&e&&this._updateMetric(e),t.imperial&&e&&this._updateImperial(e)},_updateMetric:function(t){var e=this._getRoundNum(t);this._mScale.style.width=this._getScaleWidth(e/t)+"px",this._mScale.innerHTML=1e3>e?e+" m":e/1e3+" km"},_updateImperial:function(t){var e,i,n,o=3.2808399*t,s=this._iScale;o>5280?(e=o/5280,i=this._getRoundNum(e),s.style.width=this._getScaleWidth(i/e)+"px",s.innerHTML=i+" mi"):(n=this._getRoundNum(o),s.style.width=this._getScaleWidth(n/o)+"px",s.innerHTML=n+" ft")},_getScaleWidth:function(t){return Math.round(this.options.maxWidth*t)-10},_getRoundNum:function(t){var e=Math.pow(10,(Math.floor(t)+"").length-1),i=t/e;return i=i>=10?10:i>=5?5:i>=3?3:i>=2?2:1,e*i}}),o.control.scale=function(t){return new o.Control.Scale(t)},o.Control.Layers=o.Control.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0},initialize:function(t,e,i){o.setOptions(this,i),this._layers={},this._lastZIndex=0,this._handlingClick=!1;for(var n in t)this._addLayer(t[n],n);for(n in e)this._addLayer(e[n],n,!0)},onAdd:function(t){return this._initLayout(),this._update(),t.on("layeradd",this._onLayerChange,this).on("layerremove",this._onLayerChange,this),this._container},onRemove:function(t){t.off("layeradd",this._onLayerChange,this).off("layerremove",this._onLayerChange,this)},addBaseLayer:function(t,e){return this._addLayer(t,e),this._update(),this},addOverlay:function(t,e){return this._addLayer(t,e,!0),this._update(),this},removeLayer:function(t){var e=o.stamp(t);return delete this._layers[e],this._update(),this},_initLayout:function(){var t="leaflet-control-layers",e=this._container=o.DomUtil.create("div",t);e.setAttribute("aria-haspopup",!0),o.Browser.touch?o.DomEvent.on(e,"click",o.DomEvent.stopPropagation):o.DomEvent.disableClickPropagation(e).disableScrollPropagation(e);var i=this._form=o.DomUtil.create("form",t+"-list");if(this.options.collapsed){o.Browser.android||o.DomEvent.on(e,"mouseover",this._expand,this).on(e,"mouseout",this._collapse,this);var n=this._layersLink=o.DomUtil.create("a",t+"-toggle",e);n.href="#",n.title="Layers",o.Browser.touch?o.DomEvent.on(n,"click",o.DomEvent.stop).on(n,"click",this._expand,this):o.DomEvent.on(n,"focus",this._expand,this),o.DomEvent.on(i,"click",function(){setTimeout(o.bind(this._onInputClick,this),0)},this),this._map.on("click",this._collapse,this)}else this._expand();this._baseLayersList=o.DomUtil.create("div",t+"-base",i),this._separator=o.DomUtil.create("div",t+"-separator",i),this._overlaysList=o.DomUtil.create("div",t+"-overlays",i),e.appendChild(i)},_addLayer:function(t,e,i){var n=o.stamp(t);this._layers[n]={layer:t,name:e,overlay:i},this.options.autoZIndex&&t.setZIndex&&(this._lastZIndex++,t.setZIndex(this._lastZIndex))},_update:function(){if(this._container){this._baseLayersList.innerHTML="",this._overlaysList.innerHTML="";var t,e,i=!1,n=!1;for(t in this._layers)e=this._layers[t],this._addItem(e),n=n||e.overlay,i=i||!e.overlay;this._separator.style.display=n&&i?"":"none"}},_onLayerChange:function(t){var e=this._layers[o.stamp(t.layer)];if(e){this._handlingClick||this._update();var i=e.overlay?"layeradd"===t.type?"overlayadd":"overlayremove":"layeradd"===t.type?"baselayerchange":null;i&&this._map.fire(i,e)}},_createRadioElement:function(t,i){var n='<input type="radio" class="leaflet-control-layers-selector" name="'+t+'"';i&&(n+=' checked="checked"'),n+="/>";var o=e.createElement("div");return o.innerHTML=n,o.firstChild},_addItem:function(t){var i,n=e.createElement("label"),s=this._map.hasLayer(t.layer);t.overlay?(i=e.createElement("input"),i.type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=s):i=this._createRadioElement("leaflet-base-layers",s),i.layerId=o.stamp(t.layer),o.DomEvent.on(i,"click",this._onInputClick,this);var a=e.createElement("span");a.innerHTML=" "+t.name,n.appendChild(i),n.appendChild(a);var r=t.overlay?this._overlaysList:this._baseLayersList;return r.appendChild(n),n},_onInputClick:function(){var t,e,i,n=this._form.getElementsByTagName("input"),o=n.length;for(this._handlingClick=!0,t=0;o>t;t++)e=n[t],i=this._layers[e.layerId],e.checked&&!this._map.hasLayer(i.layer)?this._map.addLayer(i.layer):!e.checked&&this._map.hasLayer(i.layer)&&this._map.removeLayer(i.layer);this._handlingClick=!1,this._refocusOnMap()},_expand:function(){o.DomUtil.addClass(this._container,"leaflet-control-layers-expanded")},_collapse:function(){this._container.className=this._container.className.replace(" leaflet-control-layers-expanded","")}}),o.control.layers=function(t,e,i){return new o.Control.Layers(t,e,i)},o.PosAnimation=o.Class.extend({includes:o.Mixin.Events,run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._newPos=e,this.fire("start"),t.style[o.DomUtil.TRANSITION]="all "+(i||.25)+"s cubic-bezier(0,0,"+(n||.5)+",1)",o.DomEvent.on(t,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),o.DomUtil.setPosition(t,e),o.Util.falseFn(t.offsetWidth),this._stepTimer=setInterval(o.bind(this._onStep,this),50)},stop:function(){this._inProgress&&(o.DomUtil.setPosition(this._el,this._getPos()),this._onTransitionEnd(),o.Util.falseFn(this._el.offsetWidth))},_onStep:function(){var t=this._getPos();return t?(this._el._leaflet_pos=t,void this.fire("step")):void this._onTransitionEnd()},_transformRe:/([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/,_getPos:function(){var e,i,n,s=this._el,a=t.getComputedStyle(s);if(o.Browser.any3d){if(n=a[o.DomUtil.TRANSFORM].match(this._transformRe),!n)return;e=parseFloat(n[1]),i=parseFloat(n[2])}else e=parseFloat(a.left),i=parseFloat(a.top);return new o.Point(e,i,!0)},_onTransitionEnd:function(){o.DomEvent.off(this._el,o.DomUtil.TRANSITION_END,this._onTransitionEnd,this),this._inProgress&&(this._inProgress=!1,this._el.style[o.DomUtil.TRANSITION]="",this._el._leaflet_pos=this._newPos,clearInterval(this._stepTimer),this.fire("step").fire("end"))}}),o.Map.include({setView:function(t,e,n){if(e=e===i?this._zoom:this._limitZoom(e),t=this._limitCenter(o.latLng(t),e,this.options.maxBounds),n=n||{},this._panAnim&&this._panAnim.stop(),this._loaded&&!n.reset&&n!==!0){n.animate!==i&&(n.zoom=o.extend({animate:n.animate},n.zoom),n.pan=o.extend({animate:n.animate},n.pan));var s=this._zoom!==e?this._tryAnimatedZoom&&this._tryAnimatedZoom(t,e,n.zoom):this._tryAnimatedPan(t,n.pan);if(s)return clearTimeout(this._sizeTimer),this}return this._resetView(t,e),this},panBy:function(t,e){if(t=o.point(t).round(),e=e||{},!t.x&&!t.y)return this;if(this._panAnim||(this._panAnim=new o.PosAnimation,this._panAnim.on({step:this._onPanTransitionStep,end:this._onPanTransitionEnd},this)),e.noMoveStart||this.fire("movestart"),e.animate!==!1){o.DomUtil.addClass(this._mapPane,"leaflet-pan-anim");var i=this._getMapPanePos().subtract(t);this._panAnim.run(this._mapPane,i,e.duration||.25,e.easeLinearity)}else this._rawPanBy(t),this.fire("move").fire("moveend");return this},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){o.DomUtil.removeClass(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,e){var i=this._getCenterOffset(t)._floor();return(e&&e.animate)===!0||this.getSize().contains(i)?(this.panBy(i,e),!0):!1}}),o.PosAnimation=o.DomUtil.TRANSITION?o.PosAnimation:o.PosAnimation.extend({run:function(t,e,i,n){this.stop(),this._el=t,this._inProgress=!0,this._duration=i||.25,this._easeOutPower=1/Math.max(n||.5,.2),this._startPos=o.DomUtil.getPosition(t),this._offset=e.subtract(this._startPos),this._startTime=+new Date,this.fire("start"),this._animate()},stop:function(){this._inProgress&&(this._step(),this._complete())},_animate:function(){this._animId=o.Util.requestAnimFrame(this._animate,this),this._step()},_step:function(){var t=+new Date-this._startTime,e=1e3*this._duration;e>t?this._runFrame(this._easeOut(t/e)):(this._runFrame(1),this._complete())},_runFrame:function(t){var e=this._startPos.add(this._offset.multiplyBy(t));o.DomUtil.setPosition(this._el,e),this.fire("step")},_complete:function(){o.Util.cancelAnimFrame(this._animId),this._inProgress=!1,this.fire("end")},_easeOut:function(t){return 1-Math.pow(1-t,this._easeOutPower)}}),o.Map.mergeOptions({zoomAnimation:!0,zoomAnimationThreshold:4}),o.DomUtil.TRANSITION&&o.Map.addInitHook(function(){this._zoomAnimated=this.options.zoomAnimation&&o.DomUtil.TRANSITION&&o.Browser.any3d&&!o.Browser.android23&&!o.Browser.mobileOpera,this._zoomAnimated&&o.DomEvent.on(this._mapPane,o.DomUtil.TRANSITION_END,this._catchTransitionEnd,this)}),o.Map.include(o.DomUtil.TRANSITION?{_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,e,i){if(this._animatingZoom)return!0;if(i=i||{},!this._zoomAnimated||i.animate===!1||this._nothingToAnimate()||Math.abs(e-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(e),o=this._getCenterOffset(t)._divideBy(1-1/n),s=this._getCenterLayerPoint()._add(o);return i.animate===!0||this.getSize().contains(o)?(this.fire("movestart").fire("zoomstart"),this._animateZoom(t,e,s,n,null,!0),!0):!1},_animateZoom:function(t,e,i,n,s,a,r){r||(this._animatingZoom=!0),o.DomUtil.addClass(this._mapPane,"leaflet-zoom-anim"),this._animateToCenter=t,this._animateToZoom=e,o.Draggable&&(o.Draggable._disabled=!0),o.Util.requestAnimFrame(function(){this.fire("zoomanim",{center:t,zoom:e,origin:i,scale:n,delta:s,backwards:a}),setTimeout(o.bind(this._onZoomTransitionEnd,this),250)},this)},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._animatingZoom=!1,o.DomUtil.removeClass(this._mapPane,"leaflet-zoom-anim"),o.Util.requestAnimFrame(function(){this._resetView(this._animateToCenter,this._animateToZoom,!0,!0),o.Draggable&&(o.Draggable._disabled=!1)},this))}}:{}),o.TileLayer.include({_animateZoom:function(t){this._animating||(this._animating=!0,this._prepareBgBuffer());var e=this._bgBuffer,i=o.DomUtil.TRANSFORM,n=t.delta?o.DomUtil.getTranslateString(t.delta):e.style[i],s=o.DomUtil.getScaleString(t.scale,t.origin);e.style[i]=t.backwards?s+" "+n:n+" "+s},_endZoomAnim:function(){var t=this._tileContainer,e=this._bgBuffer;t.style.visibility="",t.parentNode.appendChild(t),o.Util.falseFn(e.offsetWidth);var i=this._map.getZoom();(i>this.options.maxZoom||i<this.options.minZoom)&&this._clearBgBuffer(),this._animating=!1},_clearBgBuffer:function(){var t=this._map;!t||t._animatingZoom||t.touchZoom._zooming||(this._bgBuffer.innerHTML="",this._bgBuffer.style[o.DomUtil.TRANSFORM]="")},_prepareBgBuffer:function(){var t=this._tileContainer,e=this._bgBuffer,i=this._getLoadedTilesPercentage(e),n=this._getLoadedTilesPercentage(t);return e&&i>.5&&.5>n?(t.style.visibility="hidden",void this._stopLoadingImages(t)):(e.style.visibility="hidden",e.style[o.DomUtil.TRANSFORM]="",this._tileContainer=e,e=this._bgBuffer=t,this._stopLoadingImages(e),void clearTimeout(this._clearBgBufferTimer))},_getLoadedTilesPercentage:function(t){var e,i,n=t.getElementsByTagName("img"),o=0;for(e=0,i=n.length;i>e;e++)n[e].complete&&o++;return o/i},_stopLoadingImages:function(t){var e,i,n,s=Array.prototype.slice.call(t.getElementsByTagName("img"));for(e=0,i=s.length;i>e;e++)n=s[e],n.complete||(n.onload=o.Util.falseFn,n.onerror=o.Util.falseFn,n.src=o.Util.emptyImageUrl,n.parentNode.removeChild(n))}}),o.Map.include({_defaultLocateOptions:{watch:!1,setView:!1,maxZoom:1/0,timeout:1e4,maximumAge:0,enableHighAccuracy:!1},locate:function(t){if(t=this._locateOptions=o.extend(this._defaultLocateOptions,t),!navigator.geolocation)return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var e=o.bind(this._handleGeolocationResponse,this),i=o.bind(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(e,i,t):navigator.geolocation.getCurrentPosition(e,i,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var e=t.code,i=t.message||(1===e?"permission denied":2===e?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:e,message:"Geolocation error: "+i+"."})},_handleGeolocationResponse:function(t){var e=t.coords.latitude,i=t.coords.longitude,n=new o.LatLng(e,i),s=180*t.coords.accuracy/40075017,a=s/Math.cos(o.LatLng.DEG_TO_RAD*e),r=o.latLngBounds([e-s,i-a],[e+s,i+a]),h=this._locateOptions;if(h.setView){var l=Math.min(this.getBoundsZoom(r),h.maxZoom);this.setView(n,l)}var u={latlng:n,bounds:r,timestamp:t.timestamp};for(var c in t.coords)"number"==typeof t.coords[c]&&(u[c]=t.coords[c]);this.fire("locationfound",u)}})}(window,document); \ No newline at end of file diff --git a/assets/www/js/vendor/leaflet.loading.js b/assets/www/js/vendor/leaflet.loading.js deleted file mode 100644 index 7fb7b780878440160ccfbdf7f9ca4b3304fd4297..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/leaflet.loading.js +++ /dev/null @@ -1,351 +0,0 @@ -/* - * L.Control.Loading is a control that shows a loading indicator when tiles are - * loading or when map-related AJAX requests are taking place. - */ - -(function () { - - var console = window.console || { - error: function () {}, - warn: function () {} - }; - - function defineLeafletLoading(L) { - L.Control.Loading = L.Control.extend({ - options: { - delayIndicator: null, - position: 'topleft', - separate: false, - zoomControl: null, - spinjs: false, - spin: { - lines: 7, - length: 3, - width: 3, - radius: 5, - rotate: 13, - top: "83%" - } - }, - - initialize: function(options) { - L.setOptions(this, options); - this._dataLoaders = {}; - - // Try to set the zoom control this control is attached to from the - // options - if (this.options.zoomControl !== null) { - this.zoomControl = this.options.zoomControl; - } - }, - - onAdd: function(map) { - if (this.options.spinjs && (typeof Spinner !== 'function')) { - return console.error("Leaflet.loading cannot load because you didn't load spin.js (http://fgnass.github.io/spin.js/), even though you set it in options."); - } - this._addLayerListeners(map); - this._addMapListeners(map); - - // Try to set the zoom control this control is attached to from the map - // the control is being added to - if (!this.options.separate && !this.zoomControl) { - if (map.zoomControl) { - this.zoomControl = map.zoomControl; - } else if (map.zoomsliderControl) { - this.zoomControl = map.zoomsliderControl; - } - } - - // Create the loading indicator - var classes = 'leaflet-control-loading'; - var container; - if (this.zoomControl && !this.options.separate) { - // If there is a zoom control, hook into the bottom of it - container = this.zoomControl._container; - // These classes are no longer used as of Leaflet 0.6 - classes += ' leaflet-bar-part-bottom leaflet-bar-part last'; - - // Loading control will be added to the zoom control. So the visible last element is not the - // last dom element anymore. So add the part-bottom class. - L.DomUtil.addClass(this._getLastControlButton(), 'leaflet-bar-part-bottom'); - } - else { - // Otherwise, create a container for the indicator - container = L.DomUtil.create('div', 'leaflet-control-zoom leaflet-control-layer-container leaflet-bar'); - } - this._indicatorContainer = container; - this._indicator = L.DomUtil.create('a', classes, container); - if (this.options.spinjs) { - this._spinner = new Spinner(this.options.spin).spin(); - this._indicator.appendChild(this._spinner.el); - } - return container; - }, - - onRemove: function(map) { - this._removeLayerListeners(map); - this._removeMapListeners(map); - }, - - removeFrom: function (map) { - if (this.zoomControl && !this.options.separate) { - // Override Control.removeFrom() to avoid clobbering the entire - // _container, which is the same as zoomControl's - this._container.removeChild(this._indicator); - this._map = null; - this.onRemove(map); - return this; - } - else { - // If this control is separate from the zoomControl, call the - // parent method so we don't leave behind an empty container - return L.Control.prototype.removeFrom.call(this, map); - } - }, - - addLoader: function(id) { - this._dataLoaders[id] = true; - if (this.options.delayIndicator && !this.delayIndicatorTimeout) { - // If we are delaying showing the indicator and we're not - // already waiting for that delay, set up a timeout. - var that = this; - this.delayIndicatorTimeout = setTimeout(function () { - that.updateIndicator(); - that.delayIndicatorTimeout = null; - }, this.options.delayIndicator); - } - else { - // Otherwise show the indicator immediately - this.updateIndicator(); - } - }, - - removeLoader: function(id) { - delete this._dataLoaders[id]; - this.updateIndicator(); - - // If removing this loader means we're in no danger of loading, - // clear the timeout. This prevents old delays from instantly - // triggering the indicator. - if (this.options.delayIndicator && this.delayIndicatorTimeout && !this.isLoading()) { - clearTimeout(this.delayIndicatorTimeout); - this.delayIndicatorTimeout = null; - } - }, - - updateIndicator: function() { - if (this.isLoading()) { - this._showIndicator(); - } - else { - this._hideIndicator(); - } - }, - - isLoading: function() { - return this._countLoaders() > 0; - }, - - _countLoaders: function() { - var size = 0, key; - for (key in this._dataLoaders) { - if (this._dataLoaders.hasOwnProperty(key)) size++; - } - return size; - }, - - _showIndicator: function() { - // Show loading indicator - L.DomUtil.addClass(this._indicator, 'is-loading'); - L.DomUtil.addClass(this._indicatorContainer, 'is-loading'); - - // If zoomControl exists, make the zoom-out button not last - if (!this.options.separate) { - if (this.zoomControl instanceof L.Control.Zoom) { - L.DomUtil.removeClass(this._getLastControlButton(), 'leaflet-bar-part-bottom'); - } - else if (typeof L.Control.Zoomslider === 'function' && this.zoomControl instanceof L.Control.Zoomslider) { - L.DomUtil.removeClass(this.zoomControl._ui.zoomOut, 'leaflet-bar-part-bottom'); - } - } - }, - - _hideIndicator: function() { - // Hide loading indicator - L.DomUtil.removeClass(this._indicator, 'is-loading'); - L.DomUtil.removeClass(this._indicatorContainer, 'is-loading'); - - // If zoomControl exists, make the zoom-out button last - if (!this.options.separate) { - if (this.zoomControl instanceof L.Control.Zoom) { - L.DomUtil.addClass(this._getLastControlButton(), 'leaflet-bar-part-bottom'); - } - else if (typeof L.Control.Zoomslider === 'function' && this.zoomControl instanceof L.Control.Zoomslider) { - L.DomUtil.addClass(this.zoomControl._ui.zoomOut, 'leaflet-bar-part-bottom'); - } - } - }, - - _getLastControlButton: function() { - var container = this.zoomControl._container, - index = container.children.length - 1; - - // Find the last visible control button that is not our loading - // indicator - while (index > 0) { - var button = container.children[index]; - if (!(this._indicator === button || button.offsetWidth === 0 || button.offsetHeight === 0)) { - break; - } - index--; - } - - return container.children[index]; - }, - - _handleLoading: function(e) { - this.addLoader(this.getEventId(e)); - }, - - _handleBaseLayerChange: function (e) { - var that = this; - - // Check for a target 'layer' that contains multiple layers, such as - // L.LayerGroup. This will happen if you have an L.LayerGroup in an - // L.Control.Layers. - if (e.layer && e.layer.eachLayer && typeof e.layer.eachLayer === 'function') { - e.layer.eachLayer(function (layer) { - that._handleBaseLayerChange({ layer: layer }); - }); - } - else { - // If we're changing to a canvas layer, don't handle loading - // as canvas layers will not fire load events. - if (!(L.TileLayer.Canvas && e.layer instanceof L.TileLayer.Canvas)) { - that._handleLoading(e); - } - } - }, - - _handleLoad: function(e) { - this.removeLoader(this.getEventId(e)); - }, - - getEventId: function(e) { - if (e.id) { - return e.id; - } - else if (e.layer) { - return e.layer._leaflet_id; - } - return e.target._leaflet_id; - }, - - _layerAdd: function(e) { - if (!e.layer || !e.layer.on) return - try { - e.layer.on({ - loading: this._handleLoading, - load: this._handleLoad - }, this); - } - catch (exception) { - console.warn('L.Control.Loading: Tried and failed to add ' + - ' event handlers to layer', e.layer); - console.warn('L.Control.Loading: Full details', exception); - } - }, - - _layerRemove: function(e) { - if (!e.layer || !e.layer.off) return; - try { - e.layer.off({ - loading: this._handleLoading, - load: this._handleLoad - }, this); - } - catch (exception) { - console.warn('L.Control.Loading: Tried and failed to remove ' + - 'event handlers from layer', e.layer); - console.warn('L.Control.Loading: Full details', exception); - } - }, - - _addLayerListeners: function(map) { - // Add listeners for begin and end of load to any layers already on the - // map - map.eachLayer(function(layer) { - if (!layer.on) return; - layer.on({ - loading: this._handleLoading, - load: this._handleLoad - }, this); - }, this); - - // When a layer is added to the map, add listeners for begin and end - // of load - map.on('layeradd', this._layerAdd, this); - map.on('layerremove', this._layerRemove, this); - }, - - _removeLayerListeners: function(map) { - // Remove listeners for begin and end of load from all layers - map.eachLayer(function(layer) { - if (!layer.off) return; - layer.off({ - loading: this._handleLoading, - load: this._handleLoad - }, this); - }, this); - - // Remove layeradd/layerremove listener from map - map.off('layeradd', this._layerAdd, this); - map.off('layerremove', this._layerRemove, this); - }, - - _addMapListeners: function(map) { - // Add listeners to the map for (custom) dataloading and dataload - // events, eg, for AJAX calls that affect the map but will not be - // reflected in the above layer events. - map.on({ - baselayerchange: this._handleBaseLayerChange, - dataloading: this._handleLoading, - dataload: this._handleLoad, - layerremove: this._handleLoad - }, this); - }, - - _removeMapListeners: function(map) { - map.off({ - baselayerchange: this._handleBaseLayerChange, - dataloading: this._handleLoading, - dataload: this._handleLoad, - layerremove: this._handleLoad - }, this); - } - }); - - L.Map.addInitHook(function () { - if (this.options.loadingControl) { - this.loadingControl = new L.Control.Loading(); - this.addControl(this.loadingControl); - } - }); - - L.Control.loading = function(options) { - return new L.Control.Loading(options); - }; - } - - if (typeof define === 'function' && define.amd) { - // Try to add leaflet.loading to Leaflet using AMD - define(['leaflet'], function (L) { - defineLeafletLoading(L); - }); - } - else { - // Else use the global L - defineLeafletLoading(L); - } - -})(); diff --git a/assets/www/js/vendor/leaflet.markercluster.js b/assets/www/js/vendor/leaflet.markercluster.js deleted file mode 100644 index c3fa30e302e1d3e403e867fb79c4c870c8b63237..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/leaflet.markercluster.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - Leaflet.markercluster, Provides Beautiful Animated Marker Clustering functionality for Leaflet, a JS library for interactive maps. - https://github.com/Leaflet/Leaflet.markercluster - (c) 2012-2013, Dave Leaver, smartrak -*/ -!function(t,e,i){L.MarkerClusterGroup=L.FeatureGroup.extend({options:{maxClusterRadius:80,iconCreateFunction:null,spiderfyOnMaxZoom:!0,showCoverageOnHover:!0,zoomToBoundsOnClick:!0,singleMarkerMode:!1,disableClusteringAtZoom:null,removeOutsideVisibleBounds:!0,animate:!0,animateAddingMarkers:!1,spiderfyDistanceMultiplier:1,spiderLegPolylineOptions:{weight:1.5,color:"#222",opacity:.5},chunkedLoading:!1,chunkInterval:200,chunkDelay:50,chunkProgress:null,polygonOptions:{}},initialize:function(t){L.Util.setOptions(this,t),this.options.iconCreateFunction||(this.options.iconCreateFunction=this._defaultIconCreateFunction),this._featureGroup=L.featureGroup(),this._featureGroup.on(L.FeatureGroup.EVENTS,this._propagateEvent,this),this._nonPointGroup=L.featureGroup(),this._nonPointGroup.on(L.FeatureGroup.EVENTS,this._propagateEvent,this),this._inZoomAnimation=0,this._needsClustering=[],this._needsRemoving=[],this._currentShownBounds=null,this._queue=[];var e=L.DomUtil.TRANSITION&&this.options.animate;L.extend(this,e?this._withAnimation:this._noAnimation),this._markerCluster=e?L.MarkerCluster:L.MarkerClusterNonAnimated},addLayer:function(t){if(t instanceof L.LayerGroup){var e=[];for(var i in t._layers)e.push(t._layers[i]);return this.addLayers(e)}if(!t.getLatLng)return this._nonPointGroup.addLayer(t),this;if(!this._map)return this._needsClustering.push(t),this;if(this.hasLayer(t))return this;this._unspiderfy&&this._unspiderfy(),this._addLayer(t,this._maxZoom),this._topClusterLevel._recalculateBounds();var n=t,s=this._map.getZoom();if(t.__parent)for(;n.__parent._zoom>=s;)n=n.__parent;return this._currentShownBounds.contains(n.getLatLng())&&(this.options.animateAddingMarkers?this._animationAddLayer(t,n):this._animationAddLayerNonAnimated(t,n)),this},removeLayer:function(t){if(t instanceof L.LayerGroup){var e=[];for(var i in t._layers)e.push(t._layers[i]);return this.removeLayers(e)}return t.getLatLng?this._map?t.__parent?(this._unspiderfy&&(this._unspiderfy(),this._unspiderfyLayer(t)),this._removeLayer(t,!0),this._topClusterLevel._recalculateBounds(),this._featureGroup.hasLayer(t)&&(this._featureGroup.removeLayer(t),t.clusterShow&&t.clusterShow()),this):this:(!this._arraySplice(this._needsClustering,t)&&this.hasLayer(t)&&this._needsRemoving.push(t),this):(this._nonPointGroup.removeLayer(t),this)},addLayers:function(t){var e,i,n,s,r=this._featureGroup,o=this._nonPointGroup,a=this.options.chunkedLoading,h=this.options.chunkInterval,u=this.options.chunkProgress;if(this._map){var _=0,l=(new Date).getTime(),d=L.bind(function(){for(var e=(new Date).getTime();_<t.length;_++){if(a&&0===_%200){var i=(new Date).getTime()-e;if(i>h)break}if(s=t[_],s.getLatLng){if(!this.hasLayer(s)&&(this._addLayer(s,this._maxZoom),s.__parent&&2===s.__parent.getChildCount())){var n=s.__parent.getAllChildMarkers(),c=n[0]===s?n[1]:n[0];r.removeLayer(c)}}else o.addLayer(s)}u&&u(_,t.length,(new Date).getTime()-l),_===t.length?(this._topClusterLevel._recalculateBounds(),this._featureGroup.eachLayer(function(t){t instanceof L.MarkerCluster&&t._iconNeedsUpdate&&t._updateIcon()}),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds)):setTimeout(d,this.options.chunkDelay)},this);d()}else{for(e=[],i=0,n=t.length;n>i;i++)s=t[i],s.getLatLng?this.hasLayer(s)||e.push(s):o.addLayer(s);this._needsClustering=this._needsClustering.concat(e)}return this},removeLayers:function(t){var e,i,n,s=this._featureGroup,r=this._nonPointGroup;if(!this._map){for(e=0,i=t.length;i>e;e++)n=t[e],this._arraySplice(this._needsClustering,n),r.removeLayer(n),this.hasLayer(n)&&this._needsRemoving.push(n);return this}if(this._unspiderfy)for(this._unspiderfy(),e=0,i=t.length;i>e;e++)n=t[e],this._unspiderfyLayer(n);for(e=0,i=t.length;i>e;e++)n=t[e],n.__parent?(this._removeLayer(n,!0,!0),s.hasLayer(n)&&(s.removeLayer(n),n.clusterShow&&n.clusterShow())):r.removeLayer(n);return this._topClusterLevel._recalculateBounds(),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds),s.eachLayer(function(t){t instanceof L.MarkerCluster&&t._updateIcon()}),this},clearLayers:function(){return this._map||(this._needsClustering=[],delete this._gridClusters,delete this._gridUnclustered),this._noanimationUnspiderfy&&this._noanimationUnspiderfy(),this._featureGroup.clearLayers(),this._nonPointGroup.clearLayers(),this.eachLayer(function(t){delete t.__parent}),this._map&&this._generateInitialClusters(),this},getBounds:function(){var t=new L.LatLngBounds;this._topClusterLevel&&t.extend(this._topClusterLevel._bounds);for(var e=this._needsClustering.length-1;e>=0;e--)t.extend(this._needsClustering[e].getLatLng());return t.extend(this._nonPointGroup.getBounds()),t},eachLayer:function(t,e){var i,n=this._needsClustering.slice();for(this._topClusterLevel&&this._topClusterLevel.getAllChildMarkers(n),i=n.length-1;i>=0;i--)t.call(e,n[i]);this._nonPointGroup.eachLayer(t,e)},getLayers:function(){var t=[];return this.eachLayer(function(e){t.push(e)}),t},getLayer:function(t){var e=null;return t=parseInt(t,10),this.eachLayer(function(i){L.stamp(i)===t&&(e=i)}),e},hasLayer:function(t){if(!t)return!1;var e,i=this._needsClustering;for(e=i.length-1;e>=0;e--)if(i[e]===t)return!0;for(i=this._needsRemoving,e=i.length-1;e>=0;e--)if(i[e]===t)return!1;return!(!t.__parent||t.__parent._group!==this)||this._nonPointGroup.hasLayer(t)},zoomToShowLayer:function(t,e){"function"!=typeof e&&(e=function(){});var i=function(){!t._icon&&!t.__parent._icon||this._inZoomAnimation||(this._map.off("moveend",i,this),this.off("animationend",i,this),t._icon?e():t.__parent._icon&&(this.once("spiderfied",e,this),t.__parent.spiderfy()))};if(t._icon&&this._map.getBounds().contains(t.getLatLng()))e();else if(t.__parent._zoom<this._map.getZoom())this._map.on("moveend",i,this),this._map.panTo(t.getLatLng());else{var n=function(){this._map.off("movestart",n,this),n=null};this._map.on("movestart",n,this),this._map.on("moveend",i,this),this.on("animationend",i,this),t.__parent.zoomToBounds(),n&&i.call(this)}},onAdd:function(t){this._map=t;var e,i,n;if(!isFinite(this._map.getMaxZoom()))throw"Map has no maxZoom specified";for(this._featureGroup.onAdd(t),this._nonPointGroup.onAdd(t),this._gridClusters||this._generateInitialClusters(),this._maxLat=t.options.crs.projection.MAX_LATITUDE,e=0,i=this._needsRemoving.length;i>e;e++)n=this._needsRemoving[e],this._removeLayer(n,!0);this._needsRemoving=[],this._zoom=this._map.getZoom(),this._currentShownBounds=this._getExpandedVisibleBounds(),this._map.on("zoomend",this._zoomEnd,this),this._map.on("moveend",this._moveEnd,this),this._spiderfierOnAdd&&this._spiderfierOnAdd(),this._bindEvents(),i=this._needsClustering,this._needsClustering=[],this.addLayers(i)},onRemove:function(t){t.off("zoomend",this._zoomEnd,this),t.off("moveend",this._moveEnd,this),this._unbindEvents(),this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim",""),this._spiderfierOnRemove&&this._spiderfierOnRemove(),delete this._maxLat,this._hideCoverage(),this._featureGroup.onRemove(t),this._nonPointGroup.onRemove(t),this._featureGroup.clearLayers(),this._map=null},getVisibleParent:function(t){for(var e=t;e&&!e._icon;)e=e.__parent;return e||null},_arraySplice:function(t,e){for(var i=t.length-1;i>=0;i--)if(t[i]===e)return t.splice(i,1),!0},_removeFromGridUnclustered:function(t,e){for(var i=this._map,n=this._gridUnclustered;e>=0&&n[e].removeObject(t,i.project(t.getLatLng(),e));e--);},_removeLayer:function(t,e,i){var n=this._gridClusters,s=this._gridUnclustered,r=this._featureGroup,o=this._map;e&&this._removeFromGridUnclustered(t,this._maxZoom);var a,h=t.__parent,u=h._markers;for(this._arraySplice(u,t);h&&(h._childCount--,h._boundsNeedUpdate=!0,!(h._zoom<0));)e&&h._childCount<=1?(a=h._markers[0]===t?h._markers[1]:h._markers[0],n[h._zoom].removeObject(h,o.project(h._cLatLng,h._zoom)),s[h._zoom].addObject(a,o.project(a.getLatLng(),h._zoom)),this._arraySplice(h.__parent._childClusters,h),h.__parent._markers.push(a),a.__parent=h.__parent,h._icon&&(r.removeLayer(h),i||r.addLayer(a))):i&&h._icon||h._updateIcon(),h=h.__parent;delete t.__parent},_isOrIsParent:function(t,e){for(;e;){if(t===e)return!0;e=e.parentNode}return!1},_propagateEvent:function(t){if(t.layer instanceof L.MarkerCluster){if(t.originalEvent&&this._isOrIsParent(t.layer._icon,t.originalEvent.relatedTarget))return;t.type="cluster"+t.type}this.fire(t.type,t)},_defaultIconCreateFunction:function(t){var e=t.getChildCount(),i=" marker-cluster-";return i+=10>e?"small":100>e?"medium":"large",new L.DivIcon({html:"<div><span>"+e+"</span></div>",className:"marker-cluster"+i,iconSize:new L.Point(40,40)})},_bindEvents:function(){var t=this._map,e=this.options.spiderfyOnMaxZoom,i=this.options.showCoverageOnHover,n=this.options.zoomToBoundsOnClick;(e||n)&&this.on("clusterclick",this._zoomOrSpiderfy,this),i&&(this.on("clustermouseover",this._showCoverage,this),this.on("clustermouseout",this._hideCoverage,this),t.on("zoomend",this._hideCoverage,this))},_zoomOrSpiderfy:function(t){for(var e=t.layer,i=e;1===i._childClusters.length;)i=i._childClusters[0];i._zoom===this._maxZoom&&i._childCount===e._childCount?this.options.spiderfyOnMaxZoom&&e.spiderfy():this.options.zoomToBoundsOnClick&&e.zoomToBounds(),t.originalEvent&&13===t.originalEvent.keyCode&&this._map._container.focus()},_showCoverage:function(t){var e=this._map;this._inZoomAnimation||(this._shownPolygon&&e.removeLayer(this._shownPolygon),t.layer.getChildCount()>2&&t.layer!==this._spiderfied&&(this._shownPolygon=new L.Polygon(t.layer.getConvexHull(),this.options.polygonOptions),e.addLayer(this._shownPolygon)))},_hideCoverage:function(){this._shownPolygon&&(this._map.removeLayer(this._shownPolygon),this._shownPolygon=null)},_unbindEvents:function(){var t=this.options.spiderfyOnMaxZoom,e=this.options.showCoverageOnHover,i=this.options.zoomToBoundsOnClick,n=this._map;(t||i)&&this.off("clusterclick",this._zoomOrSpiderfy,this),e&&(this.off("clustermouseover",this._showCoverage,this),this.off("clustermouseout",this._hideCoverage,this),n.off("zoomend",this._hideCoverage,this))},_zoomEnd:function(){this._map&&(this._mergeSplitClusters(),this._zoom=this._map._zoom,this._currentShownBounds=this._getExpandedVisibleBounds())},_moveEnd:function(){if(!this._inZoomAnimation){var t=this._getExpandedVisibleBounds();this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,this._zoom,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._map._zoom,t),this._currentShownBounds=t}},_generateInitialClusters:function(){var t=this._map.getMaxZoom(),e=this.options.maxClusterRadius,i=e;"function"!=typeof e&&(i=function(){return e}),this.options.disableClusteringAtZoom&&(t=this.options.disableClusteringAtZoom-1),this._maxZoom=t,this._gridClusters={},this._gridUnclustered={};for(var n=t;n>=0;n--)this._gridClusters[n]=new L.DistanceGrid(i(n)),this._gridUnclustered[n]=new L.DistanceGrid(i(n));this._topClusterLevel=new this._markerCluster(this,-1)},_addLayer:function(t,e){var i,n,s=this._gridClusters,r=this._gridUnclustered;for(this.options.singleMarkerMode&&this._overrideMarkerIcon(t);e>=0;e--){i=this._map.project(t.getLatLng(),e);var o=s[e].getNearObject(i);if(o)return o._addChild(t),t.__parent=o,void 0;if(o=r[e].getNearObject(i)){var a=o.__parent;a&&this._removeLayer(o,!1);var h=new this._markerCluster(this,e,o,t);s[e].addObject(h,this._map.project(h._cLatLng,e)),o.__parent=h,t.__parent=h;var u=h;for(n=e-1;n>a._zoom;n--)u=new this._markerCluster(this,n,u),s[n].addObject(u,this._map.project(o.getLatLng(),n));return a._addChild(u),this._removeFromGridUnclustered(o,e),void 0}r[e].addObject(t,i)}this._topClusterLevel._addChild(t),t.__parent=this._topClusterLevel},_enqueue:function(t){this._queue.push(t),this._queueTimeout||(this._queueTimeout=setTimeout(L.bind(this._processQueue,this),300))},_processQueue:function(){for(var t=0;t<this._queue.length;t++)this._queue[t].call(this);this._queue.length=0,clearTimeout(this._queueTimeout),this._queueTimeout=null},_mergeSplitClusters:function(){this._processQueue(),this._zoom<this._map._zoom&&this._currentShownBounds.intersects(this._getExpandedVisibleBounds())?(this._animationStart(),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,this._zoom,this._getExpandedVisibleBounds()),this._animationZoomIn(this._zoom,this._map._zoom)):this._zoom>this._map._zoom?(this._animationStart(),this._animationZoomOut(this._zoom,this._map._zoom)):this._moveEnd()},_getExpandedVisibleBounds:function(){return this.options.removeOutsideVisibleBounds?L.Browser.mobile?this._checkBoundsMaxLat(this._map.getBounds()):this._checkBoundsMaxLat(this._map.getBounds().pad(1)):this._mapBoundsInfinite},_checkBoundsMaxLat:function(t){var e=this._maxLat;return e!==i&&(t.getNorth()>=e&&(t._northEast.lat=1/0),t.getSouth()<=-e&&(t._southWest.lat=-1/0)),t},_animationAddLayerNonAnimated:function(t,e){if(e===t)this._featureGroup.addLayer(t);else if(2===e._childCount){e._addToMap();var i=e.getAllChildMarkers();this._featureGroup.removeLayer(i[0]),this._featureGroup.removeLayer(i[1])}else e._updateIcon()},_overrideMarkerIcon:function(t){var e=t.options.icon=this.options.iconCreateFunction({getChildCount:function(){return 1},getAllChildMarkers:function(){return[t]}});return e}}),L.MarkerClusterGroup.include({_mapBoundsInfinite:new L.LatLngBounds(new L.LatLng(-1/0,-1/0),new L.LatLng(1/0,1/0))}),L.MarkerClusterGroup.include({_noAnimation:{_animationStart:function(){},_animationZoomIn:function(t,e){this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds()),this.fire("animationend")},_animationZoomOut:function(t,e){this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds()),this.fire("animationend")},_animationAddLayer:function(t,e){this._animationAddLayerNonAnimated(t,e)}},_withAnimation:{_animationStart:function(){this._map._mapPane.className+=" leaflet-cluster-anim",this._inZoomAnimation++},_animationZoomIn:function(t,e){var i,n=this._getExpandedVisibleBounds(),s=this._featureGroup;this._topClusterLevel._recursively(n,t,0,function(r){var o,a=r._latlng,h=r._markers;for(n.contains(a)||(a=null),r._isSingleParent()&&t+1===e?(s.removeLayer(r),r._recursivelyAddChildrenToMap(null,e,n)):(r.clusterHide(),r._recursivelyAddChildrenToMap(a,e,n)),i=h.length-1;i>=0;i--)o=h[i],n.contains(o._latlng)||s.removeLayer(o)}),this._forceLayout(),this._topClusterLevel._recursivelyBecomeVisible(n,e),s.eachLayer(function(t){t instanceof L.MarkerCluster||!t._icon||t.clusterShow()}),this._topClusterLevel._recursively(n,t,e,function(t){t._recursivelyRestoreChildPositions(e)}),this._enqueue(function(){this._topClusterLevel._recursively(n,t,0,function(t){s.removeLayer(t),t.clusterShow()}),this._animationEnd()})},_animationZoomOut:function(t,e){this._animationZoomOutSingle(this._topClusterLevel,t-1,e),this._topClusterLevel._recursivelyAddChildrenToMap(null,e,this._getExpandedVisibleBounds()),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,t,this._getExpandedVisibleBounds())},_animationAddLayer:function(t,e){var i=this,n=this._featureGroup;n.addLayer(t),e!==t&&(e._childCount>2?(e._updateIcon(),this._forceLayout(),this._animationStart(),t._setPos(this._map.latLngToLayerPoint(e.getLatLng())),t.clusterHide(),this._enqueue(function(){n.removeLayer(t),t.clusterShow(),i._animationEnd()})):(this._forceLayout(),i._animationStart(),i._animationZoomOutSingle(e,this._map.getMaxZoom(),this._map.getZoom())))}},_animationZoomOutSingle:function(t,e,i){var n=this._getExpandedVisibleBounds();t._recursivelyAnimateChildrenInAndAddSelfToMap(n,e+1,i);var s=this;this._forceLayout(),t._recursivelyBecomeVisible(n,i),this._enqueue(function(){if(1===t._childCount){var r=t._markers[0];r.setLatLng(r.getLatLng()),r.clusterShow&&r.clusterShow()}else t._recursively(n,i,0,function(t){t._recursivelyRemoveChildrenFromMap(n,e+1)});s._animationEnd()})},_animationEnd:function(){this._map&&(this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim","")),this._inZoomAnimation--,this.fire("animationend")},_forceLayout:function(){L.Util.falseFn(e.body.offsetWidth)}}),L.markerClusterGroup=function(t){return new L.MarkerClusterGroup(t)},L.MarkerCluster=L.Marker.extend({initialize:function(t,e,i,n){L.Marker.prototype.initialize.call(this,i?i._cLatLng||i.getLatLng():new L.LatLng(0,0),{icon:this}),this._group=t,this._zoom=e,this._markers=[],this._childClusters=[],this._childCount=0,this._iconNeedsUpdate=!0,this._boundsNeedUpdate=!0,this._bounds=new L.LatLngBounds,i&&this._addChild(i),n&&this._addChild(n)},getAllChildMarkers:function(t){t=t||[];for(var e=this._childClusters.length-1;e>=0;e--)this._childClusters[e].getAllChildMarkers(t);for(var i=this._markers.length-1;i>=0;i--)t.push(this._markers[i]);return t},getChildCount:function(){return this._childCount},zoomToBounds:function(){for(var t,e=this._childClusters.slice(),i=this._group._map,n=i.getBoundsZoom(this._bounds),s=this._zoom+1,r=i.getZoom();e.length>0&&n>s;){s++;var o=[];for(t=0;t<e.length;t++)o=o.concat(e[t]._childClusters);e=o}n>s?this._group._map.setView(this._latlng,s):r>=n?this._group._map.setView(this._latlng,r+1):this._group._map.fitBounds(this._bounds)},getBounds:function(){var t=new L.LatLngBounds;return t.extend(this._bounds),t},_updateIcon:function(){this._iconNeedsUpdate=!0,this._icon&&this.setIcon(this)},createIcon:function(){return this._iconNeedsUpdate&&(this._iconObj=this._group.options.iconCreateFunction(this),this._iconNeedsUpdate=!1),this._iconObj.createIcon()},createShadow:function(){return this._iconObj.createShadow()},_addChild:function(t,e){this._iconNeedsUpdate=!0,this._boundsNeedUpdate=!0,this._setClusterCenter(t),t instanceof L.MarkerCluster?(e||(this._childClusters.push(t),t.__parent=this),this._childCount+=t._childCount):(e||this._markers.push(t),this._childCount++),this.__parent&&this.__parent._addChild(t,!0)},_setClusterCenter:function(t){this._cLatLng||(this._cLatLng=t._cLatLng||t._latlng)},_resetBounds:function(){var t=this._bounds;t._southWest&&(t._southWest.lat=1/0,t._southWest.lng=1/0),t._northEast&&(t._northEast.lat=-1/0,t._northEast.lng=-1/0)},_recalculateBounds:function(){var t,e,i,n,s=this._markers,r=this._childClusters,o=0,a=0,h=this._childCount;if(0!==h){for(this._resetBounds(),t=0;t<s.length;t++)i=s[t]._latlng,this._bounds.extend(i),o+=i.lat,a+=i.lng;for(t=0;t<r.length;t++)e=r[t],e._boundsNeedUpdate&&e._recalculateBounds(),this._bounds.extend(e._bounds),i=e._wLatLng,n=e._childCount,o+=i.lat*n,a+=i.lng*n;this._latlng=this._wLatLng=new L.LatLng(o/h,a/h),this._boundsNeedUpdate=!1}},_addToMap:function(t){t&&(this._backupLatlng=this._latlng,this.setLatLng(t)),this._group._featureGroup.addLayer(this)},_recursivelyAnimateChildrenIn:function(t,e,i){this._recursively(t,0,i-1,function(t){var i,n,s=t._markers;for(i=s.length-1;i>=0;i--)n=s[i],n._icon&&(n._setPos(e),n.clusterHide())},function(t){var i,n,s=t._childClusters;for(i=s.length-1;i>=0;i--)n=s[i],n._icon&&(n._setPos(e),n.clusterHide())})},_recursivelyAnimateChildrenInAndAddSelfToMap:function(t,e,i){this._recursively(t,i,0,function(n){n._recursivelyAnimateChildrenIn(t,n._group._map.latLngToLayerPoint(n.getLatLng()).round(),e),n._isSingleParent()&&e-1===i?(n.clusterShow(),n._recursivelyRemoveChildrenFromMap(t,e)):n.clusterHide(),n._addToMap()})},_recursivelyBecomeVisible:function(t,e){this._recursively(t,0,e,null,function(t){t.clusterShow()})},_recursivelyAddChildrenToMap:function(t,e,i){this._recursively(i,-1,e,function(n){if(e!==n._zoom)for(var s=n._markers.length-1;s>=0;s--){var r=n._markers[s];i.contains(r._latlng)&&(t&&(r._backupLatlng=r.getLatLng(),r.setLatLng(t),r.clusterHide&&r.clusterHide()),n._group._featureGroup.addLayer(r))}},function(e){e._addToMap(t)})},_recursivelyRestoreChildPositions:function(t){for(var e=this._markers.length-1;e>=0;e--){var i=this._markers[e];i._backupLatlng&&(i.setLatLng(i._backupLatlng),delete i._backupLatlng)}if(t-1===this._zoom)for(var n=this._childClusters.length-1;n>=0;n--)this._childClusters[n]._restorePosition();else for(var s=this._childClusters.length-1;s>=0;s--)this._childClusters[s]._recursivelyRestoreChildPositions(t)},_restorePosition:function(){this._backupLatlng&&(this.setLatLng(this._backupLatlng),delete this._backupLatlng)},_recursivelyRemoveChildrenFromMap:function(t,e,i){var n,s;this._recursively(t,-1,e-1,function(t){for(s=t._markers.length-1;s>=0;s--)n=t._markers[s],i&&i.contains(n._latlng)||(t._group._featureGroup.removeLayer(n),n.clusterShow&&n.clusterShow())},function(t){for(s=t._childClusters.length-1;s>=0;s--)n=t._childClusters[s],i&&i.contains(n._latlng)||(t._group._featureGroup.removeLayer(n),n.clusterShow&&n.clusterShow())})},_recursively:function(t,e,i,n,s){var r,o,a=this._childClusters,h=this._zoom;if(e>h)for(r=a.length-1;r>=0;r--)o=a[r],t.intersects(o._bounds)&&o._recursively(t,e,i,n,s);else if(n&&n(this),s&&this._zoom===i&&s(this),i>h)for(r=a.length-1;r>=0;r--)o=a[r],t.intersects(o._bounds)&&o._recursively(t,e,i,n,s)},_isSingleParent:function(){return this._childClusters.length>0&&this._childClusters[0]._childCount===this._childCount}}),L.Marker.include({clusterHide:function(){return this.options.opacityWhenUnclustered=this.options.opacity||1,this.setOpacity(0)},clusterShow:function(){var t=this.setOpacity(this.options.opacity||this.options.opacityWhenUnclustered);return delete this.options.opacityWhenUnclustered,t}}),L.DistanceGrid=function(t){this._cellSize=t,this._sqCellSize=t*t,this._grid={},this._objectPoint={}},L.DistanceGrid.prototype={addObject:function(t,e){var i=this._getCoord(e.x),n=this._getCoord(e.y),s=this._grid,r=s[n]=s[n]||{},o=r[i]=r[i]||[],a=L.Util.stamp(t);this._objectPoint[a]=e,o.push(t)},updateObject:function(t,e){this.removeObject(t),this.addObject(t,e)},removeObject:function(t,e){var i,n,s=this._getCoord(e.x),r=this._getCoord(e.y),o=this._grid,a=o[r]=o[r]||{},h=a[s]=a[s]||[];for(delete this._objectPoint[L.Util.stamp(t)],i=0,n=h.length;n>i;i++)if(h[i]===t)return h.splice(i,1),1===n&&delete a[s],!0},eachObject:function(t,e){var i,n,s,r,o,a,h,u=this._grid;for(i in u){o=u[i];for(n in o)for(a=o[n],s=0,r=a.length;r>s;s++)h=t.call(e,a[s]),h&&(s--,r--)}},getNearObject:function(t){var e,i,n,s,r,o,a,h,u=this._getCoord(t.x),_=this._getCoord(t.y),l=this._objectPoint,d=this._sqCellSize,c=null;for(e=_-1;_+1>=e;e++)if(s=this._grid[e])for(i=u-1;u+1>=i;i++)if(r=s[i])for(n=0,o=r.length;o>n;n++)a=r[n],h=this._sqDist(l[L.Util.stamp(a)],t),d>h&&(d=h,c=a);return c},_getCoord:function(t){return Math.floor(t/this._cellSize)},_sqDist:function(t,e){var i=e.x-t.x,n=e.y-t.y;return i*i+n*n}},function(){L.QuickHull={getDistant:function(t,e){var i=e[1].lat-e[0].lat,n=e[0].lng-e[1].lng;return n*(t.lat-e[0].lat)+i*(t.lng-e[0].lng)},findMostDistantPointFromBaseLine:function(t,e){var i,n,s,r=0,o=null,a=[];for(i=e.length-1;i>=0;i--)n=e[i],s=this.getDistant(n,t),s>0&&(a.push(n),s>r&&(r=s,o=n));return{maxPoint:o,newPoints:a}},buildConvexHull:function(t,e){var i=[],n=this.findMostDistantPointFromBaseLine(t,e);return n.maxPoint?(i=i.concat(this.buildConvexHull([t[0],n.maxPoint],n.newPoints)),i=i.concat(this.buildConvexHull([n.maxPoint,t[1]],n.newPoints))):[t[0]]},getConvexHull:function(t){var e,i=!1,n=!1,s=!1,r=!1,o=null,a=null,h=null,u=null,_=null,l=null;for(e=t.length-1;e>=0;e--){var d=t[e];(i===!1||d.lat>i)&&(o=d,i=d.lat),(n===!1||d.lat<n)&&(a=d,n=d.lat),(s===!1||d.lng>s)&&(h=d,s=d.lng),(r===!1||d.lng<r)&&(u=d,r=d.lng)}n!==i?(l=a,_=o):(l=u,_=h);var c=[].concat(this.buildConvexHull([l,_],t),this.buildConvexHull([_,l],t));return c}}}(),L.MarkerCluster.include({getConvexHull:function(){var t,e,i=this.getAllChildMarkers(),n=[];for(e=i.length-1;e>=0;e--)t=i[e].getLatLng(),n.push(t);return L.QuickHull.getConvexHull(n)}}),L.MarkerCluster.include({_2PI:2*Math.PI,_circleFootSeparation:25,_circleStartAngle:Math.PI/6,_spiralFootSeparation:28,_spiralLengthStart:11,_spiralLengthFactor:5,_circleSpiralSwitchover:9,spiderfy:function(){if(this._group._spiderfied!==this&&!this._group._inZoomAnimation){var t,e=this.getAllChildMarkers(),i=this._group,n=i._map,s=n.latLngToLayerPoint(this._latlng);this._group._unspiderfy(),this._group._spiderfied=this,e.length>=this._circleSpiralSwitchover?t=this._generatePointsSpiral(e.length,s):(s.y+=10,t=this._generatePointsCircle(e.length,s)),this._animationSpiderfy(e,t)}},unspiderfy:function(t){this._group._inZoomAnimation||(this._animationUnspiderfy(t),this._group._spiderfied=null)},_generatePointsCircle:function(t,e){var i,n,s=this._group.options.spiderfyDistanceMultiplier*this._circleFootSeparation*(2+t),r=s/this._2PI,o=this._2PI/t,a=[];for(a.length=t,i=t-1;i>=0;i--)n=this._circleStartAngle+i*o,a[i]=new L.Point(e.x+r*Math.cos(n),e.y+r*Math.sin(n))._round();return a},_generatePointsSpiral:function(t,e){var i,n=this._group.options.spiderfyDistanceMultiplier,s=n*this._spiralLengthStart,r=n*this._spiralFootSeparation,o=n*this._spiralLengthFactor*this._2PI,a=0,h=[];for(h.length=t,i=t-1;i>=0;i--)a+=r/s+5e-4*i,h[i]=new L.Point(e.x+s*Math.cos(a),e.y+s*Math.sin(a))._round(),s+=o/a;return h},_noanimationUnspiderfy:function(){var t,e,i=this._group,n=i._map,s=i._featureGroup,r=this.getAllChildMarkers();for(this.setOpacity(1),e=r.length-1;e>=0;e--)t=r[e],s.removeLayer(t),t._preSpiderfyLatlng&&(t.setLatLng(t._preSpiderfyLatlng),delete t._preSpiderfyLatlng),t.setZIndexOffset&&t.setZIndexOffset(0),t._spiderLeg&&(n.removeLayer(t._spiderLeg),delete t._spiderLeg);i.fire("unspiderfied",{cluster:this,markers:r}),i._spiderfied=null}}),L.MarkerClusterNonAnimated=L.MarkerCluster.extend({_animationSpiderfy:function(t,e){var i,n,s,r,o=this._group,a=o._map,h=o._featureGroup,u=this._group.options.spiderLegPolylineOptions;for(i=0;i<t.length;i++)r=a.layerPointToLatLng(e[i]),n=t[i],s=new L.Polyline([this._latlng,r],u),a.addLayer(s),n._spiderLeg=s,n._preSpiderfyLatlng=n._latlng,n.setLatLng(r),n.setZIndexOffset&&n.setZIndexOffset(1e6),h.addLayer(n);this.setOpacity(.3),o.fire("spiderfied",{cluster:this,markers:t})},_animationUnspiderfy:function(){this._noanimationUnspiderfy()}}),L.MarkerCluster.include({_animationSpiderfy:function(t,e){var n,s,r,o,a,h,u=this,_=this._group,l=_._map,d=_._featureGroup,c=this._latlng,p=l.latLngToLayerPoint(c),f=L.Path.SVG,m=L.extend({},this._group.options.spiderLegPolylineOptions),g=m.opacity;for(g===i&&(g=L.MarkerClusterGroup.prototype.options.spiderLegPolylineOptions.opacity),f?(m.opacity=0,m.className=(m.className||"")+" leaflet-cluster-spider-leg"):m.opacity=g,n=0;n<t.length;n++)s=t[n],h=l.layerPointToLatLng(e[n]),r=new L.Polyline([c,h],m),l.addLayer(r),s._spiderLeg=r,f&&(o=r._path,a=o.getTotalLength()+.1,o.style.strokeDasharray=a,o.style.strokeDashoffset=a),s.setZIndexOffset&&s.setZIndexOffset(1e6),s.clusterHide&&s.clusterHide(),d.addLayer(s),s._setPos&&s._setPos(p);for(_._forceLayout(),_._animationStart(),n=t.length-1;n>=0;n--)h=l.layerPointToLatLng(e[n]),s=t[n],s._preSpiderfyLatlng=s._latlng,s.setLatLng(h),s.clusterShow&&s.clusterShow(),f&&(r=s._spiderLeg,o=r._path,o.style.strokeDashoffset=0,r.setStyle({opacity:g}));this.setOpacity(.3),setTimeout(function(){_._animationEnd(),_.fire("spiderfied",{cluster:u,markers:t})},200)},_animationUnspiderfy:function(t){var e,i,n,s,r,o,a=this,h=this._group,u=h._map,_=h._featureGroup,l=t?u._latLngToNewLayerPoint(this._latlng,t.zoom,t.center):u.latLngToLayerPoint(this._latlng),d=this.getAllChildMarkers(),c=L.Path.SVG;for(h._animationStart(),this.setOpacity(1),i=d.length-1;i>=0;i--)e=d[i],e._preSpiderfyLatlng&&(e.setLatLng(e._preSpiderfyLatlng),delete e._preSpiderfyLatlng,o=!0,e._setPos&&(e._setPos(l),o=!1),e.clusterHide&&(e.clusterHide(),o=!1),o&&_.removeLayer(e),c&&(n=e._spiderLeg,s=n._path,r=s.getTotalLength()+.1,s.style.strokeDashoffset=r,n.setStyle({opacity:0})));setTimeout(function(){var t=0;for(i=d.length-1;i>=0;i--)e=d[i],e._spiderLeg&&t++;for(i=d.length-1;i>=0;i--)e=d[i],e._spiderLeg&&(e.clusterShow&&e.clusterShow(),e.setZIndexOffset&&e.setZIndexOffset(0),t>1&&_.removeLayer(e),u.removeLayer(e._spiderLeg),delete e._spiderLeg);h._animationEnd(),h.fire("unspiderfied",{cluster:a,markers:d})},200)}}),L.MarkerClusterGroup.include({_spiderfied:null,_spiderfierOnAdd:function(){this._map.on("click",this._unspiderfyWrapper,this),this._map.options.zoomAnimation&&this._map.on("zoomstart",this._unspiderfyZoomStart,this),this._map.on("zoomend",this._noanimationUnspiderfy,this)},_spiderfierOnRemove:function(){this._map.off("click",this._unspiderfyWrapper,this),this._map.off("zoomstart",this._unspiderfyZoomStart,this),this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._map.off("zoomend",this._noanimationUnspiderfy,this),this._noanimationUnspiderfy()},_unspiderfyZoomStart:function(){this._map&&this._map.on("zoomanim",this._unspiderfyZoomAnim,this)},_unspiderfyZoomAnim:function(t){L.DomUtil.hasClass(this._map._mapPane,"leaflet-touching")||(this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._unspiderfy(t))},_unspiderfyWrapper:function(){this._unspiderfy()},_unspiderfy:function(t){this._spiderfied&&this._spiderfied.unspiderfy(t)},_noanimationUnspiderfy:function(){this._spiderfied&&this._spiderfied._noanimationUnspiderfy()},_unspiderfyLayer:function(t){t._spiderLeg&&(this._featureGroup.removeLayer(t),t.clusterShow&&t.clusterShow(),t.setZIndexOffset&&t.setZIndexOffset(0),this._map.removeLayer(t._spiderLeg),delete t._spiderLeg)}}),L.MarkerClusterGroup.include({refreshClusters:function(t){return t?t instanceof L.MarkerClusterGroup?t=t._topClusterLevel.getAllChildMarkers():t instanceof L.LayerGroup?t=t._layers:t instanceof L.MarkerCluster?t=t.getAllChildMarkers():t instanceof L.Marker&&(t=[t]):t=this._topClusterLevel.getAllChildMarkers(),this._flagParentsIconsNeedUpdate(t),this._refreshClustersIcons(),this.options.singleMarkerMode&&this._refreshSingleMarkerModeMarkers(t),this},_flagParentsIconsNeedUpdate:function(t){var e,i;for(e in t)for(i=t[e].__parent;i;)i._iconNeedsUpdate=!0,i=i.__parent},_refreshClustersIcons:function(){this._featureGroup.eachLayer(function(t){t instanceof L.MarkerCluster&&t._iconNeedsUpdate&&t._updateIcon()})},_refreshSingleMarkerModeMarkers:function(t){var e,i;for(e in t)i=t[e],this.hasLayer(i)&&i.setIcon(this._overrideMarkerIcon(i))}}),L.Marker.include({refreshIconOptions:function(t,e){var i=this.options.icon;return L.setOptions(i,t),this.setIcon(i),e&&this.__parent&&this.__parent._group.refreshClusters(this),this}})}(window,document); \ No newline at end of file diff --git a/assets/www/js/vendor/leaflet.search.min.js b/assets/www/js/vendor/leaflet.search.min.js deleted file mode 100644 index 97facf7ae056707b251a6cc1ac773e4b8529230d..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/leaflet.search.min.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Leaflet Control Search v2.7.2 - 2017-04-08 - * - * Copyright 2017 Stefano Cudini - * stefano.cudini@gmail.com - * http://labs.easyblog.it/ - * - * Licensed under the MIT license. - * - * Demo: - * http://labs.easyblog.it/maps/leaflet-search/ - * - * Source: - * git@github.com:stefanocudini/leaflet-search.git - * - */ -!function(a){if("function"==typeof define&&define.amd)define(["leaflet"],a);else if("undefined"!=typeof module)module.exports=a(require("leaflet"));else{if("undefined"==typeof window.L)throw"Leaflet must be loaded first";a(window.L)}}(function(a){function b(a,b){var c=b.split("."),d=c.pop(),e=c.length,f=c[0],g=1;if(e>0)for(;(a=a[f])&&e>g;)f=c[g++];return a?a[d]:void 0}function c(a){return"[object Object]"===Object.prototype.toString.call(a)}return a.Control.Search=a.Control.extend({includes:a.Mixin.Events,options:{url:"",layer:null,sourceData:null,jsonpParam:null,propertyLoc:"loc",propertyName:"title",formatData:null,filterData:null,moveToLocation:null,buildTip:null,container:"",zoom:null,minLength:1,initial:!0,casesensitive:!1,autoType:!0,delayType:400,tooltipLimit:-1,tipAutoSubmit:!0,firstTipSubmit:!1,autoResize:!0,collapsed:!0,autoCollapse:!1,autoCollapseTime:1200,textErr:"Location not found",textCancel:"Cancel",textPlaceholder:"Search...",position:"topleft",hideMarkerOnCollapse:!1,marker:{icon:!1,animate:!0,circle:{radius:10,weight:3,color:"#e03",stroke:!0,fill:!1}}},initialize:function(b){a.Util.setOptions(this,b||{}),this._inputMinSize=this.options.textPlaceholder?this.options.textPlaceholder.length:10,this._layer=this.options.layer||new a.LayerGroup,this._filterData=this.options.filterData||this._defaultFilterData,this._formatData=this.options.formatData||this._defaultFormatData,this._moveToLocation=this.options.moveToLocation||this._defaultMoveToLocation,this._autoTypeTmp=this.options.autoType,this._countertips=0,this._recordsCache={},this._curReq=null},onAdd:function(b){return this._map=b,this._container=a.DomUtil.create("div","leaflet-control-search"),this._input=this._createInput(this.options.textPlaceholder,"search-input"),this._tooltip=this._createTooltip("search-tooltip"),this._cancel=this._createCancel(this.options.textCancel,"search-cancel"),this._button=this._createButton(this.options.textPlaceholder,"search-button"),this._alert=this._createAlert("search-alert"),this.options.collapsed===!1&&this.expand(this.options.collapsed),this.options.marker&&(this.options.marker instanceof a.Marker||this.options.marker instanceof a.CircleMarker?this._markerSearch=this.options.marker:c(this.options.marker)&&(this._markerSearch=new a.Control.Search.Marker([0,0],this.options.marker)),this._markerSearch._isMarkerSearch=!0),this.setLayer(this._layer),b.on({resize:this._handleAutoresize},this),this._container},addTo:function(b){return this.options.container?(this._container=this.onAdd(b),this._wrapper=a.DomUtil.get(this.options.container),this._wrapper.style.position="relative",this._wrapper.appendChild(this._container)):a.Control.prototype.addTo.call(this,b),this},onRemove:function(a){this._recordsCache={}},setLayer:function(a){return this._layer=a,this._layer.addTo(this._map),this},showAlert:function(a){a=a||this.options.textErr,this._alert.style.display="block",this._alert.innerHTML=a,clearTimeout(this.timerAlert);var b=this;return this.timerAlert=setTimeout(function(){b.hideAlert()},this.options.autoCollapseTime),this},hideAlert:function(){return this._alert.style.display="none",this},cancel:function(){return this._input.value="",this._handleKeypress({keyCode:8}),this._input.size=this._inputMinSize,this._input.focus(),this._cancel.style.display="none",this._hideTooltip(),this},expand:function(b){return b="boolean"==typeof b?b:!0,this._input.style.display="block",a.DomUtil.addClass(this._container,"search-exp"),b!==!1&&(this._input.focus(),this._map.on("dragstart click",this.collapse,this)),this.fire("search:expanded"),this},collapse:function(){return this._hideTooltip(),this.cancel(),this._alert.style.display="none",this._input.blur(),this.options.collapsed&&(this._input.style.display="none",this._cancel.style.display="none",a.DomUtil.removeClass(this._container,"search-exp"),this.options.hideMarkerOnCollapse&&this._map.removeLayer(this._markerSearch),this._map.off("dragstart click",this.collapse,this)),this.fire("search:collapsed"),this},collapseDelayed:function(){if(!this.options.autoCollapse)return this;var a=this;return clearTimeout(this.timerCollapse),this.timerCollapse=setTimeout(function(){a.collapse()},this.options.autoCollapseTime),this},collapseDelayedStop:function(){return clearTimeout(this.timerCollapse),this},_createAlert:function(b){var c=a.DomUtil.create("div",b,this._container);return c.style.display="none",a.DomEvent.on(c,"click",a.DomEvent.stop,this).on(c,"click",this.hideAlert,this),c},_createInput:function(b,c){var d=a.DomUtil.create("label",c,this._container),e=a.DomUtil.create("input",c,this._container);return e.type="text",e.size=this._inputMinSize,e.value="",e.autocomplete="off",e.autocorrect="off",e.autocapitalize="off",e.placeholder=b,e.style.display="none",e.role="search",e.id=e.role+e.type+e.size,d.htmlFor=e.id,d.style.display="none",d.value=b,a.DomEvent.disableClickPropagation(e).on(e,"keydown",this._handleKeypress,this).on(e,"blur",this.collapseDelayed,this).on(e,"focus",this.collapseDelayedStop,this),e},_createCancel:function(b,c){var d=a.DomUtil.create("a",c,this._container);return d.href="#",d.title=b,d.style.display="none",d.innerHTML="<span>⊗</span>",a.DomEvent.on(d,"click",a.DomEvent.stop,this).on(d,"click",this.cancel,this),d},_createButton:function(b,c){var d=a.DomUtil.create("a",c,this._container);return d.href="#",d.title=b,a.DomEvent.on(d,"click",a.DomEvent.stop,this).on(d,"click",this._handleSubmit,this).on(d,"focus",this.collapseDelayedStop,this).on(d,"blur",this.collapseDelayed,this),d},_createTooltip:function(b){var c=a.DomUtil.create("ul",b,this._container);c.style.display="none";var d=this;return a.DomEvent.disableClickPropagation(c).on(c,"blur",this.collapseDelayed,this).on(c,"mousewheel",function(b){d.collapseDelayedStop(),a.DomEvent.stopPropagation(b)},this).on(c,"mouseover",function(a){d.collapseDelayedStop()},this),c},_createTip:function(b,c){var d;if(this.options.buildTip){if(d=this.options.buildTip.call(this,b,c),"string"==typeof d){var e=a.DomUtil.create("div");e.innerHTML=d,d=e.firstChild}}else d=a.DomUtil.create("li",""),d.innerHTML=b;return a.DomUtil.addClass(d,"search-tip"),d._text=b,this.options.tipAutoSubmit&&a.DomEvent.disableClickPropagation(d).on(d,"click",a.DomEvent.stop,this).on(d,"click",function(a){this._input.value=b,this._handleAutoresize(),this._input.focus(),this._hideTooltip(),this._handleSubmit()},this),d},_getUrl:function(a){return"function"==typeof this.options.url?this.options.url(a):this.options.url},_defaultFilterData:function(a,b){var c,d,e,f={};if(a=a.replace(/[.*+?^${}()|[\]\\]/g,""),""===a)return[];c=this.options.initial?"^":"",d=this.options.casesensitive?void 0:"i",e=new RegExp(c+a,d);for(var g in b)e.test(g)&&(f[g]=b[g]);return f},showTooltip:function(a){if(this._countertips=0,this._tooltip.innerHTML="",this._tooltip.currentSelection=-1,this.options.tooltipLimit)for(var b in a){if(this._countertips===this.options.tooltipLimit)break;this._countertips++,this._tooltip.appendChild(this._createTip(b,a[b]))}return this._countertips>0?(this._tooltip.style.display="block",this._autoTypeTmp&&this._autoType(),this._autoTypeTmp=this.options.autoType):this._hideTooltip(),this._tooltip.scrollTop=0,this._countertips},_hideTooltip:function(){return this._tooltip.style.display="none",this._tooltip.innerHTML="",0},_defaultFormatData:function(c){var d,e=this.options.propertyName,f=this.options.propertyLoc,g={};if(a.Util.isArray(f))for(d in c)g[b(c[d],e)]=a.latLng(c[d][f[0]],c[d][f[1]]);else for(d in c)g[b(c[d],e)]=a.latLng(b(c[d],f));return g},_recordsFromJsonp:function(b,c){a.Control.Search.callJsonp=c;var d=a.DomUtil.create("script","leaflet-search-jsonp",document.getElementsByTagName("body")[0]),e=a.Util.template(this._getUrl(b)+"&"+this.options.jsonpParam+"=L.Control.Search.callJsonp",{s:b});return d.type="text/javascript",d.src=e,{abort:function(){d.parentNode.removeChild(d)}}},_recordsFromAjax:function(b,c){void 0===window.XMLHttpRequest&&(window.XMLHttpRequest=function(){try{return new ActiveXObject("Microsoft.XMLHTTP.6.0")}catch(a){try{return new ActiveXObject("Microsoft.XMLHTTP.3.0")}catch(b){throw new Error("XMLHttpRequest is not supported")}}});var d=a.Browser.ie&&!window.atob&&document.querySelector,e=d?new XDomainRequest:new XMLHttpRequest,f=a.Util.template(this._getUrl(b),{s:b});e.open("GET",f);return e.onload=function(){c(JSON.parse(e.responseText))},e.onreadystatechange=function(){4===e.readyState&&200===e.status&&this.onload()},e.send(),e},_recordsFromLayer:function(){var c,d={},e=this.options.propertyName;return this._layer.eachLayer(function(f){if(!f.hasOwnProperty("_isMarkerSearch"))if(f instanceof a.Marker||f instanceof a.CircleMarker)try{if(b(f.options,e))c=f.getLatLng(),c.layer=f,d[b(f.options,e)]=c;else{if(!b(f.feature.properties,e))throw new Error("propertyName '"+e+"' not found in marker");c=f.getLatLng(),c.layer=f,d[b(f.feature.properties,e)]=c}}catch(g){console}else if(f.hasOwnProperty("feature"))try{if(!f.feature.properties.hasOwnProperty(e))throw new Error("propertyName '"+e+"' not found in feature");c=f.getBounds().getCenter(),c.layer=f,d[f.feature.properties[e]]=c}catch(g){console}else f instanceof a.LayerGroup&&f.eachLayer(function(a){c=a.getLatLng(),c.layer=a,d[a.feature.properties[e]]=c})},this),d},_autoType:function(){var a=this._input.value.length,b=this._tooltip.firstChild?this._tooltip.firstChild._text:"",c=b.length;if(0===b.indexOf(this._input.value))if(this._input.value=b,this._handleAutoresize(),this._input.createTextRange){var d=this._input.createTextRange();d.collapse(!0),d.moveStart("character",a),d.moveEnd("character",c),d.select()}else this._input.setSelectionRange?this._input.setSelectionRange(a,c):this._input.selectionStart&&(this._input.selectionStart=a,this._input.selectionEnd=c)},_hideAutoType:function(){var a;if((a=this._input.selection)&&a.empty)a.empty();else if(this._input.createTextRange){a=this._input.createTextRange(),a.collapse(!0);var b=this._input.value.length;a.moveStart("character",b),a.moveEnd("character",b),a.select()}else this._input.getSelection&&this._input.getSelection().removeAllRanges(),this._input.selectionStart=this._input.selectionEnd},_handleKeypress:function(a){switch(a.keyCode){case 27:this.collapse();break;case 13:(1==this._countertips||this.options.firstTipSubmit&&this._countertips>0)&&this._handleArrowSelect(1),this._handleSubmit();break;case 38:this._handleArrowSelect(-1);break;case 40:this._handleArrowSelect(1);break;case 8:case 45:case 46:this._autoTypeTmp=!1;break;case 37:case 39:case 16:case 17:case 35:case 36:break;default:if(this._input.value.length?this._cancel.style.display="block":this._cancel.style.display="none",this._input.value.length>=this.options.minLength){var b=this;clearTimeout(this.timerKeypress),this.timerKeypress=setTimeout(function(){b._fillRecordsCache()},this.options.delayType)}else this._hideTooltip()}this._handleAutoresize()},searchText:function(b){var c=b.charCodeAt(b.length);this._input.value=b,this._input.style.display="block",a.DomUtil.addClass(this._container,"search-exp"),this._autoTypeTmp=!1,this._handleKeypress({keyCode:c})},_fillRecordsCache:function(){var b,c=this._input.value,d=this;this._curReq&&this._curReq.abort&&this._curReq.abort(),a.DomUtil.addClass(this._container,"search-load"),this.options.layer?(this._recordsCache=this._recordsFromLayer(),b=this._filterData(this._input.value,this._recordsCache),this.showTooltip(b),a.DomUtil.removeClass(this._container,"search-load")):(this.options.sourceData?this._retrieveData=this.options.sourceData:this.options.url&&(this._retrieveData=this.options.jsonpParam?this._recordsFromJsonp:this._recordsFromAjax),this._curReq=this._retrieveData.call(this,c,function(c){d._recordsCache=d._formatData(c),b=d.options.sourceData?d._filterData(d._input.value,d._recordsCache):d._recordsCache,d.showTooltip(b),a.DomUtil.removeClass(d._container,"search-load")}))},_handleAutoresize:function(){this._input.style.maxWidth!=this._map._container.offsetWidth&&(this._input.style.maxWidth=a.DomUtil.getStyle(this._map._container,"width")),this.options.autoResize&&this._container.offsetWidth+45<this._map._container.offsetWidth&&(this._input.size=this._input.value.length<this._inputMinSize?this._inputMinSize:this._input.value.length)},_handleArrowSelect:function(b){var c=this._tooltip.hasChildNodes()?this._tooltip.childNodes:[];for(i=0;i<c.length;i++)a.DomUtil.removeClass(c[i],"search-tip-select");if(1==b&&this._tooltip.currentSelection>=c.length-1)a.DomUtil.addClass(c[this._tooltip.currentSelection],"search-tip-select");else if(-1==b&&this._tooltip.currentSelection<=0)this._tooltip.currentSelection=-1;else if("none"!=this._tooltip.style.display){this._tooltip.currentSelection+=b,a.DomUtil.addClass(c[this._tooltip.currentSelection],"search-tip-select"),this._input.value=c[this._tooltip.currentSelection]._text;var d=c[this._tooltip.currentSelection].offsetTop;d+c[this._tooltip.currentSelection].clientHeight>=this._tooltip.scrollTop+this._tooltip.clientHeight?this._tooltip.scrollTop=d-this._tooltip.clientHeight+c[this._tooltip.currentSelection].clientHeight:d<=this._tooltip.scrollTop&&(this._tooltip.scrollTop=d)}},_handleSubmit:function(){if(this._hideAutoType(),this.hideAlert(),this._hideTooltip(),"none"==this._input.style.display)this.expand();else if(""===this._input.value)this.collapse();else{var a=this._getLocation(this._input.value);a===!1?this.showAlert():(this.showLocation(a,this._input.value),this.fire("search:locationfound",{latlng:a,text:this._input.value,layer:a.layer?a.layer:null}))}},_getLocation:function(a){return this._recordsCache.hasOwnProperty(a)?this._recordsCache[a]:!1},_defaultMoveToLocation:function(a,b,c){this.options.zoom?this._map.setView(a,this.options.zoom):this._map.panTo(a)},showLocation:function(a,b){var c=this;return c._map.once("moveend zoomend",function(b){c._markerSearch&&c._markerSearch.addTo(c._map).setLatLng(a)}),c._moveToLocation(a,b,c._map),c.options.autoCollapse&&c.collapse(),c}}),a.Control.Search.Marker=a.Marker.extend({includes:a.Mixin.Events,options:{icon:new a.Icon.Default,animate:!0,circle:{radius:10,weight:3,color:"#e03",stroke:!0,fill:!1}},initialize:function(b,d){a.setOptions(this,d),d.icon===!0&&(d.icon=new a.Icon.Default),a.Marker.prototype.initialize.call(this,b,d),c(this.options.circle)&&(this._circleLoc=new a.CircleMarker(b,this.options.circle))},onAdd:function(b){a.Marker.prototype.onAdd.call(this,b),this._circleLoc&&(b.addLayer(this._circleLoc),this.options.animate&&this.animate())},onRemove:function(b){a.Marker.prototype.onRemove.call(this,b),this._circleLoc&&b.removeLayer(this._circleLoc)},setLatLng:function(b){return a.Marker.prototype.setLatLng.call(this,b),this._circleLoc&&this._circleLoc.setLatLng(b),this},_initIcon:function(){this.options.icon&&a.Marker.prototype._initIcon.call(this)},_removeIcon:function(){this.options.icon&&a.Marker.prototype._removeIcon.call(this)},animate:function(){if(this._circleLoc){var a=this._circleLoc,b=200,c=5,d=parseInt(a._radius/c),e=this.options.circle.radius,f=2*a._radius,g=0;a._timerAnimLoc=setInterval(function(){g+=.5,d+=g,f-=d,a.setRadius(f),e>f&&(clearInterval(a._timerAnimLoc),a.setRadius(e))},b)}return this}}),a.Map.addInitHook(function(){this.options.searchControl&&(this.searchControl=a.control.search(this.options.searchControl),this.addControl(this.searchControl))}),a.control.search=function(b){return new a.Control.Search(b)},a.Control.Search}); \ No newline at end of file diff --git a/assets/www/js/vendor/moment.es.js b/assets/www/js/vendor/moment.es.js deleted file mode 100644 index 9b24a1776d7bc6b3100955d47b1366c75df0e232..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/moment.es.js +++ /dev/null @@ -1,61 +0,0 @@ -//! moment.js locale configuration -//! locale : french (es) -//! author : Fiatou: https://github.com/fiatou - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : - typeof define === 'function' && define.amd ? define(['moment'], factory) : - factory(global.moment) -}(this, function (moment) { 'use strict'; - - - var es = moment.defineLocale('es', { - months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'), - monthsShort : 'ener._febr._mar._abr._may._jun._jul._agos_sept._oct._nov._dic.'.split('_'), - weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'), - weekdaysShort : 'dom._lun._mar._mie._jue._vie._sáb.'.split('_'), - weekdaysMin : 'Do_Lu_Ma_Mi_Ju_Vi_Sá'.split('_'), - longDateFormat : { - LT : 'HH:mm', - LTS : 'HH:mm:ss', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY HH:mm', - LLLL : 'dddd D MMMM YYYY HH:mm' - }, - calendar : { - sameDay: '[Hoy a] LT', - nextDay: '[Mañana a] LT', - nextWeek: 'dddd [a] LT', - lastDay: '[Ayer a] LT', - lastWeek: 'dddd [último a] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'en %s', - past : 'hace %s', - s : 'algunas segundas', - m : 'un minuto', - mm : '%d minutos', - h : 'una hora', - hh : '%d horas', - d : 'un dia', - dd : '%d dias', - M : 'un mes', - MM : '%d meses', - y : 'un año', - yy : '%d años' - }, - ordinalParse: /\d{1,2}(er|)/, - ordinal : function (number) { - return number + (number === 1 ? 'ero' : ''); - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); - - return es; - -})); diff --git a/assets/www/js/vendor/moment.fr.js b/assets/www/js/vendor/moment.fr.js deleted file mode 100644 index 4f60e588f3396e0eb9c968cb14cf172beb51a2c3..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/moment.fr.js +++ /dev/null @@ -1,61 +0,0 @@ -//! moment.js locale configuration -//! locale : french (fr) -//! author : John Fischer : https://github.com/jfroffice - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : - typeof define === 'function' && define.amd ? define(['moment'], factory) : - factory(global.moment) -}(this, function (moment) { 'use strict'; - - - var fr = moment.defineLocale('fr', { - months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), - monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), - weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), - weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), - weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), - longDateFormat : { - LT : 'HH:mm', - LTS : 'HH:mm:ss', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY HH:mm', - LLLL : 'dddd D MMMM YYYY HH:mm' - }, - calendar : { - sameDay: '[Aujourd\'hui à ] LT', - nextDay: '[Demain à ] LT', - nextWeek: 'dddd [à ] LT', - lastDay: '[Hier à ] LT', - lastWeek: 'dddd [dernier à ] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'dans %s', - past : 'il y a %s', - s : 'quelques secondes', - m : 'une minute', - mm : '%d minutes', - h : 'une heure', - hh : '%d heures', - d : 'un jour', - dd : '%d jours', - M : 'un mois', - MM : '%d mois', - y : 'un an', - yy : '%d ans' - }, - ordinalParse: /\d{1,2}(er|)/, - ordinal : function (number) { - return number + (number === 1 ? 'er' : ''); - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); - - return fr; - -})); \ No newline at end of file diff --git a/assets/www/js/vendor/moment.min.js b/assets/www/js/vendor/moment.min.js deleted file mode 100644 index a049687679c3d43895039554cfe5f477cd92a51d..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/moment.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";function e(){return Qe.apply(null,arguments)}function t(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function n(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function s(e){return void 0===e}function i(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function r(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function a(e,t){var n,s=[];for(n=0;n<e.length;++n)s.push(t(e[n],n));return s}function o(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function u(e,t){for(var n in t)o(t,n)&&(e[n]=t[n]);return o(t,"toString")&&(e.toString=t.toString),o(t,"valueOf")&&(e.valueOf=t.valueOf),e}function l(e,t,n,s){return ge(e,t,n,s,!0).utc()}function d(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function h(e){if(null==e._isValid){var t=d(e),n=Xe.call(t.parsedDateParts,function(e){return null!=e}),s=!isNaN(e._d.getTime())&&t.overflow<0&&!t.empty&&!t.invalidMonth&&!t.invalidWeekday&&!t.weekdayMismatch&&!t.nullInput&&!t.invalidFormat&&!t.userInvalidated&&(!t.meridiem||t.meridiem&&n);if(e._strict&&(s=s&&0===t.charsLeftOver&&0===t.unusedTokens.length&&void 0===t.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return s;e._isValid=s}return e._isValid}function c(e){var t=l(NaN);return null!=e?u(d(t),e):d(t).userInvalidated=!0,t}function f(e,t){var n,i,r;if(s(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),s(t._i)||(e._i=t._i),s(t._f)||(e._f=t._f),s(t._l)||(e._l=t._l),s(t._strict)||(e._strict=t._strict),s(t._tzm)||(e._tzm=t._tzm),s(t._isUTC)||(e._isUTC=t._isUTC),s(t._offset)||(e._offset=t._offset),s(t._pf)||(e._pf=d(t)),s(t._locale)||(e._locale=t._locale),Ke.length>0)for(n=0;n<Ke.length;n++)s(r=t[i=Ke[n]])||(e[i]=r);return e}function m(t){f(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===et&&(et=!0,e.updateOffset(this),et=!1)}function _(e){return e instanceof m||null!=e&&null!=e._isAMomentObject}function y(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function g(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=y(t)),n}function p(e,t,n){var s,i=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),a=0;for(s=0;s<i;s++)(n&&e[s]!==t[s]||!n&&g(e[s])!==g(t[s]))&&a++;return a+r}function w(t){!1===e.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function v(t,n){var s=!0;return u(function(){if(null!=e.deprecationHandler&&e.deprecationHandler(null,t),s){for(var i,r=[],a=0;a<arguments.length;a++){if(i="","object"==typeof arguments[a]){i+="\n["+a+"] ";for(var o in arguments[0])i+=o+": "+arguments[0][o]+", ";i=i.slice(0,-2)}else i=arguments[a];r.push(i)}w(t+"\nArguments: "+Array.prototype.slice.call(r).join("")+"\n"+(new Error).stack),s=!1}return n.apply(this,arguments)},n)}function M(t,n){null!=e.deprecationHandler&&e.deprecationHandler(t,n),tt[t]||(w(n),tt[t]=!0)}function k(e){return e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function S(e,t){var s,i=u({},e);for(s in t)o(t,s)&&(n(e[s])&&n(t[s])?(i[s]={},u(i[s],e[s]),u(i[s],t[s])):null!=t[s]?i[s]=t[s]:delete i[s]);for(s in e)o(e,s)&&!o(t,s)&&n(e[s])&&(i[s]=u({},i[s]));return i}function D(e){null!=e&&this.set(e)}function Y(e,t){var n=e.toLowerCase();st[n]=st[n+"s"]=st[t]=e}function O(e){return"string"==typeof e?st[e]||st[e.toLowerCase()]:void 0}function x(e){var t,n,s={};for(n in e)o(e,n)&&(t=O(n))&&(s[t]=e[n]);return s}function T(e,t){it[e]=t}function b(e,t,n){var s=""+Math.abs(e),i=t-s.length;return(e>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+s}function P(e,t,n,s){var i=s;"string"==typeof s&&(i=function(){return this[s]()}),e&&(ut[e]=i),t&&(ut[t[0]]=function(){return b(i.apply(this,arguments),t[1],t[2])}),n&&(ut[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function W(e){return e.match(/\[[\s\S]/)?e.replace(/^\[|\]$/g,""):e.replace(/\\/g,"")}function R(e,t){return e.isValid()?(t=C(t,e.localeData()),ot[t]=ot[t]||function(e){var t,n,s=e.match(rt);for(t=0,n=s.length;t<n;t++)ut[s[t]]?s[t]=ut[s[t]]:s[t]=W(s[t]);return function(t){var i,r="";for(i=0;i<n;i++)r+=k(s[i])?s[i].call(t,e):s[i];return r}}(t),ot[t](e)):e.localeData().invalidDate()}function C(e,t){function n(e){return t.longDateFormat(e)||e}var s=5;for(at.lastIndex=0;s>=0&&at.test(e);)e=e.replace(at,n),at.lastIndex=0,s-=1;return e}function F(e,t,n){Yt[e]=k(t)?t:function(e,s){return e&&n?n:t}}function U(e,t){return o(Yt,e)?Yt[e](t._strict,t._locale):new RegExp(function(e){return N(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,s,i){return t||n||s||i}))}(e))}function N(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function H(e,t){var n,s=t;for("string"==typeof e&&(e=[e]),i(t)&&(s=function(e,n){n[t]=g(e)}),n=0;n<e.length;n++)Ot[e[n]]=s}function L(e,t){H(e,function(e,n,s,i){s._w=s._w||{},t(e,s._w,s,i)})}function G(e,t,n){null!=t&&o(Ot,e)&&Ot[e](t,n._a,n,e)}function V(e){return j(e)?366:365}function j(e){return e%4==0&&e%100!=0||e%400==0}function I(t,n){return function(s){return null!=s?(A(this,t,s),e.updateOffset(this,n),this):E(this,t)}}function E(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function A(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&j(e.year())&&1===e.month()&&29===e.date()?e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),z(n,e.month())):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function z(e,t){if(isNaN(e)||isNaN(t))return NaN;var n=function(e,t){return(e%t+t)%t}(t,12);return e+=(t-n)/12,1===n?j(e)?29:28:31-n%7%2}function Z(e,t){var n;if(!e.isValid())return e;if("string"==typeof t)if(/^\d+$/.test(t))t=g(t);else if(t=e.localeData().monthsParse(t),!i(t))return e;return n=Math.min(e.date(),z(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n),e}function $(t){return null!=t?(Z(this,t),e.updateOffset(this,!0),this):E(this,"Month")}function q(){function e(e,t){return t.length-e.length}var t,n,s=[],i=[],r=[];for(t=0;t<12;t++)n=l([2e3,t]),s.push(this.monthsShort(n,"")),i.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(s.sort(e),i.sort(e),r.sort(e),t=0;t<12;t++)s[t]=N(s[t]),i[t]=N(i[t]);for(t=0;t<24;t++)r[t]=N(r[t]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+s.join("|")+")","i")}function J(e){var t=new Date(Date.UTC.apply(null,arguments));return e<100&&e>=0&&isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e),t}function B(e,t,n){var s=7+t-n;return-((7+J(e,0,s).getUTCDay()-t)%7)+s-1}function Q(e,t,n,s,i){var r,a,o=1+7*(t-1)+(7+n-s)%7+B(e,s,i);return o<=0?a=V(r=e-1)+o:o>V(e)?(r=e+1,a=o-V(e)):(r=e,a=o),{year:r,dayOfYear:a}}function X(e,t,n){var s,i,r=B(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+K(i=e.year()-1,t,n):a>K(e.year(),t,n)?(s=a-K(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function K(e,t,n){var s=B(e,t,n),i=B(e+1,t,n);return(V(e)-s+i)/7}function ee(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],d=[];for(t=0;t<7;t++)n=l([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),d.push(s),d.push(i),d.push(r);for(a.sort(e),o.sort(e),u.sort(e),d.sort(e),t=0;t<7;t++)o[t]=N(o[t]),u[t]=N(u[t]),d[t]=N(d[t]);this._weekdaysRegex=new RegExp("^("+d.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function te(){return this.hours()%12||12}function ne(e,t){P(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function se(e,t){return t._meridiemParse}function ie(e){return e?e.toLowerCase().replace("_","-"):e}function re(e){var t=null;if(!Xt[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=Jt._abbr;require("./locale/"+e),ae(t)}catch(e){}return Xt[e]}function ae(e,t){var n;return e&&(n=s(t)?ue(e):oe(e,t))&&(Jt=n),Jt._abbr}function oe(e,t){if(null!==t){var n=Qt;if(t.abbr=e,null!=Xt[e])M("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),n=Xt[e]._config;else if(null!=t.parentLocale){if(null==Xt[t.parentLocale])return Kt[t.parentLocale]||(Kt[t.parentLocale]=[]),Kt[t.parentLocale].push({name:e,config:t}),null;n=Xt[t.parentLocale]._config}return Xt[e]=new D(S(n,t)),Kt[e]&&Kt[e].forEach(function(e){oe(e.name,e.config)}),ae(e),Xt[e]}return delete Xt[e],null}function ue(e){var n;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return Jt;if(!t(e)){if(n=re(e))return n;e=[e]}return function(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=ie(e[r]).split("-")).length,n=(n=ie(e[r+1]))?n.split("-"):null;t>0;){if(s=re(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&p(i,n,!0)>=t-1)break;t--}r++}return null}(e)}function le(e){var t,n=e._a;return n&&-2===d(e).overflow&&(t=n[Tt]<0||n[Tt]>11?Tt:n[bt]<1||n[bt]>z(n[xt],n[Tt])?bt:n[Pt]<0||n[Pt]>24||24===n[Pt]&&(0!==n[Wt]||0!==n[Rt]||0!==n[Ct])?Pt:n[Wt]<0||n[Wt]>59?Wt:n[Rt]<0||n[Rt]>59?Rt:n[Ct]<0||n[Ct]>999?Ct:-1,d(e)._overflowDayOfYear&&(t<xt||t>bt)&&(t=bt),d(e)._overflowWeeks&&-1===t&&(t=Ft),d(e)._overflowWeekday&&-1===t&&(t=Ut),d(e).overflow=t),e}function de(e,t,n){return null!=e?e:null!=t?t:n}function he(t){var n,s,i,r,a,o=[];if(!t._d){for(i=function(t){var n=new Date(e.now());return t._useUTC?[n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate()]:[n.getFullYear(),n.getMonth(),n.getDate()]}(t),t._w&&null==t._a[bt]&&null==t._a[Tt]&&function(e){var t,n,s,i,r,a,o,u;if(null!=(t=e._w).GG||null!=t.W||null!=t.E)r=1,a=4,n=de(t.GG,e._a[xt],X(pe(),1,4).year),s=de(t.W,1),((i=de(t.E,1))<1||i>7)&&(u=!0);else{r=e._locale._week.dow,a=e._locale._week.doy;var l=X(pe(),r,a);n=de(t.gg,e._a[xt],l.year),s=de(t.w,l.week),null!=t.d?((i=t.d)<0||i>6)&&(u=!0):null!=t.e?(i=t.e+r,(t.e<0||t.e>6)&&(u=!0)):i=r}s<1||s>K(n,r,a)?d(e)._overflowWeeks=!0:null!=u?d(e)._overflowWeekday=!0:(o=Q(n,s,i,r,a),e._a[xt]=o.year,e._dayOfYear=o.dayOfYear)}(t),null!=t._dayOfYear&&(a=de(t._a[xt],i[xt]),(t._dayOfYear>V(a)||0===t._dayOfYear)&&(d(t)._overflowDayOfYear=!0),s=J(a,0,t._dayOfYear),t._a[Tt]=s.getUTCMonth(),t._a[bt]=s.getUTCDate()),n=0;n<3&&null==t._a[n];++n)t._a[n]=o[n]=i[n];for(;n<7;n++)t._a[n]=o[n]=null==t._a[n]?2===n?1:0:t._a[n];24===t._a[Pt]&&0===t._a[Wt]&&0===t._a[Rt]&&0===t._a[Ct]&&(t._nextDay=!0,t._a[Pt]=0),t._d=(t._useUTC?J:function(e,t,n,s,i,r,a){var o=new Date(e,t,n,s,i,r,a);return e<100&&e>=0&&isFinite(o.getFullYear())&&o.setFullYear(e),o}).apply(null,o),r=t._useUTC?t._d.getUTCDay():t._d.getDay(),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[Pt]=24),t._w&&void 0!==t._w.d&&t._w.d!==r&&(d(t).weekdayMismatch=!0)}}function ce(e){var t,n,s,i,r,a,o=e._i,u=en.exec(o)||tn.exec(o);if(u){for(d(e).iso=!0,t=0,n=sn.length;t<n;t++)if(sn[t][1].exec(u[1])){i=sn[t][0],s=!1!==sn[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=rn.length;t<n;t++)if(rn[t][1].exec(u[3])){r=(u[2]||" ")+rn[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!nn.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),_e(e)}else e._isValid=!1}function fe(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);{if(t<=49)return 2e3+t;if(t<=999)return 1900+t}return t}(e),Vt.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}function me(e){var t=on.exec(function(e){return e.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").trim()}(e._i));if(t){var n=fe(t[4],t[3],t[2],t[5],t[6],t[7]);if(!function(e,t,n){if(e&&At.indexOf(e)!==new Date(t[0],t[1],t[2]).getDay())return d(n).weekdayMismatch=!0,n._isValid=!1,!1;return!0}(t[1],n,e))return;e._a=n,e._tzm=function(e,t,n){if(e)return un[e];if(t)return 0;var s=parseInt(n,10),i=s%100;return(s-i)/100*60+i}(t[8],t[9],t[10]),e._d=J.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),d(e).rfc2822=!0}else e._isValid=!1}function _e(t){if(t._f!==e.ISO_8601)if(t._f!==e.RFC_2822){t._a=[],d(t).empty=!0;var n,s,i,r,a,o=""+t._i,u=o.length,l=0;for(i=C(t._f,t._locale).match(rt)||[],n=0;n<i.length;n++)r=i[n],(s=(o.match(U(r,t))||[])[0])&&((a=o.substr(0,o.indexOf(s))).length>0&&d(t).unusedInput.push(a),o=o.slice(o.indexOf(s)+s.length),l+=s.length),ut[r]?(s?d(t).empty=!1:d(t).unusedTokens.push(r),G(r,s,t)):t._strict&&!s&&d(t).unusedTokens.push(r);d(t).charsLeftOver=u-l,o.length>0&&d(t).unusedInput.push(o),t._a[Pt]<=12&&!0===d(t).bigHour&&t._a[Pt]>0&&(d(t).bigHour=void 0),d(t).parsedDateParts=t._a.slice(0),d(t).meridiem=t._meridiem,t._a[Pt]=function(e,t,n){var s;if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):null!=e.isPM?((s=e.isPM(n))&&t<12&&(t+=12),s||12!==t||(t=0),t):t}(t._locale,t._a[Pt],t._meridiem),he(t),le(t)}else me(t);else ce(t)}function ye(o){var l=o._i,y=o._f;return o._locale=o._locale||ue(o._l),null===l||void 0===y&&""===l?c({nullInput:!0}):("string"==typeof l&&(o._i=l=o._locale.preparse(l)),_(l)?new m(le(l)):(r(l)?o._d=l:t(y)?function(e){var t,n,s,i,r;if(0===e._f.length)return d(e).invalidFormat=!0,void(e._d=new Date(NaN));for(i=0;i<e._f.length;i++)r=0,t=f({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],_e(t),h(t)&&(r+=d(t).charsLeftOver,r+=10*d(t).unusedTokens.length,d(t).score=r,(null==s||r<s)&&(s=r,n=t));u(e,n||t)}(o):y?_e(o):function(o){var u=o._i;s(u)?o._d=new Date(e.now()):r(u)?o._d=new Date(u.valueOf()):"string"==typeof u?function(t){var n=an.exec(t._i);null===n?(ce(t),!1===t._isValid&&(delete t._isValid,me(t),!1===t._isValid&&(delete t._isValid,e.createFromInputFallback(t)))):t._d=new Date(+n[1])}(o):t(u)?(o._a=a(u.slice(0),function(e){return parseInt(e,10)}),he(o)):n(u)?function(e){if(!e._d){var t=x(e._i);e._a=a([t.year,t.month,t.day||t.date,t.hour,t.minute,t.second,t.millisecond],function(e){return e&&parseInt(e,10)}),he(e)}}(o):i(u)?o._d=new Date(u):e.createFromInputFallback(o)}(o),h(o)||(o._d=null),o))}function ge(e,s,i,r,a){var o={};return!0!==i&&!1!==i||(r=i,i=void 0),(n(e)&&function(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0}(e)||t(e)&&0===e.length)&&(e=void 0),o._isAMomentObject=!0,o._useUTC=o._isUTC=a,o._l=i,o._i=e,o._f=s,o._strict=r,function(e){var t=new m(le(ye(e)));return t._nextDay&&(t.add(1,"d"),t._nextDay=void 0),t}(o)}function pe(e,t,n,s){return ge(e,t,n,s,!1)}function we(e,n){var s,i;if(1===n.length&&t(n[0])&&(n=n[0]),!n.length)return pe();for(s=n[0],i=1;i<n.length;++i)n[i].isValid()&&!n[i][e](s)||(s=n[i]);return s}function ve(e){var t=x(e),n=t.year||0,s=t.quarter||0,i=t.month||0,r=t.week||0,a=t.day||0,o=t.hour||0,u=t.minute||0,l=t.second||0,d=t.millisecond||0;this._isValid=function(e){for(var t in e)if(-1===Nt.call(hn,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<hn.length;++s)if(e[hn[s]]){if(n)return!1;parseFloat(e[hn[s]])!==g(e[hn[s]])&&(n=!0)}return!0}(t),this._milliseconds=+d+1e3*l+6e4*u+1e3*o*60*60,this._days=+a+7*r,this._months=+i+3*s+12*n,this._data={},this._locale=ue(),this._bubble()}function Me(e){return e instanceof ve}function ke(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Se(e,t){P(e,0,0,function(){var e=this.utcOffset(),n="+";return e<0&&(e=-e,n="-"),n+b(~~(e/60),2)+t+b(~~e%60,2)})}function De(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(cn)||["-",0,0],i=60*s[1]+g(s[2]);return 0===i?0:"+"===s[0]?i:-i}function Ye(t,n){var s,i;return n._isUTC?(s=n.clone(),i=(_(t)||r(t)?t.valueOf():pe(t).valueOf())-s.valueOf(),s._d.setTime(s._d.valueOf()+i),e.updateOffset(s,!1),s):pe(t).local()}function Oe(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function xe(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function Te(e,t){var n,s,r,a=e,u=null;return Me(e)?a={ms:e._milliseconds,d:e._days,M:e._months}:i(e)?(a={},t?a[t]=e:a.milliseconds=e):(u=fn.exec(e))?(n="-"===u[1]?-1:1,a={y:0,d:g(u[bt])*n,h:g(u[Pt])*n,m:g(u[Wt])*n,s:g(u[Rt])*n,ms:g(ke(1e3*u[Ct]))*n}):(u=mn.exec(e))?(n="-"===u[1]?-1:(u[1],1),a={y:be(u[2],n),M:be(u[3],n),w:be(u[4],n),d:be(u[5],n),h:be(u[6],n),m:be(u[7],n),s:be(u[8],n)}):null==a?a={}:"object"==typeof a&&("from"in a||"to"in a)&&(r=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Ye(t,e),e.isBefore(t)?n=Pe(e,t):((n=Pe(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(pe(a.from),pe(a.to)),(a={}).ms=r.milliseconds,a.M=r.months),s=new ve(a),Me(e)&&o(e,"_locale")&&(s._locale=e._locale),s}function be(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function Pe(e,t){var n={milliseconds:0,months:0};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function We(e,t){return function(n,s){var i,r;return null===s||isNaN(+s)||(M(t,"moment()."+t+"(period, number) is deprecated. Please use moment()."+t+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),r=n,n=s,s=r),n="string"==typeof n?+n:n,i=Te(n,s),Re(this,i,e),this}}function Re(t,n,s,i){var r=n._milliseconds,a=ke(n._days),o=ke(n._months);t.isValid()&&(i=null==i||i,o&&Z(t,E(t,"Month")+o*s),a&&A(t,"Date",E(t,"Date")+a*s),r&&t._d.setTime(t._d.valueOf()+r*s),i&&e.updateOffset(t,a||o))}function Ce(e,t){var n,s=12*(t.year()-e.year())+(t.month()-e.month()),i=e.clone().add(s,"months");return n=t-i<0?(t-i)/(i-e.clone().add(s-1,"months")):(t-i)/(e.clone().add(s+1,"months")-i),-(s+n)||0}function Fe(e){var t;return void 0===e?this._locale._abbr:(null!=(t=ue(e))&&(this._locale=t),this)}function Ue(){return this._locale}function Ne(e,t){P(0,[e,e.length],0,t)}function He(e,t,n,s,i){var r;return null==e?X(this,s,i).year:(r=K(e,s,i),t>r&&(t=r),function(e,t,n,s,i){var r=Q(e,t,n,s,i),a=J(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}.call(this,e,t,n,s,i))}function Le(e,t){t[Ct]=g(1e3*("0."+e))}function Ge(e){return e}function Ve(e,t,n,s){var i=ue(),r=l().set(s,t);return i[n](r,e)}function je(e,t,n){if(i(e)&&(t=e,e=void 0),e=e||"",null!=t)return Ve(e,t,n,"month");var s,r=[];for(s=0;s<12;s++)r[s]=Ve(e,s,n,"month");return r}function Ie(e,t,n,s){"boolean"==typeof e?(i(t)&&(n=t,t=void 0),t=t||""):(n=t=e,e=!1,i(t)&&(n=t,t=void 0),t=t||"");var r=ue(),a=e?r._week.dow:0;if(null!=n)return Ve(t,(n+a)%7,s,"day");var o,u=[];for(o=0;o<7;o++)u[o]=Ve(t,(o+a)%7,s,"day");return u}function Ee(e,t,n,s){var i=Te(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function Ae(e){return e<0?Math.floor(e):Math.ceil(e)}function ze(e){return 4800*e/146097}function Ze(e){return 146097*e/4800}function $e(e){return function(){return this.as(e)}}function qe(e){return function(){return this.isValid()?this._data[e]:NaN}}function Je(e){return(e>0)-(e<0)||+e}function Be(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n=En(this._milliseconds)/1e3,s=En(this._days),i=En(this._months);t=y((e=y(n/60))/60),n%=60,e%=60;var r=y(i/12),a=i%=12,o=s,u=t,l=e,d=n?n.toFixed(3).replace(/\.?0+$/,""):"",h=this.asSeconds();if(!h)return"P0D";var c=h<0?"-":"",f=Je(this._months)!==Je(h)?"-":"",m=Je(this._days)!==Je(h)?"-":"",_=Je(this._milliseconds)!==Je(h)?"-":"";return c+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(o?m+o+"D":"")+(u||l||d?"T":"")+(u?_+u+"H":"")+(l?_+l+"M":"")+(d?_+d+"S":"")}var Qe,Xe;Xe=Array.prototype.some?Array.prototype.some:function(e){for(var t=Object(this),n=t.length>>>0,s=0;s<n;s++)if(s in t&&e.call(this,t[s],s,t))return!0;return!1};var Ke=e.momentProperties=[],et=!1,tt={};e.suppressDeprecationWarnings=!1,e.deprecationHandler=null;var nt;nt=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)o(e,t)&&n.push(t);return n};var st={},it={},rt=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,at=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,ot={},ut={},lt=/\d/,dt=/\d\d/,ht=/\d{3}/,ct=/\d{4}/,ft=/[+-]?\d{6}/,mt=/\d\d?/,_t=/\d\d\d\d?/,yt=/\d\d\d\d\d\d?/,gt=/\d{1,3}/,pt=/\d{1,4}/,wt=/[+-]?\d{1,6}/,vt=/\d+/,Mt=/[+-]?\d+/,kt=/Z|[+-]\d\d:?\d\d/gi,St=/Z|[+-]\d\d(?::?\d\d)?/gi,Dt=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,Yt={},Ot={},xt=0,Tt=1,bt=2,Pt=3,Wt=4,Rt=5,Ct=6,Ft=7,Ut=8;P("Y",0,0,function(){var e=this.year();return e<=9999?""+e:"+"+e}),P(0,["YY",2],0,function(){return this.year()%100}),P(0,["YYYY",4],0,"year"),P(0,["YYYYY",5],0,"year"),P(0,["YYYYYY",6,!0],0,"year"),Y("year","y"),T("year",1),F("Y",Mt),F("YY",mt,dt),F("YYYY",pt,ct),F("YYYYY",wt,ft),F("YYYYYY",wt,ft),H(["YYYYY","YYYYYY"],xt),H("YYYY",function(t,n){n[xt]=2===t.length?e.parseTwoDigitYear(t):g(t)}),H("YY",function(t,n){n[xt]=e.parseTwoDigitYear(t)}),H("Y",function(e,t){t[xt]=parseInt(e,10)}),e.parseTwoDigitYear=function(e){return g(e)+(g(e)>68?1900:2e3)};var Nt,Ht=I("FullYear",!0);Nt=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1},P("M",["MM",2],"Mo",function(){return this.month()+1}),P("MMM",0,0,function(e){return this.localeData().monthsShort(this,e)}),P("MMMM",0,0,function(e){return this.localeData().months(this,e)}),Y("month","M"),T("month",8),F("M",mt),F("MM",mt,dt),F("MMM",function(e,t){return t.monthsShortRegex(e)}),F("MMMM",function(e,t){return t.monthsRegex(e)}),H(["M","MM"],function(e,t){t[Tt]=g(e)-1}),H(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[Tt]=i:d(n).invalidMonth=e});var Lt=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Gt="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Vt="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),jt=Dt,It=Dt;P("w",["ww",2],"wo","week"),P("W",["WW",2],"Wo","isoWeek"),Y("week","w"),Y("isoWeek","W"),T("week",5),T("isoWeek",5),F("w",mt),F("ww",mt,dt),F("W",mt),F("WW",mt,dt),L(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=g(e)});P("d",0,"do","day"),P("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),P("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),P("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),P("e",0,0,"weekday"),P("E",0,0,"isoWeekday"),Y("day","d"),Y("weekday","e"),Y("isoWeekday","E"),T("day",11),T("weekday",11),T("isoWeekday",11),F("d",mt),F("e",mt),F("E",mt),F("dd",function(e,t){return t.weekdaysMinRegex(e)}),F("ddd",function(e,t){return t.weekdaysShortRegex(e)}),F("dddd",function(e,t){return t.weekdaysRegex(e)}),L(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:d(n).invalidWeekday=e}),L(["d","e","E"],function(e,t,n,s){t[s]=g(e)});var Et="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),At="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),zt="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Zt=Dt,$t=Dt,qt=Dt;P("H",["HH",2],0,"hour"),P("h",["hh",2],0,te),P("k",["kk",2],0,function(){return this.hours()||24}),P("hmm",0,0,function(){return""+te.apply(this)+b(this.minutes(),2)}),P("hmmss",0,0,function(){return""+te.apply(this)+b(this.minutes(),2)+b(this.seconds(),2)}),P("Hmm",0,0,function(){return""+this.hours()+b(this.minutes(),2)}),P("Hmmss",0,0,function(){return""+this.hours()+b(this.minutes(),2)+b(this.seconds(),2)}),ne("a",!0),ne("A",!1),Y("hour","h"),T("hour",13),F("a",se),F("A",se),F("H",mt),F("h",mt),F("k",mt),F("HH",mt,dt),F("hh",mt,dt),F("kk",mt,dt),F("hmm",_t),F("hmmss",yt),F("Hmm",_t),F("Hmmss",yt),H(["H","HH"],Pt),H(["k","kk"],function(e,t,n){var s=g(e);t[Pt]=24===s?0:s}),H(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),H(["h","hh"],function(e,t,n){t[Pt]=g(e),d(n).bigHour=!0}),H("hmm",function(e,t,n){var s=e.length-2;t[Pt]=g(e.substr(0,s)),t[Wt]=g(e.substr(s)),d(n).bigHour=!0}),H("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Pt]=g(e.substr(0,s)),t[Wt]=g(e.substr(s,2)),t[Rt]=g(e.substr(i)),d(n).bigHour=!0}),H("Hmm",function(e,t,n){var s=e.length-2;t[Pt]=g(e.substr(0,s)),t[Wt]=g(e.substr(s))}),H("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Pt]=g(e.substr(0,s)),t[Wt]=g(e.substr(s,2)),t[Rt]=g(e.substr(i))});var Jt,Bt=I("Hours",!0),Qt={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Gt,monthsShort:Vt,week:{dow:0,doy:6},weekdays:Et,weekdaysMin:zt,weekdaysShort:At,meridiemParse:/[ap]\.?m?\.?/i},Xt={},Kt={},en=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,tn=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,nn=/Z|[+-]\d\d(?::?\d\d)?/,sn=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],rn=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],an=/^\/?Date\((\-?\d+)/i,on=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,un={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};e.createFromInputFallback=v("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))}),e.ISO_8601=function(){},e.RFC_2822=function(){};var ln=v("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=pe.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:c()}),dn=v("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=pe.apply(null,arguments);return this.isValid()&&e.isValid()?e>this?this:e:c()}),hn=["year","quarter","month","week","day","hour","minute","second","millisecond"];Se("Z",":"),Se("ZZ",""),F("Z",St),F("ZZ",St),H(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=De(St,e)});var cn=/([\+\-]|\d\d)/gi;e.updateOffset=function(){};var fn=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,mn=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;Te.fn=ve.prototype,Te.invalid=function(){return Te(NaN)};var _n=We(1,"add"),yn=We(-1,"subtract");e.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",e.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var gn=v("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)});P(0,["gg",2],0,function(){return this.weekYear()%100}),P(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Ne("gggg","weekYear"),Ne("ggggg","weekYear"),Ne("GGGG","isoWeekYear"),Ne("GGGGG","isoWeekYear"),Y("weekYear","gg"),Y("isoWeekYear","GG"),T("weekYear",1),T("isoWeekYear",1),F("G",Mt),F("g",Mt),F("GG",mt,dt),F("gg",mt,dt),F("GGGG",pt,ct),F("gggg",pt,ct),F("GGGGG",wt,ft),F("ggggg",wt,ft),L(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,s){t[s.substr(0,2)]=g(e)}),L(["gg","GG"],function(t,n,s,i){n[i]=e.parseTwoDigitYear(t)}),P("Q",0,"Qo","quarter"),Y("quarter","Q"),T("quarter",7),F("Q",lt),H("Q",function(e,t){t[Tt]=3*(g(e)-1)}),P("D",["DD",2],"Do","date"),Y("date","D"),T("date",9),F("D",mt),F("DD",mt,dt),F("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),H(["D","DD"],bt),H("Do",function(e,t){t[bt]=g(e.match(mt)[0])});var pn=I("Date",!0);P("DDD",["DDDD",3],"DDDo","dayOfYear"),Y("dayOfYear","DDD"),T("dayOfYear",4),F("DDD",gt),F("DDDD",ht),H(["DDD","DDDD"],function(e,t,n){n._dayOfYear=g(e)}),P("m",["mm",2],0,"minute"),Y("minute","m"),T("minute",14),F("m",mt),F("mm",mt,dt),H(["m","mm"],Wt);var wn=I("Minutes",!1);P("s",["ss",2],0,"second"),Y("second","s"),T("second",15),F("s",mt),F("ss",mt,dt),H(["s","ss"],Rt);var vn=I("Seconds",!1);P("S",0,0,function(){return~~(this.millisecond()/100)}),P(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),P(0,["SSS",3],0,"millisecond"),P(0,["SSSS",4],0,function(){return 10*this.millisecond()}),P(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),P(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),P(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),P(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),P(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),Y("millisecond","ms"),T("millisecond",16),F("S",gt,lt),F("SS",gt,dt),F("SSS",gt,ht);var Mn;for(Mn="SSSS";Mn.length<=9;Mn+="S")F(Mn,vt);for(Mn="S";Mn.length<=9;Mn+="S")H(Mn,Le);var kn=I("Milliseconds",!1);P("z",0,0,"zoneAbbr"),P("zz",0,0,"zoneName");var Sn=m.prototype;Sn.add=_n,Sn.calendar=function(t,n){var s=t||pe(),i=Ye(s,this).startOf("day"),r=e.calendarFormat(this,i)||"sameElse",a=n&&(k(n[r])?n[r].call(this,s):n[r]);return this.format(a||this.localeData().calendar(r,this,pe(s)))},Sn.clone=function(){return new m(this)},Sn.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Ye(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=O(t)){case"year":r=Ce(this,s)/12;break;case"month":r=Ce(this,s);break;case"quarter":r=Ce(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:y(r)},Sn.endOf=function(e){return void 0===(e=O(e))||"millisecond"===e?this:("date"===e&&(e="day"),this.startOf(e).add(1,"isoWeek"===e?"week":e).subtract(1,"ms"))},Sn.format=function(t){t||(t=this.isUtc()?e.defaultFormatUtc:e.defaultFormat);var n=R(this,t);return this.localeData().postformat(n)},Sn.from=function(e,t){return this.isValid()&&(_(e)&&e.isValid()||pe(e).isValid())?Te({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},Sn.fromNow=function(e){return this.from(pe(),e)},Sn.to=function(e,t){return this.isValid()&&(_(e)&&e.isValid()||pe(e).isValid())?Te({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},Sn.toNow=function(e){return this.to(pe(),e)},Sn.get=function(e){return e=O(e),k(this[e])?this[e]():this},Sn.invalidAt=function(){return d(this).overflow},Sn.isAfter=function(e,t){var n=_(e)?e:pe(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=O(s(t)?"millisecond":t))?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},Sn.isBefore=function(e,t){var n=_(e)?e:pe(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=O(s(t)?"millisecond":t))?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},Sn.isBetween=function(e,t,n,s){return("("===(s=s||"()")[0]?this.isAfter(e,n):!this.isBefore(e,n))&&(")"===s[1]?this.isBefore(t,n):!this.isAfter(t,n))},Sn.isSame=function(e,t){var n,s=_(e)?e:pe(e);return!(!this.isValid()||!s.isValid())&&("millisecond"===(t=O(t||"millisecond"))?this.valueOf()===s.valueOf():(n=s.valueOf(),this.clone().startOf(t).valueOf()<=n&&n<=this.clone().endOf(t).valueOf()))},Sn.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},Sn.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},Sn.isValid=function(){return h(this)},Sn.lang=gn,Sn.locale=Fe,Sn.localeData=Ue,Sn.max=dn,Sn.min=ln,Sn.parsingFlags=function(){return u({},d(this))},Sn.set=function(e,t){if("object"==typeof e)for(var n=function(e){var t=[];for(var n in e)t.push({unit:n,priority:it[n]});return t.sort(function(e,t){return e.priority-t.priority}),t}(e=x(e)),s=0;s<n.length;s++)this[n[s].unit](e[n[s].unit]);else if(e=O(e),k(this[e]))return this[e](t);return this},Sn.startOf=function(e){switch(e=O(e)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===e&&this.weekday(0),"isoWeek"===e&&this.isoWeekday(1),"quarter"===e&&this.month(3*Math.floor(this.month()/3)),this},Sn.subtract=yn,Sn.toArray=function(){return[this.year(),this.month(),this.date(),this.hour(),this.minute(),this.second(),this.millisecond()]},Sn.toObject=function(){return{years:this.year(),months:this.month(),date:this.date(),hours:this.hours(),minutes:this.minutes(),seconds:this.seconds(),milliseconds:this.milliseconds()}},Sn.toDate=function(){return new Date(this.valueOf())},Sn.toISOString=function(){if(!this.isValid())return null;var e=this.clone().utc();return e.year()<0||e.year()>9999?R(e,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):k(Date.prototype.toISOString)?this.toDate().toISOString():R(e,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},Sn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',s=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i=t+'[")]';return this.format(n+s+"-MM-DD[T]HH:mm:ss.SSS"+i)},Sn.toJSON=function(){return this.isValid()?this.toISOString():null},Sn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},Sn.unix=function(){return Math.floor(this.valueOf()/1e3)},Sn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},Sn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},Sn.year=Ht,Sn.isLeapYear=function(){return j(this.year())},Sn.weekYear=function(e){return He.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},Sn.isoWeekYear=function(e){return He.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},Sn.quarter=Sn.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},Sn.month=$,Sn.daysInMonth=function(){return z(this.year(),this.month())},Sn.week=Sn.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},Sn.isoWeek=Sn.isoWeeks=function(e){var t=X(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},Sn.weeksInYear=function(){var e=this.localeData()._week;return K(this.year(),e.dow,e.doy)},Sn.isoWeeksInYear=function(){return K(this.year(),1,4)},Sn.date=pn,Sn.day=Sn.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(e=function(e,t){return"string"!=typeof e?e:isNaN(e)?"number"==typeof(e=t.weekdaysParse(e))?e:null:parseInt(e,10)}(e,this.localeData()),this.add(e-t,"d")):t},Sn.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},Sn.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null!=e){var t=function(e,t){return"string"==typeof e?t.weekdaysParse(e)%7||7:isNaN(e)?null:e}(e,this.localeData());return this.day(this.day()%7?t:t-7)}return this.day()||7},Sn.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},Sn.hour=Sn.hours=Bt,Sn.minute=Sn.minutes=wn,Sn.second=Sn.seconds=vn,Sn.millisecond=Sn.milliseconds=kn,Sn.utcOffset=function(t,n,s){var i,r=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(null===(t=De(St,t)))return this}else Math.abs(t)<16&&!s&&(t*=60);return!this._isUTC&&n&&(i=Oe(this)),this._offset=t,this._isUTC=!0,null!=i&&this.add(i,"m"),r!==t&&(!n||this._changeInProgress?Re(this,Te(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,e.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Oe(this)},Sn.utc=function(e){return this.utcOffset(0,e)},Sn.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Oe(this),"m")),this},Sn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=De(kt,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},Sn.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?pe(e).utcOffset():0,(this.utcOffset()-e)%60==0)},Sn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},Sn.isLocal=function(){return!!this.isValid()&&!this._isUTC},Sn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},Sn.isUtc=xe,Sn.isUTC=xe,Sn.zoneAbbr=function(){return this._isUTC?"UTC":""},Sn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},Sn.dates=v("dates accessor is deprecated. Use date instead.",pn),Sn.months=v("months accessor is deprecated. Use month instead",$),Sn.years=v("years accessor is deprecated. Use year instead",Ht),Sn.zone=v("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),Sn.isDSTShifted=v("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!s(this._isDSTShifted))return this._isDSTShifted;var e={};if(f(e,this),(e=ye(e))._a){var t=e._isUTC?l(e._a):pe(e._a);this._isDSTShifted=this.isValid()&&p(e._a,t.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var Dn=D.prototype;Dn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return k(s)?s.call(t,n):s},Dn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.replace(/MMMM|MM|DD|dddd/g,function(e){return e.slice(1)}),this._longDateFormat[e])},Dn.invalidDate=function(){return this._invalidDate},Dn.ordinal=function(e){return this._ordinal.replace("%d",e)},Dn.preparse=Ge,Dn.postformat=Ge,Dn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return k(i)?i(e,t,n,s):i.replace(/%d/i,e)},Dn.pastFuture=function(e,t){var n=this._relativeTime[e>0?"future":"past"];return k(n)?n(t):n.replace(/%s/i,t)},Dn.set=function(e){var t,n;for(n in e)k(t=e[n])?this[n]=t:this["_"+n]=t;this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},Dn.months=function(e,n){return e?t(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||Lt).test(n)?"format":"standalone"][e.month()]:t(this._months)?this._months:this._months.standalone},Dn.monthsShort=function(e,n){return e?t(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[Lt.test(n)?"format":"standalone"][e.month()]:t(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},Dn.monthsParse=function(e,t,n){var s,i,r;if(this._monthsParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=l([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=Nt.call(this._shortMonthsParse,a))?i:null:-1!==(i=Nt.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Nt.call(this._shortMonthsParse,a))?i:-1!==(i=Nt.call(this._longMonthsParse,a))?i:null:-1!==(i=Nt.call(this._longMonthsParse,a))?i:-1!==(i=Nt.call(this._shortMonthsParse,a))?i:null}.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=l([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(r="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},Dn.monthsRegex=function(e){return this._monthsParseExact?(o(this,"_monthsRegex")||q.call(this),e?this._monthsStrictRegex:this._monthsRegex):(o(this,"_monthsRegex")||(this._monthsRegex=It),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},Dn.monthsShortRegex=function(e){return this._monthsParseExact?(o(this,"_monthsRegex")||q.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(o(this,"_monthsShortRegex")||(this._monthsShortRegex=jt),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},Dn.week=function(e){return X(e,this._week.dow,this._week.doy).week},Dn.firstDayOfYear=function(){return this._week.doy},Dn.firstDayOfWeek=function(){return this._week.dow},Dn.weekdays=function(e,n){return e?t(this._weekdays)?this._weekdays[e.day()]:this._weekdays[this._weekdays.isFormat.test(n)?"format":"standalone"][e.day()]:t(this._weekdays)?this._weekdays:this._weekdays.standalone},Dn.weekdaysMin=function(e){return e?this._weekdaysMin[e.day()]:this._weekdaysMin},Dn.weekdaysShort=function(e){return e?this._weekdaysShort[e.day()]:this._weekdaysShort},Dn.weekdaysParse=function(e,t,n){var s,i,r;if(this._weekdaysParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=l([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=Nt.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Nt.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Nt.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Nt.call(this._weekdaysParse,a))?i:-1!==(i=Nt.call(this._shortWeekdaysParse,a))?i:-1!==(i=Nt.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Nt.call(this._shortWeekdaysParse,a))?i:-1!==(i=Nt.call(this._weekdaysParse,a))?i:-1!==(i=Nt.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Nt.call(this._minWeekdaysParse,a))?i:-1!==(i=Nt.call(this._weekdaysParse,a))?i:-1!==(i=Nt.call(this._shortWeekdaysParse,a))?i:null}.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=l([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".",".?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},Dn.weekdaysRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(o(this,"_weekdaysRegex")||(this._weekdaysRegex=Zt),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},Dn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(o(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=$t),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},Dn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(o(this,"_weekdaysRegex")||ee.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(o(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=qt),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},Dn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},Dn.meridiem=function(e,t,n){return e>11?n?"pm":"PM":n?"am":"AM"},ae("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===g(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),e.lang=v("moment.lang is deprecated. Use moment.locale instead.",ae),e.langData=v("moment.langData is deprecated. Use moment.localeData instead.",ue);var Yn=Math.abs,On=$e("ms"),xn=$e("s"),Tn=$e("m"),bn=$e("h"),Pn=$e("d"),Wn=$e("w"),Rn=$e("M"),Cn=$e("y"),Fn=qe("milliseconds"),Un=qe("seconds"),Nn=qe("minutes"),Hn=qe("hours"),Ln=qe("days"),Gn=qe("months"),Vn=qe("years"),jn=Math.round,In={ss:44,s:45,m:45,h:22,d:26,M:11},En=Math.abs,An=ve.prototype;return An.isValid=function(){return this._isValid},An.abs=function(){var e=this._data;return this._milliseconds=Yn(this._milliseconds),this._days=Yn(this._days),this._months=Yn(this._months),e.milliseconds=Yn(e.milliseconds),e.seconds=Yn(e.seconds),e.minutes=Yn(e.minutes),e.hours=Yn(e.hours),e.months=Yn(e.months),e.years=Yn(e.years),this},An.add=function(e,t){return Ee(this,e,t,1)},An.subtract=function(e,t){return Ee(this,e,t,-1)},An.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=O(e))||"year"===e)return t=this._days+s/864e5,n=this._months+ze(t),"month"===e?n:n/12;switch(t=this._days+Math.round(Ze(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},An.asMilliseconds=On,An.asSeconds=xn,An.asMinutes=Tn,An.asHours=bn,An.asDays=Pn,An.asWeeks=Wn,An.asMonths=Rn,An.asYears=Cn,An.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*g(this._months/12):NaN},An._bubble=function(){var e,t,n,s,i,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return r>=0&&a>=0&&o>=0||r<=0&&a<=0&&o<=0||(r+=864e5*Ae(Ze(o)+a),a=0,o=0),u.milliseconds=r%1e3,e=y(r/1e3),u.seconds=e%60,t=y(e/60),u.minutes=t%60,n=y(t/60),u.hours=n%24,a+=y(n/24),i=y(ze(a)),o+=i,a-=Ae(Ze(i)),s=y(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},An.clone=function(){return Te(this)},An.get=function(e){return e=O(e),this.isValid()?this[e+"s"]():NaN},An.milliseconds=Fn,An.seconds=Un,An.minutes=Nn,An.hours=Hn,An.days=Ln,An.weeks=function(){return y(this.days()/7)},An.months=Gn,An.years=Vn,An.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t=this.localeData(),n=function(e,t,n){var s=Te(e).abs(),i=jn(s.as("s")),r=jn(s.as("m")),a=jn(s.as("h")),o=jn(s.as("d")),u=jn(s.as("M")),l=jn(s.as("y")),d=i<=In.ss&&["s",i]||i<In.s&&["ss",i]||r<=1&&["m"]||r<In.m&&["mm",r]||a<=1&&["h"]||a<In.h&&["hh",a]||o<=1&&["d"]||o<In.d&&["dd",o]||u<=1&&["M"]||u<In.M&&["MM",u]||l<=1&&["y"]||["yy",l];return d[2]=t,d[3]=+e>0,d[4]=n,function(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}.apply(null,d)}(this,!e,t);return e&&(n=t.pastFuture(+this,n)),t.postformat(n)},An.toISOString=Be,An.toString=Be,An.toJSON=Be,An.locale=Fe,An.localeData=Ue,An.toIsoString=v("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Be),An.lang=gn,P("X",0,0,"unix"),P("x",0,0,"valueOf"),F("x",Mt),F("X",/[+-]?\d+(\.\d{1,3})?/),H("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))}),H("x",function(e,t,n){n._d=new Date(g(e))}),e.version="2.19.4",function(e){Qe=e}(pe),e.fn=Sn,e.min=function(){return we("isBefore",[].slice.call(arguments,0))},e.max=function(){return we("isAfter",[].slice.call(arguments,0))},e.now=function(){return Date.now?Date.now():+new Date},e.utc=l,e.unix=function(e){return pe(1e3*e)},e.months=function(e,t){return je(e,t,"months")},e.isDate=r,e.locale=ae,e.invalid=c,e.duration=Te,e.isMoment=_,e.weekdays=function(e,t,n){return Ie(e,t,n,"weekdays")},e.parseZone=function(){return pe.apply(null,arguments).parseZone()},e.localeData=ue,e.isDuration=Me,e.monthsShort=function(e,t){return je(e,t,"monthsShort")},e.weekdaysMin=function(e,t,n){return Ie(e,t,n,"weekdaysMin")},e.defineLocale=oe,e.updateLocale=function(e,t){if(null!=t){var n,s,i=Qt;null!=(s=re(e))&&(i=s._config),(n=new D(t=S(i,t))).parentLocale=Xt[e],Xt[e]=n,ae(e)}else null!=Xt[e]&&(null!=Xt[e].parentLocale?Xt[e]=Xt[e].parentLocale:null!=Xt[e]&&delete Xt[e]);return Xt[e]},e.locales=function(){return nt(Xt)},e.weekdaysShort=function(e,t,n){return Ie(e,t,n,"weekdaysShort")},e.normalizeUnits=O,e.relativeTimeRounding=function(e){return void 0===e?jn:"function"==typeof e&&(jn=e,!0)},e.relativeTimeThreshold=function(e,t){return void 0!==In[e]&&(void 0===t?In[e]:(In[e]=t,"s"===e&&(In.ss=t-1),!0))},e.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},e.prototype=Sn,e}); \ No newline at end of file diff --git a/assets/www/js/vendor/moment.nl.js b/assets/www/js/vendor/moment.nl.js deleted file mode 100644 index 8b47a5d107e4d2463f662078fd263b772b328451..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/moment.nl.js +++ /dev/null @@ -1,59 +0,0 @@ -//! moment.js locale configuration -//! locale : dutch (nl) -//! author : RA van Hagen : https://github.com/RavanH - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : - typeof define === 'function' && define.amd ? define(['moment'], factory) : - factory(global.moment) -}(this, function (moment) { 'use strict'; - - var nl = moment.defineLocale('nl', { - months : 'januari|februari|maart|april|mei|juni|juli|augustus|september|oktober|november|december'.split('|'), - monthsShort : 'jan|feb|mrt|apr|mei|jun|jul|aug|sep|okt|nov|dec'.split('|'), - weekdays : 'zondag|maandag|dinsdag|woensdag|donderdag|vrijdag|zaterdag'.split('|'), - weekdaysShort : 'zo.|ma.|di.|wo.|do.|vr.|za.'.split('|'), - weekdaysMin : 'zo|ma|di|wo|do|vr|za'.split('|'), - longDateFormat : { - LT : 'HH:mm', - LTS : 'HH:mm:ss', - L : 'DD/MM/YYYY', - LL : 'D MMMM YYYY', - LLL : 'D MMMM YYYY HH:mm', - LLLL : 'dddd D MMMM YYYY HH:mm' - }, - calendar : { - sameDay: '[Vandaag om] LT', - nextDay: '[Morgen om] LT', - nextWeek: 'dddd [om] LT', - lastDay: '[Gisteren om] LT', - lastWeek: '[afgelopen] dddd [om] LT', - sameElse: 'L' - }, - relativeTime : { - future : 'over %s', - past : '%s geleden', - s : 'enkele seconden', - m : 'een minuut', - mm : '%d minuten', - h : 'een uur', - hh : '%d uren', - d : 'een dag', - dd : '%d dagen', - M : 'een maand', - MM : '%d maanden', - y : 'een jaar', - yy : '%d jaar' - }, - ordinalParse: /\d{1,2}(er|)/, - ordinal : function (number) { - return number + '<sup>e</sup>'; - }, - week : { - dow : 1, // Monday is the first day of the week. - doy : 4 // The week that contains Jan 4th is the first week of the year. - } - }); - - return nl; -})); diff --git a/assets/www/js/vendor/nacl_factory.js b/assets/www/js/vendor/nacl_factory.js deleted file mode 100644 index a01f4205ded63055db8e6b640df6ec1d88bb012b..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/nacl_factory.js +++ /dev/null @@ -1,622 +0,0 @@ -var nacl_factory = { - instantiate: function (on_ready, optionsOpt) { - var options = optionsOpt || {}; - var requested_total_memory = options.requested_total_memory || 33554432; - var undefined_reference_value = (function (v) { return v; })(); - - if (typeof on_ready !== 'function') { - throw new Error("nacl_factory: Expects on_ready callback as first argument. New in v1.1.0."); - } - - return (function (window, document) { - var on_ready_call_needed = false; - var Module = { - TOTAL_MEMORY: requested_total_memory, - onRuntimeInitialized: function () { - if (nacl) { - on_ready(nacl); - } else { - on_ready_call_needed = true; - } - } - }; - if (options.memoryInitializerPrefixURL) { - Module.memoryInitializerPrefixURL = options.memoryInitializerPrefixURL; - } - var nacl_raw = Module; -var Module;if(!Module)Module=(typeof Module!=="undefined"?Module:null)||{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;if(Module["ENVIRONMENT"]){if(Module["ENVIRONMENT"]==="WEB"){ENVIRONMENT_IS_WEB=true}else if(Module["ENVIRONMENT"]==="WORKER"){ENVIRONMENT_IS_WORKER=true}else if(Module["ENVIRONMENT"]==="NODE"){ENVIRONMENT_IS_NODE=true}else if(Module["ENVIRONMENT"]==="SHELL"){ENVIRONMENT_IS_SHELL=true}else{throw new Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.")}}else{ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER}if(ENVIRONMENT_IS_NODE){if(!Module["print"])Module["print"]=console.log;if(!Module["printErr"])Module["printErr"]=console.warn;var nodeFS;var nodePath;Module["read"]=function read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);var ret=nodeFS["readFileSync"](filename);return binary?ret:ret.toString()};Module["readBinary"]=function readBinary(filename){var ret=Module["read"](filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};Module["load"]=function load(f){globalEval(read(f))};if(!Module["thisProgram"]){if(process["argv"].length>1){Module["thisProgram"]=process["argv"][1].replace(/\\/g,"/")}else{Module["thisProgram"]="unknown-program"}}Module["arguments"]=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));Module["inspect"]=(function(){return"[Emscripten Module object]"})}else if(ENVIRONMENT_IS_SHELL){if(!Module["print"])Module["print"]=print;if(typeof printErr!="undefined")Module["printErr"]=printErr;if(typeof read!="undefined"){Module["read"]=read}else{Module["read"]=function read(){throw"no read() available"}}Module["readBinary"]=function readBinary(f){if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}var data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){Module["arguments"]=scriptArgs}else if(typeof arguments!="undefined"){Module["arguments"]=arguments}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module["read"]=function read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};Module["readAsync"]=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response)}else{onerror()}};xhr.onerror=onerror;xhr.send(null)};if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof console!=="undefined"){if(!Module["print"])Module["print"]=function print(x){console.log(x)};if(!Module["printErr"])Module["printErr"]=function printErr(x){console.warn(x)}}else{var TRY_USE_DUMP=false;if(!Module["print"])Module["print"]=TRY_USE_DUMP&&typeof dump!=="undefined"?(function(x){dump(x)}):(function(x){})}if(ENVIRONMENT_IS_WORKER){Module["load"]=importScripts}if(typeof Module["setWindowTitle"]==="undefined"){Module["setWindowTitle"]=(function(title){document.title=title})}}else{throw"Unknown runtime environment. Where are we?"}function globalEval(x){abort("NO_DYNAMIC_EXECUTION=1 was set, cannot eval")}if(!Module["load"]&&Module["read"]){Module["load"]=function load(f){globalEval(Module["read"](f))}}if(!Module["print"]){Module["print"]=(function(){})}if(!Module["printErr"]){Module["printErr"]=Module["print"]}if(!Module["arguments"]){Module["arguments"]=[]}if(!Module["thisProgram"]){Module["thisProgram"]="./this.program"}Module.print=Module["print"];Module.printErr=Module["printErr"];Module["preRun"]=[];Module["postRun"]=[];for(var key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=undefined;var Runtime={setTempRet0:(function(value){tempRet0=value}),getTempRet0:(function(){return tempRet0}),stackSave:(function(){return STACKTOP}),stackRestore:(function(stackTop){STACKTOP=stackTop}),getNativeTypeSize:(function(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return Runtime.QUANTUM_SIZE}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}),getNativeFieldSize:(function(type){return Math.max(Runtime.getNativeTypeSize(type),Runtime.QUANTUM_SIZE)}),STACK_ALIGN:16,prepVararg:(function(ptr,type){if(type==="double"||type==="i64"){if(ptr&7){assert((ptr&7)===4);ptr+=4}}else{assert((ptr&3)===0)}return ptr}),getAlignSize:(function(type,size,vararg){if(!vararg&&(type=="i64"||type=="double"))return 8;if(!type)return Math.min(size,8);return Math.min(size||(type?Runtime.getNativeFieldSize(type):0),Runtime.QUANTUM_SIZE)}),dynCall:(function(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}),functionPointers:[null,null,null,null,null,null,null,null],addFunction:(function(func){for(var i=0;i<Runtime.functionPointers.length;i++){if(!Runtime.functionPointers[i]){Runtime.functionPointers[i]=func;return 1*(1+i)}}throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS."}),removeFunction:(function(index){Runtime.functionPointers[(index-1)/1]=null}),warnOnce:(function(text){if(!Runtime.warnOnce.shown)Runtime.warnOnce.shown={};if(!Runtime.warnOnce.shown[text]){Runtime.warnOnce.shown[text]=1;Module.printErr(text)}}),funcWrappers:{},getFuncWrapper:(function(func,sig){assert(sig);if(!Runtime.funcWrappers[sig]){Runtime.funcWrappers[sig]={}}var sigCache=Runtime.funcWrappers[sig];if(!sigCache[func]){if(sig.length===1){sigCache[func]=function dynCall_wrapper(){return Runtime.dynCall(sig,func)}}else if(sig.length===2){sigCache[func]=function dynCall_wrapper(arg){return Runtime.dynCall(sig,func,[arg])}}else{sigCache[func]=function dynCall_wrapper(){return Runtime.dynCall(sig,func,Array.prototype.slice.call(arguments))}}}return sigCache[func]}),getCompilerSetting:(function(name){throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work"}),stackAlloc:(function(size){var ret=STACKTOP;STACKTOP=STACKTOP+size|0;STACKTOP=STACKTOP+15&-16;return ret}),staticAlloc:(function(size){var ret=STATICTOP;STATICTOP=STATICTOP+size|0;STATICTOP=STATICTOP+15&-16;return ret}),dynamicAlloc:(function(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=(ret+size+15|0)&-16;HEAP32[DYNAMICTOP_PTR>>2]=end;if(end>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){HEAP32[DYNAMICTOP_PTR>>2]=ret;return 0}}return ret}),alignMemory:(function(size,quantum){var ret=size=Math.ceil(size/(quantum?quantum:16))*(quantum?quantum:16);return ret}),makeBigInt:(function(low,high,unsigned){var ret=unsigned?+(low>>>0)+ +(high>>>0)*+4294967296:+(low>>>0)+ +(high|0)*+4294967296;return ret}),GLOBAL_BASE:8,QUANTUM_SIZE:4,__dummy__:0};Module["Runtime"]=Runtime;var ABORT=0;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];if(!func){abort("NO_DYNAMIC_EXECUTION=1 was set, cannot eval")}assert(func,"Cannot call unknown function "+ident+" (perhaps LLVM optimizations or closure removed it?)");return func}var cwrap,ccall;((function(){var JSfuncs={"stackSave":(function(){Runtime.stackSave()}),"stackRestore":(function(){Runtime.stackRestore()}),"arrayToC":(function(arr){var ret=Runtime.stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),"stringToC":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=Runtime.stackAlloc(len);stringToUTF8(str,ret,len)}return ret})};var toC={"string":JSfuncs["stringToC"],"array":JSfuncs["arrayToC"]};ccall=function ccallFunc(ident,returnType,argTypes,args,opts){var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=Runtime.stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);if(returnType==="string")ret=Pointer_stringify(ret);if(stack!==0){if(opts&&opts.async){EmterpreterAsync.asyncFinalizers.push((function(){Runtime.stackRestore(stack)}));return}Runtime.stackRestore(stack)}return ret};cwrap=function cwrap(ident,returnType,argTypes){return(function(){return ccall(ident,returnType,argTypes,arguments)})}}))();Module["ccall"]=ccall;Module["cwrap"]=cwrap;function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}Module["setValue"]=setValue;function getValue(ptr,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":return HEAP8[ptr>>0];case"i8":return HEAP8[ptr>>0];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP32[ptr>>2];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];default:abort("invalid type for setValue: "+type)}return null}Module["getValue"]=getValue;var ALLOC_NORMAL=0;var ALLOC_STACK=1;var ALLOC_STATIC=2;var ALLOC_DYNAMIC=3;var ALLOC_NONE=4;Module["ALLOC_NORMAL"]=ALLOC_NORMAL;Module["ALLOC_STACK"]=ALLOC_STACK;Module["ALLOC_STATIC"]=ALLOC_STATIC;Module["ALLOC_DYNAMIC"]=ALLOC_DYNAMIC;Module["ALLOC_NONE"]=ALLOC_NONE;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="number"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types==="string"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[typeof _malloc==="function"?_malloc:Runtime.staticAlloc,Runtime.stackAlloc,Runtime.staticAlloc,Runtime.dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var ptr=ret,stop;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr<stop;ptr+=4){HEAP32[ptr>>2]=0}stop=ret+size;while(ptr<stop){HEAP8[ptr++>>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i<size){var curr=slab[i];if(typeof curr==="function"){curr=Runtime.getFunctionIndex(curr)}type=singleType||types[i];if(type===0){i++;continue}if(type=="i64")type="i32";setValue(ret+i,curr,type);if(previousType!==type){typeSize=Runtime.getNativeTypeSize(type);previousType=type}i+=typeSize}return ret}Module["allocate"]=allocate;function getMemory(size){if(!staticSealed)return Runtime.staticAlloc(size);if(!runtimeInitialized)return Runtime.dynamicAlloc(size);return _malloc(size)}Module["getMemory"]=getMemory;function Pointer_stringify(ptr,length){if(length===0||!ptr)return"";var hasUtf=0;var t;var i=0;while(1){t=HEAPU8[ptr+i>>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret="";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return Module["UTF8ToString"](ptr)}Module["Pointer_stringify"]=Pointer_stringify;function AsciiToString(ptr){var str="";while(1){var ch=HEAP8[ptr++>>0];if(!ch)return str;str+=String.fromCharCode(ch)}}Module["AsciiToString"]=AsciiToString;function stringToAscii(str,outPtr){return writeAsciiToMemory(str,outPtr,false)}Module["stringToAscii"]=stringToAscii;var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(u8Array,idx){var endPtr=idx;while(u8Array[endPtr])++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var u0,u1,u2,u3,u4,u5;var str="";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}}Module["UTF8ArrayToString"]=UTF8ArrayToString;function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}Module["UTF8ToString"]=UTF8ToString;function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}Module["stringToUTF8Array"]=stringToUTF8Array;function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}Module["stringToUTF8"]=stringToUTF8;function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}Module["lengthBytesUTF8"]=lengthBytesUTF8;var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function demangle(func){var hasLibcxxabi=!!Module["___cxa_demangle"];if(hasLibcxxabi){try{var s=func.substr(1);var len=lengthBytesUTF8(s)+1;var buf=_malloc(len);stringToUTF8(s,buf,len);var status=_malloc(4);var ret=Module["___cxa_demangle"](buf,0,0,status);if(getValue(status,"i32")===0&&ret){return Pointer_stringify(ret)}}catch(e){}finally{if(buf)_free(buf);if(status)_free(status);if(ret)_free(ret)}return func}Runtime.warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){return text.replace(/__Z[\w\d_]+/g,(function(x){var y=demangle(x);return x===y?x:x+" ["+y+"]"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}Module["stackTrace"]=stackTrace;var PAGE_SIZE=4096;var HEAP;var buffer;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module["HEAP8"]=HEAP8=new Int8Array(buffer);Module["HEAP16"]=HEAP16=new Int16Array(buffer);Module["HEAP32"]=HEAP32=new Int32Array(buffer);Module["HEAPU8"]=HEAPU8=new Uint8Array(buffer);Module["HEAPU16"]=HEAPU16=new Uint16Array(buffer);Module["HEAPU32"]=HEAPU32=new Uint32Array(buffer);Module["HEAPF32"]=HEAPF32=new Float32Array(buffer);Module["HEAPF64"]=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed;var STACK_BASE,STACKTOP,STACK_MAX;var DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0;staticSealed=false;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which adjusts the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module["TOTAL_STACK"]||5242880;var TOTAL_MEMORY=Module["TOTAL_MEMORY"]||35e6;var WASM_PAGE_SIZE=64*1024;var totalMemory=WASM_PAGE_SIZE;while(totalMemory<TOTAL_MEMORY||totalMemory<2*TOTAL_STACK){if(totalMemory<16*1024*1024){totalMemory*=2}else{totalMemory+=16*1024*1024}}if(totalMemory!==TOTAL_MEMORY){TOTAL_MEMORY=totalMemory}if(Module["buffer"]){buffer=Module["buffer"]}else{{buffer=new ArrayBuffer(TOTAL_MEMORY)}}updateGlobalBufferViews();function getTotalMemory(){return TOTAL_MEMORY}HEAP32[0]=1668509029;HEAP16[1]=25459;if(HEAPU8[2]!==115||HEAPU8[3]!==99)throw"Runtime error: expected the system to be little-endian!";Module["HEAP"]=HEAP;Module["buffer"]=buffer;Module["HEAP8"]=HEAP8;Module["HEAP16"]=HEAP16;Module["HEAP32"]=HEAP32;Module["HEAPU8"]=HEAPU8;Module["HEAPU16"]=HEAPU16;Module["HEAPU32"]=HEAPU32;Module["HEAPF32"]=HEAPF32;Module["HEAPF64"]=HEAPF64;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Runtime.dynCall("v",func)}else{Runtime.dynCall("vi",func,[callback.arg])}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}Module["addOnPreRun"]=addOnPreRun;function addOnInit(cb){__ATINIT__.unshift(cb)}Module["addOnInit"]=addOnInit;function addOnPreMain(cb){__ATMAIN__.unshift(cb)}Module["addOnPreMain"]=addOnPreMain;function addOnExit(cb){__ATEXIT__.unshift(cb)}Module["addOnExit"]=addOnExit;function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}Module["addOnPostRun"]=addOnPostRun;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}Module["intArrayFromString"]=intArrayFromString;function intArrayToString(array){var ret=[];for(var i=0;i<array.length;i++){var chr=array[i];if(chr>255){chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}Module["intArrayToString"]=intArrayToString;function writeStringToMemory(string,buffer,dontAddNull){Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");var lastChar,end;if(dontAddNull){end=buffer+lengthBytesUTF8(string);lastChar=HEAP8[end]}stringToUTF8(string,buffer,Infinity);if(dontAddNull)HEAP8[end]=lastChar}Module["writeStringToMemory"]=writeStringToMemory;function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}Module["writeArrayToMemory"]=writeArrayToMemory;function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}Module["writeAsciiToMemory"]=writeAsciiToMemory;if(!Math["imul"]||Math["imul"](4294967295,5)!==-5)Math["imul"]=function imul(a,b){var ah=a>>>16;var al=a&65535;var bh=b>>>16;var bl=b&65535;return al*bl+(ah*bl+al*bh<<16)|0};Math.imul=Math["imul"];if(!Math["clz32"])Math["clz32"]=(function(x){x=x>>>0;for(var i=0;i<32;i++){if(x&1<<31-i)return i}return 32});Math.clz32=Math["clz32"];if(!Math["trunc"])Math["trunc"]=(function(x){return x<0?Math.ceil(x):Math.floor(x)});Math.trunc=Math["trunc"];var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_round=Math.round;var Math_min=Math.min;var Math_clz32=Math.clz32;var Math_trunc=Math.trunc;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}Module["addRunDependency"]=addRunDependency;function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["removeRunDependency"]=removeRunDependency;Module["preloadedImages"]={};Module["preloadedAudios"]={};var ASM_CONSTS=[(function(){{return Module.getRandomValue()}}),(function(){{if(Module.getRandomValue===undefined){try{var window_="object"===typeof window?window:self,crypto_=typeof window_.crypto!=="undefined"?window_.crypto:window_.msCrypto,randomValuesStandard=(function(){var buf=new Uint32Array(1);crypto_.getRandomValues(buf);return buf[0]>>>0});randomValuesStandard();Module.getRandomValue=randomValuesStandard}catch(e){try{var crypto=require("crypto"),randomValueNodeJS=(function(){var buf=crypto.randomBytes(4);return(buf[0]<<24|buf[1]<<16|buf[2]<<8|buf[3])>>>0});randomValueNodeJS();Module.getRandomValue=randomValueNodeJS}catch(e){throw"No secure random number generator found"}}}}})];function _emscripten_asm_const_i(code){return ASM_CONSTS[code]()}function _emscripten_asm_const_v(code){return ASM_CONSTS[code]()}STATIC_BASE=8;STATICTOP=STATIC_BASE+34544;__ATINIT__.push();allocate([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,232,149,143,194,178,39,176,69,195,244,137,242,239,152,240,213,223,172,5,211,198,51,57,177,56,2,136,109,83,252,5,199,23,106,112,61,77,216,79,186,60,11,118,13,16,103,15,42,32,83,250,44,57,204,198,78,199,253,119,146,172,3,122,19,232,149,143,194,178,39,176,69,195,244,137,242,239,152,240,213,223,172,5,211,198,51,57,177,56,2,136,109,83,252,133,180,23,106,112,61,77,216,79,186,60,11,118,13,16,103,15,42,32,83,250,44,57,204,198,78,199,253,119,146,172,3,250,236,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,127,237,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,127,238,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,127,217,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,218,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,219,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,8,201,188,243,103,230,9,106,59,167,202,132,133,174,103,187,43,248,148,254,114,243,110,60,241,54,29,95,58,245,79,165,209,130,230,173,127,82,14,81,31,108,62,43,140,104,5,155,107,189,65,251,171,217,131,31,121,33,126,19,25,205,224,91,182,120,89,255,133,114,211,0,189,110,21,255,15,10,106,0,41,192,1,0,152,232,121,255,188,60,160,255,153,113,206,255,0,183,226,254,180,13,72,255,176,160,14,254,211,201,134,255,158,24,143,0,127,105,53,0,96,12,189,0,167,215,251,255,159,76,128,254,106,101,225,255,30,252,4,0,146,12,174,0,89,241,178,254,10,229,166,255,123,221,42,254,30,20,212,0,82,128,3,0,48,209,243,0,119,121,64,255,50,227,156,255,0,110,197,1,103,27,144,0,133,59,140,1,189,241,36,255,248,37,195,1,96,220,55,0,183,76,62,255,195,66,61,0,50,76,164,1,225,164,76,255,76,61,163,255,117,62,31,0,81,145,64,255,118,65,14,0,162,115,214,255,6,138,46,0,124,230,244,255,10,138,143,0,52,26,194,0,184,244,76,0,129,143,41,1,190,244,19,255,123,170,122,255,98,129,68,0,121,213,147,0,86,101,30,255,161,103,155,0,140,89,67,255,239,229,190,1,67,11,181,0,198,240,137,254,238,69,188,255,67,151,238,0,19,42,108,255,229,85,113,1,50,68,135,255,17,106,9,0,50,103,1,255,80,1,168,1,35,152,30,255,16,168,185,1,56,89,232,255,101,210,252,0,41,250,71,0,204,170,79,255,14,46,239,255,80,77,239,0,189,214,75,255,17,141,249,0,38,80,76,255,190,85,117,0,86,228,170,0,156,216,208,1,195,207,164,255,150,66,76,255,175,225,16,255,141,80,98,1,76,219,242,0,198,162,114,0,46,218,152,0,155,43,241,254,155,160,104,255,51,187,165,0,2,17,175,0,66,84,160,1,247,58,30,0,35,65,53,254,69,236,191,0,45,134,245,1,163,123,221,0,32,110,20,255,52,23,165,0,186,214,71,0,233,176,96,0,242,239,54,1,57,89,138,0,83,0,84,255,136,160,100,0,92,142,120,254,104,124,190,0,181,177,62,255,250,41,85,0,152,130,42,1,96,252,246,0,151,151,63,254,239,133,62,0,32,56,156,0,45,167,189,255,142,133,179,1,131,86,211,0,187,179,150,254,250,170,14,255,210,163,78,0,37,52,151,0,99,77,26,0,238,156,213,255,213,192,209,1,73,46,84,0,20,65,41,1,54,206,79,0,201,131,146,254,170,111,24,255,177,33,50,254,171,38,203,255,78,247,116,0,209,221,153,0,133,128,178,1,58,44,25,0,201,39,59,1,189,19,252,0,49,229,210,1,117,187,117,0,181,179,184,1,0,114,219,0,48,94,147,0,245,41,56,0,125,13,204,254,244,173,119,0,44,221,32,254,84,234,20,0,249,160,198,1,236,126,234,255,47,99,168,254,170,226,153,255,102,179,216,0,226,141,122,255,122,66,153,254,182,245,134,0,227,228,25,1,214,57,235,255,216,173,56,255,181,231,210,0,119,128,157,255,129,95,136,255,110,126,51,0,2,169,183,255,7,130,98,254,69,176,94,255,116,4,227,1,217,242,145,255,202,173,31,1,105,1,39,255,46,175,69,0,228,47,58,255,215,224,69,254,207,56,69,255,16,254,139,255,23,207,212,255,202,20,126,255,95,213,96,255,9,176,33,0,200,5,207,255,241,42,128,254,35,33,192,255,248,229,196,1,129,17,120,0,251,103,151,255,7,52,112,255,140,56,66,255,40,226,245,255,217,70,37,254,172,214,9,255,72,67,134,1,146,192,214,255,44,38,112,0,68,184,75,255,206,90,251,0,149,235,141,0,181,170,58,0,116,244,239,0,92,157,2,0,102,173,98,0,233,137,96,1,127,49,203,0,5,155,148,0,23,148,9,255,211,122,12,0,34,134,26,255,219,204,136,0,134,8,41,255,224,83,43,254,85,25,247,0,109,127,0,254,169,136,48,0,238,119,219,255,231,173,213,0,206,18,254,254,8,186,7,255,126,9,7,1,111,42,72,0,111,52,236,254,96,63,141,0,147,191,127,254,205,78,192,255,14,106,237,1,187,219,76,0,175,243,187,254,105,89,173,0,85,25,89,1,162,243,148,0,2,118,209,254,33,158,9,0,139,163,46,255,93,70,40,0,108,42,142,254,111,252,142,255,155,223,144,0,51,229,167,255,73,252,155,255,94,116,12,255,152,160,218,255,156,238,37,255,179,234,207,255,197,0,179,255,154,164,141,0,225,196,104,0,10,35,25,254,209,212,242,255,97,253,222,254,184,101,229,0,222,18,127,1,164,136,135,255,30,207,140,254,146,97,243,0,129,192,26,254,201,84,33,255,111,10,78,255,147,81,178,255,4,4,24,0,161,238,215,255,6,141,33,0,53,215,14,255,41,181,208,255,231,139,157,0,179,203,221,255,255,185,113,0,189,226,172,255,113,66,214,255,202,62,45,255,102,64,8,255,78,174,16,254,133,117,68,255,133,59,140,1,189,241,36,255,248,37,195,1,96,220,55,0,183,76,62,255,195,66,61,0,50,76,164,1,225,164,76,255,76,61,163,255,117,62,31,0,81,145,64,255,118,65,14,0,162,115,214,255,6,138,46,0,124,230,244,255,10,138,143,0,52,26,194,0,184,244,76,0,129,143,41,1,190,244,19,255,123,170,122,255,98,129,68,0,121,213,147,0,86,101,30,255,161,103,155,0,140,89,67,255,239,229,190,1,67,11,181,0,198,240,137,254,238,69,188,255,234,113,60,255,37,255,57,255,69,178,182,254,128,208,179,0,118,26,125,254,3,7,214,255,241,50,77,255,85,203,197,255,211,135,250,255,25,48,100,255,187,213,180,254,17,88,105,0,83,209,158,1,5,115,98,0,4,174,60,254,171,55,110,255,217,181,17,255,20,188,170,0,146,156,102,254,87,214,174,255,114,122,155,1,233,44,170,0,127,8,239,1,214,236,234,0,175,5,219,0,49,106,61,255,6,66,208,255,2,106,110,255,81,234,19,255,215,107,192,255,67,151,238,0,19,42,108,255,229,85,113,1,50,68,135,255,17,106,9,0,50,103,1,255,80,1,168,1,35,152,30,255,16,168,185,1,56,89,232,255,101,210,252,0,41,250,71,0,204,170,79,255,14,46,239,255,80,77,239,0,189,214,75,255,17,141,249,0,38,80,76,255,190,85,117,0,86,228,170,0,156,216,208,1,195,207,164,255,150,66,76,255,175,225,16,255,141,80,98,1,76,219,242,0,198,162,114,0,46,218,152,0,155,43,241,254,155,160,104,255,178,9,252,254,100,110,212,0,14,5,167,0,233,239,163,255,28,151,157,1,101,146,10,255,254,158,70,254,71,249,228,0,88,30,50,0,68,58,160,255,191,24,104,1,129,66,129,255,192,50,85,255,8,179,138,255,38,250,201,0,115,80,160,0,131,230,113,0,125,88,147,0,90,68,199,0,253,76,158,0,28,255,118,0,113,250,254,0,66,75,46,0,230,218,43,0,229,120,186,1,148,68,43,0,136,124,238,1,187,107,197,255,84,53,246,255,51,116,254,255,51,187,165,0,2,17,175,0,66,84,160,1,247,58,30,0,35,65,53,254,69,236,191,0,45,134,245,1,163,123,221,0,32,110,20,255,52,23,165,0,186,214,71,0,233,176,96,0,242,239,54,1,57,89,138,0,83,0,84,255,136,160,100,0,92,142,120,254,104,124,190,0,181,177,62,255,250,41,85,0,152,130,42,1,96,252,246,0,151,151,63,254,239,133,62,0,32,56,156,0,45,167,189,255,142,133,179,1,131,86,211,0,187,179,150,254,250,170,14,255,68,113,21,255,222,186,59,255,66,7,241,1,69,6,72,0,86,156,108,254,55,167,89,0,109,52,219,254,13,176,23,255,196,44,106,255,239,149,71,255,164,140,125,255,159,173,1,0,51,41,231,0,145,62,33,0,138,111,93,1,185,83,69,0,144,115,46,0,97,151,16,255,24,228,26,0,49,217,226,0,113,75,234,254,193,153,12,255,182,48,96,255,14,13,26,0,128,195,249,254,69,193,59,0,132,37,81,254,125,106,60,0,214,240,169,1,164,227,66,0,210,163,78,0,37,52,151,0,99,77,26,0,238,156,213,255,213,192,209,1,73,46,84,0,20,65,41,1,54,206,79,0,201,131,146,254,170,111,24,255,177,33,50,254,171,38,203,255,78,247,116,0,209,221,153,0,133,128,178,1,58,44,25,0,201,39,59,1,189,19,252,0,49,229,210,1,117,187,117,0,181,179,184,1,0,114,219,0,48,94,147,0,245,41,56,0,125,13,204,254,244,173,119,0,44,221,32,254,84,234,20,0,249,160,198,1,236,126,234,255,143,62,221,0,129,89,214,255,55,139,5,254,68,20,191,255,14,204,178,1,35,195,217,0,47,51,206,1,38,246,165,0,206,27,6,254,158,87,36,0,217,52,146,255,125,123,215,255,85,60,31,255,171,13,7,0,218,245,88,254,252,35,60,0,55,214,160,255,133,101,56,0,224,32,19,254,147,64,234,0,26,145,162,1,114,118,125,0,248,252,250,0,101,94,196,255,198,141,226,254,51,42,182,0,135,12,9,254,109,172,210,255,197,236,194,1,241,65,154,0,48,156,47,255,153,67,55,255,218,165,34,254,74,180,179,0,218,66,71,1,88,122,99,0,212,181,219,255,92,42,231,255,239,0,154,0,245,77,183,255,94,81,170,1,18,213,216,0,171,93,71,0,52,94,248,0,18,151,161,254,197,209,66,255,174,244,15,254,162,48,183,0,49,61,240,254,182,93,195,0,199,228,6,1,200,5,17,255,137,45,237,255,108,148,4,0,90,79,237,255,39,63,77,255,53,82,207,1,142,22,118,255,101,232,18,1,92,26,67,0,5,200,88,255,33,168,138,255,149,225,72,0,2,209,27,255,44,245,168,1,220,237,17,255,30,211,105,254,141,238,221,0,128,80,245,254,111,254,14,0,222,95,190,1,223,9,241,0,146,76,212,255,108,205,104,255,63,117,153,0,144,69,48,0,35,228,111,0,192,33,193,255,112,214,190,254,115,152,151,0,23,102,88,0,51,74,248,0,226,199,143,254,204,162,101,255,208,97,189,1,245,104,18,0,230,246,30,255,23,148,69,0,110,88,52,254,226,181,89,255,208,47,90,254,114,161,80,255,33,116,248,0,179,152,87,255,69,144,177,1,88,238,26,255,58,32,113,1,1,77,69,0,59,121,52,255,152,238,83,0,52,8,193,0,231,39,233,255,199,34,138,0,222,68,173,0,91,57,242,254,220,210,127,255,192,7,246,254,151,35,187,0,195,236,165,0,111,93,206,0,212,247,133,1,154,133,209,255,155,231,10,0,64,78,38,0,122,249,100,1,30,19,97,255,62,91,249,1,248,133,77,0,197,63,168,254,116,10,82,0,184,236,113,254,212,203,194,255,61,100,252,254,36,5,202,255,119,91,153,255,129,79,29,0,103,103,171,254,237,215,111,255,216,53,69,0,239,240,23,0,194,149,221,255,38,225,222,0,232,255,180,254,118,82,133,255,57,209,177,1,139,232,133,0,158,176,46,254,194,115,46,0,88,247,229,1,28,103,191,0,221,222,175,254,149,235,44,0,151,228,25,254,218,105,103,0,142,85,210,0,149,129,190,255,213,65,94,254,117,134,224,255,82,198,117,0,157,221,220,0,163,101,36,0,197,114,37,0,104,172,166,254,11,182,0,0,81,72,188,255,97,188,16,255,69,6,10,0,199,147,145,255,8,9,115,1,65,214,175,255,217,173,209,0,80,127,166,0,247,229,4,254,167,183,124,255,90,28,204,254,175,59,240,255,11,41,248,1,108,40,51,255,144,177,195,254,150,250,126,0,138,91,65,1,120,60,222,255,245,193,239,0,29,214,189,255,128,2,25,0,80,154,162,0,77,220,107,1,234,205,74,255,54,166,103,255,116,72,9,0,228,94,47,255,30,200,25,255,35,214,89,255,61,176,140,255,83,226,163,255,75,130,172,0,128,38,17,0,95,137,152,255,215,124,159,1,79,93,0,0,148,82,157,254,195,130,251,255,40,202,76,255,251,126,224,0,157,99,62,254,207,7,225,255,96,68,195,0,140,186,157,255,131,19,231,255,42,128,254,0,52,219,61,254,102,203,72,0,141,7,11,255,186,164,213,0,31,122,119,0,133,242,145,0,208,252,232,255,91,213,182,255,143,4,250,254,249,215,74,0,165,30,111,1,171,9,223,0,229,123,34,1,92,130,26,255,77,155,45,1,195,139,28,255,59,224,78,0,136,17,247,0,108,121,32,0,79,250,189,255,96,227,252,254,38,241,62,0,62,174,125,255,155,111,93,255,10,230,206,1,97,197,40,255,0,49,57,254,65,250,13,0,18,251,150,255,220,109,210,255,5,174,166,254,44,129,189,0,235,35,147,255,37,247,141,255,72,141,4,255,103,107,255,0,247,90,4,0,53,44,42,0,2,30,240,0,4,59,63,0,88,78,36,0,113,167,180,0,190,71,193,255,199,158,164,255,58,8,172,0,77,33,12,0,65,63,3,0,153,77,33,255,172,254,102,1,228,221,4,255,87,30,254,1,146,41,86,255,138,204,239,254,108,141,17,255,187,242,135,0,210,208,127,0,68,45,14,254,73,96,62,0,81,60,24,255,170,6,36,255,3,249,26,0,35,213,109,0,22,129,54,255,21,35,225,255,234,61,56,255,58,217,6,0,143,124,88,0,236,126,66,0,209,38,183,255,34,238,6,255,174,145,102,0,95,22,211,0,196,15,153,254,46,84,232,255,117,34,146,1,231,250,74,255,27,134,100,1,92,187,195,255,170,198,112,0,120,28,42,0,209,70,67,0,29,81,31,0,29,168,100,1,169,173,160,0,107,35,117,0,62,96,59,255,81,12,69,1,135,239,190,255,220,252,18,0,163,220,58,255,137,137,188,255,83,102,109,0,96,6,76,0,234,222,210,255,185,174,205,1,60,158,213,255,13,241,214,0,172,129,140,0,93,104,242,0,192,156,251,0,43,117,30,0,225,81,158,0,127,232,218,0,226,28,203,0,233,27,151,255,117,43,5,255,242,14,47,255,33,20,6,0,137,251,44,254,27,31,245,255,183,214,125,254,40,121,149,0,186,158,213,255,89,8,227,0,69,88,0,254,203,135,225,0,201,174,203,0,147,71,184,0,18,121,41,254,94,5,78,0,224,214,240,254,36,5,180,0,251,135,231,1,163,138,212,0,210,249,116,254,88,129,187,0,19,8,49,254,62,14,144,255,159,76,211,0,214,51,82,0,109,117,228,254,103,223,203,255,75,252,15,1,154,71,220,255,23,13,91,1,141,168,96,255,181,182,133,0,250,51,55,0,234,234,212,254,175,63,158,0,39,240,52,1,158,189,36,255,213,40,85,1,32,180,247,255,19,102,26,1,84,24,97,255,69,21,222,0,148,139,122,255,220,213,235,1,232,203,255,0,121,57,147,0,227,7,154,0,53,22,147,1,72,1,225,0,82,134,48,254,83,60,157,255,145,72,169,0,34,103,239,0,198,233,47,0,116,19,4,255,184,106,9,255,183,129,83,0,36,176,230,1,34,103,72,0,219,162,134,0,245,42,158,0,32,149,96,254,165,44,144,0,202,239,72,254,215,150,5,0,42,66,36,1,132,215,175,0,86,174,86,255,26,197,156,255,49,232,135,254,103,182,82,0,253,128,176,1,153,178,122,0,245,250,10,0,236,24,178,0,137,106,132,0,40,29,41,0,50,30,152,255,124,105,38,0,230,191,75,0,143,43,170,0,44,131,20,255,44,13,23,255,237,255,155,1,159,109,100,255,112,181,24,255,104,220,108,0,55,211,131,0,99,12,213,255,152,151,145,255,238,5,159,0,97,155,8,0,33,108,81,0,1,3,103,0,62,109,34,255,250,155,180,0,32,71,195,255,38,70,145,1,159,95,245,0,69,229,101,1,136,28,240,0,79,224,25,0,78,110,121,255,248,168,124,0,187,128,247,0,2,147,235,254,79,11,132,0,70,58,12,1,181,8,163,255,79,137,133,255,37,170,11,255,141,243,85,255,176,231,215,255,204,150,164,255,239,215,39,255,46,87,156,254,8,163,88,255,172,34,232,0,66,44,102,255,27,54,41,254,236,99,87,255,41,123,169,1,52,114,43,0,117,134,40,0,155,134,26,0,231,207,91,254,35,132,38,255,19,102,125,254,36,227,133,255,118,3,113,255,29,13,124,0,152,96,74,1,88,146,206,255,167,191,220,254,162,18,88,255,182,100,23,0,31,117,52,0,81,46,106,1,12,2,7,0,69,80,201,1,209,246,172,0,12,48,141,1,224,211,88,0,116,226,159,0,122,98,130,0,65,236,234,1,225,226,9,255,207,226,123,1,89,214,59,0,112,135,88,1,90,244,203,255,49,11,38,1,129,108,186,0,89,112,15,1,101,46,204,255,127,204,45,254,79,255,221,255,51,73,18,255,127,42,101,255,241,21,202,0,160,227,7,0,105,50,236,0,79,52,197,255,104,202,208,1,180,15,16,0,101,197,78,255,98,77,203,0,41,185,241,1,35,193,124,0,35,155,23,255,207,53,192,0,11,125,163,1,249,158,185,255,4,131,48,0,21,93,111,255,61,121,231,1,69,200,36,255,185,48,185,255,111,238,21,255,39,50,25,255,99,215,163,255,87,212,30,255,164,147,5,255,128,6,35,1,108,223,110,255,194,76,178,0,74,101,180,0,243,47,48,0,174,25,43,255,82,173,253,1,54,114,192,255,40,55,91,0,215,108,176,255,11,56,7,0,224,233,76,0,209,98,202,254,242,25,125,0,44,193,93,254,203,8,177,0,135,176,19,0,112,71,213,255,206,59,176,1,4,67,26,0,14,143,213,254,42,55,208,255,60,67,120,0,193,21,163,0,99,164,115,0,10,20,118,0,156,212,222,254,160,7,217,255,114,245,76,1,117,59,123,0,176,194,86,254,213,15,176,0,78,206,207,254,213,129,59,0,233,251,22,1,96,55,152,255,236,255,15,255,197,89,84,255,93,149,133,0,174,160,113,0,234,99,169,255,152,116,88,0,144,164,83,255,95,29,198,255,34,47,15,255,99,120,134,255,5,236,193,0,249,247,126,255,147,187,30,0,50,230,117,255,108,217,219,255,163,81,166,255,72,25,169,254,155,121,79,255,28,155,89,254,7,126,17,0,147,65,33,1,47,234,253,0,26,51,18,0,105,83,199,255,163,196,230,0,113,248,164,0,226,254,218,0,189,209,203,255,164,247,222,254,255,35,165,0,4,188,243,1,127,179,71,0,37,237,254,255,100,186,240,0,5,57,71,254,103,72,73,255,244,18,81,254,229,210,132,255,238,6,180,255,11,229,174,255,227,221,192,1,17,49,28,0,163,215,196,254,9,118,4,255,51,240,71,0,113,129,109,255,76,240,231,0,188,177,127,0,125,71,44,1,26,175,243,0,94,169,25,254,27,230,29,0,15,139,119,1,168,170,186,255,172,197,76,255,252,75,188,0,137,124,196,0,72,22,96,255,45,151,249,1,220,145,100,0,64,192,159,255,120,239,226,0,129,178,146,0,0,192,125,0,235,138,234,0,183,157,146,0,83,199,192,255,184,172,72,255,73,225,128,0,77,6,250,255,186,65,67,0,104,246,207,0,188,32,138,255,218,24,242,0,67,138,81,254,237,129,121,255,20,207,150,1,41,199,16,255,6,20,128,0,159,118,5,0,181,16,143,255,220,38,15,0,23,64,147,254,73,26,13,0,87,228,57,1,204,124,128,0,43,24,223,0,219,99,199,0,22,75,20,255,19,27,126,0,157,62,215,0,110,29,230,0,179,167,255,1,54,252,190,0,221,204,182,254,179,158,65,255,81,157,3,0,194,218,159,0,170,223,0,0,224,11,32,255,38,197,98,0,168,164,37,0,23,88,7,1,164,186,110,0,96,36,134,0,234,242,229,0,250,121,19,0,242,254,112,255,3,47,94,1,9,239,6,255,81,134,153,254,214,253,168,255,67,124,224,0,245,95,74,0,28,30,44,254,1,109,220,255,178,89,89,0,252,36,76,0,24,198,46,255,76,77,111,0,134,234,136,255,39,94,29,0,185,72,234,255,70,68,135,255,231,102,7,254,77,231,140,0,167,47,58,1,148,97,118,255,16,27,225,1,166,206,143,255,110,178,214,255,180,131,162,0,143,141,225,1,13,218,78,255,114,153,33,1,98,104,204,0,175,114,117,1,167,206,75,0,202,196,83,1,58,64,67,0,138,47,111,1,196,247,128,255,137,224,224,254,158,112,207,0,154,100,255,1,134,37,107,0,198,128,79,255,127,209,155,255,163,254,185,254,60,14,243,0,31,219,112,254,29,217,65,0,200,13,116,254,123,60,196,255,224,59,184,254,242,89,196,0,123,16,75,254,149,16,206,0,69,254,48,1,231,116,223,255,209,160,65,1,200,80,98,0,37,194,184,254,148,63,34,0,139,240,65,255,217,144,132,255,56,38,45,254,199,120,210,0,108,177,166,255,160,222,4,0,220,126,119,254,165,107,160,255,82,220,248,1,241,175,136,0,144,141,23,255,169,138,84,0,160,137,78,255,226,118,80,255,52,27,132,255,63,96,139,255,152,250,39,0,188,155,15,0,232,51,150,254,40,15,232,255,240,229,9,255,137,175,27,255,75,73,97,1,218,212,11,0,135,5,162,1,107,185,213,0,2,249,107,255,40,242,70,0,219,200,25,0,25,157,13,0,67,82,80,255,196,249,23,255,145,20,149,0,50,72,146,0,94,76,148,1,24,251,65,0,31,192,23,0,184,212,201,255,123,233,162,1,247,173,72,0,162,87,219,254,126,134,89,0,159,11,12,254,166,105,29,0,73,27,228,1,113,120,183,255,66,163,109,1,212,143,11,255,159,231,168,1,255,128,90,0,57,14,58,254,89,52,10,255,253,8,163,1,0,145,210,255,10,129,85,1,46,181,27,0,103,136,160,254,126,188,209,255,34,35,111,0,215,219,24,255,212,11,214,254,101,5,118,0,232,197,133,255,223,167,109,255,237,80,86,255,70,139,94,0,158,193,191,1,155,15,51,255,15,190,115,0,78,135,207,255,249,10,27,1,181,125,233,0,95,172,13,254,170,213,161,255,39,236,138,255,95,93,87,255,190,128,95,0,125,15,206,0,166,150,159,0,227,15,158,255,206,158,120,255,42,141,128,0,101,178,120,1,156,109,131,0,218,14,44,254,247,168,206,255,212,112,28,0,112,17,228,255,90,16,37,1,197,222,108,0,254,207,83,255,9,90,243,255,243,244,172,0,26,88,115,255,205,116,122,0,191,230,193,0,180,100,11,1,217,37,96,255,154,78,156,0,235,234,31,255,206,178,178,255,149,192,251,0,182,250,135,0,246,22,105,0,124,193,109,255,2,210,149,255,169,17,170,0,0,96,110,255,117,9,8,1,50,123,40,255,193,189,99,0,34,227,160,0,48,80,70,254,211,51,236,0,45,122,245,254,44,174,8,0,173,37,233,255,158,65,171,0,122,69,215,255,90,80,2,255,131,106,96,254,227,114,135,0,205,49,119,254,176,62,64,255,82,51,17,255,241,20,243,255,130,13,8,254,128,217,243,255,162,27,1,254,90,118,241,0,246,198,246,255,55,16,118,255,200,159,157,0,163,17,1,0,140,107,121,0,85,161,118,255,38,0,149,0,156,47,238,0,9,166,166,1,75,98,181,255,50,74,25,0,66,15,47,0,139,225,159,0,76,3,142,255,14,238,184,0,11,207,53,255,183,192,186,1,171,32,174,255,191,76,221,1,247,170,219,0,25,172,50,254,217,9,233,0,203,126,68,255,183,92,48,0,127,167,183,1,65,49,254,0,16,63,127,1,254,21,170,255,59,224,127,254,22,48,63,255,27,78,130,254,40,195,29,0,250,132,112,254,35,203,144,0,104,169,168,0,207,253,30,255,104,40,38,254,94,228,88,0,206,16,128,255,212,55,122,255,223,22,234,0,223,197,127,0,253,181,181,1,145,102,118,0,236,153,36,255,212,217,72,255,20,38,24,254,138,62,62,0,152,140,4,0,230,220,99,255,1,21,212,255,148,201,231,0,244,123,9,254,0,171,210,0,51,58,37,255,1,255,14,255,244,183,145,254,0,242,166,0,22,74,132,0,121,216,41,0,95,195,114,254,133,24,151,255,156,226,231,255,247,5,77,255,246,148,115,254,225,92,81,255,222,80,246,254,170,123,89,255,74,199,141,0,29,20,8,255,138,136,70,255,93,75,92,0,221,147,49,254,52,126,226,0,229,124,23,0,46,9,181,0,205,64,52,1,131,254,28,0,151,158,212,0,131,64,78,0,206,25,171,0,0,230,139,0,191,253,110,254,103,247,167,0,64,40,40,1,42,165,241,255,59,75,228,254,124,243,189,255,196,92,178,255,130,140,86,255,141,89,56,1,147,198,5,255,203,248,158,254,144,162,141,0,11,172,226,0,130,42,21,255,1,167,143,255,144,36,36,255,48,88,164,254,168,170,220,0,98,71,214,0,91,208,79,0,159,76,201,1,166,42,214,255,69,255,0,255,6,128,125,255,190,1,140,0,146,83,218,255,215,238,72,1,122,127,53,0,189,116,165,255,84,8,66,255,214,3,208,255,213,110,133,0,195,168,44,1,158,231,69,0,162,64,200,254,91,58,104,0,182,58,187,254,249,228,136,0,203,134,76,254,99,221,233,0,75,254,214,254,80,69,154,0,64,152,248,254,236,136,202,255,157,105,153,254,149,175,20,0,22,35,19,255,124,121,233,0,186,250,198,254,132,229,139,0,137,80,174,255,165,125,68,0,144,202,148,254,235,239,248,0,135,184,118,0,101,94,17,255,122,72,70,254,69,130,146,0,127,222,248,1,69,127,118,255,30,82,215,254,188,74,19,255,229,167,194,254,117,25,66,255,65,234,56,254,213,22,156,0,151,59,93,254,45,28,27,255,186,126,164,255,32,6,239,0,127,114,99,1,219,52,2,255,99,96,166,254,62,190,126,255,108,222,168,1,75,226,174,0,230,226,199,0,60,117,218,255,252,248,20,1,214,188,204,0,31,194,134,254,123,69,192,255,169,173,36,254,55,98,91,0,223,42,102,254,137,1,102,0,157,90,25,0,239,122,64,255,252,6,233,0,7,54,20,255,82,116,174,0,135,37,54,255,15,186,125,0,227,112,175,255,100,180,225,255,42,237,244,255,244,173,226,254,248,18,33,0,171,99,150,255,74,235,50,255,117,82,32,254,106,168,237,0,207,109,208,1,228,9,186,0,135,60,169,254,179,92,143,0,244,170,104,255,235,45,124,255,70,99,186,0,117,137,183,0,224,31,215,0,40,9,100,0,26,16,95,1,68,217,87,0,8,151,20,255,26,100,58,255,176,165,203,1,52,118,70,0,7,32,254,254,244,254,245,255,167,144,194,255,125,113,23,255,176,121,181,0,136,84,209,0,138,6,30,255,89,48,28,0,33,155,14,255,25,240,154,0,141,205,109,1,70,115,62,255,20,40,107,254,138,154,199,255,94,223,226,255,157,171,38,0,163,177,25,254,45,118,3,255,14,222,23,1,209,190,81,255,118,123,232,1,13,213,101,255,123,55,123,254,27,246,165,0,50,99,76,255,140,214,32,255,97,65,67,255,24,12,28,0,174,86,78,1,64,247,96,0,160,135,67,0,66,55,243,255,147,204,96,255,26,6,33,255,98,51,83,1,153,213,208,255,2,184,54,255,25,218,11,0,49,67,246,254,18,149,72,255,13,25,72,0,42,79,214,0,42,4,38,1,27,139,144,255,149,187,23,0,18,164,132,0,245,84,184,254,120,198,104,255,126,218,96,0,56,117,234,255,13,29,214,254,68,47,10,255,167,154,132,254,152,38,198,0,66,178,89,255,200,46,171,255,13,99,83,255,210,187,253,255,170,45,42,1,138,209,124,0,214,162,141,0,12,230,156,0,102,36,112,254,3,147,67,0,52,215,123,255,233,171,54,255,98,137,62,0,247,218,39,255,231,218,236,0,247,191,127,0,195,146,84,0,165,176,92,255,19,212,94,255,17,74,227,0,88,40,153,1,198,147,1,255,206,67,245,254,240,3,218,255,61,141,213,255,97,183,106,0,195,232,235,254,95,86,154,0,209,48,205,254,118,209,241,255,240,120,223,1,213,29,159,0,163,127,147,255,13,218,93,0,85,24,68,254,70,20,80,255,189,5,140,1,82,97,254,255,99,99,191,255,132,84,133,255,107,218,116,255,112,122,46,0,105,17,32,0,194,160,63,255,68,222,39,1,216,253,92,0,177,105,205,255,149,201,195,0,42,225,11,255,40,162,115,0,9,7,81,0,165,218,219,0,180,22,0,254,29,146,252,255,146,207,225,1,180,135,96,0,31,163,112,0,177,11,219,255,133,12,193,254,43,78,50,0,65,113,121,1,59,217,6,255,110,94,24,1,112,172,111,0,7,15,96,0,36,85,123,0,71,150,21,255,208,73,188,0,192,11,167,1,213,245,34,0,9,230,92,0,162,142,39,255,215,90,27,0,98,97,89,0,94,79,211,0,90,157,240,0,95,220,126,1,102,176,226,0,36,30,224,254,35,31,127,0,231,232,115,1,85,83,130,0,210,73,245,255,47,143,114,255,68,65,197,0,59,72,62,255,183,133,173,254,93,121,118,255,59,177,81,255,234,69,173,255,205,128,177,0,220,244,51,0,26,244,209,1,73,222,77,255,163,8,96,254,150,149,211,0,158,254,203,1,54,127,139,0,161,224,59,0,4,109,22,255,222,42,45,255,208,146,102,255,236,142,187,0,50,205,245,255,10,74,89,254,48,79,142,0,222,76,130,255,30,166,63,0,236,12,13,255,49,184,244,0,187,113,102,0,218,101,253,0,153,57,182,254,32,150,42,0,25,198,146,1,237,241,56,0,140,68,5,0,91,164,172,255,78,145,186,254,67,52,205,0,219,207,129,1,109,115,17,0,54,143,58,1,21,248,120,255,179,255,30,0,193,236,66,255,1,255,7,255,253,192,48,255,19,69,217,1,3,214,0,255,64,101,146,1,223,125,35,255,235,73,179,255,249,167,226,0,225,175,10,1,97,162,58,0,106,112,171,1,84,172,5,255,133,140,178,255,134,245,142,0,97,90,125,255,186,203,185,255,223,77,23,255,192,92,106,0,15,198,115,255,217,152,248,0,171,178,120,255,228,134,53,0,176,54,193,1,250,251,53,0,213,10,100,1,34,199,106,0,151,31,244,254,172,224,87,255,14,237,23,255,253,85,26,255,127,39,116,255,172,104,100,0,251,14,70,255,212,208,138,255,253,211,250,0,176,49,165,0,15,76,123,255,37,218,160,255,92,135,16,1,10,126,114,255,70,5,224,255,247,249,141,0,68,20,60,1,241,210,189,255,195,217,187,1,151,3,113,0,151,92,174,0,231,62,178,255,219,183,225,0,23,23,33,255,205,181,80,0,57,184,248,255,67,180,1,255,90,123,93,255,39,0,162,255,96,248,52,255,84,66,140,0,34,127,228,255,194,138,7,1,166,110,188,0,21,17,155,1,154,190,198,255,214,80,59,255,18,7,143,0,72,29,226,1,199,217,249,0,232,161,71,1,149,190,201,0,217,175,95,254,113,147,67,255,138,143,199,255,127,204,1,0,29,182,83,1,206,230,155,255,186,204,60,0,10,125,85,255,232,96,25,255,255,89,247,255,213,254,175,1,232,193,81,0,28,43,156,254,12,69,8,0,147,24,248,0,18,198,49,0,134,60,35,0,118,246,18,255,49,88,254,254,228,21,186,255,182,65,112,1,219,22,1,255,22,126,52,255,189,53,49,255,112,25,143,0,38,127,55,255,226,101,163,254,208,133,61,255,137,69,174,1,190,118,145,255,60,98,219,255,217,13,245,255,250,136,10,0,84,254,226,0,201,31,125,1,240,51,251,255,31,131,130,255,2,138,50,255,215,215,177,1,223,12,238,255,252,149,56,255,124,91,68,255,72,126,170,254,119,255,100,0,130,135,232,255,14,79,178,0,250,131,197,0,138,198,208,0,121,216,139,254,119,18,36,255,29,193,122,0,16,42,45,255,213,240,235,1,230,190,169,255,198,35,228,254,110,173,72,0,214,221,241,255,56,148,135,0,192,117,78,254,141,93,207,255,143,65,149,0,21,18,98,255,95,44,244,1,106,191,77,0,254,85,8,254,214,110,176,255,73,173,19,254,160,196,199,255,237,90,144,0,193,172,113,255,200,155,136,254,228,90,221,0,137,49,74,1,164,221,215,255,209,189,5,255,105,236,55,255,42,31,129,1,193,255,236,0,46,217,60,0,138,88,187,255,226,82,236,255,81,69,151,255,142,190,16,1,13,134,8,0,127,122,48,255,81,64,156,0,171,243,139,0,237,35,246,0,122,143,193,254,212,122,146,0,95,41,255,1,87,132,77,0,4,212,31,0,17,31,78,0,39,45,173,254,24,142,217,255,95,9,6,255,227,83,6,0,98,59,130,254,62,30,33,0,8,115,211,1,162,97,128,255,7,184,23,254,116,28,168,255,248,138,151,255,98,244,240,0,186,118,130,0,114,248,235,255,105,173,200,1,160,124,71,255,94,36,164,1,175,65,146,255,238,241,170,254,202,198,197,0,228,71,138,254,45,246,109,255,194,52,158,0,133,187,176,0,83,252,154,254,89,189,221,255,170,73,252,0,148,58,125,0,36,68,51,254,42,69,177,255,168,76,86,255,38,100,204,255,38,53,35,0,175,19,97,0,225,238,253,255,81,81,135,0,210,27,255,254,235,73,107,0,8,207,115,0,82,127,136,0,84,99,21,254,207,19,136,0,100,164,101,0,80,208,77,255,132,207,237,255,15,3,15,255,33,166,110,0,156,95,85,255,37,185,111,1,150,106,35,255,166,151,76,0,114,87,135,255,159,194,64,0,12,122,31,255,232,7,101,254,173,119,98,0,154,71,220,254,191,57,53,255,168,232,160,255,224,32,99,255,218,156,165,0,151,153,163,0,217,13,148,1,197,113,89,0,149,28,161,254,207,23,30,0,105,132,227,255,54,230,94,255,133,173,204,255,92,183,157,255,88,144,252,254,102,33,90,0,159,97,3,0,181,218,155,255,240,114,119,0,106,214,53,255,165,190,115,1,152,91,225,255,88,106,44,255,208,61,113,0,151,52,124,0,191,27,156,255,110,54,236,1,14,30,166,255,39,127,207,1,229,199,28,0,188,228,188,254,100,157,235,0,246,218,183,1,107,22,193,255,206,160,95,0,76,239,147,0,207,161,117,0,51,166,2,255,52,117,10,254,73,56,227,255,152,193,225,0,132,94,136,255,101,191,209,0,32,107,229,255,198,43,180,1,100,210,118,0,114,67,153,255,23,88,26,255,89,154,92,1,220,120,140,255,144,114,207,255,252,115,250,255,34,206,72,0,138,133,127,255,8,178,124,1,87,75,97,0,15,229,92,254,240,67,131,255,118,123,227,254,146,120,104,255,145,213,255,1,129,187,70,255,219,119,54,0,1,19,173,0,45,150,148,1,248,83,72,0,203,233,169,1,142,107,56,0,247,249,38,1,45,242,80,255,30,233,103,0,96,82,70,0,23,201,111,0,81,39,30,255,161,183,78,255,194,234,33,255,68,227,140,254,216,206,116,0,70,27,235,255,104,144,79,0,164,230,93,254,214,135,156,0,154,187,242,254,188,20,131,255,36,109,174,0,159,112,241,0,5,110,149,1,36,165,218,0,166,29,19,1,178,46,73,0,93,43,32,254,248,189,237,0,102,155,141,0,201,93,195,255,241,139,253,255,15,111,98,255,108,65,163,254,155,79,190,255,73,174,193,254,246,40,48,255,107,88,11,254,202,97,85,255,253,204,18,255,113,242,66,0,110,160,194,254,208,18,186,0,81,21,60,0,188,104,167,255,124,166,97,254,210,133,142,0,56,242,137,254,41,111,130,0,111,151,58,1,111,213,141,255,183,172,241,255,38,6,196,255,185,7,123,255,46,11,246,0,245,105,119,1,15,2,161,255,8,206,45,255,18,202,74,255,83,124,115,1,212,141,157,0,83,8,209,254,139,15,232,255,172,54,173,254,50,247,132,0,214,189,213,0,144,184,105,0,223,254,248,0,255,147,240,255,23,188,72,0,7,51,54,0,188,25,180,254,220,180,0,255,83,160,20,0,163,189,243,255,58,209,194,255,87,73,60,0,106,24,49,0,245,249,220,0,22,173,167,0,118,11,195,255,19,126,237,0,110,159,37,255,59,82,47,0,180,187,86,0,188,148,208,1,100,37,133,255,7,112,193,0,129,188,156,255,84,106,129,255,133,225,202,0,14,236,111,255,40,20,101,0,172,172,49,254,51,54,74,255,251,185,184,255,93,155,224,255,180,249,224,1,230,178,146,0,72,57,54,254,178,62,184,0,119,205,72,0,185,239,253,255,61,15,218,0,196,67,56,255,234,32,171,1,46,219,228,0,208,108,234,255,20,63,232,255,165,53,199,1,133,228,5,255,52,205,107,0,74,238,140,255,150,156,219,254,239,172,178,255,251,189,223,254,32,142,211,255,218,15,138,1,241,196,80,0,28,36,98,254,22,234,199,0,61,237,220,255,246,57,37,0,142,17,142,255,157,62,26,0,43,238,95,254,3,217,6,255,213,25,240,1,39,220,174,255,154,205,48,254,19,13,192,255,244,34,54,254,140,16,155,0,240,181,5,254,155,193,60,0,166,128,4,255,36,145,56,255,150,240,219,0,120,51,145,0,82,153,42,1,140,236,146,0,107,92,248,1,189,10,3,0,63,136,242,0,211,39,24,0,19,202,161,1,173,27,186,255,210,204,239,254,41,209,162,255,182,254,159,255,172,116,52,0,195,103,222,254,205,69,59,0,53,22,41,1,218,48,194,0,80,210,242,0,210,188,207,0,187,161,161,254,216,17,1,0,136,225,113,0,250,184,63,0,223,30,98,254,77,168,162,0,59,53,175,0,19,201,10,255,139,224,194,0,147,193,154,255,212,189,12,254,1,200,174,255,50,133,113,1,94,179,90,0,173,182,135,0,94,177,113,0,43,89,215,255,136,252,106,255,123,134,83,254,5,245,66,255,82,49,39,1,220,2,224,0,97,129,177,0,77,59,89,0,61,29,155,1,203,171,220,255,92,78,139,0,145,33,181,255,169,24,141,1,55,150,179,0,139,60,80,255,218,39,97,0,2,147,107,255,60,248,72,0,173,230,47,1,6,83,182,255,16,105,162,254,137,212,81,255,180,184,134,1,39,222,164,255,221,105,251,1,239,112,125,0,63,7,97,0,63,104,227,255,148,58,12,0,90,60,224,255,84,212,252,0,79,215,168,0,248,221,199,1,115,121,1,0,36,172,120,0,32,162,187,255,57,107,49,255,147,42,21,0,106,198,43,1,57,74,87,0,126,203,81,255,129,135,195,0,140,31,177,0,221,139,194,0,3,222,215,0,131,68,231,0,177,86,178,254,124,151,180,0,184,124,38,1,70,163,17,0,249,251,181,1,42,55,227,0,226,161,44,0,23,236,110,0,51,149,142,1,93,5,236,0,218,183,106,254,67,24,77,0,40,245,209,255,222,121,153,0,165,57,30,0,83,125,60,0,70,38,82,1,229,6,188,0,109,222,157,255,55,118,63,255,205,151,186,0,227,33,149,255,254,176,246,1,227,177,227,0,34,106,163,254,176,43,79,0,106,95,78,1,185,241,122,255,185,14,61,0,36,1,202,0,13,178,162,255,247,11,132,0,161,230,92,1,65,1,185,255,212,50,165,1,141,146,64,255,158,242,218,0,21,164,125,0,213,139,122,1,67,71,87,0,203,158,178,1,151,92,43,0,152,111,5,255,39,3,239,255,217,255,250,255,176,63,71,255,74,245,77,1,250,174,18,255,34,49,227,255,246,46,251,255,154,35,48,1,125,157,61,255,106,36,78,255,97,236,153,0,136,187,120,255,113,134,171,255,19,213,217,254,216,94,209,255,252,5,61,0,94,3,202,0,3,26,183,255,64,191,43,255,30,23,21,0,129,141,77,255,102,120,7,1,194,76,140,0,188,175,52,255,17,81,148,0,232,86,55,1,225,48,172,0,134,42,42,255,238,50,47,0,169,18,254,0,20,147,87,255,14,195,239,255,69,247,23,0,238,229,128,255,177,49,112,0,168,98,251,255,121,71,248,0,243,8,145,254,246,227,153,255,219,169,177,254,251,139,165,255,12,163,185,255,164,40,171,255,153,159,27,254,243,109,91,255,222,24,112,1,18,214,231,0,107,157,181,254,195,147,0,255,194,99,104,255,89,140,190,255,177,66,126,254,106,185,66,0,49,218,31,0,252,174,158,0,188,79,230,1,238,41,224,0,212,234,8,1,136,11,181,0,166,117,83,255,68,195,94,0,46,132,201,0,240,152,88,0,164,57,69,254,160,224,42,255,59,215,67,255,119,195,141,255,36,180,121,254,207,47,8,255,174,210,223,0,101,197,68,255,255,82,141,1,250,137,233,0,97,86,133,1,16,80,69,0,132,131,159,0,116,93,100,0,45,141,139,0,152,172,157,255,90,43,91,0,71,153,46,0,39,16,112,255,217,136,97,255,220,198,25,254,177,53,49,0,222,88,134,255,128,15,60,0,207,192,169,255,192,116,209,255,106,78,211,1,200,213,183,255,7,12,122,254,222,203,60,255,33,110,199,254,251,106,117,0,228,225,4,1,120,58,7,255,221,193,84,254,112,133,27,0,189,200,201,255,139,135,150,0,234,55,176,255,61,50,65,0,152,108,169,255,220,85,1,255,112,135,227,0,162,26,186,0,207,96,185,254,244,136,107,0,93,153,50,1,198,97,151,0,110,11,86,255,143,117,174,255,115,212,200,0,5,202,183,0,237,164,10,254,185,239,62,0,236,120,18,254,98,123,99,255,168,201,194,254,46,234,214,0,191,133,49,255,99,169,119,0,190,187,35,1,115,21,45,255,249,131,72,0,112,6,123,255,214,49,181,254,166,233,34,0,92,197,102,254,253,228,205,255,3,59,201,1,42,98,46,0,219,37,35,255,169,195,38,0,94,124,193,1,156,43,223,0,95,72,133,254,120,206,191,0,122,197,239,255,177,187,79,255,254,46,2,1,250,167,190,0,84,129,19,0,203,113,166,255,249,31,189,254,72,157,202,255,208,71,73,255,207,24,72,0,10,16,18,1,210,81,76,255,88,208,192,255,126,243,107,255,238,141,120,255,199,121,234,255,137,12,59,255,36,220,123,255,148,179,60,254,240,12,29,0,66,0,97,1,36,30,38,255,115,1,93,255,96,103,231,255,197,158,59,1,192,164,240,0,202,202,57,255,24,174,48,0,89,77,155,1,42,76,215,0,244,151,233,0,23,48,81,0,239,127,52,254,227,130,37,255,248,116,93,1,124,132,118,0,173,254,192,1,6,235,83,255,110,175,231,1,251,28,182,0,129,249,93,254,84,184,128,0,76,181,62,0,175,128,186,0,100,53,136,254,109,29,226,0,221,233,58,1,20,99,74,0,0,22,160,0,134,13,21,0,9,52,55,255,17,89,140,0,175,34,59,0,84,165,119,255,224,226,234,255,7,72,166,255,123,115,255,1,18,214,246,0,250,7,71,1,217,220,185,0,212,35,76,255,38,125,175,0,189,97,210,0,114,238,44,255,41,188,169,254,45,186,154,0,81,92,22,0,132,160,193,0,121,208,98,255,13,81,44,255,203,156,82,0,71,58,21,255,208,114,191,254,50,38,147,0,154,216,195,0,101,25,18,0,60,250,215,255,233,132,235,255,103,175,142,1,16,14,92,0,141,31,110,254,238,241,45,255,153,217,239,1,97,168,47,255,249,85,16,1,28,175,62,255],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE);allocate([57,254,54,0,222,231,126,0,166,45,117,254,18,189,96,255,228,76,50,0,200,244,94,0,198,152,120,1,68,34,69,255,12,65,160,254,101,19,90,0,167,197,120,255,68,54,185,255,41,218,188,0,113,168,48,0,88,105,189,1,26,82,32,255,185,93,164,1,228,240,237,255,66,182,53,0,171,197,92,255,107,9,233,1,199,120,144,255,78,49,10,255,109,170,105,255,90,4,31,255,28,244,113,255,74,58,11,0,62,220,246,255,121,154,200,254,144,210,178,255,126,57,129,1,43,250,14,255,101,111,28,1,47,86,241,255,61,70,150,255,53,73,5,255,30,26,158,0,209,26,86,0,138,237,74,0,164,95,188,0,142,60,29,254,162,116,248,255,187,175,160,0,151,18,16,0,209,111,65,254,203,134,39,255,88,108,49,255,131,26,71,255,221,27,215,254,104,105,93,255,31,236,31,254,135,0,211,255,143,127,110,1,212,73,229,0,233,67,167,254,195,1,208,255,132,17,221,255,51,217,90,0,67,235,50,255,223,210,143,0,179,53,130,1,233,106,198,0,217,173,220,255,112,229,24,255,175,154,93,254,71,203,246,255,48,66,133,255,3,136,230,255,23,221,113,254,235,111,213,0,170,120,95,254,251,221,2,0,45,130,158,254,105,94,217,255,242,52,180,254,213,68,45,255,104,38,28,0,244,158,76,0,161,200,96,255,207,53,13,255,187,67,148,0,170,54,248,0,119,162,178,255,83,20,11,0,42,42,192,1,146,159,163,255,183,232,111,0,77,229,21,255,71,53,143,0,27,76,34,0,246,136,47,255,219,39,182,255,92,224,201,1,19,142,14,255,69,182,241,255,163,118,245,0,9,109,106,1,170,181,247,255,78,47,238,255,84,210,176,255,213,107,139,0,39,38,11,0,72,21,150,0,72,130,69,0,205,77,155,254,142,133,21,0,71,111,172,254,226,42,59,255,179,0,215,1,33,128,241,0,234,252,13,1,184,79,8,0,110,30,73,255,246,141,189,0,170,207,218,1,74,154,69,255,138,246,49,255,155,32,100,0,125,74,105,255,90,85,61,255,35,229,177,255,62,125,193,255,153,86,188,1,73,120,212,0,209,123,246,254,135,209,38,255,151,58,44,1,92,69,214,255,14,12,88,255,252,153,166,255,253,207,112,255,60,78,83,255,227,124,110,0,180,96,252,255,53,117,33,254,164,220,82,255,41,1,27,255,38,164,166,255,164,99,169,254,61,144,70,255,192,166,18,0,107,250,66,0,197,65,50,0,1,179,18,255,255,104,1,255,43,153,35,255,80,111,168,0,110,175,168,0,41,105,45,255,219,14,205,255,164,233,140,254,43,1,118,0,233,67,195,0,178,82,159,255,138,87,122,255,212,238,90,255,144,35,124,254,25,140,164,0,251,215,44,254,133,70,107,255,101,227,80,254,92,169,55,0,215,42,49,0,114,180,85,255,33,232,27,1,172,213,25,0,62,176,123,254,32,133,24,255,225,191,62,0,93,70,153,0,181,42,104,1,22,191,224,255,200,200,140,255,249,234,37,0,149,57,141,0,195,56,208,255,254,130,70,255,32,173,240,255,29,220,199,0,110,100,115,255,132,229,249,0,228,233,223,255,37,216,209,254,178,177,209,255,183,45,165,254,224,97,114,0,137,97,168,255,225,222,172,0,165,13,49,1,210,235,204,255,252,4,28,254,70,160,151,0,232,190,52,254,83,248,93,255,62,215,77,1,175,175,179,255,160,50,66,0,121,48,208,0,63,169,209,255,0,210,200,0,224,187,44,1,73,162,82,0,9,176,143,255,19,76,193,255,29,59,167,1,24,43,154,0,28,190,190,0,141,188,129,0,232,235,203,255,234,0,109,255,54,65,159,0,60,88,232,255,121,253,150,254,252,233,131,255,198,110,41,1,83,77,71,255,200,22,59,254,106,253,242,255,21,12,207,255,237,66,189,0,90,198,202,1,225,172,127,0,53,22,202,0,56,230,132,0,1,86,183,0,109,190,42,0,243,68,174,1,109,228,154,0,200,177,122,1,35,160,183,255,177,48,85,255,90,218,169,255,248,152,78,0,202,254,110,0,6,52,43,0,142,98,65,255,63,145,22,0,70,106,93,0,232,138,107,1,110,179,61,255,211,129,218,1,242,209,92,0,35,90,217,1,182,143,106,255,116,101,217,255,114,250,221,255,173,204,6,0,60,150,163,0,73,172,44,255,239,110,80,255,237,76,153,254,161,140,249,0,149,232,229,0,133,31,40,255,174,164,119,0,113,51,214,0,129,228,2,254,64,34,243,0,107,227,244,255,174,106,200,255,84,153,70,1,50,35,16,0,250,74,216,254,236,189,66,255,153,249,13,0,230,178,4,255,221,41,238,0,118,227,121,255,94,87,140,254,254,119,92,0,73,239,246,254,117,87,128,0,19,211,145,255,177,46,252,0,229,91,246,1,69,128,247,255,202,77,54,1,8,11,9,255,153,96,166,0,217,214,173,255,134,192,2,1,0,207,0,0,189,174,107,1,140,134,100,0,158,193,243,1,182,102,171,0,235,154,51,0,142,5,123,255,60,168,89,1,217,14,92,255,19,214,5,1,211,167,254,0,44,6,202,254,120,18,236,255,15,113,184,255,184,223,139,0,40,177,119,254,182,123,90,255,176,165,176,0,247,77,194,0,27,234,120,0,231,0,214,255,59,39,30,0,125,99,145,255,150,68,68,1,141,222,248,0,153,123,210,255,110,127,152,255,229,33,214,1,135,221,197,0,137,97,2,0,12,143,204,255,81,41,188,0,115,79,130,255,94,3,132,0,152,175,187,255,124,141,10,255,126,192,179,255,11,103,198,0,149,6,45,0,219,85,187,1,230,18,178,255,72,182,152,0,3,198,184,255,128,112,224,1,97,161,230,0,254,99,38,255,58,159,197,0,151,66,219,0,59,69,143,255,185,112,249,0,119,136,47,255,123,130,132,0,168,71,95,255,113,176,40,1,232,185,173,0,207,93,117,1,68,157,108,255,102,5,147,254,49,97,33,0,89,65,111,254,247,30,163,255,124,217,221,1,102,250,216,0,198,174,75,254,57,55,18,0,227,5,236,1,229,213,173,0,201,109,218,1,49,233,239,0,30,55,158,1,25,178,106,0,155,111,188,1,94,126,140,0,215,31,238,1,77,240,16,0,213,242,25,1,38,71,168,0,205,186,93,254,49,211,140,255,219,0,180,255,134,118,165,0,160,147,134,255,110,186,35,255,198,243,42,0,243,146,119,0,134,235,163,1,4,241,135,255,193,46,193,254,103,180,79,255,225,4,184,254,242,118,130,0,146,135,176,1,234,111,30,0,69,66,213,254,41,96,123,0,121,94,42,255,178,191,195,255,46,130,42,0,117,84,8,255,233,49,214,254,238,122,109,0,6,71,89,1,236,211,123,0,244,13,48,254,119,148,14,0,114,28,86,255,75,237,25,255,145,229,16,254,129,100,53,255,134,150,120,254,168,157,50,0,23,72,104,255,224,49,14,0,255,123,22,255,151,185,151,255,170,80,184,1,134,182,20,0,41,100,101,1,153,33,16,0,76,154,111,1,86,206,234,255,192,160,164,254,165,123,93,255,1,216,164,254,67,17,175,255,169,11,59,255,158,41,61,255,73,188,14,255,195,6,137,255,22,147,29,255,20,103,3,255,246,130,227,255,122,40,128,0,226,47,24,254,35,36,32,0,152,186,183,255,69,202,20,0,195,133,195,0,222,51,247,0,169,171,94,1,183,0,160,255,64,205,18,1,156,83,15,255,197,58,249,254,251,89,110,255,50,10,88,254,51,43,216,0,98,242,198,1,245,151,113,0,171,236,194,1,197,31,199,255,229,81,38,1,41,59,20,0,253,104,230,0,152,93,14,255,246,242,146,254,214,169,240,255,240,102,108,254,160,167,236,0,154,218,188,0,150,233,202,255,27,19,250,1,2,71,133,255,175,12,63,1,145,183,198,0,104,120,115,255,130,251,247,0,17,212,167,255,62,123,132,255,247,100,189,0,155,223,152,0,143,197,33,0,155,59,44,255,150,93,240,1,127,3,87,255,95,71,207,1,167,85,1,255,188,152,116,255,10,23,23,0,137,195,93,1,54,98,97,0,240,0,168,255,148,188,127,0,134,107,151,0,76,253,171,0,90,132,192,0,146,22,54,0,224,66,54,254,230,186,229,255,39,182,196,0,148,251,130,255,65,131,108,254,128,1,160,0,169,49,167,254,199,254,148,255,251,6,131,0,187,254,129,255,85,82,62,0,178,23,58,255,254,132,5,0,164,213,39,0,134,252,146,254,37,53,81,255,155,134,82,0,205,167,238,255,94,45,180,255,132,40,161,0,254,111,112,1,54,75,217,0,179,230,221,1,235,94,191,255,23,243,48,1,202,145,203,255,39,118,42,255,117,141,253,0,254,0,222,0,43,251,50,0,54,169,234,1,80,68,208,0,148,203,243,254,145,7,135,0,6,254,0,0,252,185,127,0,98,8,129,255,38,35,72,255,211,36,220,1,40,26,89,0,168,64,197,254,3,222,239,255,2,83,215,254,180,159,105,0,58,115,194,0,186,116,106,255,229,247,219,255,129,118,193,0,202,174,183,1,166,161,72,0,201,107,147,254,237,136,74,0,233,230,106,1,105,111,168,0,64,224,30,1,1,229,3,0,102,151,175,255,194,238,228,255,254,250,212,0,187,237,121,0,67,251,96,1,197,30,11,0,183,95,204,0,205,89,138,0,64,221,37,1,255,223,30,255,178,48,211,255,241,200,90,255,167,209,96,255,57,130,221,0,46,114,200,255,61,184,66,0,55,182,24,254,110,182,33,0,171,190,232,255,114,94,31,0,18,221,8,0,47,231,254,0,255,112,83,0,118,15,215,255,173,25,40,254,192,193,31,255,238,21,146,255,171,193,118,255,101,234,53,254,131,212,112,0,89,192,107,1,8,208,27,0,181,217,15,255,231,149,232,0,140,236,126,0,144,9,199,255,12,79,181,254,147,182,202,255,19,109,182,255,49,212,225,0,74,163,203,0,175,233,148,0,26,112,51,0,193,193,9,255,15,135,249,0,150,227,130,0,204,0,219,1,24,242,205,0,238,208,117,255,22,244,112,0,26,229,34,0,37,80,188,255,38,45,206,254,240,90,225,255,29,3,47,255,42,224,76,0,186,243,167,0,32,132,15,255,5,51,125,0,139,135,24,0,6,241,219,0,172,229,133,255,246,214,50,0,231,11,207,255,191,126,83,1,180,163,170,255,245,56,24,1,178,164,211,255,3,16,202,1,98,57,118,255,141,131,89,254,33,51,24,0,243,149,91,255,253,52,14,0,35,169,67,254,49,30,88,255,179,27,36,255,165,140,183,0,58,189,151,0,88,31,0,0,75,169,66,0,66,101,199,255,24,216,199,1,121,196,26,255,14,79,203,254,240,226,81,255,94,28,10,255,83,193,240,255,204,193,131,255,94,15,86,0,218,40,157,0,51,193,209,0,0,242,177,0,102,185,247,0,158,109,116,0,38,135,91,0,223,175,149,0,220,66,1,255,86,60,232,0,25,96,37,255,225,122,162,1,215,187,168,255,158,157,46,0,56,171,162,0,232,240,101,1,122,22,9,0,51,9,21,255,53,25,238,255,217,30,232,254,125,169,148,0,13,232,102,0,148,9,37,0,165,97,141,1,228,131,41,0,222,15,243,255,254,18,17,0,6,60,237,1,106,3,113,0,59,132,189,0,92,112,30,0,105,208,213,0,48,84,179,255,187,121,231,254,27,216,109,255,162,221,107,254,73,239,195,255,250,31,57,255,149,135,89,255,185,23,115,1,3,163,157,255,18,112,250,0,25,57,187,255,161,96,164,0,47,16,243,0,12,141,251,254,67,234,184,255,41,18,161,0,175,6,96,255,160,172,52,254,24,176,183,255,198,193,85,1,124,121,137,255,151,50,114,255,220,203,60,255,207,239,5,1,0,38,107,255,55,238,94,254,70,152,94,0,213,220,77,1,120,17,69,255,85,164,190,255,203,234,81,0,38,49,37,254,61,144,124,0,137,78,49,254,168,247,48,0,95,164,252,0,105,169,135,0,253,228,134,0,64,166,75,0,81,73,20,255,207,210,10,0,234,106,150,255,94,34,90,255,254,159,57,254,220,133,99,0,139,147,180,254,24,23,185,0,41,57,30,255,189,97,76,0,65,187,223,255,224,172,37,255,34,62,95,1,231,144,240,0,77,106,126,254,64,152,91,0,29,98,155,0,226,251,53,255,234,211,5,255,144,203,222,255,164,176,221,254,5,231,24,0,179,122,205,0,36,1,134,255,125,70,151,254,97,228,252,0,172,129,23,254,48,90,209,255,150,224,82,1,84,134,30,0,241,196,46,0,103,113,234,255,46,101,121,254,40,124,250,255,135,45,242,254,9,249,168,255,140,108,131,255,143,163,171,0,50,173,199,255,88,222,142,255,200,95,158,0,142,192,163,255,7,117,135,0,111,124,22,0,236,12,65,254,68,38,65,255,227,174,254,0,244,245,38,0,240,50,208,255,161,63,250,0,60,209,239,0,122,35,19,0,14,33,230,254,2,159,113,0,106,20,127,255,228,205,96,0,137,210,174,254,180,212,144,255,89,98,154,1,34,88,139,0,167,162,112,1,65,110,197,0,241,37,169,0,66,56,131,255,10,201,83,254,133,253,187,255,177,112,45,254,196,251,0,0,196,250,151,255,238,232,214,255,150,209,205,0,28,240,118,0,71,76,83,1,236,99,91,0,42,250,131,1,96,18,64,255,118,222,35,0,113,214,203,255,122,119,184,255,66,19,36,0,204,64,249,0,146,89,139,0,134,62,135,1,104,233,101,0,188,84,26,0,49,249,129,0,208,214,75,255,207,130,77,255,115,175,235,0,171,2,137,255,175,145,186,1,55,245,135,255,154,86,181,1,100,58,246,255,109,199,60,255,82,204,134,255,215,49,230,1,140,229,192,255,222,193,251,255,81,136,15,255,179,149,162,255,23,39,29,255,7,95,75,254,191,81,222,0,241,81,90,255,107,49,201,255,244,211,157,0,222,140,149,255,65,219,56,254,189,246,90,255,178,59,157,1,48,219,52,0,98,34,215,0,28,17,187,255,175,169,24,0,92,79,161,255,236,200,194,1,147,143,234,0,229,225,7,1,197,168,14,0,235,51,53,1,253,120,174,0,197,6,168,255,202,117,171,0,163,21,206,0,114,85,90,255,15,41,10,255,194,19,99,0,65,55,216,254,162,146,116,0,50,206,212,255,64,146,29,255,158,158,131,1,100,165,130,255,172,23,129,255,125,53,9,255,15,193,18,1,26,49,11,255,181,174,201,1,135,201,14,255,100,19,149,0,219,98,79,0,42,99,143,254,96,0,48,255,197,249,83,254,104,149,79,255,235,110,136,254,82,128,44,255,65,41,36,254,88,211,10,0,187,121,187,0,98,134,199,0,171,188,179,254,210,11,238,255,66,123,130,254,52,234,61,0,48,113,23,254,6,86,120,255,119,178,245,0,87,129,201,0,242,141,209,0,202,114,85,0,148,22,161,0,103,195,48,0,25,49,171,255,138,67,130,0,182,73,122,254,148,24,130,0,211,229,154,0,32,155,158,0,84,105,61,0,177,194,9,255,166,89,86,1,54,83,187,0,249,40,117,255,109,3,215,255,53,146,44,1,63,47,179,0,194,216,3,254,14,84,136,0,136,177,13,255,72,243,186,255,117,17,125,255,211,58,211,255,93,79,223,0,90,88,245,255,139,209,111,255,70,222,47,0,10,246,79,255,198,217,178,0,227,225,11,1,78,126,179,255,62,43,126,0,103,148,35,0,129,8,165,254,245,240,148,0,61,51,142,0,81,208,134,0,15,137,115,255,211,119,236,255,159,245,248,255,2,134,136,255,230,139,58,1,160,164,254,0,114,85,141,255,49,166,182,255,144,70,84,1,85,182,7,0,46,53,93,0,9,166,161,255,55,162,178,255,45,184,188,0,146,28,44,254,169,90,49,0,120,178,241,1,14,123,127,255,7,241,199,1,189,66,50,255,198,143,101,254,189,243,135,255,141,24,24,254,75,97,87,0,118,251,154,1,237,54,156,0,171,146,207,255,131,196,246,255,136,64,113,1,151,232,57,0,240,218,115,0,49,61,27,255,64,129,73,1,252,169,27,255,40,132,10,1,90,201,193,255,252,121,240,1,186,206,41,0,43,198,97,0,145,100,183,0,204,216,80,254,172,150,65,0,249,229,196,254,104,123,73,255,77,104,96,254,130,180,8,0,104,123,57,0,220,202,229,255,102,249,211,0,86,14,232,255,182,78,209,0,239,225,164,0,106,13,32,255,120,73,17,255,134,67,233,0,83,254,181,0,183,236,112,1,48,64,131,255,241,216,243,255,65,193,226,0,206,241,100,254,100,134,166,255,237,202,197,0,55,13,81,0,32,124,102,255,40,228,177,0,118,181,31,1,231,160,134,255,119,187,202,0,0,142,60,255,128,38,189,255,166,201,150,0,207,120,26,1,54,184,172,0,12,242,204,254,133,66,230,0,34,38,31,1,184,112,80,0,32,51,165,254,191,243,55,0,58,73,146,254,155,167,205,255,100,104,152,255,197,254,207,255,173,19,247,0,238,10,202,0,239,151,242,0,94,59,39,255,240,29,102,255,10,92,154,255,229,84,219,255,161,129,80,0,208,90,204,1,240,219,174,255,158,102,145,1,53,178,76,255,52,108,168,1,83,222,107,0,211,36,109,0,118,58,56,0,8,29,22,0,237,160,199,0,170,209,157,0,137,71,47,0,143,86,32,0,198,242,2,0,212,48,136,1,92,172,186,0,230,151,105,1,96,191,229,0,138,80,191,254,240,216,130,255,98,43,6,254,168,196,49,0,253,18,91,1,144,73,121,0,61,146,39,1,63,104,24,255,184,165,112,254,126,235,98,0,80,213,98,255,123,60,87,255,82,140,245,1,223,120,173,255,15,198,134,1,206,60,239,0,231,234,92,255,33,238,19,255,165,113,142,1,176,119,38,0,160,43,166,254,239,91,105,0,107,61,194,1,25,4,68,0,15,139,51,0,164,132,106,255,34,116,46,254,168,95,197,0,137,212,23,0,72,156,58,0,137,112,69,254,150,105,154,255,236,201,157,0,23,212,154,255,136,82,227,254,226,59,221,255,95,149,192,0,81,118,52,255,33,43,215,1,14,147,75,255,89,156,121,254,14,18,79,0,147,208,139,1,151,218,62,255,156,88,8,1,210,184,98,255,20,175,123,255,102,83,229,0,220,65,116,1,150,250,4,255,92,142,220,255,34,247,66,255,204,225,179,254,151,81,151,0,71,40,236,255,138,63,62,0,6,79,240,255,183,185,181,0,118,50,27,0,63,227,192,0,123,99,58,1,50,224,155,255,17,225,223,254,220,224,77,255,14,44,123,1,141,128,175,0,248,212,200,0,150,59,183,255,147,97,29,0,150,204,181,0,253,37,71,0,145,85,119,0,154,200,186,0,2,128,249,255,83,24,124,0,14,87,143,0,168,51,245,1,124,151,231,255,208,240,197,1,124,190,185,0,48,58,246,0,20,233,232,0,125,18,98,255,13,254,31,255,245,177,130,255,108,142,35,0,171,125,242,254,140,12,34,255,165,161,162,0,206,205,101,0,247,25,34,1,100,145,57,0,39,70,57,0,118,204,203,255,242,0,162,0,165,244,30,0,198,116,226,0,128,111,153,255,140,54,182,1,60,122,15,255,155,58,57,1,54,50,198,0,171,211,29,255,107,138,167,255,173,107,199,255,109,161,193,0,89,72,242,255,206,115,89,255,250,254,142,254,177,202,94,255,81,89,50,0,7,105,66,255,25,254,255,254,203,64,23,255,79,222,108,255,39,249,75,0,241,124,50,0,239,152,133,0,221,241,105,0,147,151,98,0,213,161,121,254,242,49,137,0,233,37,249,254,42,183,27,0,184,119,230,255,217,32,163,255,208,251,228,1,137,62,131,255,79,64,9,254,94,48,113,0,17,138,50,254,193,255,22,0,247,18,197,1,67,55,104,0,16,205,95,255,48,37,66,0,55,156,63,1,64,82,74,255,200,53,71,254,239,67,125,0,26,224,222,0,223,137,93,255,30,224,202,255,9,220,132,0,198,38,235,1,102,141,86,0,60,43,81,1,136,28,26,0,233,36,8,254,207,242,148,0,164,162,63,0,51,46,224,255,114,48,79,255,9,175,226,0,222,3,193,255,47,160,232,255,255,93,105,254,14,42,230,0,26,138,82,1,208,43,244,0,27,39,38,255,98,208,127,255,64,149,182,255,5,250,209,0,187,60,28,254,49,25,218,255,169,116,205,255,119,18,120,0,156,116,147,255,132,53,109,255,13,10,202,0,110,83,167,0,157,219,137,255,6,3,130,255,50,167,30,255,60,159,47,255,129,128,157,254,94,3,189,0,3,166,68,0,83,223,215,0,150,90,194,1,15,168,65,0,227,83,51,255,205,171,66,255,54,187,60,1,152,102,45,255,119,154,225,0,240,247,136,0,100,197,178,255,139,71,223,255,204,82,16,1,41,206,42,255,156,192,221,255,216,123,244,255,218,218,185,255,187,186,239,255,252,172,160,255,195,52,22,0,144,174,181,254,187,100,115,255,211,78,176,255,27,7,193,0,147,213,104,255,90,201,10,255,80,123,66,1,22,33,186,0,1,7,99,254,30,206,10,0,229,234,5,0,53,30,210,0,138,8,220,254,71,55,167,0,72,225,86,1,118,190,188,0,254,193,101,1,171,249,172,255,94,158,183,254,93,2,108,255,176,93,76,255,73,99,79,255,74,64,129,254,246,46,65,0,99,241,127,254,246,151,102,255,44,53,208,254,59,102,234,0,154,175,164,255,88,242,32,0,111,38,1,0,255,182,190,255,115,176,15,254,169,60,129,0,122,237,241,0,90,76,63,0,62,74,120,255,122,195,110,0,119,4,178,0,222,242,210,0,130,33,46,254,156,40,41,0,167,146,112,1,49,163,111,255,121,176,235,0,76,207,14,255,3,25,198,1,41,235,213,0,85,36,214,1,49,92,109,255,200,24,30,254,168,236,195,0,145,39,124,1,236,195,149,0,90,36,184,255,67,85,170,255,38,35,26,254,131,124,68,255,239,155,35,255,54,201,164,0,196,22,117,255,49,15,205,0,24,224,29,1,126,113,144,0,117,21,182,0,203,159,141,0,223,135,77,0,176,230,176,255,190,229,215,255,99,37,181,255,51,21,138,255,25,189,89,255,49,48,165,254,152,45,247,0,170,108,222,0,80,202,5,0,27,69,103,254,204,22,129,255,180,252,62,254,210,1,91,255,146,110,254,255,219,162,28,0,223,252,213,1,59,8,33,0,206,16,244,0,129,211,48,0,107,160,208,0,112,59,209,0,109,77,216,254,34,21,185,255,246,99,56,255,179,139,19,255,185,29,50,255,84,89,19,0,74,250,98,255,225,42,200,255,192,217,205,255,210,16,167,0,99,132,95,1,43,230,57,0,254,11,203,255,99,188,63,255,119,193,251,254,80,105,54,0,232,181,189,1,183,69,112,255,208,171,165,255,47,109,180,255,123,83,165,0,146,162,52,255,154,11,4,255,151,227,90,255,146,137,97,254,61,233,41,255,94,42,55,255,108,164,236,0,152,68,254,0,10,140,131,255,10,106,79,254,243,158,137,0,67,178,66,254,177,123,198,255,15,62,34,0,197,88,42,255,149,95,177,255,152,0,198,255,149,254,113,255,225,90,163,255,125,217,247,0,18,17,224,0,128,66,120,254,192,25,9,255,50,221,205,0,49,212,70,0,233,255,164,0,2,209,9,0,221,52,219,254,172,224,244,255,94,56,206,1,242,179,2,255,31,91,164,1,230,46,138,255,189,230,220,0,57,47,61,255,111,11,157,0,177,91,152,0,28,230,98,0,97,87,126,0,198,89,145,255,167,79,107,0,249,77,160,1,29,233,230,255,150,21,86,254,60,11,193,0,151,37,36,254,185,150,243,255,228,212,83,1,172,151,180,0,201,169,155,0,244,60,234,0,142,235,4,1,67,218,60,0,192,113,75,1,116,243,207,255,65,172,155,0,81,30,156,255,80,72,33,254,18,231,109,255,142,107,21,254,125,26,132,255,176,16,59,255,150,201,58,0,206,169,201,0,208,121,226,0,40,172,14,255,150,61,94,255,56,57,156,255,141,60,145,255,45,108,149,255,238,145,155,255,209,85,31,254,192,12,210,0,99,98,93,254,152,16,151,0,225,185,220,0,141,235,44,255,160,172,21,254,71,26,31,255,13,64,93,254,28,56,198,0,177,62,248,1,182,8,241,0,166,101,148,255,78,81,133,255,129,222,215,1,188,169,129,255,232,7,97,0,49,112,60,255,217,229,251,0,119,108,138,0,39,19,123,254,131,49,235,0,132,84,145,0,130,230,148,255,25,74,187,0,5,245,54,255,185,219,241,1,18,194,228,255,241,202,102,0,105,113,202,0,155,235,79,0,21,9,178,255,156,1,239,0,200,148,61,0,115,247,210,255,49,221,135,0,58,189,8,1,35,46,9,0,81,65,5,255,52,158,185,255,125,116,46,255,74,140,13,255,210,92,172,254,147,23,71,0,217,224,253,254,115,108,180,255,145,58,48,254,219,177,24,255,156,255,60,1,154,147,242,0,253,134,87,0,53,75,229,0,48,195,222,255,31,175,50,255,156,210,120,255,208,35,222,255,18,248,179,1,2,10,101,255,157,194,248,255,158,204,101,255,104,254,197,255,79,62,4,0,178,172,101,1,96,146,251,255,65,10,156,0,2,137,165,255,116,4,231,0,242,215,1,0,19,35,29,255,43,161,79,0,59,149,246,1,251,66,176,0,200,33,3,255,80,110,142,255,195,161,17,1,228,56,66,255,123,47,145,254,132,4,164,0,67,174,172,0,25,253,114,0,87,97,87,1,250,220,84,0,96,91,200,255,37,125,59,0,19,65,118,0,161,52,241,255,237,172,6,255,176,191,255,255,1,65,130,254,223,190,230,0,101,253,231,255,146,35,109,0,250,29,77,1,49,0,19,0,123,90,155,1,22,86,32,255,218,213,65,0,111,93,127,0,60,93,169,255,8,127,182,0,17,186,14,254,253,137,246,255,213,25,48,254,76,238,0,255,248,92,70,255,99,224,139,0,184,9,255,1,7,164,208,0,205,131,198,1,87,214,199,0,130,214,95,0,221,149,222,0,23,38,171,254,197,110,213,0,43,115,140,254,215,177,118,0,96,52,66,1,117,158,237,0,14,64,182,255,46,63,174,255,158,95,190,255,225,205,177,255,43,5,142,255,172,99,212,255,244,187,147,0,29,51,153,255,228,116,24,254,30,101,207,0,19,246,150,255,134,231,5,0,125,134,226,1,77,65,98,0,236,130,33,255,5,110,62,0,69,108,127,255,7,113,22,0,145,20,83,254,194,161,231,255,131,181,60,0,217,209,177,255,229,148,212,254,3,131,184,0,117,177,187,1,28,14,31,255,176,102,80,0,50,84,151,255,125,31,54,255,21,157,133,255,19,179,139,1,224,232,26,0,34,117,170,255,167,252,171,255,73,141,206,254,129,250,35,0,72,79,236,1,220,229,20,255,41,202,173,255,99,76,238,255,198,22,224,255,108,198,195,255,36,141,96,1,236,158,59,255,106,100,87,0,110,226,2,0,227,234,222,0,154,93,119,255,74,112,164,255,67,91,2,255,21,145,33,255,102,214,137,255,175,230,103,254,163,246,166,0,93,247,116,254,167,224,28,255,220,2,57,1,171,206,84,0,123,228,17,255,27,120,119,0,119,11,147,1,180,47,225,255,104,200,185,254,165,2,114,0,77,78,212,0,45,154,177,255,24,196,121,254,82,157,182,0,90,16,190,1,12,147,197,0,95,239,152,255,11,235,71,0,86,146,119,255,172,134,214,0,60,131,196,0,161,225,129,0,31,130,120,254,95,200,51,0,105,231,210,255,58,9,148,255,43,168,221,255,124,237,142,0,198,211,50,254,46,245,103,0,164,248,84,0,152,70,208,255,180,117,177,0,70,79,185,0,243,74,32,0,149,156,207,0,197,196,161,1,245,53,239,0,15,93,246,254,139,240,49,255,196,88,36,255,162,38,123,0,128,200,157,1,174,76,103,255,173,169,34,254,216,1,171,255,114,51,17,0,136,228,194,0,110,150,56,254,106,246,159,0,19,184,79,255,150,77,240,255,155,80,162,0,0,53,169,255,29,151,86,0,68,94,16,0,92,7,110,254,98,117,149,255,249,77,230,255,253,10,140,0,214,124,92,254,35,118,235,0,89,48,57,1,22,53,166,0,184,144,61,255,179,255,194,0,214,248,61,254,59,110,246,0,121,21,81,254,166,3,228,0,106,64,26,255,69,232,134,255,242,220,53,254,46,220,85,0,113,149,247,255,97,179,103,255,190,127,11,0,135,209,182,0,95,52,129,1,170,144,206,255,122,200,204,255,168,100,146,0,60,144,149,254,70,60,40,0,122,52,177,255,246,211,101,255,174,237,8,0,7,51,120,0,19,31,173,0,126,239,156,255,143,189,203,0,196,128,88,255,233,133,226,255,30,125,173,255,201,108,50,0,123,100,59,255,254,163,3,1,221,148,181,255,214,136,57,254,222,180,137,255,207,88,54,255,28,33,251,255,67,214,52,1,210,208,100,0,81,170,94,0,145,40,53,0,224,111,231,254,35,28,244,255,226,199,195,254,238,17,230,0,217,217,164,254,169,157,221,0,218,46,162,1,199,207,163,255,108,115,162,1,14,96,187,255,118,60,76,0,184,159,152,0,209,231,71,254,42,164,186,255,186,153,51,254,221,171,182,255,162,142,173,0,235,47,193,0,7,139,16,1,95,164,64,255,16,221,166,0,219,197,16,0,132,29,44,255,100,69,117,255,60,235,88,254,40,81,173,0,71,190,61,255,187,88,157,0,231,11,23,0,237,117,164,0,225,168,223,255,154,114,116,255,163,152,242,1,24,32,170,0,125,98,113,254,168,19,76,0,17,157,220,254,155,52,5,0,19,111,161,255,71,90,252,255,173,110,240,0,10,198,121,255,253,255,240,255,66,123,210,0,221,194,215,254,121,163,17,255,225,7,99,0,190,49,182,0,115,9,133,1,232,26,138,255,213,68,132,0,44,119,122,255,179,98,51,0,149,90,106,0,71,50,230,255,10,153,118,255,177,70,25,0,165,87,205,0,55,138,234,0,238,30,97,0,113,155,207,0,98,153,127,0,34,107,219,254,117,114,172,255,76,180,255,254,242,57,179,255,221,34,172,254,56,162,49,255,83,3,255,255,113,221,189,255,188,25,228,254,16,88,89,255,71,28,198,254,22,17,149,255,243,121,254,255,107,202,99,255,9,206,14,1,220,47,153,0,107,137,39,1,97,49,194,255,149,51,197,254,186,58,11,255,107,43,232,1,200,6,14,255,181,133,65,254,221,228,171,255,123,62,231,1,227,234,179,255,34,189,212,254,244,187,249,0,190,13,80,1,130,89,1,0,223,133,173,0,9,222,198,255,66,127,74,0,167,216,93,255,155,168,198,1,66,145,0,0,68,102,46,1,172,90,154,0,216,128,75,255,160,40,51,0,158,17,27,1,124,240,49,0,236,202,176,255,151,124,192,255,38,193,190,0,95,182,61,0,163,147,124,255,255,165,51,255,28,40,17,254,215,96,78,0,86,145,218,254,31,36,202,255,86,9,5,0,111,41,200,255,237,108,97,0,57,62,44,0,117,184,15,1,45,241,116,0,152,1,220,255,157,165,188,0,250,15,131,1,60,44,125,255,65,220,251,255,75,50,184,0,53,90,128,255,231,80,194,255,136,129,127,1,21,18,187,255,45,58,161,255,71,147,34,0,174,249,11,254,35,141,29,0,239,68,177,255,115,110,58,0,238,190,177,1,87,245,166,255,190,49,247,255,146,83,184,255,173,14,39,255,146,215,104,0,142,223,120,0,149,200,155,255,212,207,145,1,16,181,217,0,173,32,87,255,255,35,181,0,119,223,161,1,200,223,94,255,70,6,186,255,192,67,85,255,50,169,152,0,144,26,123,255,56,243,179,254,20,68,136,0,39,140,188,254,253,208,5,255,200,115,135,1,43,172,229,255,156,104,187,0,151,251,167,0,52,135,23,0,151,153,72,0,147,197,107,254,148,158,5,255,238,143,206,0,126,153,137,255,88,152,197,254,7,68,167,0,252,159,165,255,239,78,54,255,24,63,55,255,38,222,94,0,237,183,12,255,206,204,210,0,19,39,246,254,30,74,231,0,135,108,29,1,179,115,0,0,117,118,116,1,132,6,252,255,145,129,161,1,105,67,141,0,82,37,226,255,238,226,228,255,204,214,129,254,162,123,100,255,185,121,234,0,45,108,231,0,66,8,56,255,132,136,128,0,172,224,66,254,175,157,188,0,230,223,226,254,242,219,69,0,184,14,119,1,82,162,56,0,114,123,20,0,162,103,85,255,49,239,99,254,156,135,215,0,111,255,167,254,39,196,214,0,144,38,79,1,249,168,125,0,155,97,156,255,23,52,219,255,150,22,144,0,44,149,165,255,40,127,183,0,196,77,233,255,118,129,210,255,170,135,230,255,214,119,198,0,233,240,35,0,253,52,7,255,117,102,48,255,21,204,154,255,179,136,177,255,23,2,3,1,149,130,89,255,252,17,159,1,70,60,26,0,144,107,17,0,180,190,60,255,56,182,59,255,110,71,54,255,198,18,129,255,149,224,87,255,223,21,152,255,138,22,182,255,250,156,205,0,236,45,208,255,79,148,242,1,101,70,209,0,103,78,174,0,101,144,172,255,152,136,237,1,191,194,136,0,113,80,125,1,152,4,141,0,155,150,53,255,196,116,245,0,239,114,73,254,19,82,17,255,124,125,234,255,40,52,191,0,42,210,158,255,155,132,165,0,178,5,42,1,64,92,40,255,36,85,77,255,178,228,118,0,137,66,96,254,115,226,66,0,110,240,69,254,151,111,80,0,167,174,236,255,227,108,107,255,188,242,65,255,183,81,255,0,57,206,181,255,47,34,181,255,213,240,158,1,71,75,95,0,156,40,24,255,102,210,81,0,171,199,228,255,154,34,41,0,227,175,75,0,21,239,195,0,138,229,95,1,76,192,49,0,117,123,87,1,227,225,130,0,125,62,63,255,2,198,171,0,254,36,13,254,145,186,206,0,148,255,244,255,35,0,166,0,30,150,219,1,92,228,212,0,92,198,60,254,62,133,200,255,201,41,59,0,125,238,109,255,180,163,238,1,140,122,82,0,9,22,88,255,197,157,47,255,153,94,57,0,88,30,182,0,84,161,85,0,178,146,124,0,166,166,7,255,21,208,223,0,156,182,242,0,155,121,185,0,83,156,174,254,154,16,118,255,186,83,232,1,223,58,121,255,29,23,88,0,35,125,127,255,170,5,149,254,164,12,130,255,155,196,29,0,161,96,136,0,7,35,29,1,162,37,251,0,3,46,242,255,0,217,188,0,57,174,226,1,206,233,2,0,57,187,136,254,123,189,9,255,201,117,127,255,186,36,204,0,231,25,216,0,80,78,105,0,19,134,129,255,148,203,68,0,141,81,125,254,248,165,200,255,214,144,135,0,151,55,166,255,38,235,91,0,21,46,154,0,223,254,150,255,35,153,180,255,125,176,29,1,43,98,30,255,216,122,230,255,233,160,12,0,57,185,12,254,240,113,7,255,5,9,16,254,26,91,108,0,109,198,203,0,8,147,40,0,129,134,228,255,124,186,40,255,114,98,132,254,166,132,23,0,99,69,44,0,9,242,238,255,184,53,59,0,132,129,102,255,52,32,243,254,147,223,200,255,123,83,179,254,135,144,201,255,141,37,56,1,151,60,227,255,90,73,156,1,203,172,187,0,80,151,47,255,94,137,231,255,36,191,59,255,225,209,181,255,74,215,213,254,6,118,179,255,153,54,193,1,50,0,231,0,104,157,72,1,140,227,154,255,182,226,16,254,96,225,92,255,115,20,170,254,6,250,78,0,248,75,173,255,53,89,6,255,0,180,118,0,72,173,1,0,64,8,206,1,174,133,223,0,185,62,133,255,214,11,98,0,197,31,208,0,171,167,244,255,22,231,181,1,150,218,185,0,247,169,97,1,165,139,247,255,47,120,149,1,103,248,51,0,60,69,28,254,25,179,196,0,124,7,218,254,58,107,81,0,184,233,156,255,252,74,36,0,118,188,67,0,141,95,53,255,222,94,165,254,46,61,53,0,206,59,115,255,47,236,250,255,74,5,32,1,129,154,238,255,106,32,226,0,121,187,61,255,3,166,241,254,67,170,172,255,29,216,178,255,23,201,252,0,253,110,243,0,200,125,57,0,109,192,96,255,52,115,238,0,38,121,243,255,201,56,33,0,194,118,130,0,75,96,25,255,170,30,230,254,39,63,253,0,36,45,250,255,251,1,239,0,160,212,92,1,45,209,237,0,243,33,87,254,237,84,201,255,212,18,157,254,212,99,127,255,217,98,16,254,139,172,239,0,168,201,130,255,143,193,169,255,238,151,193,1,215,104,41,0,239,61,165,254,2,3,242,0,22,203,177,254,177,204,22,0,149,129,213,254,31,11,41,255,0,159,121,254,160,25,114,255,162,80,200,0,157,151,11,0,154,134,78,1,216,54,252,0,48,103,133,0,105,220,197,0,253,168,77,254,53,179,23,0,24,121,240,1,255,46,96,255,107,60,135,254,98,205,249,255,63,249,119,255,120,59,211,255,114,180,55,254,91,85,237,0,149,212,77,1,56,73,49,0,86,198,150,0,93,209,160,0,69,205,182,255,244,90,43,0,20,36,176,0,122,116,221,0,51,167,39,1,231,1,63,255,13,197,134,0,3,209,34,255,135,59,202,0,167,100,78,0,47,223,76,0,185,60,62,0,178,166,123,1,132,12,161,255,61,174,43,0,195,69,144,0,127,47,191,1,34,44,78,0,57,234,52,1,255,22,40,255,246,94,146,0,83,228,128,0,60,78,224,255,0,96,210,255,153,175,236,0,159,21,73,0,180,115,196,254,131,225,106,0,255,167,134,0,159,8,112,255,120,68,194,255,176,196,198,255,118,48,168,255,93,169,1,0,112,200,102,1,74,24,254,0,19,141,4,254,142,62,63,0,131,179,187,255,77,156,155,255,119,86,164,0,170,208,146,255,208,133,154,255,148,155,58,255,162,120,232,254,252,213,155,0,241,13,42,0,94,50,131,0,179,170,112,0,140,83,151,255,55,119,84,1,140,35,239,255,153,45,67,1,236,175,39,0,54,151,103,255,158,42,65,255,196,239,135,254,86,53,203,0,149,97,47,254,216,35,17,255,70,3,70,1,103,36,90,255,40,26,173,0,184,48,13,0,163,219,217,255,81,6,1,255,221,170,108,254,233,208,93,0,100,201,249,254,86,36,35,255,209,154,30,1,227,201,251,255,2,189,167,254,100,57,3,0,13,128,41,0,197,100,75,0,150,204,235,255,145,174,59,0,120,248,149,255,85,55,225,0,114,210,53,254,199,204,119,0,14,247,74,1,63,251,129,0,67,104,151,1,135,130,80,0,79,89,55,255,117,230,157,255,25,96,143,0,213,145,5,0,69,241,120,1,149,243,95,255,114,42,20,0,131,72,2,0,154,53,20,255,73,62,109,0,196,102,152,0,41,12,204,255,122,38,11,1,250,10,145,0,207,125,148,0,246,244,222,255,41,32,85,1,112,213,126,0,162,249,86,1,71,198,127,255,81,9,21,1,98,39,4,255,204,71,45,1,75,111,137,0,234,59,231,0,32,48,95,255,204,31,114,1,29,196,181,255,51,241,167,254,93,109,142,0,104,144,45,0,235,12,181,255,52,112,164,0,76,254,202,255,174,14,162,0,61,235,147,255,43,64,185,254,233,125,217,0,243,88,167,254,74,49,8,0,156,204,66,0,124,214,123,0,38,221,118,1,146,112,236,0,114,98,177,0,151,89,199,0,87,197,112,0,185,149,161,0,44,96,165,0,248,179,20,255,188,219,216,254,40,62,13,0,243,142,141,0,229,227,206,255,172,202,35,255,117,176,225,255,82,110,38,1,42,245,14,255,20,83,97,0,49,171,10,0,242,119,120,0,25,232,61,0,212,240,147,255,4,115,56,255,145,17,239,254,202,17,251,255,249,18,245,255,99,117,239,0,184,4,179,255,246,237,51,255,37,239,137,255,166,112,166,255,81,188,33,255,185,250,142,255,54,187,173,0,208,112,201,0,246,43,228,1,104,184,88,255,212,52,196,255,51,117,108,255,254,117,155,0,46,91,15,255,87,14,144,255,87,227,204,0,83,26,83,1,159,76,227,0,159,27,213,1,24,151,108,0,117,144,179,254,137,209,82,0,38,159,10,0,115,133,201,0,223,182,156,1,110,196,93,255,57,60,233,0,5,167,105,255,154,197,164,0,96,34,186,255,147,133,37,1,220,99,190,0,1,167,84,255,20,145,171,0,194,197,251,254,95,78,133,255,252,248,243,255,225,93,131,255,187,134,196,255,216,153,170,0,20,118,158,254,140,1,118,0,86,158,15,1,45,211,41,255,147,1,100,254,113,116,76,255,211,127,108,1,103,15,48,0,193,16,102,1,69,51,95,255,107,128,157,0,137,171,233,0,90,124,144,1,106,161,182,0,175,76,236,1,200,141,172,255,163,58,104,0,233,180,52,255,240,253,14,255,162,113,254,255,38,239,138,254,52,46,166,0,241,101,33,254,131,186,156,0,111,208,62,255,124,94,160,255,31,172,254,0,112,174,56,255,188,99,27,255,67,138,251,0,125,58,128,1,156,152,174,255,178,12,247,255,252,84,158,0,82,197,14,254,172,200,83,255,37,39,46,1,106,207,167,0,24,189,34,0,131,178,144,0,206,213,4,0,161,226,210,0,72,51,105,255,97,45,187,255,78,184,223,255,176,29,251,0,79,160,86,255,116,37,178,0,82,77,213,1,82,84,141,255,226,101,212,1,175,88,199,255,245,94,247,1,172,118,109,255,166,185,190,0,131,181,120,0,87,254,93,255,134,240,73,255,32,245,143,255,139,162,103,255,179,98,18,254,217,204,112,0,147,223,120,255,53,10,243,0,166,140,150,0,125,80,200,255,14,109,219,255,91,218,1,255,252,252,47,254,109,156,116,255,115,49,127,1,204,87,211,255,148,202,217,255,26,85,249,255,14,245,134,1,76,89,169,255,242,45,230,0,59,98,172,255,114,73,132,254,78,155,49,255,158,126,84,0,49,175,43,255,16,182,84,255,157,103,35,0,104,193,109,255,67,221,154,0,201,172,1,254,8,162,88,0,165,1,29,255,125,155,229,255,30,154,220,1,103,239,92,0,220,1,109,255,202,198,1,0,94,2,142,1,36,54,44,0,235,226,158,255,170,251,214,255,185,77,9,0,97,74,242,0,219,163,149,255,240,35,118,255,223,114,88,254,192,199,3,0,106,37,24,255,201,161,118,255,97,89,99,1,224,58,103,255,101,199,147,254,222,60,99,0,234,25,59,1,52,135,27,0,102,3,91,254,168,216,235,0,229,232,136,0,104,60,129,0,46,168,238,0,39,191,67,0,75,163,47,0,143,97,98,255,56,216,168,1,168,233,252,255,35,111,22,255,92,84,43,0,26,200,87,1,91,253,152,0,202,56,70,0,142,8,77,0,80,10,175,1,252,199,76,0,22,110,82,255,129,1,194,0,11,128,61,1,87,14,145,255,253,222,190,1,15,72,174,0,85,163,86,254,58,99,44,255,45,24,188,254,26,205,15,0,19,229,210,254,248,67,195,0,99,71,184,0,154,199,37,255,151,243,121,255,38,51,75,255,201,85,130,254,44,65,250,0,57,147,243,254,146,43,59,255,89,28,53,0,33,84,24,255,179,51,18,254,189,70,83,0,11,156,179,1,98,134,119,0,158,111,111,0,119,154,73,255,200,63,140,254,45,13,13,255,154,192,2,254,81,72,42,0,46,160,185,254,44,112,6,0,146,215,149,1,26,176,104,0,68,28,87,1,236,50,153,255,179,128,250,254,206,193,191,255,166,92,137,254,53,40,239,0,210,1,204,254,168,173,35,0,141,243,45,1,36,50,109,255,15,242,194,255,227,159,122,255,176,175,202,254,70,57,72,0,40,223,56,0,208,162,58,255,183,98,93,0,15,111,12,0,30,8,76,255,132,127,246,255,45,242,103,0,69,181,15,255,10,209,30,0,3,179,121,0,241,232,218,1,123,199,88,255,2,210,202,1,188,130,81,255,94,101,208,1,103,36,45,0,76,193,24,1,95,26,241,255,165,162,187,0,36,114,140,0,202,66,5,255,37,56,147,0,152,11,243,1,127,85,232,255,250,135,212,1,185,177,113,0,90,220,75,255,69,248,146,0,50,111,50,0,92,22,80,0,244,36,115,254,163,100,82,255,25,193,6,1,127,61,36,0,253,67,30,254,65,236,170,255,161,17,215,254,63,175,140,0,55,127,4,0,79,112,233,0,109,160,40,0,143,83,7,255,65,26,238,255,217,169,140,255,78,94,189,255,0,147,190,255,147,71,186,254,106,77,127,255,233,157,233,1,135,87,237,255,208,13,236,1,155,109,36,255,180,100,218,0,180,163,18,0,190,110,9,1,17,63,123,255,179,136,180,255,165,123,123,255,144,188,81,254,71,240,108,255,25,112,11,255,227,218,51,255,167,50,234,255,114,79,108,255,31,19,115,255,183,240,99,0,227,87,143,255,72,217,248,255,102,169,95,1,129,149,149,0,238,133,12,1,227,204,35,0,208,115,26,1,102,8,234,0,112,88,143,1,144,249,14,0,240,158,172,254,100,112,119],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+10240);allocate([194,141,153,254,40,56,83,255,121,176,46,0,42,53,76,255,158,191,154,0,91,209,92,0,173,13,16,1,5,72,226,255,204,254,149,0,80,184,207,0,100,9,122,254,118,101,171,255,252,203,0,254,160,207,54,0,56,72,249,1,56,140,13,255,10,64,107,254,91,101,52,255,225,181,248,1,139,255,132,0,230,145,17,0,233,56,23,0,119,1,241,255,213,169,151,255,99,99,9,254,185,15,191,255,173,103,109,1,174,13,251,255,178,88,7,254,27,59,68,255,10,33,2,255,248,97,59,0,26,30,146,1,176,147,10,0,95,121,207,1,188,88,24,0,185,94,254,254,115,55,201,0,24,50,70,0,120,53,6,0,142,66,146,0,228,226,249,255,104,192,222,1,173,68,219,0,162,184,36,255,143,102,137,255,157,11,23,0,125,45,98,0,235,93,225,254,56,112,160,255,70,116,243,1,153,249,55,255,129,39,17,1,241,80,244,0,87,69,21,1,94,228,73,255,78,66,65,255,194,227,231,0,61,146,87,255,173,155,23,255,112,116,219,254,216,38,11,255,131,186,133,0,94,212,187,0,100,47,91,0,204,254,175,255,222,18,215,254,173,68,108,255,227,228,79,255,38,221,213,0,163,227,150,254,31,190,18,0,160,179,11,1,10,90,94,255,220,174,88,0,163,211,229,255,199,136,52,0,130,95,221,255,140,188,231,254,139,113,128,255,117,171,236,254,49,220,20,255,59,20,171,255,228,109,188,0,20,225,32,254,195,16,174,0,227,254,136,1,135,39,105,0,150,77,206,255,210,238,226,0,55,212,132,254,239,57,124,0,170,194,93,255,249,16,247,255,24,151,62,255,10,151,10,0,79,139,178,255,120,242,202,0,26,219,213,0,62,125,35,255,144,2,108,255,230,33,83,255,81,45,216,1,224,62,17,0,214,217,125,0,98,153,153,255,179,176,106,254,131,93,138,255,109,62,36,255,178,121,32,255,120,252,70,0,220,248,37,0,204,88,103,1,128,220,251,255,236,227,7,1,106,49,198,255,60,56,107,0,99,114,238,0,220,204,94,1,73,187,1,0,89,154,34,0,78,217,165,255,14,195,249,255,9,230,253,255,205,135,245,0,26,252,7,255,84,205,27,1,134,2,112,0,37,158,32,0,231,91,237,255,191,170,204,255,152,7,222,0,109,192,49,0,193,166,146,255,232,19,181,255,105,142,52,255,103,16,27,1,253,200,165,0,195,217,4,255,52,189,144,255,123,155,160,254,87,130,54,255,78,120,61,255,14,56,41,0,25,41,125,255,87,168,245,0,214,165,70,0,212,169,6,255,219,211,194,254,72,93,164,255,197,33,103,255,43,142,141,0,131,225,172,0,244,105,28,0,68,68,225,0,136,84,13,255,130,57,40,254,139,77,56,0,84,150,53,0,54,95,157,0,144,13,177,254,95,115,186,0,117,23,118,255,244,166,241,255,11,186,135,0,178,106,203,255,97,218,93,0,43,253,45,0,164,152,4,0,139,118,239,0,96,1,24,254,235,153,211,255,168,110,20,255,50,239,176,0,114,41,232,0,193,250,53,0,254,160,111,254,136,122,41,255,97,108,67,0,215,152,23,255,140,209,212,0,42,189,163,0,202,42,50,255,106,106,189,255,190,68,217,255,233,58,117,0,229,220,243,1,197,3,4,0,37,120,54,254,4,156,134,255,36,61,171,254,165,136,100,255,212,232,14,0,90,174,10,0,216,198,65,255,12,3,64,0,116,113,115,255,248,103,8,0,231,125,18,255,160,28,197,0,30,184,35,1,223,73,249,255,123,20,46,254,135,56,37,255,173,13,229,1,119,161,34,255,245,61,73,0,205,125,112,0,137,104,134,0,217,246,30,255,237,142,143,0,65,159,102,255,108,164,190,0,219,117,173,255,34,37,120,254,200,69,80,0,31,124,218,254,74,27,160,255,186,154,199,255,71,199,252,0,104,81,159,1,17,200,39,0,211,61,192,1,26,238,91,0,148,217,12,0,59,91,213,255,11,81,183,255,129,230,122,255,114,203,145,1,119,180,66,255,72,138,180,0,224,149,106,0,119,82,104,255,208,140,43,0,98,9,182,255,205,101,134,255,18,101,38,0,95,197,166,255,203,241,147,0,62,208,145,255,133,246,251,0,2,169,14,0,13,247,184,0,142,7,254,0,36,200,23,255,88,205,223,0,91,129,52,255,21,186,30,0,143,228,210,1,247,234,248,255,230,69,31,254,176,186,135,255,238,205,52,1,139,79,43,0,17,176,217,254,32,243,67,0,242,111,233,0,44,35,9,255,227,114,81,1,4,71,12,255,38,105,191,0,7,117,50,255,81,79,16,0,63,68,65,255,157,36,110,255,77,241,3,255,226,45,251,1,142,25,206,0,120,123,209,1,28,254,238,255,5,128,126,255,91,222,215,255,162,15,191,0,86,240,73,0,135,185,81,254,44,241,163,0,212,219,210,255,112,162,155,0,207,101,118,0,168,72,56,255,196,5,52,0,72,172,242,255,126,22,157,255,146,96,59,255,162,121,152,254,140,16,95,0,195,254,200,254,82,150,162,0,119,43,145,254,204,172,78,255,166,224,159,0,104,19,237,255,245,126,208,255,226,59,213,0,117,217,197,0,152,72,237,0,220,31,23,254,14,90,231,255,188,212,64,1,60,101,246,255,85,24,86,0,1,177,109,0,146,83,32,1,75,182,192,0,119,241,224,0,185,237,27,255,184,101,82,1,235,37,77,255,253,134,19,0,232,246,122,0,60,106,179,0,195,11,12,0,109,66,235,1,125,113,59,0,61,40,164,0,175,104,240,0,2,47,187,255,50,12,141,0,194,139,181,255,135,250,104,0,97,92,222,255,217,149,201,255,203,241,118,255,79,151,67,0,122,142,218,255,149,245,239,0,138,42,200,254,80,37,97,255,124,112,167,255,36,138,87,255,130,29,147,255,241,87,78,255,204,97,19,1,177,209,22,255,247,227,127,254,99,119,83,255,212,25,198,1,16,179,179,0,145,77,172,254,89,153,14,255,218,189,167,0,107,233,59,255,35,33,243,254,44,112,112,255,161,127,79,1,204,175,10,0,40,21,138,254,104,116,228,0,199,95,137,255,133,190,168,255,146,165,234,1,183,99,39,0,183,220,54,254,255,222,133,0,162,219,121,254,63,239,6,0,225,102,54,255,251,18,246,0,4,34,129,1,135,36,131,0,206,50,59,1,15,97,183,0,171,216,135,255,101,152,43,255,150,251,91,0,38,145,95,0,34,204,38,254,178,140,83,255,25,129,243,255,76,144,37,0,106,36,26,254,118,144,172,255,68,186,229,255,107,161,213,255,46,163,68,255,149,170,253,0,187,17,15,0,218,160,165,255,171,35,246,1,96,13,19,0,165,203,117,0,214,107,192,255,244,123,177,1,100,3,104,0,178,242,97,255,251,76,130,255,211,77,42,1,250,79,70,255,63,244,80,1,105,101,246,0,61,136,58,1,238,91,213,0,14,59,98,255,167,84,77,0,17,132,46,254,57,175,197,255,185,62,184,0,76,64,207,0,172,175,208,254,175,74,37,0,138,27,211,254,148,125,194,0,10,89,81,0,168,203,101,255,43,213,209,1,235,245,54,0,30,35,226,255,9,126,70,0,226,125,94,254,156,117,20,255,57,248,112,1,230,48,64,255,164,92,166,1,224,214,230,255,36,120,143,0,55,8,43,255,251,1,245,1,106,98,165,0,74,107,106,254,53,4,54,255,90,178,150,1,3,120,123,255,244,5,89,1,114,250,61,255,254,153,82,1,77,15,17,0,57,238,90,1,95,223,230,0,236,52,47,254,103,148,164,255,121,207,36,1,18,16,185,255,75,20,74,0,187,11,101,0,46,48,129,255,22,239,210,255,77,236,129,255,111,77,204,255,61,72,97,255,199,217,251,255,42,215,204,0,133,145,201,255,57,230,146,1,235,100,198,0,146,73,35,254,108,198,20,255,182,79,210,255,82,103,136,0,246,108,176,0,34,17,60,255,19,74,114,254,168,170,78,255,157,239,20,255,149,41,168,0,58,121,28,0,79,179,134,255,231,121,135,255,174,209,98,255,243,122,190,0,171,166,205,0,212,116,48,0,29,108,66,255,162,222,182,1,14,119,21,0,213,39,249,255,254,223,228,255,183,165,198,0,133,190,48,0,124,208,109,255,119,175,85,255,9,209,121,1,48,171,189,255,195,71,134,1,136,219,51,255,182,91,141,254,49,159,72,0,35,118,245,255,112,186,227,255,59,137,31,0,137,44,163,0,114,103,60,254,8,213,150,0,162,10,113,255,194,104,72,0,220,131,116,255,178,79,92,0,203,250,213,254,93,193,189,255,130,255,34,254,212,188,151,0,136,17,20,255,20,101,83,255,212,206,166,0,229,238,73,255,151,74,3,255,168,87,215,0,155,188,133,255,166,129,73,0,240,79,133,255,178,211,81,255,203,72,163,254,193,168,165,0,14,164,199,254,30,255,204,0,65,72,91,1,166,74,102,255,200,42,0,255,194,113,227,255,66,23,208,0,229,216,100,255,24,239,26,0,10,233,62,255,123,10,178,1,26,36,174,255,119,219,199,1,45,163,190,0,16,168,42,0,166,57,198,255,28,26,26,0,126,165,231,0,251,108,100,255,61,229,121,255,58,118,138,0,76,207,17,0,13,34,112,254,89,16,168,0,37,208,105,255,35,201,215,255,40,106,101,254,6,239,114,0,40,103,226,254,246,127,110,255,63,167,58,0,132,240,142,0,5,158,88,255,129,73,158,255,94,89,146,0,230,54,146,0,8,45,173,0,79,169,1,0,115,186,247,0,84,64,131,0,67,224,253,255,207,189,64,0,154,28,81,1,45,184,54,255,87,212,224,255,0,96,73,255,129,33,235,1,52,66,80,255,251,174,155,255,4,179,37,0,234,164,93,254,93,175,253,0,198,69,87,255,224,106,46,0,99,29,210,0,62,188,114,255,44,234,8,0,169,175,247,255,23,109,137,255,229,182,39,0,192,165,94,254,245,101,217,0,191,88,96,0,196,94,99,255,106,238,11,254,53,126,243,0,94,1,101,255,46,147,2,0,201,124,124,255,141,12,218,0,13,166,157,1,48,251,237,255,155,250,124,255,106,148,146,255,182,13,202,0,28,61,167,0,217,152,8,254,220,130,45,255,200,230,255,1,55,65,87,255,93,191,97,254,114,251,14,0,32,105,92,1,26,207,141,0,24,207,13,254,21,50,48,255,186,148,116,255,211,43,225,0,37,34,162,254,164,210,42,255,68,23,96,255,182,214,8,255,245,117,137,255,66,195,50,0,75,12,83,254,80,140,164,0,9,165,36,1,228,110,227,0,241,17,90,1,25,52,212,0,6,223,12,255,139,243,57,0,12,113,75,1,246,183,191,255,213,191,69,255,230,15,142,0,1,195,196,255,138,171,47,255,64,63,106,1,16,169,214,255,207,174,56,1,88,73,133,255,182,133,140,0,177,14,25,255,147,184,53,255,10,227,161,255,120,216,244,255,73,77,233,0,157,238,139,1,59,65,233,0,70,251,216,1,41,184,153,255,32,203,112,0,146,147,253,0,87,101,109,1,44,82,133,255,244,150,53,255,94,152,232,255,59,93,39,255,88,147,220,255,78,81,13,1,32,47,252,255,160,19,114,255,93,107,39,255,118,16,211,1,185,119,209,255,227,219,127,254,88,105,236,255,162,110,23,255,36,166,110,255,91,236,221,255,66,234,116,0,111,19,244,254,10,233,26,0,32,183,6,254,2,191,242,0,218,156,53,254,41,60,70,255,168,236,111,0,121,185,126,255,238,142,207,255,55,126,52,0,220,129,208,254,80,204,164,255,67,23,144,254,218,40,108,255,127,202,164,0,203,33,3,255,2,158,0,0,37,96,188,255,192,49,74,0,109,4,0,0,111,167,10,254,91,218,135,255,203,66,173,255,150,194,226,0,201,253,6,255,174,102,121,0,205,191,110,0,53,194,4,0,81,40,45,254,35,102,143,255,12,108,198,255,16,27,232,255,252,71,186,1,176,110,114,0,142,3,117,1,113,77,142,0,19,156,197,1,92,47,252,0,53,232,22,1,54,18,235,0,46,35,189,255,236,212,129,0,2,96,208,254,200,238,199,255,59,175,164,255,146,43,231,0,194,217,52,255,3,223,12,0,138,54,178,254,85,235,207,0,232,207,34,0,49,52,50,255,166,113,89,255,10,45,216,255,62,173,28,0,111,165,246,0,118,115,91,255,128,84,60,0,167,144,203,0,87,13,243,0,22,30,228,1,177,113,146,255,129,170,230,254,252,153,129,255,145,225,43,0,70,231,5,255,122,105,126,254,86,246,148,255,110,37,154,254,209,3,91,0,68,145,62,0,228,16,165,255,55,221,249,254,178,210,91,0,83,146,226,254,69,146,186,0,93,210,104,254,16,25,173,0,231,186,38,0,189,122,140,255,251,13,112,255,105,110,93,0,251,72,170,0,192,23,223,255,24,3,202,1,225,93,228,0,153,147,199,254,109,170,22,0,248,101,246,255,178,124,12,255,178,254,102,254,55,4,65,0,125,214,180,0,183,96,147,0,45,117,23,254,132,191,249,0,143,176,203,254,136,183,54,255,146,234,177,0,146,101,86,255,44,123,143,1,33,209,152,0,192,90,41,254,83,15,125,255,213,172,82,0,215,169,144,0,16,13,34,0,32,209,100,255,84,18,249,1,197,17,236,255,217,186,230,0,49,160,176,255,111,118,97,255,237,104,235,0,79,59,92,254,69,249,11,255,35,172,74,1,19,118,68,0,222,124,165,255,180,66,35,255,86,174,246,0,43,74,111,255,126,144,86,255,228,234,91,0,242,213,24,254,69,44,235,255,220,180,35,0,8,248,7,255,102,47,92,255,240,205,102,255,113,230,171,1,31,185,201,255,194,246,70,255,122,17,187,0,134,70,199,255,149,3,150,255,117,63,103,0,65,104,123,255,212,54,19,1,6,141,88,0,83,134,243,255,136,53,103,0,169,27,180,0,177,49,24,0,111,54,167,0,195,61,215,255,31,1,108,1,60,42,70,0,185,3,162,255,194,149,40,255,246,127,38,254,190,119,38,255,61,119,8,1,96,161,219,255,42,203,221,1,177,242,164,255,245,159,10,0,116,196,0,0,5,93,205,254,128,127,179,0,125,237,246,255,149,162,217,255,87,37,20,254,140,238,192,0,9,9,193,0,97,1,226,0,29,38,10,0,0,136,63,255,229,72,210,254,38,134,92,255,78,218,208,1,104,36,84,255,12,5,193,255,242,175,61,255,191,169,46,1,179,147,147,255,113,190,139,254,125,172,31,0,3,75,252,254,215,36,15,0,193,27,24,1,255,69,149,255,110,129,118,0,203,93,249,0,138,137,64,254,38,70,6,0,153,116,222,0,161,74,123,0,193,99,79,255,118,59,94,255,61,12,43,1,146,177,157,0,46,147,191,0,16,255,38,0,11,51,31,1,60,58,98,255,111,194,77,1,154,91,244,0,140,40,144,1,173,10,251,0,203,209,50,254,108,130,78,0,228,180,90,0,174,7,250,0,31,174,60,0,41,171,30,0,116,99,82,255,118,193,139,255,187,173,198,254,218,111,56,0,185,123,216,0,249,158,52,0,52,180,93,255,201,9,91,255,56,45,166,254,132,155,203,255,58,232,110,0,52,211,89,255,253,0,162,1,9,87,183,0,145,136,44,1,94,122,245,0,85,188,171,1,147,92,198,0,0,8,104,0,30,95,174,0,221,230,52,1,247,247,235,255,137,174,53,255,35,21,204,255,71,227,214,1,232,82,194,0,11,48,227,255,170,73,184,255,198,251,252,254,44,112,34,0,131,101,131,255,72,168,187,0,132,135,125,255,138,104,97,255,238,184,168,255,243,104,84,255,135,216,226,255,139,144,237,0,188,137,150,1,80,56,140,255,86,169,167,255,194,78,25,255,220,17,180,255,17,13,193,0,117,137,212,255,141,224,151,0,49,244,175,0,193,99,175,255,19,99,154,1,255,65,62,255,156,210,55,255,242,244,3,255,250,14,149,0,158,88,217,255,157,207,134,254,251,232,28,0,46,156,251,255,171,56,184,255,239,51,234,0,142,138,131,255,25,254,243,1,10,201,194,0,63,97,75,0,210,239,162,0,192,200,31,1,117,214,243,0,24,71,222,254,54,40,232,255,76,183,111,254,144,14,87,255,214,79,136,255,216,196,212,0,132,27,140,254,131,5,253,0,124,108,19,255,28,215,75,0,76,222,55,254,233,182,63,0,68,171,191,254,52,111,222,255,10,105,77,255,80,170,235,0,143,24,88,255,45,231,121,0,148,129,224,1,61,246,84,0,253,46,219,255,239,76,33,0,49,148,18,254,230,37,69,0,67,134,22,254,142,155,94,0,31,157,211,254,213,42,30,255,4,228,247,254,252,176,13,255,39,0,31,254,241,244,255,255,170,45,10,254,253,222,249,0,222,114,132,0,255,47,6,255,180,163,179,1,84,94,151,255,89,209,82,254,229,52,169,255,213,236,0,1,214,56,228,255,135,119,151,255,112,201,193,0,83,160,53,254,6,151,66,0,18,162,17,0,233,97,91,0,131,5,78,1,181,120,53,255,117,95,63,255,237,117,185,0,191,126,136,255,144,119,233,0,183,57,97,1,47,201,187,255,167,165,119,1,45,100,126,0,21,98,6,254,145,150,95,255,120,54,152,0,209,98,104,0,143,111,30,254,184,148,249,0,235,216,46,0,248,202,148,255,57,95,22,0,242,225,163,0,233,247,232,255,71,171,19,255,103,244,49,255,84,103,93,255,68,121,244,1,82,224,13,0,41,79,43,255,249,206,167,255,215,52,21,254,192,32,22,255,247,111,60,0,101,74,38,255,22,91,84,254,29,28,13,255,198,231,215,254,244,154,200,0,223,137,237,0,211,132,14,0,95,64,206,255,17,62,247,255,233,131,121,1,93,23,77,0,205,204,52,254,81,189,136,0,180,219,138,1,143,18,94,0,204,43,140,254,188,175,219,0,111,98,143,255,151,63,162,255,211,50,71,254,19,146,53,0,146,45,83,254,178,82,238,255,16,133,84,255,226,198,93,255,201,97,20,255,120,118,35,255,114,50,231,255,162,229,156,255,211,26,12,0,114,39,115,255,206,212,134,0,197,217,160,255,116,129,94,254,199,215,219,255,75,223,249,1,253,116,181,255,232,215,104,255,228,130,246,255,185,117,86,0,14,5,8,0,239,29,61,1,237,87,133,255,125,146,137,254,204,168,223,0,46,168,245,0,154,105,22,0,220,212,161,255,107,69,24,255,137,218,181,255,241,84,198,255,130,122,211,255,141,8,153,255,190,177,118,0,96,89,178,0,255,16,48,254,122,96,105,255,117,54,232,255,34,126,105,255,204,67,166,0,232,52,138,255,211,147,12,0,25,54,7,0,44,15,215,254,51,236,45,0,190,68,129,1,106,147,225,0,28,93,45,254,236,141,15,255,17,61,161,0,220,115,192,0,236,145,24,254,111,168,169,0,224,58,63,255,127,164,188,0,82,234,75,1,224,158,134,0,209,68,110,1,217,166,217,0,70,225,166,1,187,193,143,255,16,7,88,255,10,205,140,0,117,192,156,1,17,56,38,0,27,124,108,1,171,215,55,255,95,253,212,0,155,135,168,255,246,178,153,254,154,68,74,0,232,61,96,254,105,132,59,0,33,76,199,1,189,176,130,255,9,104,25,254,75,198,102,255,233,1,112,0,108,220,20,255,114,230,70,0,140,194,133,255,57,158,164,254,146,6,80,255,169,196,97,1,85,183,130,0,70,158,222,1,59,237,234,255,96,25,26,255,232,175,97,255,11,121,248,254,88,35,194,0,219,180,252,254,74,8,227,0,195,227,73,1,184,110,161,255,49,233,164,1,128,53,47,0,82,14,121,255,193,190,58,0,48,174,117,255,132,23,32,0,40,10,134,1,22,51,25,255,240,11,176,255,110,57,146,0,117,143,239,1,157,101,118,255,54,84,76,0,205,184,18,255,47,4,72,255,78,112,85,255,193,50,66,1,93,16,52,255,8,105,134,0,12,109,72,255,58,156,251,0,144,35,204,0,44,160,117,254,50,107,194,0,1,68,165,255,111,110,162,0,158,83,40,254,76,214,234,0,58,216,205,255,171,96,147,255,40,227,114,1,176,227,241,0,70,249,183,1,136,84,139,255,60,122,247,254,143,9,117,255,177,174,137,254,73,247,143,0,236,185,126,255,62,25,247,255,45,64,56,255,161,244,6,0,34,57,56,1,105,202,83,0,128,147,208,0,6,103,10,255,74,138,65,255,97,80,100,255,214,174,33,255,50,134,74,255,110,151,130,254,111,84,172,0,84,199,75,254,248,59,112,255,8,216,178,1,9,183,95,0,238,27,8,254,170,205,220,0,195,229,135,0,98,76,237,255,226,91,26,1,82,219,39,255,225,190,199,1,217,200,121,255,81,179,8,255,140,65,206,0,178,207,87,254,250,252,46,255,104,89,110,1,253,189,158,255,144,214,158,255,160,245,54,255,53,183,92,1,21,200,194,255,146,33,113,1,209,1,255,0,235,106,43,255,167,52,232,0,157,229,221,0,51,30,25,0,250,221,27,1,65,147,87,255,79,123,196,0,65,196,223,255,76,44,17,1,85,241,68,0,202,183,249,255,65,212,212,255,9,33,154,1,71,59,80,0,175,194,59,255,141,72,9,0,100,160,244,0,230,208,56,0,59,25,75,254,80,194,194,0,18,3,200,254,160,159,115,0,132,143,247,1,111,93,57,255,58,237,11,1,134,222,135,255,122,163,108,1,123,43,190,255,251,189,206,254,80,182,72,255,208,246,224,1,17,60,9,0,161,207,38,0,141,109,91,0,216,15,211,255,136,78,110,0,98,163,104,255,21,80,121,255,173,178,183,1,127,143,4,0,104,60,82,254,214,16,13,255,96,238,33,1,158,148,230,255,127,129,62,255,51,255,210,255,62,141,236,254,157,55,224,255,114,39,244,0,192,188,250,255,228,76,53,0,98,84,81,255,173,203,61,254,147,50,55,255,204,235,191,0,52,197,244,0,88,43,211,254,27,191,119,0,188,231,154,0,66,81,161,0,92,193,160,1,250,227,120,0,123,55,226,0,184,17,72,0,133,168,10,254,22,135,156,255,41,25,103,255,48,202,58,0,186,149,81,255,188,134,239,0,235,181,189,254,217,139,188,255,74,48,82,0,46,218,229,0,189,253,251,0,50,229,12,255,211,141,191,1,128,244,25,255,169,231,122,254,86,47,189,255,132,183,23,255,37,178,150,255,51,137,253,0,200,78,31,0,22,105,50,0,130,60,0,0,132,163,91,254,23,231,187,0,192,79,239,0,157,102,164,255,192,82,20,1,24,181,103,255,240,9,234,0,1,123,164,255,133,233,0,255,202,242,242,0,60,186,245,0,241,16,199,255,224,116,158,254,191,125,91,255,224,86,207,0,121,37,231,255,227,9,198,255,15,153,239,255,121,232,217,254,75,112,82,0,95,12,57,254,51,214,105,255,148,220,97,1,199,98,36,0,156,209,12,254,10,212,52,0,217,180,55,254,212,170,232,255,216,20,84,255,157,250,135,0,157,99,127,254,1,206,41,0,149,36,70,1,54,196,201,255,87,116,0,254,235,171,150,0,27,163,234,0,202,135,180,0,208,95,0,254,123,156,93,0,183,62,75,0,137,235,182,0,204,225,255,255,214,139,210,255,2,115,8,255,29,12,111,0,52,156,1,0,253,21,251,255,37,165,31,254,12,130,211,0,106,18,53,254,42,99,154,0,14,217,61,254,216,11,92,255,200,197,112,254,147,38,199,0,36,252,120,254,107,169,77,0,1,123,159,255,207,75,102,0,163,175,196,0,44,1,240,0,120,186,176,254,13,98,76,255,237,124,241,255,232,146,188,255,200,96,224,0,204,31,41,0,208,200,13,0,21,225,96,255,175,156,196,0,247,208,126,0,62,184,244,254,2,171,81,0,85,115,158,0,54,64,45,255,19,138,114,0,135,71,205,0,227,47,147,1,218,231,66,0,253,209,28,0,244,15,173,255,6,15,118,254,16,150,208,255,185,22,50,255,86,112,207,255,75,113,215,1,63,146,43,255,4,225,19,254,227,23,62,255,14,255,214,254,45,8,205,255,87,197,151,254,210,82,215,255,245,248,247,255,128,248,70,0,225,247,87,0,90,120,70,0,213,245,92,0,13,133,226,0,47,181,5,1,92,163,105,255,6,30,133,254,232,178,61,255,230,149,24,255,18,49,158,0,228,100,61,254,116,243,251,255,77,75,92,1,81,219,147,255,76,163,254,254,141,213,246,0,232,37,152,254,97,44,100,0,201,37,50,1,212,244,57,0,174,171,183,255,249,74,112,0,166,156,30,0,222,221,97,255,243,93,73,254,251,101,100,255,216,217,93,255,254,138,187,255,142,190,52,255,59,203,177,255,200,94,52,0,115,114,158,255,165,152,104,1,126,99,226,255,118,157,244,1,107,200,16,0,193,90,229,0,121,6,88,0,156,32,93,254,125,241,211,255,14,237,157,255,165,154,21,255,184,224,22,255,250,24,152,255,113,77,31,0,247,171,23,255,237,177,204,255,52,137,145,255,194,182,114,0,224,234,149,0,10,111,103,1,201,129,4,0,238,142,78,0,52,6,40,255,110,213,165,254,60,207,253,0,62,215,69,0,96,97,0,255,49,45,202,0,120,121,22,255,235,139,48,1,198,45,34,255,182,50,27,1,131,210,91,255,46,54,128,0,175,123,105,255,198,141,78,254,67,244,239,255,245,54,103,254,78,38,242,255,2,92,249,254,251,174,87,255,139,63,144,0,24,108,27,255,34,102,18,1,34,22,152,0,66,229,118,254,50,143,99,0,144,169,149,1,118,30,152,0,178,8,121,1,8,159,18,0,90,101,230,255,129,29,119,0,68,36,11,1,232,183,55,0,23,255,96,255,161,41,193,255,63,139,222,0,15,179,243,0,255,100,15,255,82,53,135,0,137,57,149,1,99,240,170,255,22,230,228,254,49,180,82,255,61,82,43,0,110,245,217,0,199,125,61,0,46,253,52,0,141,197,219,0,211,159,193,0,55,121,105,254,183,20,129,0,169,119,170,255,203,178,139,255,135,40,182,255,172,13,202,255,65,178,148,0,8,207,43,0,122,53,127,1,74,161,48,0,227,214,128,254,86,11,243,255,100,86,7,1,245,68,134,255,61,43,21,1,152,84,94,255,190,60,250,254,239,118,232,255,214,136,37,1,113,76,107,255,93,104,100,1,144,206,23,255,110,150,154,1,228,103,185,0,218,49,50,254,135,77,139,255,185,1,78,0,0,161,148,255,97,29,233,255,207,148,149,255,160,168,0,0,91,128,171,255,6,28,19,254,11,111,247,0,39,187,150,255,138,232,149,0,117,62,68,255,63,216,188,255,235,234,32,254,29,57,160,255,25,12,241,1,169,60,191,0,32,131,141,255,237,159,123,255,94,197,94,254,116,254,3,255,92,179,97,254,121,97,92,255,170,112,14,0,21,149,248,0,248,227,3,0,80,96,109,0,75,192,74,1,12,90,226,255,161,106,68,1,208,114,127,255,114,42,255,254,74,26,74,255,247,179,150,254,121,140,60,0,147,70,200,255,214,40,161,255,161,188,201,255,141,65,135,255,242,115,252,0,62,47,202,0,180,149,255,254,130,55,237,0,165,17,186,255,10,169,194,0,156,109,218,255,112,140,123,255,104,128,223,254,177,142,108,255,121,37,219,255,128,77,18,255,111,108,23,1,91,192,75,0,174,245,22,255,4,236,62,255,43,64,153,1,227,173,254,0,237,122,132,1,127,89,186,255,142,82,128,254,252,84,174,0,90,179,177,1,243,214,87,255,103,60,162,255,208,130,14,255,11,130,139,0,206,129,219,255,94,217,157,255,239,230,230,255,116,115,159,254,164,107,95,0,51,218,2,1,216,125,198,255,140,202,128,254,11,95,68,255,55,9,93,254,174,153,6,255,204,172,96,0,69,160,110,0,213,38,49,254,27,80,213,0,118,125,114,0,70,70,67,255,15,142,73,255,131,122,185,255,243,20,50,254,130,237,40,0,210,159,140,1,197,151,65,255,84,153,66,0,195,126,90,0,16,238,236,1,118,187,102,255,3,24,133,255,187,69,230,0,56,197,92,1,213,69,94,255,80,138,229,1,206,7,230,0,222,111,230,1,91,233,119,255,9,89,7,1,2,98,1,0,148,74,133,255,51,246,180,255,228,177,112,1,58,189,108,255,194,203,237,254,21,209,195,0,147,10,35,1,86,157,226,0,31,163,139,254,56,7,75,255,62,90,116,0,181,60,169,0,138,162,212,254,81,167,31,0,205,90,112,255,33,112,227,0,83,151,117,1,177,224,73,255,174,144,217,255,230,204,79,255,22,77,232,255,114,78,234,0,224,57,126,254,9,49,141,0,242,147,165,1,104,182,140,255,167,132,12,1,123,68,127,0,225,87,39,1,251,108,8,0,198,193,143,1,121,135,207,255,172,22,70,0,50,68,116,255,101,175,40,255,248,105,233,0,166,203,7,0,110,197,218,0,215,254,26,254,168,226,253,0,31,143,96,0,11,103,41,0,183,129,203,254,100,247,74,255,213,126,132,0,210,147,44,0,199,234,27,1,148,47,181,0,155,91,158,1,54,105,175,255,2,78,145,254,102,154,95,0,128,207,127,254,52,124,236,255,130,84,71,0,221,243,211,0,152,170,207,0,222,106,199,0,183,84,94,254,92,200,56,255,138,182,115,1,142,96,146,0,133,136,228,0,97,18,150,0,55,251,66,0,140,102,4,0,202,103,151,0,30,19,248,255,51,184,207,0,202,198,89,0,55,197,225,254,169,95,249,255,66,65,68,255,188,234,126,0,166,223,100,1,112,239,244,0,144,23,194,0,58,39,182,0,244,44,24,254,175,68,179,255,152,118,154,1,176,162,130,0,217,114,204,254,173,126,78,255,33,222,30,255,36,2,91,255,2,143,243,0,9,235,215,0,3,171,151,1,24,215,245,255,168,47,164,254,241,146,207,0,69,129,180,0,68,243,113,0,144,53,72,254,251,45,14,0,23,110,168,0,68,68,79,255,110,70,95,254,174,91,144,255,33,206,95,255,137,41,7,255,19,187,153,254,35,255,112,255,9,145,185,254,50,157,37,0,11,112,49,1,102,8,190,255,234,243,169,1,60,85,23,0,74,39,189,0,116,49,239,0,173,213,210,0,46,161,108,255,159,150,37,0,196,120,185,255,34,98,6,255,153,195,62,255,97,230,71,255,102,61,76,0,26,212,236,255,164,97,16,0,198,59,146,0,163,23,196,0,56,24,61,0,181,98,193,0,251,147,229,255,98,189,24,255,46,54,206,255,234,82,246,0,183,103,38,1,109,62,204,0,10,240,224,0,146,22,117,255,142,154,120,0,69,212,35,0,208,99,118,1,121,255,3,255,72,6,194,0,117,17,197,255,125,15,23,0,154,79,153,0,214,94,197,255,185,55,147,255,62,254,78,254,127,82,153,0,110,102,63,255,108,82,161,255,105,187,212,1,80,138,39,0,60,255,93,255,72,12,186,0,210,251,31,1,190,167,144,255,228,44,19,254,128,67,232,0,214,249,107,254,136,145,86,255,132,46,176,0,189,187,227,255,208,22,140,0,217,211,116,0,50,81,186,254,139,250,31,0,30,64,198,1,135,155,100,0,160,206,23,254,187,162,211,255,16,188,63,0,254,208,49,0,85,84,191,0,241,192,242,255,153,126,145,1,234,162,162,255,230,97,216,1,64,135,126,0,190,148,223,1,52,0,43,255,28,39,189,1,64,136,238,0,175,196,185,0,98,226,213,255,127,159,244,1,226,175,60,0,160,233,142,1,180,243,207,255,69,152,89,1,31,101,21,0,144,25,164,254,139,191,209,0,91,25,121,0,32,147,5,0,39,186,123,255,63,115,230,255,93,167,198,255,143,213,220,255,179,156,19,255,25,66,122,0,214,160,217,255,2,45,62,255,106,79,146,254,51,137,99,255,87,100,231,255,175,145,232,255,101,184,1,255,174,9,125,0,82,37,161,1,36,114,141,255,48,222,142,255,245,186,154,0,5,174,221,254,63,114,155,255,135,55,160,1,80,31,135,0,126,250,179,1,236,218,45,0,20,28,145,1,16,147,73,0,249,189,132,1,17,189,192,255,223,142,198,255,72,20,15,255,250,53,237,254,15,11,18,0,27,211,113,254,213,107,56,255,174,147,146,255,96,126,48,0,23,193,109,1,37,162,94,0,199,157,249,254,24,128,187,255,205,49,178,254,93,164,42,255,43,119,235,1,88,183,237,255,218,210,1,255,107,254,42,0,230,10,99,255,162,0,226,0,219,237,91,0,129,178,203,0,208,50,95,254,206,208,95,255,247,191,89,254,110,234,79,255,165,61,243,0,20,122,112,255,246,246,185,254,103,4,123,0,233,99,230,1,219,91,252,255,199,222,22,255,179,245,233,255,211,241,234,0,111,250,192,255,85,84,136,0,101,58,50,255,131,173,156,254,119,45,51,255,118,233,16,254,242,90,214,0,94,159,219,1,3,3,234,255,98,76,92,254,80,54,230,0,5,228,231,254,53,24,223,255,113,56,118,1,20,132,1,255,171,210,236,0,56,241,158,255,186,115,19,255,8,229,174,0,48,44,0,1,114,114,166,255,6,73,226,255,205,89,244,0,137,227,75,1,248,173,56,0,74,120,246,254,119,3,11,255,81,120,198,255,136,122,98,255,146,241,221,1,109,194,78,255,223,241,70,1,214,200,169,255,97,190,47,255,47,103,174,255,99,92,72,254,118,233,180,255,193,35,233,254,26,229,32,255,222,252,198,0,204,43,71,255,199,84,172,0,134,102,190,0,111,238,97,254,230,40,230,0,227,205,64,254,200,12,225,0,166,25,222,0,113,69,51,255,143,159,24,0,167,184,74,0,29,224,116,254,158,208,233,0,193,116,126,255,212,11,133,255,22,58,140,1,204,36,51,255,232,30,43,0,235,70,181,255,64,56,146,254,169,18,84,255,226,1,13,255,200,50,176,255,52,213,245,254,168,209,97,0,191,71,55,0,34,78,156,0,232,144,58,1,185,74,189,0,186,142,149,254,64,69,127,255,161,203,147,255,176,151,191,0,136,231,203,254,163,182,137,0,161,126,251,254,233,32,66,0,68,207,66,0,30,28,37,0,93,114,96,1,254,92,247,255,44,171,69,0,202,119,11,255,188,118,50,1,255,83,136,255,71,82,26,0,70,227,2,0,32,235,121,1,181,41,154,0,71,134,229,254,202,255,36,0,41,152,5,0,154,63,73,255,34,182,124,0,121,221,150,255,26,204,213,1,41,172,87,0,90,157,146,255,109,130,20,0,71,107,200,255,243,102,189,0,1,195,145,254,46,88,117,0,8,206,227,0,191,110,253,255,109,128,20,254,134,85,51,255,137,177,112,1,216,34,22,255,131,16,208,255,121,149,170,0,114,19,23,1,166,80,31,255,113,240,122,0,232,179,250,0,68,110,180,254,210,170,119,0,223,108,164,255,207,79,233,255,27,229,226,254,209,98,81,255,79,68,7,0,131,185,100,0,170,29,162,255,17,162,107,255,57,21,11,1,100,200,181,255,127,65,166,1,165,134,204,0,104,167,168,0,1,164,79,0,146,135,59,1,70,50,128,255,102,119,13,254,227,6,135,0,162,142,179,255,160,100,222,0,27,224,219,1,158,93,195,255,234,141,137,0,16,24,125,255,238,206,47,255,97,17,98,255,116,110,12,255,96,115,77,0,91,227,232,255,248,254,79,255,92,229,6,254,88,198,139,0,206,75,129,0,250,77,206,255,141,244,123,1,138,69,220,0,32,151,6,1,131,167,22,255,237,68,167,254,199,189,150,0,163,171,138,255,51,188,6,255,95,29,137,254,148,226,179,0,181,107,208,255,134,31,82,255,151,101,45,255,129,202,225,0,224,72,147,0,48,138,151,255,195,64,206,254,237,218,158,0,106,29,137,254,253,189,233,255,103,15,17,255,194,97,255,0,178,45,169,254,198,225,155,0,39,48,117,255,135,106,115,0,97,38,181,0,150,47,65,255,83,130,229,254,246,38,129,0,92,239,154,254,91,99,127,0,161,111,33,255,238,217,242,255,131,185,195,255,213,191,158,255,41,150,218,0,132,169,131,0,89,84,252,1,171,70,128,255,163,248,203,254,1,50,180,255,124,76,85,1,251,111,80,0,99,66,239,255,154,237,182,255,221,126,133,254,74,204,99,255,65,147,119,255,99,56,167,255,79,248,149,255,116,155,228,255,237,43,14,254,69,137,11,255,22,250,241,1,91,122,143,255,205,249,243,0,212,26,60,255,48,182,176,1,48,23,191,255,203,121,152,254,45,74,213,255,62,90,18,254,245,163,230,255,185,106,116,255,83,35,159,0,12,33,2,255,80,34,62,0,16,87,174,255,173,101,85,0,202,36,81,254,160,69,204,255,64,225,187,0,58,206,94,0,86,144,47,0,229,86,245,0,63,145,190,1,37,5,39,0,109,251,26,0,137,147,234,0,162,121,145,255,144,116,206,255,197,232,185,255,183,190,140,255,73,12,254,255,139,20,242,255,170,90,239,255,97,66,187,255,245,181,135,254,222,136,52,0,245,5,51,254,203,47,78,0,152,101,216,0,73,23,125,0,254,96,33,1,235,210,73,255,43,209,88,1,7,129,109,0,122,104,228,254,170,242,203,0,242,204,135,255,202,28,233,255,65,6,127,0,159,144,71,0,100,140,95,0,78,150,13,0,251,107,118,1,182,58,125,255,1,38,108,255,141,189,209,255,8,155,125,1,113,163,91,255,121,79,190,255,134,239,108,255,76,47,248,0,163,228,239,0,17,111,10,0,88,149,75,255,215,235,239,0,167,159,24,255,47,151,108,255,107,209,188,0,233,231,99,254,28,202,148,255,174,35,138,255,110,24,68,255,2,69,181,0,107,102,82,0,102,237,7,0,92,36,237,255,221,162,83,1,55,202,6,255,135,234,135,255,24,250,222,0,65,94,168,254,245,248,210,255,167,108,201,254,255,161,111,0,205,8,254,0,136,13,116,0,100,176,132,255,43,215,126,255,177,133,130,255,158,79,148,0,67,224,37,1,12,206,21,255,62,34,110,1,237,104,175,255,80,132,111,255,142,174,72,0,84,229,180,254,105,179,140,0,64,248,15,255,233,138,16,0,245,67,123,254,218,121,212,255,63,95,218,1,213,133,137,255,143,182,82,255,48,28,11,0,244,114,141,1,209,175,76,255,157,181,150,255,186,229,3,255,164,157,111,1,231,189,139,0,119,202,190,255,218,106,64,255,68,235,63,254,96,26,172,255,187,47,11,1,215,18,251,255,81,84,89,0,68,58,128,0,94,113,5,1,92,129,208,255,97,15,83,254,9,28,188,0,239,9,164,0,60,205,152,0,192,163,98,255,184,18,60,0,217,182,139,0,109,59,120,255,4,192,251,0,169,210,240,255,37,172,92,254,148,211,245,255,179,65,52,0,253,13,115,0,185,174,206,1,114,188,149,255,237,90,173,0,43,199,192,255,88,108,113,0,52,35,76,0,66,25,148,255,221,4,7,255,151,241,114,255,190,209,232,0,98,50,199,0,151,150,213,255,18,74,36,1,53,40,7,0,19,135,65,255,26,172,69,0,174,237,85,0,99,95,41,0,3,56,16,0,39,160,177,255,200,106,218,254,185,68,84,255,91,186,61,254,67,143,141,255,13,244,166,255,99,114,198,0,199,110,163,255,193,18,186,0,124,239,246,1,110,68,22,0,2,235,46,1,212,60,107,0,105,42,105,1,14,230,152,0,7,5,131,0,141,104,154,255,213,3,6,0,131,228,162,255,179,100,28,1,231,123,85,255,206,14,223,1,253,96,230,0,38,152,149,1,98,137,122,0,214,205,3,255,226,152,179,255,6,133,137,0,158,69,140,255,113,162,154,255,180,243,172,255,27,189,115,255,143,46,220,255,213,134,225,255,126,29,69,0,188,43,137,1,242,70,9,0,90,204,255,255,231,170,147,0,23,56,19,254,56,125,157,255,48,179,218,255,79,182,253,255,38,212,191,1,41,235,124,0,96,151,28,0,135,148,190,0,205,249,39,254,52,96,136,255,212,44,136,255,67,209,131,255,252,130,23,255,219,128,20,255,198,129,118,0,108,101,11,0,178,5,146,1,62,7,100,255,181,236,94,254,28,26,164,0,76,22,112,255,120,102,79,0,202,192,229,1,200,176,215,0,41,64,244,255,206,184,78,0,167,45,63,1,160,35,0,255,59,12,142,255,204,9,144,255,219,94,229,1,122,27,112,0,189,105,109,255,64,208,74,255,251,127,55,1,2,226,198,0,44,76,209,0,151,152,77,255,210,23,46,1,201,171,69,255,44,211,231,0,190,37,224,255,245,196,62,255,169,181,222,255,34,211,17,0,119,241,197,255,229,35,152,1,21,69,40,255,178,226,161,0,148,179,193,0,219,194,254,1,40,206,51,255,231,92,250,1,67,153,170,0,21,148,241,0,170,69,82,255,121,18,231,255,92,114,3,0,184,62,230,0,225,201,87,255,146,96,162,255,181,242,220,0,173,187,221,1,226,62,170,255,56,126,217,1,117,13,227,255,179,44,239,0,157,141,155,255,144,221,83,0,235,209,208,0,42,17,165,1,251,81,133,0,124,245,201,254,97,211,24,255,83,214,166,0,154,36,9,255,248,47,127,0,90,219,140,255,161,217,38,254,212,147,63,255,66,84,148,1,207,3,1,0,230,134,89,1,127,78,122,255,224,155,1,255,82,136,74,0,178,156,208,255,186,25,49,255,222,3,210,1,229,150,190,255,85,162,52,255,41,84,141,255,73,123,84,254,93,17,150,0,119,19,28,1,32,22,215,255,28,23,204,255,142,241,52,255,228,52,125,0,29,76,207,0,215,167,250,254,175,164,230,0,55,207,105,1,109,187,245,255,161,44,220,1,41,101,128,255,167,16,94,0,93,214,107,255,118,72,0,254,80,61,234,255,121,175,125,0,139,169,251,0,97,39,147,254,250,196,49,255,165,179,110,254,223,70,187,255,22,142,125,1,154,179,138,255,118,176,42,1,10,174,153,0,156,92,102,0,168,13,161,255,143,16,32,0,250,197,180,255,203,163,44,1,87,32,36,0,161,153,20,255,123,252,15,0,25,227,80,0,60,88,142,0,17,22,201,1,154,205,77,255,39,63,47,0,8,122,141,0,128,23,182,254,204,39,19,255,4,112,29,255,23,36,140,255,210,234,116,254,53,50,63,255,121,171,104,255,160,219,94,0,87,82,14,254,231,42,5,0,165,139,127,254,86,78,38,0,130,60,66,254,203,30,45,255,46,196,122,1,249,53,162,255,136,143,103,254,215,210,114,0,231,7,160,254,169,152,42,255,111,45,246,0,142,131,135,255,131,71,204,255,36,226,11,0,0,28,242,255,225,138,213,255,247,46,216,254,245,3,183,0,108,252,74,1,206,26,48,255,205,54,246,255,211,198,36,255,121,35,50,0,52,216,202,255,38,139,129,254,242,73,148,0,67,231,141,255,42,47,204,0,78,116,25,1,4,225,191,255,6,147,228,0,58,88,177,0,122,165,229,255,252,83,201,255,224,167,96,1,177,184,158,255,242,105,179,1,248,198,240,0,133,66,203,1,254,36,47,0,45,24,115,255,119,62,254,0,196,225,186,254,123,141,172,0,26,85,41,255,226,111,183,0,213,231,151,0,4,59,7,255,238,138,148,0,66,147,33,255,31,246,141,255,209,141,116,255,104,112,31,0,88,161,172,0,83,215,230,254,47,111,151,0,45,38,52,1,132,45,204,0,138,128,109,254,233,117,134,255,243,190,173,254,241,236,240,0,82,127,236,254,40,223,161,255,110,182,225,255,123,174,239,0,135,242,145,1,51,209,154,0,150,3,115,254,217,164,252,255,55,156,69,1,84,94,255,255,232,73,45,1,20,19,212,255,96,197,59,254,96,251,33,0,38,199,73,1,64,172,247,255,117,116,56,255,228,17,18,0,62,138,103,1,246,229,164,255,244,118,201,254,86,32,159,255,109,34,137,1,85,211,186,0,10,193,193,254,122,194,177,0,122,238,102,255,162,218,171,0,108,217,161,1,158,170,34,0,176,47,155,1,181,228,11,255,8,156,0,0,16,75,93,0,206,98,255,1,58,154,35,0,12,243,184,254,67,117,66,255,230,229,123,0,201,42,110,0,134,228,178,254,186,108,118,255,58,19,154,255,82,169,62,255,114,143,115,1,239,196,50,255,173,48,193,255,147,2,84,255,150,134,147,254,95,232,73,0,109,227,52,254,191,137,10,0,40,204,30,254,76,52,97,255,164,235,126,0,254,124,188,0,74,182,21,1,121,29,35,255,241,30,7,254,85,218,214,255,7,84,150,254,81,27,117,255,160,159,152,254,66,24,221,255,227,10,60,1,141,135,102,0,208,189,150,1,117,179,92,0,132,22,136,255,120,199,28,0,21,129,79,254,182,9,65,0,218,163,169,0,246,147,198,255,107,38,144,1,78,175,205,255,214,5,250,254,47,88,29,255,164,47,204,255,43,55,6,255,131,134,207,254,116,100,214,0,96,140,75,1,106,220,144,0,195,32,28,1,172,81,5,255,199,179,52,255,37,84,203,0,170,112,174,0,11,4,91,0,69,244,27,1,117,131,92,0,33,152,175,255,140,153,107,255,251,135,43,254,87,138,4,255,198,234,147,254,121,152,84,255,205,101,155,1,157,9,25,0,72,106,17,254,108,153,0,255],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+20480);allocate([189,229,186,0,193,8,176,255,174,149,209,0,238,130,29,0,233,214,126,1,61,226,102,0,57,163,4,1,198,111,51,255,45,79,78,1,115,210,10,255,218,9,25,255,158,139,198,255,211,82,187,254,80,133,83,0,157,129,230,1,243,133,134,255,40,136,16,0,77,107,79,255,183,85,92,1,177,204,202,0,163,71,147,255,152,69,190,0,172,51,188,1,250,210,172,255,211,242,113,1,89,89,26,255,64,66,111,254,116,152,42,0,161,39,27,255,54,80,254,0,106,209,115,1,103,124,97,0,221,230,98,255,31,231,6,0,178,192,120,254,15,217,203,255,124,158,79,0,112,145,247,0,92,250,48,1,163,181,193,255,37,47,142,254,144,189,165,255,46,146,240,0,6,75,128,0,41,157,200,254,87,121,213,0,1,113,236,0,5,45,250,0,144,12,82,0,31,108,231,0,225,239,119,255,167,7,189,255,187,228,132,255,110,189,34,0,94,44,204,1,162,52,197,0,78,188,241,254,57,20,141,0,244,146,47,1,206,100,51,0,125,107,148,254,27,195,77,0,152,253,90,1,7,143,144,255,51,37,31,0,34,119,38,255,7,197,118,0,153,188,211,0,151,20,116,254,245,65,52,255,180,253,110,1,47,177,209,0,161,99,17,255,118,222,202,0,125,179,252,1,123,54,126,255,145,57,191,0,55,186,121,0,10,243,138,0,205,211,229,255,125,156,241,254,148,156,185,255,227,19,188,255,124,41,32,255,31,34,206,254,17,57,83,0,204,22,37,255,42,96,98,0,119,102,184,1,3,190,28,0,110,82,218,255,200,204,192,255,201,145,118,0,117,204,146,0,132,32,98,1,192,194,121,0,106,161,248,1,237,88,124,0,23,212,26,0,205,171,90,255,248,48,216,1,141,37,230,255,124,203,0,254,158,168,30,255,214,248,21,0,112,187,7,255,75,133,239,255,74,227,243,255,250,147,70,0,214,120,162,0,167,9,179,255,22,158,18,0,218,77,209,1,97,109,81,255,244,33,179,255,57,52,57,255,65,172,210,255,249,71,209,255,142,169,238,0,158,189,153,255,174,254,103,254,98,33,14,0,141,76,230,255,113,139,52,255,15,58,212,0,168,215,201,255,248,204,215,1,223,68,160,255,57,154,183,254,47,231,121,0,106,166,137,0,81,136,138,0,165,43,51,0,231,139,61,0,57,95,59,254,118,98,25,255,151,63,236,1,94,190,250,255,169,185,114,1,5,250,58,255,75,105,97,1,215,223,134,0,113,99,163,1,128,62,112,0,99,106,147,0,163,195,10,0,33,205,182,0,214,14,174,255,129,38,231,255,53,182,223,0,98,42,159,255,247,13,40,0,188,210,177,1,6,21,0,255,255,61,148,254,137,45,129,255,89,26,116,254,126,38,114,0,251,50,242,254,121,134,128,255,204,249,167,254,165,235,215,0,202,177,243,0,133,141,62,0,240,130,190,1,110,175,255,0,0,20,146,1,37,210,121,255,7,39,130,0,142,250,84,255,141,200,207,0,9,95,104,255,11,244,174,0,134,232,126,0,167,1,123,254,16,193,149,255,232,233,239,1,213,70,112,255,252,116,160,254,242,222,220,255,205,85,227,0,7,185,58,0,118,247,63,1,116,77,177,255,62,245,200,254,63,18,37,255,107,53,232,254,50,221,211,0,162,219,7,254,2,94,43,0,182,62,182,254,160,78,200,255,135,140,170,0,235,184,228,0,175,53,138,254,80,58,77,255,152,201,2,1,63,196,34,0,5,30,184,0,171,176,154,0,121,59,206,0,38,99,39,0,172,80,77,254,0,134,151,0,186,33,241,254,94,253,223,255,44,114,252,0,108,126,57,255,201,40,13,255,39,229,27,255,39,239,23,1,151,121,51,255,153,150,248,0,10,234,174,255,118,246,4,254,200,245,38,0,69,161,242,1,16,178,150,0,113,56,130,0,171,31,105,0,26,88,108,255,49,42,106,0,251,169,66,0,69,93,149,0,20,57,254,0,164,25,111,0,90,188,90,255,204,4,197,0,40,213,50,1,212,96,132,255,88,138,180,254,228,146,124,255,184,246,247,0,65,117,86,255,253,102,210,254,254,121,36,0,137,115,3,255,60,24,216,0,134,18,29,0,59,226,97,0,176,142,71,0,7,209,161,0,189,84,51,254,155,250,72,0,213,84,235,255,45,222,224,0,238,148,143,255,170,42,53,255,78,167,117,0,186,0,40,255,125,177,103,255,69,225,66,0,227,7,88,1,75,172,6,0,169,45,227,1,16,36,70,255,50,2,9,255,139,193,22,0,143,183,231,254,218,69,50,0,236,56,161,1,213,131,42,0,138,145,44,254,136,229,40,255,49,63,35,255,61,145,245,255,101,192,2,254,232,167,113,0,152,104,38,1,121,185,218,0,121,139,211,254,119,240,35,0,65,189,217,254,187,179,162,255,160,187,230,0,62,248,14,255,60,78,97,0,255,247,163,255,225,59,91,255,107,71,58,255,241,47,33,1,50,117,236,0,219,177,63,254,244,90,179,0,35,194,215,255,189,67,50,255,23,135,129,0,104,189,37,255,185,57,194,0,35,62,231,255,220,248,108,0,12,231,178,0,143,80,91,1,131,93,101,255,144,39,2,1,255,250,178,0,5,17,236,254,139,32,46,0,204,188,38,254,245,115,52,255,191,113,73,254,191,108,69,255,22,69,245,1,23,203,178,0,170,99,170,0,65,248,111,0,37,108,153,255,64,37,69,0,0,88,62,254,89,148,144,255,191,68,224,1,241,39,53,0,41,203,237,255,145,126,194,255,221,42,253,255,25,99,151,0,97,253,223,1,74,115,49,255,6,175,72,255,59,176,203,0,124,183,249,1,228,228,99,0,129,12,207,254,168,192,195,255,204,176,16,254,152,234,171,0,77,37,85,255,33,120,135,255,142,194,227,1,31,214,58,0,213,187,125,255,232,46,60,255,190,116,42,254,151,178,19,255,51,62,237,254,204,236,193,0,194,232,60,0,172,34,157,255,189,16,184,254,103,3,95,255,141,233,36,254,41,25,11,255,21,195,166,0,118,245,45,0,67,213,149,255,159,12,18,255,187,164,227,1,160,25,5,0,12,78,195,1,43,197,225,0,48,142,41,254,196,155,60,255,223,199,18,1,145,136,156,0,252,117,169,254,145,226,238,0,239,23,107,0,109,181,188,255,230,112,49,254,73,170,237,255,231,183,227,255,80,220,20,0,194,107,127,1,127,205,101,0,46,52,197,1,210,171,36,255,88,3,90,255,56,151,141,0,96,187,255,255,42,78,200,0,254,70,70,1,244,125,168,0,204,68,138,1,124,215,70,0,102,66,200,254,17,52,228,0,117,220,143,254,203,248,123,0,56,18,174,255,186,151,164,255,51,232,208,1,160,228,43,255,249,29,25,1,68,190,63,0,103,230,9,106,133,174,103,187,114,243,110,60,58,245,79,165,127,82,14,81,140,104,5,155,171,217,131,31,25,205,224,91,99,117,114,118,101,50,53,53,49,57,120,115,97,108,115,97,50,48,112,111,108,121,49,51,48,53,0,98,108,97,107,101,50,98,0,83,45,62,98,117,102,108,101,110,32,60,61,32,66,76,65,75,69,50,66,95,66,76,79,67,75,66,89,84,69,83,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,47,98,108,97,107,101,50,47,114,101,102,47,98,108,97,107,101,50,98,45,114,101,102,46,99,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,95,95,102,105,110,97,108,0,111,117,116,108,101,110,32,60,61,32,85,73,78,84,56,95,77,65,88,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,47,98,108,97,107,101,50,47,114,101,102,47,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,46,99,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,0,107,101,121,108,101,110,32,60,61,32,85,73,78,84,56,95,77,65,88,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,95,115,97,108,116,95,112,101,114,115,111,110,97,108,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,95,105,110,105,116,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,95,105,110,105,116,95,115,97,108,116,95,112,101,114,115,111,110,97,108,0,99,114,121,112,116,111,95,103,101,110,101,114,105,99,104,97,115,104,95,98,108,97,107,101,50,98,95,102,105,110,97,108,0,115,104,97,53,49,50,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,111,108,121,49,51,48,53,0,36,97,114,103,111,110,50,105,0,36,118,61,0,36,109,61,0,44,116,61,0,44,112,61,0,44,100,97,116,97,61,0,36,97,114,103,111,110,50,105,36,118,61,0,36,97,114,103,111,110,50,105,36,0,97,114,103,111,110,50,105,0,46,47,48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,0,36,55,36,0,99,117,114,118,101,50,53,53,49,57,0,120,115,97,108,115,97,50,48,112,111,108,121,49,51,48,53,0,115,105,112,104,97,115,104,50,52,0,101,100,50,53,53,49,57,0,237,211,245,92,26,99,18,88,214,156,247,162,222,249,222,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,120,115,97,108,115,97,50,48,0,106,115,0,123,32,114,101,116,117,114,110,32,77,111,100,117,108,101,46,103,101,116,82,97,110,100,111,109,86,97,108,117,101,40,41,59,32,125,0,123,32,105,102,32,40,77,111,100,117,108,101,46,103,101,116,82,97,110,100,111,109,86,97,108,117,101,32,61,61,61,32,117,110,100,101,102,105,110,101,100,41,32,123,32,116,114,121,32,123,32,118,97,114,32,119,105,110,100,111,119,95,32,61,32,34,111,98,106,101,99,116,34,32,61,61,61,32,116,121,112,101,111,102,32,119,105,110,100,111,119,32,63,32,119,105,110,100,111,119,32,58,32,115,101,108,102,44,32,99,114,121,112,116,111,95,32,61,32,116,121,112,101,111,102,32,119,105,110,100,111,119,95,46,99,114,121,112,116,111,32,33,61,61,32,34,117,110,100,101,102,105,110,101,100,34,32,63,32,119,105,110,100,111,119,95,46,99,114,121,112,116,111,32,58,32,119,105,110,100,111,119,95,46,109,115,67,114,121,112,116,111,44,32,114,97,110,100,111,109,86,97,108,117,101,115,83,116,97,110,100,97,114,100,32,61,32,102,117,110,99,116,105,111,110,40,41,32,123,32,118,97,114,32,98,117,102,32,61,32,110,101,119,32,85,105,110,116,51,50,65,114,114,97,121,40,49,41,59,32,99,114,121,112,116,111,95,46,103,101,116,82,97,110,100,111,109,86,97,108,117,101,115,40,98,117,102,41,59,32,114,101,116,117,114,110,32,98,117,102,91,48,93,32,62,62,62,32,48,59,32,125,59,32,114,97,110,100,111,109,86,97,108,117,101,115,83,116,97,110,100,97,114,100,40,41,59,32,77,111,100,117,108,101,46,103,101,116,82,97,110,100,111,109,86,97,108,117,101,32,61,32,114,97,110,100,111,109,86,97,108,117,101,115,83,116,97,110,100,97,114,100,59,32,125,32,99,97,116,99,104,32,40,101,41,32,123,32,116,114,121,32,123,32,118,97,114,32,99,114,121,112,116,111,32,61,32,114,101,113,117,105,114,101,40,39,99,114,121,112,116,111,39,41,44,32,114,97,110,100,111,109,86,97,108,117,101,78,111,100,101,74,83,32,61,32,102,117,110,99,116,105,111,110,40,41,32,123,32,118,97,114,32,98,117,102,32,61,32,99,114,121,112,116,111,46,114,97,110,100,111,109,66,121,116,101,115,40,52,41,59,32,114,101,116,117,114,110,32,40,98,117,102,91,48,93,32,60,60,32,50,52,32,124,32,98,117,102,91,49,93,32,60,60,32,49,54,32,124,32,98,117,102,91,50,93,32,60,60,32,56,32,124,32,98,117,102,91,51,93,41,32,62,62,62,32,48,59,32,125,59,32,114,97,110,100,111,109,86,97,108,117,101,78,111,100,101,74,83,40,41,59,32,77,111,100,117,108,101,46,103,101,116,82,97,110,100,111,109,86,97,108,117,101,32,61,32,114,97,110,100,111,109,86,97,108,117,101,78,111,100,101,74,83,59,32,125,32,99,97,116,99,104,32,40,101,41,32,123,32,116,104,114,111,119,32,39,78,111,32,115,101,99,117,114,101,32,114,97,110,100,111,109,32,110,117,109,98,101,114,32,103,101,110,101,114,97,116,111,114,32,102,111,117,110,100,39,59,32,125,32,125,32,125,32,125,0,98,117,102,95,108,101,110,32,60,61,32,83,73,90,69,95,77,65,88,0,114,97,110,100,111,109,98,121,116,101,115,47,114,97,110,100,111,109,98,121,116,101,115,46,99,0,114,97,110,100,111,109,98,121,116,101,115,0,49,46,48,46,49,49,0],"i8",ALLOC_NONE,Runtime.GLOBAL_BASE+30720);var tempDoublePtr=STATICTOP;STATICTOP+=16;Module["_bitshift64Ashr"]=_bitshift64Ashr;Module["_i64Subtract"]=_i64Subtract;Module["_i64Add"]=_i64Add;Module["_memset"]=_memset;Module["_bitshift64Lshr"]=_bitshift64Lshr;Module["_bitshift64Shl"]=_bitshift64Shl;function _abort(){Module["abort"]()}function ___assert_fail(condition,filename,line,func){ABORT=true;throw"Assertion failed: "+Pointer_stringify(condition)+", at: "+[filename?Pointer_stringify(filename):"unknown filename",line,func?Pointer_stringify(func):"unknown function"]+" at "+stackTrace()}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest);return dest}Module["_memcpy"]=_memcpy;var cttz_i8=allocate([8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0],"i8",ALLOC_STATIC);Module["_llvm_cttz_i32"]=_llvm_cttz_i32;Module["___udivmoddi4"]=___udivmoddi4;Module["___udivdi3"]=___udivdi3;Module["___muldsi3"]=___muldsi3;Module["___muldi3"]=___muldi3;function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function _sysconf(name){switch(name){case 30:return PAGE_SIZE;case 85:return totalMemory/PAGE_SIZE;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:return 200809;case 79:return 0;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}___setErrNo(ERRNO_CODES.EINVAL);return-1}Module["_sbrk"]=_sbrk;Module["_memmove"]=_memmove;Module["___uremdi3"]=___uremdi3;DYNAMICTOP_PTR=allocate(1,"i32",ALLOC_STATIC);STACK_BASE=STACKTOP=Runtime.alignMemory(STATICTOP);STACK_MAX=STACK_BASE+TOTAL_STACK;DYNAMIC_BASE=Runtime.alignMemory(STACK_MAX);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;staticSealed=true;Module.asmGlobalArg={"Math":Math,"Int8Array":Int8Array,"Int16Array":Int16Array,"Int32Array":Int32Array,"Uint8Array":Uint8Array,"Uint16Array":Uint16Array,"Uint32Array":Uint32Array,"Float32Array":Float32Array,"Float64Array":Float64Array,"NaN":NaN,"Infinity":Infinity};Module.asmLibraryArg={"abort":abort,"assert":assert,"enlargeMemory":enlargeMemory,"getTotalMemory":getTotalMemory,"abortOnCannotGrowMemory":abortOnCannotGrowMemory,"_emscripten_asm_const_i":_emscripten_asm_const_i,"_sysconf":_sysconf,"_abort":_abort,"___setErrNo":___setErrNo,"_emscripten_memcpy_big":_emscripten_memcpy_big,"_emscripten_asm_const_v":_emscripten_asm_const_v,"___assert_fail":___assert_fail,"STACKTOP":STACKTOP,"STACK_MAX":STACK_MAX,"DYNAMICTOP_PTR":DYNAMICTOP_PTR,"tempDoublePtr":tempDoublePtr,"ABORT":ABORT,"cttz_i8":cttz_i8};// EMSCRIPTEN_START_ASM -var asm=(function(global,env,buffer) { -"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.DYNAMICTOP_PTR|0;var l=env.tempDoublePtr|0;var m=env.ABORT|0;var n=env.cttz_i8|0;var o=0;var p=0;var q=0;var r=0;var s=global.NaN,t=global.Infinity;var u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0;var D=0;var E=global.Math.floor;var F=global.Math.abs;var G=global.Math.sqrt;var H=global.Math.pow;var I=global.Math.cos;var J=global.Math.sin;var K=global.Math.tan;var L=global.Math.acos;var M=global.Math.asin;var N=global.Math.atan;var O=global.Math.atan2;var P=global.Math.exp;var Q=global.Math.log;var R=global.Math.ceil;var S=global.Math.imul;var T=global.Math.min;var U=global.Math.max;var V=global.Math.clz32;var W=env.abort;var X=env.assert;var Y=env.enlargeMemory;var Z=env.getTotalMemory;var _=env.abortOnCannotGrowMemory;var $=env._emscripten_asm_const_i;var aa=env._sysconf;var ba=env._abort;var ca=env.___setErrNo;var da=env._emscripten_memcpy_big;var ea=env._emscripten_asm_const_v;var fa=env.___assert_fail;var ga=0; -// EMSCRIPTEN_START_FUNCS -function ha(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0;g=i;h=i=i+63&-64;i=i+720|0;e=0;do{k=b+(e<<3)|0;p=d[k+7>>0]|0;q=Pd(d[k+6>>0]|0|0,0,8)|0;j=D;o=Pd(d[k+5>>0]|0|0,0,16)|0;j=j|D;n=Pd(d[k+4>>0]|0|0,0,24)|0;j=j|D|(d[k+3>>0]|0);m=Pd(d[k+2>>0]|0|0,0,40)|0;j=j|D;l=Pd(d[k+1>>0]|0|0,0,48)|0;j=j|D;k=Pd(d[k>>0]|0|0,0,56)|0;f=h+80+(e<<3)|0;c[f>>2]=q|p|o|n|m|l|k;c[f+4>>2]=j|D;e=e+1|0}while((e|0)!=16);e=16;b=c[h+80>>2]|0;f=c[h+80+4>>2]|0;do{s=h+80+(e+-2<<3)|0;w=c[s>>2]|0;s=c[s+4>>2]|0;r=Rd(w|0,s|0,19)|0;k=D;j=Pd(w|0,s|0,45)|0;k=k|D;u=Rd(w|0,s|0,61)|0;v=D;t=Pd(w|0,s|0,3)|0;v=v|D;s=Rd(w|0,s|0,6)|0;k=v^D^k;v=h+80+(e+-7<<3)|0;w=c[v>>2]|0;v=c[v+4>>2]|0;o=h+80+(e+-15<<3)|0;y=b;b=c[o>>2]|0;x=f;f=c[o+4>>2]|0;o=Rd(b|0,f|0,1)|0;p=D;q=Pd(b|0,f|0,63)|0;p=p|D;l=Rd(b|0,f|0,8)|0;z=D;m=Pd(b|0,f|0,56)|0;z=z|D;n=Rd(b|0,f|0,7)|0;p=z^D^p;v=oe(y|0,x|0,w|0,v|0)|0;k=oe(v|0,D|0,(u|t)^s^(r|j)|0,k|0)|0;p=oe(k|0,D|0,(l|m)^n^(o|q)|0,p|0)|0;q=h+80+(e<<3)|0;c[q>>2]=p;c[q+4>>2]=D;e=e+1|0}while((e|0)!=80);e=h+16|0;b=a;f=e+64|0;do{c[e>>2]=c[b>>2];e=e+4|0;b=b+4|0}while((e|0)<(f|0));G=h+16+56|0;x=c[G>>2]|0;E=c[G+4>>2]|0;w=h+16+32|0;I=c[w>>2]|0;H=c[w+4>>2]|0;e=Rd(I|0,H|0,14)|0;z=D;F=Pd(I|0,H|0,50)|0;z=z|D;l=Rd(I|0,H|0,18)|0;A=D;L=Pd(I|0,H|0,46)|0;A=z^(A|D);z=Rd(I|0,H|0,41)|0;J=D;K=Pd(I|0,H|0,23)|0;J=A^(J|D);A=h+16+40|0;M=c[A>>2]|0;f=c[A+4>>2]|0;k=h+16+48|0;p=c[k>>2]|0;j=c[k+4>>2]|0;r=c[h+80>>2]|0;y=c[h+80+4>>2]|0;E=oe(x|0,E|0,-685199838,1116352408)|0;y=oe(E|0,D|0,r|0,y|0)|0;J=oe(y|0,D|0,(e|F)^(l|L)^(z|K)|0,J|0)|0;J=oe(J|0,D|0,(p^M)&I^p|0,(j^f)&H^j|0)|0;K=D;z=c[h+16>>2]|0;L=c[h+16+4>>2]|0;l=Rd(z|0,L|0,28)|0;F=D;e=Pd(z|0,L|0,36)|0;F=F|D;y=Rd(z|0,L|0,34)|0;r=D;E=Pd(z|0,L|0,30)|0;r=F^(r|D);F=Rd(z|0,L|0,39)|0;x=D;m=Pd(z|0,L|0,25)|0;C=h+16+8|0;o=c[C>>2]|0;q=c[C+4>>2]|0;B=h+16+16|0;b=c[B>>2]|0;s=c[B+4>>2]|0;x=oe((b|o)&z|b&o|0,(s|q)&L|s&q|0,(l|e)^(y|E)^(F|m)|0,r^(x|D)|0)|0;r=D;m=h+16+24|0;F=oe(c[m>>2]|0,c[m+4>>2]|0,J|0,K|0)|0;E=D;c[m>>2]=F;c[m+4>>2]=E;K=oe(x|0,r|0,J|0,K|0)|0;J=D;c[G>>2]=K;c[G+4>>2]=J;r=Rd(F|0,E|0,14)|0;x=D;y=Pd(F|0,E|0,50)|0;x=x|D;e=Rd(F|0,E|0,18)|0;l=D;u=Pd(F|0,E|0,46)|0;l=x^(l|D);x=Rd(F|0,E|0,41)|0;t=D;v=Pd(F|0,E|0,23)|0;t=l^(t|D);l=c[h+80+8>>2]|0;n=c[h+80+8+4>>2]|0;j=oe(p|0,j|0,602891725,1899447441)|0;t=oe(j|0,D|0,(r|y)^(e|u)^(x|v)|0,t|0)|0;n=oe(t|0,D|0,l|0,n|0)|0;H=oe(n|0,D|0,(M^I)&F^M|0,(f^H)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;u=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;e=oe((o|z)&K|o&z|0,(q|L)&J|q&L|0,(n|t)^(v|u)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[B>>2]=s;c[B+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[k>>2]=I;c[k+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;y=Pd(s|0,b|0,50)|0;e=e|D;l=Rd(s|0,b|0,18)|0;u=D;v=Pd(s|0,b|0,46)|0;u=e^(u|D);e=Rd(s|0,b|0,41)|0;t=D;n=Pd(s|0,b|0,23)|0;t=u^(t|D);u=c[w>>2]|0;r=c[w+4>>2]|0;j=c[h+80+16>>2]|0;p=c[h+80+16+4>>2]|0;f=oe(M|0,f|0,-330482897,-1245643825)|0;t=oe(f|0,D|0,(x|y)^(l|v)^(e|n)|0,t|0)|0;p=oe(t|0,D|0,j|0,p|0)|0;p=oe(p|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;j=D;t=Rd(I|0,H|0,28)|0;n=D;e=Pd(I|0,H|0,36)|0;n=n|D;v=Rd(I|0,H|0,34)|0;l=D;y=Pd(I|0,H|0,30)|0;l=n^(l|D);n=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;x=oe((z|K)&I|z&K|0,(L|J)&H|L&J|0,(t|e)^(v|y)^(n|f)|0,l^(x|D)|0)|0;l=D;q=oe(o|0,q|0,p|0,j|0)|0;o=D;c[C>>2]=q;c[C+4>>2]=o;j=oe(x|0,l|0,p|0,j|0)|0;p=D;c[A>>2]=j;c[A+4>>2]=p;l=Rd(q|0,o|0,14)|0;x=D;f=Pd(q|0,o|0,50)|0;x=x|D;n=Rd(q|0,o|0,18)|0;y=D;v=Pd(q|0,o|0,46)|0;y=x^(y|D);x=Rd(q|0,o|0,41)|0;e=D;t=Pd(q|0,o|0,23)|0;e=y^(e|D);y=c[h+80+24>>2]|0;J=c[h+80+24+4>>2]|0;r=oe(u|0,r|0,-2121671748,-373957723)|0;e=oe(r|0,D|0,(l|f)^(n|v)^(x|t)|0,e|0)|0;J=oe(e|0,D|0,y|0,J|0)|0;J=oe(J|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;y=D;e=Rd(j|0,p|0,28)|0;t=D;x=Pd(j|0,p|0,36)|0;t=t|D;v=Rd(j|0,p|0,34)|0;n=D;f=Pd(j|0,p|0,30)|0;n=t^(n|D);t=Rd(j|0,p|0,39)|0;l=D;r=Pd(j|0,p|0,25)|0;u=c[G>>2]|0;K=c[G+4>>2]|0;l=oe((u|I)&j|u&I|0,(K|H)&p|K&H|0,(e|x)^(v|f)^(t|r)|0,n^(l|D)|0)|0;n=D;L=oe(z|0,L|0,J|0,y|0)|0;z=D;c[h+16>>2]=L;c[h+16+4>>2]=z;y=oe(l|0,n|0,J|0,y|0)|0;J=D;c[w>>2]=y;c[w+4>>2]=J;n=Rd(L|0,z|0,14)|0;l=D;r=Pd(L|0,z|0,50)|0;l=l|D;t=Rd(L|0,z|0,18)|0;f=D;v=Pd(L|0,z|0,46)|0;f=l^(f|D);l=Rd(L|0,z|0,41)|0;x=D;e=Pd(L|0,z|0,23)|0;x=f^(x|D);f=c[h+80+32>>2]|0;H=c[h+80+32+4>>2]|0;E=oe(F|0,E|0,-213338824,961987163)|0;x=oe(E|0,D|0,(n|r)^(t|v)^(l|e)|0,x|0)|0;H=oe(x|0,D|0,f|0,H|0)|0;H=oe(H|0,D|0,(s^q)&L^s|0,(b^o)&z^b|0)|0;f=D;x=Rd(y|0,J|0,28)|0;e=D;l=Pd(y|0,J|0,36)|0;e=e|D;v=Rd(y|0,J|0,34)|0;t=D;r=Pd(y|0,J|0,30)|0;t=e^(t|D);e=Rd(y|0,J|0,39)|0;n=D;E=Pd(y|0,J|0,25)|0;F=c[k>>2]|0;I=c[k+4>>2]|0;n=oe((F|j)&y|F&j|0,(I|p)&J|I&p|0,(x|l)^(v|r)^(e|E)|0,t^(n|D)|0)|0;t=D;K=oe(u|0,K|0,H|0,f|0)|0;u=D;c[G>>2]=K;c[G+4>>2]=u;f=oe(n|0,t|0,H|0,f|0)|0;H=D;c[m>>2]=f;c[m+4>>2]=H;t=Rd(K|0,u|0,14)|0;n=D;E=Pd(K|0,u|0,50)|0;n=n|D;e=Rd(K|0,u|0,18)|0;r=D;v=Pd(K|0,u|0,46)|0;r=n^(r|D);n=Rd(K|0,u|0,41)|0;l=D;x=Pd(K|0,u|0,23)|0;l=r^(l|D);r=c[h+80+40>>2]|0;p=c[h+80+40+4>>2]|0;b=oe(s|0,b|0,-1241133031,1508970993)|0;l=oe(b|0,D|0,(t|E)^(e|v)^(n|x)|0,l|0)|0;p=oe(l|0,D|0,r|0,p|0)|0;p=oe(p|0,D|0,(q^L)&K^q|0,(o^z)&u^o|0)|0;r=D;l=Rd(f|0,H|0,28)|0;x=D;n=Pd(f|0,H|0,36)|0;x=x|D;v=Rd(f|0,H|0,34)|0;e=D;E=Pd(f|0,H|0,30)|0;e=x^(e|D);x=Rd(f|0,H|0,39)|0;t=D;b=Pd(f|0,H|0,25)|0;s=c[A>>2]|0;j=c[A+4>>2]|0;t=oe((s|y)&f|s&y|0,(j|J)&H|j&J|0,(l|n)^(v|E)^(x|b)|0,e^(t|D)|0)|0;e=D;I=oe(F|0,I|0,p|0,r|0)|0;F=D;c[k>>2]=I;c[k+4>>2]=F;r=oe(t|0,e|0,p|0,r|0)|0;p=D;c[B>>2]=r;c[B+4>>2]=p;e=Rd(I|0,F|0,14)|0;t=D;b=Pd(I|0,F|0,50)|0;t=t|D;x=Rd(I|0,F|0,18)|0;E=D;v=Pd(I|0,F|0,46)|0;E=t^(E|D);t=Rd(I|0,F|0,41)|0;n=D;l=Pd(I|0,F|0,23)|0;n=E^(n|D);E=c[h+80+48>>2]|0;J=c[h+80+48+4>>2]|0;o=oe(q|0,o|0,-1357295717,-1841331548)|0;n=oe(o|0,D|0,(e|b)^(x|v)^(t|l)|0,n|0)|0;J=oe(n|0,D|0,E|0,J|0)|0;J=oe(J|0,D|0,(L^K)&I^L|0,(z^u)&F^z|0)|0;E=D;n=Rd(r|0,p|0,28)|0;l=D;t=Pd(r|0,p|0,36)|0;l=l|D;v=Rd(r|0,p|0,34)|0;x=D;b=Pd(r|0,p|0,30)|0;x=l^(x|D);l=Rd(r|0,p|0,39)|0;e=D;o=Pd(r|0,p|0,25)|0;q=c[w>>2]|0;y=c[w+4>>2]|0;e=oe((q|f)&r|q&f|0,(y|H)&p|y&H|0,(n|t)^(v|b)^(l|o)|0,x^(e|D)|0)|0;x=D;j=oe(s|0,j|0,J|0,E|0)|0;s=D;c[A>>2]=j;c[A+4>>2]=s;E=oe(e|0,x|0,J|0,E|0)|0;J=D;c[C>>2]=E;c[C+4>>2]=J;x=Rd(j|0,s|0,14)|0;e=D;o=Pd(j|0,s|0,50)|0;e=e|D;l=Rd(j|0,s|0,18)|0;b=D;v=Pd(j|0,s|0,46)|0;b=e^(b|D);e=Rd(j|0,s|0,41)|0;t=D;n=Pd(j|0,s|0,23)|0;t=b^(t|D);b=c[h+80+56>>2]|0;H=c[h+80+56+4>>2]|0;z=oe(L|0,z|0,-630357736,-1424204075)|0;t=oe(z|0,D|0,(x|o)^(l|v)^(e|n)|0,t|0)|0;H=oe(t|0,D|0,b|0,H|0)|0;H=oe(H|0,D|0,(K^I)&j^K|0,(u^F)&s^u|0)|0;b=D;t=Rd(E|0,J|0,28)|0;n=D;e=Pd(E|0,J|0,36)|0;n=n|D;v=Rd(E|0,J|0,34)|0;l=D;o=Pd(E|0,J|0,30)|0;l=n^(l|D);n=Rd(E|0,J|0,39)|0;x=D;z=Pd(E|0,J|0,25)|0;L=c[m>>2]|0;f=c[m+4>>2]|0;x=oe((L|r)&E|L&r|0,(f|p)&J|f&p|0,(t|e)^(v|o)^(n|z)|0,l^(x|D)|0)|0;l=D;y=oe(q|0,y|0,H|0,b|0)|0;q=D;c[w>>2]=y;c[w+4>>2]=q;b=oe(x|0,l|0,H|0,b|0)|0;H=D;c[h+16>>2]=b;c[h+16+4>>2]=H;l=Rd(y|0,q|0,14)|0;x=D;z=Pd(y|0,q|0,50)|0;x=x|D;n=Rd(y|0,q|0,18)|0;o=D;v=Pd(y|0,q|0,46)|0;o=x^(o|D);x=Rd(y|0,q|0,41)|0;e=D;t=Pd(y|0,q|0,23)|0;e=o^(e|D);o=c[h+80+64>>2]|0;p=c[h+80+64+4>>2]|0;u=oe(K|0,u|0,-1560083902,-670586216)|0;e=oe(u|0,D|0,(l|z)^(n|v)^(x|t)|0,e|0)|0;p=oe(e|0,D|0,o|0,p|0)|0;p=oe(p|0,D|0,(I^j)&y^I|0,(F^s)&q^F|0)|0;o=D;e=Rd(b|0,H|0,28)|0;t=D;x=Pd(b|0,H|0,36)|0;t=t|D;v=Rd(b|0,H|0,34)|0;n=D;z=Pd(b|0,H|0,30)|0;n=t^(n|D);t=Rd(b|0,H|0,39)|0;l=D;u=Pd(b|0,H|0,25)|0;K=c[B>>2]|0;r=c[B+4>>2]|0;l=oe((K|E)&b|K&E|0,(r|J)&H|r&J|0,(e|x)^(v|z)^(t|u)|0,n^(l|D)|0)|0;n=D;f=oe(L|0,f|0,p|0,o|0)|0;L=D;c[m>>2]=f;c[m+4>>2]=L;o=oe(l|0,n|0,p|0,o|0)|0;p=D;c[G>>2]=o;c[G+4>>2]=p;n=Rd(f|0,L|0,14)|0;l=D;u=Pd(f|0,L|0,50)|0;l=l|D;t=Rd(f|0,L|0,18)|0;z=D;v=Pd(f|0,L|0,46)|0;z=l^(z|D);l=Rd(f|0,L|0,41)|0;x=D;e=Pd(f|0,L|0,23)|0;x=z^(x|D);z=c[h+80+72>>2]|0;J=c[h+80+72+4>>2]|0;F=oe(I|0,F|0,1164996542,310598401)|0;x=oe(F|0,D|0,(n|u)^(t|v)^(l|e)|0,x|0)|0;J=oe(x|0,D|0,z|0,J|0)|0;J=oe(J|0,D|0,(j^y)&f^j|0,(s^q)&L^s|0)|0;z=D;x=Rd(o|0,p|0,28)|0;e=D;l=Pd(o|0,p|0,36)|0;e=e|D;v=Rd(o|0,p|0,34)|0;t=D;u=Pd(o|0,p|0,30)|0;t=e^(t|D);e=Rd(o|0,p|0,39)|0;n=D;F=Pd(o|0,p|0,25)|0;I=c[C>>2]|0;E=c[C+4>>2]|0;n=oe((I|b)&o|I&b|0,(E|H)&p|E&H|0,(x|l)^(v|u)^(e|F)|0,t^(n|D)|0)|0;t=D;r=oe(K|0,r|0,J|0,z|0)|0;K=D;c[B>>2]=r;c[B+4>>2]=K;z=oe(n|0,t|0,J|0,z|0)|0;J=D;c[k>>2]=z;c[k+4>>2]=J;t=Rd(r|0,K|0,14)|0;n=D;F=Pd(r|0,K|0,50)|0;n=n|D;e=Rd(r|0,K|0,18)|0;u=D;v=Pd(r|0,K|0,46)|0;u=n^(u|D);n=Rd(r|0,K|0,41)|0;l=D;x=Pd(r|0,K|0,23)|0;l=u^(l|D);u=c[h+80+80>>2]|0;H=c[h+80+80+4>>2]|0;s=oe(j|0,s|0,1323610764,607225278)|0;l=oe(s|0,D|0,(t|F)^(e|v)^(n|x)|0,l|0)|0;H=oe(l|0,D|0,u|0,H|0)|0;H=oe(H|0,D|0,(y^f)&r^y|0,(q^L)&K^q|0)|0;u=D;l=Rd(z|0,J|0,28)|0;x=D;n=Pd(z|0,J|0,36)|0;x=x|D;v=Rd(z|0,J|0,34)|0;e=D;F=Pd(z|0,J|0,30)|0;e=x^(e|D);x=Rd(z|0,J|0,39)|0;t=D;s=Pd(z|0,J|0,25)|0;j=c[h+16>>2]|0;b=c[h+16+4>>2]|0;t=oe((j|o)&z|j&o|0,(b|p)&J|b&p|0,(l|n)^(v|F)^(x|s)|0,e^(t|D)|0)|0;e=D;E=oe(I|0,E|0,H|0,u|0)|0;I=D;c[C>>2]=E;c[C+4>>2]=I;u=oe(t|0,e|0,H|0,u|0)|0;H=D;c[A>>2]=u;c[A+4>>2]=H;e=Rd(E|0,I|0,14)|0;t=D;s=Pd(E|0,I|0,50)|0;t=t|D;x=Rd(E|0,I|0,18)|0;F=D;v=Pd(E|0,I|0,46)|0;F=t^(F|D);t=Rd(E|0,I|0,41)|0;n=D;l=Pd(E|0,I|0,23)|0;n=F^(n|D);F=c[h+80+88>>2]|0;p=c[h+80+88+4>>2]|0;q=oe(y|0,q|0,-704662302,1426881987)|0;n=oe(q|0,D|0,(e|s)^(x|v)^(t|l)|0,n|0)|0;p=oe(n|0,D|0,F|0,p|0)|0;p=oe(p|0,D|0,(f^r)&E^f|0,(L^K)&I^L|0)|0;F=D;n=Rd(u|0,H|0,28)|0;l=D;t=Pd(u|0,H|0,36)|0;l=l|D;v=Rd(u|0,H|0,34)|0;x=D;s=Pd(u|0,H|0,30)|0;x=l^(x|D);l=Rd(u|0,H|0,39)|0;e=D;q=Pd(u|0,H|0,25)|0;y=c[G>>2]|0;o=c[G+4>>2]|0;e=oe((y|z)&u|y&z|0,(o|J)&H|o&J|0,(n|t)^(v|s)^(l|q)|0,x^(e|D)|0)|0;x=D;b=oe(j|0,b|0,p|0,F|0)|0;j=D;c[h+16>>2]=b;c[h+16+4>>2]=j;F=oe(e|0,x|0,p|0,F|0)|0;p=D;c[w>>2]=F;c[w+4>>2]=p;x=Rd(b|0,j|0,14)|0;e=D;q=Pd(b|0,j|0,50)|0;e=e|D;l=Rd(b|0,j|0,18)|0;s=D;v=Pd(b|0,j|0,46)|0;s=e^(s|D);e=Rd(b|0,j|0,41)|0;t=D;n=Pd(b|0,j|0,23)|0;t=s^(t|D);s=c[h+80+96>>2]|0;J=c[h+80+96+4>>2]|0;L=oe(f|0,L|0,-226784913,1925078388)|0;t=oe(L|0,D|0,(x|q)^(l|v)^(e|n)|0,t|0)|0;J=oe(t|0,D|0,s|0,J|0)|0;J=oe(J|0,D|0,(r^E)&b^r|0,(K^I)&j^K|0)|0;s=D;t=Rd(F|0,p|0,28)|0;n=D;e=Pd(F|0,p|0,36)|0;n=n|D;v=Rd(F|0,p|0,34)|0;l=D;q=Pd(F|0,p|0,30)|0;l=n^(l|D);n=Rd(F|0,p|0,39)|0;x=D;L=Pd(F|0,p|0,25)|0;f=c[k>>2]|0;z=c[k+4>>2]|0;x=oe((f|u)&F|f&u|0,(z|H)&p|z&H|0,(t|e)^(v|q)^(n|L)|0,l^(x|D)|0)|0;l=D;o=oe(y|0,o|0,J|0,s|0)|0;y=D;c[G>>2]=o;c[G+4>>2]=y;s=oe(x|0,l|0,J|0,s|0)|0;J=D;c[m>>2]=s;c[m+4>>2]=J;l=Rd(o|0,y|0,14)|0;x=D;L=Pd(o|0,y|0,50)|0;x=x|D;n=Rd(o|0,y|0,18)|0;q=D;v=Pd(o|0,y|0,46)|0;q=x^(q|D);x=Rd(o|0,y|0,41)|0;e=D;t=Pd(o|0,y|0,23)|0;e=q^(e|D);q=c[h+80+104>>2]|0;H=c[h+80+104+4>>2]|0;K=oe(r|0,K|0,991336113,-2132889090)|0;e=oe(K|0,D|0,(l|L)^(n|v)^(x|t)|0,e|0)|0;H=oe(e|0,D|0,q|0,H|0)|0;H=oe(H|0,D|0,(E^b)&o^E|0,(I^j)&y^I|0)|0;q=D;e=Rd(s|0,J|0,28)|0;t=D;x=Pd(s|0,J|0,36)|0;t=t|D;v=Rd(s|0,J|0,34)|0;n=D;L=Pd(s|0,J|0,30)|0;n=t^(n|D);t=Rd(s|0,J|0,39)|0;l=D;K=Pd(s|0,J|0,25)|0;r=c[A>>2]|0;u=c[A+4>>2]|0;l=oe((r|F)&s|r&F|0,(u|p)&J|u&p|0,(e|x)^(v|L)^(t|K)|0,n^(l|D)|0)|0;n=D;z=oe(f|0,z|0,H|0,q|0)|0;f=D;c[k>>2]=z;c[k+4>>2]=f;q=oe(l|0,n|0,H|0,q|0)|0;H=D;c[B>>2]=q;c[B+4>>2]=H;n=Rd(z|0,f|0,14)|0;l=D;K=Pd(z|0,f|0,50)|0;l=l|D;t=Rd(z|0,f|0,18)|0;L=D;v=Pd(z|0,f|0,46)|0;L=l^(L|D);l=Rd(z|0,f|0,41)|0;x=D;e=Pd(z|0,f|0,23)|0;x=L^(x|D);L=c[h+80+112>>2]|0;p=c[h+80+112+4>>2]|0;I=oe(E|0,I|0,633803317,-1680079193)|0;x=oe(I|0,D|0,(n|K)^(t|v)^(l|e)|0,x|0)|0;p=oe(x|0,D|0,L|0,p|0)|0;p=oe(p|0,D|0,(b^o)&z^b|0,(j^y)&f^j|0)|0;L=D;x=Rd(q|0,H|0,28)|0;e=D;l=Pd(q|0,H|0,36)|0;e=e|D;v=Rd(q|0,H|0,34)|0;t=D;K=Pd(q|0,H|0,30)|0;t=e^(t|D);e=Rd(q|0,H|0,39)|0;n=D;I=Pd(q|0,H|0,25)|0;E=c[w>>2]|0;F=c[w+4>>2]|0;n=oe((E|s)&q|E&s|0,(F|J)&H|F&J|0,(x|l)^(v|K)^(e|I)|0,t^(n|D)|0)|0;t=D;u=oe(r|0,u|0,p|0,L|0)|0;r=D;c[A>>2]=u;c[A+4>>2]=r;L=oe(n|0,t|0,p|0,L|0)|0;p=D;c[C>>2]=L;c[C+4>>2]=p;t=Rd(u|0,r|0,14)|0;n=D;I=Pd(u|0,r|0,50)|0;n=n|D;e=Rd(u|0,r|0,18)|0;K=D;v=Pd(u|0,r|0,46)|0;K=n^(K|D);n=Rd(u|0,r|0,41)|0;l=D;x=Pd(u|0,r|0,23)|0;l=K^(l|D);K=c[h+80+120>>2]|0;J=c[h+80+120+4>>2]|0;j=oe(b|0,j|0,-815192428,-1046744716)|0;l=oe(j|0,D|0,(t|I)^(e|v)^(n|x)|0,l|0)|0;J=oe(l|0,D|0,K|0,J|0)|0;J=oe(J|0,D|0,(o^z)&u^o|0,(y^f)&r^y|0)|0;K=D;l=Rd(L|0,p|0,28)|0;x=D;n=Pd(L|0,p|0,36)|0;x=x|D;v=Rd(L|0,p|0,34)|0;e=D;I=Pd(L|0,p|0,30)|0;e=x^(e|D);x=Rd(L|0,p|0,39)|0;t=D;j=Pd(L|0,p|0,25)|0;b=c[m>>2]|0;s=c[m+4>>2]|0;t=oe((b|q)&L|b&q|0,(s|H)&p|s&H|0,(l|n)^(v|I)^(x|j)|0,e^(t|D)|0)|0;e=D;F=oe(E|0,F|0,J|0,K|0)|0;E=D;c[w>>2]=F;c[w+4>>2]=E;K=oe(t|0,e|0,J|0,K|0)|0;J=D;c[h+16>>2]=K;c[h+16+4>>2]=J;e=Rd(F|0,E|0,14)|0;t=D;j=Pd(F|0,E|0,50)|0;t=t|D;x=Rd(F|0,E|0,18)|0;I=D;v=Pd(F|0,E|0,46)|0;I=t^(I|D);t=Rd(F|0,E|0,41)|0;n=D;l=Pd(F|0,E|0,23)|0;n=I^(n|D);I=c[h+80+128>>2]|0;H=c[h+80+128+4>>2]|0;y=oe(o|0,y|0,-1628353838,-459576895)|0;n=oe(y|0,D|0,(e|j)^(x|v)^(t|l)|0,n|0)|0;H=oe(n|0,D|0,I|0,H|0)|0;H=oe(H|0,D|0,(z^u)&F^z|0,(f^r)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;j=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;o=c[B>>2]|0;q=c[B+4>>2]|0;e=oe((o|L)&K|o&L|0,(q|p)&J|q&p|0,(n|t)^(v|j)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[m>>2]=s;c[m+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[G>>2]=I;c[G+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;y=Pd(s|0,b|0,50)|0;e=e|D;l=Rd(s|0,b|0,18)|0;j=D;v=Pd(s|0,b|0,46)|0;j=e^(j|D);e=Rd(s|0,b|0,41)|0;t=D;n=Pd(s|0,b|0,23)|0;t=j^(t|D);j=c[h+80+136>>2]|0;p=c[h+80+136+4>>2]|0;f=oe(z|0,f|0,944711139,-272742522)|0;t=oe(f|0,D|0,(x|y)^(l|v)^(e|n)|0,t|0)|0;p=oe(t|0,D|0,j|0,p|0)|0;p=oe(p|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;j=D;t=Rd(I|0,H|0,28)|0;n=D;e=Pd(I|0,H|0,36)|0;n=n|D;v=Rd(I|0,H|0,34)|0;l=D;y=Pd(I|0,H|0,30)|0;l=n^(l|D);n=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;z=c[C>>2]|0;L=c[C+4>>2]|0;x=oe((z|K)&I|z&K|0,(L|J)&H|L&J|0,(t|e)^(v|y)^(n|f)|0,l^(x|D)|0)|0;l=D;q=oe(o|0,q|0,p|0,j|0)|0;o=D;c[B>>2]=q;c[B+4>>2]=o;j=oe(x|0,l|0,p|0,j|0)|0;p=D;c[k>>2]=j;c[k+4>>2]=p;l=Rd(q|0,o|0,14)|0;x=D;f=Pd(q|0,o|0,50)|0;x=x|D;n=Rd(q|0,o|0,18)|0;y=D;v=Pd(q|0,o|0,46)|0;y=x^(y|D);x=Rd(q|0,o|0,41)|0;e=D;t=Pd(q|0,o|0,23)|0;e=y^(e|D);y=c[h+80+144>>2]|0;J=c[h+80+144+4>>2]|0;r=oe(u|0,r|0,-1953704523,264347078)|0;e=oe(r|0,D|0,(l|f)^(n|v)^(x|t)|0,e|0)|0;J=oe(e|0,D|0,y|0,J|0)|0;J=oe(J|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;y=D;e=Rd(j|0,p|0,28)|0;t=D;x=Pd(j|0,p|0,36)|0;t=t|D;v=Rd(j|0,p|0,34)|0;n=D;f=Pd(j|0,p|0,30)|0;n=t^(n|D);t=Rd(j|0,p|0,39)|0;l=D;r=Pd(j|0,p|0,25)|0;u=c[h+16>>2]|0;K=c[h+16+4>>2]|0;l=oe((u|I)&j|u&I|0,(K|H)&p|K&H|0,(e|x)^(v|f)^(t|r)|0,n^(l|D)|0)|0;n=D;L=oe(z|0,L|0,J|0,y|0)|0;z=D;c[C>>2]=L;c[C+4>>2]=z;y=oe(l|0,n|0,J|0,y|0)|0;J=D;c[A>>2]=y;c[A+4>>2]=J;n=Rd(L|0,z|0,14)|0;l=D;r=Pd(L|0,z|0,50)|0;l=l|D;t=Rd(L|0,z|0,18)|0;f=D;v=Pd(L|0,z|0,46)|0;f=l^(f|D);l=Rd(L|0,z|0,41)|0;x=D;e=Pd(L|0,z|0,23)|0;x=f^(x|D);f=c[h+80+152>>2]|0;H=c[h+80+152+4>>2]|0;E=oe(F|0,E|0,2007800933,604807628)|0;x=oe(E|0,D|0,(n|r)^(t|v)^(l|e)|0,x|0)|0;H=oe(x|0,D|0,f|0,H|0)|0;H=oe(H|0,D|0,(s^q)&L^s|0,(b^o)&z^b|0)|0;f=D;x=Rd(y|0,J|0,28)|0;e=D;l=Pd(y|0,J|0,36)|0;e=e|D;v=Rd(y|0,J|0,34)|0;t=D;r=Pd(y|0,J|0,30)|0;t=e^(t|D);e=Rd(y|0,J|0,39)|0;n=D;E=Pd(y|0,J|0,25)|0;F=c[G>>2]|0;I=c[G+4>>2]|0;n=oe((F|j)&y|F&j|0,(I|p)&J|I&p|0,(x|l)^(v|r)^(e|E)|0,t^(n|D)|0)|0;t=D;K=oe(u|0,K|0,H|0,f|0)|0;u=D;c[h+16>>2]=K;c[h+16+4>>2]=u;f=oe(n|0,t|0,H|0,f|0)|0;H=D;c[w>>2]=f;c[w+4>>2]=H;t=Rd(K|0,u|0,14)|0;n=D;E=Pd(K|0,u|0,50)|0;n=n|D;e=Rd(K|0,u|0,18)|0;r=D;v=Pd(K|0,u|0,46)|0;r=n^(r|D);n=Rd(K|0,u|0,41)|0;l=D;x=Pd(K|0,u|0,23)|0;l=r^(l|D);r=c[h+80+160>>2]|0;p=c[h+80+160+4>>2]|0;b=oe(s|0,b|0,1495990901,770255983)|0;l=oe(b|0,D|0,(t|E)^(e|v)^(n|x)|0,l|0)|0;p=oe(l|0,D|0,r|0,p|0)|0;p=oe(p|0,D|0,(q^L)&K^q|0,(o^z)&u^o|0)|0;r=D;l=Rd(f|0,H|0,28)|0;x=D;n=Pd(f|0,H|0,36)|0;x=x|D;v=Rd(f|0,H|0,34)|0;e=D;E=Pd(f|0,H|0,30)|0;e=x^(e|D);x=Rd(f|0,H|0,39)|0;t=D;b=Pd(f|0,H|0,25)|0;s=c[k>>2]|0;j=c[k+4>>2]|0;t=oe((s|y)&f|s&y|0,(j|J)&H|j&J|0,(l|n)^(v|E)^(x|b)|0,e^(t|D)|0)|0;e=D;I=oe(F|0,I|0,p|0,r|0)|0;F=D;c[G>>2]=I;c[G+4>>2]=F;r=oe(t|0,e|0,p|0,r|0)|0;p=D;c[m>>2]=r;c[m+4>>2]=p;e=Rd(I|0,F|0,14)|0;t=D;b=Pd(I|0,F|0,50)|0;t=t|D;x=Rd(I|0,F|0,18)|0;E=D;v=Pd(I|0,F|0,46)|0;E=t^(E|D);t=Rd(I|0,F|0,41)|0;n=D;l=Pd(I|0,F|0,23)|0;n=E^(n|D);E=c[h+80+168>>2]|0;J=c[h+80+168+4>>2]|0;o=oe(q|0,o|0,1856431235,1249150122)|0;n=oe(o|0,D|0,(e|b)^(x|v)^(t|l)|0,n|0)|0;J=oe(n|0,D|0,E|0,J|0)|0;J=oe(J|0,D|0,(L^K)&I^L|0,(z^u)&F^z|0)|0;E=D;n=Rd(r|0,p|0,28)|0;l=D;t=Pd(r|0,p|0,36)|0;l=l|D;v=Rd(r|0,p|0,34)|0;x=D;b=Pd(r|0,p|0,30)|0;x=l^(x|D);l=Rd(r|0,p|0,39)|0;e=D;o=Pd(r|0,p|0,25)|0;q=c[A>>2]|0;y=c[A+4>>2]|0;e=oe((q|f)&r|q&f|0,(y|H)&p|y&H|0,(n|t)^(v|b)^(l|o)|0,x^(e|D)|0)|0;x=D;j=oe(s|0,j|0,J|0,E|0)|0;s=D;c[k>>2]=j;c[k+4>>2]=s;E=oe(e|0,x|0,J|0,E|0)|0;J=D;c[B>>2]=E;c[B+4>>2]=J;x=Rd(j|0,s|0,14)|0;e=D;o=Pd(j|0,s|0,50)|0;e=e|D;l=Rd(j|0,s|0,18)|0;b=D;v=Pd(j|0,s|0,46)|0;b=e^(b|D);e=Rd(j|0,s|0,41)|0;t=D;n=Pd(j|0,s|0,23)|0;t=b^(t|D);b=c[h+80+176>>2]|0;H=c[h+80+176+4>>2]|0;z=oe(L|0,z|0,-1119749164,1555081692)|0;t=oe(z|0,D|0,(x|o)^(l|v)^(e|n)|0,t|0)|0;H=oe(t|0,D|0,b|0,H|0)|0;H=oe(H|0,D|0,(K^I)&j^K|0,(u^F)&s^u|0)|0;b=D;t=Rd(E|0,J|0,28)|0;n=D;e=Pd(E|0,J|0,36)|0;n=n|D;v=Rd(E|0,J|0,34)|0;l=D;o=Pd(E|0,J|0,30)|0;l=n^(l|D);n=Rd(E|0,J|0,39)|0;x=D;z=Pd(E|0,J|0,25)|0;L=c[w>>2]|0;f=c[w+4>>2]|0;x=oe((L|r)&E|L&r|0,(f|p)&J|f&p|0,(t|e)^(v|o)^(n|z)|0,l^(x|D)|0)|0;l=D;y=oe(q|0,y|0,H|0,b|0)|0;q=D;c[A>>2]=y;c[A+4>>2]=q;b=oe(x|0,l|0,H|0,b|0)|0;H=D;c[C>>2]=b;c[C+4>>2]=H;l=Rd(y|0,q|0,14)|0;x=D;z=Pd(y|0,q|0,50)|0;x=x|D;n=Rd(y|0,q|0,18)|0;o=D;v=Pd(y|0,q|0,46)|0;o=x^(o|D);x=Rd(y|0,q|0,41)|0;e=D;t=Pd(y|0,q|0,23)|0;e=o^(e|D);o=c[h+80+184>>2]|0;p=c[h+80+184+4>>2]|0;u=oe(K|0,u|0,-2096016459,1996064986)|0;e=oe(u|0,D|0,(l|z)^(n|v)^(x|t)|0,e|0)|0;p=oe(e|0,D|0,o|0,p|0)|0;p=oe(p|0,D|0,(I^j)&y^I|0,(F^s)&q^F|0)|0;o=D;e=Rd(b|0,H|0,28)|0;t=D;x=Pd(b|0,H|0,36)|0;t=t|D;v=Rd(b|0,H|0,34)|0;n=D;z=Pd(b|0,H|0,30)|0;n=t^(n|D);t=Rd(b|0,H|0,39)|0;l=D;u=Pd(b|0,H|0,25)|0;K=c[m>>2]|0;r=c[m+4>>2]|0;l=oe((K|E)&b|K&E|0,(r|J)&H|r&J|0,(e|x)^(v|z)^(t|u)|0,n^(l|D)|0)|0;n=D;f=oe(L|0,f|0,p|0,o|0)|0;L=D;c[w>>2]=f;c[w+4>>2]=L;o=oe(l|0,n|0,p|0,o|0)|0;p=D;c[h+16>>2]=o;c[h+16+4>>2]=p;n=Rd(f|0,L|0,14)|0;l=D;u=Pd(f|0,L|0,50)|0;l=l|D;t=Rd(f|0,L|0,18)|0;z=D;v=Pd(f|0,L|0,46)|0;z=l^(z|D);l=Rd(f|0,L|0,41)|0;x=D;e=Pd(f|0,L|0,23)|0;x=z^(x|D);z=c[h+80+192>>2]|0;J=c[h+80+192+4>>2]|0;F=oe(I|0,F|0,-295247957,-1740746414)|0;x=oe(F|0,D|0,(n|u)^(t|v)^(l|e)|0,x|0)|0;J=oe(x|0,D|0,z|0,J|0)|0;J=oe(J|0,D|0,(j^y)&f^j|0,(s^q)&L^s|0)|0;z=D;x=Rd(o|0,p|0,28)|0;e=D;l=Pd(o|0,p|0,36)|0;e=e|D;v=Rd(o|0,p|0,34)|0;t=D;u=Pd(o|0,p|0,30)|0;t=e^(t|D);e=Rd(o|0,p|0,39)|0;n=D;F=Pd(o|0,p|0,25)|0;I=c[B>>2]|0;E=c[B+4>>2]|0;n=oe((I|b)&o|I&b|0,(E|H)&p|E&H|0,(x|l)^(v|u)^(e|F)|0,t^(n|D)|0)|0;t=D;r=oe(K|0,r|0,J|0,z|0)|0;K=D;c[m>>2]=r;c[m+4>>2]=K;z=oe(n|0,t|0,J|0,z|0)|0;J=D;c[G>>2]=z;c[G+4>>2]=J;t=Rd(r|0,K|0,14)|0;n=D;F=Pd(r|0,K|0,50)|0;n=n|D;e=Rd(r|0,K|0,18)|0;u=D;v=Pd(r|0,K|0,46)|0;u=n^(u|D);n=Rd(r|0,K|0,41)|0;l=D;x=Pd(r|0,K|0,23)|0;l=u^(l|D);u=c[h+80+200>>2]|0;H=c[h+80+200+4>>2]|0;s=oe(j|0,s|0,766784016,-1473132947)|0;l=oe(s|0,D|0,(t|F)^(e|v)^(n|x)|0,l|0)|0;H=oe(l|0,D|0,u|0,H|0)|0;H=oe(H|0,D|0,(y^f)&r^y|0,(q^L)&K^q|0)|0;u=D;l=Rd(z|0,J|0,28)|0;x=D;n=Pd(z|0,J|0,36)|0;x=x|D;v=Rd(z|0,J|0,34)|0;e=D;F=Pd(z|0,J|0,30)|0;e=x^(e|D);x=Rd(z|0,J|0,39)|0;t=D;s=Pd(z|0,J|0,25)|0;j=c[C>>2]|0;b=c[C+4>>2]|0;t=oe((j|o)&z|j&o|0,(b|p)&J|b&p|0,(l|n)^(v|F)^(x|s)|0,e^(t|D)|0)|0;e=D;E=oe(I|0,E|0,H|0,u|0)|0;I=D;c[B>>2]=E;c[B+4>>2]=I;u=oe(t|0,e|0,H|0,u|0)|0;H=D;c[k>>2]=u;c[k+4>>2]=H;e=Rd(E|0,I|0,14)|0;t=D;s=Pd(E|0,I|0,50)|0;t=t|D;x=Rd(E|0,I|0,18)|0;F=D;v=Pd(E|0,I|0,46)|0;F=t^(F|D);t=Rd(E|0,I|0,41)|0;n=D;l=Pd(E|0,I|0,23)|0;n=F^(n|D);F=c[h+80+208>>2]|0;p=c[h+80+208+4>>2]|0;q=oe(y|0,q|0,-1728372417,-1341970488)|0;n=oe(q|0,D|0,(e|s)^(x|v)^(t|l)|0,n|0)|0;p=oe(n|0,D|0,F|0,p|0)|0;p=oe(p|0,D|0,(f^r)&E^f|0,(L^K)&I^L|0)|0;F=D;n=Rd(u|0,H|0,28)|0;l=D;t=Pd(u|0,H|0,36)|0;l=l|D;v=Rd(u|0,H|0,34)|0;x=D;s=Pd(u|0,H|0,30)|0;x=l^(x|D);l=Rd(u|0,H|0,39)|0;e=D;q=Pd(u|0,H|0,25)|0;y=c[h+16>>2]|0;o=c[h+16+4>>2]|0;e=oe((y|z)&u|y&z|0,(o|J)&H|o&J|0,(n|t)^(v|s)^(l|q)|0,x^(e|D)|0)|0;x=D;b=oe(j|0,b|0,p|0,F|0)|0;j=D;c[C>>2]=b;c[C+4>>2]=j;F=oe(e|0,x|0,p|0,F|0)|0;p=D;c[A>>2]=F;c[A+4>>2]=p;x=Rd(b|0,j|0,14)|0;e=D;q=Pd(b|0,j|0,50)|0;e=e|D;l=Rd(b|0,j|0,18)|0;s=D;v=Pd(b|0,j|0,46)|0;s=e^(s|D);e=Rd(b|0,j|0,41)|0;t=D;n=Pd(b|0,j|0,23)|0;t=s^(t|D);s=c[h+80+216>>2]|0;J=c[h+80+216+4>>2]|0;L=oe(f|0,L|0,-1091629340,-1084653625)|0;t=oe(L|0,D|0,(x|q)^(l|v)^(e|n)|0,t|0)|0;J=oe(t|0,D|0,s|0,J|0)|0;J=oe(J|0,D|0,(r^E)&b^r|0,(K^I)&j^K|0)|0;s=D;t=Rd(F|0,p|0,28)|0;n=D;e=Pd(F|0,p|0,36)|0;n=n|D;v=Rd(F|0,p|0,34)|0;l=D;q=Pd(F|0,p|0,30)|0;l=n^(l|D);n=Rd(F|0,p|0,39)|0;x=D;L=Pd(F|0,p|0,25)|0;f=c[G>>2]|0;z=c[G+4>>2]|0;x=oe((f|u)&F|f&u|0,(z|H)&p|z&H|0,(t|e)^(v|q)^(n|L)|0,l^(x|D)|0)|0;l=D;o=oe(y|0,o|0,J|0,s|0)|0;y=D;c[h+16>>2]=o;c[h+16+4>>2]=y;s=oe(x|0,l|0,J|0,s|0)|0;J=D;c[w>>2]=s;c[w+4>>2]=J;l=Rd(o|0,y|0,14)|0;x=D;L=Pd(o|0,y|0,50)|0;x=x|D;n=Rd(o|0,y|0,18)|0;q=D;v=Pd(o|0,y|0,46)|0;q=x^(q|D);x=Rd(o|0,y|0,41)|0;e=D;t=Pd(o|0,y|0,23)|0;e=q^(e|D);q=c[h+80+224>>2]|0;H=c[h+80+224+4>>2]|0;K=oe(r|0,K|0,1034457026,-958395405)|0;e=oe(K|0,D|0,(l|L)^(n|v)^(x|t)|0,e|0)|0;H=oe(e|0,D|0,q|0,H|0)|0;H=oe(H|0,D|0,(E^b)&o^E|0,(I^j)&y^I|0)|0;q=D;e=Rd(s|0,J|0,28)|0;t=D;x=Pd(s|0,J|0,36)|0;t=t|D;v=Rd(s|0,J|0,34)|0;n=D;L=Pd(s|0,J|0,30)|0;n=t^(n|D);t=Rd(s|0,J|0,39)|0;l=D;K=Pd(s|0,J|0,25)|0;r=c[k>>2]|0;u=c[k+4>>2]|0;l=oe((r|F)&s|r&F|0,(u|p)&J|u&p|0,(e|x)^(v|L)^(t|K)|0,n^(l|D)|0)|0;n=D;z=oe(f|0,z|0,H|0,q|0)|0;f=D;c[G>>2]=z;c[G+4>>2]=f;q=oe(l|0,n|0,H|0,q|0)|0;H=D;c[m>>2]=q;c[m+4>>2]=H;n=Rd(z|0,f|0,14)|0;l=D;K=Pd(z|0,f|0,50)|0;l=l|D;t=Rd(z|0,f|0,18)|0;L=D;v=Pd(z|0,f|0,46)|0;L=l^(L|D);l=Rd(z|0,f|0,41)|0;x=D;e=Pd(z|0,f|0,23)|0;x=L^(x|D);L=c[h+80+232>>2]|0;p=c[h+80+232+4>>2]|0;I=oe(E|0,I|0,-1828018395,-710438585)|0;x=oe(I|0,D|0,(n|K)^(t|v)^(l|e)|0,x|0)|0;p=oe(x|0,D|0,L|0,p|0)|0;p=oe(p|0,D|0,(b^o)&z^b|0,(j^y)&f^j|0)|0;L=D;x=Rd(q|0,H|0,28)|0;e=D;l=Pd(q|0,H|0,36)|0;e=e|D;v=Rd(q|0,H|0,34)|0;t=D;K=Pd(q|0,H|0,30)|0;t=e^(t|D);e=Rd(q|0,H|0,39)|0;n=D;I=Pd(q|0,H|0,25)|0;E=c[A>>2]|0;F=c[A+4>>2]|0;n=oe((E|s)&q|E&s|0,(F|J)&H|F&J|0,(x|l)^(v|K)^(e|I)|0,t^(n|D)|0)|0;t=D;u=oe(r|0,u|0,p|0,L|0)|0;r=D;c[k>>2]=u;c[k+4>>2]=r;L=oe(n|0,t|0,p|0,L|0)|0;p=D;c[B>>2]=L;c[B+4>>2]=p;t=Rd(u|0,r|0,14)|0;n=D;I=Pd(u|0,r|0,50)|0;n=n|D;e=Rd(u|0,r|0,18)|0;K=D;v=Pd(u|0,r|0,46)|0;K=n^(K|D);n=Rd(u|0,r|0,41)|0;l=D;x=Pd(u|0,r|0,23)|0;l=K^(l|D);K=c[h+80+240>>2]|0;J=c[h+80+240+4>>2]|0;j=oe(b|0,j|0,-536640913,113926993)|0;l=oe(j|0,D|0,(t|I)^(e|v)^(n|x)|0,l|0)|0;J=oe(l|0,D|0,K|0,J|0)|0;J=oe(J|0,D|0,(o^z)&u^o|0,(y^f)&r^y|0)|0;K=D;l=Rd(L|0,p|0,28)|0;x=D;n=Pd(L|0,p|0,36)|0;x=x|D;v=Rd(L|0,p|0,34)|0;e=D;I=Pd(L|0,p|0,30)|0;e=x^(e|D);x=Rd(L|0,p|0,39)|0;t=D;j=Pd(L|0,p|0,25)|0;b=c[w>>2]|0;s=c[w+4>>2]|0;t=oe((b|q)&L|b&q|0,(s|H)&p|s&H|0,(l|n)^(v|I)^(x|j)|0,e^(t|D)|0)|0;e=D;F=oe(E|0,F|0,J|0,K|0)|0;E=D;c[A>>2]=F;c[A+4>>2]=E;K=oe(t|0,e|0,J|0,K|0)|0;J=D;c[C>>2]=K;c[C+4>>2]=J;e=Rd(F|0,E|0,14)|0;t=D;j=Pd(F|0,E|0,50)|0;t=t|D;x=Rd(F|0,E|0,18)|0;I=D;v=Pd(F|0,E|0,46)|0;I=t^(I|D);t=Rd(F|0,E|0,41)|0;n=D;l=Pd(F|0,E|0,23)|0;n=I^(n|D);I=c[h+80+248>>2]|0;H=c[h+80+248+4>>2]|0;y=oe(o|0,y|0,168717936,338241895)|0;n=oe(y|0,D|0,(e|j)^(x|v)^(t|l)|0,n|0)|0;H=oe(n|0,D|0,I|0,H|0)|0;H=oe(H|0,D|0,(z^u)&F^z|0,(f^r)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;j=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;o=c[m>>2]|0;q=c[m+4>>2]|0;e=oe((o|L)&K|o&L|0,(q|p)&J|q&p|0,(n|t)^(v|j)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[w>>2]=s;c[w+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[h+16>>2]=I;c[h+16+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;y=Pd(s|0,b|0,50)|0;e=e|D;l=Rd(s|0,b|0,18)|0;j=D;v=Pd(s|0,b|0,46)|0;j=e^(j|D);e=Rd(s|0,b|0,41)|0;t=D;n=Pd(s|0,b|0,23)|0;t=j^(t|D);j=c[h+80+256>>2]|0;p=c[h+80+256+4>>2]|0;f=oe(z|0,f|0,1188179964,666307205)|0;t=oe(f|0,D|0,(x|y)^(l|v)^(e|n)|0,t|0)|0;p=oe(t|0,D|0,j|0,p|0)|0;p=oe(p|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;j=D;t=Rd(I|0,H|0,28)|0;n=D;e=Pd(I|0,H|0,36)|0;n=n|D;v=Rd(I|0,H|0,34)|0;l=D;y=Pd(I|0,H|0,30)|0;l=n^(l|D);n=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;z=c[B>>2]|0;L=c[B+4>>2]|0;x=oe((z|K)&I|z&K|0,(L|J)&H|L&J|0,(t|e)^(v|y)^(n|f)|0,l^(x|D)|0)|0;l=D;q=oe(o|0,q|0,p|0,j|0)|0;o=D;c[m>>2]=q;c[m+4>>2]=o;j=oe(x|0,l|0,p|0,j|0)|0;p=D;c[G>>2]=j;c[G+4>>2]=p;l=Rd(q|0,o|0,14)|0;x=D;f=Pd(q|0,o|0,50)|0;x=x|D;n=Rd(q|0,o|0,18)|0;y=D;v=Pd(q|0,o|0,46)|0;y=x^(y|D);x=Rd(q|0,o|0,41)|0;e=D;t=Pd(q|0,o|0,23)|0;e=y^(e|D);y=c[h+80+264>>2]|0;J=c[h+80+264+4>>2]|0;r=oe(u|0,r|0,1546045734,773529912)|0;e=oe(r|0,D|0,(l|f)^(n|v)^(x|t)|0,e|0)|0;J=oe(e|0,D|0,y|0,J|0)|0;J=oe(J|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;y=D;e=Rd(j|0,p|0,28)|0;t=D;x=Pd(j|0,p|0,36)|0;t=t|D;v=Rd(j|0,p|0,34)|0;n=D;f=Pd(j|0,p|0,30)|0;n=t^(n|D);t=Rd(j|0,p|0,39)|0;l=D;r=Pd(j|0,p|0,25)|0;u=c[C>>2]|0;K=c[C+4>>2]|0;l=oe((u|I)&j|u&I|0,(K|H)&p|K&H|0,(e|x)^(v|f)^(t|r)|0,n^(l|D)|0)|0;n=D;L=oe(z|0,L|0,J|0,y|0)|0;z=D;c[B>>2]=L;c[B+4>>2]=z;y=oe(l|0,n|0,J|0,y|0)|0;J=D;c[k>>2]=y;c[k+4>>2]=J;n=Rd(L|0,z|0,14)|0;l=D;r=Pd(L|0,z|0,50)|0;l=l|D;t=Rd(L|0,z|0,18)|0;f=D;v=Pd(L|0,z|0,46)|0;f=l^(f|D);l=Rd(L|0,z|0,41)|0;x=D;e=Pd(L|0,z|0,23)|0;x=f^(x|D);f=c[h+80+272>>2]|0;H=c[h+80+272+4>>2]|0;E=oe(F|0,E|0,1522805485,1294757372)|0;x=oe(E|0,D|0,(n|r)^(t|v)^(l|e)|0,x|0)|0;H=oe(x|0,D|0,f|0,H|0)|0;H=oe(H|0,D|0,(s^q)&L^s|0,(b^o)&z^b|0)|0;f=D;x=Rd(y|0,J|0,28)|0;e=D;l=Pd(y|0,J|0,36)|0;e=e|D;v=Rd(y|0,J|0,34)|0;t=D;r=Pd(y|0,J|0,30)|0;t=e^(t|D);e=Rd(y|0,J|0,39)|0;n=D;E=Pd(y|0,J|0,25)|0;F=c[h+16>>2]|0;I=c[h+16+4>>2]|0;n=oe((F|j)&y|F&j|0,(I|p)&J|I&p|0,(x|l)^(v|r)^(e|E)|0,t^(n|D)|0)|0;t=D;K=oe(u|0,K|0,H|0,f|0)|0;u=D;c[C>>2]=K;c[C+4>>2]=u;f=oe(n|0,t|0,H|0,f|0)|0;H=D;c[A>>2]=f;c[A+4>>2]=H;t=Rd(K|0,u|0,14)|0;n=D;E=Pd(K|0,u|0,50)|0;n=n|D;e=Rd(K|0,u|0,18)|0;r=D;v=Pd(K|0,u|0,46)|0;r=n^(r|D);n=Rd(K|0,u|0,41)|0;l=D;x=Pd(K|0,u|0,23)|0;l=r^(l|D);r=c[h+80+280>>2]|0;p=c[h+80+280+4>>2]|0;b=oe(s|0,b|0,-1651133473,1396182291)|0;l=oe(b|0,D|0,(t|E)^(e|v)^(n|x)|0,l|0)|0;p=oe(l|0,D|0,r|0,p|0)|0;p=oe(p|0,D|0,(q^L)&K^q|0,(o^z)&u^o|0)|0;r=D;l=Rd(f|0,H|0,28)|0;x=D;n=Pd(f|0,H|0,36)|0;x=x|D;v=Rd(f|0,H|0,34)|0;e=D;E=Pd(f|0,H|0,30)|0;e=x^(e|D);x=Rd(f|0,H|0,39)|0;t=D;b=Pd(f|0,H|0,25)|0;s=c[G>>2]|0;j=c[G+4>>2]|0;t=oe((s|y)&f|s&y|0,(j|J)&H|j&J|0,(l|n)^(v|E)^(x|b)|0,e^(t|D)|0)|0;e=D;I=oe(F|0,I|0,p|0,r|0)|0;F=D;c[h+16>>2]=I;c[h+16+4>>2]=F;r=oe(t|0,e|0,p|0,r|0)|0;p=D;c[w>>2]=r;c[w+4>>2]=p;e=Rd(I|0,F|0,14)|0;t=D;b=Pd(I|0,F|0,50)|0;t=t|D;x=Rd(I|0,F|0,18)|0;E=D;v=Pd(I|0,F|0,46)|0;E=t^(E|D);t=Rd(I|0,F|0,41)|0;n=D;l=Pd(I|0,F|0,23)|0;n=E^(n|D);E=c[h+80+288>>2]|0;J=c[h+80+288+4>>2]|0;o=oe(q|0,o|0,-1951439906,1695183700)|0;n=oe(o|0,D|0,(e|b)^(x|v)^(t|l)|0,n|0)|0;J=oe(n|0,D|0,E|0,J|0)|0;J=oe(J|0,D|0,(L^K)&I^L|0,(z^u)&F^z|0)|0;E=D;n=Rd(r|0,p|0,28)|0;l=D;t=Pd(r|0,p|0,36)|0;l=l|D;v=Rd(r|0,p|0,34)|0;x=D;b=Pd(r|0,p|0,30)|0;x=l^(x|D);l=Rd(r|0,p|0,39)|0;e=D;o=Pd(r|0,p|0,25)|0;q=c[k>>2]|0;y=c[k+4>>2]|0;e=oe((q|f)&r|q&f|0,(y|H)&p|y&H|0,(n|t)^(v|b)^(l|o)|0,x^(e|D)|0)|0;x=D;j=oe(s|0,j|0,J|0,E|0)|0;s=D;c[G>>2]=j;c[G+4>>2]=s;E=oe(e|0,x|0,J|0,E|0)|0;J=D;c[m>>2]=E;c[m+4>>2]=J;x=Rd(j|0,s|0,14)|0;e=D;o=Pd(j|0,s|0,50)|0;e=e|D;l=Rd(j|0,s|0,18)|0;b=D;v=Pd(j|0,s|0,46)|0;b=e^(b|D);e=Rd(j|0,s|0,41)|0;t=D;n=Pd(j|0,s|0,23)|0;t=b^(t|D);b=c[h+80+296>>2]|0;H=c[h+80+296+4>>2]|0;z=oe(L|0,z|0,1014477480,1986661051)|0;t=oe(z|0,D|0,(x|o)^(l|v)^(e|n)|0,t|0)|0;H=oe(t|0,D|0,b|0,H|0)|0;H=oe(H|0,D|0,(K^I)&j^K|0,(u^F)&s^u|0)|0;b=D;t=Rd(E|0,J|0,28)|0;n=D;e=Pd(E|0,J|0,36)|0;n=n|D;v=Rd(E|0,J|0,34)|0;l=D;o=Pd(E|0,J|0,30)|0;l=n^(l|D);n=Rd(E|0,J|0,39)|0;x=D;z=Pd(E|0,J|0,25)|0;L=c[A>>2]|0;f=c[A+4>>2]|0;x=oe((L|r)&E|L&r|0,(f|p)&J|f&p|0,(t|e)^(v|o)^(n|z)|0,l^(x|D)|0)|0;l=D;y=oe(q|0,y|0,H|0,b|0)|0;q=D;c[k>>2]=y;c[k+4>>2]=q;b=oe(x|0,l|0,H|0,b|0)|0;H=D;c[B>>2]=b;c[B+4>>2]=H;l=Rd(y|0,q|0,14)|0;x=D;z=Pd(y|0,q|0,50)|0;x=x|D;n=Rd(y|0,q|0,18)|0;o=D;v=Pd(y|0,q|0,46)|0;o=x^(o|D);x=Rd(y|0,q|0,41)|0;e=D;t=Pd(y|0,q|0,23)|0;e=o^(e|D);o=c[h+80+304>>2]|0;p=c[h+80+304+4>>2]|0;u=oe(K|0,u|0,1206759142,-2117940946)|0;e=oe(u|0,D|0,(l|z)^(n|v)^(x|t)|0,e|0)|0;p=oe(e|0,D|0,o|0,p|0)|0;p=oe(p|0,D|0,(I^j)&y^I|0,(F^s)&q^F|0)|0;o=D;e=Rd(b|0,H|0,28)|0;t=D;x=Pd(b|0,H|0,36)|0;t=t|D;v=Rd(b|0,H|0,34)|0;n=D;z=Pd(b|0,H|0,30)|0;n=t^(n|D);t=Rd(b|0,H|0,39)|0;l=D;u=Pd(b|0,H|0,25)|0;K=c[w>>2]|0;r=c[w+4>>2]|0;l=oe((K|E)&b|K&E|0,(r|J)&H|r&J|0,(e|x)^(v|z)^(t|u)|0,n^(l|D)|0)|0;n=D;f=oe(L|0,f|0,p|0,o|0)|0;L=D;c[A>>2]=f;c[A+4>>2]=L;o=oe(l|0,n|0,p|0,o|0)|0;p=D;c[C>>2]=o;c[C+4>>2]=p;n=Rd(f|0,L|0,14)|0;l=D;u=Pd(f|0,L|0,50)|0;l=l|D;t=Rd(f|0,L|0,18)|0;z=D;v=Pd(f|0,L|0,46)|0;z=l^(z|D);l=Rd(f|0,L|0,41)|0;x=D;e=Pd(f|0,L|0,23)|0;x=z^(x|D);z=c[h+80+312>>2]|0;J=c[h+80+312+4>>2]|0;F=oe(I|0,F|0,344077627,-1838011259)|0;x=oe(F|0,D|0,(n|u)^(t|v)^(l|e)|0,x|0)|0;J=oe(x|0,D|0,z|0,J|0)|0;J=oe(J|0,D|0,(j^y)&f^j|0,(s^q)&L^s|0)|0;z=D;x=Rd(o|0,p|0,28)|0;e=D;l=Pd(o|0,p|0,36)|0;e=e|D;v=Rd(o|0,p|0,34)|0;t=D;u=Pd(o|0,p|0,30)|0;t=e^(t|D);e=Rd(o|0,p|0,39)|0;n=D;F=Pd(o|0,p|0,25)|0;I=c[m>>2]|0;E=c[m+4>>2]|0;n=oe((I|b)&o|I&b|0,(E|H)&p|E&H|0,(x|l)^(v|u)^(e|F)|0,t^(n|D)|0)|0;t=D;r=oe(K|0,r|0,J|0,z|0)|0;K=D;c[w>>2]=r;c[w+4>>2]=K;z=oe(n|0,t|0,J|0,z|0)|0;J=D;c[h+16>>2]=z;c[h+16+4>>2]=J;t=Rd(r|0,K|0,14)|0;n=D;F=Pd(r|0,K|0,50)|0;n=n|D;e=Rd(r|0,K|0,18)|0;u=D;v=Pd(r|0,K|0,46)|0;u=n^(u|D);n=Rd(r|0,K|0,41)|0;l=D;x=Pd(r|0,K|0,23)|0;l=u^(l|D);u=c[h+80+320>>2]|0;H=c[h+80+320+4>>2]|0;s=oe(j|0,s|0,1290863460,-1564481375)|0;l=oe(s|0,D|0,(t|F)^(e|v)^(n|x)|0,l|0)|0;H=oe(l|0,D|0,u|0,H|0)|0;H=oe(H|0,D|0,(y^f)&r^y|0,(q^L)&K^q|0)|0;u=D;l=Rd(z|0,J|0,28)|0;x=D;n=Pd(z|0,J|0,36)|0;x=x|D;v=Rd(z|0,J|0,34)|0;e=D;F=Pd(z|0,J|0,30)|0;e=x^(e|D);x=Rd(z|0,J|0,39)|0;t=D;s=Pd(z|0,J|0,25)|0;j=c[B>>2]|0;b=c[B+4>>2]|0;t=oe((j|o)&z|j&o|0,(b|p)&J|b&p|0,(l|n)^(v|F)^(x|s)|0,e^(t|D)|0)|0;e=D;E=oe(I|0,E|0,H|0,u|0)|0;I=D;c[m>>2]=E;c[m+4>>2]=I;u=oe(t|0,e|0,H|0,u|0)|0;H=D;c[G>>2]=u;c[G+4>>2]=H;e=Rd(E|0,I|0,14)|0;t=D;s=Pd(E|0,I|0,50)|0;t=t|D;x=Rd(E|0,I|0,18)|0;F=D;v=Pd(E|0,I|0,46)|0;F=t^(F|D);t=Rd(E|0,I|0,41)|0;n=D;l=Pd(E|0,I|0,23)|0;n=F^(n|D);F=c[h+80+328>>2]|0;p=c[h+80+328+4>>2]|0;q=oe(y|0,q|0,-1136513023,-1474664885)|0;n=oe(q|0,D|0,(e|s)^(x|v)^(t|l)|0,n|0)|0;p=oe(n|0,D|0,F|0,p|0)|0;p=oe(p|0,D|0,(f^r)&E^f|0,(L^K)&I^L|0)|0;F=D;n=Rd(u|0,H|0,28)|0;l=D;t=Pd(u|0,H|0,36)|0;l=l|D;v=Rd(u|0,H|0,34)|0;x=D;s=Pd(u|0,H|0,30)|0;x=l^(x|D);l=Rd(u|0,H|0,39)|0;e=D;q=Pd(u|0,H|0,25)|0;y=c[C>>2]|0;o=c[C+4>>2]|0;e=oe((y|z)&u|y&z|0,(o|J)&H|o&J|0,(n|t)^(v|s)^(l|q)|0,x^(e|D)|0)|0;x=D;b=oe(j|0,b|0,p|0,F|0)|0;j=D;c[B>>2]=b;c[B+4>>2]=j;F=oe(e|0,x|0,p|0,F|0)|0;p=D;c[k>>2]=F;c[k+4>>2]=p;x=Rd(b|0,j|0,14)|0;e=D;q=Pd(b|0,j|0,50)|0;e=e|D;l=Rd(b|0,j|0,18)|0;s=D;v=Pd(b|0,j|0,46)|0;s=e^(s|D);e=Rd(b|0,j|0,41)|0;t=D;n=Pd(b|0,j|0,23)|0;t=s^(t|D);s=c[h+80+336>>2]|0;J=c[h+80+336+4>>2]|0;L=oe(f|0,L|0,-789014639,-1035236496)|0;t=oe(L|0,D|0,(x|q)^(l|v)^(e|n)|0,t|0)|0;J=oe(t|0,D|0,s|0,J|0)|0;J=oe(J|0,D|0,(r^E)&b^r|0,(K^I)&j^K|0)|0;s=D;t=Rd(F|0,p|0,28)|0;n=D;e=Pd(F|0,p|0,36)|0;n=n|D;v=Rd(F|0,p|0,34)|0;l=D;q=Pd(F|0,p|0,30)|0;l=n^(l|D);n=Rd(F|0,p|0,39)|0;x=D;L=Pd(F|0,p|0,25)|0;f=c[h+16>>2]|0;z=c[h+16+4>>2]|0;x=oe((f|u)&F|f&u|0,(z|H)&p|z&H|0,(t|e)^(v|q)^(n|L)|0,l^(x|D)|0)|0;l=D;o=oe(y|0,o|0,J|0,s|0)|0;y=D;c[C>>2]=o;c[C+4>>2]=y;s=oe(x|0,l|0,J|0,s|0)|0;J=D;c[A>>2]=s;c[A+4>>2]=J;l=Rd(o|0,y|0,14)|0;x=D;L=Pd(o|0,y|0,50)|0;x=x|D;n=Rd(o|0,y|0,18)|0;q=D;v=Pd(o|0,y|0,46)|0;q=x^(q|D);x=Rd(o|0,y|0,41)|0;e=D;t=Pd(o|0,y|0,23)|0;e=q^(e|D);q=c[h+80+344>>2]|0;H=c[h+80+344+4>>2]|0;K=oe(r|0,K|0,106217008,-949202525)|0;e=oe(K|0,D|0,(l|L)^(n|v)^(x|t)|0,e|0)|0;H=oe(e|0,D|0,q|0,H|0)|0;H=oe(H|0,D|0,(E^b)&o^E|0,(I^j)&y^I|0)|0;q=D;e=Rd(s|0,J|0,28)|0;t=D;x=Pd(s|0,J|0,36)|0;t=t|D;v=Rd(s|0,J|0,34)|0;n=D;L=Pd(s|0,J|0,30)|0;n=t^(n|D);t=Rd(s|0,J|0,39)|0;l=D;K=Pd(s|0,J|0,25)|0;r=c[G>>2]|0;u=c[G+4>>2]|0;l=oe((r|F)&s|r&F|0,(u|p)&J|u&p|0,(e|x)^(v|L)^(t|K)|0,n^(l|D)|0)|0;n=D;z=oe(f|0,z|0,H|0,q|0)|0;f=D;c[h+16>>2]=z;c[h+16+4>>2]=f;q=oe(l|0,n|0,H|0,q|0)|0;H=D;c[w>>2]=q;c[w+4>>2]=H;n=Rd(z|0,f|0,14)|0;l=D;K=Pd(z|0,f|0,50)|0;l=l|D;t=Rd(z|0,f|0,18)|0;L=D;v=Pd(z|0,f|0,46)|0;L=l^(L|D);l=Rd(z|0,f|0,41)|0;x=D;e=Pd(z|0,f|0,23)|0;x=L^(x|D);L=c[h+80+352>>2]|0;p=c[h+80+352+4>>2]|0;I=oe(E|0,I|0,-688958952,-778901479)|0;x=oe(I|0,D|0,(n|K)^(t|v)^(l|e)|0,x|0)|0;p=oe(x|0,D|0,L|0,p|0)|0;p=oe(p|0,D|0,(b^o)&z^b|0,(j^y)&f^j|0)|0;L=D;x=Rd(q|0,H|0,28)|0;e=D;l=Pd(q|0,H|0,36)|0;e=e|D;v=Rd(q|0,H|0,34)|0;t=D;K=Pd(q|0,H|0,30)|0;t=e^(t|D);e=Rd(q|0,H|0,39)|0;n=D;I=Pd(q|0,H|0,25)|0;E=c[k>>2]|0;F=c[k+4>>2]|0;n=oe((E|s)&q|E&s|0,(F|J)&H|F&J|0,(x|l)^(v|K)^(e|I)|0,t^(n|D)|0)|0;t=D;u=oe(r|0,u|0,p|0,L|0)|0;r=D;c[G>>2]=u;c[G+4>>2]=r;L=oe(n|0,t|0,p|0,L|0)|0;p=D;c[m>>2]=L;c[m+4>>2]=p;t=Rd(u|0,r|0,14)|0;n=D;I=Pd(u|0,r|0,50)|0;n=n|D;e=Rd(u|0,r|0,18)|0;K=D;v=Pd(u|0,r|0,46)|0;K=n^(K|D);n=Rd(u|0,r|0,41)|0;l=D;x=Pd(u|0,r|0,23)|0;l=K^(l|D);K=c[h+80+360>>2]|0;J=c[h+80+360+4>>2]|0;j=oe(b|0,j|0,1432725776,-694614492)|0;l=oe(j|0,D|0,(t|I)^(e|v)^(n|x)|0,l|0)|0;J=oe(l|0,D|0,K|0,J|0)|0;J=oe(J|0,D|0,(o^z)&u^o|0,(y^f)&r^y|0)|0;K=D;l=Rd(L|0,p|0,28)|0;x=D;n=Pd(L|0,p|0,36)|0;x=x|D;v=Rd(L|0,p|0,34)|0;e=D;I=Pd(L|0,p|0,30)|0;e=x^(e|D);x=Rd(L|0,p|0,39)|0;t=D;j=Pd(L|0,p|0,25)|0;b=c[A>>2]|0;s=c[A+4>>2]|0;t=oe((b|q)&L|b&q|0,(s|H)&p|s&H|0,(l|n)^(v|I)^(x|j)|0,e^(t|D)|0)|0;e=D;F=oe(E|0,F|0,J|0,K|0)|0;E=D;c[k>>2]=F;c[k+4>>2]=E;K=oe(t|0,e|0,J|0,K|0)|0;J=D;c[B>>2]=K;c[B+4>>2]=J;e=Rd(F|0,E|0,14)|0;t=D;j=Pd(F|0,E|0,50)|0;t=t|D;x=Rd(F|0,E|0,18)|0;I=D;v=Pd(F|0,E|0,46)|0;I=t^(I|D);t=Rd(F|0,E|0,41)|0;n=D;l=Pd(F|0,E|0,23)|0;n=I^(n|D);I=c[h+80+368>>2]|0;H=c[h+80+368+4>>2]|0;y=oe(o|0,y|0,1467031594,-200395387)|0;n=oe(y|0,D|0,(e|j)^(x|v)^(t|l)|0,n|0)|0;H=oe(n|0,D|0,I|0,H|0)|0;H=oe(H|0,D|0,(z^u)&F^z|0,(f^r)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;j=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;o=c[w>>2]|0;q=c[w+4>>2]|0;e=oe((o|L)&K|o&L|0,(q|p)&J|q&p|0,(n|t)^(v|j)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[A>>2]=s;c[A+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[C>>2]=I;c[C+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;y=Pd(s|0,b|0,50)|0;e=e|D;l=Rd(s|0,b|0,18)|0;j=D;v=Pd(s|0,b|0,46)|0;j=e^(j|D);e=Rd(s|0,b|0,41)|0;t=D;n=Pd(s|0,b|0,23)|0;t=j^(t|D);j=c[h+80+376>>2]|0;p=c[h+80+376+4>>2]|0;f=oe(z|0,f|0,851169720,275423344)|0;t=oe(f|0,D|0,(x|y)^(l|v)^(e|n)|0,t|0)|0;p=oe(t|0,D|0,j|0,p|0)|0;p=oe(p|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;j=D;t=Rd(I|0,H|0,28)|0;n=D;e=Pd(I|0,H|0,36)|0;n=n|D;v=Rd(I|0,H|0,34)|0;l=D;y=Pd(I|0,H|0,30)|0;l=n^(l|D);n=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;z=c[m>>2]|0;L=c[m+4>>2]|0;x=oe((z|K)&I|z&K|0,(L|J)&H|L&J|0,(t|e)^(v|y)^(n|f)|0,l^(x|D)|0)|0;l=D;q=oe(o|0,q|0,p|0,j|0)|0;o=D;c[w>>2]=q;c[w+4>>2]=o;j=oe(x|0,l|0,p|0,j|0)|0;p=D;c[h+16>>2]=j;c[h+16+4>>2]=p;l=Rd(q|0,o|0,14)|0;x=D;f=Pd(q|0,o|0,50)|0;x=x|D;n=Rd(q|0,o|0,18)|0;y=D;v=Pd(q|0,o|0,46)|0;y=x^(y|D);x=Rd(q|0,o|0,41)|0;e=D;t=Pd(q|0,o|0,23)|0;e=y^(e|D);y=c[h+80+384>>2]|0;J=c[h+80+384+4>>2]|0;r=oe(u|0,r|0,-1194143544,430227734)|0;e=oe(r|0,D|0,(l|f)^(n|v)^(x|t)|0,e|0)|0;J=oe(e|0,D|0,y|0,J|0)|0;J=oe(J|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;y=D;e=Rd(j|0,p|0,28)|0;t=D;x=Pd(j|0,p|0,36)|0;t=t|D;v=Rd(j|0,p|0,34)|0;n=D;f=Pd(j|0,p|0,30)|0;n=t^(n|D);t=Rd(j|0,p|0,39)|0;l=D;r=Pd(j|0,p|0,25)|0;u=c[B>>2]|0;K=c[B+4>>2]|0;l=oe((u|I)&j|u&I|0,(K|H)&p|K&H|0,(e|x)^(v|f)^(t|r)|0,n^(l|D)|0)|0;n=D;L=oe(z|0,L|0,J|0,y|0)|0;z=D;c[m>>2]=L;c[m+4>>2]=z;y=oe(l|0,n|0,J|0,y|0)|0;J=D;c[G>>2]=y;c[G+4>>2]=J;n=Rd(L|0,z|0,14)|0;l=D;r=Pd(L|0,z|0,50)|0;l=l|D;t=Rd(L|0,z|0,18)|0;f=D;v=Pd(L|0,z|0,46)|0;f=l^(f|D);l=Rd(L|0,z|0,41)|0;x=D;e=Pd(L|0,z|0,23)|0;x=f^(x|D);f=c[h+80+392>>2]|0;H=c[h+80+392+4>>2]|0;E=oe(F|0,E|0,1363258195,506948616)|0;x=oe(E|0,D|0,(n|r)^(t|v)^(l|e)|0,x|0)|0;H=oe(x|0,D|0,f|0,H|0)|0;H=oe(H|0,D|0,(s^q)&L^s|0,(b^o)&z^b|0)|0;f=D;x=Rd(y|0,J|0,28)|0;e=D;l=Pd(y|0,J|0,36)|0;e=e|D;v=Rd(y|0,J|0,34)|0;t=D;r=Pd(y|0,J|0,30)|0;t=e^(t|D);e=Rd(y|0,J|0,39)|0;n=D;E=Pd(y|0,J|0,25)|0;F=c[C>>2]|0;I=c[C+4>>2]|0;n=oe((F|j)&y|F&j|0,(I|p)&J|I&p|0,(x|l)^(v|r)^(e|E)|0,t^(n|D)|0)|0;t=D;K=oe(u|0,K|0,H|0,f|0)|0;u=D;c[B>>2]=K;c[B+4>>2]=u;f=oe(n|0,t|0,H|0,f|0)|0;H=D;c[k>>2]=f;c[k+4>>2]=H;t=Rd(K|0,u|0,14)|0;n=D;E=Pd(K|0,u|0,50)|0;n=n|D;e=Rd(K|0,u|0,18)|0;r=D;v=Pd(K|0,u|0,46)|0;r=n^(r|D);n=Rd(K|0,u|0,41)|0;l=D;x=Pd(K|0,u|0,23)|0;l=r^(l|D);r=c[h+80+400>>2]|0;p=c[h+80+400+4>>2]|0;b=oe(s|0,b|0,-544281703,659060556)|0;l=oe(b|0,D|0,(t|E)^(e|v)^(n|x)|0,l|0)|0;p=oe(l|0,D|0,r|0,p|0)|0;p=oe(p|0,D|0,(q^L)&K^q|0,(o^z)&u^o|0)|0;r=D;l=Rd(f|0,H|0,28)|0;x=D;n=Pd(f|0,H|0,36)|0;x=x|D;v=Rd(f|0,H|0,34)|0;e=D;E=Pd(f|0,H|0,30)|0;e=x^(e|D);x=Rd(f|0,H|0,39)|0;t=D;b=Pd(f|0,H|0,25)|0;s=c[h+16>>2]|0;j=c[h+16+4>>2]|0;t=oe((s|y)&f|s&y|0,(j|J)&H|j&J|0,(l|n)^(v|E)^(x|b)|0,e^(t|D)|0)|0;e=D;I=oe(F|0,I|0,p|0,r|0)|0;F=D;c[C>>2]=I;c[C+4>>2]=F;r=oe(t|0,e|0,p|0,r|0)|0;p=D;c[A>>2]=r;c[A+4>>2]=p;e=Rd(I|0,F|0,14)|0;t=D;b=Pd(I|0,F|0,50)|0;t=t|D;x=Rd(I|0,F|0,18)|0;E=D;v=Pd(I|0,F|0,46)|0;E=t^(E|D);t=Rd(I|0,F|0,41)|0;n=D;l=Pd(I|0,F|0,23)|0;n=E^(n|D);E=c[h+80+408>>2]|0;J=c[h+80+408+4>>2]|0;o=oe(q|0,o|0,-509917016,883997877)|0;n=oe(o|0,D|0,(e|b)^(x|v)^(t|l)|0,n|0)|0;J=oe(n|0,D|0,E|0,J|0)|0;J=oe(J|0,D|0,(L^K)&I^L|0,(z^u)&F^z|0)|0;E=D;n=Rd(r|0,p|0,28)|0;l=D;t=Pd(r|0,p|0,36)|0;l=l|D;v=Rd(r|0,p|0,34)|0;x=D;b=Pd(r|0,p|0,30)|0;x=l^(x|D);l=Rd(r|0,p|0,39)|0;e=D;o=Pd(r|0,p|0,25)|0;q=c[G>>2]|0;y=c[G+4>>2]|0;e=oe((q|f)&r|q&f|0,(y|H)&p|y&H|0,(n|t)^(v|b)^(l|o)|0,x^(e|D)|0)|0;x=D;j=oe(s|0,j|0,J|0,E|0)|0;s=D;c[h+16>>2]=j;c[h+16+4>>2]=s;E=oe(e|0,x|0,J|0,E|0)|0;J=D;c[w>>2]=E;c[w+4>>2]=J;x=Rd(j|0,s|0,14)|0;e=D;o=Pd(j|0,s|0,50)|0;e=e|D;l=Rd(j|0,s|0,18)|0;b=D;v=Pd(j|0,s|0,46)|0;b=e^(b|D);e=Rd(j|0,s|0,41)|0;t=D;n=Pd(j|0,s|0,23)|0;t=b^(t|D);b=c[h+80+416>>2]|0;H=c[h+80+416+4>>2]|0;z=oe(L|0,z|0,-976659869,958139571)|0;t=oe(z|0,D|0,(x|o)^(l|v)^(e|n)|0,t|0)|0;H=oe(t|0,D|0,b|0,H|0)|0;H=oe(H|0,D|0,(K^I)&j^K|0,(u^F)&s^u|0)|0;b=D;t=Rd(E|0,J|0,28)|0;n=D;e=Pd(E|0,J|0,36)|0;n=n|D;v=Rd(E|0,J|0,34)|0;l=D;o=Pd(E|0,J|0,30)|0;l=n^(l|D);n=Rd(E|0,J|0,39)|0;x=D;z=Pd(E|0,J|0,25)|0;L=c[k>>2]|0;f=c[k+4>>2]|0;x=oe((L|r)&E|L&r|0,(f|p)&J|f&p|0,(t|e)^(v|o)^(n|z)|0,l^(x|D)|0)|0;l=D;y=oe(q|0,y|0,H|0,b|0)|0;q=D;c[G>>2]=y;c[G+4>>2]=q;b=oe(x|0,l|0,H|0,b|0)|0;H=D;c[m>>2]=b;c[m+4>>2]=H;l=Rd(y|0,q|0,14)|0;x=D;z=Pd(y|0,q|0,50)|0;x=x|D;n=Rd(y|0,q|0,18)|0;o=D;v=Pd(y|0,q|0,46)|0;o=x^(o|D);x=Rd(y|0,q|0,41)|0;e=D;t=Pd(y|0,q|0,23)|0;e=o^(e|D);o=c[h+80+424>>2]|0;p=c[h+80+424+4>>2]|0;u=oe(K|0,u|0,-482243893,1322822218)|0;e=oe(u|0,D|0,(l|z)^(n|v)^(x|t)|0,e|0)|0;p=oe(e|0,D|0,o|0,p|0)|0;p=oe(p|0,D|0,(I^j)&y^I|0,(F^s)&q^F|0)|0;o=D;e=Rd(b|0,H|0,28)|0;t=D;x=Pd(b|0,H|0,36)|0;t=t|D;v=Rd(b|0,H|0,34)|0;n=D;z=Pd(b|0,H|0,30)|0;n=t^(n|D);t=Rd(b|0,H|0,39)|0;l=D;u=Pd(b|0,H|0,25)|0;K=c[A>>2]|0;r=c[A+4>>2]|0;l=oe((K|E)&b|K&E|0,(r|J)&H|r&J|0,(e|x)^(v|z)^(t|u)|0,n^(l|D)|0)|0;n=D;f=oe(L|0,f|0,p|0,o|0)|0;L=D;c[k>>2]=f;c[k+4>>2]=L;o=oe(l|0,n|0,p|0,o|0)|0;p=D;c[B>>2]=o;c[B+4>>2]=p;n=Rd(f|0,L|0,14)|0;l=D;u=Pd(f|0,L|0,50)|0;l=l|D;t=Rd(f|0,L|0,18)|0;z=D;v=Pd(f|0,L|0,46)|0;z=l^(z|D);l=Rd(f|0,L|0,41)|0;x=D;e=Pd(f|0,L|0,23)|0;x=z^(x|D);z=c[h+80+432>>2]|0;J=c[h+80+432+4>>2]|0;F=oe(I|0,F|0,2003034995,1537002063)|0;x=oe(F|0,D|0,(n|u)^(t|v)^(l|e)|0,x|0)|0;J=oe(x|0,D|0,z|0,J|0)|0;J=oe(J|0,D|0,(j^y)&f^j|0,(s^q)&L^s|0)|0;z=D;x=Rd(o|0,p|0,28)|0;e=D;l=Pd(o|0,p|0,36)|0;e=e|D;v=Rd(o|0,p|0,34)|0;t=D;u=Pd(o|0,p|0,30)|0;t=e^(t|D);e=Rd(o|0,p|0,39)|0;n=D;F=Pd(o|0,p|0,25)|0;I=c[w>>2]|0;E=c[w+4>>2]|0;n=oe((I|b)&o|I&b|0,(E|H)&p|E&H|0,(x|l)^(v|u)^(e|F)|0,t^(n|D)|0)|0;t=D;r=oe(K|0,r|0,J|0,z|0)|0;K=D;c[A>>2]=r;c[A+4>>2]=K;z=oe(n|0,t|0,J|0,z|0)|0;J=D;c[C>>2]=z;c[C+4>>2]=J;t=Rd(r|0,K|0,14)|0;n=D;F=Pd(r|0,K|0,50)|0;n=n|D;e=Rd(r|0,K|0,18)|0;u=D;v=Pd(r|0,K|0,46)|0;u=n^(u|D);n=Rd(r|0,K|0,41)|0;l=D;x=Pd(r|0,K|0,23)|0;l=u^(l|D);u=c[h+80+440>>2]|0;H=c[h+80+440+4>>2]|0;s=oe(j|0,s|0,-692930397,1747873779)|0;l=oe(s|0,D|0,(t|F)^(e|v)^(n|x)|0,l|0)|0;H=oe(l|0,D|0,u|0,H|0)|0;H=oe(H|0,D|0,(y^f)&r^y|0,(q^L)&K^q|0)|0;u=D;l=Rd(z|0,J|0,28)|0;x=D;n=Pd(z|0,J|0,36)|0;x=x|D;v=Rd(z|0,J|0,34)|0;e=D;F=Pd(z|0,J|0,30)|0;e=x^(e|D);x=Rd(z|0,J|0,39)|0;t=D;s=Pd(z|0,J|0,25)|0;j=c[m>>2]|0;b=c[m+4>>2]|0;t=oe((j|o)&z|j&o|0,(b|p)&J|b&p|0,(l|n)^(v|F)^(x|s)|0,e^(t|D)|0)|0;e=D;E=oe(I|0,E|0,H|0,u|0)|0;I=D;c[w>>2]=E;c[w+4>>2]=I;u=oe(t|0,e|0,H|0,u|0)|0;H=D;c[h+16>>2]=u;c[h+16+4>>2]=H;e=Rd(E|0,I|0,14)|0;t=D;s=Pd(E|0,I|0,50)|0;t=t|D;x=Rd(E|0,I|0,18)|0;F=D;v=Pd(E|0,I|0,46)|0;F=t^(F|D);t=Rd(E|0,I|0,41)|0;n=D;l=Pd(E|0,I|0,23)|0;n=F^(n|D);F=c[h+80+448>>2]|0;p=c[h+80+448+4>>2]|0;q=oe(y|0,q|0,1575990012,1955562222)|0;n=oe(q|0,D|0,(e|s)^(x|v)^(t|l)|0,n|0)|0;p=oe(n|0,D|0,F|0,p|0)|0;p=oe(p|0,D|0,(f^r)&E^f|0,(L^K)&I^L|0)|0;F=D;n=Rd(u|0,H|0,28)|0;l=D;t=Pd(u|0,H|0,36)|0;l=l|D;v=Rd(u|0,H|0,34)|0;x=D;s=Pd(u|0,H|0,30)|0;x=l^(x|D);l=Rd(u|0,H|0,39)|0;e=D;q=Pd(u|0,H|0,25)|0;y=c[B>>2]|0;o=c[B+4>>2]|0;e=oe((y|z)&u|y&z|0,(o|J)&H|o&J|0,(n|t)^(v|s)^(l|q)|0,x^(e|D)|0)|0;x=D;b=oe(j|0,b|0,p|0,F|0)|0;j=D;c[m>>2]=b;c[m+4>>2]=j;F=oe(e|0,x|0,p|0,F|0)|0;p=D;c[G>>2]=F;c[G+4>>2]=p;x=Rd(b|0,j|0,14)|0;e=D;q=Pd(b|0,j|0,50)|0;e=e|D;l=Rd(b|0,j|0,18)|0;s=D;v=Pd(b|0,j|0,46)|0;s=e^(s|D);e=Rd(b|0,j|0,41)|0;t=D;n=Pd(b|0,j|0,23)|0;t=s^(t|D);s=c[h+80+456>>2]|0;J=c[h+80+456+4>>2]|0;L=oe(f|0,L|0,1125592928,2024104815)|0;t=oe(L|0,D|0,(x|q)^(l|v)^(e|n)|0,t|0)|0;J=oe(t|0,D|0,s|0,J|0)|0;J=oe(J|0,D|0,(r^E)&b^r|0,(K^I)&j^K|0)|0;s=D;t=Rd(F|0,p|0,28)|0;n=D;e=Pd(F|0,p|0,36)|0;n=n|D;v=Rd(F|0,p|0,34)|0;l=D;q=Pd(F|0,p|0,30)|0;l=n^(l|D);n=Rd(F|0,p|0,39)|0;x=D;L=Pd(F|0,p|0,25)|0;f=c[C>>2]|0;z=c[C+4>>2]|0;x=oe((f|u)&F|f&u|0,(z|H)&p|z&H|0,(t|e)^(v|q)^(n|L)|0,l^(x|D)|0)|0;l=D;o=oe(y|0,o|0,J|0,s|0)|0;y=D;c[B>>2]=o;c[B+4>>2]=y;s=oe(x|0,l|0,J|0,s|0)|0;J=D;c[k>>2]=s;c[k+4>>2]=J;l=Rd(o|0,y|0,14)|0;x=D;L=Pd(o|0,y|0,50)|0;x=x|D;n=Rd(o|0,y|0,18)|0;q=D;v=Pd(o|0,y|0,46)|0;q=x^(q|D);x=Rd(o|0,y|0,41)|0;e=D;t=Pd(o|0,y|0,23)|0;e=q^(e|D);q=c[h+80+464>>2]|0;H=c[h+80+464+4>>2]|0;K=oe(r|0,K|0,-1578062990,-2067236844)|0;e=oe(K|0,D|0,(l|L)^(n|v)^(x|t)|0,e|0)|0;H=oe(e|0,D|0,q|0,H|0)|0;H=oe(H|0,D|0,(E^b)&o^E|0,(I^j)&y^I|0)|0;q=D;e=Rd(s|0,J|0,28)|0;t=D;x=Pd(s|0,J|0,36)|0;t=t|D;v=Rd(s|0,J|0,34)|0;n=D;L=Pd(s|0,J|0,30)|0;n=t^(n|D);t=Rd(s|0,J|0,39)|0;l=D;K=Pd(s|0,J|0,25)|0;r=c[h+16>>2]|0;u=c[h+16+4>>2]|0;l=oe((r|F)&s|r&F|0,(u|p)&J|u&p|0,(e|x)^(v|L)^(t|K)|0,n^(l|D)|0)|0;n=D;z=oe(f|0,z|0,H|0,q|0)|0;f=D;c[C>>2]=z;c[C+4>>2]=f;q=oe(l|0,n|0,H|0,q|0)|0;H=D;c[A>>2]=q;c[A+4>>2]=H;n=Rd(z|0,f|0,14)|0;l=D;K=Pd(z|0,f|0,50)|0;l=l|D;t=Rd(z|0,f|0,18)|0;L=D;v=Pd(z|0,f|0,46)|0;L=l^(L|D);l=Rd(z|0,f|0,41)|0;x=D;e=Pd(z|0,f|0,23)|0;x=L^(x|D);L=c[h+80+472>>2]|0;p=c[h+80+472+4>>2]|0;I=oe(E|0,I|0,442776044,-1933114872)|0;x=oe(I|0,D|0,(n|K)^(t|v)^(l|e)|0,x|0)|0;p=oe(x|0,D|0,L|0,p|0)|0;p=oe(p|0,D|0,(b^o)&z^b|0,(j^y)&f^j|0)|0;L=D;x=Rd(q|0,H|0,28)|0;e=D;l=Pd(q|0,H|0,36)|0;e=e|D;v=Rd(q|0,H|0,34)|0;t=D;K=Pd(q|0,H|0,30)|0;t=e^(t|D);e=Rd(q|0,H|0,39)|0;n=D;I=Pd(q|0,H|0,25)|0;E=c[G>>2]|0;F=c[G+4>>2]|0;n=oe((E|s)&q|E&s|0,(F|J)&H|F&J|0,(x|l)^(v|K)^(e|I)|0,t^(n|D)|0)|0;t=D;u=oe(r|0,u|0,p|0,L|0)|0;r=D;c[h+16>>2]=u;c[h+16+4>>2]=r;L=oe(n|0,t|0,p|0,L|0)|0;p=D;c[w>>2]=L;c[w+4>>2]=p;t=Rd(u|0,r|0,14)|0;n=D;I=Pd(u|0,r|0,50)|0;n=n|D;e=Rd(u|0,r|0,18)|0;K=D;v=Pd(u|0,r|0,46)|0;K=n^(K|D);n=Rd(u|0,r|0,41)|0;l=D;x=Pd(u|0,r|0,23)|0;l=K^(l|D);K=c[h+80+480>>2]|0;J=c[h+80+480+4>>2]|0;j=oe(b|0,j|0,593698344,-1866530822)|0;l=oe(j|0,D|0,(t|I)^(e|v)^(n|x)|0,l|0)|0;J=oe(l|0,D|0,K|0,J|0)|0;J=oe(J|0,D|0,(o^z)&u^o|0,(y^f)&r^y|0)|0;K=D;l=Rd(L|0,p|0,28)|0;x=D;n=Pd(L|0,p|0,36)|0;x=x|D;v=Rd(L|0,p|0,34)|0;e=D;I=Pd(L|0,p|0,30)|0;e=x^(e|D);x=Rd(L|0,p|0,39)|0;t=D;j=Pd(L|0,p|0,25)|0;b=c[k>>2]|0;s=c[k+4>>2]|0;t=oe((b|q)&L|b&q|0,(s|H)&p|s&H|0,(l|n)^(v|I)^(x|j)|0,e^(t|D)|0)|0;e=D;F=oe(E|0,F|0,J|0,K|0)|0;E=D;c[G>>2]=F;c[G+4>>2]=E;K=oe(t|0,e|0,J|0,K|0)|0;J=D;c[m>>2]=K;c[m+4>>2]=J;e=Rd(F|0,E|0,14)|0;t=D;j=Pd(F|0,E|0,50)|0;t=t|D;x=Rd(F|0,E|0,18)|0;I=D;v=Pd(F|0,E|0,46)|0;I=t^(I|D);t=Rd(F|0,E|0,41)|0;n=D;l=Pd(F|0,E|0,23)|0;n=I^(n|D);I=c[h+80+488>>2]|0;H=c[h+80+488+4>>2]|0;y=oe(o|0,y|0,-561857047,-1538233109)|0;n=oe(y|0,D|0,(e|j)^(x|v)^(t|l)|0,n|0)|0;H=oe(n|0,D|0,I|0,H|0)|0;H=oe(H|0,D|0,(z^u)&F^z|0,(f^r)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;j=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;o=c[A>>2]|0;q=c[A+4>>2]|0;e=oe((o|L)&K|o&L|0,(q|p)&J|q&p|0,(n|t)^(v|j)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[k>>2]=s;c[k+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[B>>2]=I;c[B+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;y=Pd(s|0,b|0,50)|0;e=e|D;l=Rd(s|0,b|0,18)|0;j=D;v=Pd(s|0,b|0,46)|0;j=e^(j|D);e=Rd(s|0,b|0,41)|0;t=D;n=Pd(s|0,b|0,23)|0;t=j^(t|D);j=c[h+80+496>>2]|0;p=c[h+80+496+4>>2]|0;f=oe(z|0,f|0,-1295615723,-1090935817)|0;t=oe(f|0,D|0,(x|y)^(l|v)^(e|n)|0,t|0)|0;p=oe(t|0,D|0,j|0,p|0)|0;p=oe(p|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;j=D;t=Rd(I|0,H|0,28)|0;n=D;e=Pd(I|0,H|0,36)|0;n=n|D;v=Rd(I|0,H|0,34)|0;l=D;y=Pd(I|0,H|0,30)|0;l=n^(l|D);n=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;z=c[w>>2]|0;L=c[w+4>>2]|0;x=oe((z|K)&I|z&K|0,(L|J)&H|L&J|0,(t|e)^(v|y)^(n|f)|0,l^(x|D)|0)|0;l=D;q=oe(o|0,q|0,p|0,j|0)|0;o=D;c[A>>2]=q;c[A+4>>2]=o;j=oe(x|0,l|0,p|0,j|0)|0;p=D;c[C>>2]=j;c[C+4>>2]=p;l=Rd(q|0,o|0,14)|0;x=D;f=Pd(q|0,o|0,50)|0;x=x|D;n=Rd(q|0,o|0,18)|0;y=D;v=Pd(q|0,o|0,46)|0;y=x^(y|D);x=Rd(q|0,o|0,41)|0;e=D;t=Pd(q|0,o|0,23)|0;e=y^(e|D);y=c[h+80+504>>2]|0;J=c[h+80+504+4>>2]|0;r=oe(u|0,r|0,-479046869,-965641998)|0;e=oe(r|0,D|0,(l|f)^(n|v)^(x|t)|0,e|0)|0;J=oe(e|0,D|0,y|0,J|0)|0;J=oe(J|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;y=D;e=Rd(j|0,p|0,28)|0;t=D;x=Pd(j|0,p|0,36)|0;t=t|D;v=Rd(j|0,p|0,34)|0;n=D;f=Pd(j|0,p|0,30)|0;n=t^(n|D);t=Rd(j|0,p|0,39)|0;l=D;r=Pd(j|0,p|0,25)|0;u=c[m>>2]|0;K=c[m+4>>2]|0;l=oe((u|I)&j|u&I|0,(K|H)&p|K&H|0,(e|x)^(v|f)^(t|r)|0,n^(l|D)|0)|0;n=D;L=oe(z|0,L|0,J|0,y|0)|0;z=D;c[w>>2]=L;c[w+4>>2]=z;y=oe(l|0,n|0,J|0,y|0)|0;J=D;c[h+16>>2]=y;c[h+16+4>>2]=J;n=Rd(L|0,z|0,14)|0;l=D;r=Pd(L|0,z|0,50)|0;l=l|D;t=Rd(L|0,z|0,18)|0;f=D;v=Pd(L|0,z|0,46)|0;f=l^(f|D);l=Rd(L|0,z|0,41)|0;x=D;e=Pd(L|0,z|0,23)|0;x=f^(x|D);f=c[h+80+512>>2]|0;H=c[h+80+512+4>>2]|0;E=oe(F|0,E|0,-366583396,-903397682)|0;x=oe(E|0,D|0,(n|r)^(t|v)^(l|e)|0,x|0)|0;H=oe(x|0,D|0,f|0,H|0)|0;H=oe(H|0,D|0,(s^q)&L^s|0,(b^o)&z^b|0)|0;f=D;x=Rd(y|0,J|0,28)|0;e=D;l=Pd(y|0,J|0,36)|0;e=e|D;v=Rd(y|0,J|0,34)|0;t=D;r=Pd(y|0,J|0,30)|0;t=e^(t|D);e=Rd(y|0,J|0,39)|0;n=D;E=Pd(y|0,J|0,25)|0;F=c[B>>2]|0;I=c[B+4>>2]|0;n=oe((F|j)&y|F&j|0,(I|p)&J|I&p|0,(x|l)^(v|r)^(e|E)|0,t^(n|D)|0)|0;t=D;K=oe(u|0,K|0,H|0,f|0)|0;u=D;c[m>>2]=K;c[m+4>>2]=u;f=oe(n|0,t|0,H|0,f|0)|0;H=D;c[G>>2]=f;c[G+4>>2]=H;t=Rd(K|0,u|0,14)|0;n=D;E=Pd(K|0,u|0,50)|0;n=n|D;e=Rd(K|0,u|0,18)|0;r=D;v=Pd(K|0,u|0,46)|0;r=n^(r|D);n=Rd(K|0,u|0,41)|0;l=D;x=Pd(K|0,u|0,23)|0;l=r^(l|D);r=c[h+80+520>>2]|0;p=c[h+80+520+4>>2]|0;b=oe(s|0,b|0,566280711,-779700025)|0;l=oe(b|0,D|0,(t|E)^(e|v)^(n|x)|0,l|0)|0;p=oe(l|0,D|0,r|0,p|0)|0;p=oe(p|0,D|0,(q^L)&K^q|0,(o^z)&u^o|0)|0;r=D;l=Rd(f|0,H|0,28)|0;x=D;n=Pd(f|0,H|0,36)|0;x=x|D;v=Rd(f|0,H|0,34)|0;e=D;E=Pd(f|0,H|0,30)|0;e=x^(e|D);x=Rd(f|0,H|0,39)|0;t=D;b=Pd(f|0,H|0,25)|0;s=c[C>>2]|0;j=c[C+4>>2]|0;t=oe((s|y)&f|s&y|0,(j|J)&H|j&J|0,(l|n)^(v|E)^(x|b)|0,e^(t|D)|0)|0;e=D;I=oe(F|0,I|0,p|0,r|0)|0;F=D;c[B>>2]=I;c[B+4>>2]=F;r=oe(t|0,e|0,p|0,r|0)|0;p=D;c[k>>2]=r;c[k+4>>2]=p;e=Rd(I|0,F|0,14)|0;t=D;b=Pd(I|0,F|0,50)|0;t=t|D;x=Rd(I|0,F|0,18)|0;E=D;v=Pd(I|0,F|0,46)|0;E=t^(E|D);t=Rd(I|0,F|0,41)|0;n=D;l=Pd(I|0,F|0,23)|0;n=E^(n|D);E=c[h+80+528>>2]|0;J=c[h+80+528+4>>2]|0;o=oe(q|0,o|0,-840897762,-354779690)|0;n=oe(o|0,D|0,(e|b)^(x|v)^(t|l)|0,n|0)|0;J=oe(n|0,D|0,E|0,J|0)|0;J=oe(J|0,D|0,(L^K)&I^L|0,(z^u)&F^z|0)|0;E=D;n=Rd(r|0,p|0,28)|0;l=D;t=Pd(r|0,p|0,36)|0;l=l|D;v=Rd(r|0,p|0,34)|0;x=D;b=Pd(r|0,p|0,30)|0;x=l^(x|D);l=Rd(r|0,p|0,39)|0;e=D;o=Pd(r|0,p|0,25)|0;q=c[h+16>>2]|0;y=c[h+16+4>>2]|0;e=oe((q|f)&r|q&f|0,(y|H)&p|y&H|0,(n|t)^(v|b)^(l|o)|0,x^(e|D)|0)|0;x=D;j=oe(s|0,j|0,J|0,E|0)|0;s=D;c[C>>2]=j;c[C+4>>2]=s;E=oe(e|0,x|0,J|0,E|0)|0;J=D;c[A>>2]=E;c[A+4>>2]=J;x=Rd(j|0,s|0,14)|0;e=D;o=Pd(j|0,s|0,50)|0;e=e|D;l=Rd(j|0,s|0,18)|0;b=D;v=Pd(j|0,s|0,46)|0;b=e^(b|D);e=Rd(j|0,s|0,41)|0;t=D;n=Pd(j|0,s|0,23)|0;t=b^(t|D);b=c[h+80+536>>2]|0;H=c[h+80+536+4>>2]|0;z=oe(L|0,z|0,-294727304,-176337025)|0;t=oe(z|0,D|0,(x|o)^(l|v)^(e|n)|0,t|0)|0;H=oe(t|0,D|0,b|0,H|0)|0;H=oe(H|0,D|0,(K^I)&j^K|0,(u^F)&s^u|0)|0;b=D;t=Rd(E|0,J|0,28)|0;n=D;e=Pd(E|0,J|0,36)|0;n=n|D;v=Rd(E|0,J|0,34)|0;l=D;o=Pd(E|0,J|0,30)|0;l=n^(l|D);n=Rd(E|0,J|0,39)|0;x=D;z=Pd(E|0,J|0,25)|0;L=c[G>>2]|0;f=c[G+4>>2]|0;x=oe((L|r)&E|L&r|0,(f|p)&J|f&p|0,(t|e)^(v|o)^(n|z)|0,l^(x|D)|0)|0;l=D;y=oe(q|0,y|0,H|0,b|0)|0;q=D;c[h+16>>2]=y;c[h+16+4>>2]=q;b=oe(x|0,l|0,H|0,b|0)|0;H=D;c[w>>2]=b;c[w+4>>2]=H;l=Rd(y|0,q|0,14)|0;x=D;z=Pd(y|0,q|0,50)|0;x=x|D;n=Rd(y|0,q|0,18)|0;o=D;v=Pd(y|0,q|0,46)|0;o=x^(o|D);x=Rd(y|0,q|0,41)|0;e=D;t=Pd(y|0,q|0,23)|0;e=o^(e|D);o=c[h+80+544>>2]|0;p=c[h+80+544+4>>2]|0;u=oe(K|0,u|0,1914138554,116418474)|0;e=oe(u|0,D|0,(l|z)^(n|v)^(x|t)|0,e|0)|0;p=oe(e|0,D|0,o|0,p|0)|0;p=oe(p|0,D|0,(I^j)&y^I|0,(F^s)&q^F|0)|0;o=D;e=Rd(b|0,H|0,28)|0;t=D;x=Pd(b|0,H|0,36)|0;t=t|D;v=Rd(b|0,H|0,34)|0;n=D;z=Pd(b|0,H|0,30)|0;n=t^(n|D);t=Rd(b|0,H|0,39)|0;l=D;u=Pd(b|0,H|0,25)|0;K=c[k>>2]|0;r=c[k+4>>2]|0;l=oe((K|E)&b|K&E|0,(r|J)&H|r&J|0,(e|x)^(v|z)^(t|u)|0,n^(l|D)|0)|0;n=D;f=oe(L|0,f|0,p|0,o|0)|0;L=D;c[G>>2]=f;c[G+4>>2]=L;o=oe(l|0,n|0,p|0,o|0)|0;p=D;c[m>>2]=o;c[m+4>>2]=p;n=Rd(f|0,L|0,14)|0;l=D;u=Pd(f|0,L|0,50)|0;l=l|D;t=Rd(f|0,L|0,18)|0;z=D;v=Pd(f|0,L|0,46)|0;z=l^(z|D);l=Rd(f|0,L|0,41)|0;x=D;e=Pd(f|0,L|0,23)|0;x=z^(x|D);z=c[h+80+552>>2]|0;J=c[h+80+552+4>>2]|0;F=oe(I|0,F|0,-1563912026,174292421)|0;x=oe(F|0,D|0,(n|u)^(t|v)^(l|e)|0,x|0)|0;J=oe(x|0,D|0,z|0,J|0)|0;J=oe(J|0,D|0,(j^y)&f^j|0,(s^q)&L^s|0)|0;z=D;x=Rd(o|0,p|0,28)|0;e=D;l=Pd(o|0,p|0,36)|0;e=e|D;v=Rd(o|0,p|0,34)|0;t=D;u=Pd(o|0,p|0,30)|0;t=e^(t|D);e=Rd(o|0,p|0,39)|0;n=D;F=Pd(o|0,p|0,25)|0;I=c[A>>2]|0;E=c[A+4>>2]|0;n=oe((I|b)&o|I&b|0,(E|H)&p|E&H|0,(x|l)^(v|u)^(e|F)|0,t^(n|D)|0)|0;t=D;r=oe(K|0,r|0,J|0,z|0)|0;K=D;c[k>>2]=r;c[k+4>>2]=K;z=oe(n|0,t|0,J|0,z|0)|0;J=D;c[B>>2]=z;c[B+4>>2]=J;t=Rd(r|0,K|0,14)|0;n=D;F=Pd(r|0,K|0,50)|0;n=n|D;e=Rd(r|0,K|0,18)|0;u=D;v=Pd(r|0,K|0,46)|0;u=n^(u|D);n=Rd(r|0,K|0,41)|0;l=D;x=Pd(r|0,K|0,23)|0;l=u^(l|D);u=c[h+80+560>>2]|0;H=c[h+80+560+4>>2]|0;s=oe(j|0,s|0,-1090974290,289380356)|0;l=oe(s|0,D|0,(t|F)^(e|v)^(n|x)|0,l|0)|0;H=oe(l|0,D|0,u|0,H|0)|0;H=oe(H|0,D|0,(y^f)&r^y|0,(q^L)&K^q|0)|0;u=D;l=Rd(z|0,J|0,28)|0;x=D;n=Pd(z|0,J|0,36)|0;x=x|D;v=Rd(z|0,J|0,34)|0;e=D;F=Pd(z|0,J|0,30)|0;e=x^(e|D);x=Rd(z|0,J|0,39)|0;t=D;s=Pd(z|0,J|0,25)|0;j=c[w>>2]|0;b=c[w+4>>2]|0;t=oe((j|o)&z|j&o|0,(b|p)&J|b&p|0,(l|n)^(v|F)^(x|s)|0,e^(t|D)|0)|0;e=D;E=oe(I|0,E|0,H|0,u|0)|0;I=D;c[A>>2]=E;c[A+4>>2]=I;u=oe(t|0,e|0,H|0,u|0)|0;H=D;c[C>>2]=u;c[C+4>>2]=H;e=Rd(E|0,I|0,14)|0;t=D;s=Pd(E|0,I|0,50)|0;t=t|D;x=Rd(E|0,I|0,18)|0;F=D;v=Pd(E|0,I|0,46)|0;F=t^(F|D);t=Rd(E|0,I|0,41)|0;n=D;l=Pd(E|0,I|0,23)|0;n=F^(n|D);F=c[h+80+568>>2]|0;p=c[h+80+568+4>>2]|0;q=oe(y|0,q|0,320620315,460393269)|0;n=oe(q|0,D|0,(e|s)^(x|v)^(t|l)|0,n|0)|0;p=oe(n|0,D|0,F|0,p|0)|0;p=oe(p|0,D|0,(f^r)&E^f|0,(L^K)&I^L|0)|0;F=D;n=Rd(u|0,H|0,28)|0;l=D;t=Pd(u|0,H|0,36)|0;l=l|D;v=Rd(u|0,H|0,34)|0;x=D;s=Pd(u|0,H|0,30)|0;x=l^(x|D);l=Rd(u|0,H|0,39)|0;e=D;q=Pd(u|0,H|0,25)|0;y=c[m>>2]|0;o=c[m+4>>2]|0;e=oe((y|z)&u|y&z|0,(o|J)&H|o&J|0,(n|t)^(v|s)^(l|q)|0,x^(e|D)|0)|0;x=D;b=oe(j|0,b|0,p|0,F|0)|0;j=D;c[w>>2]=b;c[w+4>>2]=j;F=oe(e|0,x|0,p|0,F|0)|0;p=D;c[h+16>>2]=F;c[h+16+4>>2]=p;x=Rd(b|0,j|0,14)|0;e=D;q=Pd(b|0,j|0,50)|0;e=e|D;l=Rd(b|0,j|0,18)|0;s=D;v=Pd(b|0,j|0,46)|0;s=e^(s|D);e=Rd(b|0,j|0,41)|0;t=D;n=Pd(b|0,j|0,23)|0;t=s^(t|D);s=c[h+80+576>>2]|0;J=c[h+80+576+4>>2]|0;L=oe(f|0,L|0,587496836,685471733)|0;t=oe(L|0,D|0,(x|q)^(l|v)^(e|n)|0,t|0)|0;J=oe(t|0,D|0,s|0,J|0)|0;J=oe(J|0,D|0,(r^E)&b^r|0,(K^I)&j^K|0)|0;s=D;t=Rd(F|0,p|0,28)|0;n=D;e=Pd(F|0,p|0,36)|0;n=n|D;v=Rd(F|0,p|0,34)|0;l=D;q=Pd(F|0,p|0,30)|0;l=n^(l|D);n=Rd(F|0,p|0,39)|0;x=D;L=Pd(F|0,p|0,25)|0;f=c[B>>2]|0;z=c[B+4>>2]|0;x=oe((f|u)&F|f&u|0,(z|H)&p|z&H|0,(t|e)^(v|q)^(n|L)|0,l^(x|D)|0)|0;l=D;o=oe(y|0,o|0,J|0,s|0)|0;y=D;c[m>>2]=o;c[m+4>>2]=y;s=oe(x|0,l|0,J|0,s|0)|0;J=D;c[G>>2]=s;c[G+4>>2]=J;l=Rd(o|0,y|0,14)|0;x=D;L=Pd(o|0,y|0,50)|0;x=x|D;n=Rd(o|0,y|0,18)|0;q=D;v=Pd(o|0,y|0,46)|0;q=x^(q|D);x=Rd(o|0,y|0,41)|0;e=D;t=Pd(o|0,y|0,23)|0;e=q^(e|D);q=c[h+80+584>>2]|0;H=c[h+80+584+4>>2]|0;K=oe(r|0,K|0,1086792851,852142971)|0;e=oe(K|0,D|0,(l|L)^(n|v)^(x|t)|0,e|0)|0;H=oe(e|0,D|0,q|0,H|0)|0;H=oe(H|0,D|0,(E^b)&o^E|0,(I^j)&y^I|0)|0;q=D;e=Rd(s|0,J|0,28)|0;t=D;x=Pd(s|0,J|0,36)|0;t=t|D;v=Rd(s|0,J|0,34)|0;n=D;L=Pd(s|0,J|0,30)|0;n=t^(n|D);t=Rd(s|0,J|0,39)|0;l=D;K=Pd(s|0,J|0,25)|0;r=c[C>>2]|0;u=c[C+4>>2]|0;l=oe((r|F)&s|r&F|0,(u|p)&J|u&p|0,(e|x)^(v|L)^(t|K)|0,n^(l|D)|0)|0;n=D;z=oe(f|0,z|0,H|0,q|0)|0;f=D;c[B>>2]=z;c[B+4>>2]=f;q=oe(l|0,n|0,H|0,q|0)|0;H=D;c[k>>2]=q;c[k+4>>2]=H;n=Rd(z|0,f|0,14)|0;l=D;K=Pd(z|0,f|0,50)|0;l=l|D;t=Rd(z|0,f|0,18)|0;L=D;v=Pd(z|0,f|0,46)|0;L=l^(L|D);l=Rd(z|0,f|0,41)|0;x=D;e=Pd(z|0,f|0,23)|0;x=L^(x|D);L=c[h+80+592>>2]|0;p=c[h+80+592+4>>2]|0;I=oe(E|0,I|0,365543100,1017036298)|0;x=oe(I|0,D|0,(n|K)^(t|v)^(l|e)|0,x|0)|0;p=oe(x|0,D|0,L|0,p|0)|0;p=oe(p|0,D|0,(b^o)&z^b|0,(j^y)&f^j|0)|0;L=D;x=Rd(q|0,H|0,28)|0;e=D;l=Pd(q|0,H|0,36)|0;e=e|D;v=Rd(q|0,H|0,34)|0;t=D;K=Pd(q|0,H|0,30)|0;t=e^(t|D);e=Rd(q|0,H|0,39)|0;n=D;I=Pd(q|0,H|0,25)|0;E=c[h+16>>2]|0;F=c[h+16+4>>2]|0;n=oe((E|s)&q|E&s|0,(F|J)&H|F&J|0,(x|l)^(v|K)^(e|I)|0,t^(n|D)|0)|0;t=D;u=oe(r|0,u|0,p|0,L|0)|0;r=D;c[C>>2]=u;c[C+4>>2]=r;L=oe(n|0,t|0,p|0,L|0)|0;p=D;c[A>>2]=L;c[A+4>>2]=p;t=Rd(u|0,r|0,14)|0;n=D;I=Pd(u|0,r|0,50)|0;n=n|D;e=Rd(u|0,r|0,18)|0;K=D;v=Pd(u|0,r|0,46)|0;K=n^(K|D);n=Rd(u|0,r|0,41)|0;l=D;x=Pd(u|0,r|0,23)|0;l=K^(l|D);K=c[h+80+600>>2]|0;J=c[h+80+600+4>>2]|0;j=oe(b|0,j|0,-1676669620,1126000580)|0;l=oe(j|0,D|0,(t|I)^(e|v)^(n|x)|0,l|0)|0;J=oe(l|0,D|0,K|0,J|0)|0;J=oe(J|0,D|0,(o^z)&u^o|0,(y^f)&r^y|0)|0;K=D;l=Rd(L|0,p|0,28)|0;x=D;n=Pd(L|0,p|0,36)|0;x=x|D;v=Rd(L|0,p|0,34)|0;e=D;I=Pd(L|0,p|0,30)|0;e=x^(e|D);x=Rd(L|0,p|0,39)|0;t=D;j=Pd(L|0,p|0,25)|0;b=c[G>>2]|0;s=c[G+4>>2]|0;t=oe((b|q)&L|b&q|0,(s|H)&p|s&H|0,(l|n)^(v|I)^(x|j)|0,e^(t|D)|0)|0;e=D;F=oe(E|0,F|0,J|0,K|0)|0;E=D;c[h+16>>2]=F;c[h+16+4>>2]=E;K=oe(t|0,e|0,J|0,K|0)|0;J=D;c[w>>2]=K;c[w+4>>2]=J;e=Rd(F|0,E|0,14)|0;t=D;j=Pd(F|0,E|0,50)|0;t=t|D;x=Rd(F|0,E|0,18)|0;I=D;v=Pd(F|0,E|0,46)|0;I=t^(I|D);t=Rd(F|0,E|0,41)|0;n=D;l=Pd(F|0,E|0,23)|0;n=I^(n|D);I=c[h+80+608>>2]|0;H=c[h+80+608+4>>2]|0;y=oe(o|0,y|0,-885112138,1288033470)|0;n=oe(y|0,D|0,(e|j)^(x|v)^(t|l)|0,n|0)|0;H=oe(n|0,D|0,I|0,H|0)|0;H=oe(H|0,D|0,(z^u)&F^z|0,(f^r)&E^f|0)|0;I=D;n=Rd(K|0,J|0,28)|0;l=D;t=Pd(K|0,J|0,36)|0;l=l|D;v=Rd(K|0,J|0,34)|0;x=D;j=Pd(K|0,J|0,30)|0;x=l^(x|D);l=Rd(K|0,J|0,39)|0;e=D;y=Pd(K|0,J|0,25)|0;o=c[k>>2]|0;q=c[k+4>>2]|0;e=oe((o|L)&K|o&L|0,(q|p)&J|q&p|0,(n|t)^(v|j)^(l|y)|0,x^(e|D)|0)|0;x=D;s=oe(b|0,s|0,H|0,I|0)|0;b=D;c[G>>2]=s;c[G+4>>2]=b;I=oe(e|0,x|0,H|0,I|0)|0;H=D;c[m>>2]=I;c[m+4>>2]=H;x=Rd(s|0,b|0,14)|0;e=D;G=Pd(s|0,b|0,50)|0;e=e|D;y=Rd(s|0,b|0,18)|0;l=D;j=Pd(s|0,b|0,46)|0;l=e^(l|D);e=Rd(s|0,b|0,41)|0;v=D;t=Pd(s|0,b|0,23)|0;v=l^(v|D);l=c[h+80+616>>2]|0;n=c[h+80+616+4>>2]|0;f=oe(z|0,f|0,-60457430,1501505948)|0;v=oe(f|0,D|0,(x|G)^(y|j)^(e|t)|0,v|0)|0;n=oe(v|0,D|0,l|0,n|0)|0;n=oe(n|0,D|0,(u^F)&s^u|0,(r^E)&b^r|0)|0;l=D;v=Rd(I|0,H|0,28)|0;t=D;e=Pd(I|0,H|0,36)|0;t=t|D;j=Rd(I|0,H|0,34)|0;y=D;G=Pd(I|0,H|0,30)|0;y=t^(y|D);t=Rd(I|0,H|0,39)|0;x=D;f=Pd(I|0,H|0,25)|0;z=c[A>>2]|0;p=c[A+4>>2]|0;x=oe((z|K)&I|z&K|0,(p|J)&H|p&J|0,(v|e)^(j|G)^(t|f)|0,y^(x|D)|0)|0;y=D;q=oe(o|0,q|0,n|0,l|0)|0;o=D;c[k>>2]=q;c[k+4>>2]=o;l=oe(x|0,y|0,n|0,l|0)|0;n=D;c[B>>2]=l;c[B+4>>2]=n;B=Rd(q|0,o|0,14)|0;y=D;x=Pd(q|0,o|0,50)|0;y=y|D;k=Rd(q|0,o|0,18)|0;f=D;t=Pd(q|0,o|0,46)|0;f=y^(f|D);y=Rd(q|0,o|0,41)|0;G=D;j=Pd(q|0,o|0,23)|0;G=f^(G|D);f=c[h+80+624>>2]|0;e=c[h+80+624+4>>2]|0;r=oe(u|0,r|0,987167468,1607167915)|0;G=oe(r|0,D|0,(B|x)^(k|t)^(y|j)|0,G|0)|0;e=oe(G|0,D|0,f|0,e|0)|0;e=oe(e|0,D|0,(F^s)&q^F|0,(E^b)&o^E|0)|0;f=D;G=Rd(l|0,n|0,28)|0;j=D;y=Pd(l|0,n|0,36)|0;j=j|D;t=Rd(l|0,n|0,34)|0;k=D;x=Pd(l|0,n|0,30)|0;k=j^(k|D);j=Rd(l|0,n|0,39)|0;B=D;r=Pd(l|0,n|0,25)|0;u=c[w>>2]|0;v=c[w+4>>2]|0;B=oe((u|I)&l|u&I|0,(v|H)&n|v&H|0,(G|y)^(t|x)^(j|r)|0,k^(B|D)|0)|0;k=D;p=oe(z|0,p|0,e|0,f|0)|0;z=D;c[A>>2]=p;c[A+4>>2]=z;f=oe(B|0,k|0,e|0,f|0)|0;e=D;c[C>>2]=f;c[C+4>>2]=e;C=Rd(p|0,z|0,14)|0;k=D;B=Pd(p|0,z|0,50)|0;k=k|D;A=Rd(p|0,z|0,18)|0;r=D;j=Pd(p|0,z|0,46)|0;r=k^(r|D);k=Rd(p|0,z|0,41)|0;x=D;t=Pd(p|0,z|0,23)|0;x=r^(x|D);r=c[h+80+632>>2]|0;y=c[h+80+632+4>>2]|0;E=oe(F|0,E|0,1246189591,1816402316)|0;x=oe(E|0,D|0,(C|B)^(A|j)^(k|t)|0,x|0)|0;y=oe(x|0,D|0,r|0,y|0)|0;b=oe(y|0,D|0,(s^q)&p^s|0,(b^o)&z^b|0)|0;z=D;c[h+8>>2]=b;c[h+8+4>>2]=z;o=Rd(f|0,e|0,28)|0;s=D;p=Pd(f|0,e|0,36)|0;s=s|D;q=Rd(f|0,e|0,34)|0;y=D;r=Pd(f|0,e|0,30)|0;y=s^(y|D);s=Rd(f|0,e|0,39)|0;x=D;t=Pd(f|0,e|0,25)|0;k=c[m>>2]|0;m=c[m+4>>2]|0;x=oe((k|l)&f|k&l|0,(m|n)&e|m&n|0,(o|p)^(q|r)^(s|t)|0,y^(x|D)|0)|0;y=D;c[h>>2]=x;c[h+4>>2]=y;v=oe(u|0,v|0,b|0,z|0)|0;c[w>>2]=v;c[w+4>>2]=D;z=oe(x|0,y|0,b|0,z|0)|0;b=D;c[h+16>>2]=z;c[h+16+4>>2]=b;b=oe(c[a>>2]|0,c[a+4>>2]|0,z|0,b|0)|0;c[a>>2]=b;c[a+4>>2]=D;b=1;while(1){M=a+(b<<3)|0;e=oe(c[M>>2]|0,c[M+4>>2]|0,f|0,e|0)|0;c[M>>2]=e;c[M+4>>2]=D;e=b+1|0;if((e|0)==8)break;b=e;f=c[h+16+(e<<3)>>2]|0;e=c[h+16+(e<<3)+4>>2]|0}fd(h+80|0,640);fd(h+16|0,64);fd(h+8|0,8);fd(h,8);i=g;return}function ia(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0;O=i;P=i=i+63&-64;i=i+128|0;v=d[b>>0]|d[b+1>>0]<<8|d[b+2>>0]<<16|d[b+3>>0]<<24;H=d[b+4>>0]|d[b+4+1>>0]<<8|d[b+4+2>>0]<<16|d[b+4+3>>0]<<24;h=d[b+8>>0]|d[b+8+1>>0]<<8|d[b+8+2>>0]<<16|d[b+8+3>>0]<<24;j=d[b+8+4>>0]|d[b+8+4+1>>0]<<8|d[b+8+4+2>>0]<<16|d[b+8+4+3>>0]<<24;k=d[b+16>>0]|d[b+16+1>>0]<<8|d[b+16+2>>0]<<16|d[b+16+3>>0]<<24;l=d[b+16+4>>0]|d[b+16+4+1>>0]<<8|d[b+16+4+2>>0]<<16|d[b+16+4+3>>0]<<24;m=d[b+24>>0]|d[b+24+1>>0]<<8|d[b+24+2>>0]<<16|d[b+24+3>>0]<<24;n=d[b+24+4>>0]|d[b+24+4+1>>0]<<8|d[b+24+4+2>>0]<<16|d[b+24+4+3>>0]<<24;o=d[b+32>>0]|d[b+32+1>>0]<<8|d[b+32+2>>0]<<16|d[b+32+3>>0]<<24;p=d[b+32+4>>0]|d[b+32+4+1>>0]<<8|d[b+32+4+2>>0]<<16|d[b+32+4+3>>0]<<24;q=d[b+40>>0]|d[b+40+1>>0]<<8|d[b+40+2>>0]<<16|d[b+40+3>>0]<<24;r=d[b+40+4>>0]|d[b+40+4+1>>0]<<8|d[b+40+4+2>>0]<<16|d[b+40+4+3>>0]<<24;s=d[b+48>>0]|d[b+48+1>>0]<<8|d[b+48+2>>0]<<16|d[b+48+3>>0]<<24;t=d[b+48+4>>0]|d[b+48+4+1>>0]<<8|d[b+48+4+2>>0]<<16|d[b+48+4+3>>0]<<24;u=d[b+56>>0]|d[b+56+1>>0]<<8|d[b+56+2>>0]<<16|d[b+56+3>>0]<<24;w=d[b+56+4>>0]|d[b+56+4+1>>0]<<8|d[b+56+4+2>>0]<<16|d[b+56+4+3>>0]<<24;x=d[b+64>>0]|d[b+64+1>>0]<<8|d[b+64+2>>0]<<16|d[b+64+3>>0]<<24;y=d[b+64+4>>0]|d[b+64+4+1>>0]<<8|d[b+64+4+2>>0]<<16|d[b+64+4+3>>0]<<24;z=d[b+72>>0]|d[b+72+1>>0]<<8|d[b+72+2>>0]<<16|d[b+72+3>>0]<<24;A=d[b+72+4>>0]|d[b+72+4+1>>0]<<8|d[b+72+4+2>>0]<<16|d[b+72+4+3>>0]<<24;B=d[b+80>>0]|d[b+80+1>>0]<<8|d[b+80+2>>0]<<16|d[b+80+3>>0]<<24;C=d[b+80+4>>0]|d[b+80+4+1>>0]<<8|d[b+80+4+2>>0]<<16|d[b+80+4+3>>0]<<24;E=d[b+88>>0]|d[b+88+1>>0]<<8|d[b+88+2>>0]<<16|d[b+88+3>>0]<<24;F=d[b+88+4>>0]|d[b+88+4+1>>0]<<8|d[b+88+4+2>>0]<<16|d[b+88+4+3>>0]<<24;G=d[b+96>>0]|d[b+96+1>>0]<<8|d[b+96+2>>0]<<16|d[b+96+3>>0]<<24;I=d[b+96+4>>0]|d[b+96+4+1>>0]<<8|d[b+96+4+2>>0]<<16|d[b+96+4+3>>0]<<24;J=d[b+104>>0]|d[b+104+1>>0]<<8|d[b+104+2>>0]<<16|d[b+104+3>>0]<<24;K=d[b+104+4>>0]|d[b+104+4+1>>0]<<8|d[b+104+4+2>>0]<<16|d[b+104+4+3>>0]<<24;L=d[b+112>>0]|d[b+112+1>>0]<<8|d[b+112+2>>0]<<16|d[b+112+3>>0]<<24;M=d[b+112+4>>0]|d[b+112+4+1>>0]<<8|d[b+112+4+2>>0]<<16|d[b+112+4+3>>0]<<24;N=d[b+120>>0]|d[b+120+1>>0]<<8|d[b+120+2>>0]<<16|d[b+120+3>>0]<<24;b=d[b+120+4>>0]|d[b+120+4+1>>0]<<8|d[b+120+4+2>>0]<<16|d[b+120+4+3>>0]<<24;e=P;f=a;g=e+64|0;do{c[e>>2]=c[f>>2];e=e+4|0;f=f+4|0}while((e|0)<(g|0));c[P+80>>2]=-23791573;c[P+80+4>>2]=1013904242;c[P+88>>2]=1595750129;c[P+88+4>>2]=-1521486534;Y=c[a+64>>2]^-1377402159;ha=c[a+64+4>>2]^1359893119;$=c[a+72>>2]^725511199;R=c[a+72+4>>2]^-1694144372;V=c[a+80>>2]^-79577749;ba=c[a+80+4>>2]^528734635;ka=c[a+88>>2]^327033209;ga=c[a+88+4>>2]^1541459225;c[P+120>>2]=ka;c[P+120+4>>2]=ga;X=c[P+32>>2]|0;da=c[P+32+4>>2]|0;la=oe(X|0,da|0,c[P>>2]|0,c[P+4>>2]|0)|0;la=oe(la|0,D|0,v|0,H|0)|0;ja=D;U=oe(ha^ja|0,Y^la|0,-205731576,1779033703)|0;ea=D;Z=Rd(X^U|0,da^ea|0,24)|0;e=D;da=Pd(X^U|0,da^ea|0,40)|0;e=D|e;X=oe(da|Z|0,e|0,la|0,ja|0)|0;X=oe(X|0,D|0,h|0,j|0)|0;Q=D;c[P>>2]=X;c[P+4>>2]=Q;_=Rd(ha^ja^X|0,Y^la^Q|0,16)|0;g=D;la=Pd(ha^ja^X|0,Y^la^Q|0,48)|0;g=D|g;c[P+96>>2]=la|_;c[P+96+4>>2]=g;ea=oe(la|_|0,g|0,U|0,ea|0)|0;U=D;c[P+64>>2]=ea;c[P+64+4>>2]=U;g=Rd((da|Z)^ea|0,e^U|0,63)|0;_=D;U=Pd((da|Z)^ea|0,e^U|0,1)|0;c[P+32>>2]=U|g;c[P+32+4>>2]=D|_;_=c[P+40>>2]|0;g=c[P+40+4>>2]|0;U=oe(_|0,g|0,c[P+8>>2]|0,c[P+8+4>>2]|0)|0;U=oe(U|0,D|0,k|0,l|0)|0;e=D;ea=oe(R^e|0,$^U|0,-2067093701,-1150833019)|0;Z=D;da=Rd(_^ea|0,g^Z|0,24)|0;la=D;g=Pd(_^ea|0,g^Z|0,40)|0;la=D|la;_=oe(g|da|0,la|0,U|0,e|0)|0;_=oe(_|0,D|0,m|0,n|0)|0;Y=D;c[P+8>>2]=_;c[P+8+4>>2]=Y;ja=Rd(R^e^_|0,$^U^Y|0,16)|0;ha=D;U=Pd(R^e^_|0,$^U^Y|0,48)|0;ha=D|ha;c[P+104>>2]=U|ja;c[P+104+4>>2]=ha;Z=oe(U|ja|0,ha|0,ea|0,Z|0)|0;ea=D;c[P+72>>2]=Z;c[P+72+4>>2]=ea;ha=Rd((g|da)^Z|0,la^ea|0,63)|0;ja=D;ea=Pd((g|da)^Z|0,la^ea|0,1)|0;ja=D|ja;la=c[P+48>>2]|0;Z=c[P+48+4>>2]|0;da=oe(la|0,Z|0,c[P+16>>2]|0,c[P+16+4>>2]|0)|0;da=oe(da|0,D|0,o|0,p|0)|0;g=D;U=oe(ba^g|0,V^da|0,-23791573,1013904242)|0;$=D;e=Rd(la^U|0,Z^$|0,24)|0;R=D;Z=Pd(la^U|0,Z^$|0,40)|0;R=D|R;la=oe(Z|e|0,R|0,da|0,g|0)|0;la=oe(la|0,D|0,q|0,r|0)|0;W=D;c[P+16>>2]=la;c[P+16+4>>2]=W;ia=Rd(ba^g^la|0,V^da^W|0,16)|0;fa=D;da=Pd(ba^g^la|0,V^da^W|0,48)|0;fa=D|fa;c[P+112>>2]=da|ia;c[P+112+4>>2]=fa;$=oe(da|ia|0,fa|0,U|0,$|0)|0;U=D;fa=Rd((Z|e)^$|0,R^U|0,63)|0;ia=D;R=Pd((Z|e)^$|0,R^U|0,1)|0;ia=D|ia;e=c[P+56>>2]|0;Z=c[P+56+4>>2]|0;da=oe(e|0,Z|0,c[P+24>>2]|0,c[P+24+4>>2]|0)|0;da=oe(da|0,D|0,s|0,t|0)|0;V=D;g=oe(ga^V|0,ka^da|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;ba=D;f=Rd(e^g|0,Z^ba|0,24)|0;aa=D;Z=Pd(e^g|0,Z^ba|0,40)|0;aa=D|aa;e=oe(Z|f|0,aa|0,da|0,V|0)|0;e=oe(e|0,D|0,u|0,w|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ca=Rd(ga^V^e|0,ka^da^S|0,16)|0;ma=D;da=Pd(ga^V^e|0,ka^da^S|0,48)|0;ma=D|ma;ba=oe(da|ca|0,ma|0,g|0,ba|0)|0;g=D;ka=Rd((Z|f)^ba|0,aa^g|0,63)|0;V=D;aa=Pd((Z|f)^ba|0,aa^g|0,1)|0;V=D|V;Q=oe(ea|ha|0,ja|0,X|0,Q|0)|0;Q=oe(Q|0,D|0,x|0,y|0)|0;X=D;U=oe(ma^X|0,(da|ca)^Q|0,$|0,U|0)|0;$=D;f=Rd((ea|ha)^U|0,ja^$|0,24)|0;Z=D;ja=Pd((ea|ha)^U|0,ja^$|0,40)|0;Z=D|Z;ha=oe(ja|f|0,Z|0,Q|0,X|0)|0;ha=oe(ha|0,D|0,z|0,A|0)|0;ea=D;c[P>>2]=ha;c[P+4>>2]=ea;ga=Rd(ma^X^ha|0,(da|ca)^Q^ea|0,16)|0;T=D;Q=Pd(ma^X^ha|0,(da|ca)^Q^ea|0,48)|0;T=D|T;c[P+120>>2]=Q|ga;c[P+120+4>>2]=T;$=oe(Q|ga|0,T|0,U|0,$|0)|0;U=D;c[P+80>>2]=$;c[P+80+4>>2]=U;T=Rd((ja|f)^$|0,Z^U|0,63)|0;ga=D;U=Pd((ja|f)^$|0,Z^U|0,1)|0;c[P+40>>2]=U|T;c[P+40+4>>2]=D|ga;Y=oe(R|fa|0,ia|0,_|0,Y|0)|0;Y=oe(Y|0,D|0,B|0,C|0)|0;_=D;ga=c[P+96>>2]^Y;T=c[P+96+4>>2]^_;g=oe(T|0,ga|0,ba|0,g|0)|0;ba=D;U=Rd((R|fa)^g|0,ia^ba|0,24)|0;Z=D;ia=Pd((R|fa)^g|0,ia^ba|0,40)|0;Z=D|Z;_=oe(ia|U|0,Z|0,Y|0,_|0)|0;_=oe(_|0,D|0,E|0,F|0)|0;Y=D;c[P+8>>2]=_;c[P+8+4>>2]=Y;fa=Rd(T^_|0,ga^Y|0,16)|0;R=D;ga=Pd(T^_|0,ga^Y|0,48)|0;R=D|R;ba=oe(ga|fa|0,R|0,g|0,ba|0)|0;g=D;c[P+88>>2]=ba;c[P+88+4>>2]=g;T=Rd((ia|U)^ba|0,Z^g|0,63)|0;$=D;g=Pd((ia|U)^ba|0,Z^g|0,1)|0;c[P+48>>2]=g|T;c[P+48+4>>2]=D|$;W=oe(aa|ka|0,V|0,la|0,W|0)|0;W=oe(W|0,D|0,G|0,I|0)|0;la=D;$=c[P+104>>2]^W;T=c[P+104+4>>2]^la;g=oe(T|0,$|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;Z=D;ba=Rd((aa|ka)^g|0,V^Z|0,24)|0;U=D;V=Pd((aa|ka)^g|0,V^Z|0,40)|0;U=D|U;la=oe(V|ba|0,U|0,W|0,la|0)|0;la=oe(la|0,D|0,J|0,K|0)|0;W=D;c[P+16>>2]=la;c[P+16+4>>2]=W;ka=Rd(T^la|0,$^W|0,16)|0;aa=D;$=Pd(T^la|0,$^W|0,48)|0;aa=D|aa;Z=oe($|ka|0,aa|0,g|0,Z|0)|0;g=D;T=Rd((V|ba)^Z|0,U^g|0,63)|0;ia=D;U=Pd((V|ba)^Z|0,U^g|0,1)|0;c[P+56>>2]=U|T;c[P+56+4>>2]=D|ia;ia=c[P+32>>2]|0;T=c[P+32+4>>2]|0;S=oe(ia|0,T|0,e|0,S|0)|0;S=oe(S|0,D|0,L|0,M|0)|0;e=D;U=c[P+112>>2]^S;ba=c[P+112+4>>2]^e;V=oe(ba|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;f=D;ja=Rd(ia^V|0,T^f|0,24)|0;Q=D;T=Pd(ia^V|0,T^f|0,40)|0;Q=D|Q;e=oe(T|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,N|0,b|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ia=Rd(ba^e|0,U^S|0,16)|0;ca=D;U=Pd(ba^e|0,U^S|0,48)|0;ca=D|ca;f=oe(U|ia|0,ca|0,V|0,f|0)|0;V=D;ba=Rd((T|ja)^f|0,Q^V|0,63)|0;da=D;Q=Pd((T|ja)^f|0,Q^V|0,1)|0;da=D|da;ea=oe(Q|ba|0,da|0,ha|0,ea|0)|0;ea=oe(ea|0,D|0,L|0,M|0)|0;ha=D;g=oe(R^ha|0,(ga|fa)^ea|0,Z|0,g|0)|0;Z=D;ja=Rd((Q|ba)^g|0,da^Z|0,24)|0;T=D;da=Pd((Q|ba)^g|0,da^Z|0,40)|0;T=D|T;ba=oe(da|ja|0,T|0,ea|0,ha|0)|0;ba=oe(ba|0,D|0,B|0,C|0)|0;Q=D;c[P>>2]=ba;c[P+4>>2]=Q;X=Rd(R^ha^ba|0,(ga|fa)^ea^Q|0,16)|0;ma=D;ea=Pd(R^ha^ba|0,(ga|fa)^ea^Q|0,48)|0;ma=D|ma;c[P+96>>2]=ea|X;c[P+96+4>>2]=ma;Z=oe(ea|X|0,ma|0,g|0,Z|0)|0;g=D;c[P+64>>2]=Z;c[P+64+4>>2]=g;ma=Rd((da|ja)^Z|0,T^g|0,63)|0;X=D;g=Pd((da|ja)^Z|0,T^g|0,1)|0;c[P+32>>2]=g|ma;c[P+32+4>>2]=D|X;X=c[P+40>>2]|0;ma=c[P+40+4>>2]|0;Y=oe(X|0,ma|0,_|0,Y|0)|0;Y=oe(Y|0,D|0,o|0,p|0)|0;_=D;V=oe(aa^_|0,($|ka)^Y|0,f|0,V|0)|0;f=D;g=Rd(X^V|0,ma^f|0,24)|0;T=D;ma=Pd(X^V|0,ma^f|0,40)|0;T=D|T;X=oe(ma|g|0,T|0,Y|0,_|0)|0;X=oe(X|0,D|0,x|0,y|0)|0;Z=D;c[P+8>>2]=X;c[P+8+4>>2]=Z;ja=Rd(aa^_^X|0,($|ka)^Y^Z|0,16)|0;da=D;Y=Pd(aa^_^X|0,($|ka)^Y^Z|0,48)|0;da=D|da;c[P+104>>2]=Y|ja;c[P+104+4>>2]=da;f=oe(Y|ja|0,da|0,V|0,f|0)|0;V=D;c[P+72>>2]=f;c[P+72+4>>2]=V;da=Rd((ma|g)^f|0,T^V|0,63)|0;ja=D;V=Pd((ma|g)^f|0,T^V|0,1)|0;ja=D|ja;T=c[P+48>>2]|0;f=c[P+48+4>>2]|0;W=oe(T|0,f|0,la|0,W|0)|0;W=oe(W|0,D|0,z|0,A|0)|0;la=D;g=oe(ca^la|0,(U|ia)^W|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;ma=D;Y=Rd(T^g|0,f^ma|0,24)|0;ka=D;f=Pd(T^g|0,f^ma|0,40)|0;ka=D|ka;T=oe(f|Y|0,ka|0,W|0,la|0)|0;T=oe(T|0,D|0,N|0,b|0)|0;$=D;c[P+16>>2]=T;c[P+16+4>>2]=$;_=Rd(ca^la^T|0,(U|ia)^W^$|0,16)|0;aa=D;W=Pd(ca^la^T|0,(U|ia)^W^$|0,48)|0;aa=D|aa;c[P+112>>2]=W|_;c[P+112+4>>2]=aa;ma=oe(W|_|0,aa|0,g|0,ma|0)|0;g=D;aa=Rd((f|Y)^ma|0,ka^g|0,63)|0;_=D;ka=Pd((f|Y)^ma|0,ka^g|0,1)|0;_=D|_;Y=c[P+56>>2]|0;f=c[P+56+4>>2]|0;S=oe(Y|0,f|0,e|0,S|0)|0;S=oe(S|0,D|0,J|0,K|0)|0;e=D;W=c[P+120>>2]^S;ia=c[P+120+4>>2]^e;U=oe(ia|0,W|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;la=D;ca=Rd(Y^U|0,f^la|0,24)|0;ea=D;f=Pd(Y^U|0,f^la|0,40)|0;ea=D|ea;e=oe(f|ca|0,ea|0,S|0,e|0)|0;e=oe(e|0,D|0,s|0,t|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Y=Rd(ia^e|0,W^S|0,16)|0;fa=D;W=Pd(ia^e|0,W^S|0,48)|0;fa=D|fa;la=oe(W|Y|0,fa|0,U|0,la|0)|0;U=D;ia=Rd((f|ca)^la|0,ea^U|0,63)|0;ga=D;ea=Pd((f|ca)^la|0,ea^U|0,1)|0;ga=D|ga;Q=oe(V|da|0,ja|0,ba|0,Q|0)|0;Q=oe(Q|0,D|0,h|0,j|0)|0;ba=D;g=oe(fa^ba|0,(W|Y)^Q|0,ma|0,g|0)|0;ma=D;ca=Rd((V|da)^g|0,ja^ma|0,24)|0;f=D;ja=Pd((V|da)^g|0,ja^ma|0,40)|0;f=D|f;da=oe(ja|ca|0,f|0,Q|0,ba|0)|0;da=oe(da|0,D|0,G|0,I|0)|0;V=D;c[P>>2]=da;c[P+4>>2]=V;ha=Rd(fa^ba^da|0,(W|Y)^Q^V|0,16)|0;R=D;Q=Pd(fa^ba^da|0,(W|Y)^Q^V|0,48)|0;R=D|R;c[P+120>>2]=Q|ha;c[P+120+4>>2]=R;ma=oe(Q|ha|0,R|0,g|0,ma|0)|0;g=D;c[P+80>>2]=ma;c[P+80+4>>2]=g;R=Rd((ja|ca)^ma|0,f^g|0,63)|0;ha=D;g=Pd((ja|ca)^ma|0,f^g|0,1)|0;c[P+40>>2]=g|R;c[P+40+4>>2]=D|ha;Z=oe(ka|aa|0,_|0,X|0,Z|0)|0;Z=oe(Z|0,D|0,v|0,H|0)|0;X=D;ha=c[P+96>>2]^Z;R=c[P+96+4>>2]^X;U=oe(R|0,ha|0,la|0,U|0)|0;la=D;g=Rd((ka|aa)^U|0,_^la|0,24)|0;f=D;_=Pd((ka|aa)^U|0,_^la|0,40)|0;f=D|f;X=oe(_|g|0,f|0,Z|0,X|0)|0;X=oe(X|0,D|0,k|0,l|0)|0;Z=D;c[P+8>>2]=X;c[P+8+4>>2]=Z;aa=Rd(R^X|0,ha^Z|0,16)|0;ka=D;ha=Pd(R^X|0,ha^Z|0,48)|0;ka=D|ka;la=oe(ha|aa|0,ka|0,U|0,la|0)|0;U=D;c[P+88>>2]=la;c[P+88+4>>2]=U;R=Rd((_|g)^la|0,f^U|0,63)|0;ma=D;U=Pd((_|g)^la|0,f^U|0,1)|0;c[P+48>>2]=U|R;c[P+48+4>>2]=D|ma;$=oe(ea|ia|0,ga|0,T|0,$|0)|0;$=oe($|0,D|0,E|0,F|0)|0;T=D;ma=c[P+104>>2]^$;R=c[P+104+4>>2]^T;U=oe(R|0,ma|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;f=D;la=Rd((ea|ia)^U|0,ga^f|0,24)|0;g=D;ga=Pd((ea|ia)^U|0,ga^f|0,40)|0;g=D|g;T=oe(ga|la|0,g|0,$|0,T|0)|0;T=oe(T|0,D|0,u|0,w|0)|0;$=D;c[P+16>>2]=T;c[P+16+4>>2]=$;ia=Rd(R^T|0,ma^$|0,16)|0;ea=D;ma=Pd(R^T|0,ma^$|0,48)|0;ea=D|ea;f=oe(ma|ia|0,ea|0,U|0,f|0)|0;U=D;R=Rd((ga|la)^f|0,g^U|0,63)|0;_=D;g=Pd((ga|la)^f|0,g^U|0,1)|0;c[P+56>>2]=g|R;c[P+56+4>>2]=D|_;_=c[P+32>>2]|0;R=c[P+32+4>>2]|0;S=oe(_|0,R|0,e|0,S|0)|0;S=oe(S|0,D|0,q|0,r|0)|0;e=D;g=c[P+112>>2]^S;la=c[P+112+4>>2]^e;ga=oe(la|0,g|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;ca=D;ja=Rd(_^ga|0,R^ca|0,24)|0;Q=D;R=Pd(_^ga|0,R^ca|0,40)|0;Q=D|Q;e=oe(R|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,m|0,n|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;_=Rd(la^e|0,g^S|0,16)|0;Y=D;g=Pd(la^e|0,g^S|0,48)|0;Y=D|Y;ca=oe(g|_|0,Y|0,ga|0,ca|0)|0;ga=D;la=Rd((R|ja)^ca|0,Q^ga|0,63)|0;W=D;Q=Pd((R|ja)^ca|0,Q^ga|0,1)|0;W=D|W;V=oe(Q|la|0,W|0,da|0,V|0)|0;V=oe(V|0,D|0,E|0,F|0)|0;da=D;U=oe(ka^da|0,(ha|aa)^V|0,f|0,U|0)|0;f=D;ja=Rd((Q|la)^U|0,W^f|0,24)|0;R=D;W=Pd((Q|la)^U|0,W^f|0,40)|0;R=D|R;la=oe(W|ja|0,R|0,V|0,da|0)|0;la=oe(la|0,D|0,x|0,y|0)|0;Q=D;c[P>>2]=la;c[P+4>>2]=Q;ba=Rd(ka^da^la|0,(ha|aa)^V^Q|0,16)|0;fa=D;V=Pd(ka^da^la|0,(ha|aa)^V^Q|0,48)|0;fa=D|fa;c[P+96>>2]=V|ba;c[P+96+4>>2]=fa;f=oe(V|ba|0,fa|0,U|0,f|0)|0;U=D;c[P+64>>2]=f;c[P+64+4>>2]=U;fa=Rd((W|ja)^f|0,R^U|0,63)|0;ba=D;U=Pd((W|ja)^f|0,R^U|0,1)|0;c[P+32>>2]=U|fa;c[P+32+4>>2]=D|ba;ba=c[P+40>>2]|0;fa=c[P+40+4>>2]|0;Z=oe(ba|0,fa|0,X|0,Z|0)|0;Z=oe(Z|0,D|0,G|0,I|0)|0;X=D;ga=oe(ea^X|0,(ma|ia)^Z|0,ca|0,ga|0)|0;ca=D;U=Rd(ba^ga|0,fa^ca|0,24)|0;R=D;fa=Pd(ba^ga|0,fa^ca|0,40)|0;R=D|R;ba=oe(fa|U|0,R|0,Z|0,X|0)|0;ba=oe(ba|0,D|0,v|0,H|0)|0;f=D;c[P+8>>2]=ba;c[P+8+4>>2]=f;ja=Rd(ea^X^ba|0,(ma|ia)^Z^f|0,16)|0;W=D;Z=Pd(ea^X^ba|0,(ma|ia)^Z^f|0,48)|0;W=D|W;c[P+104>>2]=Z|ja;c[P+104+4>>2]=W;ca=oe(Z|ja|0,W|0,ga|0,ca|0)|0;ga=D;c[P+72>>2]=ca;c[P+72+4>>2]=ga;W=Rd((fa|U)^ca|0,R^ga|0,63)|0;ja=D;ga=Pd((fa|U)^ca|0,R^ga|0,1)|0;ja=D|ja;R=c[P+48>>2]|0;ca=c[P+48+4>>2]|0;$=oe(R|0,ca|0,T|0,$|0)|0;$=oe($|0,D|0,q|0,r|0)|0;T=D;U=oe(Y^T|0,(g|_)^$|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;fa=D;Z=Rd(R^U|0,ca^fa|0,24)|0;ia=D;ca=Pd(R^U|0,ca^fa|0,40)|0;ia=D|ia;R=oe(ca|Z|0,ia|0,$|0,T|0)|0;R=oe(R|0,D|0,k|0,l|0)|0;ma=D;c[P+16>>2]=R;c[P+16+4>>2]=ma;X=Rd(Y^T^R|0,(g|_)^$^ma|0,16)|0;ea=D;$=Pd(Y^T^R|0,(g|_)^$^ma|0,48)|0;ea=D|ea;c[P+112>>2]=$|X;c[P+112+4>>2]=ea;fa=oe($|X|0,ea|0,U|0,fa|0)|0;U=D;ea=Rd((ca|Z)^fa|0,ia^U|0,63)|0;X=D;ia=Pd((ca|Z)^fa|0,ia^U|0,1)|0;X=D|X;Z=c[P+56>>2]|0;ca=c[P+56+4>>2]|0;S=oe(Z|0,ca|0,e|0,S|0)|0;S=oe(S|0,D|0,N|0,b|0)|0;e=D;$=c[P+120>>2]^S;_=c[P+120+4>>2]^e;g=oe(_|0,$|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;T=D;Y=Rd(Z^g|0,ca^T|0,24)|0;V=D;ca=Pd(Z^g|0,ca^T|0,40)|0;V=D|V;e=oe(ca|Y|0,V|0,S|0,e|0)|0;e=oe(e|0,D|0,J|0,K|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Z=Rd(_^e|0,$^S|0,16)|0;aa=D;$=Pd(_^e|0,$^S|0,48)|0;aa=D|aa;T=oe($|Z|0,aa|0,g|0,T|0)|0;g=D;_=Rd((ca|Y)^T|0,V^g|0,63)|0;ha=D;V=Pd((ca|Y)^T|0,V^g|0,1)|0;ha=D|ha;Q=oe(ga|W|0,ja|0,la|0,Q|0)|0;Q=oe(Q|0,D|0,B|0,C|0)|0;la=D;U=oe(aa^la|0,($|Z)^Q|0,fa|0,U|0)|0;fa=D;Y=Rd((ga|W)^U|0,ja^fa|0,24)|0;ca=D;ja=Pd((ga|W)^U|0,ja^fa|0,40)|0;ca=D|ca;W=oe(ja|Y|0,ca|0,Q|0,la|0)|0;W=oe(W|0,D|0,L|0,M|0)|0;ga=D;c[P>>2]=W;c[P+4>>2]=ga;da=Rd(aa^la^W|0,($|Z)^Q^ga|0,16)|0;ka=D;Q=Pd(aa^la^W|0,($|Z)^Q^ga|0,48)|0;ka=D|ka;c[P+120>>2]=Q|da;c[P+120+4>>2]=ka;fa=oe(Q|da|0,ka|0,U|0,fa|0)|0;U=D;c[P+80>>2]=fa;c[P+80+4>>2]=U;ka=Rd((ja|Y)^fa|0,ca^U|0,63)|0;da=D;U=Pd((ja|Y)^fa|0,ca^U|0,1)|0;c[P+40>>2]=U|ka;c[P+40+4>>2]=D|da;f=oe(ia|ea|0,X|0,ba|0,f|0)|0;f=oe(f|0,D|0,m|0,n|0)|0;ba=D;da=c[P+96>>2]^f;ka=c[P+96+4>>2]^ba;g=oe(ka|0,da|0,T|0,g|0)|0;T=D;U=Rd((ia|ea)^g|0,X^T|0,24)|0;ca=D;X=Pd((ia|ea)^g|0,X^T|0,40)|0;ca=D|ca;ba=oe(X|U|0,ca|0,f|0,ba|0)|0;ba=oe(ba|0,D|0,s|0,t|0)|0;f=D;c[P+8>>2]=ba;c[P+8+4>>2]=f;ea=Rd(ka^ba|0,da^f|0,16)|0;ia=D;da=Pd(ka^ba|0,da^f|0,48)|0;ia=D|ia;T=oe(da|ea|0,ia|0,g|0,T|0)|0;g=D;c[P+88>>2]=T;c[P+88+4>>2]=g;ka=Rd((X|U)^T|0,ca^g|0,63)|0;fa=D;g=Pd((X|U)^T|0,ca^g|0,1)|0;c[P+48>>2]=g|ka;c[P+48+4>>2]=D|fa;ma=oe(V|_|0,ha|0,R|0,ma|0)|0;ma=oe(ma|0,D|0,u|0,w|0)|0;R=D;fa=c[P+104>>2]^ma;ka=c[P+104+4>>2]^R;g=oe(ka|0,fa|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;ca=D;T=Rd((V|_)^g|0,ha^ca|0,24)|0;U=D;ha=Pd((V|_)^g|0,ha^ca|0,40)|0;U=D|U;R=oe(ha|T|0,U|0,ma|0,R|0)|0;R=oe(R|0,D|0,h|0,j|0)|0;ma=D;c[P+16>>2]=R;c[P+16+4>>2]=ma;_=Rd(ka^R|0,fa^ma|0,16)|0;V=D;fa=Pd(ka^R|0,fa^ma|0,48)|0;V=D|V;ca=oe(fa|_|0,V|0,g|0,ca|0)|0;g=D;ka=Rd((ha|T)^ca|0,U^g|0,63)|0;X=D;U=Pd((ha|T)^ca|0,U^g|0,1)|0;c[P+56>>2]=U|ka;c[P+56+4>>2]=D|X;X=c[P+32>>2]|0;ka=c[P+32+4>>2]|0;S=oe(X|0,ka|0,e|0,S|0)|0;S=oe(S|0,D|0,z|0,A|0)|0;e=D;U=c[P+112>>2]^S;T=c[P+112+4>>2]^e;ha=oe(T|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;Y=D;ja=Rd(X^ha|0,ka^Y|0,24)|0;Q=D;ka=Pd(X^ha|0,ka^Y|0,40)|0;Q=D|Q;e=oe(ka|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,o|0,p|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;X=Rd(T^e|0,U^S|0,16)|0;Z=D;U=Pd(T^e|0,U^S|0,48)|0;Z=D|Z;Y=oe(U|X|0,Z|0,ha|0,Y|0)|0;ha=D;T=Rd((ka|ja)^Y|0,Q^ha|0,63)|0;$=D;Q=Pd((ka|ja)^Y|0,Q^ha|0,1)|0;$=D|$;ga=oe(Q|T|0,$|0,W|0,ga|0)|0;ga=oe(ga|0,D|0,u|0,w|0)|0;W=D;g=oe(ia^W|0,(da|ea)^ga|0,ca|0,g|0)|0;ca=D;ja=Rd((Q|T)^g|0,$^ca|0,24)|0;ka=D;$=Pd((Q|T)^g|0,$^ca|0,40)|0;ka=D|ka;T=oe($|ja|0,ka|0,ga|0,W|0)|0;T=oe(T|0,D|0,z|0,A|0)|0;Q=D;c[P>>2]=T;c[P+4>>2]=Q;la=Rd(ia^W^T|0,(da|ea)^ga^Q|0,16)|0;aa=D;ga=Pd(ia^W^T|0,(da|ea)^ga^Q|0,48)|0;aa=D|aa;c[P+96>>2]=ga|la;c[P+96+4>>2]=aa;ca=oe(ga|la|0,aa|0,g|0,ca|0)|0;g=D;c[P+64>>2]=ca;c[P+64+4>>2]=g;aa=Rd(($|ja)^ca|0,ka^g|0,63)|0;la=D;g=Pd(($|ja)^ca|0,ka^g|0,1)|0;c[P+32>>2]=g|aa;c[P+32+4>>2]=D|la;la=c[P+40>>2]|0;aa=c[P+40+4>>2]|0;f=oe(la|0,aa|0,ba|0,f|0)|0;f=oe(f|0,D|0,m|0,n|0)|0;ba=D;ha=oe(V^ba|0,(fa|_)^f|0,Y|0,ha|0)|0;Y=D;g=Rd(la^ha|0,aa^Y|0,24)|0;ka=D;aa=Pd(la^ha|0,aa^Y|0,40)|0;ka=D|ka;la=oe(aa|g|0,ka|0,f|0,ba|0)|0;la=oe(la|0,D|0,h|0,j|0)|0;ca=D;c[P+8>>2]=la;c[P+8+4>>2]=ca;ja=Rd(V^ba^la|0,(fa|_)^f^ca|0,16)|0;$=D;f=Pd(V^ba^la|0,(fa|_)^f^ca|0,48)|0;$=D|$;c[P+104>>2]=f|ja;c[P+104+4>>2]=$;Y=oe(f|ja|0,$|0,ha|0,Y|0)|0;ha=D;c[P+72>>2]=Y;c[P+72+4>>2]=ha;$=Rd((aa|g)^Y|0,ka^ha|0,63)|0;ja=D;ha=Pd((aa|g)^Y|0,ka^ha|0,1)|0;ja=D|ja;ka=c[P+48>>2]|0;Y=c[P+48+4>>2]|0;ma=oe(ka|0,Y|0,R|0,ma|0)|0;ma=oe(ma|0,D|0,J|0,K|0)|0;R=D;g=oe(Z^R|0,(U|X)^ma|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;aa=D;f=Rd(ka^g|0,Y^aa|0,24)|0;_=D;Y=Pd(ka^g|0,Y^aa|0,40)|0;_=D|_;ka=oe(Y|f|0,_|0,ma|0,R|0)|0;ka=oe(ka|0,D|0,G|0,I|0)|0;fa=D;c[P+16>>2]=ka;c[P+16+4>>2]=fa;ba=Rd(Z^R^ka|0,(U|X)^ma^fa|0,16)|0;V=D;ma=Pd(Z^R^ka|0,(U|X)^ma^fa|0,48)|0;V=D|V;c[P+112>>2]=ma|ba;c[P+112+4>>2]=V;aa=oe(ma|ba|0,V|0,g|0,aa|0)|0;g=D;V=Rd((Y|f)^aa|0,_^g|0,63)|0;ba=D;_=Pd((Y|f)^aa|0,_^g|0,1)|0;ba=D|ba;f=c[P+56>>2]|0;Y=c[P+56+4>>2]|0;S=oe(f|0,Y|0,e|0,S|0)|0;S=oe(S|0,D|0,E|0,F|0)|0;e=D;ma=c[P+120>>2]^S;X=c[P+120+4>>2]^e;U=oe(X|0,ma|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;R=D;Z=Rd(f^U|0,Y^R|0,24)|0;ga=D;Y=Pd(f^U|0,Y^R|0,40)|0;ga=D|ga;e=oe(Y|Z|0,ga|0,S|0,e|0)|0;e=oe(e|0,D|0,L|0,M|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;f=Rd(X^e|0,ma^S|0,16)|0;ea=D;ma=Pd(X^e|0,ma^S|0,48)|0;ea=D|ea;R=oe(ma|f|0,ea|0,U|0,R|0)|0;U=D;X=Rd((Y|Z)^R|0,ga^U|0,63)|0;da=D;ga=Pd((Y|Z)^R|0,ga^U|0,1)|0;da=D|da;Q=oe(ha|$|0,ja|0,T|0,Q|0)|0;Q=oe(Q|0,D|0,k|0,l|0)|0;T=D;g=oe(ea^T|0,(ma|f)^Q|0,aa|0,g|0)|0;aa=D;Z=Rd((ha|$)^g|0,ja^aa|0,24)|0;Y=D;ja=Pd((ha|$)^g|0,ja^aa|0,40)|0;Y=D|Y;$=oe(ja|Z|0,Y|0,Q|0,T|0)|0;$=oe($|0,D|0,s|0,t|0)|0;ha=D;c[P>>2]=$;c[P+4>>2]=ha;W=Rd(ea^T^$|0,(ma|f)^Q^ha|0,16)|0;ia=D;Q=Pd(ea^T^$|0,(ma|f)^Q^ha|0,48)|0;ia=D|ia;c[P+120>>2]=Q|W;c[P+120+4>>2]=ia;aa=oe(Q|W|0,ia|0,g|0,aa|0)|0;g=D;c[P+80>>2]=aa;c[P+80+4>>2]=g;ia=Rd((ja|Z)^aa|0,Y^g|0,63)|0;W=D;g=Pd((ja|Z)^aa|0,Y^g|0,1)|0;c[P+40>>2]=g|ia;c[P+40+4>>2]=D|W;ca=oe(_|V|0,ba|0,la|0,ca|0)|0;ca=oe(ca|0,D|0,q|0,r|0)|0;la=D;W=c[P+96>>2]^ca;ia=c[P+96+4>>2]^la;U=oe(ia|0,W|0,R|0,U|0)|0;R=D;g=Rd((_|V)^U|0,ba^R|0,24)|0;Y=D;ba=Pd((_|V)^U|0,ba^R|0,40)|0;Y=D|Y;la=oe(ba|g|0,Y|0,ca|0,la|0)|0;la=oe(la|0,D|0,B|0,C|0)|0;ca=D;c[P+8>>2]=la;c[P+8+4>>2]=ca;V=Rd(ia^la|0,W^ca|0,16)|0;_=D;W=Pd(ia^la|0,W^ca|0,48)|0;_=D|_;R=oe(W|V|0,_|0,U|0,R|0)|0;U=D;c[P+88>>2]=R;c[P+88+4>>2]=U;ia=Rd((ba|g)^R|0,Y^U|0,63)|0;aa=D;U=Pd((ba|g)^R|0,Y^U|0,1)|0;c[P+48>>2]=U|ia;c[P+48+4>>2]=D|aa;fa=oe(ga|X|0,da|0,ka|0,fa|0)|0;fa=oe(fa|0,D|0,o|0,p|0)|0;ka=D;aa=c[P+104>>2]^fa;ia=c[P+104+4>>2]^ka;U=oe(ia|0,aa|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;Y=D;R=Rd((ga|X)^U|0,da^Y|0,24)|0;g=D;da=Pd((ga|X)^U|0,da^Y|0,40)|0;g=D|g;ka=oe(da|R|0,g|0,fa|0,ka|0)|0;ka=oe(ka|0,D|0,v|0,H|0)|0;fa=D;c[P+16>>2]=ka;c[P+16+4>>2]=fa;X=Rd(ia^ka|0,aa^fa|0,16)|0;ga=D;aa=Pd(ia^ka|0,aa^fa|0,48)|0;ga=D|ga;Y=oe(aa|X|0,ga|0,U|0,Y|0)|0;U=D;ia=Rd((da|R)^Y|0,g^U|0,63)|0;ba=D;g=Pd((da|R)^Y|0,g^U|0,1)|0;c[P+56>>2]=g|ia;c[P+56+4>>2]=D|ba;ba=c[P+32>>2]|0;ia=c[P+32+4>>2]|0;S=oe(ba|0,ia|0,e|0,S|0)|0;S=oe(S|0,D|0,N|0,b|0)|0;e=D;g=c[P+112>>2]^S;R=c[P+112+4>>2]^e;da=oe(R|0,g|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;Z=D;ja=Rd(ba^da|0,ia^Z|0,24)|0;Q=D;ia=Pd(ba^da|0,ia^Z|0,40)|0;Q=D|Q;e=oe(ia|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,x|0,y|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ba=Rd(R^e|0,g^S|0,16)|0;f=D;g=Pd(R^e|0,g^S|0,48)|0;f=D|f;Z=oe(g|ba|0,f|0,da|0,Z|0)|0;da=D;R=Rd((ia|ja)^Z|0,Q^da|0,63)|0;ma=D;Q=Pd((ia|ja)^Z|0,Q^da|0,1)|0;ma=D|ma;ha=oe(Q|R|0,ma|0,$|0,ha|0)|0;ha=oe(ha|0,D|0,z|0,A|0)|0;$=D;U=oe(_^$|0,(W|V)^ha|0,Y|0,U|0)|0;Y=D;ja=Rd((Q|R)^U|0,ma^Y|0,24)|0;ia=D;ma=Pd((Q|R)^U|0,ma^Y|0,40)|0;ia=D|ia;R=oe(ma|ja|0,ia|0,ha|0,$|0)|0;R=oe(R|0,D|0,v|0,H|0)|0;Q=D;c[P>>2]=R;c[P+4>>2]=Q;T=Rd(_^$^R|0,(W|V)^ha^Q|0,16)|0;ea=D;ha=Pd(_^$^R|0,(W|V)^ha^Q|0,48)|0;ea=D|ea;c[P+96>>2]=ha|T;c[P+96+4>>2]=ea;Y=oe(ha|T|0,ea|0,U|0,Y|0)|0;U=D;c[P+64>>2]=Y;c[P+64+4>>2]=U;ea=Rd((ma|ja)^Y|0,ia^U|0,63)|0;T=D;U=Pd((ma|ja)^Y|0,ia^U|0,1)|0;c[P+32>>2]=U|ea;c[P+32+4>>2]=D|T;T=c[P+40>>2]|0;ea=c[P+40+4>>2]|0;ca=oe(T|0,ea|0,la|0,ca|0)|0;ca=oe(ca|0,D|0,q|0,r|0)|0;la=D;da=oe(ga^la|0,(aa|X)^ca|0,Z|0,da|0)|0;Z=D;U=Rd(T^da|0,ea^Z|0,24)|0;ia=D;ea=Pd(T^da|0,ea^Z|0,40)|0;ia=D|ia;T=oe(ea|U|0,ia|0,ca|0,la|0)|0;T=oe(T|0,D|0,u|0,w|0)|0;Y=D;c[P+8>>2]=T;c[P+8+4>>2]=Y;ja=Rd(ga^la^T|0,(aa|X)^ca^Y|0,16)|0;ma=D;ca=Pd(ga^la^T|0,(aa|X)^ca^Y|0,48)|0;ma=D|ma;c[P+104>>2]=ca|ja;c[P+104+4>>2]=ma;Z=oe(ca|ja|0,ma|0,da|0,Z|0)|0;da=D;c[P+72>>2]=Z;c[P+72+4>>2]=da;ma=Rd((ea|U)^Z|0,ia^da|0,63)|0;ja=D;da=Pd((ea|U)^Z|0,ia^da|0,1)|0;ja=D|ja;ia=c[P+48>>2]|0;Z=c[P+48+4>>2]|0;fa=oe(ia|0,Z|0,ka|0,fa|0)|0;fa=oe(fa|0,D|0,k|0,l|0)|0;ka=D;U=oe(f^ka|0,(g|ba)^fa|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;ea=D;ca=Rd(ia^U|0,Z^ea|0,24)|0;X=D;Z=Pd(ia^U|0,Z^ea|0,40)|0;X=D|X;ia=oe(Z|ca|0,X|0,fa|0,ka|0)|0;ia=oe(ia|0,D|0,o|0,p|0)|0;aa=D;c[P+16>>2]=ia;c[P+16+4>>2]=aa;la=Rd(f^ka^ia|0,(g|ba)^fa^aa|0,16)|0;ga=D;fa=Pd(f^ka^ia|0,(g|ba)^fa^aa|0,48)|0;ga=D|ga;c[P+112>>2]=fa|la;c[P+112+4>>2]=ga;ea=oe(fa|la|0,ga|0,U|0,ea|0)|0;U=D;ga=Rd((Z|ca)^ea|0,X^U|0,63)|0;la=D;X=Pd((Z|ca)^ea|0,X^U|0,1)|0;la=D|la;ca=c[P+56>>2]|0;Z=c[P+56+4>>2]|0;S=oe(ca|0,Z|0,e|0,S|0)|0;S=oe(S|0,D|0,B|0,C|0)|0;e=D;fa=c[P+120>>2]^S;ba=c[P+120+4>>2]^e;g=oe(ba|0,fa|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;ka=D;f=Rd(ca^g|0,Z^ka|0,24)|0;ha=D;Z=Pd(ca^g|0,Z^ka|0,40)|0;ha=D|ha;e=oe(Z|f|0,ha|0,S|0,e|0)|0;e=oe(e|0,D|0,N|0,b|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ca=Rd(ba^e|0,fa^S|0,16)|0;V=D;fa=Pd(ba^e|0,fa^S|0,48)|0;V=D|V;ka=oe(fa|ca|0,V|0,g|0,ka|0)|0;g=D;ba=Rd((Z|f)^ka|0,ha^g|0,63)|0;W=D;ha=Pd((Z|f)^ka|0,ha^g|0,1)|0;W=D|W;Q=oe(da|ma|0,ja|0,R|0,Q|0)|0;Q=oe(Q|0,D|0,L|0,M|0)|0;R=D;U=oe(V^R|0,(fa|ca)^Q|0,ea|0,U|0)|0;ea=D;f=Rd((da|ma)^U|0,ja^ea|0,24)|0;Z=D;ja=Pd((da|ma)^U|0,ja^ea|0,40)|0;Z=D|Z;ma=oe(ja|f|0,Z|0,Q|0,R|0)|0;ma=oe(ma|0,D|0,h|0,j|0)|0;da=D;c[P>>2]=ma;c[P+4>>2]=da;$=Rd(V^R^ma|0,(fa|ca)^Q^da|0,16)|0;_=D;Q=Pd(V^R^ma|0,(fa|ca)^Q^da|0,48)|0;_=D|_;c[P+120>>2]=Q|$;c[P+120+4>>2]=_;ea=oe(Q|$|0,_|0,U|0,ea|0)|0;U=D;c[P+80>>2]=ea;c[P+80+4>>2]=U;_=Rd((ja|f)^ea|0,Z^U|0,63)|0;$=D;U=Pd((ja|f)^ea|0,Z^U|0,1)|0;c[P+40>>2]=U|_;c[P+40+4>>2]=D|$;Y=oe(X|ga|0,la|0,T|0,Y|0)|0;Y=oe(Y|0,D|0,E|0,F|0)|0;T=D;$=c[P+96>>2]^Y;_=c[P+96+4>>2]^T;g=oe(_|0,$|0,ka|0,g|0)|0;ka=D;U=Rd((X|ga)^g|0,la^ka|0,24)|0;Z=D;la=Pd((X|ga)^g|0,la^ka|0,40)|0;Z=D|Z;T=oe(la|U|0,Z|0,Y|0,T|0)|0;T=oe(T|0,D|0,G|0,I|0)|0;Y=D;c[P+8>>2]=T;c[P+8+4>>2]=Y;ga=Rd(_^T|0,$^Y|0,16)|0;X=D;$=Pd(_^T|0,$^Y|0,48)|0;X=D|X;ka=oe($|ga|0,X|0,g|0,ka|0)|0;g=D;c[P+88>>2]=ka;c[P+88+4>>2]=g;_=Rd((la|U)^ka|0,Z^g|0,63)|0;ea=D;g=Pd((la|U)^ka|0,Z^g|0,1)|0;c[P+48>>2]=g|_;c[P+48+4>>2]=D|ea;aa=oe(ha|ba|0,W|0,ia|0,aa|0)|0;aa=oe(aa|0,D|0,s|0,t|0)|0;ia=D;ea=c[P+104>>2]^aa;_=c[P+104+4>>2]^ia;g=oe(_|0,ea|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;Z=D;ka=Rd((ha|ba)^g|0,W^Z|0,24)|0;U=D;W=Pd((ha|ba)^g|0,W^Z|0,40)|0;U=D|U;ia=oe(W|ka|0,U|0,aa|0,ia|0)|0;ia=oe(ia|0,D|0,x|0,y|0)|0;aa=D;c[P+16>>2]=ia;c[P+16+4>>2]=aa;ba=Rd(_^ia|0,ea^aa|0,16)|0;ha=D;ea=Pd(_^ia|0,ea^aa|0,48)|0;ha=D|ha;Z=oe(ea|ba|0,ha|0,g|0,Z|0)|0;g=D;_=Rd((W|ka)^Z|0,U^g|0,63)|0;la=D;U=Pd((W|ka)^Z|0,U^g|0,1)|0;c[P+56>>2]=U|_;c[P+56+4>>2]=D|la;la=c[P+32>>2]|0;_=c[P+32+4>>2]|0;S=oe(la|0,_|0,e|0,S|0)|0;S=oe(S|0,D|0,m|0,n|0)|0;e=D;U=c[P+112>>2]^S;ka=c[P+112+4>>2]^e;W=oe(ka|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;f=D;ja=Rd(la^W|0,_^f|0,24)|0;Q=D;_=Pd(la^W|0,_^f|0,40)|0;Q=D|Q;e=oe(_|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,J|0,K|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;la=Rd(ka^e|0,U^S|0,16)|0;ca=D;U=Pd(ka^e|0,U^S|0,48)|0;ca=D|ca;f=oe(U|la|0,ca|0,W|0,f|0)|0;W=D;ka=Rd((_|ja)^f|0,Q^W|0,63)|0;fa=D;Q=Pd((_|ja)^f|0,Q^W|0,1)|0;fa=D|fa;da=oe(Q|ka|0,fa|0,ma|0,da|0)|0;da=oe(da|0,D|0,k|0,l|0)|0;ma=D;g=oe(X^ma|0,($|ga)^da|0,Z|0,g|0)|0;Z=D;ja=Rd((Q|ka)^g|0,fa^Z|0,24)|0;_=D;fa=Pd((Q|ka)^g|0,fa^Z|0,40)|0;_=D|_;ka=oe(fa|ja|0,_|0,da|0,ma|0)|0;ka=oe(ka|0,D|0,G|0,I|0)|0;Q=D;c[P>>2]=ka;c[P+4>>2]=Q;R=Rd(X^ma^ka|0,($|ga)^da^Q|0,16)|0;V=D;da=Pd(X^ma^ka|0,($|ga)^da^Q|0,48)|0;V=D|V;c[P+96>>2]=da|R;c[P+96+4>>2]=V;Z=oe(da|R|0,V|0,g|0,Z|0)|0;g=D;c[P+64>>2]=Z;c[P+64+4>>2]=g;V=Rd((fa|ja)^Z|0,_^g|0,63)|0;R=D;g=Pd((fa|ja)^Z|0,_^g|0,1)|0;c[P+32>>2]=g|V;c[P+32+4>>2]=D|R;R=c[P+40>>2]|0;V=c[P+40+4>>2]|0;Y=oe(R|0,V|0,T|0,Y|0)|0;Y=oe(Y|0,D|0,s|0,t|0)|0;T=D;W=oe(ha^T|0,(ea|ba)^Y|0,f|0,W|0)|0;f=D;g=Rd(R^W|0,V^f|0,24)|0;_=D;V=Pd(R^W|0,V^f|0,40)|0;_=D|_;R=oe(V|g|0,_|0,Y|0,T|0)|0;R=oe(R|0,D|0,B|0,C|0)|0;Z=D;c[P+8>>2]=R;c[P+8+4>>2]=Z;ja=Rd(ha^T^R|0,(ea|ba)^Y^Z|0,16)|0;fa=D;Y=Pd(ha^T^R|0,(ea|ba)^Y^Z|0,48)|0;fa=D|fa;c[P+104>>2]=Y|ja;c[P+104+4>>2]=fa;f=oe(Y|ja|0,fa|0,W|0,f|0)|0;W=D;c[P+72>>2]=f;c[P+72+4>>2]=W;fa=Rd((V|g)^f|0,_^W|0,63)|0;ja=D;W=Pd((V|g)^f|0,_^W|0,1)|0;ja=D|ja;_=c[P+48>>2]|0;f=c[P+48+4>>2]|0;aa=oe(_|0,f|0,ia|0,aa|0)|0;aa=oe(aa|0,D|0,v|0,H|0)|0;ia=D;g=oe(ca^ia|0,(U|la)^aa|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;V=D;Y=Rd(_^g|0,f^V|0,24)|0;ba=D;f=Pd(_^g|0,f^V|0,40)|0;ba=D|ba;_=oe(f|Y|0,ba|0,aa|0,ia|0)|0;_=oe(_|0,D|0,E|0,F|0)|0;ea=D;c[P+16>>2]=_;c[P+16+4>>2]=ea;T=Rd(ca^ia^_|0,(U|la)^aa^ea|0,16)|0;ha=D;aa=Pd(ca^ia^_|0,(U|la)^aa^ea|0,48)|0;ha=D|ha;c[P+112>>2]=aa|T;c[P+112+4>>2]=ha;V=oe(aa|T|0,ha|0,g|0,V|0)|0;g=D;ha=Rd((f|Y)^V|0,ba^g|0,63)|0;T=D;ba=Pd((f|Y)^V|0,ba^g|0,1)|0;T=D|T;Y=c[P+56>>2]|0;f=c[P+56+4>>2]|0;S=oe(Y|0,f|0,e|0,S|0)|0;S=oe(S|0,D|0,x|0,y|0)|0;e=D;aa=c[P+120>>2]^S;la=c[P+120+4>>2]^e;U=oe(la|0,aa|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;ia=D;ca=Rd(Y^U|0,f^ia|0,24)|0;da=D;f=Pd(Y^U|0,f^ia|0,40)|0;da=D|da;e=oe(f|ca|0,da|0,S|0,e|0)|0;e=oe(e|0,D|0,m|0,n|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Y=Rd(la^e|0,aa^S|0,16)|0;ga=D;aa=Pd(la^e|0,aa^S|0,48)|0;ga=D|ga;ia=oe(aa|Y|0,ga|0,U|0,ia|0)|0;U=D;la=Rd((f|ca)^ia|0,da^U|0,63)|0;$=D;da=Pd((f|ca)^ia|0,da^U|0,1)|0;$=D|$;Q=oe(W|fa|0,ja|0,ka|0,Q|0)|0;Q=oe(Q|0,D|0,o|0,p|0)|0;ka=D;g=oe(ga^ka|0,(aa|Y)^Q|0,V|0,g|0)|0;V=D;ca=Rd((W|fa)^g|0,ja^V|0,24)|0;f=D;ja=Pd((W|fa)^g|0,ja^V|0,40)|0;f=D|f;fa=oe(ja|ca|0,f|0,Q|0,ka|0)|0;fa=oe(fa|0,D|0,J|0,K|0)|0;W=D;c[P>>2]=fa;c[P+4>>2]=W;ma=Rd(ga^ka^fa|0,(aa|Y)^Q^W|0,16)|0;X=D;Q=Pd(ga^ka^fa|0,(aa|Y)^Q^W|0,48)|0;X=D|X;c[P+120>>2]=Q|ma;c[P+120+4>>2]=X;V=oe(Q|ma|0,X|0,g|0,V|0)|0;g=D;c[P+80>>2]=V;c[P+80+4>>2]=g;X=Rd((ja|ca)^V|0,f^g|0,63)|0;ma=D;g=Pd((ja|ca)^V|0,f^g|0,1)|0;c[P+40>>2]=g|X;c[P+40+4>>2]=D|ma;Z=oe(ba|ha|0,T|0,R|0,Z|0)|0;Z=oe(Z|0,D|0,u|0,w|0)|0;R=D;ma=c[P+96>>2]^Z;X=c[P+96+4>>2]^R;U=oe(X|0,ma|0,ia|0,U|0)|0;ia=D;g=Rd((ba|ha)^U|0,T^ia|0,24)|0;f=D;T=Pd((ba|ha)^U|0,T^ia|0,40)|0;f=D|f;R=oe(T|g|0,f|0,Z|0,R|0)|0;R=oe(R|0,D|0,q|0,r|0)|0;Z=D;c[P+8>>2]=R;c[P+8+4>>2]=Z;ha=Rd(X^R|0,ma^Z|0,16)|0;ba=D;ma=Pd(X^R|0,ma^Z|0,48)|0;ba=D|ba;ia=oe(ma|ha|0,ba|0,U|0,ia|0)|0;U=D;c[P+88>>2]=ia;c[P+88+4>>2]=U;X=Rd((T|g)^ia|0,f^U|0,63)|0;V=D;U=Pd((T|g)^ia|0,f^U|0,1)|0;c[P+48>>2]=U|X;c[P+48+4>>2]=D|V;ea=oe(da|la|0,$|0,_|0,ea|0)|0;ea=oe(ea|0,D|0,N|0,b|0)|0;_=D;V=c[P+104>>2]^ea;X=c[P+104+4>>2]^_;U=oe(X|0,V|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;f=D;ia=Rd((da|la)^U|0,$^f|0,24)|0;g=D;$=Pd((da|la)^U|0,$^f|0,40)|0;g=D|g;_=oe($|ia|0,g|0,ea|0,_|0)|0;_=oe(_|0,D|0,L|0,M|0)|0;ea=D;c[P+16>>2]=_;c[P+16+4>>2]=ea;la=Rd(X^_|0,V^ea|0,16)|0;da=D;V=Pd(X^_|0,V^ea|0,48)|0;da=D|da;f=oe(V|la|0,da|0,U|0,f|0)|0;U=D;X=Rd(($|ia)^f|0,g^U|0,63)|0;T=D;g=Pd(($|ia)^f|0,g^U|0,1)|0;c[P+56>>2]=g|X;c[P+56+4>>2]=D|T;T=c[P+32>>2]|0;X=c[P+32+4>>2]|0;S=oe(T|0,X|0,e|0,S|0)|0;S=oe(S|0,D|0,h|0,j|0)|0;e=D;g=c[P+112>>2]^S;ia=c[P+112+4>>2]^e;$=oe(ia|0,g|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;ca=D;ja=Rd(T^$|0,X^ca|0,24)|0;Q=D;X=Pd(T^$|0,X^ca|0,40)|0;Q=D|Q;e=oe(X|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,z|0,A|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;T=Rd(ia^e|0,g^S|0,16)|0;Y=D;g=Pd(ia^e|0,g^S|0,48)|0;Y=D|Y;ca=oe(g|T|0,Y|0,$|0,ca|0)|0;$=D;ia=Rd((X|ja)^ca|0,Q^$|0,63)|0;aa=D;Q=Pd((X|ja)^ca|0,Q^$|0,1)|0;aa=D|aa;W=oe(Q|ia|0,aa|0,fa|0,W|0)|0;W=oe(W|0,D|0,G|0,I|0)|0;fa=D;U=oe(ba^fa|0,(ma|ha)^W|0,f|0,U|0)|0;f=D;ja=Rd((Q|ia)^U|0,aa^f|0,24)|0;X=D;aa=Pd((Q|ia)^U|0,aa^f|0,40)|0;X=D|X;ia=oe(aa|ja|0,X|0,W|0,fa|0)|0;ia=oe(ia|0,D|0,q|0,r|0)|0;Q=D;c[P>>2]=ia;c[P+4>>2]=Q;ka=Rd(ba^fa^ia|0,(ma|ha)^W^Q|0,16)|0;ga=D;W=Pd(ba^fa^ia|0,(ma|ha)^W^Q|0,48)|0;ga=D|ga;c[P+96>>2]=W|ka;c[P+96+4>>2]=ga;f=oe(W|ka|0,ga|0,U|0,f|0)|0;U=D;c[P+64>>2]=f;c[P+64+4>>2]=U;ga=Rd((aa|ja)^f|0,X^U|0,63)|0;ka=D;U=Pd((aa|ja)^f|0,X^U|0,1)|0;c[P+32>>2]=U|ga;c[P+32+4>>2]=D|ka;ka=c[P+40>>2]|0;ga=c[P+40+4>>2]|0;Z=oe(ka|0,ga|0,R|0,Z|0)|0;Z=oe(Z|0,D|0,h|0,j|0)|0;R=D;$=oe(da^R|0,(V|la)^Z|0,ca|0,$|0)|0;ca=D;U=Rd(ka^$|0,ga^ca|0,24)|0;X=D;ga=Pd(ka^$|0,ga^ca|0,40)|0;X=D|X;ka=oe(ga|U|0,X|0,Z|0,R|0)|0;ka=oe(ka|0,D|0,N|0,b|0)|0;f=D;c[P+8>>2]=ka;c[P+8+4>>2]=f;ja=Rd(da^R^ka|0,(V|la)^Z^f|0,16)|0;aa=D;Z=Pd(da^R^ka|0,(V|la)^Z^f|0,48)|0;aa=D|aa;c[P+104>>2]=Z|ja;c[P+104+4>>2]=aa;ca=oe(Z|ja|0,aa|0,$|0,ca|0)|0;$=D;c[P+72>>2]=ca;c[P+72+4>>2]=$;aa=Rd((ga|U)^ca|0,X^$|0,63)|0;ja=D;$=Pd((ga|U)^ca|0,X^$|0,1)|0;ja=D|ja;X=c[P+48>>2]|0;ca=c[P+48+4>>2]|0;ea=oe(X|0,ca|0,_|0,ea|0)|0;ea=oe(ea|0,D|0,L|0,M|0)|0;_=D;U=oe(Y^_|0,(g|T)^ea|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;ga=D;Z=Rd(X^U|0,ca^ga|0,24)|0;la=D;ca=Pd(X^U|0,ca^ga|0,40)|0;la=D|la;X=oe(ca|Z|0,la|0,ea|0,_|0)|0;X=oe(X|0,D|0,J|0,K|0)|0;V=D;c[P+16>>2]=X;c[P+16+4>>2]=V;R=Rd(Y^_^X|0,(g|T)^ea^V|0,16)|0;da=D;ea=Pd(Y^_^X|0,(g|T)^ea^V|0,48)|0;da=D|da;c[P+112>>2]=ea|R;c[P+112+4>>2]=da;ga=oe(ea|R|0,da|0,U|0,ga|0)|0;U=D;da=Rd((ca|Z)^ga|0,la^U|0,63)|0;R=D;la=Pd((ca|Z)^ga|0,la^U|0,1)|0;R=D|R;Z=c[P+56>>2]|0;ca=c[P+56+4>>2]|0;S=oe(Z|0,ca|0,e|0,S|0)|0;S=oe(S|0,D|0,o|0,p|0)|0;e=D;ea=c[P+120>>2]^S;T=c[P+120+4>>2]^e;g=oe(T|0,ea|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;_=D;Y=Rd(Z^g|0,ca^_|0,24)|0;W=D;ca=Pd(Z^g|0,ca^_|0,40)|0;W=D|W;e=oe(ca|Y|0,W|0,S|0,e|0)|0;e=oe(e|0,D|0,B|0,C|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Z=Rd(T^e|0,ea^S|0,16)|0;ha=D;ea=Pd(T^e|0,ea^S|0,48)|0;ha=D|ha;_=oe(ea|Z|0,ha|0,g|0,_|0)|0;g=D;T=Rd((ca|Y)^_|0,W^g|0,63)|0;ma=D;W=Pd((ca|Y)^_|0,W^g|0,1)|0;ma=D|ma;Q=oe($|aa|0,ja|0,ia|0,Q|0)|0;Q=oe(Q|0,D|0,v|0,H|0)|0;ia=D;U=oe(ha^ia|0,(ea|Z)^Q|0,ga|0,U|0)|0;ga=D;Y=Rd(($|aa)^U|0,ja^ga|0,24)|0;ca=D;ja=Pd(($|aa)^U|0,ja^ga|0,40)|0;ca=D|ca;aa=oe(ja|Y|0,ca|0,Q|0,ia|0)|0;aa=oe(aa|0,D|0,u|0,w|0)|0;$=D;c[P>>2]=aa;c[P+4>>2]=$;fa=Rd(ha^ia^aa|0,(ea|Z)^Q^$|0,16)|0;ba=D;Q=Pd(ha^ia^aa|0,(ea|Z)^Q^$|0,48)|0;ba=D|ba;c[P+120>>2]=Q|fa;c[P+120+4>>2]=ba;ga=oe(Q|fa|0,ba|0,U|0,ga|0)|0;U=D;c[P+80>>2]=ga;c[P+80+4>>2]=U;ba=Rd((ja|Y)^ga|0,ca^U|0,63)|0;fa=D;U=Pd((ja|Y)^ga|0,ca^U|0,1)|0;c[P+40>>2]=U|ba;c[P+40+4>>2]=D|fa;f=oe(la|da|0,R|0,ka|0,f|0)|0;f=oe(f|0,D|0,s|0,t|0)|0;ka=D;fa=c[P+96>>2]^f;ba=c[P+96+4>>2]^ka;g=oe(ba|0,fa|0,_|0,g|0)|0;_=D;U=Rd((la|da)^g|0,R^_|0,24)|0;ca=D;R=Pd((la|da)^g|0,R^_|0,40)|0;ca=D|ca;ka=oe(R|U|0,ca|0,f|0,ka|0)|0;ka=oe(ka|0,D|0,m|0,n|0)|0;f=D;c[P+8>>2]=ka;c[P+8+4>>2]=f;da=Rd(ba^ka|0,fa^f|0,16)|0;la=D;fa=Pd(ba^ka|0,fa^f|0,48)|0;la=D|la;_=oe(fa|da|0,la|0,g|0,_|0)|0;g=D;c[P+88>>2]=_;c[P+88+4>>2]=g;ba=Rd((R|U)^_|0,ca^g|0,63)|0;ga=D;g=Pd((R|U)^_|0,ca^g|0,1)|0;c[P+48>>2]=g|ba;c[P+48+4>>2]=D|ga;V=oe(W|T|0,ma|0,X|0,V|0)|0;V=oe(V|0,D|0,z|0,A|0)|0;X=D;ga=c[P+104>>2]^V;ba=c[P+104+4>>2]^X;g=oe(ba|0,ga|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;ca=D;_=Rd((W|T)^g|0,ma^ca|0,24)|0;U=D;ma=Pd((W|T)^g|0,ma^ca|0,40)|0;U=D|U;X=oe(ma|_|0,U|0,V|0,X|0)|0;X=oe(X|0,D|0,k|0,l|0)|0;V=D;c[P+16>>2]=X;c[P+16+4>>2]=V;T=Rd(ba^X|0,ga^V|0,16)|0;W=D;ga=Pd(ba^X|0,ga^V|0,48)|0;W=D|W;ca=oe(ga|T|0,W|0,g|0,ca|0)|0;g=D;ba=Rd((ma|_)^ca|0,U^g|0,63)|0;R=D;U=Pd((ma|_)^ca|0,U^g|0,1)|0;c[P+56>>2]=U|ba;c[P+56+4>>2]=D|R;R=c[P+32>>2]|0;ba=c[P+32+4>>2]|0;S=oe(R|0,ba|0,e|0,S|0)|0;S=oe(S|0,D|0,x|0,y|0)|0;e=D;U=c[P+112>>2]^S;_=c[P+112+4>>2]^e;ma=oe(_|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;Y=D;ja=Rd(R^ma|0,ba^Y|0,24)|0;Q=D;ba=Pd(R^ma|0,ba^Y|0,40)|0;Q=D|Q;e=oe(ba|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,E|0,F|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;R=Rd(_^e|0,U^S|0,16)|0;Z=D;U=Pd(_^e|0,U^S|0,48)|0;Z=D|Z;Y=oe(U|R|0,Z|0,ma|0,Y|0)|0;ma=D;_=Rd((ba|ja)^Y|0,Q^ma|0,63)|0;ea=D;Q=Pd((ba|ja)^Y|0,Q^ma|0,1)|0;ea=D|ea;$=oe(Q|_|0,ea|0,aa|0,$|0)|0;$=oe($|0,D|0,J|0,K|0)|0;aa=D;g=oe(la^aa|0,(fa|da)^$|0,ca|0,g|0)|0;ca=D;ja=Rd((Q|_)^g|0,ea^ca|0,24)|0;ba=D;ea=Pd((Q|_)^g|0,ea^ca|0,40)|0;ba=D|ba;_=oe(ea|ja|0,ba|0,$|0,aa|0)|0;_=oe(_|0,D|0,E|0,F|0)|0;Q=D;c[P>>2]=_;c[P+4>>2]=Q;ia=Rd(la^aa^_|0,(fa|da)^$^Q|0,16)|0;ha=D;$=Pd(la^aa^_|0,(fa|da)^$^Q|0,48)|0;ha=D|ha;c[P+96>>2]=$|ia;c[P+96+4>>2]=ha;ca=oe($|ia|0,ha|0,g|0,ca|0)|0;g=D;c[P+64>>2]=ca;c[P+64+4>>2]=g;ha=Rd((ea|ja)^ca|0,ba^g|0,63)|0;ia=D;g=Pd((ea|ja)^ca|0,ba^g|0,1)|0;c[P+32>>2]=g|ha;c[P+32+4>>2]=D|ia;ia=c[P+40>>2]|0;ha=c[P+40+4>>2]|0;f=oe(ia|0,ha|0,ka|0,f|0)|0;f=oe(f|0,D|0,u|0,w|0)|0;ka=D;ma=oe(W^ka|0,(ga|T)^f|0,Y|0,ma|0)|0;Y=D;g=Rd(ia^ma|0,ha^Y|0,24)|0;ba=D;ha=Pd(ia^ma|0,ha^Y|0,40)|0;ba=D|ba;ia=oe(ha|g|0,ba|0,f|0,ka|0)|0;ia=oe(ia|0,D|0,L|0,M|0)|0;ca=D;c[P+8>>2]=ia;c[P+8+4>>2]=ca;ja=Rd(W^ka^ia|0,(ga|T)^f^ca|0,16)|0;ea=D;f=Pd(W^ka^ia|0,(ga|T)^f^ca|0,48)|0;ea=D|ea;c[P+104>>2]=f|ja;c[P+104+4>>2]=ea;Y=oe(f|ja|0,ea|0,ma|0,Y|0)|0;ma=D;c[P+72>>2]=Y;c[P+72+4>>2]=ma;ea=Rd((ha|g)^Y|0,ba^ma|0,63)|0;ja=D;ma=Pd((ha|g)^Y|0,ba^ma|0,1)|0;ja=D|ja;ba=c[P+48>>2]|0;Y=c[P+48+4>>2]|0;V=oe(ba|0,Y|0,X|0,V|0)|0;V=oe(V|0,D|0,G|0,I|0)|0;X=D;g=oe(Z^X|0,(U|R)^V|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;ha=D;f=Rd(ba^g|0,Y^ha|0,24)|0;T=D;Y=Pd(ba^g|0,Y^ha|0,40)|0;T=D|T;ba=oe(Y|f|0,T|0,V|0,X|0)|0;ba=oe(ba|0,D|0,h|0,j|0)|0;ga=D;c[P+16>>2]=ba;c[P+16+4>>2]=ga;ka=Rd(Z^X^ba|0,(U|R)^V^ga|0,16)|0;W=D;V=Pd(Z^X^ba|0,(U|R)^V^ga|0,48)|0;W=D|W;c[P+112>>2]=V|ka;c[P+112+4>>2]=W;ha=oe(V|ka|0,W|0,g|0,ha|0)|0;g=D;W=Rd((Y|f)^ha|0,T^g|0,63)|0;ka=D;T=Pd((Y|f)^ha|0,T^g|0,1)|0;ka=D|ka;f=c[P+56>>2]|0;Y=c[P+56+4>>2]|0;S=oe(f|0,Y|0,e|0,S|0)|0;S=oe(S|0,D|0,m|0,n|0)|0;e=D;V=c[P+120>>2]^S;R=c[P+120+4>>2]^e;U=oe(R|0,V|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;X=D;Z=Rd(f^U|0,Y^X|0,24)|0;$=D;Y=Pd(f^U|0,Y^X|0,40)|0;$=D|$;e=oe(Y|Z|0,$|0,S|0,e|0)|0;e=oe(e|0,D|0,z|0,A|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;f=Rd(R^e|0,V^S|0,16)|0;da=D;V=Pd(R^e|0,V^S|0,48)|0;da=D|da;X=oe(V|f|0,da|0,U|0,X|0)|0;U=D;R=Rd((Y|Z)^X|0,$^U|0,63)|0;fa=D;$=Pd((Y|Z)^X|0,$^U|0,1)|0;fa=D|fa;Q=oe(ma|ea|0,ja|0,_|0,Q|0)|0;Q=oe(Q|0,D|0,q|0,r|0)|0;_=D;g=oe(da^_|0,(V|f)^Q|0,ha|0,g|0)|0;ha=D;Z=Rd((ma|ea)^g|0,ja^ha|0,24)|0;Y=D;ja=Pd((ma|ea)^g|0,ja^ha|0,40)|0;Y=D|Y;ea=oe(ja|Z|0,Y|0,Q|0,_|0)|0;ea=oe(ea|0,D|0,v|0,H|0)|0;ma=D;c[P>>2]=ea;c[P+4>>2]=ma;aa=Rd(da^_^ea|0,(V|f)^Q^ma|0,16)|0;la=D;Q=Pd(da^_^ea|0,(V|f)^Q^ma|0,48)|0;la=D|la;c[P+120>>2]=Q|aa;c[P+120+4>>2]=la;ha=oe(Q|aa|0,la|0,g|0,ha|0)|0;g=D;c[P+80>>2]=ha;c[P+80+4>>2]=g;la=Rd((ja|Z)^ha|0,Y^g|0,63)|0;aa=D;g=Pd((ja|Z)^ha|0,Y^g|0,1)|0;c[P+40>>2]=g|la;c[P+40+4>>2]=D|aa;ca=oe(T|W|0,ka|0,ia|0,ca|0)|0;ca=oe(ca|0,D|0,N|0,b|0)|0;ia=D;aa=c[P+96>>2]^ca;la=c[P+96+4>>2]^ia;U=oe(la|0,aa|0,X|0,U|0)|0;X=D;g=Rd((T|W)^U|0,ka^X|0,24)|0;Y=D;ka=Pd((T|W)^U|0,ka^X|0,40)|0;Y=D|Y;ia=oe(ka|g|0,Y|0,ca|0,ia|0)|0;ia=oe(ia|0,D|0,o|0,p|0)|0;ca=D;c[P+8>>2]=ia;c[P+8+4>>2]=ca;W=Rd(la^ia|0,aa^ca|0,16)|0;T=D;aa=Pd(la^ia|0,aa^ca|0,48)|0;T=D|T;X=oe(aa|W|0,T|0,U|0,X|0)|0;U=D;c[P+88>>2]=X;c[P+88+4>>2]=U;la=Rd((ka|g)^X|0,Y^U|0,63)|0;ha=D;U=Pd((ka|g)^X|0,Y^U|0,1)|0;c[P+48>>2]=U|la;c[P+48+4>>2]=D|ha;ga=oe($|R|0,fa|0,ba|0,ga|0)|0;ga=oe(ga|0,D|0,x|0,y|0)|0;ba=D;ha=c[P+104>>2]^ga;la=c[P+104+4>>2]^ba;U=oe(la|0,ha|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;Y=D;X=Rd(($|R)^U|0,fa^Y|0,24)|0;g=D;fa=Pd(($|R)^U|0,fa^Y|0,40)|0;g=D|g;ba=oe(fa|X|0,g|0,ga|0,ba|0)|0;ba=oe(ba|0,D|0,s|0,t|0)|0;ga=D;c[P+16>>2]=ba;c[P+16+4>>2]=ga;R=Rd(la^ba|0,ha^ga|0,16)|0;$=D;ha=Pd(la^ba|0,ha^ga|0,48)|0;$=D|$;Y=oe(ha|R|0,$|0,U|0,Y|0)|0;U=D;la=Rd((fa|X)^Y|0,g^U|0,63)|0;ka=D;g=Pd((fa|X)^Y|0,g^U|0,1)|0;c[P+56>>2]=g|la;c[P+56+4>>2]=D|ka;ka=c[P+32>>2]|0;la=c[P+32+4>>2]|0;S=oe(ka|0,la|0,e|0,S|0)|0;S=oe(S|0,D|0,k|0,l|0)|0;e=D;g=c[P+112>>2]^S;X=c[P+112+4>>2]^e;fa=oe(X|0,g|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;Z=D;ja=Rd(ka^fa|0,la^Z|0,24)|0;Q=D;la=Pd(ka^fa|0,la^Z|0,40)|0;Q=D|Q;e=oe(la|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,B|0,C|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ka=Rd(X^e|0,g^S|0,16)|0;f=D;g=Pd(X^e|0,g^S|0,48)|0;f=D|f;Z=oe(g|ka|0,f|0,fa|0,Z|0)|0;fa=D;X=Rd((la|ja)^Z|0,Q^fa|0,63)|0;V=D;Q=Pd((la|ja)^Z|0,Q^fa|0,1)|0;V=D|V;ma=oe(Q|X|0,V|0,ea|0,ma|0)|0;ma=oe(ma|0,D|0,s|0,t|0)|0;ea=D;U=oe(T^ea|0,(aa|W)^ma|0,Y|0,U|0)|0;Y=D;ja=Rd((Q|X)^U|0,V^Y|0,24)|0;la=D;V=Pd((Q|X)^U|0,V^Y|0,40)|0;la=D|la;X=oe(V|ja|0,la|0,ma|0,ea|0)|0;X=oe(X|0,D|0,N|0,b|0)|0;Q=D;c[P>>2]=X;c[P+4>>2]=Q;_=Rd(T^ea^X|0,(aa|W)^ma^Q|0,16)|0;da=D;ma=Pd(T^ea^X|0,(aa|W)^ma^Q|0,48)|0;da=D|da;c[P+96>>2]=ma|_;c[P+96+4>>2]=da;Y=oe(ma|_|0,da|0,U|0,Y|0)|0;U=D;c[P+64>>2]=Y;c[P+64+4>>2]=U;da=Rd((V|ja)^Y|0,la^U|0,63)|0;_=D;U=Pd((V|ja)^Y|0,la^U|0,1)|0;c[P+32>>2]=U|da;c[P+32+4>>2]=D|_;_=c[P+40>>2]|0;da=c[P+40+4>>2]|0;ca=oe(_|0,da|0,ia|0,ca|0)|0;ca=oe(ca|0,D|0,L|0,M|0)|0;ia=D;fa=oe($^ia|0,(ha|R)^ca|0,Z|0,fa|0)|0;Z=D;U=Rd(_^fa|0,da^Z|0,24)|0;la=D;da=Pd(_^fa|0,da^Z|0,40)|0;la=D|la;_=oe(da|U|0,la|0,ca|0,ia|0)|0;_=oe(_|0,D|0,z|0,A|0)|0;Y=D;c[P+8>>2]=_;c[P+8+4>>2]=Y;ja=Rd($^ia^_|0,(ha|R)^ca^Y|0,16)|0;V=D;ca=Pd($^ia^_|0,(ha|R)^ca^Y|0,48)|0;V=D|V;c[P+104>>2]=ca|ja;c[P+104+4>>2]=V;Z=oe(ca|ja|0,V|0,fa|0,Z|0)|0;fa=D;c[P+72>>2]=Z;c[P+72+4>>2]=fa;V=Rd((da|U)^Z|0,la^fa|0,63)|0;ja=D;fa=Pd((da|U)^Z|0,la^fa|0,1)|0;ja=D|ja;la=c[P+48>>2]|0;Z=c[P+48+4>>2]|0;ga=oe(la|0,Z|0,ba|0,ga|0)|0;ga=oe(ga|0,D|0,E|0,F|0)|0;ba=D;U=oe(f^ba|0,(g|ka)^ga|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;da=D;ca=Rd(la^U|0,Z^da|0,24)|0;R=D;Z=Pd(la^U|0,Z^da|0,40)|0;R=D|R;la=oe(Z|ca|0,R|0,ga|0,ba|0)|0;la=oe(la|0,D|0,m|0,n|0)|0;ha=D;c[P+16>>2]=la;c[P+16+4>>2]=ha;ia=Rd(f^ba^la|0,(g|ka)^ga^ha|0,16)|0;$=D;ga=Pd(f^ba^la|0,(g|ka)^ga^ha|0,48)|0;$=D|$;c[P+112>>2]=ga|ia;c[P+112+4>>2]=$;da=oe(ga|ia|0,$|0,U|0,da|0)|0;U=D;$=Rd((Z|ca)^da|0,R^U|0,63)|0;ia=D;R=Pd((Z|ca)^da|0,R^U|0,1)|0;ia=D|ia;ca=c[P+56>>2]|0;Z=c[P+56+4>>2]|0;S=oe(ca|0,Z|0,e|0,S|0)|0;S=oe(S|0,D|0,v|0,H|0)|0;e=D;ga=c[P+120>>2]^S;ka=c[P+120+4>>2]^e;g=oe(ka|0,ga|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;ba=D;f=Rd(ca^g|0,Z^ba|0,24)|0;ma=D;Z=Pd(ca^g|0,Z^ba|0,40)|0;ma=D|ma;e=oe(Z|f|0,ma|0,S|0,e|0)|0;e=oe(e|0,D|0,x|0,y|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ca=Rd(ka^e|0,ga^S|0,16)|0;W=D;ga=Pd(ka^e|0,ga^S|0,48)|0;W=D|W;ba=oe(ga|ca|0,W|0,g|0,ba|0)|0;g=D;ka=Rd((Z|f)^ba|0,ma^g|0,63)|0;aa=D;ma=Pd((Z|f)^ba|0,ma^g|0,1)|0;aa=D|aa;Q=oe(fa|V|0,ja|0,X|0,Q|0)|0;Q=oe(Q|0,D|0,G|0,I|0)|0;X=D;U=oe(W^X|0,(ga|ca)^Q|0,da|0,U|0)|0;da=D;f=Rd((fa|V)^U|0,ja^da|0,24)|0;Z=D;ja=Pd((fa|V)^U|0,ja^da|0,40)|0;Z=D|Z;V=oe(ja|f|0,Z|0,Q|0,X|0)|0;V=oe(V|0,D|0,k|0,l|0)|0;fa=D;c[P>>2]=V;c[P+4>>2]=fa;ea=Rd(W^X^V|0,(ga|ca)^Q^fa|0,16)|0;T=D;Q=Pd(W^X^V|0,(ga|ca)^Q^fa|0,48)|0;T=D|T;c[P+120>>2]=Q|ea;c[P+120+4>>2]=T;da=oe(Q|ea|0,T|0,U|0,da|0)|0;U=D;c[P+80>>2]=da;c[P+80+4>>2]=U;T=Rd((ja|f)^da|0,Z^U|0,63)|0;ea=D;U=Pd((ja|f)^da|0,Z^U|0,1)|0;c[P+40>>2]=U|T;c[P+40+4>>2]=D|ea;Y=oe(R|$|0,ia|0,_|0,Y|0)|0;Y=oe(Y|0,D|0,J|0,K|0)|0;_=D;ea=c[P+96>>2]^Y;T=c[P+96+4>>2]^_;g=oe(T|0,ea|0,ba|0,g|0)|0;ba=D;U=Rd((R|$)^g|0,ia^ba|0,24)|0;Z=D;ia=Pd((R|$)^g|0,ia^ba|0,40)|0;Z=D|Z;_=oe(ia|U|0,Z|0,Y|0,_|0)|0;_=oe(_|0,D|0,u|0,w|0)|0;Y=D;c[P+8>>2]=_;c[P+8+4>>2]=Y;$=Rd(T^_|0,ea^Y|0,16)|0;R=D;ea=Pd(T^_|0,ea^Y|0,48)|0;R=D|R;ba=oe(ea|$|0,R|0,g|0,ba|0)|0;g=D;c[P+88>>2]=ba;c[P+88+4>>2]=g;T=Rd((ia|U)^ba|0,Z^g|0,63)|0;da=D;g=Pd((ia|U)^ba|0,Z^g|0,1)|0;c[P+48>>2]=g|T;c[P+48+4>>2]=D|da;ha=oe(ma|ka|0,aa|0,la|0,ha|0)|0;ha=oe(ha|0,D|0,h|0,j|0)|0;la=D;da=c[P+104>>2]^ha;T=c[P+104+4>>2]^la;g=oe(T|0,da|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;Z=D;ba=Rd((ma|ka)^g|0,aa^Z|0,24)|0;U=D;aa=Pd((ma|ka)^g|0,aa^Z|0,40)|0;U=D|U;la=oe(aa|ba|0,U|0,ha|0,la|0)|0;la=oe(la|0,D|0,o|0,p|0)|0;ha=D;c[P+16>>2]=la;c[P+16+4>>2]=ha;ka=Rd(T^la|0,da^ha|0,16)|0;ma=D;da=Pd(T^la|0,da^ha|0,48)|0;ma=D|ma;Z=oe(da|ka|0,ma|0,g|0,Z|0)|0;g=D;T=Rd((aa|ba)^Z|0,U^g|0,63)|0;ia=D;U=Pd((aa|ba)^Z|0,U^g|0,1)|0;c[P+56>>2]=U|T;c[P+56+4>>2]=D|ia;ia=c[P+32>>2]|0;T=c[P+32+4>>2]|0;S=oe(ia|0,T|0,e|0,S|0)|0;S=oe(S|0,D|0,B|0,C|0)|0;e=D;U=c[P+112>>2]^S;ba=c[P+112+4>>2]^e;aa=oe(ba|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;f=D;ja=Rd(ia^aa|0,T^f|0,24)|0;Q=D;T=Pd(ia^aa|0,T^f|0,40)|0;Q=D|Q;e=oe(T|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,q|0,r|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;ia=Rd(ba^e|0,U^S|0,16)|0;ca=D;U=Pd(ba^e|0,U^S|0,48)|0;ca=D|ca;f=oe(U|ia|0,ca|0,aa|0,f|0)|0;aa=D;ba=Rd((T|ja)^f|0,Q^aa|0,63)|0;ga=D;Q=Pd((T|ja)^f|0,Q^aa|0,1)|0;ga=D|ga;fa=oe(Q|ba|0,ga|0,V|0,fa|0)|0;fa=oe(fa|0,D|0,B|0,C|0)|0;V=D;g=oe(R^V|0,(ea|$)^fa|0,Z|0,g|0)|0;Z=D;ja=Rd((Q|ba)^g|0,ga^Z|0,24)|0;T=D;ga=Pd((Q|ba)^g|0,ga^Z|0,40)|0;T=D|T;ba=oe(ga|ja|0,T|0,fa|0,V|0)|0;ba=oe(ba|0,D|0,k|0,l|0)|0;Q=D;c[P>>2]=ba;c[P+4>>2]=Q;X=Rd(R^V^ba|0,(ea|$)^fa^Q|0,16)|0;W=D;fa=Pd(R^V^ba|0,(ea|$)^fa^Q|0,48)|0;W=D|W;c[P+96>>2]=fa|X;c[P+96+4>>2]=W;Z=oe(fa|X|0,W|0,g|0,Z|0)|0;g=D;c[P+64>>2]=Z;c[P+64+4>>2]=g;W=Rd((ga|ja)^Z|0,T^g|0,63)|0;X=D;g=Pd((ga|ja)^Z|0,T^g|0,1)|0;c[P+32>>2]=g|W;c[P+32+4>>2]=D|X;X=c[P+40>>2]|0;W=c[P+40+4>>2]|0;Y=oe(X|0,W|0,_|0,Y|0)|0;Y=oe(Y|0,D|0,x|0,y|0)|0;_=D;aa=oe(ma^_|0,(da|ka)^Y|0,f|0,aa|0)|0;f=D;g=Rd(X^aa|0,W^f|0,24)|0;T=D;W=Pd(X^aa|0,W^f|0,40)|0;T=D|T;X=oe(W|g|0,T|0,Y|0,_|0)|0;X=oe(X|0,D|0,o|0,p|0)|0;Z=D;c[P+8>>2]=X;c[P+8+4>>2]=Z;ja=Rd(ma^_^X|0,(da|ka)^Y^Z|0,16)|0;ga=D;Y=Pd(ma^_^X|0,(da|ka)^Y^Z|0,48)|0;ga=D|ga;c[P+104>>2]=Y|ja;c[P+104+4>>2]=ga;f=oe(Y|ja|0,ga|0,aa|0,f|0)|0;aa=D;c[P+72>>2]=f;c[P+72+4>>2]=aa;ga=Rd((W|g)^f|0,T^aa|0,63)|0;ja=D;aa=Pd((W|g)^f|0,T^aa|0,1)|0;ja=D|ja;T=c[P+48>>2]|0;f=c[P+48+4>>2]|0;ha=oe(T|0,f|0,la|0,ha|0)|0;ha=oe(ha|0,D|0,u|0,w|0)|0;la=D;g=oe(ca^la|0,(U|ia)^ha|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;W=D;Y=Rd(T^g|0,f^W|0,24)|0;ka=D;f=Pd(T^g|0,f^W|0,40)|0;ka=D|ka;T=oe(f|Y|0,ka|0,ha|0,la|0)|0;T=oe(T|0,D|0,s|0,t|0)|0;da=D;c[P+16>>2]=T;c[P+16+4>>2]=da;_=Rd(ca^la^T|0,(U|ia)^ha^da|0,16)|0;ma=D;ha=Pd(ca^la^T|0,(U|ia)^ha^da|0,48)|0;ma=D|ma;c[P+112>>2]=ha|_;c[P+112+4>>2]=ma;W=oe(ha|_|0,ma|0,g|0,W|0)|0;g=D;ma=Rd((f|Y)^W|0,ka^g|0,63)|0;_=D;ka=Pd((f|Y)^W|0,ka^g|0,1)|0;_=D|_;Y=c[P+56>>2]|0;f=c[P+56+4>>2]|0;S=oe(Y|0,f|0,e|0,S|0)|0;S=oe(S|0,D|0,h|0,j|0)|0;e=D;ha=c[P+120>>2]^S;ia=c[P+120+4>>2]^e;U=oe(ia|0,ha|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;la=D;ca=Rd(Y^U|0,f^la|0,24)|0;fa=D;f=Pd(Y^U|0,f^la|0,40)|0;fa=D|fa;e=oe(f|ca|0,fa|0,S|0,e|0)|0;e=oe(e|0,D|0,q|0,r|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Y=Rd(ia^e|0,ha^S|0,16)|0;$=D;ha=Pd(ia^e|0,ha^S|0,48)|0;$=D|$;la=oe(ha|Y|0,$|0,U|0,la|0)|0;U=D;ia=Rd((f|ca)^la|0,fa^U|0,63)|0;ea=D;fa=Pd((f|ca)^la|0,fa^U|0,1)|0;ea=D|ea;Q=oe(aa|ga|0,ja|0,ba|0,Q|0)|0;Q=oe(Q|0,D|0,N|0,b|0)|0;ba=D;g=oe($^ba|0,(ha|Y)^Q|0,W|0,g|0)|0;W=D;ca=Rd((aa|ga)^g|0,ja^W|0,24)|0;f=D;ja=Pd((aa|ga)^g|0,ja^W|0,40)|0;f=D|f;ga=oe(ja|ca|0,f|0,Q|0,ba|0)|0;ga=oe(ga|0,D|0,E|0,F|0)|0;aa=D;c[P>>2]=ga;c[P+4>>2]=aa;V=Rd($^ba^ga|0,(ha|Y)^Q^aa|0,16)|0;R=D;Q=Pd($^ba^ga|0,(ha|Y)^Q^aa|0,48)|0;R=D|R;c[P+120>>2]=Q|V;c[P+120+4>>2]=R;W=oe(Q|V|0,R|0,g|0,W|0)|0;g=D;c[P+80>>2]=W;c[P+80+4>>2]=g;R=Rd((ja|ca)^W|0,f^g|0,63)|0;V=D;g=Pd((ja|ca)^W|0,f^g|0,1)|0;c[P+40>>2]=g|R;c[P+40+4>>2]=D|V;Z=oe(ka|ma|0,_|0,X|0,Z|0)|0;Z=oe(Z|0,D|0,z|0,A|0)|0;X=D;V=c[P+96>>2]^Z;R=c[P+96+4>>2]^X;U=oe(R|0,V|0,la|0,U|0)|0;la=D;g=Rd((ka|ma)^U|0,_^la|0,24)|0;f=D;_=Pd((ka|ma)^U|0,_^la|0,40)|0;f=D|f;X=oe(_|g|0,f|0,Z|0,X|0)|0;X=oe(X|0,D|0,L|0,M|0)|0;Z=D;c[P+8>>2]=X;c[P+8+4>>2]=Z;ma=Rd(R^X|0,V^Z|0,16)|0;ka=D;V=Pd(R^X|0,V^Z|0,48)|0;ka=D|ka;la=oe(V|ma|0,ka|0,U|0,la|0)|0;U=D;c[P+88>>2]=la;c[P+88+4>>2]=U;R=Rd((_|g)^la|0,f^U|0,63)|0;W=D;U=Pd((_|g)^la|0,f^U|0,1)|0;c[P+48>>2]=U|R;c[P+48+4>>2]=D|W;da=oe(fa|ia|0,ea|0,T|0,da|0)|0;da=oe(da|0,D|0,m|0,n|0)|0;T=D;W=c[P+104>>2]^da;R=c[P+104+4>>2]^T;U=oe(R|0,W|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;f=D;la=Rd((fa|ia)^U|0,ea^f|0,24)|0;g=D;ea=Pd((fa|ia)^U|0,ea^f|0,40)|0;g=D|g;T=oe(ea|la|0,g|0,da|0,T|0)|0;T=oe(T|0,D|0,G|0,I|0)|0;da=D;c[P+16>>2]=T;c[P+16+4>>2]=da;ia=Rd(R^T|0,W^da|0,16)|0;fa=D;W=Pd(R^T|0,W^da|0,48)|0;fa=D|fa;f=oe(W|ia|0,fa|0,U|0,f|0)|0;U=D;R=Rd((ea|la)^f|0,g^U|0,63)|0;_=D;g=Pd((ea|la)^f|0,g^U|0,1)|0;c[P+56>>2]=g|R;c[P+56+4>>2]=D|_;_=c[P+32>>2]|0;R=c[P+32+4>>2]|0;S=oe(_|0,R|0,e|0,S|0)|0;S=oe(S|0,D|0,J|0,K|0)|0;e=D;g=c[P+112>>2]^S;la=c[P+112+4>>2]^e;ea=oe(la|0,g|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;ca=D;ja=Rd(_^ea|0,R^ca|0,24)|0;Q=D;R=Pd(_^ea|0,R^ca|0,40)|0;Q=D|Q;e=oe(R|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,v|0,H|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;_=Rd(la^e|0,g^S|0,16)|0;Y=D;g=Pd(la^e|0,g^S|0,48)|0;Y=D|Y;ca=oe(g|_|0,Y|0,ea|0,ca|0)|0;ea=D;la=Rd((R|ja)^ca|0,Q^ea|0,63)|0;ha=D;Q=Pd((R|ja)^ca|0,Q^ea|0,1)|0;ha=D|ha;aa=oe(Q|la|0,ha|0,ga|0,aa|0)|0;aa=oe(aa|0,D|0,v|0,H|0)|0;ga=D;U=oe(ka^ga|0,(V|ma)^aa|0,f|0,U|0)|0;f=D;ja=Rd((Q|la)^U|0,ha^f|0,24)|0;R=D;ha=Pd((Q|la)^U|0,ha^f|0,40)|0;R=D|R;la=oe(ha|ja|0,R|0,aa|0,ga|0)|0;la=oe(la|0,D|0,h|0,j|0)|0;Q=D;c[P>>2]=la;c[P+4>>2]=Q;ba=Rd(ka^ga^la|0,(V|ma)^aa^Q|0,16)|0;$=D;aa=Pd(ka^ga^la|0,(V|ma)^aa^Q|0,48)|0;$=D|$;c[P+96>>2]=aa|ba;c[P+96+4>>2]=$;f=oe(aa|ba|0,$|0,U|0,f|0)|0;U=D;c[P+64>>2]=f;c[P+64+4>>2]=U;$=Rd((ha|ja)^f|0,R^U|0,63)|0;ba=D;U=Pd((ha|ja)^f|0,R^U|0,1)|0;c[P+32>>2]=U|$;c[P+32+4>>2]=D|ba;ba=c[P+40>>2]|0;$=c[P+40+4>>2]|0;Z=oe(ba|0,$|0,X|0,Z|0)|0;Z=oe(Z|0,D|0,k|0,l|0)|0;X=D;ea=oe(fa^X|0,(W|ia)^Z|0,ca|0,ea|0)|0;ca=D;U=Rd(ba^ea|0,$^ca|0,24)|0;R=D;$=Pd(ba^ea|0,$^ca|0,40)|0;R=D|R;ba=oe($|U|0,R|0,Z|0,X|0)|0;ba=oe(ba|0,D|0,m|0,n|0)|0;f=D;c[P+8>>2]=ba;c[P+8+4>>2]=f;ja=Rd(fa^X^ba|0,(W|ia)^Z^f|0,16)|0;ha=D;Z=Pd(fa^X^ba|0,(W|ia)^Z^f|0,48)|0;ha=D|ha;c[P+104>>2]=Z|ja;c[P+104+4>>2]=ha;ca=oe(Z|ja|0,ha|0,ea|0,ca|0)|0;ea=D;c[P+72>>2]=ca;c[P+72+4>>2]=ea;ha=Rd(($|U)^ca|0,R^ea|0,63)|0;ja=D;ea=Pd(($|U)^ca|0,R^ea|0,1)|0;ja=D|ja;R=c[P+48>>2]|0;ca=c[P+48+4>>2]|0;da=oe(R|0,ca|0,T|0,da|0)|0;da=oe(da|0,D|0,o|0,p|0)|0;T=D;U=oe(Y^T|0,(g|_)^da|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;$=D;Z=Rd(R^U|0,ca^$|0,24)|0;ia=D;ca=Pd(R^U|0,ca^$|0,40)|0;ia=D|ia;R=oe(ca|Z|0,ia|0,da|0,T|0)|0;R=oe(R|0,D|0,q|0,r|0)|0;W=D;c[P+16>>2]=R;c[P+16+4>>2]=W;X=Rd(Y^T^R|0,(g|_)^da^W|0,16)|0;fa=D;da=Pd(Y^T^R|0,(g|_)^da^W|0,48)|0;fa=D|fa;c[P+112>>2]=da|X;c[P+112+4>>2]=fa;$=oe(da|X|0,fa|0,U|0,$|0)|0;U=D;fa=Rd((ca|Z)^$|0,ia^U|0,63)|0;X=D;ia=Pd((ca|Z)^$|0,ia^U|0,1)|0;X=D|X;Z=c[P+56>>2]|0;ca=c[P+56+4>>2]|0;S=oe(Z|0,ca|0,e|0,S|0)|0;S=oe(S|0,D|0,s|0,t|0)|0;e=D;da=c[P+120>>2]^S;_=c[P+120+4>>2]^e;g=oe(_|0,da|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;T=D;Y=Rd(Z^g|0,ca^T|0,24)|0;aa=D;ca=Pd(Z^g|0,ca^T|0,40)|0;aa=D|aa;e=oe(ca|Y|0,aa|0,S|0,e|0)|0;e=oe(e|0,D|0,u|0,w|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;Z=Rd(_^e|0,da^S|0,16)|0;ma=D;da=Pd(_^e|0,da^S|0,48)|0;ma=D|ma;T=oe(da|Z|0,ma|0,g|0,T|0)|0;g=D;_=Rd((ca|Y)^T|0,aa^g|0,63)|0;V=D;aa=Pd((ca|Y)^T|0,aa^g|0,1)|0;V=D|V;Q=oe(ea|ha|0,ja|0,la|0,Q|0)|0;Q=oe(Q|0,D|0,x|0,y|0)|0;la=D;U=oe(ma^la|0,(da|Z)^Q|0,$|0,U|0)|0;$=D;Y=Rd((ea|ha)^U|0,ja^$|0,24)|0;ca=D;ja=Pd((ea|ha)^U|0,ja^$|0,40)|0;ca=D|ca;ha=oe(ja|Y|0,ca|0,Q|0,la|0)|0;ha=oe(ha|0,D|0,z|0,A|0)|0;ea=D;c[P>>2]=ha;c[P+4>>2]=ea;ga=Rd(ma^la^ha|0,(da|Z)^Q^ea|0,16)|0;ka=D;Q=Pd(ma^la^ha|0,(da|Z)^Q^ea|0,48)|0;ka=D|ka;c[P+120>>2]=Q|ga;c[P+120+4>>2]=ka;$=oe(Q|ga|0,ka|0,U|0,$|0)|0;U=D;c[P+80>>2]=$;c[P+80+4>>2]=U;ka=Rd((ja|Y)^$|0,ca^U|0,63)|0;ga=D;U=Pd((ja|Y)^$|0,ca^U|0,1)|0;c[P+40>>2]=U|ka;c[P+40+4>>2]=D|ga;f=oe(ia|fa|0,X|0,ba|0,f|0)|0;f=oe(f|0,D|0,B|0,C|0)|0;ba=D;ga=c[P+96>>2]^f;ka=c[P+96+4>>2]^ba;g=oe(ka|0,ga|0,T|0,g|0)|0;T=D;U=Rd((ia|fa)^g|0,X^T|0,24)|0;ca=D;X=Pd((ia|fa)^g|0,X^T|0,40)|0;ca=D|ca;ba=oe(X|U|0,ca|0,f|0,ba|0)|0;ba=oe(ba|0,D|0,E|0,F|0)|0;f=D;c[P+8>>2]=ba;c[P+8+4>>2]=f;fa=Rd(ka^ba|0,ga^f|0,16)|0;ia=D;ga=Pd(ka^ba|0,ga^f|0,48)|0;ia=D|ia;T=oe(ga|fa|0,ia|0,g|0,T|0)|0;g=D;c[P+88>>2]=T;c[P+88+4>>2]=g;ka=Rd((X|U)^T|0,ca^g|0,63)|0;$=D;g=Pd((X|U)^T|0,ca^g|0,1)|0;c[P+48>>2]=g|ka;c[P+48+4>>2]=D|$;W=oe(aa|_|0,V|0,R|0,W|0)|0;W=oe(W|0,D|0,G|0,I|0)|0;R=D;$=c[P+104>>2]^W;ka=c[P+104+4>>2]^R;g=oe(ka|0,$|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;ca=D;T=Rd((aa|_)^g|0,V^ca|0,24)|0;U=D;V=Pd((aa|_)^g|0,V^ca|0,40)|0;U=D|U;R=oe(V|T|0,U|0,W|0,R|0)|0;R=oe(R|0,D|0,J|0,K|0)|0;W=D;c[P+16>>2]=R;c[P+16+4>>2]=W;_=Rd(ka^R|0,$^W|0,16)|0;aa=D;$=Pd(ka^R|0,$^W|0,48)|0;aa=D|aa;ca=oe($|_|0,aa|0,g|0,ca|0)|0;g=D;ka=Rd((V|T)^ca|0,U^g|0,63)|0;X=D;U=Pd((V|T)^ca|0,U^g|0,1)|0;c[P+56>>2]=U|ka;c[P+56+4>>2]=D|X;X=c[P+32>>2]|0;ka=c[P+32+4>>2]|0;S=oe(X|0,ka|0,e|0,S|0)|0;S=oe(S|0,D|0,L|0,M|0)|0;e=D;U=c[P+112>>2]^S;T=c[P+112+4>>2]^e;V=oe(T|0,U|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;Y=D;ja=Rd(X^V|0,ka^Y|0,24)|0;Q=D;ka=Pd(X^V|0,ka^Y|0,40)|0;Q=D|Q;e=oe(ka|ja|0,Q|0,S|0,e|0)|0;e=oe(e|0,D|0,N|0,b|0)|0;S=D;c[P+24>>2]=e;c[P+24+4>>2]=S;X=Rd(T^e|0,U^S|0,16)|0;Z=D;U=Pd(T^e|0,U^S|0,48)|0;Z=D|Z;Y=oe(U|X|0,Z|0,V|0,Y|0)|0;V=D;T=Rd((ka|ja)^Y|0,Q^V|0,63)|0;da=D;Q=Pd((ka|ja)^Y|0,Q^V|0,1)|0;da=D|da;ea=oe(Q|T|0,da|0,ha|0,ea|0)|0;ea=oe(ea|0,D|0,L|0,M|0)|0;ha=D;g=oe(ia^ha|0,(ga|fa)^ea|0,ca|0,g|0)|0;L=D;ca=Rd((Q|T)^g|0,da^L|0,24)|0;M=D;da=Pd((Q|T)^g|0,da^L|0,40)|0;M=D|M;T=oe(da|ca|0,M|0,ea|0,ha|0)|0;T=oe(T|0,D|0,B|0,C|0)|0;Q=D;c[P>>2]=T;c[P+4>>2]=Q;B=Rd(ia^ha^T|0,(ga|fa)^ea^Q|0,16)|0;C=D;ea=Pd(ia^ha^T|0,(ga|fa)^ea^Q|0,48)|0;C=D|C;c[P+96>>2]=ea|B;c[P+96+4>>2]=C;C=oe(ea|B|0,C|0,g|0,L|0)|0;L=D;c[P+64>>2]=C;c[P+64+4>>2]=L;B=Rd((da|ca)^C|0,M^L|0,63)|0;g=D;L=Pd((da|ca)^C|0,M^L|0,1)|0;c[P+32>>2]=L|B;c[P+32+4>>2]=D|g;g=c[P+40>>2]|0;B=c[P+40+4>>2]|0;L=oe(g|0,B|0,ba|0,f|0)|0;L=oe(L|0,D|0,o|0,p|0)|0;p=D;V=oe(aa^p|0,($|_)^L|0,Y|0,V|0)|0;Y=D;M=Rd(g^V|0,B^Y|0,24)|0;C=D;B=Pd(g^V|0,B^Y|0,40)|0;C=D|C;o=oe(B|M|0,C|0,L|0,p|0)|0;o=oe(o|0,D|0,x|0,y|0)|0;x=D;c[P+8>>2]=o;c[P+8+4>>2]=x;g=Rd(aa^p^o|0,($|_)^L^x|0,16)|0;f=D;y=Pd(aa^p^o|0,($|_)^L^x|0,48)|0;f=D|f;c[P+104>>2]=y|g;c[P+104+4>>2]=f;Y=oe(y|g|0,f|0,V|0,Y|0)|0;V=D;c[P+72>>2]=Y;c[P+72+4>>2]=V;f=Rd((B|M)^Y|0,C^V|0,63)|0;g=D;V=Pd((B|M)^Y|0,C^V|0,1)|0;g=D|g;C=c[P+48>>2]|0;Y=c[P+48+4>>2]|0;M=oe(C|0,Y|0,R|0,W|0)|0;M=oe(M|0,D|0,z|0,A|0)|0;z=D;y=oe(Z^z|0,(U|X)^M|0,c[P+80>>2]|0,c[P+80+4>>2]|0)|0;W=D;R=Rd(C^y|0,Y^W|0,24)|0;B=D;Y=Pd(C^y|0,Y^W|0,40)|0;B=D|B;C=oe(Y|R|0,B|0,M|0,z|0)|0;C=oe(C|0,D|0,N|0,b|0)|0;L=D;c[P+16>>2]=C;c[P+16+4>>2]=L;N=Rd(Z^z^C|0,(U|X)^M^L|0,16)|0;b=D;M=Pd(Z^z^C|0,(U|X)^M^L|0,48)|0;b=D|b;c[P+112>>2]=M|N;c[P+112+4>>2]=b;W=oe(M|N|0,b|0,y|0,W|0)|0;b=D;N=Rd((Y|R)^W|0,B^b|0,63)|0;y=D;B=Pd((Y|R)^W|0,B^b|0,1)|0;y=D|y;R=c[P+56>>2]|0;Y=c[P+56+4>>2]|0;M=oe(R|0,Y|0,e|0,S|0)|0;M=oe(M|0,D|0,J|0,K|0)|0;K=D;S=c[P+120>>2]^M;e=c[P+120+4>>2]^K;z=oe(e|0,S|0,c[P+88>>2]|0,c[P+88+4>>2]|0)|0;p=D;X=Rd(R^z|0,Y^p|0,24)|0;A=D;Y=Pd(R^z|0,Y^p|0,40)|0;A=D|A;K=oe(Y|X|0,A|0,M|0,K|0)|0;K=oe(K|0,D|0,s|0,t|0)|0;M=D;c[P+24>>2]=K;c[P+24+4>>2]=M;R=Rd(e^K|0,S^M|0,16)|0;U=D;S=Pd(e^K|0,S^M|0,48)|0;U=D|U;p=oe(S|R|0,U|0,z|0,p|0)|0;z=D;e=Rd((Y|X)^p|0,A^z|0,63)|0;J=D;A=Pd((Y|X)^p|0,A^z|0,1)|0;J=D|J;Q=oe(V|f|0,g|0,T|0,Q|0)|0;Q=oe(Q|0,D|0,h|0,j|0)|0;T=D;t=oe(U^T|0,(S|R)^Q|0,W|0,b|0)|0;s=D;h=Rd((V|f)^t|0,g^s|0,24)|0;j=D;g=Pd((V|f)^t|0,g^s|0,40)|0;j=D|j;f=oe(g|h|0,j|0,Q|0,T|0)|0;f=oe(f|0,D|0,G|0,I|0)|0;b=D;c[P>>2]=f;c[P+4>>2]=b;I=Rd(U^T^f|0,(S|R)^Q^b|0,16)|0;G=D;Q=Pd(U^T^f|0,(S|R)^Q^b|0,48)|0;G=D|G;c[P+120>>2]=Q|I;c[P+120+4>>2]=G;G=oe(Q|I|0,G|0,t|0,s|0)|0;I=D;c[P+80>>2]=G;c[P+80+4>>2]=I;s=Rd((g|h)^G|0,j^I|0,63)|0;t=D;I=Pd((g|h)^G|0,j^I|0,1)|0;c[P+40>>2]=I|s;c[P+40+4>>2]=D|t;x=oe(B|N|0,y|0,o|0,x|0)|0;x=oe(x|0,D|0,v|0,H|0)|0;t=D;v=c[P+96>>2]^x;s=c[P+96+4>>2]^t;H=oe(s|0,v|0,p|0,z|0)|0;I=D;z=Rd((B|N)^H|0,y^I|0,24)|0;G=D;y=Pd((B|N)^H|0,y^I|0,40)|0;G=D|G;t=oe(y|z|0,G|0,x|0,t|0)|0;t=oe(t|0,D|0,k|0,l|0)|0;x=D;c[P+8>>2]=t;c[P+8+4>>2]=x;N=Rd(s^t|0,v^x|0,16)|0;B=D;x=Pd(s^t|0,v^x|0,48)|0;B=D|B;c[P+96>>2]=x|N;c[P+96+4>>2]=B;I=oe(x|N|0,B|0,H|0,I|0)|0;H=D;c[P+88>>2]=I;c[P+88+4>>2]=H;B=Rd((y|z)^I|0,G^H|0,63)|0;N=D;H=Pd((y|z)^I|0,G^H|0,1)|0;c[P+48>>2]=H|B;c[P+48+4>>2]=D|N;L=oe(A|e|0,J|0,C|0,L|0)|0;L=oe(L|0,D|0,E|0,F|0)|0;C=D;N=c[P+104>>2]^L;B=c[P+104+4>>2]^C;H=oe(B|0,N|0,c[P+64>>2]|0,c[P+64+4>>2]|0)|0;G=D;E=Rd((A|e)^H|0,J^G|0,24)|0;F=D;J=Pd((A|e)^H|0,J^G|0,40)|0;F=D|F;C=oe(J|E|0,F|0,L|0,C|0)|0;C=oe(C|0,D|0,u|0,w|0)|0;L=D;c[P+16>>2]=C;c[P+16+4>>2]=L;e=Rd(B^C|0,N^L|0,16)|0;I=D;L=Pd(B^C|0,N^L|0,48)|0;I=D|I;c[P+104>>2]=L|e;c[P+104+4>>2]=I;G=oe(L|e|0,I|0,H|0,G|0)|0;H=D;c[P+64>>2]=G;c[P+64+4>>2]=H;I=Rd((J|E)^G|0,F^H|0,63)|0;e=D;H=Pd((J|E)^G|0,F^H|0,1)|0;c[P+56>>2]=H|I;c[P+56+4>>2]=D|e;e=c[P+32>>2]|0;I=c[P+32+4>>2]|0;H=oe(e|0,I|0,K|0,M|0)|0;H=oe(H|0,D|0,q|0,r|0)|0;F=D;G=c[P+112>>2]^H;E=c[P+112+4>>2]^F;M=oe(E|0,G|0,c[P+72>>2]|0,c[P+72+4>>2]|0)|0;K=D;J=Rd(e^M|0,I^K|0,24)|0;L=D;I=Pd(e^M|0,I^K|0,40)|0;L=D|L;F=oe(I|J|0,L|0,H|0,F|0)|0;F=oe(F|0,D|0,m|0,n|0)|0;H=D;c[P+24>>2]=F;c[P+24+4>>2]=H;e=Rd(E^F|0,G^H|0,16)|0;N=D;H=Pd(E^F|0,G^H|0,48)|0;N=D|N;c[P+112>>2]=H|e;c[P+112+4>>2]=N;K=oe(H|e|0,N|0,M|0,K|0)|0;M=D;c[P+72>>2]=K;c[P+72+4>>2]=M;N=Rd((I|J)^K|0,L^M|0,63)|0;e=D;M=Pd((I|J)^K|0,L^M|0,1)|0;c[P+32>>2]=M|N;c[P+32+4>>2]=D|e;e=0;while(1){ma=a+(e<<3)|0;la=P+(e+8<<3)|0;b=b^c[ma+4>>2]^c[la+4>>2];c[ma>>2]=f^c[ma>>2]^c[la>>2];c[ma+4>>2]=b;b=e+1|0;if((b|0)==8)break;e=b;f=c[P+(b<<3)>>2]|0;b=c[P+(b<<3)+4>>2]|0}i=O;return}function ja(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,fb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0,sc=0,tc=0,uc=0,vc=0,wc=0,xc=0,yc=0,zc=0;O=d[c>>0]|0;P=Pd(d[c+1>>0]|0|0,0,8)|0;jb=D;j=d[c+2>>0]|0;db=Pd(j|0,0,16)|0;Ma=Pd(d[c+3>>0]|0|0,0,8)|0;qb=D;A=Pd(d[c+4>>0]|0|0,0,16)|0;qb=qb|D;nb=d[c+5>>0]|0;z=Pd(nb|0,0,24)|0;qb=Rd(Ma|j|A|z|0,qb|D|0,5)|0;z=Pd(d[c+6>>0]|0|0,0,8)|0;A=D;j=d[c+7>>0]|0;Ma=Pd(j|0,0,16)|0;A=Rd(z|nb|Ma|0,A|D|0,2)|0;Ma=Pd(d[c+8>>0]|0|0,0,8)|0;nb=D;z=Pd(d[c+9>>0]|0|0,0,16)|0;nb=nb|D;ca=d[c+10>>0]|0;lb=Pd(ca|0,0,24)|0;nb=Rd(Ma|j|z|lb|0,nb|D|0,7)|0;lb=Pd(d[c+11>>0]|0|0,0,8)|0;z=D;j=Pd(d[c+12>>0]|0|0,0,16)|0;z=z|D;Ma=d[c+13>>0]|0;ra=Pd(Ma|0,0,24)|0;z=Rd(lb|ca|j|ra|0,z|D|0,4)|0;ra=Pd(d[c+14>>0]|0|0,0,8)|0;j=D;ca=d[c+15>>0]|0;lb=Pd(ca|0,0,16)|0;j=Rd(ra|Ma|lb|0,j|D|0,1)|0;lb=Pd(d[c+16>>0]|0|0,0,8)|0;Ma=D;ra=Pd(d[c+17>>0]|0|0,0,16)|0;Ma=Ma|D;Ca=d[c+18>>0]|0;I=Pd(Ca|0,0,24)|0;Ma=Rd(lb|ca|ra|I|0,Ma|D|0,6)|0;I=Pd(d[c+19>>0]|0|0,0,8)|0;ra=D;ca=Pd(d[c+20>>0]|0|0,0,16)|0;ra=Rd(I|Ca|ca|0,ra|D|0,3)|0;ca=D;Ca=d[c+21>>0]|0;I=Pd(d[c+22>>0]|0|0,0,8)|0;lb=D;eb=d[c+23>>0]|0;Ja=Pd(eb|0,0,16)|0;ba=Pd(d[c+24>>0]|0|0,0,8)|0;La=D;sc=Pd(d[c+25>>0]|0|0,0,16)|0;La=La|D;o=d[c+26>>0]|0;rb=Pd(o|0,0,24)|0;La=Rd(ba|eb|sc|rb|0,La|D|0,5)|0;rb=Pd(d[c+27>>0]|0|0,0,8)|0;sc=D;eb=d[c+28>>0]|0;ba=Pd(eb|0,0,16)|0;sc=Rd(rb|o|ba|0,sc|D|0,2)|0;ba=Pd(d[c+29>>0]|0|0,0,8)|0;o=D;rb=Pd(d[c+30>>0]|0|0,0,16)|0;o=o|D;Da=Pd(d[c+31>>0]|0|0,0,24)|0;o=Rd(ba|eb|rb|Da|0,o|D|0,7)|0;Da=D;rb=d[e>>0]|0;eb=Pd(d[e+1>>0]|0|0,0,8)|0;ba=D;Ta=d[e+2>>0]|0;aa=Pd(Ta|0,0,16)|0;m=Pd(d[e+3>>0]|0|0,0,8)|0;Ya=D;q=Pd(d[e+4>>0]|0|0,0,16)|0;Ya=Ya|D;p=d[e+5>>0]|0;ea=Pd(p|0,0,24)|0;Ya=Rd(m|Ta|q|ea|0,Ya|D|0,5)|0;ea=Pd(d[e+6>>0]|0|0,0,8)|0;q=D;Ta=d[e+7>>0]|0;m=Pd(Ta|0,0,16)|0;q=Rd(ea|p|m|0,q|D|0,2)|0;m=Pd(d[e+8>>0]|0|0,0,8)|0;p=D;ea=Pd(d[e+9>>0]|0|0,0,16)|0;p=p|D;wc=d[e+10>>0]|0;wa=Pd(wc|0,0,24)|0;p=Rd(m|Ta|ea|wa|0,p|D|0,7)|0;wa=Pd(d[e+11>>0]|0|0,0,8)|0;ea=D;Ta=Pd(d[e+12>>0]|0|0,0,16)|0;ea=ea|D;m=d[e+13>>0]|0;zc=Pd(m|0,0,24)|0;ea=Rd(wa|wc|Ta|zc|0,ea|D|0,4)|0;zc=Pd(d[e+14>>0]|0|0,0,8)|0;Ta=D;wc=d[e+15>>0]|0;wa=Pd(wc|0,0,16)|0;Ta=Rd(zc|m|wa|0,Ta|D|0,1)|0;wa=Pd(d[e+16>>0]|0|0,0,8)|0;m=D;zc=Pd(d[e+17>>0]|0|0,0,16)|0;m=m|D;ub=d[e+18>>0]|0;uc=Pd(ub|0,0,24)|0;m=Rd(wa|wc|zc|uc|0,m|D|0,6)|0;uc=Pd(d[e+19>>0]|0|0,0,8)|0;zc=D;wc=Pd(d[e+20>>0]|0|0,0,16)|0;zc=Rd(uc|ub|wc|0,zc|D|0,3)|0;wc=D;ub=d[e+21>>0]|0;uc=Pd(d[e+22>>0]|0|0,0,8)|0;wa=D;pc=d[e+23>>0]|0;na=Pd(pc|0,0,16)|0;W=Pd(d[e+24>>0]|0|0,0,8)|0;Ia=D;K=Pd(d[e+25>>0]|0|0,0,16)|0;Ia=Ia|D;x=d[e+26>>0]|0;qc=Pd(x|0,0,24)|0;Ia=Rd(W|pc|K|qc|0,Ia|D|0,5)|0;qc=Pd(d[e+27>>0]|0|0,0,8)|0;K=D;pc=d[e+28>>0]|0;W=Pd(pc|0,0,16)|0;K=Rd(qc|x|W|0,K|D|0,2)|0;W=Pd(d[e+29>>0]|0|0,0,8)|0;x=D;qc=Pd(d[e+30>>0]|0|0,0,16)|0;x=x|D;Ba=Pd(d[e+31>>0]|0|0,0,24)|0;x=Rd(W|pc|qc|Ba|0,x|D|0,7)|0;Ba=D;qc=d[f>>0]|0;pc=Pd(d[f+1>>0]|0|0,0,8)|0;W=D;y=d[f+2>>0]|0;rc=Pd(y|0,0,16)|0;Qa=Pd(d[f+3>>0]|0|0,0,8)|0;xa=D;Fa=Pd(d[f+4>>0]|0|0,0,16)|0;xa=xa|D;ib=d[f+5>>0]|0;za=Pd(ib|0,0,24)|0;xa=Rd(Qa|y|Fa|za|0,xa|D|0,5)|0;za=Pd(d[f+6>>0]|0|0,0,8)|0;Fa=D;y=d[f+7>>0]|0;Qa=Pd(y|0,0,16)|0;Fa=Rd(za|ib|Qa|0,Fa|D|0,2)|0;Qa=Pd(d[f+8>>0]|0|0,0,8)|0;ib=D;za=Pd(d[f+9>>0]|0|0,0,16)|0;ib=ib|D;h=d[f+10>>0]|0;Y=Pd(h|0,0,24)|0;ib=Rd(Qa|y|za|Y|0,ib|D|0,7)|0;Y=Pd(d[f+11>>0]|0|0,0,8)|0;za=D;y=Pd(d[f+12>>0]|0|0,0,16)|0;za=za|D;Qa=d[f+13>>0]|0;B=Pd(Qa|0,0,24)|0;za=Rd(Y|h|y|B|0,za|D|0,4)|0;B=Pd(d[f+14>>0]|0|0,0,8)|0;y=D;h=d[f+15>>0]|0;Y=Pd(h|0,0,16)|0;y=Rd(B|Qa|Y|0,y|D|0,1)|0;Y=Pd(d[f+16>>0]|0|0,0,8)|0;Qa=D;B=Pd(d[f+17>>0]|0|0,0,16)|0;Qa=Qa|D;sa=d[f+18>>0]|0;H=Pd(sa|0,0,24)|0;Qa=Rd(Y|h|B|H|0,Qa|D|0,6)|0;H=Pd(d[f+19>>0]|0|0,0,8)|0;B=D;h=Pd(d[f+20>>0]|0|0,0,16)|0;B=Rd(H|sa|h|0,B|D|0,3)|0;h=D;sa=d[f+21>>0]|0;H=Pd(d[f+22>>0]|0|0,0,8)|0;Y=D;ma=d[f+23>>0]|0;Z=Pd(ma|0,0,16)|0;ua=Pd(d[f+24>>0]|0|0,0,8)|0;G=D;N=Pd(d[f+25>>0]|0|0,0,16)|0;G=G|D;c=d[f+26>>0]|0;Aa=Pd(c|0,0,24)|0;G=Rd(ua|ma|N|Aa|0,G|D|0,5)|0;Aa=Pd(d[f+27>>0]|0|0,0,8)|0;N=D;ma=d[f+28>>0]|0;ua=Pd(ma|0,0,16)|0;N=Rd(Aa|c|ua|0,N|D|0,2)|0;ua=Pd(d[f+29>>0]|0|0,0,8)|0;c=D;Aa=Pd(d[f+30>>0]|0|0,0,16)|0;c=c|D;i=Pd(d[f+31>>0]|0|0,0,24)|0;c=Rd(ua|ma|Aa|i|0,c|D|0,7)|0;i=D;Aa=Ed(eb|rb|aa&2031616|0,ba|0,P|O|db&2031616|0,jb|0)|0;Aa=oe(pc|qc|rc&2031616|0,W|0,Aa|0,D|0)|0;W=D;rc=Ed(Ya&2097151|0,0,P|O|db&2031616|0,jb|0)|0;qc=D;pc=Ed(eb|rb|aa&2031616|0,ba|0,qb&2097151|0,0)|0;ma=D;ua=Ed(q&2097151|0,0,P|O|db&2031616|0,jb|0)|0;Ea=D;va=Ed(Ya&2097151|0,0,qb&2097151|0,0)|0;kc=D;ia=Ed(eb|rb|aa&2031616|0,ba|0,A&2097151|0,0)|0;ia=oe(va|0,kc|0,ia|0,D|0)|0;Ea=oe(ia|0,D|0,ua|0,Ea|0)|0;Fa=oe(Ea|0,D|0,Fa&2097151|0,0)|0;Ea=D;ua=Ed(p&2097151|0,0,P|O|db&2031616|0,jb|0)|0;ia=D;kc=Ed(q&2097151|0,0,qb&2097151|0,0)|0;va=D;oc=Ed(Ya&2097151|0,0,A&2097151|0,0)|0;nc=D;mc=Ed(eb|rb|aa&2031616|0,ba|0,nb&2097151|0,0)|0;lc=D;Ha=Ed(ea&2097151|0,0,P|O|db&2031616|0,jb|0)|0;ya=D;bc=Ed(p&2097151|0,0,qb&2097151|0,0)|0;u=D;dc=Ed(q&2097151|0,0,A&2097151|0,0)|0;Ga=D;ec=Ed(Ya&2097151|0,0,nb&2097151|0,0)|0;fc=D;cc=Ed(eb|rb|aa&2031616|0,ba|0,z&2097151|0,0)|0;cc=oe(ec|0,fc|0,cc|0,D|0)|0;Ga=oe(cc|0,D|0,dc|0,Ga|0)|0;u=oe(Ga|0,D|0,bc|0,u|0)|0;ya=oe(u|0,D|0,Ha|0,ya|0)|0;za=oe(ya|0,D|0,za&2097151|0,0)|0;ya=D;Ha=Ed(Ta&2097151|0,0,P|O|db&2031616|0,jb|0)|0;u=D;bc=Ed(ea&2097151|0,0,qb&2097151|0,0)|0;Ga=D;dc=Ed(p&2097151|0,0,A&2097151|0,0)|0;cc=D;fc=Ed(q&2097151|0,0,nb&2097151|0,0)|0;ec=D;jc=Ed(Ya&2097151|0,0,z&2097151|0,0)|0;ic=D;hc=Ed(eb|rb|aa&2031616|0,ba|0,j&2097151|0,0)|0;gc=D;X=Ed(m&2097151|0,0,P|O|db&2031616|0,jb|0)|0;Ra=D;Qb=Ed(Ta&2097151|0,0,qb&2097151|0,0)|0;da=D;Sb=Ed(ea&2097151|0,0,A&2097151|0,0)|0;Pb=D;Ub=Ed(p&2097151|0,0,nb&2097151|0,0)|0;Rb=D;Wb=Ed(q&2097151|0,0,z&2097151|0,0)|0;Tb=D;Xb=Ed(Ya&2097151|0,0,j&2097151|0,0)|0;Yb=D;Vb=Ed(eb|rb|aa&2031616|0,ba|0,Ma&2097151|0,0)|0;Vb=oe(Xb|0,Yb|0,Vb|0,D|0)|0;Tb=oe(Vb|0,D|0,Wb|0,Tb|0)|0;Rb=oe(Tb|0,D|0,Ub|0,Rb|0)|0;Pb=oe(Rb|0,D|0,Sb|0,Pb|0)|0;da=oe(Pb|0,D|0,Qb|0,da|0)|0;Ra=oe(da|0,D|0,X|0,Ra|0)|0;Qa=oe(Ra|0,D|0,Qa&2097151|0,0)|0;Ra=D;X=Ed(zc|0,wc|0,P|O|db&2031616|0,jb|0)|0;da=D;Qb=Ed(m&2097151|0,0,qb&2097151|0,0)|0;Pb=D;Sb=Ed(Ta&2097151|0,0,A&2097151|0,0)|0;Rb=D;Ub=Ed(ea&2097151|0,0,nb&2097151|0,0)|0;Tb=D;Wb=Ed(p&2097151|0,0,z&2097151|0,0)|0;Vb=D;Yb=Ed(q&2097151|0,0,j&2097151|0,0)|0;Xb=D;ac=Ed(Ya&2097151|0,0,Ma&2097151|0,0)|0;$b=D;_b=Ed(eb|rb|aa&2031616|0,ba|0,ra|0,ca|0)|0;Zb=D;ta=Ed(uc|ub|na&2031616|0,wa|0,P|O|db&2031616|0,jb|0)|0;yb=D;zb=Ed(zc|0,wc|0,qb&2097151|0,0)|0;Ab=D;Bb=Ed(m&2097151|0,0,A&2097151|0,0)|0;Cb=D;Db=Ed(Ta&2097151|0,0,nb&2097151|0,0)|0;Eb=D;Fb=Ed(ea&2097151|0,0,z&2097151|0,0)|0;Gb=D;Hb=Ed(p&2097151|0,0,j&2097151|0,0)|0;Ib=D;Jb=Ed(q&2097151|0,0,Ma&2097151|0,0)|0;Kb=D;Mb=Ed(Ya&2097151|0,0,ra|0,ca|0)|0;Nb=D;Ob=Ed(eb|rb|aa&2031616|0,ba|0,I|Ca|Ja&2031616|0,lb|0)|0;Ob=oe(Mb|0,Nb|0,Ob|0,D|0)|0;Kb=oe(Ob|0,D|0,Jb|0,Kb|0)|0;Ib=oe(Kb|0,D|0,Hb|0,Ib|0)|0;Gb=oe(Ib|0,D|0,Fb|0,Gb|0)|0;Eb=oe(Gb|0,D|0,Db|0,Eb|0)|0;Cb=oe(Eb|0,D|0,Bb|0,Cb|0)|0;Ab=oe(Cb|0,D|0,zb|0,Ab|0)|0;yb=oe(Ab|0,D|0,ta|0,yb|0)|0;Y=oe(yb|0,D|0,H|sa|Z&2031616|0,Y|0)|0;Z=D;sa=Ed(Ia&2097151|0,0,P|O|db&2031616|0,jb|0)|0;H=D;yb=Ed(uc|ub|na&2031616|0,wa|0,qb&2097151|0,0)|0;ta=D;Ab=Ed(zc|0,wc|0,A&2097151|0,0)|0;zb=D;Cb=Ed(m&2097151|0,0,nb&2097151|0,0)|0;Bb=D;Eb=Ed(Ta&2097151|0,0,z&2097151|0,0)|0;Db=D;Gb=Ed(ea&2097151|0,0,j&2097151|0,0)|0;Fb=D;Ib=Ed(p&2097151|0,0,Ma&2097151|0,0)|0;Hb=D;Kb=Ed(q&2097151|0,0,ra|0,ca|0)|0;Jb=D;Ob=Ed(Ya&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;Nb=D;Mb=Ed(eb|rb|aa&2031616|0,ba|0,La&2097151|0,0)|0;Lb=D;ab=Ed(K&2097151|0,0,P|O|db&2031616|0,jb|0)|0;M=D;Q=Ed(Ia&2097151|0,0,qb&2097151|0,0)|0;bb=D;ob=Ed(uc|ub|na&2031616|0,wa|0,A&2097151|0,0)|0;R=D;J=Ed(zc|0,wc|0,nb&2097151|0,0)|0;pb=D;Oa=Ed(m&2097151|0,0,z&2097151|0,0)|0;C=D;gb=Ed(Ta&2097151|0,0,j&2097151|0,0)|0;Pa=D;U=Ed(ea&2097151|0,0,Ma&2097151|0,0)|0;hb=D;Wa=Ed(p&2097151|0,0,ra|0,ca|0)|0;V=D;xb=Ed(q&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;Xa=D;fa=Ed(Ya&2097151|0,0,La&2097151|0,0)|0;w=D;wb=Ed(eb|rb|aa&2031616|0,ba|0,sc&2097151|0,0)|0;wb=oe(fa|0,w|0,wb|0,D|0)|0;Xa=oe(wb|0,D|0,xb|0,Xa|0)|0;V=oe(Xa|0,D|0,Wa|0,V|0)|0;hb=oe(V|0,D|0,U|0,hb|0)|0;Pa=oe(hb|0,D|0,gb|0,Pa|0)|0;C=oe(Pa|0,D|0,Oa|0,C|0)|0;pb=oe(C|0,D|0,J|0,pb|0)|0;R=oe(pb|0,D|0,ob|0,R|0)|0;bb=oe(R|0,D|0,Q|0,bb|0)|0;M=oe(bb|0,D|0,ab|0,M|0)|0;N=oe(M|0,D|0,N&2097151|0,0)|0;M=D;jb=Ed(x|0,Ba|0,P|O|db&2031616|0,jb|0)|0;db=D;O=Ed(K&2097151|0,0,qb&2097151|0,0)|0;P=D;ab=Ed(Ia&2097151|0,0,A&2097151|0,0)|0;bb=D;Q=Ed(uc|ub|na&2031616|0,wa|0,nb&2097151|0,0)|0;R=D;ob=Ed(zc|0,wc|0,z&2097151|0,0)|0;pb=D;J=Ed(m&2097151|0,0,j&2097151|0,0)|0;C=D;Oa=Ed(Ta&2097151|0,0,Ma&2097151|0,0)|0;Pa=D;gb=Ed(ea&2097151|0,0,ra|0,ca|0)|0;hb=D;U=Ed(p&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;V=D;Wa=Ed(q&2097151|0,0,La&2097151|0,0)|0;Xa=D;xb=Ed(Ya&2097151|0,0,sc&2097151|0,0)|0;wb=D;ba=Ed(eb|rb|aa&2031616|0,ba|0,o|0,Da|0)|0;aa=D;qb=Ed(x|0,Ba|0,qb&2097151|0,0)|0;rb=D;eb=Ed(K&2097151|0,0,A&2097151|0,0)|0;w=D;fa=Ed(Ia&2097151|0,0,nb&2097151|0,0)|0;fb=D;ha=Ed(uc|ub|na&2031616|0,wa|0,z&2097151|0,0)|0;$=D;sb=Ed(zc|0,wc|0,j&2097151|0,0)|0;kb=D;la=Ed(m&2097151|0,0,Ma&2097151|0,0)|0;tb=D;qa=Ed(Ta&2097151|0,0,ra|0,ca|0)|0;ka=D;Na=Ed(ea&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;pa=D;Za=Ed(p&2097151|0,0,La&2097151|0,0)|0;ga=D;mb=Ed(q&2097151|0,0,sc&2097151|0,0)|0;v=D;Ya=Ed(Ya&2097151|0,0,o|0,Da|0)|0;Ya=oe(mb|0,v|0,Ya|0,D|0)|0;ga=oe(Ya|0,D|0,Za|0,ga|0)|0;pa=oe(ga|0,D|0,Na|0,pa|0)|0;ka=oe(pa|0,D|0,qa|0,ka|0)|0;tb=oe(ka|0,D|0,la|0,tb|0)|0;kb=oe(tb|0,D|0,sb|0,kb|0)|0;$=oe(kb|0,D|0,ha|0,$|0)|0;fb=oe($|0,D|0,fa|0,fb|0)|0;w=oe(fb|0,D|0,eb|0,w|0)|0;rb=oe(w|0,D|0,qb|0,rb|0)|0;qb=D;A=Ed(x|0,Ba|0,A&2097151|0,0)|0;w=D;eb=Ed(K&2097151|0,0,nb&2097151|0,0)|0;fb=D;fa=Ed(Ia&2097151|0,0,z&2097151|0,0)|0;$=D;ha=Ed(uc|ub|na&2031616|0,wa|0,j&2097151|0,0)|0;kb=D;sb=Ed(zc|0,wc|0,Ma&2097151|0,0)|0;tb=D;la=Ed(m&2097151|0,0,ra|0,ca|0)|0;ka=D;qa=Ed(Ta&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;pa=D;Na=Ed(ea&2097151|0,0,La&2097151|0,0)|0;ga=D;Za=Ed(p&2097151|0,0,sc&2097151|0,0)|0;Ya=D;q=Ed(q&2097151|0,0,o|0,Da|0)|0;v=D;nb=Ed(x|0,Ba|0,nb&2097151|0,0)|0;mb=D;_a=Ed(K&2097151|0,0,z&2097151|0,0)|0;r=D;E=Ed(Ia&2097151|0,0,j&2097151|0,0)|0;$a=D;n=Ed(uc|ub|na&2031616|0,wa|0,Ma&2097151|0,0)|0;t=D;_=Ed(zc|0,wc|0,ra|0,ca|0)|0;g=D;ja=Ed(m&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;s=D;oa=Ed(Ta&2097151|0,0,La&2097151|0,0)|0;F=D;vb=Ed(ea&2097151|0,0,sc&2097151|0,0)|0;l=D;p=Ed(p&2097151|0,0,o|0,Da|0)|0;p=oe(vb|0,l|0,p|0,D|0)|0;F=oe(p|0,D|0,oa|0,F|0)|0;s=oe(F|0,D|0,ja|0,s|0)|0;g=oe(s|0,D|0,_|0,g|0)|0;t=oe(g|0,D|0,n|0,t|0)|0;$a=oe(t|0,D|0,E|0,$a|0)|0;r=oe($a|0,D|0,_a|0,r|0)|0;mb=oe(r|0,D|0,nb|0,mb|0)|0;nb=D;z=Ed(x|0,Ba|0,z&2097151|0,0)|0;r=D;_a=Ed(K&2097151|0,0,j&2097151|0,0)|0;$a=D;E=Ed(Ia&2097151|0,0,Ma&2097151|0,0)|0;t=D;n=Ed(uc|ub|na&2031616|0,wa|0,ra|0,ca|0)|0;g=D;_=Ed(zc|0,wc|0,I|Ca|Ja&2031616|0,lb|0)|0;s=D;ja=Ed(m&2097151|0,0,La&2097151|0,0)|0;F=D;oa=Ed(Ta&2097151|0,0,sc&2097151|0,0)|0;p=D;ea=Ed(ea&2097151|0,0,o|0,Da|0)|0;l=D;j=Ed(x|0,Ba|0,j&2097151|0,0)|0;vb=D;e=Ed(K&2097151|0,0,Ma&2097151|0,0)|0;L=D;T=Ed(Ia&2097151|0,0,ra|0,ca|0)|0;Ka=D;Va=Ed(uc|ub|na&2031616|0,wa|0,I|Ca|Ja&2031616|0,lb|0)|0;S=D;Sa=Ed(zc|0,wc|0,La&2097151|0,0)|0;Ua=D;f=Ed(m&2097151|0,0,sc&2097151|0,0)|0;k=D;Ta=Ed(Ta&2097151|0,0,o|0,Da|0)|0;Ta=oe(f|0,k|0,Ta|0,D|0)|0;Ua=oe(Ta|0,D|0,Sa|0,Ua|0)|0;S=oe(Ua|0,D|0,Va|0,S|0)|0;Ka=oe(S|0,D|0,T|0,Ka|0)|0;L=oe(Ka|0,D|0,e|0,L|0)|0;vb=oe(L|0,D|0,j|0,vb|0)|0;j=D;Ma=Ed(x|0,Ba|0,Ma&2097151|0,0)|0;L=D;e=Ed(K&2097151|0,0,ra|0,ca|0)|0;Ka=D;T=Ed(Ia&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;S=D;Va=Ed(uc|ub|na&2031616|0,wa|0,La&2097151|0,0)|0;Ua=D;Sa=Ed(zc|0,wc|0,sc&2097151|0,0)|0;Ta=D;m=Ed(m&2097151|0,0,o|0,Da|0)|0;k=D;ca=Ed(x|0,Ba|0,ra|0,ca|0)|0;f=D;ra=Ed(K&2097151|0,0,I|Ca|Ja&2031616|0,lb|0)|0;cb=D;vc=Ed(Ia&2097151|0,0,La&2097151|0,0)|0;tc=D;yc=Ed(uc|ub|na&2031616|0,wa|0,sc&2097151|0,0)|0;xc=D;wc=Ed(zc|0,wc|0,o|0,Da|0)|0;wc=oe(yc|0,xc|0,wc|0,D|0)|0;tc=oe(wc|0,D|0,vc|0,tc|0)|0;cb=oe(tc|0,D|0,ra|0,cb|0)|0;f=oe(cb|0,D|0,ca|0,f|0)|0;ca=D;lb=Ed(x|0,Ba|0,I|Ca|Ja&2031616|0,lb|0)|0;Ja=D;Ca=Ed(K&2097151|0,0,La&2097151|0,0)|0;I=D;cb=Ed(Ia&2097151|0,0,sc&2097151|0,0)|0;ra=D;wa=Ed(uc|ub|na&2031616|0,wa|0,o|0,Da|0)|0;na=D;La=Ed(x|0,Ba|0,La&2097151|0,0)|0;ub=D;uc=Ed(K&2097151|0,0,sc&2097151|0,0)|0;tc=D;Ia=Ed(Ia&2097151|0,0,o|0,Da|0)|0;Ia=oe(uc|0,tc|0,Ia|0,D|0)|0;ub=oe(Ia|0,D|0,La|0,ub|0)|0;La=D;sc=Ed(x|0,Ba|0,sc&2097151|0,0)|0;Ia=D;K=Ed(K&2097151|0,0,o|0,Da|0)|0;K=oe(sc|0,Ia|0,K|0,D|0)|0;Ia=D;Da=Ed(x|0,Ba|0,o|0,Da|0)|0;o=D;Ba=oe(Aa|0,W|0,1048576,0)|0;Ba=Rd(Ba|0,D|0,21)|0;x=D;ma=oe(rc|0,qc|0,pc|0,ma|0)|0;ma=oe(ma|0,D|0,Ba|0,x|0)|0;xa=oe(ma|0,D|0,xa&2097151|0,0)|0;ma=D;x=Pd(Ba|0,x|0,21)|0;x=le(Aa|0,W|0,x|0,D|0)|0;W=D;Aa=oe(Fa|0,Ea|0,1048576,0)|0;Aa=Rd(Aa|0,D|0,21)|0;Ba=D;lc=oe(oc|0,nc|0,mc|0,lc|0)|0;va=oe(lc|0,D|0,kc|0,va|0)|0;ia=oe(va|0,D|0,ua|0,ia|0)|0;ib=oe(ia|0,D|0,ib&2097151|0,0)|0;ib=oe(ib|0,D|0,Aa|0,Ba|0)|0;ia=D;Ba=Pd(Aa|0,Ba|0,21)|0;Aa=D;ua=oe(za|0,ya|0,1048576,0)|0;ua=Dd(ua|0,D|0,21)|0;va=D;gc=oe(jc|0,ic|0,hc|0,gc|0)|0;ec=oe(gc|0,D|0,fc|0,ec|0)|0;cc=oe(ec|0,D|0,dc|0,cc|0)|0;Ga=oe(cc|0,D|0,bc|0,Ga|0)|0;u=oe(Ga|0,D|0,Ha|0,u|0)|0;y=oe(u|0,D|0,y&2097151|0,0)|0;y=oe(y|0,D|0,ua|0,va|0)|0;u=D;va=Pd(ua|0,va|0,21)|0;ua=D;Ha=oe(Qa|0,Ra|0,1048576,0)|0;Ha=Dd(Ha|0,D|0,21)|0;Ga=D;Zb=oe(ac|0,$b|0,_b|0,Zb|0)|0;Xb=oe(Zb|0,D|0,Yb|0,Xb|0)|0;Vb=oe(Xb|0,D|0,Wb|0,Vb|0)|0;Tb=oe(Vb|0,D|0,Ub|0,Tb|0)|0;Rb=oe(Tb|0,D|0,Sb|0,Rb|0)|0;Pb=oe(Rb|0,D|0,Qb|0,Pb|0)|0;da=oe(Pb|0,D|0,X|0,da|0)|0;h=oe(da|0,D|0,B|0,h|0)|0;h=oe(h|0,D|0,Ha|0,Ga|0)|0;B=D;Ga=Pd(Ha|0,Ga|0,21)|0;Ha=D;da=oe(Y|0,Z|0,1048576,0)|0;da=Dd(da|0,D|0,21)|0;X=D;Lb=oe(Ob|0,Nb|0,Mb|0,Lb|0)|0;Jb=oe(Lb|0,D|0,Kb|0,Jb|0)|0;Hb=oe(Jb|0,D|0,Ib|0,Hb|0)|0;Fb=oe(Hb|0,D|0,Gb|0,Fb|0)|0;Db=oe(Fb|0,D|0,Eb|0,Db|0)|0;Bb=oe(Db|0,D|0,Cb|0,Bb|0)|0;zb=oe(Bb|0,D|0,Ab|0,zb|0)|0;ta=oe(zb|0,D|0,yb|0,ta|0)|0;H=oe(ta|0,D|0,sa|0,H|0)|0;G=oe(H|0,D|0,G&2097151|0,0)|0;G=oe(G|0,D|0,da|0,X|0)|0;H=D;X=Pd(da|0,X|0,21)|0;da=D;sa=oe(N|0,M|0,1048576,0)|0;sa=Dd(sa|0,D|0,21)|0;ta=D;aa=oe(xb|0,wb|0,ba|0,aa|0)|0;Xa=oe(aa|0,D|0,Wa|0,Xa|0)|0;V=oe(Xa|0,D|0,U|0,V|0)|0;hb=oe(V|0,D|0,gb|0,hb|0)|0;Pa=oe(hb|0,D|0,Oa|0,Pa|0)|0;C=oe(Pa|0,D|0,J|0,C|0)|0;pb=oe(C|0,D|0,ob|0,pb|0)|0;R=oe(pb|0,D|0,Q|0,R|0)|0;bb=oe(R|0,D|0,ab|0,bb|0)|0;P=oe(bb|0,D|0,O|0,P|0)|0;db=oe(P|0,D|0,jb|0,db|0)|0;i=oe(db|0,D|0,c|0,i|0)|0;i=oe(i|0,D|0,sa|0,ta|0)|0;c=D;ta=Pd(sa|0,ta|0,21)|0;sa=D;db=oe(rb|0,qb|0,1048576,0)|0;db=Dd(db|0,D|0,21)|0;jb=D;v=oe(Za|0,Ya|0,q|0,v|0)|0;ga=oe(v|0,D|0,Na|0,ga|0)|0;pa=oe(ga|0,D|0,qa|0,pa|0)|0;ka=oe(pa|0,D|0,la|0,ka|0)|0;tb=oe(ka|0,D|0,sb|0,tb|0)|0;kb=oe(tb|0,D|0,ha|0,kb|0)|0;$=oe(kb|0,D|0,fa|0,$|0)|0;fb=oe($|0,D|0,eb|0,fb|0)|0;w=oe(fb|0,D|0,A|0,w|0)|0;w=oe(w|0,D|0,db|0,jb|0)|0;A=D;jb=Pd(db|0,jb|0,21)|0;db=D;fb=oe(mb|0,nb|0,1048576,0)|0;fb=Dd(fb|0,D|0,21)|0;eb=D;l=oe(oa|0,p|0,ea|0,l|0)|0;F=oe(l|0,D|0,ja|0,F|0)|0;s=oe(F|0,D|0,_|0,s|0)|0;g=oe(s|0,D|0,n|0,g|0)|0;t=oe(g|0,D|0,E|0,t|0)|0;$a=oe(t|0,D|0,_a|0,$a|0)|0;r=oe($a|0,D|0,z|0,r|0)|0;r=oe(r|0,D|0,fb|0,eb|0)|0;z=D;eb=Pd(fb|0,eb|0,21)|0;fb=D;$a=oe(vb|0,j|0,1048576,0)|0;$a=Dd($a|0,D|0,21)|0;_a=D;k=oe(Sa|0,Ta|0,m|0,k|0)|0;Ua=oe(k|0,D|0,Va|0,Ua|0)|0;S=oe(Ua|0,D|0,T|0,S|0)|0;Ka=oe(S|0,D|0,e|0,Ka|0)|0;L=oe(Ka|0,D|0,Ma|0,L|0)|0;L=oe(L|0,D|0,$a|0,_a|0)|0;Ma=D;_a=Pd($a|0,_a|0,21)|0;$a=D;Ka=oe(f|0,ca|0,1048576,0)|0;Ka=Dd(Ka|0,D|0,21)|0;e=D;na=oe(cb|0,ra|0,wa|0,na|0)|0;I=oe(na|0,D|0,Ca|0,I|0)|0;Ja=oe(I|0,D|0,lb|0,Ja|0)|0;Ja=oe(Ja|0,D|0,Ka|0,e|0)|0;lb=D;e=Pd(Ka|0,e|0,21)|0;e=le(f|0,ca|0,e|0,D|0)|0;ca=D;f=oe(ub|0,La|0,1048576,0)|0;f=Dd(f|0,D|0,21)|0;Ka=D;Ia=oe(K|0,Ia|0,f|0,Ka|0)|0;K=D;Ka=Pd(f|0,Ka|0,21)|0;Ka=le(ub|0,La|0,Ka|0,D|0)|0;La=D;ub=oe(Da|0,o|0,1048576,0)|0;ub=Dd(ub|0,D|0,21)|0;f=D;I=Pd(ub|0,f|0,21)|0;I=le(Da|0,o|0,I|0,D|0)|0;o=D;Da=oe(xa|0,ma|0,1048576,0)|0;Da=Rd(Da|0,D|0,21)|0;Ca=D;na=Pd(Da|0,Ca|0,21)|0;na=le(xa|0,ma|0,na|0,D|0)|0;ma=D;xa=oe(ib|0,ia|0,1048576,0)|0;xa=Dd(xa|0,D|0,21)|0;wa=D;ra=Pd(xa|0,wa|0,21)|0;ra=le(ib|0,ia|0,ra|0,D|0)|0;ia=D;ib=oe(y|0,u|0,1048576,0)|0;ib=Dd(ib|0,D|0,21)|0;cb=D;S=Pd(ib|0,cb|0,21)|0;T=D;Ua=oe(h|0,B|0,1048576,0)|0;Ua=Dd(Ua|0,D|0,21)|0;Va=D;k=Pd(Ua|0,Va|0,21)|0;m=D;Ta=oe(G|0,H|0,1048576,0)|0;Ta=Dd(Ta|0,D|0,21)|0;Sa=D;t=Pd(Ta|0,Sa|0,21)|0;E=D;g=oe(i|0,c|0,1048576,0)|0;g=Dd(g|0,D|0,21)|0;n=D;s=Pd(g|0,n|0,21)|0;_=D;F=oe(w|0,A|0,1048576,0)|0;F=Dd(F|0,D|0,21)|0;ja=D;l=Pd(F|0,ja|0,21)|0;ea=D;p=oe(r|0,z|0,1048576,0)|0;p=Dd(p|0,D|0,21)|0;oa=D;$=Pd(p|0,oa|0,21)|0;fa=D;kb=oe(L|0,Ma|0,1048576,0)|0;kb=Dd(kb|0,D|0,21)|0;ha=D;ca=oe(kb|0,ha|0,e|0,ca|0)|0;e=D;ha=Pd(kb|0,ha|0,21)|0;ha=le(L|0,Ma|0,ha|0,D|0)|0;Ma=D;L=oe(Ja|0,lb|0,1048576,0)|0;L=Dd(L|0,D|0,21)|0;kb=D;La=oe(L|0,kb|0,Ka|0,La|0)|0;Ka=D;kb=Pd(L|0,kb|0,21)|0;kb=le(Ja|0,lb|0,kb|0,D|0)|0;lb=D;Ja=oe(Ia|0,K|0,1048576,0)|0;Ja=Dd(Ja|0,D|0,21)|0;L=D;o=oe(Ja|0,L|0,I|0,o|0)|0;I=D;L=Pd(Ja|0,L|0,21)|0;L=le(Ia|0,K|0,L|0,D|0)|0;K=D;Ia=Ed(ub|0,f|0,666643,0)|0;Ja=D;tb=Ed(ub|0,f|0,470296,0)|0;sb=D;ka=Ed(ub|0,f|0,654183,0)|0;la=D;pa=Ed(ub|0,f|0,-997805,-1)|0;qa=D;ga=Ed(ub|0,f|0,136657,0)|0;Na=D;f=Ed(ub|0,f|0,-683901,-1)|0;f=oe(vb|0,j|0,f|0,D|0)|0;$a=le(f|0,D|0,_a|0,$a|0)|0;oa=oe($a|0,D|0,p|0,oa|0)|0;p=D;$a=Ed(o|0,I|0,666643,0)|0;_a=D;f=Ed(o|0,I|0,470296,0)|0;j=D;vb=Ed(o|0,I|0,654183,0)|0;ub=D;v=Ed(o|0,I|0,-997805,-1)|0;q=D;Ya=Ed(o|0,I|0,136657,0)|0;Za=D;I=Ed(o|0,I|0,-683901,-1)|0;o=D;P=Ed(L|0,K|0,666643,0)|0;O=D;bb=Ed(L|0,K|0,470296,0)|0;ab=D;R=Ed(L|0,K|0,654183,0)|0;Q=D;pb=Ed(L|0,K|0,-997805,-1)|0;ob=D;C=Ed(L|0,K|0,136657,0)|0;J=D;K=Ed(L|0,K|0,-683901,-1)|0;L=D;qa=oe(mb|0,nb|0,pa|0,qa|0)|0;Za=oe(qa|0,D|0,Ya|0,Za|0)|0;L=oe(Za|0,D|0,K|0,L|0)|0;fb=le(L|0,D|0,eb|0,fb|0)|0;ja=oe(fb|0,D|0,F|0,ja|0)|0;F=D;fb=Ed(La|0,Ka|0,666643,0)|0;eb=D;L=Ed(La|0,Ka|0,470296,0)|0;K=D;Za=Ed(La|0,Ka|0,654183,0)|0;Ya=D;qa=Ed(La|0,Ka|0,-997805,-1)|0;pa=D;nb=Ed(La|0,Ka|0,136657,0)|0;mb=D;Ka=Ed(La|0,Ka|0,-683901,-1)|0;La=D;Pa=Ed(kb|0,lb|0,666643,0)|0;Oa=D;hb=Ed(kb|0,lb|0,470296,0)|0;gb=D;V=Ed(kb|0,lb|0,654183,0)|0;U=D;Xa=Ed(kb|0,lb|0,-997805,-1)|0;Wa=D;aa=Ed(kb|0,lb|0,136657,0)|0;ba=D;lb=Ed(kb|0,lb|0,-683901,-1)|0;kb=D;sb=oe(vb|0,ub|0,tb|0,sb|0)|0;qb=oe(sb|0,D|0,rb|0,qb|0)|0;ob=oe(qb|0,D|0,pb|0,ob|0)|0;mb=oe(ob|0,D|0,nb|0,mb|0)|0;kb=oe(mb|0,D|0,lb|0,kb|0)|0;db=le(kb|0,D|0,jb|0,db|0)|0;n=oe(db|0,D|0,g|0,n|0)|0;g=D;db=Ed(ca|0,e|0,666643,0)|0;db=oe(ib|0,cb|0,db|0,D|0)|0;Ra=oe(db|0,D|0,Qa|0,Ra|0)|0;Ha=le(Ra|0,D|0,Ga|0,Ha|0)|0;Ga=D;Ra=Ed(ca|0,e|0,470296,0)|0;Qa=D;db=Ed(ca|0,e|0,654183,0)|0;cb=D;eb=oe(hb|0,gb|0,fb|0,eb|0)|0;cb=oe(eb|0,D|0,db|0,cb|0)|0;Va=oe(cb|0,D|0,Ua|0,Va|0)|0;Z=oe(Va|0,D|0,Y|0,Z|0)|0;da=le(Z|0,D|0,X|0,da|0)|0;X=D;Z=Ed(ca|0,e|0,-997805,-1)|0;Y=D;Va=Ed(ca|0,e|0,136657,0)|0;Ua=D;_a=oe(bb|0,ab|0,$a|0,_a|0)|0;Ya=oe(_a|0,D|0,Za|0,Ya|0)|0;Wa=oe(Ya|0,D|0,Xa|0,Wa|0)|0;Ua=oe(Wa|0,D|0,Va|0,Ua|0)|0;Sa=oe(Ua|0,D|0,Ta|0,Sa|0)|0;M=oe(Sa|0,D|0,N|0,M|0)|0;sa=le(M|0,D|0,ta|0,sa|0)|0;ta=D;e=Ed(ca|0,e|0,-683901,-1)|0;ca=D;M=oe(Ha|0,Ga|0,1048576,0)|0;M=Dd(M|0,D|0,21)|0;N=D;Oa=oe(Ra|0,Qa|0,Pa|0,Oa|0)|0;B=oe(Oa|0,D|0,h|0,B|0)|0;m=le(B|0,D|0,k|0,m|0)|0;m=oe(m|0,D|0,M|0,N|0)|0;k=D;N=Pd(M|0,N|0,21)|0;M=D;B=oe(da|0,X|0,1048576,0)|0;B=Dd(B|0,D|0,21)|0;h=D;O=oe(L|0,K|0,P|0,O|0)|0;U=oe(O|0,D|0,V|0,U|0)|0;Y=oe(U|0,D|0,Z|0,Y|0)|0;H=oe(Y|0,D|0,G|0,H|0)|0;E=le(H|0,D|0,t|0,E|0)|0;E=oe(E|0,D|0,B|0,h|0)|0;t=D;h=Pd(B|0,h|0,21)|0;B=D;H=oe(sa|0,ta|0,1048576,0)|0;H=Dd(H|0,D|0,21)|0;G=D;Ja=oe(f|0,j|0,Ia|0,Ja|0)|0;Q=oe(Ja|0,D|0,R|0,Q|0)|0;pa=oe(Q|0,D|0,qa|0,pa|0)|0;ba=oe(pa|0,D|0,aa|0,ba|0)|0;ca=oe(ba|0,D|0,e|0,ca|0)|0;c=oe(ca|0,D|0,i|0,c|0)|0;_=le(c|0,D|0,s|0,_|0)|0;_=oe(_|0,D|0,H|0,G|0)|0;s=D;G=Pd(H|0,G|0,21)|0;H=D;c=oe(n|0,g|0,1048576,0)|0;c=Dd(c|0,D|0,21)|0;i=D;la=oe(v|0,q|0,ka|0,la|0)|0;J=oe(la|0,D|0,C|0,J|0)|0;La=oe(J|0,D|0,Ka|0,La|0)|0;A=oe(La|0,D|0,w|0,A|0)|0;ea=le(A|0,D|0,l|0,ea|0)|0;ea=oe(ea|0,D|0,c|0,i|0)|0;l=D;i=Pd(c|0,i|0,21)|0;i=le(n|0,g|0,i|0,D|0)|0;g=D;n=oe(ja|0,F|0,1048576,0)|0;n=Dd(n|0,D|0,21)|0;c=D;Na=oe(I|0,o|0,ga|0,Na|0)|0;z=oe(Na|0,D|0,r|0,z|0)|0;fa=le(z|0,D|0,$|0,fa|0)|0;fa=oe(fa|0,D|0,n|0,c|0)|0;$=D;c=Pd(n|0,c|0,21)|0;c=le(ja|0,F|0,c|0,D|0)|0;F=D;ja=oe(oa|0,p|0,1048576,0)|0;ja=Dd(ja|0,D|0,21)|0;n=D;Ma=oe(ja|0,n|0,ha|0,Ma|0)|0;ha=D;n=Pd(ja|0,n|0,21)|0;n=le(oa|0,p|0,n|0,D|0)|0;p=D;oa=oe(m|0,k|0,1048576,0)|0;oa=Dd(oa|0,D|0,21)|0;ja=D;z=Pd(oa|0,ja|0,21)|0;r=D;Na=oe(E|0,t|0,1048576,0)|0;Na=Dd(Na|0,D|0,21)|0;ga=D;o=Pd(Na|0,ga|0,21)|0;I=D;A=oe(_|0,s|0,1048576,0)|0;A=Dd(A|0,D|0,21)|0;w=D;g=oe(A|0,w|0,i|0,g|0)|0;i=D;w=Pd(A|0,w|0,21)|0;w=le(_|0,s|0,w|0,D|0)|0;s=D;_=oe(ea|0,l|0,1048576,0)|0;_=Dd(_|0,D|0,21)|0;A=D;F=oe(_|0,A|0,c|0,F|0)|0;c=D;A=Pd(_|0,A|0,21)|0;A=le(ea|0,l|0,A|0,D|0)|0;l=D;ea=oe(fa|0,$|0,1048576,0)|0;ea=Dd(ea|0,D|0,21)|0;_=D;p=oe(ea|0,_|0,n|0,p|0)|0;n=D;_=Pd(ea|0,_|0,21)|0;_=le(fa|0,$|0,_|0,D|0)|0;$=D;fa=Ed(Ma|0,ha|0,666643,0)|0;ea=D;La=Ed(Ma|0,ha|0,470296,0)|0;Ka=D;J=Ed(Ma|0,ha|0,654183,0)|0;C=D;la=Ed(Ma|0,ha|0,-997805,-1)|0;ka=D;q=Ed(Ma|0,ha|0,136657,0)|0;v=D;ha=Ed(Ma|0,ha|0,-683901,-1)|0;ha=oe(Na|0,ga|0,ha|0,D|0)|0;ta=oe(ha|0,D|0,sa|0,ta|0)|0;H=le(ta|0,D|0,G|0,H|0)|0;G=D;ta=Ed(p|0,n|0,666643,0)|0;sa=D;ha=Ed(p|0,n|0,470296,0)|0;ga=D;Na=Ed(p|0,n|0,654183,0)|0;Ma=D;ca=Ed(p|0,n|0,-997805,-1)|0;e=D;ba=Ed(p|0,n|0,136657,0)|0;aa=D;n=Ed(p|0,n|0,-683901,-1)|0;p=D;pa=Ed(_|0,$|0,666643,0)|0;pa=oe(ra|0,ia|0,pa|0,D|0)|0;ia=D;ra=Ed(_|0,$|0,470296,0)|0;qa=D;Q=Ed(_|0,$|0,654183,0)|0;R=D;Ja=Ed(_|0,$|0,-997805,-1)|0;Ia=D;j=Ed(_|0,$|0,136657,0)|0;f=D;$=Ed(_|0,$|0,-683901,-1)|0;_=D;ka=oe(ba|0,aa|0,la|0,ka|0)|0;_=oe(ka|0,D|0,$|0,_|0)|0;ja=oe(_|0,D|0,oa|0,ja|0)|0;X=oe(ja|0,D|0,da|0,X|0)|0;B=le(X|0,D|0,h|0,B|0)|0;h=D;X=Ed(F|0,c|0,666643,0)|0;da=D;ja=Ed(F|0,c|0,470296,0)|0;ja=oe(pa|0,ia|0,ja|0,D|0)|0;ia=D;pa=Ed(F|0,c|0,654183,0)|0;oa=D;_=Ed(F|0,c|0,-997805,-1)|0;$=D;ka=Ed(F|0,c|0,136657,0)|0;la=D;c=Ed(F|0,c|0,-683901,-1)|0;F=D;aa=Ed(A|0,l|0,666643,0)|0;ba=D;Y=Ed(A|0,l|0,470296,0)|0;Z=D;U=Ed(A|0,l|0,654183,0)|0;V=D;O=Ed(A|0,l|0,-997805,-1)|0;P=D;K=Ed(A|0,l|0,136657,0)|0;L=D;l=Ed(A|0,l|0,-683901,-1)|0;A=D;Ka=oe(Na|0,Ma|0,La|0,Ka|0)|0;Ia=oe(Ka|0,D|0,Ja|0,Ia|0)|0;Ga=oe(Ia|0,D|0,Ha|0,Ga|0)|0;M=le(Ga|0,D|0,N|0,M|0)|0;la=oe(M|0,D|0,ka|0,la|0)|0;A=oe(la|0,D|0,l|0,A|0)|0;l=D;la=Ed(g|0,i|0,666643,0)|0;W=oe(la|0,D|0,x|0,W|0)|0;x=D;la=Ed(g|0,i|0,470296,0)|0;ka=D;M=Ed(g|0,i|0,654183,0)|0;N=D;Ca=oe(Fa|0,Ea|0,Da|0,Ca|0)|0;Aa=le(Ca|0,D|0,Ba|0,Aa|0)|0;da=oe(Aa|0,D|0,X|0,da|0)|0;N=oe(da|0,D|0,M|0,N|0)|0;Z=oe(N|0,D|0,Y|0,Z|0)|0;Y=D;N=Ed(g|0,i|0,-997805,-1)|0;M=D;da=Ed(g|0,i|0,136657,0)|0;X=D;wa=oe(za|0,ya|0,xa|0,wa|0)|0;ua=le(wa|0,D|0,va|0,ua|0)|0;sa=oe(ua|0,D|0,ta|0,sa|0)|0;qa=oe(sa|0,D|0,ra|0,qa|0)|0;oa=oe(qa|0,D|0,pa|0,oa|0)|0;X=oe(oa|0,D|0,da|0,X|0)|0;P=oe(X|0,D|0,O|0,P|0)|0;O=D;i=Ed(g|0,i|0,-683901,-1)|0;g=D;X=oe(W|0,x|0,1048576,0)|0;X=Dd(X|0,D|0,21)|0;da=D;ka=oe(na|0,ma|0,la|0,ka|0)|0;ba=oe(ka|0,D|0,aa|0,ba|0)|0;ba=oe(ba|0,D|0,X|0,da|0)|0;aa=D;da=Pd(X|0,da|0,21)|0;da=le(W|0,x|0,da|0,D|0)|0;x=D;W=oe(Z|0,Y|0,1048576,0)|0;W=Dd(W|0,D|0,21)|0;X=D;M=oe(ja|0,ia|0,N|0,M|0)|0;V=oe(M|0,D|0,U|0,V|0)|0;V=oe(V|0,D|0,W|0,X|0)|0;U=D;X=Pd(W|0,X|0,21)|0;W=D;M=oe(P|0,O|0,1048576,0)|0;M=Dd(M|0,D|0,21)|0;N=D;ea=oe(ha|0,ga|0,fa|0,ea|0)|0;u=oe(ea|0,D|0,y|0,u|0)|0;R=oe(u|0,D|0,Q|0,R|0)|0;T=le(R|0,D|0,S|0,T|0)|0;$=oe(T|0,D|0,_|0,$|0)|0;g=oe($|0,D|0,i|0,g|0)|0;L=oe(g|0,D|0,K|0,L|0)|0;L=oe(L|0,D|0,M|0,N|0)|0;K=D;N=Pd(M|0,N|0,21)|0;M=D;g=oe(A|0,l|0,1048576,0)|0;g=Dd(g|0,D|0,21)|0;i=D;C=oe(ca|0,e|0,J|0,C|0)|0;f=oe(C|0,D|0,j|0,f|0)|0;k=oe(f|0,D|0,m|0,k|0)|0;r=le(k|0,D|0,z|0,r|0)|0;F=oe(r|0,D|0,c|0,F|0)|0;F=oe(F|0,D|0,g|0,i|0)|0;c=D;i=Pd(g|0,i|0,21)|0;i=le(A|0,l|0,i|0,D|0)|0;l=D;A=oe(B|0,h|0,1048576,0)|0;A=Dd(A|0,D|0,21)|0;g=D;v=oe(n|0,p|0,q|0,v|0)|0;t=oe(v|0,D|0,E|0,t|0)|0;I=le(t|0,D|0,o|0,I|0)|0;I=oe(I|0,D|0,A|0,g|0)|0;o=D;g=Pd(A|0,g|0,21)|0;g=le(B|0,h|0,g|0,D|0)|0;h=D;B=oe(H|0,G|0,1048576,0)|0;B=Dd(B|0,D|0,21)|0;A=D;s=oe(w|0,s|0,B|0,A|0)|0;w=D;A=Pd(B|0,A|0,21)|0;B=D;t=oe(ba|0,aa|0,1048576,0)|0;t=Dd(t|0,D|0,21)|0;E=D;v=Pd(t|0,E|0,21)|0;q=D;p=oe(V|0,U|0,1048576,0)|0;p=Dd(p|0,D|0,21)|0;n=D;r=Pd(p|0,n|0,21)|0;z=D;k=oe(L|0,K|0,1048576,0)|0;k=Dd(k|0,D|0,21)|0;m=D;l=oe(i|0,l|0,k|0,m|0)|0;i=D;m=Pd(k|0,m|0,21)|0;k=D;f=oe(F|0,c|0,1048576,0)|0;f=Dd(f|0,D|0,21)|0;j=D;h=oe(g|0,h|0,f|0,j|0)|0;g=D;j=Pd(f|0,j|0,21)|0;j=le(F|0,c|0,j|0,D|0)|0;c=D;F=oe(I|0,o|0,1048576,0)|0;F=Dd(F|0,D|0,21)|0;f=D;C=Pd(F|0,f|0,21)|0;C=le(I|0,o|0,C|0,D|0)|0;o=D;I=oe(s|0,w|0,1048576,0)|0;I=Dd(I|0,D|0,21)|0;J=D;e=Pd(I|0,J|0,21)|0;e=le(s|0,w|0,e|0,D|0)|0;w=D;s=Ed(I|0,J|0,666643,0)|0;s=oe(da|0,x|0,s|0,D|0)|0;x=D;da=Ed(I|0,J|0,470296,0)|0;ca=D;$=Ed(I|0,J|0,654183,0)|0;_=D;T=Ed(I|0,J|0,-997805,-1)|0;S=D;R=Ed(I|0,J|0,136657,0)|0;Q=D;J=Ed(I|0,J|0,-683901,-1)|0;I=D;u=Dd(s|0,x|0,21)|0;y=D;aa=oe(da|0,ca|0,ba|0,aa|0)|0;q=le(aa|0,D|0,v|0,q|0)|0;q=oe(q|0,D|0,u|0,y|0)|0;v=D;y=Pd(u|0,y|0,21)|0;y=le(s|0,x|0,y|0,D|0)|0;x=D;s=Dd(q|0,v|0,21)|0;u=D;Y=oe($|0,_|0,Z|0,Y|0)|0;W=le(Y|0,D|0,X|0,W|0)|0;E=oe(W|0,D|0,t|0,E|0)|0;E=oe(E|0,D|0,s|0,u|0)|0;t=D;u=Pd(s|0,u|0,21)|0;u=le(q|0,v|0,u|0,D|0)|0;v=D;q=Dd(E|0,t|0,21)|0;s=D;S=oe(V|0,U|0,T|0,S|0)|0;z=le(S|0,D|0,r|0,z|0)|0;z=oe(z|0,D|0,q|0,s|0)|0;r=D;s=Pd(q|0,s|0,21)|0;s=le(E|0,t|0,s|0,D|0)|0;t=D;E=Dd(z|0,r|0,21)|0;q=D;O=oe(R|0,Q|0,P|0,O|0)|0;M=le(O|0,D|0,N|0,M|0)|0;n=oe(M|0,D|0,p|0,n|0)|0;n=oe(n|0,D|0,E|0,q|0)|0;p=D;q=Pd(E|0,q|0,21)|0;q=le(z|0,r|0,q|0,D|0)|0;r=D;z=Dd(n|0,p|0,21)|0;E=D;I=oe(L|0,K|0,J|0,I|0)|0;k=le(I|0,D|0,m|0,k|0)|0;k=oe(k|0,D|0,z|0,E|0)|0;m=D;E=Pd(z|0,E|0,21)|0;E=le(n|0,p|0,E|0,D|0)|0;p=D;n=Dd(k|0,m|0,21)|0;z=D;i=oe(l|0,i|0,n|0,z|0)|0;l=D;z=Pd(n|0,z|0,21)|0;z=le(k|0,m|0,z|0,D|0)|0;m=D;k=Dd(i|0,l|0,21)|0;n=D;c=oe(k|0,n|0,j|0,c|0)|0;j=D;n=Pd(k|0,n|0,21)|0;n=le(i|0,l|0,n|0,D|0)|0;l=D;i=Dd(c|0,j|0,21)|0;k=D;g=oe(h|0,g|0,i|0,k|0)|0;h=D;k=Pd(i|0,k|0,21)|0;k=le(c|0,j|0,k|0,D|0)|0;j=D;c=Dd(g|0,h|0,21)|0;i=D;o=oe(c|0,i|0,C|0,o|0)|0;C=D;i=Pd(c|0,i|0,21)|0;i=le(g|0,h|0,i|0,D|0)|0;h=D;g=Dd(o|0,C|0,21)|0;c=D;f=oe(H|0,G|0,F|0,f|0)|0;B=le(f|0,D|0,A|0,B|0)|0;B=oe(B|0,D|0,g|0,c|0)|0;A=D;c=Pd(g|0,c|0,21)|0;c=le(o|0,C|0,c|0,D|0)|0;C=D;o=Dd(B|0,A|0,21)|0;g=D;w=oe(o|0,g|0,e|0,w|0)|0;e=D;g=Pd(o|0,g|0,21)|0;g=le(B|0,A|0,g|0,D|0)|0;A=D;B=Dd(w|0,e|0,21)|0;o=D;f=Pd(B|0,o|0,21)|0;f=le(w|0,e|0,f|0,D|0)|0;e=D;w=Ed(B|0,o|0,666643,0)|0;x=oe(w|0,D|0,y|0,x|0)|0;y=D;w=Ed(B|0,o|0,470296,0)|0;w=oe(u|0,v|0,w|0,D|0)|0;v=D;u=Ed(B|0,o|0,654183,0)|0;u=oe(s|0,t|0,u|0,D|0)|0;t=D;s=Ed(B|0,o|0,-997805,-1)|0;s=oe(q|0,r|0,s|0,D|0)|0;r=D;q=Ed(B|0,o|0,136657,0)|0;q=oe(E|0,p|0,q|0,D|0)|0;p=D;o=Ed(B|0,o|0,-683901,-1)|0;o=oe(z|0,m|0,o|0,D|0)|0;m=D;z=Dd(x|0,y|0,21)|0;B=D;v=oe(w|0,v|0,z|0,B|0)|0;w=D;B=Pd(z|0,B|0,21)|0;B=le(x|0,y|0,B|0,D|0)|0;y=D;x=Dd(v|0,w|0,21)|0;z=D;t=oe(u|0,t|0,x|0,z|0)|0;u=D;z=Pd(x|0,z|0,21)|0;z=le(v|0,w|0,z|0,D|0)|0;w=D;v=Dd(t|0,u|0,21)|0;x=D;r=oe(s|0,r|0,v|0,x|0)|0;s=D;x=Pd(v|0,x|0,21)|0;x=le(t|0,u|0,x|0,D|0)|0;u=D;t=Dd(r|0,s|0,21)|0;v=D;p=oe(q|0,p|0,t|0,v|0)|0;q=D;v=Pd(t|0,v|0,21)|0;v=le(r|0,s|0,v|0,D|0)|0;s=D;r=Dd(p|0,q|0,21)|0;t=D;m=oe(o|0,m|0,r|0,t|0)|0;o=D;t=Pd(r|0,t|0,21)|0;t=le(p|0,q|0,t|0,D|0)|0;q=D;p=Dd(m|0,o|0,21)|0;r=D;l=oe(p|0,r|0,n|0,l|0)|0;n=D;r=Pd(p|0,r|0,21)|0;r=le(m|0,o|0,r|0,D|0)|0;o=D;m=Dd(l|0,n|0,21)|0;p=D;j=oe(m|0,p|0,k|0,j|0)|0;k=D;p=Pd(m|0,p|0,21)|0;p=le(l|0,n|0,p|0,D|0)|0;n=D;l=Dd(j|0,k|0,21)|0;m=D;h=oe(l|0,m|0,i|0,h|0)|0;i=D;m=Pd(l|0,m|0,21)|0;m=le(j|0,k|0,m|0,D|0)|0;k=D;j=Dd(h|0,i|0,21)|0;l=D;C=oe(j|0,l|0,c|0,C|0)|0;c=D;l=Pd(j|0,l|0,21)|0;l=le(h|0,i|0,l|0,D|0)|0;i=D;h=Dd(C|0,c|0,21)|0;j=D;A=oe(h|0,j|0,g|0,A|0)|0;g=D;j=Pd(h|0,j|0,21)|0;j=le(C|0,c|0,j|0,D|0)|0;c=D;C=Dd(A|0,g|0,21)|0;h=D;e=oe(C|0,h|0,f|0,e|0)|0;f=D;h=Pd(C|0,h|0,21)|0;h=le(A|0,g|0,h|0,D|0)|0;g=D;a[b>>0]=B;A=Rd(B|0,y|0,8)|0;a[b+1>>0]=A;y=Rd(B|0,y|0,16)|0;B=D;A=Pd(z|0,w|0,5)|0;a[b+2>>0]=A|y;y=Rd(z|0,w|0,3)|0;a[b+3>>0]=y;y=Rd(z|0,w|0,11)|0;a[b+4>>0]=y;w=Rd(z|0,w|0,19)|0;z=D;y=Pd(x|0,u|0,2)|0;a[b+5>>0]=y|w;w=Rd(x|0,u|0,6)|0;a[b+6>>0]=w;u=Rd(x|0,u|0,14)|0;x=D;w=Pd(v|0,s|0,7)|0;a[b+7>>0]=w|u;u=Rd(v|0,s|0,1)|0;a[b+8>>0]=u;u=Rd(v|0,s|0,9)|0;a[b+9>>0]=u;s=Rd(v|0,s|0,17)|0;v=D;u=Pd(t|0,q|0,4)|0;a[b+10>>0]=u|s;s=Rd(t|0,q|0,4)|0;a[b+11>>0]=s;s=Rd(t|0,q|0,12)|0;a[b+12>>0]=s;q=Rd(t|0,q|0,20)|0;t=D;s=Pd(r|0,o|0,1)|0;a[b+13>>0]=s|q;q=Rd(r|0,o|0,7)|0;a[b+14>>0]=q;o=Rd(r|0,o|0,15)|0;r=D;q=Pd(p|0,n|0,6)|0;a[b+15>>0]=q|o;o=Rd(p|0,n|0,2)|0;a[b+16>>0]=o;o=Rd(p|0,n|0,10)|0;a[b+17>>0]=o;n=Rd(p|0,n|0,18)|0;p=D;o=Pd(m|0,k|0,3)|0;a[b+18>>0]=o|n;n=Rd(m|0,k|0,5)|0;a[b+19>>0]=n;k=Rd(m|0,k|0,13)|0;a[b+20>>0]=k;a[b+21>>0]=l;k=Rd(l|0,i|0,8)|0;a[b+22>>0]=k;i=Rd(l|0,i|0,16)|0;l=D;k=Pd(j|0,c|0,5)|0;a[b+23>>0]=k|i;i=Rd(j|0,c|0,3)|0;a[b+24>>0]=i;i=Rd(j|0,c|0,11)|0;a[b+25>>0]=i;c=Rd(j|0,c|0,19)|0;j=D;i=Pd(h|0,g|0,2)|0;a[b+26>>0]=i|c;c=Rd(h|0,g|0,6)|0;a[b+27>>0]=c;g=Rd(h|0,g|0,14)|0;h=D;c=Pd(e|0,f|0,7)|0;a[b+28>>0]=g|c;c=Rd(e|0,f|0,1)|0;a[b+29>>0]=c;c=Rd(e|0,f|0,9)|0;a[b+30>>0]=c;f=Rd(e|0,f|0,17)|0;a[b+31>>0]=f;return}function ka(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0;f=i;g=i=i+63&-64;i=i+304|0;e=0;do{h=b+(e<<2)|0;c[g+40+(e<<2)>>2]=(d[h+2>>0]|0)<<8|(d[h+3>>0]|0)|(d[h+1>>0]|0)<<16|(d[h>>0]|0)<<24;e=e+1|0}while((e|0)!=16);e=16;b=c[g+40>>2]|0;do{h=c[g+40+(e+-2<<2)>>2]|0;j=b;b=c[g+40+(e+-15<<2)>>2]|0;c[g+40+(e<<2)>>2]=j+(c[g+40+(e+-7<<2)>>2]|0)+((h>>>19|h<<13)^h>>>10^(h>>>17|h<<15))+((b>>>18|b<<14)^b>>>3^(b>>>7|b<<25));e=e+1|0}while((e|0)!=64);c[g+8>>2]=c[a>>2];c[g+8+4>>2]=c[a+4>>2];c[g+8+8>>2]=c[a+8>>2];c[g+8+12>>2]=c[a+12>>2];c[g+8+16>>2]=c[a+16>>2];c[g+8+20>>2]=c[a+20>>2];c[g+8+24>>2]=c[a+24>>2];c[g+8+28>>2]=c[a+28>>2];x=g+8+28|0;k=g+8+16|0;p=c[k>>2]|0;v=g+8+20|0;n=c[v>>2]|0;j=g+8+24|0;y=c[j>>2]|0;b=(c[x>>2]|0)+1116352408+(c[g+40>>2]|0)+((p>>>6|p<<26)^(p>>>11|p<<21)^(p>>>25|p<<7))+((y^n)&p^y)|0;l=c[g+8>>2]|0;t=g+8+4|0;o=c[t>>2]|0;w=g+8+8|0;q=c[w>>2]|0;h=g+8+12|0;e=(c[h>>2]|0)+b|0;c[h>>2]=e;c[x>>2]=((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b;p=y+1899447441+((e>>>6|e<<26)^(e>>>11|e<<21)^(e>>>25|e<<7))+(c[g+40+4>>2]|0)+((n^p)&e^n)|0;c[w>>2]=q+p;y=((o|l)&((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b|o&l)+(((((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b|0)>>>2|((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b<<30)^((((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b|0)>>>13|((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b<<19)^((((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b|0)>>>22|((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b<<10))+p|0;c[j>>2]=y;r=c[k>>2]|0;n=n+-1245643825+(((q+p|0)>>>6|q+p<<26)^((q+p|0)>>>11|q+p<<21)^((q+p|0)>>>25|q+p<<7))+(c[g+40+8>>2]|0)+((r^e)&q+p^r)|0;c[t>>2]=o+n;b=((l|((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b)&y|l&((q|o)&l|q&o)+((l>>>2|l<<30)^(l>>>13|l<<19)^(l>>>22|l<<10))+b)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+n|0;c[v>>2]=b;r=r+-373957723+(((o+n|0)>>>6|o+n<<26)^((o+n|0)>>>11|o+n<<21)^((o+n|0)>>>25|o+n<<7))+(c[g+40+12>>2]|0)+((e^q+p)&o+n^e)|0;s=c[x>>2]|0;c[g+8>>2]=l+r;c[k>>2]=((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r;e=e+961987163+(((l+r|0)>>>6|l+r<<26)^((l+r|0)>>>11|l+r<<21)^((l+r|0)>>>25|l+r<<7))+(c[g+40+16>>2]|0)+((q+p^o+n)&l+r^q+p)|0;m=c[j>>2]|0;c[x>>2]=s+e;u=((m|b)&((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|m&b)+(((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>2|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<30)^((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>13|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<19)^((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>22|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<10))+e|0;c[h>>2]=u;p=q+p+1508970993+(((s+e|0)>>>6|s+e<<26)^((s+e|0)>>>11|s+e<<21)^((s+e|0)>>>25|s+e<<7))+(c[g+40+20>>2]|0)+((o+n^l+r)&s+e^o+n)|0;q=c[v>>2]|0;c[j>>2]=m+p;b=((q|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)&u|q&((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+p|0;c[w>>2]=b;n=o+n+-1841331548+(((m+p|0)>>>6|m+p<<26)^((m+p|0)>>>11|m+p<<21)^((m+p|0)>>>25|m+p<<7))+(c[g+40+24>>2]|0)+((l+r^s+e)&m+p^l+r)|0;o=c[k>>2]|0;c[v>>2]=q+n;c[t>>2]=((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n;r=l+r+-1424204075+(((q+n|0)>>>6|q+n<<26)^((q+n|0)>>>11|q+n<<21)^((q+n|0)>>>25|q+n<<7))+(c[g+40+28>>2]|0)+((s+e^m+p)&q+n^s+e)|0;l=c[h>>2]|0;c[k>>2]=o+r;y=((l|b)&((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|l&b)+(((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>2|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<30)^((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>13|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<19)^((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>22|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<10))+r|0;c[g+8>>2]=y;e=s+e+-670586216+(((o+r|0)>>>6|o+r<<26)^((o+r|0)>>>11|o+r<<21)^((o+r|0)>>>25|o+r<<7))+(c[g+40+32>>2]|0)+((m+p^q+n)&o+r^m+p)|0;s=c[w>>2]|0;c[h>>2]=l+e;b=((s|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)&y|s&((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+e|0;c[x>>2]=b;p=m+p+310598401+(((l+e|0)>>>6|l+e<<26)^((l+e|0)>>>11|l+e<<21)^((l+e|0)>>>25|l+e<<7))+(c[g+40+36>>2]|0)+((q+n^o+r)&l+e^q+n)|0;m=c[t>>2]|0;c[w>>2]=s+p;c[j>>2]=((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p;n=q+n+607225278+(((s+p|0)>>>6|s+p<<26)^((s+p|0)>>>11|s+p<<21)^((s+p|0)>>>25|s+p<<7))+(c[g+40+40>>2]|0)+((o+r^l+e)&s+p^o+r)|0;q=c[g+8>>2]|0;c[t>>2]=m+n;u=((q|b)&((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|q&b)+(((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>2|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<30)^((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>13|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<19)^((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>22|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<10))+n|0;c[v>>2]=u;r=o+r+1426881987+(((m+n|0)>>>6|m+n<<26)^((m+n|0)>>>11|m+n<<21)^((m+n|0)>>>25|m+n<<7))+(c[g+40+44>>2]|0)+((l+e^s+p)&m+n^l+e)|0;o=c[x>>2]|0;c[g+8>>2]=q+r;b=((o|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)&u|o&((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+r|0;c[k>>2]=b;e=l+e+1925078388+(((q+r|0)>>>6|q+r<<26)^((q+r|0)>>>11|q+r<<21)^((q+r|0)>>>25|q+r<<7))+(c[g+40+48>>2]|0)+((s+p^m+n)&q+r^s+p)|0;l=c[j>>2]|0;c[x>>2]=o+e;c[h>>2]=((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e;p=s+p+-2132889090+(((o+e|0)>>>6|o+e<<26)^((o+e|0)>>>11|o+e<<21)^((o+e|0)>>>25|o+e<<7))+(c[g+40+52>>2]|0)+((m+n^q+r)&o+e^m+n)|0;s=c[v>>2]|0;c[j>>2]=l+p;y=((s|b)&((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|s&b)+(((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>2|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<30)^((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>13|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<19)^((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>22|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<10))+p|0;c[w>>2]=y;n=m+n+-1680079193+(((l+p|0)>>>6|l+p<<26)^((l+p|0)>>>11|l+p<<21)^((l+p|0)>>>25|l+p<<7))+(c[g+40+56>>2]|0)+((q+r^o+e)&l+p^q+r)|0;m=c[k>>2]|0;c[v>>2]=s+n;b=((m|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)&y|m&((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+n|0;c[t>>2]=b;r=q+r+-1046744716+(((s+n|0)>>>6|s+n<<26)^((s+n|0)>>>11|s+n<<21)^((s+n|0)>>>25|s+n<<7))+(c[g+40+60>>2]|0)+((o+e^l+p)&s+n^o+e)|0;q=c[h>>2]|0;c[k>>2]=m+r;c[g+8>>2]=((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r;e=o+e+-459576895+(((m+r|0)>>>6|m+r<<26)^((m+r|0)>>>11|m+r<<21)^((m+r|0)>>>25|m+r<<7))+(c[g+40+64>>2]|0)+((l+p^s+n)&m+r^l+p)|0;o=c[w>>2]|0;c[h>>2]=q+e;u=((o|b)&((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|o&b)+(((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>2|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<30)^((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>13|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<19)^((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>22|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<10))+e|0;c[x>>2]=u;p=l+p+-272742522+(((q+e|0)>>>6|q+e<<26)^((q+e|0)>>>11|q+e<<21)^((q+e|0)>>>25|q+e<<7))+(c[g+40+68>>2]|0)+((s+n^m+r)&q+e^s+n)|0;l=c[t>>2]|0;c[w>>2]=o+p;b=((l|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)&u|l&((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+p|0;c[j>>2]=b;n=s+n+264347078+(((o+p|0)>>>6|o+p<<26)^((o+p|0)>>>11|o+p<<21)^((o+p|0)>>>25|o+p<<7))+(c[g+40+72>>2]|0)+((m+r^q+e)&o+p^m+r)|0;s=c[g+8>>2]|0;c[t>>2]=l+n;c[v>>2]=((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n;r=m+r+604807628+(((l+n|0)>>>6|l+n<<26)^((l+n|0)>>>11|l+n<<21)^((l+n|0)>>>25|l+n<<7))+(c[g+40+76>>2]|0)+((q+e^o+p)&l+n^q+e)|0;m=c[x>>2]|0;c[g+8>>2]=s+r;y=((m|b)&((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|m&b)+(((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>2|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<30)^((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>13|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<19)^((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>22|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<10))+r|0;c[k>>2]=y;e=q+e+770255983+(((s+r|0)>>>6|s+r<<26)^((s+r|0)>>>11|s+r<<21)^((s+r|0)>>>25|s+r<<7))+(c[g+40+80>>2]|0)+((o+p^l+n)&s+r^o+p)|0;q=c[j>>2]|0;c[x>>2]=m+e;b=((q|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)&y|q&((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+e|0;c[h>>2]=b;p=o+p+1249150122+(((m+e|0)>>>6|m+e<<26)^((m+e|0)>>>11|m+e<<21)^((m+e|0)>>>25|m+e<<7))+(c[g+40+84>>2]|0)+((l+n^s+r)&m+e^l+n)|0;o=c[v>>2]|0;c[j>>2]=q+p;c[w>>2]=((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p;n=l+n+1555081692+(((q+p|0)>>>6|q+p<<26)^((q+p|0)>>>11|q+p<<21)^((q+p|0)>>>25|q+p<<7))+(c[g+40+88>>2]|0)+((s+r^m+e)&q+p^s+r)|0;l=c[k>>2]|0;c[v>>2]=o+n;u=((l|b)&((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|l&b)+(((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>2|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<30)^((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>13|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<19)^((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>22|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<10))+n|0;c[t>>2]=u;r=s+r+1996064986+(((o+n|0)>>>6|o+n<<26)^((o+n|0)>>>11|o+n<<21)^((o+n|0)>>>25|o+n<<7))+(c[g+40+92>>2]|0)+((m+e^q+p)&o+n^m+e)|0;s=c[h>>2]|0;c[k>>2]=l+r;b=((s|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)&u|s&((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+r|0;c[g+8>>2]=b;e=m+e+-1740746414+(((l+r|0)>>>6|l+r<<26)^((l+r|0)>>>11|l+r<<21)^((l+r|0)>>>25|l+r<<7))+(c[g+40+96>>2]|0)+((q+p^o+n)&l+r^q+p)|0;m=c[w>>2]|0;c[h>>2]=s+e;c[x>>2]=((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e;p=q+p+-1473132947+(((s+e|0)>>>6|s+e<<26)^((s+e|0)>>>11|s+e<<21)^((s+e|0)>>>25|s+e<<7))+(c[g+40+100>>2]|0)+((o+n^l+r)&s+e^o+n)|0;q=c[t>>2]|0;c[w>>2]=m+p;y=((q|b)&((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|q&b)+(((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>2|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<30)^((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>13|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<19)^((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>22|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<10))+p|0;c[j>>2]=y;n=o+n+-1341970488+(((m+p|0)>>>6|m+p<<26)^((m+p|0)>>>11|m+p<<21)^((m+p|0)>>>25|m+p<<7))+(c[g+40+104>>2]|0)+((l+r^s+e)&m+p^l+r)|0;o=c[g+8>>2]|0;c[t>>2]=q+n;b=((o|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)&y|o&((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+n|0;c[v>>2]=b;r=l+r+-1084653625+(((q+n|0)>>>6|q+n<<26)^((q+n|0)>>>11|q+n<<21)^((q+n|0)>>>25|q+n<<7))+(c[g+40+108>>2]|0)+((s+e^m+p)&q+n^s+e)|0;l=c[x>>2]|0;c[g+8>>2]=o+r;c[k>>2]=((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r;e=s+e+-958395405+(((o+r|0)>>>6|o+r<<26)^((o+r|0)>>>11|o+r<<21)^((o+r|0)>>>25|o+r<<7))+(c[g+40+112>>2]|0)+((m+p^q+n)&o+r^m+p)|0;s=c[j>>2]|0;c[x>>2]=l+e;u=((s|b)&((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|s&b)+(((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>2|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<30)^((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>13|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<19)^((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>22|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<10))+e|0;c[h>>2]=u;p=m+p+-710438585+(((l+e|0)>>>6|l+e<<26)^((l+e|0)>>>11|l+e<<21)^((l+e|0)>>>25|l+e<<7))+(c[g+40+116>>2]|0)+((q+n^o+r)&l+e^q+n)|0;m=c[v>>2]|0;c[j>>2]=s+p;b=((m|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)&u|m&((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+p|0;c[w>>2]=b;n=q+n+113926993+(((s+p|0)>>>6|s+p<<26)^((s+p|0)>>>11|s+p<<21)^((s+p|0)>>>25|s+p<<7))+(c[g+40+120>>2]|0)+((o+r^l+e)&s+p^o+r)|0;q=c[k>>2]|0;c[v>>2]=m+n;c[t>>2]=((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n;r=o+r+338241895+(((m+n|0)>>>6|m+n<<26)^((m+n|0)>>>11|m+n<<21)^((m+n|0)>>>25|m+n<<7))+(c[g+40+124>>2]|0)+((l+e^s+p)&m+n^l+e)|0;o=c[h>>2]|0;c[k>>2]=q+r;y=((o|b)&((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|o&b)+(((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>2|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<30)^((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>13|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<19)^((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>22|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<10))+r|0;c[g+8>>2]=y;e=l+e+666307205+(((q+r|0)>>>6|q+r<<26)^((q+r|0)>>>11|q+r<<21)^((q+r|0)>>>25|q+r<<7))+(c[g+40+128>>2]|0)+((s+p^m+n)&q+r^s+p)|0;l=c[w>>2]|0;c[h>>2]=o+e;b=((l|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)&y|l&((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+e|0;c[x>>2]=b;p=s+p+773529912+(((o+e|0)>>>6|o+e<<26)^((o+e|0)>>>11|o+e<<21)^((o+e|0)>>>25|o+e<<7))+(c[g+40+132>>2]|0)+((m+n^q+r)&o+e^m+n)|0;s=c[t>>2]|0;c[w>>2]=l+p;c[j>>2]=((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p;n=m+n+1294757372+(((l+p|0)>>>6|l+p<<26)^((l+p|0)>>>11|l+p<<21)^((l+p|0)>>>25|l+p<<7))+(c[g+40+136>>2]|0)+((q+r^o+e)&l+p^q+r)|0;m=c[g+8>>2]|0;c[t>>2]=s+n;u=((m|b)&((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|m&b)+(((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>2|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<30)^((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>13|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<19)^((((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>22|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<10))+n|0;c[v>>2]=u;r=q+r+1396182291+(((s+n|0)>>>6|s+n<<26)^((s+n|0)>>>11|s+n<<21)^((s+n|0)>>>25|s+n<<7))+(c[g+40+140>>2]|0)+((o+e^l+p)&s+n^o+e)|0;q=c[x>>2]|0;c[g+8>>2]=m+r;b=((q|((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)&u|q&((s|y)&b|s&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+r|0;c[k>>2]=b;e=o+e+1695183700+(((m+r|0)>>>6|m+r<<26)^((m+r|0)>>>11|m+r<<21)^((m+r|0)>>>25|m+r<<7))+(c[g+40+144>>2]|0)+((l+p^s+n)&m+r^l+p)|0;o=c[j>>2]|0;c[x>>2]=q+e;c[h>>2]=((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e;p=l+p+1986661051+(((q+e|0)>>>6|q+e<<26)^((q+e|0)>>>11|q+e<<21)^((q+e|0)>>>25|q+e<<7))+(c[g+40+148>>2]|0)+((s+n^m+r)&q+e^s+n)|0;l=c[v>>2]|0;c[j>>2]=o+p;y=((l|b)&((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|l&b)+(((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>2|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<30)^((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>13|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<19)^((((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>22|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<10))+p|0;c[w>>2]=y;n=s+n+-2117940946+(((o+p|0)>>>6|o+p<<26)^((o+p|0)>>>11|o+p<<21)^((o+p|0)>>>25|o+p<<7))+(c[g+40+152>>2]|0)+((m+r^q+e)&o+p^m+r)|0;s=c[k>>2]|0;c[v>>2]=l+n;b=((s|((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)&y|s&((o|u)&b|o&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+n|0;c[t>>2]=b;r=m+r+-1838011259+(((l+n|0)>>>6|l+n<<26)^((l+n|0)>>>11|l+n<<21)^((l+n|0)>>>25|l+n<<7))+(c[g+40+156>>2]|0)+((q+e^o+p)&l+n^q+e)|0;m=c[h>>2]|0;c[k>>2]=s+r;c[g+8>>2]=((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r;e=q+e+-1564481375+(((s+r|0)>>>6|s+r<<26)^((s+r|0)>>>11|s+r<<21)^((s+r|0)>>>25|s+r<<7))+(c[g+40+160>>2]|0)+((o+p^l+n)&s+r^o+p)|0;q=c[w>>2]|0;c[h>>2]=m+e;u=((q|b)&((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|q&b)+(((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>2|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<30)^((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>13|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<19)^((((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>22|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<10))+e|0;c[x>>2]=u;p=o+p+-1474664885+(((m+e|0)>>>6|m+e<<26)^((m+e|0)>>>11|m+e<<21)^((m+e|0)>>>25|m+e<<7))+(c[g+40+164>>2]|0)+((l+n^s+r)&m+e^l+n)|0;o=c[t>>2]|0;c[w>>2]=q+p;b=((o|((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)&u|o&((m|y)&b|m&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+p|0;c[j>>2]=b;n=l+n+-1035236496+(((q+p|0)>>>6|q+p<<26)^((q+p|0)>>>11|q+p<<21)^((q+p|0)>>>25|q+p<<7))+(c[g+40+168>>2]|0)+((s+r^m+e)&q+p^s+r)|0;l=c[g+8>>2]|0;c[t>>2]=o+n;c[v>>2]=((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n;r=s+r+-949202525+(((o+n|0)>>>6|o+n<<26)^((o+n|0)>>>11|o+n<<21)^((o+n|0)>>>25|o+n<<7))+(c[g+40+172>>2]|0)+((m+e^q+p)&o+n^m+e)|0;s=c[x>>2]|0;c[g+8>>2]=l+r;y=((s|b)&((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|s&b)+(((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>2|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<30)^((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>13|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<19)^((((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>22|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<10))+r|0;c[k>>2]=y;e=m+e+-778901479+(((l+r|0)>>>6|l+r<<26)^((l+r|0)>>>11|l+r<<21)^((l+r|0)>>>25|l+r<<7))+(c[g+40+176>>2]|0)+((q+p^o+n)&l+r^q+p)|0;m=c[j>>2]|0;c[x>>2]=s+e;b=((m|((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)&y|m&((l|u)&b|l&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+e|0;c[h>>2]=b;p=q+p+-694614492+(((s+e|0)>>>6|s+e<<26)^((s+e|0)>>>11|s+e<<21)^((s+e|0)>>>25|s+e<<7))+(c[g+40+180>>2]|0)+((o+n^l+r)&s+e^o+n)|0;q=c[v>>2]|0;c[j>>2]=m+p;c[w>>2]=((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p;n=o+n+-200395387+(((m+p|0)>>>6|m+p<<26)^((m+p|0)>>>11|m+p<<21)^((m+p|0)>>>25|m+p<<7))+(c[g+40+184>>2]|0)+((l+r^s+e)&m+p^l+r)|0;o=c[k>>2]|0;c[v>>2]=q+n;u=((o|b)&((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|o&b)+(((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>2|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<30)^((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>13|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<19)^((((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>22|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<10))+n|0;c[t>>2]=u;r=l+r+275423344+(((q+n|0)>>>6|q+n<<26)^((q+n|0)>>>11|q+n<<21)^((q+n|0)>>>25|q+n<<7))+(c[g+40+188>>2]|0)+((s+e^m+p)&q+n^s+e)|0;l=c[h>>2]|0;c[k>>2]=o+r;b=((l|((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)&u|l&((q|y)&b|q&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+r|0;c[g+8>>2]=b;e=s+e+430227734+(((o+r|0)>>>6|o+r<<26)^((o+r|0)>>>11|o+r<<21)^((o+r|0)>>>25|o+r<<7))+(c[g+40+192>>2]|0)+((m+p^q+n)&o+r^m+p)|0;s=c[w>>2]|0;c[h>>2]=l+e;c[x>>2]=((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e;p=m+p+506948616+(((l+e|0)>>>6|l+e<<26)^((l+e|0)>>>11|l+e<<21)^((l+e|0)>>>25|l+e<<7))+(c[g+40+196>>2]|0)+((q+n^o+r)&l+e^q+n)|0;m=c[t>>2]|0;c[w>>2]=s+p;y=((m|b)&((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|m&b)+(((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>2|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<30)^((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>13|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<19)^((((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>22|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<10))+p|0;c[j>>2]=y;n=q+n+659060556+(((s+p|0)>>>6|s+p<<26)^((s+p|0)>>>11|s+p<<21)^((s+p|0)>>>25|s+p<<7))+(c[g+40+200>>2]|0)+((o+r^l+e)&s+p^o+r)|0;q=c[g+8>>2]|0;c[t>>2]=m+n;b=((q|((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)&y|q&((s|u)&b|s&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+n|0;c[v>>2]=b;r=o+r+883997877+(((m+n|0)>>>6|m+n<<26)^((m+n|0)>>>11|m+n<<21)^((m+n|0)>>>25|m+n<<7))+(c[g+40+204>>2]|0)+((l+e^s+p)&m+n^l+e)|0;o=c[x>>2]|0;c[g+8>>2]=q+r;c[k>>2]=((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r;e=l+e+958139571+(((q+r|0)>>>6|q+r<<26)^((q+r|0)>>>11|q+r<<21)^((q+r|0)>>>25|q+r<<7))+(c[g+40+208>>2]|0)+((s+p^m+n)&q+r^s+p)|0;l=c[j>>2]|0;c[x>>2]=o+e;u=((l|b)&((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|l&b)+(((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>2|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<30)^((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>13|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<19)^((((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r|0)>>>22|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r<<10))+e|0;c[h>>2]=u;p=s+p+1322822218+(((o+e|0)>>>6|o+e<<26)^((o+e|0)>>>11|o+e<<21)^((o+e|0)>>>25|o+e<<7))+(c[g+40+212>>2]|0)+((m+n^q+r)&o+e^m+n)|0;s=c[v>>2]|0;c[j>>2]=l+p;b=((s|((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)&u|s&((o|y)&b|o&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+r)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+p|0;c[w>>2]=b;n=m+n+1537002063+(((l+p|0)>>>6|l+p<<26)^((l+p|0)>>>11|l+p<<21)^((l+p|0)>>>25|l+p<<7))+(c[g+40+216>>2]|0)+((q+r^o+e)&l+p^q+r)|0;m=c[k>>2]|0;c[v>>2]=s+n;c[t>>2]=((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n;r=q+r+1747873779+(((s+n|0)>>>6|s+n<<26)^((s+n|0)>>>11|s+n<<21)^((s+n|0)>>>25|s+n<<7))+(c[g+40+220>>2]|0)+((o+e^l+p)&s+n^o+e)|0;q=c[h>>2]|0;c[k>>2]=m+r;y=((q|b)&((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|q&b)+(((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>2|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<30)^((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>13|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<19)^((((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n|0)>>>22|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n<<10))+r|0;c[g+8>>2]=y;e=o+e+1955562222+(((m+r|0)>>>6|m+r<<26)^((m+r|0)>>>11|m+r<<21)^((m+r|0)>>>25|m+r<<7))+(c[g+40+224>>2]|0)+((l+p^s+n)&m+r^l+p)|0;o=c[w>>2]|0;c[h>>2]=q+e;b=((o|((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)&y|o&((m|u)&b|m&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+n)+((y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10))+e|0;c[x>>2]=b;p=l+p+2024104815+(((q+e|0)>>>6|q+e<<26)^((q+e|0)>>>11|q+e<<21)^((q+e|0)>>>25|q+e<<7))+(c[g+40+228>>2]|0)+((s+n^m+r)&q+e^s+n)|0;l=c[t>>2]|0;c[w>>2]=o+p;c[j>>2]=((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p;n=s+n+-2067236844+(((o+p|0)>>>6|o+p<<26)^((o+p|0)>>>11|o+p<<21)^((o+p|0)>>>25|o+p<<7))+(c[g+40+232>>2]|0)+((m+r^q+e)&o+p^m+r)|0;s=c[g+8>>2]|0;c[t>>2]=l+n;u=((s|b)&((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|s&b)+(((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>2|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<30)^((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>13|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<19)^((((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p|0)>>>22|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p<<10))+n|0;c[v>>2]=u;r=m+r+-1933114872+(((l+n|0)>>>6|l+n<<26)^((l+n|0)>>>11|l+n<<21)^((l+n|0)>>>25|l+n<<7))+(c[g+40+236>>2]|0)+((q+e^o+p)&l+n^q+e)|0;m=c[x>>2]|0;c[g+8>>2]=s+r;b=((m|((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)&u|m&((l|y)&b|l&y)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+p)+((u>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10))+r|0;c[k>>2]=b;e=q+e+-1866530822+(((s+r|0)>>>6|s+r<<26)^((s+r|0)>>>11|s+r<<21)^((s+r|0)>>>25|s+r<<7))+(c[g+40+240>>2]|0)+((o+p^l+n)&s+r^o+p)|0;q=c[j>>2]|0;c[x>>2]=m+e;c[h>>2]=((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e;p=o+p+-1538233109+(((m+e|0)>>>6|m+e<<26)^((m+e|0)>>>11|m+e<<21)^((m+e|0)>>>25|m+e<<7))+(c[g+40+244>>2]|0)+((l+n^s+r)&m+e^l+n)|0;o=c[v>>2]|0;c[j>>2]=q+p;j=((o|b)&((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|o&b)+(((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>2|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<30)^((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>13|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<19)^((((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0)>>>22|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e<<10))+p|0;c[w>>2]=j;n=l+n+-1090935817+(((q+p|0)>>>6|q+p<<26)^((q+p|0)>>>11|q+p<<21)^((q+p|0)>>>25|q+p<<7))+(c[g+40+248>>2]|0)+((s+r^m+e)&q+p^s+r)|0;l=c[k>>2]|0;c[v>>2]=o+n;b=((l|((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)&j|l&((q|u)&b|q&u)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e)+((j>>>2|j<<30)^(j>>>13|j<<19)^(j>>>22|j<<10))+n|0;c[t>>2]=b;e=s+r+-965641998+(((o+n|0)>>>6|o+n<<26)^((o+n|0)>>>11|o+n<<21)^((o+n|0)>>>25|o+n<<7))+(c[g+40+252>>2]|0)+((m+e^q+p)&o+n^m+e)|0;c[g+4>>2]=e;h=c[h>>2]|0;c[g>>2]=((h|j)&b|h&j)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10));c[k>>2]=l+e;e=((h|j)&b|h&j)+((b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10))+e|0;c[g+8>>2]=e;c[a>>2]=(c[a>>2]|0)+e;e=1;while(1){y=a+(e<<2)|0;c[y>>2]=(c[y>>2]|0)+b;e=e+1|0;if((e|0)==8)break;b=c[g+8+(e<<2)>>2]|0}fd(g+40|0,256);fd(g+8|0,32);fd(g+4|0,4);fd(g,4);i=f;return}function la(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0;r=i;q=i=i+63&-64;i=i+4096|0;if(b){p=na(c[b+12>>2]<<3)|0;if(!p)e=-22;else{kf(q+3072|0);kf(q+2048|0);l=c[d>>2]|0;c[q+2048>>2]=l;c[q+2048+4>>2]=0;j=c[d+4>>2]|0;c[q+2048+8>>2]=j;c[q+2048+8+4>>2]=0;k=a[d+8>>0]|0;c[q+2048+16>>2]=k&255;c[q+2048+16+4>>2]=0;c[q+2048+24>>2]=c[b+8>>2];c[q+2048+24+4>>2]=0;c[q+2048+32>>2]=c[b+4>>2];c[q+2048+32+4>>2]=0;c[q+2048+40>>2]=c[b+28>>2];c[q+2048+40+4>>2]=0;e=c[b+12>>2]|0;if(!e)f=0;else{g=0;do{f=g&127;if(!f){e=oe(c[q+2048+48>>2]|0,c[q+2048+48+4>>2]|0,1,0)|0;c[q+2048+48>>2]=e;c[q+2048+48+4>>2]=D;kf(q);kf(q+1024|0);ma(q+3072|0,q+2048|0,q);ma(q+3072|0,q,q+1024|0);e=c[b+12>>2]|0}n=c[q+1024+(f<<3)+4>>2]|0;o=p+(g<<3)|0;c[o>>2]=c[q+1024+(f<<3)>>2];c[o+4>>2]=n;g=g+1|0}while(g>>>0<e>>>0);f=e}e=(l|0)==0&k<<24>>24==0?2:0;h=c[b+16>>2]|0;g=(S(h,j)|0)+e+(S(k&255,f)|0)|0;a:do if(e>>>0<f>>>0){o=g;f=(((g>>>0)%(h>>>0)|0|0)==0?h+-1|0:-1)+g|0;m=h;g=l;while(1){n=((o>>>0)%(m>>>0)|0|0)==1?o+-1|0:f;f=p+(e<<3)|0;j=c[f>>2]|0;f=Bd(c[f+4>>2]|0,0,c[b+20>>2]|0,0)|0;h=D;l=(g|0)==0;if(l?(a[d+8>>0]|0)==0:0){f=c[d+4>>2]|0;h=0}c[d+12>>2]=e;j=Eb(b,d,j,((h|0)==0?(f|0)==(c[d+4>>2]|0):0)&1)|0;k=c[(c[b>>2]|0)+4>>2]|0;f=Ed(m|0,0,f|0,h|0)|0;g=k+(o<<10)|0;if(l){ef(q+3072|0,k+(f<<10)+(j<<10)|0);gd(q+3072|0,k+(n<<10)|0);ef(q+2048|0,q+3072|0);f=0;do{m=f<<4;z=c[q+3072+(m<<3)>>2]|0;G=c[q+3072+(m<<3)+4>>2]|0;u=c[q+3072+((m|4)<<3)>>2]|0;s=c[q+3072+((m|4)<<3)+4>>2]|0;l=oe(u|0,s|0,z|0,G|0)|0;v=D;G=Pd(z|0,G|0,1)|0;G=Ed(G&-2|0,D&1|0,u|0,0)|0;G=oe(l|0,v|0,G|0,D|0)|0;v=D;l=G^c[q+3072+((m|12)<<3)>>2];z=v^c[q+3072+((m|12)<<3)+4>>2];y=c[q+3072+((m|8)<<3)>>2]|0;A=c[q+3072+((m|8)<<3)+4>>2]|0;C=oe(z|0,l|0,y|0,A|0)|0;j=D;A=Pd(y|0,A|0,1)|0;A=Ed(z|0,0,A&-2|0,D&1|0)|0;A=oe(C|0,j|0,A|0,D|0)|0;j=D;C=Rd(A^u|0,j^s|0,24)|0;y=D;s=Pd(A^u|0,j^s|0,40)|0;y=D|y;u=oe(s|C|0,y|0,G|0,v|0)|0;h=D;v=Pd(G|0,v|0,1)|0;v=Ed(C|0,0,v&-2|0,D&1|0)|0;v=oe(u|0,h|0,v|0,D|0)|0;h=D;c[q+3072+(m<<3)>>2]=v;c[q+3072+(m<<3)+4>>2]=h;u=Rd(v^z|0,h^l|0,16)|0;G=D;l=Pd(v^z|0,h^l|0,48)|0;G=D|G;c[q+3072+((m|12)<<3)>>2]=l|u;c[q+3072+((m|12)<<3)+4>>2]=G;G=oe(l|u|0,G|0,A|0,j|0)|0;l=D;j=Pd(A|0,j|0,1)|0;j=Ed(u|0,0,j&-2|0,D&1|0)|0;j=oe(G|0,l|0,j|0,D|0)|0;l=D;c[q+3072+((m|8)<<3)>>2]=j;c[q+3072+((m|8)<<3)+4>>2]=l;G=Rd(j^(s|C)|0,l^y|0,63)|0;u=D;y=Pd(j^(s|C)|0,l^y|0,1)|0;c[q+3072+((m|4)<<3)>>2]=y|G;c[q+3072+((m|4)<<3)+4>>2]=D|u;u=c[q+3072+((m|1)<<3)>>2]|0;G=c[q+3072+((m|1)<<3)+4>>2]|0;y=c[q+3072+((m|5)<<3)>>2]|0;l=c[q+3072+((m|5)<<3)+4>>2]|0;C=oe(y|0,l|0,u|0,G|0)|0;s=D;G=Pd(u|0,G|0,1)|0;G=Ed(G&-2|0,D&1|0,y|0,0)|0;G=oe(C|0,s|0,G|0,D|0)|0;s=D;C=G^c[q+3072+((m|13)<<3)>>2];u=s^c[q+3072+((m|13)<<3)+4>>2];j=c[q+3072+((m|9)<<3)>>2]|0;A=c[q+3072+((m|9)<<3)+4>>2]|0;h=oe(u|0,C|0,j|0,A|0)|0;z=D;A=Pd(j|0,A|0,1)|0;A=Ed(u|0,0,A&-2|0,D&1|0)|0;A=oe(h|0,z|0,A|0,D|0)|0;z=D;h=Rd(A^y|0,z^l|0,24)|0;j=D;l=Pd(A^y|0,z^l|0,40)|0;j=D|j;y=oe(l|h|0,j|0,G|0,s|0)|0;v=D;s=Pd(G|0,s|0,1)|0;s=Ed(h|0,0,s&-2|0,D&1|0)|0;s=oe(y|0,v|0,s|0,D|0)|0;v=D;c[q+3072+((m|1)<<3)>>2]=s;c[q+3072+((m|1)<<3)+4>>2]=v;y=Rd(s^u|0,v^C|0,16)|0;G=D;C=Pd(s^u|0,v^C|0,48)|0;G=D|G;c[q+3072+((m|13)<<3)>>2]=C|y;c[q+3072+((m|13)<<3)+4>>2]=G;G=oe(C|y|0,G|0,A|0,z|0)|0;C=D;z=Pd(A|0,z|0,1)|0;z=Ed(y|0,0,z&-2|0,D&1|0)|0;z=oe(G|0,C|0,z|0,D|0)|0;C=D;c[q+3072+((m|9)<<3)>>2]=z;c[q+3072+((m|9)<<3)+4>>2]=C;G=Rd(z^(l|h)|0,C^j|0,63)|0;y=D;j=Pd(z^(l|h)|0,C^j|0,1)|0;c[q+3072+((m|5)<<3)>>2]=j|G;c[q+3072+((m|5)<<3)+4>>2]=D|y;y=c[q+3072+((m|2)<<3)>>2]|0;G=c[q+3072+((m|2)<<3)+4>>2]|0;j=c[q+3072+((m|6)<<3)>>2]|0;C=c[q+3072+((m|6)<<3)+4>>2]|0;h=oe(j|0,C|0,y|0,G|0)|0;l=D;G=Pd(y|0,G|0,1)|0;G=Ed(G&-2|0,D&1|0,j|0,0)|0;G=oe(h|0,l|0,G|0,D|0)|0;l=D;h=G^c[q+3072+((m|14)<<3)>>2];y=l^c[q+3072+((m|14)<<3)+4>>2];z=c[q+3072+((m|10)<<3)>>2]|0;A=c[q+3072+((m|10)<<3)+4>>2]|0;v=oe(y|0,h|0,z|0,A|0)|0;u=D;A=Pd(z|0,A|0,1)|0;A=Ed(y|0,0,A&-2|0,D&1|0)|0;A=oe(v|0,u|0,A|0,D|0)|0;u=D;v=Rd(A^j|0,u^C|0,24)|0;z=D;C=Pd(A^j|0,u^C|0,40)|0;z=D|z;j=oe(C|v|0,z|0,G|0,l|0)|0;s=D;l=Pd(G|0,l|0,1)|0;l=Ed(v|0,0,l&-2|0,D&1|0)|0;l=oe(j|0,s|0,l|0,D|0)|0;s=D;c[q+3072+((m|2)<<3)>>2]=l;c[q+3072+((m|2)<<3)+4>>2]=s;j=Rd(l^y|0,s^h|0,16)|0;G=D;h=Pd(l^y|0,s^h|0,48)|0;G=D|G;c[q+3072+((m|14)<<3)>>2]=h|j;c[q+3072+((m|14)<<3)+4>>2]=G;G=oe(h|j|0,G|0,A|0,u|0)|0;h=D;u=Pd(A|0,u|0,1)|0;u=Ed(j|0,0,u&-2|0,D&1|0)|0;u=oe(G|0,h|0,u|0,D|0)|0;h=D;G=Rd(u^(C|v)|0,h^z|0,63)|0;j=D;z=Pd(u^(C|v)|0,h^z|0,1)|0;c[q+3072+((m|6)<<3)>>2]=z|G;c[q+3072+((m|6)<<3)+4>>2]=D|j;j=c[q+3072+((m|3)<<3)>>2]|0;G=c[q+3072+((m|3)<<3)+4>>2]|0;z=c[q+3072+((m|7)<<3)>>2]|0;v=c[q+3072+((m|7)<<3)+4>>2]|0;C=oe(z|0,v|0,j|0,G|0)|0;A=D;G=Pd(j|0,G|0,1)|0;G=Ed(G&-2|0,D&1|0,z|0,0)|0;G=oe(C|0,A|0,G|0,D|0)|0;A=D;C=G^c[q+3072+((m|15)<<3)>>2];j=A^c[q+3072+((m|15)<<3)+4>>2];s=c[q+3072+((m|11)<<3)>>2]|0;y=c[q+3072+((m|11)<<3)+4>>2]|0;l=oe(j|0,C|0,s|0,y|0)|0;t=D;y=Pd(s|0,y|0,1)|0;y=Ed(j|0,0,y&-2|0,D&1|0)|0;y=oe(l|0,t|0,y|0,D|0)|0;t=D;l=Rd(y^z|0,t^v|0,24)|0;s=D;v=Pd(y^z|0,t^v|0,40)|0;s=D|s;z=oe(v|l|0,s|0,G|0,A|0)|0;x=D;A=Pd(G|0,A|0,1)|0;A=Ed(l|0,0,A&-2|0,D&1|0)|0;A=oe(z|0,x|0,A|0,D|0)|0;x=D;c[q+3072+((m|3)<<3)>>2]=A;c[q+3072+((m|3)<<3)+4>>2]=x;z=Rd(A^j|0,x^C|0,16)|0;G=D;C=Pd(A^j|0,x^C|0,48)|0;G=D|G;x=oe(C|z|0,G|0,y|0,t|0)|0;j=D;t=Pd(y|0,t|0,1)|0;t=Ed(z|0,0,t&-2|0,D&1|0)|0;t=oe(x|0,j|0,t|0,D|0)|0;j=D;x=Rd(t^(v|l)|0,j^s|0,63)|0;y=D;s=Pd(t^(v|l)|0,j^s|0,1)|0;y=D|y;c[q+3072+((m|7)<<3)>>2]=s|x;c[q+3072+((m|7)<<3)+4>>2]=y;l=c[q+3072+(m<<3)>>2]|0;v=c[q+3072+(m<<3)+4>>2]|0;A=c[q+3072+((m|5)<<3)>>2]|0;B=c[q+3072+((m|5)<<3)+4>>2]|0;w=oe(A|0,B|0,l|0,v|0)|0;F=D;v=Pd(l|0,v|0,1)|0;v=Ed(v&-2|0,D&1|0,A|0,0)|0;v=oe(w|0,F|0,v|0,D|0)|0;F=D;w=oe(G^F|0,(C|z)^v|0,u|0,h|0)|0;l=D;h=Pd(u|0,h|0,1)|0;h=Ed(G^F|0,0,h&-2|0,D&1|0)|0;h=oe(w|0,l|0,h|0,D|0)|0;l=D;w=Rd(h^A|0,l^B|0,24)|0;u=D;B=Pd(h^A|0,l^B|0,40)|0;u=D|u;A=oe(B|w|0,u|0,v|0,F|0)|0;E=D;H=Pd(v|0,F|0,1)|0;H=Ed(w|0,0,H&-2|0,D&1|0)|0;H=oe(A|0,E|0,H|0,D|0)|0;E=D;c[q+3072+(m<<3)>>2]=H;c[q+3072+(m<<3)+4>>2]=E;A=Rd(H^(G^F)|0,E^((C|z)^v)|0,16)|0;k=D;v=Pd(H^(G^F)|0,E^((C|z)^v)|0,48)|0;k=D|k;c[q+3072+((m|15)<<3)>>2]=v|A;c[q+3072+((m|15)<<3)+4>>2]=k;k=oe(v|A|0,k|0,h|0,l|0)|0;v=D;l=Pd(h|0,l|0,1)|0;l=Ed(A|0,0,l&-2|0,D&1|0)|0;l=oe(k|0,v|0,l|0,D|0)|0;v=D;c[q+3072+((m|10)<<3)>>2]=l;c[q+3072+((m|10)<<3)+4>>2]=v;k=Rd(l^(B|w)|0,v^u|0,63)|0;A=D;u=Pd(l^(B|w)|0,v^u|0,1)|0;c[q+3072+((m|5)<<3)>>2]=u|k;c[q+3072+((m|5)<<3)+4>>2]=D|A;A=c[q+3072+((m|1)<<3)>>2]|0;k=c[q+3072+((m|1)<<3)+4>>2]|0;u=c[q+3072+((m|6)<<3)>>2]|0;v=c[q+3072+((m|6)<<3)+4>>2]|0;w=oe(u|0,v|0,A|0,k|0)|0;B=D;k=Pd(A|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,u|0,0)|0;k=oe(w|0,B|0,k|0,D|0)|0;B=D;w=k^c[q+3072+((m|12)<<3)>>2];A=B^c[q+3072+((m|12)<<3)+4>>2];l=oe(A|0,w|0,t|0,j|0)|0;h=D;j=Pd(t|0,j|0,1)|0;j=Ed(j&-2|0,D&1|0,A|0,0)|0;j=oe(l|0,h|0,j|0,D|0)|0;h=D;l=Rd(j^u|0,h^v|0,24)|0;t=D;v=Pd(j^u|0,h^v|0,40)|0;t=D|t;u=oe(v|l|0,t|0,k|0,B|0)|0;z=D;B=Pd(k|0,B|0,1)|0;B=Ed(l|0,0,B&-2|0,D&1|0)|0;B=oe(u|0,z|0,B|0,D|0)|0;z=D;c[q+3072+((m|1)<<3)>>2]=B;c[q+3072+((m|1)<<3)+4>>2]=z;u=Rd(B^A|0,z^w|0,16)|0;k=D;w=Pd(B^A|0,z^w|0,48)|0;k=D|k;c[q+3072+((m|12)<<3)>>2]=w|u;c[q+3072+((m|12)<<3)+4>>2]=k;k=oe(w|u|0,k|0,j|0,h|0)|0;w=D;h=Pd(j|0,h|0,1)|0;h=Ed(u|0,0,h&-2|0,D&1|0)|0;h=oe(k|0,w|0,h|0,D|0)|0;w=D;c[q+3072+((m|11)<<3)>>2]=h;c[q+3072+((m|11)<<3)+4>>2]=w;k=Rd(h^(v|l)|0,w^t|0,63)|0;u=D;t=Pd(h^(v|l)|0,w^t|0,1)|0;c[q+3072+((m|6)<<3)>>2]=t|k;c[q+3072+((m|6)<<3)+4>>2]=D|u;u=c[q+3072+((m|2)<<3)>>2]|0;k=c[q+3072+((m|2)<<3)+4>>2]|0;t=oe(s|x|0,y|0,u|0,k|0)|0;w=D;k=Pd(u|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,s|x|0,0)|0;k=oe(t|0,w|0,k|0,D|0)|0;w=D;t=k^c[q+3072+((m|13)<<3)>>2];u=w^c[q+3072+((m|13)<<3)+4>>2];l=c[q+3072+((m|8)<<3)>>2]|0;v=c[q+3072+((m|8)<<3)+4>>2]|0;h=oe(u|0,t|0,l|0,v|0)|0;j=D;v=Pd(l|0,v|0,1)|0;v=Ed(u|0,0,v&-2|0,D&1|0)|0;v=oe(h|0,j|0,v|0,D|0)|0;j=D;h=Rd(v^(s|x)|0,j^y|0,24)|0;l=D;y=Pd(v^(s|x)|0,j^y|0,40)|0;l=D|l;x=oe(y|h|0,l|0,k|0,w|0)|0;s=D;w=Pd(k|0,w|0,1)|0;w=Ed(h|0,0,w&-2|0,D&1|0)|0;w=oe(x|0,s|0,w|0,D|0)|0;s=D;c[q+3072+((m|2)<<3)>>2]=w;c[q+3072+((m|2)<<3)+4>>2]=s;x=Rd(w^u|0,s^t|0,16)|0;k=D;t=Pd(w^u|0,s^t|0,48)|0;k=D|k;c[q+3072+((m|13)<<3)>>2]=t|x;c[q+3072+((m|13)<<3)+4>>2]=k;k=oe(t|x|0,k|0,v|0,j|0)|0;t=D;j=Pd(v|0,j|0,1)|0;j=Ed(x|0,0,j&-2|0,D&1|0)|0;j=oe(k|0,t|0,j|0,D|0)|0;t=D;c[q+3072+((m|8)<<3)>>2]=j;c[q+3072+((m|8)<<3)+4>>2]=t;k=Rd(j^(y|h)|0,t^l|0,63)|0;x=D;l=Pd(j^(y|h)|0,t^l|0,1)|0;c[q+3072+((m|7)<<3)>>2]=l|k;c[q+3072+((m|7)<<3)+4>>2]=D|x;x=c[q+3072+((m|3)<<3)>>2]|0;k=c[q+3072+((m|3)<<3)+4>>2]|0;l=c[q+3072+((m|4)<<3)>>2]|0;t=c[q+3072+((m|4)<<3)+4>>2]|0;h=oe(l|0,t|0,x|0,k|0)|0;y=D;k=Pd(x|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,l|0,0)|0;k=oe(h|0,y|0,k|0,D|0)|0;y=D;h=k^c[q+3072+((m|14)<<3)>>2];x=y^c[q+3072+((m|14)<<3)+4>>2];j=c[q+3072+((m|9)<<3)>>2]|0;v=c[q+3072+((m|9)<<3)+4>>2]|0;s=oe(x|0,h|0,j|0,v|0)|0;u=D;v=Pd(j|0,v|0,1)|0;v=Ed(x|0,0,v&-2|0,D&1|0)|0;v=oe(s|0,u|0,v|0,D|0)|0;u=D;s=Rd(v^l|0,u^t|0,24)|0;j=D;t=Pd(v^l|0,u^t|0,40)|0;j=D|j;l=oe(t|s|0,j|0,k|0,y|0)|0;w=D;y=Pd(k|0,y|0,1)|0;y=Ed(s|0,0,y&-2|0,D&1|0)|0;y=oe(l|0,w|0,y|0,D|0)|0;w=D;c[q+3072+((m|3)<<3)>>2]=y;c[q+3072+((m|3)<<3)+4>>2]=w;l=Rd(y^x|0,w^h|0,16)|0;k=D;h=Pd(y^x|0,w^h|0,48)|0;k=D|k;c[q+3072+((m|14)<<3)>>2]=h|l;c[q+3072+((m|14)<<3)+4>>2]=k;k=oe(h|l|0,k|0,v|0,u|0)|0;h=D;u=Pd(v|0,u|0,1)|0;u=Ed(l|0,0,u&-2|0,D&1|0)|0;u=oe(k|0,h|0,u|0,D|0)|0;h=D;c[q+3072+((m|9)<<3)>>2]=u;c[q+3072+((m|9)<<3)+4>>2]=h;k=Rd(u^(t|s)|0,h^j|0,63)|0;l=D;j=Pd(u^(t|s)|0,h^j|0,1)|0;c[q+3072+((m|4)<<3)>>2]=j|k;c[q+3072+((m|4)<<3)+4>>2]=D|l;f=f+1|0}while((f|0)!=8);f=0;do{H=f<<1;A=c[q+3072+(H<<3)>>2]|0;E=c[q+3072+(H<<3)+4>>2]|0;v=q+3072+(H+32<<3)|0;y=c[v>>2]|0;v=c[v+4>>2]|0;s=oe(y|0,v|0,A|0,E|0)|0;j=D;E=Pd(A|0,E|0,1)|0;E=Ed(E&-2|0,D&1|0,y|0,0)|0;E=oe(s|0,j|0,E|0,D|0)|0;j=D;s=q+3072+(H+96<<3)|0;A=E^c[s>>2];s=j^c[s+4>>2];m=q+3072+(H+64<<3)|0;w=c[m>>2]|0;m=c[m+4>>2]|0;F=oe(s|0,A|0,w|0,m|0)|0;u=D;m=Pd(w|0,m|0,1)|0;m=Ed(s|0,0,m&-2|0,D&1|0)|0;m=oe(F|0,u|0,m|0,D|0)|0;u=D;F=Rd(m^y|0,u^v|0,24)|0;w=D;v=Pd(m^y|0,u^v|0,40)|0;w=D|w;y=oe(v|F|0,w|0,E|0,j|0)|0;B=D;j=Pd(E|0,j|0,1)|0;j=Ed(F|0,0,j&-2|0,D&1|0)|0;j=oe(y|0,B|0,j|0,D|0)|0;B=D;c[q+3072+(H<<3)>>2]=j;c[q+3072+(H<<3)+4>>2]=B;y=Rd(j^s|0,B^A|0,16)|0;E=D;A=Pd(j^s|0,B^A|0,48)|0;E=D|E;B=q+3072+(H+96<<3)|0;c[B>>2]=A|y;c[B+4>>2]=E;E=oe(A|y|0,E|0,m|0,u|0)|0;A=D;u=Pd(m|0,u|0,1)|0;u=Ed(y|0,0,u&-2|0,D&1|0)|0;u=oe(E|0,A|0,u|0,D|0)|0;A=D;E=q+3072+(H+64<<3)|0;c[E>>2]=u;c[E+4>>2]=A;E=Rd(u^(v|F)|0,A^w|0,63)|0;y=D;w=Pd(u^(v|F)|0,A^w|0,1)|0;A=q+3072+(H+32<<3)|0;c[A>>2]=w|E;c[A+4>>2]=D|y;A=c[q+3072+((H|1)<<3)>>2]|0;y=c[q+3072+((H|1)<<3)+4>>2]|0;E=q+3072+(H+33<<3)|0;w=c[E>>2]|0;E=c[E+4>>2]|0;F=oe(w|0,E|0,A|0,y|0)|0;v=D;y=Pd(A|0,y|0,1)|0;y=Ed(y&-2|0,D&1|0,w|0,0)|0;y=oe(F|0,v|0,y|0,D|0)|0;v=D;F=q+3072+(H+97<<3)|0;A=y^c[F>>2];F=v^c[F+4>>2];u=q+3072+(H+65<<3)|0;m=c[u>>2]|0;u=c[u+4>>2]|0;B=oe(F|0,A|0,m|0,u|0)|0;s=D;u=Pd(m|0,u|0,1)|0;u=Ed(F|0,0,u&-2|0,D&1|0)|0;u=oe(B|0,s|0,u|0,D|0)|0;s=D;B=Rd(u^w|0,s^E|0,24)|0;m=D;E=Pd(u^w|0,s^E|0,40)|0;m=D|m;w=oe(E|B|0,m|0,y|0,v|0)|0;j=D;v=Pd(y|0,v|0,1)|0;v=Ed(B|0,0,v&-2|0,D&1|0)|0;v=oe(w|0,j|0,v|0,D|0)|0;j=D;c[q+3072+((H|1)<<3)>>2]=v;c[q+3072+((H|1)<<3)+4>>2]=j;w=Rd(v^F|0,j^A|0,16)|0;y=D;A=Pd(v^F|0,j^A|0,48)|0;y=D|y;j=q+3072+(H+97<<3)|0;c[j>>2]=A|w;c[j+4>>2]=y;y=oe(A|w|0,y|0,u|0,s|0)|0;A=D;s=Pd(u|0,s|0,1)|0;s=Ed(w|0,0,s&-2|0,D&1|0)|0;s=oe(y|0,A|0,s|0,D|0)|0;A=D;y=q+3072+(H+65<<3)|0;c[y>>2]=s;c[y+4>>2]=A;y=Rd(s^(E|B)|0,A^m|0,63)|0;w=D;m=Pd(s^(E|B)|0,A^m|0,1)|0;A=q+3072+(H+33<<3)|0;c[A>>2]=m|y;c[A+4>>2]=D|w;A=q+3072+(H+16<<3)|0;w=c[A>>2]|0;A=c[A+4>>2]|0;y=q+3072+(H+48<<3)|0;m=c[y>>2]|0;y=c[y+4>>2]|0;B=oe(m|0,y|0,w|0,A|0)|0;E=D;A=Pd(w|0,A|0,1)|0;A=Ed(A&-2|0,D&1|0,m|0,0)|0;A=oe(B|0,E|0,A|0,D|0)|0;E=D;B=q+3072+(H+112<<3)|0;w=A^c[B>>2];B=E^c[B+4>>2];s=q+3072+(H+80<<3)|0;u=c[s>>2]|0;s=c[s+4>>2]|0;j=oe(B|0,w|0,u|0,s|0)|0;F=D;s=Pd(u|0,s|0,1)|0;s=Ed(B|0,0,s&-2|0,D&1|0)|0;s=oe(j|0,F|0,s|0,D|0)|0;F=D;j=Rd(s^m|0,F^y|0,24)|0;u=D;y=Pd(s^m|0,F^y|0,40)|0;u=D|u;m=oe(y|j|0,u|0,A|0,E|0)|0;v=D;E=Pd(A|0,E|0,1)|0;E=Ed(j|0,0,E&-2|0,D&1|0)|0;E=oe(m|0,v|0,E|0,D|0)|0;v=D;m=q+3072+(H+16<<3)|0;c[m>>2]=E;c[m+4>>2]=v;m=Rd(E^B|0,v^w|0,16)|0;A=D;w=Pd(E^B|0,v^w|0,48)|0;A=D|A;v=q+3072+(H+112<<3)|0;c[v>>2]=w|m;c[v+4>>2]=A;A=oe(w|m|0,A|0,s|0,F|0)|0;w=D;F=Pd(s|0,F|0,1)|0;F=Ed(m|0,0,F&-2|0,D&1|0)|0;F=oe(A|0,w|0,F|0,D|0)|0;w=D;A=Rd(F^(y|j)|0,w^u|0,63)|0;m=D;u=Pd(F^(y|j)|0,w^u|0,1)|0;j=q+3072+(H+48<<3)|0;c[j>>2]=u|A;c[j+4>>2]=D|m;j=q+3072+(H+17<<3)|0;m=c[j>>2]|0;j=c[j+4>>2]|0;A=q+3072+(H+49<<3)|0;u=c[A>>2]|0;A=c[A+4>>2]|0;y=oe(u|0,A|0,m|0,j|0)|0;s=D;j=Pd(m|0,j|0,1)|0;j=Ed(j&-2|0,D&1|0,u|0,0)|0;j=oe(y|0,s|0,j|0,D|0)|0;s=D;y=q+3072+(H+113<<3)|0;m=j^c[y>>2];y=s^c[y+4>>2];v=q+3072+(H+81<<3)|0;B=c[v>>2]|0;v=c[v+4>>2]|0;E=oe(y|0,m|0,B|0,v|0)|0;x=D;v=Pd(B|0,v|0,1)|0;v=Ed(y|0,0,v&-2|0,D&1|0)|0;v=oe(E|0,x|0,v|0,D|0)|0;x=D;E=Rd(v^u|0,x^A|0,24)|0;B=D;A=Pd(v^u|0,x^A|0,40)|0;B=D|B;u=oe(A|E|0,B|0,j|0,s|0)|0;C=D;s=Pd(j|0,s|0,1)|0;s=Ed(E|0,0,s&-2|0,D&1|0)|0;s=oe(u|0,C|0,s|0,D|0)|0;C=D;u=q+3072+(H+17<<3)|0;c[u>>2]=s;c[u+4>>2]=C;u=Rd(s^y|0,C^m|0,16)|0;j=D;m=Pd(s^y|0,C^m|0,48)|0;j=D|j;C=oe(m|u|0,j|0,v|0,x|0)|0;y=D;x=Pd(v|0,x|0,1)|0;x=Ed(u|0,0,x&-2|0,D&1|0)|0;x=oe(C|0,y|0,x|0,D|0)|0;y=D;C=Rd(x^(A|E)|0,y^B|0,63)|0;v=D;B=Pd(x^(A|E)|0,y^B|0,1)|0;v=D|v;E=q+3072+(H+49<<3)|0;c[E>>2]=B|C;c[E+4>>2]=v;E=c[q+3072+(H<<3)>>2]|0;A=c[q+3072+(H<<3)+4>>2]|0;s=q+3072+(H+33<<3)|0;z=c[s>>2]|0;s=c[s+4>>2]|0;t=oe(z|0,s|0,E|0,A|0)|0;k=D;A=Pd(E|0,A|0,1)|0;A=Ed(A&-2|0,D&1|0,z|0,0)|0;A=oe(t|0,k|0,A|0,D|0)|0;k=D;t=oe(j^k|0,(m|u)^A|0,F|0,w|0)|0;E=D;w=Pd(F|0,w|0,1)|0;w=Ed(j^k|0,0,w&-2|0,D&1|0)|0;w=oe(t|0,E|0,w|0,D|0)|0;E=D;t=Rd(w^z|0,E^s|0,24)|0;F=D;s=Pd(w^z|0,E^s|0,40)|0;F=D|F;z=oe(s|t|0,F|0,A|0,k|0)|0;l=D;h=Pd(A|0,k|0,1)|0;h=Ed(t|0,0,h&-2|0,D&1|0)|0;h=oe(z|0,l|0,h|0,D|0)|0;l=D;c[q+3072+(H<<3)>>2]=h;c[q+3072+(H<<3)+4>>2]=l;z=Rd(h^(j^k)|0,l^((m|u)^A)|0,16)|0;G=D;A=Pd(h^(j^k)|0,l^((m|u)^A)|0,48)|0;G=D|G;u=q+3072+(H+113<<3)|0;c[u>>2]=A|z;c[u+4>>2]=G;G=oe(A|z|0,G|0,w|0,E|0)|0;A=D;E=Pd(w|0,E|0,1)|0;E=Ed(z|0,0,E&-2|0,D&1|0)|0;E=oe(G|0,A|0,E|0,D|0)|0;A=D;G=q+3072+(H+80<<3)|0;c[G>>2]=E;c[G+4>>2]=A;G=Rd(E^(s|t)|0,A^F|0,63)|0;z=D;F=Pd(E^(s|t)|0,A^F|0,1)|0;A=q+3072+(H+33<<3)|0;c[A>>2]=F|G;c[A+4>>2]=D|z;A=c[q+3072+((H|1)<<3)>>2]|0;z=c[q+3072+((H|1)<<3)+4>>2]|0;G=q+3072+(H+48<<3)|0;F=c[G>>2]|0;G=c[G+4>>2]|0;t=oe(F|0,G|0,A|0,z|0)|0;s=D;z=Pd(A|0,z|0,1)|0;z=Ed(z&-2|0,D&1|0,F|0,0)|0;z=oe(t|0,s|0,z|0,D|0)|0;s=D;t=q+3072+(H+96<<3)|0;A=z^c[t>>2];t=s^c[t+4>>2];E=oe(t|0,A|0,x|0,y|0)|0;w=D;y=Pd(x|0,y|0,1)|0;y=Ed(y&-2|0,D&1|0,t|0,0)|0;y=oe(E|0,w|0,y|0,D|0)|0;w=D;E=Rd(y^F|0,w^G|0,24)|0;x=D;G=Pd(y^F|0,w^G|0,40)|0;x=D|x;F=oe(G|E|0,x|0,z|0,s|0)|0;u=D;s=Pd(z|0,s|0,1)|0;s=Ed(E|0,0,s&-2|0,D&1|0)|0;s=oe(F|0,u|0,s|0,D|0)|0;u=D;c[q+3072+((H|1)<<3)>>2]=s;c[q+3072+((H|1)<<3)+4>>2]=u;F=Rd(s^t|0,u^A|0,16)|0;z=D;A=Pd(s^t|0,u^A|0,48)|0;z=D|z;u=q+3072+(H+96<<3)|0;c[u>>2]=A|F;c[u+4>>2]=z;z=oe(A|F|0,z|0,y|0,w|0)|0;A=D;w=Pd(y|0,w|0,1)|0;w=Ed(F|0,0,w&-2|0,D&1|0)|0;w=oe(z|0,A|0,w|0,D|0)|0;A=D;z=q+3072+(H+81<<3)|0;c[z>>2]=w;c[z+4>>2]=A;z=Rd(w^(G|E)|0,A^x|0,63)|0;F=D;x=Pd(w^(G|E)|0,A^x|0,1)|0;A=q+3072+(H+48<<3)|0;c[A>>2]=x|z;c[A+4>>2]=D|F;A=q+3072+(H+16<<3)|0;F=c[A>>2]|0;A=c[A+4>>2]|0;z=oe(B|C|0,v|0,F|0,A|0)|0;x=D;A=Pd(F|0,A|0,1)|0;A=Ed(A&-2|0,D&1|0,B|C|0,0)|0;A=oe(z|0,x|0,A|0,D|0)|0;x=D;z=q+3072+(H+97<<3)|0;F=A^c[z>>2];z=x^c[z+4>>2];E=q+3072+(H+64<<3)|0;G=c[E>>2]|0;E=c[E+4>>2]|0;w=oe(z|0,F|0,G|0,E|0)|0;y=D;E=Pd(G|0,E|0,1)|0;E=Ed(z|0,0,E&-2|0,D&1|0)|0;E=oe(w|0,y|0,E|0,D|0)|0;y=D;w=Rd(E^(B|C)|0,y^v|0,24)|0;G=D;v=Pd(E^(B|C)|0,y^v|0,40)|0;G=D|G;C=oe(v|w|0,G|0,A|0,x|0)|0;B=D;x=Pd(A|0,x|0,1)|0;x=Ed(w|0,0,x&-2|0,D&1|0)|0;x=oe(C|0,B|0,x|0,D|0)|0;B=D;C=q+3072+(H+16<<3)|0;c[C>>2]=x;c[C+4>>2]=B;C=Rd(x^z|0,B^F|0,16)|0;A=D;F=Pd(x^z|0,B^F|0,48)|0;A=D|A;B=q+3072+(H+97<<3)|0;c[B>>2]=F|C;c[B+4>>2]=A;A=oe(F|C|0,A|0,E|0,y|0)|0;F=D;y=Pd(E|0,y|0,1)|0;y=Ed(C|0,0,y&-2|0,D&1|0)|0;y=oe(A|0,F|0,y|0,D|0)|0;F=D;A=q+3072+(H+64<<3)|0;c[A>>2]=y;c[A+4>>2]=F;A=Rd(y^(v|w)|0,F^G|0,63)|0;C=D;G=Pd(y^(v|w)|0,F^G|0,1)|0;F=q+3072+(H+49<<3)|0;c[F>>2]=G|A;c[F+4>>2]=D|C;F=q+3072+(H+17<<3)|0;C=c[F>>2]|0;F=c[F+4>>2]|0;A=q+3072+(H+32<<3)|0;G=c[A>>2]|0;A=c[A+4>>2]|0;w=oe(G|0,A|0,C|0,F|0)|0;v=D;F=Pd(C|0,F|0,1)|0;F=Ed(F&-2|0,D&1|0,G|0,0)|0;F=oe(w|0,v|0,F|0,D|0)|0;v=D;w=q+3072+(H+112<<3)|0;C=F^c[w>>2];w=v^c[w+4>>2];y=q+3072+(H+65<<3)|0;E=c[y>>2]|0;y=c[y+4>>2]|0;B=oe(w|0,C|0,E|0,y|0)|0;z=D;y=Pd(E|0,y|0,1)|0;y=Ed(w|0,0,y&-2|0,D&1|0)|0;y=oe(B|0,z|0,y|0,D|0)|0;z=D;B=Rd(y^G|0,z^A|0,24)|0;E=D;A=Pd(y^G|0,z^A|0,40)|0;E=D|E;G=oe(A|B|0,E|0,F|0,v|0)|0;x=D;v=Pd(F|0,v|0,1)|0;v=Ed(B|0,0,v&-2|0,D&1|0)|0;v=oe(G|0,x|0,v|0,D|0)|0;x=D;G=q+3072+(H+17<<3)|0;c[G>>2]=v;c[G+4>>2]=x;G=Rd(v^w|0,x^C|0,16)|0;F=D;C=Pd(v^w|0,x^C|0,48)|0;F=D|F;x=q+3072+(H+112<<3)|0;c[x>>2]=C|G;c[x+4>>2]=F;F=oe(C|G|0,F|0,y|0,z|0)|0;C=D;z=Pd(y|0,z|0,1)|0;z=Ed(G|0,0,z&-2|0,D&1|0)|0;z=oe(F|0,C|0,z|0,D|0)|0;C=D;F=q+3072+(H+65<<3)|0;c[F>>2]=z;c[F+4>>2]=C;F=Rd(z^(A|B)|0,C^E|0,63)|0;G=D;E=Pd(z^(A|B)|0,C^E|0,1)|0;H=q+3072+(H+32<<3)|0;c[H>>2]=E|F;c[H+4>>2]=D|G;f=f+1|0}while((f|0)!=8);ef(g,q+2048|0);gd(g,q+3072|0)}else ma(k+(n<<10)|0,k+(f<<10)+(j<<10)|0,g);e=e+1|0;if(e>>>0>=(c[b+12>>2]|0)>>>0)break a;o=o+1|0;f=n+1|0;m=c[b+16>>2]|0;g=c[d>>2]|0}}while(0);ta(p);e=0}}else e=0;i=r;return e|0}function ma(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0;e=i;f=i=i+63&-64;i=i+2048|0;ef(f+1024|0,b);gd(f+1024|0,a);ef(f,f+1024|0);gd(f,d);a=0;do{b=a<<4;o=c[f+1024+(b<<3)>>2]|0;x=c[f+1024+(b<<3)+4>>2]|0;n=c[f+1024+((b|4)<<3)>>2]|0;l=c[f+1024+((b|4)<<3)+4>>2]|0;g=oe(n|0,l|0,o|0,x|0)|0;v=D;x=Pd(o|0,x|0,1)|0;x=Ed(x&-2|0,D&1|0,n|0,0)|0;x=oe(g|0,v|0,x|0,D|0)|0;v=D;g=x^c[f+1024+((b|12)<<3)>>2];o=v^c[f+1024+((b|12)<<3)+4>>2];r=c[f+1024+((b|8)<<3)>>2]|0;t=c[f+1024+((b|8)<<3)+4>>2]|0;s=oe(o|0,g|0,r|0,t|0)|0;j=D;t=Pd(r|0,t|0,1)|0;t=Ed(t&-2|0,D&1|0,o|0,0)|0;t=oe(s|0,j|0,t|0,D|0)|0;j=D;s=Rd(t^n|0,j^l|0,24)|0;r=D;l=Pd(t^n|0,j^l|0,40)|0;r=D|r;n=oe(l|s|0,r|0,x|0,v|0)|0;k=D;v=Pd(x|0,v|0,1)|0;v=Ed(s|0,0,v&-2|0,D&1|0)|0;v=oe(n|0,k|0,v|0,D|0)|0;k=D;c[f+1024+(b<<3)>>2]=v;c[f+1024+(b<<3)+4>>2]=k;n=Rd(v^o|0,k^g|0,16)|0;x=D;g=Pd(v^o|0,k^g|0,48)|0;x=D|x;c[f+1024+((b|12)<<3)>>2]=g|n;c[f+1024+((b|12)<<3)+4>>2]=x;x=oe(g|n|0,x|0,t|0,j|0)|0;g=D;j=Pd(t|0,j|0,1)|0;j=Ed(n|0,0,j&-2|0,D&1|0)|0;j=oe(x|0,g|0,j|0,D|0)|0;g=D;c[f+1024+((b|8)<<3)>>2]=j;c[f+1024+((b|8)<<3)+4>>2]=g;x=Rd(j^(l|s)|0,g^r|0,63)|0;n=D;r=Pd(j^(l|s)|0,g^r|0,1)|0;c[f+1024+((b|4)<<3)>>2]=r|x;c[f+1024+((b|4)<<3)+4>>2]=D|n;n=c[f+1024+((b|1)<<3)>>2]|0;x=c[f+1024+((b|1)<<3)+4>>2]|0;r=c[f+1024+((b|5)<<3)>>2]|0;g=c[f+1024+((b|5)<<3)+4>>2]|0;s=oe(r|0,g|0,n|0,x|0)|0;l=D;x=Pd(n|0,x|0,1)|0;x=Ed(x&-2|0,D&1|0,r|0,0)|0;x=oe(s|0,l|0,x|0,D|0)|0;l=D;s=x^c[f+1024+((b|13)<<3)>>2];n=l^c[f+1024+((b|13)<<3)+4>>2];j=c[f+1024+((b|9)<<3)>>2]|0;t=c[f+1024+((b|9)<<3)+4>>2]|0;k=oe(n|0,s|0,j|0,t|0)|0;o=D;t=Pd(j|0,t|0,1)|0;t=Ed(t&-2|0,D&1|0,n|0,0)|0;t=oe(k|0,o|0,t|0,D|0)|0;o=D;k=Rd(t^r|0,o^g|0,24)|0;j=D;g=Pd(t^r|0,o^g|0,40)|0;j=D|j;r=oe(g|k|0,j|0,x|0,l|0)|0;v=D;l=Pd(x|0,l|0,1)|0;l=Ed(k|0,0,l&-2|0,D&1|0)|0;l=oe(r|0,v|0,l|0,D|0)|0;v=D;c[f+1024+((b|1)<<3)>>2]=l;c[f+1024+((b|1)<<3)+4>>2]=v;r=Rd(l^n|0,v^s|0,16)|0;x=D;s=Pd(l^n|0,v^s|0,48)|0;x=D|x;c[f+1024+((b|13)<<3)>>2]=s|r;c[f+1024+((b|13)<<3)+4>>2]=x;x=oe(s|r|0,x|0,t|0,o|0)|0;s=D;o=Pd(t|0,o|0,1)|0;o=Ed(r|0,0,o&-2|0,D&1|0)|0;o=oe(x|0,s|0,o|0,D|0)|0;s=D;c[f+1024+((b|9)<<3)>>2]=o;c[f+1024+((b|9)<<3)+4>>2]=s;x=Rd(o^(g|k)|0,s^j|0,63)|0;r=D;j=Pd(o^(g|k)|0,s^j|0,1)|0;c[f+1024+((b|5)<<3)>>2]=j|x;c[f+1024+((b|5)<<3)+4>>2]=D|r;r=c[f+1024+((b|2)<<3)>>2]|0;x=c[f+1024+((b|2)<<3)+4>>2]|0;j=c[f+1024+((b|6)<<3)>>2]|0;s=c[f+1024+((b|6)<<3)+4>>2]|0;k=oe(j|0,s|0,r|0,x|0)|0;g=D;x=Pd(r|0,x|0,1)|0;x=Ed(x&-2|0,D&1|0,j|0,0)|0;x=oe(k|0,g|0,x|0,D|0)|0;g=D;k=x^c[f+1024+((b|14)<<3)>>2];r=g^c[f+1024+((b|14)<<3)+4>>2];o=c[f+1024+((b|10)<<3)>>2]|0;t=c[f+1024+((b|10)<<3)+4>>2]|0;v=oe(r|0,k|0,o|0,t|0)|0;n=D;t=Pd(o|0,t|0,1)|0;t=Ed(t&-2|0,D&1|0,r|0,0)|0;t=oe(v|0,n|0,t|0,D|0)|0;n=D;v=Rd(t^j|0,n^s|0,24)|0;o=D;s=Pd(t^j|0,n^s|0,40)|0;o=D|o;j=oe(s|v|0,o|0,x|0,g|0)|0;l=D;g=Pd(x|0,g|0,1)|0;g=Ed(v|0,0,g&-2|0,D&1|0)|0;g=oe(j|0,l|0,g|0,D|0)|0;l=D;c[f+1024+((b|2)<<3)>>2]=g;c[f+1024+((b|2)<<3)+4>>2]=l;j=Rd(g^r|0,l^k|0,16)|0;x=D;k=Pd(g^r|0,l^k|0,48)|0;x=D|x;c[f+1024+((b|14)<<3)>>2]=k|j;c[f+1024+((b|14)<<3)+4>>2]=x;x=oe(k|j|0,x|0,t|0,n|0)|0;k=D;n=Pd(t|0,n|0,1)|0;n=Ed(j|0,0,n&-2|0,D&1|0)|0;n=oe(x|0,k|0,n|0,D|0)|0;k=D;x=Rd(n^(s|v)|0,k^o|0,63)|0;j=D;o=Pd(n^(s|v)|0,k^o|0,1)|0;c[f+1024+((b|6)<<3)>>2]=o|x;c[f+1024+((b|6)<<3)+4>>2]=D|j;j=c[f+1024+((b|3)<<3)>>2]|0;x=c[f+1024+((b|3)<<3)+4>>2]|0;o=c[f+1024+((b|7)<<3)>>2]|0;v=c[f+1024+((b|7)<<3)+4>>2]|0;s=oe(o|0,v|0,j|0,x|0)|0;t=D;x=Pd(j|0,x|0,1)|0;x=Ed(x&-2|0,D&1|0,o|0,0)|0;x=oe(s|0,t|0,x|0,D|0)|0;t=D;s=x^c[f+1024+((b|15)<<3)>>2];j=t^c[f+1024+((b|15)<<3)+4>>2];l=c[f+1024+((b|11)<<3)>>2]|0;r=c[f+1024+((b|11)<<3)+4>>2]|0;g=oe(j|0,s|0,l|0,r|0)|0;m=D;r=Pd(l|0,r|0,1)|0;r=Ed(r&-2|0,D&1|0,j|0,0)|0;r=oe(g|0,m|0,r|0,D|0)|0;m=D;g=Rd(r^o|0,m^v|0,24)|0;l=D;v=Pd(r^o|0,m^v|0,40)|0;l=D|l;o=oe(v|g|0,l|0,x|0,t|0)|0;q=D;t=Pd(x|0,t|0,1)|0;t=Ed(g|0,0,t&-2|0,D&1|0)|0;t=oe(o|0,q|0,t|0,D|0)|0;q=D;c[f+1024+((b|3)<<3)>>2]=t;c[f+1024+((b|3)<<3)+4>>2]=q;o=Rd(t^j|0,q^s|0,16)|0;x=D;s=Pd(t^j|0,q^s|0,48)|0;x=D|x;q=oe(s|o|0,x|0,r|0,m|0)|0;j=D;m=Pd(r|0,m|0,1)|0;m=Ed(o|0,0,m&-2|0,D&1|0)|0;m=oe(q|0,j|0,m|0,D|0)|0;j=D;q=Rd(m^(v|g)|0,j^l|0,63)|0;r=D;l=Pd(m^(v|g)|0,j^l|0,1)|0;r=D|r;c[f+1024+((b|7)<<3)>>2]=l|q;c[f+1024+((b|7)<<3)+4>>2]=r;g=c[f+1024+(b<<3)>>2]|0;v=c[f+1024+(b<<3)+4>>2]|0;t=c[f+1024+((b|5)<<3)>>2]|0;u=c[f+1024+((b|5)<<3)+4>>2]|0;p=oe(t|0,u|0,g|0,v|0)|0;y=D;v=Pd(g|0,v|0,1)|0;v=Ed(v&-2|0,D&1|0,t|0,0)|0;v=oe(p|0,y|0,v|0,D|0)|0;y=D;p=oe(y^x|0,v^(s|o)|0,n|0,k|0)|0;g=D;k=Pd(n|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,y^x|0,0)|0;k=oe(p|0,g|0,k|0,D|0)|0;g=D;p=Rd(k^t|0,g^u|0,24)|0;n=D;u=Pd(k^t|0,g^u|0,40)|0;n=D|n;t=oe(u|p|0,n|0,v|0,y|0)|0;w=D;z=Pd(v|0,y|0,1)|0;z=Ed(p|0,0,z&-2|0,D&1|0)|0;z=oe(t|0,w|0,z|0,D|0)|0;w=D;c[f+1024+(b<<3)>>2]=z;c[f+1024+(b<<3)+4>>2]=w;t=Rd(z^(y^x)|0,w^(v^(s|o))|0,16)|0;h=D;o=Pd(z^(y^x)|0,w^(v^(s|o))|0,48)|0;h=D|h;c[f+1024+((b|15)<<3)>>2]=o|t;c[f+1024+((b|15)<<3)+4>>2]=h;h=oe(o|t|0,h|0,k|0,g|0)|0;o=D;g=Pd(k|0,g|0,1)|0;g=Ed(t|0,0,g&-2|0,D&1|0)|0;g=oe(h|0,o|0,g|0,D|0)|0;o=D;c[f+1024+((b|10)<<3)>>2]=g;c[f+1024+((b|10)<<3)+4>>2]=o;h=Rd(g^(u|p)|0,o^n|0,63)|0;t=D;n=Pd(g^(u|p)|0,o^n|0,1)|0;c[f+1024+((b|5)<<3)>>2]=n|h;c[f+1024+((b|5)<<3)+4>>2]=D|t;t=c[f+1024+((b|1)<<3)>>2]|0;h=c[f+1024+((b|1)<<3)+4>>2]|0;n=c[f+1024+((b|6)<<3)>>2]|0;o=c[f+1024+((b|6)<<3)+4>>2]|0;p=oe(n|0,o|0,t|0,h|0)|0;u=D;h=Pd(t|0,h|0,1)|0;h=Ed(h&-2|0,D&1|0,n|0,0)|0;h=oe(p|0,u|0,h|0,D|0)|0;u=D;p=h^c[f+1024+((b|12)<<3)>>2];t=u^c[f+1024+((b|12)<<3)+4>>2];g=oe(t|0,p|0,m|0,j|0)|0;k=D;j=Pd(m|0,j|0,1)|0;j=Ed(j&-2|0,D&1|0,t|0,0)|0;j=oe(g|0,k|0,j|0,D|0)|0;k=D;g=Rd(j^n|0,k^o|0,24)|0;m=D;o=Pd(j^n|0,k^o|0,40)|0;m=D|m;n=oe(o|g|0,m|0,h|0,u|0)|0;s=D;u=Pd(h|0,u|0,1)|0;u=Ed(g|0,0,u&-2|0,D&1|0)|0;u=oe(n|0,s|0,u|0,D|0)|0;s=D;c[f+1024+((b|1)<<3)>>2]=u;c[f+1024+((b|1)<<3)+4>>2]=s;n=Rd(u^t|0,s^p|0,16)|0;h=D;p=Pd(u^t|0,s^p|0,48)|0;h=D|h;c[f+1024+((b|12)<<3)>>2]=p|n;c[f+1024+((b|12)<<3)+4>>2]=h;h=oe(p|n|0,h|0,j|0,k|0)|0;p=D;k=Pd(j|0,k|0,1)|0;k=Ed(n|0,0,k&-2|0,D&1|0)|0;k=oe(h|0,p|0,k|0,D|0)|0;p=D;c[f+1024+((b|11)<<3)>>2]=k;c[f+1024+((b|11)<<3)+4>>2]=p;h=Rd(k^(o|g)|0,p^m|0,63)|0;n=D;m=Pd(k^(o|g)|0,p^m|0,1)|0;c[f+1024+((b|6)<<3)>>2]=m|h;c[f+1024+((b|6)<<3)+4>>2]=D|n;n=c[f+1024+((b|2)<<3)>>2]|0;h=c[f+1024+((b|2)<<3)+4>>2]|0;m=oe(l|q|0,r|0,n|0,h|0)|0;p=D;h=Pd(n|0,h|0,1)|0;h=Ed(h&-2|0,D&1|0,l|q|0,0)|0;h=oe(m|0,p|0,h|0,D|0)|0;p=D;m=h^c[f+1024+((b|13)<<3)>>2];n=p^c[f+1024+((b|13)<<3)+4>>2];g=c[f+1024+((b|8)<<3)>>2]|0;o=c[f+1024+((b|8)<<3)+4>>2]|0;k=oe(n|0,m|0,g|0,o|0)|0;j=D;o=Pd(g|0,o|0,1)|0;o=Ed(o&-2|0,D&1|0,n|0,0)|0;o=oe(k|0,j|0,o|0,D|0)|0;j=D;k=Rd(o^(l|q)|0,j^r|0,24)|0;g=D;r=Pd(o^(l|q)|0,j^r|0,40)|0;g=D|g;q=oe(r|k|0,g|0,h|0,p|0)|0;l=D;p=Pd(h|0,p|0,1)|0;p=Ed(k|0,0,p&-2|0,D&1|0)|0;p=oe(q|0,l|0,p|0,D|0)|0;l=D;c[f+1024+((b|2)<<3)>>2]=p;c[f+1024+((b|2)<<3)+4>>2]=l;q=Rd(p^n|0,l^m|0,16)|0;h=D;m=Pd(p^n|0,l^m|0,48)|0;h=D|h;c[f+1024+((b|13)<<3)>>2]=m|q;c[f+1024+((b|13)<<3)+4>>2]=h;h=oe(m|q|0,h|0,o|0,j|0)|0;m=D;j=Pd(o|0,j|0,1)|0;j=Ed(q|0,0,j&-2|0,D&1|0)|0;j=oe(h|0,m|0,j|0,D|0)|0;m=D;c[f+1024+((b|8)<<3)>>2]=j;c[f+1024+((b|8)<<3)+4>>2]=m;h=Rd(j^(r|k)|0,m^g|0,63)|0;q=D;g=Pd(j^(r|k)|0,m^g|0,1)|0;c[f+1024+((b|7)<<3)>>2]=g|h;c[f+1024+((b|7)<<3)+4>>2]=D|q;q=c[f+1024+((b|3)<<3)>>2]|0;h=c[f+1024+((b|3)<<3)+4>>2]|0;g=c[f+1024+((b|4)<<3)>>2]|0;m=c[f+1024+((b|4)<<3)+4>>2]|0;k=oe(g|0,m|0,q|0,h|0)|0;r=D;h=Pd(q|0,h|0,1)|0;h=Ed(h&-2|0,D&1|0,g|0,0)|0;h=oe(k|0,r|0,h|0,D|0)|0;r=D;k=h^c[f+1024+((b|14)<<3)>>2];q=r^c[f+1024+((b|14)<<3)+4>>2];j=c[f+1024+((b|9)<<3)>>2]|0;o=c[f+1024+((b|9)<<3)+4>>2]|0;l=oe(q|0,k|0,j|0,o|0)|0;n=D;o=Pd(j|0,o|0,1)|0;o=Ed(o&-2|0,D&1|0,q|0,0)|0;o=oe(l|0,n|0,o|0,D|0)|0;n=D;l=Rd(o^g|0,n^m|0,24)|0;j=D;m=Pd(o^g|0,n^m|0,40)|0;j=D|j;g=oe(m|l|0,j|0,h|0,r|0)|0;p=D;r=Pd(h|0,r|0,1)|0;r=Ed(l|0,0,r&-2|0,D&1|0)|0;r=oe(g|0,p|0,r|0,D|0)|0;p=D;c[f+1024+((b|3)<<3)>>2]=r;c[f+1024+((b|3)<<3)+4>>2]=p;g=Rd(r^q|0,p^k|0,16)|0;h=D;k=Pd(r^q|0,p^k|0,48)|0;h=D|h;c[f+1024+((b|14)<<3)>>2]=k|g;c[f+1024+((b|14)<<3)+4>>2]=h;h=oe(k|g|0,h|0,o|0,n|0)|0;k=D;n=Pd(o|0,n|0,1)|0;n=Ed(g|0,0,n&-2|0,D&1|0)|0;n=oe(h|0,k|0,n|0,D|0)|0;k=D;c[f+1024+((b|9)<<3)>>2]=n;c[f+1024+((b|9)<<3)+4>>2]=k;h=Rd(n^(m|l)|0,k^j|0,63)|0;g=D;j=Pd(n^(m|l)|0,k^j|0,1)|0;c[f+1024+((b|4)<<3)>>2]=j|h;c[f+1024+((b|4)<<3)+4>>2]=D|g;a=a+1|0}while((a|0)!=8);a=0;do{z=a<<1;k=c[f+1024+(z<<3)>>2]|0;w=c[f+1024+(z<<3)+4>>2]|0;o=f+1024+(z+32<<3)|0;r=c[o>>2]|0;o=c[o+4>>2]|0;l=oe(r|0,o|0,k|0,w|0)|0;h=D;w=Pd(k|0,w|0,1)|0;w=Ed(w&-2|0,D&1|0,r|0,0)|0;w=oe(l|0,h|0,w|0,D|0)|0;h=D;l=f+1024+(z+96<<3)|0;k=w^c[l>>2];l=h^c[l+4>>2];n=f+1024+(z+64<<3)|0;p=c[n>>2]|0;n=c[n+4>>2]|0;x=oe(l|0,k|0,p|0,n|0)|0;t=D;n=Pd(p|0,n|0,1)|0;n=Ed(n&-2|0,D&1|0,l|0,0)|0;n=oe(x|0,t|0,n|0,D|0)|0;t=D;x=Rd(n^r|0,t^o|0,24)|0;p=D;o=Pd(n^r|0,t^o|0,40)|0;p=D|p;r=oe(o|x|0,p|0,w|0,h|0)|0;u=D;h=Pd(w|0,h|0,1)|0;h=Ed(x|0,0,h&-2|0,D&1|0)|0;h=oe(r|0,u|0,h|0,D|0)|0;u=D;c[f+1024+(z<<3)>>2]=h;c[f+1024+(z<<3)+4>>2]=u;r=Rd(h^l|0,u^k|0,16)|0;w=D;k=Pd(h^l|0,u^k|0,48)|0;w=D|w;u=f+1024+(z+96<<3)|0;c[u>>2]=k|r;c[u+4>>2]=w;w=oe(k|r|0,w|0,n|0,t|0)|0;k=D;t=Pd(n|0,t|0,1)|0;t=Ed(r|0,0,t&-2|0,D&1|0)|0;t=oe(w|0,k|0,t|0,D|0)|0;k=D;w=f+1024+(z+64<<3)|0;c[w>>2]=t;c[w+4>>2]=k;w=Rd(t^(o|x)|0,k^p|0,63)|0;r=D;p=Pd(t^(o|x)|0,k^p|0,1)|0;k=f+1024+(z+32<<3)|0;c[k>>2]=p|w;c[k+4>>2]=D|r;k=c[f+1024+((z|1)<<3)>>2]|0;r=c[f+1024+((z|1)<<3)+4>>2]|0;w=f+1024+(z+33<<3)|0;p=c[w>>2]|0;w=c[w+4>>2]|0;x=oe(p|0,w|0,k|0,r|0)|0;o=D;r=Pd(k|0,r|0,1)|0;r=Ed(r&-2|0,D&1|0,p|0,0)|0;r=oe(x|0,o|0,r|0,D|0)|0;o=D;x=f+1024+(z+97<<3)|0;k=r^c[x>>2];x=o^c[x+4>>2];t=f+1024+(z+65<<3)|0;n=c[t>>2]|0;t=c[t+4>>2]|0;u=oe(x|0,k|0,n|0,t|0)|0;l=D;t=Pd(n|0,t|0,1)|0;t=Ed(t&-2|0,D&1|0,x|0,0)|0;t=oe(u|0,l|0,t|0,D|0)|0;l=D;u=Rd(t^p|0,l^w|0,24)|0;n=D;w=Pd(t^p|0,l^w|0,40)|0;n=D|n;p=oe(w|u|0,n|0,r|0,o|0)|0;h=D;o=Pd(r|0,o|0,1)|0;o=Ed(u|0,0,o&-2|0,D&1|0)|0;o=oe(p|0,h|0,o|0,D|0)|0;h=D;c[f+1024+((z|1)<<3)>>2]=o;c[f+1024+((z|1)<<3)+4>>2]=h;p=Rd(o^x|0,h^k|0,16)|0;r=D;k=Pd(o^x|0,h^k|0,48)|0;r=D|r;h=f+1024+(z+97<<3)|0;c[h>>2]=k|p;c[h+4>>2]=r;r=oe(k|p|0,r|0,t|0,l|0)|0;k=D;l=Pd(t|0,l|0,1)|0;l=Ed(p|0,0,l&-2|0,D&1|0)|0;l=oe(r|0,k|0,l|0,D|0)|0;k=D;r=f+1024+(z+65<<3)|0;c[r>>2]=l;c[r+4>>2]=k;r=Rd(l^(w|u)|0,k^n|0,63)|0;p=D;n=Pd(l^(w|u)|0,k^n|0,1)|0;k=f+1024+(z+33<<3)|0;c[k>>2]=n|r;c[k+4>>2]=D|p;k=f+1024+(z+16<<3)|0;p=c[k>>2]|0;k=c[k+4>>2]|0;r=f+1024+(z+48<<3)|0;n=c[r>>2]|0;r=c[r+4>>2]|0;u=oe(n|0,r|0,p|0,k|0)|0;w=D;k=Pd(p|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,n|0,0)|0;k=oe(u|0,w|0,k|0,D|0)|0;w=D;u=f+1024+(z+112<<3)|0;p=k^c[u>>2];u=w^c[u+4>>2];l=f+1024+(z+80<<3)|0;t=c[l>>2]|0;l=c[l+4>>2]|0;h=oe(u|0,p|0,t|0,l|0)|0;x=D;l=Pd(t|0,l|0,1)|0;l=Ed(l&-2|0,D&1|0,u|0,0)|0;l=oe(h|0,x|0,l|0,D|0)|0;x=D;h=Rd(l^n|0,x^r|0,24)|0;t=D;r=Pd(l^n|0,x^r|0,40)|0;t=D|t;n=oe(r|h|0,t|0,k|0,w|0)|0;o=D;w=Pd(k|0,w|0,1)|0;w=Ed(h|0,0,w&-2|0,D&1|0)|0;w=oe(n|0,o|0,w|0,D|0)|0;o=D;n=f+1024+(z+16<<3)|0;c[n>>2]=w;c[n+4>>2]=o;n=Rd(w^u|0,o^p|0,16)|0;k=D;p=Pd(w^u|0,o^p|0,48)|0;k=D|k;o=f+1024+(z+112<<3)|0;c[o>>2]=p|n;c[o+4>>2]=k;k=oe(p|n|0,k|0,l|0,x|0)|0;p=D;x=Pd(l|0,x|0,1)|0;x=Ed(n|0,0,x&-2|0,D&1|0)|0;x=oe(k|0,p|0,x|0,D|0)|0;p=D;k=Rd(x^(r|h)|0,p^t|0,63)|0;n=D;t=Pd(x^(r|h)|0,p^t|0,1)|0;h=f+1024+(z+48<<3)|0;c[h>>2]=t|k;c[h+4>>2]=D|n;h=f+1024+(z+17<<3)|0;n=c[h>>2]|0;h=c[h+4>>2]|0;k=f+1024+(z+49<<3)|0;t=c[k>>2]|0;k=c[k+4>>2]|0;r=oe(t|0,k|0,n|0,h|0)|0;l=D;h=Pd(n|0,h|0,1)|0;h=Ed(h&-2|0,D&1|0,t|0,0)|0;h=oe(r|0,l|0,h|0,D|0)|0;l=D;r=f+1024+(z+113<<3)|0;n=h^c[r>>2];r=l^c[r+4>>2];o=f+1024+(z+81<<3)|0;u=c[o>>2]|0;o=c[o+4>>2]|0;w=oe(r|0,n|0,u|0,o|0)|0;q=D;o=Pd(u|0,o|0,1)|0;o=Ed(o&-2|0,D&1|0,r|0,0)|0;o=oe(w|0,q|0,o|0,D|0)|0;q=D;w=Rd(o^t|0,q^k|0,24)|0;u=D;k=Pd(o^t|0,q^k|0,40)|0;u=D|u;t=oe(k|w|0,u|0,h|0,l|0)|0;v=D;l=Pd(h|0,l|0,1)|0;l=Ed(w|0,0,l&-2|0,D&1|0)|0;l=oe(t|0,v|0,l|0,D|0)|0;v=D;t=f+1024+(z+17<<3)|0;c[t>>2]=l;c[t+4>>2]=v;t=Rd(l^r|0,v^n|0,16)|0;h=D;n=Pd(l^r|0,v^n|0,48)|0;h=D|h;v=oe(n|t|0,h|0,o|0,q|0)|0;r=D;q=Pd(o|0,q|0,1)|0;q=Ed(t|0,0,q&-2|0,D&1|0)|0;q=oe(v|0,r|0,q|0,D|0)|0;r=D;v=Rd(q^(k|w)|0,r^u|0,63)|0;o=D;u=Pd(q^(k|w)|0,r^u|0,1)|0;o=D|o;w=f+1024+(z+49<<3)|0;c[w>>2]=u|v;c[w+4>>2]=o;w=c[f+1024+(z<<3)>>2]|0;k=c[f+1024+(z<<3)+4>>2]|0;l=f+1024+(z+33<<3)|0;s=c[l>>2]|0;l=c[l+4>>2]|0;m=oe(s|0,l|0,w|0,k|0)|0;g=D;k=Pd(w|0,k|0,1)|0;k=Ed(k&-2|0,D&1|0,s|0,0)|0;k=oe(m|0,g|0,k|0,D|0)|0;g=D;m=oe(g^h|0,k^(n|t)|0,x|0,p|0)|0;w=D;p=Pd(x|0,p|0,1)|0;p=Ed(p&-2|0,D&1|0,g^h|0,0)|0;p=oe(m|0,w|0,p|0,D|0)|0;w=D;m=Rd(p^s|0,w^l|0,24)|0;x=D;l=Pd(p^s|0,w^l|0,40)|0;x=D|x;s=oe(l|m|0,x|0,k|0,g|0)|0;j=D;b=Pd(k|0,g|0,1)|0;b=Ed(m|0,0,b&-2|0,D&1|0)|0;b=oe(s|0,j|0,b|0,D|0)|0;j=D;c[f+1024+(z<<3)>>2]=b;c[f+1024+(z<<3)+4>>2]=j;s=Rd(b^(g^h)|0,j^(k^(n|t))|0,16)|0;y=D;t=Pd(b^(g^h)|0,j^(k^(n|t))|0,48)|0;y=D|y;n=f+1024+(z+113<<3)|0;c[n>>2]=t|s;c[n+4>>2]=y;y=oe(t|s|0,y|0,p|0,w|0)|0;t=D;w=Pd(p|0,w|0,1)|0;w=Ed(s|0,0,w&-2|0,D&1|0)|0;w=oe(y|0,t|0,w|0,D|0)|0;t=D;y=f+1024+(z+80<<3)|0;c[y>>2]=w;c[y+4>>2]=t;y=Rd(w^(l|m)|0,t^x|0,63)|0;s=D;x=Pd(w^(l|m)|0,t^x|0,1)|0;t=f+1024+(z+33<<3)|0;c[t>>2]=x|y;c[t+4>>2]=D|s;t=c[f+1024+((z|1)<<3)>>2]|0;s=c[f+1024+((z|1)<<3)+4>>2]|0;y=f+1024+(z+48<<3)|0;x=c[y>>2]|0;y=c[y+4>>2]|0;m=oe(x|0,y|0,t|0,s|0)|0;l=D;s=Pd(t|0,s|0,1)|0;s=Ed(s&-2|0,D&1|0,x|0,0)|0;s=oe(m|0,l|0,s|0,D|0)|0;l=D;m=f+1024+(z+96<<3)|0;t=s^c[m>>2];m=l^c[m+4>>2];w=oe(m|0,t|0,q|0,r|0)|0;p=D;r=Pd(q|0,r|0,1)|0;r=Ed(r&-2|0,D&1|0,m|0,0)|0;r=oe(w|0,p|0,r|0,D|0)|0;p=D;w=Rd(r^x|0,p^y|0,24)|0;q=D;y=Pd(r^x|0,p^y|0,40)|0;q=D|q;x=oe(y|w|0,q|0,s|0,l|0)|0;n=D;l=Pd(s|0,l|0,1)|0;l=Ed(w|0,0,l&-2|0,D&1|0)|0;l=oe(x|0,n|0,l|0,D|0)|0;n=D;c[f+1024+((z|1)<<3)>>2]=l;c[f+1024+((z|1)<<3)+4>>2]=n;x=Rd(l^m|0,n^t|0,16)|0;s=D;t=Pd(l^m|0,n^t|0,48)|0;s=D|s;n=f+1024+(z+96<<3)|0;c[n>>2]=t|x;c[n+4>>2]=s;s=oe(t|x|0,s|0,r|0,p|0)|0;t=D;p=Pd(r|0,p|0,1)|0;p=Ed(x|0,0,p&-2|0,D&1|0)|0;p=oe(s|0,t|0,p|0,D|0)|0;t=D;s=f+1024+(z+81<<3)|0;c[s>>2]=p;c[s+4>>2]=t;s=Rd(p^(y|w)|0,t^q|0,63)|0;x=D;q=Pd(p^(y|w)|0,t^q|0,1)|0;t=f+1024+(z+48<<3)|0;c[t>>2]=q|s;c[t+4>>2]=D|x;t=f+1024+(z+16<<3)|0;x=c[t>>2]|0;t=c[t+4>>2]|0;s=oe(u|v|0,o|0,x|0,t|0)|0;q=D;t=Pd(x|0,t|0,1)|0;t=Ed(t&-2|0,D&1|0,u|v|0,0)|0;t=oe(s|0,q|0,t|0,D|0)|0;q=D;s=f+1024+(z+97<<3)|0;x=t^c[s>>2];s=q^c[s+4>>2];w=f+1024+(z+64<<3)|0;y=c[w>>2]|0;w=c[w+4>>2]|0;p=oe(s|0,x|0,y|0,w|0)|0;r=D;w=Pd(y|0,w|0,1)|0;w=Ed(w&-2|0,D&1|0,s|0,0)|0;w=oe(p|0,r|0,w|0,D|0)|0;r=D;p=Rd(w^(u|v)|0,r^o|0,24)|0;y=D;o=Pd(w^(u|v)|0,r^o|0,40)|0;y=D|y;v=oe(o|p|0,y|0,t|0,q|0)|0;u=D;q=Pd(t|0,q|0,1)|0;q=Ed(p|0,0,q&-2|0,D&1|0)|0;q=oe(v|0,u|0,q|0,D|0)|0;u=D;v=f+1024+(z+16<<3)|0;c[v>>2]=q;c[v+4>>2]=u;v=Rd(q^s|0,u^x|0,16)|0;t=D;x=Pd(q^s|0,u^x|0,48)|0;t=D|t;u=f+1024+(z+97<<3)|0;c[u>>2]=x|v;c[u+4>>2]=t;t=oe(x|v|0,t|0,w|0,r|0)|0;x=D;r=Pd(w|0,r|0,1)|0;r=Ed(v|0,0,r&-2|0,D&1|0)|0;r=oe(t|0,x|0,r|0,D|0)|0;x=D;t=f+1024+(z+64<<3)|0;c[t>>2]=r;c[t+4>>2]=x;t=Rd(r^(o|p)|0,x^y|0,63)|0;v=D;y=Pd(r^(o|p)|0,x^y|0,1)|0;x=f+1024+(z+49<<3)|0;c[x>>2]=y|t;c[x+4>>2]=D|v;x=f+1024+(z+17<<3)|0;v=c[x>>2]|0;x=c[x+4>>2]|0;t=f+1024+(z+32<<3)|0;y=c[t>>2]|0;t=c[t+4>>2]|0;p=oe(y|0,t|0,v|0,x|0)|0;o=D;x=Pd(v|0,x|0,1)|0;x=Ed(x&-2|0,D&1|0,y|0,0)|0;x=oe(p|0,o|0,x|0,D|0)|0;o=D;p=f+1024+(z+112<<3)|0;v=x^c[p>>2];p=o^c[p+4>>2];r=f+1024+(z+65<<3)|0;w=c[r>>2]|0;r=c[r+4>>2]|0;u=oe(p|0,v|0,w|0,r|0)|0;s=D;r=Pd(w|0,r|0,1)|0;r=Ed(r&-2|0,D&1|0,p|0,0)|0;r=oe(u|0,s|0,r|0,D|0)|0;s=D;u=Rd(r^y|0,s^t|0,24)|0;w=D;t=Pd(r^y|0,s^t|0,40)|0;w=D|w;y=oe(t|u|0,w|0,x|0,o|0)|0;q=D;o=Pd(x|0,o|0,1)|0;o=Ed(u|0,0,o&-2|0,D&1|0)|0;o=oe(y|0,q|0,o|0,D|0)|0;q=D;y=f+1024+(z+17<<3)|0;c[y>>2]=o;c[y+4>>2]=q;y=Rd(o^p|0,q^v|0,16)|0;x=D;v=Pd(o^p|0,q^v|0,48)|0;x=D|x;q=f+1024+(z+112<<3)|0;c[q>>2]=v|y;c[q+4>>2]=x;x=oe(v|y|0,x|0,r|0,s|0)|0;v=D;s=Pd(r|0,s|0,1)|0;s=Ed(y|0,0,s&-2|0,D&1|0)|0;s=oe(x|0,v|0,s|0,D|0)|0;v=D;x=f+1024+(z+65<<3)|0;c[x>>2]=s;c[x+4>>2]=v;x=Rd(s^(t|u)|0,v^w|0,63)|0;y=D;w=Pd(s^(t|u)|0,v^w|0,1)|0;z=f+1024+(z+32<<3)|0;c[z>>2]=w|x;c[z+4>>2]=D|y;a=a+1|0}while((a|0)!=8);ef(d,f);gd(d,f+1024|0);i=e;return}function na(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0;I=i;s=i=i+63&-64;i=i+16|0;do if(a>>>0<245){r=a>>>0<11?16:a+11&-8;q=c[8491]|0;if(q>>>(r>>>3)&3|0){b=34004+((q>>>(r>>>3)&1^1)+(r>>>3)<<1<<2)|0;a=c[b+8>>2]|0;d=c[a+8>>2]|0;do if((b|0)!=(d|0)){if(d>>>0<(c[8495]|0)>>>0)ba();if((c[d+12>>2]|0)==(a|0)){c[d+12>>2]=b;c[b+8>>2]=d;break}else ba()}else c[8491]=q&~(1<<(q>>>(r>>>3)&1^1)+(r>>>3));while(0);H=(q>>>(r>>>3)&1^1)+(r>>>3)<<3;c[a+4>>2]=H|3;c[a+H+4>>2]=c[a+H+4>>2]|1;H=a+8|0;i=I;return H|0}p=c[8493]|0;if(r>>>0>p>>>0){if(q>>>(r>>>3)|0){b=q>>>(r>>>3)<<(r>>>3)&(2<<(r>>>3)|0-(2<<(r>>>3)));e=((b&0-b)+-1|0)>>>(((b&0-b)+-1|0)>>>12&16);d=e>>>(e>>>5&8)>>>(e>>>(e>>>5&8)>>>2&4);d=(e>>>5&8|((b&0-b)+-1|0)>>>12&16|e>>>(e>>>5&8)>>>2&4|d>>>1&2|d>>>(d>>>1&2)>>>1&1)+(d>>>(d>>>1&2)>>>(d>>>(d>>>1&2)>>>1&1))|0;e=c[34004+(d<<1<<2)+8>>2]|0;b=c[e+8>>2]|0;do if((34004+(d<<1<<2)|0)!=(b|0)){if(b>>>0<(c[8495]|0)>>>0)ba();if((c[b+12>>2]|0)==(e|0)){c[b+12>>2]=34004+(d<<1<<2);c[34004+(d<<1<<2)+8>>2]=b;f=q;break}else ba()}else{c[8491]=q&~(1<<d);f=q&~(1<<d)}while(0);c[e+4>>2]=r|3;c[e+r+4>>2]=(d<<3)-r|1;c[e+r+((d<<3)-r)>>2]=(d<<3)-r;if(p|0){a=c[8496]|0;if(f&1<<(p>>>3)){b=c[34004+(p>>>3<<1<<2)+8>>2]|0;if(b>>>0<(c[8495]|0)>>>0)ba();else{h=b;j=34004+(p>>>3<<1<<2)+8|0}}else{c[8491]=f|1<<(p>>>3);h=34004+(p>>>3<<1<<2)|0;j=34004+(p>>>3<<1<<2)+8|0}c[j>>2]=a;c[h+12>>2]=a;c[a+8>>2]=h;c[a+12>>2]=34004+(p>>>3<<1<<2)}c[8493]=(d<<3)-r;c[8496]=e+r;H=e+8|0;i=I;return H|0}l=c[8492]|0;if(l){a=((l&0-l)+-1|0)>>>(((l&0-l)+-1|0)>>>12&16);k=a>>>(a>>>5&8)>>>(a>>>(a>>>5&8)>>>2&4);k=c[34268+((a>>>5&8|((l&0-l)+-1|0)>>>12&16|a>>>(a>>>5&8)>>>2&4|k>>>1&2|k>>>(k>>>1&2)>>>1&1)+(k>>>(k>>>1&2)>>>(k>>>(k>>>1&2)>>>1&1))<<2)>>2]|0;a=k;j=k;k=(c[k+4>>2]&-8)-r|0;while(1){b=c[a+16>>2]|0;if(!b){b=c[a+20>>2]|0;if(!b)break}H=(c[b+4>>2]&-8)-r|0;G=H>>>0<k>>>0;a=b;j=G?b:j;k=G?H:k}f=c[8495]|0;if(j>>>0<f>>>0)ba();h=j+r|0;if(j>>>0>=h>>>0)ba();g=c[j+24>>2]|0;b=c[j+12>>2]|0;do if((b|0)==(j|0)){a=j+20|0;b=c[a>>2]|0;if(!b){a=j+16|0;b=c[a>>2]|0;if(!b){m=0;break}}while(1){d=b+20|0;e=c[d>>2]|0;if(e|0){b=e;a=d;continue}d=b+16|0;e=c[d>>2]|0;if(!e)break;else{b=e;a=d}}if(a>>>0<f>>>0)ba();else{c[a>>2]=0;m=b;break}}else{a=c[j+8>>2]|0;if(a>>>0<f>>>0)ba();if((c[a+12>>2]|0)!=(j|0))ba();if((c[b+8>>2]|0)==(j|0)){c[a+12>>2]=b;c[b+8>>2]=a;m=b;break}else ba()}while(0);do if(g|0){b=c[j+28>>2]|0;if((j|0)==(c[34268+(b<<2)>>2]|0)){c[34268+(b<<2)>>2]=m;if(!m){c[8492]=l&~(1<<b);break}}else{if(g>>>0<(c[8495]|0)>>>0)ba();if((c[g+16>>2]|0)==(j|0))c[g+16>>2]=m;else c[g+20>>2]=m;if(!m)break}a=c[8495]|0;if(m>>>0<a>>>0)ba();c[m+24>>2]=g;b=c[j+16>>2]|0;do if(b|0)if(b>>>0<a>>>0)ba();else{c[m+16>>2]=b;c[b+24>>2]=m;break}while(0);b=c[j+20>>2]|0;if(b|0)if(b>>>0<(c[8495]|0)>>>0)ba();else{c[m+20>>2]=b;c[b+24>>2]=m;break}}while(0);if(k>>>0<16){H=k+r|0;c[j+4>>2]=H|3;H=j+H+4|0;c[H>>2]=c[H>>2]|1}else{c[j+4>>2]=r|3;c[h+4>>2]=k|1;c[h+k>>2]=k;if(p|0){a=c[8496]|0;if(q&1<<(p>>>3)){b=c[34004+(p>>>3<<1<<2)+8>>2]|0;if(b>>>0<(c[8495]|0)>>>0)ba();else{n=b;o=34004+(p>>>3<<1<<2)+8|0}}else{c[8491]=q|1<<(p>>>3);n=34004+(p>>>3<<1<<2)|0;o=34004+(p>>>3<<1<<2)+8|0}c[o>>2]=a;c[n+12>>2]=a;c[a+8>>2]=n;c[a+12>>2]=34004+(p>>>3<<1<<2)}c[8493]=k;c[8496]=h}H=j+8|0;i=I;return H|0}}}else if(a>>>0<=4294967231){r=a+11&-8;l=c[8492]|0;if(l){if((a+11|0)>>>8)if(r>>>0>16777215)k=31;else{k=(a+11|0)>>>8<<((((a+11|0)>>>8)+1048320|0)>>>16&8);k=14-((k+520192|0)>>>16&4|(((a+11|0)>>>8)+1048320|0)>>>16&8|((k<<((k+520192|0)>>>16&4))+245760|0)>>>16&2)+(k<<((k+520192|0)>>>16&4)<<(((k<<((k+520192|0)>>>16&4))+245760|0)>>>16&2)>>>15)|0;k=r>>>(k+7|0)&1|k<<1}else k=0;a=c[34268+(k<<2)>>2]|0;a:do if(!a){a=0;e=0;d=0-r|0;A=86}else{e=0;d=0-r|0;j=r<<((k|0)==31?0:25-(k>>>1)|0);h=0;while(1){f=(c[a+4>>2]&-8)-r|0;if(f>>>0<d>>>0)if(!f){h=a;d=0;e=a;A=90;break a}else{e=a;d=f}f=c[a+20>>2]|0;a=c[a+16+(j>>>31<<2)>>2]|0;h=(f|0)==0|(f|0)==(a|0)?h:f;f=(a|0)==0;if(f){a=h;A=86;break}else j=j<<(f&1^1)}}while(0);if((A|0)==86){if((a|0)==0&(e|0)==0){a=2<<k;if(!(l&(a|0-a)))break;n=(l&(a|0-a)&0-(l&(a|0-a)))+-1|0;o=n>>>(n>>>12&16)>>>(n>>>(n>>>12&16)>>>5&8);a=o>>>(o>>>2&4)>>>(o>>>(o>>>2&4)>>>1&2);a=c[34268+((n>>>(n>>>12&16)>>>5&8|n>>>12&16|o>>>2&4|o>>>(o>>>2&4)>>>1&2|a>>>1&1)+(a>>>(a>>>1&1))<<2)>>2]|0}if(!a){k=e;j=d}else{h=e;e=a;A=90}}if((A|0)==90)while(1){A=0;f=(c[e+4>>2]&-8)-r|0;a=f>>>0<d>>>0;d=a?f:d;a=a?e:h;f=c[e+16>>2]|0;if(f|0){h=a;e=f;A=90;continue}e=c[e+20>>2]|0;if(!e){k=a;j=d;break}else{h=a;A=90}}if((k|0)!=0?j>>>0<((c[8493]|0)-r|0)>>>0:0){f=c[8495]|0;if(k>>>0<f>>>0)ba();h=k+r|0;if(k>>>0>=h>>>0)ba();g=c[k+24>>2]|0;b=c[k+12>>2]|0;do if((b|0)==(k|0)){a=k+20|0;b=c[a>>2]|0;if(!b){a=k+16|0;b=c[a>>2]|0;if(!b){p=0;break}}while(1){d=b+20|0;e=c[d>>2]|0;if(e|0){b=e;a=d;continue}d=b+16|0;e=c[d>>2]|0;if(!e)break;else{b=e;a=d}}if(a>>>0<f>>>0)ba();else{c[a>>2]=0;p=b;break}}else{a=c[k+8>>2]|0;if(a>>>0<f>>>0)ba();if((c[a+12>>2]|0)!=(k|0))ba();if((c[b+8>>2]|0)==(k|0)){c[a+12>>2]=b;c[b+8>>2]=a;p=b;break}else ba()}while(0);do if(g){b=c[k+28>>2]|0;if((k|0)==(c[34268+(b<<2)>>2]|0)){c[34268+(b<<2)>>2]=p;if(!p){c[8492]=l&~(1<<b);y=l&~(1<<b);break}}else{if(g>>>0<(c[8495]|0)>>>0)ba();if((c[g+16>>2]|0)==(k|0))c[g+16>>2]=p;else c[g+20>>2]=p;if(!p){y=l;break}}a=c[8495]|0;if(p>>>0<a>>>0)ba();c[p+24>>2]=g;b=c[k+16>>2]|0;do if(b|0)if(b>>>0<a>>>0)ba();else{c[p+16>>2]=b;c[b+24>>2]=p;break}while(0);b=c[k+20>>2]|0;if(b)if(b>>>0<(c[8495]|0)>>>0)ba();else{c[p+20>>2]=b;c[b+24>>2]=p;y=l;break}else y=l}else y=l;while(0);do if(j>>>0>=16){c[k+4>>2]=r|3;c[h+4>>2]=j|1;c[h+j>>2]=j;a=j>>>3;if(j>>>0<256){b=c[8491]|0;if(b&1<<a){b=c[34004+(a<<1<<2)+8>>2]|0;if(b>>>0<(c[8495]|0)>>>0)ba();else{q=b;v=34004+(a<<1<<2)+8|0}}else{c[8491]=b|1<<a;q=34004+(a<<1<<2)|0;v=34004+(a<<1<<2)+8|0}c[v>>2]=h;c[q+12>>2]=h;c[h+8>>2]=q;c[h+12>>2]=34004+(a<<1<<2);break}b=j>>>8;if(b)if(j>>>0>16777215)b=31;else{H=b<<((b+1048320|0)>>>16&8)<<(((b<<((b+1048320|0)>>>16&8))+520192|0)>>>16&4);b=14-(((b<<((b+1048320|0)>>>16&8))+520192|0)>>>16&4|(b+1048320|0)>>>16&8|(H+245760|0)>>>16&2)+(H<<((H+245760|0)>>>16&2)>>>15)|0;b=j>>>(b+7|0)&1|b<<1}else b=0;d=34268+(b<<2)|0;c[h+28>>2]=b;c[h+16+4>>2]=0;c[h+16>>2]=0;a=1<<b;if(!(y&a)){c[8492]=y|a;c[d>>2]=h;c[h+24>>2]=d;c[h+12>>2]=h;c[h+8>>2]=h;break}a=j<<((b|0)==31?0:25-(b>>>1)|0);e=c[d>>2]|0;while(1){if((c[e+4>>2]&-8|0)==(j|0)){A=148;break}d=e+16+(a>>>31<<2)|0;b=c[d>>2]|0;if(!b){A=145;break}else{a=a<<1;e=b}}if((A|0)==145)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[d>>2]=h;c[h+24>>2]=e;c[h+12>>2]=h;c[h+8>>2]=h;break}else if((A|0)==148){b=e+8|0;a=c[b>>2]|0;H=c[8495]|0;if(a>>>0>=H>>>0&e>>>0>=H>>>0){c[a+12>>2]=h;c[b>>2]=h;c[h+8>>2]=a;c[h+12>>2]=e;c[h+24>>2]=0;break}else ba()}}else{H=j+r|0;c[k+4>>2]=H|3;H=k+H+4|0;c[H>>2]=c[H>>2]|1}while(0);H=k+8|0;i=I;return H|0}}}else r=-1;while(0);d=c[8493]|0;if(d>>>0>=r>>>0){b=d-r|0;a=c[8496]|0;if(b>>>0>15){H=a+r|0;c[8496]=H;c[8493]=b;c[H+4>>2]=b|1;c[H+b>>2]=b;c[a+4>>2]=r|3}else{c[8493]=0;c[8496]=0;c[a+4>>2]=d|3;c[a+d+4>>2]=c[a+d+4>>2]|1}H=a+8|0;i=I;return H|0}f=c[8494]|0;if(f>>>0>r>>>0){F=f-r|0;c[8494]=F;H=c[8497]|0;G=H+r|0;c[8497]=G;c[G+4>>2]=F|1;c[H+4>>2]=r|3;H=H+8|0;i=I;return H|0}if(!(c[8609]|0)){c[8611]=4096;c[8610]=4096;c[8612]=-1;c[8613]=-1;c[8614]=0;c[8602]=0;c[s>>2]=s&-16^1431655768;c[8609]=s&-16^1431655768;a=4096}else a=c[8611]|0;h=r+48|0;j=r+47|0;l=a+j|0;k=0-a|0;if((l&k)>>>0<=r>>>0){H=0;i=I;return H|0}a=c[8601]|0;if(a|0?(y=c[8599]|0,(y+(l&k)|0)>>>0<=y>>>0?1:(y+(l&k)|0)>>>0>a>>>0):0){H=0;i=I;return H|0}b:do if(!(c[8602]&4)){e=c[8497]|0;c:do if(e){d=34412;while(1){a=c[d>>2]|0;if(a>>>0<=e>>>0?(t=d+4|0,(a+(c[t>>2]|0)|0)>>>0>e>>>0):0)break;a=c[d+8>>2]|0;if(!a){A=172;break c}else d=a}if((l-f&k)>>>0<2147483647){a=Pc(l-f&k|0)|0;if((a|0)==((c[d>>2]|0)+(c[t>>2]|0)|0)){if((a|0)!=(-1|0)){h=l-f&k;g=a;A=190;break b}}else{b=l-f&k;A=180}}}else A=172;while(0);do if(((A|0)==172?(g=Pc(0)|0,(g|0)!=(-1|0)):0)?(b=c[8610]|0,b=((b+-1&g|0)==0?0:(b+-1+g&0-b)-g|0)+(l&k)|0,u=c[8599]|0,b>>>0>r>>>0&b>>>0<2147483647):0){y=c[8601]|0;if(y|0?(b+u|0)>>>0<=u>>>0|(b+u|0)>>>0>y>>>0:0)break;a=Pc(b|0)|0;if((a|0)==(g|0)){h=b;A=190;break b}else A=180}while(0);d:do if((A|0)==180){d=0-b|0;do if(h>>>0>b>>>0&(b>>>0<2147483647&(a|0)!=(-1|0))?(w=c[8611]|0,w=j-b+w&0-w,w>>>0<2147483647):0)if((Pc(w|0)|0)==(-1|0)){Pc(d|0)|0;break d}else{b=w+b|0;break}while(0);if((a|0)!=(-1|0)){h=b;g=a;A=190;break b}}while(0);c[8602]=c[8602]|4;A=187}else A=187;while(0);if((((A|0)==187?(l&k)>>>0<2147483647:0)?(z=Pc(l&k|0)|0,x=Pc(0)|0,z>>>0<x>>>0&((z|0)!=(-1|0)&(x|0)!=(-1|0))):0)?(x-z|0)>>>0>(r+40|0)>>>0:0){h=x-z|0;g=z;A=190}if((A|0)==190){b=(c[8599]|0)+h|0;c[8599]=b;if(b>>>0>(c[8600]|0)>>>0)c[8600]=b;j=c[8497]|0;do if(j){b=34412;while(1){a=c[b>>2]|0;d=b+4|0;e=c[d>>2]|0;if((g|0)==(a+e|0)){A=200;break}f=c[b+8>>2]|0;if(!f)break;else b=f}if(((A|0)==200?(c[b+12>>2]&8|0)==0:0)?j>>>0<g>>>0&j>>>0>=a>>>0:0){c[d>>2]=e+h;G=(j+8&7|0)==0?0:0-(j+8)&7;H=h-G+(c[8494]|0)|0;c[8497]=j+G;c[8494]=H;c[j+G+4>>2]=H|1;c[j+G+H+4>>2]=40;c[8498]=c[8613];break}b=c[8495]|0;if(g>>>0<b>>>0){c[8495]=g;k=g}else k=b;a=g+h|0;b=34412;while(1){if((c[b>>2]|0)==(a|0)){A=208;break}b=c[b+8>>2]|0;if(!b){a=34412;break}}if((A|0)==208)if(!(c[b+12>>2]&8)){c[b>>2]=g;m=b+4|0;c[m>>2]=(c[m>>2]|0)+h;m=g+8|0;m=g+((m&7|0)==0?0:0-m&7)|0;b=a+((a+8&7|0)==0?0:0-(a+8)&7)|0;l=m+r|0;f=b-m-r|0;c[m+4>>2]=r|3;do if((b|0)!=(j|0)){if((b|0)==(c[8496]|0)){H=(c[8493]|0)+f|0;c[8493]=H;c[8496]=l;c[l+4>>2]=H|1;c[l+H>>2]=H;break}j=c[b+4>>2]|0;if((j&3|0)==1){e:do if(j>>>0>=256){h=c[b+24>>2]|0;a=c[b+12>>2]|0;do if((a|0)==(b|0)){a=c[b+16+4>>2]|0;if(!a){a=c[b+16>>2]|0;if(!a){F=0;break}else g=b+16|0}else g=b+16+4|0;while(1){d=a+20|0;e=c[d>>2]|0;if(e|0){a=e;g=d;continue}d=a+16|0;e=c[d>>2]|0;if(!e)break;else{a=e;g=d}}if(g>>>0<k>>>0)ba();else{c[g>>2]=0;F=a;break}}else{d=c[b+8>>2]|0;if(d>>>0<k>>>0)ba();if((c[d+12>>2]|0)!=(b|0))ba();if((c[a+8>>2]|0)==(b|0)){c[d+12>>2]=a;c[a+8>>2]=d;F=a;break}else ba()}while(0);if(!h)break;a=c[b+28>>2]|0;do if((b|0)!=(c[34268+(a<<2)>>2]|0)){if(h>>>0<(c[8495]|0)>>>0)ba();if((c[h+16>>2]|0)==(b|0))c[h+16>>2]=F;else c[h+20>>2]=F;if(!F)break e}else{c[34268+(a<<2)>>2]=F;if(F|0)break;c[8492]=c[8492]&~(1<<a);break e}while(0);d=c[8495]|0;if(F>>>0<d>>>0)ba();c[F+24>>2]=h;a=c[b+16>>2]|0;do if(a|0)if(a>>>0<d>>>0)ba();else{c[F+16>>2]=a;c[a+24>>2]=F;break}while(0);a=c[b+16+4>>2]|0;if(!a)break;if(a>>>0<(c[8495]|0)>>>0)ba();else{c[F+20>>2]=a;c[a+24>>2]=F;break}}else{a=c[b+8>>2]|0;d=c[b+12>>2]|0;do if((a|0)!=(34004+(j>>>3<<1<<2)|0)){if(a>>>0<k>>>0)ba();if((c[a+12>>2]|0)==(b|0))break;ba()}while(0);if((d|0)==(a|0)){c[8491]=c[8491]&~(1<<(j>>>3));break}do if((d|0)==(34004+(j>>>3<<1<<2)|0))E=d+8|0;else{if(d>>>0<k>>>0)ba();if((c[d+8>>2]|0)==(b|0)){E=d+8|0;break}ba()}while(0);c[a+12>>2]=d;c[E>>2]=a}while(0);b=b+(j&-8)|0;f=(j&-8)+f|0}a=b+4|0;c[a>>2]=c[a>>2]&-2;c[l+4>>2]=f|1;c[l+f>>2]=f;a=f>>>3;if(f>>>0<256){b=c[8491]|0;do if(!(b&1<<a)){c[8491]=b|1<<a;G=34004+(a<<1<<2)|0;H=34004+(a<<1<<2)+8|0}else{b=c[34004+(a<<1<<2)+8>>2]|0;if(b>>>0>=(c[8495]|0)>>>0){G=b;H=34004+(a<<1<<2)+8|0;break}ba()}while(0);c[H>>2]=l;c[G+12>>2]=l;c[l+8>>2]=G;c[l+12>>2]=34004+(a<<1<<2);break}b=f>>>8;do if(!b)b=0;else{if(f>>>0>16777215){b=31;break}H=b<<((b+1048320|0)>>>16&8)<<(((b<<((b+1048320|0)>>>16&8))+520192|0)>>>16&4);b=14-(((b<<((b+1048320|0)>>>16&8))+520192|0)>>>16&4|(b+1048320|0)>>>16&8|(H+245760|0)>>>16&2)+(H<<((H+245760|0)>>>16&2)>>>15)|0;b=f>>>(b+7|0)&1|b<<1}while(0);e=34268+(b<<2)|0;c[l+28>>2]=b;c[l+16+4>>2]=0;c[l+16>>2]=0;a=c[8492]|0;d=1<<b;if(!(a&d)){c[8492]=a|d;c[e>>2]=l;c[l+24>>2]=e;c[l+12>>2]=l;c[l+8>>2]=l;break}a=f<<((b|0)==31?0:25-(b>>>1)|0);e=c[e>>2]|0;while(1){if((c[e+4>>2]&-8|0)==(f|0)){A=278;break}d=e+16+(a>>>31<<2)|0;b=c[d>>2]|0;if(!b){A=275;break}else{a=a<<1;e=b}}if((A|0)==275)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[d>>2]=l;c[l+24>>2]=e;c[l+12>>2]=l;c[l+8>>2]=l;break}else if((A|0)==278){b=e+8|0;a=c[b>>2]|0;H=c[8495]|0;if(a>>>0>=H>>>0&e>>>0>=H>>>0){c[a+12>>2]=l;c[b>>2]=l;c[l+8>>2]=a;c[l+12>>2]=e;c[l+24>>2]=0;break}else ba()}}else{H=(c[8494]|0)+f|0;c[8494]=H;c[8497]=l;c[l+4>>2]=H|1}while(0);H=m+8|0;i=I;return H|0}else a=34412;while(1){b=c[a>>2]|0;if(b>>>0<=j>>>0?(B=b+(c[a+4>>2]|0)|0,B>>>0>j>>>0):0)break;a=c[a+8>>2]|0}f=B+-47+((B+-47+8&7|0)==0?0:0-(B+-47+8)&7)|0;f=f>>>0<(j+16|0)>>>0?j:f;b=g+8|0;b=(b&7|0)==0?0:0-b&7;H=g+b|0;b=h+-40-b|0;c[8497]=H;c[8494]=b;c[H+4>>2]=b|1;c[H+b+4>>2]=40;c[8498]=c[8613];c[f+4>>2]=27;c[f+8>>2]=c[8603];c[f+8+4>>2]=c[8604];c[f+8+8>>2]=c[8605];c[f+8+12>>2]=c[8606];c[8603]=g;c[8604]=h;c[8606]=0;c[8605]=f+8;b=f+24|0;do{b=b+4|0;c[b>>2]=7}while((b+4|0)>>>0<B>>>0);if((f|0)!=(j|0)){c[f+4>>2]=c[f+4>>2]&-2;c[j+4>>2]=f-j|1;c[f>>2]=f-j;if((f-j|0)>>>0<256){a=34004+((f-j|0)>>>3<<1<<2)|0;b=c[8491]|0;if(b&1<<((f-j|0)>>>3)){b=c[a+8>>2]|0;if(b>>>0<(c[8495]|0)>>>0)ba();else{C=b;D=a+8|0}}else{c[8491]=b|1<<((f-j|0)>>>3);C=a;D=a+8|0}c[D>>2]=j;c[C+12>>2]=j;c[j+8>>2]=C;c[j+12>>2]=a;break}if((f-j|0)>>>8)if((f-j|0)>>>0>16777215)b=31;else{b=(f-j|0)>>>8<<((((f-j|0)>>>8)+1048320|0)>>>16&8);b=14-((b+520192|0)>>>16&4|(((f-j|0)>>>8)+1048320|0)>>>16&8|((b<<((b+520192|0)>>>16&4))+245760|0)>>>16&2)+(b<<((b+520192|0)>>>16&4)<<(((b<<((b+520192|0)>>>16&4))+245760|0)>>>16&2)>>>15)|0;b=(f-j|0)>>>(b+7|0)&1|b<<1}else b=0;e=34268+(b<<2)|0;c[j+28>>2]=b;c[j+20>>2]=0;c[j+16>>2]=0;a=c[8492]|0;d=1<<b;if(!(a&d)){c[8492]=a|d;c[e>>2]=j;c[j+24>>2]=e;c[j+12>>2]=j;c[j+8>>2]=j;break}a=f-j<<((b|0)==31?0:25-(b>>>1)|0);e=c[e>>2]|0;while(1){if((c[e+4>>2]&-8|0)==(f-j|0)){A=304;break}d=e+16+(a>>>31<<2)|0;b=c[d>>2]|0;if(!b){A=301;break}else{a=a<<1;e=b}}if((A|0)==301)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[d>>2]=j;c[j+24>>2]=e;c[j+12>>2]=j;c[j+8>>2]=j;break}else if((A|0)==304){b=e+8|0;a=c[b>>2]|0;H=c[8495]|0;if(a>>>0>=H>>>0&e>>>0>=H>>>0){c[a+12>>2]=j;c[b>>2]=j;c[j+8>>2]=a;c[j+12>>2]=e;c[j+24>>2]=0;break}else ba()}}}else{H=c[8495]|0;if((H|0)==0|g>>>0<H>>>0)c[8495]=g;c[8603]=g;c[8604]=h;c[8606]=0;c[8500]=c[8609];c[8499]=-1;b=0;do{H=34004+(b<<1<<2)|0;c[H+12>>2]=H;c[H+8>>2]=H;b=b+1|0}while((b|0)!=32);H=g+8|0;H=(H&7|0)==0?0:0-H&7;G=g+H|0;H=h+-40-H|0;c[8497]=G;c[8494]=H;c[G+4>>2]=H|1;c[G+H+4>>2]=40;c[8498]=c[8613]}while(0);b=c[8494]|0;if(b>>>0>r>>>0){F=b-r|0;c[8494]=F;H=c[8497]|0;G=H+r|0;c[8497]=G;c[G+4>>2]=F|1;c[H+4>>2]=r|3;H=H+8|0;i=I;return H|0}}c[(Zf()|0)>>2]=12;H=0;i=I;return H|0} -function oa(b){b=b|0;var c=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0;e=d[b>>0]|0;j=Pd(d[b+1>>0]|0|0,0,8)|0;S=D;_=d[b+2>>0]|0;x=Pd(_|0,0,16)|0;Z=Pd(d[b+3>>0]|0|0,0,8)|0;C=D;Y=Pd(d[b+4>>0]|0|0,0,16)|0;C=C|D;m=d[b+5>>0]|0;n=Pd(m|0,0,24)|0;C=Rd(Z|_|Y|n|0,C|D|0,5)|0;n=Pd(d[b+6>>0]|0|0,0,8)|0;Y=D;_=d[b+7>>0]|0;Z=Pd(_|0,0,16)|0;Y=Rd(n|m|Z|0,Y|D|0,2)|0;Z=Pd(d[b+8>>0]|0|0,0,8)|0;m=D;n=Pd(d[b+9>>0]|0|0,0,16)|0;m=m|D;na=d[b+10>>0]|0;va=Pd(na|0,0,24)|0;m=Rd(Z|_|n|va|0,m|D|0,7)|0;va=Pd(d[b+11>>0]|0|0,0,8)|0;n=D;_=Pd(d[b+12>>0]|0|0,0,16)|0;n=n|D;Z=d[b+13>>0]|0;oa=Pd(Z|0,0,24)|0;n=Rd(va|na|_|oa|0,n|D|0,4)|0;oa=Pd(d[b+14>>0]|0|0,0,8)|0;_=D;na=d[b+15>>0]|0;va=Pd(na|0,0,16)|0;_=Rd(oa|Z|va|0,_|D|0,1)|0;va=Pd(d[b+16>>0]|0|0,0,8)|0;Z=D;oa=Pd(d[b+17>>0]|0|0,0,16)|0;Z=Z|D;xa=d[b+18>>0]|0;ya=Pd(xa|0,0,24)|0;Z=Rd(va|na|oa|ya|0,Z|D|0,6)|0;ya=Pd(d[b+19>>0]|0|0,0,8)|0;oa=D;na=Pd(d[b+20>>0]|0|0,0,16)|0;oa=Rd(ya|xa|na|0,oa|D|0,3)|0;na=D;xa=d[b+21>>0]|0;ya=Pd(d[b+22>>0]|0|0,0,8)|0;va=D;N=d[b+23>>0]|0;wa=Pd(N|0,0,16)|0;U=Pd(d[b+24>>0]|0|0,0,8)|0;ka=D;ua=Pd(d[b+25>>0]|0|0,0,16)|0;ka=ka|D;fa=d[b+26>>0]|0;Ca=Pd(fa|0,0,24)|0;ka=Rd(U|N|ua|Ca|0,ka|D|0,5)|0;Ca=Pd(d[b+27>>0]|0|0,0,8)|0;ua=D;N=d[b+28>>0]|0;U=Pd(N|0,0,16)|0;ua=Rd(Ca|fa|U|0,ua|D|0,2)|0;U=Pd(d[b+29>>0]|0|0,0,8)|0;fa=D;Ca=Pd(d[b+30>>0]|0|0,0,16)|0;fa=fa|D;A=d[b+31>>0]|0;g=Pd(A|0,0,24)|0;fa=Rd(U|N|Ca|g|0,fa|D|0,7)|0;g=Pd(d[b+32>>0]|0|0,0,8)|0;Ca=D;N=Pd(d[b+33>>0]|0|0,0,16)|0;Ca=Ca|D;U=d[b+34>>0]|0;I=Pd(U|0,0,24)|0;Ca=Rd(g|A|N|I|0,Ca|D|0,4)|0;I=Pd(d[b+35>>0]|0|0,0,8)|0;N=D;A=d[b+36>>0]|0;g=Pd(A|0,0,16)|0;N=Rd(I|U|g|0,N|D|0,1)|0;g=Pd(d[b+37>>0]|0|0,0,8)|0;U=D;I=Pd(d[b+38>>0]|0|0,0,16)|0;U=U|D;K=d[b+39>>0]|0;L=Pd(K|0,0,24)|0;U=Rd(g|A|I|L|0,U|D|0,6)|0;L=Pd(d[b+40>>0]|0|0,0,8)|0;I=D;A=Pd(d[b+41>>0]|0|0,0,16)|0;I=Rd(L|K|A|0,I|D|0,3)|0;A=D;K=d[b+42>>0]|0;L=Pd(d[b+43>>0]|0|0,0,8)|0;g=D;X=d[b+44>>0]|0;W=Pd(X|0,0,16)|0;G=Pd(d[b+45>>0]|0|0,0,8)|0;t=D;ha=Pd(d[b+46>>0]|0|0,0,16)|0;t=t|D;Da=d[b+47>>0]|0;u=Pd(Da|0,0,24)|0;t=Rd(G|X|ha|u|0,t|D|0,5)|0;u=Pd(d[b+48>>0]|0|0,0,8)|0;ha=D;X=d[b+49>>0]|0;G=Pd(X|0,0,16)|0;ha=Rd(u|Da|G|0,ha|D|0,2)|0;G=Pd(d[b+50>>0]|0|0,0,8)|0;Da=D;u=Pd(d[b+51>>0]|0|0,0,16)|0;Da=Da|D;s=d[b+52>>0]|0;q=Pd(s|0,0,24)|0;Da=Rd(G|X|u|q|0,Da|D|0,7)|0;q=Pd(d[b+53>>0]|0|0,0,8)|0;u=D;X=Pd(d[b+54>>0]|0|0,0,16)|0;u=u|D;G=d[b+55>>0]|0;f=Pd(G|0,0,24)|0;u=Rd(q|s|X|f|0,u|D|0,4)|0;f=Pd(d[b+56>>0]|0|0,0,8)|0;X=D;s=d[b+57>>0]|0;q=Pd(s|0,0,16)|0;X=Rd(f|G|q|0,X|D|0,1)|0;q=Pd(d[b+58>>0]|0|0,0,8)|0;G=D;f=Pd(d[b+59>>0]|0|0,0,16)|0;G=G|D;E=d[b+60>>0]|0;v=Pd(E|0,0,24)|0;G=Rd(q|s|f|v|0,G|D|0,6)|0;v=Pd(d[b+61>>0]|0|0,0,8)|0;f=D;s=Pd(d[b+62>>0]|0|0,0,16)|0;f=f|D;q=Pd(d[b+63>>0]|0|0,0,24)|0;f=Rd(v|E|s|q|0,f|D|0,3)|0;q=D;s=Ed(f|0,q|0,666643,0)|0;E=D;v=Ed(f|0,q|0,470296,0)|0;o=D;B=Ed(f|0,q|0,654183,0)|0;Q=D;$=Ed(f|0,q|0,-997805,-1)|0;i=D;h=Ed(f|0,q|0,136657,0)|0;p=D;q=Ed(f|0,q|0,-683901,-1)|0;g=oe(q|0,D|0,L|K|W&2031616|0,g|0)|0;W=D;K=Ed(G&2097151|0,0,666643,0)|0;L=D;q=Ed(G&2097151|0,0,470296,0)|0;f=D;qa=Ed(G&2097151|0,0,654183,0)|0;l=D;J=Ed(G&2097151|0,0,-997805,-1)|0;w=D;V=Ed(G&2097151|0,0,136657,0)|0;P=D;G=Ed(G&2097151|0,0,-683901,-1)|0;r=D;c=Ed(X&2097151|0,0,666643,0)|0;O=D;T=Ed(X&2097151|0,0,470296,0)|0;ga=D;aa=Ed(X&2097151|0,0,654183,0)|0;y=D;za=Ed(X&2097151|0,0,-997805,-1)|0;pa=D;H=Ed(X&2097151|0,0,136657,0)|0;k=D;X=Ed(X&2097151|0,0,-683901,-1)|0;U=oe(X|0,D|0,U&2097151|0,0)|0;P=oe(U|0,D|0,V|0,P|0)|0;i=oe(P|0,D|0,$|0,i|0)|0;$=D;P=Ed(u&2097151|0,0,666643,0)|0;V=D;U=Ed(u&2097151|0,0,470296,0)|0;X=D;ra=Ed(u&2097151|0,0,654183,0)|0;z=D;ca=Ed(u&2097151|0,0,-997805,-1)|0;ba=D;Ba=Ed(u&2097151|0,0,136657,0)|0;Aa=D;u=Ed(u&2097151|0,0,-683901,-1)|0;M=D;F=Ed(Da&2097151|0,0,666643,0)|0;R=D;la=Ed(Da&2097151|0,0,470296,0)|0;ma=D;ja=Ed(Da&2097151|0,0,654183,0)|0;ia=D;ta=Ed(Da&2097151|0,0,-997805,-1)|0;sa=D;ea=Ed(Da&2097151|0,0,136657,0)|0;da=D;Da=Ed(Da&2097151|0,0,-683901,-1)|0;Ca=oe(Da|0,D|0,Ca&2097151|0,0)|0;Aa=oe(Ca|0,D|0,Ba|0,Aa|0)|0;pa=oe(Aa|0,D|0,za|0,pa|0)|0;l=oe(pa|0,D|0,qa|0,l|0)|0;o=oe(l|0,D|0,v|0,o|0)|0;v=D;l=Ed(ha&2097151|0,0,666643,0)|0;Z=oe(l|0,D|0,Z&2097151|0,0)|0;l=D;qa=Ed(ha&2097151|0,0,470296,0)|0;pa=D;za=Ed(ha&2097151|0,0,654183,0)|0;va=oe(za|0,D|0,ya|xa|wa&2031616|0,va|0)|0;ma=oe(va|0,D|0,la|0,ma|0)|0;V=oe(ma|0,D|0,P|0,V|0)|0;P=D;ma=Ed(ha&2097151|0,0,-997805,-1)|0;la=D;va=Ed(ha&2097151|0,0,136657,0)|0;ua=oe(va|0,D|0,ua&2097151|0,0)|0;sa=oe(ua|0,D|0,ta|0,sa|0)|0;z=oe(sa|0,D|0,ra|0,z|0)|0;ga=oe(z|0,D|0,T|0,ga|0)|0;L=oe(ga|0,D|0,K|0,L|0)|0;K=D;ha=Ed(ha&2097151|0,0,-683901,-1)|0;ga=D;T=oe(Z|0,l|0,1048576,0)|0;T=Rd(T|0,D|0,21)|0;z=D;na=oe(qa|0,pa|0,oa|0,na|0)|0;na=oe(na|0,D|0,T|0,z|0)|0;R=oe(na|0,D|0,F|0,R|0)|0;F=D;z=Pd(T|0,z|0,21)|0;z=le(Z|0,l|0,z|0,D|0)|0;l=D;Z=oe(V|0,P|0,1048576,0)|0;Z=Rd(Z|0,D|0,21)|0;T=D;ka=oe(ma|0,la|0,ka&2097151|0,0)|0;ia=oe(ka|0,D|0,ja|0,ia|0)|0;X=oe(ia|0,D|0,U|0,X|0)|0;O=oe(X|0,D|0,c|0,O|0)|0;O=oe(O|0,D|0,Z|0,T|0)|0;c=D;T=Pd(Z|0,T|0,21)|0;Z=D;X=oe(L|0,K|0,1048576,0)|0;X=Dd(X|0,D|0,21)|0;U=D;fa=oe(ha|0,ga|0,fa&2097151|0,0)|0;da=oe(fa|0,D|0,ea|0,da|0)|0;ba=oe(da|0,D|0,ca|0,ba|0)|0;y=oe(ba|0,D|0,aa|0,y|0)|0;f=oe(y|0,D|0,q|0,f|0)|0;E=oe(f|0,D|0,s|0,E|0)|0;E=oe(E|0,D|0,X|0,U|0)|0;s=D;U=Pd(X|0,U|0,21)|0;X=D;f=oe(o|0,v|0,1048576,0)|0;f=Dd(f|0,D|0,21)|0;q=D;N=oe(u|0,M|0,N&2097151|0,0)|0;k=oe(N|0,D|0,H|0,k|0)|0;w=oe(k|0,D|0,J|0,w|0)|0;Q=oe(w|0,D|0,B|0,Q|0)|0;Q=oe(Q|0,D|0,f|0,q|0)|0;B=D;q=Pd(f|0,q|0,21)|0;q=le(o|0,v|0,q|0,D|0)|0;v=D;o=oe(i|0,$|0,1048576,0)|0;o=Dd(o|0,D|0,21)|0;f=D;A=oe(G|0,r|0,I|0,A|0)|0;p=oe(A|0,D|0,h|0,p|0)|0;p=oe(p|0,D|0,o|0,f|0)|0;h=D;f=Pd(o|0,f|0,21)|0;f=le(i|0,$|0,f|0,D|0)|0;$=D;i=oe(g|0,W|0,1048576,0)|0;i=Dd(i|0,D|0,21)|0;o=D;t=oe(i|0,o|0,t&2097151|0,0)|0;A=D;o=Pd(i|0,o|0,21)|0;o=le(g|0,W|0,o|0,D|0)|0;W=D;g=oe(R|0,F|0,1048576,0)|0;g=Rd(g|0,D|0,21)|0;i=D;I=Pd(g|0,i|0,21)|0;I=le(R|0,F|0,I|0,D|0)|0;F=D;R=oe(O|0,c|0,1048576,0)|0;R=Dd(R|0,D|0,21)|0;r=D;G=Pd(R|0,r|0,21)|0;G=le(O|0,c|0,G|0,D|0)|0;c=D;O=oe(E|0,s|0,1048576,0)|0;O=Dd(O|0,D|0,21)|0;w=D;v=oe(q|0,v|0,O|0,w|0)|0;q=D;w=Pd(O|0,w|0,21)|0;w=le(E|0,s|0,w|0,D|0)|0;s=D;E=oe(Q|0,B|0,1048576,0)|0;E=Dd(E|0,D|0,21)|0;O=D;$=oe(E|0,O|0,f|0,$|0)|0;f=D;O=Pd(E|0,O|0,21)|0;O=le(Q|0,B|0,O|0,D|0)|0;B=D;Q=oe(p|0,h|0,1048576,0)|0;Q=Dd(Q|0,D|0,21)|0;E=D;W=oe(Q|0,E|0,o|0,W|0)|0;o=D;E=Pd(Q|0,E|0,21)|0;E=le(p|0,h|0,E|0,D|0)|0;h=D;p=Ed(t|0,A|0,666643,0)|0;_=oe(p|0,D|0,_&2097151|0,0)|0;p=D;Q=Ed(t|0,A|0,470296,0)|0;Q=oe(z|0,l|0,Q|0,D|0)|0;l=D;z=Ed(t|0,A|0,654183,0)|0;z=oe(I|0,F|0,z|0,D|0)|0;F=D;I=Ed(t|0,A|0,-997805,-1)|0;J=D;k=Ed(t|0,A|0,136657,0)|0;k=oe(G|0,c|0,k|0,D|0)|0;c=D;A=Ed(t|0,A|0,-683901,-1)|0;t=D;r=oe(L|0,K|0,R|0,r|0)|0;X=le(r|0,D|0,U|0,X|0)|0;t=oe(X|0,D|0,A|0,t|0)|0;A=D;X=Ed(W|0,o|0,666643,0)|0;n=oe(X|0,D|0,n&2097151|0,0)|0;X=D;U=Ed(W|0,o|0,470296,0)|0;U=oe(_|0,p|0,U|0,D|0)|0;p=D;_=Ed(W|0,o|0,654183,0)|0;_=oe(Q|0,l|0,_|0,D|0)|0;l=D;Q=Ed(W|0,o|0,-997805,-1)|0;Q=oe(z|0,F|0,Q|0,D|0)|0;F=D;z=Ed(W|0,o|0,136657,0)|0;r=D;o=Ed(W|0,o|0,-683901,-1)|0;o=oe(k|0,c|0,o|0,D|0)|0;c=D;k=Ed(E|0,h|0,666643,0)|0;m=oe(k|0,D|0,m&2097151|0,0)|0;k=D;W=Ed(E|0,h|0,470296,0)|0;W=oe(n|0,X|0,W|0,D|0)|0;X=D;n=Ed(E|0,h|0,654183,0)|0;n=oe(U|0,p|0,n|0,D|0)|0;p=D;U=Ed(E|0,h|0,-997805,-1)|0;U=oe(_|0,l|0,U|0,D|0)|0;l=D;_=Ed(E|0,h|0,136657,0)|0;_=oe(Q|0,F|0,_|0,D|0)|0;F=D;h=Ed(E|0,h|0,-683901,-1)|0;E=D;i=oe(V|0,P|0,g|0,i|0)|0;Z=le(i|0,D|0,T|0,Z|0)|0;J=oe(Z|0,D|0,I|0,J|0)|0;r=oe(J|0,D|0,z|0,r|0)|0;E=oe(r|0,D|0,h|0,E|0)|0;h=D;r=Ed($|0,f|0,666643,0)|0;z=D;J=Ed($|0,f|0,470296,0)|0;I=D;Z=Ed($|0,f|0,654183,0)|0;T=D;i=Ed($|0,f|0,-997805,-1)|0;g=D;P=Ed($|0,f|0,136657,0)|0;P=oe(U|0,l|0,P|0,D|0)|0;l=D;f=Ed($|0,f|0,-683901,-1)|0;f=oe(_|0,F|0,f|0,D|0)|0;F=D;_=Ed(O|0,B|0,666643,0)|0;$=D;U=Ed(O|0,B|0,470296,0)|0;V=D;Q=Ed(O|0,B|0,654183,0)|0;R=D;K=Ed(O|0,B|0,-997805,-1)|0;L=D;G=Ed(O|0,B|0,136657,0)|0;H=D;B=Ed(O|0,B|0,-683901,-1)|0;B=oe(P|0,l|0,B|0,D|0)|0;l=D;P=Ed(v|0,q|0,666643,0)|0;S=oe(P|0,D|0,j|e|x&2031616|0,S|0)|0;x=D;e=Ed(v|0,q|0,470296,0)|0;j=D;P=Ed(v|0,q|0,654183,0)|0;Y=oe(P|0,D|0,Y&2097151|0,0)|0;z=oe(Y|0,D|0,r|0,z|0)|0;V=oe(z|0,D|0,U|0,V|0)|0;U=D;z=Ed(v|0,q|0,-997805,-1)|0;r=D;Y=Ed(v|0,q|0,136657,0)|0;Y=oe(W|0,X|0,Y|0,D|0)|0;T=oe(Y|0,D|0,Z|0,T|0)|0;L=oe(T|0,D|0,K|0,L|0)|0;K=D;q=Ed(v|0,q|0,-683901,-1)|0;v=D;T=oe(S|0,x|0,1048576,0)|0;T=Dd(T|0,D|0,21)|0;Z=D;C=oe(e|0,j|0,C&2097151|0,0)|0;$=oe(C|0,D|0,_|0,$|0)|0;$=oe($|0,D|0,T|0,Z|0)|0;_=D;Z=Pd(T|0,Z|0,21)|0;Z=le(S|0,x|0,Z|0,D|0)|0;x=D;S=oe(V|0,U|0,1048576,0)|0;S=Dd(S|0,D|0,21)|0;T=D;r=oe(m|0,k|0,z|0,r|0)|0;I=oe(r|0,D|0,J|0,I|0)|0;R=oe(I|0,D|0,Q|0,R|0)|0;R=oe(R|0,D|0,S|0,T|0)|0;Q=D;T=Pd(S|0,T|0,21)|0;S=D;I=oe(L|0,K|0,1048576,0)|0;I=Dd(I|0,D|0,21)|0;J=D;v=oe(n|0,p|0,q|0,v|0)|0;g=oe(v|0,D|0,i|0,g|0)|0;H=oe(g|0,D|0,G|0,H|0)|0;H=oe(H|0,D|0,I|0,J|0)|0;G=D;J=Pd(I|0,J|0,21)|0;I=D;g=oe(B|0,l|0,1048576,0)|0;g=Dd(g|0,D|0,21)|0;i=D;F=oe(f|0,F|0,g|0,i|0)|0;f=D;i=Pd(g|0,i|0,21)|0;i=le(B|0,l|0,i|0,D|0)|0;l=D;B=oe(E|0,h|0,1048576,0)|0;B=Dd(B|0,D|0,21)|0;g=D;c=oe(o|0,c|0,B|0,g|0)|0;o=D;g=Pd(B|0,g|0,21)|0;g=le(E|0,h|0,g|0,D|0)|0;h=D;E=oe(t|0,A|0,1048576,0)|0;E=Dd(E|0,D|0,21)|0;B=D;s=oe(w|0,s|0,E|0,B|0)|0;w=D;B=Pd(E|0,B|0,21)|0;B=le(t|0,A|0,B|0,D|0)|0;A=D;t=oe($|0,_|0,1048576,0)|0;t=Dd(t|0,D|0,21)|0;E=D;v=Pd(t|0,E|0,21)|0;q=D;p=oe(R|0,Q|0,1048576,0)|0;p=Dd(p|0,D|0,21)|0;n=D;r=Pd(p|0,n|0,21)|0;z=D;k=oe(H|0,G|0,1048576,0)|0;k=Dd(k|0,D|0,21)|0;m=D;l=oe(i|0,l|0,k|0,m|0)|0;i=D;m=Pd(k|0,m|0,21)|0;k=D;C=oe(F|0,f|0,1048576,0)|0;C=Dd(C|0,D|0,21)|0;j=D;h=oe(g|0,h|0,C|0,j|0)|0;g=D;j=Pd(C|0,j|0,21)|0;j=le(F|0,f|0,j|0,D|0)|0;f=D;F=oe(c|0,o|0,1048576,0)|0;F=Dd(F|0,D|0,21)|0;C=D;A=oe(B|0,A|0,F|0,C|0)|0;B=D;C=Pd(F|0,C|0,21)|0;C=le(c|0,o|0,C|0,D|0)|0;o=D;c=oe(s|0,w|0,1048576,0)|0;c=Dd(c|0,D|0,21)|0;F=D;e=Pd(c|0,F|0,21)|0;e=le(s|0,w|0,e|0,D|0)|0;w=D;s=Ed(c|0,F|0,666643,0)|0;s=oe(Z|0,x|0,s|0,D|0)|0;x=D;Z=Ed(c|0,F|0,470296,0)|0;Y=D;X=Ed(c|0,F|0,654183,0)|0;W=D;P=Ed(c|0,F|0,-997805,-1)|0;O=D;N=Ed(c|0,F|0,136657,0)|0;M=D;F=Ed(c|0,F|0,-683901,-1)|0;c=D;u=Dd(s|0,x|0,21)|0;y=D;Y=oe($|0,_|0,Z|0,Y|0)|0;Y=oe(Y|0,D|0,u|0,y|0)|0;q=le(Y|0,D|0,v|0,q|0)|0;v=D;y=Pd(u|0,y|0,21)|0;y=le(s|0,x|0,y|0,D|0)|0;x=D;s=Dd(q|0,v|0,21)|0;u=D;U=oe(X|0,W|0,V|0,U|0)|0;S=le(U|0,D|0,T|0,S|0)|0;E=oe(S|0,D|0,t|0,E|0)|0;E=oe(E|0,D|0,s|0,u|0)|0;t=D;u=Pd(s|0,u|0,21)|0;u=le(q|0,v|0,u|0,D|0)|0;v=D;q=Dd(E|0,t|0,21)|0;s=D;O=oe(R|0,Q|0,P|0,O|0)|0;z=le(O|0,D|0,r|0,z|0)|0;z=oe(z|0,D|0,q|0,s|0)|0;r=D;s=Pd(q|0,s|0,21)|0;s=le(E|0,t|0,s|0,D|0)|0;t=D;E=Dd(z|0,r|0,21)|0;q=D;K=oe(N|0,M|0,L|0,K|0)|0;I=le(K|0,D|0,J|0,I|0)|0;n=oe(I|0,D|0,p|0,n|0)|0;n=oe(n|0,D|0,E|0,q|0)|0;p=D;q=Pd(E|0,q|0,21)|0;q=le(z|0,r|0,q|0,D|0)|0;r=D;z=Dd(n|0,p|0,21)|0;E=D;c=oe(H|0,G|0,F|0,c|0)|0;k=le(c|0,D|0,m|0,k|0)|0;k=oe(k|0,D|0,z|0,E|0)|0;m=D;E=Pd(z|0,E|0,21)|0;E=le(n|0,p|0,E|0,D|0)|0;p=D;n=Dd(k|0,m|0,21)|0;z=D;i=oe(l|0,i|0,n|0,z|0)|0;l=D;z=Pd(n|0,z|0,21)|0;z=le(k|0,m|0,z|0,D|0)|0;m=D;k=Dd(i|0,l|0,21)|0;n=D;f=oe(k|0,n|0,j|0,f|0)|0;j=D;n=Pd(k|0,n|0,21)|0;n=le(i|0,l|0,n|0,D|0)|0;l=D;i=Dd(f|0,j|0,21)|0;k=D;g=oe(h|0,g|0,i|0,k|0)|0;h=D;k=Pd(i|0,k|0,21)|0;k=le(f|0,j|0,k|0,D|0)|0;j=D;f=Dd(g|0,h|0,21)|0;i=D;o=oe(f|0,i|0,C|0,o|0)|0;C=D;i=Pd(f|0,i|0,21)|0;i=le(g|0,h|0,i|0,D|0)|0;h=D;g=Dd(o|0,C|0,21)|0;f=D;B=oe(A|0,B|0,g|0,f|0)|0;A=D;f=Pd(g|0,f|0,21)|0;f=le(o|0,C|0,f|0,D|0)|0;C=D;o=Dd(B|0,A|0,21)|0;g=D;w=oe(o|0,g|0,e|0,w|0)|0;e=D;g=Pd(o|0,g|0,21)|0;g=le(B|0,A|0,g|0,D|0)|0;A=D;B=Dd(w|0,e|0,21)|0;o=D;c=Pd(B|0,o|0,21)|0;c=le(w|0,e|0,c|0,D|0)|0;e=D;w=Ed(B|0,o|0,666643,0)|0;x=oe(w|0,D|0,y|0,x|0)|0;y=D;w=Ed(B|0,o|0,470296,0)|0;w=oe(u|0,v|0,w|0,D|0)|0;v=D;u=Ed(B|0,o|0,654183,0)|0;u=oe(s|0,t|0,u|0,D|0)|0;t=D;s=Ed(B|0,o|0,-997805,-1)|0;s=oe(q|0,r|0,s|0,D|0)|0;r=D;q=Ed(B|0,o|0,136657,0)|0;q=oe(E|0,p|0,q|0,D|0)|0;p=D;o=Ed(B|0,o|0,-683901,-1)|0;o=oe(z|0,m|0,o|0,D|0)|0;m=D;z=Dd(x|0,y|0,21)|0;B=D;v=oe(w|0,v|0,z|0,B|0)|0;w=D;B=Pd(z|0,B|0,21)|0;B=le(x|0,y|0,B|0,D|0)|0;y=D;x=Dd(v|0,w|0,21)|0;z=D;t=oe(u|0,t|0,x|0,z|0)|0;u=D;z=Pd(x|0,z|0,21)|0;z=le(v|0,w|0,z|0,D|0)|0;w=D;v=Dd(t|0,u|0,21)|0;x=D;r=oe(s|0,r|0,v|0,x|0)|0;s=D;x=Pd(v|0,x|0,21)|0;x=le(t|0,u|0,x|0,D|0)|0;u=D;t=Dd(r|0,s|0,21)|0;v=D;p=oe(q|0,p|0,t|0,v|0)|0;q=D;v=Pd(t|0,v|0,21)|0;v=le(r|0,s|0,v|0,D|0)|0;s=D;r=Dd(p|0,q|0,21)|0;t=D;m=oe(o|0,m|0,r|0,t|0)|0;o=D;t=Pd(r|0,t|0,21)|0;t=le(p|0,q|0,t|0,D|0)|0;q=D;p=Dd(m|0,o|0,21)|0;r=D;l=oe(p|0,r|0,n|0,l|0)|0;n=D;r=Pd(p|0,r|0,21)|0;r=le(m|0,o|0,r|0,D|0)|0;o=D;m=Dd(l|0,n|0,21)|0;p=D;j=oe(m|0,p|0,k|0,j|0)|0;k=D;p=Pd(m|0,p|0,21)|0;p=le(l|0,n|0,p|0,D|0)|0;n=D;l=Dd(j|0,k|0,21)|0;m=D;h=oe(l|0,m|0,i|0,h|0)|0;i=D;m=Pd(l|0,m|0,21)|0;m=le(j|0,k|0,m|0,D|0)|0;k=D;j=Dd(h|0,i|0,21)|0;l=D;C=oe(j|0,l|0,f|0,C|0)|0;f=D;l=Pd(j|0,l|0,21)|0;l=le(h|0,i|0,l|0,D|0)|0;i=D;h=Dd(C|0,f|0,21)|0;j=D;A=oe(h|0,j|0,g|0,A|0)|0;g=D;j=Pd(h|0,j|0,21)|0;j=le(C|0,f|0,j|0,D|0)|0;f=D;C=Dd(A|0,g|0,21)|0;h=D;e=oe(C|0,h|0,c|0,e|0)|0;c=D;h=Pd(C|0,h|0,21)|0;h=le(A|0,g|0,h|0,D|0)|0;g=D;a[b>>0]=B;A=Rd(B|0,y|0,8)|0;a[b+1>>0]=A;y=Rd(B|0,y|0,16)|0;B=D;A=Pd(z|0,w|0,5)|0;a[b+2>>0]=A|y;y=Rd(z|0,w|0,3)|0;a[b+3>>0]=y;y=Rd(z|0,w|0,11)|0;a[b+4>>0]=y;w=Rd(z|0,w|0,19)|0;z=D;y=Pd(x|0,u|0,2)|0;a[b+5>>0]=y|w;w=Rd(x|0,u|0,6)|0;a[b+6>>0]=w;u=Rd(x|0,u|0,14)|0;x=D;w=Pd(v|0,s|0,7)|0;a[b+7>>0]=w|u;u=Rd(v|0,s|0,1)|0;a[b+8>>0]=u;u=Rd(v|0,s|0,9)|0;a[b+9>>0]=u;s=Rd(v|0,s|0,17)|0;v=D;u=Pd(t|0,q|0,4)|0;a[b+10>>0]=u|s;s=Rd(t|0,q|0,4)|0;a[b+11>>0]=s;s=Rd(t|0,q|0,12)|0;a[b+12>>0]=s;q=Rd(t|0,q|0,20)|0;t=D;s=Pd(r|0,o|0,1)|0;a[b+13>>0]=s|q;q=Rd(r|0,o|0,7)|0;a[b+14>>0]=q;o=Rd(r|0,o|0,15)|0;r=D;q=Pd(p|0,n|0,6)|0;a[b+15>>0]=q|o;o=Rd(p|0,n|0,2)|0;a[b+16>>0]=o;o=Rd(p|0,n|0,10)|0;a[b+17>>0]=o;n=Rd(p|0,n|0,18)|0;p=D;o=Pd(m|0,k|0,3)|0;a[b+18>>0]=o|n;n=Rd(m|0,k|0,5)|0;a[b+19>>0]=n;k=Rd(m|0,k|0,13)|0;a[b+20>>0]=k;a[b+21>>0]=l;k=Rd(l|0,i|0,8)|0;a[b+22>>0]=k;i=Rd(l|0,i|0,16)|0;l=D;k=Pd(j|0,f|0,5)|0;a[b+23>>0]=k|i;i=Rd(j|0,f|0,3)|0;a[b+24>>0]=i;i=Rd(j|0,f|0,11)|0;a[b+25>>0]=i;f=Rd(j|0,f|0,19)|0;j=D;i=Pd(h|0,g|0,2)|0;a[b+26>>0]=i|f;f=Rd(h|0,g|0,6)|0;a[b+27>>0]=f;g=Rd(h|0,g|0,14)|0;h=D;f=Pd(e|0,c|0,7)|0;a[b+28>>0]=g|f;f=Rd(e|0,c|0,1)|0;a[b+29>>0]=f;f=Rd(e|0,c|0,9)|0;a[b+30>>0]=f;c=Rd(e|0,c|0,17)|0;a[b+31>>0]=c;return}function pa(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0,fb=0,gb=0,hb=0,ib=0,jb=0,kb=0,lb=0,mb=0,nb=0,ob=0,pb=0,qb=0,rb=0,sb=0,tb=0,ub=0,vb=0,wb=0,xb=0,yb=0,zb=0,Ab=0,Bb=0,Cb=0,Db=0,Eb=0,Fb=0,Gb=0,Hb=0,Ib=0,Jb=0,Kb=0,Lb=0,Mb=0,Nb=0,Ob=0,Pb=0,Qb=0,Rb=0,Sb=0,Tb=0,Ub=0,Vb=0,Wb=0,Xb=0,Yb=0,Zb=0,_b=0,$b=0,ac=0,bc=0,cc=0,dc=0,ec=0,fc=0,gc=0,hc=0,ic=0,jc=0,kc=0,lc=0,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0,sc=0,tc=0,uc=0,vc=0,wc=0,xc=0,yc=0,zc=0,Ac=0,Bc=0,Cc=0,Dc=0,Ec=0,Fc=0,Gc=0,Hc=0,Ic=0,Jc=0,Kc=0,Lc=0,Mc=0,Nc=0,Oc=0,Pc=0;o=c[b>>2]|0;n=c[b+4>>2]|0;k=c[b+8>>2]|0;fa=c[b+12>>2]|0;N=c[b+16>>2]|0;M=c[b+20>>2]|0;g=c[b+24>>2]|0;ea=c[b+28>>2]|0;L=c[b+32>>2]|0;q=c[b+36>>2]|0;I=c[d>>2]|0;Oc=c[d+4>>2]|0;cc=c[d+8>>2]|0;sb=c[d+12>>2]|0;Ia=c[d+16>>2]|0;jc=c[d+20>>2]|0;Db=c[d+24>>2]|0;Ta=c[d+28>>2]|0;ga=c[d+32>>2]|0;Pc=c[d+36>>2]|0;Mc=Ed(I|0,((I|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;Lc=D;wc=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;vc=D;ub=Ed(cc|0,((cc|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;tb=D;Ka=Ed(sb|0,((sb|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;Ja=D;mc=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;lc=D;Gb=Ed(jc|0,((jc|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;Fb=D;Wa=Ed(Db|0,((Db|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;Va=D;ja=Ed(Ta|0,((Ta|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;ia=D;P=Ed(ga|0,((ga|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;O=D;o=Ed(Pc|0,((Pc|0)<0)<<31>>31|0,o|0,((o|0)<0)<<31>>31|0)|0;l=D;dc=Ed(I|0,((I|0)<0)<<31>>31|0,n|0,((n|0)<0)<<31>>31|0)|0;ec=D;yb=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,n<<1|0,((n<<1|0)<0)<<31>>31|0)|0;xb=D;Ma=Ed(cc|0,((cc|0)<0)<<31>>31|0,n|0,((n|0)<0)<<31>>31|0)|0;La=D;oc=Ed(sb|0,((sb|0)<0)<<31>>31|0,n<<1|0,((n<<1|0)<0)<<31>>31|0)|0;nc=D;Ib=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,n|0,((n|0)<0)<<31>>31|0)|0;Hb=D;Ya=Ed(jc|0,((jc|0)<0)<<31>>31|0,n<<1|0,((n<<1|0)<0)<<31>>31|0)|0;Xa=D;la=Ed(Db|0,((Db|0)<0)<<31>>31|0,n|0,((n|0)<0)<<31>>31|0)|0;ka=D;R=Ed(Ta|0,((Ta|0)<0)<<31>>31|0,n<<1|0,((n<<1|0)<0)<<31>>31|0)|0;Q=D;t=Ed(ga|0,((ga|0)<0)<<31>>31|0,n|0,((n|0)<0)<<31>>31|0)|0;s=D;d=((Pc*19|0)<0)<<31>>31;n=Ed(Pc*19|0,d|0,n<<1|0,((n<<1|0)<0)<<31>>31|0)|0;p=D;wb=Ed(I|0,((I|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;vb=D;Qa=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;Pa=D;qc=Ed(cc|0,((cc|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;pc=D;Kb=Ed(sb|0,((sb|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;Jb=D;_a=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;Za=D;na=Ed(jc|0,((jc|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;ma=D;T=Ed(Db|0,((Db|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;S=D;v=Ed(Ta|0,((Ta|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;u=D;ha=((ga*19|0)<0)<<31>>31;yc=Ed(ga*19|0,ha|0,k|0,((k|0)<0)<<31>>31|0)|0;xc=D;k=Ed(Pc*19|0,d|0,k|0,((k|0)<0)<<31>>31|0)|0;j=D;Oa=Ed(I|0,((I|0)<0)<<31>>31|0,fa|0,((fa|0)<0)<<31>>31|0)|0;Na=D;uc=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,fa<<1|0,((fa<<1|0)<0)<<31>>31|0)|0;tc=D;Mb=Ed(cc|0,((cc|0)<0)<<31>>31|0,fa|0,((fa|0)<0)<<31>>31|0)|0;Lb=D;ab=Ed(sb|0,((sb|0)<0)<<31>>31|0,fa<<1|0,((fa<<1|0)<0)<<31>>31|0)|0;$a=D;pa=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,fa|0,((fa|0)<0)<<31>>31|0)|0;oa=D;V=Ed(jc|0,((jc|0)<0)<<31>>31|0,fa<<1|0,((fa<<1|0)<0)<<31>>31|0)|0;U=D;x=Ed(Db|0,((Db|0)<0)<<31>>31|0,fa|0,((fa|0)<0)<<31>>31|0)|0;w=D;Ua=((Ta*19|0)<0)<<31>>31;Ac=Ed(Ta*19|0,Ua|0,fa<<1|0,((fa<<1|0)<0)<<31>>31|0)|0;zc=D;Sb=Ed(ga*19|0,ha|0,fa|0,((fa|0)<0)<<31>>31|0)|0;Rb=D;fa=Ed(Pc*19|0,d|0,fa<<1|0,((fa<<1|0)<0)<<31>>31|0)|0;f=D;sc=Ed(I|0,((I|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;rc=D;Qb=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;Pb=D;cb=Ed(cc|0,((cc|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;bb=D;ra=Ed(sb|0,((sb|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;qa=D;X=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;W=D;z=Ed(jc|0,((jc|0)<0)<<31>>31|0,N|0,((N|0)<0)<<31>>31|0)|0;y=D;Eb=((Db*19|0)<0)<<31>>31;Cc=Ed(Db*19|0,Eb|0,N|0,((N|0)<0)<<31>>31|0)|0;Bc=D;Ub=Ed(Ta*19|0,Ua|0,N|0,((N|0)<0)<<31>>31|0)|0;Tb=D;ib=Ed(ga*19|0,ha|0,N|0,((N|0)<0)<<31>>31|0)|0;hb=D;N=Ed(Pc*19|0,d|0,N|0,((N|0)<0)<<31>>31|0)|0;e=D;Ob=Ed(I|0,((I|0)<0)<<31>>31|0,M|0,((M|0)<0)<<31>>31|0)|0;Nb=D;gb=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,M<<1|0,((M<<1|0)<0)<<31>>31|0)|0;fb=D;ta=Ed(cc|0,((cc|0)<0)<<31>>31|0,M|0,((M|0)<0)<<31>>31|0)|0;sa=D;Z=Ed(sb|0,((sb|0)<0)<<31>>31|0,M<<1|0,((M<<1|0)<0)<<31>>31|0)|0;Y=D;B=Ed(Ia|0,((Ia|0)<0)<<31>>31|0,M|0,((M|0)<0)<<31>>31|0)|0;A=D;kc=((jc*19|0)<0)<<31>>31;Ec=Ed(jc*19|0,kc|0,M<<1|0,((M<<1|0)<0)<<31>>31|0)|0;Dc=D;Wb=Ed(Db*19|0,Eb|0,M|0,((M|0)<0)<<31>>31|0)|0;Vb=D;kb=Ed(Ta*19|0,Ua|0,M<<1|0,((M<<1|0)<0)<<31>>31|0)|0;jb=D;Aa=Ed(ga*19|0,ha|0,M|0,((M|0)<0)<<31>>31|0)|0;za=D;b=Ed(Pc*19|0,d|0,M<<1|0,((M<<1|0)<0)<<31>>31|0)|0;M=D;eb=Ed(I|0,((I|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;db=D;xa=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;wa=D;$=Ed(cc|0,((cc|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;_=D;E=Ed(sb|0,((sb|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;C=D;Gc=Ed(Ia*19|0,((Ia*19|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;Fc=D;Yb=Ed(jc*19|0,kc|0,g|0,((g|0)<0)<<31>>31|0)|0;Xb=D;mb=Ed(Db*19|0,Eb|0,g|0,((g|0)<0)<<31>>31|0)|0;lb=D;Ca=Ed(Ta*19|0,Ua|0,g|0,((g|0)<0)<<31>>31|0)|0;Ba=D;m=Ed(ga*19|0,ha|0,g|0,((g|0)<0)<<31>>31|0)|0;r=D;g=Ed(Pc*19|0,d|0,g|0,((g|0)<0)<<31>>31|0)|0;ya=D;va=Ed(I|0,((I|0)<0)<<31>>31|0,ea|0,((ea|0)<0)<<31>>31|0)|0;ua=D;da=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,ea<<1|0,((ea<<1|0)<0)<<31>>31|0)|0;ca=D;G=Ed(cc|0,((cc|0)<0)<<31>>31|0,ea|0,((ea|0)<0)<<31>>31|0)|0;F=D;Ic=Ed(sb*19|0,((sb*19|0)<0)<<31>>31|0,ea<<1|0,((ea<<1|0)<0)<<31>>31|0)|0;Hc=D;_b=Ed(Ia*19|0,((Ia*19|0)<0)<<31>>31|0,ea|0,((ea|0)<0)<<31>>31|0)|0;Zb=D;ob=Ed(jc*19|0,kc|0,ea<<1|0,((ea<<1|0)<0)<<31>>31|0)|0;nb=D;Ea=Ed(Db*19|0,Eb|0,ea|0,((ea|0)<0)<<31>>31|0)|0;Da=D;gc=Ed(Ta*19|0,Ua|0,ea<<1|0,((ea<<1|0)<0)<<31>>31|0)|0;fc=D;Ab=Ed(ga*19|0,ha|0,ea|0,((ea|0)<0)<<31>>31|0)|0;zb=D;ea=Ed(Pc*19|0,d|0,ea<<1|0,((ea<<1|0)<0)<<31>>31|0)|0;i=D;ba=Ed(I|0,((I|0)<0)<<31>>31|0,L|0,((L|0)<0)<<31>>31|0)|0;aa=D;K=Ed(Oc|0,((Oc|0)<0)<<31>>31|0,L|0,((L|0)<0)<<31>>31|0)|0;J=D;Kc=Ed(cc*19|0,((cc*19|0)<0)<<31>>31|0,L|0,((L|0)<0)<<31>>31|0)|0;Jc=D;ac=Ed(sb*19|0,((sb*19|0)<0)<<31>>31|0,L|0,((L|0)<0)<<31>>31|0)|0;$b=D;qb=Ed(Ia*19|0,((Ia*19|0)<0)<<31>>31|0,L|0,((L|0)<0)<<31>>31|0)|0;pb=D;Ga=Ed(jc*19|0,kc|0,L|0,((L|0)<0)<<31>>31|0)|0;Fa=D;ic=Ed(Db*19|0,Eb|0,L|0,((L|0)<0)<<31>>31|0)|0;hc=D;Cb=Ed(Ta*19|0,Ua|0,L|0,((L|0)<0)<<31>>31|0)|0;Bb=D;Sa=Ed(ga*19|0,ha|0,L|0,((L|0)<0)<<31>>31|0)|0;Ra=D;L=Ed(Pc*19|0,d|0,L|0,((L|0)<0)<<31>>31|0)|0;h=D;I=Ed(I|0,((I|0)<0)<<31>>31|0,q|0,((q|0)<0)<<31>>31|0)|0;H=D;Oc=Ed(Oc*19|0,((Oc*19|0)<0)<<31>>31|0,q<<1|0,((q<<1|0)<0)<<31>>31|0)|0;Nc=D;cc=Ed(cc*19|0,((cc*19|0)<0)<<31>>31|0,q|0,((q|0)<0)<<31>>31|0)|0;bc=D;sb=Ed(sb*19|0,((sb*19|0)<0)<<31>>31|0,q<<1|0,((q<<1|0)<0)<<31>>31|0)|0;rb=D;Ia=Ed(Ia*19|0,((Ia*19|0)<0)<<31>>31|0,q|0,((q|0)<0)<<31>>31|0)|0;Ha=D;kc=Ed(jc*19|0,kc|0,q<<1|0,((q<<1|0)<0)<<31>>31|0)|0;jc=D;Eb=Ed(Db*19|0,Eb|0,q|0,((q|0)<0)<<31>>31|0)|0;Db=D;Ua=Ed(Ta*19|0,Ua|0,q<<1|0,((q<<1|0)<0)<<31>>31|0)|0;Ta=D;ha=Ed(ga*19|0,ha|0,q|0,((q|0)<0)<<31>>31|0)|0;ga=D;q=Ed(Pc*19|0,d|0,q<<1|0,((q<<1|0)<0)<<31>>31|0)|0;d=D;Lc=oe(Oc|0,Nc|0,Mc|0,Lc|0)|0;Jc=oe(Lc|0,D|0,Kc|0,Jc|0)|0;Hc=oe(Jc|0,D|0,Ic|0,Hc|0)|0;Fc=oe(Hc|0,D|0,Gc|0,Fc|0)|0;Dc=oe(Fc|0,D|0,Ec|0,Dc|0)|0;Bc=oe(Dc|0,D|0,Cc|0,Bc|0)|0;zc=oe(Bc|0,D|0,Ac|0,zc|0)|0;xc=oe(zc|0,D|0,yc|0,xc|0)|0;p=oe(xc|0,D|0,n|0,p|0)|0;n=D;ec=oe(wc|0,vc|0,dc|0,ec|0)|0;dc=D;rc=oe(uc|0,tc|0,sc|0,rc|0)|0;pc=oe(rc|0,D|0,qc|0,pc|0)|0;nc=oe(pc|0,D|0,oc|0,nc|0)|0;lc=oe(nc|0,D|0,mc|0,lc|0)|0;jc=oe(lc|0,D|0,kc|0,jc|0)|0;hc=oe(jc|0,D|0,ic|0,hc|0)|0;fc=oe(hc|0,D|0,gc|0,fc|0)|0;r=oe(fc|0,D|0,m|0,r|0)|0;M=oe(r|0,D|0,b|0,M|0)|0;b=D;r=oe(p|0,n|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;m=D;bc=oe(ec|0,dc|0,cc|0,bc|0)|0;$b=oe(bc|0,D|0,ac|0,$b|0)|0;Zb=oe($b|0,D|0,_b|0,Zb|0)|0;Xb=oe(Zb|0,D|0,Yb|0,Xb|0)|0;Vb=oe(Xb|0,D|0,Wb|0,Vb|0)|0;Tb=oe(Vb|0,D|0,Ub|0,Tb|0)|0;Rb=oe(Tb|0,D|0,Sb|0,Rb|0)|0;j=oe(Rb|0,D|0,k|0,j|0)|0;j=oe(j|0,D|0,r|0,m|0)|0;k=D;m=Pd(r|0,m|0,26)|0;m=le(p|0,n|0,m|0,D|0)|0;n=D;p=oe(M|0,b|0,33554432,0)|0;p=Dd(p|0,D|0,26)|0;r=D;Nb=oe(Qb|0,Pb|0,Ob|0,Nb|0)|0;Lb=oe(Nb|0,D|0,Mb|0,Lb|0)|0;Jb=oe(Lb|0,D|0,Kb|0,Jb|0)|0;Hb=oe(Jb|0,D|0,Ib|0,Hb|0)|0;Fb=oe(Hb|0,D|0,Gb|0,Fb|0)|0;Db=oe(Fb|0,D|0,Eb|0,Db|0)|0;Bb=oe(Db|0,D|0,Cb|0,Bb|0)|0;zb=oe(Bb|0,D|0,Ab|0,zb|0)|0;ya=oe(zb|0,D|0,g|0,ya|0)|0;ya=oe(ya|0,D|0,p|0,r|0)|0;g=D;r=Pd(p|0,r|0,26)|0;r=le(M|0,b|0,r|0,D|0)|0;b=D;M=oe(j|0,k|0,16777216,0)|0;M=Dd(M|0,D|0,25)|0;p=D;vb=oe(yb|0,xb|0,wb|0,vb|0)|0;tb=oe(vb|0,D|0,ub|0,tb|0)|0;rb=oe(tb|0,D|0,sb|0,rb|0)|0;pb=oe(rb|0,D|0,qb|0,pb|0)|0;nb=oe(pb|0,D|0,ob|0,nb|0)|0;lb=oe(nb|0,D|0,mb|0,lb|0)|0;jb=oe(lb|0,D|0,kb|0,jb|0)|0;hb=oe(jb|0,D|0,ib|0,hb|0)|0;f=oe(hb|0,D|0,fa|0,f|0)|0;f=oe(f|0,D|0,M|0,p|0)|0;fa=D;p=Pd(M|0,p|0,25)|0;p=le(j|0,k|0,p|0,D|0)|0;k=D;j=oe(ya|0,g|0,16777216,0)|0;j=Dd(j|0,D|0,25)|0;M=D;db=oe(gb|0,fb|0,eb|0,db|0)|0;bb=oe(db|0,D|0,cb|0,bb|0)|0;$a=oe(bb|0,D|0,ab|0,$a|0)|0;Za=oe($a|0,D|0,_a|0,Za|0)|0;Xa=oe(Za|0,D|0,Ya|0,Xa|0)|0;Va=oe(Xa|0,D|0,Wa|0,Va|0)|0;Ta=oe(Va|0,D|0,Ua|0,Ta|0)|0;Ra=oe(Ta|0,D|0,Sa|0,Ra|0)|0;i=oe(Ra|0,D|0,ea|0,i|0)|0;i=oe(i|0,D|0,j|0,M|0)|0;ea=D;M=Pd(j|0,M|0,25)|0;M=le(ya|0,g|0,M|0,D|0)|0;g=D;ya=oe(f|0,fa|0,33554432,0)|0;ya=Dd(ya|0,D|0,26)|0;j=D;Na=oe(Qa|0,Pa|0,Oa|0,Na|0)|0;La=oe(Na|0,D|0,Ma|0,La|0)|0;Ja=oe(La|0,D|0,Ka|0,Ja|0)|0;Ha=oe(Ja|0,D|0,Ia|0,Ha|0)|0;Fa=oe(Ha|0,D|0,Ga|0,Fa|0)|0;Da=oe(Fa|0,D|0,Ea|0,Da|0)|0;Ba=oe(Da|0,D|0,Ca|0,Ba|0)|0;za=oe(Ba|0,D|0,Aa|0,za|0)|0;e=oe(za|0,D|0,N|0,e|0)|0;e=oe(e|0,D|0,ya|0,j|0)|0;N=D;j=Pd(ya|0,j|0,26)|0;j=le(f|0,fa|0,j|0,D|0)|0;fa=oe(i|0,ea|0,33554432,0)|0;fa=Dd(fa|0,D|0,26)|0;f=D;ua=oe(xa|0,wa|0,va|0,ua|0)|0;sa=oe(ua|0,D|0,ta|0,sa|0)|0;qa=oe(sa|0,D|0,ra|0,qa|0)|0;oa=oe(qa|0,D|0,pa|0,oa|0)|0;ma=oe(oa|0,D|0,na|0,ma|0)|0;ka=oe(ma|0,D|0,la|0,ka|0)|0;ia=oe(ka|0,D|0,ja|0,ia|0)|0;ga=oe(ia|0,D|0,ha|0,ga|0)|0;h=oe(ga|0,D|0,L|0,h|0)|0;h=oe(h|0,D|0,fa|0,f|0)|0;L=D;f=Pd(fa|0,f|0,26)|0;f=le(i|0,ea|0,f|0,D|0)|0;ea=oe(e|0,N|0,16777216,0)|0;ea=Dd(ea|0,D|0,25)|0;i=D;b=oe(ea|0,i|0,r|0,b|0)|0;r=D;i=Pd(ea|0,i|0,25)|0;i=le(e|0,N|0,i|0,D|0)|0;N=oe(h|0,L|0,16777216,0)|0;N=Dd(N|0,D|0,25)|0;e=D;aa=oe(da|0,ca|0,ba|0,aa|0)|0;_=oe(aa|0,D|0,$|0,_|0)|0;Y=oe(_|0,D|0,Z|0,Y|0)|0;W=oe(Y|0,D|0,X|0,W|0)|0;U=oe(W|0,D|0,V|0,U|0)|0;S=oe(U|0,D|0,T|0,S|0)|0;Q=oe(S|0,D|0,R|0,Q|0)|0;O=oe(Q|0,D|0,P|0,O|0)|0;d=oe(O|0,D|0,q|0,d|0)|0;d=oe(d|0,D|0,N|0,e|0)|0;q=D;e=Pd(N|0,e|0,25)|0;e=le(h|0,L|0,e|0,D|0)|0;L=oe(b|0,r|0,33554432,0)|0;L=Dd(L|0,D|0,26)|0;h=D;g=oe(M|0,g|0,L|0,h|0)|0;h=Pd(L|0,h|0,26)|0;h=le(b|0,r|0,h|0,D|0)|0;r=oe(d|0,q|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;b=D;H=oe(K|0,J|0,I|0,H|0)|0;F=oe(H|0,D|0,G|0,F|0)|0;C=oe(F|0,D|0,E|0,C|0)|0;A=oe(C|0,D|0,B|0,A|0)|0;y=oe(A|0,D|0,z|0,y|0)|0;w=oe(y|0,D|0,x|0,w|0)|0;u=oe(w|0,D|0,v|0,u|0)|0;s=oe(u|0,D|0,t|0,s|0)|0;l=oe(s|0,D|0,o|0,l|0)|0;l=oe(l|0,D|0,r|0,b|0)|0;o=D;b=Pd(r|0,b|0,26)|0;b=le(d|0,q|0,b|0,D|0)|0;q=oe(l|0,o|0,16777216,0)|0;q=Dd(q|0,D|0,25)|0;d=D;r=Ed(q|0,d|0,19,0)|0;n=oe(r|0,D|0,m|0,n|0)|0;m=D;d=Pd(q|0,d|0,25)|0;d=le(l|0,o|0,d|0,D|0)|0;o=oe(n|0,m|0,33554432,0)|0;o=Dd(o|0,D|0,26)|0;l=D;k=oe(p|0,k|0,o|0,l|0)|0;l=Pd(o|0,l|0,26)|0;l=le(n|0,m|0,l|0,D|0)|0;c[a>>2]=l;c[a+4>>2]=k;c[a+8>>2]=j;c[a+12>>2]=i;c[a+16>>2]=h;c[a+20>>2]=g;c[a+24>>2]=f;c[a+28>>2]=e;c[a+32>>2]=b;c[a+36>>2]=d;return}function qa(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0;l=c[b>>2]|0;n=c[b+4>>2]|0;k=c[b+8>>2]|0;f=c[b+12>>2]|0;u=c[b+16>>2]|0;t=c[b+20>>2]|0;g=c[b+24>>2]|0;v=c[b+28>>2]|0;s=c[b+32>>2]|0;q=c[b+36>>2]|0;cb=Ed(l|0,((l|0)<0)<<31>>31|0,l|0,((l|0)<0)<<31>>31|0)|0;bb=D;o=((l<<1|0)<0)<<31>>31;Ua=Ed(l<<1|0,o|0,n|0,((n|0)<0)<<31>>31|0)|0;Ta=D;Oa=Ed(k|0,((k|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Na=D;Ea=Ed(f|0,((f|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Da=D;sa=Ed(u|0,((u|0)<0)<<31>>31|0,l<<1|0,o|0)|0;ra=D;ia=Ed(t|0,((t|0)<0)<<31>>31|0,l<<1|0,o|0)|0;ha=D;_=Ed(g|0,((g|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Z=D;Q=Ed(v|0,((v|0)<0)<<31>>31|0,l<<1|0,o|0)|0;P=D;G=Ed(s|0,((s|0)<0)<<31>>31|0,l<<1|0,o|0)|0;F=D;o=Ed(q|0,((q|0)<0)<<31>>31|0,l<<1|0,o|0)|0;l=D;p=((n<<1|0)<0)<<31>>31;Ma=Ed(n<<1|0,p|0,n|0,((n|0)<0)<<31>>31|0)|0;La=D;Ca=Ed(n<<1|0,p|0,k|0,((k|0)<0)<<31>>31|0)|0;Ba=D;w=((f<<1|0)<0)<<31>>31;wa=Ed(f<<1|0,w|0,n<<1|0,p|0)|0;va=D;ma=Ed(u|0,((u|0)<0)<<31>>31|0,n<<1|0,p|0)|0;la=D;aa=Ed(t<<1|0,((t<<1|0)<0)<<31>>31|0,n<<1|0,p|0)|0;$=D;S=Ed(g|0,((g|0)<0)<<31>>31|0,n<<1|0,p|0)|0;R=D;I=Ed(v<<1|0,((v<<1|0)<0)<<31>>31|0,n<<1|0,p|0)|0;H=D;m=Ed(s|0,((s|0)<0)<<31>>31|0,n<<1|0,p|0)|0;r=D;b=((q*38|0)<0)<<31>>31;p=Ed(q*38|0,b|0,n<<1|0,p|0)|0;n=D;ua=Ed(k|0,((k|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;ta=D;ka=Ed(k<<1|0,((k<<1|0)<0)<<31>>31|0,f|0,((f|0)<0)<<31>>31|0)|0;ja=D;ca=Ed(u|0,((u|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;ba=D;W=Ed(t|0,((t|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;V=D;O=Ed(g|0,((g|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;N=D;z=Ed(v|0,((v|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;y=D;Y=((s*19|0)<0)<<31>>31;Ya=Ed(s*19|0,Y|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;Xa=D;k=Ed(q*38|0,b|0,k|0,((k|0)<0)<<31>>31|0)|0;j=D;ea=Ed(f<<1|0,w|0,f|0,((f|0)<0)<<31>>31|0)|0;da=D;U=Ed(f<<1|0,w|0,u|0,((u|0)<0)<<31>>31|0)|0;T=D;K=Ed(t<<1|0,((t<<1|0)<0)<<31>>31|0,f<<1|0,w|0)|0;J=D;E=Ed(g|0,((g|0)<0)<<31>>31|0,f<<1|0,w|0)|0;C=D;qa=((v*38|0)<0)<<31>>31;_a=Ed(v*38|0,qa|0,f<<1|0,w|0)|0;Za=D;Qa=Ed(s*19|0,Y|0,f<<1|0,w|0)|0;Pa=D;w=Ed(q*38|0,b|0,f<<1|0,w|0)|0;f=D;M=Ed(u|0,((u|0)<0)<<31>>31|0,u|0,((u|0)<0)<<31>>31|0)|0;L=D;B=Ed(u<<1|0,((u<<1|0)<0)<<31>>31|0,t|0,((t|0)<0)<<31>>31|0)|0;A=D;ab=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,u<<1|0,((u<<1|0)<0)<<31>>31|0)|0;$a=D;Sa=Ed(v*38|0,qa|0,u|0,((u|0)<0)<<31>>31|0)|0;Ra=D;Ga=Ed(s*19|0,Y|0,u<<1|0,((u<<1|0)<0)<<31>>31|0)|0;Fa=D;u=Ed(q*38|0,b|0,u|0,((u|0)<0)<<31>>31|0)|0;e=D;eb=Ed(t*38|0,((t*38|0)<0)<<31>>31|0,t|0,((t|0)<0)<<31>>31|0)|0;db=D;Wa=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,t<<1|0,((t<<1|0)<0)<<31>>31|0)|0;Va=D;Ia=Ed(v*38|0,qa|0,t<<1|0,((t<<1|0)<0)<<31>>31|0)|0;Ha=D;ya=Ed(s*19|0,Y|0,t<<1|0,((t<<1|0)<0)<<31>>31|0)|0;xa=D;t=Ed(q*38|0,b|0,t<<1|0,((t<<1|0)<0)<<31>>31|0)|0;d=D;Ka=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;Ja=D;Aa=Ed(v*38|0,qa|0,g|0,((g|0)<0)<<31>>31|0)|0;za=D;oa=Ed(s*19|0,Y|0,g<<1|0,((g<<1|0)<0)<<31>>31|0)|0;na=D;g=Ed(q*38|0,b|0,g|0,((g|0)<0)<<31>>31|0)|0;x=D;qa=Ed(v*38|0,qa|0,v|0,((v|0)<0)<<31>>31|0)|0;pa=D;ga=Ed(s*19|0,Y|0,v<<1|0,((v<<1|0)<0)<<31>>31|0)|0;fa=D;v=Ed(q*38|0,b|0,v<<1|0,((v<<1|0)<0)<<31>>31|0)|0;i=D;Y=Ed(s*19|0,Y|0,s|0,((s|0)<0)<<31>>31|0)|0;X=D;s=Ed(q*38|0,b|0,s|0,((s|0)<0)<<31>>31|0)|0;h=D;q=Ed(q*38|0,b|0,q|0,((q|0)<0)<<31>>31|0)|0;b=D;bb=oe(eb|0,db|0,cb|0,bb|0)|0;$a=oe(bb|0,D|0,ab|0,$a|0)|0;Za=oe($a|0,D|0,_a|0,Za|0)|0;Xa=oe(Za|0,D|0,Ya|0,Xa|0)|0;n=oe(Xa|0,D|0,p|0,n|0)|0;p=D;Ta=oe(Wa|0,Va|0,Ua|0,Ta|0)|0;Ra=oe(Ta|0,D|0,Sa|0,Ra|0)|0;Pa=oe(Ra|0,D|0,Qa|0,Pa|0)|0;j=oe(Pa|0,D|0,k|0,j|0)|0;k=D;La=oe(Oa|0,Na|0,Ma|0,La|0)|0;Ja=oe(La|0,D|0,Ka|0,Ja|0)|0;Ha=oe(Ja|0,D|0,Ia|0,Ha|0)|0;Fa=oe(Ha|0,D|0,Ga|0,Fa|0)|0;f=oe(Fa|0,D|0,w|0,f|0)|0;w=D;Ba=oe(Ea|0,Da|0,Ca|0,Ba|0)|0;za=oe(Ba|0,D|0,Aa|0,za|0)|0;xa=oe(za|0,D|0,ya|0,xa|0)|0;e=oe(xa|0,D|0,u|0,e|0)|0;u=D;ta=oe(wa|0,va|0,ua|0,ta|0)|0;ra=oe(ta|0,D|0,sa|0,ra|0)|0;pa=oe(ra|0,D|0,qa|0,pa|0)|0;na=oe(pa|0,D|0,oa|0,na|0)|0;d=oe(na|0,D|0,t|0,d|0)|0;t=D;ja=oe(ma|0,la|0,ka|0,ja|0)|0;ha=oe(ja|0,D|0,ia|0,ha|0)|0;fa=oe(ha|0,D|0,ga|0,fa|0)|0;x=oe(fa|0,D|0,g|0,x|0)|0;g=D;ba=oe(ea|0,da|0,ca|0,ba|0)|0;$=oe(ba|0,D|0,aa|0,$|0)|0;Z=oe($|0,D|0,_|0,Z|0)|0;X=oe(Z|0,D|0,Y|0,X|0)|0;i=oe(X|0,D|0,v|0,i|0)|0;v=D;T=oe(W|0,V|0,U|0,T|0)|0;R=oe(T|0,D|0,S|0,R|0)|0;P=oe(R|0,D|0,Q|0,P|0)|0;h=oe(P|0,D|0,s|0,h|0)|0;s=D;L=oe(O|0,N|0,M|0,L|0)|0;J=oe(L|0,D|0,K|0,J|0)|0;H=oe(J|0,D|0,I|0,H|0)|0;F=oe(H|0,D|0,G|0,F|0)|0;b=oe(F|0,D|0,q|0,b|0)|0;q=D;A=oe(E|0,C|0,B|0,A|0)|0;y=oe(A|0,D|0,z|0,y|0)|0;r=oe(y|0,D|0,m|0,r|0)|0;l=oe(r|0,D|0,o|0,l|0)|0;o=D;p=Pd(n|0,p|0,1)|0;n=D;k=Pd(j|0,k|0,1)|0;j=D;w=Pd(f|0,w|0,1)|0;f=D;u=Pd(e|0,u|0,1)|0;e=D;t=Pd(d|0,t|0,1)|0;d=D;g=Pd(x|0,g|0,1)|0;x=D;v=Pd(i|0,v|0,1)|0;i=D;s=Pd(h|0,s|0,1)|0;h=D;q=Pd(b|0,q|0,1)|0;b=D;o=Pd(l|0,o|0,1)|0;l=D;r=oe(p|0,n|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;m=D;j=oe(r|0,m|0,k|0,j|0)|0;k=D;m=Pd(r|0,m|0,26)|0;m=le(p|0,n|0,m|0,D|0)|0;n=D;p=oe(t|0,d|0,33554432,0)|0;p=Dd(p|0,D|0,26)|0;r=D;x=oe(p|0,r|0,g|0,x|0)|0;g=D;r=Pd(p|0,r|0,26)|0;r=le(t|0,d|0,r|0,D|0)|0;d=D;t=oe(j|0,k|0,16777216,0)|0;t=Dd(t|0,D|0,25)|0;p=D;f=oe(t|0,p|0,w|0,f|0)|0;w=D;p=Pd(t|0,p|0,25)|0;p=le(j|0,k|0,p|0,D|0)|0;k=D;j=oe(x|0,g|0,16777216,0)|0;j=Dd(j|0,D|0,25)|0;t=D;i=oe(j|0,t|0,v|0,i|0)|0;v=D;t=Pd(j|0,t|0,25)|0;t=le(x|0,g|0,t|0,D|0)|0;g=D;x=oe(f|0,w|0,33554432,0)|0;x=Dd(x|0,D|0,26)|0;j=D;e=oe(x|0,j|0,u|0,e|0)|0;u=D;j=Pd(x|0,j|0,26)|0;j=le(f|0,w|0,j|0,D|0)|0;w=oe(i|0,v|0,33554432,0)|0;w=Dd(w|0,D|0,26)|0;f=D;h=oe(w|0,f|0,s|0,h|0)|0;s=D;f=Pd(w|0,f|0,26)|0;f=le(i|0,v|0,f|0,D|0)|0;v=oe(e|0,u|0,16777216,0)|0;v=Dd(v|0,D|0,25)|0;i=D;d=oe(v|0,i|0,r|0,d|0)|0;r=D;i=Pd(v|0,i|0,25)|0;i=le(e|0,u|0,i|0,D|0)|0;u=oe(h|0,s|0,16777216,0)|0;u=Dd(u|0,D|0,25)|0;e=D;b=oe(u|0,e|0,q|0,b|0)|0;q=D;e=Pd(u|0,e|0,25)|0;e=le(h|0,s|0,e|0,D|0)|0;s=oe(d|0,r|0,33554432,0)|0;s=Dd(s|0,D|0,26)|0;h=D;g=oe(t|0,g|0,s|0,h|0)|0;h=Pd(s|0,h|0,26)|0;h=le(d|0,r|0,h|0,D|0)|0;r=oe(b|0,q|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;d=D;l=oe(r|0,d|0,o|0,l|0)|0;o=D;d=Pd(r|0,d|0,26)|0;d=le(b|0,q|0,d|0,D|0)|0;q=oe(l|0,o|0,16777216,0)|0;q=Dd(q|0,D|0,25)|0;b=D;r=Ed(q|0,b|0,19,0)|0;n=oe(r|0,D|0,m|0,n|0)|0;m=D;b=Pd(q|0,b|0,25)|0;b=le(l|0,o|0,b|0,D|0)|0;o=oe(n|0,m|0,33554432,0)|0;o=Dd(o|0,D|0,26)|0;l=D;k=oe(p|0,k|0,o|0,l|0)|0;l=Pd(o|0,l|0,26)|0;l=le(n|0,m|0,l|0,D|0)|0;c[a>>2]=l;c[a+4>>2]=k;c[a+8>>2]=j;c[a+12>>2]=i;c[a+16>>2]=h;c[a+20>>2]=g;c[a+24>>2]=f;c[a+28>>2]=e;c[a+32>>2]=d;c[a+36>>2]=b;return}function ra(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0,qa=0,ra=0,sa=0,ta=0,ua=0,va=0,wa=0,xa=0,ya=0,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=0,La=0,Ma=0,Na=0,Oa=0,Pa=0,Qa=0,Ra=0,Sa=0,Ta=0,Ua=0,Va=0,Wa=0,Xa=0,Ya=0,Za=0,_a=0,$a=0,ab=0,bb=0,cb=0,db=0,eb=0;l=c[b>>2]|0;p=c[b+4>>2]|0;k=c[b+8>>2]|0;f=c[b+12>>2]|0;C=c[b+16>>2]|0;d=c[b+20>>2]|0;g=c[b+24>>2]|0;O=c[b+28>>2]|0;A=c[b+32>>2]|0;q=c[b+36>>2]|0;cb=Ed(l|0,((l|0)<0)<<31>>31|0,l|0,((l|0)<0)<<31>>31|0)|0;bb=D;o=((l<<1|0)<0)<<31>>31;Ia=Ed(l<<1|0,o|0,p|0,((p|0)<0)<<31>>31|0)|0;Ha=D;Wa=Ed(k|0,((k|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Va=D;Ua=Ed(f|0,((f|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Ta=D;Oa=Ed(C|0,((C|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Na=D;ya=Ed(d|0,((d|0)<0)<<31>>31|0,l<<1|0,o|0)|0;xa=D;ga=Ed(g|0,((g|0)<0)<<31>>31|0,l<<1|0,o|0)|0;fa=D;R=Ed(O|0,((O|0)<0)<<31>>31|0,l<<1|0,o|0)|0;Q=D;F=Ed(A|0,((A|0)<0)<<31>>31|0,l<<1|0,o|0)|0;E=D;o=Ed(q|0,((q|0)<0)<<31>>31|0,l<<1|0,o|0)|0;l=D;n=((p<<1|0)<0)<<31>>31;ta=Ed(p<<1|0,n|0,p|0,((p|0)<0)<<31>>31|0)|0;ua=D;ba=Ed(p<<1|0,n|0,k|0,((k|0)<0)<<31>>31|0)|0;ca=D;P=((f<<1|0)<0)<<31>>31;Sa=Ed(f<<1|0,P|0,p<<1|0,n|0)|0;Ra=D;Ca=Ed(C|0,((C|0)<0)<<31>>31|0,p<<1|0,n|0)|0;Ba=D;ia=Ed(d<<1|0,((d<<1|0)<0)<<31>>31|0,p<<1|0,n|0)|0;ha=D;T=Ed(g|0,((g|0)<0)<<31>>31|0,p<<1|0,n|0)|0;S=D;H=Ed(O<<1|0,((O<<1|0)<0)<<31>>31|0,p<<1|0,n|0)|0;G=D;t=Ed(A|0,((A|0)<0)<<31>>31|0,p<<1|0,n|0)|0;s=D;b=((q*38|0)<0)<<31>>31;n=Ed(q*38|0,b|0,p<<1|0,n|0)|0;p=D;Qa=Ed(k|0,((k|0)<0)<<31>>31|0,k|0,((k|0)<0)<<31>>31|0)|0;Pa=D;Aa=Ed(k<<1|0,((k<<1|0)<0)<<31>>31|0,f|0,((f|0)<0)<<31>>31|0)|0;za=D;ka=Ed(C|0,((C|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;ja=D;X=Ed(d|0,((d|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;W=D;N=Ed(g|0,((g|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;M=D;v=Ed(O|0,((O|0)<0)<<31>>31|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;u=D;ea=((A*19|0)<0)<<31>>31;Ya=Ed(A*19|0,ea|0,k<<1|0,((k<<1|0)<0)<<31>>31|0)|0;Xa=D;k=Ed(q*38|0,b|0,k|0,((k|0)<0)<<31>>31|0)|0;j=D;ma=Ed(f<<1|0,P|0,f|0,((f|0)<0)<<31>>31|0)|0;la=D;V=Ed(f<<1|0,P|0,C|0,((C|0)<0)<<31>>31|0)|0;U=D;J=Ed(d<<1|0,((d<<1|0)<0)<<31>>31|0,f<<1|0,P|0)|0;I=D;z=Ed(g|0,((g|0)<0)<<31>>31|0,f<<1|0,P|0)|0;y=D;Ma=((O*38|0)<0)<<31>>31;_a=Ed(O*38|0,Ma|0,f<<1|0,P|0)|0;Za=D;Ea=Ed(A*19|0,ea|0,f<<1|0,P|0)|0;Da=D;P=Ed(q*38|0,b|0,f<<1|0,P|0)|0;f=D;L=Ed(C|0,((C|0)<0)<<31>>31|0,C|0,((C|0)<0)<<31>>31|0)|0;K=D;x=Ed(C<<1|0,((C<<1|0)<0)<<31>>31|0,d|0,((d|0)<0)<<31>>31|0)|0;w=D;ab=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,C<<1|0,((C<<1|0)<0)<<31>>31|0)|0;$a=D;Ga=Ed(O*38|0,Ma|0,C|0,((C|0)<0)<<31>>31|0)|0;Fa=D;oa=Ed(A*19|0,ea|0,C<<1|0,((C<<1|0)<0)<<31>>31|0)|0;na=D;C=Ed(q*38|0,b|0,C|0,((C|0)<0)<<31>>31|0)|0;e=D;eb=Ed(d*38|0,((d*38|0)<0)<<31>>31|0,d|0,((d|0)<0)<<31>>31|0)|0;db=D;Ka=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,d<<1|0,((d<<1|0)<0)<<31>>31|0)|0;Ja=D;qa=Ed(O*38|0,Ma|0,d<<1|0,((d<<1|0)<0)<<31>>31|0)|0;pa=D;_=Ed(A*19|0,ea|0,d<<1|0,((d<<1|0)<0)<<31>>31|0)|0;Z=D;d=Ed(q*38|0,b|0,d<<1|0,((d<<1|0)<0)<<31>>31|0)|0;B=D;sa=Ed(g*19|0,((g*19|0)<0)<<31>>31|0,g|0,((g|0)<0)<<31>>31|0)|0;ra=D;aa=Ed(O*38|0,Ma|0,g|0,((g|0)<0)<<31>>31|0)|0;$=D;m=Ed(A*19|0,ea|0,g<<1|0,((g<<1|0)<0)<<31>>31|0)|0;r=D;g=Ed(q*38|0,b|0,g|0,((g|0)<0)<<31>>31|0)|0;Y=D;Ma=Ed(O*38|0,Ma|0,O|0,((O|0)<0)<<31>>31|0)|0;La=D;wa=Ed(A*19|0,ea|0,O<<1|0,((O<<1|0)<0)<<31>>31|0)|0;va=D;O=Ed(q*38|0,b|0,O<<1|0,((O<<1|0)<0)<<31>>31|0)|0;i=D;ea=Ed(A*19|0,ea|0,A|0,((A|0)<0)<<31>>31|0)|0;da=D;A=Ed(q*38|0,b|0,A|0,((A|0)<0)<<31>>31|0)|0;h=D;q=Ed(q*38|0,b|0,q|0,((q|0)<0)<<31>>31|0)|0;b=D;bb=oe(eb|0,db|0,cb|0,bb|0)|0;$a=oe(bb|0,D|0,ab|0,$a|0)|0;Za=oe($a|0,D|0,_a|0,Za|0)|0;Xa=oe(Za|0,D|0,Ya|0,Xa|0)|0;p=oe(Xa|0,D|0,n|0,p|0)|0;n=D;ua=oe(Wa|0,Va|0,ta|0,ua|0)|0;ta=D;ca=oe(Ua|0,Ta|0,ba|0,ca|0)|0;ba=D;Pa=oe(Sa|0,Ra|0,Qa|0,Pa|0)|0;Na=oe(Pa|0,D|0,Oa|0,Na|0)|0;La=oe(Na|0,D|0,Ma|0,La|0)|0;r=oe(La|0,D|0,m|0,r|0)|0;B=oe(r|0,D|0,d|0,B|0)|0;d=D;r=oe(p|0,n|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;m=D;Ha=oe(Ka|0,Ja|0,Ia|0,Ha|0)|0;Fa=oe(Ha|0,D|0,Ga|0,Fa|0)|0;Da=oe(Fa|0,D|0,Ea|0,Da|0)|0;j=oe(Da|0,D|0,k|0,j|0)|0;j=oe(j|0,D|0,r|0,m|0)|0;k=D;m=Pd(r|0,m|0,26)|0;m=le(p|0,n|0,m|0,D|0)|0;n=D;p=oe(B|0,d|0,33554432,0)|0;p=Dd(p|0,D|0,26)|0;r=D;za=oe(Ca|0,Ba|0,Aa|0,za|0)|0;xa=oe(za|0,D|0,ya|0,xa|0)|0;va=oe(xa|0,D|0,wa|0,va|0)|0;Y=oe(va|0,D|0,g|0,Y|0)|0;Y=oe(Y|0,D|0,p|0,r|0)|0;g=D;r=Pd(p|0,r|0,26)|0;r=le(B|0,d|0,r|0,D|0)|0;d=D;B=oe(j|0,k|0,16777216,0)|0;B=Dd(B|0,D|0,25)|0;p=D;ra=oe(ua|0,ta|0,sa|0,ra|0)|0;pa=oe(ra|0,D|0,qa|0,pa|0)|0;na=oe(pa|0,D|0,oa|0,na|0)|0;f=oe(na|0,D|0,P|0,f|0)|0;f=oe(f|0,D|0,B|0,p|0)|0;P=D;p=Pd(B|0,p|0,25)|0;p=le(j|0,k|0,p|0,D|0)|0;k=D;j=oe(Y|0,g|0,16777216,0)|0;j=Dd(j|0,D|0,25)|0;B=D;ja=oe(ma|0,la|0,ka|0,ja|0)|0;ha=oe(ja|0,D|0,ia|0,ha|0)|0;fa=oe(ha|0,D|0,ga|0,fa|0)|0;da=oe(fa|0,D|0,ea|0,da|0)|0;i=oe(da|0,D|0,O|0,i|0)|0;i=oe(i|0,D|0,j|0,B|0)|0;O=D;B=Pd(j|0,B|0,25)|0;B=le(Y|0,g|0,B|0,D|0)|0;g=D;Y=oe(f|0,P|0,33554432,0)|0;Y=Dd(Y|0,D|0,26)|0;j=D;$=oe(ca|0,ba|0,aa|0,$|0)|0;Z=oe($|0,D|0,_|0,Z|0)|0;e=oe(Z|0,D|0,C|0,e|0)|0;e=oe(e|0,D|0,Y|0,j|0)|0;C=D;j=Pd(Y|0,j|0,26)|0;j=le(f|0,P|0,j|0,D|0)|0;P=oe(i|0,O|0,33554432,0)|0;P=Dd(P|0,D|0,26)|0;f=D;U=oe(X|0,W|0,V|0,U|0)|0;S=oe(U|0,D|0,T|0,S|0)|0;Q=oe(S|0,D|0,R|0,Q|0)|0;h=oe(Q|0,D|0,A|0,h|0)|0;h=oe(h|0,D|0,P|0,f|0)|0;A=D;f=Pd(P|0,f|0,26)|0;f=le(i|0,O|0,f|0,D|0)|0;O=oe(e|0,C|0,16777216,0)|0;O=Dd(O|0,D|0,25)|0;i=D;d=oe(O|0,i|0,r|0,d|0)|0;r=D;i=Pd(O|0,i|0,25)|0;i=le(e|0,C|0,i|0,D|0)|0;C=oe(h|0,A|0,16777216,0)|0;C=Dd(C|0,D|0,25)|0;e=D;K=oe(N|0,M|0,L|0,K|0)|0;I=oe(K|0,D|0,J|0,I|0)|0;G=oe(I|0,D|0,H|0,G|0)|0;E=oe(G|0,D|0,F|0,E|0)|0;b=oe(E|0,D|0,q|0,b|0)|0;b=oe(b|0,D|0,C|0,e|0)|0;q=D;e=Pd(C|0,e|0,25)|0;e=le(h|0,A|0,e|0,D|0)|0;A=oe(d|0,r|0,33554432,0)|0;A=Dd(A|0,D|0,26)|0;h=D;g=oe(B|0,g|0,A|0,h|0)|0;h=Pd(A|0,h|0,26)|0;h=le(d|0,r|0,h|0,D|0)|0;r=oe(b|0,q|0,33554432,0)|0;r=Dd(r|0,D|0,26)|0;d=D;w=oe(z|0,y|0,x|0,w|0)|0;u=oe(w|0,D|0,v|0,u|0)|0;s=oe(u|0,D|0,t|0,s|0)|0;l=oe(s|0,D|0,o|0,l|0)|0;l=oe(l|0,D|0,r|0,d|0)|0;o=D;d=Pd(r|0,d|0,26)|0;d=le(b|0,q|0,d|0,D|0)|0;q=oe(l|0,o|0,16777216,0)|0;q=Dd(q|0,D|0,25)|0;b=D;r=Ed(q|0,b|0,19,0)|0;n=oe(r|0,D|0,m|0,n|0)|0;m=D;b=Pd(q|0,b|0,25)|0;b=le(l|0,o|0,b|0,D|0)|0;o=oe(n|0,m|0,33554432,0)|0;o=Dd(o|0,D|0,26)|0;l=D;k=oe(p|0,k|0,o|0,l|0)|0;l=Pd(o|0,l|0,26)|0;l=le(n|0,m|0,l|0,D|0)|0;c[a>>2]=l;c[a+4>>2]=k;c[a+8>>2]=j;c[a+12>>2]=i;c[a+16>>2]=h;c[a+20>>2]=g;c[a+24>>2]=f;c[a+28>>2]=e;c[a+32>>2]=d;c[a+36>>2]=b;return}function sa(b,c,e,f,g){b=b|0;c=c|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;n=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;p=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;h=d[g+8>>0]|d[g+8+1>>0]<<8|d[g+8+2>>0]<<16|d[g+8+3>>0]<<24;i=d[g+8+4>>0]|d[g+8+4+1>>0]<<8|d[g+8+4+2>>0]<<16|d[g+8+4+3>>0]<<24;f=Pd(e|0,f|0,56)|0;g=D;if((c+e+(0-(e&7))|0)==(c|0)){o=h^2037671283;l=i^1952801890;m=n^1886610805;k=p^1936682341;j=h^1852075885;s=i^1685025377;i=n^1852142177;h=p^1819895653}else{u=c;r=h^2037671283;l=i^1952801890;o=n^1886610805;m=p^1936682341;k=h^1852075885;j=i^1685025377;i=n^1852142177;h=p^1819895653;while(1){v=u;t=d[v>>0]|d[v+1>>0]<<8|d[v+2>>0]<<16|d[v+3>>0]<<24;v=d[v+4>>0]|d[v+4+1>>0]<<8|d[v+4+2>>0]<<16|d[v+4+3>>0]<<24;p=t^r;r=v^l;m=oe(o|0,m|0,k|0,j|0)|0;n=D;q=Pd(k|0,j|0,13)|0;s=D;x=Rd(k|0,j|0,51)|0;s=(s|D)^n;h=oe(p|0,r|0,i|0,h|0)|0;i=D;o=Pd(p|0,r|0,16)|0;j=D;k=Rd(p|0,r|0,48)|0;j=(j|D)^i;n=oe((o|k)^h|0,j|0,n|0,m|0)|0;r=D;l=Pd((o|k)^h|0,j|0,21)|0;p=D;j=Rd((o|k)^h|0,j|0,43)|0;p=(p|D)^r;i=oe(h|0,i|0,(q|x)^m|0,s|0)|0;h=D;k=Pd((q|x)^m|0,s|0,17)|0;o=D;s=Rd((q|x)^m|0,s|0,47)|0;o=h^(o|D);r=oe(n|0,r|0,i^(k|s)|0,o|0)|0;m=D;x=Pd(i^(k|s)|0,o|0,13)|0;q=D;o=Rd(i^(k|s)|0,o|0,51)|0;q=(q|D)^m;i=oe((l|j)^n|0,p|0,h|0,i|0)|0;h=D;s=Pd((l|j)^n|0,p|0,16)|0;k=D;p=Rd((l|j)^n|0,p|0,48)|0;k=(k|D)^h;m=oe((s|p)^i|0,k|0,m|0,r|0)|0;n=D;j=Pd((s|p)^i|0,k|0,21)|0;l=D;k=Rd((s|p)^i|0,k|0,43)|0;l=(l|D)^n;h=oe(i|0,h|0,(x|o)^r|0,q|0)|0;i=D;p=Pd((x|o)^r|0,q|0,17)|0;s=D;q=Rd((x|o)^r|0,q|0,47)|0;s=(s|D)^i;u=u+8|0;if((u|0)==(c+e+(0-(e&7))|0)){c=c+e+(0-(e&7))|0;o=(j|k)^m;m=m^t;k=n^v;j=(p|q)^h;break}else{r=(j|k)^m;o=m^t;m=n^v;k=(p|q)^h;j=s}}}switch(e&7){case 7:{f=Pd(d[c+6>>0]|0|0,0,48)|0|f;g=D|g;w=5;break}case 6:{w=5;break}case 5:{w=6;break}case 4:{w=7;break}case 3:{w=8;break}case 2:{w=9;break}case 1:{w=10;break}default:{}}if((w|0)==5){x=Pd(d[c+5>>0]|0|0,0,40)|0;g=D|g;f=x|f;w=6}if((w|0)==6){g=d[c+4>>0]|0|g;w=7}if((w|0)==7){x=Pd(d[c+3>>0]|0|0,0,24)|0;f=x|f;g=D|g;w=8}if((w|0)==8){x=Pd(d[c+2>>0]|0|0,0,16)|0;f=x|f;g=D|g;w=9}if((w|0)==9){x=Pd(d[c+1>>0]|0|0,0,8)|0;f=x|f;g=D|g;w=10}if((w|0)==10)f=d[c>>0]|0|f;u=f^o;n=g^l;e=oe(m|0,k|0,j|0,s|0)|0;q=D;m=Pd(j|0,s|0,13)|0;r=D;p=Rd(j|0,s|0,51)|0;r=(r|D)^q;v=oe(u|0,n|0,i|0,h|0)|0;c=D;w=Pd(u|0,n|0,16)|0;x=D;n=Rd(u|0,n|0,48)|0;x=(x|D)^c;q=oe((w|n)^v|0,x|0,q|0,e|0)|0;u=D;o=Pd((w|n)^v|0,x|0,21)|0;t=D;x=Rd((w|n)^v|0,x|0,43)|0;t=(t|D)^u;c=oe(v|0,c|0,(m|p)^e|0,r|0)|0;v=D;n=Pd((m|p)^e|0,r|0,17)|0;w=D;r=Rd((m|p)^e|0,r|0,47)|0;w=v^(w|D);u=oe(q|0,u|0,c^(n|r)|0,w|0)|0;e=D;p=Pd(c^(n|r)|0,w|0,13)|0;s=D;w=Rd(c^(n|r)|0,w|0,51)|0;s=(s|D)^e;c=oe((o|x)^q|0,t|0,v|0,c|0)|0;v=D;r=Pd((o|x)^q|0,t|0,16)|0;n=D;t=Rd((o|x)^q|0,t|0,48)|0;n=(n|D)^v;e=oe((r|t)^c|0,n|0,e|0,u|0)|0;q=D;x=Pd((r|t)^c|0,n|0,21)|0;o=D;n=Rd((r|t)^c|0,n|0,43)|0;o=(o|D)^q;v=oe(c|0,v|0,(p|w)^u|0,s|0)|0;c=D;t=Pd((p|w)^u|0,s|0,17)|0;r=D;s=Rd((p|w)^u|0,s|0,47)|0;r=(r|D)^c;q=oe(e^f|0,q^g|0,(t|s)^v|0,r|0)|0;u=D;w=Pd((t|s)^v|0,r|0,13)|0;p=D;r=Rd((t|s)^v|0,r|0,51)|0;p=u^(p|D);v=oe((x|n)^e|0,o|0,c^255|0,v|0)|0;c=D;s=Pd((x|n)^e|0,o|0,16)|0;t=D;o=Rd((x|n)^e|0,o|0,48)|0;t=(t|D)^c;u=oe((s|o)^v|0,t|0,u|0,q|0)|0;e=D;n=Pd((s|o)^v|0,t|0,21)|0;x=D;t=Rd((s|o)^v|0,t|0,43)|0;x=(x|D)^e;c=oe(v|0,c|0,q^(w|r)|0,p|0)|0;v=D;o=Pd(q^(w|r)|0,p|0,17)|0;s=D;p=Rd(q^(w|r)|0,p|0,47)|0;s=(s|D)^v;e=oe(u|0,e|0,(o|p)^c|0,s|0)|0;r=D;w=Pd((o|p)^c|0,s|0,13)|0;q=D;s=Rd((o|p)^c|0,s|0,51)|0;q=(q|D)^r;c=oe((n|t)^u|0,x|0,v|0,c|0)|0;v=D;p=Pd((n|t)^u|0,x|0,16)|0;o=D;x=Rd((n|t)^u|0,x|0,48)|0;o=(o|D)^v;r=oe((p|x)^c|0,o|0,r|0,e|0)|0;u=D;t=Pd((p|x)^c|0,o|0,21)|0;n=D;o=Rd((p|x)^c|0,o|0,43)|0;n=(n|D)^u;v=oe(c|0,v|0,(w|s)^e|0,q|0)|0;c=D;x=Pd((w|s)^e|0,q|0,17)|0;p=D;q=Rd((w|s)^e|0,q|0,47)|0;p=(p|D)^c;u=oe(r|0,u|0,(x|q)^v|0,p|0)|0;e=D;s=Pd((x|q)^v|0,p|0,13)|0;w=D;p=Rd((x|q)^v|0,p|0,51)|0;w=(w|D)^e;v=oe((t|o)^r|0,n|0,c|0,v|0)|0;c=D;q=Pd((t|o)^r|0,n|0,16)|0;x=D;n=Rd((t|o)^r|0,n|0,48)|0;x=(x|D)^c;e=oe((q|n)^v|0,x|0,e|0,u|0)|0;r=D;o=Pd((q|n)^v|0,x|0,21)|0;t=D;x=Rd((q|n)^v|0,x|0,43)|0;t=(t|D)^r;c=oe(v|0,c|0,(s|p)^u|0,w|0)|0;v=D;n=Pd((s|p)^u|0,w|0,17)|0;q=D;w=Rd((s|p)^u|0,w|0,47)|0;q=(q|D)^v;r=oe(e|0,r|0,(n|w)^c|0,q|0)|0;u=D;p=Pd((n|w)^c|0,q|0,13)|0;s=D;q=Rd((n|w)^c|0,q|0,51)|0;u=(s|D)^u;c=oe((o|x)^e|0,t|0,v|0,c|0)|0;v=D;s=Pd((o|x)^e|0,t|0,16)|0;w=D;t=Rd((o|x)^e|0,t|0,48)|0;w=(w|D)^v;e=Pd((s|t)^c|0,w|0,21)|0;x=D;w=Rd((s|t)^c|0,w|0,43)|0;x=x|D;v=oe(c|0,v|0,(p|q)^r|0,u|0)|0;c=D;t=Pd((p|q)^r|0,u|0,17)|0;s=D;u=Rd((p|q)^r|0,u|0,47)|0;x=(s|D)^c^v^x;a[b>>0]=(t|u)^v^c^(e|w);a[b+1>>0]=((t|u)^v^c^(e|w))>>8;a[b+2>>0]=((t|u)^v^c^(e|w))>>16;a[b+3>>0]=((t|u)^v^c^(e|w))>>24;a[b+4>>0]=x;a[b+4+1>>0]=x>>8;a[b+4+2>>0]=x>>16;a[b+4+3>>0]=x>>24;return 0}function ta(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;if(!a)return;h=c[8495]|0;if((a+-8|0)>>>0<h>>>0)ba();b=c[a+-4>>2]|0;if((b&3|0)==1)ba();n=a+-8+(b&-8)|0;do if(!(b&1)){e=c[a+-8>>2]|0;if(!(b&3))return;k=a+-8+(0-e)|0;j=e+(b&-8)|0;if(k>>>0<h>>>0)ba();if((k|0)==(c[8496]|0)){a=c[n+4>>2]|0;if((a&3|0)!=3){q=k;f=j;break}c[8493]=j;c[n+4>>2]=a&-2;c[k+4>>2]=j|1;c[k+j>>2]=j;return}if(e>>>0<256){a=c[k+8>>2]|0;b=c[k+12>>2]|0;if((a|0)!=(34004+(e>>>3<<1<<2)|0)){if(a>>>0<h>>>0)ba();if((c[a+12>>2]|0)!=(k|0))ba()}if((b|0)==(a|0)){c[8491]=c[8491]&~(1<<(e>>>3));q=k;f=j;break}if((b|0)!=(34004+(e>>>3<<1<<2)|0)){if(b>>>0<h>>>0)ba();if((c[b+8>>2]|0)!=(k|0))ba();else d=b+8|0}else d=b+8|0;c[a+12>>2]=b;c[d>>2]=a;q=k;f=j;break}g=c[k+24>>2]|0;a=c[k+12>>2]|0;do if((a|0)==(k|0)){a=c[k+16+4>>2]|0;if(!a){a=c[k+16>>2]|0;if(!a){i=0;break}else e=k+16|0}else e=k+16+4|0;while(1){b=a+20|0;d=c[b>>2]|0;if(d|0){a=d;e=b;continue}b=a+16|0;d=c[b>>2]|0;if(!d)break;else{a=d;e=b}}if(e>>>0<h>>>0)ba();else{c[e>>2]=0;i=a;break}}else{b=c[k+8>>2]|0;if(b>>>0<h>>>0)ba();if((c[b+12>>2]|0)!=(k|0))ba();if((c[a+8>>2]|0)==(k|0)){c[b+12>>2]=a;c[a+8>>2]=b;i=a;break}else ba()}while(0);if(g){a=c[k+28>>2]|0;if((k|0)==(c[34268+(a<<2)>>2]|0)){c[34268+(a<<2)>>2]=i;if(!i){c[8492]=c[8492]&~(1<<a);q=k;f=j;break}}else{if(g>>>0<(c[8495]|0)>>>0)ba();if((c[g+16>>2]|0)==(k|0))c[g+16>>2]=i;else c[g+20>>2]=i;if(!i){q=k;f=j;break}}b=c[8495]|0;if(i>>>0<b>>>0)ba();c[i+24>>2]=g;a=c[k+16>>2]|0;do if(a|0)if(a>>>0<b>>>0)ba();else{c[i+16>>2]=a;c[a+24>>2]=i;break}while(0);a=c[k+16+4>>2]|0;if(a)if(a>>>0<(c[8495]|0)>>>0)ba();else{c[i+20>>2]=a;c[a+24>>2]=i;q=k;f=j;break}else{q=k;f=j}}else{q=k;f=j}}else{q=a+-8|0;f=b&-8}while(0);if(q>>>0>=n>>>0)ba();d=c[n+4>>2]|0;if(!(d&1))ba();if(!(d&2)){if((n|0)==(c[8497]|0)){p=(c[8494]|0)+f|0;c[8494]=p;c[8497]=q;c[q+4>>2]=p|1;if((q|0)!=(c[8496]|0))return;c[8496]=0;c[8493]=0;return}if((n|0)==(c[8496]|0)){p=(c[8493]|0)+f|0;c[8493]=p;c[8496]=q;c[q+4>>2]=p|1;c[q+p>>2]=p;return}f=(d&-8)+f|0;do if(d>>>0>=256){g=c[n+24>>2]|0;a=c[n+12>>2]|0;do if((a|0)==(n|0)){a=c[n+16+4>>2]|0;if(!a){a=c[n+16>>2]|0;if(!a){m=0;break}else e=n+16|0}else e=n+16+4|0;while(1){b=a+20|0;d=c[b>>2]|0;if(d|0){a=d;e=b;continue}b=a+16|0;d=c[b>>2]|0;if(!d)break;else{a=d;e=b}}if(e>>>0<(c[8495]|0)>>>0)ba();else{c[e>>2]=0;m=a;break}}else{b=c[n+8>>2]|0;if(b>>>0<(c[8495]|0)>>>0)ba();if((c[b+12>>2]|0)!=(n|0))ba();if((c[a+8>>2]|0)==(n|0)){c[b+12>>2]=a;c[a+8>>2]=b;m=a;break}else ba()}while(0);if(g|0){a=c[n+28>>2]|0;if((n|0)==(c[34268+(a<<2)>>2]|0)){c[34268+(a<<2)>>2]=m;if(!m){c[8492]=c[8492]&~(1<<a);break}}else{if(g>>>0<(c[8495]|0)>>>0)ba();if((c[g+16>>2]|0)==(n|0))c[g+16>>2]=m;else c[g+20>>2]=m;if(!m)break}b=c[8495]|0;if(m>>>0<b>>>0)ba();c[m+24>>2]=g;a=c[n+16>>2]|0;do if(a|0)if(a>>>0<b>>>0)ba();else{c[m+16>>2]=a;c[a+24>>2]=m;break}while(0);a=c[n+16+4>>2]|0;if(a|0)if(a>>>0<(c[8495]|0)>>>0)ba();else{c[m+20>>2]=a;c[a+24>>2]=m;break}}}else{a=c[n+8>>2]|0;b=c[n+12>>2]|0;if((a|0)!=(34004+(d>>>3<<1<<2)|0)){if(a>>>0<(c[8495]|0)>>>0)ba();if((c[a+12>>2]|0)!=(n|0))ba()}if((b|0)==(a|0)){c[8491]=c[8491]&~(1<<(d>>>3));break}if((b|0)!=(34004+(d>>>3<<1<<2)|0)){if(b>>>0<(c[8495]|0)>>>0)ba();if((c[b+8>>2]|0)!=(n|0))ba();else l=b+8|0}else l=b+8|0;c[a+12>>2]=b;c[l>>2]=a}while(0);c[q+4>>2]=f|1;c[q+f>>2]=f;if((q|0)==(c[8496]|0)){c[8493]=f;return}}else{c[n+4>>2]=d&-2;c[q+4>>2]=f|1;c[q+f>>2]=f}b=f>>>3;if(f>>>0<256){a=c[8491]|0;if(a&1<<b){a=c[34004+(b<<1<<2)+8>>2]|0;if(a>>>0<(c[8495]|0)>>>0)ba();else{o=a;p=34004+(b<<1<<2)+8|0}}else{c[8491]=a|1<<b;o=34004+(b<<1<<2)|0;p=34004+(b<<1<<2)+8|0}c[p>>2]=q;c[o+12>>2]=q;c[q+8>>2]=o;c[q+12>>2]=34004+(b<<1<<2);return}a=f>>>8;if(a)if(f>>>0>16777215)a=31;else{p=a<<((a+1048320|0)>>>16&8)<<(((a<<((a+1048320|0)>>>16&8))+520192|0)>>>16&4);a=14-(((a<<((a+1048320|0)>>>16&8))+520192|0)>>>16&4|(a+1048320|0)>>>16&8|(p+245760|0)>>>16&2)+(p<<((p+245760|0)>>>16&2)>>>15)|0;a=f>>>(a+7|0)&1|a<<1}else a=0;e=34268+(a<<2)|0;c[q+28>>2]=a;c[q+20>>2]=0;c[q+16>>2]=0;b=c[8492]|0;d=1<<a;do if(b&d){b=f<<((a|0)==31?0:25-(a>>>1)|0);e=c[e>>2]|0;while(1){if((c[e+4>>2]&-8|0)==(f|0)){a=130;break}d=e+16+(b>>>31<<2)|0;a=c[d>>2]|0;if(!a){a=127;break}else{b=b<<1;e=a}}if((a|0)==127)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[d>>2]=q;c[q+24>>2]=e;c[q+12>>2]=q;c[q+8>>2]=q;break}else if((a|0)==130){a=e+8|0;b=c[a>>2]|0;p=c[8495]|0;if(b>>>0>=p>>>0&e>>>0>=p>>>0){c[b+12>>2]=q;c[a>>2]=q;c[q+8>>2]=b;c[q+12>>2]=e;c[q+24>>2]=0;break}else ba()}}else{c[8492]=b|d;c[e>>2]=q;c[q+24>>2]=e;c[q+12>>2]=q;c[q+8>>2]=q}while(0);q=(c[8499]|0)+-1|0;c[8499]=q;if(!q)a=34420;else return;while(1){a=c[a>>2]|0;if(!a)break;else a=a+8|0}c[8499]=-1;return}function ua(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;d=c[a+4>>2]|0;do if(!(d&1)){l=c[a>>2]|0;if(!(d&3))return;j=c[8495]|0;if((a+(0-l)|0)>>>0<j>>>0)ba();if((a+(0-l)|0)==(c[8496]|0)){d=c[a+b+4>>2]|0;if((d&3|0)!=3){q=a+(0-l)|0;h=l+b|0;break}c[8493]=l+b;c[a+b+4>>2]=d&-2;c[a+(0-l)+4>>2]=l+b|1;c[a+(0-l)+(l+b)>>2]=l+b;return}if(l>>>0<256){d=c[a+(0-l)+8>>2]|0;e=c[a+(0-l)+12>>2]|0;if((d|0)!=(34004+(l>>>3<<1<<2)|0)){if(d>>>0<j>>>0)ba();if((c[d+12>>2]|0)!=(a+(0-l)|0))ba()}if((e|0)==(d|0)){c[8491]=c[8491]&~(1<<(l>>>3));q=a+(0-l)|0;h=l+b|0;break}if((e|0)!=(34004+(l>>>3<<1<<2)|0)){if(e>>>0<j>>>0)ba();if((c[e+8>>2]|0)!=(a+(0-l)|0))ba();else f=e+8|0}else f=e+8|0;c[d+12>>2]=e;c[f>>2]=d;q=a+(0-l)|0;h=l+b|0;break}i=c[a+(0-l)+24>>2]|0;d=c[a+(0-l)+12>>2]|0;do if((d|0)==(a+(0-l)|0)){e=a+(0-l)+16|0;d=c[e+4>>2]|0;if(!d){d=c[e>>2]|0;if(!d){k=0;break}}else e=e+4|0;while(1){f=d+20|0;g=c[f>>2]|0;if(g|0){d=g;e=f;continue}f=d+16|0;g=c[f>>2]|0;if(!g)break;else{d=g;e=f}}if(e>>>0<j>>>0)ba();else{c[e>>2]=0;k=d;break}}else{e=c[a+(0-l)+8>>2]|0;if(e>>>0<j>>>0)ba();if((c[e+12>>2]|0)!=(a+(0-l)|0))ba();if((c[d+8>>2]|0)==(a+(0-l)|0)){c[e+12>>2]=d;c[d+8>>2]=e;k=d;break}else ba()}while(0);if(i){d=c[a+(0-l)+28>>2]|0;if((a+(0-l)|0)==(c[34268+(d<<2)>>2]|0)){c[34268+(d<<2)>>2]=k;if(!k){c[8492]=c[8492]&~(1<<d);q=a+(0-l)|0;h=l+b|0;break}}else{if(i>>>0<(c[8495]|0)>>>0)ba();if((c[i+16>>2]|0)==(a+(0-l)|0))c[i+16>>2]=k;else c[i+20>>2]=k;if(!k){q=a+(0-l)|0;h=l+b|0;break}}e=c[8495]|0;if(k>>>0<e>>>0)ba();c[k+24>>2]=i;d=c[a+(0-l)+16>>2]|0;do if(d|0)if(d>>>0<e>>>0)ba();else{c[k+16>>2]=d;c[d+24>>2]=k;break}while(0);d=c[a+(0-l)+16+4>>2]|0;if(d)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[k+20>>2]=d;c[d+24>>2]=k;q=a+(0-l)|0;h=l+b|0;break}else{q=a+(0-l)|0;h=l+b|0}}else{q=a+(0-l)|0;h=l+b|0}}else{q=a;h=b}while(0);j=c[8495]|0;if((a+b|0)>>>0<j>>>0)ba();f=c[a+b+4>>2]|0;if(!(f&2)){if((a+b|0)==(c[8497]|0)){p=(c[8494]|0)+h|0;c[8494]=p;c[8497]=q;c[q+4>>2]=p|1;if((q|0)!=(c[8496]|0))return;c[8496]=0;c[8493]=0;return}if((a+b|0)==(c[8496]|0)){p=(c[8493]|0)+h|0;c[8493]=p;c[8496]=q;c[q+4>>2]=p|1;c[q+p>>2]=p;return}h=(f&-8)+h|0;do if(f>>>0>=256){i=c[a+b+24>>2]|0;d=c[a+b+12>>2]|0;do if((d|0)==(a+b|0)){d=c[a+b+16+4>>2]|0;if(!d){d=c[a+b+16>>2]|0;if(!d){n=0;break}else g=a+b+16|0}else g=a+b+16+4|0;while(1){e=d+20|0;f=c[e>>2]|0;if(f|0){d=f;g=e;continue}e=d+16|0;f=c[e>>2]|0;if(!f)break;else{d=f;g=e}}if(g>>>0<j>>>0)ba();else{c[g>>2]=0;n=d;break}}else{e=c[a+b+8>>2]|0;if(e>>>0<j>>>0)ba();if((c[e+12>>2]|0)!=(a+b|0))ba();if((c[d+8>>2]|0)==(a+b|0)){c[e+12>>2]=d;c[d+8>>2]=e;n=d;break}else ba()}while(0);if(i|0){d=c[a+b+28>>2]|0;if((a+b|0)==(c[34268+(d<<2)>>2]|0)){c[34268+(d<<2)>>2]=n;if(!n){c[8492]=c[8492]&~(1<<d);break}}else{if(i>>>0<(c[8495]|0)>>>0)ba();if((c[i+16>>2]|0)==(a+b|0))c[i+16>>2]=n;else c[i+20>>2]=n;if(!n)break}e=c[8495]|0;if(n>>>0<e>>>0)ba();c[n+24>>2]=i;d=c[a+b+16>>2]|0;do if(d|0)if(d>>>0<e>>>0)ba();else{c[n+16>>2]=d;c[d+24>>2]=n;break}while(0);d=c[a+b+16+4>>2]|0;if(d|0)if(d>>>0<(c[8495]|0)>>>0)ba();else{c[n+20>>2]=d;c[d+24>>2]=n;break}}}else{d=c[a+b+8>>2]|0;e=c[a+b+12>>2]|0;if((d|0)!=(34004+(f>>>3<<1<<2)|0)){if(d>>>0<j>>>0)ba();if((c[d+12>>2]|0)!=(a+b|0))ba()}if((e|0)==(d|0)){c[8491]=c[8491]&~(1<<(f>>>3));break}if((e|0)!=(34004+(f>>>3<<1<<2)|0)){if(e>>>0<j>>>0)ba();if((c[e+8>>2]|0)!=(a+b|0))ba();else m=e+8|0}else m=e+8|0;c[d+12>>2]=e;c[m>>2]=d}while(0);c[q+4>>2]=h|1;c[q+h>>2]=h;if((q|0)==(c[8496]|0)){c[8493]=h;return}}else{c[a+b+4>>2]=f&-2;c[q+4>>2]=h|1;c[q+h>>2]=h}e=h>>>3;if(h>>>0<256){d=c[8491]|0;if(d&1<<e){d=c[34004+(e<<1<<2)+8>>2]|0;if(d>>>0<(c[8495]|0)>>>0)ba();else{o=d;p=34004+(e<<1<<2)+8|0}}else{c[8491]=d|1<<e;o=34004+(e<<1<<2)|0;p=34004+(e<<1<<2)+8|0}c[p>>2]=q;c[o+12>>2]=q;c[q+8>>2]=o;c[q+12>>2]=34004+(e<<1<<2);return}d=h>>>8;if(d)if(h>>>0>16777215)d=31;else{p=d<<((d+1048320|0)>>>16&8)<<(((d<<((d+1048320|0)>>>16&8))+520192|0)>>>16&4);d=14-(((d<<((d+1048320|0)>>>16&8))+520192|0)>>>16&4|(d+1048320|0)>>>16&8|(p+245760|0)>>>16&2)+(p<<((p+245760|0)>>>16&2)>>>15)|0;d=h>>>(d+7|0)&1|d<<1}else d=0;g=34268+(d<<2)|0;c[q+28>>2]=d;c[q+20>>2]=0;c[q+16>>2]=0;e=c[8492]|0;f=1<<d;if(!(e&f)){c[8492]=e|f;c[g>>2]=q;c[q+24>>2]=g;c[q+12>>2]=q;c[q+8>>2]=q;return}e=h<<((d|0)==31?0:25-(d>>>1)|0);g=c[g>>2]|0;while(1){if((c[g+4>>2]&-8|0)==(h|0)){d=127;break}f=g+16+(e>>>31<<2)|0;d=c[f>>2]|0;if(!d){d=124;break}else{e=e<<1;g=d}}if((d|0)==124){if(f>>>0<(c[8495]|0)>>>0)ba();c[f>>2]=q;c[q+24>>2]=g;c[q+12>>2]=q;c[q+8>>2]=q;return}else if((d|0)==127){d=g+8|0;e=c[d>>2]|0;p=c[8495]|0;if(!(e>>>0>=p>>>0&g>>>0>=p>>>0))ba();c[e+12>>2]=q;c[d>>2]=q;c[q+8>>2]=e;c[q+12>>2]=g;c[q+24>>2]=0;return}}function va(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0;V=i;U=i=i+63&-64;i=i+64|0;if(!((g|0)==0&(h|0)==0)){if(h>>>0>63|(h|0)==63&g>>>0>4294967232)ba();G=c[b>>2]|0;H=c[b+4>>2]|0;I=c[b+8>>2]|0;J=c[b+12>>2]|0;K=c[b+16>>2]|0;L=c[b+20>>2]|0;M=c[b+24>>2]|0;N=c[b+28>>2]|0;O=c[b+32>>2]|0;P=c[b+36>>2]|0;Q=c[b+40>>2]|0;R=c[b+44>>2]|0;S=c[b+56>>2]|0;T=c[b+60>>2]|0;j=0;C=c[b+52>>2]|0;A=c[b+48>>2]|0;E=h;F=g;while(1){B=E>>>0<0|(E|0)==0&F>>>0<64;if(B){h=U;g=h+64|0;do{a[h>>0]=0;h=h+1|0}while((h|0)<(g|0));h=0;do{a[U+h>>0]=a[e+h>>0]|0;h=h+1|0}while(0<E>>>0|0==(E|0)&h>>>0<F>>>0);j=f;e=U;f=U}h=G;k=H;l=I;m=J;n=K;o=L;p=M;q=N;r=O;s=P;t=Q;u=T;v=S;w=C;x=A;y=R;g=20;do{na=h+n|0;ca=na^x;aa=(ca<<16|ca>>>16)+r|0;ma=aa^n;ca=(ma<<12|ma>>>20)+na^(ca<<16|ca>>>16);z=(ca<<8|ca>>>24)+aa^(ma<<12|ma>>>20);ja=k+o|0;X=ja^w;W=(X<<16|X>>>16)+s|0;ia=W^o;X=(ia<<12|ia>>>20)+ja^(X<<16|X>>>16);ka=(X<<8|X>>>24)+W^(ia<<12|ia>>>20);ea=l+p|0;Y=ea^v;la=(Y<<16|Y>>>16)+t|0;da=la^p;Y=(da<<12|da>>>20)+ea^(Y<<16|Y>>>16);fa=(Y<<8|Y>>>24)+la^(da<<12|da>>>20);Z=m+q|0;ha=Z^u;ga=(ha<<16|ha>>>16)+y|0;_=ga^q;ha=(_<<12|_>>>20)+Z^(ha<<16|ha>>>16);$=(ha<<8|ha>>>24)+ga^(_<<12|_>>>20);na=(ka<<7|ka>>>25)+((ma<<12|ma>>>20)+na)|0;ma=(na^(ha<<8|ha>>>24))<<16|(na^(ha<<8|ha>>>24))>>>16;ka=ma+((Y<<8|Y>>>24)+la)^(ka<<7|ka>>>25);h=(ka<<12|ka>>>20)+na|0;na=h^ma;u=na<<8|na>>>24;t=u+(ma+((Y<<8|Y>>>24)+la))|0;ka=t^(ka<<12|ka>>>20);o=ka<<7|ka>>>25;ja=(fa<<7|fa>>>25)+((ia<<12|ia>>>20)+ja)|0;ia=(ja^(ca<<8|ca>>>24))<<16|(ja^(ca<<8|ca>>>24))>>>16;fa=ia+((ha<<8|ha>>>24)+ga)^(fa<<7|fa>>>25);k=(fa<<12|fa>>>20)+ja|0;ja=k^ia;x=ja<<8|ja>>>24;y=x+(ia+((ha<<8|ha>>>24)+ga))|0;fa=y^(fa<<12|fa>>>20);p=fa<<7|fa>>>25;ea=($<<7|$>>>25)+((da<<12|da>>>20)+ea)|0;da=(ea^(X<<8|X>>>24))<<16|(ea^(X<<8|X>>>24))>>>16;$=da+((ca<<8|ca>>>24)+aa)^($<<7|$>>>25);l=($<<12|$>>>20)+ea|0;ea=l^da;w=ea<<8|ea>>>24;r=w+(da+((ca<<8|ca>>>24)+aa))|0;$=r^($<<12|$>>>20);q=$<<7|$>>>25;Z=(z<<7|z>>>25)+((_<<12|_>>>20)+Z)|0;Y=(Z^(Y<<8|Y>>>24))<<16|(Z^(Y<<8|Y>>>24))>>>16;z=Y+((X<<8|X>>>24)+W)^(z<<7|z>>>25);m=(z<<12|z>>>20)+Z|0;Z=m^Y;v=Z<<8|Z>>>24;s=v+(Y+((X<<8|X>>>24)+W))|0;z=s^(z<<12|z>>>20);n=z<<7|z>>>25;g=g+-2|0}while((g|0)!=0);z=(d[e>>0]|d[e+1>>0]<<8|d[e+2>>0]<<16|d[e+3>>0]<<24)^h+G;Z=e+4|0;Z=(d[Z>>0]|d[Z+1>>0]<<8|d[Z+2>>0]<<16|d[Z+3>>0]<<24)^k+H;_=e+8|0;_=(d[_>>0]|d[_+1>>0]<<8|d[_+2>>0]<<16|d[_+3>>0]<<24)^l+I;$=e+12|0;$=(d[$>>0]|d[$+1>>0]<<8|d[$+2>>0]<<16|d[$+3>>0]<<24)^m+J;aa=e+16|0;aa=(d[aa>>0]|d[aa+1>>0]<<8|d[aa+2>>0]<<16|d[aa+3>>0]<<24)^n+K;ca=e+20|0;ca=(d[ca>>0]|d[ca+1>>0]<<8|d[ca+2>>0]<<16|d[ca+3>>0]<<24)^o+L;da=e+24|0;da=(d[da>>0]|d[da+1>>0]<<8|d[da+2>>0]<<16|d[da+3>>0]<<24)^p+M;ea=e+28|0;ea=(d[ea>>0]|d[ea+1>>0]<<8|d[ea+2>>0]<<16|d[ea+3>>0]<<24)^q+N;fa=e+32|0;fa=(d[fa>>0]|d[fa+1>>0]<<8|d[fa+2>>0]<<16|d[fa+3>>0]<<24)^r+O;ga=e+36|0;ga=(d[ga>>0]|d[ga+1>>0]<<8|d[ga+2>>0]<<16|d[ga+3>>0]<<24)^s+P;ha=e+40|0;ha=(d[ha>>0]|d[ha+1>>0]<<8|d[ha+2>>0]<<16|d[ha+3>>0]<<24)^t+Q;ia=e+44|0;ia=(d[ia>>0]|d[ia+1>>0]<<8|d[ia+2>>0]<<16|d[ia+3>>0]<<24)^y+R;ja=e+48|0;ja=(d[ja>>0]|d[ja+1>>0]<<8|d[ja+2>>0]<<16|d[ja+3>>0]<<24)^x+A;ka=e+52|0;ka=(d[ka>>0]|d[ka+1>>0]<<8|d[ka+2>>0]<<16|d[ka+3>>0]<<24)^w+C;la=e+56|0;la=(d[la>>0]|d[la+1>>0]<<8|d[la+2>>0]<<16|d[la+3>>0]<<24)^v+S;ma=e+60|0;ma=(d[ma>>0]|d[ma+1>>0]<<8|d[ma+2>>0]<<16|d[ma+3>>0]<<24)^u+T;g=A+1|0;h=((g|0)==0&1)+C|0;a[f>>0]=z;a[f+1>>0]=z>>8;a[f+2>>0]=z>>16;a[f+3>>0]=z>>24;na=f+4|0;a[na>>0]=Z;a[na+1>>0]=Z>>8;a[na+2>>0]=Z>>16;a[na+3>>0]=Z>>24;na=f+8|0;a[na>>0]=_;a[na+1>>0]=_>>8;a[na+2>>0]=_>>16;a[na+3>>0]=_>>24;na=f+12|0;a[na>>0]=$;a[na+1>>0]=$>>8;a[na+2>>0]=$>>16;a[na+3>>0]=$>>24;na=f+16|0;a[na>>0]=aa;a[na+1>>0]=aa>>8;a[na+2>>0]=aa>>16;a[na+3>>0]=aa>>24;na=f+20|0;a[na>>0]=ca;a[na+1>>0]=ca>>8;a[na+2>>0]=ca>>16;a[na+3>>0]=ca>>24;na=f+24|0;a[na>>0]=da;a[na+1>>0]=da>>8;a[na+2>>0]=da>>16;a[na+3>>0]=da>>24;na=f+28|0;a[na>>0]=ea;a[na+1>>0]=ea>>8;a[na+2>>0]=ea>>16;a[na+3>>0]=ea>>24;na=f+32|0;a[na>>0]=fa;a[na+1>>0]=fa>>8;a[na+2>>0]=fa>>16;a[na+3>>0]=fa>>24;na=f+36|0;a[na>>0]=ga;a[na+1>>0]=ga>>8;a[na+2>>0]=ga>>16;a[na+3>>0]=ga>>24;na=f+40|0;a[na>>0]=ha;a[na+1>>0]=ha>>8;a[na+2>>0]=ha>>16;a[na+3>>0]=ha>>24;na=f+44|0;a[na>>0]=ia;a[na+1>>0]=ia>>8;a[na+2>>0]=ia>>16;a[na+3>>0]=ia>>24;na=f+48|0;a[na>>0]=ja;a[na+1>>0]=ja>>8;a[na+2>>0]=ja>>16;a[na+3>>0]=ja>>24;na=f+52|0;a[na>>0]=ka;a[na+1>>0]=ka>>8;a[na+2>>0]=ka>>16;a[na+3>>0]=ka>>24;na=f+56|0;a[na>>0]=la;a[na+1>>0]=la>>8;a[na+2>>0]=la>>16;a[na+3>>0]=la>>24;na=f+60|0;a[na>>0]=ma;a[na+1>>0]=ma>>8;a[na+2>>0]=ma>>16;a[na+3>>0]=ma>>24;if(E>>>0<0|(E|0)==0&F>>>0<65)break;na=oe(F|0,E|0,-64,-1)|0;e=e+64|0;f=f+64|0;C=h;A=g;E=D;F=na}if((B?F|0:0)?(a[j>>0]=z,(F|0)!=1):0){e=1;do{a[j+e>>0]=a[f+e>>0]|0;e=e+1|0}while((e|0)!=(F|0))}c[b+48>>2]=g;c[b+52>>2]=h}i=V;return}function wa(b,e,f){b=b|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0;j=i;k=i=i+63&-64;i=i+320|0;h=k+280|0;g=h+32|0;do{a[h>>0]=a[e>>0]|0;h=h+1|0;e=e+1|0}while((h|0)<(g|0));a[k+280>>0]=(d[k+280>>0]|0)&248;a[k+280+31>>0]=(d[k+280+31>>0]|0)&63|64;ya(k+240|0,f);Ud(k+200|0);re(k+160|0);hc(k+120|0,k+240|0);Ud(k+80|0);e=0;g=254;while(1){B=e;e=(d[k+280+(g>>>3)>>0]|0)>>>(g&7)&1;B=e^B;db(k+200|0,k+120|0,B);db(k+160|0,k+80|0,B);Jb(k+40|0,k+120|0,k+80|0);Jb(k,k+200|0,k+160|0);Kb(k+200|0,k+200|0,k+160|0);Kb(k+160|0,k+120|0,k+80|0);pa(k+80|0,k+40|0,k+200|0);pa(k+160|0,k+160|0,k);ra(k+40|0,k);ra(k,k+200|0);Kb(k+120|0,k+80|0,k+160|0);Jb(k+160|0,k+80|0,k+160|0);pa(k+200|0,k,k+40|0);Jb(k,k,k+40|0);ra(k+160|0,k+160|0);B=c[k>>2]|0;A=c[k+4>>2]|0;z=c[k+8>>2]|0;y=c[k+12>>2]|0;x=c[k+16>>2]|0;s=c[k+20>>2]|0;v=c[k+24>>2]|0;E=c[k+28>>2]|0;t=c[k+32>>2]|0;C=c[k+36>>2]|0;B=Ed(B|0,((B|0)<0)<<31>>31|0,121666,0)|0;q=D;A=Ed(A|0,((A|0)<0)<<31>>31|0,121666,0)|0;r=D;z=Ed(z|0,((z|0)<0)<<31>>31|0,121666,0)|0;o=D;y=Ed(y|0,((y|0)<0)<<31>>31|0,121666,0)|0;p=D;x=Ed(x|0,((x|0)<0)<<31>>31|0,121666,0)|0;m=D;s=Ed(s|0,((s|0)<0)<<31>>31|0,121666,0)|0;n=D;v=Ed(v|0,((v|0)<0)<<31>>31|0,121666,0)|0;f=D;E=Ed(E|0,((E|0)<0)<<31>>31|0,121666,0)|0;l=D;t=Ed(t|0,((t|0)<0)<<31>>31|0,121666,0)|0;u=D;C=Ed(C|0,((C|0)<0)<<31>>31|0,121666,0)|0;h=D;F=oe(C|0,h|0,16777216,0)|0;F=Dd(F|0,D|0,25)|0;w=D;G=Ed(F|0,w|0,19,0)|0;q=oe(G|0,D|0,B|0,q|0)|0;B=D;w=Pd(F|0,w|0,25)|0;w=le(C|0,h|0,w|0,D|0)|0;h=D;C=oe(A|0,r|0,16777216,0)|0;C=Dd(C|0,D|0,25)|0;F=D;o=oe(C|0,F|0,z|0,o|0)|0;z=D;F=Pd(C|0,F|0,25)|0;F=le(A|0,r|0,F|0,D|0)|0;r=D;A=oe(y|0,p|0,16777216,0)|0;A=Dd(A|0,D|0,25)|0;C=D;m=oe(A|0,C|0,x|0,m|0)|0;x=D;C=Pd(A|0,C|0,25)|0;C=le(y|0,p|0,C|0,D|0)|0;p=D;y=oe(s|0,n|0,16777216,0)|0;y=Dd(y|0,D|0,25)|0;A=D;f=oe(y|0,A|0,v|0,f|0)|0;v=D;A=Pd(y|0,A|0,25)|0;A=le(s|0,n|0,A|0,D|0)|0;n=D;s=oe(E|0,l|0,16777216,0)|0;s=Dd(s|0,D|0,25)|0;y=D;u=oe(s|0,y|0,t|0,u|0)|0;t=D;y=Pd(s|0,y|0,25)|0;y=le(E|0,l|0,y|0,D|0)|0;l=D;E=oe(q|0,B|0,33554432,0)|0;E=Dd(E|0,D|0,26)|0;s=D;r=oe(F|0,r|0,E|0,s|0)|0;s=Pd(E|0,s|0,26)|0;s=le(q|0,B|0,s|0,D|0)|0;B=oe(o|0,z|0,33554432,0)|0;B=Dd(B|0,D|0,26)|0;q=D;p=oe(C|0,p|0,B|0,q|0)|0;q=Pd(B|0,q|0,26)|0;q=le(o|0,z|0,q|0,D|0)|0;z=oe(m|0,x|0,33554432,0)|0;z=Dd(z|0,D|0,26)|0;o=D;n=oe(A|0,n|0,z|0,o|0)|0;o=Pd(z|0,o|0,26)|0;o=le(m|0,x|0,o|0,D|0)|0;x=oe(f|0,v|0,33554432,0)|0;x=Dd(x|0,D|0,26)|0;m=D;l=oe(y|0,l|0,x|0,m|0)|0;m=Pd(x|0,m|0,26)|0;m=le(f|0,v|0,m|0,D|0)|0;v=oe(u|0,t|0,33554432,0)|0;v=Dd(v|0,D|0,26)|0;f=D;h=oe(w|0,h|0,v|0,f|0)|0;f=Pd(v|0,f|0,26)|0;f=le(u|0,t|0,f|0,D|0)|0;c[k+80>>2]=s;c[k+80+4>>2]=r;c[k+80+8>>2]=q;c[k+80+12>>2]=p;c[k+80+16>>2]=o;c[k+80+20>>2]=n;c[k+80+24>>2]=m;c[k+80+28>>2]=l;c[k+80+32>>2]=f;c[k+80+36>>2]=h;ra(k+120|0,k+120|0);Kb(k+40|0,k+40|0,k+80|0);pa(k+80|0,k+240|0,k+160|0);pa(k+160|0,k,k+40|0);if((g|0)<=0)break;else g=g+-1|0}db(k+200|0,k+120|0,e);db(k+160|0,k+80|0,e);Ia(k+160|0,k+160|0);pa(k+200|0,k+200|0,k+160|0);La(b,k+200|0);i=j;return 0}function xa(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0;if(!f){H=857760878;I=2036477234;J=1634760805;G=1797285236}else{H=d[f+4>>0]|d[f+4+1>>0]<<8|d[f+4+2>>0]<<16|d[f+4+3>>0]<<24;I=d[f+8>>0]|d[f+8+1>>0]<<8|d[f+8+2>>0]<<16|d[f+8+3>>0]<<24;J=d[f>>0]|d[f+1>>0]<<8|d[f+2>>0]<<16|d[f+3>>0]<<24;G=d[f+12>>0]|d[f+12+1>>0]<<8|d[f+12+2>>0]<<16|d[f+12+3>>0]<<24}F=d[e>>0]|d[e+1>>0]<<8|d[e+2>>0]<<16|d[e+3>>0]<<24;E=d[e+4>>0]|d[e+4+1>>0]<<8|d[e+4+2>>0]<<16|d[e+4+3>>0]<<24;D=d[e+8>>0]|d[e+8+1>>0]<<8|d[e+8+2>>0]<<16|d[e+8+3>>0]<<24;C=d[e+12>>0]|d[e+12+1>>0]<<8|d[e+12+2>>0]<<16|d[e+12+3>>0]<<24;B=d[c>>0]|d[c+1>>0]<<8|d[c+2>>0]<<16|d[c+3>>0]<<24;A=d[c+4>>0]|d[c+4+1>>0]<<8|d[c+4+2>>0]<<16|d[c+4+3>>0]<<24;z=d[c+8>>0]|d[c+8+1>>0]<<8|d[c+8+2>>0]<<16|d[c+8+3>>0]<<24;y=d[c+12>>0]|d[c+12+1>>0]<<8|d[c+12+2>>0]<<16|d[c+12+3>>0]<<24;x=d[e+16>>0]|d[e+16+1>>0]<<8|d[e+16+2>>0]<<16|d[e+16+3>>0]<<24;w=d[e+20>>0]|d[e+20+1>>0]<<8|d[e+20+2>>0]<<16|d[e+20+3>>0]<<24;v=d[e+24>>0]|d[e+24+1>>0]<<8|d[e+24+2>>0]<<16|d[e+24+3>>0]<<24;f=d[e+28>>0]|d[e+28+1>>0]<<8|d[e+28+2>>0]<<16|d[e+28+3>>0]<<24;c=F;e=E;g=D;h=C;i=B;j=A;k=z;l=y;m=x;n=f;o=v;p=w;q=20;r=H;s=I;t=G;u=J;while(1){T=u+p|0;T=(T>>>25|T<<7)^h;Q=T+u|0;Q=(Q>>>23|Q<<9)^k;N=((Q+T|0)>>>19|Q+T<<13)^p;W=((N+Q|0)>>>14|N+Q<<18)^u;P=c+r|0;P=(P>>>25|P<<7)^l;M=P+r|0;M=(M>>>23|M<<9)^o;Z=((M+P|0)>>>19|M+P<<13)^c;S=((Z+M|0)>>>14|Z+M<<18)^r;L=i+s|0;L=(L>>>25|L<<7)^n;Y=L+s|0;Y=(Y>>>23|Y<<9)^e;V=((Y+L|0)>>>19|Y+L<<13)^i;O=((V+Y|0)>>>14|V+Y<<18)^s;X=m+t|0;X=g^(X>>>25|X<<7);U=X+t|0;U=(U>>>23|U<<9)^j;R=((U+X|0)>>>19|U+X<<13)^m;K=((R+U|0)>>>14|R+U<<18)^t;c=((W+X|0)>>>25|W+X<<7)^Z;Z=c+W|0;e=(Z>>>23|Z<<9)^Y;Y=e+c|0;g=(Y>>>19|Y<<13)^X;X=g+e|0;u=(X>>>14|X<<18)^W;i=((S+T|0)>>>25|S+T<<7)^V;V=i+S|0;j=(V>>>23|V<<9)^U;U=j+i|0;h=(U>>>19|U<<13)^T;T=h+j|0;r=(T>>>14|T<<18)^S;m=((O+P|0)>>>25|O+P<<7)^R;R=m+O|0;k=(R>>>23|R<<9)^Q;Q=k+m|0;l=(Q>>>19|Q<<13)^P;P=l+k|0;s=(P>>>14|P<<18)^O;p=((K+L|0)>>>25|K+L<<7)^N;N=p+K|0;o=(N>>>23|N<<9)^M;M=o+p|0;n=(M>>>19|M<<13)^L;L=n+o|0;t=(L>>>14|L<<18)^K;if((q|0)<=2)break;else q=q+-2|0}K=u+J|0;L=c+F|0;M=e+E|0;N=g+D|0;O=h+C|0;P=r+H|0;Q=i+B|0;R=j+A|0;S=k+z|0;T=l+y|0;U=s+I|0;V=m+x|0;W=p+w|0;X=o+v|0;Y=n+f|0;Z=t+G|0;a[b>>0]=K;a[b+1>>0]=K>>8;a[b+2>>0]=K>>16;a[b+3>>0]=K>>24;a[b+4>>0]=L;a[b+4+1>>0]=L>>8;a[b+4+2>>0]=L>>16;a[b+4+3>>0]=L>>24;a[b+8>>0]=M;a[b+8+1>>0]=M>>8;a[b+8+2>>0]=M>>16;a[b+8+3>>0]=M>>24;a[b+12>>0]=N;a[b+12+1>>0]=N>>8;a[b+12+2>>0]=N>>16;a[b+12+3>>0]=N>>24;a[b+16>>0]=O;a[b+16+1>>0]=O>>8;a[b+16+2>>0]=O>>16;a[b+16+3>>0]=O>>24;a[b+20>>0]=P;a[b+20+1>>0]=P>>8;a[b+20+2>>0]=P>>16;a[b+20+3>>0]=P>>24;a[b+24>>0]=Q;a[b+24+1>>0]=Q>>8;a[b+24+2>>0]=Q>>16;a[b+24+3>>0]=Q>>24;a[b+28>>0]=R;a[b+28+1>>0]=R>>8;a[b+28+2>>0]=R>>16;a[b+28+3>>0]=R>>24;a[b+32>>0]=S;a[b+32+1>>0]=S>>8;a[b+32+2>>0]=S>>16;a[b+32+3>>0]=S>>24;a[b+36>>0]=T;a[b+36+1>>0]=T>>8;a[b+36+2>>0]=T>>16;a[b+36+3>>0]=T>>24;a[b+40>>0]=U;a[b+40+1>>0]=U>>8;a[b+40+2>>0]=U>>16;a[b+40+3>>0]=U>>24;a[b+44>>0]=V;a[b+44+1>>0]=V>>8;a[b+44+2>>0]=V>>16;a[b+44+3>>0]=V>>24;a[b+48>>0]=W;a[b+48+1>>0]=W>>8;a[b+48+2>>0]=W>>16;a[b+48+3>>0]=W>>24;a[b+52>>0]=X;a[b+52+1>>0]=X>>8;a[b+52+2>>0]=X>>16;a[b+52+3>>0]=X>>24;a[b+56>>0]=Y;a[b+56+1>>0]=Y>>8;a[b+56+2>>0]=Y>>16;a[b+56+3>>0]=Y>>24;a[b+60>>0]=Z;a[b+60+1>>0]=Z>>8;a[b+60+2>>0]=Z>>16;a[b+60+3>>0]=Z>>24;return 0}function ya(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,E=0,F=0,G=0,H=0,I=0,J=0;J=d[b>>0]|0;h=Pd(d[b+1>>0]|0|0,0,8)|0;k=D;F=Pd(d[b+2>>0]|0|0,0,16)|0;k=k|D;E=Pd(d[b+3>>0]|0|0,0,24)|0;k=k|D;B=d[b+4>>0]|0;C=Pd(d[b+5>>0]|0|0,0,8)|0;j=D;l=Pd(d[b+6>>0]|0|0,0,16)|0;j=Pd(C|B|l|0,j|D|0,6)|0;l=D;B=d[b+7>>0]|0;C=Pd(d[b+8>>0]|0|0,0,8)|0;w=D;i=Pd(d[b+9>>0]|0|0,0,16)|0;w=Pd(C|B|i|0,w|D|0,5)|0;i=D;B=d[b+10>>0]|0;C=Pd(d[b+11>>0]|0|0,0,8)|0;H=D;G=Pd(d[b+12>>0]|0|0,0,16)|0;H=Pd(C|B|G|0,H|D|0,3)|0;G=D;B=d[b+13>>0]|0;C=Pd(d[b+14>>0]|0|0,0,8)|0;s=D;g=Pd(d[b+15>>0]|0|0,0,16)|0;s=Pd(C|B|g|0,s|D|0,2)|0;g=D;B=d[b+16>>0]|0;C=Pd(d[b+17>>0]|0|0,0,8)|0;y=D;A=Pd(d[b+18>>0]|0|0,0,16)|0;y=y|D;z=Pd(d[b+19>>0]|0|0,0,24)|0;y=y|D;q=d[b+20>>0]|0;x=Pd(d[b+21>>0]|0|0,0,8)|0;p=D;e=Pd(d[b+22>>0]|0|0,0,16)|0;p=Pd(x|q|e|0,p|D|0,7)|0;e=D;q=d[b+23>>0]|0;x=Pd(d[b+24>>0]|0|0,0,8)|0;v=D;u=Pd(d[b+25>>0]|0|0,0,16)|0;v=Pd(x|q|u|0,v|D|0,5)|0;u=D;q=d[b+26>>0]|0;x=Pd(d[b+27>>0]|0|0,0,8)|0;n=D;o=Pd(d[b+28>>0]|0|0,0,16)|0;n=Pd(x|q|o|0,n|D|0,4)|0;o=D;q=d[b+29>>0]|0;x=Pd(d[b+30>>0]|0|0,0,8)|0;r=D;b=Pd(d[b+31>>0]|0|0,0,16)|0;r=Pd(x|q|b|0,r|D|0,2)|0;b=oe(r&33554428|0,0,16777216,0)|0;b=Rd(b|0,D|0,25)|0;q=D;x=le(0,0,b|0,q|0)|0;k=oe(x&19|0,0,h|J|F|E|0,k|0)|0;E=D;q=Pd(b|0,q|0,25)|0;b=D;F=oe(j|0,l|0,16777216,0)|0;F=Rd(F|0,D|0,25)|0;J=D;i=oe(w|0,i|0,F|0,J|0)|0;w=D;J=Pd(F|0,J|0,25)|0;J=le(j|0,l|0,J|0,D|0)|0;l=D;j=oe(H|0,G|0,16777216,0)|0;j=Rd(j|0,D|0,25)|0;F=D;g=oe(s|0,g|0,j|0,F|0)|0;s=D;F=Pd(j|0,F|0,25)|0;j=D;h=oe(C|B|A|z|0,y|0,16777216,0)|0;h=Rd(h|0,D|0,25)|0;x=D;e=oe(p|0,e|0,h|0,x|0)|0;p=D;x=Pd(h|0,x|0,25)|0;h=D;f=oe(v|0,u|0,16777216,0)|0;f=Rd(f|0,D|0,25)|0;t=D;o=oe(n|0,o|0,f|0,t|0)|0;n=D;t=Pd(f|0,t|0,25)|0;f=D;I=oe(k|0,E|0,33554432,0)|0;I=Dd(I|0,D|0,26)|0;m=D;l=oe(J|0,l|0,I|0,m|0)|0;m=Pd(I|0,m|0,26)|0;m=le(k|0,E|0,m|0,D|0)|0;E=oe(i|0,w|0,33554432,0)|0;E=Dd(E|0,D|0,26)|0;k=D;G=oe(E|0,k|0,H|0,G|0)|0;j=le(G|0,D|0,F|0,j|0)|0;k=Pd(E|0,k|0,26)|0;k=le(i|0,w|0,k|0,D|0)|0;w=oe(g|0,s|0,33554432,0)|0;w=Dd(w|0,D|0,26)|0;i=D;y=oe(w|0,i|0,C|B|A|z|0,y|0)|0;h=le(y|0,D|0,x|0,h|0)|0;i=Pd(w|0,i|0,26)|0;i=le(g|0,s|0,i|0,D|0)|0;s=oe(e|0,p|0,33554432,0)|0;s=Dd(s|0,D|0,26)|0;g=D;u=oe(s|0,g|0,v|0,u|0)|0;f=le(u|0,D|0,t|0,f|0)|0;g=Pd(s|0,g|0,26)|0;g=le(e|0,p|0,g|0,D|0)|0;p=oe(o|0,n|0,33554432,0)|0;p=Dd(p|0,D|0,26)|0;e=D;r=oe(r&33554428|0,0,p|0,e|0)|0;b=le(r|0,D|0,q|0,b|0)|0;e=Pd(p|0,e|0,26)|0;e=le(o|0,n|0,e|0,D|0)|0;c[a>>2]=m;c[a+4>>2]=l;c[a+8>>2]=k;c[a+12>>2]=j;c[a+16>>2]=i;c[a+20>>2]=h;c[a+24>>2]=g;c[a+28>>2]=f;c[a+32>>2]=e;c[a+36>>2]=b;return}function za(a,b){a=a|0;b=b|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0;r=i;p=i=i+63&-64;i=i+240|0;ya(a+40|0,b);c[a+80>>2]=1;e=a+84|0;f=e+36|0;do{c[e>>2]=0;e=e+4|0}while((e|0)<(f|0));ra(p+160|0,a+40|0);pa(p+120|0,p+160|0,464);g=c[a+80>>2]|0;f=c[a+84>>2]|0;e=c[a+88>>2]|0;o=c[a+92>>2]|0;n=c[a+96>>2]|0;m=c[a+100>>2]|0;l=c[a+104>>2]|0;k=c[a+108>>2]|0;j=c[a+112>>2]|0;h=c[a+116>>2]|0;B=(c[p+160>>2]|0)-g|0;A=(c[p+160+4>>2]|0)-f|0;z=(c[p+160+8>>2]|0)-e|0;y=(c[p+160+12>>2]|0)-o|0;x=(c[p+160+16>>2]|0)-n|0;w=(c[p+160+20>>2]|0)-m|0;v=(c[p+160+24>>2]|0)-l|0;u=(c[p+160+28>>2]|0)-k|0;t=(c[p+160+32>>2]|0)-j|0;s=(c[p+160+36>>2]|0)-h|0;c[p+160>>2]=B;c[p+160+4>>2]=A;c[p+160+8>>2]=z;c[p+160+12>>2]=y;c[p+160+16>>2]=x;c[p+160+20>>2]=w;c[p+160+24>>2]=v;c[p+160+28>>2]=u;c[p+160+32>>2]=t;c[p+160+36>>2]=s;f=f+(c[p+120+4>>2]|0)|0;e=e+(c[p+120+8>>2]|0)|0;o=o+(c[p+120+12>>2]|0)|0;n=n+(c[p+120+16>>2]|0)|0;m=m+(c[p+120+20>>2]|0)|0;l=l+(c[p+120+24>>2]|0)|0;k=k+(c[p+120+28>>2]|0)|0;j=j+(c[p+120+32>>2]|0)|0;h=h+(c[p+120+36>>2]|0)|0;c[p+120>>2]=g+(c[p+120>>2]|0);c[p+120+4>>2]=f;c[p+120+8>>2]=e;c[p+120+12>>2]=o;c[p+120+16>>2]=n;c[p+120+20>>2]=m;c[p+120+24>>2]=l;c[p+120+28>>2]=k;c[p+120+32>>2]=j;c[p+120+36>>2]=h;ra(p+80|0,p+120|0);pa(p+80|0,p+80|0,p+120|0);ra(a,p+80|0);pa(a,a,p+120|0);pa(a,a,p+160|0);Ka(a,a);pa(a,a,p+80|0);pa(a,a,p+160|0);ra(p+40|0,a);pa(p+40|0,p+40|0,p+120|0);h=c[p+40>>2]|0;j=c[p+40+4>>2]|0;k=c[p+40+8>>2]|0;l=c[p+40+12>>2]|0;m=c[p+40+16>>2]|0;n=c[p+40+20>>2]|0;o=c[p+40+24>>2]|0;e=c[p+40+28>>2]|0;f=c[p+40+32>>2]|0;g=c[p+40+36>>2]|0;c[p>>2]=h-B;c[p+4>>2]=j-A;c[p+8>>2]=k-z;c[p+12>>2]=l-y;c[p+16>>2]=m-x;c[p+20>>2]=n-w;c[p+24>>2]=o-v;c[p+28>>2]=e-u;c[p+32>>2]=f-t;c[p+36>>2]=g-s;La(p+200|0,p);if(zd(p+200|0,34492)|0){t=(c[p+160+4>>2]|0)+j|0;u=(c[p+160+8>>2]|0)+k|0;v=(c[p+160+12>>2]|0)+l|0;w=(c[p+160+16>>2]|0)+m|0;x=(c[p+160+20>>2]|0)+n|0;y=(c[p+160+24>>2]|0)+o|0;z=(c[p+160+28>>2]|0)+e|0;A=(c[p+160+32>>2]|0)+f|0;B=(c[p+160+36>>2]|0)+g|0;c[p>>2]=(c[p+160>>2]|0)+h;c[p+4>>2]=t;c[p+8>>2]=u;c[p+12>>2]=v;c[p+16>>2]=w;c[p+20>>2]=x;c[p+24>>2]=y;c[p+28>>2]=z;c[p+32>>2]=A;c[p+36>>2]=B;La(p+200|0,p);if(!(zd(p+200|0,34492)|0)){pa(a,a,504);q=4}else e=-1}else q=4;if((q|0)==4){La(p+200|0,a);if(((d[p+200>>0]|0)&1|0)==((d[b+31>>0]|0)>>>7|0))$b(a,a);pa(a+120|0,a,a+40|0);e=0}i=r;return e|0}function Aa(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0;if(!f){o=1797285236;g=2036477234;h=857760878;f=1634760805}else{o=d[f+12>>0]|d[f+12+1>>0]<<8|d[f+12+2>>0]<<16|d[f+12+3>>0]<<24;g=d[f+8>>0]|d[f+8+1>>0]<<8|d[f+8+2>>0]<<16|d[f+8+3>>0]<<24;h=d[f+4>>0]|d[f+4+1>>0]<<8|d[f+4+2>>0]<<16|d[f+4+3>>0]<<24;f=d[f>>0]|d[f+1>>0]<<8|d[f+2>>0]<<16|d[f+3>>0]<<24}p=d[e+28>>0]|d[e+28+1>>0]<<8|d[e+28+2>>0]<<16|d[e+28+3>>0]<<24;q=d[e+24>>0]|d[e+24+1>>0]<<8|d[e+24+2>>0]<<16|d[e+24+3>>0]<<24;r=d[e+20>>0]|d[e+20+1>>0]<<8|d[e+20+2>>0]<<16|d[e+20+3>>0]<<24;s=d[e+16>>0]|d[e+16+1>>0]<<8|d[e+16+2>>0]<<16|d[e+16+3>>0]<<24;t=d[c+12>>0]|d[c+12+1>>0]<<8|d[c+12+2>>0]<<16|d[c+12+3>>0]<<24;u=d[c+8>>0]|d[c+8+1>>0]<<8|d[c+8+2>>0]<<16|d[c+8+3>>0]<<24;v=d[c+4>>0]|d[c+4+1>>0]<<8|d[c+4+2>>0]<<16|d[c+4+3>>0]<<24;k=d[c>>0]|d[c+1>>0]<<8|d[c+2>>0]<<16|d[c+3>>0]<<24;l=d[e+12>>0]|d[e+12+1>>0]<<8|d[e+12+2>>0]<<16|d[e+12+3>>0]<<24;m=d[e+8>>0]|d[e+8+1>>0]<<8|d[e+8+2>>0]<<16|d[e+8+3>>0]<<24;n=d[e+4>>0]|d[e+4+1>>0]<<8|d[e+4+2>>0]<<16|d[e+4+3>>0]<<24;i=d[e>>0]|d[e+1>>0]<<8|d[e+2>>0]<<16|d[e+3>>0]<<24;j=20;e=h;c=f;f=o;while(1){D=r+c|0;D=(D>>>25|D<<7)^l;A=D+c|0;A=(A>>>23|A<<9)^u;x=((A+D|0)>>>19|A+D<<13)^r;G=((x+A|0)>>>14|x+A<<18)^c;z=e+i|0;z=t^(z>>>25|z<<7);w=z+e|0;w=q^(w>>>23|w<<9);J=((w+z|0)>>>19|w+z<<13)^i;C=((J+w|0)>>>14|J+w<<18)^e;h=g+k|0;h=p^(h>>>25|h<<7);I=h+g|0;I=(I>>>23|I<<9)^n;F=((I+h|0)>>>19|I+h<<13)^k;y=((F+I|0)>>>14|F+I<<18)^g;H=f+s|0;H=(H>>>25|H<<7)^m;E=H+f|0;E=(E>>>23|E<<9)^v;B=((E+H|0)>>>19|E+H<<13)^s;o=((B+E|0)>>>14|B+E<<18)^f;i=((G+H|0)>>>25|G+H<<7)^J;J=i+G|0;n=(J>>>23|J<<9)^I;I=n+i|0;m=(I>>>19|I<<13)^H;H=m+n|0;c=(H>>>14|H<<18)^G;k=((C+D|0)>>>25|C+D<<7)^F;F=k+C|0;v=(F>>>23|F<<9)^E;E=v+k|0;l=(E>>>19|E<<13)^D;D=l+v|0;e=(D>>>14|D<<18)^C;s=((y+z|0)>>>25|y+z<<7)^B;B=s+y|0;u=(B>>>23|B<<9)^A;A=u+s|0;t=(A>>>19|A<<13)^z;z=t+u|0;g=(z>>>14|z<<18)^y;r=((o+h|0)>>>25|o+h<<7)^x;x=r+o|0;q=(x>>>23|x<<9)^w;w=q+r|0;p=(w>>>19|w<<13)^h;h=p+q|0;f=(h>>>14|h<<18)^o;if((j|0)<=2)break;else j=j+-2|0}a[b>>0]=c;a[b+1>>0]=c>>8;a[b+2>>0]=c>>16;a[b+3>>0]=c>>24;a[b+4>>0]=e;a[b+4+1>>0]=e>>8;a[b+4+2>>0]=e>>16;a[b+4+3>>0]=e>>24;a[b+8>>0]=g;a[b+8+1>>0]=g>>8;a[b+8+2>>0]=g>>16;a[b+8+3>>0]=g>>24;a[b+12>>0]=f;a[b+12+1>>0]=f>>8;a[b+12+2>>0]=f>>16;a[b+12+3>>0]=f>>24;a[b+16>>0]=k;a[b+16+1>>0]=k>>8;a[b+16+2>>0]=k>>16;a[b+16+3>>0]=k>>24;a[b+20>>0]=v;a[b+20+1>>0]=v>>8;a[b+20+2>>0]=v>>16;a[b+20+3>>0]=v>>24;a[b+24>>0]=u;a[b+24+1>>0]=u>>8;a[b+24+2>>0]=u>>16;a[b+24+3>>0]=u>>24;a[b+28>>0]=t;a[b+28+1>>0]=t>>8;a[b+28+2>>0]=t>>16;a[b+28+3>>0]=t>>24;return 0}function Ba(b,e,f,g){b=b|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0;t=a[b+80>>0]|0?0:16777216;u=c[b+4>>2]|0;p=c[b+8>>2]|0;q=c[b+12>>2]|0;r=c[b+16>>2]|0;l=c[b+20>>2]|0;k=c[b+24>>2]|0;j=c[b+28>>2]|0;i=c[b+32>>2]|0;h=c[b+36>>2]|0;if(g>>>0>0|(g|0)==0&f>>>0>15){s=c[b>>2]|0;n=f;while(1){z=((d[e>>0]|d[e+1>>0]<<8|d[e+2>>0]<<16|d[e+3>>0]<<24)&67108863)+l|0;A=e+3|0;A=((d[A>>0]|d[A+1>>0]<<8|d[A+2>>0]<<16|d[A+3>>0]<<24)>>>2&67108863)+k|0;y=e+6|0;y=((d[y>>0]|d[y+1>>0]<<8|d[y+2>>0]<<16|d[y+3>>0]<<24)>>>4&67108863)+j|0;x=e+9|0;x=((d[x>>0]|d[x+1>>0]<<8|d[x+2>>0]<<16|d[x+3>>0]<<24)>>>6)+i|0;l=e+12|0;l=((d[l>>0]|d[l+1>>0]<<8|d[l+2>>0]<<16|d[l+3>>0]<<24)>>>8|t)+h|0;h=Ed(z|0,0,s|0,0)|0;f=D;j=Ed(A|0,0,r*5|0,0)|0;f=oe(j|0,D|0,h|0,f|0)|0;h=D;j=Ed(y|0,0,q*5|0,0)|0;j=oe(f|0,h|0,j|0,D|0)|0;h=D;f=Ed(x|0,0,p*5|0,0)|0;f=oe(j|0,h|0,f|0,D|0)|0;h=D;j=Ed(l|0,0,u*5|0,0)|0;j=oe(f|0,h|0,j|0,D|0)|0;h=D;f=Ed(z|0,0,u|0,0)|0;m=D;w=Ed(A|0,0,s|0,0)|0;m=oe(w|0,D|0,f|0,m|0)|0;f=D;w=Ed(y|0,0,r*5|0,0)|0;w=oe(m|0,f|0,w|0,D|0)|0;f=D;m=Ed(x|0,0,q*5|0,0)|0;m=oe(w|0,f|0,m|0,D|0)|0;f=D;w=Ed(l|0,0,p*5|0,0)|0;w=oe(m|0,f|0,w|0,D|0)|0;f=D;m=Ed(z|0,0,p|0,0)|0;o=D;v=Ed(A|0,0,u|0,0)|0;o=oe(v|0,D|0,m|0,o|0)|0;m=D;v=Ed(y|0,0,s|0,0)|0;v=oe(o|0,m|0,v|0,D|0)|0;m=D;o=Ed(x|0,0,r*5|0,0)|0;o=oe(v|0,m|0,o|0,D|0)|0;m=D;v=Ed(l|0,0,q*5|0,0)|0;v=oe(o|0,m|0,v|0,D|0)|0;m=D;o=Ed(z|0,0,q|0,0)|0;i=D;k=Ed(A|0,0,p|0,0)|0;i=oe(k|0,D|0,o|0,i|0)|0;o=D;k=Ed(y|0,0,u|0,0)|0;k=oe(i|0,o|0,k|0,D|0)|0;o=D;i=Ed(x|0,0,s|0,0)|0;i=oe(k|0,o|0,i|0,D|0)|0;o=D;k=Ed(l|0,0,r*5|0,0)|0;k=oe(i|0,o|0,k|0,D|0)|0;o=D;i=Ed(z|0,0,r|0,0)|0;z=D;A=Ed(A|0,0,q|0,0)|0;z=oe(A|0,D|0,i|0,z|0)|0;i=D;y=Ed(y|0,0,p|0,0)|0;y=oe(z|0,i|0,y|0,D|0)|0;i=D;x=Ed(x|0,0,u|0,0)|0;x=oe(y|0,i|0,x|0,D|0)|0;i=D;l=Ed(l|0,0,s|0,0)|0;l=oe(x|0,i|0,l|0,D|0)|0;i=D;h=Rd(j|0,h|0,26)|0;h=oe(w|0,f|0,h|0,0)|0;f=Rd(h|0,D|0,26)|0;f=oe(v|0,m|0,f|0,0)|0;m=Rd(f|0,D|0,26)|0;m=oe(k|0,o|0,m|0,0)|0;o=Rd(m|0,D|0,26)|0;o=oe(l|0,i|0,o|0,0)|0;i=Rd(o|0,D|0,26)|0;n=oe(n|0,g|0,-16,-1)|0;g=D;if(!(g>>>0>0|(g|0)==0&n>>>0>15)){l=(i*5|0)+j&67108863;k=(((i*5|0)+(j&67108863)|0)>>>26)+(h&67108863)|0;j=f&67108863;i=m&67108863;h=o&67108863;break}else{l=(i*5|0)+j&67108863;k=(((i*5|0)+(j&67108863)|0)>>>26)+(h&67108863)|0;j=f&67108863;i=m&67108863;h=o&67108863;e=e+16|0}}}c[b+20>>2]=l;c[b+24>>2]=k;c[b+28>>2]=j;c[b+32>>2]=i;c[b+36>>2]=h;return}function Ca(b,e,f,g,h,i,j,k,l,m,n){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;var o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;v=Ed(l|0,0,k|0,0)|0;u=D;do if(u>>>0>0|(u|0)==0&v>>>0>1073741823){c[(Zf()|0)>>2]=27;b=-1}else{if(j>>>0>0|(j|0)==0&i>>>0>4294967295){c[(Zf()|0)>>2]=27;b=-1;break}u=oe(i|0,j|0,-1,-1)|0;if(j>>>0<0|(j|0)==0&i>>>0<2|((u&i|0)!=0|(D&j|0)!=0)){c[(Zf()|0)>>2]=22;b=-1;break}if((k|0)==0|(l|0)==0){c[(Zf()|0)>>2]=22;b=-1;break}if(!(k>>>0>16777215?1:(33554431/(l>>>0)|0)>>>0<k>>>0)?!(0<j>>>0|(0==(j|0)?(33554431/(k>>>0)|0)>>>0<i>>>0:0)):0){v=S(k<<7,l)|0;p=Ed(k<<7|0,0,i|0,j|0)|0;if((p+v|0)>>>0<p>>>0){c[(Zf()|0)>>2]=12;b=-1;break}o=p+v+(k<<8|64)|0;if(o>>>0<(k<<8|64)>>>0){c[(Zf()|0)>>2]=12;b=-1;break}if((c[b+8>>2]|0)>>>0<o>>>0?(je(b),(Nc(b,o)|0)==0):0){b=-1;break}t=c[b+4>>2]|0;s=t+v+p|0;Tb(e,f,g,h,t,v);q=s+(k<<5<<2)|0;h=0;do{r=t+(S(k<<7,h)|0)|0;if(k<<5|0){b=0;do{g=r+(b<<2)|0;c[s+(b<<2)>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;b=b+1|0}while((b|0)!=(k<<5|0))}if(!((i|0)==0&(j|0)==0)){p=0;g=0;do{if(!(k<<5&1073741792))wb(s,q,s+(k<<6<<2)|0,k);else{o=Ed(p|0,g|0,k<<5|0,0)|0;b=0;do{c[t+v+(o<<2)+(b<<2)>>2]=c[s+(b<<2)>>2];b=b+1|0}while((b|0)!=(k<<5&1073741792|0));wb(s,q,s+(k<<6<<2)|0,k);o=Ed(p|1|0,g|0,k<<5|0,0)|0;b=0;do{c[t+v+(o<<2)+(b<<2)>>2]=c[q+(b<<2)>>2];b=b+1|0}while((b|0)!=(k<<5&1073741792|0))}wb(q,s,s+(k<<6<<2)|0,k);p=oe(p|0,g|0,2,0)|0;g=D}while(g>>>0<j>>>0|(g|0)==(j|0)&p>>>0<i>>>0);p=0;g=0;do{if(!(k<<5&1073741792))wb(s,q,s+(k<<6<<2)|0,k);else{o=Ed(c[s+((k<<7)+-64)>>2]&u|0,0,k<<5|0,0)|0;b=0;do{w=s+(b<<2)|0;c[w>>2]=c[w>>2]^c[t+v+(o<<2)+(b<<2)>>2];b=b+1|0}while((b|0)!=(k<<5&1073741792|0));wb(s,q,s+(k<<6<<2)|0,k);o=Ed(c[q+((k<<7)+-64)>>2]&u|0,0,k<<5|0,0)|0;b=0;do{w=q+(b<<2)|0;c[w>>2]=c[w>>2]^c[t+v+(o<<2)+(b<<2)>>2];b=b+1|0}while((b|0)!=(k<<5&1073741792|0))}wb(q,s,s+(k<<6<<2)|0,k);p=oe(p|0,g|0,2,0)|0;g=D}while(g>>>0<j>>>0|(g|0)==(j|0)&p>>>0<i>>>0)}if(k<<5|0){b=0;do{w=r+(b<<2)|0;g=c[s+(b<<2)>>2]|0;a[w>>0]=g;a[w+1>>0]=g>>8;a[w+2>>0]=g>>16;a[w+3>>0]=g>>24;b=b+1|0}while((b|0)!=(k<<5|0))}h=h+1|0}while((h|0)!=(l|0));Tb(e,f,t,v,m,n);b=0;break}c[(Zf()|0)>>2]=12;b=-1}while(0);return b|0}function Da(e,f,g){e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;r=i;o=i=i+63&-64;i=i+32|0;do if(f>>>0>=12){h=e;j=32952;k=h+12|0;do{a[h>>0]=a[j>>0]|0;h=h+1|0;j=j+1|0}while((h|0)<(k|0));h=jb(g)|0;if(!h){a[o+12+9>>0]=57;a[o+12+8>>0]=49;b[o>>1]=d[o+12+8>>0]|d[o+12+8+1>>0]<<8;a[o+2>>0]=0;l=kc(o)|0;m=e+11+l|0;if((f+-11|0)>>>0<=l>>>0){h=-31;break}tc(e+11|0,o|0,l+1|0)|0;if((f+-11-l|0)>>>0>=4){a[m>>0]=36;a[m+1>>0]=109;a[m+2>>0]=61;a[m+3>>0]=0;h=10;j=c[g+44>>2]|0;while(1){k=h+-1|0;a[o+12+k>>0]=(j>>>0)%10|0|48;if(j>>>0>9&(k|0)!=0){h=k;j=(j>>>0)/10|0}else break}h=11-h|0;tc(o|0,o+12+k|0,h|0)|0;a[o+h>>0]=0;h=kc(o)|0;e=m+3+h|0;n=f+-11-l+-3-h|0;if((f+-11-l+-3|0)>>>0<=h>>>0){h=-31;break}tc(m+3|0,o|0,h+1|0)|0;if(n>>>0>=4){a[e>>0]=44;a[e+1>>0]=116;a[e+2>>0]=61;a[e+3>>0]=0;h=10;j=c[g+40>>2]|0;while(1){k=h+-1|0;a[o+12+k>>0]=(j>>>0)%10|0|48;if(j>>>0>9&(k|0)!=0){h=k;j=(j>>>0)/10|0}else break}l=11-h|0;tc(o|0,o+12+k|0,l|0)|0;a[o+l>>0]=0;l=kc(o)|0;m=e+3+l|0;if((n+-3|0)>>>0<=l>>>0){h=-31;break}tc(e+3|0,o|0,l+1|0)|0;if((n+-3-l|0)>>>0>=4){a[m>>0]=44;a[m+1>>0]=112;a[m+2>>0]=61;a[m+3>>0]=0;h=10;j=c[g+48>>2]|0;while(1){k=h+-1|0;a[o+12+k>>0]=(j>>>0)%10|0|48;if(j>>>0>9&(k|0)!=0){h=k;j=(j>>>0)/10|0}else break}j=11-h|0;tc(o|0,o+12+k|0,j|0)|0;a[o+j>>0]=0;j=kc(o)|0;e=m+3+j|0;h=n+-3-l+-3-j|0;if((n+-3-l+-3|0)>>>0<=j>>>0){h=-31;break}tc(m+3|0,o|0,j+1|0)|0;if(c[g+36>>2]|0){if(h>>>0<7){h=-31;break}a[e>>0]=a[32945]|0;a[e+1>>0]=a[32946]|0;a[e+2>>0]=a[32947]|0;a[e+3>>0]=a[32948]|0;a[e+4>>0]=a[32949]|0;a[e+5>>0]=a[32950]|0;a[e+6>>0]=a[32951]|0;j=Lb(e+6|0,h+-6|0,c[g+32>>2]|0,c[g+36>>2]|0)|0;if((j|0)==-1){h=-31;break}else{e=e+6+j|0;h=h+-6-((j|0)==-1?0:j)|0}}if(c[g+20>>2]|0){k=e+1|0;j=h+-1|0;if(h>>>0>=2?(a[e>>0]=36,a[e+1>>0]=0,o=Lb(k,j,c[g+16>>2]|0,c[g+20>>2]|0)|0,q=j-((o|0)==-1?0:o)|0,p=(o|0)==-1?k:k+o|0,(o|0)!=-1):0)if(c[g+4>>2]|0)if(q>>>0<2)h=-31;else{a[p>>0]=36;a[p+1>>0]=0;g=(Lb(p+1|0,q+-1|0,c[g>>2]|0,c[g+4>>2]|0)|0)!=-1;i=r;return (g?0:-31)|0}else h=0;else h=-31}else h=0}else h=-31}else h=-31}else h=-31}}else h=-31;while(0);i=r;return h|0}function Ea(a,b,d,e,f){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;if(!b)if(!e){if(f|0){c[f>>2]=(a>>>0)%(d>>>0);c[f+4>>2]=0}e=0;f=(a>>>0)/(d>>>0)>>>0;return (D=e,f)|0}else{if(!f){e=0;f=0;return (D=e,f)|0}c[f>>2]=a|0;c[f+4>>2]=b&0;e=0;f=0;return (D=e,f)|0}do if(d){if(e|0){h=(V(e|0)|0)-(V(b|0)|0)|0;if(h>>>0<=31){n=h+1|0;i=a>>>((h+1|0)>>>0)&h-31>>31|b<<31-h;m=b>>>((h+1|0)>>>0)&h-31>>31;g=0;h=a<<31-h;break}if(!f){e=0;f=0;return (D=e,f)|0}c[f>>2]=a|0;c[f+4>>2]=b|b&0;e=0;f=0;return (D=e,f)|0}if(d-1&d|0){h=(V(d|0)|0)+33-(V(b|0)|0)|0;n=h;i=32-h-1>>31&b>>>((h-32|0)>>>0)|(b<<32-h|a>>>(h>>>0))&h-32>>31;m=h-32>>31&b>>>(h>>>0);g=a<<64-h&32-h>>31;h=(b<<64-h|a>>>((h-32|0)>>>0))&32-h>>31|a<<32-h&h-33>>31;break}if(f|0){c[f>>2]=d-1&a;c[f+4>>2]=0}if((d|0)==1){e=b|b&0;f=a|0|0;return (D=e,f)|0}else{f=id(d|0)|0;e=b>>>(f>>>0)|0;f=b<<32-f|a>>>(f>>>0)|0;return (D=e,f)|0}}else{if(!e){if(f|0){c[f>>2]=(b>>>0)%(d>>>0);c[f+4>>2]=0}e=0;f=(b>>>0)/(d>>>0)>>>0;return (D=e,f)|0}if(!a){if(f|0){c[f>>2]=0;c[f+4>>2]=(b>>>0)%(e>>>0)}d=0;f=(b>>>0)/(e>>>0)>>>0;return (D=d,f)|0}if(!(e-1&e)){if(f|0){c[f>>2]=a|0;c[f+4>>2]=e-1&b|b&0}d=0;f=b>>>((id(e|0)|0)>>>0);return (D=d,f)|0}h=(V(e|0)|0)-(V(b|0)|0)|0;if(h>>>0<=30){n=h+1|0;i=b<<31-h|a>>>((h+1|0)>>>0);m=b>>>((h+1|0)>>>0);g=0;h=a<<31-h;break}if(!f){e=0;f=0;return (D=e,f)|0}c[f>>2]=a|0;c[f+4>>2]=b|b&0;e=0;f=0;return (D=e,f)|0}while(0);if(!n){j=h;b=m;a=0;h=0}else{k=oe(d|0|0,e|e&0|0,-1,-1)|0;l=D;j=h;b=m;a=n;h=0;do{p=j;j=g>>>31|j<<1;g=h|g<<1;p=i<<1|p>>>31|0;o=i>>>31|b<<1|0;le(k|0,l|0,p|0,o|0)|0;n=D;m=n>>31|((n|0)<0?-1:0)<<1;h=m&1;i=le(p|0,o|0,m&(d|0)|0,(((n|0)<0?-1:0)>>31|((n|0)<0?-1:0)<<1)&(e|e&0)|0)|0;b=D;a=a-1|0}while((a|0)!=0);a=0}if(f|0){c[f>>2]=i;c[f+4>>2]=b}o=(g|0)>>>31|j<<1|(0<<1|g>>>31)&0|a;p=(g<<1|0>>>31)&-2|h;return (D=o,p)|0}function Fa(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0;g=i;h=i=i+63&-64;i=i+2400|0;Gb(h+2136|0,d);Gb(h+1880|0,f);Rb(h+480|0,e);bb(h+1760|0,e);dc(h+320|0,h+1760|0);Zc(h,h+320|0);Qb(h+320|0,h,h+480|0);Zc(h+160|0,h+320|0);Rb(h+480+160|0,h+160|0);Qb(h+320|0,h,h+480+160|0);Zc(h+160|0,h+320|0);Rb(h+480+320|0,h+160|0);Qb(h+320|0,h,h+480+320|0);Zc(h+160|0,h+320|0);Rb(h+480+480|0,h+160|0);Qb(h+320|0,h,h+480+480|0);Zc(h+160|0,h+320|0);Rb(h+480+640|0,h+160|0);Qb(h+320|0,h,h+480+640|0);Zc(h+160|0,h+320|0);Rb(h+480+800|0,h+160|0);Qb(h+320|0,h,h+480+800|0);Zc(h+160|0,h+320|0);Rb(h+480+960|0,h+160|0);Qb(h+320|0,h,h+480+960|0);Zc(h+160|0,h+320|0);Rb(h+480+1120|0,h+160|0);d=b;e=d+40|0;do{c[d>>2]=0;d=d+4|0}while((d|0)<(e|0));c[b+40>>2]=1;d=b+44|0;e=d+36|0;do{c[d>>2]=0;d=d+4|0}while((d|0)<(e|0));c[b+80>>2]=1;d=b+84|0;e=d+36|0;do{c[d>>2]=0;d=d+4|0}while((d|0)<(e|0));d=255;while(1){if(a[h+2136+d>>0]|0)break;if(a[h+1880+d>>0]|0)break;e=d+-1|0;if((d|0)>0)d=e;else{d=e;break}}if((d|0)>-1)while(1){dc(h+320|0,b);e=a[h+2136+d>>0]|0;if(e<<24>>24<=0){if(e<<24>>24<0){Zc(h+160|0,h+320|0);Pb(h+320|0,h+160|0,h+480+((((e<<24>>24)/-2|0)<<24>>24)*160|0)|0)}}else{Zc(h+160|0,h+320|0);Qb(h+320|0,h+160|0,h+480+(((e&255)>>>1&255)*160|0)|0)}e=a[h+1880+d>>0]|0;if(e<<24>>24<=0){if(e<<24>>24<0){Zc(h+160|0,h+320|0);Ub(h+320|0,h+160|0,584+((((e<<24>>24)/-2|0)<<24>>24)*120|0)|0)}}else{Zc(h+160|0,h+320|0);Vb(h+320|0,h+160|0,584+(((e&255)>>>1&255)*120|0)|0)}ud(b,h+320|0);if((d|0)>0)d=d+-1|0;else break}i=g;return}function Ga(a){a=a|0;var b=0,d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0;u=i;v=i=i+63&-64;i=i+64|0;b=v;d=a;e=b+64|0;do{c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0}while((b|0)<(e|0));b=0;e=c[v+60>>2]|0;f=c[v+44>>2]|0;g=c[v+12>>2]|0;h=c[v+28>>2]|0;j=c[v>>2]|0;k=c[v+48>>2]|0;l=c[v+16>>2]|0;m=c[v+32>>2]|0;n=c[v+20>>2]|0;d=c[v+4>>2]|0;o=c[v+36>>2]|0;p=c[v+52>>2]|0;q=c[v+40>>2]|0;r=c[v+24>>2]|0;s=c[v+56>>2]|0;t=c[v+8>>2]|0;do{F=k+j|0;F=(F<<7|F>>>25)^l;C=F+j|0;C=(C<<9|C>>>23)^m;z=(C+F<<13|(C+F|0)>>>19)^k;I=(z+C<<18|(z+C|0)>>>14)^j;B=d+n|0;B=(B<<7|B>>>25)^o;y=B+n|0;y=(y<<9|y>>>23)^p;L=(y+B<<13|(y+B|0)>>>19)^d;E=(L+y<<18|(L+y|0)>>>14)^n;x=r+q|0;x=(x<<7|x>>>25)^s;K=x+q|0;K=(K<<9|K>>>23)^t;H=(K+x<<13|(K+x|0)>>>19)^r;A=(H+K<<18|(H+K|0)>>>14)^q;J=f+e|0;J=(J<<7|J>>>25)^g;G=J+e|0;G=(G<<9|G>>>23)^h;D=(G+J<<13|(G+J|0)>>>19)^f;w=(D+G<<18|(D+G|0)>>>14)^e;d=(J+I<<7|(J+I|0)>>>25)^L;L=d+I|0;t=(L<<9|L>>>23)^K;K=t+d|0;g=(K<<13|K>>>19)^J;J=g+t|0;j=(J<<18|J>>>14)^I;r=(F+E<<7|(F+E|0)>>>25)^H;H=r+E|0;h=(H<<9|H>>>23)^G;G=h+r|0;l=(G<<13|G>>>19)^F;F=l+h|0;n=(F<<18|F>>>14)^E;f=(B+A<<7|(B+A|0)>>>25)^D;D=f+A|0;m=(D<<9|D>>>23)^C;C=m+f|0;o=(C<<13|C>>>19)^B;B=o+m|0;q=(B<<18|B>>>14)^A;k=(x+w<<7|(x+w|0)>>>25)^z;z=k+w|0;p=(z<<9|z>>>23)^y;y=p+k|0;s=(y<<13|y>>>19)^x;x=s+p|0;e=(x<<18|x>>>14)^w;b=b+2|0}while(b>>>0<8);c[v>>2]=j;c[v+48>>2]=k;c[v+16>>2]=l;c[v+32>>2]=m;c[v+20>>2]=n;c[v+4>>2]=d;c[v+36>>2]=o;c[v+52>>2]=p;c[v+40>>2]=q;c[v+24>>2]=r;c[v+56>>2]=s;c[v+8>>2]=t;c[v+60>>2]=e;c[v+44>>2]=f;c[v+12>>2]=g;c[v+28>>2]=h;c[a>>2]=(c[a>>2]|0)+j;b=1;while(1){L=a+(b<<2)|0;c[L>>2]=(c[L>>2]|0)+d;b=b+1|0;if((b|0)==16)break;d=c[v+(b<<2)>>2]|0}i=u;return}function Ha(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;g=i;h=i=i+63&-64;i=i+128|0;e=Rd(d<<24>>24|0,((d<<24>>24|0)<0)<<31>>31|0,63)|0;c[a>>2]=1;f=a+4|0;j=f+36|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(j|0));c[a+40>>2]=1;f=a+44|0;j=f+76|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(j|0));o=(d<<24>>24)-((d<<24>>24&0-e)<<1)&255;xd(a,1544+(b*960|0)|0,((o^1)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+120|0,((o^2)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+240|0,((o^3)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+360|0,((o^4)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+480|0,((o^5)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+600|0,((o^6)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+720|0,((o^7)+-1|0)>>>31&255);xd(a,1544+(b*960|0)+840|0,((o^8)+-1|0)>>>31&255);o=c[a+44>>2]|0;n=c[a+48>>2]|0;m=c[a+52>>2]|0;l=c[a+56>>2]|0;k=c[a+60>>2]|0;b=c[a+64>>2]|0;d=c[a+68>>2]|0;f=c[a+72>>2]|0;j=c[a+76>>2]|0;c[h>>2]=c[a+40>>2];c[h+4>>2]=o;c[h+8>>2]=n;c[h+12>>2]=m;c[h+16>>2]=l;c[h+20>>2]=k;c[h+24>>2]=b;c[h+28>>2]=d;c[h+32>>2]=f;c[h+36>>2]=j;j=c[a+4>>2]|0;f=c[a+8>>2]|0;d=c[a+12>>2]|0;b=c[a+16>>2]|0;k=c[a+20>>2]|0;l=c[a+24>>2]|0;m=c[a+28>>2]|0;n=c[a+32>>2]|0;o=c[a+36>>2]|0;c[h+40>>2]=c[a>>2];c[h+44>>2]=j;c[h+48>>2]=f;c[h+52>>2]=d;c[h+56>>2]=b;c[h+60>>2]=k;c[h+64>>2]=l;c[h+68>>2]=m;c[h+72>>2]=n;c[h+76>>2]=o;o=0-(c[a+84>>2]|0)|0;n=0-(c[a+88>>2]|0)|0;m=0-(c[a+92>>2]|0)|0;l=0-(c[a+96>>2]|0)|0;k=0-(c[a+100>>2]|0)|0;b=0-(c[a+104>>2]|0)|0;d=0-(c[a+108>>2]|0)|0;f=0-(c[a+112>>2]|0)|0;j=0-(c[a+116>>2]|0)|0;c[h+80>>2]=0-(c[a+80>>2]|0);c[h+84>>2]=o;c[h+88>>2]=n;c[h+92>>2]=m;c[h+96>>2]=l;c[h+100>>2]=k;c[h+104>>2]=b;c[h+108>>2]=d;c[h+112>>2]=f;c[h+116>>2]=j;xd(a,h,e&255);i=g;return}function Ia(a,b){a=a|0;b=b|0;var c=0,d=0;c=i;d=i=i+63&-64;i=i+160|0;ra(d+120|0,b);ra(d+80|0,d+120|0);ra(d+80|0,d+80|0);pa(d+80|0,b,d+80|0);pa(d+120|0,d+120|0,d+80|0);ra(d+40|0,d+120|0);pa(d+80|0,d+80|0,d+40|0);ra(d+40|0,d+80|0);b=1;do{ra(d+40|0,d+40|0);b=b+1|0}while((b|0)!=5);pa(d+80|0,d+40|0,d+80|0);ra(d+40|0,d+80|0);b=1;do{ra(d+40|0,d+40|0);b=b+1|0}while((b|0)!=10);pa(d+40|0,d+40|0,d+80|0);ra(d,d+40|0);b=1;do{ra(d,d);b=b+1|0}while((b|0)!=20);pa(d+40|0,d,d+40|0);ra(d+40|0,d+40|0);b=1;do{ra(d+40|0,d+40|0);b=b+1|0}while((b|0)!=10);pa(d+80|0,d+40|0,d+80|0);ra(d+40|0,d+80|0);b=1;do{ra(d+40|0,d+40|0);b=b+1|0}while((b|0)!=50);pa(d+40|0,d+40|0,d+80|0);ra(d,d+40|0);b=1;do{ra(d,d);b=b+1|0}while((b|0)!=100);pa(d+40|0,d,d+40|0);ra(d+40|0,d+40|0);b=1;do{ra(d+40|0,d+40|0);b=b+1|0}while((b|0)!=50);pa(d+80|0,d+40|0,d+80|0);ra(d+80|0,d+80|0);b=1;do{ra(d+80|0,d+80|0);b=b+1|0}while((b|0)!=5);pa(a,d+80|0,d+120|0);i=c;return}function Ja(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;k=i;j=i=i+63&-64;i=i+16|0;f=c[b+36>>2]|0;g=c[b+20>>2]|0;h=c[b+4>>2]|0;c[b+36>>2]=0;c[b+20>>2]=0;c[b+4>>2]=0;l=(sc(d,32920,8)|0)==0;d=l?d+8|0:d;a:do if((l?(sc(d,32929,3)|0)==0:0)?(e=jc(d+3|0,j)|0,(e|0)!=0):0)if((c[j>>2]|0)==19)if(!(sc(e,32933,3)|0)){d=jc(e+3|0,j)|0;if(!d){d=-32;break}c[b+44>>2]=c[j>>2];if(!(sc(d,32937,3)|0)){d=jc(d+3|0,j)|0;if(!d){d=-32;break}c[b+40>>2]=c[j>>2];if(!(sc(d,32941,3)|0)){d=jc(d+3|0,j)|0;if(!d){d=-32;break}l=c[j>>2]|0;c[b+48>>2]=l;c[b+52>>2]=l;do if(!(sc(d,32945,6)|0)){c[j>>2]=f;d=ub(c[b+32>>2]|0,j,d+6|0)|0;if(!d){d=-32;break a}else{c[b+36>>2]=c[j>>2];break}}while(0);e=a[d>>0]|0;if(e<<24>>24)if(e<<24>>24==36){c[j>>2]=g;d=ub(c[b+16>>2]|0,j,d+1|0)|0;if(!d){d=-32;break}c[b+20>>2]=c[j>>2];e=a[d>>0]|0;if(e<<24>>24)if(e<<24>>24==36){c[j>>2]=h;e=ub(c[b>>2]|0,j,d+1|0)|0;if(!e){d=-32;break}c[b+4>>2]=c[j>>2];d=jb(b)|0;if(!d)d=(a[e>>0]|0)==0?0:-32}else d=-32;else d=0}else d=-32;else d=0}else d=-32}else d=-32}else d=-32;else d=-26;else d=-32;while(0);i=k;return d|0}function Ka(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;d=i;e=i=i+63&-64;i=i+128|0;ra(e+80|0,b);ra(e+40|0,e+80|0);ra(e+40|0,e+40|0);pa(e+40|0,b,e+40|0);pa(e+80|0,e+80|0,e+40|0);ra(e+80|0,e+80|0);pa(e+80|0,e+40|0,e+80|0);ra(e+40|0,e+80|0);c=1;do{ra(e+40|0,e+40|0);c=c+1|0}while((c|0)!=5);pa(e+80|0,e+40|0,e+80|0);ra(e+40|0,e+80|0);c=1;do{ra(e+40|0,e+40|0);c=c+1|0}while((c|0)!=10);pa(e+40|0,e+40|0,e+80|0);ra(e,e+40|0);c=1;do{ra(e,e);c=c+1|0}while((c|0)!=20);pa(e+40|0,e,e+40|0);ra(e+40|0,e+40|0);c=1;do{ra(e+40|0,e+40|0);c=c+1|0}while((c|0)!=10);pa(e+80|0,e+40|0,e+80|0);ra(e+40|0,e+80|0);c=1;do{ra(e+40|0,e+40|0);c=c+1|0}while((c|0)!=50);pa(e+40|0,e+40|0,e+80|0);ra(e,e+40|0);c=1;do{ra(e,e);c=c+1|0}while((c|0)!=100);pa(e+40|0,e,e+40|0);ra(e+40|0,e+40|0);c=1;do{ra(e+40|0,e+40|0);c=c+1|0}while((c|0)!=50);pa(e+80|0,e+40|0,e+80|0);ra(e+80|0,e+80|0);ra(e+80|0,e+80|0);pa(a,e+80|0,b);i=d;return}function La(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;m=c[d>>2]|0;h=c[d+4>>2]|0;i=c[d+8>>2]|0;j=c[d+12>>2]|0;p=c[d+16>>2]|0;f=c[d+20>>2]|0;g=c[d+24>>2]|0;n=c[d+28>>2]|0;e=c[d+32>>2]|0;d=c[d+36>>2]|0;o=((((((((((((((d*19|0)+16777216|0)>>>25)+m>>26)+h>>25)+i>>26)+j>>25)+p>>26)+f>>25)+g>>26)+n>>25)+e>>26)+d>>25)*19|0)+m>>26;m=((((((((((((((d*19|0)+16777216|0)>>>25)+m>>26)+h>>25)+i>>26)+j>>25)+p>>26)+f>>25)+g>>26)+n>>25)+e>>26)+d>>25)*19|0)+m-(o<<26)|0;l=o+h-(o+h>>25<<25)|0;k=(o+h>>25)+i-((o+h>>25)+i>>26<<26)|0;q=((o+h>>25)+i>>26)+j>>25;j=((o+h>>25)+i>>26)+j-(q<<25)|0;i=q+p-(q+p>>26<<26)|0;h=(q+p>>26)+f-((q+p>>26)+f>>25<<25)|0;o=((q+p>>26)+f>>25)+g>>26;g=((q+p>>26)+f>>25)+g-(o<<26)|0;f=o+n-(o+n>>25<<25)|0;d=((o+n>>25)+e>>26)+d|0;e=(o+n>>25)+e-((o+n>>25)+e>>26<<26)|0;a[b>>0]=m;a[b+1>>0]=m>>>8;a[b+2>>0]=m>>>16;a[b+3>>0]=l<<2|m>>>24;a[b+4>>0]=l>>>6;a[b+5>>0]=l>>>14;a[b+6>>0]=k<<3|l>>>22;a[b+7>>0]=k>>>5;a[b+8>>0]=k>>>13;a[b+9>>0]=j<<5|k>>>21;a[b+10>>0]=j>>>3;a[b+11>>0]=j>>>11;a[b+12>>0]=i<<6|j>>>19;a[b+13>>0]=i>>>2;a[b+14>>0]=i>>>10;a[b+15>>0]=i>>>18;a[b+16>>0]=h;a[b+17>>0]=h>>>8;a[b+18>>0]=h>>>16;a[b+19>>0]=g<<1|h>>>24;a[b+20>>0]=g>>>7;a[b+21>>0]=g>>>15;a[b+22>>0]=f<<3|g>>>23;a[b+23>>0]=f>>>5;a[b+24>>0]=f>>>13;a[b+25>>0]=e<<4|f>>>21;a[b+26>>0]=e>>>4;a[b+27>>0]=e>>>12;a[b+28>>0]=e>>>20|(d&33554431)<<6;a[b+29>>0]=d>>>2;a[b+30>>0]=d>>>10;a[b+31>>0]=(d&33554431)>>>18;return}function Ma(b,e,f,g,h,j,k,l){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;var m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;s=i;t=i=i+63&-64;i=i+112|0;if(!((f|0)==0&(g|0)==0)){n=t+16|0;m=n+32|0;do{a[n>>0]=a[l>>0]|0;n=n+1|0;l=l+1|0}while((n|0)<(m|0));n=d[h+4>>0]|d[h+4+1>>0]<<8|d[h+4+2>>0]<<16|d[h+4+3>>0]<<24;c[t>>2]=d[h>>0]|d[h+1>>0]<<8|d[h+2>>0]<<16|d[h+3>>0]<<24;c[t+4>>2]=n;a[t+8>>0]=j;n=Rd(j|0,k|0,8)|0;a[t+9>>0]=n;n=Rd(j|0,k|0,16)|0;a[t+10>>0]=n;n=Rd(j|0,k|0,24)|0;a[t+11>>0]=n;a[t+12>>0]=k;n=Rd(j|0,k|0,40)|0;a[t+13>>0]=n;n=Rd(j|0,k|0,48)|0;a[t+14>>0]=n;n=Rd(j|0,k|0,56)|0;a[t+15>>0]=n;if(g>>>0>0|(g|0)==0&f>>>0>63){do{xa(t+48|0,t,t+16|0,0)|0;l=0;do{a[b+l>>0]=a[t+48+l>>0]^a[e+l>>0];l=l+1|0}while((l|0)!=64);l=1;m=8;while(1){n=t+m|0;l=(d[n>>0]|0)+l|0;a[n>>0]=l;m=m+1|0;if((m|0)==16)break;else l=l>>>8}f=oe(f|0,g|0,-64,-1)|0;g=D;b=b+64|0;e=e+64|0}while(g>>>0>0|(g|0)==0&f>>>0>63);if(!((f|0)==0&(g|0)==0)){p=b;q=f;r=e;o=8}}else{p=b;q=f;r=e;o=8}if((o|0)==8?(xa(t+48|0,t,t+16|0,0)|0,q|0):0){l=0;do{a[p+l>>0]=a[t+48+l>>0]^a[r+l>>0];l=l+1|0}while((l|0)!=(q|0))}fd(t+48|0,64);fd(t+16|0,32)}i=s;return 0}function Na(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;o=c[b+72>>2]|0;m=c[b+72+4>>2]|0;k=Rd(o|0,m|0,3)|0;l=Pd(e|0,f|0,3)|0;n=D;i=Rd(e|0,f|0,61)|0;j=D;m=oe(o|0,m|0,l|0,n|0)|0;o=D;c[b+72>>2]=m;c[b+72+4>>2]=o;g=c[b+64>>2]|0;h=c[b+64+4>>2]|0;if(o>>>0<n>>>0|(o|0)==(n|0)&m>>>0<l>>>0){g=oe(g|0,h|0,1,0)|0;h=D;c[b+64>>2]=g;c[b+64+4>>2]=h}j=oe(g|0,h|0,i|0,j|0)|0;c[b+64>>2]=j;c[b+64+4>>2]=D;j=le(128,0,k&127|0,0)|0;g=D;if(g>>>0>f>>>0|(g|0)==(f|0)&j>>>0>e>>>0){if(!((e|0)==0&(f|0)==0)){g=0;h=0;do{n=a[d+g>>0]|0;o=oe(g|0,h|0,k&127|0,0)|0;a[b+80+o>>0]=n;g=oe(g|0,h|0,1,0)|0;h=D}while(h>>>0<f>>>0|(h|0)==(f|0)&g>>>0<e>>>0)}}else{if(!((j|0)==0&(g|0)==0)){h=0;i=0;do{n=a[d+h>>0]|0;o=oe(h|0,i|0,k&127|0,0)|0;a[b+80+o>>0]=n;h=oe(h|0,i|0,1,0)|0;i=D}while(i>>>0<g>>>0|(i|0)==(g|0)&h>>>0<j>>>0)}ha(b,b+80|0);g=le(e|0,f|0,j|0,g|0)|0;h=D;if(h>>>0>0|(h|0)==0&g>>>0>127){i=d+j|0;do{ha(b,i);i=i+128|0;g=oe(g|0,h|0,-128,-1)|0;h=D}while(h>>>0>0|(h|0)==0&g>>>0>127);j=i}else j=d+j|0;g=g&127;if(!((g|0)==0&0==0)){h=0;i=0;do{a[b+80+h>>0]=a[j+h>>0]|0;h=oe(h|0,i|0,1,0)|0;i=D}while(i>>>0<0|(i|0)==0&h>>>0<g>>>0)}}return 0}function Oa(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;f=c[b+56>>2]|0;g=c[b+56+4>>2]|0;if(!((f|0)==0&(g|0)==0)){a[b+64+f>>0]=1;e=oe(f|0,g|0,1,0)|0;h=D;if(h>>>0<0|(h|0)==0&e>>>0<16){h=le(14,0,f|0,g|0)|0;Hc(b+64+e|0,0,h+1|0)|0}a[b+80>>0]=1;Ba(b,b+64|0,16,0)}g=c[b+24>>2]|0;h=(c[b+28>>2]|0)+(g>>>26)|0;k=(h>>>26)+(c[b+32>>2]|0)|0;i=(k>>>26)+(c[b+36>>2]|0)|0;e=((i>>>26)*5|0)+(c[b+20>>2]|0)|0;l=((((e&67108863)+5|0)>>>26)+((e>>>26)+(g&67108863))|0)>>>26;j=(i|-67108864)+((((l+(h&67108863)|0)>>>26)+(k&67108863)|0)>>>26)|0;g=(((e&67108863)+5|0)>>>26)+((e>>>26)+(g&67108863))&67108863&(j>>>31)+-1|j>>31&(e>>>26)+(g&67108863);k=((l+(h&67108863)|0)>>>26)+k&67108863&(j>>>31)+-1|j>>31&(k&67108863);e=oe(e+5&67108863&(j>>>31)+-1|j>>31&(e&67108863)|g<<26|0,0,c[b+40>>2]|0,0)|0;f=D;g=oe(g>>>6|(l+h&67108863&(j>>>31)+-1|j>>31&(h&67108863))<<20|0,0,c[b+44>>2]|0,0)|0;f=oe(g|0,D|0,f|0,0)|0;g=D;h=oe((l+h&67108863&(j>>>31)+-1|j>>31&(h&67108863))>>>12|k<<14|0,0,c[b+48>>2]|0,0)|0;g=oe(h|0,D|0,g|0,0)|0;h=D;i=oe(k>>>18|((j>>>31)+-1&j|j>>31&i)<<8|0,0,c[b+52>>2]|0,0)|0;h=oe(i|0,D|0,h|0,0)|0;a[d>>0]=e;a[d+1>>0]=e>>8;a[d+2>>0]=e>>16;a[d+3>>0]=e>>24;a[d+4>>0]=f;a[d+4+1>>0]=f>>8;a[d+4+2>>0]=f>>16;a[d+4+3>>0]=f>>24;a[d+8>>0]=g;a[d+8+1>>0]=g>>8;a[d+8+2>>0]=g>>16;a[d+8+3>>0]=g>>24;a[d+12>>0]=h;a[d+12+1>>0]=h>>8;a[d+12+2>>0]=h>>16;a[d+12+3>>0]=h>>24;fd(b,88);return}function Pa(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0;g=i;h=i=i+63&-64;i=i+592|0;f=0;do{k=a[e+f>>0]|0;j=f<<1;a[h+520+j>>0]=k&15;a[h+520+(j|1)>>0]=(k&255)>>>4;f=f+1|0}while((f|0)!=32);f=0;e=0;do{k=h+520+e|0;j=(d[k>>0]|0)+f|0;f=(j<<24)+134217728>>28;a[k>>0]=j-(f<<4);e=e+1|0}while((e|0)!=63);a[h+520+63>>0]=(d[h+520+63>>0]|0)+f;f=b;e=f+40|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(e|0));c[b+40>>2]=1;f=b+44|0;e=f+36|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(e|0));c[b+80>>2]=1;f=b+84|0;e=f+76|0;do{c[f>>2]=0;f=f+4|0}while((f|0)<(e|0));f=1;do{Ha(h,(f|0)/2|0,a[h+520+f>>0]|0);Vb(h+240|0,b,h);Zc(b,h+240|0);f=f+2|0}while((f|0)<64);bb(h+400|0,b);dc(h+240|0,h+400|0);ud(h+120|0,h+240|0);dc(h+240|0,h+120|0);ud(h+120|0,h+240|0);dc(h+240|0,h+120|0);ud(h+120|0,h+240|0);dc(h+240|0,h+120|0);Zc(b,h+240|0);f=0;do{Ha(h,(f|0)/2|0,a[h+520+f>>0]|0);Vb(h+240|0,b,h);Zc(b,h+240|0);f=f+2|0}while((f|0)<64);i=g;return}function Qa(b,e,f,g,h,j){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0;m=i;n=i=i+63&-64;i=i+192|0;if((e+-1&255)>63)ba();if((f|0)!=0&g<<24>>24!=0?(g&255)<=64:0){a[n+128>>0]=e;a[n+128+1>>0]=g;a[n+128+2>>0]=1;a[n+128+3>>0]=1;k=n+128+4|0;l=k+28|0;do{a[k>>0]=0;k=k+1|0}while((k|0)<(l|0));if(!h){k=n+128+32|0;l=k+16|0;do{a[k>>0]=0;k=k+1|0}while((k|0)<(l|0))}else{k=n+128+32|0;e=h;l=k+16|0;do{a[k>>0]=a[e>>0]|0;k=k+1|0;e=e+1|0}while((k|0)<(l|0))}if(!j){k=n+128+48|0;l=k+16|0;do{a[k>>0]=0;k=k+1|0}while((k|0)<(l|0))}else{k=n+128+48|0;e=j;l=k+16|0;do{a[k>>0]=a[e>>0]|0;k=k+1|0;e=e+1|0}while((k|0)<(l|0))}Hc(b+64|0,0,293)|0;k=b;e=400;l=k+64|0;do{c[k>>2]=c[e>>2];k=k+4|0;e=e+4|0}while((k|0)<(l|0));e=0;do{k=n+128+(e<<3)|0;j=b+(e<<3)|0;l=c[j+4>>2]^(d[k+4>>0]|d[k+4+1>>0]<<8|d[k+4+2>>0]<<16|d[k+4+3>>0]<<24);c[j>>2]=c[j>>2]^(d[k>>0]|d[k+1>>0]<<8|d[k+2>>0]<<16|d[k+3>>0]<<24);c[j+4>>2]=l;e=e+1|0}while((e|0)!=8);Hc(n+(g&255)|0,0,(g<<24>>24<0?0:128-(g&255)|0)|0)|0;tc(n|0,f|0,g&255|0)|0;ib(b,n,128,0);fd(n,128);i=m;return}ba()}function Ra(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0;h=c[b+56>>2]|0;g=c[b+56+4>>2]|0;if(!((h|0)==0&(g|0)==0)){j=le(16,0,h|0,g|0)|0;l=D;k=l>>>0>f>>>0|(l|0)==(f|0)&j>>>0>e>>>0?e:j;l=l>>>0>f>>>0|(l|0)==(f|0)&j>>>0>e>>>0?f:l;if(!((k|0)==0&(l|0)==0)){j=0;i=0;do{n=a[d+j>>0]|0;h=oe(h|0,g|0,j|0,i|0)|0;a[b+64+h>>0]=n;j=oe(j|0,i|0,1,0)|0;i=D;h=c[b+56>>2]|0;g=c[b+56+4>>2]|0}while(i>>>0<l>>>0|(i|0)==(l|0)&j>>>0<k>>>0)}n=oe(h|0,g|0,k|0,l|0)|0;j=D;c[b+56>>2]=n;c[b+56+4>>2]=j;if(!(j>>>0<0|(j|0)==0&n>>>0<16)){e=le(e|0,f|0,k|0,l|0)|0;f=D;Ba(b,b+64|0,16,0);c[b+56>>2]=0;c[b+56+4>>2]=0;d=d+k|0;m=6}}else m=6;if((m|0)==6){g=e&-16;if(f>>>0>0|(f|0)==0&e>>>0>15){h=le(e|0,f|0,g|0,f|0)|0;n=D;Ba(b,d,g,f);i=d+g|0;g=n}else{i=d;h=e;g=f}if(!((h|0)==0&(g|0)==0)){e=0;d=0;do{m=a[i+e>>0]|0;n=oe(c[b+56>>2]|0,c[b+56+4>>2]|0,e|0,d|0)|0;a[b+64+n>>0]=m;e=oe(e|0,d|0,1,0)|0;d=D}while(d>>>0<g>>>0|(d|0)==(g|0)&e>>>0<h>>>0);n=oe(c[b+56>>2]|0,c[b+56+4>>2]|0,h|0,g|0)|0;c[b+56>>2]=n;c[b+56+4>>2]=D}}return}function Sa(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0;e=i;f=i=i+63&-64;i=i+368|0;if(!((a|0)==0|(b|0)==0)){yc(f,0,0,64)|0;c[f+360>>2]=c[b+48>>2];ue(f,f+360|0,4,0)|0;c[f+360>>2]=c[b+4>>2];ue(f,f+360|0,4,0)|0;c[f+360>>2]=c[b+44>>2];ue(f,f+360|0,4,0)|0;c[f+360>>2]=c[b+40>>2];ue(f,f+360|0,4,0)|0;c[f+360>>2]=19;ue(f,f+360|0,4,0)|0;c[f+360>>2]=d;ue(f,f+360|0,4,0)|0;c[f+360>>2]=c[b+12>>2];ue(f,f+360|0,4,0)|0;d=c[b+8>>2]|0;if(d|0?(ue(f,d,c[b+12>>2]|0,0)|0,c[b+56>>2]&1|0):0){fd(c[b+8>>2]|0,c[b+12>>2]|0);c[b+12>>2]=0}c[f+360>>2]=c[b+20>>2];ue(f,f+360|0,4,0)|0;d=c[b+16>>2]|0;if(d|0)ue(f,d,c[b+20>>2]|0,0)|0;c[f+360>>2]=c[b+28>>2];ue(f,f+360|0,4,0)|0;d=c[b+24>>2]|0;if(d|0?(ue(f,d,c[b+28>>2]|0,0)|0,c[b+56>>2]&2|0):0){fd(c[b+24>>2]|0,c[b+28>>2]|0);c[b+28>>2]=0}c[f+360>>2]=c[b+36>>2];ue(f,f+360|0,4,0)|0;d=c[b+32>>2]|0;if(d|0)ue(f,d,c[b+36>>2]|0,0)|0;Fd(f,a,64)|0}i=e;return}function Ta(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0;k=i;l=i=i+63&-64;i=i+496|0;c[l+360>>2]=d;if(d>>>0<65){if((yc(l,0,0,d)|0)>=0){ue(l,l+360|0,4,0)|0;ue(l,e,f,0)|0;Fd(l,b,d)|0}}else a:do if((yc(l,0,0,64)|0)>=0?(ue(l,l+360|0,4,0)|0,ue(l,e,f,0)|0,(Fd(l,l+432|0,64)|0)>=0):0){g=b;h=l+432|0;j=g+32|0;do{a[g>>0]=a[h>>0]|0;g=g+1|0;h=h+1|0}while((g|0)<(j|0));g=l+368|0;h=l+432|0;j=g+64|0;do{a[g>>0]=a[h>>0]|0;g=g+1|0;h=h+1|0}while((g|0)<(j|0));if((d+-32|0)>>>0>64){f=d+-32|0;e=b+32|0;do{if((Cc(l+432|0,64,l+368|0,64,0,0,0)|0)<0)break a;g=e;h=l+432|0;j=g+32|0;do{a[g>>0]=a[h>>0]|0;g=g+1|0;h=h+1|0}while((g|0)<(j|0));f=f+-32|0;e=e+32|0;g=l+368|0;h=l+432|0;j=g+64|0;do{a[g>>0]=a[h>>0]|0;g=g+1|0;h=h+1|0}while((g|0)<(j|0))}while(f>>>0>64)}else{f=d+-32|0;e=b+32|0}if((Cc(l+432|0,f,l+368|0,64,0,0,0)|0)>=0)tc(e|0,l+432|0,f|0)|0}while(0);fd(l,357);i=k;return}function Ua(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0,k=0;a:do if(!((e|0)==0&(f|0)==0)){j=c[b+32>>2]|0;g=c[b+32+4>>2]|0;i=Rd(j|0,g|0,3)|0;h=Pd(e|0,f|0,3)|0;h=oe(j|0,g|0,h|0,D|0)|0;c[b+32>>2]=h;c[b+32+4>>2]=D;if(0>f>>>0|0==(f|0)&(64-(i&63)|0)>>>0>e>>>0){g=0;h=0;while(1){k=a[d+g>>0]|0;j=oe(g|0,h|0,i&63|0,0)|0;a[b+40+j>>0]=k;g=oe(g|0,h|0,1,0)|0;h=D;if(!(h>>>0<f>>>0|(h|0)==(f|0)&g>>>0<e>>>0))break a}}if(64-(i&63)|0){g=0;h=0;do{j=a[d+g>>0]|0;k=oe(g|0,h|0,i&63|0,0)|0;a[b+40+k>>0]=j;g=oe(g|0,h|0,1,0)|0;h=D}while(h>>>0<0|(h|0)==0&g>>>0<(64-(i&63)|0)>>>0)}ka(b,b+40|0);g=le(e|0,f|0,64-(i&63)|0,0)|0;h=D;if(h>>>0>0|(h|0)==0&g>>>0>63){e=d+(64-(i&63))|0;do{ka(b,e);e=e+64|0;g=oe(g|0,h|0,-64,-1)|0;h=D}while(h>>>0>0|(h|0)==0&g>>>0>63);f=e}else f=d+(64-(i&63))|0;g=g&63;if(!((g|0)==0&0==0)){h=0;e=0;do{a[b+40+h>>0]=a[f+h>>0]|0;h=oe(h|0,e|0,1,0)|0;e=D}while(e>>>0<0|(e|0)==0&h>>>0<g>>>0)}}while(0);return 0}function Va(a,b,e,f,g,h,j){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0;k=i;l=i=i+63&-64;i=i+64|0;if(!((e|0)==0&(f|0)==0)){c[l>>2]=1634760805;c[l+4>>2]=857760878;c[l+8>>2]=2036477234;c[l+12>>2]=1797285236;c[l+16>>2]=d[j>>0]|d[j+1>>0]<<8|d[j+2>>0]<<16|d[j+3>>0]<<24;c[l+20>>2]=d[j+4>>0]|d[j+4+1>>0]<<8|d[j+4+2>>0]<<16|d[j+4+3>>0]<<24;c[l+24>>2]=d[j+8>>0]|d[j+8+1>>0]<<8|d[j+8+2>>0]<<16|d[j+8+3>>0]<<24;c[l+28>>2]=d[j+12>>0]|d[j+12+1>>0]<<8|d[j+12+2>>0]<<16|d[j+12+3>>0]<<24;c[l+32>>2]=d[j+16>>0]|d[j+16+1>>0]<<8|d[j+16+2>>0]<<16|d[j+16+3>>0]<<24;c[l+36>>2]=d[j+20>>0]|d[j+20+1>>0]<<8|d[j+20+2>>0]<<16|d[j+20+3>>0]<<24;c[l+40>>2]=d[j+24>>0]|d[j+24+1>>0]<<8|d[j+24+2>>0]<<16|d[j+24+3>>0]<<24;c[l+44>>2]=d[j+28>>0]|d[j+28+1>>0]<<8|d[j+28+2>>0]<<16|d[j+28+3>>0]<<24;c[l+48>>2]=h;c[l+52>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;c[l+56>>2]=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;c[l+60>>2]=d[g+8>>0]|d[g+8+1>>0]<<8|d[g+8+2>>0]<<16|d[g+8+3>>0]<<24;va(l,b,a,e,f);fd(l,64)}i=k;return 0}function Wa(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;h=i;j=i=i+63&-64;i=i+64|0;if(!((b|0)==0&(e|0)==0)){c[j>>2]=1634760805;c[j+4>>2]=857760878;c[j+8>>2]=2036477234;c[j+12>>2]=1797285236;c[j+16>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;c[j+20>>2]=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;c[j+24>>2]=d[g+8>>0]|d[g+8+1>>0]<<8|d[g+8+2>>0]<<16|d[g+8+3>>0]<<24;c[j+28>>2]=d[g+12>>0]|d[g+12+1>>0]<<8|d[g+12+2>>0]<<16|d[g+12+3>>0]<<24;c[j+32>>2]=d[g+16>>0]|d[g+16+1>>0]<<8|d[g+16+2>>0]<<16|d[g+16+3>>0]<<24;c[j+36>>2]=d[g+20>>0]|d[g+20+1>>0]<<8|d[g+20+2>>0]<<16|d[g+20+3>>0]<<24;c[j+40>>2]=d[g+24>>0]|d[g+24+1>>0]<<8|d[g+24+2>>0]<<16|d[g+24+3>>0]<<24;c[j+44>>2]=d[g+28>>0]|d[g+28+1>>0]<<8|d[g+28+2>>0]<<16|d[g+28+3>>0]<<24;c[j+48>>2]=0;c[j+52>>2]=d[f>>0]|d[f+1>>0]<<8|d[f+2>>0]<<16|d[f+3>>0]<<24;c[j+56>>2]=d[f+4>>0]|d[f+4+1>>0]<<8|d[f+4+2>>0]<<16|d[f+4+3>>0]<<24;c[j+60>>2]=d[f+8>>0]|d[f+8+1>>0]<<8|d[f+8+2>>0]<<16|d[f+8+3>>0]<<24;Hc(a|0,0,b|0)|0;va(j,a,a,b,e);fd(j,64)}i=h;return 0}function Xa(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0,l=0,m=0,n=0;n=i;m=i=i+63&-64;i=i+592|0;h=32;g=1;j=0;while(1){h=h+-1|0;k=a[b+32+h>>0]|0;l=a[33097+h>>0]|0;g=g&255;j=((k&255)-(l&255)|0)>>>8&g|j&255;if(!h)break;else g=(((l^k)&255)+65535|0)>>>8&g}a:do if(j){h=0;do{g=0;j=0;do{j=a[16+(h<<5)+g>>0]^a[b+g>>0]|j;g=g+1|0}while((g|0)!=32);h=h+1|0;if(!(j<<24>>24)){g=-1;break a}}while(h>>>0<12);if(!(za(m+328|0,f)|0)){g=0;h=0;do{h=a[f+g>>0]|h;g=g+1|0}while((g|0)!=32);if(h<<24>>24){nd(m)|0;Na(m,b,32,0)|0;Na(m,f,32,0)|0;Na(m,c,d,e)|0;rc(m,m+520|0)|0;oa(m+520|0);Fa(m+208|0,m+520|0,m+328|0,b+32|0);vc(m+488|0,m+208|0);g=zd(m+488|0,b)|0;g=((m+488|0)==(b|0)?-1:g)|(Dc(b,m+488|0,32)|0)}else g=-1}else g=-1}else g=-1;while(0);i=n;return g|0}function Ya(b,c,d,e,f,g,h){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0;k=i;l=i=i+63&-64;i=i+352|0;Aa(l+256|0,g,h,0)|0;if(b>>>0>=d>>>0?0<f>>>0|0==(f|0)&(b-d|0)>>>0<e>>>0:0)j=5;else if(d>>>0>=b>>>0?0<f>>>0|0==(f|0)&(d-b|0)>>>0<e>>>0:0)j=5;if((j|0)==5){Xc(b|0,d|0,e|0)|0;d=b}h=l+288|0;j=h+32|0;do{a[h>>0]=0;h=h+1|0}while((h|0)<(j|0));h=f>>>0>0|(f|0)==0&e>>>0>32?32:e;j=f>>>0>0|(f|0)==0&e>>>0>32?0:f;if(!((h|0)==0&(j|0)==0)){m=oe((f>>>0<0|(f|0)==0&e>>>0<32?e:32)|0,(f>>>0<0|(f|0)==0&e>>>0<32?f:0)|0,-1,0)|0;tc(l+288+32|0,d|0,m+1|0)|0}m=oe(h|0,j|0,32,0)|0;Wd(l+288|0,l+288|0,m,D,g+16|0,l+256|0)|0;Se(l,l+288|0)|0;if(!((h|0)==0&(j|0)==0)){m=oe((f>>>0<0|(f|0)==0&e>>>0<32?e:32)|0,(f>>>0<0|(f|0)==0&e>>>0<32?f:0)|0,-1,0)|0;tc(b|0,l+288+32|0,m+1|0)|0}fd(l+288|0,64);if(f>>>0>0|(f|0)==0&e>>>0>32){m=le(e|0,f|0,h|0,j|0)|0;Ma(b+h|0,d+h|0,m,D,g+16|0,1,0,l+256|0)|0}fd(l+256|0,32);ne(l,b,e,f)|0;Re(l,c)|0;fd(l,256);i=k;return 0}function Za(a,b,e,f,g,h,j,k){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0;l=i;m=i=i+63&-64;i=i+64|0;if(!((e|0)==0&(f|0)==0)){c[m>>2]=1634760805;c[m+4>>2]=857760878;c[m+8>>2]=2036477234;c[m+12>>2]=1797285236;c[m+16>>2]=d[k>>0]|d[k+1>>0]<<8|d[k+2>>0]<<16|d[k+3>>0]<<24;c[m+20>>2]=d[k+4>>0]|d[k+4+1>>0]<<8|d[k+4+2>>0]<<16|d[k+4+3>>0]<<24;c[m+24>>2]=d[k+8>>0]|d[k+8+1>>0]<<8|d[k+8+2>>0]<<16|d[k+8+3>>0]<<24;c[m+28>>2]=d[k+12>>0]|d[k+12+1>>0]<<8|d[k+12+2>>0]<<16|d[k+12+3>>0]<<24;c[m+32>>2]=d[k+16>>0]|d[k+16+1>>0]<<8|d[k+16+2>>0]<<16|d[k+16+3>>0]<<24;c[m+36>>2]=d[k+20>>0]|d[k+20+1>>0]<<8|d[k+20+2>>0]<<16|d[k+20+3>>0]<<24;c[m+40>>2]=d[k+24>>0]|d[k+24+1>>0]<<8|d[k+24+2>>0]<<16|d[k+24+3>>0]<<24;c[m+44>>2]=d[k+28>>0]|d[k+28+1>>0]<<8|d[k+28+2>>0]<<16|d[k+28+3>>0]<<24;c[m+48>>2]=h;c[m+52>>2]=j;c[m+56>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;c[m+60>>2]=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;va(m,b,a,e,f);fd(m,64)}i=l;return 0}function _a(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0;k=i;l=i=i+63&-64;i=i+1024|0;if(c[e+20>>2]|0){j=0;do{a[b+64>>0]=0;a[b+64+1>>0]=0;a[b+64+2>>0]=0;a[b+64+3>>0]=0;a[b+68>>0]=j;a[b+68+1>>0]=j>>8;a[b+68+2>>0]=j>>16;a[b+68+3>>0]=j>>24;Ta(l,1024,b,72);g=S(c[e+16>>2]|0,j)|0;h=c[(c[e>>2]|0)+4>>2]|0;f=0;do{o=l+(f<<3)|0;n=d[o+4>>0]|d[o+4+1>>0]<<8|d[o+4+2>>0]<<16|d[o+4+3>>0]<<24;m=h+(g<<10)+(f<<3)|0;c[m>>2]=d[o>>0]|d[o+1>>0]<<8|d[o+2>>0]<<16|d[o+3>>0]<<24;c[m+4>>2]=n;f=f+1|0}while((f|0)!=128);a[b+64>>0]=1;a[b+64+1>>0]=0;a[b+64+2>>0]=0;a[b+64+3>>0]=0;Ta(l,1024,b,72);g=(S(c[e+16>>2]|0,j)|0)+1|0;h=c[(c[e>>2]|0)+4>>2]|0;f=0;do{m=l+(f<<3)|0;n=d[m+4>>0]|d[m+4+1>>0]<<8|d[m+4+2>>0]<<16|d[m+4+3>>0]<<24;o=h+(g<<10)+(f<<3)|0;c[o>>2]=d[m>>0]|d[m+1>>0]<<8|d[m+2>>0]<<16|d[m+3>>0]<<24;c[o+4>>2]=n;f=f+1|0}while((f|0)!=128);j=j+1|0}while(j>>>0<(c[e+20>>2]|0)>>>0)}fd(l,1024);i=k;return}function $a(a,b,e,f,g){a=a|0;b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;h=i;j=i=i+63&-64;i=i+64|0;if(!((b|0)==0&(e|0)==0)){c[j>>2]=1634760805;c[j+4>>2]=857760878;c[j+8>>2]=2036477234;c[j+12>>2]=1797285236;c[j+16>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;c[j+20>>2]=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;c[j+24>>2]=d[g+8>>0]|d[g+8+1>>0]<<8|d[g+8+2>>0]<<16|d[g+8+3>>0]<<24;c[j+28>>2]=d[g+12>>0]|d[g+12+1>>0]<<8|d[g+12+2>>0]<<16|d[g+12+3>>0]<<24;c[j+32>>2]=d[g+16>>0]|d[g+16+1>>0]<<8|d[g+16+2>>0]<<16|d[g+16+3>>0]<<24;c[j+36>>2]=d[g+20>>0]|d[g+20+1>>0]<<8|d[g+20+2>>0]<<16|d[g+20+3>>0]<<24;c[j+40>>2]=d[g+24>>0]|d[g+24+1>>0]<<8|d[g+24+2>>0]<<16|d[g+24+3>>0]<<24;c[j+44>>2]=d[g+28>>0]|d[g+28+1>>0]<<8|d[g+28+2>>0]<<16|d[g+28+3>>0]<<24;c[j+48>>2]=0;c[j+52>>2]=0;c[j+56>>2]=d[f>>0]|d[f+1>>0]<<8|d[f+2>>0]<<16|d[f+3>>0]<<24;c[j+60>>2]=d[f+4>>0]|d[f+4+1>>0]<<8|d[f+4+2>>0]<<16|d[f+4+3>>0]<<24;Hc(a|0,0,b|0)|0;va(j,a,a,b,e);fd(j,64)}i=h;return 0}function ab(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;if(e<<24>>24?(e&255)<=64:0){if((c[b+80>>2]|0)==0?(c[b+80+4>>2]|0)==0:0){f=c[b+352>>2]|0;do if(f>>>0>128){f=c[b+64>>2]|0;i=c[b+64+4>>2]|0;j=oe(f|0,i|0,128,0)|0;c[b+64>>2]=j;c[b+64+4>>2]=D;f=oe((i>>>0>4294967295|(i|0)==-1&f>>>0>4294967167)&1|0,0,c[b+72>>2]|0,c[b+72+4>>2]|0)|0;c[b+72>>2]=f;c[b+72+4>>2]=D;ia(b,b+96|0);f=(c[b+352>>2]|0)+-128|0;c[b+352>>2]=f;if(f>>>0<129){tc(b+96|0,b+224|0,f|0)|0;g=b+72|0;h=c[b+352>>2]|0;break}else fa(32331,32363,343,32407)}else{g=b+72|0;h=f}while(0);j=oe(c[b+64>>2]|0,c[b+64+4>>2]|0,h|0,0)|0;f=D;c[b+64>>2]=j;c[b+64+4>>2]=f;i=g;i=oe((f>>>0<0|(f|0)==0&j>>>0<h>>>0)&1|0,0,c[i>>2]|0,c[i+4>>2]|0)|0;j=g;c[j>>2]=i;c[j+4>>2]=D;if(a[b+356>>0]|0){c[b+88>>2]=-1;c[b+88+4>>2]=-1}c[b+80>>2]=-1;c[b+80+4>>2]=-1;Hc(b+96+h|0,0,256-h|0)|0;ia(b,b+96|0);tc(d|0,b|0,e&255|0)|0;f=0}else f=-1;return f|0}ba();return 0}function bb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;l=c[b+4>>2]|0;k=c[b+8>>2]|0;j=c[b+12>>2]|0;i=c[b+16>>2]|0;h=c[b+20>>2]|0;g=c[b+24>>2]|0;f=c[b+28>>2]|0;e=c[b+32>>2]|0;d=c[b+36>>2]|0;c[a>>2]=c[b>>2];c[a+4>>2]=l;c[a+8>>2]=k;c[a+12>>2]=j;c[a+16>>2]=i;c[a+20>>2]=h;c[a+24>>2]=g;c[a+28>>2]=f;c[a+32>>2]=e;c[a+36>>2]=d;d=c[b+44>>2]|0;e=c[b+48>>2]|0;f=c[b+52>>2]|0;g=c[b+56>>2]|0;h=c[b+60>>2]|0;i=c[b+64>>2]|0;j=c[b+68>>2]|0;k=c[b+72>>2]|0;l=c[b+76>>2]|0;c[a+40>>2]=c[b+40>>2];c[a+44>>2]=d;c[a+48>>2]=e;c[a+52>>2]=f;c[a+56>>2]=g;c[a+60>>2]=h;c[a+64>>2]=i;c[a+68>>2]=j;c[a+72>>2]=k;c[a+76>>2]=l;l=c[b+84>>2]|0;k=c[b+88>>2]|0;j=c[b+92>>2]|0;i=c[b+96>>2]|0;h=c[b+100>>2]|0;g=c[b+104>>2]|0;f=c[b+108>>2]|0;e=c[b+112>>2]|0;d=c[b+116>>2]|0;c[a+80>>2]=c[b+80>>2];c[a+84>>2]=l;c[a+88>>2]=k;c[a+92>>2]=j;c[a+96>>2]=i;c[a+100>>2]=h;c[a+104>>2]=g;c[a+108>>2]=f;c[a+112>>2]=e;c[a+116>>2]=d;return}function cb(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0;j=i;k=i=i+63&-64;i=i+96|0;c[k>>2]=(d[h>>0]|d[h+1>>0]<<8|d[h+2>>0]<<16|d[h+3>>0]<<24)&67108863;c[k+4>>2]=(d[h+3>>0]|d[h+3+1>>0]<<8|d[h+3+2>>0]<<16|d[h+3+3>>0]<<24)>>>2&67108611;c[k+8>>2]=(d[h+6>>0]|d[h+6+1>>0]<<8|d[h+6+2>>0]<<16|d[h+6+3>>0]<<24)>>>4&67092735;c[k+12>>2]=(d[h+9>>0]|d[h+9+1>>0]<<8|d[h+9+2>>0]<<16|d[h+9+3>>0]<<24)>>>6&66076671;c[k+16>>2]=(d[h+12>>0]|d[h+12+1>>0]<<8|d[h+12+2>>0]<<16|d[h+12+3>>0]<<24)>>>8&1048575;c[k+20>>2]=0;c[k+20+4>>2]=0;c[k+20+8>>2]=0;c[k+20+12>>2]=0;c[k+20+16>>2]=0;c[k+40>>2]=d[h+16>>0]|d[h+16+1>>0]<<8|d[h+16+2>>0]<<16|d[h+16+3>>0]<<24;c[k+44>>2]=d[h+20>>0]|d[h+20+1>>0]<<8|d[h+20+2>>0]<<16|d[h+20+3>>0]<<24;c[k+48>>2]=d[h+24>>0]|d[h+24+1>>0]<<8|d[h+24+2>>0]<<16|d[h+24+3>>0]<<24;c[k+52>>2]=d[h+28>>0]|d[h+28+1>>0]<<8|d[h+28+2>>0]<<16|d[h+28+3>>0]<<24;c[k+56>>2]=0;c[k+56+4>>2]=0;a[k+80>>0]=0;Ra(k,e,f,g);Oa(k,b);i=j;return 0}function db(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0,x=0;x=c[a>>2]|0;v=c[a+4>>2]|0;t=c[a+8>>2]|0;r=c[a+12>>2]|0;p=c[a+16>>2]|0;n=c[a+20>>2]|0;l=c[a+24>>2]|0;j=c[a+28>>2]|0;h=c[a+32>>2]|0;f=c[a+36>>2]|0;w=c[b>>2]|0;u=c[b+4>>2]|0;s=c[b+8>>2]|0;q=c[b+12>>2]|0;o=c[b+16>>2]|0;m=c[b+20>>2]|0;k=c[b+24>>2]|0;i=c[b+28>>2]|0;g=c[b+32>>2]|0;e=c[b+36>>2]|0;c[a>>2]=(w^x)&0-d^x;c[a+4>>2]=(u^v)&0-d^v;c[a+8>>2]=(s^t)&0-d^t;c[a+12>>2]=(q^r)&0-d^r;c[a+16>>2]=(o^p)&0-d^p;c[a+20>>2]=(m^n)&0-d^n;c[a+24>>2]=(k^l)&0-d^l;c[a+28>>2]=(i^j)&0-d^j;c[a+32>>2]=(g^h)&0-d^h;c[a+36>>2]=(e^f)&0-d^f;c[b>>2]=(w^x)&0-d^w;c[b+4>>2]=(u^v)&0-d^u;c[b+8>>2]=(s^t)&0-d^s;c[b+12>>2]=(q^r)&0-d^q;c[b+16>>2]=(o^p)&0-d^o;c[b+20>>2]=(m^n)&0-d^m;c[b+24>>2]=(k^l)&0-d^k;c[b+28>>2]=(i^j)&0-d^i;c[b+32>>2]=(g^h)&0-d^g;c[b+36>>2]=(e^f)&0-d^e;return}function eb(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0;k=i;j=i=i+63&-64;i=i+96|0;Aa(j,f,g,0)|0;fb(j+32|0,32,0,f+16|0,j)|0;if(!($d(c,b,d,e,j+32|0)|0))if(!a)c=0;else{if(b>>>0>=a>>>0?0<e>>>0|0==(e|0)&(b-a|0)>>>0<d>>>0:0)h=8;else if(a>>>0>=b>>>0?0<e>>>0|0==(e|0)&(a-b|0)>>>0<d>>>0:0)h=8;if((h|0)==8){Xc(a|0,b|0,d|0)|0;b=a}c=e>>>0>0|(e|0)==0&d>>>0>32?32:d;g=e>>>0>0|(e|0)==0&d>>>0>32?0:e;if((c|0)==0&(g|0)==0)Wd(j+32|0,j+32|0,32,0,f+16|0,j)|0;else{h=oe((e>>>0<0|(e|0)==0&d>>>0<32?d:32)|0,(e>>>0<0|(e|0)==0&d>>>0<32?e:0)|0,-1,0)|0;tc(j+32+32|0,b|0,h+1|0)|0;l=oe(c|0,g|0,32,0)|0;Wd(j+32|0,j+32|0,l,D,f+16|0,j)|0;tc(a|0,j+32+32|0,h+1|0)|0}if(e>>>0>0|(e|0)==0&d>>>0>32){l=le(d|0,e|0,c|0,g|0)|0;Ma(a+c|0,b+c|0,l,D,f+16|0,1,0,j)|0}fd(j,32);c=0}else{fd(j,32);c=-1}i=k;return c|0}function fb(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0;o=i;p=i=i+63&-64;i=i+112|0;if(!((e|0)==0&(f|0)==0)){k=p+16|0;j=k+32|0;do{a[k>>0]=a[h>>0]|0;k=k+1|0;h=h+1|0}while((k|0)<(j|0));k=d[g+4>>0]|d[g+4+1>>0]<<8|d[g+4+2>>0]<<16|d[g+4+3>>0]<<24;c[p>>2]=d[g>>0]|d[g+1>>0]<<8|d[g+2>>0]<<16|d[g+3>>0]<<24;c[p+4>>2]=k;c[p+8>>2]=0;c[p+8+4>>2]=0;if(f>>>0>0|(f|0)==0&e>>>0>63){do{xa(b,p,p+16|0,0)|0;h=1;j=8;while(1){k=p+j|0;h=(d[k>>0]|0)+h|0;a[k>>0]=h;j=j+1|0;if((j|0)==16)break;else h=h>>>8}e=oe(e|0,f|0,-64,-1)|0;f=D;b=b+64|0}while(f>>>0>0|(f|0)==0&e>>>0>63);if(!((e|0)==0&(f|0)==0)){m=b;n=e;l=7}}else{m=b;n=e;l=7}if((l|0)==7?(xa(p+48|0,p,p+16|0,0)|0,n|0):0){h=0;do{a[m+h>>0]=a[p+48+h>>0]|0;h=h+1|0}while((h|0)!=(n|0))}fd(p+48|0,64);fd(p+16|0,32)}i=o;return 0}function gb(b,e,f,g){b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0;k=i;l=i=i+63&-64;i=i+64|0;if((e+-1&255)>63)ba();a[l>>0]=e;a[l+1>>0]=0;a[l+2>>0]=1;a[l+3>>0]=1;h=l+4|0;j=h+28|0;do{a[h>>0]=0;h=h+1|0}while((h|0)<(j|0));if(!f){h=l+32|0;j=h+16|0;do{a[h>>0]=0;h=h+1|0}while((h|0)<(j|0))}else{h=l+32|0;e=f;j=h+16|0;do{a[h>>0]=a[e>>0]|0;h=h+1|0;e=e+1|0}while((h|0)<(j|0))}if(!g){h=l+48|0;j=h+16|0;do{a[h>>0]=0;h=h+1|0}while((h|0)<(j|0))}else{h=l+48|0;e=g;j=h+16|0;do{a[h>>0]=a[e>>0]|0;h=h+1|0;e=e+1|0}while((h|0)<(j|0))}Hc(b+64|0,0,293)|0;h=b;e=400;j=h+64|0;do{c[h>>2]=c[e>>2];h=h+4|0;e=e+4|0}while((h|0)<(j|0));e=0;do{h=l+(e<<3)|0;g=b+(e<<3)|0;j=c[g+4>>2]^(d[h+4>>0]|d[h+4+1>>0]<<8|d[h+4+2>>0]<<16|d[h+4+3>>0]<<24);c[g>>2]=c[g>>2]^(d[h>>0]|d[h+1>>0]<<8|d[h+2>>0]<<16|d[h+3>>0]<<24);c[g+4>>2]=j;e=e+1|0}while((e|0)!=8);i=k;return}function hb(b,e){b=b|0;e=e|0;c[b>>2]=(d[e>>0]|d[e+1>>0]<<8|d[e+2>>0]<<16|d[e+3>>0]<<24)&67108863;c[b+4>>2]=(d[e+3>>0]|d[e+3+1>>0]<<8|d[e+3+2>>0]<<16|d[e+3+3>>0]<<24)>>>2&67108611;c[b+8>>2]=(d[e+6>>0]|d[e+6+1>>0]<<8|d[e+6+2>>0]<<16|d[e+6+3>>0]<<24)>>>4&67092735;c[b+12>>2]=(d[e+9>>0]|d[e+9+1>>0]<<8|d[e+9+2>>0]<<16|d[e+9+3>>0]<<24)>>>6&66076671;c[b+16>>2]=(d[e+12>>0]|d[e+12+1>>0]<<8|d[e+12+2>>0]<<16|d[e+12+3>>0]<<24)>>>8&1048575;c[b+20>>2]=0;c[b+20+4>>2]=0;c[b+20+8>>2]=0;c[b+20+12>>2]=0;c[b+20+16>>2]=0;c[b+40>>2]=d[e+16>>0]|d[e+16+1>>0]<<8|d[e+16+2>>0]<<16|d[e+16+3>>0]<<24;c[b+44>>2]=d[e+20>>0]|d[e+20+1>>0]<<8|d[e+20+2>>0]<<16|d[e+20+3>>0]<<24;c[b+48>>2]=d[e+24>>0]|d[e+24+1>>0]<<8|d[e+24+2>>0]<<16|d[e+24+3>>0]<<24;c[b+52>>2]=d[e+28>>0]|d[e+28+1>>0]<<8|d[e+28+2>>0]<<16|d[e+28+3>>0]<<24;c[b+56>>2]=0;c[b+56+4>>2]=0;a[b+80>>0]=0;return 0}function ib(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;a:do if(!((e|0)==0&(f|0)==0)){g=c[b+352>>2]|0;j=f;while(1){i=256-g|0;f=b+96+g|0;if(!(j>>>0>0|(j|0)==0&e>>>0>i>>>0))break;tc(f|0,d|0,i|0)|0;c[b+352>>2]=(c[b+352>>2]|0)+i;f=c[b+64>>2]|0;g=c[b+64+4>>2]|0;h=oe(f|0,g|0,128,0)|0;c[b+64>>2]=h;c[b+64+4>>2]=D;f=oe((g>>>0>4294967295|(g|0)==-1&f>>>0>4294967167)&1|0,0,c[b+72>>2]|0,c[b+72+4>>2]|0)|0;c[b+72>>2]=f;c[b+72+4>>2]=D;ia(b,b+96|0);f=b+96|0;g=b+224|0;h=f+128|0;do{a[f>>0]=a[g>>0]|0;f=f+1|0;g=g+1|0}while((f|0)<(h|0));g=(c[b+352>>2]|0)+-128|0;c[b+352>>2]=g;e=le(e|0,j|0,i|0,0)|0;f=D;if((e|0)==0&(f|0)==0)break a;else{d=d+i|0;j=f}}tc(f|0,d|0,e|0)|0;j=oe(c[b+352>>2]|0,0,e|0,j|0)|0;c[b+352>>2]=j}while(0);return}function jb(a){a=a|0;var b=0,d=0;do if(a)if(c[a>>2]|0)if((c[a+4>>2]|0)>>>0>=16){if((c[a+8>>2]|0)==0?c[a+12>>2]|0:0){b=-18;break}b=c[a+20>>2]|0;if(!(c[a+16>>2]|0)){if(b|0){b=-19;break}}else if(b>>>0<8){b=-6;break}if((c[a+24>>2]|0)==0?c[a+28>>2]|0:0){b=-20;break}if((c[a+32>>2]|0)==0?c[a+36>>2]|0:0){b=-21;break}b=c[a+44>>2]|0;if(b>>>0>=8)if(b>>>0<=2097152){d=c[a+48>>2]|0;if(b>>>0>=d<<3>>>0)if((c[a+40>>2]|0)>>>0>=3)if(d)if(d>>>0<=16777215){b=c[a+52>>2]|0;if(!b)b=-28;else b=b>>>0>16777215?-29:0}else b=-17;else b=-16;else b=-12;else b=-14}else b=-15;else b=-14}else b=-2;else b=-1;else b=-25;while(0);return b|0}function kb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0,k=0,l=0;l=i;k=i=i+63&-64;i=i+64|0;e=k+4+4|0;f=e+52|0;do{c[e>>2]=0;e=e+4|0}while((e|0)<(f|0));e=kc(a)|0;c[k+36>>2]=e;c[k+20>>2]=e;c[k+4>>2]=e;h=na(e)|0;c[k+32>>2]=h;f=na(e)|0;c[k+16>>2]=f;g=na(e)|0;c[k>>2]=g;do if((f|0)==0|(g|0)==0|(h|0)==0){ta(h);ta(f);ta(g);e=-22}else{j=na(e)|0;if(!j){ta(h);ta(f);ta(g);e=-22;break}e=Ja(k,a)|0;if(e|0){ta(c[k+32>>2]|0);ta(c[k+16>>2]|0);ta(c[k>>2]|0);ta(j);break}d=xb(c[k+40>>2]|0,c[k+44>>2]|0,c[k+52>>2]|0,b,d,c[k+16>>2]|0,c[k+20>>2]|0,j,c[k+4>>2]|0,0,0)|0;ta(c[k+32>>2]|0);ta(c[k+16>>2]|0);if((d|0)==0?(Dc(j,c[k>>2]|0,c[k+4>>2]|0)|0)==0:0)e=0;else e=-35;ta(j);ta(c[k>>2]|0)}while(0);i=l;return e|0}function lb(a,b,d,e,f,g,h,j,k,l,m){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0;n=i;i=i+352|0;we(n+280|0,64,0,l,m)|0;Se(n,n+280|0)|0;fd(n+280|0,64);ne(n,h,j,k)|0;b=le(0,0,j|0,k|0)|0;ne(n,34460,b&15,0)|0;ne(n,d,e,f)|0;b=le(0,0,e|0,f|0)|0;ne(n,34460,b&15,0)|0;c[n+256>>2]=j;c[n+256+4>>2]=k;ne(n,n+256|0,8,0)|0;c[n+256>>2]=e;c[n+256+4>>2]=f;ne(n,n+256|0,8,0)|0;Re(n,n+264|0)|0;fd(n,256);b=Ad(n+264|0,g)|0;fd(n+264|0,16);do if(a)if(!b){Ld(a,d,e,f,l,1,m)|0;b=0;break}else{Hc(a|0,0,e|0)|0;b=-1;break}while(0);i=n;return b|0}function mb(b,e,f,g,h,i,j){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;var k=0,l=0,m=0,n=0,o=0,p=0,q=0;a:do if(!g){n=0;m=0;k=0;l=0}else{n=0;m=0;k=0;q=0;while(1){p=n<<24>>24==0;while(1){l=d[f+k>>0]|0;o=(((l&223)+201&255)+65526^((l&223)+201&255)+65520)>>>8;if((o|((l^48)+65526|0)>>>8)&255|0)break;if(!((h|0)!=0&p)){l=0;break a}if(!(Ke(h,l)|0)){n=0;l=0;break a}k=k+1|0;if(k>>>0>=g>>>0){n=0;l=0;break a}}l=o&(l&223)+201|((l^48)+65526|0)>>>8&(l^48);if(m>>>0>=e>>>0)break;if(p)l=l<<4&255;else{a[b+m>>0]=l|q&255;m=m+1|0;l=q}n=(n&255^255)&255;k=k+1|0;if(k>>>0<g>>>0)q=l;else{l=0;break a}}c[(Zf()|0)>>2]=34;l=-1}while(0);if(j|0)c[j>>2]=f+(((n<<24>>24!=0)<<31>>31)+k);if(i|0)c[i>>2]=m;return l|0}function nb(b,e,f,g){b=b|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0;k=i;l=i=i+63&-64;i=i+192|0;if((e+-1&255)>63)ba();if((f|0)!=0&g<<24>>24!=0?(g&255)<=64:0){a[l+128>>0]=e;a[l+128+1>>0]=g;a[l+128+2>>0]=1;a[l+128+3>>0]=1;e=l+128+4|0;j=e+60|0;do{a[e>>0]=0;e=e+1|0}while((e|0)<(j|0));Hc(b+64|0,0,293)|0;e=b;h=400;j=e+64|0;do{c[e>>2]=c[h>>2];e=e+4|0;h=h+4|0}while((e|0)<(j|0));e=0;do{m=l+128+(e<<3)|0;j=b+(e<<3)|0;h=c[j+4>>2]^(d[m+4>>0]|d[m+4+1>>0]<<8|d[m+4+2>>0]<<16|d[m+4+3>>0]<<24);c[j>>2]=c[j>>2]^(d[m>>0]|d[m+1>>0]<<8|d[m+2>>0]<<16|d[m+3>>0]<<24);c[j+4>>2]=h;e=e+1|0}while((e|0)!=8);Hc(l+(g&255)|0,0,(g<<24>>24<0?0:128-(g&255)|0)|0)|0;tc(l|0,f|0,g&255|0)|0;ib(b,l,128,0);fd(l,128);i=k;return}ba()}function ob(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,i=0,j=0,k=0;i=b>>>0<0|(b|0)==0&a>>>0<32768?32768:a;h=b>>>0<0|(b|0)==0&a>>>0<32768?0:b;c[g>>2]=8;a:do if(h>>>0<0|(h|0)==0&i>>>0<d>>>5>>>0){c[f>>2]=1;a=Te(i|0,h|0,c[g>>2]<<2|0,0)|0;c[e>>2]=1;a=Rd(a|0,D|0,1)|0;b=D;h=1;do{g=Pd(1,0,h|0)|0;f=D;h=h+1|0;if(f>>>0>b>>>0|(f|0)==(b|0)&g>>>0>a>>>0)break a;c[e>>2]=h}while(h>>>0<63)}else{c[e>>2]=1;b=1;while(1){j=Pd(1,0,b|0)|0;k=D;a=b+1|0;if(k>>>0>0|(k|0)==0&j>>>0>d>>>11>>>0){a=b;break}c[e>>2]=a;if(a>>>0<63)b=a;else break}e=Rd(i|0,h|0,2)|0;e=Rd(e|0,D|0,a|0)|0;j=D;k=j>>>0>0|(j|0)==0&e>>>0>1073741823?1073741823:e;c[f>>2]=(k>>>0)/((c[g>>2]|0)>>>0)|0}while(0);return}function pb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;m=i;l=i=i+63&-64;i=i+2048|0;if((a|0)!=0&(b|0)!=0){k=(c[b>>2]|0)+4|0;f=c[b+16>>2]|0;tc(l|0,(c[k>>2]|0)+(f<<10)+-1024|0,1024)|0;g=c[b+20>>2]|0;if(g>>>0>1){d=1;do{h=f+-1+(S(f,d)|0)|0;j=c[k>>2]|0;e=0;do{p=j+(h<<10)+(e<<3)|0;n=l+(e<<3)|0;o=c[n+4>>2]^c[p+4>>2];c[n>>2]=c[n>>2]^c[p>>2];c[n+4>>2]=o;e=e+1|0}while((e|0)!=128);d=d+1|0}while((d|0)!=(g|0))}tc(l+1024|0,l|0,1024)|0;Ta(c[a>>2]|0,c[a+4>>2]|0,l+1024|0,1024);fd(l,1024);fd(l+1024|0,1024);e=c[b>>2]|0;if(e|0?(c[a+56>>2]&1|0)!=0:0){fd(c[e+4>>2]|0,c[b+8>>2]<<10);e=c[b>>2]|0}d=c[e>>2]|0;if(d|0)ta(d);ta(e)}i=m;return}function qb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;a:do if((e|0)!=0&(b&3|0)!=0){f=e;while(1){if((a[b>>0]|0)==(d&255)<<24>>24)break a;b=b+1|0;e=f+-1|0;if((e|0)!=0&(b&3|0)!=0)f=e;else{f=e;e=(e|0)!=0;g=5;break}}}else{f=e;e=(e|0)!=0;g=5}while(0);b:do if((g|0)==5)if(e){if((a[b>>0]|0)!=(d&255)<<24>>24){e=S(d&255,16843009)|0;c:do if(f>>>0>3)while(1){h=c[b>>2]^e;if((h&-2139062144^-2139062144)&h+-16843009|0)break;b=b+4|0;f=f+-4|0;if(f>>>0<=3){g=11;break c}}else g=11;while(0);if((g|0)==11)if(!f){f=0;break}while(1){if((a[b>>0]|0)==(d&255)<<24>>24)break b;b=b+1|0;f=f+-1|0;if(!f){f=0;break}}}}else f=0;while(0);return (f|0?b:0)|0}function rb(a){a=a|0;var b=0,d=0,e=0,f=0;if(a>>>0>=4294967168){c[(Zf()|0)>>2]=12;f=0;return f|0}f=a>>>0<11?16:a+11&-8;e=na(f+76|0)|0;if(!e){f=0;return f|0}do if(e&63){a=((e+63&-64)+-8-(e+-8)|0)>>>0>15?(e+63&-64)+-8|0:(e+63&-64)+56|0;b=a-(e+-8)|0;d=c[e+-4>>2]|0;if(!(d&3)){c[a>>2]=(c[e+-8>>2]|0)+b;c[a+4>>2]=(d&-8)-b;break}else{c[a+4>>2]=(d&-8)-b|c[a+4>>2]&1|2;c[a+((d&-8)-b)+4>>2]=c[a+((d&-8)-b)+4>>2]|1;c[e+-4>>2]=b|c[e+-4>>2]&1|2;c[a+4>>2]=c[a+4>>2]|1;ua(e+-8|0,b);break}}else a=e+-8|0;while(0);b=a+4|0;d=c[b>>2]|0;if(d&3|0?(d&-8)>>>0>(f+16|0)>>>0:0){e=a+f|0;c[b>>2]=f|d&1|2;c[e+4>>2]=(d&-8)-f|3;c[e+((d&-8)-f)+4>>2]=c[e+((d&-8)-f)+4>>2]|1;ua(e,(d&-8)-f|0)}f=a+8|0;return f|0}function sb(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;h=i;i=i+192|0;if(d>>>0>128){nd(b)|0;Na(b,c,d,0)|0;rc(b,h)|0;d=64;c=h}nd(b)|0;e=h+64|0;f=e+128|0;do{a[e>>0]=54;e=e+1|0}while((e|0)<(f|0));g=(d|0)==0;if(!g?(a[h+64>>0]=a[c>>0]^54,(d|0)!=1):0){e=1;do{f=h+64+e|0;a[f>>0]=a[f>>0]^a[c+e>>0];e=e+1|0}while((e|0)!=(d|0))}Na(b,h+64|0,128,0)|0;nd(b+208|0)|0;e=h+64|0;f=e+128|0;do{a[e>>0]=92;e=e+1|0}while((e|0)<(f|0));if(!g?(a[h+64>>0]=a[c>>0]^92,(d|0)!=1):0){e=1;do{g=h+64+e|0;a[g>>0]=a[g>>0]^a[c+e>>0];e=e+1|0}while((e|0)!=(d|0))}Na(b+208|0,h+64|0,128,0)|0;fd(h+64|0,128);fd(h,64);i=h;return 0}function tb(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;h=i;i=i+96|0;if(d>>>0>64){Sc(b)|0;Ua(b,c,d,0)|0;Fb(b,h)|0;d=32;c=h}Sc(b)|0;e=h+32|0;f=e+64|0;do{a[e>>0]=54;e=e+1|0}while((e|0)<(f|0));g=(d|0)==0;if(!g?(a[h+32>>0]=a[c>>0]^54,(d|0)!=1):0){e=1;do{f=h+32+e|0;a[f>>0]=a[f>>0]^a[c+e>>0];e=e+1|0}while((e|0)!=(d|0))}Ua(b,h+32|0,64,0)|0;Sc(b+104|0)|0;e=h+32|0;f=e+64|0;do{a[e>>0]=92;e=e+1|0}while((e|0)<(f|0));if(!g?(a[h+32>>0]=a[c>>0]^92,(d|0)!=1):0){e=1;do{g=h+32+e|0;a[g>>0]=a[g>>0]^a[c+e>>0];e=e+1|0}while((e|0)!=(d|0))}Ua(b+104|0,h+32|0,64,0)|0;fd(h+32|0,64);fd(h,32);i=h;return 0}function ub(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;f=0;h=0;i=0;a:while(1){while(1){g=a[e>>0]|0;g=((0-((0-(g^47)|0)>>>8&63^63|(0-(g^43)|0)>>>8&62^62|((g+65439|0)>>>8^255)&g+185&((122-g|0)>>>8&255^255)|((g+-65|0)>>>8^255)&g+-65&((90-g|0)>>>8&255^255)|((g+65488|0)>>>8^255)&g+4&((57-g|0)>>>8&255^255))|0)>>>8&255^255)&(0-(g^65)|0)>>>8|((0-(g^47)|0)>>>8&63^63|(0-(g^43)|0)>>>8&62^62|((g+65439|0)>>>8^255)&g+185&((122-g|0)>>>8&255^255)|((g+-65|0)>>>8^255)&g+-65&((90-g|0)>>>8&255^255)|((g+65488|0)>>>8^255)&g+4&((57-g|0)>>>8&255^255));if((g|0)==255){j=7;break a}e=e+1|0;h=g+(h<<6)|0;g=f+6|0;if(g>>>0>7)break;else f=g}f=f+-2|0;if(i>>>0>=(c[d>>2]|0)>>>0){e=0;break}a[b>>0]=h>>>f;b=b+1|0;i=i+1|0}if((j|0)==7)if(f>>>0<=4?((1<<f)+-1&h|0)==0:0)c[d>>2]=i;else e=0;return e|0}function vb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;w=c[a>>2]|0;u=c[a+4>>2]|0;s=c[a+8>>2]|0;q=c[a+12>>2]|0;o=c[a+16>>2]|0;m=c[a+20>>2]|0;k=c[a+24>>2]|0;i=c[a+28>>2]|0;g=c[a+32>>2]|0;e=c[a+36>>2]|0;v=(c[b+4>>2]^u)&0-d;t=(c[b+8>>2]^s)&0-d;r=(c[b+12>>2]^q)&0-d;p=(c[b+16>>2]^o)&0-d;n=(c[b+20>>2]^m)&0-d;l=(c[b+24>>2]^k)&0-d;j=(c[b+28>>2]^i)&0-d;h=(c[b+32>>2]^g)&0-d;f=(c[b+36>>2]^e)&0-d;c[a>>2]=(c[b>>2]^w)&0-d^w;c[a+4>>2]=v^u;c[a+8>>2]=t^s;c[a+12>>2]=r^q;c[a+16>>2]=p^o;c[a+20>>2]=n^m;c[a+24>>2]=l^k;c[a+28>>2]=j^i;c[a+32>>2]=h^g;c[a+36>>2]=f^e;return}function wb(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0;f=0;do{c[d+(f<<2)>>2]=c[a+((e<<5)+-16<<2)+(f<<2)>>2];f=f+1|0}while((f|0)!=16);if(e<<1|0){i=0;j=0;while(1){g=i<<4;f=0;do{h=d+(f<<2)|0;c[h>>2]=c[h>>2]^c[a+(g<<2)+(f<<2)>>2];f=f+1|0}while((f|0)!=16);Ga(d);h=i<<3;f=0;do{c[b+(h<<2)+(f<<2)>>2]=c[d+(f<<2)>>2];f=f+1|0}while((f|0)!=16);f=0;do{k=d+(f<<2)|0;c[k>>2]=c[k>>2]^c[a+((g|16)<<2)+(f<<2)>>2];f=f+1|0}while((f|0)!=16);Ga(d);f=0;do{c[b+(h+(e<<4)<<2)+(f<<2)>>2]=c[d+(f<<2)>>2];f=f+1|0}while((f|0)!=16);if((j|0)==(((e<<1)+-1|0)>>>1|0))break;else{i=i+2|0;j=j+1|0}}}return}function xb(a,b,d,e,f,g,h,j,k,l,m){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0,o=0,p=0;p=i;o=i=i+63&-64;i=i+64|0;n=na(k)|0;do if(!n)a=-22;else{c[o>>2]=n;c[o+4>>2]=k;c[o+8>>2]=e;c[o+12>>2]=f;c[o+16>>2]=g;c[o+20>>2]=h;c[o+24>>2]=0;c[o+24+4>>2]=0;c[o+24+8>>2]=0;c[o+24+12>>2]=0;c[o+40>>2]=a;c[o+44>>2]=b;c[o+48>>2]=d;c[o+52>>2]=d;c[o+56>>2]=4;a=_b(o)|0;if(a|0){fd(n,k);ta(n);break}if(j|0)tc(j|0,n|0,k|0)|0;if((l|0)!=0&(m|0)!=0?Da(l,m,o)|0:0){fd(n,k);fd(l,m);ta(n);a=-31;break}fd(n,k);ta(n);a=0}while(0);i=p;return a|0}function yb(b,e,f,g,h){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;q=i;p=i=i+63&-64;i=i+48|0;if((((((a[g>>0]|0)==36?(a[g+1>>0]|0)==55:0)?(a[g+2>>0]|0)==36:0)?(k=qb(32982,d[g+3>>0]|0,65)|0,(k|0)!=0):0)?(l=Pd(1,0,k-32982|0)|0,m=D,j=cd(p+4|0,g+4|0)|0,(j|0)!=0):0)?(n=cd(p,j)|0,(n|0)!=0):0){j=gf(n)|0;if(!j)j=kc(n)|0;else j=j-n|0;k=j+(n-g)|0;if((!((k+45|0)>>>0>102|(k+45|0)>>>0<j>>>0)?(Ca(b,e,f,n,j,l,m,c[p+4>>2]|0,c[p>>2]|0,p+8|0,32)|0)==0:0)?(tc(h|0,g|0,k|0)|0,a[h+k>>0]=36,o=Yb(h+k+1|0,h+102-(h+k+1)|0,p+8|0)|0,fd(p+8|0,32),(o|0)!=0&o>>>0<(h+102|0)>>>0):0)a[o>>0]=0;else h=0}else h=0;i=q;return h|0}function zb(b,e,f,g,h,j){b=b|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0;k=i;l=i=i+63&-64;i=i+560|0;xc(l+496|0,j,32,0)|0;a[l+496>>0]=(d[l+496>>0]|0)&248;a[l+496+31>>0]=(d[l+496+31>>0]|0)&63|64;nd(l)|0;Na(l,l+496+32|0,32,0)|0;Na(l,f,g,h)|0;rc(l,l+432|0)|0;Xc(b+32|0,j+32|0,32)|0;oa(l+432|0);Pa(l+208|0,l+432|0);vc(b,l+208|0);nd(l)|0;Na(l,b,64,0)|0;Na(l,f,g,h)|0;rc(l,l+368|0)|0;oa(l+368|0);ja(b+32|0,l+368|0,l+496|0,l+432|0);fd(l+496|0,64);if(e|0){c[e>>2]=64;c[e+4>>2]=0}i=k;return 0}function Ab(a,b,d,e,f,g,h,j,k,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;l=i;i=i+336|0;we(l+264|0,64,0,m,n)|0;Se(l,l+264|0)|0;fd(l+264|0,64);ne(l,h,j,k)|0;h=le(0,0,j|0,k|0)|0;ne(l,34460,h&15,0)|0;Ld(a,e,f,g,m,1,n)|0;ne(l,a,f,g)|0;h=le(0,0,f|0,g|0)|0;ne(l,34460,h&15,0)|0;c[l+256>>2]=j;c[l+256+4>>2]=k;ne(l,l+256|0,8,0)|0;c[l+256>>2]=f;c[l+256+4>>2]=g;ne(l,l+256|0,8,0)|0;Re(l,b)|0;fd(l,256);if(d|0){c[d>>2]=16;c[d+4>>2]=0}i=l;return 0}function Bb(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0;a:do if(b>>>0<=63?(g=Ed(d|0,0,c|0,0)|0,i=D,!(i>>>0>0|(i|0)==0&g>>>0>1073741823)):0){a[f>>0]=36;a[f+1>>0]=55;a[f+2>>0]=36;a[f+3>>0]=a[32982+b>>0]|0;b=f+4|0;g=0;while(1){i=b;b=b+1|0;a[i>>0]=a[32982+(c&63)>>0]|0;g=g+6|0;if(g>>>0>=30)break;else c=c>>>6}if(b){g=d;d=f+58-b|0;c=0;while(1){if(!d){f=0;break a}i=b;b=b+1|0;a[i>>0]=a[32982+(g&63)>>0]|0;c=c+6|0;if(c>>>0>=30)break;else{g=g>>>6;d=d+-1|0}}if((b|0)!=0?(h=Yb(b,f+58-b|0,e)|0,(h|0)!=0&h>>>0<(f+58|0)>>>0):0)a[h>>0]=0;else f=0}else f=0}else f=0;while(0);return f|0}function Cb(b){b=b|0;var d=0,e=0,f=0,g=0,h=0,j=0,k=0;k=i;j=i=i+63&-64;i=i+32|0;a:do if(((b|0)!=0?(d=c[b+20>>2]|0,(d|0)!=0):0)?(c[b+4>>2]|0)!=0:0){h=0;while(1){g=0;do{if(!d)d=0;else{f=g&255;e=0;do{c[j>>2]=h;c[j+4>>2]=e;a[j+8>>0]=f;c[j+12>>2]=0;c[j+16>>2]=c[j>>2];c[j+16+4>>2]=c[j+4>>2];c[j+16+8>>2]=c[j+8>>2];c[j+16+12>>2]=c[j+12>>2];d=la(b,j+16|0)|0;e=e+1|0;if(d|0)break a;d=c[b+20>>2]|0}while(e>>>0<d>>>0)}g=g+1|0}while(g>>>0<4);h=h+1|0;if(h>>>0>=(c[b+4>>2]|0)>>>0){d=0;break}}}else d=0;while(0);i=k;return d|0}function Db(a,b,d,e,f,g,h,j,k,l,m){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;var n=0;n=i;i=i+352|0;Ge(n+280|0,64,0,l,m)|0;Se(n,n+280|0)|0;fd(n+280|0,64);ne(n,h,j,k)|0;c[n+256>>2]=j;c[n+256+4>>2]=k;ne(n,n+256|0,8,0)|0;ne(n,d,e,f)|0;c[n+256>>2]=e;c[n+256+4>>2]=f;ne(n,n+256|0,8,0)|0;Re(n,n+264|0)|0;fd(n,256);b=Ad(n+264|0,g)|0;fd(n+264|0,16);do if(a)if(!b){Id(a,d,e,f,l,1,0,m)|0;b=0;break}else{Hc(a|0,0,e|0)|0;b=-1;break}while(0);i=n;return b|0}function Eb(b,d,e,f){b=b|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,i=0,j=0;j=(c[d>>2]|0)==0;do if(j){g=a[d+8>>0]|0;if(!(g<<24>>24)){g=(c[d+12>>2]|0)+-1|0;break}g=S(c[b+12>>2]|0,g&255)|0;h=c[d+12>>2]|0;if(!f){g=(((h|0)==0)<<31>>31)+g|0;break}else{g=h+-1+g|0;break}}else{g=(c[b+16>>2]|0)-(c[b+12>>2]|0)|0;h=c[d+12>>2]|0;if(!f){g=(((h|0)==0)<<31>>31)+g|0;break}else{g=h+-1+g|0;break}}while(0);Ed(e|0,0,e|0,0)|0;Ed(g|0,0,D|0,0)|0;f=le(g+-1|0,0,D|0,0)|0;e=D;if(!j?(i=a[d+8>>0]|0,i<<24>>24!=3):0){g=S(c[b+12>>2]|0,(i&255)+1|0)|0;h=0}else{g=0;h=0}j=oe(f|0,e|0,g|0,h|0)|0;b=Bd(j|0,D|0,c[b+16>>2]|0,0)|0;return b|0}function Fb(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,j=0;f=i;e=i=i+63&-64;i=i+16|0;h=c[b+32>>2]|0;g=c[b+32+4>>2]|0;a[e+7>>0]=h;j=Rd(h|0,g|0,8)|0;a[e+6>>0]=j;j=Rd(h|0,g|0,16)|0;a[e+5>>0]=j;j=Rd(h|0,g|0,24)|0;a[e+4>>0]=j;a[e+3>>0]=g;j=Rd(h|0,g|0,40)|0;a[e+2>>0]=j;j=Rd(h|0,g|0,48)|0;a[e+1>>0]=j;j=Rd(h|0,g|0,56)|0;a[e>>0]=j;g=Rd(h|0,g|0,3)|0;Ua(b,32719,((g&63)>>>0<56?56:120)-(g&63)|0,0)|0;Ua(b,e,8,0)|0;e=0;do{j=d+(e<<2)|0;h=c[b+(e<<2)>>2]|0;a[j+3>>0]=h;a[j+2>>0]=h>>>8;a[j+1>>0]=h>>>16;a[j>>0]=h>>>24;e=e+1|0}while((e|0)!=8);fd(b,104);i=f;return 0}function Gb(b,c){b=b|0;c=c|0;var e=0,f=0,g=0,h=0,i=0;e=0;do{a[b+e>>0]=(d[c+(e>>3)>>0]|0)>>>(e&7)&1;e=e+1|0}while((e|0)!=256);h=0;do{i=b+h|0;a:do if(a[i>>0]|0){g=1;do{e=g+h|0;if((e|0)>=256)break a;c=a[b+e>>0]|0;b:do if(c<<24>>24){f=a[i>>0]|0;c=c<<24>>24<<g;if((f+c|0)<16){a[i>>0]=f+c;a[b+e>>0]=0;break}if((f-c|0)<=-16)break a;a[i>>0]=f-c;while(1){c=b+e|0;if(!(a[c>>0]|0))break;a[c>>0]=0;e=e+1|0;if((e|0)>=256)break b}a[c>>0]=1}while(0);g=g+1|0}while((g|0)<7)}while(0);h=h+1|0}while((h|0)!=256);return}function Hb(b,d,e,f,g,h,j){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0;n=i;l=i=i+63&-64;i=i+128|0;k=b;m=k+102|0;do{a[k>>0]=0;k=k+1|0}while((k|0)<(m|0));do if(!(f>>>0>0|(f|0)==0&e>>>0>4294967295)){ob(g,h,j,l+8|0,l+4|0,l);Gd(l+88|0,32);if(!(Bb(c[l+8>>2]|0,c[l>>2]|0,c[l+4>>2]|0,l+88|0,l+24|0)|0)){c[(Zf()|0)>>2]=22;b=-1;break}We(l+12|0);m=(yb(l+12|0,d,e,l+24|0,b)|0)==0;je(l+12|0);if(m){c[(Zf()|0)>>2]=22;b=-1}else b=0}else{c[(Zf()|0)>>2]=27;b=-1}while(0);i=n;return b|0}function Ib(b,e){b=b|0;e=e|0;var f=0,g=0,h=0,j=0,k=0;h=i;j=i=i+63&-64;i=i+64|0;if((e+-1&255)>63)ba();a[j>>0]=e;a[j+1>>0]=0;a[j+2>>0]=1;a[j+3>>0]=1;e=j+4|0;g=e+60|0;do{a[e>>0]=0;e=e+1|0}while((e|0)<(g|0));Hc(b+64|0,0,293)|0;e=b;f=400;g=e+64|0;do{c[e>>2]=c[f>>2];e=e+4|0;f=f+4|0}while((e|0)<(g|0));e=0;do{k=j+(e<<3)|0;g=b+(e<<3)|0;f=c[g+4>>2]^(d[k+4>>0]|d[k+4+1>>0]<<8|d[k+4+2>>0]<<16|d[k+4+3>>0]<<24);c[g>>2]=c[g>>2]^(d[k>>0]|d[k+1>>0]<<8|d[k+2>>0]<<16|d[k+3>>0]<<24);c[g+4>>2]=f;e=e+1|0}while((e|0)!=8);i=h;return}function Jb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;m=(c[b+4>>2]|0)-(c[d+4>>2]|0)|0;l=(c[b+8>>2]|0)-(c[d+8>>2]|0)|0;k=(c[b+12>>2]|0)-(c[d+12>>2]|0)|0;j=(c[b+16>>2]|0)-(c[d+16>>2]|0)|0;i=(c[b+20>>2]|0)-(c[d+20>>2]|0)|0;h=(c[b+24>>2]|0)-(c[d+24>>2]|0)|0;g=(c[b+28>>2]|0)-(c[d+28>>2]|0)|0;f=(c[b+32>>2]|0)-(c[d+32>>2]|0)|0;e=(c[b+36>>2]|0)-(c[d+36>>2]|0)|0;c[a>>2]=(c[b>>2]|0)-(c[d>>2]|0);c[a+4>>2]=m;c[a+8>>2]=l;c[a+12>>2]=k;c[a+16>>2]=j;c[a+20>>2]=i;c[a+24>>2]=h;c[a+28>>2]=g;c[a+32>>2]=f;c[a+36>>2]=e;return}function Kb(a,b,d){a=a|0;b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;m=(c[d+4>>2]|0)+(c[b+4>>2]|0)|0;l=(c[d+8>>2]|0)+(c[b+8>>2]|0)|0;k=(c[d+12>>2]|0)+(c[b+12>>2]|0)|0;j=(c[d+16>>2]|0)+(c[b+16>>2]|0)|0;i=(c[d+20>>2]|0)+(c[b+20>>2]|0)|0;h=(c[d+24>>2]|0)+(c[b+24>>2]|0)|0;g=(c[d+28>>2]|0)+(c[b+28>>2]|0)|0;f=(c[d+32>>2]|0)+(c[b+32>>2]|0)|0;e=(c[d+36>>2]|0)+(c[b+36>>2]|0)|0;c[a>>2]=(c[d>>2]|0)+(c[b>>2]|0);c[a+4>>2]=m;c[a+8>>2]=l;c[a+12>>2]=k;c[a+16>>2]=j;c[a+20>>2]=i;c[a+24>>2]=h;c[a+28>>2]=g;c[a+32>>2]=f;c[a+36>>2]=e;return}function Lb(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;var g=0,h=0,i=0;switch(((f>>>0)%3|0)&3){case 2:{g=((f>>>0)/3|0)<<2|1;h=3;break}case 1:{g=((f>>>0)/3|0)<<2;h=3;break}default:g=((f>>>0)/3|0)<<2}if((h|0)==3)g=g+2|0;if(g>>>0<c>>>0){if(f){i=0;c=0;do{f=f+-1|0;h=e;e=e+1|0;i=d[h>>0]|0|i<<8;c=c+8|0;if(c>>>0>5)while(1){c=c+-6|0;h=b+1|0;a[b>>0]=td(i>>>c&63)|0;if(c>>>0>5)b=h;else{b=h;break}}}while((f|0)!=0);if(c){a[b>>0]=td(i<<6-c&63)|0;b=b+1|0}}a[b>>0]=0}else g=-1;return g|0}function Mb(b,d){b=b|0;d=d|0;var e=0,f=0;a:do if(!(d&255))b=b+(kc(b)|0)|0;else{if(b&3)do{f=a[b>>0]|0;if(f<<24>>24==0?1:f<<24>>24==(d&255)<<24>>24)break a;b=b+1|0}while((b&3|0)!=0);f=S(d&255,16843009)|0;e=c[b>>2]|0;b:do if(!((e&-2139062144^-2139062144)&e+-16843009))do{e=e^f;if((e&-2139062144^-2139062144)&e+-16843009|0)break b;b=b+4|0;e=c[b>>2]|0}while(!((e&-2139062144^-2139062144)&e+-16843009|0));while(0);while(1){f=a[b>>0]|0;if(f<<24>>24==0?1:f<<24>>24==(d&255)<<24>>24)break;else b=b+1|0}}while(0);return b|0}function Nb(a,b,d,e,f,g,h,j,k,l,m,n){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;m=m|0;n=n|0;l=i;i=i+336|0;Ge(l+264|0,64,0,m,n)|0;Se(l,l+264|0)|0;fd(l+264|0,64);ne(l,h,j,k)|0;c[l+256>>2]=j;c[l+256+4>>2]=k;ne(l,l+256|0,8,0)|0;Id(a,e,f,g,m,1,0,n)|0;ne(l,a,f,g)|0;c[l+256>>2]=f;c[l+256+4>>2]=g;ne(l,l+256|0,8,0)|0;Re(l,b)|0;fd(l,256);if(d|0){c[d>>2]=16;c[d+4>>2]=0}i=l;return 0}function Ob(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;g=i;f=i=i+63&-64;i=i+80|0;a:do if((a|0)==0|(b|0)==0)d=-25;else{e=c[a+8>>2]|0;do if((e|0?((e<<10>>>0)/(e>>>0)|0|0)==1024:0)?(d=na(12)|0,c[a>>2]=d,d|0):0){d=Od(f,e<<10)|0;c[(Zf()|0)>>2]=d;if(d|0){c[f>>2]=0;break}d=c[f>>2]|0;if(d|0){c[c[a>>2]>>2]=d;c[(c[a>>2]|0)+4>>2]=d;c[(c[a>>2]|0)+8>>2]=e<<10;Sa(f+8|0,b,c[a+28>>2]|0);fd(f+8+64|0,8);_a(f+8|0,a);fd(f+8|0,72);d=0;break a}}while(0);d=-22}while(0);i=g;return d|0}function Pb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=i=i+63&-64;i=i+48|0;Kb(a,b+40|0,b);Jb(a+40|0,b+40|0,b);pa(a+80|0,a,c+40|0);pa(a+40|0,a+40|0,c);pa(a+120|0,c+120|0,b+120|0);pa(a,b+80|0,c+80|0);Kb(e,a,a);Jb(a,a+80|0,a+40|0);Kb(a+40|0,a+80|0,a+40|0);Jb(a+80|0,e,a+120|0);Kb(a+120|0,e,a+120|0);i=d;return}function Qb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=i=i+63&-64;i=i+48|0;Kb(a,b+40|0,b);Jb(a+40|0,b+40|0,b);pa(a+80|0,a,c);pa(a+40|0,a+40|0,c+40|0);pa(a+120|0,c+120|0,b+120|0);pa(a,b+80|0,c+80|0);Kb(e,a,a);Jb(a,a+80|0,a+40|0);Kb(a+40|0,a+80|0,a+40|0);Kb(a+80|0,e,a+120|0);Jb(a+120|0,e,a+120|0);i=d;return}function Rb(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;Kb(a,b+40|0,b);Jb(a+40|0,b+40|0,b);l=c[b+84>>2]|0;k=c[b+88>>2]|0;j=c[b+92>>2]|0;i=c[b+96>>2]|0;h=c[b+100>>2]|0;g=c[b+104>>2]|0;f=c[b+108>>2]|0;e=c[b+112>>2]|0;d=c[b+116>>2]|0;c[a+80>>2]=c[b+80>>2];c[a+84>>2]=l;c[a+88>>2]=k;c[a+92>>2]=j;c[a+96>>2]=i;c[a+100>>2]=h;c[a+104>>2]=g;c[a+108>>2]=f;c[a+112>>2]=e;c[a+116>>2]=d;pa(a+120|0,b+120|0,544);return}function Sb(b,c){b=b|0;c=c|0;var e=0,f=0,g=0,h=0;g=i;h=i=i+63&-64;i=i+320|0;f=h+280|0;e=f+32|0;do{a[f>>0]=a[c>>0]|0;f=f+1|0;c=c+1|0}while((f|0)<(e|0));a[h+280>>0]=(d[h+280>>0]|0)&248;a[h+280+31>>0]=(d[h+280+31>>0]|0)&63|64;Pa(h+40|0,h+280|0);Kb(h+240|0,h+40+80|0,h+40+40|0);Jb(h+200|0,h+40+80|0,h+40+40|0);Ia(h+200|0,h+200|0);pa(h,h+240|0,h+200|0);La(b,h);i=g;return 0}function Tb(b,c,d,e,f,g){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;h=i;j=i=i+63&-64;i=i+464|0;tb(j+208|0,b,c)|0;De(j+208|0,d,e,0)|0;if(g|0){b=0;c=0;do{b=b+1|0;a[j+448+3>>0]=b;a[j+448+2>>0]=b>>>8;a[j+448+1>>0]=b>>>16;a[j+448>>0]=b>>>24;tc(j|0,j+208|0,208)|0;De(j,j+448|0,4,0)|0;pd(j,j+416|0)|0;e=g-c|0;tc(f+c|0,j+416|0,(e>>>0>32?32:e)|0)|0;c=b<<5}while(c>>>0<g>>>0)}fd(j+208|0,208);i=h;return}function Ub(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=i=i+63&-64;i=i+48|0;Kb(a,b+40|0,b);Jb(a+40|0,b+40|0,b);pa(a+80|0,a,c+40|0);pa(a+40|0,a+40|0,c);pa(a+120|0,c+80|0,b+120|0);Kb(e,b+80|0,b+80|0);Jb(a,a+80|0,a+40|0);Kb(a+40|0,a+80|0,a+40|0);Jb(a+80|0,e,a+120|0);Kb(a+120|0,e,a+120|0);i=d;return}function Vb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=i=i+63&-64;i=i+48|0;Kb(a,b+40|0,b);Jb(a+40|0,b+40|0,b);pa(a+80|0,a,c);pa(a+40|0,a+40|0,c+40|0);pa(a+120|0,c+80|0,b+120|0);Kb(e,b+80|0,b+80|0);Jb(a,a+80|0,a+40|0);Kb(a+40|0,a+80|0,a+40|0);Kb(a+80|0,e,a+120|0);Jb(a+120|0,e,a+120|0);i=d;return}function Wb(b,d,e,f,g,h,j){b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0,m=0,n=0;n=i;l=i=i+63&-64;i=i+16|0;k=b;m=k+128|0;do{a[k>>0]=0;k=k+1|0}while((k|0)<(m|0));do if(!((h|f)>>>0>0|(h|f|0)==0&(g|e)>>>0>4294967295|j>>>0>2147484671))if(h>>>0<0|(h|0)==0&g>>>0<3|j>>>0<8192){c[(Zf()|0)>>2]=22;b=-1;break}else{Gd(l,16);b=((ae(g,j>>>10,d,e,l,b)|0)!=0)<<31>>31;break}else{c[(Zf()|0)>>2]=27;b=-1}while(0);i=n;return b|0}function Xb(a,b,c,d,e,f,g,h,j){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;var k=0,l=0;k=i;l=i=i+63&-64;i=i+368|0;if((b|0)==0&((e|0)!=0|(f|0)!=0))ba();if(!a)ba();if((d+-1&255)>63)ba();if(!((c|0)!=0|g<<24>>24==0))ba();if((g&255)>64)ba();if(!(g<<24>>24))gb(l,d,h,j);else Qa(l,d,c,g,h,j);ib(l,b,e,f);ab(l,a,d)|0;i=k;return}function Yb(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0,h=0,i=0,j=0,k=0,l=0;g=0;a:while(1){if(g>>>0<32){k=0;f=0;j=g}else break;do{i=j;j=j+1|0;f=(d[e+i>>0]|0)<<k|f;k=k+8|0}while(j>>>0<32&k>>>0<24);g=c;i=b;h=0;while(1){if(!g){b=0;break a}l=i;i=i+1|0;a[l>>0]=a[32982+(f&63)>>0]|0;h=h+6|0;if(h>>>0>=k>>>0)break;else{f=f>>>6;g=g+-1|0}}l=(i|0)==0;c=(l?0:b-i|0)+c|0;if(l){b=0;break}else{g=j;b=i}}return b|0}function Zb(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0,j=0;if(e>>>3|0){f=0;do{g=b+(f<<3)|0;h=d+(f<<3)|0;i=c[h>>2]|0;h=c[h+4>>2]|0;a[g+7>>0]=i;j=Rd(i|0,h|0,8)|0;a[g+6>>0]=j;j=Rd(i|0,h|0,16)|0;a[g+5>>0]=j;j=Rd(i|0,h|0,24)|0;a[g+4>>0]=j;a[g+3>>0]=h;j=Rd(i|0,h|0,40)|0;a[g+2>>0]=j;j=Rd(i|0,h|0,48)|0;a[g+1>>0]=j;h=Rd(i|0,h|0,56)|0;a[g>>0]=h;f=f+1|0}while((f|0)!=(e>>>3|0))}return}function _b(a){a=a|0;var b=0,d=0,e=0,f=0,g=0;e=i;d=i=i+63&-64;i=i+48|0;b=jb(a)|0;if(!b){f=c[a+44>>2]|0;b=c[a+48>>2]|0;f=((f>>>0<b<<3>>>0?b<<3:f)>>>0)/(b<<2>>>0)|0;g=S(f,b<<2)|0;c[d>>2]=0;c[d+4>>2]=c[a+40>>2];c[d+8>>2]=g;c[d+12>>2]=f;c[d+16>>2]=f<<2;c[d+20>>2]=b;c[d+24>>2]=c[a+52>>2];c[d+28>>2]=1;b=Ob(d,a)|0;if(!b){b=Cb(d)|0;if(!b){pb(a,d);b=0}}}i=e;return b|0}function $b(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;l=0-(c[b+4>>2]|0)|0;k=0-(c[b+8>>2]|0)|0;j=0-(c[b+12>>2]|0)|0;i=0-(c[b+16>>2]|0)|0;h=0-(c[b+20>>2]|0)|0;g=0-(c[b+24>>2]|0)|0;f=0-(c[b+28>>2]|0)|0;e=0-(c[b+32>>2]|0)|0;d=0-(c[b+36>>2]|0)|0;c[a>>2]=0-(c[b>>2]|0);c[a+4>>2]=l;c[a+8>>2]=k;c[a+12>>2]=j;c[a+16>>2]=i;c[a+20>>2]=h;c[a+24>>2]=g;c[a+28>>2]=f;c[a+32>>2]=e;c[a+36>>2]=d;return}function ac(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;do if((l|0)==1){if((g|d|j)>>>0>0|(g|d|j|0)==0&(f|b|i)>>>0>4294967295|k>>>0>2147484671){c[(Zf()|0)>>2]=27;a=-1;break}if(d>>>0<0|(d|0)==0&b>>>0<16|(j>>>0<0|(j|0)==0&i>>>0<3)|k>>>0<8192){c[(Zf()|0)>>2]=22;a=-1;break}else{a=((Xd(i,k>>>10,e,f,h,a,b)|0)!=0)<<31>>31;break}}else a=-1;while(0);return a|0}function bc(a,b,d,e,f,g,h,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;l=l|0;var m=0,n=0;n=i;m=i=i+63&-64;i=i+16|0;Hc(a|0,0,b|0)|0;if((g|d)>>>0>0|(g|d|0)==0&(f|b)>>>0>4294967295){c[(Zf()|0)>>2]=27;a=-1}else{ob(j,k,l,m+8|0,m+4|0,m);l=Pd(1,0,c[m+8>>2]|0)|0;a=Lc(e,f,h,32,l,D,c[m>>2]|0,c[m+4>>2]|0,a,b)|0}i=n;return a|0}function cc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;h=i;j=i=i+63&-64;i=i+368|0;if((b|0)==0&((e|0)!=0|(f|0)!=0))ba();if(!a)ba();if((d+-1&255)>63)ba();if(!((c|0)!=0|g<<24>>24==0))ba();if((g&255)>64)ba();if(!(g<<24>>24))Ib(j,d);else nb(j,d,c,g);ib(j,b,e,f);ab(j,a,d)|0;i=h;return}function dc(a,b){a=a|0;b=b|0;var c=0,d=0;c=i;d=i=i+63&-64;i=i+48|0;ra(a,b);ra(a+80|0,b+40|0);qa(a+120|0,b+80|0);Kb(a+40|0,b,b+40|0);ra(d,a+40|0);Kb(a+40|0,a+80|0,a);Jb(a+80|0,a+80|0,a);Jb(a,d,a+40|0);Jb(a+120|0,a+120|0,a+80|0);i=c;return}function ec(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;h=i;j=i=i+63&-64;i=i+16|0;Xc(a+64|0,d|0,e|0)|0;zb(a,j,a+64|0,e,f,g)|0;if((c[j>>2]|0)==64&(c[j+4>>2]|0)==0)if(b|0){a=oe(e|0,f|0,64,0)|0;c[b>>2]=a;c[b+4>>2]=D;a=0}else a=0;else{if(b|0){c[b>>2]=0;c[b+4>>2]=0}j=oe(e|0,f|0,64,0)|0;Hc(a|0,0,j|0)|0;a=-1}i=h;return a|0}function fc(a,b){a=a|0;b=b|0;var c=0,d=0;d=i;c=i=i+63&-64;i=i+240|0;if(!(za(c+80|0,b)|0)){Ud(c);Jb(c,c,c+80+40|0);Ia(c,c);Ud(c+40|0);Kb(c+40|0,c+40|0,c+80+40|0);pa(c+40|0,c+40|0,c);La(a,c+40|0);a=0}else a=-1;i=d;return a|0}function gc(a,b,d,e,f,g){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0;e=oe(e|0,f|0,-64,-1)|0;f=D;do if(f>>>0>0|(f|0)==0&e>>>0>4294967231)h=7;else{if(Xa(d,d+64|0,e,f,g)|0){Hc(a|0,0,e|0)|0;h=7;break}if(b|0){c[b>>2]=e;c[b+4>>2]=f}Xc(a|0,d+64|0,e|0)|0;e=0}while(0);if((h|0)==7)if(!b)e=-1;else{c[b>>2]=0;c[b+4>>2]=0;e=-1}return e|0}function hc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0,l=0;l=c[b+4>>2]|0;k=c[b+8>>2]|0;j=c[b+12>>2]|0;i=c[b+16>>2]|0;h=c[b+20>>2]|0;g=c[b+24>>2]|0;f=c[b+28>>2]|0;e=c[b+32>>2]|0;d=c[b+36>>2]|0;c[a>>2]=c[b>>2];c[a+4>>2]=l;c[a+8>>2]=k;c[a+12>>2]=j;c[a+16>>2]=i;c[a+20>>2]=h;c[a+24>>2]=g;c[a+28>>2]=f;c[a+32>>2]=e;c[a+36>>2]=d;return}function ic(b,c,d,e,f,g){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0;j=i;h=i=i+63&-64;i=i+32|0;if(!(e>>>0<0|(e|0)==0&d>>>0<32)?(bd(h,32,0,f,g)|0,k=oe(d|0,e|0,-32,-1)|0,($d(c+16|0,c+32|0,k,D,h)|0)==0):0){Td(b,c,d,e,f,g)|0;c=b+32|0;do{a[b>>0]=0;b=b+1|0}while((b|0)<(c|0));b=0}else b=-1;i=j;return b|0}function jc(b,d){b=b|0;d=d|0;var e=0,f=0,g=0,h=0,i=0;i=a[b>>0]|0;a:do if((i+-48&255)<=9){g=0;h=b;f=i;while(1){e=(f<<24>>24)+-48|0;f=g*10|0;if(g>>>0>429496729|e>>>0>~f>>>0){e=0;break a}g=e+f|0;e=h+1|0;f=a[e>>0]|0;if((f+-48&255)>9)break;else h=e}if((e|0)!=(b|0)?(h|0)==(b|0)|i<<24>>24!=48:0)c[d>>2]=g;else e=0}else e=0;while(0);return e|0}function kc(b){b=b|0;var d=0,e=0,f=0;a:do if(!(b&3)){d=b;f=4}else{d=b;e=b;while(1){if(!(a[d>>0]|0)){d=e;break a}d=d+1|0;e=d;if(!(e&3)){f=4;break}}}while(0);if((f|0)==4){while(1){e=c[d>>2]|0;if(!((e&-2139062144^-2139062144)&e+-16843009))d=d+4|0;else break}if((e&255)<<24>>24)do d=d+1|0;while((a[d>>0]|0)!=0)}return d-b|0}function lc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0,j=0,k=0;k=i;i=i+96|0;if(!(Ve(k+32|0,k)|0)){g=b;h=k+32|0;j=g+32|0;do{a[g>>0]=a[h>>0]|0;g=g+1|0;h=h+1|0}while((g|0)<(j|0));Uc(k+64|0,k+32|0,f);b=qd(b+32|0,c,d,e,k+64|0,f,k)|0;fd(k,32);fd(k+32|0,32);fd(k+64|0,24)}else b=-1;i=k;return b|0}function mc(b,c,d,e){b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0,h=0;h=i;f=i=i+63&-64;i=i+128|0;if((qb(b,0,102)|0)==(b+101|0)){We(f);e=f+12|0;g=e+102|0;do{a[e>>0]=0;e=e+1|0}while((e|0)<(g|0));d=(yb(f,c,d,b,f+12|0)|0)==0;je(f);if(!d){e=Dc(f+12|0,b,102)|0;fd(f+12|0,102)}else e=-1}else e=-1;i=h;return e|0}function nc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;do if(!(c>>>0>64|(d+-1|0)>>>0>63)){if(d>>>0>=256)fa(32441,32461,77,32633);if(c>>>0>=256)fa(32540,32461,78,32633);if((b|0)==0|(c|0)==0){gb(a,d&255,e,f);a=0;break}else{Qa(a,d&255,b,c&255,e,f);a=0;break}}else a=-1;while(0);return a|0}function oc(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;if(g>>>0>0|(g|0)==0&f>>>0>15){d=oe(f|0,g|0,-16,-1)|0;a=lb(a,0,e,d,D,e+f+-16|0,h,i,j,k,l)|0}else a=-1;if(b|0){f=oe(f|0,g|0,-16,-1)|0;g=(a|0)==0;c[b>>2]=g?f:0;c[b+4>>2]=g?D:0}return a|0}function pc(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;if(g>>>0>0|(g|0)==0&f>>>0>15){d=oe(f|0,g|0,-16,-1)|0;a=Db(a,0,e,d,D,e+f+-16|0,h,i,j,k,l)|0}else a=-1;if(b|0){f=oe(f|0,g|0,-16,-1)|0;g=(a|0)==0;c[b>>2]=g?f:0;c[b+4>>2]=g?D:0}return a|0}function qc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0;f=i;g=i=i+63&-64;i=i+112|0;c[g+32>>2]=0;c[g+32+4>>2]=0;c[g>>2]=c[8066];c[g+4>>2]=c[8067];c[g+8>>2]=c[8068];c[g+12>>2]=c[8069];c[g+16>>2]=c[8070];c[g+20>>2]=c[8071];c[g+24>>2]=c[8072];c[g+28>>2]=c[8073];Ua(g,b,d,e)|0;Fb(g,a)|0;i=f;return 0}function rc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;d=i;e=i=i+63&-64;i=i+16|0;Zb(e,a+64|0,16);f=Rd(c[a+72>>2]|0,c[a+72+4>>2]|0,3)|0;f=le((0<0|0==0&(f&127)>>>0<112?112:240)|0,(0<0|0==0&(f&127)>>>0<112?0:0)|0,f&127|0,0)|0;Na(a,32783,f,D)|0;Na(a,e,16,0)|0;Zb(b,a,64);fd(a,208);i=d;return 0}function sc(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0;if(!e)f=0;else{f=a[b>>0]|0;a:do if(!(f<<24>>24))f=0;else while(1){e=e+-1|0;g=a[c>>0]|0;if(!(f<<24>>24==g<<24>>24&((e|0)!=0&g<<24>>24!=0)))break a;b=b+1|0;c=c+1|0;f=a[b>>0]|0;if(!(f<<24>>24)){f=0;break}}while(0);f=(f&255)-(d[c>>0]|0)|0}return f|0}function tc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return da(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if(!e)return f|0;a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b>>0]=a[d>>0]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}function uc(a,b,c,d,e,f,g,h,i){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;var j=0;do if(!((b+-1|0)>>>0>63|g>>>0>64)){if(b>>>0>=256)fa(32441,32461,36,32560);if(g>>>0<256){Xb(a,c,f,b&255,d,e,g&255,h,i);j=0;break}else fa(32540,32461,37,32560)}else j=-1;while(0);return j|0}function vc(b,c){b=b|0;c=c|0;var e=0,f=0;e=i;f=i=i+63&-64;i=i+160|0;Ia(f+80|0,c+80|0);pa(f+40|0,c,f+80|0);pa(f,c+40|0,f+80|0);La(b,f);La(f+120|0,f+40|0);a[b+31>>0]=(d[b+31>>0]|0)^(d[f+120>>0]|0)<<7;i=e;return}function wc(b,c,e,f){b=b|0;c=c|0;e=e|0;f=f|0;var g=0,h=0;if(!(f>>>0<2147483647&f<<1>>>0<c>>>0))ba();if(!f)c=0;else{c=0;do{h=d[e+c>>0]|0;g=c<<1;a[b+g>>0]=(h>>>4)+87+(((h>>>4)+65526|0)>>>8&217);a[b+(g|1)>>0]=(((h&15)<<8)+22272+((h&15)+65526&55552)|0)>>>8;c=c+1|0}while((c|0)!=(f|0));c=f<<1}a[b+c>>0]=0;return b|0}function xc(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,j=0,k=0;g=i;h=i=i+63&-64;i=i+208|0;c[h+64>>2]=0;c[h+64+4>>2]=0;c[h+64+8>>2]=0;c[h+64+12>>2]=0;f=h;j=400;k=f+64|0;do{c[f>>2]=c[j>>2];f=f+4|0;j=j+4|0}while((f|0)<(k|0));Na(h,b,d,e)|0;rc(h,a)|0;i=g;return 0}function yc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;do if(!(c>>>0>64|(d+-1|0)>>>0>63)){if(d>>>0>=256)fa(32441,32461,53,32601);if(c>>>0>=256)fa(32540,32461,54,32601);if((b|0)==0|(c|0)==0){Ib(a,d&255);a=0;break}else{nb(a,d&255,b,c&255);a=0;break}}else a=-1;while(0);return a|0}function zc(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;if(f>>>0>4294967295|(f|0)==-1&e>>>0>4294967279)ba();Ab(a,a+e|0,0,d,e,f,g,h,i,0,k,l)|0;if(b|0){k=oe(e|0,f|0,16,0)|0;c[b>>2]=k;c[b+4>>2]=D}return 0}function Ac(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;if(f>>>0>4294967295|(f|0)==-1&e>>>0>4294967279)ba();Nb(a,a+e|0,0,d,e,f,g,h,i,0,k,l)|0;if(b|0){k=oe(e|0,f|0,16,0)|0;c[b>>2]=k;c[b+4>>2]=D}return 0}function Bc(b,c,e){b=b|0;c=c|0;e=e|0;var f=0,g=0;f=i;g=i=i+63&-64;i=i+160|0;xc(c,e,32,0)|0;a[c>>0]=(d[c>>0]|0)&248;a[c+31>>0]=(d[c+31>>0]|0)&63|64;Pa(g,c);vc(b,g);Xc(c|0,e|0,32)|0;Xc(c+32|0,b|0,32)|0;i=f;return 0}function Cc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0;do if(!((b+-1|0)>>>0>63|g>>>0>64)){if(b>>>0>=256)fa(32441,32461,18,32513);if(g>>>0<256){cc(a,c,f,b&255,d,e,g&255);h=0;break}else fa(32540,32461,19,32513)}else h=-1;while(0);return h|0}function Dc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0;g=i;f=i=i+63&-64;i=i+16|0;c[f+4>>2]=b;c[f>>2]=d;if(!e)b=0;else{d=0;b=0;do{b=a[(c[f>>2]|0)+d>>0]^a[(c[f+4>>2]|0)+d>>0]|b;d=d+1|0}while((d|0)!=(e|0))}i=g;return (((b&255)+511|0)>>>8&1)+-1|0}function Ec(b,c,d){b=b|0;c=c|0;d=d|0;var e=0,f=0,g=0,h=0;g=i;h=i=i+63&-64;i=i+64|0;xc(h,d,32,0)|0;d=c;e=h;f=d+32|0;do{a[d>>0]=a[e>>0]|0;d=d+1|0;e=e+1|0}while((d|0)<(f|0));fd(h,64);h=Qe(b,c)|0;i=g;return h|0}function Fc(b,c){b=b|0;c=c|0;var e=0,f=0,g=0;f=i;g=i=i+63&-64;i=i+64|0;xc(g,c,32,0)|0;a[g>>0]=(d[g>>0]|0)&248;a[g+31>>0]=(d[g+31>>0]|0)&63|64;c=g;e=b+32|0;do{a[b>>0]=a[c>>0]|0;b=b+1|0;c=c+1|0}while((b|0)<(e|0));fd(g,64);i=f;return 0}function Gc(b,c,d,e,f,g){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;if(e>>>0<0|(e|0)==0&d>>>0<32)b=-1;else{Td(b,c,d,e,f,g)|0;c=oe(d|0,e|0,-32,-1)|0;he(b+16|0,b+32|0,c,D,b)|0;c=b+16|0;do{a[b>>0]=0;b=b+1|0}while((b|0)<(c|0));b=0}return b|0}function Hc(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0;f=b+e|0;if((e|0)>=20){d=d&255;g=b&3;h=d|d<<8|d<<16|d<<24;if(g){g=b+4-g|0;while((b|0)<(g|0)){a[b>>0]=d;b=b+1|0}}while((b|0)<(f&~3|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b>>0]=d;b=b+1|0}return b-e|0}function Ic(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0,h=0;h=i;g=i=i+63&-64;i=i+32|0;if(d>>>0<0|(d|0)==0&c>>>0<48)a=-1;else{c=oe(c|0,d|0,-32,-1)|0;d=D;Uc(g,b,e);a=dd(a,b+32|0,c,d,g,b,f)|0}i=h;return a|0}function Jc(b,c,d,e,f){b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;var g=0;g=i;i=i+480|0;sb(g,f,32)|0;Ce(g,c,d,e)|0;od(g,g+416|0)|0;c=g+416|0;d=b+32|0;do{a[b>>0]=a[c>>0]|0;b=b+1|0;c=c+1|0}while((b|0)<(d|0));i=g;return 0}function Kc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;j=i;h=i=i+63&-64;i=i+32|0;if(!(Vc(h,f,g)|0)){a=Yd(a,b,c,d,e,h)|0;fd(h,32)}else a=-1;i=j;return a|0}function Lc(a,b,c,d,e,f,g,h,j,k){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;j=j|0;k=k|0;var l=0,m=0;l=i;m=i=i+63&-64;i=i+16|0;We(m);k=Ca(m,a,b,c,d,e,f,g,h,j,k)|0;je(m);i=l;return k|0}function Mc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0;j=i;h=i=i+63&-64;i=i+32|0;if(!(Vc(h,f,g)|0)){a=ce(a,b,c,d,e,h)|0;fd(h,32)}else a=-1;i=j;return a|0}function Nc(a,b){a=a|0;b=b|0;var d=0,e=0,f=0;e=i;d=i=i+63&-64;i=i+16|0;f=Od(d,b)|0;c[(Zf()|0)>>2]=f;if(!f)d=c[d>>2]|0;else{c[d>>2]=0;d=0}c[a>>2]=d;c[a+4>>2]=d;c[a+8>>2]=d|0?b:0;i=e;return d|0}function Oc(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0;j=i;k=i=i+63&-64;i=i+32|0;Aa(k,e,h,0)|0;Ma(a,b,c,d,e+16|0,f,g,k)|0;fd(k,32);i=j;return 0}function Pc(a){a=a|0;var b=0,d=0;d=a+15&-16|0;b=c[k>>2]|0;a=b+d|0;if((d|0)>0&(a|0)<(b|0)|(a|0)<0){_()|0;ca(12);return -1}c[k>>2]=a;if((a|0)>(Z()|0)?(Y()|0)==0:0){ca(12);c[k>>2]=b;return -1}return b|0}function Qc(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0;j=i;i=i+32|0;if(!(Je(j,g,h)|0)){a=eb(a,b,c,d,e,f,j)|0;fd(j,32)}else a=-1;i=j;return a|0}function Rc(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;var j=0;j=i;i=i+32|0;if(!(Je(j,g,h)|0)){Ya(a,b,c,d,e,f,j)|0;fd(j,32);a=0}else a=-1;i=j;return a|0}function Sc(a){a=a|0;c[a+32>>2]=0;c[a+32+4>>2]=0;c[a>>2]=c[8066];c[a+4>>2]=c[8067];c[a+8>>2]=c[8068];c[a+12>>2]=c[8069];c[a+16>>2]=c[8070];c[a+20>>2]=c[8071];c[a+24>>2]=c[8072];c[a+28>>2]=c[8073];return 0}function Tc(a,b,d,e,f,g,h,i,j,k,l){a=a|0;b=b|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;i=i|0;j=j|0;k=k|0;l=l|0;if((l|0)==1)a=ac(a,b,d,e,f,g,h,i,j,k,1)|0;else{c[(Zf()|0)>>2]=22;a=-1}return a|0}function Uc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=i;e=i=i+63&-64;i=i+368|0;He(e,0,0,24)|0;xe(e,b,32,0)|0;xe(e,c,32,0)|0;Ne(e,a,24)|0;i=d;return}function Vc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;e=i;d=i=i+63&-64;i=i+32|0;if(!(_c(d,c,b)|0)){Aa(a,34476,d,0)|0;a=0}else a=-1;i=e;return a|0}function Wc(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0;f=i;i=i+32|0;Jc(f,b,c,d,e)|0;e=zd(a,f)|0;e=((f|0)==(a|0)?-1:e)|(Dc(f,a,32)|0);i=f;return e|0}function Xc(b,c,d){b=b|0;c=c|0;d=d|0;var e=0;if((c|0)<(b|0)&(b|0)<(c+d|0)){e=b;c=c+d|0;b=b+d|0;while((d|0)>0){b=b-1|0;c=c-1|0;d=d-1|0;a[b>>0]=a[c>>0]|0}b=e}else tc(b,c,d)|0;return b|0}function Yc(a,b){a=a|0;b=b|0;var c=0,d=0,e=0;c=S(b&65535,a&65535)|0;e=(c>>>16)+(S(b&65535,a>>>16)|0)|0;d=S(b>>>16,a&65535)|0;return (D=(e>>>16)+(S(b>>>16,a>>>16)|0)+(((e&65535)+d|0)>>>16)|0,e+d<<16|c&65535|0)|0}function Zc(a,b){a=a|0;b=b|0;pa(a,b,b+120|0);pa(a+40|0,b+40|0,b+80|0);pa(a+80|0,b+80|0,b+120|0);pa(a+120|0,b,b+40|0);return}function _c(b,c,d){b=b|0;c=c|0;d=d|0;if(!(wa(b,c,d)|0)){c=0;d=0;do{d=a[b+c>>0]|d;c=c+1|0}while((c|0)!=32);c=0-(((d&255)+511|0)>>>8&1)|0}else c=-1;return c|0}function $c(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0;f=i;i=i+64|0;ld(f,b,c,d,e)|0;e=yd(a,f)|0;e=((f|0)==(a|0)?-1:e)|(Dc(f,a,64)|0);i=f;return e|0}function ad(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0;f=i;i=i+32|0;md(f,b,c,d,e)|0;e=zd(a,f)|0;e=((f|0)==(a|0)?-1:e)|(Dc(f,a,32)|0);i=f;return e|0}function bd(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;f=i;g=i=i+63&-64;i=i+32|0;Aa(g,d,e,0)|0;fb(a,b,c,d+16|0,g)|0;fd(g,32);i=f;return 0}function cd(a,b){a=a|0;b=b|0;var e=0,f=0,g=0;e=0;g=0;do{f=qb(32982,d[b>>0]|0,65)|0;if(!f){b=0;e=0;break}b=b+1|0;e=f-32982<<g|e;g=g+6|0}while(g>>>0<30);c[a>>2]=e;return b|0}function dd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;if(d>>>0<0|(d|0)==0&c>>>0<16)a=-1;else{d=oe(c|0,d|0,-16,-1)|0;a=Qc(a,b+16|0,b,d,D,e,f,g)|0}return a|0}function ed(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;f=i;g=i=i+63&-64;i=i+16|0;cb(g,b,c,d,e)|0;e=Ad(a,g)|0;i=f;return e|0}function fd(b,d){b=b|0;d=d|0;var e=0,f=0;e=i;f=i=i+63&-64;i=i+16|0;c[f>>2]=b;if(d|0){b=0;do{a[(c[f>>2]|0)+b>>0]=0;b=b+1|0}while((b|0)!=(d|0))}i=e;return}function gd(a,b){a=a|0;b=b|0;var d=0,e=0,f=0,g=0;d=0;do{g=b+(d<<3)|0;e=a+(d<<3)|0;f=c[e+4>>2]^c[g+4>>2];c[e>>2]=c[e>>2]^c[g>>2];c[e+4>>2]=f;d=d+1|0}while((d|0)!=128);return}function hd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;if(d>>>0<0|(d|0)==0&c>>>0<16)a=-1;else{d=oe(c|0,d|0,-16,-1)|0;a=eb(a,b+16|0,b,d,D,e,f)|0}return a|0}function id(b){b=b|0;var c=0;c=a[n+(b&255)>>0]|0;if((c|0)<8)return c|0;c=a[n+(b>>8&255)>>0]|0;if((c|0)<8)return c+8|0;c=a[n+(b>>16&255)>>0]|0;if((c|0)<8)return c+16|0;return (a[n+(b>>>24)>>0]|0)+24|0}function jd(b,c){b=b|0;c=c|0;var d=0,e=0;e=i;i=i+64|0;od(b,e)|0;b=e;d=c+32|0;do{a[c>>0]=a[b>>0]|0;c=c+1|0;b=b+1|0}while((c|0)<(d|0));i=e;return 0}function kd(b,c,d){b=b|0;c=c|0;d=d|0;if(!(d>>>0<1|(d|0)==1&c>>>0<0))fa(33884,33904,172,33930);if(c|0){d=0;do{a[b+d>>0]=$(0)|0;d=d+1|0}while((d|0)!=(c|0))}return}function ld(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0;f=i;i=i+416|0;sb(f,e,32)|0;Na(f,b,c,d)|0;od(f,a)|0;i=f;return 0}function md(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0;f=i;i=i+208|0;tb(f,e,32)|0;Ua(f,b,c,d)|0;pd(f,a)|0;i=f;return 0}function nd(a){a=a|0;var b=0,d=0;c[a+64>>2]=0;c[a+64+4>>2]=0;c[a+64+8>>2]=0;c[a+64+12>>2]=0;b=400;d=a+64|0;do{c[a>>2]=c[b>>2];a=a+4|0;b=b+4|0}while((a|0)<(d|0));return 0}function od(a,b){a=a|0;b=b|0;var c=0;c=i;i=i+64|0;rc(a,c)|0;Na(a+208|0,c,64,0)|0;rc(a+208|0,b)|0;fd(c,64);i=c;return 0}function pd(a,b){a=a|0;b=b|0;var c=0;c=i;i=i+32|0;Fb(a,c)|0;Ua(a+104|0,c,32,0)|0;Fb(a+104|0,b)|0;fd(c,32);i=c;return 0}function qd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;if(d>>>0>0|(d|0)==0&c>>>0>4294967279)a=-1;else a=Rc(a+16|0,a,b,c,d,e,f,g)|0;return a|0}function rd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;if(e>>>0>0|(e|0)==0&d>>>0>4294967295){c[(Zf()|0)>>2]=27;a=-1}else a=((df(a,b,d)|0)!=0)<<31>>31;return a|0}function sd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;if(d>>>0>0|(d|0)==0&c>>>0>4294967279)a=-1;else{Ya(a+16|0,a,b,c,d,e,f)|0;a=0}return a|0}function td(a){a=a|0;return (0-(a^62)|0)>>>8&43^43|(a+65510|0)>>>8&255&a+65|(0-(a^63)|0)>>>8&47^47|(a+65484|0)>>>8&a+71&((a+65510|0)>>>8&255^255)|(a+65474|0)>>>8&a+252&((a+65484|0)>>>8&255^255)|0}function ud(a,b){a=a|0;b=b|0;pa(a,b,b+120|0);pa(a+40|0,b+40|0,b+80|0);pa(a+80|0,b+80|0,b+120|0);return}function vd(a,b){a=a|0;b=b|0;var c=0,d=0;c=i;d=i=i+63&-64;i=i+32|0;Gd(d,32);Bc(a,b,d)|0;fd(d,32);i=c;return 0}function wd(a){a=a|0;var b=0;if(a>>>0<2)a=0;else{do b=$(0)|0;while(b>>>0<(((0-a|0)>>>0)%(a>>>0)|0)>>>0);a=(b>>>0)%(a>>>0)|0}return a|0}function xd(a,b,c){a=a|0;b=b|0;c=c|0;vb(a,b,c&255);vb(a+40|0,b+40|0,c&255);vb(a+80|0,b+80|0,c&255);return}function yd(b,c){b=b|0;c=c|0;var d=0,e=0;d=0;e=0;do{d=(a[c+e>>0]^a[b+e>>0])&255|d;e=e+1|0}while((e|0)!=64);return ((d+511|0)>>>8&1)+-1|0}function zd(b,c){b=b|0;c=c|0;var d=0,e=0;d=0;e=0;do{d=(a[c+e>>0]^a[b+e>>0])&255|d;e=e+1|0}while((e|0)!=32);return ((d+511|0)>>>8&1)+-1|0}function Ad(b,c){b=b|0;c=c|0;var d=0,e=0;d=0;e=0;do{d=(a[c+e>>0]^a[b+e>>0])&255|d;e=e+1|0}while((e|0)!=16);return ((d+511|0)>>>8&1)+-1|0}function Bd(a,b,d,e){a=a|0;b=b|0;d=d|0;e=e|0;var f=0;f=i;i=i+16|0;Ea(a,b,d,e,f|0)|0;i=f;return (D=c[f+4>>2]|0,c[f>>2]|0)|0}function Cd(){}function Dd(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){D=b>>c;return a>>>c|(b&(1<<c)-1)<<32-c}D=(b|0)<0?-1:0;return b>>c-32|0}function Ed(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,f=0;e=Yc(a,c)|0;f=D;return (D=(S(b,c)|0)+(S(d,a)|0)+f|f&0,e|0|0)|0}function Fd(a,b,c){a=a|0;b=b|0;c=c|0;if(c>>>0<256)return ab(a,b,c&255)|0;else fa(32441,32461,106,32679);return 0}function Gd(b,c){b=b|0;c=c|0;var d=0;if(c|0){d=0;do{a[b+d>>0]=$(0)|0;d=d+1|0}while((d|0)!=(c|0))}return}function Hd(b,c){b=b|0;c=c|0;var d=0;d=c;do{if(!d){c=0;break}d=d+-1|0;c=b+d|0}while((a[c>>0]|0)!=36);return c|0}function Id(a,b,c,d,e,f,g,h){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;h=h|0;return Za(a,b,c,d,e,f,g,h)|0}function Jd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return eb(a,b,c,d,e,f,g)|0}function Kd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return Kc(a,b,c,d,e,f,g)|0}function Ld(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return Va(a,b,c,d,e,f,g)|0}function Md(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;Ya(a,b,c,d,e,f,g)|0;return 0}function Nd(){var a=0;a=aa(30)|0;if((a|0)>0)c[8489]=a;else a=c[8489]|0;if(a>>>0<16)ba();else{Gd(34524,16);return}}function Od(a,b){a=a|0;b=b|0;var d=0;if(b>>>0<=4294967168?(d=rb(b)|0,(d|0)!=0):0){c[a>>2]=d;a=0}else a=12;return a|0}function Pd(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){D=b<<c|(a&(1<<c)-1<<32-c)>>>32-c;return a<<c}D=a<<c-32;return 0}function Qd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return Mc(a,b,c,d,e,f,g)|0}function Rd(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){D=b>>>c;return a>>>c|(b&(1<<c)-1)<<32-c}D=0;return b>>>c-32|0}function Sd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return Cc(a,b,c,d,e,f,g)|0}function Td(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;Oc(a,b,c,d,e,0,0,f)|0;return 0}function Ud(a){a=a|0;var b=0;c[a>>2]=1;a=a+4|0;b=a+36|0;do{c[a>>2]=0;a=a+4|0}while((a|0)<(b|0));return}function Vd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return Wb(a,b,c,d,e,f,g)|0}function Wd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;Ma(a,b,c,d,e,0,0,f)|0;return 0}function Xd(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;return xb(a,b,1,c,d,e,16,f,g,0,0)|0}function Yd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return ic(a,b,c,d,e,f)|0}function Zd(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return Va(a,b,c,d,e,0,f)|0}function _d(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;zb(a,b,c,d,e,f)|0;return 0}function $d(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return ed(a,b,c,d,e)|0}function ae(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return xb(a,b,1,c,d,e,16,0,32,f,128)|0}function be(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return Za(a,b,c,d,e,0,0,f)|0}function ce(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return Gc(a,b,c,d,e,f)|0}function de(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;Td(a,b,c,d,e,f)|0;return 0}function ee(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return Yd(a,b,c,d,e,f)|0}function fe(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return Xa(a,b,c,d,e)|0}function ge(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return gc(a,b,c,d,e,f)|0}function he(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return cb(a,b,c,d,e)|0}function ie(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return $d(a,b,c,d,e)|0}function je(a){a=a|0;var b=0;b=c[a>>2]|0;if(b|0)ta(b);c[a+4>>2]=0;c[a>>2]=0;c[a+8>>2]=0;return}function ke(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return ce(a,b,c,d,e,f)|0}function le(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;d=b-d-(c>>>0>a>>>0|0)>>>0;return (D=d,a-c>>>0|0)|0}function me(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;return ec(a,b,c,d,e,f)|0}function ne(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return Fe(a,b,c,d)|0}function oe(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return (D=b+d+(a+c>>>0>>>0<a>>>0|0)>>>0,a+c>>>0|0)|0}function pe(){var a=0;if(!(c[8488]|0)){pf();Nd();c[8488]=1;a=0}else a=1;return a|0}function qe(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return Wc(a,b,c,d,e)|0}function re(a){a=a|0;var b=0;b=a+40|0;do{c[a>>2]=0;a=a+4|0}while((a|0)<(b|0));return}function se(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;sa(a,b,c,d,e)|0;return 0}function te(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return he(a,b,c,d,e)|0}function ue(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;ib(a,b,c,d);return 0}function ve(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Ce(a,b,c,d)|0;return 0}function we(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return Wa(a,b,c,d,e)|0}function xe(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;ue(a,b,c,d)|0;return 0}function ye(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;Jc(a,b,c,d,e)|0;return 0}function ze(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;bd(a,b,c,d,e)|0;return 0}function Ae(a,b){a=a|0;b=b|0;Gd(b,32);return Qe(a,b)|0}function Be(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return ne(a,b,c,d)|0}function Ce(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Na(a,b,c,d)|0;return 0}function De(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Ua(a,b,c,d)|0;return 0}function Ee(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return rd(a,b,c,d)|0}function Fe(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Ra(a,b,c,d);return 0}function Ge(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;return $a(a,b,c,d,e)|0}function He(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return yc(a,b,c,d)|0}function Ie(a,b,c){a=a|0;b=b|0;c=c|0;return Ec(a,b,c)|0}function Je(a,b,c){a=a|0;b=b|0;c=c|0;return Vc(a,b,c)|0}function Ke(b,c){b=b|0;c=c|0;b=Mb(b,c)|0;return ((a[b>>0]|0)==(c&255)<<24>>24?b:0)|0}function Le(a,b,c){a=a|0;b=b|0;c=c|0;sb(a,b,c)|0;return 0}function Me(a,b,c){a=a|0;b=b|0;c=c|0;Bc(a,b,c)|0;return 0}function Ne(a,b,c){a=a|0;b=b|0;c=c|0;return Fd(a,b,c)|0}function Oe(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+15&-16;return b|0}function Pe(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;xc(a,b,c,d)|0;return 0}function Qe(a,b){a=a|0;b=b|0;return Sb(a,b)|0}function Re(a,b){a=a|0;b=b|0;return $e(a,b)|0}function Se(a,b){a=a|0;b=b|0;return hb(a,b)|0}function Te(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return Ea(a,b,c,d,0)|0}function Ue(a,b,c){a=a|0;b=b|0;c=c|0;return _c(a,b,c)|0}function Ve(a,b){a=a|0;b=b|0;return Ae(a,b)|0}function We(a){a=a|0;c[a+4>>2]=0;c[a>>2]=0;c[a+8>>2]=0;return}function Xe(a,b){a=a|0;b=b|0;return Re(a,b)|0}function Ye(a,b){a=a|0;b=b|0;Xc(a|0,b+32|0,32)|0;return 0}function Ze(a,b){a=a|0;b=b|0;return Qe(a,b)|0}function _e(a,b){a=a|0;b=b|0;return Se(a,b)|0}function $e(a,b){a=a|0;b=b|0;Oa(a,b);return 0}function af(a,b){a=a|0;b=b|0;if(!o){o=a;p=b}}function bf(a,b){a=a|0;b=b|0;Xc(a|0,b|0,32)|0;return 0}function cf(a,b){a=a|0;b=b|0;vd(a,b)|0;return 0}function df(a,b,c){a=a|0;b=b|0;c=c|0;return kb(a,b,c)|0}function ef(a,b){a=a|0;b=b|0;tc(a|0,b|0,1024)|0;return}function ff(a,b){a=a|0;b=b|0;i=a;j=b}function gf(a){a=a|0;return Hd(a,(kc(a)|0)+1|0)|0}function hf(){return 1073741824}function jf(){return 16777216}function kf(a){a=a|0;Hc(a|0,0,1024)|0;return}function lf(){return 524288}function mf(){return 33047}function nf(){return $(0)|0}function of(){return 102}function pf(){ea(1);return}function qf(){return 33554432}function rf(){return 536870912}function sf(){return 12}function tf(){return 134217728}function uf(){return 33138}function vf(){return 416}function wf(){return 4}function xf(a){a=a|0;i=a}function yf(){return 32911}function zf(){return 32323}function Af(a){a=a|0;D=a}function Bf(){return 33051}function Cf(){return 6}function Df(){return 256}function Ef(){return 208}function Ff(){return 104}function Gf(){return 384}function Hf(){return 33079}function If(){return 33062}function Jf(){return 3}function Kf(){return 9}function Lf(){return 33129}function Mf(){return 32964}function Nf(){return 32974}function Of(){return 33942}function Pf(){return 33089}function Qf(){return 1}function Rf(){return 32712}function Sf(){return 128}function Tf(){return 32296}function Uf(){return 8}function Vf(){return 24}function Wf(){return D|0}function Xf(){return 48}function Yf(){return 16}function Zf(){return 33960}function _f(){return i|0}function $f(){return 64}function ag(){return 32}function bg(){return 0} - -// EMSCRIPTEN_END_FUNCS -return{_crypto_onetimeauth_poly1305_init:Se,_crypto_hash_sha512_init:nd,_crypto_hash_primitive:Rf,_crypto_onetimeauth_bytes:Yf,_crypto_box_open:Kd,_crypto_stream_chacha20_ietf_noncebytes:sf,_crypto_stream_salsa20_xor:Wd,_randombytes_buf:Gd,_crypto_auth_hmacsha512_verify:$c,_crypto_generichash_blake2b_keybytes_min:Yf,_crypto_sign_open:ge,_crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive:hf,_crypto_sign_ed25519_keypair:vd,_crypto_scalarmult_curve25519_base:Qe,_crypto_stream_salsa20:fb,_crypto_sign_ed25519_open:gc,_sodium_init:pe,_crypto_pwhash_scryptsalsa208sha256:bc,_crypto_scalarmult_primitive:Bf,_crypto_box_noncebytes:Vf,_crypto_aead_chacha20poly1305_ietf_keybytes:ag,_crypto_aead_chacha20poly1305_ietf_encrypt_detached:Ab,_crypto_scalarmult_base:Ze,_crypto_aead_chacha20poly1305_abytes:Yf,_crypto_auth_bytes:ag,_crypto_pwhash_opslimit_sensitive:Uf,_crypto_pwhash_strbytes:Sf,_crypto_auth_hmacsha512256_update:ve,_sbrk:Pc,_memcpy:tc,_crypto_onetimeauth_poly1305:he,_crypto_sign_secretkeybytes:$f,_crypto_generichash_primitive:zf,_crypto_auth_hmacsha512256:Jc,_crypto_box_seed_keypair:Ie,_crypto_auth_hmacsha512_init:sb,_crypto_generichash_blake2b_keybytes_max:$f,_crypto_box_curve25519xsalsa20poly1305_macbytes:Yf,_bitshift64Lshr:Rd,_crypto_pwhash_scryptsalsa208sha256_memlimit_interactive:jf,_crypto_sign_ed25519_sk_to_pk:Ye,_crypto_verify_16_bytes:Yf,_crypto_stream_xsalsa20:bd,_crypto_scalarmult_curve25519:_c,_crypto_box_open_easy_afternm:hd,_crypto_auth_hmacsha512:ld,_crypto_stream_chacha20_ietf_xor_ic:Ld,_crypto_hash:Pe,_crypto_box_curve25519xsalsa20poly1305_seedbytes:ag,_crypto_box_zerobytes:ag,_crypto_stream_salsa20_keybytes:ag,_crypto_auth_hmacsha512256_keybytes:ag,_crypto_aead_chacha20poly1305_keybytes:ag,_crypto_hash_sha512_bytes:$f,_crypto_verify_32:zd,_crypto_generichash_blake2b_final:Fd,_crypto_generichash_blake2b_init_salt_personal:nc,_crypto_box_seal:lc,_crypto_core_hsalsa20_outputbytes:ag,_free:ta,_crypto_sign_ed25519_publickeybytes:ag,_crypto_core_hsalsa20_keybytes:ag,_crypto_sign_primitive:Pf,_crypto_scalarmult_curve25519_bytes:ag,_crypto_auth_keybytes:ag,_crypto_box:Qd,_crypto_stream_xsalsa20_noncebytes:Vf,_crypto_onetimeauth_poly1305_keybytes:ag,_crypto_box_beforenm:Je,_crypto_box_curve25519xsalsa20poly1305_open_afternm:Yd,_crypto_pwhash_scryptsalsa208sha256_saltbytes:ag,_crypto_aead_chacha20poly1305_npubbytes:Uf,_crypto_stream_primitive:Lf,_crypto_pwhash_argon2i_str_verify:rd,_crypto_pwhash_memlimit_sensitive:rf,_crypto_shorthash:se,_crypto_onetimeauth_poly1305_bytes:Yf,_crypto_secretbox_detached:Ya,_crypto_box_curve25519xsalsa20poly1305_seed_keypair:Ec,_crypto_box_primitive:Tf,_crypto_pwhash_str:Vd,_crypto_box_detached_afternm:Md,_crypto_stream_salsa20_xor_ic:Ma,_crypto_secretbox_xsalsa20poly1305_boxzerobytes:Yf,_crypto_core_salsa20_constbytes:Yf,_crypto_auth_hmacsha512_keybytes:ag,_crypto_auth:ye,_crypto_auth_hmacsha512256_final:jd,_randombytes_random:nf,_crypto_stream_chacha20_keybytes:ag,_crypto_pwhash_str_verify:Ee,_crypto_sign_keypair:cf,_crypto_auth_hmacsha256_statebytes:Ef,_crypto_generichash_keybytes_min:Yf,_crypto_generichash_statebytes:Gf,_randombytes:kd,_crypto_aead_chacha20poly1305_encrypt_detached:Nb,_randombytes_implementation_name:uf,_crypto_core_salsa20_keybytes:ag,_sodium_library_version_major:Kf,_crypto_hash_sha256_statebytes:Ff,_crypto_pwhash_strprefix:Mf,_crypto_box_afternm:ke,_crypto_secretbox_primitive:If,_i64Add:oe,_malloc:na,_crypto_scalarmult_curve25519_scalarbytes:ag,_crypto_box_curve25519xsalsa20poly1305_keypair:Ae,_crypto_hash_sha256_init:Sc,_crypto_sign_ed25519_detached:zb,_crypto_pwhash_scryptsalsa208sha256_str_verify:mc,_crypto_generichash_init:He,_crypto_generichash_keybytes_max:$f,_crypto_sign_ed25519_pk_to_curve25519:fc,_crypto_stream_chacha20_ietf_xor:Zd,_crypto_verify_64:yd,_crypto_sign_publickeybytes:ag,_crypto_shorthash_siphash24:sa,_crypto_box_beforenmbytes:ag,_crypto_stream_chacha20_ietf:we,_crypto_generichash:Sd,_crypto_sign_ed25519:ec,_crypto_box_curve25519xsalsa20poly1305_open:Kc,_crypto_pwhash_opslimit_interactive:wf,_sodium_hex2bin:mb,_crypto_onetimeauth_poly1305_final:Re,_crypto_auth_hmacsha256_init:tb,_crypto_aead_chacha20poly1305_ietf_encrypt:zc,_crypto_aead_chacha20poly1305_ietf_nsecbytes:bg,_crypto_box_curve25519xsalsa20poly1305_noncebytes:Vf,_crypto_secretbox:ce,_crypto_box_boxzerobytes:Yf,_crypto_pwhash_argon2i_saltbytes:Yf,_crypto_hash_sha512_update:Na,_crypto_onetimeauth_poly1305_verify:$d,_crypto_box_curve25519xsalsa20poly1305_beforenmbytes:ag,_crypto_generichash_blake2b_init:yc,_crypto_aead_chacha20poly1305_ietf_decrypt:oc,_crypto_auth_hmacsha512256_init:Le,_crypto_pwhash_primitive:Nf,_crypto_onetimeauth_keybytes:ag,_crypto_pwhash_argon2i:ac,_crypto_auth_hmacsha512_final:od,_crypto_sign_ed25519_seedbytes:ag,_crypto_auth_hmacsha512256_verify:Wc,_crypto_auth_hmacsha256_final:pd,_crypto_box_secretkeybytes:ag,_crypto_verify_16:Ad,_crypto_stream_chacha20_noncebytes:Uf,_crypto_onetimeauth_update:Be,_crypto_aead_chacha20poly1305_encrypt:Ac,_crypto_core_salsa20:xa,_crypto_pwhash_scryptsalsa208sha256_ll:Lc,_crypto_box_detached:Rc,_crypto_stream_xsalsa20_xor:Td,_crypto_sign_seedbytes:ag,_memset:Hc,_crypto_pwhash_scryptsalsa208sha256_str:Hb,_crypto_generichash_blake2b_saltbytes:Yf,_bitshift64Ashr:Dd,_bitshift64Shl:Pd,_sodium_version_string:Of,_crypto_box_open_detached:Qc,_crypto_scalarmult_bytes:ag,_crypto_secretbox_xsalsa20poly1305:Gc,_crypto_pwhash:Tc,_crypto_auth_verify:qe,_crypto_sign_ed25519_seed_keypair:Bc,_crypto_secretbox_xsalsa20poly1305_zerobytes:ag,_crypto_onetimeauth_poly1305_update:ne,_crypto_sign_detached:_d,_crypto_verify_32_bytes:ag,_crypto_box_curve25519xsalsa20poly1305_zerobytes:ag,_crypto_generichash_blake2b_keybytes:ag,_crypto_sign_ed25519_secretkeybytes:$f,_crypto_stream_xor:de,_crypto_stream_xsalsa20_xor_ic:Oc,_crypto_verify_64_bytes:$f,_randombytes_stir:pf,_crypto_secretbox_easy:sd,_crypto_pwhash_argon2i_strprefix:Mf,_crypto_auth_hmacsha256_update:De,_crypto_pwhash_scryptsalsa208sha256_strbytes:of,_crypto_stream_chacha20:Ge,_crypto_stream_xsalsa20_keybytes:ag,_crypto_sign:me,_crypto_pwhash_argon2i_str:Wb,_crypto_box_open_detached_afternm:Jd,_crypto_pwhash_argon2i_memlimit_sensitive:rf,_crypto_box_sealbytes:Xf,_crypto_onetimeauth:te,_crypto_auth_hmacsha512_statebytes:vf,_crypto_secretbox_boxzerobytes:Yf,_i64Subtract:le,_crypto_pwhash_alg_default:Qf,_crypto_pwhash_scryptsalsa208sha256_strprefix:mf,_crypto_onetimeauth_primitive:yf,_crypto_box_seedbytes:ag,_crypto_hash_sha256_update:Ua,_crypto_core_hsalsa20_constbytes:Yf,_crypto_box_curve25519xsalsa20poly1305:Mc,_crypto_generichash_blake2b_statebytes:Gf,_crypto_box_curve25519xsalsa20poly1305_boxzerobytes:Yf,_crypto_generichash_blake2b_bytes_min:Yf,_crypto_pwhash_opslimit_moderate:Cf,_crypto_secretbox_open:Yd,_crypto_hash_sha256_bytes:ag,_crypto_core_salsa20_inputbytes:Yf,_crypto_box_macbytes:Yf,_crypto_shorthash_bytes:Uf,_crypto_box_publickeybytes:ag,___udivdi3:Te,_crypto_aead_chacha20poly1305_decrypt_detached:Db,_crypto_auth_hmacsha256_verify:ad,_crypto_pwhash_argon2i_strbytes:Sf,___muldsi3:Yc,_sodium_library_version_minor:Jf,_crypto_scalarmult_scalarbytes:ag,_crypto_onetimeauth_statebytes:Df,_crypto_auth_hmacsha256_bytes:ag,_crypto_sign_seed_keypair:Me,_crypto_pwhash_argon2i_opslimit_interactive:wf,_crypto_stream_salsa20_noncebytes:Uf,_crypto_shorthash_keybytes:Yf,___udivmoddi4:Ea,_crypto_box_curve25519xsalsa20poly1305_afternm:ce,_crypto_stream_noncebytes:Vf,_crypto_aead_chacha20poly1305_decrypt:pc,_sodium_bin2hex:wc,_crypto_secretbox_open_easy:hd,_crypto_aead_chacha20poly1305_ietf_decrypt_detached:lb,_crypto_pwhash_memlimit_interactive:qf,_crypto_hash_sha512_final:rc,_crypto_generichash_final:Ne,_crypto_secretbox_xsalsa20poly1305_keybytes:ag,_crypto_auth_hmacsha512_update:Ce,_crypto_pwhash_saltbytes:Yf,_crypto_auth_hmacsha256:md,_crypto_secretbox_noncebytes:Vf,_crypto_box_keypair:Ve,_crypto_secretbox_xsalsa20poly1305_macbytes:Yf,_crypto_box_open_afternm:ee,_crypto_auth_hmacsha512_bytes:$f,_crypto_generichash_keybytes:ag,_crypto_hash_bytes:$f,_crypto_generichash_bytes_min:Yf,_crypto_pwhash_argon2i_alg_argon2i13:Qf,_crypto_secretbox_macbytes:Yf,_crypto_secretbox_keybytes:ag,_crypto_auth_hmacsha256_keybytes:ag,_crypto_pwhash_argon2i_opslimit_sensitive:Uf,_crypto_aead_chacha20poly1305_ietf_abytes:Yf,_randombytes_close:bg,_crypto_pwhash_argon2i_memlimit_moderate:tf,_crypto_generichash_blake2b_bytes_max:$f,_crypto_generichash_blake2b:Cc,_crypto_generichash_bytes:ag,_crypto_generichash_bytes_max:$f,_crypto_secretbox_open_detached:eb,_crypto_sign_ed25519_sk_to_seed:bf,_crypto_sign_ed25519_sk_to_curve25519:Fc,_crypto_core_salsa20_outputbytes:$f,_crypto_box_easy_afternm:sd,___muldi3:Ed,_crypto_generichash_blake2b_personalbytes:Yf,_crypto_stream_chacha20_xor_ic:Id,___uremdi3:Bd,_crypto_sign_verify_detached:fe,_crypto_pwhash_argon2i_opslimit_moderate:Cf,_crypto_onetimeauth_verify:ie,_crypto_box_open_easy:dd,_crypto_stream:ze,_crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive:qf,_crypto_box_curve25519xsalsa20poly1305_secretkeybytes:ag,_crypto_aead_chacha20poly1305_nsecbytes:bg,_crypto_hash_sha512_statebytes:Ef,_crypto_sign_bytes:$f,_crypto_secretbox_zerobytes:ag,_crypto_generichash_update:xe,_crypto_scalarmult:Ue,_crypto_shorthash_primitive:Hf,_crypto_hash_sha512:xc,_llvm_cttz_i32:id,_crypto_stream_chacha20_xor:be,_crypto_box_seal_open:Ic,_crypto_box_easy:qd,_crypto_sign_ed25519_verify_detached:Xa,_memmove:Xc,_crypto_sign_ed25519_bytes:$f,_crypto_generichash_blake2b_update:ue,_crypto_hash_sha256:qc,_crypto_box_curve25519xsalsa20poly1305_beforenm:Vc,_crypto_pwhash_alg_argon2i13:Qf,_crypto_core_hsalsa20_inputbytes:Yf,_crypto_onetimeauth_final:Xe,_crypto_generichash_blake2b_bytes:ag,_crypto_auth_hmacsha512256_bytes:ag,_crypto_generichash_blake2b_salt_personal:uc,_randombytes_uniform:wd,_crypto_shorthash_siphash24_bytes:Uf,_crypto_auth_hmacsha512256_statebytes:vf,_crypto_shorthash_siphash24_keybytes:Yf,_crypto_secretbox_xsalsa20poly1305_noncebytes:Vf,_crypto_pwhash_scryptsalsa208sha256_opslimit_interactive:lf,_crypto_core_hsalsa20:Aa,_crypto_pwhash_argon2i_memlimit_interactive:qf,_crypto_hash_sha256_final:Fb,_crypto_secretbox_xsalsa20poly1305_open:ic,_crypto_stream_keybytes:ag,_crypto_box_curve25519xsalsa20poly1305_publickeybytes:ag,_crypto_onetimeauth_init:_e,_crypto_aead_chacha20poly1305_ietf_npubbytes:sf,_crypto_pwhash_memlimit_moderate:tf,runPostSets:Cd,stackAlloc:Oe,stackSave:_f,stackRestore:xf,establishStackSpace:ff,setThrew:af,setTempRet0:Af,getTempRet0:Wf}}) - - -// EMSCRIPTEN_END_ASM -(Module.asmGlobalArg,Module.asmLibraryArg,buffer);var _crypto_onetimeauth_poly1305_init=Module["_crypto_onetimeauth_poly1305_init"]=asm["_crypto_onetimeauth_poly1305_init"];var _crypto_hash_sha512_init=Module["_crypto_hash_sha512_init"]=asm["_crypto_hash_sha512_init"];var _crypto_stream_xsalsa20_noncebytes=Module["_crypto_stream_xsalsa20_noncebytes"]=asm["_crypto_stream_xsalsa20_noncebytes"];var _crypto_auth_hmacsha256_verify=Module["_crypto_auth_hmacsha256_verify"]=asm["_crypto_auth_hmacsha256_verify"];var _crypto_onetimeauth_bytes=Module["_crypto_onetimeauth_bytes"]=asm["_crypto_onetimeauth_bytes"];var _crypto_shorthash_primitive=Module["_crypto_shorthash_primitive"]=asm["_crypto_shorthash_primitive"];var _crypto_box_open=Module["_crypto_box_open"]=asm["_crypto_box_open"];var _crypto_stream_chacha20_ietf_noncebytes=Module["_crypto_stream_chacha20_ietf_noncebytes"]=asm["_crypto_stream_chacha20_ietf_noncebytes"];var _crypto_stream_salsa20_xor=Module["_crypto_stream_salsa20_xor"]=asm["_crypto_stream_salsa20_xor"];var _crypto_auth_hmacsha512_verify=Module["_crypto_auth_hmacsha512_verify"]=asm["_crypto_auth_hmacsha512_verify"];var _crypto_generichash_blake2b_keybytes_min=Module["_crypto_generichash_blake2b_keybytes_min"]=asm["_crypto_generichash_blake2b_keybytes_min"];var _crypto_generichash_blake2b_bytes=Module["_crypto_generichash_blake2b_bytes"]=asm["_crypto_generichash_blake2b_bytes"];var _crypto_pwhash_saltbytes=Module["_crypto_pwhash_saltbytes"]=asm["_crypto_pwhash_saltbytes"];var _crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive=Module["_crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive"]=asm["_crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive"];var _crypto_box_seal_open=Module["_crypto_box_seal_open"]=asm["_crypto_box_seal_open"];var _crypto_scalarmult_curve25519_base=Module["_crypto_scalarmult_curve25519_base"]=asm["_crypto_scalarmult_curve25519_base"];var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _sodium_bin2hex=Module["_sodium_bin2hex"]=asm["_sodium_bin2hex"];var _crypto_pwhash_scryptsalsa208sha256=Module["_crypto_pwhash_scryptsalsa208sha256"]=asm["_crypto_pwhash_scryptsalsa208sha256"];var _crypto_scalarmult_primitive=Module["_crypto_scalarmult_primitive"]=asm["_crypto_scalarmult_primitive"];var _crypto_secretbox_xsalsa20poly1305_open=Module["_crypto_secretbox_xsalsa20poly1305_open"]=asm["_crypto_secretbox_xsalsa20poly1305_open"];var _crypto_box_noncebytes=Module["_crypto_box_noncebytes"]=asm["_crypto_box_noncebytes"];var _crypto_aead_chacha20poly1305_ietf_keybytes=Module["_crypto_aead_chacha20poly1305_ietf_keybytes"]=asm["_crypto_aead_chacha20poly1305_ietf_keybytes"];var _crypto_aead_chacha20poly1305_ietf_encrypt_detached=Module["_crypto_aead_chacha20poly1305_ietf_encrypt_detached"]=asm["_crypto_aead_chacha20poly1305_ietf_encrypt_detached"];var _crypto_scalarmult_base=Module["_crypto_scalarmult_base"]=asm["_crypto_scalarmult_base"];var _crypto_aead_chacha20poly1305_abytes=Module["_crypto_aead_chacha20poly1305_abytes"]=asm["_crypto_aead_chacha20poly1305_abytes"];var _crypto_auth_bytes=Module["_crypto_auth_bytes"]=asm["_crypto_auth_bytes"];var _crypto_onetimeauth=Module["_crypto_onetimeauth"]=asm["_crypto_onetimeauth"];var _crypto_stream_chacha20_keybytes=Module["_crypto_stream_chacha20_keybytes"]=asm["_crypto_stream_chacha20_keybytes"];var _crypto_sign_open=Module["_crypto_sign_open"]=asm["_crypto_sign_open"];var _crypto_auth_hmacsha512256_update=Module["_crypto_auth_hmacsha512256_update"]=asm["_crypto_auth_hmacsha512256_update"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var _crypto_onetimeauth_poly1305=Module["_crypto_onetimeauth_poly1305"]=asm["_crypto_onetimeauth_poly1305"];var _crypto_sign_ed25519_keypair=Module["_crypto_sign_ed25519_keypair"]=asm["_crypto_sign_ed25519_keypair"];var _crypto_pwhash=Module["_crypto_pwhash"]=asm["_crypto_pwhash"];var _crypto_auth_hmacsha512256=Module["_crypto_auth_hmacsha512256"]=asm["_crypto_auth_hmacsha512256"];var _crypto_shorthash_siphash24_keybytes=Module["_crypto_shorthash_siphash24_keybytes"]=asm["_crypto_shorthash_siphash24_keybytes"];var _crypto_box_seed_keypair=Module["_crypto_box_seed_keypair"]=asm["_crypto_box_seed_keypair"];var _crypto_auth_hmacsha512_init=Module["_crypto_auth_hmacsha512_init"]=asm["_crypto_auth_hmacsha512_init"];var _crypto_generichash_blake2b_keybytes_max=Module["_crypto_generichash_blake2b_keybytes_max"]=asm["_crypto_generichash_blake2b_keybytes_max"];var _crypto_box_beforenmbytes=Module["_crypto_box_beforenmbytes"]=asm["_crypto_box_beforenmbytes"];var _crypto_pwhash_scryptsalsa208sha256_memlimit_interactive=Module["_crypto_pwhash_scryptsalsa208sha256_memlimit_interactive"]=asm["_crypto_pwhash_scryptsalsa208sha256_memlimit_interactive"];var _crypto_sign_ed25519_sk_to_pk=Module["_crypto_sign_ed25519_sk_to_pk"]=asm["_crypto_sign_ed25519_sk_to_pk"];var _crypto_auth_hmacsha512_update=Module["_crypto_auth_hmacsha512_update"]=asm["_crypto_auth_hmacsha512_update"];var ___udivmoddi4=Module["___udivmoddi4"]=asm["___udivmoddi4"];var _crypto_stream_xsalsa20=Module["_crypto_stream_xsalsa20"]=asm["_crypto_stream_xsalsa20"];var _crypto_scalarmult_curve25519=Module["_crypto_scalarmult_curve25519"]=asm["_crypto_scalarmult_curve25519"];var _crypto_box_open_easy_afternm=Module["_crypto_box_open_easy_afternm"]=asm["_crypto_box_open_easy_afternm"];var _crypto_auth_hmacsha512=Module["_crypto_auth_hmacsha512"]=asm["_crypto_auth_hmacsha512"];var _crypto_stream_chacha20_ietf_xor_ic=Module["_crypto_stream_chacha20_ietf_xor_ic"]=asm["_crypto_stream_chacha20_ietf_xor_ic"];var _crypto_hash_sha256_update=Module["_crypto_hash_sha256_update"]=asm["_crypto_hash_sha256_update"];var _crypto_box_curve25519xsalsa20poly1305_seedbytes=Module["_crypto_box_curve25519xsalsa20poly1305_seedbytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_seedbytes"];var _crypto_box_zerobytes=Module["_crypto_box_zerobytes"]=asm["_crypto_box_zerobytes"];var _crypto_stream_salsa20_keybytes=Module["_crypto_stream_salsa20_keybytes"]=asm["_crypto_stream_salsa20_keybytes"];var _crypto_auth_hmacsha512256_keybytes=Module["_crypto_auth_hmacsha512256_keybytes"]=asm["_crypto_auth_hmacsha512256_keybytes"];var _randombytes_uniform=Module["_randombytes_uniform"]=asm["_randombytes_uniform"];var _crypto_aead_chacha20poly1305_keybytes=Module["_crypto_aead_chacha20poly1305_keybytes"]=asm["_crypto_aead_chacha20poly1305_keybytes"];var _crypto_hash_sha512_bytes=Module["_crypto_hash_sha512_bytes"]=asm["_crypto_hash_sha512_bytes"];var _crypto_onetimeauth_statebytes=Module["_crypto_onetimeauth_statebytes"]=asm["_crypto_onetimeauth_statebytes"];var _crypto_generichash_blake2b_final=Module["_crypto_generichash_blake2b_final"]=asm["_crypto_generichash_blake2b_final"];var _crypto_generichash_blake2b_init_salt_personal=Module["_crypto_generichash_blake2b_init_salt_personal"]=asm["_crypto_generichash_blake2b_init_salt_personal"];var _crypto_box_seal=Module["_crypto_box_seal"]=asm["_crypto_box_seal"];var _crypto_sign_ed25519_publickeybytes=Module["_crypto_sign_ed25519_publickeybytes"]=asm["_crypto_sign_ed25519_publickeybytes"];var _free=Module["_free"]=asm["_free"];var runPostSets=Module["runPostSets"]=asm["runPostSets"];var _crypto_core_hsalsa20_keybytes=Module["_crypto_core_hsalsa20_keybytes"]=asm["_crypto_core_hsalsa20_keybytes"];var _crypto_sign_primitive=Module["_crypto_sign_primitive"]=asm["_crypto_sign_primitive"];var ___uremdi3=Module["___uremdi3"]=asm["___uremdi3"];var _crypto_scalarmult_curve25519_bytes=Module["_crypto_scalarmult_curve25519_bytes"]=asm["_crypto_scalarmult_curve25519_bytes"];var _crypto_auth_keybytes=Module["_crypto_auth_keybytes"]=asm["_crypto_auth_keybytes"];var _crypto_box=Module["_crypto_box"]=asm["_crypto_box"];var _crypto_onetimeauth_poly1305_keybytes=Module["_crypto_onetimeauth_poly1305_keybytes"]=asm["_crypto_onetimeauth_poly1305_keybytes"];var _crypto_box_curve25519xsalsa20poly1305_open_afternm=Module["_crypto_box_curve25519xsalsa20poly1305_open_afternm"]=asm["_crypto_box_curve25519xsalsa20poly1305_open_afternm"];var _crypto_pwhash_scryptsalsa208sha256_saltbytes=Module["_crypto_pwhash_scryptsalsa208sha256_saltbytes"]=asm["_crypto_pwhash_scryptsalsa208sha256_saltbytes"];var _crypto_aead_chacha20poly1305_npubbytes=Module["_crypto_aead_chacha20poly1305_npubbytes"]=asm["_crypto_aead_chacha20poly1305_npubbytes"];var _crypto_stream_primitive=Module["_crypto_stream_primitive"]=asm["_crypto_stream_primitive"];var _crypto_pwhash_argon2i_str_verify=Module["_crypto_pwhash_argon2i_str_verify"]=asm["_crypto_pwhash_argon2i_str_verify"];var _crypto_onetimeauth_poly1305_final=Module["_crypto_onetimeauth_poly1305_final"]=asm["_crypto_onetimeauth_poly1305_final"];var _crypto_shorthash=Module["_crypto_shorthash"]=asm["_crypto_shorthash"];var _crypto_onetimeauth_poly1305_bytes=Module["_crypto_onetimeauth_poly1305_bytes"]=asm["_crypto_onetimeauth_poly1305_bytes"];var _crypto_secretbox_detached=Module["_crypto_secretbox_detached"]=asm["_crypto_secretbox_detached"];var _crypto_box_curve25519xsalsa20poly1305_seed_keypair=Module["_crypto_box_curve25519xsalsa20poly1305_seed_keypair"]=asm["_crypto_box_curve25519xsalsa20poly1305_seed_keypair"];var _crypto_box_primitive=Module["_crypto_box_primitive"]=asm["_crypto_box_primitive"];var _crypto_pwhash_str=Module["_crypto_pwhash_str"]=asm["_crypto_pwhash_str"];var _crypto_box_detached_afternm=Module["_crypto_box_detached_afternm"]=asm["_crypto_box_detached_afternm"];var _crypto_stream_salsa20_xor_ic=Module["_crypto_stream_salsa20_xor_ic"]=asm["_crypto_stream_salsa20_xor_ic"];var _crypto_secretbox_xsalsa20poly1305_boxzerobytes=Module["_crypto_secretbox_xsalsa20poly1305_boxzerobytes"]=asm["_crypto_secretbox_xsalsa20poly1305_boxzerobytes"];var _crypto_auth_hmacsha256_init=Module["_crypto_auth_hmacsha256_init"]=asm["_crypto_auth_hmacsha256_init"];var _crypto_auth_hmacsha512_keybytes=Module["_crypto_auth_hmacsha512_keybytes"]=asm["_crypto_auth_hmacsha512_keybytes"];var _crypto_auth=Module["_crypto_auth"]=asm["_crypto_auth"];var _crypto_auth_hmacsha512256_final=Module["_crypto_auth_hmacsha512256_final"]=asm["_crypto_auth_hmacsha512256_final"];var _randombytes_random=Module["_randombytes_random"]=asm["_randombytes_random"];var _crypto_onetimeauth_verify=Module["_crypto_onetimeauth_verify"]=asm["_crypto_onetimeauth_verify"];var _crypto_pwhash_str_verify=Module["_crypto_pwhash_str_verify"]=asm["_crypto_pwhash_str_verify"];var _crypto_sign_keypair=Module["_crypto_sign_keypair"]=asm["_crypto_sign_keypair"];var _crypto_sign_ed25519_open=Module["_crypto_sign_ed25519_open"]=asm["_crypto_sign_ed25519_open"];var _crypto_generichash_keybytes_min=Module["_crypto_generichash_keybytes_min"]=asm["_crypto_generichash_keybytes_min"];var _crypto_generichash_statebytes=Module["_crypto_generichash_statebytes"]=asm["_crypto_generichash_statebytes"];var _crypto_aead_chacha20poly1305_encrypt_detached=Module["_crypto_aead_chacha20poly1305_encrypt_detached"]=asm["_crypto_aead_chacha20poly1305_encrypt_detached"];var _crypto_core_salsa20_keybytes=Module["_crypto_core_salsa20_keybytes"]=asm["_crypto_core_salsa20_keybytes"];var _crypto_aead_chacha20poly1305_ietf_nsecbytes=Module["_crypto_aead_chacha20poly1305_ietf_nsecbytes"]=asm["_crypto_aead_chacha20poly1305_ietf_nsecbytes"];var _crypto_pwhash_strprefix=Module["_crypto_pwhash_strprefix"]=asm["_crypto_pwhash_strprefix"];var _crypto_box_afternm=Module["_crypto_box_afternm"]=asm["_crypto_box_afternm"];var _crypto_auth_hmacsha512256_bytes=Module["_crypto_auth_hmacsha512256_bytes"]=asm["_crypto_auth_hmacsha512256_bytes"];var _crypto_box_curve25519xsalsa20poly1305_keypair=Module["_crypto_box_curve25519xsalsa20poly1305_keypair"]=asm["_crypto_box_curve25519xsalsa20poly1305_keypair"];var _crypto_hash_sha256_init=Module["_crypto_hash_sha256_init"]=asm["_crypto_hash_sha256_init"];var _crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive=Module["_crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive"]=asm["_crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive"];var _crypto_pwhash_scryptsalsa208sha256_str_verify=Module["_crypto_pwhash_scryptsalsa208sha256_str_verify"]=asm["_crypto_pwhash_scryptsalsa208sha256_str_verify"];var _crypto_hash_primitive=Module["_crypto_hash_primitive"]=asm["_crypto_hash_primitive"];var _crypto_scalarmult_curve25519_scalarbytes=Module["_crypto_scalarmult_curve25519_scalarbytes"]=asm["_crypto_scalarmult_curve25519_scalarbytes"];var _crypto_sign_ed25519_pk_to_curve25519=Module["_crypto_sign_ed25519_pk_to_curve25519"]=asm["_crypto_sign_ed25519_pk_to_curve25519"];var _crypto_verify_64=Module["_crypto_verify_64"]=asm["_crypto_verify_64"];var _crypto_aead_chacha20poly1305_nsecbytes=Module["_crypto_aead_chacha20poly1305_nsecbytes"]=asm["_crypto_aead_chacha20poly1305_nsecbytes"];var _crypto_shorthash_siphash24=Module["_crypto_shorthash_siphash24"]=asm["_crypto_shorthash_siphash24"];var _crypto_box_curve25519xsalsa20poly1305_macbytes=Module["_crypto_box_curve25519xsalsa20poly1305_macbytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_macbytes"];var _crypto_stream_chacha20_ietf=Module["_crypto_stream_chacha20_ietf"]=asm["_crypto_stream_chacha20_ietf"];var _crypto_generichash=Module["_crypto_generichash"]=asm["_crypto_generichash"];var _crypto_sign_ed25519=Module["_crypto_sign_ed25519"]=asm["_crypto_sign_ed25519"];var _crypto_core_hsalsa20_outputbytes=Module["_crypto_core_hsalsa20_outputbytes"]=asm["_crypto_core_hsalsa20_outputbytes"];var _crypto_pwhash_opslimit_interactive=Module["_crypto_pwhash_opslimit_interactive"]=asm["_crypto_pwhash_opslimit_interactive"];var _crypto_box_curve25519xsalsa20poly1305_noncebytes=Module["_crypto_box_curve25519xsalsa20poly1305_noncebytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_noncebytes"];var _crypto_pwhash_memlimit_sensitive=Module["_crypto_pwhash_memlimit_sensitive"]=asm["_crypto_pwhash_memlimit_sensitive"];var _crypto_core_salsa20_constbytes=Module["_crypto_core_salsa20_constbytes"]=asm["_crypto_core_salsa20_constbytes"];var _crypto_box_boxzerobytes=Module["_crypto_box_boxzerobytes"]=asm["_crypto_box_boxzerobytes"];var _sodium_library_version_major=Module["_sodium_library_version_major"]=asm["_sodium_library_version_major"];var _crypto_verify_16_bytes=Module["_crypto_verify_16_bytes"]=asm["_crypto_verify_16_bytes"];var _crypto_aead_chacha20poly1305_ietf_encrypt=Module["_crypto_aead_chacha20poly1305_ietf_encrypt"]=asm["_crypto_aead_chacha20poly1305_ietf_encrypt"];var _crypto_pwhash_argon2i_saltbytes=Module["_crypto_pwhash_argon2i_saltbytes"]=asm["_crypto_pwhash_argon2i_saltbytes"];var _crypto_hash_sha512_update=Module["_crypto_hash_sha512_update"]=asm["_crypto_hash_sha512_update"];var _crypto_onetimeauth_poly1305_verify=Module["_crypto_onetimeauth_poly1305_verify"]=asm["_crypto_onetimeauth_poly1305_verify"];var _crypto_box_beforenm=Module["_crypto_box_beforenm"]=asm["_crypto_box_beforenm"];var _crypto_generichash_blake2b_init=Module["_crypto_generichash_blake2b_init"]=asm["_crypto_generichash_blake2b_init"];var _crypto_aead_chacha20poly1305_ietf_decrypt=Module["_crypto_aead_chacha20poly1305_ietf_decrypt"]=asm["_crypto_aead_chacha20poly1305_ietf_decrypt"];var _crypto_stream_chacha20_ietf_xor=Module["_crypto_stream_chacha20_ietf_xor"]=asm["_crypto_stream_chacha20_ietf_xor"];var _crypto_pwhash_primitive=Module["_crypto_pwhash_primitive"]=asm["_crypto_pwhash_primitive"];var _crypto_scalarmult=Module["_crypto_scalarmult"]=asm["_crypto_scalarmult"];var _crypto_onetimeauth_keybytes=Module["_crypto_onetimeauth_keybytes"]=asm["_crypto_onetimeauth_keybytes"];var _crypto_pwhash_argon2i=Module["_crypto_pwhash_argon2i"]=asm["_crypto_pwhash_argon2i"];var _crypto_auth_hmacsha512256_verify=Module["_crypto_auth_hmacsha512256_verify"]=asm["_crypto_auth_hmacsha512256_verify"];var _crypto_auth_hmacsha256_final=Module["_crypto_auth_hmacsha256_final"]=asm["_crypto_auth_hmacsha256_final"];var _crypto_box_secretkeybytes=Module["_crypto_box_secretkeybytes"]=asm["_crypto_box_secretkeybytes"];var _crypto_verify_16=Module["_crypto_verify_16"]=asm["_crypto_verify_16"];var _crypto_aead_chacha20poly1305_ietf_npubbytes=Module["_crypto_aead_chacha20poly1305_ietf_npubbytes"]=asm["_crypto_aead_chacha20poly1305_ietf_npubbytes"];var _crypto_onetimeauth_update=Module["_crypto_onetimeauth_update"]=asm["_crypto_onetimeauth_update"];var _crypto_aead_chacha20poly1305_encrypt=Module["_crypto_aead_chacha20poly1305_encrypt"]=asm["_crypto_aead_chacha20poly1305_encrypt"];var _crypto_secretbox_zerobytes=Module["_crypto_secretbox_zerobytes"]=asm["_crypto_secretbox_zerobytes"];var _crypto_core_salsa20=Module["_crypto_core_salsa20"]=asm["_crypto_core_salsa20"];var _llvm_cttz_i32=Module["_llvm_cttz_i32"]=asm["_llvm_cttz_i32"];var _crypto_box_curve25519xsalsa20poly1305_beforenmbytes=Module["_crypto_box_curve25519xsalsa20poly1305_beforenmbytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_beforenmbytes"];var _crypto_pwhash_scryptsalsa208sha256_ll=Module["_crypto_pwhash_scryptsalsa208sha256_ll"]=asm["_crypto_pwhash_scryptsalsa208sha256_ll"];var _crypto_box_detached=Module["_crypto_box_detached"]=asm["_crypto_box_detached"];var _randombytes_buf=Module["_randombytes_buf"]=asm["_randombytes_buf"];var _crypto_box_open_detached_afternm=Module["_crypto_box_open_detached_afternm"]=asm["_crypto_box_open_detached_afternm"];var _crypto_sign_seedbytes=Module["_crypto_sign_seedbytes"]=asm["_crypto_sign_seedbytes"];var _crypto_pwhash_scryptsalsa208sha256_strbytes=Module["_crypto_pwhash_scryptsalsa208sha256_strbytes"]=asm["_crypto_pwhash_scryptsalsa208sha256_strbytes"];var _crypto_generichash_blake2b_saltbytes=Module["_crypto_generichash_blake2b_saltbytes"]=asm["_crypto_generichash_blake2b_saltbytes"];var _bitshift64Ashr=Module["_bitshift64Ashr"]=asm["_bitshift64Ashr"];var _crypto_box_open_detached=Module["_crypto_box_open_detached"]=asm["_crypto_box_open_detached"];var _crypto_scalarmult_bytes=Module["_crypto_scalarmult_bytes"]=asm["_crypto_scalarmult_bytes"];var _crypto_secretbox_xsalsa20poly1305=Module["_crypto_secretbox_xsalsa20poly1305"]=asm["_crypto_secretbox_xsalsa20poly1305"];var _crypto_auth_verify=Module["_crypto_auth_verify"]=asm["_crypto_auth_verify"];var _crypto_sign_ed25519_seed_keypair=Module["_crypto_sign_ed25519_seed_keypair"]=asm["_crypto_sign_ed25519_seed_keypair"];var _crypto_secretbox_xsalsa20poly1305_zerobytes=Module["_crypto_secretbox_xsalsa20poly1305_zerobytes"]=asm["_crypto_secretbox_xsalsa20poly1305_zerobytes"];var _crypto_onetimeauth_poly1305_update=Module["_crypto_onetimeauth_poly1305_update"]=asm["_crypto_onetimeauth_poly1305_update"];var _crypto_auth_hmacsha512256_init=Module["_crypto_auth_hmacsha512256_init"]=asm["_crypto_auth_hmacsha512256_init"];var _crypto_auth_hmacsha256=Module["_crypto_auth_hmacsha256"]=asm["_crypto_auth_hmacsha256"];var _crypto_pwhash_strbytes=Module["_crypto_pwhash_strbytes"]=asm["_crypto_pwhash_strbytes"];var _crypto_stream_xor=Module["_crypto_stream_xor"]=asm["_crypto_stream_xor"];var _crypto_stream_xsalsa20_xor_ic=Module["_crypto_stream_xsalsa20_xor_ic"]=asm["_crypto_stream_xsalsa20_xor_ic"];var _crypto_verify_64_bytes=Module["_crypto_verify_64_bytes"]=asm["_crypto_verify_64_bytes"];var _randombytes_stir=Module["_randombytes_stir"]=asm["_randombytes_stir"];var _crypto_secretbox_easy=Module["_crypto_secretbox_easy"]=asm["_crypto_secretbox_easy"];var _crypto_box_open_easy=Module["_crypto_box_open_easy"]=asm["_crypto_box_open_easy"];var _crypto_pwhash_argon2i_strprefix=Module["_crypto_pwhash_argon2i_strprefix"]=asm["_crypto_pwhash_argon2i_strprefix"];var _crypto_auth_hmacsha256_update=Module["_crypto_auth_hmacsha256_update"]=asm["_crypto_auth_hmacsha256_update"];var _crypto_pwhash_scryptsalsa208sha256_str=Module["_crypto_pwhash_scryptsalsa208sha256_str"]=asm["_crypto_pwhash_scryptsalsa208sha256_str"];var _memset=Module["_memset"]=asm["_memset"];var _crypto_stream_salsa20=Module["_crypto_stream_salsa20"]=asm["_crypto_stream_salsa20"];var _crypto_pwhash_argon2i_str=Module["_crypto_pwhash_argon2i_str"]=asm["_crypto_pwhash_argon2i_str"];var _crypto_hash=Module["_crypto_hash"]=asm["_crypto_hash"];var _crypto_pwhash_argon2i_memlimit_sensitive=Module["_crypto_pwhash_argon2i_memlimit_sensitive"]=asm["_crypto_pwhash_argon2i_memlimit_sensitive"];var _crypto_pwhash_argon2i_opslimit_sensitive=Module["_crypto_pwhash_argon2i_opslimit_sensitive"]=asm["_crypto_pwhash_argon2i_opslimit_sensitive"];var _crypto_box_sealbytes=Module["_crypto_box_sealbytes"]=asm["_crypto_box_sealbytes"];var _crypto_auth_hmacsha512_final=Module["_crypto_auth_hmacsha512_final"]=asm["_crypto_auth_hmacsha512_final"];var _crypto_auth_hmacsha512_statebytes=Module["_crypto_auth_hmacsha512_statebytes"]=asm["_crypto_auth_hmacsha512_statebytes"];var _crypto_secretbox_boxzerobytes=Module["_crypto_secretbox_boxzerobytes"]=asm["_crypto_secretbox_boxzerobytes"];var _i64Subtract=Module["_i64Subtract"]=asm["_i64Subtract"];var _crypto_pwhash_alg_default=Module["_crypto_pwhash_alg_default"]=asm["_crypto_pwhash_alg_default"];var _crypto_pwhash_scryptsalsa208sha256_strprefix=Module["_crypto_pwhash_scryptsalsa208sha256_strprefix"]=asm["_crypto_pwhash_scryptsalsa208sha256_strprefix"];var _crypto_onetimeauth_primitive=Module["_crypto_onetimeauth_primitive"]=asm["_crypto_onetimeauth_primitive"];var _crypto_box_seedbytes=Module["_crypto_box_seedbytes"]=asm["_crypto_box_seedbytes"];var _crypto_stream_chacha20=Module["_crypto_stream_chacha20"]=asm["_crypto_stream_chacha20"];var _crypto_core_hsalsa20_constbytes=Module["_crypto_core_hsalsa20_constbytes"]=asm["_crypto_core_hsalsa20_constbytes"];var _crypto_generichash_bytes=Module["_crypto_generichash_bytes"]=asm["_crypto_generichash_bytes"];var _crypto_secretbox=Module["_crypto_secretbox"]=asm["_crypto_secretbox"];var _crypto_generichash_blake2b_statebytes=Module["_crypto_generichash_blake2b_statebytes"]=asm["_crypto_generichash_blake2b_statebytes"];var _crypto_box_open_afternm=Module["_crypto_box_open_afternm"]=asm["_crypto_box_open_afternm"];var _crypto_generichash_blake2b_bytes_min=Module["_crypto_generichash_blake2b_bytes_min"]=asm["_crypto_generichash_blake2b_bytes_min"];var _crypto_pwhash_opslimit_moderate=Module["_crypto_pwhash_opslimit_moderate"]=asm["_crypto_pwhash_opslimit_moderate"];var _crypto_secretbox_open=Module["_crypto_secretbox_open"]=asm["_crypto_secretbox_open"];var _crypto_auth_hmacsha512_bytes=Module["_crypto_auth_hmacsha512_bytes"]=asm["_crypto_auth_hmacsha512_bytes"];var _crypto_core_salsa20_inputbytes=Module["_crypto_core_salsa20_inputbytes"]=asm["_crypto_core_salsa20_inputbytes"];var _crypto_box_macbytes=Module["_crypto_box_macbytes"]=asm["_crypto_box_macbytes"];var _crypto_secretbox_macbytes=Module["_crypto_secretbox_macbytes"]=asm["_crypto_secretbox_macbytes"];var _crypto_shorthash_bytes=Module["_crypto_shorthash_bytes"]=asm["_crypto_shorthash_bytes"];var _crypto_box_publickeybytes=Module["_crypto_box_publickeybytes"]=asm["_crypto_box_publickeybytes"];var _crypto_generichash_keybytes=Module["_crypto_generichash_keybytes"]=asm["_crypto_generichash_keybytes"];var _crypto_generichash_primitive=Module["_crypto_generichash_primitive"]=asm["_crypto_generichash_primitive"];var _crypto_sign_secretkeybytes=Module["_crypto_sign_secretkeybytes"]=asm["_crypto_sign_secretkeybytes"];var _crypto_pwhash_argon2i_strbytes=Module["_crypto_pwhash_argon2i_strbytes"]=asm["_crypto_pwhash_argon2i_strbytes"];var ___muldsi3=Module["___muldsi3"]=asm["___muldsi3"];var _crypto_hash_sha512_statebytes=Module["_crypto_hash_sha512_statebytes"]=asm["_crypto_hash_sha512_statebytes"];var _crypto_scalarmult_scalarbytes=Module["_crypto_scalarmult_scalarbytes"]=asm["_crypto_scalarmult_scalarbytes"];var _crypto_verify_32=Module["_crypto_verify_32"]=asm["_crypto_verify_32"];var _crypto_auth_hmacsha256_bytes=Module["_crypto_auth_hmacsha256_bytes"]=asm["_crypto_auth_hmacsha256_bytes"];var _crypto_auth_hmacsha256_statebytes=Module["_crypto_auth_hmacsha256_statebytes"]=asm["_crypto_auth_hmacsha256_statebytes"];var _crypto_pwhash_argon2i_opslimit_interactive=Module["_crypto_pwhash_argon2i_opslimit_interactive"]=asm["_crypto_pwhash_argon2i_opslimit_interactive"];var _crypto_aead_chacha20poly1305_decrypt=Module["_crypto_aead_chacha20poly1305_decrypt"]=asm["_crypto_aead_chacha20poly1305_decrypt"];var _crypto_stream_salsa20_noncebytes=Module["_crypto_stream_salsa20_noncebytes"]=asm["_crypto_stream_salsa20_noncebytes"];var _crypto_shorthash_keybytes=Module["_crypto_shorthash_keybytes"]=asm["_crypto_shorthash_keybytes"];var _malloc=Module["_malloc"]=asm["_malloc"];var _crypto_stream_noncebytes=Module["_crypto_stream_noncebytes"]=asm["_crypto_stream_noncebytes"];var _crypto_generichash_keybytes_max=Module["_crypto_generichash_keybytes_max"]=asm["_crypto_generichash_keybytes_max"];var _sodium_version_string=Module["_sodium_version_string"]=asm["_sodium_version_string"];var _memmove=Module["_memmove"]=asm["_memmove"];var _crypto_aead_chacha20poly1305_ietf_decrypt_detached=Module["_crypto_aead_chacha20poly1305_ietf_decrypt_detached"]=asm["_crypto_aead_chacha20poly1305_ietf_decrypt_detached"];var _crypto_hash_sha512_final=Module["_crypto_hash_sha512_final"]=asm["_crypto_hash_sha512_final"];var _crypto_pwhash_memlimit_interactive=Module["_crypto_pwhash_memlimit_interactive"]=asm["_crypto_pwhash_memlimit_interactive"];var _crypto_secretbox_xsalsa20poly1305_keybytes=Module["_crypto_secretbox_xsalsa20poly1305_keybytes"]=asm["_crypto_secretbox_xsalsa20poly1305_keybytes"];var _crypto_aead_chacha20poly1305_decrypt_detached=Module["_crypto_aead_chacha20poly1305_decrypt_detached"]=asm["_crypto_aead_chacha20poly1305_decrypt_detached"];var _crypto_sign=Module["_crypto_sign"]=asm["_crypto_sign"];var _crypto_box_curve25519xsalsa20poly1305_zerobytes=Module["_crypto_box_curve25519xsalsa20poly1305_zerobytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_zerobytes"];var _crypto_secretbox_noncebytes=Module["_crypto_secretbox_noncebytes"]=asm["_crypto_secretbox_noncebytes"];var _crypto_box_keypair=Module["_crypto_box_keypair"]=asm["_crypto_box_keypair"];var _crypto_secretbox_xsalsa20poly1305_macbytes=Module["_crypto_secretbox_xsalsa20poly1305_macbytes"]=asm["_crypto_secretbox_xsalsa20poly1305_macbytes"];var _crypto_box_curve25519xsalsa20poly1305_boxzerobytes=Module["_crypto_box_curve25519xsalsa20poly1305_boxzerobytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_boxzerobytes"];var _crypto_hash_sha256_bytes=Module["_crypto_hash_sha256_bytes"]=asm["_crypto_hash_sha256_bytes"];var ___udivdi3=Module["___udivdi3"]=asm["___udivdi3"];var _crypto_hash_bytes=Module["_crypto_hash_bytes"]=asm["_crypto_hash_bytes"];var _sodium_hex2bin=Module["_sodium_hex2bin"]=asm["_sodium_hex2bin"];var _sodium_init=Module["_sodium_init"]=asm["_sodium_init"];var _crypto_box_curve25519xsalsa20poly1305_afternm=Module["_crypto_box_curve25519xsalsa20poly1305_afternm"]=asm["_crypto_box_curve25519xsalsa20poly1305_afternm"];var _crypto_auth_hmacsha256_keybytes=Module["_crypto_auth_hmacsha256_keybytes"]=asm["_crypto_auth_hmacsha256_keybytes"];var _crypto_secretbox_keybytes=Module["_crypto_secretbox_keybytes"]=asm["_crypto_secretbox_keybytes"];var _crypto_box_easy=Module["_crypto_box_easy"]=asm["_crypto_box_easy"];var _randombytes=Module["_randombytes"]=asm["_randombytes"];var _crypto_sign_publickeybytes=Module["_crypto_sign_publickeybytes"]=asm["_crypto_sign_publickeybytes"];var _randombytes_close=Module["_randombytes_close"]=asm["_randombytes_close"];var _crypto_pwhash_argon2i_memlimit_moderate=Module["_crypto_pwhash_argon2i_memlimit_moderate"]=asm["_crypto_pwhash_argon2i_memlimit_moderate"];var _crypto_generichash_blake2b_bytes_max=Module["_crypto_generichash_blake2b_bytes_max"]=asm["_crypto_generichash_blake2b_bytes_max"];var _crypto_generichash_blake2b=Module["_crypto_generichash_blake2b"]=asm["_crypto_generichash_blake2b"];var _crypto_stream_chacha20_noncebytes=Module["_crypto_stream_chacha20_noncebytes"]=asm["_crypto_stream_chacha20_noncebytes"];var _crypto_hash_sha256_statebytes=Module["_crypto_hash_sha256_statebytes"]=asm["_crypto_hash_sha256_statebytes"];var _crypto_secretbox_open_detached=Module["_crypto_secretbox_open_detached"]=asm["_crypto_secretbox_open_detached"];var _crypto_sign_ed25519_sk_to_seed=Module["_crypto_sign_ed25519_sk_to_seed"]=asm["_crypto_sign_ed25519_sk_to_seed"];var _crypto_core_salsa20_outputbytes=Module["_crypto_core_salsa20_outputbytes"]=asm["_crypto_core_salsa20_outputbytes"];var _crypto_sign_ed25519_secretkeybytes=Module["_crypto_sign_ed25519_secretkeybytes"]=asm["_crypto_sign_ed25519_secretkeybytes"];var _crypto_pwhash_opslimit_sensitive=Module["_crypto_pwhash_opslimit_sensitive"]=asm["_crypto_pwhash_opslimit_sensitive"];var ___muldi3=Module["___muldi3"]=asm["___muldi3"];var _crypto_generichash_blake2b_personalbytes=Module["_crypto_generichash_blake2b_personalbytes"]=asm["_crypto_generichash_blake2b_personalbytes"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var _crypto_box_curve25519xsalsa20poly1305_open=Module["_crypto_box_curve25519xsalsa20poly1305_open"]=asm["_crypto_box_curve25519xsalsa20poly1305_open"];var _crypto_sign_verify_detached=Module["_crypto_sign_verify_detached"]=asm["_crypto_sign_verify_detached"];var _crypto_pwhash_argon2i_opslimit_moderate=Module["_crypto_pwhash_argon2i_opslimit_moderate"]=asm["_crypto_pwhash_argon2i_opslimit_moderate"];var _crypto_pwhash_alg_argon2i13=Module["_crypto_pwhash_alg_argon2i13"]=asm["_crypto_pwhash_alg_argon2i13"];var _randombytes_implementation_name=Module["_randombytes_implementation_name"]=asm["_randombytes_implementation_name"];var _crypto_box_curve25519xsalsa20poly1305=Module["_crypto_box_curve25519xsalsa20poly1305"]=asm["_crypto_box_curve25519xsalsa20poly1305"];var _crypto_stream=Module["_crypto_stream"]=asm["_crypto_stream"];var _crypto_sign_ed25519_detached=Module["_crypto_sign_ed25519_detached"]=asm["_crypto_sign_ed25519_detached"];var _crypto_generichash_init=Module["_crypto_generichash_init"]=asm["_crypto_generichash_init"];var _i64Add=Module["_i64Add"]=asm["_i64Add"];var _crypto_sign_ed25519_sk_to_curve25519=Module["_crypto_sign_ed25519_sk_to_curve25519"]=asm["_crypto_sign_ed25519_sk_to_curve25519"];var _crypto_sign_bytes=Module["_crypto_sign_bytes"]=asm["_crypto_sign_bytes"];var _crypto_secretbox_primitive=Module["_crypto_secretbox_primitive"]=asm["_crypto_secretbox_primitive"];var _crypto_generichash_update=Module["_crypto_generichash_update"]=asm["_crypto_generichash_update"];var _crypto_generichash_blake2b_update=Module["_crypto_generichash_blake2b_update"]=asm["_crypto_generichash_blake2b_update"];var _crypto_verify_32_bytes=Module["_crypto_verify_32_bytes"]=asm["_crypto_verify_32_bytes"];var _crypto_aead_chacha20poly1305_ietf_abytes=Module["_crypto_aead_chacha20poly1305_ietf_abytes"]=asm["_crypto_aead_chacha20poly1305_ietf_abytes"];var _crypto_generichash_blake2b_keybytes=Module["_crypto_generichash_blake2b_keybytes"]=asm["_crypto_generichash_blake2b_keybytes"];var _crypto_generichash_bytes_min=Module["_crypto_generichash_bytes_min"]=asm["_crypto_generichash_bytes_min"];var _crypto_box_curve25519xsalsa20poly1305_secretkeybytes=Module["_crypto_box_curve25519xsalsa20poly1305_secretkeybytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_secretkeybytes"];var _crypto_stream_xsalsa20_xor=Module["_crypto_stream_xsalsa20_xor"]=asm["_crypto_stream_xsalsa20_xor"];var _crypto_sign_detached=Module["_crypto_sign_detached"]=asm["_crypto_sign_detached"];var _crypto_hash_sha512=Module["_crypto_hash_sha512"]=asm["_crypto_hash_sha512"];var _crypto_generichash_bytes_max=Module["_crypto_generichash_bytes_max"]=asm["_crypto_generichash_bytes_max"];var _crypto_box_easy_afternm=Module["_crypto_box_easy_afternm"]=asm["_crypto_box_easy_afternm"];var _crypto_stream_chacha20_xor_ic=Module["_crypto_stream_chacha20_xor_ic"]=asm["_crypto_stream_chacha20_xor_ic"];var _crypto_sign_ed25519_verify_detached=Module["_crypto_sign_ed25519_verify_detached"]=asm["_crypto_sign_ed25519_verify_detached"];var _crypto_sign_ed25519_bytes=Module["_crypto_sign_ed25519_bytes"]=asm["_crypto_sign_ed25519_bytes"];var _crypto_stream_xsalsa20_keybytes=Module["_crypto_stream_xsalsa20_keybytes"]=asm["_crypto_stream_xsalsa20_keybytes"];var _crypto_hash_sha256=Module["_crypto_hash_sha256"]=asm["_crypto_hash_sha256"];var _crypto_sign_ed25519_seedbytes=Module["_crypto_sign_ed25519_seedbytes"]=asm["_crypto_sign_ed25519_seedbytes"];var _sodium_library_version_minor=Module["_sodium_library_version_minor"]=asm["_sodium_library_version_minor"];var _crypto_core_hsalsa20_inputbytes=Module["_crypto_core_hsalsa20_inputbytes"]=asm["_crypto_core_hsalsa20_inputbytes"];var _crypto_onetimeauth_final=Module["_crypto_onetimeauth_final"]=asm["_crypto_onetimeauth_final"];var _crypto_secretbox_open_easy=Module["_crypto_secretbox_open_easy"]=asm["_crypto_secretbox_open_easy"];var _crypto_generichash_final=Module["_crypto_generichash_final"]=asm["_crypto_generichash_final"];var _crypto_generichash_blake2b_salt_personal=Module["_crypto_generichash_blake2b_salt_personal"]=asm["_crypto_generichash_blake2b_salt_personal"];var _crypto_pwhash_argon2i_alg_argon2i13=Module["_crypto_pwhash_argon2i_alg_argon2i13"]=asm["_crypto_pwhash_argon2i_alg_argon2i13"];var _crypto_shorthash_siphash24_bytes=Module["_crypto_shorthash_siphash24_bytes"]=asm["_crypto_shorthash_siphash24_bytes"];var _crypto_auth_hmacsha512256_statebytes=Module["_crypto_auth_hmacsha512256_statebytes"]=asm["_crypto_auth_hmacsha512256_statebytes"];var _crypto_sign_seed_keypair=Module["_crypto_sign_seed_keypair"]=asm["_crypto_sign_seed_keypair"];var _crypto_secretbox_xsalsa20poly1305_noncebytes=Module["_crypto_secretbox_xsalsa20poly1305_noncebytes"]=asm["_crypto_secretbox_xsalsa20poly1305_noncebytes"];var _crypto_pwhash_scryptsalsa208sha256_opslimit_interactive=Module["_crypto_pwhash_scryptsalsa208sha256_opslimit_interactive"]=asm["_crypto_pwhash_scryptsalsa208sha256_opslimit_interactive"];var _crypto_box_curve25519xsalsa20poly1305_beforenm=Module["_crypto_box_curve25519xsalsa20poly1305_beforenm"]=asm["_crypto_box_curve25519xsalsa20poly1305_beforenm"];var _crypto_pwhash_argon2i_memlimit_interactive=Module["_crypto_pwhash_argon2i_memlimit_interactive"]=asm["_crypto_pwhash_argon2i_memlimit_interactive"];var _crypto_hash_sha256_final=Module["_crypto_hash_sha256_final"]=asm["_crypto_hash_sha256_final"];var _crypto_stream_chacha20_xor=Module["_crypto_stream_chacha20_xor"]=asm["_crypto_stream_chacha20_xor"];var _crypto_stream_keybytes=Module["_crypto_stream_keybytes"]=asm["_crypto_stream_keybytes"];var _crypto_box_curve25519xsalsa20poly1305_publickeybytes=Module["_crypto_box_curve25519xsalsa20poly1305_publickeybytes"]=asm["_crypto_box_curve25519xsalsa20poly1305_publickeybytes"];var _crypto_onetimeauth_init=Module["_crypto_onetimeauth_init"]=asm["_crypto_onetimeauth_init"];var _crypto_core_hsalsa20=Module["_crypto_core_hsalsa20"]=asm["_crypto_core_hsalsa20"];var _crypto_pwhash_memlimit_moderate=Module["_crypto_pwhash_memlimit_moderate"]=asm["_crypto_pwhash_memlimit_moderate"];Runtime.stackAlloc=asm["stackAlloc"];Runtime.stackSave=asm["stackSave"];Runtime.stackRestore=asm["stackRestore"];Runtime.establishStackSpace=asm["establishStackSpace"];Runtime.setTempRet0=asm["setTempRet0"];Runtime.getTempRet0=asm["getTempRet0"];function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;var preloadStartTime=null;var calledMain=false;dependenciesFulfilled=function runCaller(){if(!Module["calledRun"])run();if(!Module["calledRun"])dependenciesFulfilled=runCaller};Module["callMain"]=Module.callMain=function callMain(args){args=args||[];ensureInitRuntime();var argc=args.length+1;function pad(){for(var i=0;i<4-1;i++){argv.push(0)}}var argv=[allocate(intArrayFromString(Module["thisProgram"]),"i8",ALLOC_NORMAL)];pad();for(var i=0;i<argc-1;i=i+1){argv.push(allocate(intArrayFromString(args[i]),"i8",ALLOC_NORMAL));pad()}argv.push(0);argv=allocate(argv,"i32",ALLOC_NORMAL);try{var ret=Module["_main"](argc,argv,0);exit(ret,true)}catch(e){if(e instanceof ExitStatus){return}else if(e=="SimulateInfiniteLoop"){Module["noExitRuntime"]=true;return}else{if(e&&typeof e==="object"&&e.stack)Module.printErr("exception thrown: "+[e,e.stack]);throw e}}finally{calledMain=true}};function run(args){args=args||Module["arguments"];if(preloadStartTime===null)preloadStartTime=Date.now();if(runDependencies>0){return}preRun();if(runDependencies>0)return;if(Module["calledRun"])return;function doRun(){if(Module["calledRun"])return;Module["calledRun"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(Module["_main"]&&shouldRunNow)Module["callMain"](args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}Module["run"]=Module.run=run;function exit(status,implicit){if(implicit&&Module["noExitRuntime"]){return}if(Module["noExitRuntime"]){}else{ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(Module["onExit"])Module["onExit"](status)}if(ENVIRONMENT_IS_NODE){process["exit"](status)}else if(ENVIRONMENT_IS_SHELL&&typeof quit==="function"){quit(status)}throw new ExitStatus(status)}Module["exit"]=Module.exit=exit;var abortDecorators=[];function abort(what){if(what!==undefined){Module.print(what);Module.printErr(what);what=JSON.stringify(what)}else{what=""}ABORT=true;EXITSTATUS=1;var extra="\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";var output="abort("+what+") at "+stackTrace()+extra;if(abortDecorators){abortDecorators.forEach((function(decorator){output=decorator(output,what)}))}throw output}Module["abort"]=Module.abort=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"]){shouldRunNow=false}run() - - - - -var nacl = (function () { - 'use strict'; - var exports = {}; - - //--------------------------------------------------------------------------- - // Horrifying UTF-8 and hex codecs - - function encode_utf8(s) { - return encode_latin1(unescape(encodeURIComponent(s))); - } - - function encode_latin1(s) { - var result = new Uint8Array(s.length); - for (var i = 0; i < s.length; i++) { - var c = s.charCodeAt(i); - if ((c & 0xff) !== c) throw {message: "Cannot encode string in Latin1", str: s}; - result[i] = (c & 0xff); - } - return result; - } - - function decode_utf8(bs) { - return decodeURIComponent(escape(decode_latin1(bs))); - } - - function decode_latin1(bs) { - var encoded = []; - for (var i = 0; i < bs.length; i++) { - encoded.push(String.fromCharCode(bs[i])); - } - return encoded.join(''); - } - - function to_hex(bs) { - var encoded = []; - for (var i = 0; i < bs.length; i++) { - encoded.push("0123456789abcdef"[(bs[i] >> 4) & 15]); - encoded.push("0123456789abcdef"[bs[i] & 15]); - } - return encoded.join(''); - } - - function from_hex(s) { - var result = new Uint8Array(s.length / 2); - for (var i = 0; i < s.length / 2; i++) { - result[i] = parseInt(s.substr(2*i,2),16); - } - return result; - } - - //--------------------------------------------------------------------------- - // Allocation - - function MALLOC(nbytes) { - var result = nacl_raw._malloc(nbytes); - if (result === 0) { - throw {message: "malloc() failed", nbytes: nbytes}; - } - return result; - } - - function FREE(pointer) { - nacl_raw._free(pointer); - } - - //--------------------------------------------------------------------------- - - function injectBytes(bs, leftPadding) { - var p = leftPadding || 0; - var address = MALLOC(bs.length + p); - nacl_raw.HEAPU8.set(bs, address + p); - for (var i = address; i < address + p; i++) { - nacl_raw.HEAPU8[i] = 0; - } - return address; - } - - function check_injectBytes(function_name, what, thing, expected_length, leftPadding) { - check_length(function_name, what, thing, expected_length); - return injectBytes(thing, leftPadding); - } - - function extractBytes(address, length) { - var result = new Uint8Array(length); - result.set(nacl_raw.HEAPU8.subarray(address, address + length)); - return result; - } - - //--------------------------------------------------------------------------- - - function check(function_name, result) { - if (result !== 0) { - throw {message: "nacl_raw." + function_name + " signalled an error"}; - } - } - - function check_length(function_name, what, thing, expected_length) { - if (thing.length !== expected_length) { - throw {message: "nacl." + function_name + " expected " + - expected_length + "-byte " + what + " but got length " + thing.length}; - } - } - - function Target(length) { - this.length = length; - this.address = MALLOC(length); - } - - Target.prototype.extractBytes = function (offset) { - var result = extractBytes(this.address + (offset || 0), this.length - (offset || 0)); - FREE(this.address); - this.address = null; - return result; - }; - - function free_all(addresses) { - for (var i = 0; i < addresses.length; i++) { - FREE(addresses[i]); - } - } - - //--------------------------------------------------------------------------- - // Randomness - - function random_bytes(count) { - var bs = new Target(count); - nacl_raw._randombytes_buf(bs.address, count); - return bs.extractBytes(); - } - - nacl_raw._randombytes_stir(); - - //--------------------------------------------------------------------------- - // Boxing - - function crypto_box_keypair() { - var pk = new Target(nacl_raw._crypto_box_publickeybytes()); - var sk = new Target(nacl_raw._crypto_box_secretkeybytes()); - check("_crypto_box_keypair", nacl_raw._crypto_box_keypair(pk.address, sk.address)); - return {boxPk: pk.extractBytes(), boxSk: sk.extractBytes()}; - } - - function crypto_box_random_nonce() { - return random_bytes(nacl_raw._crypto_box_noncebytes()); - } - - function crypto_box(msg, nonce, pk, sk) { - var m = injectBytes(msg, nacl_raw._crypto_box_zerobytes()); - var na = check_injectBytes("crypto_box", "nonce", nonce, nacl_raw._crypto_box_noncebytes()); - var pka = check_injectBytes("crypto_box", "pk", pk, nacl_raw._crypto_box_publickeybytes()); - var ska = check_injectBytes("crypto_box", "sk", sk, nacl_raw._crypto_box_secretkeybytes()); - var c = new Target(msg.length + nacl_raw._crypto_box_zerobytes()); - check("_crypto_box", nacl_raw._crypto_box(c.address, m, c.length, 0, na, pka, ska)); - free_all([m, na, pka, ska]); - return c.extractBytes(nacl_raw._crypto_box_boxzerobytes()); - } - - function crypto_box_open(ciphertext, nonce, pk, sk) { - var c = injectBytes(ciphertext, nacl_raw._crypto_box_boxzerobytes()); - var na = check_injectBytes("crypto_box_open", - "nonce", nonce, nacl_raw._crypto_box_noncebytes()); - var pka = check_injectBytes("crypto_box_open", - "pk", pk, nacl_raw._crypto_box_publickeybytes()); - var ska = check_injectBytes("crypto_box_open", - "sk", sk, nacl_raw._crypto_box_secretkeybytes()); - var m = new Target(ciphertext.length + nacl_raw._crypto_box_boxzerobytes()); - check("_crypto_box_open", nacl_raw._crypto_box_open(m.address, c, m.length, 0, na, pka, ska)); - free_all([c, na, pka, ska]); - return m.extractBytes(nacl_raw._crypto_box_zerobytes()); - } - - function crypto_box_precompute(pk, sk) { - var pka = check_injectBytes("crypto_box_precompute", - "pk", pk, nacl_raw._crypto_box_publickeybytes()); - var ska = check_injectBytes("crypto_box_precompute", - "sk", sk, nacl_raw._crypto_box_secretkeybytes()); - var k = new Target(nacl_raw._crypto_box_beforenmbytes()); - check("_crypto_box_beforenm", - nacl_raw._crypto_box_beforenm(k.address, pka, ska)); - free_all([pka, ska]); - return {boxK: k.extractBytes()}; - } - - function crypto_box_precomputed(msg, nonce, state) { - var m = injectBytes(msg, nacl_raw._crypto_box_zerobytes()); - var na = check_injectBytes("crypto_box_precomputed", - "nonce", nonce, nacl_raw._crypto_box_noncebytes()); - var ka = check_injectBytes("crypto_box_precomputed", - "boxK", state.boxK, nacl_raw._crypto_box_beforenmbytes()); - var c = new Target(msg.length + nacl_raw._crypto_box_zerobytes()); - check("_crypto_box_afternm", - nacl_raw._crypto_box_afternm(c.address, m, c.length, 0, na, ka)); - free_all([m, na, ka]); - return c.extractBytes(nacl_raw._crypto_box_boxzerobytes()); - } - - function crypto_box_open_precomputed(ciphertext, nonce, state) { - var c = injectBytes(ciphertext, nacl_raw._crypto_box_boxzerobytes()); - var na = check_injectBytes("crypto_box_open_precomputed", - "nonce", nonce, nacl_raw._crypto_box_noncebytes()); - var ka = check_injectBytes("crypto_box_open_precomputed", - "boxK", state.boxK, nacl_raw._crypto_box_beforenmbytes()); - var m = new Target(ciphertext.length + nacl_raw._crypto_box_boxzerobytes()); - check("_crypto_box_open_afternm", - nacl_raw._crypto_box_open_afternm(m.address, c, m.length, 0, na, ka)); - free_all([c, na, ka]); - return m.extractBytes(nacl_raw._crypto_box_zerobytes()); - } - - //--------------------------------------------------------------------------- - // Hashing - - function crypto_hash(bs) { - var address = injectBytes(bs); - var hash = new Target(nacl_raw._crypto_hash_bytes()); - check("_crypto_hash", nacl_raw._crypto_hash(hash.address, address, bs.length, 0)); - FREE(address); - return hash.extractBytes(); - } - - function crypto_hash_sha256(bs) { - var address = injectBytes(bs); - var hash = new Target(nacl_raw._crypto_hash_sha256_bytes()); - check("_crypto_hash_sha256", - nacl_raw._crypto_hash_sha256(hash.address, address, bs.length, 0)); - FREE(address); - return hash.extractBytes(); - } - - function crypto_hash_string(s) { - return crypto_hash(encode_utf8(s)); - } - - //--------------------------------------------------------------------------- - // Symmetric-key encryption - - function crypto_stream_random_nonce() { - return random_bytes(nacl_raw._crypto_stream_noncebytes()); - } - - function crypto_stream(len, nonce, key) { - var na = check_injectBytes("crypto_stream", - "nonce", nonce, nacl_raw._crypto_stream_noncebytes()); - var ka = check_injectBytes("crypto_stream", - "key", key, nacl_raw._crypto_stream_keybytes()); - var out = new Target(len); - check("_crypto_stream", nacl_raw._crypto_stream(out.address, len, 0, na, ka)); - free_all([na, ka]); - return out.extractBytes(); - } - - function crypto_stream_xor(msg, nonce, key) { - var na = check_injectBytes("crypto_stream_xor", - "nonce", nonce, nacl_raw._crypto_stream_noncebytes()); - var ka = check_injectBytes("crypto_stream_xor", - "key", key, nacl_raw._crypto_stream_keybytes()); - var ma = injectBytes(msg); - var out = new Target(msg.length); - check("_crypto_stream_xor", - nacl_raw._crypto_stream_xor(out.address, ma, msg.length, 0, na, ka)); - free_all([na, ka, ma]); - return out.extractBytes(); - } - - //--------------------------------------------------------------------------- - // One-time authentication - - function crypto_onetimeauth(msg, key) { - var ka = check_injectBytes("crypto_onetimeauth", - "key", key, nacl_raw._crypto_onetimeauth_keybytes()); - var ma = injectBytes(msg); - var authenticator = new Target(nacl_raw._crypto_onetimeauth_bytes()); - check("_crypto_onetimeauth", - nacl_raw._crypto_onetimeauth(authenticator.address, ma, msg.length, 0, ka)); - free_all([ka, ma]); - return authenticator.extractBytes(); - } - - function crypto_onetimeauth_verify(authenticator, msg, key) { - if (authenticator.length != nacl_raw._crypto_onetimeauth_bytes()) return false; - var ka = check_injectBytes("crypto_onetimeauth_verify", - "key", key, nacl_raw._crypto_onetimeauth_keybytes()); - var ma = injectBytes(msg); - var aa = injectBytes(authenticator); - var result = nacl_raw._crypto_onetimeauth_verify(aa, ma, msg.length, 0, ka); - free_all([ka, ma, aa]); - return (result == 0); - } - - //--------------------------------------------------------------------------- - // Authentication - - function crypto_auth(msg, key) { - var ka = check_injectBytes("crypto_auth", "key", key, nacl_raw._crypto_auth_keybytes()); - var ma = injectBytes(msg); - var authenticator = new Target(nacl_raw._crypto_auth_bytes()); - check("_crypto_auth", nacl_raw._crypto_auth(authenticator.address, ma, msg.length, 0, ka)); - free_all([ka, ma]); - return authenticator.extractBytes(); - } - - function crypto_auth_verify(authenticator, msg, key) { - if (authenticator.length != nacl_raw._crypto_auth_bytes()) return false; - var ka = check_injectBytes("crypto_auth_verify", - "key", key, nacl_raw._crypto_auth_keybytes()); - var ma = injectBytes(msg); - var aa = injectBytes(authenticator); - var result = nacl_raw._crypto_auth_verify(aa, ma, msg.length, 0, ka); - free_all([ka, ma, aa]); - return (result == 0); - } - - //--------------------------------------------------------------------------- - // Authenticated symmetric-key encryption - - function crypto_secretbox_random_nonce() { - return random_bytes(nacl_raw._crypto_secretbox_noncebytes()); - } - - function crypto_secretbox(msg, nonce, key) { - var m = injectBytes(msg, nacl_raw._crypto_secretbox_zerobytes()); - var na = check_injectBytes("crypto_secretbox", - "nonce", nonce, nacl_raw._crypto_secretbox_noncebytes()); - var ka = check_injectBytes("crypto_secretbox", - "key", key, nacl_raw._crypto_secretbox_keybytes()); - var c = new Target(msg.length + nacl_raw._crypto_secretbox_zerobytes()); - check("_crypto_secretbox", nacl_raw._crypto_secretbox(c.address, m, c.length, 0, na, ka)); - free_all([m, na, ka]); - return c.extractBytes(nacl_raw._crypto_secretbox_boxzerobytes()); - } - - function crypto_secretbox_open(ciphertext, nonce, key) { - var c = injectBytes(ciphertext, nacl_raw._crypto_secretbox_boxzerobytes()); - var na = check_injectBytes("crypto_secretbox_open", - "nonce", nonce, nacl_raw._crypto_secretbox_noncebytes()); - var ka = check_injectBytes("crypto_secretbox_open", - "key", key, nacl_raw._crypto_secretbox_keybytes()); - var m = new Target(ciphertext.length + nacl_raw._crypto_secretbox_boxzerobytes()); - check("_crypto_secretbox_open", - nacl_raw._crypto_secretbox_open(m.address, c, m.length, 0, na, ka)); - free_all([c, na, ka]); - return m.extractBytes(nacl_raw._crypto_secretbox_zerobytes()); - } - - //--------------------------------------------------------------------------- - // Signing - - function crypto_sign_keypair() { - var pk = new Target(nacl_raw._crypto_sign_publickeybytes()); - var sk = new Target(nacl_raw._crypto_sign_secretkeybytes()); - check("_crypto_sign_keypair", nacl_raw._crypto_sign_keypair(pk.address, sk.address)); - return {signPk: pk.extractBytes(), signSk: sk.extractBytes()}; - } - - function crypto_sign(msg, sk) { - var ma = injectBytes(msg); - var ska = check_injectBytes("crypto_sign", "sk", sk, nacl_raw._crypto_sign_secretkeybytes()); - var sm = new Target(msg.length + nacl_raw._crypto_sign_bytes()); - var smlen = new Target(8); - check("_crypto_sign", - nacl_raw._crypto_sign(sm.address, smlen.address, ma, msg.length, 0, ska)); - free_all([ma, ska]); - sm.length = nacl_raw.HEAPU32[smlen.address >> 2]; - FREE(smlen.address); - return sm.extractBytes(); - } - - function crypto_sign_detached(msg, sk) { - // WARNING: Experimental. Works for ed25519 but not necessarily other implementations. - var signed_msg = crypto_sign(msg, sk); - return signed_msg.subarray(0, nacl_raw._crypto_sign_bytes()); - } - - function crypto_sign_open(sm, pk) { - var sma = injectBytes(sm); - var pka = check_injectBytes("crypto_sign_open", - "pk", pk, nacl_raw._crypto_sign_publickeybytes()); - var m = new Target(sm.length); - var mlen = new Target(8); - if (nacl_raw._crypto_sign_open(m.address, mlen.address, sma, sm.length, 0, pka) === 0) { - free_all([sma, pka]); - m.length = nacl_raw.HEAPU32[mlen.address >> 2]; - FREE(mlen.address); - return m.extractBytes(); - } else { - free_all([sma, pka, m.address, mlen.address]); - return null; - } - } - - function crypto_sign_verify_detached(detached_signature, msg, pk) { - // WARNING: Experimental. Works for ed25519 but not necessarily other implementations. - var signed_msg = new Uint8Array(detached_signature.length + msg.length); - signed_msg.set(detached_signature, 0); - signed_msg.set(msg, detached_signature.length); - return crypto_sign_open(signed_msg, pk) !== null; - } - - //--------------------------------------------------------------------------- - // Keys - - function crypto_sign_seed_keypair(bs) { - var seeda = check_injectBytes("crypto_sign_seed_keypair", - "seed", bs, nacl_raw._crypto_sign_secretkeybytes() / 2); - var pk = new Target(nacl_raw._crypto_sign_publickeybytes()); - var sk = new Target(nacl_raw._crypto_sign_secretkeybytes()); - check("_crypto_sign_seed_keypair", - nacl_raw._crypto_sign_seed_keypair(pk.address, sk.address, seeda)); - FREE(seeda); - return {signPk: pk.extractBytes(), signSk: sk.extractBytes()}; - } - - function crypto_box_seed_keypair(bs) { - var hash = new Uint8Array(crypto_hash(bs)); - return crypto_box_keypair_from_raw_sk(hash.subarray(0, - nacl_raw._crypto_box_secretkeybytes())); - } - - function crypto_box_keypair_from_raw_sk(sk) { - return {boxPk: crypto_scalarmult_base(sk), boxSk: sk}; - } - - function crypto_box_keypair_from_sign_sk(sk) { - var ska = check_injectBytes("crypto_box_keypair_from_sign_sk", "sk", sk, - nacl_raw._crypto_sign_secretkeybytes()); - var skb = new Target(nacl_raw._crypto_box_secretkeybytes()); - check("_crypto_sign_ed25519_sk_to_curve25519", - nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska)); - FREE(ska); - return crypto_box_keypair_from_raw_sk(skb.extractBytes()); - } - - function crypto_box_sk_from_sign_sk(sk) { - var ska = check_injectBytes("crypto_box_keypair_from_sign_sk", "sk", sk, - nacl_raw._crypto_sign_secretkeybytes()); - var skb = new Target(nacl_raw._crypto_box_secretkeybytes()); - check("_crypto_sign_ed25519_sk_to_curve25519", - nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska)); - FREE(ska); - return skb.extractBytes(); - } - - function crypto_box_pk_from_sign_pk(pk) { - var pka = check_injectBytes("crypto_box_pk_from_sign_pk", "pk", pk, - nacl_raw._crypto_sign_publickeybytes()); - var pkb = new Target(nacl_raw._crypto_box_publickeybytes()); - check("_crypto_sign_ed25519_pk_to_curve25519", - nacl_raw._crypto_sign_ed25519_pk_to_curve25519(pkb.address, pka)); - FREE(pka); - return pkb.extractBytes(); - } - - //--------------------------------------------------------------------------- - // Scalarmult - - function crypto_scalarmult(n,p) { - var na = check_injectBytes("crypto_scalarmult", "n", n, - nacl_raw._crypto_scalarmult_curve25519_scalarbytes()); - var pa = check_injectBytes("crypto_scalarmult", "p", p, - nacl_raw._crypto_scalarmult_curve25519_bytes()); - var q = new Target(nacl_raw._crypto_scalarmult_curve25519_bytes()); - check("_crypto_scalarmult_curve25519", - nacl_raw._crypto_scalarmult_curve25519(q.address, na, pa)); - FREE(na); - FREE(pa); - return q.extractBytes(); - } - - function crypto_scalarmult_base(n) { - var na = check_injectBytes("crypto_scalarmult_base", "n", n, - nacl_raw._crypto_scalarmult_curve25519_scalarbytes()); - var q = new Target(nacl_raw._crypto_scalarmult_curve25519_bytes()); - check("_crypto_scalarmult_curve25519_base", - nacl_raw._crypto_scalarmult_curve25519_base(q.address, na)); - FREE(na); - return q.extractBytes(); - } - - //--------------------------------------------------------------------------- - - exports.crypto_auth_BYTES = nacl_raw._crypto_auth_bytes(); - exports.crypto_auth_KEYBYTES = nacl_raw._crypto_auth_keybytes(); - exports.crypto_box_BEFORENMBYTES = nacl_raw._crypto_box_beforenmbytes(); - exports.crypto_box_BOXZEROBYTES = nacl_raw._crypto_box_boxzerobytes(); - exports.crypto_box_NONCEBYTES = nacl_raw._crypto_box_noncebytes(); - exports.crypto_box_PUBLICKEYBYTES = nacl_raw._crypto_box_publickeybytes(); - exports.crypto_box_SECRETKEYBYTES = nacl_raw._crypto_box_secretkeybytes(); - exports.crypto_box_ZEROBYTES = nacl_raw._crypto_box_zerobytes(); - exports.crypto_hash_BYTES = nacl_raw._crypto_hash_bytes(); - exports.crypto_hash_sha256_BYTES = nacl_raw._crypto_hash_sha256_bytes(); - // exports.crypto_hashblocks_BLOCKBYTES = nacl_raw._crypto_hashblocks_blockbytes(); - // exports.crypto_hashblocks_STATEBYTES = nacl_raw._crypto_hashblocks_statebytes(); - exports.crypto_onetimeauth_BYTES = nacl_raw._crypto_onetimeauth_bytes(); - exports.crypto_onetimeauth_KEYBYTES = nacl_raw._crypto_onetimeauth_keybytes(); - exports.crypto_secretbox_BOXZEROBYTES = nacl_raw._crypto_secretbox_boxzerobytes(); - exports.crypto_secretbox_KEYBYTES = nacl_raw._crypto_secretbox_keybytes(); - exports.crypto_secretbox_NONCEBYTES = nacl_raw._crypto_secretbox_noncebytes(); - exports.crypto_secretbox_ZEROBYTES = nacl_raw._crypto_secretbox_zerobytes(); - exports.crypto_sign_BYTES = nacl_raw._crypto_sign_bytes(); - exports.crypto_sign_PUBLICKEYBYTES = nacl_raw._crypto_sign_publickeybytes(); - exports.crypto_sign_SECRETKEYBYTES = nacl_raw._crypto_sign_secretkeybytes(); - // exports.crypto_stream_BEFORENMBYTES = nacl_raw._crypto_stream_beforenmbytes(); - exports.crypto_stream_KEYBYTES = nacl_raw._crypto_stream_keybytes(); - exports.crypto_stream_NONCEBYTES = nacl_raw._crypto_stream_noncebytes(); - exports.crypto_scalarmult_SCALARBYTES = nacl_raw._crypto_scalarmult_curve25519_scalarbytes(); - exports.crypto_scalarmult_BYTES = nacl_raw._crypto_scalarmult_curve25519_bytes(); - - exports.encode_utf8 = encode_utf8; - exports.encode_latin1 = encode_latin1; - exports.decode_utf8 = decode_utf8; - exports.decode_latin1 = decode_latin1; - exports.to_hex = to_hex; - exports.from_hex = from_hex; - - exports.random_bytes = random_bytes; - - exports.crypto_box_keypair = crypto_box_keypair; - exports.crypto_box_random_nonce = crypto_box_random_nonce; - exports.crypto_box = crypto_box; - exports.crypto_box_open = crypto_box_open; - exports.crypto_box_precompute = crypto_box_precompute; - exports.crypto_box_precomputed = crypto_box_precomputed; - exports.crypto_box_open_precomputed = crypto_box_open_precomputed; - - exports.crypto_stream_random_nonce = crypto_stream_random_nonce; - exports.crypto_stream = crypto_stream; - exports.crypto_stream_xor = crypto_stream_xor; - - exports.crypto_onetimeauth = crypto_onetimeauth; - exports.crypto_onetimeauth_verify = crypto_onetimeauth_verify; - - exports.crypto_auth = crypto_auth; - exports.crypto_auth_verify = crypto_auth_verify; - - exports.crypto_secretbox_random_nonce = crypto_secretbox_random_nonce; - exports.crypto_secretbox = crypto_secretbox; - exports.crypto_secretbox_open = crypto_secretbox_open; - - exports.crypto_sign_keypair = crypto_sign_keypair; - exports.crypto_sign = crypto_sign; - exports.crypto_sign_detached = crypto_sign_detached; - exports.crypto_sign_open = crypto_sign_open; - exports.crypto_sign_verify_detached = crypto_sign_verify_detached; - - exports.crypto_hash = crypto_hash; - exports.crypto_hash_sha256 = crypto_hash_sha256; - exports.crypto_hash_string = crypto_hash_string; - - exports.crypto_sign_seed_keypair = crypto_sign_seed_keypair; - exports.crypto_box_seed_keypair = crypto_box_seed_keypair; - exports.crypto_box_keypair_from_raw_sk = crypto_box_keypair_from_raw_sk; - exports.crypto_box_keypair_from_sign_sk = crypto_box_keypair_from_sign_sk; - exports.crypto_box_pk_from_sign_pk = crypto_box_pk_from_sign_pk; - exports.crypto_box_sk_from_sign_sk = crypto_box_sk_from_sign_sk; - // Backwards-compatibility: - exports.crypto_sign_keypair_from_seed = crypto_sign_seed_keypair; - exports.crypto_box_keypair_from_seed = crypto_box_seed_keypair; - - exports.crypto_scalarmult = crypto_scalarmult; - exports.crypto_scalarmult_base = crypto_scalarmult_base; - - return exports; -})(); - nacl.nacl_raw = nacl_raw; - - if (on_ready_call_needed) { - on_ready(nacl); - } - - return "nacl_factory API has changed -- see js-nacl README"; - })((typeof window !== 'undefined') ? window : undefined_reference_value, - (typeof document !== 'undefined') ? document : undefined_reference_value); - } -}; - -// export common.js module to allow one js file for browser and node.js -if (typeof module !== 'undefined' && module.exports) { - module.exports = nacl_factory; -} diff --git a/assets/www/js/vendor/ng-cordova.min.js b/assets/www/js/vendor/ng-cordova.min.js deleted file mode 100644 index 4ae32822d7219ee0176b83737f144bc7e320d900..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/ng-cordova.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/*! - * ngCordova - * v0.1.26-alpha - * Copyright 2015 Drifty Co. http://drifty.com/ - * See LICENSE in this repository for license information - */ -!function(){angular.module("ngCordova",["ngCordova.plugins"]),angular.module("ngCordova.plugins.actionSheet",[]).factory("$cordovaActionSheet",["$q","$window",function(e,n){return{show:function(r){var o=e.defer();return n.plugins.actionsheet.show(r,function(e){o.resolve(e)}),o.promise},hide:function(){return n.plugins.actionsheet.hide()}}}]),angular.module("ngCordova.plugins.adMob",[]).factory("$cordovaAdMob",["$q","$window",function(e,n){return{createBannerView:function(r){var o=e.defer();return n.plugins.AdMob.createBannerView(r,function(){o.resolve()},function(){o.reject()}),o.promise},createInterstitialView:function(r){var o=e.defer();return n.plugins.AdMob.createInterstitialView(r,function(){o.resolve()},function(){o.reject()}),o.promise},requestAd:function(r){var o=e.defer();return n.plugins.AdMob.requestAd(r,function(){o.resolve()},function(){o.reject()}),o.promise},showAd:function(r){var o=e.defer();return n.plugins.AdMob.showAd(r,function(){o.resolve()},function(){o.reject()}),o.promise},requestInterstitialAd:function(r){var o=e.defer();return n.plugins.AdMob.requestInterstitialAd(r,function(){o.resolve()},function(){o.reject()}),o.promise}}}]),angular.module("ngCordova.plugins.appAvailability",[]).factory("$cordovaAppAvailability",["$q",function(e){return{check:function(n){var r=e.defer();return appAvailability.check(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.appRate",[]).provider("$cordovaAppRate",[function(){this.setPreferences=function(e){e&&angular.isObject(e)&&(AppRate.preferences.useLanguage=e.language||null,AppRate.preferences.displayAppName=e.appName||"",AppRate.preferences.promptAgainForEachNewVersion=e.promptForNewVersion||!0,AppRate.preferences.openStoreInApp=e.openStoreInApp||!1,AppRate.preferences.usesUntilPrompt=e.usesUntilPrompt||3,AppRate.preferences.useCustomRateDialog=e.useCustomRateDialog||!1,AppRate.preferences.storeAppURL.ios=e.iosURL||null,AppRate.preferences.storeAppURL.android=e.androidURL||null,AppRate.preferences.storeAppURL.blackberry=e.blackberryURL||null,AppRate.preferences.storeAppURL.windows8=e.windowsURL||null)},this.setCustomLocale=function(e){var n={title:"Rate %@",message:"If you enjoy using %@, would you mind taking a moment to rate it? It won’t take more than a minute. Thanks for your support!",cancelButtonLabel:"No, Thanks",laterButtonLabel:"Remind Me Later",rateButtonLabel:"Rate It Now"};n=angular.extend(n,e),AppRate.preferences.customLocale=n},this.$get=["$q",function(e){return{promptForRating:function(n){var r=e.defer(),o=AppRate.promptForRating(n);return r.resolve(o),r.promise},navigateToAppStore:function(){var n=e.defer(),r=AppRate.navigateToAppStore();return n.resolve(r),n.promise},onButtonClicked:function(e){AppRate.onButtonClicked=function(n){e.call(this,n)}},onRateDialogShow:function(e){AppRate.onRateDialogShow=e()}}}]}]),angular.module("ngCordova.plugins.appVersion",[]).factory("$cordovaAppVersion",["$q",function(e){return{getAppName:function(){var n=e.defer();return cordova.getAppVersion.getAppName(function(e){n.resolve(e)}),n.promise},getPackageName:function(){var n=e.defer();return cordova.getAppVersion.getPackageName(function(e){n.resolve(e)}),n.promise},getVersionNumber:function(){var n=e.defer();return cordova.getAppVersion.getVersionNumber(function(e){n.resolve(e)}),n.promise},getVersionCode:function(){var n=e.defer();return cordova.getAppVersion.getVersionCode(function(e){n.resolve(e)}),n.promise}}}]),angular.module("ngCordova.plugins.backgroundGeolocation",[]).factory("$cordovaBackgroundGeolocation",["$q","$window",function(e,n){return{init:function(){n.navigator.geolocation.getCurrentPosition(function(e){return e})},configure:function(r){this.init();var o=e.defer();return n.plugins.backgroundGeoLocation.configure(function(e){o.notify(e),n.plugins.backgroundGeoLocation.finish()},function(e){o.reject(e)},r),this.start(),o.promise},start:function(){var r=e.defer();return n.plugins.backgroundGeoLocation.start(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},stop:function(){var r=e.defer();return n.plugins.backgroundGeoLocation.stop(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.badge",[]).factory("$cordovaBadge",["$q",function(e){return{hasPermission:function(){var n=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?n.resolve(!0):n.reject("You do not have permission")}),n.promise},promptForPermission:function(){return cordova.plugins.notification.badge.promptForPermission()},set:function(n,r,o){var t=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?t.resolve(cordova.plugins.notification.badge.set(n,r,o)):t.reject("You do not have permission to set Badge")}),t.promise},get:function(){var n=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?cordova.plugins.notification.badge.get(function(e){n.resolve(e)}):n.reject("You do not have permission to get Badge")}),n.promise},clear:function(n,r){var o=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?o.resolve(cordova.plugins.notification.badge.clear(n,r)):o.reject("You do not have permission to clear Badge")}),o.promise},increase:function(n,r,o){var t=e.defer();return this.hasPermission().then(function(){t.resolve(cordova.plugins.notification.badge.increase(n,r,o))},function(){t.reject("You do not have permission to increase Badge")}),t.promise},decrease:function(n,r,o){var t=e.defer();return this.hasPermission().then(function(){t.resolve(cordova.plugins.notification.badge.decrease(n,r,o))},function(){t.reject("You do not have permission to decrease Badge")}),t.promise},configure:function(e){return cordova.plugins.notification.badge.configure(e)}}}]),angular.module("ngCordova.plugins.barcodeScanner",[]).factory("$cordovaBarcodeScanner",["$q",function(e){return{scan:function(n){var r=e.defer();return cordova.plugins.barcodeScanner.scan(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},encode:function(n,r){var o=e.defer();return n=n||"TEXT_TYPE",cordova.plugins.barcodeScanner.encode(n,r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.batteryStatus",[]).factory("$cordovaBatteryStatus",["$rootScope","$window","$timeout",function(e,n,r){var o=function(n){r(function(){e.$broadcast("$cordovaBatteryStatus:status",n)})},t=function(n){r(function(){e.$broadcast("$cordovaBatteryStatus:critical",n)})},i=function(n){r(function(){e.$broadcast("$cordovaBatteryStatus:low",n)})};return document.addEventListener("deviceready",function(){navigator.battery&&(n.addEventListener("batterystatus",o,!1),n.addEventListener("batterycritical",t,!1),n.addEventListener("batterylow",i,!1))},!1),!0}]).run(["$injector",function(e){e.get("$cordovaBatteryStatus")}]),angular.module("ngCordova.plugins.beacon",[]).factory("$cordovaBeacon",["$window","$rootScope","$timeout","$q",function(e,n,r,o){var t=null,i=null,a=null,c=null,u=null,s=null,l=null,f=null;return document.addEventListener("deviceready",function(){if(e.cordova&&e.cordova.plugins&&e.cordova.plugins.locationManager){var o=new e.cordova.plugins.locationManager.Delegate;o.didDetermineStateForRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didDetermineStateForRegion",e)}),t&&t(e)},o.didStartMonitoringForRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didStartMonitoringForRegion",e)}),i&&i(e)},o.didExitRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didExitRegion",e)}),a&&a(e)},o.didEnterRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didEnterRegion",e)}),c&&c(e)},o.didRangeBeaconsInRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didRangeBeaconsInRegion",e)}),u&&u(e)},o.peripheralManagerDidStartAdvertising=function(e){r(function(){n.$broadcast("$cordovaBeacon:peripheralManagerDidStartAdvertising",e)}),s&&s(e)},o.peripheralManagerDidUpdateState=function(e){r(function(){n.$broadcast("$cordovaBeacon:peripheralManagerDidUpdateState",e)}),l&&l(e)},o.didChangeAuthorizationStatus=function(e){r(function(){n.$broadcast("$cordovaBeacon:didChangeAuthorizationStatus",e)}),f&&f(e)},e.cordova.plugins.locationManager.setDelegate(o)}},!1),{setCallbackDidDetermineStateForRegion:function(e){t=e},setCallbackDidStartMonitoringForRegion:function(e){i=e},setCallbackDidExitRegion:function(e){a=e},setCallbackDidEnterRegion:function(e){c=e},setCallbackDidRangeBeaconsInRegion:function(e){u=e},setCallbackPeripheralManagerDidStartAdvertising:function(e){s=e},setCallbackPeripheralManagerDidUpdateState:function(e){l=e},setCallbackDidChangeAuthorizationStatus:function(e){f=e},createBeaconRegion:function(n,r,o,t,i){return o=o||void 0,t=t||void 0,new e.cordova.plugins.locationManager.BeaconRegion(n,r,o,t,i)},isBluetoothEnabled:function(){return o.when(e.cordova.plugins.locationManager.isBluetoothEnabled())},enableBluetooth:function(){return o.when(e.cordova.plugins.locationManager.enableBluetooth())},disableBluetooth:function(){return o.when(e.cordova.plugins.locationManager.disableBluetooth())},startMonitoringForRegion:function(n){return o.when(e.cordova.plugins.locationManager.startMonitoringForRegion(n))},stopMonitoringForRegion:function(n){return o.when(e.cordova.plugins.locationManager.stopMonitoringForRegion(n))},requestStateForRegion:function(n){return o.when(e.cordova.plugins.locationManager.requestStateForRegion(n))},startRangingBeaconsInRegion:function(n){return o.when(e.cordova.plugins.locationManager.startRangingBeaconsInRegion(n))},stopRangingBeaconsInRegion:function(n){return o.when(e.cordova.plugins.locationManager.stopRangingBeaconsInRegion(n))},getAuthorizationStatus:function(){return o.when(e.cordova.plugins.locationManager.getAuthorizationStatus())},requestWhenInUseAuthorization:function(){return o.when(e.cordova.plugins.locationManager.requestWhenInUseAuthorization())},requestAlwaysAuthorization:function(){return o.when(e.cordova.plugins.locationManager.requestAlwaysAuthorization())},getMonitoredRegions:function(){return o.when(e.cordova.plugins.locationManager.getMonitoredRegions())},getRangedRegions:function(){return o.when(e.cordova.plugins.locationManager.getRangedRegions())},isRangingAvailable:function(){return o.when(e.cordova.plugins.locationManager.isRangingAvailable())},isMonitoringAvailableForClass:function(n){return o.when(e.cordova.plugins.locationManager.isMonitoringAvailableForClass(n))},startAdvertising:function(n,r){return o.when(e.cordova.plugins.locationManager.startAdvertising(n,r))},stopAdvertising:function(){return o.when(e.cordova.plugins.locationManager.stopAdvertising())},isAdvertisingAvailable:function(){return o.when(e.cordova.plugins.locationManager.isAdvertisingAvailable())},isAdvertising:function(){return o.when(e.cordova.plugins.locationManager.isAdvertising())},disableDebugLogs:function(){return o.when(e.cordova.plugins.locationManager.disableDebugLogs())},enableDebugNotifications:function(){return o.when(e.cordova.plugins.locationManager.enableDebugNotifications())},disableDebugNotifications:function(){return o.when(e.cordova.plugins.locationManager.disableDebugNotifications())},enableDebugLogs:function(){return o.when(e.cordova.plugins.locationManager.enableDebugLogs())},appendToDeviceLog:function(n){return o.when(e.cordova.plugins.locationManager.appendToDeviceLog(n))}}}]),angular.module("ngCordova.plugins.ble",[]).factory("$cordovaBLE",["$q","$timeout","$log",function(e,n,r){return{scan:function(r,o){var t=e.defer();return ble.startScan(r,function(e){t.notify(e)},function(e){t.reject(e)}),n(function(){ble.stopScan(function(){t.resolve()},function(e){t.reject(e)})},1e3*o),t.promise},startScan:function(e,n,r){return ble.startScan(e,n,r)},stopScan:function(){var n=e.defer();return ble.stopScan(function(){n.resolve()},function(e){n.reject(e)}),n.promise},connect:function(n){var r=e.defer();return ble.connect(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},disconnect:function(n){var r=e.defer();return ble.disconnect(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},read:function(n,r,o){var t=e.defer();return ble.read(n,r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},write:function(n,r,o,t){var i=e.defer();return ble.write(n,r,o,t,function(e){i.resolve(e)},function(e){i.reject(e)}),i.promise},writeWithoutResponse:function(n,r,o,t){var i=e.defer();return ble.writeWithoutResponse(n,r,o,t,function(e){i.resolve(e)},function(e){i.reject(e)}),i.promise},writeCommand:function(e,n,o,t){return r.warning("writeCommand is deprecated, use writeWithoutResponse"),this.writeWithoutResponse(e,n,o,t)},startNotification:function(e,n,r,o,t){return ble.startNotification(e,n,r,o,t)},stopNotification:function(n,r,o){var t=e.defer();return ble.stopNotification(n,r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},isConnected:function(n){var r=e.defer();return ble.isConnected(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},enable:function(){var n=e.defer();return ble.enable(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},isEnabled:function(){var n=e.defer();return ble.isEnabled(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.bluetoothSerial",[]).factory("$cordovaBluetoothSerial",["$q","$window",function(e,n){return{connect:function(r){var o=e.defer(),t=e.defer(),i=!1;return n.bluetoothSerial.connect(r,function(){i=!0,o.resolve(t)},function(e){i===!1&&t.reject(e),o.reject(e)}),o.promise},connectInsecure:function(r){var o=e.defer();return n.bluetoothSerial.connectInsecure(r,function(){o.resolve()},function(e){o.reject(e)}),o.promise},disconnect:function(){var r=e.defer();return n.bluetoothSerial.disconnect(function(){r.resolve()},function(e){r.reject(e)}),r.promise},list:function(){var r=e.defer();return n.bluetoothSerial.list(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},discoverUnpaired:function(){var r=e.defer();return n.bluetoothSerial.discoverUnpaired(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},setDeviceDiscoveredListener:function(){var r=e.defer();return n.bluetoothSerial.setDeviceDiscoveredListener(function(e){r.notify(e)}),r.promise},clearDeviceDiscoveredListener:function(){n.bluetoothSerial.clearDeviceDiscoveredListener()},showBluetoothSettings:function(){var r=e.defer();return n.bluetoothSerial.showBluetoothSettings(function(){r.resolve()},function(e){r.reject(e)}),r.promise},isEnabled:function(){var r=e.defer();return n.bluetoothSerial.isEnabled(function(){r.resolve()},function(){r.reject()}),r.promise},enable:function(){var r=e.defer();return n.bluetoothSerial.enable(function(){r.resolve()},function(){r.reject()}),r.promise},isConnected:function(){var r=e.defer();return n.bluetoothSerial.isConnected(function(){r.resolve()},function(){r.reject()}),r.promise},available:function(){var r=e.defer();return n.bluetoothSerial.available(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},read:function(){var r=e.defer();return n.bluetoothSerial.read(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},readUntil:function(r){var o=e.defer();return n.bluetoothSerial.readUntil(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},write:function(r){var o=e.defer();return n.bluetoothSerial.write(r,function(){o.resolve()},function(e){o.reject(e)}),o.promise},subscribe:function(r){var o=e.defer();return n.bluetoothSerial.subscribe(r,function(e){o.notify(e)},function(e){o.reject(e)}),o.promise},subscribeRawData:function(){var r=e.defer();return n.bluetoothSerial.subscribeRawData(function(e){r.notify(e)},function(e){r.reject(e)}),r.promise},unsubscribe:function(){var r=e.defer();return n.bluetoothSerial.unsubscribe(function(){r.resolve()},function(e){r.reject(e)}),r.promise},unsubscribeRawData:function(){var r=e.defer();return n.bluetoothSerial.unsubscribeRawData(function(){r.resolve()},function(e){r.reject(e)}),r.promise},clear:function(){var r=e.defer();return n.bluetoothSerial.clear(function(){r.resolve()},function(e){r.reject(e)}),r.promise},readRSSI:function(){var r=e.defer();return n.bluetoothSerial.readRSSI(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.brightness",[]).factory("$cordovaBrightness",["$q","$window",function(e,n){return{get:function(){var r=e.defer();return n.cordova?n.cordova.plugins.brightness.getBrightness(function(e){r.resolve(e)},function(e){r.reject(e)}):r.reject("Not supported without cordova.js"),r.promise},set:function(r){var o=e.defer();return n.cordova?n.cordova.plugins.brightness.setBrightness(r,function(e){o.resolve(e)},function(e){o.reject(e)}):o.reject("Not supported without cordova.js"),o.promise},setKeepScreenOn:function(r){var o=e.defer();return n.cordova?n.cordova.plugins.brightness.setKeepScreenOn(r,function(e){o.resolve(e)},function(e){o.reject(e)}):o.reject("Not supported without cordova.js"),o.promise}}}]),angular.module("ngCordova.plugins.calendar",[]).factory("$cordovaCalendar",["$q","$window",function(e,n){return{createCalendar:function(r){var o=e.defer(),t=n.plugins.calendar.getCreateCalendarOptions();return"string"==typeof r?t.calendarName=r:t=angular.extend(t,r),n.plugins.calendar.createCalendar(t,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},deleteCalendar:function(r){var o=e.defer();return n.plugins.calendar.deleteCalendar(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEvent:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.createEvent(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEventWithOptions:function(r){var o=e.defer(),t=[],i=window.plugins.calendar.getCalendarOptions(),a={title:null,location:null,notes:null,startDate:null,endDate:null};t=Object.keys(a);for(var c in r)-1===t.indexOf(c)?i[c]=r[c]:a[c]=r[c];return n.plugins.calendar.createEventWithOptions(a.title,a.location,a.notes,new Date(a.startDate),new Date(a.endDate),i,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEventInteractively:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.createEventInteractively(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEventInNamedCalendar:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null,calendarName:null};return t=angular.extend(t,r),n.plugins.calendar.createEventInNamedCalendar(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),t.calendarName,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},findEvent:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.findEvent(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},listEventsInRange:function(r,o){var t=e.defer();return n.plugins.calendar.listEventsInRange(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},listCalendars:function(){var r=e.defer();return n.plugins.calendar.listCalendars(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},findAllEventsInNamedCalendar:function(r){var o=e.defer();return n.plugins.calendar.findAllEventsInNamedCalendar(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},modifyEvent:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null,newTitle:null,newLocation:null,newNotes:null,newStartDate:null,newEndDate:null};return t=angular.extend(t,r),n.plugins.calendar.modifyEvent(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),t.newTitle,t.newLocation,t.newNotes,new Date(t.newStartDate),new Date(t.newEndDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},deleteEvent:function(r){var o=e.defer(),t={newTitle:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.deleteEvent(t.newTitle,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.camera",[]).factory("$cordovaCamera",["$q",function(e){return{getPicture:function(n){var r=e.defer();return navigator.camera?(navigator.camera.getPicture(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)},cleanup:function(){var n=e.defer();return navigator.camera.cleanup(function(){n.resolve()},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.capture",[]).factory("$cordovaCapture",["$q",function(e){return{captureAudio:function(n){var r=e.defer();return navigator.device.capture?(navigator.device.capture.captureAudio(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)},captureImage:function(n){var r=e.defer();return navigator.device.capture?(navigator.device.capture.captureImage(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)},captureVideo:function(n){var r=e.defer();return navigator.device.capture?(navigator.device.capture.captureVideo(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)}}}]),angular.module("ngCordova.plugins.cardIO",[]).provider("$cordovaNgCardIO",[function(){var e=["card_type","redacted_card_number","card_number","expiry_month","expiry_year","short_expiry_year","cvv","zip"],n={expiry:!0,cvv:!0,zip:!1,suppressManual:!1,suppressConfirm:!1,hideLogo:!0};this.setCardIOResponseFields=function(n){n&&angular.isArray(n)&&(e=n)},this.setScanerConfig=function(e){e&&angular.isObject(e)&&(n.expiry=e.expiry||!0,n.cvv=e.cvv||!0,n.zip=e.zip||!1,n.suppressManual=e.suppressManual||!1,n.suppressConfirm=e.suppressConfirm||!1,n.hideLogo=e.hideLogo||!0)},this.$get=["$q",function(r){return{scanCard:function(){var o=r.defer();return CardIO.scan(n,function(n){if(null===n)o.reject(null);else{for(var r={},t=0,i=e.length;i>t;t++){var a=e[t];"short_expiry_year"===a?r[a]=String(n.expiry_year).substr(2,2)||"":r[a]=n[a]||""}o.resolve(r)}},function(){o.reject(null)}),o.promise}}}]}]),angular.module("ngCordova.plugins.clipboard",[]).factory("$cordovaClipboard",["$q","$window",function(e,n){return{copy:function(r){var o=e.defer();return n.cordova.plugins.clipboard.copy(r,function(){o.resolve()},function(){o.reject()}),o.promise},paste:function(){var r=e.defer();return n.cordova.plugins.clipboard.paste(function(e){r.resolve(e)},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.contacts",[]).factory("$cordovaContacts",["$q",function(e){return{save:function(n){var r=e.defer(),o=navigator.contacts.create(n);return o.save(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},remove:function(n){var r=e.defer(),o=navigator.contacts.create(n);return o.remove(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},clone:function(e){var n=navigator.contacts.create(e);return n.clone(e)},find:function(n){var r=e.defer(),o=n.fields||["id","displayName"];return delete n.fields,0===Object.keys(n).length?navigator.contacts.find(o,function(e){r.resolve(e)},function(e){r.reject(e)}):navigator.contacts.find(o,function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},pickContact:function(){var n=e.defer();return navigator.contacts.pickContact(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.datePicker",[]).factory("$cordovaDatePicker",["$window","$q",function(e,n){return{show:function(r){var o=n.defer();return r=r||{date:new Date,mode:"date"},e.datePicker.show(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.device",[]).factory("$cordovaDevice",[function(){return{getDevice:function(){return device},getCordova:function(){return device.cordova},getModel:function(){return device.model},getName:function(){return device.name},getPlatform:function(){return device.platform},getUUID:function(){return device.uuid},getVersion:function(){return device.version},getManufacturer:function(){return device.manufacturer}}}]),angular.module("ngCordova.plugins.deviceMotion",[]).factory("$cordovaDeviceMotion",["$q",function(e){return{getCurrentAcceleration:function(){var n=e.defer();return angular.isUndefined(navigator.accelerometer)||!angular.isFunction(navigator.accelerometer.getCurrentAcceleration)?(n.reject("Device do not support watchAcceleration"),n.promise):(navigator.accelerometer.getCurrentAcceleration(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise)},watchAcceleration:function(n){var r=e.defer();if(angular.isUndefined(navigator.accelerometer)||!angular.isFunction(navigator.accelerometer.watchAcceleration))return r.reject("Device do not support watchAcceleration"),r.promise;var o=navigator.accelerometer.watchAcceleration(function(e){r.notify(e)},function(e){r.reject(e)},n);return r.promise.cancel=function(){navigator.accelerometer.clearWatch(o)},r.promise.clearWatch=function(e){navigator.accelerometer.clearWatch(e||o)},r.promise.watchID=o,r.promise},clearWatch:function(e){return navigator.accelerometer.clearWatch(e)}}}]),angular.module("ngCordova.plugins.deviceOrientation",[]).factory("$cordovaDeviceOrientation",["$q",function(e){var n={frequency:3e3};return{getCurrentHeading:function(){var n=e.defer();return navigator.compass?(navigator.compass.getCurrentHeading(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise):(n.reject("No compass on Device"),n.promise)},watchHeading:function(r){var o=e.defer();if(!navigator.compass)return o.reject("No compass on Device"),o.promise;var t=angular.extend(n,r),i=navigator.compass.watchHeading(function(e){o.notify(e)},function(e){o.reject(e)},t);return o.promise.cancel=function(){navigator.compass.clearWatch(i)},o.promise.clearWatch=function(e){navigator.compass.clearWatch(e||i)},o.promise.watchID=i,o.promise},clearWatch:function(e){return navigator.compass.clearWatch(e)}}}]),angular.module("ngCordova.plugins.dialogs",[]).factory("$cordovaDialogs",["$q","$window",function(e,n){return{alert:function(r,o,t){var i=e.defer();return n.navigator.notification?navigator.notification.alert(r,function(){i.resolve()},o,t):(n.alert(r),i.resolve()),i.promise},confirm:function(r,o,t){var i=e.defer();return n.navigator.notification?navigator.notification.confirm(r,function(e){i.resolve(e)},o,t):n.confirm(r)?i.resolve(1):i.resolve(2),i.promise},prompt:function(r,o,t,i){var a=e.defer();if(n.navigator.notification)navigator.notification.prompt(r,function(e){a.resolve(e)},o,t,i);else{var c=n.prompt(r,i);null!==c?a.resolve({input1:c,buttonIndex:1}):a.resolve({input1:c,buttonIndex:2})}return a.promise},beep:function(e){return navigator.notification.beep(e)},activityStart:function(n,r){var o=e.defer();return"android"===cordova.platformId?(navigator.notification.activityStart(r,n),o.resolve()):o.reject(n,r),o.promise},activityStop:function(){var n=e.defer();return"android"===cordova.platformId?(navigator.notification.activityStop(),n.resolve()):n.reject(),n.promise},progressStart:function(n,r){var o=e.defer();return"android"===cordova.platformId?(navigator.notification.progressStart(r,n),o.resolve()):o.reject(n,r),o.promise},progressStop:function(){var n=e.defer();return"android"===cordova.platformId?(navigator.notification.progressStop(),n.resolve()):n.reject(),n.promise},progressValue:function(n){var r=e.defer();return"android"===cordova.platformId?(navigator.notification.progressValue(n),r.resolve()):r.reject(n),r.promise}}}]),angular.module("ngCordova.plugins.emailComposer",[]).factory("$cordovaEmailComposer",["$q",function(e){return{isAvailable:function(){var n=e.defer();return cordova.plugins.email.isAvailable(function(e){e?n.resolve():n.reject()}),n.promise},open:function(n){var r=e.defer();return cordova.plugins.email.open(n,function(){r.reject()}),r.promise},addAlias:function(e,n){cordova.plugins.email.addAlias(e,n)}}}]),angular.module("ngCordova.plugins.facebook",[]).provider("$cordovaFacebook",[function(){this.browserInit=function(e,n){this.appID=e,this.appVersion=n||"v2.0",facebookConnectPlugin.browserInit(this.appID,this.appVersion)},this.$get=["$q",function(e){return{login:function(n){var r=e.defer();return facebookConnectPlugin.login(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},showDialog:function(n){var r=e.defer();return facebookConnectPlugin.showDialog(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},api:function(n,r){var o=e.defer();return facebookConnectPlugin.api(n,r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},getAccessToken:function(){var n=e.defer();return facebookConnectPlugin.getAccessToken(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getLoginStatus:function(){var n=e.defer();return facebookConnectPlugin.getLoginStatus(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},logout:function(){var n=e.defer();return facebookConnectPlugin.logout(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]}]),angular.module("ngCordova.plugins.facebookAds",[]).factory("$cordovaFacebookAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.FacebookAds.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.FacebookAds.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.FacebookAds.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.FacebookAds.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.FacebookAds.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.FacebookAds.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.FacebookAds.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.FacebookAds.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.file",[]).constant("$cordovaFileError",{1:"NOT_FOUND_ERR",2:"SECURITY_ERR",3:"ABORT_ERR",4:"NOT_READABLE_ERR",5:"ENCODING_ERR",6:"NO_MODIFICATION_ALLOWED_ERR",7:"INVALID_STATE_ERR",8:"SYNTAX_ERR",9:"INVALID_MODIFICATION_ERR",10:"QUOTA_EXCEEDED_ERR",11:"TYPE_MISMATCH_ERR",12:"PATH_EXISTS_ERR"}).provider("$cordovaFile",[function(){this.$get=["$q","$window","$cordovaFileError",function(e,n,r){return{getFreeDiskSpace:function(){var n=e.defer();return cordova.exec(function(e){n.resolve(e)},function(e){n.reject(e)},"File","getFreeDiskSpace",[]),n.promise},checkDir:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("directory cannot start with /");try{var a=o+t;n.resolveLocalFileSystemURL(a,function(e){e.isDirectory===!0?i.resolve(e):i.reject({code:13,message:"input is not a directory"})},function(e){e.message=r[e.code],i.reject(e)})}catch(c){c.message=r[c.code],i.reject(c)}return i.promise},checkFile:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("directory cannot start with /");try{var a=o+t;n.resolveLocalFileSystemURL(a,function(e){e.isFile===!0?i.resolve(e):i.reject({code:13,message:"input is not a file"})},function(e){e.message=r[e.code],i.reject(e)})}catch(c){c.message=r[c.code],i.reject(c)}return i.promise},createDir:function(o,t,i){var a=e.defer();/^\//.test(t)&&a.reject("directory cannot start with /"), -i=i?!1:!0;var c={create:!0,exclusive:i};try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,c,function(e){a.resolve(e)},function(e){e.message=r[e.code],a.reject(e)})},function(e){e.message=r[e.code],a.reject(e)})}catch(u){u.message=r[u.code],a.reject(u)}return a.promise},createFile:function(o,t,i){var a=e.defer();/^\//.test(t)&&a.reject("file-name cannot start with /"),i=i?!1:!0;var c={create:!0,exclusive:i};try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,c,function(e){a.resolve(e)},function(e){e.message=r[e.code],a.reject(e)})},function(e){e.message=r[e.code],a.reject(e)})}catch(u){u.message=r[u.code],a.reject(u)}return a.promise},removeDir:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,{create:!1},function(e){e.remove(function(){i.resolve({success:!0,fileRemoved:e})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},removeFile:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.remove(function(){i.resolve({success:!0,fileRemoved:e})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},removeRecursively:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,{create:!1},function(e){e.removeRecursively(function(){i.resolve({success:!0,fileRemoved:e})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},writeFile:function(o,t,i,a){var c=e.defer();/^\//.test(t)&&c.reject("file-name cannot start with /"),a=a?!1:!0;var u={create:!0,exclusive:a};try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,u,function(e){e.createWriter(function(e){u.append===!0&&e.seek(e.length),u.truncate&&e.truncate(u.truncate),e.onwriteend=function(e){this.error?c.reject(this.error):c.resolve(e)},e.write(i),c.promise.abort=function(){e.abort()}})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})}catch(s){s.message=r[s.code],c.reject(s)}return c.promise},writeExistingFile:function(o,t,i){var a=e.defer();/^\//.test(t)&&a.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.createWriter(function(e){e.seek(e.length),e.onwriteend=function(e){this.error?a.reject(this.error):a.resolve(e)},e.write(i),a.promise.abort=function(){e.abort()}})},function(e){e.message=r[e.code],a.reject(e)})},function(e){e.message=r[e.code],a.reject(e)})}catch(c){c.message=r[c.code],a.reject(c)}return a.promise},readAsText:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsText(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},readAsDataURL:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsDataURL(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},readAsBinaryString:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsBinaryString(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},readAsArrayBuffer:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsArrayBuffer(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},moveFile:function(r,o,t,i){var a=e.defer();i=i||o,(/^\//.test(o)||/^\//.test(i))&&a.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(r,function(e){e.getFile(o,{create:!1},function(e){n.resolveLocalFileSystemURL(t,function(n){e.moveTo(n,i,function(e){a.resolve(e)},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})}catch(c){a.reject(c)}return a.promise},moveDir:function(r,o,t,i){var a=e.defer();i=i||o,(/^\//.test(o)||/^\//.test(i))&&a.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(r,function(e){e.getDirectory(o,{create:!1},function(e){n.resolveLocalFileSystemURL(t,function(n){e.moveTo(n,i,function(e){a.resolve(e)},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})}catch(c){a.reject(c)}return a.promise},copyDir:function(o,t,i,a){var c=e.defer();a=a||t,(/^\//.test(t)||/^\//.test(a))&&c.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,{create:!1,exclusive:!1},function(e){n.resolveLocalFileSystemURL(i,function(n){e.copyTo(n,a,function(e){c.resolve(e)},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})}catch(u){u.message=r[u.code],c.reject(u)}return c.promise},copyFile:function(o,t,i,a){var c=e.defer();a=a||t,/^\//.test(t)&&c.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1,exclusive:!1},function(e){n.resolveLocalFileSystemURL(i,function(n){e.copyTo(n,a,function(e){c.resolve(e)},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})}catch(u){u.message=r[u.code],c.reject(u)}return c.promise},readFileMetadata:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("directory cannot start with /");try{var a=o+t;n.resolveLocalFileSystemURL(a,function(e){e.file(function(e){i.resolve(e)},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(c){c.message=r[c.code],i.reject(c)}return i.promise}}}]}]),angular.module("ngCordova.plugins.fileOpener2",[]).factory("$cordovaFileOpener2",["$q",function(e){return{open:function(n,r){var o=e.defer();return cordova.plugins.fileOpener2.open(n,r,{error:function(e){o.reject(e)},success:function(){o.resolve()}}),o.promise},uninstall:function(n){var r=e.defer();return cordova.plugins.fileOpener2.uninstall(n,{error:function(e){r.reject(e)},success:function(){r.resolve()}}),r.promise},appIsInstalled:function(n){var r=e.defer();return cordova.plugins.fileOpener2.appIsInstalled(n,{success:function(e){r.resolve(e)}}),r.promise}}}]),angular.module("ngCordova.plugins.fileTransfer",[]).factory("$cordovaFileTransfer",["$q","$timeout",function(e,n){return{download:function(r,o,t,i){var a=e.defer(),c=new FileTransfer,u=t&&t.encodeURI===!1?r:encodeURI(r);return t&&void 0!==t.timeout&&null!==t.timeout&&(n(function(){c.abort()},t.timeout),t.timeout=null),c.onprogress=function(e){a.notify(e)},a.promise.abort=function(){c.abort()},c.download(u,o,a.resolve,a.reject,i,t),a.promise},upload:function(r,o,t,i){var a=e.defer(),c=new FileTransfer,u=t&&t.encodeURI===!1?r:encodeURI(r);return t&&void 0!==t.timeout&&null!==t.timeout&&(n(function(){c.abort()},t.timeout),t.timeout=null),c.onprogress=function(e){a.notify(e)},a.promise.abort=function(){c.abort()},c.upload(o,u,a.resolve,a.reject,t,i),a.promise}}}]),angular.module("ngCordova.plugins.flashlight",[]).factory("$cordovaFlashlight",["$q","$window",function(e,n){return{available:function(){var r=e.defer();return n.plugins.flashlight.available(function(e){r.resolve(e)}),r.promise},switchOn:function(){var r=e.defer();return n.plugins.flashlight.switchOn(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},switchOff:function(){var r=e.defer();return n.plugins.flashlight.switchOff(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},toggle:function(){var r=e.defer();return n.plugins.flashlight.toggle(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.flurryAds",[]).factory("$cordovaFlurryAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.FlurryAds.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.FlurryAds.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.FlurryAds.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.FlurryAds.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.FlurryAds.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.FlurryAds.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.FlurryAds.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.FlurryAds.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.ga",[]).factory("$cordovaGA",["$q","$window",function(e,n){return{init:function(r,o){var t=e.defer();return o=o>=0?o:10,n.plugins.gaPlugin.init(function(e){t.resolve(e)},function(e){t.reject(e)},r,o),t.promise},trackEvent:function(r,o,t,i,a,c){var u=e.defer();return n.plugins.gaPlugin.trackEvent(function(e){u.resolve(e)},function(e){u.reject(e)},t,i,a,c),u.promise},trackPage:function(r,o,t){var i=e.defer();return n.plugins.gaPlugin.trackPage(function(e){i.resolve(e)},function(e){i.reject(e)},t),i.promise},setVariable:function(r,o,t,i){var a=e.defer();return n.plugins.gaPlugin.setVariable(function(e){a.resolve(e)},function(e){a.reject(e)},t,i),a.promise},exit:function(){var r=e.defer();return n.plugins.gaPlugin.exit(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.geolocation",[]).factory("$cordovaGeolocation",["$q",function(e){return{getCurrentPosition:function(n){var r=e.defer();return navigator.geolocation.getCurrentPosition(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},watchPosition:function(n){var r=e.defer(),o=navigator.geolocation.watchPosition(function(e){r.notify(e)},function(e){r.reject(e)},n);return r.promise.cancel=function(){navigator.geolocation.clearWatch(o)},r.promise.clearWatch=function(e){navigator.geolocation.clearWatch(e||o)},r.promise.watchID=o,r.promise},clearWatch:function(e){return navigator.geolocation.clearWatch(e)}}}]),angular.module("ngCordova.plugins.globalization",[]).factory("$cordovaGlobalization",["$q",function(e){return{getPreferredLanguage:function(){var n=e.defer();return navigator.globalization.getPreferredLanguage(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getLocaleName:function(){var n=e.defer();return navigator.globalization.getLocaleName(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getFirstDayOfWeek:function(){var n=e.defer();return navigator.globalization.getFirstDayOfWeek(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},dateToString:function(n,r){var o=e.defer();return navigator.globalization.dateToString(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},stringToDate:function(n,r){var o=e.defer();return navigator.globalization.stringToDate(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},getDatePattern:function(n){var r=e.defer();return navigator.globalization.getDatePattern(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},getDateNames:function(n){var r=e.defer();return navigator.globalization.getDateNames(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},isDayLightSavingsTime:function(n){var r=e.defer();return navigator.globalization.isDayLightSavingsTime(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},numberToString:function(n,r){var o=e.defer();return navigator.globalization.numberToString(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},stringToNumber:function(n,r){var o=e.defer();return navigator.globalization.stringToNumber(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},getNumberPattern:function(n){var r=e.defer();return navigator.globalization.getNumberPattern(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},getCurrencyPattern:function(n){var r=e.defer();return navigator.globalization.getCurrencyPattern(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.googleAds",[]).factory("$cordovaGoogleAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.AdMob.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.AdMob.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.AdMob.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.AdMob.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.AdMob.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.AdMob.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.AdMob.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.AdMob.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.googleAnalytics",[]).factory("$cordovaGoogleAnalytics",["$q","$window",function(e,n){return{startTrackerWithId:function(r){var o=e.defer();return n.analytics.startTrackerWithId(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},setUserId:function(r){var o=e.defer();return n.analytics.setUserId(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},debugMode:function(){var r=e.defer();return n.analytics.debugMode(function(e){r.resolve(e)},function(){r.reject()}),r.promise},trackView:function(r){var o=e.defer();return n.analytics.trackView(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},addCustomDimension:function(r,o){var t=e.defer();return n.analytics.addCustomDimension(r,o,function(){t.resolve()},function(e){t.reject(e)}),t.promise},trackEvent:function(r,o,t,i){var a=e.defer();return n.analytics.trackEvent(r,o,t,i,function(e){a.resolve(e)},function(e){a.reject(e)}),a.promise},trackException:function(r,o){var t=e.defer();return n.analytics.trackException(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},trackTiming:function(r,o,t,i){var a=e.defer();return n.analytics.trackTiming(r,o,t,i,function(e){a.resolve(e)},function(e){a.reject(e)}),a.promise},addTransaction:function(r,o,t,i,a,c){var u=e.defer();return n.analytics.addTransaction(r,o,t,i,a,c,function(e){u.resolve(e)},function(e){u.reject(e)}),u.promise},addTransactionItem:function(r,o,t,i,a,c,u){var s=e.defer();return n.analytics.addTransactionItem(r,o,t,i,a,c,u,function(e){s.resolve(e)},function(e){s.reject(e)}),s.promise}}}]),angular.module("ngCordova.plugins.googleMap",[]).factory("$cordovaGoogleMap",["$q","$window",function(e,n){var r=null;return{getMap:function(o){var t=e.defer();if(n.plugin.google.maps){var i=document.getElementById("map_canvas");r=n.plugin.google.maps.Map.getMap(o),r.setDiv(i),t.resolve(r)}else t.reject(null);return t.promise},isMapLoaded:function(){return!!r},addMarker:function(n){var o=e.defer();return r.addMarker(n,function(e){o.resolve(e)}),o.promise},getMapTypeIds:function(){return n.plugin.google.maps.mapTypeId},setVisible:function(n){var o=e.defer();return r.setVisible(n),o.promise},cleanup:function(){r=null}}}]),angular.module("ngCordova.plugins.googlePlayGame",[]).factory("$cordovaGooglePlayGame",["$q",function(e){return{auth:function(){var n=e.defer();return googleplaygame.auth(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},signout:function(){var n=e.defer();return googleplaygame.signout(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},isSignedIn:function(){var n=e.defer();return googleplaygame.isSignedIn(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},showPlayer:function(){var n=e.defer();return googleplaygame.showPlayer(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},submitScore:function(n){var r=e.defer();return googleplaygame.submitScore(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},showAllLeaderboards:function(){var n=e.defer();return googleplaygame.showAllLeaderboards(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},showLeaderboard:function(n){var r=e.defer();return googleplaygame.showLeaderboard(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},unlockAchievement:function(n){var r=e.defer();return googleplaygame.unlockAchievement(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},incrementAchievement:function(n){var r=e.defer();return googleplaygame.incrementAchievement(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},showAchievements:function(){var n=e.defer();return googleplaygame.showAchievements(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.googlePlus",[]).factory("$cordovaGooglePlus",["$q","$window",function(e,n){return{login:function(r){var o=e.defer();return void 0===r&&(r={}),n.plugins.googleplus.login({iOSApiKey:r},function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},silentLogin:function(r){var o=e.defer();return void 0===r&&(r={}),n.plugins.googleplus.trySilentLogin({iOSApiKey:r},function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},logout:function(){var r=e.defer();n.plugins.googleplus.logout(function(e){r.resolve(e)})},disconnect:function(){var r=e.defer();n.plugins.googleplus.disconnect(function(e){r.resolve(e)})},isAvailable:function(){var r=e.defer();return n.plugins.googleplus.isAvailable(function(e){e?r.resolve(e):r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.healthKit",[]).factory("$cordovaHealthKit",["$q","$window",function(e,n){return{isAvailable:function(){var r=e.defer();return n.plugins.healthkit.available(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},checkAuthStatus:function(r){var o=e.defer();return r=r||"HKQuantityTypeIdentifierHeight",n.plugins.healthkit.checkAuthStatus({type:r},function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},requestAuthorization:function(r,o){var t=e.defer();return r=r||["HKCharacteristicTypeIdentifierDateOfBirth","HKQuantityTypeIdentifierActiveEnergyBurned","HKQuantityTypeIdentifierHeight"],o=o||["HKQuantityTypeIdentifierActiveEnergyBurned","HKQuantityTypeIdentifierHeight","HKQuantityTypeIdentifierDistanceCycling"],n.plugins.healthkit.requestAuthorization({readTypes:r,writeTypes:o},function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},readDateOfBirth:function(){var r=e.defer();return n.plugins.healthkit.readDateOfBirth(function(e){r.resolve(e)},function(e){r.resolve(e)}),r.promise},readGender:function(){var r=e.defer();return n.plugins.healthkit.readGender(function(e){r.resolve(e)},function(e){r.resolve(e)}),r.promise},saveWeight:function(r,o,t){var i=e.defer();return n.plugins.healthkit.saveWeight({unit:o||"lb",amount:r,date:t||new Date},function(e){i.resolve(e)},function(e){i.resolve(e)}),i.promise},readWeight:function(r){var o=e.defer();return n.plugins.healthkit.readWeight({unit:r||"lb"},function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise},saveHeight:function(r,o,t){var i=e.defer();return n.plugins.healthkit.saveHeight({unit:o||"in",amount:r,date:t||new Date},function(e){i.resolve(e)},function(e){i.resolve(e)}),i.promise},readHeight:function(r){var o=e.defer();return n.plugins.healthkit.readHeight({unit:r||"in"},function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise},findWorkouts:function(){var r=e.defer();return n.plugins.healthkit.findWorkouts({},function(e){r.resolve(e)},function(e){r.resolve(e)}),r.promise},saveWorkout:function(r){var o=e.defer();return n.plugins.healthkit.saveWorkout(r,function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise},querySampleType:function(r){var o=e.defer();return n.plugins.healthkit.querySampleType(r,function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise}}}]),angular.module("ngCordova.plugins.httpd",[]).factory("$cordovaHttpd",["$q",function(e){return{startServer:function(n){var r=e.defer();return cordova.plugins.CorHttpd.startServer(n,function(){r.resolve()},function(){r.reject()}),r.promise},stopServer:function(){var n=e.defer();return cordova.plugins.CorHttpd.stopServer(function(){n.resolve()},function(){n.reject()}),n.promise},getURL:function(){var n=e.defer();return cordova.plugins.CorHttpd.getURL(function(e){n.resolve(e)},function(){n.reject()}),n.promise},getLocalPath:function(){var n=e.defer();return cordova.plugins.CorHttpd.getLocalPath(function(e){n.resolve(e)},function(){n.reject()}),n.promise}}}]),angular.module("ngCordova.plugins.iAd",[]).factory("$cordovaiAd",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.iAd.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.iAd.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.iAd.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.iAd.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.iAd.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.iAd.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.iAd.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.iAd.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.imagePicker",[]).factory("$cordovaImagePicker",["$q","$window",function(e,n){return{getPictures:function(r){var o=e.defer();return n.imagePicker.getPictures(function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise}}}]),angular.module("ngCordova.plugins.inAppBrowser",[]).provider("$cordovaInAppBrowser",[function(){var e,n=this.defaultOptions={};this.setDefaultOptions=function(e){n=angular.extend(n,e)},this.$get=["$rootScope","$q","$window","$timeout",function(r,o,t,i){return{open:function(a,c,u){var s=o.defer();if(u&&!angular.isObject(u))return s.reject("options must be an object"),s.promise;var l=angular.extend({},n,u),f=[];angular.forEach(l,function(e,n){f.push(n+"="+e)});var d=f.join();return e=t.open(a,c,d),e.addEventListener("loadstart",function(e){i(function(){r.$broadcast("$cordovaInAppBrowser:loadstart",e)})},!1),e.addEventListener("loadstop",function(e){s.resolve(e),i(function(){r.$broadcast("$cordovaInAppBrowser:loadstop",e)})},!1),e.addEventListener("loaderror",function(e){s.reject(e),i(function(){r.$broadcast("$cordovaInAppBrowser:loaderror",e)})},!1),e.addEventListener("exit",function(e){i(function(){r.$broadcast("$cordovaInAppBrowser:exit",e)})},!1),s.promise},close:function(){e.close(),e=null},show:function(){e.show()},executeScript:function(n){var r=o.defer();return e.executeScript(n,function(e){r.resolve(e)}),r.promise},insertCSS:function(n){var r=o.defer();return e.insertCSS(n,function(e){r.resolve(e)}),r.promise}}}]}]),angular.module("ngCordova.plugins.insomnia",[]).factory("$cordovaInsomnia",["$window",function(e){return{keepAwake:function(){return e.plugins.insomnia.keepAwake()},allowSleepAgain:function(){return e.plugins.insomnia.allowSleepAgain()}}}]),angular.module("ngCordova.plugins.instagram",[]).factory("$cordovaInstagram",["$q",function(e){return{share:function(n){var r=e.defer();return window.Instagram?(Instagram.share(n.image,n.caption,function(e){e?r.reject(e):r.resolve(!0)}),r.promise):(console.error("Tried to call Instagram.share but the Instagram plugin isn't installed!"),r.resolve(null),r.promise)},isInstalled:function(){var n=e.defer();return window.Instagram?(Instagram.isInstalled(function(e,r){e?n.reject(e):n.resolve(r)}),n.promise):(console.error("Tried to call Instagram.isInstalled but the Instagram plugin isn't installed!"),n.resolve(null),n.promise)}}}]),angular.module("ngCordova.plugins.keyboard",[]).factory("$cordovaKeyboard",["$rootScope",function(e){var n=function(){e.$evalAsync(function(){e.$broadcast("$cordovaKeyboard:show")})},r=function(){e.$evalAsync(function(){e.$broadcast("$cordovaKeyboard:hide")})};return document.addEventListener("deviceready",function(){cordova.plugins.Keyboard&&(window.addEventListener("native.keyboardshow",n,!1),window.addEventListener("native.keyboardhide",r,!1))}),{hideAccessoryBar:function(e){return cordova.plugins.Keyboard.hideKeyboardAccessoryBar(e)},close:function(){return cordova.plugins.Keyboard.close()},show:function(){return cordova.plugins.Keyboard.show()},disableScroll:function(e){return cordova.plugins.Keyboard.disableScroll(e)},isVisible:function(){return cordova.plugins.Keyboard.isVisible},clearShowWatch:function(){document.removeEventListener("native.keyboardshow",n),e.$$listeners["$cordovaKeyboard:show"]=[]},clearHideWatch:function(){document.removeEventListener("native.keyboardhide",r),e.$$listeners["$cordovaKeyboard:hide"]=[]}}}]),angular.module("ngCordova.plugins.keychain",[]).factory("$cordovaKeychain",["$q",function(e){return{getForKey:function(n,r){var o=e.defer(),t=new Keychain;return t.getForKey(o.resolve,o.reject,n,r),o.promise},setForKey:function(n,r,o){var t=e.defer(),i=new Keychain;return i.setForKey(t.resolve,t.reject,n,r,o),t.promise},removeForKey:function(n,r){var o=e.defer(),t=new Keychain;return t.removeForKey(o.resolve,o.reject,n,r),o.promise}}}]),angular.module("ngCordova.plugins.launchNavigator",[]).factory("$cordovaLaunchNavigator",["$q",function(e){return{navigate:function(n,r,o){var t=e.defer();return launchnavigator.navigate(n,r,function(){t.resolve()},function(e){t.reject(e)},o),t.promise}}}]),angular.module("ngCordova.plugins.localNotification",[]).factory("$cordovaLocalNotification",["$q","$window","$rootScope","$timeout",function(e,n,r,o){return document.addEventListener("deviceready",function(){n.cordova&&n.cordova.plugins&&n.cordova.plugins.notification&&n.cordova.plugins.notification.local&&(n.cordova.plugins.notification.local.on("schedule",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:schedule",e,n)})}),n.cordova.plugins.notification.local.on("trigger",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:trigger",e,n)})}),n.cordova.plugins.notification.local.on("update",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:update",e,n)})}),n.cordova.plugins.notification.local.on("clear",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:clear",e,n)})}),n.cordova.plugins.notification.local.on("clearall",function(e){o(function(){r.$broadcast("$cordovaLocalNotification:clearall",e)})}),n.cordova.plugins.notification.local.on("cancel",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:cancel",e,n)})}),n.cordova.plugins.notification.local.on("cancelall",function(e){o(function(){r.$broadcast("$cordovaLocalNotification:cancelall",e)})}),n.cordova.plugins.notification.local.on("click",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:click",e,n)})}))},!1),{schedule:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.schedule(r,function(e){t.resolve(e)},o),t.promise},add:function(r,o){console.warn('Deprecated: use "schedule" instead.');var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.schedule(r,function(e){t.resolve(e)},o),t.promise},update:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.update(r,function(e){t.resolve(e)},o),t.promise},clear:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.clear(r,function(e){t.resolve(e)},o),t.promise},clearAll:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.clearAll(function(e){o.resolve(e)},r),o.promise},cancel:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.cancel(r,function(e){t.resolve(e)},o),t.promise},cancelAll:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.cancelAll(function(e){o.resolve(e)},r),o.promise},isPresent:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.isPresent(r,function(e){t.resolve(e)},o),t.promise},isScheduled:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.isScheduled(r,function(e){t.resolve(e)},o),t.promise},isTriggered:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.isTriggered(r,function(e){t.resolve(e)},o),t.promise},hasPermission:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.hasPermission(function(e){e?o.resolve(e):o.reject(e)},r),o.promise},registerPermission:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.registerPermission(function(e){e?o.resolve(e):o.reject(e)},r),o.promise},promptForPermission:function(r){console.warn('Deprecated: use "registerPermission" instead.');var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.registerPermission(function(e){ -e?o.resolve(e):o.reject(e)},r),o.promise},getAllIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAllIds(function(e){o.resolve(e)},r),o.promise},getIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getIds(function(e){o.resolve(e)},r),o.promise},getScheduledIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getScheduledIds(function(e){o.resolve(e)},r),o.promise},getTriggeredIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getTriggeredIds(function(e){o.resolve(e)},r),o.promise},get:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.get(r,function(e){t.resolve(e)},o),t.promise},getAll:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAll(function(e){o.resolve(e)},r),o.promise},getScheduled:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.getScheduled(r,function(e){t.resolve(e)},o),t.promise},getAllScheduled:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAllScheduled(function(e){o.resolve(e)},r),o.promise},getTriggered:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.getTriggered(r,function(e){t.resolve(e)},o),t.promise},getAllTriggered:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAllTriggered(function(e){o.resolve(e)},r),o.promise},getDefaults:function(){return n.cordova.plugins.notification.local.getDefaults()},setDefaults:function(e){n.cordova.plugins.notification.local.setDefaults(e)}}}]),angular.module("ngCordova.plugins.mMediaAds",[]).factory("$cordovaMMediaAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.mMedia.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.mMedia.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.mMedia.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.mMedia.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.mMedia.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.mMedia.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.mMedia.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.mMedia.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.media",[]).service("NewMedia",["$q","$interval",function(e,n){function r(e){angular.isDefined(s)||(s=n(function(){0>d&&(d=e.getDuration(),a&&d>0&&a.notify({duration:d})),e.getCurrentPosition(function(e){e>-1&&(f=e)},function(e){console.log("Error getting pos="+e)}),a&&a.notify({position:f})},1e3))}function o(){angular.isDefined(s)&&(n.cancel(s),s=void 0)}function t(){f=-1,d=-1}function i(e){this.media=new Media(e,function(e){o(),t(),a.resolve(e)},function(e){o(),t(),a.reject(e)},function(e){l=e,a.notify({status:l})})}var a,c,u,s,l=null,f=-1,d=-1;return i.prototype.play=function(n){return a=e.defer(),"object"!=typeof n&&(n={}),this.media.play(n),r(this.media),a.promise},i.prototype.pause=function(){o(),this.media.pause()},i.prototype.stop=function(){this.media.stop()},i.prototype.release=function(){this.media.release(),this.media=void 0},i.prototype.seekTo=function(e){this.media.seekTo(e)},i.prototype.setVolume=function(e){this.media.setVolume(e)},i.prototype.startRecord=function(){this.media.startRecord()},i.prototype.stopRecord=function(){this.media.stopRecord()},i.prototype.currentTime=function(){return c=e.defer(),this.media.getCurrentPosition(function(e){c.resolve(e)}),c.promise},i.prototype.getDuration=function(){return u=e.defer(),this.media.getDuration(function(e){u.resolve(e)}),u.promise},i}]).factory("$cordovaMedia",["NewMedia",function(e){return{newMedia:function(n){return new e(n)}}}]),angular.module("ngCordova.plugins.mobfoxAds",[]).factory("$cordovaMobFoxAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.MobFox.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.MobFox.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.MobFox.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.MobFox.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.MobFox.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.MobFox.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.MobFox.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.MobFox.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins",["ngCordova.plugins.actionSheet","ngCordova.plugins.adMob","ngCordova.plugins.appAvailability","ngCordova.plugins.appRate","ngCordova.plugins.appVersion","ngCordova.plugins.backgroundGeolocation","ngCordova.plugins.badge","ngCordova.plugins.barcodeScanner","ngCordova.plugins.batteryStatus","ngCordova.plugins.beacon","ngCordova.plugins.ble","ngCordova.plugins.bluetoothSerial","ngCordova.plugins.brightness","ngCordova.plugins.calendar","ngCordova.plugins.camera","ngCordova.plugins.capture","ngCordova.plugins.clipboard","ngCordova.plugins.contacts","ngCordova.plugins.datePicker","ngCordova.plugins.device","ngCordova.plugins.deviceMotion","ngCordova.plugins.deviceOrientation","ngCordova.plugins.dialogs","ngCordova.plugins.emailComposer","ngCordova.plugins.facebook","ngCordova.plugins.facebookAds","ngCordova.plugins.file","ngCordova.plugins.fileTransfer","ngCordova.plugins.fileOpener2","ngCordova.plugins.flashlight","ngCordova.plugins.flurryAds","ngCordova.plugins.ga","ngCordova.plugins.geolocation","ngCordova.plugins.globalization","ngCordova.plugins.googleAds","ngCordova.plugins.googleAnalytics","ngCordova.plugins.googleMap","ngCordova.plugins.googlePlayGame","ngCordova.plugins.googlePlus","ngCordova.plugins.healthKit","ngCordova.plugins.httpd","ngCordova.plugins.iAd","ngCordova.plugins.imagePicker","ngCordova.plugins.inAppBrowser","ngCordova.plugins.instagram","ngCordova.plugins.keyboard","ngCordova.plugins.keychain","ngCordova.plugins.launchNavigator","ngCordova.plugins.localNotification","ngCordova.plugins.media","ngCordova.plugins.mMediaAds","ngCordova.plugins.mobfoxAds","ngCordova.plugins.mopubAds","ngCordova.plugins.nativeAudio","ngCordova.plugins.network","ngCordova.plugins.pinDialog","ngCordova.plugins.preferences","ngCordova.plugins.printer","ngCordova.plugins.progressIndicator","ngCordova.plugins.push","ngCordova.plugins.push_v5","ngCordova.plugins.sms","ngCordova.plugins.socialSharing","ngCordova.plugins.spinnerDialog","ngCordova.plugins.splashscreen","ngCordova.plugins.sqlite","ngCordova.plugins.statusbar","ngCordova.plugins.toast","ngCordova.plugins.touchid","ngCordova.plugins.vibration","ngCordova.plugins.videoCapturePlus","ngCordova.plugins.zip","ngCordova.plugins.insomnia"]),angular.module("ngCordova.plugins.mopubAds",[]).factory("$cordovaMoPubAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.MoPub.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.MoPub.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.MoPub.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.MoPub.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.MoPub.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.MoPub.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.MoPub.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.MoPub.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.nativeAudio",[]).factory("$cordovaNativeAudio",["$q","$window",function(e,n){return{preloadSimple:function(r,o){var t=e.defer();return n.plugins.NativeAudio.preloadSimple(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},preloadComplex:function(r,o,t,i,a){var c=e.defer();return n.plugins.NativeAudio.preloadComplex(r,o,t,i,a,function(e){c.resolve(e)},function(e){c.reject(e)}),c.promise},play:function(r,o){var t=e.defer();return n.plugins.NativeAudio.play(r,function(e){t.resolve(e)},function(e){t.reject(e)},o),t.promise},stop:function(r){var o=e.defer();return n.plugins.NativeAudio.stop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},loop:function(r){var o=e.defer();return n.plugins.NativeAudio.loop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},unload:function(r){var o=e.defer();return n.plugins.NativeAudio.unload(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},setVolumeForComplexAsset:function(r,o){var t=e.defer();return n.plugins.NativeAudio.setVolumeForComplexAsset(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise}}}]),angular.module("ngCordova.plugins.network",[]).factory("$cordovaNetwork",["$rootScope","$timeout",function(e,n){var r=function(){var r=navigator.connection.type;n(function(){e.$broadcast("$cordovaNetwork:offline",r)})},o=function(){var r=navigator.connection.type;n(function(){e.$broadcast("$cordovaNetwork:online",r)})};return document.addEventListener("deviceready",function(){navigator.connection&&(document.addEventListener("offline",r,!1),document.addEventListener("online",o,!1))}),{getNetwork:function(){return navigator.connection.type},isOnline:function(){var e=navigator.connection.type;return e!==Connection.UNKNOWN&&e!==Connection.NONE},isOffline:function(){var e=navigator.connection.type;return e===Connection.UNKNOWN||e===Connection.NONE},clearOfflineWatch:function(){document.removeEventListener("offline",r),e.$$listeners["$cordovaNetwork:offline"]=[]},clearOnlineWatch:function(){document.removeEventListener("online",o),e.$$listeners["$cordovaNetwork:online"]=[]}}}]).run(["$injector",function(e){e.get("$cordovaNetwork")}]),angular.module("ngCordova.plugins.pinDialog",[]).factory("$cordovaPinDialog",["$q","$window",function(e,n){return{prompt:function(r,o,t){var i=e.defer();return n.plugins.pinDialog.prompt(r,function(e){i.resolve(e)},o,t),i.promise}}}]),angular.module("ngCordova.plugins.preferences",[]).factory("$cordovaPreferences",["$window","$q",function(e,n){return{pluginNotEnabledMessage:"Plugin not enabled",decoratePromise:function(e){e.success=function(n){return e.then(n),e},e.error=function(n){return e.then(null,n),e}},store:function(r,o,t){function i(e){c.resolve(e)}function a(e){c.reject(new Error(e))}var c=n.defer(),u=c.promise;if(e.plugins){var s;s=3===arguments.length?e.plugins.appPreferences.store(t,r,o):e.plugins.appPreferences.store(r,o),s.then(i,a)}else c.reject(new Error(this.pluginNotEnabledMessage));return this.decoratePromise(u),u},fetch:function(r,o){function t(e){a.resolve(e)}function i(e){a.reject(new Error(e))}var a=n.defer(),c=a.promise;if(e.plugins){var u;u=2===arguments.length?e.plugins.appPreferences.fetch(o,r):e.plugins.appPreferences.fetch(r),u.then(t,i)}else a.reject(new Error(this.pluginNotEnabledMessage));return this.decoratePromise(c),c},remove:function(r,o){function t(e){a.resolve(e)}function i(e){a.reject(new Error(e))}var a=n.defer(),c=a.promise;if(e.plugins){var u;u=2===arguments.length?e.plugins.appPreferences.remove(o,r):e.plugins.appPreferences.remove(r),u.then(t,i)}else a.reject(new Error(this.pluginNotEnabledMessage));return this.decoratePromise(c),c},show:function(){function r(e){t.resolve(e)}function o(e){t.reject(new Error(e))}var t=n.defer(),i=t.promise;return e.plugins?e.plugins.appPreferences.show().then(r,o):t.reject(new Error(this.pluginNotEnabledMessage)),this.decoratePromise(i),i}}}]),angular.module("ngCordova.plugins.printer",[]).factory("$cordovaPrinter",["$q","$window",function(e,n){return{isAvailable:function(){var r=e.defer();return n.plugin.printer.isAvailable(function(e){r.resolve(e)}),r.promise},print:function(r,o){var t=e.defer();return n.plugin.printer.print(r,o,function(){t.resolve()}),t.promise}}}]),angular.module("ngCordova.plugins.progressIndicator",[]).factory("$cordovaProgress",[function(){return{show:function(e){var n=e||"Please wait...";return ProgressIndicator.show(n)},showSimple:function(e){var n=e||!1;return ProgressIndicator.showSimple(n)},showSimpleWithLabel:function(e,n){var r=e||!1,o=n||"Loading...";return ProgressIndicator.showSimpleWithLabel(r,o)},showSimpleWithLabelDetail:function(e,n,r){var o=e||!1,t=n||"Loading...",i=r||"Please wait";return ProgressIndicator.showSimpleWithLabelDetail(o,t,i)},showDeterminate:function(e,n){var r=e||!1,o=n||5e4;return ProgressIndicator.showDeterminate(r,o)},showDeterminateWithLabel:function(e,n,r){var o=e||!1,t=n||5e4,i=r||"Loading...";return ProgressIndicator.showDeterminateWithLabel(o,t,i)},showAnnular:function(e,n){var r=e||!1,o=n||5e4;return ProgressIndicator.showAnnular(r,o)},showAnnularWithLabel:function(e,n,r){var o=e||!1,t=n||5e4,i=r||"Loading...";return ProgressIndicator.showAnnularWithLabel(o,t,i)},showBar:function(e,n){var r=e||!1,o=n||5e4;return ProgressIndicator.showBar(r,o)},showBarWithLabel:function(e,n,r){var o=e||!1,t=n||5e4,i=r||"Loading...";return ProgressIndicator.showBarWithLabel(o,t,i)},showSuccess:function(e,n){var r=e||!1,o=n||"Success";return ProgressIndicator.showSuccess(r,o)},showText:function(e,n,r){var o=e||!1,t=n||"Warning",i=r||"center";return ProgressIndicator.showText(o,t,i)},hide:function(){return ProgressIndicator.hide()}}}]),angular.module("ngCordova.plugins.push",[]).factory("$cordovaPush",["$q","$window","$rootScope","$timeout",function(e,n,r,o){return{onNotification:function(e){o(function(){r.$broadcast("$cordovaPush:notificationReceived",e)})},register:function(r){var o,t=e.defer();return void 0!==r&&void 0===r.ecb&&(o=null===document.querySelector("[ng-app]")?"document.body":"document.querySelector('[ng-app]')",r.ecb="angular.element("+o+").injector().get('$cordovaPush').onNotification"),n.plugins.pushNotification.register(function(e){t.resolve(e)},function(e){t.reject(e)},r),t.promise},unregister:function(r){var o=e.defer();return n.plugins.pushNotification.unregister(function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},setBadgeNumber:function(r){var o=e.defer();return n.plugins.pushNotification.setApplicationIconBadgeNumber(function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise}}}]),angular.module("ngCordova.plugins.push_v5",[]).factory("$cordovaPushV5",["$q","$rootScope","$timeout",function(e,n,r){var o;return{initialize:function(n){var r=e.defer();return o=PushNotification.init(n),r.resolve(o),r.promise},onNotification:function(){r(function(){o.on("notification",function(e){n.$emit("$cordovaPushV5:notificationReceived",e)})})},onError:function(){r(function(){o.on("error",function(e){n.$emit("$cordovaPushV5:errorOccurred",e)})})},register:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.on("registration",function(e){n.resolve(e.registrationId)}),n.promise},unregister:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.unregister(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getBadgeNumber:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.getApplicationIconBadgeNumber(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},setBadgeNumber:function(n){var r=e.defer();return void 0===o?r.reject(new Error("init must be called before any other operation")):o.setApplicationIconBadgeNumber(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},finish:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.finish(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.screenshot",[]).factory("$cordovaScreenshot",["$q",function(e){return{captureToFile:function(n){var r=n||{},o=r.extension||"jpg",t=r.quality||"100",i=e.defer();return navigator.screenshot?(navigator.screenshot.save(function(e,n){e?i.reject(e):i.resolve(n.filePath)},o,t,r.filename),i.promise):(i.resolve(null),i.promise)},captureToUri:function(n){var r=n||{},o=r.extension||"jpg",t=r.quality||"100",i=e.defer();return navigator.screenshot?(navigator.screenshot.URI(function(e,n){e?i.reject(e):i.resolve(n.URI)},o,t,r.filename),i.promise):(i.resolve(null),i.promise)}}}]),angular.module("ngCordova.plugins.sms",[]).factory("$cordovaSms",["$q",function(e){return{send:function(n,r,o){var t=e.defer();return sms.send(n,r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise}}}]),angular.module("ngCordova.plugins.socialSharing",[]).factory("$cordovaSocialSharing",["$q","$window",function(e,n){return{share:function(r,o,t,i){var a=e.defer();return o=o||null,t=t||null,i=i||null,n.plugins.socialsharing.share(r,o,t,i,function(){a.resolve(!0)},function(){a.reject(!1)}),a.promise},shareViaTwitter:function(r,o,t){var i=e.defer();return o=o||null,t=t||null,n.plugins.socialsharing.shareViaTwitter(r,o,t,function(){i.resolve(!0)},function(){i.reject(!1)}),i.promise},shareViaWhatsApp:function(r,o,t){var i=e.defer();return o=o||null,t=t||null,n.plugins.socialsharing.shareViaWhatsApp(r,o,t,function(){i.resolve(!0)},function(){i.reject(!1)}),i.promise},shareViaFacebook:function(r,o,t){var i=e.defer();return r=r||null,o=o||null,t=t||null,n.plugins.socialsharing.shareViaFacebook(r,o,t,function(){i.resolve(!0)},function(){i.reject(!1)}),i.promise},shareViaFacebookWithPasteMessageHint:function(r,o,t,i){var a=e.defer();return o=o||null,t=t||null,n.plugins.socialsharing.shareViaFacebookWithPasteMessageHint(r,o,t,i,function(){a.resolve(!0)},function(){a.reject(!1)}),a.promise},shareViaSMS:function(r,o){var t=e.defer();return n.plugins.socialsharing.shareViaSMS(r,o,function(){t.resolve(!0)},function(){t.reject(!1)}),t.promise},shareViaEmail:function(r,o,t,i,a,c){var u=e.defer();return t=t||null,i=i||null,a=a||null,c=c||null,n.plugins.socialsharing.shareViaEmail(r,o,t,i,a,c,function(){u.resolve(!0)},function(){u.reject(!1)}),u.promise},shareVia:function(r,o,t,i,a){var c=e.defer();return o=o||null,t=t||null,i=i||null,a=a||null,n.plugins.socialsharing.shareVia(r,o,t,i,a,function(){c.resolve(!0)},function(){c.reject(!1)}),c.promise},canShareViaEmail:function(){var r=e.defer();return n.plugins.socialsharing.canShareViaEmail(function(){r.resolve(!0)},function(){r.reject(!1)}),r.promise},canShareVia:function(r,o,t,i,a){var c=e.defer();return n.plugins.socialsharing.canShareVia(r,o,t,i,a,function(e){c.resolve(e)},function(e){c.reject(e)}),c.promise},available:function(){var n=e.defer();return window.plugins.socialsharing.available(function(e){e?n.resolve():n.reject()}),n.promise}}}]),angular.module("ngCordova.plugins.spinnerDialog",[]).factory("$cordovaSpinnerDialog",["$window",function(e){return{show:function(n,r,o){return o=o||!1,e.plugins.spinnerDialog.show(n,r,o)},hide:function(){return e.plugins.spinnerDialog.hide()}}}]),angular.module("ngCordova.plugins.splashscreen",[]).factory("$cordovaSplashscreen",[function(){return{hide:function(){return navigator.splashscreen.hide()},show:function(){return navigator.splashscreen.show()}}}]),angular.module("ngCordova.plugins.sqlite",[]).factory("$cordovaSQLite",["$q","$window",function(e,n){return{openDB:function(e,r){return angular.isObject(e)&&!angular.isString(e)?("undefined"!=typeof r&&(e.bgType=r),n.sqlitePlugin.openDatabase(e)):n.sqlitePlugin.openDatabase({name:e,bgType:r})},execute:function(n,r,o){var t=e.defer();return n.transaction(function(e){e.executeSql(r,o,function(e,n){t.resolve(n)},function(e,n){t.reject(n)})}),t.promise},insertCollection:function(n,r,o){var t=e.defer(),i=o.slice(0);return n.transaction(function(e){!function n(){var o=i.splice(0,1)[0];try{e.executeSql(r,o,function(e,r){0===i.length?t.resolve(r):n()},function(e,n){t.reject(n)})}catch(a){t.reject(a)}}()}),t.promise},nestedExecute:function(n,r,o,t,i){var a=e.defer();return n.transaction(function(e){e.executeSql(r,t,function(e,n){a.resolve(n),e.executeSql(o,i,function(e,n){a.resolve(n)})})},function(e,n){a.reject(n)}),a.promise},deleteDB:function(r){var o=e.defer();return n.sqlitePlugin.deleteDatabase(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.statusbar",[]).factory("$cordovaStatusbar",[function(){return{overlaysWebView:function(e){return StatusBar.overlaysWebView(!!e)},STYLES:{DEFAULT:0,LIGHT_CONTENT:1,BLACK_TRANSLUCENT:2,BLACK_OPAQUE:3},style:function(e){switch(e){case 0:return StatusBar.styleDefault();case 1:return StatusBar.styleLightContent();case 2:return StatusBar.styleBlackTranslucent();case 3:return StatusBar.styleBlackOpaque();default:return StatusBar.styleDefault()}},styleColor:function(e){return StatusBar.backgroundColorByName(e)},styleHex:function(e){return StatusBar.backgroundColorByHexString(e)},hide:function(){return StatusBar.hide()},show:function(){return StatusBar.show()},isVisible:function(){return StatusBar.isVisible}}}]),angular.module("ngCordova.plugins.toast",[]).factory("$cordovaToast",["$q","$window",function(e,n){return{showShortTop:function(r){var o=e.defer();return n.plugins.toast.showShortTop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showShortCenter:function(r){var o=e.defer();return n.plugins.toast.showShortCenter(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showShortBottom:function(r){var o=e.defer();return n.plugins.toast.showShortBottom(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showLongTop:function(r){var o=e.defer();return n.plugins.toast.showLongTop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showLongCenter:function(r){var o=e.defer();return n.plugins.toast.showLongCenter(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showLongBottom:function(r){var o=e.defer();return n.plugins.toast.showLongBottom(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},show:function(r,o,t){var i=e.defer();return n.plugins.toast.show(r,o,t,function(e){i.resolve(e)},function(e){i.reject(e)}),i.promise},hide:function(){var r=e.defer();try{n.plugins.toast.hide(),r.resolve()}catch(o){r.reject(o&&o.message)}return r.promise}}}]),angular.module("ngCordova.plugins.touchid",[]).factory("$cordovaTouchID",["$q",function(e){return{checkSupport:function(){var n=e.defer();return window.cordova?touchid.checkSupport(function(e){n.resolve(e)},function(e){n.reject(e)}):n.reject("Not supported without cordova.js"),n.promise},authenticate:function(n){var r=e.defer();return window.cordova?touchid.authenticate(function(e){r.resolve(e)},function(e){r.reject(e)},n):r.reject("Not supported without cordova.js"),r.promise}}}]),angular.module("ngCordova.plugins.upsPush",[]).factory("$cordovaUpsPush",["$q","$window","$rootScope","$timeout",function(e,n,r,o){return{register:function(t){var i=e.defer();return n.push.register(function(e){o(function(){r.$broadcast("$cordovaUpsPush:notificationReceived",e)})},function(){i.resolve()},function(e){i.reject(e)},t),i.promise},unregister:function(r){var o=e.defer();return n.push.unregister(function(){o.resolve()},function(e){o.reject(e)},r),o.promise},setBadgeNumber:function(r){var o=e.defer();return n.push.setApplicationIconBadgeNumber(function(){o.resolve()},r),o.promise}}}]),angular.module("ngCordova.plugins.vibration",[]).factory("$cordovaVibration",[function(){return{vibrate:function(e){return navigator.notification.vibrate(e)},vibrateWithPattern:function(e,n){return navigator.notification.vibrateWithPattern(e,n)},cancelVibration:function(){return navigator.notification.cancelVibration()}}}]),angular.module("ngCordova.plugins.videoCapturePlus",[]).provider("$cordovaVideoCapturePlus",[function(){var e={};this.setLimit=function(n){e.limit=n},this.setMaxDuration=function(n){e.duration=n},this.setHighQuality=function(n){e.highquality=n},this.useFrontCamera=function(n){e.frontcamera=n},this.setPortraitOverlay=function(n){e.portraitOverlay=n},this.setLandscapeOverlay=function(n){e.landscapeOverlay=n},this.setOverlayText=function(n){e.overlayText=n},this.$get=["$q","$window",function(n,r){return{captureVideo:function(o){var t=n.defer();return r.plugins.videocaptureplus?(r.plugins.videocaptureplus.captureVideo(t.resolve,t.reject,angular.extend({},e,o)),t.promise):(t.resolve(null),t.promise)}}}]}]),angular.module("ngCordova.plugins.zip",[]).factory("$cordovaZip",["$q","$window",function(e,n){return{unzip:function(r,o){var t=e.defer();return n.zip.unzip(r,o,function(e){0===e?t.resolve():t.reject()},function(e){t.notify(e)}),t.promise}}}])}(); \ No newline at end of file diff --git a/assets/www/js/vendor/numeral.en.js b/assets/www/js/vendor/numeral.en.js deleted file mode 100644 index 8e2d6402bcc01ac04a4f9ead620d38587baff58c..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/numeral.en.js +++ /dev/null @@ -1,26 +0,0 @@ -//! moment.js locale configuration -//! locale : english (en) -//! author : Benoit Lavenier : https://github.com/blavenie - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('./numeral')) : - typeof define === 'function' && define.amd ? define(['numeral'], factory) : - factory(global.numeral) -}(this, function (numeral) { 'use strict'; - - numeral.language('en', { - "delimiters": { - "thousands": ",", - "decimal": "." - }, - "abbreviations": { - "thousand": "<small>x10<sup>3</sup></small>", - "million": "<small>x10<sup>6</sup></small>", - "billion": "<small>x10<sup>9</sup></small>", - "trillion": "<small>x10<sup>12</sup></small>" - }, - "currency": { - "symbol": "X" - } - }); -})); diff --git a/assets/www/dist/dist_js/app/vendor/numeral.fr.js b/assets/www/js/vendor/numeral.eo.js similarity index 80% rename from assets/www/dist/dist_js/app/vendor/numeral.fr.js rename to assets/www/js/vendor/numeral.eo.js index 89679d85949df84fd6aea7122d107a0c210a11fe..5ccd37e71a5a7908db44f3e8d6d055379ae51758 100644 --- a/assets/www/dist/dist_js/app/vendor/numeral.fr.js +++ b/assets/www/js/vendor/numeral.eo.js @@ -1,6 +1,6 @@ //! numeral.js locale configuration -//! locale : french (fr) -//! author : blavenie: https://github.com/blavenie +//! locale : esperanto (eo) +//! author : Vivakvo: https://github.com/vivakvo (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../numeral')) : @@ -8,7 +8,7 @@ factory(global.numeral) }(this, function (numeral) { 'use strict'; - numeral.language('fr', { + numeral.language('eo', { "delimiters": { "thousands": " ", "decimal": "," @@ -20,7 +20,7 @@ "trillion": "x10^12" }, "ordinal": function (number) { - return (number === 1) ? 'er' : 'ième'; + return (number === 1) ? 'a' : 'a'; }, "currency": { "symbol": "X" diff --git a/assets/www/js/vendor/numeral.es.js b/assets/www/js/vendor/numeral.es.js deleted file mode 100644 index 82885185fa168bb52f40e6df4b260d4f7e479ea4..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/numeral.es.js +++ /dev/null @@ -1,47 +0,0 @@ -//! numeral.js locale configuration -//! locale : spanish (es) -//! author : Fiatou: https://github.com/fiatou - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../numeral')) : - typeof define === 'function' && define.amd ? define(['numeral'], factory) : - factory(global.numeral) -}(this, function (numeral) { 'use strict'; - - numeral.language('es', { - "delimiters": { - "thousands": " ", - "decimal": "," - }, - "abbreviations": { - "thousand": "<small>x10<sup>3</sup></small>", - "million": "<small>x10<sup>6</sup></small>", - "billion": "<small>x10<sup>9</sup></small>", - "trillion": "<small>x10<sup>12</sup></small>" - }, - "ordinal": function (number) { - switch(number) { - case 1: - return 'ero'; - case 2: - return 'do'; - case 3: - return 'ro'; - case 4: - case 5: - case 6: - case 7: - return 'to'; - case 8: - return 'vo'; - case 9: - return 'no'; - default: - return 'mo'; - } - }, - "currency": { - "symbol": "X" - } - }); -})); diff --git a/assets/www/js/vendor/numeral.js b/assets/www/js/vendor/numeral.js deleted file mode 100644 index 9f46ab65574ea436c29b25880725915cdd9737aa..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/numeral.js +++ /dev/null @@ -1,679 +0,0 @@ -/*! - * numeral.js - * version : 1.5.3 - * author : Adam Draper - * license : MIT - * http://adamwdraper.github.com/Numeral-js/ - */ - -(function () { - - /************************************ - Constants - ************************************/ - - var numeral, - VERSION = '1.5.3', - // internal storage for language config files - languages = {}, - currentLanguage = 'en', - zeroFormat = null, - defaultFormat = '0,0', - // check for nodeJS - hasModule = (typeof module !== 'undefined' && module.exports); - - - /************************************ - Constructors - ************************************/ - - - // Numeral prototype object - function Numeral (number) { - this._value = number; - } - - /** - * Implementation of toFixed() that treats floats more like decimals - * - * Fixes binary rounding issues (eg. (0.615).toFixed(2) === '0.61') that present - * problems for accounting- and finance-related software. - */ - function toFixed (value, precision, roundingFunction, optionals) { - var power = Math.pow(10, precision), - optionalsRegExp, - output; - - //roundingFunction = (roundingFunction !== undefined ? roundingFunction : Math.round); - // Multiply up by precision, round accurately, then divide and use native toFixed(): - output = (roundingFunction(value * power) / power).toFixed(precision); - - if (optionals) { - optionalsRegExp = new RegExp('0{1,' + optionals + '}$'); - output = output.replace(optionalsRegExp, ''); - } - - return output; - } - - /************************************ - Formatting - ************************************/ - - // determine what type of formatting we need to do - function formatNumeral (n, format, roundingFunction) { - var output; - - // figure out what kind of format we are dealing with - if (format.indexOf('$') > -1) { // currency!!!!! - output = formatCurrency(n, format, roundingFunction); - } else if (format.indexOf('%') > -1) { // percentage - output = formatPercentage(n, format, roundingFunction); - } else if (format.indexOf(':') > -1) { // time - output = formatTime(n, format); - } else { // plain ol' numbers or bytes - output = formatNumber(n._value, format, roundingFunction); - } - - // return string - return output; - } - - // revert to number - function unformatNumeral (n, string) { - var stringOriginal = string, - thousandRegExp, - millionRegExp, - billionRegExp, - trillionRegExp, - suffixes = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], - bytesMultiplier = false, - power; - - if (string.indexOf(':') > -1) { - n._value = unformatTime(string); - } else { - if (string === zeroFormat) { - n._value = 0; - } else { - if (languages[currentLanguage].delimiters.decimal !== '.') { - string = string.replace(/\./g,'').replace(languages[currentLanguage].delimiters.decimal, '.'); - } - - // see if abbreviations are there so that we can multiply to the correct number - thousandRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.thousand + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'); - millionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.million + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'); - billionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.billion + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'); - trillionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.trillion + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$'); - - // see if bytes are there so that we can multiply to the correct number - for (power = 0; power <= suffixes.length; power++) { - bytesMultiplier = (string.indexOf(suffixes[power]) > -1) ? Math.pow(1024, power + 1) : false; - - if (bytesMultiplier) { - break; - } - } - - // do some math to create our number - n._value = ((bytesMultiplier) ? bytesMultiplier : 1) * ((stringOriginal.match(thousandRegExp)) ? Math.pow(10, 3) : 1) * ((stringOriginal.match(millionRegExp)) ? Math.pow(10, 6) : 1) * ((stringOriginal.match(billionRegExp)) ? Math.pow(10, 9) : 1) * ((stringOriginal.match(trillionRegExp)) ? Math.pow(10, 12) : 1) * ((string.indexOf('%') > -1) ? 0.01 : 1) * (((string.split('-').length + Math.min(string.split('(').length-1, string.split(')').length-1)) % 2)? 1: -1) * Number(string.replace(/[^0-9\.]+/g, '')); - - // round if we are talking about bytes - n._value = (bytesMultiplier) ? Math.ceil(n._value) : n._value; - } - } - return n._value; - } - - function formatCurrency (n, format, roundingFunction) { - var symbolIndex = format.indexOf('$'), - openParenIndex = format.indexOf('('), - minusSignIndex = format.indexOf('-'), - space = '', - spliceIndex, - output; - - // check for space before or after currency - if (format.indexOf(' $') > -1) { - space = ' '; - format = format.replace(' $', ''); - } else if (format.indexOf('$ ') > -1) { - space = ' '; - format = format.replace('$ ', ''); - } else { - format = format.replace('$', ''); - } - - // format the number - output = formatNumber(n._value, format, roundingFunction); - - // position the symbol - if (symbolIndex <= 1) { - if (output.indexOf('(') > -1 || output.indexOf('-') > -1) { - output = output.split(''); - spliceIndex = 1; - if (symbolIndex < openParenIndex || symbolIndex < minusSignIndex){ - // the symbol appears before the "(" or "-" - spliceIndex = 0; - } - output.splice(spliceIndex, 0, languages[currentLanguage].currency.symbol + space); - output = output.join(''); - } else { - output = languages[currentLanguage].currency.symbol + space + output; - } - } else { - if (output.indexOf(')') > -1) { - output = output.split(''); - output.splice(-1, 0, space + languages[currentLanguage].currency.symbol); - output = output.join(''); - } else { - output = output + space + languages[currentLanguage].currency.symbol; - } - } - - return output; - } - - function formatPercentage (n, format, roundingFunction) { - var space = '', - output, - value = n._value * 100; - - // check for space before % - if (format.indexOf(' %') > -1) { - space = ' '; - format = format.replace(' %', ''); - } else { - format = format.replace('%', ''); - } - - output = formatNumber(value, format, roundingFunction); - - if (output.indexOf(')') > -1 ) { - output = output.split(''); - output.splice(-1, 0, space + '%'); - output = output.join(''); - } else { - output = output + space + '%'; - } - - return output; - } - - function formatTime (n) { - var hours = Math.floor(n._value/60/60), - minutes = Math.floor((n._value - (hours * 60 * 60))/60), - seconds = Math.round(n._value - (hours * 60 * 60) - (minutes * 60)); - return hours + ':' + ((minutes < 10) ? '0' + minutes : minutes) + ':' + ((seconds < 10) ? '0' + seconds : seconds); - } - - function unformatTime (string) { - var timeArray = string.split(':'), - seconds = 0; - // turn hours and minutes into seconds and add them all up - if (timeArray.length === 3) { - // hours - seconds = seconds + (Number(timeArray[0]) * 60 * 60); - // minutes - seconds = seconds + (Number(timeArray[1]) * 60); - // seconds - seconds = seconds + Number(timeArray[2]); - } else if (timeArray.length === 2) { - // minutes - seconds = seconds + (Number(timeArray[0]) * 60); - // seconds - seconds = seconds + Number(timeArray[1]); - } - return Number(seconds); - } - - function formatNumber (value, format, roundingFunction) { - var negP = false, - signed = false, - optDec = false, - abbr = '', - abbrK = false, // force abbreviation to thousands - abbrM = false, // force abbreviation to millions - abbrB = false, // force abbreviation to billions - abbrT = false, // force abbreviation to trillions - abbrForce = false, // force abbreviation - bytes = '', - ord = '', - abs = Math.abs(value), - suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], - min, - max, - power, - w, - precision, - thousands, - d = '', - neg = false; - - // check if number is zero and a custom zero format has been set - if (value === 0 && zeroFormat !== null) { - return zeroFormat; - } else { - // see if we should use parentheses for negative number or if we should prefix with a sign - // if both are present we default to parentheses - if (format.indexOf('(') > -1) { - negP = true; - format = format.slice(1, -1); - } else if (format.indexOf('+') > -1) { - signed = true; - format = format.replace(/\+/g, ''); - } - - // see if abbreviation is wanted - if (format.indexOf('a') > -1) { - // check if abbreviation is specified - abbrK = format.indexOf('aK') >= 0; - abbrM = format.indexOf('aM') >= 0; - abbrB = format.indexOf('aB') >= 0; - abbrT = format.indexOf('aT') >= 0; - abbrForce = abbrK || abbrM || abbrB || abbrT; - - // check for space before abbreviation - if (format.indexOf(' a') > -1) { - abbr = ' '; - format = format.replace(' a', ''); - } else { - format = format.replace('a', ''); - } - - if (abs >= Math.pow(10, 12) && !abbrForce || abbrT) { - // trillion - abbr = abbr + languages[currentLanguage].abbreviations.trillion; - value = value / Math.pow(10, 12); - } else if (abs < Math.pow(10, 12) && abs >= Math.pow(10, 9) && !abbrForce || abbrB) { - // billion - abbr = abbr + languages[currentLanguage].abbreviations.billion; - value = value / Math.pow(10, 9); - } else if (abs < Math.pow(10, 9) && abs >= Math.pow(10, 6) && !abbrForce || abbrM) { - // million - abbr = abbr + languages[currentLanguage].abbreviations.million; - value = value / Math.pow(10, 6); - } else if (abs < Math.pow(10, 6) && abs >= Math.pow(10, 3) && !abbrForce || abbrK) { - // thousand - abbr = abbr + languages[currentLanguage].abbreviations.thousand; - value = value / Math.pow(10, 3); - } - } - - // see if we are formatting bytes - if (format.indexOf('b') > -1) { - // check for space before - if (format.indexOf(' b') > -1) { - bytes = ' '; - format = format.replace(' b', ''); - } else { - format = format.replace('b', ''); - } - - for (power = 0; power <= suffixes.length; power++) { - min = Math.pow(1024, power); - max = Math.pow(1024, power+1); - - if (value >= min && value < max) { - bytes = bytes + suffixes[power]; - if (min > 0) { - value = value / min; - } - break; - } - } - } - - // see if ordinal is wanted - if (format.indexOf('o') > -1) { - // check for space before - if (format.indexOf(' o') > -1) { - ord = ' '; - format = format.replace(' o', ''); - } else { - format = format.replace('o', ''); - } - - ord = ord + languages[currentLanguage].ordinal(value); - } - - if (format.indexOf('[.]') > -1) { - optDec = true; - format = format.replace('[.]', '.'); - } - - w = value.toString().split('.')[0]; - precision = format.split('.')[1]; - thousands = format.indexOf(','); - - if (precision) { - if (precision.indexOf('[') > -1) { - precision = precision.replace(']', ''); - precision = precision.split('['); - d = toFixed(value, (precision[0].length + precision[1].length), roundingFunction, precision[1].length); - } else { - d = toFixed(value, precision.length, roundingFunction); - } - - w = d.split('.')[0]; - - if (d.split('.')[1].length) { - d = languages[currentLanguage].delimiters.decimal + d.split('.')[1]; - } else { - d = ''; - } - - if (optDec && Number(d.slice(1)) === 0) { - d = ''; - } - } else { - w = toFixed(value, null, roundingFunction); - } - - // format number - if (w.indexOf('-') > -1) { - w = w.slice(1); - neg = true; - } - - if (thousands > -1) { - w = w.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + languages[currentLanguage].delimiters.thousands); - } - - if (format.indexOf('.') === 0) { - w = ''; - } - - return ((negP && neg) ? '(' : '') + ((!negP && neg) ? '-' : '') + ((!neg && signed) ? '+' : '') + w + d + ((ord) ? ord : '') + ((abbr) ? abbr : '') + ((bytes) ? bytes : '') + ((negP && neg) ? ')' : ''); - } - } - - /************************************ - Top Level Functions - ************************************/ - - numeral = function (input) { - if (numeral.isNumeral(input)) { - input = input.value(); - } else if (input === 0 || typeof input === 'undefined') { - input = 0; - } else if (!Number(input)) { - input = numeral.fn.unformat(input); - } - - return new Numeral(Number(input)); - }; - - // version number - numeral.version = VERSION; - - // compare numeral object - numeral.isNumeral = function (obj) { - return obj instanceof Numeral; - }; - - // This function will load languages and then set the global language. If - // no arguments are passed in, it will simply return the current global - // language key. - numeral.language = function (key, values) { - if (!key) { - return currentLanguage; - } - - if (key && !values) { - if(!languages[key]) { - throw new Error('Unknown language : ' + key); - } - currentLanguage = key; - } - - if (values || !languages[key]) { - loadLanguage(key, values); - } - - return numeral; - }; - - // This function provides access to the loaded language data. If - // no arguments are passed in, it will simply return the current - // global language object. - numeral.languageData = function (key) { - if (!key) { - return languages[currentLanguage]; - } - - if (!languages[key]) { - throw new Error('Unknown language : ' + key); - } - - return languages[key]; - }; - - numeral.language('en', { - delimiters: { - thousands: ',', - decimal: '.' - }, - abbreviations: { - thousand: 'k', - million: 'm', - billion: 'b', - trillion: 't' - }, - ordinal: function (number) { - var b = number % 10; - return (~~ (number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : - (b === 3) ? 'rd' : 'th'; - }, - currency: { - symbol: '$' - } - }); - - numeral.zeroFormat = function (format) { - zeroFormat = typeof(format) === 'string' ? format : null; - }; - - numeral.defaultFormat = function (format) { - defaultFormat = typeof(format) === 'string' ? format : '0.0'; - }; - - /************************************ - Helpers - ************************************/ - - function loadLanguage(key, values) { - languages[key] = values; - } - - /************************************ - Floating-point helpers - ************************************/ - - // The floating-point helper functions and implementation - // borrows heavily from sinful.js: http://guipn.github.io/sinful.js/ - - /** - * Array.prototype.reduce for browsers that don't support it - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Compatibility - */ - if ('function' !== typeof Array.prototype.reduce) { - Array.prototype.reduce = function (callback, opt_initialValue) { - 'use strict'; - - if (null === this || 'undefined' === typeof this) { - // At the moment all modern browsers, that support strict mode, have - // native implementation of Array.prototype.reduce. For instance, IE8 - // does not support strict mode, so this check is actually useless. - throw new TypeError('Array.prototype.reduce called on null or undefined'); - } - - if ('function' !== typeof callback) { - throw new TypeError(callback + ' is not a function'); - } - - var index, - value, - length = this.length >>> 0, - isValueSet = false; - - if (1 < arguments.length) { - value = opt_initialValue; - isValueSet = true; - } - - for (index = 0; length > index; ++index) { - if (this.hasOwnProperty(index)) { - if (isValueSet) { - value = callback(value, this[index], index, this); - } else { - value = this[index]; - isValueSet = true; - } - } - } - - if (!isValueSet) { - throw new TypeError('Reduce of empty array with no initial value'); - } - - return value; - }; - } - - - /** - * Computes the multiplier necessary to make x >= 1, - * effectively eliminating miscalculations caused by - * finite precision. - */ - function multiplier(x) { - var parts = x.toString().split('.'); - if (parts.length < 2) { - return 1; - } - return Math.pow(10, parts[1].length); - } - - /** - * Given a variable number of arguments, returns the maximum - * multiplier that must be used to normalize an operation involving - * all of them. - */ - function correctionFactor() { - var args = Array.prototype.slice.call(arguments); - return args.reduce(function (prev, next) { - var mp = multiplier(prev), - mn = multiplier(next); - return mp > mn ? mp : mn; - }, -Infinity); - } - - - /************************************ - Numeral Prototype - ************************************/ - - - numeral.fn = Numeral.prototype = { - - clone : function () { - return numeral(this); - }, - - format : function (inputString, roundingFunction) { - return formatNumeral(this, - inputString ? inputString : defaultFormat, - (roundingFunction !== undefined) ? roundingFunction : Math.round - ); - }, - - unformat : function (inputString) { - if (Object.prototype.toString.call(inputString) === '[object Number]') { - return inputString; - } - return unformatNumeral(this, inputString ? inputString : defaultFormat); - }, - - value : function () { - return this._value; - }, - - valueOf : function () { - return this._value; - }, - - set : function (value) { - this._value = Number(value); - return this; - }, - - add : function (value) { - var corrFactor = correctionFactor.call(null, this._value, value); - function cback(accum, curr, currI, O) { - return accum + corrFactor * curr; - } - this._value = [this._value, value].reduce(cback, 0) / corrFactor; - return this; - }, - - subtract : function (value) { - var corrFactor = correctionFactor.call(null, this._value, value); - function cback(accum, curr, currI, O) { - return accum - corrFactor * curr; - } - this._value = [value].reduce(cback, this._value * corrFactor) / corrFactor; - return this; - }, - - multiply : function (value) { - function cback(accum, curr, currI, O) { - var corrFactor = correctionFactor(accum, curr); - return (accum * corrFactor) * (curr * corrFactor) / - (corrFactor * corrFactor); - } - this._value = [this._value, value].reduce(cback, 1); - return this; - }, - - divide : function (value) { - function cback(accum, curr, currI, O) { - var corrFactor = correctionFactor(accum, curr); - return (accum * corrFactor) / (curr * corrFactor); - } - this._value = [this._value, value].reduce(cback); - return this; - }, - - difference : function (value) { - return Math.abs(numeral(this._value).subtract(value).value()); - } - - }; - - /************************************ - Exposing Numeral - ************************************/ - - // CommonJS module is defined - if (hasModule) { - module.exports = numeral; - } - - /*global ender:false */ - if (typeof ender === 'undefined') { - // here, `this` means `window` in the browser, or `global` on the server - // add `numeral` as a global object via a string identifier, - // for Closure Compiler 'advanced' mode - this['numeral'] = numeral; - } - - /*global define:false */ - if (typeof define === 'function' && define.amd) { - define([], function () { - return numeral; - }); - } -}).call(this); diff --git a/assets/www/js/vendor/numeral.nl.js b/assets/www/js/vendor/numeral.nl.js deleted file mode 100644 index f1f704a226a8ee16c212f063d347fde976f9d8ea..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/numeral.nl.js +++ /dev/null @@ -1,27 +0,0 @@ -//! numeral.js locale configuration -//! locale : dutch (nl) -//! author : RA van Hagen : https://github.com/RavanH - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../numeral')) : - typeof define === 'function' && define.amd ? define(['numeral'], factory) : - factory(global.numeral) -}(this, function (numeral) { 'use strict'; - - numeral.language('nl', { - "delimiters": { - "thousands": " ", - "decimal": "," - }, - "abbreviations": { - "thousand": "<small>x10<sup>3</sup></small>", - "million": "<small>x10<sup>6</sup></small>", - "billion": "<small>x10<sup>9</sup></small>", - "trillion": "<small>x10<sup>12</sup></small>" - }, - "ordinal": "<sup>e</sup>", - "currency": { - "symbol": "X" - } - }); -})); diff --git a/assets/www/js/vendor/qrcode.min.js b/assets/www/js/vendor/qrcode.min.js deleted file mode 100644 index 993e88f396640f881b69f98db7a4d17401ef83ca..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/qrcode.min.js +++ /dev/null @@ -1 +0,0 @@ -var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c<a.length&&0==a[c];)c++;this.num=new Array(a.length-c+b);for(var d=0;d<a.length-c;d++)this.num[d]=a[d+c]}function j(a,b){this.totalCount=a,this.dataCount=b}function k(){this.buffer=[],this.length=0}function m(){return"undefined"!=typeof CanvasRenderingContext2D}function n(){var a=!1,b=navigator.userAgent;return/android/i.test(b)&&(a=!0,aMat=b.toString().match(/android ([0-9]\.[0-9])/i),aMat&&aMat[1]&&(a=parseFloat(aMat[1]))),a}function r(a,b){for(var c=1,e=s(a),f=0,g=l.length;g>=f;f++){var h=0;switch(b){case d.L:h=l[f][0];break;case d.M:h=l[f][1];break;case d.Q:h=l[f][2];break;case d.H:h=l[f][3]}if(h>=e)break;c++}if(c>l.length)throw new Error("Too long data");return c}function s(a){var b=encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return b.length+(b.length!=a?3:0)}a.prototype={getLength:function(){return this.parsedData.length},write:function(a){for(var b=0,c=this.parsedData.length;c>b;b++)a.put(this.parsedData[b],8)}},b.prototype={addData:function(b){var c=new a(b);this.dataList.push(c),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d<this.moduleCount;d++){this.modules[d]=new Array(this.moduleCount);for(var e=0;e<this.moduleCount;e++)this.modules[d][e]=null}this.setupPositionProbePattern(0,0),this.setupPositionProbePattern(this.moduleCount-7,0),this.setupPositionProbePattern(0,this.moduleCount-7),this.setupPositionAdjustPattern(),this.setupTimingPattern(),this.setupTypeInfo(a,c),this.typeNumber>=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=f.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;f<this.modules.length;f++)for(var g=f*e,h=0;h<this.modules[f].length;h++){var i=h*e,j=this.modules[f][h];j&&(d.beginFill(0,100),d.moveTo(i,g),d.lineTo(i+e,g),d.lineTo(i+e,g+e),d.lineTo(i,g+e),d.endFill())}return d},setupTimingPattern:function(){for(var a=8;a<this.moduleCount-8;a++)null==this.modules[a][6]&&(this.modules[a][6]=0==a%2);for(var b=8;b<this.moduleCount-8;b++)null==this.modules[6][b]&&(this.modules[6][b]=0==b%2)},setupPositionAdjustPattern:function(){for(var a=f.getPatternPosition(this.typeNumber),b=0;b<a.length;b++)for(var c=0;c<a.length;c++){var d=a[b],e=a[c];if(null==this.modules[d][e])for(var g=-2;2>=g;g++)for(var h=-2;2>=h;h++)this.modules[d+g][e+h]=-2==g||2==g||-2==h||2==h||0==g&&0==h?!0:!1}},setupTypeNumber:function(a){for(var b=f.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=f.getBCHTypeInfo(c),e=0;15>e;e++){var g=!a&&1==(1&d>>e);6>e?this.modules[e][8]=g:8>e?this.modules[e+1][8]=g:this.modules[this.moduleCount-15+e][8]=g}for(var e=0;15>e;e++){var g=!a&&1==(1&d>>e);8>e?this.modules[8][this.moduleCount-e-1]=g:9>e?this.modules[8][15-e-1+1]=g:this.modules[8][15-e-1]=g}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,g=0,h=this.moduleCount-1;h>0;h-=2)for(6==h&&h--;;){for(var i=0;2>i;i++)if(null==this.modules[d][h-i]){var j=!1;g<a.length&&(j=1==(1&a[g]>>>e));var k=f.getMask(b,d,h-i);k&&(j=!j),this.modules[d][h-i]=j,e--,-1==e&&(g++,e=7)}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=j.getRSBlocks(a,c),g=new k,h=0;h<d.length;h++){var i=d[h];g.put(i.mode,4),g.put(i.getLength(),f.getLengthInBits(i.mode,a)),i.write(g)}for(var l=0,h=0;h<e.length;h++)l+=e[h].dataCount;if(g.getLengthInBits()>8*l)throw new Error("code length overflow. ("+g.getLengthInBits()+">"+8*l+")");for(g.getLengthInBits()+4<=8*l&&g.put(0,4);0!=g.getLengthInBits()%8;)g.putBit(!1);for(;;){if(g.getLengthInBits()>=8*l)break;if(g.put(b.PAD0,8),g.getLengthInBits()>=8*l)break;g.put(b.PAD1,8)}return b.createBytes(g,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,g=new Array(b.length),h=new Array(b.length),j=0;j<b.length;j++){var k=b[j].dataCount,l=b[j].totalCount-k;d=Math.max(d,k),e=Math.max(e,l),g[j]=new Array(k);for(var m=0;m<g[j].length;m++)g[j][m]=255&a.buffer[m+c];c+=k;var n=f.getErrorCorrectPolynomial(l),o=new i(g[j],n.getLength()-1),p=o.mod(n);h[j]=new Array(n.getLength()-1);for(var m=0;m<h[j].length;m++){var q=m+p.getLength()-h[j].length;h[j][m]=q>=0?p.get(q):0}}for(var r=0,m=0;m<b.length;m++)r+=b[m].totalCount;for(var s=new Array(r),t=0,m=0;d>m;m++)for(var j=0;j<b.length;j++)m<g[j].length&&(s[t++]=g[j][m]);for(var m=0;e>m;m++)for(var j=0;j<b.length;j++)m<h[j].length&&(s[t++]=h[j][m]);return s};for(var c={MODE_NUMBER:1,MODE_ALPHA_NUM:2,MODE_8BIT_BYTE:4,MODE_KANJI:8},d={L:1,M:0,Q:3,H:2},e={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7},f={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:1335,G18:7973,G15_MASK:21522,getBCHTypeInfo:function(a){for(var b=a<<10;f.getBCHDigit(b)-f.getBCHDigit(f.G15)>=0;)b^=f.G15<<f.getBCHDigit(b)-f.getBCHDigit(f.G15);return(a<<10|b)^f.G15_MASK},getBCHTypeNumber:function(a){for(var b=a<<12;f.getBCHDigit(b)-f.getBCHDigit(f.G18)>=0;)b^=f.G18<<f.getBCHDigit(b)-f.getBCHDigit(f.G18);return a<<12|b},getBCHDigit:function(a){for(var b=0;0!=a;)b++,a>>>=1;return b},getPatternPosition:function(a){return f.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case e.PATTERN000:return 0==(b+c)%2;case e.PATTERN001:return 0==b%2;case e.PATTERN010:return 0==c%3;case e.PATTERN011:return 0==(b+c)%3;case e.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case e.PATTERN101:return 0==b*c%2+b*c%3;case e.PATTERN110:return 0==(b*c%2+b*c%3)%2;case e.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new i([1],0),c=0;a>c;c++)b=b.multiply(new i([1,g.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||d+h>=b))for(var i=-1;1>=i;i++)0>e+i||e+i>=b||(0!=h||0!=i)&&g==a.isDark(d+h,e+i)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b-1>d;d++)for(var e=0;b-1>e;e++){var j=0;a.isDark(d,e)&&j++,a.isDark(d+1,e)&&j++,a.isDark(d,e+1)&&j++,a.isDark(d+1,e+1)&&j++,(0==j||4==j)&&(c+=3)}for(var d=0;b>d;d++)for(var e=0;b-6>e;e++)a.isDark(d,e)&&!a.isDark(d,e+1)&&a.isDark(d,e+2)&&a.isDark(d,e+3)&&a.isDark(d,e+4)&&!a.isDark(d,e+5)&&a.isDark(d,e+6)&&(c+=40);for(var e=0;b>e;e++)for(var d=0;b-6>d;d++)a.isDark(d,e)&&!a.isDark(d+1,e)&&a.isDark(d+2,e)&&a.isDark(d+3,e)&&a.isDark(d+4,e)&&!a.isDark(d+5,e)&&a.isDark(d+6,e)&&(c+=40);for(var k=0,e=0;b>e;e++)for(var d=0;b>d;d++)a.isDark(d,e)&&k++;var l=Math.abs(100*k/b/b-50)/5;return c+=10*l}},g={glog:function(a){if(1>a)throw new Error("glog("+a+")");return g.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return g.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},h=0;8>h;h++)g.EXP_TABLE[h]=1<<h;for(var h=8;256>h;h++)g.EXP_TABLE[h]=g.EXP_TABLE[h-4]^g.EXP_TABLE[h-5]^g.EXP_TABLE[h-6]^g.EXP_TABLE[h-8];for(var h=0;255>h;h++)g.LOG_TABLE[g.EXP_TABLE[h]]=h;i.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;c<this.getLength();c++)for(var d=0;d<a.getLength();d++)b[c+d]^=g.gexp(g.glog(this.get(c))+g.glog(a.get(d)));return new i(b,0)},mod:function(a){if(this.getLength()-a.getLength()<0)return this;for(var b=g.glog(this.get(0))-g.glog(a.get(0)),c=new Array(this.getLength()),d=0;d<this.getLength();d++)c[d]=this.get(d);for(var d=0;d<a.getLength();d++)c[d]^=g.gexp(g.glog(a.get(d))+b);return new i(c,0).mod(a)}},j.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]],j.getRSBlocks=function(a,b){var c=j.getRsBlockTable(a,b);if(void 0==c)throw new Error("bad rs block @ typeNumber:"+a+"/errorCorrectLevel:"+b);for(var d=c.length/3,e=[],f=0;d>f;f++)for(var g=c[3*f+0],h=c[3*f+1],i=c[3*f+2],k=0;g>k;k++)e.push(new j(h,i));return e},j.getRsBlockTable=function(a,b){switch(b){case d.L:return j.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return j.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return j.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return j.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},k.prototype={get:function(a){var b=Math.floor(a/8);return 1==(1&this.buffer[b]>>>7-a%8)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(1&a>>>b-c-1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}};var l=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]],o=function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){function g(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)b.hasOwnProperty(d)&&c.setAttribute(d,b[d]);return c}var b=this._htOption,c=this._el,d=a.getModuleCount();Math.floor(b.width/d),Math.floor(b.height/d),this.clear();var h=g("svg",{viewBox:"0 0 "+String(d)+" "+String(d),width:"100%",height:"100%",fill:b.colorLight});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),c.appendChild(h),h.appendChild(g("rect",{fill:b.colorDark,width:"1",height:"1",id:"template"}));for(var i=0;d>i;i++)for(var j=0;d>j;j++)if(a.isDark(i,j)){var k=g("use",{x:String(i),y:String(j)});k.setAttributeNS("http://www.w3.org/1999/xlink","href","#template"),h.appendChild(k)}},a.prototype.clear=function(){for(;this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild)},a}(),p="svg"===document.documentElement.tagName.toLowerCase(),q=p?o:m()?function(){function a(){this._elImage.src=this._elCanvas.toDataURL("image/png"),this._elImage.style.display="block",this._elCanvas.style.display="none"}function d(a,b){var c=this;if(c._fFail=b,c._fSuccess=a,null===c._bSupportDataURI){var d=document.createElement("img"),e=function(){c._bSupportDataURI=!1,c._fFail&&_fFail.call(c)},f=function(){c._bSupportDataURI=!0,c._fSuccess&&c._fSuccess.call(c)};return d.onabort=e,d.onerror=e,d.onload=f,d.src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",void 0}c._bSupportDataURI===!0&&c._fSuccess?c._fSuccess.call(c):c._bSupportDataURI===!1&&c._fFail&&c._fFail.call(c)}if(this._android&&this._android<=2.1){var b=1/window.devicePixelRatio,c=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(a,d,e,f,g,h,i,j){if("nodeName"in a&&/img/i.test(a.nodeName))for(var l=arguments.length-1;l>=1;l--)arguments[l]=arguments[l]*b;else"undefined"==typeof j&&(arguments[1]*=b,arguments[2]*=b,arguments[3]*=b,arguments[4]*=b);c.apply(this,arguments)}}var e=function(a,b){this._bIsPainted=!1,this._android=n(),this._htOption=b,this._elCanvas=document.createElement("canvas"),this._elCanvas.width=b.width,this._elCanvas.height=b.height,a.appendChild(this._elCanvas),this._el=a,this._oContext=this._elCanvas.getContext("2d"),this._bIsPainted=!1,this._elImage=document.createElement("img"),this._elImage.style.display="none",this._el.appendChild(this._elImage),this._bSupportDataURI=null};return e.prototype.draw=function(a){var b=this._elImage,c=this._oContext,d=this._htOption,e=a.getModuleCount(),f=d.width/e,g=d.height/e,h=Math.round(f),i=Math.round(g);b.style.display="none",this.clear();for(var j=0;e>j;j++)for(var k=0;e>k;k++){var l=a.isDark(j,k),m=k*f,n=j*g;c.strokeStyle=l?d.colorDark:d.colorLight,c.lineWidth=1,c.fillStyle=l?d.colorDark:d.colorLight,c.fillRect(m,n,f,g),c.strokeRect(Math.floor(m)+.5,Math.floor(n)+.5,h,i),c.strokeRect(Math.ceil(m)-.5,Math.ceil(n)-.5,h,i)}this._bIsPainted=!0},e.prototype.makeImage=function(){this._bIsPainted&&d.call(this,a)},e.prototype.isPainted=function(){return this._bIsPainted},e.prototype.clear=function(){this._oContext.clearRect(0,0,this._elCanvas.width,this._elCanvas.height),this._bIsPainted=!1},e.prototype.round=function(a){return a?Math.floor(1e3*a)/1e3:a},e}():function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){for(var b=this._htOption,c=this._el,d=a.getModuleCount(),e=Math.floor(b.width/d),f=Math.floor(b.height/d),g=['<table style="border:0;border-collapse:collapse;">'],h=0;d>h;h++){g.push("<tr>");for(var i=0;d>i;i++)g.push('<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:'+e+"px;height:"+f+"px;background-color:"+(a.isDark(h,i)?b.colorDark:b.colorLight)+';"></td>');g.push("</tr>")}g.push("</table>"),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}(); \ No newline at end of file diff --git a/assets/www/js/vendor/scrypt-em.js b/assets/www/js/vendor/scrypt-em.js deleted file mode 100644 index a98182e62e3580bfa8dfe9ee91c6235720428067..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/scrypt-em.js +++ /dev/null @@ -1,10306 +0,0 @@ -/* - * #%L - * uCoinj :: UI Wicket - * %% - * Copyright (C) 2014 - 2016 EIS - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/gpl-3.0.html>. - * #L% - */ - - -var scrypt_module_factory = (function (requested_total_memory) { - var Module = {TOTAL_MEMORY: (requested_total_memory || 33554432)}; - var scrypt_raw = Module; -function g(a) { - throw a; -} -var k = void 0, l = !0, m = null, p = !1; -function aa() { - return function() { - } -} -var q, s; -s || (s = eval("(function() { try { return Module || {} } catch(e) { return {} } })()")); -var ba = {}, t; -for(t in s) { - s.hasOwnProperty(t) && (ba[t] = s[t]) -} -var ca = "object" === typeof process && "function" === typeof require, da = "object" === typeof window, ea = "function" === typeof importScripts, fa = !da && !ca && !ea; -if(ca) { - s.print = function(a) { - process.stdout.write(a + "\n") - }; - s.printErr = function(a) { - process.stderr.write(a + "\n") - }; - var ga = require("fs"), ha = require("path"); - s.read = function(a, b) { - var a = ha.normalize(a), c = ga.readFileSync(a); - !c && a != ha.resolve(a) && (a = path.join(__dirname, "..", "src", a), c = ga.readFileSync(a)); - c && !b && (c = c.toString()); - return c - }; - s.readBinary = function(a) { - return s.read(a, l) - }; - s.load = function(a) { - ia(read(a)) - }; - s.arguments = process.argv.slice(2); - module.ee = s -}else { - fa ? (s.print = print, "undefined" != typeof printErr && (s.printErr = printErr), s.read = read, s.readBinary = function(a) { - return read(a, "binary") - }, "undefined" != typeof scriptArgs ? s.arguments = scriptArgs : "undefined" != typeof arguments && (s.arguments = arguments), this.Module = s) : da || ea ? (s.read = function(a) { - var b = new XMLHttpRequest; - b.open("GET", a, p); - b.send(m); - return b.responseText - }, "undefined" != typeof arguments && (s.arguments = arguments), da ? (s.print = function(a) { - console.log(a) - }, s.printErr = function(a) { - console.log(a) - }, this.Module = s) : ea && (s.print = aa(), s.load = importScripts)) : g("Unknown runtime environment. Where are we?") -} -function ia(a) { - eval.call(m, a) -} -"undefined" == !s.load && s.read && (s.load = function(a) { - ia(s.read(a)) -}); -s.print || (s.print = aa()); -s.printErr || (s.printErr = s.print); -s.arguments || (s.arguments = []); -s.print = s.print; -s.P = s.printErr; -s.preRun = []; -s.postRun = []; -for(t in ba) { - ba.hasOwnProperty(t) && (s[t] = ba[t]) -} -function ja() { - return u -} -function ka(a) { - u = a -} -function la(a) { - if(1 == ma) { - return 1 - } - var b = {"%i1":1, "%i8":1, "%i16":2, "%i32":4, "%i64":8, "%float":4, "%double":8}["%" + a]; - b || ("*" == a.charAt(a.length - 1) ? b = ma : "i" == a[0] && (a = parseInt(a.substr(1)), w(0 == a % 8), b = a / 8)); - return b -} -function na(a, b, c) { - c && c.length ? (c.splice || (c = Array.prototype.slice.call(c)), c.splice(0, 0, b), s["dynCall_" + a].apply(m, c)) : s["dynCall_" + a].call(m, b) -} -var oa; -function pa() { - var a = [], b = 0; - this.oa = function(c) { - c &= 255; - b && (a.push(c), b--); - if(0 == a.length) { - if(128 > c) { - return String.fromCharCode(c) - } - a.push(c); - b = 191 < c && 224 > c ? 1 : 2; - return"" - } - if(0 < b) { - return"" - } - var c = a[0], d = a[1], e = a[2], c = 191 < c && 224 > c ? String.fromCharCode((c & 31) << 6 | d & 63) : String.fromCharCode((c & 15) << 12 | (d & 63) << 6 | e & 63); - a.length = 0; - return c - }; - this.yb = function(a) { - for(var a = unescape(encodeURIComponent(a)), b = [], e = 0;e < a.length;e++) { - b.push(a.charCodeAt(e)) - } - return b - } -} -function qa(a) { - var b = u; - u = u + a | 0; - u = u + 7 >> 3 << 3; - return b -} -function ra(a) { - var b = sa; - sa = sa + a | 0; - sa = sa + 7 >> 3 << 3; - return b -} -function ua(a) { - var b = z; - z = z + a | 0; - z = z + 7 >> 3 << 3; - z >= va && wa("Cannot enlarge memory arrays in asm.js. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, or (2) set Module.TOTAL_MEMORY before the program runs."); - return b -} -function xa(a, b) { - return Math.ceil(a / (b ? b : 8)) * (b ? b : 8) -} -var ma = 4, ya = {}, za = p, Aa; -function w(a, b) { - a || wa("Assertion failed: " + b) -} -s.ccall = function(a, b, c, d) { - return Ba(Ca(a), b, c, d) -}; -function Ca(a) { - try { - var b = s["_" + a]; - b || (b = eval("_" + a)) - }catch(c) { - } - w(b, "Cannot call unknown function " + a + " (perhaps LLVM optimizations or closure removed it?)"); - return b -} -function Ba(a, b, c, d) { - function e(a, b) { - if("string" == b) { - if(a === m || a === k || 0 === a) { - return 0 - } - f || (f = ja()); - var c = qa(a.length + 1); - Da(a, c); - return c - } - return"array" == b ? (f || (f = ja()), c = qa(a.length), Ea(a, c), c) : a - } - var f = 0, h = 0, d = d ? d.map(function(a) { - return e(a, c[h++]) - }) : []; - a = a.apply(m, d); - "string" == b ? b = Fa(a) : (w("array" != b), b = a); - f && ka(f); - return b -} -s.cwrap = function(a, b, c) { - var d = Ca(a); - return function() { - return Ba(d, b, c, Array.prototype.slice.call(arguments)) - } -}; -function Ga(a, b, c) { - c = c || "i8"; - "*" === c.charAt(c.length - 1) && (c = "i32"); - switch(c) { - case "i1": - A[a] = b; - break; - case "i8": - A[a] = b; - break; - case "i16": - Ha[a >> 1] = b; - break; - case "i32": - B[a >> 2] = b; - break; - case "i64": - Aa = [b >>> 0, (Math.min(+Math.floor(b / 4294967296), 4294967295) | 0) >>> 0]; - B[a >> 2] = Aa[0]; - B[a + 4 >> 2] = Aa[1]; - break; - case "float": - Ia[a >> 2] = b; - break; - case "double": - Ja[a >> 3] = b; - break; - default: - wa("invalid type for setValue: " + c) - } -} -s.setValue = Ga; -s.getValue = function(a, b) { - b = b || "i8"; - "*" === b.charAt(b.length - 1) && (b = "i32"); - switch(b) { - case "i1": - return A[a]; - case "i8": - return A[a]; - case "i16": - return Ha[a >> 1]; - case "i32": - return B[a >> 2]; - case "i64": - return B[a >> 2]; - case "float": - return Ia[a >> 2]; - case "double": - return Ja[a >> 3]; - default: - wa("invalid type for setValue: " + b) - } - return m -}; -var Ka = 0, La = 1, E = 2, Na = 4; -s.ALLOC_NORMAL = Ka; -s.ALLOC_STACK = La; -s.ALLOC_STATIC = E; -s.ALLOC_DYNAMIC = 3; -s.ALLOC_NONE = Na; -function F(a, b, c, d) { - var e, f; - "number" === typeof a ? (e = l, f = a) : (e = p, f = a.length); - var h = "string" === typeof b ? b : m, c = c == Na ? d : [Oa, qa, ra, ua][c === k ? E : c](Math.max(f, h ? 1 : b.length)); - if(e) { - d = c; - w(0 == (c & 3)); - for(a = c + (f & -4);d < a;d += 4) { - B[d >> 2] = 0 - } - for(a = c + f;d < a;) { - A[d++ | 0] = 0 - } - return c - } - if("i8" === h) { - return a.subarray || a.slice ? G.set(a, c) : G.set(new Uint8Array(a), c), c - } - for(var d = 0, i, j;d < f;) { - var n = a[d]; - "function" === typeof n && (n = ya.fe(n)); - e = h || b[d]; - 0 === e ? d++ : ("i64" == e && (e = "i32"), Ga(c + d, n, e), j !== e && (i = la(e), j = e), d += i) - } - return c -} -s.allocate = F; -function Fa(a, b) { - for(var c = p, d, e = 0;;) { - d = G[a + e | 0]; - if(128 <= d) { - c = l - }else { - if(0 == d && !b) { - break - } - } - e++; - if(b && e == b) { - break - } - } - b || (b = e); - var f = ""; - if(!c) { - for(;0 < b;) { - d = String.fromCharCode.apply(String, G.subarray(a, a + Math.min(b, 1024))), f = f ? f + d : d, a += 1024, b -= 1024 - } - return f - } - c = new pa; - for(e = 0;e < b;e++) { - d = G[a + e | 0], f += c.oa(d) - } - return f -} -s.Pointer_stringify = Fa; -var A, G, Ha, Pa, B, Qa, Ia, Ja, Ra = 0, sa = 0, Sa = 0, u = 0, Ta = 0, Ua = 0, z = 0, va = s.TOTAL_MEMORY || 33554432; -w(!!Int32Array && !!Float64Array && !!(new Int32Array(1)).subarray && !!(new Int32Array(1)).set, "Cannot fallback to non-typed array case: Code is too specialized"); -var I = new ArrayBuffer(va); -A = new Int8Array(I); -Ha = new Int16Array(I); -B = new Int32Array(I); -G = new Uint8Array(I); -Pa = new Uint16Array(I); -Qa = new Uint32Array(I); -Ia = new Float32Array(I); -Ja = new Float64Array(I); -B[0] = 255; -w(255 === G[0] && 0 === G[3], "Typed arrays 2 must be run on a little-endian system"); -s.HEAP = k; -s.HEAP8 = A; -s.HEAP16 = Ha; -s.HEAP32 = B; -s.HEAPU8 = G; -s.HEAPU16 = Pa; -s.HEAPU32 = Qa; -s.HEAPF32 = Ia; -s.HEAPF64 = Ja; -function Va(a) { - for(;0 < a.length;) { - var b = a.shift(); - if("function" == typeof b) { - b() - }else { - var c = b.V; - "number" === typeof c ? b.ha === k ? na("v", c) : na("vi", c, [b.ha]) : c(b.ha === k ? m : b.ha) - } - } -} -var Wa = [], Xa = [], Ya = [], Za = [], $a = [], ab = p; -function bb(a) { - Wa.unshift(a) -} -s.addOnPreRun = s.Vd = bb; -s.addOnInit = s.Sd = function(a) { - Xa.unshift(a) -}; -s.addOnPreMain = s.Ud = function(a) { - Ya.unshift(a) -}; -s.addOnExit = s.Rd = function(a) { - Za.unshift(a) -}; -function cb(a) { - $a.unshift(a) -} -s.addOnPostRun = s.Td = cb; -function J(a, b, c) { - a = (new pa).yb(a); - c && (a.length = c); - b || a.push(0); - return a -} -s.intArrayFromString = J; -s.intArrayToString = function(a) { - for(var b = [], c = 0;c < a.length;c++) { - var d = a[c]; - 255 < d && (d &= 255); - b.push(String.fromCharCode(d)) - } - return b.join("") -}; -function Da(a, b, c) { - a = J(a, c); - for(c = 0;c < a.length;) { - A[b + c | 0] = a[c], c += 1 - } -} -s.writeStringToMemory = Da; -function Ea(a, b) { - for(var c = 0;c < a.length;c++) { - A[b + c | 0] = a[c] - } -} -s.writeArrayToMemory = Ea; -function db(a, b) { - return 0 <= a ? a : 32 >= b ? 2 * Math.abs(1 << b - 1) + a : Math.pow(2, b) + a -} -function eb(a, b) { - if(0 >= a) { - return a - } - var c = 32 >= b ? Math.abs(1 << b - 1) : Math.pow(2, b - 1); - if(a >= c && (32 >= b || a > c)) { - a = -2 * c + a - } - return a -} -Math.imul || (Math.imul = function(a, b) { - var c = a & 65535, d = b & 65535; - return c * d + ((a >>> 16) * d + c * (b >>> 16) << 16) | 0 -}); -Math.ie = Math.imul; -var L = 0, fb = {}, gb = p, hb = m; -function ib(a) { - L++; - s.monitorRunDependencies && s.monitorRunDependencies(L); - a ? (w(!fb[a]), fb[a] = 1) : s.P("warning: run dependency added without ID") -} -s.addRunDependency = ib; -function jb(a) { - L--; - s.monitorRunDependencies && s.monitorRunDependencies(L); - a ? (w(fb[a]), delete fb[a]) : s.P("warning: run dependency removed without ID"); - 0 == L && (hb !== m && (clearInterval(hb), hb = m), !gb && kb && lb()) -} -s.removeRunDependency = jb; -s.preloadedImages = {}; -s.preloadedAudios = {}; -Ra = 8; -sa = Ra + 1312; -Xa.push({V:function() { - mb() -}}); -var nb, ob, pb; -nb = nb = F([0, 0, 0, 0, 0, 0, 0, 0], "i8", E); -ob = ob = F([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "i8", E); -pb = pb = F([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "i8", E); -F([111, 112, 116, 105, 111, 110, 32, 114, 101, 113, 117, 105, 114, 101, 115, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 115, 0, 0, 0, 0, 0, 0, 0, 111, 112, 116, 105, 111, 110, 32, 114, 101, 113, 117, 105, 114, 101, 115, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 64, 0, 0, 0, 0, 0, 0, 89, 64, 0, 0, 0, 0, 0, 136, 195, 64, 0, 0, 0, 0, 132, 215, 151, 65, 0, 128, 224, 55, 121, 195, 65, 67, -23, 110, 5, 181, 181, 184, 147, 70, 245, 249, 63, 233, 3, 79, 56, 77, 50, 29, 48, 249, 72, 119, 130, 90, 60, 191, 115, 127, 221, 79, 21, 117, 56, 3, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 111, 112, 116, 105, 111, 110, 32, 100, 111, 101, 115, 110, 39, 116, 32, 116, 97, 107, 101, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 46, 42, 115, 0, 117, 110, 107, -110, 111, 119, 110, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 115, 0, 0, 0, 0, 117, 110, 107, 110, 111, 119, 110, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 99, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 97, 109, 98, 105, 103, 117, 111, 117, 115, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 46, 42, 115, 0, 0, 0, 0, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 80, 79, 83, 73, 88, 76, 89, 95, 67, 79, 82, 82, 69, 67, 84, 0, 115, 116, 100, 58, 58, 98, 97, 100, 95, 97, 108, -108, 111, 99, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 37, 115, 10, 0, 0, 0, 0, 0, 37, 115, 10, 0, 0, 0, 0, 0, 105, 110, 32, 117, 115, 101, 32, 98, 121, 116, 101, 115, 32, 32, 32, 32, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, 0, 0, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 98, 97, 100, 95, 97, 114, 114, 97, 121, 95, 110, 101, 119, 95, 108, 101, 110, 103, 116, 104, 0, 0, 0, 0, 58, 32, 0, 0, 0, 0, 0, 0, 58, 32, 0, 0, 0, 0, 0, 0, 115, 121, 115, 116, 101, 109, 32, 98, 121, 116, 101, -115, 32, 32, 32, 32, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, 0, 0, 0, 0, 0, 0, 109, 97, 120, 32, 115, 121, 115, 116, 101, 109, 32, 98, 121, 116, 101, 115, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 2, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 2, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 116, 57, 101, 120, 99, 101, 112, 116, 105, 111, 110, 0, 0, 0, 0, 83, 116, 57, 98, 97, -100, 95, 97, 108, 108, 111, 99, 0, 0, 0, 0, 83, 116, 50, 48, 98, 97, 100, 95, 97, 114, 114, 97, 121, 95, 110, 101, 119, 95, 108, 101, 110, 103, 116, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, 2, 0, 0, 0, 0, 0, 0, 120, 2, 0, 0, 168, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 2, 0, 0, 176, 2, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], -"i8", Na, 8); -var qb = xa(F(12, "i8", E), 8); -w(0 == qb % 8); -var rb = 0; -function M(a) { - return B[rb >> 2] = a -} -s._memcpy = sb; -s._memset = tb; -var N = {L:1, ca:2, Bd:3, sc:4, I:5, za:6, Jb:7, Sc:8, $:9, Zb:10, ua:11, Ld:11, $a:12, Ya:13, kc:14, ed:15, Wb:16, va:17, Md:18, wa:19, gd:20, aa:21, A:22, Mc:23, Za:24, ld:25, Id:26, lc:27, ad:28, da:29, yd:30, Fc:31, rd:32, hc:33, ab:34, Wc:35, pc:36, $b:37, vc:38, wc:39, xc:40, Ec:41, Jd:42, Qc:43, uc:44, ec:45, Tc:46, Pb:50, Sb:51, Nd:52, Oc:53, Tb:54, Ub:55, fc:56, Vb:57, cd:60, Rc:61, Fd:62, bd:63, Xc:64, Yc:65, xd:66, Uc:67, Mb:68, Cd:69, ac:70, td:71, Hc:74, yc:75, ic:76, Rb:77, mc:79, md:80, -Qb:81, wd:82, zc:83, Ac:84, Dc:85, Cc:86, Bc:87, dd:88, Nc:89, ya:90, Ic:91, ba:92, nd:95, qd:96, dc:104, Pc:105, Nb:106, vd:107, jd:108, Zc:109, zd:110, cc:111, Kb:112, bc:113, Lc:114, Jc:115, Gd:116, nc:117, oc:118, rc:119, Ob:120, gc:121, Gc:122, ud:123, Ad:124, Lb:125, Kc:126, tc:127, fd:128, Hd:129, sd:130, Kd:131, jc:132, Dd:133, kd:134, Vc:135, $c:136, Yb:137, qc:138, od:139, Xb:140, hd:141, pd:142, Ed:143}, ub = {"0":"Success", 1:"Not super-user", 2:"No such file or directory", 3:"No such process", -4:"Interrupted system call", 5:"I/O error", 6:"No such device or address", 7:"Arg list too long", 8:"Exec format error", 9:"Bad file number", 10:"No children", 11:"No more processes", 12:"Not enough core", 13:"Permission denied", 14:"Bad address", 15:"Block device required", 16:"Mount device busy", 17:"File exists", 18:"Cross-device link", 19:"No such device", 20:"Not a directory", 21:"Is a directory", 22:"Invalid argument", 23:"Too many open files in system", 24:"Too many open files", 25:"Not a typewriter", -26:"Text file busy", 27:"File too large", 28:"No space left on device", 29:"Illegal seek", 30:"Read only file system", 31:"Too many links", 32:"Broken pipe", 33:"Math arg out of domain of func", 34:"Math result not representable", 35:"No message of desired type", 36:"Identifier removed", 37:"Channel number out of range", 38:"Level 2 not synchronized", 39:"Level 3 halted", 40:"Level 3 reset", 41:"Link number out of range", 42:"Protocol driver not attached", 43:"No CSI structure available", 44:"Level 2 halted", -45:"Deadlock condition", 46:"No record locks available", 50:"Invalid exchange", 51:"Invalid request descriptor", 52:"Exchange full", 53:"No anode", 54:"Invalid request code", 55:"Invalid slot", 56:"File locking deadlock error", 57:"Bad font file fmt", 60:"Device not a stream", 61:"No data (for no delay io)", 62:"Timer expired", 63:"Out of streams resources", 64:"Machine is not on the network", 65:"Package not installed", 66:"The object is remote", 67:"The link has been severed", 68:"Advertise error", -69:"Srmount error", 70:"Communication error on send", 71:"Protocol error", 74:"Multihop attempted", 75:"Inode is remote (not really error)", 76:"Cross mount point (not really error)", 77:"Trying to read unreadable message", 79:"Inappropriate file type or format", 80:"Given log. name not unique", 81:"f.d. invalid for this operation", 82:"Remote address changed", 83:"Can\t access a needed shared lib", 84:"Accessing a corrupted shared lib", 85:".lib section in a.out corrupted", 86:"Attempting to link in too many libs", -87:"Attempting to exec a shared library", 88:"Function not implemented", 89:"No more files", 90:"Directory not empty", 91:"File or path name too long", 92:"Too many symbolic links", 95:"Operation not supported on transport endpoint", 96:"Protocol family not supported", 104:"Connection reset by peer", 105:"No buffer space available", 106:"Address family not supported by protocol family", 107:"Protocol wrong type for socket", 108:"Socket operation on non-socket", 109:"Protocol not available", 110:"Can't send after socket shutdown", -111:"Connection refused", 112:"Address already in use", 113:"Connection aborted", 114:"Network is unreachable", 115:"Network interface is not configured", 116:"Connection timed out", 117:"Host is down", 118:"Host is unreachable", 119:"Connection already in progress", 120:"Socket already connected", 121:"Destination address required", 122:"Message too long", 123:"Unknown protocol", 124:"Socket type not supported", 125:"Address not available", 126:"ENETRESET", 127:"Socket is already connected", 128:"Socket is not connected", -129:"TOOMANYREFS", 130:"EPROCLIM", 131:"EUSERS", 132:"EDQUOT", 133:"ESTALE", 134:"Not supported", 135:"No medium (in tape drive)", 136:"No such host or network path", 137:"Filename exists with different case", 138:"EILSEQ", 139:"Value too large for defined data type", 140:"Operation canceled", 141:"State not recoverable", 142:"Previous owner died", 143:"Streams pipe error"}; -function vb(a, b, c) { - var d = O(a, {parent:l}).d, a = "/" === a ? "/" : wb(a)[2], e = xb(d, a); - e && g(new Q(e)); - d.l.Ta || g(new Q(N.L)); - return d.l.Ta(d, a, b, c) -} -function yb(a, b) { - b = b & 4095 | 32768; - return vb(a, b, 0) -} -function zb(a, b) { - b = b & 1023 | 16384; - return vb(a, b, 0) -} -function Ab(a, b, c) { - return vb(a, b | 8192, c) -} -function Bb(a, b) { - var c = O(b, {parent:l}).d, d = "/" === b ? "/" : wb(b)[2], e = xb(c, d); - e && g(new Q(e)); - c.l.Wa || g(new Q(N.L)); - return c.l.Wa(c, d, a) -} -function Cb(a, b) { - var c; - c = "string" === typeof a ? O(a, {N:l}).d : a; - c.l.Y || g(new Q(N.L)); - c.l.Y(c, {mode:b & 4095 | c.mode & -4096, timestamp:Date.now()}) -} -function Db(a, b) { - var c, a = Eb(a), d; - "string" === typeof b ? (d = Fb[b], "undefined" === typeof d && g(Error("Unknown file open mode: " + b))) : d = b; - b = d; - c = b & 512 ? c & 4095 | 32768 : 0; - var e; - try { - var f = O(a, {N:!(b & 65536)}); - e = f.d; - a = f.path - }catch(h) { - } - b & 512 && (e ? b & 2048 && g(new Q(N.va)) : e = vb(a, c, 0)); - e || g(new Q(N.ca)); - 8192 === (e.mode & 61440) && (b &= -1025); - e ? 40960 === (e.mode & 61440) ? c = N.ba : 16384 === (e.mode & 61440) && (0 !== (b & 3) || b & 1024) ? c = N.aa : (c = ["r", "w", "rw"][b & 3], b & 1024 && (c += "w"), c = Gb(e, c)) : c = N.ca; - c && g(new Q(c)); - b & 1024 && (c = e, c = "string" === typeof c ? O(c, {N:l}).d : c, c.l.Y || g(new Q(N.L)), 16384 === (c.mode & 61440) && g(new Q(N.aa)), 32768 !== (c.mode & 61440) && g(new Q(N.A)), (f = Gb(c, "w")) && g(new Q(f)), c.l.Y(c, {size:0, timestamp:Date.now()})); - var i = {path:a, d:e, M:b, seekable:l, position:0, e:e.e, Gb:[], error:p}, j; - a: { - e = k || 4096; - for(c = k || 1;c <= e;c++) { - if(!R[c]) { - j = c; - break a - } - } - g(new Q(N.Za)) - } - i.s = j; - Object.defineProperty(i, "object", {get:function() { - return i.d - }, set:function(a) { - i.d = a - }}); - Object.defineProperty(i, "isRead", {get:function() { - return 1 !== (i.M & 3) - }}); - Object.defineProperty(i, "isWrite", {get:function() { - return 0 !== (i.M & 3) - }}); - Object.defineProperty(i, "isAppend", {get:function() { - return i.M & 8 - }}); - R[j] = i; - i.e.open && i.e.open(i); - return i -} -function Hb(a) { - try { - a.e.close && a.e.close(a) - }catch(b) { - g(b) - }finally { - R[a.s] = m - } -} -function Ib(a, b, c, d, e) { - (0 > d || 0 > e) && g(new Q(N.A)); - 0 === (a.M & 3) && g(new Q(N.$)); - 16384 === (a.d.mode & 61440) && g(new Q(N.aa)); - a.e.write || g(new Q(N.A)); - var f = l; - "undefined" === typeof e ? (e = a.position, f = p) : a.seekable || g(new Q(N.da)); - a.M & 8 && ((!a.seekable || !a.e.na) && g(new Q(N.da)), a.e.na(a, 0, 2)); - b = a.e.write(a, b, c, d, e); - f || (a.position += b); - return b -} -function wb(a) { - return/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(a).slice(1) -} -function Jb(a, b) { - for(var c = 0, d = a.length - 1;0 <= d;d--) { - var e = a[d]; - "." === e ? a.splice(d, 1) : ".." === e ? (a.splice(d, 1), c++) : c && (a.splice(d, 1), c--) - } - if(b) { - for(;c--;c) { - a.unshift("..") - } - } - return a -} -function Eb(a) { - var b = "/" === a.charAt(0), c = "/" === a.substr(-1), a = Jb(a.split("/").filter(function(a) { - return!!a - }), !b).join("/"); - !a && !b && (a = "."); - a && c && (a += "/"); - return(b ? "/" : "") + a -} -function S() { - var a = Array.prototype.slice.call(arguments, 0); - return Eb(a.filter(function(a) { - "string" !== typeof a && g(new TypeError("Arguments to path.join must be strings")); - return a - }).join("/")) -} -function Kb() { - for(var a = "", b = p, c = arguments.length - 1;-1 <= c && !b;c--) { - var d = 0 <= c ? arguments[c] : "/"; - "string" !== typeof d && g(new TypeError("Arguments to path.resolve must be strings")); - d && (a = d + "/" + a, b = "/" === d.charAt(0)) - } - a = Jb(a.split("/").filter(function(a) { - return!!a - }), !b).join("/"); - return(b ? "/" : "") + a || "." -} -var Lb = []; -function Mb(a, b) { - Lb[a] = {input:[], H:[], O:b}; - Nb[a] = {e:Ob} -} -var Ob = {open:function(a) { - Pb || (Pb = new pa); - var b = Lb[a.d.X]; - b || g(new Q(N.wa)); - a.q = b; - a.seekable = p -}, close:function(a) { - a.q.H.length && a.q.O.W(a.q, 10) -}, Q:function(a, b, c, d) { - (!a.q || !a.q.O.Na) && g(new Q(N.za)); - for(var e = 0, f = 0;f < d;f++) { - var h; - try { - h = a.q.O.Na(a.q) - }catch(i) { - g(new Q(N.I)) - } - h === k && 0 === e && g(new Q(N.ua)); - if(h === m || h === k) { - break - } - e++; - b[c + f] = h - } - e && (a.d.timestamp = Date.now()); - return e -}, write:function(a, b, c, d) { - (!a.q || !a.q.O.W) && g(new Q(N.za)); - for(var e = 0;e < d;e++) { - try { - a.q.O.W(a.q, b[c + e]) - }catch(f) { - g(new Q(N.I)) - } - } - d && (a.d.timestamp = Date.now()); - return e -}}, Pb, T = {z:function() { - return T.ka(m, "/", 16895, 0) -}, ka:function(a, b, c, d) { - (24576 === (c & 61440) || 4096 === (c & 61440)) && g(new Q(N.L)); - c = Qb(a, b, c, d); - c.l = T.l; - 16384 === (c.mode & 61440) ? (c.e = T.e, c.g = {}) : 32768 === (c.mode & 61440) ? (c.e = T.e, c.g = []) : 40960 === (c.mode & 61440) ? c.e = T.e : 8192 === (c.mode & 61440) && (c.e = Rb); - c.timestamp = Date.now(); - a && (a.g[b] = c); - return c -}, l:{ge:function(a) { - var b = {}; - b.ce = 8192 === (a.mode & 61440) ? a.id : 1; - b.je = a.id; - b.mode = a.mode; - b.pe = 1; - b.uid = 0; - b.he = 0; - b.X = a.X; - b.size = 16384 === (a.mode & 61440) ? 4096 : 32768 === (a.mode & 61440) ? a.g.length : 40960 === (a.mode & 61440) ? a.link.length : 0; - b.Yd = new Date(a.timestamp); - b.oe = new Date(a.timestamp); - b.ae = new Date(a.timestamp); - b.ib = 4096; - b.Zd = Math.ceil(b.size / b.ib); - return b -}, Y:function(a, b) { - b.mode !== k && (a.mode = b.mode); - b.timestamp !== k && (a.timestamp = b.timestamp); - if(b.size !== k) { - var c = a.g; - if(b.size < c.length) { - c.length = b.size - }else { - for(;b.size > c.length;) { - c.push(0) - } - } - } -}, tb:function() { - g(new Q(N.ca)) -}, Ta:function(a, b, c, d) { - return T.ka(a, b, c, d) -}, rename:function(a, b, c) { - if(16384 === (a.mode & 61440)) { - var d; - try { - d = Sb(b, c) - }catch(e) { - } - if(d) { - for(var f in d.g) { - g(new Q(N.ya)) - } - } - } - delete a.parent.g[a.name]; - a.name = c; - b.g[c] = a -}, ze:function(a, b) { - delete a.g[b] -}, ve:function(a, b) { - var c = Sb(a, b), d; - for(d in c.g) { - g(new Q(N.ya)) - } - delete a.g[b] -}, Wa:function(a, b, c) { - a = T.ka(a, b, 41471, 0); - a.link = c; - return a -}, Va:function(a) { - 40960 !== (a.mode & 61440) && g(new Q(N.A)); - return a.link -}}, e:{open:function(a) { - if(16384 === (a.d.mode & 61440)) { - var b = [".", ".."], c; - for(c in a.d.g) { - a.d.g.hasOwnProperty(c) && b.push(c) - } - a.lb = b - } -}, Q:function(a, b, c, d, e) { - a = a.d.g; - d = Math.min(a.length - e, d); - if(a.subarray) { - b.set(a.subarray(e, e + d), c) - }else { - for(var f = 0;f < d;f++) { - b[c + f] = a[e + f] - } - } - return d -}, write:function(a, b, c, d, e) { - for(var f = a.d.g;f.length < e;) { - f.push(0) - } - for(var h = 0;h < d;h++) { - f[e + h] = b[c + h] - } - a.d.timestamp = Date.now(); - return d -}, na:function(a, b, c) { - 1 === c ? b += a.position : 2 === c && 32768 === (a.d.mode & 61440) && (b += a.d.g.length); - 0 > b && g(new Q(N.A)); - a.Gb = []; - return a.position = b -}, ue:function(a) { - return a.lb -}, Wd:function(a, b, c) { - a = a.d.g; - for(b += c;b > a.length;) { - a.push(0) - } -}, ne:function(a, b, c, d, e, f, h) { - 32768 !== (a.d.mode & 61440) && g(new Q(N.wa)); - a = a.d.g; - if(h & 2) { - if(0 < e || e + d < a.length) { - a = a.subarray ? a.subarray(e, e + d) : Array.prototype.slice.call(a, e, e + d) - } - e = l; - (d = Oa(d)) || g(new Q(N.$a)); - b.set(a, d) - }else { - w(a.buffer === b || a.buffer === b.buffer), e = p, d = a.byteOffset - } - return{te:d, Xd:e} -}}}, Tb = F(1, "i32*", E), Ub = F(1, "i32*", E); -nb = F(1, "i32*", E); -var Vb = m, Nb = [m], R = [m], Wb = 1, Xb = [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ], Yb = l; -function Q(a) { - this.mb = a; - for(var b in N) { - if(N[b] === a) { - this.code = b; - break - } - } - this.message = ub[a] -} -function Zb(a) { - a instanceof Q || g(a + " : " + Error().stack); - M(a.mb) -} -function $b(a, b) { - for(var c = 0, d = 0;d < b.length;d++) { - c = (c << 5) - c + b.charCodeAt(d) | 0 - } - return(a + c) % Xb.length -} -function Sb(a, b) { - var c = Gb(a, "x"); - c && g(new Q(c)); - for(c = Xb[$b(a.id, b)];c;c = c.wb) { - if(c.parent.id === a.id && c.name === b) { - return c - } - } - return a.l.tb(a, b) -} -function Qb(a, b, c, d) { - var e = {id:Wb++, name:b, mode:c, l:{}, e:{}, X:d, parent:m, z:m}; - a || (a = e); - e.parent = a; - e.z = a.z; - Object.defineProperty(e, "read", {get:function() { - return 365 === (e.mode & 365) - }, set:function(a) { - a ? e.mode |= 365 : e.mode &= -366 - }}); - Object.defineProperty(e, "write", {get:function() { - return 146 === (e.mode & 146) - }, set:function(a) { - a ? e.mode |= 146 : e.mode &= -147 - }}); - a = $b(e.parent.id, e.name); - e.wb = Xb[a]; - return Xb[a] = e -} -function O(a, b) { - a = Kb("/", a); - b = b || {pa:0}; - 8 < b.pa && g(new Q(N.ba)); - for(var c = Jb(a.split("/").filter(function(a) { - return!!a - }), p), d = Vb, e = "/", f = 0;f < c.length;f++) { - var h = f === c.length - 1; - if(h && b.parent) { - break - } - d = Sb(d, c[f]); - e = S(e, c[f]); - d.ub && (d = d.z.root); - if(!h || b.N) { - for(h = 0;40960 === (d.mode & 61440);) { - d = O(e, {N:p}).d; - d.l.Va || g(new Q(N.A)); - var d = d.l.Va(d), i = Kb; - var j = wb(e), e = j[0], j = j[1]; - !e && !j ? e = "." : (j && (j = j.substr(0, j.length - 1)), e += j); - e = i(e, d); - d = O(e, {pa:b.pa}).d; - 40 < h++ && g(new Q(N.ba)) - } - } - } - return{path:e, d:d} -} -function ac(a) { - for(var b;;) { - if(a === a.parent) { - return b ? S(a.z.Ua, b) : a.z.Ua - } - b = b ? S(a.name, b) : a.name; - a = a.parent - } -} -var Fb = {r:0, rs:8192, "r+":2, w:1537, wx:3585, xw:3585, "w+":1538, "wx+":3586, "xw+":3586, a:521, ax:2569, xa:2569, "a+":522, "ax+":2570, "xa+":2570}; -function Gb(a, b) { - return Yb ? 0 : -1 !== b.indexOf("r") && !(a.mode & 292) || -1 !== b.indexOf("w") && !(a.mode & 146) || -1 !== b.indexOf("x") && !(a.mode & 73) ? N.Ya : 0 -} -function xb(a, b) { - try { - return Sb(a, b), N.va - }catch(c) { - } - return Gb(a, "wx") -} -var Rb = {open:function(a) { - a.e = Nb[a.d.X].e; - a.e.open && a.e.open(a) -}, na:function() { - g(new Q(N.da)) -}}, bc; -function cc(a, b) { - var c = 0; - a && (c |= 365); - b && (c |= 146); - return c -} -function dc(a, b, c, d, e) { - a = S("string" === typeof a ? a : ac(a), b); - d = cc(d, e); - e = yb(a, d); - if(c) { - if("string" === typeof c) { - for(var b = Array(c.length), f = 0, h = c.length;f < h;++f) { - b[f] = c.charCodeAt(f) - } - c = b - } - Cb(a, d | 146); - b = Db(a, "w"); - Ib(b, c, 0, c.length, 0); - Hb(b); - Cb(a, d) - } - return e -} -function ec(a, b, c, d) { - a = S("string" === typeof a ? a : ac(a), b); - ec.Sa || (ec.Sa = 64); - b = ec.Sa++ << 8 | 0; - Nb[b] = {e:{open:function(a) { - a.seekable = p - }, close:function() { - d && (d.buffer && d.buffer.length) && d(10) - }, Q:function(a, b, d, i) { - for(var j = 0, n = 0;n < i;n++) { - var y; - try { - y = c() - }catch(v) { - g(new Q(N.I)) - } - y === k && 0 === j && g(new Q(N.ua)); - if(y === m || y === k) { - break - } - j++; - b[d + n] = y - } - j && (a.d.timestamp = Date.now()); - return j - }, write:function(a, b, c, i) { - for(var j = 0;j < i;j++) { - try { - d(b[c + j]) - }catch(n) { - g(new Q(N.I)) - } - } - i && (a.d.timestamp = Date.now()); - return j - }}}; - return Ab(a, c && d ? 511 : c ? 219 : 365, b) -} -function fc(a, b, c) { - a = R[a]; - if(!a) { - return-1 - } - a.sender(G.subarray(b, b + c)); - return c -} -function gc(a, b, c) { - var d = R[a]; - if(!d) { - return M(N.$), -1 - } - if(d && "socket" in d) { - return fc(a, b, c) - } - try { - return Ib(d, A, b, c) - }catch(e) { - return Zb(e), -1 - } -} -function hc(a, b, c, d) { - c *= b; - if(0 == c) { - return 0 - } - a = gc(d, a, c); - if(-1 == a) { - if(b = R[d]) { - b.error = l - } - return 0 - } - return Math.floor(a / b) -} -s._strlen = ic; -function jc(a) { - return 0 > a || 0 === a && -Infinity === 1 / a -} -function kc(a, b) { - function c(a) { - var c; - "double" === a ? c = Ja[b + e >> 3] : "i64" == a ? (c = [B[b + e >> 2], B[b + (e + 8) >> 2]], e += 8) : (a = "i32", c = B[b + e >> 2]); - e += Math.max(Math.max(la(a), ma), 8); - return c - } - for(var d = a, e = 0, f = [], h, i;;) { - var j = d; - h = A[d]; - if(0 === h) { - break - } - i = A[d + 1 | 0]; - if(37 == h) { - var n = p, y = p, v = p, C = p; - a:for(;;) { - switch(i) { - case 43: - n = l; - break; - case 45: - y = l; - break; - case 35: - v = l; - break; - case 48: - if(C) { - break a - }else { - C = l; - break - } - ; - default: - break a - } - d++; - i = A[d + 1 | 0] - } - var D = 0; - if(42 == i) { - D = c("i32"), d++, i = A[d + 1 | 0] - }else { - for(;48 <= i && 57 >= i;) { - D = 10 * D + (i - 48), d++, i = A[d + 1 | 0] - } - } - var K = p; - if(46 == i) { - var H = 0, K = l; - d++; - i = A[d + 1 | 0]; - if(42 == i) { - H = c("i32"), d++ - }else { - for(;;) { - i = A[d + 1 | 0]; - if(48 > i || 57 < i) { - break - } - H = 10 * H + (i - 48); - d++ - } - } - i = A[d + 1 | 0] - }else { - H = 6 - } - var x; - switch(String.fromCharCode(i)) { - case "h": - i = A[d + 2 | 0]; - 104 == i ? (d++, x = 1) : x = 2; - break; - case "l": - i = A[d + 2 | 0]; - 108 == i ? (d++, x = 8) : x = 4; - break; - case "L": - ; - case "q": - ; - case "j": - x = 8; - break; - case "z": - ; - case "t": - ; - case "I": - x = 4; - break; - default: - x = m - } - x && d++; - i = A[d + 1 | 0]; - switch(String.fromCharCode(i)) { - case "d": - ; - case "i": - ; - case "u": - ; - case "o": - ; - case "x": - ; - case "X": - ; - case "p": - j = 100 == i || 105 == i; - x = x || 4; - var P = h = c("i" + 8 * x), r; - 8 == x && (h = 117 == i ? +(h[0] >>> 0) + 4294967296 * +(h[1] >>> 0) : +(h[0] >>> 0) + 4294967296 * +(h[1] | 0)); - 4 >= x && (h = (j ? eb : db)(h & Math.pow(256, x) - 1, 8 * x)); - var ta = Math.abs(h), j = ""; - if(100 == i || 105 == i) { - r = 8 == x && lc ? lc.stringify(P[0], P[1], m) : eb(h, 8 * x).toString(10) - }else { - if(117 == i) { - r = 8 == x && lc ? lc.stringify(P[0], P[1], l) : db(h, 8 * x).toString(10), h = Math.abs(h) - }else { - if(111 == i) { - r = (v ? "0" : "") + ta.toString(8) - }else { - if(120 == i || 88 == i) { - j = v && 0 != h ? "0x" : ""; - if(8 == x && lc) { - if(P[1]) { - r = (P[1] >>> 0).toString(16); - for(v = (P[0] >>> 0).toString(16);8 > v.length;) { - v = "0" + v - } - r += v - }else { - r = (P[0] >>> 0).toString(16) - } - }else { - if(0 > h) { - h = -h; - r = (ta - 1).toString(16); - P = []; - for(v = 0;v < r.length;v++) { - P.push((15 - parseInt(r[v], 16)).toString(16)) - } - for(r = P.join("");r.length < 2 * x;) { - r = "f" + r - } - }else { - r = ta.toString(16) - } - } - 88 == i && (j = j.toUpperCase(), r = r.toUpperCase()) - }else { - 112 == i && (0 === ta ? r = "(nil)" : (j = "0x", r = ta.toString(16))) - } - } - } - } - if(K) { - for(;r.length < H;) { - r = "0" + r - } - } - for(n && (j = 0 > h ? "-" + j : "+" + j);j.length + r.length < D;) { - y ? r += " " : C ? r = "0" + r : j = " " + j - } - r = j + r; - r.split("").forEach(function(a) { - f.push(a.charCodeAt(0)) - }); - break; - case "f": - ; - case "F": - ; - case "e": - ; - case "E": - ; - case "g": - ; - case "G": - h = c("double"); - if(isNaN(h)) { - r = "nan", C = p - }else { - if(isFinite(h)) { - K = p; - x = Math.min(H, 20); - if(103 == i || 71 == i) { - K = l, H = H || 1, x = parseInt(h.toExponential(x).split("e")[1], 10), H > x && -4 <= x ? (i = (103 == i ? "f" : "F").charCodeAt(0), H -= x + 1) : (i = (103 == i ? "e" : "E").charCodeAt(0), H--), x = Math.min(H, 20) - } - if(101 == i || 69 == i) { - r = h.toExponential(x), /[eE][-+]\d$/.test(r) && (r = r.slice(0, -1) + "0" + r.slice(-1)) - }else { - if(102 == i || 70 == i) { - r = h.toFixed(x), 0 === h && jc(h) && (r = "-" + r) - } - } - j = r.split("e"); - if(K && !v) { - for(;1 < j[0].length && -1 != j[0].indexOf(".") && ("0" == j[0].slice(-1) || "." == j[0].slice(-1));) { - j[0] = j[0].slice(0, -1) - } - }else { - for(v && -1 == r.indexOf(".") && (j[0] += ".");H > x++;) { - j[0] += "0" - } - } - r = j[0] + (1 < j.length ? "e" + j[1] : ""); - 69 == i && (r = r.toUpperCase()); - n && 0 <= h && (r = "+" + r) - }else { - r = (0 > h ? "-" : "") + "inf", C = p - } - } - for(;r.length < D;) { - r = y ? r + " " : C && ("-" == r[0] || "+" == r[0]) ? r[0] + "0" + r.slice(1) : (C ? "0" : " ") + r - } - 97 > i && (r = r.toUpperCase()); - r.split("").forEach(function(a) { - f.push(a.charCodeAt(0)) - }); - break; - case "s": - C = (n = c("i8*")) ? ic(n) : 6; - K && (C = Math.min(C, H)); - if(!y) { - for(;C < D--;) { - f.push(32) - } - } - if(n) { - for(v = 0;v < C;v++) { - f.push(G[n++ | 0]) - } - }else { - f = f.concat(J("(null)".substr(0, C), l)) - } - if(y) { - for(;C < D--;) { - f.push(32) - } - } - break; - case "c": - for(y && f.push(c("i8"));0 < --D;) { - f.push(32) - } - y || f.push(c("i8")); - break; - case "n": - y = c("i32*"); - B[y >> 2] = f.length; - break; - case "%": - f.push(h); - break; - default: - for(v = j;v < d + 2;v++) { - f.push(A[v]) - } - } - d += 2 - }else { - f.push(h), d += 1 - } - } - return f -} -function mc(a, b, c) { - c = kc(b, c); - b = ja(); - a = hc(F(c, "i8", La), 1, c.length, a); - ka(b); - return a -} -function nc(a) { - nc.ia || (z = z + 4095 >> 12 << 12, nc.ia = l, w(ua), nc.hb = ua, ua = function() { - wa("cannot dynamically allocate, sbrk now has control") - }); - var b = z; - 0 != a && nc.hb(a); - return b -} -function U() { - return B[U.m >> 2] -} -function oc() { - return!!oc.ta -} -function pc(a) { - var b = p; - try { - a == __ZTIi && (b = l) - }catch(c) { - } - try { - a == __ZTIj && (b = l) - }catch(d) { - } - try { - a == __ZTIl && (b = l) - }catch(e) { - } - try { - a == __ZTIm && (b = l) - }catch(f) { - } - try { - a == __ZTIx && (b = l) - }catch(h) { - } - try { - a == __ZTIy && (b = l) - }catch(i) { - } - try { - a == __ZTIf && (b = l) - }catch(j) { - } - try { - a == __ZTId && (b = l) - }catch(n) { - } - try { - a == __ZTIe && (b = l) - }catch(y) { - } - try { - a == __ZTIc && (b = l) - }catch(v) { - } - try { - a == __ZTIa && (b = l) - }catch(C) { - } - try { - a == __ZTIh && (b = l) - }catch(D) { - } - try { - a == __ZTIs && (b = l) - }catch(K) { - } - try { - a == __ZTIt && (b = l) - }catch(H) { - } - return b -} -function qc(a, b, c) { - if(0 == c) { - return p - } - if(0 == b || b == a) { - return l - } - switch(pc(b) ? b : B[B[b >> 2] - 8 >> 2]) { - case 0: - return 0 == B[B[a >> 2] - 8 >> 2] ? qc(B[a + 8 >> 2], B[b + 8 >> 2], c) : p; - case 1: - return p; - case 2: - return qc(a, B[b + 8 >> 2], c); - default: - return p - } -} -function rc(a, b, c) { - if(!rc.sb) { - try { - B[__ZTVN10__cxxabiv119__pointer_type_infoE >> 2] = 0 - }catch(d) { - } - try { - B[pb >> 2] = 1 - }catch(e) { - } - try { - B[ob >> 2] = 2 - }catch(f) { - } - rc.sb = l - } - B[U.m >> 2] = a; - B[U.m + 4 >> 2] = b; - B[U.m + 8 >> 2] = c; - "uncaught_exception" in oc ? oc.ta++ : oc.ta = 1; - g(a + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.") -} -function sc(a) { - try { - return tc(a) - }catch(b) { - } -} -function uc() { - if(uc.Bb) { - uc.Bb = p - }else { - V.setThrew(0); - B[U.m + 4 >> 2] = 0; - var a = B[U.m >> 2], b = B[U.m + 8 >> 2]; - b && (na("vi", b, [a]), B[U.m + 8 >> 2] = 0); - a && (sc(a), B[U.m >> 2] = 0) - } -} -var vc = F(1, "i32*", E); -function wc(a) { - var b, c; - wc.ia ? (c = B[vc >> 2], b = B[c >> 2]) : (wc.ia = l, W.USER = "root", W.PATH = "/", W.PWD = "/", W.HOME = "/home/emscripten", W.LANG = "en_US.UTF-8", W._ = "./this.program", b = F(1024, "i8", E), c = F(256, "i8*", E), B[c >> 2] = b, B[vc >> 2] = c); - var d = [], e = 0, f; - for(f in a) { - if("string" === typeof a[f]) { - var h = f + "=" + a[f]; - d.push(h); - e += h.length - } - } - 1024 < e && g(Error("Environment size exceeded TOTAL_ENV_SIZE!")); - for(a = 0;a < d.length;a++) { - h = d[a]; - for(e = 0;e < h.length;e++) { - A[b + e | 0] = h.charCodeAt(e) - } - A[b + e | 0] = 0; - B[c + 4 * a >> 2] = b; - b += h.length + 1 - } - B[c + 4 * d.length >> 2] = 0 -} -var W = {}; -function xc(a) { - if(0 === a) { - return 0 - } - a = Fa(a); - if(!W.hasOwnProperty(a)) { - return 0 - } - xc.J && tc(xc.J); - xc.J = F(J(W[a]), "i8", Ka); - return xc.J -} -function yc(a, b, c) { - if(a in ub) { - if(ub[a].length > c - 1) { - return M(N.ab) - } - a = ub[a]; - for(c = 0;c < a.length;c++) { - A[b + c | 0] = a.charCodeAt(c) - } - return A[b + c | 0] = 0 - } - return M(N.A) -} -function zc(a) { - zc.buffer || (zc.buffer = Oa(256)); - yc(a, zc.buffer, 256); - return zc.buffer -} -function Ac(a) { - s.exit(a) -} -function Bc(a, b) { - var c = db(a & 255); - A[Bc.J | 0] = c; - if(-1 == gc(b, Bc.J, 1)) { - if(c = R[b]) { - c.error = l - } - return-1 - } - return c -} -var Cc = p, Dc = p, Ec = p, Fc = p, Gc = k, Hc = k; -function Ic(a) { - return{jpg:"image/jpeg", jpeg:"image/jpeg", png:"image/png", bmp:"image/bmp", ogg:"audio/ogg", wav:"audio/wav", mp3:"audio/mpeg"}[a.substr(a.lastIndexOf(".") + 1)] -} -var Jc = []; -function Kc() { - var a = s.canvas; - Jc.forEach(function(b) { - b(a.width, a.height) - }) -} -function Lc() { - var a = s.canvas; - this.Ib = a.width; - this.Hb = a.height; - a.width = screen.width; - a.height = screen.height; - "undefined" != typeof SDL && (a = Qa[SDL.screen + 0 * ma >> 2], B[SDL.screen + 0 * ma >> 2] = a | 8388608); - Kc() -} -function Mc() { - var a = s.canvas; - a.width = this.Ib; - a.height = this.Hb; - "undefined" != typeof SDL && (a = Qa[SDL.screen + 0 * ma >> 2], B[SDL.screen + 0 * ma >> 2] = a & -8388609); - Kc() -} -var Nc, Oc, Pc, Qc, rb = ra(4); -B[rb >> 2] = 0; -var Vb = Qb(m, "/", 16895, 0), Rc = T, Sc = {type:Rc, se:{}, Ua:"/", root:m}, Tc; -Tc = O("/", {N:p}); -var Uc = Rc.z(Sc); -Uc.z = Sc; -Sc.root = Uc; -Tc && (Tc.d.z = Sc, Tc.d.ub = l, Vb = Sc.root); -zb("/tmp", 511); -zb("/dev", 511); -Nb[259] = {e:{Q:function() { - return 0 -}, write:function() { - return 0 -}}}; -Ab("/dev/null", 438, 259); -Mb(1280, {Na:function(a) { - if(!a.input.length) { - var b = m; - if(ca) { - if(process.Eb.be) { - return - } - b = process.Eb.Q() - }else { - "undefined" != typeof window && "function" == typeof window.prompt ? (b = window.prompt("Input: "), b !== m && (b += "\n")) : "function" == typeof readline && (b = readline(), b !== m && (b += "\n")) - } - if(!b) { - return m - } - a.input = J(b, l) - } - return a.input.shift() -}, W:function(a, b) { - b === m || 10 === b ? (s.print(a.H.join("")), a.H = []) : a.H.push(Pb.oa(b)) -}}); -Mb(1536, {W:function(a, b) { - b === m || 10 === b ? (s.printErr(a.H.join("")), a.H = []) : a.H.push(Pb.oa(b)) -}}); -Ab("/dev/tty", 438, 1280); -Ab("/dev/tty1", 438, 1536); -zb("/dev/shm", 511); -zb("/dev/shm/tmp", 511); -Xa.unshift({V:function() { - if(!s.noFSInit && !bc) { - w(!bc, "FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)"); - bc = l; - s.stdin = s.stdin; - s.stdout = s.stdout; - s.stderr = s.stderr; - s.stdin ? ec("/dev", "stdin", s.stdin) : Bb("/dev/tty", "/dev/stdin"); - s.stdout ? ec("/dev", "stdout", m, s.stdout) : Bb("/dev/tty", "/dev/stdout"); - s.stderr ? ec("/dev", "stderr", m, s.stderr) : Bb("/dev/tty1", "/dev/stderr"); - var a = Db("/dev/stdin", "r"); - B[Tb >> 2] = a.s; - w(1 === a.s, "invalid handle for stdin (" + a.s + ")"); - a = Db("/dev/stdout", "w"); - B[Ub >> 2] = a.s; - w(2 === a.s, "invalid handle for stdout (" + a.s + ")"); - a = Db("/dev/stderr", "w"); - B[nb >> 2] = a.s; - w(3 === a.s, "invalid handle for stderr (" + a.s + ")") - } -}}); -Ya.push({V:function() { - Yb = p -}}); -Za.push({V:function() { - bc = p; - for(var a = 0;a < R.length;a++) { - var b = R[a]; - b && Hb(b) - } -}}); -s.FS_createFolder = function(a, b, c, d) { - a = S("string" === typeof a ? a : ac(a), b); - return zb(a, cc(c, d)) -}; -s.FS_createPath = function(a, b) { - for(var a = "string" === typeof a ? a : ac(a), c = b.split("/").reverse();c.length;) { - var d = c.pop(); - if(d) { - var e = S(a, d); - try { - zb(e, 511) - }catch(f) { - } - a = e - } - } - return e -}; -s.FS_createDataFile = dc; -s.FS_createPreloadedFile = function(a, b, c, d, e, f, h, i) { - function j() { - Ec = document.pointerLockElement === v || document.mozPointerLockElement === v || document.webkitPointerLockElement === v - } - function n(c) { - function j(c) { - i || dc(a, b, c, d, e); - f && f(); - jb("cp " + C) - } - var n = p; - s.preloadPlugins.forEach(function(a) { - !n && a.canHandle(C) && (a.handle(c, C, j, function() { - h && h(); - jb("cp " + C) - }), n = l) - }); - n || j(c) - } - s.preloadPlugins || (s.preloadPlugins = []); - if(!Nc && !ea) { - Nc = l; - try { - new Blob, Oc = l - }catch(y) { - Oc = p, console.log("warning: no blob constructor, cannot create blobs with mimetypes") - } - Pc = "undefined" != typeof MozBlobBuilder ? MozBlobBuilder : "undefined" != typeof WebKitBlobBuilder ? WebKitBlobBuilder : !Oc ? console.log("warning: no BlobBuilder") : m; - Qc = "undefined" != typeof window ? window.URL ? window.URL : window.webkitURL : console.log("warning: cannot create object URLs"); - s.preloadPlugins.push({canHandle:function(a) { - return!s.re && /\.(jpg|jpeg|png|bmp)$/i.test(a) - }, handle:function(a, b, c, d) { - var e = m; - if(Oc) { - try { - e = new Blob([a], {type:Ic(b)}), e.size !== a.length && (e = new Blob([(new Uint8Array(a)).buffer], {type:Ic(b)})) - }catch(f) { - var h = "Blob constructor present but fails: " + f + "; falling back to blob builder"; - oa || (oa = {}); - oa[h] || (oa[h] = 1, s.P(h)) - } - } - e || (e = new Pc, e.append((new Uint8Array(a)).buffer), e = e.getBlob()); - var i = Qc.createObjectURL(e), j = new Image; - j.onload = function() { - w(j.complete, "Image " + b + " could not be decoded"); - var d = document.createElement("canvas"); - d.width = j.width; - d.height = j.height; - d.getContext("2d").drawImage(j, 0, 0); - s.preloadedImages[b] = d; - Qc.revokeObjectURL(i); - c && c(a) - }; - j.onerror = function() { - console.log("Image " + i + " could not be decoded"); - d && d() - }; - j.src = i - }}); - s.preloadPlugins.push({canHandle:function(a) { - return!s.qe && a.substr(-4) in {".ogg":1, ".wav":1, ".mp3":1} - }, handle:function(a, b, c, d) { - function e(d) { - h || (h = l, s.preloadedAudios[b] = d, c && c(a)) - } - function f() { - h || (h = l, s.preloadedAudios[b] = new Audio, d && d()) - } - var h = p; - if(Oc) { - try { - var i = new Blob([a], {type:Ic(b)}) - }catch(j) { - return f() - } - var i = Qc.createObjectURL(i), n = new Audio; - n.addEventListener("canplaythrough", function() { - e(n) - }, p); - n.onerror = function() { - if(!h) { - console.log("warning: browser could not fully decode audio " + b + ", trying slower base64 approach"); - for(var c = "", d = 0, f = 0, i = 0;i < a.length;i++) { - d = d << 8 | a[i]; - for(f += 8;6 <= f;) { - var j = d >> f - 6 & 63, f = f - 6, c = c + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[j] - } - } - 2 == f ? (c += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(d & 3) << 4], c += "==") : 4 == f && (c += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(d & 15) << 2], c += "="); - n.src = "data:audio/x-" + b.substr(-3) + ";base64," + c; - e(n) - } - }; - n.src = i; - setTimeout(function() { - za || e(n) - }, 1E4) - }else { - return f() - } - }}); - var v = s.canvas; - v.qa = v.requestPointerLock || v.mozRequestPointerLock || v.webkitRequestPointerLock; - v.La = document.exitPointerLock || document.mozExitPointerLock || document.webkitExitPointerLock || aa(); - v.La = v.La.bind(document); - document.addEventListener("pointerlockchange", j, p); - document.addEventListener("mozpointerlockchange", j, p); - document.addEventListener("webkitpointerlockchange", j, p); - s.elementPointerLock && v.addEventListener("click", function(a) { - !Ec && v.qa && (v.qa(), a.preventDefault()) - }, p) - } - var C, D = S.apply(m, [a, b]); - "/" == D[0] && (D = D.substr(1)); - C = D; - ib("cp " + C); - if("string" == typeof c) { - var K = h, H = function() { - K ? K() : g('Loading data file "' + c + '" failed.') - }, x = new XMLHttpRequest; - x.open("GET", c, l); - x.responseType = "arraybuffer"; - x.onload = function() { - if(200 == x.status || 0 == x.status && x.response) { - var a = x.response; - w(a, 'Loading data file "' + c + '" failed (no arrayBuffer).'); - a = new Uint8Array(a); - n(a); - jb("al " + c) - }else { - H() - } - }; - x.onerror = H; - x.send(m); - ib("al " + c) - }else { - n(c) - } -}; -s.FS_createLazyFile = function(a, b, c, d, e) { - var f, h; - "undefined" !== typeof XMLHttpRequest ? (ea || g("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc"), f = function() { - this.ma = p; - this.T = [] - }, f.prototype.get = function(a) { - if(!(a > this.length - 1 || 0 > a)) { - var b = a % this.S; - return this.pb(Math.floor(a / this.S))[b] - } - }, f.prototype.Cb = function(a) { - this.pb = a - }, f.prototype.Fa = function() { - var a = new XMLHttpRequest; - a.open("HEAD", c, p); - a.send(m); - 200 <= a.status && 300 > a.status || 304 === a.status || g(Error("Couldn't load " + c + ". Status: " + a.status)); - var b = Number(a.getResponseHeader("Content-length")), d, e = 1048576; - if(!((d = a.getResponseHeader("Accept-Ranges")) && "bytes" === d)) { - e = b - } - var f = this; - f.Cb(function(a) { - var d = a * e, h = (a + 1) * e - 1, h = Math.min(h, b - 1); - if("undefined" === typeof f.T[a]) { - var i = f.T; - d > h && g(Error("invalid range (" + d + ", " + h + ") or no bytes requested!")); - h > b - 1 && g(Error("only " + b + " bytes available! programmer error!")); - var j = new XMLHttpRequest; - j.open("GET", c, p); - b !== e && j.setRequestHeader("Range", "bytes=" + d + "-" + h); - "undefined" != typeof Uint8Array && (j.responseType = "arraybuffer"); - j.overrideMimeType && j.overrideMimeType("text/plain; charset=x-user-defined"); - j.send(m); - 200 <= j.status && 300 > j.status || 304 === j.status || g(Error("Couldn't load " + c + ". Status: " + j.status)); - d = j.response !== k ? new Uint8Array(j.response || []) : J(j.responseText || "", l); - i[a] = d - } - "undefined" === typeof f.T[a] && g(Error("doXHR failed!")); - return f.T[a] - }); - this.gb = b; - this.fb = e; - this.ma = l - }, f = new f, Object.defineProperty(f, "length", {get:function() { - this.ma || this.Fa(); - return this.gb - }}), Object.defineProperty(f, "chunkSize", {get:function() { - this.ma || this.Fa(); - return this.fb - }}), h = k) : (h = c, f = k); - var i, a = S("string" === typeof a ? a : ac(a), b); - i = yb(a, cc(d, e)); - f ? i.g = f : h && (i.g = m, i.url = h); - var j = {}; - Object.keys(i.e).forEach(function(a) { - var b = i.e[a]; - j[a] = function() { - var a; - if(i.ke || i.le || i.link || i.g) { - a = l - }else { - a = l; - "undefined" !== typeof XMLHttpRequest && g(Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.")); - if(s.read) { - try { - i.g = J(s.read(i.url), l) - }catch(c) { - a = p - } - }else { - g(Error("Cannot load without read() or XMLHttpRequest.")) - } - a || M(N.I) - } - a || g(new Q(N.I)); - return b.apply(m, arguments) - } - }); - j.Q = function(a, b, c, d, e) { - a = a.d.g; - d = Math.min(a.length - e, d); - if(a.slice) { - for(var f = 0;f < d;f++) { - b[c + f] = a[e + f] - } - }else { - for(f = 0;f < d;f++) { - b[c + f] = a.get(e + f) - } - } - return d - }; - i.e = j; - return i -}; -s.FS_createLink = function(a, b, c) { - a = S("string" === typeof a ? a : ac(a), b); - return Bb(c, a) -}; -s.FS_createDevice = ec; -U.m = F(12, "void*", E); -wc(W); -Bc.J = F([0], "i8", E); -s.requestFullScreen = function(a, b) { - function c() { - Dc = p; - (document.webkitFullScreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.mozFullscreenElement || document.fullScreenElement || document.fullscreenElement) === d ? (d.Ga = document.cancelFullScreen || document.mozCancelFullScreen || document.webkitCancelFullScreen, d.Ga = d.Ga.bind(document), Gc && d.qa(), Dc = l, Hc && Lc()) : Hc && Mc(); - if(s.onFullScreen) { - s.onFullScreen(Dc) - } - } - Gc = a; - Hc = b; - "undefined" === typeof Gc && (Gc = l); - "undefined" === typeof Hc && (Hc = p); - var d = s.canvas; - Fc || (Fc = l, document.addEventListener("fullscreenchange", c, p), document.addEventListener("mozfullscreenchange", c, p), document.addEventListener("webkitfullscreenchange", c, p)); - d.Ab = d.requestFullScreen || d.mozRequestFullScreen || (d.webkitRequestFullScreen ? function() { - d.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT) - } : m); - d.Ab() -}; -s.requestAnimationFrame = function(a) { - window.requestAnimationFrame || (window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame || window.setTimeout); - window.requestAnimationFrame(a) -}; -s.pauseMainLoop = aa(); -s.resumeMainLoop = function() { - Cc && (Cc = p, m()) -}; -s.getUserMedia = function() { - window.Ma || (window.Ma = navigator.getUserMedia || navigator.mozGetUserMedia); - window.Ma(k) -}; -Sa = u = xa(sa); -Ta = Sa + 5242880; -Ua = z = xa(Ta); -w(Ua < va); -var Vc = F([8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "i8", 3), Wc = F([8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, -2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, -0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0], "i8", 3), Xc = Math.min; -var V = (function(global,env,buffer) { -// EMSCRIPTEN_START_ASM - "use asm"; - var a = new global.Int8Array(buffer); - var b = new global.Int16Array(buffer); - var c = new global.Int32Array(buffer); - var d = new global.Uint8Array(buffer); - var e = new global.Uint16Array(buffer); - var f = new global.Uint32Array(buffer); - var g = new global.Float32Array(buffer); - var h = new global.Float64Array(buffer); - var i = env.STACKTOP | 0; - var j = env.STACK_MAX | 0; - var k = env.tempDoublePtr | 0; - var l = env.ABORT | 0; - var m = env.cttz_i8 | 0; - var n = env.ctlz_i8 | 0; - var o = env._stderr | 0; - var p = env.__ZTVN10__cxxabiv120__si_class_type_infoE | 0; - var q = env.__ZTVN10__cxxabiv117__class_type_infoE | 0; - var r = env.___progname | 0; - var s = +env.NaN; - var t = +env.Infinity; - var u = 0; - var v = 0; - var w = 0; - var x = 0; - var y = 0, z = 0, A = 0, B = 0, C = 0.0, D = 0, E = 0, F = 0, G = 0.0; - var H = 0; - var I = 0; - var J = 0; - var K = 0; - var L = 0; - var M = 0; - var N = 0; - var O = 0; - var P = 0; - var Q = 0; - var R = global.Math.floor; - var S = global.Math.abs; - var T = global.Math.sqrt; - var U = global.Math.pow; - var V = global.Math.cos; - var W = global.Math.sin; - var X = global.Math.tan; - var Y = global.Math.acos; - var Z = global.Math.asin; - var _ = global.Math.atan; - var $ = global.Math.atan2; - var aa = global.Math.exp; - var ab = global.Math.log; - var ac = global.Math.ceil; - var ad = global.Math.imul; - var ae = env.abort; - var af = env.assert; - var ag = env.asmPrintInt; - var ah = env.asmPrintFloat; - var ai = env.min; - var aj = env.invoke_vi; - var ak = env.invoke_vii; - var al = env.invoke_ii; - var am = env.invoke_viii; - var an = env.invoke_v; - var ao = env.invoke_iii; - var ap = env._strncmp; - var aq = env._llvm_va_end; - var ar = env._sysconf; - var as = env.___cxa_throw; - var at = env._strerror; - var au = env._abort; - var av = env._fprintf; - var aw = env._llvm_eh_exception; - var ax = env.___cxa_free_exception; - var ay = env._fflush; - var az = env.___buildEnvironment; - var aA = env.__reallyNegative; - var aB = env._strchr; - var aC = env._fputc; - var aD = env.___setErrNo; - var aE = env._fwrite; - var aF = env._send; - var aG = env._write; - var aH = env._exit; - var aI = env.___cxa_find_matching_catch; - var aJ = env.___cxa_allocate_exception; - var aK = env._isspace; - var aL = env.__formatString; - var aM = env.___resumeException; - var aN = env._llvm_uadd_with_overflow_i32; - var aO = env.___cxa_does_inherit; - var aP = env._getenv; - var aQ = env._vfprintf; - var aR = env.___cxa_begin_catch; - var aS = env.__ZSt18uncaught_exceptionv; - var aT = env._pwrite; - var aU = env.___cxa_call_unexpected; - var aV = env._sbrk; - var aW = env._strerror_r; - var aX = env.___errno_location; - var aY = env.___gxx_personality_v0; - var aZ = env.___cxa_is_number_type; - var a_ = env._time; - var a$ = env.__exit; - var a0 = env.___cxa_end_catch; -// EMSCRIPTEN_START_FUNCS -function a7(a) { - a = a | 0; - var b = 0; - b = i; - i = i + a | 0; - i = i + 7 >> 3 << 3; - return b | 0; -} -function a8() { - return i | 0; -} -function a9(a) { - a = a | 0; - i = a; -} -function ba(a, b) { - a = a | 0; - b = b | 0; - if ((u | 0) == 0) { - u = a; - v = b; - } -} -function bb(b) { - b = b | 0; - a[k] = a[b]; - a[k + 1 | 0] = a[b + 1 | 0]; - a[k + 2 | 0] = a[b + 2 | 0]; - a[k + 3 | 0] = a[b + 3 | 0]; -} -function bc(b) { - b = b | 0; - a[k] = a[b]; - a[k + 1 | 0] = a[b + 1 | 0]; - a[k + 2 | 0] = a[b + 2 | 0]; - a[k + 3 | 0] = a[b + 3 | 0]; - a[k + 4 | 0] = a[b + 4 | 0]; - a[k + 5 | 0] = a[b + 5 | 0]; - a[k + 6 | 0] = a[b + 6 | 0]; - a[k + 7 | 0] = a[b + 7 | 0]; -} -function bd(a) { - a = a | 0; - H = a; -} -function be(a) { - a = a | 0; - I = a; -} -function bf(a) { - a = a | 0; - J = a; -} -function bg(a) { - a = a | 0; - K = a; -} -function bh(a) { - a = a | 0; - L = a; -} -function bi(a) { - a = a | 0; - M = a; -} -function bj(a) { - a = a | 0; - N = a; -} -function bk(a) { - a = a | 0; - O = a; -} -function bl(a) { - a = a | 0; - P = a; -} -function bm(a) { - a = a | 0; - Q = a; -} -function bn() { - c[170] = q + 8; - c[172] = p + 8; - c[176] = p + 8; -} -function bo(b, c, d) { - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0; - if ((d | 0) == 0) { - return; - } else { - e = 0; - } - do { - a[b + e | 0] = a[c + e | 0] | 0; - e = e + 1 | 0; - } while (e >>> 0 < d >>> 0); - return; -} -function bp(b, c, d) { - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0, f = 0; - if ((d | 0) == 0) { - return; - } else { - e = 0; - } - do { - f = b + e | 0; - a[f] = a[f] ^ a[c + e | 0]; - e = e + 1 | 0; - } while (e >>> 0 < d >>> 0); - return; -} -function bq(a) { - a = a | 0; - var b = 0, c = 0, e = 0, f = 0; - b = d[a + 1 | 0] | 0; - c = d[a + 2 | 0] | 0; - e = d[a + 3 | 0] | 0; - f = cN(b << 8 | 0 >>> 24 | (d[a] | 0) | (c << 16 | 0 >>> 16) | (e << 24 | 0 >>> 8) | (0 << 8 | 0 >>> 24), 0 << 8 | b >>> 24 | (0 << 16 | c >>> 16) | (0 << 24 | e >>> 8) | (d[a + 4 | 0] | 0) | ((d[a + 5 | 0] | 0) << 8 | 0 >>> 24), 0 << 16 | 0 >>> 16, (d[a + 6 | 0] | 0) << 16 | 0 >>> 16) | 0; - e = cN(f, H, 0 << 24 | 0 >>> 8, (d[a + 7 | 0] | 0) << 24 | 0 >>> 8) | 0; - return (H = H, e) | 0; -} -function br(a) { - a = a | 0; - return (d[a + 1 | 0] | 0) << 8 | (d[a] | 0) | (d[a + 2 | 0] | 0) << 16 | (d[a + 3 | 0] | 0) << 24 | 0; -} -function bs(b, c) { - b = b | 0; - c = c | 0; - a[b] = c & 255; - a[b + 1 | 0] = c >>> 8 & 255; - a[b + 2 | 0] = c >>> 16 & 255; - a[b + 3 | 0] = c >>> 24 & 255; - return; -} -function bt(a) { - a = a | 0; - c[a + 36 >> 2] = 0; - c[a + 32 >> 2] = 0; - c[a >> 2] = 1779033703; - c[a + 4 >> 2] = -1150833019; - c[a + 8 >> 2] = 1013904242; - c[a + 12 >> 2] = -1521486534; - c[a + 16 >> 2] = 1359893119; - c[a + 20 >> 2] = -1694144372; - c[a + 24 >> 2] = 528734635; - c[a + 28 >> 2] = 1541459225; - return; -} -function bu(a, b, d, e, f, g, h, i, j, k) { - a = a | 0; - b = b | 0; - d = d | 0; - e = e | 0; - f = f | 0; - g = g | 0; - h = h | 0; - i = i | 0; - j = j | 0; - k = k | 0; - var l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0; - l = cX(i, 0, h, 0) | 0; - m = H; - n = 0; - if (m >>> 0 > n >>> 0 | m >>> 0 == n >>> 0 & l >>> 0 > 1073741823 >>> 0) { - c[(aX() | 0) >> 2] = 27; - o = -1; - return o | 0; - } - l = cN(f, g, -1, -1) | 0; - if ((l & f | 0) != 0 | (H & g | 0) != 0 | (f | 0) == 0 & (g | 0) == 0) { - c[(aX() | 0) >> 2] = 22; - o = -1; - return o | 0; - } - do { - if (!((33554431 / (i >>> 0) | 0) >>> 0 < h >>> 0 | h >>> 0 > 16777215)) { - l = 0; - if (l >>> 0 < g >>> 0 | l >>> 0 == g >>> 0 & (33554431 / (h >>> 0) | 0) >>> 0 < f >>> 0) { - break; - } - l = h << 7; - n = bL(ad(l, i) | 0) | 0; - if ((n | 0) == 0) { - o = -1; - return o | 0; - } - m = bL(h << 8) | 0; - do { - if ((m | 0) != 0) { - p = cX(l, 0, f, g) | 0; - q = bL(p) | 0; - if ((q | 0) == 0) { - bM(m); - break; - } - p = ad(i << 7, h) | 0; - bJ(a, b, d, e, 1, 0, n, p); - if ((i | 0) != 0) { - r = h << 7; - s = 0; - do { - bv(n + (ad(r, s) | 0) | 0, h, f, g, q, m); - s = s + 1 | 0; - } while (s >>> 0 < i >>> 0); - } - bJ(a, b, n, p, 1, 0, j, k); - bM(q); - bM(m); - bM(n); - o = 0; - return o | 0; - } - } while (0); - bM(n); - o = -1; - return o | 0; - } - } while (0); - c[(aX() | 0) >> 2] = 12; - o = -1; - return o | 0; -} -function bv(a, b, c, d, e, f) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - e = e | 0; - f = f | 0; - var g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0; - g = b << 7; - h = f + g | 0; - bo(f, a, g); - if ((c | 0) == 0 & (d | 0) == 0) { - bo(a, f, g); - return; - } - i = g; - j = 0; - k = 0; - l = 0; - do { - m = cX(l, k, i, j) | 0; - bo(e + m | 0, f, g); - bw(f, h, b); - l = cN(l, k, 1, 0) | 0; - k = H; - } while (k >>> 0 < d >>> 0 | k >>> 0 == d >>> 0 & l >>> 0 < c >>> 0); - if ((c | 0) == 0 & (d | 0) == 0) { - bo(a, f, g); - return; - } - l = cN(c, d, -1, -1) | 0; - k = H; - j = g; - i = 0; - m = 0; - n = 0; - do { - o = bx(f, b) | 0; - p = cX(o & l, H & k, j, i) | 0; - bp(f, e + p | 0, g); - bw(f, h, b); - n = cN(n, m, 1, 0) | 0; - m = H; - } while (m >>> 0 < d >>> 0 | m >>> 0 == d >>> 0 & n >>> 0 < c >>> 0); - bo(a, f, g); - return; -} -function bw(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, j = 0, k = 0; - d = i; - i = i + 64 | 0; - e = d | 0; - f = c << 1; - bo(e, a + ((c << 7) - 64) | 0, 64); - if ((f | 0) != 0) { - g = 0; - do { - h = g << 6; - bp(e, a + h | 0, 64); - by(e); - bo(b + h | 0, e, 64); - g = g + 1 | 0; - } while (g >>> 0 < f >>> 0); - } - if ((c | 0) == 0) { - i = d; - return; - } else { - j = 0; - } - do { - bo(a + (j << 6) | 0, b + (j << 7) | 0, 64); - j = j + 1 | 0; - } while (j >>> 0 < c >>> 0); - if ((c | 0) == 0) { - i = d; - return; - } else { - k = 0; - } - do { - bo(a + (k + c << 6) | 0, b + (k << 7 | 64) | 0, 64); - k = k + 1 | 0; - } while (k >>> 0 < c >>> 0); - i = d; - return; -} -function bx(a, b) { - a = a | 0; - b = b | 0; - var c = 0; - c = bq(a + ((b << 7) - 64) | 0) | 0; - return (H = H, c) | 0; -} -function by(a) { - a = a | 0; - var b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0, M = 0, N = 0, O = 0, P = 0, Q = 0, R = 0, S = 0, T = 0, U = 0, V = 0, W = 0, X = 0, Y = 0, Z = 0, _ = 0, $ = 0, aa = 0, ab = 0; - b = i; - i = i + 128 | 0; - d = b | 0; - e = b + 64 | 0; - f = 0; - do { - c[d + (f << 2) >> 2] = br(a + (f << 2) | 0) | 0; - f = f + 1 | 0; - } while (f >>> 0 < 16); - f = d; - g = e; - cK(g | 0, f | 0, 64) | 0; - f = e | 0; - g = e + 48 | 0; - h = e + 16 | 0; - j = e + 32 | 0; - k = e + 20 | 0; - l = e + 4 | 0; - m = e + 36 | 0; - n = e + 52 | 0; - o = e + 40 | 0; - p = e + 24 | 0; - q = e + 56 | 0; - r = e + 8 | 0; - s = e + 60 | 0; - t = e + 44 | 0; - u = e + 12 | 0; - v = e + 28 | 0; - w = 0; - x = c[f >> 2] | 0; - y = c[g >> 2] | 0; - z = c[h >> 2] | 0; - A = c[j >> 2] | 0; - B = c[k >> 2] | 0; - C = c[l >> 2] | 0; - D = c[m >> 2] | 0; - E = c[n >> 2] | 0; - F = c[o >> 2] | 0; - G = c[p >> 2] | 0; - H = c[q >> 2] | 0; - I = c[r >> 2] | 0; - J = c[s >> 2] | 0; - K = c[t >> 2] | 0; - L = c[u >> 2] | 0; - M = c[v >> 2] | 0; - do { - N = y + x | 0; - O = (N << 7 | N >>> 25) ^ z; - N = O + x | 0; - P = (N << 9 | N >>> 23) ^ A; - N = P + O | 0; - Q = (N << 13 | N >>> 19) ^ y; - N = Q + P | 0; - R = (N << 18 | N >>> 14) ^ x; - N = C + B | 0; - S = (N << 7 | N >>> 25) ^ D; - N = S + B | 0; - T = (N << 9 | N >>> 23) ^ E; - N = T + S | 0; - U = (N << 13 | N >>> 19) ^ C; - N = U + T | 0; - V = (N << 18 | N >>> 14) ^ B; - N = G + F | 0; - W = (N << 7 | N >>> 25) ^ H; - N = W + F | 0; - X = (N << 9 | N >>> 23) ^ I; - N = X + W | 0; - Y = (N << 13 | N >>> 19) ^ G; - N = Y + X | 0; - Z = (N << 18 | N >>> 14) ^ F; - N = K + J | 0; - _ = (N << 7 | N >>> 25) ^ L; - N = _ + J | 0; - $ = (N << 9 | N >>> 23) ^ M; - N = $ + _ | 0; - aa = (N << 13 | N >>> 19) ^ K; - N = aa + $ | 0; - ab = (N << 18 | N >>> 14) ^ J; - N = _ + R | 0; - C = (N << 7 | N >>> 25) ^ U; - U = C + R | 0; - I = (U << 9 | U >>> 23) ^ X; - X = I + C | 0; - L = (X << 13 | X >>> 19) ^ _; - _ = L + I | 0; - x = (_ << 18 | _ >>> 14) ^ R; - R = O + V | 0; - G = (R << 7 | R >>> 25) ^ Y; - Y = G + V | 0; - M = (Y << 9 | Y >>> 23) ^ $; - $ = M + G | 0; - z = ($ << 13 | $ >>> 19) ^ O; - O = z + M | 0; - B = (O << 18 | O >>> 14) ^ V; - V = S + Z | 0; - K = (V << 7 | V >>> 25) ^ aa; - aa = K + Z | 0; - A = (aa << 9 | aa >>> 23) ^ P; - P = A + K | 0; - D = (P << 13 | P >>> 19) ^ S; - S = D + A | 0; - F = (S << 18 | S >>> 14) ^ Z; - Z = W + ab | 0; - y = (Z << 7 | Z >>> 25) ^ Q; - Q = y + ab | 0; - E = (Q << 9 | Q >>> 23) ^ T; - T = E + y | 0; - H = (T << 13 | T >>> 19) ^ W; - W = H + E | 0; - J = (W << 18 | W >>> 14) ^ ab; - w = w + 2 | 0; - } while (w >>> 0 < 8); - c[f >> 2] = x; - c[g >> 2] = y; - c[h >> 2] = z; - c[j >> 2] = A; - c[k >> 2] = B; - c[l >> 2] = C; - c[m >> 2] = D; - c[n >> 2] = E; - c[o >> 2] = F; - c[p >> 2] = G; - c[q >> 2] = H; - c[r >> 2] = I; - c[s >> 2] = J; - c[t >> 2] = K; - c[u >> 2] = L; - c[v >> 2] = M; - M = d | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e >> 2] | 0); - M = d + 4 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 4 >> 2] | 0); - M = d + 8 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 8 >> 2] | 0); - M = d + 12 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 12 >> 2] | 0); - M = d + 16 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 16 >> 2] | 0); - M = d + 20 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 20 >> 2] | 0); - M = d + 24 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 24 >> 2] | 0); - M = d + 28 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 28 >> 2] | 0); - M = d + 32 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 32 >> 2] | 0); - M = d + 36 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 36 >> 2] | 0); - M = d + 40 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 40 >> 2] | 0); - M = d + 44 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 44 >> 2] | 0); - M = d + 48 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 48 >> 2] | 0); - M = d + 52 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 52 >> 2] | 0); - M = d + 56 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 56 >> 2] | 0); - M = d + 60 | 0; - c[M >> 2] = (c[M >> 2] | 0) + (c[e + 60 >> 2] | 0); - e = 0; - do { - bs(a + (e << 2) | 0, c[d + (e << 2) >> 2] | 0); - e = e + 1 | 0; - } while (e >>> 0 < 16); - i = b; - return; -} -function bz(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0; - e = a + 32 | 0; - f = a + 36 | 0; - g = c[f >> 2] | 0; - h = g >>> 3 & 63; - i = aN(g | 0, d << 3 | 0) | 0; - c[f >> 2] = i; - if (H) { - i = e | 0; - c[i >> 2] = (c[i >> 2] | 0) + 1; - } - i = e | 0; - c[i >> 2] = (c[i >> 2] | 0) + (d >>> 29); - i = 64 - h | 0; - e = a + 40 + h | 0; - if (i >>> 0 > d >>> 0) { - cK(e | 0, b | 0, d) | 0; - return; - } - cK(e | 0, b | 0, i) | 0; - e = a | 0; - h = a + 40 | 0; - bA(e, h); - a = b + i | 0; - b = d - i | 0; - if (b >>> 0 > 63) { - i = b; - d = a; - while (1) { - bA(e, d); - f = d + 64 | 0; - g = i - 64 | 0; - if (g >>> 0 > 63) { - i = g; - d = f; - } else { - j = g; - k = f; - break; - } - } - } else { - j = b; - k = a; - } - cK(h | 0, k | 0, j) | 0; - return; -} -function bA(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0; - d = i; - i = i + 288 | 0; - e = d | 0; - f = d + 256 | 0; - g = e | 0; - bK(g, b); - b = 16; - do { - h = c[e + (b - 2 << 2) >> 2] | 0; - j = c[e + (b - 15 << 2) >> 2] | 0; - c[e + (b << 2) >> 2] = (c[e + (b - 16 << 2) >> 2] | 0) + (c[e + (b - 7 << 2) >> 2] | 0) + ((h >>> 19 | h << 13) ^ h >>> 10 ^ (h >>> 17 | h << 15)) + ((j >>> 18 | j << 14) ^ j >>> 3 ^ (j >>> 7 | j << 25)); - b = b + 1 | 0; - } while ((b | 0) < 64); - b = f; - j = a; - cK(b | 0, j | 0, 32) | 0; - j = f + 28 | 0; - b = f + 16 | 0; - h = c[b >> 2] | 0; - k = f + 20 | 0; - l = f + 24 | 0; - m = c[l >> 2] | 0; - n = (c[j >> 2] | 0) + 1116352408 + (c[g >> 2] | 0) + ((h >>> 6 | h << 26) ^ (h >>> 11 | h << 21) ^ (h >>> 25 | h << 7)) + ((m ^ c[k >> 2]) & h ^ m) | 0; - m = f | 0; - h = c[m >> 2] | 0; - g = f + 4 | 0; - o = c[g >> 2] | 0; - p = f + 8 | 0; - q = c[p >> 2] | 0; - r = f + 12 | 0; - c[r >> 2] = (c[r >> 2] | 0) + n; - s = ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + n + ((q | o) & h | q & o) | 0; - c[j >> 2] = s; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - h = (c[l >> 2] | 0) + 1899447441 + (c[e + 4 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[l >> 2] = n; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - s = (c[k >> 2] | 0) - 1245643825 + (c[e + 8 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[k >> 2] = h; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - n = (c[b >> 2] | 0) - 373957723 + (c[e + 12 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[b >> 2] = s; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - h = (c[r >> 2] | 0) + 961987163 + (c[e + 16 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[r >> 2] = n; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - s = (c[p >> 2] | 0) + 1508970993 + (c[e + 20 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[p >> 2] = h; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - n = (c[g >> 2] | 0) - 1841331548 + (c[e + 24 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[g >> 2] = s; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - h = (c[m >> 2] | 0) - 1424204075 + (c[e + 28 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[m >> 2] = n; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - s = (c[j >> 2] | 0) - 670586216 + (c[e + 32 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[j >> 2] = h; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - n = (c[l >> 2] | 0) + 310598401 + (c[e + 36 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[l >> 2] = s; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - h = (c[k >> 2] | 0) + 607225278 + (c[e + 40 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[k >> 2] = n; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - s = (c[b >> 2] | 0) + 1426881987 + (c[e + 44 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[b >> 2] = h; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - n = (c[r >> 2] | 0) + 1925078388 + (c[e + 48 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[r >> 2] = s; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - h = (c[p >> 2] | 0) - 2132889090 + (c[e + 52 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[p >> 2] = n; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - s = (c[g >> 2] | 0) - 1680079193 + (c[e + 56 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[g >> 2] = h; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - n = (c[m >> 2] | 0) - 1046744716 + (c[e + 60 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[m >> 2] = s; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - h = (c[j >> 2] | 0) - 459576895 + (c[e + 64 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[j >> 2] = n; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - s = (c[l >> 2] | 0) - 272742522 + (c[e + 68 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[l >> 2] = h; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - n = (c[k >> 2] | 0) + 264347078 + (c[e + 72 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[k >> 2] = s; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - h = (c[b >> 2] | 0) + 604807628 + (c[e + 76 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[b >> 2] = n; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - s = (c[r >> 2] | 0) + 770255983 + (c[e + 80 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[r >> 2] = h; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - n = (c[p >> 2] | 0) + 1249150122 + (c[e + 84 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[p >> 2] = s; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - h = (c[g >> 2] | 0) + 1555081692 + (c[e + 88 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[g >> 2] = n; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - s = (c[m >> 2] | 0) + 1996064986 + (c[e + 92 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[m >> 2] = h; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - n = (c[j >> 2] | 0) - 1740746414 + (c[e + 96 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[j >> 2] = s; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - h = (c[l >> 2] | 0) - 1473132947 + (c[e + 100 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[l >> 2] = n; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - s = (c[k >> 2] | 0) - 1341970488 + (c[e + 104 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[k >> 2] = h; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - n = (c[b >> 2] | 0) - 1084653625 + (c[e + 108 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[b >> 2] = s; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - h = (c[r >> 2] | 0) - 958395405 + (c[e + 112 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[r >> 2] = n; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - s = (c[p >> 2] | 0) - 710438585 + (c[e + 116 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[p >> 2] = h; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - n = (c[g >> 2] | 0) + 113926993 + (c[e + 120 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[g >> 2] = s; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - h = (c[m >> 2] | 0) + 338241895 + (c[e + 124 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[m >> 2] = n; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - s = (c[j >> 2] | 0) + 666307205 + (c[e + 128 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[j >> 2] = h; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - n = (c[l >> 2] | 0) + 773529912 + (c[e + 132 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[l >> 2] = s; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - h = (c[k >> 2] | 0) + 1294757372 + (c[e + 136 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[k >> 2] = n; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - s = (c[b >> 2] | 0) + 1396182291 + (c[e + 140 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[b >> 2] = h; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - n = (c[r >> 2] | 0) + 1695183700 + (c[e + 144 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[r >> 2] = s; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - h = (c[p >> 2] | 0) + 1986661051 + (c[e + 148 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[p >> 2] = n; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - s = (c[g >> 2] | 0) - 2117940946 + (c[e + 152 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[g >> 2] = h; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - n = (c[m >> 2] | 0) - 1838011259 + (c[e + 156 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[m >> 2] = s; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - h = (c[j >> 2] | 0) - 1564481375 + (c[e + 160 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[j >> 2] = n; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - s = (c[l >> 2] | 0) - 1474664885 + (c[e + 164 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[l >> 2] = h; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - n = (c[k >> 2] | 0) - 1035236496 + (c[e + 168 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[k >> 2] = s; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - h = (c[b >> 2] | 0) - 949202525 + (c[e + 172 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[b >> 2] = n; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - s = (c[r >> 2] | 0) - 778901479 + (c[e + 176 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[r >> 2] = h; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - n = (c[p >> 2] | 0) - 694614492 + (c[e + 180 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[p >> 2] = s; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - h = (c[g >> 2] | 0) - 200395387 + (c[e + 184 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[g >> 2] = n; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - s = (c[m >> 2] | 0) + 275423344 + (c[e + 188 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[m >> 2] = h; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - n = (c[j >> 2] | 0) + 430227734 + (c[e + 192 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[j >> 2] = s; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - h = (c[l >> 2] | 0) + 506948616 + (c[e + 196 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[l >> 2] = n; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - s = (c[k >> 2] | 0) + 659060556 + (c[e + 200 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[k >> 2] = h; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - n = (c[b >> 2] | 0) + 883997877 + (c[e + 204 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[b >> 2] = s; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - h = (c[r >> 2] | 0) + 958139571 + (c[e + 208 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[r >> 2] = n; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - s = (c[p >> 2] | 0) + 1322822218 + (c[e + 212 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[p >> 2] = h; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - n = (c[g >> 2] | 0) + 1537002063 + (c[e + 216 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[g >> 2] = s; - o = c[k >> 2] | 0; - q = c[j >> 2] | 0; - h = (c[m >> 2] | 0) + 1747873779 + (c[e + 220 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[l >> 2]) & o ^ q) | 0; - q = c[p >> 2] | 0; - o = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[m >> 2] = n; - q = c[b >> 2] | 0; - o = c[l >> 2] | 0; - s = (c[j >> 2] | 0) + 1955562222 + (c[e + 224 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[k >> 2]) & q ^ o) | 0; - o = c[g >> 2] | 0; - q = c[p >> 2] | 0; - c[r >> 2] = (c[r >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[j >> 2] = h; - o = c[r >> 2] | 0; - q = c[k >> 2] | 0; - n = (c[l >> 2] | 0) + 2024104815 + (c[e + 228 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[b >> 2]) & o ^ q) | 0; - q = c[m >> 2] | 0; - o = c[g >> 2] | 0; - c[p >> 2] = (c[p >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((o | q) & h | o & q) | 0; - c[l >> 2] = s; - q = c[p >> 2] | 0; - o = c[b >> 2] | 0; - h = (c[k >> 2] | 0) - 2067236844 + (c[e + 232 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[r >> 2]) & q ^ o) | 0; - o = c[j >> 2] | 0; - q = c[m >> 2] | 0; - c[g >> 2] = (c[g >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((q | o) & s | q & o) | 0; - c[k >> 2] = n; - o = c[g >> 2] | 0; - q = c[r >> 2] | 0; - s = (c[b >> 2] | 0) - 1933114872 + (c[e + 236 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[p >> 2]) & o ^ q) | 0; - q = c[l >> 2] | 0; - o = c[j >> 2] | 0; - c[m >> 2] = (c[m >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((o | q) & n | o & q) | 0; - c[b >> 2] = h; - q = c[m >> 2] | 0; - o = c[p >> 2] | 0; - n = (c[r >> 2] | 0) - 1866530822 + (c[e + 240 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[g >> 2]) & q ^ o) | 0; - o = c[k >> 2] | 0; - q = c[l >> 2] | 0; - c[j >> 2] = (c[j >> 2] | 0) + n; - s = n + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((q | o) & h | q & o) | 0; - c[r >> 2] = s; - o = c[j >> 2] | 0; - q = c[g >> 2] | 0; - h = (c[p >> 2] | 0) - 1538233109 + (c[e + 244 >> 2] | 0) + ((o >>> 6 | o << 26) ^ (o >>> 11 | o << 21) ^ (o >>> 25 | o << 7)) + ((q ^ c[m >> 2]) & o ^ q) | 0; - q = c[b >> 2] | 0; - o = c[k >> 2] | 0; - c[l >> 2] = (c[l >> 2] | 0) + h; - n = h + ((s >>> 2 | s << 30) ^ (s >>> 13 | s << 19) ^ (s >>> 22 | s << 10)) + ((o | q) & s | o & q) | 0; - c[p >> 2] = n; - q = c[l >> 2] | 0; - o = c[m >> 2] | 0; - s = (c[g >> 2] | 0) - 1090935817 + (c[e + 248 >> 2] | 0) + ((q >>> 6 | q << 26) ^ (q >>> 11 | q << 21) ^ (q >>> 25 | q << 7)) + ((o ^ c[j >> 2]) & q ^ o) | 0; - o = c[r >> 2] | 0; - q = c[b >> 2] | 0; - c[k >> 2] = (c[k >> 2] | 0) + s; - h = s + ((n >>> 2 | n << 30) ^ (n >>> 13 | n << 19) ^ (n >>> 22 | n << 10)) + ((q | o) & n | q & o) | 0; - c[g >> 2] = h; - g = c[k >> 2] | 0; - k = c[j >> 2] | 0; - j = (c[m >> 2] | 0) - 965641998 + (c[e + 252 >> 2] | 0) + ((g >>> 6 | g << 26) ^ (g >>> 11 | g << 21) ^ (g >>> 25 | g << 7)) + ((k ^ c[l >> 2]) & g ^ k) | 0; - k = c[p >> 2] | 0; - p = c[r >> 2] | 0; - c[b >> 2] = (c[b >> 2] | 0) + j; - b = j + ((h >>> 2 | h << 30) ^ (h >>> 13 | h << 19) ^ (h >>> 22 | h << 10)) + ((p | k) & h | p & k) | 0; - c[m >> 2] = b; - c[a >> 2] = (c[a >> 2] | 0) + b; - b = a + 4 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 4 >> 2] | 0); - b = a + 8 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 8 >> 2] | 0); - b = a + 12 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 12 >> 2] | 0); - b = a + 16 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 16 >> 2] | 0); - b = a + 20 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 20 >> 2] | 0); - b = a + 24 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 24 >> 2] | 0); - b = a + 28 | 0; - c[b >> 2] = (c[b >> 2] | 0) + (c[f + 28 >> 2] | 0); - i = d; - return; -} -function bB(b, c) { - b = b | 0; - c = c | 0; - a[b + 3 | 0] = c & 255; - a[b + 2 | 0] = c >>> 8 & 255; - a[b + 1 | 0] = c >>> 16 & 255; - a[b] = c >>> 24 & 255; - return; -} -function bC(a) { - a = a | 0; - return (d[a + 2 | 0] | 0) << 8 | (d[a + 3 | 0] | 0) | (d[a + 1 | 0] | 0) << 16 | (d[a] | 0) << 24 | 0; -} -function bD(a, b) { - a = a | 0; - b = b | 0; - bE(b); - bF(a, b | 0, 32); - cL(b | 0, 0, 104); - return; -} -function bE(a) { - a = a | 0; - var b = 0, d = 0, e = 0; - b = i; - i = i + 8 | 0; - d = b | 0; - bF(d, a + 32 | 0, 8); - e = (c[a + 36 >> 2] | 0) >>> 3 & 63; - bz(a, 720, (e >>> 0 < 56 ? 56 : 120) - e | 0); - bz(a, d, 8); - i = b; - return; -} -function bF(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0; - e = d >>> 2; - if ((e | 0) == 0) { - return; - } else { - f = 0; - } - do { - bB(a + (f << 2) | 0, c[b + (f << 2) >> 2] | 0); - f = f + 1 | 0; - } while (f >>> 0 < e >>> 0); - return; -} -function bG(b, c, d) { - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0, f = 0, g = 0, h = 0, j = 0, k = 0, l = 0; - e = i; - i = i + 96 | 0; - f = e | 0; - if (d >>> 0 > 64) { - g = b | 0; - bt(g); - bz(g, c, d); - h = e + 64 | 0; - bD(h, g); - j = h; - k = 32; - } else { - j = c; - k = d; - } - d = b | 0; - bt(d); - c = f | 0; - cL(c | 0, 54, 64); - if ((k | 0) != 0) { - h = 0; - do { - g = f + h | 0; - a[g] = a[g] ^ a[j + h | 0]; - h = h + 1 | 0; - } while (h >>> 0 < k >>> 0); - } - bz(d, c, 64); - d = b + 104 | 0; - bt(d); - cL(c | 0, 92, 64); - if ((k | 0) == 0) { - bz(d, c, 64); - i = e; - return; - } else { - l = 0; - } - do { - b = f + l | 0; - a[b] = a[b] ^ a[j + l | 0]; - l = l + 1 | 0; - } while (l >>> 0 < k >>> 0); - bz(d, c, 64); - i = e; - return; -} -function bH(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - bz(a | 0, b, c); - return; -} -function bI(a, b) { - a = a | 0; - b = b | 0; - var c = 0, d = 0, e = 0; - c = i; - i = i + 32 | 0; - d = c | 0; - bD(d, b | 0); - e = b + 104 | 0; - bz(e, d, 32); - bD(a, e); - i = c; - return; -} -function bJ(b, c, d, e, f, g, h, j) { - b = b | 0; - c = c | 0; - d = d | 0; - e = e | 0; - f = f | 0; - g = g | 0; - h = h | 0; - j = j | 0; - var k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0; - k = i; - i = i + 488 | 0; - l = k | 0; - m = k + 208 | 0; - n = k + 424 | 0; - o = k + 456 | 0; - bG(l, b, c); - bH(l, d, e); - if ((j | 0) == 0) { - i = k; - return; - } - e = k + 416 | 0; - d = m; - p = l; - l = n | 0; - q = o | 0; - r = 0; - s = g >>> 0 < r >>> 0 | g >>> 0 == r >>> 0 & f >>> 0 < 2 >>> 0; - r = 0; - t = 0; - do { - r = r + 1 | 0; - bB(e, r); - cK(d | 0, p | 0, 208) | 0; - bH(m, e, 4); - bI(l, m); - cK(q | 0, l | 0, 32) | 0; - if (!s) { - u = 0; - v = 2; - do { - bG(m, b, c); - bH(m, l, 32); - bI(l, m); - w = 0; - do { - x = o + w | 0; - a[x] = a[x] ^ a[n + w | 0]; - w = w + 1 | 0; - } while ((w | 0) < 32); - v = cN(v, u, 1, 0) | 0; - u = H; - } while (!(u >>> 0 > g >>> 0 | u >>> 0 == g >>> 0 & v >>> 0 > f >>> 0)); - } - v = j - t | 0; - u = v >>> 0 > 32 ? 32 : v; - v = h + t | 0; - cK(v | 0, q | 0, u) | 0; - t = r << 5; - } while (t >>> 0 < j >>> 0); - i = k; - return; -} -function bK(a, b) { - a = a | 0; - b = b | 0; - var d = 0; - d = 0; - do { - c[a + (d << 2) >> 2] = bC(b + (d << 2) | 0) | 0; - d = d + 1 | 0; - } while (d >>> 0 < 16); - return; -} -function bL(a) { - a = a | 0; - var b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0, M = 0, N = 0, O = 0, P = 0, Q = 0, R = 0, S = 0, T = 0, U = 0, V = 0, W = 0, X = 0, Y = 0, Z = 0, _ = 0, $ = 0, aa = 0, ab = 0, ac = 0, ad = 0, ae = 0, af = 0, ag = 0, ah = 0, ai = 0, aj = 0, ak = 0, al = 0, am = 0, an = 0, ao = 0, ap = 0, aq = 0, as = 0, at = 0, av = 0, aw = 0, ax = 0, ay = 0, az = 0, aA = 0, aB = 0, aC = 0, aD = 0, aE = 0, aF = 0, aG = 0, aH = 0, aI = 0; - do { - if (a >>> 0 < 245) { - if (a >>> 0 < 11) { - b = 16; - } else { - b = a + 11 & -8; - } - d = b >>> 3; - e = c[208] | 0; - f = e >>> (d >>> 0); - if ((f & 3 | 0) != 0) { - g = (f & 1 ^ 1) + d | 0; - h = g << 1; - i = 872 + (h << 2) | 0; - j = 872 + (h + 2 << 2) | 0; - h = c[j >> 2] | 0; - k = h + 8 | 0; - l = c[k >> 2] | 0; - do { - if ((i | 0) == (l | 0)) { - c[208] = e & ~(1 << g); - } else { - if (l >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - m = l + 12 | 0; - if ((c[m >> 2] | 0) == (h | 0)) { - c[m >> 2] = i; - c[j >> 2] = l; - break; - } else { - au(); - return 0; - } - } - } while (0); - l = g << 3; - c[h + 4 >> 2] = l | 3; - j = h + (l | 4) | 0; - c[j >> 2] = c[j >> 2] | 1; - n = k; - return n | 0; - } - if (b >>> 0 <= (c[210] | 0) >>> 0) { - o = b; - break; - } - if ((f | 0) != 0) { - j = 2 << d; - l = f << d & (j | -j); - j = (l & -l) - 1 | 0; - l = j >>> 12 & 16; - i = j >>> (l >>> 0); - j = i >>> 5 & 8; - m = i >>> (j >>> 0); - i = m >>> 2 & 4; - p = m >>> (i >>> 0); - m = p >>> 1 & 2; - q = p >>> (m >>> 0); - p = q >>> 1 & 1; - r = (j | l | i | m | p) + (q >>> (p >>> 0)) | 0; - p = r << 1; - q = 872 + (p << 2) | 0; - m = 872 + (p + 2 << 2) | 0; - p = c[m >> 2] | 0; - i = p + 8 | 0; - l = c[i >> 2] | 0; - do { - if ((q | 0) == (l | 0)) { - c[208] = e & ~(1 << r); - } else { - if (l >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - j = l + 12 | 0; - if ((c[j >> 2] | 0) == (p | 0)) { - c[j >> 2] = q; - c[m >> 2] = l; - break; - } else { - au(); - return 0; - } - } - } while (0); - l = r << 3; - m = l - b | 0; - c[p + 4 >> 2] = b | 3; - q = p; - e = q + b | 0; - c[q + (b | 4) >> 2] = m | 1; - c[q + l >> 2] = m; - l = c[210] | 0; - if ((l | 0) != 0) { - q = c[213] | 0; - d = l >>> 3; - l = d << 1; - f = 872 + (l << 2) | 0; - k = c[208] | 0; - h = 1 << d; - do { - if ((k & h | 0) == 0) { - c[208] = k | h; - s = f; - t = 872 + (l + 2 << 2) | 0; - } else { - d = 872 + (l + 2 << 2) | 0; - g = c[d >> 2] | 0; - if (g >>> 0 >= (c[212] | 0) >>> 0) { - s = g; - t = d; - break; - } - au(); - return 0; - } - } while (0); - c[t >> 2] = q; - c[s + 12 >> 2] = q; - c[q + 8 >> 2] = s; - c[q + 12 >> 2] = f; - } - c[210] = m; - c[213] = e; - n = i; - return n | 0; - } - l = c[209] | 0; - if ((l | 0) == 0) { - o = b; - break; - } - h = (l & -l) - 1 | 0; - l = h >>> 12 & 16; - k = h >>> (l >>> 0); - h = k >>> 5 & 8; - p = k >>> (h >>> 0); - k = p >>> 2 & 4; - r = p >>> (k >>> 0); - p = r >>> 1 & 2; - d = r >>> (p >>> 0); - r = d >>> 1 & 1; - g = c[1136 + ((h | l | k | p | r) + (d >>> (r >>> 0)) << 2) >> 2] | 0; - r = g; - d = g; - p = (c[g + 4 >> 2] & -8) - b | 0; - while (1) { - g = c[r + 16 >> 2] | 0; - if ((g | 0) == 0) { - k = c[r + 20 >> 2] | 0; - if ((k | 0) == 0) { - break; - } else { - u = k; - } - } else { - u = g; - } - g = (c[u + 4 >> 2] & -8) - b | 0; - k = g >>> 0 < p >>> 0; - r = u; - d = k ? u : d; - p = k ? g : p; - } - r = d; - i = c[212] | 0; - if (r >>> 0 < i >>> 0) { - au(); - return 0; - } - e = r + b | 0; - m = e; - if (r >>> 0 >= e >>> 0) { - au(); - return 0; - } - e = c[d + 24 >> 2] | 0; - f = c[d + 12 >> 2] | 0; - do { - if ((f | 0) == (d | 0)) { - q = d + 20 | 0; - g = c[q >> 2] | 0; - if ((g | 0) == 0) { - k = d + 16 | 0; - l = c[k >> 2] | 0; - if ((l | 0) == 0) { - v = 0; - break; - } else { - w = l; - x = k; - } - } else { - w = g; - x = q; - } - while (1) { - q = w + 20 | 0; - g = c[q >> 2] | 0; - if ((g | 0) != 0) { - w = g; - x = q; - continue; - } - q = w + 16 | 0; - g = c[q >> 2] | 0; - if ((g | 0) == 0) { - break; - } else { - w = g; - x = q; - } - } - if (x >>> 0 < i >>> 0) { - au(); - return 0; - } else { - c[x >> 2] = 0; - v = w; - break; - } - } else { - q = c[d + 8 >> 2] | 0; - if (q >>> 0 < i >>> 0) { - au(); - return 0; - } - g = q + 12 | 0; - if ((c[g >> 2] | 0) != (d | 0)) { - au(); - return 0; - } - k = f + 8 | 0; - if ((c[k >> 2] | 0) == (d | 0)) { - c[g >> 2] = f; - c[k >> 2] = q; - v = f; - break; - } else { - au(); - return 0; - } - } - } while (0); - L223 : do { - if ((e | 0) != 0) { - f = d + 28 | 0; - i = 1136 + (c[f >> 2] << 2) | 0; - do { - if ((d | 0) == (c[i >> 2] | 0)) { - c[i >> 2] = v; - if ((v | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[f >> 2]); - break L223; - } else { - if (e >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - q = e + 16 | 0; - if ((c[q >> 2] | 0) == (d | 0)) { - c[q >> 2] = v; - } else { - c[e + 20 >> 2] = v; - } - if ((v | 0) == 0) { - break L223; - } - } - } while (0); - if (v >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - c[v + 24 >> 2] = e; - f = c[d + 16 >> 2] | 0; - do { - if ((f | 0) != 0) { - if (f >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[v + 16 >> 2] = f; - c[f + 24 >> 2] = v; - break; - } - } - } while (0); - f = c[d + 20 >> 2] | 0; - if ((f | 0) == 0) { - break; - } - if (f >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[v + 20 >> 2] = f; - c[f + 24 >> 2] = v; - break; - } - } - } while (0); - if (p >>> 0 < 16) { - e = p + b | 0; - c[d + 4 >> 2] = e | 3; - f = r + (e + 4) | 0; - c[f >> 2] = c[f >> 2] | 1; - } else { - c[d + 4 >> 2] = b | 3; - c[r + (b | 4) >> 2] = p | 1; - c[r + (p + b) >> 2] = p; - f = c[210] | 0; - if ((f | 0) != 0) { - e = c[213] | 0; - i = f >>> 3; - f = i << 1; - q = 872 + (f << 2) | 0; - k = c[208] | 0; - g = 1 << i; - do { - if ((k & g | 0) == 0) { - c[208] = k | g; - y = q; - z = 872 + (f + 2 << 2) | 0; - } else { - i = 872 + (f + 2 << 2) | 0; - l = c[i >> 2] | 0; - if (l >>> 0 >= (c[212] | 0) >>> 0) { - y = l; - z = i; - break; - } - au(); - return 0; - } - } while (0); - c[z >> 2] = e; - c[y + 12 >> 2] = e; - c[e + 8 >> 2] = y; - c[e + 12 >> 2] = q; - } - c[210] = p; - c[213] = m; - } - f = d + 8 | 0; - if ((f | 0) == 0) { - o = b; - break; - } else { - n = f; - } - return n | 0; - } else { - if (a >>> 0 > 4294967231) { - o = -1; - break; - } - f = a + 11 | 0; - g = f & -8; - k = c[209] | 0; - if ((k | 0) == 0) { - o = g; - break; - } - r = -g | 0; - i = f >>> 8; - do { - if ((i | 0) == 0) { - A = 0; - } else { - if (g >>> 0 > 16777215) { - A = 31; - break; - } - f = (i + 1048320 | 0) >>> 16 & 8; - l = i << f; - h = (l + 520192 | 0) >>> 16 & 4; - j = l << h; - l = (j + 245760 | 0) >>> 16 & 2; - B = 14 - (h | f | l) + (j << l >>> 15) | 0; - A = g >>> ((B + 7 | 0) >>> 0) & 1 | B << 1; - } - } while (0); - i = c[1136 + (A << 2) >> 2] | 0; - L271 : do { - if ((i | 0) == 0) { - C = 0; - D = r; - E = 0; - } else { - if ((A | 0) == 31) { - F = 0; - } else { - F = 25 - (A >>> 1) | 0; - } - d = 0; - m = r; - p = i; - q = g << F; - e = 0; - while (1) { - B = c[p + 4 >> 2] & -8; - l = B - g | 0; - if (l >>> 0 < m >>> 0) { - if ((B | 0) == (g | 0)) { - C = p; - D = l; - E = p; - break L271; - } else { - G = p; - H = l; - } - } else { - G = d; - H = m; - } - l = c[p + 20 >> 2] | 0; - B = c[p + 16 + (q >>> 31 << 2) >> 2] | 0; - j = (l | 0) == 0 | (l | 0) == (B | 0) ? e : l; - if ((B | 0) == 0) { - C = G; - D = H; - E = j; - break; - } else { - d = G; - m = H; - p = B; - q = q << 1; - e = j; - } - } - } - } while (0); - if ((E | 0) == 0 & (C | 0) == 0) { - i = 2 << A; - r = k & (i | -i); - if ((r | 0) == 0) { - o = g; - break; - } - i = (r & -r) - 1 | 0; - r = i >>> 12 & 16; - e = i >>> (r >>> 0); - i = e >>> 5 & 8; - q = e >>> (i >>> 0); - e = q >>> 2 & 4; - p = q >>> (e >>> 0); - q = p >>> 1 & 2; - m = p >>> (q >>> 0); - p = m >>> 1 & 1; - I = c[1136 + ((i | r | e | q | p) + (m >>> (p >>> 0)) << 2) >> 2] | 0; - } else { - I = E; - } - if ((I | 0) == 0) { - J = D; - K = C; - } else { - p = I; - m = D; - q = C; - while (1) { - e = (c[p + 4 >> 2] & -8) - g | 0; - r = e >>> 0 < m >>> 0; - i = r ? e : m; - e = r ? p : q; - r = c[p + 16 >> 2] | 0; - if ((r | 0) != 0) { - p = r; - m = i; - q = e; - continue; - } - r = c[p + 20 >> 2] | 0; - if ((r | 0) == 0) { - J = i; - K = e; - break; - } else { - p = r; - m = i; - q = e; - } - } - } - if ((K | 0) == 0) { - o = g; - break; - } - if (J >>> 0 >= ((c[210] | 0) - g | 0) >>> 0) { - o = g; - break; - } - q = K; - m = c[212] | 0; - if (q >>> 0 < m >>> 0) { - au(); - return 0; - } - p = q + g | 0; - k = p; - if (q >>> 0 >= p >>> 0) { - au(); - return 0; - } - e = c[K + 24 >> 2] | 0; - i = c[K + 12 >> 2] | 0; - do { - if ((i | 0) == (K | 0)) { - r = K + 20 | 0; - d = c[r >> 2] | 0; - if ((d | 0) == 0) { - j = K + 16 | 0; - B = c[j >> 2] | 0; - if ((B | 0) == 0) { - L = 0; - break; - } else { - M = B; - N = j; - } - } else { - M = d; - N = r; - } - while (1) { - r = M + 20 | 0; - d = c[r >> 2] | 0; - if ((d | 0) != 0) { - M = d; - N = r; - continue; - } - r = M + 16 | 0; - d = c[r >> 2] | 0; - if ((d | 0) == 0) { - break; - } else { - M = d; - N = r; - } - } - if (N >>> 0 < m >>> 0) { - au(); - return 0; - } else { - c[N >> 2] = 0; - L = M; - break; - } - } else { - r = c[K + 8 >> 2] | 0; - if (r >>> 0 < m >>> 0) { - au(); - return 0; - } - d = r + 12 | 0; - if ((c[d >> 2] | 0) != (K | 0)) { - au(); - return 0; - } - j = i + 8 | 0; - if ((c[j >> 2] | 0) == (K | 0)) { - c[d >> 2] = i; - c[j >> 2] = r; - L = i; - break; - } else { - au(); - return 0; - } - } - } while (0); - L321 : do { - if ((e | 0) != 0) { - i = K + 28 | 0; - m = 1136 + (c[i >> 2] << 2) | 0; - do { - if ((K | 0) == (c[m >> 2] | 0)) { - c[m >> 2] = L; - if ((L | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[i >> 2]); - break L321; - } else { - if (e >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - r = e + 16 | 0; - if ((c[r >> 2] | 0) == (K | 0)) { - c[r >> 2] = L; - } else { - c[e + 20 >> 2] = L; - } - if ((L | 0) == 0) { - break L321; - } - } - } while (0); - if (L >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - c[L + 24 >> 2] = e; - i = c[K + 16 >> 2] | 0; - do { - if ((i | 0) != 0) { - if (i >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[L + 16 >> 2] = i; - c[i + 24 >> 2] = L; - break; - } - } - } while (0); - i = c[K + 20 >> 2] | 0; - if ((i | 0) == 0) { - break; - } - if (i >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[L + 20 >> 2] = i; - c[i + 24 >> 2] = L; - break; - } - } - } while (0); - do { - if (J >>> 0 < 16) { - e = J + g | 0; - c[K + 4 >> 2] = e | 3; - i = q + (e + 4) | 0; - c[i >> 2] = c[i >> 2] | 1; - } else { - c[K + 4 >> 2] = g | 3; - c[q + (g | 4) >> 2] = J | 1; - c[q + (J + g) >> 2] = J; - i = J >>> 3; - if (J >>> 0 < 256) { - e = i << 1; - m = 872 + (e << 2) | 0; - r = c[208] | 0; - j = 1 << i; - do { - if ((r & j | 0) == 0) { - c[208] = r | j; - O = m; - P = 872 + (e + 2 << 2) | 0; - } else { - i = 872 + (e + 2 << 2) | 0; - d = c[i >> 2] | 0; - if (d >>> 0 >= (c[212] | 0) >>> 0) { - O = d; - P = i; - break; - } - au(); - return 0; - } - } while (0); - c[P >> 2] = k; - c[O + 12 >> 2] = k; - c[q + (g + 8) >> 2] = O; - c[q + (g + 12) >> 2] = m; - break; - } - e = p; - j = J >>> 8; - do { - if ((j | 0) == 0) { - Q = 0; - } else { - if (J >>> 0 > 16777215) { - Q = 31; - break; - } - r = (j + 1048320 | 0) >>> 16 & 8; - i = j << r; - d = (i + 520192 | 0) >>> 16 & 4; - B = i << d; - i = (B + 245760 | 0) >>> 16 & 2; - l = 14 - (d | r | i) + (B << i >>> 15) | 0; - Q = J >>> ((l + 7 | 0) >>> 0) & 1 | l << 1; - } - } while (0); - j = 1136 + (Q << 2) | 0; - c[q + (g + 28) >> 2] = Q; - c[q + (g + 20) >> 2] = 0; - c[q + (g + 16) >> 2] = 0; - m = c[209] | 0; - l = 1 << Q; - if ((m & l | 0) == 0) { - c[209] = m | l; - c[j >> 2] = e; - c[q + (g + 24) >> 2] = j; - c[q + (g + 12) >> 2] = e; - c[q + (g + 8) >> 2] = e; - break; - } - if ((Q | 0) == 31) { - R = 0; - } else { - R = 25 - (Q >>> 1) | 0; - } - l = J << R; - m = c[j >> 2] | 0; - while (1) { - if ((c[m + 4 >> 2] & -8 | 0) == (J | 0)) { - break; - } - S = m + 16 + (l >>> 31 << 2) | 0; - j = c[S >> 2] | 0; - if ((j | 0) == 0) { - T = 262; - break; - } else { - l = l << 1; - m = j; - } - } - if ((T | 0) == 262) { - if (S >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[S >> 2] = e; - c[q + (g + 24) >> 2] = m; - c[q + (g + 12) >> 2] = e; - c[q + (g + 8) >> 2] = e; - break; - } - } - l = m + 8 | 0; - j = c[l >> 2] | 0; - i = c[212] | 0; - if (m >>> 0 < i >>> 0) { - au(); - return 0; - } - if (j >>> 0 < i >>> 0) { - au(); - return 0; - } else { - c[j + 12 >> 2] = e; - c[l >> 2] = e; - c[q + (g + 8) >> 2] = j; - c[q + (g + 12) >> 2] = m; - c[q + (g + 24) >> 2] = 0; - break; - } - } - } while (0); - q = K + 8 | 0; - if ((q | 0) == 0) { - o = g; - break; - } else { - n = q; - } - return n | 0; - } - } while (0); - K = c[210] | 0; - if (o >>> 0 <= K >>> 0) { - S = K - o | 0; - J = c[213] | 0; - if (S >>> 0 > 15) { - R = J; - c[213] = R + o; - c[210] = S; - c[R + (o + 4) >> 2] = S | 1; - c[R + K >> 2] = S; - c[J + 4 >> 2] = o | 3; - } else { - c[210] = 0; - c[213] = 0; - c[J + 4 >> 2] = K | 3; - S = J + (K + 4) | 0; - c[S >> 2] = c[S >> 2] | 1; - } - n = J + 8 | 0; - return n | 0; - } - J = c[211] | 0; - if (o >>> 0 < J >>> 0) { - S = J - o | 0; - c[211] = S; - J = c[214] | 0; - K = J; - c[214] = K + o; - c[K + (o + 4) >> 2] = S | 1; - c[J + 4 >> 2] = o | 3; - n = J + 8 | 0; - return n | 0; - } - do { - if ((c[200] | 0) == 0) { - J = ar(8) | 0; - if ((J - 1 & J | 0) == 0) { - c[202] = J; - c[201] = J; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - return 0; - } - } - } while (0); - J = o + 48 | 0; - S = c[202] | 0; - K = o + 47 | 0; - R = S + K | 0; - Q = -S | 0; - S = R & Q; - if (S >>> 0 <= o >>> 0) { - n = 0; - return n | 0; - } - O = c[318] | 0; - do { - if ((O | 0) != 0) { - P = c[316] | 0; - L = P + S | 0; - if (L >>> 0 <= P >>> 0 | L >>> 0 > O >>> 0) { - n = 0; - } else { - break; - } - return n | 0; - } - } while (0); - L413 : do { - if ((c[319] & 4 | 0) == 0) { - O = c[214] | 0; - L415 : do { - if ((O | 0) == 0) { - T = 292; - } else { - L = O; - P = 1280; - while (1) { - U = P | 0; - M = c[U >> 2] | 0; - if (M >>> 0 <= L >>> 0) { - V = P + 4 | 0; - if ((M + (c[V >> 2] | 0) | 0) >>> 0 > L >>> 0) { - break; - } - } - M = c[P + 8 >> 2] | 0; - if ((M | 0) == 0) { - T = 292; - break L415; - } else { - P = M; - } - } - if ((P | 0) == 0) { - T = 292; - break; - } - L = R - (c[211] | 0) & Q; - if (L >>> 0 >= 2147483647) { - W = 0; - break; - } - m = aV(L | 0) | 0; - e = (m | 0) == ((c[U >> 2] | 0) + (c[V >> 2] | 0) | 0); - X = e ? m : -1; - Y = e ? L : 0; - Z = m; - _ = L; - T = 301; - } - } while (0); - do { - if ((T | 0) == 292) { - O = aV(0) | 0; - if ((O | 0) == -1) { - W = 0; - break; - } - g = O; - L = c[201] | 0; - m = L - 1 | 0; - if ((m & g | 0) == 0) { - $ = S; - } else { - $ = S - g + (m + g & -L) | 0; - } - L = c[316] | 0; - g = L + $ | 0; - if (!($ >>> 0 > o >>> 0 & $ >>> 0 < 2147483647)) { - W = 0; - break; - } - m = c[318] | 0; - if ((m | 0) != 0) { - if (g >>> 0 <= L >>> 0 | g >>> 0 > m >>> 0) { - W = 0; - break; - } - } - m = aV($ | 0) | 0; - g = (m | 0) == (O | 0); - X = g ? O : -1; - Y = g ? $ : 0; - Z = m; - _ = $; - T = 301; - } - } while (0); - L435 : do { - if ((T | 0) == 301) { - m = -_ | 0; - if ((X | 0) != -1) { - aa = Y; - ab = X; - T = 312; - break L413; - } - do { - if ((Z | 0) != -1 & _ >>> 0 < 2147483647 & _ >>> 0 < J >>> 0) { - g = c[202] | 0; - O = K - _ + g & -g; - if (O >>> 0 >= 2147483647) { - ac = _; - break; - } - if ((aV(O | 0) | 0) == -1) { - aV(m | 0) | 0; - W = Y; - break L435; - } else { - ac = O + _ | 0; - break; - } - } else { - ac = _; - } - } while (0); - if ((Z | 0) == -1) { - W = Y; - } else { - aa = ac; - ab = Z; - T = 312; - break L413; - } - } - } while (0); - c[319] = c[319] | 4; - ad = W; - T = 309; - } else { - ad = 0; - T = 309; - } - } while (0); - do { - if ((T | 0) == 309) { - if (S >>> 0 >= 2147483647) { - break; - } - W = aV(S | 0) | 0; - Z = aV(0) | 0; - if (!((Z | 0) != -1 & (W | 0) != -1 & W >>> 0 < Z >>> 0)) { - break; - } - ac = Z - W | 0; - Z = ac >>> 0 > (o + 40 | 0) >>> 0; - Y = Z ? W : -1; - if ((Y | 0) != -1) { - aa = Z ? ac : ad; - ab = Y; - T = 312; - } - } - } while (0); - do { - if ((T | 0) == 312) { - ad = (c[316] | 0) + aa | 0; - c[316] = ad; - if (ad >>> 0 > (c[317] | 0) >>> 0) { - c[317] = ad; - } - ad = c[214] | 0; - L455 : do { - if ((ad | 0) == 0) { - S = c[212] | 0; - if ((S | 0) == 0 | ab >>> 0 < S >>> 0) { - c[212] = ab; - } - c[320] = ab; - c[321] = aa; - c[323] = 0; - c[217] = c[200]; - c[216] = -1; - S = 0; - do { - Y = S << 1; - ac = 872 + (Y << 2) | 0; - c[872 + (Y + 3 << 2) >> 2] = ac; - c[872 + (Y + 2 << 2) >> 2] = ac; - S = S + 1 | 0; - } while (S >>> 0 < 32); - S = ab + 8 | 0; - if ((S & 7 | 0) == 0) { - ae = 0; - } else { - ae = -S & 7; - } - S = aa - 40 - ae | 0; - c[214] = ab + ae; - c[211] = S; - c[ab + (ae + 4) >> 2] = S | 1; - c[ab + (aa - 36) >> 2] = 40; - c[215] = c[204]; - } else { - S = 1280; - while (1) { - af = c[S >> 2] | 0; - ag = S + 4 | 0; - ah = c[ag >> 2] | 0; - if ((ab | 0) == (af + ah | 0)) { - T = 324; - break; - } - ac = c[S + 8 >> 2] | 0; - if ((ac | 0) == 0) { - break; - } else { - S = ac; - } - } - do { - if ((T | 0) == 324) { - if ((c[S + 12 >> 2] & 8 | 0) != 0) { - break; - } - ac = ad; - if (!(ac >>> 0 >= af >>> 0 & ac >>> 0 < ab >>> 0)) { - break; - } - c[ag >> 2] = ah + aa; - ac = c[214] | 0; - Y = (c[211] | 0) + aa | 0; - Z = ac; - W = ac + 8 | 0; - if ((W & 7 | 0) == 0) { - ai = 0; - } else { - ai = -W & 7; - } - W = Y - ai | 0; - c[214] = Z + ai; - c[211] = W; - c[Z + (ai + 4) >> 2] = W | 1; - c[Z + (Y + 4) >> 2] = 40; - c[215] = c[204]; - break L455; - } - } while (0); - if (ab >>> 0 < (c[212] | 0) >>> 0) { - c[212] = ab; - } - S = ab + aa | 0; - Y = 1280; - while (1) { - aj = Y | 0; - if ((c[aj >> 2] | 0) == (S | 0)) { - T = 334; - break; - } - Z = c[Y + 8 >> 2] | 0; - if ((Z | 0) == 0) { - break; - } else { - Y = Z; - } - } - do { - if ((T | 0) == 334) { - if ((c[Y + 12 >> 2] & 8 | 0) != 0) { - break; - } - c[aj >> 2] = ab; - S = Y + 4 | 0; - c[S >> 2] = (c[S >> 2] | 0) + aa; - S = ab + 8 | 0; - if ((S & 7 | 0) == 0) { - ak = 0; - } else { - ak = -S & 7; - } - S = ab + (aa + 8) | 0; - if ((S & 7 | 0) == 0) { - al = 0; - } else { - al = -S & 7; - } - S = ab + (al + aa) | 0; - Z = S; - W = ak + o | 0; - ac = ab + W | 0; - _ = ac; - K = S - (ab + ak) - o | 0; - c[ab + (ak + 4) >> 2] = o | 3; - do { - if ((Z | 0) == (c[214] | 0)) { - J = (c[211] | 0) + K | 0; - c[211] = J; - c[214] = _; - c[ab + (W + 4) >> 2] = J | 1; - } else { - if ((Z | 0) == (c[213] | 0)) { - J = (c[210] | 0) + K | 0; - c[210] = J; - c[213] = _; - c[ab + (W + 4) >> 2] = J | 1; - c[ab + (J + W) >> 2] = J; - break; - } - J = aa + 4 | 0; - X = c[ab + (J + al) >> 2] | 0; - if ((X & 3 | 0) == 1) { - $ = X & -8; - V = X >>> 3; - L500 : do { - if (X >>> 0 < 256) { - U = c[ab + ((al | 8) + aa) >> 2] | 0; - Q = c[ab + (aa + 12 + al) >> 2] | 0; - R = 872 + (V << 1 << 2) | 0; - do { - if ((U | 0) != (R | 0)) { - if (U >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - if ((c[U + 12 >> 2] | 0) == (Z | 0)) { - break; - } - au(); - return 0; - } - } while (0); - if ((Q | 0) == (U | 0)) { - c[208] = c[208] & ~(1 << V); - break; - } - do { - if ((Q | 0) == (R | 0)) { - am = Q + 8 | 0; - } else { - if (Q >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - m = Q + 8 | 0; - if ((c[m >> 2] | 0) == (Z | 0)) { - am = m; - break; - } - au(); - return 0; - } - } while (0); - c[U + 12 >> 2] = Q; - c[am >> 2] = U; - } else { - R = S; - m = c[ab + ((al | 24) + aa) >> 2] | 0; - P = c[ab + (aa + 12 + al) >> 2] | 0; - do { - if ((P | 0) == (R | 0)) { - O = al | 16; - g = ab + (J + O) | 0; - L = c[g >> 2] | 0; - if ((L | 0) == 0) { - e = ab + (O + aa) | 0; - O = c[e >> 2] | 0; - if ((O | 0) == 0) { - an = 0; - break; - } else { - ao = O; - ap = e; - } - } else { - ao = L; - ap = g; - } - while (1) { - g = ao + 20 | 0; - L = c[g >> 2] | 0; - if ((L | 0) != 0) { - ao = L; - ap = g; - continue; - } - g = ao + 16 | 0; - L = c[g >> 2] | 0; - if ((L | 0) == 0) { - break; - } else { - ao = L; - ap = g; - } - } - if (ap >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[ap >> 2] = 0; - an = ao; - break; - } - } else { - g = c[ab + ((al | 8) + aa) >> 2] | 0; - if (g >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - L = g + 12 | 0; - if ((c[L >> 2] | 0) != (R | 0)) { - au(); - return 0; - } - e = P + 8 | 0; - if ((c[e >> 2] | 0) == (R | 0)) { - c[L >> 2] = P; - c[e >> 2] = g; - an = P; - break; - } else { - au(); - return 0; - } - } - } while (0); - if ((m | 0) == 0) { - break; - } - P = ab + (aa + 28 + al) | 0; - U = 1136 + (c[P >> 2] << 2) | 0; - do { - if ((R | 0) == (c[U >> 2] | 0)) { - c[U >> 2] = an; - if ((an | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[P >> 2]); - break L500; - } else { - if (m >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - Q = m + 16 | 0; - if ((c[Q >> 2] | 0) == (R | 0)) { - c[Q >> 2] = an; - } else { - c[m + 20 >> 2] = an; - } - if ((an | 0) == 0) { - break L500; - } - } - } while (0); - if (an >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - c[an + 24 >> 2] = m; - R = al | 16; - P = c[ab + (R + aa) >> 2] | 0; - do { - if ((P | 0) != 0) { - if (P >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[an + 16 >> 2] = P; - c[P + 24 >> 2] = an; - break; - } - } - } while (0); - P = c[ab + (J + R) >> 2] | 0; - if ((P | 0) == 0) { - break; - } - if (P >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[an + 20 >> 2] = P; - c[P + 24 >> 2] = an; - break; - } - } - } while (0); - aq = ab + (($ | al) + aa) | 0; - as = $ + K | 0; - } else { - aq = Z; - as = K; - } - J = aq + 4 | 0; - c[J >> 2] = c[J >> 2] & -2; - c[ab + (W + 4) >> 2] = as | 1; - c[ab + (as + W) >> 2] = as; - J = as >>> 3; - if (as >>> 0 < 256) { - V = J << 1; - X = 872 + (V << 2) | 0; - P = c[208] | 0; - m = 1 << J; - do { - if ((P & m | 0) == 0) { - c[208] = P | m; - at = X; - av = 872 + (V + 2 << 2) | 0; - } else { - J = 872 + (V + 2 << 2) | 0; - U = c[J >> 2] | 0; - if (U >>> 0 >= (c[212] | 0) >>> 0) { - at = U; - av = J; - break; - } - au(); - return 0; - } - } while (0); - c[av >> 2] = _; - c[at + 12 >> 2] = _; - c[ab + (W + 8) >> 2] = at; - c[ab + (W + 12) >> 2] = X; - break; - } - V = ac; - m = as >>> 8; - do { - if ((m | 0) == 0) { - aw = 0; - } else { - if (as >>> 0 > 16777215) { - aw = 31; - break; - } - P = (m + 1048320 | 0) >>> 16 & 8; - $ = m << P; - J = ($ + 520192 | 0) >>> 16 & 4; - U = $ << J; - $ = (U + 245760 | 0) >>> 16 & 2; - Q = 14 - (J | P | $) + (U << $ >>> 15) | 0; - aw = as >>> ((Q + 7 | 0) >>> 0) & 1 | Q << 1; - } - } while (0); - m = 1136 + (aw << 2) | 0; - c[ab + (W + 28) >> 2] = aw; - c[ab + (W + 20) >> 2] = 0; - c[ab + (W + 16) >> 2] = 0; - X = c[209] | 0; - Q = 1 << aw; - if ((X & Q | 0) == 0) { - c[209] = X | Q; - c[m >> 2] = V; - c[ab + (W + 24) >> 2] = m; - c[ab + (W + 12) >> 2] = V; - c[ab + (W + 8) >> 2] = V; - break; - } - if ((aw | 0) == 31) { - ax = 0; - } else { - ax = 25 - (aw >>> 1) | 0; - } - Q = as << ax; - X = c[m >> 2] | 0; - while (1) { - if ((c[X + 4 >> 2] & -8 | 0) == (as | 0)) { - break; - } - ay = X + 16 + (Q >>> 31 << 2) | 0; - m = c[ay >> 2] | 0; - if ((m | 0) == 0) { - T = 407; - break; - } else { - Q = Q << 1; - X = m; - } - } - if ((T | 0) == 407) { - if (ay >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[ay >> 2] = V; - c[ab + (W + 24) >> 2] = X; - c[ab + (W + 12) >> 2] = V; - c[ab + (W + 8) >> 2] = V; - break; - } - } - Q = X + 8 | 0; - m = c[Q >> 2] | 0; - $ = c[212] | 0; - if (X >>> 0 < $ >>> 0) { - au(); - return 0; - } - if (m >>> 0 < $ >>> 0) { - au(); - return 0; - } else { - c[m + 12 >> 2] = V; - c[Q >> 2] = V; - c[ab + (W + 8) >> 2] = m; - c[ab + (W + 12) >> 2] = X; - c[ab + (W + 24) >> 2] = 0; - break; - } - } - } while (0); - n = ab + (ak | 8) | 0; - return n | 0; - } - } while (0); - Y = ad; - W = 1280; - while (1) { - az = c[W >> 2] | 0; - if (az >>> 0 <= Y >>> 0) { - aA = c[W + 4 >> 2] | 0; - aB = az + aA | 0; - if (aB >>> 0 > Y >>> 0) { - break; - } - } - W = c[W + 8 >> 2] | 0; - } - W = az + (aA - 39) | 0; - if ((W & 7 | 0) == 0) { - aC = 0; - } else { - aC = -W & 7; - } - W = az + (aA - 47 + aC) | 0; - ac = W >>> 0 < (ad + 16 | 0) >>> 0 ? Y : W; - W = ac + 8 | 0; - _ = ab + 8 | 0; - if ((_ & 7 | 0) == 0) { - aD = 0; - } else { - aD = -_ & 7; - } - _ = aa - 40 - aD | 0; - c[214] = ab + aD; - c[211] = _; - c[ab + (aD + 4) >> 2] = _ | 1; - c[ab + (aa - 36) >> 2] = 40; - c[215] = c[204]; - c[ac + 4 >> 2] = 27; - c[W >> 2] = c[320]; - c[W + 4 >> 2] = c[1284 >> 2]; - c[W + 8 >> 2] = c[1288 >> 2]; - c[W + 12 >> 2] = c[1292 >> 2]; - c[320] = ab; - c[321] = aa; - c[323] = 0; - c[322] = W; - W = ac + 28 | 0; - c[W >> 2] = 7; - if ((ac + 32 | 0) >>> 0 < aB >>> 0) { - _ = W; - while (1) { - W = _ + 4 | 0; - c[W >> 2] = 7; - if ((_ + 8 | 0) >>> 0 < aB >>> 0) { - _ = W; - } else { - break; - } - } - } - if ((ac | 0) == (Y | 0)) { - break; - } - _ = ac - ad | 0; - W = Y + (_ + 4) | 0; - c[W >> 2] = c[W >> 2] & -2; - c[ad + 4 >> 2] = _ | 1; - c[Y + _ >> 2] = _; - W = _ >>> 3; - if (_ >>> 0 < 256) { - K = W << 1; - Z = 872 + (K << 2) | 0; - S = c[208] | 0; - m = 1 << W; - do { - if ((S & m | 0) == 0) { - c[208] = S | m; - aE = Z; - aF = 872 + (K + 2 << 2) | 0; - } else { - W = 872 + (K + 2 << 2) | 0; - Q = c[W >> 2] | 0; - if (Q >>> 0 >= (c[212] | 0) >>> 0) { - aE = Q; - aF = W; - break; - } - au(); - return 0; - } - } while (0); - c[aF >> 2] = ad; - c[aE + 12 >> 2] = ad; - c[ad + 8 >> 2] = aE; - c[ad + 12 >> 2] = Z; - break; - } - K = ad; - m = _ >>> 8; - do { - if ((m | 0) == 0) { - aG = 0; - } else { - if (_ >>> 0 > 16777215) { - aG = 31; - break; - } - S = (m + 1048320 | 0) >>> 16 & 8; - Y = m << S; - ac = (Y + 520192 | 0) >>> 16 & 4; - W = Y << ac; - Y = (W + 245760 | 0) >>> 16 & 2; - Q = 14 - (ac | S | Y) + (W << Y >>> 15) | 0; - aG = _ >>> ((Q + 7 | 0) >>> 0) & 1 | Q << 1; - } - } while (0); - m = 1136 + (aG << 2) | 0; - c[ad + 28 >> 2] = aG; - c[ad + 20 >> 2] = 0; - c[ad + 16 >> 2] = 0; - Z = c[209] | 0; - Q = 1 << aG; - if ((Z & Q | 0) == 0) { - c[209] = Z | Q; - c[m >> 2] = K; - c[ad + 24 >> 2] = m; - c[ad + 12 >> 2] = ad; - c[ad + 8 >> 2] = ad; - break; - } - if ((aG | 0) == 31) { - aH = 0; - } else { - aH = 25 - (aG >>> 1) | 0; - } - Q = _ << aH; - Z = c[m >> 2] | 0; - while (1) { - if ((c[Z + 4 >> 2] & -8 | 0) == (_ | 0)) { - break; - } - aI = Z + 16 + (Q >>> 31 << 2) | 0; - m = c[aI >> 2] | 0; - if ((m | 0) == 0) { - T = 442; - break; - } else { - Q = Q << 1; - Z = m; - } - } - if ((T | 0) == 442) { - if (aI >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[aI >> 2] = K; - c[ad + 24 >> 2] = Z; - c[ad + 12 >> 2] = ad; - c[ad + 8 >> 2] = ad; - break; - } - } - Q = Z + 8 | 0; - _ = c[Q >> 2] | 0; - m = c[212] | 0; - if (Z >>> 0 < m >>> 0) { - au(); - return 0; - } - if (_ >>> 0 < m >>> 0) { - au(); - return 0; - } else { - c[_ + 12 >> 2] = K; - c[Q >> 2] = K; - c[ad + 8 >> 2] = _; - c[ad + 12 >> 2] = Z; - c[ad + 24 >> 2] = 0; - break; - } - } - } while (0); - ad = c[211] | 0; - if (ad >>> 0 <= o >>> 0) { - break; - } - _ = ad - o | 0; - c[211] = _; - ad = c[214] | 0; - Q = ad; - c[214] = Q + o; - c[Q + (o + 4) >> 2] = _ | 1; - c[ad + 4 >> 2] = o | 3; - n = ad + 8 | 0; - return n | 0; - } - } while (0); - c[(aX() | 0) >> 2] = 12; - n = 0; - return n | 0; -} -function bM(a) { - a = a | 0; - var b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0, M = 0, N = 0, O = 0; - if ((a | 0) == 0) { - return; - } - b = a - 8 | 0; - d = b; - e = c[212] | 0; - if (b >>> 0 < e >>> 0) { - au(); - } - f = c[a - 4 >> 2] | 0; - g = f & 3; - if ((g | 0) == 1) { - au(); - } - h = f & -8; - i = a + (h - 8) | 0; - j = i; - L672 : do { - if ((f & 1 | 0) == 0) { - k = c[b >> 2] | 0; - if ((g | 0) == 0) { - return; - } - l = -8 - k | 0; - m = a + l | 0; - n = m; - o = k + h | 0; - if (m >>> 0 < e >>> 0) { - au(); - } - if ((n | 0) == (c[213] | 0)) { - p = a + (h - 4) | 0; - if ((c[p >> 2] & 3 | 0) != 3) { - q = n; - r = o; - break; - } - c[210] = o; - c[p >> 2] = c[p >> 2] & -2; - c[a + (l + 4) >> 2] = o | 1; - c[i >> 2] = o; - return; - } - p = k >>> 3; - if (k >>> 0 < 256) { - k = c[a + (l + 8) >> 2] | 0; - s = c[a + (l + 12) >> 2] | 0; - t = 872 + (p << 1 << 2) | 0; - do { - if ((k | 0) != (t | 0)) { - if (k >>> 0 < e >>> 0) { - au(); - } - if ((c[k + 12 >> 2] | 0) == (n | 0)) { - break; - } - au(); - } - } while (0); - if ((s | 0) == (k | 0)) { - c[208] = c[208] & ~(1 << p); - q = n; - r = o; - break; - } - do { - if ((s | 0) == (t | 0)) { - u = s + 8 | 0; - } else { - if (s >>> 0 < e >>> 0) { - au(); - } - v = s + 8 | 0; - if ((c[v >> 2] | 0) == (n | 0)) { - u = v; - break; - } - au(); - } - } while (0); - c[k + 12 >> 2] = s; - c[u >> 2] = k; - q = n; - r = o; - break; - } - t = m; - p = c[a + (l + 24) >> 2] | 0; - v = c[a + (l + 12) >> 2] | 0; - do { - if ((v | 0) == (t | 0)) { - w = a + (l + 20) | 0; - x = c[w >> 2] | 0; - if ((x | 0) == 0) { - y = a + (l + 16) | 0; - z = c[y >> 2] | 0; - if ((z | 0) == 0) { - A = 0; - break; - } else { - B = z; - C = y; - } - } else { - B = x; - C = w; - } - while (1) { - w = B + 20 | 0; - x = c[w >> 2] | 0; - if ((x | 0) != 0) { - B = x; - C = w; - continue; - } - w = B + 16 | 0; - x = c[w >> 2] | 0; - if ((x | 0) == 0) { - break; - } else { - B = x; - C = w; - } - } - if (C >>> 0 < e >>> 0) { - au(); - } else { - c[C >> 2] = 0; - A = B; - break; - } - } else { - w = c[a + (l + 8) >> 2] | 0; - if (w >>> 0 < e >>> 0) { - au(); - } - x = w + 12 | 0; - if ((c[x >> 2] | 0) != (t | 0)) { - au(); - } - y = v + 8 | 0; - if ((c[y >> 2] | 0) == (t | 0)) { - c[x >> 2] = v; - c[y >> 2] = w; - A = v; - break; - } else { - au(); - } - } - } while (0); - if ((p | 0) == 0) { - q = n; - r = o; - break; - } - v = a + (l + 28) | 0; - m = 1136 + (c[v >> 2] << 2) | 0; - do { - if ((t | 0) == (c[m >> 2] | 0)) { - c[m >> 2] = A; - if ((A | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[v >> 2]); - q = n; - r = o; - break L672; - } else { - if (p >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - k = p + 16 | 0; - if ((c[k >> 2] | 0) == (t | 0)) { - c[k >> 2] = A; - } else { - c[p + 20 >> 2] = A; - } - if ((A | 0) == 0) { - q = n; - r = o; - break L672; - } - } - } while (0); - if (A >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - c[A + 24 >> 2] = p; - t = c[a + (l + 16) >> 2] | 0; - do { - if ((t | 0) != 0) { - if (t >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[A + 16 >> 2] = t; - c[t + 24 >> 2] = A; - break; - } - } - } while (0); - t = c[a + (l + 20) >> 2] | 0; - if ((t | 0) == 0) { - q = n; - r = o; - break; - } - if (t >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[A + 20 >> 2] = t; - c[t + 24 >> 2] = A; - q = n; - r = o; - break; - } - } else { - q = d; - r = h; - } - } while (0); - d = q; - if (d >>> 0 >= i >>> 0) { - au(); - } - A = a + (h - 4) | 0; - e = c[A >> 2] | 0; - if ((e & 1 | 0) == 0) { - au(); - } - do { - if ((e & 2 | 0) == 0) { - if ((j | 0) == (c[214] | 0)) { - B = (c[211] | 0) + r | 0; - c[211] = B; - c[214] = q; - c[q + 4 >> 2] = B | 1; - if ((q | 0) == (c[213] | 0)) { - c[213] = 0; - c[210] = 0; - } - if (B >>> 0 <= (c[215] | 0) >>> 0) { - return; - } - bS(0) | 0; - return; - } - if ((j | 0) == (c[213] | 0)) { - B = (c[210] | 0) + r | 0; - c[210] = B; - c[213] = q; - c[q + 4 >> 2] = B | 1; - c[d + B >> 2] = B; - return; - } - B = (e & -8) + r | 0; - C = e >>> 3; - L777 : do { - if (e >>> 0 < 256) { - u = c[a + h >> 2] | 0; - g = c[a + (h | 4) >> 2] | 0; - b = 872 + (C << 1 << 2) | 0; - do { - if ((u | 0) != (b | 0)) { - if (u >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - if ((c[u + 12 >> 2] | 0) == (j | 0)) { - break; - } - au(); - } - } while (0); - if ((g | 0) == (u | 0)) { - c[208] = c[208] & ~(1 << C); - break; - } - do { - if ((g | 0) == (b | 0)) { - D = g + 8 | 0; - } else { - if (g >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - f = g + 8 | 0; - if ((c[f >> 2] | 0) == (j | 0)) { - D = f; - break; - } - au(); - } - } while (0); - c[u + 12 >> 2] = g; - c[D >> 2] = u; - } else { - b = i; - f = c[a + (h + 16) >> 2] | 0; - t = c[a + (h | 4) >> 2] | 0; - do { - if ((t | 0) == (b | 0)) { - p = a + (h + 12) | 0; - v = c[p >> 2] | 0; - if ((v | 0) == 0) { - m = a + (h + 8) | 0; - k = c[m >> 2] | 0; - if ((k | 0) == 0) { - E = 0; - break; - } else { - F = k; - G = m; - } - } else { - F = v; - G = p; - } - while (1) { - p = F + 20 | 0; - v = c[p >> 2] | 0; - if ((v | 0) != 0) { - F = v; - G = p; - continue; - } - p = F + 16 | 0; - v = c[p >> 2] | 0; - if ((v | 0) == 0) { - break; - } else { - F = v; - G = p; - } - } - if (G >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[G >> 2] = 0; - E = F; - break; - } - } else { - p = c[a + h >> 2] | 0; - if (p >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - v = p + 12 | 0; - if ((c[v >> 2] | 0) != (b | 0)) { - au(); - } - m = t + 8 | 0; - if ((c[m >> 2] | 0) == (b | 0)) { - c[v >> 2] = t; - c[m >> 2] = p; - E = t; - break; - } else { - au(); - } - } - } while (0); - if ((f | 0) == 0) { - break; - } - t = a + (h + 20) | 0; - u = 1136 + (c[t >> 2] << 2) | 0; - do { - if ((b | 0) == (c[u >> 2] | 0)) { - c[u >> 2] = E; - if ((E | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[t >> 2]); - break L777; - } else { - if (f >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - g = f + 16 | 0; - if ((c[g >> 2] | 0) == (b | 0)) { - c[g >> 2] = E; - } else { - c[f + 20 >> 2] = E; - } - if ((E | 0) == 0) { - break L777; - } - } - } while (0); - if (E >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - c[E + 24 >> 2] = f; - b = c[a + (h + 8) >> 2] | 0; - do { - if ((b | 0) != 0) { - if (b >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[E + 16 >> 2] = b; - c[b + 24 >> 2] = E; - break; - } - } - } while (0); - b = c[a + (h + 12) >> 2] | 0; - if ((b | 0) == 0) { - break; - } - if (b >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[E + 20 >> 2] = b; - c[b + 24 >> 2] = E; - break; - } - } - } while (0); - c[q + 4 >> 2] = B | 1; - c[d + B >> 2] = B; - if ((q | 0) != (c[213] | 0)) { - H = B; - break; - } - c[210] = B; - return; - } else { - c[A >> 2] = e & -2; - c[q + 4 >> 2] = r | 1; - c[d + r >> 2] = r; - H = r; - } - } while (0); - r = H >>> 3; - if (H >>> 0 < 256) { - d = r << 1; - e = 872 + (d << 2) | 0; - A = c[208] | 0; - E = 1 << r; - do { - if ((A & E | 0) == 0) { - c[208] = A | E; - I = e; - J = 872 + (d + 2 << 2) | 0; - } else { - r = 872 + (d + 2 << 2) | 0; - h = c[r >> 2] | 0; - if (h >>> 0 >= (c[212] | 0) >>> 0) { - I = h; - J = r; - break; - } - au(); - } - } while (0); - c[J >> 2] = q; - c[I + 12 >> 2] = q; - c[q + 8 >> 2] = I; - c[q + 12 >> 2] = e; - return; - } - e = q; - I = H >>> 8; - do { - if ((I | 0) == 0) { - K = 0; - } else { - if (H >>> 0 > 16777215) { - K = 31; - break; - } - J = (I + 1048320 | 0) >>> 16 & 8; - d = I << J; - E = (d + 520192 | 0) >>> 16 & 4; - A = d << E; - d = (A + 245760 | 0) >>> 16 & 2; - r = 14 - (E | J | d) + (A << d >>> 15) | 0; - K = H >>> ((r + 7 | 0) >>> 0) & 1 | r << 1; - } - } while (0); - I = 1136 + (K << 2) | 0; - c[q + 28 >> 2] = K; - c[q + 20 >> 2] = 0; - c[q + 16 >> 2] = 0; - r = c[209] | 0; - d = 1 << K; - do { - if ((r & d | 0) == 0) { - c[209] = r | d; - c[I >> 2] = e; - c[q + 24 >> 2] = I; - c[q + 12 >> 2] = q; - c[q + 8 >> 2] = q; - } else { - if ((K | 0) == 31) { - L = 0; - } else { - L = 25 - (K >>> 1) | 0; - } - A = H << L; - J = c[I >> 2] | 0; - while (1) { - if ((c[J + 4 >> 2] & -8 | 0) == (H | 0)) { - break; - } - M = J + 16 + (A >>> 31 << 2) | 0; - E = c[M >> 2] | 0; - if ((E | 0) == 0) { - N = 621; - break; - } else { - A = A << 1; - J = E; - } - } - if ((N | 0) == 621) { - if (M >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[M >> 2] = e; - c[q + 24 >> 2] = J; - c[q + 12 >> 2] = q; - c[q + 8 >> 2] = q; - break; - } - } - A = J + 8 | 0; - B = c[A >> 2] | 0; - E = c[212] | 0; - if (J >>> 0 < E >>> 0) { - au(); - } - if (B >>> 0 < E >>> 0) { - au(); - } else { - c[B + 12 >> 2] = e; - c[A >> 2] = e; - c[q + 8 >> 2] = B; - c[q + 12 >> 2] = J; - c[q + 24 >> 2] = 0; - break; - } - } - } while (0); - q = (c[216] | 0) - 1 | 0; - c[216] = q; - if ((q | 0) == 0) { - O = 1288; - } else { - return; - } - while (1) { - q = c[O >> 2] | 0; - if ((q | 0) == 0) { - break; - } else { - O = q + 8 | 0; - } - } - c[216] = -1; - return; -} -function bN(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0; - do { - if ((a | 0) == 0) { - d = 0; - } else { - e = ad(b, a) | 0; - if ((b | a) >>> 0 <= 65535) { - d = e; - break; - } - d = ((e >>> 0) / (a >>> 0) | 0 | 0) == (b | 0) ? e : -1; - } - } while (0); - b = bL(d) | 0; - if ((b | 0) == 0) { - return b | 0; - } - if ((c[b - 4 >> 2] & 3 | 0) == 0) { - return b | 0; - } - cL(b | 0, 0, d | 0); - return b | 0; -} -function bO(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0; - if ((a | 0) == 0) { - d = bL(b) | 0; - return d | 0; - } - if (b >>> 0 > 4294967231) { - c[(aX() | 0) >> 2] = 12; - d = 0; - return d | 0; - } - if (b >>> 0 < 11) { - e = 16; - } else { - e = b + 11 & -8; - } - f = bT(a - 8 | 0, e) | 0; - if ((f | 0) != 0) { - d = f + 8 | 0; - return d | 0; - } - f = bL(b) | 0; - if ((f | 0) == 0) { - d = 0; - return d | 0; - } - e = c[a - 4 >> 2] | 0; - g = (e & -8) - ((e & 3 | 0) == 0 ? 8 : 4) | 0; - e = g >>> 0 < b >>> 0 ? g : b; - cK(f | 0, a | 0, e) | 0; - bM(a); - d = f; - return d | 0; -} -function bP(a, b) { - a = a | 0; - b = b | 0; - var d = 0; - if ((a | 0) == 0) { - return 0; - } - if (b >>> 0 > 4294967231) { - c[(aX() | 0) >> 2] = 12; - return 0; - } - if (b >>> 0 < 11) { - d = 16; - } else { - d = b + 11 & -8; - } - b = a - 8 | 0; - return ((bT(b, d) | 0) == (b | 0) ? a : 0) | 0; -} -function bQ(a, b) { - a = a | 0; - b = b | 0; - var c = 0; - if (a >>> 0 < 9) { - c = bL(b) | 0; - return c | 0; - } else { - c = bR(a, b) | 0; - return c | 0; - } - return 0; -} -function bR(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0; - d = a >>> 0 < 16 ? 16 : a; - if ((d - 1 & d | 0) == 0) { - e = d; - } else { - a = 16; - while (1) { - if (a >>> 0 < d >>> 0) { - a = a << 1; - } else { - e = a; - break; - } - } - } - if ((-64 - e | 0) >>> 0 <= b >>> 0) { - c[(aX() | 0) >> 2] = 12; - f = 0; - return f | 0; - } - if (b >>> 0 < 11) { - g = 16; - } else { - g = b + 11 & -8; - } - b = bL(e + 12 + g | 0) | 0; - if ((b | 0) == 0) { - f = 0; - return f | 0; - } - a = b - 8 | 0; - d = a; - h = e - 1 | 0; - do { - if ((b & h | 0) == 0) { - i = d; - } else { - j = b + h & -e; - k = j - 8 | 0; - l = a; - if ((k - l | 0) >>> 0 > 15) { - m = k; - } else { - m = j + (e - 8) | 0; - } - j = m; - k = m - l | 0; - l = b - 4 | 0; - n = c[l >> 2] | 0; - o = (n & -8) - k | 0; - if ((n & 3 | 0) == 0) { - c[m >> 2] = (c[a >> 2] | 0) + k; - c[m + 4 >> 2] = o; - i = j; - break; - } else { - n = m + 4 | 0; - c[n >> 2] = o | c[n >> 2] & 1 | 2; - n = m + (o + 4) | 0; - c[n >> 2] = c[n >> 2] | 1; - c[l >> 2] = k | c[l >> 2] & 1 | 2; - l = b + (k - 4) | 0; - c[l >> 2] = c[l >> 2] | 1; - b9(d, k); - i = j; - break; - } - } - } while (0); - d = i + 4 | 0; - b = c[d >> 2] | 0; - do { - if ((b & 3 | 0) != 0) { - m = b & -8; - if (m >>> 0 <= (g + 16 | 0) >>> 0) { - break; - } - a = m - g | 0; - e = i; - c[d >> 2] = g | b & 1 | 2; - c[e + (g | 4) >> 2] = a | 3; - h = e + (m | 4) | 0; - c[h >> 2] = c[h >> 2] | 1; - b9(e + g | 0, a); - } - } while (0); - f = i + 8 | 0; - return f | 0; -} -function bS(a) { - a = a | 0; - var b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0; - do { - if ((c[200] | 0) == 0) { - b = ar(8) | 0; - if ((b - 1 & b | 0) == 0) { - c[202] = b; - c[201] = b; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - return 0; - } - } - } while (0); - if (a >>> 0 >= 4294967232) { - d = 0; - return d | 0; - } - b = c[214] | 0; - if ((b | 0) == 0) { - d = 0; - return d | 0; - } - e = c[211] | 0; - do { - if (e >>> 0 > (a + 40 | 0) >>> 0) { - f = c[202] | 0; - g = ad((((-40 - a - 1 + e + f | 0) >>> 0) / (f >>> 0) | 0) - 1 | 0, f) | 0; - h = b; - i = 1280; - while (1) { - j = c[i >> 2] | 0; - if (j >>> 0 <= h >>> 0) { - if ((j + (c[i + 4 >> 2] | 0) | 0) >>> 0 > h >>> 0) { - k = i; - break; - } - } - j = c[i + 8 >> 2] | 0; - if ((j | 0) == 0) { - k = 0; - break; - } else { - i = j; - } - } - if ((c[k + 12 >> 2] & 8 | 0) != 0) { - break; - } - i = aV(0) | 0; - h = k + 4 | 0; - if ((i | 0) != ((c[k >> 2] | 0) + (c[h >> 2] | 0) | 0)) { - break; - } - j = aV(-(g >>> 0 > 2147483646 ? -2147483648 - f | 0 : g) | 0) | 0; - l = aV(0) | 0; - if (!((j | 0) != -1 & l >>> 0 < i >>> 0)) { - break; - } - j = i - l | 0; - if ((i | 0) == (l | 0)) { - break; - } - c[h >> 2] = (c[h >> 2] | 0) - j; - c[316] = (c[316] | 0) - j; - h = c[214] | 0; - m = (c[211] | 0) - j | 0; - j = h; - n = h + 8 | 0; - if ((n & 7 | 0) == 0) { - o = 0; - } else { - o = -n & 7; - } - n = m - o | 0; - c[214] = j + o; - c[211] = n; - c[j + (o + 4) >> 2] = n | 1; - c[j + (m + 4) >> 2] = 40; - c[215] = c[204]; - d = (i | 0) != (l | 0) | 0; - return d | 0; - } - } while (0); - if ((c[211] | 0) >>> 0 <= (c[215] | 0) >>> 0) { - d = 0; - return d | 0; - } - c[215] = -1; - d = 0; - return d | 0; -} -function bT(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0; - d = a + 4 | 0; - e = c[d >> 2] | 0; - f = e & -8; - g = a; - h = g + f | 0; - i = h; - j = c[212] | 0; - if (g >>> 0 < j >>> 0) { - au(); - return 0; - } - k = e & 3; - if (!((k | 0) != 1 & g >>> 0 < h >>> 0)) { - au(); - return 0; - } - l = g + (f | 4) | 0; - m = c[l >> 2] | 0; - if ((m & 1 | 0) == 0) { - au(); - return 0; - } - if ((k | 0) == 0) { - if (b >>> 0 < 256) { - n = 0; - return n | 0; - } - do { - if (f >>> 0 >= (b + 4 | 0) >>> 0) { - if ((f - b | 0) >>> 0 > c[202] << 1 >>> 0) { - break; - } else { - n = a; - } - return n | 0; - } - } while (0); - n = 0; - return n | 0; - } - if (f >>> 0 >= b >>> 0) { - k = f - b | 0; - if (k >>> 0 <= 15) { - n = a; - return n | 0; - } - c[d >> 2] = e & 1 | b | 2; - c[g + (b + 4) >> 2] = k | 3; - c[l >> 2] = c[l >> 2] | 1; - b9(g + b | 0, k); - n = a; - return n | 0; - } - if ((i | 0) == (c[214] | 0)) { - k = (c[211] | 0) + f | 0; - if (k >>> 0 <= b >>> 0) { - n = 0; - return n | 0; - } - l = k - b | 0; - c[d >> 2] = e & 1 | b | 2; - c[g + (b + 4) >> 2] = l | 1; - c[214] = g + b; - c[211] = l; - n = a; - return n | 0; - } - if ((i | 0) == (c[213] | 0)) { - l = (c[210] | 0) + f | 0; - if (l >>> 0 < b >>> 0) { - n = 0; - return n | 0; - } - k = l - b | 0; - if (k >>> 0 > 15) { - c[d >> 2] = e & 1 | b | 2; - c[g + (b + 4) >> 2] = k | 1; - c[g + l >> 2] = k; - o = g + (l + 4) | 0; - c[o >> 2] = c[o >> 2] & -2; - p = g + b | 0; - q = k; - } else { - c[d >> 2] = e & 1 | l | 2; - e = g + (l + 4) | 0; - c[e >> 2] = c[e >> 2] | 1; - p = 0; - q = 0; - } - c[210] = q; - c[213] = p; - n = a; - return n | 0; - } - if ((m & 2 | 0) != 0) { - n = 0; - return n | 0; - } - p = (m & -8) + f | 0; - if (p >>> 0 < b >>> 0) { - n = 0; - return n | 0; - } - q = p - b | 0; - e = m >>> 3; - L1056 : do { - if (m >>> 0 < 256) { - l = c[g + (f + 8) >> 2] | 0; - k = c[g + (f + 12) >> 2] | 0; - o = 872 + (e << 1 << 2) | 0; - do { - if ((l | 0) != (o | 0)) { - if (l >>> 0 < j >>> 0) { - au(); - return 0; - } - if ((c[l + 12 >> 2] | 0) == (i | 0)) { - break; - } - au(); - return 0; - } - } while (0); - if ((k | 0) == (l | 0)) { - c[208] = c[208] & ~(1 << e); - break; - } - do { - if ((k | 0) == (o | 0)) { - r = k + 8 | 0; - } else { - if (k >>> 0 < j >>> 0) { - au(); - return 0; - } - s = k + 8 | 0; - if ((c[s >> 2] | 0) == (i | 0)) { - r = s; - break; - } - au(); - return 0; - } - } while (0); - c[l + 12 >> 2] = k; - c[r >> 2] = l; - } else { - o = h; - s = c[g + (f + 24) >> 2] | 0; - t = c[g + (f + 12) >> 2] | 0; - do { - if ((t | 0) == (o | 0)) { - u = g + (f + 20) | 0; - v = c[u >> 2] | 0; - if ((v | 0) == 0) { - w = g + (f + 16) | 0; - x = c[w >> 2] | 0; - if ((x | 0) == 0) { - y = 0; - break; - } else { - z = x; - A = w; - } - } else { - z = v; - A = u; - } - while (1) { - u = z + 20 | 0; - v = c[u >> 2] | 0; - if ((v | 0) != 0) { - z = v; - A = u; - continue; - } - u = z + 16 | 0; - v = c[u >> 2] | 0; - if ((v | 0) == 0) { - break; - } else { - z = v; - A = u; - } - } - if (A >>> 0 < j >>> 0) { - au(); - return 0; - } else { - c[A >> 2] = 0; - y = z; - break; - } - } else { - u = c[g + (f + 8) >> 2] | 0; - if (u >>> 0 < j >>> 0) { - au(); - return 0; - } - v = u + 12 | 0; - if ((c[v >> 2] | 0) != (o | 0)) { - au(); - return 0; - } - w = t + 8 | 0; - if ((c[w >> 2] | 0) == (o | 0)) { - c[v >> 2] = t; - c[w >> 2] = u; - y = t; - break; - } else { - au(); - return 0; - } - } - } while (0); - if ((s | 0) == 0) { - break; - } - t = g + (f + 28) | 0; - l = 1136 + (c[t >> 2] << 2) | 0; - do { - if ((o | 0) == (c[l >> 2] | 0)) { - c[l >> 2] = y; - if ((y | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[t >> 2]); - break L1056; - } else { - if (s >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - k = s + 16 | 0; - if ((c[k >> 2] | 0) == (o | 0)) { - c[k >> 2] = y; - } else { - c[s + 20 >> 2] = y; - } - if ((y | 0) == 0) { - break L1056; - } - } - } while (0); - if (y >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } - c[y + 24 >> 2] = s; - o = c[g + (f + 16) >> 2] | 0; - do { - if ((o | 0) != 0) { - if (o >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[y + 16 >> 2] = o; - c[o + 24 >> 2] = y; - break; - } - } - } while (0); - o = c[g + (f + 20) >> 2] | 0; - if ((o | 0) == 0) { - break; - } - if (o >>> 0 < (c[212] | 0) >>> 0) { - au(); - return 0; - } else { - c[y + 20 >> 2] = o; - c[o + 24 >> 2] = y; - break; - } - } - } while (0); - if (q >>> 0 < 16) { - c[d >> 2] = p | c[d >> 2] & 1 | 2; - y = g + (p | 4) | 0; - c[y >> 2] = c[y >> 2] | 1; - n = a; - return n | 0; - } else { - c[d >> 2] = c[d >> 2] & 1 | b | 2; - c[g + (b + 4) >> 2] = q | 3; - d = g + (p | 4) | 0; - c[d >> 2] = c[d >> 2] | 1; - b9(g + b | 0, q); - n = a; - return n | 0; - } - return 0; -} -function bU() { - return c[316] | 0; -} -function bV() { - return c[317] | 0; -} -function bW() { - var a = 0; - a = c[318] | 0; - return ((a | 0) == 0 ? -1 : a) | 0; -} -function bX(a) { - a = a | 0; - var b = 0, d = 0; - if ((a | 0) == -1) { - b = 0; - } else { - d = c[202] | 0; - b = a - 1 + d & -d; - } - c[318] = b; - return b | 0; -} -function bY(a) { - a = a | 0; - var b = 0, d = 0, e = 0; - do { - if ((a | 0) == 0) { - b = 0; - } else { - d = c[a - 4 >> 2] | 0; - e = d & 3; - if ((e | 0) == 1) { - b = 0; - break; - } - b = (d & -8) - ((e | 0) == 0 ? 8 : 4) | 0; - } - } while (0); - return b | 0; -} -function bZ(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0, g = 0; - do { - if ((b | 0) == 8) { - e = bL(d) | 0; - } else { - f = b >>> 2; - if ((b & 3 | 0) != 0 | (f | 0) == 0) { - g = 22; - return g | 0; - } - if ((f + 1073741823 & f | 0) != 0) { - g = 22; - return g | 0; - } - if ((-64 - b | 0) >>> 0 < d >>> 0) { - g = 12; - return g | 0; - } else { - e = bR(b >>> 0 < 16 ? 16 : b, d) | 0; - break; - } - } - } while (0); - if ((e | 0) == 0) { - g = 12; - return g | 0; - } - c[a >> 2] = e; - g = 0; - return g | 0; -} -function b_(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0; - e = i; - i = i + 8 | 0; - f = e | 0; - c[f >> 2] = b; - b = b2(a, f, 3, d) | 0; - i = e; - return b | 0; -} -function b$(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - return b2(a, b, 0, c) | 0; -} -function b0(a) { - a = a | 0; - var b = 0, d = 0, e = 0; - if ((c[200] | 0) != 0) { - b = c[201] | 0; - d = bQ(b, a) | 0; - return d | 0; - } - e = ar(8) | 0; - if ((e - 1 & e | 0) != 0) { - au(); - return 0; - } - c[202] = e; - c[201] = e; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - b = c[201] | 0; - d = bQ(b, a) | 0; - return d | 0; -} -function b1(a) { - a = a | 0; - var b = 0; - do { - if ((c[200] | 0) == 0) { - b = ar(8) | 0; - if ((b - 1 & b | 0) == 0) { - c[202] = b; - c[201] = b; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - return 0; - } - } - } while (0); - b = c[201] | 0; - return bQ(b, a - 1 + b & -b) | 0; -} -function b2(a, b, d, e) { - a = a | 0; - b = b | 0; - d = d | 0; - e = e | 0; - var f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0; - do { - if ((c[200] | 0) == 0) { - f = ar(8) | 0; - if ((f - 1 & f | 0) == 0) { - c[202] = f; - c[201] = f; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - return 0; - } - } - } while (0); - f = (a | 0) == 0; - do { - if ((e | 0) == 0) { - if (f) { - g = bL(0) | 0; - return g | 0; - } else { - h = a << 2; - if (h >>> 0 < 11) { - i = 0; - j = 16; - break; - } - i = 0; - j = h + 11 & -8; - break; - } - } else { - if (f) { - g = e; - } else { - i = e; - j = 0; - break; - } - return g | 0; - } - } while (0); - do { - if ((d & 1 | 0) == 0) { - if (f) { - k = 0; - l = 0; - break; - } else { - m = 0; - n = 0; - } - while (1) { - e = c[b + (n << 2) >> 2] | 0; - if (e >>> 0 < 11) { - o = 16; - } else { - o = e + 11 & -8; - } - e = o + m | 0; - h = n + 1 | 0; - if ((h | 0) == (a | 0)) { - k = 0; - l = e; - break; - } else { - m = e; - n = h; - } - } - } else { - h = c[b >> 2] | 0; - if (h >>> 0 < 11) { - p = 16; - } else { - p = h + 11 & -8; - } - k = p; - l = ad(p, a) | 0; - } - } while (0); - p = bL(j - 4 + l | 0) | 0; - if ((p | 0) == 0) { - g = 0; - return g | 0; - } - n = p - 8 | 0; - m = c[p - 4 >> 2] & -8; - if ((d & 2 | 0) != 0) { - cL(p | 0, 0, -4 - j + m | 0); - } - if ((i | 0) == 0) { - c[p + (l - 4) >> 2] = m - l | 3; - q = p + l | 0; - r = l; - } else { - q = i; - r = m; - } - c[q >> 2] = p; - p = a - 1 | 0; - L1216 : do { - if ((p | 0) == 0) { - s = n; - t = r; - } else { - if ((k | 0) == 0) { - u = n; - v = r; - w = 0; - } else { - a = n; - m = r; - i = 0; - while (1) { - l = m - k | 0; - c[a + 4 >> 2] = k | 3; - j = a + k | 0; - d = i + 1 | 0; - c[q + (d << 2) >> 2] = a + (k + 8); - if ((d | 0) == (p | 0)) { - s = j; - t = l; - break L1216; - } else { - a = j; - m = l; - i = d; - } - } - } - while (1) { - i = c[b + (w << 2) >> 2] | 0; - if (i >>> 0 < 11) { - x = 16; - } else { - x = i + 11 & -8; - } - i = v - x | 0; - c[u + 4 >> 2] = x | 3; - m = u + x | 0; - a = w + 1 | 0; - c[q + (a << 2) >> 2] = u + (x + 8); - if ((a | 0) == (p | 0)) { - s = m; - t = i; - break; - } else { - u = m; - v = i; - w = a; - } - } - } - } while (0); - c[s + 4 >> 2] = t | 3; - g = q; - return g | 0; -} -function b3(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0; - d = a + (b << 2) | 0; - L1229 : do { - if ((b | 0) != 0) { - e = a; - L1230 : while (1) { - f = c[e >> 2] | 0; - L1232 : do { - if ((f | 0) == 0) { - g = e + 4 | 0; - } else { - h = f - 8 | 0; - i = h; - j = f - 4 | 0; - k = c[j >> 2] & -8; - c[e >> 2] = 0; - if (h >>> 0 < (c[212] | 0) >>> 0) { - l = 935; - break L1230; - } - h = c[j >> 2] | 0; - if ((h & 3 | 0) == 1) { - l = 936; - break L1230; - } - m = e + 4 | 0; - n = h - 8 & -8; - do { - if ((m | 0) != (d | 0)) { - if ((c[m >> 2] | 0) != (f + (n + 8) | 0)) { - break; - } - o = (c[f + (n | 4) >> 2] & -8) + k | 0; - c[j >> 2] = h & 1 | o | 2; - p = f + (o - 4) | 0; - c[p >> 2] = c[p >> 2] | 1; - c[m >> 2] = f; - g = m; - break L1232; - } - } while (0); - b9(i, k); - g = m; - } - } while (0); - if ((g | 0) == (d | 0)) { - break L1229; - } else { - e = g; - } - } - if ((l | 0) == 935) { - au(); - return 0; - } else if ((l | 0) == 936) { - au(); - return 0; - } - } - } while (0); - if ((c[211] | 0) >>> 0 <= (c[215] | 0) >>> 0) { - return 0; - } - bS(0) | 0; - return 0; -} -function b4(a) { - a = a | 0; - var b = 0, d = 0; - if ((c[200] | 0) != 0) { - b = bS(a) | 0; - return b | 0; - } - d = ar(8) | 0; - if ((d - 1 & d | 0) != 0) { - au(); - return 0; - } - c[202] = d; - c[201] = d; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - b = bS(a) | 0; - return b | 0; -} -function b5(a) { - a = a | 0; - var b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0; - do { - if ((c[200] | 0) == 0) { - b = ar(8) | 0; - if ((b - 1 & b | 0) == 0) { - c[202] = b; - c[201] = b; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - } - } - } while (0); - b = c[214] | 0; - if ((b | 0) == 0) { - d = 0; - e = 0; - f = 0; - g = 0; - h = 0; - i = 0; - j = 0; - } else { - k = c[211] | 0; - l = k + 40 | 0; - m = 1; - n = l; - o = l; - l = 1280; - while (1) { - p = c[l >> 2] | 0; - q = p + 8 | 0; - if ((q & 7 | 0) == 0) { - r = 0; - } else { - r = -q & 7; - } - q = p + (c[l + 4 >> 2] | 0) | 0; - s = m; - t = n; - u = o; - v = p + r | 0; - while (1) { - if (v >>> 0 >= q >>> 0 | (v | 0) == (b | 0)) { - w = s; - x = t; - y = u; - break; - } - z = c[v + 4 >> 2] | 0; - if ((z | 0) == 7) { - w = s; - x = t; - y = u; - break; - } - A = z & -8; - B = A + u | 0; - if ((z & 3 | 0) == 1) { - C = A + t | 0; - D = s + 1 | 0; - } else { - C = t; - D = s; - } - z = v + A | 0; - if (z >>> 0 < p >>> 0) { - w = D; - x = C; - y = B; - break; - } else { - s = D; - t = C; - u = B; - v = z; - } - } - v = c[l + 8 >> 2] | 0; - if ((v | 0) == 0) { - break; - } else { - m = w; - n = x; - o = y; - l = v; - } - } - l = c[316] | 0; - d = k; - e = y; - f = w; - g = l - y | 0; - h = c[317] | 0; - i = l - x | 0; - j = x; - } - c[a >> 2] = e; - c[a + 4 >> 2] = f; - f = a + 8 | 0; - c[f >> 2] = 0; - c[f + 4 >> 2] = 0; - c[a + 16 >> 2] = g; - c[a + 20 >> 2] = h; - c[a + 24 >> 2] = 0; - c[a + 28 >> 2] = i; - c[a + 32 >> 2] = j; - c[a + 36 >> 2] = d; - return; -} -function b6() { - var a = 0, b = 0, d = 0, e = 0, f = 0, g = 0, h = 0, j = 0, k = 0, l = 0, m = 0, n = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0; - a = i; - do { - if ((c[200] | 0) == 0) { - b = ar(8) | 0; - if ((b - 1 & b | 0) == 0) { - c[202] = b; - c[201] = b; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - } - } - } while (0); - b = c[214] | 0; - if ((b | 0) == 0) { - d = 0; - e = 0; - f = 0; - } else { - g = c[317] | 0; - h = c[316] | 0; - j = h - 40 - (c[211] | 0) | 0; - k = 1280; - while (1) { - l = c[k >> 2] | 0; - m = l + 8 | 0; - if ((m & 7 | 0) == 0) { - n = 0; - } else { - n = -m & 7; - } - m = l + (c[k + 4 >> 2] | 0) | 0; - p = j; - q = l + n | 0; - while (1) { - if (q >>> 0 >= m >>> 0 | (q | 0) == (b | 0)) { - r = p; - break; - } - s = c[q + 4 >> 2] | 0; - if ((s | 0) == 7) { - r = p; - break; - } - t = s & -8; - u = p - ((s & 3 | 0) == 1 ? t : 0) | 0; - s = q + t | 0; - if (s >>> 0 < l >>> 0) { - r = u; - break; - } else { - p = u; - q = s; - } - } - q = c[k + 8 >> 2] | 0; - if ((q | 0) == 0) { - d = r; - e = h; - f = g; - break; - } else { - j = r; - k = q; - } - } - } - av(c[o >> 2] | 0, 520, (y = i, i = i + 8 | 0, c[y >> 2] = f, y) | 0) | 0; - av(c[o >> 2] | 0, 488, (y = i, i = i + 8 | 0, c[y >> 2] = e, y) | 0) | 0; - av(c[o >> 2] | 0, 400, (y = i, i = i + 8 | 0, c[y >> 2] = d, y) | 0) | 0; - i = a; - return; -} -function b7(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0; - do { - if ((c[200] | 0) == 0) { - d = ar(8) | 0; - if ((d - 1 & d | 0) == 0) { - c[202] = d; - c[201] = d; - c[203] = -1; - c[204] = 2097152; - c[205] = 0; - c[319] = 0; - c[200] = (a_(0) | 0) & -16 ^ 1431655768; - break; - } else { - au(); - return 0; - } - } - } while (0); - if ((a | 0) == (-1 | 0)) { - c[204] = b; - e = 1; - return e | 0; - } else if ((a | 0) == (-2 | 0)) { - if ((c[201] | 0) >>> 0 > b >>> 0) { - e = 0; - return e | 0; - } - if ((b - 1 & b | 0) != 0) { - e = 0; - return e | 0; - } - c[202] = b; - e = 1; - return e | 0; - } else if ((a | 0) == (-3 | 0)) { - c[203] = b; - e = 1; - return e | 0; - } else { - e = 0; - return e | 0; - } - return 0; -} -function b8() { - return (F = c[328] | 0, c[328] = F + 0, F) | 0; -} -function b9(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0, g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0; - d = a; - e = d + b | 0; - f = e; - g = c[a + 4 >> 2] | 0; - L1325 : do { - if ((g & 1 | 0) == 0) { - h = c[a >> 2] | 0; - if ((g & 3 | 0) == 0) { - return; - } - i = d + (-h | 0) | 0; - j = i; - k = h + b | 0; - l = c[212] | 0; - if (i >>> 0 < l >>> 0) { - au(); - } - if ((j | 0) == (c[213] | 0)) { - m = d + (b + 4) | 0; - if ((c[m >> 2] & 3 | 0) != 3) { - n = j; - o = k; - break; - } - c[210] = k; - c[m >> 2] = c[m >> 2] & -2; - c[d + (4 - h) >> 2] = k | 1; - c[e >> 2] = k; - return; - } - m = h >>> 3; - if (h >>> 0 < 256) { - p = c[d + (8 - h) >> 2] | 0; - q = c[d + (12 - h) >> 2] | 0; - r = 872 + (m << 1 << 2) | 0; - do { - if ((p | 0) != (r | 0)) { - if (p >>> 0 < l >>> 0) { - au(); - } - if ((c[p + 12 >> 2] | 0) == (j | 0)) { - break; - } - au(); - } - } while (0); - if ((q | 0) == (p | 0)) { - c[208] = c[208] & ~(1 << m); - n = j; - o = k; - break; - } - do { - if ((q | 0) == (r | 0)) { - s = q + 8 | 0; - } else { - if (q >>> 0 < l >>> 0) { - au(); - } - t = q + 8 | 0; - if ((c[t >> 2] | 0) == (j | 0)) { - s = t; - break; - } - au(); - } - } while (0); - c[p + 12 >> 2] = q; - c[s >> 2] = p; - n = j; - o = k; - break; - } - r = i; - m = c[d + (24 - h) >> 2] | 0; - t = c[d + (12 - h) >> 2] | 0; - do { - if ((t | 0) == (r | 0)) { - u = 16 - h | 0; - v = d + (u + 4) | 0; - w = c[v >> 2] | 0; - if ((w | 0) == 0) { - x = d + u | 0; - u = c[x >> 2] | 0; - if ((u | 0) == 0) { - y = 0; - break; - } else { - z = u; - A = x; - } - } else { - z = w; - A = v; - } - while (1) { - v = z + 20 | 0; - w = c[v >> 2] | 0; - if ((w | 0) != 0) { - z = w; - A = v; - continue; - } - v = z + 16 | 0; - w = c[v >> 2] | 0; - if ((w | 0) == 0) { - break; - } else { - z = w; - A = v; - } - } - if (A >>> 0 < l >>> 0) { - au(); - } else { - c[A >> 2] = 0; - y = z; - break; - } - } else { - v = c[d + (8 - h) >> 2] | 0; - if (v >>> 0 < l >>> 0) { - au(); - } - w = v + 12 | 0; - if ((c[w >> 2] | 0) != (r | 0)) { - au(); - } - x = t + 8 | 0; - if ((c[x >> 2] | 0) == (r | 0)) { - c[w >> 2] = t; - c[x >> 2] = v; - y = t; - break; - } else { - au(); - } - } - } while (0); - if ((m | 0) == 0) { - n = j; - o = k; - break; - } - t = d + (28 - h) | 0; - l = 1136 + (c[t >> 2] << 2) | 0; - do { - if ((r | 0) == (c[l >> 2] | 0)) { - c[l >> 2] = y; - if ((y | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[t >> 2]); - n = j; - o = k; - break L1325; - } else { - if (m >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - i = m + 16 | 0; - if ((c[i >> 2] | 0) == (r | 0)) { - c[i >> 2] = y; - } else { - c[m + 20 >> 2] = y; - } - if ((y | 0) == 0) { - n = j; - o = k; - break L1325; - } - } - } while (0); - if (y >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - c[y + 24 >> 2] = m; - r = 16 - h | 0; - t = c[d + r >> 2] | 0; - do { - if ((t | 0) != 0) { - if (t >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[y + 16 >> 2] = t; - c[t + 24 >> 2] = y; - break; - } - } - } while (0); - t = c[d + (r + 4) >> 2] | 0; - if ((t | 0) == 0) { - n = j; - o = k; - break; - } - if (t >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[y + 20 >> 2] = t; - c[t + 24 >> 2] = y; - n = j; - o = k; - break; - } - } else { - n = a; - o = b; - } - } while (0); - a = c[212] | 0; - if (e >>> 0 < a >>> 0) { - au(); - } - y = d + (b + 4) | 0; - z = c[y >> 2] | 0; - do { - if ((z & 2 | 0) == 0) { - if ((f | 0) == (c[214] | 0)) { - A = (c[211] | 0) + o | 0; - c[211] = A; - c[214] = n; - c[n + 4 >> 2] = A | 1; - if ((n | 0) != (c[213] | 0)) { - return; - } - c[213] = 0; - c[210] = 0; - return; - } - if ((f | 0) == (c[213] | 0)) { - A = (c[210] | 0) + o | 0; - c[210] = A; - c[213] = n; - c[n + 4 >> 2] = A | 1; - c[n + A >> 2] = A; - return; - } - A = (z & -8) + o | 0; - s = z >>> 3; - L1424 : do { - if (z >>> 0 < 256) { - g = c[d + (b + 8) >> 2] | 0; - t = c[d + (b + 12) >> 2] | 0; - h = 872 + (s << 1 << 2) | 0; - do { - if ((g | 0) != (h | 0)) { - if (g >>> 0 < a >>> 0) { - au(); - } - if ((c[g + 12 >> 2] | 0) == (f | 0)) { - break; - } - au(); - } - } while (0); - if ((t | 0) == (g | 0)) { - c[208] = c[208] & ~(1 << s); - break; - } - do { - if ((t | 0) == (h | 0)) { - B = t + 8 | 0; - } else { - if (t >>> 0 < a >>> 0) { - au(); - } - m = t + 8 | 0; - if ((c[m >> 2] | 0) == (f | 0)) { - B = m; - break; - } - au(); - } - } while (0); - c[g + 12 >> 2] = t; - c[B >> 2] = g; - } else { - h = e; - m = c[d + (b + 24) >> 2] | 0; - l = c[d + (b + 12) >> 2] | 0; - do { - if ((l | 0) == (h | 0)) { - i = d + (b + 20) | 0; - p = c[i >> 2] | 0; - if ((p | 0) == 0) { - q = d + (b + 16) | 0; - v = c[q >> 2] | 0; - if ((v | 0) == 0) { - C = 0; - break; - } else { - D = v; - E = q; - } - } else { - D = p; - E = i; - } - while (1) { - i = D + 20 | 0; - p = c[i >> 2] | 0; - if ((p | 0) != 0) { - D = p; - E = i; - continue; - } - i = D + 16 | 0; - p = c[i >> 2] | 0; - if ((p | 0) == 0) { - break; - } else { - D = p; - E = i; - } - } - if (E >>> 0 < a >>> 0) { - au(); - } else { - c[E >> 2] = 0; - C = D; - break; - } - } else { - i = c[d + (b + 8) >> 2] | 0; - if (i >>> 0 < a >>> 0) { - au(); - } - p = i + 12 | 0; - if ((c[p >> 2] | 0) != (h | 0)) { - au(); - } - q = l + 8 | 0; - if ((c[q >> 2] | 0) == (h | 0)) { - c[p >> 2] = l; - c[q >> 2] = i; - C = l; - break; - } else { - au(); - } - } - } while (0); - if ((m | 0) == 0) { - break; - } - l = d + (b + 28) | 0; - g = 1136 + (c[l >> 2] << 2) | 0; - do { - if ((h | 0) == (c[g >> 2] | 0)) { - c[g >> 2] = C; - if ((C | 0) != 0) { - break; - } - c[209] = c[209] & ~(1 << c[l >> 2]); - break L1424; - } else { - if (m >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - t = m + 16 | 0; - if ((c[t >> 2] | 0) == (h | 0)) { - c[t >> 2] = C; - } else { - c[m + 20 >> 2] = C; - } - if ((C | 0) == 0) { - break L1424; - } - } - } while (0); - if (C >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - c[C + 24 >> 2] = m; - h = c[d + (b + 16) >> 2] | 0; - do { - if ((h | 0) != 0) { - if (h >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[C + 16 >> 2] = h; - c[h + 24 >> 2] = C; - break; - } - } - } while (0); - h = c[d + (b + 20) >> 2] | 0; - if ((h | 0) == 0) { - break; - } - if (h >>> 0 < (c[212] | 0) >>> 0) { - au(); - } else { - c[C + 20 >> 2] = h; - c[h + 24 >> 2] = C; - break; - } - } - } while (0); - c[n + 4 >> 2] = A | 1; - c[n + A >> 2] = A; - if ((n | 0) != (c[213] | 0)) { - F = A; - break; - } - c[210] = A; - return; - } else { - c[y >> 2] = z & -2; - c[n + 4 >> 2] = o | 1; - c[n + o >> 2] = o; - F = o; - } - } while (0); - o = F >>> 3; - if (F >>> 0 < 256) { - z = o << 1; - y = 872 + (z << 2) | 0; - C = c[208] | 0; - b = 1 << o; - do { - if ((C & b | 0) == 0) { - c[208] = C | b; - G = y; - H = 872 + (z + 2 << 2) | 0; - } else { - o = 872 + (z + 2 << 2) | 0; - d = c[o >> 2] | 0; - if (d >>> 0 >= (c[212] | 0) >>> 0) { - G = d; - H = o; - break; - } - au(); - } - } while (0); - c[H >> 2] = n; - c[G + 12 >> 2] = n; - c[n + 8 >> 2] = G; - c[n + 12 >> 2] = y; - return; - } - y = n; - G = F >>> 8; - do { - if ((G | 0) == 0) { - I = 0; - } else { - if (F >>> 0 > 16777215) { - I = 31; - break; - } - H = (G + 1048320 | 0) >>> 16 & 8; - z = G << H; - b = (z + 520192 | 0) >>> 16 & 4; - C = z << b; - z = (C + 245760 | 0) >>> 16 & 2; - o = 14 - (b | H | z) + (C << z >>> 15) | 0; - I = F >>> ((o + 7 | 0) >>> 0) & 1 | o << 1; - } - } while (0); - G = 1136 + (I << 2) | 0; - c[n + 28 >> 2] = I; - c[n + 20 >> 2] = 0; - c[n + 16 >> 2] = 0; - o = c[209] | 0; - z = 1 << I; - if ((o & z | 0) == 0) { - c[209] = o | z; - c[G >> 2] = y; - c[n + 24 >> 2] = G; - c[n + 12 >> 2] = n; - c[n + 8 >> 2] = n; - return; - } - if ((I | 0) == 31) { - J = 0; - } else { - J = 25 - (I >>> 1) | 0; - } - I = F << J; - J = c[G >> 2] | 0; - while (1) { - if ((c[J + 4 >> 2] & -8 | 0) == (F | 0)) { - break; - } - K = J + 16 + (I >>> 31 << 2) | 0; - G = c[K >> 2] | 0; - if ((G | 0) == 0) { - L = 1120; - break; - } else { - I = I << 1; - J = G; - } - } - if ((L | 0) == 1120) { - if (K >>> 0 < (c[212] | 0) >>> 0) { - au(); - } - c[K >> 2] = y; - c[n + 24 >> 2] = J; - c[n + 12 >> 2] = n; - c[n + 8 >> 2] = n; - return; - } - K = J + 8 | 0; - L = c[K >> 2] | 0; - I = c[212] | 0; - if (J >>> 0 < I >>> 0) { - au(); - } - if (L >>> 0 < I >>> 0) { - au(); - } - c[L + 12 >> 2] = y; - c[K >> 2] = y; - c[n + 8 >> 2] = L; - c[n + 12 >> 2] = J; - c[n + 24 >> 2] = 0; - return; -} -function ca(a) { - a = a | 0; - var b = 0, d = 0, e = 0; - b = (a | 0) == 0 ? 1 : a; - while (1) { - d = bL(b) | 0; - if ((d | 0) != 0) { - e = 1164; - break; - } - a = (F = c[328] | 0, c[328] = F + 0, F); - if ((a | 0) == 0) { - break; - } - a5[a & 1](); - } - if ((e | 0) == 1164) { - return d | 0; - } - d = aJ(4) | 0; - c[d >> 2] = 560; - as(d | 0, 688, 6); - return 0; -} -function cb(a, b) { - a = a | 0; - b = b | 0; - return ca(a) | 0; -} -function cc(a) { - a = a | 0; - return; -} -function cd(a) { - a = a | 0; - return 360 | 0; -} -function ce(a) { - a = a | 0; - return 448 | 0; -} -function cf(a) { - a = a | 0; - return (F = c[328] | 0, c[328] = a, F) | 0; -} -function cg(a) { - a = a | 0; - c[a >> 2] = 560; - return; -} -function ch(a) { - a = a | 0; - c[a >> 2] = 592; - return; -} -function ci(a) { - a = a | 0; - if ((a | 0) != 0) { - bM(a); - } - return; -} -function cj(a, b) { - a = a | 0; - b = b | 0; - ci(a); - return; -} -function ck(a) { - a = a | 0; - ci(a); - return; -} -function cl(a, b) { - a = a | 0; - b = b | 0; - ck(a); - return; -} -function cm(a) { - a = a | 0; - ci(a); - return; -} -function cn(a) { - a = a | 0; - ci(a); - return; -} -function co(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - return cp(a, b, c, 0, 0, 0) | 0; -} -function cp(b, d, e, f, g, h) { - b = b | 0; - d = d | 0; - e = e | 0; - f = f | 0; - g = g | 0; - h = h | 0; - var j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0, M = 0, N = 0, O = 0, P = 0, Q = 0, R = 0, S = 0, T = 0, U = 0, V = 0, W = 0, X = 0, Y = 0, Z = 0, _ = 0, $ = 0, aa = 0, ab = 0, ac = 0, ad = 0; - j = i; - if ((e | 0) == 0) { - k = -1; - i = j; - return k | 0; - } - l = c[44] | 0; - if ((l | 0) == 0) { - c[196] = 1; - c[44] = 1; - m = 1; - n = 1; - o = 1190; - } else { - p = c[196] | 0; - q = c[74] | 0; - if ((q | 0) == -1 | (p | 0) != 0) { - m = p; - n = l; - o = 1190; - } else { - r = q; - s = p; - t = l; - } - } - if ((o | 0) == 1190) { - l = (aP(344) | 0) != 0 | 0; - c[74] = l; - r = l; - s = m; - t = n; - } - n = a[e] | 0; - if (n << 24 >> 24 == 45) { - u = h | 2; - o = 1194; - } else { - m = (r | 0) != 0 | n << 24 >> 24 == 43 ? h & -2 : h; - if (n << 24 >> 24 == 43) { - u = m; - o = 1194; - } else { - v = e; - w = m; - } - } - if ((o | 0) == 1194) { - v = e + 1 | 0; - w = u; - } - c[198] = 0; - if ((s | 0) == 0) { - x = t; - o = 1198; - } else { - c[50] = -1; - c[48] = -1; - z = t; - A = s; - o = 1197; - } - while (1) { - if ((o | 0) == 1197) { - o = 0; - if ((A | 0) == 0) { - x = z; - o = 1198; - continue; - } else { - B = z; - } - } else if ((o | 0) == 1198) { - o = 0; - s = c[40] | 0; - if ((a[s] | 0) == 0) { - B = x; - } else { - C = s; - D = x; - break; - } - } - c[196] = 0; - if ((B | 0) >= (b | 0)) { - o = 1200; - break; - } - E = d + (B << 2) | 0; - F = c[E >> 2] | 0; - c[40] = F; - if ((a[F] | 0) == 45) { - G = F + 1 | 0; - H = a[G] | 0; - if (H << 24 >> 24 != 0) { - o = 1232; - break; - } - if ((aB(v | 0, 45) | 0) != 0) { - o = 1232; - break; - } - } - c[40] = 824; - if ((w & 2 | 0) != 0) { - o = 1217; - break; - } - if ((w & 1 | 0) == 0) { - k = -1; - o = 1298; - break; - } - s = c[48] | 0; - do { - if ((s | 0) == -1) { - c[48] = B; - I = B; - J = 0; - } else { - t = c[50] | 0; - if ((t | 0) == -1) { - I = B; - J = 0; - break; - } - u = t - s | 0; - e = B - t | 0; - m = (u | 0) % (e | 0) | 0; - if ((m | 0) == 0) { - K = e; - } else { - n = e; - h = m; - while (1) { - m = (n | 0) % (h | 0) | 0; - if ((m | 0) == 0) { - K = h; - break; - } else { - n = h; - h = m; - } - } - } - h = (B - s | 0) / (K | 0) | 0; - do { - if ((K | 0) > 0) { - n = -u | 0; - if ((h | 0) > 0) { - L = 0; - } else { - M = B; - N = t; - O = s; - P = 0; - break; - } - do { - m = L + t | 0; - r = d + (m << 2) | 0; - l = 0; - p = m; - m = c[r >> 2] | 0; - while (1) { - q = ((p | 0) < (t | 0) ? e : n) + p | 0; - Q = d + (q << 2) | 0; - R = c[Q >> 2] | 0; - c[Q >> 2] = m; - c[r >> 2] = R; - Q = l + 1 | 0; - if ((Q | 0) < (h | 0)) { - l = Q; - p = q; - m = R; - } else { - break; - } - } - L = L + 1 | 0; - } while ((L | 0) < (K | 0)); - M = c[44] | 0; - N = c[50] | 0; - O = c[48] | 0; - P = c[196] | 0; - } else { - M = B; - N = t; - O = s; - P = 0; - } - } while (0); - c[48] = M - N + O; - c[50] = -1; - I = M; - J = P; - } - } while (0); - s = I + 1 | 0; - c[44] = s; - z = s; - A = J; - o = 1197; - } - do { - if ((o | 0) == 1298) { - i = j; - return k | 0; - } else if ((o | 0) == 1232) { - J = c[48] | 0; - A = c[50] | 0; - if ((J | 0) != -1 & (A | 0) == -1) { - c[50] = B; - S = a[G] | 0; - T = B; - } else { - S = H; - T = A; - } - if (S << 24 >> 24 == 0) { - C = F; - D = B; - break; - } - c[40] = G; - if ((a[G] | 0) != 45) { - C = G; - D = B; - break; - } - if ((a[F + 2 | 0] | 0) != 0) { - C = G; - D = B; - break; - } - A = B + 1 | 0; - c[44] = A; - c[40] = 824; - if ((T | 0) != -1) { - z = T - J | 0; - I = A - T | 0; - P = (z | 0) % (I | 0) | 0; - if ((P | 0) == 0) { - U = I; - } else { - M = I; - O = P; - while (1) { - P = (M | 0) % (O | 0) | 0; - if ((P | 0) == 0) { - U = O; - break; - } else { - M = O; - O = P; - } - } - } - O = (A - J | 0) / (U | 0) | 0; - do { - if ((U | 0) > 0) { - M = -z | 0; - if ((O | 0) > 0) { - V = 0; - } else { - W = T; - X = J; - Y = A; - break; - } - do { - P = V + T | 0; - N = d + (P << 2) | 0; - K = 0; - L = P; - P = c[N >> 2] | 0; - while (1) { - x = ((L | 0) < (T | 0) ? I : M) + L | 0; - s = d + (x << 2) | 0; - t = c[s >> 2] | 0; - c[s >> 2] = P; - c[N >> 2] = t; - s = K + 1 | 0; - if ((s | 0) < (O | 0)) { - K = s; - L = x; - P = t; - } else { - break; - } - } - V = V + 1 | 0; - } while ((V | 0) < (U | 0)); - W = c[50] | 0; - X = c[48] | 0; - Y = c[44] | 0; - } else { - W = T; - X = J; - Y = A; - } - } while (0); - c[44] = X - W + Y; - } - c[50] = -1; - c[48] = -1; - k = -1; - i = j; - return k | 0; - } else if ((o | 0) == 1200) { - c[40] = 824; - A = c[50] | 0; - J = c[48] | 0; - do { - if ((A | 0) == -1) { - if ((J | 0) == -1) { - break; - } - c[44] = J; - } else { - O = A - J | 0; - I = B - A | 0; - z = (O | 0) % (I | 0) | 0; - if ((z | 0) == 0) { - Z = I; - } else { - M = I; - P = z; - while (1) { - z = (M | 0) % (P | 0) | 0; - if ((z | 0) == 0) { - Z = P; - break; - } else { - M = P; - P = z; - } - } - } - P = (B - J | 0) / (Z | 0) | 0; - do { - if ((Z | 0) > 0) { - M = -O | 0; - if ((P | 0) > 0) { - _ = 0; - } else { - $ = A; - aa = J; - ab = B; - break; - } - do { - z = _ + A | 0; - L = d + (z << 2) | 0; - K = 0; - N = z; - z = c[L >> 2] | 0; - while (1) { - t = ((N | 0) < (A | 0) ? I : M) + N | 0; - x = d + (t << 2) | 0; - s = c[x >> 2] | 0; - c[x >> 2] = z; - c[L >> 2] = s; - x = K + 1 | 0; - if ((x | 0) < (P | 0)) { - K = x; - N = t; - z = s; - } else { - break; - } - } - _ = _ + 1 | 0; - } while ((_ | 0) < (Z | 0)); - $ = c[50] | 0; - aa = c[48] | 0; - ab = c[44] | 0; - } else { - $ = A; - aa = J; - ab = B; - } - } while (0); - c[44] = aa - $ + ab; - } - } while (0); - c[50] = -1; - c[48] = -1; - k = -1; - i = j; - return k | 0; - } else if ((o | 0) == 1217) { - c[44] = B + 1; - c[198] = c[E >> 2]; - k = 1; - i = j; - return k | 0; - } - } while (0); - E = (f | 0) != 0; - L1659 : do { - if (E) { - if ((C | 0) == (c[d + (D << 2) >> 2] | 0)) { - ac = C; - break; - } - B = a[C] | 0; - do { - if (B << 24 >> 24 == 45) { - c[40] = C + 1; - ad = 0; - } else { - if ((w & 4 | 0) == 0) { - ac = C; - break L1659; - } - if (B << 24 >> 24 == 58) { - ad = 0; - break; - } - ad = (aB(v | 0, B << 24 >> 24 | 0) | 0) != 0 | 0; - } - } while (0); - B = cv(d, v, f, g, ad) | 0; - if ((B | 0) == -1) { - ac = c[40] | 0; - break; - } - c[40] = 824; - k = B; - i = j; - return k | 0; - } else { - ac = C; - } - } while (0); - C = ac + 1 | 0; - c[40] = C; - ad = a[ac] | 0; - ac = ad << 24 >> 24; - if ((ad << 24 >> 24 | 0) == 45) { - if ((a[C] | 0) == 0) { - o = 1260; - } - } else if ((ad << 24 >> 24 | 0) == 58) { - o = 1263; - } else { - o = 1260; - } - do { - if ((o | 0) == 1260) { - w = aB(v | 0, ac | 0) | 0; - if ((w | 0) == 0) { - if (ad << 24 >> 24 != 45) { - o = 1263; - break; - } - if ((a[C] | 0) == 0) { - k = -1; - } else { - break; - } - i = j; - return k | 0; - } - D = a[w + 1 | 0] | 0; - if (E & ad << 24 >> 24 == 87 & D << 24 >> 24 == 59) { - do { - if ((a[C] | 0) == 0) { - B = (c[44] | 0) + 1 | 0; - c[44] = B; - if ((B | 0) < (b | 0)) { - c[40] = c[d + (B << 2) >> 2]; - break; - } - c[40] = 824; - do { - if ((c[46] | 0) != 0) { - if ((a[v] | 0) == 58) { - break; - } - cx(48, (y = i, i = i + 8 | 0, c[y >> 2] = ac, y) | 0); - } - } while (0); - c[42] = ac; - k = (a[v] | 0) == 58 ? 58 : 63; - i = j; - return k | 0; - } - } while (0); - B = cv(d, v, f, g, 0) | 0; - c[40] = 824; - k = B; - i = j; - return k | 0; - } - if (D << 24 >> 24 != 58) { - if ((a[C] | 0) != 0) { - k = ac; - i = j; - return k | 0; - } - c[44] = (c[44] | 0) + 1; - k = ac; - i = j; - return k | 0; - } - c[198] = 0; - do { - if ((a[C] | 0) == 0) { - if ((a[w + 2 | 0] | 0) == 58) { - break; - } - B = (c[44] | 0) + 1 | 0; - c[44] = B; - if ((B | 0) < (b | 0)) { - c[198] = c[d + (B << 2) >> 2]; - break; - } - c[40] = 824; - do { - if ((c[46] | 0) != 0) { - if ((a[v] | 0) == 58) { - break; - } - cx(48, (y = i, i = i + 8 | 0, c[y >> 2] = ac, y) | 0); - } - } while (0); - c[42] = ac; - k = (a[v] | 0) == 58 ? 58 : 63; - i = j; - return k | 0; - } else { - c[198] = C; - } - } while (0); - c[40] = 824; - c[44] = (c[44] | 0) + 1; - k = ac; - i = j; - return k | 0; - } - } while (0); - do { - if ((o | 0) == 1263) { - if ((a[C] | 0) != 0) { - break; - } - c[44] = (c[44] | 0) + 1; - } - } while (0); - do { - if ((c[46] | 0) != 0) { - if ((a[v] | 0) == 58) { - break; - } - cx(272, (y = i, i = i + 8 | 0, c[y >> 2] = ac, y) | 0); - } - } while (0); - c[42] = ac; - k = 63; - i = j; - return k | 0; -} -function cq(a, b, c, d, e) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - e = e | 0; - return cp(a, b, c, d, e, 1) | 0; -} -function cr(a, b, c, d, e) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - e = e | 0; - return cp(a, b, c, d, e, 5) | 0; -} -function cs(a) { - a = a | 0; - return ca(a) | 0; -} -function ct(a, b) { - a = a | 0; - b = b | 0; - return cs(a) | 0; -} -function cu() { - var a = 0; - a = aJ(4) | 0; - c[a >> 2] = 560; - as(a | 0, 688, 6); -} -function cv(b, d, e, f, g) { - b = b | 0; - d = d | 0; - e = e | 0; - f = f | 0; - g = g | 0; - var h = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, z = 0; - h = i; - j = c[40] | 0; - k = c[44] | 0; - l = k + 1 | 0; - c[44] = l; - m = aB(j | 0, 61) | 0; - if ((m | 0) == 0) { - n = cM(j | 0) | 0; - o = 0; - } else { - n = m - j | 0; - o = m + 1 | 0; - } - m = c[e >> 2] | 0; - L1739 : do { - if ((m | 0) != 0) { - L1741 : do { - if ((g | 0) != 0 & (n | 0) == 1) { - p = 0; - q = m; - while (1) { - if ((a[j] | 0) == (a[q] | 0)) { - if ((cM(q | 0) | 0) == 1) { - r = p; - break L1741; - } - } - p = p + 1 | 0; - q = c[e + (p << 4) >> 2] | 0; - if ((q | 0) == 0) { - break L1739; - } - } - } else { - q = 0; - p = -1; - s = m; - while (1) { - if ((ap(j | 0, s | 0, n | 0) | 0) == 0) { - if ((cM(s | 0) | 0) == (n | 0)) { - r = q; - break L1741; - } - if ((p | 0) == -1) { - t = q; - } else { - break; - } - } else { - t = p; - } - u = q + 1 | 0; - v = c[e + (u << 4) >> 2] | 0; - if ((v | 0) == 0) { - r = t; - break L1741; - } else { - q = u; - p = t; - s = v; - } - } - do { - if ((c[46] | 0) != 0) { - if ((a[d] | 0) == 58) { - break; - } - cx(304, (y = i, i = i + 16 | 0, c[y >> 2] = n, c[y + 8 >> 2] = j, y) | 0); - } - } while (0); - c[42] = 0; - w = 63; - i = h; - return w | 0; - } - } while (0); - if ((r | 0) == -1) { - break; - } - s = e + (r << 4) + 4 | 0; - p = c[s >> 2] | 0; - q = (o | 0) == 0; - if (!((p | 0) != 0 | q)) { - do { - if ((c[46] | 0) != 0) { - if ((a[d] | 0) == 58) { - break; - } - cx(208, (y = i, i = i + 16 | 0, c[y >> 2] = n, c[y + 8 >> 2] = j, y) | 0); - } - } while (0); - if ((c[e + (r << 4) + 8 >> 2] | 0) == 0) { - x = c[e + (r << 4) + 12 >> 2] | 0; - } else { - x = 0; - } - c[42] = x; - w = (a[d] | 0) == 58 ? 58 : 63; - i = h; - return w | 0; - } - do { - if ((p - 1 | 0) >>> 0 < 2) { - if (!q) { - c[198] = o; - break; - } - if ((p | 0) != 1) { - break; - } - c[44] = k + 2; - c[198] = c[b + (l << 2) >> 2]; - } - } while (0); - if (!((c[s >> 2] | 0) == 1 & (c[198] | 0) == 0)) { - if ((f | 0) != 0) { - c[f >> 2] = r; - } - p = c[e + (r << 4) + 8 >> 2] | 0; - q = c[e + (r << 4) + 12 >> 2] | 0; - if ((p | 0) == 0) { - w = q; - i = h; - return w | 0; - } - c[p >> 2] = q; - w = 0; - i = h; - return w | 0; - } - do { - if ((c[46] | 0) != 0) { - if ((a[d] | 0) == 58) { - break; - } - cx(8, (y = i, i = i + 8 | 0, c[y >> 2] = j, y) | 0); - } - } while (0); - if ((c[e + (r << 4) + 8 >> 2] | 0) == 0) { - z = c[e + (r << 4) + 12 >> 2] | 0; - } else { - z = 0; - } - c[42] = z; - c[44] = (c[44] | 0) - 1; - w = (a[d] | 0) == 58 ? 58 : 63; - i = h; - return w | 0; - } - } while (0); - if ((g | 0) != 0) { - c[44] = k; - w = -1; - i = h; - return w | 0; - } - do { - if ((c[46] | 0) != 0) { - if ((a[d] | 0) == 58) { - break; - } - cx(248, (y = i, i = i + 8 | 0, c[y >> 2] = j, y) | 0); - } - } while (0); - c[42] = 0; - w = 63; - i = h; - return w | 0; -} -function cw(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0; - d = i; - i = i + 16 | 0; - e = d | 0; - f = e; - c[f >> 2] = b; - c[f + 4 >> 2] = 0; - cy(a, e | 0); - i = d; - return; -} -function cx(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0; - d = i; - i = i + 16 | 0; - e = d | 0; - f = e; - c[f >> 2] = b; - c[f + 4 >> 2] = 0; - cz(a, e | 0); - i = d; - return; -} -function cy(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0, f = 0; - d = i; - e = c[(aX() | 0) >> 2] | 0; - f = c[r >> 2] | 0; - av(c[o >> 2] | 0, 432, (y = i, i = i + 8 | 0, c[y >> 2] = f, y) | 0) | 0; - if ((a | 0) != 0) { - f = c[o >> 2] | 0; - aQ(f | 0, a | 0, b | 0) | 0; - b = c[o >> 2] | 0; - aE(472, 2, 1, b | 0) | 0; - } - b = c[o >> 2] | 0; - a = at(e | 0) | 0; - av(b | 0, 384, (y = i, i = i + 8 | 0, c[y >> 2] = a, y) | 0) | 0; - i = d; - return; -} -function cz(a, b) { - a = a | 0; - b = b | 0; - var d = 0, e = 0; - d = i; - e = c[r >> 2] | 0; - av(c[o >> 2] | 0, 376, (y = i, i = i + 8 | 0, c[y >> 2] = e, y) | 0) | 0; - if ((a | 0) != 0) { - e = c[o >> 2] | 0; - aQ(e | 0, a | 0, b | 0) | 0; - } - aC(10, c[o >> 2] | 0) | 0; - i = d; - return; -} -function cA(b, d) { - b = b | 0; - d = d | 0; - var e = 0, f = 0, g = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0.0, r = 0, s = 0, t = 0, u = 0, v = 0.0, w = 0, x = 0, y = 0, z = 0.0, A = 0.0, B = 0, C = 0, D = 0, E = 0.0, F = 0, G = 0, H = 0, I = 0, J = 0, K = 0, L = 0, M = 0, N = 0.0, O = 0, P = 0, Q = 0.0, R = 0.0, S = 0.0; - e = b; - while (1) { - f = e + 1 | 0; - if ((aK(a[e] | 0) | 0) == 0) { - break; - } else { - e = f; - } - } - g = a[e] | 0; - if ((g << 24 >> 24 | 0) == 45) { - i = f; - j = 1; - } else if ((g << 24 >> 24 | 0) == 43) { - i = f; - j = 0; - } else { - i = e; - j = 0; - } - e = -1; - f = 0; - g = i; - while (1) { - k = a[g] | 0; - if (((k << 24 >> 24) - 48 | 0) >>> 0 < 10) { - l = e; - } else { - if (k << 24 >> 24 != 46 | (e | 0) > -1) { - break; - } else { - l = f; - } - } - e = l; - f = f + 1 | 0; - g = g + 1 | 0; - } - l = g + (-f | 0) | 0; - i = (e | 0) < 0; - m = ((i ^ 1) << 31 >> 31) + f | 0; - n = (m | 0) > 18; - o = (n ? -18 : -m | 0) + (i ? f : e) | 0; - e = n ? 18 : m; - do { - if ((e | 0) == 0) { - p = b; - q = 0.0; - } else { - if ((e | 0) > 9) { - m = l; - n = e; - f = 0; - while (1) { - i = a[m] | 0; - r = m + 1 | 0; - if (i << 24 >> 24 == 46) { - s = a[r] | 0; - t = m + 2 | 0; - } else { - s = i; - t = r; - } - u = (f * 10 | 0) - 48 + (s << 24 >> 24) | 0; - r = n - 1 | 0; - if ((r | 0) > 9) { - m = t; - n = r; - f = u; - } else { - break; - } - } - v = +(u | 0) * 1.0e9; - w = 9; - x = t; - y = 1393; - } else { - if ((e | 0) > 0) { - v = 0.0; - w = e; - x = l; - y = 1393; - } else { - z = 0.0; - A = 0.0; - } - } - if ((y | 0) == 1393) { - f = x; - n = w; - m = 0; - while (1) { - r = a[f] | 0; - i = f + 1 | 0; - if (r << 24 >> 24 == 46) { - B = a[i] | 0; - C = f + 2 | 0; - } else { - B = r; - C = i; - } - D = (m * 10 | 0) - 48 + (B << 24 >> 24) | 0; - i = n - 1 | 0; - if ((i | 0) > 0) { - f = C; - n = i; - m = D; - } else { - break; - } - } - z = +(D | 0); - A = v; - } - E = A + z; - do { - if ((k << 24 >> 24 | 0) == 69 | (k << 24 >> 24 | 0) == 101) { - m = g + 1 | 0; - n = a[m] | 0; - if ((n << 24 >> 24 | 0) == 43) { - F = g + 2 | 0; - G = 0; - } else if ((n << 24 >> 24 | 0) == 45) { - F = g + 2 | 0; - G = 1; - } else { - F = m; - G = 0; - } - m = a[F] | 0; - if (((m << 24 >> 24) - 48 | 0) >>> 0 < 10) { - H = F; - I = 0; - J = m; - } else { - K = 0; - L = F; - M = G; - break; - } - while (1) { - m = (I * 10 | 0) - 48 + (J << 24 >> 24) | 0; - n = H + 1 | 0; - f = a[n] | 0; - if (((f << 24 >> 24) - 48 | 0) >>> 0 < 10) { - H = n; - I = m; - J = f; - } else { - K = m; - L = n; - M = G; - break; - } - } - } else { - K = 0; - L = g; - M = 0; - } - } while (0); - n = o + ((M | 0) == 0 ? K : -K | 0) | 0; - m = (n | 0) < 0 ? -n | 0 : n; - if ((m | 0) > 511) { - c[(aX() | 0) >> 2] = 34; - N = 1.0; - O = 88; - P = 511; - y = 1410; - } else { - if ((m | 0) == 0) { - Q = 1.0; - } else { - N = 1.0; - O = 88; - P = m; - y = 1410; - } - } - if ((y | 0) == 1410) { - while (1) { - y = 0; - if ((P & 1 | 0) == 0) { - R = N; - } else { - R = N * +h[O >> 3]; - } - m = P >> 1; - if ((m | 0) == 0) { - Q = R; - break; - } else { - N = R; - O = O + 8 | 0; - P = m; - y = 1410; - } - } - } - if ((n | 0) > -1) { - p = L; - q = E * Q; - break; - } else { - p = L; - q = E / Q; - break; - } - } - } while (0); - if ((d | 0) != 0) { - c[d >> 2] = p; - } - if ((j | 0) == 0) { - S = q; - return +S; - } - S = -0.0 - q; - return +S; -} -function cB(a, b) { - a = a | 0; - b = b | 0; - return +(+cA(a, b)); -} -function cC(a, b) { - a = a | 0; - b = b | 0; - return +(+cA(a, b)); -} -function cD(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - return +(+cA(a, b)); -} -function cE(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - return +(+cA(a, b)); -} -function cF(a) { - a = a | 0; - return +(+cA(a, 0)); -} -function cG(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0; - e = i; - i = i + 16 | 0; - f = e | 0; - e = f; - c[e >> 2] = d; - c[e + 4 >> 2] = 0; - cI(a, b, f | 0); -} -function cH(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0; - e = i; - i = i + 16 | 0; - f = e | 0; - e = f; - c[e >> 2] = d; - c[e + 4 >> 2] = 0; - cJ(a, b, f | 0); -} -function cI(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0, f = 0; - e = c[(aX() | 0) >> 2] | 0; - f = c[r >> 2] | 0; - av(c[o >> 2] | 0, 336, (y = i, i = i + 8 | 0, c[y >> 2] = f, y) | 0) | 0; - if ((b | 0) != 0) { - f = c[o >> 2] | 0; - aQ(f | 0, b | 0, d | 0) | 0; - d = c[o >> 2] | 0; - aE(480, 2, 1, d | 0) | 0; - } - d = c[o >> 2] | 0; - b = at(e | 0) | 0; - av(d | 0, 392, (y = i, i = i + 8 | 0, c[y >> 2] = b, y) | 0) | 0; - aH(a | 0); -} -function cJ(a, b, d) { - a = a | 0; - b = b | 0; - d = d | 0; - var e = 0; - e = c[r >> 2] | 0; - av(c[o >> 2] | 0, 440, (y = i, i = i + 8 | 0, c[y >> 2] = e, y) | 0) | 0; - if ((b | 0) != 0) { - e = c[o >> 2] | 0; - aQ(e | 0, b | 0, d | 0) | 0; - } - aC(10, c[o >> 2] | 0) | 0; - aH(a | 0); -} -function cK(b, d, e) { - b = b | 0; - d = d | 0; - e = e | 0; - var f = 0; - f = b | 0; - if ((b & 3) == (d & 3)) { - while (b & 3) { - if ((e | 0) == 0) return f | 0; - a[b] = a[d] | 0; - b = b + 1 | 0; - d = d + 1 | 0; - e = e - 1 | 0; - } - while ((e | 0) >= 4) { - c[b >> 2] = c[d >> 2]; - b = b + 4 | 0; - d = d + 4 | 0; - e = e - 4 | 0; - } - } - while ((e | 0) > 0) { - a[b] = a[d] | 0; - b = b + 1 | 0; - d = d + 1 | 0; - e = e - 1 | 0; - } - return f | 0; -} -function cL(b, d, e) { - b = b | 0; - d = d | 0; - e = e | 0; - var f = 0, g = 0, h = 0; - f = b + e | 0; - if ((e | 0) >= 20) { - d = d & 255; - e = b & 3; - g = d | d << 8 | d << 16 | d << 24; - h = f & ~3; - if (e) { - e = b + 4 - e | 0; - while ((b | 0) < (e | 0)) { - a[b] = d; - b = b + 1 | 0; - } - } - while ((b | 0) < (h | 0)) { - c[b >> 2] = g; - b = b + 4 | 0; - } - } - while ((b | 0) < (f | 0)) { - a[b] = d; - b = b + 1 | 0; - } -} -function cM(b) { - b = b | 0; - var c = 0; - c = b; - while (a[c] | 0) { - c = c + 1 | 0; - } - return c - b | 0; -} -function cN(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0; - e = a + c >>> 0; - return (H = b + d + (e >>> 0 < a >>> 0 | 0) >>> 0, e | 0) | 0; -} -function cO(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0; - e = b - d >>> 0; - e = b - d - (c >>> 0 > a >>> 0 | 0) >>> 0; - return (H = e, a - c >>> 0 | 0) | 0; -} -function cP(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - if ((c | 0) < 32) { - H = b << c | (a & (1 << c) - 1 << 32 - c) >>> 32 - c; - return a << c; - } - H = a << c - 32; - return 0; -} -function cQ(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - if ((c | 0) < 32) { - H = b >>> c; - return a >>> c | (b & (1 << c) - 1) << 32 - c; - } - H = 0; - return b >>> c - 32 | 0; -} -function cR(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - if ((c | 0) < 32) { - H = b >> c; - return a >>> c | (b & (1 << c) - 1) << 32 - c; - } - H = (b | 0) < 0 ? -1 : 0; - return b >> c - 32 | 0; -} -function cS(b) { - b = b | 0; - var c = 0; - c = a[n + (b >>> 24) | 0] | 0; - if ((c | 0) < 8) return c | 0; - c = a[n + (b >> 16 & 255) | 0] | 0; - if ((c | 0) < 8) return c + 8 | 0; - c = a[n + (b >> 8 & 255) | 0] | 0; - if ((c | 0) < 8) return c + 16 | 0; - return (a[n + (b & 255) | 0] | 0) + 24 | 0; -} -function cT(b) { - b = b | 0; - var c = 0; - c = a[m + (b & 255) | 0] | 0; - if ((c | 0) < 8) return c | 0; - c = a[m + (b >> 8 & 255) | 0] | 0; - if ((c | 0) < 8) return c + 8 | 0; - c = a[m + (b >> 16 & 255) | 0] | 0; - if ((c | 0) < 8) return c + 16 | 0; - return (a[m + (b >>> 24) | 0] | 0) + 24 | 0; -} -function cU(a, b) { - a = a | 0; - b = b | 0; - var c = 0, d = 0, e = 0, f = 0; - c = a & 65535; - d = b & 65535; - e = ad(d, c) | 0; - f = a >>> 16; - a = (e >>> 16) + (ad(d, f) | 0) | 0; - d = b >>> 16; - b = ad(d, c) | 0; - return (H = (a >>> 16) + (ad(d, f) | 0) + (((a & 65535) + b | 0) >>> 16) | 0, a + b << 16 | e & 65535 | 0) | 0; -} -function cV(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0, f = 0, g = 0, h = 0, i = 0; - e = b >> 31 | ((b | 0) < 0 ? -1 : 0) << 1; - f = ((b | 0) < 0 ? -1 : 0) >> 31 | ((b | 0) < 0 ? -1 : 0) << 1; - g = d >> 31 | ((d | 0) < 0 ? -1 : 0) << 1; - h = ((d | 0) < 0 ? -1 : 0) >> 31 | ((d | 0) < 0 ? -1 : 0) << 1; - i = cO(e ^ a, f ^ b, e, f) | 0; - b = H; - a = g ^ e; - e = h ^ f; - f = cO((c_(i, b, cO(g ^ c, h ^ d, g, h) | 0, H, 0) | 0) ^ a, H ^ e, a, e) | 0; - return (H = H, f) | 0; -} -function cW(a, b, d, e) { - a = a | 0; - b = b | 0; - d = d | 0; - e = e | 0; - var f = 0, g = 0, h = 0, j = 0, k = 0, l = 0, m = 0; - f = i; - i = i + 8 | 0; - g = f | 0; - h = b >> 31 | ((b | 0) < 0 ? -1 : 0) << 1; - j = ((b | 0) < 0 ? -1 : 0) >> 31 | ((b | 0) < 0 ? -1 : 0) << 1; - k = e >> 31 | ((e | 0) < 0 ? -1 : 0) << 1; - l = ((e | 0) < 0 ? -1 : 0) >> 31 | ((e | 0) < 0 ? -1 : 0) << 1; - m = cO(h ^ a, j ^ b, h, j) | 0; - b = H; - a = cO(k ^ d, l ^ e, k, l) | 0; - c_(m, b, a, H, g) | 0; - a = cO(c[g >> 2] ^ h, c[g + 4 >> 2] ^ j, h, j) | 0; - j = H; - i = f; - return (H = j, a) | 0; -} -function cX(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0, f = 0; - e = a; - a = c; - c = cU(e, a) | 0; - f = H; - return (H = (ad(b, a) | 0) + (ad(d, e) | 0) + f | f & 0, c | 0 | 0) | 0; -} -function cY(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - var e = 0; - e = c_(a, b, c, d, 0) | 0; - return (H = H, e) | 0; -} -function cZ(a, b, d, e) { - a = a | 0; - b = b | 0; - d = d | 0; - e = e | 0; - var f = 0, g = 0; - f = i; - i = i + 8 | 0; - g = f | 0; - c_(a, b, d, e, g) | 0; - i = f; - return (H = c[g + 4 >> 2] | 0, c[g >> 2] | 0) | 0; -} -function c_(a, b, d, e, f) { - a = a | 0; - b = b | 0; - d = d | 0; - e = e | 0; - f = f | 0; - var g = 0, h = 0, i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, o = 0, p = 0, q = 0, r = 0, s = 0, t = 0, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0, A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, I = 0, J = 0, K = 0, L = 0, M = 0; - g = a; - h = b; - i = h; - j = d; - k = e; - l = k; - if ((i | 0) == 0) { - m = (f | 0) != 0; - if ((l | 0) == 0) { - if (m) { - c[f >> 2] = (g >>> 0) % (j >>> 0); - c[f + 4 >> 2] = 0; - } - n = 0; - o = (g >>> 0) / (j >>> 0) >>> 0; - return (H = n, o) | 0; - } else { - if (!m) { - n = 0; - o = 0; - return (H = n, o) | 0; - } - c[f >> 2] = a | 0; - c[f + 4 >> 2] = b & 0; - n = 0; - o = 0; - return (H = n, o) | 0; - } - } - m = (l | 0) == 0; - do { - if ((j | 0) == 0) { - if (m) { - if ((f | 0) != 0) { - c[f >> 2] = (i >>> 0) % (j >>> 0); - c[f + 4 >> 2] = 0; - } - n = 0; - o = (i >>> 0) / (j >>> 0) >>> 0; - return (H = n, o) | 0; - } - if ((g | 0) == 0) { - if ((f | 0) != 0) { - c[f >> 2] = 0; - c[f + 4 >> 2] = (i >>> 0) % (l >>> 0); - } - n = 0; - o = (i >>> 0) / (l >>> 0) >>> 0; - return (H = n, o) | 0; - } - p = l - 1 | 0; - if ((p & l | 0) == 0) { - if ((f | 0) != 0) { - c[f >> 2] = a | 0; - c[f + 4 >> 2] = p & i | b & 0; - } - n = 0; - o = i >>> ((cT(l | 0) | 0) >>> 0); - return (H = n, o) | 0; - } - p = (cS(l | 0) | 0) - (cS(i | 0) | 0) | 0; - if (p >>> 0 <= 30) { - q = p + 1 | 0; - r = 31 - p | 0; - s = q; - t = i << r | g >>> (q >>> 0); - u = i >>> (q >>> 0); - v = 0; - w = g << r; - break; - } - if ((f | 0) == 0) { - n = 0; - o = 0; - return (H = n, o) | 0; - } - c[f >> 2] = a | 0; - c[f + 4 >> 2] = h | b & 0; - n = 0; - o = 0; - return (H = n, o) | 0; - } else { - if (!m) { - r = (cS(l | 0) | 0) - (cS(i | 0) | 0) | 0; - if (r >>> 0 <= 31) { - q = r + 1 | 0; - p = 31 - r | 0; - x = r - 31 >> 31; - s = q; - t = g >>> (q >>> 0) & x | i << p; - u = i >>> (q >>> 0) & x; - v = 0; - w = g << p; - break; - } - if ((f | 0) == 0) { - n = 0; - o = 0; - return (H = n, o) | 0; - } - c[f >> 2] = a | 0; - c[f + 4 >> 2] = h | b & 0; - n = 0; - o = 0; - return (H = n, o) | 0; - } - p = j - 1 | 0; - if ((p & j | 0) != 0) { - x = (cS(j | 0) | 0) + 33 - (cS(i | 0) | 0) | 0; - q = 64 - x | 0; - r = 32 - x | 0; - y = r >> 31; - z = x - 32 | 0; - A = z >> 31; - s = x; - t = r - 1 >> 31 & i >>> (z >>> 0) | (i << r | g >>> (x >>> 0)) & A; - u = A & i >>> (x >>> 0); - v = g << q & y; - w = (i << q | g >>> (z >>> 0)) & y | g << r & x - 33 >> 31; - break; - } - if ((f | 0) != 0) { - c[f >> 2] = p & g; - c[f + 4 >> 2] = 0; - } - if ((j | 0) == 1) { - n = h | b & 0; - o = a | 0 | 0; - return (H = n, o) | 0; - } else { - p = cT(j | 0) | 0; - n = i >>> (p >>> 0) | 0; - o = i << 32 - p | g >>> (p >>> 0) | 0; - return (H = n, o) | 0; - } - } - } while (0); - if ((s | 0) == 0) { - B = w; - C = v; - D = u; - E = t; - F = 0; - G = 0; - } else { - g = d | 0 | 0; - d = k | e & 0; - e = cN(g, d, -1, -1) | 0; - k = H; - i = w; - w = v; - v = u; - u = t; - t = s; - s = 0; - while (1) { - I = w >>> 31 | i << 1; - J = s | w << 1; - j = u << 1 | i >>> 31 | 0; - a = u >>> 31 | v << 1 | 0; - cO(e, k, j, a) | 0; - b = H; - h = b >> 31 | ((b | 0) < 0 ? -1 : 0) << 1; - K = h & 1; - L = cO(j, a, h & g, (((b | 0) < 0 ? -1 : 0) >> 31 | ((b | 0) < 0 ? -1 : 0) << 1) & d) | 0; - M = H; - b = t - 1 | 0; - if ((b | 0) == 0) { - break; - } else { - i = I; - w = J; - v = M; - u = L; - t = b; - s = K; - } - } - B = I; - C = J; - D = M; - E = L; - F = 0; - G = K; - } - K = C; - C = 0; - if ((f | 0) != 0) { - c[f >> 2] = E; - c[f + 4 >> 2] = D; - } - n = (K | 0) >>> 31 | (B | C) << 1 | (C << 1 | K >>> 31) & 0 | F; - o = (K << 1 | 0 >>> 31) & -2 | G; - return (H = n, o) | 0; -} -function c$(a, b) { - a = a | 0; - b = b | 0; - a1[a & 15](b | 0); -} -function c0(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - a2[a & 15](b | 0, c | 0); -} -function c1(a, b) { - a = a | 0; - b = b | 0; - return a3[a & 7](b | 0) | 0; -} -function c2(a, b, c, d) { - a = a | 0; - b = b | 0; - c = c | 0; - d = d | 0; - a4[a & 15](b | 0, c | 0, d | 0); -} -function c3(a) { - a = a | 0; - a5[a & 1](); -} -function c4(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - return a6[a & 1](b | 0, c | 0) | 0; -} -function c5(a) { - a = a | 0; - ae(0); -} -function c6(a, b) { - a = a | 0; - b = b | 0; - ae(1); -} -function c7(a) { - a = a | 0; - ae(2); - return 0; -} -function c8(a, b, c) { - a = a | 0; - b = b | 0; - c = c | 0; - ae(3); -} -function c9() { - ae(4); -} -function da(a, b) { - a = a | 0; - b = b | 0; - ae(5); - return 0; -} -// EMSCRIPTEN_END_FUNCS - var a1 = [ c5, c5, ch, c5, cn, c5, cc, c5, cg, c5, cm, c5, c5, c5, c5, c5 ]; - var a2 = [ c6, c6, cw, c6, cy, c6, cx, c6, cz, c6, c6, c6, c6, c6, c6, c6 ]; - var a3 = [ c7, c7, cd, c7, ce, c7, c7, c7 ]; - var a4 = [ c8, c8, cJ, c8, cI, c8, cG, c8, cH, c8, c8, c8, c8, c8, c8, c8 ]; - var a5 = [ c9, c9 ]; - var a6 = [ da, da ]; - return { - _crypto_scrypt: bu, - _strlen: cM, - _free: bM, - _realloc: bO, - _memset: cL, - _malloc: bL, - _memcpy: cK, - _calloc: bN, - runPostSets: bn, - stackAlloc: a7, - stackSave: a8, - stackRestore: a9, - setThrew: ba, - setTempRet0: bd, - setTempRet1: be, - setTempRet2: bf, - setTempRet3: bg, - setTempRet4: bh, - setTempRet5: bi, - setTempRet6: bj, - setTempRet7: bk, - setTempRet8: bl, - setTempRet9: bm, - dynCall_vi: c$, - dynCall_vii: c0, - dynCall_ii: c1, - dynCall_viii: c2, - dynCall_v: c3, - dynCall_iii: c4 - }; -// EMSCRIPTEN_END_ASM -})({Math:Math, Int8Array:Int8Array, Int16Array:Int16Array, Int32Array:Int32Array, Uint8Array:Uint8Array, Uint16Array:Uint16Array, Uint32Array:Uint32Array, Float32Array:Float32Array, Float64Array:Float64Array}, {abort:wa, assert:w, asmPrintInt:function(a, b) { - s.print("int " + a + "," + b) -}, asmPrintFloat:function(a, b) { - s.print("float " + a + "," + b) -}, min:Xc, invoke_vi:function(a, b) { - try { - s.dynCall_vi(a, b) - }catch(c) { - "number" !== typeof c && "longjmp" !== c && g(c), V.setThrew(1, 0) - } -}, invoke_vii:function(a, b, c) { - try { - s.dynCall_vii(a, b, c) - }catch(d) { - "number" !== typeof d && "longjmp" !== d && g(d), V.setThrew(1, 0) - } -}, invoke_ii:function(a, b) { - try { - return s.dynCall_ii(a, b) - }catch(c) { - "number" !== typeof c && "longjmp" !== c && g(c), V.setThrew(1, 0) - } -}, invoke_viii:function(a, b, c, d) { - try { - s.dynCall_viii(a, b, c, d) - }catch(e) { - "number" !== typeof e && "longjmp" !== e && g(e), V.setThrew(1, 0) - } -}, invoke_v:function(a) { - try { - s.dynCall_v(a) - }catch(b) { - "number" !== typeof b && "longjmp" !== b && g(b), V.setThrew(1, 0) - } -}, invoke_iii:function(a, b, c) { - try { - return s.dynCall_iii(a, b, c) - }catch(d) { - "number" !== typeof d && "longjmp" !== d && g(d), V.setThrew(1, 0) - } -}, _strncmp:function(a, b, c) { - for(var d = 0;d < c;) { - var e = G[a + d | 0], f = G[b + d | 0]; - if(e == f && 0 == e) { - break - } - if(0 == e) { - return-1 - } - if(0 == f) { - return 1 - } - if(e == f) { - d++ - }else { - return e > f ? 1 : -1 - } - } - return 0 -}, _llvm_va_end:aa(), _sysconf:function(a) { - switch(a) { - case 8: - return 4096; - case 54: - ; - case 56: - ; - case 21: - ; - case 61: - ; - case 63: - ; - case 22: - ; - case 67: - ; - case 23: - ; - case 24: - ; - case 25: - ; - case 26: - ; - case 27: - ; - case 69: - ; - case 28: - ; - case 101: - ; - case 70: - ; - case 71: - ; - case 29: - ; - case 30: - ; - case 199: - ; - case 75: - ; - case 76: - ; - case 32: - ; - case 43: - ; - case 44: - ; - case 80: - ; - case 46: - ; - case 47: - ; - case 45: - ; - case 48: - ; - case 49: - ; - case 42: - ; - case 82: - ; - case 33: - ; - case 7: - ; - case 108: - ; - case 109: - ; - case 107: - ; - case 112: - ; - case 119: - ; - case 121: - return 200809; - case 13: - ; - case 104: - ; - case 94: - ; - case 95: - ; - case 34: - ; - case 35: - ; - case 77: - ; - case 81: - ; - case 83: - ; - case 84: - ; - case 85: - ; - case 86: - ; - case 87: - ; - case 88: - ; - case 89: - ; - case 90: - ; - case 91: - ; - case 94: - ; - case 95: - ; - case 110: - ; - case 111: - ; - case 113: - ; - case 114: - ; - case 115: - ; - case 116: - ; - case 117: - ; - case 118: - ; - case 120: - ; - case 40: - ; - case 16: - ; - case 79: - ; - case 19: - return-1; - case 92: - ; - case 93: - ; - case 5: - ; - case 72: - ; - case 6: - ; - case 74: - ; - case 92: - ; - case 93: - ; - case 96: - ; - case 97: - ; - case 98: - ; - case 99: - ; - case 102: - ; - case 103: - ; - case 105: - return 1; - case 38: - ; - case 66: - ; - case 50: - ; - case 51: - ; - case 4: - return 1024; - case 15: - ; - case 64: - ; - case 41: - return 32; - case 55: - ; - case 37: - ; - case 17: - return 2147483647; - case 18: - ; - case 1: - return 47839; - case 59: - ; - case 57: - return 99; - case 68: - ; - case 58: - return 2048; - case 0: - return 2097152; - case 3: - return 65536; - case 14: - return 32768; - case 73: - return 32767; - case 39: - return 16384; - case 60: - return 1E3; - case 106: - return 700; - case 52: - return 256; - case 62: - return 255; - case 2: - return 100; - case 65: - return 64; - case 36: - return 20; - case 100: - return 16; - case 20: - return 6; - case 53: - return 4; - case 10: - return 1 - } - M(N.A); - return-1 -}, ___cxa_throw:rc, _strerror:zc, _abort:function() { - s.abort() -}, _fprintf:mc, _llvm_eh_exception:U, ___cxa_free_exception:sc, _fflush:aa(), ___buildEnvironment:wc, __reallyNegative:jc, _strchr:function(a, b) { - a--; - do { - a++; - var c = A[a]; - if(c == b) { - return a - } - }while(c); - return 0 -}, _fputc:Bc, ___setErrNo:M, _fwrite:hc, _send:fc, _write:gc, _exit:function(a) { - Ac(a) -}, ___cxa_find_matching_catch:function(a, b) { - -1 == a && (a = B[U.m >> 2]); - -1 == b && (b = B[U.m + 4 >> 2]); - var c = Array.prototype.slice.call(arguments, 2); - 0 != b && !pc(b) && 0 == B[B[b >> 2] - 8 >> 2] && (a = B[a >> 2]); - for(var d = 0;d < c.length;d++) { - if(qc(c[d], b, a)) { - return(V.setTempRet0(c[d]), a) | 0 - } - } - return(V.setTempRet0(b), a) | 0 -}, ___cxa_allocate_exception:function(a) { - return Oa(a) -}, _isspace:function(a) { - return 32 == a || 9 <= a && 13 >= a -}, __formatString:kc, ___resumeException:function(a) { - 0 == B[U.m >> 2] && (B[U.m >> 2] = a); - g(a + " - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.") -}, _llvm_uadd_with_overflow_i32:function(a, b) { - a >>>= 0; - b >>>= 0; - return(V.setTempRet0(4294967295 < a + b), a + b >>> 0) | 0 -}, ___cxa_does_inherit:qc, _getenv:xc, _vfprintf:function(a, b, c) { - return mc(a, b, B[c >> 2]) -}, ___cxa_begin_catch:function(a) { - oc.ta--; - return a -}, __ZSt18uncaught_exceptionv:oc, _pwrite:function(a, b, c, d) { - a = R[a]; - if(!a) { - return M(N.$), -1 - } - try { - return Ib(a, A, b, c, d) - }catch(e) { - return Zb(e), -1 - } -}, ___cxa_call_unexpected:function(a) { - s.P("Unexpected exception thrown, this is not properly supported - aborting"); - za = l; - g(a) -}, _sbrk:nc, _strerror_r:yc, ___errno_location:function() { - return rb -}, ___gxx_personality_v0:aa(), ___cxa_is_number_type:pc, _time:function(a) { - var b = Math.floor(Date.now() / 1E3); - a && (B[a >> 2] = b); - return b -}, __exit:Ac, ___cxa_end_catch:uc, STACKTOP:u, STACK_MAX:Ta, tempDoublePtr:qb, ABORT:za, cttz_i8:Wc, ctlz_i8:Vc, NaN:NaN, Infinity:Infinity, _stderr:nb, __ZTVN10__cxxabiv120__si_class_type_infoE:ob, __ZTVN10__cxxabiv117__class_type_infoE:pb, ___progname:k}, I); -s._crypto_scrypt = V._crypto_scrypt; -var ic = s._strlen = V._strlen, tc = s._free = V._free; -s._realloc = V._realloc; -var tb = s._memset = V._memset, Oa = s._malloc = V._malloc, sb = s._memcpy = V._memcpy; -s._calloc = V._calloc; -var mb = s.runPostSets = V.runPostSets; -s.dynCall_vi = V.dynCall_vi; -s.dynCall_vii = V.dynCall_vii; -s.dynCall_ii = V.dynCall_ii; -s.dynCall_viii = V.dynCall_viii; -s.dynCall_v = V.dynCall_v; -s.dynCall_iii = V.dynCall_iii; -var qa = function(a) { - return V.stackAlloc(a) -}, ja = function() { - return V.stackSave() -}, ka = function(a) { - V.stackRestore(a) -}, lc; -function X(a, b) { - a != m && ("number" == typeof a ? this.p(a) : b == m && "string" != typeof a ? this.k(a, 256) : this.k(a, b)) -} -function Yc() { - return new X(m) -} -function Zc(a, b) { - var c = $c[a.charCodeAt(b)]; - return c == m ? -1 : c -} -function ad(a) { - var b = Yc(); - b.D(a); - return b -} -function Y(a, b) { - this.h = a | 0; - this.j = b | 0 -} -Y.Ca = {}; -Y.D = function(a) { - if(-128 <= a && 128 > a) { - var b = Y.Ca[a]; - if(b) { - return b - } - } - b = new Y(a | 0, 0 > a ? -1 : 0); - -128 <= a && 128 > a && (Y.Ca[a] = b); - return b -}; -Y.p = function(a) { - return isNaN(a) || !isFinite(a) ? Y.ZERO : a <= -Y.Ea ? Y.MIN_VALUE : a + 1 >= Y.Ea ? Y.MAX_VALUE : 0 > a ? Y.p(-a).i() : new Y(a % Y.B | 0, a / Y.B | 0) -}; -Y.v = function(a, b) { - return new Y(a, b) -}; -Y.k = function(a, b) { - 0 == a.length && g(Error("number format error: empty string")); - var c = b || 10; - (2 > c || 36 < c) && g(Error("radix out of range: " + c)); - if("-" == a.charAt(0)) { - return Y.k(a.substring(1), c).i() - } - 0 <= a.indexOf("-") && g(Error('number format error: interior "-" character: ' + a)); - for(var d = Y.p(Math.pow(c, 8)), e = Y.ZERO, f = 0;f < a.length;f += 8) { - var h = Math.min(8, a.length - f), i = parseInt(a.substring(f, f + h), c); - 8 > h ? (h = Y.p(Math.pow(c, h)), e = e.multiply(h).add(Y.p(i))) : (e = e.multiply(d), e = e.add(Y.p(i))) - } - return e -}; -Y.ea = 65536; -Y.Od = 16777216; -Y.B = Y.ea * Y.ea; -Y.Pd = Y.B / 2; -Y.Qd = Y.B * Y.ea; -Y.eb = Y.B * Y.B; -Y.Ea = Y.eb / 2; -Y.ZERO = Y.D(0); -Y.ONE = Y.D(1); -Y.Da = Y.D(-1); -Y.MAX_VALUE = Y.v(-1, 2147483647); -Y.MIN_VALUE = Y.v(0, -2147483648); -Y.cb = Y.D(16777216); -q = Y.prototype; -q.Z = function() { - return this.j * Y.B + this.ob() -}; -q.toString = function(a) { - a = a || 10; - (2 > a || 36 < a) && g(Error("radix out of range: " + a)); - if(this.G()) { - return"0" - } - if(this.n()) { - if(this.o(Y.MIN_VALUE)) { - var b = Y.p(a), c = this.F(b), b = c.multiply(b).R(this); - return c.toString(a) + b.h.toString(a) - } - return"-" + this.i().toString(a) - } - for(var c = Y.p(Math.pow(a, 6)), b = this, d = "";;) { - var e = b.F(c), f = b.R(e.multiply(c)).h.toString(a), b = e; - if(b.G()) { - return f + d - } - for(;6 > f.length;) { - f = "0" + f - } - d = "" + f + d - } -}; -q.ob = function() { - return 0 <= this.h ? this.h : Y.B + this.h -}; -q.G = function() { - return 0 == this.j && 0 == this.h -}; -q.n = function() { - return 0 > this.j -}; -q.Pa = function() { - return 1 == (this.h & 1) -}; -q.o = function(a) { - return this.j == a.j && this.h == a.h -}; -q.Ra = function() { - return 0 > this.ja(Y.cb) -}; -q.qb = function(a) { - return 0 < this.ja(a) -}; -q.rb = function(a) { - return 0 <= this.ja(a) -}; -q.ja = function(a) { - if(this.o(a)) { - return 0 - } - var b = this.n(), c = a.n(); - return b && !c ? -1 : !b && c ? 1 : this.R(a).n() ? -1 : 1 -}; -q.i = function() { - return this.o(Y.MIN_VALUE) ? Y.MIN_VALUE : this.xb().add(Y.ONE) -}; -q.add = function(a) { - var b = this.j >>> 16, c = this.j & 65535, d = this.h >>> 16, e = a.j >>> 16, f = a.j & 65535, h = a.h >>> 16, i; - i = 0 + ((this.h & 65535) + (a.h & 65535)); - a = 0 + (i >>> 16); - a += d + h; - d = 0 + (a >>> 16); - d += c + f; - c = 0 + (d >>> 16); - c = c + (b + e) & 65535; - return Y.v((a & 65535) << 16 | i & 65535, c << 16 | d & 65535) -}; -q.R = function(a) { - return this.add(a.i()) -}; -q.multiply = function(a) { - if(this.G() || a.G()) { - return Y.ZERO - } - if(this.o(Y.MIN_VALUE)) { - return a.Pa() ? Y.MIN_VALUE : Y.ZERO - } - if(a.o(Y.MIN_VALUE)) { - return this.Pa() ? Y.MIN_VALUE : Y.ZERO - } - if(this.n()) { - return a.n() ? this.i().multiply(a.i()) : this.i().multiply(a).i() - } - if(a.n()) { - return this.multiply(a.i()).i() - } - if(this.Ra() && a.Ra()) { - return Y.p(this.Z() * a.Z()) - } - var b = this.j >>> 16, c = this.j & 65535, d = this.h >>> 16, e = this.h & 65535, f = a.j >>> 16, h = a.j & 65535, i = a.h >>> 16, a = a.h & 65535, j, n, y, v; - v = 0 + e * a; - y = 0 + (v >>> 16); - y += d * a; - n = 0 + (y >>> 16); - y = (y & 65535) + e * i; - n += y >>> 16; - y &= 65535; - n += c * a; - j = 0 + (n >>> 16); - n = (n & 65535) + d * i; - j += n >>> 16; - n &= 65535; - n += e * h; - j += n >>> 16; - n &= 65535; - j = j + (b * a + c * i + d * h + e * f) & 65535; - return Y.v(y << 16 | v & 65535, j << 16 | n) -}; -q.F = function(a) { - a.G() && g(Error("division by zero")); - if(this.G()) { - return Y.ZERO - } - if(this.o(Y.MIN_VALUE)) { - if(a.o(Y.ONE) || a.o(Y.Da)) { - return Y.MIN_VALUE - } - if(a.o(Y.MIN_VALUE)) { - return Y.ONE - } - var b = this.Db().F(a).shiftLeft(1); - if(b.o(Y.ZERO)) { - return a.n() ? Y.ONE : Y.Da - } - var c = this.R(a.multiply(b)); - return b.add(c.F(a)) - } - if(a.o(Y.MIN_VALUE)) { - return Y.ZERO - } - if(this.n()) { - return a.n() ? this.i().F(a.i()) : this.i().F(a).i() - } - if(a.n()) { - return this.F(a.i()).i() - } - for(var d = Y.ZERO, c = this;c.rb(a);) { - for(var b = Math.max(1, Math.floor(c.Z() / a.Z())), e = Math.ceil(Math.log(b) / Math.LN2), e = 48 >= e ? 1 : Math.pow(2, e - 48), f = Y.p(b), h = f.multiply(a);h.n() || h.qb(c);) { - b -= e, f = Y.p(b), h = f.multiply(a) - } - f.G() && (f = Y.ONE); - d = d.add(f); - c = c.R(h) - } - return d -}; -q.xb = function() { - return Y.v(~this.h, ~this.j) -}; -q.shiftLeft = function(a) { - a &= 63; - if(0 == a) { - return this - } - var b = this.h; - return 32 > a ? Y.v(b << a, this.j << a | b >>> 32 - a) : Y.v(0, b << a - 32) -}; -q.Db = function() { - var a; - a = 1; - if(0 == a) { - return this - } - var b = this.j; - return 32 > a ? Y.v(this.h >>> a | b << 32 - a, b >> a) : Y.v(b >> a - 32, 0 <= b ? 0 : -1) -}; -q = X.prototype; -q.ga = function(a, b, c, d) { - for(var e = 0, f = 0;0 <= --d;) { - var h = a * this[e++] + b[c] + f, f = Math.floor(h / 67108864); - b[c++] = h & 67108863 - } - return f -}; -q.f = 26; -q.u = 67108863; -q.K = 67108864; -q.bb = Math.pow(2, 52); -q.Aa = 26; -q.Ba = 0; -var $c = [], bd, Z; -bd = 48; -for(Z = 0;9 >= Z;++Z) { - $c[bd++] = Z -} -bd = 97; -for(Z = 10;36 > Z;++Z) { - $c[bd++] = Z -} -bd = 65; -for(Z = 10;36 > Z;++Z) { - $c[bd++] = Z -} -q = X.prototype; -q.copyTo = function(a) { - for(var b = this.b - 1;0 <= b;--b) { - a[b] = this[b] - } - a.b = this.b; - a.c = this.c -}; -q.D = function(a) { - this.b = 1; - this.c = 0 > a ? -1 : 0; - 0 < a ? this[0] = a : -1 > a ? this[0] = a + DV : this.b = 0 -}; -q.k = function(a, b) { - var c; - if(16 == b) { - c = 4 - }else { - if(8 == b) { - c = 3 - }else { - if(256 == b) { - c = 8 - }else { - if(2 == b) { - c = 1 - }else { - if(32 == b) { - c = 5 - }else { - if(4 == b) { - c = 2 - }else { - this.nb(a, b); - return - } - } - } - } - } - } - this.c = this.b = 0; - for(var d = a.length, e = p, f = 0;0 <= --d;) { - var h = 8 == c ? a[d] & 255 : Zc(a, d); - 0 > h ? "-" == a.charAt(d) && (e = l) : (e = p, 0 == f ? this[this.b++] = h : f + c > this.f ? (this[this.b - 1] |= (h & (1 << this.f - f) - 1) << f, this[this.b++] = h >> this.f - f) : this[this.b - 1] |= h << f, f += c, f >= this.f && (f -= this.f)) - } - 8 == c && 0 != (a[0] & 128) && (this.c = -1, 0 < f && (this[this.b - 1] |= (1 << this.f - f) - 1 << f)); - this.C(); - e && X.ZERO.t(this, this) -}; -q.C = function() { - for(var a = this.c & this.u;0 < this.b && this[this.b - 1] == a;) { - --this.b - } -}; -q.la = function(a, b) { - var c; - for(c = this.b - 1;0 <= c;--c) { - b[c + a] = this[c] - } - for(c = a - 1;0 <= c;--c) { - b[c] = 0 - } - b.b = this.b + a; - b.c = this.c -}; -q.jb = function(a, b) { - for(var c = a;c < this.b;++c) { - b[c - a] = this[c] - } - b.b = Math.max(this.b - a, 0); - b.c = this.c -}; -q.Qa = function(a, b) { - var c = a % this.f, d = this.f - c, e = (1 << d) - 1, f = Math.floor(a / this.f), h = this.c << c & this.u, i; - for(i = this.b - 1;0 <= i;--i) { - b[i + f + 1] = this[i] >> d | h, h = (this[i] & e) << c - } - for(i = f - 1;0 <= i;--i) { - b[i] = 0 - } - b[f] = h; - b.b = this.b + f + 1; - b.c = this.c; - b.C() -}; -q.zb = function(a, b) { - b.c = this.c; - var c = Math.floor(a / this.f); - if(c >= this.b) { - b.b = 0 - }else { - var d = a % this.f, e = this.f - d, f = (1 << d) - 1; - b[0] = this[c] >> d; - for(var h = c + 1;h < this.b;++h) { - b[h - c - 1] |= (this[h] & f) << e, b[h - c] = this[h] >> d - } - 0 < d && (b[this.b - c - 1] |= (this.c & f) << e); - b.b = this.b - c; - b.C() - } -}; -q.t = function(a, b) { - for(var c = 0, d = 0, e = Math.min(a.b, this.b);c < e;) { - d += this[c] - a[c], b[c++] = d & this.u, d >>= this.f - } - if(a.b < this.b) { - for(d -= a.c;c < this.b;) { - d += this[c], b[c++] = d & this.u, d >>= this.f - } - d += this.c - }else { - for(d += this.c;c < a.b;) { - d -= a[c], b[c++] = d & this.u, d >>= this.f - } - d -= a.c - } - b.c = 0 > d ? -1 : 0; - -1 > d ? b[c++] = this.K + d : 0 < d && (b[c++] = d); - b.b = c; - b.C() -}; -q.vb = function(a) { - var b = $.Xa, c = this.abs(), d = b.abs(), e = c.b; - for(a.b = e + d.b;0 <= --e;) { - a[e] = 0 - } - for(e = 0;e < d.b;++e) { - a[e + c.b] = c.ga(d[e], a, e, c.b) - } - a.c = 0; - a.C(); - this.c != b.c && X.ZERO.t(a, a) -}; -q.Ja = function(a, b, c) { - var d = a.abs(); - if(!(0 >= d.b)) { - var e = this.abs(); - if(e.b < d.b) { - b != m && b.D(0), c != m && this.copyTo(c) - }else { - c == m && (c = Yc()); - var f = Yc(), h = this.c, a = a.c, i = d[d.b - 1], j = 1, n; - if(0 != (n = i >>> 16)) { - i = n, j += 16 - } - if(0 != (n = i >> 8)) { - i = n, j += 8 - } - if(0 != (n = i >> 4)) { - i = n, j += 4 - } - if(0 != (n = i >> 2)) { - i = n, j += 2 - } - 0 != i >> 1 && (j += 1); - i = this.f - j; - 0 < i ? (d.Qa(i, f), e.Qa(i, c)) : (d.copyTo(f), e.copyTo(c)); - d = f.b; - e = f[d - 1]; - if(0 != e) { - n = e * (1 << this.Aa) + (1 < d ? f[d - 2] >> this.Ba : 0); - j = this.bb / n; - n = (1 << this.Aa) / n; - var y = 1 << this.Ba, v = c.b, C = v - d, D = b == m ? Yc() : b; - f.la(C, D); - 0 <= c.U(D) && (c[c.b++] = 1, c.t(D, c)); - X.ONE.la(d, D); - for(D.t(f, f);f.b < d;) { - f[f.b++] = 0 - } - for(;0 <= --C;) { - var K = c[--v] == e ? this.u : Math.floor(c[v] * j + (c[v - 1] + y) * n); - if((c[v] += f.ga(K, c, C, d)) < K) { - f.la(C, D); - for(c.t(D, c);c[v] < --K;) { - c.t(D, c) - } - } - } - b != m && (c.jb(d, b), h != a && X.ZERO.t(b, b)); - c.b = d; - c.C(); - 0 < i && c.zb(i, c); - 0 > h && X.ZERO.t(c, c) - } - } - } -}; -q.toString = function(a) { - if(0 > this.c) { - return"-" + this.i().toString(a) - } - if(16 == a) { - a = 4 - }else { - if(8 == a) { - a = 3 - }else { - if(2 == a) { - a = 1 - }else { - if(32 == a) { - a = 5 - }else { - if(4 == a) { - a = 2 - }else { - return this.Fb(a) - } - } - } - } - } - var b = (1 << a) - 1, c, d = p, e = "", f = this.b, h = this.f - f * this.f % a; - if(0 < f--) { - if(h < this.f && 0 < (c = this[f] >> h)) { - d = l, e = "0123456789abcdefghijklmnopqrstuvwxyz".charAt(c) - } - for(;0 <= f;) { - h < a ? (c = (this[f] & (1 << h) - 1) << a - h, c |= this[--f] >> (h += this.f - a)) : (c = this[f] >> (h -= a) & b, 0 >= h && (h += this.f, --f)), 0 < c && (d = l), d && (e += "0123456789abcdefghijklmnopqrstuvwxyz".charAt(c)) - } - } - return d ? e : "0" -}; -q.i = function() { - var a = Yc(); - X.ZERO.t(this, a); - return a -}; -q.abs = function() { - return 0 > this.c ? this.i() : this -}; -q.U = function(a) { - var b = this.c - a.c; - if(0 != b) { - return b - } - var c = this.b, b = c - a.b; - if(0 != b) { - return 0 > this.c ? -b : b - } - for(;0 <= --c;) { - if(0 != (b = this[c] - a[c])) { - return b - } - } - return 0 -}; -X.ZERO = ad(0); -X.ONE = ad(1); -q = X.prototype; -q.nb = function(a, b) { - this.D(0); - b == m && (b = 10); - for(var c = this.S(b), d = Math.pow(b, c), e = p, f = 0, h = 0, i = 0;i < a.length;++i) { - var j = Zc(a, i); - 0 > j ? "-" == a.charAt(i) && 0 == this.ra() && (e = l) : (h = b * h + j, ++f >= c && (this.Ia(d), this.Ha(h), h = f = 0)) - } - 0 < f && (this.Ia(Math.pow(b, f)), this.Ha(h)); - e && X.ZERO.t(this, this) -}; -q.S = function(a) { - return Math.floor(Math.LN2 * this.f / Math.log(a)) -}; -q.ra = function() { - return 0 > this.c ? -1 : 0 >= this.b || 1 == this.b && 0 >= this[0] ? 0 : 1 -}; -q.Ia = function(a) { - this[this.b] = this.ga(a - 1, this, 0, this.b); - ++this.b; - this.C() -}; -q.Ha = function(a) { - var b = 0; - if(0 != a) { - for(;this.b <= b;) { - this[this.b++] = 0 - } - for(this[b] += a;this[b] >= this.K;) { - this[b] -= this.K, ++b >= this.b && (this[this.b++] = 0), ++this[b] - } - } -}; -q.Fb = function(a) { - a == m && (a = 10); - if(0 == this.ra() || 2 > a || 36 < a) { - return"0" - } - var b = this.S(a), b = Math.pow(a, b), c = ad(b), d = Yc(), e = Yc(), f = ""; - for(this.Ja(c, d, e);0 < d.ra();) { - f = (b + e.Oa()).toString(a).substr(1) + f, d.Ja(c, d, e) - } - return e.Oa().toString(a) + f -}; -q.Oa = function() { - if(0 > this.c) { - if(1 == this.b) { - return this[0] - this.K - } - if(0 == this.b) { - return-1 - } - }else { - if(1 == this.b) { - return this[0] - } - if(0 == this.b) { - return 0 - } - } - return(this[1] & (1 << 32 - this.f) - 1) << this.f | this[0] -}; -q.fa = function(a, b) { - for(var c = 0, d = 0, e = Math.min(a.b, this.b);c < e;) { - d += this[c] + a[c], b[c++] = d & this.u, d >>= this.f - } - if(a.b < this.b) { - for(d += a.c;c < this.b;) { - d += this[c], b[c++] = d & this.u, d >>= this.f - } - d += this.c - }else { - for(d += this.c;c < a.b;) { - d += a[c], b[c++] = d & this.u, d >>= this.f - } - d += a.c - } - b.c = 0 > d ? -1 : 0; - 0 < d ? b[c++] = d : -1 > d && (b[c++] = this.K + d); - b.b = c; - b.C() -}; -var $ = {abs:function(a, b) { - var c = new Y(a, b), c = c.n() ? c.i() : c; - B[qb >> 2] = c.h; - B[qb + 4 >> 2] = c.j -}, Ka:function() { - $.kb || ($.kb = l, $.Xa = new X, $.Xa.k("4294967296", 10), $.sa = new X, $.sa.k("18446744073709551616", 10), $.xe = new X, $.ye = new X) -}, me:function(a, b) { - var c = new X; - c.k(b.toString(), 10); - var d = new X; - c.vb(d); - c = new X; - c.k(a.toString(), 10); - var e = new X; - c.fa(d, e); - return e -}, stringify:function(a, b, c) { - a = (new Y(a, b)).toString(); - c && "-" == a[0] && ($.Ka(), c = new X, c.k(a, 10), a = new X, $.sa.fa(c, a), a = a.toString(10)); - return a -}, k:function(a, b, c, d, e) { - $.Ka(); - var f = new X; - f.k(a, b); - a = new X; - a.k(c, 10); - c = new X; - c.k(d, 10); - e && 0 > f.U(X.ZERO) && (d = new X, f.fa($.sa, d), f = d); - d = p; - 0 > f.U(a) ? (f = a, d = l) : 0 < f.U(c) && (f = c, d = l); - f = Y.k(f.toString()); - B[qb >> 2] = f.h; - B[qb + 4 >> 2] = f.j; - d && g("range error") -}}; -lc = $; -var cd, dd; -s.callMain = s.$d = function(a) { - function b() { - for(var a = 0;3 > a;a++) { - d.push(0) - } - } - w(0 == L, "cannot call main when async dependencies remain! (listen on __ATMAIN__)"); - w(0 == Wa.length, "cannot call main when preRun functions remain to be called"); - a = a || []; - ab || (ab = l, Va(Xa)); - var c = a.length + 1, d = [F(J("/bin/this.program"), "i8", Ka)]; - b(); - for(var e = 0;e < c - 1;e += 1) { - d.push(F(J(a[e]), "i8", Ka)), b() - } - d.push(0); - d = F(d, "i32", Ka); - cd = u; - dd = l; - var f; - try { - f = s._main(c, d, 0) - }catch(h) { - if(h && "object" == typeof h && "ExitStatus" == h.type) { - return s.print("Exit Status: " + h.value), h.value - } - "SimulateInfiniteLoop" == h ? s.noExitRuntime = l : g(h) - }finally { - dd = p - } - s.noExitRuntime || ed(f) -}; -function lb(a) { - function b() { - ab || (ab = l, Va(Xa)); - Va(Ya); - gb = l; - s._main && kb && s.callMain(a); - if(s.postRun) { - for("function" == typeof s.postRun && (s.postRun = [s.postRun]);s.postRun.length;) { - cb(s.postRun.shift()) - } - } - Va($a) - } - a = a || s.arguments; - if(0 < L) { - s.P("run() called, but dependencies remain, so not running") - }else { - if(s.preRun) { - for("function" == typeof s.preRun && (s.preRun = [s.preRun]);s.preRun.length;) { - bb(s.preRun.shift()) - } - } - Va(Wa); - 0 < L || (s.setStatus ? (s.setStatus("Running..."), setTimeout(function() { - setTimeout(function() { - s.setStatus("") - }, 1); - za || b() - }, 1)) : b()) - } -} -s.run = s.we = lb; -function ed(a) { - za = l; - u = cd; - Va(Za); - dd && g({type:"ExitStatus", value:a}) -} -s.exit = s.de = ed; -function wa(a) { - a && s.print(a); - za = l; - g("abort() at " + Error().stack) -} -s.abort = s.abort = wa; -if(s.preInit) { - for("function" == typeof s.preInit && (s.preInit = [s.preInit]);0 < s.preInit.length;) { - s.preInit.pop()() - } -} -var kb = l; -s.noInitialRun && (kb = p); -lb(); -var scrypt = (function () { - var exports = {}; - - //--------------------------------------------------------------------------- - // Horrifying UTF-8 and hex codecs - - function encode_utf8(s) { - return encode_latin1(unescape(encodeURIComponent(s))); - } - - function encode_latin1(s) { - var result = new Uint8Array(s.length); - for (var i = 0; i < s.length; i++) { - var c = s.charCodeAt(i); - if ((c & 0xff) !== c) throw {message: "Cannot encode string in Latin1", str: s}; - result[i] = (c & 0xff); - } - return result; - } - - function decode_utf8(bs) { - return decodeURIComponent(escape(decode_latin1(bs))); - } - - function decode_latin1(bs) { - var encoded = []; - for (var i = 0; i < bs.length; i++) { - encoded.push(String.fromCharCode(bs[i])); - } - return encoded.join(''); - } - - function to_hex(bs) { - var encoded = []; - for (var i = 0; i < bs.length; i++) { - encoded.push("0123456789abcdef"[(bs[i] >> 4) & 15]); - encoded.push("0123456789abcdef"[bs[i] & 15]); - } - return encoded.join(''); - } - - //--------------------------------------------------------------------------- - - function injectBytes(bs, leftPadding) { - var p = leftPadding || 0; - var address = scrypt_raw._malloc(bs.length + p); - scrypt_raw.HEAPU8.set(bs, address + p); - for (var i = address; i < address + p; i++) { - scrypt_raw.HEAPU8[i] = 0; - } - return address; - } - - function check_injectBytes(function_name, what, thing, expected_length, leftPadding) { - check_length(function_name, what, thing, expected_length); - return injectBytes(thing, leftPadding); - } - - function extractBytes(address, length) { - var result = new Uint8Array(length); - result.set(scrypt_raw.HEAPU8.subarray(address, address + length)); - return result; - } - - //--------------------------------------------------------------------------- - - function check(function_name, result) { - if (result !== 0) { - throw {message: "scrypt_raw." + function_name + " signalled an error"}; - } - } - - function check_length(function_name, what, thing, expected_length) { - if (thing.length !== expected_length) { - throw {message: "scrypt." + function_name + " expected " + - expected_length + "-byte " + what + " but got length " + thing.length}; - } - } - - function Target(length) { - this.length = length; - this.address = scrypt_raw._malloc(length); - } - - Target.prototype.extractBytes = function (offset) { - var result = extractBytes(this.address + (offset || 0), this.length - (offset || 0)); - scrypt_raw._free(this.address); - this.address = null; - return result; - }; - - function free_all(addresses) { - for (var i = 0; i < addresses.length; i++) { - scrypt_raw._free(addresses[i]); - } - } - - //--------------------------------------------------------------------------- - - function random_bytes(count) { - var bs = new Uint8Array(count); - if(typeof(window.crypto) !== "undefined") { - if(typeof(window.crypto.getRandomValues) !== "undefined") { - window.crypto.getRandomValues(bs); - return bs; - } - } - if(typeof(window.msCrypto) !== "undefined") { - if(typeof(window.msCrypto.getRandomValues) !== "undefined") { - window.msCrypto.getRandomValues(bs); - return bs; - } - } - throw { message: "No suitable random number generator found!"}; - } - - function crypto_scrypt(passwd, salt, n, r, p, buflen) { - var buf = new Target(buflen); - var pa = injectBytes(passwd); - var sa = injectBytes(salt); - check("_crypto_scrypt", - scrypt_raw._crypto_scrypt(pa, passwd.length, - sa, salt.length, - n, 0, // 64 bits; zero upper half - r, - p, - buf.address, buf.length)); - free_all([pa, sa]); - return buf.extractBytes(); - } - - //--------------------------------------------------------------------------- - - exports.encode_utf8 = encode_utf8; - exports.encode_latin1 = encode_latin1; - exports.decode_utf8 = decode_utf8; - exports.decode_latin1 = decode_latin1; - exports.to_hex = to_hex; - - exports.random_bytes = random_bytes; - exports.crypto_scrypt = crypto_scrypt; - - return exports; -})(); - return scrypt; -}); - diff --git a/assets/www/js/vendor/socket-io.js b/assets/www/js/vendor/socket-io.js deleted file mode 100644 index b848ccb276b31924469e0d767bdd2aa5e3be0562..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/socket-io.js +++ /dev/null @@ -1,7000 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.io=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ - - module.exports = _dereq_('./lib/'); - -},{"./lib/":2}],2:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var url = _dereq_('./url'); - var parser = _dereq_('socket.io-parser'); - var Manager = _dereq_('./manager'); - var debug = _dereq_('debug')('socket.io-client'); - - /** - * Module exports. - */ - - module.exports = exports = lookup; - - /** - * Managers cache. - */ - - var cache = exports.managers = {}; - - /** - * Looks up an existing `Manager` for multiplexing. - * If the user summons: - * - * `io('http://localhost/a');` - * `io('http://localhost/b');` - * - * We reuse the existing instance based on same scheme/port/host, - * and we initialize sockets for each namespace. - * - * @api public - */ - - function lookup(uri, opts) { - if (typeof uri == 'object') { - opts = uri; - uri = undefined; - } - - opts = opts || {}; - - var parsed = url(uri); - var source = parsed.source; - var id = parsed.id; - var io; - - if (opts.forceNew || opts['force new connection'] || false === opts.multiplex) { - debug('ignoring socket cache for %s', source); - io = Manager(source, opts); - } else { - if (!cache[id]) { - debug('new io instance for %s', source); - cache[id] = Manager(source, opts); - } - io = cache[id]; - } - - return io.socket(parsed.path); - } - - /** - * Protocol version. - * - * @api public - */ - - exports.protocol = parser.protocol; - - /** - * `connect`. - * - * @param {String} uri - * @api public - */ - - exports.connect = lookup; - - /** - * Expose constructors for standalone build. - * - * @api public - */ - - exports.Manager = _dereq_('./manager'); - exports.Socket = _dereq_('./socket'); - -},{"./manager":3,"./socket":5,"./url":6,"debug":10,"socket.io-parser":46}],3:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var url = _dereq_('./url'); - var eio = _dereq_('engine.io-client'); - var Socket = _dereq_('./socket'); - var Emitter = _dereq_('component-emitter'); - var parser = _dereq_('socket.io-parser'); - var on = _dereq_('./on'); - var bind = _dereq_('component-bind'); - var object = _dereq_('object-component'); - var debug = _dereq_('debug')('socket.io-client:manager'); - var indexOf = _dereq_('indexof'); - var Backoff = _dereq_('backo2'); - - /** - * Module exports - */ - - module.exports = Manager; - - /** - * `Manager` constructor. - * - * @param {String} engine instance or engine uri/opts - * @param {Object} options - * @api public - */ - - function Manager(uri, opts){ - if (!(this instanceof Manager)) return new Manager(uri, opts); - if (uri && ('object' == typeof uri)) { - opts = uri; - uri = undefined; - } - opts = opts || {}; - - opts.path = opts.path || '/socket.io'; - this.nsps = {}; - this.subs = []; - this.opts = opts; - this.reconnection(opts.reconnection !== false); - this.reconnectionAttempts(opts.reconnectionAttempts || Infinity); - this.reconnectionDelay(opts.reconnectionDelay || 1000); - this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000); - this.randomizationFactor(opts.randomizationFactor || 0.5); - this.backoff = new Backoff({ - min: this.reconnectionDelay(), - max: this.reconnectionDelayMax(), - jitter: this.randomizationFactor() - }); - this.timeout(null == opts.timeout ? 20000 : opts.timeout); - this.readyState = 'closed'; - this.uri = uri; - this.connected = []; - this.encoding = false; - this.packetBuffer = []; - this.encoder = new parser.Encoder(); - this.decoder = new parser.Decoder(); - this.autoConnect = opts.autoConnect !== false; - if (this.autoConnect) this.open(); - } - - /** - * Propagate given event to sockets and emit on `this` - * - * @api private - */ - - Manager.prototype.emitAll = function() { - this.emit.apply(this, arguments); - for (var nsp in this.nsps) { - this.nsps[nsp].emit.apply(this.nsps[nsp], arguments); - } - }; - - /** - * Update `socket.id` of all sockets - * - * @api private - */ - - Manager.prototype.updateSocketIds = function(){ - for (var nsp in this.nsps) { - this.nsps[nsp].id = this.engine.id; - } - }; - - /** - * Mix in `Emitter`. - */ - - Emitter(Manager.prototype); - - /** - * Sets the `reconnection` config. - * - * @param {Boolean} true/false if it should automatically reconnect - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnection = function(v){ - if (!arguments.length) return this._reconnection; - this._reconnection = !!v; - return this; - }; - - /** - * Sets the reconnection attempts config. - * - * @param {Number} max reconnection attempts before giving up - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnectionAttempts = function(v){ - if (!arguments.length) return this._reconnectionAttempts; - this._reconnectionAttempts = v; - return this; - }; - - /** - * Sets the delay between reconnections. - * - * @param {Number} delay - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnectionDelay = function(v){ - if (!arguments.length) return this._reconnectionDelay; - this._reconnectionDelay = v; - this.backoff && this.backoff.setMin(v); - return this; - }; - - Manager.prototype.randomizationFactor = function(v){ - if (!arguments.length) return this._randomizationFactor; - this._randomizationFactor = v; - this.backoff && this.backoff.setJitter(v); - return this; - }; - - /** - * Sets the maximum delay between reconnections. - * - * @param {Number} delay - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnectionDelayMax = function(v){ - if (!arguments.length) return this._reconnectionDelayMax; - this._reconnectionDelayMax = v; - this.backoff && this.backoff.setMax(v); - return this; - }; - - /** - * Sets the connection timeout. `false` to disable - * - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.timeout = function(v){ - if (!arguments.length) return this._timeout; - this._timeout = v; - return this; - }; - - /** - * Starts trying to reconnect if reconnection is enabled and we have not - * started reconnecting yet - * - * @api private - */ - - Manager.prototype.maybeReconnectOnOpen = function() { - // Only try to reconnect if it's the first time we're connecting - if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) { - // keeps reconnection from firing twice for the same reconnection loop - this.reconnect(); - } - }; - - - /** - * Sets the current transport `socket`. - * - * @param {Function} optional, callback - * @return {Manager} self - * @api public - */ - - Manager.prototype.open = - Manager.prototype.connect = function(fn){ - debug('readyState %s', this.readyState); - if (~this.readyState.indexOf('open')) return this; - - debug('opening %s', this.uri); - this.engine = eio(this.uri, this.opts); - var socket = this.engine; - var self = this; - this.readyState = 'opening'; - this.skipReconnect = false; - - // emit `open` - var openSub = on(socket, 'open', function() { - self.onopen(); - fn && fn(); - }); - - // emit `connect_error` - var errorSub = on(socket, 'error', function(data){ - debug('connect_error'); - self.cleanup(); - self.readyState = 'closed'; - self.emitAll('connect_error', data); - if (fn) { - var err = new Error('Connection error'); - err.data = data; - fn(err); - } else { - // Only do this if there is no fn to handle the error - self.maybeReconnectOnOpen(); - } - }); - - // emit `connect_timeout` - if (false !== this._timeout) { - var timeout = this._timeout; - debug('connect attempt will timeout after %d', timeout); - - // set timer - var timer = setTimeout(function(){ - debug('connect attempt timed out after %d', timeout); - openSub.destroy(); - socket.close(); - socket.emit('error', 'timeout'); - self.emitAll('connect_timeout', timeout); - }, timeout); - - this.subs.push({ - destroy: function(){ - clearTimeout(timer); - } - }); - } - - this.subs.push(openSub); - this.subs.push(errorSub); - - return this; - }; - - /** - * Called upon transport open. - * - * @api private - */ - - Manager.prototype.onopen = function(){ - debug('open'); - - // clear old subs - this.cleanup(); - - // mark as open - this.readyState = 'open'; - this.emit('open'); - - // add new subs - var socket = this.engine; - this.subs.push(on(socket, 'data', bind(this, 'ondata'))); - this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded'))); - this.subs.push(on(socket, 'error', bind(this, 'onerror'))); - this.subs.push(on(socket, 'close', bind(this, 'onclose'))); - }; - - /** - * Called with data. - * - * @api private - */ - - Manager.prototype.ondata = function(data){ - this.decoder.add(data); - }; - - /** - * Called when parser fully decodes a packet. - * - * @api private - */ - - Manager.prototype.ondecoded = function(packet) { - this.emit('packet', packet); - }; - - /** - * Called upon socket error. - * - * @api private - */ - - Manager.prototype.onerror = function(err){ - debug('error', err); - this.emitAll('error', err); - }; - - /** - * Creates a new socket for the given `nsp`. - * - * @return {Socket} - * @api public - */ - - Manager.prototype.socket = function(nsp){ - var socket = this.nsps[nsp]; - if (!socket) { - socket = new Socket(this, nsp); - this.nsps[nsp] = socket; - var self = this; - socket.on('connect', function(){ - socket.id = self.engine.id; - if (!~indexOf(self.connected, socket)) { - self.connected.push(socket); - } - }); - } - return socket; - }; - - /** - * Called upon a socket close. - * - * @param {Socket} socket - */ - - Manager.prototype.destroy = function(socket){ - var index = indexOf(this.connected, socket); - if (~index) this.connected.splice(index, 1); - if (this.connected.length) return; - - this.close(); - }; - - /** - * Writes a packet. - * - * @param {Object} packet - * @api private - */ - - Manager.prototype.packet = function(packet){ - debug('writing packet %j', packet); - var self = this; - - if (!self.encoding) { - // encode, then write to engine with result - self.encoding = true; - this.encoder.encode(packet, function(encodedPackets) { - for (var i = 0; i < encodedPackets.length; i++) { - self.engine.write(encodedPackets[i]); - } - self.encoding = false; - self.processPacketQueue(); - }); - } else { // add packet to the queue - self.packetBuffer.push(packet); - } - }; - - /** - * If packet buffer is non-empty, begins encoding the - * next packet in line. - * - * @api private - */ - - Manager.prototype.processPacketQueue = function() { - if (this.packetBuffer.length > 0 && !this.encoding) { - var pack = this.packetBuffer.shift(); - this.packet(pack); - } - }; - - /** - * Clean up transport subscriptions and packet buffer. - * - * @api private - */ - - Manager.prototype.cleanup = function(){ - var sub; - while (sub = this.subs.shift()) sub.destroy(); - - this.packetBuffer = []; - this.encoding = false; - - this.decoder.destroy(); - }; - - /** - * Close the current socket. - * - * @api private - */ - - Manager.prototype.close = - Manager.prototype.disconnect = function(){ - this.skipReconnect = true; - this.backoff.reset(); - this.readyState = 'closed'; - this.engine && this.engine.close(); - }; - - /** - * Called upon engine close. - * - * @api private - */ - - Manager.prototype.onclose = function(reason){ - debug('close'); - this.cleanup(); - this.backoff.reset(); - this.readyState = 'closed'; - this.emit('close', reason); - if (this._reconnection && !this.skipReconnect) { - this.reconnect(); - } - }; - - /** - * Attempt a reconnection. - * - * @api private - */ - - Manager.prototype.reconnect = function(){ - if (this.reconnecting || this.skipReconnect) return this; - - var self = this; - - if (this.backoff.attempts >= this._reconnectionAttempts) { - debug('reconnect failed'); - this.backoff.reset(); - this.emitAll('reconnect_failed'); - this.reconnecting = false; - } else { - var delay = this.backoff.duration(); - debug('will wait %dms before reconnect attempt', delay); - - this.reconnecting = true; - var timer = setTimeout(function(){ - if (self.skipReconnect) return; - - debug('attempting reconnect'); - self.emitAll('reconnect_attempt', self.backoff.attempts); - self.emitAll('reconnecting', self.backoff.attempts); - - // check again for the case socket closed in above events - if (self.skipReconnect) return; - - self.open(function(err){ - if (err) { - debug('reconnect attempt error'); - self.reconnecting = false; - self.reconnect(); - self.emitAll('reconnect_error', err.data); - } else { - debug('reconnect success'); - self.onreconnect(); - } - }); - }, delay); - - this.subs.push({ - destroy: function(){ - clearTimeout(timer); - } - }); - } - }; - - /** - * Called upon successful reconnect. - * - * @api private - */ - - Manager.prototype.onreconnect = function(){ - var attempt = this.backoff.attempts; - this.reconnecting = false; - this.backoff.reset(); - this.updateSocketIds(); - this.emitAll('reconnect', attempt); - }; - -},{"./on":4,"./socket":5,"./url":6,"backo2":7,"component-bind":8,"component-emitter":9,"debug":10,"engine.io-client":11,"indexof":42,"object-component":43,"socket.io-parser":46}],4:[function(_dereq_,module,exports){ - - /** - * Module exports. - */ - - module.exports = on; - - /** - * Helper for subscriptions. - * - * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter` - * @param {String} event name - * @param {Function} callback - * @api public - */ - - function on(obj, ev, fn) { - obj.on(ev, fn); - return { - destroy: function(){ - obj.removeListener(ev, fn); - } - }; - } - -},{}],5:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var parser = _dereq_('socket.io-parser'); - var Emitter = _dereq_('component-emitter'); - var toArray = _dereq_('to-array'); - var on = _dereq_('./on'); - var bind = _dereq_('component-bind'); - var debug = _dereq_('debug')('socket.io-client:socket'); - var hasBin = _dereq_('has-binary'); - - /** - * Module exports. - */ - - module.exports = exports = Socket; - - /** - * Internal events (blacklisted). - * These events can't be emitted by the user. - * - * @api private - */ - - var events = { - connect: 1, - connect_error: 1, - connect_timeout: 1, - disconnect: 1, - error: 1, - reconnect: 1, - reconnect_attempt: 1, - reconnect_failed: 1, - reconnect_error: 1, - reconnecting: 1 - }; - - /** - * Shortcut to `Emitter#emit`. - */ - - var emit = Emitter.prototype.emit; - - /** - * `Socket` constructor. - * - * @api public - */ - - function Socket(io, nsp){ - this.io = io; - this.nsp = nsp; - this.json = this; // compat - this.ids = 0; - this.acks = {}; - if (this.io.autoConnect) this.open(); - this.receiveBuffer = []; - this.sendBuffer = []; - this.connected = false; - this.disconnected = true; - } - - /** - * Mix in `Emitter`. - */ - - Emitter(Socket.prototype); - - /** - * Subscribe to open, close and packet events - * - * @api private - */ - - Socket.prototype.subEvents = function() { - if (this.subs) return; - - var io = this.io; - this.subs = [ - on(io, 'open', bind(this, 'onopen')), - on(io, 'packet', bind(this, 'onpacket')), - on(io, 'close', bind(this, 'onclose')) - ]; - }; - - /** - * "Opens" the socket. - * - * @api public - */ - - Socket.prototype.open = - Socket.prototype.connect = function(){ - if (this.connected) return this; - - this.subEvents(); - this.io.open(); // ensure open - if ('open' == this.io.readyState) this.onopen(); - return this; - }; - - /** - * Sends a `message` event. - * - * @return {Socket} self - * @api public - */ - - Socket.prototype.send = function(){ - var args = toArray(arguments); - args.unshift('message'); - this.emit.apply(this, args); - return this; - }; - - /** - * Override `emit`. - * If the event is in `events`, it's emitted normally. - * - * @param {String} event name - * @return {Socket} self - * @api public - */ - - Socket.prototype.emit = function(ev){ - if (events.hasOwnProperty(ev)) { - emit.apply(this, arguments); - return this; - } - - var args = toArray(arguments); - var parserType = parser.EVENT; // default - if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary - var packet = { type: parserType, data: args }; - - // event ack callback - if ('function' == typeof args[args.length - 1]) { - debug('emitting packet with ack id %d', this.ids); - this.acks[this.ids] = args.pop(); - packet.id = this.ids++; - } - - if (this.connected) { - this.packet(packet); - } else { - this.sendBuffer.push(packet); - } - - return this; - }; - - /** - * Sends a packet. - * - * @param {Object} packet - * @api private - */ - - Socket.prototype.packet = function(packet){ - packet.nsp = this.nsp; - this.io.packet(packet); - }; - - /** - * Called upon engine `open`. - * - * @api private - */ - - Socket.prototype.onopen = function(){ - debug('transport is open - connecting'); - - // write connect packet if necessary - if ('/' != this.nsp) { - this.packet({ type: parser.CONNECT }); - } - }; - - /** - * Called upon engine `close`. - * - * @param {String} reason - * @api private - */ - - Socket.prototype.onclose = function(reason){ - debug('close (%s)', reason); - this.connected = false; - this.disconnected = true; - delete this.id; - this.emit('disconnect', reason); - }; - - /** - * Called with socket packet. - * - * @param {Object} packet - * @api private - */ - - Socket.prototype.onpacket = function(packet){ - if (packet.nsp != this.nsp) return; - - switch (packet.type) { - case parser.CONNECT: - this.onconnect(); - break; - - case parser.EVENT: - this.onevent(packet); - break; - - case parser.BINARY_EVENT: - this.onevent(packet); - break; - - case parser.ACK: - this.onack(packet); - break; - - case parser.BINARY_ACK: - this.onack(packet); - break; - - case parser.DISCONNECT: - this.ondisconnect(); - break; - - case parser.ERROR: - this.emit('error', packet.data); - break; - } - }; - - /** - * Called upon a server event. - * - * @param {Object} packet - * @api private - */ - - Socket.prototype.onevent = function(packet){ - var args = packet.data || []; - debug('emitting event %j', args); - - if (null != packet.id) { - debug('attaching ack callback to event'); - args.push(this.ack(packet.id)); - } - - if (this.connected) { - emit.apply(this, args); - } else { - this.receiveBuffer.push(args); - } - }; - - /** - * Produces an ack callback to emit with an event. - * - * @api private - */ - - Socket.prototype.ack = function(id){ - var self = this; - var sent = false; - return function(){ - // prevent double callbacks - if (sent) return; - sent = true; - var args = toArray(arguments); - debug('sending ack %j', args); - - var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK; - self.packet({ - type: type, - id: id, - data: args - }); - }; - }; - - /** - * Called upon a server acknowlegement. - * - * @param {Object} packet - * @api private - */ - - Socket.prototype.onack = function(packet){ - debug('calling ack %s with %j', packet.id, packet.data); - var fn = this.acks[packet.id]; - fn.apply(this, packet.data); - delete this.acks[packet.id]; - }; - - /** - * Called upon server connect. - * - * @api private - */ - - Socket.prototype.onconnect = function(){ - this.connected = true; - this.disconnected = false; - this.emit('connect'); - this.emitBuffered(); - }; - - /** - * Emit buffered events (received and emitted). - * - * @api private - */ - - Socket.prototype.emitBuffered = function(){ - var i; - for (i = 0; i < this.receiveBuffer.length; i++) { - emit.apply(this, this.receiveBuffer[i]); - } - this.receiveBuffer = []; - - for (i = 0; i < this.sendBuffer.length; i++) { - this.packet(this.sendBuffer[i]); - } - this.sendBuffer = []; - }; - - /** - * Called upon server disconnect. - * - * @api private - */ - - Socket.prototype.ondisconnect = function(){ - debug('server disconnect (%s)', this.nsp); - this.destroy(); - this.onclose('io server disconnect'); - }; - - /** - * Called upon forced client/server side disconnections, - * this method ensures the manager stops tracking us and - * that reconnections don't get triggered for this. - * - * @api private. - */ - - Socket.prototype.destroy = function(){ - if (this.subs) { - // clean subscriptions to avoid reconnections - for (var i = 0; i < this.subs.length; i++) { - this.subs[i].destroy(); - } - this.subs = null; - } - - this.io.destroy(this); - }; - - /** - * Disconnects the socket manually. - * - * @return {Socket} self - * @api public - */ - - Socket.prototype.close = - Socket.prototype.disconnect = function(){ - if (this.connected) { - debug('performing disconnect (%s)', this.nsp); - this.packet({ type: parser.DISCONNECT }); - } - - // remove socket from pool - this.destroy(); - - if (this.connected) { - // fire events - this.onclose('io client disconnect'); - } - return this; - }; - -},{"./on":4,"component-bind":8,"component-emitter":9,"debug":10,"has-binary":38,"socket.io-parser":46,"to-array":50}],6:[function(_dereq_,module,exports){ - (function (global){ - - /** - * Module dependencies. - */ - - var parseuri = _dereq_('parseuri'); - var debug = _dereq_('debug')('socket.io-client:url'); - - /** - * Module exports. - */ - - module.exports = url; - - /** - * URL parser. - * - * @param {String} url - * @param {Object} An object meant to mimic window.location. - * Defaults to window.location. - * @api public - */ - - function url(uri, loc){ - var obj = uri; - - // default to window.location - var loc = loc || global.location; - if (null == uri) uri = loc.protocol + '//' + loc.host; - - // relative path support - if ('string' == typeof uri) { - if ('/' == uri.charAt(0)) { - if ('/' == uri.charAt(1)) { - uri = loc.protocol + uri; - } else { - uri = loc.hostname + uri; - } - } - - if (!/^(https?|wss?):\/\//.test(uri)) { - debug('protocol-less url %s', uri); - if ('undefined' != typeof loc) { - uri = loc.protocol + '//' + uri; - } else { - uri = 'https://' + uri; - } - } - - // parse - debug('parse %s', uri); - obj = parseuri(uri); - } - - // make sure we treat `localhost:80` and `localhost` equally - if (!obj.port) { - if (/^(http|ws)$/.test(obj.protocol)) { - obj.port = '80'; - } - else if (/^(http|ws)s$/.test(obj.protocol)) { - obj.port = '443'; - } - } - - obj.path = obj.path || '/'; - - // define unique id - obj.id = obj.protocol + '://' + obj.host + ':' + obj.port; - // define href - obj.href = obj.protocol + '://' + obj.host + (loc && loc.port == obj.port ? '' : (':' + obj.port)); - - return obj; - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"debug":10,"parseuri":44}],7:[function(_dereq_,module,exports){ - - /** - * Expose `Backoff`. - */ - - module.exports = Backoff; - - /** - * Initialize backoff timer with `opts`. - * - * - `min` initial timeout in milliseconds [100] - * - `max` max timeout [10000] - * - `jitter` [0] - * - `factor` [2] - * - * @param {Object} opts - * @api public - */ - - function Backoff(opts) { - opts = opts || {}; - this.ms = opts.min || 100; - this.max = opts.max || 10000; - this.factor = opts.factor || 2; - this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0; - this.attempts = 0; - } - - /** - * Return the backoff duration. - * - * @return {Number} - * @api public - */ - - Backoff.prototype.duration = function(){ - var ms = this.ms * Math.pow(this.factor, this.attempts++); - if (this.jitter) { - var rand = Math.random(); - var deviation = Math.floor(rand * this.jitter * ms); - ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation; - } - return Math.min(ms, this.max) | 0; - }; - - /** - * Reset the number of attempts. - * - * @api public - */ - - Backoff.prototype.reset = function(){ - this.attempts = 0; - }; - - /** - * Set the minimum duration - * - * @api public - */ - - Backoff.prototype.setMin = function(min){ - this.ms = min; - }; - - /** - * Set the maximum duration - * - * @api public - */ - - Backoff.prototype.setMax = function(max){ - this.max = max; - }; - - /** - * Set the jitter - * - * @api public - */ - - Backoff.prototype.setJitter = function(jitter){ - this.jitter = jitter; - }; - - -},{}],8:[function(_dereq_,module,exports){ - /** - * Slice reference. - */ - - var slice = [].slice; - - /** - * Bind `obj` to `fn`. - * - * @param {Object} obj - * @param {Function|String} fn or string - * @return {Function} - * @api public - */ - - module.exports = function(obj, fn){ - if ('string' == typeof fn) fn = obj[fn]; - if ('function' != typeof fn) throw new Error('bind() requires a function'); - var args = slice.call(arguments, 2); - return function(){ - return fn.apply(obj, args.concat(slice.call(arguments))); - } - }; - -},{}],9:[function(_dereq_,module,exports){ - - /** - * Expose `Emitter`. - */ - - module.exports = Emitter; - - /** - * Initialize a new `Emitter`. - * - * @api public - */ - - function Emitter(obj) { - if (obj) return mixin(obj); - }; - - /** - * Mixin the emitter properties. - * - * @param {Object} obj - * @return {Object} - * @api private - */ - - function mixin(obj) { - for (var key in Emitter.prototype) { - obj[key] = Emitter.prototype[key]; - } - return obj; - } - - /** - * Listen on the given `event` with `fn`. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - - Emitter.prototype.on = - Emitter.prototype.addEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - (this._callbacks[event] = this._callbacks[event] || []) - .push(fn); - return this; - }; - - /** - * Adds an `event` listener that will be invoked a single - * time then automatically removed. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - - Emitter.prototype.once = function(event, fn){ - var self = this; - this._callbacks = this._callbacks || {}; - - function on() { - self.off(event, on); - fn.apply(this, arguments); - } - - on.fn = fn; - this.on(event, on); - return this; - }; - - /** - * Remove the given callback for `event` or all - * registered callbacks. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - - Emitter.prototype.off = - Emitter.prototype.removeListener = - Emitter.prototype.removeAllListeners = - Emitter.prototype.removeEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - - // all - if (0 == arguments.length) { - this._callbacks = {}; - return this; - } - - // specific event - var callbacks = this._callbacks[event]; - if (!callbacks) return this; - - // remove all handlers - if (1 == arguments.length) { - delete this._callbacks[event]; - return this; - } - - // remove specific handler - var cb; - for (var i = 0; i < callbacks.length; i++) { - cb = callbacks[i]; - if (cb === fn || cb.fn === fn) { - callbacks.splice(i, 1); - break; - } - } - return this; - }; - - /** - * Emit `event` with the given args. - * - * @param {String} event - * @param {Mixed} ... - * @return {Emitter} - */ - - Emitter.prototype.emit = function(event){ - this._callbacks = this._callbacks || {}; - var args = [].slice.call(arguments, 1) - , callbacks = this._callbacks[event]; - - if (callbacks) { - callbacks = callbacks.slice(0); - for (var i = 0, len = callbacks.length; i < len; ++i) { - callbacks[i].apply(this, args); - } - } - - return this; - }; - - /** - * Return array of callbacks for `event`. - * - * @param {String} event - * @return {Array} - * @api public - */ - - Emitter.prototype.listeners = function(event){ - this._callbacks = this._callbacks || {}; - return this._callbacks[event] || []; - }; - - /** - * Check if this emitter has `event` handlers. - * - * @param {String} event - * @return {Boolean} - * @api public - */ - - Emitter.prototype.hasListeners = function(event){ - return !! this.listeners(event).length; - }; - -},{}],10:[function(_dereq_,module,exports){ - - /** - * Expose `debug()` as the module. - */ - - module.exports = debug; - - /** - * Create a debugger with the given `name`. - * - * @param {String} name - * @return {Type} - * @api public - */ - - function debug(name) { - if (!debug.enabled(name)) return function(){}; - - return function(fmt){ - fmt = coerce(fmt); - - var curr = new Date; - var ms = curr - (debug[name] || curr); - debug[name] = curr; - - fmt = name - + ' ' - + fmt - + ' +' + debug.humanize(ms); - - // This hackery is required for IE8 - // where `console.log` doesn't have 'apply' - window.console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); - } - } - - /** - * The currently active debug mode names. - */ - - debug.names = []; - debug.skips = []; - - /** - * Enables a debug mode by name. This can include modes - * separated by a colon and wildcards. - * - * @param {String} name - * @api public - */ - - debug.enable = function(name) { - try { - localStorage.debug = name; - } catch(e){} - - var split = (name || '').split(/[\s,]+/) - , len = split.length; - - for (var i = 0; i < len; i++) { - name = split[i].replace('*', '.*?'); - if (name[0] === '-') { - debug.skips.push(new RegExp('^' + name.substr(1) + '$')); - } - else { - debug.names.push(new RegExp('^' + name + '$')); - } - } - }; - - /** - * Disable debug output. - * - * @api public - */ - - debug.disable = function(){ - debug.enable(''); - }; - - /** - * Humanize the given `ms`. - * - * @param {Number} m - * @return {String} - * @api private - */ - - debug.humanize = function(ms) { - var sec = 1000 - , min = 60 * 1000 - , hour = 60 * min; - - if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; - if (ms >= min) return (ms / min).toFixed(1) + 'm'; - if (ms >= sec) return (ms / sec | 0) + 's'; - return ms + 'ms'; - }; - - /** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - - debug.enabled = function(name) { - for (var i = 0, len = debug.skips.length; i < len; i++) { - if (debug.skips[i].test(name)) { - return false; - } - } - for (var i = 0, len = debug.names.length; i < len; i++) { - if (debug.names[i].test(name)) { - return true; - } - } - return false; - }; - - /** - * Coerce `val`. - */ - - function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; - } - -// persist - - try { - if (window.localStorage) debug.enable(localStorage.debug); - } catch(e){} - -},{}],11:[function(_dereq_,module,exports){ - - module.exports = _dereq_('./lib/'); - -},{"./lib/":12}],12:[function(_dereq_,module,exports){ - - module.exports = _dereq_('./socket'); - - /** - * Exports parser - * - * @api public - * - */ - module.exports.parser = _dereq_('engine.io-parser'); - -},{"./socket":13,"engine.io-parser":25}],13:[function(_dereq_,module,exports){ - (function (global){ - /** - * Module dependencies. - */ - - var transports = _dereq_('./transports'); - var Emitter = _dereq_('component-emitter'); - var debug = _dereq_('debug')('engine.io-client:socket'); - var index = _dereq_('indexof'); - var parser = _dereq_('engine.io-parser'); - var parseuri = _dereq_('parseuri'); - var parsejson = _dereq_('parsejson'); - var parseqs = _dereq_('parseqs'); - - /** - * Module exports. - */ - - module.exports = Socket; - - /** - * Noop function. - * - * @api private - */ - - function noop(){} - - /** - * Socket constructor. - * - * @param {String|Object} uri or options - * @param {Object} options - * @api public - */ - - function Socket(uri, opts){ - if (!(this instanceof Socket)) return new Socket(uri, opts); - - opts = opts || {}; - - if (uri && 'object' == typeof uri) { - opts = uri; - uri = null; - } - - if (uri) { - uri = parseuri(uri); - opts.host = uri.host; - opts.secure = uri.protocol == 'https' || uri.protocol == 'wss'; - opts.port = uri.port; - if (uri.query) opts.query = uri.query; - } - - this.secure = null != opts.secure ? opts.secure : - (global.location && 'https:' == location.protocol); - - if (opts.host) { - var pieces = opts.host.split(':'); - opts.hostname = pieces.shift(); - if (pieces.length) { - opts.port = pieces.pop(); - } else if (!opts.port) { - // if no port is specified manually, use the protocol default - opts.port = this.secure ? '443' : '80'; - } - } - - this.agent = opts.agent || false; - this.hostname = opts.hostname || - (global.location ? location.hostname : 'localhost'); - this.port = opts.port || (global.location && location.port ? - location.port : - (this.secure ? 443 : 80)); - this.query = opts.query || {}; - if ('string' == typeof this.query) this.query = parseqs.decode(this.query); - this.upgrade = false !== opts.upgrade; - this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/'; - this.forceJSONP = !!opts.forceJSONP; - this.jsonp = false !== opts.jsonp; - this.forceBase64 = !!opts.forceBase64; - this.enablesXDR = !!opts.enablesXDR; - this.timestampParam = opts.timestampParam || 't'; - this.timestampRequests = opts.timestampRequests; - this.transports = opts.transports || ['polling', 'websocket']; - this.readyState = ''; - this.writeBuffer = []; - this.callbackBuffer = []; - this.policyPort = opts.policyPort || 843; - this.rememberUpgrade = opts.rememberUpgrade || false; - this.binaryType = null; - this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades; - - // SSL options for Node.js client - this.pfx = opts.pfx || null; - this.key = opts.key || null; - this.passphrase = opts.passphrase || null; - this.cert = opts.cert || null; - this.ca = opts.ca || null; - this.ciphers = opts.ciphers || null; - this.rejectUnauthorized = opts.rejectUnauthorized || null; - - this.open(); - } - - Socket.priorWebsocketSuccess = false; - - /** - * Mix in `Emitter`. - */ - - Emitter(Socket.prototype); - - /** - * Protocol version. - * - * @api public - */ - - Socket.protocol = parser.protocol; // this is an int - - /** - * Expose deps for legacy compatibility - * and standalone browser access. - */ - - Socket.Socket = Socket; - Socket.Transport = _dereq_('./transport'); - Socket.transports = _dereq_('./transports'); - Socket.parser = _dereq_('engine.io-parser'); - - /** - * Creates transport of the given type. - * - * @param {String} transport name - * @return {Transport} - * @api private - */ - - Socket.prototype.createTransport = function (name) { - debug('creating transport "%s"', name); - var query = clone(this.query); - - // append engine.io protocol identifier - query.EIO = parser.protocol; - - // transport name - query.transport = name; - - // session id if we already have one - if (this.id) query.sid = this.id; - - var transport = new transports[name]({ - agent: this.agent, - hostname: this.hostname, - port: this.port, - secure: this.secure, - path: this.path, - query: query, - forceJSONP: this.forceJSONP, - jsonp: this.jsonp, - forceBase64: this.forceBase64, - enablesXDR: this.enablesXDR, - timestampRequests: this.timestampRequests, - timestampParam: this.timestampParam, - policyPort: this.policyPort, - socket: this, - pfx: this.pfx, - key: this.key, - passphrase: this.passphrase, - cert: this.cert, - ca: this.ca, - ciphers: this.ciphers, - rejectUnauthorized: this.rejectUnauthorized - }); - - return transport; - }; - - function clone (obj) { - var o = {}; - for (var i in obj) { - if (obj.hasOwnProperty(i)) { - o[i] = obj[i]; - } - } - return o; - } - - /** - * Initializes transport to use and starts probe. - * - * @api private - */ - Socket.prototype.open = function () { - var transport; - if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') != -1) { - transport = 'websocket'; - } else if (0 == this.transports.length) { - // Emit error on next tick so it can be listened to - var self = this; - setTimeout(function() { - self.emit('error', 'No transports available'); - }, 0); - return; - } else { - transport = this.transports[0]; - } - this.readyState = 'opening'; - - // Retry with the next transport if the transport is disabled (jsonp: false) - var transport; - try { - transport = this.createTransport(transport); - } catch (e) { - this.transports.shift(); - this.open(); - return; - } - - transport.open(); - this.setTransport(transport); - }; - - /** - * Sets the current transport. Disables the existing one (if any). - * - * @api private - */ - - Socket.prototype.setTransport = function(transport){ - debug('setting transport %s', transport.name); - var self = this; - - if (this.transport) { - debug('clearing existing transport %s', this.transport.name); - this.transport.removeAllListeners(); - } - - // set up transport - this.transport = transport; - - // set up transport listeners - transport - .on('drain', function(){ - self.onDrain(); - }) - .on('packet', function(packet){ - self.onPacket(packet); - }) - .on('error', function(e){ - self.onError(e); - }) - .on('close', function(){ - self.onClose('transport close'); - }); - }; - - /** - * Probes a transport. - * - * @param {String} transport name - * @api private - */ - - Socket.prototype.probe = function (name) { - debug('probing transport "%s"', name); - var transport = this.createTransport(name, { probe: 1 }) - , failed = false - , self = this; - - Socket.priorWebsocketSuccess = false; - - function onTransportOpen(){ - if (self.onlyBinaryUpgrades) { - var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary; - failed = failed || upgradeLosesBinary; - } - if (failed) return; - - debug('probe transport "%s" opened', name); - transport.send([{ type: 'ping', data: 'probe' }]); - transport.once('packet', function (msg) { - if (failed) return; - if ('pong' == msg.type && 'probe' == msg.data) { - debug('probe transport "%s" pong', name); - self.upgrading = true; - self.emit('upgrading', transport); - if (!transport) return; - Socket.priorWebsocketSuccess = 'websocket' == transport.name; - - debug('pausing current transport "%s"', self.transport.name); - self.transport.pause(function () { - if (failed) return; - if ('closed' == self.readyState) return; - debug('changing transport and sending upgrade packet'); - - cleanup(); - - self.setTransport(transport); - transport.send([{ type: 'upgrade' }]); - self.emit('upgrade', transport); - transport = null; - self.upgrading = false; - self.flush(); - }); - } else { - debug('probe transport "%s" failed', name); - var err = new Error('probe error'); - err.transport = transport.name; - self.emit('upgradeError', err); - } - }); - } - - function freezeTransport() { - if (failed) return; - - // Any callback called by transport should be ignored since now - failed = true; - - cleanup(); - - transport.close(); - transport = null; - } - - //Handle any error that happens while probing - function onerror(err) { - var error = new Error('probe error: ' + err); - error.transport = transport.name; - - freezeTransport(); - - debug('probe transport "%s" failed because of error: %s', name, err); - - self.emit('upgradeError', error); - } - - function onTransportClose(){ - onerror("transport closed"); - } - - //When the socket is closed while we're probing - function onclose(){ - onerror("socket closed"); - } - - //When the socket is upgraded while we're probing - function onupgrade(to){ - if (transport && to.name != transport.name) { - debug('"%s" works - aborting "%s"', to.name, transport.name); - freezeTransport(); - } - } - - //Remove all listeners on the transport and on self - function cleanup(){ - transport.removeListener('open', onTransportOpen); - transport.removeListener('error', onerror); - transport.removeListener('close', onTransportClose); - self.removeListener('close', onclose); - self.removeListener('upgrading', onupgrade); - } - - transport.once('open', onTransportOpen); - transport.once('error', onerror); - transport.once('close', onTransportClose); - - this.once('close', onclose); - this.once('upgrading', onupgrade); - - transport.open(); - - }; - - /** - * Called when connection is deemed open. - * - * @api public - */ - - Socket.prototype.onOpen = function () { - debug('socket open'); - this.readyState = 'open'; - Socket.priorWebsocketSuccess = 'websocket' == this.transport.name; - this.emit('open'); - this.flush(); - - // we check for `readyState` in case an `open` - // listener already closed the socket - if ('open' == this.readyState && this.upgrade && this.transport.pause) { - debug('starting upgrade probes'); - for (var i = 0, l = this.upgrades.length; i < l; i++) { - this.probe(this.upgrades[i]); - } - } - }; - - /** - * Handles a packet. - * - * @api private - */ - - Socket.prototype.onPacket = function (packet) { - if ('opening' == this.readyState || 'open' == this.readyState) { - debug('socket receive: type "%s", data "%s"', packet.type, packet.data); - - this.emit('packet', packet); - - // Socket is live - any packet counts - this.emit('heartbeat'); - - switch (packet.type) { - case 'open': - this.onHandshake(parsejson(packet.data)); - break; - - case 'pong': - this.setPing(); - break; - - case 'error': - var err = new Error('server error'); - err.code = packet.data; - this.emit('error', err); - break; - - case 'message': - this.emit('data', packet.data); - this.emit('message', packet.data); - break; - } - } else { - debug('packet received with socket readyState "%s"', this.readyState); - } - }; - - /** - * Called upon handshake completion. - * - * @param {Object} handshake obj - * @api private - */ - - Socket.prototype.onHandshake = function (data) { - this.emit('handshake', data); - this.id = data.sid; - this.transport.query.sid = data.sid; - this.upgrades = this.filterUpgrades(data.upgrades); - this.pingInterval = data.pingInterval; - this.pingTimeout = data.pingTimeout; - this.onOpen(); - // In case open handler closes socket - if ('closed' == this.readyState) return; - this.setPing(); - - // Prolong liveness of socket on heartbeat - this.removeListener('heartbeat', this.onHeartbeat); - this.on('heartbeat', this.onHeartbeat); - }; - - /** - * Resets ping timeout. - * - * @api private - */ - - Socket.prototype.onHeartbeat = function (timeout) { - clearTimeout(this.pingTimeoutTimer); - var self = this; - self.pingTimeoutTimer = setTimeout(function () { - if ('closed' == self.readyState) return; - self.onClose('ping timeout'); - }, timeout || (self.pingInterval + self.pingTimeout)); - }; - - /** - * Pings server every `this.pingInterval` and expects response - * within `this.pingTimeout` or closes connection. - * - * @api private - */ - - Socket.prototype.setPing = function () { - var self = this; - clearTimeout(self.pingIntervalTimer); - self.pingIntervalTimer = setTimeout(function () { - debug('writing ping packet - expecting pong within %sms', self.pingTimeout); - self.ping(); - self.onHeartbeat(self.pingTimeout); - }, self.pingInterval); - }; - - /** - * Sends a ping packet. - * - * @api public - */ - - Socket.prototype.ping = function () { - this.sendPacket('ping'); - }; - - /** - * Called on `drain` event - * - * @api private - */ - - Socket.prototype.onDrain = function() { - for (var i = 0; i < this.prevBufferLen; i++) { - if (this.callbackBuffer[i]) { - this.callbackBuffer[i](); - } - } - - this.writeBuffer.splice(0, this.prevBufferLen); - this.callbackBuffer.splice(0, this.prevBufferLen); - - // setting prevBufferLen = 0 is very important - // for example, when upgrading, upgrade packet is sent over, - // and a nonzero prevBufferLen could cause problems on `drain` - this.prevBufferLen = 0; - - if (this.writeBuffer.length == 0) { - this.emit('drain'); - } else { - this.flush(); - } - }; - - /** - * Flush write buffers. - * - * @api private - */ - - Socket.prototype.flush = function () { - if ('closed' != this.readyState && this.transport.writable && - !this.upgrading && this.writeBuffer.length) { - debug('flushing %d packets in socket', this.writeBuffer.length); - this.transport.send(this.writeBuffer); - // keep track of current length of writeBuffer - // splice writeBuffer and callbackBuffer on `drain` - this.prevBufferLen = this.writeBuffer.length; - this.emit('flush'); - } - }; - - /** - * Sends a message. - * - * @param {String} message. - * @param {Function} callback function. - * @return {Socket} for chaining. - * @api public - */ - - Socket.prototype.write = - Socket.prototype.send = function (msg, fn) { - this.sendPacket('message', msg, fn); - return this; - }; - - /** - * Sends a packet. - * - * @param {String} packet type. - * @param {String} data. - * @param {Function} callback function. - * @api private - */ - - Socket.prototype.sendPacket = function (type, data, fn) { - if ('closing' == this.readyState || 'closed' == this.readyState) { - return; - } - - var packet = { type: type, data: data }; - this.emit('packetCreate', packet); - this.writeBuffer.push(packet); - this.callbackBuffer.push(fn); - this.flush(); - }; - - /** - * Closes the connection. - * - * @api private - */ - - Socket.prototype.close = function () { - if ('opening' == this.readyState || 'open' == this.readyState) { - this.readyState = 'closing'; - - var self = this; - - function close() { - self.onClose('forced close'); - debug('socket closing - telling transport to close'); - self.transport.close(); - } - - function cleanupAndClose() { - self.removeListener('upgrade', cleanupAndClose); - self.removeListener('upgradeError', cleanupAndClose); - close(); - } - - function waitForUpgrade() { - // wait for upgrade to finish since we can't send packets while pausing a transport - self.once('upgrade', cleanupAndClose); - self.once('upgradeError', cleanupAndClose); - } - - if (this.writeBuffer.length) { - this.once('drain', function() { - if (this.upgrading) { - waitForUpgrade(); - } else { - close(); - } - }); - } else if (this.upgrading) { - waitForUpgrade(); - } else { - close(); - } - } - - return this; - }; - - /** - * Called upon transport error - * - * @api private - */ - - Socket.prototype.onError = function (err) { - debug('socket error %j', err); - Socket.priorWebsocketSuccess = false; - this.emit('error', err); - this.onClose('transport error', err); - }; - - /** - * Called upon transport close. - * - * @api private - */ - - Socket.prototype.onClose = function (reason, desc) { - if ('opening' == this.readyState || 'open' == this.readyState || 'closing' == this.readyState) { - debug('socket close with reason: "%s"', reason); - var self = this; - - // clear timers - clearTimeout(this.pingIntervalTimer); - clearTimeout(this.pingTimeoutTimer); - - // clean buffers in next tick, so developers can still - // grab the buffers on `close` event - setTimeout(function() { - self.writeBuffer = []; - self.callbackBuffer = []; - self.prevBufferLen = 0; - }, 0); - - // stop event from firing again for transport - this.transport.removeAllListeners('close'); - - // ensure transport won't stay open - this.transport.close(); - - // ignore further transport communication - this.transport.removeAllListeners(); - - // set ready state - this.readyState = 'closed'; - - // clear session id - this.id = null; - - // emit close event - this.emit('close', reason, desc); - } - }; - - /** - * Filters upgrades, returning only those matching client transports. - * - * @param {Array} server upgrades - * @api private - * - */ - - Socket.prototype.filterUpgrades = function (upgrades) { - var filteredUpgrades = []; - for (var i = 0, j = upgrades.length; i<j; i++) { - if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]); - } - return filteredUpgrades; - }; - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./transport":14,"./transports":15,"component-emitter":9,"debug":22,"engine.io-parser":25,"indexof":42,"parsejson":34,"parseqs":35,"parseuri":36}],14:[function(_dereq_,module,exports){ - /** - * Module dependencies. - */ - - var parser = _dereq_('engine.io-parser'); - var Emitter = _dereq_('component-emitter'); - - /** - * Module exports. - */ - - module.exports = Transport; - - /** - * Transport abstract constructor. - * - * @param {Object} options. - * @api private - */ - - function Transport (opts) { - this.path = opts.path; - this.hostname = opts.hostname; - this.port = opts.port; - this.secure = opts.secure; - this.query = opts.query; - this.timestampParam = opts.timestampParam; - this.timestampRequests = opts.timestampRequests; - this.readyState = ''; - this.agent = opts.agent || false; - this.socket = opts.socket; - this.enablesXDR = opts.enablesXDR; - - // SSL options for Node.js client - this.pfx = opts.pfx; - this.key = opts.key; - this.passphrase = opts.passphrase; - this.cert = opts.cert; - this.ca = opts.ca; - this.ciphers = opts.ciphers; - this.rejectUnauthorized = opts.rejectUnauthorized; - } - - /** - * Mix in `Emitter`. - */ - - Emitter(Transport.prototype); - - /** - * A counter used to prevent collisions in the timestamps used - * for cache busting. - */ - - Transport.timestamps = 0; - - /** - * Emits an error. - * - * @param {String} str - * @return {Transport} for chaining - * @api public - */ - - Transport.prototype.onError = function (msg, desc) { - var err = new Error(msg); - err.type = 'TransportError'; - err.description = desc; - this.emit('error', err); - return this; - }; - - /** - * Opens the transport. - * - * @api public - */ - - Transport.prototype.open = function () { - if ('closed' == this.readyState || '' == this.readyState) { - this.readyState = 'opening'; - this.doOpen(); - } - - return this; - }; - - /** - * Closes the transport. - * - * @api private - */ - - Transport.prototype.close = function () { - if ('opening' == this.readyState || 'open' == this.readyState) { - this.doClose(); - this.onClose(); - } - - return this; - }; - - /** - * Sends multiple packets. - * - * @param {Array} packets - * @api private - */ - - Transport.prototype.send = function(packets){ - if ('open' == this.readyState) { - this.write(packets); - } else { - throw new Error('Transport not open'); - } - }; - - /** - * Called upon open - * - * @api private - */ - - Transport.prototype.onOpen = function () { - this.readyState = 'open'; - this.writable = true; - this.emit('open'); - }; - - /** - * Called with data. - * - * @param {String} data - * @api private - */ - - Transport.prototype.onData = function(data){ - var packet = parser.decodePacket(data, this.socket.binaryType); - this.onPacket(packet); - }; - - /** - * Called with a decoded packet. - */ - - Transport.prototype.onPacket = function (packet) { - this.emit('packet', packet); - }; - - /** - * Called upon close. - * - * @api private - */ - - Transport.prototype.onClose = function () { - this.readyState = 'closed'; - this.emit('close'); - }; - -},{"component-emitter":9,"engine.io-parser":25}],15:[function(_dereq_,module,exports){ - (function (global){ - /** - * Module dependencies - */ - - var XMLHttpRequest = _dereq_('xmlhttprequest'); - var XHR = _dereq_('./polling-xhr'); - var JSONP = _dereq_('./polling-jsonp'); - var websocket = _dereq_('./websocket'); - - /** - * Export transports. - */ - - exports.polling = polling; - exports.websocket = websocket; - - /** - * Polling transport polymorphic constructor. - * Decides on xhr vs jsonp based on feature detection. - * - * @api private - */ - - function polling(opts){ - var xhr; - var xd = false; - var xs = false; - var jsonp = false !== opts.jsonp; - - if (global.location) { - var isSSL = 'https:' == location.protocol; - var port = location.port; - - // some user agents have empty `location.port` - if (!port) { - port = isSSL ? 443 : 80; - } - - xd = opts.hostname != location.hostname || port != opts.port; - xs = opts.secure != isSSL; - } - - opts.xdomain = xd; - opts.xscheme = xs; - xhr = new XMLHttpRequest(opts); - - if ('open' in xhr && !opts.forceJSONP) { - return new XHR(opts); - } else { - if (!jsonp) throw new Error('JSONP disabled'); - return new JSONP(opts); - } - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./polling-jsonp":16,"./polling-xhr":17,"./websocket":19,"xmlhttprequest":20}],16:[function(_dereq_,module,exports){ - (function (global){ - - /** - * Module requirements. - */ - - var Polling = _dereq_('./polling'); - var inherit = _dereq_('component-inherit'); - - /** - * Module exports. - */ - - module.exports = JSONPPolling; - - /** - * Cached regular expressions. - */ - - var rNewline = /\n/g; - var rEscapedNewline = /\\n/g; - - /** - * Global JSONP callbacks. - */ - - var callbacks; - - /** - * Callbacks count. - */ - - var index = 0; - - /** - * Noop. - */ - - function empty () { } - - /** - * JSONP Polling constructor. - * - * @param {Object} opts. - * @api public - */ - - function JSONPPolling (opts) { - Polling.call(this, opts); - - this.query = this.query || {}; - - // define global callbacks array if not present - // we do this here (lazily) to avoid unneeded global pollution - if (!callbacks) { - // we need to consider multiple engines in the same page - if (!global.___eio) global.___eio = []; - callbacks = global.___eio; - } - - // callback identifier - this.index = callbacks.length; - - // add callback to jsonp global - var self = this; - callbacks.push(function (msg) { - self.onData(msg); - }); - - // append to query string - this.query.j = this.index; - - // prevent spurious errors from being emitted when the window is unloaded - if (global.document && global.addEventListener) { - global.addEventListener('beforeunload', function () { - if (self.script) self.script.onerror = empty; - }, false); - } - } - - /** - * Inherits from Polling. - */ - - inherit(JSONPPolling, Polling); - - /* - * JSONP only supports binary as base64 encoded strings - */ - - JSONPPolling.prototype.supportsBinary = false; - - /** - * Closes the socket. - * - * @api private - */ - - JSONPPolling.prototype.doClose = function () { - if (this.script) { - this.script.parentNode.removeChild(this.script); - this.script = null; - } - - if (this.form) { - this.form.parentNode.removeChild(this.form); - this.form = null; - this.iframe = null; - } - - Polling.prototype.doClose.call(this); - }; - - /** - * Starts a poll cycle. - * - * @api private - */ - - JSONPPolling.prototype.doPoll = function () { - var self = this; - var script = document.createElement('script'); - - if (this.script) { - this.script.parentNode.removeChild(this.script); - this.script = null; - } - - script.async = true; - script.src = this.uri(); - script.onerror = function(e){ - self.onError('jsonp poll error',e); - }; - - var insertAt = document.getElementsByTagName('script')[0]; - insertAt.parentNode.insertBefore(script, insertAt); - this.script = script; - - var isUAgecko = 'undefined' != typeof navigator && /gecko/i.test(navigator.userAgent); - - if (isUAgecko) { - setTimeout(function () { - var iframe = document.createElement('iframe'); - document.body.appendChild(iframe); - document.body.removeChild(iframe); - }, 100); - } - }; - - /** - * Writes with a hidden iframe. - * - * @param {String} data to send - * @param {Function} called upon flush. - * @api private - */ - - JSONPPolling.prototype.doWrite = function (data, fn) { - var self = this; - - if (!this.form) { - var form = document.createElement('form'); - var area = document.createElement('textarea'); - var id = this.iframeId = 'eio_iframe_' + this.index; - var iframe; - - form.className = 'socketio'; - form.style.position = 'absolute'; - form.style.top = '-1000px'; - form.style.left = '-1000px'; - form.target = id; - form.method = 'POST'; - form.setAttribute('accept-charset', 'utf-8'); - area.name = 'd'; - form.appendChild(area); - document.body.appendChild(form); - - this.form = form; - this.area = area; - } - - this.form.action = this.uri(); - - function complete () { - initIframe(); - fn(); - } - - function initIframe () { - if (self.iframe) { - try { - self.form.removeChild(self.iframe); - } catch (e) { - self.onError('jsonp polling iframe removal error', e); - } - } - - try { - // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) - var html = '<iframe src="javascript:0" name="'+ self.iframeId +'">'; - iframe = document.createElement(html); - } catch (e) { - iframe = document.createElement('iframe'); - iframe.name = self.iframeId; - iframe.src = 'javascript:0'; - } - - iframe.id = self.iframeId; - - self.form.appendChild(iframe); - self.iframe = iframe; - } - - initIframe(); - - // escape \n to prevent it from being converted into \r\n by some UAs - // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side - data = data.replace(rEscapedNewline, '\\\n'); - this.area.value = data.replace(rNewline, '\\n'); - - try { - this.form.submit(); - } catch(e) {} - - if (this.iframe.attachEvent) { - this.iframe.onreadystatechange = function(){ - if (self.iframe.readyState == 'complete') { - complete(); - } - }; - } else { - this.iframe.onload = complete; - } - }; - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./polling":18,"component-inherit":21}],17:[function(_dereq_,module,exports){ - (function (global){ - /** - * Module requirements. - */ - - var XMLHttpRequest = _dereq_('xmlhttprequest'); - var Polling = _dereq_('./polling'); - var Emitter = _dereq_('component-emitter'); - var inherit = _dereq_('component-inherit'); - var debug = _dereq_('debug')('engine.io-client:polling-xhr'); - - /** - * Module exports. - */ - - module.exports = XHR; - module.exports.Request = Request; - - /** - * Empty function - */ - - function empty(){} - - /** - * XHR Polling constructor. - * - * @param {Object} opts - * @api public - */ - - function XHR(opts){ - Polling.call(this, opts); - - if (global.location) { - var isSSL = 'https:' == location.protocol; - var port = location.port; - - // some user agents have empty `location.port` - if (!port) { - port = isSSL ? 443 : 80; - } - - this.xd = opts.hostname != global.location.hostname || - port != opts.port; - this.xs = opts.secure != isSSL; - } - } - - /** - * Inherits from Polling. - */ - - inherit(XHR, Polling); - - /** - * XHR supports binary - */ - - XHR.prototype.supportsBinary = true; - - /** - * Creates a request. - * - * @param {String} method - * @api private - */ - - XHR.prototype.request = function(opts){ - opts = opts || {}; - opts.uri = this.uri(); - opts.xd = this.xd; - opts.xs = this.xs; - opts.agent = this.agent || false; - opts.supportsBinary = this.supportsBinary; - opts.enablesXDR = this.enablesXDR; - - // SSL options for Node.js client - opts.pfx = this.pfx; - opts.key = this.key; - opts.passphrase = this.passphrase; - opts.cert = this.cert; - opts.ca = this.ca; - opts.ciphers = this.ciphers; - opts.rejectUnauthorized = this.rejectUnauthorized; - - return new Request(opts); - }; - - /** - * Sends data. - * - * @param {String} data to send. - * @param {Function} called upon flush. - * @api private - */ - - XHR.prototype.doWrite = function(data, fn){ - var isBinary = typeof data !== 'string' && data !== undefined; - var req = this.request({ method: 'POST', data: data, isBinary: isBinary }); - var self = this; - req.on('success', fn); - req.on('error', function(err){ - self.onError('xhr post error', err); - }); - this.sendXhr = req; - }; - - /** - * Starts a poll cycle. - * - * @api private - */ - - XHR.prototype.doPoll = function(){ - debug('xhr poll'); - var req = this.request(); - var self = this; - req.on('data', function(data){ - self.onData(data); - }); - req.on('error', function(err){ - self.onError('xhr poll error', err); - }); - this.pollXhr = req; - }; - - /** - * Request constructor - * - * @param {Object} options - * @api public - */ - - function Request(opts){ - this.method = opts.method || 'GET'; - this.uri = opts.uri; - this.xd = !!opts.xd; - this.xs = !!opts.xs; - this.async = false !== opts.async; - this.data = undefined != opts.data ? opts.data : null; - this.agent = opts.agent; - this.isBinary = opts.isBinary; - this.supportsBinary = opts.supportsBinary; - this.enablesXDR = opts.enablesXDR; - - // SSL options for Node.js client - this.pfx = opts.pfx; - this.key = opts.key; - this.passphrase = opts.passphrase; - this.cert = opts.cert; - this.ca = opts.ca; - this.ciphers = opts.ciphers; - this.rejectUnauthorized = opts.rejectUnauthorized; - - this.create(); - } - - /** - * Mix in `Emitter`. - */ - - Emitter(Request.prototype); - - /** - * Creates the XHR object and sends the request. - * - * @api private - */ - - Request.prototype.create = function(){ - var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR }; - - // SSL options for Node.js client - opts.pfx = this.pfx; - opts.key = this.key; - opts.passphrase = this.passphrase; - opts.cert = this.cert; - opts.ca = this.ca; - opts.ciphers = this.ciphers; - opts.rejectUnauthorized = this.rejectUnauthorized; - - var xhr = this.xhr = new XMLHttpRequest(opts); - var self = this; - - try { - debug('xhr open %s: %s', this.method, this.uri); - xhr.open(this.method, this.uri, this.async); - if (this.supportsBinary) { - // This has to be done after open because Firefox is stupid - // http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension - xhr.responseType = 'arraybuffer'; - } - - if ('POST' == this.method) { - try { - if (this.isBinary) { - xhr.setRequestHeader('Content-type', 'application/octet-stream'); - } else { - xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8'); - } - } catch (e) {} - } - - // ie6 check - if ('withCredentials' in xhr) { - xhr.withCredentials = true; - } - - if (this.hasXDR()) { - xhr.onload = function(){ - self.onLoad(); - }; - xhr.onerror = function(){ - self.onError(xhr.responseText); - }; - } else { - xhr.onreadystatechange = function(){ - if (4 != xhr.readyState) return; - if (200 == xhr.status || 1223 == xhr.status) { - self.onLoad(); - } else { - // make sure the `error` event handler that's user-set - // does not throw in the same tick and gets caught here - setTimeout(function(){ - self.onError(xhr.status); - }, 0); - } - }; - } - - debug('xhr data %s', this.data); - xhr.send(this.data); - } catch (e) { - // Need to defer since .create() is called directly fhrom the constructor - // and thus the 'error' event can only be only bound *after* this exception - // occurs. Therefore, also, we cannot throw here at all. - setTimeout(function() { - self.onError(e); - }, 0); - return; - } - - if (global.document) { - this.index = Request.requestsCount++; - Request.requests[this.index] = this; - } - }; - - /** - * Called upon successful response. - * - * @api private - */ - - Request.prototype.onSuccess = function(){ - this.emit('success'); - this.cleanup(); - }; - - /** - * Called if we have data. - * - * @api private - */ - - Request.prototype.onData = function(data){ - this.emit('data', data); - this.onSuccess(); - }; - - /** - * Called upon error. - * - * @api private - */ - - Request.prototype.onError = function(err){ - this.emit('error', err); - this.cleanup(true); - }; - - /** - * Cleans up house. - * - * @api private - */ - - Request.prototype.cleanup = function(fromError){ - if ('undefined' == typeof this.xhr || null === this.xhr) { - return; - } - // xmlhttprequest - if (this.hasXDR()) { - this.xhr.onload = this.xhr.onerror = empty; - } else { - this.xhr.onreadystatechange = empty; - } - - if (fromError) { - try { - this.xhr.abort(); - } catch(e) {} - } - - if (global.document) { - delete Request.requests[this.index]; - } - - this.xhr = null; - }; - - /** - * Called upon load. - * - * @api private - */ - - Request.prototype.onLoad = function(){ - var data; - try { - var contentType; - try { - contentType = this.xhr.getResponseHeader('Content-Type').split(';')[0]; - } catch (e) {} - if (contentType === 'application/octet-stream') { - data = this.xhr.response; - } else { - if (!this.supportsBinary) { - data = this.xhr.responseText; - } else { - data = 'ok'; - } - } - } catch (e) { - this.onError(e); - } - if (null != data) { - this.onData(data); - } - }; - - /** - * Check if it has XDomainRequest. - * - * @api private - */ - - Request.prototype.hasXDR = function(){ - return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR; - }; - - /** - * Aborts the request. - * - * @api public - */ - - Request.prototype.abort = function(){ - this.cleanup(); - }; - - /** - * Aborts pending requests when unloading the window. This is needed to prevent - * memory leaks (e.g. when using IE) and to ensure that no spurious error is - * emitted. - */ - - if (global.document) { - Request.requestsCount = 0; - Request.requests = {}; - if (global.attachEvent) { - global.attachEvent('onunload', unloadHandler); - } else if (global.addEventListener) { - global.addEventListener('beforeunload', unloadHandler, false); - } - } - - function unloadHandler() { - for (var i in Request.requests) { - if (Request.requests.hasOwnProperty(i)) { - Request.requests[i].abort(); - } - } - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./polling":18,"component-emitter":9,"component-inherit":21,"debug":22,"xmlhttprequest":20}],18:[function(_dereq_,module,exports){ - /** - * Module dependencies. - */ - - var Transport = _dereq_('../transport'); - var parseqs = _dereq_('parseqs'); - var parser = _dereq_('engine.io-parser'); - var inherit = _dereq_('component-inherit'); - var debug = _dereq_('debug')('engine.io-client:polling'); - - /** - * Module exports. - */ - - module.exports = Polling; - - /** - * Is XHR2 supported? - */ - - var hasXHR2 = (function() { - var XMLHttpRequest = _dereq_('xmlhttprequest'); - var xhr = new XMLHttpRequest({ xdomain: false }); - return null != xhr.responseType; - })(); - - /** - * Polling interface. - * - * @param {Object} opts - * @api private - */ - - function Polling(opts){ - var forceBase64 = (opts && opts.forceBase64); - if (!hasXHR2 || forceBase64) { - this.supportsBinary = false; - } - Transport.call(this, opts); - } - - /** - * Inherits from Transport. - */ - - inherit(Polling, Transport); - - /** - * Transport name. - */ - - Polling.prototype.name = 'polling'; - - /** - * Opens the socket (triggers polling). We write a PING message to determine - * when the transport is open. - * - * @api private - */ - - Polling.prototype.doOpen = function(){ - this.poll(); - }; - - /** - * Pauses polling. - * - * @param {Function} callback upon buffers are flushed and transport is paused - * @api private - */ - - Polling.prototype.pause = function(onPause){ - var pending = 0; - var self = this; - - this.readyState = 'pausing'; - - function pause(){ - debug('paused'); - self.readyState = 'paused'; - onPause(); - } - - if (this.polling || !this.writable) { - var total = 0; - - if (this.polling) { - debug('we are currently polling - waiting to pause'); - total++; - this.once('pollComplete', function(){ - debug('pre-pause polling complete'); - --total || pause(); - }); - } - - if (!this.writable) { - debug('we are currently writing - waiting to pause'); - total++; - this.once('drain', function(){ - debug('pre-pause writing complete'); - --total || pause(); - }); - } - } else { - pause(); - } - }; - - /** - * Starts polling cycle. - * - * @api public - */ - - Polling.prototype.poll = function(){ - debug('polling'); - this.polling = true; - this.doPoll(); - this.emit('poll'); - }; - - /** - * Overloads onData to detect payloads. - * - * @api private - */ - - Polling.prototype.onData = function(data){ - var self = this; - debug('polling got data %s', data); - var callback = function(packet, index, total) { - // if its the first message we consider the transport open - if ('opening' == self.readyState) { - self.onOpen(); - } - - // if its a close packet, we close the ongoing requests - if ('close' == packet.type) { - self.onClose(); - return false; - } - - // otherwise bypass onData and handle the message - self.onPacket(packet); - }; - - // decode payload - parser.decodePayload(data, this.socket.binaryType, callback); - - // if an event did not trigger closing - if ('closed' != this.readyState) { - // if we got data we're not polling - this.polling = false; - this.emit('pollComplete'); - - if ('open' == this.readyState) { - this.poll(); - } else { - debug('ignoring poll - transport state "%s"', this.readyState); - } - } - }; - - /** - * For polling, send a close packet. - * - * @api private - */ - - Polling.prototype.doClose = function(){ - var self = this; - - function close(){ - debug('writing close packet'); - self.write([{ type: 'close' }]); - } - - if ('open' == this.readyState) { - debug('transport open - closing'); - close(); - } else { - // in case we're trying to close while - // handshaking is in progress (GH-164) - debug('transport not open - deferring close'); - this.once('open', close); - } - }; - - /** - * Writes a packets payload. - * - * @param {Array} data packets - * @param {Function} drain callback - * @api private - */ - - Polling.prototype.write = function(packets){ - var self = this; - this.writable = false; - var callbackfn = function() { - self.writable = true; - self.emit('drain'); - }; - - var self = this; - parser.encodePayload(packets, this.supportsBinary, function(data) { - self.doWrite(data, callbackfn); - }); - }; - - /** - * Generates uri for connection. - * - * @api private - */ - - Polling.prototype.uri = function(){ - var query = this.query || {}; - var schema = this.secure ? 'https' : 'http'; - var port = ''; - - // cache busting is forced - if (false !== this.timestampRequests) { - query[this.timestampParam] = +new Date + '-' + Transport.timestamps++; - } - - if (!this.supportsBinary && !query.sid) { - query.b64 = 1; - } - - query = parseqs.encode(query); - - // avoid port if default for schema - if (this.port && (('https' == schema && this.port != 443) || - ('http' == schema && this.port != 80))) { - port = ':' + this.port; - } - - // prepend ? to query - if (query.length) { - query = '?' + query; - } - - return schema + '://' + this.hostname + port + this.path + query; - }; - -},{"../transport":14,"component-inherit":21,"debug":22,"engine.io-parser":25,"parseqs":35,"xmlhttprequest":20}],19:[function(_dereq_,module,exports){ - /** - * Module dependencies. - */ - - var Transport = _dereq_('../transport'); - var parser = _dereq_('engine.io-parser'); - var parseqs = _dereq_('parseqs'); - var inherit = _dereq_('component-inherit'); - var debug = _dereq_('debug')('engine.io-client:websocket'); - - /** - * `ws` exposes a WebSocket-compatible interface in - * Node, or the `WebSocket` or `MozWebSocket` globals - * in the browser. - */ - - var WebSocket = _dereq_('ws'); - - /** - * Module exports. - */ - - module.exports = WS; - - /** - * WebSocket transport constructor. - * - * @api {Object} connection options - * @api public - */ - - function WS(opts){ - var forceBase64 = (opts && opts.forceBase64); - if (forceBase64) { - this.supportsBinary = false; - } - Transport.call(this, opts); - } - - /** - * Inherits from Transport. - */ - - inherit(WS, Transport); - - /** - * Transport name. - * - * @api public - */ - - WS.prototype.name = 'websocket'; - - /* - * WebSockets support binary - */ - - WS.prototype.supportsBinary = true; - - /** - * Opens socket. - * - * @api private - */ - - WS.prototype.doOpen = function(){ - if (!this.check()) { - // let probe timeout - return; - } - - var self = this; - var uri = this.uri(); - var protocols = void(0); - var opts = { agent: this.agent }; - - // SSL options for Node.js client - opts.pfx = this.pfx; - opts.key = this.key; - opts.passphrase = this.passphrase; - opts.cert = this.cert; - opts.ca = this.ca; - opts.ciphers = this.ciphers; - opts.rejectUnauthorized = this.rejectUnauthorized; - - this.ws = new WebSocket(uri, protocols, opts); - - if (this.ws.binaryType === undefined) { - this.supportsBinary = false; - } - - this.ws.binaryType = 'arraybuffer'; - this.addEventListeners(); - }; - - /** - * Adds event listeners to the socket - * - * @api private - */ - - WS.prototype.addEventListeners = function(){ - var self = this; - - this.ws.onopen = function(){ - self.onOpen(); - }; - this.ws.onclose = function(){ - self.onClose(); - }; - this.ws.onmessage = function(ev){ - self.onData(ev.data); - }; - this.ws.onerror = function(e){ - self.onError('websocket error', e); - }; - }; - - /** - * Override `onData` to use a timer on iOS. - * See: https://gist.github.com/mloughran/2052006 - * - * @api private - */ - - if ('undefined' != typeof navigator - && /iPad|iPhone|iPod/i.test(navigator.userAgent)) { - WS.prototype.onData = function(data){ - var self = this; - setTimeout(function(){ - Transport.prototype.onData.call(self, data); - }, 0); - }; - } - - /** - * Writes data to socket. - * - * @param {Array} array of packets. - * @api private - */ - - WS.prototype.write = function(packets){ - var self = this; - this.writable = false; - // encodePacket efficient as it uses WS framing - // no need for encodePayload - for (var i = 0, l = packets.length; i < l; i++) { - parser.encodePacket(packets[i], this.supportsBinary, function(data) { - //Sometimes the websocket has already been closed but the browser didn't - //have a chance of informing us about it yet, in that case send will - //throw an error - try { - self.ws.send(data); - } catch (e){ - debug('websocket closed before onclose event'); - } - }); - } - - function ondrain() { - self.writable = true; - self.emit('drain'); - } - // fake drain - // defer to next tick to allow Socket to clear writeBuffer - setTimeout(ondrain, 0); - }; - - /** - * Called upon close - * - * @api private - */ - - WS.prototype.onClose = function(){ - Transport.prototype.onClose.call(this); - }; - - /** - * Closes socket. - * - * @api private - */ - - WS.prototype.doClose = function(){ - if (typeof this.ws !== 'undefined') { - this.ws.close(); - } - }; - - /** - * Generates uri for connection. - * - * @api private - */ - - WS.prototype.uri = function(){ - var query = this.query || {}; - var schema = this.secure ? 'wss' : 'ws'; - var port = ''; - - // avoid port if default for schema - if (this.port && (('wss' == schema && this.port != 443) - || ('ws' == schema && this.port != 80))) { - port = ':' + this.port; - } - - // append timestamp to URI - if (this.timestampRequests) { - query[this.timestampParam] = +new Date; - } - - // communicate binary support capabilities - if (!this.supportsBinary) { - query.b64 = 1; - } - - query = parseqs.encode(query); - - // prepend ? to query - if (query.length) { - query = '?' + query; - } - - return schema + '://' + this.hostname + port + this.path + query; - }; - - /** - * Feature detection for WebSocket. - * - * @return {Boolean} whether this transport is available. - * @api public - */ - - WS.prototype.check = function(){ - return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name); - }; - -},{"../transport":14,"component-inherit":21,"debug":22,"engine.io-parser":25,"parseqs":35,"ws":37}],20:[function(_dereq_,module,exports){ -// browser shim for xmlhttprequest module - var hasCORS = _dereq_('has-cors'); - - module.exports = function(opts) { - var xdomain = opts.xdomain; - - // scheme must be same when usign XDomainRequest - // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx - var xscheme = opts.xscheme; - - // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default. - // https://github.com/Automattic/engine.io-client/pull/217 - var enablesXDR = opts.enablesXDR; - - // XMLHttpRequest can be disabled on IE - try { - if ('undefined' != typeof XMLHttpRequest && (!xdomain || hasCORS)) { - return new XMLHttpRequest(); - } - } catch (e) { } - - // Use XDomainRequest for IE8 if enablesXDR is true - // because loading bar keeps flashing when using jsonp-polling - // https://github.com/yujiosaka/socke.io-ie8-loading-example - try { - if ('undefined' != typeof XDomainRequest && !xscheme && enablesXDR) { - return new XDomainRequest(); - } - } catch (e) { } - - if (!xdomain) { - try { - return new ActiveXObject('Microsoft.XMLHTTP'); - } catch(e) { } - } - } - -},{"has-cors":40}],21:[function(_dereq_,module,exports){ - - module.exports = function(a, b){ - var fn = function(){}; - fn.prototype = b.prototype; - a.prototype = new fn; - a.prototype.constructor = a; - }; -},{}],22:[function(_dereq_,module,exports){ - - /** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - - exports = module.exports = _dereq_('./debug'); - exports.log = log; - exports.formatArgs = formatArgs; - exports.save = save; - exports.load = load; - exports.useColors = useColors; - - /** - * Colors. - */ - - exports.colors = [ - 'lightseagreen', - 'forestgreen', - 'goldenrod', - 'dodgerblue', - 'darkorchid', - 'crimson' - ]; - - /** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ - - function useColors() { - // is webkit? http://stackoverflow.com/a/16459606/376773 - return ('WebkitAppearance' in document.documentElement.style) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (window.console && (console.firebug || (console.exception && console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); - } - - /** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - - exports.formatters.j = function(v) { - return JSON.stringify(v); - }; - - - /** - * Colorize log arguments if enabled. - * - * @api public - */ - - function formatArgs() { - var args = arguments; - var useColors = this.useColors; - - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - - if (!useColors) return args; - - var c = 'color: ' + this.color; - args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); - - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-z%]/g, function(match) { - if ('%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - - args.splice(lastC, 0, c); - return args; - } - - /** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ - - function log() { - // This hackery is required for IE8, - // where the `console.log` function doesn't have 'apply' - return 'object' == typeof console - && 'function' == typeof console.log - && Function.prototype.apply.call(console.log, console, arguments); - } - - /** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ - - function save(namespaces) { - try { - if (null == namespaces) { - localStorage.removeItem('debug'); - } else { - localStorage.debug = namespaces; - } - } catch(e) {} - } - - /** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ - - function load() { - var r; - try { - r = localStorage.debug; - } catch(e) {} - return r; - } - - /** - * Enable namespaces listed in `localStorage.debug` initially. - */ - - exports.enable(load()); - -},{"./debug":23}],23:[function(_dereq_,module,exports){ - - /** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ - - exports = module.exports = debug; - exports.coerce = coerce; - exports.disable = disable; - exports.enable = enable; - exports.enabled = enabled; - exports.humanize = _dereq_('ms'); - - /** - * The currently active debug mode names, and names to skip. - */ - - exports.names = []; - exports.skips = []; - - /** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lowercased letter, i.e. "n". - */ - - exports.formatters = {}; - - /** - * Previously assigned color. - */ - - var prevColor = 0; - - /** - * Previous log timestamp. - */ - - var prevTime; - - /** - * Select a color. - * - * @return {Number} - * @api private - */ - - function selectColor() { - return exports.colors[prevColor++ % exports.colors.length]; - } - - /** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - - function debug(namespace) { - - // define the `disabled` version - function disabled() { - } - disabled.enabled = false; - - // define the `enabled` version - function enabled() { - - var self = enabled; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - // add the `color` if not set - if (null == self.useColors) self.useColors = exports.useColors(); - if (null == self.color && self.useColors) self.color = selectColor(); - - var args = Array.prototype.slice.call(arguments); - - args[0] = exports.coerce(args[0]); - - if ('string' !== typeof args[0]) { - // anything else let's inspect with %o - args = ['%o'].concat(args); - } - - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); - - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); - - if ('function' === typeof exports.formatArgs) { - args = exports.formatArgs.apply(self, args); - } - var logFn = enabled.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - enabled.enabled = true; - - var fn = exports.enabled(namespace) ? enabled : disabled; - - fn.namespace = namespace; - - return fn; - } - - /** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - - function enable(namespaces) { - exports.save(namespaces); - - var split = (namespaces || '').split(/[\s,]+/); - var len = split.length; - - for (var i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } - } - - /** - * Disable debug output. - * - * @api public - */ - - function disable() { - exports.enable(''); - } - - /** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - - function enabled(name) { - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; - } - } - return false; - } - - /** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - - function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; - } - -},{"ms":24}],24:[function(_dereq_,module,exports){ - /** - * Helpers. - */ - - var s = 1000; - var m = s * 60; - var h = m * 60; - var d = h * 24; - var y = d * 365.25; - - /** - * Parse or format the given `val`. - * - * Options: - * - * - `long` verbose formatting [false] - * - * @param {String|Number} val - * @param {Object} options - * @return {String|Number} - * @api public - */ - - module.exports = function(val, options){ - options = options || {}; - if ('string' == typeof val) return parse(val); - return options.long - ? long(val) - : short(val); - }; - - /** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ - - function parse(str) { - var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); - if (!match) return; - var n = parseFloat(match[1]); - var type = (match[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'y': - return n * y; - case 'days': - case 'day': - case 'd': - return n * d; - case 'hours': - case 'hour': - case 'h': - return n * h; - case 'minutes': - case 'minute': - case 'm': - return n * m; - case 'seconds': - case 'second': - case 's': - return n * s; - case 'ms': - return n; - } - } - - /** - * Short format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - - function short(ms) { - if (ms >= d) return Math.round(ms / d) + 'd'; - if (ms >= h) return Math.round(ms / h) + 'h'; - if (ms >= m) return Math.round(ms / m) + 'm'; - if (ms >= s) return Math.round(ms / s) + 's'; - return ms + 'ms'; - } - - /** - * Long format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - - function long(ms) { - return plural(ms, d, 'day') - || plural(ms, h, 'hour') - || plural(ms, m, 'minute') - || plural(ms, s, 'second') - || ms + ' ms'; - } - - /** - * Pluralization helper. - */ - - function plural(ms, n, name) { - if (ms < n) return; - if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; - return Math.ceil(ms / n) + ' ' + name + 's'; - } - -},{}],25:[function(_dereq_,module,exports){ - (function (global){ - /** - * Module dependencies. - */ - - var keys = _dereq_('./keys'); - var hasBinary = _dereq_('has-binary'); - var sliceBuffer = _dereq_('arraybuffer.slice'); - var base64encoder = _dereq_('base64-arraybuffer'); - var after = _dereq_('after'); - var utf8 = _dereq_('utf8'); - - /** - * Check if we are running an android browser. That requires us to use - * ArrayBuffer with polling transports... - * - * http://ghinda.net/jpeg-blob-ajax-android/ - */ - - var isAndroid = navigator.userAgent.match(/Android/i); - - /** - * Check if we are running in PhantomJS. - * Uploading a Blob with PhantomJS does not work correctly, as reported here: - * https://github.com/ariya/phantomjs/issues/11395 - * @type boolean - */ - var isPhantomJS = /PhantomJS/i.test(navigator.userAgent); - - /** - * When true, avoids using Blobs to encode payloads. - * @type boolean - */ - var dontSendBlobs = isAndroid || isPhantomJS; - - /** - * Current protocol version. - */ - - exports.protocol = 3; - - /** - * Packet types. - */ - - var packets = exports.packets = { - open: 0 // non-ws - , close: 1 // non-ws - , ping: 2 - , pong: 3 - , message: 4 - , upgrade: 5 - , noop: 6 - }; - - var packetslist = keys(packets); - - /** - * Premade error packet. - */ - - var err = { type: 'error', data: 'parser error' }; - - /** - * Create a blob api even for blob builder when vendor prefixes exist - */ - - var Blob = _dereq_('blob'); - - /** - * Encodes a packet. - * - * <packet type id> [ <data> ] - * - * Example: - * - * 5hello world - * 3 - * 4 - * - * Binary is encoded in an identical principle - * - * @api private - */ - - exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) { - if ('function' == typeof supportsBinary) { - callback = supportsBinary; - supportsBinary = false; - } - - if ('function' == typeof utf8encode) { - callback = utf8encode; - utf8encode = null; - } - - var data = (packet.data === undefined) - ? undefined - : packet.data.buffer || packet.data; - - if (global.ArrayBuffer && data instanceof ArrayBuffer) { - return encodeArrayBuffer(packet, supportsBinary, callback); - } else if (Blob && data instanceof global.Blob) { - return encodeBlob(packet, supportsBinary, callback); - } - - // might be an object with { base64: true, data: dataAsBase64String } - if (data && data.base64) { - return encodeBase64Object(packet, callback); - } - - // Sending data as a utf-8 string - var encoded = packets[packet.type]; - - // data fragment is optional - if (undefined !== packet.data) { - encoded += utf8encode ? utf8.encode(String(packet.data)) : String(packet.data); - } - - return callback('' + encoded); - - }; - - function encodeBase64Object(packet, callback) { - // packet data is an object { base64: true, data: dataAsBase64String } - var message = 'b' + exports.packets[packet.type] + packet.data.data; - return callback(message); - } - - /** - * Encode packet helpers for binary types - */ - - function encodeArrayBuffer(packet, supportsBinary, callback) { - if (!supportsBinary) { - return exports.encodeBase64Packet(packet, callback); - } - - var data = packet.data; - var contentArray = new Uint8Array(data); - var resultBuffer = new Uint8Array(1 + data.byteLength); - - resultBuffer[0] = packets[packet.type]; - for (var i = 0; i < contentArray.length; i++) { - resultBuffer[i+1] = contentArray[i]; - } - - return callback(resultBuffer.buffer); - } - - function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) { - if (!supportsBinary) { - return exports.encodeBase64Packet(packet, callback); - } - - var fr = new FileReader(); - fr.onload = function() { - packet.data = fr.result; - exports.encodePacket(packet, supportsBinary, true, callback); - }; - return fr.readAsArrayBuffer(packet.data); - } - - function encodeBlob(packet, supportsBinary, callback) { - if (!supportsBinary) { - return exports.encodeBase64Packet(packet, callback); - } - - if (dontSendBlobs) { - return encodeBlobAsArrayBuffer(packet, supportsBinary, callback); - } - - var length = new Uint8Array(1); - length[0] = packets[packet.type]; - var blob = new Blob([length.buffer, packet.data]); - - return callback(blob); - } - - /** - * Encodes a packet with binary data in a base64 string - * - * @param {Object} packet, has `type` and `data` - * @return {String} base64 encoded message - */ - - exports.encodeBase64Packet = function(packet, callback) { - var message = 'b' + exports.packets[packet.type]; - if (Blob && packet.data instanceof Blob) { - var fr = new FileReader(); - fr.onload = function() { - var b64 = fr.result.split(',')[1]; - callback(message + b64); - }; - return fr.readAsDataURL(packet.data); - } - - var b64data; - try { - b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data)); - } catch (e) { - // iPhone Safari doesn't let you apply with typed arrays - var typed = new Uint8Array(packet.data); - var basic = new Array(typed.length); - for (var i = 0; i < typed.length; i++) { - basic[i] = typed[i]; - } - b64data = String.fromCharCode.apply(null, basic); - } - message += global.btoa(b64data); - return callback(message); - }; - - /** - * Decodes a packet. Changes format to Blob if requested. - * - * @return {Object} with `type` and `data` (if any) - * @api private - */ - - exports.decodePacket = function (data, binaryType, utf8decode) { - // String data - if (typeof data == 'string' || data === undefined) { - if (data.charAt(0) == 'b') { - return exports.decodeBase64Packet(data.substr(1), binaryType); - } - - if (utf8decode) { - try { - data = utf8.decode(data); - } catch (e) { - return err; - } - } - var type = data.charAt(0); - - if (Number(type) != type || !packetslist[type]) { - return err; - } - - if (data.length > 1) { - return { type: packetslist[type], data: data.substring(1) }; - } else { - return { type: packetslist[type] }; - } - } - - var asArray = new Uint8Array(data); - var type = asArray[0]; - var rest = sliceBuffer(data, 1); - if (Blob && binaryType === 'blob') { - rest = new Blob([rest]); - } - return { type: packetslist[type], data: rest }; - }; - - /** - * Decodes a packet encoded in a base64 string - * - * @param {String} base64 encoded message - * @return {Object} with `type` and `data` (if any) - */ - - exports.decodeBase64Packet = function(msg, binaryType) { - var type = packetslist[msg.charAt(0)]; - if (!global.ArrayBuffer) { - return { type: type, data: { base64: true, data: msg.substr(1) } }; - } - - var data = base64encoder.decode(msg.substr(1)); - - if (binaryType === 'blob' && Blob) { - data = new Blob([data]); - } - - return { type: type, data: data }; - }; - - /** - * Encodes multiple messages (payload). - * - * <length>:data - * - * Example: - * - * 11:hello world2:hi - * - * If any contents are binary, they will be encoded as base64 strings. Base64 - * encoded strings are marked with a b before the length specifier - * - * @param {Array} packets - * @api private - */ - - exports.encodePayload = function (packets, supportsBinary, callback) { - if (typeof supportsBinary == 'function') { - callback = supportsBinary; - supportsBinary = null; - } - - var isBinary = hasBinary(packets); - - if (supportsBinary && isBinary) { - if (Blob && !dontSendBlobs) { - return exports.encodePayloadAsBlob(packets, callback); - } - - return exports.encodePayloadAsArrayBuffer(packets, callback); - } - - if (!packets.length) { - return callback('0:'); - } - - function setLengthHeader(message) { - return message.length + ':' + message; - } - - function encodeOne(packet, doneCallback) { - exports.encodePacket(packet, !isBinary ? false : supportsBinary, true, function(message) { - doneCallback(null, setLengthHeader(message)); - }); - } - - map(packets, encodeOne, function(err, results) { - return callback(results.join('')); - }); - }; - - /** - * Async array map using after - */ - - function map(ary, each, done) { - var result = new Array(ary.length); - var next = after(ary.length, done); - - var eachWithIndex = function(i, el, cb) { - each(el, function(error, msg) { - result[i] = msg; - cb(error, result); - }); - }; - - for (var i = 0; i < ary.length; i++) { - eachWithIndex(i, ary[i], next); - } - } - - /* - * Decodes data when a payload is maybe expected. Possible binary contents are - * decoded from their base64 representation - * - * @param {String} data, callback method - * @api public - */ - - exports.decodePayload = function (data, binaryType, callback) { - if (typeof data != 'string') { - return exports.decodePayloadAsBinary(data, binaryType, callback); - } - - if (typeof binaryType === 'function') { - callback = binaryType; - binaryType = null; - } - - var packet; - if (data == '') { - // parser error - ignoring payload - return callback(err, 0, 1); - } - - var length = '' - , n, msg; - - for (var i = 0, l = data.length; i < l; i++) { - var chr = data.charAt(i); - - if (':' != chr) { - length += chr; - } else { - if ('' == length || (length != (n = Number(length)))) { - // parser error - ignoring payload - return callback(err, 0, 1); - } - - msg = data.substr(i + 1, n); - - if (length != msg.length) { - // parser error - ignoring payload - return callback(err, 0, 1); - } - - if (msg.length) { - packet = exports.decodePacket(msg, binaryType, true); - - if (err.type == packet.type && err.data == packet.data) { - // parser error in individual packet - ignoring payload - return callback(err, 0, 1); - } - - var ret = callback(packet, i + n, l); - if (false === ret) return; - } - - // advance cursor - i += n; - length = ''; - } - } - - if (length != '') { - // parser error - ignoring payload - return callback(err, 0, 1); - } - - }; - - /** - * Encodes multiple messages (payload) as binary. - * - * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number - * 255><data> - * - * Example: - * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers - * - * @param {Array} packets - * @return {ArrayBuffer} encoded payload - * @api private - */ - - exports.encodePayloadAsArrayBuffer = function(packets, callback) { - if (!packets.length) { - return callback(new ArrayBuffer(0)); - } - - function encodeOne(packet, doneCallback) { - exports.encodePacket(packet, true, true, function(data) { - return doneCallback(null, data); - }); - } - - map(packets, encodeOne, function(err, encodedPackets) { - var totalLength = encodedPackets.reduce(function(acc, p) { - var len; - if (typeof p === 'string'){ - len = p.length; - } else { - len = p.byteLength; - } - return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2 - }, 0); - - var resultArray = new Uint8Array(totalLength); - - var bufferIndex = 0; - encodedPackets.forEach(function(p) { - var isString = typeof p === 'string'; - var ab = p; - if (isString) { - var view = new Uint8Array(p.length); - for (var i = 0; i < p.length; i++) { - view[i] = p.charCodeAt(i); - } - ab = view.buffer; - } - - if (isString) { // not true binary - resultArray[bufferIndex++] = 0; - } else { // true binary - resultArray[bufferIndex++] = 1; - } - - var lenStr = ab.byteLength.toString(); - for (var i = 0; i < lenStr.length; i++) { - resultArray[bufferIndex++] = parseInt(lenStr[i]); - } - resultArray[bufferIndex++] = 255; - - var view = new Uint8Array(ab); - for (var i = 0; i < view.length; i++) { - resultArray[bufferIndex++] = view[i]; - } - }); - - return callback(resultArray.buffer); - }); - }; - - /** - * Encode as Blob - */ - - exports.encodePayloadAsBlob = function(packets, callback) { - function encodeOne(packet, doneCallback) { - exports.encodePacket(packet, true, true, function(encoded) { - var binaryIdentifier = new Uint8Array(1); - binaryIdentifier[0] = 1; - if (typeof encoded === 'string') { - var view = new Uint8Array(encoded.length); - for (var i = 0; i < encoded.length; i++) { - view[i] = encoded.charCodeAt(i); - } - encoded = view.buffer; - binaryIdentifier[0] = 0; - } - - var len = (encoded instanceof ArrayBuffer) - ? encoded.byteLength - : encoded.size; - - var lenStr = len.toString(); - var lengthAry = new Uint8Array(lenStr.length + 1); - for (var i = 0; i < lenStr.length; i++) { - lengthAry[i] = parseInt(lenStr[i]); - } - lengthAry[lenStr.length] = 255; - - if (Blob) { - var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]); - doneCallback(null, blob); - } - }); - } - - map(packets, encodeOne, function(err, results) { - return callback(new Blob(results)); - }); - }; - - /* - * Decodes data when a payload is maybe expected. Strings are decoded by - * interpreting each byte as a key code for entries marked to start with 0. See - * description of encodePayloadAsBinary - * - * @param {ArrayBuffer} data, callback method - * @api public - */ - - exports.decodePayloadAsBinary = function (data, binaryType, callback) { - if (typeof binaryType === 'function') { - callback = binaryType; - binaryType = null; - } - - var bufferTail = data; - var buffers = []; - - var numberTooLong = false; - while (bufferTail.byteLength > 0) { - var tailArray = new Uint8Array(bufferTail); - var isString = tailArray[0] === 0; - var msgLength = ''; - - for (var i = 1; ; i++) { - if (tailArray[i] == 255) break; - - if (msgLength.length > 310) { - numberTooLong = true; - break; - } - - msgLength += tailArray[i]; - } - - if(numberTooLong) return callback(err, 0, 1); - - bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length); - msgLength = parseInt(msgLength); - - var msg = sliceBuffer(bufferTail, 0, msgLength); - if (isString) { - try { - msg = String.fromCharCode.apply(null, new Uint8Array(msg)); - } catch (e) { - // iPhone Safari doesn't let you apply to typed arrays - var typed = new Uint8Array(msg); - msg = ''; - for (var i = 0; i < typed.length; i++) { - msg += String.fromCharCode(typed[i]); - } - } - } - - buffers.push(msg); - bufferTail = sliceBuffer(bufferTail, msgLength); - } - - var total = buffers.length; - buffers.forEach(function(buffer, i) { - callback(exports.decodePacket(buffer, binaryType, true), i, total); - }); - }; - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./keys":26,"after":27,"arraybuffer.slice":28,"base64-arraybuffer":29,"blob":30,"has-binary":31,"utf8":33}],26:[function(_dereq_,module,exports){ - - /** - * Gets the keys for an object. - * - * @return {Array} keys - * @api private - */ - - module.exports = Object.keys || function keys (obj){ - var arr = []; - var has = Object.prototype.hasOwnProperty; - - for (var i in obj) { - if (has.call(obj, i)) { - arr.push(i); - } - } - return arr; - }; - -},{}],27:[function(_dereq_,module,exports){ - module.exports = after - - function after(count, callback, err_cb) { - var bail = false - err_cb = err_cb || noop - proxy.count = count - - return (count === 0) ? callback() : proxy - - function proxy(err, result) { - if (proxy.count <= 0) { - throw new Error('after called too many times') - } - --proxy.count - - // after first error, rest are passed to err_cb - if (err) { - bail = true - callback(err) - // future error callbacks will go to error handler - callback = err_cb - } else if (proxy.count === 0 && !bail) { - callback(null, result) - } - } - } - - function noop() {} - -},{}],28:[function(_dereq_,module,exports){ - /** - * An abstraction for slicing an arraybuffer even when - * ArrayBuffer.prototype.slice is not supported - * - * @api public - */ - - module.exports = function(arraybuffer, start, end) { - var bytes = arraybuffer.byteLength; - start = start || 0; - end = end || bytes; - - if (arraybuffer.slice) { return arraybuffer.slice(start, end); } - - if (start < 0) { start += bytes; } - if (end < 0) { end += bytes; } - if (end > bytes) { end = bytes; } - - if (start >= bytes || start >= end || bytes === 0) { - return new ArrayBuffer(0); - } - - var abv = new Uint8Array(arraybuffer); - var result = new Uint8Array(end - start); - for (var i = start, ii = 0; i < end; i++, ii++) { - result[ii] = abv[i]; - } - return result.buffer; - }; - -},{}],29:[function(_dereq_,module,exports){ - /* - * base64-arraybuffer - * https://github.com/niklasvh/base64-arraybuffer - * - * Copyright (c) 2012 Niklas von Hertzen - * Licensed under the MIT license. - */ - (function(chars){ - "use strict"; - - exports.encode = function(arraybuffer) { - var bytes = new Uint8Array(arraybuffer), - i, len = bytes.length, base64 = ""; - - for (i = 0; i < len; i+=3) { - base64 += chars[bytes[i] >> 2]; - base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; - base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; - base64 += chars[bytes[i + 2] & 63]; - } - - if ((len % 3) === 2) { - base64 = base64.substring(0, base64.length - 1) + "="; - } else if (len % 3 === 1) { - base64 = base64.substring(0, base64.length - 2) + "=="; - } - - return base64; - }; - - exports.decode = function(base64) { - var bufferLength = base64.length * 0.75, - len = base64.length, i, p = 0, - encoded1, encoded2, encoded3, encoded4; - - if (base64[base64.length - 1] === "=") { - bufferLength--; - if (base64[base64.length - 2] === "=") { - bufferLength--; - } - } - - var arraybuffer = new ArrayBuffer(bufferLength), - bytes = new Uint8Array(arraybuffer); - - for (i = 0; i < len; i+=4) { - encoded1 = chars.indexOf(base64[i]); - encoded2 = chars.indexOf(base64[i+1]); - encoded3 = chars.indexOf(base64[i+2]); - encoded4 = chars.indexOf(base64[i+3]); - - bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); - bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); - bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); - } - - return arraybuffer; - }; - })("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); - -},{}],30:[function(_dereq_,module,exports){ - (function (global){ - /** - * Create a blob builder even when vendor prefixes exist - */ - - var BlobBuilder = global.BlobBuilder - || global.WebKitBlobBuilder - || global.MSBlobBuilder - || global.MozBlobBuilder; - - /** - * Check if Blob constructor is supported - */ - - var blobSupported = (function() { - try { - var b = new Blob(['hi']); - return b.size == 2; - } catch(e) { - return false; - } - })(); - - /** - * Check if BlobBuilder is supported - */ - - var blobBuilderSupported = BlobBuilder - && BlobBuilder.prototype.append - && BlobBuilder.prototype.getBlob; - - function BlobBuilderConstructor(ary, options) { - options = options || {}; - - var bb = new BlobBuilder(); - for (var i = 0; i < ary.length; i++) { - bb.append(ary[i]); - } - return (options.type) ? bb.getBlob(options.type) : bb.getBlob(); - }; - - module.exports = (function() { - if (blobSupported) { - return global.Blob; - } else if (blobBuilderSupported) { - return BlobBuilderConstructor; - } else { - return undefined; - } - })(); - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],31:[function(_dereq_,module,exports){ - (function (global){ - - /* - * Module requirements. - */ - - var isArray = _dereq_('isarray'); - - /** - * Module exports. - */ - - module.exports = hasBinary; - - /** - * Checks for binary data. - * - * Right now only Buffer and ArrayBuffer are supported.. - * - * @param {Object} anything - * @api public - */ - - function hasBinary(data) { - - function _hasBinary(obj) { - if (!obj) return false; - - if ( (global.Buffer && global.Buffer.isBuffer(obj)) || - (global.ArrayBuffer && obj instanceof ArrayBuffer) || - (global.Blob && obj instanceof Blob) || - (global.File && obj instanceof File) - ) { - return true; - } - - if (isArray(obj)) { - for (var i = 0; i < obj.length; i++) { - if (_hasBinary(obj[i])) { - return true; - } - } - } else if (obj && 'object' == typeof obj) { - if (obj.toJSON) { - obj = obj.toJSON(); - } - - for (var key in obj) { - if (obj.hasOwnProperty(key) && _hasBinary(obj[key])) { - return true; - } - } - } - - return false; - } - - return _hasBinary(data); - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"isarray":32}],32:[function(_dereq_,module,exports){ - module.exports = Array.isArray || function (arr) { - return Object.prototype.toString.call(arr) == '[object Array]'; - }; - -},{}],33:[function(_dereq_,module,exports){ - (function (global){ - /*! http://mths.be/utf8js v2.0.0 by @mathias */ - ;(function(root) { - - // Detect free variables `exports` - var freeExports = typeof exports == 'object' && exports; - - // Detect free variable `module` - var freeModule = typeof module == 'object' && module && - module.exports == freeExports && module; - - // Detect free variable `global`, from Node.js or Browserified code, - // and use it as `root` - var freeGlobal = typeof global == 'object' && global; - if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { - root = freeGlobal; - } - - /*--------------------------------------------------------------------------*/ - - var stringFromCharCode = String.fromCharCode; - - // Taken from http://mths.be/punycode - function ucs2decode(string) { - var output = []; - var counter = 0; - var length = string.length; - var value; - var extra; - while (counter < length) { - value = string.charCodeAt(counter++); - if (value >= 0xD800 && value <= 0xDBFF && counter < length) { - // high surrogate, and there is a next character - extra = string.charCodeAt(counter++); - if ((extra & 0xFC00) == 0xDC00) { // low surrogate - output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - // unmatched surrogate; only append this code unit, in case the next - // code unit is the high surrogate of a surrogate pair - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; - } - - // Taken from http://mths.be/punycode - function ucs2encode(array) { - var length = array.length; - var index = -1; - var value; - var output = ''; - while (++index < length) { - value = array[index]; - if (value > 0xFFFF) { - value -= 0x10000; - output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - output += stringFromCharCode(value); - } - return output; - } - - /*--------------------------------------------------------------------------*/ - - function createByte(codePoint, shift) { - return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80); - } - - function encodeCodePoint(codePoint) { - if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence - return stringFromCharCode(codePoint); - } - var symbol = ''; - if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence - symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0); - } - else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence - symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0); - symbol += createByte(codePoint, 6); - } - else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence - symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0); - symbol += createByte(codePoint, 12); - symbol += createByte(codePoint, 6); - } - symbol += stringFromCharCode((codePoint & 0x3F) | 0x80); - return symbol; - } - - function utf8encode(string) { - var codePoints = ucs2decode(string); - - // console.log(JSON.stringify(codePoints.map(function(x) { - // return 'U+' + x.toString(16).toUpperCase(); - // }))); - - var length = codePoints.length; - var index = -1; - var codePoint; - var byteString = ''; - while (++index < length) { - codePoint = codePoints[index]; - byteString += encodeCodePoint(codePoint); - } - return byteString; - } - - /*--------------------------------------------------------------------------*/ - - function readContinuationByte() { - if (byteIndex >= byteCount) { - throw Error('Invalid byte index'); - } - - var continuationByte = byteArray[byteIndex] & 0xFF; - byteIndex++; - - if ((continuationByte & 0xC0) == 0x80) { - return continuationByte & 0x3F; - } - - // If we end up here, it’s not a continuation byte - throw Error('Invalid continuation byte'); - } - - function decodeSymbol() { - var byte1; - var byte2; - var byte3; - var byte4; - var codePoint; - - if (byteIndex > byteCount) { - throw Error('Invalid byte index'); - } - - if (byteIndex == byteCount) { - return false; - } - - // Read first byte - byte1 = byteArray[byteIndex] & 0xFF; - byteIndex++; - - // 1-byte sequence (no continuation bytes) - if ((byte1 & 0x80) == 0) { - return byte1; - } - - // 2-byte sequence - if ((byte1 & 0xE0) == 0xC0) { - var byte2 = readContinuationByte(); - codePoint = ((byte1 & 0x1F) << 6) | byte2; - if (codePoint >= 0x80) { - return codePoint; - } else { - throw Error('Invalid continuation byte'); - } - } - - // 3-byte sequence (may include unpaired surrogates) - if ((byte1 & 0xF0) == 0xE0) { - byte2 = readContinuationByte(); - byte3 = readContinuationByte(); - codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3; - if (codePoint >= 0x0800) { - return codePoint; - } else { - throw Error('Invalid continuation byte'); - } - } - - // 4-byte sequence - if ((byte1 & 0xF8) == 0xF0) { - byte2 = readContinuationByte(); - byte3 = readContinuationByte(); - byte4 = readContinuationByte(); - codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) | - (byte3 << 0x06) | byte4; - if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) { - return codePoint; - } - } - - throw Error('Invalid UTF-8 detected'); - } - - var byteArray; - var byteCount; - var byteIndex; - function utf8decode(byteString) { - byteArray = ucs2decode(byteString); - byteCount = byteArray.length; - byteIndex = 0; - var codePoints = []; - var tmp; - while ((tmp = decodeSymbol()) !== false) { - codePoints.push(tmp); - } - return ucs2encode(codePoints); - } - - /*--------------------------------------------------------------------------*/ - - var utf8 = { - 'version': '2.0.0', - 'encode': utf8encode, - 'decode': utf8decode - }; - - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - typeof define == 'function' && - typeof define.amd == 'object' && - define.amd - ) { - define(function() { - return utf8; - }); - } else if (freeExports && !freeExports.nodeType) { - if (freeModule) { // in Node.js or RingoJS v0.8.0+ - freeModule.exports = utf8; - } else { // in Narwhal or RingoJS v0.7.0- - var object = {}; - var hasOwnProperty = object.hasOwnProperty; - for (var key in utf8) { - hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]); - } - } - } else { // in Rhino or a web browser - root.utf8 = utf8; - } - - }(this)); - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],34:[function(_dereq_,module,exports){ - (function (global){ - /** - * JSON parse. - * - * @see Based on jQuery#parseJSON (MIT) and JSON2 - * @api private - */ - - var rvalidchars = /^[\],:{}\s]*$/; - var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g; - var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g; - var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g; - var rtrimLeft = /^\s+/; - var rtrimRight = /\s+$/; - - module.exports = function parsejson(data) { - if ('string' != typeof data || !data) { - return null; - } - - data = data.replace(rtrimLeft, '').replace(rtrimRight, ''); - - // Attempt to parse using the native JSON parser first - if (global.JSON && JSON.parse) { - return JSON.parse(data); - } - - if (rvalidchars.test(data.replace(rvalidescape, '@') - .replace(rvalidtokens, ']') - .replace(rvalidbraces, ''))) { - return (new Function('return ' + data))(); - } - }; - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],35:[function(_dereq_,module,exports){ - /** - * Compiles a querystring - * Returns string representation of the object - * - * @param {Object} - * @api private - */ - - exports.encode = function (obj) { - var str = ''; - - for (var i in obj) { - if (obj.hasOwnProperty(i)) { - if (str.length) str += '&'; - str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]); - } - } - - return str; - }; - - /** - * Parses a simple querystring into an object - * - * @param {String} qs - * @api private - */ - - exports.decode = function(qs){ - var qry = {}; - var pairs = qs.split('&'); - for (var i = 0, l = pairs.length; i < l; i++) { - var pair = pairs[i].split('='); - qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); - } - return qry; - }; - -},{}],36:[function(_dereq_,module,exports){ - /** - * Parses an URI - * - * @author Steven Levithan <stevenlevithan.com> (MIT license) - * @api private - */ - - var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; - - var parts = [ - 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' - ]; - - module.exports = function parseuri(str) { - var src = str, - b = str.indexOf('['), - e = str.indexOf(']'); - - if (b != -1 && e != -1) { - str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length); - } - - var m = re.exec(str || ''), - uri = {}, - i = 14; - - while (i--) { - uri[parts[i]] = m[i] || ''; - } - - if (b != -1 && e != -1) { - uri.source = src; - uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':'); - uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':'); - uri.ipv6uri = true; - } - - return uri; - }; - -},{}],37:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var global = (function() { return this; })(); - - /** - * WebSocket constructor. - */ - - var WebSocket = global.WebSocket || global.MozWebSocket; - - /** - * Module exports. - */ - - module.exports = WebSocket ? ws : null; - - /** - * WebSocket constructor. - * - * The third `opts` options object gets ignored in web browsers, since it's - * non-standard, and throws a TypeError if passed to the constructor. - * See: https://github.com/einaros/ws/issues/227 - * - * @param {String} uri - * @param {Array} protocols (optional) - * @param {Object) opts (optional) - * @api public - */ - - function ws(uri, protocols, opts) { - var instance; - if (protocols) { - instance = new WebSocket(uri, protocols); - } else { - instance = new WebSocket(uri); - } - return instance; - } - - if (WebSocket) ws.prototype = WebSocket.prototype; - -},{}],38:[function(_dereq_,module,exports){ - (function (global){ - - /* - * Module requirements. - */ - - var isArray = _dereq_('isarray'); - - /** - * Module exports. - */ - - module.exports = hasBinary; - - /** - * Checks for binary data. - * - * Right now only Buffer and ArrayBuffer are supported.. - * - * @param {Object} anything - * @api public - */ - - function hasBinary(data) { - - function _hasBinary(obj) { - if (!obj) return false; - - if ( (global.Buffer && global.Buffer.isBuffer(obj)) || - (global.ArrayBuffer && obj instanceof ArrayBuffer) || - (global.Blob && obj instanceof Blob) || - (global.File && obj instanceof File) - ) { - return true; - } - - if (isArray(obj)) { - for (var i = 0; i < obj.length; i++) { - if (_hasBinary(obj[i])) { - return true; - } - } - } else if (obj && 'object' == typeof obj) { - if (obj.toJSON) { - obj = obj.toJSON(); - } - - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) { - return true; - } - } - } - - return false; - } - - return _hasBinary(data); - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"isarray":39}],39:[function(_dereq_,module,exports){ - module.exports=_dereq_(32) -},{}],40:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var global = _dereq_('global'); - - /** - * Module exports. - * - * Logic borrowed from Modernizr: - * - * - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js - */ - - try { - module.exports = 'XMLHttpRequest' in global && - 'withCredentials' in new global.XMLHttpRequest(); - } catch (err) { - // if XMLHttp support is disabled in IE then it will throw - // when trying to create - module.exports = false; - } - -},{"global":41}],41:[function(_dereq_,module,exports){ - - /** - * Returns `this`. Execute this without a "context" (i.e. without it being - * attached to an object of the left-hand side), and `this` points to the - * "global" scope of the current JS execution. - */ - - module.exports = (function () { return this; })(); - -},{}],42:[function(_dereq_,module,exports){ - - var indexOf = [].indexOf; - - module.exports = function(arr, obj){ - if (indexOf) return arr.indexOf(obj); - for (var i = 0; i < arr.length; ++i) { - if (arr[i] === obj) return i; - } - return -1; - }; -},{}],43:[function(_dereq_,module,exports){ - - /** - * HOP ref. - */ - - var has = Object.prototype.hasOwnProperty; - - /** - * Return own keys in `obj`. - * - * @param {Object} obj - * @return {Array} - * @api public - */ - - exports.keys = Object.keys || function(obj){ - var keys = []; - for (var key in obj) { - if (has.call(obj, key)) { - keys.push(key); - } - } - return keys; - }; - - /** - * Return own values in `obj`. - * - * @param {Object} obj - * @return {Array} - * @api public - */ - - exports.values = function(obj){ - var vals = []; - for (var key in obj) { - if (has.call(obj, key)) { - vals.push(obj[key]); - } - } - return vals; - }; - - /** - * Merge `b` into `a`. - * - * @param {Object} a - * @param {Object} b - * @return {Object} a - * @api public - */ - - exports.merge = function(a, b){ - for (var key in b) { - if (has.call(b, key)) { - a[key] = b[key]; - } - } - return a; - }; - - /** - * Return length of `obj`. - * - * @param {Object} obj - * @return {Number} - * @api public - */ - - exports.length = function(obj){ - return exports.keys(obj).length; - }; - - /** - * Check if `obj` is empty. - * - * @param {Object} obj - * @return {Boolean} - * @api public - */ - - exports.isEmpty = function(obj){ - return 0 == exports.length(obj); - }; -},{}],44:[function(_dereq_,module,exports){ - /** - * Parses an URI - * - * @author Steven Levithan <stevenlevithan.com> (MIT license) - * @api private - */ - - var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; - - var parts = [ - 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host' - , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' - ]; - - module.exports = function parseuri(str) { - var m = re.exec(str || '') - , uri = {} - , i = 14; - - while (i--) { - uri[parts[i]] = m[i] || ''; - } - - return uri; - }; - -},{}],45:[function(_dereq_,module,exports){ - (function (global){ - /*global Blob,File*/ - - /** - * Module requirements - */ - - var isArray = _dereq_('isarray'); - var isBuf = _dereq_('./is-buffer'); - - /** - * Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder. - * Anything with blobs or files should be fed through removeBlobs before coming - * here. - * - * @param {Object} packet - socket.io event packet - * @return {Object} with deconstructed packet and list of buffers - * @api public - */ - - exports.deconstructPacket = function(packet){ - var buffers = []; - var packetData = packet.data; - - function _deconstructPacket(data) { - if (!data) return data; - - if (isBuf(data)) { - var placeholder = { _placeholder: true, num: buffers.length }; - buffers.push(data); - return placeholder; - } else if (isArray(data)) { - var newData = new Array(data.length); - for (var i = 0; i < data.length; i++) { - newData[i] = _deconstructPacket(data[i]); - } - return newData; - } else if ('object' == typeof data && !(data instanceof Date)) { - var newData = {}; - for (var key in data) { - newData[key] = _deconstructPacket(data[key]); - } - return newData; - } - return data; - } - - var pack = packet; - pack.data = _deconstructPacket(packetData); - pack.attachments = buffers.length; // number of binary 'attachments' - return {packet: pack, buffers: buffers}; - }; - - /** - * Reconstructs a binary packet from its placeholder packet and buffers - * - * @param {Object} packet - event packet with placeholders - * @param {Array} buffers - binary buffers to put in placeholder positions - * @return {Object} reconstructed packet - * @api public - */ - - exports.reconstructPacket = function(packet, buffers) { - var curPlaceHolder = 0; - - function _reconstructPacket(data) { - if (data && data._placeholder) { - var buf = buffers[data.num]; // appropriate buffer (should be natural order anyway) - return buf; - } else if (isArray(data)) { - for (var i = 0; i < data.length; i++) { - data[i] = _reconstructPacket(data[i]); - } - return data; - } else if (data && 'object' == typeof data) { - for (var key in data) { - data[key] = _reconstructPacket(data[key]); - } - return data; - } - return data; - } - - packet.data = _reconstructPacket(packet.data); - packet.attachments = undefined; // no longer useful - return packet; - }; - - /** - * Asynchronously removes Blobs or Files from data via - * FileReader's readAsArrayBuffer method. Used before encoding - * data as msgpack. Calls callback with the blobless data. - * - * @param {Object} data - * @param {Function} callback - * @api private - */ - - exports.removeBlobs = function(data, callback) { - function _removeBlobs(obj, curKey, containingObject) { - if (!obj) return obj; - - // convert any blob - if ((global.Blob && obj instanceof Blob) || - (global.File && obj instanceof File)) { - pendingBlobs++; - - // async filereader - var fileReader = new FileReader(); - fileReader.onload = function() { // this.result == arraybuffer - if (containingObject) { - containingObject[curKey] = this.result; - } - else { - bloblessData = this.result; - } - - // if nothing pending its callback time - if(! --pendingBlobs) { - callback(bloblessData); - } - }; - - fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer - } else if (isArray(obj)) { // handle array - for (var i = 0; i < obj.length; i++) { - _removeBlobs(obj[i], i, obj); - } - } else if (obj && 'object' == typeof obj && !isBuf(obj)) { // and object - for (var key in obj) { - _removeBlobs(obj[key], key, obj); - } - } - } - - var pendingBlobs = 0; - var bloblessData = data; - _removeBlobs(bloblessData); - if (!pendingBlobs) { - callback(bloblessData); - } - }; - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./is-buffer":47,"isarray":48}],46:[function(_dereq_,module,exports){ - - /** - * Module dependencies. - */ - - var debug = _dereq_('debug')('socket.io-parser'); - var json = _dereq_('json3'); - var isArray = _dereq_('isarray'); - var Emitter = _dereq_('component-emitter'); - var binary = _dereq_('./binary'); - var isBuf = _dereq_('./is-buffer'); - - /** - * Protocol version. - * - * @api public - */ - - exports.protocol = 4; - - /** - * Packet types. - * - * @api public - */ - - exports.types = [ - 'CONNECT', - 'DISCONNECT', - 'EVENT', - 'BINARY_EVENT', - 'ACK', - 'BINARY_ACK', - 'ERROR' - ]; - - /** - * Packet type `connect`. - * - * @api public - */ - - exports.CONNECT = 0; - - /** - * Packet type `disconnect`. - * - * @api public - */ - - exports.DISCONNECT = 1; - - /** - * Packet type `event`. - * - * @api public - */ - - exports.EVENT = 2; - - /** - * Packet type `ack`. - * - * @api public - */ - - exports.ACK = 3; - - /** - * Packet type `error`. - * - * @api public - */ - - exports.ERROR = 4; - - /** - * Packet type 'binary event' - * - * @api public - */ - - exports.BINARY_EVENT = 5; - - /** - * Packet type `binary ack`. For acks with binary arguments. - * - * @api public - */ - - exports.BINARY_ACK = 6; - - /** - * Encoder constructor. - * - * @api public - */ - - exports.Encoder = Encoder; - - /** - * Decoder constructor. - * - * @api public - */ - - exports.Decoder = Decoder; - - /** - * A socket.io Encoder instance - * - * @api public - */ - - function Encoder() {} - - /** - * Encode a packet as a single string if non-binary, or as a - * buffer sequence, depending on packet type. - * - * @param {Object} obj - packet object - * @param {Function} callback - function to handle encodings (likely engine.write) - * @return Calls callback with Array of encodings - * @api public - */ - - Encoder.prototype.encode = function(obj, callback){ - debug('encoding packet %j', obj); - - if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) { - encodeAsBinary(obj, callback); - } - else { - var encoding = encodeAsString(obj); - callback([encoding]); - } - }; - - /** - * Encode packet as string. - * - * @param {Object} packet - * @return {String} encoded - * @api private - */ - - function encodeAsString(obj) { - var str = ''; - var nsp = false; - - // first is type - str += obj.type; - - // attachments if we have them - if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) { - str += obj.attachments; - str += '-'; - } - - // if we have a namespace other than `/` - // we append it followed by a comma `,` - if (obj.nsp && '/' != obj.nsp) { - nsp = true; - str += obj.nsp; - } - - // immediately followed by the id - if (null != obj.id) { - if (nsp) { - str += ','; - nsp = false; - } - str += obj.id; - } - - // json data - if (null != obj.data) { - if (nsp) str += ','; - str += json.stringify(obj.data); - } - - debug('encoded %j as %s', obj, str); - return str; - } - - /** - * Encode packet as 'buffer sequence' by removing blobs, and - * deconstructing packet into object with placeholders and - * a list of buffers. - * - * @param {Object} packet - * @return {Buffer} encoded - * @api private - */ - - function encodeAsBinary(obj, callback) { - - function writeEncoding(bloblessData) { - var deconstruction = binary.deconstructPacket(bloblessData); - var pack = encodeAsString(deconstruction.packet); - var buffers = deconstruction.buffers; - - buffers.unshift(pack); // add packet info to beginning of data list - callback(buffers); // write all the buffers - } - - binary.removeBlobs(obj, writeEncoding); - } - - /** - * A socket.io Decoder instance - * - * @return {Object} decoder - * @api public - */ - - function Decoder() { - this.reconstructor = null; - } - - /** - * Mix in `Emitter` with Decoder. - */ - - Emitter(Decoder.prototype); - - /** - * Decodes an ecoded packet string into packet JSON. - * - * @param {String} obj - encoded packet - * @return {Object} packet - * @api public - */ - - Decoder.prototype.add = function(obj) { - var packet; - if ('string' == typeof obj) { - packet = decodeString(obj); - if (exports.BINARY_EVENT == packet.type || exports.BINARY_ACK == packet.type) { // binary packet's json - this.reconstructor = new BinaryReconstructor(packet); - - // no attachments, labeled binary but no binary data to follow - if (this.reconstructor.reconPack.attachments === 0) { - this.emit('decoded', packet); - } - } else { // non-binary full packet - this.emit('decoded', packet); - } - } - else if (isBuf(obj) || obj.base64) { // raw binary data - if (!this.reconstructor) { - throw new Error('got binary data when not reconstructing a packet'); - } else { - packet = this.reconstructor.takeBinaryData(obj); - if (packet) { // received final buffer - this.reconstructor = null; - this.emit('decoded', packet); - } - } - } - else { - throw new Error('Unknown type: ' + obj); - } - }; - - /** - * Decode a packet String (JSON data) - * - * @param {String} str - * @return {Object} packet - * @api private - */ - - function decodeString(str) { - var p = {}; - var i = 0; - - // look up type - p.type = Number(str.charAt(0)); - if (null == exports.types[p.type]) return error(); - - // look up attachments if type binary - if (exports.BINARY_EVENT == p.type || exports.BINARY_ACK == p.type) { - var buf = ''; - while (str.charAt(++i) != '-') { - buf += str.charAt(i); - if (i + 1 == str.length) break; - } - if (buf != Number(buf) || str.charAt(i) != '-') { - throw new Error('Illegal attachments'); - } - p.attachments = Number(buf); - } - - // look up namespace (if any) - if ('/' == str.charAt(i + 1)) { - p.nsp = ''; - while (++i) { - var c = str.charAt(i); - if (',' == c) break; - p.nsp += c; - if (i + 1 == str.length) break; - } - } else { - p.nsp = '/'; - } - - // look up id - var next = str.charAt(i + 1); - if ('' !== next && Number(next) == next) { - p.id = ''; - while (++i) { - var c = str.charAt(i); - if (null == c || Number(c) != c) { - --i; - break; - } - p.id += str.charAt(i); - if (i + 1 == str.length) break; - } - p.id = Number(p.id); - } - - // look up json data - if (str.charAt(++i)) { - try { - p.data = json.parse(str.substr(i)); - } catch(e){ - return error(); - } - } - - debug('decoded %s as %j', str, p); - return p; - } - - /** - * Deallocates a parser's resources - * - * @api public - */ - - Decoder.prototype.destroy = function() { - if (this.reconstructor) { - this.reconstructor.finishedReconstruction(); - } - }; - - /** - * A manager of a binary event's 'buffer sequence'. Should - * be constructed whenever a packet of type BINARY_EVENT is - * decoded. - * - * @param {Object} packet - * @return {BinaryReconstructor} initialized reconstructor - * @api private - */ - - function BinaryReconstructor(packet) { - this.reconPack = packet; - this.buffers = []; - } - - /** - * Method to be called when binary data received from connection - * after a BINARY_EVENT packet. - * - * @param {Buffer | ArrayBuffer} binData - the raw binary data received - * @return {null | Object} returns null if more binary data is expected or - * a reconstructed packet object if all buffers have been received. - * @api private - */ - - BinaryReconstructor.prototype.takeBinaryData = function(binData) { - this.buffers.push(binData); - if (this.buffers.length == this.reconPack.attachments) { // done with buffer list - var packet = binary.reconstructPacket(this.reconPack, this.buffers); - this.finishedReconstruction(); - return packet; - } - return null; - }; - - /** - * Cleans up binary packet reconstruction variables. - * - * @api private - */ - - BinaryReconstructor.prototype.finishedReconstruction = function() { - this.reconPack = null; - this.buffers = []; - }; - - function error(data){ - return { - type: exports.ERROR, - data: 'parser error' - }; - } - -},{"./binary":45,"./is-buffer":47,"component-emitter":9,"debug":10,"isarray":48,"json3":49}],47:[function(_dereq_,module,exports){ - (function (global){ - - module.exports = isBuf; - - /** - * Returns true if obj is a buffer or an arraybuffer. - * - * @api private - */ - - function isBuf(obj) { - return (global.Buffer && global.Buffer.isBuffer(obj)) || - (global.ArrayBuffer && obj instanceof ArrayBuffer); - } - - }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],48:[function(_dereq_,module,exports){ - module.exports=_dereq_(32) -},{}],49:[function(_dereq_,module,exports){ - /*! JSON v3.2.6 | http://bestiejs.github.io/json3 | Copyright 2012-2013, Kit Cambridge | http://kit.mit-license.org */ - ;(function (window) { - // Convenience aliases. - var getClass = {}.toString, isProperty, forEach, undef; - - // Detect the `define` function exposed by asynchronous module loaders. The - // strict `define` check is necessary for compatibility with `r.js`. - var isLoader = typeof define === "function" && define.amd; - - // Detect native implementations. - var nativeJSON = typeof JSON == "object" && JSON; - - // Set up the JSON 3 namespace, preferring the CommonJS `exports` object if - // available. - var JSON3 = typeof exports == "object" && exports && !exports.nodeType && exports; - - if (JSON3 && nativeJSON) { - // Explicitly delegate to the native `stringify` and `parse` - // implementations in CommonJS environments. - JSON3.stringify = nativeJSON.stringify; - JSON3.parse = nativeJSON.parse; - } else { - // Export for web browsers, JavaScript engines, and asynchronous module - // loaders, using the global `JSON` object if available. - JSON3 = window.JSON = nativeJSON || {}; - } - - // Test the `Date#getUTC*` methods. Based on work by @Yaffle. - var isExtended = new Date(-3509827334573292); - try { - // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical - // results for certain dates in Opera >= 10.53. - isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 && - // Safari < 2.0.2 stores the internal millisecond time value correctly, - // but clips the values returned by the date methods to the range of - // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]). - isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708; - } catch (exception) {} - - // Internal: Determines whether the native `JSON.stringify` and `parse` - // implementations are spec-compliant. Based on work by Ken Snyder. - function has(name) { - if (has[name] !== undef) { - // Return cached feature test result. - return has[name]; - } - - var isSupported; - if (name == "bug-string-char-index") { - // IE <= 7 doesn't support accessing string characters using square - // bracket notation. IE 8 only supports this for primitives. - isSupported = "a"[0] != "a"; - } else if (name == "json") { - // Indicates whether both `JSON.stringify` and `JSON.parse` are - // supported. - isSupported = has("json-stringify") && has("json-parse"); - } else { - var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'; - // Test `JSON.stringify`. - if (name == "json-stringify") { - var stringify = JSON3.stringify, stringifySupported = typeof stringify == "function" && isExtended; - if (stringifySupported) { - // A test function object with a custom `toJSON` method. - (value = function () { - return 1; - }).toJSON = value; - try { - stringifySupported = - // Firefox 3.1b1 and b2 serialize string, number, and boolean - // primitives as object literals. - stringify(0) === "0" && - // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object - // literals. - stringify(new Number()) === "0" && - stringify(new String()) == '""' && - // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or - // does not define a canonical JSON representation (this applies to - // objects with `toJSON` properties as well, *unless* they are nested - // within an object or array). - stringify(getClass) === undef && - // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and - // FF 3.1b3 pass this test. - stringify(undef) === undef && - // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s, - // respectively, if the value is omitted entirely. - stringify() === undef && - // FF 3.1b1, 2 throw an error if the given value is not a number, - // string, array, object, Boolean, or `null` literal. This applies to - // objects with custom `toJSON` methods as well, unless they are nested - // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON` - // methods entirely. - stringify(value) === "1" && - stringify([value]) == "[1]" && - // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of - // `"[null]"`. - stringify([undef]) == "[null]" && - // YUI 3.0.0b1 fails to serialize `null` literals. - stringify(null) == "null" && - // FF 3.1b1, 2 halts serialization if an array contains a function: - // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3 - // elides non-JSON values from objects and arrays, unless they - // define custom `toJSON` methods. - stringify([undef, getClass, null]) == "[null,null,null]" && - // Simple serialization test. FF 3.1b1 uses Unicode escape sequences - // where character escape codes are expected (e.g., `\b` => `\u0008`). - stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized && - // FF 3.1b1 and b2 ignore the `filter` and `width` arguments. - stringify(null, value) === "1" && - stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" && - // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly - // serialize extended years. - stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' && - // The milliseconds are optional in ES 5, but required in 5.1. - stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' && - // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative - // four-digit years instead of six-digit years. Credits: @Yaffle. - stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' && - // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond - // values less than 1000. Credits: @Yaffle. - stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"'; - } catch (exception) { - stringifySupported = false; - } - } - isSupported = stringifySupported; - } - // Test `JSON.parse`. - if (name == "json-parse") { - var parse = JSON3.parse; - if (typeof parse == "function") { - try { - // FF 3.1b1, b2 will throw an exception if a bare literal is provided. - // Conforming implementations should also coerce the initial argument to - // a string prior to parsing. - if (parse("0") === 0 && !parse(false)) { - // Simple parsing test. - value = parse(serialized); - var parseSupported = value["a"].length == 5 && value["a"][0] === 1; - if (parseSupported) { - try { - // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings. - parseSupported = !parse('"\t"'); - } catch (exception) {} - if (parseSupported) { - try { - // FF 4.0 and 4.0.1 allow leading `+` signs and leading - // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow - // certain octal literals. - parseSupported = parse("01") !== 1; - } catch (exception) {} - } - if (parseSupported) { - try { - // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal - // points. These environments, along with FF 3.1b1 and 2, - // also allow trailing commas in JSON objects and arrays. - parseSupported = parse("1.") !== 1; - } catch (exception) {} - } - } - } - } catch (exception) { - parseSupported = false; - } - } - isSupported = parseSupported; - } - } - return has[name] = !!isSupported; - } - - if (!has("json")) { - // Common `[[Class]]` name aliases. - var functionClass = "[object Function]"; - var dateClass = "[object Date]"; - var numberClass = "[object Number]"; - var stringClass = "[object String]"; - var arrayClass = "[object Array]"; - var booleanClass = "[object Boolean]"; - - // Detect incomplete support for accessing string characters by index. - var charIndexBuggy = has("bug-string-char-index"); - - // Define additional utility methods if the `Date` methods are buggy. - if (!isExtended) { - var floor = Math.floor; - // A mapping between the months of the year and the number of days between - // January 1st and the first of the respective month. - var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; - // Internal: Calculates the number of days between the Unix epoch and the - // first day of the given month. - var getDay = function (year, month) { - return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400); - }; - } - - // Internal: Determines if a property is a direct property of the given - // object. Delegates to the native `Object#hasOwnProperty` method. - if (!(isProperty = {}.hasOwnProperty)) { - isProperty = function (property) { - var members = {}, constructor; - if ((members.__proto__ = null, members.__proto__ = { - // The *proto* property cannot be set multiple times in recent - // versions of Firefox and SeaMonkey. - "toString": 1 - }, members).toString != getClass) { - // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but - // supports the mutable *proto* property. - isProperty = function (property) { - // Capture and break the object's prototype chain (see section 8.6.2 - // of the ES 5.1 spec). The parenthesized expression prevents an - // unsafe transformation by the Closure Compiler. - var original = this.__proto__, result = property in (this.__proto__ = null, this); - // Restore the original prototype chain. - this.__proto__ = original; - return result; - }; - } else { - // Capture a reference to the top-level `Object` constructor. - constructor = members.constructor; - // Use the `constructor` property to simulate `Object#hasOwnProperty` in - // other environments. - isProperty = function (property) { - var parent = (this.constructor || constructor).prototype; - return property in this && !(property in parent && this[property] === parent[property]); - }; - } - members = null; - return isProperty.call(this, property); - }; - } - - // Internal: A set of primitive types used by `isHostType`. - var PrimitiveTypes = { - 'boolean': 1, - 'number': 1, - 'string': 1, - 'undefined': 1 - }; - - // Internal: Determines if the given object `property` value is a - // non-primitive. - var isHostType = function (object, property) { - var type = typeof object[property]; - return type == 'object' ? !!object[property] : !PrimitiveTypes[type]; - }; - - // Internal: Normalizes the `for...in` iteration algorithm across - // environments. Each enumerated key is yielded to a `callback` function. - forEach = function (object, callback) { - var size = 0, Properties, members, property; - - // Tests for bugs in the current environment's `for...in` algorithm. The - // `valueOf` property inherits the non-enumerable flag from - // `Object.prototype` in older versions of IE, Netscape, and Mozilla. - (Properties = function () { - this.valueOf = 0; - }).prototype.valueOf = 0; - - // Iterate over a new instance of the `Properties` class. - members = new Properties(); - for (property in members) { - // Ignore all properties inherited from `Object.prototype`. - if (isProperty.call(members, property)) { - size++; - } - } - Properties = members = null; - - // Normalize the iteration algorithm. - if (!size) { - // A list of non-enumerable properties inherited from `Object.prototype`. - members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"]; - // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable - // properties. - forEach = function (object, callback) { - var isFunction = getClass.call(object) == functionClass, property, length; - var hasProperty = !isFunction && typeof object.constructor != 'function' && isHostType(object, 'hasOwnProperty') ? object.hasOwnProperty : isProperty; - for (property in object) { - // Gecko <= 1.0 enumerates the `prototype` property of functions under - // certain conditions; IE does not. - if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) { - callback(property); - } - } - // Manually invoke the callback for each non-enumerable property. - for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property)); - }; - } else if (size == 2) { - // Safari <= 2.0.4 enumerates shadowed properties twice. - forEach = function (object, callback) { - // Create a set of iterated properties. - var members = {}, isFunction = getClass.call(object) == functionClass, property; - for (property in object) { - // Store each property name to prevent double enumeration. The - // `prototype` property of functions is not enumerated due to cross- - // environment inconsistencies. - if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) { - callback(property); - } - } - }; - } else { - // No bugs detected; use the standard `for...in` algorithm. - forEach = function (object, callback) { - var isFunction = getClass.call(object) == functionClass, property, isConstructor; - for (property in object) { - if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) { - callback(property); - } - } - // Manually invoke the callback for the `constructor` property due to - // cross-environment inconsistencies. - if (isConstructor || isProperty.call(object, (property = "constructor"))) { - callback(property); - } - }; - } - return forEach(object, callback); - }; - - // Public: Serializes a JavaScript `value` as a JSON string. The optional - // `filter` argument may specify either a function that alters how object and - // array members are serialized, or an array of strings and numbers that - // indicates which properties should be serialized. The optional `width` - // argument may be either a string or number that specifies the indentation - // level of the output. - if (!has("json-stringify")) { - // Internal: A map of control characters and their escaped equivalents. - var Escapes = { - 92: "\\\\", - 34: '\\"', - 8: "\\b", - 12: "\\f", - 10: "\\n", - 13: "\\r", - 9: "\\t" - }; - - // Internal: Converts `value` into a zero-padded string such that its - // length is at least equal to `width`. The `width` must be <= 6. - var leadingZeroes = "000000"; - var toPaddedString = function (width, value) { - // The `|| 0` expression is necessary to work around a bug in - // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`. - return (leadingZeroes + (value || 0)).slice(-width); - }; - - // Internal: Double-quotes a string `value`, replacing all ASCII control - // characters (characters with code unit values between 0 and 31) with - // their escaped equivalents. This is an implementation of the - // `Quote(value)` operation defined in ES 5.1 section 15.12.3. - var unicodePrefix = "\\u00"; - var quote = function (value) { - var result = '"', index = 0, length = value.length, isLarge = length > 10 && charIndexBuggy, symbols; - if (isLarge) { - symbols = value.split(""); - } - for (; index < length; index++) { - var charCode = value.charCodeAt(index); - // If the character is a control character, append its Unicode or - // shorthand escape sequence; otherwise, append the character as-is. - switch (charCode) { - case 8: case 9: case 10: case 12: case 13: case 34: case 92: - result += Escapes[charCode]; - break; - default: - if (charCode < 32) { - result += unicodePrefix + toPaddedString(2, charCode.toString(16)); - break; - } - result += isLarge ? symbols[index] : charIndexBuggy ? value.charAt(index) : value[index]; - } - } - return result + '"'; - }; - - // Internal: Recursively serializes an object. Implements the - // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations. - var serialize = function (property, object, callback, properties, whitespace, indentation, stack) { - var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result; - try { - // Necessary for host object support. - value = object[property]; - } catch (exception) {} - if (typeof value == "object" && value) { - className = getClass.call(value); - if (className == dateClass && !isProperty.call(value, "toJSON")) { - if (value > -1 / 0 && value < 1 / 0) { - // Dates are serialized according to the `Date#toJSON` method - // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15 - // for the ISO 8601 date time string format. - if (getDay) { - // Manually compute the year, month, date, hours, minutes, - // seconds, and milliseconds if the `getUTC*` methods are - // buggy. Adapted from @Yaffle's `date-shim` project. - date = floor(value / 864e5); - for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++); - for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++); - date = 1 + date - getDay(year, month); - // The `time` value specifies the time within the day (see ES - // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used - // to compute `A modulo B`, as the `%` operator does not - // correspond to the `modulo` operation for negative numbers. - time = (value % 864e5 + 864e5) % 864e5; - // The hours, minutes, seconds, and milliseconds are obtained by - // decomposing the time within the day. See section 15.9.1.10. - hours = floor(time / 36e5) % 24; - minutes = floor(time / 6e4) % 60; - seconds = floor(time / 1e3) % 60; - milliseconds = time % 1e3; - } else { - year = value.getUTCFullYear(); - month = value.getUTCMonth(); - date = value.getUTCDate(); - hours = value.getUTCHours(); - minutes = value.getUTCMinutes(); - seconds = value.getUTCSeconds(); - milliseconds = value.getUTCMilliseconds(); - } - // Serialize extended years correctly. - value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) + - "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) + - // Months, dates, hours, minutes, and seconds should have two - // digits; milliseconds should have three. - "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) + - // Milliseconds are optional in ES 5.0, but required in 5.1. - "." + toPaddedString(3, milliseconds) + "Z"; - } else { - value = null; - } - } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) { - // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the - // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3 - // ignores all `toJSON` methods on these objects unless they are - // defined directly on an instance. - value = value.toJSON(property); - } - } - if (callback) { - // If a replacement function was provided, call it to obtain the value - // for serialization. - value = callback.call(object, property, value); - } - if (value === null) { - return "null"; - } - className = getClass.call(value); - if (className == booleanClass) { - // Booleans are represented literally. - return "" + value; - } else if (className == numberClass) { - // JSON numbers must be finite. `Infinity` and `NaN` are serialized as - // `"null"`. - return value > -1 / 0 && value < 1 / 0 ? "" + value : "null"; - } else if (className == stringClass) { - // Strings are double-quoted and escaped. - return quote("" + value); - } - // Recursively serialize objects and arrays. - if (typeof value == "object") { - // Check for cyclic structures. This is a linear search; performance - // is inversely proportional to the number of unique nested objects. - for (length = stack.length; length--;) { - if (stack[length] === value) { - // Cyclic structures cannot be serialized by `JSON.stringify`. - throw TypeError(); - } - } - // Add the object to the stack of traversed objects. - stack.push(value); - results = []; - // Save the current indentation level and indent one additional level. - prefix = indentation; - indentation += whitespace; - if (className == arrayClass) { - // Recursively serialize array elements. - for (index = 0, length = value.length; index < length; index++) { - element = serialize(index, value, callback, properties, whitespace, indentation, stack); - results.push(element === undef ? "null" : element); - } - result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]"; - } else { - // Recursively serialize object members. Members are selected from - // either a user-specified list of property names, or the object - // itself. - forEach(properties || value, function (property) { - var element = serialize(property, value, callback, properties, whitespace, indentation, stack); - if (element !== undef) { - // According to ES 5.1 section 15.12.3: "If `gap` {whitespace} - // is not the empty string, let `member` {quote(property) + ":"} - // be the concatenation of `member` and the `space` character." - // The "`space` character" refers to the literal space - // character, not the `space` {width} argument provided to - // `JSON.stringify`. - results.push(quote(property) + ":" + (whitespace ? " " : "") + element); - } - }); - result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}"; - } - // Remove the object from the traversed object stack. - stack.pop(); - return result; - } - }; - - // Public: `JSON.stringify`. See ES 5.1 section 15.12.3. - JSON3.stringify = function (source, filter, width) { - var whitespace, callback, properties, className; - if (typeof filter == "function" || typeof filter == "object" && filter) { - if ((className = getClass.call(filter)) == functionClass) { - callback = filter; - } else if (className == arrayClass) { - // Convert the property names array into a makeshift set. - properties = {}; - for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1)); - } - } - if (width) { - if ((className = getClass.call(width)) == numberClass) { - // Convert the `width` to an integer and create a string containing - // `width` number of space characters. - if ((width -= width % 1) > 0) { - for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " "); - } - } else if (className == stringClass) { - whitespace = width.length <= 10 ? width : width.slice(0, 10); - } - } - // Opera <= 7.54u2 discards the values associated with empty string keys - // (`""`) only if they are used directly within an object member list - // (e.g., `!("" in { "": 1})`). - return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []); - }; - } - - // Public: Parses a JSON source string. - if (!has("json-parse")) { - var fromCharCode = String.fromCharCode; - - // Internal: A map of escaped control characters and their unescaped - // equivalents. - var Unescapes = { - 92: "\\", - 34: '"', - 47: "/", - 98: "\b", - 116: "\t", - 110: "\n", - 102: "\f", - 114: "\r" - }; - - // Internal: Stores the parser state. - var Index, Source; - - // Internal: Resets the parser state and throws a `SyntaxError`. - var abort = function() { - Index = Source = null; - throw SyntaxError(); - }; - - // Internal: Returns the next token, or `"$"` if the parser has reached - // the end of the source string. A token may be a string, number, `null` - // literal, or Boolean literal. - var lex = function () { - var source = Source, length = source.length, value, begin, position, isSigned, charCode; - while (Index < length) { - charCode = source.charCodeAt(Index); - switch (charCode) { - case 9: case 10: case 13: case 32: - // Skip whitespace tokens, including tabs, carriage returns, line - // feeds, and space characters. - Index++; - break; - case 123: case 125: case 91: case 93: case 58: case 44: - // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at - // the current position. - value = charIndexBuggy ? source.charAt(Index) : source[Index]; - Index++; - return value; - case 34: - // `"` delimits a JSON string; advance to the next character and - // begin parsing the string. String tokens are prefixed with the - // sentinel `@` character to distinguish them from punctuators and - // end-of-string tokens. - for (value = "@", Index++; Index < length;) { - charCode = source.charCodeAt(Index); - if (charCode < 32) { - // Unescaped ASCII control characters (those with a code unit - // less than the space character) are not permitted. - abort(); - } else if (charCode == 92) { - // A reverse solidus (`\`) marks the beginning of an escaped - // control character (including `"`, `\`, and `/`) or Unicode - // escape sequence. - charCode = source.charCodeAt(++Index); - switch (charCode) { - case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114: - // Revive escaped control characters. - value += Unescapes[charCode]; - Index++; - break; - case 117: - // `\u` marks the beginning of a Unicode escape sequence. - // Advance to the first character and validate the - // four-digit code point. - begin = ++Index; - for (position = Index + 4; Index < position; Index++) { - charCode = source.charCodeAt(Index); - // A valid sequence comprises four hexdigits (case- - // insensitive) that form a single hexadecimal value. - if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) { - // Invalid Unicode escape sequence. - abort(); - } - } - // Revive the escaped character. - value += fromCharCode("0x" + source.slice(begin, Index)); - break; - default: - // Invalid escape sequence. - abort(); - } - } else { - if (charCode == 34) { - // An unescaped double-quote character marks the end of the - // string. - break; - } - charCode = source.charCodeAt(Index); - begin = Index; - // Optimize for the common case where a string is valid. - while (charCode >= 32 && charCode != 92 && charCode != 34) { - charCode = source.charCodeAt(++Index); - } - // Append the string as-is. - value += source.slice(begin, Index); - } - } - if (source.charCodeAt(Index) == 34) { - // Advance to the next character and return the revived string. - Index++; - return value; - } - // Unterminated string. - abort(); - default: - // Parse numbers and literals. - begin = Index; - // Advance past the negative sign, if one is specified. - if (charCode == 45) { - isSigned = true; - charCode = source.charCodeAt(++Index); - } - // Parse an integer or floating-point value. - if (charCode >= 48 && charCode <= 57) { - // Leading zeroes are interpreted as octal literals. - if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) { - // Illegal octal literal. - abort(); - } - isSigned = false; - // Parse the integer component. - for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++); - // Floats cannot contain a leading decimal point; however, this - // case is already accounted for by the parser. - if (source.charCodeAt(Index) == 46) { - position = ++Index; - // Parse the decimal component. - for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); - if (position == Index) { - // Illegal trailing decimal. - abort(); - } - Index = position; - } - // Parse exponents. The `e` denoting the exponent is - // case-insensitive. - charCode = source.charCodeAt(Index); - if (charCode == 101 || charCode == 69) { - charCode = source.charCodeAt(++Index); - // Skip past the sign following the exponent, if one is - // specified. - if (charCode == 43 || charCode == 45) { - Index++; - } - // Parse the exponential component. - for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); - if (position == Index) { - // Illegal empty exponent. - abort(); - } - Index = position; - } - // Coerce the parsed value to a JavaScript number. - return +source.slice(begin, Index); - } - // A negative sign may only precede numbers. - if (isSigned) { - abort(); - } - // `true`, `false`, and `null` literals. - if (source.slice(Index, Index + 4) == "true") { - Index += 4; - return true; - } else if (source.slice(Index, Index + 5) == "false") { - Index += 5; - return false; - } else if (source.slice(Index, Index + 4) == "null") { - Index += 4; - return null; - } - // Unrecognized token. - abort(); - } - } - // Return the sentinel `$` character if the parser has reached the end - // of the source string. - return "$"; - }; - - // Internal: Parses a JSON `value` token. - var get = function (value) { - var results, hasMembers; - if (value == "$") { - // Unexpected end of input. - abort(); - } - if (typeof value == "string") { - if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") { - // Remove the sentinel `@` character. - return value.slice(1); - } - // Parse object and array literals. - if (value == "[") { - // Parses a JSON array, returning a new JavaScript array. - results = []; - for (;; hasMembers || (hasMembers = true)) { - value = lex(); - // A closing square bracket marks the end of the array literal. - if (value == "]") { - break; - } - // If the array literal contains elements, the current token - // should be a comma separating the previous element from the - // next. - if (hasMembers) { - if (value == ",") { - value = lex(); - if (value == "]") { - // Unexpected trailing `,` in array literal. - abort(); - } - } else { - // A `,` must separate each array element. - abort(); - } - } - // Elisions and leading commas are not permitted. - if (value == ",") { - abort(); - } - results.push(get(value)); - } - return results; - } else if (value == "{") { - // Parses a JSON object, returning a new JavaScript object. - results = {}; - for (;; hasMembers || (hasMembers = true)) { - value = lex(); - // A closing curly brace marks the end of the object literal. - if (value == "}") { - break; - } - // If the object literal contains members, the current token - // should be a comma separator. - if (hasMembers) { - if (value == ",") { - value = lex(); - if (value == "}") { - // Unexpected trailing `,` in object literal. - abort(); - } - } else { - // A `,` must separate each object member. - abort(); - } - } - // Leading commas are not permitted, object property names must be - // double-quoted strings, and a `:` must separate each property - // name and value. - if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") { - abort(); - } - results[value.slice(1)] = get(lex()); - } - return results; - } - // Unexpected token encountered. - abort(); - } - return value; - }; - - // Internal: Updates a traversed object member. - var update = function(source, property, callback) { - var element = walk(source, property, callback); - if (element === undef) { - delete source[property]; - } else { - source[property] = element; - } - }; - - // Internal: Recursively traverses a parsed JSON object, invoking the - // `callback` function for each value. This is an implementation of the - // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2. - var walk = function (source, property, callback) { - var value = source[property], length; - if (typeof value == "object" && value) { - // `forEach` can't be used to traverse an array in Opera <= 8.54 - // because its `Object#hasOwnProperty` implementation returns `false` - // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`). - if (getClass.call(value) == arrayClass) { - for (length = value.length; length--;) { - update(value, length, callback); - } - } else { - forEach(value, function (property) { - update(value, property, callback); - }); - } - } - return callback.call(source, property, value); - }; - - // Public: `JSON.parse`. See ES 5.1 section 15.12.2. - JSON3.parse = function (source, callback) { - var result, value; - Index = 0; - Source = "" + source; - result = get(lex()); - // If a JSON string contains multiple tokens, it is invalid. - if (lex() != "$") { - abort(); - } - // Reset the parser state. - Index = Source = null; - return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result; - }; - } - } - - // Export for asynchronous module loaders. - if (isLoader) { - define(function () { - return JSON3; - }); - } - }(this)); - -},{}],50:[function(_dereq_,module,exports){ - module.exports = toArray - - function toArray(list, index) { - var array = [] - - index = index || 0 - - for (var i = index || 0; i < list.length; i++) { - array[i - index] = list[i] - } - - return array - } - -},{}]},{},[1]) -(1) -}); \ No newline at end of file diff --git a/assets/www/js/vendor/underscore.js b/assets/www/js/vendor/underscore.js deleted file mode 100644 index f01025b7bcaab18e6b698141c854f95669a5975c..0000000000000000000000000000000000000000 --- a/assets/www/js/vendor/underscore.js +++ /dev/null @@ -1,6 +0,0 @@ -// Underscore.js 1.8.3 -// http://underscorejs.org -// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. -(function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.hasOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}},j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])<u?i=a+1:o=a}return i},m.indexOf=r(1,m.findIndex,m.sortedIndex),m.lastIndexOf=r(-1,m.findLastIndex),m.range=function(n,t,r){null==t&&(t=n||0,n=0),r=r||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=Array(e),i=0;e>i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e<arguments.length;)i.push(arguments[e++]);return E(n,r,this,this,i)};return r},m.bindAll=function(n){var t,r,e=arguments.length;if(1>=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this); -//# sourceMappingURL=underscore-min.map \ No newline at end of file diff --git a/assets/www/license/license_g1-en.html b/assets/www/license/license_g1-en.html index 4ee6d007b6b87087862b0b7f616ecb529917fd5f..5e14d6f20d20e610ee7a77e424ee84b88dc343f3 100644 --- a/assets/www/license/license_g1-en.html +++ b/assets/www/license/license_g1-en.html @@ -1,10 +1,57 @@ -<html><header><meta charset="utf-8"></header><body><h1 id="license-1-v0-2-5">License Äž1 - v0.2.5</h1> +<html><header><meta charset="utf-8"></header><body><h1 id="license-1-v0-2-9">License Äž1 - v0.2.9</h1> <p>:date: 2017-08-21 16:59 -:modified: 2018-01-24 19:20</p> +:modified: 2018-07-14 18:05</p> <p><strong>Money licensing and liability commitment.</strong></p> -<p>Any certification operation of a new member of Äž1 must first be accompanied by the transmission of this license of the currency Äž1 whose certifier must ensure that it has been studied, understood and accepted by the person who will be certified.</p> -<h2 id="money-1">Money Äž1</h2> -<p>Äž1 occurs via a Universal Dividend (DU) for any human member, which is of the form:</p> +<p>Any certification operation of a new member of Äž1 must first be accompanied by the transmission of this license of the Äž1 currency +whose certifier must ensure that it has been studied, understood and accepted by the person who will be certified.</p> +<p>Any meeting event about Ḡ1 should include the acknowledgment of this license, which can be read out loud, or given by any means.</p> +<h2 id="-1-web-of-trust-1-wot-">Äž1 Web of Trust (Äž1 WoT)</h2> +<p><strong>Warning:</strong> Certifying is not just about making sure you've met the person, it's ensuring the Äž1 community you know +the certified person well enough and you will know how to contact her easily, and be able to spot a double account made by a person certified by you, +or other types of problems (disappearance ...), by cross-checking that will reveal the problem if necessary.</p> +<p><strong>Highly recommended advices</strong></p> +<p>A well-known person imply that you are able to contact her by many different means (physically, digitally, other...) but also +that you know some who know her as well and can contact her as easily. Notably, if you don't know well her other certifiers it's +a strong sign that you don't know the person well and a certification made in this context will alert all the Äž1 community. +In a case of insufficient knowledge then no certification should occur.</p> +<p>Never certify alone, but always with another member of the Web of Trust to avoid any software misuse. In case of any error, +immediately contact other community member of the Äž1 WoT.</p> +<p>Verify that the future certified person master her account operations : a good way to verify it is to transfer some Äž1 to the target account, +and to ask then a refund to your own account, it will assure you that the certified person master his private key.</p> +<p>Verify that your contacts have studied and understood the last version of the license.</p> +<p>If you are aware that an effective certifier or a future certifier of an account does not know the account owner, please alert immediately some +experts of the subject among your contacts in the Äž1 WoT, for the procedure to be verified by the Äž1 WoT members.</p> +<p>When you are a member of the Äž1 WoT and you are about to certify a new account:</p> +<p><strong>You are assured:</strong></p> +<p><strong>1 -</strong> That you know well enough (not only "have seen" once) the person who declare to handle this public key (new account). +Look at the above advices about "know well".</p> +<p><strong>2 -</strong> To have personally verified with her that it is the good public key you are about to certify. (see advices above).</p> +<p><strong>3 -</strong> To have verified with the person that she has indeed generated his Duniter account revocation document file, which will enable her, +if necessary, to cancel his member status (in case of account theft, UID change, an incorrectly created account, etc.).</p> +<p><strong>4a -</strong> To meet her physically to make sure that it is this person you know who manages this public key.</p> +<p><strong>4b -</strong> Or to remotely verify the person <-> public key link by contacting the person via several different means of communication, +such as post mail + social network + forum + email + video meeting + phone (acknowledge voice). Because if you can hack an email account +or a forum account, it will be much harder to imagine hacking four distinct means of communication, +and mimic the appearance (video) as well as the voice of the person.</p> +<p>However, the <strong>4a</strong> is preferable to <strong>4b</strong>, whereas the <strong>1</strong>, <strong>2</strong> and <strong>3</strong> statements are always required in all cases.</p> +<p><strong>Abbreviated WoT rules:</strong></p> +<p>Each member has a stock of 100 possible certifications, which can only be issued at the rate of 1 certification / 5 days.</p> +<p>Valid for 2 months, certification for a new member is definitively adopted only if the certified has at least 4 other certifications after these 2 months, +otherwise the entry process will have to be relaunched.</p> +<p>To become a new member of the Äž1 WoT therefore 5 certifications must be obtained at a distance <= 5 of 80% of the WoT sentinels.</p> +<p>A member of the Äž1 WoT is sentinel when he has received and issued at least Y[N] certifications where N is the number of members of the WoT and +Y[N] = ceiling N ^ (1/5).</p> +<p>Examples:</p> +<ul> +<li>For 1024 < N ≤ 3125 we have Y [N] = 5</li> +<li>For 7776 < N ≤ 16807 we have Y [N] = 7</li> +<li>For 59049 < N ≤ 100 000 we have Y [N] = 10</li> +</ul> +<p>Once the new member is part of the Äž1 WoT his certifications remain valid for 2 years.</p> +<p>To remain a member, you must renew your agreement regularly with your private key (every 12 months) and make sure you have +at least 5 certifications valid after 2 years.</p> +<h2 id="-1-money">Äž1 money</h2> +<p>Äž1 creation occurs via a Universal Dividend (DU) for any human member, which is of the form:</p> <ul> <li>1 DU per person per day</li> </ul> @@ -22,30 +69,10 @@ <li>_M_ the total monetary mass at the equinox</li> <li>_N_ the number of members at the equinox</li> </ul> -<h2 id="web-of-trust-1-wot-1-">Web of Trust Äž1 (WoT Äž1)</h2> -<p><strong>Warning:</strong> Certifying is not just about making sure you've met the person, it's ensuring that the community Äž1 knows the certified person well enough and Duplicate account made by a person certified by you, or other types of problems (disappearance ...), by cross-checking that will reveal the problem if necessary.</p> -<p>When you are a member of Äž1 and you are about to certify a new account:</p> -<p><strong>You are assured:</strong></p> -<p>1°) The person who declares to manage this public key (new account) and to have personally checked with him that this is the public key is sufficiently well known (not only to know this person visually) that you are about to certify.</p> -<p>2a°) To meet her physically to make sure that it is this person you know who manages this public key.</p> -<p>2b°) Remotely verify the public person / key link by contacting the person via several different means of communication, such as social network + forum + mail + video conference + phone (acknowledge voice).</p> -<p>Because if you can hack an email account or a forum account, it will be much harder to imagine hacking four distinct means of communication, and mimic the appearance (video) as well as the voice of the person .</p> -<p>However, the 2 °) is preferable to 3 °, whereas the 1 °) is always indispensable in all cases.</p> -<p>3 °) To have verified with the person concerned that he has indeed generated his Duniter account revocation document, which will enable him, if necessary, to cancel his account (in case of account theft, ID, an incorrectly created account, etc.).</p> -<p><strong>Abbreviated WoT rules:</strong></p> -<p>Each member has a stock of 100 possible certifications, which can only be issued at the rate of 1 certification / 5 days.</p> -<p>Valid for 2 months, certification for a new member is definitively adopted only if the certified has at least 4 other certifications after these 2 months, otherwise the entry process will have to be relaunched.</p> -<p>To become a new member of WoT Äž1 therefore 5 certifications must be obtained at a distance < 5 of 80% of the WoT sentinels.</p> -<p>A member of the TdC Äž1 is sentinel when he has received and issued at least Y [N] certifications where N is the number of members of the TdC and Y [N] = ceiling N ^ (1/5). Examples:</p> -<ul> -<li>For 1024 < N ≤ 3125 we have Y [N] = 5</li> -<li>For 7776 < N ≤ 16807 we have Y [N] = 7</li> -<li>For 59049 < N ≤ 100 000 we have Y [N] = 10</li> -</ul> -<p>Once the new member is part of the WoT Äž1 his certifications remain valid for 2 years.</p> -<p>To remain a member, you must renew your agreement regularly with your private key (every 12 months) and make sure you have at least 5 certifications valid after 2 years.</p> -<h2 id="software-1-and-license-1">Software Äž1 and license Äž1</h2> -<p>The software Äž1 allowing users to manage their use of Äž1 must transmit this license with the software and all the technical parameters of the currency Äž1 and TdC Äž1 which are entered in block 0 of Äž1.</p> -<p>For more details in the technical details it is possible to consult directly the code of Duniter which is a free software and also the data of the blockchain Äž1 by retrieving it via a Duniter instance or node Äž1.</p> +<h2 id="-1-softwares-and-1-license">Äž1 softwares and Äž1 license</h2> +<p>The Äž1 softwares allowing users to manage their use of Äž1 must transmit this license with the software and all the technical parameters +of the Äž1 currency and Äž1 WoT which are entered in block 0 of Äž1.</p> +<p>For more accuracy in the technical details it is possible to consult directly the code of Duniter which is a free software +and also the data of the Äž1 blockchain by retrieving it via a Duniter instance or Äž1 node.</p> <p>More information on the Duniter Team website <a href="https://www.duniter.org">https://www.duniter.org</a></p> </body></html> \ No newline at end of file diff --git a/assets/www/license/license_g1-en.md b/assets/www/license/license_g1-en.md index e3bc41fe8bd3b92eb7d6f543768223ba8c9892dd..1cb16740aef2b1a484a53f6b6daebd98afc7826d 100644 --- a/assets/www/license/license_g1-en.md +++ b/assets/www/license/license_g1-en.md @@ -1,78 +1,113 @@ -License Äž1 - v0.2.5 +License Äž1 - v0.2.9 =================== :date: 2017-08-21 16:59 -:modified: 2018-01-24 19:20 +:modified: 2018-07-14 18:05 **Money licensing and liability commitment.** -Any certification operation of a new member of Äž1 must first be accompanied by the transmission of this license of the currency Äž1 whose certifier must ensure that it has been studied, understood and accepted by the person who will be certified. +Any certification operation of a new member of Äž1 must first be accompanied by the transmission of this license of the Äž1 currency +whose certifier must ensure that it has been studied, understood and accepted by the person who will be certified. -Money Äž1 --------- +Any meeting event about Ḡ1 should include the acknowledgment of this license, which can be read out loud, or given by any means. -Äž1 occurs via a Universal Dividend (DU) for any human member, which is of the form: +Äž1 Web of Trust (Äž1 WoT) +------------------------ -* 1 DU per person per day +**Warning:** Certifying is not just about making sure you've met the person, it's ensuring the Äž1 community you know +the certified person well enough and you will know how to contact her easily, and be able to spot a double account made by a person certified by you, +or other types of problems (disappearance ...), by cross-checking that will reveal the problem if necessary. -The amount of DU is identical each day until the next equinox, where the DU will then be reevaluated according to the formula: +**Highly recommended advices** -* DU <sub>day</sub> (the following equinox) = DU <day>(equinox) + c² (M / N) (equinox) / (15778800 seconds)</day> +A well-known person imply that you are able to contact her by many different means (physically, digitally, other...) but also +that you know some who know her as well and can contact her as easily. Notably, if you don't know well her other certifiers it's +a strong sign that you don't know the person well and a certification made in this context will alert all the Äž1 community. +In a case of insufficient knowledge then no certification should occur. -With as parameters: +Never certify alone, but always with another member of the Web of Trust to avoid any software misuse. In case of any error, +immediately contact other community member of the Äž1 WoT. -* c = 4.88% / equinox -* UD (0) = 10.00 Äž1 +Verify that the future certified person master her account operations : a good way to verify it is to transfer some Äž1 to the target account, +and to ask then a refund to your own account, it will assure you that the certified person master his private key. -And as variables: +Verify that your contacts have studied and understood the last version of the license. -* _M_ the total monetary mass at the equinox -* _N_ the number of members at the equinox - -Web of Trust Äž1 (WoT Äž1) ------------------------- +If you are aware that an effective certifier or a future certifier of an account does not know the account owner, please alert immediately some +experts of the subject among your contacts in the Äž1 WoT, for the procedure to be verified by the Äž1 WoT members. -**Warning:** Certifying is not just about making sure you've met the person, it's ensuring that the community Äž1 knows the certified person well enough and Duplicate account made by a person certified by you, or other types of problems (disappearance ...), by cross-checking that will reveal the problem if necessary. - -When you are a member of Äž1 and you are about to certify a new account: +When you are a member of the Äž1 WoT and you are about to certify a new account: **You are assured:** -1°) The person who declares to manage this public key (new account) and to have personally checked with him that this is the public key is sufficiently well known (not only to know this person visually) that you are about to certify. +**1 -** That you know well enough (not only "have seen" once) the person who declare to handle this public key (new account). +Look at the above advices about "know well". -2a°) To meet her physically to make sure that it is this person you know who manages this public key. +**2 -** To have personally verified with her that it is the good public key you are about to certify. (see advices above). -2b°) Remotely verify the public person / key link by contacting the person via several different means of communication, such as social network + forum + mail + video conference + phone (acknowledge voice). +**3 -** To have verified with the person that she has indeed generated his Duniter account revocation document file, which will enable her, +if necessary, to cancel his member status (in case of account theft, UID change, an incorrectly created account, etc.). -Because if you can hack an email account or a forum account, it will be much harder to imagine hacking four distinct means of communication, and mimic the appearance (video) as well as the voice of the person . +**4a -** To meet her physically to make sure that it is this person you know who manages this public key. -However, the 2 °) is preferable to 3 °, whereas the 1 °) is always indispensable in all cases. +**4b -** Or to remotely verify the person <-> public key link by contacting the person via several different means of communication, +such as post mail + social network + forum + email + video meeting + phone (acknowledge voice). Because if you can hack an email account +or a forum account, it will be much harder to imagine hacking four distinct means of communication, +and mimic the appearance (video) as well as the voice of the person. -3 °) To have verified with the person concerned that he has indeed generated his Duniter account revocation document, which will enable him, if necessary, to cancel his account (in case of account theft, ID, an incorrectly created account, etc.). +However, the **4a** is preferable to **4b**, whereas the **1**, **2** and **3** statements are always required in all cases. **Abbreviated WoT rules:** Each member has a stock of 100 possible certifications, which can only be issued at the rate of 1 certification / 5 days. -Valid for 2 months, certification for a new member is definitively adopted only if the certified has at least 4 other certifications after these 2 months, otherwise the entry process will have to be relaunched. +Valid for 2 months, certification for a new member is definitively adopted only if the certified has at least 4 other certifications after these 2 months, +otherwise the entry process will have to be relaunched. + +To become a new member of the Äž1 WoT therefore 5 certifications must be obtained at a distance <= 5 of 80% of the WoT sentinels. -To become a new member of WoT Äž1 therefore 5 certifications must be obtained at a distance < 5 of 80% of the WoT sentinels. +A member of the Äž1 WoT is sentinel when he has received and issued at least Y[N] certifications where N is the number of members of the WoT and +Y[N] = ceiling N ^ (1/5). -A member of the TdC Äž1 is sentinel when he has received and issued at least Y [N] certifications where N is the number of members of the TdC and Y [N] = ceiling N ^ (1/5). Examples: +Examples: * For 1024 < N ≤ 3125 we have Y [N] = 5 * For 7776 < N ≤ 16807 we have Y [N] = 7 * For 59049 < N ≤ 100 000 we have Y [N] = 10 -Once the new member is part of the WoT Äž1 his certifications remain valid for 2 years. +Once the new member is part of the Äž1 WoT his certifications remain valid for 2 years. + +To remain a member, you must renew your agreement regularly with your private key (every 12 months) and make sure you have +at least 5 certifications valid after 2 years. + +Äž1 money +-------- + +Äž1 creation occurs via a Universal Dividend (DU) for any human member, which is of the form: -To remain a member, you must renew your agreement regularly with your private key (every 12 months) and make sure you have at least 5 certifications valid after 2 years. +* 1 DU per person per day + +The amount of DU is identical each day until the next equinox, where the DU will then be reevaluated according to the formula: + +* DU <sub>day</sub> (the following equinox) = DU <day>(equinox) + c² (M / N) (equinox) / (15778800 seconds)</day> + +With as parameters: + +* c = 4.88% / equinox +* UD (0) = 10.00 Äž1 + +And as variables: + +* _M_ the total monetary mass at the equinox +* _N_ the number of members at the equinox -Software Äž1 and license Äž1 --------------------------- +Äž1 softwares and Äž1 license +--------------------------- -The software Äž1 allowing users to manage their use of Äž1 must transmit this license with the software and all the technical parameters of the currency Äž1 and TdC Äž1 which are entered in block 0 of Äž1. +The Äž1 softwares allowing users to manage their use of Äž1 must transmit this license with the software and all the technical parameters +of the Äž1 currency and Äž1 WoT which are entered in block 0 of Äž1. -For more details in the technical details it is possible to consult directly the code of Duniter which is a free software and also the data of the blockchain Äž1 by retrieving it via a Duniter instance or node Äž1. +For more accuracy in the technical details it is possible to consult directly the code of Duniter which is a free software +and also the data of the Äž1 blockchain by retrieving it via a Duniter instance or Äž1 node. More information on the Duniter Team website [https://www.duniter.org](https://www.duniter.org) diff --git a/assets/www/license/license_g1-en.txt b/assets/www/license/license_g1-en.txt index e3bc41fe8bd3b92eb7d6f543768223ba8c9892dd..1cb16740aef2b1a484a53f6b6daebd98afc7826d 100644 --- a/assets/www/license/license_g1-en.txt +++ b/assets/www/license/license_g1-en.txt @@ -1,78 +1,113 @@ -License Äž1 - v0.2.5 +License Äž1 - v0.2.9 =================== :date: 2017-08-21 16:59 -:modified: 2018-01-24 19:20 +:modified: 2018-07-14 18:05 **Money licensing and liability commitment.** -Any certification operation of a new member of Äž1 must first be accompanied by the transmission of this license of the currency Äž1 whose certifier must ensure that it has been studied, understood and accepted by the person who will be certified. +Any certification operation of a new member of Äž1 must first be accompanied by the transmission of this license of the Äž1 currency +whose certifier must ensure that it has been studied, understood and accepted by the person who will be certified. -Money Äž1 --------- +Any meeting event about Ḡ1 should include the acknowledgment of this license, which can be read out loud, or given by any means. -Äž1 occurs via a Universal Dividend (DU) for any human member, which is of the form: +Äž1 Web of Trust (Äž1 WoT) +------------------------ -* 1 DU per person per day +**Warning:** Certifying is not just about making sure you've met the person, it's ensuring the Äž1 community you know +the certified person well enough and you will know how to contact her easily, and be able to spot a double account made by a person certified by you, +or other types of problems (disappearance ...), by cross-checking that will reveal the problem if necessary. -The amount of DU is identical each day until the next equinox, where the DU will then be reevaluated according to the formula: +**Highly recommended advices** -* DU <sub>day</sub> (the following equinox) = DU <day>(equinox) + c² (M / N) (equinox) / (15778800 seconds)</day> +A well-known person imply that you are able to contact her by many different means (physically, digitally, other...) but also +that you know some who know her as well and can contact her as easily. Notably, if you don't know well her other certifiers it's +a strong sign that you don't know the person well and a certification made in this context will alert all the Äž1 community. +In a case of insufficient knowledge then no certification should occur. -With as parameters: +Never certify alone, but always with another member of the Web of Trust to avoid any software misuse. In case of any error, +immediately contact other community member of the Äž1 WoT. -* c = 4.88% / equinox -* UD (0) = 10.00 Äž1 +Verify that the future certified person master her account operations : a good way to verify it is to transfer some Äž1 to the target account, +and to ask then a refund to your own account, it will assure you that the certified person master his private key. -And as variables: +Verify that your contacts have studied and understood the last version of the license. -* _M_ the total monetary mass at the equinox -* _N_ the number of members at the equinox - -Web of Trust Äž1 (WoT Äž1) ------------------------- +If you are aware that an effective certifier or a future certifier of an account does not know the account owner, please alert immediately some +experts of the subject among your contacts in the Äž1 WoT, for the procedure to be verified by the Äž1 WoT members. -**Warning:** Certifying is not just about making sure you've met the person, it's ensuring that the community Äž1 knows the certified person well enough and Duplicate account made by a person certified by you, or other types of problems (disappearance ...), by cross-checking that will reveal the problem if necessary. - -When you are a member of Äž1 and you are about to certify a new account: +When you are a member of the Äž1 WoT and you are about to certify a new account: **You are assured:** -1°) The person who declares to manage this public key (new account) and to have personally checked with him that this is the public key is sufficiently well known (not only to know this person visually) that you are about to certify. +**1 -** That you know well enough (not only "have seen" once) the person who declare to handle this public key (new account). +Look at the above advices about "know well". -2a°) To meet her physically to make sure that it is this person you know who manages this public key. +**2 -** To have personally verified with her that it is the good public key you are about to certify. (see advices above). -2b°) Remotely verify the public person / key link by contacting the person via several different means of communication, such as social network + forum + mail + video conference + phone (acknowledge voice). +**3 -** To have verified with the person that she has indeed generated his Duniter account revocation document file, which will enable her, +if necessary, to cancel his member status (in case of account theft, UID change, an incorrectly created account, etc.). -Because if you can hack an email account or a forum account, it will be much harder to imagine hacking four distinct means of communication, and mimic the appearance (video) as well as the voice of the person . +**4a -** To meet her physically to make sure that it is this person you know who manages this public key. -However, the 2 °) is preferable to 3 °, whereas the 1 °) is always indispensable in all cases. +**4b -** Or to remotely verify the person <-> public key link by contacting the person via several different means of communication, +such as post mail + social network + forum + email + video meeting + phone (acknowledge voice). Because if you can hack an email account +or a forum account, it will be much harder to imagine hacking four distinct means of communication, +and mimic the appearance (video) as well as the voice of the person. -3 °) To have verified with the person concerned that he has indeed generated his Duniter account revocation document, which will enable him, if necessary, to cancel his account (in case of account theft, ID, an incorrectly created account, etc.). +However, the **4a** is preferable to **4b**, whereas the **1**, **2** and **3** statements are always required in all cases. **Abbreviated WoT rules:** Each member has a stock of 100 possible certifications, which can only be issued at the rate of 1 certification / 5 days. -Valid for 2 months, certification for a new member is definitively adopted only if the certified has at least 4 other certifications after these 2 months, otherwise the entry process will have to be relaunched. +Valid for 2 months, certification for a new member is definitively adopted only if the certified has at least 4 other certifications after these 2 months, +otherwise the entry process will have to be relaunched. + +To become a new member of the Äž1 WoT therefore 5 certifications must be obtained at a distance <= 5 of 80% of the WoT sentinels. -To become a new member of WoT Äž1 therefore 5 certifications must be obtained at a distance < 5 of 80% of the WoT sentinels. +A member of the Äž1 WoT is sentinel when he has received and issued at least Y[N] certifications where N is the number of members of the WoT and +Y[N] = ceiling N ^ (1/5). -A member of the TdC Äž1 is sentinel when he has received and issued at least Y [N] certifications where N is the number of members of the TdC and Y [N] = ceiling N ^ (1/5). Examples: +Examples: * For 1024 < N ≤ 3125 we have Y [N] = 5 * For 7776 < N ≤ 16807 we have Y [N] = 7 * For 59049 < N ≤ 100 000 we have Y [N] = 10 -Once the new member is part of the WoT Äž1 his certifications remain valid for 2 years. +Once the new member is part of the Äž1 WoT his certifications remain valid for 2 years. + +To remain a member, you must renew your agreement regularly with your private key (every 12 months) and make sure you have +at least 5 certifications valid after 2 years. + +Äž1 money +-------- + +Äž1 creation occurs via a Universal Dividend (DU) for any human member, which is of the form: -To remain a member, you must renew your agreement regularly with your private key (every 12 months) and make sure you have at least 5 certifications valid after 2 years. +* 1 DU per person per day + +The amount of DU is identical each day until the next equinox, where the DU will then be reevaluated according to the formula: + +* DU <sub>day</sub> (the following equinox) = DU <day>(equinox) + c² (M / N) (equinox) / (15778800 seconds)</day> + +With as parameters: + +* c = 4.88% / equinox +* UD (0) = 10.00 Äž1 + +And as variables: + +* _M_ the total monetary mass at the equinox +* _N_ the number of members at the equinox -Software Äž1 and license Äž1 --------------------------- +Äž1 softwares and Äž1 license +--------------------------- -The software Äž1 allowing users to manage their use of Äž1 must transmit this license with the software and all the technical parameters of the currency Äž1 and TdC Äž1 which are entered in block 0 of Äž1. +The Äž1 softwares allowing users to manage their use of Äž1 must transmit this license with the software and all the technical parameters +of the Äž1 currency and Äž1 WoT which are entered in block 0 of Äž1. -For more details in the technical details it is possible to consult directly the code of Duniter which is a free software and also the data of the blockchain Äž1 by retrieving it via a Duniter instance or node Äž1. +For more accuracy in the technical details it is possible to consult directly the code of Duniter which is a free software +and also the data of the Äž1 blockchain by retrieving it via a Duniter instance or Äž1 node. More information on the Duniter Team website [https://www.duniter.org](https://www.duniter.org) diff --git a/assets/www/license/license_g1-eo-EO.html b/assets/www/license/license_g1-eo-EO.html new file mode 100644 index 0000000000000000000000000000000000000000..99ddb48abad406e41c431579002eabcf0408b499 --- /dev/null +++ b/assets/www/license/license_g1-eo-EO.html @@ -0,0 +1,60 @@ +<html><header><meta charset="utf-8"></header><body><h1 id="licenco-1-v0-2-9">Licenco Äž1 - v0.2.9</h1> +<p>:dato: 2017-04-04 12:59 +:modifita: 2019-07-14 12:00</p> +<p><strong>Licenco de la mono kaj promeso de respondeco.</strong></p> +<p>Ĉiu atestado de nova membro de Äž1 devas antaÅe akompaniÄi per transdono de tiu ĉi licenco de la mono Äž1, pri kiu la atestanto devas certiÄi, ke Äi estis studita, komprenita kaj akceptita de la persono, kiu estos atestita.</p> +<p>Ĉiu okazo de renkontiÄo rilate al Äž1 devus akompaniÄi per transdono de tiu ĉi licenco, kiu povas esti laÅte legata, kaj transdonita ĉiamaniere.</p> +<h2 id="reto-de-fido-1-rdf-1-">Reto de Fido Äž1 (RdF Äž1)</h2> +<p><strong>Averto :</strong> Atesti ne estas nur certiÄi, ke vi renkontis la personon, tio estas certigi al la komunumo Äž1, ke vi sufiĉe bone konas la atestitan personon, kaj ke vi tiel scipovos facile kontakti lin/Åin, kaj kapablos malkovri duoblan konton kreitan de persono atestita de vi mem, aÅ alitipajn problemojn (malapero...), farante komparajn kontrolojn, kiuj eventuale ebligos elmontri la problemon.</p> +<p><strong>Ege rekomendindaj konsiloj</strong></p> +<p>Bone koni personon supozigas, ke vi scipovas kontakti lin/Åin per pluraj rimedoj malsamaj (fizika, elektronika, alitipa...), sed ankaÅ ke vi konas plurajn personojn, kiuj konas lin/Åin same bone, kaj kiuj ankaÅ scipovas kontakti lin/Åin simile. Aparte se vi ne bone konas neniun el ties aliaj atestantoj, tio estas forta indiko, ke vi ne bone konas la personon, kaj tia atestaĵo ekas signalon al la tuta komunumo Äž1. Kaze de nesufiĉa kono, necesas nepre ne atesti.</p> +<p>Neniam atestu sola, sed akompanata de almenaÅ unu alia membro de la RdF Äž1 por eviti ĉian manipulan eraron. Kaze de eraro, tuj avertu aliajn membrojn de la RdF Äž1.</p> +<p>AntaŠĉiu atestado, nepre kontrolu, ke tiu konto (ĉu Äi estas validigota aÅ jam membro) jam ricevis unu aÅ plurajn atestaĵojn. LaÅnecese petu informojn por konkakti ties aliajn atestintojn por kune kontroli, ke vi bone konas la personon, kiu kreis la novan konton, kaj ankaÅ ties publikan Ålosilon.</p> +<p>Kontrolu ke la atestoto bone regas sian konton: bona rimedo por kontroli tion estas sendi kelkajn Äž1 al la celata konto, kaj poste peti resendon al via propra konto. Tio certigas, ke la atestoto bone regas sian privatan Ålosilon.</p> +<p>Kontrolu ke viaj kontaktoj bone studis kaj komprenis la licencon Äž1 Äisdatan.</p> +<p>Se vi ekkonscias, ke efektiva aÅ ebla atestanto de la koncernata konto ne konas la koncernatan personon, tuj avertu fakulojn pri la temo inter viaj konatoj de la RdF Äž1, por ke la valid-procezo estu kontrolata de la RdF Äž1.</p> +<p>Kiam vi estas membro de la RdF Äž1, kaj ke vi estas atestonta novan konton:</p> +<p><strong>Vi certiÄis:</strong></p> +<p>1°) ke vi sufiĉe bone konas (ne nur "vide" konas) la personon, kiu deklaras regi tiun publikan Ålosilon (novan konton). Vidu la ĉi-suprajn ege rekomendindajn konsilojn por certiÄi "bone koni".</p> +<p>2°) ke vi persone kontrolis kun li/Åi, ke temas ja pri tiu publika Ålosilo, kiun vi estas atestonta (vidu ĉi-suprajn konsilojn).</p> +<p>3°) ke vi bone kontrolis kun la koncernata persono, ke li/Åi ja kreis sian Duniter-dokumenton pri konto-nuligo, kiu laÅbezone ebligos al li/Åi malaktivigi sian membro-statuson (kaze de konto-Åtelo, ID-ÅanÄo, konto erare kreita, ktp.).</p> +<p>4a°) ke vi fizike renkontis la personon por certiÄi, ke ja lin/Åin vi bone konas, kaj ke ja li/Åi uzas tiun publikan Ålosilon.</p> +<p>4b°) aÅ ke vi distance kontrolis la ligon persono / publik-Ålosilo kontaktante la personon per pluraj komunikiloj malsamaj, kiel paper-poÅto + sociaj retoj + forumo + retpoÅto + video-konferenco + telefono (rekoni la voĉon). Ĉar se oni povas fiuzi retadreson aÅ forum-konton, estos multe pli malfacile fiuzi kvar malsamajn komunikilojn, kaj imiti la aspekton (vidan) kaj plie la voĉon de la persono.</p> +<p>La 4a°) tamen preferindas al la 4b°), dum la punktoj 1°) 2°) kaj 3°) estas antaŠĉio nepraj.</p> +<p><strong>Resumitaj reguloj de la RdF:</strong></p> +<p>Ĉiu membro havas rezervon da 100 eblaj atestaĵoj, kiujn li/Åi povas sendi nur po 1 ĉiun 5-an tagon.</p> +<p>Valida 2 monatojn, atestaĵo por nova membro estas definitive aprobita nur se la atestito havas almenaÅ 4 aliajn atestaĵojn fine de tiuj 2 monatoj, alie la enir-procezo devos esti rekomencita.</p> +<p>Por fariÄi nova membro de la RdF Äž1, necesas do akiri 5 atestaĵojn kaj troviÄi je distanco <= 5 paÅoj de 80% el la referencaj membroj de la RdF.</p> +<p>Membro de la RdF Äž1 estas referenca membro, kiam li/Åi ricevis kaj sendis almenaÅ Y[N] atestaĵojn, kie N estas la nombro de membroj de la RdF kaj Y[N] = plafono N^(1/5). Ekzemploj:</p> +<ul> +<li>por 1024 < N ≤ 3125 oni havas Y[N] = 5</li> +<li>por 7776 < N ≤ 16807 oni havas Y[N] = 7</li> +<li>por 59049 < N ≤ 100 000 oni havas Y[N] = 10</li> +</ul> +<p>Ekde kiam la nova membro partoprenas en la RdF Äž1, ties atestaĵoj restas validaj 2 jarojn.</p> +<p>Por resti membro necesas redoni regule sian konsenton per sia privata Ålosilo (ĉiun 12-an monaton) kaj certiÄi daÅre havi almenaÅ 5 atestaĵojn validajn post la 2 jaroj.</p> +<h2 id="mono-1">Mono Äž1</h2> +<p>Äž1 produktiÄas per Universala Dividendo (UD) por ĉiu homa estaĵo membro de la Reto de Fido Äž1, laÅ la formo:</p> +<ul> +<li>po 1 UD por ĉiu persono ĉiutage</li> +</ul> +<p><strong>Kodo de la mono Äž1</strong></p> +<p>La sumo en Äž1 de la UD samas ĉiutage Äis la venonta ekvinokso, kiam la UD estos tiam revalorigita laÅ la formulo (kun 1 tago = 86 400 sekundoj):</p> +<ul> +<li>UDtago(sekvanta ekvinokso) = UDtago(ekvinokso) + c² (M/N)(ekvinokso) / (182,625 tagoj)</li> +</ul> +<p>kun kiel parametroj:</p> +<ul> +<li>c = 4,88% / ekvinokso</li> +<li>UD(0) = 10,00 Äž1</li> +</ul> +<p>kaj kiel variabloj:</p> +<ul> +<li><em>M</em> la ĉioma mona maso je la ekvinokso</li> +<li><em>N</em> la nombro de membroj je la ekvinokso</li> +</ul> +<h2 id="programoj-1-kaj-licenco-1">Programoj Äž1 kaj licenco Äž1</h2> +<p>La programoj Äž1, kiuj ebligas al la uzantoj mastrumi ties uzon de Äž1, devas transdoni tiun licencon kun la programo, kaj ankaÅ la aron de la teknikaj parametroj de la mono Äž1 kaj de la RdF Äž1, kiu estas enskribita en la bloko 0 de Äž1. Programo, kiu ne konformiÄus al tiuj devigoj de la licenco, ne estus kongrua kun Äž1.</p> +<p>Por pli da precizigoj pri la teknikaj detaloj, eblas rekte konsulti la kodon de Duniter, kiu estas libera programo, kaj ankaÅ la datenojn de la blokĉeno Äž1 ekhavante ilin tra ekzemplero (aÅ nodo) Duniter Äž1.</p> +<p>Pli da informoj ĉe la retejo de la teamo Duniter <a href="https://www.duniter.org">https://www.duniter.org</a></p> +</body></html> \ No newline at end of file diff --git a/assets/www/license/license_g1-eo-EO.md b/assets/www/license/license_g1-eo-EO.md new file mode 100644 index 0000000000000000000000000000000000000000..774064c8fec0e477d23fe314231da1573b2f6dd1 --- /dev/null +++ b/assets/www/license/license_g1-eo-EO.md @@ -0,0 +1,97 @@ +Licenco Äž1 - v0.2.9 +=================== + +:dato: 2017-04-04 12:59 +:modifita: 2019-07-14 12:00 + +**Licenco de la mono kaj promeso de respondeco.** + +Ĉiu atestado de nova membro de Äž1 devas antaÅe akompaniÄi per transdono de tiu ĉi licenco de la mono Äž1, pri kiu la atestanto devas certiÄi, ke Äi estis studita, komprenita kaj akceptita de la persono, kiu estos atestita. + +Ĉiu okazo de renkontiÄo rilate al Äž1 devus akompaniÄi per transdono de tiu ĉi licenco, kiu povas esti laÅte legata, kaj transdonita ĉiamaniere. + +Reto de Fido Äž1 (RdF Äž1) +------------------------------ + +**Averto :** Atesti ne estas nur certiÄi, ke vi renkontis la personon, tio estas certigi al la komunumo Äž1, ke vi sufiĉe bone konas la atestitan personon, kaj ke vi tiel scipovos facile kontakti lin/Åin, kaj kapablos malkovri duoblan konton kreitan de persono atestita de vi mem, aÅ alitipajn problemojn (malapero...), farante komparajn kontrolojn, kiuj eventuale ebligos elmontri la problemon. + +**Ege rekomendindaj konsiloj** + +Bone koni personon supozigas, ke vi scipovas kontakti lin/Åin per pluraj rimedoj malsamaj (fizika, elektronika, alitipa...), sed ankaÅ ke vi konas plurajn personojn, kiuj konas lin/Åin same bone, kaj kiuj ankaÅ scipovas kontakti lin/Åin simile. Aparte se vi ne bone konas neniun el ties aliaj atestantoj, tio estas forta indiko, ke vi ne bone konas la personon, kaj tia atestaĵo ekas signalon al la tuta komunumo Äž1. Kaze de nesufiĉa kono, necesas nepre ne atesti. + +Neniam atestu sola, sed akompanata de almenaÅ unu alia membro de la RdF Äž1 por eviti ĉian manipulan eraron. Kaze de eraro, tuj avertu aliajn membrojn de la RdF Äž1. + +AntaŠĉiu atestado, nepre kontrolu, ke tiu konto (ĉu Äi estas validigota aÅ jam membro) jam ricevis unu aÅ plurajn atestaĵojn. LaÅnecese petu informojn por konkakti ties aliajn atestintojn por kune kontroli, ke vi bone konas la personon, kiu kreis la novan konton, kaj ankaÅ ties publikan Ålosilon. + +Kontrolu ke la atestoto bone regas sian konton: bona rimedo por kontroli tion estas sendi kelkajn Äž1 al la celata konto, kaj poste peti resendon al via propra konto. Tio certigas, ke la atestoto bone regas sian privatan Ålosilon. + +Kontrolu ke viaj kontaktoj bone studis kaj komprenis la licencon Äž1 Äisdatan. + +Se vi ekkonscias, ke efektiva aÅ ebla atestanto de la koncernata konto ne konas la koncernatan personon, tuj avertu fakulojn pri la temo inter viaj konatoj de la RdF Äž1, por ke la valid-procezo estu kontrolata de la RdF Äž1. + +Kiam vi estas membro de la RdF Äž1, kaj ke vi estas atestonta novan konton: + + +**Vi certiÄis:** + +1°) ke vi sufiĉe bone konas (ne nur "vide" konas) la personon, kiu deklaras regi tiun publikan Ålosilon (novan konton). Vidu la ĉi-suprajn ege rekomendindajn konsilojn por certiÄi "bone koni". + +2°) ke vi persone kontrolis kun li/Åi, ke temas ja pri tiu publika Ålosilo, kiun vi estas atestonta (vidu ĉi-suprajn konsilojn). + +3°) ke vi bone kontrolis kun la koncernata persono, ke li/Åi ja kreis sian Duniter-dokumenton pri konto-nuligo, kiu laÅbezone ebligos al li/Åi malaktivigi sian membro-statuson (kaze de konto-Åtelo, ID-ÅanÄo, konto erare kreita, ktp.). + +4a°) ke vi fizike renkontis la personon por certiÄi, ke ja lin/Åin vi bone konas, kaj ke ja li/Åi uzas tiun publikan Ålosilon. + +4b°) aÅ ke vi distance kontrolis la ligon persono / publik-Ålosilo kontaktante la personon per pluraj komunikiloj malsamaj, kiel paper-poÅto + sociaj retoj + forumo + retpoÅto + video-konferenco + telefono (rekoni la voĉon). Ĉar se oni povas fiuzi retadreson aÅ forum-konton, estos multe pli malfacile fiuzi kvar malsamajn komunikilojn, kaj imiti la aspekton (vidan) kaj plie la voĉon de la persono. + +La 4a°) tamen preferindas al la 4b°), dum la punktoj 1°) 2°) kaj 3°) estas antaŠĉio nepraj. + +**Resumitaj reguloj de la RdF:** + +Ĉiu membro havas rezervon da 100 eblaj atestaĵoj, kiujn li/Åi povas sendi nur po 1 ĉiun 5-an tagon. + +Valida 2 monatojn, atestaĵo por nova membro estas definitive aprobita nur se la atestito havas almenaÅ 4 aliajn atestaĵojn fine de tiuj 2 monatoj, alie la enir-procezo devos esti rekomencita. + +Por fariÄi nova membro de la RdF Äž1, necesas do akiri 5 atestaĵojn kaj troviÄi je distanco <= 5 paÅoj de 80% el la referencaj membroj de la RdF. + +Membro de la RdF Äž1 estas referenca membro, kiam li/Åi ricevis kaj sendis almenaÅ Y[N] atestaĵojn, kie N estas la nombro de membroj de la RdF kaj Y[N] = plafono N^(1/5). Ekzemploj: + +* por 1024 < N ≤ 3125 oni havas Y[N] = 5 +* por 7776 < N ≤ 16807 oni havas Y[N] = 7 +* por 59049 < N ≤ 100 000 oni havas Y[N] = 10 + +Ekde kiam la nova membro partoprenas en la RdF Äž1, ties atestaĵoj restas validaj 2 jarojn. + +Por resti membro necesas redoni regule sian konsenton per sia privata Ålosilo (ĉiun 12-an monaton) kaj certiÄi daÅre havi almenaÅ 5 atestaĵojn validajn post la 2 jaroj. + +Mono Äž1 +---------- + +Äž1 produktiÄas per Universala Dividendo (UD) por ĉiu homa estaĵo membro de la Reto de Fido Äž1, laÅ la formo: + +* po 1 UD por ĉiu persono ĉiutage + +**Kodo de la mono Äž1** + +La sumo en Äž1 de la UD samas ĉiutage Äis la venonta ekvinokso, kiam la UD estos tiam revalorigita laÅ la formulo (kun 1 tago = 86 400 sekundoj): + +* UDtago(sekvanta ekvinokso) = UDtago(ekvinokso) + c² (M/N)(ekvinokso) / (182,625 tagoj) + +kun kiel parametroj: + +* c = 4,88% / ekvinokso +* UD(0) = 10,00 Äž1 + +kaj kiel variabloj: + +* *M* la ĉioma mona maso je la ekvinokso +* *N* la nombro de membroj je la ekvinokso + +Programoj Äž1 kaj licenco Äž1 +-------------------------- + +La programoj Äž1, kiuj ebligas al la uzantoj mastrumi ties uzon de Äž1, devas transdoni tiun licencon kun la programo, kaj ankaÅ la aron de la teknikaj parametroj de la mono Äž1 kaj de la RdF Äž1, kiu estas enskribita en la bloko 0 de Äž1. Programo, kiu ne konformiÄus al tiuj devigoj de la licenco, ne estus kongrua kun Äž1. + +Por pli da precizigoj pri la teknikaj detaloj, eblas rekte konsulti la kodon de Duniter, kiu estas libera programo, kaj ankaÅ la datenojn de la blokĉeno Äž1 ekhavante ilin tra ekzemplero (aÅ nodo) Duniter Äž1. + +Pli da informoj ĉe la retejo de la teamo Duniter https://www.duniter.org diff --git a/assets/www/license/license_g1-eo-EO.txt b/assets/www/license/license_g1-eo-EO.txt new file mode 100644 index 0000000000000000000000000000000000000000..b6f3b652e547a82bce2b071c1bf621b38ce14ff7 --- /dev/null +++ b/assets/www/license/license_g1-eo-EO.txt @@ -0,0 +1,97 @@ +Licenco Äž1 - v0.2.9 +=================== + +:dato: 2017-04-04 12:59 +:modifita: 2019-07-14 12:00 + +**Licenco de la mono kaj promeso de respondeco.** + +Ĉiu atestado de nova membro de Äž1 devas antaÅe akompaniÄi per transdono de tiu ĉi licenco de la mono Äž1, pri kiu la atestanto devas certiÄi, ke Äi estis studita, komprenita kaj akceptita de la persono, kiu estos atestita. + +Ĉiu okazo de renkontiÄo rilate al Äž1 devus akompaniÄi per transdono de tiu ĉi licenco, kiu povas esti laÅte legata, kaj transdonita ĉiamaniere. + +Reto de Fido Äž1 (RdF Äž1) +------------------------------ + +**Averto :** Atesti ne estas nur certiÄi, ke vi renkontis la personon, tio estas certigi al la komunumo Äž1, ke vi sufiĉe bone konas la atestitan personon, kaj ke vi tiel scipovos facile kontakti lin/Åin, kaj kapablos malkovri duoblan konton kreitan de persono atestita de vi mem, aÅ alitipajn problemojn (malapero...), farante komparajn kontrolojn, kiuj eventuale ebligos elmontri la problemon. + +**Ege rekomendindaj konsiloj** + +Bone koni personon supozigas, ke vi scipovas kontakti lin/Åin per pluraj rimedoj malsamaj (fizika, elektronika, alitipa...), sed ankaÅ ke vi konas plurajn personojn, kiuj konas lin/Åin same bone, kaj kiuj ankaÅ scipovas kontakti lin/Åin simile. Aparte se vi ne bone konas neniun el ties aliaj atestantoj, tio estas forta indiko, ke vi ne bone konas la personon, kaj tia atestaĵo ekas signalon al la tuta komunumo Äž1. Kaze de nesufiĉa kono, necesas nepre ne atesti. + +Neniam atestu sola, sed akompanata de almenaÅ unu alia membro de la RdF Äž1 por eviti ĉian manipulan eraron. Kaze de eraro, tuj avertu aliajn membrojn de la RdF Äž1. + +AntaŠĉiu atestado, nepre kontrolu, ke tiu konto (ĉu Äi estas validigota aÅ jam membro) jam ricevis unu aÅ plurajn atestaĵojn. LaÅnecese petu informojn por konkakti ties aliajn atestintojn por kune kontroli, ke vi bone konas la personon, kiu kreis la novan konton, kaj ankaÅ ties publikan Ålosilon. + +Kontrolu ke la atestoto bone regas sian konton: bona rimedo por kontroli tion estas sendi kelkajn Äž1 al la celata konto, kaj poste peti resendon al via propra konto. Tio certigas, ke la atestoto bone regas sian privatan Ålosilon. + +Kontrolu ke viaj kontaktoj bone studis kaj komprenis la licencon Äž1 Äisdatan. + +Se vi ekkonscias, ke efektiva aÅ ebla atestanto de la koncernata konto ne konas la koncernatan personon, tuj avertu fakulojn pri la temo inter viaj konatoj de la RdF Äž1, por ke la valid-procezo estu kontrolata de la RdF Äž1. + +Kiam vi estas membro de la RdF Äž1, kaj ke vi estas atestonta novan konton: + + +**Vi certiÄis:** + +1°) ke vi sufiĉe bone konas (ne nur "vide" konas) la personon, kiu deklaras regi tiun publikan Ålosilon (novan konton). Vidu la ĉi-suprajn ege rekomendindajn konsilojn por certiÄi "bone koni". + +2°) ke vi persone kontrolis kun li/Åi, ke temas ja pri tiu publika Ålosilo, kiun vi estas atestonta (vidu ĉi-suprajn konsilojn). + +3°) ke vi bone kontrolis kun la koncernata persono, ke li/Åi ja kreis sian Duniter-dokumenton pri konto-nuligo, kiu laÅbezone ebligos al li/Åi malaktivigi sian membro-statuson (kaze de konto-Åtelo, ID-ÅanÄo, konto erare kreita, ktp.). + +4a°) ke vi fizike renkontis la personon por certiÄi, ke ja lin/Åin vi bone konas, kaj ke ja li/Åi uzas tiun publikan Ålosilon. + +4b°) aÅ ke vi distance kontrolis la ligon persono / publik-Ålosilo kontaktante la personon per pluraj komunikiloj malsamaj, kiel paper-poÅto + sociaj retoj + forumo + retpoÅto + video-konferenco + telefono (rekoni la voĉon). Ĉar se oni povas fiuzi retadreson aÅ forum-konton, estos multe pli malfacile fiuzi kvar malsamajn komunikilojn, kaj imiti la aspekton (vidan) kaj plie la voĉon de la persono. + +La 4a°) tamen preferindas al la 4b°), dum la punktoj 1°) 2°) kaj 3°) estas antaŠĉio nepraj. + +**Resumitaj reguloj de la RdF:** + +Ĉiu membro havas rezervon da 100 eblaj atestaĵoj, kiujn li/Åi povas sendi nur po 1 ĉiun 5-an tagon. + +Valida 2 monatojn, atestaĵo por nova membro estas definitive aprobita nur se la atestito havas almenaÅ 4 aliajn atestaĵojn fine de tiuj 2 monatoj, alie la enir-procezo devos esti rekomencita. + +Por fariÄi nova membro de la RdF Äž1, necesas do akiri 5 atestaĵojn kaj troviÄi je distanco <= 5 paÅoj de 80% el la referencaj membroj de la RdF. + +Membro de la RdF Äž1 estas referenca membro, kiam li/Åi ricevis kaj sendis almenaÅ Y[N] atestaĵojn, kie N estas la nombro de membroj de la RdF kaj Y[N] = plafono N^(1/5). Ekzemploj: + +* por 1024 < N ≤ 3125 oni havas Y[N] = 5 +* por 7776 < N ≤ 16807 oni havas Y[N] = 7 +* por 59049 < N ≤ 100 000 oni havas Y[N] = 10 + +Ekde kiam la nova membro partoprenas en la RdF Äž1, ties atestaĵoj restas validaj 2 jarojn. + +Por resti membro necesas redoni regule sian konsenton per sia privata Ålosilo (ĉiun 12-an monaton) kaj certiÄi daÅre havi almenaÅ 5 atestaĵojn validajn post la 2 jaroj. + +Mono Äž1 +---------- + +Äž1 produktiÄas per Universala Dividendo (UD) por ĉiu homa estaĵo membro de la Reto de Fido Äž1, laÅ la formo: + +* po 1 UD por ĉiu persono ĉiutage + +**Kodo de la mono Äž1** + +La sumo en Äž1 de la UD samas ĉiutage Äis la venonta ekvinokso, kiam la UD estos tiam revalorigita laÅ la formulo (kun 1 tago = 86 400 sekundoj): + +* UDtago(sekvanta ekvinokso) = UDtago(ekvinokso) + c² (M/N)(ekvinokso) / (182,625 tagoj) + +kun kiel parametroj: + +* c = 4,88% / ekvinokso +* UD(0) = 10,00 Äž1 + +kaj kiel variabloj: + +* *M* la ĉioma mona maso je la ekvinokso +* *N* la nombro de membroj je la ekvinokso + +Programoj Äž1 kaj licenco Äž1 +-------------------------- + +La programoj Äž1, kiuj ebligas al la uzantoj mastrumi ties uzon de Äž1, devas transdoni tiun licencon kun la programo, kaj ankaÅ la aron de la teknikaj parametroj de la mono Äž1 kaj de la RdF Äž1, kiu estas enskribita en la bloko 0 de Äž1. Programo, kiu ne konformiÄus al tiuj devigoj de la licenco, ne estus kongrua kun Äž1. + +Por pli da precizigoj pri la teknikaj detaloj, eblas rekte konsulti la kodon de Duniter, kiu estas libera programo, kaj ankaÅ la datenojn de la blokĉeno Äž1 ekhavante ilin tra ekzemplero (aÅ nodo) Duniter Äž1. + +Pli da informoj ĉe la retejo de la teamo Duniter https://www.duniter.org diff --git a/assets/www/license/license_g1-es-ES.html b/assets/www/license/license_g1-es-ES.html new file mode 100644 index 0000000000000000000000000000000000000000..8799c965c650f63fee17b5bf2c0a3de2bf51b067 --- /dev/null +++ b/assets/www/license/license_g1-es-ES.html @@ -0,0 +1,60 @@ +<html><header><meta charset="utf-8"></header><body><h1 id="licencia-1-v0-2-8">Licencia Äž1 - v0.2.8</h1> +<p>:fecha: 2017-04-04 12:59 +:modificación: 2018-02-24 09:30</p> +<p><strong>Licencia de la moneda y compromiso de responsabilidad.</strong></p> +<p>Cualquier certificación de un nuevo miembro de Äž1 debe ir primero acompañada por la transmisión de esta licencia de moneda Äž1 la cual el certificador debe garantizar que ha sido estudiada, entendida y aceptada por la persona que será certificada.</p> +<p>Cualquier evento de encuentro relacionado con Äž1 debe ir acompañado de la transmisión de esta licencia, que puede leerse en voz alta y transmitirse por cualquier medio.</p> +<h2 id="red-de-confianza-1-rdc-1-">Red de confianza Äž1 (RdC Äž1)</h2> +<p><strong> Aviso de advertencia :</strong> Certificar no solo es asegurarte de que has conocido a la persona, es asegurar a la comunidad Äž1 que conoces a la persona lo suficientemente bien y que sabes cómo contactarla fácilmente, y ser capaz de identificar una cuenta duplicada realizada por una persona que has certificado, u otros tipos de problemas (desaparición ...), haciendo verificaciones cruzadas que revelan el problema en caso de que lo haya.</p> +<p><strong>Consejos muy recomendados</strong></p> +<p>Bien conocer a una persona significa que puedes comunicarte con ella por varios medios distintos (fÃsicos, electrónicos, otros ...) pero también que conoces a varias personas que la conocen bien y, por lo tanto, pueden comunicarse con ella igualmente. Especialmente si no conoces bien ninguno de sus otros certificadores, es una clara indicación de que no conoces bien a la persona; una certificación de este tipo provoca una alerta hacia toda la comunidad Äž1. En caso de conocimiento insuficiente, es importante NO certificar.</p> +<p>Nunca certifiques solo, sino que acompañado por al menos otro miembro de la RdC Äž1 para evitar cualquier mal manejo. En caso de error, advierte a otros miembros de la RdC Äž1 inmediatamente.</p> +<p>Antes de cualquier certificación, asegúrate de verificar si su cuenta (tanto si se esté validando como ya sea miembro) ha recibido ya una o más certificaciones. Si es necesario, solicite información para ponerte en contacto con estos otros certificadores para verificar juntos que conoces bien la persona en cuestión por la creación de la nueva cuenta, asà como la clave pública correspondiente.</p> +<p>Comprueba que la persona a punta de ser certificada domina el manejo su cuenta: una buena manera de comprobar esto es transferir unos Äž1 a la cuenta de destino, y luego pedir la vuelta a tu propia cuenta. Esto asegura el control eficaz, por el futuro certificado, de su clave privada.</p> +<p>Compruebe que tus contactos hayan estudiado y comprendido a fondo la licencia Äž1 actualizada.</p> +<p>Si te das cuenta de que un certificador real o potencial de la cuenta en cuestión no conoce a la persona interesada, avise inmediatamente a los expertos del tema dentro de tus contactos de la RdC Äž1, para que la RdC Äž1 verifique el procedimiento de validación.</p> +<p>Cuando eres miembro de la RdC Äž1 y estás a punto de certificar una nueva cuenta:</p> +<p><strong> Estás seguro: </strong></p> +<p>1 °) de conocer lo suficiente (no solo "de visu") la persona que declara administrar esta clave pública (nueva cuenta). Vea los consejos altamente recomendados más arriba para asegurarte de que conoces "bien".</p> +<p>2) Haber comprobado personalmente con ella que esta es la clave pública que está a punto de certificar (consulte las sugerencias anteriores).</p> +<p>3°) Haber verificado con la persona interesada que ha generado su documento de revocación de cuenta Duniter que le permitirá, si es necesario, desactivar su estado de miembro (caso de robo de cuenta, un cambio de identificación, una cuenta creada incorrectamente, etc.).</p> +<p>4a °) De haberte encontrado con la persona fÃsicamente para asegurarte de que la conoces bien y quién es ella que administra esta clave pública.</p> +<p>4b °) O verificar de forma remota el enlace entre la clave pública y la persona, contactando a esta persona por diferentes medios de comunicación, como correo en papel + red social + foro + correo electronico + video conferencia + teléfono (reconocer la voz). Porque si se puede piratear una cuenta de correo electrónico o una cuenta de foro, es mucho más difÃcil imaginar piratear cuatro medios de comunicación separados, e imitar la apariencia (video) y la voz de la persona además.</p> +<p>El 4a °) sin embargo, es preferible a 4b °), mientras que los puntos 1 °) 2 °) y 3 °) son previamente indispensables.</p> +<p><strong>Reglas abreviadas de la RdC :</strong></p> +<p>Cada miembro tiene un stock de 100 posibles certificaciones, que solo puede emitir a razón de 1 certificación cada 5 dÃas.</p> +<p>Válido por 2 meses, se adopta definitivamente una certificación para un nuevo miembro siesta persona tiene al menos otras 4 certificaciones al cabo de estos 2 meses, de lo contrario, el proceso de inscripción deberá reiniciarse.</p> +<p>Para convertirse en un nuevo miembro de la RdC Äž1 es necesario obtener 5 certificaciones y y estar a una distancia <= 5 pasos del 80% de los referentes de la RdC.</p> +<p>Un miembro de la RdC Äž1 es un miembro referente cuando ha recibido y emitido al menos Y [N] certificaciones donde N es el número de miembros RdC e Y [N] = techo N ^ (1/5). Ejemplos:</p> +<ul> +<li>Para 1024 < N ≤ 3125 tenemos Y[N] = 5</li> +<li>Para 7776 < N ≤ 16807 tenemos Y[N] = 7</li> +<li>para 59049 < N ≤ 100 000 tenemos Y[N] = 10</li> +</ul> +<p>Una vez que el nuevo miembro participa en la RdC Äž1, sus certificaciones seguirán siendo válidas durante 2 años.</p> +<p>Para seguir siendo miembro, debe renovar su acuerdo regularmente con su clave privada (cada 12 meses) y asegurarse de que siempre tenga al menos 5 certificaciones válidas más de allá de los 2 años.</p> +<h2 id="moneda-1">Moneda Äž1</h2> +<p>Äž1 se genera a través de un Dividendo Universal (DU) para cada ser humano en el Anillo de Confianza Äž1, que tiene la siguiente forma:</p> +<ul> +<li>1 DU por persona y por dÃa.</li> +</ul> +<p><strong>Codigo de la moneda Äž1</strong></p> +<p>La cantidad en Äž1 del DU es idéntica cada dÃa hasta el próximo equinoccio en el que se re-evaluará el DU según la fórmula (con 1 dÃa = 86,400 segundos): :</p> +<ul> +<li>DU dÃa (próximo equinoccio) = DU dÃa(equinoccio) + c² (M/N)(equinoccio) / (182,625 dÃas)</li> +</ul> +<p>Y como parámetros:</p> +<ul> +<li>c = 4,88% / equinoccio</li> +<li>DU(0) = 10,00 Äž1</li> +</ul> +<p>Y como variables :</p> +<ul> +<li><em>M</em> la oferta de dinero o masa monetaria total en el equinoccio</li> +<li><em>N</em> el número de miembros al dÃa del equinoccio</li> +</ul> +<h2 id="software-1-y-licencia-1">Software Äž1 y licencia Äž1</h2> +<p>El software Äž1 que permite a los usuarios administrar su uso de Äž1 debe transmitir esta licencia con el software y todos los parámetros técnicos de la moneda Äž1 y de la RdC Äž1 que se ingresan en el bloque 0 de Äž1. El software que no cumple con estas obligaciones de la licencia no es compatible con Äž1.</p> +<p>Para obtener más informaciones en los detalles técnicos, es posible consultar directamente el código de Duniter, que es un software libre asà como los datos de la blockchain Äž1, recuperándolos a través de una instancia de Duniter Äž1 (o nodo).</p> +<p>Más información en el sitio web del equipo de Duniter <a href="https://www.duniter.org">https://www.duniter.org</a></p> +</body></html> \ No newline at end of file diff --git a/assets/www/license/license_g1-es-ES.md b/assets/www/license/license_g1-es-ES.md new file mode 100644 index 0000000000000000000000000000000000000000..d97c51c01794bc426c815662e231ef323473cf31 --- /dev/null +++ b/assets/www/license/license_g1-es-ES.md @@ -0,0 +1,97 @@ +Licencia Äž1 - v0.2.8 +=================== + +:fecha: 2017-04-04 12:59 +:modificación: 2018-02-24 09:30 + +**Licencia de la moneda y compromiso de responsabilidad.** + +Cualquier certificación de un nuevo miembro de Äž1 debe ir primero acompañada por la transmisión de esta licencia de moneda Äž1 la cual el certificador debe garantizar que ha sido estudiada, entendida y aceptada por la persona que será certificada. + +Cualquier evento de encuentro relacionado con Äž1 debe ir acompañado de la transmisión de esta licencia, que puede leerse en voz alta y transmitirse por cualquier medio. + +Red de confianza Äž1 (RdC Äž1) +------------------------------ + +** Aviso de advertencia :** Certificar no solo es asegurarte de que has conocido a la persona, es asegurar a la comunidad Äž1 que conoces a la persona lo suficientemente bien y que sabes cómo contactarla fácilmente, y ser capaz de identificar una cuenta duplicada realizada por una persona que has certificado, u otros tipos de problemas (desaparición ...), haciendo verificaciones cruzadas que revelan el problema en caso de que lo haya. + +**Consejos muy recomendados** + +Bien conocer a una persona significa que puedes comunicarte con ella por varios medios distintos (fÃsicos, electrónicos, otros ...) pero también que conoces a varias personas que la conocen bien y, por lo tanto, pueden comunicarse con ella igualmente. Especialmente si no conoces bien ninguno de sus otros certificadores, es una clara indicación de que no conoces bien a la persona; una certificación de este tipo provoca una alerta hacia toda la comunidad Äž1. En caso de conocimiento insuficiente, es importante NO certificar. + +Nunca certifiques solo, sino que acompañado por al menos otro miembro de la RdC Äž1 para evitar cualquier mal manejo. En caso de error, advierte a otros miembros de la RdC Äž1 inmediatamente. + +Antes de cualquier certificación, asegúrate de verificar si su cuenta (tanto si se esté validando como ya sea miembro) ha recibido ya una o más certificaciones. Si es necesario, solicite información para ponerte en contacto con estos otros certificadores para verificar juntos que conoces bien la persona en cuestión por la creación de la nueva cuenta, asà como la clave pública correspondiente. + +Comprueba que la persona a punta de ser certificada domina el manejo su cuenta: una buena manera de comprobar esto es transferir unos Äž1 a la cuenta de destino, y luego pedir la vuelta a tu propia cuenta. Esto asegura el control eficaz, por el futuro certificado, de su clave privada. + +Compruebe que tus contactos hayan estudiado y comprendido a fondo la licencia Äž1 actualizada. + +Si te das cuenta de que un certificador real o potencial de la cuenta en cuestión no conoce a la persona interesada, avise inmediatamente a los expertos del tema dentro de tus contactos de la RdC Äž1, para que la RdC Äž1 verifique el procedimiento de validación. + +Cuando eres miembro de la RdC Äž1 y estás a punto de certificar una nueva cuenta: + + +** Estás seguro: ** + +1 °) de conocer lo suficiente (no solo "de visu") la persona que declara administrar esta clave pública (nueva cuenta). Vea los consejos altamente recomendados más arriba para asegurarte de que conoces "bien". + +2) Haber comprobado personalmente con ella que esta es la clave pública que está a punto de certificar (consulte las sugerencias anteriores). + +3°) Haber verificado con la persona interesada que ha generado su documento de revocación de cuenta Duniter que le permitirá, si es necesario, desactivar su estado de miembro (caso de robo de cuenta, un cambio de identificación, una cuenta creada incorrectamente, etc.). + +4a °) De haberte encontrado con la persona fÃsicamente para asegurarte de que la conoces bien y quién es ella que administra esta clave pública. + +4b °) O verificar de forma remota el enlace entre la clave pública y la persona, contactando a esta persona por diferentes medios de comunicación, como correo en papel + red social + foro + correo electronico + video conferencia + teléfono (reconocer la voz). Porque si se puede piratear una cuenta de correo electrónico o una cuenta de foro, es mucho más difÃcil imaginar piratear cuatro medios de comunicación separados, e imitar la apariencia (video) y la voz de la persona además. + +El 4a °) sin embargo, es preferible a 4b °), mientras que los puntos 1 °) 2 °) y 3 °) son previamente indispensables. + +**Reglas abreviadas de la RdC :** + +Cada miembro tiene un stock de 100 posibles certificaciones, que solo puede emitir a razón de 1 certificación cada 5 dÃas. + +Válido por 2 meses, se adopta definitivamente una certificación para un nuevo miembro siesta persona tiene al menos otras 4 certificaciones al cabo de estos 2 meses, de lo contrario, el proceso de inscripción deberá reiniciarse. + +Para convertirse en un nuevo miembro de la RdC Äž1 es necesario obtener 5 certificaciones y y estar a una distancia <= 5 pasos del 80% de los referentes de la RdC. + +Un miembro de la RdC Äž1 es un miembro referente cuando ha recibido y emitido al menos Y [N] certificaciones donde N es el número de miembros RdC e Y [N] = techo N ^ (1/5). Ejemplos: + +* Para 1024 < N ≤ 3125 tenemos Y[N] = 5 +* Para 7776 < N ≤ 16807 tenemos Y[N] = 7 +* para 59049 < N ≤ 100 000 tenemos Y[N] = 10 + +Una vez que el nuevo miembro participa en la RdC Äž1, sus certificaciones seguirán siendo válidas durante 2 años. + +Para seguir siendo miembro, debe renovar su acuerdo regularmente con su clave privada (cada 12 meses) y asegurarse de que siempre tenga al menos 5 certificaciones válidas más de allá de los 2 años. + +Moneda Äž1 +---------- + +Äž1 se genera a través de un Dividendo Universal (DU) para cada ser humano en el Anillo de Confianza Äž1, que tiene la siguiente forma: + +* 1 DU por persona y por dÃa. + +**Codigo de la moneda Äž1** + +La cantidad en Äž1 del DU es idéntica cada dÃa hasta el próximo equinoccio en el que se re-evaluará el DU según la fórmula (con 1 dÃa = 86,400 segundos): : + +* DU dÃa (próximo equinoccio) = DU dÃa(equinoccio) + c² (M/N)(equinoccio) / (182,625 dÃas) + +Y como parámetros: + +* c = 4,88% / equinoccio +* DU(0) = 10,00 Äž1 + +Y como variables : + +* *M* la oferta de dinero o masa monetaria total en el equinoccio +* *N* el número de miembros al dÃa del equinoccio + +Software Äž1 y licencia Äž1 +-------------------------- + +El software Äž1 que permite a los usuarios administrar su uso de Äž1 debe transmitir esta licencia con el software y todos los parámetros técnicos de la moneda Äž1 y de la RdC Äž1 que se ingresan en el bloque 0 de Äž1. El software que no cumple con estas obligaciones de la licencia no es compatible con Äž1. + +Para obtener más informaciones en los detalles técnicos, es posible consultar directamente el código de Duniter, que es un software libre asà como los datos de la blockchain Äž1, recuperándolos a través de una instancia de Duniter Äž1 (o nodo). + +Más información en el sitio web del equipo de Duniter https://www.duniter.org \ No newline at end of file diff --git a/assets/www/license/license_g1-es-ES.txt b/assets/www/license/license_g1-es-ES.txt new file mode 100644 index 0000000000000000000000000000000000000000..2409f3323f632caaccca397d23b8d09b3c59c0a2 --- /dev/null +++ b/assets/www/license/license_g1-es-ES.txt @@ -0,0 +1,97 @@ +Licencia Äž1 - v0.2.8 +=================== + +:fecha: 2017-04-04 12:59 +:modificación: 2018-02-24 09:30 + +**Licencia de la moneda y compromiso de responsabilidad.** + +Cualquier certificación de un nuevo miembro de Äž1 debe ir primero acompañada por la transmisión de esta licencia de moneda Äž1 la cual el certificador debe garantizar que ha sido estudiada, entendida y aceptada por la persona que será certificada. + +Cualquier evento de encuentro relacionado con Äž1 debe ir acompañado de la transmisión de esta licencia, que puede leerse en voz alta y transmitirse por cualquier medio. + +Red de confianza Äž1 (RdC Äž1) +------------------------------ + +** Aviso de advertencia :** Certificar no solo es asegurarte de que has conocido a la persona, es asegurar a la comunidad Äž1 que conoces a la persona lo suficientemente bien y que sabes cómo contactarla fácilmente, y ser capaz de identificar una cuenta duplicada realizada por una persona que has certificado, u otros tipos de problemas (desaparición ...), haciendo verificaciones cruzadas que revelan el problema en caso de que lo haya. + +**Consejos muy recomendados** + +Bien conocer a una persona significa que puedes comunicarte con ella por varios medios distintos (fÃsicos, electrónicos, otros ...) pero también que conoces a varias personas que la conocen bien y, por lo tanto, pueden comunicarse con ella igualmente. Especialmente si no conoces bien ninguno de sus otros certificadores, es una clara indicación de que no conoces bien a la persona; una certificación de este tipo provoca una alerta hacia toda la comunidad Äž1. En caso de conocimiento insuficiente, es importante NO certificar. + +Nunca certifiques solo, sino que acompañado por al menos otro miembro de la RdC Äž1 para evitar cualquier mal manejo. En caso de error, advierte a otros miembros de la RdC Äž1 inmediatamente. + +Antes de cualquier certificación, asegúrate de verificar si su cuenta (tanto si se esté validando como ya sea miembro) ha recibido ya una o más certificaciones. Si es necesario, solicite información para ponerte en contacto con estos otros certificadores para verificar juntos que conoces bien la persona en cuestión por la creación de la nueva cuenta, asà como la clave pública correspondiente. + +Comprueba que la persona a punta de ser certificada domina el manejo su cuenta: una buena manera de comprobar esto es transferir unos Äž1 a la cuenta de destino, y luego pedir la vuelta a tu propia cuenta. Esto asegura el control eficaz, por el futuro certificado, de su clave privada. + +Compruebe que tus contactos hayan estudiado y comprendido a fondo la licencia Äž1 actualizada. + +Si te das cuenta de que un certificador real o potencial de la cuenta en cuestión no conoce a la persona interesada, avise inmediatamente a los expertos del tema dentro de tus contactos de la RdC Äž1, para que la RdC Äž1 verifique el procedimiento de validación. + +Cuando eres miembro de la RdC Äž1 y estás a punto de certificar una nueva cuenta: + + +** Estás seguro: ** + +1 °) de conocer lo suficiente (no solo "de visu") la persona que declara administrar esta clave pública (nueva cuenta). Vea los consejos altamente recomendados más arriba para asegurarte de que conoces "bien". + +2) Haber comprobado personalmente con ella que esta es la clave pública que está a punto de certificar (consulte las sugerencias anteriores). + +3°) Haber verificado con la persona interesada que ha generado su documento de revocación de cuenta Duniter que le permitirá, si es necesario, desactivar su estado de miembro (caso de robo de cuenta, un cambio de identificación, una cuenta creada incorrectamente, etc.). + +4a °) De haberte encontrado con la persona fÃsicamente para asegurarte de que la conoces bien y quién es ella que administra esta clave pública. + +4b °) O verificar de forma remota el enlace entre la clave pública y la persona, contactando a esta persona por diferentes medios de comunicación, como correo en papel + red social + foro + correo electronico + video conferencia + teléfono (reconocer la voz). Porque si se puede piratear una cuenta de correo electrónico o una cuenta de foro, es mucho más difÃcil imaginar piratear cuatro medios de comunicación separados, e imitar la apariencia (video) y la voz de la persona además. + +El 4a °) sin embargo, es preferible a 4b °), mientras que los puntos 1 °) 2 °) y 3 °) son previamente indispensables. + +**Reglas abreviadas de la RdC :** + +Cada miembro tiene un stock de 100 posibles certificaciones, que solo puede emitir a razón de 1 certificación cada 5 dÃas. + +Válido por 2 meses, se adopta definitivamente una certificación para un nuevo miembro siesta persona tiene al menos otras 4 certificaciones al cabo de estos 2 meses, de lo contrario, el proceso de inscripción deberá reiniciarse. + +Para convertirse en un nuevo miembro de la RdC Äž1 es necesario obtener 5 certificaciones y y estar a una distancia <= 5 pasos del 80% de los referentes de la RdC. + +Un miembro de la RdC Äž1 es un miembro referente cuando ha recibido y emitido al menos Y [N] certificaciones donde N es el número de miembros RdC e Y [N] = techo N ^ (1/5). Ejemplos: + +* Para 1024 < N ≤ 3125 tenemos Y[N] = 5 +* Para 7776 < N ≤ 16807 tenemos Y[N] = 7 +* para 59049 < N ≤ 100 000 tenemos Y[N] = 10 + +Una vez que el nuevo miembro participa en la RdC Äž1, sus certificaciones seguirán siendo válidas durante 2 años. + +Para seguir siendo miembro, debe renovar su acuerdo regularmente con su clave privada (cada 12 meses) y asegurarse de que siempre tenga al menos 5 certificaciones válidas más de allá de los 2 años. + +Moneda Äž1 +---------- + +Äž1 se genera a través de un Dividendo Universal (DU) para cada ser humano en el Anillo de Confianza Äž1, que tiene la siguiente forma: + +* 1 DU por persona y por dÃa. + +**Codigo de la moneda Äž1** + +La cantidad en Äž1 del DU es idéntica cada dÃa hasta el próximo equinoccio en el que se re-evaluará el DU según la fórmula (con 1 dÃa = 86,400 segundos): : + +* DU dÃa (próximo equinoccio) = DU dÃa(equinoccio) + c² (M/N)(equinoccio) / (182,625 dÃas) + +Y como parámetros: + +* c = 4,88% / equinoccio +* DU(0) = 10,00 Äž1 + +Y como variables : + +* *M* la oferta de dinero o masa monetaria total en el equinoccio +* *N* el número de miembros al dÃa del equinoccio + +Software Äž1 y licencia Äž1 +-------------------------- + +El software Äž1 que permite a los usuarios administrar su uso de Äž1 debe transmitir esta licencia con el software y todos los parámetros técnicos de la moneda Äž1 y de la RdC Äž1 que se ingresan en el bloque 0 de Äž1. El software que no cumple con estas obligaciones de la licencia no es compatible con Äž1. + +Para obtener más informaciones en los detalles técnicos, es posible consultar directamente el código de Duniter, que es un software libre asà como los datos de la blockchain Äž1, recuperándolos a través de una instancia de Duniter Äž1 (o nodo). + +Más información en el sitio web del equipo de Duniter https://www.duniter.org \ No newline at end of file diff --git a/assets/www/license/license_g1-fr-FR.html b/assets/www/license/license_g1-fr-FR.html index 86e8ea0930c4109512205d65408645f51df8f9ea..8d00899c658e531f2b014b5ce9df14e8d19d6aea 100644 --- a/assets/www/license/license_g1-fr-FR.html +++ b/assets/www/license/license_g1-fr-FR.html @@ -1,30 +1,30 @@ -<html><header><meta charset="utf-8"></header><body><h1 id="licence-1-v0-2-8">Licence Äž1 - v0.2.8</h1> +<html><header><meta charset="utf-8"></header><body><h1 id="licence-1-v0-2-9">Licence Äž1 - v0.2.9</h1> <p>:date: 2017-04-04 12:59 -:modified: 2018-02-24 09:30</p> +:modified: 2019-07-14 12:00</p> <p><strong>Licence de la monnaie et engagement de responsabilité.</strong></p> <p>Toute opération de certification d'un nouveau membre de Äž1 doit préalablement s'accompagner de la transmission de cette licence de la monnaie Äž1 dont le certificateur doit s'assurer qu'elle a été étudiée, comprise et acceptée par la personne qui sera certifiée.</p> <p>Tout événement de rencontre concernant Äž1 devrait s'accompagner de la transmission de cette licence, qui peut être lue à haute voix, et transmise par tout moyen.</p> <h2 id="toile-de-confiance-1-tdc-1-">Toile de confiance Äž1 (TdC Äž1)</h2> <p><strong>Avertissement :</strong> Certifier n'est pas uniquement s'assurer que vous avez rencontré la personne, c'est assurer à la communauté Äž1 que vous connaissez suffisamment bien la personne certifiée et que vous saurez ainsi la contacter facilement, et être en mesure de repérer un double compte effectué par une personne certifiée par vous-même, ou d'autres types de problèmes (disparition...), en effectuant des recoupements qui permettront de révéler le problème le cas échéant.</p> <p><strong>Conseils fortement recommandés</strong></p> -<p>Bien connaître une personne suppose que vous êtes en mesure de la contacter par plusieurs moyens différents (physique, électronique, autre...) mais aussi que vous connaissez aussi plusieurs personnes qui la connaissent tout aussi bien et sont donc aussi en mesure de la contacter de même. Notamment si vous ne connaissez pas bien aucun de ses autres certifieurs c'est une indication forte que vous ne connaissez pas bien la personne et une certification de ce type déclenche une alerte vers toute la communauté Äž1. En cas de connaissance insuffisante il convient de ne surtout pas certifier.</p> +<p>Bien connaître une personne suppose que vous êtes en mesure de la contacter par plusieurs moyens différents (physique, électronique, autre...) mais aussi que vous connaissez aussi plusieurs personnes qui la connaissent tout aussi bien et sont donc aussi en mesure de la contacter de même. Notamment si vous ne connaissez pas bien aucun de ses autres certificateurs c'est une indication forte que vous ne connaissez pas bien la personne et une certification de ce type déclenche une alerte vers toute la communauté Äž1. En cas de connaissance insuffisante il convient de ne surtout pas certifier.</p> <p>Ne certifiez jamais seul, mais accompagné d'au moins un autre membre de la TdC Äž1 afin d'éviter toute erreur de manipulation. En cas d'erreur, prévenez immédiatement d'autres membres de la TdC Äž1.</p> -<p>Avant toute certification, assurez vous de vérifier si son compte (qu'il soit en cours de validation ou déjà membre) a déjà reçu une ou plusieurs certifications. Le cas échéant demandez des informations pour entrer en contact avec ces autres certifieurs afin de vérifier ensemble que vous connaissez bien la personne concernée par la création du nouveau compte, ainsi que la clé publique correspondante.</p> +<p>Avant toute certification, assurez vous de vérifier si son compte (qu'il soit en cours de validation ou déjà membre) a déjà reçu une ou plusieurs certifications. Le cas échéant demandez des informations pour entrer en contact avec ces autres certificateurs afin de vérifier ensemble que vous connaissez bien la personne concernée par la création du nouveau compte, ainsi que la clé publique correspondante.</p> <p>Vérifiez que le futur certifié maîtrise bien son compte : un bon moyen de vérifier cela est de transférer quelques Äž1 vers le compte cible, et de demander ensuite un renvoi vers votre propre compte, cela assure de la bonne maîtrise par le futur certifié de sa clé privée.</p> <p>Vérifiez que vos contacts ont bien étudié et compris la licence Äž1 à jour.</p> -<p>Si vous vous rendez compte qu'un certifieur effectif ou potentiel du compte concerné ne connaît pas la personne concernée, alertez immédiatement des experts du sujet au sein de vos connaissance de la TdC Äž1, afin que la procédure de validation soit vérifiée par la TdC Äž1.</p> +<p>Si vous vous rendez compte qu'un certificateur effectif ou potentiel du compte concerné ne connaît pas la personne concernée, alertez immédiatement des experts du sujet au sein de vos connaissance de la TdC Äž1, afin que la procédure de validation soit vérifiée par la TdC Äž1.</p> <p>Lorsque vous êtes membre de la TdC Äž1 et que vous vous apprêtez à certifier un nouveau compte :</p> <p><strong>Vous êtes vous assuré :</strong></p> <p>1°) De suffisamment bien connaître (pas seulement de la connaître "de visu") la personne qui déclare gérer cette clé publique (nouveau compte). Voir les conseils fortement recommandés ci-dessus pour s'assurer de "bien connaître".</p> <p>2°) D'avoir personnellement vérifié avec elle qu'il s'agit bien de cette clé publique que vous vous apprêtez à certifier (voir conseils ci-dessus).</p> <p>3°) D'avoir bien vérifié avec la personne concernée qu'elle a bien généré son document Duniter de révocation de compte qui lui permettra le cas échéant de pouvoir désactiver son statut de membre (cas d'un vol de compte, d'un changement de ID, d'un compte créé à tort etc.).</p> <p>4a°) De rencontrer la personne physiquement pour vous assurer que c'est bien elle que vous connaissez bien et qui gère cette clé publique.</p> -<p>4b°) Ou bien de vérifer à distance le lien personne / clé publique en contactant la personne par plusieurs moyens de communication différents, comme courrier papier + réseau social + forum + mail + vidéo conférence + téléphone (reconnaître la voix). Car si l'on peut pirater un compte mail ou un compte forum, il sera bien plus difficile d'imaginer pirater quatre moyens de communication distincts, et imiter l'apparence (vidéo) ainsi que la voix de la personne en plus.</p> +<p>4b°) Ou bien de vérifier à distance le lien personne / clé publique en contactant la personne par plusieurs moyens de communication différents, comme courrier papier + réseau social + forum + mail + vidéo conférence + téléphone (reconnaître la voix). Car si l'on peut pirater un compte mail ou un compte forum, il sera bien plus difficile d'imaginer pirater quatre moyens de communication distincts, et imiter l'apparence (vidéo) ainsi que la voix de la personne en plus.</p> <p>Le 4a°) restant toutefois préférable au 4b°), tandis que les points 1°) 2°) et 3°) sont préalablement indispensables.</p> <p><strong>Règles abrégées de la TdC :</strong></p> <p>Chaque membre a un stock de 100 certifications possibles, qu'il ne peut émettre qu'au rythme de 1 certification / 5 jours.</p> <p>Valable 2 mois, une certification pour un nouveau membre n'est définitivement adoptée que si le certifié possède au moins 4 autres certifications au bout de ces 2 mois, sinon le processus d'entrée devra être relancé.</p> -<p>Pour devenir un nouveau membre de la TdC Äž1 il faut donc obtenir 5 certifications et ne pas se trouver à une distance < 5 de 80% des membres référents de la TdC.</p> +<p>Pour devenir un nouveau membre de la TdC Äž1 il faut donc obtenir 5 certifications et se trouver à une distance <= 5 pas de 80% des membres référents de la TdC.</p> <p>Un membre de la TdC Äž1 est membre référent lorsqu'il a reçu et émis au moins Y[N] certifications où N est le nombre de membres de la TdC et Y[N] = plafond N^(1/5). Exemples :</p> <ul> <li>Pour 1024 < N ≤ 3125 on a Y[N] = 5</li> @@ -54,7 +54,7 @@ <li><em>N</em> le nombre de membres à l'équinoxe</li> </ul> <h2 id="logiciels-1-et-licence-1">Logiciels Äž1 et licence Äž1</h2> -<p>Les logiciels Äž1 permettant aux utilisateurs de gérer leur utilisation de Äž1 doivent transmettre cette licence avec le logiciel ainsi que l'ensemble des paramètres techniques de la monnaie Äž1 et de la TdC Äž1 qui sont inscrits dans le bloc 0 de Äž1. Un logiciel qui ne remplirait pas ces obigations de la licence n'est pas compatible Äž1.</p> -<p>Pour plus de précisions dans les détails techniques il est possible de consulter directement le code de Duniter qui est un logiciel libre ansi que les données de la blockchain Äž1 en la récupérant via une instance (ou noeud) Duniter Äž1.</p> +<p>Les logiciels Äž1 permettant aux utilisateurs de gérer leur utilisation de Äž1 doivent transmettre cette licence avec le logiciel ainsi que l'ensemble des paramètres techniques de la monnaie Äž1 et de la TdC Äž1 qui sont inscrits dans le bloc 0 de Äž1. Un logiciel qui ne remplirait pas ces obligations de la licence n'est pas compatible Äž1.</p> +<p>Pour plus de précisions dans les détails techniques il est possible de consulter directement le code de Duniter qui est un logiciel libre ainsi que les données de la blockchain Äž1 en la récupérant via une instance (ou nÅ“ud) Duniter Äž1.</p> <p>Plus d'informations sur le site de l'équipe Duniter <a href="https://www.duniter.org">https://www.duniter.org</a></p> </body></html> \ No newline at end of file diff --git a/assets/www/license/license_g1-fr-FR.md b/assets/www/license/license_g1-fr-FR.md index 35a620ca15ef6a0b0537fea97789b1345cf372eb..808165183d1645ba5d8a8a8868b5ebac41ad5447 100644 --- a/assets/www/license/license_g1-fr-FR.md +++ b/assets/www/license/license_g1-fr-FR.md @@ -1,8 +1,8 @@ -Licence Äž1 - v0.2.8 +Licence Äž1 - v0.2.9 =================== :date: 2017-04-04 12:59 -:modified: 2018-02-24 09:30 +:modified: 2019-07-14 12:00 **Licence de la monnaie et engagement de responsabilité.** @@ -17,17 +17,17 @@ Toile de confiance Äž1 (TdC Äž1) **Conseils fortement recommandés** -Bien connaître une personne suppose que vous êtes en mesure de la contacter par plusieurs moyens différents (physique, électronique, autre...) mais aussi que vous connaissez aussi plusieurs personnes qui la connaissent tout aussi bien et sont donc aussi en mesure de la contacter de même. Notamment si vous ne connaissez pas bien aucun de ses autres certifieurs c'est une indication forte que vous ne connaissez pas bien la personne et une certification de ce type déclenche une alerte vers toute la communauté Äž1. En cas de connaissance insuffisante il convient de ne surtout pas certifier. +Bien connaître une personne suppose que vous êtes en mesure de la contacter par plusieurs moyens différents (physique, électronique, autre...) mais aussi que vous connaissez aussi plusieurs personnes qui la connaissent tout aussi bien et sont donc aussi en mesure de la contacter de même. Notamment si vous ne connaissez pas bien aucun de ses autres certificateurs c'est une indication forte que vous ne connaissez pas bien la personne et une certification de ce type déclenche une alerte vers toute la communauté Äž1. En cas de connaissance insuffisante il convient de ne surtout pas certifier. Ne certifiez jamais seul, mais accompagné d'au moins un autre membre de la TdC Äž1 afin d'éviter toute erreur de manipulation. En cas d'erreur, prévenez immédiatement d'autres membres de la TdC Äž1. -Avant toute certification, assurez vous de vérifier si son compte (qu'il soit en cours de validation ou déjà membre) a déjà reçu une ou plusieurs certifications. Le cas échéant demandez des informations pour entrer en contact avec ces autres certifieurs afin de vérifier ensemble que vous connaissez bien la personne concernée par la création du nouveau compte, ainsi que la clé publique correspondante. +Avant toute certification, assurez vous de vérifier si son compte (qu'il soit en cours de validation ou déjà membre) a déjà reçu une ou plusieurs certifications. Le cas échéant demandez des informations pour entrer en contact avec ces autres certificateurs afin de vérifier ensemble que vous connaissez bien la personne concernée par la création du nouveau compte, ainsi que la clé publique correspondante. Vérifiez que le futur certifié maîtrise bien son compte : un bon moyen de vérifier cela est de transférer quelques Äž1 vers le compte cible, et de demander ensuite un renvoi vers votre propre compte, cela assure de la bonne maîtrise par le futur certifié de sa clé privée. Vérifiez que vos contacts ont bien étudié et compris la licence Äž1 à jour. -Si vous vous rendez compte qu'un certifieur effectif ou potentiel du compte concerné ne connaît pas la personne concernée, alertez immédiatement des experts du sujet au sein de vos connaissance de la TdC Äž1, afin que la procédure de validation soit vérifiée par la TdC Äž1. +Si vous vous rendez compte qu'un certificateur effectif ou potentiel du compte concerné ne connaît pas la personne concernée, alertez immédiatement des experts du sujet au sein de vos connaissance de la TdC Äž1, afin que la procédure de validation soit vérifiée par la TdC Äž1. Lorsque vous êtes membre de la TdC Äž1 et que vous vous apprêtez à certifier un nouveau compte : @@ -42,7 +42,7 @@ Lorsque vous êtes membre de la TdC Äž1 et que vous vous apprêtez à certifier 4a°) De rencontrer la personne physiquement pour vous assurer que c'est bien elle que vous connaissez bien et qui gère cette clé publique. -4b°) Ou bien de vérifer à distance le lien personne / clé publique en contactant la personne par plusieurs moyens de communication différents, comme courrier papier + réseau social + forum + mail + vidéo conférence + téléphone (reconnaître la voix). Car si l'on peut pirater un compte mail ou un compte forum, il sera bien plus difficile d'imaginer pirater quatre moyens de communication distincts, et imiter l'apparence (vidéo) ainsi que la voix de la personne en plus. +4b°) Ou bien de vérifier à distance le lien personne / clé publique en contactant la personne par plusieurs moyens de communication différents, comme courrier papier + réseau social + forum + mail + vidéo conférence + téléphone (reconnaître la voix). Car si l'on peut pirater un compte mail ou un compte forum, il sera bien plus difficile d'imaginer pirater quatre moyens de communication distincts, et imiter l'apparence (vidéo) ainsi que la voix de la personne en plus. Le 4a°) restant toutefois préférable au 4b°), tandis que les points 1°) 2°) et 3°) sont préalablement indispensables. @@ -52,7 +52,7 @@ Chaque membre a un stock de 100 certifications possibles, qu'il ne peut émettre Valable 2 mois, une certification pour un nouveau membre n'est définitivement adoptée que si le certifié possède au moins 4 autres certifications au bout de ces 2 mois, sinon le processus d'entrée devra être relancé. -Pour devenir un nouveau membre de la TdC Äž1 il faut donc obtenir 5 certifications et ne pas se trouver à une distance < 5 de 80% des membres référents de la TdC. +Pour devenir un nouveau membre de la TdC Äž1 il faut donc obtenir 5 certifications et se trouver à une distance <= 5 pas de 80% des membres référents de la TdC. Un membre de la TdC Äž1 est membre référent lorsqu'il a reçu et émis au moins Y[N] certifications où N est le nombre de membres de la TdC et Y[N] = plafond N^(1/5). Exemples : @@ -90,8 +90,8 @@ Et comme variables : Logiciels Äž1 et licence Äž1 -------------------------- -Les logiciels Äž1 permettant aux utilisateurs de gérer leur utilisation de Äž1 doivent transmettre cette licence avec le logiciel ainsi que l'ensemble des paramètres techniques de la monnaie Äž1 et de la TdC Äž1 qui sont inscrits dans le bloc 0 de Äž1. Un logiciel qui ne remplirait pas ces obigations de la licence n'est pas compatible Äž1. +Les logiciels Äž1 permettant aux utilisateurs de gérer leur utilisation de Äž1 doivent transmettre cette licence avec le logiciel ainsi que l'ensemble des paramètres techniques de la monnaie Äž1 et de la TdC Äž1 qui sont inscrits dans le bloc 0 de Äž1. Un logiciel qui ne remplirait pas ces obligations de la licence n'est pas compatible Äž1. -Pour plus de précisions dans les détails techniques il est possible de consulter directement le code de Duniter qui est un logiciel libre ansi que les données de la blockchain Äž1 en la récupérant via une instance (ou noeud) Duniter Äž1. +Pour plus de précisions dans les détails techniques il est possible de consulter directement le code de Duniter qui est un logiciel libre ainsi que les données de la blockchain Äž1 en la récupérant via une instance (ou nÅ“ud) Duniter Äž1. -Plus d'informations sur le site de l'équipe Duniter https://www.duniter.org +Plus d'informations sur le site de l'équipe Duniter https://www.duniter.org \ No newline at end of file diff --git a/assets/www/license/license_g1-fr-FR.txt b/assets/www/license/license_g1-fr-FR.txt index 35a620ca15ef6a0b0537fea97789b1345cf372eb..808165183d1645ba5d8a8a8868b5ebac41ad5447 100644 --- a/assets/www/license/license_g1-fr-FR.txt +++ b/assets/www/license/license_g1-fr-FR.txt @@ -1,8 +1,8 @@ -Licence Äž1 - v0.2.8 +Licence Äž1 - v0.2.9 =================== :date: 2017-04-04 12:59 -:modified: 2018-02-24 09:30 +:modified: 2019-07-14 12:00 **Licence de la monnaie et engagement de responsabilité.** @@ -17,17 +17,17 @@ Toile de confiance Äž1 (TdC Äž1) **Conseils fortement recommandés** -Bien connaître une personne suppose que vous êtes en mesure de la contacter par plusieurs moyens différents (physique, électronique, autre...) mais aussi que vous connaissez aussi plusieurs personnes qui la connaissent tout aussi bien et sont donc aussi en mesure de la contacter de même. Notamment si vous ne connaissez pas bien aucun de ses autres certifieurs c'est une indication forte que vous ne connaissez pas bien la personne et une certification de ce type déclenche une alerte vers toute la communauté Äž1. En cas de connaissance insuffisante il convient de ne surtout pas certifier. +Bien connaître une personne suppose que vous êtes en mesure de la contacter par plusieurs moyens différents (physique, électronique, autre...) mais aussi que vous connaissez aussi plusieurs personnes qui la connaissent tout aussi bien et sont donc aussi en mesure de la contacter de même. Notamment si vous ne connaissez pas bien aucun de ses autres certificateurs c'est une indication forte que vous ne connaissez pas bien la personne et une certification de ce type déclenche une alerte vers toute la communauté Äž1. En cas de connaissance insuffisante il convient de ne surtout pas certifier. Ne certifiez jamais seul, mais accompagné d'au moins un autre membre de la TdC Äž1 afin d'éviter toute erreur de manipulation. En cas d'erreur, prévenez immédiatement d'autres membres de la TdC Äž1. -Avant toute certification, assurez vous de vérifier si son compte (qu'il soit en cours de validation ou déjà membre) a déjà reçu une ou plusieurs certifications. Le cas échéant demandez des informations pour entrer en contact avec ces autres certifieurs afin de vérifier ensemble que vous connaissez bien la personne concernée par la création du nouveau compte, ainsi que la clé publique correspondante. +Avant toute certification, assurez vous de vérifier si son compte (qu'il soit en cours de validation ou déjà membre) a déjà reçu une ou plusieurs certifications. Le cas échéant demandez des informations pour entrer en contact avec ces autres certificateurs afin de vérifier ensemble que vous connaissez bien la personne concernée par la création du nouveau compte, ainsi que la clé publique correspondante. Vérifiez que le futur certifié maîtrise bien son compte : un bon moyen de vérifier cela est de transférer quelques Äž1 vers le compte cible, et de demander ensuite un renvoi vers votre propre compte, cela assure de la bonne maîtrise par le futur certifié de sa clé privée. Vérifiez que vos contacts ont bien étudié et compris la licence Äž1 à jour. -Si vous vous rendez compte qu'un certifieur effectif ou potentiel du compte concerné ne connaît pas la personne concernée, alertez immédiatement des experts du sujet au sein de vos connaissance de la TdC Äž1, afin que la procédure de validation soit vérifiée par la TdC Äž1. +Si vous vous rendez compte qu'un certificateur effectif ou potentiel du compte concerné ne connaît pas la personne concernée, alertez immédiatement des experts du sujet au sein de vos connaissance de la TdC Äž1, afin que la procédure de validation soit vérifiée par la TdC Äž1. Lorsque vous êtes membre de la TdC Äž1 et que vous vous apprêtez à certifier un nouveau compte : @@ -42,7 +42,7 @@ Lorsque vous êtes membre de la TdC Äž1 et que vous vous apprêtez à certifier 4a°) De rencontrer la personne physiquement pour vous assurer que c'est bien elle que vous connaissez bien et qui gère cette clé publique. -4b°) Ou bien de vérifer à distance le lien personne / clé publique en contactant la personne par plusieurs moyens de communication différents, comme courrier papier + réseau social + forum + mail + vidéo conférence + téléphone (reconnaître la voix). Car si l'on peut pirater un compte mail ou un compte forum, il sera bien plus difficile d'imaginer pirater quatre moyens de communication distincts, et imiter l'apparence (vidéo) ainsi que la voix de la personne en plus. +4b°) Ou bien de vérifier à distance le lien personne / clé publique en contactant la personne par plusieurs moyens de communication différents, comme courrier papier + réseau social + forum + mail + vidéo conférence + téléphone (reconnaître la voix). Car si l'on peut pirater un compte mail ou un compte forum, il sera bien plus difficile d'imaginer pirater quatre moyens de communication distincts, et imiter l'apparence (vidéo) ainsi que la voix de la personne en plus. Le 4a°) restant toutefois préférable au 4b°), tandis que les points 1°) 2°) et 3°) sont préalablement indispensables. @@ -52,7 +52,7 @@ Chaque membre a un stock de 100 certifications possibles, qu'il ne peut émettre Valable 2 mois, une certification pour un nouveau membre n'est définitivement adoptée que si le certifié possède au moins 4 autres certifications au bout de ces 2 mois, sinon le processus d'entrée devra être relancé. -Pour devenir un nouveau membre de la TdC Äž1 il faut donc obtenir 5 certifications et ne pas se trouver à une distance < 5 de 80% des membres référents de la TdC. +Pour devenir un nouveau membre de la TdC Äž1 il faut donc obtenir 5 certifications et se trouver à une distance <= 5 pas de 80% des membres référents de la TdC. Un membre de la TdC Äž1 est membre référent lorsqu'il a reçu et émis au moins Y[N] certifications où N est le nombre de membres de la TdC et Y[N] = plafond N^(1/5). Exemples : @@ -90,8 +90,8 @@ Et comme variables : Logiciels Äž1 et licence Äž1 -------------------------- -Les logiciels Äž1 permettant aux utilisateurs de gérer leur utilisation de Äž1 doivent transmettre cette licence avec le logiciel ainsi que l'ensemble des paramètres techniques de la monnaie Äž1 et de la TdC Äž1 qui sont inscrits dans le bloc 0 de Äž1. Un logiciel qui ne remplirait pas ces obigations de la licence n'est pas compatible Äž1. +Les logiciels Äž1 permettant aux utilisateurs de gérer leur utilisation de Äž1 doivent transmettre cette licence avec le logiciel ainsi que l'ensemble des paramètres techniques de la monnaie Äž1 et de la TdC Äž1 qui sont inscrits dans le bloc 0 de Äž1. Un logiciel qui ne remplirait pas ces obligations de la licence n'est pas compatible Äž1. -Pour plus de précisions dans les détails techniques il est possible de consulter directement le code de Duniter qui est un logiciel libre ansi que les données de la blockchain Äž1 en la récupérant via une instance (ou noeud) Duniter Äž1. +Pour plus de précisions dans les détails techniques il est possible de consulter directement le code de Duniter qui est un logiciel libre ainsi que les données de la blockchain Äž1 en la récupérant via une instance (ou nÅ“ud) Duniter Äž1. -Plus d'informations sur le site de l'équipe Duniter https://www.duniter.org +Plus d'informations sur le site de l'équipe Duniter https://www.duniter.org \ No newline at end of file diff --git a/assets/www/manifest.json b/assets/www/manifest.json index 22988374bc1d1f535703e751ed85553e71617c6f..be4ab73a24187b5f0bff9909831077a5b17387d2 100644 --- a/assets/www/manifest.json +++ b/assets/www/manifest.json @@ -2,7 +2,7 @@ "short_name": "Cesium", "name": "Cesium", "manifest_version": 1, - "version": "1.0.6", + "version": "1.4.15", "default_locale": "fr", "description": "Manage your Duniter Wallet on a libre currency, like Äž1", "icons": [ @@ -22,7 +22,8 @@ "type": "image/svg" } ], + "background_color": "#1a237e", + "theme_color": "black", "start_url": "/#/app/home", - "display": "standalone", - "orientation": "portrait" + "display": "standalone" } diff --git a/assets/www/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js b/assets/www/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js new file mode 100644 index 0000000000000000000000000000000000000000..19062bf15874ad66e03019743e8d3678738d8d39 --- /dev/null +++ b/assets/www/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js @@ -0,0 +1,87 @@ +cordova.define("cordova-plugin-ionic-keyboard.keyboard", function(require, exports, module) { +var argscheck = require('cordova/argscheck'), + utils = require('cordova/utils'), + exec = require('cordova/exec'), + channel = require('cordova/channel'); + +var Keyboard = function () {}; + +Keyboard.fireOnShow = function (height) { + Keyboard.isVisible = true; + cordova.fireWindowEvent('keyboardDidShow', { + 'keyboardHeight': height + }); + + // To support the keyboardAttach directive listening events + // inside Ionic's main bundle + cordova.fireWindowEvent('native.keyboardshow', { + 'keyboardHeight': height + }); +}; + +Keyboard.fireOnHide = function () { + Keyboard.isVisible = false; + cordova.fireWindowEvent('keyboardDidHide'); + + // To support the keyboardAttach directive listening events + // inside Ionic's main bundle + cordova.fireWindowEvent('native.keyboardhide'); +}; + +Keyboard.fireOnHiding = function () { + cordova.fireWindowEvent('keyboardWillHide'); +}; + +Keyboard.fireOnShowing = function (height) { + cordova.fireWindowEvent('keyboardWillShow', { + 'keyboardHeight': height + }); +}; + +Keyboard.hideFormAccessoryBar = Keyboard.hideKeyboardAccessoryBar = function (hide) { + console.warn("Keyboard.hideKeyboardAccessoryBar() not supported in Android"); +}; + +Keyboard.hide = function () { + exec(null, null, "CDVIonicKeyboard", "hide", []); +}; + +Keyboard.show = function () { + exec(null, null, "CDVIonicKeyboard", "show", []); +}; + +Keyboard.disableScroll = function (disable) { + console.warn("Keyboard.disableScroll() not supported in Android"); +}; + +Keyboard.setResizeMode = function (mode) { + console.warn("Keyboard.setResizeMode() not supported in Android"); +} + +Keyboard.setKeyboardStyle = function(style) { + console.warn("Keyboard.setKeyboardStyle() not supported in Android"); +}; + +channel.onCordovaReady.subscribe(function () { + exec(success, null, 'CDVIonicKeyboard', 'init', []); + + function success(msg) { + var action = msg.charAt(0); + if (action === 'S') { + var keyboardHeight = parseInt(msg.substr(1)); + Keyboard.fireOnShowing(keyboardHeight); + Keyboard.fireOnShow(keyboardHeight); + + } else if (action === 'H') { + Keyboard.fireOnHiding(); + Keyboard.fireOnHide(); + } + } +}); + + +Keyboard.isVisible = false; + +module.exports = Keyboard; + +}); diff --git a/assets/www/plugins/cordova-plugin-ionic-webview/src/www/util.js b/assets/www/plugins/cordova-plugin-ionic-webview/src/www/util.js new file mode 100644 index 0000000000000000000000000000000000000000..1e2aa1c4e5de8d1f4db964133678035609f6f69a --- /dev/null +++ b/assets/www/plugins/cordova-plugin-ionic-webview/src/www/util.js @@ -0,0 +1,32 @@ +cordova.define("cordova-plugin-ionic-webview.IonicWebView", function(require, exports, module) { +var exec = require('cordova/exec'); + +var WebView = { + convertFileSrc: function(url) { + if (!url) { + return url; + } + if (url.startsWith('/')) { + return window.WEBVIEW_SERVER_URL + '/_app_file_' + url; + } + if (url.startsWith('file://')) { + return window.WEBVIEW_SERVER_URL + url.replace('file://', '/_app_file_'); + } + if (url.startsWith('content://')) { + return window.WEBVIEW_SERVER_URL + url.replace('content:/', '/_app_content_'); + } + return url; + }, + setServerBasePath: function(path) { + exec(null, null, 'IonicWebView', 'setServerBasePath', [path]); + }, + getServerBasePath: function(callback) { + exec(callback, null, 'IonicWebView', 'getServerBasePath', []); + }, + persistServerBasePath: function() { + exec(null, null, 'IonicWebView', 'persistServerBasePath', []); + } +} + +module.exports = WebView; +}); diff --git a/assets/www/plugins/es/i18n/locale-en-GB.json b/assets/www/plugins/es/i18n/locale-en-GB.json index 479cd428326aa5568319031f5e4798d120ee919b..4ab28fa5cfa4deb5b1a08e0bbaa76cd60f803f14 100644 --- a/assets/www/plugins/es/i18n/locale-en-GB.json +++ b/assets/www/plugins/es/i18n/locale-en-GB.json @@ -10,6 +10,10 @@ "BTN_PICTURE_FAVORISE": "Default", "BTN_PICTURE_ROTATE": "Rotate", "BTN_ADD_PICTURE": "Add picture", + "NOTIFICATION": { + "TITLE": "New notification | {{'COMMON.APP_NAME'|translate}}", + "HAS_UNREAD": "You have {{count}} unread notification{{count>0?'s':''}}" + }, "NOTIFICATIONS": { "TITLE": "Notifications", "MARK_ALL_AS_READ": "Mark all as read", @@ -31,7 +35,7 @@ "ORGANIZATION_ACCOUNT_HELP": "If you represent a company, association, etc.<br/>No universal dividend will be created by this account." }, "EVENT": { - "MEMBER_WITHOUT_PROFILE": "To obtain your certification more quickly, fill in <a ui-sref=\"app.user_edit_profile\">your user profile</a>. Members will more easily put their trust in a verifiable identity." + "MEMBER_WITHOUT_PROFILE": "You can <a ui-sref=\"app.edit_profile\">fill your Cesium+ profile</a> (optional) to provide better visibility of your account. This profile will be stored in <b>a directory independent</b> of the currency, but decentralized." }, "ERROR": { "WS_CONNECTION_FAILED": "Cesium can not receive notifications because of a technical error (connection to the Cesium + data node).<br/><br/>If the problem persists, please <b>choose another data node</b> in Cesium+ settings." @@ -203,7 +207,7 @@ "TX_SEARCH_FILTER": { "MEMBER_FLOWS": "<b class=\"ion-person\"></b> Members input/output", "EXISTING_TRANSACTION": "<b class=\"ion-card\"></b> Having transactions", - "PERIOD": "<b class=\"ion-clock\"></b> Between <b class=\"gray\">{{params[1]|formatDateShort}}</b> ({{params[1]|formatTime}}) and <b class=\"gray\">{{params[2]|formatDateShort}}</b> ({{params[2]|formatTime}})", + "PERIOD": "<b class=\"ion-clock\"></b> Between <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) and <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", "ISSUER": "<b class=\"ion-android-desktop\"></b> Computed by {{params[1]|formatPubkey}}", "TX_PUBKEY": "<b class=\"ion-card\"></b> Transactions concerning <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" } @@ -226,7 +230,7 @@ "MY_PAGES": "My pages", "NO_PAGE": "No page", "SEARCH": { - "TITLE": "Professional Directory", + "TITLE": "Pages", "SEARCH_HELP": "What, Who: hairdresser, Lili's restaurant, ...", "BTN_ADD": "New", "BTN_LAST_RECORDS": "Recent pages", @@ -253,7 +257,7 @@ "REMOVE_CONFIRMATION" : "Are you sure you want to delete this reference?<br/><br/>This is irreversible." }, "TYPE": { - "TITLE": "New reference", + "TITLE": "New page", "SELECT_TYPE": "Kind of organization:", "ENUM": { "SHOP": "Local shops", @@ -264,7 +268,7 @@ }, "EDIT": { "TITLE": "Edit", - "TITLE_NEW": "New reference", + "TITLE_NEW": "New page", "RECORD_TYPE":"Kind of organization", "RECORD_TITLE": "Name", "RECORD_TITLE_HELP": "Name", @@ -350,7 +354,8 @@ "DISTANCE": "Maximum distance around the city", "DISTANCE_UNIT": "mi", "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", - "SEARCH_HELP": "Ville, Country", + "SEARCH_HELP": "City, Country", + "PROFILE_POSITION": "Profile position", "MODAL": { "TITLE": "Search address", "SEARCH_HELP": "City, Country", @@ -358,6 +363,7 @@ "POSITION": "lat/lon : {{lat}} / {{lon}}" }, "ERROR": { + "CITY_REQUIRED_IF_STREET": "Required if a street has been filled", "REQUIRED_FOR_LOCATION": "Required field to appear on the map", "INVALID_FOR_LOCATION": "Unknown address", "GEO_LOCATION_FAILED": "Unable to retrieve your current position. Please use the search button.", @@ -437,8 +443,9 @@ "PLUGIN_NAME": "Cesium+", "PLUGIN_NAME_HELP": "User profiles, notifications, private messages", "ENABLE_TOGGLE": "Enable extension?", - "ENABLE_MESSAGE_TOGGLE": "Enable messages?", - "ENABLE_SETTINGS_TOGGLE": "Enable remote storage for settings?", + "ENABLE_REMOTE_STORAGE": "Enable remote storage for settings?", + "ENABLE_REMOTE_STORAGE_HELP": "Enables (encrypted) storage of your settings on Cesium + nodes", + "ENABLE_MESSAGE_TOGGLE": "Enable private messages?", "PEER": "Data peer address", "POPUP_PEER": { "TITLE" : "Data peer", @@ -451,7 +458,9 @@ "ENABLE_TX_SENT": "Notify the validation of <b>sent payments</b>?", "ENABLE_TX_RECEIVED": "Notify the validation of <b>received payments</b>?", "ENABLE_CERT_SENT": "Notify the validation of <b>sent certifications</b>?", - "ENABLE_CERT_RECEIVED": "Notify the validation of <b>received certifications</b>?" + "ENABLE_CERT_RECEIVED": "Notify the validation of <b>received certifications</b>?", + "ENABLE_HTML5_NOTIFICATION": "Warn with each new notification?", + "ENABLE_HTML5_NOTIFICATION_HELP": "Opens a small popup window with each new notification." }, "CONFIRM": { "ASK_ENABLE_TITLE": "Optional features", diff --git a/assets/www/plugins/es/i18n/locale-en.json b/assets/www/plugins/es/i18n/locale-en.json index 479cd428326aa5568319031f5e4798d120ee919b..4ab28fa5cfa4deb5b1a08e0bbaa76cd60f803f14 100644 --- a/assets/www/plugins/es/i18n/locale-en.json +++ b/assets/www/plugins/es/i18n/locale-en.json @@ -10,6 +10,10 @@ "BTN_PICTURE_FAVORISE": "Default", "BTN_PICTURE_ROTATE": "Rotate", "BTN_ADD_PICTURE": "Add picture", + "NOTIFICATION": { + "TITLE": "New notification | {{'COMMON.APP_NAME'|translate}}", + "HAS_UNREAD": "You have {{count}} unread notification{{count>0?'s':''}}" + }, "NOTIFICATIONS": { "TITLE": "Notifications", "MARK_ALL_AS_READ": "Mark all as read", @@ -31,7 +35,7 @@ "ORGANIZATION_ACCOUNT_HELP": "If you represent a company, association, etc.<br/>No universal dividend will be created by this account." }, "EVENT": { - "MEMBER_WITHOUT_PROFILE": "To obtain your certification more quickly, fill in <a ui-sref=\"app.user_edit_profile\">your user profile</a>. Members will more easily put their trust in a verifiable identity." + "MEMBER_WITHOUT_PROFILE": "You can <a ui-sref=\"app.edit_profile\">fill your Cesium+ profile</a> (optional) to provide better visibility of your account. This profile will be stored in <b>a directory independent</b> of the currency, but decentralized." }, "ERROR": { "WS_CONNECTION_FAILED": "Cesium can not receive notifications because of a technical error (connection to the Cesium + data node).<br/><br/>If the problem persists, please <b>choose another data node</b> in Cesium+ settings." @@ -203,7 +207,7 @@ "TX_SEARCH_FILTER": { "MEMBER_FLOWS": "<b class=\"ion-person\"></b> Members input/output", "EXISTING_TRANSACTION": "<b class=\"ion-card\"></b> Having transactions", - "PERIOD": "<b class=\"ion-clock\"></b> Between <b class=\"gray\">{{params[1]|formatDateShort}}</b> ({{params[1]|formatTime}}) and <b class=\"gray\">{{params[2]|formatDateShort}}</b> ({{params[2]|formatTime}})", + "PERIOD": "<b class=\"ion-clock\"></b> Between <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) and <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", "ISSUER": "<b class=\"ion-android-desktop\"></b> Computed by {{params[1]|formatPubkey}}", "TX_PUBKEY": "<b class=\"ion-card\"></b> Transactions concerning <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" } @@ -226,7 +230,7 @@ "MY_PAGES": "My pages", "NO_PAGE": "No page", "SEARCH": { - "TITLE": "Professional Directory", + "TITLE": "Pages", "SEARCH_HELP": "What, Who: hairdresser, Lili's restaurant, ...", "BTN_ADD": "New", "BTN_LAST_RECORDS": "Recent pages", @@ -253,7 +257,7 @@ "REMOVE_CONFIRMATION" : "Are you sure you want to delete this reference?<br/><br/>This is irreversible." }, "TYPE": { - "TITLE": "New reference", + "TITLE": "New page", "SELECT_TYPE": "Kind of organization:", "ENUM": { "SHOP": "Local shops", @@ -264,7 +268,7 @@ }, "EDIT": { "TITLE": "Edit", - "TITLE_NEW": "New reference", + "TITLE_NEW": "New page", "RECORD_TYPE":"Kind of organization", "RECORD_TITLE": "Name", "RECORD_TITLE_HELP": "Name", @@ -350,7 +354,8 @@ "DISTANCE": "Maximum distance around the city", "DISTANCE_UNIT": "mi", "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", - "SEARCH_HELP": "Ville, Country", + "SEARCH_HELP": "City, Country", + "PROFILE_POSITION": "Profile position", "MODAL": { "TITLE": "Search address", "SEARCH_HELP": "City, Country", @@ -358,6 +363,7 @@ "POSITION": "lat/lon : {{lat}} / {{lon}}" }, "ERROR": { + "CITY_REQUIRED_IF_STREET": "Required if a street has been filled", "REQUIRED_FOR_LOCATION": "Required field to appear on the map", "INVALID_FOR_LOCATION": "Unknown address", "GEO_LOCATION_FAILED": "Unable to retrieve your current position. Please use the search button.", @@ -437,8 +443,9 @@ "PLUGIN_NAME": "Cesium+", "PLUGIN_NAME_HELP": "User profiles, notifications, private messages", "ENABLE_TOGGLE": "Enable extension?", - "ENABLE_MESSAGE_TOGGLE": "Enable messages?", - "ENABLE_SETTINGS_TOGGLE": "Enable remote storage for settings?", + "ENABLE_REMOTE_STORAGE": "Enable remote storage for settings?", + "ENABLE_REMOTE_STORAGE_HELP": "Enables (encrypted) storage of your settings on Cesium + nodes", + "ENABLE_MESSAGE_TOGGLE": "Enable private messages?", "PEER": "Data peer address", "POPUP_PEER": { "TITLE" : "Data peer", @@ -451,7 +458,9 @@ "ENABLE_TX_SENT": "Notify the validation of <b>sent payments</b>?", "ENABLE_TX_RECEIVED": "Notify the validation of <b>received payments</b>?", "ENABLE_CERT_SENT": "Notify the validation of <b>sent certifications</b>?", - "ENABLE_CERT_RECEIVED": "Notify the validation of <b>received certifications</b>?" + "ENABLE_CERT_RECEIVED": "Notify the validation of <b>received certifications</b>?", + "ENABLE_HTML5_NOTIFICATION": "Warn with each new notification?", + "ENABLE_HTML5_NOTIFICATION_HELP": "Opens a small popup window with each new notification." }, "CONFIRM": { "ASK_ENABLE_TITLE": "Optional features", diff --git a/assets/www/plugins/es/i18n/locale-eo-EO.json b/assets/www/plugins/es/i18n/locale-eo-EO.json new file mode 100644 index 0000000000000000000000000000000000000000..fe8978016c0049c54249f5a63b6d221236bf555b --- /dev/null +++ b/assets/www/plugins/es/i18n/locale-eo-EO.json @@ -0,0 +1,555 @@ +{ + "COMMON": { + "CATEGORY": "Kategorio", + "CATEGORIES": "Kategorioj", + "CATEGORY_SEARCH_HELP": "Serĉado", + "LAST_MODIFICATION_DATE": "Äœisdatigita la", + "SUBMIT_BY": "Submetita de", + "BTN_PUBLISH": "Publikigi", + "BTN_PICTURE_DELETE": "Forigi", + "BTN_PICTURE_FAVORISE": "Precipa", + "BTN_PICTURE_ROTATE": "Turni", + "BTN_ADD_PICTURE": "Aldoni foton", + "NOTIFICATION": { + "TITLE": "Nova avizo | {{'COMMON.APP_NAME'|translate}}", + "HAS_UNREAD": "Vi havas {{count}} avizo{{count>0?'j':''}}n ne legita{{count>0?'j':''}}n" + }, + "NOTIFICATIONS": { + "TITLE": "Avizoj", + "MARK_ALL_AS_READ": "Ĉion marki legita", + "NO_RESULT": "Neniu avizo", + "SHOW_ALL": "Vidi ĉion", + "LOAD_NOTIFICATIONS_FAILED": "Malsukceso por ÅarÄi la avizojn" + } + }, + "MENU": { + "REGISTRY": "PaÄoj", + "USER_PROFILE": "Mia profilo", + "MESSAGES": "MesaÄoj", + "NOTIFICATIONS": "Avizoj", + "INVITATIONS": "Invitoj" + }, + "ACCOUNT": { + "NEW": { + "ORGANIZATION_ACCOUNT": "Konto por organizaĵo", + "ORGANIZATION_ACCOUNT_HELP": "Se vi reprezentas entreprenon, asocion, ktp.<br/>Neniu universala dividendo estos kreita per tiu ĉi konto." + }, + "EVENT": { + "MEMBER_WITHOUT_PROFILE": "Vi povas <a ui-sref=\"app.edit_profile\">tajpi vian profilon Cesium+</a> (kromebleco) por disponi pli bonan videblecon por via konto." + }, + "ERROR": { + "WS_CONNECTION_FAILED": "Cesium ne povas ricevi la avizojn pro teknika eraro (konekto al la daten-nodo Cesium+).<br/><br/>Se la problemo daÅradas, bonvolu <b>elekti alian daten-nodon</b> ĉe la parametroj Cesium+." + } + }, + "WOT": { + "BTN_SUGGEST_CERTIFICATIONS_DOTS": "Sugesti identecojn atestotajn...", + "BTN_ASK_CERTIFICATIONS_DOTS": "Peti membrojn atesti min...", + "BTN_ASK_CERTIFICATION": "Peti atestaĵon", + "SUGGEST_CERTIFICATIONS_MODAL": { + "TITLE": "Sugesti atestadojn", + "HELP": "Elekti viajn sugestojn" + }, + "ASK_CERTIFICATIONS_MODAL": { + "TITLE": "Peti atestaĵojn", + "HELP": "Elekti la ricevontojn" + }, + "SEARCH": { + "DIVIDER_PROFILE": "Kontoj", + "DIVIDER_PAGE": "PaÄoj", + "DIVIDER_GROUP": "Grupoj" + }, + "CONFIRM": { + "SUGGEST_CERTIFICATIONS": "Ĉu vi certas, ke vi volas <b>sendi tiujn sugestojn por atestado</b>?", + "ASK_CERTIFICATION": "Ĉu vi certas, ke vi volas <b>sendi atesto-peton</b>?", + "ASK_CERTIFICATIONS": "Ĉu vi certas, ke vi volas <b>sendi atesto-peton</b> al tiuj personoj?" + } + }, + "INVITATION": { + "TITLE": "Invitoj", + "NO_RESULT": "Neniu invito atendanta", + "BTN_DELETE_ALL": "Forigi ĉiujn invitojn", + "BTN_DELETE": "Forigi la inviton", + "BTN_NEW_INVITATION": "Nova invito", + "ASK_CERTIFICATION": "<a href=\"#/app/wot/{{pubkey}}/{{::uid}}\">{{::name||uid}}</a> petas vian atestadon", + "SUGGESTION_CERTIFICATION": "<a href=\"#/app/wot/{{::pubkey}}/{{::uid}}\">{{::name||uid}}</a> estas sugestita al vi por atestado", + "SUGGESTED_BY": "Sugesto sendita de <a class=\"positive\" href=\"#/app/wot/{{::issuer.pubkey}}/{{::issuer.uid}}\">{{::issuer.name||issuer.uid}}</a>", + "NOTIFICATIONS": { + "TITLE": "Invitoj" + }, + "LIST": { + "TITLE": "Invitoj" + }, + "NEW": { + "TITLE": "Nova invito", + "RECIPIENTS": "Al", + "RECIPIENTS_HELP": "Ricevontoj de la invito", + "RECIPIENTS_MODAL_TITLE": "Ricevontoj", + "RECIPIENTS_MODAL_HELP": "Bonvolu elekti la ricevontojn:", + "SUGGESTION_IDENTITIES": "Sugestoj por atestado", + "SUGGESTION_IDENTITIES_HELP": "Atestadoj sugestotaj", + "SUGGESTION_IDENTITIES_MODAL_TITLE": "Sugestoj", + "SUGGESTION_IDENTITIES_MODAL_HELP": "Bonvolu elekti viajn sugestojn:" + }, + "CONFIRM": { + "DELETE_ALL_CONFIRMATION": "La forigo de la invitoj estas <b>neinversigebla ago</b>.<br/><br/><b>Ĉu vi certas</b>, ke vi volas daÅrigi?", + "SEND_INVITATIONS_TO_CERTIFY": "Ĉu vi certas, ke vi volas <b>sendi tiun inviton atestotan</b>?" + }, + "INFO": { + "INVITATION_SENT": "Invito sendita" + }, + "ERROR": { + "LOAD_INVITATIONS_FAILED": "Malsukceso por ÅarÄi la invitojn", + "REMOVE_INVITATION_FAILED": "Eraro dum la forigo de la invito", + "REMOVE_ALL_INVITATIONS_FAILED": "Eraro dum la forigo de la invitoj", + "SEND_INVITATION_FAILED": "Eraro dum la sendo de la invito", + "BAD_INVITATION_FORMAT": "<span class=\"assertive\"><i class=\"ion-close-circled\"></i> Invito nelegebla (strukturo nekonata)</span> - sendita de <a ui-sref=\"app.wot_identity({pubkey: '{{::pubkey}}', uid: '{{::uid}}' })\">{{::name||uid}}</a>" + } + }, + "COMMENTS": { + "DIVIDER": "Komentoj", + "SHOW_MORE_COMMENTS": "AfiÅi la antaÅajn komentojn", + "COMMENT_HELP": "Via komento, demando, ktp.", + "COMMENT_HELP_REPLY_TO": "Via respondo...", + "BTN_SEND": "Sendi", + "POPOVER_SHARE_TITLE": "MesaÄo #{{number}}", + "REPLY": "Respondi", + "REPLY_TO": "Respondo al:", + "REPLY_TO_LINK": "Responde al ", + "REPLY_TO_DELETED_COMMENT": "Responde al forigita komento", + "REPLY_COUNT": "{{replyCount}} respondoj", + "DELETED_COMMENT": "Komento forigita", + "ERROR": { + "FAILED_SAVE_COMMENT": "Eraro dum la konservo de la komento", + "FAILED_REMOVE_COMMENT": "Eraro dum la forigo de la komento" + } + }, + "MESSAGE": { + "REPLY_TITLE_PREFIX": "Resp: ", + "FORWARD_TITLE_PREFIX": "Tr: ", + "BTN_REPLY": "Respondi", + "BTN_COMPOSE": "Nova mesaÄo", + "BTN_WRITE": "Skribi", + "NO_MESSAGE_INBOX": "Neniu mesaÄo ricevita", + "NO_MESSAGE_OUTBOX": "Neniu mesaÄo sendita", + "NOTIFICATIONS": { + "TITLE": "MesaÄoj", + "MESSAGE_RECEIVED": "Vi <b>ricevis mesaÄon</b><br/>de" + }, + "LIST": { + "INBOX": "Ricevujo", + "OUTBOX": "Senditaj mesaÄoj", + "LAST_INBOX": "Novaj mesaÄoj", + "LAST_OUTBOX": "Senditaj mesaÄoj", + "BTN_LAST_MESSAGES": "FreÅdataj mesaÄoj", + "TITLE": "MesaÄoj", + "SEARCH_HELP": "Serĉado en la mesaÄoj", + "POPOVER_ACTIONS": { + "TITLE": "Kromaĵoj", + "DELETE_ALL": "Forigi ĉiujn mesaÄojn" + } + }, + "COMPOSE": { + "TITLE": "Nova mesaÄo", + "TITLE_REPLY": "Respondi", + "SUB_TITLE": "Nova mesaÄo", + "TO": "Al", + "OBJECT": "Temo", + "OBJECT_HELP": "Temo", + "ENCRYPTED_HELP": "Bonvolu noti, ke tiu ĉi mesaÄo estos ĉifrita antaÅ sendo, tiel ke nur la adresato povos legi Äin, kaj ke li estos certa, ke vi ja estas ties aÅtoro.", + "MESSAGE": "MesaÄo", + "MESSAGE_HELP": "Enhavo de la mesaÄo", + "CONTENT_CONFIRMATION": "La enhavo de la mesaÄo estas malplena.<br/><br/>Ĉu vi volas tamen sendi la mesaÄon?" + }, + "VIEW": { + "TITLE": "MesaÄo", + "SENDER": "Sendita de", + "RECIPIENT": "Sendita al", + "NO_CONTENT": "MesaÄo malplena", + "DELETE": "Forigi la mesaÄon" + }, + "CONFIRM": { + "REMOVE": "Ĉu vi certas, ke vi volas <b>forigi tiun ĉi mesaÄon</b>?<br/><br/>Tiu ago estas neinversigebla.", + "REMOVE_ALL" : "Ĉu vi certas, ke vi volas <b>forigi ĉiujn mesaÄojn</b>?<br/><br/>Tiu ago estas neinversigebla.", + "MARK_ALL_AS_READ": "Ĉu vi certas, ke vi volas <b>marki ĉiujn mesaÄojn legitaj</b>?", + "USER_HAS_NO_PROFILE": "Tiu identeco havas neniun profilon Cesium+. Eblas ke Äi ne uzas la krom-programon Cesium+, kaj <b>do ne legos vian mesaÄon</b>.<br/><br/>Ĉu vi certas, ke vi volas tamen <b>daÅrigi</b>?" + }, + "INFO": { + "MESSAGE_REMOVED": "MesaÄo forigita", + "All_MESSAGE_REMOVED": "Ĉiuj mesaÄoj estis forigitaj", + "MESSAGE_SENT": "MesaÄo sendita" + }, + "ERROR": { + "SEND_MSG_FAILED": "Eraro dum la sendo de la mesaÄo.", + "LOAD_MESSAGES_FAILED": "Eraro dum la ricevo de la mesaÄoj.", + "LOAD_MESSAGE_FAILED": "Eraro dum la ricevo de la mesaÄo.", + "MESSAGE_NOT_READABLE": "Legado de la mesaÄo neebla.", + "USER_NOT_RECIPIENT": "Vi ne estas la adresato de tiu ĉi mesaÄo: malĉifrado neebla.", + "NOT_AUTHENTICATED_MESSAGE": "La aÅtenteco de la mesaÄo estas dubinda aÅ ties enhavo estas difektita.", + "REMOVE_MESSAGE_FAILED": "Malsukceso por forigi la mesaÄon", + "MESSAGE_CONTENT_TOO_LONG": "Signaro tro longa ({{maxLength}} signoj maksimume).", + "MARK_AS_READ_FAILED": "Neeblas marki la mesaÄon 'legita'.", + "LOAD_NOTIFICATIONS_FAILED": "Eraro dum la ricevo de la mesaÄo-avizoj.", + "REMOVE_All_MESSAGES_FAILED": "Eraro dum la forigo de ĉiuj mesaÄoj.", + "MARK_ALL_AS_READ_FAILED": "Eraro por marki la mesaÄojn legitaj.", + "RECIPIENT_IS_MANDATORY": "La adresato estas deviga." + } + }, + "BLOCKCHAIN": { + "LOOKUP": { + "SEARCH_HELP": "Numero de bloko, haketo, publika Ålosilo, ktp.", + "POPOVER_FILTER_TITLE": "Filtriloj", + "HEADER_MEDIAN_TIME": "Dato / Horo", + "HEADER_BLOCK": "Bloko #", + "HEADER_ISSUER": "Nodo elsendinta", + "BTN_LAST": "Lastaj blokoj", + "DISPLAY_QUERY": "AfiÅi la informpeton", + "HIDE_QUERY": "KaÅi la informpeton", + "TX_SEARCH_FILTER": { + "MEMBER_FLOWS": "<b class=\"ion-person\"></b> Eniroj/eliroj de membroj", + "EXISTING_TRANSACTION": "<b class=\"ion-card\"></b> Kun spezoj", + "PERIOD": "<b class=\"ion-clock\"></b> Inter <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) kaj <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", + "ISSUER": "<b class=\"ion-android-desktop\"></b> Kalkulita de <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}", + "TX_PUBKEY": "<b class=\"ion-card\"></b> Spezoj koncernantaj <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" + } + }, + "ERROR": { + "SEARCH_BLOCKS_FAILED": "Eraro dum la serĉado de la blokoj." + } + }, + "GROUP": { + "GENERAL_DIVIDER": "Äœeneralaj informoj", + "LOCATION_DIVIDER": "Adreso", + "SOCIAL_NETWORKS_DIVIDER": "Sociaj retoj kaj retejo", + "TECHNICAL_DIVIDER": "Teknikaj informoj", + "CREATED_TIME": "Kreita {{creationTime|formatFromNow}}", + "NOTIFICATIONS": { + "TITLE": "Invitoj" + }, + "LOOKUP": { + "TITLE": "Grupoj", + "SEARCH_HELP": "Nomo de grupo, vortoj, loko, ktp.", + "LAST_RESULTS_LIST": "Novaj grupoj:", + "OPEN_RESULTS_LIST": "Malfermitaj grupoj:", + "MANAGED_RESULTS_LIST": "Fermitaj grupoj:", + "BTN_LAST": "Novaj grupoj", + "BTN_NEW": "Mi aldonas grupon" + }, + "TYPE": { + "TITLE": "Nova grupo", + "SELECT_TYPE": "Tipo de grupo:", + "OPEN_GROUP": "Malfermita grupo", + "OPEN_GROUP_HELP": "Malfermita grupo estas alirebla de iu ajn membro de la mono.", + "MANAGED_GROUP": "Administrita grupo", + "MANAGED_GROUP_HELP": "Administrita grupo estas mastrumata de administrantoj kaj moderigantoj, kiuj povas akcepti, rifuzi aÅ eksigi membron.", + "ENUM": { + "OPEN": "Malfermita grupo", + "MANAGED": "Administrita grupo" + } + }, + "VIEW": { + "POPOVER_SHARE_TITLE": "{{title}}", + "MENU_TITLE": "Kromaĵoj", + "REMOVE_CONFIRMATION" : "Ĉu vi certas, ke vi volas forigi tiun ĉi grupon?<br/><br/>Tiu ago estas neinversigebla." + }, + "EDIT": { + "TITLE": "Grupo", + "TITLE_NEW": "Nova grupo", + "RECORD_TITLE": "Titolo", + "RECORD_TITLE_HELP": "Titolo", + "RECORD_DESCRIPTION": "Priskribo", + "RECORD_DESCRIPTION_HELP": "Priskribo" + }, + "ERROR": { + "SEARCH_GROUPS_FAILED": "Malsukceso por traserĉi grupojn", + "REMOVE_RECORD_FAILED": "Malsukceso por forigi la grupon" + }, + "INFO": { + "RECORD_REMOVED" : "Grupo forigita" + } + }, + "REGISTRY": { + "CATEGORY": "Ĉefa agado", + "GENERAL_DIVIDER": "Äœeneralaj informoj", + "LOCATION_DIVIDER": "Adreso", + "SOCIAL_NETWORKS_DIVIDER": "Sociaj retoj kaj retejo", + "TECHNICAL_DIVIDER": "Teknikaj informoj", + "BTN_SHOW_WOT": "Personoj", + "BTN_SHOW_WOT_HELP": "Traserĉi personojn", + "BTN_SHOW_PAGES": "PaÄoj", + "BTN_SHOW_PAGES_HELP": "Traserĉi paÄojn", + "BTN_NEW": "Krei paÄon", + "MY_PAGES": "Miaj paÄoj", + "NO_PAGE": "Neniu paÄo", + "SEARCH": { + "TITLE": "PaÄoj", + "SEARCH_HELP": "Kio, Kiu: restoracio, Ĉe Marcelo, ...", + "BTN_ADD": "Nova", + "BTN_LAST_RECORDS": "FreÅdataj paÄoj", + "BTN_ADVANCED_SEARCH": "Sperta serĉado", + "BTN_OPTIONS": "Sperta serĉado", + "TYPE": "Tipo de paÄo", + "LOCATION_HELP": "Kie: PoÅto-kodo, Urbo", + "RESULTS": "Rezultoj", + "RESULT_COUNT_LOCATION": "{{count}} rezulto{{count>0?'j':''}}, proksime de {{location}}", + "RESULT_COUNT": "{{count}} rezulto{{count>0?'j':''}}", + "LAST_RECORDS": "FreÅdataj paÄoj", + "LAST_RECORD_COUNT_LOCATION": "{{count}} paÄo{{count>0?'j':''}} freÅdata{{count>0?'j':''}}, proksime de {{location}}", + "LAST_RECORD_COUNT": "{{count}} paÄo{{count>0?'j':''}} freÅdata{{count>0?'j':''}}", + "POPOVER_FILTERS": { + "BTN_ADVANCED_SEARCH": "Spertaj kromaĵoj?" + } + }, + "VIEW": { + "TITLE": "Adresaro", + "CATEGORY": "Ĉefa agado:", + "LOCATION": "Adreso:", + "MENU_TITLE": "Kromaĵoj", + "POPOVER_SHARE_TITLE": "{{title}}", + "REMOVE_CONFIRMATION" : "Ĉu vi certas, ke vi volas forigi tiun ĉi paÄon?<br/><br/>Tiu ago estas neinversigebla." + }, + "TYPE": { + "TITLE": "Tipoj", + "SELECT_TYPE": "Tipo de paÄo:", + "ENUM": { + "SHOP": "Loka komerco", + "COMPANY": "Entrepreno", + "ASSOCIATION": "Asocio", + "INSTITUTION": "Institucio" + } + }, + "EDIT": { + "TITLE": "Redaktado", + "TITLE_NEW": "Nova paÄo", + "RECORD_TYPE":"Tipo de paÄo", + "RECORD_TITLE": "Nomo", + "RECORD_TITLE_HELP": "Nomo", + "RECORD_DESCRIPTION": "Priskribo", + "RECORD_DESCRIPTION_HELP": "Priskribo de la agado", + "RECORD_ADDRESS": "Strato", + "RECORD_ADDRESS_HELP": "Strato, konstruaĵo...", + "RECORD_CITY": "Urbo", + "RECORD_CITY_HELP": "Urbo", + "RECORD_SOCIAL_NETWORKS": "Sociaj retoj kaj retejo", + "RECORD_PUBKEY": "Publika Ålosilo", + "RECORD_PUBKEY_HELP": "Publika Ålosilo por ricevi la pagojn" + }, + "WALLET": { + "REGISTRY_DIVIDER": "PaÄoj", + "REGISTRY_HELP": "La paÄoj listigas agadojn, kiuj akceptas la liberan monon aÅ helpas Äin: komercoj, entreprenoj, asocioj, institucioj." + }, + "ERROR": { + "LOAD_CATEGORY_FAILED": "Malsukceso por ÅarÄi la liston de la agadoj", + "LOAD_RECORD_FAILED": "Eraro dum la ÅarÄado de la paÄo", + "LOOKUP_RECORDS_FAILED": "Eraro dum la serĉado", + "REMOVE_RECORD_FAILED": "Malsukceso por forigi la paÄon", + "SAVE_RECORD_FAILED": "Eraro dum la konservado", + "RECORD_NOT_EXISTS": "PaÄo neekzistanta", + "GEO_LOCATION_NOT_FOUND": "Urbo aÅ poÅto-kodo ne trovita" + }, + "INFO": { + "RECORD_REMOVED" : "PaÄo forigita", + "RECORD_SAVED": "PaÄo konservita" + } + }, + "PROFILE": { + "PROFILE_DIVIDER": "Profilo Cesium+", + "PROFILE_DIVIDER_HELP": "Temas pri kromaj datenoj, stokitaj ekster la mon-reto.", + "NO_PROFILE_DEFINED": "Neniu profilo tajpita", + "BTN_ADD": "Tajpi mian profilon", + "BTN_EDIT": "Redakti mian profilon", + "BTN_DELETE": "Forigi mian profilon", + "BTN_REORDER": "Reordigi", + "UID": "PseÅdonimo", + "TITLE": "Familia nomo, Persona nomo", + "TITLE_HELP": "Familia nomo, Persona nomo", + "DESCRIPTION": "Pri mi", + "DESCRIPTION_HELP": "Pri mi...", + "SOCIAL_HELP": "http://...", + "GENERAL_DIVIDER": "Äœeneralaj informoj", + "SOCIAL_NETWORKS_DIVIDER": "Sociaj retoj, retejoj", + "TECHNICAL_DIVIDER": "Teknikaj informoj", + "MODAL_AVATAR": { + "TITLE": "Profil-foto", + "SELECT_FILE_HELP": "Bonvolu <b>elekti bildo-dosieron</b>, alklakante la ĉi-suban butonon:", + "BTN_SELECT_FILE": "Elekti foton", + "RESIZE_HELP": "<b>Rekadri la bildon</b>, laÅbezone. Pluigi klakon sur la bildo ebligas movi Äin. Alklaku la zonon malsupre maldekstre por zomi.", + "RESULT_HELP": "<b>Jen la rezulto</b> tiel videbla ĉe via profilo:" + }, + "CONFIRM": { + "DELETE": "Ĉu vi certas, ke vi volas <b>forigi vian profilon Cesium+ ?</b><br/><br/>Tiu ago estas neinversigebla." + }, + "ERROR": { + "REMOVE_PROFILE_FAILED": "Malsukceso por forigi la profilon", + "LOAD_PROFILE_FAILED": "Malsukceso por ÅarÄi la profilon de la uzanto.", + "SAVE_PROFILE_FAILED": "Eraro dum la konservado", + "INVALID_SOCIAL_NETWORK_FORMAT": "Strukturo ne rekonata: bonvolu tajpi validan adreson.<br/><br/>Ezemploj:<ul><li>- Facebook-paÄo (https://www.facebook.com/uzanto)</li><li>- RetpaÄo (http://www.miaretejo.net)</li><li>- Retadreso (joe@dalton.com)</li></ul>", + "IMAGE_RESIZE_FAILED": "Eraro dum la reformatigo de la bildo" + }, + "INFO": { + "PROFILE_REMOVED": "Profilo forigita", + "PROFILE_SAVED": "Profilo konservita" + }, + "HELP": { + "WARNING_PUBLIC_DATA": "La informoj afiÅitaj en via profilo <b>estas publikaj</b>: videblaj inkluzive de la personoj <b>ne konektitaj</b>.<br/>{{'PROFILE.PROFILE_DIVIDER_HELP'|translate}}" + } + }, + "LOCATION": { + "BTN_GEOLOC_ADDRESS": "Trovi mian adreson surmape", + "USE_GEO_POINT": "Aperi sur la mapoj {{'COMMON.APP_NAME'|translate}}?", + "LOADING_LOCATION": "Serĉado de la adreso...", + "LOCATION_DIVIDER": "Adreso", + "ADDRESS": "Strato", + "ADDRESS_HELP": "Strato, adres-aldonaĵo...", + "CITY": "Urbo", + "CITY_HELP": "PoÅto-kodo, Urbo, Lando", + "DISTANCE": "Maksimuma distanco ĉirkaÅ la urbo", + "DISTANCE_UNIT": "km", + "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", + "SEARCH_HELP": "PoÅto-kodo, Urbo", + "PROFILE_POSITION": "Loko de la profilo", + "MODAL": { + "TITLE": "Serĉado de la adreso", + "SEARCH_HELP": "Urbo, PoÅto-kodo, Lando", + "ALTERNATIVE_RESULT_DIVIDER": "Alternativaj rezultoj por <b>{{address}}</b>:", + "POSITION": "Lat/Lon: {{lat}}/{{lon}}" + }, + "ERROR": { + "CITY_REQUIRED_IF_STREET": "Deviga kampo (ĉar strato estas tajpita)", + "REQUIRED_FOR_LOCATION": "Deviga kampo por aperi sur la mapo", + "INVALID_FOR_LOCATION": "Adreso nekonata", + "GEO_LOCATION_FAILED": "Neeblas ricevi vian lokiÄon. Bonvolu uzi la serĉo-butonon.", + "ADDRESS_LOCATION_FAILED": "Neeblas ricevi la lokon per la adreso" + } + }, + "SUBSCRIPTION": { + "SUBSCRIPTION_DIVIDER": "Retaj servoj", + "SUBSCRIPTION_DIVIDER_HELP": "La retaj servoj proponas pliajn nedevigajn servojn, delegitajn al aliulo.", + "BTN_ADD": "Aldoni servon", + "BTN_EDIT": "Mastrumi miajn servojn", + "NO_SUBSCRIPTION": "Neniu servo uzata", + "SUBSCRIPTION_COUNT": "Servoj / Abonoj", + "EDIT": { + "TITLE": "Retaj servoj", + "HELP_TEXT": "Mastrumu ĉi tie viajn abonojn kaj aliajn retajn servojn", + "PROVIDER": "Provizanto:" + }, + "TYPE": { + "ENUM": { + "EMAIL": "Ricevi la avizojn per retmesaÄo" + } + }, + "CONFIRM": { + "DELETE_SUBSCRIPTION": "Ĉu vi certas, ke vi volas <b>forigi tiun abonon</b>?" + }, + "ERROR": { + "LOAD_SUBSCRIPTIONS_FAILED": "Eraro dum la ÅarÄo de la retaj servoj", + "ADD_SUBSCRIPTION_FAILED": "Malsukceso por sendi la abonon", + "UPDATE_SUBSCRIPTION_FAILED": "Malsukceso por Äisdatigi la abonon", + "DELETE_SUBSCRIPTION_FAILED": "Eraro dum la forigo de la abono" + }, + "MODAL_EMAIL": { + "TITLE" : "Avizo per retmesaÄo", + "HELP" : "Plenigu tiun ĉi formularon por <b>esti avizita per retmesaÄo</b> pri la okazaĵoj ĉe via konto.<br/>Via retadreso estos ĉifrita por esti videbla nur de la servo-provizanto.", + "EMAIL_LABEL" : "Via retadreso:", + "EMAIL_HELP": "johano.stelaro@esperanto.org", + "FREQUENCY_LABEL": "Periodo de la avizoj:", + "FREQUENCY_DAILY": "Ĉiutaga", + "FREQUENCY_WEEKLY": "Ĉiusemajna", + "PROVIDER": "Servo-provizanto:" + } + }, + "DOCUMENT": { + "HASH": "Haketo: ", + "LOOKUP": { + "TITLE": "Serĉado de dokumentoj", + "BTN_ACTIONS": "Agoj", + "SEARCH_HELP": "Sendanto:AAA*, tempo:1508406169", + "LAST_DOCUMENTS": "Lastaj dokumentoj", + "SHOW_QUERY": "Vidi la informpeton", + "HIDE_QUERY": "KaÅi la informpeton", + "HEADER_TIME": "Dato/Horo", + "HEADER_ISSUER": "Sendanto", + "HEADER_RECIPIENT": "Ricevonto", + "READ": "Legita", + "BTN_REMOVE": "Forigi tiun ĉi dokumenton", + "POPOVER_ACTIONS": { + "TITLE": "Agoj", + "REMOVE_ALL": "Forigi tiujn ĉi dokumentojn..." + } + }, + "INFO": { + "REMOVED": "Dokumento forigita" + }, + "CONFIRM": { + "REMOVE": "Ĉu vi certas, ke vi volas <b>forigi tiun ĉi dokumenton</b>?", + "REMOVE_ALL": "Ĉu vi certas, ke vi volas <b>forigi tiujn ĉi dokumentojn</b>?" + }, + "ERROR": { + "LOAD_DOCUMENTS_FAILED": "Eraro dum la serĉado de dokumentoj", + "REMOVE_FAILED": "Eraro dum la forigo de la dokumento", + "REMOVE_ALL_FAILED": "Eraro dum la forigo de la dokumentoj" + } + }, + "ES_SETTINGS": { + "PLUGIN_NAME": "Cesium+", + "PLUGIN_NAME_HELP": "Profiloj, avizoj, privataj mesaÄoj", + "ENABLE_TOGGLE": "Aktivigi la krom-programon?", + "ENABLE_REMOTE_STORAGE": "Aktivigi la foran stokadon?", + "ENABLE_REMOTE_STORAGE_HELP": "Ebligas stoki (ĉifrite) viajn parametrojn ĉe la nodoj Cesium+", + "ENABLE_MESSAGE_TOGGLE": "Aktivigi la privatajn mesaÄojn?", + "PEER": "Adreso de la daten-nodo", + "POPUP_PEER": { + "TITLE" : "Daten-nodo", + "HELP" : "Tajpu la adreson de la nodo, kiun vi volas uzi:", + "PEER_HELP": "servo.domajno.com:port" + }, + "NOTIFICATIONS": { + "DIVIDER": "Avizoj", + "HELP_TEXT": "Aktivigu la avizo-tipojn, kiujn vi deziras ricevi:", + "ENABLE_TX_SENT": "Avizi pri la <b>senditaj pagoj</b>?", + "ENABLE_TX_RECEIVED": "Avizi pri la <b>ricevitaj pagoj</b>?", + "ENABLE_CERT_SENT": "Avizi pri la <b>senditaj atestaĵoj</b>?", + "ENABLE_CERT_RECEIVED": "Avizi pri <b>la ricevitaj atestaĵoj</b>?", + "ENABLE_HTML5_NOTIFICATION": "Anonci ĉiun novan avizon?", + "ENABLE_HTML5_NOTIFICATION_HELP": "Malfermas fenestreton por ĉiu nova avizo." + }, + "CONFIRM": { + "ASK_ENABLE_TITLE": "Kromaj funkcioj", + "ASK_ENABLE": "La krom-programo Cesium+ estas <b>malaktivigita</b> ĉe viaj parametroj, kio senaktivigas la funkciojn: <ul><li> <b><i class=\"icon ion-person\"></i> Profiloj Cesium+</b>;<li> <b><i class=\"icon ion-android-notifications\"></i> Avizoj</b>;<li> <b><i class=\"icon ion-email\"></i> Privataj mesaÄoj</b>.<li> <b><i class=\"icon ion-location\"></i> Mapoj, ktp.</b>.</ul><br/><b>Ĉu vi deziras reaktivigi</b> la krom-programon?" + } + }, + "ES_WALLET": { + "ERROR": { + "RECIPIENT_IS_MANDATORY": "Adresito estas deviga por la ĉifrado." + } + }, + "EVENT": { + "NODE_STARTED": "Via nodo ES API <b>{{params[0]}}</b> ekis", + "NODE_BMA_DOWN": "La nodo <b>{{params[0]}}:{{params[1]}}</b> (uzata de via nodo ES API) estas <b>neatingebla</b>.", + "NODE_BMA_UP": "La nodo <b>{{params[0]}}:{{params[1]}}</b> estas denove alirebla.", + "MEMBER_JOIN": "Vi estas nun <b>membro</b> de la mono <b>{{params[0]}}</b>!", + "MEMBER_LEAVE": "Vi <b>ne plu estas membro</b> de la mono <b>{{params[0]}}</b>!", + "MEMBER_EXCLUDE": "Vi <b>ne plu estas membro</b> de la mono <b>{{params[0]}}</b>, pro ne revalidiÄo aÅ pro manko da atestaĵoj.", + "MEMBER_REVOKE": "La nuligo de via konto efektiviÄis. Äœi ne plu povos esti membro-konto de la mono <b>{{params[0]}}</b>.", + "MEMBER_ACTIVE": "La revalidiÄo de via aliÄo al la mono <b>{{params[0]}}</b> estis <b>ricevita</b>.", + "TX_SENT": "Via <b>pago</b> al <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\" ><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> efektiviÄis.", + "TX_SENT_MULTI": "Via <b>pago</b> al <b>{{params[1]}}</b> efektiviÄis.", + "TX_RECEIVED": "Vi <b>ricevis pagon</b> de <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span>.", + "TX_RECEIVED_MULTI": "Vi <b>ricevis pagon</b> de <b>{{params[1]}}</b>.", + "CERT_SENT": "Via <b>atestado</b> al <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\" ><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> efektiviÄis.", + "CERT_RECEIVED": "Vi <b>ricevis atestaĵon</b> de <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span>.", + "REGISTRY": { + "NEW_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> komentis vian anoncon: <b>{{params[2]}}</b>", + "UPDATE_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> modifis sian komenton pri via anonco: <b>{{params[2]}}</b>", + "NEW_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> respondis al via komento pri la anonco: <b>{{params[2]}}</b>", + "UPDATE_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> modifis sian respondon al via komento pri la anonco: <b>{{params[2]}}</b>" + } + }, + "CONFIRM": { + "ES_USE_FALLBACK_NODE": "Daten-nodo <b>{{old}}</b> neatingebla aÅ adreso nevalida.<br/><br/>Ĉu vi volas provizore uzi la daten-nodon <b>{{new}}</b> ?" + }, + "ERROR": { + "ES_CONNECTION_ERROR": "Daten-nodo <b>{{server}}</b> neatingebla aÅ adreso nevalida.<br/><br/>Cesium daÅrigos funkcii, <b>sen la krom-programo Cesium+</b> (uzanto-profiloj, privataj mesaÄoj, mapoj kaj grafikoj)<br/><br/>Kontrolu vian ret-konekton, aÅ ÅanÄu daten-nodon ĉe la <a class=\"positive\" ng-click=\"doQuickFix('settings')\">parametroj de la krom-programo</a>.", + "ES_MAX_UPLOAD_BODY_SIZE": "La kvanto de datenoj sendotaj superas la limon fiksitan de la servilo.<br/>Bonvolu reprovi post, ekzemple, forigo de fotoj." + } +} diff --git a/assets/www/plugins/es/i18n/locale-es-ES.json b/assets/www/plugins/es/i18n/locale-es-ES.json index 7b663445b0c028ef3a9e9d91573ba6eb72afd3f7..49be7a99468121da776c1951e2ad340bcea5f13f 100644 --- a/assets/www/plugins/es/i18n/locale-es-ES.json +++ b/assets/www/plugins/es/i18n/locale-es-ES.json @@ -31,7 +31,7 @@ "ORGANIZATION_ACCOUNT_HELP": "Si representa una empresa, una asociación, etc.<br/>Ningún dividendo universal será creÃdo por esta cuenta." }, "EVENT": { - "MEMBER_WITHOUT_PROFILE": "Para obtener sus certificaciónes más rapidamente, completa <a ui-sref=\"app.user_edit_profile\">su perfil usuario</a>. Los miembros concederán más fácilmente su confianza a una identidad verificable." + "MEMBER_WITHOUT_PROFILE": "Para obtener sus certificaciónes más rapidamente, completa <a ui-sref=\"app.edit_profile\">su perfil usuario</a>. Los miembros concederán más fácilmente su confianza a una identidad verificable." }, "ERROR": { "WS_CONNECTION_FAILED": "Cesium no puede recibir las notificaciónes, a causa de un error técnico (conexión al nodo de datos Cesium+).<br/><br/>Si el problema persiste, por favor <b>elige un otro nodo de datos</b> en las configuraciónes Cesium+." @@ -203,7 +203,7 @@ "TX_SEARCH_FILTER": { "MEMBER_FLOWS": "Entradas/salidas de miembros", "EXISTING_TRANSACTION": "Con transacciones", - "PERIOD": "<b class=\"ion-clock\"></b> Entre el <b class=\"gray\">{{params[1]|formatDateShort}}</b> ({{params[1]|formatTime}}) y el <b class=\"gray\">{{params[2]|formatDateShort}}</b> ({{params[2]|formatTime}})", + "PERIOD": "<b class=\"ion-clock\"></b> Entre el <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) y el <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", "ISSUER": "<b class=\"ion-android-desktop\"></b> Calculado por <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}", "TX_PUBKEY": "<b class=\"ion-card\"></b> Transacciones que implican <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" } @@ -402,6 +402,7 @@ "DISTANCE_UNIT": "km", "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", "SEARCH_HELP": "Ciudad, PaÃs", + "PROFILE_POSITION": "Posición del perfil", "MODAL": { "TITLE": "Búsqueda de dirección", "SEARCH_HELP": "Ciudad, PaÃs", @@ -409,6 +410,7 @@ "POSITION": "Latitud/Longitud : {{lat}} / {{lon}}" }, "ERROR": { + "CITY_REQUIRED_IF_STREET": "Requerido si una calle ha sido llenada", "REQUIRED_FOR_LOCATION": "Campo obligatorio para aparecer en el mapa", "INVALID_FOR_LOCATION": "Dirección desconocida", "GEO_LOCATION_FAILED": "No se puede recuperar su ubicación Por favor usa el botón de búsqueda.", diff --git a/assets/www/plugins/es/i18n/locale-fr-FR.json b/assets/www/plugins/es/i18n/locale-fr-FR.json index 6dfdfa65cd3c49da41b82d3aede241dcef56f2c1..c5c84bf3e2d57b466824a14c12da2383fcdcc451 100644 --- a/assets/www/plugins/es/i18n/locale-fr-FR.json +++ b/assets/www/plugins/es/i18n/locale-fr-FR.json @@ -10,6 +10,10 @@ "BTN_PICTURE_FAVORISE": "Principale", "BTN_PICTURE_ROTATE": "Tourner", "BTN_ADD_PICTURE": "Ajouter une photo", + "NOTIFICATION": { + "TITLE": "Nouvelle notification | {{'COMMON.APP_NAME'|translate}}", + "HAS_UNREAD": "Vous avez {{count}} notification{{count>0?'s':''}} non lue{{count>0?'s':''}}" + }, "NOTIFICATIONS": { "TITLE": "Notifications", "MARK_ALL_AS_READ": "Tout marquer comme lu", @@ -31,7 +35,7 @@ "ORGANIZATION_ACCOUNT_HELP": "Si vous représentez une entreprise, une association, etc.<br/>Aucun dividende universel ne sera créé par ce compte." }, "EVENT": { - "MEMBER_WITHOUT_PROFILE": "Pour obtenir vos certifications plus rapidement, completez <a ui-sref=\"app.user_edit_profile\">votre profil utilisateur</a>. Les membres accorderont plus facilement leur confiance à une identité vérifiable." + "MEMBER_WITHOUT_PROFILE": "Vous pouvez <a ui-sref=\"app.edit_profile\">saisir votre profil Cesium+</a> (optionnel) pour offrir une meilleure visibilité de votre compte. Ce profil sera stocké dans <b>un annuaire indépendant</b> de la monnaie, mais décentralisé." }, "ERROR": { "WS_CONNECTION_FAILED": "Cesium ne peut pas recevoir les notifications, à cause d'une erreur technique (connexion au noeud de données Cesium+).<br/><br/>Si le problème persiste, veuillez <b>choisir un autre noeud de données</b> dans les paramètres Cesium+." @@ -55,9 +59,9 @@ "DIVIDER_GROUP": "Groupes" }, "CONFIRM": { - "SUGGEST_CERTIFICATIONS": "Etes-vous sûr de vouloir <b>envoyer ces suggestions de certification</b> ?", - "ASK_CERTIFICATION": "Etes-vous sûr de vouloir <b>envoyer une demande de certification</b> ?", - "ASK_CERTIFICATIONS": "Etes-vous sûr de vouloir <b>envoyer une demande de certification</b> à ces personnes ?" + "SUGGEST_CERTIFICATIONS": "Êtes-vous sûr de vouloir <b>envoyer ces suggestions de certification</b> ?", + "ASK_CERTIFICATION": "Êtes-vous sûr de vouloir <b>envoyer une demande de certification</b> ?", + "ASK_CERTIFICATIONS": "Êtes-vous sûr de vouloir <b>envoyer une demande de certification</b> à ces personnes ?" } }, "INVITATION": { @@ -87,14 +91,14 @@ "SUGGESTION_IDENTITIES_MODAL_HELP": "Veuillez choisir vos suggestions :" }, "CONFIRM": { - "DELETE_ALL_CONFIRMATION": "La suppression des invitations est une <b>opération irréversible</b>.<br/><br/><b>Etes-vous sûr</b> de vouloir continuer ?", - "SEND_INVITATIONS_TO_CERTIFY": "Etes-vous sûr de vouloir <b>envoyer cette invitation à certfier</b> ?" + "DELETE_ALL_CONFIRMATION": "La suppression des invitations est une <b>opération irréversible</b>.<br/><br/><b>Êtes-vous sûr</b> de vouloir continuer ?", + "SEND_INVITATIONS_TO_CERTIFY": "Êtes-vous sûr de vouloir <b>envoyer cette invitation à certifier</b> ?" }, "INFO": { "INVITATION_SENT": "Invitation envoyée" }, "ERROR": { - "LOAD_INVITATIONS_FAILED": "Echec du chargement des invitations", + "LOAD_INVITATIONS_FAILED": "Échec du chargement des invitations", "REMOVE_INVITATION_FAILED": "Erreur lors de la suppression de l'invitation", "REMOVE_ALL_INVITATIONS_FAILED": "Erreur lors de la suppression des invitations", "SEND_INVITATION_FAILED": "Erreur lors de l'envoi de l'invitation", @@ -166,12 +170,12 @@ "CONFIRM": { "REMOVE": "Êtes-vous sûr de vouloir <b>supprimer ce message</b> ?<br/><br/>Cette opération est irréversible.", "REMOVE_ALL" : "Êtes-vous sûr de vouloir <b>supprimer tous les messages</b> ?<br/><br/>Cette opération est irréversible.", - "MARK_ALL_AS_READ": "Êtes-vous sûr de vouloir <b>marquer tous les messages comme lu</b> ?", + "MARK_ALL_AS_READ": "Êtes-vous sûr de vouloir <b>marquer tous les messages comme lus</b> ?", "USER_HAS_NO_PROFILE": "Cette identité n'a aucun profil Cesium+. Il se peut qu'elle n'utilise pas l'extension Cesium+, et <b>ne consultera donc pas votre message</b>.<br/><br/>Êtes-vous sûr de vouloir <b>continuer</b> malgré tout ?" }, "INFO": { "MESSAGE_REMOVED": "Message supprimé", - "All_MESSAGE_REMOVED": "Tous les messages ont été supprimé", + "All_MESSAGE_REMOVED": "Tous les messages ont été supprimés", "MESSAGE_SENT": "Message envoyé" }, "ERROR": { @@ -186,7 +190,7 @@ "MARK_AS_READ_FAILED": "Impossible de marquer le message comme 'lu'.", "LOAD_NOTIFICATIONS_FAILED": "Erreur lors de la récupération des notifications de messages.", "REMOVE_All_MESSAGES_FAILED": "Erreur lors de la suppression de tous les messages.", - "MARK_ALL_AS_READ_FAILED": "Erreur lors du marquage des message comme lu.", + "MARK_ALL_AS_READ_FAILED": "Erreur lors du marquage des messages comme lus.", "RECIPIENT_IS_MANDATORY": "Le destinataire est obligatoire." } }, @@ -203,7 +207,7 @@ "TX_SEARCH_FILTER": { "MEMBER_FLOWS": "<b class=\"ion-person\"></b> Entrées/sorties de membres", "EXISTING_TRANSACTION": "<b class=\"ion-card\"></b> Avec transactions", - "PERIOD": "<b class=\"ion-clock\"></b> Entre <b class=\"gray\">{{params[1]|formatDateShort}}</b> ({{params[1]|formatTime}}) et <b class=\"gray\">{{params[2]|formatDateShort}}</b> ({{params[2]|formatTime}})", + "PERIOD": "<b class=\"ion-clock\"></b> Entre <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) et <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", "ISSUER": "<b class=\"ion-android-desktop\"></b> Calculé par <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}", "TX_PUBKEY": "<b class=\"ion-card\"></b> Transactions concernant <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" } @@ -217,7 +221,7 @@ "LOCATION_DIVIDER": "Adresse", "SOCIAL_NETWORKS_DIVIDER": "Réseaux sociaux et site web", "TECHNICAL_DIVIDER": "Informations techniques", - "CREATED_TIME": "Crée {{creationTime|formatFromNow}}", + "CREATED_TIME": "Créé {{creationTime|formatFromNow}}", "NOTIFICATIONS": { "TITLE": "Invitations" }, @@ -236,7 +240,7 @@ "OPEN_GROUP": "Groupe ouvert", "OPEN_GROUP_HELP": "Un groupe ouvert est accessible par n'importe quel membre de la monnaie.", "MANAGED_GROUP": "Groupe administré", - "MANAGED_GROUP_HELP": "un groupe administré est gérer par des administrateurs et des modérateurs, qui peuvent accepter, refuser ou exclure un membre en son sein.", + "MANAGED_GROUP_HELP": "un groupe administré est géré par des administrateurs et des modérateurs, qui peuvent accepter, refuser ou exclure un membre en son sein.", "ENUM": { "OPEN": "Groupe ouvert", "MANAGED": "Groupe administré" @@ -256,7 +260,7 @@ "RECORD_DESCRIPTION_HELP": "Description" }, "ERROR": { - "SEARCH_GROUPS_FAILED": "Echec de la recherche de groupes", + "SEARCH_GROUPS_FAILED": "Échec de la recherche de groupes", "REMOVE_RECORD_FAILED": "Erreur de la suppression du groupe" }, "INFO": { @@ -284,7 +288,7 @@ "BTN_ADVANCED_SEARCH": "Recherche avancée", "BTN_OPTIONS": "Recherche avancée", "TYPE": "Type de page", - "LOCATION_HELP": "Où : Ville, Code postal", + "LOCATION_HELP": "Où : Code postal, Ville", "RESULTS": "Résultats", "RESULT_COUNT_LOCATION": "{{count}} résultat{{count>0?'s':''}}, près de {{location}}", "RESULT_COUNT": "{{count}} résultat{{count>0?'s':''}}", @@ -322,7 +326,7 @@ "RECORD_DESCRIPTION": "Description", "RECORD_DESCRIPTION_HELP": "Description de l'activité", "RECORD_ADDRESS": "Rue", - "RECORD_ADDRESS_HELP": "Rue, batiment...", + "RECORD_ADDRESS_HELP": "Rue, bâtiment...", "RECORD_CITY": "Ville", "RECORD_CITY_HELP": "Ville", "RECORD_SOCIAL_NETWORKS": "Réseaux sociaux et site web", @@ -336,7 +340,7 @@ "ERROR": { "LOAD_CATEGORY_FAILED": "Erreur de chargement de la liste des activités", "LOAD_RECORD_FAILED": "Erreur lors du chargement de la page", - "LOOKUP_RECORDS_FAILED": "Erreur lors de l'execution de la recherche.", + "LOOKUP_RECORDS_FAILED": "Erreur lors de l'exécution de la recherche", "REMOVE_RECORD_FAILED": "Erreur de la suppression de la page", "SAVE_RECORD_FAILED": "Erreur lors de la sauvegarde", "RECORD_NOT_EXISTS": "Page inexistante", @@ -372,11 +376,11 @@ "RESULT_HELP": "<b>Voici le résultat</b> tel que visible sur votre profil :" }, "CONFIRM": { - "DELETE": "Etes-vous sur de vouloir <b>supprimer votre profif Cesium+ ?</b><br/><br/>Cette opération est irréversible." + "DELETE": "Êtes-vous sûr de vouloir <b>supprimer votre profil Cesium+ ?</b><br/><br/>Cette opération est irréversible." }, "ERROR": { "REMOVE_PROFILE_FAILED": "Erreur de suppression du profil", - "LOAD_PROFILE_FAILED": "Erreur de chargement du profil utilisateur.", + "LOAD_PROFILE_FAILED": "Erreur de chargement du profil utilisateur", "SAVE_PROFILE_FAILED": "Erreur lors de la sauvegarde", "INVALID_SOCIAL_NETWORK_FORMAT": "Format non pris en compte : veuillez indiquer une adresse valide.<br/><br/>Exemples :<ul><li>- Une page Facebook (https://www.facebook.com/user)</li><li>- Une page web (http://www.monsite.fr)</li><li>- Une adresse email (joe@dalton.com)</li></ul>", "IMAGE_RESIZE_FAILED": "Erreur lors du redimensionnement de l'image" @@ -397,11 +401,12 @@ "ADDRESS": "Rue", "ADDRESS_HELP": "Rue, complément d'adresse...", "CITY": "Ville", - "CITY_HELP": "Ville, Pays", + "CITY_HELP": "Code postal, Ville, Pays", "DISTANCE": "Distance maximale autour de la ville", "DISTANCE_UNIT": "km", "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", - "SEARCH_HELP": "Ville, Code postal", + "SEARCH_HELP": "Code postal, Ville", + "PROFILE_POSITION": "Position du profil", "MODAL": { "TITLE": "Recherche de l'adresse", "SEARCH_HELP": "Ville, Code postal, Pays", @@ -409,6 +414,7 @@ "POSITION": "Lat/Lon : {{lat}}/{{lon}}" }, "ERROR": { + "CITY_REQUIRED_IF_STREET": "Champ obligatoire (car une rue est saisie)", "REQUIRED_FOR_LOCATION": "Champ obligatoire pour apparaître sur la carte", "INVALID_FOR_LOCATION": "Adresse inconnue", "GEO_LOCATION_FAILED": "Impossible de récupérer votre position. Veuillez utiliser le bouton de recherche.", @@ -423,8 +429,8 @@ "NO_SUBSCRIPTION": "Aucun service utilisé", "SUBSCRIPTION_COUNT": "Services / Abonnements", "EDIT": { - "TITLE": "Services en lignes", - "HELP_TEXT": "Gérer ici vos abonnements et autres services en ligne", + "TITLE": "Services en ligne", + "HELP_TEXT": "Gérez ici vos abonnements et autres services en ligne", "PROVIDER": "Prestataire :" }, "TYPE": { @@ -433,7 +439,7 @@ } }, "CONFIRM": { - "DELETE_SUBSCRIPTION": "Etes-vous sûr de vouloir <b>supprimer cet abonnement</b> ?" + "DELETE_SUBSCRIPTION": "Êtes-vous sûr de vouloir <b>supprimer cet abonnement</b> ?" }, "ERROR": { "LOAD_SUBSCRIPTIONS_FAILED": "Erreur lors du chargement des services en ligne", @@ -453,11 +459,11 @@ } }, "DOCUMENT": { - "HASH": "Hash: ", + "HASH": "Hash : ", "LOOKUP": { "TITLE": "Recherche de documents", "BTN_ACTIONS": "Actions", - "SEARCH_HELP": "issuer:AAA*, time:1508406169", + "SEARCH_HELP": "Emetteur:AAA*, temps:1508406169", "LAST_DOCUMENTS": "Derniers documents", "SHOW_QUERY": "Voir la requête", "HIDE_QUERY": "Masquer la requête", @@ -475,8 +481,8 @@ "REMOVED": "Document supprimé" }, "CONFIRM": { - "REMOVE": "Etes-vous sûr de vouloir <b>supprimer ce document</b> ?", - "REMOVE_ALL": "Etes-vous sûr de vouloir <b>supprimer ces documents</b> ?" + "REMOVE": "Êtes-vous sûr de vouloir <b>supprimer ce document</b> ?", + "REMOVE_ALL": "Êtes-vous sûr de vouloir <b>supprimer ces documents</b> ?" }, "ERROR": { "LOAD_DOCUMENTS_FAILED": "Erreur lors de la recherche de documents", @@ -488,9 +494,10 @@ "PLUGIN_NAME": "Cesium+", "PLUGIN_NAME_HELP": "Profils, notifications, messages privés", "ENABLE_TOGGLE": "Activer l'extension ?", + "ENABLE_REMOTE_STORAGE": "Activer le stockage distant ?", + "ENABLE_REMOTE_STORAGE_HELP": "Permet de stockage (chiffré) de vos paramètres sur les noeuds Cesium+", "ENABLE_MESSAGE_TOGGLE": "Activer les messages privés ?", - "ENABLE_SETTINGS_TOGGLE": "Activer le stockage distant des paramètres ?", - "PEER": "Addresse du nÅ“ud de données", + "PEER": "Adresse du nÅ“ud de données", "POPUP_PEER": { "TITLE" : "NÅ“ud de données", "HELP" : "Saisissez l'adresse du nÅ“ud que vous voulez utiliser :", @@ -499,14 +506,16 @@ "NOTIFICATIONS": { "DIVIDER": "Notifications", "HELP_TEXT": "Activez les types de notifications que vous souhaitez recevoir :", - "ENABLE_TX_SENT": "Notifier les <b>paiement émis</b> ?", + "ENABLE_TX_SENT": "Notifier les <b>paiements émis</b> ?", "ENABLE_TX_RECEIVED": "Notifier les <b>paiements reçus</b> ?", "ENABLE_CERT_SENT": "Notifier les <b>certifications émises</b> ?", - "ENABLE_CERT_RECEIVED": "Notifier les <b>certifications reçues</b> ?" + "ENABLE_CERT_RECEIVED": "Notifier les <b>certifications reçues</b> ?", + "ENABLE_HTML5_NOTIFICATION": "Avertir à chaque nouvelle notification ?", + "ENABLE_HTML5_NOTIFICATION_HELP": "Ouvre une petite fenêtre à chaque nouvelle notification." }, "CONFIRM": { "ASK_ENABLE_TITLE": "Fonctionnalités optionnelles", - "ASK_ENABLE": "L'extension Cesium+ est <b>désactivée</b> dans vos paramètres, rendant inactives les fonctionnalités : <ul><li> <b><i class=\"icon ion-person\"></i> Profils Cesium+</b>;<li> <b><i class=\"icon ion-android-notifications\"></i> Notifications</b>;<li> <b><i class=\"icon ion-email\"></i> Messages privés</b>.<li> <b><i class=\"icon ion-location\"></i> Cartes, etc.</b>.</ul><br/><b>Souhaitez-vous la ré-activer</b> l'extension ?" + "ASK_ENABLE": "L'extension Cesium+ est <b>désactivée</b> dans vos paramètres, rendant inactives les fonctionnalités : <ul><li> <b><i class=\"icon ion-person\"></i> Profils Cesium+</b>;<li> <b><i class=\"icon ion-android-notifications\"></i> Notifications</b>;<li> <b><i class=\"icon ion-email\"></i> Messages privés</b>.<li> <b><i class=\"icon ion-location\"></i> Cartes, etc.</b>.</ul><br/><b>Souhaitez-vous ré-activer</b> l'extension ?" } }, "ES_WALLET": { @@ -519,7 +528,7 @@ "NODE_BMA_DOWN": "Le noeud <b>{{params[0]}}:{{params[1]}}</b> (utilisé par votre noeud ES API) est <b>injoignable</b>.", "NODE_BMA_UP": "Le noeud <b>{{params[0]}}:{{params[1]}}</b> est à nouveau accessible.", "MEMBER_JOIN": "Vous êtes maintenant <b>membre</b> de la monnaie <b>{{params[0]}}</b> !", - "MEMBER_LEAVE": "Vous n'êtes <b>plus membre</b> de la monnaie <b>{{params[0]}}</b>!", + "MEMBER_LEAVE": "Vous n'êtes <b>plus membre</b> de la monnaie <b>{{params[0]}}</b> !", "MEMBER_EXCLUDE": "Vous n'êtes <b>plus membre</b> de la monnaie <b>{{params[0]}}</b>, faute de non renouvellement ou par manque de certifications.", "MEMBER_REVOKE": "La révocation de votre compte a été effectuée. Il ne pourra plus être un compte membre de la monnaie <b>{{params[0]}}</b>.", "MEMBER_ACTIVE": "Votre renouvellement d'adhésion à la monnaie <b>{{params[0]}}</b> a été <b>pris en compte</b>.", @@ -540,7 +549,7 @@ "ES_USE_FALLBACK_NODE": "NÅ“ud de données <b>{{old}}</b> injoignable ou adresse invalide.<br/><br/>Voulez-vous temporairement utiliser le nÅ“ud de données <b>{{new}}</b> ?" }, "ERROR": { - "ES_CONNECTION_ERROR": "NÅ“ud de données <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Cesium va continuer à fonctionner, <b>sans l'extension Cesium+</b> (profils utilisateur, messages privés, cartes et graphiques)<br/><br/>Vérifiez votre connection Internet, ou changer de nÅ“ud de données dans les <a class=\"positive\" ng-click=\"doQuickFix('settings')\">paramètres de l'extension</a>.", + "ES_CONNECTION_ERROR": "NÅ“ud de données <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Cesium va continuer à fonctionner, <b>sans l'extension Cesium+</b> (profils utilisateur, messages privés, cartes et graphiques)<br/><br/>Vérifiez votre connexion Internet, ou changez de nÅ“ud de données dans les <a class=\"positive\" ng-click=\"doQuickFix('settings')\">paramètres de l'extension</a>.", "ES_MAX_UPLOAD_BODY_SIZE": "Le volume des données à envoyer dépasse la limite fixée par le serveur.<br/>Veuillez ré-essayer après avoir, par exemple, supprimer des photos." } } diff --git a/assets/www/plugins/es/i18n/locale-it-IT.json b/assets/www/plugins/es/i18n/locale-it-IT.json new file mode 100644 index 0000000000000000000000000000000000000000..9227ffe45248986fbb5a194d314a71fad97f184a --- /dev/null +++ b/assets/www/plugins/es/i18n/locale-it-IT.json @@ -0,0 +1,535 @@ +{ + "COMMON": { + "CATEGORY": "Categoria", + "CATEGORIES": "Categorie", + "CATEGORY_SEARCH_HELP": "Ricerca", + "LAST_MODIFICATION_DATE": "Aggiornato il ", + "SUBMIT_BY": "Inviato da", + "BTN_PUBLISH": "Pubblicare", + "BTN_PICTURE_DELETE": "Eliminare", + "BTN_PICTURE_FAVORISE": "Predefinito", + "BTN_PICTURE_ROTATE": "Girare", + "BTN_ADD_PICTURE": "Aggiungere foto", + "NOTIFICATIONS": { + "TITLE": "Notifiche", + "MARK_ALL_AS_READ": "Segna tutte come lette", + "NO_RESULT": "Nessuna notifica", + "SHOW_ALL": "Mostrare tutte", + "LOAD_NOTIFICATIONS_FAILED": "Impossibile caricare le notifiche" + } + }, + "MENU": { + "REGISTRY": "Pagine", + "USER_PROFILE": "Mio profilo", + "MESSAGES": "Messaggi", + "NOTIFICATIONS": "Notifiche", + "INVITATIONS": "Inviti" + }, + "ACCOUNT": { + "NEW": { + "ORGANIZATION_ACCOUNT": "Conto per enti", + "ORGANIZATION_ACCOUNT_HELP": "Se rappresenta un'azienda, un'associazione, etc.<br/>Questo conto non potrà creare il Dividendo Universale." + }, + "EVENT": { + "MEMBER_WITHOUT_PROFILE": "Per ottenere sue certificazioni più velocemente, riempire le informazioni<a ui-sref=\"app.edit_profile\">del suo profilo</a>. I membri della rete si fidano più volontieri di profili verificabili." + }, + "ERROR": { + "WS_CONNECTION_FAILED": "Cesium non può ricevere notifiche a causa di un problema tecnico (di conessione al data node Cesium+).<br/><br/>Se il problema persiste, le chiediamo di <b>scegliere un'altro data node</b> nelle impostazioni di Cesium+." + } + }, + "WOT": { + "BTN_SUGGEST_CERTIFICATIONS_DOTS": "Suggerire delle identità da certificare..", + "BTN_ASK_CERTIFICATIONS_DOTS": "Chiedere una certificazione ai membri...", + "BTN_ASK_CERTIFICATION": "Chiedere una certificazione", + "SUGGEST_CERTIFICATIONS_MODAL": { + "TITLE": "Suggerire delle certificazioni", + "HELP": "Scegliere i suoi suggerimenti, aiuti" + }, + "ASK_CERTIFICATIONS_MODAL": { + "TITLE": "Chiedere delle certificazioni", + "HELP": "Selezionare un ricevente" + }, + "SEARCH": { + "DIVIDER_PROFILE": "Conti", + "DIVIDER_PAGE": "Pagine", + "DIVIDER_GROUP": "Gruppi" + }, + "CONFIRM": { + "SUGGEST_CERTIFICATIONS": "E’ sicuro(a) di voler <b>suggerire queste certificazioni</b> ?", + "ASK_CERTIFICATION": " E’ sicuro(a) di voler <b>chiedere una certificazione</b> ?", + "ASK_CERTIFICATIONS": " E’ sicuro(a) di voler <b>chiedere una certificazione</b> a questi membri ?" + }, + }, + "INVITATION": { + "TITLE": "Invitazioni", + "NO_RESULT": "Nessun invito ricevuto", + "BTN_DELETE_ALL": "Cancellare tutti gli inviti", + "BTN_DELETE": "Cancellare l'invito", + "BTN_NEW_INVITATION": "Nuovo invito", + "ASK_CERTIFICATION": "<a href=\"#/app/wot/{{pubkey}}/{{::uid}}\">{{::name||uid}}</a> ti ha chiesto una certificazione", + "SUGGESTION_CERTIFICATION": "<a href=\"#/app/wot/{{::pubkey}}/{{::uid}}\">{{::name||uid}}</a> è proposto per ricevere una certificazione", + "SUGGESTED_BY": "Suggerimento inviato da by <a class=\"positive\" href=\"#/app/wot/{{::issuer.pubkey}}/{{::issuer.uid}}\">{{::issuer.name||issuer.uid}}</a>", + "NOTIFICATIONS": { + "TITLE": "Inviti" + }, + "LIST": { + "TITLE": "Inviti" + }, + "NEW": { + "TITLE": "Nuovo invito", + "RECIPIENTS": "A", + "RECIPIENTS_HELP": "Riceventi dell'invito", + "RECIPIENTS_MODAL_TITLE": "Riceventi", + "RECIPIENTS_MODAL_HELP": "Scegliere riceventi:", + "SUGGESTION_IDENTITIES": "Suggerimenti di identità da certificare", + "SUGGESTION_IDENTITIES_HELP": "Suggerimenti di certificazioni", + "SUGGESTION_IDENTITIES_MODAL_TITLE": "Suggerimenti", + "SUGGESTION_IDENTITIES_MODAL_HELP": "Scegli tuoi sugerimenti:" + }, + "CONFIRM": { + "DELETE_ALL_CONFIRMATION": "Cancellare degli inviti è <b>una operazione irreversibile</b>.<br/><br/><b>Sei sicuro/a</b> di voler proseguire", + "SEND_INVITATIONS_TO_CERTIFY": "<b>Sei sicuro/a</b> di voler <b>inviare questo suggerimento di certificazione</b> ?" + }, + "INFO": { + "INVITATION_SENT": "Invito inviato" + }, + "ERROR": { + "LOAD_INVITATIONS_FAILED": "Errore nel caricare gli inviti", + "REMOVE_INVITATION_FAILED": "Errore nel cancellare gli inviti", + "REMOVE_ALL_INVITATIONS_FAILED": "Errore nel cancellare inviti", + "SEND_INVITATION_FAILED": "Errore nel invio degli inviti", + "BAD_INVITATION_FORMAT": "<span class=\"assertive\"><i class=\"ion-close-circled\"></i> Invito illegibile (formatto sconosciuto)</span> - inviato da <a ui-sref=\"app.wot_identity({pubkey: '{{::pubkey}}', uid: '{{::uid}}' })\">{{::name||uid}}</a>" + } + }, + "COMMENTS": { + "DIVIDER": "Commenti", + "SHOW_MORE_COMMENTS": "Mostrare commenti precedenti", + "COMMENT_HELP": "Suo commento o domanda...", + "COMMENT_HELP_REPLY_TO": "Sua risposta...", + "BTN_SEND": "Inviare", + "POPOVER_SHARE_TITLE": "Messaggio #{{number}}", + "REPLY": "Rispondere", + "REPLY_TO": "Rispondere a:", + "REPLY_TO_LINK": "In risposta a", + "REPLY_TO_DELETED_COMMENT": "In risposta ad un commento cancellato", + "REPLY_COUNT": "{{replyCount}} risposte", + "DELETED_COMMENT": "Commento cancellato", + "ERROR": { + "FAILED_SAVE_COMMENT": "Salvare il commento cancellato", + "FAILED_REMOVE_COMMENT": "Cancellazione del commento fallita" + } + }, + "MESSAGE": { + "REPLY_TITLE_PREFIX": "Re: ", + "FORWARD_TITLE_PREFIX": "Fw: ", + "BTN_REPLY": "Rispondere", + "BTN_COMPOSE": "Nuovo messaggio", + "BTN_WRITE": "Scrivere", + "NO_MESSAGE_INBOX": "Nessun messaggio ricevuto", + "NO_MESSAGE_OUTBOX": "Nessun messaggio inviato", + "NOTIFICATIONS": { + "TITLE": "Messaggi", + "MESSAGE_RECEIVED": "Hai <b>ricevuto un messaggio/b><br/>da" + }, + "LIST": { + "INBOX": "In entrata", + "OUTBOX": "In uscita", + "TITLE": "Messaggi privati", + "POPOVER_ACTIONS": { + "TITLE": "Opzioni", + "DELETE_ALL": "Eliminare tutti i messaggi" + } + }, + "COMPOSE": { + "TITLE": "Nuovo messaggio", + "TITLE_REPLY": "Rispondere", + "SUB_TITLE": "Nuovo messaggio", + "TO": "A", + "OBJECT": "Oggetto", + "OBJECT_HELP": "Oggetto", + "ENCRYPTED_HELP": "La informiamo che questo messaggio verrà criptato prima della sua spedizione in modo che solo il destinatario lo possa leggere e essere sicuro che ne sia Lei l'autore.", + "MESSAGE": "Messaggio", + "MESSAGE_HELP": "Contenuto del messaggio", + "CONTENT_CONFIRMATION": "Nessun contenuto. <br/><br/>E’ sicura di voler inviare questo messaggio?" + }, + "VIEW": { + "TITLE": "Messaggio", + "SENDER": "Inviato da", + "RECIPIENT": "Inviato a", + "NO_CONTENT": "Messaggio vuoto", + "DELETE": "Cancellare il messaggio" + }, + "CONFIRM": { + "REMOVE": "E’ sicuro/a di voler <b>eliminare il messaggio</b>?<br/><br/> Questa operazione è irreversibile.", + "REMOVE_ALL": "E’ sicuro/a di voler <b>eliminare tutti i messaggi</b>?<br/><br/> Questa operazione è irreversibile.", + "MARK_ALL_AS_READ": "E’ sicuro/a di voler <b>segnare tutti i messaggi come letti/b>?", + "USER_HAS_NO_PROFILE": "Questa identità non ha un profilo Cesium+. Pertanto non può <b>leggere il suo messaggio</b>.<br/><br/>E’ sicuro/a di voler <b>continuare</b>?" + }, + "INFO": { + "MESSAGE_REMOVED": "Messaggio eliminato correttamente", + "All_MESSAGE_REMOVED": "Messaggi eliminati correttamente", + "MESSAGE_SENT": "Messaggio inviato" + }, + "ERROR": { + "SEND_MSG_FAILED": "Errore nella spedizione del messaggio.", + "LOAD_MESSAGES_FAILED": "Errore durante il caricamento dei messaggi.", + "LOAD_MESSAGE_FAILED": "Errore durante il caricamento del messaggio.", + "MESSAGE_NOT_READABLE": "Impossibile leggere il messaggio.", + "USER_NOT_RECIPIENT": "Lei non è il destinatario del messaggio: impossibile leggerlo.", + "NOT_AUTHENTICATED_MESSAGE": "Impossibile verificare l'autenticità del messaggio o contenuto corrotto.", + "REMOVE_MESSAGE_FAILED": "Errore avvenuto durante l'eliminazione del messaggio", + "MESSAGE_CONTENT_TOO_LONG": "Il contenuto supera il limite ({{maxLength}} caratteri ammessi).", + "MARK_AS_READ_FAILED": "Impossibile segnare il messaggio come 'letto'.", + "LOAD_NOTIFICATIONS_FAILED": "Errore nel caricare le notifiche.", + "REMOVE_All_MESSAGES_FAILED": "Errore avvenuto durante l'eliminazione dei messaggi.", + "MARK_ALL_AS_READ_FAILED": "Errore avvenuto nel segnare i messaggi come 'letti", + "RECIPIENT_IS_MANDATORY": "Destinatario obbligatorio" + } + }, + "BLOCKCHAIN": { + "LOOKUP": { + "SEARCH_HELP": "Numero di blocco, hash...", + "POPOVER_FILTER_TITLE": "Filtro", + "HEADER_MEDIAN_TIME": "Data / Ora", + "HEADER_BLOCK": "Blocco #", + "HEADER_ISSUER": "Peer proprietario", + "BTN_LAST": "Ultimi blocchi", + "DISPLAY_QUERY": "Visualizzare query", + "HIDE_QUERY": "Nascondere query", + "TX_SEARCH_FILTER": { + "MEMBER_FLOWS": "<b class=\"ion-person\"></b> Input/output Membri", + "EXISTING_TRANSACTION": "<b class=\"ion-card\"></b> hanno transazioni", + "PERIOD": "<b class=\"ion-clock\"></b> Tra <b class=\"gray\">{{params[1]|medianDateShort}}</b> ({{params[1]|medianTime}}) e <b class=\"gray\">{{params[2]|medianDateShort}}</b> ({{params[2]|medianTime}})", + "ISSUER": "<b class=\"ion-android-desktop\"></b> Calcolato da {{params[1]|formatPubkey}}", + "TX_PUBKEY": "<b class=\"ion-card\"></b> Transazioni legate a <b class=\"ion-key\"></b> {{params[1]|formatPubkey}}" + } + }, + "ERROR": { + "SEARCH_BLOCKS_FAILED": "Errore durante la ricerca dei blocchi." + } + }, + "GROUP": { + "GENERAL_DIVIDER": "Informazioni generali", + "LOCATION_DIVIDER": "Indirizzo", + "SOCIAL_NETWORKS_DIVIDER": "Presenza sui social e/o sito web", + "TECHNICAL_DIVIDER": "Dati tecnici", + "CREATED_TIME": "Creato {{creationTime|formatFromNow}}", + "NOTIFICATIONS": { + "TITLE": "Inviti" + }, + "LOOKUP": { + "TITLE": "Gruppi", + "SEARCH_HELP": "Nome del grupo, parole chiavi, luogo, etc.", + "LAST_RESULTS_LIST": "Nuovi gruppi :", + "OPEN_RESULTS_LIST": "Gruppi aperti :", + "MANAGED_RESULTS_LIST": "Gruppi chiusi :", + "BTN_LAST": "Nuovi gruppi", + "BTN_NEW": "Aggiungo un grupo!" + }, + "TYPE": { + "TITLE": "Nuovo gruppo", + "SELECT_TYPE": "Tipo di gruppo :", + "OPEN_GROUP": "Gruppo aperto", + "OPEN_GROUP_HELP": "Un gruppo aperto è accessibile da qualsiasi membro della moneta.", + "MANAGED_GROUP": "Gruppo amministrato", + "MANAGED_GROUP_HELP": "un gruppo amministrato è gestito da amministratori e moderatori, che possono accetare, rifiutare o escludere membri del gruppo.", + "ENUM": { + "OPEN": "Gruppo aperto", + "MANAGED": "Gruppo amministrato" + } + }, + "VIEW": { + "POPOVER_SHARE_TITLE": "{{title}}", + "MENU_TITLE": "Opzioni", + "REMOVE_CONFIRMATION" : "Sei sicuro/a di voler chiudere questo gruppo ?<br/><br/>Questa operazione è irreversibile." + }, + "EDIT": { + "TITLE": "Gruppo", + "TITLE_NEW": "Nuovo gruppo", + "RECORD_TITLE": "Titolo", + "RECORD_TITLE_HELP": "Titolo", + "RECORD_DESCRIPTION": "Descrizione", + "RECORD_DESCRIPTION_HELP": "Descrizione" + }, + "ERROR": { + "SEARCH_GROUPS_FAILED": "Errore nella ricerca di gruppi", + "REMOVE_RECORD_FAILED": "Errore nel chiudere il gruppo" + }, + "INFO": { + "RECORD_REMOVED" : "Gruppo eliminato" + } + }, + "REGISTRY": { + "CATEGORY": "Attività principale", + "GENERAL_DIVIDER": "Informazioni di base", + "LOCATION_DIVIDER": "Indirizzo", + "SOCIAL_NETWORKS_DIVIDER": "Presenza sui social, sito web", + "TECHNICAL_DIVIDER": "Dati tecnici", + "BTN_SHOW_WOT": "Persone", + "BTN_SHOW_WOT_HELP": "Cercare persone", + "BTN_SHOW_PAGES": "Pagine", + "BTN_SHOW_PAGES_HELP": "Cercare pagine", + "BTN_NEW": "Aggiungere", + "MY_PAGES": "Mie pagine", + "NO_PAGE": "Nessuna pagina", + "SEARCH": { + "TITLE": "Pagine", + "SEARCH_HELP": "Che, chi: parrucchiere, Pizza Efisio, ...", + "BTN_ADD": "Nuovo", + "BTN_LAST_RECORDS": "Pagine recenti", + "BTN_ADVANCED_SEARCH": "Ricerca avanzata", + "BTN_OPTIONS": "Ricerca avanzata", + "TYPE": "Tipo di ente", + "LOCATION_HELP": "Città ", + "RESULTS": "Risultati", + "RESULT_COUNT_LOCATION": "{{count}} risultato{{count>0?'i':''}}, vicino a {{location}}", + "RESULT_COUNT": "{{count}} risultato{{count>0?'i':''}}", + "LAST_RECORDS": "Pagine recenti:", + "LAST_RECORD_COUNT_LOCATION": "{{count}} pagina{{count>0?'e':''}} recente{{count>0?'i':''}}, vicino a{{location}}", + "LAST_RECORD_COUNT": "{{count}} pagina{{count>0?'e':''}} recente{{count>0?'i':''}}", + "POPOVER_FILTERS": { + "BTN_ADVANCED_SEARCH": "Opzioni avanzate ?" + } + }, + "VIEW": { + "TITLE": "Annuario", + "CATEGORY": "Attività principale:", + "LOCATION": "Indirizzo:", + "MENU_TITLE": "Impostazioni", + "POPOVER_SHARE_TITLE": "{{title}}", + "REMOVE_CONFIRMATION" : "E’ sicuro/a di voler eliminare questo riferimento?<br/><br/>Questa operazione è irreversibile." + }, + "TYPE": { + "TITLE": "Nuovo riferimento", + "SELECT_TYPE": "Tipo di ente/organismo:", + "ENUM": { + "SHOP": "Negozi locali", + "COMPANY": "Azienda", + "ASSOCIATION": "Associazione", + "INSTITUTION": "Istituto" + } + }, + "EDIT": { + "TITLE": "Modificare", + "TITLE_NEW": "Nuovo riferimento", + "RECORD_TYPE": "Tipo di ente", + "RECORD_TITLE": "Nome", + "RECORD_TITLE_HELP": "Nome", + "RECORD_DESCRIPTION": "Descrizione", + "RECORD_DESCRIPTION_HELP": "Descrivere l'attività ", + "RECORD_ADDRESS": "Indirizzo", + "RECORD_ADDRESS_HELP": "Indirizzo: Strada, numero civico...", + "RECORD_CITY": "Città ", + "RECORD_CITY_HELP": "Città , Paese", + "RECORD_SOCIAL_NETWORKS": "Presenza sui social e/o sito web", + "RECORD_PUBKEY": "Chiave pubblica", + "RECORD_PUBKEY_HELP": "Chiave pubblica per ricevere pagamenti" + }, + "WALLET": { + "REGISTRY_DIVIDER": "Pagine", + "REGISTRY_HELP": "Le pagine sono un elenco dei profesionisti che accettano o favoriscono: negozi, aziende, associazioni, istituti..." + }, + "ERROR": { + "LOAD_CATEGORY_FAILED": "Errore nel caricamento delle attività principali", + "LOAD_RECORD_FAILED": "Caricamento fallito", + "LOOKUP_RECORDS_FAILED": "Errore nel caricare i dati", + "REMOVE_RECORD_FAILED": "Errore nella cancellazione", + "SAVE_RECORD_FAILED": "Impossibile salvare", + "RECORD_NOT_EXISTS": "Inesistente", + "GEO_LOCATION_NOT_FOUND": "Città o CAP inesistente" + }, + "INFO": { + "RECORD_REMOVED" : "Pagina eliminata con successo.", + "RECORD_SAVED": "Pagina salvata" + } + }, + "PROFILE": { + "PROFILE_DIVIDER": "Profilo Cesium+", + "PROFILE_DIVIDER_HELP": "Si tratta qui di data esterni, salvati fuori della rete della moneta.", + "NO_PROFILE_DEFINED": "Nessun profilo Cesium+", + "BTN_ADD": "Creare mio profilo", + "BTN_EDIT": "Modificare mio profilo", + "UID": "Pseudonimo", + "TITLE": "Cognome, Nome", + "TITLE_HELP": "Nome", + "DESCRIPTION": "A proposito di me", + "DESCRIPTION_HELP": "A proposito di me...", + "SOCIAL_HELP": "http://...", + "GENERAL_DIVIDER": "Informazioni generali", + "SOCIAL_NETWORKS_DIVIDER": "Presenza sui social e sito/i web", + "TECHNICAL_DIVIDER": "Dati tecnici", + "MODAL_AVATAR": { + "TITLE": "Avatar", + "SELECT_FILE_HELP": "<b>Scegliere un'immagine</b>, cliccando sul bottone qui sotto:", + "BTN_SELECT_FILE": "Scegliere un'immagine", + "RESIZE_HELP": "<b>Ritagliare l'immagine</b> se necessario. Cliccare sull'immagine permette di spostarla. Cliccando nella zona a basso sinistra permette di fare uno zoom-in.", + "RESULT_HELP": "<b>Questo è il risultato</b> come visibile sul suo profilo:" + }, + "ERROR": { + "LOAD_PROFILE_FAILED": "Impossibile caricare il profilo dell’utente.", + "SAVE_PROFILE_FAILED": "Impossibile salvare il profilo", + "INVALID_SOCIAL_NETWORK_FORMAT": "Formatto scorretto: URL sbagliato.<br/><br/>Esempi: :<ul><li>- Una pagina Facebook (https://www.facebook.com/user)</li><li>- Un sito: (http://www.domain.com)</li><li>- Un indirizzo mail: (joe@dalton.com)</li></ul>", + "IMAGE_RESIZE_FAILED": "Errore nel ritagliare l'immagine" + }, + "INFO": { + "PROFILE_SAVED": "Profilo salvato" + }, + "HELP": { + "WARNING_PUBLIC_DATA": "La informiamo che le informazioni qui pubblicate <b>sono pubbliche</b>: sono anche visibili <b>da gente non registrata/b>." + } + }, + "LOCATION": { + "BTN_GEOLOC_ADDRESS": "Trovare mio indirizzo sulla mappa", + "USE_GEO_POINT": "Geo-localizzare (raccomandato)?", + "LOADING_LOCATION": "Cercando indirizzo...", + "LOCATION_DIVIDER": "Posizione", + "ADDRESS": "Indirizzo", + "ADDRESS_HELP": "Indirizzo (opzionale)", + "CITY": "Città ", + "CITY_HELP": "Città , Paese", + "DISTANCE": "Distanza massimale intorno alla città ", + "DISTANCE_UNIT": "km", + "DISTANCE_OPTION": "{{value}} {{'LOCATION.DISTANCE_UNIT'|translate}}", + "SEARCH_HELP": "Città , CAP", + "MODAL": { + "TITLE": "Cercare indirizzo", + "SEARCH_HELP": "Città , Paese", + "ALTERNATIVE_RESULT_DIVIDER": "Risultati alternativi <b>{{address}}</b>:", + "POSITION": "lat/lon : {{lat}} {{lon}}" + }, + "ERROR": { + "REQUIRED_FOR_LOCATION": "Campo obbligatorio per apparire sulla mappa", + "INVALID_FOR_LOCATION": "Indirizzo sconosciuto", + "GEO_LOCATION_FAILED": "Impossibile trovare sua posizione. Utilizzi il bottone di ricerca.", + "ADDRESS_LOCATION_FAILED": "Indirizzo non trovato" + } + }, + "SUBSCRIPTION": { + "SUBSCRIPTION_DIVIDER": "Servizi online", + "SUBSCRIPTION_DIVIDER_HELP": "I servizi online offrono servizi addizionali opzionali, delegati ad terzi.", + "BTN_ADD": "Aggiungere un servizio", + "BTN_EDIT": "Gestire miei servizi", + "NO_SUBSCRIPTION": "Nessun servizio utilizzato", + "SUBSCRIPTION_COUNT": "Servizi/ Abbonamenti", + "EDIT": { + "TITLE": "Servizi online", + "HELP_TEXT": "Qui si possono gestire gli abbonamenti e/o altri servizi online", + "PROVIDER": "Prestatore :" + }, + "TYPE": { + "ENUM": { + "EMAIL": "Ricevere notifiche per posta elettronica" + } + }, + "CONFIRM": { + "DELETE_SUBSCRIPTION": "Sei sicuro/a di voler <b>cancellare questo abbonamento</b> ?" + }, + "ERROR": { + "LOAD_SUBSCRIPTIONS_FAILED": "Errore nel caricamento dei servizi online", + "ADD_SUBSCRIPTION_FAILED": "Errore nel invio dell' abbonamento", + "UPDATE_SUBSCRIPTION_FAILED": "Errore nel aggiornamento dell' abbonamento", + "DELETE_SUBSCRIPTION_FAILED": "Errore nella cancellazine dell' abbonamento" + }, + "MODAL_EMAIL": { + "TITLE" : "Notifiche per posta elettronica", + "HELP" : "Riempi questo formulario per <b>essere notificato/a per e-mail</b> degli eventi che avvengono sul tuo conto.<br/>Tuo indizzo mail sarà cifrato e solo il prestatore del servizio lo potrà vedere.", + "EMAIL_LABEL" : "Tuo indirizzo mail :", + "EMAIL_HELP": "cristiana.leonardi@dominio.com", + "FREQUENCY_LABEL": "Frequenza delle notifiche :", + "FREQUENCY_DAILY": "Quotidiano", + "FREQUENCY_WEEKLY": "Settimanale", + "PROVIDER": "Prestatore del servizio :" + } + }, + "DOCUMENT": { + "HASH": "Hash: ", + "LOOKUP": { + "TITLE": "Ricerca di documenti", + "BTN_ACTIONS": "Azioni", + "SEARCH_HELP": "issuer:AAA*, time:1508406169", + "LAST_DOCUMENTS": "Ultimi documenti", + "SHOW_QUERY": "Visualizzare la richiesta", + "HIDE_QUERY": "Nacondere la richiesta", + "HEADER_TIME": "Data/Ora", + "HEADER_ISSUER": "Emittente", + "HEADER_RECIPIENT": "Destinatario", + "READ": "Letto", + "BTN_REMOVE": "Eliminare questo documento", + "POPOVER_ACTIONS": { + "TITLE": "Azioni", + "REMOVE_ALL": "Eliminare questi documenti..." + } + }, + "INFO": { + "REMOVED": "Documento eliminato" + }, + "CONFIRM": { + "REMOVE": "Sei sicuro/a di voler <b>eliminare questo documento</b> ?", + "REMOVE_ALL": "Si sicuro/a di voler <b>eliminare questi documenti</b> ?" + }, + "ERROR": { + "LOAD_DOCUMENTS_FAILED": "Errore nella ricerca dei documenti", + "REMOVE_FAILED": "Errore nell'eliminazione del documento", + "REMOVE_ALL_FAILED": "Errore nell'eliminazione dei documenti" + } + }, + "ES_SETTINGS": { + "PLUGIN_NAME": "Cesium+", + "PLUGIN_NAME_HELP": "Profili di utenti, notifiche, messaggi privati", + "ENABLE_TOGGLE": "Abilitare l'estensione ?", + "ENABLE_MESSAGE_TOGGLE": "Abilitare i messaggi? privati", + "ENABLE_SETTINGS_TOGGLE": "Abilitare stoccaggio su dispositivi esterni per le impostazioni?", + "PEER": "Indirizzo di data peers", + "POPUP_PEER": { + "TITLE" : "Data peer", + "HELP" : "Definire l'indirizzo da usare per il peer:", + "PEER_HELP": "server.domain.com:port" + }, + "NOTIFICATIONS": { + "DIVIDER": "Notifiche", + "HELP_TEXT": "Scegliere le notifiche che accetta ricevere:", + "ENABLE_TX_SENT": "Notificarmi di <b>pagamenti inviati</b> con successo?", + "ENABLE_TX_RECEIVED": "Notificarmi di <b>pagamenti in entrata</b>?", + "ENABLE_CERT_SENT": "Notificarmi delle <b>certificazioni inviate</b>?", + "ENABLE_CERT_RECEIVED": "Notificarmi di <b>certificazioni ricevute</b>?" + }, + "CONFIRM": { + "ASK_ENABLE_TITLE": "Nuove funzionalità ", + "ASK_ENABLE": "Sono disponibili nuove funzionalità : <ul><li> <b><i class=\"icon ion-person\"></i>Profili di utenti</b>;<li> <b><i class=\"icon ion-android-notifications\"></i> Notifications</b>;<li> <b><i class=\"icon ion-email\"></i> Messaggi privati/b>.</ul><br/>Sono state <b>disabilitate</b> nelle sue impostazioni.<br/><br/><b>Desidera abilitare</b> queste funzionalità ?" + } + }, + "ES_WALLET": { + "ERROR": { + "RECIPIENT_IS_MANDATORY": "Un destinatario è necessario per il criptaggio." + } + }, + "EVENT": { + "NODE_STARTED": "Suo nodo ES API <b>{{params[0]}}</b> è UP", + "NODE_BMA_DOWN": "Nodo<b>{{params[0]}}:{{params[1]}}</b> (utilizzato dal suo ES API) è <b>indisponibile</b>.", + "NODE_BMA_UP": "Nodo <b>{{params[0]}}:{{params[1]}}</b> è di nuovo attivo.", + "MEMBER_JOIN": "E diventato <b>membro/a</b> della WoT della moneta <b>{{params[0]}}</b>!", + "MEMBER_LEAVE": "Non <b>è più membro/a</b> della WoT della moneta <b>{{params[0]}}</b>!", + "MEMBER_EXCLUDE": "Non è <b>più membro/a</b> della WoT della moneta<b>{{params[0]}}</b>, a causa di certificazioni non rinnovate o soglia di certificazioni non raggiunta.", + "MEMBER_REVOKE": "Il suo conto è stato revocato. Da ora in poi non farà più parte della WoT. <b>{{params[0]}}</b>.", + "MEMBER_ACTIVE": "La sua presenza nella WoT <b>{{params[0]}}</b> è stata <b>rinnovata correttamente</b>.", + "TX_SENT": "Il suo pagamento <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\" ><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> è stato eseguito.", + "TX_SENT_MULTI": "Il suo pagamento <b>{{params[1]}}</b> è stato eseguito.", + "TX_RECEIVED": "Ha ricevuto un pagamento da <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span>.", + "TX_RECEIVED_MULTI": "Ha ricevuto un pagamento da <b>{{params[1]}}</b>.", + "CERT_SENT": "Sua <b>certificazione</b> a favore di <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\" ><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> è stata eseguita.", + "CERT_RECEIVED": "Ha ricevuto <b>una certificazione</b> da parte di <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span>.", + "REGISTRY": { + "NEW_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> ha scritto un commento sul suo riferimento: <b>{{params[2]}}</b>", + "UPDATE_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> ha modificato il suo commento sul suo riferimento: <b>{{params[2]}}</b>", + "NEW_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> ha risposto al suo commento sul riferimento: <b>{{params[2]}}</b>", + "UPDATE_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> ha modificato sua risposta sul suo commento a proposito del riferimento: <b>{{params[2]}}</b>" + } + }, + "CONFIRM": { + "ES_USE_FALLBACK_NODE": "Nodo<b>{{old}}</b> irraggiungibile o indirizzo sbagliato.<br/><br/>Vuoi utilizzare temporaneamente il nodo di dati <b>{{new}}</b> ?" + }, + "ERROR": { + "ES_CONNECTION_ERROR": "Nodo di dati<b>{{server}}</b> irraggiungibile o indirizzo sbagliato.<br/><br/>Cesium continuerà a funzionare <b>senza l'estensione Cesium+</b> (profili utenti, messaggi privati, mappe e grafici)<br/><br/>Verifica tua connessione o cambia nodo <a class=\"positive\" ng-click=\"doQuickFix('settings')\">impostazioni dell'estensione</a>.", + "ES_MAX_UPLOAD_BODY_SIZE": "Il volume di data da inviare supera il limite imposto dal server.<br/><br/>Suggeriamo di riprovare dopo aver eliminato delle foto, per esempio." + } + } diff --git a/assets/www/plugins/es/i18n/locale-nl-NL.json b/assets/www/plugins/es/i18n/locale-nl-NL.json index c8f0e3494285999753271758a8234985167c5bb9..4d6894532f95f2ca1ed53cf4deb280bbd7e2572a 100644 --- a/assets/www/plugins/es/i18n/locale-nl-NL.json +++ b/assets/www/plugins/es/i18n/locale-nl-NL.json @@ -3,7 +3,7 @@ "CATEGORY": "Categorie", "CATEGORIES": "Categorieën", "CATEGORY_SEARCH_HELP": "Zoeken", - "LAST_MODIFICATION_DATE": "Vernieuws op ", + "LAST_MODIFICATION_DATE": "Vernieuwd op ", "SUBMIT_BY": "Ingediend door", "BTN_PUBLISH": "Publiceren", "BTN_PICTURE_DELETE": "Wissen", @@ -18,22 +18,22 @@ } }, "MENU": { - "REGISTRY": "Ondernemingen", + "REGISTRY": "Pagina's", "USER_PROFILE": "Mijn profiel", "MESSAGES": "Berichten" }, "ACCOUNT": { "NEW": { "ORGANIZATION_ACCOUNT": "Ondernemingsrekening", - "ORGANIZATION_ACCOUNT_HELP": "Als je een onderneming, vereniging etc. vertegenwoordigd.<br/>Deze rekening zal geen dividend créeren." + "ORGANIZATION_ACCOUNT_HELP": "Als je een onderneming, vereniging etc. vertegenwoordigt.<br/>Deze rekening zal geen dividend créeren." }, "EVENT": { - "MEMBER_WITHOUT_PROFILE": "Vul <a ui-sref=\"app.user_edit_profile\"je gebruikersprofiel</a> in om sneller een certificering te verkrijgen. Leden zullen een verfifieerbare identiteit eerder vertrouwen." + "MEMBER_WITHOUT_PROFILE": "Vul <a ui-sref=\"app.edit_profile\"je gebruikersprofiel</a> in om sneller een certificering te verkrijgen. Leden zullen een verfifieerbare identiteit eerder vertrouwen." } }, "COMMENTS": { "DIVIDER": "Commentaren", - "SHOW_MORE_COMMENTS": "Toon eerder commentaren", + "SHOW_MORE_COMMENTS": "Toon eerdere commentaren", "COMMENT_HELP": "Jouw commentaar, vraag...", "COMMENT_HELP_REPLY_TO": "Jouw antwoord...", "BTN_SEND": "Verzenden", @@ -102,7 +102,7 @@ "USER_NOT_RECIPIENT": "Je bent niet de geadresseerde van dit bericht: het kan niet gelezen worden.", "NOT_AUTHENTICATED_MESSAGE": "De authenticiteit van het bericht is onduidelijk of de inhoud is gecorrumpeerd.", "REMOVE_MESSAGE_FAILED": "Kan bericht niet wissen.", - "MESSAGE_CONTENT_TOO_LONG": "Waarde te land (max {{maxLength}} characters).", + "MESSAGE_CONTENT_TOO_LONG": "Waarde te lang (max {{maxLength}} characters).", "MARK_AS_READ_FAILED": "Kan bericht niet als gelezen markeren.", "LOAD_NOTIFICATIONS_FAILED": "Kan niet alle berichtnotificaties laden.", "REMOVE_All_MESSAGES_FAILED": "Kan niet alle berichten wissen.", @@ -222,14 +222,14 @@ "ENABLE_CERT_RECEIVED": "Bericht bij validatie van <b>ontvangen certificaties</b>?" }, "CONFIRM": { - "ASK_ENABLE_TITLE": "Nieuwe functies", - "ASK_ENABLE": "Er zijn nieuwe functies beschikbaar: <ul><li> <b><i class=\"icon ion-person\"></i> Profile Cesium+</b>;<li> <b><i class=\"icon ion-android-notifcaitions\"></i> Notifications</b>;<li> <b><i class=\"icon ion-email\"></i> Privé berichten</b>.</ul><br/>Deze zijn <b>uitgeschakeld</b> in je instellingen.<br/><br/>Wil je deze functies <b>inschakelen</b>?" + "ASK_ENABLE_TITLE": "Optionele functies", + "ASK_ENABLE": "Cesium+ is <b>uitgeschakeld</b> waardoor deze functies niet beschikbaar zijn: <ul><li> <b><i class=\"icon ion-person\"></i> Gebruikersprofielen</b>;<li> <b><i class=\"icon ion-android-notifcaitions\"></i> Notificaties</b>;<li> <b><i class=\"icon ion-email\"></i> Privéberichten</b>.</ul><br/><br/>Wil je deze functies <b>inschakelen</b>?" } }, "EVENT": { "NODE_STARTED": "Je knoop ES API <b>{{params[0]}}</b> is UP", "NODE_BMA_DOWN": "Knooppunt <b>{{params[0]}}:{{params[1]}}</b> (gebruikt door je ES API) is <b>onbereikbaar</b>.", - "NODE_BMA_UP": "Knooppunt <b>{{p0}}:{{params[1]}}</b> is weer onbereikbaar.", + "NODE_BMA_UP": "Knooppunt <b>{{p0}}:{{params[1]}}</b> is weer bereikbaar.", "MEMBER_JOIN": "Je bent nu <b>lid</b> van valuta <b>{{params[0]}}</b>!", "MEMBER_LEAVE": "Je bent <b>geen lid meer</b> van valuta <b>{{params[0]}}</b>!", "MEMBER_ACTIVE": "Je lidmaatschap bij <b>{{params[0]}}</b> is met <b>succes verlengd</b>.", @@ -245,5 +245,12 @@ "NEW_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> hheeft gereageerd op jouw commentaar op referentie: <b>{{params[2]}}</b>", "UPDATE_REPLY_COMMENT": "<span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid }\"><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> heeft zijn/haar reactie op jouw commentaar bewerkt, op referentie: <b>{{params[2]}}</b>" } + }, + "CONFIRM": { + "ES_USE_FALLBACK_NODE": "Knooppunt <b>{{old}}</b> onbereikbaar of ongeldig adres.<br/><br/>Tijdelijk knooppunt <b>{{new}}</b> gebruiken?" + }, + "ERROR": { + "ES_CONNECTION_ERROR": "Knooppunt <b>{{server}}</b> onbereikbaar of ongeldig adres.<br/><br/>Cesium zal verder weken, <b>zonder de Cesium+ uitbreiding</b> (gebruikersprofielens, privéberichten, kaarten en grafieken).<br/><br/>Controleer je internetverbinding, of verander je knooppunt in <a class=\"positive\" ng-click=\"doQuickFix('settings')\">instellingen</a>.", + "ES_MAX_UPLOAD_BODY_SIZE": "De hoveelheid te verzenden gegevens is overschrijdt de serverlimiet.<br/><br/>Probeer het nogmaals na, bijvoorbeeld, het wissen foto's." } } diff --git a/assets/www/plugins/es/js/controllers/app-controllers.js b/assets/www/plugins/es/js/controllers/app-controllers.js index b593797c990e9706b40abbdb75bfc167f46a23a9..c324806e7c6cdf300d218a49d42863cc69c43a82 100644 --- a/assets/www/plugins/es/js/controllers/app-controllers.js +++ b/assets/www/plugins/es/js/controllers/app-controllers.js @@ -53,26 +53,35 @@ function ESExtensionController($scope, esSettings, PluginService) { $scope.enable = esSettings.isEnable(); esSettings.api.state.on.changed($scope, function(enable) { $scope.enable = enable; + $scope.$broadcast('$$rebind::state'); }); } /** * Control menu extension */ -function ESMenuExtendController($scope, $state, PluginService, esSettings, UIUtils, csWallet) { +function ESMenuExtendController($scope, $state, $controller, UIUtils, csWallet) { 'ngInject'; - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); + + // Initialize the super class and extend it. + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); $scope.showRegistryLookupView = function() { - $state.go(UIUtils.screen.isSmall() ? 'app.registry_lookup': 'app.registry_lookup_lg'); + $state.go(UIUtils.screen.isSmall() ? 'app.wot_lookup.tab_registry': 'app.registry_lookup_lg'); }; $scope.showNotificationsPopover = function(event) { return UIUtils.popover.show(event, { templateUrl :'plugins/es/templates/notification/popover_notification.html', scope: $scope, - autoremove: false // reuse popover + autoremove: false, // reuse popover + // Auto-close if open when un-authenticate + afterShow: function(popover) { + var listener = csWallet.api.data.on.unauth(popover.scope, function() { + popover.scope.closePopover(); + listener(); + }); + } }); }; @@ -88,7 +97,14 @@ function ESMenuExtendController($scope, $state, PluginService, esSettings, UIUti return UIUtils.popover.show(event, { templateUrl :'plugins/es/templates/message/popover_message.html', scope: $scope, - autoremove: false // reuse popover + autoremove: false, // reuse popover + // Auto-close if open when un-authenticate + afterShow: function(popover) { + var listener = csWallet.api.data.on.unauth(popover.scope, function() { + popover.scope.closePopover(); + listener(); + }); + } }); }; @@ -107,18 +123,13 @@ function ESMenuExtendController($scope, $state, PluginService, esSettings, UIUti autoremove: false, // reuse popover // Auto-close if open when un-authenticate afterShow: function(popover) { - csWallet.api.data.on.unauth(popover.scope, function() { + var listener = csWallet.api.data.on.unauth(popover.scope, function() { popover.scope.closePopover(); + listener(); }); } }); }; - - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; - }); - - } /** @@ -133,7 +144,7 @@ function ESProfilePopoverExtendController($scope, $q, $state, esSettings, csWall $scope.showEditUserProfile = function() { $scope.closeProfilePopover(); - $state.go('app.user_edit_profile'); + $state.go('app.edit_profile'); }; esSettings.api.state.on.changed($scope, $scope.updateView); diff --git a/assets/www/plugins/es/js/controllers/blockchain-controllers.js b/assets/www/plugins/es/js/controllers/blockchain-controllers.js index 10c675d03f8c0bed37c44292a1f2af24ecc8b172..826ac512e8f1f026eb64719601308b8f37d27d13 100644 --- a/assets/www/plugins/es/js/controllers/blockchain-controllers.js +++ b/assets/www/plugins/es/js/controllers/blockchain-controllers.js @@ -134,7 +134,7 @@ function ESBlockLookupController($scope, $controller, $ionicPopover, $location, promise = esBlockchain.block.searchText($scope.currency, $scope.search.query, request); } - var time = new Date().getTime(); + var now = Date.now(); return promise .then(function(result) { // Apply transformation need by UI (e.g add avatar and name...) @@ -146,7 +146,7 @@ function ESBlockLookupController($scope, $controller, $ionicPopover, $location, .then(function(result) { $scope.showPubkey = ($scope.search.sort == 'issuer'); // Compute time only once (on first page) - $scope.search.took = (from === 0) ? (new Date().getTime() - time) : $scope.search.took; + $scope.search.took = (from === 0) ? (Date.now() - now) : $scope.search.took; // Keep previous total, when already computed (because of current, that is excluded only in the first page) var total = (from === 0) ? result.total : $scope.search.total; $scope.doDisplayResult(result.hits, from, total); @@ -181,26 +181,20 @@ function ESBlockLookupController($scope, $controller, $ionicPopover, $location, /* -- popups -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/blockchain/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/blockchain/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; diff --git a/assets/www/plugins/es/js/controllers/common-controllers.js b/assets/www/plugins/es/js/controllers/common-controllers.js index 247708f449c0465177b5ecba86bcd44a0f4d75ea..415602f8936985b7cc5fdee8a45431b3e9fd0fde 100644 --- a/assets/www/plugins/es/js/controllers/common-controllers.js +++ b/assets/www/plugins/es/js/controllers/common-controllers.js @@ -51,19 +51,23 @@ function ESPicturesEditController($scope, UIUtils, $q, Device) { }; $scope.fileChanged = function(event) { + if (!event.target.files || !event.target.files.length) return; UIUtils.loading.show(); - return $q(function(resolve, reject) { - var file = event.target.files[0]; - UIUtils.image.resizeFile(file) - .then(function(imageData) { - $scope.pictures.push({ - src: imageData, - isnew: true // use to prevent visibility hidden (if animation) - }); - UIUtils.loading.hide(100); - resolve(); + var file = event.target.files[0]; + return UIUtils.image.resizeFile(file) + .then(function(imageData) { + $scope.pictures.push({ + src: imageData, + isnew: true // use to prevent visibility hidden (if animation) }); - }); + event.target.value = ""; // reset input[type=file] + UIUtils.loading.hide(100); + }) + .catch(function(err) { + console.error(err); + event.target.value = ""; // reset input[type=file] + UIUtils.loading.hide(); + }); }; $scope.removePicture = function(index){ @@ -141,7 +145,7 @@ function ESCategoryModalController($scope, UIUtils, $timeout, parameters) { -function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { +function ESCommentsController($scope, $filter, $state, $focus, $timeout, $anchorScroll, UIUtils) { 'ngInject'; $scope.loading = true; @@ -150,8 +154,12 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { $scope.comments = {}; $scope.$on('$recordView.enter', function(e, state) { + // First enter + if ($scope.loading) { + $scope.anchor = state && state.stateParams.anchor; + } // second call (when using cached view) - if (!$scope.loading && $scope.id) { + else if (!$scope.loading && $scope.id) { $scope.load($scope.id, {animate: false}); } }); @@ -159,15 +167,21 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { $scope.$on('$recordView.load', function(event, id, service) { $scope.id = id || $scope.id; $scope.service = service || $scope.service; - console.debug("[ES] [comment] Initialized service with: " + service.id); + console.debug("[ES] [comment] Will use {" + service.index + "} service"); if ($scope.id) { - $scope.load($scope.id); + $scope.load($scope.id) + .then(function() { + // Scroll to anchor + $scope.scrollToAnchor(); + }); } }); $scope.load = function(id, options) { options = options || {}; options.from = options.from || 0; + // If anchor has been defined, load all comments + options.size = options.size || ($scope.anchor && -1/*all*/); options.size = options.size || $scope.defaultCommentSize; options.animate = angular.isDefined(options.animate) ? options.animate : true; options.loadAvatarAllParent = angular.isDefined(options.loadAvatarAllParent) ? options.loadAvatarAllParent : true; @@ -202,6 +216,25 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { } }); + $scope.scrollToAnchor = function() { + if (!$scope.anchor) return; + var elemList = document.getElementsByName($scope.anchor); + // Waiting for the element + if (!elemList || !elemList.length) { + return $timeout($scope.scrollToAnchor, 500); + } + // If many, remove all anchor except the last one + for (var i = 0; i<elemList.length-1; i++) { + angular.element(elemList[i]).remove(); + } + // Scroll to the anchor + $anchorScroll($scope.anchor); + // Remove the anchor. This will the CSS class 'positive-100-bg' on the comment + $timeout(function () { + $scope.anchor = null; + }, 1500); + }; + $scope.showMore = function(){ var from = 0; var size = -1; @@ -214,6 +247,14 @@ function ESCommentsController($scope, $filter, $state, $focus, UIUtils) { }); }; + $scope.onKeypress = function(event) { + // If Ctrl + Enter: submit + if (event && event.charCode == 10 && event.ctrlKey) { + $scope.save(); + event.preventDefault(); + } + }; + $scope.save = function() { if (!$scope.formData.message || !$scope.formData.message.length) return; @@ -347,8 +388,6 @@ function ESSocialsEditController($scope, $focus, $filter, UIUtils, SocialUtils) selector: '#social-' + $filter('formatSlug')(social.url), startVelocity: 10000 }); - - }; $scope.editSocialNetwork = function(index) { @@ -373,9 +412,8 @@ function ESSocialsEditController($scope, $focus, $filter, UIUtils, SocialUtils) function ESSocialsViewController($scope) { 'ngInject'; - $scope.openSocial = function($event, social) { - $event.stopPropagation(); - return $scope.openLink($event, social.url, { + $scope.openSocial = function(event, social) { + return $scope.openLink(event, social.url, { type: social.type }); }; @@ -474,7 +512,6 @@ function ESPositionEditController($scope, csConfig, esGeo, ModalUtils) { .catch(function(err) { console.error(err); // Silent loadingCurrentPosition = false; - //$scope.form.geoPoint.$setValidity('required', false); }); } @@ -499,22 +536,24 @@ function ESPositionEditController($scope, csConfig, esGeo, ModalUtils) { }); }; - $scope.onCityChanged = function() { - if ($scope.loading) return; - if ($scope.form) { - $scope.form.$valid = undefined; - } - if ($scope.formPosition.enable) { - return $scope.tryToLocalize(); - } - }; + $scope.onCityChanged = function() { + if ($scope.loading) return; + if ($scope.formPosition.enable) { + if ($scope.formData.geoPoint) { + // Invalidate the position + $scope.formData.geoPoint.lat = undefined; + $scope.formData.geoPoint.lon = undefined; + } + return $scope.tryToLocalize(); + } + }; $scope.onUseGeopointChanged = function() { if ($scope.loading) return; if (!$scope.formPosition.enable) { if ($scope.formData.geoPoint) { - $scope.formData.geoPoint = null; - //$scope.form.geoPoint.$setValidity('required', true); + $scope.formData.geoPoint.lat = undefined; + $scope.formData.geoPoint.lon = undefined; $scope.dirty = true; } } @@ -688,7 +727,7 @@ function ESLookupPositionController($scope, $q, csConfig, esGeo, ModalUtils) { }; } -function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConfig, esGeo) { +function ESSearchPositionItemController($scope, $timeout, ModalUtils, csConfig, esGeo) { 'ngInject'; // The default country used for address localisation @@ -772,15 +811,20 @@ function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConf $scope.showDropdown = function() { var text = $scope.search.location && $scope.search.location.trim(); if (!text || text.length < minLength) { - $scope.locations = undefined; - return $q.when(); // nothing to search + return $scope.hideDropdown(true/*force, if still loading*/); } + // Compute a request id, to apply response only if current request + var requestId = ($scope.requestId && $scope.requestId + 1) || 1; + $scope.requestId = requestId; + loadingPosition = true; // Execute the given query return esGeo.point.searchByAddress(text) .then(function(res) { + if ($scope.requestId != requestId) return; // Skip apply if not same request: + loadingPosition = false; $scope.locations = res||[]; $scope.license = res && res.length && res[0].license; @@ -792,6 +836,7 @@ function ESSearchPositionItemController($scope, $q, $timeout, ModalUtils, csConf }; $scope.hideDropdown = function(force) { + // force, even if still loading if (force) { $scope.locations = undefined; $scope.selectLocationIndex = -1; diff --git a/assets/www/plugins/es/js/controllers/document-controllers.js b/assets/www/plugins/es/js/controllers/document-controllers.js index 1ea1f5be71e36df4f35e3985709f4ad02fdc6e68..3e9f5212675fed9c93f2436c9ee621c0a54d2a5b 100644 --- a/assets/www/plugins/es/js/controllers/document-controllers.js +++ b/assets/www/plugins/es/js/controllers/document-controllers.js @@ -147,7 +147,7 @@ function ESDocumentLookupController($scope, $ionicPopover, $location, $timeout, }); }; - $scope.remove = function(index) { + $scope.remove = function(index, options) { var doc = $scope.search.results[index]; if (!doc) return; @@ -188,26 +188,20 @@ function ESDocumentLookupController($scope, $ionicPopover, $location, $timeout, /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/document/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/document/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; diff --git a/assets/www/plugins/es/js/controllers/group-controllers.js b/assets/www/plugins/es/js/controllers/group-controllers.js index 7b3f31c0cbf051d3e40eb567f70419ee27e6b89d..ff51915b11895a45e55d3ee47e5455fe37512e2d 100644 --- a/assets/www/plugins/es/js/controllers/group-controllers.js +++ b/assets/www/plugins/es/js/controllers/group-controllers.js @@ -185,7 +185,9 @@ function ESGroupViewController($scope, $state, $ionicPopover, $ionicHistory, $tr $scope.formData = {}; $scope.id = null; $scope.pictures = []; + $scope.canEdit = false; $scope.loading = true; + $scope.motion = UIUtils.motion.fadeSlideIn; $scope.$on('$ionicView.enter', function(e, state) { if (state.stateParams && state.stateParams.id) { // Load by id @@ -208,7 +210,7 @@ function ESGroupViewController($scope, $state, $ionicPopover, $ionicHistory, $tr $scope.id = data.id; $scope.formData = data.record; $scope.issuer= data.issuer; - $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer); + $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer) || csWallet.children.hasPubkey($scope.formData.issuer); $scope.pictures = data.record.pictures || []; delete data.record.pictures; // remove, as already stored in $scope.pictures @@ -262,26 +264,20 @@ function ESGroupViewController($scope, $state, $ionicPopover, $ionicHistory, $tr /* -- modals & popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/group/view_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/group/view_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; @@ -379,7 +375,7 @@ function ESGroupEditController($scope, esGroup, UIUtils, $state, $q, Device, .then(function(){ var json = $scope.formData; - json.time = esHttp.date.now(); + json.time = moment().utc().unix(); // Resize pictures json.picturesCount = $scope.pictures.length; @@ -409,7 +405,7 @@ function ESGroupEditController($scope, esGroup, UIUtils, $state, $q, Device, .then(function(json){ // Create if (!$scope.id) { - json.creationTime = esHttp.date.now(); + json.creationTime = moment().utc().unix(); return esGroup.record.add(json); } // Update diff --git a/assets/www/plugins/es/js/controllers/invitation-controllers.js b/assets/www/plugins/es/js/controllers/invitation-controllers.js index a86470ffd2052a75e0afa0327d930ff87aac1b33..96ce0780fa5a6fcf23943e08ae6471bed1063e25 100644 --- a/assets/www/plugins/es/js/controllers/invitation-controllers.js +++ b/assets/www/plugins/es/js/controllers/invitation-controllers.js @@ -6,7 +6,7 @@ angular.module('cesium.es.invitation.controllers', ['cesium.es.services']) $stateProvider .state('app.view_invitations', { - url: "/invitations", + url: "/invitations?id", views: { 'menuContent': { templateUrl: "plugins/es/templates/invitation/view_invitations.html", @@ -17,6 +17,19 @@ angular.module('cesium.es.invitation.controllers', ['cesium.es.services']) auth: true } }) + + .state('app.view_invitations_by_id', { + url: "/wallets/:id/invitations", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/invitation/view_invitations.html", + controller: 'InvitationsCtrl' + } + }, + data: { + login: true + } + }) ; }) @@ -27,7 +40,7 @@ angular.module('cesium.es.invitation.controllers', ['cesium.es.services']) .controller('ESNewInvitationModalCtrl', NewInvitationModalController) ; -function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUtils, csSettings, csWallet, +function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUtils, csWallet, esHttp, esModals, esNotification, esInvitation) { 'ngInject'; @@ -46,16 +59,37 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt } }; - $scope.$on('$ionicView.enter', function() { - if ($scope.search.loading) { - if (esHttp.isAlive()) { - $scope.load(); + var wallet; - // Reset unread counter - $scope.resetUnreadCount(); + $scope.setWallet = function(aWallet) { + wallet = aWallet; + }; + + $scope.$on('$ionicView.enter', function(e, state) { + if ($scope.search.loading) { + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); } - $scope.showFab('fab-new-invitation'); + $scope.loadWallet({ + wallet: wallet, + minData: true + }) + .then(function() { + + $scope.addListeners(); + + if (esHttp.isAlive()) { + $scope.load(); + + // Reset unread counter + $scope.resetUnreadCount(); + + $scope.showFab('fab-new-invitation'); + } + }); } }); @@ -64,7 +98,10 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt options.from = options.from || from || 0; options.size = options.size || size || defaultSearchLimit; - return esInvitation.load(options) + // Make sure wallet is init (need by PopoverInvitationCtrl) + wallet = wallet || csWallet; + + return esInvitation.load(options, wallet.data.keypair) .then(function(invitations) { $scope.search.results = invitations; $scope.search.loading = false; @@ -129,19 +166,18 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt }; $scope.resetUnreadCount = function() { - if ($scope.search.loading || !csWallet.data.invitations) { + if ($scope.search.loading || !wallet.data.invitations) { return $timeout($scope.resetUnreadCount, 2000); } - if (!csWallet.data.invitations.unreadCount) return; + if (!wallet.data.invitations.unreadCount) return; console.debug('[ES] [invitation] Resetting unread count'); - csWallet.data.invitations.unreadCount = 0; + wallet.data.invitations.unreadCount = 0; if (!$scope.search.results || !$scope.search.results.length) return; var lastNotification = $scope.search.results[0]; var readTime = lastNotification.time ? lastNotification.time : 0; - if (readTime && (!csSettings.data.plugins.es.invitations || csSettings.data.plugins.es.invitations.readTime != readTime)) { - csSettings.data.plugins.es.invitations = csSettings.data.plugins.es.invitations || {}; - csSettings.data.plugins.es.invitations.readTime = readTime; - csSettings.store(); + if (readTime && (!wallet.data.invitations.readTime || wallet.data.invitations.readTime != readTime)) { + wallet.data.invitations.readTime = readTime; + wallet.storeData(); } }; @@ -158,7 +194,7 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt return $q.all([ UIUtils.loading.show(), - esInvitation.deleteAll(csWallet.data.pubkey) + esInvitation.deleteAll(wallet.data.pubkey) ]) .then(function() { $scope.search.results.splice(0, $scope.search.results.length); // update list @@ -200,39 +236,44 @@ function InvitationsController($scope, $q, $ionicPopover, $state, $timeout, UIUt /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/invitation/popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/invitation/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; // Listeners - csWallet.api.data.on.logout($scope, $scope.resetData); - esHttp.api.node.on.stop($scope, $scope.resetData); - esHttp.api.node.on.start($scope, $scope.load); - esInvitation.api.data.on.new($scope, $scope.onNewInvitation); - + $scope.addListeners = function() { + if (!wallet) throw "Controller wallet not set !"; + + $scope.listeners = [ + esHttp.api.node.on.stop($scope, $scope.resetData), + esHttp.api.node.on.start($scope, $scope.load), + wallet.api.data.on.logout($scope, $scope.resetData) + ]; + + if (wallet.isDefault()) { + // Subscribe to new invitation + $scope.listeners.push( + esInvitation.api.data.on.new($scope, $scope.onNewInvitation) + ); + } + }; } -function PopoverInvitationController($scope, $controller) { +function PopoverInvitationController($scope, $controller, csWallet) { 'ngInject'; // Initialize the super class and extend it. @@ -241,8 +282,12 @@ function PopoverInvitationController($scope, $controller) { // Disable list effects $scope.motion = null; + // Set the wallet to use + $scope.setWallet(csWallet); + $scope.$on('popover.shown', function() { if ($scope.search.loading) { + $scope.addListeners(); $scope.load(); } }); @@ -263,14 +308,71 @@ function PopoverInvitationController($scope, $controller) { } -function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esHttp, esWallet, esInvitation) { +function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esHttp, esWallet, esInvitation, parameters) { 'ngInject'; + // Controller var + var wallet; + + // Scope var $scope.recipients = []; $scope.suggestions = []; $scope.formData = { - useComment: false + useComment: false, + walletId: null }; + $scope.enableSelectWallet = true; + + /* -- scope functions -- */ + + $scope.setParameters = function(parameters) { + if (!parameters) return; + if (!parameters.wallet || parameters.wallet === "default") { + $scope.formData.walletId = csWallet.id; + } + else { + $scope.formData.walletId = parameters.wallet; + } + }; + // Read default parameters + $scope.setParameters(parameters); + + $scope.load = function() { + $scope.enableSelectWallet = csWallet.children.count() > 0; + + wallet = $scope.enableSelectWallet && ($scope.formData.walletId ? csWallet.children.get($scope.formData.walletId) : csWallet) || csWallet; + $scope.formData.walletId = wallet.id; // update the walletId (could have changed) + if (!wallet.isDefault()) { + console.debug("[transfer] Using {" + wallet.id + "} wallet"); + } + + // Make to sure to load full wallet data (balance) + return wallet.login({sources: true, silent: true}) + .then(function(data) { + $scope.walletData = data; + UIUtils.ink({selector: '.modal-invitation .ink'}); + + if (!$scope.destPub || $scope.destUid) { + $scope.loading = false; + } + else { + // Fill the uid from the pubkey + return csWot.extend({pubkey: $scope.destPub}) + .then(function(res) { + $scope.destUid = res && (res.name || res.uid); + if ($scope.destUid) { + $scope.destPub = ''; + } + $scope.loading = false; + }); + } + }) + .catch(function(err){ + if (err == 'CANCELLED') return $scope.cancel(); // close the modal + UIUtils.onError('ERROR.LOGIN_FAILED')(err); + }); + }; + $scope.$on('modal.shown', $scope.load); // When changing use comment $scope.onUseCommentChanged = function() { @@ -301,21 +403,24 @@ function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esH return; } - if (!csWallet.isLogin()) return $scope.closeModal(); // should never happen + if (!wallet.isLogin()) return $scope.closeModal(); // should never happen - return $q.all([ - // Get keypair only once (if not done here, certification.send() with compute it many times) - esWallet.box.getKeypair(csWallet.data.keypair), - // Ask confirmation - UIUtils.alert.confirm('INVITATION.CONFIRM.SEND_INVITATIONS_TO_CERTIFY', undefined, {okText: 'COMMON.BTN_SEND'}) - ]) + // Make sure user is still authenticated + return wallet.auth({silent: true}) + .then(function() { + return $q.all([ + // Get keypair only once (if not done here, esInvitation.send() with compute it many times) + esWallet.box.getKeypair(wallet.data.keypair), + // Ask confirmation + UIUtils.alert.confirm('INVITATION.CONFIRM.SEND_INVITATIONS_TO_CERTIFY', undefined, {okText: 'COMMON.BTN_SEND'}) + ]); + }) .then(function(res) { - if (!res) return; - var keypair = res[0]; - var confirm = res[1]; - if (!confirm) return; + var keypair = res && res[0]; + var confirm = res && res[1]; + if (!keypair || !confirm) return; UIUtils.loading.show(); - var time = esHttp.date.now(); // use same date for each invitation + var time = moment().utc().unix(); // use same date for each invitation var comment = $scope.formData.useComment && $scope.formData.comment && $scope.formData.comment.trim(); return $q.all( $scope.recipients.reduce(function (res, recipient) { @@ -325,14 +430,17 @@ function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esH return res; } var invitation = { - issuer: csWallet.data.pubkey, + issuer: wallet.data.pubkey, recipient: recipient.pubkey, time: time, content: [identity.uid, identity.pubkey].join('-'), comment: comment }; return res.concat( - esInvitation.send(invitation, keypair, 'certification')); + esInvitation.send(invitation, { + wallet: wallet, + type: 'certification' + })); }, [])); }, [])) .then(function() { @@ -384,5 +492,20 @@ function NewInvitationModalController($scope, $q, Modals, UIUtils, csWallet, esH $scope.suggestions = res; }); }; + + + $scope.showSelectWalletModal = function() { + if (!$scope.enableSelectWallet) return; + + return Modals.showSelectWallet() + .then(function(wallet) { + if (!wallet || $scope.formData.walletId === wallet.id) return; + console.debug("[transfer] Using {" + wallet.id + "} wallet"); + $scope.wallet = wallet; + $scope.walletData = wallet.data; + $scope.formData.walletId = wallet.id; + $scope.onAmountChanged(); + }); + }; } diff --git a/assets/www/plugins/es/js/controllers/message-controllers.js b/assets/www/plugins/es/js/controllers/message-controllers.js index 73f6105b86a88628b2b8495bd35b557100d08039..283e5252b1456bfb511a8306299806065a5933c5 100644 --- a/assets/www/plugins/es/js/controllers/message-controllers.js +++ b/assets/www/plugins/es/js/controllers/message-controllers.js @@ -58,6 +58,51 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services']) } }) + .state('app.user_messages_by_id', { + url: "/wallets/:id/message", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/lookup_by_id.html" + } + } + }) + + .state('app.user_messages_by_id.tab_inbox', { + url: "/inbox", + views: { + 'tab_inbox': { + controller: 'ESMessageInboxListCtrl', + templateUrl: "plugins/es/templates/message/tabs/tab_list.html" + } + }, + data: { + large: 'app.user_messages_lg_inbox_by_id' + } + }) + + .state('app.user_messages_by_id.tab_outbox', { + url: "/outbox", + views: { + 'tab_outbox': { + controller: 'ESMessageOutboxListCtrl', + templateUrl: "plugins/es/templates/message/tabs/tab_list.html" + } + }, + data: { + large: 'app.user_messages_lg_outbox_by_id' + } + }) + + .state('app.user_messages_lg_inbox_by_id', { + url: "/wallets/:id/message/lg/inbox", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/lookup_lg.html", + controller: 'ESMessageInboxListCtrl' + } + } + }) + .state('app.user_messages_lg_outbox', { url: "/user/message/lg/outbox", views: { @@ -72,9 +117,19 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services']) } }) + .state('app.user_messages_lg_outbox_by_id', { + url: "/wallets/:id/message/lg/outbox", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/lookup_lg.html", + controller: 'ESMessageOutboxListCtrl' + } + } + }) + .state('app.user_new_message', { cache: false, - url: "/user/message/new?pubkey&uid&title&content", + url: "/user/message/new?pubkey&uid&title&content&isReply", views: { 'menuContent': { templateUrl: "plugins/es/templates/message/compose.html", @@ -85,7 +140,7 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services']) .state('app.user_view_message', { cache: false, - url: "/user/message/view/:type/:id", + url: "/user/message/view/:type/:messageId", views: { 'menuContent': { templateUrl: "plugins/es/templates/message/view_message.html", @@ -98,6 +153,17 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services']) } }) + .state('app.user_view_message_by_id', { + cache: false, + url: "/wallets/:id/message/view/:type/:messageId", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/message/view_message.html", + controller: 'ESMessageViewCtrl' + } + } + }) + ; }) @@ -117,11 +183,13 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services']) ; -function ESMessageAbstractListController($scope, $state, $translate, $ionicHistory, $ionicPopover, $timeout, $filter, +function ESMessageAbstractListController($scope, $state, $translate, $ionicHistory, $ionicPopover, $timeout, csWallet, esModals, UIUtils, esMessage) { 'ngInject'; var defaultSearchLimit = 40; + var wallet; + var selectPrevented = false; $scope.search = { loading: true, @@ -137,33 +205,45 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto $scope.fabButtonNewMessageId = undefined; - $scope.$on('$ionicView.enter', function(e, state) { + $scope.enter = function(s, state) { + // First enter + if ($scope.search.loading) { + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } - $scope.loadWallet({minData: true}) - .then(function() { - if (!$scope.entered) { - $scope.entered = true; - $scope.type = $scope.type || state.stateParams && state.stateParams.type || 'inbox'; - $scope.load(); - } + $scope.isDefaultWallet = wallet.isDefault(); + $scope.walletId = wallet.id; - if ($scope.fabButtonNewMessageId) { - $scope.showFab($scope.fabButtonNewMessageId); - } - }) - .catch(function(err) { - if ('CANCELLED' === err) { - $ionicHistory.nextViewOptions({ - historyRoot: true - }); - $state.go('app.home'); - } - }); - }); + wallet.auth({minData: true}) + .then(function() { + if (!$scope.entered) { + $scope.entered = true; + $scope.type = $scope.type || state.stateParams && state.stateParams.type || 'inbox'; + $scope.load(); + } - $scope.refresh = function(silent) { - return $scope.load(undefined, undefined, silent); + if ($scope.fabButtonNewMessageId) { + $scope.showFab($scope.fabButtonNewMessageId); + } + }) + .catch(function(err) { + if ('CANCELLED' === err) { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + $scope.showHome(); + } + }); + } + // Not first entering: refresh the view + else { + $scope.updateView(); + } }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function(from, size, silent) { @@ -174,6 +254,7 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto options.summary = false; options.filter = ($scope.search.type == 'text' && $scope.search.text && $scope.search.text.trim().length > 0) ? $scope.search.text : undefined; + options.wallet = wallet; $scope.search.loading = !silent; return esMessage.load(options) @@ -201,15 +282,11 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto }); }; - $scope.setType = function(type) { - $scope.type = type; - $scope.load(); - }; - $scope.updateView = function() { if ($scope.motion && $scope.motion.ionListClass && $scope.search.results.length) { $scope.motion.show({selector: '.view-messages .list .item'}); } + $scope.$broadcast('$$rebind::rebind'); // notifier binder }; $scope.showMore = function() { @@ -254,9 +331,10 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE') .then(function(confirm) { if (confirm) { - esMessage.remove(message.id, $scope.type) + esMessage.remove(message.id, $scope.type, {walletId: $scope.walletId}) .then(function () { $scope.search.results.splice(index,1); // remove from messages array + $scope.updateView(); UIUtils.toast.show('MESSAGE.INFO.MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_MESSAGE_FAILED')); @@ -271,9 +349,10 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE_ALL') .then(function(confirm) { if (confirm) { - esMessage.removeAll($scope.type) + esMessage.removeAll($scope.type, {walletId: $scope.walletId}) .then(function () { $scope.search.results.splice(0,$scope.search.results.length); // reset array + $scope.updateView(); UIUtils.toast.show('MESSAGE.INFO.All_MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_All_MESSAGES_FAILED')); @@ -301,12 +380,45 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto return $scope.load(); }; + + $scope.refresh = function(silent) { + selectPrevented = true; // Will disable select() to open the message + return $scope.load(undefined, undefined, silent) + .then(function() { + selectPrevented = false; + }) + .catch(function() { + selectPrevented = false; + }); + }; + + $scope.select = function(message, event) { + if (event.isDefaultPrevented() || $scope.search.loading || selectPrevented) return; // skip + + // Add a timeout, to be sure the refres action was not called before + return $timeout(function() { + if (selectPrevented || event.isDefaultPrevented()) return; // skip + event.preventDefault(); + + if ($scope.walletId === 'default') { + return $state.go('app.user_view_message', {type: $scope.type, messageId:message.id}); + } + else { + return $state.go('app.user_view_message_by_id', {type: $scope.type, messageId:message.id, id: $scope.walletId}); + } + }, 200); + }; + /* -- Modals -- */ $scope.showNewMessageModal = function(parameters) { - return $scope.loadWallet({minData: true}) + return wallet.login({minData: true}) .then(function() { UIUtils.loading.hide(); + + parameters = parameters || {}; + parameters.wallet = $scope.walletId; + return esModals.showMessageCompose(parameters) .then(function(id) { if (id) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT'); @@ -328,7 +440,8 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto destUid: message.name||message.uid, title: prefix + message.title, content: content, - isReply: true + isReply: true, + wallet: $scope.walletId }); }) .then(function(sent) { @@ -339,26 +452,20 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/message/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/message/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; @@ -372,22 +479,23 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto if (index) { $scope.search.results.splice(index,1); // remove from messages array } + $scope.updateView(); }; esMessage.api.data.on.delete($scope, $scope.onMessageDelete); // Watch user sent message $scope.onNewOutboxMessage = function(id) { - if ($scope.type != 'outbox') return; + if ($scope.type !== 'outbox') return; // Add message sent to list - $scope.loading = true; + $scope.search.loading = true; return $timeout(function() { // Load the message sent - return esMessage.get(id, {type: $scope.type, summary: true}); + return esMessage.get(id, $scope.type, {summary: true, wallet: wallet}); }, 500 /*waiting ES propagation*/) .then(function(msg) { $scope.search.results.splice(0,0,msg); - $scope.loading = false; - $scope.motion.show({selector: '.view-messages .list .item'}); + $scope.search.loading = false; + $scope.updateView(); }) .catch(function() { $scope.loading = false; @@ -397,15 +505,15 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto // Watch received message $scope.onNewInboxMessage = function(notification) { - if ($scope.type != 'inbox' || !$scope.entered) return; + if ($scope.type !== 'inbox' || !$scope.entered || !wallet.isUserPubkey(notification.issuer)) return; // Add message sent to list - $scope.loading = true; + $scope.search.loading = true; // Load the the message - return esMessage.get(notification.id, {type: $scope.type, summary: true}) + return esMessage.get(notification.id, $scope.type, {summary: true, wallet: wallet}) .then(function(msg) { $scope.search.results.splice(0,0,msg); $scope.search.loading = false; - $scope.motion.show({selector: '.view-messages .list .item'}); + $scope.updateView(); }) .catch(function() { $scope.search.loading = false; @@ -451,47 +559,28 @@ function ESMessageOutboxListController($scope, $controller) { $scope.fabButtonNewMessageId = 'fab-add-message-record-outbox'; } -function ESMessageComposeController($scope, $controller, UIUtils) { +function ESMessageComposeController($scope, $controller) { 'ngInject'; // Initialize the super class and extend it. angular.extend(this, $controller('ESMessageComposeModalCtrl', {$scope: $scope, parameters: {}})); - $scope.$on('$ionicView.enter', function(e, state) { - if (state.stateParams) { - if (state.stateParams.pubkey) { - $scope.formData.destPub = state.stateParams.pubkey; - if (state.stateParams.uid) { - $scope.destUid = state.stateParams.uid; - $scope.destPub = ''; - } - else { - $scope.destUid = ''; - $scope.destPub = $scope.formData.destPub; - } - } - if (state.stateParams.title) { - $scope.formData.title = state.stateParams.title; - } + $scope.enter = function(e, state) { - if (state.stateParams.content) { - $scope.formData.content = state.stateParams.content; - } + // Apply state parameters + if (state && state.stateParams) { + $scope.setParameters(state.stateParams); } - $scope.loadWallet({minData: true}) - .then(function() { - UIUtils.loading.hide(); - }) - .catch(function(err){ - if (err === 'CANCELLED') { - $scope.showHome(); - } - }); - }); + // Load wallet + return $scope.load() + .then(UIUtils.loading.hide); + }; + $scope.$on('$ionicView.enter',$scope.enter); $scope.cancel = function() { + $scope.sending = false; $scope.showHome(); }; @@ -500,6 +589,7 @@ function ESMessageComposeController($scope, $controller, UIUtils) { }; $scope.closeModal = function() { + $scope.sending = false; $scope.showHome(); }; @@ -508,18 +598,79 @@ function ESMessageComposeController($scope, $controller, UIUtils) { function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHttp, esMessage, parameters) { 'ngInject'; + var wallet; + $scope.formData = { - title: parameters ? parameters.title : null, - content: parameters ? parameters.content : null, - destPub: parameters ? parameters.destPub : null + title: null, + content: null, + destPub: null, + walletId: null + }; + $scope.destUid = null; + $scope.destPub = null; + $scope.isReply = false; + $scope.enableSelectWallet = true; + $scope.sending = false; + + $scope.setParameters = function(parameters) { + if (!parameters) return; + + if (parameters.pubkey || parameters.destPub) { + $scope.formData.destPub = parameters.pubkey || parameters.destPub; + if (parameters.uid || parameters.destUid) { + $scope.destUid = parameters.uid || parameters.destUid; + $scope.destPub = ''; + } + else { + $scope.destUid = ''; + $scope.destPub = $scope.formData.destPub; + } + } + + if (parameters.title) { + $scope.formData.title = parameters.title; + } + + if (parameters.content) { + $scope.formData.content = parameters.content; + } + + $scope.isReply = parameters.isReply || false; + + if (parameters.wallet) { + $scope.formData.walletId = parameters.wallet; + } + }; + + // Read default parameters + $scope.setParameters(parameters); + + $scope.load = function() { + $scope.enableSelectWallet = csWallet.children.count() > 0; + + wallet = $scope.enableSelectWallet && ($scope.formData.walletId ? csWallet.children.get($scope.formData.walletId) : csWallet) || csWallet; + if (!wallet.isDefault()) { + console.debug("[message] Using {" + wallet.id + "} wallet"); + } + else { + console.debug("[message] Using default wallet"); + } + + return wallet.login({minData: true, silent: true}) + .then(function(data) { + $scope.walletData = data; + }) + .catch(function(err){ + if (err === 'CANCELLED') { + $scope.cancel(); + } + }); }; - $scope.destUid = parameters ? parameters.destUid : null; - $scope.destPub = (parameters && !parameters.destUid) ? parameters.destPub : null; - $scope.isResponse = parameters ? parameters.isResponse : false; + $scope.$on('modal.shown', $scope.load); $scope.doSend = function(forceNoContent) { $scope.form.$submitted=true; - if(!$scope.form.$valid /*|| !$scope.formData.destPub*/) { + if(!$scope.form.$valid) { return; } @@ -533,22 +684,36 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt }); } + $scope.sending = true; UIUtils.loading.show(); var data = { - issuer: csWallet.data.pubkey, + issuer: wallet.data.pubkey, recipient: $scope.formData.destPub, title: $scope.formData.title, content: $scope.formData.content, - time: esHttp.date.now() + time: moment().utc().unix() }; - esMessage.send(data) + esMessage.send(data, {wallet: wallet}) .then(function(id) { $scope.id=id; UIUtils.loading.hide(); $scope.closeModal(id); }) - .catch(UIUtils.onError('MESSAGE.ERROR.SEND_MSG_FAILED')); + .catch(function(err) { + $scope.sending = false; + // silent, if user cancelled; + if (err === 'CANCELLED') { + UIUtils.loading.hide(); + return; + } + UIUtils.onError('MESSAGE.ERROR.SEND_MSG_FAILED')(err); + }); + }; + + + $scope.cancel = function() { + $scope.closeModal(); }; /* -- Modals -- */ @@ -565,6 +730,7 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt $scope.destUid = ''; $scope.destPub = result.pubkey; } + $scope.destName = result.name || result.uid; $scope.formData.destPub = result.pubkey; // TODO focus on title field //$focus(''); @@ -572,11 +738,23 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt }); }; - $scope.cancel = function() { - $scope.closeModal(); + $scope.showSelectWalletModal = function() { + if (!$scope.enableSelectWallet) return; + + return Modals.showSelectWallet({ + showDefault: true, + showBalance: false + }) + .then(function(newWallet) { + if (!newWallet || (wallet && wallet.id === newWallet.id)) return; + wallet = newWallet; + $scope.walletData = wallet.data; + console.debug("[message] Using {" + wallet.id + "} wallet"); + }); }; + // TODO : for DEV only /*$timeout(function() { $scope.formData.destPub = 'G2CBgZBPLe6FSFUgpx2Jf1Aqsgta6iib3vmDRA1yLiqU'; @@ -593,76 +771,96 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHistory, $ionicPopover, - UIUtils, esModals, esMessage) { + UIUtils, esModals, esMessage, csWallet) { 'ngInject'; $scope.formData = {}; $scope.id = null; $scope.loading = true; + var wallet; + $scope.$on('$ionicView.beforeEnter', function (event, viewData) { // Enable back button (workaround need for navigation outside tabs - https://stackoverflow.com/a/35064602) viewData.enableBack = UIUtils.screen.isSmall() ? true : viewData.enableBack; }); - $scope.$on('$ionicView.enter', function (e, state) { - if (state.stateParams && state.stateParams.id) { // Load by id - if ($scope.loading) { // prevent reload if same id - $scope.type = state.stateParams.type || 'inbox'; - - $scope.load(state.stateParams.id, $scope.type) - .then(function(message) { - $scope.loading = false; - UIUtils.loading.hide(); - if (!message) return; - - $scope.id = message.id; - $scope.formData = message; - $scope.canDelete = true; - $scope.motion.show({selector: '.view-message .list .item'}); - // Mark as read - if (!message.read) { - $timeout(function() { - // Message has NOT changed - if ($scope.id === message.id) { - esMessage.markAsRead(message, $scope.type) - .then(function() { - console.debug("[message] marked as read"); - }) - .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED')); - } - }, 2000); // 2s - } - }); + $scope.enter = function(e, state) { + // First enter + if ($scope.loading) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); } - $scope.showFab('fab-view-message-reply'); - } - else { - $state.go('app.user_message'); + $scope.isDefaultWallet = wallet.isDefault(); + $scope.walletId = wallet.id; + + var messageId = state.stateParams && state.stateParams.messageId; + $scope.type = state.stateParams.type || 'inbox'; + + // No message id: redirect + if (angular.isUndefined(messageId)) { + $scope.goBack(); + return; + } + + wallet.auth({minData: true}) + .then(function () { + return $scope.load(messageId, $scope.type); + }) + .then(function(message) { + + UIUtils.loading.hide(); + if (!message) return; // SKip + + $scope.updateView(message); + $scope.showFab('fab-view-message-reply'); + + // Mark as read + if (!message.read) { + $timeout(function() { + // Message has NOT changed + if ($scope.id === message.id) { + esMessage.markAsRead(message, {type: $scope.type, wallet: wallet}) + .then(function() { + console.debug("[message] marked as read"); + }) + .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED')); + } + }, 2000); // 2s + } + }); } - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function(id, type) { type = type || 'inbox'; - - return $scope.loadWallet({minData: true}) - .then(function() { - return esMessage.get(id, {type: type}); - }) + return esMessage.get(id, type, {wallet: wallet}) .catch(UIUtils.onError('MESSAGE.ERROR.LOAD_MESSAGE_FAILED')) .then(function(message) { if (!message.valid) { return UIUtils.alert.error(!$scope.isUserPubkey(message.recipient) ? 'MESSAGE.ERROR.USER_NOT_RECIPIENT' : 'MESSAGE.ERROR.NOT_AUTHENTICATED_MESSAGE', 'MESSAGE.ERROR.MESSAGE_NOT_READABLE') .then(function () { - $state.go('app.user_message', {type: type}); + $scope.goBack(true/*clear cache*/); }); } return message; }); }; + $scope.updateView = function(message) { + $scope.loading = false; + $scope.id = message.id; + $scope.formData = message; + $scope.canDelete = true; + $scope.motion.show({selector: '.view-message .list .item'}); + }; + $scope.delete = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); @@ -671,14 +869,9 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE') .then(function(confirm) { if (confirm) { - return esMessage.remove($scope.id, $scope.type) + return esMessage.remove($scope.id, $scope.type, {wallet: wallet}) .then(function () { - $ionicHistory.nextViewOptions({ - historyRoot: true - }); - $state.go($scope.type == 'inbox' ? 'app.user_message.tab_inbox' : 'app.user_message.tab_outbox', - {type: $scope.type} - ); + $scope.goBack(true/*clear page cache*/); UIUtils.toast.show('MESSAGE.INFO.MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_MESSAGE_FAILED')); @@ -686,36 +879,47 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis }); }; + $scope.goBack = function(clearPageCache) { + if (clearPageCache) { + $ionicHistory.clearCache($ionicHistory.currentView().stateId); // clear current view + } + $ionicHistory.nextViewOptions({historyRoot: true}); + if ($scope.isDefaultWallet) { + if ($scope.type) { + $state.go('app.user_message.tab_' + $scope.type, {type: $scope.type}); + } + } + else { + if ($scope.type) { + $state.go('app.user_messages_by_id.tab_' + $scope.type, {type: $scope.type, id: $scope.walletId}); + } + } + }; + /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/message/view_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/message/view_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; /* -- Modals -- */ $scope.showReplyModal = function() { - var recipientField = ($scope.type == 'inbox') ? 'issuer' : 'recipient'; + var recipientField = ($scope.type === 'inbox') ? 'issuer' : 'recipient'; $translate('MESSAGE.REPLY_TITLE_PREFIX') .then(function (prefix) { var content = $scope.formData.content ? $scope.formData.content.replace(/^/g, ' > ') : null; @@ -726,7 +930,8 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis destUid: $scope.formData.name||$scope.formData.uid, title: prefix + $scope.formData.title, content: content, - isReply: true + isReply: true, + walletId: wallet.id }); }) .then(function(sent) { @@ -741,10 +946,11 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis }; } -function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esMessage, esModals) { +function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esMessage, esModals, $timeout) { 'ngInject'; var defaultSearchLimit = 40; + var wallet; $scope.search = { loading : true, @@ -756,6 +962,15 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM $scope.$on('popover.shown', function() { if ($scope.search.loading) { + // TODO manage secondary wallets + wallet = $scope.walletId && csWallet.children.get($scope.walletId) || csWallet; + + /* -- wallet listeners -- */ + if (wallet.isDefault()) { + wallet.api.data.on.logout($scope, $scope.resetData); + esMessage.api.data.on.new($scope, $scope.onNewMessageNotification); + } + $scope.load(); } }); @@ -811,13 +1026,22 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM // Listen notifications changes $scope.onNewMessageNotification = function(notification) { if ($scope.search.loading || $scope.search.loadingMore) return; + + if (!wallet.isUserPubkey(notification.issuer)) return; // skip + + // Prepend to list $scope.search.results.splice(0,0,notification); $scope.updateView(); }; $scope.select = function(notification) { if (!notification.read) notification.read = true; - $state.go('app.user_view_message', {id: notification.id}); + if ($scope.walletId === 'default') { + $state.go('app.user_view_message', {messageId: notification.id}); + } + else { + $state.go('app.user_view_message_by_id', {messageId: notification.id, id: $scope.walletId}); + } $scope.closePopover(notification); }; @@ -834,18 +1058,23 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM /* -- Modals -- */ $scope.showNewMessageModal = function(parameters) { + $scope.closePopover(); - return esModals.showMessageCompose(parameters) - .then(function(id) { - if (id) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT'); - }); + + $timeout(function() { + parameters = parameters || {}; + parameters.walletId = wallet.id; + + esModals.showMessageCompose(parameters) + .then(function(id) { + if (id) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT'); + }); + }, 500); // Timeout need, to avoid freeze }; /* -- listeners -- */ - csWallet.api.data.on.logout($scope, $scope.resetData); esHttp.api.node.on.stop($scope, $scope.resetData); esHttp.api.node.on.start($scope, $scope.load); - esMessage.api.data.on.new($scope, $scope.onNewMessageNotification); } diff --git a/assets/www/plugins/es/js/controllers/network-controllers.js b/assets/www/plugins/es/js/controllers/network-controllers.js index e329488e6b2fa03a9aa073fdcff14b8a81162bf3..cbf2346249dfb63197ca2bf71d1968068ec6677f 100644 --- a/assets/www/plugins/es/js/controllers/network-controllers.js +++ b/assets/www/plugins/es/js/controllers/network-controllers.js @@ -10,25 +10,11 @@ angular.module('cesium.es.network.controllers', ['cesium.es.services']) points: { 'buttons': { templateUrl: "plugins/es/templates/network/view_network_extend.html", - controller: 'ESNetworkViewExtendCtrl' + controller: 'ESExtensionCtrl' } } }) ; } - }) - - .controller('ESNetworkViewExtendCtrl', ESNetworkViewExtendController) -; - - -function ESNetworkViewExtendController($scope, PluginService, esSettings) { - 'ngInject'; - - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); - - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; }); -} + diff --git a/assets/www/plugins/es/js/controllers/notification-controllers.js b/assets/www/plugins/es/js/controllers/notification-controllers.js index f18fcfe5e61678dd291a26cf0befbc15acc57137..ad0d702bff1dfe968949e62f1e293af2ccc13157 100644 --- a/assets/www/plugins/es/js/controllers/notification-controllers.js +++ b/assets/www/plugins/es/js/controllers/notification-controllers.js @@ -19,6 +19,18 @@ angular.module('cesium.es.notification.controllers', ['cesium.es.services']) login: true } }) + .state('app.view_notifications_by_id', { + url: "/wallets/:id/notifications", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/notification/view_notifications.html", + controller: 'NotificationsCtrl' + } + }, + data: { + login: true + } + }) ; }) @@ -28,11 +40,12 @@ angular.module('cesium.es.notification.controllers', ['cesium.es.services']) ; -function NotificationsController($scope, $rootScope, $ionicPopover, $state, $timeout, UIUtils, esHttp, csSettings, csWallet, esNotification) { +function NotificationsController($scope, $ionicPopover, $state, $timeout, UIUtils, esHttp, csWallet, esNotification) { 'ngInject'; var defaultSearchLimit = 40; + $scope.preventSelect = false; $scope.search = { loading : true, results: null, @@ -45,14 +58,32 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim } } }; + $scope.listeners = []; - $scope.$on('$ionicView.enter', function() { + var wallet; + + $scope.setWallet = function(aWallet) { + wallet = aWallet; + }; + + $scope.$on('$ionicView.enter', function(e, state) { if ($scope.search.loading) { - $scope.loadWallet({minData: true}) + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + wallet.login({ + minData: true + }) .then(function() { $scope.load(); UIUtils.loading.hide(); + $scope.addListeners(); + // Reset unread counter return $timeout(function() { $scope.resetUnreadCount(); @@ -66,16 +97,22 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim }; $scope.load = function(from, size, silent) { - if (!csWallet.data.pubkey) { + // Make sure wallet is init (need by PopoverInvitationCtrl) + wallet = wallet || csWallet; + + if (!wallet.data.pubkey) { $scope.search.loading = true; return; } + $scope.search.preventSelect = true; + var options = angular.copy($scope.search.options); options.from = options.from || from || 0; options.size = options.size || size || defaultSearchLimit; + options.pubkey = wallet.data.pubkey; $scope.search.loading = !silent; - return esNotification.load(csWallet.data.pubkey, options) + return esNotification.load(options) .then(function(res) { if (!options.from) { $scope.search.results = res || []; @@ -84,6 +121,7 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim $scope.search.results = $scope.search.results.concat(res); } $scope.search.loading = false; + $scope.search.preventSelect = false; $scope.search.hasMore = $scope.search.results.length >= $scope.search.limit; $scope.updateView(); }) @@ -92,6 +130,7 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim if (!options.from) { $scope.search.results = []; } + $scope.search.preventSelect = false; $scope.search.hasMore = false; UIUtils.onError('COMMON.NOTIFICATIONS.LOAD_NOTIFICATIONS_FAILED')(err); }); @@ -104,23 +143,23 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim }; $scope.markAllAsRead = function() { + $scope.hideActionsPopover(); + // Make sure to be auth before doing this - if (!csWallet.isAuth()) { - return csWallet.auth().then(function(){ + if (!wallet.isAuth()) { + return wallet.auth().then(function(){ UIUtils.loading.hide(); return $scope.markAllAsRead(); // loop }); } - $scope.hideActionsPopover(); - if (!$scope.search.results.length) return; UIUtils.loading.show() .then(function() { - $rootScope.walletData.notifications.unreadCount = 0; + wallet.data.notifications.unreadCount = 0; var lastNotification = $scope.search.results[0]; - $rootScope.walletData.notifications.readTime = lastNotification ? lastNotification.time : 0; + wallet.data.notifications.time = lastNotification ? lastNotification.time : 0; _.forEach($scope.search.results, function (item) { if (item.markAsRead && typeof item.markAsRead == 'function') item.markAsRead(); }); @@ -130,18 +169,22 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim }; $scope.resetUnreadCount = function() { - if (!csWallet.data.notifications.unreadCount || !$scope.search.results || !$scope.search.results.length) return; - csWallet.data.notifications.unreadCount = 0; + if ($scope.search.loading || !wallet.data.notifications) { + return $timeout($scope.resetUnreadCount, 2000); + } + if (!wallet.data.notifications.unreadCount || !$scope.search.results || !$scope.search.results.length) return; + wallet.data.notifications.unreadCount = 0; var lastNotification = $scope.search.results[0]; var readTime = lastNotification.time ? lastNotification.time : 0; - if (readTime && (!csSettings.data.wallet || csSettings.data.wallet.notificationReadTime != readTime)) { - csSettings.data.wallet = csSettings.data.wallet || {}; - csSettings.data.wallet.notificationReadTime = readTime; - csSettings.store(); + if (readTime && (!wallet.data.notifications.time || wallet.data.notifications.time != readTime)) { + wallet.data.notifications.time = readTime; + wallet.storeData(); } }; - $scope.select = function(item) { + $scope.select = function(event, item) { + + if ($scope.search.loading || event.preventDefault() || $scope.search.preventSelect) return; if (item.markAsRead && typeof item.markAsRead == 'function') { $timeout(item.markAsRead); @@ -194,38 +237,52 @@ function NotificationsController($scope, $rootScope, $ionicPopover, $state, $tim /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/notification/popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl :'plugins/es/templates/notification/popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; /* -- listeners -- */ - csWallet.api.data.on.logout($scope, $scope.resetData); - esHttp.api.node.on.stop($scope, $scope.resetData); - esHttp.api.node.on.start($scope, $scope.load); - esNotification.api.data.on.new($scope, $scope.onNewNotification); + $scope.addListeners = function() { + if (!wallet) throw "Controller wallet not set !"; + + $scope.listeners = [ + esHttp.api.node.on.stop($scope, $scope.resetData), + esHttp.api.node.on.start($scope, $scope.load), + wallet.api.data.on.logout($scope, $scope.resetData) + ]; + + if (wallet.isDefault()) { + // Subscribe to new notification + $scope.listeners.push( + esNotification.api.data.on.new($scope, $scope.onNewNotification) + ); + } + }; + + $scope.removeListeners = function() { + _.forEach($scope.listeners, function(remove){ + remove(); + }); + $scope.listeners = []; + }; } -function PopoverNotificationsController($scope, $timeout, $controller, UIUtils, $state) { +function PopoverNotificationsController($scope, $timeout, $controller, $state, + UIUtils, csWallet) { 'ngInject'; // Initialize the super class and extend it. @@ -234,8 +291,12 @@ function PopoverNotificationsController($scope, $timeout, $controller, UIUtils, // Disable list motion $scope.motion = null; + // Set the wallet to use + $scope.setWallet(csWallet); + $scope.$on('popover.shown', function() { if ($scope.search.loading) { + $scope.addListeners(); $scope.load(); } }); @@ -251,8 +312,8 @@ function PopoverNotificationsController($scope, $timeout, $controller, UIUtils, $scope.$on('popover.hidden', $scope.resetUnreadCount); - $scope.select = function(notification) { - if (!notification) return; // no selection + $scope.select = function($event, notification) { + if ($event.preventDefault() || !notification) return; // no selection if (notification.markAsRead && typeof notification.markAsRead == 'function') notification.markAsRead(); if (notification.state) { $state.go(notification.state, notification.stateParams); diff --git a/assets/www/plugins/es/js/controllers/profile-controllers.js b/assets/www/plugins/es/js/controllers/profile-controllers.js index 7580eb47e24db494c29bec1e0b30014edce59097..82a6123019bf62ed916cb97880df003ef4ac9452 100644 --- a/assets/www/plugins/es/js/controllers/profile-controllers.js +++ b/assets/www/plugins/es/js/controllers/profile-controllers.js @@ -2,19 +2,34 @@ angular.module('cesium.es.profile.controllers', ['cesium.es.services']) .config(function($stateProvider) { - $stateProvider.state('app.user_edit_profile', { - url: "/wallet/profile/edit", - views: { - 'menuContent': { - templateUrl: "plugins/es/templates/user/edit_profile.html", - controller: 'ESViewEditProfileCtrl' + $stateProvider + .state('app.edit_profile', { + url: "/wallet/profile/edit", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/user/edit_profile.html", + controller: 'ESViewEditProfileCtrl' + } + }, + cache: false, + data: { + auth: true } - }, - cache: false, - data: { - auth: true - } - }); + }) + + .state('app.edit_profile_by_id', { + url: "/wallets/:id/profile/edit", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/user/edit_profile.html", + controller: 'ESViewEditProfileCtrl' + } + }, + cache: false, + data: { + login: true + } + }); }) @@ -23,7 +38,7 @@ angular.module('cesium.es.profile.controllers', ['cesium.es.services']) ; -function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $focus, $translate, $controller, +function ESViewEditProfileController($scope, $q, $timeout, $state, $focus, $translate, $controller, $ionicHistory, $ionicPopover, UIUtils, csWallet, esHttp, esProfile, ModalUtils, Device) { 'ngInject'; @@ -47,19 +62,32 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ }; $scope.socialReorder = true; - $scope.$on('$ionicView.enter', function(e) { - $scope.loadWallet() - .then(function(walletData) { - return $scope.load(walletData); + var wallet; + + $scope.enter = function(e, state) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + $scope.walletId = wallet.id; + + return wallet.auth({ + minData: true }) + .then($scope.load) .catch(function(err){ if (err == 'CANCELLED') { - return $scope.close() - .then(UIUtils.loading.hide); + UIUtils.loading.hide(10); + $scope.cancel(); + return; } UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')(err); }); - }); + }; + $scope.$on('$ionicView.enter', $scope.enter); $scope.$on('$stateChangeStart', function (event, next, nextParams, fromState) { if ($scope.dirty && !$scope.saving) { @@ -124,34 +152,32 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ $scope.updateView(walletData, {}); } + UIUtils.loading.hide(); + + // Update loading - done with a delay, to avoid trigger onFormDataChanged() + return $timeout(function() { + $scope.loading = false; + }, 1000); + }) + .then(function() { // removeIf(device) $focus('profile-name'); // endRemoveIf(device) }) - .catch(function(err){ - UIUtils.loading.hide(10); - UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')(err); - }); + .catch(UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')); }; $scope.setForm = function(form) { $scope.form = form; }; - $scope.updateView = function(wallet, profile) { - $scope.walletData = wallet; + $scope.updateView = function(walletData, profile) { + $scope.walletData = walletData; $scope.formData = profile; if (profile.avatar) { $scope.avatarStyle={'background-image':'url("'+$scope.avatar.src+'")'}; } - $scope.motion.show(); - UIUtils.loading.hide(); - - // Update loading - done with a delay, to avoid trigger onFormDataChanged() - $timeout(function() { - $scope.loading = false; - }, 1000); }; $scope.onFormDataChanged = function() { @@ -161,7 +187,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ $scope.$watch('formData', $scope.onFormDataChanged, true); $scope.save = function(silent, hasWaitDebounce) { - if($scope.form.$invalid || !$rootScope.walletData || ($scope.saving && !hasWaitDebounce)) { + if($scope.form.$invalid || !$scope.walletData || ($scope.saving && !hasWaitDebounce)) { return $q.reject(); } @@ -238,7 +264,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ } if (!$scope.existing) { - return esProfile.add(formData) + return esProfile.add(formData, {wallet: wallet}) .then(function() { console.info("[ES] [profile] Successfully created."); $scope.existing = true; @@ -251,7 +277,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ .catch(onError('PROFILE.ERROR.SAVE_PROFILE_FAILED')); } else { - return esProfile.update(formData, {id: $rootScope.walletData.pubkey}) + return esProfile.update(formData, {id: $scope.walletData.pubkey, wallet: wallet}) .then(function() { console.info("[ES] Profile successfully updated."); $scope.saving = false; @@ -291,11 +317,27 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ $scope.cancel = function() { $scope.dirty = false; // force not saved - $scope.close(); + if (wallet.isDefault()) { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + return $state.go('app.view_wallet'); + } + else { + return $state.go('app.view_wallet_by_id', {id: wallet.id}); + } }; $scope.close = function() { - return $state.go('app.view_wallet', {refresh: true}); + if (wallet.isDefault()) { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + return $state.go('app.view_wallet', {refresh: true}); + } + else { + return $state.go('app.view_wallet_by_id', {refresh: true, id: wallet.id}); + } }; $scope.showAvatarModal = function() { @@ -343,7 +385,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ // Hide popover if need $scope.hideActionsPopover(); - return $scope.existing && csWallet.auth({minData: true}) + return $scope.existing && wallet.auth({minData: true}) .then(function(walletData) { UIUtils.loading.hide(); @@ -355,9 +397,11 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ // removeIf(no-device) UIUtils.loading.show(); // endRemoveIf(no-device) - return esProfile.remove(walletData.pubkey) + return esProfile.remove(walletData.pubkey, {wallet: wallet}) .then(function () { - walletData.name=null; + if (wallet.isDefault()) { + walletData.name=null; // keep local name, on children wallets + } walletData.profile = null; walletData.avatar = null; console.debug('[ES] [profile] Successfully deleted'); @@ -378,26 +422,20 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ /* -- Popover -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/user/edit_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/user/edit_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; } diff --git a/assets/www/plugins/es/js/controllers/registry-controllers.js b/assets/www/plugins/es/js/controllers/registry-controllers.js index d9e25ef22afdd748e9e2f36a2a6279ccac360f8a..04b3c29fb109e1e58a6f46fa5a4d4ef1242b4f81 100644 --- a/assets/www/plugins/es/js/controllers/registry-controllers.js +++ b/assets/www/plugins/es/js/controllers/registry-controllers.js @@ -33,7 +33,7 @@ angular.module('cesium.es.registry.controllers', ['cesium.es.services', 'cesium. }) .state('app.wallet_pages', { - url: "/wallet/pages?refresh", + url: "/account/pages?refresh", views: { 'menuContent': { templateUrl: "plugins/es/templates/registry/view_wallet_pages.html", @@ -42,7 +42,23 @@ angular.module('cesium.es.registry.controllers', ['cesium.es.services', 'cesium. }, data: { login: true, - minData: true + minData: true, + silentLocationChange: true + } + }) + + .state('app.wallet_pages_by_id', { + url: "/wallets/:id/pages?refresh", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/registry/view_wallet_pages.html", + controller: 'ESWalletPagesCtrl' + } + }, + data: { + login: true, + minData: true, + silentLocationChange: true } }) @@ -68,7 +84,7 @@ angular.module('cesium.es.registry.controllers', ['cesium.es.services', 'cesium. .state('app.registry_add_record', { cache: false, - url: "/page/add/:type", + url: "/page/add/:type?wallet", views: { 'menuContent': { templateUrl: "plugins/es/templates/registry/edit_record.html", @@ -83,7 +99,7 @@ angular.module('cesium.es.registry.controllers', ['cesium.es.services', 'cesium. .state('app.registry_edit_record', { cache: false, - url: "/page/edit/:id/:title", + url: "/page/edit/:id/:title?wallet", views: { 'menuContent': { templateUrl: "plugins/es/templates/registry/edit_record.html", @@ -209,7 +225,7 @@ function ESRegistryLookupController($scope, $focus, $timeout, $filter, $controll }); } $scope.search.geoPoint = csWallet.data.profile.geoPoint; - $scope.search.location = csWallet.data.profile.city||(csWallet.data.profile.geoPoint ? 'profile position' : undefined); + $scope.search.location = csWallet.data.profile.city||(csWallet.data.profile.geoPoint ? $translate.instant('LOCATION.PROFILE_POSITION') : undefined); } } @@ -656,50 +672,38 @@ function ESRegistryLookupController($scope, $focus, $timeout, $filter, $controll /* -- popovers -- */ $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/registry/lookup_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl :'plugins/es/templates/registry/lookup_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.filtersPopover = null; } }; $scope.showFiltersPopover = function(event) { - if (!$scope.filtersPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/registry/lookup_popover_filters.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl :'plugins/es/templates/registry/lookup_popover_filters.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.filtersPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.filtersPopover.remove(); - }); - $scope.filtersPopover.show(event); - }); - } - else { - $scope.filtersPopover.show(event); - } + } + }); }; $scope.hideFiltersPopover = function() { if ($scope.filtersPopover) { $scope.filtersPopover.hide(); + $scope.filtersPopover = null; } }; @@ -718,7 +722,7 @@ function ESRegistryLookupController($scope, $focus, $timeout, $filter, $controll } -function ESWalletPagesController($scope, $controller, $timeout, UIUtils, csWallet) { +function ESWalletPagesController($scope, $controller, $timeout, UIUtils, esModals, csWallet) { 'ngInject'; // Initialize the super class and extend it. @@ -726,15 +730,25 @@ function ESWalletPagesController($scope, $controller, $timeout, UIUtils, csWalle $scope.searchTextId = undefined; // avoid focus + var wallet; + // Override the default enter $scope.enter = function(e, state) { if (!$scope.entered) { - return csWallet.login({minData: true}) + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + return wallet.login({minData: true}) .then(function(walletData) { UIUtils.loading.hide(); $scope.search.issuer = walletData.pubkey; $scope.search.advanced = true; $timeout($scope.doSearch, 100); + $scope.showFab('fab-wallet-add-registry-record'); }); } else { @@ -746,12 +760,18 @@ function ESWalletPagesController($scope, $controller, $timeout, UIUtils, csWalle }; $scope.doUpdate = function() { - if (!csWallet.isLogin()) return; + if (!wallet || !wallet.isLogin()) return; $scope.search.issuer = csWallet.data.pubkey; $scope.search.advanced = true; return $scope.doSearch(); }; + // Override inherited, to pass the select wallet + $scope.showNewPageModal = function() { + $scope.hidePopovers(); + return esModals.showNewPage({wallet: wallet}); + }; + } @@ -764,6 +784,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.category = {}; $scope.pictures = []; $scope.canEdit = false; + $scope.showTransfer = false; $scope.loading = true; $scope.motion = UIUtils.motion.fadeSlideIn; @@ -780,7 +801,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.$broadcast('$recordView.enter', state); } else { - $state.go('app.registry_lookup'); + $state.go('app.wot_lookup.tab_registry'); } }); @@ -798,7 +819,8 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.id= data.id; $scope.formData = data.record; //console.debug('Loading record', $scope.formData); - $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer); + $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer) || csWallet.children.hasPubkey($scope.formData.issuer); + $scope.showTransfer = !$scope.canEdit && $scope.formData.pubkey; $scope.issuer = data.issuer; // avatar $scope.avatar = $scope.formData.avatar; @@ -821,7 +843,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.loading = false; if (err && err.ucode === 404) { UIUtils.toast.show('REGISTRY.ERROR.RECORD_NOT_EXISTS'); - $state.go('app.registry_lookup'); + $state.go('app.wot_lookup.tab_registry'); } else { UIUtils.onError('REGISTRY.ERROR.LOAD_RECORD_FAILED')(err); @@ -870,13 +892,18 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout // Edit click $scope.edit = function() { + var wallet = csWallet.isUserPubkey($scope.formData.issuer) ? csWallet : csWallet.children.getByPubkey($scope.formData.issuer); + if (!wallet) return; UIUtils.loading.show(); - $state.go('app.registry_edit_record', {id: $scope.id}); + return $state.go('app.registry_edit_record', {id: $scope.id, wallet: wallet.id}); }; $scope.delete = function() { $scope.hideActionsPopover(); + var wallet = csWallet.isUserPubkey($scope.formData.issuer) ? csWallet : csWallet.children.getByPubkey($scope.formData.issuer); + if (!wallet) return; + // translate var translations; $translate(['REGISTRY.VIEW.REMOVE_CONFIRMATION', 'REGISTRY.INFO.RECORD_REMOVED']) @@ -886,15 +913,21 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout }) .then(function(confirm) { if (confirm) { - esRegistry.record.remove($scope.id) + esRegistry.record.remove($scope.id, {wallet: wallet}) .then(function () { - if (csWallet.data.pages && csWallet.data.pages.count) { - csWallet.data.pages.count--; + if (wallet.data.pages && wallet.data.pages.count) { + wallet.data.pages.count--; } $ionicHistory.nextViewOptions({ historyRoot: true }); - $state.go('app.wallet_pages', {refresh: true}); + if (wallet.isDefault()) { + $state.go('app.wallet_pages', {refresh: true}); + } + else { + $state.go('app.wallet_pages_by_id', {refresh: true, id: wallet.id}); + } + UIUtils.toast.show(translations['REGISTRY.INFO.RECORD_REMOVED']); }) .catch(UIUtils.onError('REGISTRY.ERROR.REMOVE_RECORD_FAILED')); @@ -904,27 +937,22 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout /* -- modals & popover -- */ + $scope.showActionsPopover = function(event) { - if (!$scope.actionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/registry/view_popover_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/registry/view_popover_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); - }); - } - else { - $scope.actionsPopover.show(event); - } + } + }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; @@ -975,26 +1003,37 @@ function ESRegistryRecordEditController($scope, $timeout, $state, $q, $ionicHis $scope.form = form; }; + var wallet; + $scope.$on('$ionicView.enter', function(e, state) { - $scope.loadWallet({minData: true}) - .then(function(walletData) { - $scope.walletData = walletData; - if (state.stateParams && state.stateParams.id) { // Load by id - $scope.load(state.stateParams.id); - } - else { - if (state.stateParams && state.stateParams.type) { - $scope.updateView({ - record: { - type: state.stateParams.type - } - }); + + if ($scope.loading) { + wallet = (state.stateParams && state.stateParams.wallet && state.stateParams.wallet != 'default') ? csWallet.children.get(state.stateParams.wallet) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + return wallet.login({minData: true}) + .then(function(walletData) { + $scope.walletData = walletData; + if (state.stateParams && state.stateParams.id) { // Load by id + $scope.load(state.stateParams.id); } - } - // removeIf(device) - $focus('registry-record-title'); - // endRemoveIf(device) - }); + else { + if (state.stateParams && state.stateParams.type) { + $scope.updateView({ + record: { + type: state.stateParams.type + } + }); + } + } + // removeIf(device) + $focus('registry-record-title'); + // endRemoveIf(device) + }); + } }); $scope.$on('$stateChangeStart', function (event, next, nextParams, fromState) { @@ -1151,7 +1190,7 @@ function ESRegistryRecordEditController($scope, $timeout, $state, $q, $ionicHis if (!$scope.needCategory()) { delete json.category; } - json.time = esHttp.date.now(); + json.time = moment().utc().unix(); // geo point if (json.geoPoint && json.geoPoint.lat && json.geoPoint.lon) { @@ -1201,15 +1240,15 @@ function ESRegistryRecordEditController($scope, $timeout, $state, $q, $ionicHis .then(function(json){ // Create if (!$scope.id) { - return esRegistry.record.add(json); + return esRegistry.record.add(json, {wallet: wallet}); } // Update - return esRegistry.record.update(json, {id: $scope.id}); + return esRegistry.record.update(json, {id: $scope.id, wallet: wallet}); }) .then(function(id) { console.info("[ES] [page] Record successfully saved."); - if (!$scope.id && csWallet.data.pages && csWallet.data.pages.count) { + if (!$scope.id && wallet.data.pages && wallet.data.pages.count) { csWallet.data.pages.count++; } $scope.id = $scope.id || id; diff --git a/assets/www/plugins/es/js/controllers/settings-controllers.js b/assets/www/plugins/es/js/controllers/settings-controllers.js index b6b981a8817aaedfa62ac18164632687ff651d3b..8635cb3f55b93f8dae44a8af0cca28e0db9f96cc 100644 --- a/assets/www/plugins/es/js/controllers/settings-controllers.js +++ b/assets/www/plugins/es/js/controllers/settings-controllers.js @@ -11,7 +11,7 @@ angular.module('cesium.es.settings.controllers', ['cesium.es.services']) points: { 'plugins': { templateUrl: "plugins/es/templates/settings/settings_extend.html", - controller: "ESExtendSettingsCtrl" + controller: "ESExtensionCtrl" } } }); @@ -48,9 +48,11 @@ function ESExtendSettingsController ($scope, PluginService) { /* * Settings extend controller */ -function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUtils, Modals, csHttp, csSettings, esHttp, esSettings) { +function ESPluginSettingsController ($scope, $window, $q, $translate, $ionicPopup, + UIUtils, Modals, csHttp, csConfig, csSettings, esHttp, esSettings) { 'ngInject'; + $scope.hasWindowNotification = !!("Notification" in window); $scope.formData = {}; $scope.popupData = {}; // need for the node popup $scope.loading = true; @@ -93,7 +95,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti node = node || { host: $scope.formData.host, port: $scope.formData.port && $scope.formData.port != 80 && $scope.formData.port != 443 ? $scope.formData.port : undefined, - wsPort: $scope.formData.wsPort && $scope.formData.wsPort != $scope.formData.port ? $scope.formData.wsPort : undefined, useSsl: angular.isDefined($scope.formData.useSsl) ? $scope.formData.useSsl : ($scope.formData.port == 443) @@ -103,14 +104,13 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti .then(function(newNode) { if (newNode.host == $scope.formData.host && newNode.port == $scope.formData.port && - newNode.wsPort == $scope.formData.wsPort && newNode.useSsl == $scope.formData.useSsl) { UIUtils.loading.hide(); return; // same node = nothing to do } UIUtils.loading.show(); - var newEsNode = esHttp.instance(newNode.host, newNode.port, newNode.wsPort, newNode.useSsl); + var newEsNode = esHttp.instance(newNode.host, newNode.port, newNode.useSsl); return newEsNode.isAlive() // ping the node .then(function(alive) { if (!alive) { @@ -123,7 +123,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti $scope.formData.host = newEsNode.host; $scope.formData.port = newEsNode.port; - $scope.formData.wsPort = newEsNode.wsPort; $scope.formData.useSsl = newEsNode.useSsl; return esHttp.copy(newEsNode); @@ -138,13 +137,10 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti // Show node popup $scope.showNodePopup = function(node) { + return $q(function(resolve, reject) { var parts = [node.host]; - if (node.wsPort && node.wsPort != (node.port||80)) { - parts.push(node.port||80); - parts.push(node.wsPort); - } - else if (node.port && node.port != 80) { + if (node.port && node.port != 80) { parts.push(node.port); } $scope.popupData.newNode = parts.join(':'); @@ -187,7 +183,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti resolve({ host: parts[0], port: parts[1] || (useSsl ? 443 : 80), - wsPort: parts[2] || parts[1] || (useSsl ? 443 : 80), useSsl: useSsl }); }); @@ -196,10 +191,15 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti }; $scope.showNodeList = function() { + // Check if need a filter on SSL node + var forceUseSsl = (csConfig.httpsMode === 'true' || csConfig.httpsMode === true || csConfig.httpsMode === 'force') || + ($window.location && $window.location.protocol === 'https:') ? true : false; + $ionicPopup._popupStack[0].responseDeferred.promise.close(); return Modals.showNetworkLookup({ enableFilter: true, - endpointFilter: esHttp.constants.ES_USER_API_ENDPOINT + endpoint: esHttp.constants.ES_USER_API_ENDPOINT, + ssl: forceUseSsl ? true: undefined }) .then(function (peer) { if (!peer) return; @@ -212,14 +212,11 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti return { host: (ep.dns ? ep.dns : (peer.hasValid4(ep) ? ep.ipv4 : ep.ipv6)), - port: ep.port || 80 + port: ep.port || 80, + useSsl: ep.useSsl || ep.port == 443 }; }) .then(function(newEsNode) { - if (!newEsNode) { - UIUtils.alert.error('ERROR.INVALID_NODE_SUMMARY'); - return; - } $scope.changeEsNode(newEsNode); }); }; @@ -227,6 +224,16 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti $scope.onFormChanged = function() { if ($scope.loading) return; + if ($scope.hasWindowNotification && + $scope.formData.notifications.emitHtml5 !== (window.Notification.permission === "granted")){ + window.Notification.requestPermission(function (permission) { + // If the user accepts, let's create a notification + $scope.formData.notifications.emitHtml5 = (permission === "granted"); // revert to false if permission not granted + $scope.onFormChanged(); // Loop + }); + return; + } + $scope.loading = true; csSettings.data.plugins = csSettings.data.plugins || {}; csSettings.data.plugins.es = csSettings.data.plugins.es ? @@ -246,7 +253,6 @@ function ESPluginSettingsController ($scope, $q, $translate, $ionicPopup, UIUti $scope.getServer = function(node) { node = node || $scope.formData; if (!node.host) return undefined; - var server = csHttp.getServer(node.host, node.port); - return server + (node.wsPort && node.wsPort != node.port ? ':' + node.wsPort : ''); + return csHttp.getServer(node.host, node.port); }; } diff --git a/assets/www/plugins/es/js/controllers/subscription-controllers.js b/assets/www/plugins/es/js/controllers/subscription-controllers.js index c9fde17b7daff3dce330a18ef98eff9de94402b6..d73f7736112f42d44862b77c9b827f59790629f7 100644 --- a/assets/www/plugins/es/js/controllers/subscription-controllers.js +++ b/assets/www/plugins/es/js/controllers/subscription-controllers.js @@ -2,20 +2,36 @@ angular.module('cesium.es.subscription.controllers', ['cesium.es.services']) .config(function($stateProvider) { - $stateProvider.state('app.edit_subscriptions', { - cache: false, - url: "/wallet/subscriptions", - views: { - 'menuContent': { - templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", - controller: 'ViewSubscriptionsCtrl' + $stateProvider + .state('app.edit_subscriptions', { + cache: false, + url: "/wallet/subscriptions", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", + controller: 'ViewSubscriptionsCtrl' + } + }, + data: { + auth: true, + minData: true } - }, - data: { - auth: true, - minData: true - } - }); + }) + + .state('app.edit_subscriptions_by_id', { + cache: false, + url: "/wallets/:id/subscriptions", + views: { + 'menuContent': { + templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html", + controller: 'ViewSubscriptionsCtrl' + } + }, + data: { + login: true, + minData: true + } + }); }) @@ -25,9 +41,10 @@ angular.module('cesium.es.subscription.controllers', ['cesium.es.services']) ; -function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, ModalUtils, esSubscription) { +function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, UIUtils, ModalUtils, esSubscription) { 'ngInject'; + $scope.loading = true; $scope.popupData = {}; // need for the node popup $scope.search = { results: [], @@ -38,25 +55,44 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod {id: "weekly", label: "weekly"} ]; - $scope.onEnter = function() { - $scope.loading = true; - $scope.loadWallet({minData: true}) - .then(function() { - UIUtils.loading.hide(); - return $scope.load(); - }) - .catch(function(err){ - if (err == 'CANCELLED') { - return UIUtils.loading.hide(); - } - UIUtils.onError('SUBSCRIPTION.ERROR.LOAD_SUBSCRIPTIONS_FAILED')(err); - }); + var wallet; + + $scope.enter = function(e, state) { + + // First load + if ($scope.loading) { + + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } + + wallet.auth({minData: true}) + .then(function() { + UIUtils.loading.hide(); + return $scope.load(); + }) + .then(function() { + $scope.showFab('fab-add-subscription-record'); + }) + .catch(function(err){ + if (err === 'CANCELLED') { + UIUtils.loading.hide(10); + $scope.loading=true; // reset for force reload next time + $ionicHistory.goBack(); + return; + } + UIUtils.onError('SUBSCRIPTION.ERROR.LOAD_SUBSCRIPTIONS_FAILED')(err); + }); + } + }; - $scope.$on('$ionicView.enter', $scope.onEnter); + $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function() { $scope.loading = true; // to avoid the call of doSave() - return esSubscription.record.load($rootScope.walletData.pubkey, $rootScope.walletData.keypair) + return esSubscription.record.load(wallet.data.pubkey, wallet.data.keypair) .then(function(results) { // Group by type var groups = _.groupBy((results || []), function (record) { @@ -74,10 +110,8 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod .then(function(results) { return csWot.extendAll(results, 'recipient'); }) - .then(function(results) { - // Display result - $scope.updateView(results); - }) + // Display result + .then($scope.updateView) .catch(function(err){ UIUtils.loading.hide(10); if (err && err.ucode == 404) { @@ -108,7 +142,7 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod if (!cat) return; type = cat.id; // get subscription parameters - if (type == 'email') { + if (type === 'email') { return $scope.showEmailModal(); } else { @@ -118,11 +152,11 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod .then(function(record) { if (!record) return; UIUtils.loading.show(); - esSubscription.record.add(record) + esSubscription.record.add(record, {wallet: wallet}) .then($scope.addToUI) .then(function() { - $rootScope.walletData.subscriptions = $rootScope.walletData.subscriptions || {count: 0}; - $rootScope.walletData.subscriptions.count++; + wallet.data.subscriptions = wallet.data.subscriptions || {count: 0}; + wallet.data.subscriptions.count++; UIUtils.loading.hide(); $scope.updateView(); }) @@ -135,20 +169,20 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod // get subscription parameters var promise; var oldRecord = angular.copy(record); - if (record.type == 'email') { + if (record.type === 'email') { promise = $scope.showEmailModal(record); } if (!promise) return; return promise - .then(function() { - if (!record) return; + .then(function(res) { + if (!res) return; UIUtils.loading.show(); record.id = oldRecord.id; - return esSubscription.record.update(record) + return esSubscription.record.update(record, wallet) .then(function() { // If recipient change, update in results - if (oldRecord.type != record.type || - oldRecord.recipient != record.recipient) { + if (oldRecord.type !== record.type || + oldRecord.recipient !== record.recipient) { $scope.removeFromUI(oldRecord); return $scope.addToUI(record); } @@ -172,10 +206,10 @@ function ViewSubscriptionsController($scope, $rootScope, $q, csWot, UIUtils, Mod } UIUtils.loading.show(); - esSubscription.record.remove(record.id) + esSubscription.record.remove(record.id, {wallet: wallet}) .then(function() { - $rootScope.walletData.subscriptions = $rootScope.walletData.subscriptions || {count: 1}; - $rootScope.walletData.subscriptions.count--; + wallet.data.subscriptions = wallet.data.subscriptions || {count: 1}; + wallet.data.subscriptions.count--; $scope.removeFromUI(record); UIUtils.loading.hide(); }) @@ -286,7 +320,8 @@ function ModalEmailSubscriptionsController($scope, Modals, csSettings, esHttp, c $scope.showNetworkLookup = function() { return Modals.showNetworkLookup({ enableFilter: true, - endpointFilter: esHttp.constants.ES_USER_API_ENDPOINT + endpoint: esHttp.constants.ES_USER_API_ENDPOINT, + bma: false }) .then(function (peer) { if (peer) { diff --git a/assets/www/plugins/es/js/controllers/wallet-controllers.js b/assets/www/plugins/es/js/controllers/wallet-controllers.js index 692eaeb1bd6fad4ba4a6a0a428e52851e1703b83..ad1ba4bfb175e0b249f0ea88046b4ecb0c6e4229 100644 --- a/assets/www/plugins/es/js/controllers/wallet-controllers.js +++ b/assets/www/plugins/es/js/controllers/wallet-controllers.js @@ -5,7 +5,8 @@ angular.module('cesium.es.wallet.controllers', ['cesium.es.services']) var enable = csConfig.plugins && csConfig.plugins.es; if (enable) { - PluginServiceProvider.extendState('app.view_wallet', { + PluginServiceProvider + .extendStates(['app.view_wallet', 'app.view_wallet_by_id'], { points: { 'after-general': { templateUrl: "plugins/es/templates/wallet/view_wallet_extend.html", @@ -13,6 +14,16 @@ angular.module('cesium.es.wallet.controllers', ['cesium.es.services']) } } }) + + .extendState('app.view_wallets', { + points: { + 'item-wallet': { + templateUrl: "plugins/es/templates/wallet/item_wallet_extend.html", + controller: 'ESExtensionCtrl' + } + } + }) + ; } @@ -23,18 +34,24 @@ angular.module('cesium.es.wallet.controllers', ['cesium.es.services']) ; -function ESWalletController($scope, $controller, esModals) { +function ESWalletController($scope, $controller, $state, esModals, csWallet) { 'ngInject'; // Initialize the super class and extend it. - angular.extend(this, $controller('ESWotIdentityViewCtrl', {$scope: $scope})); + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); $scope.showProfileHelp = false; /* -- modals -- */ $scope.showNewPageModal = function() { - return esModals.showNewPage(); + var wallet = ($state.params && $state.params.id) ? csWallet.children.get($state.params.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return; + } + + return esModals.showNewPage({wallet: wallet}); }; } diff --git a/assets/www/plugins/es/js/controllers/wot-controllers.js b/assets/www/plugins/es/js/controllers/wot-controllers.js index 420c9ecbdeadee49581580e38761fcfcaa96b415..4ac6d8ed6c890e794adaa165884c92d8ce9f7fea 100644 --- a/assets/www/plugins/es/js/controllers/wot-controllers.js +++ b/assets/www/plugins/es/js/controllers/wot-controllers.js @@ -10,7 +10,8 @@ angular.module('cesium.es.wot.controllers', ['cesium.es.services']) .extendState('app.wot_lookup', { points: { 'tabs': { - templateUrl: "plugins/es/templates/wot/lookup_extend.html" + templateUrl: "plugins/es/templates/wot/lookup_extend.html", + controller: "ESExtensionCtrl" } } }) @@ -33,6 +34,10 @@ angular.module('cesium.es.wot.controllers', ['cesium.es.services']) 'buttons': { templateUrl: "plugins/es/templates/wot/view_identity_extend.html", controller: 'ESWotIdentityViewCtrl' + }, + 'buttons-top-fab': { + templateUrl: "plugins/es/templates/wot/view_identity_extend.html", + controller: 'ESWotIdentityViewCtrl' } } }) @@ -78,25 +83,24 @@ function ESWotLookupExtendController($scope, $controller, $state) { location: location.length ? location : undefined }; - $state.go('app.registry_lookup', stateParams); + $state.go('app.wot_lookup.tab_registry', stateParams); }; } -function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, esSettings, PluginService, csWallet, - esModals, esHttp, esWallet, esInvitation) { +function ESWotIdentityViewController($scope, $ionicPopover, $q, $controller, UIUtils, Modals, csWallet, + esModals, esWallet, esInvitation) { 'ngInject'; - $scope.extensionPoint = PluginService.extensions.points.current.get(); - $scope.enable = esSettings.isEnable(); - esSettings.api.state.on.changed($scope, function(enable) { - $scope.enable = enable; - }); + // Initialize the super class and extend it. + angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); + + $scope.canCertify = false; // disable certity on the popover (by default - override by the wot map controller) /* -- modals -- */ $scope.showNewMessageModal = function(confirm) { - return $scope.loadWallet({minData: true}) + return csWallet.login({minData: true, method: 'default'}) .then(function() { UIUtils.loading.hide(); @@ -133,6 +137,7 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, return csWallet.auth({minData: true}) .then(function(walletData) { UIUtils.loading.hide(); + if (!walletData) return; // Not allow for non-member - issue #561 if (!walletData.isMember) { @@ -162,7 +167,7 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, var keypair = res[0]; var confirm = res[1]; if (!confirm) return; - var time = esHttp.date.now(); // use same date for each invitation + var time = moment().utc().unix(); // use same date for each invitation return $q.all( identities.reduce(function(res, identity){ return res.concat( @@ -189,9 +194,13 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, $scope.hideCertificationActionsPopover(); var identities; - return csWallet.auth({minData: true}) + return (csWallet.children.count() ? Modals.showSelectWallet({displayBalance: false}) : $q.when(csWallet)) + .then(function(wallet) { + return wallet.auth({minData: true}); + }) .then(function(walletData) { UIUtils.loading.hide(); + if (!walletData) return; // Not allow for non-member - issue #561 if (!walletData.isMember) { @@ -217,11 +226,10 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, UIUtils.alert.confirm('WOT.CONFIRM.ASK_CERTIFICATIONS', undefined, {okText: 'COMMON.BTN_SEND'}) ]) .then(function(res) { - if (!res) return; - var keypair = res[0]; - var confirm = res[1]; - if (!confirm) return; - var time = esHttp.date.now(); // use same date for each invitation + var keypair = res && res[0]; + var confirm = res && res[1]; + if (!keypair || !confirm) return; + var time = moment().utc().unix(); // use same date for each invitation return $q.all(identities.reduce(function(res, identity){ return res.concat( esInvitation.send({ @@ -244,25 +252,36 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, $scope.askCertification = function() { $scope.hideCertificationActionsPopover(); - return csWallet.auth({minData: true}) + return (csWallet.children.count() ? Modals.showSelectWallet({displayBalance: false}) : $q.when(csWallet)) + .then(function(wallet) { + return wallet.auth({minData: true}); + }) .then(function(walletData) { UIUtils.loading.hide(); + if (!walletData) return; // Not allow for non-member - issue #561 if (!walletData.isMember) { return UIUtils.alert.error('ERROR.ONLY_MEMBER_CAN_EXECUTE_THIS_ACTION'); } - + // ask confirmation return UIUtils.alert.confirm('WOT.CONFIRM.ASK_CERTIFICATION', undefined, { - okText: 'COMMON.BTN_SEND' - }) + okText: 'COMMON.BTN_SEND' + }) .then(function(confirm) { if (!confirm) return; return esInvitation.send({ issuer: walletData.pubkey, recipient: $scope.formData.pubkey, content: [walletData.uid, walletData.pubkey].join('-') - }, undefined, 'certification') + }, + { + type: 'certification', + keypair: walletData.keypair + }) + .then(function() { + UIUtils.toast.show('INVITATION.INFO.INVITATION_SENT'); + }) .catch(UIUtils.onError('INVITATION.ERROR.SEND_INVITATION_FAILED')); }); }); @@ -271,29 +290,32 @@ function ESWotIdentityViewController($scope, $ionicPopover, $q, UIUtils, Modals, /* -- Popover -- */ $scope.showCertificationActionsPopover = function(event) { - if (!$scope.certificationActionsPopover) { - $ionicPopover.fromTemplateUrl('plugins/es/templates/wot/popover_certification_actions.html', { - scope: $scope - }).then(function(popover) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/es/templates/wot/popover_certification_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { $scope.certificationActionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.certificationActionsPopover.remove(); - }); - $scope.certificationActionsPopover.show(event); - }); - } - else { - $scope.certificationActionsPopover.show(event); - } + } + }); }; $scope.hideCertificationActionsPopover = function() { if ($scope.certificationActionsPopover) { $scope.certificationActionsPopover.hide(); + $scope.certificationActionsPopover = null; } }; + if ($scope.extensionPoint === 'buttons-top-fab') { + // Show fab button, when parent execute motions + $scope.$on('$csExtension.motion', function(event) { + var canCompose = !!$scope.formData.profile; + if (canCompose) { + $scope.showFab('fab-compose-' + $scope.formData.uid); + } + }); + } // TODO : for DEV only /*$timeout(function() { diff --git a/assets/www/plugins/es/js/entities/notification.js b/assets/www/plugins/es/js/entities/notification.js index cd564c88c1fceb73773192b3fe5000a88a59a27b..f928c32002304b8ba750b9ab1704920109a9e380 100644 --- a/assets/www/plugins/es/js/entities/notification.js +++ b/assets/www/plugins/es/js/entities/notification.js @@ -1,5 +1,5 @@ -function Notification(json, markAsReadCallback) { +function EsNotification(json, markAsReadCallback) { var messagePrefixes = { 'registry': 'EVENT.REGISTRY.' @@ -42,12 +42,15 @@ function Notification(json, markAsReadCallback) { if (json.code.startsWith('MEMBER_')) { that.avatarIcon = 'ion-person'; that.icon = 'ion-information-circled positive'; + that.state = 'app.view_wallet'; + that.medianTime = that.time; } // TX else if (json.code.startsWith('TX_')) { that.avatarIcon = 'ion-card'; that.icon = (json.code == 'TX_SENT') ? 'ion-paper-airplane dark' : 'ion-archive balanced'; + that.medianTime = that.time; pubkeys = json.params.length > 0 ? json.params[0] : null; if (pubkeys && pubkeys.indexOf(',') == -1) { that.pubkey = pubkeys; @@ -61,6 +64,7 @@ function Notification(json, markAsReadCallback) { that.avatarIcon = (json.code == 'CERT_RECEIVED') ? 'ion-ribbon-b' : 'ion-ribbon-a'; that.icon = (json.code == 'CERT_RECEIVED') ? 'ion-ribbon-b balanced' : 'ion-ribbon-a gray'; that.pubkey = json.params.length > 0 ? json.params[0] : null; + that.medianTime = that.time; that.state = 'app.wallet_cert'; that.stateParams = { type: (json.code == 'CERT_RECEIVED') ? 'received' : 'given' @@ -114,4 +118,6 @@ function Notification(json, markAsReadCallback) { that.avatarIcon = 'ion-close'; that.icon = 'ion-close-circled assertive'; } + + return that; } diff --git a/assets/www/plugins/es/js/services/blockchain-services.js b/assets/www/plugins/es/js/services/blockchain-services.js index dd768ba36d1d8c1c2bf2f8c769222bf40d109047..9116acf0c87525009aa79a4368e583fbc2a8defd 100644 --- a/assets/www/plugins/es/js/services/blockchain-services.js +++ b/assets/www/plugins/es/js/services/blockchain-services.js @@ -31,22 +31,23 @@ angular.module('cesium.es.blockchain.services', ['cesium.services', 'cesium.es.h block: {}, raw: { block: { - search: esHttp.post('/:currency/block/_search'), + search: esHttp.post('/:currency/block/_search', esHttp.cache.SHORT), searchText: esHttp.get('/:currency/block/_search?q=:text'), - get: esHttp.get('/:currency/block/:number/_source') + get: esHttp.get('/:currency/block/:number/_source', esHttp.cache.SHORT) } }, - regex: { + regexp: { ES_CORE_API_ENDPOINT: exact(CONSTANTS.ES_CORE_API_ENDPOINT) } }; + exports.regex = exports.regexp; // deprecated function exact(regexpContent) { return new RegExp('^' + regexpContent + '$'); } exports.node.parseEndPoint = function(endpoint) { - var matches = REGEX.ES_CORE_API_ENDPOINT.exec(endpoint); + var matches = exports.regexp.ES_CORE_API_ENDPOINT.exec(endpoint); if (!matches) return; return { dns: matches[2] || '', diff --git a/assets/www/plugins/es/js/services/comment-services.js b/assets/www/plugins/es/js/services/comment-services.js index 8b42d98ca29c8bc75658b8a3258b34d2380dc7af..374752bbec7a371e6b57cd0fd67e7998140b66f6 100644 --- a/assets/www/plugins/es/js/services/comment-services.js +++ b/assets/www/plugins/es/js/services/comment-services.js @@ -167,16 +167,19 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', if (index === -1) return; data.result.splice(index, 1); delete data.mapById[comment.id]; + + var wallet = !csWallet.isUserPubkey(comment.issuer) ? csWallet.children.getByPubkey(comment.issuer) : csWallet; + // Send deletion request - if (csWallet.isUserPubkey(comment.issuer)) { + if (wallet) { return exports.raw.remove(comment.id) .catch(function(err){ console.error(err); - throw new Error('MARKET.ERROR.FAILED_REMOVE_COMMENT'); + throw new Error('COMMENTS.ERROR.FAILED_REMOVE_COMMENT'); }); } else { - return $q.reject("User is not the comment issuer"); + return $q.reject("No wallet found corresponding to the comment issuer"); } }; }; @@ -196,7 +199,7 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', }); // Open websocket - var time = new Date().getTime(); + var time = Date.now(); console.info("[ES] [comment] Starting websocket to listen comments on [{0}/record/{1}]".format(index, recordId.substr(0,8))); var wsChanges = exports.raw.wsChanges(); return wsChanges.open() @@ -208,7 +211,7 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', // Listen changes .then(function(){ - console.debug("[ES] [comment] Websocket opened in {0} ms".format(new Date().getTime() - time)); + console.debug("[ES] [comment] Websocket opened in {0} ms".format(Date.now() - time)); wsChanges.on(function(change) { if (!change) return; scope.$applyAsync(function() { @@ -267,7 +270,7 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', // Preparing JSON to sent var id = comment.id; var json = { - creationTime: id ? comment.creationTime || comment.time/*for compat*/ : esHttp.date.now(), + creationTime: id ? comment.creationTime || comment.time/*for compat*/ : moment().utc().unix(), message: comment.message, record: recordId, issuer: csWallet.data.pubkey diff --git a/assets/www/plugins/es/js/services/crypto-services.js b/assets/www/plugins/es/js/services/crypto-services.js index 1ddf3feaef45ae2daea41b8ee2e82a07a22b7a32..c715451e53e42525a67bbb59ea58c010136b71fd 100644 --- a/assets/www/plugins/es/js/services/crypto-services.js +++ b/assets/www/plugins/es/js/services/crypto-services.js @@ -92,7 +92,7 @@ angular.module('cesium.es.crypto.services', ['ngResource', 'cesium.services']) cypherFieldNames = [cypherFieldNames]; } - var now = new Date().getTime(); + var now = Date.now(); var issuerBoxPks = {}; // a map used as cache var jobs = [getBoxKeypair(keypair)]; @@ -129,7 +129,7 @@ angular.module('cesium.es.crypto.services', ['ngResource', 'cesium.services']) }, [])); }) .then(function() { - console.debug('[ES] [crypto] All record decrypted in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[ES] [crypto] All record decrypted in ' + (Date.now() - now) + 'ms'); return records; }); diff --git a/assets/www/plugins/es/js/services/document-services.js b/assets/www/plugins/es/js/services/document-services.js index 7eb8d2f1df6ba47cc78bfd3392537e14724981b4..41567a05474b7178d224b9c6b9b352ad35faf4f0 100644 --- a/assets/www/plugins/es/js/services/document-services.js +++ b/assets/www/plugins/es/js/services/document-services.js @@ -147,7 +147,7 @@ angular.module('cesium.es.document.services', ['ngResource', 'cesium.platform', options.index, options.type )); - var now = new Date().getTime(); + var now = Date.now(); return raw.searchText(request) .then(function(res) { @@ -158,25 +158,27 @@ angular.module('cesium.es.document.services', ['ngResource', 'cesium.platform', options.index, options.type, res && res.hits && res.hits.length || 0, - new Date().getTime() - now + Date.now() - now )); return res; }); } - function remove(document) { + function remove(document, options) { if (!document || !document.index || !document.type || !document.id) return $q.reject('Could not remove document: missing mandatory fields'); - return esHttp.record.remove(document.index, document.type)(document.id); + return esHttp.record.remove(document.index, document.type)(document.id, options); } - function removeAll(documents) { + function removeAll(documents, options) { if (!documents || !documents.length) return; - return csWallet.auth() - .then(function(walletData) { + var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet; + + return wallet.auth() // Auth once + .then(function() { // Remove each doc return $q.all(documents.reduce(function (res, doc) { - return res.concat(esHttp.record.remove(doc.index, doc.type)(doc.id, walletData)); + return res.concat(esHttp.record.remove(doc.index, doc.type)(doc.id, {wallet: wallet})); }, [])); }); } diff --git a/assets/www/plugins/es/js/services/geo-services.js b/assets/www/plugins/es/js/services/geo-services.js index 960977828319dfa65a18fa5c2e281d3369bde617..6f62b41fcaadfae4247490aabfb68c2f1ec627e5 100644 --- a/assets/www/plugins/es/js/services/geo-services.js +++ b/assets/www/plugins/es/js/services/geo-services.js @@ -29,6 +29,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser search: csHttp.get('maps.google.com', 443, '/maps/api/geocode/json') }, freegeoip: { + //search: csHttp.get('localhost', 8080, '/json/:ip'), search: csHttp.get('freegeoip.net', 443, '/json/:ip'), license: { name: 'freegeoip', @@ -88,7 +89,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser query.addressdetails = 1; // need address field - var now = new Date(); + var now = Date.now(); //console.debug('[ES] [geo] Searching position...', query); return that.raw.osm.search(query) @@ -116,7 +117,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser }); }, []); - console.debug('[ES] [geo] Found {0} address position(s)'.format(res && res.length || 0, new Date().getTime() - now.getTime()), res); + console.debug('[ES] [geo] Found {0} address position(s)'.format(res && res.length || 0, Date.now() - now), res); return res.length ? res : undefined; }) @@ -156,7 +157,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser return that.raw.freegeoip.search({ip: ip}) .then(function(res) { - //console.debug('[ES] [geo] Found IP {0} position in {0}ms'.format(res ? 1 : 0, new Date().getTime() - now.getTime())); + //console.debug('[ES] [geo] Found IP {0} position in {0}ms'.format(res ? 1 : 0, Date.now() - now.getTime())); return res ? { lat: res.latitude, lng: res.longitude diff --git a/assets/www/plugins/es/js/services/http-services.js b/assets/www/plugins/es/js/services/http-services.js index 8f7c01fd5362d2e9468e157c4df1b1fff2364351..bc1b070799232d93e40f113f2a56e540b715fcbc 100644 --- a/assets/www/plugins/es/js/services/http-services.js +++ b/assets/www/plugins/es/js/services/http-services.js @@ -4,7 +4,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic * Elastic Search Http */ .factory('esHttp', function($q, $timeout, $rootScope, $state, $sce, $translate, $window, $filter, - CryptoUtils, UIUtils, csHttp, csConfig, csSettings, BMA, csWallet, csPlatform, Api) { + CryptoUtils, UIUtils, csHttp, csConfig, csSettings, csCache, BMA, csWallet, csPlatform, Api) { 'ngInject'; // Allow to force SSL connection with port different from 443 @@ -14,12 +14,14 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic console.debug('[ES] [https] Enable SSL (forced by config or detected in URL)'); } - function Factory(host, port, wsPort, useSsl) { + function EsHttp(host, port, useSsl, useCache) { var that = this, + cachePrefix = 'esHttp-', constants = { - ES_USER_API_ENDPOINT: 'ES_USER_API( ([a-z_][a-z0-9-_.]*))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))' + ES_USER_API_ENDPOINT: 'ES_USER_API( ([a-z_][a-z0-9-_.]*))?( ([0-9.]+))?( ([0-9a-f:]+))?( ([0-9]+))', + MAX_UPLOAD_BODY_SIZE: csConfig.plugins && csConfig.plugins.es && csConfig.plugins.es.maxUploadBodySize || 2097152 /*=2M*/ }, regexp = { IMAGE_SRC: exact('data:([A-Za-z//]+);base64,(.+)'), @@ -41,22 +43,22 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic that.started = false; that.init = init; - init(host, port, wsPort, useSsl); + init(host, port, useSsl, useCache); + that.useCache = angular.isDefined(useCache) ? useCache : false; // need here because used in get() function - function init(host, port, wsPort, useSsl) { + function init(host, port, useSsl, useCache) { // Use settings as default if (!host && csSettings.data) { host = host || (csSettings.data.plugins && csSettings.data.plugins.es ? csSettings.data.plugins.es.host : null); port = port || (host ? csSettings.data.plugins.es.port : null); - wsPort = wsPort || (host ? csSettings.data.plugins.es.wsPort : null); useSsl = angular.isDefined(useSsl) ? useSsl : (port == 443 || csSettings.data.plugins.es.useSsl || forceUseSsl); } that.alive = false; that.host = host; that.port = port || ((useSsl || forceUseSsl) ? 443 : 80); - that.wsPort = wsPort || that.port; that.useSsl = angular.isDefined(useSsl) ? useSsl : (that.port == 443 || forceUseSsl); + that.server = csHttp.getServer(host, port); } @@ -67,15 +69,13 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic var host = data.plugins.es.host; var useSsl = data.plugins.es.port == 443 || data.plugins.es.useSsl || forceUseSsl; var port = data.plugins.es.port || (useSsl ? 443 : 80); - var wsPort = data.plugins.es.wsPort || port; - return isSameNode(host, port, wsPort, useSsl); + return isSameNode(host, port, useSsl); } - function isSameNode(host, port, wsPort, useSsl) { + function isSameNode(host, port, useSsl) { return (that.host == host) && (that.port == port) && - (!wsPort || that.wsPort == wsPort) && (angular.isUndefined(useSsl) || useSsl == that.useSsl); } @@ -129,46 +129,56 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic sock.close(); }); that.cache = _emptyCache(); + + csCache.clear(cachePrefix); }; that.copy = function(otherNode) { if (that.started) that.stop(); - that.init(otherNode.host, otherNode.port, otherNode.wsPort, otherNode.useSsl || otherNode.port == 443); + that.init(otherNode.host, otherNode.port, otherNode.useSsl || otherNode.port == 443); that.data.isTemporary = false; // reset temporary flag return that.start(true /*skipInit*/); }; - - - // Get time (UTC) - that.date = { now : csHttp.date.now }; + that.byteCount = function (s) { + s = (typeof s == 'string') ? s : JSON.stringify(s); + return encodeURI(s).split(/%(?:u[0-9A-F]{2})?[0-9A-F]{2}|./).length - 1; + }; that.getUrl = function(path) { return csHttp.getUrl(that.host, that.port, path, that.useSsl); }; - that.get = function (path) { + that.get = function (path, cacheTime) { + + cacheTime = that.useCache && cacheTime; + var cacheKey = path + (cacheTime ? ('#'+cacheTime) : ''); - var getRequest = function(params) { + var getRequestFn = function(params) { if (!that.started) { if (!that._startPromise) { - console.error('[ES] [http] Trying to get [{0}] before start()...'.format(path)); + console.error('[ES] [http] Trying to get [{0}] before start(). Waiting...'.format(path)); } return that.ready().then(function(start) { if (!start) return $q.reject('ERROR.ES_CONNECTION_ERROR'); - return getRequest(params); // loop + return getRequestFn(params); // loop }); } - var request = that.cache.getByPath[path]; + var request = that.cache.getByPath[cacheKey]; if (!request) { - request = csHttp.get(that.host, that.port, path, that.useSsl); - that.cache.getByPath[path] = request; + if (cacheTime) { + request = csHttp.getWithCache(that.host, that.port, path, that.useSsl, cacheTime, null, null, cachePrefix); + } + else { + request = csHttp.get(that.host, that.port, path, that.useSsl); + } + that.cache.getByPath[cacheKey] = request; } return request(params); }; - return getRequest; + return getRequestFn; }; that.post = function(path) { @@ -197,7 +207,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic return function() { var sock = that.cache.wsByPath[path]; if (!sock) { - sock = csHttp.ws(that.host, that.wsPort, path, that.useSsl); + sock = csHttp.ws(that.host, that.port, path, that.useSsl); that.cache.wsByPath[path] = sock; } return sock; @@ -208,8 +218,8 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic return csHttp.get(that.host, that.port, '/node/summary', that.useSsl)() .then(function(json) { var software = json && json.duniter && json.duniter.software || 'unknown'; - if (software == 'duniter4j-elasticsearch') return true; - console.error("[ES] [http] Not a Duniter4j ES node, but a {0} node".format(software)); + if (software === "cesium-plus-pod" || software === "duniter4j-elasticsearch") return true; + console.error("[ES] [http] Not a Cesium+ Pod, but a {0} node. Please check '/node/summary'".format(software)); return false; }) .catch(function() { @@ -232,8 +242,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Remember the default node defaultSettingsNode = defaultSettingsNode || { host: settings.host, - port: settings.port, - wsPort: settings.wsPort + port: settings.port }; var fallbackNode = settings.fallbackNodes && fallbackNodeIndex < settings.fallbackNodes.length && settings.fallbackNodes[fallbackNodeIndex++]; @@ -251,7 +260,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic that.cleanCache(); - that.init(fallbackNode.host, fallbackNode.port, fallbackNode.wsPort, fallbackNode.useSsl || fallbackNode.port == 443); + that.init(fallbackNode.host, fallbackNode.port, fallbackNode.useSsl || fallbackNode.port == 443); // check is alive then loop return that.isAlive().then(that.checkNodeAlive); @@ -284,7 +293,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic that.server, (that.useSsl ? ' (SSL on)' : '') )); - var now = new Date().getTime(); + var now = Date.now(); return that.checkNodeAlive() .then(function(alive) { @@ -300,7 +309,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Add listeners addListeners(); - console.debug('[ES] [http] Started in '+(new Date().getTime()-now)+'ms'); + console.debug('[ES] [http] Started in '+(Date.now()-now)+'ms'); that.api.node.raise.start(); @@ -343,10 +352,9 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic prefix = prefix || '#'; var reg = prefix === '@' ? regexp.USER_TAG : regexp.HASH_TAG; var matches = value && reg.exec(value); - var tags; + var tags = matches && []; while(matches) { var tag = matches[1]; - tags = tags || []; if (!_.contains(tags, tag)) { tags.push(tag); } @@ -358,10 +366,9 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic function parseUrlsFromText(value) { var matches = value && regexp.URL.exec(value); - var urls; + var urls = matches && []; while(matches) { var url = matches[0]; - urls = urls || []; if (!_.contains(urls, url)) { urls.push(url); } @@ -390,8 +397,10 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Replace URL in description var urls = parseUrlsFromText(content); _.forEach(urls, function(url){ + // Make sure protocol is defined + var href = (url.startsWith('http://') || url.startsWith('https://')) ? url : ('http://' + url); // Redirect URL to the function 'openLink', to open a new window if need (e.g. desktop app) - var link = '<a on-tap=\"openLink($event, \'{0}\')\" href=\"{1}\" target="_blank">{2}</a>'.format(url, url, truncUrlFilter(url)); + var link = '<a on-tap=\"openLink($event, \'{0}\')\" href=\"{1}\" target="_blank">{2}</a>'.format(href, href, truncUrlFilter(url)); content = content.replace(url, link); }); @@ -404,9 +413,9 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic // Replace user tags var userTags = parseTagsFromText(content, '@'); - _.forEach(userTags, function(uid){ - var link = '<a ui-sref=\"{0}({uid: \'{1}\'})\">@{2}</a>'.format(options.uidState, uid, uid); - content = content.replace('@'+uid, link); + _.forEach(userTags, function(tag){ + var link = '<a ui-sref=\"{0}({uid: \'{1}\'})\">@{2}</a>'.format(options.uidState, tag, tag); + content = content.replace('@'+tag, link); }); } return content; @@ -440,21 +449,40 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic function postRecord(path, options) { options = options || {}; var postRequest = that.post(path); - return function(record, params) { - return csWallet.auth() - .then(function(walletData) { + return function(record, options) { + options = options || {}; + var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) || + ((!options.pubkey || csWallet.isUserPubkey(options.pubkey)) && csWallet) || + (options.pubkey && csWallet.children.getByPubkey(options.pubkey)); + + var keypair = options.keypair || wallet && wallet.data && wallet.data.keypair; + + if (!keypair && !wallet) { + throw new Error('Missing wallet or keypair, to sign record'); + } + + // Create the POSt request params, + // but BEFORE, remove protected options + delete options.wallet; + delete options.walletId; + delete options.keypair; + var params = angular.copy(options); + params.pubkey = params.pubkey || wallet.data.pubkey; + + return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true})) + .then(function() { if (options.creationTime && !record.creationTime) { - record.creationTime = that.date.now(); + record.creationTime = moment().utc().unix(); } // Always update the time - fix #572 // Make sure time is always > previous (required by ES node) - var now = that.date.now(); + var now = moment().utc().unix(); record.time = (!record.time || record.time < now) ? now : (record.time+1); var obj = angular.copy(record); delete obj.signature; delete obj.hash; - obj.issuer = walletData.pubkey; + obj.issuer = params.pubkey; // force keypair pubkey if (!obj.version) { obj.version = 2; } @@ -464,29 +492,41 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic fillRecordTags(obj, options.tagFields); } - //console.debug("Will send obj: ", obj); - var str = JSON.stringify(obj); - - return CryptoUtils.util.hash(str) - .then(function(hash) { - return CryptoUtils.sign(hash, walletData.keypair) - .then(function(signature) { - // Prepend hash+signature - str = '{"hash":"{0}","signature":"{1}",'.format(hash, signature) + str.substring(1); - // Send data - return postRequest(str, params) - .then(function (id){ - return id; - }); - }); - }); - }); + var str = JSON.stringify(obj); + + return CryptoUtils.util.hash(str) + .then(function(hash) { + return CryptoUtils.sign(hash, keypair) + .then(function(signature) { + // Prepend hash+signature + str = '{"hash":"{0}","signature":"{1}",'.format(hash, signature) + str.substring(1); + // Send data + return postRequest(str, params) + .then(function (id){ + + // Clear cache + csCache.clear(cachePrefix); + + return id; + }) + .catch(function(err) { + var bodyLength = that.byteCount(obj); + if (bodyLength > constants.MAX_UPLOAD_BODY_SIZE) { + throw {message: 'ERROR.ES_MAX_UPLOAD_BODY_SIZE', length: bodyLength}; + } + throw err; + }); + }); + }); + }); }; } function removeRecord(index, type) { - return function(id) { - return (csWallet.isAuth() ? $q.when(csWallet.data) : csWallet.auth({silent: true, minData: true})) + return function(id, options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true})) .then(function(walletData) { var obj = { @@ -495,7 +535,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic type: type, id: id, issuer: walletData.pubkey, - time: that.date.now() + time: moment().utc().unix() }; var str = JSON.stringify(obj); return CryptoUtils.util.hash(str) @@ -586,11 +626,13 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic function parseEndPoint(endpoint) { var matches = regexp.ES_USER_API_ENDPOINT.exec(endpoint); if (!matches) return; + var port = matches[8] || 80; return { "dns": matches[2] || '', "ipv4": matches[4] || '', "ipv6": matches[6] || '', - "port": matches[8] || 80 + "port": port, + "useSsl": port == 80 ? false : (port == 443) }; } @@ -631,6 +673,10 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic sameAsSettings: isSameNodeAsSettings, isFallback: isFallbackNode }, + network: { + peering: that.get('/network/peering'), + peers: that.get('/network/peers') + }, record: { post: postRecord, remove: removeRecord @@ -647,6 +693,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic parseAsHtml: parseAsHtml, findObjectInTree: findObjectInTree }, + cache: csHttp.cache, constants: constants }; exports.constants.regexp = regexp; @@ -654,10 +701,10 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic } - var service = new Factory(); + var service = new EsHttp(undefined, undefined, undefined, true); - service.instance = function(host, port, wsPort, useSsl) { - return new Factory(host, port, wsPort, useSsl); + service.instance = function(host, port, useSsl, useCache) { + return new EsHttp(host, port, useSsl, useCache); }; return service; diff --git a/assets/www/plugins/es/js/services/invitation-services.js b/assets/www/plugins/es/js/services/invitation-services.js index 0128e617e73b734e5f69528e2f63f86d1f0ee5a2..befb724efd60b498a31e534a918750b188b704b0 100644 --- a/assets/www/plugins/es/js/services/invitation-services.js +++ b/assets/www/plugins/es/js/services/invitation-services.js @@ -39,6 +39,7 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', function onWalletInit(data) { data.invitations = data.invitations || {}; data.invitations.unreadCount = null; + data.invitations.time = null; } function onWalletReset(data) { @@ -47,22 +48,33 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', } } - function onWalletLogin(data, deferred) { + function onWalletLoad(data, deferred) { deferred = deferred || $q.defer(); if (!data || !data.pubkey) { deferred.resolve(); return deferred.promise; } - console.debug('[ES] [invitations] Loading count...'); - var now = new Date().getTime(); + var now = Date.now(); + var time = Math.trunc(now / 1000); - // Count unread messages + // Skip if loaded less than 1 min ago + // (This is need to avoid reload on login AND load phases) + if (data.invitations && data.invitations.time && (time - data.invitations.time < 30 /*=30s*/)) { + console.debug('[ES] [invitation] Skipping load (loaded '+(time - data.invitations.time)+'s ago)'); + deferred.resolve(); + return deferred.promise; + } + + console.debug('[ES] [invitation] Loading count...'); + + // Count unread invitations countUnreadInvitations(data.pubkey) .then(function(unreadCount){ data.invitations = data.invitations || {}; data.invitations.unreadCount = unreadCount; - console.debug('[ES] [invitation] Loaded count (' + unreadCount + ') in '+(new Date().getTime()-now)+'ms'); + data.invitations.time = time; + console.debug('[ES] [invitation] Loaded count (' + unreadCount + ') in '+(Date.now()-now)+'ms'); deferred.resolve(data); }) .catch(function(err){ @@ -142,11 +154,13 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }); } - function sendInvitation(record, keypair, type) { - type = type || 'certification'; + function sendInvitation(record, options) { + options = options || {}; + options.type = options.type || 'certification'; + var keypair = options.keypair || (options.wallet && options.wallet.data.keypair); return esWallet.box.record.pack(record, keypair, 'recipient', ['content', 'comment']) .then(function(record) { - return that.raw[type].add(record); + return that.raw[options.type].add(record, options); }); } @@ -180,16 +194,18 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }); } - function loadInvitations(options) { + function loadInvitations(options, keypair) { if (!csWallet.isLogin()) return $q.when([]); // Should never happen options = options || {}; options.from = options.from || 0; options.size = options.size || constants.DEFAULT_LOAD_SIZE; + + var issuer = options.issuer || csWallet.data.pubkey; var request = { sort: { "time" : "desc" }, - query: {bool: {filter: {term: {recipient: csWallet.data.pubkey}}}}, + query: {bool: {filter: {term: {recipient: issuer}}}}, from: options.from, size: options.size, _source: fields.commons @@ -200,13 +216,8 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', query.bool.must = [{range: {time: {gt: options.readTime}}}]; } - return $q.all([ - esWallet.box.getKeypair(), - that.raw.certification.postSearch(request) - ]) + return that.raw.certification.postSearch(request) .then(function(res) { - var keypair = res[0]; - res = res[1]; if (!res || !res.hits || !res.hits.total) return []; var invitations = res.hits.hits.reduce(function (result, hit) { @@ -264,42 +275,47 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }); } - function deleteInvitation(invitation) { + function deleteInvitation(invitation, options) { if (!invitation || !invitation.id) throw 'Invalid invitation (empty or without id). Could not delete.'; var type = invitation.type || 'certification'; - return that.raw[type].remove(invitation.id) + var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet; + return that.raw[type].remove(invitation.id, {wallet: wallet}) .then(function() { // Always reset unread count - csWallet.data.invitations.unreadCount = 0; + wallet.data.invitations.unreadCount = 0; - if (!csWallet.data.invitations || !csWallet.data.invitations.list) return; + if (!wallet.data.invitations || !wallet.data.invitations.list) return; // Remove form list - csWallet.data.invitations.list.splice(csWallet.data.invitations.list.indexOf(invitation), 1); + wallet.data.invitations.list.splice(wallet.data.invitations.list.indexOf(invitation), 1); }); } - function deleteInvitationsByIds(ids, type) { + function deleteInvitationsByIds(ids, type, options) { if (!ids || !ids.length) return $q.when(); type = type || 'certification'; return $q.all( ids.reduce(function(res, id) { - return res.concat(that.raw[type].remove(id)); + return res.concat(that.raw[type].remove(id, options)); }, []) ); } - function deleteAllInvitations(pubkey, type) { - pubkey = pubkey || csWallet.data.pubkey; + function deleteAllInvitationsByPubkey(type, options) { + type = type || 'certification'; - console.debug('[ES] [invitation] Deleting all invitations...'); - var now = new Date().getTime(); - var countBeforeDeletion = (csWallet.data.invitations && csWallet.data.invitations.count) || 0; - var unreadCountBeforeDeletion = (csWallet.data.invitations && csWallet.data.invitations.unreadCount) || 0; + var now = Date.now(); + console.debug('[ES] [invitation] Deleting all {0} invitations...'.format(type)); + + var wallet = (options && options.pubkey && csWallet.children.getByPubkey(options.pubkey)) || + (options && options.walletId && csWallet.children.getByPubkey(options.walletId)) || + csWallet; + var countBeforeDeletion = (wallet.data.invitations && wallet.data.invitations.count) || 0; + var unreadCountBeforeDeletion = (wallet.data.invitations && wallet.data.invitations.unreadCount) || 0; // Get invitation ids - return that.raw[type].getIds({pubkey: pubkey}) + return that.raw[type].getIds({pubkey: wallet.data.pubkey}) .then(function(res) { if (!res || !res.hits || !res.hits.total) return; var ids = res.hits.hits.reduce(function (res, hit) { @@ -307,26 +323,26 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }, []); // Do deletion by ids - return deleteInvitationsByIds(ids, type) + return deleteInvitationsByIds(ids, type, {walletId: wallet.id}) .then(function() { // Update wallet count - csWallet.data.invitations = csWallet.data.invitations || {}; + wallet.data.invitations = wallet.data.invitations || {}; // Decrement count (warning: could have received new invitations during deletion execution) - if (csWallet.data.invitations.count >= countBeforeDeletion) { - csWallet.data.invitations.count -= countBeforeDeletion || 0; + if (wallet.data.invitations.count >= countBeforeDeletion) { + wallet.data.invitations.count -= countBeforeDeletion || 0; } else { - csWallet.data.invitations.count = 0; + wallet.data.invitations.count = 0; } // Decrement count (warning: could have received new invitations during deletion execution) - if (csWallet.data.invitations.unreadCount >= unreadCountBeforeDeletion) { - csWallet.data.invitations.unreadCount -= unreadCountBeforeDeletion || 0; + if (wallet.data.invitations.unreadCount >= unreadCountBeforeDeletion) { + wallet.data.invitations.unreadCount -= unreadCountBeforeDeletion || 0; } else { - csWallet.data.invitations.unreadCount = 0; + wallet.data.invitations.unreadCount = 0; } - console.debug('[ES] [invitation] All invitations deleted in {0}ms'.format(new Date().getTime()-now)); + console.debug('[ES] [invitation] All {0} invitations deleted in {1}ms'.format(type, Date.now()-now)); }); }); } @@ -342,8 +358,9 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', function addListeners() { // Extend csWallet events listeners = [ - csWallet.api.data.on.login($rootScope, onWalletLogin, this), csWallet.api.data.on.init($rootScope, onWalletInit, this), + csWallet.api.data.on.login($rootScope, onWalletLoad, this), + csWallet.api.data.on.load($rootScope, onWalletLoad, this), csWallet.api.data.on.reset($rootScope, onWalletReset, this), csWallet.api.action.on.certify($rootScope, onWalletCertify, this), esNotification.api.event.on.newInvitation($rootScope, onNewInvitationEvent, this) @@ -363,7 +380,7 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', console.debug("[ES] [invitations] Enable"); addListeners(); if (csWallet.isLogin()) { - onWalletLogin(csWallet.data); + onWalletLoad(csWallet.data); } } } @@ -385,7 +402,7 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', that.send = sendInvitation; that.delete = deleteInvitation; that.deleteByIds = deleteInvitationsByIds; - that.deleteAll = deleteAllInvitations; + that.deleteAll = deleteAllInvitationsByPubkey; that.constants = constants; diff --git a/assets/www/plugins/es/js/services/message-services.js b/assets/www/plugins/es/js/services/message-services.js index f492d36d8875dcd8d8d8e28cadffe838b58253f5..2009ad1610160e71d3208061e373006bc32732c5 100644 --- a/assets/www/plugins/es/js/services/message-services.js +++ b/assets/www/plugins/es/js/services/message-services.js @@ -35,6 +35,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', function onWalletInit(data) { data.messages = data.messages || {}; data.messages.unreadCount = null; + data.messages.time = null; } function onWalletReset(data) { @@ -43,35 +44,50 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } } - function onWalletLogin(data, deferred) { + function onWalletLoad(data, deferred) { deferred = deferred || $q.defer(); + if (!data || !data.pubkey) { deferred.resolve(); return deferred.promise; } + var now = Date.now(); + var time = Math.trunc(now / 1000); + + // Skip if loaded less than 1 min ago + // (This is need to avoid reload on login AND load phases) + if (data.messages && data.messages.time && (time - data.messages.time < 30 /*=30s*/)) { + console.debug('[ES] [message] Skipping load (loaded '+(time - data.messages.time)+'s ago)'); + deferred.resolve(); + return deferred.promise; + } + console.debug('[ES] [message] Loading count...'); - var now = new Date().getTime(); // Count unread messages - countUnreadMessages(data.pubkey) - .then(function(unreadCount){ + countUnreadMessages({pubkey: data.pubkey}) + .then(function(unreadCount) { data.messages = data.messages || {}; data.messages.unreadCount = unreadCount; - console.debug('[ES] [message] Loaded count (' + unreadCount + ') in '+(new Date().getTime()-now)+'ms'); + data.messages.time = time; + console.debug('[ES] [message] Loaded count (' + unreadCount + ') in '+(Date.now()-now)+'ms'); deferred.resolve(data); }) .catch(function(err){ - console.error('Error chile counting message: ' + (err.message ? err.message : err)); + console.error('Error while counting messages: ' + (err.message ? err.message : err)); deferred.resolve(data); }); return deferred.promise; } - function countUnreadMessages(pubkey) { - pubkey = pubkey || (csWallet.isLogin() ? csWallet.data.pubkey : pubkey); + function countUnreadMessages(options) { + options = options || {}; + var wallet = options.wallet || + (options.walletId && csWallet.children.get(options.walletId)) || csWallet; + var pubkey = options.pubkey || (wallet && wallet.data && wallet.data.pubkey); if (!pubkey) { - throw new Error('no pubkey, and user not connected.'); + throw new Error('no pubkey or wallet found in options, and user not connected.'); } var request = { @@ -92,33 +108,50 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } // Listen message changes - function onNewMessageEvent(event) { + function onNewMessageEvent(event, wallet) { console.debug("[ES] [message] detected new message (from notification service)"); - var notification = new Notification(event); + var notification = new EsNotification(event); notification.issuer = notification.pubkey; delete notification.pubkey; + if (!notification.issuer) return; // Skip if invalid + + // Get the wallet + wallet = wallet || (notification.issuer && csWallet.isUserPubkey(notification.issuer) && csWallet) || + (notification.issuer && csWallet.children.getByPubkey(notification.issuer)); + + if (!wallet) { + throw new Error("No wallet for pubkey: {0}".format(notification.issuer.substring(0, 6))); + } + csWot.extend(notification, 'issuer') .then(function() { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount++; + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.unreadCount++; // Raise event api.data.raise.new(notification); }); } - function sendMessage(message) { - return csWallet.getKeypair() + function sendMessage(message, options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + delete options.wallet; + message.issuer = message.issuer || wallet.data.pubkey; + return wallet.getKeypair() .then(function(keypair) { + + // Send to recipient inbox return doSendMessage(message, keypair) .then(function (res) { + + // Check if outbox is enable (in settings) var outbox = (csSettings.data.plugins.es.message && angular.isDefined(csSettings.data.plugins.es.message.outbox)) ? csSettings.data.plugins.es.message.outbox : true; - if (!outbox) return res; // Send to outbox @@ -129,7 +162,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }); }) .then(function (res) { - // Raise event + // Raise API event api.data.raise.sent(res); return res; @@ -144,22 +177,25 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', return esWallet.box.record.pack(message, keypair, recipientFieldName, ['title', 'content']) // Send message .then(function(message){ - return esHttp.record.post(boxPath)(message); + return esHttp.record.post(boxPath)(message, {pubkey: message.issuer, keypair: keypair}); }); } function loadMessageNotifications(options) { - if (!csWallet.isLogin()) { - return $q.when([]); // Should never happen - } options = options || {}; options.from = options.from || 0; options.size = options.size || constants.DEFAULT_LOAD_SIZE; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + delete options.wallet; + + if (!wallet.isLogin()) { + return $q.when([]); // Should never happen + } var request = { sort: { "time" : "desc" }, - query: {bool: {filter: {term: {recipient: csWallet.data.pubkey}}}}, + query: {bool: {filter: {term: {recipient: wallet.data.pubkey}}}}, from: options.from, size: options.size, _source: fields.notifications @@ -231,7 +267,10 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', options.filter = angular.isDefined(options.filter) ? options.filter : undefined; options.from = options.from || 0; - var promise = csWallet.auth() + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + delete options.wallet; // avoid error in angular.copy() + + var promise = wallet.auth() .then(function(walletData) { // Get encrypted message (with common fields) @@ -254,12 +293,15 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', if (messages.length && options.filter){ var filteredMessages = filterMessages(messages, options.filter); - // Recursive loop, if need more + // Need more messages: iterate again if (filteredMessages.length < messages.length) { options = angular.copy(options); options.from += options.size; options.size = messages.length - filteredMessages.length; - return loadMessages(options) + // put the wallet again, because it has been removed before the angular.copy() + // To avoid an error + options.wallet = wallet; + return loadMessages(options) // Loop .then(function(messages) { return filteredMessages.concat(messages); }); @@ -267,8 +309,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } if (options.from === 0 && !options.filter) { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = messages.length; + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.count = messages.length; } return messages; @@ -282,19 +324,20 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', return promise; } - function getAndDecrypt(id, options) { + function getAndDecrypt(id, type, options) { + type = type || 'inbox'; options = options || {}; - options.type = options.type || 'inbox'; options.summary = angular.isDefined(options.summary) ? options.summary : false/*summary not need by default*/; + var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) || csWallet; - return csWallet.auth() + return wallet.auth() .then(function(walletData) { - return raw.getByTypeAndId({id: id, type: options.type}) + return raw.getByTypeAndId({id: id, type: type}) .then(function(hit) { if (!hit.found) return; var msg = hit._source; msg.id = hit._id; - msg.read = (options.type == 'outbox') || !!msg.read_signature; + msg.read = (type == 'outbox') || !!msg.read_signature; delete msg.read_signature; // not need anymore // Decrypt message @@ -302,7 +345,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Add avatar .then(function(){ - var avatarField = (options.type == 'inbox') ? 'issuer' : 'recipient'; + var avatarField = (type == 'inbox') ? 'issuer' : 'recipient'; return csWot.extend(msg, avatarField); }); }); @@ -311,7 +354,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', function decryptMessages(messages, keypair, withSummary) { - var now = new Date().getTime(); + var now = Date.now(); var issuerBoxPks = {}; // a map used as cache var jobs = [esWallet.box.getKeypair(keypair)]; @@ -362,7 +405,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }, [])); }) .then(function() { - console.debug('[ES] [message] All messages decrypted in ' + (new Date().getTime() - now) + 'ms'); + console.debug('[ES] [message] All messages decrypted in ' + (Date.now() - now) + 'ms'); return messages; }); @@ -378,26 +421,32 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } } - function removeMessage(id, type) { + function removeMessage(id, type, options) { type = type || 'inbox'; - return esHttp.record.remove('message', type)(id) + + var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) || csWallet; + + return esHttp.record.remove('message', type)(id, {wallet: wallet}) .then(function(res) { - // update message count - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = csWallet.data.messages.count > 0 ? csWallet.data.messages.count-1 : 0; + // Update message count + if (type === 'inbox') { + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.count = wallet.data.messages.count > 0 ? wallet.data.messages.count-1 : 0; } + // Raise event - api.data.raise.delete(id); + if (wallet.isDefault()) { + api.data.raise.delete(id); + } return res; }); } - function removeAllMessages(type) { + function removeAllMessages(type, options) { type = type || 'inbox'; - - return csWallet.auth() + var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet; + return wallet.auth() .then(function(walletData) { // Get all message id return searchMessages(walletData.pubkey, {type: type, from: 0, size: 1000, _source: false}) @@ -408,7 +457,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Remove each messages return $q.all(res.reduce(function (res, msg) { - return res.concat(esHttp.record.remove('message', type)(msg.id, walletData)); + return res.concat(esHttp.record.remove('message', type)(msg.id, {wallet: wallet})); }, [])) .then(function() { return ids; @@ -416,21 +465,25 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }) .then(function (ids) { // update message count - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = 0; - csWallet.data.messages.unreadCount = 0; + if (type === 'inbox') { + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.count = 0; + wallet.data.messages.unreadCount = 0; } // Raise events - _.forEach(ids, api.data.raise.delete); + if (wallet.isDefault()) { + _.forEach(ids, api.data.raise.delete); + } }); }); } // Mark a message as read - function markMessageAsRead(message, type) { - type = type || 'inbox'; + function markMessageAsRead(message, options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + var type = options && options.type || (!wallet.isUserPubkey(message.recipient) ? 'outbox' : 'inbox'); if (message.read) { var deferred = $q.defer(); deferred.resolve(); @@ -438,7 +491,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } message.read = true; - return csWallet.getKeypair() + return wallet.getKeypair() // Prepare the read_signature to sent .then(function(keypair) { @@ -452,16 +505,18 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Update message count .then(function() { - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount = csWallet.data.messages.unreadCount ? csWallet.data.messages.unreadCount - 1 : 0; + if (type === 'inbox') { + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.unreadCount = wallet.data.messages.unreadCount ? wallet.data.messages.unreadCount - 1 : 0; } }); } // Mark all messages as read - function markAllMessageAsRead() { - return csWallet.auth() + function markAllMessageAsRead(options) { + options = options || {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + return wallet.auth() .then(function(walletData) { // Get all messages hash @@ -491,8 +546,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }) .then(function () { // update message count - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount = 0; + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.unreadCount = 0; }); }); } @@ -574,7 +629,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', console.info("[ES] [message] Sending logs to developers..."); message.issuer = csWallet.data.pubkey; message.title = message.title || 'Sending log'; - message.time = esHttp.date.now(); + message.time = moment().utc().unix(); csWallet.getKeypair() .then(function(keypair) { @@ -598,8 +653,9 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', function addListeners() { // Extend csWallet events listeners = [ - csWallet.api.data.on.login($rootScope, onWalletLogin, this), csWallet.api.data.on.init($rootScope, onWalletInit, this), + csWallet.api.data.on.login($rootScope, onWalletLoad, this), + csWallet.api.data.on.load($rootScope, onWalletLoad, this), // need for secondary wallets csWallet.api.data.on.reset($rootScope, onWalletReset, this), esNotification.api.event.on.newMessage($rootScope, onNewMessageEvent, this), // for issue #524 @@ -620,7 +676,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', console.debug("[ES] [message] Enable"); addListeners(); if (csWallet.isLogin()) { - onWalletLogin(csWallet.data); + onWalletLoad(csWallet.data); } } } diff --git a/assets/www/plugins/es/js/services/modal-services.js b/assets/www/plugins/es/js/services/modal-services.js index e955ff66bc6990c1d56765b14bcaafefcc29c437..06a11add94f65b63b4354b30633e9f5d0ae4eba1 100644 --- a/assets/www/plugins/es/js/services/modal-services.js +++ b/assets/www/plugins/es/js/services/modal-services.js @@ -8,25 +8,12 @@ angular.module('cesium.es.modal.services', ['cesium.modal.services', 'cesium.es. parameters, {focusFirstInput: true}); } - function updateNotificationCountAndReadTime() { - csWallet.data.notifications.unreadCount = 0; - if (csWallet.data.notifications && csWallet.data.notifications.history.length) { - var lastNotification = csWallet.data.notifications.history[0]; - var readTime = lastNotification ? lastNotification.time : 0; - csSettings.data.wallet = csSettings.data.wallet || {}; - if (readTime && csSettings.data.wallet.notificationReadTime != readTime) { - csSettings.data.wallet.notificationReadTime = readTime; - csSettings.store(); - } - } - } - function showNotificationsPopover(scope, event) { return UIUtils.popover.show(event, { templateUrl :'plugins/es/templates/common/popover_notification.html', scope: scope, autoremove: false, // reuse popover - afterHidden: updateNotificationCountAndReadTime + afterHidden: scope.resetUnreadCount }) .then(function(notification) { if (!notification) return; // no selection @@ -51,8 +38,9 @@ angular.module('cesium.es.modal.services', ['cesium.modal.services', 'cesium.es. }); } - function showNewPage() { - return csWallet.auth({minData: true}) + function showNewPage(options) { + var wallet = options && options.wallet || csWallet; + return wallet.auth({minData: true}) .then(function() { UIUtils.loading.hide(); @@ -61,7 +49,7 @@ angular.module('cesium.es.modal.services', ['cesium.modal.services', 'cesium.es. }) .then(function(type){ if (type) { - $state.go('app.registry_add_record', {type: type}); + $state.go('app.registry_add_record', {type: type, wallet: wallet.id}); } }); }); diff --git a/assets/www/plugins/es/js/services/notification-services.js b/assets/www/plugins/es/js/services/notification-services.js index 4a12dbd155e6dc6077d921ba428db6f5a3fee245..630c0dcf29372b2c16a6c8930f04afa02bf839a2 100644 --- a/assets/www/plugins/es/js/services/notification-services.js +++ b/assets/www/plugins/es/js/services/notification-services.js @@ -10,7 +10,9 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es }) -.factory('esNotification', function($rootScope, $q, $timeout, esHttp, csConfig, csSettings, csWallet, csWot, UIUtils, BMA, CryptoUtils, csPlatform, Api) { +.factory('esNotification', function($rootScope, $q, $timeout, $translate, $state, csHttp, + csConfig, csSettings, esHttp, esSettings, csWallet, csWot, UIUtils, filterTranslations, + BMA, CryptoUtils, csPlatform, Api) { 'ngInject'; var @@ -25,6 +27,7 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es }, that = this, listeners, + wsUserEventCloseFn, api = new Api(this, 'esNotification') ; @@ -105,16 +108,51 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es }); } + function getWalletNotifications(options) { + options = options || {}; + var wallet = options.wallet || csWallet; + + return new Promise(function(resolve) { + if (!wallet.data || !wallet.data.events ||!wallet.data.events.length) return resolve([]); + + // Add some wallet events as notifications + var time = csHttp.date.now() - filterTranslations.MEDIAN_TIME_OFFSET; + var result = (wallet.data.events || []).reduce(function(res, event) { + if (event.type != "warn" && event.type != "error") return res; // Keep only warn and error events + var notification = new EsNotification({}, function(self) { + if (!self.read) { + self.read = true; + if (wallet.data.notifications && wallet.data.notifications.warnCount > 0) { + wallet.data.notifications.warnCount--; + } + } + }); + notification.id=event.code; + notification.read = false; + notification.state = 'app.view_wallet'; + notification.avatarIcon = 'ion-alert-circled'; + notification.icon = 'ion-alert-circled assertive'; + notification.time = time; + notification.message = event.message; + notification.messageParams = event.messageParams; + return res.concat(notification); + }, []); + + resolve(result); + }); + + } + // Load user notifications - function loadNotifications(pubkey, options) { - if (!pubkey) { - return $q.reject('[ES] [notification] Unable to load - missing pubkey'); - } + function loadNotifications(options) { options = options || {}; + if (!options.pubkey) { + return $q.reject('[ES] [notification] Unable to load - missing options.pubkey'); + } options.from = options.from || 0; options.size = options.size || constants.DEFAULT_LOAD_SIZE; var request = { - query: createFilterQuery(pubkey, options), + query: createFilterQuery(options.pubkey, options), sort : [ { "time" : {"order" : "desc"}} ], @@ -123,14 +161,24 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es _source: fields.commons }; - return that.raw.postSearch(request) - .then(function(res) { - if (!res.hits || !res.hits.total) return []; + return $q.all([ + // Get wallet events (as notifications) + getWalletNotifications(options), + + // Load notification from ES node + that.raw.postSearch(request) + ]).then(function(res) { + + var walletNotifs = res[0] || []; + res = res[1]; + + if (!res.hits || !res.hits.total) return walletNotifs; + var notifications = res.hits.hits.reduce(function(res, hit) { - var item = new Notification(hit._source, markNotificationAsRead); + var item = new EsNotification(hit._source, markNotificationAsRead); item.id = hit._id; return res.concat(item); - }, []); + }, walletNotifs); return csWot.extendAll(notifications); }); @@ -151,7 +199,7 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es return; } - var notification = new Notification(event, markNotificationAsRead); + var notification = new EsNotification(event, markNotificationAsRead); // Extend the notification entity return csWot.extendAll([notification]) @@ -164,6 +212,9 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es else { addNewNotification(notification); } + }) + .then(function() { + if (esSettings.notifications.isEmitHtml5Enable()) return emitEsNotification(notification); }); } @@ -171,6 +222,66 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es csWallet.data.notifications = csWallet.data.notifications || {}; csWallet.data.notifications.unreadCount++; api.data.raise.new(notification); + + return notification; + } + + function htmlToPlaintext(text) { + return text ? String(text).replace(/<[^>]*>/gm, '').replace(/&[^;]+;/gm, '') : ''; + } + + function emitEsNotification(notification, title) { + + // If it's okay let's create a notification + $q.all([ + $translate(title||'COMMON.NOTIFICATION.TITLE'), + $translate(notification.message, notification) + ]) + .then(function(res) { + var title = htmlToPlaintext(res[0]); + var body = htmlToPlaintext(res[1]); + var icon = notification.avatar && notification.avatar.src || './img/logo.png'; + emitHtml5Notification(title, { + body: body, + icon: icon, + lang: $translate.use(), + tag: notification.id, + onclick: function() { + $rootScope.$applyAsync(function() { + if (typeof notification.markAsRead === "function") { + notification.markAsRead(); + } + if (notification.state) { + $state.go(notification.state, notification.stateParams); + } + }); + } + }); + }); + } + + function emitHtml5Notification(title, options) { + + // Let's check if the browser supports notifications + if (!("Notification" in window)) return; + + // Let's check whether notification permissions have already been granted + if (Notification.permission === "granted") { + + // If it's okay let's create a notification + var browserNotification = new Notification(title, options); + browserNotification.onclick = options.onclick || browserNotification.onclick; + } + + // Otherwise, we need to ask the user for permission + else if (Notification.permission !== "denied") { + Notification.requestPermission(function (permission) { + // If the user accepts, let's create a notification + if (permission === "granted") { + emitHtml5Notification(title, options); // recursive call + } + }); + } } // Mark a notification as read @@ -202,44 +313,82 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es function onWalletReset(data) { data.notifications = data.notifications || {}; data.notifications.unreadCount = null; + data.notifications.warnCount = null; + data.notifications.time = null; // Stop listening notification - that.raw.ws.getUserEvent().close(); + if (wsUserEventCloseFn) { + console.debug("[ES] [notification] Closing websocket..."); + wsUserEventCloseFn(); + wsUserEventCloseFn = null; + } } - function onWalletLogin(data, deferred) { + function onWalletLoad(data, deferred) { deferred = deferred || $q.defer(); if (!data || !data.pubkey || !data.keypair) { deferred.resolve(); return deferred.promise; } - console.debug('[ES] [notification] Loading count...'); - var now = new Date().getTime(); + var now = Date.now(); + var time = Math.trunc(now / 1000); + + // Skip if loaded less than 1 min ago + // (This is need to avoid reload on login AND load phases) + if (data.notifications && data.notifications.time && (time - data.notifications.time < 30 /*=30s*/)) { + // update warn count + data.notifications.warnCount = countWarnEvents(data); + + console.debug('[ES] [notification] Skipping load (loaded '+(time - data.notifications.time)+'s ago)'); + deferred.resolve(); + return deferred.promise; + } + + var isDefaultWallet = csWallet.isUserPubkey(data.pubkey); + console.debug('[ES] [notification] Loading count...' + data.pubkey.substr(0,8)); // Load unread notifications count loadUnreadNotificationsCount( data.pubkey, { - readTime: csSettings.data.wallet ? csSettings.data.wallet.notificationReadTime : 0, + readTime: data.notifications && data.notifications.time || 0, excludeCodes: constants.EXCLUDED_CODES }) .then(function(unreadCount) { data.notifications = data.notifications || {}; data.notifications.unreadCount = unreadCount; - console.debug('[ES] [notification] Loaded count (' + unreadCount + ') in '+(new Date().getTime()-now)+'ms'); + data.notifications.warnCount = countWarnEvents(data); + + // Emit HTML5 notification (only on main wallet) + if (unreadCount > 0 && esSettings.notifications.isEmitHtml5Enable() && isDefaultWallet) { + $timeout(function() { + emitEsNotification({ + message: 'COMMON.NOTIFICATION.HAS_UNREAD', + count: unreadCount, + state: 'app.view_notifications' + }, data.ui || data.name || data.pubkey && data.pubkey.substr(0,8)); + }, 500); + } + + console.debug('[ES] [notification] Loaded count (' + unreadCount + ') in '+(Date.now()-now)+'ms'); deferred.resolve(data); }) - .catch(function(err){ - deferred.reject(err); - }) + .catch(deferred.reject); - // Listen new events + return deferred.promise; + } + + function onWalletLogin(data, deferred) { + // Call load + return onWalletLoad(data, deferred) + + // then start listening new events .then(function(){ console.debug('[ES] [notification] Starting listen user event...'); - var userEventWs = that.raw.ws.getUserEvent(); - listeners.push(userEventWs.close); - return userEventWs.on(onNewUserEvent, - {pubkey: data.pubkey, locale: csSettings.data.locale.id} - ) + var wsUserEvent = that.raw.ws.getUserEvent(); + wsUserEvent.on( + onNewUserEvent, + {pubkey: data.pubkey, locale: csSettings.data.locale.id} + ) .catch(function(err) { console.error('[ES] [notification] Unable to listen user event', err); @@ -247,15 +396,22 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es // And display such connectivity errors in UI UIUtils.alert.error('ACCOUNT.ERROR.WS_CONNECTION_FAILED'); }); + wsUserEventCloseFn = function() {wsUserEvent.close();}; }); + } - return deferred.promise; + function countWarnEvents(data){ + if (!data.events) return 0; + return data.events.reduce(function(counter, event) { + return (event.type == "warn") ? counter+1 : counter; + }, 0); } function addListeners() { // Listen some events listeners = [ csWallet.api.data.on.login($rootScope, onWalletLogin, this), + csWallet.api.data.on.load($rootScope, onWalletLoad, this), csWallet.api.data.on.init($rootScope, onWalletReset, this), csWallet.api.data.on.reset($rootScope, onWalletReset, this) ]; @@ -301,6 +457,9 @@ angular.module('cesium.es.notification.services', ['cesium.platform', 'cesium.es // Exports that.load = loadNotifications; that.unreadCount = loadUnreadNotificationsCount; + that.html5 = { + emit: emitHtml5Notification + }; that.api = api; that.websocket = { event: that.raw.ws.getUserEvent, diff --git a/assets/www/plugins/es/js/services/profile-services.js b/assets/www/plugins/es/js/services/profile-services.js index 39ab95e81b8998527189c1c92da029571b246a29..c36f3123b0ef714d60e5cbdf0e99f52c8a5743b7 100644 --- a/assets/www/plugins/es/js/services/profile-services.js +++ b/assets/www/plugins/es/js/services/profile-services.js @@ -19,10 +19,10 @@ angular.module('cesium.es.profile.services', ['cesium.services', 'cesium.es.http that.raw = { getFields: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content&_source=:fields'), - get: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content'), - getAll: esHttp.get('/user/profile/:id'), - search: esHttp.post('/user/profile/_search'), - mixedSearch: esHttp.post('/user,page,group/profile,record/_search') + get: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content', esHttp.cache.MEDIUM), + getAll: esHttp.get('/user/profile/:id', esHttp.cache.MEDIUM), + search: esHttp.post('/user/profile/_search', esHttp.cache.MEDIUM), + mixedSearch: esHttp.post('/user,page,group/profile,record/_search', esHttp.cache.MEDIUM) }; function getAvatarAndName(pubkey) { @@ -192,20 +192,16 @@ angular.module('cesium.es.profile.services', ['cesium.services', 'cesium.es.http }; } else { - request.query.constant_score = { - filter: {bool: {should: [ - {terms : {_id : pubkeys}}, - {bool: { - must: [ - {match: {title: {query: text, boost: 2}}}, - {prefix: {title: text}} - ]} - } - ]}} + request.query.bool = { + should: [ + {terms : {"_id^4" : pubkeys}}, + {match: {title: {query: text, boost: 2}}}, + {prefix: {title: text}} + ] }; if (tags) { - request.query.constant_score.filter.bool.should.push({terms: {tags: tags}}); + request.query.bool.should.push({terms: {tags: tags}}); } } } diff --git a/assets/www/plugins/es/js/services/settings-services.js b/assets/www/plugins/es/js/services/settings-services.js index 8999754db2685090575183c817b428f30d4699be..aa2e539f59ec60eae9e762899252bc59424648c5 100644 --- a/assets/www/plugins/es/js/services/settings-services.js +++ b/assets/www/plugins/es/js/services/settings-services.js @@ -16,27 +16,37 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt var SETTINGS_SAVE_SPEC = { - includes: ['locale', 'showUDHistory', 'useRelative', 'useLocalStorage', 'expertMode', 'logoutIdle'], - excludes: ['timeout', 'cacheTimeMs', 'time', 'login', 'build'], + includes: ['locale', 'showUDHistory', 'useRelative', 'useLocalStorage', 'useLocalStorageEncryption', 'expertMode', 'logoutIdle', 'blockValidityWindow'], + excludes: ['timeout', 'cacheTimeMs', 'version', 'build', 'minVersion', 'fallbackLanguage'], plugins: { es: { - excludes: ['enable', 'host', 'port', 'wsPort', 'fallbackNodes'] + excludes: ['enable', 'host', 'port', 'fallbackNodes', 'enableGoogleApi', 'googleApiKey'], + notifications: { + } } }, + wallet: { + includes: ['alertIfUnusedWallet'], + excludes: ['notificationReadTime'] // deprecated - should be removed later + }, helptip: { excludes: ['installDocUrl'] + }, + notifications: { + excludes: ['time', 'warnCount', 'unreadCount'] } }, defaultSettings = angular.merge({ plugins: { es: { askEnable: false, + useRemoteStorage: true, notifications: { - readTime: true, txSent: true, txReceived: true, certSent: true, - certReceived: true + certReceived: true, + emitHtml5: false }, invitations: { readTime: true @@ -77,6 +87,13 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt !!csSettings.data.plugins.es.host; }; + that.notifications = {}; + that.notifications.isEmitHtml5Enable = function() { + return that.isEnable() && + csSettings.data.plugins.es.notifications && + angular.isDefined(csSettings.data.plugins.es.notifications.emitHtml5) ? csSettings.data.plugins.es.notifications.emitHtml5 : false; + }; + that.wot = {}; that.wot.isMixedSearchEnable = function() { return that.isEnable() && @@ -113,7 +130,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt // Load settings function loadSettings(pubkey, boxKeypair) { - var now = new Date().getTime(); + var now = Date.now(); return that.get({id: pubkey}) .catch(function(err){ if (err && err.ucode && err.ucode == 404) { @@ -130,7 +147,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt var record = res._source; // Do not apply if same version if (record.time === csSettings.data.time) { - console.debug('[ES] [settings] Loaded in '+ (new Date().getTime()-now) +'ms, but already up to date'); + console.debug('[ES] [settings] Loaded in '+ (Date.now()-now) +'ms, but already up to date'); return; } var nonce = CryptoUtils.util.decode_base58(record.nonce); @@ -139,7 +156,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt .then(function(json) { var settings = JSON.parse(json || '{}'); settings.time = record.time; - console.debug('[ES] [settings] Loaded and decrypted in '+ (new Date().getTime()-now) +'ms'); + console.debug('[ES] [settings] Loaded and decrypted in '+ (Date.now()-now) +'ms'); return settings; }) // if error: skip stored content @@ -236,8 +253,13 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt return $q.when(); } - var time = esHttp.date.now(); // always update time - console.debug('[ES] [settings] Saving user settings... at time ' + time); + // Skip remote saving, if remote storage disable + if (!csSettings.data.plugins.es.useRemoteStorage) { + return storeSettingsLocally(); + } + + var time = moment().utc().unix(); // always update time + console.debug('[ES] [settings] Saving user settings remotely...'); return $q.all([ csWallet.getKeypair(), // same result as esWallet.box.getKeypair(), because box keypair computed on auth @@ -266,7 +288,13 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt // create or update return angular.isUndefined(data.time) ? that.add(record) : - that.update(record, {id: record.issuer}); + that.update(record, {id: record.issuer}) + .catch(function(err) { + // Workaround if update failed: try to add() instead + // Can occur when changing the cesium+ pod + if (err && err.ucode == 404) return that.add(record); + throw err; + }); }) .then(function() { return true; @@ -277,7 +305,7 @@ angular.module('cesium.es.settings.services', ['cesium.services', 'cesium.es.htt // Update settings version, then store (on local store only) data.time = time; previousRemoteData = filteredData; - console.debug('[ES] [settings] Saved user settings in ' + (esHttp.date.now() - time) + 'ms'); + console.debug('[ES] [settings] Saved user settings remotely in ' + (moment().utc().unix() - time) + 'ms'); return storeSettingsLocally(); }) .catch(function(err) { diff --git a/assets/www/plugins/es/js/services/social-services.js b/assets/www/plugins/es/js/services/social-services.js index 37305a2d62ef2c2adc1acb720b669d0295c9c270..679afbd9b9d8ae41a542b71f418ea86386ea1b6e 100644 --- a/assets/www/plugins/es/js/services/social-services.js +++ b/assets/www/plugins/es/js/services/social-services.js @@ -1,6 +1,6 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) - .factory('SocialUtils', function($filter, $q, CryptoUtils, BMA, csWallet, esCrypto) { + .factory('SocialUtils', function($filter, $q, CryptoUtils, BMA, csWallet, esCrypto, $timeout) { 'ngInject'; function SocialUtils() { @@ -52,7 +52,7 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) urlToMatch = url.substring(0, slashPathIndex); } } - //console.log("match URI, try to match: " + urlToMatch); + //console.debug("match URI, try to match: " + urlToMatch); _.keys(regexp.socials).forEach(function(key){ if (regexp.socials[key].test(urlToMatch)) { type = key; diff --git a/assets/www/plugins/es/js/services/subscription-services.js b/assets/www/plugins/es/js/services/subscription-services.js index b18115b36d7e6203a646d4276bab85021388e709..34b72c1e219c590c5fbd5cc3d0eb0e92b1e6a045 100644 --- a/assets/www/plugins/es/js/services/subscription-services.js +++ b/assets/www/plugins/es/js/services/subscription-services.js @@ -81,12 +81,13 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es }); } - function addRecord(record) { + function addRecord(record, options) { if (!record || !record.type || !record.content || !record.recipient) { return $q.reject("Missing arguments 'record' or 'record.type' or 'record.content' or 'record.recipient'"); } - var issuer = csWallet.data.pubkey; + var wallet = options && options.wallet || (options && options.walletId && csWallet.children.get(options.walletId)) || csWallet; + var issuer = wallet.data.pubkey; var contentStr = JSON.stringify(record.content); @@ -95,8 +96,8 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es // Encrypt contents .then(function(nonce) { return $q.all([ - esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, csWallet.data.keypair, 'issuer', 'issuerContent', nonce), - esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, csWallet.data.keypair, 'recipient', 'recipientContent', nonce) + esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, wallet.data.keypair, 'issuer', 'issuerContent', nonce), + esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, wallet.data.keypair, 'recipient', 'recipientContent', nonce) ]); }) // Merge encrypted record @@ -105,7 +106,7 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es encryptedRecord.type = record.type; // Post subscription - return that.raw.add(encryptedRecord) + return that.raw.add(encryptedRecord, {wallet: wallet}) .then(function(id) { record.id = id; return record; @@ -114,12 +115,13 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es ; } - function updateRecord(record) { + function updateRecord(record, options) { if (!record || !record.content || !record.recipient) { return $q.reject("Missing arguments 'record' or 'record.content', or 'record.recipient'"); } - var issuer = csWallet.data.pubkey; + var wallet = options && options.wallet || (options && options.walletId && csWallet.children.get(options.walletId)) || csWallet; + var issuer = wallet.data.pubkey; var contentStr = JSON.stringify(record.content); // Get a unique nonce @@ -127,8 +129,8 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es // Encrypt contents .then(function(nonce) { return $q.all([ - esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, csWallet.data.keypair, 'issuer', 'issuerContent', nonce), - esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, csWallet.data.keypair, 'recipient', 'recipientContent', nonce) + esWallet.box.record.pack({issuer: issuer, issuerContent: contentStr}, wallet.data.keypair, 'issuer', 'issuerContent', nonce), + esWallet.box.record.pack({recipient: record.recipient, recipientContent: contentStr}, wallet.data.keypair, 'recipient', 'recipientContent', nonce) ]); }) // Merge encrypted record @@ -137,7 +139,7 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es encryptedRecord.type = record.type; // Post subscription - return that.raw.update(encryptedRecord, {id:record.id}) + return that.raw.update(encryptedRecord, {id:record.id, wallet: wallet}) .then(function() { return record; // return original record }); diff --git a/assets/www/plugins/es/js/services/tx-services.js b/assets/www/plugins/es/js/services/tx-services.js index 2773457b3c7c743ba37561bc23d31c8a9b11989a..1a1f41e1869a046dad1e159740c14d578d6a7cdd 100644 --- a/assets/www/plugins/es/js/services/tx-services.js +++ b/assets/www/plugins/es/js/services/tx-services.js @@ -11,10 +11,11 @@ angular.module('cesium.es.tx.services', ['ngResource', 'cesium.services', 'cesiu }) - .factory('esTx', function($q, $rootScope, csCurrency, csTx, esHttp, esWot) { + .factory('esTx', function($q, $rootScope, csPlatform, csCurrency, csTx, esHttp, esWot) { 'ngInject'; var + listeners, raw = { block: { search: esHttp.post('/:currency/block/_search') @@ -67,7 +68,8 @@ angular.module('cesium.es.tx.services', ['ngResource', 'cesium.services', 'cesiu { range: { medianTime: { - from: membership.joinTime, + // Fix #736: Add 1 second, because when membership begins in a block with DU, the DU is not received + from: membership.joinTime+1, to: membership.leaveTime } } @@ -114,8 +116,38 @@ angular.module('cesium.es.tx.services', ['ngResource', 'cesium.services', 'cesiu return deferred.promise; } - // Register extensions - csTx.api.data.on.loadUDs($rootScope, onLoadUDs, this); + function addListeners() { + // Extend API events + listeners = [ + csTx.api.data.on.loadUDs($rootScope, onLoadUDs, this) + ]; + } + + function removeListeners() { + _.forEach(listeners, function(remove){ + remove(); + }); + listeners = []; + } + + function refreshState() { + var enable = esHttp.alive; + if (!enable && listeners && listeners.length > 0) { + console.debug("[ES] [tx] Disable"); + removeListeners(); + } + else if (enable && (!listeners || listeners.length === 0)) { + console.debug("[ES] [tx] Enable"); + addListeners(); + } + } + + // Default action + csPlatform.ready().then(function() { + esHttp.api.node.on.start($rootScope, refreshState, this); + esHttp.api.node.on.stop($rootScope, refreshState, this); + return refreshState(); + }); // Exports return {}; diff --git a/assets/www/plugins/es/js/services/wallet-services.js b/assets/www/plugins/es/js/services/wallet-services.js index 08cd7646d8ce864806d59c81d096670841553660..66a8a2405a1f8fcd6a3962686b068fd7cff38358 100644 --- a/assets/www/plugins/es/js/services/wallet-services.js +++ b/assets/www/plugins/es/js/services/wallet-services.js @@ -1,6 +1,6 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'cesium.es.http.services', 'cesium.es.crypto.services']) - .factory('esWallet', function($q, $rootScope, CryptoUtils, csPlatform, csWallet, esCrypto, esProfile, esHttp) { + .factory('esWallet', function($q, $rootScope, $timeout, CryptoUtils, csPlatform, csWallet, esCrypto, esProfile, esHttp) { 'ngInject'; var @@ -24,8 +24,8 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c // Generate box keypair esCrypto.box.getKeypair(data.keypair) .then(function(res) { - csWallet.data.keypair.boxSk = res.boxSk; - csWallet.data.keypair.boxPk = res.boxPk; + data.keypair.boxSk = res.boxSk; + data.keypair.boxPk = res.boxPk; console.debug("[ES] [wallet] Box keypair successfully computed"); deferred.resolve(); }); @@ -56,7 +56,7 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c } console.debug('[ES] [wallet] Loading user avatar+name...'); - var now = new Date().getTime(); + var now = Date.now(); esProfile.getAvatarAndName(data.pubkey) .then(function(profile) { @@ -64,7 +64,7 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c data.name = profile.name; data.avatarStyle = profile.avatarStyle; data.avatar = profile.avatar; - console.debug('[ES] [wallet] Loaded user avatar+name in '+ (new Date().getTime()-now) +'ms'); + console.debug('[ES] [wallet] Loaded user avatar+name in '+ (Date.now()-now) +'ms'); } else { console.debug('[ES] [wallet] No user avatar+name found'); @@ -84,13 +84,13 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c // Reset events csWallet.events.cleanByContext('esWallet'); - // If membership pending, but not enough certifications: suggest to fill user profile - if (!data.name && data.requirements.pendingMembership && data.requirements.needCertificationCount > 0) { + // If membership pending and not revocated, but not enough certifications: suggest to fill user profile + if (!data.name && !data.requirements.revoked && data.requirements.pendingMembership && data.requirements.needCertificationCount > 0) { csWallet.events.add({type:'info', message: 'ACCOUNT.EVENT.MEMBER_WITHOUT_PROFILE', context: 'esWallet'}); } console.debug('[ES] [wallet] Loading full user profile...'); - var now = new Date().getTime(); + var now = Date.now(); // Load full profile esProfile.get(data.pubkey) @@ -100,7 +100,7 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c data.avatar = profile.avatar; data.profile = profile.source; data.profile.description = profile.description; - console.debug('[ES] [wallet] Loaded full user profile in '+ (new Date().getTime()-now) +'ms'); + console.debug('[ES] [wallet] Loaded full user profile in '+ (Date.now()-now) +'ms'); } deferred.resolve(); }); @@ -108,23 +108,26 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c return deferred.promise; } - function getBoxKeypair() { - if (!csWallet.isAuth()) { + function getBoxKeypair(keypair) { + if (!keypair && !csWallet.isAuth()) { throw new Error('Unable to get box keypair: user not authenticated !'); } - return csWallet.getKeypair({silent: true}) + return (keypair ? $q.when(keypair) : csWallet.getKeypair({silent: true})) .then(function(keypair) { + // box keypair already computed: use it if (keypair && keypair.boxPk && keypair.boxSk) { - return $q.when(csWallet.data.keypair); + return $q.when(keypair); } - return esCrypto.box.getKeypair(keypair); - }) - .then(function(res) { - csWallet.data.keypair.boxSk = res.boxSk; - csWallet.data.keypair.boxPk = res.boxPk; - console.debug("[ES] [wallet] Box keypair successfully computed"); - return csWallet.data.keypair; + // Compute box keypair + return esCrypto.box.getKeypair(keypair) + .then(function(res) { + // Store in the wallet keypair + keypair.boxSk = res.boxSk; + keypair.boxPk = res.boxPk; + console.debug("[ES] [wallet] Box keypair successfully computed"); + return keypair; + }); }); } @@ -177,15 +180,15 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c getKeypair: getBoxKeypair, record: { pack: function(record, keypair, recipientFieldName, cypherFieldNames, nonce) { - return getBoxKeypair() - .then(function(keypair) { - return esCrypto.box.pack(record, keypair, recipientFieldName, cypherFieldNames, nonce); + return getBoxKeypair(keypair) + .then(function(fullKeypair) { + return esCrypto.box.pack(record, fullKeypair, recipientFieldName, cypherFieldNames, nonce); }); }, open: function(records, keypair, issuerFieldName, cypherFieldNames) { - return getBoxKeypair() - .then(function(keypair) { - return esCrypto.box.open(records, keypair, issuerFieldName, cypherFieldNames); + return getBoxKeypair(keypair) + .then(function(fullKeypair) { + return esCrypto.box.open(records, fullKeypair, issuerFieldName, cypherFieldNames); }); } } diff --git a/assets/www/plugins/es/js/services/wot-services.js b/assets/www/plugins/es/js/services/wot-services.js index 7e8179aabb8b49bbe7e09b45757879792eb0df73..9c40566c10712719b42d31ff240603c494df934d 100644 --- a/assets/www/plugins/es/js/services/wot-services.js +++ b/assets/www/plugins/es/js/services/wot-services.js @@ -1,16 +1,23 @@ angular.module('cesium.es.wot.services', ['ngResource', 'cesium.es.http.services']) - .factory('esWot', function($q, esHttp) { + .factory('esWot', function($rootScope, $q, esHttp, csCache) { 'ngInject'; var + cachePrefix = 'esWot-', + membershipsCache = csCache.get(cachePrefix + 'memberships-', csCache.constants.MEDIUM), raw = { user: { - event: esHttp.post('/user/event/_search?pretty') + event: esHttp.post('/user/event/_search') } }, - loadMemberships = function(pubkey) { + + loadMemberships = function(pubkey, options) { + options = options || {}; + + var result = (options.cache !== false) ? membershipsCache.get(pubkey) : null; + if (result) return $q.when(result); // Get user events on membership state var request = { @@ -62,10 +69,21 @@ angular.module('cesium.es.wot.services', ['ngResource', 'cesium.es.http.services }); } + // Put in the cache + membershipsCache.put(pubkey, result); + return result; }); + }, + + cleanCache = function() { + console.debug('[ES] [wot] Clean cache...'); + csCache.clear(cachePrefix); }; + // Listen if node changed + esHttp.api.node.on.stop($rootScope, cleanCache, this); + return { memberships: loadMemberships }; diff --git a/assets/www/plugins/es/templates/blockchain/lookup.html b/assets/www/plugins/es/templates/blockchain/lookup.html index 88579fd344e85d3ffa54a8ba1de88a96767098c5..147c32d3228c6e025f41e4f8325733035aa86e74 100644 --- a/assets/www/plugins/es/templates/blockchain/lookup.html +++ b/assets/www/plugins/es/templates/blockchain/lookup.html @@ -1 +1 @@ -<ion-view><ion-nav-title><span translate>BLOCKCHAIN.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-navicon visible-xs visible-sm" ng-click="toggleCompactMode()"><b class="icon-secondary" ng-class="{'ion-arrow-down-b': !compactMode, 'ion-arrow-up-b': compactMode}" style="top: -12px; left: 11px; font-size: 10px"></b> <b class="icon-secondary" ng-class="{'ion-arrow-up-b': !compactMode,'ion-arrow-down-b': compactMode}" style="top: 12px; left: 11px; font-size: 10px"></b></button> <button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs" scroll="true"><ng-include src="'plugins/es/templates/blockchain/lookup_form.html'"></ng-include></ion-content></ion-view> \ No newline at end of file +<ion-view><ion-nav-title><span translate>BLOCKCHAIN.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-navicon visible-xs visible-sm" ng-click="toggleCompactMode()"><b class="icon-secondary" ng-class="{'ion-arrow-down-b': !compactMode, 'ion-arrow-up-b': compactMode}" style="top: -12px; left: 11px; font-size: 10px"></b> <b class="icon-secondary" ng-class="{'ion-arrow-up-b': !compactMode,'ion-arrow-down-b': compactMode}" style="top: 12px; left: 11px; font-size: 10px"></b></button> <button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ng-include src="'plugins/es/templates/blockchain/lookup_form.html'"></ng-include></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/blockchain/lookup_form.html b/assets/www/plugins/es/templates/blockchain/lookup_form.html index 3657f240a239500578c936d13aa7e7b74ef375b3..36c0f9ee09ed0c84f882bd5a0d774ba59a183b7a 100644 --- a/assets/www/plugins/es/templates/blockchain/lookup_form.html +++ b/assets/www/plugins/es/templates/blockchain/lookup_form.html @@ -1 +1 @@ -<div class="lookupForm"><div class="item no-padding"><div class="button button-small button-text button-stable button-icon-event padding no-padding-right ink" ng-repeat="filter in search.filters" ng-if="filter"><span ng-bind-html="'BLOCKCHAIN.LOOKUP.TX_SEARCH_FILTER.'+filter.type|translate:filter"></span> <i class="icon ion-close" ng-click="itemRemove($index)"></i></div><label class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{'BLOCKCHAIN.LOOKUP.SEARCH_HELP'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearchText()"><div class="helptip-anchor-center"><a id="helptip-blockchain-search-text"></a></div></label></div><div class="padding-top padding-xs" style="display: block; height: 60px"><div class="pull-left"><h4 ng-if="search.type=='last'" translate="">BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4><h4 ng-if="search.type=='text'">{{'COMMON.RESULTS_LIST'|translate}}</h4><h5 class="dark" ng-if="!search.loading && search.total"><span translate="COMMON.RESULTS_COUNT" translate-values="{count: search.total}"></span> <small class="gray" ng-if=":rebind:search.took && expertMode">- {{:rebind:'COMMON.EXECUTION_TIME'|translate: {duration: search.took} }} </small><small class="gray" ng-if=":rebind:expertMode && search.filters && search.filters.length">- <a ng-click="toggleShowQuery()" ng-if="!showQuery">Voir la requête <i class="icon ion-arrow-down-b gray"></i> </a><a ng-click="toggleShowQuery()" ng-if="showQuery">Masquer la requête <i class="icon ion-arrow-up-b gray"></i></a></small></h5><h5 class="gray" ng-if="search.loading"><ion-spinner class="icon ion-spinner-small" icon="android"></ion-spinner><span translate="">COMMON.SEARCHING</span><br></h5></div></div><div class="item no-border no-padding" ng-if=":rebind:search.filters && search.filters.length && expertMode"><small class="no-padding no-margin" ng-if="showQuery"><span class="gray text-wrap dark">{{:rebind:search.query}}</span></small></div><ion-list class="list list-blocks" ng-class="::motion.ionListClass"><ng-include src="'plugins/es/templates/blockchain/items_blocks.html'"></ng-include></ion-list><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll></div> \ No newline at end of file +<div class="lookupForm"><div class="item no-padding"><div class="button button-small button-text button-stable button-icon-event padding no-padding-right ink" ng-repeat="filter in search.filters" ng-if="filter"><span ng-bind-html="'BLOCKCHAIN.LOOKUP.TX_SEARCH_FILTER.'+filter.type|translate:filter"></span> <i class="icon ion-close" ng-click="itemRemove($index)"></i></div><label class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{'BLOCKCHAIN.LOOKUP.SEARCH_HELP'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearchText()"><div class="helptip-anchor-center"><a id="helptip-blockchain-search-text"></a></div></label></div><div class="padding-top padding-xs" style="display: block; height: 60px"><div class="pull-left"><h4 ng-if="search.type=='last'" translate="">BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4><h4 ng-if="search.type=='text'">{{'COMMON.RESULTS_LIST'|translate}}</h4><h5 class="dark" ng-if="!search.loading && search.total"><span translate="COMMON.RESULTS_COUNT" translate-values="{count: search.total}"></span> <small class="gray" ng-if=":rebind:search.took && expertMode">- {{:rebind:'COMMON.EXECUTION_TIME'|translate: {duration: search.took} }} </small><small class="gray" ng-if=":rebind:expertMode && search.filters && search.filters.length">- <a ng-click="toggleShowQuery()" ng-if="!showQuery">{{'DOCUMENT.LOOKUP.SHOW_QUERY'|translate }} <i class="icon ion-arrow-down-b gray"></i> </a><a ng-click="toggleShowQuery()" ng-if="showQuery">{{'DOCUMENT.LOOKUP.HIDE_QUERY'|translate }} <i class="icon ion-arrow-up-b gray"></i></a></small></h5><h5 class="gray" ng-if="search.loading"><ion-spinner class="icon ion-spinner-small" icon="android"></ion-spinner><span translate="">COMMON.SEARCHING</span><br></h5></div></div><div class="item no-border no-padding" ng-if=":rebind:search.filters && search.filters.length && expertMode"><small class="no-padding no-margin" ng-if="showQuery"><span class="gray text-wrap dark">{{:rebind:search.query}}</span></small></div><ion-list class="list list-blocks" ng-class="::motion.ionListClass"><ng-include src="'plugins/es/templates/blockchain/items_blocks.html'"></ng-include></ion-list><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll></div> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/common/edit_position.html b/assets/www/plugins/es/templates/common/edit_position.html index 7089b36ba09cb39ba096ceb749179fcd5be0d33a..2c8b777eaf61ee9482265e1789b6e2fefc5a6e1b 100644 --- a/assets/www/plugins/es/templates/common/edit_position.html +++ b/assets/www/plugins/es/templates/common/edit_position.html @@ -1,2 +1,2 @@ <div class="item item-divider" translate>LOCATION.LOCATION_DIVIDER</div><ion-item class="item-input item-floating-label item-button-right"><span class="input-label">{{'LOCATION.ADDRESS' | translate}}</span><textarea placeholder="{{'LOCATION.ADDRESS_HELP' | translate}}" ng-model="formData.address" ng-model-options="{ debounce: 350 }" rows="4" cols="10"> - </textarea></ion-item><div class="item item-input item-floating-label" ng-class="{'item-input-error': form.$submitted && form.geoPoint.$invalid}"><span class="input-label" translate>LOCATION.CITY</span> <input type="text" placeholder="{{'LOCATION.CITY_HELP'|translate}}" ng-model="formData.city" ng-model-options="{ updateOn: 'blur' }" ng-change="onCityChanged()"></div><input type="hidden" name="geoPoint" ng-model="formData.geoPoint" required-if="formPosition.enable" geo-point><div class="form-errors" ng-show="form.$submitted && form.geoPoint.$error" ng-messages="form.geoPoint.$error"><div class="form-error" ng-message="required"><span translate="LOCATION.ERROR.REQUIRED_FOR_LOCATION" ng-if="!formData.city"></span> <span translate="LOCATION.ERROR.INVALID_FOR_LOCATION" ng-if="formData.city"></span></div><div class="form-error" ng-message="geoPoint"><span translate="LOCATION.ERROR.REQUIRED_FOR_LOCATION" ng-if="!formData.city"></span> <span translate="LOCATION.ERROR.INVALID_FOR_LOCATION" ng-if="formData.city"></span></div></div><div class="item row item-text-wrap no-padding"><div class="col no-padding"><ion-checkbox ng-model="formPosition.enable" ng-change="onUseGeopointChanged()" class="item item-border-large done in"><div class="item-content"><span translate>LOCATION.USE_GEO_POINT</span><h4 class="gray" ng-if="formPosition.loading"><ion-spinner class="icon ion-spinner-small" icon="android"></ion-spinner>{{'LOCATION.LOADING_LOCATION'|translate}}</h4></div></ion-checkbox></div><div class="col col-10 no-padding" style="min-width: 60px"><div class="row text-center"><a class="button button-stable button-small-padding" title="{{'LOCATION.BTN_GEOLOC_ADDRESS'|translate}}" ng-disabled="!formPosition.enable" ng-click="openSearchLocationModal()"><i class="icon ion-home" style="left: 15px"></i> <b class="icon-secondary ion-search" style="top: -9px; left:32px; font-size: 18px"></b></a></div></div></div><cs-extension-point name="after-position"></cs-extension-point> \ No newline at end of file + </textarea></ion-item><div class="item item-input item-floating-label" ng-class="{'item-input-error': form.$submitted && form.geoPoint.$invalid}"><span class="input-label" translate>LOCATION.CITY</span> <input type="text" placeholder="{{'LOCATION.CITY_HELP'|translate}}" ng-model="formData.city" ng-model-options="{ updateOn: 'blur' }" required-if="formData.address" ng-change="onCityChanged()"></div><input type="hidden" name="geoPoint" ng-model="formData.geoPoint" required-if="formPosition.enable" geo-point><div class="form-errors" ng-show="form.$submitted && form.city.$error" ng-messages="form.city.$error"><div class="form-error" ng-message="required"><span translate="LOCATION.ERROR.CITY_REQUIRED_IF_STREET"></span></div></div><div class="form-errors" ng-show="form.$submitted && form.geoPoint.$error" ng-messages="form.geoPoint.$error"><div class="form-error" ng-message="required"><span translate="LOCATION.ERROR.REQUIRED_FOR_LOCATION" ng-if="!formData.city"></span> <span translate="LOCATION.ERROR.INVALID_FOR_LOCATION" ng-if="formData.city"></span></div><div class="form-error" ng-message="geoPoint"><span translate="LOCATION.ERROR.REQUIRED_FOR_LOCATION" ng-if="!formData.city"></span> <span translate="LOCATION.ERROR.INVALID_FOR_LOCATION" ng-if="formData.city"></span></div></div><div class="item row item-text-wrap no-padding"><div class="col no-padding"><ion-checkbox ng-model="formPosition.enable" ng-change="onUseGeopointChanged()" class="item item-border-large done in"><div class="item-content"><span translate>LOCATION.USE_GEO_POINT</span><h4 class="gray" ng-if="formPosition.loading"><ion-spinner class="icon ion-spinner-small" icon="android"></ion-spinner>{{'LOCATION.LOADING_LOCATION'|translate}}</h4></div></ion-checkbox></div><div class="col col-10 no-padding" style="min-width: 60px"><div class="row text-center"><a class="button button-stable button-small-padding" title="{{'LOCATION.BTN_GEOLOC_ADDRESS'|translate}}" ng-disabled="!formPosition.enable" ng-click="openSearchLocationModal()"><i class="icon ion-home" style="left: 15px"></i> <b class="icon-secondary ion-search" style="top: -9px; left:32px; font-size: 18px"></b></a></div></div></div><cs-extension-point name="after-position"></cs-extension-point> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/common/modal_edit_avatar.html b/assets/www/plugins/es/templates/common/modal_edit_avatar.html index d3b90b0d5b7c000db6b40e5ab86d7bcaee0d7049..d92f031f7f4f3e3461ad286cd0d7342d6c5f2a89 100644 --- a/assets/www/plugins/es/templates/common/modal_edit_avatar.html +++ b/assets/www/plugins/es/templates/common/modal_edit_avatar.html @@ -1 +1 @@ -<ion-modal-view><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs visible-sm" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>PROFILE.MODAL_AVATAR.TITLE</h1><button class="button button-clear icon-right visible-xs" ng-click="doCrop()" ng-disabled="formData.imageCropStep == 1" ng-if="formData.imageCropStep <= 2"><span translate>COMMON.BTN_NEXT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-clear icon-right visible-xs" ng-click="closeModal(formData.result)" ng-if="formData.imageCropStep == 3"><i class="icon ion-android-done"></i></button></ion-header-bar><ion-content class="modal-avatar padding"><div ng-show="formData.imageCropStep == 1"><p translate>PROFILE.MODAL_AVATAR.SELECT_FILE_HELP</p><div class="item card text-center padding ink" ng-click="openFileSelector()"><i class="ion-image stable" style="font-size:150px"></i> <b class="ion-plus gray" style="position:relative; font-size:80px; top:-51px; right: 19px"></b><p translate>PROFILE.MODAL_AVATAR.BTN_SELECT_FILE</p></div><input type="file" name="fileInput" accept="image/*" id="fileInput" onchange="angular.element(this).scope().fileChanged(event)" style="visibility:hidden; position:absolute"></div><div ng-show="formData.imageCropStep == 2"><p translate>PROFILE.MODAL_AVATAR.RESIZE_HELP</p><div class="item card text-center padding ink"><image-crop data-height="100" data-width="100" data-shape="circle" data-step="formData.imageCropStep" src="formData.imgSrc" data-result="formData.result" data-result-blob="formData.resultBlob" crop="formData.initCrop" padding="150" max-size="1024"></image-crop></div></div><div ng-show="formData.imageCropStep == 3"><p translate>PROFILE.MODAL_AVATAR.RESULT_HELP</p><div class="item card padding hero" style="height: 110px"><div class="content"><img class="avatar" ng-src="{{formData.result}}" style="height: 88px; width: 88px"></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" ng-click="doCrop()" translate ng-disabled="formData.imageCropStep == 1" ng-if="formData.imageCropStep <= 2">COMMON.BTN_NEXT</button> <button class="button button-positive ink" ng-click="closeModal(formData.result)" translate ng-if="formData.imageCropStep == 3">COMMON.BTN_CONTINUE</button></div></ion-content></ion-modal-view> \ No newline at end of file +<ion-modal-view><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs visible-sm" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>PROFILE.MODAL_AVATAR.TITLE</h1><button class="button button-clear icon-right visible-xs" ng-click="doCrop()" ng-disabled="formData.imageCropStep == 1" ng-if="formData.imageCropStep <= 2"><span translate>COMMON.BTN_NEXT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-clear icon-right visible-xs" ng-click="closeModal(formData.result)" ng-if="formData.imageCropStep == 3"><i class="icon ion-android-done"></i></button></ion-header-bar><ion-content class="modal-avatar padding"><div ng-show="formData.imageCropStep == 1"><p translate>PROFILE.MODAL_AVATAR.SELECT_FILE_HELP</p><div class="item card text-center padding ink" ng-click="openFileSelector()"><i class="ion-image stable" style="font-size:150px"></i> <b class="ion-plus gray" style="position:relative; font-size:80px; top:-51px; right: 19px"></b><p translate>PROFILE.MODAL_AVATAR.BTN_SELECT_FILE</p></div><input type="file" name="fileInput" accept="image/*" id="fileInput" onchange="angular.element(this).scope().fileChanged(event)" style="visibility:hidden; position:absolute"></div><div ng-show="formData.imageCropStep == 2"><p translate>PROFILE.MODAL_AVATAR.RESIZE_HELP</p><div class="item card text-center padding ink"><image-crop data-height="200" data-width="200" data-shape="circle" data-step="formData.imageCropStep" src="formData.imgSrc" data-result="formData.result" data-result-blob="formData.resultBlob" crop="formData.initCrop" padding="150" max-size="1024"></image-crop></div></div><div ng-show="formData.imageCropStep == 3"><p translate>PROFILE.MODAL_AVATAR.RESULT_HELP</p><div class="item card padding hero" style="height: 110px"><div class="content"><img class="avatar" ng-src="{{formData.result}}" style="height: 88px; width: 88px"></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" ng-click="doCrop()" translate ng-disabled="formData.imageCropStep == 1" ng-if="formData.imageCropStep <= 2">COMMON.BTN_NEXT</button> <button class="button button-positive ink" ng-click="closeModal(formData.result)" translate ng-if="formData.imageCropStep == 3">COMMON.BTN_CONTINUE</button></div></ion-content></ion-modal-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/common/modal_location.html b/assets/www/plugins/es/templates/common/modal_location.html index 9c31fcbcc77fe446a3405afb88d011fe5a80ab36..aea52a8f21834773257240e0134d1b8b1efcbc66 100644 --- a/assets/www/plugins/es/templates/common/modal_location.html +++ b/assets/www/plugins/es/templates/common/modal_location.html @@ -1 +1 @@ -<ion-modal-view class="modal-full-height modal-search-location"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button><h1 class="title" translate="">LOCATION.MODAL.TITLE</h1></ion-header-bar><ion-content class="padding no-padding-xs" scroll="true"><div class="item item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{'LOCATION.MODAL.SEARCH_HELP'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()"></div><div class="padding-top padding-xs" style="display: block; height: 60px"><div class="pull-left" ng-if="!search.loading && search.results"><h4 translate="">COMMON.RESULTS_LIST</h4></div></div><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div ng-if="!search.loading && search.results && (!search.results.length || !search.results[0].address)" class="assertive padding"><span translate="">COMMON.SEARCH_NO_RESULT</span></div><ion-list ng-if="!search.loading" class="padding-top {{::motion.ionListClass}}"><div ng-repeat="res in search.results" class="item item-border-large item-text-wrap ink" ng-class="::{'item-divider': !res.address, 'item-icon-left item-icon-right': res.address}" ng-click="res.address ? closeModal(res) : false"><h4 class="text-italic" ng-if="::!res.address" ng-bind-html="res.name"></h4><ng-if ng-if="::res.address"><i class="icon ion-location"></i><h2 ng-if="res.address.road">{{::res.address.road}}</h2><h3><span ng-if="res.address.postcode">{{::res.address.postcode}}</span> {{::res.address.city||res.address.village}} <span class="gray">| {{::res.address.country}}</span></h3><h5 class="gray">{{'LOCATION.MODAL.POSITION'|translate:res }}</h5><i class="icon ion-ios-arrow-right"></i></ng-if></div></ion-list></ion-content><ion-footer-bar class="stable-bg padding-left padding-right block" ng-if="license"><div class="pull-right copyright"><span class="dark">© </span><a class="positive" href="{{license.url}}" target="_blank">{{license.name}}</a></div></ion-footer-bar></ion-modal-view> \ No newline at end of file +<ion-modal-view class="modal-full-height modal-search-location"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button><h1 class="title" translate="">LOCATION.MODAL.TITLE</h1></ion-header-bar><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><div class="item item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{'LOCATION.MODAL.SEARCH_HELP'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()"></div><div class="padding-top padding-xs" style="display: block; height: 60px"><div class="pull-left" ng-if="!search.loading && search.results"><h4 translate="">COMMON.RESULTS_LIST</h4></div></div><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div ng-if="!search.loading && search.results && (!search.results.length || !search.results[0].address)" class="assertive padding"><span translate="">COMMON.SEARCH_NO_RESULT</span></div><ion-list ng-if="!search.loading" class="padding-top {{::motion.ionListClass}}"><div ng-repeat="res in search.results" class="item item-border-large item-text-wrap ink" ng-class="::{'item-divider': !res.address, 'item-icon-left item-icon-right': res.address}" ng-click="res.address ? closeModal(res) : false"><h4 class="text-italic" ng-if="::!res.address" ng-bind-html="res.name"></h4><ng-if ng-if="::res.address"><i class="icon ion-location"></i><h2 ng-if="res.address.road">{{::res.address.road}}</h2><h3><span ng-if="res.address.postcode">{{::res.address.postcode}}</span> {{::res.address.city||res.address.village}} <span class="gray">| {{::res.address.country}}</span></h3><h5 class="gray">{{'LOCATION.MODAL.POSITION'|translate:res }}</h5><i class="icon ion-ios-arrow-right"></i></ng-if></div></ion-list></ion-content><ion-footer-bar class="stable-bg padding-left padding-right block" ng-if="license"><div class="pull-right copyright"><span class="dark">© </span><a class="positive" href="{{license.url}}" target="_blank">{{license.name}}</a></div></ion-footer-bar></ion-modal-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/common/popover_profile_extend.html b/assets/www/plugins/es/templates/common/popover_profile_extend.html index c7f828029cd8a53a3c35b7f356b4e447d5b445dc..585685025c65ddddc8acc2e3e9c6bb9ea382539a 100644 --- a/assets/www/plugins/es/templates/common/popover_profile_extend.html +++ b/assets/www/plugins/es/templates/common/popover_profile_extend.html @@ -1 +1 @@ -<button ng-if="enable && auth" class="button button-positive button-small ink" ng-click="showEditUserProfile()">{{'PROFILE.BTN_EDIT' | translate}}</button> \ No newline at end of file +<button ng-if=":state:enable && auth" class="button button-positive button-small ink" ng-click="showEditUserProfile()">{{'PROFILE.BTN_EDIT' | translate}}</button> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/common/view_comments.html b/assets/www/plugins/es/templates/common/view_comments.html index 898cb9d917ae8775d38e2b1ce5b6841e1f406dc7..b98a61cfe573a6c59e36f9f4bb8a30101950a0bb 100644 --- a/assets/www/plugins/es/templates/common/view_comments.html +++ b/assets/www/plugins/es/templates/common/view_comments.html @@ -1 +1 @@ -<div class="comments" ng-controller="ESCommentsCtrl"><div class="item item-divider"><i class="icon ion-chatboxes"></i> <span translate="">COMMENTS.DIVIDER</span> <span class="gray" ng-if="comments.total">({{comments.total}})</span></div><span class="item item-more-comments" ng-if="comments.hasMore"><small><a ng-click="showMore()" translate="">COMMENTS.SHOW_MORE_COMMENTS</a></small></span><div class="padding-right"><ng-repeat ng-repeat="comment in comments.result track by comment.id" ng-include="'plugins/es/templates/common/item_comment.html'"></ng-repeat></div><div class="visible-xs visible-sm" style="margin-bottom"><div class="block"><div class="item item-input-inset done in" ng-if="formData.parent"><div class="padding text-right pull-left" translate="">COMMENTS.REPLY_TO</div><br><div class="padding-left expanded"><div class="card card-comment stable-900-bg item-text-wrap no-padding in done"><ng-include ng-if="::formData.parent.message" ng-init="comment = formData.parent" src="'plugins/es/templates/common/item_comment_content.html'"></ng-include><span ng-if="::!formData.parent.message" translate="">COMMENTS.DELETED_COMMENT</span><div class="card-footer text-right gray"><div class="pull-right"><a class="ion-close" ng-click="removeParentLink()">{{::'COMMON.BTN_CANCEL'|translate}}</a></div></div></div></div></div><div class="item item-input-inset"><div class="item-input-wrapper"><input type="text" id="comment-form-input" style="width: 100%" placeholder="{{'COMMENTS.COMMENT_HELP'|translate}}" on-return="save();" ng-model="formData.message"> <button class="button button-small button-small-padding button-icon button-dark button-icon gray" ng-click="save()"><i class="icon ion-android-send"></i></button></div></div></div></div></div> \ No newline at end of file +<form class="comments" ng-controller="ESCommentsCtrl" ng-submit="save()"><div class="item item-divider"><i class="icon ion-chatboxes"></i> <span translate="">COMMENTS.DIVIDER</span> <span class="gray" ng-if="comments.total">({{comments.total}})</span></div><span class="item item-more-comments" ng-if="comments.hasMore"><small><a ng-click="showMore()" translate="">COMMENTS.SHOW_MORE_COMMENTS</a></small></span><div class="padding-right"><ng-repeat ng-repeat="comment in comments.result track by comment.id" ng-include="'plugins/es/templates/common/item_comment.html'"></ng-repeat></div><div class="visible-xs visible-sm" style="margin-bottom"><div class="block"><div class="item item-input-inset done in" ng-if="formData.parent"><div class="padding text-right pull-left" translate="">COMMENTS.REPLY_TO</div><br><div class="padding-left expanded"><div class="card card-comment stable-900-bg item-text-wrap no-padding in done"><ng-include ng-if="::formData.parent.message" ng-init="comment = formData.parent" src="'plugins/es/templates/common/item_comment_content.html'"></ng-include><span ng-if="::!formData.parent.message" translate="">COMMENTS.DELETED_COMMENT</span><div class="card-footer text-right gray"><div class="pull-right"><a class="ion-close" ng-click="removeParentLink()">{{::'COMMON.BTN_CANCEL'|translate}}</a></div></div></div></div></div><div class="item item-input-inset"><div class="item-input-wrapper"><input type="text" id="comment-form-input" style="width: 100%" placeholder="{{'COMMENTS.COMMENT_HELP'|translate}}" on-return="save();" ng-model="formData.message"> <button type="submit" class="button button-small button-small-padding button-icon button-dark button-icon gray"><i class="icon ion-android-send"></i></button></div></div></div></div></form> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/currency/tab_blocks_extend.html b/assets/www/plugins/es/templates/currency/tab_blocks_extend.html index 8388a6ce92fbd2d0f1693e3069cb9ade7a87799e..872d4373e307cfdffe7bf433fd6a1ae149457479 100644 --- a/assets/www/plugins/es/templates/currency/tab_blocks_extend.html +++ b/assets/www/plugins/es/templates/currency/tab_blocks_extend.html @@ -1 +1 @@ -<ng-if ng-if="enable && extensionPoint === 'nav-buttons'"><button class="button button-icon button-clear icon ion-android-search visible-xs visible-sm" ui-sref="app.blockchain_search"></button></ng-if> \ No newline at end of file +<ng-if ng-if=":state:enable && extensionPoint === 'nav-buttons'"><button class="button button-icon button-clear icon ion-android-search visible-xs visible-sm" ui-sref="app.blockchain_search"></button></ng-if> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/document/item_document.html b/assets/www/plugins/es/templates/document/item_document.html index 06744b367c36d0f9b2db9d23e41016a7e518bdb8..29fb20eefb664ae034c4f1375677543620059a92 100644 --- a/assets/www/plugins/es/templates/document/item_document.html +++ b/assets/www/plugins/es/templates/document/item_document.html @@ -1 +1 @@ -<ion-item id="doc-{{::doc.id}}" class="item item-document item-icon-left ink {{::ionItemClass}} no-padding-top no-padding-bottom" ng-click="selectDocument($event, doc)"><i class="icon ion-document stable" ng-if=":rebind:!doc.avatar"></i> <i class="avatar" ng-if=":rebind:doc.avatar" style="background-image: url('{{:rebind:doc.avatar.src}}')"></i><div class="row no-padding"><div class="col"><h3 class="dark"><i class="ion-locked" ng-if=":rebind:doc.nonce"></i> {{:rebind:doc.time|formatDate}}</h3><h4 class="gray">{{:rebind:'DOCUMENT.HASH'|translate}} {{:rebind:doc.hash|formatHash}}</h4></div><div class="col"><h3><a ui-sref="app.wot_identity({pubkey: doc.pubkey, uid: doc.uid})"><span class="gray"><i class="ion-key"></i> {{:rebind:doc.pubkey|formatPubkey}} </span><span class="positive" ng-if=":rebind:doc.uid"><i class="ion-person"></i> {{:rebind:doc.name||doc.uid}}</span></a></h3></div><div class="col"><a ng-if=":rebind:login && doc.pubkey==$root.walletData.pubkey" ng-click="remove($index)" class="gray pull-right" title="{{'DOCUMENT.LOOKUP.BTN_REMOVE'|translate}}"><i class="ion-trash-a"></i></a><h3 ng-if=":rebind:doc.recipient"><a ui-sref="app.wot_identity({pubkey: doc.recipient.pubkey, uid: doc.recipient.uid})"><span class="gray"><i class="ion-key"></i> {{:rebind:doc.recipient.pubkey|formatPubkey}} </span><span class="positive" ng-if=":rebind:doc.recipient.uid"><i class="ion-person"></i> {{:rebind:doc.recipient.name||doc.recipient.uid}}</span></a></h3><h4 class="gray" ng-if=":rebind:doc.read_signature"><i class="ion-checkmark"></i> <span translate>DOCUMENT.LOOKUP.READ</span></h4></div></div></ion-item> \ No newline at end of file +<ion-item id="doc-{{::doc.id}}" class="item item-document item-icon-left ink {{::ionItemClass}} no-padding-top no-padding-bottom" ng-click="selectDocument($event, doc)"><i class="icon ion-document stable" ng-if=":rebind:!doc.avatar"></i> <i class="avatar" ng-if=":rebind:doc.avatar" style="background-image: url('{{:rebind:doc.avatar.src}}')"></i><div class="row no-padding"><div class="col"><h3 class="dark"><i class="ion-locked" ng-if=":rebind:doc.nonce"></i> {{:rebind:doc.time|formatDate}}</h3><h4 class="gray">{{:rebind:'DOCUMENT.HASH'|translate}} {{:rebind:doc.hash|formatHash}}</h4></div><div class="col"><h3><a ui-sref="app.wot_identity({pubkey: doc.pubkey, uid: doc.uid})"><span class="gray"><i class="ion-key"></i> {{:rebind:doc.pubkey|formatPubkey}} </span><span class="positive" ng-if=":rebind:doc.uid"><i class="ion-person"></i> {{:rebind:doc.name||doc.uid}}</span></a></h3></div><div class="col"><a ng-if=":rebind:login && doc.pubkey==walletData.pubkey" ng-click="remove($index)" class="gray pull-right" title="{{'DOCUMENT.LOOKUP.BTN_REMOVE'|translate}}"><i class="ion-trash-a"></i></a><h3 ng-if=":rebind:doc.recipient"><a ui-sref="app.wot_identity({pubkey: doc.recipient.pubkey, uid: doc.recipient.uid})"><span class="gray"><i class="ion-key"></i> {{:rebind:doc.recipient.pubkey|formatPubkey}} </span><span class="positive" ng-if=":rebind:doc.recipient.uid"><i class="ion-person"></i> {{:rebind:doc.recipient.name||doc.recipient.uid}}</span></a></h3><h4 class="gray" ng-if=":rebind:doc.read_signature"><i class="ion-checkmark"></i> <span translate>DOCUMENT.LOOKUP.READ</span></h4></div></div></ion-item> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/document/lookup.html b/assets/www/plugins/es/templates/document/lookup.html index 284d43fea07d9e898fd6762bd77b54de0aa43b74..56391efa52bb8931ac21493068d172f868a4d99d 100644 --- a/assets/www/plugins/es/templates/document/lookup.html +++ b/assets/www/plugins/es/templates/document/lookup.html @@ -1 +1 @@ -<ion-view><ion-nav-title><span translate>DOCUMENT.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs" scroll="true"><ng-include src="'plugins/es/templates/document/lookup_form.html'"></ng-include></ion-content></ion-view> \ No newline at end of file +<ion-view><ion-nav-title><span translate>DOCUMENT.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ng-include src="'plugins/es/templates/document/lookup_form.html'"></ng-include></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/group/lookup.html b/assets/www/plugins/es/templates/group/lookup.html index 87adfe3599acdc3a87941fcc8e8c99e88d0b4075..9de493c8b815a9daa2e2f0f686200f4eb1aa1535 100644 --- a/assets/www/plugins/es/templates/group/lookup.html +++ b/assets/www/plugins/es/templates/group/lookup.html @@ -1 +1 @@ -<ion-view class="view-group"><ion-nav-title><span translate>GROUP.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs" scroll="true"><ng-include src="'plugins/es/templates/group/lookup_form.html'"></ng-include></ion-content></ion-view> \ No newline at end of file +<ion-view class="view-group"><ion-nav-title><span translate>GROUP.LOOKUP.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ng-include src="'plugins/es/templates/group/lookup_form.html'"></ng-include></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/group/view_record.html b/assets/www/plugins/es/templates/group/view_record.html index b33efc613e522822d898434e075e89afdf20b525..ff01553d3b1614958a3ffa3cb76eadb15a89c8b3 100644 --- a/assets/www/plugins/es/templates/group/view_record.html +++ b/assets/www/plugins/es/templates/group/view_record.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-bar button-icon button-clear visible-xs visible-sm" ng-click="edit()" ng-if="canEdit"><i class="icon ion-android-create"></i></button> <button class="button button-bar button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true"><div class="positive-900-bg hero"><div class="content" ng-if="!loading"><i class="avatar cion-registry-{{formData.type}}" ng-if="!formData.avatar"></i> <i class="avatar" style="background-image: url({{::formData.avatar.src}})" ng-if="formData.avatar"></i><h3 ng-bind-html="formData.title"></h3><h4> </h4></div><h4 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><div class="row no-padding-xs"><div class="col list item-text-wrap no-padding-xs" ng-class="::motion.ionListClass"><div class="item"><h2 class="gray"><a ng-if="formData.city" ui-sref="app.groups({location:formData.city})"><i class="icon ion-location"></i> <span ng-bind-html="formData.city"></span> </a><span ng-if="formData.city && formData.type"> | </span> <a ng-if="formData.type" ui-sref="app.groups({type:formData.type})"><i class="icon ion-flag"></i> {{'GROUP.TYPE.ENUM.'+formData.type|upper|translate}}</a></h2><h4><i class="icon ion-clock" ng-if="formData.time"></i> <span translate="">COMMON.SUBMIT_BY</span> <a ng-class="{'positive': issuer.uid, 'gray': !issuer.uid}" ui-sref="app.wot_identity({pubkey:issuer.pubkey, uid: issuer.name||issuer.uid})"><ng-if ng-if="issuer.uid"><i class="icon ion-person"></i> {{::issuer.name||issuer.uid}}</ng-if><span ng-if="!issuer.uid"><i class="icon ion-key"></i> {{issuer.pubkey|formatPubkey}} </span></a><span>{{formData.time|formatFromNow}}<h4 class="gray hidden-xs">| {{formData.time | formatDate}}</h4></span></h4></div><a id="group-share-anchor-{{id}}"></a><ion-item><h2><span trust-as-html="formData.description"></span></h2></ion-item><ion-item><h4 ng-if="formData.address"><span class="gray" translate="">REGISTRY.VIEW.LOCATION</span> <a class="positive" target="_blank" href="https://www.google.fr/maps/?q={{formData.address}},%20{{formData.city}}"><span ng-bind-html="formData.address"></span> <span ng-if="formData.city">- </span><span ng-bind-html="formData.city"></span></a></h4></ion-item><ng-if ng-if="formData.socials && formData.socials.length>0"><ion-item class="item-icon-left" type="no-padding item-text-wrap" ng-repeat="social in formData.socials track by social.url" id="social-{{social.url|formatSlug}}"><i class="icon ion-social-{{social.type}}" ng-class="{'ion-bookmark': social.type == 'other', 'ion-link': social.type == 'web', 'ion-email': social.type == 'email'}"></i><p ng-if="social.type && social.type != 'web'">{{social.type}}</p><h2><a href="{{social.url}}" ng-if="social.type != 'email'" target="_blank">{{social.url}}</a> <a href="mailto:{{social.url}}" ng-if="social.type == 'email'">{{social.url}}</a></h2></ion-item></ng-if><div class="lazy-load"><ng-include src="'plugins/es/templates/common/view_pictures.html'"></ng-include><span class="item item-divider" ng-if="formData.pubkey"><span translate="">REGISTRY.TECHNICAL_DIVIDER</span></span><div class="item item-icon-left item-text-wrap ink" ng-if="formData.pubkey" copy-on-click="{{::formData.pubkey}}"><i class="icon ion-key"></i> <span translate="">REGISTRY.EDIT.RECORD_PUBKEY</span><h4 class="dark">{{::formData.pubkey}}</h4></div><ng-include src="'plugins/es/templates/common/view_comments.html'"></ng-include></div></div></div></ion-content><button class="button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm" ng-if="formData.pubkey && !isUserPubkey(formData.pubkey)" ng-click="showTransferModal({pubkey: formData.pubkey, uid: formData.title})"></button></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-bar button-icon button-clear visible-xs visible-sm" ng-click="edit()" ng-if="canEdit"><i class="icon ion-android-create"></i></button> <button class="button button-bar button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true"><div class="positive-900-bg hero"><div class="content" ng-if="!loading"><i class="avatar cion-registry-{{formData.type}}" ng-if="!formData.avatar"></i> <i class="avatar" style="background-image: url({{::formData.avatar.src}})" ng-if="formData.avatar"></i><h3 ng-bind-html="formData.title"></h3><h4> </h4></div><h4 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><div class="row no-padding-xs no-padding-sm"><div class="col list item-text-wrap no-padding-xs no-padding-sm" ng-class="::motion.ionListClass"><div class="item"><h2 class="gray"><a ng-if="formData.city" ui-sref="app.groups({location:formData.city})"><i class="icon ion-location"></i> <span ng-bind-html="formData.city"></span> </a><span ng-if="formData.city && formData.type"> | </span> <a ng-if="formData.type" ui-sref="app.groups({type:formData.type})"><i class="icon ion-flag"></i> {{'GROUP.TYPE.ENUM.'+formData.type|upper|translate}}</a></h2><h4><i class="icon ion-clock" ng-if="formData.time"></i> <span translate="">COMMON.SUBMIT_BY</span> <a ng-class="{'positive': issuer.uid, 'gray': !issuer.uid}" ui-sref="app.wot_identity({pubkey:issuer.pubkey, uid: issuer.name||issuer.uid})"><ng-if ng-if="issuer.uid"><i class="icon ion-person"></i> {{::issuer.name||issuer.uid}}</ng-if><span ng-if="!issuer.uid"><i class="icon ion-key"></i> {{issuer.pubkey|formatPubkey}} </span></a><span>{{formData.time|formatFromNow}}<h4 class="gray hidden-xs">| {{formData.time | formatDate}}</h4></span></h4></div><a id="group-share-anchor-{{id}}"></a><ion-item><h2><span trust-as-html="formData.description"></span></h2></ion-item><ion-item><h4 ng-if="formData.address"><span class="gray" translate="">REGISTRY.VIEW.LOCATION</span> <a class="positive" target="_blank" href="https://www.google.fr/maps/?q={{formData.address}},%20{{formData.city}}"><span ng-bind-html="formData.address"></span> <span ng-if="formData.city">- </span><span ng-bind-html="formData.city"></span></a></h4></ion-item><ng-if ng-if="formData.socials && formData.socials.length>0"><ion-item class="item-icon-left" type="no-padding item-text-wrap" ng-repeat="social in formData.socials track by social.url" id="social-{{social.url|formatSlug}}"><i class="icon ion-social-{{social.type}}" ng-class="{'ion-bookmark': social.type == 'other', 'ion-link': social.type == 'web', 'ion-email': social.type == 'email'}"></i><p ng-if="social.type && social.type != 'web'">{{social.type}}</p><h2><a href="{{social.url}}" ng-if="social.type != 'email'" target="_blank">{{social.url}}</a> <a href="mailto:{{social.url}}" ng-if="social.type == 'email'">{{social.url}}</a></h2></ion-item></ng-if><div class="lazy-load"><ng-include src="'plugins/es/templates/common/view_pictures.html'"></ng-include><span class="item item-divider" ng-if="formData.pubkey"><span translate="">REGISTRY.TECHNICAL_DIVIDER</span></span><div class="item item-icon-left item-text-wrap ink" ng-if="formData.pubkey" copy-on-click="{{::formData.pubkey}}"><i class="icon ion-key"></i> <span translate="">REGISTRY.EDIT.RECORD_PUBKEY</span><h4 class="dark">{{::formData.pubkey}}</h4></div><ng-include src="'plugins/es/templates/common/view_comments.html'"></ng-include></div></div></div></ion-content><button class="button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm" ng-if="formData.pubkey && !isUserPubkey(formData.pubkey)" ng-click="showTransferModal({pubkey: formData.pubkey, uid: formData.title})"></button></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/invitation/modal_new_invitation.html b/assets/www/plugins/es/templates/invitation/modal_new_invitation.html index 5f308054ceb1f7f046e9bcbeb1600d2f83304a84..0792198cc17753886217850ceabc31276481f2da 100644 --- a/assets/www/plugins/es/templates/invitation/modal_new_invitation.html +++ b/assets/www/plugins/es/templates/invitation/modal_new_invitation.html @@ -1 +1 @@ -<ion-modal-view id="transfer" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>INVITATION.NEW.TITLE</h1><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doSend()"></button></ion-header-bar><ion-content scroll="true"><ng-include src="'plugins/es/templates/invitation/new_invitation_form.html'"></ng-include></ion-content></ion-modal-view> \ No newline at end of file +<ion-modal-view id="transfer" class="modal-invitation modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>INVITATION.NEW.TITLE</h1><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doSend()"></button></ion-header-bar><ion-content scroll="true"><ng-include src="'plugins/es/templates/invitation/new_invitation_form.html'"></ng-include></ion-content></ion-modal-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/invitation/view_invitations.html b/assets/www/plugins/es/templates/invitation/view_invitations.html index 5b572f652fc9c20414f79a687e455f377384fcd2..2b7f78a41baaa59400646edf2b44bbe9651e9ef4 100644 --- a/assets/www/plugins/es/templates/invitation/view_invitations.html +++ b/assets/www/plugins/es/templates/invitation/view_invitations.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" class="view-invitation"><ion-nav-title>{{'INVITATION.LIST.TITLE' | translate}}</ion-nav-title><ion-content class="padding no-padding-xs" scroll="true"><div class="row no-padding"><div class="col no-padding-xs"><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="padding gray" ng-if="!search.loading && !search.results.length" translate="">INVITATION.NO_RESULT</div><ng-include src="'plugins/es/templates/invitation/list_invitation.html'"></ng-include></div></div></ion-content><button id="fab-new-invitation" class="button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm spin" ng-click="showNewInvitationModal()"></button></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="view-invitation"><ion-nav-title>{{'INVITATION.LIST.TITLE' | translate}}</ion-nav-title><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><div class="row no-padding"><div class="col no-padding-xs no-padding-sm"><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="padding gray" ng-if="!search.loading && !search.results.length" translate="">INVITATION.NO_RESULT</div><ng-include src="'plugins/es/templates/invitation/list_invitation.html'"></ng-include></div></div></ion-content><button id="fab-new-invitation" class="button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm spin" ng-click="showNewInvitationModal()"></button></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/join/modal_join_extend.html b/assets/www/plugins/es/templates/join/modal_join_extend.html index 0aa83b2d363ea510ad0cb7fead6d8cde14584e23..9b7c3a1d1a336cce0bc46d557d4ae75485cc9880 100644 --- a/assets/www/plugins/es/templates/join/modal_join_extend.html +++ b/assets/www/plugins/es/templates/join/modal_join_extend.html @@ -1 +1 @@ -<ng-if ng-if="enable && extensionPoint === 'select-account-type'"><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-class="{ activated: accountTypeMember != null && !accountTypeMember }" ng-click="selectAccountType('organization')"><div class="item-content item-text-wrap"><i class="item-image icon dark cion-registry-association"></i><h2 translate>ACCOUNT.NEW.ORGANIZATION_ACCOUNT</h2><h4 class="gray" translate>ACCOUNT.NEW.ORGANIZATION_ACCOUNT_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div></ng-if><ng-if ng-if="enable && extensionPoint === 'last-slide'"><ion-slide-page><ion-content class="has-header" scroll="false"><p>TOTO</p></ion-content></ion-slide-page></ng-if> \ No newline at end of file +<ng-if ng-if=":state:enable && extensionPoint === 'select-account-type'"><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-class="{ activated: accountTypeMember != null && !accountTypeMember }" ng-click="selectAccountType('organization')"><div class="item-content item-text-wrap"><i class="item-image icon dark cion-registry-association"></i><h2 translate>ACCOUNT.NEW.ORGANIZATION_ACCOUNT</h2><h4 class="gray" translate>ACCOUNT.NEW.ORGANIZATION_ACCOUNT_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div></ng-if><ng-if ng-if=":state:enable && extensionPoint === 'last-slide'"><ion-slide-page><ion-content class="has-header" scroll="false"><p>TOTO</p></ion-content></ion-slide-page></ng-if> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/menu_extend.html b/assets/www/plugins/es/templates/menu_extend.html index 46efedbb66a66276d90de30de57779fe07904b2c..039b2e8776516102b055023188b3c9551d6a116c 100644 --- a/assets/www/plugins/es/templates/menu_extend.html +++ b/assets/www/plugins/es/templates/menu_extend.html @@ -1 +1 @@ -<div ng-if="enable && extensionPoint === 'menu-user'" class="visible-xs visible-sm"><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/invitations" ng-class="{'item-menu-disable': !login}" ui-sref="app.view_invitations"><i class="icon ion-person-stalker"></i> <span translate="">MENU.INVITATIONS</span> <span class="badge badge-positive" ng-if="$root.walletData.invitations.unreadCount">{{$root.walletData.invitations.unreadCount}}</span> </a><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/user/message" ng-class="{'item-menu-disable': !login}" ui-sref="app.user_message.tab_inbox"><i class="icon ion-email"></i> <span translate="">MENU.MESSAGES</span> <span class="badge badge-positive" ng-if="$root.walletData.messages.unreadCount">{{$root.walletData.messages.unreadCount}}</span> </a><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/notifications" ng-class="{'item-menu-disable': !login}" ui-sref="app.view_notifications"><i class="icon ion-android-notifications"></i> <span translate="">MENU.NOTIFICATIONS</span> <span class="badge badge-positive" ng-if="$root.walletData.notifications.unreadCount">{{$root.walletData.notifications.unreadCount}}</span></a></div> \ No newline at end of file +<div ng-if=":state:enable && extensionPoint === 'menu-user'" class="visible-xs visible-sm"><a menu-close="" class="item item-icon-left" active-link="active" ng-if="login && walletData.isMember" active-link-path-prefix="#/app/invitations" ui-sref="app.view_invitations"><i class="icon ion-person-stalker"></i> <span translate="">MENU.INVITATIONS</span> <span class="badge badge-positive" ng-if="walletData.invitations.unreadCount">{{walletData.invitations.unreadCount}}</span> </a><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/user/message" ng-class="{'item-menu-disable': !login}" ui-sref="app.user_message.tab_inbox"><i class="icon ion-email"></i> <span translate="">MENU.MESSAGES</span> <span class="badge badge-positive" ng-if="walletData.messages.unreadCount">{{walletData.messages.unreadCount}}</span> </a><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/notifications" ng-class="{'item-menu-disable': !login}" ui-sref="app.view_notifications"><i class="icon ion-android-notifications"></i> <span translate="">MENU.NOTIFICATIONS</span> <span class="badge badge-positive" ng-if="walletData.notifications.unreadCount">{{walletData.notifications.unreadCount}}</span></a></div> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/message/compose_form.html b/assets/www/plugins/es/templates/message/compose_form.html index 668e4cb34133a0ae8ae4b2b6e4a9d2e591bfc99b..2b738d578ea935dee1713c9c415468178d56e4ed 100644 --- a/assets/www/plugins/es/templates/message/compose_form.html +++ b/assets/www/plugins/es/templates/message/compose_form.html @@ -1,2 +1,2 @@ -<form name="messageForm" novalidate="" ng-submit="doSend()"><div class="list no-margin" ng-init="setForm(messageForm)"><a class="item item-icon-right gray ink" ng-class="{'item-input-error': form.$submitted && !formData.destPub}" ng-click="showWotLookupModal()"><span class="gray" translate>MESSAGE.COMPOSE.TO</span> <span class="badge badge-royal">{{destUid}}{{destPub | formatPubkey}}</span> <i class="gray icon ion-ios-arrow-right"></i></a><div class="form-errors" ng-if="form.$submitted && !formData.destPub"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-text-wrap"><span class="gray" translate>TRANSFER.FROM</span> <span class="badge badge-balanced"><ion-spinner icon="android" ng-if="!$root.walletData.pubkey"></ion-spinner><span ng-if="$root.walletData.pubkey && !$root.walletData.isMember">{{$root.walletData.pubkey| formatPubkey}} </span><span ng-if="$root.walletData.isMember">{{$root.walletData.name||$root.walletData.uid}}</span></span></div><div class="item item-input" ng-class="{'item-input-error': form.$submitted && form.title.$invalid}"><input type="text" placeholder="{{'MESSAGE.COMPOSE.OBJECT_HELP' | translate}}" name="title" ng-model="formData.title" ng-maxlength="256" required></div><div class="form-errors" ng-show="form.$submitted && form.title.$error" ng-messages="form.title.$error"><div class="form-error" ng-message="maxlength"><span translate="MESSAGE.ERROR.MESSAGE_CONTENT_TOO_LONG" translate-values="{maxLength: 256}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-input item-floating-label" ng-class="{'item-input-error': form.$submitted && form.content.$invalid}"><span class="input-label">{{'MESSAGE.COMPOSE.MESSAGE' | translate}}</span><textarea placeholder="{{'MESSAGE.COMPOSE.MESSAGE_HELP' | translate}}" name="content" ng-model="formData.content" rows="8" ng-maxlength="5000"> - </textarea></div><div class="form-errors" ng-show="form.$submitted && form.content.$error" ng-messages="form.content.$error"><div class="form-error" ng-message="maxlength"><span translate="MESSAGE.ERROR.MESSAGE_CONTENT_TOO_LONG" translate-values="{maxLength: 5000}"></span></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="cancel()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" type="submit" translate>TRANSFER.BTN_SEND</button></div><div class="list no-margin"><div class="item item-icon-left item-text-wrap"><i class="icon ion-ios-information-outline positive"></i><h4 class="positive" translate>MESSAGE.COMPOSE.ENCRYPTED_HELP</h4></div></div></form> \ No newline at end of file +<form name="messageForm" novalidate="" ng-submit="doSend()"><div class="list no-margin" ng-init="setForm(messageForm)"><a class="item item-icon-right gray ink" ng-class="{'item-input-error': form.$submitted && !formData.destPub}" ng-click="showWotLookupModal()"><span class="gray" translate>MESSAGE.COMPOSE.TO</span> <span class="badge badge-royal" ng-if="destUid"><i class="ion-person"></i> {{destName||destUid}}</span> <span class="badge badge-stable" ng-if="!destUid && destPub">{{destName}} <span ng-if="!destName"><i class="ion-key"></i>{{destPub | formatPubkey}}</span> </span> <i class="gray icon ion-ios-arrow-right"></i></a><div class="form-errors" ng-if="form.$submitted && !formData.destPub"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><ion-item class="item-text-wrap ink" ng-class="{'item-icon-right': enableSelectWallet}" ng-click="showSelectWalletModal()"><span class="gray" translate>TRANSFER.FROM</span> <span class="badge badge-balanced animate-fade-in animate-show-hide" ng-show="!loading"><ion-spinner icon="android" ng-if="!walletData.pubkey"></ion-spinner><span ng-if="walletData.pubkey && !walletData.isMember"><i class="ion-key"></i> {{walletData.pubkey| formatPubkey}} </span><span ng-if="walletData.isMember"><i class="ion-person"></i> {{walletData.name||walletData.uid}} </span></span><i class="gray icon ion-ios-arrow-right" ng-if="enableSelectWallet"></i></ion-item><div class="item item-input" ng-class="{'item-input-error': form.$submitted && form.title.$invalid}"><input type="text" autocomplete="off" placeholder="{{'MESSAGE.COMPOSE.OBJECT_HELP' | translate}}" name="title" ng-model="formData.title" ng-maxlength="256" required> <span class="badge item-note" ng-if="isReply">({{'MESSAGE.COMPOSE.OBJECT' | translate}})</span></div><div class="form-errors" ng-show="form.$submitted && form.title.$error" ng-messages="form.title.$error"><div class="form-error" ng-message="maxlength"><span translate="MESSAGE.ERROR.MESSAGE_CONTENT_TOO_LONG" translate-values="{maxLength: 256}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-input item-floating-label" ng-class="{'item-input-error': form.$submitted && form.content.$invalid}"><span class="input-label">{{'MESSAGE.COMPOSE.MESSAGE' | translate}}</span><textarea placeholder="{{'MESSAGE.COMPOSE.MESSAGE_HELP' | translate}}" autocomplete="off" name="content" ng-model="formData.content" rows="8" ng-maxlength="5000"> + </textarea></div><div class="form-errors" ng-show="form.$submitted && form.content.$error" ng-messages="form.content.$error"><div class="form-error" ng-message="maxlength"><span translate="MESSAGE.ERROR.MESSAGE_CONTENT_TOO_LONG" translate-values="{maxLength: 5000}"></span></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="cancel()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" type="submit" ng-disabled="sending" translate>TRANSFER.BTN_SEND</button></div><div class="list no-margin"><div class="item item-icon-left item-text-wrap"><i class="icon ion-ios-information-outline positive"></i><h4 class="positive" translate>MESSAGE.COMPOSE.ENCRYPTED_HELP</h4></div></div></form> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/message/list.html b/assets/www/plugins/es/templates/message/list.html index bc9a0e910c35ab4bc56edbe1c9d15465dd8d3b66..5df5353af229197e3003da7ffe26976b7595e838 100644 --- a/assets/www/plugins/es/templates/message/list.html +++ b/assets/www/plugins/es/templates/message/list.html @@ -1 +1 @@ -<div class="padding gray" ng-if="!search.loading && !search.results.length"><span ng-if="search.type=='last'">{{ ('MESSAGE.NO_MESSAGE_' + type) | upper | translate }}</span> <span ng-if="search.type=='text'" translate="">COMMON.SEARCH_NO_RESULT</span></div><ion-list class="{{::motion.ionListClass}}" can-swipe="$root.device.enable"><ion-item class="item item-border-large item-avatar item-icon-right ink" ng-repeat="msg in search.results" ui-sref="app.user_view_message({type:type, id:msg.id})"><i ng-if="::!msg.avatar" class="item-image icon" ng-class="{'ion-person': msg.uid, 'ion-email': !msg.uid}"></i> <i ng-if="::msg.avatar" class="item-image avatar" style="background-image: url({{::msg.avatar.src}})"></i><h4 class="pull-right visible-xs visible-sm dark"><i class="ion-clock"></i> {{::msg.time|formatFromNow}}</h4><h3><a class="positive" ng-if="::msg.name||msg.uid" ui-sref="app.wot_identity({pubkey:msg.issuer, uid:msg.name||msg.uid})"><i class="ion-person"></i> {{::msg.name||msg.uid}} </a><a class="gray" ng-if="::!msg.name && !msg.uid" ui-sref="app.wot_identity({pubkey:msg.issuer})"><i class="ion-key"></i> {{::msg.issuer|formatPubkey}}</a></h3><h2 ng-class="{'unread': !msg.read}" ng-bind-html="::msg.title"></h2><p ng-bind-html="::msg.summary||msg.content"></p><i class="icon ion-ios-arrow-right"></i><ion-option-button class="button-stable" ng-click="showReplyModal($index)" translate="">MESSAGE.BTN_REPLY</ion-option-button><ion-option-button class="button-assertive" ng-click="delete($index)" translate="">COMMON.BTN_DELETE</ion-option-button></ion-item></ion-list><ion-infinite-scroll ng-if="!search.loading && search.hasMore" icon="ion-loading-c" on-infinite="showMore()" distance="10%"></ion-infinite-scroll> \ No newline at end of file +<div class="padding gray" ng-if="!search.loading && !search.results.length"><span ng-if="search.type=='last'">{{ ('MESSAGE.NO_MESSAGE_' + type) | upper | translate }}</span> <span ng-if="search.type=='text'" translate="">COMMON.SEARCH_NO_RESULT</span></div><ion-list class="{{::motion.ionListClass}}" can-swipe="$root.device.enable"><ion-item class="item item-border-large item-avatar item-icon-right ink" ng-repeat="msg in :rebind:search.results track by msg.id" ng-click="select(msg, $event)"><i ng-if="::!msg.avatar" class="item-image icon" ng-class="{'ion-person': msg.uid, 'ion-email': !msg.uid}"></i> <i ng-if="::msg.avatar" class="item-image avatar" style="background-image: url({{::msg.avatar.src}})"></i><h4 class="pull-right visible-xs visible-sm dark"><i class="ion-clock"></i> {{::msg.time|formatFromNow}}</h4><h3><a class="positive" ng-if="::msg.name||msg.uid" ui-sref="app.wot_identity({pubkey:msg.issuer, uid:msg.name||msg.uid})"><i class="ion-person"></i> {{::msg.name||msg.uid}} </a><a class="gray" ng-if="::!msg.name && !msg.uid" ui-sref="app.wot_identity({pubkey:msg.issuer})"><i class="ion-key"></i> {{::msg.issuer|formatPubkey}}</a></h3><h2 ng-class="{'unread': !msg.read}" ng-bind-html="::msg.title"></h2><p ng-bind-html="::msg.summary||msg.content"></p><i class="icon ion-ios-arrow-right"></i><ion-option-button class="button-stable" ng-click="showReplyModal($index)" translate="">MESSAGE.BTN_REPLY</ion-option-button><ion-option-button class="button-assertive" ng-click="delete($index)" translate="">COMMON.BTN_DELETE</ion-option-button></ion-item></ion-list><ion-infinite-scroll ng-if="!search.loading && search.hasMore" icon="ion-loading-c" on-infinite="showMore()" distance="10%"></ion-infinite-scroll> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/message/lookup_by_id.html b/assets/www/plugins/es/templates/message/lookup_by_id.html new file mode 100644 index 0000000000000000000000000000000000000000..a43360bd0d59038bf3eb23a3a9187e55ee33cfc1 --- /dev/null +++ b/assets/www/plugins/es/templates/message/lookup_by_id.html @@ -0,0 +1 @@ +<ion-view left-buttons="leftButtons" class="view-messages"><ion-tabs class="tabs-positive tabs-icon-top"><ion-tab title="{{'MESSAGE.LIST.INBOX'|translate}}" icon="ion-archive" ui-sref="app.user_messages_by_id.tab_inbox"><ion-nav-view name="tab_inbox"></ion-nav-view></ion-tab><ion-tab title="{{'MESSAGE.LIST.OUTBOX'|translate}}" icon="ion-paper-airplane" ui-sref="app.user_messages_by_id.tab_outbox"><ion-nav-view name="tab_outbox"></ion-nav-view></ion-tab></ion-tabs></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/message/lookup_lg.html b/assets/www/plugins/es/templates/message/lookup_lg.html index c9ab307683073be0660a5c9cf73ed2e6f7bd3075..63c36da9aff0198699df363879ba84849528d5bc 100644 --- a/assets/www/plugins/es/templates/message/lookup_lg.html +++ b/assets/www/plugins/es/templates/message/lookup_lg.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" class="view-messages"><ion-nav-title><span translate="">MESSAGE.LIST.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear visible-xs visible-sm" ng-click="showActionsPopover($event)"><i class="icon ion-android-more-vertical"></i></button></ion-nav-buttons><ion-content class="padding no-padding-xs"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="refresh(true)"></ion-refresher><div class="item no-padding"><div class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{'MESSAGE.LIST.SEARCH_HELP'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()" on-return="doSearch()" select-on-click=""><div class="helptip-anchor-center"><a id="helptip-message-search-text"></a></div></div></div><div class="padding-top hidden-xs" style="display: block; height: 60px"><div class="pull-left" ng-if="!search.loading"><ng-if ng-if="search.type=='last'"><h4>{{ ('MESSAGE.LIST.LAST_' + type) | upper | translate}}</h4></ng-if><ng-if ng-if="search.type=='text'"><h4 translate="">COMMON.RESULTS_LIST</h4></ng-if></div></div><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><ng-include src="'plugins/es/templates/message/list.html'"></ng-include></ion-content><button id="fab-add-message-record" class="button button-fab button-fab-bottom-right button-assertive icon ion-compose visible-xs visible-sm spin" ng-click="showNewMessageModal()"></button></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="view-messages"><ion-nav-title><span translate="">MESSAGE.LIST.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear visible-xs visible-sm" ng-click="showActionsPopover($event)"><i class="icon ion-android-more-vertical"></i></button></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="refresh(true, $event)"></ion-refresher><div class="item no-padding"><div class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{'MESSAGE.LIST.SEARCH_HELP'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()" on-return="doSearch()" select-on-click=""><div class="helptip-anchor-center"><a id="helptip-message-search-text"></a></div></div></div><div class="padding-top hidden-xs" style="display: block; height: 60px"><div class="pull-left" ng-if="!search.loading"><ng-if ng-if="search.type=='last'"><h4>{{ ('MESSAGE.LIST.LAST_' + type) | upper | translate}}</h4></ng-if><ng-if ng-if="search.type=='text'"><h4 translate="">COMMON.RESULTS_LIST</h4></ng-if></div></div><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><ng-include src="'plugins/es/templates/message/list.html'"></ng-include></ion-content><button id="fab-add-message-record" class="button button-fab button-fab-bottom-right button-assertive icon ion-compose visible-xs visible-sm spin" ng-click="showNewMessageModal()"></button></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/message/view_message.html b/assets/www/plugins/es/templates/message/view_message.html index 4dd1a8d55e32ddd8f4babfa3915daaf681d98182..e3559b26a323fa11e0d4907af6ec34b93b824a6f 100644 --- a/assets/www/plugins/es/templates/message/view_message.html +++ b/assets/www/plugins/es/templates/message/view_message.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" class="view-message"><ion-nav-title><span translate="">MESSAGE.VIEW.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true"><div class="row no-padding"><div class="col no-padding"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><ion-list class="animate-fade-slide-in item-text-wrap"><div class="item item-avatar" ng-class="{'item-avatar': formData.avatar}"><i ng-if="!formData.avatar" class="item-image" ng-class="{'ion-person': formData.uid, 'ion-email': !formData.uid}"></i> <i ng-if="formData.avatar" class="item-image avatar" style="background-image: url({{::formData.avatar.src}})"></i><h4>{{type == 'inbox' ? 'MESSAGE.VIEW.SENDER': 'MESSAGE.VIEW.RECIPIENT'|translate}} <a class="positive" ui-sref="app.wot_identity({pubkey: (type == 'inbox') ? formData.issuer : formData.recipient, uid: formData.name||formData.uid})"><span ng-if="formData.uid"><i class="ion-person"></i> {{formData.name||formData.uid}} </span><span ng-if="!formData.uid" class="gray"><i class="ion-key gray"></i> {{formData.name||(formData.issuer|formatPubkey)}}</span></a></h4><h5 class="gray visible-xs visible-sm"><i class="ion-clock"></i> {{formData.time | formatDate}}</h5></div><ion-item class="visible-xs visible-sm"><h1 class="title" ng-bind-html="formData.title"></h1></ion-item><ion-item><p ng-bind-html="formData.html"></p><div class="padding gray" ng-if="!formData.content" translate="">MESSAGE.VIEW.NO_CONTENT</div></ion-item></ion-list></div></div></ion-content><button id="fab-view-message-reply" class="button button-fab button-fab-bottom-right button-calm icon ion-reply visible-xs visible-sm spin" ng-click="showReplyModal()"></button></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="view-message"><ion-nav-title><span translate="">MESSAGE.VIEW.TITLE</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true"><div class="row no-padding"><div class="col no-padding"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="list animate-fade-slide-in item-text-wrap"><div class="item item-avatar" ng-class="{'item-avatar': formData.avatar}"><i ng-if="!formData.avatar" class="item-image" ng-class="{'ion-person': formData.uid, 'ion-email': !formData.uid}"></i> <i ng-if="formData.avatar" class="item-image avatar" style="background-image: url({{::formData.avatar.src}})"></i><h4>{{type == 'inbox' ? 'MESSAGE.VIEW.SENDER': 'MESSAGE.VIEW.RECIPIENT'|translate}} <a class="positive" ui-sref="app.wot_identity({pubkey: (type == 'inbox') ? formData.issuer : formData.recipient, uid: formData.name||formData.uid})"><span ng-if="formData.uid"><i class="ion-person"></i> {{formData.name||formData.uid}} </span><span ng-if="!formData.uid" class="gray"><i class="ion-key gray"></i> {{formData.name||(formData.issuer|formatPubkey)}}</span></a></h4><h5 class="gray visible-xs visible-sm"><i class="ion-clock"></i> {{formData.time | formatDate}}</h5></div><ion-item class="visible-xs visible-sm"><h1 class="title" ng-bind-html="formData.title"></h1></ion-item><ion-item><p ng-bind-html="formData.html"></p><div class="padding gray" ng-if="!formData.content" translate="">MESSAGE.VIEW.NO_CONTENT</div></ion-item></div></div></div></ion-content><button id="fab-view-message-reply" class="button button-fab button-fab-bottom-right button-calm icon ion-reply visible-xs visible-sm spin" ng-click="showReplyModal()"></button></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/network/view_network_extend.html b/assets/www/plugins/es/templates/network/view_network_extend.html index 21e182bd87da4f2362c8ec6582cacf1d24d877c2..78761c3a1ca6625fc5634807c4690cb70c84c533 100644 --- a/assets/www/plugins/es/templates/network/view_network_extend.html +++ b/assets/www/plugins/es/templates/network/view_network_extend.html @@ -1 +1 @@ -<ng-if ng-if="enable && extensionPoint === 'buttons'"><a class="button button-text button-small ink" ui-sref="app.blockchain_search"><i class="icon ion-android-search"></i> <span>{{'COMMON.BTN_SEARCH'|translate}}</span></a></ng-if> \ No newline at end of file +<ng-if ng-if=":state:enable"><a class="button button-text button-small ink" ui-sref="app.blockchain_search"><i class="icon ion-android-search"></i> <span>{{'COMMON.BTN_SEARCH'|translate}}</span></a></ng-if> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/notification/list_notification.html b/assets/www/plugins/es/templates/notification/list_notification.html index 1e31e096b2acd7e8758ad6aa063791fe7d181817..4f10121211ed4748568f310da2a9220d60b6c358 100644 --- a/assets/www/plugins/es/templates/notification/list_notification.html +++ b/assets/www/plugins/es/templates/notification/list_notification.html @@ -1 +1 @@ -<ion-list class="{{::motion.ionListClass}}"><ion-item ng-repeat="notification in search.results" class="item-border-large item-text-wrap ink item-avatar" ng-class="{'unread': !notification.read}" ng-click="select(notification)"><i ng-if="!notification.avatar" class="item-image icon {{::notification.avatarIcon}}"></i> <i ng-if="notification.avatar" class="item-image avatar" style="background-image: url({{::notification.avatar.src}})"></i><h3 trust-as-html="notification.message | translate:notification"></h3><h4><i class="icon {{notification.icon}}"></i> <span class="dark">{{notification.time|formatFromNow}}</span> <span class="gray">| {{notification.time|formatDate}}</span></h4></ion-item></ion-list><ion-infinite-scroll ng-if="!search.loading && search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll> \ No newline at end of file +<ion-list class="{{::motion.ionListClass}}"><ion-item ng-repeat="notification in search.results track by notification.id" class="item-border-large item-text-wrap ink item-avatar" ng-class="{'unread': !notification.read}" ng-click="select($event, notification)"><i ng-if="!notification.avatar" class="item-image icon {{::notification.avatarIcon}}"></i> <i ng-if="notification.avatar" class="item-image avatar" style="background-image: url({{::notification.avatar.src}})"></i><h3 trust-as-html="notification.message | translate:(notification.messageParams||notification)"></h3><h4 ng-if="!notification.medianTime"><i class="icon {{notification.icon}}"></i> <span class="dark">{{notification.time|formatFromNow}}</span> <span class="gray">| {{notification.time|formatDate}}</span></h4><h4 ng-if="notification.medianTime"><i class="icon {{notification.icon}}"></i> <span class="dark">{{notification.medianTime|medianFromNow}}</span> <span class="gray">| {{notification.medianTime|medianDate}}</span></h4></ion-item></ion-list><ion-infinite-scroll ng-if="!search.loading && search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/notification/view_notifications.html b/assets/www/plugins/es/templates/notification/view_notifications.html index b3d674c12d8122e40e4d4aa01c3770ce598e0cd5..a48a8222410625762271f0d55a46beb6e5a48d7f 100644 --- a/assets/www/plugins/es/templates/notification/view_notifications.html +++ b/assets/www/plugins/es/templates/notification/view_notifications.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" class="view-notification"><ion-nav-title>{{'COMMON.NOTIFICATIONS.TITLE' | translate}}</ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs" scroll="true"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="refresh(true)"></ion-refresher><div class="row no-padding"><div class="col no-padding-xs"><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="padding gray" ng-if="!search.loading && !search.results.length" translate="">COMMON.NOTIFICATIONS.NO_RESULT</div><ng-include src="'plugins/es/templates/notification/list_notification.html'"></ng-include></div></div></ion-content></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="view-notification"><ion-nav-title>{{'COMMON.NOTIFICATIONS.TITLE' | translate}}</ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="refresh(true)"></ion-refresher><div class="row no-padding"><div class="col no-padding-xs no-padding-sm"><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="padding gray" ng-if="!search.loading && !search.results.length" translate="">COMMON.NOTIFICATIONS.NO_RESULT</div><ng-include src="'plugins/es/templates/notification/list_notification.html'"></ng-include></div></div></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/registry/edit_record.html b/assets/www/plugins/es/templates/registry/edit_record.html index c45cb66d20c1da82450f9040c7960945dcf143e5..18deca60ed4ae728c40ae710f9b1f3286a1e9155 100644 --- a/assets/www/plugins/es/templates/registry/edit_record.html +++ b/assets/www/plugins/es/templates/registry/edit_record.html @@ -1,2 +1,2 @@ -<ion-view left-buttons="leftButtons" class="view-page"><ion-nav-title><span class="visible-xs" ng-if="id" ng-bind-html="formData.title"></span> <span class="visible-xs" ng-if="!loading && !id" translate="">REGISTRY.EDIT.TITLE_NEW</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear visible-xs visible-sm" ng-class="{'ion-android-send':!id, 'ion-android-done': id}" ng-click="save()"></button></ion-nav-buttons><ion-content scroll="true"><div class="hero"><div class="content"><i class="avatar" ng-class="avatarClass" ng-style="avatarStyle"><button class="button button-positive button-large button-clear flat icon ion-camera visible-xs visible-sm" style="display: inline-block" ng-click="showAvatarModal()"></button> <button ng-if="avatar.src" class="button button-positive button-large button-clear flat visible-xs visible-sm" style="display: inline-block; left: 85px; bottom:15px" ng-click="rotateAvatar()"><i class="icon-secondary ion-image" style="left: 24px; top: 3px; font-size: 24px"></i> <i class="icon-secondary ion-forward" style="left: 26px; top: -13px"></i></button></i><h3 class="dark"><span ng-if="!loading && formData.title">{{formData.title}}</span> <span ng-if="!loading && !id && !formData.title" translate="">REGISTRY.EDIT.TITLE_NEW</span></h3><h4 class="dark"><ion-spinner ng-if="loading" icon="android"></ion-spinner></h4></div></div><div class="row no-padding"><div class="col no-padding-xs"><form name="recordForm" novalidate="" ng-submit="save()"><div class="list {{::motion.ionListClass}}" ng-init="setForm(recordForm)"><div class="item" ng-if="id"><h4 class="gray"><i class="icon ion-calendar"></i> {{'COMMON.LAST_MODIFICATION_DATE'|translate}} {{formData.time | formatDate}}</h4><div class="badge badge-balanced badge-editable" ng-click="showRecordTypeModal()">{{'REGISTRY.TYPE.ENUM.'+formData.type|upper|translate}}</div></div><ng-include src="'plugins/es/templates/common/edit_pictures.html'"></ng-include><div class="item item-divider" translate="">REGISTRY.GENERAL_DIVIDER</div><div class="item item-input item-floating-label" ng-class="{'item-input-error': form.$submitted && form.title.$invalid}"><span class="input-label" translate="">REGISTRY.EDIT.RECORD_TITLE</span> <input type="text" placeholder="{{'REGISTRY.EDIT.RECORD_TITLE_HELP'|translate}}" name="title" id="registry-record-title" ng-model="formData.title" ng-minlength="3" ng-required="true"></div><div class="form-errors" ng-if="form.$submitted && form.title.$error" ng-messages="form.title.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div><div class="item item-input item-floating-label"><span class="input-label" translate="">REGISTRY.EDIT.RECORD_DESCRIPTION</span><textarea placeholder="{{'REGISTRY.EDIT.RECORD_DESCRIPTION_HELP'|translate}}" ng-model="formData.description" rows="8" cols="10"> +<ion-view left-buttons="leftButtons" class="view-page"><ion-nav-title><span class="visible-xs" ng-if="id" ng-bind-html="formData.title"></span> <span class="visible-xs" ng-if="!loading && !id" translate="">REGISTRY.EDIT.TITLE_NEW</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear visible-xs visible-sm" ng-class="{'ion-android-send':!id, 'ion-android-done': id}" ng-click="save()"></button></ion-nav-buttons><ion-content scroll="true"><div class="hero"><div class="content"><i class="avatar" ng-class="avatarClass" ng-style="avatarStyle"><button class="button button-positive button-large button-clear flat icon ion-camera visible-xs visible-sm" style="display: inline-block" ng-click="showAvatarModal()"></button> <button ng-if="avatar.src" class="button button-positive button-large button-clear flat visible-xs visible-sm" style="display: inline-block; left: 85px; bottom:15px" ng-click="rotateAvatar()"><i class="icon-secondary ion-image" style="left: 24px; top: 3px; font-size: 24px"></i> <i class="icon-secondary ion-forward" style="left: 26px; top: -13px"></i></button></i><h3 class="dark"><span ng-if="!loading && formData.title">{{formData.title}}</span> <span ng-if="!loading && !id && !formData.title" translate="">REGISTRY.EDIT.TITLE_NEW</span></h3><h4 class="dark"><ion-spinner ng-if="loading" icon="android"></ion-spinner></h4></div></div><div class="row no-padding"><div class="col no-padding-xs no-padding-sm"><form name="recordForm" novalidate="" ng-submit="save()"><div class="list {{::motion.ionListClass}}" ng-init="setForm(recordForm)"><div class="item" ng-if="id"><h4 class="gray"><i class="icon ion-calendar"></i> {{'COMMON.LAST_MODIFICATION_DATE'|translate}} {{formData.time | formatDate}}</h4><div class="badge badge-balanced badge-editable" ng-click="showRecordTypeModal()">{{'REGISTRY.TYPE.ENUM.'+formData.type|upper|translate}}</div></div><ng-include src="'plugins/es/templates/common/edit_pictures.html'"></ng-include><div class="item item-divider" translate="">REGISTRY.GENERAL_DIVIDER</div><div class="item item-input item-floating-label" ng-class="{'item-input-error': form.$submitted && form.title.$invalid}"><span class="input-label" translate="">REGISTRY.EDIT.RECORD_TITLE</span> <input type="text" placeholder="{{'REGISTRY.EDIT.RECORD_TITLE_HELP'|translate}}" name="title" id="registry-record-title" ng-model="formData.title" ng-minlength="3" ng-required="true"></div><div class="form-errors" ng-if="form.$submitted && form.title.$error" ng-messages="form.title.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div><div class="item item-input item-floating-label"><span class="input-label" translate="">REGISTRY.EDIT.RECORD_DESCRIPTION</span><textarea placeholder="{{'REGISTRY.EDIT.RECORD_DESCRIPTION_HELP'|translate}}" ng-model="formData.description" rows="8" cols="10"> </textarea></div><div class="item item-icon-right ink" ng-if="loading || formData.type==='company' || formData.type==='shop'" ng-class="{'item-input-error': form.$submitted && !formData.category.id, 'done in': !loading}" ng-click="showCategoryModal()"><span translate="">REGISTRY.CATEGORY</span> <span class="badge badge-royal">{{formData.category.name | formatCategory}}</span> <i class="gray icon ion-ios-arrow-right"></i></div><input type="hidden" name="category" ng-model="formData.category.id" required-if="formData.type=='company' || formData.type=='shop'"><div class="form-errors" ng-if="form.$submitted && form.category.$error" ng-messages="form.category.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><ng-include src="'plugins/es/templates/common/edit_position.html'"></ng-include><ng-include src="'plugins/es/templates/common/edit_socials.html'" ng-controller="ESSocialsEditCtrl"></ng-include><div class="item item-divider" translate="">REGISTRY.TECHNICAL_DIVIDER</div><div class="item item-input item-floating-label"><span class="input-label" translate="">REGISTRY.EDIT.RECORD_PUBKEY</span> <input type="text" placeholder="{{'REGISTRY.EDIT.RECORD_PUBKEY_HELP'|translate}}" ng-model="formData.pubkey"></div></div></form></div></div></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/registry/lookup_form.html b/assets/www/plugins/es/templates/registry/lookup_form.html index ad9a9ae1c147e2a8435d50a5dbeaa5dabca9c443..c297dc0fd995e6bbaa54166fa7a27d0ec9a5a44f 100644 --- a/assets/www/plugins/es/templates/registry/lookup_form.html +++ b/assets/www/plugins/es/templates/registry/lookup_form.html @@ -1 +1 @@ -<form ng-submit="doSearch()"><div class="item no-padding"><div class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{'REGISTRY.SEARCH.SEARCH_HELP'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()" on-return="doSearchText()" select-on-click=""></div></div><ng-include src="::'plugins/es/templates/common/item_location_search.html'" ng-if="entered && options.location.show && (!search.geoPoint || smallscreen)" ng-controller="ESSearchPositionItemCtrl"></ng-include><ng-include src="::'plugins/es/templates/registry/lookup_form_options.html'"></ng-include></form><div class="padding-xs" style="display: block; height: 60px"><div class="pull-left ng-hide" ng-show="!search.loading && search.results"><ng-if ng-if="search.lastRecords"><h4 translate="">REGISTRY.SEARCH.LAST_RECORDS</h4><small class="gray no-padding" ng-if="search.total"><span ng-if="search.geoPoint && search.total">{{'REGISTRY.SEARCH.LAST_RECORD_COUNT_LOCATION'|translate:{count: search.total, location: search.location} }}</span> <span ng-if="!search.geoPoint && search.total">{{'REGISTRY.SEARCH.LAST_RECORD_COUNT'|translate:{count: search.total} }}</span></small></ng-if><ng-if ng-if="!search.lastRecords"><h4 translate="">COMMON.RESULTS_LIST</h4><small class="gray no-padding" ng-if="search.total"><span ng-if="search.geoPoint && search.total">{{'REGISTRY.SEARCH.RESULT_COUNT_LOCATION'|translate:{count: search.total, location: search.location} }}</span> <span ng-if="!search.geoPoint && search.total">{{'REGISTRY.SEARCH.RESULT_COUNT'|translate:{count: search.total} }}</span></small></ng-if></div></div><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="padding assertive" ng-if="!search.loading && search.results.length===0" translate="">COMMON.SEARCH_NO_RESULT</div> \ No newline at end of file +<form ng-submit="doSearch()"><div class="item no-padding"><div class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{'REGISTRY.SEARCH.SEARCH_HELP'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()" on-return="doSearchText()" select-on-click=""></div></div><ng-include src="::'plugins/es/templates/common/item_location_search.html'" ng-if="entered && options.location.show && (!search.geoPoint || smallscreen)" ng-controller="ESSearchPositionItemCtrl"></ng-include><ng-include src="::'plugins/es/templates/registry/lookup_form_options.html'"></ng-include></form><div class="padding-top padding-xs padding-sm" style="display: block; height: 60px"><div class="pull-left ng-hide" ng-show="!search.loading && search.results"><ng-if ng-if="search.lastRecords"><h4 translate="">REGISTRY.SEARCH.LAST_RECORDS</h4><small class="gray no-padding" ng-if="search.total"><span ng-if="search.geoPoint && search.total">{{'REGISTRY.SEARCH.LAST_RECORD_COUNT_LOCATION'|translate:{count: search.total, location: search.location} }}</span> <span ng-if="!search.geoPoint && search.total">{{'REGISTRY.SEARCH.LAST_RECORD_COUNT'|translate:{count: search.total} }}</span></small></ng-if><ng-if ng-if="!search.lastRecords"><h4 translate="">COMMON.RESULTS_LIST</h4><small class="gray no-padding" ng-if="search.total"><span ng-if="search.geoPoint && search.total">{{'REGISTRY.SEARCH.RESULT_COUNT_LOCATION'|translate:{count: search.total, location: search.location} }}</span> <span ng-if="!search.geoPoint && search.total">{{'REGISTRY.SEARCH.RESULT_COUNT'|translate:{count: search.total} }}</span></small></ng-if></div></div><div class="center" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="padding assertive" ng-if="!search.loading && search.results.length===0" translate="">COMMON.SEARCH_NO_RESULT</div> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/registry/lookup_lg.html b/assets/www/plugins/es/templates/registry/lookup_lg.html index 06c9f392d6d80ef808bdfbcbd3f3ed706c5196da..e63736f12aa90b153d8a8ff3d7781071897ce447 100644 --- a/assets/www/plugins/es/templates/registry/lookup_lg.html +++ b/assets/www/plugins/es/templates/registry/lookup_lg.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons"><ion-nav-title>{{'REGISTRY.SEARCH.TITLE' | translate}}</ion-nav-title><ion-content class="lookupForm padding no-padding-xs"><ng-include src="::'plugins/es/templates/wot/lookup_lg_extend.html'" ng-init="showNewPageButton=true;"></ng-include><ng-include src="::'plugins/es/templates/registry/lookup_form.html'"></ng-include><ng-include src="::'plugins/es/templates/registry/lookup_list_lg.html'"></ng-include></ion-content><button id="fab-add-registry-record" class="button button-fab button-fab-bottom-right button-assertive icon ion-plus hidden-md hidden-lg spin" ng-click="showNewPageModal()"></button></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons"><ion-nav-title>{{'REGISTRY.SEARCH.TITLE' | translate}}</ion-nav-title><ion-content class="lookupForm padding no-padding-xs no-padding-sm"><ng-include src="::'plugins/es/templates/wot/lookup_lg_extend.html'" ng-init="enable= true; showNewPageButton=true;"></ng-include><ng-include src="::'plugins/es/templates/registry/lookup_form.html'"></ng-include><ng-include src="::'plugins/es/templates/registry/lookup_list_lg.html'"></ng-include></ion-content><button id="fab-add-registry-record" class="button button-fab button-fab-bottom-right button-assertive icon ion-plus hidden-md hidden-lg spin" ng-click="showNewPageModal()"></button></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/registry/lookup_list.html b/assets/www/plugins/es/templates/registry/lookup_list.html index 619be642d5e2867be414b9d05d60b096b9731eb6..fa6232229b289208d79176fe1fa318fbe5f6771d 100644 --- a/assets/www/plugins/es/templates/registry/lookup_list.html +++ b/assets/www/plugins/es/templates/registry/lookup_list.html @@ -1 +1 @@ -<ion-list class="{{::motion.ionListClass}}" ng-if="!search.loading && search.results && search.results.length > 0"><ion-item ng-repeat="item in search.results" class="item item-border-large item-avatar item-icon-right ink" ng-class="::{'item-icon-left': !smallscreen}" ui-sref="app.view_page({id: item.id, title: item.urlTitle})"><i ng-if="::!item.avatar" class="item-image icon cion-page-{{::item.type}}"></i> <i ng-if="::item.avatar" class="item-image avatar" style="background-image: url({{::item.avatar.src}})"></i><h2 ng-bind-html="::item.title"></h2><h4><span class="dark" ng-if="::item.city"><b class="ion-location"></b> <span ng-bind-html="::item.city"></span> </span><span class="gray" ng-if="::item.distance">({{::item.distance|formatDecimal}} {{::geoUnit}})</span></h4><h4 class="gray" ng-if="::item.time && search.lastRecords"><i class="ion-clock"></i> {{::item.time | formatFromNow}}</h4><h4 class="gray" ng-if="!search.lastRecords"><i class="cion-page-{{::item.type}}"></i> <span ng-if="item.category">{{::item.category.name}}</span> <span ng-if="!item.category">{{::'REGISTRY.TYPE.ENUM.'+item.type|uppercase|translate}}</span></h4><i class="icon ion-ios-arrow-right"></i></ion-item></ion-list> \ No newline at end of file +<ion-list class="{{::motion.ionListClass}}" ng-if="!search.loading && search.results"><div class="item item-avatar item-icon-right item-border-large ink" ng-repeat="item in search.results" ui-sref="app.view_page({id: item.id, title: item.urlTitle})"><i ng-if="::!item.avatar" class="item-image icon cion-page-{{::item.type}}"></i> <i ng-if="::item.avatar" class="item-image avatar" style="background-image: url({{::item.avatar.src}})"></i><h2 ng-bind-html="::item.title"></h2><h4><span class="dark" ng-if="::item.city"><b class="ion-location"></b> <span ng-bind-html="::item.city"></span> </span><span class="gray" ng-if="::item.distance">({{::item.distance|formatDecimal}} {{::geoUnit}})</span></h4><h4 class="gray" ng-if="::item.time && search.lastRecords"><i class="ion-clock"></i> {{::item.time | formatFromNow}}</h4><h4 class="gray" ng-if="!search.lastRecords"><i class="cion-page-{{::item.type}}"></i> <span ng-if="item.category">{{::item.category.name}}</span> <span ng-if="!item.category">{{::'REGISTRY.TYPE.ENUM.'+item.type|uppercase|translate}}</span></h4><i class="icon ion-ios-arrow-right"></i></div></ion-list> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/registry/view_record.html b/assets/www/plugins/es/templates/registry/view_record.html index 2f57b5eac6663a8425aec929e47d984ac0918aec..2bb647bf6c83d688f18ea37ca15aa548b754c76a 100644 --- a/assets/www/plugins/es/templates/registry/view_record.html +++ b/assets/www/plugins/es/templates/registry/view_record.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" class="view-page"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-bar button-icon button-clear visible-xs visible-sm" ng-click="edit()" ng-if="canEdit"><i class="icon ion-android-create"></i></button> <button class="button button-bar button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true" class="refresher-top-bg"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="load()"></ion-refresher><div class="hero"><div class="content" ng-if="!loading"><i class="avatar cion-page-{{formData.type}}" ng-if="!formData.avatar"></i> <i class="avatar" ng-style="{{avatarStyle}}" ng-if="formData.avatar"></i><h3><span class="dark" ng-bind-html="formData.title"></span></h3><h4> </h4></div><h4 class="content dark" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><div class="row no-padding-xs"><div class="col list animate-fade-slide-in item-text-wrap no-padding-xs"><div class="item"><h2 class="gray"><a ng-if="formData.city" ui-sref="app.wot_lookup.tab_registry({location:formData.city})"><i class="icon ion-location"></i> <span ng-bind-html="formData.city"></span> </a><span ng-if="formData.city && formData.type"> | </span> <a ng-if="formData.type" ui-sref="app.wot_lookup.tab_registry({type:formData.type})"><i class="cion-page-{{formData.type}}"></i> {{'REGISTRY.TYPE.ENUM.'+formData.type|upper|translate}}</a></h2><h4><i class="icon ion-clock" ng-if="formData.time"></i> <span translate="">COMMON.SUBMIT_BY</span> <a ng-class="{'positive': issuer.uid, 'gray': !issuer.uid}" ui-sref="app.wot_identity({pubkey:issuer.pubkey, uid: issuer.name||issuer.uid})"><ng-if ng-if="issuer.uid"><i class="icon ion-person"></i> {{::issuer.name||issuer.uid}}</ng-if><span ng-if="!issuer.uid"><i class="icon ion-key"></i> {{issuer.pubkey|formatPubkey}} </span></a><span>{{formData.time|formatFromNow}}<h4 class="gray hidden-xs">| {{formData.time | formatDate}}</h4></span></h4></div><a id="registry-share-anchor-{{id}}"></a><ion-item><h2 trust-as-html="formData.description"></h2></ion-item><ion-item ng-if="formData.category || formData.address"><h4 ng-if="formData.category"><span class="gray" translate="">REGISTRY.VIEW.CATEGORY</span> <a class="positive" ng-if="formData.category" ui-sref="app.wot_lookup.tab_registry({category:formData.category.id})"><span ng-bind-html="formData.category.name"></span></a></h4><h4 ng-if="formData.address"><span class="gray" translate="">REGISTRY.VIEW.LOCATION</span> <a class="positive" target="_system" href="https://www.openstreetmap.org/search?query={{formData.address}},%20{{formData.city}}"><span ng-bind-html="formData.address"></span> <span ng-if="formData.city">- </span><span ng-bind-html="formData.city"></span></a></h4></ion-item><ng-if ng-if="formData.socials && formData.socials.length>0"><ion-item class="item-icon-left" type="no-padding item-text-wrap" ng-repeat="social in formData.socials track by social.url" id="social-{{social.url|formatSlug}}"><i class="icon ion-social-{{social.type}}" ng-class="{'ion-bookmark': social.type == 'other', 'ion-link': social.type == 'web', 'ion-email': social.type == 'email'}"></i><p ng-if="social.type && social.type != 'web'">{{social.type}}</p><h2><a ng-click="openLink($event, social.url, social.type)">{{social.url}}</a></h2></ion-item></ng-if><div class="item item-icon-left item-text-wrap ink" ng-if="formData.pubkey" copy-on-click="{{::formData.pubkey}}"><i class="icon ion-key"></i> <span translate="">REGISTRY.EDIT.RECORD_PUBKEY</span><h4 class="dark">{{::formData.pubkey}}</h4></div><div class="lazy-load"><ng-include src="'plugins/es/templates/common/view_pictures.html'"></ng-include><ng-include src="'plugins/es/templates/common/view_comments.html'"></ng-include></div></div></div></ion-content><button class="button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm" ng-if="formData.pubkey && !isUserPubkey(formData.pubkey)" ng-click="showTransferModal({pubkey: formData.pubkey, uid: formData.title})"></button></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="view-page"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-bar button-icon button-clear visible-xs visible-sm" ng-click="edit()" ng-if="canEdit"><i class="icon ion-android-create"></i></button> <button class="button button-bar button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true" class="refresher-top-bg"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="load()"></ion-refresher><div class="hero"><div class="content" ng-if="!loading"><i class="avatar cion-page-{{formData.type}}" ng-if="!formData.avatar"></i> <i class="avatar" ng-style="{{avatarStyle}}" ng-if="formData.avatar"></i><h3><span class="dark" ng-bind-html="formData.title"></span></h3><h4> </h4></div><h4 class="content dark" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><div class="row no-padding-xs no-padding-sm"><div class="col list animate-fade-slide-in item-text-wrap no-padding-xs no-padding-sm"><div class="item"><h2 class="gray"><a ng-if="formData.city" ui-sref="app.wot_lookup.tab_registry({location:formData.city})"><i class="icon ion-location"></i> <span ng-bind-html="formData.city"></span> </a><span ng-if="formData.city && formData.type"> | </span> <a ng-if="formData.type" ui-sref="app.wot_lookup.tab_registry({type:formData.type})"><i class="cion-page-{{formData.type}}"></i> {{'REGISTRY.TYPE.ENUM.'+formData.type|upper|translate}}</a></h2><h4><i class="icon ion-clock" ng-if="formData.time"></i> <span translate="">COMMON.SUBMIT_BY</span> <a ng-class="{'positive': issuer.uid, 'gray': !issuer.uid}" ui-sref="app.wot_identity({pubkey:issuer.pubkey, uid: issuer.name||issuer.uid})"><ng-if ng-if="issuer.uid"><i class="icon ion-person"></i> {{::issuer.name||issuer.uid}}</ng-if><span ng-if="!issuer.uid"><i class="icon ion-key"></i> {{issuer.pubkey|formatPubkey}} </span></a><span>{{formData.time|formatFromNow}}<h4 class="gray hidden-xs">| {{formData.time | formatDate}}</h4></span></h4></div><a id="registry-share-anchor-{{id}}"></a><div class="item"><h2 trust-as-html="formData.description"></h2></div><div class="item" ng-if="formData.category || formData.address"><h4 ng-if="formData.category"><span class="gray" translate="">REGISTRY.VIEW.CATEGORY</span> <a class="positive" ng-if="formData.category" ui-sref="app.wot_lookup.tab_registry({category:formData.category.id})"><span ng-bind-html="formData.category.name"></span></a></h4><h4 ng-if="formData.address"><span class="gray" translate="">REGISTRY.VIEW.LOCATION</span> <a class="positive" target="_system" href="https://www.openstreetmap.org/search?query={{formData.address}},%20{{formData.city}}"><span ng-bind-html="formData.address"></span> <span ng-if="formData.city">- </span><span ng-bind-html="formData.city"></span></a></h4></div><ng-if ng-if="formData.socials && formData.socials.length>0"><div class="item item-icon-left" type="no-padding item-text-wrap" ng-repeat="social in formData.socials track by social.url" id="social-{{social.url|formatSlug}}"><i class="icon ion-social-{{social.type}}" ng-class="{'ion-bookmark': social.type == 'other', 'ion-link': social.type == 'web', 'ion-email': social.type == 'email'}"></i><p ng-if="social.type && social.type != 'web'">{{social.type}}</p><h2><a ng-click="openLink($event, social.url, social.type)">{{social.url}}</a></h2></div></ng-if><div class="item item-icon-left item-text-wrap ink" ng-if="formData.pubkey" copy-on-click="{{::formData.pubkey}}"><i class="icon ion-key"></i> <span translate="">REGISTRY.EDIT.RECORD_PUBKEY</span><h4 class="dark">{{::formData.pubkey}}</h4></div><div class="lazy-load"><ng-include src="'plugins/es/templates/common/view_pictures.html'"></ng-include><ng-include src="'plugins/es/templates/common/view_comments.html'"></ng-include></div></div></div></ion-content><button class="button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm" ng-if="formData.pubkey && !isUserPubkey(formData.pubkey)" ng-click="showTransferModal({pubkey: formData.pubkey, uid: formData.title})"></button></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/registry/view_wallet_pages.html b/assets/www/plugins/es/templates/registry/view_wallet_pages.html index 501d72a1c01df281ad524c59ed17ed296b7cf74e..940cfbe690e3526d2a329899611f8196d853c07a 100644 --- a/assets/www/plugins/es/templates/registry/view_wallet_pages.html +++ b/assets/www/plugins/es/templates/registry/view_wallet_pages.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" class="view-notification"><ion-nav-title>{{'REGISTRY.MY_PAGES' | translate}}</ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-loop visible-xs visible-sm" ng-click="load()"></button> <button class="button button-icon button-clear visible-xs visible-sm" ng-click="showActionsPopover($event)"><i class="icon ion-android-more-vertical"></i></button></ion-nav-buttons><ion-content class="padding no-padding-xs" scroll="true"><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding gray" ng-if="!search.loading && !search.results.length" translate="">REGISTRY.NO_PAGE</div><ng-include src="'plugins/es/templates/registry/lookup_list.html'"></ng-include></ion-content></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="view-notification"><ion-nav-title>{{'REGISTRY.MY_PAGES' | translate}}</ion-nav-title><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ion-refresher pulling-text="{{:locale:'COMMON.BTN_REFRESH' | translate}}" on-refresh="doUpdate()"></ion-refresher><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding gray" ng-if="!search.loading && !search.results.length" translate="">REGISTRY.NO_PAGE</div><ng-include src="'plugins/es/templates/registry/lookup_list.html'"></ng-include></ion-content><button id="fab-wallet-add-registry-record" class="button button-fab button-fab-bottom-right button-assertive hidden-md hidden-lg spin" ng-click="showNewPageModal()"><i class="icon ion-plus"></i></button></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/settings/plugin_settings.html b/assets/www/plugins/es/templates/settings/plugin_settings.html index f2d38a70e0208678f4f1046ae8f7a2a7eb0d0717..e91d5cb0475199a1bdb826aa2b8d8763bb36d2d0 100644 --- a/assets/www/plugins/es/templates/settings/plugin_settings.html +++ b/assets/www/plugins/es/templates/settings/plugin_settings.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" class="settings"><ion-nav-title translate>ES_SETTINGS.PLUGIN_NAME</ion-nav-title><ion-content scroll="true"><div class="item item-toggle dark"><div class="input-label" translate>ES_SETTINGS.ENABLE_TOGGLE</div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.enable"><div class="track"><div class="handle"></div></div></label></div><span class="item item-divider" translate>SETTINGS.NETWORK_SETTINGS</span><div class="item ink" ng-click="formData.enable && changeEsNode()" ng-disabled="!formData.enable"><div class="input-label" ng-class="{'gray': !formData.enable}">{{'ES_SETTINGS.PEER' | translate}}</div><ng-if ng-if="isFallbackNode"><h4 class="gray text-wrap assertive"><i class="icon ion-alert-circled"></i> <span ng-bind-html="'SETTINGS.PEER_CHANGED_TEMPORARY' | translate "></span></h4><div class="item-note assertive text-italic">{{server}}</div></ng-if><span ng-if="!isFallbackNode" class="item-note" ng-class="{'dark': formData.enable}">{{server}}</span></div><span class="item item-divider" translate>ES_SETTINGS.NOTIFICATIONS.DIVIDER</span> <span class="item gray item-text-wrap" translate>ES_SETTINGS.NOTIFICATIONS.HELP_TEXT</span><label class="item item-toggle dark item-text-wrap"><span ng-class="{'gray': !formData.enable}" translate>ES_SETTINGS.NOTIFICATIONS.ENABLE_TX_SENT</span><div class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.txSent" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></div></label><label class="item item-toggle dark item-text-wrap"><span ng-class="{'gray': !formData.enable}" translate>ES_SETTINGS.NOTIFICATIONS.ENABLE_TX_RECEIVED</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.txReceived" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></label></label><label class="item item-toggle dark item-text-wrap"><span ng-class="{'gray': !formData.enable}" translate>ES_SETTINGS.NOTIFICATIONS.ENABLE_CERT_SENT</span><div class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.certSent" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></div></label><label class="item item-toggle dark item-text-wrap"><span ng-class="{'gray': !formData.enable}" translate>ES_SETTINGS.NOTIFICATIONS.ENABLE_CERT_RECEIVED</span><div class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.certReceived" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></div></label><cs-extension-point name="common"></cs-extension-point></ion-content></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="settings"><ion-nav-title translate="">ES_SETTINGS.PLUGIN_NAME</ion-nav-title><ion-content scroll="true"><div class="item item-toggle dark"><div class="input-label" translate="">ES_SETTINGS.ENABLE_TOGGLE</div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.enable"><div class="track"><div class="handle"></div></div></label></div><span class="item item-divider" translate="">SETTINGS.STORAGE_DIVIDER</span><div class="item item-toggle item-text-wrap dark"><div class="input-label" ng-class="{'gray': !formData.enable}" translate="">ES_SETTINGS.ENABLE_REMOTE_STORAGE</div><h4 class="gray text-wrap" ng-bind-html="'ES_SETTINGS.ENABLE_REMOTE_STORAGE_HELP' | translate"></h4><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.useRemoteStorage" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></label></div><span class="item item-divider" translate="">SETTINGS.NETWORK_SETTINGS</span><ion-item class="ink item-icon-right item-text-wrap visible-xs visible-sm" ng-click="formData.enable && changeEsNode()" ng-disabled="!formData.enable"><div class="input-label" ng-class="{'gray': !formData.enable}" translate="">ES_SETTINGS.PEER</div><ng-if ng-if="isFallbackNode"><h4 class="gray text-wrap assertive"><b class="ion-alert-circled"></b> <span ng-bind-html="'SETTINGS.PEER_CHANGED_TEMPORARY' | translate "></span></h4><div class="badge badge-assertive">{{server}}</div></ng-if><div class="badge" ng-class="{'badge-balanced': formData.enable, 'badge-stable': !formData.enable}" ng-if="!isFallbackNode">{{server}}</div><i class="icon ion-ios-arrow-right"></i></ion-item><span class="item item-divider" translate="">ES_SETTINGS.NOTIFICATIONS.DIVIDER</span><span class="item gray item-text-wrap" translate="">ES_SETTINGS.NOTIFICATIONS.HELP_TEXT</span><label class="item item-toggle dark item-text-wrap"><span ng-class="{'gray': !formData.enable}" translate="">ES_SETTINGS.NOTIFICATIONS.ENABLE_TX_SENT</span><div class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.txSent" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></div></label><label class="item item-toggle dark item-text-wrap"><span ng-class="{'gray': !formData.enable}" translate="">ES_SETTINGS.NOTIFICATIONS.ENABLE_TX_RECEIVED</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.txReceived" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></label></label><label class="item item-toggle dark item-text-wrap"><span ng-class="{'gray': !formData.enable}" translate="">ES_SETTINGS.NOTIFICATIONS.ENABLE_CERT_SENT</span><div class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.certSent" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></div></label><label class="item item-toggle dark item-text-wrap"><span ng-class="{'gray': !formData.enable}" translate="">ES_SETTINGS.NOTIFICATIONS.ENABLE_CERT_RECEIVED</span><div class="toggle toggle-royal"><input type="checkbox" ng-model="formData.notifications.certReceived" ng-disabled="!formData.enable"><div class="track"><div class="handle"></div></div></div></label><cs-extension-point name="common"></cs-extension-point></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/subscription/edit_subscriptions.html b/assets/www/plugins/es/templates/subscription/edit_subscriptions.html index 54ba409f91b03359b99633411391e8060a75beac..8763cb48412d1f78299e2d6913cdabdd15fa437d 100644 --- a/assets/www/plugins/es/templates/subscription/edit_subscriptions.html +++ b/assets/www/plugins/es/templates/subscription/edit_subscriptions.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" class="view-notification"><ion-nav-title>{{'SUBSCRIPTION.EDIT.TITLE' | translate}}</ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-loop visible-xs visible-sm" ng-click="load()"></button> <button class="button button-icon button-clear visible-xs visible-sm" ng-click="showActionsPopover($event)"><i class="icon ion-android-more-vertical"></i></button></ion-nav-buttons><ion-content class="padding no-padding-xs" scroll="true"><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding gray" ng-if="!search.loading && !search.results.length" translate="">SUBSCRIPTION.NO_SUBSCRIPTION</div><div class="row no-padding"><div class="col list {{::motion.ionListClass}} item-border-large"><ng-repeat ng-repeat="subscriptions in search.results | filter: { type: 'email' }" ng-include="'plugins/es/templates/subscription/item_' + subscriptions.type.toLowerCase() + '_subscription.html'">></ng-repeat></div></div></ion-content></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="view-notification"><ion-nav-title>{{'SUBSCRIPTION.EDIT.TITLE' | translate}}</ion-nav-title><ion-nav-buttons side="secondary"></ion-nav-buttons><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ion-refresher pulling-text="{{:locale:'COMMON.BTN_REFRESH' | translate}}" on-refresh="load()"></ion-refresher><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding gray" ng-if="!search.loading && !search.results.length" translate="">SUBSCRIPTION.NO_SUBSCRIPTION</div><div class="row no-padding"><div class="col list {{::motion.ionListClass}} item-border-large"><ng-repeat ng-repeat="subscriptions in search.results | filter: { type: 'email' }" ng-include="'plugins/es/templates/subscription/item_' + subscriptions.type.toLowerCase() + '_subscription.html'">></ng-repeat></div></div></ion-content><button id="fab-add-subscription-record" class="button button-fab button-fab-bottom-right button-assertive icon ion-plus hidden-md hidden-lg spin" ng-click="addSubscription()"></button></ion-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/subscription/item_email_subscription.html b/assets/www/plugins/es/templates/subscription/item_email_subscription.html index 84d34cd8716cef11ea407598a465ce4b348e9202..b1dc83e123724b41551ce2da93222a993659da92 100644 --- a/assets/www/plugins/es/templates/subscription/item_email_subscription.html +++ b/assets/www/plugins/es/templates/subscription/item_email_subscription.html @@ -1 +1 @@ -<div class="item item-thumbnail-left"><i class="item-image icon ion-email"></i><h3>{{'SUBSCRIPTION.TYPE.ENUM.' + subscriptions.type.toUpperCase() | translate}}</h3><h4 class="gray">{{'SUBSCRIPTION.EDIT.PROVIDER'|translate}} <a ui-sref="app.wot_identity({pubkey: subscriptions.recipient, uid: subscriptions.uid})"><span ng-class="{'positive': subscriptions.uid, 'dark': !subscriptions.uid}" ng-if="subscriptions.name||subscriptions.uid"><i class="ion-person" ng-if="subscriptions.uid"></i> {{subscriptions.name||subscriptions.uid}} </span><span class="gray" ng-if="!subscriptions.uid"><i class="ion-key"></i> {{subscriptions.recipient | formatPubkey}}</span></a></h4><div class="item-note text-right"><span ng-repeat="item in subscriptions.items">{{item.content.email}} <a class="ion-trash-a gray padding-left" ng-click="deleteSubscription(item)"></a> <a class="ion-edit gray padding-left" ng-click="editSubscription(item)"></a><br></span></div></div> \ No newline at end of file +<div class="item item-avatar"><i class="item-image icon ion-email"></i><h3>{{'SUBSCRIPTION.TYPE.ENUM.' + subscriptions.type.toUpperCase() | translate}}</h3><h4 class="gray">{{'SUBSCRIPTION.EDIT.PROVIDER'|translate}} <a ui-sref="app.wot_identity({pubkey: subscriptions.recipient, uid: subscriptions.uid})"><span ng-class="{'positive': subscriptions.uid, 'dark': !subscriptions.uid}" ng-if="subscriptions.name||subscriptions.uid"><i class="ion-person" ng-if="subscriptions.uid"></i> {{subscriptions.name||subscriptions.uid}} </span><span class="gray" ng-if="!subscriptions.uid"><i class="ion-key"></i> {{subscriptions.recipient | formatPubkey}}</span></a></h4><div class="item-note text-right"><span ng-repeat="item in subscriptions.items">{{item.content.email}} <a class="ion-trash-a gray padding-left" ng-click="deleteSubscription(item)"></a> <a class="ion-edit gray padding-left" ng-click="editSubscription(item)"></a><br></span></div></div> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/subscription/modal_email.html b/assets/www/plugins/es/templates/subscription/modal_email.html index 81c6835aa871f060d095d3f7e7157615219a4bf2..5d7d0e8f0cfc8e2aede4f6a1e287673ca539dc04 100644 --- a/assets/www/plugins/es/templates/subscription/modal_email.html +++ b/assets/www/plugins/es/templates/subscription/modal_email.html @@ -1 +1 @@ -<ion-modal-view id="composeMessage" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>SUBSCRIPTION.MODAL_EMAIL.TITLE</h1><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doSubmit()"></button></ion-header-bar><ion-content scroll="true"><div class="item item-icon-left item-text-wrap"><i class="icon ion-ios-information-outline positive"></i><h4 class="positive" translate>SUBSCRIPTION.MODAL_EMAIL.HELP</h4></div><form name="subscriptionForm" novalidate="" ng-submit="doSubmit()"><div class="list" ng-init="setForm(subscriptionForm)"><label class="item item-input" ng-class="{'item-input-error': form.$submitted && (form.email.$invalid || form.email.$error)}"><span class="input-label" translate>SUBSCRIPTION.MODAL_EMAIL.EMAIL_LABEL</span> <input name="email" type="text" placeholder="{{'SUBSCRIPTION.MODAL_EMAIL.EMAIL_HELP' | translate}}" ng-model="formData.content.email" ng-minlength="3" required email></label><div class="form-errors" ng-if="form.$submitted && (form.email.$invalid || form.email.$error)" ng-messages="form.email.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div><div class="form-error" ng-message="email"><span translate="ERROR.FIELD_NOT_EMAIL"></span></div></div><label class="item item-input item-select" ng-class="{'item-input-error': form.$submitted && !formData.content.frequency}"><span class="input-label" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_LABEL</span><select name="frequency" ng-model="formData.content.frequency" style="height: 46px;margin-top: 1px"><option value="weekly" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_WEEKLY</option><option value="daily" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_DAILY</option></select></label><div class="form-errors" ng-if="form.$submitted && !formData.content.frequency"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><a class="item item-input item-icon-right gray ink" ng-class="{'item-input-error': form.$submitted && !formData.recipient}" ng-click="showNetworkLookup()" style="height: 67px"><span class="input-label" translate>SUBSCRIPTION.MODAL_EMAIL.PROVIDER</span> <span class="badge animate-fade-in animate-show-hide ng-hide" ng-class="{'badge-royal': recipient.uid, 'badge-stable': !recipient.uid}" ng-show="recipient && (recipient.name||recipient.uid)"><i class="ion-person" ng-if="recipient.uid"></i> {{recipient.name||recipient.uid}} </span><span class="badge badge-secondary animate-fade-in animate-show-hide ng-hide" ng-show="formData.recipient"><i class="ion-key"></i> {{formData.recipient | formatPubkey}} </span><i class="gray icon ion-ios-arrow-right"></i></a><div class="form-errors" ng-if="form.$submitted && !formData.recipient"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div></div><div class="padding hidden-xs text-right"><button class="button button-small button-clear button-dark ink" ng-click="cancel()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-small button-positive ink" type="submit">{{'COMMON.BTN_SEND' | translate}}</button></div></form></ion-content></ion-modal-view> \ No newline at end of file +<ion-modal-view id="composeMessage" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>SUBSCRIPTION.MODAL_EMAIL.TITLE</h1><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doSubmit()"></button></ion-header-bar><ion-content scroll="true"><div class="item item-icon-left item-text-wrap"><i class="icon ion-ios-information-outline positive"></i><h4 class="positive" translate>SUBSCRIPTION.MODAL_EMAIL.HELP</h4></div><form name="subscriptionForm" novalidate="" ng-submit="doSubmit()"><div class="list" ng-init="setForm(subscriptionForm)"><label class="item item-input" ng-class="{'item-input-error': form.$submitted && (form.email.$invalid || form.email.$error)}"><span class="input-label" translate>SUBSCRIPTION.MODAL_EMAIL.EMAIL_LABEL</span> <input name="email" type="text" placeholder="{{'SUBSCRIPTION.MODAL_EMAIL.EMAIL_HELP' | translate}}" ng-model="formData.content.email" ng-minlength="3" required email></label><div class="form-errors" ng-if="form.$submitted && (form.email.$invalid || form.email.$error)" ng-messages="form.email.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div><div class="form-error" ng-message="email"><span translate="ERROR.FIELD_NOT_EMAIL"></span></div></div><label class="item item-input item-select" ng-class="{'item-input-error': form.$submitted && !formData.content.frequency}"><span class="input-label" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_LABEL</span><select name="frequency" ng-model="formData.content.frequency" style="height: 46px;margin-top: 1px"><option value="weekly" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_WEEKLY</option><option value="daily" translate>SUBSCRIPTION.MODAL_EMAIL.FREQUENCY_DAILY</option></select></label><div class="form-errors" ng-if="form.$submitted && !formData.content.frequency"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><a class="item item-input item-icon-right gray ink" ng-class="{'item-input-error': form.$submitted && !formData.recipient}" ng-click="showNetworkLookup()" style="height: 67px"><span class="input-label" translate>SUBSCRIPTION.MODAL_EMAIL.PROVIDER</span> <span class="badge animate-fade-in animate-show-hide ng-hide" ng-class="{'badge-royal': recipient.uid, 'badge-stable': !recipient.uid}" ng-show="recipient && (recipient.name||recipient.uid)"><i class="ion-person" ng-if="recipient.uid"></i> {{recipient.name||recipient.uid}} </span><span class="badge badge-secondary animate-fade-in animate-show-hide ng-hide" ng-show="formData.recipient"><i class="ion-key"></i> {{formData.recipient | formatPubkey}} </span><i class="gray icon ion-ios-arrow-right"></i></a><div class="form-errors" ng-if="form.$submitted && !formData.recipient"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="cancel()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" type="submit">{{'COMMON.BTN_ADD' | translate}}</button></div></form></ion-content></ion-modal-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/user/items_profile.html b/assets/www/plugins/es/templates/user/items_profile.html index c8a7e6ed2e9dfcf0044cb851bc01666d1fba04ed..51d57477dd7e12b133a5f2b1b54f09c8b3fbcbbb 100644 --- a/assets/www/plugins/es/templates/user/items_profile.html +++ b/assets/www/plugins/es/templates/user/items_profile.html @@ -1 +1 @@ -<div ng-if="!formData.profile && !formData.name" class="item gray" translate>PROFILE.NO_PROFILE_DEFINED</div><div class="item" ng-if="formData.name && showName"><span class="gray" translate>PROFILE.TITLE</span><h3>{{formData.name}}</h3></div><div class="item item-text-wrap" ng-if="formData.profile.description"><span class="gray" translate>PROFILE.DESCRIPTION</span><h3 trust-as-html="formData.profile.description"></h3></div><div class="item" ng-if="formData.profile.address || formData.profile.city" copy-on-click="{{formData.profile.address ? formData.profile.address + ' ' : ''}}{{formData.profile.city}}"><span class="gray" translate>LOCATION.LOCATION_DIVIDER</span><h3><span class="text-keep-lines" ng-if="formData.profile.address">{{formData.profile.address}}<br></span>{{formData.profile.city}}</h3></div><div class="item" ng-if="formData.profile.socials && formData.profile.socials.length" ng-controller="ESSocialsViewCtrl"><span class="gray" translate>PROFILE.SOCIAL_NETWORKS_DIVIDER</span><div class="list no-padding"><ion-item ng-repeat="social in formData.profile.socials | filter:filterFn track by social.url " id="social-{{::social.url|formatSlug}}" class="item-icon-left item-text-wrap no-padding-bottom ink" on-tap="openSocial($event, social)"><i class="icon ion-social-{{social.type}}" ng-class="{'ion-bookmark': social.type == 'other', 'ion-link': social.type == 'web', 'ion-email': social.type == 'email', 'ion-iphone': social.type == 'phone'}"></i><p ng-if="social.type && social.type != 'web'">{{social.type}} <i class="ion-locked" ng-if="social.recipient"></i></p><h4><a on-tap="openSocial($event, social)" href="{{::social.url}}" target="_blank">{{::social.url}}</a></h4></ion-item></div></div> \ No newline at end of file +<div ng-if="!formData.profile" class="item gray" translate>PROFILE.NO_PROFILE_DEFINED</div><div class="item" ng-if="formData.profile && formData.name && showName"><span class="gray" translate>PROFILE.TITLE</span><h3>{{formData.name}}</h3></div><div class="item item-text-wrap" ng-if="formData.profile.description"><span class="gray" translate>PROFILE.DESCRIPTION</span><h3 trust-as-html="formData.profile.description"></h3></div><div class="item" ng-if="formData.profile.address || formData.profile.city" copy-on-click="{{formData.profile.address ? formData.profile.address + ' ' : ''}}{{formData.profile.city}}"><span class="gray" translate>LOCATION.LOCATION_DIVIDER</span><h3><span class="text-keep-lines" ng-if="formData.profile.address">{{formData.profile.address}}<br></span>{{formData.profile.city}}</h3></div><div class="item" ng-if="formData.profile.socials && formData.profile.socials.length" ng-controller="ESSocialsViewCtrl"><span class="gray" translate>PROFILE.SOCIAL_NETWORKS_DIVIDER</span><div class="list no-padding"><ion-item ng-repeat="social in formData.profile.socials | filter:filterFn track by social.url " id="social-{{::social.url|formatSlug}}" class="item-icon-left item-text-wrap no-padding-bottom ink" on-tap="openSocial($event, social)"><i class="icon ion-social-{{social.type}}" ng-class="{'ion-bookmark': social.type == 'other', 'ion-link': social.type == 'web', 'ion-email': social.type == 'email', 'ion-iphone': social.type == 'phone'}"></i><p ng-if="social.type && social.type != 'web'">{{social.type}} <i class="ion-locked" ng-if="social.recipient"></i></p><h4><a on-tap="openSocial($event, social)" href="{{::social.url}}" target="_blank">{{::social.url}}</a></h4></ion-item></div></div> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/wallet/item_wallet_extend.html b/assets/www/plugins/es/templates/wallet/item_wallet_extend.html new file mode 100644 index 0000000000000000000000000000000000000000..a76494426b51acfb5ab432b7089d655797ff3451 --- /dev/null +++ b/assets/www/plugins/es/templates/wallet/item_wallet_extend.html @@ -0,0 +1 @@ +<h4 class="dark" ng-if=":state:enable && wallet.id!='default'"><a ng-if="walletData.invitations.unreadCount"><i class="dark ion-person-stalker"></i> {{walletData.invitations.unreadCount}} </a><a ng-if="walletData.messages.unreadCount" ui-sref="app.user_messages_by_id.tab_inbox({id: wallet.id})"><i class="dark ion-email"></i> {{walletData.messages.unreadCount}} </a><a ng-if="walletData.notifications.unreadCount" ui-sref="app.view_notifications_by_id({id: wallet.id})"><i class="dark ion-android-notifications"></i> {{walletData.notifications.unreadCount}}</a></h4> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/wallet/view_wallet_extend.html b/assets/www/plugins/es/templates/wallet/view_wallet_extend.html index b184da14e0d7a667a1a4f1ae8608777ea640ad30..f8699e0502fcbf3dc3ada6cd72b042640ba11c83 100644 --- a/assets/www/plugins/es/templates/wallet/view_wallet_extend.html +++ b/assets/www/plugins/es/templates/wallet/view_wallet_extend.html @@ -1 +1 @@ -<ng-if ng-if="enable"><div class="item item-divider item-divider-top-border"><span>{{'PROFILE.PROFILE_DIVIDER' | translate}} <i style="font-size: 12pt; cursor: pointer" ng-click="showProfileHelp=!showProfileHelp" class="icon positive ion-ios-help-outline" title="{{'PROFILE.PROFILE_DIVIDER_HELP' | translate}}"></i> </span><a class="badge button button-text button-small button-small-padding" ui-sref="app.user_edit_profile"><i class="icon ion-edit"></i> <span ng-if="!formData.profile" translate>PROFILE.BTN_ADD</span> <span ng-if="formData.profile" translate>PROFILE.BTN_EDIT</span></a></div><div class="item item-text-wrap positive item-small-height" ng-show="showProfileHelp"><small translate>PROFILE.PROFILE_DIVIDER_HELP</small></div><div class="double-padding-x padding-bottom"><ng-include src="'plugins/es/templates/user/items_profile.html'" ng-init="showName=true;"></ng-include></div><div class="item item-divider item-divider-top-border"><span>{{'SUBSCRIPTION.SUBSCRIPTION_DIVIDER' | translate}} <i style="font-size: 12pt; cursor: pointer" ng-click="showSubscriptionHelp=!showSubscriptionHelp" class="icon positive ion-ios-help-outline" title="{{'SUBSCRIPTION.SUBSCRIPTION_DIVIDER_HELP' | translate}}"></i> <span><a class="badge button button-text button-small button-small-padding" ng-if="!formData.subscriptions.count" ui-sref="app.edit_subscriptions"><i class="icon ion-edit"></i> <span translate>SUBSCRIPTION.BTN_ADD</span></a></span></span></div><div class="item item-text-wrap positive item-small-height" ng-show="showSubscriptionHelp"><small translate>SUBSCRIPTION.SUBSCRIPTION_DIVIDER_HELP</small></div><div class="double-padding-x padding-bottom"><div ng-if="!formData.subscriptions.count" class="item gray" translate>SUBSCRIPTION.NO_SUBSCRIPTION</div><a class="item item-icon-left item-text-wrap item-icon-right ink" ng-if="formData.subscriptions.count" ui-sref="app.edit_subscriptions"><i class="icon ion-gear-a"></i> <span translate>SUBSCRIPTION.SUBSCRIPTION_COUNT</span> <span class="badge badge-calm">{{formData.subscriptions.count}}</span> <i class="gray icon ion-ios-arrow-right"></i></a></div><div class="item item-divider item-divider-top-border"><span>{{'REGISTRY.WALLET.REGISTRY_DIVIDER' | translate}} <i style="font-size: 12pt; cursor: pointer" ng-click="showPagesHelp=!showPagesHelp" class="icon positive ion-ios-help-outline" title="{{'REGISTRY.WALLET.REGISTRY_HELP' | translate}}"></i> <span><a class="badge button button-text button-small button-small-padding" ng-if="!formData.pages.count" ng-click="showNewPageModal()"><i class="icon ion-edit"></i> <span translate>REGISTRY.BTN_NEW</span></a></span></span></div><div class="item item-text-wrap positive item-small-height" ng-show="showPagesHelp"><small translate>REGISTRY.WALLET.REGISTRY_HELP</small></div><div class="double-padding-x padding-bottom"><div ng-if="!formData.pages.count" class="item gray" translate>REGISTRY.NO_PAGE</div><a class="item item-icon-left item-text-wrap item-icon-right ink" ng-if="formData.pages.count" ui-sref="app.wallet_pages"><i class="icon ion-social-buffer"></i> <span translate>REGISTRY.MY_PAGES</span> <span class="badge badge-calm">{{formData.pages.count}}</span> <i class="gray icon ion-ios-arrow-right"></i></a></div></ng-if> \ No newline at end of file +<ng-if ng-if=":state:enable"><div class="item item-divider item-divider-top-border"><span>{{'PROFILE.PROFILE_DIVIDER' | translate}} <i style="font-size: 12pt; cursor: pointer" ng-click="showProfileHelp=!showProfileHelp" class="icon positive ion-ios-help-outline" title="{{'PROFILE.PROFILE_DIVIDER_HELP' | translate}}"></i> </span><a class="badge button button-text button-small button-small-padding" ng-if="isDefaultWallet" ui-sref="app.edit_profile"><i class="icon ion-edit"></i> <span ng-if="!formData.profile" translate>PROFILE.BTN_ADD</span> <span ng-if="formData.profile" translate>PROFILE.BTN_EDIT</span> </a><a class="badge button button-text button-small button-small-padding" ng-if="!isDefaultWallet" ui-sref="app.edit_profile_by_id({id: walletId})"><i class="icon ion-edit"></i> <span ng-if="!formData.profile" translate>PROFILE.BTN_ADD</span> <span ng-if="formData.profile" translate>PROFILE.BTN_EDIT</span></a></div><div class="item item-text-wrap positive item-small-height" ng-show="showProfileHelp"><small translate>PROFILE.PROFILE_DIVIDER_HELP</small></div><ng-include src="'plugins/es/templates/user/items_profile.html'" ng-init="showName=true"></ng-include><div class="item item-divider item-divider-top-border"><span>{{'SUBSCRIPTION.SUBSCRIPTION_DIVIDER' | translate}} <i style="font-size: 12pt; cursor: pointer" ng-click="showSubscriptionHelp=!showSubscriptionHelp" class="icon positive ion-ios-help-outline" title="{{'SUBSCRIPTION.SUBSCRIPTION_DIVIDER_HELP' | translate}}"></i> <span><a class="badge button button-text button-small button-small-padding" ng-if="!formData.subscriptions.count && isDefaultWallet" ui-sref="app.edit_subscriptions"><i class="icon ion-edit"></i> <span translate>SUBSCRIPTION.BTN_ADD</span> </a><a class="badge button button-text button-small button-small-padding" ng-if="!formData.subscriptions.count && !isDefaultWallet" ui-sref="app.edit_subscriptions_by_id({id: walletId})"><i class="icon ion-edit"></i> <span translate>SUBSCRIPTION.BTN_ADD</span></a></span></span></div><div class="item item-text-wrap positive item-small-height" ng-show="showSubscriptionHelp"><small translate>SUBSCRIPTION.SUBSCRIPTION_DIVIDER_HELP</small></div><div ng-if="!formData.subscriptions.count" class="item gray" translate>SUBSCRIPTION.NO_SUBSCRIPTION</div><a class="item item-icon-left item-text-wrap item-icon-right ink" ng-if="formData.subscriptions.count && isDefaultWallet" ui-sref="app.edit_subscriptions"><i class="icon ion-gear-a"></i> <span translate>SUBSCRIPTION.SUBSCRIPTION_COUNT</span> <span class="badge badge-calm">{{formData.subscriptions.count}}</span> <i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-text-wrap item-icon-right ink" ng-if="formData.subscriptions.count && !isDefaultWallet" ui-sref="app.edit_subscriptions_by_id({id: walletId})"><i class="icon ion-gear-a"></i> <span translate>SUBSCRIPTION.SUBSCRIPTION_COUNT</span> <span class="badge badge-calm">{{formData.subscriptions.count}}</span> <i class="gray icon ion-ios-arrow-right"></i></a><div class="item item-divider item-divider-top-border"><span>{{'REGISTRY.WALLET.REGISTRY_DIVIDER' | translate}} <i style="font-size: 12pt; cursor: pointer" ng-click="showPagesHelp=!showPagesHelp" class="icon positive ion-ios-help-outline" title="{{'REGISTRY.WALLET.REGISTRY_HELP' | translate}}"></i> <span><a class="badge button button-text button-small button-small-padding" ng-if="!formData.pages.count" ng-click="showNewPageModal()"><i class="icon ion-edit"></i> <span translate>REGISTRY.BTN_NEW</span></a></span></span></div><div class="item item-text-wrap positive item-small-height" ng-show="showPagesHelp"><small translate>REGISTRY.WALLET.REGISTRY_HELP</small></div><div ng-if="!formData.pages.count" class="item gray" translate>REGISTRY.NO_PAGE</div><a class="item item-icon-left item-text-wrap item-icon-right ink" ng-if="formData.pages.count && isDefaultWallet" ui-sref="app.wallet_pages"><i class="icon ion-social-buffer"></i> <span translate>REGISTRY.MY_PAGES</span> <span class="badge badge-calm">{{formData.pages.count}}</span> <i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-text-wrap item-icon-right ink" ng-if="formData.pages.count && !isDefaultWallet" ui-sref="app.wallet_pages_by_id({id: walletId})"><i class="icon ion-social-buffer"></i> <span translate>REGISTRY.MY_PAGES</span> <span class="badge badge-calm">{{formData.pages.count}}</span> <i class="gray icon ion-ios-arrow-right"></i></a></ng-if> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/wot/lookup_extend.html b/assets/www/plugins/es/templates/wot/lookup_extend.html index 8ee865be486ea36a005c9dfbe13714948e5da8d7..19492c6c083c40a829d7fdd254147fc5f5a67afc 100644 --- a/assets/www/plugins/es/templates/wot/lookup_extend.html +++ b/assets/www/plugins/es/templates/wot/lookup_extend.html @@ -1 +1 @@ -<ion-tab title="{{'MENU.REGISTRY'|translate}}" icon="ion-social-buffer" ui-sref="app.wot_lookup.tab_registry"><ion-nav-view name="tab_registry"></ion-nav-view></ion-tab> \ No newline at end of file +<ion-tab ng-if=":state:enable" title="{{'MENU.REGISTRY'|translate}}" icon="ion-social-buffer" ui-sref="app.wot_lookup.tab_registry"><ion-nav-view name="tab_registry"></ion-nav-view></ion-tab> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/wot/lookup_lg_extend.html b/assets/www/plugins/es/templates/wot/lookup_lg_extend.html index 32d8b209dc6171210e7841abf5ed874b47ddb3f4..19cf96074dfabdd0fd79831720da2f830a9c1ec5 100644 --- a/assets/www/plugins/es/templates/wot/lookup_lg_extend.html +++ b/assets/www/plugins/es/templates/wot/lookup_lg_extend.html @@ -1 +1 @@ -<div class="buttons-tabs"><div class="pull-right"><div class="button button-tab dark" title="{{'REGISTRY.BTN_SHOW_WOT_HELP' | translate}}" nav-transition="none" active-link="active" active-link-path-prefix="#/app/wot/lg" ui-sref="app.wot_lookup_lg"><i class="icon ion-person-stalker"></i> {{'REGISTRY.BTN_SHOW_WOT' | translate}}</div><a class="button button-tab ink dark" title="{{'REGISTRY.BTN_SHOW_PAGES_HELP' | translate}}" nav-transition="none" active-link="active" active-link-path-prefix="#/app/wot/page" ui-sref="app.registry_lookup_lg"><i class="icon ion-social-buffer"></i> {{'REGISTRY.BTN_SHOW_PAGES' | translate}}</a></div><div class="pull-right" ng-if="showNewPageButton"> </div></div> \ No newline at end of file +<div class="buttons-tabs" ng-if=":state:enable"><div class="pull-right"><div class="button button-tab dark" title="{{'REGISTRY.BTN_SHOW_WOT_HELP' | translate}}" nav-transition="none" active-link="active" active-link-path-prefix="#/app/wot/lg" ui-sref="app.wot_lookup_lg"><i class="icon ion-person-stalker"></i> {{'REGISTRY.BTN_SHOW_WOT' | translate}}</div><a class="button button-tab ink dark" title="{{'REGISTRY.BTN_SHOW_PAGES_HELP' | translate}}" nav-transition="none" active-link="active" active-link-path-prefix="#/app/wot/page" ui-sref="app.registry_lookup_lg"><i class="icon ion-social-buffer"></i> {{'REGISTRY.BTN_SHOW_PAGES' | translate}}</a></div><div class="pull-right" ng-if="showNewPageButton"> </div></div> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/wot/popover_certification_actions.html b/assets/www/plugins/es/templates/wot/popover_certification_actions.html index 8f0e1df97bb000f8c7bec91bc6dde73d92fb371c..2f69160bd99e4b42e6b570bdd22909a91057bd5f 100644 --- a/assets/www/plugins/es/templates/wot/popover_certification_actions.html +++ b/assets/www/plugins/es/templates/wot/popover_certification_actions.html @@ -1 +1 @@ -<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-if="!isUserPubkey(formData.pubkey) && formData.isMember" ng-click="askCertification()"><i class="icon-secondary ion-ribbon-b" style="left: 16px; top: 0px; font-size: 25px"></i> <b class="icon-secondary ion-help" style="left: 35px; top: 0px"></b> {{'WOT.BTN_ASK_CERTIFICATION' | translate}} </a><a class="item item-icon-left ink" ng-if="isUserPubkey(formData.pubkey)" ng-click="showAskCertificationModal()"><i class="icon-secondary ion-ribbon-b" style="left: 16px; top: 0px; font-size: 25px"></i> <b class="icon-secondary ion-help" style="left: 35px; top: 0px"></b> {{'WOT.BTN_ASK_CERTIFICATIONS_DOTS' | translate}} </a><a class="item item-icon-left ink" ng-if="!isUserPubkey(formData.pubkey)" ng-click="showSuggestCertificationModal()"><i class="icon-secondary ion-person-stalker" style="left: 16px; top: 0px; font-size: 25px"></i> <b class="icon-secondary ion-help" style="left: 37px; top: -4px"></b> {{'WOT.BTN_SUGGEST_CERTIFICATIONS_DOTS' | translate}}</a></div></ion-content></ion-popover-view> \ No newline at end of file +<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-if="canCertify" ng-click="certify()"><i class="icon ion-ribbon-b"></i> {{'WOT.BTN_CERTIFY' | translate}} </a><a class="item item-icon-left ink" ng-if="!isUserPubkey(formData.pubkey) && formData.isMember" ng-click="askCertification()"><i class="icon-secondary ion-ribbon-b" style="left: 16px; top: 0px; font-size: 25px"></i> <b class="icon-secondary ion-help" style="left: 35px; top: 0px"></b> {{'WOT.BTN_ASK_CERTIFICATION' | translate}} </a><a class="item item-icon-left ink" ng-if="isUserPubkey(formData.pubkey)" ng-click="showAskCertificationModal()"><i class="icon-secondary ion-ribbon-b" style="left: 16px; top: 0px; font-size: 25px"></i> <b class="icon-secondary ion-help" style="left: 35px; top: 0px"></b> {{'WOT.BTN_ASK_CERTIFICATIONS_DOTS' | translate}} </a><a class="item item-icon-left ink" ng-if="!isUserPubkey(formData.pubkey)" ng-click="showSuggestCertificationModal()"><i class="icon-secondary ion-person-stalker" style="left: 16px; top: 0px; font-size: 25px"></i> <b class="icon-secondary ion-help" style="left: 37px; top: -4px"></b> {{'WOT.BTN_SUGGEST_CERTIFICATIONS_DOTS' | translate}}</a></div></ion-content></ion-popover-view> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/wot/view_certifications_extend.html b/assets/www/plugins/es/templates/wot/view_certifications_extend.html index cc88d9d020f05c8492a0b0fcdc20fa96d5e3dffe..be927851abd6d61b2a0b6bd0ebc772ec120c4143 100644 --- a/assets/www/plugins/es/templates/wot/view_certifications_extend.html +++ b/assets/www/plugins/es/templates/wot/view_certifications_extend.html @@ -1 +1 @@ -<ng-if ng-if="enable && extensionPoint === 'nav-buttons'"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showCertificationActionsPopover($event)"></button></ng-if><ng-if ng-if="enable && extensionPoint === 'buttons'"><button class="button button-stable button-small-padding icon ion-android-more-vertical" ng-click="showCertificationActionsPopover($event)" title="{{'COMMON.POPOVER_ACTIONS_TITLE' | translate}}"></button></ng-if> \ No newline at end of file +<ng-if ng-if=":state:enable && extensionPoint === 'nav-buttons'"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showCertificationActionsPopover($event)"></button></ng-if><ng-if ng-if=":state:enable && extensionPoint === 'buttons'"><button class="button button-stable button-small-padding icon ion-android-more-vertical" ng-click="showCertificationActionsPopover($event)" title="{{'COMMON.POPOVER_ACTIONS_TITLE' | translate}}"></button></ng-if> \ No newline at end of file diff --git a/assets/www/plugins/es/templates/wot/view_identity_extend.html b/assets/www/plugins/es/templates/wot/view_identity_extend.html index c83a3aa7ce251ac12222f0d93f199ff2c460f8f9..2ab296c0dd043ea92eb3e9710a9dbef9d62a9ef1 100644 --- a/assets/www/plugins/es/templates/wot/view_identity_extend.html +++ b/assets/www/plugins/es/templates/wot/view_identity_extend.html @@ -1 +1 @@ -<ng-if ng-if="enable && extensionPoint === 'buttons'"><button class="button button-stable button-small-padding icon ion-compose" ng-click="showNewMessageModal()" title="{{'MESSAGE.BTN_WRITE' | translate}}"></button></ng-if><ng-if ng-if="enable && extensionPoint === 'after-general'"><span class="item item-divider item-divider-top-border"><span>{{'PROFILE.PROFILE_DIVIDER' | translate}} <a style="font-size: 12pt; cursor: pointer" ng-click="showProfileHelp=!showProfileHelp" class="icon positive ion-ios-help-outline ink" title="{{'PROFILE.PROFILE_DIVIDER_HELP' | translate}}"></a></span></span><div class="item item-text-wrap positive item-small-height" ng-show="showProfileHelp"><small translate>PROFILE.PROFILE_DIVIDER_HELP</small></div><div class="double-padding-x padding-bottom"><ng-include src="'plugins/es/templates/user/items_profile.html'" ng-init="showName=false;"></ng-include></div></ng-if> \ No newline at end of file +<ng-if ng-if=":state:enable && extensionPoint === 'buttons'"><button class="button button-stable button-small-padding icon ion-compose" ng-click="showNewMessageModal()" title="{{'MESSAGE.BTN_WRITE' | translate}}"></button></ng-if><ng-if ng-if=":state:enable && extensionPoint === 'buttons-top-fab'"><button id="fab-compose-{{:rebind:formData.uid}}" class="button button-fab button-fab-top-left button-fab-hero mini button-stable spin" style="left: 88px" ng-click="showNewMessageModal()"><i class="icon ion-compose"></i></button></ng-if><ng-if ng-if=":state:enable && extensionPoint === 'after-general'"><span class="item item-divider item-divider-top-border"><span>{{'PROFILE.PROFILE_DIVIDER' | translate}} <a style="font-size: 12pt; cursor: pointer" ng-click="showProfileHelp=!showProfileHelp" class="icon positive ion-ios-help-outline ink" title="{{'PROFILE.PROFILE_DIVIDER_HELP' | translate}}"></a></span></span><div class="item item-text-wrap positive item-small-height" ng-show="showProfileHelp"><small translate>PROFILE.PROFILE_DIVIDER_HELP</small></div><ng-include src="'plugins/es/templates/user/items_profile.html'" ng-init="showName=false;"></ng-include></ng-if> \ No newline at end of file diff --git a/assets/www/plugins/graph/i18n/locale-en-GB.json b/assets/www/plugins/graph/i18n/locale-en-GB.json index 85cb9b5cf89d001465cf6d82a880b24676013618..d972514c8080e7603fe3884326ace68294ed5346 100644 --- a/assets/www/plugins/graph/i18n/locale-en-GB.json +++ b/assets/www/plugins/graph/i18n/locale-en-GB.json @@ -9,7 +9,13 @@ "LINEAR_SCALE" : "Linear scale", "LOGARITHMIC_SCALE" : "Logarithmic scale", "BTN_SHOW_STATS": "See statistics", - "BTN_SHOW_DETAILED_STATS": "Detailed statistics" + "BTN_SHOW_DETAILED_STATS": "Detailed statistics", + "RANGE_DURATION_DIVIDER": "Step unit:", + "RANGE_DURATION": { + "HOUR": "Group by <b>hour</b>", + "DAY": "Group by <b>day</b>", + "MONTH": "Group by <b>month</b>" + } }, "ACCOUNT": { "TITLE": "Statistics", @@ -35,13 +41,7 @@ "TX_AMOUNT_LABEL": "Exchange volume", "TX_COUNT_TITLE": "Number of written transactions", "TX_COUNT_LABEL": "Number of transactions", - "TX_AVG_BY_BLOCK": "Average per block", - "TX_RANGE_DURATION_DIVIDER": "Step unit:", - "TX_RANGE_DURATION": { - "HOUR": "Group by <b>hour</b>", - "DAY": "Group by <b>day</b>", - "MONTH": "Group by <b>month</b>" - } + "TX_AVG_BY_BLOCK": "Average per block" }, "CURRENCY": { "MONETARY_MASS_TITLE": "Evolution of the monetary mass", @@ -57,6 +57,35 @@ "BLOCK_COUNT": "{{count}} blocks", "NO_BLOCK": "No block" } + }, + "DOC_STATS": { + "TITLE": "Data storage statistics (Cesium+)", + "USER": { + "TITLE": "Number of documents linked to an account", + "USER_PROFILE": "User profiles", + "USER_SETTINGS": "Saved settings" + }, + "USER_DELTA": { + "TITLE": "Delta / Number of documents linked to an account", + "USER_PROFILE": "User profiles", + "USER_SETTINGS": "Saved settings" + }, + "MESSAGE": { + "TITLE": "Number of documents related to the communication", + "MESSAGE_INBOX": "Messages in inbox", + "MESSAGE_OUTBOX": "Messages in outbox", + "INVITATION_CERTIFICATION": "Invitations to certify" + }, + "SOCIAL": { + "TITLE": "Number of page or group", + "PAGE_COMMENT": "Comments", + "PAGE_RECORD": "Pages", + "GROUP_RECORD": "Groups" + }, + "OTHER": { + "TITLE": "Other documents", + "HISTORY_DELETE": "Deletion of documents" + } } } } diff --git a/assets/www/plugins/graph/i18n/locale-en.json b/assets/www/plugins/graph/i18n/locale-en.json index 5ecac739daa3e2c16723a0d6d3ec9c6713f0f10f..d972514c8080e7603fe3884326ace68294ed5346 100644 --- a/assets/www/plugins/graph/i18n/locale-en.json +++ b/assets/www/plugins/graph/i18n/locale-en.json @@ -9,7 +9,13 @@ "LINEAR_SCALE" : "Linear scale", "LOGARITHMIC_SCALE" : "Logarithmic scale", "BTN_SHOW_STATS": "See statistics", - "BTN_SHOW_DETAILED_STATS": "Detailed statistics" + "BTN_SHOW_DETAILED_STATS": "Detailed statistics", + "RANGE_DURATION_DIVIDER": "Step unit:", + "RANGE_DURATION": { + "HOUR": "Group by <b>hour</b>", + "DAY": "Group by <b>day</b>", + "MONTH": "Group by <b>month</b>" + } }, "ACCOUNT": { "TITLE": "Statistics", @@ -35,13 +41,7 @@ "TX_AMOUNT_LABEL": "Exchange volume", "TX_COUNT_TITLE": "Number of written transactions", "TX_COUNT_LABEL": "Number of transactions", - "TX_AVG_BY_BLOCK": "Average per block", - "TX_RANGE_DURATION_DIVIDER": "Step unit:", - "TX_RANGE_DURATION": { - "HOUR": "Group by <b>hour</b>", - "DAY": "Group by <b>day</b>", - "MONTH": "Group by <b>month</b>" - } + "TX_AVG_BY_BLOCK": "Average per block" }, "CURRENCY": { "MONETARY_MASS_TITLE": "Evolution of the monetary mass", @@ -59,11 +59,16 @@ } }, "DOC_STATS": { - "TITLE": "Data storage statistitics", + "TITLE": "Data storage statistics (Cesium+)", "USER": { "TITLE": "Number of documents linked to an account", - "USER_PROFILE": "User profiles utilisateur", - "USER_SETTINGS": "Saved settings", + "USER_PROFILE": "User profiles", + "USER_SETTINGS": "Saved settings" + }, + "USER_DELTA": { + "TITLE": "Delta / Number of documents linked to an account", + "USER_PROFILE": "User profiles", + "USER_SETTINGS": "Saved settings" }, "MESSAGE": { "TITLE": "Number of documents related to the communication", @@ -75,11 +80,11 @@ "TITLE": "Number of page or group", "PAGE_COMMENT": "Comments", "PAGE_RECORD": "Pages", - "GROUP_RECORD": "Groups", + "GROUP_RECORD": "Groups" }, "OTHER": { "TITLE": "Other documents", - "HISTORY_DELETE": "Deletion of documents", + "HISTORY_DELETE": "Deletion of documents" } } } diff --git a/assets/www/plugins/graph/i18n/locale-eo-EO.json b/assets/www/plugins/graph/i18n/locale-eo-EO.json new file mode 100644 index 0000000000000000000000000000000000000000..c2e16e8936f29320287f4ed35159368ac731dcfd --- /dev/null +++ b/assets/www/plugins/graph/i18n/locale-eo-EO.json @@ -0,0 +1,113 @@ +{ + "NETWORK": { + "VIEW": { + "BTN_GRAPH": "Statistikoj" + } + }, + "GRAPH": { + "COMMON": { + "LINEAR_SCALE" : "Lineara skalo", + "LOGARITHMIC_SCALE" : "Logaritma skalo", + "BTN_SHOW_STATS": "Vidi la statistikojn", + "BTN_SHOW_DETAILED_STATS": "Detalaj statistikoj", + "RANGE_DURATION_DIVIDER": "Tempo-unuo:", + "RANGE_DURATION": { + "HOUR": "Horo", + "DAY": "Tago", + "MONTH": "Monato" + } + }, + "ACCOUNT": { + "TITLE": "Statistikoj", + "BTN_SHOW_STATS": "Vidi la statistikojn de la konto", + "BALANCE_DIVIDER": "Stato de la konto", + "BALANCE_TITLE": "Evoluo de la konto {{pubkey|formatPubkey}}", + "TX_RECEIVED_LABEL": "Enspezoj", + "TX_SENT_LABEL": "Elspezoj", + "TX_ACCUMULATION_LABEL": "Bilanco de la spezoj", + "UD_LABEL": "UD", + "UD_ACCUMULATION_LABEL": "Bilanco de la UD", + "BALANCE_LABEL": "Saldo", + "WOT_DIVIDER": "Reto de fido", + "CERTIFICATION_TITLE": "Nombro de atestaĵoj - {{pubkey|formatPubkey}}", + "RECEIVED_CERT_LABEL": "Tuto pri la ricevitaj", + "RECEIVED_CERT_DELTA_LABEL": "Vario pri la ricevitaj", + "GIVEN_CERT_LABEL": "Tuto pri la senditaj", + "GIVEN_CERT_DELTA_LABEL": "Vario pri la senditaj", + "INPUT_CHART_TITLE": "Sumo de la enirantaj fluoj, por ĉiu sendinto:", + "OUTPUT_CHART_TITLE": "Sumo de la elirantaj fluoj, por ĉiu ricevinto:" + }, + "BLOCKCHAIN": { + "TITLE": "Statistikoj", + "BLOCKS_ISSUERS_DIVIDER": "Analizo de la kalkul-distribuo", + "BLOCKS_ISSUERS_HELP": "<b>{{issuerCount|formatInteger}} membroj</b> kalkulis <b>{{blockCount|formatInteger}} blokojn</b>", + "BLOCKS_ISSUERS_TITLE": "Nombro de blokoj kalkulitaj por membro", + "BLOCKS_ISSUERS_LABEL": "Nombro de blokoj", + "TX_DIVIDER": "Analizo de la spezoj", + "TX_AMOUNT_TITLE": "Kvanto de la spezoj", + "TX_AMOUNT_PUBKEY_TITLE": "Kvanto de spezoj kalkulitaj de {{issuer | formatPubkey}}", + "TX_AMOUNT_LABEL": "Kvanto interÅanÄita", + "TX_COUNT_TITLE": "Nombro de spezoj skribitaj", + "TX_COUNT_LABEL": "Nombro de spezoj", + "TX_AVG_BY_BLOCK": "Meza nombro de spezoj / bloko" + + }, + "CURRENCY": { + "MONETARY_MASS_TITLE": "Evoluo de la mona maso", + "MONETARY_MASS_LABEL": "Mona maso", + "MONETARY_MASS_SHARE_LABEL": "Mezumo por membro", + "UD_TITLE": "Evoluo de la universala dividendo", + "MEMBERS_COUNT_TITLE": "Evoluo de la nombro de membroj", + "MEMBERS_COUNT_LABEL": "Nombro de membroj" + }, + "PEER": { + "VIEW": { + "BLOCK_COUNT_LABEL": "Nombro de blokoj kalkulitaj", + "BLOCK_COUNT": "{{count}} blokoj", + "NO_BLOCK": "Neniu bloko" + } + }, + "DOC_STATS": { + "TITLE": "Statistikoj pri stokado", + "USER": { + "TITLE": "Nombro de dokumentoj ligitaj al konto", + "USER_PROFILE": "Uzanto-profiloj", + "USER_SETTINGS": "Parametroj konservitaj" + }, + "MESSAGE": { + "TITLE": "Nombro de dokumentoj ligitaj al komunikado", + "MESSAGE_INBOX": "MesaÄoj en ricevujo", + "MESSAGE_OUTBOX": "Senditaj mesaÄoj konservitaj", + "INVITATION_CERTIFICATION": "Invitoj atestotaj" + }, + "SOCIAL": { + "TITLE": "Nombro de paÄoj aÅ grupoj", + "PAGE_COMMENT": "Komentoj", + "PAGE_RECORD": "PaÄoj", + "GROUP_RECORD": "Grupoj" + }, + "OTHER": { + "TITLE": "Aliaj dokumentoj", + "HISTORY_DELETE": "Forigoj de dokumentoj" + } + }, + "SYNCHRO": { + "TITLE": "Statistikoj pri sinkronigoj", + "COUNT": { + "TITLE": "Kvanto sinkronigita", + "INSERTS": "Enmetoj", + "UPDATES": "Äœisdatigoj", + "DELETES": "Forigoj" + }, + "PEER": { + "TITLE": "Nodoj informpetitaj", + "ES_USER_API": "Nodoj pri datenoj de uzantoj", + "ES_SUBSCRIPTION_API": "Nodoj pri retaj servoj" + }, + "PERFORMANCE": { + "TITLE": "Efikecoj pri efektiviÄo", + "DURATION": "Tempo por efektiviÄo (ms)" + } + } + } +} diff --git a/assets/www/plugins/graph/i18n/locale-es-ES.json b/assets/www/plugins/graph/i18n/locale-es-ES.json index e59f9224663a7b6212be1b1d4df0a136b2e2345d..1bf03bf2f888671146f31151eb24f874bab59621 100644 --- a/assets/www/plugins/graph/i18n/locale-es-ES.json +++ b/assets/www/plugins/graph/i18n/locale-es-ES.json @@ -9,7 +9,13 @@ "LINEAR_SCALE" : "Escala lineal", "LOGARITHMIC_SCALE" : "Escala logarÃtmica", "BTN_SHOW_STATS": "Ver estadÃsticas", - "BTN_SHOW_DETAILED_STATS": "EstadÃsticas detalladas" + "BTN_SHOW_DETAILED_STATS": "EstadÃsticas detalladas", + "RANGE_DURATION_DIVIDER": "Unidad de paso:", + "RANGE_DURATION": { + "HOUR": "Grupo por <b>hora</b>", + "DAY": "Grupo por <b>dÃa</b>", + "MONTH": "Grupo por <b>mes</b>" + } }, "ACCOUNT": { "INPUT_CHART_TITLE": "Suma del flujo entrante, por el transmisor:", @@ -27,12 +33,7 @@ "TX_AMOUNT_LABEL": "Volumen negociado", "TX_COUNT_TITLE": "Número de transacciones escritas", "TX_COUNT_LABEL": "Número de transacciones", - "TX_AVG_BY_BLOCK": "Promedio por bloque", - "TX_RANGE_DURATION": { - "HOUR": "Grupo por <b>hora</b>", - "DAY": "Grupo por <b>dÃa</b>", - "MONTH": "Grupo por <b>mes</b>" - } + "TX_AVG_BY_BLOCK": "Promedio por bloque" }, "CURRENCY": { "MONETARY_MASS_TITLE": "Evolución de la masa monetaria", diff --git a/assets/www/plugins/graph/i18n/locale-fr-FR.json b/assets/www/plugins/graph/i18n/locale-fr-FR.json index 00de906b5308c2d9270229e938245e4f57d10ffe..83edacad00d19a1a4053b56d329e4b28d54aeb44 100644 --- a/assets/www/plugins/graph/i18n/locale-fr-FR.json +++ b/assets/www/plugins/graph/i18n/locale-fr-FR.json @@ -9,7 +9,13 @@ "LINEAR_SCALE" : "Echelle linéaire", "LOGARITHMIC_SCALE" : "Echelle logarithmique", "BTN_SHOW_STATS": "Voir les statistiques", - "BTN_SHOW_DETAILED_STATS": "Statistiques détaillées" + "BTN_SHOW_DETAILED_STATS": "Statistiques détaillées", + "RANGE_DURATION_DIVIDER": "Unité de temps :", + "RANGE_DURATION": { + "HOUR": "Heure", + "DAY": "Jour", + "MONTH": "Mois" + } }, "ACCOUNT": { "TITLE": "Statistiques", @@ -43,13 +49,8 @@ "TX_AMOUNT_LABEL": "Volume échangé", "TX_COUNT_TITLE": "Nombre de transactions écrites", "TX_COUNT_LABEL": "Nombre de transactions", - "TX_AVG_BY_BLOCK": "Nombre moyen de transactions / bloc", - "TX_RANGE_DURATION_DIVIDER": "Unité de temps :", - "TX_RANGE_DURATION": { - "HOUR": "Heure", - "DAY": "Jour", - "MONTH": "Mois" - } + "TX_AVG_BY_BLOCK": "Nombre moyen de transactions / bloc" + }, "CURRENCY": { "MONETARY_MASS_TITLE": "Evolution de la masse monétaire", @@ -67,15 +68,20 @@ } }, "DOC_STATS": { - "TITLE": "Statistiques de stockage", + "TITLE": "Statistiques de stockage (Cesium+)", "USER": { "TITLE": "Nombre de documents liés à un compte", "USER_PROFILE": "Profils utilisateur", - "USER_SETTINGS": "Paramètres sauvegardés", + "USER_SETTINGS": "Paramètres sauvegardés" + }, + "USER_DELTA": { + "TITLE": "Variation du nombre de documents liés à un compte", + "USER_PROFILE": "Profils utilisateur", + "USER_SETTINGS": "Paramètres sauvegardés" }, "MESSAGE": { - "TITLE": "Nombre de documents lié à la communication", - "MESSAGE_INBOX": "Messages en boite de réception", + "TITLE": "Nombre de documents liés à la communication", + "MESSAGE_INBOX": "Messages en boîte de réception", "MESSAGE_OUTBOX": "Messages envoyés sauvegardés", "INVITATION_CERTIFICATION": "Invitations à certifier" }, @@ -83,11 +89,11 @@ "TITLE": "Nombre de pages ou groupes", "PAGE_COMMENT": "Commentaires", "PAGE_RECORD": "Pages", - "GROUP_RECORD": "Groupes", + "GROUP_RECORD": "Groupes" }, "OTHER": { "TITLE": "Autres documents", - "HISTORY_DELETE": "Suppressions de documents", + "HISTORY_DELETE": "Suppressions de documents" } }, "SYNCHRO": { @@ -101,11 +107,11 @@ "PEER": { "TITLE": "Noeuds requêtés", "ES_USER_API": "Noeuds données utilisateurs", - "ES_SUBSCRIPTION_API": "Noeuds services en lignes" + "ES_SUBSCRIPTION_API": "Noeuds services en ligne" }, "PERFORMANCE": { - "TITLE": "Performances d'execution", - "DURATION": "Temps d'execution (ms)" + "TITLE": "Performances d'exécution", + "DURATION": "Temps d'exécution (ms)" } } } diff --git a/assets/www/plugins/graph/i18n/locale-it-IT.json b/assets/www/plugins/graph/i18n/locale-it-IT.json new file mode 100644 index 0000000000000000000000000000000000000000..69bd0e1a2973f16c3d703e564375d740b36e05cf --- /dev/null +++ b/assets/www/plugins/graph/i18n/locale-it-IT.json @@ -0,0 +1,112 @@ +{ + "NETWORK": { + "VIEW": { + "BTN_GRAPH": "Statistiche" + } + }, + "GRAPH": { + "COMMON": { + "LINEAR_SCALE" : "Scala lineare", + "LOGARITHMIC_SCALE" : "Scala logaritmica", + "BTN_SHOW_STATS": "Vedere le statistiche", + "BTN_SHOW_DETAILED_STATS": "Statistiche dettagliate", + "RANGE_DURATION_DIVIDER": "Unità di tempo :", + "RANGE_DURATION": { + "HOUR": "Ora", + "DAY": "Giorno", + "MONTH": "Mese" + } + }, + "ACCOUNT": { + "TITLE": "Statistiche", + "BTN_SHOW_STATS": "Visualizzare le statistiche del conto", + "BALANCE_DIVIDER": "Situazione del conto", + "BALANCE_TITLE": "Evoluzione del conto {{pubkey|formatPubkey}}", + "TX_RECEIVED_LABEL": "Incassi", + "TX_SENT_LABEL": "Spese", + "TX_ACCUMULATION_LABEL": "Bilancio delle transazioni", + "UD_LABEL": "DU", + "UD_ACCUMULATION_LABEL": "Bilancio dei DU", + "BALANCE_LABEL": "Saldo", + "WOT_DIVIDER": "Tela di fiducia", + "CERTIFICATION_TITLE": "Numero di certificazioni - {{pubkey|formatPubkey}}", + "RECEIVED_CERT_LABEL": "Totale ricevute", + "RECEIVED_CERT_DELTA_LABEL": "Variazione ricevute", + "GIVEN_CERT_LABEL": "Totale inviate", + "GIVEN_CERT_DELTA_LABEL": "Variazione inviate", + "INPUT_CHART_TITLE": "Somma dei flussi in entrata, par emittente :", + "OUTPUT_CHART_TITLE": "Somma dei flussi in uscita, per destinatario :" + }, + "BLOCKCHAIN": { + "TITLE": "Statistiche", + "BLOCKS_ISSUERS_DIVIDER": "Analisi della ripartizione del calcolo", + "BLOCKS_ISSUERS_HELP": "<b>{{issuerCount|formatInteger}} membri</b> hanno calcolato <b>{{blockCount|formatInteger}} blocchi</b>", + "BLOCKS_ISSUERS_TITLE": "Numero di blocchi calcolati a membro", + "BLOCKS_ISSUERS_LABEL": "Numero di blocchi", + "TX_DIVIDER": "Analisi delle transazioni", + "TX_AMOUNT_TITLE": "Volume delle transazioni", + "TX_AMOUNT_PUBKEY_TITLE": "Volume delle transazioni calcolato da {{issuer | formatPubkey}}", + "TX_AMOUNT_LABEL": "Volume scambiato", + "TX_COUNT_TITLE": "Numero di transazioni scritte", + "TX_COUNT_LABEL": "Numero di transazioni", + "TX_AVG_BY_BLOCK": "Numero medio di transazioni / blocco" + }, + "CURRENCY": { + "MONETARY_MASS_TITLE": "Evoluzione della massa monetaria", + "MONETARY_MASS_LABEL": "Massa monetaria", + "MONETARY_MASS_SHARE_LABEL": "Media a membro", + "UD_TITLE": "Evoluzione del Dividendo Universale", + "MEMBERS_COUNT_TITLE": "Evoluzione del numero di membri", + "MEMBERS_COUNT_LABEL": "Numero di membri" + }, + "PEER": { + "VIEW": { + "BLOCK_COUNT_LABEL": "Numero di blocchi calcolati", + "BLOCK_COUNT": "{{count}} blocchi", + "NO_BLOCK": "Nessun blocco" + } + }, + "DOC_STATS": { + "TITLE": "Statistiche di stoccaggio", + "USER": { + "TITLE": "Numero di documenti legati ad un conto", + "USER_PROFILE": "Profili dell'utente", + "USER_SETTINGS": "Impostazioni salvate", + }, + "MESSAGE": { + "TITLE": "Numero di documenti legati alla conversazione", + "MESSAGE_INBOX": "Messaggi in arrivo", + "MESSAGE_OUTBOX": "Messaggi inviati salvati", + "INVITATION_CERTIFICATION": "Invitazioni da certificare" + }, + "SOCIAL": { + "TITLE": "Numero di pagine o gruppi", + "PAGE_COMMENT": "Commenti", + "PAGE_RECORD": "Pagine", + "GROUP_RECORD": "Gruppi", + }, + "OTHER": { + "TITLE": "Altri documenti", + "HISTORY_DELETE": "Cronologia eliminazione documenti", + } + }, + "SYNCHRO": { + "TITLE": "Statistiche di sincronizzazioni", + "COUNT": { + "TITLE": "Volume sincronizzato", + "INSERTS": "Inserimenti", + "UPDATES": "Aggiornamenti", + "DELETES": "Eliminazioni" + }, + "PEER": { + "TITLE": "Nodi interrogati", + "ES_USER_API": "Nodi dati utenti", + "ES_SUBSCRIPTION_API": "Noeuds servizi online" + }, + "PERFORMANCE": { + "TITLE": "Prestazioni (performance) di esecuzione", + "DURATION": "Tempo di esecuzione (ms)" + } + } + } + } diff --git a/assets/www/plugins/graph/i18n/locale-nl-NL.json b/assets/www/plugins/graph/i18n/locale-nl-NL.json index 4370a96462864fa6c582507841802a1f6ba6ed2f..cec6d859788df5858c21fc9e498c6a8d18bb768a 100644 --- a/assets/www/plugins/graph/i18n/locale-nl-NL.json +++ b/assets/www/plugins/graph/i18n/locale-nl-NL.json @@ -9,11 +9,17 @@ "LINEAR_SCALE" : "Lineaire schaal", "LOGARITHMIC_SCALE" : "Logaritmische schaal", "BTN_SHOW_STATS": "Zie statistieken", - "BTN_SHOW_DETAILED_STATS": "Gedetailleerde statistieken" + "BTN_SHOW_DETAILED_STATS": "Gedetailleerde statistieken", + "RANGE_DURATION_DIVIDER": "Stap eenheid:", + "RANGE_DURATION": { + "HOUR": "Groep per <b>uur</b>", + "DAY": "Groep per <b>dag</b>", + "MONTH": "Groep per <b>maand</b>" + } }, "ACCOUNT": { - "INPUT_CHART_TITLE": "Som van de binnenkomende stroom, door de zender:", - "OUTPUT_CHART_TITLE": "Som van de uitstroom per bestemming:" + "INPUT_CHART_TITLE": "Som van de binnenkomende stroom, door de zender:", + "OUTPUT_CHART_TITLE": "Som van de uitstroom per bestemming:" }, "BLOCKCHAIN": { "TITLE": "Statistieken", @@ -27,12 +33,7 @@ "TX_AMOUNT_LABEL": "Verhandeld volume", "TX_COUNT_TITLE": "Aantal schriftelijke transacties", "TX_COUNT_LABEL": "Aantal transacties", - "TX_AVG_BY_BLOCK": "Gemiddeld aantal transacties / blok", - "TX_RANGE_DURATION": { - "HOUR": "Groep per <b>uur</b>", - "DAY": "Groep per <b>dag</b>", - "MONTH": "Groep per <b>maand</b>" - } + "TX_AVG_BY_BLOCK": "Gemiddeld aantal transacties / blok" }, "CURRENCY": { "MONETARY_MASS_TITLE": "Evolutie van de monetaire massa", diff --git a/assets/www/plugins/graph/js/controllers/account-controllers.js b/assets/www/plugins/graph/js/controllers/account-controllers.js index ab9d2076dc6a696083df0cb1f6b8ad547df8ead4..5f5b3fa9b008a414457c3299a92dca7457c08ccb 100644 --- a/assets/www/plugins/graph/js/controllers/account-controllers.js +++ b/assets/www/plugins/graph/js/controllers/account-controllers.js @@ -17,6 +17,15 @@ angular.module('cesium.graph.account.controllers', ['chart.js', 'cesium.graph.se } }) + .extendState('app.view_wallet_tx_by_id', { + points: { + 'buttons': { + templateUrl: "plugins/graph/templates/account/view_wallet_tx_extend.html", + controller: 'GpExtendCtrl' + } + } + }) + .extendState('app.wot_identity', { points: { 'buttons': { @@ -49,6 +58,18 @@ angular.module('cesium.graph.account.controllers', ['chart.js', 'cesium.graph.se } }) + .state('app.view_wallet_stats_by_id', { + url: "/wallets/:id/stats?t&stepUnit&hide&scale", + views: { + 'menuContent': { + templateUrl: "plugins/graph/templates/account/view_stats.html" + } + }, + data: { + auth: true + } + }) + .state('app.wot_identity_stats', { url: "/wot/:pubkey/stats?t&stepUnit&hide&scale", views: { @@ -136,7 +157,7 @@ function GpAccountBalanceController($scope, $controller, $q, $state, $filter, $t var withUD = true; - return csWot.load($scope.formData.pubkey) + return csWot.load($scope.formData.pubkey, null/*uid*/, {cache: true}) .then(function(identity) { $scope.identity = identity; withUD = $scope.identity.isMember || $scope.identity.wasMember; @@ -157,7 +178,7 @@ function GpAccountBalanceController($scope, $controller, $q, $state, $filter, $t 'COMMON.DATE_MONTH_YEAR_PATTERN']), // get data - gpData.blockchain.movement($scope.formData.currency, angular.copy($scope.formData)) + gpData.blockchain.movement($scope.formData.currency, angular.copy($scope.formData, {withUD: withUD})) ]); }) .then(function(result) { @@ -168,8 +189,7 @@ function GpAccountBalanceController($scope, $controller, $q, $state, $filter, $t if (!result || !result.times) return; // no data $scope.times = result.times; - var formatInteger = $filter('formatInteger'); - var formatAmount = $filter('formatDecimal'); + var formatDecimal = $filter('formatDecimal'); $scope.currencySymbol = $filter('currencySymbolNoHtml')($scope.formData.currency, $scope.formData.useRelative); // Data @@ -230,7 +250,7 @@ function GpAccountBalanceController($scope, $controller, $q, $state, $filter, $t return data.datasets[tooltipItems.datasetIndex].label + ': ' + (!tooltipItems.yLabel ? '0' : - (formatAmount(tooltipItems.yLabel) + ' ' + $scope.currencySymbol)); + (formatDecimal(tooltipItems.yLabel) + ' ' + $scope.currencySymbol)); } } } @@ -323,8 +343,6 @@ function GpAccountSumTxController($scope, $controller, $filter, $state, csTx, gp $scope.load = function(e, state) { if (!$scope.pubkey) return; - var formatDecimal = $filter('formatDecimal'); - // Load account TX data return csTx.load($scope.pubkey, -1) .then(function(result) { @@ -354,12 +372,17 @@ function GpAccountSumTxController($scope, $controller, $filter, $state, csTx, gp pubkey: tx.pubkey, sum: 0 }; - sumByPubkeys[tx.pubkey].sum += Math.abs(tx.amount/100); + sumByPubkeys[tx.pubkey].sum += Math.abs(tx.amount); }); // Get values (from the map), then sort (desc) on sum var sumItems = _.sortBy(_.values(sumByPubkeys), 'sum').reverse(); + // Divide total amount by 100 + _.each(sumItems, function(item) { + item.sum = item.sum / 100; + }); + // Return arrays expected by angular-chart return { data: _.pluck(sumItems, 'sum'), diff --git a/assets/www/plugins/graph/js/controllers/common-controllers.js b/assets/www/plugins/graph/js/controllers/common-controllers.js index 1f79881825fa04ffe562d5921a9043b6031cfbc7..79c2969569628d5a4479bc51d36a7be0902881f1 100644 --- a/assets/www/plugins/graph/js/controllers/common-controllers.js +++ b/assets/www/plugins/graph/js/controllers/common-controllers.js @@ -4,7 +4,7 @@ angular.module('cesium.graph.common.controllers', ['cesium.services']) .controller('GpCurrencyAbstractCtrl', GpCurrencyAbstractController) ; -function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHistory, $state, csSettings, csCurrency, esHttp) { +function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHistory, $state, csSettings, csCurrency, esHttp, UIUtils) { 'ngInject'; $scope.loading = true; @@ -14,7 +14,8 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist rangeDuration: 'day', firstBlockTime: 0, scale: 'linear', - hide: [] + hide: [], + beginAtZero: true }; $scope.formData.useRelative = false; /*angular.isDefined($scope.formData.useRelative) ? $scope.formData.useRelative : csSettings.data.useRelative;*/ @@ -71,7 +72,7 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist if (!$scope.formData.firstBlockTime){ console.warn('[graph] currency.firstBlockTime not loaded ! Should have been loaded by currrency service!'); } - $scope.formData.currencyAge = _truncDate(esHttp.date.now()) - $scope.formData.firstBlockTime; + $scope.formData.currencyAge = _truncDate(moment().utc().unix()) - $scope.formData.firstBlockTime; return $scope.enter(e, state); }); @@ -92,6 +93,8 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist $scope.$on('$ionicParentView.enter', $scope.enter); $scope.updateLocation = function() { + if (!$scope.stateName) return; + $ionicHistory.nextViewOptions({ disableAnimate: true, disableBack: true, @@ -150,7 +153,7 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist yAxe.type = scale; yAxe.ticks = yAxe.ticks || {}; if (scale == 'linear') { - yAxe.ticks.beginAtZero = true; + yAxe.ticks.beginAtZero = angular.isDefined($scope.formData.beginAtZero) ? $scope.formData.beginAtZero : true; delete yAxe.ticks.min; yAxe.ticks.callback = function(value) { return format(value); @@ -312,22 +315,21 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist /* -- Popover -- */ $scope.showActionsPopover = function(event) { - $scope.hideActionsPopover(); - $ionicPopover.fromTemplateUrl('plugins/graph/templates/common/popover_range_actions.html', { - scope: $scope - }).then(function(popover) { - $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); + UIUtils.popover.show(event, { + templateUrl: 'plugins/graph/templates/common/popover_range_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; + } diff --git a/assets/www/plugins/graph/js/controllers/currency-controllers.js b/assets/www/plugins/graph/js/controllers/currency-controllers.js index 992353e9cc1ff8d239d86b7a923a5d9de1cba4c2..caaaadff7eeed90683e59b7c178c84350eeb370d 100644 --- a/assets/www/plugins/graph/js/controllers/currency-controllers.js +++ b/assets/www/plugins/graph/js/controllers/currency-controllers.js @@ -9,8 +9,7 @@ angular.module('cesium.graph.currency.controllers', ['chart.js', 'cesium.graph.s url: "/parameters/stats", views: { 'tab-parameters': { - templateUrl: "plugins/graph/templates/currency/tabs/tab_parameters_stats.html", - controller: 'GpCurrencyMonetaryMassCtrl' + templateUrl: "plugins/graph/templates/currency/tabs/tab_parameters_stats.html" } } }) @@ -101,7 +100,7 @@ function GpCurrencyViewExtendController($scope, PluginService, UIUtils, esSettin }); } -function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $translate, $ionicPopover, gpColor, gpData, $filter, csSettings) { +function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $translate, UIUtils, gpColor, gpData, $filter, csSettings) { 'ngInject'; // Initialize the super class and extend it. @@ -151,10 +150,10 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran var blocksPeriod = result.times[result.times.length-1] - result.times[0]; var formatDate; if (blocksPeriod < 31557600/* less than 1 year */) { - formatDate = $filter('formatDateShort'); + formatDate = $filter('medianDateShort'); } else { - formatDate = $filter('formatDateMonth'); + formatDate = $filter('formatDateMonth'); //see #683 } var formatAmount = $filter('formatDecimal'); @@ -164,31 +163,31 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran var data = []; if($scope.formData.useRelative) { - // Mass + // M/N data.push( result.blocks.reduce(function(res, block) { - return res.concat(truncAmount(block.monetaryMass / block.dividend)); + return res.concat(truncAmount(block.monetaryMass / block.dividend / block.membersCount)); }, [])); - // M/N + // Mass data.push( result.blocks.reduce(function(res, block) { - return res.concat(truncAmount(block.monetaryMass / block.dividend / block.membersCount)); + return res.concat(truncAmount(block.monetaryMass / block.dividend)); }, [])); } // Data: quantitative else { - // Mass + // M/N data.push( result.blocks.reduce(function(res, block) { - return res.concat(block.monetaryMass / 100); + return res.concat(truncAmount(block.monetaryMass / block.membersCount / 100)); }, [])); - // M/N + // Mass data.push( result.blocks.reduce(function(res, block) { - return res.concat(truncAmount(block.monetaryMass / block.membersCount / 100)); + return res.concat(block.monetaryMass / 100); }, [])); } $scope.data = data; @@ -216,16 +215,17 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran scales: { yAxes: [ { - id: 'y-axis-mass' + id: 'y-axis-mn' }, { - id: 'y-axis-mn', + id: 'y-axis-mass', display: $scope.displayShareAxis, position: 'right', gridLines: { drawOnChartArea: false } - } + }, + ] }, tooltips: { @@ -243,18 +243,18 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran $scope.datasetOverride = [ { - yAxisID: 'y-axis-mass', + yAxisID: 'y-axis-mn', type: 'line', - label: translations['GRAPH.CURRENCY.MONETARY_MASS_LABEL'], + label: translations['GRAPH.CURRENCY.MONETARY_MASS_SHARE_LABEL'], borderWidth: 2, pointRadius: 0, pointHitRadius: 4, pointHoverRadius: 3 }, { - yAxisID: 'y-axis-mn', + yAxisID: 'y-axis-mass', type: 'line', - label: translations['GRAPH.CURRENCY.MONETARY_MASS_SHARE_LABEL'], + label: translations['GRAPH.CURRENCY.MONETARY_MASS_LABEL'], fill: false, showLine: true, borderColor: gpColor.rgba.energized(), @@ -288,32 +288,38 @@ function GpCurrencyMonetaryMassController($scope, $controller, $q, $state, $tran /* -- Popover -- */ $scope.showActionsPopover = function(event) { - $scope.hideActionsPopover(); - $ionicPopover.fromTemplateUrl('plugins/graph/templates/currency/popover_monetary_mass_actions.html', { - scope: $scope - }).then(function(popover) { - $scope.actionsPopover = popover; - //Cleanup the popover when we're done with it! - $scope.$on('$destroy', function() { - $scope.actionsPopover.remove(); - }); - $scope.actionsPopover.show(event); + UIUtils.popover.show(event, { + templateUrl: 'plugins/graph/templates/currency/popover_monetary_mass_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } }); }; $scope.hideActionsPopover = function() { if ($scope.actionsPopover) { $scope.actionsPopover.hide(); + $scope.actionsPopover = null; } }; + } -function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gpData, $filter) { +function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gpData, $filter, UIUtils) { 'ngInject'; + + $scope.formData = { + scale: 'linear', + beginAtZero: false + }; + // Initialize the super class and extend it. angular.extend(this, $controller('GpCurrencyMonetaryMassCtrl', {$scope: $scope})); + $scope.load = function(from, size) { from = from || 0; size = size || 10000; @@ -337,7 +343,7 @@ function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gp var blocksPeriod = result.times[result.times.length-1] - result.times[0]; var dateFilter; if (blocksPeriod < 31557600/* less than 1 year */) { - dateFilter = $filter('formatDateShort'); + dateFilter = $filter('medianDateShort'); } else { dateFilter = $filter('formatDateMonth'); @@ -376,7 +382,7 @@ function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gp { id: 'y-axis-ud', ticks: { - beginAtZero: false + beginAtZero: $scope.formData.beginAtZero } } ] @@ -413,6 +419,26 @@ function GpCurrencyDUController($scope, $q, $controller, $translate, gpColor, gp }); }; + + /* -- Popover -- */ + $scope.showActionsPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'plugins/graph/templates/currency/popover_monetary_mass_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } + }); + }; + + $scope.hideActionsPopover = function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + $scope.actionsPopover = null; + } + }; + } @@ -445,7 +471,7 @@ function GpCurrencyMembersCountController($scope, $controller, $q, $state, $tran var blocksPeriod = result.times[result.blocks.length-1] - result.times[0]; var dateFilter; if (blocksPeriod < 31557600/* less than 1 year*/) { - dateFilter = $filter('formatDateShort'); + dateFilter = $filter('medianDateShort'); } else { dateFilter = $filter('formatDateMonth'); @@ -510,4 +536,6 @@ function GpCurrencyMembersCountController($scope, $controller, $q, $state, $tran q: '(_exists_:joiners OR _exists_:leavers OR _exists_:revoked OR _exists_:excluded) AND medianTime:>{0} AND medianTime:<={1}'.format(from, to) }); }; + + } diff --git a/assets/www/plugins/graph/js/controllers/docstats-controllers.js b/assets/www/plugins/graph/js/controllers/docstats-controllers.js index c2dd913634ba99a0ad27cf00b366deac5eb0d313..2052e4b3734686ee9a9ba608a283bf1da12afbcc 100644 --- a/assets/www/plugins/graph/js/controllers/docstats-controllers.js +++ b/assets/www/plugins/graph/js/controllers/docstats-controllers.js @@ -31,6 +31,7 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol // Initialize the super class and extend it. angular.extend(this, $controller('GpCurrencyAbstractCtrl', {$scope: $scope})); + $scope.displayRightAxis = true; $scope.hiddenDatasets = []; $scope.chartIdPrefix = 'docstats-chart-'; @@ -44,7 +45,7 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol { key: 'user_profile', label: 'GRAPH.DOC_STATS.USER.USER_PROFILE', - color: gpColor.rgba.royal(), + color: gpColor.rgba.royal(0.7), pointHoverBackgroundColor: gpColor.rgba.royal(), clickState: { name: 'app.document_search', @@ -64,6 +65,30 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol ] }, + // User delta + { + id: 'user_delta', + title: 'GRAPH.DOC_STATS.USER_DELTA.TITLE', + series: [ + { + key: 'user_profile_delta', + label: 'GRAPH.DOC_STATS.USER_DELTA.USER_PROFILE', + type: 'line', + yAxisID: 'y-axis-delta', + color: gpColor.rgba.royal(), + pointHoverBackgroundColor: gpColor.rgba.royal() + }, + { + key: 'user_settings_delta', + label: 'GRAPH.DOC_STATS.USER_DELTA.USER_SETTINGS', + type: 'line', + yAxisID: 'y-axis-delta', + color: gpColor.rgba.gray(0.5), + pointHoverBackgroundColor: gpColor.rgba.gray() + } + ] + }, + // Message & Co. { id: 'message', @@ -177,8 +202,21 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol }], yAxes: [ { - stacked: true, - id: 'y-axis' + id: 'y-axis', + stacked: true + }, + { + id: 'y-axis-delta', + stacked: false + }, + { + id: 'y-axis-delta-right', + stacked: false, + display: $scope.displayRightAxis, + position: 'right', + gridLines: { + drawOnChartArea: false + } } ] }, @@ -231,9 +269,9 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol // Labels var labelPattern = datePatterns[$scope.formData.rangeDuration]; - $scope.labels = result.times.reduce(function(res, time) { - return res.concat(moment.unix(time).local().format(labelPattern)); - }, []); + $scope.labels = _.map(result.times, function(time) { + return moment.unix(time).local().format(labelPattern); + }); // Update range options with received values $scope.updateRange(result.times[0], result.times[result.times.length-1], updateTimePct); @@ -243,25 +281,36 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol // For each chart _.forEach($scope.charts, function(chart){ - // Data - chart.data = []; - _.forEach(chart.series, function(serie){ - chart.data.push(result[serie.key]||[]); + // Prepare chart data + var usedYAxisIDs = {}; + chart.data = _.map(chart.series, function(serie) { + usedYAxisIDs[serie.yAxisID||'y-axis'] = true; + // If 'delta' serie, then compute delta from the source serie + if (serie.key.endsWith('_delta')) { + var key = serie.key.substring(0, serie.key.length - '_delta'.length); + return getDeltaFromValueArray(result[key]) || []; + } + return result[serie.key]||[]; }); // Options (with title) chart.options = angular.copy($scope.defaultChartOptions); chart.options.title.text = translations[chart.title]; + // Remove unused yAxis + chart.options.scales.yAxes = chart.options.scales.yAxes.reduce(function(res, yAxe){ + return usedYAxisIDs[yAxe.id] ? res.concat(yAxe) : res; + }, []); + // Series datasets - chart.datasetOverride = chart.series.reduce(function(res, serie) { - return res.concat({ - yAxisID: 'y-axis', + chart.datasetOverride = _.map(chart.series, function(serie) { + return { + yAxisID: serie.yAxisID || 'y-axis', type: serie.type || 'line', label: translations[serie.label], - fill: true, + fill: serie.type !== 'line', borderWidth: 2, - pointRadius: 0, + pointRadius: serie.type !== 'line' ? 0 : 2, pointHitRadius: 4, pointHoverRadius: 3, borderColor: serie.color, @@ -270,8 +319,8 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol pointBorderColor: serie.color, pointHoverBackgroundColor: serie.pointHoverBackgroundColor||serie.color, pointHoverBorderColor: serie.pointHoverBorderColor||gpColor.rgba.white() - }); - }, []); + }; + }); }); }); @@ -300,5 +349,14 @@ function GpDocStatsController($scope, $state, $controller, $q, $translate, gpCol } }; + function getDeltaFromValueArray(values) { + if (!values) return undefined; + var previousValue; + return _.map(values, function(value) { + var newValue = (value !== undefined) && (value - (previousValue || value)) || undefined; + previousValue = value; + return newValue; + }); + } } diff --git a/assets/www/plugins/graph/templates/account/graph_sum_tx.html b/assets/www/plugins/graph/templates/account/graph_sum_tx.html index bfecae086b242b90244f0cbe253262a15f1f4180..ca11e96571bbd5ffae4125efa736f29734dffa11 100644 --- a/assets/www/plugins/graph/templates/account/graph_sum_tx.html +++ b/assets/www/plugins/graph/templates/account/graph_sum_tx.html @@ -4,7 +4,7 @@ <div class="col text-center"> - <!-- [NEW] TX input chart --> + <!-- TX input chart --> <p class="gray padding text-wrap" ng-if="inputChart.data.length" translate>GRAPH.ACCOUNT.INPUT_CHART_TITLE</p> @@ -21,7 +21,7 @@ <div class="col text-center"> - <!-- [NEW] TX input chart --> + <!-- TX output chart --> <p class="gray padding text-wrap" ng-if="outputChart.data.length" translate>GRAPH.ACCOUNT.OUTPUT_CHART_TITLE</p> diff --git a/assets/www/plugins/graph/templates/account/view_stats.html b/assets/www/plugins/graph/templates/account/view_stats.html index ece16b12769c8040173e7681dbce9b1524095e4c..cac7dec8b067bab9c9a83eab42abd6bd9820d77d 100644 --- a/assets/www/plugins/graph/templates/account/view_stats.html +++ b/assets/www/plugins/graph/templates/account/view_stats.html @@ -35,16 +35,16 @@ ng-controller="GpAccountSumTxCtrl"> </div> - <!-- - - - - WOT - - - - --> - <!--<div class="item item-divider" translate> - GRAPH.ACCOUNT.WOT_DIVIDER - </div> - - <div class="item no-padding-xs" - ng-include="'plugins/graph/templates/account/graph_certifications.html'" - ng-controller="GpAccountCertificationCtrl" - ng-init="setSize(350, 1000)"> - </div>--> + <!-- - - - - WOT - - - - + <div class="item item-divider" translate> + GRAPH.ACCOUNT.WOT_DIVIDER + </div> + + <div class="item no-padding-xs" + ng-include="'plugins/graph/templates/account/graph_certifications.html'" + ng-controller="GpAccountCertificationCtrl" + ng-init="setSize(350, 1000)"> + </div>--> </ion-content> diff --git a/assets/www/plugins/graph/templates/blockchain/view_stats.html b/assets/www/plugins/graph/templates/blockchain/view_stats.html index 4c66ade43efd09eabe7f1916a8ae523c085f4ddb..4ec97c1e62ba4ce698557b0b6c14c19d8707431e 100644 --- a/assets/www/plugins/graph/templates/blockchain/view_stats.html +++ b/assets/www/plugins/graph/templates/blockchain/view_stats.html @@ -24,7 +24,7 @@ <ion-spinner ng-if="loadingRange" class="ion-spinner-small" icon="android"></ion-spinner> </div> - <div class="item no-padding-xs" + <div class="item no-padding-xs no-padding-sm" ng-if="!loading" ng-include="'plugins/graph/templates/blockchain/graph_tx_count.html'" ng-init="setSize(350, 1000)"> @@ -37,7 +37,7 @@ <div class="item item-divider" ng-if="!loading" translate>GRAPH.BLOCKCHAIN.BLOCKS_ISSUERS_DIVIDER</div> - <div class="item no-padding-xs" + <div class="item no-padding-xs no-padding-sm" ng-if="!loading" ng-include="'plugins/graph/templates/blockchain/graph_block_issuers.html'" ng-init="setSize(300, 750)"> diff --git a/assets/www/plugins/graph/templates/common/popover_range_actions.html b/assets/www/plugins/graph/templates/common/popover_range_actions.html index 8342186d4d23b7425e5c7d365a86d4a7a480840f..cf8893b84273e2c61fda7be7293a90257aad453d 100644 --- a/assets/www/plugins/graph/templates/common/popover_range_actions.html +++ b/assets/www/plugins/graph/templates/common/popover_range_actions.html @@ -14,28 +14,28 @@ <!-- duration divider --> <div class="item item-divider"> - {{'GRAPH.BLOCKCHAIN.TX_RANGE_DURATION_DIVIDER'|translate}} + {{'GRAPH.COMMON.RANGE_DURATION_DIVIDER'|translate}} </div> <!-- duration: hour --> <a class="item item-icon-left ink" ng-click="setRangeDuration('hour')"> <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration=='hour'"></i> - <span ng-bind-html="'GRAPH.BLOCKCHAIN.TX_RANGE_DURATION.HOUR' | translate"></span> + <span ng-bind-html="'GRAPH.COMMON.RANGE_DURATION.HOUR' | translate"></span> </a> <!-- duration: day --> <a class="item item-icon-left ink" ng-click="setRangeDuration('day')"> <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration=='day'"></i> - <span ng-bind-html="'GRAPH.BLOCKCHAIN.TX_RANGE_DURATION.DAY' | translate"></span> + <span ng-bind-html="'GRAPH.COMMON.RANGE_DURATION.DAY' | translate"></span> </a> <!-- duration: month --> <a class="item item-icon-left ink" ng-click="setRangeDuration('month')"> <i class="icon ion-ios-checkmark-empty" ng-show="formData.rangeDuration=='month'"></i> - <span ng-bind-html="'GRAPH.BLOCKCHAIN.TX_RANGE_DURATION.MONTH' | translate"></span> + <span ng-bind-html="'GRAPH.COMMON.RANGE_DURATION.MONTH' | translate"></span> </a> </div> diff --git a/assets/www/plugins/graph/templates/currency/graph_du.html b/assets/www/plugins/graph/templates/currency/graph_du.html index 2b34a02ac999b5c537c9ce34b5e15ea3bd8dd750..a64e45467eb90e2bdc36f5474b50099ef86ffb07 100644 --- a/assets/www/plugins/graph/templates/currency/graph_du.html +++ b/assets/www/plugins/graph/templates/currency/graph_du.html @@ -3,7 +3,7 @@ <div class="button-bar-inline " style="top: 33px; margin-top:-33px; position: relative;"> <button - class="button button-stable button-clear no-padding-xs pull-right" + class="button button-stable button-clear no-padding-xs no-padding-sm pull-right" ng-click="showActionsPopover($event)"> <i class="icon ion-navicon-round"></i> </button> diff --git a/assets/www/plugins/graph/templates/currency/tabs/tab_parameters_stats.html b/assets/www/plugins/graph/templates/currency/tabs/tab_parameters_stats.html index 2be6dcc1a12a4269aec105d0b0f7cc9179ad4506..80465c1d432b136bd2f0ef2571e185a5ab42121a 100644 --- a/assets/www/plugins/graph/templates/currency/tabs/tab_parameters_stats.html +++ b/assets/www/plugins/graph/templates/currency/tabs/tab_parameters_stats.html @@ -1,21 +1,27 @@ <ion-view> <ion-content> - <div class="center padding" ng-if="loading"> - <ion-spinner icon="android"></ion-spinner> - </div> + <div class="list no-padding-xs no-padding-sm"> + + <ng-container ng-controller="GpCurrencyMonetaryMassCtrl"> + + <div class="center padding" ng-if="loading"> + <ion-spinner icon="android"></ion-spinner> + </div> - <div class="row responsive-sm"> - <div class="col" - ng-include="'plugins/graph/templates/currency/graph_monetary_mass.html'" - ng-init="setSize(500,700,true)"> - </div> + <!-- Monetary mass --> + <div class="item" + ng-include="'plugins/graph/templates/currency/graph_monetary_mass.html'" + ng-init="setSize(500,700,true)"> + </div> + </ng-container> <!-- DU --> - <div class="col" - ng-include="'plugins/graph/templates/currency/graph_du.html'" - ng-controller="GpCurrencyDUCtrl" - ng-init="setSize(500,700,true)"> - </div> + <ng-container ng-controller="GpCurrencyDUCtrl"> + <div class="item" + ng-include="'plugins/graph/templates/currency/graph_du.html'" + ng-init="setSize(500,700,true)"> + </div> + </ng-container> </div> </ion-content> </ion-view> diff --git a/assets/www/plugins/graph/templates/currency/view_currency_extend.html b/assets/www/plugins/graph/templates/currency/view_currency_extend.html index dc99c2799d0b76a554c2d129b0a3cc6747c73762..088160024482bf91835ad178b557107e8d044f56 100644 --- a/assets/www/plugins/graph/templates/currency/view_currency_extend.html +++ b/assets/www/plugins/graph/templates/currency/view_currency_extend.html @@ -3,7 +3,7 @@ <ng-if ng-if="enable && extensionPoint === 'parameters-actual'" > <ng-if ng-if="!smallscreen"> - <div class="item padding-left padding-right no-padding-xs" + <div class="item padding-left padding-right no-padding-xs no-padding-sm" ng-include="'plugins/graph/templates/currency/graph_monetary_mass.html'" ng-controller="GpCurrencyMonetaryMassCtrl" ng-init="displayShareAxis=false;"> @@ -29,7 +29,7 @@ <ng-if ng-if="enable && extensionPoint === 'wot-actual'" > <ng-if ng-if="!smallscreen"> - <div class="item padding-left padding-right no-padding-xs" + <div class="item padding-left padding-right no-padding-xs no-padding-sm" ng-include="'plugins/graph/templates/currency/graph_members_count.html'" ng-controller="GpCurrencyMembersCountCtrl"> </div> @@ -53,7 +53,7 @@ <!-- section Wot --> <ng-if ng-if="enable && extensionPoint === 'network-actual'" > - <div class="item padding-left padding-right no-padding-xs" + <div class="item padding-left padding-right no-padding-xs no-padding-sm" ng-if="!smallscreen" ng-include="'plugins/graph/templates/blockchain/graph_block_issuers.html'" ng-controller="GpBlockchainIssuersCtrl"> diff --git a/assets/www/plugins/graph/templates/currency/view_parameters_stats.html b/assets/www/plugins/graph/templates/currency/view_parameters_stats.html deleted file mode 100644 index 9108dfbf6bb5e75aae03723f554c3327843bc8ba..0000000000000000000000000000000000000000 --- a/assets/www/plugins/graph/templates/currency/view_parameters_stats.html +++ /dev/null @@ -1,23 +0,0 @@ -<ion-view left-buttons="leftButtons" - cache-view="false"> - - <ion-content scroll="true" > - - <div class="center padding" ng-if="loading"> - <ion-spinner icon="android"></ion-spinner> - </div> - - <div class="list no-padding-xs"> - <div class="item no-padding-xs" - ng-include="'plugins/graph/templates/currency/graph_monetary_mass.html'"> - </div> - - <!-- DU --> - <div class="item no-padding-xs" - ng-include="'plugins/graph/templates/currency/graph_du.html'" - ng-controller="GpCurrencyDUCtrl" - ng-init="setSize(undefined, undefined)"> - </div> - </div> - </ion-content> -</ion-view> diff --git a/assets/www/plugins/graph/templates/docstats/graph.html b/assets/www/plugins/graph/templates/docstats/graph.html index 8cdde39e4fc6d458847ef016fa93349a3fbfe1a8..7a9b7939f742949aae250f2096fa1bfc880812f8 100644 --- a/assets/www/plugins/graph/templates/docstats/graph.html +++ b/assets/www/plugins/graph/templates/docstats/graph.html @@ -3,7 +3,7 @@ <div class="button-bar-inline " style="top: 33px; margin-top:-33px; position: relative;"> <button - class="button button-stable button-clear no-padding-xs pull-right" + class="button button-stable button-clear no-padding-xs no-padding-sm pull-right" ng-click="showActionsPopover($event)"> <i class="icon ion-navicon-round"></i> </button> diff --git a/assets/www/plugins/graph/templates/docstats/view_stats.html b/assets/www/plugins/graph/templates/docstats/view_stats.html index dfea0e947cae1f356e5ca05b660a1c8e5fd112a3..88fc2cffd84b48596257842d7ae80ae415349ff5 100644 --- a/assets/www/plugins/graph/templates/docstats/view_stats.html +++ b/assets/www/plugins/graph/templates/docstats/view_stats.html @@ -13,7 +13,7 @@ <ion-spinner icon="android"></ion-spinner> </div> - <div class="item no-padding-xs" ng-if="!loading" + <div class="item no-padding-xs no-padding-sm" ng-if="!loading" ng-repeat="chart in charts" ng-include="'plugins/graph/templates/docstats/graph.html'" ng-init="setSize(250, 1000)"> diff --git a/assets/www/plugins/map/i18n/locale-en-GB.json b/assets/www/plugins/map/i18n/locale-en-GB.json index 6f7d56b2d1918ec6874a63a96847fc2d3bb338cb..9c7381ed937f81f12e59d7247d39b6b963d101e3 100644 --- a/assets/www/plugins/map/i18n/locale-en-GB.json +++ b/assets/www/plugins/map/i18n/locale-en-GB.json @@ -20,7 +20,7 @@ }, "WOT": { "LOOKUP": { - "BTN_MAP": "Members map", + "BTN_MAP": "Map", "BTN_MAP_HELP": "Open members map" }, "VIEW": { diff --git a/assets/www/plugins/map/i18n/locale-en.json b/assets/www/plugins/map/i18n/locale-en.json index 6f7d56b2d1918ec6874a63a96847fc2d3bb338cb..9c7381ed937f81f12e59d7247d39b6b963d101e3 100644 --- a/assets/www/plugins/map/i18n/locale-en.json +++ b/assets/www/plugins/map/i18n/locale-en.json @@ -20,7 +20,7 @@ }, "WOT": { "LOOKUP": { - "BTN_MAP": "Members map", + "BTN_MAP": "Map", "BTN_MAP_HELP": "Open members map" }, "VIEW": { diff --git a/assets/www/plugins/map/i18n/locale-eo-EO.json b/assets/www/plugins/map/i18n/locale-eo-EO.json new file mode 100644 index 0000000000000000000000000000000000000000..2cc86780de3450f5df72e68b3343fae1d4564987 --- /dev/null +++ b/assets/www/plugins/map/i18n/locale-eo-EO.json @@ -0,0 +1,76 @@ +{ + "MAP": { + "COMMON": { + "SEARCH_DOTS": "Traserĉi...", + "BTN_LOCALIZE_ME": "Lokalizi min" + }, + "NETWORK": { + "LOOKUP": { + "BTN_MAP": "Mapo", + "BTN_MAP_HELP": "Malfermi la mapon pri nodoj" + }, + "VIEW": { + "TITLE": "Mapo pri nodoj", + "LAYER": { + "MEMBER": "Membro-nodoj", + "MIRROR": "Spegul-nodoj", + "OFFLINE": "Nekonektitaj nodoj" + } + } + }, + "WOT": { + "LOOKUP": { + "BTN_MAP": "Mapo", + "BTN_MAP_HELP": "Malfermi la mapon pri membroj" + }, + "VIEW": { + "TITLE": "Mapo pri membroj", + "LAYER": { + "MEMBER": "<i class=\"icon ion-person positive\"></i> Membroj", + "PENDING": "<i class=\"icon ion-clock energized\"></i> AliÄoj atendantaj", + "WALLET": "<i class=\"icon ion-card gray\"></i> Simplaj monujoj" + } + }, + "ERROR": { + "LOAD_POSITION_FAILED": "Neeblas ricevi la lokojn afiÅotajn." + } + }, + "REGISTRY": { + "LOOKUP": { + "BTN_MAP": "Mapo", + "BTN_MAP_HELP": "Malfermi la mapon pri paÄoj" + }, + "VIEW": { + "TITLE": "Mapo pri paÄoj", + "LAYER": { + "SHOP": "<i class=\"icon ion-page-shop positive\"></i> Lokaj komercoj", + "COMPANY": "<i class=\"icon ion-page-company positive\"></i> Entreprenoj", + "ASSOCIATION": "<i class=\"icon ion-page-association energized\"></i> Asocioj", + "INSTITUTION": "<i class=\"icon ion-page-institution gray\"></i> Institucioj" + } + } + }, + "PROFILE": { + "MARKER_HELP": "<b>Åœovu-demetu</b> tiun ĉi markilon por <b>aktualigi<br/> vian lokon</b> sur la mapo, aÅ uzu la serĉo-butonon<br/>super la mapo." + }, + "ERROR": { + "LOCALIZE_ME_FAILED": "Neeblas ricevi vian nunan lokon" + }, + "SETTINGS": { + "MAP_DIVIDER": "Mapoj", + "ENABLE_GOOGLE_API": "Aktivigi la Google-API-servojn?", + "ENABLE_GOOGLE_API_HELP": "Ebligas afiÅi sur la <b>mapo pri membroj</b> kontojn kun adreso sed sen iu GPS-lokalizo.", + "GOOGLE_API_KEY": "Google-API-Ålosilo", + "BTN_GOOGLE_API": "Ekhavi Ålosilon", + "BTN_GOOGLE_API_WARNING": "Necesigas havi Google-konton", + "GOOGLE_API_KEY_PLACEHOLDER": "Ekzemple: AIzaqyAgszvWm0tM81x1sMK_ipDHBI7EowLqR7I" + }, + "HELP": { + "TIP": { + "WOT": "Tiu ĉi mapo afiÅas <b>la profilojn kun loko</b>, ĉu ili rilatas al membro-kontoj aÅ ne.<br/><br/>Nur videblas la profiloj, kies kromaĵo "aperi sur la mapo" estis aktivigita.", + "WOT_BTN_LAYERS": "<b>Filtru ĉi tie la afiÅitajn datenojn</b>: membroj, aliÄoj atendantaj, simplaj monujoj, ktp.", + "WOT_BTN_SEARCH": "Vi povas <b>efektivigi serĉadon</b> laÅ nomo, publika Ålosilo aÅ membro-pseÅdonimo." + } + } + } +} diff --git a/assets/www/plugins/map/i18n/locale-fr-FR.json b/assets/www/plugins/map/i18n/locale-fr-FR.json index 2290781dd2ee02972463d8522c5f0318e49174ea..4df5952191533bc9e2671205d3d38f2ccf7d8af5 100644 --- a/assets/www/plugins/map/i18n/locale-fr-FR.json +++ b/assets/www/plugins/map/i18n/locale-fr-FR.json @@ -13,7 +13,7 @@ "TITLE": "Carte des noeuds", "LAYER": { "MEMBER": "NÅ“uds membre", - "MIRROR": "NÅ“uds mirroir", + "MIRROR": "NÅ“uds miroir", "OFFLINE": "NÅ“uds hors ligne" } } @@ -51,7 +51,7 @@ } }, "PROFILE": { - "MARKER_HELP": "<b>Glissez-déposez</b> ce marqueur pour <b>mettre<br/>à jour votre position</b> sur la carte, ou utilisez le bouton<br/>de recherche au dessus de la carte." + "MARKER_HELP": "<b>Glissez-déposez</b> ce marqueur pour <b>mettre<br/>à jour votre position</b> sur la carte, ou utilisez le bouton<br/>de recherche au-dessus de la carte." }, "ERROR": { "LOCALIZE_ME_FAILED": "Impossible de récupérer votre position actuelle" @@ -62,13 +62,13 @@ "ENABLE_GOOGLE_API_HELP": "Permet l'affichage dans la <b>carte des membres</b> des comptes ayant une adresse mais aucun positionnement GPS.", "GOOGLE_API_KEY": "Clé d'API Google", "BTN_GOOGLE_API": "Obtenir une clé", - "BTN_GOOGLE_API_WARNING": "nécessite d'avoir un compte Google", - "GOOGLE_API_KEY_PLACEHOLDER": "Exemple: AIzaqyAgszvWm0tM81x1sMK_ipDHBI7EowLqR7I" + "BTN_GOOGLE_API_WARNING": "Nécessite d'avoir un compte Google", + "GOOGLE_API_KEY_PLACEHOLDER": "Exemple : AIzaqyAgszvWm0tM81x1sMK_ipDHBI7EowLqR7I" }, "HELP": { "TIP": { - "WOT": "Cette carte affiche <b>les profils ayant une position</b>, qu'ils correspondent à des comptes membre ou non.<br/><br/>Seuls sont visibles les profils dont l'option "apparaitre sur le carte" a été activée.", - "WOT_BTN_LAYERS": "<b>Filtrez ici les données affichées</b>: membres, inscriptions en attente, simples portefeuilles, etc.", + "WOT": "Cette carte affiche <b>les profils ayant une position</b>, qu'ils correspondent à des comptes membre ou non.<br/><br/>Seuls sont visibles les profils dont l'option "apparaître sur la carte" a été activée.", + "WOT_BTN_LAYERS": "<b>Filtrez ici les données affichées</b> : membres, inscriptions en attente, simples portefeuilles, etc.", "WOT_BTN_SEARCH": "Vous pouvez <b>effectuer une recherche</b> par nom, clef publique ou pseudonyme de membre." } } diff --git a/assets/www/plugins/map/i18n/locale-it-IT.json b/assets/www/plugins/map/i18n/locale-it-IT.json new file mode 100644 index 0000000000000000000000000000000000000000..dd08ef28657ec334ed0b4070f3d1114c87d3fa94 --- /dev/null +++ b/assets/www/plugins/map/i18n/locale-it-IT.json @@ -0,0 +1,77 @@ +{ + "MAP": { + "COMMON": { + "SEARCH_DOTS": "Ricerca...", + "BTN_LOCALIZE_ME": "Trovami" + }, + "NETWORK": { + "LOOKUP": { + "BTN_MAP": "Mappa dei peers", + "BTN_MAP_HELP": "Aprire mappa dei peers" + }, + "VIEW": { + "TITLE": "Mappa dei peers", + "LAYER": { + "MEMBER": "Peers membri", + "MIRROR": "Peers specchi", + "OFFLINE": "Peers offline" + } + } + }, + "WOT": { + "LOOKUP": { + "BTN_MAP": "Mappa dei membri", + "BTN_MAP_HELP": "Aprire mappa dei membri" + }, + "VIEW": { + "TITLE": "Mappa membri", + "LAYER": { + "MEMBER": "<i class=\"icon ion-person positive\"></i> Membri", + "PENDING": "<i class=\"icon ion-clock energized\"></i> Registrazione pendenti", + "WALLET": "<i class=\"icon ion-card gray\"></i> Portafogli osservatori" + } + }, + "ERROR": { + "LOAD_POSITION_FAILED": "Errore nel caricamento delle posizioni." + } + }, + "REGISTRY": { + "LOOKUP": { + "BTN_MAP": "Mappa", + "BTN_MAP_HELP": "Aprire la mappa delle pagine pro" + }, + "VIEW": { + "TITLE": "Mappa delle pagine pro", + "LAYER": { + "SHOP": "<i class=\"icon ion-page-shop positive\"></i> Negozi locali", + "COMPANY": "<i class=\"icon ion-page-company positive\"></i> Aziende", + "ASSOCIATION": "<i class=\"icon ion-page-association energized\"></i> Associazioni", + "INSTITUTION": "<i class=\"icon ion-page-institution gray\"></i> Instituti" + } + } + }, + "PROFILE": { + "MARKER_HELP": "<b>Drag and drop</b> questo indicatore per <b>aggiornare<br/>tua posizione</b>, o usa i bottoni <br/>sopra la mappa." + }, + "ERROR": { + "LOCALIZE_ME_FAILED": "Impossible trovare tua posizione attuale" + }, + "SETTINGS": { + "MAP_DIVIDER": "Mappe", + "ENABLE_GOOGLE_API": "Abilitare i servizi Google API ?", + "ENABLE_GOOGLE_API_HELP": "Sulla <b>mappa dei membri</b>, ti permette di visualizzare i conti con un indirizzo ma senza geolocalizzazione.", + "GOOGLE_API_KEY": "Chiave Google API", + "BTN_GOOGLE_API": "Ottenere una chiave", + "BTN_GOOGLE_API_WARNING": "necessita un conto Google", + "GOOGLE_API_KEY_PLACEHOLDER": "per es. : AIzaqyAgszvWm0tM81x1sMK_ipDHBI7EowLqR7I" + }, + "HELP": { + "TIP": { + "WOT": "Questa mappa mostra <b>profili che hanno fornito una posizione</b>, che siano conti membri o no.<br/><br/>Solo i profili che hanno attivato l'opzione "apparire sulla mappa" sono stati attivati.", + "WOT_BTN_LAYERS": "<b>Filtrare i dati visibili</b>: membri, registrazioni pendenti, portafogli osservatori, etc.", + "WOT_BTN_SEARCH": "Puoi <b>cercare</b> per nome, chiave pubblica, o pseudonimo del membro." + } + } + } + } + \ No newline at end of file diff --git a/assets/www/plugins/map/js/controllers/registry-controllers.js b/assets/www/plugins/map/js/controllers/registry-controllers.js index 9efde6a6ea1f07351b0eb8d053b1dd4ca963056c..562dfe96f344b4f383c0ac5a173d89203c0fb251 100644 --- a/assets/www/plugins/map/js/controllers/registry-controllers.js +++ b/assets/www/plugins/map/js/controllers/registry-controllers.js @@ -50,7 +50,8 @@ angular.module('cesium.map.registry.controllers', ['cesium.services', 'cesium.ma function MapRegistryViewController($scope, $filter, $templateCache, $interpolate, $timeout, $location, $translate, $q, - leafletData, UIUtils, csSettings, csWallet, MapUtils, mapRegistry) { + ionicReady, leafletData, + UIUtils, csSettings, csWallet, MapUtils, mapRegistry) { 'ngInject'; var @@ -81,7 +82,8 @@ function MapRegistryViewController($scope, $filter, $templateCache, $interpolate }; $scope.loading = true; - $scope.mapId = 'map-wot-' + $scope.$id; + $scope.loadingMarker = true; + $scope.mapId = 'map-registry-' + $scope.$id; $scope.map = MapUtils.map({ cache: 'map-registry', @@ -115,6 +117,15 @@ function MapRegistryViewController($scope, $filter, $templateCache, $interpolate loading: true }, $scope.mapId); + // Variables for marker + $scope.formData = {}; + $scope.showDescription = false; + ionicReady().then(function() { + $scope.enableDescription = !UIUtils.screen.isSmall() && ionic.Platform.grade.toLowerCase() === 'a'; + if (!$scope.enableDescription) { + console.debug("[map] [wot] Disable profile description.", ionic.Platform.grade); + } + }); $scope.$on('$ionicView.beforeEnter', function (event, viewData) { // Enable back button (workaround need for navigation outside tabs - https://stackoverflow.com/a/35064602) @@ -168,19 +179,6 @@ function MapRegistryViewController($scope, $filter, $templateCache, $interpolate if (!$scope.map.loading) return map; // already loaded if (!UIUtils.screen.isSmall()) { - // Add a start tour button - /*L.easyButton({ - position: 'topright', // inherited from L.Control -- the corner it goes in - type: 'replace', // set to animate when you're comfy with css - leafletClasses: true, // use leaflet classes to style the button? - states:[{ // specify different icons and responses for your button - stateName: 'show-help-tour', - onClick: $scope.startHelpTour, - title: translations['COMMON.BTN_HELP_TOUR_SCREEN'], - icon: 'icon ion-easel' - }] - } - ).addTo(map);*/ // Add a refresh button L.easyButton({ @@ -291,7 +289,7 @@ function MapRegistryViewController($scope, $filter, $templateCache, $interpolate var options = { fields: { - description: !UIUtils.screen.isSmall() + description: $scope.enableDescription } }; @@ -307,41 +305,44 @@ function MapRegistryViewController($scope, $filter, $templateCache, $interpolate if (res && res.length) { var formatPubkey = $filter('formatPubkey'); - var userMarkerTemplate = $templateCache.get('plugins/map/templates/wot/popup_marker.html'); - var pageMarkerTemplate = $templateCache.get('plugins/map/templates/wot/popup_page_marker.html'); + var pageMarkerTemplate = $templateCache.get('plugins/map/templates/registry/popup_marker.html'); _.forEach(res, function (hit) { - var type = hit.type || (hit.pending ? 'pending' : (hit.uid ? 'member' : 'wallet')); var shortPubkey = formatPubkey(hit.pubkey); - var id = hit.index + '_' + (hit.id || (hit.uid ? (hit.uid + ':' + hit.pubkey) : hit.pubkey)).replace(/-/g, '_'); + var id = hit.index + '_' + (hit.id).replace(/-/g, '_'); var marker = { - layer: type, - icon: icons[type], - opacity: hit.uid || hit.type ? 1 : 0.7, + layer: hit.type, + icon: icons[hit.type], + opacity: 1, title: hit.name + ' | ' + shortPubkey, lat: hit.geoPoint.lat, lng: hit.geoPoint.lon, getMessageScope: function () { var scope = $scope.$new(); - scope.hit = hit; + scope.loadingMarker = true; + scope.formData = {}; + scope.$applyAsync(function() { + angular.extend(scope.formData, hit); + scope.loadingMarker = false; + }); return scope; }, focus: false, - message: hit.type ? pageMarkerTemplate : userMarkerTemplate, + message: pageMarkerTemplate, id: id }; markers[id] = marker; // Create a search marker (will be hide) - var searchText = hit.name + ((hit.uid && hit.uid != hit.name) ? (' | ' + hit.uid) : '') + ' | ' + shortPubkey; + var searchText = hit.name + ' | ' + shortPubkey; var searchMarker = angular.merge({ - type: type, + type: hit.type, opacity: 0, icon: L.divIcon({ - className: type + ' ng-hide', + className: hit.type + ' ng-hide', iconSize: L.point(0, 0) }) - }, {title: searchText, pubkey: hit.pubkey, uid: hit.uid, name: hit.name, pending: hit.pending, popupMarkerId: id}); + }, {title: searchText, pubkey: hit.pubkey, name: hit.name, popupMarkerId: id}); markersSearchLayer.addLayer(new L.Marker({ lat: hit.geoPoint.lat, lng: hit.geoPoint.lon diff --git a/assets/www/plugins/map/js/controllers/user-controllers.js b/assets/www/plugins/map/js/controllers/user-controllers.js index 9fff394e579b9fed2a53f95ccdf11c76feb01ac6..5b429c2e5ed9531fca8050bdfbaca42372a7a01d 100644 --- a/assets/www/plugins/map/js/controllers/user-controllers.js +++ b/assets/www/plugins/map/js/controllers/user-controllers.js @@ -9,7 +9,16 @@ angular.module('cesium.map.user.controllers', ['cesium.services', 'cesium.map.se PluginServiceProvider - .extendState('app.user_edit_profile', { + .extendState('app.edit_profile', { + points: { + 'after-position': { + templateUrl: 'plugins/map/templates/user/edit_profile_extend.html', + controller: 'MapEditProfileViewCtrl' + } + } + }) + + .extendState('app.edit_profile_by_id', { points: { 'after-position': { templateUrl: 'plugins/map/templates/user/edit_profile_extend.html', diff --git a/assets/www/plugins/map/js/controllers/wot-controllers.js b/assets/www/plugins/map/js/controllers/wot-controllers.js index cb57dbf5efa2bb5febaba422cb456f498b044a2d..c11884f2900195517de2e6ed5bb1c595f507ec65 100644 --- a/assets/www/plugins/map/js/controllers/wot-controllers.js +++ b/assets/www/plugins/map/js/controllers/wot-controllers.js @@ -50,10 +50,15 @@ angular.module('cesium.map.wot.controllers', ['cesium.services', 'cesium.map.ser ; -function MapWotViewController($scope, $filter, $templateCache, $interpolate, $timeout, $location, $translate, $q, +function MapWotViewController($scope, $filter, $templateCache, $interpolate, $timeout, $location, $translate, $q, $controller, + ionicReady, leafletData, UIUtils, csSettings, csWallet, MapUtils, mapWot) { 'ngInject'; + // Initialize the super classes and extend it. + angular.extend(this, $controller('WotIdentityAbstractCtrl', { $scope: $scope})); + angular.extend(this, $controller('ESWotIdentityViewCtrl', {$scope: $scope})); + var // Create a hidden layer, to hold search markers markersSearchLayer, @@ -77,6 +82,7 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti }; $scope.loading = true; + $scope.loadingMarker = true; $scope.mapId = 'map-wot-' + $scope.$id; $scope.map = MapUtils.map({ @@ -107,6 +113,14 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti loading: true }, $scope.mapId); + // Variables for marker + $scope.showDescription = false; + ionicReady().then(function() { + $scope.enableDescription = !UIUtils.screen.isSmall() && ionic.Platform.grade.toLowerCase() === 'a'; + if (!$scope.enableDescription) { + console.debug("[map] [wot] Disable profile description.", ionic.Platform.grade); + } + }); $scope.$on('$ionicView.beforeEnter', function (event, viewData) { // Enable back button (workaround need for navigation outside tabs - https://stackoverflow.com/a/35064602) @@ -116,6 +130,10 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti $scope.enter = function(e, state) { if ($scope.loading) { + + UIUtils.loading.show({ + noBackdrop: true // avoid a too long release + }); if (state.stateParams && state.stateParams.c) { var cPart = state.stateParams.c.split(':'); $scope.map.center.lat = parseFloat(cPart[0]); @@ -132,20 +150,19 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti }, true); // Load the map (and init if need) + var now = Date.now(); $scope.loadMap() + .then($scope.load) .then(function() { - if (csWallet.isLogin()) { - $scope.showHelpTip(); - } - return $scope.load(); + console.debug("[map] [wot] Loaded in "+ (Date.now() - now) +"ms"); + + $scope.showHelpTip(); }); } else { // Make sure to have previous center coordinate defined in the location URL $scope.updateLocationHref(); - if (csWallet.isLogin()) { - $scope.showHelpTip(); - } + $scope.showHelpTip(); } }; $scope.$on('$ionicView.enter', $scope.enter); @@ -265,6 +282,7 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti //MapUtils.cache.bind($scope, $scope.mapId, $scope.map); $scope.map.loading = false; + return map; }); }; @@ -283,10 +301,17 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti var options = { fields: { - description: !UIUtils.screen.isSmall() + description: $scope.enableDescription } }; + // add bounding box + if ($scope.map.bounds) { + // FIXME - this is not working well + //options.bounds = angular.copy($scope.map.bounds); + //delete options.bounds.options; + } + // Load wot data, from service return mapWot.load(options) @@ -299,8 +324,7 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti if (res && res.length) { var formatPubkey = $filter('formatPubkey'); - var userMarkerTemplate = $templateCache.get('plugins/map/templates/wot/popup_marker.html'); - var pageMarkerTemplate = $templateCache.get('plugins/map/templates/wot/popup_page_marker.html'); + var markerTemplate = $templateCache.get('plugins/map/templates/wot/popup_marker.html'); _.forEach(res, function (hit) { var type = hit.pending ? 'pending' : (hit.uid ? 'member' : 'wallet'); @@ -309,17 +333,27 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti var marker = { layer: type, icon: icons[type], - opacity: hit.uid || hit.type ? 1 : 0.7, + opacity: hit.uid ? 1 : 0.7, title: hit.name + ' | ' + shortPubkey, lat: hit.geoPoint.lat, lng: hit.geoPoint.lon, getMessageScope: function () { var scope = $scope.$new(); - scope.hit = hit; + scope.loadingMarker = true; + scope.formData = {}; + scope.$applyAsync(function() { + scope.formData = { + pubkey: hit.pubkey, + uid: hit.uid, + name: hit.name, + profile: hit + }; + scope.loadingMarker = false; + }); return scope; }, focus: false, - message: hit.type ? pageMarkerTemplate : userMarkerTemplate, + message: markerTemplate, id: id }; markers[id] = marker; @@ -344,10 +378,14 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti $scope.map.markers = markers; - $scope.loading = false; + return $timeout(function(){ + $scope.loading = false; + + // hide loading indicator + map.fire('dataload'); - // hide loading indicator - map.fire('dataload'); + UIUtils.loading.hide(); + }); }) .catch(function(err) { $scope.map.markers = {}; @@ -367,20 +405,6 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti // endRemoveIf(device) }; - // removeIf(device) - // Update the browser location, to be able to refresh the page - // FIXME: not need, should be removed - $scope.$on("centerUrlHash", function(event, centerHash) { - if (!$scope.loading) { - - return $timeout(function() { - $scope.updateLocationHref(centerHash); - }, 300); - } - }); - // endRemoveIf(device) - - /* -- help tip -- */ // Show help tour @@ -390,6 +414,8 @@ function MapWotViewController($scope, $filter, $templateCache, $interpolate, $ti // Show help tip $scope.showHelpTip = function(index, isTour) { + if (!isTour && !csWallet.isLogin()) return; + index = angular.isDefined(index) ? index : (angular.isNumber(csSettings.data.helptip.mapwot) ? csSettings.data.helptip.mapwot : 0); isTour = angular.isDefined(isTour) ? isTour : false; diff --git a/assets/www/plugins/map/js/services/registry-services.js b/assets/www/plugins/map/js/services/registry-services.js index 3ca5df42a564a1321b1a75e6cac92228d4b2e67a..30cc657f1024c1e50c923cecb44d5e4cbb49a294 100644 --- a/assets/www/plugins/map/js/services/registry-services.js +++ b/assets/www/plugins/map/js/services/registry-services.js @@ -168,7 +168,7 @@ angular.module('cesium.map.registry.services', ['cesium.services']) // Resolve missing positions by addresses (only if google API enable) if (searchAddressItems.length) { - var now = new Date().getTime(); + var now = Date.now(); console.debug('[map] [registry] Search positions of {0} addresses...'.format(searchAddressItems.length)); var counter = 0; @@ -189,7 +189,7 @@ angular.module('cesium.map.registry.services', ['cesium.services']) .catch(function() {/*silent*/})); }, [])) .then(function(){ - console.debug('[map] [registry] Resolved {0}/{1} addresses in {2}ms'.format(counter, searchAddressItems.length, new Date().getTime()-now)); + console.debug('[map] [registry] Resolved {0}/{1} addresses in {2}ms'.format(counter, searchAddressItems.length, Date.now()-now)); return items; }); } diff --git a/assets/www/plugins/map/js/services/wot-services.js b/assets/www/plugins/map/js/services/wot-services.js index b3d83d140fb4a436d737172545c14caee149e4a0..62c7a885b15e1477fe87abe69764d386117ba342 100644 --- a/assets/www/plugins/map/js/services/wot-services.js +++ b/assets/www/plugins/map/js/services/wot-services.js @@ -10,6 +10,7 @@ angular.module('cesium.map.wot.services', ['cesium.services']) DEFAULT_LOAD_SIZE: 1000 }, fields = { + min: ["title", "geoPoint"], profile: ["title", "geoPoint", "avatar._content_type", "address", "city"] }; @@ -43,8 +44,7 @@ angular.module('cesium.map.wot.services', ['cesium.services']) // Filter on bounding box // see https://www.elastic.co/guide/en/elasticsearch/reference/2.4/geo-point.html if (options.bounds && options.bounds.northEast && options.bounds.southWest) { - query.bool.should = query.bool.should || {}; - query.bool.should.geo_bounding_box = { + var boundingBox = { "geoPoint" : { "top_left" : { "lat" : Math.max(Math.min(options.bounds.northEast.lat, 90), -90), @@ -56,6 +56,9 @@ angular.module('cesium.map.wot.services', ['cesium.services']) } } }; + console.debug("[map] [wot] Filtering on bounds: ", options.bounds); + query.bool.must = query.bool.must || []; + query.bool.must.push({geo_bounding_box: boundingBox}); } return query; } @@ -67,7 +70,7 @@ angular.module('cesium.map.wot.services', ['cesium.services']) options.searchAddress = esGeo.google.isEnable() && (angular.isDefined(options.searchAddress) ? options.searchAddress : true); options.fields = options.fields || {}; - options.fields.description = angular.isDefined(options.fields.description) ? options.fields.description : true; + options.fields.description = angular.isDefined(options.fields.description) ? options.fields.description : false; var request = { query: createFilterQuery(options), @@ -193,7 +196,7 @@ angular.module('cesium.map.wot.services', ['cesium.services']) // Resolve missing positions by addresses (only if google API enable) if (searchAddressItems.length) { - var now = new Date().getTime(); + var now = Date.now(); console.debug('[map] [wot] Search positions of {0} addresses...'.format(searchAddressItems.length)); var counter = 0; @@ -214,7 +217,7 @@ angular.module('cesium.map.wot.services', ['cesium.services']) .catch(function() {/*silent*/})); }, [])) .then(function(){ - console.debug('[map] [wot] Resolved {0}/{1} addresses in {2}ms'.format(counter, searchAddressItems.length, new Date().getTime()-now)); + console.debug('[map] [wot] Resolved {0}/{1} addresses in {2}ms'.format(counter, searchAddressItems.length, Date.now()-now)); return items; }); } diff --git a/assets/www/plugins/map/templates/network/lookup_extend.html b/assets/www/plugins/map/templates/network/lookup_extend.html index dc388fc87f9efa7d8fac66ea7a334a85e59f0140..cef1529a3b2d240f4467d1d48c65a6f17500c82e 100644 --- a/assets/www/plugins/map/templates/network/lookup_extend.html +++ b/assets/www/plugins/map/templates/network/lookup_extend.html @@ -1,3 +1,4 @@ +<!-- FIXME issue #755 - https://git.duniter.org/clients/cesium-grp/cesium/issues/755 <a ng-if="enable" class="button button-text button-small ink hidden-sm hidden-xs" title="{{'MAP.NETWORK.LOOKUP.BTN_MAP_HELP' | translate}}" @@ -5,3 +6,4 @@ <i class="icon ion-ios-location"></i> {{'MAP.NETWORK.LOOKUP.BTN_MAP' | translate}} </a> + --> diff --git a/assets/www/plugins/map/templates/registry/popup_marker.html b/assets/www/plugins/map/templates/registry/popup_marker.html new file mode 100644 index 0000000000000000000000000000000000000000..444f732ac6b51555841408925b9936cd9cf72c73 --- /dev/null +++ b/assets/www/plugins/map/templates/registry/popup_marker.html @@ -0,0 +1,51 @@ +<div class="item no-border no-padding item-avatar " + ng-if="loadingMarker"> + + <i class="item-image icon ion-person"></i> + + <div class="item-content item-avatar-left-padding padding-top" > + <h2 class="stable-bg"> + + </h2> + <h4 class="stable-bg col-75"> + + </h4> + <h4 class="stable-bg col-50"> + + </h4> + </div> +</div> + +<a class="item no-border no-padding item-avatar ink animate-fade-in animate-show-hide ng-hide" + ng-show="!loadingMarker" + ui-sref="app.view_page({id: formData.id, title: formData.name})"> + <i ng-if="formData.avatar" class="item-image avatar" style="background-image: url({{::formData.avatar.src}}"></i> + <i ng-if="!formData.avatar" class="item-image icon cion-page-{{::formData.type}}"></i> + <div class="item-content item-avatar-left-padding padding-top"> + <h2 class="dark"> + {{::formData.name}} + </h2> + <h4 ng-if="::formData.category" class="gray" title="{{::formData.category.name}}"> + <b class="ion-flag"></b> {{::formData.category.name}} + </h4> + <h4 ng-if="::formData.city" class="gray" title="{{::formData.city}}"> + <b class="ion-location"></b> {{::formData.city}} + </h4> + </div> +</a> +<!-- buttons --> +<div class="item no-border no-padding"> + <div class="pull-left gray"> + <!-- show description --> + <a class="animate-fade-in animate-show-hide gray ng-hide" + ng-class="{'ion-arrow-down-b': !showDescription, 'ion-arrow-up-b': showDescription}" + ng-click="showDescription=!showDescription;" + title="{{'PROFILE.DESCRIPTION'|translate}}" + ng-show="!loadingMarker && formData.description"> + + </a> + </div> +</div> +<div class="item no-border no-padding item-text-wrap hidden-xs ng-hide" ng-show="showDescription"> + <small trust-as-html="::formData.description|truncText:500"></small> +</div> diff --git a/assets/www/plugins/map/templates/user/edit_profile_extend.html b/assets/www/plugins/map/templates/user/edit_profile_extend.html index 9f1706f9a11e1f256bd2b2f58c123ec807ec042a..38462888622ba7b4ae2a2527379b9cc33cd71fc4 100644 --- a/assets/www/plugins/map/templates/user/edit_profile_extend.html +++ b/assets/www/plugins/map/templates/user/edit_profile_extend.html @@ -1,4 +1,4 @@ -<div class="item no-padding {{ionItemClass}}" ng-if="formData.geoPoint && formData.geoPoint.lat && formData.geoPoint.lon"> +<div class="item no-padding hidden-xs hidden-sm {{ionItemClass}}" ng-if="formData.geoPoint && formData.geoPoint.lat && formData.geoPoint.lon"> <leaflet id="{{::mapId}}" height="250px" center="map.center" diff --git a/assets/www/plugins/map/templates/wot/popup_marker.html b/assets/www/plugins/map/templates/wot/popup_marker.html index 29ba453a2545a1d2288d91db7d7b290e8e43f384..633503f07bc9d95856f124fe591b13a70bc7dfb0 100644 --- a/assets/www/plugins/map/templates/wot/popup_marker.html +++ b/assets/www/plugins/map/templates/wot/popup_marker.html @@ -1,23 +1,82 @@ -<div class="item no-border no-padding item-avatar" ng-class="::{'item-avatar': hit.avatar}"> - <img ng-if="::hit.avatar" class="item-image avatar" ng-src="{{::hit.avatar.src}}"> - <i ng-if="::!hit.avatar" class="item-image icon " ng-class="::{'ion-person': hit.uid, 'ion-card': !hit.uid}"></i> + +<div class="item no-border no-padding item-avatar " + ng-if="loadingMarker"> + + <i class="item-image icon ion-person"></i> + + <div class="item-content item-avatar-left-padding padding-top" > + <h2 class="stable-bg"> + + </h2> + <h4 class="stable-bg col-75"> + + </h4> + <h4 class="stable-bg col-50"> + + </h4> + </div> +</div> + +<a class="item no-border no-padding item-avatar ink animate-fade-in animate-show-hide ng-hide" + ng-show="!loadingMarker" + ui-sref="app.wot_identity({pubkey: formData.pubkey, uid: formData.uid})"> + + <i ng-if="formData.avatar" class="item-image avatar" style="background-image: url({{::formData.avatar.src}})"></i> + <i ng-if="!formData.avatar && formData.uid" class="item-image icon ion-person"></i> + <i ng-if="!formData.avatar && !formData.uid" class="item-image icon ion-card"></i> + <div class="item-content item-avatar-left-padding padding-top"> - <h2 class="dark"><a ui-sref="app.wot_identity({pubkey: hit.pubkey, uid: hit.uid})">{{::hit.name}}</a></h2> + <h2 class="dark"> + {{formData.name}} + </h2> <h4> - <span ng-if="::hit.uid" class="positive"> + <span ng-if="formData.uid" class="positive"> <b class="ion-person"></b> - {{::hit.uid}} + {{formData.uid}} </span> - <span class="gray" title="{{::hit.pubkey}}"><b class="ion-key"></b> {{::hit.pubkey|formatPubkey}}</span> - <span class="assertive" ng-if="!hit.uid"> + <span class="gray" title="{{formData.pubkey}}"><b class="ion-key"></b> {{formData.pubkey|formatPubkey}}</span> + <span class="assertive" ng-if="!formData.isMember"> {{::'WOT.NOT_MEMBER_PARENTHESIS'|translate}} </span> </h4> - <h4 ng-if="::hit.city" class="gray" title="{{::hit.city}}"> - <b class="ion-location"></b> {{::hit.city}} + <h4 ng-if="formData.profile.city" class="gray" title="{{formData.profile.city}}"> + <b class="ion-location"></b> {{formData.profile.city}} </h4> </div> +</a> +<!-- buttons --> +<div class="item no-border no-padding"> + <div class="pull-left gray"> + <!-- show description --> + <a class="animate-fade-in animate-show-hide gray ng-hide" + ng-class="{'ion-arrow-down-b': !showDescription, 'ion-arrow-up-b': showDescription}" + ng-click="showDescription=!showDescription;" + title="{{'PROFILE.DESCRIPTION'|translate}}" + ng-show="!loadingMarker && formData.profile.description"> + + </a> + </div> + <div style="font-size: 18px;" class="pull-right gray"> + <!-- share --> + <a class="icon ion-android-share-alt " + ng-click="showSharePopover($event)" + title="{{'COMMON.BTN_SHARE' | translate}}"> </a> + <!-- certify --> + <a class="icon ion-ribbon-b" + ng-click="certify()" + title="{{'WOT.BTN_CERTIFY' | translate}}" + ng-hide="!canCertify"> </a> + <!-- compose message --> + <a class="icon ion-compose" + ng-click="showNewMessageModal()" + title="{{'MESSAGE.BTN_WRITE' | translate}}"> </a> + <!-- transfer --> + <a class="icon ion-card" + ng-click="showTransferModal({pubkey:formData.pubkey, uid: formData.name||formData.uid})" + title="{{'COMMON.BTN_SEND_MONEY' | translate}}"> </a> + + </div> </div> -<div class="item no-border no-padding item-text-wrap hidden-xs" ng-if="::hit.description"> - <small trust-as-html="::hit.description"></small> +<div class="item no-border no-padding item-text-wrap hidden-xs ng-hide" ng-show="showDescription"> + <small trust-as-html="formData.profile.description|truncText:500"></small> </div> diff --git a/assets/www/plugins/map/templates/wot/popup_page_marker.html b/assets/www/plugins/map/templates/wot/popup_page_marker.html deleted file mode 100644 index ded9405b0f6770a617f1956c45a2c3c41fc3f639..0000000000000000000000000000000000000000 --- a/assets/www/plugins/map/templates/wot/popup_page_marker.html +++ /dev/null @@ -1,16 +0,0 @@ -<div class="item no-border no-padding item-avatar" ng-class="::{'item-avatar': hit.avatar}"> - <img ng-if="::hit.avatar" class="item-image avatar" ng-src="{{::hit.avatar.src}}"> - <i ng-if="::!hit.avatar" class="item-image icon cion-page-{{::hit.type}}"></i> - <div class="item-content item-avatar-left-padding padding-top"> - <h2 class="dark"><a ui-sref="app.view_page({id: hit.id, title: hit.title})">{{::hit.name}}</a></h2> - <h4 ng-if="::hit.category" class="gray" title="{{::hit.category.name}}"> - <a ui-sref="app.registry_lookup({category: hit.category.id})"><b class="ion-flag"></b> {{::hit.category.name}}</a> - </h4> - <h4 ng-if="::hit.city" class="gray" title="{{::hit.city}}"> - <b class="ion-location"></b> {{::hit.city}} - </h4> - </div> -</div> -<div class="item no-border no-padding item-text-wrap hidden-xs" ng-if="::hit.description"> - <small trust-as-html="::hit.description"></small> -</div> diff --git a/assets/www/plugins/rml9/plugin-final.js b/assets/www/plugins/rml9/plugin-final.js index ee81968f4bb892ae573da121891168c5d9342423..17f21d3f28294030cb19022fbcb17e808d399c09 100644 --- a/assets/www/plugins/rml9/plugin-final.js +++ b/assets/www/plugins/rml9/plugin-final.js @@ -111,9 +111,7 @@ angular.module('cesium.rml9.plugin', ['ngFileSaver', 'cesium.services']) if (!result || !result.tx || !result.tx.history) return; // no TX var formatDecimal = $filter('formatDecimal'); - var formatPubkey = $filter('formatPubkey'); var formatDate = $filter('formatDate'); - var formatDateForFile = $filter('formatDateForFile'); var headers = [translations['RML9.HEADERS.TIME'], translations['COMMON.UID'], diff --git a/assets/www/templates/api/doc.html b/assets/www/templates/api/doc.html index b4ba988ffc17fd57dddc904b7a26b51d24d48d03..eee193039a567e27453e8ee3262fade3511ca390 100644 --- a/assets/www/templates/api/doc.html +++ b/assets/www/templates/api/doc.html @@ -1 +1 @@ -<h2 class="padding" translate="">API.DOC.TRANSFER.TITLE</h2><div class="list padding no-padding-xs no-padding-top"><div class="item item-divider no-border"><p translate="">API.DOC.DESCRIPTION_DIVIDER</p></div><div class="item item-text-wrap"><p translate="">API.DOC.TRANSFER.DESCRIPTION</p></div><div class="item item-divider no-border"><p translate="">API.DOC.URL_DIVIDER</p></div><div class="item item-text-wrap"><p class="gray text-right">{{$root.rootPath}}#/v1/payment/:pubkey?amount=<span class="text-italic" translate="">API.DOC.TRANSFER.PARAM_AMOUNT</span></p></div><div class="item item-divider no-border"><p translate="">API.DOC.PARAMETERS_DIVIDER</p></div><div class="item item-text-wrap"><p translate="">API.DOC.AVAILABLE_PARAMETERS</p><div class="row"><div class="col col-20 text-italic">pubkey</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_PUBKEY_HELP</div></div><div class="row stable-bg"><div class="col col-20 text-italic dark">amount</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_AMOUNT_HELP</div></div><div class="row"><div class="col col-20 text-italic">comment</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_COMMENT_HELP</div></div><div class="row stable-bg"><div class="col col-20 text-italic dark">name</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_NAME_HELP</div></div><div class="row"><div class="col col-20 text-italic">redirect_url</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_REDIRECT_URL_HELP</div></div><div class="row stable-bg"><div class="col col-20 text-italic dark">cancel_url</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_CANCEL_URL_HELP</div></div></div><div class="item item-divider no-border"><p translate="">API.DOC.DEMO_DIVIDER</p></div><div class="item item-button-right item-text-wrap padding-bottom"><p class="item-icon-right-padding" translate="">API.DOC.DEMO_HELP</p><span class="badge" ng-if="loading"><ion-spinner class="icon" icon="android"></ion-spinner></span><a ng-if="!loading" href="{{transferDemoUrl}}" class="button button-raised button-positive icon ion-play"></a></div><div class="item item-text-wrap" ng-if="result.type === 'payment' && !result.cancelled"><h2 class="text-right balanced" translate="">API.DOC.DEMO_SUCCEED</h2><h4 class="gray" translate="">API.DOC.DEMO_RESULT</h4><p class="balanced-100-bg padding dark text-keep-lines">{{result.content}}</p></div><div class="item item-text-wrap" ng-if="result.type === 'payment' && result.cancelled"><h2 class="text-right assertive" translate="">API.DOC.DEMO_CANCELLED</h2></div><div class="item item-divider no-border"><p translate="">API.DOC.INTEGRATE_DIVIDER</p></div><div class="item item-text-wrap"><p translate="">API.DOC.TRANSFER.EXAMPLES_HELP</p><div class="row responsive-sm"><div class="col col-20 text-italic"><span translate="">API.DOC.TRANSFER.EXAMPLE_BUTTON</span></div><div class="col gray no-border"><p><i class="icon ion-code"></i> <span translate="">API.DOC.INTEGRATE_CODE</span></p><div class="item item-input"><textarea class="gray" select-on-click="" rows="5" ng-model="transferButton.html" ng-model-options="{ debounce: 650 }"></textarea></div><p class="padding-top"><i class="icon ion-eye"></i> <span translate="">API.DOC.INTEGRATE_RESULT</span></p><div class="padding-left" bind-notifier="{ notifierKey:watchedExpression }"><ng-bind-html ng-bind-html="transferButton.html|trustAsHtml"></ng-bind-html></div></div></div><div class="row responsive-sm"><div class="col gray no-border"><p class="padding-top"><a class="positive" ng-click="transferButton.showParameters=!transferButton.showParameters"><i class="icon ion-wrench"></i> <span translate="">API.DOC.INTEGRATE_PARAMETERS</span> <i class="icon" ng-class="{'ion-arrow-down-b': !transferButton.showParameters, 'ion-arrow-up-b': transferButton.showParameters}"></i></a></p><div ng-if="transferButton.showParameters" class="padding-left"><form id="transferForm" class="stable-bg padding"><p class="padding-top"><i class="icon ion-key"></i> {{'API.DOC.TRANSFER.PARAM_PUBKEY' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.pubkey" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.PARAM_PUBKEY_HELP'|translate}}"></label><p class="padding-top"><i class="icon ion-pricetag"></i> {{'API.DOC.TRANSFER.PARAM_AMOUNT' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.amount" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.PARAM_AMOUNT_HELP'|translate}}"></label><p class="padding-top"><i class="icon ion-flag"></i> {{'API.DOC.TRANSFER.PARAM_COMMENT' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.comment" placeholder="{{'API.DOC.TRANSFER.PARAM_COMMENT'|translate}}"></label><p class="padding-top"><i class="icon ion-ios-world-outline"></i> {{'API.DOC.TRANSFER.PARAM_NAME' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.name" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.PARAM_NAME'|translate}}"></label><p class="padding-top"><i class="icon ion-arrow-return-left"></i> {{'API.DOC.TRANSFER.PARAM_REDIRECT_URL' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.redirect_url" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.PARAM_REDIRECT_URL'|translate}}"></label><p class="padding-top"><i class="icon ion-backspace"></i> {{'API.DOC.TRANSFER.PARAM_CANCEL_URL' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.cancel_url" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.PARAM_CANCEL_URL'|translate}}"></label><p class="padding-top"><a class="positive" ng-click="transferButton.style.enable=!transferButton.style.enable"><i class="icon" ng-class="{'ion-android-checkbox-outline': transferButton.style.enable, 'ion-android-checkbox-outline-blank': !transferButton.style.enable}"></i> <span translate="">API.DOC.TRANSFER.EXAMPLE_BUTTON_DEFAULT_STYLE</span></a></p><div ng-if="transferButton.style.enable"><p class="padding-top"><i class="icon ion-image"></i> {{'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_ICON' | translate}} :</p><label class="item item-input item-select"><select class="stable-bg dark" ng-model="transferButton.style.icon" style="width: 100%; max-width: 100%" ng-options="l as (l.label | translate) for l in transferButton.icons track by l.filename"></select></label><p class="padding-top"><i class="icon ion-quote"></i> {{'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_HELP' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.text" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_HELP'|translate}}"></label><p class="padding-top"><i class="icon ion-paintbucket"></i> {{'API.DOC.TRANSFER.EXAMPLE_BUTTON_BG_COLOR' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.bgColor" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.EXAMPLE_BUTTON_BG_COLOR_HELP'|translate}}"></label><p class="padding-top"><i class="icon ion-paintbrush"></i> {{'API.DOC.TRANSFER.EXAMPLE_BUTTON_FONT_COLOR' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.fontColor" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.EXAMPLE_BUTTON_FONT_COLOR_HELP'|translate}}"></label><p class="padding-top"><i class="icon ion-ios-crop-strong"></i> {{'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_WIDTH' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.width" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_WIDTH_HELP'|translate}}"></label></div></form></div></div></div></div></div> \ No newline at end of file +<h2 class="padding" translate="">API.DOC.TRANSFER.TITLE</h2><div class="list padding no-padding-xs no-padding-top"><div class="item item-divider no-border"><p translate="">API.DOC.DESCRIPTION_DIVIDER</p></div><div class="item item-text-wrap"><p translate="">API.DOC.TRANSFER.DESCRIPTION</p></div><div class="item item-divider no-border"><p translate="">API.DOC.URL_DIVIDER</p></div><div class="item item-text-wrap"><p class="gray text-right">{{$root.rootPath}}#/v1/payment/:pubkey?amount=<span class="text-italic" translate="">API.DOC.TRANSFER.PARAM_AMOUNT</span></p></div><div class="item item-divider no-border"><p translate="">API.DOC.PARAMETERS_DIVIDER</p></div><div class="item item-text-wrap"><p translate="">API.DOC.AVAILABLE_PARAMETERS</p><div class="row"><div class="col col-20 text-italic">pubkey</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_PUBKEY_HELP</div></div><div class="row stable-bg"><div class="col col-20 text-italic dark">amount</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_AMOUNT_HELP</div></div><div class="row"><div class="col col-20 text-italic">comment</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_COMMENT_HELP</div></div><div class="row stable-bg"><div class="col col-20 text-italic dark">name</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_NAME_HELP</div></div><div class="row"><div class="col col-20 text-italic">preferred_node</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_PREFERRED_NODE_HELP</div></div><div class="row stable-bg"><div class="col col-20 text-italic dark">redirect_url</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_REDIRECT_URL_HELP</div></div><div class="row"><div class="col col-20 text-italic">cancel_url</div><div class="col gray" translate="">API.DOC.TRANSFER.PARAM_CANCEL_URL_HELP</div></div></div><div class="item item-divider no-border"><p translate="">API.DOC.DEMO_DIVIDER</p></div><div class="item item-button-right item-text-wrap padding-bottom"><p class="item-icon-right-padding" translate="">API.DOC.DEMO_HELP</p><span class="badge" ng-if="loading"><ion-spinner class="icon" icon="android"></ion-spinner></span><a ng-if="!loading" href="{{transferDemoUrl}}" class="button button-raised button-positive icon ion-play"></a></div><div class="item item-text-wrap" ng-if="result.type === 'payment' && !result.cancelled"><h2 class="text-right balanced" translate="">API.DOC.DEMO_SUCCEED</h2><h4 class="gray" translate="">API.DOC.DEMO_RESULT</h4><p class="balanced-100-bg padding dark text-keep-lines">{{result.content}}</p><h4 class="gray"><span translate="">API.DOC.DEMO_RESULT_PEER</span> <b>{{result.node}}</b></h4></div><div class="item item-text-wrap" ng-if="result.type === 'payment' && result.cancelled"><h2 class="text-right assertive" translate="">API.DOC.DEMO_CANCELLED</h2></div><div class="item item-divider no-border"><p translate="">API.DOC.INTEGRATE_DIVIDER</p></div><div class="item item-text-wrap"><p translate="">API.DOC.TRANSFER.EXAMPLES_HELP</p><div class="row responsive-sm"><div class="col col-20 text-italic"><span translate="">API.DOC.TRANSFER.EXAMPLE_BUTTON</span></div><div class="col gray no-border"><p><i class="icon ion-code"></i> <span translate="">API.DOC.INTEGRATE_CODE</span></p><div class="item item-input"><textarea class="gray" select-on-click="" rows="5" ng-model="transferButton.html" ng-model-options="{ debounce: 650 }"></textarea></div><p class="padding-top"><i class="icon ion-eye"></i> <span translate="">API.DOC.INTEGRATE_RESULT</span></p><div class="padding-left" bind-notifier="{ notifierKey:watchedExpression }"><ng-bind-html ng-bind-html="transferButton.html|trustAsHtml"></ng-bind-html></div></div></div><div class="row responsive-sm"><div class="col gray no-border"><p class="padding-top"><a class="positive" ng-click="transferButton.showParameters=!transferButton.showParameters"><i class="icon ion-wrench"></i> <span translate="">API.DOC.INTEGRATE_PARAMETERS</span> <i class="icon" ng-class="{'ion-arrow-down-b': !transferButton.showParameters, 'ion-arrow-up-b': transferButton.showParameters}"></i></a></p><div ng-if="transferButton.showParameters" class="padding-left"><form id="transferForm" class="stable-bg padding"><p class="padding-top"><i class="icon ion-key"></i> {{'API.DOC.TRANSFER.PARAM_PUBKEY' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.pubkey" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.PARAM_PUBKEY_HELP'|translate}}"></label><p class="padding-top"><i class="icon ion-pricetag"></i> {{'API.DOC.TRANSFER.PARAM_AMOUNT' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.amount" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.PARAM_AMOUNT_HELP'|translate}}"></label><p class="padding-top"><i class="icon ion-flag"></i> {{'API.DOC.TRANSFER.PARAM_COMMENT' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.comment" placeholder="{{'API.DOC.TRANSFER.PARAM_COMMENT'|translate}}"></label><p class="padding-top"><i class="icon ion-ios-world-outline"></i> {{'API.DOC.TRANSFER.PARAM_NAME' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.name" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.PARAM_NAME'|translate}}"></label><p class="padding-top"><i class="icon ion-key"></i> {{'API.DOC.TRANSFER.PARAM_PREFERRED_NODE' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.preferred_node" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.PARAM_PREFERRED_NODE_HELP'|translate}}"></label><p class="padding-top"><i class="icon ion-arrow-return-left"></i> {{'API.DOC.TRANSFER.PARAM_REDIRECT_URL' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.redirect_url" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.PARAM_REDIRECT_URL'|translate}}"></label><p class="padding-top"><i class="icon ion-backspace"></i> {{'API.DOC.TRANSFER.PARAM_CANCEL_URL' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferData.cancel_url" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.PARAM_CANCEL_URL'|translate}}"></label><p class="padding-top"><a class="positive" ng-click="transferButton.style.enable=!transferButton.style.enable"><i class="icon" ng-class="{'ion-android-checkbox-outline': transferButton.style.enable, 'ion-android-checkbox-outline-blank': !transferButton.style.enable}"></i> <span translate="">API.DOC.TRANSFER.EXAMPLE_BUTTON_DEFAULT_STYLE</span></a></p><div ng-if="transferButton.style.enable"><p class="padding-top"><i class="icon ion-image"></i> {{'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_ICON' | translate}} :</p><label class="item item-input item-select"><select class="stable-bg dark" ng-model="transferButton.style.icon" style="width: 100%; max-width: 100%" ng-options="l as (l.label | translate) for l in transferButton.icons track by l.filename"></select></label><p class="padding-top"><i class="icon ion-quote"></i> {{'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_HELP' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.text" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_HELP'|translate}}"></label><p class="padding-top"><i class="icon ion-paintbucket"></i> {{'API.DOC.TRANSFER.EXAMPLE_BUTTON_BG_COLOR' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.bgColor" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.EXAMPLE_BUTTON_BG_COLOR_HELP'|translate}}"></label><p class="padding-top"><i class="icon ion-paintbrush"></i> {{'API.DOC.TRANSFER.EXAMPLE_BUTTON_FONT_COLOR' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.fontColor" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.EXAMPLE_BUTTON_FONT_COLOR_HELP'|translate}}"></label><p class="padding-top"><i class="icon ion-ios-crop-strong"></i> {{'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_WIDTH' | translate}} :</p><label class="item item-input"><input type="text" ng-model="transferButton.style.width" ng-model-options="{ debounce: 650 }" placeholder="{{'API.DOC.TRANSFER.EXAMPLE_BUTTON_TEXT_WIDTH_HELP'|translate}}"></label></div></form></div></div></div></div></div> \ No newline at end of file diff --git a/assets/www/templates/api/home.html b/assets/www/templates/api/home.html index 986783e471e861f4de01929367bae90e0b705a3b..c899062ecb8103170e8966b3e89a87aad68e9579 100644 --- a/assets/www/templates/api/home.html +++ b/assets/www/templates/api/home.html @@ -1 +1 @@ -<ion-view class="circle-bg-dark"><ion-nav-title><span class="title visible-xs visible-sm" translate="">API.HOME.TITLE</span></ion-nav-title><ion-nav-buttons side="right"></ion-nav-buttons><ion-content class="has-header no-padding-xs positive-900-bg"><br class="hidden-xs"><div class="light text-center"><h4 class="hidden-xs" translate="">API.HOME.MESSAGE</h4><h4 class="visible-xs padding" translate="">API.HOME.MESSAGE_SHORT</h4></div><br class="hidden-xs"><div class="row no-padding-xs"><div class="col"><div class="light-bg no-padding"><ng-include src="'templates/api/doc.html'"></ng-include></div></div></div><p class="visible-xs visible-sm light padding-top text-center">{{'COMMON.APP_NAME'|translate}} API - <a href="#" ng-click="showAboutModal($event)">v{{$root.config.version}}</a></p></ion-content></ion-view> \ No newline at end of file +<ion-view class="circle-bg-dark"><ion-nav-title><span class="title visible-xs visible-sm" translate="">API.HOME.TITLE</span></ion-nav-title><ion-nav-buttons side="right"></ion-nav-buttons><ion-content class="has-header no-padding-xs no-padding-sm positive-900-bg"><br class="hidden-xs"><div class="light text-center"><h4 class="hidden-xs" translate="">API.HOME.MESSAGE</h4><h4 class="visible-xs padding" translate="">API.HOME.MESSAGE_SHORT</h4></div><br class="hidden-xs"><div class="row no-padding-xs"><div class="col"><div class="light-bg no-padding"><ng-include src="'templates/api/doc.html'"></ng-include></div></div></div><p class="visible-xs visible-sm light padding-top text-center">{{'COMMON.APP_NAME'|translate}} API - <a href="#" ng-click="showAboutModal($event)">v{{$root.config.version}}</a></p></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/api/locales_popover.html b/assets/www/templates/api/locales_popover.html index 43b5b4ecb742de151f9463cc636286e3b518ca82..e9276debd77ae3962c6b560e0875b5abe81c4a74 100644 --- a/assets/www/templates/api/locales_popover.html +++ b/assets/www/templates/api/locales_popover.html @@ -1 +1 @@ -<ion-popover-view class="fit popover-locales" style="height: {{locales.length*48}}px"><ion-content scroll="false"><div class="list item-text-wrap block"><a ng-repeat="l in locales track by l.id" class="item item-icon-left ink" ng-click="changeLanguage(l.id)">{{l.label | translate}}</a></div></ion-content></ion-popover-view> \ No newline at end of file +<ion-popover-view class="fit popover-locales" style="height: {{locales.length*48}}px"><ion-content scroll="false"><div class="list item-text-wrap block"><a ng-repeat="l in locales track by l.id" class="item item-icon-left ink" ng-click="changeLanguage(l.id)"><i class="item-image avatar" style="border-radius: 0; background-image: url(https://www.countryflags.io/{{l.country}}/shiny/64.png)"></i> {{l.label | translate}}</a></div></ion-content></ion-popover-view> \ No newline at end of file diff --git a/assets/www/templates/api/transfer.html b/assets/www/templates/api/transfer.html index b7fe4d6ce5508a53f50ce663781b2e9915d7f11e..d39925dca0d61aba7f423b3cdf081fc24da6b64a 100644 --- a/assets/www/templates/api/transfer.html +++ b/assets/www/templates/api/transfer.html @@ -1 +1 @@ -<ion-view class="circle-bg-dark"><ion-nav-buttons side="left"><button class="button button-clear visible-xs" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button></ion-nav-buttons><ion-nav-title><span class="title visible-xs" translate="">API.TRANSFER.TITLE_SHORT</span></ion-nav-title><ion-nav-buttons side="right"><button class="button button-positive button-icon button-clear icon ion-android-done visible-xs" ng-click="doLogin()"></button></ion-nav-buttons><ion-content class="has-header no-padding-xs positive-900-bg"><br class="hidden-xs"><div class="row no-padding-xs"><div class="col no-padding-xs"><div class="light-bg"><h2 class="padding-top text-center hidden-xs" translate="">API.TRANSFER.TITLE</h2><div class="no-padding energized-100-bg" ng-if="demo"><div class="item item-icon-left item-text-wrap no-border"><i class="icon ion-information-circled positive"></i><p translate="">API.TRANSFER.DEMO.HELP</p></div></div><ng-include src="'templates/login/form_login.html'"></ng-include></div><br class="hidden-xs"><br class="hidden-xs"><div class="list padding no-padding-xs light-bg expert-mode"><div class="item"><p translate="">API.TRANSFER.SUMMARY</p></div><div class="item item-icon-left-padding item-tx no-border"><h2 translate="">API.TRANSFER.AMOUNT</h2><div class="badge item-note badge-calm" ng-bind-html="transferData.amount|formatAmount:{useRelative: false, currency: $root.currency.name}"></div><div class="badge badge-secondary" ng-bind-html="transferData.amount|formatAmount:{useRelative: true, currency: $root.currency.name}"></div></div><div class="item item-icon-left-padding" ng-if="transferData.name"><h2 translate="">API.TRANSFER.NAME</h2><div class="badge item-note">{{transferData.name}}</div></div><div class="item item-icon-left-padding item-text-wrap"><h2 translate="">API.TRANSFER.PUBKEY</h2><div class="badge"><span class="hidden-xs"><br class="visible-sm visible-md"><i class="icon ion-key"></i>{{transferData.pubkey}}</span> <span class="visible-xs" copy-on-click="{{transferData.pubkey}}"><br class="visible-xs"><i class="icon ion-key"></i> {{transferData.pubkey|formatPubkey}}</span></div></div><div class="item item-icon-left-padding"><h2 translate="">API.TRANSFER.COMMENT</h2><div class="badge item-note"><span class="hidden-xs"><br class="visible-sm visible-md">{{transferData.comment}}</span> <span class="visible-xs" copy-on-click="{{transferData.comment}}"><br>{{transferData.comment}}</span></div></div><div class="padding-bottom visible-xs"> </div></div></div></div><p class="visible-xs visible-sm light padding-top text-center">{{'COMMON.APP_NAME'|translate}} - <a href="#" ng-click="showAboutModal($event)">v{{$root.config.version}}</a></p></ion-content></ion-view> \ No newline at end of file +<ion-view class="circle-bg-dark"><ion-nav-buttons side="left"><button class="button button-clear visible-xs" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button></ion-nav-buttons><ion-nav-title><span class="title visible-xs" translate="">API.TRANSFER.TITLE_SHORT</span></ion-nav-title><ion-nav-buttons side="right"><button class="button button-positive button-icon button-clear icon ion-android-send visible-xs" ng-click="doLogin()"></button></ion-nav-buttons><ion-content class="has-header no-padding-xs positive-900-bg"><br class="hidden-xs"><div class="row no-padding-xs"><div class="col no-padding-xs"><div class="light-bg"><h2 class="padding-top text-center hidden-xs" translate="">API.TRANSFER.TITLE</h2><div class="no-padding energized-100-bg" ng-if="demo"><div class="item item-icon-left item-text-wrap no-border"><i class="icon ion-information-circled positive"></i><p translate="">API.TRANSFER.DEMO.HELP</p></div></div><ng-include src="'templates/login/form_login.html'"></ng-include></div><br class="hidden-xs"><br class="hidden-xs"><div class="list padding no-padding-xs light-bg"><div class="item"><p translate="">API.TRANSFER.SUMMARY</p></div><div class="item item-icon-left-padding item-tx no-border" ng-if="!transferData.amounts" style="min-height: 56px"><h2 translate="">API.TRANSFER.AMOUNT</h2><ion-spinner class="badge item-note" icon="android" ng-show="loading"></ion-spinner><div class="badge badge-calm ng-hide" ng-show="!loading" ng-bind-html="transferData.amount|formatAmount:{useRelative: false, currency: currency.name}"></div><div class="badge badge-secondary ng-hide" ng-show="!loading" ng-bind-html="transferData.amount|formatAmount:{useRelative: true, currency: currency.name, currentUD: currency.currentUD}"></div></div><label ng-if="transferData.amounts" style="min-height: 58px" class="item item-icon-left-padding item-input item-select item-tx no-border" ng-class="{ 'item-input-error': form.$submitted && !transferData.amount}"><div class="input-label"><span translate="">API.TRANSFER.AMOUNT</span></div><select ng-model="transferData.amount" required="true" ng-options="(amount |formatAmount:{useRelative: false, currency: currency.name}) for amount in transferData.amounts"></select><span class="badge badge-secondary ng-hide" ng-show="transferData.amount" ng-bind-html="transferData.amount|formatAmount:{useRelative: true, currency: currency.name, currentUD: currency.currentUD}"></span></label><div class="form-errors" ng-if="form.$submitted && !transferData.amount"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-icon-left-padding"><h2 translate="">API.TRANSFER.NAME</h2><div class="badge item-note">{{transferData.name}}</div></div><div class="item item-icon-left-padding item-text-wrap"><h2 translate="">API.TRANSFER.PUBKEY</h2><div class="badge"><span class="hidden-xs"><br class="visible-sm visible-md"><i class="icon ion-key"></i>{{transferData.pubkey}}</span> <span class="visible-xs" copy-on-click="{{transferData.pubkey}}"><br class="visible-xs"><i class="icon ion-key"></i> {{transferData.pubkey|formatPubkey}}</span></div></div><div class="item item-icon-left-padding"><h2 translate="">API.TRANSFER.COMMENT</h2><div class="badge item-note"><span class="hidden-xs"><br class="visible-sm visible-md">{{::transferData.comment}}</span> <span class="visible-xs" copy-on-click="{{transferData.comment}}"><br>{{::transferData.comment}}</span></div></div><div class="item item-icon-left-padding" ng-hide="error"><h2 translate="">API.TRANSFER.NODE</h2><div class="badge item-note" ng-if="!loading"><br class="visible-sm visible-md"><i class="icon ion-locked" ng-if="node.useSsl"></i> {{node.server}}</div></div><div class="center padding animate-fade-in animate-show-hide ng-hide" ng-show="!loading && error"><div class="card card-item padding"><p class="item-content item-text-wrap"><i class="icon ion-android-alert assertive"></i> <span class="dark" trust-as-html="'API.COMMON.CONNECTION_ERROR'|translate:node"></span></p><button type="button" class="button button-positive icon icon-left ion-refresh ink" ng-click="start()">{{'COMMON.BTN_REFRESH'|translate}}</button></div></div><div class="padding-bottom visible-xs"> </div></div></div></div><p class="visible-xs visible-sm light padding-top text-center">{{'COMMON.APP_NAME'|translate}} - <a href="#" ng-click="showAboutModal($event)">v{{$root.config.version}}</a></p></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/blockchain/item_block.html b/assets/www/templates/blockchain/item_block.html index 289c382409b4fbc84f76fb8d6e831ede8fa423e7..8ea53c43b5a5f1f8272a1628413871e2cd4c1413 100644 --- a/assets/www/templates/blockchain/item_block.html +++ b/assets/www/templates/blockchain/item_block.html @@ -1 +1 @@ -<a name="block-{{:rebind:block.number}}"></a><ion-item id="block-{{:rebind:block.number}}" class="item item-icon-left item-block {{::ionItemClass}}" ng-class="{'ink': !block.empty||!block.compacted, 'item-block-empty': block.empty, 'compacted': block.compacted && compactMode}" ng-click="selectBlock(block)"><i class="icon ion-cube stable" ng-if=":rebind:(!block.empty && !block.avatar)"></i> <i class="avatar" ng-if=":rebind:!block.empty && block.avatar" style="background-image: url('{{:rebind:block.avatar.src}}')"></i><div class="row no-padding" ng-if=":rebind:!block.compacted || !compactMode"><div class="col"><h4 ng-class="{'gray': block.compacted, 'dark': !block.compacted}"><i class="ion-clock"></i> {{:rebind:block.medianTime|formatDate}}</h4><h4 ng-if="!block.empty"><ng-if ng-if=":rebind:block.joinersCount||(block.excludedCount-block.revokedCount)"><i class="dark ion-person"></i> <span class="dark" ng-if=":rebind:block.joinersCount">+{{:rebind:block.joinersCount}}</span> <span class="dark" ng-if=":rebind:block.excludedCount">-{{:rebind:block.excludedCount-block.revokedCount}}</span></ng-if><span class="dark" ng-if=":rebind:block.revokedCount" class="assertive"><i class="ion-minus-circled"></i> {{:rebind:block.revokedCount}} </span> <span class="dark" ng-if=":rebind:block.activesCount" class="gray"><i class="gray ion-refresh"></i> {{:rebind:block.activesCount}} </span> <span class="dark" ng-if=":rebind:block.certificationsCount"><i class="ion-ribbon-a"></i> {{:rebind:block.certificationsCount}} </span> <span class="dark" ng-if=":rebind:block.dividend" class="gray"><i class="gray ion-arrow-up-c"></i> {{'COMMON.UD'|translate}} </span> <span class="dark" ng-if=":rebind:block.transactionsCount"><i class="ion-card">{{:rebind:block.transactionsCount}}</i></span></h4></div><div class="col col-33 positive hidden-md"><h4><i class="ion-person"></i> {{:rebind:block.name||block.uid}}</h4></div><div class="col col-20"><span class="badge" ng-class="{'badge-balanced': !$index , 'badge-calm': $index && !block.compacted && !block.empty}">{{:rebind:block.number|formatInteger}}</span></div></div></ion-item> \ No newline at end of file +<a name="block-{{:rebind:block.number}}"></a><ion-item id="block-{{:rebind:block.number}}" class="item item-icon-left item-block {{::ionItemClass}}" ng-class="{'ink': !block.empty||!block.compacted, 'item-block-empty': block.empty, 'compacted': block.compacted && compactMode}" ng-click="selectBlock(block)"><i class="icon ion-cube stable" ng-if=":rebind:(!block.empty && !block.avatar)"></i> <i class="avatar" ng-if=":rebind:!block.empty && block.avatar" style="background-image: url('{{:rebind:block.avatar.src}}')"></i><div class="row no-padding" ng-if=":rebind:!block.compacted || !compactMode"><div class="col" style="min-width: 110px; max-width: 130px"><h4 ng-class="{'gray': block.compacted, 'dark': !block.compacted}"><i class="ion-clock"></i> {{:rebind:block.medianTime|medianDate}}</h4><h4 ng-if="!block.empty"><ng-if ng-if=":rebind:block.joinersCount||(block.excludedCount-block.revokedCount)"><i class="dark ion-person"></i> <span class="dark" ng-if=":rebind:block.joinersCount">+{{:rebind:block.joinersCount}}</span> <span class="dark" ng-if=":rebind:block.excludedCount">-{{:rebind:block.excludedCount-block.revokedCount}}</span></ng-if><span class="dark" ng-if=":rebind:block.revokedCount" class="assertive"><i class="ion-minus-circled"></i> {{:rebind:block.revokedCount}} </span> <span class="dark" ng-if=":rebind:block.activesCount" class="gray"><i class="gray ion-refresh"></i> {{:rebind:block.activesCount}} </span> <span class="dark" ng-if=":rebind:block.certificationsCount"><i class="ion-ribbon-a"></i> {{:rebind:block.certificationsCount}} </span> <span class="dark" ng-if=":rebind:block.dividend" class="gray"><i class="gray ion-arrow-up-c"></i> {{'COMMON.UD'|translate}} </span> <span class="dark" ng-if=":rebind:block.transactionsCount"><i class="ion-card">{{:rebind:block.transactionsCount}}</i></span></h4></div><div class="col positive hidden-md"><h4><i class="ion-person"></i> {{:rebind:block.name||block.uid}}</h4></div><div class="col col-20"><span class="badge" ng-class="{'badge-balanced': !$index , 'badge-calm': $index && !block.compacted && !block.empty}">{{:rebind:block.number|formatInteger}}</span></div></div></ion-item> \ No newline at end of file diff --git a/assets/www/templates/blockchain/item_block_empty_lg.html b/assets/www/templates/blockchain/item_block_empty_lg.html index 1da8d9b2131ed07134880d64a6fd3859a1e83654..160cffbc1f29130888eff942e55d1d1e0ba4f855 100644 --- a/assets/www/templates/blockchain/item_block_empty_lg.html +++ b/assets/www/templates/blockchain/item_block_empty_lg.html @@ -1 +1 @@ -<a name="block-{{::block.number}}"></a><div id="block-{{::block.number}}" class="item item-block item-icon-left item-block-empty" ng-class="{'compacted': block.compacted && compactMode}" ng-click="selectBlock(block)"><div class="row no-padding" ng-if=":rebind:!block.compacted || !compactMode"><div class="col"><h3 class="gray"><i class="ion-clock"></i> {{:rebind:block.medianTime|formatDate}}</h3></div><div class="col"><h3><span class="gray" ng-if=":rebind:expertMode"><i class="ion-key"></i> {{:rebind:block.issuer|formatPubkey}} </span><span class="positive"><i class="ion-person"></i> {{:rebind:block.name||block.uid}}</span></h3></div><div class="col col-20"></div><div class="col col-20"><span class="badge" ng-class="{'badge-balanced': !$index && search.type=='last'}">{{block.number|formatInteger}}</span></div></div></div> \ No newline at end of file +<a name="block-{{::block.number}}"></a><div id="block-{{::block.number}}" class="item item-block item-icon-left item-block-empty" ng-class="{'compacted': block.compacted && compactMode}" ng-click="selectBlock(block)"><div class="row no-padding" ng-if=":rebind:!block.compacted || !compactMode"><div class="col"><h3 class="gray"><i class="ion-clock"></i> {{:rebind:block.medianTime|medianDate}}</h3></div><div class="col"><h3><span class="gray" ng-if=":rebind:expertMode"><i class="ion-key"></i> {{:rebind:block.issuer|formatPubkey}} </span><span class="positive"><i class="ion-person"></i> {{:rebind:block.name||block.uid}}</span></h3></div><div class="col col-20"></div><div class="col col-20"><span class="badge" ng-class="{'badge-balanced': !$index && search.type=='last'}">{{block.number|formatInteger}}</span></div></div></div> \ No newline at end of file diff --git a/assets/www/templates/blockchain/item_block_lg.html b/assets/www/templates/blockchain/item_block_lg.html index ae36f3f97486296fdf006b786761530031de164e..e2c2c92a964869226a0fb3ccf2b3506aa2be69a4 100644 --- a/assets/www/templates/blockchain/item_block_lg.html +++ b/assets/www/templates/blockchain/item_block_lg.html @@ -1 +1 @@ -<ion-item id="block-{{::block.number}}" class="item item-block item-icon-left ink {{::ionItemClass}}" ng-class="{{::ionItemClass}}" ng-click="selectBlock(block)"><i class="icon ion-cube stable" ng-if=":rebind:!block.avatar"></i> <i class="avatar" ng-if=":rebind:!block.empty && block.avatar" style="background-image: url('{{:rebind:block.avatar.src}}')"></i><div class="row no-padding"><div class="col"><h3 class="dark"><i class="ion-clock"></i> {{:rebind:block.medianTime|formatDate}}</h3><h4 class="gray">{{:rebind:'BLOCKCHAIN.HASH'|translate}} {{:rebind:block.hash|formatHash}}</h4></div><div class="col"><h3><span class="gray" ng-if=":rebind:expertMode"><i class="ion-key"></i> {{:rebind:block.issuer|formatPubkey}} </span><span class="positive"><i class="ion-person"></i> {{:rebind:block.name||block.uid}}</span></h3></div><div class="col col-20"><small><ng-if ng-if=":rebind:block.joinersCount||(block.excludedCount-block.revokedCount)"><i class="ion-person"></i> <span ng-if=":rebind:block.joinersCount">+{{:rebind:block.joinersCount}}</span> <span ng-if=":rebind:block.excludedCount">-{{:rebind:block.excludedCount-block.revokedCount}}</span> </ng-if><span ng-if=":rebind:block.revokedCount" class="assertive"><i class="ion-minus-circled"></i> -{{:rebind:block.revokedCount}} </span> <span ng-if=":rebind:block.activesCount"><i class="ion-refresh"></i> {{:rebind:block.activesCount}} </span> <span ng-if=":rebind:block.certificationsCount"><i class="ion-ribbon-a"></i> {{:rebind:block.certificationsCount}} </span> <span ng-if=":rebind:block.dividend"><i class="gray ion-arrow-up-c"></i> {{:rebind:'COMMON.UD'|translate}} </span> <span ng-if=":rebind:block.transactionsCount"><i class="ion-card">{{:rebind:block.transactionsCount}}</i> </span></small></div><div class="col col-20"><span class="badge" ng-class="{'badge-balanced': !$index && search.type=='last', 'badge-calm': ($index || search.type!='last')&& !block.compacted && !block.empty}">{{:rebind:block.number}}</span></div></div></ion-item> \ No newline at end of file +<ion-item id="block-{{::block.number}}" class="item item-block item-icon-left ink {{::ionItemClass}}" ng-class="{{::ionItemClass}}" ng-click="selectBlock(block)"><i class="icon ion-cube stable" ng-if=":rebind:!block.avatar"></i> <i class="avatar" ng-if=":rebind:!block.empty && block.avatar" style="background-image: url('{{:rebind:block.avatar.src}}')"></i><div class="row no-padding"><div class="col"><h3 class="dark"><i class="ion-clock"></i> {{:rebind:block.medianTime|medianDate}}</h3><h4 class="gray">{{:rebind:'BLOCKCHAIN.HASH'|translate}} {{:rebind:block.hash|formatHash}}</h4></div><div class="col"><h3><span class="gray" ng-if=":rebind:expertMode"><i class="ion-key"></i> {{:rebind:block.issuer|formatPubkey}} </span><span class="positive"><i class="ion-person"></i> {{:rebind:block.name||block.uid}}</span></h3></div><div class="col col-20"><small><ng-if ng-if=":rebind:block.joinersCount||(block.excludedCount-block.revokedCount)"><i class="ion-person"></i> <span ng-if=":rebind:block.joinersCount">+{{:rebind:block.joinersCount}}</span> <span ng-if=":rebind:block.excludedCount">-{{:rebind:block.excludedCount-block.revokedCount}}</span> </ng-if><span ng-if=":rebind:block.revokedCount" class="assertive"><i class="ion-minus-circled"></i> -{{:rebind:block.revokedCount}} </span> <span ng-if=":rebind:block.activesCount"><i class="ion-refresh"></i> {{:rebind:block.activesCount}} </span> <span ng-if=":rebind:block.certificationsCount"><i class="ion-ribbon-a"></i> {{:rebind:block.certificationsCount}} </span> <span ng-if=":rebind:block.dividend"><i class="gray ion-arrow-up-c"></i> {{:rebind:'COMMON.UD'|translate}} </span> <span ng-if=":rebind:block.transactionsCount"><i class="ion-card">{{:rebind:block.transactionsCount}}</i> </span></small></div><div class="col col-20"><span class="badge" ng-class="{'badge-balanced': !$index && search.type=='last', 'badge-calm': ($index || search.type!='last')&& !block.compacted && !block.empty}">{{:rebind:block.number}}</span></div></div></ion-item> \ No newline at end of file diff --git a/assets/www/templates/blockchain/list_blocks.html b/assets/www/templates/blockchain/list_blocks.html index 88496c6c00624e646ae23a0b17ef8d0878a95e31..f621d47a749a868c243cc0d0f4092afe5a0e3b22 100644 --- a/assets/www/templates/blockchain/list_blocks.html +++ b/assets/www/templates/blockchain/list_blocks.html @@ -1 +1 @@ -<div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><ion-list class="padding padding-xs list-blocks" ng-class="::motion.ionListClass"><div class="padding gray" ng-if="!search.loading && !search.results.length" translate>BLOCKCHAIN.LOOKUP.NO_BLOCK</div><ng-repeat ng-repeat="block in :rebind:search.results track by block.number" ng-include="'templates/blockchain/item_block.html'"></ng-repeat></ion-list><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll> \ No newline at end of file +<div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><ion-list class="padding padding-xs list-blocks {{::motion.ionListClass}}"><div class="padding gray" ng-if="!search.loading && !search.results.length" translate>BLOCKCHAIN.LOOKUP.NO_BLOCK</div><ng-repeat ng-repeat="block in :rebind:search.results track by block.number" ng-include="'templates/blockchain/item_block.html'"></ng-repeat></ion-list><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll> \ No newline at end of file diff --git a/assets/www/templates/blockchain/list_blocks_lg.html b/assets/www/templates/blockchain/list_blocks_lg.html index 5875417441c01db89058c7455ee0b5144ae3220c..dd1d806f5636b46ed16028695cf077bcf3182df1 100644 --- a/assets/www/templates/blockchain/list_blocks_lg.html +++ b/assets/www/templates/blockchain/list_blocks_lg.html @@ -1 +1 @@ -<div class="padding padding-xs" style="display: block; height: 100px"><h4 translate>BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4><div class="pull-right"><a class="button button-text button-small ink" ng-class="{'button-text-positive': compactMode, 'button-text-stable': !compactMode}" ng-click="toggleCompactMode()"><i class="icon ion-navicon"></i> <b class="ion-arrow-down-b" style="position: absolute; top: -2px; left: 4px; font-size: 8px"></b> <b class="ion-arrow-up-b" style="position: absolute; top: 10px; left: 4px; font-size: 8px"></b> <span>{{'BLOCKCHAIN.LOOKUP.BTN_COMPACT'|translate}}</span></a></div></div><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><ion-list class="padding padding-xs list-blocks" ng-class="::motion.ionListClass"><div class="padding gray" ng-if="!search.loading && !search.results.length" translate>BLOCKCHAIN.LOOKUP.NO_BLOCK</div><ng-repeat ng-repeat="block in search.results" ng-include="!block.empty ? 'templates/blockchain/item_block_lg.html' : 'templates/blockchain/item_block_empty_lg.html'"></ng-repeat></ion-list><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll> \ No newline at end of file +<div class="padding padding-xs" style="display: block; height: 100px"><h4 translate>BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4><div class="pull-right"><a class="button button-text button-small ink" ng-class="{'button-text-positive': compactMode, 'button-text-stable': !compactMode}" ng-click="toggleCompactMode()"><i class="icon ion-navicon"></i> <b class="ion-arrow-down-b" style="position: absolute; top: -2px; left: 4px; font-size: 8px"></b> <b class="ion-arrow-up-b" style="position: absolute; top: 10px; left: 4px; font-size: 8px"></b> <span>{{'BLOCKCHAIN.LOOKUP.BTN_COMPACT'|translate}}</span></a></div></div><div class="center padding" ng-if="search.loading"><ion-spinner icon="android"></ion-spinner></div><ion-list class="padding padding-xs list-blocks {{::motion.ionListClass}}"><div class="padding gray" ng-if="!search.loading && !search.results.length" translate>BLOCKCHAIN.LOOKUP.NO_BLOCK</div><ng-repeat ng-repeat="block in search.results" ng-include="!block.empty ? 'templates/blockchain/item_block_lg.html' : 'templates/blockchain/item_block_empty_lg.html'"></ng-repeat></ion-list><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="1%"></ion-infinite-scroll> \ No newline at end of file diff --git a/assets/www/templates/blockchain/lookup_lg.html b/assets/www/templates/blockchain/lookup_lg.html index ee9471982f32e06770b25b9f54991c44b6a6ad24..4c9917965b97cb1548f6fa10146e960819c2ba15 100644 --- a/assets/www/templates/blockchain/lookup_lg.html +++ b/assets/www/templates/blockchain/lookup_lg.html @@ -1 +1 @@ -<ion-view><ion-nav-title><span translate>BLOCKCHAIN.LOOKUP.TITLE</span></ion-nav-title><ion-content class="padding no-padding-xs" scroll="true"><ng-include src="'templates/blockchain/list_blocks_lg.html'"></ng-include></ion-content></ion-view> \ No newline at end of file +<ion-view><ion-nav-title><span translate>BLOCKCHAIN.LOOKUP.TITLE</span></ion-nav-title><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><ng-include src="'templates/blockchain/list_blocks_lg.html'"></ng-include></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/blockchain/unlock_condition_popover.html b/assets/www/templates/blockchain/unlock_condition_popover.html index c4e014fe2fe81be0101d9515f42f7a4810a6c11f..036f2dd282477285b0a7aa6ce786b51a3d75c99a 100644 --- a/assets/www/templates/blockchain/unlock_condition_popover.html +++ b/assets/www/templates/blockchain/unlock_condition_popover.html @@ -1 +1 @@ -<ion-popover-view class="fit"><ion-header-bar><h1 class="title" translate>BLOCKCHAIN.VIEW.TX_OUTPUT_UNLOCK_CONDITIONS</h1></ion-header-bar><ion-content scroll="true"><div class="row" ng-repeat="condition in popoverData.unlockConditions track by $index" ng-style="::condition.style"><span class="gray" ng-if="::condition.operator">{{::'BLOCKCHAIN.VIEW.TX_OUTPUT_OPERATOR.'+condition.operator|translate}} </span><div ng-if="::condition.type=='SIG'"><i class="icon ion-key dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.SIG' | translate"></span> <a ng-click="goState('app.wot_identity', {pubkey:condition.value})" style="text-decoration: none" class="positive">{{condition.value|formatPubkey}}</a></div><div ng-if="::condition.type=='XHX'"><i class="icon ion-lock-combination dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.XHX' | translate"></span> <a copy-on-click="{{::condition.value}}" class="positive">{{::condition.value|formatPubkey}}...</a></div><div ng-if="condition.type=='CSV'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CSV' | translate"></span> {{::condition.value|formatDuration}}</div><div ng-if="condition.type=='CLTV'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CLTV' | translate"></span> {{::condition.value|formatDate}}</div></div></ion-content></ion-popover-view> \ No newline at end of file +<ion-popover-view class="fit"><ion-header-bar><h1 class="title" translate>BLOCKCHAIN.VIEW.TX_OUTPUT_UNLOCK_CONDITIONS</h1></ion-header-bar><ion-content scroll="true"><div class="row" ng-repeat="condition in popoverData.unlockConditions track by $index" ng-style="::condition.style"><span class="gray" ng-if="::condition.operator">{{::'BLOCKCHAIN.VIEW.TX_OUTPUT_OPERATOR.'+condition.operator|translate}} </span><div ng-if="::condition.type=='SIG'"><i class="icon ion-key dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.SIG' | translate"></span> <a ng-click="goState('app.wot_identity', {pubkey:condition.value})" style="text-decoration: none" class="positive">{{condition.value|formatPubkey}}</a></div><div ng-if="::condition.type=='XHX'"><i class="icon ion-lock-combination dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.XHX' | translate"></span> <a copy-on-click="{{::condition.value}}" class="positive">{{::condition.value|formatPubkey}}...</a></div><div ng-if="condition.type=='CSV'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CSV' | translate"></span> {{::condition.value|formatDuration}}</div><div ng-if="condition.type=='CLTV'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CLTV' | translate"></span> {{::condition.value|medianDate}}</div></div></ion-content></ion-popover-view> \ No newline at end of file diff --git a/assets/www/templates/blockchain/view_block.html b/assets/www/templates/blockchain/view_block.html index 8f360a53d4d0a326abc526edc04a3f22338c31ec..58e764ef51d9dd17a254e8e7293aad5c0ef16535 100644 --- a/assets/www/templates/blockchain/view_block.html +++ b/assets/www/templates/blockchain/view_block.html @@ -1 +1 @@ -<ion-view><ion-nav-title><span class="title visible-xs visible-sm" ng-if="number=='current'">{{'BLOCKCHAIN.VIEW.TITLE_CURRENT'|translate}}</span> <span class="title visible-xs visible-sm" ng-if="number!='current'">{{'BLOCKCHAIN.VIEW.TITLE'|translate:formData}}</span></ion-nav-title><ion-content class="no-padding-xs" scroll="true"><div class="row no-padding"><div class="col no-padding"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><ion-list class="item-text-wrap no-padding-xs" ng-if="!loading"><div class="item item-text-wrap"><h3><span class="dark"><i class="icon ion-clock"></i> {{formData.medianTime | formatDate}} </span><span class="gray">| {{formData.medianTime | formatFromNow}}</span></h3><h3><span class="dark"><i class="icon ion-lock-combination"></i> {{'BLOCKCHAIN.VIEW.COMPUTED_BY'|translate}} </span><a class="positive" ui-sref="app.wot_identity({pubkey:issuer.pubkey, uid: issuer.uid})"><i class="icon ion-person positive"></i> {{issuer.name||issuer.uid}} <span class="gray" ng-if="issuer.name">({{issuer.uid}})</span></a></h3><h3><a ng-click="openRawBlock($event)"><i class="icon ion-share"></i> {{'BLOCKCHAIN.VIEW.SHOW_RAW'|translate}}</a></h3></div><span class="item item-divider">{{'BLOCKCHAIN.VIEW.TECHNICAL_DIVIDER' | translate}}</span><ion-item class="item-icon-left item-text-wrap" ng-if="!compactMode || $root.settings.expertMode"><i class="icon ion-gear-b"></i> {{'BLOCKCHAIN.VIEW.VERSION'|translate}} <span class="badge badge-stable">{{::formData.version}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="!compactMode || $root.settings.expertMode" copy-on-click="{{::formData.powMin}}"><i class="icon ion-lock-combination"></i> {{'BLOCKCHAIN.VIEW.POW_MIN'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.POW_MIN_HELP'|translate}}</h4><span class="badge badge-stable">{{::formData.powMin}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" copy-on-click="{{::formData.hash}}"><i class="icon ion-pound"></i> {{'BLOCKCHAIN.VIEW.HASH'|translate}}<h5 class="visible-xs visible-sm dark">{{::formData.hash}}</h5></ion-item><span class="item item-divider">{{'BLOCKCHAIN.VIEW.DATA_DIVIDER' | translate}}</span><ion-item ng-if="compactMode && formData.empty" class="item-icon-left item-text-wrap">{{'BLOCKCHAIN.VIEW.EMPTY'|translate}}</ion-item><ion-item ng-if="!compactMode || formData.dividend" class="item-icon-left item-text-wrap" copy-on-click="{{::formData.dividend/100}}"><i class="icon ion-arrow-up-c"></i><div class="col col-60">{{'COMMON.UNIVERSAL_DIVIDEND'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.UNIVERSAL_DIVIDEND_HELP'|translate: {membersCount: formData.membersCount} }}</h4></div><span class="badge badge-balanced" ng-if="formData.dividend">+1 <span ng-bind-html="formData.currency|currencySymbol: {useRelative: true} "></span> / {{'COMMON.MEMBER'|translate|lowercase}} </span><span class="badge badge-stable" ng-if="!formData.dividend">0</span> <span class="badge badge-secondary" ng-if="formData.dividend">+ {{formData.dividend| formatAmount: {currency: formData.currency, useRelative: false} }} / {{'COMMON.MEMBER'|translate|lowercase}}</span></ion-item><ng-if ng-if="!compactMode || formData.identitiesCount"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-clock" style="position: absolute; top: 16px; left: 39px; font-size: 12px"></b> {{'BLOCKCHAIN.VIEW.IDENTITIES_COUNT'|translate}} <span class="badge badge-balanced" ng-if="formData.identitiesCount">+{{::formData.identitiesCount}}</span> <span class="badge badge-stable" ng-if="!formData.identitiesCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.identitiesCount"><ion-item ng-repeat="identity in ::formData.identities" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.joinersCount"><ion-item class="item-icon-left"><i class="icon ion-person-add"></i> {{'BLOCKCHAIN.VIEW.JOINERS_COUNT'|translate}} <span class="badge badge-balanced" ng-if="formData.joinersCount">+{{::formData.joinersCount}}</span> <span class="badge badge-stable" ng-if="!formData.joinersCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.joinersCount"><ion-item ng-repeat="identity in ::formData.joiners" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.activesCount"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-refresh" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{'BLOCKCHAIN.VIEW.ACTIVES_COUNT'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.ACTIVES_COUNT_HELP'|translate}}</h4><span class="badge badge-balanced" ng-if="formData.activesCount">{{::formData.activesCount}}</span> <span class="badge badge-stable" ng-if="!formData.activesCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.activesCount"><ion-item ng-repeat="identity in ::formData.actives" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || (formData.excludedCount-formData.revokedCount)"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-close dark" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{'BLOCKCHAIN.VIEW.EXCLUDED_COUNT'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.EXCLUDED_COUNT_HELP'|translate}}</h4><span class="badge badge-assertive" ng-if="formData.excludedCount-formData.revokedCount">-{{::formData.excludedCount-formData.revokedCount}}</span> <span class="badge badge-stable" ng-if="!(formData.excludedCount-formData.revokedCount)">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.excludedCount"><ion-item ng-repeat="identity in ::formData.excluded" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.leaversCount"><ion-item class="item-icon-left" ng-if="!compactMode || formData.leaversCount"><i class="icon ion-person"></i> <b class="ion-minus" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{'BLOCKCHAIN.VIEW.LEAVERS_COUNT'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.LEAVERS_COUNT_HELP'|translate}}</h4><span class="badge badge-assertive" ng-if="formData.leaversCount">-{{::formData.leaversCount}}</span> <span class="badge badge-stable" ng-if="!formData.leaversCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.leaversCount"><ion-item ng-repeat="identity in ::formData.leavers" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.revokedCount"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-minus-circled assertive" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{'BLOCKCHAIN.VIEW.REVOKED_COUNT'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.REVOKED_COUNT_HELP'|translate}}</h4><span class="badge badge-balanced" ng-if="formData.revokedCount">-{{::formData.revokedCount}}</span> <span class="badge badge-stable" ng-if="!formData.revokedCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.revokedCount"><ion-item ng-repeat="identity in ::formData.revoked" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.certificationsCount"><ion-item class="item-icon-left"><i class="icon ion-ribbon-a"></i> {{'BLOCKCHAIN.VIEW.CERT_COUNT'|translate}} <span class="badge badge-stable" ng-class="{'badge-positive':formData.certificationsCount}">{{::formData.certificationsCount}}</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding no-padding-xs" ng-if="formData.certificationsCount"><div ng-repeat="(key, certs) in formData.certifications" class="item item-border-large item-small-height"><div class="row no-padding"><div class="col col-center no-padding"><ng-repeat ng-repeat="cert in certs"><ng-include src="'templates/blockchain/link_identity.html'" onload="identity=cert.from"></ng-include><br></ng-repeat></div><div class="col col-10 col-center gray text-center no-padding"><h2><i class="icon ion-arrow-right-a"></i></h2></div><div class="col col-40 col-center no-padding" ng-include="'templates/blockchain/link_identity.html'" onload="identity=certs[0].to"></div></div></div></div></ng-if><ng-if ng-if="!compactMode || formData.transactionsCount"><ion-item class="item-icon-left"><i class="icon ion-card"></i> {{'BLOCKCHAIN.VIEW.TX_COUNT'|translate}} <span class="badge badge-stable" ng-class="{'badge-positive':formData.transactionsCount}">{{::formData.transactionsCount}}</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding no-padding-xs" ng-if="formData.transactionsCount"><div ng-repeat="tx in ::formData.transactions" class="item item-small-height item-border-large"><div class="row no-padding" style="padding-top: 3px"><div class="col col-40 col-center no-padding list no-margin"><div ng-repeat="identity in ::tx.issuers" class="item no-padding item-small-height"><ng-include src="'templates/blockchain/link_identity.html'"></ng-include></div></div><div class="col col-10 col-center gray text-center no-padding"><h2><i class="icon ion-arrow-right-a"></i></h2></div><div class="col no-padding padding-right no-padding-xs col-text-wrap list no-margin"><span class="gray" ng-if="tx.toHimself" translate="">BLOCKCHAIN.VIEW.TX_TO_HIMSELF</span><div ng-repeat="output in ::tx.outputs" class="item no-padding item-small-height"><ng-include ng-if="::output.pubkey" src="'templates/blockchain/link_identity.html'" onload="identity=output"></ng-include><span ng-if="::!output.pubkey && output.unlockFunctions"><i class="icon ion-locked"></i> (<a ng-click="showUnlockConditionPopover(output, $event)"> <i ng-repeat="unlockFunction in ::output.unlockFunctions" ng-class="::{'ion-key': (unlockFunction=='SIG'), 'ion-clock': (unlockFunction=='CSV' || unlockFunction=='CLTV'), 'ion-lock-combination': (unlockFunction=='XHX') }" class="icon"></i> </a>) </span><span class="badge badge-balanced" ng-bind-html="::output.amount | formatAmount:{currency: formData.currency, useRelative: false} "></span></div></div></div></div></div></ng-if></ion-list></div><div class="col col-15 hidden-xs"></div></div></ion-content></ion-view> \ No newline at end of file +<ion-view><ion-nav-title><span class="title visible-xs visible-sm" ng-if="number=='current'">{{'BLOCKCHAIN.VIEW.TITLE_CURRENT'|translate}}</span> <span class="title visible-xs visible-sm" ng-if="number!='current'">{{'BLOCKCHAIN.VIEW.TITLE'|translate:formData}}</span></ion-nav-title><ion-content class="no-padding-xs no-padding-sm" scroll="true"><div class="row no-padding"><div class="col no-padding"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="list item-text-wrap no-padding-xs" ng-if="!loading"><div class="item item-text-wrap"><h3><span class="dark"><i class="icon ion-clock"></i> {{formData.medianTime | medianFromNowAndDate}}</span></h3><h3><span class="dark"><i class="icon ion-lock-combination"></i> {{'BLOCKCHAIN.VIEW.COMPUTED_BY'|translate}} </span><a class="positive" ui-sref="app.wot_identity({pubkey:issuer.pubkey, uid: issuer.uid})"><i class="icon ion-person positive"></i> {{issuer.name||issuer.uid}} <span class="gray" ng-if="issuer.name">({{issuer.uid}})</span></a></h3><h3><a ng-click="openRawBlock($event)"><i class="icon ion-share"></i> {{'BLOCKCHAIN.VIEW.SHOW_RAW'|translate}}</a></h3></div><span class="item item-divider">{{'BLOCKCHAIN.VIEW.TECHNICAL_DIVIDER' | translate}}</span><ion-item class="item-icon-left item-text-wrap" ng-if="!compactMode || $root.settings.expertMode"><i class="icon ion-gear-b"></i> {{'BLOCKCHAIN.VIEW.VERSION'|translate}} <span class="badge badge-stable">{{::formData.version}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="!compactMode || $root.settings.expertMode" copy-on-click="{{::formData.powMin}}"><i class="icon ion-lock-combination"></i> {{'BLOCKCHAIN.VIEW.POW_MIN'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.POW_MIN_HELP'|translate}}</h4><span class="badge badge-stable">{{::formData.powMin}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" copy-on-click="{{::formData.hash}}"><i class="icon ion-pound"></i> {{'BLOCKCHAIN.VIEW.HASH'|translate}}<h5 class="visible-xs visible-sm dark">{{::formData.hash}}</h5></ion-item><span class="item item-divider">{{'BLOCKCHAIN.VIEW.DATA_DIVIDER' | translate}}</span><ion-item ng-if="compactMode && formData.empty" class="item-icon-left item-text-wrap">{{'BLOCKCHAIN.VIEW.EMPTY'|translate}}</ion-item><ion-item ng-if="!compactMode || formData.dividend" class="item-icon-left item-text-wrap" copy-on-click="{{::formData.dividend/100}}"><i class="icon ion-arrow-up-c"></i><div class="col col-60">{{'COMMON.UNIVERSAL_DIVIDEND'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.UNIVERSAL_DIVIDEND_HELP'|translate: {membersCount: formData.membersCount} }}</h4></div><span class="badge badge-balanced" ng-if="formData.dividend">+1 <span ng-bind-html="formData.currency|currencySymbol: {useRelative: true} "></span> / {{'COMMON.MEMBER'|translate|lowercase}} </span><span class="badge badge-stable" ng-if="!formData.dividend">0</span> <span class="badge badge-secondary" ng-if="formData.dividend">+ {{formData.dividend| formatAmount: {currency: formData.currency, useRelative: false} }} / {{'COMMON.MEMBER'|translate|lowercase}}</span></ion-item><ng-if ng-if="!compactMode || formData.identitiesCount"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-clock" style="position: absolute; top: 16px; left: 39px; font-size: 12px"></b> {{'BLOCKCHAIN.VIEW.IDENTITIES_COUNT'|translate}} <span class="badge badge-balanced" ng-if="formData.identitiesCount">+{{::formData.identitiesCount}}</span> <span class="badge badge-stable" ng-if="!formData.identitiesCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.identitiesCount"><ion-item ng-repeat="identity in ::formData.identities" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.joinersCount"><ion-item class="item-icon-left"><i class="icon ion-person-add"></i> {{'BLOCKCHAIN.VIEW.JOINERS_COUNT'|translate}} <span class="badge badge-balanced" ng-if="formData.joinersCount">+{{::formData.joinersCount}}</span> <span class="badge badge-stable" ng-if="!formData.joinersCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.joinersCount"><ion-item ng-repeat="identity in ::formData.joiners" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.activesCount"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-refresh" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{'BLOCKCHAIN.VIEW.ACTIVES_COUNT'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.ACTIVES_COUNT_HELP'|translate}}</h4><span class="badge badge-balanced" ng-if="formData.activesCount">{{::formData.activesCount}}</span> <span class="badge badge-stable" ng-if="!formData.activesCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.activesCount"><ion-item ng-repeat="identity in ::formData.actives" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || (formData.excludedCount-formData.revokedCount)"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-close dark" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{'BLOCKCHAIN.VIEW.EXCLUDED_COUNT'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.EXCLUDED_COUNT_HELP'|translate}}</h4><span class="badge badge-assertive" ng-if="formData.excludedCount-formData.revokedCount">-{{::formData.excludedCount-formData.revokedCount}}</span> <span class="badge badge-stable" ng-if="!(formData.excludedCount-formData.revokedCount)">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.excludedCount"><ion-item ng-repeat="identity in ::formData.excluded" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.leaversCount"><ion-item class="item-icon-left" ng-if="!compactMode || formData.leaversCount"><i class="icon ion-person"></i> <b class="ion-minus" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{'BLOCKCHAIN.VIEW.LEAVERS_COUNT'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.LEAVERS_COUNT_HELP'|translate}}</h4><span class="badge badge-assertive" ng-if="formData.leaversCount">-{{::formData.leaversCount}}</span> <span class="badge badge-stable" ng-if="!formData.leaversCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.leaversCount"><ion-item ng-repeat="identity in ::formData.leavers" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.revokedCount"><ion-item class="item-icon-left"><i class="icon ion-person"></i> <b class="ion-minus-circled assertive" style="position: absolute; top: 25px; left: 39px; font-size: 12px"></b> {{'BLOCKCHAIN.VIEW.REVOKED_COUNT'|translate}}<h4 class="gray">{{'BLOCKCHAIN.VIEW.REVOKED_COUNT_HELP'|translate}}</h4><span class="badge badge-balanced" ng-if="formData.revokedCount">-{{::formData.revokedCount}}</span> <span class="badge badge-stable" ng-if="!formData.revokedCount">0</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding" ng-if="formData.revokedCount"><ion-item ng-repeat="identity in ::formData.revoked" class="item-border-large item-small-height" ng-include="'templates/blockchain/link_identity.html'"></ion-item></div></ng-if><ng-if ng-if="!compactMode || formData.certificationsCount"><ion-item class="item-icon-left"><i class="icon ion-ribbon-a"></i> {{'BLOCKCHAIN.VIEW.CERT_COUNT'|translate}} <span class="badge badge-stable" ng-class="{'badge-positive':formData.certificationsCount}">{{::formData.certificationsCount}}</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding no-padding-xs" ng-if="formData.certificationsCount"><div ng-repeat="(key, certs) in formData.certifications" class="item item-border-large item-small-height"><div class="row no-padding"><div class="col col-center no-padding"><ng-repeat ng-repeat="cert in certs"><ng-include src="'templates/blockchain/link_identity.html'" onload="identity=cert.from"></ng-include><br></ng-repeat></div><div class="col col-10 col-center gray text-center no-padding"><h2><i class="icon ion-arrow-right-a"></i></h2></div><div class="col col-40 col-center no-padding" ng-include="'templates/blockchain/link_identity.html'" onload="identity=certs[0].to"></div></div></div></div></ng-if><ng-if ng-if="!compactMode || formData.transactionsCount"><ion-item class="item-icon-left"><i class="icon ion-card"></i> {{'BLOCKCHAIN.VIEW.TX_COUNT'|translate}} <span class="badge badge-stable" ng-class="{'badge-positive':formData.transactionsCount}">{{::formData.transactionsCount}}</span></ion-item><div class="padding-bottom item-icon-left-padding item-icon-right-padding no-padding-xs" ng-if="formData.transactionsCount"><div ng-repeat="tx in ::formData.transactions" class="item item-small-height item-border-large"><div class="row no-padding" style="padding-top: 3px"><div class="col col-40 col-center no-padding list no-margin"><div ng-repeat="identity in ::tx.issuers" class="item no-padding item-small-height"><ng-include src="'templates/blockchain/link_identity.html'"></ng-include></div></div><div class="col col-10 col-center gray text-center no-padding"><h2><i class="icon ion-arrow-right-a"></i></h2></div><div class="col no-padding padding-right no-padding-xs col-text-wrap list no-margin"><span class="gray" ng-if="tx.toHimself" translate="">BLOCKCHAIN.VIEW.TX_TO_HIMSELF</span><div ng-repeat="output in ::tx.outputs" class="item no-padding item-small-height"><ng-include ng-if="::output.pubkey" src="'templates/blockchain/link_identity.html'" onload="identity=output"></ng-include><span ng-if="::!output.pubkey && output.unlockFunctions"><i class="icon ion-locked"></i> (<a ng-click="showUnlockConditionPopover(output, $event)"> <i ng-repeat="unlockFunction in ::output.unlockFunctions" ng-class="::{'ion-key': (unlockFunction=='SIG'), 'ion-clock': (unlockFunction=='CSV' || unlockFunction=='CLTV'), 'ion-lock-combination': (unlockFunction=='XHX') }" class="icon"></i> </a>) </span><span class="badge badge-balanced" ng-bind-html="::output.amount | formatAmount:{currency: formData.currency, useRelative: false} "></span></div></div></div></div></div></ng-if></div></div></div></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/common/popup_password.html b/assets/www/templates/common/popup_password.html index e369f2e73a672d82d891489e39907add3d12199a..ac5a521e49d8492f0a3168784f794dd4b83d58a5 100644 --- a/assets/www/templates/common/popup_password.html +++ b/assets/www/templates/common/popup_password.html @@ -1 +1 @@ -<form name="pwdForm" ng-submit="submit($event)"><div class="list" ng-init="setForm(pwdForm)"><label class="item item-input" ng-class="{'item-input-error': pwdForm.$submitted && pwdForm.password.$invalid}"><input name="password" type="password" placeholder="{{'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.PASSWORD_HELP' | translate}}" ng-model="formData.password" ng-minlength="1" required></label><div class="form-errors" ng-if="pwdForm.$submitted && pwdForm.pseudo.$error" ng-messages="pwdForm.password.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div></div></form> \ No newline at end of file +<form name="pwdForm" ng-submit="submit($event)"><div class="list" ng-init="setForm(pwdForm)"><label class="item item-input" ng-class="{'item-input-error': pwdForm.$submitted && pwdForm.password.$invalid}"><input name="password" type="password" placeholder="{{'ACCOUNT.SECURITY.KEYFILE.PASSWORD_POPUP.PASSWORD_HELP' | translate}}" ng-model="formData.password" ng-minlength="1" required></label><div class="form-errors" ng-if="pwdForm.$submitted && pwdForm.pseudo.$error" ng-messages="pwdForm.password.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div><div class="form-errors" ng-if="error"><div class="form-error">{{error|translate}}</div></div></div></form> \ No newline at end of file diff --git a/assets/www/templates/currency/items_network.html b/assets/www/templates/currency/items_network.html index 9521ce53248b02a178426ccaf6b2c93addae61a2..28349634b94adb8a707a3059d62dfd9ffa9301dc 100644 --- a/assets/www/templates/currency/items_network.html +++ b/assets/www/templates/currency/items_network.html @@ -1 +1 @@ -<ion-item id="helptip-network-blockchain" class="item-icon-left item-text-wrap"><i class="icon ion-clock"></i> <span class="col col-60" translate="">CURRENCY.VIEW.MEDIAN_TIME</span> <span class="badge badge-stable">{{formData.medianTime | formatDate}}</span></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-lock-combination"></i> <span class="col col-75" translate="">CURRENCY.VIEW.POW_MIN</span> <span class="badge badge-stable">{{formData.difficulty | formatInteger}}</span></ion-item><cs-extension-point name="network-actual"></cs-extension-point><div class="item item-divider"><span translate="">CURRENCY.VIEW.NETWORK_RULES_DIVIDER</span></div><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-clock" style="position: absolute; font-size: 20px; left: 16px; margin-top: 11px"></i> <b class="icon-secondary ion-lock-combination" style="left: 14px; margin-top: -4px"></b> <b class="icon-secondary ion-arrow-right-c" style="font-size: 12px; left: 28px; margin-top: -4px"></b> <b class="icon-secondary ion-lock-combination" style="left: 38px; margin-top: -4px"></b> <span class="col col-75" translate="">CURRENCY.VIEW.AVG_GEN_TIME</span> <span class="badge badge-stable">{{formData.avgGenTime | formatDuration}}</span></ion-item><div id="helptip-network-peers" class="item item-divider"><div class="pull-left"><span ng-if="search.type=='member'" translate="">PEER.MEMBERS</span> <span ng-if="search.type=='mirror'" translate="">PEER.MIRRORS</span> <span ng-if="search.type=='offline'" translate="">PEER.OFFLINE</span> <span ng-if="!search.type" translate="">PEER.PEERS</span> <span ng-if="!search.loading">({{search.results.length}})</span></div><div class="buttons pull-right"><ion-spinner class="icon" icon="android" ng-if="search.loading"></ion-spinner></div></div><ng-include src="'templates/network/items_peers.html'"></ng-include> \ No newline at end of file +<ion-item id="helptip-network-blockchain" class="item-icon-left item-text-wrap"><i class="icon ion-clock"></i> <span class="col col-60" translate="">CURRENCY.VIEW.MEDIAN_TIME</span> <span class="badge badge-stable">{{formData.medianTime | medianDate}}</span></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-lock-combination"></i> <span class="col col-75" translate="">CURRENCY.VIEW.POW_MIN</span> <span class="badge badge-stable">{{formData.difficulty | formatInteger}}</span></ion-item><cs-extension-point name="network-actual"></cs-extension-point><div class="item item-divider"><span translate="">CURRENCY.VIEW.NETWORK_RULES_DIVIDER</span></div><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-clock" style="position: absolute; font-size: 20px; left: 16px; margin-top: 11px"></i> <b class="icon-secondary ion-lock-combination" style="left: 14px; margin-top: -4px"></b> <b class="icon-secondary ion-arrow-right-c" style="font-size: 12px; left: 28px; margin-top: -4px"></b> <b class="icon-secondary ion-lock-combination" style="left: 38px; margin-top: -4px"></b> <span class="col col-75" translate="">CURRENCY.VIEW.AVG_GEN_TIME</span> <span class="badge badge-stable">{{formData.avgGenTime | formatDuration}}</span></ion-item><div id="helptip-network-peers" class="item item-divider"><div class="pull-left"><span ng-if="search.type=='member'" translate="">PEER.MEMBERS</span> <span ng-if="search.type=='mirror'" translate="">PEER.MIRRORS</span> <span ng-if="search.type=='offline'" translate="">PEER.OFFLINE</span> <span ng-if="!search.type" translate="">PEER.PEERS</span> <span ng-if="!search.loading">({{search.results.length}})</span></div><div class="buttons pull-right"><ion-spinner class="icon" icon="android" ng-if="search.loading"></ion-spinner></div></div><ng-include src="'templates/network/items_peers.html'"></ng-include> \ No newline at end of file diff --git a/assets/www/templates/currency/items_parameters.html b/assets/www/templates/currency/items_parameters.html index 803800d5d1e7442d9148e3c303e8a07396ec5e58..9ac597adb94217609a4a7cdc0055ccefb903c64e 100644 --- a/assets/www/templates/currency/items_parameters.html +++ b/assets/www/templates/currency/items_parameters.html @@ -1 +1 @@ -<div bind-notifier="{ rebind:formData.useRelative }"><ion-item class="item-icon-left item-text-wrap visible-xs visible-sm"><i class="icon ion-android-bookmark"></i> <span translate>CURRENCY.VIEW.CURRENCY_NAME</span><div class="item-note dark" ng-if="!loading">{{formData.currency}} (<span ng-bind-html=":rebind:formData.currency | currencySymbol:formData.useRelative"></span>)</div></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-record"></i><div class="col col-60"><span translate>CURRENCY.VIEW.MASS</span> <span class="gray">(M<sub>t</sub>)</span></div><span class="badge badge-calm" ng-if="!loading" ng-bind-html=":rebind:formData.M | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}"></span></ion-item><ion-item id="helptip-currency-mass-member" class="item-icon-left item-text-wrap"><i class="icon ion-pie-graph"></i><div class="col col-60"><span translate>CURRENCY.VIEW.SHARE</span> <span class="gray">(M<sub>t</sub>/N<sub>t</sub>)</span></div><span id="helptip-currency-mass-member-unit" ng-if="!loading" class="badge badge-energized" ng-bind-html=":rebind:formData.MoverN | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}"></span></ion-item><cs-extension-point name="parameters-actual"></cs-extension-point><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-arrow-graph-up-right"></i><div class="col col-60"><span translate>CURRENCY.VIEW.C_ACTUAL</span> <span class="gray">(c<sub>{{'CURRENCY.VIEW.CURRENT'|translate}}</sub>)</span></div><span class="badge badge-stable">{{formData.cactual | formatNumeral: '0,0.00'}} % / {{formData.dt | formatPeriod}}</span></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-load-c"></i><div class="col col-60"><span translate>CURRENCY.VIEW.UD</span> <span class="gray">({{'COMMON.UD'|translate}}<sub>t</sub>)</span></div><div class="badge badge-royal" ng-if="!loading"><span ng-if="formData.useRelative">1<ng-bind-html ng-bind-html=":rebind:formData.currency| currencySymbol:true"></ng-bind-html></span><span ng-if="!formData.useRelative" ng-bind-html=":rebind:formData.currentUD | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}"></span> / {{formData.dt | formatPeriod}}</div></ion-item><div class="item item-toggle dark"><div class="item-label text-right gray" translate>COMMON.BTN_RELATIVE_UNIT</div><label class="toggle toggle-royal" id="helptip-currency-change-unit"><input type="checkbox" ng-model="formData.useRelative"><div class="track"><div class="handle"></div></div></label></div><a name="helptip-currency-rules-anchor"></a><div class="item item-divider" id="helptip-currency-rules"><span translate>CURRENCY.VIEW.MONEY_RULES_DIVIDER</span></div><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-arrow-graph-up-right"></i><div class="col col-60"><span translate>CURRENCY.VIEW.C_RULE</span> <span class="gray">(c)</span></div><span class="item-note dark" ng-if="!loading && !formData.udReevalTime0">{{formData.c*100 | formatNumeral: '0,0.00'}} % / {{formData.dt | formatPeriod}}</span><span class="badge badge-stable" ng-if="!loading && formData.udReevalTime0">{{formData.c*100 | formatNumeral: '0,0.00'}} % / {{formData.dtReeval | formatDuration}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.udReevalTime0 && formData.allRules"><i class="icon ion-load-c"></i> <b class="ion-clock icon-secondary" style="font-size: 18px; left: 36px; top: -12px"></b><div class="col col-60"><span translate>CURRENCY.VIEW.DT_REEVAL</span> <span class="gray">(dt<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub>)</span></div><span class="item-note dark" ng-if="!loading" translate="CURRENCY.VIEW.DT_REEVAL_VALUE" translate-values="formData"></span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.udReevalTime0 && formData.allRules"><i class="icon ion-load-c"></i> <b class="ion-calendar icon-secondary" style="font-size: 18px; left: 36px; top: -12px"></b><div class="col col-60"><span translate>CURRENCY.VIEW.UD_REEVAL_TIME0</span> <span class="gray">(t0<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub>)</span></div><span class="item-note dark" ng-if="!loading">{{formData.udReevalTime0|formatDate}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.allRules"><i class="icon ion-load-c"></i> <b class="ion-calculator icon-secondary" style="font-size: 18px; left: 36px; top: -12px"></b><div class="col col-60"><span translate>CURRENCY.VIEW.UD_RULE</span> <span class="gray" ng-if="formData.udReevalTime0">- {{'COMMON.UD'|translate}}<sub>{{formData.dt|formatPeriod}}</sub>(t<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub>)</span></div><span class="item-note dark" ng-if="!loading && !formData.udReevalTime0">{{'COMMON.UD'|translate}}<sub>t-1</sub> + c<sup>2</sup> * M<sub>t-1</sub>/N<sub>t-1</sub></span><span class="item-note dark" ng-if="!loading && formData.udReevalTime0">{{'COMMON.UD'|translate}}<sub>{{formData.dt|formatPeriod}}</sub>(t<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub> - dt<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub>)+ c<sup>2</sup> * (M/N)(t<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub> - dt<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub>) / dt<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub></span></ion-item><div class="item item-toggle dark"><div class="item-label text-right gray" translate>CURRENCY.VIEW.DISPLAY_ALL_RULES</div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.allRules"><div class="track"><div class="handle"></div></div></label></div></div> \ No newline at end of file +<div bind-notifier="{ rebind:formData.useRelative }"><ion-item class="item-icon-left item-text-wrap visible-xs visible-sm"><i class="icon ion-android-bookmark"></i> <span translate>CURRENCY.VIEW.CURRENCY_NAME</span><div class="item-note dark" ng-if="!loading">{{formData.currency}} (<span ng-bind-html=":rebind:formData.currency | currencySymbol:formData.useRelative"></span>)</div></ion-item><ion-item id="helptip-currency-mass-member" class="item-icon-left item-text-wrap"><i class="icon ion-pie-graph"></i><div class="col col-60"><span translate>CURRENCY.VIEW.SHARE</span> <span class="gray">(M<sub>t</sub>/N<sub>t</sub>)</span></div><span id="helptip-currency-mass-member-unit" ng-if="!loading" class="badge badge-calm" ng-bind-html=":rebind:formData.MoverN | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}"></span></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-record"></i><div class="col col-60"><span translate>CURRENCY.VIEW.MASS</span> <span class="gray">(M<sub>t</sub>)</span></div><span class="badge badge-energized" ng-if="!loading" ng-bind-html=":rebind:formData.M | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}"></span></ion-item><cs-extension-point name="parameters-actual"></cs-extension-point><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-arrow-graph-up-right"></i><div class="col col-60"><span translate>CURRENCY.VIEW.C_ACTUAL</span> <span class="gray">(c<sub>{{'CURRENCY.VIEW.CURRENT'|translate}}</sub>)</span></div><span class="badge badge-stable">{{formData.cactual | formatNumeral: '0,0.00'}} % / {{formData.dt | formatPeriod}}</span></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-load-c"></i><div class="col col-60"><span translate>CURRENCY.VIEW.UD</span> <span class="gray">({{'COMMON.UD'|translate}}<sub>t</sub>)</span></div><div class="badge badge-royal" ng-if="!loading"><span ng-if="formData.useRelative">1<ng-bind-html ng-bind-html=":rebind:formData.currency| currencySymbol:true"></ng-bind-html></span><span ng-if="!formData.useRelative" ng-bind-html=":rebind:formData.currentUD | formatAmount:{currency: formData.currency, useRelative: formData.useRelative, currentUD: formData.currentUD}"></span> / {{formData.dt | formatPeriod}}</div></ion-item><div class="item item-toggle dark"><div class="item-label text-right gray" translate>COMMON.BTN_RELATIVE_UNIT</div><label class="toggle toggle-royal" id="helptip-currency-change-unit"><input type="checkbox" ng-model="formData.useRelative"><div class="track"><div class="handle"></div></div></label></div><a name="helptip-currency-rules-anchor"></a><div class="item item-divider" id="helptip-currency-rules"><span translate>CURRENCY.VIEW.MONEY_RULES_DIVIDER</span></div><ion-item class="item-icon-left item-text-wrap"><i class="icon ion-arrow-graph-up-right"></i><div class="col col-60"><span translate>CURRENCY.VIEW.C_RULE</span> <span class="gray">(c)</span></div><span class="item-note dark" ng-if="!loading && !formData.udReevalTime0">{{formData.c*100 | formatNumeral: '0,0.00'}} % / {{formData.dt | formatPeriod}}</span><span class="badge badge-stable" ng-if="!loading && formData.udReevalTime0">{{formData.c*100 | formatNumeral: '0,0.00'}} % / {{formData.dtReeval | formatDuration}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.udReevalTime0 && formData.allRules"><i class="icon ion-load-c"></i> <b class="ion-clock icon-secondary" style="font-size: 18px; left: 36px; top: -12px"></b><div class="col col-60"><span translate>CURRENCY.VIEW.DT_REEVAL</span> <span class="gray">(dt<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub>)</span></div><span class="item-note dark" ng-if="!loading" translate="CURRENCY.VIEW.DT_REEVAL_VALUE" translate-values="formData"></span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.udReevalTime0 && formData.allRules"><i class="icon ion-load-c"></i> <b class="ion-calendar icon-secondary" style="font-size: 18px; left: 36px; top: -12px"></b><div class="col col-60"><span translate>CURRENCY.VIEW.UD_REEVAL_TIME0</span> <span class="gray">(t0<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub>)</span></div><span class="item-note dark" ng-if="!loading">{{formData.udReevalTime0|medianDate}}</span></ion-item><ion-item class="item-icon-left item-text-wrap" ng-if="formData.allRules"><i class="icon ion-load-c"></i> <b class="ion-calculator icon-secondary" style="font-size: 18px; left: 36px; top: -12px"></b><div class="col col-60"><span translate>CURRENCY.VIEW.UD_RULE</span> <span class="gray" ng-if="formData.udReevalTime0">- {{'COMMON.UD'|translate}}<sub>{{formData.dt|formatPeriod}}</sub>(t<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub>)</span></div><span class="item-note dark" ng-if="!loading && !formData.udReevalTime0">{{'COMMON.UD'|translate}}<sub>t-1</sub> + c<sup>2</sup> * M<sub>t-1</sub>/N<sub>t-1</sub></span><span class="item-note dark" ng-if="!loading && formData.udReevalTime0">{{'COMMON.UD'|translate}}<sub>{{formData.dt|formatPeriod}}</sub>(t<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub> - dt<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub>)+ c<sup>2</sup> * (M/N)(t<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub> - dt<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub>) / dt<sub>{{'CURRENCY.VIEW.REEVAL_SYMBOL'|translate}}</sub></span></ion-item><div class="item item-toggle dark"><div class="item-label text-right gray" translate>CURRENCY.VIEW.DISPLAY_ALL_RULES</div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.allRules"><div class="track"><div class="handle"></div></div></label></div></div> \ No newline at end of file diff --git a/assets/www/templates/currency/lookup.html b/assets/www/templates/currency/lookup.html index de8c4e3488580769a49f1112f3604e50a041c66c..31ac255839f0255c0b99b58653f3b29ee48647f4 100644 --- a/assets/www/templates/currency/lookup.html +++ b/assets/www/templates/currency/lookup.html @@ -1 +1 @@ -<ion-view view-title="{{'CURRENCY.SELECT.TITLE' | translate}}"><ion-content class="padding no-padding-xs"><h4 class="content double-padding-x" translate>CURRENCY.SELECT.CURRENCIES</h4><ng-include src="'templates/currency/lookup_form.html'"></ion-content></ion-view> \ No newline at end of file +<ion-view view-title="{{'CURRENCY.SELECT.TITLE' | translate}}"><ion-content class="padding no-padding-xs no-padding-sm"><h4 class="content double-padding-x" translate>CURRENCY.SELECT.CURRENCIES</h4><ng-include src="'templates/currency/lookup_form.html'"></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/help/help.html b/assets/www/templates/help/help.html index 1a3a154be80a3efc55bdb90a5a381e4551fbcc39..b436cb175c070334588f8abbd01a2ffa516bb3ae 100644 --- a/assets/www/templates/help/help.html +++ b/assets/www/templates/help/help.html @@ -1 +1 @@ -<a name="join"></a><h2 translate>HELP.JOIN.SECTION</h2><a name="join-salt"></a><div class="row responsive-sm" ng-class="itemsClass['join-salt']"><div class="col col-20" translate>LOGIN.SALT</div><div class="col" translate>HELP.JOIN.SALT</div></div><a name="join-password"></a><div class="row responsive-sm" ng-class="itemsClass['join-password']"><div class="col col-20" translate>LOGIN.PASSWORD</div><div class="col" translate>HELP.JOIN.PASSWORD</div></div><a name="join-pseudo"></a><div class="row responsive-sm" ng-class="itemsClass['join-pseudo']"><div class="col col-20" translate>ACCOUNT.NEW.PSEUDO</div><div class="col" translate>HELP.JOIN.PSEUDO</div></div><a name="login"></a><h2 translate>HELP.LOGIN.SECTION</h2><a name="login-pubkey"></a><div class="row responsive-sm" ng-class="itemsClass['login-pubkey']"><div class="col col-20" translate>HELP.LOGIN.PUBKEY</div><div class="col" translate>HELP.LOGIN.PUBKEY_DEF</div></div><a name="login-method"></a><div class="row responsive-sm" ng-class="itemsClass['login-method']"><div class="col col-20" translate>HELP.LOGIN.METHOD</div><div class="col" translate>HELP.LOGIN.METHOD_DEF</div></div><a name="glossary"></a><h2 translate>HELP.GLOSSARY.SECTION</h2><a name="pubkey"></a><div class="row responsive-sm" ng-class="itemsClass.pubkey"><div class="col col-20" translate>COMMON.PUBKEY</div><div class="col" translate>HELP.GLOSSARY.PUBKEY_DEF</div></div><a name="blockchain"></a><div class="row responsive-sm" ng-class="itemsClass.blockchain"><div class="col col-20" translate>HELP.GLOSSARY.BLOCKCHAIN</div><div class="col" translate>HELP.GLOSSARY.BLOCKCHAIN_DEF</div></div><a name="universal_dividend"></a> <a name="ud"></a><div class="row responsive-sm" ng-class="itemsClass.ud"><div class="col col-20" translate>COMMON.UNIVERSAL_DIVIDEND</div><div class="col" translate>HELP.GLOSSARY.UNIVERSAL_DIVIDEND_DEF</div></div><a name="member"></a><div class="row responsive-sm" ng-class="itemsClass.member"><div class="col col-20" translate>HELP.GLOSSARY.MEMBER</div><div class="col" translate>HELP.GLOSSARY.MEMBER_DEF</div></div><a name="currency_rules"></a><div class="row responsive-sm" ng-class="itemsClass.currency_rules"><div class="col col-20" translate>HELP.GLOSSARY.CURRENCY_RULES</div><div class="col" translate>HELP.GLOSSARY.CURRENCY_RULES_DEF</div></div> \ No newline at end of file +<a name="join"></a><h2 translate>HELP.JOIN.SECTION</h2><a name="join-salt"></a><div class="row responsive-sm" ng-class="itemsClass['join-salt']"><div class="col col-20" translate>LOGIN.SALT</div><div class="col" translate>HELP.JOIN.SALT</div></div><a name="join-password"></a><div class="row responsive-sm" ng-class="itemsClass['join-password']"><div class="col col-20" translate>LOGIN.PASSWORD</div><div class="col" translate>HELP.JOIN.PASSWORD</div></div><a name="join-pseudo"></a><div class="row responsive-sm" ng-class="itemsClass['join-pseudo']"><div class="col col-20" translate>ACCOUNT.NEW.PSEUDO</div><div class="col" translate>HELP.JOIN.PSEUDO</div></div><a name="login"></a><h2 translate>HELP.LOGIN.SECTION</h2><a name="login-pubkey"></a><div class="row responsive-sm" ng-class="itemsClass['login-pubkey']"><div class="col col-20" translate>HELP.LOGIN.PUBKEY</div><div class="col" translate>HELP.LOGIN.PUBKEY_DEF</div></div><a name="login-method"></a><div class="row responsive-sm" ng-class="itemsClass['login-method']"><div class="col col-20" translate>HELP.LOGIN.METHOD</div><div class="col" translate>HELP.LOGIN.METHOD_DEF</div></div><a name="glossary"></a><h2 translate>HELP.GLOSSARY.SECTION</h2><a name="pubkey"></a><div class="row responsive-sm" ng-class="itemsClass.pubkey"><div class="col col-20" translate>COMMON.PUBKEY</div><div class="col" translate>HELP.GLOSSARY.PUBKEY_DEF</div></div><a name="blockchain"></a><div class="row responsive-sm" ng-class="itemsClass.blockchain"><div class="col col-20" translate>HELP.GLOSSARY.BLOCKCHAIN</div><div class="col" translate>HELP.GLOSSARY.BLOCKCHAIN_DEF</div></div><a name="universal_dividend"></a> <a name="ud"></a><div class="row responsive-sm" ng-class="itemsClass.ud"><div class="col col-20" translate>COMMON.UNIVERSAL_DIVIDEND</div><div class="col" translate>HELP.GLOSSARY.UNIVERSAL_DIVIDEND_DEF</div></div><a name="member"></a><div class="row responsive-sm" ng-class="itemsClass.member"><div class="col col-20" translate>HELP.GLOSSARY.MEMBER</div><div class="col" translate>HELP.GLOSSARY.MEMBER_DEF</div></div><a name="wot"></a><div class="row responsive-sm" ng-class="itemsClass.wot"><div class="col col-20" translate>HELP.GLOSSARY.WOT</div><div class="col" translate>HELP.GLOSSARY.WOT_DEF</div></div><a name="currency_rules"></a><div class="row responsive-sm" ng-class="itemsClass.currency_rules"><div class="col col-20" translate>HELP.GLOSSARY.CURRENCY_RULES</div><div class="col" translate>HELP.GLOSSARY.CURRENCY_RULES_DEF</div></div><a name="distance_rule"></a><div class="row responsive-sm" ng-class="itemsClass.distance_rule"><div class="col col-20" translate>HELP.GLOSSARY.DISTANCE_RULE</div><div class="col" translate>HELP.GLOSSARY.DISTANCE_RULE_DEF</div></div> \ No newline at end of file diff --git a/assets/www/templates/home/home.html b/assets/www/templates/home/home.html index 783896665d7f391b505a34161ab930ad0a7bc4be..5c1f24dfc0e7d0e613883b8040bee80292239691 100644 --- a/assets/www/templates/home/home.html +++ b/assets/www/templates/home/home.html @@ -1 +1 @@ -<ion-view id="home" class=""><ion-nav-title></ion-nav-title><ion-content class="has-header text-center padding-xs positive-900-bg circle-bg-dark"><div id="helptip-home-logo" class="logo"></div><h4><span class="hidden-xs" translate="">HOME.WELCOME</span> <span ng-show="!loading" translate-values=":currency:{currency: $root.currency.name}" translate="">HOME.MESSAGE</span></h4><div class="center padding"><ion-spinner icon="android" ng-if="loading"></ion-spinner><div class="animate-fade-in animate-show-hide ng-hide" ng-show="!loading && error"><div class="card card-item padding"><p class="item-content item-text-wrap"><span class="dark" trust-as-html="'HOME.CONNECTION_ERROR'|translate:node"></span></p><button type="button" class="button button-positive icon icon-left ion-refresh ink" ng-click="reload()">{{'COMMON.BTN_REFRESH'|translate}}</button></div></div></div><div class="center animate-fade-in animate-show-hide ng-hide" ng-show="!loading && !error"><button type="button" class="button button-block button-stable button-raised icon-left icon ion-easel ink-dark hidden-xs" ng-click="startHelpTour()">{{'COMMON.BTN_HELP_TOUR'|translate}}</button> <button type="button" class="item button button-block button-positive button-raised icon icon-left ion-locked ink-dark" ui-sref="app.view_wallet" ng-show="!login" translate="">COMMON.BTN_LOGIN</button> <button type="button" class="item button button-block button-positive button-raised icon icon-left ion-person ink-dark" ui-sref="app.view_wallet" ng-show="login" translate="">MENU.ACCOUNT</button> <button type="button" class="item button button-block button-positive button-raised icon icon-left ion-card ink-dark visible-xs" ui-sref="app.view_wallet_tx" ng-show="login" translate="">MENU.TRANSACTIONS</button><br class="visible-xs visible-sm"><div class="text-center no-padding" ng-show="!login"><br class="visible-xs visible-sm">{{'LOGIN.NO_ACCOUNT_QUESTION'|translate}} <b></b></div><div class="text-center no-padding" ng-show="login"><br class="visible-xs visible-sm"><span ng-bind-html="'HOME.NOT_YOUR_ACCOUNT_QUESTION'|translate:$root.walletData"></span><br><b></b></div><button type="button" class="button button-block button-calm button-raised icon icon-left ion-wand ink-dark visible-xs visible-sm" ng-click="showJoinModal()" ng-if="!login" translate="">LOGIN.CREATE_ACCOUNT</button> <button type="button" class="button button-block button-assertive button-raised icon icon-left ion-wand ink-dark visible-xs visible-sm" ng-click="logout()" ng-if="login" translate="">COMMON.BTN_LOGOUT</button><div class="text-center no-padding visible-xs stable"><br>{{'COMMON.APP_VERSION'|translate:{version: config.version} }} | <a href="#" ng-click="showAboutModal()" translate="">HOME.BTN_ABOUT</a></div></div></ion-content></ion-view> \ No newline at end of file +<ion-view id="home" class=""><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"></ion-nav-buttons><ion-content class="has-header text-center no-padding-xs positive-900-bg circle-bg-dark"><div id="helptip-home-logo" class="logo"></div><h4><span class="hidden-xs" translate="">HOME.WELCOME</span> <b ng-show="!loading" translate-values=":currency:{currency: $root.currency.name}" translate="">HOME.MESSAGE</b></h4><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding animate-fade-in animate-show-hide ng-hide" ng-show="!loading && error"><div class="card card-item padding"><p class="item-content item-text-wrap"><span class="dark" trust-as-html="'HOME.CONNECTION_ERROR'|translate:node"></span></p><button type="button" class="button button-positive icon icon-left ion-refresh ink" ng-click="reload()">{{'COMMON.BTN_REFRESH'|translate}}</button></div></div><div class="center animate-fade-in animate-show-hide ng-hide" ng-show="!loading && !error"><button type="button" class="button button-block button-stable button-raised icon-left icon ion-easel ink-dark hidden-xs" ng-show="login" ng-click="startHelpTour()">{{'COMMON.BTN_HELP_TOUR'|translate}}</button> <button type="button" class="button button-block button-positive button-raised ink-dark" ng-click="showJoinModal()" ng-if="!login" translate="">LOGIN.CREATE_FREE_ACCOUNT</button> <button type="button" class="item button button-block button-positive button-raised icon icon-left ion-person ink-dark" ui-sref="app.view_wallet" ng-show="login" translate="">MENU.ACCOUNT</button> <button type="button" class="item button button-block button-positive button-raised icon icon-left ion-card ink-dark visible-xs" ui-sref="app.view_wallet_tx" ng-if="login" translate="">MENU.TRANSACTIONS</button><br class="visible-xs visible-sm"><div class="text-center no-padding" ng-show="!login"><br class="visible-xs visible-sm">{{'LOGIN.HAVE_ACCOUNT_QUESTION'|translate}} <b></b></div><div class="text-center no-padding" ng-show="login"><br class="visible-xs visible-sm"><span ng-bind-html="'HOME.NOT_YOUR_ACCOUNT_QUESTION'|translate:{pubkey: walletData.pubkey}"></span><br><b></b></div><button type="button" class="button button-block button-stable button-raised ink visible-xs visible-sm" ui-sref="app.view_wallet" ng-if="!login" translate="">COMMON.BTN_LOGIN</button> <button type="button" class="button button-block button-assertive button-raised icon icon-left ion-wand ink-dark visible-xs visible-sm" ng-click="logout()" ng-if="login" translate="">COMMON.BTN_LOGOUT</button><div class="text-center no-padding visible-xs stable"><br>{{'COMMON.APP_VERSION'|translate:{version: config.version} }} | <a href="#" ng-click="showAboutModal()" translate="">HOME.BTN_ABOUT</a></div></div></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/join/modal_join_member.html b/assets/www/templates/join/modal_join_member.html index 8098fd3ddd99acbd0a469be7faa9cbaeeb3e429c..7c5e325391b4c828ba76305410f1842c902adcc2 100644 --- a/assets/www/templates/join/modal_join_member.html +++ b/assets/www/templates/join/modal_join_member.html @@ -1 +1 @@ -<ion-modal-view class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-if="!slides.slider.activeIndex" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button> <button class="button button-icon button-clear icon ion-ios-arrow-back buttons header-item" ng-click="slidePrev()" ng-if="slides.slider.activeIndex && slideBehavior.hasPreviousButton"></button> <button class="button button-icon button-clear icon ion-ios-help-outline visible-xs" ng-if="slideBehavior.helpAnchor" ng-click="showHelpModal(slideBehavior.helpAnchor)"></button><h1 class="title" translate>ACCOUNT.NEW.MEMBER_ACCOUNT_TITLE</h1><button class="button button-clear icon-right visible-xs" ng-if="slideBehavior.hasNextButton" ng-click="doNext()"><span translate>COMMON.BTN_NEXT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-clear icon-right visible-xs" ng-class="{'button-text-stable': !isLicenseRead}" ng-if="slideBehavior.hasAcceptButton" ng-click="isLicenseRead ? doNext() : undefined"><span translate>ACCOUNT.NEW.BTN_ACCEPT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-clear icon-right visible-xs" ng-if="slideBehavior.hasSendButton" ng-click="doNewAccount()"><i class="icon ion-android-send"></i></button></ion-header-bar><ion-slides options="slides.options" slider="slides.slider" ng-init="console.log('START SLIDE');"><ion-slide-page ng-if="licenseFileUrl"><ion-content class="has-header" scroll="false"><div class="padding" translate>ACCOUNT.NEW.INFO_LICENSE</div><div class="center padding" ng-if="loading"><ion-spinner class="icon" icon="android"></ion-spinner></div><iframe ng-if="!loading" class="padding-left padding-right no-padding-xs iframe-license" id="iframe-license" ng-src="{{licenseFileUrl}}"></iframe><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" ng-click="doNext('licenceForm')" ng-disabled="!isLicenseRead" type="button" translate>ACCOUNT.NEW.BTN_ACCEPT_LICENSE</button></div></ion-content></ion-slide-page><ion-slide-page><ion-content class="has-header" scroll="false"><form name="pseudoForm" novalidate="" ng-submit="doNext('pseudoForm')"><div class="item item-text-wrap text-center padding"><a class="pull-right icon-help hidden-xs" ng-click="showHelpModal('join-pseudo')"></a> <span translate>ACCOUNT.NEW.PSEUDO_WARNING</span></div><div class="list" ng-init="setForm(pseudoForm, 'pseudoForm')"><div class="item item-input" ng-class="{'item-input-error': (pseudoForm.$submitted && pseudoForm.pseudo.$invalid) || (uiAlreadyUsed && formData.pseudo)}"><span class="input-label" translate>ACCOUNT.NEW.PSEUDO</span> <input id="pseudo" name="pseudo" type="text" placeholder="{{'ACCOUNT.NEW.PSEUDO_HELP' | translate}}" ng-model="formData.pseudo" autocomplete="off" ng-minlength="3" ng-maxlength="100" ng-pattern="userIdPattern" ng-model-options="{ debounce: 250 }" required></div><div class="form-errors" ng-show="pseudoForm.$submitted && pseudoForm.pseudo.$error" ng-messages="pseudoForm.pseudo.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT_WITH_LENGTH" translate-values="{minLength: 3}"></span></div><div class="form-error" ng-message="maxlength"><span translate="ERROR.FIELD_TOO_LONG_WITH_LENGTH" translate-values="{maxLength: 100}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="pattern"><span translate="ERROR.INVALID_USER_ID"></span></div></div><div class="text-right" style="min-height: 18px"><div class="form-error gray" ng-if="formData.computing && formData.pseudo"><ion-spinner class="icon ion-spinner-small" icon="android" ng-if="formData.computing && formData.pseudo"></ion-spinner><span translate>ACCOUNT.NEW.CHECKING_PSEUDO</span></div><ng-if ng-if="!formData.computing && formData.pseudo"><div class="form-error balanced" ng-if="!uiAlreadyUsed "><i class="icon ion-checkmark balanced"></i> <span translate>ACCOUNT.NEW.PSEUDO_AVAILABLE</span></div><div class="form-error" ng-if="uiAlreadyUsed"><i class="icon ion-close-circled assertive"></i> <span translate>ACCOUNT.NEW.PSEUDO_NOT_AVAILABLE</span></div></ng-if></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" ng-disabled="UIDFound" translate>COMMON.BTN_NEXT</button></div></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class="has-header" scroll="false"><form name="saltForm" novalidate="" ng-submit="doNext('saltForm')"><div class="list" ng-init="setForm(saltForm, 'saltForm')"><div class="item item-text-wrap text-center padding hidden-xs"><a class="pull-right icon-help" ng-click="showHelpModal('join-salt')"></a> <span translate>ACCOUNT.NEW.SALT_WARNING</span></div><div class="item item-input" ng-class="{ 'item-input-error': saltForm.$submitted && saltForm.username.$invalid}"><span class="input-label" translate>LOGIN.SALT</span> <input ng-if="!showUsername" name="username" type="password" placeholder="{{'LOGIN.SALT_HELP' | translate}}" ng-change="formDataChanged()" ng-model="formData.username" autocomplete="off" ng-minlength="8" different-to="formData.pseudo" required> <input ng-if="showUsername" name="username" type="text" placeholder="{{'LOGIN.SALT_HELP' | translate}}" ng-change="formDataChanged()" ng-model="formData.username" autocomplete="off" ng-minlength="8" different-to="formData.pseudo" required></div><div class="form-errors" ng-show="saltForm.$submitted && saltForm.username.$error" ng-messages="saltForm.username.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT_WITH_LENGTH" translate-values="{minLength: 8}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="differentTo"><span translate="ERROR.EQUALS_TO_PSEUDO"></span></div></div><div class="item item-input" ng-class="{ 'item-input-error': saltForm.$submitted && saltForm.confirmSalt.$invalid}"><span class="input-label pull-right" translate>ACCOUNT.NEW.SALT_CONFIRM</span> <input ng-if="!showUsername" name="confirmUsername" type="password" placeholder="{{'ACCOUNT.NEW.SALT_CONFIRM_HELP' | translate}}" ng-model="formData.confirmUsername" autocomplete="off" compare-to="formData.username"> <input ng-if="showUsername" name="confirmUsername" type="text" placeholder="{{'ACCOUNT.NEW.SALT_CONFIRM_HELP' | translate}}" ng-model="formData.confirmUsername" autocomplete="off" compare-to="formData.username"></div><div class="form-errors" ng-show="saltForm.$submitted && saltForm.confirmUsername.$error" ng-messages="saltForm.confirmUsername.$error"><div class="form-error" ng-message="compareTo"><span translate="ERROR.SALT_NOT_CONFIRMED"></span></div></div><div class="item item-toggle dark"><span translate>COMMON.SHOW_VALUES</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="showUsername"><div class="track"><div class="handle"></div></div></label></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" translate>COMMON.BTN_NEXT <i class="icon ion-arrow-right-a"></i></button></div></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class="has-header" scroll="false"><form name="passwordForm" novalidate="" ng-submit="doNext('passwordForm')"><div class="item item-text-wrap text-center padding hidden-xs"><a class="pull-right icon-help" ng-click="showHelpModal('join-password')"></a> <span translate>ACCOUNT.NEW.PASSWORD_WARNING</span></div><div class="list" ng-init="setForm(passwordForm, 'passwordForm')"><div class="item item-input" ng-class="{ 'item-input-error': passwordForm.$submitted && passwordForm.password.$invalid}"><span class="input-label" translate>LOGIN.PASSWORD</span> <input ng-if="!showPassword" name="password" type="password" placeholder="{{'LOGIN.PASSWORD_HELP' | translate}}" ng-model="formData.password" autocomplete="off" ng-change="formDataChanged()" ng-minlength="8" different-to="formData.username" required> <input ng-if="showPassword" name="text" type="text" placeholder="{{'LOGIN.PASSWORD_HELP' | translate}}" ng-model="formData.password" autocomplete="off" ng-change="formDataChanged()" ng-minlength="8" different-to="formData.username" required></div><div class="form-errors" ng-show="passwordForm.$submitted && passwordForm.password.$error" ng-messages="passwordForm.password.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT_WITH_LENGTH" translate-values="{minLength: 8}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="differentTo"><span translate="ERROR.EQUALS_TO_SALT"></span></div></div><div class="item item-input" ng-class="{ 'item-input-error': passwordForm.$submitted && passwordForm.confirmPassword.$invalid}"><span class="input-label" translate>ACCOUNT.NEW.PASSWORD_CONFIRM</span> <input ng-if="!showPassword" name="confirmPassword" type="password" placeholder="{{'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP' | translate}}" ng-model="formData.confirmPassword" autocomplete="off" compare-to="formData.password"> <input ng-if="showPassword" name="confirmPassword" type="text" placeholder="{{'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP' | translate}}" ng-model="formData.confirmPassword" autocomplete="off" compare-to="formData.password"></div><div class="form-errors" ng-show="passwordForm.$submitted && passwordForm.confirmPassword.$error" ng-messages="passwordForm.confirmPassword.$error"><div class="form-error" ng-message="compareTo"><span translate="ERROR.PASSWORD_NOT_CONFIRMED"></span></div></div><div class="item item-toggle dark"><span translate>COMMON.SHOW_VALUES</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="showPassword"><div class="track"><div class="handle"></div></div></label></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" ng-click="getRevocationDocument()" translate>COMMON.BTN_NEXT</button></div><div class="padding hidden-xs"></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class="has-header" scroll="false"><div class="center padding" ng-if="formData.computing"><ion-spinner icon="android"></ion-spinner></div><div ng-if="accountAvailable && !formData.computing"><div class="padding text-center" translate>ACCOUNT.NEW.LAST_SLIDE_CONGRATULATION</div><div class="list"><ion-item class="item text-center item-text-wrap"><h3 class="gray" translate>LOGIN.ASSOCIATED_PUBKEY</h3><h3 class="dark bold">{{formData.pubkey}}</h3></ion-item></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" ng-click="doNewAccount()" translate>COMMON.BTN_SEND <i class="icon ion-android-send"></i></button></div></div><div ng-if="!accountAvailable && !formData.computing"><ion-item class="item-icon-left item-text-wrap text-center"><i class="icon ion-minus-circled assertive"></i> <span id="modal-license" trust-as-html="'ERROR.EXISTING_ACCOUNT'|translate"></span></ion-item><div class="list"><ion-item class="item item-text-wrap item-border"><div class="padding text-center"><span class="gray text-no-wrap">{{formData.pubkey}}</span></div></ion-item><div class="padding text-center"><span translate>ERROR.EXISTING_ACCOUNT_REQUEST</span></div></div><div class="padding hidden-xs text-left"><button class="button button-assertive icon-left ion-chevron-left ink" ng-click="identifierRecovery()" translate>COMMON.BTN_MODIFY</button></div></div></ion-content></ion-slide-page></ion-slides></ion-modal-view> \ No newline at end of file +<ion-modal-view class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-if="!slides.slider.activeIndex" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button> <button class="button button-icon button-clear icon ion-ios-arrow-back buttons header-item" ng-click="doPrev()" ng-if="slides.slider.activeIndex && slideBehavior.hasPreviousButton"></button> <button class="button button-icon button-clear icon ion-ios-help-outline visible-xs" ng-if="slideBehavior.helpAnchor" ng-click="showHelpModal(slideBehavior.helpAnchor)"></button><h1 class="title" translate>ACCOUNT.NEW.MEMBER_ACCOUNT_TITLE</h1><button class="button button-clear icon-right visible-xs" ng-if="slideBehavior.hasNextButton" ng-click="doNext()"><span translate>COMMON.BTN_NEXT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-clear icon-right visible-xs" ng-class="{'button-text-stable': !isLicenseRead}" ng-if="slideBehavior.hasAcceptButton" ng-click="isLicenseRead ? doNext() : undefined"><span translate>ACCOUNT.NEW.BTN_ACCEPT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-clear icon-right visible-xs" ng-if="slideBehavior.hasSendButton" ng-click="doNewAccount()"><i class="icon ion-android-send"></i></button></ion-header-bar><ion-slides options="slides.options" slider="slides.slider"><ion-slide-page ng-if="licenseFileUrl"><ion-content class="has-header" scroll="false"><div class="padding" translate>ACCOUNT.NEW.INFO_LICENSE</div><div class="center padding" ng-if="loading"><ion-spinner class="icon" icon="android"></ion-spinner></div><iframe ng-if="!loading" class="padding-left padding-right no-padding-xs iframe-license" id="iframe-license" ng-src="{{licenseFileUrl}}"></iframe><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" ng-click="doNext('licenceForm')" ng-disabled="!isLicenseRead" type="button" translate>ACCOUNT.NEW.BTN_ACCEPT_LICENSE</button></div></ion-content></ion-slide-page><ion-slide-page><ion-content class="has-header" scroll="true"><form name="pseudoForm" novalidate="" ng-submit="doNext('pseudoForm')"><div class="item item-text-wrap text-center padding"><a class="pull-right icon-help hidden-xs" ng-click="showHelpModal('join-pseudo')"></a> <span translate>ACCOUNT.NEW.PSEUDO_WARNING</span></div><div class="list" ng-init="setForm(pseudoForm, 'pseudoForm')"><div class="item item-input" ng-class="{'item-input-error': (pseudoForm.$submitted && pseudoForm.pseudo.$invalid) || (uiAlreadyUsed && formData.pseudo)}"><span class="input-label" translate>ACCOUNT.NEW.PSEUDO</span> <input id="pseudo" name="pseudo" type="text" placeholder="{{'ACCOUNT.NEW.PSEUDO_HELP' | translate}}" ng-model="formData.pseudo" autocomplete="off" ng-minlength="3" ng-maxlength="100" ng-pattern="userIdPattern" ng-model-options="{ debounce: 250 }" required></div><div class="form-errors" ng-show="pseudoForm.$submitted && pseudoForm.pseudo.$error" ng-messages="pseudoForm.pseudo.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT_WITH_LENGTH" translate-values="{minLength: 3}"></span></div><div class="form-error" ng-message="maxlength"><span translate="ERROR.FIELD_TOO_LONG_WITH_LENGTH" translate-values="{maxLength: 100}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="pattern"><span translate="ERROR.INVALID_USER_ID"></span></div></div><div class="text-right" style="min-height: 18px"><div class="form-error gray" ng-if="formData.computing && formData.pseudo"><ion-spinner class="icon ion-spinner-small" icon="android" ng-if="formData.computing && formData.pseudo"></ion-spinner><span translate>ACCOUNT.NEW.CHECKING_PSEUDO</span></div><ng-if ng-if="!formData.computing && formData.pseudo"><div class="form-error balanced" ng-if="!uiAlreadyUsed "><i class="icon ion-checkmark balanced"></i> <span translate>ACCOUNT.NEW.PSEUDO_AVAILABLE</span></div><div class="form-error" ng-if="uiAlreadyUsed"><i class="icon ion-close-circled assertive"></i> <span translate>ACCOUNT.NEW.PSEUDO_NOT_AVAILABLE</span></div></ng-if></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" ng-disabled="uiAlreadyUsed" translate>COMMON.BTN_NEXT</button></div></div></form></ion-content></ion-slide-page><ion-slide-page ng-if="!formData.pubkey"><ion-content class="has-header" scroll="true"><form name="saltForm" novalidate="" ng-submit="doNext('saltForm')"><div class="list" ng-init="setForm(saltForm, 'saltForm')"><div class="item item-text-wrap text-center padding hidden-xs"><a class="pull-right icon-help" ng-click="showHelpModal('join-salt')"></a> <span translate>ACCOUNT.NEW.SALT_WARNING</span></div><div class="item item-input" ng-class="{ 'item-input-error': saltForm.$submitted && saltForm.username.$invalid}"><span class="input-label" translate>LOGIN.SALT</span> <input ng-if="!showUsername" name="username" type="password" placeholder="{{'LOGIN.SALT_HELP' | translate}}" ng-change="formDataChanged()" ng-model="formData.username" autocomplete="off" ng-minlength="8" different-to="formData.pseudo" required> <input ng-if="showUsername" name="username" type="text" placeholder="{{'LOGIN.SALT_HELP' | translate}}" ng-change="formDataChanged()" ng-model="formData.username" autocomplete="off" ng-minlength="8" different-to="formData.pseudo" required></div><div class="form-errors" ng-show="saltForm.$submitted && saltForm.username.$error" ng-messages="saltForm.username.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT_WITH_LENGTH" translate-values="{minLength: 8}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="differentTo"><span translate="ERROR.EQUALS_TO_PSEUDO"></span></div></div><div class="item item-input" ng-class="{ 'item-input-error': saltForm.$submitted && saltForm.confirmSalt.$invalid}"><span class="input-label pull-right" translate>ACCOUNT.NEW.SALT_CONFIRM</span> <input ng-if="!showUsername" name="confirmUsername" type="password" placeholder="{{'ACCOUNT.NEW.SALT_CONFIRM_HELP' | translate}}" ng-model="formData.confirmUsername" autocomplete="off" compare-to="formData.username"> <input ng-if="showUsername" name="confirmUsername" type="text" placeholder="{{'ACCOUNT.NEW.SALT_CONFIRM_HELP' | translate}}" ng-model="formData.confirmUsername" autocomplete="off" compare-to="formData.username"></div><div class="form-errors" ng-show="saltForm.$submitted && saltForm.confirmUsername.$error" ng-messages="saltForm.confirmUsername.$error"><div class="form-error" ng-message="compareTo"><span translate="ERROR.SALT_NOT_CONFIRMED"></span></div></div><div class="item item-toggle dark"><span translate>COMMON.SHOW_VALUES</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="showUsername"><div class="track"><div class="handle"></div></div></label></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" translate>COMMON.BTN_NEXT <i class="icon ion-arrow-right-a"></i></button></div></div></form></ion-content></ion-slide-page><ion-slide-page ng-if="!formData.pubkey"><ion-content class="has-header" scroll="true"><form name="passwordForm" novalidate="" ng-submit="doNext('passwordForm')"><div class="item item-text-wrap text-center padding hidden-xs"><a class="pull-right icon-help" ng-click="showHelpModal('join-password')"></a> <span translate>ACCOUNT.NEW.PASSWORD_WARNING</span></div><div class="list" ng-init="setForm(passwordForm, 'passwordForm')"><div class="item item-input" ng-class="{ 'item-input-error': passwordForm.$submitted && passwordForm.password.$invalid}"><span class="input-label" translate>LOGIN.PASSWORD</span> <input ng-if="!showPassword" name="password" type="password" placeholder="{{'LOGIN.PASSWORD_HELP' | translate}}" ng-model="formData.password" autocomplete="off" ng-change="formDataChanged()" ng-minlength="8" different-to="formData.username" required> <input ng-if="showPassword" name="text" type="text" placeholder="{{'LOGIN.PASSWORD_HELP' | translate}}" ng-model="formData.password" autocomplete="off" ng-change="formDataChanged()" ng-minlength="8" different-to="formData.username" required></div><div class="form-errors" ng-show="passwordForm.$submitted && passwordForm.password.$error" ng-messages="passwordForm.password.$error"><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT_WITH_LENGTH" translate-values="{minLength: 8}"></span></div><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="differentTo"><span translate="ERROR.EQUALS_TO_SALT"></span></div></div><div class="item item-input" ng-class="{ 'item-input-error': passwordForm.$submitted && passwordForm.confirmPassword.$invalid}"><span class="input-label" translate>ACCOUNT.NEW.PASSWORD_CONFIRM</span> <input ng-if="!showPassword" name="confirmPassword" type="password" placeholder="{{'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP' | translate}}" ng-model="formData.confirmPassword" autocomplete="off" compare-to="formData.password"> <input ng-if="showPassword" name="confirmPassword" type="text" placeholder="{{'ACCOUNT.NEW.PASSWORD_CONFIRM_HELP' | translate}}" ng-model="formData.confirmPassword" autocomplete="off" compare-to="formData.password"></div><div class="form-errors" ng-show="passwordForm.$submitted && passwordForm.confirmPassword.$error" ng-messages="passwordForm.confirmPassword.$error"><div class="form-error" ng-message="compareTo"><span translate="ERROR.PASSWORD_NOT_CONFIRMED"></span></div></div><div class="item item-toggle dark"><span translate>COMMON.SHOW_VALUES</span><label class="toggle toggle-royal"><input type="checkbox" ng-model="showPassword"><div class="track"><div class="handle"></div></div></label></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-calm icon-right ion-chevron-right ink" type="submit" ng-click="getRevocationDocument()" translate>COMMON.BTN_NEXT</button></div><div class="padding hidden-xs"></div></form></ion-content></ion-slide-page><ion-slide-page><ion-content class="has-header" scroll="true"><div class="center padding" ng-if="formData.computing"><ion-spinner icon="android"></ion-spinner></div><ng-if ng-if="!formData.computing"><div class="animate-fade-in animate-show-hide ng-hide" ng-show="accountAvailable"><div class="padding text-center" translate>ACCOUNT.NEW.LAST_SLIDE_CONGRATULATION</div><div class="list"><ion-item class="item text-center item-text-wrap"><h3 class="gray" translate>LOGIN.ASSOCIATED_PUBKEY</h3><h3 class="dark bold">{{formData.pubkey}}</h3></ion-item></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" ng-click="doNewAccount()" translate>COMMON.BTN_SEND <i class="icon ion-android-send"></i></button></div></div><div class="animate-fade-in animate-show-hide ng-hide" ng-show="!accountAvailable"><ion-item class="item-icon-left item-text-wrap text-center"><i class="icon ion-minus-circled assertive"></i> <span id="modal-license" trust-as-html="'ERROR.EXISTING_ACCOUNT'|translate"></span></ion-item><div class="list"><ion-item class="item item-text-wrap item-border"><div class="padding text-center"><span class="gray text-no-wrap">{{formData.pubkey}}</span></div></ion-item><div class="padding text-center"><span translate>ERROR.EXISTING_ACCOUNT_REQUEST</span></div></div><div class="padding hidden-xs text-left"><button class="button button-assertive icon-left ion-chevron-left ink" ng-click="identifierRecovery()" translate>COMMON.BTN_MODIFY</button></div></div></ng-if></ion-content></ion-slide-page></ion-slides></ion-modal-view> \ No newline at end of file diff --git a/assets/www/templates/login/form_file_import.html b/assets/www/templates/login/form_file_import.html index c1918a4c1afc84bb478ed2a2e2e19370ea721fa3..32149eb0e3ecdc036cce7726007074b784408a64 100644 --- a/assets/www/templates/login/form_file_import.html +++ b/assets/www/templates/login/form_file_import.html @@ -1 +1 @@ -<div class="item"><p class="item-text-wrap" translate>LOGIN.FILE_FORM_HELP</p></div><div class="item item-icon-left item-text-wrap"><i class="icon ion-ios-information-outline positive"></i> <span class="positive" translate>LOGIN.FILE.HELP</span></div><div class="dropzone" dropzone="onKeyFileDrop(file)"><div ng-if="!formData.file" onclick="angular.element(document.querySelector('#loginImportFile'))[0].click();"><h2 class="gray" translate>COMMON.CHOOSE_FILE</h2><input type="file" id="loginImportFile" accept=".dunikey,.yml" style="visibility:hidden; position:absolute" onchange="angular.element(this).scope().fileChanged(event)"></div><div class="item item-icon-left item-icon-right stable-bg" ng-if="formData.file"><i class="icon ion-document-text dark"></i><div class="item-content row"><div class="col"><h2>{{formData.file.name}}</h2><h4 class="dark" ng-if="formData.file.lastModified"><span class="gray" translate>LOGIN.FILE.DATE</span> {{formData.file.lastModified/1000|formatDate}}</h4><h5 class="dark"><span class="gray" translate>LOGIN.FILE.SIZE</span> {{formData.file.size|formatInteger}} Ko</h5></div><div class="col"><h3><span class="gray" translate>COMMON.PUBKEY</span></h3><h3 ng-if="validatingFile" translate>LOGIN.FILE.VALIDATING</h3><h3 ng-if="!validatingFile"><span class="dark animate-show-hide ng-hide" ng-show="formData.file.pubkey">{{formData.file.pubkey}}</span> <span class="assertive animate-show-hide ng-hide" ng-show="!formData.file.valid"><br><i class="ion-close-circled assertive"></i> {{formData.file.pubkey ? 'ERROR.AUTH_INVALID_PUBKEY' : 'ERROR.AUTH_INVALID_FILE' |translate}}</span></h3></div></div><a class="ion-close-round gray pull-right" style="font-size: 10px; position: absolute; top: 6px; right: 6px" ng-click="removeKeyFile()"></a></div></div><ion-checkbox ng-model="formData.keepAuth" class="item ink item-text-wrap"><div class="item-content dark" translate>LOGIN.MEMORIZE_AUTH_FILE</div></ion-checkbox> \ No newline at end of file +<div class="item"><p class="item-text-wrap" translate>LOGIN.FILE_FORM_HELP</p></div><div class="item item-icon-left item-text-wrap"><i class="icon ion-ios-information-outline positive"></i> <span class="positive" translate>LOGIN.FILE.HELP</span></div><div dropzone="onKeyFileDrop(file)"><div ng-if="!formData.file" onclick="angular.element(document.querySelector('#loginImportFile'))[0].click();"><h2 class="gray" translate>COMMON.CHOOSE_FILE</h2><input type="file" id="loginImportFile" accept=".dunikey,.yml" style="visibility:hidden; position:absolute" onchange="angular.element(this).scope().fileChanged(event)"></div><div class="item item-icon-left item-icon-right stable-bg" ng-if="formData.file"><i class="icon ion-document-text dark"></i><div class="item-content row"><div class="col"><h2>{{formData.file.name}}</h2><h4 class="dark" ng-if="formData.file.lastModified"><span class="gray" translate>COMMON.FILE.DATE</span> {{formData.file.lastModified/1000|formatDate}}</h4><h5 class="dark"><span class="gray" translate>COMMON.FILE.SIZE</span> {{formData.file.size|formatInteger}} Ko</h5></div><div class="col"><h3><span class="gray" translate>COMMON.PUBKEY</span></h3><h3 ng-if="validatingFile" translate>COMMON.FILE.VALIDATING</h3><h3 ng-if="!validatingFile"><span class="dark animate-show-hide ng-hide" ng-show="formData.file.pubkey">{{formData.file.pubkey}}</span> <span class="assertive animate-show-hide ng-hide" ng-show="!formData.file.valid"><br><i class="ion-close-circled assertive"></i> {{formData.file.pubkey ? 'ERROR.AUTH_INVALID_PUBKEY' : 'ERROR.AUTH_INVALID_FILE' |translate}}</span></h3></div></div><a class="ion-close-round gray pull-right" style="font-size: 10px; position: absolute; top: 6px; right: 6px" ng-click="removeKeyFile()"></a></div></div><ion-checkbox ng-model="formData.keepAuth" class="item ink item-text-wrap"><div class="item-content dark" translate>LOGIN.MEMORIZE_AUTH_FILE</div></ion-checkbox> \ No newline at end of file diff --git a/assets/www/templates/login/form_login.html b/assets/www/templates/login/form_login.html index 6768d681bdc641a751c4413c1d55097a7adde832..d1a38b64cf98d8c160d84a3a2baa9f6675488293 100644 --- a/assets/www/templates/login/form_login.html +++ b/assets/www/templates/login/form_login.html @@ -1 +1 @@ -<form name="loginForm" novalidate="" ng-submit="doLogin()" autocomplete="off"><div class="list padding no-padding-xs" ng-init="setForm(loginForm)" ng-switch on="formData.method"><div class="item hidden-xs no-padding" ng-if="showMethods"><div class="pull-right"><a class="button button-text button-small-padding icon-right ink" ng-click="showMethodsPopover($event)"><i class="icon ion-wrench"></i> {{'LOGIN.BTN_METHODS'| translate}} </a> <a class="button button-icon positive button-small-padding icon ion-ios-help-outline" style="right: 8px" ng-click="showHelpModal('login-method')"></a></div></div><div ng-switch-when="SCRYPT_DEFAULT"><ng-include src="'templates/login/form_scrypt.html'"></ng-include></div><div ng-switch-when="SCRYPT_ADVANCED"><ng-include src="'templates/login/form_scrypt_advanced.html'"></ng-include></div><div ng-switch-when="PUBKEY"><ng-include src="'templates/login/form_pubkey.html'"></ng-include></div><div ng-switch-when="FILE"><ng-include src="'templates/login/form_file_import.html'"></ng-include></div><div ng-switch-default><ng-include src="'templates/login/form_scrypt.html'"></ng-include></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" ng-class="{'button-assertive': isAuth, 'button-positive': !isAuth}" type="submit">{{isAuth ? 'AUTH.BTN_AUTH' : 'COMMON.BTN_LOGIN' | translate}}</button></div><div class="text-center no-padding visible-xs"><br><a ng-click="showMethodsPopover($event)"><i class="ion-loop"></i> <span translate>LOGIN.BTN_METHODS_DOTS</span></a><br><br></div><ng-if ng-if="!isAuth"><div class="text-center no-padding">{{'LOGIN.NO_ACCOUNT_QUESTION'|translate}}<br class="visible-xs"><a ng-click="showJoinModal()" translate>LOGIN.CREATE_ACCOUNT</a></div><br class="visible-xs"><div class="text-center no-padding"><a ng-click="showAccountSecurityModal()" translate>LOGIN.FORGOTTEN_ID</a></div></ng-if></form> \ No newline at end of file +<form name="loginForm" novalidate="" ng-submit="doLogin()" autocomplete="off"><div class="list padding no-padding-xs" ng-init="setForm(loginForm)" ng-switch on="formData.method"><div class="item hidden-xs no-padding" ng-if="showMethods"><div class="pull-right"><a class="button button-text button-small-padding icon-right ink" ng-click="showMethodsPopover($event)"><i class="icon ion-wrench"></i> {{'LOGIN.BTN_METHODS'| translate}} </a> <a class="button button-icon positive button-small-padding icon ion-ios-help-outline" style="right: 8px" ng-click="showHelpModal('login-method')"></a></div></div><div class="item item-text-wrap" ng-if="::isAuth"><p ng-if="::expectedPubkey" ng-bind-html="::expectedUid ? 'AUTH.EXPECTED_UID_HELP' : 'AUTH.EXPECTED_PUBKEY_HELP' |translate: {uid: expectedUid, pubkey: expectedPubkey}"></p><p ng-if="::!expectedPubkey" ng-bind-html="::'AUTH.GENERAL_HELP'|translate"></p></div><div ng-switch-when="SCRYPT_DEFAULT"><ng-include src="'templates/login/form_scrypt.html'"></ng-include></div><div ng-switch-when="SCRYPT_ADVANCED"><ng-include src="'templates/login/form_scrypt_advanced.html'"></ng-include></div><div ng-switch-when="PUBKEY"><ng-include src="'templates/login/form_pubkey.html'"></ng-include></div><div ng-switch-when="FILE"><ng-include src="'templates/login/form_file_import.html'"></ng-include></div><div ng-switch-when="SCAN"><ng-include src="'templates/login/form_scan.html'"></ng-include></div><div ng-switch-default><ng-include src="'templates/login/form_scrypt.html'"></ng-include></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" ng-class="{'button-assertive': isAuth, 'button-positive': !isAuth}" type="submit">{{okText || (isAuth ? 'AUTH.BTN_AUTH' : 'COMMON.BTN_LOGIN') | translate}}</button></div><div class="text-center no-padding visible-xs"><button type="button" class="button button-small icon-right ink" ng-click="showMethodsPopover($event)"><i class="icon ion-loop"></i> <span translate>LOGIN.BTN_METHODS_DOTS</span></button><br><br></div><ng-if ng-if="!isAuth && showNewAccountLink"><div class="text-center no-padding">{{'LOGIN.NO_ACCOUNT_QUESTION'|translate}}<br class="visible-xs"><a ng-click="showJoinModal()" translate>LOGIN.CREATE_ACCOUNT</a></div><br class="visible-xs"><div class="text-center no-padding"><a ng-click="showAccountSecurityModal()" translate>LOGIN.FORGOTTEN_ID</a></div></ng-if></form> \ No newline at end of file diff --git a/assets/www/templates/login/form_pubkey.html b/assets/www/templates/login/form_pubkey.html index b282fc08678ff5f5ec29cb07ab10aac828143466..64a16b325799412839d21533b063af778c1623ef 100644 --- a/assets/www/templates/login/form_pubkey.html +++ b/assets/www/templates/login/form_pubkey.html @@ -1 +1 @@ -<div class="item"><p class="item-text-wrap" translate>LOGIN.PUBKEY_FORM_HELP</p></div><div class="item item-input item-button-right" ng-class="{ 'item-input-error': form.$submitted && form.pubkey.$invalid}"><span class="input-label hidden-xs" translate>COMMON.PUBKEY</span> <input name="pubkey" type="text" placeholder="{{'LOGIN.PUBKEY_HELP' | translate}}" ng-model="formData.pubkey" ng-model-options="{ debounce: 650 }" ng-pattern="pubkeyPattern" required> <a class="button button-stable icon ion-android-search ink" ng-click="showWotLookupModal()"></a></div><div class="form-errors" ng-show="form.$submitted && form.pubkey.$error" ng-messages="form.pubkey.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="pattern"><span translate="ERROR.INVALID_PUBKEY"></span></div></div> \ No newline at end of file +<div class="item"><p class="item-text-wrap" translate>LOGIN.PUBKEY_FORM_HELP</p></div><div class="item item-input item-button-right" ng-class="{ 'item-input-error': form.$submitted && form.pubkey.$invalid}"><span class="input-label hidden-xs" translate>COMMON.PUBKEY</span> <input name="pubkey" type="text" placeholder="{{'LOGIN.PUBKEY_HELP' | translate}}" autocomplete="off" ng-model="formData.pubkey" ng-model-options="{ debounce: 650 }" required> <a class="button button-stable icon ion-android-search ink" ng-click="showWotLookupModal(form.pubkey.$viewValue)"></a></div><div class="form-errors" ng-show="form.$submitted && form.pubkey.$error" ng-messages="form.pubkey.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="checksum"><span translate="ERROR.INVALID_PUBKEY_CHECKSUM"></span></div></div> \ No newline at end of file diff --git a/assets/www/templates/login/form_scan.html b/assets/www/templates/login/form_scan.html new file mode 100644 index 0000000000000000000000000000000000000000..3514625499f89e6812bbc17d3d0553993671a456 --- /dev/null +++ b/assets/www/templates/login/form_scan.html @@ -0,0 +1 @@ +<div class="item"><p class="item-text-wrap" ng-bind-html="::isAuth ? 'AUTH.SCAN_FORM_HELP' : 'LOGIN.SCAN_FORM_HELP' |translate"></p></div><div class="item item-icon-right item-text-wrap item-input" ng-class="{ 'item-input-error': pubkeyError}"><span class="input-label" translate>COMMON.PUBKEY</span><div class="item-content text-wrap"><span class="gray animate-show-hide" ng-show="!computing && formData.pubkey">{{formData.pubkey}}</span><ion-spinner class="ion-spinner-small" icon="android" ng-if="computing"></ion-spinner><input type="hidden" ng-model="formData.pubkey" required></div><a class="button button-icon positive button-small-padding icon ion-qr-scanner animate-show-hide" ng-show="!computing && (!expectedPubkey || pubkeyError)" ng-click="doScan()"></a> <span class="button button-icon balanced button-small-padding icon ion-checkmark animate-show-hide" ng-if="expectedPubkey" ng-show="!computing && !pubkeyError"></span></div><div class="form-errors" ng-if="expectedPubkey"><div class="form-error" ng-show="pubkeyError"><span trust-as-html="::'ERROR.AUTH_INVALID_PUBKEY'|translate:{pubkey: expectedPubkey}"></span></div></div> \ No newline at end of file diff --git a/assets/www/templates/login/form_scrypt.html b/assets/www/templates/login/form_scrypt.html index 9c864d9e9aba3aeb436f3c4cabe9c73c6901d499..5c61869f75aee6dd8bdb125d6f26ceb5eefdceb4 100644 --- a/assets/www/templates/login/form_scrypt.html +++ b/assets/www/templates/login/form_scrypt.html @@ -1 +1 @@ -<div class="item item-text-wrap"><p ng-bind-html="isAuth ? 'AUTH.SCRYPT_FORM_HELP': 'LOGIN.SCRYPT_FORM_HELP'|translate"></p></div><input type="password" name="fake-password" autocomplete="off" style="visibility:hidden; position:absolute"><label class="item item-input" ng-class="{ 'item-input-error': form.$submitted && form.username.$invalid}"><span class="input-label hidden-xs" translate>LOGIN.SALT</span> <input name="username" type="password" placeholder="{{'LOGIN.SALT_HELP' | translate}}" autocomplete="off" ng-model="formData.username" ng-model-options="{ debounce: 650 }" class="highlight-light" required></label><div class="form-errors" ng-show="form.$submitted && form.username.$error" ng-messages="form.username.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><label class="item item-input" ng-class="{ 'item-input-error': form.$submitted && form.password.$invalid}"><span class="input-label hidden-xs" translate>LOGIN.PASSWORD</span> <input name="password" type="password" placeholder="{{'LOGIN.PASSWORD_HELP' | translate}}" autocomplete="off" ng-model="formData.password" ng-model-options="{ debounce: 650 }" select-on-click required></label><div class="form-errors" ng-show="form.$submitted && form.password.$error" ng-messages="form.password.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-icon-right item-text-wrap" ng-class="{ 'item-input-error': pubkeyError, 'item-input': showPubkey}"><span class="input-label hidden-xs animate-show-hide ng-hide" ng-show="showPubkey" translate>COMMON.PUBKEY</span><div class="item-content text-wrap"><a class="positive ink animate-show-hide ng-hide" ng-show="showComputePubkeyButton && !pubkey" ng-click="computePubkey()"><i class="ion-eye"></i> {{'COMMON.BTN_SHOW_PUBKEY' | translate}} </a><span class="gray animate-show-hide" ng-show="!computing && pubkey">{{pubkey}}</span><ion-spinner class="ion-spinner-small" icon="android" ng-if="computing"></ion-spinner></div><a class="button button-icon positive button-small-padding icon ion-ios-help-outline animate-show-hide" ng-click="showHelpModal('login-pubkey')" ng-if="!expectedPubkey" ng-show="showPubkey"></a> <span class="button button-icon balanced button-small-padding icon ion-checkmark animate-show-hide" ng-if="expectedPubkey" ng-show="showPubkey && !showComputePubkeyButton && !computing && !pubkeyError"></span></div><div class="form-errors" ng-if="expectedPubkey"><div class="form-error" ng-show="pubkeyError"><span trust-as-html="::'ERROR.AUTH_INVALID_PUBKEY'|translate:{pubkey: expectedPubkey}"></span></div></div> \ No newline at end of file +<div class="item item-text-wrap" ng-if="!isAuth"><p ng-bind-html="'LOGIN.SCRYPT_FORM_HELP'|translate"></p></div><input type="password" name="fake-password" autocomplete="off" style="visibility:hidden; position:absolute"><label class="item item-input" ng-class="{ 'item-input-error': form.$submitted && form.username.$invalid}"><span class="input-label hidden-xs" translate>LOGIN.SALT</span> <input name="username" type="password" placeholder="{{'LOGIN.SALT_HELP' | translate}}" autocomplete="off" ng-model="formData.username" ng-model-options="{ debounce: 650 }" class="highlight-light" required></label><div class="form-errors" ng-show="form.$submitted && form.username.$error" ng-messages="form.username.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><label class="item item-input" ng-class="{ 'item-input-error': form.$submitted && form.password.$invalid}"><span class="input-label hidden-xs" translate>LOGIN.PASSWORD</span> <input name="password" type="password" placeholder="{{'LOGIN.PASSWORD_HELP' | translate}}" autocomplete="off" ng-model="formData.password" ng-model-options="{ debounce: 650 }" select-on-click required></label><div class="form-errors" ng-show="form.$submitted && form.password.$error" ng-messages="form.password.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="item item-icon-right item-text-wrap" ng-class="{ 'item-input-error': pubkeyError, 'item-input': showPubkey}"><span class="input-label hidden-xs animate-show-hide ng-hide" ng-show="showPubkey" translate>COMMON.PUBKEY</span><div class="item-content text-wrap"><a class="positive ink animate-show-hide ng-hide" ng-show="showComputePubkeyButton && !pubkey" ng-click="computePubkey()"><i class="ion-eye"></i> {{'COMMON.BTN_SHOW_PUBKEY' | translate}} </a><span class="gray animate-show-hide" ng-show="!computing && pubkey">{{pubkey}}</span><ion-spinner class="ion-spinner-small" icon="android" ng-if="computing"></ion-spinner></div><a class="button button-icon positive button-small-padding icon ion-ios-help-outline animate-show-hide" ng-click="showHelpModal('login-pubkey')" ng-if="!expectedPubkey" ng-show="showPubkey"></a> <span class="button button-icon balanced button-small-padding icon ion-checkmark animate-show-hide" ng-if="expectedPubkey" ng-show="showPubkey && !showComputePubkeyButton && !computing && !pubkeyError"></span></div><div class="form-errors" ng-if="expectedPubkey"><div class="form-error" ng-show="pubkeyError"><span trust-as-html="::'ERROR.AUTH_INVALID_PUBKEY'|translate:{pubkey: expectedPubkey}"></span></div></div> \ No newline at end of file diff --git a/assets/www/templates/login/form_scrypt_advanced.html b/assets/www/templates/login/form_scrypt_advanced.html index 34149552e6de1bf0f9758ca2c52212d293395c96..4ceaca4f422ff716774cdf77b520ed189aef6a7f 100644 --- a/assets/www/templates/login/form_scrypt_advanced.html +++ b/assets/www/templates/login/form_scrypt_advanced.html @@ -1 +1 @@ -<div class="row responsive-md responsive-sm padding-left"><div class="col col-33 no-padding"><label class="item item-input item-select"><select ng-model="formData.scrypt" style="max-width: 100%" ng-change="changeScrypt(formData.scrypt)" ng-options="l as (l.label | translate) for l in scryptParamsValues track by l.id"></select></label></div><div class="col no-padding"><label class="item item-input"><span class="input-label" translate>LOGIN.SCRYPT.N</span> <input class="no-padding-right" type="number" placeholder="N" ng-model="formData.scrypt.params.N" ng-model-options="{ debounce: 650 }" ng-change="onScryptFormChanged()" required></label></div><div class="col no-padding"><label class="item item-input"><span class="input-label" translate>LOGIN.SCRYPT.r</span> <input class="no-padding-right" type="number" placeholder="r" ng-model="formData.scrypt.params.r" ng-model-options="{ debounce: 650 }" ng-change="onScryptFormChanged()" required></label></div><div class="col no-padding"><label class="item item-input"><span class="input-label" translate>LOGIN.SCRYPT.p</span> <input class="no-padding-right" type="number" placeholder="p" ng-model="formData.scrypt.params.p" ng-model-options="{ debounce: 650 }" ng-change="onScryptFormChanged()" required></label></div></div><p class="energized-100-bg padding"><i class="icon ion-android-warning"></i> <span translate>INFO.FEATURES_NOT_IMPLEMENTED</span></p><ng-include src="'templates/login/form_scrypt.html'"></ng-include> \ No newline at end of file +<div class="row responsive-md responsive-sm padding-left"><div class="col col-33 no-padding"><label class="item item-input item-select"><select ng-model="formData.scrypt" style="max-width: 100%" ng-change="changeScrypt(formData.scrypt)" ng-options="l as (l.label | translate) for l in scryptParamsValues track by l.id"></select></label></div><div class="col no-padding"><label class="item item-input"><span class="input-label" translate>LOGIN.SCRYPT.N</span> <input class="no-padding-right" type="number" placeholder="N" autocomplete="off" ng-model="formData.scrypt.params.N" ng-model-options="{ debounce: 650 }" ng-change="onScryptFormChanged()" required></label></div><div class="col no-padding"><label class="item item-input"><span class="input-label" translate>LOGIN.SCRYPT.r</span> <input class="no-padding-right" type="number" placeholder="r" ng-model="formData.scrypt.params.r" autocomplete="off" ng-model-options="{ debounce: 650 }" ng-change="onScryptFormChanged()" required></label></div><div class="col no-padding"><label class="item item-input"><span class="input-label" translate>LOGIN.SCRYPT.p</span> <input class="no-padding-right" type="number" placeholder="p" autocomplete="off" ng-model="formData.scrypt.params.p" ng-model-options="{ debounce: 650 }" ng-change="onScryptFormChanged()" required></label></div></div><p class="energized-100-bg padding dark"><i class="icon ion-android-warning"></i> <span translate>INFO.FEATURES_NOT_IMPLEMENTED</span></p><ng-include src="'templates/login/form_scrypt.html'"></ng-include> \ No newline at end of file diff --git a/assets/www/templates/login/modal_login.html b/assets/www/templates/login/modal_login.html index 5871369acad78d917d1418f57a196f812bd16d44..93fba2368225fa29de29dd19055ef58aea4eb054 100644 --- a/assets/www/templates/login/modal_login.html +++ b/assets/www/templates/login/modal_login.html @@ -1 +1 @@ -<ion-modal-view class="modal-full-height modal-login"><ion-header-bar class="" ng-class="{'bar-positive': !isAuth, 'bar-assertive': isAuth}"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" ng-bind-html="isAuth ? 'AUTH.TITLE' : 'LOGIN.TITLE' | translate"></h1><div class="buttons buttons-right"><div class="secondary-buttons"><button class="button button-positive button-icon button-clear icon ion-android-done visible-xs" ng-click="doLogin()"></button></div></div></ion-header-bar><ion-content><ng-include src="'templates/login/form_login.html'"></ng-include></ion-content></ion-modal-view> \ No newline at end of file +<ion-modal-view class="modal-full-height modal-login"><ion-header-bar class="" ng-class="{'bar-positive': !isAuth, 'bar-assertive': isAuth}"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" ng-bind-html="title | translate"></h1><div class="buttons buttons-right"><div class="secondary-buttons"><button class="button button-icon button-clear icon ion-android-done visible-xs" ng-class="{'button-positive': !isAuth}" style="color: #fff" ng-click="doLogin()"></button></div></div></ion-header-bar><ion-content scroll="true"><ng-include src="'templates/login/form_login.html'"></ng-include></ion-content></ion-modal-view> \ No newline at end of file diff --git a/assets/www/templates/login/popover_methods.html b/assets/www/templates/login/popover_methods.html index 7173075f69d8d43bb55d8986abe8d5acaaad8e12..892d6232bc265fa6c44b43765d70d64c40419097 100644 --- a/assets/www/templates/login/popover_methods.html +++ b/assets/www/templates/login/popover_methods.html @@ -1 +1 @@ -<ion-popover-view class="fit has-header popover-login-methods" ng-class="{'auth': isAuth}"><ion-header-bar><h1 class="title" translate>LOGIN.METHOD_POPOVER_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-click="changeMethod('SCRYPT_DEFAULT')"><i class="icon ion-shuffle" style="font-size: 22px"></i> {{'LOGIN.METHOD.SCRYPT_DEFAULT' | translate}} </a><a class="item item-icon-left ink" ng-click="changeMethod('SCRYPT_ADVANCED')"><i class="icon ion-shuffle" style="font-size: 22px"></i> <i class="icon-secondary ion-plus" style="font-size: 13px; left: 40px; margin-top: -4px"></i> {{'LOGIN.METHOD.SCRYPT_ADVANCED' | translate}} </a><a class="item item-icon-left ink hidden-xs" ng-click="changeMethod('FILE')"><i class="icon ion-document-text"></i> {{'LOGIN.METHOD.FILE' | translate}}</a><ng-if ng-if="!isAuth"><div class="item-divider"></div><a class="item item-icon-left ink" ng-click="changeMethod('PUBKEY')"><i class="icon ion-key"></i> {{'LOGIN.METHOD.PUBKEY' | translate}}</a></ng-if></div></ion-content></ion-popover-view> \ No newline at end of file +<ion-popover-view class="fit has-header popover-login-methods" ng-class="{'auth': isAuth}"><ion-header-bar><h1 class="title" translate="">LOGIN.METHOD_POPOVER_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><a class="item item-icon-left ink" ng-click="changeMethod('SCRYPT_DEFAULT')"><i class="icon ion-shuffle" style="font-size: 22px"></i> {{'LOGIN.METHOD.SCRYPT_DEFAULT' | translate}} </a><a class="item item-icon-left ink" ng-click="changeMethod('SCRYPT_ADVANCED')"><i class="icon ion-shuffle" style="font-size: 22px"></i> <i class="icon-secondary ion-plus" style="font-size: 13px; left: 40px; margin-top: -4px"></i> {{'LOGIN.METHOD.SCRYPT_ADVANCED' | translate}} </a><a class="item item-icon-left ink hidden-xs" ng-click="changeMethod('FILE')"><i class="icon ion-document-text"></i> {{'LOGIN.METHOD.FILE' | translate}} </a><a class="item item-icon-left ink" ng-if="$root.device.barcode.enable" ng-click="changeMethod('SCAN')"><i class="icon ion-qr-scanner"></i> {{'LOGIN.METHOD.SCAN' | translate}} </a><a class="item item-icon-left ink" ng-if="!isAuth" ng-click="changeMethod('PUBKEY')"><i class="icon ion-key"></i> {{'LOGIN.METHOD.PUBKEY' | translate}}</a></div></ion-content></ion-popover-view> \ No newline at end of file diff --git a/assets/www/templates/menu.html b/assets/www/templates/menu.html index 5f618265986e65ea773ff243ae6e6149e4d71e8b..b3a5b8384fecc3d82a22864098862d98de98f017 100644 --- a/assets/www/templates/menu.html +++ b/assets/www/templates/menu.html @@ -1 +1 @@ -<ion-side-menus enable-menu-with-back-views="true" bind-notifier="{locale:$root.settings.locale.id}"><ion-side-menu-content><ion-nav-bar class="bar-dark" title-align="left"><ion-nav-back-button class="no-text"></ion-nav-back-button><ion-nav-buttons side="left"><button class="button button-icon button-clear icon ion-navicon visible-nomenu" menu-toggle="left"></button></ion-nav-buttons><ion-nav-buttons side="right"><cs-extension-point name="nav-buttons-right"></cs-extension-point></ion-nav-buttons></ion-nav-bar><ion-nav-view name="menuContent"></ion-nav-view></ion-side-menu-content><ion-side-menu id="menu" side="left" expose-aside-when="large" enable-menu-with-back-views="false" width="225"><ion-header-bar><div class="visible-sm visible-xs hero"><div class="content"><i class="avatar avatar-member hero-icon" ng-if="!$root.walletData.avatar" ng-class="{'royal-bg': login, 'stable-bg': !login}" ng-click="!login ? showHome() : loginAndGo()" menu-close=""></i> <a class="avatar hero-icon" ng-if="$root.walletData.avatar" style="background-image: url('{{$root.walletData.avatar.src}}')" ui-sref="app.view_wallet" menu-close=""></a><h4 ng-if="login"><a class="light" ui-sref="app.view_wallet" menu-close="">{{$root.walletData.name||$root.walletData.uid}} <span ng-if="!$root.walletData.name && !$root.walletData.uid"><i class="icon ion-key"></i> {{$root.walletData.pubkey|formatPubkey}}</span></a></h4><h4 ng-if="!login"><a class="light" ui-sref="app.home" menu-close="">{{'COMMON.BTN_LOGIN'|translate}} <i class="ion-arrow-right-b"></i></a></h4><cs-extension-point name="menu-profile-user"></cs-extension-point></div><a ng-if="login" class="button-icon" ng-click="logout({askConfirm: true})" style="position: absolute; top: 5px; left: 5px"><i class="icon stable ion-android-exit"></i></a></div></ion-header-bar><ion-content scroll="false"><ion-list class="list"><ion-item menu-close="" class="item-icon-left hidden-xs" ui-sref="app.home" active-link="active"><i class="icon ion-home"></i> {{:locale:'MENU.HOME'|translate}}</ion-item><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/currency" ui-sref="app.currency"><i class="icon ion-ios-world-outline"></i> {{:locale:'MENU.CURRENCY'|translate}} </a><a id="helptip-menu-btn-currency"></a> <a id="helptip-menu-btn-network"></a><cs-extension-point name="menu-discover"></cs-extension-point><div class="item item-divider"></div><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/wot" ui-sref="app.wot_lookup.tab_search"><i class="icon ion-person-stalker"></i> {{:locale:'MENU.WOT'|translate}} </a><a id="helptip-menu-btn-wot"></a><cs-extension-point name="menu-main"></cs-extension-point><div class="item item-divider"></div><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/wallet" ui-sref="app.view_wallet" ng-class="{'item-menu-disable': !login}"><i class="icon ion-person"></i> {{:locale:'MENU.ACCOUNT'|translate}} </a><a id="helptip-menu-btn-account"></a> <a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/history" ui-sref="app.view_wallet_tx" ng-class="{'item-menu-disable': !login}"><i class="icon ion-card"></i> {{:locale:'MENU.TRANSACTIONS'|translate}} </a><a id="helptip-menu-btn-tx"></a><div class="item item-divider visible-xs visible-sm"></div><cs-extension-point name="menu-user"></cs-extension-point><a menu-close="" class="item item-icon-left visible-xs visible-sm" active-link="active" active-link-path-prefix="#/app/settings" ui-sref="app.settings"><i class="icon ion-android-settings"></i> {{:locale:'MENU.SETTINGS'|translate}} </a><a id="helptip-menu-btn-settings"></a><div class="item item-divider" ng-if="login"></div><ion-item menu-close="" class="item item-button-right" ng-if="$root.device.barcode.enable">{{:locale:'MENU.SCAN'|translate}} <button class="button button-stable ink" ng-click="scanQrCodeAndGo()"><i class="icon ion-qr-scanner"></i></button></ion-item><cs-extension-point name="menu-actions"></cs-extension-point></ion-list></ion-content></ion-side-menu></ion-side-menus> \ No newline at end of file +<ion-side-menus enable-menu-with-back-views="true" bind-notifier="{locale:$root.settings.locale.id}"><ion-side-menu-content><ion-nav-bar class="bar-dark" title-align="left"><ion-nav-back-button class="no-text"></ion-nav-back-button><ion-nav-buttons side="left"><button class="button button-icon button-clear icon ion-navicon visible-nomenu" menu-toggle="left"></button></ion-nav-buttons><ion-nav-buttons side="right"><cs-extension-point name="nav-buttons-right"></cs-extension-point></ion-nav-buttons></ion-nav-bar><ion-nav-view name="menuContent"></ion-nav-view></ion-side-menu-content><ion-side-menu id="menu" side="left" expose-aside-when="large" enable-menu-with-back-views="false" width="225"><ion-header-bar class="bar-title"><div class="visible-sm visible-xs hero"><div class="content"><i class="avatar avatar-member hero-icon" ng-if="!walletData.avatar" ng-class="{'royal-bg': login, 'stable-bg': !login}" ng-click="!login ? showHome() : loginAndGo()" menu-close=""></i> <a class="avatar hero-icon" ng-if="walletData.avatar" style="background-image: url('{{walletData.avatar.src}}')" ui-sref="app.view_wallet" menu-close=""></a><h4 ng-if="login"><a class="light" ui-sref="app.view_wallet" menu-close="">{{walletData.name||walletData.uid}} <span ng-if="!walletData.name && !walletData.uid"><i class="icon ion-key"></i> {{walletData.pubkey|formatPubkey}}</span></a></h4><h4 ng-if="!login"><a class="light" ui-sref="app.login" menu-close="">{{'COMMON.BTN_LOGIN'|translate}} <i class="ion-arrow-right-b"></i></a></h4><cs-extension-point name="menu-profile-user"></cs-extension-point></div><a ng-if="login" class="button-icon" ng-click="logout({askConfirm: true})" style="position: absolute; top: 5px; left: 5px; z-index: 999"><i class="icon light ion-android-exit"></i></a></div></ion-header-bar><ion-content scroll="false" class="scroll-content ionic-scroll" ng-class="{'overflow-scroll': smallscreen, 'scroll-content-false': !smallscreen}"><ion-list class="list" ng-class="{'scroll': smallscreen}"><ion-item menu-close="" class="item-icon-left hidden-xs" ui-sref="app.home" active-link="active"><i class="icon ion-home"></i> {{:locale:'MENU.HOME'|translate}}</ion-item><ion-item menu-close="" ng-if="!login" class="item-icon-left visible-xs" ui-sref="app.home" active-link="active"><i class="icon ion-home"></i> {{:locale:'MENU.HOME'|translate}}</ion-item><div class="item item-divider"></div><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/account" ui-sref="app.view_wallet" ng-class="{'item-menu-disable': !login}"><i class="icon ion-person"></i> {{:locale:'MENU.ACCOUNT'|translate}} </a><a id="helptip-menu-btn-account"></a> <a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/history" ui-sref="app.view_wallet_tx" ng-class="{'item-menu-disable': !login}"><i class="icon ion-card"></i> {{:locale:'MENU.TRANSACTIONS'|translate}} </a><a id="helptip-menu-btn-tx"></a> <a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/wallets" ui-sref="app.view_wallets" ng-class="{'item-menu-disable': !login}"><i class="icon ion-card" style="top: -5px; left: 22px; font-size: 18px"></i> <i class="icon-secondary ion-card" style="top: 22px; left: 19px; font-size: 20px; background-color: white; width:17px; height: 14px"></i> {{:locale:'MENU.WALLETS'|translate}}</a><div class="item item-divider"></div><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/wot" ui-sref="app.wot_lookup.tab_search"><i class="icon ion-person-stalker"></i> {{:locale:'MENU.WOT'|translate}} </a><a id="helptip-menu-btn-wot"></a><cs-extension-point name="menu-main"></cs-extension-point><div class="item item-divider"></div><a menu-close="" class="item item-icon-left" active-link="active" active-link-path-prefix="#/app/currency" ui-sref="app.currency"><i class="icon ion-ios-world-outline"></i> {{:locale:'MENU.CURRENCY'|translate}} </a><a id="helptip-menu-btn-currency"></a> <a id="helptip-menu-btn-network"></a><cs-extension-point name="menu-discover"></cs-extension-point><div class="item item-divider visible-xs visible-sm"></div><cs-extension-point name="menu-user"></cs-extension-point><a menu-close="" class="item item-icon-left visible-xs visible-sm" active-link="active" active-link-path-prefix="#/app/settings" ui-sref="app.settings"><i class="icon ion-android-settings"></i> {{:locale:'MENU.SETTINGS'|translate}} </a><a id="helptip-menu-btn-settings"></a><div class="item item-divider" ng-if="login"></div><ion-item menu-close="" class="item item-button-right" ng-if="login" ng-class="::{'item-button-left': $root.device.barcode.enable}"><button class="button button-positive ink-dark" ng-click="showTransferModal()"><i class="icon ion-paper-airplane"></i></button> <button class="button button-stable ink" ng-if="$root.device.barcode.enable" ng-click="scanQrCodeAndGo()"><i class="icon ion-qr-scanner"></i></button></ion-item><cs-extension-point name="menu-actions"></cs-extension-point></ion-list></ion-content></ion-side-menu></ion-side-menus> \ No newline at end of file diff --git a/assets/www/templates/modal_about.html b/assets/www/templates/modal_about.html index 5fee7afca7c525bd681dfac0f9284fc826ba4a86..eba267252057ce304788ec100a18d1982274d582 100644 --- a/assets/www/templates/modal_about.html +++ b/assets/www/templates/modal_about.html @@ -1 +1 @@ -<ion-modal-view class="about"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CLOSE</button><h1 class="title" translate>ABOUT.TITLE</h1></ion-header-bar><ion-content class="text-center" scroll="true"><ion-list class="item-wrap-text"><ion-item class="item-icon-left item-text-wrap">{{'COMMON.APP_NAME'|translate}} <b>{{'COMMON.APP_VERSION'|translate:$root.config}}</b> <i ng-if="$root.newRelease" class="assertive ion-alert-circled"></i><h3 ng-if="$root.config.build" class="gray">{{'COMMON.APP_BUILD'|translate:$root.config}}</h3><span translate>ABOUT.LICENSE</span></ion-item><ion-item class="item-icon-left" ng-if="$root.newRelease"><i class="item-image icon ion-alert-circled assertive"></i> <span ng-if="!$root.device.isWeb()" ng-bind-html="'ABOUT.PLEASE_UPDATE' | translate:$root.newRelease "></span> <span ng-if="$root.device.isWeb()" ng-bind-html="'ABOUT.LATEST_RELEASE' | translate:$root.newRelease "></span><h3 ng-if="!$root.device.enable"><a ng-click="openLink($event, $root.newRelease.url)" translate>{{::$root.newRelease.url}}</a></h3></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="item-image icon ion-bug"></i> <span translate>ABOUT.PLEASE_REPORT_ISSUE</span><h3><a ng-click="openLink($event, $root.settings.newIssueUrl)" translate>ABOUT.REPORT_ISSUE</a></h3></ion-item><ion-item class="item-icon-left"><i class="item-image icon ion-network"></i> {{'ABOUT.CODE' | translate}}<h3><a ng-click="openLink($event, 'https://git.duniter.org/clients/cesium/cesium')">https://git.duniter.org/clients/cesium/cesium</a></h3></ion-item><ion-item class="item-icon-left"><i class="item-image icon ion-chatbubbles"></i> {{'ABOUT.FORUM' | translate}}<h3><a ng-click="openLink($event, $root.settings.userForumUrl)">{{::$root.settings.userForumUrl}}</a></h3></ion-item><ion-item class="item-icon-left"><i class="item-image icon ion-person-stalker"></i> {{'ABOUT.DEVELOPERS' | translate}}<h3><a href="https://github.com/blavenie" target="_system">Benoit Lavenier</a>, <a href="https://github.com/c-geek" target="_system">cgeek</a>, <a href="https://github.com/devingfx" target="_system">DiG</a>, <a href="https://git.duniter.org/ji_emme" target="_system">Ji_emme</a></h3></ion-item><div class="padding hidden-xs text-center"><button class="button button-stable icon-left ink" type="submit" ng-click="closeModal()" ui-sref="app.help"><i class="icon ion-ios-help-outline"></i> {{'HOME.BTN_HELP' | translate}}</button> <button class="button button-positive ink" type="submit" ng-click="closeModal()">{{'COMMON.BTN_CLOSE' | translate}}</button></div></ion-list></ion-content></ion-modal-view> \ No newline at end of file +<ion-modal-view class="about"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CLOSE</button><h1 class="title" translate>ABOUT.TITLE</h1></ion-header-bar><ion-content class="text-center" scroll="true"><div class="list item-wrap-text"><ion-item class="item-icon-left item-text-wrap"><span>{{'COMMON.APP_NAME'|translate}} <b>{{'COMMON.APP_VERSION'|translate:$root.config}}</b> - <a ng-click="openLink($event, 'http://cesium.app')">www.cesium.app</a></span> <i ng-if="$root.newRelease" class="assertive ion-alert-circled"></i><h3 ng-if="$root.config.build" class="gray">{{'COMMON.APP_BUILD'|translate:$root.config}}</h3><span translate>ABOUT.LICENSE</span></ion-item><ion-item class="item-icon-left" ng-if="$root.newRelease"><i class="item-image icon ion-alert-circled assertive"></i> <span ng-if="!$root.device.isWeb()" ng-bind-html="'ABOUT.PLEASE_UPDATE' | translate:$root.newRelease "></span> <span ng-if="$root.device.isWeb()" ng-bind-html="'ABOUT.LATEST_RELEASE' | translate:$root.newRelease "></span><h3 ng-if="!$root.device.enable"><a ng-click="openLink($event, $root.newRelease.url)" translate>{{::$root.newRelease.url}}</a></h3></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="item-image icon ion-android-laptop"></i> <span translate>ABOUT.OFFICIAL_WEB_SITE</span><h3><a ng-click="openLink($event, 'https://www.cesium.app')">https://www.cesium.app</a></h3></ion-item><ion-item class="item-icon-left"><i class="item-image icon ion-chatbubbles"></i> {{'ABOUT.FORUM' | translate}}<h3><a ng-click="openLink($event, $root.settings.userForumUrl)">{{::$root.settings.userForumUrl}}</a></h3></ion-item><ion-item class="item-icon-left item-text-wrap"><i class="item-image icon ion-bug"></i> <span translate>ABOUT.PLEASE_REPORT_ISSUE</span><h3><a ng-click="openLink($event, $root.settings.newIssueUrl)" translate>ABOUT.REPORT_ISSUE</a></h3></ion-item><ion-item class="item-icon-left"><i class="item-image icon ion-network"></i> {{'ABOUT.CODE' | translate}}<h3><a ng-click="openLink($event, 'https://git.duniter.org/clients/cesium-grp/cesium')">https://git.duniter.org/clients/cesium-grp/cesium</a></h3></ion-item><ion-item class="item-icon-left"><i class="item-image icon ion-person-stalker"></i> {{'ABOUT.DEVELOPERS' | translate}}<h3><a href="https://github.com/blavenie" target="_system">Benoit Lavenier</a>, <a href="https://github.com/bpresles" target="_system">bpresles</a>, <a href="https://github.com/c-geek" target="_system">cgeek</a>, <a href="https://github.com/devingfx" target="_system">DiG</a>, <a href="https://git.duniter.org/ji_emme" target="_system">Ji_emme</a></h3></ion-item><div class="padding hidden-xs text-center"><button class="button button-stable icon-left ink" type="submit" ng-click="closeModal()" ui-sref="app.help"><i class="icon ion-ios-help-outline"></i> {{'HOME.BTN_HELP' | translate}}</button> <button class="button button-positive ink" type="submit" ng-click="closeModal()">{{'COMMON.BTN_CLOSE' | translate}}</button></div></div></ion-content></ion-modal-view> \ No newline at end of file diff --git a/assets/www/templates/network/item_content_peer.html b/assets/www/templates/network/item_content_peer.html index 03d2692e7cf4d1353e1c196cfbb67e4947f1c139..3c753506627aabe90f9c4be8e2ead138b8670d87 100644 --- a/assets/www/templates/network/item_content_peer.html +++ b/assets/www/templates/network/item_content_peer.html @@ -1 +1 @@ -<i class="icon ion-android-desktop" ng-class=":rebind:{'balanced': peer.online && peer.hasMainConsensusBlock, 'energized': peer.online && peer.hasConsensusBlock, 'gray': peer.online && !peer.hasConsensusBlock && !peer.hasMainConsensusBlock, 'stable': !peer.online}" ng-if=":rebind:!peer.avatar"></i> <b class="icon-secondary ion-person" ng-if=":rebind:!peer.avatar" ng-class=":rebind:{'balanced': peer.online && peer.hasMainConsensusBlock, 'energized': peer.online && peer.hasConsensusBlock, 'gray': peer.online && !peer.hasConsensusBlock && !peer.hasMainConsensusBlock, 'stable': !peer.online}" style="left: 26px; top: -3px"></b> <i class="avatar" ng-if=":rebind:peer.avatar" style="background-image: url('{{:rebind:peer.avatar.src}}')"></i> <b class="icon-secondary assertive ion-close-circled" ng-if=":rebind:!peer.online" style="left: 37px; top: -10px"></b><div class="row no-padding"><div class="col no-padding"><h3 class="dark" ng-if=":rebind:!peer.bma.private">{{:rebind:peer.dns || peer.server}}</h3><h4 class="gray" ng-if=":rebind:peer.bma.private"><i class="ion-flash"></i> {{'NETWORK.VIEW.PRIVATE_ACCESS'|translate}}</h4><h4><span class="gray" ng-if=":rebind:!peer.uid"><i class="ion-key"></i> {{:rebind:peer.pubkey|formatPubkey}} </span><span class="positive" ng-if=":rebind:peer.uid"><i class="ion-person"></i> {{:rebind:peer.name || peer.uid}} </span><span class="gray">{{:rebind:peer.dns && (' | ' + peer.server) + (peer.bma.path||'') }}</span></h4></div><div class="col col-20 no-padding text-center" ng-if="::expertMode && search.type != 'offline'"></div><div class="col col-20 no-padding text-center"><span id="{{$index === 0 ? helptipPrefix + '-peer-0-block' : ''}}" class="badge" ng-class=":rebind:{'badge-balanced': peer.hasMainConsensusBlock, 'badge-energized': peer.hasConsensusBlock, 'ng-hide': !peer.currentNumber }">{{::!expertMode ? ('COMMON.BLOCK'|translate) : '' }} {{:rebind:peer.currentNumber|formatInteger}}</span> <span class="badge badge-secondary" ng-if=":rebind:peer.consensusBlockDelta && expertMode"><i class="ion-clock"></i> {{:rebind:peer.consensusBlockDelta|formatDurationTime}}</span></div></div> \ No newline at end of file +<i class="icon ion-android-desktop" ng-class=":rebind:{'balanced': peer.online && peer.hasMainConsensusBlock, 'energized': peer.online && peer.hasConsensusBlock, 'gray': peer.online && !peer.hasConsensusBlock && !peer.hasMainConsensusBlock, 'stable': !peer.online}" ng-if=":rebind:!peer.avatar"></i> <b class="icon-secondary ion-person" ng-if=":rebind:!peer.avatar" ng-class=":rebind:{'balanced': peer.online && peer.hasMainConsensusBlock, 'energized': peer.online && peer.hasConsensusBlock, 'gray': peer.online && !peer.hasConsensusBlock && !peer.hasMainConsensusBlock, 'stable': !peer.online}" style="left: 26px; top: -3px"></b> <i class="avatar" ng-if=":rebind:peer.avatar" style="background-image: url('{{:rebind:peer.avatar.src}}')"></i> <b class="icon-secondary assertive ion-close-circled" ng-if=":rebind:!peer.online" style="left: 37px; top: -10px"></b><div class="row no-padding"><div class="col no-padding"><h3 class="dark" ng-if=":rebind:!peer.bma.private">{{:rebind:peer.dns || peer.server}}</h3><h4 class="gray" ng-if=":rebind:peer.bma.private"><i class="ion-flash"></i> {{'NETWORK.VIEW.PRIVATE_ACCESS'|translate}}</h4><h4><span class="gray" ng-if=":rebind:!peer.uid"><i class="ion-key"></i> {{:rebind:peer.pubkey|formatPubkey}} </span><span class="positive" ng-if=":rebind:peer.uid"><i class="ion-person"></i> {{:rebind:peer.name || peer.uid}} </span><span class="gray" ng-if=":rebind:!compactMode">{{:rebind:peer.dns && (' | ' + peer.server) + (peer.bma.path||'') }}</span></h4></div><div class="col col-20 no-padding text-center" ng-if="::expertMode && search.type != 'offline'"></div><div class="col col-20 no-padding text-center"><span id="{{$index === 0 ? helptipPrefix + '-peer-0-block' : ''}}" class="badge" ng-class=":rebind:{'badge-balanced': peer.hasMainConsensusBlock, 'badge-energized': peer.hasConsensusBlock, 'ng-hide': !peer.currentNumber && !peer.blockNumber }">{{::!expertMode ? ('COMMON.BLOCK'|translate) : '' }} {{:rebind:(peer.currentNumber || peer.blockNumber) | formatInteger}}</span> <span class="badge badge-secondary" ng-if=":rebind:peer.consensusBlockDelta && expertMode"><i class="ion-clock"></i> {{:rebind:peer.consensusBlockDelta|formatDurationTime}}</span></div></div> \ No newline at end of file diff --git a/assets/www/templates/network/items_peers.html b/assets/www/templates/network/items_peers.html index 37dcd844b6377209b6a6a721aed90e1ec54b45fb..665f38bba1cc09f301e05da988eacad599698eab 100644 --- a/assets/www/templates/network/items_peers.html +++ b/assets/www/templates/network/items_peers.html @@ -1 +1 @@ -<div ng-class="::motion.ionListClass" class="no-padding"><div class="item item-text-wrap no-border done in gray no-padding-top no-padding-bottom inline text-italic" ng-if="::isHttps && expertMode"><small><i class="icon ion-alert-circled"></i> {{'NETWORK.INFO.ONLY_SSL_PEERS'|translate}}</small></div><div ng-repeat="peer in :rebind:search.results track by peer.id" class="item item-peer item-icon-left ink" ng-class="::ionItemClass" id="{{helptipPrefix}}-peer-{{$index}}" ng-click="selectPeer(peer)" ng-include="'templates/network/item_content_peer.html'"></div></div> \ No newline at end of file +<div class="no-padding {{::motion.ionListClass}}"><div class="item item-text-wrap no-border done in gray no-padding-top no-padding-bottom inline text-italic" ng-if="::isHttps && expertMode"><small><i class="icon ion-alert-circled"></i> {{'NETWORK.INFO.ONLY_SSL_PEERS'|translate}}</small></div><div ng-repeat="peer in :rebind:search.results track by peer.id" class="item item-peer item-icon-left ink {{::ionItemClass}}" ng-class=":rebind:{'compacted': peer.compacted && compactMode}" id="{{::helptipPrefix}}-peer-{{::$index}}" ng-click="selectPeer(peer)" ng-include="::'templates/network/item_content_peer.html'"></div></div> \ No newline at end of file diff --git a/assets/www/templates/network/modal_network.html b/assets/www/templates/network/modal_network.html index 76dca21f7cb7bf7a4155280bbc0fb16b5bf42eb0..ec7af61922a403633776003ef718cbc6a1acaa46 100644 --- a/assets/www/templates/network/modal_network.html +++ b/assets/www/templates/network/modal_network.html @@ -1 +1 @@ -<ion-modal-view id="nodes" class="modal-full-height" cache-view="false"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button><h1 class="title" translate="">PEER.PEER_LIST</h1><div class="buttons buttons-right header-item"><span class="secondary"><button class="button button-clear icon ion-loop button-clear" ng-click="refresh()"></button> <button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></span></div></ion-header-bar><ion-content><div class="list"><div class="padding padding-xs" style="display: block; height: 60px"><div class="pull-left"><h4 ng-if="enableFilter && search.type=='member'">{{'PEER.MEMBERS' | translate}} <span ng-if="!search.loading">({{search.results.length}})</span></h4><h4 ng-if="enableFilter && search.type=='mirror'">{{'PEER.MIRRORS' | translate}} <span ng-if="!search.loading">({{search.results.length}})</span></h4><h4 ng-if="!enableFilter || !search.type">{{'PEER.ALL_PEERS' | translate}} <span ng-if="!search.loading">({{search.results.length}})</span></h4></div><div class="pull-right"><ion-spinner class="icon" icon="android" ng-if="search.loading"></ion-spinner> <div class="pull-right"> </div></div></div><ng-include src="'templates/network/items_peers.html'"></ng-include></div></ion-content></ion-modal-view> \ No newline at end of file +<ion-modal-view id="nodes" class="modal-full-height" cache-view="false"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button><h1 class="title" translate="">PEER.PEER_LIST</h1><div class="buttons buttons-right header-item"><span class="secondary"><button class="button button-clear icon ion-loop button-clear" ng-click="refresh()"></button> <button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></span></div></ion-header-bar><ion-content><div class="list"><div class="padding padding-xs" style="display: block; height: 60px"><div class="pull-left"><h4><span ng-if="enableFilter && search.type=='member'" translate="">PEER.MEMBER_PEERS</span> <span ng-if="enableFilter && search.type=='mirror'" translate="">PEER.MIRROR_PEERS</span> <span ng-if="!enableFilter || !search.type" translate="">PEER.ALL_PEERS</span> <span ng-if="!search.loading">({{search.results.length}})</span></h4></div><div class="pull-right"><ion-spinner class="icon" icon="android" ng-if="search.loading"></ion-spinner> <div class="pull-right"> </div></div></div><ng-include src="'templates/network/items_peers.html'"></ng-include></div></ion-content></ion-modal-view> \ No newline at end of file diff --git a/assets/www/templates/network/view_network.html b/assets/www/templates/network/view_network.html index 269032d8983f5ce62089ce9c5439be92566ddf67..801f3939ce54a60b1da9b6df39a9b0431850cba4 100644 --- a/assets/www/templates/network/view_network.html +++ b/assets/www/templates/network/view_network.html @@ -1 +1 @@ -<ion-view><ion-nav-title><span translate="">MENU.NETWORK</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-loop visible-xs visible-sm" ng-click="refresh()"></button></ion-nav-buttons><ion-content scroll="true" ng-init="enableFilter=true; ionItemClass='item-border-large';"><div class="row responsive-sm responsive-md responsive-lg"><div class="col list col-border-right"><div class="padding padding-xs" style="display: block; height: 60px"><div class="pull-left"><h4><span ng-if="enableFilter && search.type=='member'" translate="">PEER.MEMBERS</span> <span ng-if="enableFilter && search.type=='mirror'" translate="">PEER.MIRRORS</span> <span ng-if="enableFilter && search.type=='offline'" translate="">PEER.OFFLINE</span> <span ng-if="!enableFilter || !search.type" translate="">PEER.ALL_PEERS</span> <span ng-if="search.results.length">({{search.results.length}})</span><ion-spinner ng-if="search.loading" class="icon ion-spinner-small" icon="android"></ion-spinner></h4></div><div class="pull-right"><div class="pull-right" ng-if="enableFilter"> <cs-extension-point name="filter-buttons"></cs-extension-point></div></div></div><div id="helptip-network-blockchain" style="display: block"></div><div id="helptip-network-peers" style="display: block"></div><ng-include src="'templates/network/items_peers.html'"></ng-include></div><div class="col col-33" ng-controller="BlockLookupCtrl"><div class="padding padding-xs" style="display: block; height: 100px"><h4 translate="">BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4></div><ng-include src="'templates/blockchain/list_blocks.html'"></ng-include></div></div></ion-content></ion-view> \ No newline at end of file +<ion-view><ion-nav-title><span translate="">MENU.NETWORK</span></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-loop visible-xs visible-sm" ng-click="refresh()"></button></ion-nav-buttons><ion-content scroll="true" ng-init="enableFilter=true; ionItemClass='item-border-large';"><div class="row responsive-sm responsive-md responsive-lg"><div class="col list col-border-right"><div class="padding padding-xs" style="display: block; height: 60px"><div class="pull-left"><h4><span ng-if="enableFilter && search.type=='member'" translate="">PEER.MEMBER_PEERS</span> <span ng-if="enableFilter && search.type=='mirror'" translate="">PEER.MIRROR_PEERS</span> <span ng-if="enableFilter && search.type=='offline'" translate="">PEER.OFFLINE_PEERS</span> <span ng-if="!enableFilter || !search.type" translate="">PEER.ALL_PEERS</span> <span ng-if="search.results.length">({{search.results.length}})</span><ion-spinner ng-if="search.loading" class="icon ion-spinner-small" icon="android"></ion-spinner></h4></div><div class="pull-right"><div class="pull-right" ng-if="enableFilter"> <cs-extension-point name="filter-buttons"></cs-extension-point></div></div></div><div id="helptip-network-blockchain" style="display: block"></div><div id="helptip-network-peers" style="display: block"></div><ng-include src="'templates/network/items_peers.html'"></ng-include></div><div class="col col-33" ng-controller="BlockLookupCtrl"><div class="padding padding-xs" style="display: block; height: 100px"><h4 translate="">BLOCKCHAIN.LOOKUP.LAST_BLOCKS</h4></div><ng-include src="'templates/blockchain/list_blocks.html'"></ng-include></div></div></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/network/view_peer.html b/assets/www/templates/network/view_peer.html index c8bbdb24062bea3e25a8a7dce3429e1f3deb854f..19fd2d63d266f9fb9ff2d3f7fa7d341507c15881 100644 --- a/assets/www/templates/network/view_peer.html +++ b/assets/www/templates/network/view_peer.html @@ -1 +1 @@ -<ion-view><ion-nav-title><span translate="">PEER.VIEW.TITLE</span></ion-nav-title><ion-content class="has-header" scroll="true"><div class="row no-padding"><div class="col list"><ion-item><h1><span translate="">PEER.VIEW.TITLE</span> <span class="gray">{{node.host}}</span></h1><h2 class="gray"><i class="gray icon ion-android-globe"></i> {{node.bma.dns || node.server}} <span class="gray" ng-if="!loading && node.useSsl"><i class="gray ion-locked"></i> <small>SSL</small> </span><span class="gray" ng-if="!loading && node.useTor"><i class="gray ion-bma-tor-api"></i> </span><span class="assertive" ng-if="!loading && !node.uid">({{'PEER.MIRROR'|translate}})</span></h2><h3><span class="dark"><i class="icon ion-android-desktop"></i> {{'PEER.VIEW.OWNER'|translate}} </span><a class="positive" ng-if="node.uid" ui-sref="app.wot_identity({pubkey: node.pubkey, uid: node.uid})"><i class="ion-person"></i> {{node.name || node.uid}} <span class="gray" ng-if="node.name">({{node.uid}}) </span></a><span ng-if="!loading && !node.uid"><a class="gray" ui-sref="app.wot_identity({pubkey: node.pubkey})"><i class="ion-key"></i> {{node.pubkey|formatPubkey}} <span class="gray" ng-if="node.name">({{node.name}})</span></a></span></h3><h3><a ng-click="openRawPeering($event)"><i class="icon ion-share"></i> {{'PEER.VIEW.SHOW_RAW_PEERING'|translate}} </a><span class="gray" ng-if="!isReachable">| </span><a ng-if="!isReachable" ng-click="openRawCurrentBlock($event)"><i class="icon ion-share"></i> <span translate="">PEER.VIEW.SHOW_RAW_CURRENT_BLOCK</span></a></h3></ion-item><div class="item item-divider" translate="">PEER.VIEW.GENERAL_DIVIDER</div><ion-item class="item-icon-left item-text-wrap ink" copy-on-click="{{node.pubkey}}"><i class="icon ion-key"></i> <span translate="">COMMON.PUBKEY</span><h4 class="dark text-left">{{node.pubkey}}</h4></ion-item><a class="item item-icon-left item-icon-right item-text-wrap ink" ng-if="isReachable" ui-sref="app.view_server_block_hash({server: node.server, ssl: node.useSsl, tor: node.useTor, number: current.number, hash: current.hash})"><i class="icon ion-cube"></i> <span translate="">BLOCKCHAIN.VIEW.TITLE_CURRENT</span><div class="badge badge-calm" ng-if="!loading">{{current.number|formatInteger}}</div><i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-icon-right item-text-wrap ink" ng-if="isReachable" ui-sref="app.server_blockchain({server: node.server, ssl: node.useSsl, tor: node.useTor})"><i class="icon ion-cube" style="font-size: 25px"></i> <i class="icon-secondary ion-clock" style="font-size: 18px; left: 33px; top: -12px"></i> <span translate="">PEER.VIEW.LAST_BLOCKS</span> <i class="gray icon ion-ios-arrow-right"></i></a><cs-extension-point name="general"></cs-extension-point><div class="item item-divider" ng-hide="loading || !isReachable" translate="">PEER.VIEW.KNOWN_PEERS</div><ion-item class="item item-text-wrap no-border done in gray no-padding-top no-padding-bottom inline text-italic" ng-show="!loading && !isReachable"><small><i class="icon ion-alert-circled"></i> {{'NETWORK.INFO.ONLY_SSL_PEERS'|translate}}</small></ion-item><div class="item center" ng-if="loading"><ion-spinner class="icon" icon="android"></ion-spinner></div><div class="list no-padding {{::motion.ionListClass}}" ng-if="isReachable"><div ng-repeat="peer in :rebind:peers track by peer.id" class="item item-peer item-icon-left ink" ng-class="::ionItemClass" ng-click="selectPeer(peer)" ng-include="'templates/network/item_content_peer.html'"></div></div></div></div></ion-content></ion-view> \ No newline at end of file +<ion-view><ion-nav-title><span translate="">PEER.VIEW.TITLE</span></ion-nav-title><ion-content class="has-header" scroll="true"><div class="row no-padding"><div class="col list"><ion-item><h1><span translate="">PEER.VIEW.TITLE</span> <span class="gray">{{node.host}}</span></h1><h2 class="gray"><i class="gray icon ion-android-globe"></i> {{node.bma.dns || node.server}} <span class="gray" ng-if="!loading && node.useSsl"><i class="gray ion-locked"></i> <small>SSL</small> </span><span class="gray" ng-if="!loading && node.useTor"><i class="gray ion-bma-tor-api"></i> </span><span class="assertive" ng-if="!loading && !node.uid">({{'PEER.MIRROR'|translate}})</span></h2><h3><span class="dark"><i class="icon ion-android-desktop"></i> {{'PEER.VIEW.OWNER'|translate}} </span><a class="positive" ng-if="node.uid" ui-sref="app.wot_identity({pubkey: node.pubkey, uid: node.uid})"><i class="ion-person"></i> {{node.name || node.uid}} <span class="gray" ng-if="node.name">({{node.uid}}) </span></a><span ng-if="!loading && !node.uid"><a class="gray" ui-sref="app.wot_identity({pubkey: node.pubkey})"><i class="ion-key"></i> {{node.pubkey|formatPubkey}} <span class="gray" ng-if="node.name">({{node.name}})</span></a></span></h3><h3><a ng-click="openRawPeering($event)"><i class="icon ion-share"></i> {{'PEER.VIEW.SHOW_RAW_PEERING'|translate}} </a><span class="gray" ng-if="!isReachable">| </span><a ng-if="!isReachable" ng-click="openRawCurrentBlock($event)"><i class="icon ion-share"></i> <span translate="">PEER.VIEW.SHOW_RAW_CURRENT_BLOCK</span></a></h3></ion-item><div class="item item-divider" translate="">PEER.VIEW.GENERAL_DIVIDER</div><ion-item class="item-icon-left item-text-wrap ink" copy-on-click="{{node.pubkey}}"><i class="icon ion-key"></i> <span translate="">COMMON.PUBKEY</span><h4 class="dark text-left">{{node.pubkey}}</h4></ion-item><a class="item item-icon-left item-icon-right item-text-wrap ink" ng-if="isReachable" ui-sref="app.view_server_block_hash({server: node.server, ssl: node.useSsl, tor: node.useTor, number: current.number, hash: current.hash})"><i class="icon ion-cube"></i> <span translate="">BLOCKCHAIN.VIEW.TITLE_CURRENT</span><div class="badge badge-calm" ng-if="!loading">{{current.number|formatInteger}}</div><i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-icon-right item-text-wrap ink" ng-if="isReachable" ui-sref="app.server_blockchain({server: node.server, ssl: node.useSsl, tor: node.useTor})"><i class="icon ion-cube" style="font-size: 25px"></i> <i class="icon-secondary ion-clock" style="font-size: 18px; left: 33px; top: -12px"></i> <span translate="">PEER.VIEW.LAST_BLOCKS</span> <i class="gray icon ion-ios-arrow-right"></i></a><cs-extension-point name="general"></cs-extension-point><div class="item item-divider" ng-hide="loading || !isReachable" translate="">PEER.VIEW.KNOWN_PEERS</div><ion-item class="item item-text-wrap no-border done in gray no-padding-top no-padding-bottom inline text-italic" ng-show="!loading && !isReachable"><small><i class="icon ion-alert-circled"></i> {{'NETWORK.INFO.ONLY_SSL_PEERS'|translate}}</small></ion-item><div class="item center" ng-if="loading"><ion-spinner class="icon" icon="android"></ion-spinner></div><div class="list no-padding {{::motion.ionListClass}}" ng-if="isReachable"><div ng-repeat="peer in :rebind:peers track by peer.id" class="item item-peer item-icon-left ink {{::ionItemClass}}" ng-click="selectPeer(peer)" ng-include="'templates/network/item_content_peer.html'"></div></div></div></div></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/settings/settings.html b/assets/www/templates/settings/settings.html index c777af341e96542fd1e1d62aaa52ce8bf12989c6..9f4efea91bcf2ee17eb0b696841443eb69addc43 100644 --- a/assets/www/templates/settings/settings.html +++ b/assets/www/templates/settings/settings.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" cache-view="false" class="settings"><ion-nav-title translate="">SETTINGS.TITLE</ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content><div class="list item-border-large"><div class="item item-toggle dark"><div class="input-label">{{'COMMON.BTN_RELATIVE_UNIT' | translate}}</div><label class="toggle toggle-royal" id="helptip-settings-btn-unit-relative"><input type="checkbox" ng-model="formData.useRelative"><div class="track"><div class="handle"></div></div></label></div><label class="item item-input item-select"><div class="input-label">{{'COMMON.LANGUAGE' | translate}}</div><select ng-model="formData.locale" ng-change="changeLanguage(formData.locale.id)" ng-options="l as l.label for l in locales track by l.id"></select></label><div class="item item-text-wrap item-toggle dark"><div class="input-label">{{'SETTINGS.USE_LOCAL_STORAGE' | translate}}</div><h4 class="gray" ng-bind-html="'SETTINGS.USE_LOCAL_STORAGE_HELP' | translate"></h4><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.useLocalStorage"><div class="track"><div class="handle"></div></div></label></div><div class="item item-toggle dark item-text-wrap"><div class="input-label" ng-bind-html="'SETTINGS.ENABLE_HELPTIP' | translate"></div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.helptip.enable"><div class="track"><div class="handle"></div></div></label></div><cs-extension-point name="common"></cs-extension-point><span class="item item-divider">{{'SETTINGS.AUTHENTICATION_SETTINGS' | translate}}</span><div class="item item-toggle"><div class="input-label" ng-class="{'gray': !formData.useLocalStorage}">{{'SETTINGS.REMEMBER_ME' | translate}}</div><h4 class="gray text-wrap" ng-bind-html="'SETTINGS.REMEMBER_ME_HELP' | translate"></h4><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.rememberMe" ng-disabled="!formData.useLocalStorage"><div class="track"><div class="handle"></div></div></label></div><div class="item item-input item-select"><div class="input-label"><span class="input-label" translate="">SETTINGS.KEEP_AUTH</span><h4 class="gray text-wrap" ng-bind-html="'SETTINGS.KEEP_AUTH_HELP' | translate"></h4></div><label><select ng-model="formData.keepAuthIdle" ng-options="i as (keepAuthIdleLabels[i].labelKey | translate:keepAuthIdleLabels[i].labelParams ) for i in keepAuthIdles track by i"></select></label></div><span class="item item-divider" translate="">SETTINGS.HISTORY_SETTINGS</span><div class="item item-toggle dark"><div class="col col-75 input-label" translate="">SETTINGS.DISPLAY_UD_HISTORY</div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.showUDHistory"><div class="track"><div class="handle"></div></div></label></div><cs-extension-point name="history"></cs-extension-point><span class="item item-divider" translate="">SETTINGS.NETWORK_SETTINGS</span><div class="item ink item-text-wrap" ng-click="changeNode()"><div class="input-label">{{'SETTINGS.PEER' | translate}}</div><ng-if ng-if="formData.node.temporary"><h4 class="gray text-wrap assertive"><i class="icon ion-alert-circled"></i> <span ng-bind-html="'SETTINGS.PEER_CHANGED_TEMPORARY' | translate "></span></h4><div class="item-note assertive text-italic">{{bma.server}}</div></ng-if><div class="item-note dark" ng-if="!formData.node.temporary">{{bma.server}}</div></div><cs-extension-point name="network"></cs-extension-point><span class="item item-divider" ng-if="$root.config.plugins" translate="">SETTINGS.PLUGINS_SETTINGS</span><cs-extension-point name="plugins"></cs-extension-point></div></ion-content></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" cache-view="false" class="settings"><ion-nav-title translate="">SETTINGS.TITLE</ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content><div class="row no-padding responsive-sm responsive-md responsive-lg"><div class="col col-50 list item-border-large padding-left padding-right no-padding-xs no-padding-sm" style="margin-bottom: 2px"><span class="item item-divider" translate="">SETTINGS.DISPLAY_DIVIDER</span><label class="item item-input item-select"><div class="input-label" translate="">COMMON.LANGUAGE</div><select ng-model="formData.locale" ng-change="changeLanguage(formData.locale.id)" ng-options="l as l.label for l in locales track by l.id"></select></label><div class="item item-toggle dark"><div class="input-label">{{'COMMON.BTN_RELATIVE_UNIT' | translate}}</div><label class="toggle toggle-royal" id="helptip-settings-btn-unit-relative"><input type="checkbox" ng-model="formData.useRelative"><div class="track"><div class="handle"></div></div></label></div><div class="item item-toggle dark item-text-wrap"><div class="input-label" ng-bind-html="'SETTINGS.ENABLE_HELPTIP' | translate"></div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.helptip.enable"><div class="track"><div class="handle"></div></div></label></div><span class="item item-divider" translate="">SETTINGS.STORAGE_DIVIDER</span><div class="item item-text-wrap item-toggle dark"><div class="input-label">{{'SETTINGS.USE_LOCAL_STORAGE' | translate}}</div><h4 class="gray" ng-bind-html="'SETTINGS.USE_LOCAL_STORAGE_HELP' | translate"></h4><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.useLocalStorage"><div class="track"><div class="handle"></div></div></label></div><cs-extension-point name="common"></cs-extension-point><span class="item item-divider">{{'SETTINGS.AUTHENTICATION_SETTINGS' | translate}}</span><div class="item item-toggle item-text-wrap"><div class="input-label" ng-class="{'gray': !formData.useLocalStorage}">{{'SETTINGS.REMEMBER_ME' | translate}}</div><h4 class="gray text-wrap" ng-bind-html="'SETTINGS.REMEMBER_ME_HELP' | translate"></h4><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.rememberMe" ng-disabled="!formData.useLocalStorage"><div class="track"><div class="handle"></div></div></label></div><label class="item item-input item-select item-text-wrap"><div class="input-label hidden-xs"><span class="hidden-xs" translate="">SETTINGS.KEEP_AUTH</span><h4 class="gray text-wrap hidden-xs" ng-bind-html="'SETTINGS.KEEP_AUTH_HELP' | translate"></h4></div><span class="visible-xs" translate="">SETTINGS.KEEP_AUTH_SHORT</span><select ng-model="formData.keepAuthIdle" ng-options="i as (keepAuthIdleLabels[i].labelKey | translate:keepAuthIdleLabels[i].labelParams ) for i in keepAuthIdles track by i"></select></label></div><div class="col col-50 list item-border-large padding-left padding-right no-padding-xs no-padding-sm no-margin-xs no-margin-sm"><span class="item item-divider">{{'SETTINGS.WALLETS_SETTINGS' | translate}}</span><div class="item item-toggle item-text-wrap dark"><span class="input-label" ng-class="{'gray': !formData.useLocalStorage}" translate="">SETTINGS.USE_WALLETS_ENCRYPTION</span><h4 class="gray text-wrap" ng-bind-html="'SETTINGS.USE_WALLETS_ENCRYPTION_HELP' | translate"></h4><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.useLocalStorageEncryption" ng-disabled="!formData.useLocalStorage"><div class="track"><div class="handle"></div></div></label></div><span class="item item-divider" translate="">SETTINGS.HISTORY_SETTINGS</span><div class="item item-toggle item-text-wrap dark"><div class="input-label" translate="">SETTINGS.DISPLAY_UD_HISTORY</div><label class="toggle toggle-royal"><input type="checkbox" ng-model="formData.showUDHistory"><div class="track"><div class="handle"></div></div></label></div><cs-extension-point name="history"></cs-extension-point><span class="item item-divider" translate="">SETTINGS.NETWORK_SETTINGS</span><ion-item class="ink item-icon-right visible-xs visible-sm" ng-click="changeNode()"><div class="input-label hidden-xs" translate="">SETTINGS.PEER</div><div class="input-label visible-xs" translate="">SETTINGS.PEER_SHORT</div><ng-if ng-if="formData.node.temporary"><h4 class="gray text-wrap assertive"><b class="ion-alert-circled"></b> <span ng-bind-html="'SETTINGS.PEER_CHANGED_TEMPORARY' | translate "></span></h4><div class="badge badge-assertive">{{bma.server}}</div></ng-if><div class="badge badge-balanced" ng-if="!formData.node.temporary">{{bma.server}}</div><i class="icon ion-ios-arrow-right"></i></ion-item><label class="item item-input item-select item-text-wrap"><div class="input-label hidden-xs"><span translate="">SETTINGS.BLOCK_VALIDITY_WINDOW</span><h4 class="gray text-wrap hidden-xs" ng-bind-html="'SETTINGS.BLOCK_VALIDITY_WINDOW_HELP' | translate"></h4></div><div class="input-label visible-xs" translate="">SETTINGS.BLOCK_VALIDITY_WINDOW_SHORT</div><select ng-model="formData.blockValidityWindow" ng-options="i as (blockValidityWindowLabels[i].labelKey | translate:blockValidityWindowLabels[i].labelParams ) for i in blockValidityWindows track by i"></select></label><cs-extension-point name="network"></cs-extension-point><span class="item item-divider" ng-if="$root.config.plugins" translate="">SETTINGS.PLUGINS_SETTINGS</span><cs-extension-point name="plugins"></cs-extension-point></div></div></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/wallet/item_tx.html b/assets/www/templates/wallet/item_tx.html index 1710ee96d2c30eae464b183b6633515f281ccb58..2a2e85329f1a09ed2c46015dd77149e3fcfa021d 100644 --- a/assets/www/templates/wallet/item_tx.html +++ b/assets/www/templates/wallet/item_tx.html @@ -1 +1 @@ -<i class="icon item-image" ng-if="::!tx.avatar" ng-class="::{'ion-person dark': tx.uid, 'ion-card dark': !tx.uid}"></i> <i class="avatar" ng-if="::tx.avatar" style="background-image: url({{::tx.avatar.src}})"></i><div class="row no-padding"><div class="col no-padding"><b class="ion-clock" ng-if="::pending"></b> <a class="" ui-sref="app.wot_identity({pubkey:tx.pubkey, uid:tx.uid})" ng-if="tx.uid">{{::tx.name||tx.uid}} </a><a class="gray" ui-sref="app.wot_identity({pubkey:tx.pubkey, uid:tx.uid})" ng-if="!tx.uid"><i class="ion-key gray"></i> {{::tx.pubkey | formatPubkey}}</a><p class="dark visible-xs width-cup text-italic" data-toggle="tooltip" ng-if="::tx.comment" title="{{::tx.comment}}"><i class="ion-ios-chatbubble-outline"></i> {{::tx.comment}}<br></p><h4><a ng-if="::!pending" class="gray underline" ui-sref="app.view_block({number: tx.block_number})">{{::tx.time | formatFromNow}} | {{::tx.time | formatDate}} </a><span ng-if="::pending" class="gray">{{::tx.time | formatFromNow}} | {{::tx.time | formatDate}}</span></h4></div><div class="col col-50 no-padding" ng-if="::tx.comment"><p class="vertical-center gray text-italic hidden-xs" data-toggle="tooltip" title="{{::tx.comment}}">{{::tx.comment}}</p></div><div class="col col-10 no-padding"><span ng-if="::!tx.lockedOutputs" class="badge item-note" ng-class="{'badge-calm': tx.amount > 0}"><span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span> </span><a ng-if=":rebind:tx.lockedOutputs" class="badge item-note" ng-class="{'badge-calm': tx.amount > 0}" ng-click="showLockedOutputsPopover(tx, $event)"><i class="icon ion-locked"></i><span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span></a><div class="badge badge-secondary" ng-if="$root.settings.expertMode">(<span ng-bind-html=":rebind:tx.amount| formatAmount:{useRelative: !$root.settings.useRelative, currency:$root.currency.name}"></span>)</div></div></div> \ No newline at end of file +<i class="icon item-image" ng-if="::!tx.avatar" ng-class="::{'ion-person dark': tx.uid, 'ion-card dark': !tx.uid}"></i> <i class="avatar" ng-if="::tx.avatar" style="background-image: url({{::tx.avatar.src}})"></i><div class="row no-padding"><div class="col no-padding"><a class="" ui-sref="app.wot_identity({pubkey:tx.pubkey, uid:tx.uid})" ng-if="::tx.uid">{{::tx.name||tx.uid}} </a><a class="gray" ui-sref="app.wot_identity({pubkey:tx.pubkey, uid:tx.uid})" ng-if="::!tx.uid && tx.pubkey"><i class="ion-key gray"></i> {{::tx.pubkey | formatPubkey}} <span ng-if="::tx.name">- {{::tx.name | truncText:40}}</span></a><p class="dark visible-xs width-cup text-italic" data-toggle="tooltip" ng-if="::tx.comment" title="{{::tx.comment}}"><i class="ion-ios-chatbubble-outline"></i> {{::tx.comment}}<br></p><h4><a ng-if="::!pending" class="gray underline" ui-sref="app.view_block({number: tx.block_number})">{{::tx.time | medianFromNowAndDate: false}} </a><span ng-if="::pending" class="gray">{{::tx.time | medianFromNowAndDate: false}}</span></h4></div><div class="col col-50 no-padding" ng-if="::tx.comment"><p class="vertical-center gray text-italic hidden-xs" data-toggle="tooltip" title="{{::tx.comment}}">{{::tx.comment}}</p></div><div class="col col-10 no-padding"><span ng-if="::!tx.lockedOutputs" class="badge item-note" ng-class="{'badge-calm': tx.amount > 0, 'badge-white': tx.amount <= 0}"><span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span> </span><a ng-if=":rebind:tx.lockedOutputs" class="badge item-note" ng-class="{'badge-calm': tx.amount > 0}" ng-click="showLockedOutputsPopover(tx, $event)"><b class="ion-locked"></b> <span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span></a><div class="badge badge-secondary" ng-if="$root.settings.expertMode">(<span ng-bind-html=":rebind:tx.amount| formatAmount:{useRelative: !$root.settings.useRelative, currency:$root.currency.name}"></span>)</div></div></div> \ No newline at end of file diff --git a/assets/www/templates/wallet/item_ud.html b/assets/www/templates/wallet/item_ud.html index 71c4ff6e9e5074300faf6f99418ceb3ce5e0b405..3b52ee1a50ad202905d31c10bff00b41cdbf85fd 100644 --- a/assets/www/templates/wallet/item_ud.html +++ b/assets/www/templates/wallet/item_ud.html @@ -1 +1 @@ -<i class="icon item-image ion-arrow-up-c energized"></i><div class="row no-padding"><div class="col no-padding"><span class="energized" translate>COMMON.UNIVERSAL_DIVIDEND</span><h4><a class="gray underline" ui-sref="app.view_block({number: tx.block_number})">{{::tx.time | formatFromNow}} | {{::tx.time | formatDate}}</a></h4></div><div class="col col-10 no-padding"><span class="badge item-note badge-energized"><span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span></span><div class="badge badge-secondary" ng-if="$root.settings.expertMode">(<span ng-bind-html=":rebind:tx.amount| formatAmount:{useRelative: !$root.settings.useRelative, currency:$root.currency.name}"></span>)</div></div></div> \ No newline at end of file +<i class="icon item-image ion-arrow-up-c energized"></i><div class="row no-padding"><div class="col no-padding"><span class="energized" translate>COMMON.UNIVERSAL_DIVIDEND</span><h4><a class="gray underline" ui-sref="app.view_block({number: tx.block_number})">{{::tx.time | medianFromNowAndDate}}</a></h4></div><div class="col col-10 no-padding"><span class="badge item-note badge-energized"><span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span></span><div class="badge badge-secondary" ng-if="$root.settings.expertMode">(<span ng-bind-html=":rebind:tx.amount| formatAmount:{useRelative: !$root.settings.useRelative, currency:$root.currency.name}"></span>)</div></div></div> \ No newline at end of file diff --git a/assets/www/templates/wallet/list/item_wallet.html b/assets/www/templates/wallet/list/item_wallet.html new file mode 100644 index 0000000000000000000000000000000000000000..188f0b3e62c8891a7528b491a30c76f56d76b156 --- /dev/null +++ b/assets/www/templates/wallet/list/item_wallet.html @@ -0,0 +1 @@ +<div class="item item-avatar item-icon-right item-border-large item-wallet ink" id="wallet-{{::wallet.id}}" ng-click="select($event, wallet)" ng-init="walletData=wallet.data;"><i ng-if=":rebind:!walletData.avatar" class="item-image icon" ng-class=":rebind:{'ion-card': !walletData.isMember, 'ion-person': walletData.isMember}"></i> <i ng-if=":rebind:walletData.avatar" class="item-image avatar" style="background-image: url({{::walletData.avatar.src}})"></i><div class="badge badge-button badge-avatar badge-assertive ion-locked" ng-hide=":rebind:wallet.isAuth()"></div><h2><span class="text-editable" ng-click="editWallet($event, wallet)" title="{{'ACCOUNT.WALLET_LIST.BTN_RENAME'|translate}}"><ng-if ng-if=":rebind:walletData.localName||walletData.name||walletData.uid" ng-bind-html="::walletData.localName||walletData.name||walletData.uid"></ng-if><ng-if ng-if=":rebind:!walletData.localName && !walletData.name && !walletData.uid">{{::walletData.pubkey|formatPubkey}}</ng-if></span></h2><h4 class="gray"><span class="positive" ng-if="::walletData.name && walletData.uid"><i class="ion-person"></i> {{::walletData.uid}} </span><b class="ion-key"></b> {{::walletData.pubkey | formatPubkey}} <span ng-if="::!walletData.uid" class="assertive" translate>WOT.NOT_MEMBER_PARENTHESIS</span></h4><cs-extension-point name="item-wallet"></cs-extension-point><span class="badge" ng-if=":rebind:formData.showBalance && walletData.sources" ng-class=":rebind:{'badge-calm': (walletData.balance > 0) }"><ion-spinner class="ion-spinner-small" ng-if="formData.updatingWalletId==wallet.id" icon="android"></ion-spinner><span ng-bind-html=":rebind:walletData.balance|formatAmount:{useRelative: formData.useRelative, currency: currency}"></span> </span><i class="icon ion-ios-arrow-right"></i></div> \ No newline at end of file diff --git a/assets/www/templates/wallet/list/item_wallet_light.html b/assets/www/templates/wallet/list/item_wallet_light.html new file mode 100644 index 0000000000000000000000000000000000000000..ed64b40e55931657c15e2717e48ae6c3848d6d36 --- /dev/null +++ b/assets/www/templates/wallet/list/item_wallet_light.html @@ -0,0 +1 @@ +<div class="item item-avatar item-icon-right item-border item-wallet" ng-click="select($event, wallet)" ng-init="walletData=wallet.data;"><i ng-if="::!walletData.avatar" class="item-image icon" ng-class="::{'ion-card': !walletData.isMember, 'ion-person': walletData.isMember}"></i> <i ng-if="::walletData.avatar" class="item-image avatar" style="background-image: url({{::walletData.avatar.src}})"></i><div class="badge badge-button badge-avatar badge-assertive ion-locked" ng-hide="::wallet.isAuth()"></div><h2><ng-if ng-if="::walletData.localName||walletData.name||walletData.uid">{{::walletData.localName||walletData.name||walletData.uid}}</ng-if><ng-if ng-if="::!walletData.localName && !walletData.name && !walletData.uid">{{::walletData.pubkey|formatPubkey}}</ng-if></h2><h4 class="gray"><span class="positive" ng-if="::walletData.name && walletData.uid"><i class="ion-person"></i> {{::walletData.uid}} </span><b class="ion-key"></b> {{::walletData.pubkey | formatPubkey}} <span ng-if="::!walletData.uid" class="assertive" translate>WOT.NOT_MEMBER_PARENTHESIS</span></h4><div class="badge" ng-if="formData.showBalance" ng-class="{'badge-calm': (walletData.balance > 0) }"><span ng-bind-html="walletData.balance|formatAmount:{useRelative: formData.useRelative, currency: currency}"></span></div><i class="icon ion-ios-arrow-right"></i></div> \ No newline at end of file diff --git a/assets/www/templates/wallet/list/modal_import_file.html b/assets/www/templates/wallet/list/modal_import_file.html new file mode 100644 index 0000000000000000000000000000000000000000..4076e15ab25fc5eced061b6e8ca70f6c638c36c9 --- /dev/null +++ b/assets/www/templates/wallet/list/modal_import_file.html @@ -0,0 +1 @@ +<ion-modal-view id="transfer" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>ACCOUNT.WALLET_LIST.IMPORT_MODAL.TITLE</h1></ion-header-bar><ion-content scroll="true" class="padding"><p translate>ACCOUNT.WALLET_LIST.IMPORT_MODAL.HELP</p><div dropzone="importFromFile(file)"><div ng-if="!hasContent" onclick="angular.element(document.querySelector('#walletsImportFile'))[0].click();"><h2 class="gray" translate>COMMON.CHOOSE_FILE</h2><input type="file" id="walletsImportFile" accept=".csv,.txt" style="visibility:hidden; position:absolute" on-read-file="importFromFile(file)"></div><div ng-if="hasContent" class="item item-icon-left item-icon-right stable-bg"><i class="icon ion-document-text gray"></i><div class="item-content row"><div class="col"><h2>{{fileData.name}}</h2><h4 ng-if="fileData.lastModified"><span class="gray" translate>COMMON.FILE.DATE</span> {{fileData.lastModified/1000|formatDate}}</h4><h5><span class="gray" translate>COMMON.FILE.SIZE</span> {{fileData.size|formatInteger}} Ko</h5></div><div class="col padding-left"><h3 ng-if="validatingFile" translate>COMMON.FILE.VALIDATING</h3><h3 ng-if="!validatingFile"><span class="dark animate-show-hide ng-hide" ng-show="isValidFile && content.length" ng-bind-html="'ACCOUNT.WALLET_LIST.IMPORT_MODAL.WALLET_COUNT'|translate:{count: content.length}"></span> <span class="assertive animate-show-hide ng-hide" ng-show="isValidFile && !content.length"><br><i class="ion-close-circled assertive"></i> {{'ACCOUNT.WALLET_LIST.IMPORT_MODAL.NO_NEW_WALLET' |translate}} </span><span class="assertive animate-show-hide ng-hide" ng-show="!isValidFile"><br><i class="ion-close-circled assertive"></i> {{'ERROR.INVALID_FILE_FORMAT' |translate}}</span></h3></div></div><a class="ion-close-round gray pull-right" style="font-size: 10px; position: absolute; top: 6px; right: 6px" ng-click="removeFile()"></a></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate>COMMON.BTN_CANCEL</button> <button class="button button-positive ink" ng-disabled="loading || !content.length" ng-click="closeModal(content)" translate>COMMON.BTN_IMPORT</button></div></ion-content></ion-modal-view> \ No newline at end of file diff --git a/assets/www/templates/wallet/list/modal_wallets.html b/assets/www/templates/wallet/list/modal_wallets.html new file mode 100644 index 0000000000000000000000000000000000000000..e887f364082bc81f805e2b735fb0a1f520bad752 --- /dev/null +++ b/assets/www/templates/wallet/list/modal_wallets.html @@ -0,0 +1 @@ +<ion-modal-view id="transfer" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>ACCOUNT.SELECT_WALLET_MODAL.TITLE</h1></ion-header-bar><ion-content scroll="true"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding gray" ng-if="!loading && !wallets.length && !defaultWallet">{{:locale:'ACCOUNT.WALLET_LIST.NO_WALLET'|translate}}</div><ion-list ng-if="!loading" class="{{::motion.ionListClass}}"><ng-include ng-if="defaultWallet" ng-init="wallet = defaultWallet" src="'templates/wallet/list/item_wallet.html'"></ng-include><ng-repeat ng-repeat="wallet in wallets track by wallet.id" ng-include="'templates/wallet/list/item_wallet_light.html'"></ng-repeat></ion-list></ion-content></ion-modal-view> \ No newline at end of file diff --git a/assets/www/templates/wallet/list/popover_actions.html b/assets/www/templates/wallet/list/popover_actions.html new file mode 100644 index 0000000000000000000000000000000000000000..beac2a900bc1890766ba5b55a4ee4c5eef06e13e --- /dev/null +++ b/assets/www/templates/wallet/list/popover_actions.html @@ -0,0 +1 @@ +<ion-popover-view class="fit has-header"><ion-header-bar><h1 class="title" translate="">COMMON.POPOVER_ACTIONS_TITLE</h1></ion-header-bar><ion-content scroll="false"><div class="list item-text-wrap"><button class="item item-icon-left ink" ng-class="{'gray': loading || !wallets.length, 'assertive': !loading && wallets.length}" ng-disabled="loading || !wallets.length" ng-click="selectAndRemoveWallet()"><i class="icon ion-trash-a"></i> {{'ACCOUNT.WALLET_LIST.BTN_DELETE' | translate}}</button></div></ion-content></ion-popover-view> \ No newline at end of file diff --git a/assets/www/templates/wallet/list/popover_wallets.html b/assets/www/templates/wallet/list/popover_wallets.html new file mode 100644 index 0000000000000000000000000000000000000000..a9159a9461a44f7d414dd9e9597b7e7e9be64be9 --- /dev/null +++ b/assets/www/templates/wallet/list/popover_wallets.html @@ -0,0 +1 @@ +<ion-popover-view class="fit popover-wallets popover-light"><ion-header-bar class="stable-bg block"><div class="title" translate>ACCOUNT.SELECT_WALLET_MODAL.TITLE</div><div class="pull-right"><a class="positive" ng-click="showNewWalletModal()" translate>ACCOUNT.WALLET_LIST.BTN_NEW</a></div></ion-header-bar><ion-content scroll="true"><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="center padding gray" ng-if="!loading && !wallets.length && !defaultWallet">{{:locale:'ACCOUNT.WALLET_LIST.NO_WALLET'|translate}}</div><ion-list ng-if="!loading"><ng-include ng-if="defaultWallet" ng-init="wallet = defaultWallet" src="'templates/wallet/list/item_wallet_light.html'"></ng-include><ng-repeat ng-repeat="wallet in :rebind:wallets | filter:filterFn(formData) track by wallet.id" ng-include="'templates/wallet/list/item_wallet_light.html'"></ng-repeat></ion-list></ion-content><ion-footer-bar class="stable-bg block"><div class="pull-right"><a class="positive" ui-sref="app.view_wallets" ng-click="closePopover()" translate>COMMON.NOTIFICATIONS.SHOW_ALL</a></div></ion-footer-bar></ion-popover-view> \ No newline at end of file diff --git a/assets/www/templates/wallet/list/popup_edit_name.html b/assets/www/templates/wallet/list/popup_edit_name.html new file mode 100644 index 0000000000000000000000000000000000000000..f438afc46452d7c2c86061ac2397817a57223a2c --- /dev/null +++ b/assets/www/templates/wallet/list/popup_edit_name.html @@ -0,0 +1 @@ +<form name="editForm" ng-submit=""><div class="list" ng-init="setEditForm(editForm)"><label class="item item-input" ng-class="{'item-input-error': editForm.$submitted && editForm.name.$invalid}"><input name="name" type="text" placeholder="{{'ACCOUNT.WALLET_LIST.EDIT_POPOVER.NAME_HELP' | translate}}" ng-model="formData.name" ng-minlength="3" required></label><div class="form-errors" ng-if="editForm.$submitted && editForm.name.$error" ng-messages="editForm.name.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div></div></form> \ No newline at end of file diff --git a/assets/www/templates/wallet/list/view_wallets.html b/assets/www/templates/wallet/list/view_wallets.html new file mode 100644 index 0000000000000000000000000000000000000000..23f6569d0fdc65d150bbf86c4c62b8ae56442899 --- /dev/null +++ b/assets/www/templates/wallet/list/view_wallets.html @@ -0,0 +1 @@ +<ion-view left-buttons="leftButtons" class="view-wallet-list"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true" class="padding no-padding-xs no-padding-sm" bind-notifier="{ rebind:formData.useRelative, locale:settings.locale.id}"><ion-refresher pulling-text="{{:locale:'COMMON.BTN_REFRESH' | translate}}" on-refresh="doUpdate(true, $event)"></ion-refresher><div class="center padding gray" ng-if="!loading && wallets && !wallets.length && !defaultWallet">{{:locale:'ACCOUNT.WALLET_LIST.NO_WALLET'|translate}}</div><ion-list class="{{::motion.ionListClass}}"><ng-include ng-if="defaultWallet" ng-init="wallet = defaultWallet" src="'templates/wallet/list/item_wallet.html'"></ng-include><ng-include ng-repeat="wallet in wallets track by wallet.id" src="'templates/wallet/list/item_wallet.html'"></ng-include></ion-list><div class="center padding visible-xs visible-sm" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div></ion-content><button id="fab-add-wallet" class="button button-fab button-fab-bottom-right button-assertive hidden-md hidden-lg drop ng-hide" ng-show="!loading" ng-click="showNewWalletModal()"><i class="icon ion-plus"></i></button></ion-view> \ No newline at end of file diff --git a/assets/www/templates/wallet/modal_security.html b/assets/www/templates/wallet/modal_security.html index bb917d1d1466edf44498bc932e1ab99f75acd808..e8e323c44e7af131da817c35bf15a5aa924469c6 100644 --- a/assets/www/templates/wallet/modal_security.html +++ b/assets/www/templates/wallet/modal_security.html @@ -1 +1 @@ -<ion-modal-view class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-if="!slides.slider.activeIndex" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button> <button class="button button-icon button-clear icon ion-ios-arrow-back buttons header-item" ng-click="slidePrev()" ng-if="slides.slider.activeIndex"></button><h1 class="title hidden-xs" translate="">ACCOUNT.SECURITY.TITLE</h1><button class="button button-clear icon-right visible-xs" ng-if="!isLastSlide && slides.slider.activeIndex > 0" ng-click="doNext()"><span translate="">COMMON.BTN_NEXT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-positive button-icon button-clear icon ion-android-done visible-xs" ng-click="doNext()" ng-if="isLastSlide && option === 'saveID'"></button></ion-header-bar><ion-slides options="slides.options" slider="slides.slider"><ion-slide-page><ion-content class="has-header padding"><div class="list"><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="selectOption('recoverID')" ng-if="!isLogin"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-person"></i> <b class="ion-ios-undo icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.RECOVER_ID</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.RECOVER_ID_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="selectOption('revocation')" ng-if="!isLogin"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-person"></i> <b class="ion-close icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.REVOCATION_WITH_FILE</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.REVOCATION_WITH_FILE_DESCRIPTION</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="selectOption('saveID')" ng-if="isLogin"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-person"></i> <b class="ion-ios-redo icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b> <b class="ion-locked icon-secondary dark" style="top: 0px; left: 40px; font-size: 8px"></b><h2 translate="">ACCOUNT.SECURITY.SAVE_ID</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.SAVE_ID_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="selectOption('generateKeyfile')" ng-if="isLogin"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-document-text"></i> <b class="ion-key icon-secondary dark" style="top: -8px; left: 42px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.GENERATE_KEYFILE</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.GENERATE_KEYFILE_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="self()" ng-if="needSelf"><div class="item-content item-text-wrap"><i class="item-image icon ion-person dark"></i> <b class="ion-flag icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.SEND_IDENTITY</h2><h4 class="gray" ng-bind-html="::'ACCOUNT.SECURITY.SEND_IDENTITY_HELP' | translate"></h4></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="membershipIn()" ng-if="needMembership"><div class="item-content item-text-wrap"><i class="item-image icon ion-person dark"></i> <b class="ion-plus icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.MEMBERSHIP_IN</h2><h4 class="gray" ng-bind-html="::'ACCOUNT.SECURITY.MEMBERSHIP_IN_HELP' | translate"></h4></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="revokeWalletIdentity()" ng-if="isLogin && hasSelf"><div class="item-content item-text-wrap"><i class="item-image icon ion-person assertive-900"></i> <b class="ion-close icon-secondary assertive-900" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.REVOCATION_WALLET</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.REVOCATION_WALLET_HELP</h4></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate="">COMMON.BTN_CANCEL</button></div></ion-content></ion-slide-page><ion-slide-page ng-if="option == 'revocation'"><ng-include src="'templates/wallet/slides/slides_revocation_file.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="isLogin && option == 'saveID'"><ng-include src="'templates/wallet/slides/slides_saveID_1.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="isLogin && option == 'saveID'"><ng-include src="'templates/wallet/slides/slides_saveID_2.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="option == 'recoverID'"><ng-include src="'templates/wallet/slides/slides_recoverID_1.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="option == 'recoverID'"><ng-include src="'templates/wallet/slides/slides_recoverID_2.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="option == 'recoverID'"><ng-include src="'templates/wallet/slides/slides_recoverID_3.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="isLogin && option == 'generateKeyfile'"><ng-include src="'templates/wallet/slides/slides_generate_keyfile.html'"></ng-include></ion-slide-page></ion-slides></ion-modal-view> \ No newline at end of file +<ion-modal-view class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-if="!slides.slider.activeIndex" ng-click="closeModal()" translate="">COMMON.BTN_CANCEL</button> <button class="button button-icon button-clear icon ion-ios-arrow-back buttons header-item" ng-click="slidePrev()" ng-if="slides.slider.activeIndex"></button><h1 class="title hidden-xs" translate="">ACCOUNT.SECURITY.TITLE</h1><button class="button button-clear icon-right visible-xs" ng-if="!isLastSlide && slides.slider.activeIndex > 0" ng-click="doNext()"><span translate="">COMMON.BTN_NEXT</span> <i class="icon ion-ios-arrow-right"></i></button> <button class="button button-positive button-icon button-clear icon ion-android-done visible-xs" ng-click="doNext()" ng-if="isLastSlide && option === 'saveID'"></button></ion-header-bar><ion-slides options="slides.options" slider="slides.slider"><ion-slide-page><ion-content class="has-header padding"><div class="list"><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="selectOption('recoverID')" ng-if="!login"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-person"></i> <b class="ion-ios-undo icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.RECOVER_ID</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.RECOVER_ID_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="selectOption('revocation')" ng-if="!login"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-person"></i> <b class="ion-close icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.REVOCATION_WITH_FILE</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.REVOCATION_WITH_FILE_DESCRIPTION</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink hidden-xs" ng-click="selectOption('saveID')" ng-if="login && !$root.device.enable"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-person"></i> <b class="ion-ios-redo icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b> <b class="ion-locked icon-secondary dark" style="top: 0px; left: 40px; font-size: 8px"></b><h2 translate="">ACCOUNT.SECURITY.SAVE_ID</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.SAVE_ID_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink hidden-xs" ng-click="selectOption('generateKeyfile')" ng-if="login && !$root.device.enable"><div class="item-content item-text-wrap"><i class="item-image dark icon ion-document-text"></i> <b class="ion-key icon-secondary dark" style="top: -8px; left: 42px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.GENERATE_KEYFILE</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.GENERATE_KEYFILE_HELP</h4><i class="icon dark ion-ios-arrow-right"></i></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="self()" ng-if="needSelf"><div class="item-content item-text-wrap"><i class="item-image icon ion-person dark"></i> <b class="ion-flag icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.SEND_IDENTITY</h2><h4 class="gray" ng-bind-html="::'ACCOUNT.SECURITY.SEND_IDENTITY_HELP' | translate"></h4></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="membershipIn()" ng-if="needMembership"><div class="item-content item-text-wrap"><i class="item-image icon ion-person dark"></i> <b class="ion-plus icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.MEMBERSHIP_IN</h2><h4 class="gray" ng-bind-html="::'ACCOUNT.SECURITY.MEMBERSHIP_IN_HELP' | translate"></h4></div></div><div class="item item-complex card stable-bg item-icon-left item-icon-right ink" ng-click="revokeWalletIdentity()" ng-if="canRevoke"><div class="item-content item-text-wrap"><i class="item-image icon ion-person assertive-900"></i> <b class="ion-close icon-secondary assertive-900" style="top: -8px; left: 39px; font-size: 12px"></b><h2 translate="">ACCOUNT.SECURITY.REVOCATION_WALLET</h2><h4 class="gray" translate="">ACCOUNT.SECURITY.REVOCATION_WALLET_HELP</h4></div></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="closeModal()" type="button" translate="">COMMON.BTN_CANCEL</button></div></ion-content></ion-slide-page><ion-slide-page ng-if="option == 'revocation'"><ng-include src="'templates/wallet/slides/slides_revocation_file.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="login && option == 'saveID'"><ng-include src="'templates/wallet/slides/slides_saveID_1.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="login && option == 'saveID'"><ng-include src="'templates/wallet/slides/slides_saveID_2.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="option == 'recoverID'"><ng-include src="'templates/wallet/slides/slides_recoverID_1.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="option == 'recoverID'"><ng-include src="'templates/wallet/slides/slides_recoverID_2.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="option == 'recoverID'"><ng-include src="'templates/wallet/slides/slides_recoverID_3.html'"></ng-include></ion-slide-page><ion-slide-page ng-if="login && option == 'generateKeyfile'"><ng-include src="'templates/wallet/slides/slides_generate_keyfile.html'"></ng-include></ion-slide-page></ion-slides></ion-modal-view> \ No newline at end of file diff --git a/assets/www/templates/wallet/modal_transfer.html b/assets/www/templates/wallet/modal_transfer.html index dae6ca6ae79011816cde90d08012c77371cf9e3f..d0ad76dfb00507765d3cf2b15dfac2e45ecae88d 100644 --- a/assets/www/templates/wallet/modal_transfer.html +++ b/assets/www/templates/wallet/modal_transfer.html @@ -1 +1 @@ -<ion-modal-view id="transfer" class="modal-full-height modal-transfer"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>TRANSFER.MODAL.TITLE</h1><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doTransfer()"></button></ion-header-bar><ion-content scroll="true"><ng-include src="'templates/wallet/transfer_form.html'"></ng-include></ion-content><ion-digit-keyboard settings="digitKeyboardSettings" ng-if="digitKeyboardVisible"></ion-digit-keyboard></ion-modal-view> \ No newline at end of file +<ion-modal-view id="transfer" class="modal-full-height modal-transfer"><ion-header-bar class="bar-positive"><button class="button button-clear visible-xs" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>TRANSFER.MODAL.TITLE</h1><button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doTransfer()"></button></ion-header-bar><ion-content><ng-include src="'templates/wallet/transfer_form.html'"></ng-include></ion-content><ion-digit-keyboard settings="digitKeyboardSettings" ng-if="digitKeyboardVisible"></ion-digit-keyboard></ion-modal-view> \ No newline at end of file diff --git a/assets/www/templates/wallet/popup_register.html b/assets/www/templates/wallet/popup_register.html index 10fb3dfaf7e7d99de90a22bd69d9c00d3561377d..c3323433da17ee77e8d9e3d799d9e68ef1192bb5 100644 --- a/assets/www/templates/wallet/popup_register.html +++ b/assets/www/templates/wallet/popup_register.html @@ -1 +1 @@ -<form name="registerForm" ng-submit=""><div class="list" ng-init="setRegisterForm(registerForm)"><label class="item item-input" ng-class="{'item-input-error': registerForm.$submitted && registerForm.pseudo.$invalid}"><input name="pseudo" type="text" placeholder="{{'ACCOUNT.NEW.PSEUDO_HELP' | translate}}" ng-model="walletData.newUid" ng-minlength="3" required></label><div class="form-errors" ng-if="registerForm.$submitted && registerForm.pseudo.$error" ng-messages="registerForm.pseudo.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div></div></form> \ No newline at end of file +<form name="registerForm" ng-submit=""><div class="list" ng-init="setRegisterForm(registerForm)"><label class="item item-input" ng-class="{'item-input-error': registerForm.$submitted && registerForm.pseudo.$invalid}"><input name="pseudo" type="text" placeholder="{{'ACCOUNT.NEW.PSEUDO_HELP' | translate}}" ng-model="formData.newUid" ng-minlength="3" required></label><div class="form-errors" ng-if="registerForm.$submitted && registerForm.pseudo.$error" ng-messages="registerForm.pseudo.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="minlength"><span translate="ERROR.FIELD_TOO_SHORT"></span></div></div></div></form> \ No newline at end of file diff --git a/assets/www/templates/wallet/transfer_form.html b/assets/www/templates/wallet/transfer_form.html index d80f8b8e4c500b87eff9d88d76bfc932e3a68555..6483ad8c611daaa8d5935c7f3cbc46923bce2c08 100644 --- a/assets/www/templates/wallet/transfer_form.html +++ b/assets/www/templates/wallet/transfer_form.html @@ -1,2 +1 @@ -<form name="transferForm" novalidate="" ng-submit="doTransfer()"><div class="list no-padding-xs" ng-init="setForm(transferForm)"><a class="item item-icon-right gray ink" ng-class="{'item-input-error': form.$submitted && !formData.destPub}" ng-click="showWotLookupModal()"><span class="gray" translate="">TRANSFER.TO</span> <span class="badge badge-royal animate-fade-in animate-show-hide ng-hide" ng-show="destUid"><i class="ion-person"></i> {{destUid}} </span> <span class="badge badge-royal" ng-show="!destUid && formData.destPub"><i class="ion-key"></i> {{formData.destPub | formatPubkey}} </span><i class="gray icon ion-ios-arrow-right"></i></a><div class="form-errors" ng-if="form.$submitted && !formData.destPub"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><span class="item item-text-wrap"><span class="gray" translate="">TRANSFER.FROM</span> <span class="badge animate-fade-in animate-show-hide ng-hide" ng-show="!loading" ng-class="{'badge-assertive': (convertedBalance <= 0 || (formData.amount && convertedBalance < formData.amount)), 'badge-balanced': (convertedBalance > 0 && (!formData.amount || convertedBalance >= formData.amount)) }"><ion-spinner icon="android" ng-if="!walletData.pubkey"></ion-spinner><span ng-if="walletData.pubkey && !walletData.isMember"><i class="ion-key"></i> {{walletData.pubkey| formatPubkey}} </span><span ng-if="walletData.isMember"><i class="ion-person"></i> {{walletData.name||walletData.uid}} </span><span ng-bind-html="walletData.balance|formatAmount:{useRelative: formData.useRelative, currency:currency}"></span></span></span><ion-item class="item-input item-floating-label item-button-right" ng-class="{'item-input-error': form.$submitted && form.amount.$invalid}"><div class="input-label"><span translate="">TRANSFER.AMOUNT</span> (<span ng-bind-html="$root.currency.name | currencySymbol:formData.useRelative"></span>)</div><input type="text" class="visible-xs visible-sm" name="amount" placeholder="{{::'TRANSFER.AMOUNT_HELP' | translate}} ({{$root.currency.name | currencySymbolNoHtml:formData.useRelative}})" ng-model="formData.amount" required number-float=""><div class="block visible-xs visible-sm" style="position:absolute; opacity:0; z-index:100; top: 0; left: 0; height: 100%; width: 100%" ng-click="showDigitKeyboard()"></div><a class="button button-icon gray icon ion-android-more-vertical ink visible-xs visible-sm" style="z-index:110; right: 0px" ng-click="showUnitPopover($event)"></a></ion-item><div class="form-errors" ng-show="form.$submitted && form.amount.$error" ng-messages="form.amount.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="numberFloat"><span translate="ERROR.FIELD_NOT_NUMBER"></span></div><div class="form-error" ng-message="numberInt"><span translate="ERROR.FIELD_NOT_INT"></span></div><div class="form-error" ng-message="min"><span translate="ERROR.FIELD_MIN" translate-values="{min: minAmount}"></span></div></div><div class="pull-right visible-xs visible-sm" ng-if="!formData.useComment"><a class="button button-text button-small ink" ng-click="addComment()"><i class="icon ion-plus"></i> <span translate="">TRANSFER.BTN_ADD_COMMENT</span></a></div><label class="item item-input item-floating-label visible-xs visible-sm" ng-if="formData.useComment" ng-class="{'item-input-error': form.$submitted && form.comment.$invalid}"><span class="input-label">{{'TRANSFER.COMMENT' | translate}}</span><textarea placeholder="{{'TRANSFER.COMMENT_HELP' | translate}}" id="{{commentInputId}}" name="comment" ng-model="formData.comment" ng-maxlength="255" ng-pattern="commentPattern" ng-focus="hideDigitKeyboard()"> - </textarea></label><div class="form-errors" ng-show="form.$submitted && form.comment.$error" ng-messages="form.comment.$error"><div class="form-error" ng-message="maxlength"><span translate="ERROR.FIELD_TOO_LONG"></span></div><div class="form-error" ng-message="pattern"><span translate="ERROR.FIELD_ACCENT"></span></div></div><div class="item item-icon-left item-text-wrap visible-xs visible-sm" ng-if="formData.useComment"><i class="icon ion-ios-information-outline positive"></i><h4 class="positive" translate="">TRANSFER.WARN_COMMENT_IS_PUBLIC</h4></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" ng-click="cancel()" type="button" translate="">COMMON.BTN_CANCEL</button> <button class="button button-positive ink" type="submit">{{'TRANSFER.BTN_SEND' | translate}}</button></div></form> \ No newline at end of file +<form name="transferForm" novalidate="" ng-submit="doTransfer()"><div class="list no-padding-xs" ng-init="setForm(transferForm)"><ion-item class="item-icon-right gray ink" ng-class="{'item-input-error': form.$submitted && !formData.destPub}" tabindex="1" ng-click="showWotLookupModal()"><span class="gray" translate="">TRANSFER.TO</span> <span class="badge badge-royal animate-fade-in animate-show-hide ng-hide" ng-show="destUid"><i class="ion-person"></i> {{destUid}} </span> <span class="badge badge-royal" ng-show="!destUid && formData.destPub"><i class="ion-key"></i> {{formData.destPub | formatPubkey}} </span><i class="gray icon ion-ios-arrow-right"></i></ion-item><div class="form-errors" ng-if="form.$submitted && !formData.destPub"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><ion-item class="item-text-wrap ink" ng-class="{'item-icon-right': enableSelectWallet}" tabindex="2" ng-click="showSelectWalletModal()"><span class="gray" translate="">TRANSFER.FROM</span> <span class="badge animate-fade-in animate-show-hide ng-hide" ng-show="!loading" ng-class="{'badge-assertive': (convertedBalance <= 0 || form.amount.$error.max), 'badge-balanced': (convertedBalance > 0 && (!form.amount.$error.max)) }"><ion-spinner icon="android" ng-show="!walletData.pubkey"></ion-spinner><span ng-if="walletData.pubkey && !walletData.isMember"><i class="ion-key"></i> {{walletData.pubkey| formatPubkey}} </span><span ng-if="walletData.isMember"><i class="ion-person"></i> {{walletData.name||walletData.uid}} </span><span ng-bind-html="walletData.balance|formatAmount:{useRelative: formData.useRelative, currency:currency}"></span> </span><i class="gray icon ion-ios-arrow-right" ng-if="enableSelectWallet"></i></ion-item><ion-item class="item-input item-floating-label item-button-right" ng-class="{'item-input-error': form.$submitted && form.amount.$invalid}"><div class="input-label"><span translate="">TRANSFER.AMOUNT</span> (<span ng-bind-html="$root.currency.name | currencySymbol:formData.useRelative"></span>)</div><input type="text" tabindex="-1" autocomplete="off" class="visible-xs visible-sm" name="amount" placeholder="{{::'TRANSFER.AMOUNT_HELP' | translate}}" ng-model="formData.amount" required number-float=""><div class="block visible-xs visible-sm" style="position:absolute; opacity:0; z-index:100; top: 0; left: 0; height: 100%; width: 100%" tabindex="4" ng-click="showDigitKeyboard()"></div><a class="button button-clear button-stable dark ink" tabindex="-1" style="z-index:110; padding: 0px 16px" ng-click="showUnitPopover($event)"><span ng-bind-html="$root.currency.name | currencySymbol:formData.useRelative"></span> <b class="ion-arrow-down-b" style="font-size: 12pt"></b></a></ion-item><div class="form-errors" ng-show="form.$submitted && form.amount.$error" ng-messages="form.amount.$error"><div class="form-error" ng-message="required"><span translate="ERROR.FIELD_REQUIRED"></span></div><div class="form-error" ng-message="numberFloat"><span translate="ERROR.FIELD_NOT_NUMBER"></span></div><div class="form-error" ng-message="numberInt"><span translate="ERROR.FIELD_NOT_INT"></span></div><div class="form-error" ng-message="min"><span translate="ERROR.FIELD_MIN" translate-values="{min: minAmount}"></span></div><div class="form-error" ng-message="max"><span translate="ERROR.NOT_ENOUGH_CREDIT"></span></div></div><a class="item item-icon-right gray ink" ng-class="{'item-input-error': form.$submitted && !formData.destPub}" ng-click="showWotLookupModal('restPub')" tabindex="5" ng-if="formData.all && formData.restAmount"><span class="gray"><i translate="">TRANSFER.REST</i><ng-if ng-if="formData.restAmount">(<i ng-bind-html="formData.restAmount|formatAmount:{useRelative: formData.useRelative, currency:currency}"></i>)</ng-if><i translate="">TRANSFER.REST_TO</i> </span><span class="badge badge-royal animate-fade-in animate-show-hide ng-hide" ng-show="restUid"><i class="ion-person"></i> {{restUid}} </span> <span class="badge badge-royal" ng-show="!restUid && formData.restPub"><i class="ion-key"></i> {{formData.restPub | formatPubkey}} </span><i class="gray icon ion-ios-arrow-right"></i></a><div class="form-errors" ng-if="form.$submitted && formData.all && !formData.restPub && formData.restAmount > 0"><div class="form-error"><span translate="ERROR.FIELD_REQUIRED"></span></div></div><div class="pull-right visible-xs visible-sm" ng-if="!formData.useComment"><a class="button button-text button-small ink" tabindex="-1" ng-click="addComment()"><i class="icon ion-plus"></i> <span translate="">TRANSFER.BTN_ADD_COMMENT</span></a></div><label class="item item-input item-floating-label visible-xs visible-sm" ng-if="formData.useComment" ng-class="{'item-input-error': form.$submitted && form.comment.$invalid}"><span class="input-label">{{'TRANSFER.COMMENT' | translate}}</span> <input type="text" placeholder="{{'TRANSFER.COMMENT_HELP' | translate}}" id="{{commentInputId}}" tabindex="7" name="comment" autocomplete="off" ng-model="formData.comment" ng-model-options="{ debounce: 650 }" ng-maxlength="255" ng-pattern="commentPattern" ng-focus="hideDigitKeyboard()"></label><div class="form-errors" ng-show="form.comment.$error" ng-messages="form.comment.$error"><div class="form-error" ng-message="maxlength"><span translate="ERROR.FIELD_TOO_LONG"></span></div><div class="form-error" ng-message="pattern"><span translate="ERROR.FIELD_ACCENT"></span></div></div><div class="item item-icon-left item-text-wrap item-no-border visible-xs visible-sm" ng-if="formData.useComment"><i class="icon ion-android-alert positive"></i><h4 class="positive" translate="">TRANSFER.WARN_COMMENT_IS_PUBLIC</h4></div></div><div class="padding hidden-xs text-right"><button class="button button-clear button-dark ink" tabindex="-1" ng-click="cancel()" type="button" translate="">COMMON.BTN_CANCEL</button> <button class="button ink" tabindex="8" ng-class="{'button-assertive': formData.all, 'button-positive': !formData.all}" type="submit" translate="">TRANSFER.BTN_SEND</button></div></form> \ No newline at end of file diff --git a/assets/www/templates/wallet/tx_locked_outputs_popover.html b/assets/www/templates/wallet/tx_locked_outputs_popover.html index 2f83a017778cac2664e7d783ca940f306fe66e7c..3ccdd3a3459ce93d3caff7c09f60dee8fb2557ef 100644 --- a/assets/www/templates/wallet/tx_locked_outputs_popover.html +++ b/assets/www/templates/wallet/tx_locked_outputs_popover.html @@ -1 +1 @@ -<ion-popover-view class="fit popover-locked-outputs"><ion-header-bar><h1 class="title" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.TITLE</h1></ion-header-bar><ion-content scroll="true"><div ng-if="popoverData.lockedOuputs.length == 1" class="item item-text-wrap no-border"><h4 class="positive" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.DESCRIPTION</h4></div><div ng-if="popoverData.lockedOuputs.length > 1" class="item item-text-wrap no-border"><h4 class="positive" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.DESCRIPTION_MANY</h4></div><div ng-repeat="output in popoverData.lockedOuputs track by $index" class="item"><h2 class="gray" ng-if="popoverData.lockedOuputs.length > 1" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.LOCKED_AMOUNT</h2><div ng-if="popoverData.lockedOuputs.length > 1" class="badge item-note" ng-class="{'badge-balanced': output.amount > 0}"><i class="icon ion-locked"></i> <span ng-bind-html="::output.amount| formatAmount"></span> <span ng-bind-html="::unit"></span></div><div ng-repeat="condition in output.unlockConditions track by $index" class="row" ng-class="::{'padding-top': !$index && popoverData.lockedOuputs.length > 1}" ng-style="::condition.style"><span class="gray" ng-if="::condition.operator">{{::'BLOCKCHAIN.VIEW.TX_OUTPUT_OPERATOR.'+condition.operator|translate}} </span><div ng-if="::condition.type=='SIG'"><i class="icon ion-key dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.SIG' | translate"></span> <a ng-click="goState('app.wot_identity', {pubkey:condition.value})" style="text-decoration: none" class="positive">{{condition.value|formatPubkey}}</a></div><div ng-if="::condition.type=='XHX'"><i class="icon ion-lock-combination dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.XHX' | translate"></span> <a copy-on-click="{{::condition.value}}" class="positive">{{::condition.value|formatPubkey}}...</a></div><div ng-if="condition.type=='CSV'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CSV' | translate"></span> {{::condition.value|formatDuration}}</div><div ng-if="condition.type=='CLTV'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CLTV' | translate"></span> {{::condition.value|formatDate}}</div></div></div></ion-content></ion-popover-view> \ No newline at end of file +<ion-popover-view class="fit popover-locked-outputs"><ion-header-bar><h1 class="title" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.TITLE</h1></ion-header-bar><ion-content scroll="true"><div ng-if="popoverData.lockedOuputs.length == 1" class="item item-text-wrap no-border"><h4 class="positive" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.DESCRIPTION</h4></div><div ng-if="popoverData.lockedOuputs.length > 1" class="item item-text-wrap no-border"><h4 class="positive" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.DESCRIPTION_MANY</h4></div><div ng-repeat="output in popoverData.lockedOuputs track by $index" class="item"><h2 class="gray" ng-if="popoverData.lockedOuputs.length > 1" translate>ACCOUNT.LOCKED_OUTPUTS_POPOVER.LOCKED_AMOUNT</h2><div ng-if="popoverData.lockedOuputs.length > 1" class="badge item-note" ng-class="{'badge-balanced': output.amount > 0}"><i class="icon ion-locked"></i> <span ng-bind-html="::output.amount| formatAmount"></span> <span ng-bind-html="::unit"></span></div><div ng-repeat="condition in output.unlockConditions track by $index" class="row" ng-class="::{'padding-top': !$index && popoverData.lockedOuputs.length > 1}" ng-style="::condition.style"><span class="gray" ng-if="::condition.operator">{{::'BLOCKCHAIN.VIEW.TX_OUTPUT_OPERATOR.'+condition.operator|translate}} </span><div ng-if="::condition.type=='SIG'"><i class="icon ion-key dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.SIG' | translate"></span> <a ng-click="goState('app.wot_identity', {pubkey:condition.value})" style="text-decoration: none" class="positive">{{condition.value|formatPubkey}}</a></div><div ng-if="::condition.type=='XHX'"><i class="icon ion-lock-combination dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.XHX' | translate"></span> <a copy-on-click="{{::condition.value}}" class="positive">{{::condition.value|formatPubkey}}...</a></div><div ng-if="condition.type=='CSV'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CSV' | translate"></span> {{::condition.value|formatDuration}}</div><div ng-if="condition.type=='CLTV'"><i class="icon ion-clock dark"></i> <span class="dark" ng-bind-html="::'BLOCKCHAIN.VIEW.TX_OUTPUT_FUNCTION.CLTV' | translate"></span> {{::condition.value|medianDate}}</div></div></div></ion-content></ion-popover-view> \ No newline at end of file diff --git a/assets/www/templates/wallet/view_wallet.html b/assets/www/templates/wallet/view_wallet.html index 137ff5385d742c3862aee1fd023071d9096b2879..e554a7b8bc69e141c8acf180e2ffdcf11d548d9f 100644 --- a/assets/www/templates/wallet/view_wallet.html +++ b/assets/www/templates/wallet/view_wallet.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" class="view-wallet" id="wallet"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" id="helptip-wallet-options-xs" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true" class="refresher-top-bg refresher-light" bind-notifier="{ rebind:settings.useRelative, locale:$root.settings.locale.id}"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="positive-900-bg hero" id="wallet-header" ng-class="{'hero-qrcode-active': toggleQRCode}"><div class="content" ng-if="!loading"><i class="avatar" ng-if=":rebind:!formData.avatar" ng-class=":rebind:{'avatar-wallet': !formData.isMember, 'avatar-member': formData.isMember}"></i> <i class="avatar" ng-if=":rebind:formData.avatar" style="background-image: url({{:rebind:formData.avatar.src}})"></i><ng-if ng-if=":rebind:formData.name"><h3 class="light">{{:rebind:formData.name}}</h3></ng-if><ng-if ng-if=":rebind:!formData.name"><h3 class="light" ng-if=":rebind:formData.uid">{{:rebind:formData.uid}}</h3><h3 class="light" ng-if=":rebind:!formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</h3></ng-if><h4 class="assertive"><ng-if ng-if=":rebind:(formData.name || formData.uid) && !formData.isMember" translate="">WOT.NOT_MEMBER_PARENTHESIS</ng-if></h4></div><h4 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><div ng-attr-id="{{ qrcodeId }}" class="qrcode spin" ng-class="{'active': toggleQRCode}" ng-click="toggleQRCode = !toggleQRCode"></div><a id="wallet-share-anchor"></a><div class="visible-xs visible-sm padding text-center" ng-if="!loading"><button class="button button-assertive button-small-padding ink" ng-click="logout({askConfirm: true})"><i class="icon ion-log-out"></i> {{'COMMON.BTN_LOGOUT' | translate}}</button><div ng-if="formData.requirements.needRenew"><br><button class="button button-raised button-stable button-small-padding ink" ng-click="renewMembership()"><i class="icon ion-loop assertive"></i> <span class="assertive">{{:locale:'ACCOUNT.BTN_MEMBERSHIP_RENEW' | translate}}</span></button></div></div><div class="row no-padding"><div class="col"><div class="list" ng-class="::motion.ionListClass" ng-hide="loading"><span class="item item-divider" translate="">WOT.GENERAL_DIVIDER</span><div id="helptip-wallet-pubkey" class="item item-icon-left item-text-wrap ink" on-hold="copy(formData.pubkey)" copy-on-click="{{:rebind:formData.pubkey}}"><i class="icon ion-key"></i> <span>{{:locale:'COMMON.PUBKEY'|translate}}</span><h4 id="pubkey" class="dark">{{:rebind:formData.pubkey}}</h4></div><ion-item class="item-icon-left" ng-if=":rebind:formData.sigDate||formData.uid"><i class="icon ion-calendar"></i> <span translate="">COMMON.UID</span><h5 class="dark" ng-if=":rebind:formData.sigDate"><span translate="">WOT.REGISTERED_SINCE</span> {{:rebind:formData.sigDate | formatDate}}</h5><span class="badge badge-stable">{{:rebind:formData.uid}}</span></ion-item><a id="helptip-wallet-certifications" class="item item-icon-left item-icon-right item-text-wrap ink" ng-if="formData.isMember||formData.requirements.pendingMembership||!formData.requirements.needSelf" ng-click="showCertifications()"><i class="icon ion-ribbon-b"></i> <b ng-if="formData.requirements.isSentry" class="ion-star icon-secondary" style="color: yellow; font-size: 16px; left: 25px; top: -7px"></b> {{:locale:'ACCOUNT.CERTIFICATION_COUNT'|translate}}<cs-badge-certification requirements="formData.requirements" parameters="::currency.parameters"></cs-badge-certification><i class="gray icon ion-ios-arrow-right"></i> </a><a id="helptip-wallet-given-certifications" class="item item-icon-left item-text-wrap item-icon-right ink visible-xs visible-sm" ng-if="formData.isMember" ng-click="showGivenCertifications()"><i class="icon ion-ribbon-a"></i> <span translate="">WOT.GIVEN_CERTIFICATIONS.SENT</span> <i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-icon-right ink" ng-if="!loading" ui-sref="app.view_wallet_tx"><i class="icon ion-card"></i> <span translate="">WOT.ACCOUNT_OPERATIONS</span> <i class="gray icon ion-ios-arrow-right"></i> </a><span class="item item-divider" ng-if="formData.events.length">{{:locale:'ACCOUNT.EVENTS' | translate}}</span><div class="item item-text-wrap item-icon-left item-wallet-event" ng-repeat="event in formData.events"><i class="icon" ng-class="{'ion-information-circled royal': event.type=='info','ion-alert-circled': event.type=='warn'||event.type=='error','assertive': event.type=='error','ion-clock': event.type=='pending'}"></i> <span trust-as-html="event.message | translate:event.messageParams"></span></div><cs-extension-point name="general"></cs-extension-point><cs-extension-point name="after-general"></cs-extension-point></div></div></div></ion-content></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="view-wallet" id="wallet"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point><button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" id="helptip-wallet-options-xs" ng-click="showActionsPopover($event)"></button></ion-nav-buttons><ion-content scroll="true" class="refresher-positive-900-bg" bind-notifier="{ rebind:settings.useRelative, locale:$root.settings.locale.id}"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="positive-900-bg hero" style="max-width: 100%; display: block" ng-class="{'hero-qrcode-active': toggleQRCode}"><div class="content" ng-if="!loading" style="max-width: 100%"><i class="avatar" ng-if=":rebind:!formData.avatar" ng-class=":rebind:{'avatar-wallet': !formData.isMember, 'avatar-member': formData.isMember}"></i> <i class="avatar" ng-if=":rebind:formData.avatar" style="background-image: url({{:rebind:formData.avatar.src}})"></i><h3 class="light" ng-if=":rebind:!enableSelectWallet"><span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span> <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span> <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span></h3><h3 class="light" ng-if=":rebind:enableSelectWallet"><a class="visible-xs visible-sm" style="color: lightgray" title="{{:locale:'ACCOUNT.SELECT_WALLET_MODAL.TITLE'|translate}}" ng-click="showSelectWalletModal($event)"><span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span> <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span> <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span> <small><i class="ion-arrow-down-b"></i></small></a></h3><h4 class="assertive"><span ng-if=":rebind:(formData.name || formData.uid) && !formData.isMember" translate="">WOT.NOT_MEMBER_PARENTHESIS</span></h4></div><h4 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><a ng-attr-id="{{ qrcodeId }}" class="qrcode spin pull-right" ng-class="{'active': toggleQRCode}" ng-click="toggleQRCode = !toggleQRCode"></a><a id="wallet-share-anchor"></a><div class="visible-xs visible-sm padding text-center" ng-if="!loading"><button class="button button-assertive button-small-padding ink" ng-if="isDefaultWallet" ng-click="logout({askConfirm: true})"><i class="icon ion-log-out"></i> {{'COMMON.BTN_LOGOUT' | translate}}</button><div ng-if="formData.requirements.needRenew"><br><button class="button button-raised icon-left button-stable button-small-padding ink" ng-click="renewMembership()"><i class="icon ion-loop assertive"></i> <span class="assertive">{{:locale:'ACCOUNT.BTN_MEMBERSHIP_RENEW' | translate}}</span></button></div></div><div class="row no-padding"><div class="col"><div class="list {{::motion.ionListClass}}" ng-hide="loading"><span class="item item-divider" translate="">WOT.GENERAL_DIVIDER</span><div id="helptip-wallet-pubkey" class="item item-icon-left item-text-wrap ink" on-hold="copy(formData.pubkey)" copy-on-click="{{:rebind:formData.pubkey}}"><i class="icon ion-key"></i> <span>{{:locale:'COMMON.PUBKEY'|translate}}</span><h4 id="pubkey" class="dark">{{:rebind:formData.pubkey}}</h4></div><ion-item class="item-icon-left" ng-if=":rebind:formData.sigDate||formData.uid"><i class="icon ion-calendar"></i> <span translate="">COMMON.UID</span><h5 class="dark" ng-if=":rebind:formData.sigDate"><span translate="">WOT.REGISTERED_SINCE</span> {{:rebind:formData.sigDate | medianDate}}</h5><span class="badge badge-stable">{{:rebind:formData.uid}}</span></ion-item><a id="helptip-wallet-certifications" class="item item-icon-left item-icon-right item-text-wrap ink" ng-if="formData.isMember||formData.requirements.pendingMembership||!formData.requirements.needSelf" ng-click="showCertifications()"><i class="icon ion-ribbon-b"></i> <b ng-if="formData.requirements.isSentry" class="ion-star icon-secondary" style="color: yellow; font-size: 16px; left: 25px; top: -7px"></b> {{:locale:'ACCOUNT.CERTIFICATION_COUNT'|translate}}<cs-badge-certification requirements="formData.requirements" parameters="::currency.parameters"></cs-badge-certification><i class="gray icon ion-ios-arrow-right"></i> </a><a id="helptip-wallet-given-certifications" class="item item-icon-left item-text-wrap item-icon-right ink visible-xs visible-sm" ng-if="formData.isMember" ng-click="showGivenCertifications()"><i class="icon ion-ribbon-a"></i> <span translate="">WOT.GIVEN_CERTIFICATIONS.SENT</span> <i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-icon-right ink" ng-click="showTxHistory()"><i class="icon ion-card"></i> <span translate="">WOT.ACCOUNT_OPERATIONS</span> <i class="gray icon ion-ios-arrow-right"></i> </a><span class="item item-divider" ng-if="formData.events.length">{{:locale:'ACCOUNT.EVENTS' | translate}}</span><div class="item item-text-wrap item-icon-left item-wallet-event" ng-repeat="event in formData.events"><i class="icon" ng-class="{'ion-information-circled royal': event.type=='info','ion-alert-circled assertive': event.type=='warn'||event.type=='error','assertive': event.type=='error','ion-clock': event.type=='pending'}"></i> <span trust-as-html="event.message | translate:event.messageParams"></span></div><cs-extension-point name="general"></cs-extension-point><cs-extension-point name="after-general"></cs-extension-point></div></div></div></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/wallet/view_wallet_tx.html b/assets/www/templates/wallet/view_wallet_tx.html index dbfbf297f363358d9070382b080b1ed2de8c29f5..ec4ccf22bd2c448e0dad77735dffea4e26093a1e 100644 --- a/assets/www/templates/wallet/view_wallet_tx.html +++ b/assets/www/templates/wallet/view_wallet_tx.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" class="view-wallet-tx"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point></ion-nav-buttons><ion-content scroll="true" class="refresher-top-bg refresher-light" bind-notifier="{ rebind:settings.useRelative, locale:settings.locale.id}"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="positive-900-bg hero"><div class="content" ng-if="!loading"><h1 class="light"><span ng-bind-html=":balance:rebind:formData.balance | formatAmount:{currency: $root.currency.name}"></span></h1><h4 ng-if="!loading && $root.settings.expertMode" style="font-style: italic">(<span ng-bind-html=":balance:rebind:formData.balance | formatAmount:{useRelative:!$root.settings.useRelative, currency: $root.currency.name}"></span>)</h4><div class="helptip-anchor-center"><a id="helptip-wallet-balance"> </a></div></div><h2 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h2></div><div class="row no-padding"><div class="col"><div class="list" ng-class="::motion.ionListClass"><a class="item item-icon-left item-icon-right ink" ng-if="formData.tx.errors && formData.tx.errors.length" ui-sref="app.view_wallet_tx_errors"><i class="icon ion-alert-circled"></i> {{:locale:'ACCOUNT.ERROR_TX'|translate}}<div class="badge badge-assertive">{{formData.tx.errors.length}}</div><i class="gray icon ion-ios-arrow-right"></i> </a><span class="item item-pending item-divider" ng-if="formData.tx.pendings && formData.tx.pendings.length">{{:locale:'ACCOUNT.PENDING_TX'|translate}}</span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.pendings" ng-init="pending=true;" ng-include="'templates/wallet/item_tx.html'"></div><span class="item item-divider" ng-if="!loading">{{:locale:'ACCOUNT.LAST_TX'|translate}} <a id="helptip-wallet-tx" style="position: relative; bottom: 0; right: 0px"> </a> </span><span class="item padding" ng-if="!loading && !formData.tx.history.length"><span class="gray">{{:locale:'ACCOUNT.NO_TX'|translate}}</span></span><div ng-repeat="tx in formData.tx.history" class="item item-tx item-icon-left" ng-include="::!tx.isUD ? 'templates/wallet/item_tx.html' : 'templates/wallet/item_ud.html'"></div><div class="item item-text-wrap text-center" ng-if="formData.tx.fromTime > 0"><p><a ng-click="showMoreTx()">{{:locale:'ACCOUNT.SHOW_MORE_TX'|translate}}</a> <span class="gray" translate="ACCOUNT.TX_FROM_DATE" translate-values="{fromTime: formData.tx.fromTime}"></span> <span class="gray">|</span> <a ng-click="showMoreTx(-1)" translate="">ACCOUNT.SHOW_ALL_TX</a></p></div></div></div></div></ion-content><button id="fab-transfer" ng-if="formData" class="button button-fab button-fab-bottom-right button-energized-900 hidden-md hidden-lg drop" ng-click="showTransferModal()"><i class="icon ion-android-send"></i></button></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="view-wallet-tx"><ion-nav-title><span class="visible-xs visible-sm" translate="">MENU.TRANSACTIONS</span></ion-nav-title><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point></ion-nav-buttons><ion-content scroll="true" class="refresher-positive-900-bg" bind-notifier="{ rebind:settings.useRelative, locale:settings.locale.id}"><ion-refresher pulling-text="{{:locale:'COMMON.BTN_REFRESH' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="positive-900-bg hero"><div class="content" ng-if="!loading"><h1 class="light"><span ng-bind-html=":balance:rebind:formData.balance | formatAmount:{currency: $root.currency.name}"></span></h1><h4><ng-if ng-if="!loading && $root.settings.expertMode" style="font-style: italic">(<span ng-bind-html=":balance:rebind:formData.balance | formatAmount:{useRelative:!$root.settings.useRelative, currency: $root.currency.name}"></span>)</ng-if><ng-if ng-if=":rebind:!enableSelectWallet" style="color: lightgray"><span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span> <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span> <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span></ng-if><ng-if ng-if=":rebind:enableSelectWallet"><a class="visible-xs visible-sm" style="color: lightgray" title="{{:locale:'ACCOUNT.SELECT_WALLET_MODAL.TITLE'|translate}}" ng-click="showSelectWalletModal($event)"><span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span> <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span> <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span> <small><i class="ion-arrow-down-b"></i></small></a></ng-if></h4><div class="helptip-anchor-center"><a id="helptip-wallet-balance"> </a></div></div><h2 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h2></div><div class="row no-padding"><div class="col"><div class="list {{::motion.ionListClass}}"><a class="item item-icon-left item-icon-right ink" ng-if="formData.tx.errors && formData.tx.errors.length" ng-click="showTxErrors()"><i class="icon ion-alert-circled"></i> {{:locale:'ACCOUNT.ERROR_TX'|translate}}<div class="badge badge-assertive">{{formData.tx.errors.length}}</div><i class="gray icon ion-ios-arrow-right"></i></a><ng-if ng-if="formData.tx.pendings.length"><span class="item item-pending item-divider"><b class="ion-clock"></b> {{:locale:'ACCOUNT.PENDING_TX'|translate}}</span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.pendings" ng-init="pending=true;" ng-include="'templates/wallet/item_tx.html'"></div></ng-if><ng-if ng-if="formData.tx.validating.length"><span class="item item-pending item-divider"><b class="icon ion-checkmark" style="font-size: 12px"></b> <b class="icon-secondary ion-help" style="font-size: 12px; top: 2px; left: 11px"></b> {{:locale:'ACCOUNT.VALIDATING_TX'|translate}}</span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.validating" ng-init="validating=true;" ng-include="::'templates/wallet/item_tx.html'"></div></ng-if><span class="item item-divider" ng-if="!loading"><b class="icon ion-checkmark"></b> {{:locale:'ACCOUNT.LAST_TX'|translate}} <a id="helptip-wallet-tx" style="position: relative; bottom: 0; right: 0px"> </a> </span><span class="item padding" ng-if="!loading && !formData.tx.history.length"><span class="gray">{{:locale:'ACCOUNT.NO_TX'|translate}}</span></span><div ng-repeat="tx in formData.tx.history" class="item item-tx item-icon-left" ng-include="::!tx.isUD ? 'templates/wallet/item_tx.html' : 'templates/wallet/item_ud.html'"></div><div class="item item-text-wrap text-center" ng-if="formData.tx.fromTime > 0"><p><a ng-click="showMoreTx()">{{:locale:'ACCOUNT.SHOW_MORE_TX'|translate}}</a> <span class="gray" translate="ACCOUNT.TX_FROM_DATE" translate-values="{fromTime: formData.tx.fromTime}"></span> <span class="gray">|</span> <a ng-click="showMoreTx(-1)" translate="">ACCOUNT.SHOW_ALL_TX</a></p></div></div></div></div></ion-content><button id="fab-transfer" ng-show="!loading" class="button button-fab button-fab-bottom-right button-energized-900 hidden-md hidden-lg drop ng-hide" ng-click="showTransferModal()"><i class="icon ion-android-send"></i></button></ion-view> \ No newline at end of file diff --git a/assets/www/templates/wallet/view_wallet_tx_error.html b/assets/www/templates/wallet/view_wallet_tx_error.html index f8da69e0b999eb2b30bce323f7782afb3117e43c..918b50d027d3f1dd3ebb0a7ef8d4104af90c9924 100644 --- a/assets/www/templates/wallet/view_wallet_tx_error.html +++ b/assets/www/templates/wallet/view_wallet_tx_error.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" id="wallet"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-loop visible-xs visible-sm" ng-click="doUpdate()"></button></ion-nav-buttons><ion-content scroll="true"><div class="row no-padding"><div class="col list" ng-class="::motion.ionListClass"><span class="item item-divider"><span translate="">ACCOUNT.PENDING_TX_RECEIVED</span><div class="badge item-note"><span ng-if="!$root.settings.useRelative">({{$root.currency.name | abbreviate}})</span> <span ng-if="$root.settings.useRelative">({{'COMMON.UD' | translate}}<sub>{{$root.currency.name | abbreviate}}</sub>)</span></div></span><span class="item" ng-if="!formData.tx.errors.length"><h3 translate="">ACCOUNT.NO_TX</h3></span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.errors | filter: filterReceivedTx" ng-init="pending=true;" ng-include="'templates/wallet/item_tx.html'"></div><span class="item item-divider"><span translate="">ACCOUNT.ERROR_TX_SENT</span><div class="badge item-note"><span ng-if="!$root.settings.useRelative">({{$root.currency.name | abbreviate}})</span> <span ng-if="$root.settings.useRelative">({{'COMMON.UD' | translate}}<sub>{{$root.currency.name | abbreviate}}</sub>)</span></div></span><span class="item" ng-if="!formData.tx.errors.length"><h3 translate="">ACCOUNT.NO_TX</h3></span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.errors | filter: filterSentTx" ng-init="error=true;" ng-include="'templates/wallet/item_tx.html'"></div></div></div></ion-content></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="view-wallet-tx-error"><ion-nav-title></ion-nav-title><ion-nav-buttons side="secondary"><cs-extension-point name="nav-buttons"></cs-extension-point></ion-nav-buttons><ion-content scroll="true" class="refresher-top-bg" bind-notifier="{ rebind:settings.useRelative, locale:settings.locale.id}"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="row no-padding"><div class="col list {{::motion.ionListClass}}"><div class="item item-divider"><span><b class="ion-clock"></b> {{:locale:'ACCOUNT.PENDING_TX_RECEIVED'|translate}}</span><div class="badge item-note"><span ng-if="!$root.settings.useRelative">({{$root.currency.name | abbreviate}})</span> <span ng-if="$root.settings.useRelative">({{'COMMON.UD' | translate}}<sub>{{$root.currency.name | abbreviate}}</sub>)</span></div></div><span class="item padding" ng-if="!loading && !hasReceivedTx()"><span class="gray">{{:locale:'ACCOUNT.NO_TX'|translate}}</span></span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.errors | filter: filterReceivedTx" ng-init="pending=true;" ng-include="'templates/wallet/item_tx.html'"></div><div class="item item-divider"><span><b class="ion-close-circled"></b> {{:locale:'ACCOUNT.ERROR_TX_SENT'|translate}}</span><div class="badge item-note"><span ng-if="!$root.settings.useRelative">({{$root.currency.name | abbreviate}})</span> <span ng-if="$root.settings.useRelative">({{'COMMON.UD' | translate}}<sub>{{$root.currency.name | abbreviate}}</sub>)</span></div></div><span class="item padding" ng-if="!loading && !hasSentTx()"><span class="gray">{{:locale:'ACCOUNT.NO_TX'|translate}}</span></span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.errors | filter: filterSentTx" ng-init="error=true;" ng-include="'templates/wallet/item_tx.html'"></div></div></div></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/wot/item_certification.html b/assets/www/templates/wot/item_certification.html index bf1553aed7d8773be95db35ffa2c1c6ab5c62a45..a7dcf998b559a6fe5005b44705b058a3feeec16c 100644 --- a/assets/www/templates/wot/item_certification.html +++ b/assets/www/templates/wot/item_certification.html @@ -1 +1 @@ -<i class="item-image" ng-if="!cert.avatar" ng-class="{'ion-card': !cert.isMember, 'ion-person': cert.isMember}"></i> <i class="item-image avatar" ng-if="cert.avatar" style="background-image: url({{::cert.avatar.src}})"></i> <span ng-if="cert.isMember"><h3><i class="icon ion-clock" ng-if="cert.pending"></i> <span class="positive">{{::cert.name||cert.uid}}</span></h3><h4 class="gray"><i class="ion-key"></i> {{::cert.pubkey | formatPubkey}} <span class="gray">| {{::cert.time|formatDate}}</span> <span class="gray" ng-if="$root.settings.expertMode">| {{::cert.pending ? 'WOT.SIGNED_ON_BLOCK' : 'WOT.WRITTEN_ON_BLOCK' | translate:cert}}</span></h4></span><span ng-if="!cert.isMember"><h3><i class="icon ion-clock" ng-if="cert.pending"></i> <span ng-if="cert.uid" class="dark">{{::cert.name||cert.uid}} </span><span ng-if="!cert.uid" class="gray"><i class="ion-key"></i> {{::cert.pubkey | formatPubkey}}</span></h3><h5 class="assertive">{{::'WOT.NOT_MEMBER_PARENTHESIS'|translate}}</h5><h4 class="gray"><span ng-if="cert.uid"><i class="ion-key"></i> {{::cert.pubkey | formatPubkey}} </span><span class="gray">| {{::cert.time|formatDate}}</span> <span class="gray" ng-if="$root.settings.expertMode">| {{::cert.pending ? 'WOT.SIGNED_ON_BLOCK' : 'WOT.WRITTEN_ON_BLOCK' | translate:cert}}</span></h4></span><div class="badge badge-stable" ng-class="{'badge-energized': cert.willExpire}" ng-if="cert.expiresIn">{{::cert.expiresIn | formatDurationTo}}</div><div class="badge badge-assertive" ng-if="!cert.expiresIn">{{::'WOT.EXPIRED' | translate}}</div> \ No newline at end of file +<i class="item-image" ng-if="!cert.avatar" ng-class="{'ion-card': !cert.isMember, 'ion-person': cert.isMember}"></i> <i class="item-image avatar" ng-if="cert.avatar" style="background-image: url({{::cert.avatar.src}})"></i> <span ng-if="cert.isMember"><h3><i class="icon ion-clock" ng-if="cert.pending"></i> <span class="positive">{{::cert.name||cert.uid}}</span></h3><h4 class="gray"><i class="ion-key"></i> {{::cert.pubkey | formatPubkey}} <span class="gray">| {{::cert.time|medianDate}}</span> <span class="gray" ng-if="$root.settings.expertMode">| {{::cert.pending ? 'WOT.SIGNED_ON_BLOCK' : 'WOT.WRITTEN_ON_BLOCK' | translate:cert}}</span></h4></span><span ng-if="!cert.isMember"><h3><i class="icon ion-clock" ng-if="cert.pending"></i> <span ng-if="cert.uid" class="dark">{{::cert.name||cert.uid}} </span><span ng-if="!cert.uid" class="gray"><i class="ion-key"></i> {{::cert.pubkey | formatPubkey}}</span></h3><h5 class="assertive">{{::'WOT.NOT_MEMBER_PARENTHESIS'|translate}}</h5><h4 class="gray"><span ng-if="cert.uid"><i class="ion-key"></i> {{::cert.pubkey | formatPubkey}} </span><span class="gray">| {{::cert.time|medianDate}}</span> <span class="gray" ng-if="$root.settings.expertMode">| {{::cert.pending ? 'WOT.SIGNED_ON_BLOCK' : 'WOT.WRITTEN_ON_BLOCK' | translate:cert}}</span></h4></span><div class="badge badge-stable" ng-class="{'badge-energized': cert.willExpire}" ng-if="cert.expiresIn">{{::cert.expiresIn | formatDurationTo}}</div><div class="badge badge-assertive" ng-if="!cert.expiresIn">{{::'WOT.EXPIRED' | translate}}</div> \ No newline at end of file diff --git a/assets/www/templates/wot/item_content_identity.html b/assets/www/templates/wot/item_content_identity.html index e9c2ede114f8284a0ae241b975a480dd2880264c..08a027115dc119cdde515a2b3f3429141fcfa223 100644 --- a/assets/www/templates/wot/item_content_identity.html +++ b/assets/www/templates/wot/item_content_identity.html @@ -1 +1 @@ -<i ng-if="::!item.avatar" class="item-image icon ion-person"></i> <i ng-if="::item.avatar" class="item-image avatar" style="background-image: url({{::item.avatar.src}})"></i><h2><ng-if ng-if="::item.name||item.uid" ng-bind-html="::item.name||item.uid"></ng-if><ng-if ng-if="::!item.name && !item.uid">{{::item.pubkey|formatPubkey}}</ng-if></h2><h4 class="gray" ng-class="{'pull-right': !smallscreen}" ng-if="::item.sigDate"><i class="ion-clock"></i> {{::'WOT.LOOKUP.REGISTERED' | translate:item}}</h4><h4 class="gray" ng-class="{'pull-right': !smallscreen}" ng-if="item.memberDate"><i class="ion-clock"></i> {{::'WOT.LOOKUP.MEMBER_FROM' | translate:item}}</h4><h4 class="gray"><span class="positive" ng-if="::item.name && item.uid"><i class="ion-person"></i> {{::item.uid}} </span><b class="ion-key"></b> {{::item.pubkey | formatPubkey}} <span ng-if="::!item.uid" class="assertive" translate>WOT.NOT_MEMBER_PARENTHESIS</span> <span ng-if="::item.revoked" class="assertive" translate>WOT.IDENTITY_REVOKED_PARENTHESIS</span></h4><h4 ng-if="::item.events||item.tags"><span ng-repeat="event in ::item.events" class="assertive"><i class="ion-alert-circled" ng-if="::!item.valid"></i> <span ng-bind-html="::event.message|translate:event.messageParams"></span> </span><span ng-if="::item.tags" class="dark"><ng-repeat ng-repeat="tag in ::item.tags">#<ng-bind-html ng-bind-html="::tag"></ng-bind-html></ng-repeat></span></h4> \ No newline at end of file +<i ng-if="::!item.avatar" class="item-image icon ion-person"></i> <i ng-if="::item.avatar" class="item-image avatar" style="background-image: url({{::item.avatar.src}})"></i><h2><ng-if ng-if="::item.name||item.uid" ng-bind-html="::item.name||item.uid"></ng-if><ng-if ng-if="::!item.name && !item.uid">{{::item.pubkey|formatPubkey}}</ng-if></h2><h4 class="gray" ng-class="{'pull-right': !smallscreen}" ng-if="::item.sigDate"><i class="ion-clock"></i> {{::'WOT.LOOKUP.REGISTERED' | translate:item }}</h4><h4 class="gray" ng-class="{'pull-right': !smallscreen}" ng-if="item.memberDate"><i class="ion-clock"></i> {{::'WOT.LOOKUP.MEMBER_FROM' | translate:item}}</h4><h4 class="gray"><span class="positive" ng-if="::item.name && item.uid"><i class="ion-person"></i> {{::item.uid}} </span><b class="ion-key"></b> {{::item.pubkey | formatPubkey}} <span ng-if="::(!item.uid && !item.revoked)" class="assertive" translate>WOT.NOT_MEMBER_PARENTHESIS</span> <span ng-if="::item.revoked" class="assertive" translate>WOT.IDENTITY_REVOKED_PARENTHESIS</span></h4><h4 ng-if="::item.events||item.tags"><span ng-repeat="event in ::item.events" class="assertive"><i class="ion-alert-circled" ng-if="::!item.valid"></i> <span ng-bind-html="::event.message|translate:event.messageParams"></span> </span><span ng-if="::item.tags" class="dark"><ng-repeat ng-repeat="tag in ::item.tags">#<ng-bind-html ng-bind-html="::tag"></ng-bind-html></ng-repeat></span></h4> \ No newline at end of file diff --git a/assets/www/templates/wot/lookup_form.html b/assets/www/templates/wot/lookup_form.html index 977dee408ba7e383108e83af74bcf98900863394..65f9b55920b71caaf54dd6b9c7ef6914906fb4de 100644 --- a/assets/www/templates/wot/lookup_form.html +++ b/assets/www/templates/wot/lookup_form.html @@ -1 +1 @@ -<div class="lookupForm"><div class="item no-padding"><div class="double-padding-x padding-top-xs item-text-wrap" ng-if="::allowMultiple" style="height: 36px"><div class="gray padding-top" ng-if="!selection.length && parameters.help">{{::parameters.help|translate}}</div><div ng-repeat="identity in selection track by identity.id" class="button button-small button-text button-stable button-icon-event ink" ng-class="{'button-text-positive': identity.selected}"><span ng-bind-html="identity.name||identity.uid||(identity.pubkey|formatPubkey)"></span> <i class="icon ion-close" ng-click="removeSelection(identity, $event)"> </i></div></div><div class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{'WOT.SEARCH_HELP'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()" on-return="doSearchText()" select-on-click=""><div class="helptip-anchor-center"><a id="helptip-wot-search-text"></a></div></div></div><div class="padding-top padding-xs" style="display: block; height: 60px" ng-class="::{'hidden-xs': !showResultLabel}"><div class="pull-left" ng-if="!search.loading && showResultLabel"><ng-if ng-if="search.type=='newcomers'"><h4 translate="">WOT.LOOKUP.NEWCOMERS</h4><small class="gray no-padding" ng-if="search.total">{{'WOT.LOOKUP.NEWCOMERS_COUNT'|translate:{count: search.total} }}</small></ng-if><ng-if ng-if="search.type=='pending'"><h4 translate="">WOT.LOOKUP.PENDING</h4><small class="gray no-padding" ng-if="search.total">{{'WOT.LOOKUP.PENDING_COUNT'|translate:{count: search.total} }}</small></ng-if><h4 ng-if="search.type=='text'"><span translate="">COMMON.RESULTS_LIST</span> <small class="gray" ng-if="search.total">({{search.total}})</small></h4></div></div><div class="text-center" ng-if="search.loading"><p class="gray" ng-if="::$root.currency.initPhase" translate="">WOT.SEARCH_INIT_PHASE_WARNING</p><ion-spinner icon="android"></ion-spinner></div><ng-if ng-if="!search.loading"><div class="assertive padding" ng-if="!search.results.length"><span ng-if="search.type=='text'" translate="">COMMON.SEARCH_NO_RESULT</span> <span ng-if="search.type=='pending'" translate="">WOT.LOOKUP.NO_PENDING</span> <span ng-if="search.type=='newcomers'" translate="">WOT.LOOKUP.NO_NEWCOMERS</span></div><ion-list ng-if="::!allowMultiple && $root.device.enable" class="{{::motion.ionListClass}}" can-swipe="true"><ng-repeat ng-repeat="item in search.results track by item.id"><div ng-if="::item.divider" class="item item-divider" id="helptip-wot-search-result-{{$index}}">{{::('WOT.SEARCH.DIVIDER_' + item.index)|upper|translate}}</div><ion-item ng-if="::!item.divider" id="helptip-wot-search-result-{{$index}}" class="item item-border-large item-avatar item-icon-right ink" ng-click="::select(item)"><ng-include src="item.templateUrl || 'templates/wot/item_content_identity.html'"></ng-include><i class="icon ion-ios-arrow-right"></i><ion-option-button class="button-positive" ng-click="showTransferModal({pubkey: item.pubkey, uid: item.name ||item.uid})" translate="">COMMON.BTN_SEND_MONEY_SHORT</ion-option-button></ion-item></ng-repeat></ion-list><div ng-if="::allowMultiple" class="list {{::motion.ionListClass}}"><ion-checkbox ng-repeat="item in search.results track by item.id" ng-model="item.checked" class="item item-border-large item-avatar ink" ng-click="toggleCheck($index, $event)"><ng-include src="'templates/wot/item_content_identity.html'"></ng-include></ion-checkbox></div><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="20%"></ion-infinite-scroll></ng-if></div> \ No newline at end of file +<div class="lookupForm"><div class="item no-padding"><div class="double-padding-x padding-top-xs item-text-wrap" ng-if="::allowMultiple" style="height: 36px"><div class="gray padding-top" ng-if="!selection.length && parameters.help">{{::parameters.help|translate}}</div><div ng-repeat="identity in selection track by identity.id" class="button button-small button-text button-stable button-icon-event ink" ng-class="{'button-text-positive': identity.selected}"><span ng-bind-html="identity.name||identity.uid||(identity.pubkey|formatPubkey)"></span> <i class="icon ion-close" ng-click="removeSelection(identity, $event)"> </i></div></div><div class="item-input"><i class="icon ion-search placeholder-icon"></i> <input type="text" class="visible-xs visible-sm" placeholder="{{'WOT.SEARCH_HELP'|translate}}" ng-model="search.text" ng-model-options="{ debounce: 650 }" ng-change="doSearch()" on-return="doSearchText()" select-on-click=""><div class="helptip-anchor-center"><a id="helptip-wot-search-text"></a></div></div></div><div class="padding-top padding-xs padding-sm" style="display: block; height: 60px" ng-class="::{'hidden-xs hidden-sm': !showResultLabel}"><div class="pull-left" ng-if="!search.loading && showResultLabel"><ng-if ng-if="search.type=='newcomers'"><h4 translate="">WOT.LOOKUP.NEWCOMERS</h4><small class="gray no-padding" ng-if="search.total">{{'WOT.LOOKUP.NEWCOMERS_COUNT'|translate:{count: search.total} }}</small></ng-if><ng-if ng-if="search.type=='pending'"><h4 translate="">WOT.LOOKUP.PENDING</h4><small class="gray no-padding" ng-if="search.total">{{'WOT.LOOKUP.PENDING_COUNT'|translate:{count: search.total} }}</small></ng-if><h4 ng-if="search.type=='text'"><span translate="">COMMON.RESULTS_LIST</span> <small class="gray" ng-if="search.total">({{search.total}})</small></h4></div></div><div class="text-center padding-top" ng-if="search.loading"><p class="gray" ng-if="::$root.currency.initPhase" translate="">WOT.SEARCH_INIT_PHASE_WARNING</p><ion-spinner icon="android"></ion-spinner></div><ng-if ng-if="!search.loading"><div class="assertive padding" ng-if="!search.results.length"><span ng-if="search.type=='text'" translate="">COMMON.SEARCH_NO_RESULT</span> <span ng-if="search.type=='pending'" translate="">WOT.LOOKUP.NO_PENDING</span> <span ng-if="search.type=='newcomers'" translate="">WOT.LOOKUP.NO_NEWCOMERS</span></div><ion-list ng-if="::!allowMultiple && $root.device.enable" class="{{::motion.ionListClass}}" can-swipe="true"><ng-repeat ng-repeat="item in search.results track by item.id"><div ng-if="::item.divider" class="item item-divider" id="helptip-wot-search-result-{{$index}}">{{::('WOT.SEARCH.DIVIDER_' + item.index)|upper|translate}}</div><ion-item ng-if="::!item.divider" id="helptip-wot-search-result-{{$index}}" class="item item-border-large item-avatar item-icon-right ink" ng-click="::select(item)"><ng-include src="item.templateUrl || 'templates/wot/item_content_identity.html'"></ng-include><i class="icon ion-ios-arrow-right"></i><ion-option-button class="button-positive" ng-click="showTransferModal({pubkey: item.pubkey, uid: item.name ||item.uid})" translate="">COMMON.BTN_SEND_MONEY_SHORT</ion-option-button></ion-item></ng-repeat></ion-list><div ng-if="::allowMultiple" class="list {{::motion.ionListClass}}"><ion-checkbox ng-repeat="item in search.results track by item.id" ng-model="item.checked" class="item item-border-large item-avatar ink" ng-click="toggleCheck($index, $event)"><ng-include src="'templates/wot/item_content_identity.html'"></ng-include></ion-checkbox></div><ion-infinite-scroll ng-if="search.hasMore" spinner="android" on-infinite="showMore()" distance="20%"></ion-infinite-scroll></ng-if></div> \ No newline at end of file diff --git a/assets/www/templates/wot/lookup_lg.html b/assets/www/templates/wot/lookup_lg.html index e74e991813d1bbf0acbe5501ed345922a3a8f9bd..0f14bcde8ab43f135380e5694d981b0ecb8d5ef5 100644 --- a/assets/www/templates/wot/lookup_lg.html +++ b/assets/www/templates/wot/lookup_lg.html @@ -1 +1 @@ -<ion-view><ion-nav-title>{{'MENU.WOT' | translate}}</ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-qr-scanner hidden-no-device" ng-if="$root.device.barcode.enable" ng-click="scanQrCode()"></button> <button class="button button-icon button-clear visible-xs visible-sm" ng-click="showActionsPopover($event)"><i class="icon ion-android-funnel"></i></button></ion-nav-buttons><ion-content class="padding no-padding-xs" scroll="true"><cs-extension-point name="top"></cs-extension-point><ng-include src="'templates/wot/lookup_form.html'"></ng-include></ion-content></ion-view> \ No newline at end of file +<ion-view><ion-nav-title>{{'MENU.WOT' | translate}}</ion-nav-title><ion-nav-buttons side="secondary"><button class="button button-icon button-clear icon ion-qr-scanner hidden-no-device" ng-if="$root.device.barcode.enable" ng-click="scanQrCode()"></button> <button class="button button-icon button-clear visible-xs visible-sm" ng-click="showActionsPopover($event)"><i class="icon ion-android-funnel"></i></button></ion-nav-buttons><ion-content class="padding no-padding-x no-padding-sm" scroll="true"><cs-extension-point name="top"></cs-extension-point><ng-include src="'templates/wot/lookup_form.html'"></ng-include></ion-content></ion-view> \ No newline at end of file diff --git a/assets/www/templates/wot/modal_lookup.html b/assets/www/templates/wot/modal_lookup.html index 581a88d8f4004a6cad85655e09516c5bf404a944..39aeb997b513e0f54894cacb33279a78df01d680 100644 --- a/assets/www/templates/wot/modal_lookup.html +++ b/assets/www/templates/wot/modal_lookup.html @@ -1 +1 @@ -<ion-modal-view id="wotLookup" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title hidden-xs">{{::parameters.title?parameters.title:'WOT.MODAL.TITLE'|translate}}</h1><button class="button button-clear icon-right visible-xs ink" ng-if="allowMultiple && selection.length" ng-click="closeModal(selection)">{{::parameters.okText||'COMMON.BTN_NEXT' | translate}} <i ng-if="::!parameters.okText||parameters.okIcon" class="icon {{::parameters.okIcon||'ion-ios-arrow-right'}}"></i></button></ion-header-bar><ion-content class="padding no-padding-xs" scroll="true"><div class="visible-xs visible-sm text-right stable-bg stable"><button class="button button-icon button-small-padding dark hidden-no-device ink" ng-if="$root.device.barcode.enable" ng-click="scanQrCode()"><i class="icon ion-qr-scanner"></i></button> <button class="button button-icon button-small-padding dark ink" ng-click="showActionsPopover($event)"><i class="icon ion-android-funnel"></i></button></div><ng-include src="'templates/wot/lookup_form.html'"></ng-include></ion-content></ion-modal-view> \ No newline at end of file +<ion-modal-view id="wotLookup" class="modal-full-height"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title hidden-xs">{{::parameters.title?parameters.title:'WOT.MODAL.TITLE'|translate}}</h1><button class="button button-clear icon-right visible-xs ink" ng-if="allowMultiple && selection.length" ng-click="closeModal(selection)">{{::parameters.okText||'COMMON.BTN_NEXT' | translate}} <i ng-if="::!parameters.okText||parameters.okIcon" class="icon {{::parameters.okIcon||'ion-ios-arrow-right'}}"></i></button></ion-header-bar><ion-content class="padding no-padding-xs no-padding-sm" scroll="true"><div class="visible-xs visible-sm text-right stable-bg stable"><button class="button button-icon button-small-padding dark hidden-no-device ink" ng-if="$root.device.barcode.enable" ng-click="scanQrCode()"><i class="icon ion-qr-scanner"></i></button> <button class="button button-icon button-small-padding dark ink" ng-click="showActionsPopover($event)"><i class="icon ion-android-funnel"></i></button></div><ng-include src="'templates/wot/lookup_form.html'"></ng-include></ion-content></ion-modal-view> \ No newline at end of file diff --git a/assets/www/templates/wot/modal_select_pubkey_identity.html b/assets/www/templates/wot/modal_select_pubkey_identity.html index 95473b1950369358909a027369cb392bcc095a1f..0d0e344a32366fb2c0d543cedbf2f4d0193220b9 100644 --- a/assets/www/templates/wot/modal_select_pubkey_identity.html +++ b/assets/www/templates/wot/modal_select_pubkey_identity.html @@ -1 +1 @@ -<ion-modal-view id="transfer" class="modal-full-height modal-transfer"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>ACCOUNT.SELECT_IDENTITY_MODAL.TITLE</h1></ion-header-bar><ion-content scroll="true"><div class="padding"><p trust-as-html="'ACCOUNT.SELECT_IDENTITY_MODAL.HELP'|translate:{pubkey: pubkey}"></p></div><ion-list><ion-item class="item-avatar item-icon-right" ng-repeat="item in identities" ng-click="closeModal(item)"><i class="item-image icon ion-person"></i><h2>{{item.uid}}</h2><h4 class="gray"><b class="ion-key"></b> {{::item.pubkey | formatPubkey}} <span ng-if="::!item.revoked && !item.pendingRevocation && !item.isMember" class="assertive" translate>WOT.NOT_MEMBER_PARENTHESIS</span> <span ng-if="::item.revoked || item.pendingRevocation" class="assertive bold" translate>WOT.IDENTITY_REVOKED_PARENTHESIS</span></h4><ng-if ng-if="::!item.revoked && !item.pendingRevocation && (item.certificationCount || item.pendingCertificationCount)"><cs-badge-certification requirements="item" parameters="$root.currency.parameters"></cs-badge-certification><div class="gray badge badge-secondary"><span translate>ACCOUNT.CERTIFICATION_COUNT</span></div></ng-if><i class="icon ion-ios-arrow-right"></i></ion-item></ion-list></ion-content></ion-modal-view> \ No newline at end of file +<ion-modal-view id="transfer" class="modal-full-height modal-transfer"><ion-header-bar class="bar-positive"><button class="button button-clear" ng-click="closeModal()" translate>COMMON.BTN_CANCEL</button><h1 class="title" translate>ACCOUNT.SELECT_IDENTITY_MODAL.TITLE</h1></ion-header-bar><ion-content scroll="true"><div class="padding"><p trust-as-html="'ACCOUNT.SELECT_IDENTITY_MODAL.HELP'|translate:{pubkey: pubkey}"></p></div><ion-list><ion-item class="item-avatar item-icon-right" ng-repeat="item in identities" ng-click="closeModal(item)"><i class="item-image icon ion-person"></i><h2>{{item.uid}}</h2><h4 class="gray"><b class="ion-key"></b> {{::item.pubkey | formatPubkey}} <span ng-if="::!item.revoked && !item.pendingRevocation && !item.isMember" class="assertive" translate>WOT.NOT_MEMBER_PARENTHESIS</span> <span ng-if="::item.revoked || item.pendingRevocation" class="assertive bold" translate>WOT.IDENTITY_REVOKED_PARENTHESIS</span> <span ng-if="::item.meta.invalid" class="assertive" translate>ERROR.WOT_PENDING_INVALID_BLOCK_HASH</span></h4><h4 class="dark" ng-if="::item.meta.time"><i class="ion-calendar"></i> <span translate>WOT.REGISTERED_SINCE</span> {{::item.meta.time|medianDate}}</h4><ng-if ng-if="::!item.revoked && !item.pendingRevocation && (item.certificationCount || item.pendingCertificationCount)"><cs-badge-certification requirements="item" parameters="$root.currency.parameters"></cs-badge-certification><div class="gray badge badge-secondary hidden-xs"><span translate>ACCOUNT.CERTIFICATION_COUNT</span></div></ng-if><i class="icon ion-ios-arrow-right"></i></ion-item></ion-list></ion-content></ion-modal-view> \ No newline at end of file diff --git a/assets/www/templates/wot/view_identity.html b/assets/www/templates/wot/view_identity.html index cd0800a83f3bb51c7e9376356340fc4bb7acc577..71aa09cde0e2b9576a6219c3b758e3bd25cd4306 100644 --- a/assets/www/templates/wot/view_identity.html +++ b/assets/www/templates/wot/view_identity.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons" class="view-identity"><ion-nav-title></ion-nav-title><ion-content scroll="true" class="refresher-top-bg" ng-class="{'member': !loading && formData.isMember}"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="hero"><div class="content" ng-if="!loading"><i class="avatar" ng-if="::!formData.avatar" ng-class="{'avatar-wallet': !formData.isMember, 'avatar-member': formData.isMember}"></i> <i class="avatar" ng-if="::formData.avatar" style="background-image: url({{::formData.avatar.src}})"></i><ng-if ng-if="::formData.name"><h3 class="light">{{::formData.name}}</h3></ng-if><ng-if ng-if="::!formData.name"><h3 class="light" ng-if="::formData.uid">{{::formData.uid}}</h3><h3 class="light" ng-if="::!formData.uid"><i class="ion-key"></i> {{::formData.pubkey | formatPubkey}}</h3></ng-if><h4 class="assertive"><ng-if ng-if="::(formData.name || formData.uid) && !formData.isMember && revoked" translate="">WOT.IDENTITY_REVOKED_PARENTHESIS</ng-if><ng-if ng-if="::(formData.name || formData.uid) && formData.isMember && revoked" translate="">WOT.MEMBER_PENDING_REVOCATION_PARENTHESIS</ng-if></h4></div><h4 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><a id="wot-share-anchor-{{::formData.pubkey}}"></a><div class="row no-padding"><div class="visible-xs visible-sm"><button id="fab-certify-{{:rebind:formData.uid}}" style="top: 170px" class="button button-fab button-fab-top-left button-fab-hero button-calm spin" ng-if=":rebind:(canCertify && !alreadyCertified)" ng-click="certify()"><i class="icon ion-ribbon-b"></i></button></div><div class="col list" ng-class="::motion.ionListClass" bind-notifier="{ rebind:loading}"><span class="item item-divider" translate="">WOT.GENERAL_DIVIDER</span><ion-item class="item-icon-left item-text-wrap ink" copy-on-click="{{:rebind:formData.pubkey}}"><i class="icon ion-key"></i> <span translate="">COMMON.PUBKEY</span><h4 id="pubkey" class="dark text-left">{{:rebind:formData.pubkey}}</h4></ion-item><div class="item item-icon-left item-text-wrap" ng-if=":rebind:!formData.hasSelf"><i class="icon ion-ios-help-outline positive"></i> <span translate="">WOT.NOT_MEMBER_ACCOUNT</span><h4 class="gray" translate="">WOT.NOT_MEMBER_ACCOUNT_HELP</h4></div><ion-item class="item-icon-left" ng-if=":rebind:formData.sigDate||formData.uid"><i class="icon ion-calendar"></i> <span translate="">COMMON.UID</span><h5 class="dark" ng-if=":rebind:formData.sigDate"><span translate="">WOT.REGISTERED_SINCE</span> {{:rebind:formData.sigDate | formatDate}}</h5><span class="badge badge-stable">{{:rebind:formData.uid}}</span></ion-item><a id="helptip-wot-view-certifications" class="item item-icon-left item-text-wrap item-icon-right ink" ng-if=":rebind:formData.hasSelf" ng-click="showCertifications()"><i class="icon ion-ribbon-b"></i> <b ng-if=":rebind:formData.requirements.isSentry" class="ion-star icon-secondary" style="color: yellow; font-size: 16px; left: 25px; top: -7px"></b> <span translate="">ACCOUNT.CERTIFICATION_COUNT</span><cs-badge-certification cs-id="helptip-wot-view-certifications-count" requirements="formData.requirements" parameters="{sigQty: formData.sigQty}"></cs-badge-certification><i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-text-wrap item-icon-right ink visible-xs visible-sm" ng-if=":rebind:formData.hasSelf && formData.isMember" ng-click="showGivenCertifications()"><i class="icon ion-ribbon-a"></i> <span translate="">WOT.GIVEN_CERTIFICATIONS.SENT</span><cs-badge-given-certification identity="formData" parameters="{sigStock: formData.sigStock}"></cs-badge-given-certification><i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-icon-right ink" ng-if="!loading" ui-sref="app.wot_identity_tx_uid({uid:formData.uid,pubkey:formData.pubkey})"><i class="icon ion-card"></i> <span translate="">WOT.ACCOUNT_OPERATIONS</span> <i class="gray icon ion-ios-arrow-right"></i></a><div class="item item-text-wrap item-icon-left item-wallet-event assertive" ng-repeat="event in :rebind:formData.events | filter: {type: 'error'}"><i class="icon ion-alert-circled"></i> <span trust-as-html="event.message | translate:event.messageParams"></span></div><cs-extension-point name="general"></cs-extension-point><cs-extension-point name="after-general"></cs-extension-point></div></div></ion-content><div class="visible-xs visible-sm" ng-hide="loading"><button id="fab-transfer" class="button button-fab button-fab-bottom-right button-assertive drop" ng-click="showTransferModal({pubkey:formData.pubkey, uid: formData.uid})"><i class="icon ion-android-send"></i></button></div></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons" class="view-identity"><ion-nav-title></ion-nav-title><ion-content scroll="true" class="refresher-light" ng-class="{'member refresher-positive-900-bg': !loading && formData.isMember, 'refresher-dark-100-bg': loading || !formData.isMember}"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="hero" ng-class="{'hero-qrcode-active': toggleQRCode}"><div class="content" ng-if="!loading"><i class="avatar" ng-if=":rebind:!formData.avatar" ng-class="{'avatar-wallet': !formData.isMember, 'avatar-member': formData.isMember}"></i> <i class="avatar" ng-if=":rebind:formData.avatar" style="background-image: url({{::formData.avatar.src}})"></i><ng-if ng-if=":rebind:formData.name"><h3 class="light">{{::formData.name}}</h3></ng-if><ng-if ng-if=":rebind:!formData.name"><h3 class="light" ng-if=":rebind:formData.uid">{{:rebind:formData.uid}}</h3><h3 class="light" ng-if=":rebind:!formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</h3></ng-if><h4 class="assertive"><ng-if ng-if=":rebind:(formData.name || formData.uid) && !formData.isMember && revoked" translate="">WOT.IDENTITY_REVOKED_PARENTHESIS</ng-if><ng-if ng-if=":rebind:(formData.name || formData.uid) && formData.isMember && revoked" translate="">WOT.MEMBER_PENDING_REVOCATION_PARENTHESIS</ng-if></h4></div><h4 class="content light" ng-if="loading"><ion-spinner icon="android"></ion-spinner></h4></div><div ng-attr-id="{{ qrcodeId }}" class="qrcode spin" ng-class="{'active': toggleQRCode}" ng-click="toggleQRCode = !toggleQRCode"></div><a id="wot-share-anchor-{{::formData.pubkey}}"></a><div class="visible-xs visible-sm"><button id="fab-certify-{{:rebind:formData.uid}}" class="button button-fab button-fab-top-left button-fab-hero button-calm spin" ng-if=":rebind:(canCertify && !alreadyCertified)" ng-click="certify()"><i class="icon ion-ribbon-b"></i></button><cs-extension-point name="buttons-top-fab"></cs-extension-point></div><div class="row no-padding"><div class="col list {{::motion.ionListClass}}" bind-notifier="{ rebind:loading}"><span class="item item-divider" translate="">WOT.GENERAL_DIVIDER</span><ion-item class="item-icon-left item-text-wrap ink" copy-on-click="{{:rebind:formData.pubkey}}"><i class="icon ion-key"></i> <span translate="">COMMON.PUBKEY</span><h4 id="pubkey" class="dark text-left">{{:rebind:formData.pubkey}}</h4></ion-item><div class="item item-icon-left item-text-wrap" ng-if=":rebind:!formData.hasSelf"><i class="icon ion-ios-help-outline positive"></i> <span translate="">WOT.NOT_MEMBER_ACCOUNT</span><h4 class="gray" translate="">WOT.NOT_MEMBER_ACCOUNT_HELP</h4></div><ion-item class="item-icon-left" ng-if=":rebind:formData.sigDate||formData.uid"><i class="icon ion-calendar"></i> <span translate="">COMMON.UID</span><h5 class="dark" ng-if=":rebind:formData.sigDate "><span translate="">WOT.REGISTERED_SINCE</span> {{:rebind:formData.sigDate|medianDate}}</h5><span class="badge badge-energized">{{:rebind:formData.uid}}</span></ion-item><a id="helptip-wot-view-certifications" class="item item-icon-left item-text-wrap item-icon-right ink" ng-if=":rebind:formData.hasSelf" ng-click="showCertifications()"><i class="icon ion-ribbon-b"></i> <b ng-if=":rebind:formData.requirements.isSentry" class="ion-star icon-secondary" style="color: yellow; font-size: 16px; left: 25px; top: -7px"></b> <span translate="">ACCOUNT.CERTIFICATION_COUNT</span><cs-badge-certification cs-id="helptip-wot-view-certifications-count" requirements="formData.requirements" parameters="{sigQty: formData.sigQty}"></cs-badge-certification><i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-text-wrap item-icon-right ink visible-xs visible-sm" ng-if=":rebind:formData.hasSelf && formData.isMember" ng-click="showGivenCertifications()"><i class="icon ion-ribbon-a"></i> <span translate="">WOT.GIVEN_CERTIFICATIONS.SENT</span><cs-badge-given-certification identity="formData" parameters="$root.currency.parameters"></cs-badge-given-certification><i class="gray icon ion-ios-arrow-right"></i> </a><a class="item item-icon-left item-icon-right ink" ng-if="!loading" ui-sref="app.wot_identity_tx_uid({uid:formData.uid,pubkey:formData.pubkey})"><i class="icon ion-card"></i> <span translate="">WOT.ACCOUNT_OPERATIONS</span> <i class="gray icon ion-ios-arrow-right"></i></a><div class="item item-text-wrap item-icon-left item-wallet-event" ng-class="{'assertive': event.type=='error'}" ng-repeat="event in :rebind:formData.events"><i class="icon" ng-class="{'ion-information-circled royal': event.type=='info','ion-alert-circled': event.type=='warn'||event.type=='error','assertive': event.type=='error','ion-clock': event.type=='pending'}"></i> <span trust-as-html="event.message | translate:event.messageParams"></span></div><cs-extension-point name="general"></cs-extension-point><cs-extension-point name="after-general"></cs-extension-point></div></div></ion-content><div class="visible-xs visible-sm" ng-hide="loading"><button id="fab-transfer" class="button button-fab button-fab-bottom-right button-assertive drop" ng-click="showTransferModal({pubkey:formData.pubkey, uid: formData.uid})"><i class="icon ion-android-send"></i></button></div></ion-view> \ No newline at end of file diff --git a/assets/www/templates/wot/view_identity_tx.html b/assets/www/templates/wot/view_identity_tx.html index adb9153cd9c3b4bb3389d0c16b1b783e434de1b1..62790bb288405e901c43339ef8c428d4977c2195 100644 --- a/assets/www/templates/wot/view_identity_tx.html +++ b/assets/www/templates/wot/view_identity_tx.html @@ -1 +1 @@ -<ion-view left-buttons="leftButtons"><ion-nav-title><span class="visible-xs visible-sm">{{::formData.name||formData.uid}}</span></ion-nav-title><ion-content scroll="true"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="list {{motion.ionListClass}}" ng-if="!loading"><div class="row"><div class="col"><div class="item item-tx item-divider">{{'ACCOUNT.BALANCE_ACCOUNT'|translate}}<div class="badge item-note badge-balanced" ng-bind-html=":balance:formData.balance|formatAmount:{currency: $root.currency.name}"></div><div class="badge badge-secondary" ng-if="$root.settings.expertMode">(<span ng-bind-html=":balance:formData.balance| formatAmount: {useRelative: !$root.settings.useRelative, currency: $root.currency.name} "></span>)</div></div><span class="item item-divider" ng-if="!loading">{{:locale:'ACCOUNT.LAST_TX'|translate}} <a id="helptip-wallet-tx" style="position: relative; bottom: 0; right: 0px"> </a></span><div ng-repeat="tx in formData.tx.history" class="item item-tx item-icon-left" ng-include="::!tx.isUD ? 'templates/wallet/item_tx.html' : 'templates/wallet/item_ud.html'"></div><div class="item item-text-wrap text-center" ng-if="formData.tx.fromTime > 0"><p><a ng-click="showMoreTx()">{{:locale:'ACCOUNT.SHOW_MORE_TX'|translate}}</a> <span class="gray" translate="ACCOUNT.TX_FROM_DATE" translate-values="{fromTime: tx.fromTime}"></span> <span class="gray">|</span> <a ng-click="showMoreTx(-1)" translate="">ACCOUNT.SHOW_ALL_TX</a></p></div></div></div></div></ion-content></ion-view> \ No newline at end of file +<ion-view left-buttons="leftButtons"><ion-nav-title><span class="visible-xs visible-sm" ng-if="!loading"><span ng-if="formData.name || formData.uid">{{formData.name || formData.uid}} </span><span ng-if="!formData.name && !formData.uid"><i class="ion-key"></i> {{formData.pubkey|formatPubkey}}</span></span></ion-nav-title><ion-content scroll="true"><ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" on-refresh="doUpdate(true)"></ion-refresher><div class="center padding" ng-if="loading"><ion-spinner icon="android"></ion-spinner></div><div class="list {{motion.ionListClass}}" ng-if="!loading"><div class="row"><div class="col"><div class="item item-tx item-divider">{{:locale:'ACCOUNT.BALANCE_ACCOUNT'|translate}}<div class="badge item-note" ng-class=":balance:{'badge-assertive': formData.balance <= 0, 'badge-balanced': formData.balance > 0 }" ng-bind-html=":balance:formData.balance|formatAmount:{currency: $root.currency.name}"></div><div class="badge badge-secondary" ng-if="$root.settings.expertMode">(<span ng-bind-html=":balance:formData.balance| formatAmount: {useRelative: !$root.settings.useRelative, currency: $root.currency.name} "></span>)</div></div><div class="item item-icon-left" ng-if="formData.tx.errors.length"><i class="icon ion-alert-circled"></i> {{:locale:'ACCOUNT.ERROR_TX'|translate}}<div class="badge badge-assertive">{{formData.tx.errors.length}}</div></div><ng-if ng-if="formData.tx.pendings.length"><span class="item item-pending item-divider"><i class="ion-clock"></i> {{:locale:'ACCOUNT.PENDING_TX'|translate}}</span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.pendings" ng-init="pending=true;" ng-include="::'templates/wallet/item_tx.html'"></div></ng-if><ng-if ng-if="formData.tx.validating.length"><span class="item item-pending item-divider">{{:locale:'ACCOUNT.VALIDATING_TX'|translate}}</span><div class="item item-pending item-tx item-icon-left" ng-repeat="tx in formData.tx.validating" ng-init="validating=true;" ng-include="::'templates/wallet/item_tx.html'"></div></ng-if><span class="item item-divider" ng-if="!loading">{{:locale:'ACCOUNT.LAST_TX'|translate}} <a id="helptip-wallet-tx" style="position: relative; bottom: 0; right: 0px"> </a></span><div ng-repeat="tx in formData.tx.history" class="item item-tx item-icon-left" ng-include="::!tx.isUD ? 'templates/wallet/item_tx.html' : 'templates/wallet/item_ud.html'"></div><div class="item item-text-wrap text-center" ng-if="formData.tx.fromTime > 0"><p><a ng-click="showMoreTx()">{{:locale:'ACCOUNT.SHOW_MORE_TX'|translate}}</a> <span class="gray" translate="ACCOUNT.TX_FROM_DATE" translate-values="{fromTime: formData.tx.fromTime}"></span> <span class="gray">|</span> <a ng-click="showMoreTx(-1)" translate="">ACCOUNT.SHOW_ALL_TX</a></p></div></div></div></div></ion-content></ion-view> \ No newline at end of file diff --git a/build.gradle b/build.gradle index 328908361dfeeab8eed44a13969b0153490b015f..f8c95a8d1af1eeba57f49f7af886693c3493400d 100644 --- a/build.gradle +++ b/build.gradle @@ -256,6 +256,7 @@ dependencies { // SUB-PROJECT DEPENDENCIES START implementation(project(path: "CordovaLib")) compile "com.android.support:support-v4:24.1.1+" + compile "com.android.support:support-annotations:27.+" // SUB-PROJECT DEPENDENCIES END } diff --git a/cordova/node_modules/.bin/nopt b/cordova/node_modules/.bin/nopt new file mode 120000 index 0000000000000000000000000000000000000000..6b6566ea7febba5ef6355fb774abeeba134ca1cb --- /dev/null +++ b/cordova/node_modules/.bin/nopt @@ -0,0 +1 @@ +../nopt/bin/nopt.js \ No newline at end of file diff --git a/cordova/node_modules/.bin/semver b/cordova/node_modules/.bin/semver new file mode 120000 index 0000000000000000000000000000000000000000..317eb293d8e125968256d4819f26caf2343475c4 --- /dev/null +++ b/cordova/node_modules/.bin/semver @@ -0,0 +1 @@ +../semver/bin/semver \ No newline at end of file diff --git a/cordova/node_modules/.bin/shjs b/cordova/node_modules/.bin/shjs new file mode 120000 index 0000000000000000000000000000000000000000..a0449975bf894c44ebdb579fcfd7a4d742050a8a --- /dev/null +++ b/cordova/node_modules/.bin/shjs @@ -0,0 +1 @@ +../shelljs/bin/shjs \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..9ab0a835890a5db3e8ae4f8159e0cee6a2f64f45 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 47bfcac8e3979b735d11f1a3d8a480896b89f279..ddb3e1024ce810a0ed5e3707cbcaf77801c61f17 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1 @@ -#Wed May 30 14:27:22 CEST 2018 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-4.10.3-all.zip diff --git a/libs/barcodescanner-release-2.1.5.aar b/libs/barcodescanner-release-2.1.5.aar new file mode 100644 index 0000000000000000000000000000000000000000..6312ccab948387f970089d0aeabf5afc1b834d9b Binary files /dev/null and b/libs/barcodescanner-release-2.1.5.aar differ diff --git a/libs/libsodium-jni-release.aar b/libs/libsodium-jni-release.aar index 0734b4b3a14c1a0aefb2038883eba776fc07fa3b..a88fe7e2303dfc4648ee16dd53c0a9f43b747dac 100644 Binary files a/libs/libsodium-jni-release.aar and b/libs/libsodium-jni-release.aar differ diff --git a/platform_www/cordova_plugins.js b/platform_www/cordova_plugins.js index 119dd559adedd09804eb2a912245542ec963e574..2f67d65f5bcdf6c704b89d61fb1c6f99f6f08e98 100644 --- a/platform_www/cordova_plugins.js +++ b/platform_www/cordova_plugins.js @@ -157,6 +157,22 @@ module.exports = [ "clobbers": [ "cordova.plugins.barcodeScanner" ] + }, + { + "id": "cordova-plugin-ionic-keyboard.keyboard", + "file": "plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js", + "pluginId": "cordova-plugin-ionic-keyboard", + "clobbers": [ + "window.Keyboard" + ] + }, + { + "id": "cordova-plugin-ionic-webview.IonicWebView", + "file": "plugins/cordova-plugin-ionic-webview/src/www/util.js", + "pluginId": "cordova-plugin-ionic-webview", + "clobbers": [ + "Ionic.WebView" + ] } ]; module.exports.metadata = @@ -177,7 +193,9 @@ module.exports.metadata = "cordova-plugin-whitelist": "1.3.3", "cordova-plugin-x-toast": "2.6.0", "ionic-plugin-keyboard": "2.2.1", - "phonegap-plugin-barcodescanner": "7.0.0" + "phonegap-plugin-barcodescanner": "7.0.0", + "cordova-plugin-ionic-keyboard": "2.2.0", + "cordova-plugin-ionic-webview": "4.1.3" }; // BOTTOM OF METADATA }); \ No newline at end of file diff --git a/platform_www/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js b/platform_www/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js new file mode 100644 index 0000000000000000000000000000000000000000..19062bf15874ad66e03019743e8d3678738d8d39 --- /dev/null +++ b/platform_www/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js @@ -0,0 +1,87 @@ +cordova.define("cordova-plugin-ionic-keyboard.keyboard", function(require, exports, module) { +var argscheck = require('cordova/argscheck'), + utils = require('cordova/utils'), + exec = require('cordova/exec'), + channel = require('cordova/channel'); + +var Keyboard = function () {}; + +Keyboard.fireOnShow = function (height) { + Keyboard.isVisible = true; + cordova.fireWindowEvent('keyboardDidShow', { + 'keyboardHeight': height + }); + + // To support the keyboardAttach directive listening events + // inside Ionic's main bundle + cordova.fireWindowEvent('native.keyboardshow', { + 'keyboardHeight': height + }); +}; + +Keyboard.fireOnHide = function () { + Keyboard.isVisible = false; + cordova.fireWindowEvent('keyboardDidHide'); + + // To support the keyboardAttach directive listening events + // inside Ionic's main bundle + cordova.fireWindowEvent('native.keyboardhide'); +}; + +Keyboard.fireOnHiding = function () { + cordova.fireWindowEvent('keyboardWillHide'); +}; + +Keyboard.fireOnShowing = function (height) { + cordova.fireWindowEvent('keyboardWillShow', { + 'keyboardHeight': height + }); +}; + +Keyboard.hideFormAccessoryBar = Keyboard.hideKeyboardAccessoryBar = function (hide) { + console.warn("Keyboard.hideKeyboardAccessoryBar() not supported in Android"); +}; + +Keyboard.hide = function () { + exec(null, null, "CDVIonicKeyboard", "hide", []); +}; + +Keyboard.show = function () { + exec(null, null, "CDVIonicKeyboard", "show", []); +}; + +Keyboard.disableScroll = function (disable) { + console.warn("Keyboard.disableScroll() not supported in Android"); +}; + +Keyboard.setResizeMode = function (mode) { + console.warn("Keyboard.setResizeMode() not supported in Android"); +} + +Keyboard.setKeyboardStyle = function(style) { + console.warn("Keyboard.setKeyboardStyle() not supported in Android"); +}; + +channel.onCordovaReady.subscribe(function () { + exec(success, null, 'CDVIonicKeyboard', 'init', []); + + function success(msg) { + var action = msg.charAt(0); + if (action === 'S') { + var keyboardHeight = parseInt(msg.substr(1)); + Keyboard.fireOnShowing(keyboardHeight); + Keyboard.fireOnShow(keyboardHeight); + + } else if (action === 'H') { + Keyboard.fireOnHiding(); + Keyboard.fireOnHide(); + } + } +}); + + +Keyboard.isVisible = false; + +module.exports = Keyboard; + +}); diff --git a/platform_www/plugins/cordova-plugin-ionic-webview/src/www/util.js b/platform_www/plugins/cordova-plugin-ionic-webview/src/www/util.js new file mode 100644 index 0000000000000000000000000000000000000000..1e2aa1c4e5de8d1f4db964133678035609f6f69a --- /dev/null +++ b/platform_www/plugins/cordova-plugin-ionic-webview/src/www/util.js @@ -0,0 +1,32 @@ +cordova.define("cordova-plugin-ionic-webview.IonicWebView", function(require, exports, module) { +var exec = require('cordova/exec'); + +var WebView = { + convertFileSrc: function(url) { + if (!url) { + return url; + } + if (url.startsWith('/')) { + return window.WEBVIEW_SERVER_URL + '/_app_file_' + url; + } + if (url.startsWith('file://')) { + return window.WEBVIEW_SERVER_URL + url.replace('file://', '/_app_file_'); + } + if (url.startsWith('content://')) { + return window.WEBVIEW_SERVER_URL + url.replace('content:/', '/_app_content_'); + } + return url; + }, + setServerBasePath: function(path) { + exec(null, null, 'IonicWebView', 'setServerBasePath', [path]); + }, + getServerBasePath: function(callback) { + exec(callback, null, 'IonicWebView', 'getServerBasePath', []); + }, + persistServerBasePath: function() { + exec(null, null, 'IonicWebView', 'persistServerBasePath', []); + } +} + +module.exports = WebView; +}); diff --git a/project.properties b/project.properties index 5de2966e9907ffc9d26fbef9b24dbcfed7780728..1ba6ee07cd1fa4faa35cf7e9f77fefb14b998ebb 100644 --- a/project.properties +++ b/project.properties @@ -14,4 +14,5 @@ target=android-26 android.library.reference.1=CordovaLib cordova.system.library.1=com.android.support:support-v4:24.1.1+ cordova.gradle.include.1=cordova-plugin-minisodium/cesium-jni.gradle -cordova.gradle.include.2=phonegap-plugin-barcodescanner/cesium-barcodescanner.gradle \ No newline at end of file +cordova.gradle.include.2=phonegap-plugin-barcodescanner/cesium-barcodescanner.gradle +cordova.system.library.2=com.android.support:support-annotations:27.+ \ No newline at end of file diff --git a/res/xml/camera_provider_paths.xml b/res/xml/camera_provider_paths.xml new file mode 100644 index 0000000000000000000000000000000000000000..2db87bdbd3ec6d5ce1a4d3d548abaaf41d1e1cdc --- /dev/null +++ b/res/xml/camera_provider_paths.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> + +<paths xmlns:android="http://schemas.android.com/apk/res/android"> + <external-path name="external_files" path="."/> +</paths> \ No newline at end of file diff --git a/res/xml/config.xml b/res/xml/config.xml index 94c8a98a69118cf6a9046491122cb2ef2e47bc19..b560eefeb4b01547d2f276fb9bc13bd713ea843d 100644 --- a/res/xml/config.xml +++ b/res/xml/config.xml @@ -1,5 +1,5 @@ <?xml version='1.0' encoding='utf-8'?> -<widget android-versionCode="100060" id="fr.duniter.cesium" version="1.0.6" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> +<widget android-versionCode="104015" id="fr.duniter.cesium" ios-CFBundleIdentifier="org.duniter.cesium" version="1.4.15" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> <feature name="Clipboard"> <param name="android-package" value="com.verso.cordova.clipboard.Clipboard" /> </feature> @@ -50,6 +50,15 @@ <feature name="BarcodeScanner"> <param name="android-package" value="com.phonegap.plugins.barcodescanner.BarcodeScanner" /> </feature> + <feature name="CDVIonicKeyboard"> + <param name="android-package" onload="true" value="io.ionic.keyboard.CDVIonicKeyboard" /> + </feature> + <allow-navigation href="http://localhost/*" /> + <allow-navigation href="https://localhost/*" /> + <allow-navigation href="ionic://*" /> + <feature name="IonicWebView"> + <param name="android-package" value="com.ionicframework.cordova.webview.IonicWebView" /> + </feature> <name>Cesium</name> <description> An simple App for Duniter wallet @@ -89,13 +98,19 @@ <splash density="port-xxhdpi" src="resources/android/splash/drawable-port-xxhdpi-screen.png" /> <splash density="port-xxxhdpi" src="resources/android/splash/drawable-port-xxxhdpi-screen.png" /> <preference name="loglevel" value="DEBUG" /> + <preference name="webView" value="com.ionicframework.cordova.webview.IonicWebViewEngine" /> <preference name="webviewbounce" value="false" /> <preference name="UIWebViewBounce" value="false" /> <preference name="DisallowOverscroll" value="true" /> <preference name="SplashScreen" value="screen" /> <preference name="SplashScreenDelay" value="4000" /> + <preference name="KeyboardDisplayRequiresUserAction" value="false" /> + <preference name="KeyboardResizeMode" value="ionic" /> <preference name="xwalkVersion" value="19" /> <preference name="xwalkMultipleApk" value="false" /> - <preference name="android-minSdkVersion" value="16" /> - <preference name="android-targetSdkVersion" value="25" /> + <preference name="android-minSdkVersion" value="20" /> + <preference name="android-targetSdkVersion" value="28" /> + <preference name="StatusBarOverlaysWebView" value="false" /> + <preference name="StatusBarBackgroundColor" value="#000" /> + <preference name="StatusBarStyle" value="lightcontent" /> </widget> diff --git a/src/com/ionicframework/cordova/webview/AndroidProtocolHandler.java b/src/com/ionicframework/cordova/webview/AndroidProtocolHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..6202a5b919c0f3d816478bfbf23aef3490ffba22 --- /dev/null +++ b/src/com/ionicframework/cordova/webview/AndroidProtocolHandler.java @@ -0,0 +1,107 @@ +package com.ionicframework.cordova.webview; + +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import android.content.Context; +import android.content.res.AssetManager; +import android.net.Uri; +import android.util.Log; +import android.util.TypedValue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + + +public class AndroidProtocolHandler { + private static final String TAG = "AndroidProtocolHandler"; + + private Context context; + + public AndroidProtocolHandler(Context context) { + this.context = context; + } + + public InputStream openAsset(String path) throws IOException { + return context.getAssets().open(path, AssetManager.ACCESS_STREAMING); + } + + public InputStream openResource(Uri uri) { + assert uri.getPath() != null; + // The path must be of the form ".../asset_type/asset_name.ext". + List<String> pathSegments = uri.getPathSegments(); + String assetType = pathSegments.get(pathSegments.size() - 2); + String assetName = pathSegments.get(pathSegments.size() - 1); + + // Drop the file extension. + assetName = assetName.split("\\.")[0]; + try { + // Use the application context for resolving the resource package name so that we do + // not use the browser's own resources. Note that if 'context' here belongs to the + // test suite, it does not have a separate application context. In that case we use + // the original context object directly. + if (context.getApplicationContext() != null) { + context = context.getApplicationContext(); + } + int fieldId = getFieldId(context, assetType, assetName); + int valueType = getValueType(context, fieldId); + if (valueType == TypedValue.TYPE_STRING) { + return context.getResources().openRawResource(fieldId); + } else { + Log.e(TAG, "Asset not of type string: " + uri); + return null; + } + } catch (ClassNotFoundException e) { + Log.e(TAG, "Unable to open resource URL: " + uri, e); + return null; + } catch (NoSuchFieldException e) { + Log.e(TAG, "Unable to open resource URL: " + uri, e); + return null; + } catch (IllegalAccessException e) { + Log.e(TAG, "Unable to open resource URL: " + uri, e); + return null; + } + } + + public InputStream openFile(String filePath) throws IOException { + String realPath = filePath.replace(WebViewLocalServer.fileStart, ""); + File localFile = new File(realPath); + return new FileInputStream(localFile); + } + + public InputStream openContentUrl(Uri uri) throws IOException { + Integer port = uri.getPort(); + String realPath; + if (port == -1) { + realPath = uri.toString().replace(uri.getScheme() + "://" + uri.getHost() + WebViewLocalServer.contentStart, "content:/"); + } else { + realPath = uri.toString().replace(uri.getScheme() + "://" + uri.getHost() + ":" + port + WebViewLocalServer.contentStart, "content:/"); + } + InputStream stream = null; + try { + stream = context.getContentResolver().openInputStream(Uri.parse(realPath)); + } catch (SecurityException e) { + Log.e(TAG, "Unable to open content URL: " + uri, e); + } + return stream; + } + + private static int getFieldId(Context context, String assetType, String assetName) + throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { + Class<?> d = context.getClassLoader() + .loadClass(context.getPackageName() + ".R$" + assetType); + java.lang.reflect.Field field = d.getField(assetName); + int id = field.getInt(null); + return id; + } + + private static int getValueType(Context context, int fieldId) { + TypedValue value = new TypedValue(); + context.getResources().getValue(fieldId, value, true); + return value.type; + } +} diff --git a/src/com/ionicframework/cordova/webview/IonicWebView.java b/src/com/ionicframework/cordova/webview/IonicWebView.java new file mode 100644 index 0000000000000000000000000000000000000000..ff771371e7161e081b95948bcfa730e13a09dbb5 --- /dev/null +++ b/src/com/ionicframework/cordova/webview/IonicWebView.java @@ -0,0 +1,41 @@ +package com.ionicframework.cordova.webview; + +import android.app.Activity; +import android.content.SharedPreferences; + +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaPlugin; +import org.json.JSONArray; +import org.json.JSONException; + +public class IonicWebView extends CordovaPlugin { + + public static final String WEBVIEW_PREFS_NAME = "WebViewSettings"; + public static final String CDV_SERVER_PATH = "serverBasePath"; + + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + + if (action.equals("setServerBasePath")) { + final String path = args.getString(0); + cordova.getActivity().runOnUiThread(new Runnable() { + public void run() { + ((IonicWebViewEngine)webView.getEngine()).setServerBasePath(path); + } + }); + return true; + } else if (action.equals("getServerBasePath")) { + callbackContext.success(((IonicWebViewEngine)webView.getEngine()).getServerBasePath()); + return true; + } else if (action.equals("persistServerBasePath")) { + String path = ((IonicWebViewEngine)webView.getEngine()).getServerBasePath(); + SharedPreferences prefs = cordova.getActivity().getApplicationContext().getSharedPreferences(WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(CDV_SERVER_PATH, path); + editor.apply(); + return true; + } + return false; + } + +} + diff --git a/src/com/ionicframework/cordova/webview/IonicWebViewEngine.java b/src/com/ionicframework/cordova/webview/IonicWebViewEngine.java new file mode 100644 index 0000000000000000000000000000000000000000..81d04978b3041ddf4bc2351b19c06c0f8cec4ba3 --- /dev/null +++ b/src/com/ionicframework/cordova/webview/IonicWebViewEngine.java @@ -0,0 +1,166 @@ +package com.ionicframework.cordova.webview; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.annotation.TargetApi; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Build; +import android.support.annotation.RequiresApi; +import android.util.Log; +import android.webkit.WebResourceRequest; +import android.webkit.WebResourceResponse; +import android.webkit.WebSettings; +import android.webkit.WebView; +import org.apache.cordova.ConfigXmlParser; +import org.apache.cordova.CordovaInterface; +import org.apache.cordova.CordovaPreferences; +import org.apache.cordova.CordovaResourceApi; +import org.apache.cordova.CordovaWebView; +import org.apache.cordova.CordovaWebViewEngine; +import org.apache.cordova.NativeToJsMessageQueue; +import org.apache.cordova.PluginManager; +import org.apache.cordova.engine.SystemWebViewClient; +import org.apache.cordova.engine.SystemWebViewEngine; +import org.apache.cordova.engine.SystemWebView; + +public class IonicWebViewEngine extends SystemWebViewEngine { + public static final String TAG = "IonicWebViewEngine"; + + private WebViewLocalServer localServer; + private String CDV_LOCAL_SERVER; + private String scheme; + private static final String LAST_BINARY_VERSION_CODE = "lastBinaryVersionCode"; + private static final String LAST_BINARY_VERSION_NAME = "lastBinaryVersionName"; + + /** + * Used when created via reflection. + */ + public IonicWebViewEngine(Context context, CordovaPreferences preferences) { + super(new SystemWebView(context), preferences); + Log.d(TAG, "Ionic Web View Engine Starting Right Up 1..."); + } + + public IonicWebViewEngine(SystemWebView webView) { + super(webView, null); + Log.d(TAG, "Ionic Web View Engine Starting Right Up 2..."); + } + + public IonicWebViewEngine(SystemWebView webView, CordovaPreferences preferences) { + super(webView, preferences); + Log.d(TAG, "Ionic Web View Engine Starting Right Up 3..."); + } + + @Override + public void init(CordovaWebView parentWebView, CordovaInterface cordova, final CordovaWebViewEngine.Client client, + CordovaResourceApi resourceApi, PluginManager pluginManager, + NativeToJsMessageQueue nativeToJsMessageQueue) { + ConfigXmlParser parser = new ConfigXmlParser(); + parser.parse(cordova.getActivity()); + + String hostname = preferences.getString("Hostname", "localhost"); + scheme = preferences.getString("Scheme", "http"); + CDV_LOCAL_SERVER = scheme + "://" + hostname; + + localServer = new WebViewLocalServer(cordova.getActivity(), hostname, true, parser, scheme); + localServer.hostAssets("www"); + + webView.setWebViewClient(new ServerClient(this, parser)); + + super.init(parentWebView, cordova, client, resourceApi, pluginManager, nativeToJsMessageQueue); + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + final WebSettings settings = webView.getSettings(); + int mode = preferences.getInteger("MixedContentMode", 0); + settings.setMixedContentMode(mode); + } + SharedPreferences prefs = cordova.getActivity().getApplicationContext().getSharedPreferences(IonicWebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE); + String path = prefs.getString(IonicWebView.CDV_SERVER_PATH, null); + if (!isDeployDisabled() && !isNewBinary() && path != null && !path.isEmpty()) { + setServerBasePath(path); + } + } + + private boolean isNewBinary() { + String versionCode = ""; + String versionName = ""; + SharedPreferences prefs = cordova.getActivity().getApplicationContext().getSharedPreferences(IonicWebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE); + String lastVersionCode = prefs.getString(LAST_BINARY_VERSION_CODE, null); + String lastVersionName = prefs.getString(LAST_BINARY_VERSION_NAME, null); + + try { + PackageInfo pInfo = this.cordova.getActivity().getPackageManager().getPackageInfo(this.cordova.getActivity().getPackageName(), 0); + versionCode = Integer.toString(pInfo.versionCode); + versionName = pInfo.versionName; + } catch(Exception ex) { + Log.e(TAG, "Unable to get package info", ex); + } + + if (!versionCode.equals(lastVersionCode) || !versionName.equals(lastVersionName)) { + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(LAST_BINARY_VERSION_CODE, versionCode); + editor.putString(LAST_BINARY_VERSION_NAME, versionName); + editor.putString(IonicWebView.CDV_SERVER_PATH, ""); + editor.apply(); + return true; + } + return false; + } + + private boolean isDeployDisabled() { + return preferences.getBoolean("DisableDeploy", false); + } + private class ServerClient extends SystemWebViewClient { + private ConfigXmlParser parser; + + public ServerClient(SystemWebViewEngine parentEngine, ConfigXmlParser parser) { + super(parentEngine); + this.parser = parser; + } + + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { + return localServer.shouldInterceptRequest(request.getUrl(), request); + } + + @TargetApi(Build.VERSION_CODES.KITKAT) + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, String url) { + return localServer.shouldInterceptRequest(Uri.parse(url), null); + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + super.onPageStarted(view, url, favicon); + String launchUrl = parser.getLaunchUrl(); + if (!launchUrl.contains(WebViewLocalServer.httpsScheme) && !launchUrl.contains(WebViewLocalServer.httpScheme) && url.equals(launchUrl)) { + view.stopLoading(); + // When using a custom scheme the app won't load if server start url doesn't end in / + String startUrl = CDV_LOCAL_SERVER; + if (!scheme.equalsIgnoreCase(WebViewLocalServer.httpsScheme) && !scheme.equalsIgnoreCase(WebViewLocalServer.httpScheme)) { + startUrl += "/"; + } + view.loadUrl(startUrl); + } + } + + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + view.loadUrl("javascript:(function() { " + + "window.WEBVIEW_SERVER_URL = '" + CDV_LOCAL_SERVER + "';" + + "})()"); + } + } + + public void setServerBasePath(String path) { + localServer.hostFiles(path); + webView.loadUrl(CDV_LOCAL_SERVER); + } + + public String getServerBasePath() { + return this.localServer.getBasePath(); + } +} diff --git a/src/com/ionicframework/cordova/webview/UriMatcher.java b/src/com/ionicframework/cordova/webview/UriMatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..d8addb9b95a7f5fbb840d89250087c47487b150b --- /dev/null +++ b/src/com/ionicframework/cordova/webview/UriMatcher.java @@ -0,0 +1,183 @@ +package com.ionicframework.cordova.webview; + +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +//package com.google.webviewlocalserver.third_party.android; + +import android.net.Uri; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +public class UriMatcher { + /** + * Creates the root node of the URI tree. + * + * @param code the code to match for the root URI + */ + public UriMatcher(Object code) { + mCode = code; + mWhich = -1; + mChildren = new ArrayList<UriMatcher>(); + mText = null; + } + + private UriMatcher() { + mCode = null; + mWhich = -1; + mChildren = new ArrayList<UriMatcher>(); + mText = null; + } + + /** + * Add a URI to match, and the code to return when this URI is + * matched. URI nodes may be exact match string, the token "*" + * that matches any text, or the token "#" that matches only + * numbers. + * <p> + * Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, + * this method will accept a leading slash in the path. + * + * @param authority the authority to match + * @param path the path to match. * may be used as a wild card for + * any text, and # may be used as a wild card for numbers. + * @param code the code that is returned when a URI is matched + * against the given components. Must be positive. + */ + public void addURI(String scheme, String authority, String path, Object code) { + if (code == null) { + throw new IllegalArgumentException("Code can't be null"); + } + + String[] tokens = null; + if (path != null) { + String newPath = path; + // Strip leading slash if present. + if (path.length() > 0 && path.charAt(0) == '/') { + newPath = path.substring(1); + } + tokens = PATH_SPLIT_PATTERN.split(newPath); + } + + int numTokens = tokens != null ? tokens.length : 0; + UriMatcher node = this; + for (int i = -2; i < numTokens; i++) { + String token; + if (i == -2) + token = scheme; + else if (i == -1) + token = authority; + else + token = tokens[i]; + ArrayList<UriMatcher> children = node.mChildren; + int numChildren = children.size(); + UriMatcher child; + int j; + for (j = 0; j < numChildren; j++) { + child = children.get(j); + if (token.equals(child.mText)) { + node = child; + break; + } + } + if (j == numChildren) { + // Child not found, create it + child = new UriMatcher(); + if (token.equals("**")) { + child.mWhich = REST; + } else if (token.equals("*")) { + child.mWhich = TEXT; + } else { + child.mWhich = EXACT; + } + child.mText = token; + node.mChildren.add(child); + node = child; + } + } + node.mCode = code; + } + + static final Pattern PATH_SPLIT_PATTERN = Pattern.compile("/"); + + /** + * Try to match against the path in a url. + * + * @param uri The url whose path we will match against. + * @return The code for the matched node (added using addURI), + * or null if there is no matched node. + */ + public Object match(Uri uri) { + final List<String> pathSegments = uri.getPathSegments(); + final int li = pathSegments.size(); + + UriMatcher node = this; + + if (li == 0 && uri.getAuthority() == null) { + return this.mCode; + } + + for (int i = -2; i < li; i++) { + String u; + if (i == -2) + u = uri.getScheme(); + else if (i == -1) + u = uri.getAuthority(); + else + u = pathSegments.get(i); + ArrayList<UriMatcher> list = node.mChildren; + if (list == null) { + break; + } + node = null; + int lj = list.size(); + for (int j = 0; j < lj; j++) { + UriMatcher n = list.get(j); + which_switch: + switch (n.mWhich) { + case EXACT: + if (n.mText.equals(u)) { + node = n; + } + break; + case TEXT: + node = n; + break; + case REST: + return n.mCode; + } + if (node != null) { + break; + } + } + if (node == null) { + return null; + } + } + + return node.mCode; + } + + private static final int EXACT = 0; + private static final int TEXT = 1; + private static final int REST = 2; + + private Object mCode; + private int mWhich; + private String mText; + private ArrayList<UriMatcher> mChildren; +} diff --git a/src/com/ionicframework/cordova/webview/WebViewLocalServer.java b/src/com/ionicframework/cordova/webview/WebViewLocalServer.java new file mode 100644 index 0000000000000000000000000000000000000000..cf134932bff438f691e52b79873ff80dcb0e028d --- /dev/null +++ b/src/com/ionicframework/cordova/webview/WebViewLocalServer.java @@ -0,0 +1,645 @@ +/* +Copyright 2015 Google Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + */ +package com.ionicframework.cordova.webview; + +import android.content.Context; +import android.net.Uri; +import android.os.Build; +import android.util.Log; +import android.webkit.WebResourceRequest; +import android.webkit.WebResourceResponse; + +import org.apache.cordova.ConfigXmlParser; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Helper class meant to be used with the android.webkit.WebView class to enable hosting assets, + * resources and other data on 'virtual' http(s):// URL. + * Hosting assets and resources on http(s):// URLs is desirable as it is compatible with the + * Same-Origin policy. + * <p> + * This class is intended to be used from within the + * {@link android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView, String)} and + * {@link android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView, + * android.webkit.WebResourceRequest)} + * methods. + */ +public class WebViewLocalServer { + private static String TAG = "WebViewAssetServer"; + private String basePath; + public final static String httpScheme = "http"; + public final static String httpsScheme = "https"; + public final static String fileStart = "/_app_file_"; + public final static String contentStart = "/_app_content_"; + + private final UriMatcher uriMatcher; + private final AndroidProtocolHandler protocolHandler; + private final String authority; + private final String customScheme; + // Whether we're serving local files or proxying (for example, when doing livereload on a + // non-local endpoint (will be false in that case) + private boolean isAsset; + // Whether to route all requests to paths without extensions back to `index.html` + private final boolean html5mode; + private ConfigXmlParser parser; + + public String getAuthority() { return authority; } + + /** + * A handler that produces responses for paths on the virtual asset server. + * <p> + * Methods of this handler will be invoked on a background thread and care must be taken to + * correctly synchronize access to any shared state. + * <p> + * On Android KitKat and above these methods may be called on more than one thread. This thread + * may be different than the thread on which the shouldInterceptRequest method was invoke. + * This means that on Android KitKat and above it is possible to block in this method without + * blocking other resources from loading. The number of threads used to parallelize loading + * is an internal implementation detail of the WebView and may change between updates which + * means that the amount of time spend blocking in this method should be kept to an absolute + * minimum. + */ + public abstract static class PathHandler { + protected String mimeType; + private String encoding; + private String charset; + private int statusCode; + private String reasonPhrase; + private Map<String, String> responseHeaders; + + public PathHandler() { + this(null, null, 200, "OK", null); + } + + public PathHandler(String encoding, String charset, int statusCode, + String reasonPhrase, Map<String, String> responseHeaders) { + this.encoding = encoding; + this.charset = charset; + this.statusCode = statusCode; + this.reasonPhrase = reasonPhrase; + Map<String, String> tempResponseHeaders; + if (responseHeaders == null) { + tempResponseHeaders = new HashMap<String, String>(); + } else { + tempResponseHeaders = responseHeaders; + } + tempResponseHeaders.put("Cache-Control", "no-cache"); + this.responseHeaders = tempResponseHeaders; + } + + abstract public InputStream handle(Uri url); + + public String getEncoding() { + return encoding; + } + + public String getCharset() { + return charset; + } + + public int getStatusCode() { + return statusCode; + } + + public String getReasonPhrase() { + return reasonPhrase; + } + + public Map<String, String> getResponseHeaders() { + return responseHeaders; + } + } + + /** + * Information about the URLs used to host the assets in the WebView. + */ + public static class AssetHostingDetails { + private Uri httpPrefix; + private Uri httpsPrefix; + + /*package*/ AssetHostingDetails(Uri httpPrefix, Uri httpsPrefix) { + this.httpPrefix = httpPrefix; + this.httpsPrefix = httpsPrefix; + } + + /** + * Gets the http: scheme prefix at which assets are hosted. + * + * @return the http: scheme prefix at which assets are hosted. Can return null. + */ + public Uri getHttpPrefix() { + return httpPrefix; + } + + /** + * Gets the https: scheme prefix at which assets are hosted. + * + * @return the https: scheme prefix at which assets are hosted. Can return null. + */ + public Uri getHttpsPrefix() { + return httpsPrefix; + } + } + + WebViewLocalServer(Context context, String authority, boolean html5mode, ConfigXmlParser parser, String customScheme) { + uriMatcher = new UriMatcher(null); + this.html5mode = html5mode; + this.parser = parser; + this.protocolHandler = new AndroidProtocolHandler(context.getApplicationContext()); + this.authority = authority; + this.customScheme = customScheme; + } + + private static Uri parseAndVerifyUrl(String url) { + if (url == null) { + return null; + } + Uri uri = Uri.parse(url); + if (uri == null) { + Log.e(TAG, "Malformed URL: " + url); + return null; + } + String path = uri.getPath(); + if (path == null || path.length() == 0) { + Log.e(TAG, "URL does not have a path: " + url); + return null; + } + return uri; + } + + private static WebResourceResponse createWebResourceResponse(String mimeType, String encoding, int statusCode, String reasonPhrase, Map<String, String> responseHeaders, InputStream data) { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + int finalStatusCode = statusCode; + try { + if (data.available() == 0) { + finalStatusCode = 404; + } + } catch (IOException e) { + finalStatusCode = 500; + } + return new WebResourceResponse(mimeType, encoding, finalStatusCode, reasonPhrase, responseHeaders, data); + } else { + return new WebResourceResponse(mimeType, encoding, data); + } + } + + /** + * Attempt to retrieve the WebResourceResponse associated with the given <code>request</code>. + * This method should be invoked from within + * {@link android.webkit.WebViewClient#shouldInterceptRequest(android.webkit.WebView, + * android.webkit.WebResourceRequest)}. + * + * @param uri the request Uri to process. + * @return a response if the request URL had a matching handler, null if no handler was found. + */ + public WebResourceResponse shouldInterceptRequest(Uri uri, WebResourceRequest request) { + PathHandler handler; + synchronized (uriMatcher) { + handler = (PathHandler) uriMatcher.match(uri); + } + if (handler == null) { + return null; + } + + if (isLocalFile(uri) || uri.getAuthority().equals(this.authority)) { + Log.d("SERVER", "Handling local request: " + uri.toString()); + return handleLocalRequest(uri, handler, request); + } else { + return handleProxyRequest(uri, handler); + } + } + + private boolean isLocalFile(Uri uri) { + String path = uri.getPath(); + if (path.startsWith(contentStart) || path.startsWith(fileStart)) { + return true; + } + return false; + } + + + private WebResourceResponse handleLocalRequest(Uri uri, PathHandler handler, WebResourceRequest request) { + String path = uri.getPath(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && request != null && request.getRequestHeaders().get("Range") != null) { + InputStream responseStream = new LollipopLazyInputStream(handler, uri); + String mimeType = getMimeType(path, responseStream); + Map<String, String> tempResponseHeaders = handler.getResponseHeaders(); + int statusCode = 206; + try { + int totalRange = responseStream.available(); + String rangeString = request.getRequestHeaders().get("Range"); + String[] parts = rangeString.split("="); + String[] streamParts = parts[1].split("-"); + String fromRange = streamParts[0]; + int range = totalRange-1; + if (streamParts.length > 1) { + range = Integer.parseInt(streamParts[1]); + } + tempResponseHeaders.put("Accept-Ranges", "bytes"); + tempResponseHeaders.put("Content-Range", "bytes " + fromRange + "-" + range + "/" + totalRange); + } catch (IOException e) { + statusCode = 404; + } + return createWebResourceResponse(mimeType, handler.getEncoding(), + statusCode, handler.getReasonPhrase(), tempResponseHeaders, responseStream); + } + if (isLocalFile(uri)) { + InputStream responseStream = new LollipopLazyInputStream(handler, uri); + String mimeType = getMimeType(path, responseStream); + return createWebResourceResponse(mimeType, handler.getEncoding(), + handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(), responseStream); + } + + if (path.equals("") || path.equals("/") || (!uri.getLastPathSegment().contains(".") && html5mode)) { + InputStream stream; + String launchURL = parser.getLaunchUrl(); + String launchFile = launchURL.substring(launchURL.lastIndexOf("/") + 1, launchURL.length()); + try { + String startPath = this.basePath + "/" + launchFile; + if (isAsset) { + stream = protocolHandler.openAsset(startPath); + } else { + stream = protocolHandler.openFile(startPath); + } + + } catch (IOException e) { + Log.e(TAG, "Unable to open " + launchFile, e); + return null; + } + + return createWebResourceResponse("text/html", handler.getEncoding(), + handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(), stream); + } + + int periodIndex = path.lastIndexOf("."); + if (periodIndex >= 0) { + InputStream responseStream = new LollipopLazyInputStream(handler, uri); + String mimeType = getMimeType(path, responseStream); + return createWebResourceResponse(mimeType, handler.getEncoding(), + handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(), responseStream); + } + + return null; + } + + /** + * Instead of reading files from the filesystem/assets, proxy through to the URL + * and let an external server handle it. + * @param uri + * @param handler + * @return + */ + private WebResourceResponse handleProxyRequest(Uri uri, PathHandler handler) { + try { + String path = uri.getPath(); + URL url = new URL(uri.toString()); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + conn.setReadTimeout(30 * 1000); + conn.setConnectTimeout(30 * 1000); + + InputStream stream = conn.getInputStream(); + + if (path.equals("/") || (!uri.getLastPathSegment().contains(".") && html5mode)) { + return createWebResourceResponse("text/html", handler.getEncoding(), + handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(), stream); + } + + int periodIndex = path.lastIndexOf("."); + if (periodIndex >= 0) { + String ext = path.substring(path.lastIndexOf("."), path.length()); + + // TODO: Conjure up a bit more subtlety than this + if (ext.equals(".html")) { + } + + String mimeType = getMimeType(path, stream); + + return createWebResourceResponse(mimeType, handler.getEncoding(), + handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(), stream); + } + + return createWebResourceResponse("", handler.getEncoding(), + handler.getStatusCode(), handler.getReasonPhrase(), handler.getResponseHeaders(), stream); + + } catch (SocketTimeoutException ex) { + // bridge.handleAppUrlLoadError(ex); + } catch (Exception ex) { + // bridge.handleAppUrlLoadError(ex); + } + return null; + } + + private String getMimeType(String path, InputStream stream) { + String mimeType = null; + try { + mimeType = URLConnection.guessContentTypeFromName(path); // Does not recognize *.js + if (mimeType != null && path.endsWith(".js") && mimeType.equals("image/x-icon")) { + Log.d(IonicWebViewEngine.TAG, "We shouldn't be here"); + } + if (mimeType == null) { + if (path.endsWith(".js") || path.endsWith(".mjs")) { + // Make sure JS files get the proper mimetype to support ES modules + mimeType = "application/javascript"; + } else if (path.endsWith(".wasm")) { + mimeType = "application/wasm"; + } else { + mimeType = URLConnection.guessContentTypeFromStream(stream); + } + } + } catch (Exception ex) { + Log.e(TAG, "Unable to get mime type" + path, ex); + } + return mimeType; + } + + /** + * Registers a handler for the given <code>uri</code>. The <code>handler</code> will be invoked + * every time the <code>shouldInterceptRequest</code> method of the instance is called with + * a matching <code>uri</code>. + * + * @param uri the uri to use the handler for. The scheme and authority (domain) will be matched + * exactly. The path may contain a '*' element which will match a single element of + * a path (so a handler registered for /a/* will be invoked for /a/b and /a/c.html + * but not for /a/b/b) or the '**' element which will match any number of path + * elements. + * @param handler the handler to use for the uri. + */ + void register(Uri uri, PathHandler handler) { + synchronized (uriMatcher) { + uriMatcher.addURI(uri.getScheme(), uri.getAuthority(), uri.getPath(), handler); + } + } + + /** + * Hosts the application's assets on an http(s):// URL. Assets from the local path + * <code>assetPath/...</code> will be available under + * <code>http(s)://{uuid}.androidplatform.net/assets/...</code>. + * + * @param assetPath the local path in the application's asset folder which will be made + * available by the server (for example "/www"). + */ + public void hostAssets(String assetPath) { + hostAssets(authority, assetPath); + } + + + /** + * Hosts the application's assets on an http(s):// URL. Assets from the local path + * <code>assetPath/...</code> will be available under + * <code>http(s)://{domain}/{virtualAssetPath}/...</code>. + * + * @param domain custom domain on which the assets should be hosted (for example "example.com"). + * @param assetPath the local path in the application's asset folder which will be made + * available by the server (for example "/www"). + * @return prefixes under which the assets are hosted. + */ + public void hostAssets(final String domain, + final String assetPath) { + this.isAsset = true; + this.basePath = assetPath; + + createHostingDetails(); + } + + private void createHostingDetails() { + final String assetPath = this.basePath; + + if (assetPath.indexOf('*') != -1) { + throw new IllegalArgumentException("assetPath cannot contain the '*' character."); + } + + PathHandler handler = new PathHandler() { + @Override + public InputStream handle(Uri url) { + InputStream stream = null; + String path = url.getPath(); + try { + if (path.startsWith(contentStart)) { + stream = protocolHandler.openContentUrl(url); + } else if (path.startsWith(fileStart) || !isAsset) { + if (!path.startsWith(fileStart)) { + path = basePath + url.getPath(); + } + stream = protocolHandler.openFile(path); + } else { + stream = protocolHandler.openAsset(assetPath + path); + } + } catch (IOException e) { + Log.e(TAG, "Unable to open asset URL: " + url); + return null; + } + + return stream; + } + }; + + registerUriForScheme(httpScheme, handler, authority); + registerUriForScheme(httpsScheme, handler, authority); + if (!customScheme.equals(httpScheme) && !customScheme.equals(httpsScheme)) { + registerUriForScheme(customScheme, handler, authority); + } + + } + + private void registerUriForScheme(String scheme, PathHandler handler, String authority) { + Uri.Builder uriBuilder = new Uri.Builder(); + uriBuilder.scheme(scheme); + uriBuilder.authority(authority); + uriBuilder.path(""); + Uri uriPrefix = uriBuilder.build(); + + register(Uri.withAppendedPath(uriPrefix, "/"), handler); + register(Uri.withAppendedPath(uriPrefix, "**"), handler); + } + + /** + * Hosts the application's resources on an http(s):// URL. Resources + * <code>http(s)://{uuid}.androidplatform.net/res/{resource_type}/{resource_name}</code>. + * + * @return prefixes under which the resources are hosted. + */ + public AssetHostingDetails hostResources() { + return hostResources(authority, "/res", true, true); + } + + /** + * Hosts the application's resources on an http(s):// URL. Resources + * <code>http(s)://{uuid}.androidplatform.net/{virtualResourcesPath}/{resource_type}/{resource_name}</code>. + * + * @param virtualResourcesPath the path on the local server under which the resources + * should be hosted. + * @param enableHttp whether to enable hosting using the http scheme. + * @param enableHttps whether to enable hosting using the https scheme. + * @return prefixes under which the resources are hosted. + */ + public AssetHostingDetails hostResources(final String virtualResourcesPath, boolean enableHttp, + boolean enableHttps) { + return hostResources(authority, virtualResourcesPath, enableHttp, enableHttps); + } + + /** + * Hosts the application's resources on an http(s):// URL. Resources + * <code>http(s)://{domain}/{virtualResourcesPath}/{resource_type}/{resource_name}</code>. + * + * @param domain custom domain on which the assets should be hosted (for example "example.com"). + * If untrusted content is to be loaded into the WebView it is advised to make + * this random. + * @param virtualResourcesPath the path on the local server under which the resources + * should be hosted. + * @param enableHttp whether to enable hosting using the http scheme. + * @param enableHttps whether to enable hosting using the https scheme. + * @return prefixes under which the resources are hosted. + */ + public AssetHostingDetails hostResources(final String domain, + final String virtualResourcesPath, boolean enableHttp, + boolean enableHttps) { + if (virtualResourcesPath.indexOf('*') != -1) { + throw new IllegalArgumentException( + "virtualResourcesPath cannot contain the '*' character."); + } + + Uri.Builder uriBuilder = new Uri.Builder(); + uriBuilder.scheme(httpScheme); + uriBuilder.authority(domain); + uriBuilder.path(virtualResourcesPath); + + Uri httpPrefix = null; + Uri httpsPrefix = null; + + PathHandler handler = new PathHandler() { + @Override + public InputStream handle(Uri url) { + InputStream stream = protocolHandler.openResource(url); + String mimeType = null; + try { + mimeType = URLConnection.guessContentTypeFromStream(stream); + } catch (Exception ex) { + Log.e(TAG, "Unable to get mime type" + url); + } + + return stream; + } + }; + + if (enableHttp) { + httpPrefix = uriBuilder.build(); + register(Uri.withAppendedPath(httpPrefix, "**"), handler); + } + if (enableHttps) { + uriBuilder.scheme(httpsScheme); + httpsPrefix = uriBuilder.build(); + register(Uri.withAppendedPath(httpsPrefix, "**"), handler); + } + return new AssetHostingDetails(httpPrefix, httpsPrefix); + } + + + /** + * Hosts the application's files on an http(s):// URL. Files from the basePath + * <code>basePath/...</code> will be available under + * <code>http(s)://{uuid}.androidplatform.net/...</code>. + * + * @param basePath the local path in the application's data folder which will be made + * available by the server (for example "/www"). + */ + public void hostFiles(final String basePath) { + this.isAsset = false; + this.basePath = basePath; + createHostingDetails(); + } + + /** + * The KitKat WebView reads the InputStream on a separate threadpool. We can use that to + * parallelize loading. + */ + private static abstract class LazyInputStream extends InputStream { + protected final PathHandler handler; + private InputStream is = null; + + public LazyInputStream(PathHandler handler) { + this.handler = handler; + } + + private InputStream getInputStream() { + if (is == null) { + is = handle(); + } + return is; + } + + protected abstract InputStream handle(); + + @Override + public int available() throws IOException { + InputStream is = getInputStream(); + return (is != null